From dd657ad3f1428b026486db3ec36691df17ddf515 Mon Sep 17 00:00:00 2001 From: "Steve M. Robbins" Date: Sat, 22 Oct 2011 04:54:51 +0200 Subject: Import nyquist_3.05.orig.tar.gz [dgit import orig nyquist_3.05.orig.tar.gz] --- Readme.txt | 231 + advantages.txt | 27 + cmt/cext.c | 107 + cmt/cext.h | 194 + cmt/cleanup.c | 62 + cmt/cleanup.h | 9 + cmt/cmdline.c | 479 + cmt/cmdline.h | 8 + cmt/cmtcmd.c | 53 + cmt/cmtcmd.h | 35 + cmt/cmtio.c | 161 + cmt/cmtio.h | 9 + cmt/hash.h | 23 + cmt/hashrout.h | 220 + cmt/mem.c | 91 + cmt/mem.h | 12 + cmt/mfmidi.h | 19 + cmt/midibuff.h | 23 + cmt/midicode.h | 62 + cmt/midierr.h | 17 + cmt/midifile.c | 618 + cmt/midifile.h | 27 + cmt/midifns.c | 1886 ++ cmt/midifns.h | 137 + cmt/midimgr.c | 784 + cmt/midimgr.h | 14 + cmt/moxc.c | 669 + cmt/moxc.h | 44 + cmt/musiprog.h | 31 + cmt/pitch.h | 9 + cmt/record.c | 638 + cmt/record.h | 6 + cmt/seq.c | 1199 + cmt/seq.h | 295 + cmt/seqdecls.h | 11 + cmt/seqmread.c | 448 + cmt/seqmread.h | 4 + cmt/seqmwrite.c | 658 + cmt/seqmwrite.h | 4 + cmt/seqread.c | 1890 ++ cmt/seqread.h | 7 + cmt/seqwrite.c | 282 + cmt/seqwrite.h | 6 + cmt/swlogic.h | 197 + cmt/tempomap.c | 124 + cmt/tempomap.h | 25 + cmt/timebase.c | 322 + cmt/timebase.h | 85 + cmt/userio.c | 1285 ++ cmt/userio.h | 96 + comp-ide.bat | 12 + convert.dsp | 153 + convert.dsw | 29 + demos/allewis/cell_aut.lsp | 83 + demos/allewis/cellularautomata.htm | 79 + demos/allewis/cmusic_pres.ppt | Bin 0 -> 51200 bytes demos/allewis/rule30.jpg | Bin 0 -> 39403 bytes demos/arp.sal | 99 + demos/arpeggiator.htm | 31 + demos/bandfx.htm | 59 + demos/beginclip.jpg | Bin 0 -> 10372 bytes demos/demo-snd.aiff | Bin 0 -> 8054 bytes demos/demo.mid | Bin 0 -> 1601 bytes demos/distortion.htm | 118 + demos/examples.lsp | 424 + demos/examples.sal | 518 + demos/examples_home.htm | 116 + demos/fft_demo.lsp | 176 + demos/fft_tutorial.htm | 553 + demos/largeclip.jpg | Bin 0 -> 27006 bytes demos/lpc-exmpl.dat | 162 + demos/lpc_tutorial.htm | 186 + demos/lpcdemo.lsp | 263 + demos/mateos/bell.lsp | 33 + demos/mateos/gong.lsp | 64 + demos/mateos/organ.lsp | 58 + demos/mateos/tuba.lsp | 94 + demos/midi_tutorial.htm | 2 + demos/osc-test.lsp | 90 + demos/piano.htm | 2 + demos/pitch_change.htm | 83 + demos/pmorales/a4.lsp | 25 + demos/pmorales/a5.lsp | 20 + demos/pmorales/a6.lsp | 33 + demos/pmorales/b1.lsp | 60 + demos/pmorales/b10.lsp | 63 + demos/pmorales/b2.lsp | 45 + demos/pmorales/b3.lsp | 40 + demos/pmorales/b5.lsp | 19 + demos/pmorales/b7.lsp | 40 + demos/pmorales/b8.lsp | 51 + demos/pmorales/b9.lsp | 42 + demos/pmorales/buzz.lsp | 88 + demos/pmorales/c1.lsp | 32 + demos/pmorales/d1.lsp | 43 + demos/pmorales/e2.lsp | 157 + demos/pmorales/ks.lsp | 33 + demos/pmorales/partial.lsp | 30 + demos/pmorales/phm.lsp | 79 + demos/pmorales/pjmg.lsp | 40 + demos/pmorales/readme.txt | 27 + demos/probability_distributions.htm | 137 + demos/rhythm_tutorial.htm | 2 + demos/scratch_tutorial.htm | 93 + demos/sdl/ej2.lsp | 66 + demos/sdl/inv-08.lsp | 180 + demos/sequence_example.htm | 52 + demos/shepard.lsp | 195 + demos/shepard.ny | 139 + demos/softclip.gif | Bin 0 -> 16618 bytes demos/softclip.jpg | Bin 0 -> 11172 bytes demos/stktest.lsp | 407 + demos/voice_synthesis.htm | 290 + demos/warble_tutorial.htm | 76 + demos/wind_tutorial.htm | 43 + doc/arcsine-fig.gif | Bin 0 -> 1044 bytes doc/bernoulli-fig.gif | Bin 0 -> 3343 bytes doc/beta-fig.gif | Bin 0 -> 980 bytes doc/bilateral-fig.gif | Bin 0 -> 1100 bytes doc/binomial-fig.gif | Bin 0 -> 3984 bytes doc/cauchy-fig.gif | Bin 0 -> 1143 bytes doc/exponential-fig.gif | Bin 0 -> 979 bytes doc/fig1.gif | Bin 0 -> 1790 bytes doc/fig2.gif | Bin 0 -> 1753 bytes doc/fig3.gif | Bin 0 -> 1954 bytes doc/fig4.gif | Bin 0 -> 1826 bytes doc/fig5.gif | Bin 0 -> 1534 bytes doc/fig6.gif | Bin 0 -> 2122 bytes doc/foot.html | 49 + doc/gamma-fig.gif | Bin 0 -> 1133 bytes doc/gaussian-fig.gif | Bin 0 -> 1096 bytes doc/geometric-fig.gif | Bin 0 -> 3454 bytes doc/guide.html | 1949 ++ doc/home.html | 7 + doc/hyperbolic-fig.gif | Bin 0 -> 1163 bytes doc/indx.html | 1611 ++ doc/linear-fig.gif | Bin 0 -> 1008 bytes doc/logistic-fig.gif | Bin 0 -> 1154 bytes doc/moog-fig.gif | Bin 0 -> 18556 bytes doc/musicbib.html | 13 + doc/nyqman.txt | 13387 +++++++++++ doc/nyquistman.pdf | Bin 0 -> 644495 bytes doc/part1.html | 72 + doc/part10.html | 77 + doc/part11.html | 899 + doc/part12.html | 157 + doc/part13.html | 218 + doc/part14.html | 1495 ++ doc/part15.html | 840 + doc/part16.html | 422 + doc/part17.html | 71 + doc/part18.html | 238 + doc/part19.html | 2704 +++ doc/part2.html | 491 + doc/part3.html | 266 + doc/part4.html | 429 + doc/part5.html | 313 + doc/part6.html | 573 + doc/part7.html | 673 + doc/part8.html | 2823 +++ doc/part9.html | 40 + doc/poisson-fig.gif | Bin 0 -> 4022 bytes doc/sdl-man.pdf | Bin 0 -> 152845 bytes doc/title.html | 377 + docsrc/bib/music.bib | 3465 +++ docsrc/convert/convert.lsp | 171 + docsrc/convert/convert2.lsp | 381 + docsrc/convert/init.lsp | 9 + docsrc/nyquist/adagio-nyquist.mss | 825 + docsrc/nyquist/adagio.mss | 840 + docsrc/nyquist/arcsine-fig.ps | 64 + docsrc/nyquist/bernoulli-fig.ps | 1149 + docsrc/nyquist/beta-fig.ps | 64 + docsrc/nyquist/bilateral-fig.ps | 65 + docsrc/nyquist/binomial-fig.ps | 1197 + docsrc/nyquist/cauchy-fig.ps | 68 + docsrc/nyquist/envfig.ps | 198 + docsrc/nyquist/exponential-fig.ps | 60 + docsrc/nyquist/gamma-fig.ps | 71 + docsrc/nyquist/gaussian-fig.ps | 69 + docsrc/nyquist/geometric-fig.ps | 1173 + docsrc/nyquist/hyperbolic-fig.ps | 70 + docsrc/nyquist/linear-fig.ps | 63 + docsrc/nyquist/linear-fig.ps.ORIGINAL | 62 + docsrc/nyquist/logistic-fig.ps | 69 + docsrc/nyquist/moog-fig.ps | 2808 +++ docsrc/nyquist/nymanimpl.mss | 467 + docsrc/nyquist/nyquistman-sal-only.mss | 8113 +++++++ docsrc/nyquist/nyquistman.mss | 8763 ++++++++ docsrc/nyquist/poisson-fig.ps | 1236 + docsrc/nyquist/rampfig.ps | 694 + docsrc/nyquist/shifttimefig.ps | 643 + docsrc/nyquist/test.ps | 1020 + docsrc/nyquist/warpfig.ps | 650 + docsrc/nyquist/warpnotesfig.ps | 851 + docsrc/nyquist/warponsetfig.ps | 864 + docsrc/s2h/citations.lsp | 21 + docsrc/s2h/do-nyquist-manual.lsp | 6 + docsrc/s2h/s2h.lsp | 1642 ++ docsrc/scribe.htm | 1523 ++ docsrc/sdl/part1.tex | 606 + docsrc/sdl/pjmcfg.sty | 127 + docsrc/sdl/sdl-man.tex | 87 + docsrc/template/filcap.mss | 5 + docsrc/toafs.bat | 5 + docsrc/toafs.sh | 5 + docsrc/xlisp/intgen.mss | 241 + docsrc/xlisp/xlisp-doc/README | 11 + docsrc/xlisp/xlisp-doc/examples/apropos.htm | 268 + docsrc/xlisp/xlisp-doc/examples/arrays.htm | 430 + docsrc/xlisp/xlisp-doc/examples/binary.htm | 160 + docsrc/xlisp/xlisp-doc/examples/circular-lists.htm | 133 + docsrc/xlisp/xlisp-doc/examples/common-lisp.htm | 161 + .../xlisp-doc/examples/common-lisp/ceiling.htm | 137 + .../xlisp-doc/examples/common-lisp/debug-mv.htm | 110 + .../xlisp-doc/examples/common-lisp/equalp.htm | 162 + .../xlisp/xlisp-doc/examples/common-lisp/exp.htm | 92 + .../xlisp/xlisp-doc/examples/common-lisp/expt.htm | 105 + .../xlisp/xlisp-doc/examples/common-lisp/floor.htm | 150 + .../common-lisp/global-multiple-values.htm | 142 + .../xlisp/xlisp-doc/examples/common-lisp/log.htm | 95 + .../xlisp/xlisp-doc/examples/common-lisp/mod.htm | 97 + .../examples/common-lisp/multiple-value-bind.htm | 193 + .../examples/common-lisp/multiple-value-call.htm | 119 + .../examples/common-lisp/multiple-value-list.htm | 112 + .../examples/common-lisp/multiple-value-prog1.htm | 106 + .../examples/common-lisp/multiple-value-setq.htm | 239 + .../examples/common-lisp/multiple-values.htm | 181 + .../xlisp-doc/examples/common-lisp/numbers.htm | 104 + .../xlisp/xlisp-doc/examples/common-lisp/rem.htm | 93 + .../examples/common-lisp/remainder-and-modulus.htm | 93 + .../xlisp/xlisp-doc/examples/common-lisp/round.htm | 141 + .../common-lisp/rounding-and-truncation.htm | 179 + .../xlisp/xlisp-doc/examples/common-lisp/sqrt.htm | 92 + .../xlisp-doc/examples/common-lisp/truncate.htm | 135 + .../xlisp-doc/examples/common-lisp/values-list.htm | 113 + .../xlisp-doc/examples/common-lisp/values.htm | 160 + docsrc/xlisp/xlisp-doc/examples/environment.htm | 1001 + docsrc/xlisp/xlisp-doc/examples/evaluation.htm | 131 + docsrc/xlisp/xlisp-doc/examples/examples.htm | 211 + docsrc/xlisp/xlisp-doc/examples/files.htm | 459 + docsrc/xlisp/xlisp-doc/examples/hash-tables.htm | 496 + docsrc/xlisp/xlisp-doc/examples/hexadecimal.htm | 151 + docsrc/xlisp/xlisp-doc/examples/lists.htm | 580 + docsrc/xlisp/xlisp-doc/examples/macros.htm | 302 + docsrc/xlisp/xlisp-doc/examples/math.htm | 824 + docsrc/xlisp/xlisp-doc/examples/octal.htm | 148 + docsrc/xlisp/xlisp-doc/examples/posix-chars.htm | 459 + docsrc/xlisp/xlisp-doc/examples/predicates.htm | 526 + docsrc/xlisp/xlisp-doc/examples/reader.htm | 311 + docsrc/xlisp/xlisp-doc/examples/sequences.htm | 563 + docsrc/xlisp/xlisp-doc/examples/strings.htm | 802 + docsrc/xlisp/xlisp-doc/examples/xlisp/ash.htm | 130 + docsrc/xlisp/xlisp-doc/examples/xlisp/bsh.htm | 127 + docsrc/xlisp/xlisp-doc/examples/xlisp/ceiling.htm | 103 + docsrc/xlisp/xlisp-doc/examples/xlisp/floor.htm | 103 + docsrc/xlisp/xlisp-doc/internals/c-printf.htm | 518 + .../xlisp/xlisp-doc/internals/xlisp-internals.html | 1206 + docsrc/xlisp/xlisp-doc/manual/contents.htm | 858 + docsrc/xlisp/xlisp-doc/manual/links.htm | 3 + docsrc/xlisp/xlisp-doc/manual/manual.css | 34 + docsrc/xlisp/xlisp-doc/manual/objects.htm | 358 + docsrc/xlisp/xlisp-doc/manual/part15.html | 2131 ++ docsrc/xlisp/xlisp-doc/manual/sal.htm | 160 + docsrc/xlisp/xlisp-doc/manual/xlisp-man-033.htm | 356 + docsrc/xlisp/xlisp-doc/manual/xlisp.htm | 1256 ++ docsrc/xlisp/xlisp-doc/misc/ascii-table.htm | 1403 ++ docsrc/xlisp/xlisp-doc/misc/c-printf.htm | 560 + docsrc/xlisp/xlisp-doc/misc/links.htm | 115 + docsrc/xlisp/xlisp-doc/misc/preface.htm | 116 + .../xlisp/xlisp-doc/objects/advanced-objects.htm | 590 + docsrc/xlisp/xlisp-doc/objects/smalltalk.htm | 441 + docsrc/xlisp/xlisp-doc/reference/abs.htm | 78 + docsrc/xlisp/xlisp-doc/reference/acos.htm | 93 + docsrc/xlisp/xlisp-doc/reference/addition.htm | 87 + docsrc/xlisp/xlisp-doc/reference/address-of.htm | 99 + docsrc/xlisp/xlisp-doc/reference/alloc.htm | 98 + docsrc/xlisp/xlisp-doc/reference/alphanumericp.htm | 84 + docsrc/xlisp/xlisp-doc/reference/and.htm | 118 + docsrc/xlisp/xlisp-doc/reference/append.htm | 90 + docsrc/xlisp/xlisp-doc/reference/apply.htm | 89 + docsrc/xlisp/xlisp-doc/reference/aref.htm | 105 + docsrc/xlisp/xlisp-doc/reference/arrayp.htm | 84 + docsrc/xlisp/xlisp-doc/reference/asin.htm | 93 + docsrc/xlisp/xlisp-doc/reference/assoc.htm | 121 + docsrc/xlisp/xlisp-doc/reference/atan.htm | 77 + docsrc/xlisp/xlisp-doc/reference/atom.htm | 90 + docsrc/xlisp/xlisp-doc/reference/backquote.htm | 170 + docsrc/xlisp/xlisp-doc/reference/baktrace.htm | 117 + docsrc/xlisp/xlisp-doc/reference/bigendianp.htm | 69 + docsrc/xlisp/xlisp-doc/reference/block.htm | 94 + docsrc/xlisp/xlisp-doc/reference/both-case-p.htm | 84 + docsrc/xlisp/xlisp-doc/reference/boundp.htm | 104 + docsrc/xlisp/xlisp-doc/reference/break.htm | 107 + docsrc/xlisp/xlisp-doc/reference/caaaar.htm | 134 + docsrc/xlisp/xlisp-doc/reference/caaar.htm | 106 + docsrc/xlisp/xlisp-doc/reference/caar.htm | 101 + docsrc/xlisp/xlisp-doc/reference/car.htm | 85 + docsrc/xlisp/xlisp-doc/reference/case.htm | 171 + docsrc/xlisp/xlisp-doc/reference/catch.htm | 197 + docsrc/xlisp/xlisp-doc/reference/cddddr.htm | 135 + docsrc/xlisp/xlisp-doc/reference/cdddr.htm | 104 + docsrc/xlisp/xlisp-doc/reference/cddr.htm | 101 + docsrc/xlisp/xlisp-doc/reference/cdr.htm | 85 + docsrc/xlisp/xlisp-doc/reference/cerror.htm | 23 + docsrc/xlisp/xlisp-doc/reference/char-code.htm | 86 + docsrc/xlisp/xlisp-doc/reference/char-downcase.htm | 79 + docsrc/xlisp/xlisp-doc/reference/char-equal-i.htm | 89 + docsrc/xlisp/xlisp-doc/reference/char-equal-s.htm | 91 + .../xlisp/xlisp-doc/reference/char-greaterp-i.htm | 91 + .../xlisp/xlisp-doc/reference/char-greaterp-s.htm | 91 + docsrc/xlisp/xlisp-doc/reference/char-int.htm | 86 + docsrc/xlisp/xlisp-doc/reference/char-lessp-i.htm | 91 + docsrc/xlisp/xlisp-doc/reference/char-lessp-s.htm | 92 + .../xlisp/xlisp-doc/reference/char-not-equal-i.htm | 90 + .../xlisp/xlisp-doc/reference/char-not-equal-s.htm | 98 + .../xlisp-doc/reference/char-not-greaterp-i.htm | 92 + .../xlisp-doc/reference/char-not-greaterp-s.htm | 92 + .../xlisp/xlisp-doc/reference/char-not-lessp-i.htm | 92 + .../xlisp/xlisp-doc/reference/char-not-lessp-s.htm | 92 + docsrc/xlisp/xlisp-doc/reference/char-upcase.htm | 79 + docsrc/xlisp/xlisp-doc/reference/char.htm | 80 + docsrc/xlisp/xlisp-doc/reference/characterp.htm | 86 + docsrc/xlisp/xlisp-doc/reference/class.htm | 113 + docsrc/xlisp/xlisp-doc/reference/clean-up.htm | 90 + docsrc/xlisp/xlisp-doc/reference/close.htm | 85 + docsrc/xlisp/xlisp-doc/reference/code-char.htm | 92 + docsrc/xlisp/xlisp-doc/reference/cond.htm | 95 + docsrc/xlisp/xlisp-doc/reference/cons.htm | 74 + docsrc/xlisp/xlisp-doc/reference/consp.htm | 95 + docsrc/xlisp/xlisp-doc/reference/continue.htm | 90 + docsrc/xlisp/xlisp-doc/reference/cos.htm | 71 + docsrc/xlisp/xlisp-doc/reference/decf.htm | 88 + docsrc/xlisp/xlisp-doc/reference/decrement.htm | 75 + docsrc/xlisp/xlisp-doc/reference/defmacro.htm | 142 + docsrc/xlisp/xlisp-doc/reference/defun.htm | 134 + docsrc/xlisp/xlisp-doc/reference/delete-if-not.htm | 107 + docsrc/xlisp/xlisp-doc/reference/delete-if.htm | 110 + docsrc/xlisp/xlisp-doc/reference/delete.htm | 99 + docsrc/xlisp/xlisp-doc/reference/digit-char-p.htm | 87 + docsrc/xlisp/xlisp-doc/reference/digit-char.htm | 79 + docsrc/xlisp/xlisp-doc/reference/division.htm | 101 + docsrc/xlisp/xlisp-doc/reference/do-star.htm | 144 + docsrc/xlisp/xlisp-doc/reference/do.htm | 133 + docsrc/xlisp/xlisp-doc/reference/dolist.htm | 111 + docsrc/xlisp/xlisp-doc/reference/dotimes.htm | 101 + docsrc/xlisp/xlisp-doc/reference/dribble.htm | 82 + docsrc/xlisp/xlisp-doc/reference/echoenabled.htm | 68 + docsrc/xlisp/xlisp-doc/reference/endp.htm | 86 + docsrc/xlisp/xlisp-doc/reference/eq.htm | 93 + docsrc/xlisp/xlisp-doc/reference/eql.htm | 99 + docsrc/xlisp/xlisp-doc/reference/equal.htm | 111 + docsrc/xlisp/xlisp-doc/reference/error.htm | 161 + docsrc/xlisp/xlisp-doc/reference/errset.htm | 117 + docsrc/xlisp/xlisp-doc/reference/eval.htm | 79 + docsrc/xlisp/xlisp-doc/reference/evalhook.htm | 142 + docsrc/xlisp/xlisp-doc/reference/evenp.htm | 92 + docsrc/xlisp/xlisp-doc/reference/exit.htm | 69 + docsrc/xlisp/xlisp-doc/reference/exp.htm | 76 + docsrc/xlisp/xlisp-doc/reference/expand.htm | 91 + docsrc/xlisp/xlisp-doc/reference/expt.htm | 79 + docsrc/xlisp/xlisp-doc/reference/fboundp.htm | 84 + docsrc/xlisp/xlisp-doc/reference/filep.htm | 75 + .../xlisp-doc/reference/find-in-xlisp-path.htm | 66 + docsrc/xlisp/xlisp-doc/reference/first.htm | 74 + docsrc/xlisp/xlisp-doc/reference/flatc.htm | 74 + docsrc/xlisp/xlisp-doc/reference/flatsize.htm | 74 + docsrc/xlisp/xlisp-doc/reference/flet.htm | 87 + docsrc/xlisp/xlisp-doc/reference/float.htm | 71 + docsrc/xlisp/xlisp-doc/reference/floatp.htm | 81 + docsrc/xlisp/xlisp-doc/reference/format.htm | 161 + docsrc/xlisp/xlisp-doc/reference/fourth.htm | 79 + docsrc/xlisp/xlisp-doc/reference/funcall.htm | 102 + docsrc/xlisp/xlisp-doc/reference/function.htm | 87 + docsrc/xlisp/xlisp-doc/reference/gc.htm | 74 + docsrc/xlisp/xlisp-doc/reference/gcd.htm | 75 + docsrc/xlisp/xlisp-doc/reference/gensym.htm | 89 + docsrc/xlisp/xlisp-doc/reference/get-env.htm | 64 + docsrc/xlisp/xlisp-doc/reference/get-key.htm | 66 + .../xlisp-doc/reference/get-lambda-expression.htm | 78 + .../xlisp-doc/reference/get-output-stream-list.htm | 75 + .../reference/get-output-stream-string.htm | 80 + docsrc/xlisp/xlisp-doc/reference/get-temp-path.htm | 68 + docsrc/xlisp/xlisp-doc/reference/get-user.htm | 67 + docsrc/xlisp/xlisp-doc/reference/get.htm | 97 + .../xlisp/xlisp-doc/reference/global-applyhook.htm | 78 + .../xlisp-doc/reference/global-breakenable.htm | 106 + .../xlisp/xlisp-doc/reference/global-debug-io.htm | 72 + .../xlisp-doc/reference/global-error-output.htm | 71 + .../xlisp/xlisp-doc/reference/global-evalhook.htm | 123 + .../xlisp-doc/reference/global-file-separator.htm | 68 + .../xlisp-doc/reference/global-float-format.htm | 179 + .../xlisp/xlisp-doc/reference/global-gc-flag.htm | 79 + .../xlisp/xlisp-doc/reference/global-gc-hook.htm | 125 + .../xlisp-doc/reference/global-integer-format.htm | 129 + .../xlisp/xlisp-doc/reference/global-obarray.htm | 79 + .../xlisp-doc/reference/global-print-case.htm | 82 + .../xlisp/xlisp-doc/reference/global-readtable.htm | 166 + docsrc/xlisp/xlisp-doc/reference/global-rslt.htm | 83 + .../xlisp-doc/reference/global-standard-input.htm | 73 + .../xlisp-doc/reference/global-standard-output.htm | 81 + .../xlisp-doc/reference/global-trace-output.htm | 71 + .../xlisp-doc/reference/global-tracelimit.htm | 103 + .../xlisp/xlisp-doc/reference/global-tracelist.htm | 74 + .../xlisp-doc/reference/global-tracenable.htm | 105 + .../xlisp/xlisp-doc/reference/global-unbound.htm | 70 + docsrc/xlisp/xlisp-doc/reference/go.htm | 106 + docsrc/xlisp/xlisp-doc/reference/hash.htm | 90 + docsrc/xlisp/xlisp-doc/reference/if.htm | 83 + docsrc/xlisp/xlisp-doc/reference/incf.htm | 88 + docsrc/xlisp/xlisp-doc/reference/increment.htm | 75 + docsrc/xlisp/xlisp-doc/reference/info.htm | 63 + docsrc/xlisp/xlisp-doc/reference/int-char.htm | 92 + docsrc/xlisp/xlisp-doc/reference/integerp.htm | 82 + docsrc/xlisp/xlisp-doc/reference/intern.htm | 117 + docsrc/xlisp/xlisp-doc/reference/interpolate.htm | 76 + docsrc/xlisp/xlisp-doc/reference/intersection.htm | 76 + .../xlisp/xlisp-doc/reference/keyword-answer.htm | 107 + docsrc/xlisp/xlisp-doc/reference/keyword-class.htm | 83 + .../xlisp-doc/reference/keyword-constituent.htm | 95 + docsrc/xlisp/xlisp-doc/reference/keyword-isa.htm | 83 + docsrc/xlisp/xlisp-doc/reference/keyword-isnew.htm | 96 + .../xlisp/xlisp-doc/reference/keyword-mescape.htm | 86 + docsrc/xlisp/xlisp-doc/reference/keyword-new.htm | 86 + .../xlisp/xlisp-doc/reference/keyword-nmacro.htm | 103 + .../xlisp/xlisp-doc/reference/keyword-sescape.htm | 84 + docsrc/xlisp/xlisp-doc/reference/keyword-show.htm | 82 + .../xlisp/xlisp-doc/reference/keyword-tmacro.htm | 107 + .../xlisp-doc/reference/keyword-white-space.htm | 92 + docsrc/xlisp/xlisp-doc/reference/keywordp.htm | 78 + docsrc/xlisp/xlisp-doc/reference/labels.htm | 101 + .../xlisp-doc/reference/lambda-keyword-aux.htm | 116 + .../xlisp-doc/reference/lambda-keyword-key.htm | 132 + .../reference/lambda-keyword-optional.htm | 98 + .../xlisp-doc/reference/lambda-keyword-rest.htm | 104 + docsrc/xlisp/xlisp-doc/reference/lambda.htm | 109 + docsrc/xlisp/xlisp-doc/reference/last.htm | 75 + docsrc/xlisp/xlisp-doc/reference/length.htm | 74 + docsrc/xlisp/xlisp-doc/reference/let-star.htm | 106 + docsrc/xlisp/xlisp-doc/reference/let.htm | 94 + docsrc/xlisp/xlisp-doc/reference/list.htm | 74 + docsrc/xlisp/xlisp-doc/reference/listdir.htm | 67 + docsrc/xlisp/xlisp-doc/reference/listp.htm | 92 + docsrc/xlisp/xlisp-doc/reference/load.htm | 162 + docsrc/xlisp/xlisp-doc/reference/log.htm | 67 + docsrc/xlisp/xlisp-doc/reference/logand.htm | 81 + docsrc/xlisp/xlisp-doc/reference/logior.htm | 82 + docsrc/xlisp/xlisp-doc/reference/lognot.htm | 79 + docsrc/xlisp/xlisp-doc/reference/logxor.htm | 82 + docsrc/xlisp/xlisp-doc/reference/loop.htm | 84 + docsrc/xlisp/xlisp-doc/reference/lower-case-p.htm | 79 + docsrc/xlisp/xlisp-doc/reference/macroexpand-1.htm | 85 + docsrc/xlisp/xlisp-doc/reference/macroexpand.htm | 83 + docsrc/xlisp/xlisp-doc/reference/macrolet.htm | 146 + docsrc/xlisp/xlisp-doc/reference/make-array.htm | 95 + .../reference/make-string-input-stream.htm | 84 + .../reference/make-string-output-stream.htm | 79 + docsrc/xlisp/xlisp-doc/reference/make-symbol.htm | 93 + docsrc/xlisp/xlisp-doc/reference/mapc.htm | 87 + docsrc/xlisp/xlisp-doc/reference/mapcar.htm | 151 + docsrc/xlisp/xlisp-doc/reference/mapl.htm | 89 + docsrc/xlisp/xlisp-doc/reference/maplist.htm | 86 + docsrc/xlisp/xlisp-doc/reference/max.htm | 73 + docsrc/xlisp/xlisp-doc/reference/member.htm | 93 + docsrc/xlisp/xlisp-doc/reference/min.htm | 73 + docsrc/xlisp/xlisp-doc/reference/minusp.htm | 84 + .../xlisp/xlisp-doc/reference/multiplication.htm | 87 + docsrc/xlisp/xlisp-doc/reference/nconc.htm | 89 + docsrc/xlisp/xlisp-doc/reference/nil.htm | 70 + docsrc/xlisp/xlisp-doc/reference/not.htm | 80 + .../xlisp/xlisp-doc/reference/nstring-downcase.htm | 82 + .../xlisp/xlisp-doc/reference/nstring-upcase.htm | 82 + docsrc/xlisp/xlisp-doc/reference/nth.htm | 74 + docsrc/xlisp/xlisp-doc/reference/nthcdr.htm | 75 + docsrc/xlisp/xlisp-doc/reference/null.htm | 80 + docsrc/xlisp/xlisp-doc/reference/number-equal.htm | 87 + .../xlisp/xlisp-doc/reference/number-greaterp.htm | 90 + docsrc/xlisp/xlisp-doc/reference/number-lessp.htm | 90 + .../xlisp/xlisp-doc/reference/number-not-equal.htm | 101 + .../xlisp-doc/reference/number-not-greaterp.htm | 91 + .../xlisp/xlisp-doc/reference/number-not-lessp.htm | 92 + docsrc/xlisp/xlisp-doc/reference/numberp.htm | 78 + docsrc/xlisp/xlisp-doc/reference/object.htm | 120 + docsrc/xlisp/xlisp-doc/reference/objectp.htm | 72 + docsrc/xlisp/xlisp-doc/reference/oddp.htm | 92 + docsrc/xlisp/xlisp-doc/reference/open-binary.htm | 103 + docsrc/xlisp/xlisp-doc/reference/open.htm | 117 + docsrc/xlisp/xlisp-doc/reference/or.htm | 87 + docsrc/xlisp/xlisp-doc/reference/peek-char.htm | 105 + docsrc/xlisp/xlisp-doc/reference/peek.htm | 86 + docsrc/xlisp/xlisp-doc/reference/pi.htm | 66 + docsrc/xlisp/xlisp-doc/reference/plus.htm | 75 + docsrc/xlisp/xlisp-doc/reference/poke.htm | 88 + docsrc/xlisp/xlisp-doc/reference/pop.htm | 85 + docsrc/xlisp/xlisp-doc/reference/power.htm | 77 + docsrc/xlisp/xlisp-doc/reference/pprint.htm | 94 + docsrc/xlisp/xlisp-doc/reference/prin1.htm | 94 + docsrc/xlisp/xlisp-doc/reference/princ.htm | 94 + docsrc/xlisp/xlisp-doc/reference/print.htm | 95 + docsrc/xlisp/xlisp-doc/reference/profile.htm | 85 + docsrc/xlisp/xlisp-doc/reference/prog-star.htm | 101 + docsrc/xlisp/xlisp-doc/reference/prog.htm | 96 + docsrc/xlisp/xlisp-doc/reference/prog1.htm | 80 + docsrc/xlisp/xlisp-doc/reference/prog2.htm | 82 + docsrc/xlisp/xlisp-doc/reference/progn.htm | 81 + docsrc/xlisp/xlisp-doc/reference/progv.htm | 133 + docsrc/xlisp/xlisp-doc/reference/psetq.htm | 78 + docsrc/xlisp/xlisp-doc/reference/push.htm | 83 + docsrc/xlisp/xlisp-doc/reference/putprop.htm | 108 + docsrc/xlisp/xlisp-doc/reference/quit.htm | 69 + docsrc/xlisp/xlisp-doc/reference/quote.htm | 84 + docsrc/xlisp/xlisp-doc/reference/random.htm | 86 + docsrc/xlisp/xlisp-doc/reference/read-byte.htm | 100 + docsrc/xlisp/xlisp-doc/reference/read-char.htm | 100 + docsrc/xlisp/xlisp-doc/reference/read-float.htm | 79 + docsrc/xlisp/xlisp-doc/reference/read-int.htm | 78 + docsrc/xlisp/xlisp-doc/reference/read-line.htm | 97 + docsrc/xlisp/xlisp-doc/reference/read.htm | 125 + docsrc/xlisp/xlisp-doc/reference/real-random.htm | 82 + .../xlisp-doc/reference/reference-copyright.htm | 50 + .../xlisp/xlisp-doc/reference/reference-format.htm | 83 + .../xlisp/xlisp-doc/reference/reference-index.htm | 2468 ++ docsrc/xlisp/xlisp-doc/reference/reference.css | 34 + docsrc/xlisp/xlisp-doc/reference/rem.htm | 88 + docsrc/xlisp/xlisp-doc/reference/remove-if-not.htm | 80 + docsrc/xlisp/xlisp-doc/reference/remove-if.htm | 80 + docsrc/xlisp/xlisp-doc/reference/remove.htm | 100 + docsrc/xlisp/xlisp-doc/reference/remprop.htm | 94 + docsrc/xlisp/xlisp-doc/reference/rest.htm | 80 + docsrc/xlisp/xlisp-doc/reference/restore.htm | 112 + docsrc/xlisp/xlisp-doc/reference/return-from.htm | 89 + docsrc/xlisp/xlisp-doc/reference/return.htm | 93 + docsrc/xlisp/xlisp-doc/reference/reverse.htm | 73 + docsrc/xlisp/xlisp-doc/reference/room.htm | 90 + docsrc/xlisp/xlisp-doc/reference/round.htm | 81 + docsrc/xlisp/xlisp-doc/reference/rplaca.htm | 99 + docsrc/xlisp/xlisp-doc/reference/rplacd.htm | 89 + docsrc/xlisp/xlisp-doc/reference/rrandom.htm | 66 + docsrc/xlisp/xlisp-doc/reference/save.htm | 124 + docsrc/xlisp/xlisp-doc/reference/second.htm | 81 + docsrc/xlisp/xlisp-doc/reference/self.htm | 81 + docsrc/xlisp/xlisp-doc/reference/send-super.htm | 87 + docsrc/xlisp/xlisp-doc/reference/send.htm | 96 + .../xlisp/xlisp-doc/reference/set-difference.htm | 75 + docsrc/xlisp/xlisp-doc/reference/set.htm | 83 + docsrc/xlisp/xlisp-doc/reference/setdir.htm | 65 + docsrc/xlisp/xlisp-doc/reference/setf.htm | 273 + docsrc/xlisp/xlisp-doc/reference/setq.htm | 70 + docsrc/xlisp/xlisp-doc/reference/setup-console.htm | 72 + docsrc/xlisp/xlisp-doc/reference/sin.htm | 76 + docsrc/xlisp/xlisp-doc/reference/sort.htm | 104 + docsrc/xlisp/xlisp-doc/reference/soundp.htm | 70 + docsrc/xlisp/xlisp-doc/reference/sqrt.htm | 76 + docsrc/xlisp/xlisp-doc/reference/strcat.htm | 72 + docsrc/xlisp/xlisp-doc/reference/streamp.htm | 84 + .../xlisp/xlisp-doc/reference/string-downcase.htm | 80 + .../xlisp/xlisp-doc/reference/string-equal-i.htm | 111 + .../xlisp/xlisp-doc/reference/string-equal-s.htm | 96 + .../xlisp-doc/reference/string-greaterp-i.htm | 98 + .../xlisp-doc/reference/string-greaterp-s.htm | 99 + .../xlisp/xlisp-doc/reference/string-left-trim.htm | 84 + .../xlisp/xlisp-doc/reference/string-lessp-i.htm | 98 + .../xlisp/xlisp-doc/reference/string-lessp-s.htm | 98 + .../xlisp-doc/reference/string-not-equal-i.htm | 112 + .../xlisp-doc/reference/string-not-equal-s.htm | 104 + .../xlisp-doc/reference/string-not-greaterp-i.htm | 99 + .../xlisp-doc/reference/string-not-greaterp-s.htm | 99 + .../xlisp-doc/reference/string-not-lessp-i.htm | 98 + .../xlisp-doc/reference/string-not-lessp-s.htm | 99 + .../xlisp-doc/reference/string-right-trim.htm | 85 + docsrc/xlisp/xlisp-doc/reference/string-search.htm | 68 + docsrc/xlisp/xlisp-doc/reference/string-trim.htm | 84 + docsrc/xlisp/xlisp-doc/reference/string-upcase.htm | 80 + docsrc/xlisp/xlisp-doc/reference/string.htm | 88 + docsrc/xlisp/xlisp-doc/reference/stringp.htm | 80 + docsrc/xlisp/xlisp-doc/reference/sublis.htm | 129 + docsrc/xlisp/xlisp-doc/reference/subseq.htm | 83 + docsrc/xlisp/xlisp-doc/reference/subsetp.htm | 79 + docsrc/xlisp/xlisp-doc/reference/subst.htm | 96 + docsrc/xlisp/xlisp-doc/reference/subtraction.htm | 88 + .../xlisp/xlisp-doc/reference/symbol-function.htm | 67 + docsrc/xlisp/xlisp-doc/reference/symbol-name.htm | 80 + docsrc/xlisp/xlisp-doc/reference/symbol-plist.htm | 85 + docsrc/xlisp/xlisp-doc/reference/symbol-value.htm | 82 + docsrc/xlisp/xlisp-doc/reference/symbolp.htm | 85 + docsrc/xlisp/xlisp-doc/reference/system.htm | 73 + docsrc/xlisp/xlisp-doc/reference/t.htm | 71 + docsrc/xlisp/xlisp-doc/reference/tagbody.htm | 81 + docsrc/xlisp/xlisp-doc/reference/tan.htm | 76 + docsrc/xlisp/xlisp-doc/reference/terpri.htm | 90 + docsrc/xlisp/xlisp-doc/reference/third.htm | 81 + docsrc/xlisp/xlisp-doc/reference/throw.htm | 23 + docsrc/xlisp/xlisp-doc/reference/top-level.htm | 91 + docsrc/xlisp/xlisp-doc/reference/trace.htm | 93 + docsrc/xlisp/xlisp-doc/reference/truncate.htm | 74 + docsrc/xlisp/xlisp-doc/reference/type-of.htm | 103 + docsrc/xlisp/xlisp-doc/reference/union.htm | 80 + docsrc/xlisp/xlisp-doc/reference/unless.htm | 82 + docsrc/xlisp/xlisp-doc/reference/untrace.htm | 86 + .../xlisp/xlisp-doc/reference/unwind-protect.htm | 137 + docsrc/xlisp/xlisp-doc/reference/upper-case-p.htm | 76 + docsrc/xlisp/xlisp-doc/reference/vector.htm | 73 + docsrc/xlisp/xlisp-doc/reference/when.htm | 82 + docsrc/xlisp/xlisp-doc/reference/while.htm | 81 + docsrc/xlisp/xlisp-doc/reference/write-byte.htm | 92 + docsrc/xlisp/xlisp-doc/reference/write-char.htm | 92 + docsrc/xlisp/xlisp-doc/reference/write-float.htm | 80 + docsrc/xlisp/xlisp-doc/reference/write-int.htm | 79 + docsrc/xlisp/xlisp-doc/reference/zerop.htm | 81 + docsrc/xlisp/xlisp-doc/start.htm | 86 + docsrc/xlisp/xlisp-doc/tutorials/binary-io.htm | 79 + docsrc/xlisp/xlisp-doc/tutorials/environment.htm | 530 + docsrc/xlisp/xlisp-doc/tutorials/file-io.htm | 349 + docsrc/xlisp/xlisp-doc/tutorials/lisp-faq.htm | 199 + docsrc/xlisp/xlisp-doc/tutorials/lisp-hints.htm | 2055 ++ docsrc/xlisp/xlisp-doc/tutorials/nyquist.htm | 383 + .../xlisp/xlisp-doc/tutorials/shell-utilities.htm | 539 + docsrc/xlisp/xlisp-doc/tutorials/tutorials.htm | 28 + docsrc/xlisp/xlisp-doc/tutorials/xlisp-objects.htm | 839 + docsrc/xlisp/xlisp-doc/tutorials/xobj-1.png | Bin 0 -> 1551 bytes docsrc/xlisp/xlisp-no-sal.mss | 3339 +++ docsrc/xlisp/xlisp.mss | 4016 ++++ fft/fftn.c | 1046 + fft/fftn.h | 32 + ffts/Matlab-testing/conv2dTest.c | 116 + ffts/Matlab-testing/conv2dtest.m | 25 + ffts/Matlab-testing/convTest.c | 113 + ffts/Matlab-testing/convtest.m | 26 + ffts/Matlab-testing/rfft2dTestML.c | 102 + ffts/Matlab-testing/rfft2dTestML.m | 39 + ffts/Numerical-Recipes-testing/fftTest.c | 121 + ffts/Numerical-Recipes-testing/fftTest2d.c | 130 + ffts/Numerical-Recipes-testing/fftTest3d.c | 135 + ffts/Numerical-Recipes-testing/rfftTest.c | 121 + ffts/Numerical-Recipes-testing/rfftTest2d.c | 158 + ffts/README.txt | 70 + ffts/Timing-code/fftTiming.c | 98 + ffts/Timing-code/rfftTiming.c | 90 + ffts/abstract | 37 + ffts/src/dxpose.c | 79 + ffts/src/dxpose.h | 16 + ffts/src/fft2d.c | 402 + ffts/src/fft2d.h | 114 + ffts/src/fftext.c | 156 + ffts/src/fftext.h | 106 + ffts/src/fftlib.c | 3174 +++ ffts/src/fftlib.h | 76 + ffts/src/files | 22 + ffts/src/matlib.c | 297 + ffts/src/matlib.h | 33 + files.txt | 997 + howtorelease.txt | 118 + init.lsp~ | 4 + jny | 3 + jnyqide.bat | 2 + jnyqide/BareBonesBrowserLaunch.java | 66 + jnyqide/CodePane.java | 671 + jnyqide/EnvelopeFrame.java | 1317 ++ jnyqide/FindDialog.java | 118 + jnyqide/InstrumentCharacteristics.java | 364 + jnyqide/Jslide.java | 201 + jnyqide/LispFileFilter.java | 33 + jnyqide/Main.java | 75 + jnyqide/MainFrame.java | 1539 ++ jnyqide/MainFrame_AboutBox.java | 98 + jnyqide/MiniBrowser.java | 66 + jnyqide/NotFoundDialog.java | 79 + jnyqide/NyqPlot.java | 131 + jnyqide/NyquistFile.java | 590 + jnyqide/NyquistThread.java | 424 + jnyqide/NyquistWords.txt | 1520 ++ jnyqide/Pair.java | 38 + jnyqide/Piano_Roll.java | 1104 + jnyqide/PlotFrame.java | 333 + jnyqide/PlotMouseAdapter.java | 67 + jnyqide/PopupListener.java | 46 + jnyqide/PreferencesDialog.java | 426 + jnyqide/README.txt | 152 + jnyqide/ReplaceDialog.java | 167 + jnyqide/SalFileFilter.java | 41 + jnyqide/SalWordList.java | 57 + jnyqide/SpecialMacHandler.java | 70 + jnyqide/SpringUtilities.java | 194 + jnyqide/TextColor.java | 984 + jnyqide/Trie.java | 129 + jnyqide/UPICFrame.java | 1425 ++ jnyqide/WordList.java | 247 + jnyqide/browser.java | 439 + jnyqide/closeFile.gif | Bin 0 -> 1154 bytes jnyqide/help.gif | Bin 0 -> 118 bytes jnyqide/keywords.txt | 512 + jnyqide/manifest.txt | 1 + jnyqide/openFile.gif | Bin 0 -> 1132 bytes lib/bandfx.lsp | 153 + lib/compress.lsp | 310 + lib/dist-test.lsp | 193 + lib/distributions.lsp | 155 + lib/dtmf.lsp | 46 + lib/gran.lsp | 149 + lib/grapheq.lsp | 74 + lib/instruments.txt | 249 + lib/lpc.lsp | 178 + lib/midishow.lsp | 48 + lib/moog.lsp | 146 + lib/piano/att11025.pcm | Bin 0 -> 10372 bytes lib/piano/att16000.pcm | Bin 0 -> 15052 bytes lib/piano/att22050.pcm | Bin 0 -> 20744 bytes lib/piano/att32000.pcm | Bin 0 -> 30108 bytes lib/piano/att44100.pcm | Bin 0 -> 41486 bytes lib/piano/att48000.pcm | Bin 0 -> 45156 bytes lib/piano/att8000.pcm | Bin 0 -> 7526 bytes lib/piano/demo.mid | Bin 0 -> 1601 bytes lib/piano/demo.mp3 | Bin 0 -> 769462 bytes lib/piano/dur.tab | Bin 0 -> 65552 bytes lib/piano/gmax.tab | Bin 0 -> 259088 bytes lib/piano/pn00.cod | Bin 0 -> 13724 bytes lib/piano/pn01.cod | Bin 0 -> 12968 bytes lib/piano/pn02.cod | Bin 0 -> 12740 bytes lib/piano/pn03.cod | Bin 0 -> 12528 bytes lib/piano/pn04.cod | Bin 0 -> 12700 bytes lib/piano/pn05.cod | Bin 0 -> 13008 bytes lib/piano/pn06.cod | Bin 0 -> 13344 bytes lib/piano/pn07.cod | Bin 0 -> 13864 bytes lib/piano/pn08.cod | Bin 0 -> 14436 bytes lib/piano/pn09.cod | Bin 0 -> 15128 bytes lib/piano/pn10.cod | Bin 0 -> 15916 bytes lib/piano/pn11.cod | Bin 0 -> 16776 bytes lib/piano/pn12.cod | Bin 0 -> 17608 bytes lib/piano/pn13.cod | Bin 0 -> 18240 bytes lib/piano/pn14.cod | Bin 0 -> 19808 bytes lib/piano/pn15.cod | Bin 0 -> 20216 bytes lib/piano/pn16.cod | Bin 0 -> 21144 bytes lib/piano/pn17.cod | Bin 0 -> 22272 bytes lib/piano/pn18.cod | Bin 0 -> 22724 bytes lib/piano/pn19.cod | Bin 0 -> 18104 bytes lib/piano/pn20.cod | Bin 0 -> 13256 bytes lib/piano/pn21.cod | Bin 0 -> 18224 bytes lib/piano/pn22.cod | Bin 0 -> 7984 bytes lib/piano/rls11025.pcm | Bin 0 -> 13982 bytes lib/piano/rls16000.pcm | Bin 0 -> 20292 bytes lib/piano/rls22050.pcm | Bin 0 -> 27964 bytes lib/piano/rls32000.pcm | Bin 0 -> 40586 bytes lib/piano/rls44100.pcm | Bin 0 -> 55928 bytes lib/piano/rls48000.pcm | Bin 0 -> 60876 bytes lib/piano/rls8000.pcm | Bin 0 -> 10146 bytes lib/piano/rlsrate.tab | Bin 0 -> 45584 bytes lib/pianosyn.lsp | 579 + lib/plugin-test.lsp | 184 + lib/reverb.lsp | 45 + lib/reverse.lsp | 117 + lib/sdl.lsp | 402 + lib/soften.lsp | 45 + lib/spatial.lsp | 506 + lib/spectrum.lsp | 135 + lib/statistics.lsp | 428 + lib/surround.lsp | 368 + lib/time-delay-fns.lsp | 90 + lib/vectors.lsp | 137 + lib/xm-test.lsp | 622 + liblo/AUTHORS | 30 + liblo/COPYING | 504 + liblo/ChangeLog | 350 + liblo/INSTALL | 229 + liblo/Makefile.am | 11 + liblo/Makefile.in | 776 + liblo/Makefile.osx | 4 + liblo/NEWS | 327 + liblo/README | 54 + liblo/README.txt | 57 + liblo/TODO | 14 + liblo/aclocal.m4 | 1003 + liblo/autogen.sh | 121 + liblo/build/Makefile.am | 4 + liblo/build/Makefile.in | 355 + liblo/build/lo_endian-msvc.h | 138 + liblo/build/premake4.exe | Bin 0 -> 205312 bytes liblo/build/premake4.lua | 210 + liblo/build/vs2008/config-msvc.h | 92 + liblo/build/vs2008/config.h | 2 + liblo/build/vs2008/liblo.suo | Bin 0 -> 13312 bytes liblo/build/vs2008/liblo.vcproj | 252 + liblo/build/vs2008/subtest.vcproj | 368 + liblo/build/vs2008/testlo.vcproj | 368 + liblo/compile | 142 + liblo/config.guess | 1561 ++ liblo/config.h.in | 98 + liblo/config.sub | 1686 ++ liblo/configure | 13468 +++++++++++ liblo/configure.ac | 90 + liblo/depcomp | 589 + liblo/doc/Makefile.am | 32 + liblo/doc/Makefile.in | 383 + liblo/doc/reference.doxygen | 1083 + liblo/doc/reference.doxygen.in | 1083 + liblo/examples/Makefile.am | 13 + liblo/examples/Makefile.in | 496 + liblo/examples/example_client.c | 62 + liblo/examples/example_server.c | 111 + liblo/examples/nonblocking_server_example.c | 197 + liblo/install-sh | 520 + liblo/liblo.pc.in | 10 + liblo/lo/Makefile.am | 4 + liblo/lo/Makefile.in | 456 + liblo/lo/lo.h | 353 + liblo/lo/lo_endian.h | 166 + liblo/lo/lo_endian.h.in | 166 + liblo/lo/lo_errors.h | 45 + liblo/lo/lo_lowlevel.h | 860 + liblo/lo/lo_macros.h | 80 + liblo/lo/lo_osc_types.h | 141 + liblo/lo/lo_throw.h | 30 + liblo/lo/lo_types.h | 141 + liblo/ltmain.sh | 8406 +++++++ liblo/m4/libtool.m4 | 7360 ++++++ liblo/m4/ltoptions.m4 | 368 + liblo/m4/ltsugar.m4 | 123 + liblo/m4/ltversion.m4 | 23 + liblo/m4/lt~obsolete.m4 | 92 + liblo/missing | 367 + liblo/osx/config.h | 92 + liblo/pthreads.2/ANNOUNCE | 476 + liblo/pthreads.2/BUGS | 133 + liblo/pthreads.2/Bmakefile | 266 + liblo/pthreads.2/BuildLog.htm | Bin 0 -> 3514 bytes liblo/pthreads.2/CONTRIBUTORS | 129 + liblo/pthreads.2/COPYING | 150 + liblo/pthreads.2/COPYING.LIB | 504 + liblo/pthreads.2/ChangeLog | 4821 ++++ liblo/pthreads.2/FAQ | 403 + liblo/pthreads.2/GNUmakefile | 583 + liblo/pthreads.2/MAINTAINERS | 4 + liblo/pthreads.2/Makefile | 504 + liblo/pthreads.2/NEWS | 1110 + liblo/pthreads.2/Nmakefile | 24 + liblo/pthreads.2/Nmakefile.tests | 260 + liblo/pthreads.2/PROGRESS | 4 + liblo/pthreads.2/README | 593 + liblo/pthreads.2/README.Borland | 57 + liblo/pthreads.2/README.CV | 3036 +++ liblo/pthreads.2/README.NONPORTABLE | 285 + liblo/pthreads.2/README.Watcom | 62 + liblo/pthreads.2/README.WinCE | 6 + liblo/pthreads.2/TODO | 7 + liblo/pthreads.2/WinCE-PORT | 217 + liblo/pthreads.2/attr.c | 53 + liblo/pthreads.2/barrier.c | 47 + liblo/pthreads.2/builddmc.bat | 9 + liblo/pthreads.2/cancel.c | 44 + liblo/pthreads.2/cleanup.c | 148 + liblo/pthreads.2/condvar.c | 50 + liblo/pthreads.2/config.h | 134 + liblo/pthreads.2/create.c | 305 + liblo/pthreads.2/dll.c | 92 + liblo/pthreads.2/errno.c | 94 + liblo/pthreads.2/exit.c | 44 + liblo/pthreads.2/fork.c | 39 + liblo/pthreads.2/global.c | 115 + liblo/pthreads.2/implement.h | 710 + liblo/pthreads.2/manual/ChangeLog | 62 + liblo/pthreads.2/manual/PortabilityIssues.html | 718 + liblo/pthreads.2/manual/index.html | 146 + liblo/pthreads.2/manual/pthreadCancelableWait.html | 86 + liblo/pthreads.2/manual/pthread_attr_init.html | 280 + .../manual/pthread_attr_setstackaddr.html | 158 + .../manual/pthread_attr_setstacksize.html | 127 + liblo/pthreads.2/manual/pthread_barrier_init.html | 200 + liblo/pthreads.2/manual/pthread_barrier_wait.html | 167 + .../manual/pthread_barrierattr_init.html | 142 + .../manual/pthread_barrierattr_setpshared.html | 159 + liblo/pthreads.2/manual/pthread_cancel.html | 205 + liblo/pthreads.2/manual/pthread_cleanup_push.html | 140 + liblo/pthreads.2/manual/pthread_cond_init.html | 313 + liblo/pthreads.2/manual/pthread_condattr_init.html | 98 + .../manual/pthread_condattr_setpshared.html | 153 + liblo/pthreads.2/manual/pthread_create.html | 94 + liblo/pthreads.2/manual/pthread_delay_np.html | 71 + liblo/pthreads.2/manual/pthread_detach.html | 90 + liblo/pthreads.2/manual/pthread_equal.html | 48 + liblo/pthreads.2/manual/pthread_exit.html | 59 + .../manual/pthread_getw32threadhandle_np.html | 57 + liblo/pthreads.2/manual/pthread_join.html | 118 + liblo/pthreads.2/manual/pthread_key_create.html | 211 + liblo/pthreads.2/manual/pthread_kill.html | 152 + liblo/pthreads.2/manual/pthread_mutex_init.html | 277 + .../pthreads.2/manual/pthread_mutexattr_init.html | 157 + .../manual/pthread_mutexattr_setpshared.html | 151 + .../manual/pthread_num_processors_np.html | 57 + liblo/pthreads.2/manual/pthread_once.html | 83 + liblo/pthreads.2/manual/pthread_rwlock_init.html | 193 + liblo/pthreads.2/manual/pthread_rwlock_rdlock.html | 168 + .../manual/pthread_rwlock_timedrdlock.html | 156 + .../manual/pthread_rwlock_timedwrlock.html | 150 + liblo/pthreads.2/manual/pthread_rwlock_unlock.html | 141 + liblo/pthreads.2/manual/pthread_rwlock_wrlock.html | 153 + .../pthreads.2/manual/pthread_rwlockattr_init.html | 141 + .../manual/pthread_rwlockattr_setpshared.html | 160 + liblo/pthreads.2/manual/pthread_self.html | 70 + .../pthreads.2/manual/pthread_setcancelstate.html | 207 + liblo/pthreads.2/manual/pthread_setcanceltype.html | 207 + .../pthreads.2/manual/pthread_setconcurrency.html | 155 + liblo/pthreads.2/manual/pthread_setschedparam.html | 113 + liblo/pthreads.2/manual/pthread_spin_init.html | 176 + liblo/pthreads.2/manual/pthread_spin_lock.html | 141 + liblo/pthreads.2/manual/pthread_spin_unlock.html | 124 + .../manual/pthread_timechange_handler_np.html | 76 + .../manual/pthread_win32_attach_detach_np.html | 74 + .../manual/pthread_win32_test_features_np.html | 68 + .../pthreads.2/manual/sched_get_priority_max.html | 115 + liblo/pthreads.2/manual/sched_getscheduler.html | 127 + liblo/pthreads.2/manual/sched_setscheduler.html | 181 + liblo/pthreads.2/manual/sched_yield.html | 98 + liblo/pthreads.2/manual/sem_init.html | 200 + liblo/pthreads.2/misc.c | 50 + liblo/pthreads.2/mt.dep | 1 + liblo/pthreads.2/mutex.c | 59 + liblo/pthreads.2/need_errno.h | 132 + liblo/pthreads.2/nonportable.c | 46 + liblo/pthreads.2/private.c | 57 + liblo/pthreads.2/pthread.c | 65 + liblo/pthreads.2/pthread.h | 1368 ++ liblo/pthreads.2/pthread.suo | Bin 0 -> 9728 bytes liblo/pthreads.2/pthread.vcproj | 259 + liblo/pthreads.2/pthreadVC2.dll.embed.manifest.res | Bin 0 -> 728 bytes liblo/pthreads.2/pthread_attr_destroy.c | 79 + liblo/pthreads.2/pthread_attr_getdetachstate.c | 87 + liblo/pthreads.2/pthread_attr_getinheritsched.c | 51 + liblo/pthreads.2/pthread_attr_getschedparam.c | 52 + liblo/pthreads.2/pthread_attr_getschedpolicy.c | 61 + liblo/pthreads.2/pthread_attr_getscope.c | 54 + liblo/pthreads.2/pthread_attr_getstackaddr.c | 97 + liblo/pthreads.2/pthread_attr_getstacksize.c | 100 + liblo/pthreads.2/pthread_attr_init.c | 117 + liblo/pthreads.2/pthread_attr_setdetachstate.c | 91 + liblo/pthreads.2/pthread_attr_setinheritsched.c | 57 + liblo/pthreads.2/pthread_attr_setschedparam.c | 63 + liblo/pthreads.2/pthread_attr_setschedpolicy.c | 55 + liblo/pthreads.2/pthread_attr_setscope.c | 62 + liblo/pthreads.2/pthread_attr_setstackaddr.c | 97 + liblo/pthreads.2/pthread_attr_setstacksize.c | 110 + liblo/pthreads.2/pthread_barrier_destroy.c | 67 + liblo/pthreads.2/pthread_barrier_init.c | 81 + liblo/pthreads.2/pthread_barrier_wait.c | 99 + liblo/pthreads.2/pthread_barrierattr_destroy.c | 83 + liblo/pthreads.2/pthread_barrierattr_getpshared.c | 95 + liblo/pthreads.2/pthread_barrierattr_init.c | 85 + liblo/pthreads.2/pthread_barrierattr_setpshared.c | 119 + liblo/pthreads.2/pthread_cancel.c | 223 + liblo/pthreads.2/pthread_cond_destroy.c | 244 + liblo/pthreads.2/pthread_cond_init.c | 165 + liblo/pthreads.2/pthread_cond_signal.c | 231 + liblo/pthreads.2/pthread_cond_wait.c | 567 + liblo/pthreads.2/pthread_condattr_destroy.c | 86 + liblo/pthreads.2/pthread_condattr_getpshared.c | 97 + liblo/pthreads.2/pthread_condattr_init.c | 87 + liblo/pthreads.2/pthread_condattr_setpshared.c | 117 + liblo/pthreads.2/pthread_delay_np.c | 171 + liblo/pthreads.2/pthread_detach.c | 139 + liblo/pthreads.2/pthread_equal.c | 76 + liblo/pthreads.2/pthread_exit.c | 106 + liblo/pthreads.2/pthread_getconcurrency.c | 45 + liblo/pthreads.2/pthread_getschedparam.c | 75 + liblo/pthreads.2/pthread_getspecific.c | 84 + liblo/pthreads.2/pthread_getw32threadhandle_np.c | 53 + liblo/pthreads.2/pthread_join.c | 154 + liblo/pthreads.2/pthread_key_create.c | 108 + liblo/pthreads.2/pthread_key_delete.c | 133 + liblo/pthreads.2/pthread_kill.c | 102 + liblo/pthreads.2/pthread_mutex_destroy.c | 146 + liblo/pthreads.2/pthread_mutex_init.c | 104 + liblo/pthreads.2/pthread_mutex_lock.c | 139 + liblo/pthreads.2/pthread_mutex_timedlock.c | 196 + liblo/pthreads.2/pthread_mutex_trylock.c | 92 + liblo/pthreads.2/pthread_mutex_unlock.c | 119 + liblo/pthreads.2/pthread_mutexattr_destroy.c | 83 + liblo/pthreads.2/pthread_mutexattr_getkind_np.c | 44 + liblo/pthreads.2/pthread_mutexattr_getpshared.c | 95 + liblo/pthreads.2/pthread_mutexattr_gettype.c | 56 + liblo/pthreads.2/pthread_mutexattr_init.c | 86 + liblo/pthreads.2/pthread_mutexattr_setkind_np.c | 44 + liblo/pthreads.2/pthread_mutexattr_setpshared.c | 119 + liblo/pthreads.2/pthread_mutexattr_settype.c | 143 + liblo/pthreads.2/pthread_num_processors_np.c | 56 + liblo/pthreads.2/pthread_once.c | 86 + liblo/pthreads.2/pthread_once.x | 204 + liblo/pthreads.2/pthread_rwlock_destroy.c | 143 + liblo/pthreads.2/pthread_rwlock_init.c | 110 + liblo/pthreads.2/pthread_rwlock_rdlock.c | 103 + liblo/pthreads.2/pthread_rwlock_timedrdlock.c | 110 + liblo/pthreads.2/pthread_rwlock_timedwrlock.c | 140 + liblo/pthreads.2/pthread_rwlock_tryrdlock.c | 103 + liblo/pthreads.2/pthread_rwlock_trywrlock.c | 123 + liblo/pthreads.2/pthread_rwlock_unlock.c | 94 + liblo/pthreads.2/pthread_rwlock_wrlock.c | 134 + liblo/pthreads.2/pthread_rwlockattr_destroy.c | 85 + liblo/pthreads.2/pthread_rwlockattr_getpshared.c | 98 + liblo/pthreads.2/pthread_rwlockattr_init.c | 84 + liblo/pthreads.2/pthread_rwlockattr_setpshared.c | 121 + liblo/pthreads.2/pthread_self.c | 138 + liblo/pthreads.2/pthread_setcancelstate.c | 124 + liblo/pthreads.2/pthread_setcanceltype.c | 125 + liblo/pthreads.2/pthread_setconcurrency.c | 53 + liblo/pthreads.2/pthread_setschedparam.c | 125 + liblo/pthreads.2/pthread_setspecific.c | 168 + liblo/pthreads.2/pthread_spin_destroy.c | 112 + liblo/pthreads.2/pthread_spin_init.c | 123 + liblo/pthreads.2/pthread_spin_lock.c | 83 + liblo/pthreads.2/pthread_spin_trylock.c | 80 + liblo/pthreads.2/pthread_spin_unlock.c | 75 + liblo/pthreads.2/pthread_testcancel.c | 102 + liblo/pthreads.2/pthread_timechange_handler_np.c | 107 + liblo/pthreads.2/pthread_win32_attach_detach_np.c | 303 + .../pthreads.2/ptw32_InterlockedCompareExchange.c | 303 + liblo/pthreads.2/ptw32_MCS_lock.c | 210 + liblo/pthreads.2/ptw32_callUserDestroyRoutines.c | 220 + liblo/pthreads.2/ptw32_calloc.c | 56 + liblo/pthreads.2/ptw32_cond_check_need_init.c | 94 + liblo/pthreads.2/ptw32_getprocessors.c | 91 + liblo/pthreads.2/ptw32_is_attr.c | 47 + liblo/pthreads.2/ptw32_mutex_check_need_init.c | 112 + liblo/pthreads.2/ptw32_new.c | 91 + liblo/pthreads.2/ptw32_processInitialize.c | 102 + liblo/pthreads.2/ptw32_processTerminate.c | 114 + liblo/pthreads.2/ptw32_relmillisecs.c | 120 + liblo/pthreads.2/ptw32_reuse.c | 147 + liblo/pthreads.2/ptw32_rwlock_cancelwrwait.c | 50 + liblo/pthreads.2/ptw32_rwlock_check_need_init.c | 93 + liblo/pthreads.2/ptw32_semwait.c | 118 + liblo/pthreads.2/ptw32_spinlock_check_need_init.c | 81 + liblo/pthreads.2/ptw32_threadDestroy.c | 82 + liblo/pthreads.2/ptw32_threadStart.c | 360 + liblo/pthreads.2/ptw32_throw.c | 167 + liblo/pthreads.2/ptw32_timespec.c | 83 + liblo/pthreads.2/ptw32_tkAssocCreate.c | 118 + liblo/pthreads.2/ptw32_tkAssocDestroy.c | 114 + liblo/pthreads.2/rwlock.c | 51 + liblo/pthreads.2/sched.c | 53 + liblo/pthreads.2/sched.h | 178 + liblo/pthreads.2/sched_get_priority_max.c | 134 + liblo/pthreads.2/sched_get_priority_min.c | 135 + liblo/pthreads.2/sched_getscheduler.c | 69 + liblo/pthreads.2/sched_setscheduler.c | 81 + liblo/pthreads.2/sched_yield.c | 71 + liblo/pthreads.2/sem_close.c | 58 + liblo/pthreads.2/sem_destroy.c | 144 + liblo/pthreads.2/sem_getvalue.c | 110 + liblo/pthreads.2/sem_init.c | 169 + liblo/pthreads.2/sem_open.c | 58 + liblo/pthreads.2/sem_post.c | 128 + liblo/pthreads.2/sem_post_multiple.c | 142 + liblo/pthreads.2/sem_timedwait.c | 238 + liblo/pthreads.2/sem_trywait.c | 117 + liblo/pthreads.2/sem_unlink.c | 58 + liblo/pthreads.2/sem_wait.c | 187 + liblo/pthreads.2/semaphore.c | 69 + liblo/pthreads.2/semaphore.h | 166 + liblo/pthreads.2/signal.c | 179 + liblo/pthreads.2/spin.c | 46 + liblo/pthreads.2/sync.c | 43 + liblo/pthreads.2/tests/Bmakefile | 350 + liblo/pthreads.2/tests/ChangeLog | 894 + liblo/pthreads.2/tests/Debug.dsp | 93 + liblo/pthreads.2/tests/Debug.dsw | 29 + liblo/pthreads.2/tests/Debug.txt | 6 + liblo/pthreads.2/tests/GNUmakefile | 375 + liblo/pthreads.2/tests/Makefile | 404 + liblo/pthreads.2/tests/README.BENCHTESTS | 74 + liblo/pthreads.2/tests/SIZES.VCE | 21 + liblo/pthreads.2/tests/Wmakefile | 346 + liblo/pthreads.2/tests/barrier1.c | 58 + liblo/pthreads.2/tests/barrier2.c | 55 + liblo/pthreads.2/tests/barrier3.c | 71 + liblo/pthreads.2/tests/barrier4.c | 110 + liblo/pthreads.2/tests/barrier5.c | 128 + liblo/pthreads.2/tests/benchlib.c | 363 + liblo/pthreads.2/tests/benchtest.h | 70 + liblo/pthreads.2/tests/benchtest1.c | 249 + liblo/pthreads.2/tests/benchtest2.c | 311 + liblo/pthreads.2/tests/benchtest3.c | 201 + liblo/pthreads.2/tests/benchtest4.c | 182 + liblo/pthreads.2/tests/benchtest5.c | 159 + liblo/pthreads.2/tests/cancel1.c | 179 + liblo/pthreads.2/tests/cancel2.c | 251 + liblo/pthreads.2/tests/cancel3.c | 201 + liblo/pthreads.2/tests/cancel4.c | 203 + liblo/pthreads.2/tests/cancel5.c | 199 + liblo/pthreads.2/tests/cancel6a.c | 191 + liblo/pthreads.2/tests/cancel6d.c | 190 + liblo/pthreads.2/tests/cancel7.c | 216 + liblo/pthreads.2/tests/cancel8.c | 217 + liblo/pthreads.2/tests/cancel9.c | 202 + liblo/pthreads.2/tests/cleanup0.c | 229 + liblo/pthreads.2/tests/cleanup1.c | 242 + liblo/pthreads.2/tests/cleanup2.c | 217 + liblo/pthreads.2/tests/cleanup3.c | 222 + liblo/pthreads.2/tests/condvar1.c | 97 + liblo/pthreads.2/tests/condvar1_1.c | 115 + liblo/pthreads.2/tests/condvar1_2.c | 124 + liblo/pthreads.2/tests/condvar2.c | 125 + liblo/pthreads.2/tests/condvar2_1.c | 153 + liblo/pthreads.2/tests/condvar3.c | 148 + liblo/pthreads.2/tests/condvar3_1.c | 201 + liblo/pthreads.2/tests/condvar3_2.c | 193 + liblo/pthreads.2/tests/condvar3_3.c | 132 + liblo/pthreads.2/tests/condvar4.c | 169 + liblo/pthreads.2/tests/condvar5.c | 168 + liblo/pthreads.2/tests/condvar6.c | 242 + liblo/pthreads.2/tests/condvar7.c | 257 + liblo/pthreads.2/tests/condvar8.c | 258 + liblo/pthreads.2/tests/condvar9.c | 267 + liblo/pthreads.2/tests/context1.c | 144 + liblo/pthreads.2/tests/count1.c | 90 + liblo/pthreads.2/tests/create1.c | 66 + liblo/pthreads.2/tests/create2.c | 108 + liblo/pthreads.2/tests/create3.c | 122 + liblo/pthreads.2/tests/delay1.c | 51 + liblo/pthreads.2/tests/delay2.c | 82 + liblo/pthreads.2/tests/detach1.c | 93 + liblo/pthreads.2/tests/equal1.c | 66 + liblo/pthreads.2/tests/errno1.c | 177 + liblo/pthreads.2/tests/exception1.c | 263 + liblo/pthreads.2/tests/exception2.c | 158 + liblo/pthreads.2/tests/exception3.c | 196 + liblo/pthreads.2/tests/exit1.c | 50 + liblo/pthreads.2/tests/exit2.c | 64 + liblo/pthreads.2/tests/exit3.c | 68 + liblo/pthreads.2/tests/exit4.c | 199 + liblo/pthreads.2/tests/exit5.c | 205 + liblo/pthreads.2/tests/eyal1.c | 367 + liblo/pthreads.2/tests/inherit1.c | 177 + liblo/pthreads.2/tests/join0.c | 67 + liblo/pthreads.2/tests/join1.c | 78 + liblo/pthreads.2/tests/join2.c | 69 + liblo/pthreads.2/tests/join3.c | 75 + liblo/pthreads.2/tests/kill1.c | 83 + liblo/pthreads.2/tests/loadfree.c | 70 + liblo/pthreads.2/tests/multiPCcaBetter.c | 282 + liblo/pthreads.2/tests/mutex1.c | 68 + liblo/pthreads.2/tests/mutex1e.c | 74 + liblo/pthreads.2/tests/mutex1n.c | 74 + liblo/pthreads.2/tests/mutex1r.c | 74 + liblo/pthreads.2/tests/mutex2.c | 66 + liblo/pthreads.2/tests/mutex2e.c | 66 + liblo/pthreads.2/tests/mutex2r.c | 66 + liblo/pthreads.2/tests/mutex3.c | 75 + liblo/pthreads.2/tests/mutex3e.c | 75 + liblo/pthreads.2/tests/mutex3r.c | 75 + liblo/pthreads.2/tests/mutex4.c | 111 + liblo/pthreads.2/tests/mutex5.c | 67 + liblo/pthreads.2/tests/mutex6.c | 93 + liblo/pthreads.2/tests/mutex6e.c | 102 + liblo/pthreads.2/tests/mutex6es.c | 94 + liblo/pthreads.2/tests/mutex6n.c | 104 + liblo/pthreads.2/tests/mutex6r.c | 100 + liblo/pthreads.2/tests/mutex6rs.c | 92 + liblo/pthreads.2/tests/mutex6s.c | 93 + liblo/pthreads.2/tests/mutex7.c | 82 + liblo/pthreads.2/tests/mutex7e.c | 102 + liblo/pthreads.2/tests/mutex7n.c | 93 + liblo/pthreads.2/tests/mutex7r.c | 100 + liblo/pthreads.2/tests/mutex8.c | 82 + liblo/pthreads.2/tests/mutex8e.c | 97 + liblo/pthreads.2/tests/mutex8n.c | 97 + liblo/pthreads.2/tests/mutex8r.c | 97 + liblo/pthreads.2/tests/once1.c | 77 + liblo/pthreads.2/tests/once2.c | 109 + liblo/pthreads.2/tests/once3.c | 132 + liblo/pthreads.2/tests/once4.c | 191 + liblo/pthreads.2/tests/priority1.c | 172 + liblo/pthreads.2/tests/priority2.c | 169 + liblo/pthreads.2/tests/readme | 44 + liblo/pthreads.2/tests/reuse1.c | 124 + liblo/pthreads.2/tests/reuse2.c | 167 + liblo/pthreads.2/tests/rwlock1.c | 61 + liblo/pthreads.2/tests/rwlock2.c | 66 + liblo/pthreads.2/tests/rwlock2_t.c | 78 + liblo/pthreads.2/tests/rwlock3.c | 76 + liblo/pthreads.2/tests/rwlock3_t.c | 87 + liblo/pthreads.2/tests/rwlock4.c | 76 + liblo/pthreads.2/tests/rwlock4_t.c | 87 + liblo/pthreads.2/tests/rwlock5.c | 78 + liblo/pthreads.2/tests/rwlock5_t.c | 89 + liblo/pthreads.2/tests/rwlock6.c | 101 + liblo/pthreads.2/tests/rwlock6_t.c | 126 + liblo/pthreads.2/tests/rwlock6_t2.c | 119 + liblo/pthreads.2/tests/rwlock7.c | 199 + liblo/pthreads.2/tests/rwlock8.c | 205 + liblo/pthreads.2/tests/self1.c | 69 + liblo/pthreads.2/tests/self2.c | 73 + liblo/pthreads.2/tests/semaphore1.c | 161 + liblo/pthreads.2/tests/semaphore2.c | 108 + liblo/pthreads.2/tests/semaphore3.c | 121 + liblo/pthreads.2/tests/semaphore4.c | 138 + liblo/pthreads.2/tests/semaphore4t.c | 132 + liblo/pthreads.2/tests/semaphore5.c | 103 + liblo/pthreads.2/tests/sizes.c | 32 + liblo/pthreads.2/tests/sizes.gc | 21 + liblo/pthreads.2/tests/sizes.gce | 21 + liblo/pthreads.2/tests/sizes.vc | 21 + liblo/pthreads.2/tests/sizes.vse | 21 + liblo/pthreads.2/tests/spin1.c | 59 + liblo/pthreads.2/tests/spin2.c | 75 + liblo/pthreads.2/tests/spin3.c | 72 + liblo/pthreads.2/tests/spin4.c | 103 + liblo/pthreads.2/tests/stress1.c | 278 + liblo/pthreads.2/tests/test.h | 140 + liblo/pthreads.2/tests/tryentercs.c | 103 + liblo/pthreads.2/tests/tryentercs2.c | 92 + liblo/pthreads.2/tests/tsd1.c | 211 + liblo/pthreads.2/tests/tsd2.c | 215 + liblo/pthreads.2/tests/valid1.c | 103 + liblo/pthreads.2/tests/valid2.c | 84 + liblo/pthreads.2/tsd.c | 44 + liblo/pthreads.2/version.rc | 384 + liblo/pthreads.2/version.res | Bin 0 -> 1100 bytes liblo/pthreads.2/w32_CancelableWait.c | 160 + liblo/ser-to-osc/README.txt | 21 + liblo/ser-to-osc/Serial.cpp | 1428 ++ liblo/ser-to-osc/Serial.h | 367 + liblo/ser-to-osc/ser-to-osc.cpp | 245 + liblo/ser-to-osc/ser-to-osc.vcproj | 208 + liblo/src/Makefile.am | 33 + liblo/src/Makefile.in | 842 + liblo/src/address.c | 346 + liblo/src/blob.c | 64 + liblo/src/bundle.c | 181 + liblo/src/liblo.def | 113 + liblo/src/lo_internal.h | 63 + liblo/src/lo_types_internal.h | 139 + liblo/src/message.c | 1081 + liblo/src/method.c | 35 + liblo/src/pattern_match.c | 248 + liblo/src/send.c | 491 + liblo/src/server.c | 1400 ++ liblo/src/server_thread.c | 180 + liblo/src/subtest.c | 96 + liblo/src/testlo.c | 1193 + liblo/src/timetag.c | 58 + liblo/src/tools/Makefile.am | 11 + liblo/src/tools/Makefile.in | 708 + liblo/src/tools/README | 71 + liblo/src/tools/oscdump.c | 85 + liblo/src/tools/oscsend.c | 269 + liblo/test-client/README.txt | 10 + liblo/test-client/osc-test-client.vcproj | 204 + liblo/test-client/test-client.c | 73 + license.txt | 116 + lpc/compile.txt | 101 + lpc/lpc-example.dat | 1 + lpc/lpc-exmpl.dat | 162 + lpc/lpc-orig.lsp | 151 + lpc/lpc.lsp | 178 + lpc/lpcdemo-orig.lsp | 301 + lpc/lpcdemo.lsp | 275 + lpc/prims-ref.txt | 57 + lpc/readme.txt | 28 + lpc/src/allpoles.alg | 70 + lpc/src/lpanal.c | 177 + lpc/src/lpanal.h | 5 + lpc/src/lpreson.alg | 104 + macosxproject/.DS_Store | Bin 0 -> 6148 bytes macosxproject/Nyquist.icns | Bin 0 -> 32994 bytes macosxproject/NyquistIDE-Info.plist | 42 + macosxproject/README.txt | 1 + macosxproject/alternate.icns | Bin 0 -> 78406 bytes macosxproject/nycon2008.gif | Bin 0 -> 4344 bytes macosxproject/nycon2008.png | Bin 0 -> 49506 bytes macosxproject/nycon2008.xcf | Bin 0 -> 14472 bytes macosxproject/nyquist.pbproj/project.pbxproj | 6120 +++++ macosxproject/nyquist.xcodeproj/project.pbxproj | 3137 +++ macproject/NyquistIcon | 1 + macproject/NyquistIcon.sit | Bin 0 -> 1424 bytes macproject/mac_port_changes.txt | 2 + macproject/nyquist.mcp | Bin 0 -> 166747 bytes macproject/nyquist.rsrc | 0 macproject/nyquistdata/CWSettingsMacOS.stg | Bin 0 -> 4580 bytes macproject/packer/packer.mcp | Bin 0 -> 91082 bytes macproject/packer/packerdata/.DS_Store | Bin 0 -> 6148 bytes macproject/unpacker/unpacker.mcp | Bin 0 -> 91082 bytes .../unpacker/unpackerdata/CWSettingsMacOS.stg | Bin 0 -> 3656 bytes .../unpackerdata/unpacker/TargetDataMacOS.tdt | Bin 0 -> 109546 bytes misc/Makefile | 67 + misc/args.h | 65 + misc/cext.h | 7 + misc/cmdline.c | 406 + misc/cmdline.h | 6 + misc/cmu/Projects.zip | Bin 0 -> 5881 bytes misc/cmu/cleanup.bat | 53 + misc/cmu/cmu-linux-install.lsp | 68 + misc/cmu/cmuinstall.bat | 7 + misc/cmu/cmuinstall.sh | 8 + misc/cmu/cmuinstall2.bat | 10 + misc/cmu/cmuinstallmac.sh | 40 + misc/cmu/init.lsp | 190 + misc/cmu/install-plight.sh | 10 + misc/cmu/music.software.html | 189 + misc/cmu/new.html | 189 + misc/cmu/nyqide_setup.sgp | Bin 0 -> 812 bytes misc/cmu/nyquist_setup.sgp | Bin 0 -> 801 bytes misc/cmu/nyqwin_setup.sgp | Bin 0 -> 816 bytes misc/cmu/restore.bat | 17 + misc/convert.c | 59 + misc/convert.h | 7 + misc/filelist.c | 222 + misc/filelist.dsp | 109 + misc/filelist.vcproj | 264 + misc/intgen.c | 911 + misc/intgen2.c | 910 + misc/intgen_win32/intgen.dsp | 113 + misc/intgen_win32/intgen.vcproj | 253 + misc/mac-to-win.lsp | 41 + misc/makefile.lsp | 679 + misc/packer.c | 311 + misc/packer.dsp | 109 + misc/packer.vcproj | 268 + misc/play.c | 90 + misc/plot.c | 249 + misc/sampleprint.c | 39 + misc/sine.c | 73 + misc/stdefs2.h | 50 + misc/transfiles.lsp | 73 + misc/unpacker.c | 328 + misc/unpacker.dsp | 105 + misc/unpacker.vcproj | 263 + nylsf/COPYING | 503 + nylsf/G72x/README.original | 94 + nylsf/G72x/g721.c | 162 + nylsf/G72x/g723_16.c | 169 + nylsf/G72x/g723_24.c | 146 + nylsf/G72x/g723_40.c | 160 + nylsf/G72x/g72x.c | 652 + nylsf/G72x/g72x.h | 99 + nylsf/G72x/g72x_priv.h | 118 + nylsf/G72x/g72x_test.c | 222 + nylsf/GSM610/README | 36 + nylsf/GSM610/add.c | 249 + nylsf/GSM610/code.c | 97 + nylsf/GSM610/decode.c | 69 + nylsf/GSM610/gsm.h | 58 + nylsf/GSM610/gsm610_priv.h | 312 + nylsf/GSM610/gsm_create.c | 44 + nylsf/GSM610/gsm_decode.c | 368 + nylsf/GSM610/gsm_destroy.c | 31 + nylsf/GSM610/gsm_encode.c | 458 + nylsf/GSM610/gsm_option.c | 76 + nylsf/GSM610/long_term.c | 953 + nylsf/GSM610/lpc.c | 343 + nylsf/GSM610/preprocess.c | 117 + nylsf/GSM610/rpe.c | 492 + nylsf/GSM610/short_term.c | 429 + nylsf/GSM610/table.c | 70 + nylsf/README.txt | 20 + nylsf/aiff.c | 1516 ++ nylsf/alaw.c | 544 + nylsf/au.c | 453 + nylsf/avr.c | 254 + nylsf/broadcast.c | 89 + nylsf/caf.c | 538 + nylsf/command.c | 367 + nylsf/common.c | 1290 ++ nylsf/common.h | 773 + nylsf/config.h | 47 + nylsf/dither.c | 535 + nylsf/double64.c | 1008 + nylsf/dwd.c | 210 + nylsf/dwvw.c | 671 + nylsf/file_io.c | 1537 ++ nylsf/flac.c | 1156 + nylsf/float32.c | 961 + nylsf/float_cast.h | 262 + nylsf/g72x.c | 615 + nylsf/gsm610.c | 628 + nylsf/htk.c | 225 + nylsf/ima_adpcm.c | 976 + nylsf/interleave.c | 306 + nylsf/ircam.c | 331 + nylsf/macbinary3.c | 58 + nylsf/macos.c | 63 + nylsf/mat4.c | 394 + nylsf/mat5.c | 507 + nylsf/ms_adpcm.c | 834 + nylsf/nist.c | 367 + nylsf/ogg.c | 44 + nylsf/paf.c | 843 + nylsf/pcm.c | 2899 +++ nylsf/ppc-config.h | 254 + nylsf/pvf.c | 199 + nylsf/raw.c | 111 + nylsf/rx2.c | 326 + nylsf/sd2.c | 613 + nylsf/sds.c | 993 + nylsf/sf_unistd.h | 67 + nylsf/sfconfig.h | 108 + nylsf/sfendian.h | 256 + nylsf/sndfile.c | 2707 +++ nylsf/sndfile.h | 562 + nylsf/strings.c | 204 + nylsf/svx.c | 410 + nylsf/test_endswap.c | 245 + nylsf/test_file_io.c | 448 + nylsf/test_log_printf.c | 138 + nylsf/txw.c | 379 + nylsf/ulaw.c | 1047 + nylsf/voc.c | 878 + nylsf/vox_adpcm.c | 537 + nylsf/w64.c | 578 + nylsf/wav.c | 1633 ++ nylsf/wav_w64.c | 509 + nylsf/wav_w64.h | 286 + nylsf/wve.c | 125 + nylsf/xi.c | 1204 + nyqide/doc/nyqide_plot.gif | Bin 0 -> 22607 bytes nyqide/doc/nyquistide.gif | Bin 0 -> 50583 bytes nyqide/doc/tips.htm | 122 + nyqide/nyqide_src.zip | Bin 0 -> 212904 bytes nyqide/readme-vcl.txt | 8 + nyqsrc/add.c | 917 + nyqsrc/add.h | 44 + nyqsrc/avg.c | 273 + nyqsrc/avg.h | 6 + nyqsrc/compose.c | 304 + nyqsrc/compose.h | 3 + nyqsrc/convolve.c | 329 + nyqsrc/convolve.h | 3 + nyqsrc/cque.h | 25 + nyqsrc/debug.c | 249 + nyqsrc/debug.h | 47 + nyqsrc/downsample.c | 404 + nyqsrc/downsample.h | 3 + nyqsrc/exitpa.h | 3 + nyqsrc/f0.cpp | 139 + nyqsrc/f0.h | 8 + nyqsrc/falloc.c | 272 + nyqsrc/falloc.h | 253 + nyqsrc/ffilterkit.c | 123 + nyqsrc/ffilterkit.h | 15 + nyqsrc/fft-rbd.c | 156 + nyqsrc/fft.c | 223 + nyqsrc/fft.h | 4 + nyqsrc/fftr4.c | 264 + nyqsrc/fftw.h | 412 + nyqsrc/fresample.h | 75 + nyqsrc/fsmallfilter.h | 3079 +++ nyqsrc/handlers.c | 120 + nyqsrc/inverse.c | 214 + nyqsrc/inverse.h | 3 + nyqsrc/local.c | 55 + nyqsrc/localdefs.h | 3 + nyqsrc/localptrs.h | 9 + nyqsrc/lpanal.c | 177 + nyqsrc/lpanal.h | 4 + nyqsrc/multiread.c | 298 + nyqsrc/multiread.h | 3 + nyqsrc/multiseq.c | 673 + nyqsrc/multiseq.h | 19 + nyqsrc/nfilterkit.c | 199 + nyqsrc/nfilterkit.h | 80 + nyqsrc/nyq-osc-server.c | 112 + nyqsrc/nyq-osc-server.h | 9 + nyqsrc/nyx.c | 1294 ++ nyqsrc/nyx.h | 66 + nyqsrc/oldyin.c | 466 + nyqsrc/oldyin.h | 6 + nyqsrc/phasevocoder.c | 102 + nyqsrc/phasevocoder.h | 6 + nyqsrc/probe.c | 38 + nyqsrc/probe.h | 6 + nyqsrc/pvshell.c | 202 + nyqsrc/pvshell.h | 90 + nyqsrc/resamp.c | 348 + nyqsrc/resamp.h | 3 + nyqsrc/resampv.c | 394 + nyqsrc/resampv.h | 3 + nyqsrc/rfftw.h | 98 + nyqsrc/samples.c | 304 + nyqsrc/samples.h | 20 + nyqsrc/seqext.c | 92 + nyqsrc/seqext.h | 14 + nyqsrc/seqfn.cl | 2 + nyqsrc/seqfn.wcl | 2 + nyqsrc/seqfnint.c | 249 + nyqsrc/seqfnint.lsp | 31 + nyqsrc/seqfnintdefs.h | 13 + nyqsrc/seqfnintptrs.h | 13 + nyqsrc/seqinterf.c | 98 + nyqsrc/seqinterf.h | 37 + nyqsrc/sliders.c | 160 + nyqsrc/sliders.h | 11 + nyqsrc/sndfail.c | 23 + nyqsrc/sndfmt.h | 118 + nyqsrc/sndfn.cl | 54 + nyqsrc/sndfn.wcl | 54 + nyqsrc/sndfnint.c | 2232 ++ nyqsrc/sndfnint.lsp | 86 + nyqsrc/sndfnintdefs.h | 127 + nyqsrc/sndfnintptrs.h | 127 + nyqsrc/sndmax.c | 73 + nyqsrc/sndmax.h | 4 + nyqsrc/sndread.c | 297 + nyqsrc/sndread.h | 20 + nyqsrc/sndseq.c | 349 + nyqsrc/sndseq.h | 3 + nyqsrc/sndsliders.h | 5 + nyqsrc/sndwrite.c | 640 + nyqsrc/sndwrite.h | 12 + nyqsrc/sndwritepa.c | 818 + nyqsrc/sound.c | 1709 ++ nyqsrc/sound.h | 533 + nyqsrc/stats.c | 27 + nyqsrc/stdefs.h | 49 + nyqsrc/trigger.c | 326 + nyqsrc/trigger.h | 3 + nyqsrc/yin.c | 579 + nyqsrc/yin.h | 6 + nyqstk/globals.h | 8 + nyqstk/include/ADSR.h | 90 + nyqstk/include/BandedWG.h | 121 + nyqstk/include/BiQuad.h | 117 + nyqstk/include/BowTable.h | 56 + nyqstk/include/Bowed.h | 91 + nyqstk/include/Chorus.h | 56 + nyqstk/include/Clarinet.h | 91 + nyqstk/include/Delay.h | 115 + nyqstk/include/DelayA.h | 79 + nyqstk/include/DelayL.h | 78 + nyqstk/include/Effect.h | 74 + nyqstk/include/Envelope.h | 73 + nyqstk/include/FileRead.h | 129 + nyqstk/include/FileWvIn.h | 148 + nyqstk/include/Filter.h | 127 + nyqstk/include/Flute.h | 108 + nyqstk/include/Function.h | 59 + nyqstk/include/Generator.h | 58 + nyqstk/include/Instrmnt.h | 75 + nyqstk/include/JCRev.h | 57 + nyqstk/include/JetTable.h | 41 + nyqstk/include/Mandolin.h | 75 + nyqstk/include/Modal.h | 96 + nyqstk/include/ModalBar.h | 66 + nyqstk/include/NRev.h | 58 + nyqstk/include/Noise.h | 53 + nyqstk/include/OnePole.h | 84 + nyqstk/include/OneZero.h | 84 + nyqstk/include/PRCRev.h | 55 + nyqstk/include/PitShift.h | 52 + nyqstk/include/PluckTwo.h | 90 + nyqstk/include/PoleZero.h | 91 + nyqstk/include/ReedTabl.h | 70 + nyqstk/include/ReedTable.h | 64 + nyqstk/include/SKINI.msg | 127 + nyqstk/include/Saxofony.h | 108 + nyqstk/include/SineWave.h | 90 + nyqstk/include/Sitar.h | 75 + nyqstk/include/Stk.h | 369 + nyqstk/include/WaveLoop.h | 97 + nyqstk/include/WvIn.h | 92 + nyqstk/instr.cpp | 104 + nyqstk/instr.h | 54 + nyqstk/src/ADSR.cpp | 191 + nyqstk/src/BandedWG.cpp | 380 + nyqstk/src/BiQuad.cpp | 126 + nyqstk/src/BowTable.cpp | 53 + nyqstk/src/Bowed.cpp | 189 + nyqstk/src/Chorus.cpp | 63 + nyqstk/src/Clarinet.cpp | 162 + nyqstk/src/Delay.cpp | 197 + nyqstk/src/DelayA.cpp | 145 + nyqstk/src/DelayL.cpp | 132 + nyqstk/src/Effect.cpp | 98 + nyqstk/src/Envelope.cpp | 125 + nyqstk/src/FileRead.cpp | 727 + nyqstk/src/FileWvIn.cpp | 213 + nyqstk/src/Filter.cpp | 236 + nyqstk/src/Flute.cpp | 201 + nyqstk/src/Function.cpp | 57 + nyqstk/src/Generator.cpp | 56 + nyqstk/src/Instrmnt.cpp | 83 + nyqstk/src/JCRev.cpp | 125 + nyqstk/src/JetTable.cpp | 41 + nyqstk/src/Mandolin.cpp | 188 + nyqstk/src/Modal.cpp | 210 + nyqstk/src/ModalBar.cpp | 198 + nyqstk/src/NRev.cpp | 117 + nyqstk/src/Noise.cpp | 51 + nyqstk/src/OnePole.cpp | 99 + nyqstk/src/OneZero.cpp | 98 + nyqstk/src/PRCRev.cpp | 100 + nyqstk/src/PitShift.cpp | 90 + nyqstk/src/PluckTwo.cpp | 132 + nyqstk/src/PoleZero.cpp | 97 + nyqstk/src/ReedTabl.cpp | 71 + nyqstk/src/ReedTable.cpp | 59 + nyqstk/src/Saxofony.cpp | 198 + nyqstk/src/SineWave.cpp | 105 + nyqstk/src/Sitar.cpp | 117 + nyqstk/src/Stk.cpp | 314 + nyqstk/src/WaveLoop.cpp | 190 + nyqstk/src/WvIn.cpp | 118 + nyqstk/stkinit.cpp | 50 + nyqstk/stkinit.h | 11 + nyqstk/stkint.cpp | 80 + nyqstk/stkint.h | 22 + nyquist.dsp | 1335 ++ nyquist.dsw | 101 + nyquist.sln | 177 + nyquist.vcproj | 4983 +++++ nyqwin.dsp | 1310 ++ nyqwin.vcproj | 4975 +++++ portaudio/COMPILING.DARWIN | 1 + portaudio/Doxyfile | 239 + portaudio/LICENSE.txt | 81 + portaudio/Makefile.in | 212 + portaudio/README.txt | 96 + portaudio/SConstruct | 194 + portaudio/V19-devel-readme.txt | 129 + portaudio/aclocal.m4 | 57 + portaudio/bindings/cpp/AUTHORS | 0 portaudio/bindings/cpp/COPYING | 31 + portaudio/bindings/cpp/ChangeLog | 178 + portaudio/bindings/cpp/INSTALL | 236 + portaudio/bindings/cpp/Makefile.am | 7 + portaudio/bindings/cpp/Makefile.in | 642 + portaudio/bindings/cpp/NEWS | 0 portaudio/bindings/cpp/README | 0 portaudio/bindings/cpp/SConscript | 64 + portaudio/bindings/cpp/aclocal.m4 | 7336 ++++++ portaudio/bindings/cpp/bin/Makefile.am | 9 + portaudio/bindings/cpp/bin/Makefile.in | 470 + portaudio/bindings/cpp/build/gnu/Makefile.in | 106 + portaudio/bindings/cpp/build/gnu/OUT_OF_DATE | 0 portaudio/bindings/cpp/build/gnu/aclocal.m4 | 57 + portaudio/bindings/cpp/build/gnu/config.guess | 1308 ++ portaudio/bindings/cpp/build/gnu/config.sub | 1505 ++ portaudio/bindings/cpp/build/gnu/configure | 4297 ++++ portaudio/bindings/cpp/build/gnu/configure.ac | 214 + portaudio/bindings/cpp/build/gnu/install-sh | 251 + portaudio/bindings/cpp/build/vc6/devs_example.dsp | 248 + portaudio/bindings/cpp/build/vc6/devs_example.dsw | 44 + portaudio/bindings/cpp/build/vc6/sine_example.dsp | 252 + portaudio/bindings/cpp/build/vc6/sine_example.dsw | 44 + .../bindings/cpp/build/vc6/static_library.dsp | 395 + .../bindings/cpp/build/vc6/static_library.dsw | 29 + portaudio/bindings/cpp/build/vc7/OUT_OF_DATE | 0 .../bindings/cpp/build/vc7_1/devs_example.sln | 30 + .../bindings/cpp/build/vc7_1/devs_example.vcproj | 195 + .../bindings/cpp/build/vc7_1/sine_example.sln | 30 + .../bindings/cpp/build/vc7_1/sine_example.vcproj | 327 + .../bindings/cpp/build/vc7_1/static_library.sln | 21 + .../bindings/cpp/build/vc7_1/static_library.vcproj | 218 + portaudio/bindings/cpp/configure | 21505 ++++++++++++++++++ portaudio/bindings/cpp/configure.ac | 54 + portaudio/bindings/cpp/doc/Makefile.am | 5 + portaudio/bindings/cpp/doc/Makefile.in | 326 + portaudio/bindings/cpp/doc/README | 34 + portaudio/bindings/cpp/doc/config.doxy | 211 + portaudio/bindings/cpp/doc/config.doxy.linux | 210 + portaudio/bindings/cpp/example/devs.cxx | 177 + portaudio/bindings/cpp/example/sine.cxx | 137 + portaudio/bindings/cpp/include/Makefile.am | 22 + portaudio/bindings/cpp/include/Makefile.in | 423 + .../cpp/include/portaudiocpp/AsioDeviceAdapter.hxx | 44 + .../cpp/include/portaudiocpp/AutoSystem.hxx | 62 + .../cpp/include/portaudiocpp/BlockingStream.hxx | 45 + .../include/portaudiocpp/CFunCallbackStream.hxx | 49 + .../cpp/include/portaudiocpp/CallbackInterface.hxx | 45 + .../cpp/include/portaudiocpp/CallbackStream.hxx | 40 + .../include/portaudiocpp/CppFunCallbackStream.hxx | 86 + .../bindings/cpp/include/portaudiocpp/Device.hxx | 91 + .../DirectionSpecificStreamParameters.hxx | 77 + .../cpp/include/portaudiocpp/Exception.hxx | 108 + .../bindings/cpp/include/portaudiocpp/HostApi.hxx | 76 + .../portaudiocpp/InterfaceCallbackStream.hxx | 49 + .../include/portaudiocpp/MemFunCallbackStream.hxx | 107 + .../cpp/include/portaudiocpp/PortAudioCpp.hxx | 109 + .../cpp/include/portaudiocpp/SampleDataFormat.hxx | 35 + .../bindings/cpp/include/portaudiocpp/Stream.hxx | 82 + .../cpp/include/portaudiocpp/StreamParameters.hxx | 77 + .../bindings/cpp/include/portaudiocpp/System.hxx | 107 + .../include/portaudiocpp/SystemDeviceIterator.hxx | 66 + .../include/portaudiocpp/SystemHostApiIterator.hxx | 61 + portaudio/bindings/cpp/lib/Makefile.am | 26 + portaudio/bindings/cpp/lib/Makefile.in | 615 + portaudio/bindings/cpp/portaudiocpp.pc.in | 12 + .../cpp/source/portaudiocpp/AsioDeviceAdapter.cxx | 83 + .../cpp/source/portaudiocpp/BlockingStream.cxx | 100 + .../cpp/source/portaudiocpp/CFunCallbackStream.cxx | 41 + .../cpp/source/portaudiocpp/CallbackInterface.cxx | 25 + .../cpp/source/portaudiocpp/CallbackStream.cxx | 20 + .../source/portaudiocpp/CppFunCallbackStream.cxx | 81 + .../bindings/cpp/source/portaudiocpp/Device.cxx | 168 + .../DirectionSpecificStreamParameters.cxx | 163 + .../bindings/cpp/source/portaudiocpp/Exception.cxx | 123 + .../bindings/cpp/source/portaudiocpp/HostApi.cxx | 121 + .../portaudiocpp/InterfaceCallbackStream.cxx | 45 + .../source/portaudiocpp/MemFunCallbackStream.cxx | 4 + .../bindings/cpp/source/portaudiocpp/Stream.cxx | 195 + .../cpp/source/portaudiocpp/StreamParameters.cxx | 165 + .../bindings/cpp/source/portaudiocpp/System.cxx | 308 + .../source/portaudiocpp/SystemDeviceIterator.cxx | 60 + .../source/portaudiocpp/SystemHostApiIterator.cxx | 59 + portaudio/build/dev-cpp/Makefile-dll | 78 + portaudio/build/dev-cpp/Makefile-static | 75 + portaudio/build/dev-cpp/portaudio-dll.dev | 209 + portaudio/build/dev-cpp/portaudio-static.dev | 209 + portaudio/build/dev-cpp/readme.txt | 23 + portaudio/build/msvc/portaudio.def | 43 + portaudio/build/msvc/portaudio.dsp | 265 + portaudio/build/msvc/portaudio.dsw | 29 + portaudio/build/msvc/portaudio.sln | 26 + portaudio/build/msvc/portaudio.vcproj | 1471 ++ portaudio/build/msvc/readme.txt | 80 + portaudio/build/scons/SConscript_common | 28 + portaudio/build/scons/SConscript_opts | 92 + portaudio/config.cache | 26 + portaudio/config.doxy | 185 + portaudio/config.guess | 1388 ++ portaudio/config.sub | 1489 ++ portaudio/configure | 22294 +++++++++++++++++++ portaudio/configure.in | 320 + portaudio/depcomp | 530 + portaudio/doc/src/license.dox | 38 + portaudio/doc/src/mainpage.dox | 44 + portaudio/doc/src/srcguide.dox | 38 + portaudio/doc/utils/checkfiledocs.py | 76 + portaudio/fixdir.bat | 19 + portaudio/fixfile.bat | 7 + portaudio/include/pa_asio.h | 129 + portaudio/include/pa_jack.h | 75 + portaudio/include/pa_linux_alsa.h | 93 + portaudio/include/pa_mac_core.h | 171 + portaudio/include/pa_win_ds.h | 100 + portaudio/include/pa_win_waveformat.h | 180 + portaudio/include/pa_win_wmme.h | 176 + portaudio/include/portaudio.h | 1133 + portaudio/index.html | 105 + portaudio/install-sh | 251 + portaudio/ltmain.sh | 6971 ++++++ portaudio/missing | 360 + portaudio/pablio/README.txt | 45 + portaudio/pablio/pablio.c | 314 + portaudio/pablio/pablio.def | 35 + portaudio/pablio/pablio.h | 116 + portaudio/pablio/test_rw.c | 105 + portaudio/pablio/test_rw_echo.c | 129 + portaudio/pablio/test_w_saw.c | 114 + portaudio/pablio/test_w_saw8.c | 112 + portaudio/portaudio-2.0.pc.in | 12 + portaudio/src/SConscript | 211 + portaudio/src/common/pa_allocation.c | 243 + portaudio/src/common/pa_allocation.h | 104 + portaudio/src/common/pa_converters.c | 1935 ++ portaudio/src/common/pa_converters.h | 263 + portaudio/src/common/pa_cpuload.c | 105 + portaudio/src/common/pa_cpuload.h | 72 + portaudio/src/common/pa_debugprint.c | 107 + portaudio/src/common/pa_debugprint.h | 149 + portaudio/src/common/pa_dither.c | 213 + portaudio/src/common/pa_dither.h | 100 + portaudio/src/common/pa_endianness.h | 141 + portaudio/src/common/pa_front.c | 1760 ++ portaudio/src/common/pa_hostapi.h | 253 + portaudio/src/common/pa_process.c | 1772 ++ portaudio/src/common/pa_process.h | 750 + portaudio/src/common/pa_ringbuffer.c | 285 + portaudio/src/common/pa_ringbuffer.h | 198 + portaudio/src/common/pa_skeleton.c | 816 + portaudio/src/common/pa_stream.c | 150 + portaudio/src/common/pa_stream.h | 205 + portaudio/src/common/pa_trace.c | 97 + portaudio/src/common/pa_trace.h | 79 + portaudio/src/common/pa_types.h | 107 + portaudio/src/common/pa_util.h | 159 + portaudio/src/hostapi/alsa/pa_linux_alsa.c | 3563 +++ portaudio/src/hostapi/asihpi/pa_linux_asihpi.c | 2910 +++ portaudio/src/hostapi/asio/ASIO-README.txt | 137 + .../src/hostapi/asio/Callback_adaptation_.pdf | Bin 0 -> 50527 bytes portaudio/src/hostapi/asio/Pa_ASIO.pdf | Bin 0 -> 50778 bytes .../src/hostapi/asio/iasiothiscallresolver.cpp | 563 + portaudio/src/hostapi/asio/iasiothiscallresolver.h | 197 + portaudio/src/hostapi/asio/pa_asio.cpp | 3023 +++ portaudio/src/hostapi/coreaudio/notes.txt | 196 + portaudio/src/hostapi/coreaudio/pa_mac_core.c | 2327 ++ .../src/hostapi/coreaudio/pa_mac_core_blocking.c | 585 + .../src/hostapi/coreaudio/pa_mac_core_blocking.h | 136 + .../src/hostapi/coreaudio/pa_mac_core_internal.h | 164 + portaudio/src/hostapi/coreaudio/pa_mac_core_old.c | 913 + .../src/hostapi/coreaudio/pa_mac_core_utilities.c | 620 + .../src/hostapi/coreaudio/pa_mac_core_utilities.h | 205 + portaudio/src/hostapi/dsound/pa_win_ds.c | 2510 +++ portaudio/src/hostapi/dsound/pa_win_ds_dynlink.c | 180 + portaudio/src/hostapi/dsound/pa_win_ds_dynlink.h | 95 + portaudio/src/hostapi/jack/pa_jack.c | 1761 ++ portaudio/src/hostapi/oss/low_latency_tip.txt | Bin 0 -> 3111 bytes portaudio/src/hostapi/oss/pa_unix_oss.c | 1955 ++ portaudio/src/hostapi/oss/recplay.c | 114 + portaudio/src/hostapi/wasapi/pa_win_wasapi.cpp | 1911 ++ portaudio/src/hostapi/wdmks/pa_win_wdmks.c | 3283 +++ portaudio/src/hostapi/wdmks/readme.txt | 82 + portaudio/src/hostapi/wmme/pa_win_wmme.c | 3900 ++++ portaudio/src/os/mac_osx/pa_mac_hostapis.c | 87 + portaudio/src/os/unix/pa_unix_hostapis.c | 78 + portaudio/src/os/unix/pa_unix_util.c | 666 + portaudio/src/os/unix/pa_unix_util.h | 224 + portaudio/src/os/win/pa_win_hostapis.c | 100 + portaudio/src/os/win/pa_win_util.c | 147 + portaudio/src/os/win/pa_win_waveformat.c | 159 + portaudio/src/os/win/pa_win_wdmks_utils.c | 260 + portaudio/src/os/win/pa_win_wdmks_utils.h | 65 + portaudio/src/os/win/pa_x86_plain_converters.c | 1219 + portaudio/src/os/win/pa_x86_plain_converters.h | 60 + portaudio/test/README.txt | 60 + portaudio/test/debug_convert.c | 138 + portaudio/test/debug_dither_calc.c | 62 + portaudio/test/debug_dual.c | 190 + portaudio/test/debug_multi_in.c | 186 + portaudio/test/debug_multi_out.c | 151 + portaudio/test/debug_record.c | 346 + portaudio/test/debug_record_reuse.c | 358 + portaudio/test/debug_sine.c | 199 + portaudio/test/debug_sine_amp.c | 164 + portaudio/test/debug_sine_formats.c | 209 + portaudio/test/debug_srate.c | 272 + portaudio/test/debug_test1.c | 114 + portaudio/test/pa_devs.c | 238 + portaudio/test/pa_fuzz.c | 176 + portaudio/test/pa_minlat.c | 194 + portaudio/test/paqa_devs.c | 355 + portaudio/test/paqa_errs.c | 387 + portaudio/test/patest1.c | 200 + portaudio/test/patest_buffer.c | 200 + portaudio/test/patest_callbackstop.c | 248 + portaudio/test/patest_clip.c | 186 + portaudio/test/patest_dither.c | 186 + portaudio/test/patest_dsound_surround.c | 205 + portaudio/test/patest_hang.c | 160 + portaudio/test/patest_in_overflow.c | 232 + portaudio/test/patest_latency.c | 189 + portaudio/test/patest_leftright.c | 181 + portaudio/test/patest_longsine.c | 147 + portaudio/test/patest_many.c | 206 + portaudio/test/patest_maxsines.c | 212 + portaudio/test/patest_mono.c | 155 + portaudio/test/patest_mono_asio_channel_select.c | 166 + portaudio/test/patest_multi_sine.c | 201 + portaudio/test/patest_out_underflow.c | 225 + portaudio/test/patest_pink.c | 276 + portaudio/test/patest_prime.c | 230 + portaudio/test/patest_read_record.c | 236 + portaudio/test/patest_read_write_wire.c | 215 + portaudio/test/patest_record.c | 344 + portaudio/test/patest_ringmix.c | 86 + portaudio/test/patest_saw.c | 133 + portaudio/test/patest_sine.c | 172 + portaudio/test/patest_sine8.c | 221 + portaudio/test/patest_sine_channelmaps.c | 184 + portaudio/test/patest_sine_formats.c | 203 + portaudio/test/patest_sine_time.c | 215 + portaudio/test/patest_start_stop.c | 168 + portaudio/test/patest_stop.c | 320 + portaudio/test/patest_stop_playout.c | 439 + portaudio/test/patest_sync.c | 267 + portaudio/test/patest_timing.c | 173 + portaudio/test/patest_toomanysines.c | 181 + portaudio/test/patest_two_rates.c | 178 + portaudio/test/patest_underflow.c | 158 + portaudio/test/patest_wire.c | 292 + portaudio/test/patest_wmme_surround.c | 206 + portaudio/test/patest_write_sine.c | 155 + portaudio/test/patest_write_stop.c | 165 + portaudio/testcvs/changeme.txt | 8 + portaudio_test/portaudio_test.dsp | 181 + portaudio_test/syncwrite.c | 128 + release.bat | 36 + releasenyqide.bat | 45 + releasenyqwin.bat | 37 + runtime/dspprims.lsp | 578 + runtime/envelopes.lsp | 163 + runtime/equalizer.lsp | 75 + runtime/evalenv.lsp | 36 + runtime/fileio.lsp | 315 + runtime/follow.lsp | 70 + runtime/init.lsp | 8 + runtime/misc.lsp | 191 + runtime/nyinit.lsp | 38 + runtime/nyqmisc.lsp | 27 + runtime/nyquist-plot.txt | 3 + runtime/nyquist.lsp | 1725 ++ runtime/printrec.lsp | 30 + runtime/profile.lsp | 27 + runtime/rawwaves/mand1.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand10.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand11.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand12.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand2.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand3.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand4.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand5.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand6.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand7.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand8.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mand9.raw | Bin 0 -> 2048 bytes runtime/rawwaves/mandpluk.raw | Bin 0 -> 8900 bytes runtime/rawwaves/marmstk1.raw | Bin 0 -> 512 bytes runtime/rawwaves/sinewave.raw | Bin 0 -> 2048 bytes runtime/sal-parse.lsp | 1827 ++ runtime/sal.lsp | 584 + runtime/seq.lsp | 252 + runtime/seqfnint.lsp | 31 + runtime/seqmidi.lsp | 159 + runtime/sndfnint.lsp | 86 + runtime/stk.lsp | 189 + runtime/test.lsp | 43 + runtime/upic.sal | 53 + runtime/xlinit.lsp | 67 + runtime/xm.lsp | 2349 ++ snd/audio.c | 50 + snd/audiolinux.c | 217 + snd/audiomac.c | 534 + snd/audiomac.h | 41 + snd/audionone.c | 52 + snd/audiooss.c | 199 + snd/audiopa.c | 52 + snd/audiors6k.c | 54 + snd/audiosgi.c | 47 + snd/audiowin32.c | 901 + snd/audiowin32.h | 46 + snd/convert.c | 247 + snd/ieeecvt.c | 183 + snd/ieeecvt.h | 2 + snd/rs6kplaydemo.c | 100 + snd/snd.c | 483 + snd/snd.h | 363 + snd/snd.htm | 55 + snd/snd.txt | 275 + snd/sndconfig.h | 83 + snd/sndcvt.c | 2 + snd/sndfaillinux.c | 13 + snd/sndfailwin32.c | 20 + snd/sndfileio.h | 16 + snd/sndfreebsd.h | 15 + snd/sndhead.h | 60 + snd/sndheader.c | 614 + snd/sndheader.h | 5 + snd/sndio.c | 48 + snd/sndlinux.c | 102 + snd/sndlinux.h | 19 + snd/sndmac.c | 95 + snd/sndmac.h | 13 + snd/sndnt.h | 43 + snd/sndrs6k.h | 40 + snd/sndsystem.c | 42 + snd/sndsystem.h | 67 + snd/sndsystemmac.h | 1 + snd/sndwin32.c | 74 + snd/sndwin32.h | 16 + snd/sndwrite.h | 15 + snd/wxsnd.cpp | 101 + snd/wxsnd.h | 47 + sys/mac/MacAE.c | 58 + sys/mac/MacCommandWin.c | 764 + sys/mac/MacCommandWin.h | 17 + sys/mac/MacDrag.h | 3 + sys/mac/MacFileUtils.c | 81 + sys/mac/MacFileUtils.h | 3 + sys/mac/MacGlobals.h | 50 + sys/mac/MacHandleEv.c | 64 + sys/mac/MacHandleEv.h | 3 + sys/mac/README.txt | 55 + sys/mac/macaboutbox.c | 123 + sys/mac/macaboutbox.h | 3 + sys/mac/macdrag.c | 161 + sys/mac/macfun.c | 222 + sys/mac/macint.c | 521 + sys/mac/macint.h | 166 + sys/mac/macptrs.h | 52 + sys/mac/macstuff.c | 226 + sys/mac/macstuff.h | 7 + sys/mac/sndsystem.h | 2 + sys/mac/switches.h | 58 + sys/mac/system.lsp | 107 + sys/mac/xlextstart.c | 1 + sys/unix/README.txt | 138 + sys/unix/alsa/Makefile | 1178 + sys/unix/alsa/system.lsp | 101 + sys/unix/cmu/backup.script | 1 + sys/unix/cmu/tar.script | 14 + sys/unix/cmu/update.lsp | 79 + sys/unix/io.c | 162 + sys/unix/io.h | 9 + sys/unix/next/Makefile | 521 + sys/unix/next/system.lsp | 37 + sys/unix/nonalsa/Makefile | 1178 + sys/unix/nonalsa/system.lsp | 101 + sys/unix/osstuff.c | 804 + sys/unix/osx/run | 5 + sys/unix/osx/system.lsp | 69 + sys/unix/pl | 2 + sys/unix/pmax/Makefile | 520 + sys/unix/pmax/system.lsp | 37 + sys/unix/rs6k/Makefile | 529 + sys/unix/rs6k/plotscript | 3 + sys/unix/rs6k/system.lsp | 80 + sys/unix/setup | 10 + sys/unix/sgi/Makefile | 521 + sys/unix/sgi/system.lsp | 46 + sys/unix/sndsystem.h | 41 + sys/unix/sparc/Makefile | 520 + sys/unix/sparc/system.lsp | 33 + sys/unix/switches.h | 197 + sys/unix/term.c | 133 + sys/unix/term.h | 6 + sys/unix/termtest.c | 28 + sys/win/README.txt | 143 + sys/win/msvc/sndsystem.h | 1 + sys/win/msvc/stdint.h | 240 + sys/win/msvc/switches.h | 175 + sys/win/msvc/system.lsp | 131 + sys/win/msvc/winfun.c | 276 + sys/win/msvc/winfun.h | 11 + sys/win/msvc/winstuff.c | 398 + sys/win/nyqrelide.iss | 44 + sys/win/wingui/button.h | 2 + sys/win/wingui/cppext.h | 39 + sys/win/wingui/longque.cpp | 34 + sys/win/wingui/longque.h | 28 + sys/win/wingui/nycon.ico | Bin 0 -> 766 bytes sys/win/wingui/resource.h | 21 + sys/win/wingui/slider.h | 6 + sys/win/wingui/textio.cpp | 244 + sys/win/wingui/textio.h | 36 + sys/win/wingui/typein.h | 8 + sys/win/wingui/winguistuff.c | 344 + sys/win/wingui/winmain.aps | Bin 0 -> 3344 bytes sys/win/wingui/winmain.cpp | 657 + sys/win/wingui/winmain.h | 28 + sys/win/wingui/winmain.rc | 120 + sys/win/wingui/winmain2.h | 41 + sys/win/wingui/xlextstart.c | 1 + sys/win/wingui/xlispfns.c | 11 + sys/win/wingui/xlispfns.h | 9 + test/alex.lsp | 292 + test/alpass.lsp | 88 + test/arraystream.lsp | 0 test/articulator1.txt | 275 + test/audio.lsp | 9 + test/cnvl.lsp | 18 + test/comb.lsp | 75 + test/convolve.lsp | 31 + test/delaytest.lsp | 12 + test/envtest.lsp | 15 + test/eq.lsp | 33 + test/fft.lsp | 211 + test/fmfb-test.lsp | 14 + test/fmfbv-test.lsp | 19 + test/gab.lsp | 951 + test/gatetest.lsp | 24 + test/gr.lsp | 35 + test/ifft.lsp | 142 + test/ifftnt.lsp | 90 + test/init.lsp | 24 + test/linux-segfault.lsp | 40 + test/midi2.lsp | 94 + test/ms2.lsp | 7 + test/multiseq.lsp | 88 + test/natbug.lsp | 112 + test/nonewline.lsp | 3 + test/overwrite.lsp | 118 + test/product.lsp | 30 + test/rbd.lsp | 23 + test/readme | 3 + test/s-add-to.lsp | 19 + test/save-float.lsp | 19 + test/seqmiditest.lsp | 0 test/shape.lsp | 29 + test/snd-fetch-array.lsp | 19 + test/sr.lsp | 17 + test/stktest.lsp | 101 + test/str.lsp | 25 + test/temp.gio | 19 + test/temp2.gio | 19 + test/temp3.gio | 0 test/test.gio | 3 + test/tp.lsp | 71 + test/trigger.lsp | 13 + test/variable-resample.lsp | 9 + test/warp.lsp | 12 + todo.txt | 338 + tran/abs.alg | 9 + tran/abs.c | 198 + tran/abs.h | 3 + tran/allpoles.alg | 70 + tran/allpoles.c | 264 + tran/allpoles.h | 3 + tran/alpass.alg | 22 + tran/alpass.c | 193 + tran/alpass.h | 3 + tran/alpasscv.alg | 21 + tran/alpasscv.c | 302 + tran/alpasscv.h | 3 + tran/alpassvc.alg | 59 + tran/alpassvc.c | 374 + tran/alpassvc.h | 3 + tran/alpassvv.alg | 59 + tran/alpassvv.c | 645 + tran/alpassvv.h | 3 + tran/amosc.alg | 33 + tran/amosc.c | 227 + tran/amosc.h | 3 + tran/areson.alg | 24 + tran/areson.c | 237 + tran/areson.h | 3 + tran/aresoncv.alg | 36 + tran/aresoncv.c | 554 + tran/aresoncv.h | 3 + tran/aresonvc.alg | 34 + tran/aresonvc.c | 586 + tran/aresonvc.h | 3 + tran/aresonvv.alg | 50 + tran/aresonvv.c | 1729 ++ tran/aresonvv.h | 3 + tran/atone.alg | 20 + tran/atone.c | 317 + tran/atone.h | 3 + tran/atonev.alg | 25 + tran/atonev.c | 526 + tran/atonev.h | 3 + tran/biquadfilt.alg | 28 + tran/biquadfilt.c | 343 + tran/biquadfilt.h | 3 + tran/buzz.alg | 54 + tran/buzz.c | 536 + tran/buzz.h | 3 + tran/chase.alg | 19 + tran/chase.c | 333 + tran/chase.h | 3 + tran/clip.alg | 9 + tran/clip.c | 301 + tran/clip.h | 3 + tran/congen.alg | 17 + tran/congen.c | 185 + tran/congen.h | 3 + tran/const.alg | 11 + tran/const.c | 109 + tran/const.h | 3 + tran/convolve.alg | 63 + tran/coterm.alg | 11 + tran/coterm.c | 238 + tran/coterm.h | 3 + tran/delay.alg | 20 + tran/delaycc.alg | 20 + tran/delaycc.c | 191 + tran/delaycc.h | 3 + tran/delaycv.alg | 19 + tran/delaycv.c | 300 + tran/delaycv.h | 3 + tran/downproto.alg | 18 + tran/eqbandv.alg | 56 + tran/eqbandvvv.alg | 64 + tran/eqbandvvv.c | 868 + tran/eqbandvvv.h | 3 + tran/exp.alg | 9 + tran/exp.c | 198 + tran/exp.h | 3 + tran/exprel.alg | 50 + tran/fmfb.alg | 26 + tran/fmfb.c | 139 + tran/fmfb.h | 4 + tran/fmfbv.alg | 30 + tran/fmfbv.c | 606 + tran/fmfbv.h | 4 + tran/fmosc.alg | 39 + tran/fmosc.c | 494 + tran/fmosc.h | 3 + tran/follow.alg | 106 + tran/follow.c | 286 + tran/follow.h | 3 + tran/fromarraystream.alg | 82 + tran/fromarraystream.c | 170 + tran/fromarraystream.h | 3 + tran/fromobject.alg | 37 + tran/fromobject.c | 134 + tran/fromobject.h | 3 + tran/gate.alg | 166 + tran/gate.c | 353 + tran/gate.h | 3 + tran/ifft-old.alg | 92 + tran/ifft.alg | 182 + tran/ifft.c | 286 + tran/ifft.h | 3 + tran/init.lsp | 24 + tran/innerloop.lsp | 311 + tran/instrbanded.alg | 24 + tran/instrbanded.c | 181 + tran/instrbanded.h | 5 + tran/instrbow.alg | 25 + tran/instrbow.c | 181 + tran/instrbow.h | 5 + tran/instrbowedfreq.alg | 28 + tran/instrbowedfreq.c | 298 + tran/instrbowedfreq.h | 5 + tran/instrclar.alg | 25 + tran/instrclar.c | 181 + tran/instrclar.h | 5 + tran/instrclarall.alg | 44 + tran/instrclarall.c | 281 + tran/instrclarall.h | 5 + tran/instrclarfreq.alg | 29 + tran/instrclarfreq.c | 298 + tran/instrclarfreq.h | 5 + tran/instrflute.alg | 25 + tran/instrflute.c | 181 + tran/instrflute.h | 5 + tran/instrfluteall.alg | 43 + tran/instrfluteall.c | 281 + tran/instrfluteall.h | 5 + tran/instrflutefreq.alg | 28 + tran/instrflutefreq.c | 298 + tran/instrflutefreq.h | 5 + tran/instrmandolin.alg | 25 + tran/instrmandolin.c | 121 + tran/instrmandolin.h | 5 + tran/instrmodalbar.alg | 19 + tran/instrmodalbar.c | 119 + tran/instrmodalbar.h | 3 + tran/instrsax.alg | 24 + tran/instrsax.c | 249 + tran/instrsax.h | 5 + tran/instrsaxall.alg | 38 + tran/instrsaxall.c | 345 + tran/instrsaxall.h | 5 + tran/instrsaxfreq.alg | 27 + tran/instrsaxfreq.c | 446 + tran/instrsaxfreq.h | 5 + tran/instrsitar.alg | 17 + tran/instrsitar.c | 118 + tran/instrsitar.h | 3 + tran/integrate.alg | 12 + tran/integrate.c | 211 + tran/integrate.h | 3 + tran/log.alg | 9 + tran/log.c | 198 + tran/log.h | 3 + tran/lpreson.alg | 109 + tran/lpreson.c | 313 + tran/lpreson.h | 3 + tran/maxv.alg | 11 + tran/maxv.c | 235 + tran/maxv.h | 3 + tran/offset.alg | 11 + tran/offset.c | 299 + tran/offset.h | 3 + tran/oneshot.alg | 16 + tran/oneshot.c | 319 + tran/oneshot.h | 3 + tran/osc.alg | 31 + tran/osc.c | 133 + tran/osc.h | 3 + tran/partial.alg | 20 + tran/partial.c | 314 + tran/partial.h | 3 + tran/pluck.alg | 144 + tran/pluck.c | 256 + tran/pluck.h | 3 + tran/prod.alg | 11 + tran/prod.c | 244 + tran/prod.h | 3 + tran/pwl.alg | 82 + tran/pwl.c | 180 + tran/pwl.h | 3 + tran/quantize.alg | 11 + tran/quantize.c | 202 + tran/quantize.h | 3 + tran/recip.alg | 11 + tran/recip.c | 202 + tran/recip.h | 3 + tran/reson.alg | 23 + tran/reson.c | 339 + tran/reson.h | 3 + tran/resoncv.alg | 35 + tran/resoncv.c | 600 + tran/resoncv.h | 3 + tran/resonvc.alg | 33 + tran/resonvc.c | 588 + tran/resonvc.h | 3 + tran/resonvv.alg | 47 + tran/resonvv.c | 3251 +++ tran/resonvv.h | 3 + tran/sampler.alg | 49 + tran/sampler.c | 510 + tran/sampler.h | 3 + tran/scale.alg | 11 + tran/scale.c | 202 + tran/scale.h | 3 + tran/shape.alg | 39 + tran/shape.c | 237 + tran/shape.h | 3 + tran/sine.alg | 31 + tran/sine.c | 126 + tran/sine.h | 8 + tran/siosc.alg | 131 + tran/siosc.c | 637 + tran/siosc.h | 3 + tran/slope.alg | 15 + tran/slope.c | 210 + tran/slope.h | 3 + tran/sqrt.alg | 9 + tran/sqrt.c | 198 + tran/sqrt.h | 3 + tran/stkchorus.alg | 21 + tran/stkchorus.c | 311 + tran/stkchorus.h | 3 + tran/stkpitshift.alg | 20 + tran/stkpitshift.c | 311 + tran/stkpitshift.h | 3 + tran/stkrev.alg | 20 + tran/stkrev.c | 311 + tran/stkrev.h | 3 + tran/tapf.alg | 49 + tran/tapf.c | 619 + tran/tapf.h | 3 + tran/tapv.alg | 53 + tran/tapv.c | 634 + tran/tapv.h | 3 + tran/tone.alg | 15 + tran/tone.c | 213 + tran/tone.h | 3 + tran/tonev.alg | 24 + tran/tonev.c | 531 + tran/tonev.h | 3 + tran/translate-stk.lsp | 13 + tran/translate.lsp | 1013 + tran/upsample.alg | 18 + tran/upsample.c | 448 + tran/upsample.h | 3 + tran/white.alg | 24 + tran/white.c | 104 + tran/white.h | 17 + tran/writemake.lsp | 934 + tran/writesusp.lsp | 1025 + tran/writetoss.lsp | 85 + xlisp/extern.c | 129 + xlisp/extern.h | 6 + xlisp/osdefs.h | 4 + xlisp/osptrs.h | 6 + xlisp/path.c | 226 + xlisp/xlbfun.c | 674 + xlisp/xlcont.c | 1428 ++ xlisp/xldbug.c | 218 + xlisp/xldmem.c | 762 + xlisp/xldmem.h | 216 + xlisp/xleval.c | 885 + xlisp/xlfio.c | 734 + xlisp/xlftab.c | 513 + xlisp/xlglob.c | 95 + xlisp/xlimage.c | 407 + xlisp/xlinit.c | 264 + xlisp/xlio.c | 242 + xlisp/xlisp.c | 302 + xlisp/xlisp.h | 1013 + xlisp/xljump.c | 165 + xlisp/xllist.c | 927 + xlisp/xlmath.c | 451 + xlisp/xlobj.c | 489 + xlisp/xlpp.c | 115 + xlisp/xlprin.c | 338 + xlisp/xlread.c | 991 + xlisp/xlstr.c | 561 + xlisp/xlsubr.c | 192 + xlisp/xlsym.c | 370 + xlisp/xlsys.c | 271 + 2369 files changed, 634171 insertions(+) create mode 100644 Readme.txt create mode 100644 advantages.txt create mode 100644 cmt/cext.c create mode 100644 cmt/cext.h create mode 100644 cmt/cleanup.c create mode 100644 cmt/cleanup.h create mode 100644 cmt/cmdline.c create mode 100644 cmt/cmdline.h create mode 100644 cmt/cmtcmd.c create mode 100644 cmt/cmtcmd.h create mode 100644 cmt/cmtio.c create mode 100644 cmt/cmtio.h create mode 100644 cmt/hash.h create mode 100644 cmt/hashrout.h create mode 100644 cmt/mem.c create mode 100644 cmt/mem.h create mode 100644 cmt/mfmidi.h create mode 100644 cmt/midibuff.h create mode 100644 cmt/midicode.h create mode 100644 cmt/midierr.h create mode 100644 cmt/midifile.c create mode 100644 cmt/midifile.h create mode 100644 cmt/midifns.c create mode 100644 cmt/midifns.h create mode 100644 cmt/midimgr.c create mode 100644 cmt/midimgr.h create mode 100644 cmt/moxc.c create mode 100644 cmt/moxc.h create mode 100644 cmt/musiprog.h create mode 100644 cmt/pitch.h create mode 100644 cmt/record.c create mode 100644 cmt/record.h create mode 100644 cmt/seq.c create mode 100644 cmt/seq.h create mode 100644 cmt/seqdecls.h create mode 100644 cmt/seqmread.c create mode 100644 cmt/seqmread.h create mode 100644 cmt/seqmwrite.c create mode 100644 cmt/seqmwrite.h create mode 100644 cmt/seqread.c create mode 100644 cmt/seqread.h create mode 100644 cmt/seqwrite.c create mode 100644 cmt/seqwrite.h create mode 100644 cmt/swlogic.h create mode 100644 cmt/tempomap.c create mode 100644 cmt/tempomap.h create mode 100644 cmt/timebase.c create mode 100644 cmt/timebase.h create mode 100644 cmt/userio.c create mode 100644 cmt/userio.h create mode 100644 comp-ide.bat create mode 100644 convert.dsp create mode 100644 convert.dsw create mode 100644 demos/allewis/cell_aut.lsp create mode 100644 demos/allewis/cellularautomata.htm create mode 100644 demos/allewis/cmusic_pres.ppt create mode 100644 demos/allewis/rule30.jpg create mode 100644 demos/arp.sal create mode 100644 demos/arpeggiator.htm create mode 100644 demos/bandfx.htm create mode 100644 demos/beginclip.jpg create mode 100644 demos/demo-snd.aiff create mode 100644 demos/demo.mid create mode 100644 demos/distortion.htm create mode 100644 demos/examples.lsp create mode 100644 demos/examples.sal create mode 100644 demos/examples_home.htm create mode 100644 demos/fft_demo.lsp create mode 100644 demos/fft_tutorial.htm create mode 100644 demos/largeclip.jpg create mode 100644 demos/lpc-exmpl.dat create mode 100644 demos/lpc_tutorial.htm create mode 100644 demos/lpcdemo.lsp create mode 100644 demos/mateos/bell.lsp create mode 100644 demos/mateos/gong.lsp create mode 100644 demos/mateos/organ.lsp create mode 100644 demos/mateos/tuba.lsp create mode 100644 demos/midi_tutorial.htm create mode 100644 demos/osc-test.lsp create mode 100644 demos/piano.htm create mode 100644 demos/pitch_change.htm create mode 100644 demos/pmorales/a4.lsp create mode 100644 demos/pmorales/a5.lsp create mode 100644 demos/pmorales/a6.lsp create mode 100644 demos/pmorales/b1.lsp create mode 100644 demos/pmorales/b10.lsp create mode 100644 demos/pmorales/b2.lsp create mode 100644 demos/pmorales/b3.lsp create mode 100644 demos/pmorales/b5.lsp create mode 100644 demos/pmorales/b7.lsp create mode 100644 demos/pmorales/b8.lsp create mode 100644 demos/pmorales/b9.lsp create mode 100644 demos/pmorales/buzz.lsp create mode 100644 demos/pmorales/c1.lsp create mode 100644 demos/pmorales/d1.lsp create mode 100644 demos/pmorales/e2.lsp create mode 100644 demos/pmorales/ks.lsp create mode 100644 demos/pmorales/partial.lsp create mode 100644 demos/pmorales/phm.lsp create mode 100644 demos/pmorales/pjmg.lsp create mode 100644 demos/pmorales/readme.txt create mode 100644 demos/probability_distributions.htm create mode 100644 demos/rhythm_tutorial.htm create mode 100644 demos/scratch_tutorial.htm create mode 100755 demos/sdl/ej2.lsp create mode 100644 demos/sdl/inv-08.lsp create mode 100644 demos/sequence_example.htm create mode 100644 demos/shepard.lsp create mode 100644 demos/shepard.ny create mode 100644 demos/softclip.gif create mode 100644 demos/softclip.jpg create mode 100644 demos/stktest.lsp create mode 100644 demos/voice_synthesis.htm create mode 100644 demos/warble_tutorial.htm create mode 100644 demos/wind_tutorial.htm create mode 100644 doc/arcsine-fig.gif create mode 100644 doc/bernoulli-fig.gif create mode 100644 doc/beta-fig.gif create mode 100644 doc/bilateral-fig.gif create mode 100644 doc/binomial-fig.gif create mode 100644 doc/cauchy-fig.gif create mode 100644 doc/exponential-fig.gif create mode 100644 doc/fig1.gif create mode 100644 doc/fig2.gif create mode 100644 doc/fig3.gif create mode 100644 doc/fig4.gif create mode 100644 doc/fig5.gif create mode 100644 doc/fig6.gif create mode 100644 doc/foot.html create mode 100644 doc/gamma-fig.gif create mode 100644 doc/gaussian-fig.gif create mode 100644 doc/geometric-fig.gif create mode 100644 doc/guide.html create mode 100644 doc/home.html create mode 100644 doc/hyperbolic-fig.gif create mode 100644 doc/indx.html create mode 100644 doc/linear-fig.gif create mode 100644 doc/logistic-fig.gif create mode 100644 doc/moog-fig.gif create mode 100644 doc/musicbib.html create mode 100644 doc/nyqman.txt create mode 100644 doc/nyquistman.pdf create mode 100644 doc/part1.html create mode 100644 doc/part10.html create mode 100644 doc/part11.html create mode 100644 doc/part12.html create mode 100644 doc/part13.html create mode 100644 doc/part14.html create mode 100644 doc/part15.html create mode 100644 doc/part16.html create mode 100644 doc/part17.html create mode 100644 doc/part18.html create mode 100644 doc/part19.html create mode 100644 doc/part2.html create mode 100644 doc/part3.html create mode 100644 doc/part4.html create mode 100644 doc/part5.html create mode 100644 doc/part6.html create mode 100644 doc/part7.html create mode 100644 doc/part8.html create mode 100644 doc/part9.html create mode 100644 doc/poisson-fig.gif create mode 100644 doc/sdl-man.pdf create mode 100644 doc/title.html create mode 100644 docsrc/bib/music.bib create mode 100644 docsrc/convert/convert.lsp create mode 100644 docsrc/convert/convert2.lsp create mode 100644 docsrc/convert/init.lsp create mode 100644 docsrc/nyquist/adagio-nyquist.mss create mode 100644 docsrc/nyquist/adagio.mss create mode 100644 docsrc/nyquist/arcsine-fig.ps create mode 100644 docsrc/nyquist/bernoulli-fig.ps create mode 100644 docsrc/nyquist/beta-fig.ps create mode 100644 docsrc/nyquist/bilateral-fig.ps create mode 100644 docsrc/nyquist/binomial-fig.ps create mode 100644 docsrc/nyquist/cauchy-fig.ps create mode 100644 docsrc/nyquist/envfig.ps create mode 100644 docsrc/nyquist/exponential-fig.ps create mode 100644 docsrc/nyquist/gamma-fig.ps create mode 100644 docsrc/nyquist/gaussian-fig.ps create mode 100644 docsrc/nyquist/geometric-fig.ps create mode 100644 docsrc/nyquist/hyperbolic-fig.ps create mode 100644 docsrc/nyquist/linear-fig.ps create mode 100644 docsrc/nyquist/linear-fig.ps.ORIGINAL create mode 100644 docsrc/nyquist/logistic-fig.ps create mode 100644 docsrc/nyquist/moog-fig.ps create mode 100644 docsrc/nyquist/nymanimpl.mss create mode 100644 docsrc/nyquist/nyquistman-sal-only.mss create mode 100644 docsrc/nyquist/nyquistman.mss create mode 100644 docsrc/nyquist/poisson-fig.ps create mode 100644 docsrc/nyquist/rampfig.ps create mode 100644 docsrc/nyquist/shifttimefig.ps create mode 100644 docsrc/nyquist/test.ps create mode 100644 docsrc/nyquist/warpfig.ps create mode 100644 docsrc/nyquist/warpnotesfig.ps create mode 100644 docsrc/nyquist/warponsetfig.ps create mode 100644 docsrc/s2h/citations.lsp create mode 100644 docsrc/s2h/do-nyquist-manual.lsp create mode 100644 docsrc/s2h/s2h.lsp create mode 100644 docsrc/scribe.htm create mode 100755 docsrc/sdl/part1.tex create mode 100755 docsrc/sdl/pjmcfg.sty create mode 100755 docsrc/sdl/sdl-man.tex create mode 100644 docsrc/template/filcap.mss create mode 100644 docsrc/toafs.bat create mode 100644 docsrc/toafs.sh create mode 100644 docsrc/xlisp/intgen.mss create mode 100644 docsrc/xlisp/xlisp-doc/README create mode 100644 docsrc/xlisp/xlisp-doc/examples/apropos.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/arrays.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/binary.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/circular-lists.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/ceiling.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/debug-mv.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/equalp.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/exp.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/expt.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/floor.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/global-multiple-values.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/log.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/mod.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-bind.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-call.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-list.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-prog1.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-setq.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-values.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/numbers.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/rem.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/remainder-and-modulus.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/round.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/rounding-and-truncation.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/sqrt.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/truncate.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/values-list.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/common-lisp/values.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/environment.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/evaluation.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/examples.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/files.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/hash-tables.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/hexadecimal.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/lists.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/macros.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/math.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/octal.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/posix-chars.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/predicates.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/reader.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/sequences.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/strings.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/xlisp/ash.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/xlisp/bsh.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/xlisp/ceiling.htm create mode 100644 docsrc/xlisp/xlisp-doc/examples/xlisp/floor.htm create mode 100644 docsrc/xlisp/xlisp-doc/internals/c-printf.htm create mode 100644 docsrc/xlisp/xlisp-doc/internals/xlisp-internals.html create mode 100644 docsrc/xlisp/xlisp-doc/manual/contents.htm create mode 100644 docsrc/xlisp/xlisp-doc/manual/links.htm create mode 100644 docsrc/xlisp/xlisp-doc/manual/manual.css create mode 100644 docsrc/xlisp/xlisp-doc/manual/objects.htm create mode 100755 docsrc/xlisp/xlisp-doc/manual/part15.html create mode 100644 docsrc/xlisp/xlisp-doc/manual/sal.htm create mode 100644 docsrc/xlisp/xlisp-doc/manual/xlisp-man-033.htm create mode 100644 docsrc/xlisp/xlisp-doc/manual/xlisp.htm create mode 100644 docsrc/xlisp/xlisp-doc/misc/ascii-table.htm create mode 100644 docsrc/xlisp/xlisp-doc/misc/c-printf.htm create mode 100644 docsrc/xlisp/xlisp-doc/misc/links.htm create mode 100644 docsrc/xlisp/xlisp-doc/misc/preface.htm create mode 100644 docsrc/xlisp/xlisp-doc/objects/advanced-objects.htm create mode 100644 docsrc/xlisp/xlisp-doc/objects/smalltalk.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/abs.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/acos.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/addition.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/address-of.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/alloc.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/alphanumericp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/and.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/append.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/apply.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/aref.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/arrayp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/asin.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/assoc.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/atan.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/atom.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/backquote.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/baktrace.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/bigendianp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/block.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/both-case-p.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/boundp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/break.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/caaaar.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/caaar.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/caar.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/car.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/case.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/catch.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cddddr.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cdddr.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cddr.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cdr.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cerror.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-code.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-downcase.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-equal-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-equal-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-greaterp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-greaterp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-int.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-lessp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-lessp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-not-equal-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-not-equal-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-not-lessp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-not-lessp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char-upcase.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/char.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/characterp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/class.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/clean-up.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/close.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/code-char.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cond.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cons.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/consp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/continue.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/cos.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/decf.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/decrement.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/defmacro.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/defun.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/delete-if-not.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/delete-if.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/delete.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/digit-char-p.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/digit-char.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/division.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/do-star.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/do.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/dolist.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/dotimes.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/dribble.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/echoenabled.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/endp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/eq.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/eql.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/equal.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/error.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/errset.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/eval.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/evalhook.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/evenp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/exit.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/exp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/expand.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/expt.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/fboundp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/filep.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/find-in-xlisp-path.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/first.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/flatc.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/flatsize.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/flet.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/float.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/floatp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/format.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/fourth.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/funcall.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/function.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/gc.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/gcd.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/gensym.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get-env.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get-key.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get-lambda-expression.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get-output-stream-list.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get-output-stream-string.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get-temp-path.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get-user.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/get.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-applyhook.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-breakenable.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-debug-io.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-error-output.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-evalhook.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-file-separator.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-float-format.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-gc-flag.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-gc-hook.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-integer-format.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-obarray.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-print-case.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-readtable.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-rslt.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-standard-input.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-standard-output.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-trace-output.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-tracelimit.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-tracelist.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-tracenable.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/global-unbound.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/go.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/hash.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/if.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/incf.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/increment.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/info.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/int-char.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/integerp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/intern.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/interpolate.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/intersection.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-answer.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-class.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-constituent.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-isa.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-isnew.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-mescape.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-new.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-nmacro.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-sescape.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-show.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-tmacro.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keyword-white-space.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/keywordp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/labels.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/lambda-keyword-aux.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/lambda-keyword-key.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/lambda-keyword-optional.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/lambda-keyword-rest.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/lambda.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/last.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/length.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/let-star.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/let.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/list.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/listdir.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/listp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/load.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/log.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/logand.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/logior.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/lognot.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/logxor.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/loop.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/lower-case-p.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/macroexpand-1.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/macroexpand.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/macrolet.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/make-array.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/make-string-input-stream.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/make-string-output-stream.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/make-symbol.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/mapc.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/mapcar.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/mapl.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/maplist.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/max.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/member.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/min.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/minusp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/multiplication.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/nconc.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/nil.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/not.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/nstring-downcase.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/nstring-upcase.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/nth.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/nthcdr.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/null.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/number-equal.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/number-greaterp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/number-lessp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/number-not-equal.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/number-not-greaterp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/number-not-lessp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/numberp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/object.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/objectp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/oddp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/open-binary.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/open.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/or.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/peek-char.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/peek.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/pi.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/plus.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/poke.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/pop.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/power.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/pprint.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/prin1.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/princ.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/print.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/profile.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/prog-star.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/prog.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/prog1.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/prog2.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/progn.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/progv.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/psetq.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/push.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/putprop.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/quit.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/quote.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/random.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/read-byte.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/read-char.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/read-float.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/read-int.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/read-line.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/read.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/real-random.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/reference-copyright.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/reference-format.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/reference-index.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/reference.css create mode 100644 docsrc/xlisp/xlisp-doc/reference/rem.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/remove-if-not.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/remove-if.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/remove.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/remprop.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/rest.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/restore.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/return-from.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/return.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/reverse.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/room.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/round.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/rplaca.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/rplacd.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/rrandom.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/save.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/second.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/self.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/send-super.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/send.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/set-difference.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/set.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/setdir.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/setf.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/setq.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/setup-console.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/sin.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/sort.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/soundp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/sqrt.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/strcat.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/streamp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-downcase.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-equal-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-equal-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-greaterp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-greaterp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-left-trim.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-lessp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-lessp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-not-equal-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-not-equal-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-not-lessp-i.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-not-lessp-s.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-right-trim.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-search.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-trim.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string-upcase.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/string.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/stringp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/sublis.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/subseq.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/subsetp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/subst.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/subtraction.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/symbol-function.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/symbol-name.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/symbol-plist.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/symbol-value.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/symbolp.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/system.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/t.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/tagbody.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/tan.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/terpri.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/third.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/throw.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/top-level.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/trace.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/truncate.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/type-of.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/union.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/unless.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/untrace.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/unwind-protect.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/upper-case-p.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/vector.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/when.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/while.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/write-byte.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/write-char.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/write-float.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/write-int.htm create mode 100644 docsrc/xlisp/xlisp-doc/reference/zerop.htm create mode 100644 docsrc/xlisp/xlisp-doc/start.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/binary-io.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/environment.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/file-io.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/lisp-faq.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/lisp-hints.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/nyquist.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/shell-utilities.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/tutorials.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/xlisp-objects.htm create mode 100644 docsrc/xlisp/xlisp-doc/tutorials/xobj-1.png create mode 100644 docsrc/xlisp/xlisp-no-sal.mss create mode 100644 docsrc/xlisp/xlisp.mss create mode 100644 fft/fftn.c create mode 100644 fft/fftn.h create mode 100644 ffts/Matlab-testing/conv2dTest.c create mode 100644 ffts/Matlab-testing/conv2dtest.m create mode 100644 ffts/Matlab-testing/convTest.c create mode 100644 ffts/Matlab-testing/convtest.m create mode 100644 ffts/Matlab-testing/rfft2dTestML.c create mode 100644 ffts/Matlab-testing/rfft2dTestML.m create mode 100644 ffts/Numerical-Recipes-testing/fftTest.c create mode 100644 ffts/Numerical-Recipes-testing/fftTest2d.c create mode 100644 ffts/Numerical-Recipes-testing/fftTest3d.c create mode 100644 ffts/Numerical-Recipes-testing/rfftTest.c create mode 100644 ffts/Numerical-Recipes-testing/rfftTest2d.c create mode 100644 ffts/README.txt create mode 100644 ffts/Timing-code/fftTiming.c create mode 100644 ffts/Timing-code/rfftTiming.c create mode 100644 ffts/abstract create mode 100644 ffts/src/dxpose.c create mode 100644 ffts/src/dxpose.h create mode 100644 ffts/src/fft2d.c create mode 100644 ffts/src/fft2d.h create mode 100644 ffts/src/fftext.c create mode 100644 ffts/src/fftext.h create mode 100644 ffts/src/fftlib.c create mode 100644 ffts/src/fftlib.h create mode 100644 ffts/src/files create mode 100644 ffts/src/matlib.c create mode 100644 ffts/src/matlib.h create mode 100644 files.txt create mode 100644 howtorelease.txt create mode 100644 init.lsp~ create mode 100755 jny create mode 100644 jnyqide.bat create mode 100644 jnyqide/BareBonesBrowserLaunch.java create mode 100644 jnyqide/CodePane.java create mode 100644 jnyqide/EnvelopeFrame.java create mode 100644 jnyqide/FindDialog.java create mode 100644 jnyqide/InstrumentCharacteristics.java create mode 100755 jnyqide/Jslide.java create mode 100644 jnyqide/LispFileFilter.java create mode 100644 jnyqide/Main.java create mode 100644 jnyqide/MainFrame.java create mode 100644 jnyqide/MainFrame_AboutBox.java create mode 100644 jnyqide/MiniBrowser.java create mode 100644 jnyqide/NotFoundDialog.java create mode 100644 jnyqide/NyqPlot.java create mode 100644 jnyqide/NyquistFile.java create mode 100644 jnyqide/NyquistThread.java create mode 100644 jnyqide/NyquistWords.txt create mode 100644 jnyqide/Pair.java create mode 100755 jnyqide/Piano_Roll.java create mode 100644 jnyqide/PlotFrame.java create mode 100644 jnyqide/PlotMouseAdapter.java create mode 100644 jnyqide/PopupListener.java create mode 100644 jnyqide/PreferencesDialog.java create mode 100644 jnyqide/README.txt create mode 100644 jnyqide/ReplaceDialog.java create mode 100644 jnyqide/SalFileFilter.java create mode 100644 jnyqide/SalWordList.java create mode 100644 jnyqide/SpecialMacHandler.java create mode 100644 jnyqide/SpringUtilities.java create mode 100644 jnyqide/TextColor.java create mode 100644 jnyqide/Trie.java create mode 100644 jnyqide/UPICFrame.java create mode 100644 jnyqide/WordList.java create mode 100644 jnyqide/browser.java create mode 100644 jnyqide/closeFile.gif create mode 100644 jnyqide/help.gif create mode 100644 jnyqide/keywords.txt create mode 100644 jnyqide/manifest.txt create mode 100644 jnyqide/openFile.gif create mode 100644 lib/bandfx.lsp create mode 100644 lib/compress.lsp create mode 100644 lib/dist-test.lsp create mode 100644 lib/distributions.lsp create mode 100644 lib/dtmf.lsp create mode 100644 lib/gran.lsp create mode 100644 lib/grapheq.lsp create mode 100644 lib/instruments.txt create mode 100644 lib/lpc.lsp create mode 100644 lib/midishow.lsp create mode 100644 lib/moog.lsp create mode 100644 lib/piano/att11025.pcm create mode 100644 lib/piano/att16000.pcm create mode 100644 lib/piano/att22050.pcm create mode 100644 lib/piano/att32000.pcm create mode 100644 lib/piano/att44100.pcm create mode 100644 lib/piano/att48000.pcm create mode 100644 lib/piano/att8000.pcm create mode 100644 lib/piano/demo.mid create mode 100644 lib/piano/demo.mp3 create mode 100644 lib/piano/dur.tab create mode 100644 lib/piano/gmax.tab create mode 100644 lib/piano/pn00.cod create mode 100644 lib/piano/pn01.cod create mode 100644 lib/piano/pn02.cod create mode 100644 lib/piano/pn03.cod create mode 100644 lib/piano/pn04.cod create mode 100644 lib/piano/pn05.cod create mode 100644 lib/piano/pn06.cod create mode 100644 lib/piano/pn07.cod create mode 100644 lib/piano/pn08.cod create mode 100644 lib/piano/pn09.cod create mode 100644 lib/piano/pn10.cod create mode 100644 lib/piano/pn11.cod create mode 100644 lib/piano/pn12.cod create mode 100644 lib/piano/pn13.cod create mode 100644 lib/piano/pn14.cod create mode 100644 lib/piano/pn15.cod create mode 100644 lib/piano/pn16.cod create mode 100644 lib/piano/pn17.cod create mode 100644 lib/piano/pn18.cod create mode 100644 lib/piano/pn19.cod create mode 100644 lib/piano/pn20.cod create mode 100644 lib/piano/pn21.cod create mode 100644 lib/piano/pn22.cod create mode 100644 lib/piano/rls11025.pcm create mode 100644 lib/piano/rls16000.pcm create mode 100644 lib/piano/rls22050.pcm create mode 100644 lib/piano/rls32000.pcm create mode 100644 lib/piano/rls44100.pcm create mode 100644 lib/piano/rls48000.pcm create mode 100644 lib/piano/rls8000.pcm create mode 100644 lib/piano/rlsrate.tab create mode 100644 lib/pianosyn.lsp create mode 100644 lib/plugin-test.lsp create mode 100644 lib/reverb.lsp create mode 100644 lib/reverse.lsp create mode 100755 lib/sdl.lsp create mode 100644 lib/soften.lsp create mode 100644 lib/spatial.lsp create mode 100644 lib/spectrum.lsp create mode 100644 lib/statistics.lsp create mode 100644 lib/surround.lsp create mode 100644 lib/time-delay-fns.lsp create mode 100644 lib/vectors.lsp create mode 100644 lib/xm-test.lsp create mode 100644 liblo/AUTHORS create mode 100644 liblo/COPYING create mode 100644 liblo/ChangeLog create mode 100644 liblo/INSTALL create mode 100644 liblo/Makefile.am create mode 100644 liblo/Makefile.in create mode 100644 liblo/Makefile.osx create mode 100644 liblo/NEWS create mode 100644 liblo/README create mode 100644 liblo/README.txt create mode 100644 liblo/TODO create mode 100644 liblo/aclocal.m4 create mode 100755 liblo/autogen.sh create mode 100644 liblo/build/Makefile.am create mode 100644 liblo/build/Makefile.in create mode 100644 liblo/build/lo_endian-msvc.h create mode 100644 liblo/build/premake4.exe create mode 100644 liblo/build/premake4.lua create mode 100644 liblo/build/vs2008/config-msvc.h create mode 100644 liblo/build/vs2008/config.h create mode 100644 liblo/build/vs2008/liblo.suo create mode 100644 liblo/build/vs2008/liblo.vcproj create mode 100644 liblo/build/vs2008/subtest.vcproj create mode 100644 liblo/build/vs2008/testlo.vcproj create mode 100755 liblo/compile create mode 100755 liblo/config.guess create mode 100644 liblo/config.h.in create mode 100755 liblo/config.sub create mode 100755 liblo/configure create mode 100644 liblo/configure.ac create mode 100755 liblo/depcomp create mode 100644 liblo/doc/Makefile.am create mode 100644 liblo/doc/Makefile.in create mode 100644 liblo/doc/reference.doxygen create mode 100644 liblo/doc/reference.doxygen.in create mode 100644 liblo/examples/Makefile.am create mode 100644 liblo/examples/Makefile.in create mode 100644 liblo/examples/example_client.c create mode 100644 liblo/examples/example_server.c create mode 100644 liblo/examples/nonblocking_server_example.c create mode 100755 liblo/install-sh create mode 100644 liblo/liblo.pc.in create mode 100644 liblo/lo/Makefile.am create mode 100644 liblo/lo/Makefile.in create mode 100644 liblo/lo/lo.h create mode 100644 liblo/lo/lo_endian.h create mode 100644 liblo/lo/lo_endian.h.in create mode 100644 liblo/lo/lo_errors.h create mode 100644 liblo/lo/lo_lowlevel.h create mode 100644 liblo/lo/lo_macros.h create mode 100644 liblo/lo/lo_osc_types.h create mode 100644 liblo/lo/lo_throw.h create mode 100644 liblo/lo/lo_types.h create mode 100755 liblo/ltmain.sh create mode 100644 liblo/m4/libtool.m4 create mode 100644 liblo/m4/ltoptions.m4 create mode 100644 liblo/m4/ltsugar.m4 create mode 100644 liblo/m4/ltversion.m4 create mode 100644 liblo/m4/lt~obsolete.m4 create mode 100755 liblo/missing create mode 100644 liblo/osx/config.h create mode 100644 liblo/pthreads.2/ANNOUNCE create mode 100644 liblo/pthreads.2/BUGS create mode 100644 liblo/pthreads.2/Bmakefile create mode 100644 liblo/pthreads.2/BuildLog.htm create mode 100644 liblo/pthreads.2/CONTRIBUTORS create mode 100644 liblo/pthreads.2/COPYING create mode 100644 liblo/pthreads.2/COPYING.LIB create mode 100644 liblo/pthreads.2/ChangeLog create mode 100644 liblo/pthreads.2/FAQ create mode 100644 liblo/pthreads.2/GNUmakefile create mode 100644 liblo/pthreads.2/MAINTAINERS create mode 100644 liblo/pthreads.2/Makefile create mode 100644 liblo/pthreads.2/NEWS create mode 100644 liblo/pthreads.2/Nmakefile create mode 100644 liblo/pthreads.2/Nmakefile.tests create mode 100644 liblo/pthreads.2/PROGRESS create mode 100644 liblo/pthreads.2/README create mode 100644 liblo/pthreads.2/README.Borland create mode 100644 liblo/pthreads.2/README.CV create mode 100644 liblo/pthreads.2/README.NONPORTABLE create mode 100644 liblo/pthreads.2/README.Watcom create mode 100644 liblo/pthreads.2/README.WinCE create mode 100644 liblo/pthreads.2/TODO create mode 100644 liblo/pthreads.2/WinCE-PORT create mode 100644 liblo/pthreads.2/attr.c create mode 100644 liblo/pthreads.2/barrier.c create mode 100644 liblo/pthreads.2/builddmc.bat create mode 100644 liblo/pthreads.2/cancel.c create mode 100644 liblo/pthreads.2/cleanup.c create mode 100644 liblo/pthreads.2/condvar.c create mode 100644 liblo/pthreads.2/config.h create mode 100644 liblo/pthreads.2/create.c create mode 100644 liblo/pthreads.2/dll.c create mode 100644 liblo/pthreads.2/errno.c create mode 100644 liblo/pthreads.2/exit.c create mode 100644 liblo/pthreads.2/fork.c create mode 100644 liblo/pthreads.2/global.c create mode 100644 liblo/pthreads.2/implement.h create mode 100644 liblo/pthreads.2/manual/ChangeLog create mode 100644 liblo/pthreads.2/manual/PortabilityIssues.html create mode 100644 liblo/pthreads.2/manual/index.html create mode 100644 liblo/pthreads.2/manual/pthreadCancelableWait.html create mode 100644 liblo/pthreads.2/manual/pthread_attr_init.html create mode 100644 liblo/pthreads.2/manual/pthread_attr_setstackaddr.html create mode 100644 liblo/pthreads.2/manual/pthread_attr_setstacksize.html create mode 100644 liblo/pthreads.2/manual/pthread_barrier_init.html create mode 100644 liblo/pthreads.2/manual/pthread_barrier_wait.html create mode 100644 liblo/pthreads.2/manual/pthread_barrierattr_init.html create mode 100644 liblo/pthreads.2/manual/pthread_barrierattr_setpshared.html create mode 100644 liblo/pthreads.2/manual/pthread_cancel.html create mode 100644 liblo/pthreads.2/manual/pthread_cleanup_push.html create mode 100644 liblo/pthreads.2/manual/pthread_cond_init.html create mode 100644 liblo/pthreads.2/manual/pthread_condattr_init.html create mode 100644 liblo/pthreads.2/manual/pthread_condattr_setpshared.html create mode 100644 liblo/pthreads.2/manual/pthread_create.html create mode 100644 liblo/pthreads.2/manual/pthread_delay_np.html create mode 100644 liblo/pthreads.2/manual/pthread_detach.html create mode 100644 liblo/pthreads.2/manual/pthread_equal.html create mode 100644 liblo/pthreads.2/manual/pthread_exit.html create mode 100644 liblo/pthreads.2/manual/pthread_getw32threadhandle_np.html create mode 100644 liblo/pthreads.2/manual/pthread_join.html create mode 100644 liblo/pthreads.2/manual/pthread_key_create.html create mode 100644 liblo/pthreads.2/manual/pthread_kill.html create mode 100644 liblo/pthreads.2/manual/pthread_mutex_init.html create mode 100644 liblo/pthreads.2/manual/pthread_mutexattr_init.html create mode 100644 liblo/pthreads.2/manual/pthread_mutexattr_setpshared.html create mode 100644 liblo/pthreads.2/manual/pthread_num_processors_np.html create mode 100644 liblo/pthreads.2/manual/pthread_once.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlock_init.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlock_rdlock.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlock_timedrdlock.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlock_timedwrlock.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlock_unlock.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlock_wrlock.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlockattr_init.html create mode 100644 liblo/pthreads.2/manual/pthread_rwlockattr_setpshared.html create mode 100644 liblo/pthreads.2/manual/pthread_self.html create mode 100644 liblo/pthreads.2/manual/pthread_setcancelstate.html create mode 100644 liblo/pthreads.2/manual/pthread_setcanceltype.html create mode 100644 liblo/pthreads.2/manual/pthread_setconcurrency.html create mode 100644 liblo/pthreads.2/manual/pthread_setschedparam.html create mode 100644 liblo/pthreads.2/manual/pthread_spin_init.html create mode 100644 liblo/pthreads.2/manual/pthread_spin_lock.html create mode 100644 liblo/pthreads.2/manual/pthread_spin_unlock.html create mode 100644 liblo/pthreads.2/manual/pthread_timechange_handler_np.html create mode 100644 liblo/pthreads.2/manual/pthread_win32_attach_detach_np.html create mode 100644 liblo/pthreads.2/manual/pthread_win32_test_features_np.html create mode 100644 liblo/pthreads.2/manual/sched_get_priority_max.html create mode 100644 liblo/pthreads.2/manual/sched_getscheduler.html create mode 100644 liblo/pthreads.2/manual/sched_setscheduler.html create mode 100644 liblo/pthreads.2/manual/sched_yield.html create mode 100644 liblo/pthreads.2/manual/sem_init.html create mode 100644 liblo/pthreads.2/misc.c create mode 100644 liblo/pthreads.2/mt.dep create mode 100644 liblo/pthreads.2/mutex.c create mode 100644 liblo/pthreads.2/need_errno.h create mode 100644 liblo/pthreads.2/nonportable.c create mode 100644 liblo/pthreads.2/private.c create mode 100644 liblo/pthreads.2/pthread.c create mode 100644 liblo/pthreads.2/pthread.h create mode 100644 liblo/pthreads.2/pthread.suo create mode 100644 liblo/pthreads.2/pthread.vcproj create mode 100644 liblo/pthreads.2/pthreadVC2.dll.embed.manifest.res create mode 100644 liblo/pthreads.2/pthread_attr_destroy.c create mode 100644 liblo/pthreads.2/pthread_attr_getdetachstate.c create mode 100644 liblo/pthreads.2/pthread_attr_getinheritsched.c create mode 100644 liblo/pthreads.2/pthread_attr_getschedparam.c create mode 100644 liblo/pthreads.2/pthread_attr_getschedpolicy.c create mode 100644 liblo/pthreads.2/pthread_attr_getscope.c create mode 100644 liblo/pthreads.2/pthread_attr_getstackaddr.c create mode 100644 liblo/pthreads.2/pthread_attr_getstacksize.c create mode 100644 liblo/pthreads.2/pthread_attr_init.c create mode 100644 liblo/pthreads.2/pthread_attr_setdetachstate.c create mode 100644 liblo/pthreads.2/pthread_attr_setinheritsched.c create mode 100644 liblo/pthreads.2/pthread_attr_setschedparam.c create mode 100644 liblo/pthreads.2/pthread_attr_setschedpolicy.c create mode 100644 liblo/pthreads.2/pthread_attr_setscope.c create mode 100644 liblo/pthreads.2/pthread_attr_setstackaddr.c create mode 100644 liblo/pthreads.2/pthread_attr_setstacksize.c create mode 100644 liblo/pthreads.2/pthread_barrier_destroy.c create mode 100644 liblo/pthreads.2/pthread_barrier_init.c create mode 100644 liblo/pthreads.2/pthread_barrier_wait.c create mode 100644 liblo/pthreads.2/pthread_barrierattr_destroy.c create mode 100644 liblo/pthreads.2/pthread_barrierattr_getpshared.c create mode 100644 liblo/pthreads.2/pthread_barrierattr_init.c create mode 100644 liblo/pthreads.2/pthread_barrierattr_setpshared.c create mode 100644 liblo/pthreads.2/pthread_cancel.c create mode 100644 liblo/pthreads.2/pthread_cond_destroy.c create mode 100644 liblo/pthreads.2/pthread_cond_init.c create mode 100644 liblo/pthreads.2/pthread_cond_signal.c create mode 100644 liblo/pthreads.2/pthread_cond_wait.c create mode 100644 liblo/pthreads.2/pthread_condattr_destroy.c create mode 100644 liblo/pthreads.2/pthread_condattr_getpshared.c create mode 100644 liblo/pthreads.2/pthread_condattr_init.c create mode 100644 liblo/pthreads.2/pthread_condattr_setpshared.c create mode 100644 liblo/pthreads.2/pthread_delay_np.c create mode 100644 liblo/pthreads.2/pthread_detach.c create mode 100644 liblo/pthreads.2/pthread_equal.c create mode 100644 liblo/pthreads.2/pthread_exit.c create mode 100644 liblo/pthreads.2/pthread_getconcurrency.c create mode 100644 liblo/pthreads.2/pthread_getschedparam.c create mode 100644 liblo/pthreads.2/pthread_getspecific.c create mode 100644 liblo/pthreads.2/pthread_getw32threadhandle_np.c create mode 100644 liblo/pthreads.2/pthread_join.c create mode 100644 liblo/pthreads.2/pthread_key_create.c create mode 100644 liblo/pthreads.2/pthread_key_delete.c create mode 100644 liblo/pthreads.2/pthread_kill.c create mode 100644 liblo/pthreads.2/pthread_mutex_destroy.c create mode 100644 liblo/pthreads.2/pthread_mutex_init.c create mode 100644 liblo/pthreads.2/pthread_mutex_lock.c create mode 100644 liblo/pthreads.2/pthread_mutex_timedlock.c create mode 100644 liblo/pthreads.2/pthread_mutex_trylock.c create mode 100644 liblo/pthreads.2/pthread_mutex_unlock.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_destroy.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_getkind_np.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_getpshared.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_gettype.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_init.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_setkind_np.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_setpshared.c create mode 100644 liblo/pthreads.2/pthread_mutexattr_settype.c create mode 100644 liblo/pthreads.2/pthread_num_processors_np.c create mode 100644 liblo/pthreads.2/pthread_once.c create mode 100644 liblo/pthreads.2/pthread_once.x create mode 100644 liblo/pthreads.2/pthread_rwlock_destroy.c create mode 100644 liblo/pthreads.2/pthread_rwlock_init.c create mode 100644 liblo/pthreads.2/pthread_rwlock_rdlock.c create mode 100644 liblo/pthreads.2/pthread_rwlock_timedrdlock.c create mode 100644 liblo/pthreads.2/pthread_rwlock_timedwrlock.c create mode 100644 liblo/pthreads.2/pthread_rwlock_tryrdlock.c create mode 100644 liblo/pthreads.2/pthread_rwlock_trywrlock.c create mode 100644 liblo/pthreads.2/pthread_rwlock_unlock.c create mode 100644 liblo/pthreads.2/pthread_rwlock_wrlock.c create mode 100644 liblo/pthreads.2/pthread_rwlockattr_destroy.c create mode 100644 liblo/pthreads.2/pthread_rwlockattr_getpshared.c create mode 100644 liblo/pthreads.2/pthread_rwlockattr_init.c create mode 100644 liblo/pthreads.2/pthread_rwlockattr_setpshared.c create mode 100644 liblo/pthreads.2/pthread_self.c create mode 100644 liblo/pthreads.2/pthread_setcancelstate.c create mode 100644 liblo/pthreads.2/pthread_setcanceltype.c create mode 100644 liblo/pthreads.2/pthread_setconcurrency.c create mode 100644 liblo/pthreads.2/pthread_setschedparam.c create mode 100644 liblo/pthreads.2/pthread_setspecific.c create mode 100644 liblo/pthreads.2/pthread_spin_destroy.c create mode 100644 liblo/pthreads.2/pthread_spin_init.c create mode 100644 liblo/pthreads.2/pthread_spin_lock.c create mode 100644 liblo/pthreads.2/pthread_spin_trylock.c create mode 100644 liblo/pthreads.2/pthread_spin_unlock.c create mode 100644 liblo/pthreads.2/pthread_testcancel.c create mode 100644 liblo/pthreads.2/pthread_timechange_handler_np.c create mode 100644 liblo/pthreads.2/pthread_win32_attach_detach_np.c create mode 100644 liblo/pthreads.2/ptw32_InterlockedCompareExchange.c create mode 100644 liblo/pthreads.2/ptw32_MCS_lock.c create mode 100644 liblo/pthreads.2/ptw32_callUserDestroyRoutines.c create mode 100644 liblo/pthreads.2/ptw32_calloc.c create mode 100644 liblo/pthreads.2/ptw32_cond_check_need_init.c create mode 100644 liblo/pthreads.2/ptw32_getprocessors.c create mode 100644 liblo/pthreads.2/ptw32_is_attr.c create mode 100644 liblo/pthreads.2/ptw32_mutex_check_need_init.c create mode 100644 liblo/pthreads.2/ptw32_new.c create mode 100644 liblo/pthreads.2/ptw32_processInitialize.c create mode 100644 liblo/pthreads.2/ptw32_processTerminate.c create mode 100644 liblo/pthreads.2/ptw32_relmillisecs.c create mode 100644 liblo/pthreads.2/ptw32_reuse.c create mode 100644 liblo/pthreads.2/ptw32_rwlock_cancelwrwait.c create mode 100644 liblo/pthreads.2/ptw32_rwlock_check_need_init.c create mode 100644 liblo/pthreads.2/ptw32_semwait.c create mode 100644 liblo/pthreads.2/ptw32_spinlock_check_need_init.c create mode 100644 liblo/pthreads.2/ptw32_threadDestroy.c create mode 100644 liblo/pthreads.2/ptw32_threadStart.c create mode 100644 liblo/pthreads.2/ptw32_throw.c create mode 100644 liblo/pthreads.2/ptw32_timespec.c create mode 100644 liblo/pthreads.2/ptw32_tkAssocCreate.c create mode 100644 liblo/pthreads.2/ptw32_tkAssocDestroy.c create mode 100644 liblo/pthreads.2/rwlock.c create mode 100644 liblo/pthreads.2/sched.c create mode 100644 liblo/pthreads.2/sched.h create mode 100644 liblo/pthreads.2/sched_get_priority_max.c create mode 100644 liblo/pthreads.2/sched_get_priority_min.c create mode 100644 liblo/pthreads.2/sched_getscheduler.c create mode 100644 liblo/pthreads.2/sched_setscheduler.c create mode 100644 liblo/pthreads.2/sched_yield.c create mode 100644 liblo/pthreads.2/sem_close.c create mode 100644 liblo/pthreads.2/sem_destroy.c create mode 100644 liblo/pthreads.2/sem_getvalue.c create mode 100644 liblo/pthreads.2/sem_init.c create mode 100644 liblo/pthreads.2/sem_open.c create mode 100644 liblo/pthreads.2/sem_post.c create mode 100644 liblo/pthreads.2/sem_post_multiple.c create mode 100644 liblo/pthreads.2/sem_timedwait.c create mode 100644 liblo/pthreads.2/sem_trywait.c create mode 100644 liblo/pthreads.2/sem_unlink.c create mode 100644 liblo/pthreads.2/sem_wait.c create mode 100644 liblo/pthreads.2/semaphore.c create mode 100644 liblo/pthreads.2/semaphore.h create mode 100644 liblo/pthreads.2/signal.c create mode 100644 liblo/pthreads.2/spin.c create mode 100644 liblo/pthreads.2/sync.c create mode 100644 liblo/pthreads.2/tests/Bmakefile create mode 100644 liblo/pthreads.2/tests/ChangeLog create mode 100644 liblo/pthreads.2/tests/Debug.dsp create mode 100644 liblo/pthreads.2/tests/Debug.dsw create mode 100644 liblo/pthreads.2/tests/Debug.txt create mode 100644 liblo/pthreads.2/tests/GNUmakefile create mode 100644 liblo/pthreads.2/tests/Makefile create mode 100644 liblo/pthreads.2/tests/README.BENCHTESTS create mode 100644 liblo/pthreads.2/tests/SIZES.VCE create mode 100644 liblo/pthreads.2/tests/Wmakefile create mode 100644 liblo/pthreads.2/tests/barrier1.c create mode 100644 liblo/pthreads.2/tests/barrier2.c create mode 100644 liblo/pthreads.2/tests/barrier3.c create mode 100644 liblo/pthreads.2/tests/barrier4.c create mode 100644 liblo/pthreads.2/tests/barrier5.c create mode 100644 liblo/pthreads.2/tests/benchlib.c create mode 100644 liblo/pthreads.2/tests/benchtest.h create mode 100644 liblo/pthreads.2/tests/benchtest1.c create mode 100644 liblo/pthreads.2/tests/benchtest2.c create mode 100644 liblo/pthreads.2/tests/benchtest3.c create mode 100644 liblo/pthreads.2/tests/benchtest4.c create mode 100644 liblo/pthreads.2/tests/benchtest5.c create mode 100644 liblo/pthreads.2/tests/cancel1.c create mode 100644 liblo/pthreads.2/tests/cancel2.c create mode 100644 liblo/pthreads.2/tests/cancel3.c create mode 100644 liblo/pthreads.2/tests/cancel4.c create mode 100644 liblo/pthreads.2/tests/cancel5.c create mode 100644 liblo/pthreads.2/tests/cancel6a.c create mode 100644 liblo/pthreads.2/tests/cancel6d.c create mode 100644 liblo/pthreads.2/tests/cancel7.c create mode 100644 liblo/pthreads.2/tests/cancel8.c create mode 100644 liblo/pthreads.2/tests/cancel9.c create mode 100644 liblo/pthreads.2/tests/cleanup0.c create mode 100644 liblo/pthreads.2/tests/cleanup1.c create mode 100644 liblo/pthreads.2/tests/cleanup2.c create mode 100644 liblo/pthreads.2/tests/cleanup3.c create mode 100644 liblo/pthreads.2/tests/condvar1.c create mode 100644 liblo/pthreads.2/tests/condvar1_1.c create mode 100644 liblo/pthreads.2/tests/condvar1_2.c create mode 100644 liblo/pthreads.2/tests/condvar2.c create mode 100644 liblo/pthreads.2/tests/condvar2_1.c create mode 100644 liblo/pthreads.2/tests/condvar3.c create mode 100644 liblo/pthreads.2/tests/condvar3_1.c create mode 100644 liblo/pthreads.2/tests/condvar3_2.c create mode 100644 liblo/pthreads.2/tests/condvar3_3.c create mode 100644 liblo/pthreads.2/tests/condvar4.c create mode 100644 liblo/pthreads.2/tests/condvar5.c create mode 100644 liblo/pthreads.2/tests/condvar6.c create mode 100644 liblo/pthreads.2/tests/condvar7.c create mode 100644 liblo/pthreads.2/tests/condvar8.c create mode 100644 liblo/pthreads.2/tests/condvar9.c create mode 100644 liblo/pthreads.2/tests/context1.c create mode 100644 liblo/pthreads.2/tests/count1.c create mode 100644 liblo/pthreads.2/tests/create1.c create mode 100644 liblo/pthreads.2/tests/create2.c create mode 100644 liblo/pthreads.2/tests/create3.c create mode 100644 liblo/pthreads.2/tests/delay1.c create mode 100644 liblo/pthreads.2/tests/delay2.c create mode 100644 liblo/pthreads.2/tests/detach1.c create mode 100644 liblo/pthreads.2/tests/equal1.c create mode 100644 liblo/pthreads.2/tests/errno1.c create mode 100644 liblo/pthreads.2/tests/exception1.c create mode 100644 liblo/pthreads.2/tests/exception2.c create mode 100644 liblo/pthreads.2/tests/exception3.c create mode 100644 liblo/pthreads.2/tests/exit1.c create mode 100644 liblo/pthreads.2/tests/exit2.c create mode 100644 liblo/pthreads.2/tests/exit3.c create mode 100644 liblo/pthreads.2/tests/exit4.c create mode 100644 liblo/pthreads.2/tests/exit5.c create mode 100644 liblo/pthreads.2/tests/eyal1.c create mode 100644 liblo/pthreads.2/tests/inherit1.c create mode 100644 liblo/pthreads.2/tests/join0.c create mode 100644 liblo/pthreads.2/tests/join1.c create mode 100644 liblo/pthreads.2/tests/join2.c create mode 100644 liblo/pthreads.2/tests/join3.c create mode 100644 liblo/pthreads.2/tests/kill1.c create mode 100644 liblo/pthreads.2/tests/loadfree.c create mode 100644 liblo/pthreads.2/tests/multiPCcaBetter.c create mode 100644 liblo/pthreads.2/tests/mutex1.c create mode 100644 liblo/pthreads.2/tests/mutex1e.c create mode 100644 liblo/pthreads.2/tests/mutex1n.c create mode 100644 liblo/pthreads.2/tests/mutex1r.c create mode 100644 liblo/pthreads.2/tests/mutex2.c create mode 100644 liblo/pthreads.2/tests/mutex2e.c create mode 100644 liblo/pthreads.2/tests/mutex2r.c create mode 100644 liblo/pthreads.2/tests/mutex3.c create mode 100644 liblo/pthreads.2/tests/mutex3e.c create mode 100644 liblo/pthreads.2/tests/mutex3r.c create mode 100644 liblo/pthreads.2/tests/mutex4.c create mode 100644 liblo/pthreads.2/tests/mutex5.c create mode 100644 liblo/pthreads.2/tests/mutex6.c create mode 100644 liblo/pthreads.2/tests/mutex6e.c create mode 100644 liblo/pthreads.2/tests/mutex6es.c create mode 100644 liblo/pthreads.2/tests/mutex6n.c create mode 100644 liblo/pthreads.2/tests/mutex6r.c create mode 100644 liblo/pthreads.2/tests/mutex6rs.c create mode 100644 liblo/pthreads.2/tests/mutex6s.c create mode 100644 liblo/pthreads.2/tests/mutex7.c create mode 100644 liblo/pthreads.2/tests/mutex7e.c create mode 100644 liblo/pthreads.2/tests/mutex7n.c create mode 100644 liblo/pthreads.2/tests/mutex7r.c create mode 100644 liblo/pthreads.2/tests/mutex8.c create mode 100644 liblo/pthreads.2/tests/mutex8e.c create mode 100644 liblo/pthreads.2/tests/mutex8n.c create mode 100644 liblo/pthreads.2/tests/mutex8r.c create mode 100644 liblo/pthreads.2/tests/once1.c create mode 100644 liblo/pthreads.2/tests/once2.c create mode 100644 liblo/pthreads.2/tests/once3.c create mode 100644 liblo/pthreads.2/tests/once4.c create mode 100644 liblo/pthreads.2/tests/priority1.c create mode 100644 liblo/pthreads.2/tests/priority2.c create mode 100644 liblo/pthreads.2/tests/readme create mode 100644 liblo/pthreads.2/tests/reuse1.c create mode 100644 liblo/pthreads.2/tests/reuse2.c create mode 100644 liblo/pthreads.2/tests/rwlock1.c create mode 100644 liblo/pthreads.2/tests/rwlock2.c create mode 100644 liblo/pthreads.2/tests/rwlock2_t.c create mode 100644 liblo/pthreads.2/tests/rwlock3.c create mode 100644 liblo/pthreads.2/tests/rwlock3_t.c create mode 100644 liblo/pthreads.2/tests/rwlock4.c create mode 100644 liblo/pthreads.2/tests/rwlock4_t.c create mode 100644 liblo/pthreads.2/tests/rwlock5.c create mode 100644 liblo/pthreads.2/tests/rwlock5_t.c create mode 100644 liblo/pthreads.2/tests/rwlock6.c create mode 100644 liblo/pthreads.2/tests/rwlock6_t.c create mode 100644 liblo/pthreads.2/tests/rwlock6_t2.c create mode 100644 liblo/pthreads.2/tests/rwlock7.c create mode 100644 liblo/pthreads.2/tests/rwlock8.c create mode 100644 liblo/pthreads.2/tests/self1.c create mode 100644 liblo/pthreads.2/tests/self2.c create mode 100644 liblo/pthreads.2/tests/semaphore1.c create mode 100644 liblo/pthreads.2/tests/semaphore2.c create mode 100644 liblo/pthreads.2/tests/semaphore3.c create mode 100644 liblo/pthreads.2/tests/semaphore4.c create mode 100644 liblo/pthreads.2/tests/semaphore4t.c create mode 100644 liblo/pthreads.2/tests/semaphore5.c create mode 100644 liblo/pthreads.2/tests/sizes.c create mode 100644 liblo/pthreads.2/tests/sizes.gc create mode 100644 liblo/pthreads.2/tests/sizes.gce create mode 100644 liblo/pthreads.2/tests/sizes.vc create mode 100644 liblo/pthreads.2/tests/sizes.vse create mode 100644 liblo/pthreads.2/tests/spin1.c create mode 100644 liblo/pthreads.2/tests/spin2.c create mode 100644 liblo/pthreads.2/tests/spin3.c create mode 100644 liblo/pthreads.2/tests/spin4.c create mode 100644 liblo/pthreads.2/tests/stress1.c create mode 100644 liblo/pthreads.2/tests/test.h create mode 100644 liblo/pthreads.2/tests/tryentercs.c create mode 100644 liblo/pthreads.2/tests/tryentercs2.c create mode 100644 liblo/pthreads.2/tests/tsd1.c create mode 100644 liblo/pthreads.2/tests/tsd2.c create mode 100644 liblo/pthreads.2/tests/valid1.c create mode 100644 liblo/pthreads.2/tests/valid2.c create mode 100644 liblo/pthreads.2/tsd.c create mode 100644 liblo/pthreads.2/version.rc create mode 100644 liblo/pthreads.2/version.res create mode 100644 liblo/pthreads.2/w32_CancelableWait.c create mode 100644 liblo/ser-to-osc/README.txt create mode 100644 liblo/ser-to-osc/Serial.cpp create mode 100644 liblo/ser-to-osc/Serial.h create mode 100644 liblo/ser-to-osc/ser-to-osc.cpp create mode 100644 liblo/ser-to-osc/ser-to-osc.vcproj create mode 100644 liblo/src/Makefile.am create mode 100644 liblo/src/Makefile.in create mode 100644 liblo/src/address.c create mode 100644 liblo/src/blob.c create mode 100644 liblo/src/bundle.c create mode 100644 liblo/src/liblo.def create mode 100644 liblo/src/lo_internal.h create mode 100644 liblo/src/lo_types_internal.h create mode 100644 liblo/src/message.c create mode 100644 liblo/src/method.c create mode 100644 liblo/src/pattern_match.c create mode 100644 liblo/src/send.c create mode 100644 liblo/src/server.c create mode 100644 liblo/src/server_thread.c create mode 100644 liblo/src/subtest.c create mode 100644 liblo/src/testlo.c create mode 100644 liblo/src/timetag.c create mode 100644 liblo/src/tools/Makefile.am create mode 100644 liblo/src/tools/Makefile.in create mode 100644 liblo/src/tools/README create mode 100644 liblo/src/tools/oscdump.c create mode 100644 liblo/src/tools/oscsend.c create mode 100644 liblo/test-client/README.txt create mode 100644 liblo/test-client/osc-test-client.vcproj create mode 100644 liblo/test-client/test-client.c create mode 100644 license.txt create mode 100644 lpc/compile.txt create mode 100644 lpc/lpc-example.dat create mode 100644 lpc/lpc-exmpl.dat create mode 100644 lpc/lpc-orig.lsp create mode 100644 lpc/lpc.lsp create mode 100644 lpc/lpcdemo-orig.lsp create mode 100644 lpc/lpcdemo.lsp create mode 100644 lpc/prims-ref.txt create mode 100644 lpc/readme.txt create mode 100644 lpc/src/allpoles.alg create mode 100644 lpc/src/lpanal.c create mode 100644 lpc/src/lpanal.h create mode 100644 lpc/src/lpreson.alg create mode 100644 macosxproject/.DS_Store create mode 100644 macosxproject/Nyquist.icns create mode 100644 macosxproject/NyquistIDE-Info.plist create mode 100644 macosxproject/README.txt create mode 100644 macosxproject/alternate.icns create mode 100644 macosxproject/nycon2008.gif create mode 100644 macosxproject/nycon2008.png create mode 100644 macosxproject/nycon2008.xcf create mode 100644 macosxproject/nyquist.pbproj/project.pbxproj create mode 100644 macosxproject/nyquist.xcodeproj/project.pbxproj create mode 100644 macproject/NyquistIcon create mode 100644 macproject/NyquistIcon.sit create mode 100644 macproject/mac_port_changes.txt create mode 100644 macproject/nyquist.mcp create mode 100644 macproject/nyquist.rsrc create mode 100644 macproject/nyquistdata/CWSettingsMacOS.stg create mode 100644 macproject/packer/packer.mcp create mode 100644 macproject/packer/packerdata/.DS_Store create mode 100644 macproject/unpacker/unpacker.mcp create mode 100644 macproject/unpacker/unpackerdata/CWSettingsMacOS.stg create mode 100644 macproject/unpacker/unpackerdata/unpacker/TargetDataMacOS.tdt create mode 100644 misc/Makefile create mode 100644 misc/args.h create mode 100644 misc/cext.h create mode 100644 misc/cmdline.c create mode 100644 misc/cmdline.h create mode 100644 misc/cmu/Projects.zip create mode 100644 misc/cmu/cleanup.bat create mode 100644 misc/cmu/cmu-linux-install.lsp create mode 100644 misc/cmu/cmuinstall.bat create mode 100644 misc/cmu/cmuinstall.sh create mode 100644 misc/cmu/cmuinstall2.bat create mode 100644 misc/cmu/cmuinstallmac.sh create mode 100644 misc/cmu/init.lsp create mode 100644 misc/cmu/install-plight.sh create mode 100644 misc/cmu/music.software.html create mode 100644 misc/cmu/new.html create mode 100644 misc/cmu/nyqide_setup.sgp create mode 100644 misc/cmu/nyquist_setup.sgp create mode 100644 misc/cmu/nyqwin_setup.sgp create mode 100644 misc/cmu/restore.bat create mode 100644 misc/convert.c create mode 100644 misc/convert.h create mode 100644 misc/filelist.c create mode 100644 misc/filelist.dsp create mode 100644 misc/filelist.vcproj create mode 100644 misc/intgen.c create mode 100644 misc/intgen2.c create mode 100644 misc/intgen_win32/intgen.dsp create mode 100644 misc/intgen_win32/intgen.vcproj create mode 100644 misc/mac-to-win.lsp create mode 100644 misc/makefile.lsp create mode 100644 misc/packer.c create mode 100644 misc/packer.dsp create mode 100644 misc/packer.vcproj create mode 100644 misc/play.c create mode 100644 misc/plot.c create mode 100644 misc/sampleprint.c create mode 100644 misc/sine.c create mode 100644 misc/stdefs2.h create mode 100644 misc/transfiles.lsp create mode 100644 misc/unpacker.c create mode 100644 misc/unpacker.dsp create mode 100644 misc/unpacker.vcproj create mode 100644 nylsf/COPYING create mode 100644 nylsf/G72x/README.original create mode 100644 nylsf/G72x/g721.c create mode 100644 nylsf/G72x/g723_16.c create mode 100644 nylsf/G72x/g723_24.c create mode 100644 nylsf/G72x/g723_40.c create mode 100644 nylsf/G72x/g72x.c create mode 100644 nylsf/G72x/g72x.h create mode 100644 nylsf/G72x/g72x_priv.h create mode 100644 nylsf/G72x/g72x_test.c create mode 100644 nylsf/GSM610/README create mode 100644 nylsf/GSM610/add.c create mode 100644 nylsf/GSM610/code.c create mode 100644 nylsf/GSM610/decode.c create mode 100644 nylsf/GSM610/gsm.h create mode 100644 nylsf/GSM610/gsm610_priv.h create mode 100644 nylsf/GSM610/gsm_create.c create mode 100644 nylsf/GSM610/gsm_decode.c create mode 100644 nylsf/GSM610/gsm_destroy.c create mode 100644 nylsf/GSM610/gsm_encode.c create mode 100644 nylsf/GSM610/gsm_option.c create mode 100644 nylsf/GSM610/long_term.c create mode 100644 nylsf/GSM610/lpc.c create mode 100644 nylsf/GSM610/preprocess.c create mode 100644 nylsf/GSM610/rpe.c create mode 100644 nylsf/GSM610/short_term.c create mode 100644 nylsf/GSM610/table.c create mode 100644 nylsf/README.txt create mode 100644 nylsf/aiff.c create mode 100644 nylsf/alaw.c create mode 100644 nylsf/au.c create mode 100644 nylsf/avr.c create mode 100644 nylsf/broadcast.c create mode 100644 nylsf/caf.c create mode 100644 nylsf/command.c create mode 100644 nylsf/common.c create mode 100644 nylsf/common.h create mode 100644 nylsf/config.h create mode 100644 nylsf/dither.c create mode 100644 nylsf/double64.c create mode 100644 nylsf/dwd.c create mode 100644 nylsf/dwvw.c create mode 100644 nylsf/file_io.c create mode 100644 nylsf/flac.c create mode 100644 nylsf/float32.c create mode 100644 nylsf/float_cast.h create mode 100644 nylsf/g72x.c create mode 100644 nylsf/gsm610.c create mode 100644 nylsf/htk.c create mode 100644 nylsf/ima_adpcm.c create mode 100644 nylsf/interleave.c create mode 100644 nylsf/ircam.c create mode 100644 nylsf/macbinary3.c create mode 100644 nylsf/macos.c create mode 100644 nylsf/mat4.c create mode 100644 nylsf/mat5.c create mode 100644 nylsf/ms_adpcm.c create mode 100644 nylsf/nist.c create mode 100644 nylsf/ogg.c create mode 100644 nylsf/paf.c create mode 100644 nylsf/pcm.c create mode 100644 nylsf/ppc-config.h create mode 100644 nylsf/pvf.c create mode 100644 nylsf/raw.c create mode 100644 nylsf/rx2.c create mode 100644 nylsf/sd2.c create mode 100644 nylsf/sds.c create mode 100644 nylsf/sf_unistd.h create mode 100644 nylsf/sfconfig.h create mode 100644 nylsf/sfendian.h create mode 100644 nylsf/sndfile.c create mode 100644 nylsf/sndfile.h create mode 100644 nylsf/strings.c create mode 100644 nylsf/svx.c create mode 100644 nylsf/test_endswap.c create mode 100644 nylsf/test_file_io.c create mode 100644 nylsf/test_log_printf.c create mode 100644 nylsf/txw.c create mode 100644 nylsf/ulaw.c create mode 100644 nylsf/voc.c create mode 100644 nylsf/vox_adpcm.c create mode 100644 nylsf/w64.c create mode 100644 nylsf/wav.c create mode 100644 nylsf/wav_w64.c create mode 100644 nylsf/wav_w64.h create mode 100644 nylsf/wve.c create mode 100644 nylsf/xi.c create mode 100644 nyqide/doc/nyqide_plot.gif create mode 100644 nyqide/doc/nyquistide.gif create mode 100644 nyqide/doc/tips.htm create mode 100644 nyqide/nyqide_src.zip create mode 100644 nyqide/readme-vcl.txt create mode 100644 nyqsrc/add.c create mode 100644 nyqsrc/add.h create mode 100644 nyqsrc/avg.c create mode 100644 nyqsrc/avg.h create mode 100644 nyqsrc/compose.c create mode 100644 nyqsrc/compose.h create mode 100644 nyqsrc/convolve.c create mode 100644 nyqsrc/convolve.h create mode 100644 nyqsrc/cque.h create mode 100644 nyqsrc/debug.c create mode 100644 nyqsrc/debug.h create mode 100644 nyqsrc/downsample.c create mode 100644 nyqsrc/downsample.h create mode 100644 nyqsrc/exitpa.h create mode 100644 nyqsrc/f0.cpp create mode 100644 nyqsrc/f0.h create mode 100644 nyqsrc/falloc.c create mode 100644 nyqsrc/falloc.h create mode 100644 nyqsrc/ffilterkit.c create mode 100644 nyqsrc/ffilterkit.h create mode 100644 nyqsrc/fft-rbd.c create mode 100644 nyqsrc/fft.c create mode 100644 nyqsrc/fft.h create mode 100644 nyqsrc/fftr4.c create mode 100644 nyqsrc/fftw.h create mode 100644 nyqsrc/fresample.h create mode 100644 nyqsrc/fsmallfilter.h create mode 100644 nyqsrc/handlers.c create mode 100644 nyqsrc/inverse.c create mode 100644 nyqsrc/inverse.h create mode 100644 nyqsrc/local.c create mode 100644 nyqsrc/localdefs.h create mode 100644 nyqsrc/localptrs.h create mode 100644 nyqsrc/lpanal.c create mode 100644 nyqsrc/lpanal.h create mode 100644 nyqsrc/multiread.c create mode 100644 nyqsrc/multiread.h create mode 100644 nyqsrc/multiseq.c create mode 100644 nyqsrc/multiseq.h create mode 100644 nyqsrc/nfilterkit.c create mode 100644 nyqsrc/nfilterkit.h create mode 100644 nyqsrc/nyq-osc-server.c create mode 100644 nyqsrc/nyq-osc-server.h create mode 100644 nyqsrc/nyx.c create mode 100644 nyqsrc/nyx.h create mode 100644 nyqsrc/oldyin.c create mode 100644 nyqsrc/oldyin.h create mode 100644 nyqsrc/phasevocoder.c create mode 100644 nyqsrc/phasevocoder.h create mode 100644 nyqsrc/probe.c create mode 100644 nyqsrc/probe.h create mode 100644 nyqsrc/pvshell.c create mode 100644 nyqsrc/pvshell.h create mode 100644 nyqsrc/resamp.c create mode 100644 nyqsrc/resamp.h create mode 100644 nyqsrc/resampv.c create mode 100644 nyqsrc/resampv.h create mode 100644 nyqsrc/rfftw.h create mode 100644 nyqsrc/samples.c create mode 100644 nyqsrc/samples.h create mode 100644 nyqsrc/seqext.c create mode 100644 nyqsrc/seqext.h create mode 100644 nyqsrc/seqfn.cl create mode 100644 nyqsrc/seqfn.wcl create mode 100644 nyqsrc/seqfnint.c create mode 100644 nyqsrc/seqfnint.lsp create mode 100644 nyqsrc/seqfnintdefs.h create mode 100644 nyqsrc/seqfnintptrs.h create mode 100644 nyqsrc/seqinterf.c create mode 100644 nyqsrc/seqinterf.h create mode 100644 nyqsrc/sliders.c create mode 100644 nyqsrc/sliders.h create mode 100644 nyqsrc/sndfail.c create mode 100644 nyqsrc/sndfmt.h create mode 100644 nyqsrc/sndfn.cl create mode 100644 nyqsrc/sndfn.wcl create mode 100644 nyqsrc/sndfnint.c create mode 100644 nyqsrc/sndfnint.lsp create mode 100644 nyqsrc/sndfnintdefs.h create mode 100644 nyqsrc/sndfnintptrs.h create mode 100644 nyqsrc/sndmax.c create mode 100644 nyqsrc/sndmax.h create mode 100644 nyqsrc/sndread.c create mode 100644 nyqsrc/sndread.h create mode 100644 nyqsrc/sndseq.c create mode 100644 nyqsrc/sndseq.h create mode 100644 nyqsrc/sndsliders.h create mode 100644 nyqsrc/sndwrite.c create mode 100644 nyqsrc/sndwrite.h create mode 100644 nyqsrc/sndwritepa.c create mode 100644 nyqsrc/sound.c create mode 100644 nyqsrc/sound.h create mode 100644 nyqsrc/stats.c create mode 100644 nyqsrc/stdefs.h create mode 100644 nyqsrc/trigger.c create mode 100644 nyqsrc/trigger.h create mode 100644 nyqsrc/yin.c create mode 100644 nyqsrc/yin.h create mode 100644 nyqstk/globals.h create mode 100644 nyqstk/include/ADSR.h create mode 100644 nyqstk/include/BandedWG.h create mode 100644 nyqstk/include/BiQuad.h create mode 100644 nyqstk/include/BowTable.h create mode 100644 nyqstk/include/Bowed.h create mode 100644 nyqstk/include/Chorus.h create mode 100644 nyqstk/include/Clarinet.h create mode 100644 nyqstk/include/Delay.h create mode 100644 nyqstk/include/DelayA.h create mode 100644 nyqstk/include/DelayL.h create mode 100644 nyqstk/include/Effect.h create mode 100644 nyqstk/include/Envelope.h create mode 100644 nyqstk/include/FileRead.h create mode 100644 nyqstk/include/FileWvIn.h create mode 100644 nyqstk/include/Filter.h create mode 100644 nyqstk/include/Flute.h create mode 100644 nyqstk/include/Function.h create mode 100644 nyqstk/include/Generator.h create mode 100644 nyqstk/include/Instrmnt.h create mode 100644 nyqstk/include/JCRev.h create mode 100644 nyqstk/include/JetTable.h create mode 100644 nyqstk/include/Mandolin.h create mode 100644 nyqstk/include/Modal.h create mode 100644 nyqstk/include/ModalBar.h create mode 100644 nyqstk/include/NRev.h create mode 100644 nyqstk/include/Noise.h create mode 100644 nyqstk/include/OnePole.h create mode 100644 nyqstk/include/OneZero.h create mode 100644 nyqstk/include/PRCRev.h create mode 100644 nyqstk/include/PitShift.h create mode 100644 nyqstk/include/PluckTwo.h create mode 100644 nyqstk/include/PoleZero.h create mode 100644 nyqstk/include/ReedTabl.h create mode 100644 nyqstk/include/ReedTable.h create mode 100644 nyqstk/include/SKINI.msg create mode 100644 nyqstk/include/Saxofony.h create mode 100644 nyqstk/include/SineWave.h create mode 100644 nyqstk/include/Sitar.h create mode 100644 nyqstk/include/Stk.h create mode 100644 nyqstk/include/WaveLoop.h create mode 100644 nyqstk/include/WvIn.h create mode 100644 nyqstk/instr.cpp create mode 100644 nyqstk/instr.h create mode 100644 nyqstk/src/ADSR.cpp create mode 100644 nyqstk/src/BandedWG.cpp create mode 100644 nyqstk/src/BiQuad.cpp create mode 100644 nyqstk/src/BowTable.cpp create mode 100644 nyqstk/src/Bowed.cpp create mode 100644 nyqstk/src/Chorus.cpp create mode 100644 nyqstk/src/Clarinet.cpp create mode 100644 nyqstk/src/Delay.cpp create mode 100644 nyqstk/src/DelayA.cpp create mode 100644 nyqstk/src/DelayL.cpp create mode 100644 nyqstk/src/Effect.cpp create mode 100644 nyqstk/src/Envelope.cpp create mode 100644 nyqstk/src/FileRead.cpp create mode 100644 nyqstk/src/FileWvIn.cpp create mode 100644 nyqstk/src/Filter.cpp create mode 100644 nyqstk/src/Flute.cpp create mode 100644 nyqstk/src/Function.cpp create mode 100644 nyqstk/src/Generator.cpp create mode 100644 nyqstk/src/Instrmnt.cpp create mode 100644 nyqstk/src/JCRev.cpp create mode 100644 nyqstk/src/JetTable.cpp create mode 100644 nyqstk/src/Mandolin.cpp create mode 100644 nyqstk/src/Modal.cpp create mode 100644 nyqstk/src/ModalBar.cpp create mode 100644 nyqstk/src/NRev.cpp create mode 100644 nyqstk/src/Noise.cpp create mode 100644 nyqstk/src/OnePole.cpp create mode 100644 nyqstk/src/OneZero.cpp create mode 100644 nyqstk/src/PRCRev.cpp create mode 100644 nyqstk/src/PitShift.cpp create mode 100644 nyqstk/src/PluckTwo.cpp create mode 100644 nyqstk/src/PoleZero.cpp create mode 100644 nyqstk/src/ReedTabl.cpp create mode 100644 nyqstk/src/ReedTable.cpp create mode 100644 nyqstk/src/Saxofony.cpp create mode 100644 nyqstk/src/SineWave.cpp create mode 100644 nyqstk/src/Sitar.cpp create mode 100644 nyqstk/src/Stk.cpp create mode 100644 nyqstk/src/WaveLoop.cpp create mode 100644 nyqstk/src/WvIn.cpp create mode 100644 nyqstk/stkinit.cpp create mode 100644 nyqstk/stkinit.h create mode 100644 nyqstk/stkint.cpp create mode 100644 nyqstk/stkint.h create mode 100644 nyquist.dsp create mode 100644 nyquist.dsw create mode 100644 nyquist.sln create mode 100644 nyquist.vcproj create mode 100644 nyqwin.dsp create mode 100644 nyqwin.vcproj create mode 100644 portaudio/COMPILING.DARWIN create mode 100644 portaudio/Doxyfile create mode 100644 portaudio/LICENSE.txt create mode 100644 portaudio/Makefile.in create mode 100644 portaudio/README.txt create mode 100644 portaudio/SConstruct create mode 100644 portaudio/V19-devel-readme.txt create mode 100644 portaudio/aclocal.m4 create mode 100644 portaudio/bindings/cpp/AUTHORS create mode 100644 portaudio/bindings/cpp/COPYING create mode 100644 portaudio/bindings/cpp/ChangeLog create mode 100644 portaudio/bindings/cpp/INSTALL create mode 100644 portaudio/bindings/cpp/Makefile.am create mode 100644 portaudio/bindings/cpp/Makefile.in create mode 100644 portaudio/bindings/cpp/NEWS create mode 100644 portaudio/bindings/cpp/README create mode 100644 portaudio/bindings/cpp/SConscript create mode 100644 portaudio/bindings/cpp/aclocal.m4 create mode 100644 portaudio/bindings/cpp/bin/Makefile.am create mode 100644 portaudio/bindings/cpp/bin/Makefile.in create mode 100644 portaudio/bindings/cpp/build/gnu/Makefile.in create mode 100644 portaudio/bindings/cpp/build/gnu/OUT_OF_DATE create mode 100644 portaudio/bindings/cpp/build/gnu/aclocal.m4 create mode 100644 portaudio/bindings/cpp/build/gnu/config.guess create mode 100644 portaudio/bindings/cpp/build/gnu/config.sub create mode 100644 portaudio/bindings/cpp/build/gnu/configure create mode 100644 portaudio/bindings/cpp/build/gnu/configure.ac create mode 100644 portaudio/bindings/cpp/build/gnu/install-sh create mode 100644 portaudio/bindings/cpp/build/vc6/devs_example.dsp create mode 100644 portaudio/bindings/cpp/build/vc6/devs_example.dsw create mode 100644 portaudio/bindings/cpp/build/vc6/sine_example.dsp create mode 100644 portaudio/bindings/cpp/build/vc6/sine_example.dsw create mode 100644 portaudio/bindings/cpp/build/vc6/static_library.dsp create mode 100644 portaudio/bindings/cpp/build/vc6/static_library.dsw create mode 100644 portaudio/bindings/cpp/build/vc7/OUT_OF_DATE create mode 100644 portaudio/bindings/cpp/build/vc7_1/devs_example.sln create mode 100644 portaudio/bindings/cpp/build/vc7_1/devs_example.vcproj create mode 100644 portaudio/bindings/cpp/build/vc7_1/sine_example.sln create mode 100644 portaudio/bindings/cpp/build/vc7_1/sine_example.vcproj create mode 100644 portaudio/bindings/cpp/build/vc7_1/static_library.sln create mode 100644 portaudio/bindings/cpp/build/vc7_1/static_library.vcproj create mode 100644 portaudio/bindings/cpp/configure create mode 100644 portaudio/bindings/cpp/configure.ac create mode 100644 portaudio/bindings/cpp/doc/Makefile.am create mode 100644 portaudio/bindings/cpp/doc/Makefile.in create mode 100644 portaudio/bindings/cpp/doc/README create mode 100644 portaudio/bindings/cpp/doc/config.doxy create mode 100644 portaudio/bindings/cpp/doc/config.doxy.linux create mode 100644 portaudio/bindings/cpp/example/devs.cxx create mode 100644 portaudio/bindings/cpp/example/sine.cxx create mode 100644 portaudio/bindings/cpp/include/Makefile.am create mode 100644 portaudio/bindings/cpp/include/Makefile.in create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/AsioDeviceAdapter.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/AutoSystem.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/BlockingStream.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/CFunCallbackStream.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/CallbackInterface.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/CallbackStream.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/CppFunCallbackStream.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/Device.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/DirectionSpecificStreamParameters.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/Exception.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/HostApi.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/InterfaceCallbackStream.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/MemFunCallbackStream.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/System.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx create mode 100644 portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx create mode 100644 portaudio/bindings/cpp/lib/Makefile.am create mode 100644 portaudio/bindings/cpp/lib/Makefile.in create mode 100644 portaudio/bindings/cpp/portaudiocpp.pc.in create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/Device.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/System.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx create mode 100644 portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx create mode 100644 portaudio/build/dev-cpp/Makefile-dll create mode 100644 portaudio/build/dev-cpp/Makefile-static create mode 100644 portaudio/build/dev-cpp/portaudio-dll.dev create mode 100644 portaudio/build/dev-cpp/portaudio-static.dev create mode 100644 portaudio/build/dev-cpp/readme.txt create mode 100644 portaudio/build/msvc/portaudio.def create mode 100644 portaudio/build/msvc/portaudio.dsp create mode 100644 portaudio/build/msvc/portaudio.dsw create mode 100644 portaudio/build/msvc/portaudio.sln create mode 100644 portaudio/build/msvc/portaudio.vcproj create mode 100644 portaudio/build/msvc/readme.txt create mode 100644 portaudio/build/scons/SConscript_common create mode 100644 portaudio/build/scons/SConscript_opts create mode 100644 portaudio/config.cache create mode 100644 portaudio/config.doxy create mode 100755 portaudio/config.guess create mode 100755 portaudio/config.sub create mode 100755 portaudio/configure create mode 100644 portaudio/configure.in create mode 100644 portaudio/depcomp create mode 100644 portaudio/doc/src/license.dox create mode 100644 portaudio/doc/src/mainpage.dox create mode 100644 portaudio/doc/src/srcguide.dox create mode 100644 portaudio/doc/utils/checkfiledocs.py create mode 100755 portaudio/fixdir.bat create mode 100755 portaudio/fixfile.bat create mode 100644 portaudio/include/pa_asio.h create mode 100644 portaudio/include/pa_jack.h create mode 100644 portaudio/include/pa_linux_alsa.h create mode 100644 portaudio/include/pa_mac_core.h create mode 100644 portaudio/include/pa_win_ds.h create mode 100644 portaudio/include/pa_win_waveformat.h create mode 100644 portaudio/include/pa_win_wmme.h create mode 100644 portaudio/include/portaudio.h create mode 100644 portaudio/index.html create mode 100755 portaudio/install-sh create mode 100644 portaudio/ltmain.sh create mode 100644 portaudio/missing create mode 100644 portaudio/pablio/README.txt create mode 100644 portaudio/pablio/pablio.c create mode 100644 portaudio/pablio/pablio.def create mode 100644 portaudio/pablio/pablio.h create mode 100644 portaudio/pablio/test_rw.c create mode 100644 portaudio/pablio/test_rw_echo.c create mode 100644 portaudio/pablio/test_w_saw.c create mode 100644 portaudio/pablio/test_w_saw8.c create mode 100644 portaudio/portaudio-2.0.pc.in create mode 100644 portaudio/src/SConscript create mode 100644 portaudio/src/common/pa_allocation.c create mode 100644 portaudio/src/common/pa_allocation.h create mode 100644 portaudio/src/common/pa_converters.c create mode 100644 portaudio/src/common/pa_converters.h create mode 100644 portaudio/src/common/pa_cpuload.c create mode 100644 portaudio/src/common/pa_cpuload.h create mode 100644 portaudio/src/common/pa_debugprint.c create mode 100644 portaudio/src/common/pa_debugprint.h create mode 100644 portaudio/src/common/pa_dither.c create mode 100644 portaudio/src/common/pa_dither.h create mode 100644 portaudio/src/common/pa_endianness.h create mode 100644 portaudio/src/common/pa_front.c create mode 100644 portaudio/src/common/pa_hostapi.h create mode 100644 portaudio/src/common/pa_process.c create mode 100644 portaudio/src/common/pa_process.h create mode 100644 portaudio/src/common/pa_ringbuffer.c create mode 100644 portaudio/src/common/pa_ringbuffer.h create mode 100644 portaudio/src/common/pa_skeleton.c create mode 100644 portaudio/src/common/pa_stream.c create mode 100644 portaudio/src/common/pa_stream.h create mode 100644 portaudio/src/common/pa_trace.c create mode 100644 portaudio/src/common/pa_trace.h create mode 100644 portaudio/src/common/pa_types.h create mode 100644 portaudio/src/common/pa_util.h create mode 100644 portaudio/src/hostapi/alsa/pa_linux_alsa.c create mode 100644 portaudio/src/hostapi/asihpi/pa_linux_asihpi.c create mode 100644 portaudio/src/hostapi/asio/ASIO-README.txt create mode 100644 portaudio/src/hostapi/asio/Callback_adaptation_.pdf create mode 100644 portaudio/src/hostapi/asio/Pa_ASIO.pdf create mode 100644 portaudio/src/hostapi/asio/iasiothiscallresolver.cpp create mode 100644 portaudio/src/hostapi/asio/iasiothiscallresolver.h create mode 100644 portaudio/src/hostapi/asio/pa_asio.cpp create mode 100644 portaudio/src/hostapi/coreaudio/notes.txt create mode 100644 portaudio/src/hostapi/coreaudio/pa_mac_core.c create mode 100644 portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c create mode 100644 portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h create mode 100644 portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h create mode 100644 portaudio/src/hostapi/coreaudio/pa_mac_core_old.c create mode 100644 portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c create mode 100644 portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.h create mode 100644 portaudio/src/hostapi/dsound/pa_win_ds.c create mode 100644 portaudio/src/hostapi/dsound/pa_win_ds_dynlink.c create mode 100644 portaudio/src/hostapi/dsound/pa_win_ds_dynlink.h create mode 100644 portaudio/src/hostapi/jack/pa_jack.c create mode 100644 portaudio/src/hostapi/oss/low_latency_tip.txt create mode 100644 portaudio/src/hostapi/oss/pa_unix_oss.c create mode 100644 portaudio/src/hostapi/oss/recplay.c create mode 100644 portaudio/src/hostapi/wasapi/pa_win_wasapi.cpp create mode 100644 portaudio/src/hostapi/wdmks/pa_win_wdmks.c create mode 100644 portaudio/src/hostapi/wdmks/readme.txt create mode 100644 portaudio/src/hostapi/wmme/pa_win_wmme.c create mode 100644 portaudio/src/os/mac_osx/pa_mac_hostapis.c create mode 100644 portaudio/src/os/unix/pa_unix_hostapis.c create mode 100644 portaudio/src/os/unix/pa_unix_util.c create mode 100644 portaudio/src/os/unix/pa_unix_util.h create mode 100644 portaudio/src/os/win/pa_win_hostapis.c create mode 100644 portaudio/src/os/win/pa_win_util.c create mode 100644 portaudio/src/os/win/pa_win_waveformat.c create mode 100644 portaudio/src/os/win/pa_win_wdmks_utils.c create mode 100644 portaudio/src/os/win/pa_win_wdmks_utils.h create mode 100644 portaudio/src/os/win/pa_x86_plain_converters.c create mode 100644 portaudio/src/os/win/pa_x86_plain_converters.h create mode 100644 portaudio/test/README.txt create mode 100644 portaudio/test/debug_convert.c create mode 100644 portaudio/test/debug_dither_calc.c create mode 100644 portaudio/test/debug_dual.c create mode 100644 portaudio/test/debug_multi_in.c create mode 100644 portaudio/test/debug_multi_out.c create mode 100644 portaudio/test/debug_record.c create mode 100644 portaudio/test/debug_record_reuse.c create mode 100644 portaudio/test/debug_sine.c create mode 100644 portaudio/test/debug_sine_amp.c create mode 100644 portaudio/test/debug_sine_formats.c create mode 100644 portaudio/test/debug_srate.c create mode 100644 portaudio/test/debug_test1.c create mode 100644 portaudio/test/pa_devs.c create mode 100644 portaudio/test/pa_fuzz.c create mode 100644 portaudio/test/pa_minlat.c create mode 100644 portaudio/test/paqa_devs.c create mode 100644 portaudio/test/paqa_errs.c create mode 100644 portaudio/test/patest1.c create mode 100644 portaudio/test/patest_buffer.c create mode 100644 portaudio/test/patest_callbackstop.c create mode 100644 portaudio/test/patest_clip.c create mode 100644 portaudio/test/patest_dither.c create mode 100644 portaudio/test/patest_dsound_surround.c create mode 100644 portaudio/test/patest_hang.c create mode 100644 portaudio/test/patest_in_overflow.c create mode 100644 portaudio/test/patest_latency.c create mode 100644 portaudio/test/patest_leftright.c create mode 100644 portaudio/test/patest_longsine.c create mode 100644 portaudio/test/patest_many.c create mode 100644 portaudio/test/patest_maxsines.c create mode 100644 portaudio/test/patest_mono.c create mode 100644 portaudio/test/patest_mono_asio_channel_select.c create mode 100644 portaudio/test/patest_multi_sine.c create mode 100644 portaudio/test/patest_out_underflow.c create mode 100644 portaudio/test/patest_pink.c create mode 100644 portaudio/test/patest_prime.c create mode 100644 portaudio/test/patest_read_record.c create mode 100644 portaudio/test/patest_read_write_wire.c create mode 100644 portaudio/test/patest_record.c create mode 100644 portaudio/test/patest_ringmix.c create mode 100644 portaudio/test/patest_saw.c create mode 100644 portaudio/test/patest_sine.c create mode 100644 portaudio/test/patest_sine8.c create mode 100644 portaudio/test/patest_sine_channelmaps.c create mode 100644 portaudio/test/patest_sine_formats.c create mode 100644 portaudio/test/patest_sine_time.c create mode 100644 portaudio/test/patest_start_stop.c create mode 100644 portaudio/test/patest_stop.c create mode 100644 portaudio/test/patest_stop_playout.c create mode 100644 portaudio/test/patest_sync.c create mode 100644 portaudio/test/patest_timing.c create mode 100644 portaudio/test/patest_toomanysines.c create mode 100644 portaudio/test/patest_two_rates.c create mode 100644 portaudio/test/patest_underflow.c create mode 100644 portaudio/test/patest_wire.c create mode 100644 portaudio/test/patest_wmme_surround.c create mode 100644 portaudio/test/patest_write_sine.c create mode 100644 portaudio/test/patest_write_stop.c create mode 100644 portaudio/testcvs/changeme.txt create mode 100644 portaudio_test/portaudio_test.dsp create mode 100644 portaudio_test/syncwrite.c create mode 100644 release.bat create mode 100644 releasenyqide.bat create mode 100644 releasenyqwin.bat create mode 100644 runtime/dspprims.lsp create mode 100644 runtime/envelopes.lsp create mode 100644 runtime/equalizer.lsp create mode 100644 runtime/evalenv.lsp create mode 100644 runtime/fileio.lsp create mode 100644 runtime/follow.lsp create mode 100644 runtime/init.lsp create mode 100644 runtime/misc.lsp create mode 100644 runtime/nyinit.lsp create mode 100644 runtime/nyqmisc.lsp create mode 100644 runtime/nyquist-plot.txt create mode 100644 runtime/nyquist.lsp create mode 100644 runtime/printrec.lsp create mode 100644 runtime/profile.lsp create mode 100644 runtime/rawwaves/mand1.raw create mode 100644 runtime/rawwaves/mand10.raw create mode 100644 runtime/rawwaves/mand11.raw create mode 100644 runtime/rawwaves/mand12.raw create mode 100644 runtime/rawwaves/mand2.raw create mode 100644 runtime/rawwaves/mand3.raw create mode 100644 runtime/rawwaves/mand4.raw create mode 100644 runtime/rawwaves/mand5.raw create mode 100644 runtime/rawwaves/mand6.raw create mode 100644 runtime/rawwaves/mand7.raw create mode 100644 runtime/rawwaves/mand8.raw create mode 100644 runtime/rawwaves/mand9.raw create mode 100644 runtime/rawwaves/mandpluk.raw create mode 100644 runtime/rawwaves/marmstk1.raw create mode 100644 runtime/rawwaves/sinewave.raw create mode 100644 runtime/sal-parse.lsp create mode 100644 runtime/sal.lsp create mode 100644 runtime/seq.lsp create mode 100644 runtime/seqfnint.lsp create mode 100644 runtime/seqmidi.lsp create mode 100644 runtime/sndfnint.lsp create mode 100644 runtime/stk.lsp create mode 100644 runtime/test.lsp create mode 100644 runtime/upic.sal create mode 100644 runtime/xlinit.lsp create mode 100644 runtime/xm.lsp create mode 100644 snd/audio.c create mode 100644 snd/audiolinux.c create mode 100644 snd/audiomac.c create mode 100644 snd/audiomac.h create mode 100644 snd/audionone.c create mode 100644 snd/audiooss.c create mode 100644 snd/audiopa.c create mode 100644 snd/audiors6k.c create mode 100644 snd/audiosgi.c create mode 100644 snd/audiowin32.c create mode 100644 snd/audiowin32.h create mode 100644 snd/convert.c create mode 100644 snd/ieeecvt.c create mode 100644 snd/ieeecvt.h create mode 100644 snd/rs6kplaydemo.c create mode 100644 snd/snd.c create mode 100644 snd/snd.h create mode 100644 snd/snd.htm create mode 100644 snd/snd.txt create mode 100644 snd/sndconfig.h create mode 100644 snd/sndcvt.c create mode 100644 snd/sndfaillinux.c create mode 100644 snd/sndfailwin32.c create mode 100644 snd/sndfileio.h create mode 100644 snd/sndfreebsd.h create mode 100644 snd/sndhead.h create mode 100644 snd/sndheader.c create mode 100644 snd/sndheader.h create mode 100644 snd/sndio.c create mode 100644 snd/sndlinux.c create mode 100644 snd/sndlinux.h create mode 100644 snd/sndmac.c create mode 100644 snd/sndmac.h create mode 100644 snd/sndnt.h create mode 100644 snd/sndrs6k.h create mode 100644 snd/sndsystem.c create mode 100644 snd/sndsystem.h create mode 100644 snd/sndsystemmac.h create mode 100644 snd/sndwin32.c create mode 100644 snd/sndwin32.h create mode 100644 snd/sndwrite.h create mode 100644 snd/wxsnd.cpp create mode 100644 snd/wxsnd.h create mode 100644 sys/mac/MacAE.c create mode 100644 sys/mac/MacCommandWin.c create mode 100644 sys/mac/MacCommandWin.h create mode 100644 sys/mac/MacDrag.h create mode 100644 sys/mac/MacFileUtils.c create mode 100644 sys/mac/MacFileUtils.h create mode 100644 sys/mac/MacGlobals.h create mode 100644 sys/mac/MacHandleEv.c create mode 100644 sys/mac/MacHandleEv.h create mode 100644 sys/mac/README.txt create mode 100644 sys/mac/macaboutbox.c create mode 100644 sys/mac/macaboutbox.h create mode 100644 sys/mac/macdrag.c create mode 100644 sys/mac/macfun.c create mode 100644 sys/mac/macint.c create mode 100644 sys/mac/macint.h create mode 100644 sys/mac/macptrs.h create mode 100644 sys/mac/macstuff.c create mode 100644 sys/mac/macstuff.h create mode 100644 sys/mac/sndsystem.h create mode 100644 sys/mac/switches.h create mode 100644 sys/mac/system.lsp create mode 100644 sys/mac/xlextstart.c create mode 100644 sys/unix/README.txt create mode 100644 sys/unix/alsa/Makefile create mode 100644 sys/unix/alsa/system.lsp create mode 100644 sys/unix/cmu/backup.script create mode 100644 sys/unix/cmu/tar.script create mode 100644 sys/unix/cmu/update.lsp create mode 100644 sys/unix/io.c create mode 100644 sys/unix/io.h create mode 100644 sys/unix/next/Makefile create mode 100644 sys/unix/next/system.lsp create mode 100644 sys/unix/nonalsa/Makefile create mode 100644 sys/unix/nonalsa/system.lsp create mode 100644 sys/unix/osstuff.c create mode 100755 sys/unix/osx/run create mode 100644 sys/unix/osx/system.lsp create mode 100644 sys/unix/pl create mode 100644 sys/unix/pmax/Makefile create mode 100644 sys/unix/pmax/system.lsp create mode 100644 sys/unix/rs6k/Makefile create mode 100644 sys/unix/rs6k/plotscript create mode 100644 sys/unix/rs6k/system.lsp create mode 100644 sys/unix/setup create mode 100644 sys/unix/sgi/Makefile create mode 100644 sys/unix/sgi/system.lsp create mode 100644 sys/unix/sndsystem.h create mode 100644 sys/unix/sparc/Makefile create mode 100644 sys/unix/sparc/system.lsp create mode 100644 sys/unix/switches.h create mode 100644 sys/unix/term.c create mode 100644 sys/unix/term.h create mode 100644 sys/unix/termtest.c create mode 100644 sys/win/README.txt create mode 100644 sys/win/msvc/sndsystem.h create mode 100644 sys/win/msvc/stdint.h create mode 100644 sys/win/msvc/switches.h create mode 100644 sys/win/msvc/system.lsp create mode 100644 sys/win/msvc/winfun.c create mode 100644 sys/win/msvc/winfun.h create mode 100644 sys/win/msvc/winstuff.c create mode 100644 sys/win/nyqrelide.iss create mode 100644 sys/win/wingui/button.h create mode 100644 sys/win/wingui/cppext.h create mode 100644 sys/win/wingui/longque.cpp create mode 100644 sys/win/wingui/longque.h create mode 100644 sys/win/wingui/nycon.ico create mode 100644 sys/win/wingui/resource.h create mode 100644 sys/win/wingui/slider.h create mode 100644 sys/win/wingui/textio.cpp create mode 100644 sys/win/wingui/textio.h create mode 100644 sys/win/wingui/typein.h create mode 100644 sys/win/wingui/winguistuff.c create mode 100644 sys/win/wingui/winmain.aps create mode 100644 sys/win/wingui/winmain.cpp create mode 100644 sys/win/wingui/winmain.h create mode 100644 sys/win/wingui/winmain.rc create mode 100644 sys/win/wingui/winmain2.h create mode 100644 sys/win/wingui/xlextstart.c create mode 100644 sys/win/wingui/xlispfns.c create mode 100644 sys/win/wingui/xlispfns.h create mode 100644 test/alex.lsp create mode 100644 test/alpass.lsp create mode 100644 test/arraystream.lsp create mode 100644 test/articulator1.txt create mode 100644 test/audio.lsp create mode 100644 test/cnvl.lsp create mode 100644 test/comb.lsp create mode 100644 test/convolve.lsp create mode 100644 test/delaytest.lsp create mode 100644 test/envtest.lsp create mode 100644 test/eq.lsp create mode 100644 test/fft.lsp create mode 100644 test/fmfb-test.lsp create mode 100644 test/fmfbv-test.lsp create mode 100644 test/gab.lsp create mode 100644 test/gatetest.lsp create mode 100644 test/gr.lsp create mode 100644 test/ifft.lsp create mode 100644 test/ifftnt.lsp create mode 100644 test/init.lsp create mode 100644 test/linux-segfault.lsp create mode 100644 test/midi2.lsp create mode 100644 test/ms2.lsp create mode 100644 test/multiseq.lsp create mode 100644 test/natbug.lsp create mode 100644 test/nonewline.lsp create mode 100644 test/overwrite.lsp create mode 100644 test/product.lsp create mode 100644 test/rbd.lsp create mode 100644 test/readme create mode 100644 test/s-add-to.lsp create mode 100644 test/save-float.lsp create mode 100644 test/seqmiditest.lsp create mode 100644 test/shape.lsp create mode 100644 test/snd-fetch-array.lsp create mode 100644 test/sr.lsp create mode 100644 test/stktest.lsp create mode 100644 test/str.lsp create mode 100644 test/temp.gio create mode 100644 test/temp2.gio create mode 100644 test/temp3.gio create mode 100644 test/test.gio create mode 100644 test/tp.lsp create mode 100644 test/trigger.lsp create mode 100644 test/variable-resample.lsp create mode 100644 test/warp.lsp create mode 100644 todo.txt create mode 100644 tran/abs.alg create mode 100644 tran/abs.c create mode 100644 tran/abs.h create mode 100644 tran/allpoles.alg create mode 100644 tran/allpoles.c create mode 100644 tran/allpoles.h create mode 100644 tran/alpass.alg create mode 100644 tran/alpass.c create mode 100644 tran/alpass.h create mode 100644 tran/alpasscv.alg create mode 100644 tran/alpasscv.c create mode 100644 tran/alpasscv.h create mode 100644 tran/alpassvc.alg create mode 100644 tran/alpassvc.c create mode 100644 tran/alpassvc.h create mode 100644 tran/alpassvv.alg create mode 100644 tran/alpassvv.c create mode 100644 tran/alpassvv.h create mode 100644 tran/amosc.alg create mode 100644 tran/amosc.c create mode 100644 tran/amosc.h create mode 100644 tran/areson.alg create mode 100644 tran/areson.c create mode 100644 tran/areson.h create mode 100644 tran/aresoncv.alg create mode 100644 tran/aresoncv.c create mode 100644 tran/aresoncv.h create mode 100644 tran/aresonvc.alg create mode 100644 tran/aresonvc.c create mode 100644 tran/aresonvc.h create mode 100644 tran/aresonvv.alg create mode 100644 tran/aresonvv.c create mode 100644 tran/aresonvv.h create mode 100644 tran/atone.alg create mode 100644 tran/atone.c create mode 100644 tran/atone.h create mode 100644 tran/atonev.alg create mode 100644 tran/atonev.c create mode 100644 tran/atonev.h create mode 100644 tran/biquadfilt.alg create mode 100644 tran/biquadfilt.c create mode 100644 tran/biquadfilt.h create mode 100644 tran/buzz.alg create mode 100644 tran/buzz.c create mode 100644 tran/buzz.h create mode 100644 tran/chase.alg create mode 100644 tran/chase.c create mode 100644 tran/chase.h create mode 100644 tran/clip.alg create mode 100644 tran/clip.c create mode 100644 tran/clip.h create mode 100644 tran/congen.alg create mode 100644 tran/congen.c create mode 100644 tran/congen.h create mode 100644 tran/const.alg create mode 100644 tran/const.c create mode 100644 tran/const.h create mode 100644 tran/convolve.alg create mode 100644 tran/coterm.alg create mode 100644 tran/coterm.c create mode 100644 tran/coterm.h create mode 100644 tran/delay.alg create mode 100644 tran/delaycc.alg create mode 100644 tran/delaycc.c create mode 100644 tran/delaycc.h create mode 100644 tran/delaycv.alg create mode 100644 tran/delaycv.c create mode 100644 tran/delaycv.h create mode 100644 tran/downproto.alg create mode 100644 tran/eqbandv.alg create mode 100644 tran/eqbandvvv.alg create mode 100644 tran/eqbandvvv.c create mode 100644 tran/eqbandvvv.h create mode 100644 tran/exp.alg create mode 100644 tran/exp.c create mode 100644 tran/exp.h create mode 100644 tran/exprel.alg create mode 100644 tran/fmfb.alg create mode 100644 tran/fmfb.c create mode 100644 tran/fmfb.h create mode 100644 tran/fmfbv.alg create mode 100644 tran/fmfbv.c create mode 100644 tran/fmfbv.h create mode 100644 tran/fmosc.alg create mode 100644 tran/fmosc.c create mode 100644 tran/fmosc.h create mode 100644 tran/follow.alg create mode 100644 tran/follow.c create mode 100644 tran/follow.h create mode 100644 tran/fromarraystream.alg create mode 100644 tran/fromarraystream.c create mode 100644 tran/fromarraystream.h create mode 100644 tran/fromobject.alg create mode 100644 tran/fromobject.c create mode 100644 tran/fromobject.h create mode 100644 tran/gate.alg create mode 100644 tran/gate.c create mode 100644 tran/gate.h create mode 100644 tran/ifft-old.alg create mode 100644 tran/ifft.alg create mode 100644 tran/ifft.c create mode 100644 tran/ifft.h create mode 100644 tran/init.lsp create mode 100644 tran/innerloop.lsp create mode 100644 tran/instrbanded.alg create mode 100644 tran/instrbanded.c create mode 100644 tran/instrbanded.h create mode 100644 tran/instrbow.alg create mode 100644 tran/instrbow.c create mode 100644 tran/instrbow.h create mode 100644 tran/instrbowedfreq.alg create mode 100644 tran/instrbowedfreq.c create mode 100644 tran/instrbowedfreq.h create mode 100644 tran/instrclar.alg create mode 100644 tran/instrclar.c create mode 100644 tran/instrclar.h create mode 100644 tran/instrclarall.alg create mode 100644 tran/instrclarall.c create mode 100644 tran/instrclarall.h create mode 100644 tran/instrclarfreq.alg create mode 100644 tran/instrclarfreq.c create mode 100644 tran/instrclarfreq.h create mode 100644 tran/instrflute.alg create mode 100644 tran/instrflute.c create mode 100644 tran/instrflute.h create mode 100644 tran/instrfluteall.alg create mode 100644 tran/instrfluteall.c create mode 100644 tran/instrfluteall.h create mode 100644 tran/instrflutefreq.alg create mode 100644 tran/instrflutefreq.c create mode 100644 tran/instrflutefreq.h create mode 100644 tran/instrmandolin.alg create mode 100644 tran/instrmandolin.c create mode 100644 tran/instrmandolin.h create mode 100644 tran/instrmodalbar.alg create mode 100644 tran/instrmodalbar.c create mode 100644 tran/instrmodalbar.h create mode 100644 tran/instrsax.alg create mode 100644 tran/instrsax.c create mode 100644 tran/instrsax.h create mode 100644 tran/instrsaxall.alg create mode 100644 tran/instrsaxall.c create mode 100644 tran/instrsaxall.h create mode 100644 tran/instrsaxfreq.alg create mode 100644 tran/instrsaxfreq.c create mode 100644 tran/instrsaxfreq.h create mode 100644 tran/instrsitar.alg create mode 100644 tran/instrsitar.c create mode 100644 tran/instrsitar.h create mode 100644 tran/integrate.alg create mode 100644 tran/integrate.c create mode 100644 tran/integrate.h create mode 100644 tran/log.alg create mode 100644 tran/log.c create mode 100644 tran/log.h create mode 100644 tran/lpreson.alg create mode 100644 tran/lpreson.c create mode 100644 tran/lpreson.h create mode 100644 tran/maxv.alg create mode 100644 tran/maxv.c create mode 100644 tran/maxv.h create mode 100644 tran/offset.alg create mode 100644 tran/offset.c create mode 100644 tran/offset.h create mode 100644 tran/oneshot.alg create mode 100644 tran/oneshot.c create mode 100644 tran/oneshot.h create mode 100644 tran/osc.alg create mode 100644 tran/osc.c create mode 100644 tran/osc.h create mode 100644 tran/partial.alg create mode 100644 tran/partial.c create mode 100644 tran/partial.h create mode 100644 tran/pluck.alg create mode 100644 tran/pluck.c create mode 100644 tran/pluck.h create mode 100644 tran/prod.alg create mode 100644 tran/prod.c create mode 100644 tran/prod.h create mode 100644 tran/pwl.alg create mode 100644 tran/pwl.c create mode 100644 tran/pwl.h create mode 100644 tran/quantize.alg create mode 100644 tran/quantize.c create mode 100644 tran/quantize.h create mode 100644 tran/recip.alg create mode 100644 tran/recip.c create mode 100644 tran/recip.h create mode 100644 tran/reson.alg create mode 100644 tran/reson.c create mode 100644 tran/reson.h create mode 100644 tran/resoncv.alg create mode 100644 tran/resoncv.c create mode 100644 tran/resoncv.h create mode 100644 tran/resonvc.alg create mode 100644 tran/resonvc.c create mode 100644 tran/resonvc.h create mode 100644 tran/resonvv.alg create mode 100644 tran/resonvv.c create mode 100644 tran/resonvv.h create mode 100644 tran/sampler.alg create mode 100644 tran/sampler.c create mode 100644 tran/sampler.h create mode 100644 tran/scale.alg create mode 100644 tran/scale.c create mode 100644 tran/scale.h create mode 100644 tran/shape.alg create mode 100644 tran/shape.c create mode 100644 tran/shape.h create mode 100644 tran/sine.alg create mode 100644 tran/sine.c create mode 100644 tran/sine.h create mode 100644 tran/siosc.alg create mode 100644 tran/siosc.c create mode 100644 tran/siosc.h create mode 100644 tran/slope.alg create mode 100644 tran/slope.c create mode 100644 tran/slope.h create mode 100644 tran/sqrt.alg create mode 100644 tran/sqrt.c create mode 100644 tran/sqrt.h create mode 100644 tran/stkchorus.alg create mode 100644 tran/stkchorus.c create mode 100644 tran/stkchorus.h create mode 100644 tran/stkpitshift.alg create mode 100644 tran/stkpitshift.c create mode 100644 tran/stkpitshift.h create mode 100644 tran/stkrev.alg create mode 100644 tran/stkrev.c create mode 100644 tran/stkrev.h create mode 100644 tran/tapf.alg create mode 100644 tran/tapf.c create mode 100644 tran/tapf.h create mode 100644 tran/tapv.alg create mode 100644 tran/tapv.c create mode 100644 tran/tapv.h create mode 100644 tran/tone.alg create mode 100644 tran/tone.c create mode 100644 tran/tone.h create mode 100644 tran/tonev.alg create mode 100644 tran/tonev.c create mode 100644 tran/tonev.h create mode 100644 tran/translate-stk.lsp create mode 100644 tran/translate.lsp create mode 100644 tran/upsample.alg create mode 100644 tran/upsample.c create mode 100644 tran/upsample.h create mode 100644 tran/white.alg create mode 100644 tran/white.c create mode 100644 tran/white.h create mode 100644 tran/writemake.lsp create mode 100644 tran/writesusp.lsp create mode 100644 tran/writetoss.lsp create mode 100644 xlisp/extern.c create mode 100644 xlisp/extern.h create mode 100644 xlisp/osdefs.h create mode 100644 xlisp/osptrs.h create mode 100644 xlisp/path.c create mode 100644 xlisp/xlbfun.c create mode 100644 xlisp/xlcont.c create mode 100644 xlisp/xldbug.c create mode 100644 xlisp/xldmem.c create mode 100644 xlisp/xldmem.h create mode 100644 xlisp/xleval.c create mode 100644 xlisp/xlfio.c create mode 100644 xlisp/xlftab.c create mode 100644 xlisp/xlglob.c create mode 100644 xlisp/xlimage.c create mode 100644 xlisp/xlinit.c create mode 100644 xlisp/xlio.c create mode 100644 xlisp/xlisp.c create mode 100644 xlisp/xlisp.h create mode 100644 xlisp/xljump.c create mode 100644 xlisp/xllist.c create mode 100644 xlisp/xlmath.c create mode 100644 xlisp/xlobj.c create mode 100644 xlisp/xlpp.c create mode 100644 xlisp/xlprin.c create mode 100644 xlisp/xlread.c create mode 100644 xlisp/xlstr.c create mode 100644 xlisp/xlsubr.c create mode 100644 xlisp/xlsym.c create mode 100644 xlisp/xlsys.c diff --git a/Readme.txt b/Readme.txt new file mode 100644 index 0000000..a1a36e9 --- /dev/null +++ b/Readme.txt @@ -0,0 +1,231 @@ +README file for Nyquist Version 3.05 +13 Mar 2011 +Roger B. Dannenberg + +LICENSE: see license.txt +WEB SITE: http://www.cs.cmu.edu/~music/nyquist + +INSTALLING NYQUIST +==================== +You can download pre-compiled versions for Windows and OS X. + +You can compile Nyquist from sources for Windows, OS X, linux, and +other versions of Unix. For details, see one of these files: + - sys/win/README.txt + - sys/mac/README.txt + - sys/unix/README.txt + + +IMPLEMENTATION STATUS +===================== + +Version 3.05 provides: + New "UPIC Editor" window in NyquistIDE + Fix to escape backslashes in default windows directory + Fix to other problems with Preferences + Arpeggiator example in nyquist/demos + +Version 3.04 provides: + Updates to libraries, including liblo and PortAudio + Documentation uses both syntax SAL and Lisp syntax + Some STK instruments have been added + Build files modified to make 32-bit code even on 64-bit + architectures (Nyquist only runs in 32-bit mode) +Version 3.03 provides: + Bug fix to Markov pattern generator (see make-markov). + Update to current (24-feb-09) liblo library. + Slight change to license.txt to comply wiht two LGPL + library licenses: libsndfile and liblo. + score-sort can sort very big scores now using iterative + merge sort +Version 3.02 provides: + Uses libsndfile and recent version of portaudio. + Many bug fixes. + Support & compatibility for Algorithmic Composition (to appear) +Version 3.01 provides: + Feedback FM: see fmfb, snd-fmfb and snd-fmfbv + fixed help functions and internal browser window + Documentation mostly using SAL syntax now +Version 3.00 provides: + First release supporting SAL syntax + Major revision to documentation (but more to come) + Bug fixes for sustain transformation + Many new STK instruments ported by Pedro Morales + Pedro's sdl music input language +Version 2.38 provides: + improved PWL editor + improved preferences dialog + bug fixes in Equalizer editor + additional documentation for demos/plight/drums.lsp + option click or right click on completion list to get help + manual can be displayed in an internal window in jNyqIDE +Version 2.37 provides: + fix for byte order on Mac PPC that prevented pianosyn.lsp from loading +Version 2.36 provides: + cross-platform browser launching in jNyqIDE + fix search path set by jNyqIDE (OS X-related bug introduced in 2.35) + fix bug in slider update code on OS X +Version 2.35 provides: + fix for Open Sound Control under Windows/jNyqIDE + other minor jNyqIDE fixes +Version 2.34 provides: + fix to ^U (send selection to Nyquist) in jNyqIDE + default sound file path for Mac OS X is /tmp + Nyquist exits when EOF detected -- try to make orphans abort +Version 2.33 provides: + additional documentation for Open Sound Control + interface and utility programs +Version 2.32 provides: + envelope editor in jNyqIDE + EQ editor in jNyqIDE + score editor in jNyqIDE + slider support in Nyquist + OSC (Open Sound Control) interface + OSC test program and serial-to-OSC program + drum machine (as separate download) + jNyqIDE has pop-up menus and per-file menu bars +Version 2.31 provides: + new compositional algorithm support in xm.lsp + many bug fixes + MiniMoog emulator + spatialization libraries + sound reversal functions + Dolby Surround encode/decode +Version 2.30 provides: + many many changes, bug fixes, enhancements + new Java-based IDE: jnyqide + LPC analysis/synthesis + uses PortAudio for audio I/O + changes for Debian Linux compatibility + new examples in demos + new documentation and html files +Version 2.29 provides: + new functions: snd-alpassvc, sndalpassvv, snd-eqbandvvv + corresponding high-level functions in Nyquist + new licenses for both Nyquist and XLISP + new NyqIDE implementation + fixed BUZZ function + various bug and documentation fixes +Version 2.28 provides: + include indx.html in doc folder (in files.txt) + fixed compute-default-sound-file in nyquist.lsp to + compute appropriate extension (.wav, .aif) + more code to automate win32 releases +Version 2.27 provides: + makefile.lsp now generates sndfn.wcl & sndfn.cl + fix to include snd-pluck and some others omittted from 2.26 +Version 2.26 provides: + bug fix in sampler, negative frequency handling + guard against out-of-order events in TIMED-SEQ + added FMLFO, an lfo with frequency modulation + added SND-SQRT, S-SQRT, SND-ABS, S-ABS functions + new NyqIDE version with S-PLOT function (!) + NyqIDE has better parsing for paren balancing + NyqIDE upgrade to WindowsXP and Delphi 6 + NyqIDE increases input string length maximum + NyqIDE prompts on save conflict + added voice-synthesis demo from Eduardo Miranda + corrected absolute path in demos/pmorales/e2.lsp + minor documentation and indexing improvements + pointer to demo docs goes on start menu now +Version 2.25 provides: + new way to provide search path: set *SEARCH-PATH* to a string, + e.g. (SETF *SEARCH-PATH* + "C:/program files/nyquist/runtime,c:/program files/nyquist/lib") + allowing Nyquist to be run without setting registry. +Version 2.24 provides: + text editing for command lines in Linux version +Version 2.23 provides: + bug fix in (current-path) for Mac + fixes to some Mac sources corrupted in 2.22 +Version 2.22 provides: + documentation (HTML) included in release now + bug fix for Mac console output exceeding 32K limit + protection from playing very high sample rates in Win32 + (crashes in Windows MME library!) + change s-save to take :endian rather than :swap parameter + pianosyn.lsp runs on the Mac now + demos/examples.lsp generates audio with "normal" sample rates +Version 2.21 provides: + s-plot uses gnu-plot in Linux + separation from CVS -- I just couldn't keep beating my head + against the wall +Version 2.20 provides: + improved Macintosh support +Version 2.19 provides: + integration of Macintosh code (from v2.12) + addition of PLUCK and BUZZ synthesis functions +Version 2.18 provides: + bug fix in midifile read routine under Linux +Version 2.17 provides: + bug fix for long line input under linux and windows + biquad filters + hzosc osc-tri osc-saw osc-pulse -- new oscillator variants + bug fix for reading in non-AIFF files with 'FORM' headings + extension to s-read to support explicit byte-swap parameter +Version 2.16 provides: + bug fix in tables (lookup oscillators and other functions) + Windows GUI version of Nyquist +Version 2.15 provides: + port to Linux +Version 2.5 provides: + more signal processing functions +Version 2.2 provides: + ports to more systems including Win32 (Win95 and NT) + bug fixes + more signal processing functions + improved sound I/O subsystem +Version 2.1 provides: + bug fixes + documentation and code for user extensions +Version 2.0 provides: + continuous time warps + many more functions + bug fixes + +The distribution may contain sources for Nyquist. If not, +you got the runtime distribution, and there is a source version +available. + +A number of "source" files are machine generated, including: +- many .c and .h files that implement signal processing functions. + These are generated by translation system that converts + .alg files to .c and .h files. .alg files give high-level + descriptions of DSP algorithms. +- Makefile.* is generated by "makefile.lsp". + +The status is: + +System Status + +RS6K = RS6000, AIX untested, but used to work +NEXT = NeXT 3.0 (Cube) untested, but worked fine on a previous version +SGI = ??? untested, but used to work +PMAX = Mach 2.5 on Dec workstation + untested, but worked in previous version +SPARC = Sun Sparc ??? untested - previous version of Nyquist DID work +LINUX = Linux tested +Win32 tested +Mac tested + +If you have problems running Nyquist on a Unix machine, I'd be happy to +help. I can give you advice or if you give me an account, I can log in +remotely and install Nyquist for you. If you make corrections yourself, +please let me have them so I can put them in the next release. + +DIRECTORY STRUCTURE +=================== +cmt - CMU MIDI Toolkit files, used by Nyquist for MIDI File I/O +demos - Nyquist demos go here +fft - some fft functions +lib - .lsp files offering extensions to Nyquist +misc - various files and programs used to implement Nyquist +nyqsrc - general Nyquist source code (mostly in C) +runtime - the Nyquist and XLisp runtime code (mostly in XLisp) +sys - system specific files +snd - the sound file, sound input, and sound output package +test - test code (this is not maintained and may not be in the release) +todo - list of things to do (this may not be in the release) +tran - descriptor (.alg) files for machine-translated Nyquist code +xlisp - sources for Xlisp (these are linked into Nyquist) + diff --git a/advantages.txt b/advantages.txt new file mode 100644 index 0000000..702c549 --- /dev/null +++ b/advantages.txt @@ -0,0 +1,27 @@ +This is a list of things I see people trying to do with other systems that are natural in Nyquist: + +1. computing wavetables from mathematical functions: Nyquist tables are just sounds; +anything you can synthesize works as a wavetable + +2. generating "events" from within "instruments": Nyquist has no separation between +scores and instruments, so this restriction does not exist. + +3. parameterize sounds with complex control functions: rather than defining an +instrument with its one envelope generator, limiting envelopes to a few parameters, +in Nyquist it is easy to make the envelope a parameter so that you can pass in +any desired envelope shape. This flexibility actually makes instrument definitions +simpler while at the same time making them more powerful. + +4. synthesizing control functions: In Nyquist, you can use the full power of the +synthesis capabilities to generate control parameters. For example, you can use +a low-pass filter to smooth an amplitude envelope. + +5. routing instrument sounds to further processing: Nyquist instruments are +functions that can be combined to any level of hierarchy, so you do not need to +employ tricks like assigning sounds to global variables or defining reverb as +an "instrument" that reads from a special global buffer. + +6. inspecting sounds at the sample level: Nyquist is a complete language, so you +can examine and process sounds down to the sample level if necessary. (This is +too slow for production synthesis, but the flexibility is there and useful.) + diff --git a/cmt/cext.c b/cmt/cext.c new file mode 100644 index 0000000..452e18f --- /dev/null +++ b/cmt/cext.c @@ -0,0 +1,107 @@ +/**************************************************************************** + cext.c + Copyright 1989 Carnegie Mellon University + + August 3, 1987 + Author: Frits Habermann +---------------------------------------------------------------------------- + 02-May-1988 | JCD : portable & AMIGA version. + 17-Oct-1988 | JCD : more portability (FREE). + 28-Apr-2003 | DM : changed includes for portability +****************************************************************************/ + +#include "switches.h" + +#include +#include + +#include "cext.h" +#include "userio.h" + +#define calc_middle(top, bot) (((top - bot) / 2 ) + bottom ) + +#define kbyte 1000 +#define outof_mem(blocksize) (blocksize == 0 ) +#define done_search(top, bot, middle) ( (( (top - bot) < kbyte ) && \ +( !toomuch_mem(middle)) ) || \ + ( outof_mem( middle )) ) + +private boolean toomuch_mem(ushort maximum) +{ + char *test; + boolean istoo_much; + istoo_much = ( (test = (char *) MALLOC(maximum)) == NULL ); + if (test) FREE(test); + return( istoo_much ); +} + +private boolean toolittle_mem(maximum) +ushort maximum; +{ + char *test; + boolean istoo_little; + istoo_little = !( (test = (char *) MALLOC(maximum)) == NULL ); + if (test) FREE( test ); + return(istoo_little); +} + +private ushort get_biggest_block( maximum ) +ushort maximum; +{ + ushort maxblock; + ushort top = maximum; + ushort bottom = 0; + if (!toomuch_mem(maximum)) return(maximum); /* If there's enough memory */ + else { + gprintf(ERROR, "Running out of memory...\n"); + maxblock = calc_middle( top, bottom ); + while( !done_search(top, bottom, maxblock) ) { + if( toomuch_mem(maxblock) ) { + top = maxblock; + maxblock = calc_middle(top,bottom); + } + else if (toolittle_mem(maxblock)) { + bottom = maxblock; + maxblock = calc_middle(top,bottom); + } + } + } + return( maxblock ); +} + +public ulong MyMaxMem(ushort *growbytes) +{ + ulong x; + if( growbytes != NULL ) *growbytes = 0; + x=( (ulong)get_biggest_block((ushort)BIGGEST_BLOCK)); +/* gprintf(TRANS,"cext: MyMaxMem %ld\n",x); */ + return x; +} + +/* note: EXIT is defined to be cmt_exit */ + +void cmt_exit(n) + int n; +{ + cu_cleanup(); +/* For protection, exit is #defined to hide it. Expose it and call it. */ +#undef exit + exit(n); +} + + +#ifdef AMIGA +#ifdef LATTICE +/* for some reason, these don't seem to be defined + anywhere in the standard libraries + */ +#include "signal.h" + +int _FPERR; +int (*_SIGFPE)(int) = SIG_DFL; + +int _oserr; + +#endif +#endif + diff --git a/cmt/cext.h b/cmt/cext.h new file mode 100644 index 0000000..665c13d --- /dev/null +++ b/cmt/cext.h @@ -0,0 +1,194 @@ +/****************************************************************** +* modified JCD 27 Apr-88 for AMIGA +* cext.h -- extensions to c to make it more portable +* Copyright 1989 Carnegie Mellon University +* +******************************************************************* + +cext must provide the following definitions: + +true -- a constant +false -- a boolean constant +private -- defined as static, used to declare local functions +public -- defined as empty string, used to declare exported functions +boolean -- a new type +byte -- unsigned 8-bit quantity +ushort -- unsigned 16-bit quantity +ulong -- unsigned 32-bit quantity +Pointer -- pointer to char, a generic pointer +ABS() -- absolute value of any type of number +MAX() -- maximum of two numbers +MIN() -- minimum of two numbers +ROUND() -- round a double to long + +NULL -- pointer to nothing, a constant +EOS -- end of string, a constant '\0' +MALLOC(x) -- allocates x bytes +FREE(x) -- frees something from MALLOC +AVAILMEM -- tells how much memory is available. + (N.B.: no parens, no args.) +EXIT(n) -- calls exit(n) after shutting down/deallocating resources + +*****************************************************************************/ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm many changes for new conditional compilation switches + * 28Apr03 rbd removed macro redefinitions: min, max + */ + +#ifndef CEXT_H +#ifndef SWITCHES +#include "switches.h" +#endif + +#include +#include +#include + +#if HAS_STDLIB_H +#include +#endif + +#if HAS_SYS_TYPES_H +#include +#endif + +#if HAS_MALLOC_H +#include +#endif + +#if NEED_ULONG +typedef unsigned long ulong; +#endif + +#if NEED_USHORT +typedef unsigned long ushort; +#endif + +#if NEED_BYTE +typedef unsigned char byte; +#endif + +/* There's a name conflict between true/false as an enum type in + * Apple #includes:Types.h on the Mac, and true/false as #defined below + */ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define private static +#define public + +#if NEED_DEFINE_MALLOC +public void *malloc(); +#endif + +typedef char *Pointer; + +#ifdef UNIX_MACH +typedef int boolean; +#else +/* hopefully, unsigned short will save sign extension instructions */ +typedef unsigned char boolean; +#endif + +#ifndef ABS +#define ABS(a) (((a) > 0) ? (a) : -(a)) +#endif +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#define MAXULONG 0xffffffff + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef EOS +#define EOS '\0' +#endif + +#define SAFETYBUF 10 /* Safety buffer when allocating memory */ +#define BIGGEST_BLOCK 32765 /* Should find a happy medium for this */ + +#ifdef MACINTOSH /*DMH: gets AVAILMEM in record.c*/ +#include +#define MALLOC(x) malloc((size_t)(x)) /*DMH: size_t is ulong, for MAC*/ +#define FREE(x) free((char *)(x)) +#define AVAILMEM MyMaxMem(NULL)/*???*/ +#endif + +#ifdef LATTICE322 +#define MALLOC malloc +#define FREE free +#define AVAILMEM MyMaxMem(NULL) + +#else + +#ifdef DOS /* was MICROSOFT */ +#define MALLOC malloc +#define FREE free +#define AVAILMEM MyMaxMem(NULL) +#endif +#endif + +#ifdef UNIX +#define MALLOC malloc +#define FREE free +#define AVAILMEM 10000000 /* since we have virtual memory, assume 10Mb */ +#endif + +#ifdef AMIGA +#define MALLOC malloc +#define FREE free +#define AVAILMEM 128000 +#endif + +public ulong MyMaxMem(ushort *); + +#ifndef MEM +#include "mem.h" +#endif + +#ifndef CLEANUP +#include "cleanup.h" +#endif + +#ifdef CMTSTUFF +#define EXIT cmt_exit +public void EXIT(int); +/* don't allow anyone to call exit directly */ +#define exit(n) PLEASE_CALL_EXIT_NOT_exit +#else +#define EXIT(n) exit(n) +#endif + +#define _cext + +#ifndef MALLOC +MALLOC is not defined! +#endif + +#define ROUND(x) ((long) ((x) + 0.5)) + +/* for compatibility */ +#ifdef NEED_ROUND +#define round ROUND +#endif + +#ifndef min +#define min MIN +#define max MAX +#endif + +#define CEXT_H +#endif diff --git a/cmt/cleanup.c b/cmt/cleanup.c new file mode 100644 index 0000000..a0797d9 --- /dev/null +++ b/cmt/cleanup.c @@ -0,0 +1,62 @@ +/* cleanup.c -- registers work to do upon exit */ + +#include "stdio.h" +#include "cext.h" + +typedef struct cleanup_struct { + struct cleanup_struct *next; + cu_fn_type fn; + cu_parm_type obj; +} cleanup_node, *cleanup_type; + +cleanup_type cleanup_list = NULL; + +/* cu_register -- remember function and arg to call in order to clean up */ +/**/ +void cu_register(cu_fn_type fn, cu_parm_type obj) +{ + cleanup_type cu = (cleanup_type) memget(sizeof(cleanup_node)); + cu->fn = fn; + cu->obj = obj; + cu->next = cleanup_list; + cleanup_list = cu; +} + + +/* cu_unregister -- erase memory of obj (should be unique in cleanup list) */ +/**/ +void cu_unregister(obj) + void *obj; +{ + cleanup_type *cu = &cleanup_list; + while (*cu) { + if ((*cu)->obj == obj) { + cleanup_type found = *cu; + *cu = (*cu)->next; /* splice out found */ + memfree((char *) found, sizeof(cleanup_node)); + return; + } + cu = &((*cu)->next); + } +} + + +/* cu_cleanup -- call the registered functions */ +/**/ +void cu_cleanup() +{ + while (cleanup_list) { + cleanup_type cu = cleanup_list; +#ifdef CU_TRACE + gprintf(GTRANS, "cu_cleanup: node %lx fn %lx obj %lx\n", + cu, cu->fn, cu->obj); +#endif + cu->fn(cu->obj); + cleanup_list = cu->next; + memfree((char *) cu, sizeof(cleanup_node)); + } +#ifdef CU_TRACE + gprintf(GTRANS, "cu_cleanup done.\n"); + fflush(stdout); +#endif +} diff --git a/cmt/cleanup.h b/cmt/cleanup.h new file mode 100644 index 0000000..62aaf6f --- /dev/null +++ b/cmt/cleanup.h @@ -0,0 +1,9 @@ +/* cleanup.c -- registers work to do upon exit */ + +typedef void *cu_parm_type; +typedef void (*cu_fn_type)(cu_parm_type); +void cu_register(cu_fn_type fn, cu_parm_type obj); +void cu_unregister(void *obj); +void cu_cleanup(void); + +#define CLEANUP diff --git a/cmt/cmdline.c b/cmt/cmdline.c new file mode 100644 index 0000000..a215b08 --- /dev/null +++ b/cmt/cmdline.c @@ -0,0 +1,479 @@ +/* cmdline.c -- command line parsing routines */ +/* Copyright 1989 Carnegie Mellon University */ +/* + * This module is designed to allow various modules to scan (and rescan) + * the command line for applicable arguments. The goal is to hide as + * much information about switches and their names as possible so that + * switches become more consistent across applications and so that the + * author of an application need not do a lot of work to provide numerous + * options. Instead, each module scans the command line for its own + * arguments. + * + * Command lines are of the following form: + * command -s1 -s2 opt2 -s3 arg1 arg2 -s4 opt4 arg3 + * Note that there are three kinds of command line parameters: + * (1) A Switch is a "-" followed by a name, e.g. "-s1" + * (2) An Option is a Switch followed by a space and name, e.g. "-s2 opt2" + * (3) An Argument is a name by itself, e.g. "arg1" + * Note also that a switch followed by an argument looks just like an + * option, so a list of valid option names is necessary to disambiguate. + * + * Long names are good for readability, but single character abbreviations + * are nice for experienced users. cmdline.c allows single character + * abbreviations provided that they are unambiguous. These are + * recognized with no extra work by the programmer. If an + * isolated '?' is encountered in the command line, then all of + * the options and switches are printed as help and for debugging. + * + * Given that we must tell this module about option names and switch + * names, how should we do it? We can't wait until modules are + * initialized, since often modules want to read the command line + * at initialization time. In the original implementation, the + * main program was supposed to provide names for the whole program, + * but this violates modularity: when an option is added to a module, + * the main program has to be modified too. This is a real pain when + * different machines support different options and you want to have + * a single machine-independent main program. The solution is to + * have the main program import strings describing the options and + * switches used by each module. These are passed into cmdline.c + * before initialization of other modules is begun. + * + * A main program that uses cmdline.c should do the following: + * call cl_syntax(s) for each module's option/switch string. + * The string s should have the following format: + * "opt1description;opt2description;...;switch1description;..." + * where opt1 and opt2 are option names (without the preceding "-"), and + * switch1 is a switch name. The and indicate whether the + * name is an option or a switch. The descriptions are arbitrary strings + * (without semicolons) that are printed out for the user when "?" + * is typed on the command line. + * + * After calling cl_syntax, main() should call + * cl_init(argv, argc) + * cl_init will report an error (to STDERR) if it finds any illegal + * switch or option names in argv, and help will be printed if "?" + * is found in argv. If cl_init returns false, then the user has been + * given an error message or help, and main should probably exit. + * + * Afterward, switches, options, and arguments can be accessed by + * calling cl_switch, cl_option, and cl_arg. If cl_switch or cl_option + * is called with a switch name that was not mentioned in the call to + * cl_init, an error will result. This indicates that the application + * author omitted a valid switch or option name when calling cl_init. + * This is an error because the full set of names is needed for error + * checking and to distinguish arguments from options. + * + */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 13-Jun-86 | Created Change Log +* 6-Aug-86 | Modified for Lattice 3.0 -- use "void" to type some routines +* 20-Sep-89 | Redesigned the interface, adding cl_syntax call. +* 2-Apr-91 | JDW : further changes +* 27-Dec-93 | "@file" as first arg reads command line args from file +* 11-Mar-94 | PLu: Add private to cl_search() definition. +* 28-Apr-03 | DM: true->TRUE, false->FALSE +*****************************************************************************/ + +/* stdlib.h not on PMAX */ +#ifndef mips +#include "stdlib.h" +#endif +#include "stdio.h" +#include "cext.h" +#include "userio.h" +#include "cmdline.h" +#include "ctype.h" +#include "string.h" + +#define syntax_max 10 /* allow for 10 syntax strings */ +private char *syntax[syntax_max]; +private int n_syntax = 0; /* number of strings so far */ +private char **argv; /* command line argument vector */ +private int argc; /* length of argv */ + +private boolean cl_rdy = FALSE; /* set to TRUE when initialized */ + +#define cl_OPT 1 +#define cl_SW 2 +#define cl_INIT 3 +#define cl_ARG 4 + +/***************************************************************************** +* Routines local to this module +*****************************************************************************/ +private char *cl_search(); +private int find_string(); +private void indirect_command(char *filename, char *oldarg0); +private void ready_check(); + +/**************************************************************** +* cl_arg +* Inputs: +* n: the index of the arg needed +* Results: +* pointer to the nth arg, or NULL if none exists +* arg 0 is the command name +*****************************************************************/ + +char *cl_arg(n) + int n; +{ + return (n <= 0 ? argv[0] : + cl_search((char *)NULL, cl_ARG, n)); +} + +/* cl_help -- print help from syntax strings */ +/**/ +void cl_help() +{ + register int i, j; + int count = 0; /* see if there are any switches or flags */ + + for (i = 0; i < n_syntax; i++) { + register char *ptr = syntax[i]; + register char c = *ptr++; + while (c != EOS) { + while (c != EOS && !(isalnum(c))) c = *ptr++; + if (c != EOS) { + count++; + gprintf(TRANS, "-"); + j = 1; + while (c != EOS && c != '<') { + gprintf(TRANS, "%c", c); + c = *ptr++; + j++; + } + if (c != EOS) { + c = *ptr++; + if (c == 'o') { + gprintf(TRANS, " xxx"); + j += 4; + } + } + /* attempt to tab */ + do { + gprintf(TRANS, " "); + } while (j++ < 16); + while (c != EOS && c != '>') c = *ptr++; + if (c != EOS) c = *ptr++; + while (c != EOS && c != ';') { + gprintf(TRANS, "%c", c); + c = *ptr++; + } + gprintf(TRANS, "\n"); + } + } + } + if (!count) gprintf(TRANS, "No switches or options exist.\n"); +} + +/***************************************************************************** +* cl_init +* Inputs: +* char *switches[]: array of switch names +* int nsw: number of switch names +* char *options[]: array of option names +* int nopt: number of option names +* char *av: array of command line fields (argv) +* int ac: number of command line fields (argc) +* Effect: +* Checks that all command line entries are valid. +* Saves info for use by other routines. +* Returns: +* TRUE if syntax checks OK, otherwise false +*****************************************************************************/ + +boolean cl_init(av, ac) + char *av[]; + int ac; +{ + argv = av; + argc = ac; + + /* check for help request */ + if (argc == 2 && strcmp(argv[1], "?") == 0) { + cl_help(); + return FALSE; /* avoid cl_search which would complain about "?" */ + } + /* check for indirection */ + if (argc == 2 && *(argv[1]) == '@') { + /* read new args from file */ + indirect_command(av[1] + 1, av[0]); + } + /* check command line syntax: */ + cl_rdy = TRUE; + return (cl_rdy = (cl_search("true", cl_INIT, 0) != NULL)); +} + + +/**************************************************************** +* cl_int_option +* Inputs: +* char *name: name of option +* long default: default value for option +* Result: +* returns long encoding of the option, deflt if none +* Implementation: +* call cl_option and sscanf result +*****************************************************************/ + +long cl_int_option(name, deflt) + char *name; + long deflt; +{ + char *opt = cl_option(name); + if (opt) { + if (sscanf(opt, "%ld", &deflt) != 1) { + gprintf(TRANS, "Warning: option %s %s not an integer, ignored\n", + name, opt); + } + } + return deflt; +} + + +/**************************************************************** +* cl_search +* Inputs: +* char *name: name of field, must be non-null if opt_sw == cl_INIT +* int opt_sw: option, switch, init, or arg +* int n: argument number (if opt_sw is cl_ARG) +* Result: +* returns pointer to option value/switch if one exists, otherwise null +* Implementation: +* parse the command line until name or arg is found +* see if the option is followed by a string that does +* not start with "-" +*****************************************************************/ + +private char *cl_search(name, opt_sw, n) + char *name; + int opt_sw; + int n; /* if opt_sw is cl_ARG, n > 0 tells which one */ +{ + register int i = 1; /* index into command line */ + boolean abbr; + boolean result = TRUE; + + ready_check(); + + /* parse command line: */ + while (i < argc) { + register char *arg = argv[i]; + /* arguments that start with '-' should be quoted and quotes must + be removed by the application + */ + if (*arg == '-') { + int arg_type = find_string(arg + 1, &abbr); + if (arg_type == cl_OPT) { + i += 1; /* skip name and option */ + /* don't look for '-' because the option might be a + * negative number + */ + if (i >= argc /* || *arg == '-' */) { + if (opt_sw == cl_INIT) { + gprintf(ERROR, "missing argument after %s\n", arg); + result = FALSE; + } + } else if (opt_sw == cl_OPT && + (strcmp(arg + 1, name) == 0 || + (abbr && *(arg + 1) == name[0]))) { + return argv[i]; + } + } else if (arg_type == cl_SW) { + if (opt_sw == cl_SW && + (strcmp(arg + 1, name) == 0 || + (abbr && *(arg + 1) == name[0]))) + return arg; + } else if (opt_sw == cl_INIT) { + gprintf(ERROR, "invalid switch: %s\n", arg); + result = FALSE; + } + } else if (opt_sw == cl_ARG) { + if (n == 1) return arg; + n--; + } + i++; /* skip to next field */ + } + if (opt_sw == cl_INIT) { + /* return name or NULL to represent TRUE or FALSE */ + return (result ? name : NULL); + } + return NULL; +} + +/**************************************************************** +* cl_option +* Inputs: +* char *name: option name +* Outputs: +* returns char *: the option string if found, otherwise null +****************************************************************/ + +char *cl_option(name) +char *name; +{ + return cl_search(name, cl_OPT, 0); +} + +/**************************************************************** +* cl_switch +* Inputs: +* char *name: switch name +* Outputs: +* boolean: TRUE if switch found +****************************************************************/ + +boolean cl_switch(name) +char *name; +{ + return (boolean)(cl_search(name, cl_SW, 0) != NULL); +} + +/* cl_syntax -- install a string specifying options and switches */ +/**/ +boolean cl_syntax(char *s) +{ + if (n_syntax < syntax_max) { + syntax[n_syntax++] = s; + return TRUE; + } else { + gprintf(ERROR, "cl_syntax: out of room\n"); + return FALSE; + } +} + +/**************************************************************** +* find_string +* Inputs: +* char *s: string to find, terminated by any non-alphanumeric +* boolean *abbr: set TRUE if s is an abbreviation, otherwise false +* Effect: +* Looks for s in syntax strings +* Returns: +* 0 = FALSE = not found, 1 = cl_OPT = option, 2 = cl_SW = switch +*****************************************************************/ + +private int find_string(s, abbr) + char *s; + boolean *abbr; +{ + int found_it = FALSE; + int i; + *abbr = FALSE; + for (i = 0; i < n_syntax; i++) { /* loop through strings */ + register char *syntax_ptr = syntax[i]; + while (*syntax_ptr != EOS) { + register char *s_ptr = s; + while (*syntax_ptr != EOS && + !(isalnum(*syntax_ptr))) syntax_ptr++; + while (*s_ptr != EOS && (*s_ptr++ == *syntax_ptr)) + syntax_ptr++; /* only increment if there's a match */ + if (!(isalnum(*s_ptr)) && *syntax_ptr == '<') { + syntax_ptr++; /* advance to the type field */ + if (*syntax_ptr == 's') return cl_SW; + if (*syntax_ptr != 'o') + gprintf(ERROR, + "(internal error) bad cl_syntax string: %s\n", + syntax[i]); + return cl_OPT; + } + /* no match, so go to next */ + while (*syntax_ptr != ';' && *syntax_ptr != EOS) syntax_ptr++; + if (*syntax_ptr == ';') syntax_ptr++; + } + } + + /* no match, maybe there is a single character match */ + if (s[0] == EOS || s[1] != EOS) return FALSE; + + for (i = 0; i < n_syntax; i++) { /* loop through strings */ + char *syntax_ptr = syntax[i]; + while (*syntax_ptr != EOS) { + while (*syntax_ptr != EOS && + !(isalnum(*syntax_ptr))) syntax_ptr++; + if (s[0] == *syntax_ptr) { + if (found_it) return FALSE; /* ambiguous */ + /* else, find the type */ + while (*syntax_ptr != '<' && *syntax_ptr != EOS) + syntax_ptr++; + syntax_ptr++; + if (*syntax_ptr == 's') found_it = cl_SW; + else if (*syntax_ptr == 'o') found_it = cl_OPT; + else return FALSE; /* error in string syntax */ + } + /* no match, so go to next */ + while (*syntax_ptr != ';' && *syntax_ptr != EOS) syntax_ptr++; + if (*syntax_ptr == ';') syntax_ptr++; + } + } + if (found_it) *abbr = TRUE; + return found_it; +} + + +/* get_arg -- get an argument from a file */ +/**/ +boolean get_arg(file, arg) + FILE *file; + char *arg; +{ + int c; + while ((c = getc(file)) != EOF && isspace(c)) ; + if (c == EOF) return FALSE; + ungetc(c, file); + while ((c = getc(file)) != EOF && !isspace(c)) { + *arg++ = c; + } + *arg = 0; + return TRUE; +} + + +/* indirect_command -- get argv, argc from a file */ +/**/ +private void indirect_command(filename, oldarg0) + char *filename; + char *oldarg0; +{ + FILE *argfile = fopen(filename, "r"); + if (!argfile) { + argv = (char **) malloc(sizeof(char *)); + argv[0] = oldarg0; + argc = 1; + } else { + int i = 1; + char arg[100]; + while (get_arg(argfile, arg)) i++; + fclose(argfile); + argfile = fopen(filename, "r"); + argv = (char **) malloc(sizeof(char *) * i); + argv[0] = oldarg0; + argc = i; + i = 1; + while (get_arg(argfile, arg)) { + argv[i] = (char *) malloc(strlen(arg) + 1); + strcpy(argv[i], arg); + i++; + } + fclose(argfile); + } +} + +/**************************************************************** +* ready_check +* Effect: +* Halt program if cl_rdy is not true. +*****************************************************************/ +private void ready_check() +{ + if (!cl_rdy) { + gprintf(ERROR, + "Internal error: cl_init was not called, see cmdline.c\n"); + EXIT(1); + } +} diff --git a/cmt/cmdline.h b/cmt/cmdline.h new file mode 100644 index 0000000..06ff4c3 --- /dev/null +++ b/cmt/cmdline.h @@ -0,0 +1,8 @@ +/* Copyright 1989 Carnegie Mellon University */ + +char *cl_arg(int n); +boolean cl_init(char *av[], int ac); +long cl_int_option(char *name, long deflt); +char *cl_option(char *name); +boolean cl_switch(char *name); +boolean cl_syntax(char *name); diff --git a/cmt/cmtcmd.c b/cmt/cmtcmd.c new file mode 100644 index 0000000..2881467 --- /dev/null +++ b/cmt/cmtcmd.c @@ -0,0 +1,53 @@ +/* cmtcmd.c -- routines for the moxc side of the command interface */ + +#include "switches.h" +#include "stdio.h" +#ifdef AMIGA +#include "exec/types.h" +#include "exec/exec.h" +#endif +#include "cmtcmd.h" +#include "cext.h" +#include "userio.h" +#include "string.h" + +#define HASHELEM(p) ((p).symbol_name) +#define HASHVAL 50 +#define HASHENTRIES 50 +#define HASHENTER lookup +#define HASHNOCOPY + +#include "hashrout.h" + +void defvar(name, addr) + char *name; + int *addr; +{ + int i = lookup(name); + HASHENTRY(i).symb_type = var_symb_type; + HASHENTRY(i).ptr.intptr = addr; +} + + +void defun(name, addr) + char *name; + int (*addr)(); +{ + int i = lookup(name); + HASHENTRY(i).symb_type = fn_symb_type; + HASHENTRY(i).ptr.routine = addr; +} + + +void defvec(name, addr, size) + char *name; + int *addr; + int size; +{ + int i = lookup(name); + HASHENTRY(i).symb_type = vec_symb_type; + HASHENTRY(i).size = size; + HASHENTRY(i).ptr.intptr = addr; +} + + diff --git a/cmt/cmtcmd.h b/cmt/cmtcmd.h new file mode 100644 index 0000000..9ad1cac --- /dev/null +++ b/cmt/cmtcmd.h @@ -0,0 +1,35 @@ +/* cmtcmd.h -- header for remote action and variable setting interface */ + +#define var_symb_type 333 +#define fn_symb_type 555 +#define vec_symb_type 777 + +#ifdef AMIGA +struct cmd_msg { + struct Message msg; + long symb_type; /* one of var_, fn_, or vec_symb_type */ + char *symbol_name; + long the_args[8]; /* args for function call. If var_symb_type, + the_args[0] is the new value. If vec_symb_type, + the_args[0] is index, the_args[1] is new value. */ +}; +#endif + +typedef struct symb_descr { + char *symbol_name; + int symb_type; + int size; /* for array bounds checking */ + union { + int *intptr; + int (*routine)(); + } ptr; +} symb_descr_node; + +int lookup(char *s); +void defvar(char *name, int *addr); +void defvec(char *name, int *addr, int size); +typedef int (*defun_type)(); +void defun(char *name, defun_type addr); + +#define HASHTYPE symb_descr_node +#include "hash.h" diff --git a/cmt/cmtio.c b/cmt/cmtio.c new file mode 100644 index 0000000..e6f1ebc --- /dev/null +++ b/cmt/cmtio.c @@ -0,0 +1,161 @@ +/* + ********************************************************************** + * File io.c + ********************************************************************** + * + * Non blocking input routine + * Works by puttng the terminal in CBREAK mode and using the FIONREAD + * ioctl call to determine the number of characters in the input queue + */ + +#include "stdio.h" +#include "io.h" +#include +#include +#include +#include +#include "cext.h" + +int IOinputfd; /* input file descriptor (usually 0) */ + +int IOnochar; /* Value to be returned by IOgetchar() + where there is no input to be had */ + +static struct sgttyb IOoldmodes, IOcurrentmodes; + /* Initial and current tty modes */ + +/* + * IOsetup(inputfd) + * Args: + * inputfd - input file descriptor (should be zero for standard input) + * Returns: + * 0 - if all goes well + * -1 - if an ioctl fails (also calls perror) + * Side Effects: + * Puts the terminal in CBREAK mode - before process termination + * IOcleanup() should be called to restore old terminal modes + * Catch's interrupts (if they are not already being caught) and + * calls IOcleanup before exiting + * + */ + +#define ERROR(s) return (perror(s), -1) + +IOsetup(inputfd) +{ + static IOdiegracefully(); + int (*interrupt_handler)(); + + IOinputfd = inputfd; + IOnochar = NOCHAR; + if(ioctl(IOinputfd, TIOCGETP, &IOoldmodes) < 0) + ERROR("IOsetup"); + + IOcurrentmodes = IOoldmodes; + IOcurrentmodes.sg_flags |= CBREAK; + IOcurrentmodes.sg_flags &= ~ECHO; + if(ioctl(IOinputfd, TIOCSETP, &IOcurrentmodes)) + ERROR("IOsetup-2"); + + if( (interrupt_handler = signal(SIGINT, IOdiegracefully)) != 0) + signal(SIGINT, interrupt_handler); + return 0; +} + +static +IOdiegracefully() +{ + write(2, "\nBye\n", 5); + IOcleanup(); + EXIT(2); +} + +/* + * IOcleanup() + * Returns: + * 0 - if all goes well + * -1 - if an ioctl fails (also calls perror) + * Side Effects: + * Restores initial terminal modes + */ + +IOcleanup() +{ + if(ioctl(IOinputfd, TIOCSETP, &IOoldmodes) < 0) + ERROR("IOclean"); + return 0; +} + + +/* + * IOgetchar() + * Returns: + * A character off the input queue if there is one, + * IOnochar if there is no character waiting to be read, + * -1 if an ioctl fails (shouldn't happen if IOsetup went OK) + */ + +#ifndef UNIX_MACH + +IOgetchar() +{ + int n; + char c; + + if(ioctl(IOinputfd, FIONREAD, &n) < 0) + ERROR("IOgetchar"); + if(n <= 0) + return IOnochar; + switch(read(IOinputfd, &c, 1)) { + case 1: + return c; + case 0: + return EOF; + default: + ERROR("IOgetchar-read"); + } +} + +#ifdef IOGETCHAR2 +IOgetchar2() +{ + int nfds, readfds = 1 << IOinputfd; + char c; + static struct timeval zero; + + if(IOinputfd < 0 || IOinputfd >= 32) { + printf("IOgetchar2: bad IOinputfd (%d)%s\n", IOinputfd, + IOinputfd == -1 ? "Did you call IOsetup(fd)?" : ""); + } + nfds = select(32, &readfds, 0, 0, &zero); + if(nfds > 0) { + switch(read(IOinputfd, &c, 1)) { + case 0: + return EOF; + case 1: + return c; + default: + printf("IOgetchar2: read failed!\n"); + return NOCHAR; + } + } + else if(nfds < 0) + printf("IOgetchar2: select failed!\n"); + return NOCHAR; +} +#endif + +/* + * IOwaitchar() + * Returns: + * A character off the input queue. Waits if necessary. + */ + +int IOwaitchar() +{ + char c; + if (read(IOinputfd, &c, 1) == 1) return c; + else return EOF; +} + +#endif /* not UNIX_MACH */ diff --git a/cmt/cmtio.h b/cmt/cmtio.h new file mode 100644 index 0000000..3e50ad9 --- /dev/null +++ b/cmt/cmtio.h @@ -0,0 +1,9 @@ +#define NOCHAR -2 + +int IOinputfd; +int IOnochar; + +int IOsetup(int inputfd); +int IOcleanup(void); +int IOgetchar(void); +int IOwaitchar(void); diff --git a/cmt/hash.h b/cmt/hash.h new file mode 100644 index 0000000..0257cfe --- /dev/null +++ b/cmt/hash.h @@ -0,0 +1,23 @@ +/* + * This file should be included in all files that use + * the HASHENTRY macro; see hashrout.h for details + */ +/* Copyright 1989 Carnegie Mellon University */ + +#ifndef HASHTYPE +# include "-- HASHTYPE undefined" +#endif + +/* + * An element really is a HASHTYPE along with a h_next entry, + * which chains together entries of the same hash value. + */ + +typedef struct hashelem { + HASHTYPE h_elem; + struct hashelem *h_next; +} hashelem; + +extern hashelem hashfirstchunk[]; + +#define HASHENTRY(i) (hashfirstchunk[i].h_elem) diff --git a/cmt/hashrout.h b/cmt/hashrout.h new file mode 100644 index 0000000..a566b9f --- /dev/null +++ b/cmt/hashrout.h @@ -0,0 +1,220 @@ +/* hashrout.h -- Rubine's hash table package */ +/* Copyright 1989 Carnegie Mellon University */ + +/* ChangeLog: + * 2-jan-85 rbd Added option to count entries: define COUNTER and + * HASHENTER routine will increment it on new entries + * 28-Apr-03 DM Explicit declaration of int type for HASHENTER() + */ + +/* + * Generic symbol table functions + * + * After writing this code over for a bunch of interpreters + * I think I know how to do it once and for all, generally + * enough for most application. + * There are enough settable parameters to suit anyone, and + * the defaults usually do something sane. + * + * The basic idea is that you have a bunch of symbol table entries + * that need to be entered or looked up given a character string. + * Symbol table entries are usually structures, and one element + * of the structure must be the character string of the key. + * The structure should be given a type name, and these routines + * are informed of the type name via + * #define HASHTYPE type-name-of-symbol-table-entry + * You must inform the routines how to access the character string + * given the symbol table entry; for example + * #define HASHELEM(p) ((p).name) + * There are two size parameters - the number of different hash + * values and the number of symbol table entries to allocate at one + * time. Both default to 256. + * #define HASHVAL 128 + * #define HASHENTRIES 512 + * The name of the function that performs both entry and lookup is + * enter(name) - it takes one argument, a character string. The name + * of the function may be changed via + * #define HASHENTER new-name-for-enter-routine + * Note that if there is no entry in the table for name, name is entered + * automatically. The returned structure will have only the name + * field filled in; the rest of the fields are guarenteed to be zero + * so an application can check if this is the first time name was entered. + * If HASHPOINT is defined, the enter routine returns a pointer to a hash + * table entry. In the default case, i.e. HASHPOINT undefined, the + * enter routine returns an integer between zero and HASHENTRIES. + * The macro HASHENTRY(i) will, given that integer, return the + * table element (not a pointer to it), so for example, + * HASHENTRY(enter(x)).name == x. + * Any file that wishes to use HASHENTRY should have at the top + * #define HASHTYPE type-name-of-symbol-table-entry + * #include "hash.h" + * Note in this case at most HASHENTRIES entries will be allocated + * before hash table overflow. If HASHPOINT is defined, allocations + * will take place until memory runs out. + * By default, hash strings are copied into space obtained from malloc + * before being placed in new entry. This copying can be supressed + * by defining HASHNOCOPY. + * The following is an example of using the hash table stuff. + +typedef struct { + char *n_name; + int n_value; +} symbolentry; + +#define HASHTYPE symbolentry +#define HASHELEM(p) ((p).n_name) +#define HASHENTRIES 1024 + +#include "hashrout.h" + +*/ + + +/* + * OK, now the meat. + */ + +#ifndef HASHTYPE +# include "-- HASHTYPE undefined" +#endif + +#ifndef HASHELEM +# include "-- HASHELEM undefined" +#endif + +#ifndef HASHVAL +# define HASHVAL 256 +#endif + +#ifndef HASHENTRIES +# define HASHENTRIES 256 +#endif + +#ifndef HASHENTER +# define HASHENTER enter +#endif + +/* + * HASHNOCOPY, HASHPOINT are undefined by default + */ + +/* + * get definition of hash elem structure + */ + +#ifndef HASHENTRY +# include "hash.h" +#endif + +/* + * Table of pointers, indexed by hash values + */ + +hashelem *hashtab[HASHVAL]; + +/* + * First chunk of elements, pointer to the start, + * and index for allocation + */ + +hashelem hashfirstchunk[HASHENTRIES]; +hashelem *hashchunk = hashfirstchunk; +int hashindex = 0; + +/* + * stdio.h if we don't have it yet + */ + +#ifndef _NFILE +# include +#endif + +/* + * Declare counter if necessary + */ + +#ifdef COUNTER +extern COUNTER; +#endif + +/* + * The enter routine + */ + +#ifdef HASHPOINT +HASHTYPE * +#else +int +#endif +HASHENTER (s) +char *s; +{ + register int i, hash; + register hashelem *elem; + + /* + * Compute s's hash value + * I really should look up some good hash functions, but + * I haven't bothered. + */ + +for(i = 0, hash = 0; s[i] != '\0' && i < 15; i++) + hash += (i + 1) * s[i]; +hash %= HASHVAL; + +/* + * search for s in the table + */ + +for(elem = hashtab[hash]; elem != NULL; elem = elem->h_next) + if(strcmp(s, HASHELEM((elem->h_elem))) == 0) { /* found it */ +#ifdef HASHPOINT + return(&elem->h_elem); +#else + return(elem - hashfirstchunk); +#endif + } + +if(hashindex >= HASHENTRIES) { +#ifdef HASHPOINT + char *calloc(); + + hashindex = 0; + hashchunk = (hashelem *) calloc(HASHENTRIES, sizeof(hashelem)); + if(hashchunk == NULL) { + gprintf(FATAL, "No mem for hash symbol table\n"); + EXIT(1); +#ifdef COUNTER + COUNTER++; /* optional symbol counter */ +#endif + } +#else + gprintf(FATAL, "No hash table space, increase HASHENTRIES\n"); + EXIT(1); +#endif +} + +/* + * Splice a new entry into the list and fill in the string field + */ + +elem = &hashchunk[hashindex++]; +elem->h_next = hashtab[hash]; +hashtab[hash] = elem; + +#ifdef HASHNOCOPY +HASHELEM((elem->h_elem)) = s; +#else +{ + char *strcpy(); + HASHELEM((elem->h_elem)) = memget((strlen(s) + 1)); + strcpy(HASHELEM((elem->h_elem)), s); +} +#endif + +#ifdef HASHPOINT +return(&elem->h_elem); +#else +return(elem - hashfirstchunk); +#endif +} diff --git a/cmt/mem.c b/cmt/mem.c new file mode 100644 index 0000000..7256188 --- /dev/null +++ b/cmt/mem.c @@ -0,0 +1,91 @@ +/* mem.c -- fast memory allocation/deallocation module */ + +/* Allocate large chunks of memory using malloc. From the chunks, + allocate memory as needed on long-word boundaries. Memory is + freed by linking memory onto a freelist. An array of freelists, + one for each size, is maintained and checked before going to the + chunck for more memory. The freelist array only holds lists of + nodes up to a certain size. After that, malloc is used directly. + */ +/* CHANGE LOG + ---------------------------------------------------------------------- + 28-Apr-03 | DM : fix #includes for portability + ---------------------------------------------------------------------- + */ + +#include "switches.h" + +#include +#include + +#include "cext.h" +#include "userio.h" + +/* how many bytes in the largest node managed in mem_free_list array */ +#define MAX_SIZE_FOR_FREELIST 256 + +long *mem_free_list[MAX_SIZE_FOR_FREELIST/4]; + +#define MEM_CHUNK_SIZE 4096 +char *mem_chunk; +long mem_chunk_remaining = 0; + +void meminit() +{ + int i; + for (i = 0; i < MAX_SIZE_FOR_FREELIST/4; i++) { + mem_free_list[i] = NULL; + } +} + + +void *memget(register size_t size) +{ + if (size > MAX_SIZE_FOR_FREELIST) { +/* gprintf(TRANS, "memget calling MALLOC\n"); */ + return MALLOC(size); + } else { + long **p = mem_free_list + ((size - 1) >> 2); + if (*p) { + register long *result = *p; + *p = (long *) *result; +/* gprintf(TRANS, "memget->%lx\n", result); */ + return (char *) result; + } else if ((size_t) mem_chunk_remaining >= size) { + register char *result = mem_chunk; + size = (size + 3) & ~3; /* round up to multiple of 4 */ + mem_chunk += size; + mem_chunk_remaining -= size; +/* gprintf(TRANS, "memget->%lx\n", result); */ + return result; + /* note that we throw away remaining chunk when there isn't enough */ + } else if ((mem_chunk = (char *) MALLOC(MEM_CHUNK_SIZE))) { + register char *result = mem_chunk; +/* gprintf(TRANS, "mem_chunk at %lx\n", mem_chunk); */ + size = (size + 3) & ~3; /* round up to multiple of 4 */ + mem_chunk += size; + mem_chunk_remaining = MEM_CHUNK_SIZE - size; +/* gprintf(TRANS, "memget->%lx\n", result); */ + return result; + } else { + return NULL; + } + } +} + + +void memfree(register void *ptr, register size_t size) +{ + register long **p = (long **) ptr; + if (size > MAX_SIZE_FOR_FREELIST) { + FREE(ptr); + } else { + register long **head_ptr = mem_free_list + ((size - 1) >> 2); + *p = *head_ptr; + *head_ptr = (long *) p; + } +} + + + + diff --git a/cmt/mem.h b/cmt/mem.h new file mode 100644 index 0000000..ea33ba9 --- /dev/null +++ b/cmt/mem.h @@ -0,0 +1,12 @@ +#ifdef AMIGA +#include "stddef.h" +#endif + +extern long *mem_free_list[]; + +void *memget(register size_t size); +void memfree(register void *ptr, register size_t size); + +void meminit(void); + +#define MEM diff --git a/cmt/mfmidi.h b/cmt/mfmidi.h new file mode 100644 index 0000000..9621c67 --- /dev/null +++ b/cmt/mfmidi.h @@ -0,0 +1,19 @@ +#define NOTEOFF 0x80 +#define NOTEON 0x90 +#define PRESSURE 0xa0 +#define CONTROLLER 0xb0 +#define PITCHBEND 0xe0 +#define PROGRAM 0xc0 +#define CHANPRESSURE 0xd0 + +/* These are the strings used in keynote to identify Standard MIDI File */ +/* meta text messages. */ + +#define METATEXT "Text Event" +#define METACOPYRIGHT "Copyright Notice" +#define METASEQUENCE "Sequence/Track Name" +#define METAINSTRUMENT "Instrument Name" +#define METALYRIC "Lyric" +#define METAMARKER "Marker" +#define METACUE "Cue Point" +#define METAUNRECOGNIZED "Unrecognized" diff --git a/cmt/midibuff.h b/cmt/midibuff.h new file mode 100644 index 0000000..f8dc1c1 --- /dev/null +++ b/cmt/midibuff.h @@ -0,0 +1,23 @@ +/* midibuff.h -- defines the size of the midi input buffer */ + +/* midi input buffer */ +/* WARNING: BUFF_SIZE must be a power of 2 so we can use masking to wrap */ +#define EVENT_COUNT 128 +#define EVENT_SIZE 4 +#define BUFF_SIZE (EVENT_COUNT * EVENT_SIZE) +#define BUFF_MASK (BUFF_SIZE - 1) + +#ifdef WINDOWS +#define huge +#endif + +extern byte huge *xbuff; /* application-supplied sysex buffer */ +extern long xbufmask; /* mask for circular buffer */ +extern long xbufhead; /* buffer head and tail offsets */ +extern long xbuftail; +extern int midi_error; +/* midi input buffer */ +/* data buffer, declared long to get 32-bit alignment: */ +extern long buff[BUFF_SIZE/4]; +extern int buffhead; /* buffer head and tail pointers */ +extern int bufftail; diff --git a/cmt/midicode.h b/cmt/midicode.h new file mode 100644 index 0000000..26361d3 --- /dev/null +++ b/cmt/midicode.h @@ -0,0 +1,62 @@ +/************************************************************************ +* +* Midi codes +* Copyright 1989 Carnegie Mellon University +* +************************************************************************* +* Change Log +* Date | Change +*-----------+------------------------------------------------------------ +* 11-Mar-94 | PLu : Port to IRI +************************************************************************/ + +#define MIDI_DATA(d) (0x7f & (d)) +#define MIDI_CHANNEL(c) (0x0f & ((c) - 1)) +#define MIDI_PORT(c) (((c) - 1) >> 4) +#define MIDI_PROGRAM(p) MIDI_DATA((p) - 1) + +#define MIDI_STATUS_BIT 0x80 +#define MIDI_COMMON 0x70 +#define MIDI_CODE_MASK 0xf0 +#define MIDI_CHN_MASK 0x0f +#define MIDI_REALTIME 0xf8 +#define MIDI_CHAN_MODE 0xfa + +#define MIDI_OFF_NOTE 0x80 +#define MIDI_ON_NOTE 0x90 +#define MIDI_POLY_TOUCH 0xa0 +#define MIDI_CTRL 0xb0 +#define MIDI_CH_PROGRAM 0xc0 +#define MIDI_TOUCH 0xd0 +#define MIDI_BEND 0xe0 + +#ifdef UNIX_IRIX_MIDIFNS +#define CMT_MIDI_SYSEX 0xf0 +#define CMT_MIDI_EOX 0xf7 +#else +#define MIDI_SYSEX 0xf0 +#define MIDI_EOX 0xf7 +#endif +#define MIDI_Q_FRAME 0xf1 +#define MIDI_SONG_POINTER 0xf2 +#define MIDI_SONG_SELECT 0xf3 +#define MIDI_F4 0xf4 +#define MIDI_F5 0xf5 +#define MIDI_TUNE_REQ 0xf6 +#define MIDI_TIME_CLOCK 0xf8 +#define MIDI_F9 0xf9 +#define MIDI_START 0xfa +#define MIDI_CONTINUE 0xfb +#define MIDI_STOP 0xfc +#define MIDI_FD 0xfd +#define MIDI_ACTIVE_SENSING 0xfe +#define MIDI_SYS_RESET 0xff + +#define MIDI_LOCAL 0x7a +#define MIDI_LOCAL_OFF 0x00 +#define MIDI_LOCAL_ON 0x7f +#define MIDI_ALL_OFF 0x7b +#define MIDI_OMNI_OFF 0x7c +#define MIDI_OMNI_ON 0x7d +#define MIDI_MONO_ON 0x7e +#define MIDI_POLY_ON 0x7f diff --git a/cmt/midierr.h b/cmt/midierr.h new file mode 100644 index 0000000..d00ce4c --- /dev/null +++ b/cmt/midierr.h @@ -0,0 +1,17 @@ +/* midierr.h -- error codes */ + +#define NESTERR 1 /* nested interrupts */ +#define BUFFOVFL 2 /* input buffer overflow */ +#define CMDERR 3 /* unknown command from mpu-401 */ +#define TIMEOUTERR 4 /* interface timeout */ +#define MSGERR 5 /* invalid message */ +#define SYSEXOVFL 6 /* sysex buffer overflow */ +#define MEMERR 7 /* internal out of memory */ +#define RECVERR 8 /* receive error or device buffer overflow */ +#define MIDIMGRERR 9 /* error reported by midi manager (Macintosh) */ + +#define SYSEX_ERR ((1< +#include + +#include "mfmidi.h" +#include "midifile.h" +#include "cext.h" +#include "userio.h" +#include "string.h" + +#define MIDIFILE_ERROR -1 + +#ifdef PROTOTYPES +#define NOARGS void +#else +#define NOARGS +#endif + +/* public stuff */ +extern int abort_flag; + +/* Functions to be called while processing the MIDI file. */ +void (*Mf_starttrack)(NOARGS) = 0; +void (*Mf_endtrack)(NOARGS) = 0; +int (*Mf_getc)(NOARGS) = 0; +void (*Mf_eot)(NOARGS) = 0; +#ifdef PROTOTYPES +void (*Mf_error)(char *) = 0; +void (*Mf_header)(int,int,int) = 0; +void (*Mf_on)(int,int,int) = 0; +void (*Mf_off)(int,int,int) = 0; +void (*Mf_pressure)(int,int,int) = 0; +void (*Mf_controller)(int,int,int) = 0; +void (*Mf_pitchbend)(int,int,int) = 0; +void (*Mf_program)(int,int) = 0; +void (*Mf_chanpressure)(int,int) = 0; +void (*Mf_sysex)(int,char*) = 0; +void (*Mf_arbitrary)(int,char*) = 0; +void (*Mf_metamisc)(int,int,char*) = 0; +void (*Mf_seqnum)(int) = 0; +void (*Mf_smpte)(int,int,int,int,int) = 0; +void (*Mf_timesig)(int,int,int,int) = 0; +void (*Mf_tempo)(int) = 0; +void (*Mf_keysig)(int,int) = 0; +void (*Mf_sqspecific)(int,char*) = 0; +void (*Mf_text)(int,int,char*) = 0; +#else +void (*Mf_error)() = 0; +void (*Mf_header)() = 0; +void (*Mf_on)() = 0; +void (*Mf_off)() = 0; +void (*Mf_pressure)() = 0; +void (*Mf_controller)() = 0; +void (*Mf_pitchbend)() = 0; +void (*Mf_program)() = 0; +void (*Mf_chanpressure)() = 0; +void (*Mf_sysex)() = 0; +void (*Mf_arbitrary)() = 0; +void (*Mf_metamisc)() = 0; +void (*Mf_seqnum)() = 0; +void (*Mf_smpte)() = 0; +void (*Mf_tempo)() = 0; +void (*Mf_timesig)() = 0; +void (*Mf_keysig)() = 0; +void (*Mf_sqspecific)() = 0; +void (*Mf_text)() = 0; +#endif + +int Mf_nomerge = 0; /* 1 => continue'ed system exclusives are */ + /* not collapsed. */ +long Mf_currtime = 0L; /* current time in delta-time units */ +int Mf_skipinit = 0; /* 1 if initial garbage should be skipped */ + +/* private stuff */ + +static long Mf_toberead = 0L; + +static long readvarinum(NOARGS); +static long read32bit(NOARGS); +static int read16bit(NOARGS); +static void msgenlarge(NOARGS); +static char *msg(NOARGS); +static int readheader(NOARGS); +static void readtrack(NOARGS); +static void sysex(NOARGS), msginit(NOARGS); +static int egetc(NOARGS); +static int msgleng(NOARGS); + +#ifdef PROTOTYPES +static int readmt(char*,int); +static long to32bit(int,int,int,int); +static int to16bit(int,int); +static void mferror(char *); +static void badbyte(int); +static void metaevent(int); +static void msgadd(int); +static void chanmessage(int,int,int); +#else +static long to32bit(); +static int to16bit(); +static void mferror(); +static void badbyte(); +static void metaevent(); +static void msgadd(); +static void chanmessage(); +#endif + +static int midifile_error; + +void +midifile() /* The only non-static function in this file. */ +{ + int ntrks; + midifile_error = 0; + + if ( Mf_getc == 0 ) { + mferror("mf.h() called without setting Mf_getc"); + return; + } + ntrks = readheader(); + if (midifile_error) return; + if ( ntrks <= 0 ) { + mferror("No tracks!"); + /* no need to return since midifile_error is set */ + } + while ( ntrks-- > 0 && !midifile_error && !check_aborted()) + readtrack(); + if (check_aborted()) { + mferror("Midifile read aborted\n\ +\tthe rest of your file will be ignored.\n"); + if (abort_flag == BREAK_LEVEL) abort_flag = 0; + } +} + +static int +readmt(s,skip) /* read through the "MThd" or "MTrk" header string */ +char *s; +int skip; /* if 1, we attempt to skip initial garbage. */ +{ + int nread = 0; + char b[4]; + char buff[32]; + int c; + char *errmsg = "expecting "; + + retry: + while ( nread<4 ) { + c = (*Mf_getc)(); + if ( c == EOF ) { + errmsg = "EOF while expecting "; + goto err; + } + b[nread++] = c; + } + /* See if we found the 4 characters we're looking for */ + if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] ) + return(0); + if ( skip ) { + /* If we are supposed to skip initial garbage, */ + /* try again with the next character. */ + b[0]=b[1]; + b[1]=b[2]; + b[2]=b[3]; + nread = 3; + goto retry; + } + err: + (void) strcpy(buff,errmsg); + (void) strcat(buff,s); + mferror(buff); + return(0); +} + +static int +egetc() /* read a single character and abort on EOF */ +{ + int c = (*Mf_getc)(); + + if ( c == EOF ) { + mferror("premature EOF"); + return EOF; + } + Mf_toberead--; + return(c); +} + +static int +readheader() /* read a header chunk */ +{ + int format, ntrks, division; + + if ( readmt("MThd",Mf_skipinit) == EOF ) + return(0); + + Mf_toberead = read32bit(); + if (midifile_error) return MIDIFILE_ERROR; + format = read16bit(); + if (midifile_error) return MIDIFILE_ERROR; + ntrks = read16bit(); + if (midifile_error) return MIDIFILE_ERROR; + division = read16bit(); + if (midifile_error) return MIDIFILE_ERROR; + + if ( Mf_header ) + (*Mf_header)(format,ntrks,division); + + /* flush any extra stuff, in case the length of header is not 6 */ + while ( Mf_toberead > 0 && !midifile_error) + (void) egetc(); + return(ntrks); +} + +static void +readtrack() /* read a track chunk */ +{ + /* This array is indexed by the high half of a status byte. It's */ + /* value is either the number of bytes needed (1 or 2) for a channel */ + /* message, or 0 (meaning it's not a channel message). */ + static int chantype[] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 through 0x70 */ + 2, 2, 2, 2, 1, 1, 2, 0 /* 0x80 through 0xf0 */ + }; + long lookfor, lng; + int c, c1, type; + int sysexcontinue = 0; /* 1 if last message was an unfinished sysex */ + int running = 0; /* 1 when running status used */ + int status = 0; /* (possibly running) status byte */ + int needed; + + if ( readmt("MTrk",0) == EOF ) + return; + + Mf_toberead = read32bit(); + + if (midifile_error) return; + + Mf_currtime = 0L; + + if ( Mf_starttrack ){ + + (*Mf_starttrack)(); + } + while ( Mf_toberead > 0 ) { + + Mf_currtime += readvarinum(); /* delta time */ + if (midifile_error) return; + + c = egetc(); if (midifile_error) return; + + if ( sysexcontinue && c != 0xf7 ) { + mferror("didn't find expected continuation of a sysex"); + return; + } + if ( (c & 0x80) == 0 ) { /* running status? */ + if ( status == 0 ) { + mferror("unexpected running status"); + return; + } + running = 1; + } + else { + status = c; + running = 0; + } + + needed = chantype[ (status>>4) & 0xf ]; + + if ( needed ) { /* ie. is it a channel message? */ + + if ( running ) + c1 = c; + else { + c1 = egetc(); + if (midifile_error) return; + } + chanmessage( status, c1, (needed>1) ? egetc() : 0 ); + if (midifile_error) return; + continue;; + } + + switch ( c ) { + + case 0xff: /* meta event */ + + type = egetc(); + if (midifile_error) return; + /* watch out - Don't combine the next 2 statements */ + lng = readvarinum(); + if (midifile_error) return; + lookfor = Mf_toberead - lng; + msginit(); + + while ( Mf_toberead > lookfor ) { + char c = egetc(); + if (midifile_error) return; + msgadd(c); + } + metaevent(type); + break; + + case 0xf0: /* start of system exclusive */ + + /* watch out - Don't combine the next 2 statements */ + lng = readvarinum(); + if (midifile_error) return; + lookfor = Mf_toberead - lng; + msginit(); + msgadd(0xf0); + + while ( Mf_toberead > lookfor ) { + c = egetc(); + if (midifile_error) return; + msgadd(c); + } + if ( c==0xf7 || Mf_nomerge==0 ) + sysex(); + else + sysexcontinue = 1; /* merge into next msg */ + break; + + case 0xf7: /* sysex continuation or arbitrary stuff */ + + /* watch out - Don't combine the next 2 statements */ + lng = readvarinum(); + if (midifile_error) return; + lookfor = Mf_toberead - lng; + + if ( ! sysexcontinue ) + msginit(); + + while ( Mf_toberead > lookfor ) { + c = egetc(); + if (midifile_error) return; + msgadd(c); + } + if ( ! sysexcontinue ) { + if ( Mf_arbitrary ) + (*Mf_arbitrary)(msgleng(),msg()); + } + else if ( c == 0xf7 ) { + sysex(); + sysexcontinue = 0; + } + break; + default: + + badbyte(c); + + break; + } + } + if ( Mf_endtrack ) + (*Mf_endtrack)(); + return; +} + +static void +badbyte(c) +int c; +{ + char buff[32]; + + (void) sprintf(buff,"unexpected byte: 0x%02x",c); + mferror(buff); +} + +static void +metaevent(type) +{ + int leng = msgleng(); + char *m = msg(); + + switch ( type ) { + case 0x00: + if ( Mf_seqnum ) + (*Mf_seqnum)(to16bit(m[0],m[1])); + break; + case 0x01: /* Text event */ + case 0x02: /* Copyright notice */ + case 0x03: /* Sequence/Track name */ + case 0x04: /* Instrument name */ + case 0x05: /* Lyric */ + case 0x06: /* Marker */ + case 0x07: /* Cue point */ + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + /* These are all text events */ + if ( Mf_text ) + (*Mf_text)(type,leng,m); + break; + case 0x2f: /* End of Track */ + if ( Mf_eot ) + (*Mf_eot)(); + break; + case 0x51: /* Set tempo */ + if ( Mf_tempo ) + (*Mf_tempo)(to32bit(0,m[0],m[1],m[2])); + break; + case 0x54: + if ( Mf_smpte ) + (*Mf_smpte)(m[0],m[1],m[2],m[3],m[4]); + break; + case 0x58: + if ( Mf_timesig ) + (*Mf_timesig)(m[0],m[1],m[2],m[3]); + break; + case 0x59: + if ( Mf_keysig ) + (*Mf_keysig)(m[0],m[1]); + break; + case 0x7f: + if ( Mf_sqspecific ) + (*Mf_sqspecific)(leng,m); + break; + default: + if ( Mf_metamisc ) + (*Mf_metamisc)(type,leng,m); + } +} + +static void +sysex() +{ + if ( Mf_sysex ) + (*Mf_sysex)(msgleng(),msg()); +} + +static void +chanmessage(status,c1,c2) +int status; +int c1, c2; +{ + int chan = status & 0xf; + + switch ( status & 0xf0 ) { + case NOTEOFF: + if ( Mf_off ) + (*Mf_off)(chan,c1,c2); + break; + case NOTEON: + if ( Mf_on ) + (*Mf_on)(chan,c1,c2); + break; + case PRESSURE: + if ( Mf_pressure ) + (*Mf_pressure)(chan,c1,c2); + break; + case CONTROLLER: + if ( Mf_controller ) + (*Mf_controller)(chan,c1,c2); + break; + case PITCHBEND: + if ( Mf_pitchbend ) + (*Mf_pitchbend)(chan,c1,c2); + break; + case PROGRAM: + if ( Mf_program ) + (*Mf_program)(chan,c1); + break; + case CHANPRESSURE: + if ( Mf_chanpressure ) + (*Mf_chanpressure)(chan,c1); + break; + } +} + +/* readvarinum - read a varying-length number, and return the */ +/* number of characters it took. */ + +static long +readvarinum() +{ + long value; + int c; + + c = egetc(); + if (midifile_error) return 0; + + value = (long) c; + if ( c & 0x80 ) { + value &= 0x7f; + do { + c = egetc(); + if (midifile_error) return 0; + value = (value << 7) + (c & 0x7f); + } while (c & 0x80); + } + return (value); +} + +static long +to32bit(c1,c2,c3,c4) +{ + long value = 0L; + + value = (c1 & 0xff); + value = (value<<8) + (c2 & 0xff); + value = (value<<8) + (c3 & 0xff); + value = (value<<8) + (c4 & 0xff); + return (value); +} + +static int +to16bit(c1,c2) +int c1, c2; +{ + return ((c1 & 0xff ) << 8) + (c2 & 0xff); +} + +static long +read32bit() +{ + int c1, c2, c3, c4; + + c1 = egetc(); if (midifile_error) return 0; + c2 = egetc(); if (midifile_error) return 0; + c3 = egetc(); if (midifile_error) return 0; + c4 = egetc(); if (midifile_error) return 0; + return to32bit(c1,c2,c3,c4); +} + +static int +read16bit() +{ + int c1, c2; + c1 = egetc(); if (midifile_error) return 0; + c2 = egetc(); if (midifile_error) return 0; + return to16bit(c1,c2); +} + +static void +mferror(s) +char *s; +{ + if ( Mf_error ) + (*Mf_error)(s); + midifile_error = 1; +} + +/* The code below allows collection of a system exclusive message of */ +/* arbitrary length. The Msgbuff is expanded as necessary. The only */ +/* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */ + +#define MSGINCREMENT 128 +static char *Msgbuff = 0; /* message buffer */ +static int Msgsize = 0; /* Size of currently allocated Msg */ +static int Msgindex = 0; /* index of next available location in Msg */ + +static void +msginit() +{ + Msgindex = 0; +} + +static char * +msg() +{ + return(Msgbuff); +} + +static int +msgleng() +{ + return(Msgindex); +} + +static void +msgadd(c) +int c; +{ + /* If necessary, allocate larger message buffer. */ + if ( Msgindex >= Msgsize ) + msgenlarge(); + Msgbuff[Msgindex++] = c; +} + +static void +msgenlarge() +{ + char *newmess; + char *oldmess = Msgbuff; + int oldleng = Msgsize; + + Msgsize += MSGINCREMENT; + newmess = MALLOC((sizeof(char)*Msgsize) ); + + /* copy old message into larger new one */ + if ( oldmess != 0 ) { + register char *p = newmess; + register char *q = oldmess; + register char *endq = &oldmess[oldleng]; + + for ( ; q!=endq ; p++,q++ ) + *p = *q; + free(oldmess); + } + Msgbuff = newmess; +} diff --git a/cmt/midifile.h b/cmt/midifile.h new file mode 100644 index 0000000..a759d76 --- /dev/null +++ b/cmt/midifile.h @@ -0,0 +1,27 @@ +extern void midifile(void); +extern int (*Mf_getc)(void); +extern void (*Mf_header)(int,int,int); +extern void (*Mf_starttrack)(void); +extern void (*Mf_endtrack)(void); +extern void (*Mf_on)(int,int,int); +extern void (*Mf_off)(int,int,int); +extern void (*Mf_pressure)(int,int,int); +extern void (*Mf_controller)(int,int,int); +extern void (*Mf_pitchbend)(int,int,int); +extern void (*Mf_program)(int,int); +extern void (*Mf_chanpressure)(int,int); +extern void (*Mf_sysex)(int,char*); +extern void (*Mf_metamisc)(int,int,char*); +extern void (*Mf_sqspecific)(int,char*); +extern void (*Mf_seqnum)(int); +extern void (*Mf_text)(int,int,char*); +extern void (*Mf_eot)(void); +extern void (*Mf_timesig)(int,int,int,int); +extern void (*Mf_smpte)(int,int,int,int,int); +extern void (*Mf_tempo)(int); +extern void (*Mf_keysig)(int,int); +extern void (*Mf_arbitrary)(int,char*); +extern void (*Mf_error)(char *); +extern long Mf_currtime; +extern int Mf_nomerge; +extern int Mf_skipinit; diff --git a/cmt/midifns.c b/cmt/midifns.c new file mode 100644 index 0000000..e8f7482 --- /dev/null +++ b/cmt/midifns.c @@ -0,0 +1,1886 @@ +/***************************************************************************** +* midifns.c +* Copyright 1989 Carnegie Mellon University +* Date | Change +*-----------+----------------------------------------------------------------- +* 29-Mar-88 | Created from IBM PC version of mpu.c +* | Added settime() +* 02-May-88 | AMIGA 2000 version. portable version. +* 12-Oct-88 | JCD : Exclusive AMIGA Version. +* 13-Apr-89 | JCD : New portable version. +* 19-Apr-89 | JCD : Amiga CAMD Version added. +* 5-Apr-91 | JDW : Further modification +* 17-Feb-92 | GWL : incorporate JMN's new mpu.c +* 8-Jun-92 | JDZ : add support for ITC midi interface +* 16-Dec-92 | RBD : replace JMN's mpu.c with LMS's mpu.c +* 11-Mar-94 | PLu : port to IRIX +* 25-Apr-97 | RBD : it looks like SGI changed their interface. I +* | made it compile again, but MIDI does not work, so +* | took out calls to actually send/recv MIDI data +* 28-Apr-03 | DM : Renamed random -> cmtrand, true->TRUE, false->FALSE +* | Use features rather than system names in #ifdef's +*****************************************************************************/ + +#include "switches.h" + +#ifdef UNIX +#include +#include +#ifndef OPEN_MAX +/* this is here for compiling the UNIX version under AIX. This is a BSDism */ +#define OPEN_MAX 2000 +#endif /* OPEN_MAX */ +#endif /* UNIX */ + +#ifdef UNIX_MACH +#include "machmidi.h" +#endif + + +#ifdef AMIGA +#ifdef AZTEC +#include "functions.h" +#endif /* AZTEC */ +#include "midi/camd.h" +#include "clib/camd_protos.h" +/* note: azt_camd_pragmas.h was produced by running MAPFD on the + * lib/camd_lib.fd file included in the CAMD disk from Commodore. + * The "CamdClient" calls are manually removed from + */ +#ifdef AZTEC +#include "pragmas/azt_camd_pragmas.h" +#else /* !AZTEC */ +#include "pragmas/lat_camd_pragmas.h" +#endif /* AZTEC */ +#include "camdmidi.h" +#include "ctype.h" +#endif /* AMIGA */ + +#ifdef UNIX_IRIX +/* #define UNIX_IRIX_MIDIFNS -- this would enable actual midi I/O + * if the actual midi I/O code worked + */ +/* IRIX changed the MIDI interface, + * retain this for older systems: + */ +#ifdef UNIX_IRIX_MIDIFNS +#include +#endif +#endif + +#include "stdio.h" +#include "cext.h" +#include "midicode.h" +#include "cmdline.h" +#include "pitch.h" +#include "midifns.h" +#include "userio.h" +#include "string.h" +#ifdef MACINTOSH_OR_DOS +#ifndef WINDOWS +#include "midibuff.h" +#endif +#endif + +#ifdef UNIX_ITC /* was ITC */ +#include "sys/param.h" +/* since boolean is defined, block its definition in midistruct.h. + * CMT defines boolean as ushort, but midistruct.h uses int. + * This is not a problem on RS/6000s, but beware! + */ +/* the following would be included if we had the BSD switch set. I think + we should try to avoid BSDisms; when fixed, the following should be + removed + */ +#define NBBY 8 +#include "sys/select.h" /* defines fd_set */ +#define MIDI_HAS_BOOLEAN +#include "midistruct.h" +#include "cmtio.h" +#endif /* UNIX_ITC */ + +#ifdef DOS +#ifndef WINDOWS +#include "timer.h" +#include "mpu.h" +#endif /* ifndef WINDOWS */ +#endif /* ifdef DOS */ + +#ifndef BREAKTEST +#define BREAKTEST +#endif + +#ifdef __APPLE__ +#include +#include +#include +#else +#ifdef UNIX +#ifndef UNIX_IRIX +#include "sys/time.h" +#include "sys/timeb.h" +#include "cmtio.h" +#else +#include +#include +#include + +#ifdef UNIX_IRIX_MIDIFNS +#include +#include +#endif /* UNIX_IRIX_MIDIFNS */ +#endif /* UNIX_IRIX */ +#endif /* UNIX */ +#endif /* __APPLE__ */ + +#ifdef ITC +static int ignore_realtime = 0; +#endif /* ITC */ + +#ifdef MACINTOSH + +/* added for ThinkC 7: */ +#include + +/* port numbers are in the range 0..MAX_PORTS-1 */ +#define CHANNELS_PER_PORT 16 +#define MAX_PORTS ((MAX_CHANNELS + CHANNELS_PER_PORT - 1) / CHANNELS_PER_PORT) + +/* here are some MIDIMGR specific definitions */ +#ifdef MIDIMGR +#include "MIDI.h" +#include "midimgr.h" + +#define TICKS_TO_MS(t) t +#define MS_TO_TICKS(t) t + +#else +/* here are some non-MIDIMGR definitions for the Mac */ +/**************************************************************************** +* +* DMH: constants from macmidi.c +* +****************************************************************************/ + +/* the modem port, also called port A */ +#define portA 0 + +/* the printer port, also called port B */ +#define portB 1 + +/* a tick is 1/60 of a second + * + * the following tables and routines are used to convert + * between ticks and milliseconds + */ +#define TICKS_TO_MS(t) (((t) * 50) / 3) +#define MS_TO_TICKS(t) (((t) * 3) / 50) +#endif /* def MIDIMGR */ +#endif /* def MACINTOSH */ + +#ifdef WINDOWS +#define huge +#endif + +/**************************************************************************** +* +* exported flags +* +****************************************************************************/ + +boolean miditrace = FALSE; /* enables printed trace of MIDI output */ +boolean musictrace = FALSE; /* enables printed trace of commands */ +#ifdef MACINTOSH_OR_DOS +boolean ctrlFilter = TRUE; /* suppress continuous controller data */ +boolean exclFilter = TRUE; /* suppress exclusive messages */ +boolean realFilter = TRUE; /* suppress realtime messages */ +#endif + +/**************************************************************************** +* +* exported variables +* +****************************************************************************/ + +public int keyloud; /* set to velocity of last getkey event */ +/* public long error; */ +public short midi_error_flags = 0; + +/* The following midifns_syntax lists command line switches and options. + Since these are machine dependent, use conditional compilation. + Conditional compilation within a string is a bit tricky: you want to + write "\" for line continuation within the string, but "\" gets eaten + by the macro preprocessor. + That's why we define macros like AMIGAINPORT. + Regretably it doesn't work for all compilers. + */ + + +/* Lattice and RT/Unix aren't happy expanding the embedded macros below, so + I made a separate declaration of midifns_syntax for Unix + */ +#ifdef UNIX +public char *midifns_syntax = "blockTurn off midi THRU;\ + miditraceTrace low-level midi functions;\ + noalloffDo not send alloff message when done;\ + traceTrace music operations;\ + tuneLoad a tuning file"; +#else +#ifdef MACINTOSH +#ifdef MIDIMGR +public char *midifns_syntax = "miditraceTrace low-level midi functions;\ + noalloffDo not send alloff message when done;\ + patchRemember/reuse Midi Mgr patches;\ + traceTrace music operations;\ + keepKeep other processes running;\ + tuneLoad a tuning file"; +#else /* no MIDIMGR */ +public char *midifns_syntax = "miditraceTrace low-level midi functions;\ + noalloffDo not send alloff message when done;\ + patchRemember/reuse Midi Mgr patches;\ + traceTrace music operations;\ + tuneLoad a tuning file"; +#endif /* MIDIMGR */ +#else +#ifdef AMIGA +public char *midifns_syntax = "blockTurn off midi THRU;\ + inportInpur port number;\ + miditraceTrace low-level midi functions;\ + noalloffDo not send alloff message when done;\ + outportOutput port number;\ + traceTrace music operations;\ + tuneLoad a tuning file"; +#else /* not UNIX or MACINTOSH or MIDIMGR or AMIGA */ +#ifdef DOS +public char *midifns_syntax = "miditraceTrace low-level midi functions;\ + noalloffDo not send alloff message when done;\ + traceTrace music operations;\ + tuneLoad a tuning file"; +#endif /* DOS */ +#endif /* AMIGA */ +#endif /* MACINTOSH */ +#endif /* UNIX */ + +#ifdef MACINTOSH +boolean do_midi_thru = FALSE; /* exported: copy midi in to midi out */ +#endif + + +/**************************************************************************** +* +* local module variables +* +****************************************************************************/ + +private int initialized = FALSE; /* set by musicinit, cleared by musicterm */ +private boolean tune_flag = FALSE; /* set by musicinit, never cleared */ +#ifdef DOS +private boolean metroflag = FALSE; /* flag to turn on metronome */ +#endif +private int user_scale = FALSE; /* TRUE if user-defined scale */ +private int bend[MAX_CHANNELS]; /* current pitch bend on channel */ +short cur_midi_prgm[MAX_CHANNELS]; +private pitch_table pit_tab[128]; /* scale definition */ + +#ifdef DOS +private ulong timeoffset = 0; +public boolean exclerr = FALSE; +public byte xcodemask; /* mask (00 or FF) */ +public byte xcode; /* mfr code */ +#endif + +#ifdef MACINTOSH_OR_DOS +boolean sysex_pending = FALSE; +#endif + +#ifdef AMIGA + +#define CONTCONT ((CMF_Ctrl & ~CMF_CtrlSwitch) | CMF_PitchBend | \ + CMF_ChanPress) +#endif /* def AMIGA */ + +#ifdef UNIX +private ulong timeoffset = 0; +#endif + +#ifdef UNIX_IRIX_MIDIFNS +static MIport *miport; +static int ignore_realtime = 0; + +private byte *sysex_p; +private int sysex_n; +#endif + +#ifdef ITC +mi_id midiconn; +#endif + +#ifdef MACINTOSH +private ulong ticksAtStart = 0L; + /* clock ticks at time of last musicinit or timereset + * ASSUME: tick clock never wraps. this is a good assumption, since + * the tick clock is set to zero when the power is turned on and the + * tick counter is 32 bits. the Macintosh would need to be on for + * 828.5 days for the tick counter to wrap around! */ + +#endif /* def MACINTOSH */ + +/**************************************************************************** +* +* functions declared in this module +* +****************************************************************************/ + +private void fixup(); +private void midi_init(); +extern boolean check_ascii(); /*userio.c*/ +private void musicterm(); + + +/**************************************************************************** +* alloff +* Inputs: +* none +* Effect: +* Sends MIDI all notes off command on every channel. +****************************************************************************/ + +#define ALL_NOTES_OFF 0x7B /*DMH: from macmidi.c*/ + +void alloff() +{ + int c; + + if (!initialized) fixup(); + if (musictrace) + gprintf(TRANS,"alloff()\n"); + for (c = 1; c <= MAX_CHANNELS; c++) { + midi_write(3, MIDI_PORT(c), (byte) (0xb0 | MIDI_CHANNEL(c)), ALL_NOTES_OFF, 0); + } +} + + + +/*************************************************************** +* eventwait +* +* Input : wakeup time, -1 means forever +* Output : none +* Return: none +* Effect: waits until ascii or midi input or timeout +***************************************************************/ + +#ifdef UNIX_ITC +void eventwait(timeout) + long timeout; +{ + struct timeval unix_timeout; + struct timeval *waitspec = NULL; + fd_set readfds; + struct rlimit file_limit; + + FD_ZERO(&readfds); + FD_SET(MI_CONNECTION(midiconn), &readfds); + FD_SET(fileno(stdin), &readfds); + if (timeout >= 0) { + timeout -= gettime(); /* convert to millisecond delay */ + unix_timeout.tv_sec = timeout / 1000; + /* remainder become microsecs: */ + unix_timeout.tv_usec = (timeout - (unix_timeout.tv_sec * 1000)) * 1000; + waitspec = &unix_timeout; + } + getrlimit(RLIMIT_NOFILE, &file_limit); + select(file_limit.rlim_max+1, &readfds, 0, 0, waitspec); + return; +} +#else /* !UNIX_ITC */ +#ifdef UNIX +/* see machmidi.c for UNIX_MACH implementation */ +#ifndef UNIX_MACH +#ifdef UNIX_IRIX_MIDIFNS +void eventwait(timeout) + long timeout; +{ + struct timeval unix_timeout; + struct timeval *waitspec = NULL; + fd_set readfds; + + FD_ZERO(&readfds); + FD_SET(mdGetFd(miport), &readfds); + FD_SET(fileno(stdin), &readfds); + if (timeout >= 0) { + + timeout -= gettime(); /* convert to millisecond delay */ + unix_timeout.tv_sec = timeout / 1000; + /* remainder become microsecs: */ + unix_timeout.tv_usec = (timeout - (unix_timeout.tv_sec * 1000)) * 1000; + waitspec = &unix_timeout; + } + select(FD_SETSIZE, &readfds, 0, 0, waitspec); + + return; +} +#else +#ifdef BUFFERED_SYNCHRONOUS_INPUT +void eventwait(timeout) + long timeout; +{ + struct timeval unix_timeout; + struct timeval *waitspec = NULL; + struct rlimit file_limit; + + if (timeout >= 0) { + timeout -= gettime(); /* convert to millisecond delay */ + unix_timeout.tv_sec = timeout / 1000; + /* remainder become microsecs: */ + unix_timeout.tv_usec = (timeout - (unix_timeout.tv_sec * 1000)) * 1000; + waitspec = &unix_timeout; + getrlimit(RLIMIT_NOFILE, &file_limit); + select(file_limit.rlim_max+1, 0, 0, 0, waitspec); + } else { + int c = getc(stdin); + ungetc(c, stdin); + } + return; +} +#else +void eventwait(timeout) + long timeout; +{ + struct timeval unix_timeout; + struct timeval *waitspec = NULL; + int readfds = 1 << IOinputfd; + struct rlimit file_limit; + + if (timeout >= 0) { + timeout -= gettime(); /* convert to millisecond delay */ + unix_timeout.tv_sec = timeout / 1000; + /* remainder become microsecs: */ + unix_timeout.tv_usec = (timeout - (unix_timeout.tv_sec * 1000)) * 1000; + waitspec = &unix_timeout; + } + getrlimit(RLIMIT_NOFILE, &file_limit); + select(file_limit.rlim_max+1, &readfds, 0, 0, waitspec); + return; +} +#endif /* BUFFERED_SYNCHRONOUS_INPUT */ +#endif /* UNIX_IRIX */ +#endif /* UNIX_MACH */ +#endif /* UNIX */ /* I wanted to put an else here, but this confused a Unix C compiler */ +#endif /* UNIX_ITC */ +#ifdef AMIGA +/* see camdmidi.c for Amiga implementation */ +#else +#ifndef UNIX /* since I couldn't use an else above, have to check UNIX here */ +#ifdef WINDOWS +void eventwait(timeout) + long timeout; +{ + if (timeout >= 0) { + gprintf(TRANS, "eventwait: not implemented\n"); + return; + } else { + int c = getc(stdin); + ungetc(c, stdin); + } + return; +} +#else +void eventwait(timeout) + long timeout; +{ + while (timeout > gettime() || timeout == -1) { + if (check_ascii() || check_midi()) return; + } +} +#endif /* WINDOWS */ +#endif /* UNIX */ +#endif /* AMIGA */ + + +/**************************************************************************** +* exclusive +* Inputs: +* boolean onflag -- set to TRUE to receive midi exclusive data +* Effect: +* Tells module to read exclusive messages into buffer +****************************************************************************/ + +void exclusive(boolean onflag) +{ + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS, "exclusive: %d\n", onflag); +#ifdef AMIGA + if (onflag) SetMidiFilters(cmt_mi, + cmt_mi->PortFilter, cmt_mi->TypeFilter | CMF_SysEx, cmt_mi->ChanFilter); + else SetMidiFilters(cmt_mi, + cmt_mi->PortFilter, cmt_mi->TypeFilter & ~CMF_SysEx, cmt_mi->ChanFilter); +#endif +#ifdef MACINTOSH_OR_DOS + exclFilter = !onflag; +#endif +} + + +/**************************************************************************** +* fixup +* Effect: +* Print error message and call musicinit +****************************************************************************/ + +private void fixup() +{ + gprintf(ERROR, "You forgot to call musicinit. I'll do it for you.\n"); + musicinit(); +} + +#ifdef UNIX_IRIX_MIDIFNS +private void flush_sysex(void); +#endif + +long get_excl(byte *buffer, long len) +{ + long ret = 0; +#ifdef UNIX_IRIX_MIDIFNS + byte *sxp = sysex_p; + long l = len; +#endif +#ifdef UNIX_ITC /* was ITC */ + ret = mi_getx(midiconn, FALSE, len, (char *) buffer); +#endif +#ifdef UNIX_MACH + ret = mi_getx(midiconn, FALSE, len, (unsigned char *)buffer); +#endif +#ifdef UNIX_IRIX_MIDIFNS + if (!sysex_p) return 0; + if (len > sysex_n) len = sysex_n; + while (l--) + { + *buffer = *(sxp++); + if (*(buffer++) == CMT_MIDI_EOX) + { + flush_sysex(); + break; + } + } + ret = len - l - 1; +#endif +#ifdef AMIGA + ret = GetSysEx(cmt_mi, (UBYTE *) buffer, len); + AMIGA_ERROR_CHECK; +#endif +#ifdef MACINTOSH_OR_DOS +#ifndef WINDOWS + /* I'm not sure the following line is a good thing: it forces the + * caller to wait until a full sysex message is received and the + * 1st 4 bytes are fetched via getbuf() before a sysex message can + * be read via get_excl(). Without this, both mm.c and exget.c + * were fetching ahead and getting out of sync with getbuf(). I + * fixed mm.c and exget.c to work (by checking for EOX), but I added + * this line (which should never have any effect) just to make the + * DOS interface behave more like the Amiga and Mac interfaces. The + * drawback is that you can't fetch bytes until the EOX is seen, + * because nothing goes into the getbuf() buffer until then. + */ + if (!sysex_pending) return 0; + while (len-- && (xbufhead != xbuftail)) { + *buffer = xbuff[xbufhead++]; + ret++; + if (*buffer == MIDI_EOX) { + sysex_pending = FALSE; + break; + } + buffer++; + xbufhead &= xbufmask; + } +#endif +#endif + return ret; +} + +/**************************************************************************** +* getbuf +* Inputs: +* boolean waitflag: TRUE if routine should wait for data +* byte * p: Pointer to data destination +* Result: boolean +* TRUE if data was written to *p +* FALSE if data not written to *p +* Effect: +* copies data from buffer to *p +* will wait for buffer to become nonempty if waitflag is TRUE +* +* Modified 24 May 1988 for AMIGA (JCD) +****************************************************************************/ + +#ifdef UNIX_IRIX_MIDIFNS + private void setup_sysex(MDevent *event, u_char *buffer); +#endif /* UNIX_IRIX */ +boolean getbuf(boolean waitflag, unsigned char * p) +{ +#ifdef UNIX_IRIX_MIDIFNS + MDevent event; + int ret; +#endif /* UNIX_IRIX */ + + if (!initialized) fixup(); +#ifdef UNIX +#ifdef UNIX_IRIX_MIDIFNS +/* current IRIX version ignores the waitflag (it never waits) */ + + if (sysex_p) flush_sysex(); + if (ignore_realtime == 0) { + ret = mdReceive(miport, &event, 1); + if (ret) { + if (event.msg[0] != 0xF0) { + *((u_long*) p) = *((u_long*) event.msg); + } else { + setup_sysex(&event, p); + } + } + return ret; + } else { + do /* skip realtime messages */ + { + ret = mdReceive(miport, &event, 1); + if (ret == -1) return ret; + } while (event.msg[0] == 0xf8); + if (event.msg[0] != 0xF0) { + *((u_long*) p) = *((u_long*) event.msg); + } else { + setup_sysex(&event, p); + } + return ret; + } +#endif /* UNIX_IRIX */ +#ifdef UNIX_ITC + if (ignore_realtime == 0) { + return(mi_get(midiconn, waitflag, (char *) p)); + } + else { + boolean ret=false; + /* filter out realtime msgs */ + do { + ret = mi_get(midiconn, waitflag, (char *) p); + if (ret == FALSE) + return(ret); + } while(p[0] == 0xf8); + return(ret); + } +#else /* UNIX_ITC */ +#ifndef UNIX_IRIX + if (waitflag) { + gprintf(ERROR, "getbuf called with waitflag!"); + EXIT(1); + } + return FALSE; +#endif /* UNIX_IRIX */ +#endif /* UNIX_ITC */ +#endif /* UNIX */ + +#ifdef MACINTOSH_OR_DOS +#ifndef WINDOWS + if (sysex_pending) { /* flush sysex to keep buffers in sync */ + while (xbuff[xbufhead++] != MIDI_EOX) { + xbufhead &= xbufmask; + if (xbufhead == xbuftail) break; + } + sysex_pending = FALSE; + } + if (waitflag) while (buffhead == bufftail) /* wait */ ; + else if (buffhead == bufftail) return(false); + *(long *)p = *(long *)(((char *)buff)+buffhead); + buffhead = (buffhead + 4) & BUFF_MASK; + if (*p == MIDI_SYSEX) { /* if sys-ex, remember to fetch from xbuff */ + sysex_pending = TRUE; + } + return(true); +#else + return FALSE; +#endif /* WINDOWS */ +#endif /* MACINTOSH_OR_DOS */ + +#ifdef AMIGA + if (waitflag) { + do { + WaitMidi(cmt_mi, &cmt_msg); + AMIGA_ERROR_CHECK; + } while (amigaerrflags); + } else { + AMIGA_ERROR_CHECK; + if (!GetMidi(cmt_mi, &cmt_msg)) return(false); + } + *(long *)p = *(long *)&cmt_msg; + clearmsg(cmt_msg); + return(true); +#endif /* AMIGA */ +} + +#ifdef UNIX_IRIX_MIDIFNS + +private void setup_sysex(MDevent *event, u_char *buffer) +/* N.B. do not leak memory remember to call free(sysex_p) */ +{ + u_char *sxp = (u_char *) event->sysexmsg; + int i; + + for (i=0;i<4;i++) + *(buffer++) = *(sxp++); + sysex_p = event->sysexmsg; + sysex_n = event->msglen; +} + +private void flush_sysex() +{ + mdFree(sysex_p); + sysex_p = 0; + sysex_n = 0; +} +#endif + +#ifdef MACINTOSH_OR_DOS +#ifndef WINDOWS +public boolean check_midi() +{ + if (buffhead == bufftail) return FALSE; + else return TRUE; +} +#endif +#endif + + +/**************************************************************************** +* getkey +* Inputs: +* boolean waitflag: TRUE if wait until key depression, FALSE if +* return immediately +* Result: int +* key number of key which has been depressed +* It returns -1 if waitflag is FALSE and no key has been pressed +* If waitflag is TRUE this routine will block until a key is pressed +* Effect: +* reads a key +****************************************************************************/ + +/*DMH: in previous version, macmidi.c subtracted 12 from msg to get key at each occurence...*/ + +short getkey(boolean waitflag) +{ + byte msg[4]; + short k; + + if (!initialized) fixup(); + + while (TRUE) { /* process data until you find a note */ + /* look for data and exit if none found */ + /* NOTE: waitflag will force waiting until data arrives */ + if (!getbuf(waitflag, msg)) { /* nothing there */ + k = -1; + break; + } else if ((msg[0] & MIDI_CODE_MASK) == MIDI_ON_NOTE) { + if (msg[2] == 0) { /* velocity 0 -> note off */ + keyloud = 0; + k = msg[1] + 128; + } else { + keyloud = msg[2]; + k = msg[1]; + } + break; + } else if ((msg[0] & MIDI_CODE_MASK) == MIDI_OFF_NOTE) { + keyloud = 0; + k = msg[1] + 128; + break; + } + } + if (musictrace) { + if (k != -1) gprintf(TRANS,"getkey got %d\n", k); + } + return k; +} + + +/**************************************************************************** +* gettime +* Result: ulong +* current timestamp since the last call to +* musicinit or timereset +* Effect: +* fakes it +****************************************************************************/ + +ulong gettime() /*DMH: ulong is from mpu->midifns conversion, for Mac*/ +{ +#if HAS_GETTIMEOFDAY + struct timeval timeval; +#endif +#if HAS_FTIME + struct timeb ftime_res; +#endif + register ulong ticks = 0L; + + BREAKTEST /* abort if user typed Ctrl Break */ + if (!initialized) fixup(); + +#ifdef MACINTOSH +#ifdef MIDIMGR + ticks = MIDIGetCurTime(OutputRefNum) - ticksAtStart; +#else + ticks = TickCount() - ticksAtStart; +#endif + if (initialized) abort_check(); /* give user a chance to abort */ + ticks = TICKS_TO_MS(ticks); +#endif + +#ifdef AMIGA + ticks = (*camdtime - timeoffset) << 1; /* return milliseconds */ +#endif + +#ifdef DOS +#ifndef WINDOWS + ticks = elapsedtime(timeoffset, readtimer()); /* return milliseconds */ + /* gprintf(TRANS, "currtime = %ld, timeoffset = %ld\n", currtime, timeoffset); */ +#endif +#endif /* ifdef DOS */ + +#if HAS_GETTIMEOFDAY + gettimeofday(&timeval, 0); + ticks = timeval.tv_sec * 1000 + timeval.tv_usec / 1000 - timeoffset; +#endif +#if HAS_FTIME + ftime(&ftime_res); + ticks = ((ftime_res.time - timeoffset) * 1000) + ftime_res.millitm; +#endif + + /* if (miditrace) gprintf(TRANS, "."); */ + return(ticks); +} + + +/**************************************************************************** +* l_rest +* Inputs: +* long time: Amount of time to rest +* Effect: +* Waits until the amount of time specified has lapsed +****************************************************************************/ + +void l_rest(time) +long time; +{ + if (!initialized) fixup(); + l_restuntil(time + gettime()); +} + +/**************************************************************************** +* l_restuntil +* Inputs: +* long time: Event time to rest until +* Effect: +* Waits until the specified time has been reached (absolute time) +****************************************************************************/ + +void l_restuntil(time) +long time; +{ +#ifdef MACINTOSH + ulong now = gettime(); + ulong junk; /* changed from ulong for ThinkC 7, back to ulong for CW5 */ +#endif + +#ifdef AMIGA + while (time > gettime()) eventwait(time); +#else + for(; (time_type) time > gettime();); +#endif + +#ifdef MACINTOSH + now = gettime(); + + if (time > now) Delay(MS_TO_TICKS(time - now), &junk); + /* else time <= now, so return immediately */ +#endif + +} + +/**************************************************************************** +* metronome +* Inputs: +* boolean onflag: TRUE or FALSE +* Effect: +* enables (true) or disables (false) MPU-401 metronome function. +* must be called before musicinit +****************************************************************************/ + +void metronome(boolean onflag) +{ +#ifdef DOS +metroflag = onflag; +#endif +} + + +/**************************************************************************** +* midi_bend +* Inputs: +* int channel: midi channel on which to send data +* int value: pitch bend value +* Effect: +* Sends a midi pitch bend message +****************************************************************************/ + +void midi_bend(int channel, int value) +{ + if (!initialized) fixup(); + if (musictrace) + gprintf(TRANS,"midi_bend: ch %d, val %d\n", channel, value - (1 << 13)); + bend[MIDI_CHANNEL(channel)] = value; + + midi_write(3, MIDI_PORT(channel), (byte) (MIDI_BEND | MIDI_CHANNEL(channel)), + (byte) MIDI_DATA(value), (byte) MIDI_DATA(value >> 7)); +} + + +/**************************************************************************** +* midi_buffer +* Inputs: +* byte * buffer: the buffer address +* int size: number of bytes in buffer +* Returns: +* FALSE if size is less than 16 or buffer is NULL, otherwise TRUE +* Effect: DOS, MAC: +* tells interrupt routine to store system exclusive messages in +* buffer. The largest power of 2 bytes less than size will be +* used. xbufhead and xbuftail will be initialized to zero, +* and xbuftail will be one greater than the index of the last +* system exclusive byte read. Since there may already be a buffer +* and therefore the normal midi message buffer may have the first +* 4 bytes of some sysex messages, clear the normal midi buffer too. +* AMIGA: +* adds buffer to midi interface +* +****************************************************************************/ + +boolean midi_buffer(byte huge *buffer, ulong size) +{ + if (!buffer) return FALSE; +#ifdef AMIGA + if (!SetSysExQueue(cmt_mi, (UBYTE *) buffer, (ULONG) size)) return(false); + cu_register(remove_sysex_buffer, buffer); +#endif + +#ifdef MACINTOSH_OR_DOS +#ifndef WINDOWS + { + int mask = 0x000F; + + if (size < 16) return(false); + while (mask < size && mask > 0) mask = ((mask << 1) | 1); + midi_flush(); + xbuff = NULL; /* turn off buffering */ + xbufmask = mask >> 1; + xbufhead = xbuftail = 0; + xbuff = buffer; /* set buffer, turn on buffering */ + } +#endif +#endif +#ifdef UNIX + return FALSE; +#else + exclusive(TRUE); + return TRUE; +#endif +} + + +/* midi_clock -- send a midi time clock message */ +/**/ +void midi_clock() +{ + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS, "+"); + midi_write(1, 0, MIDI_TIME_CLOCK, 0, 0); +} + + +/**************************************************************************** +* midi_cont +* Inputs: +* boolean onflag: TRUE or FALSE +* Effect: +* enables (true) or disables (false) continuous control +****************************************************************************/ + +void midi_cont(boolean onflag) +{ + if (!initialized) fixup(); + if (onflag) { +#ifdef AMIGA + SetMidiFilters(cmt_mi, cmt_mi->PortFilter, + cmt_mi->TypeFilter | CONTCONT, cmt_mi->ChanFilter); +#endif +#ifdef DOS +#ifndef WINDOWS + mPutCmd(BENDERON); +#endif +#endif + } else { +#ifdef AMIGA + SetMidiFilters(cmt_mi, cmt_mi->PortFilter, + cmt_mi->TypeFilter & ~CONTCONT, cmt_mi->ChanFilter); +#endif + } +#ifdef MACINTOSH_OR_DOS + ctrlFilter = !onflag; +#endif + if (musictrace) gprintf(TRANS,"midi_cont: %d\n", onflag); +} + + +/**************************************************************************** +* midi_ctrl +* Inputs: +* int channel: midi channel on which to send data +* int control: control number +* int value: control value +* Effect: +* Sends a midi control change message +****************************************************************************/ + +void midi_ctrl(int channel, int control, int value) +{ + if (!initialized) fixup(); + if (musictrace) + gprintf(TRANS,"midi_ctrl: ch %d, ctrl %d, val %d\n", + channel, control, value); + + midi_write(3, MIDI_PORT(channel), (byte) (MIDI_CTRL | MIDI_CHANNEL(channel)), + (byte) MIDI_DATA(control), (byte) MIDI_DATA(value)); +} + + +/**************************************************************************** +* midi_exclusive +* Inputs: +* byte *msg: pointer to a midi exclusive message, terminated by 0xF7 +* Effect: +* Sends a midi exclusive message +* Bugs: +* 18-mar-94 PLu : This function does not know which port to send to in +* case of multiple midi-ports (MAC, IRIX) +****************************************************************************/ + +#ifdef MACINTOSH +#define INTERBYTE_DELAY 10 +#endif + +void midi_exclusive(msg) +unsigned char *msg; /* the data to be sent */ +{ +#ifdef ITC + int count, done, tosend, willsend; + unsigned char *m; + mi_status ret; +#endif +#ifdef UNIX_IRIX_MIDIFNS + unsigned char *m; + MDevent mdevent; +#endif + +#ifdef MACINTOSH +#ifndef NYQUIST + int i; /* for DX7 delay loop */ + int count = 0; /* counter for formatting midi byte trace */ + MIDIPacket TheMIDIPacket; + unsigned char prev = 0; + boolean first_packet = TRUE; +#endif +#endif + + /* + * if user mistakenly called midi_exclusive instead of exclusive, + * the argument will be TRUE or FALSE, both of which are highly + * unlikely valid arguments for midi_exclusive: + */ + + if (msg == (byte *) FALSE || msg == (byte *) TRUE) { + gprintf(ERROR,"midi_exclusive: invalid argument %u.\n", msg); + EXIT(1); + } + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS,"midi_exclusive\n"); + +#ifdef AMIGA + PutSysEx(cmt_mi, msg); +#endif +#ifdef MACINTOSH +#ifndef NYQUIST /* if NYQUIST, do nothing */ +#ifdef MIDIMGR + while (prev != MIDI_EOX) { + int len = 0; + while (prev != MIDI_EOX && len < 249) { + TheMIDIPacket.data[len++] = prev = *msg++; + } + TheMIDIPacket.len = 6 + len; + TheMIDIPacket.tStamp = 0; + if (first_packet && (prev != MIDI_EOX)) { + TheMIDIPacket.flags = midiTimeStampCurrent + midiStartCont; + first_packet = FALSE; + } else if (first_packet) { + TheMIDIPacket.flags = midiTimeStampCurrent + midiNoCont; + } else if (prev == MIDI_EOX) { + TheMIDIPacket.flags = midiTimeStampCurrent + midiEndCont; + } else { + TheMIDIPacket.flags = midiTimeStampCurrent + midiMidCont; + } + MIDIWritePacket(OutputRefNum, &TheMIDIPacket); + } +#else + while (*msg != MIDI_EOX) { + Xmit(0, *msg); + msg++; + count++; + /* this is a delay loop, without which your DX7 will crash */ + for (i = INTERBYTE_DELAY; i > 0; i--) + abort_check(); + } + Xmit(0, MIDI_EOX); +#endif /* MIDIMGR */ +#endif /* NYQUIST */ +#endif /* MACINTOSH */ + +#ifdef DOS +#ifndef WINDOWS + do { + mPutData(*msg); + } while (*msg++ != MIDI_EOX); +#endif +#endif +#ifdef ITC + for (m = msg, tosend = 1; (*m) != MIDI_EOX; m++, tosend++); + for (count = 0; count < tosend; count += done) { + willsend = min(16384, tosend); + ret = mi_exclusive(midiconn, 1, msg, (short) willsend); + if (ret != MI_SUCCESS) { + gprintf(GWARN, "Got %d from mi_exclusive\n", ret); + } + done = willsend; + } +#endif +#ifdef UNIX_IRIX_MIDIFNS +/* we don't know which device to sent SYSEX messages to so port zero is + assumed. */ + for (m = msg, mdevent.msglen = 1; (*m) != CMT_MIDI_EOX; m++, mdevent.msglen++); + mdevent.sysexmsg = msg; + if (mdSend(miport, &mdevent, 1) == -1) { + gprintf(GWARN, "could not send SYSEX message\n"); + } +#endif + + if (miditrace) { + do { gprintf(TRANS, "~%2x", *msg); +#ifdef UNIX_IRIX_MIDIFNS + } while (*msg++ != CMT_MIDI_EOX); +#else + } while (*msg++ != MIDI_EOX); +#endif + } +} + + +/**************************************************************************** +* midi_note +* Inputs: +* int channel: midi channel on which to send data +* int pitch: midi pitch code +* int velocity: velocity with which to sound it (0=> release) +* Effect: +* Sends a midi note-play request out +****************************************************************************/ + +void midi_note(int channel, int pitch, int velocity) +{ + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS,"midi_note: ch %d, key %d, vel %d\n", + channel, pitch, velocity); + if (user_scale) { + /* check for correct pitch bend */ + if ((pit_tab[pitch].pbend != bend[MIDI_CHANNEL(channel)]) + && (velocity != 0)) { + midi_bend(channel, pit_tab[pitch].pbend); + bend[channel] = pit_tab[pitch].pbend; + } + pitch = pit_tab[pitch].ppitch; + } + midi_write(3, MIDI_PORT(channel), (byte) (MIDI_ON_NOTE | MIDI_CHANNEL(channel)), + (byte) MIDI_DATA(pitch), (byte) MIDI_DATA(velocity)); +} + + +/**************************************************************************** +* midi_program +* Inputs: +* int channel: Channel on which to send midi program change request +* int program: Program number to send (decremented by 1 before +* being sent as midi data) +* Effect: +* Sends a program change request out the channel +****************************************************************************/ + +void midi_program(int channel, int program) +{ +#ifdef MACINTOSH + int port, midi_chan; +#endif + + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS,"midi_program: ch %d, prog %d\n", + channel, program); + channel = MIDI_CHANNEL(channel); + if (cur_midi_prgm[channel] != program) { + midi_write(2, MIDI_PORT(channel), (byte) (MIDI_CH_PROGRAM | channel), + (byte) (MIDI_PROGRAM(program)), 0); + cur_midi_prgm[channel] = program; + } +} + + +/**************************************************************************** +* midi_real +* Inputs: +* boolean onflag: TRUE or FALSE +* Effect: +* enables (true) or disables (false) midi realtime messages F8-FF +****************************************************************************/ + +void midi_real(boolean onflag) +{ + if (!initialized) fixup(); +#ifdef UNIX_ITC + { + mi_status ret; + + ret = mi_realtime(midiconn, onflag); + if (ret != MI_SUCCESS) { + gprintf(ERROR, "Warning: bad ret = %d in midi_real\n", ret); + } + } +#endif /* UNIX_ITC */ +#ifdef ITC + ignore_realtime = !onflag; +#endif /* ITC */ +#ifdef AMIGA + if (onflag) { + SetMidiFilters(cmt_mi, cmt_mi->PortFilter, + cmt_mi->TypeFilter | CMF_RealTime, cmt_mi->ChanFilter); + } else { + SetMidiFilters(cmt_mi, cmt_mi->PortFilter, + cmt_mi->TypeFilter & ~CMF_RealTime, cmt_mi->ChanFilter); + } +#endif +#ifdef MACINTOSH_OR_DOS + realFilter = !onflag; +#endif + + if (musictrace) gprintf(TRANS,"midi_real: %d\n", onflag); +} + + +/* midi_start -- send a midi start message */ +/**/ +void midi_start() +{ + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS, "`"); + midi_write(1, 0, MIDI_START, 0, 0); +} + + +/* midi_stop -- send a midi stop message */ +/**/ +void midi_stop() +{ + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS, "'"); + midi_write(1, 0 /* ignored */, MIDI_STOP, 0, 0); +} + + +/**************************************************************************** +* midi_thru +* Inputs: +* boolean onflag: TRUE or FALSE +* Effect: +* DOS: enables (true) or disables (false) midi thru info from +* MPU-401 to host. (Default is set; reset with cmdline -block.) +* AMIGA: enables (true) or disables (false) midi route from AMIGA +* midi input to AMIGA midi output. +****************************************************************************/ + +void midi_thru(boolean onflag) /* DMH: midi thru is not supported on the MAC or DOS */ +{ + if (!initialized) fixup(); +#ifndef MIDI_THRU + gprintf(ERROR, "midi_thru called but not implemented\n"); +#else +#ifdef AMIGA + MidiThru(0L, (long) onflag); +#endif +#ifdef MACINTOSH + /* this currently does not do anything - Mac driver doesn't + * support THRU + */ + do_midi_thru = onflag; +#endif +#endif + + if (musictrace) gprintf(TRANS,"midi_thru: %d\n", onflag); +} + + +/**************************************************************************** +* midi_touch +* Inputs: +* int channel: midi channel on which to send data +* int value: control value +* Effect: +* Sends a midi after touch message +****************************************************************************/ + +void midi_touch(int channel, int value) +{ + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS,"midi_touch: ch %d, val %d\n",channel,value); + midi_write(2, MIDI_PORT(channel), (byte) (MIDI_TOUCH | MIDI_CHANNEL(channel)), + (byte) MIDI_DATA(value), 0); +} + + +/**************************************************************************** +* midi_write +* Inputs: +* UBYTE n: number of characters to send (1, 2 or 3); + int port: the port number (usually 0), on MAC, this may be 1 +* char c1,c2,c3: Character(s) to write to MIDI data port +* Effect: +* Writes the data to the serial interface designated by port +**************************************************************************** +* Change log +* Date | Change +*-----------+---------------------------------------------------------------- +* 15-Mar-94 | PLu : Added IRIX version +****************************************************************************/ + +#ifdef UNIX +#ifdef UNIX_IRIX_MIDIFNS +void midi_write(int n, int port, unsigned char c1, unsigned char c2, unsigned char c3) +{ + MDevent event; + + if (port < 0) return; + + * ((u_long *) event.msg) = 0xe0000000 | ((port & 0x1f) << 24) | (c1 << 16) | + (c2 << 8) | c3; + if (mdSend(miport, &event, 1) == -1) + gprintf(ERROR, "Can not send midi message in midi_write"); + + midi_write_trace(n, port, c1, c2, c3); +} +#else + +#ifdef ITC +void midi_write(int n, int port, + unsigned char c1, unsigned char c2, unsigned char c3) +{ + unsigned char outb[3]; + mi_channel mch; + mi_status ret; + + if (port < 0) return; + outb[0] = c1; + outb[1] = c2; + outb[2] = c3; + mch = (16*port)+((int)MI_CHANNEL(c1)); + ret = mi_put(midiconn, mch, outb); + if (ret != MI_SUCCESS) + gprintf(ERROR, "Warning: bad ret = %d in midi_write\n", (int)ret); + midi_write_trace(n, port, c1, c2, c3); +} +#else +void midi_write(int n, int port, + unsigned char c1, unsigned char c2, unsigned char c3) +{ + /* no output */ + midi_write_trace(n, port, c1, c2, c3); +} +#endif /* ITC */ +#endif /* UNIX_IRIX */ +#endif /* UNIX */ + +#ifdef DOS +#ifndef WINDOWS +void midi_write(int n, int port, + unsigned char c1, unsigned char c2, unsigned char c3) +{ + if (n >= 1) mPutData(c1); + if (n >= 2) mPutData(c2); + if (n >= 3) mPutData(c3); + midi_write_trace(n, port, c1, c2, c3); +} +#else +void midi_write(int n, int port, + unsigned char c1, unsigned char c2, unsigned char c3) +{ + midi_write_trace(n, port, c1, c2, c3); +} +#endif +#endif + +#ifdef MACINTOSH +#ifdef MIDIMGR +void midi_write(int n, int port, + unsigned char c1, unsigned char c2, unsigned char c3) +{ + MIDIPacket TheMIDIPacket; + + TheMIDIPacket.flags = midiTimeStampCurrent; + TheMIDIPacket.len = 6 + n; + TheMIDIPacket.tStamp = 0; + TheMIDIPacket.data[0] = c1; + TheMIDIPacket.data[1] = c2; + TheMIDIPacket.data[2] = c3; + MIDIWritePacket(OutputRefNum, &TheMIDIPacket); + midi_write_trace(n, port, c1, c2, c3); +} +#else +void midi_write(int n, int port, unsigned char c1, unsigned char c2, unsigned char c3) +{ +#ifndef NYQUIST + Xmit(port, c1); + if (n >= 2) Xmit(port, c2); + if (n >= 3) Xmit(port, c3); +#endif + midi_write_trace(n, port, c1, c2, c3); +} +#endif +#endif + +void midi_write_trace(int n, int port, + unsigned char c1, unsigned char c2, unsigned char c3) +{ + if (miditrace) { + /* to indicate bytes going out on port 1, put message in brackets + * with the port number, e.g. [1:~90~3c~64] + */ + if (port > 0) gprintf(TRANS, "[%d:", port); + if (n >= 1) gprintf(TRANS, "~%2x", c1); + if (n >= 2) gprintf(TRANS, "~%2x", c2); + if (n >= 3) gprintf(TRANS, "~%2x", c3); + if (port > 0) gprintf(TRANS, "]", port); + } +} + + + +/***************************************************************** +* set_pitch_default +*****************************************************************/ + +private void set_pitch_default() +{ + int i; + + for (i = 0; i < 128; i++) { + pit_tab[i].pbend = 8192; + pit_tab[i].ppitch = i; + } +} + +/***************************************************************** +* read_tuning +*****************************************************************/ + +void read_tuning(filename) +char *filename; +{ + int index, pit, lineno = 0; + float bend; + FILE *fpp; + + user_scale = TRUE; + set_pitch_default(); + + fpp = fileopen(filename, "tun", "r", "Tuning definition file"); + while ((fscanf(fpp, "%d %d %f\n", &index, &pit, &bend) > 2) && + (lineno < 128)) { + lineno++; + if (index >= 0 && index <= 127) { + pit_tab[index].pbend = (int)(8192 * bend/100 + 8192); + pit_tab[index].ppitch = pit; + } + } +} + + +/**************************************************************************** +* musicinit +* Effect: +****************************************************************************/ + +void musicinit() +{ + int i; + char *filename; + + if (!tune_flag) { /* do this code only once */ + miditrace = cl_switch("miditrace"); + musictrace = cl_switch("trace"); + } + + if (!initialized) { + cu_register((cu_fn_type) musicterm, NULL); + midi_init(); + } + initialized = TRUE; + /* this does some random cleanup activity */ + +#ifndef APPLICATION + if (!tune_flag) { /* do this code only once */ +#ifdef DOS +#ifndef WINDOWS +#if 0 + version = mPutGetCmd(GETMPUVER); + revision = mPutGetCmd(GETMPUREV); + gprintf(TRANS, "MPU version %d.%d%c\n", version >> 4, version & 0x0f, + revision + 'A' - 1); +#endif + mPutCmd(UARTMODE); + mPutCmd(NOREALTIME); /* initially prevent Real Time MIDI info */ + mPutCmd(EXCLUSIVOFF); /* initially prevent Sys-Ex data */ +#endif +#endif + tune_flag = TRUE; + filename = cl_option("tune"); + if (filename != NULL) read_tuning(filename); + } + /* now that flags are set, print the trace message */ + if (musictrace) gprintf(TRANS, "musicinit()\n"); + + if (user_scale) { + for (i = 0; i < MAX_CHANNELS; i++) { + midi_bend(i, 8192); + bend[i] = 8192; + } + } +#endif /* ifndef APPLICATION */ + + for (i = 0; i < MAX_CHANNELS; i++) { + /* initialize to impossible values so that the + * next call to midi_bend or midi_program will + * not match and therefore send an output: + */ + bend[i] = -1; + cur_midi_prgm[i] = -1; + } +#ifdef MIDI_THRU + midi_thru(!(cl_switch("block"))); /* set MIDI thru */ +#endif + timereset(); /* Reset clock */ +#ifdef AMIGA + event_mask |= (1L << ascii_signal()) | (1L << cmt_mi->AlarmSigBit) | + (1L << cmt_mi->RecvSigBit); +#endif +} + + +/**************************************************************************** +* musicterm +* Effect: +* Miscellaneous cleanup of things done by musicinit. +****************************************************************************/ + +private void musicterm() +{ + if (musictrace) gprintf(TRANS, "musicterm()\n"); + initialized = FALSE; +} + + +/**************************************************************************** +* cmtrand +* Inputs: +* int lo: Lower limit of value +* int hi: Upper limit of value +* Result: int +* random number (lo <= result <= hi) +****************************************************************************/ + +long randseed = 1534781L; + +short cmtrand(short lo, short hi) +{ + randseed *= 13L; + randseed += 1874351L; + return((short)(lo + (((hi + 1 - lo) * ((0x00ffff00 & randseed) >> 8)) >> 16))); +} + + +#ifdef AMIGA +/* remove_sysex_buffer -- a cleanup procedure for the Amiga */ +/**/ +void remove_sysex_buffer(void *obj) +{ + ClearSysExQueue(cmt_mi); +} +#endif /* AMIGA */ + + +/**************************************************************************** +* settime +* Inputs: new time +* Effect: +* Sets the current time to the new time. +* DMH: for MAC, sets the clock to absTime +* implemented by adjusting ticksATStart +****************************************************************************/ + +void settime(newtime) + time_type newtime; +{ + if (musictrace) gprintf(TRANS, "settime(%lu)\n", newtime); +#ifdef AMIGA + timeoffset = *camdtime - (newtime >> 1); +#endif + +#ifdef MACINTOSH +#ifdef MIDIMGR + ticksAtStart = MIDIGetCurTime(OutputRefNum); +#else + ticksAtStart = TickCount() - MS_TO_TICKS(newtime); +#endif +#endif +} + +/**************************************************************************** +* timereset +* Effect: +* Resets the time. +* DMH: for MAC, implemented by setting ticksAtStart to +* current value of system tick counter +* JMN: for DOS, resets the time on the MPU-401. Ticks is reset to 0 +****************************************************************************/ + +void timereset() +{ +#if HAS_GETTIMEOFDAY + struct timeval timeval; +#endif +#if HAS_FTIME + struct timeb ftime_res; +#endif + + if (!initialized) fixup(); + if (musictrace) gprintf(TRANS,"timereset()\n"); + +#ifdef AMIGA + timeoffset = *camdtime; +#endif + +#ifdef DOS +#ifndef WINDOWS + timeoffset = (ulong) readtimer(); +#endif +#endif + +#ifdef MACINTOSH +#ifdef MIDIMGR + ticksAtStart = MIDIGetCurTime(OutputRefNum); +#else + ticksAtStart = TickCount(); +#endif +#endif + +#if HAS_GETTIMEOFDAY + gettimeofday(&timeval, 0); + timeoffset = timeval.tv_sec * 1000 + timeval.tv_usec / 1000 - timeoffset; +#endif +#if HAS_FTIME + ftime(&ftime_res); + timeoffset = ftime_res.time; +#endif +} + + +/**************************************************************************** +* trace +* Inputs: +* boolean flag: TRUE for trace on +* Effect: +* turns tracing on (flag == TRUE) or off (flag == FALSE) +****************************************************************************/ + +void trace(boolean flag) +{ + musictrace = flag; +} + +/**************************************************************************** +* tracemidi +* Inputs: +* boolean flag: TRUE for trace on +* Effect: +* turns midi tracing on (flag == TRUE) or off (flag == FALSE) +****************************************************************************/ + +void tracemidi(boolean flag) +{ + miditrace = flag; +} + + + +/*********************************************************************** +* +* midi and timer initialization +* +***********************************************************************/ + +#ifdef DOS + +/* binary value of hex char */ + +private int xval(int c) +{ + int i; + static char t[]="0123456789abcdef"; + + for (i=0; i<16; i++) + if(tolower(c)==t[i]) return(i); + return (-1); +} + +/* binary value of hex string */ + +private int atox(char *t) +{ + int i=0; + int x; + while(*t) + { + if ((x=xval(*t++))<0)return (0); + i=(i<<4)+x; + } + return (i); +} +#endif /* def DOS */ + + +private void midi_init() +{ +#ifdef UNIX_IRIX_MIDIFNS +#define PBUFLEN 4 + MIconfig *config; + static u_int pbuf[] = { MI_STAMPING, MINOSTAMP, MI_BLOCKING, MINONBLOCKING}; +#endif + +#ifdef UNIX_MACH + mach_midi_init(); +#else +#ifdef ITC + midiconn = mi_open(NULL); + if (midiconn == NULL) { + gprintf(FATAL, "could not open a MIDI device\n"); + EXIT(1); + } + cu_register((cu_fn_type) mi_close, (void *) midiconn); +#endif +#endif +#ifdef AMIGA + amiga_midi_init(); +#endif /* def AMIGA */ +#ifdef DOS +#ifndef WINDOWS + int err; + int irq=SEARCHIRQ; + int base=MPUBASEADDR; + char *t; + + if (t=getenv("MPUIRQ")) { + if (musictrace) + gprintf(TRANS,"MPUIRQ %s\n",t); + irq=atoi(t); + } + if (t=getenv("MPUBASE")) { + if (musictrace) + gprintf(TRANS,"MPUBASE %s\n",t); + base=atox(t); + } + if(err = mOpen(base, irq)) { + mClose(err); + EXIT(1); + } + cu_register((cu_fn_type) mClose, 0); + cu_register((cu_fn_type) mPutCmd, (cu_parm_type) MPURESET); + initializetimer(); + cu_register((cu_fn_type) restoretimer, NULL); +#endif +#endif + +#ifdef MACINTOSH +#ifndef NYQUIST /* if NYQUIST, do nothing */ +#ifdef MIDIMGR + setup_midimgr(); /* this registers itself for cleanup */ +#else + init_abort_handler(); + cu_register(cleanup_abort_handler, NULL); + setupMIDI(portA, 0x80); + cu_register(restoreMIDI, (long) portA); + /* only initialize portB if necessary */ + if (MAX_CHANNELS > CHANNELS_PER_PORT) { + setupMIDI(portB, 0x80); + cu_register(restoreMIDI, (long) portB); + } +#endif +#endif /* NYQUIST */ +#ifdef MIDIMGR + ticksAtStart = MIDIGetCurTime(OutputRefNum); +#else + ticksAtStart = TickCount(); /* reset the clock */ +#endif +#endif /* def MACINTOSH */ + + if (!(cl_switch("noalloff"))) + cu_register((cu_fn_type) alloff, NULL); +} + +#ifdef DOS +/**************************************************************************** +* set_x_mfr +* Inputs: +* unsigned char mfr: Manufacturer ID for MIDI +* Result: void +* +* Effect: +* Sets the xcode and xcodemask to allow only these sysex messages +****************************************************************************/ + +void set_x_mfr(mfr) +unsigned char mfr; +{ + xcode = mfr; + xcodemask = 0xFF; +} + +/**************************************************************************** +* clear_x_mfr +* Result: void +* +* Effect: +* Clears sysex manufacturer code filter; accepts all sysex messages +****************************************************************************/ + +void clear_x_mfr() +{ + xcode = 0; + xcodemask = 0; +} +#endif /* DOS */ diff --git a/cmt/midifns.h b/cmt/midifns.h new file mode 100644 index 0000000..99042d3 --- /dev/null +++ b/cmt/midifns.h @@ -0,0 +1,137 @@ +/* midifns.h -- definitions for users of midifns.c */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 5-Mar-92 | GWL : insert definitions and logs from JMN's mpu.h +* for LATTICE322, only variable type in prototypes +* 28-Apr-03 | DM : random() is now named cmtrand() to avoid conflicts +*****************************************************************************/ + +#ifndef _MIDIFNS_H_ +#define _MIDIFNS_H_ + +/* declaration types */ + +typedef unsigned long time_type; +typedef long sgnd_time_type; + +/* Maximum time value: */ +#define MAXTIME 0xFFFFFFFFL + +#define delay_type long + +/* controller numbers */ + +#define MODWHEEL 1 +#define BREATH 2 +#define FOOT 4 +#define PORTARATE 5 +#define VOLUME 7 +#define SUSTAIN 64 +#define PORTASWITCH 65 + +#include "midierr.h" + +extern char *midifns_syntax; + +/* support for allocating sysex buffer - examples in mm.c & exget.c */ +#ifdef DOS +#define midibuff_alloc(size) (byte huge *) halloc(size, 1) +#endif +#ifndef midibuff_alloc +#define midibuff_alloc (byte *) MALLOC +#endif + +/* DMH: from mpu.h -- definitions for users of mpu.c */ + +#ifdef OLD_PROTOTYPES + +void eventwait(); +void exclusive(boolean); +boolean getbuf(boolean, unsigned char * ); +long get_excl(); +boolean getxbuf(); +boolean testxbuf(); +short getkey(boolean); +ulong gettime(void); /*DMH: note- now unsigned*/ +void l_rest(long); +void l_restuntil(long); +void metronome(boolean); +void midi_bend(short,short); +boolean midi_buffer(byte * , ulong); +void midi_cont(boolean); +void midi_clock(); +void midi_ctrl(short, short, short); +void midi_exclusive(unsigned char * ); +void midi_note(short, short, short); +void midi_program(short, short); +void midi_real(); +void midi_start(); +void midi_stop(); +#ifdef AMIGA +/* MIDI_THRU defined means that it is really implemented. */ +#define MIDI_THRU +#endif +void midi_thru();/*boolean onflag*/ +void midi_touch(short, short); +void midi_write(); +void musicinit(); +short cmtrand(short, short); +void read_tuning();/*char *filename*/ +void settime(); +void synth_init();/*void*/ +void timereset(); +void trace(); +void tracemidi(); +boolean is_exclusive(void); +unsigned char get_exclusive(void); + +#else + +void alloff(void); +void eventwait(long timeout); +void exclusive(boolean onflag); +long get_excl(byte *buffer, long len); +boolean getbuf(boolean waitflag, unsigned char * p); +short getkey(boolean waitflag); +ulong gettime(void); +void l_rest(long time); +void l_restuntil(long time); +void metronome(boolean onflag); +void midi_bend(int channel, int value); +boolean midi_buffer(byte *buffer, ulong size); +void midi_clock(void); +void midi_cont(boolean onflag); +void midi_ctrl(int channel, int control, int value); +void midi_exclusive(unsigned char *msg); +void midi_flush(); +void midi_note(int channel, int pitch, int velocity); +void midi_program(int channel, int program); +void midi_real(boolean onflag); +void midi_start(void); +void midi_stop(void); +void midi_thru(boolean onflag); +void midi_touch(int channel, int value); +void read_tuning(char *filename); +void midi_write(int n, int port, unsigned char c1, unsigned char c2, unsigned char c3); +void midi_write_trace(int n, int port, + unsigned char c1, unsigned char c2, unsigned char c3); +void musicinit(void); +void settime(time_type newtime); +void timereset(void); +void trace(boolean flag); +void tracemidi(boolean flag); + + +boolean check_midi(void); +#endif /* ifdef OLD_PROTOTYPES */ + + +#ifdef AMIGA +byte *head_of_excl(); +byte *tail_of_excl(); +#endif + +#endif /* _MIDIFNS_H_ */ diff --git a/cmt/midimgr.c b/cmt/midimgr.c new file mode 100644 index 0000000..e7db136 --- /dev/null +++ b/cmt/midimgr.c @@ -0,0 +1,784 @@ +/* midimgr.c -- this file contains interface code to support use of Apple Midi Manager */ +/* + * This code is based on code supplied with the Apple Midi Manager. + * Copyright 1991, Carnegie Mellon University + */ + +/* BUGS: + * If exclusive() is called to turn exclusive messages on or off DURING the + * receipt of an exclusive message, incoming data will be garbled. The correct + * handling would be to record when receipt of an exclusive message is in + * progress, then properly remove any partial message when exclusive is turned + * off, and ignore any remaining message part when exclusive is turned on. + * The present code does neither. + */ + +#include "cext.h" +#undef round +#ifdef THINK_C +#include /* for ThinkC 7 */ +#endif + +#include "stdio.h" +#include "userio.h" +#include "MIDI.h" +#include "midifns.h" +#include "midibuff.h" +#include "midierr.h" +#include "midimgr.h" +#include "midicode.h" +#include "cmdline.h" + +/* Needed for KillEverybody */ +#include +#include +#include +#include +#include +#include +#include + + +#define CMTclientID 'CMT ' +/* note the following are in alphabetical order for Patcher display */ +#define timePortID 'Atim' +#define inputPortID 'Bin ' +#define outputPortID 'Cout' +#define noClient ' ' + +#define noTimeBaseRefNum 0 +#define noReadHook 0L +#define zeroTime 0L +#define timePortBuffSize 0L +#define inputPortBuffSize 2048 +#define outputPortBuffSize 0L +#define refCon0 0L + +pascal short CMTreader(MIDIPacket *ThePacketPtr, long TheRefCon); + +/* "patch" switch from command line. This switch is cached in patch_flag and tells + whether to look in the resource fork for a patch, or just hook up to midi in and + out. If the resource fork is used, the patch will be saved upon exit. */ +private boolean patch_flag; +extern boolean ctrlFilter; +extern boolean exclFilter; +extern boolean realFilter; + +private midi_read_lock = false; /* used to stop input during data structure manipulation */ + +private void set_error(int bit); +#ifndef NYQUIST +void PatchPorts(void); +void SavePatch(OSType PortID, short PortInfoResID, char *PortInfoResName); +#endif + +/* exported: */ +public short InputRefNum; /* Input port reference number. */ +public short OutputRefNum; /* Output port reference number. */ +public short TimeRefNum; /* Time base port reference number. */ + +Boolean GManualPatch; /* True if not launched by a PatchBay Config. File. */ + +/**************************************************************************** +* +* variables shared with other modules +* +****************************************************************************/ + +/* midi input buffer */ +long buff[BUFF_SIZE/4]; /* data buffer, declared long to get 32-bit alignment */ +int buffhead = 0; /* buffer head and tail pointers */ +int bufftail = 0; + +/* user supplied system exclusive buffer */ +byte *xbuff = NULL; /* address of the user-supplied buffer */ +public long xbufmask; /* mask for circular buffer address calculation */ +long xbufhead = 0; /* buffer head and tail pointers */ +long xbuftail = 0; +boolean xbuf_flush = true; /* says to flush remainder of sysex message */ + +#ifdef SYSEXDEBUG +int sysexcount = 0; /* for debugging */ +int sysexdone = 0; +int sysexheadcount = 0; +byte sysexfirst = 0; +int sysexsysex = 0; +#endif + +/* midi_flush -- empty out buffers */ +/**/ +void midi_flush() +{ + midi_read_lock = true; + buffhead = 0; + bufftail = 0; + xbufhead = 0; + xbuftail = 0; + xbuf_flush = true; /* in case sysex continuation messages are still coming */ + midi_read_lock = false; +} + + +/* Nyquist only uses CMT for Midi and Adagio file IO */ +#ifndef NYQUIST +/* Get String representation of MIDI Mgr Version Num.*/ +/* See Mac Tech Note #189 for details. */ +char *StdMacVerNumToStr(long VerNum, char *VerStr) +{ + char *RetVal; + char MajVer, MinVer, VerStage, VerRev, BugFixVer = 0; + + if (VerNum == 0) + { + RetVal = NULL; + } + else + { + MajVer = (VerNum & 0xFF000000) >> 24; + MinVer = (VerNum & 0x00FF0000) >> 16; + VerStage = (VerNum & 0x0000FF00) >> 8; + VerRev = (VerNum & 0x000000FF) >> 0; + BugFixVer = MinVer & 0x0F; + + switch (VerStage) + { + case 0x20: + VerStage = 'd'; + break; + case 0x40: + VerStage = 'a'; + break; + case 0x60: + VerStage = 'b'; + break; + case 0x80: + VerStage = ' '; + break; + default: + VerStage = '?'; + break; + } + + if (BugFixVer == 0) + { + sprintf(VerStr,"%X.%X%c%X", + MajVer, MinVer>>4, VerStage, VerRev); + } + else + { + sprintf(VerStr,"%X.%X.%X%c%X", + MajVer, MinVer >> 4, MinVer & 0x0F, VerStage, VerRev); + } + + RetVal = VerStr; + } + + return(RetVal); +} + + +/* C2PStrCpy -- Convert a C String (from Cstr) into a Pascal string */ +/* + * NOTE: this is not the same code as shipped with midi manager example + */ +char *C2PStrCpy(char *Cstr, Str255 Pstr) +{ + char *c = Cstr; + char *p = ((char *) Pstr) + 1; + + while (*c) *p++ = *c++; + *Pstr = c - Cstr; + return( (char *) Pstr ); +} + +/* This checks to see if THINK C is running under System 7, + and ONLY WORKS UNDER SYSTEM 7! Don't use unless you check! */ +boolean ThinkCRunning(void) +{ + ProcessSerialNumber processSN; + OSErr myErr; + ProcessInfoRec infoRec; + + processSN.lowLongOfPSN = kNoProcess; + processSN.highLongOfPSN = kNoProcess; + do { + myErr = GetNextProcess(&processSN); + + infoRec.processInfoLength = sizeof(ProcessInfoRec); + infoRec.processName = 0L; + infoRec.processAppSpec = 0L; + myErr = GetProcessInformation(&processSN, &infoRec); + if (!myErr) { + if (infoRec.processSignature == 'KAHL') { + return(true); + } + } + } while (myErr == noErr); + return(false); +} + +/* This kills off all the other running processes... + ONLY WORKS UNDER SYSTEM 7! Don't use unless you check! */ +void KillEverybody(void) +{ + ProcessSerialNumber myProc, processSN; + ProcessSerialNumber finderPSN; + ProcessInfoRec infoRec; + Str31 processName; + FSSpec procSpec; + + OSErr myErr = noErr; + OSErr otherError; + AppleEvent theEvent; + AEDesc theAddress; + Boolean ourFlag, notFinder; + Boolean finderFound = false; + + GetCurrentProcess(&myProc); + /* Preset the PSN to no PSN, see IM VI, the Process Manager */ + processSN.lowLongOfPSN = kNoProcess; + processSN.highLongOfPSN = kNoProcess; + finderPSN.lowLongOfPSN = 0UL; /* brk: was nil */ + finderPSN.highLongOfPSN = 0UL; /* brk: was nil */ + + do { + myErr = GetNextProcess(&processSN); + /* See if it's us first */ + notFinder = true; + SameProcess(&myProc, &processSN, &ourFlag); + + infoRec.processInfoLength = sizeof(ProcessInfoRec); + infoRec.processName = (StringPtr) &processName; + infoRec.processAppSpec = &procSpec; + GetProcessInformation(&processSN, &infoRec); + if (!ourFlag && !finderFound) { + /* see if it's the Finder, we have to kill the finder LAST */ + /* or else non-sys 7 apps won't get killed */ + /* since the Finder must be there to convert the AppleEvent to Puppet Strings */ + /* if the app is not APpleEvent aware */ + /* Also, FileShare HAS to be killed before the Finder */ + /* or your life will be unpleasant */ + + if (infoRec.processSignature == 'MACS' && infoRec.processType == 'FNDR') { + /* save this number for later */ + finderPSN = processSN; + notFinder = false; + finderFound = true; + + } else { + notFinder = true; + } + } + if (!myErr && !ourFlag && notFinder) { + otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&processSN, sizeof(processSN), &theAddress); + if (!otherError) + otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID, + kAnyTransactionID, &theEvent); + if (!otherError) + AEDisposeDesc(&theAddress); + /* Again, the Finder will convert the AppleEvent to puppetstrings if */ + /* the application is a System 6 or non-AE aware app. This ONLY */ + /* happens for the 4 required (oapp,odoc,pdoc, and quit) AppleEvents */ + /* and ONLY if you use the PSN for the address */ + if (!otherError) + AESend(&theEvent, 0L, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, + 0L, 0L); + AEDisposeDesc(&theEvent); + } + } while (!myErr); + + /* Now, if the finder was running, it's safe to kill it */ + if (finderPSN.lowLongOfPSN || finderPSN.highLongOfPSN) { + otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&finderPSN, sizeof(processSN), &theAddress); + if (!otherError) + otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID, + kAnyTransactionID, &theEvent); + if (!otherError) + AEDisposeDesc(&theAddress); + if (!otherError) + AESend(&theEvent, 0L, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, 0L, + 0L); + AEDisposeDesc(&theEvent); + } +} + +/* Sign into the MIDI Manager. */ +/* Set up time, input, and output ports. */ +/* Start our time base clock. */ +void setup_midimgr(void) +{ + MIDIPortParams Init; /* MIDI Mgr Init data structure */ + Handle TheIconHndl; + OSErr TheErr; + long MIDIMgrVerNum; /* MIDI Manager Ver (Std Mac Ver #) */ + Str255 name = "\pCMU MIDI Toolkit"; + char MIDIMgrVerStr[256]; /* MIDI Manager Ver (Std Mac Ver # String) */ + long vers; + EventRecord theEvent; + + Gestalt(gestaltSystemVersion, &vers); + vers = (vers >> 8) & 0xf; /* shift result over and mask out major version number */ + if ((vers >= 7) && (!cl_switch("keep")) && (!ThinkCRunning())) { + gprintf(TRANS,"Killing other processes...\n"); + KillEverybody(); + for (vers=0; vers<100; ++vers) { + while (WaitNextEvent(everyEvent, &theEvent, 0L, 0L)) ; + } + } + + /* Make sure MIDIMgr is installed and save version num. */ + MIDIMgrVerNum = SndDispVersion(midiToolNum); + if (MIDIMgrVerNum == 0) { + gprintf(ERROR, "The MIDI Manager is not installed! Exiting...\n"); + EXIT(1); + } else { + StdMacVerNumToStr(MIDIMgrVerNum, MIDIMgrVerStr); + gprintf(TRANS,"MIDI Manager Version %s\n", MIDIMgrVerStr); + } + + + /* Sign in to the MIDI Manager. */ + TheIconHndl = GetResource('ICN#', 1); + TheErr = MIDISignIn(CMTclientID, + 0L, + TheIconHndl, + name); + if (TheErr) { + gprintf(ERROR, "Trouble signing into MIDI Manager! Aborting..."); + EXIT(1); + } + + /* Assume not a Patchbay configuration. */ + GManualPatch = true; + + /* Add time port. */ + Init.portID = timePortID; + Init.portType = midiPortTypeTime; + Init.timeBase = noTimeBaseRefNum; + Init.readHook = noReadHook; + Init.initClock.syncType = midiInternalSync; + Init.initClock.curTime = zeroTime; + Init.initClock.format = midiFormatMSec; + Init.refCon = SetCurrentA5(); + C2PStrCpy("TimeBase", Init.name); + TheErr = MIDIAddPort(CMTclientID, timePortBuffSize, &TimeRefNum, &Init); + /* Has a PatchBay connection been resolved? */ + if (TheErr == midiVConnectMade) { + GManualPatch = false; + } else if (TheErr == memFullErr) { + gprintf(ERROR, "Not enough room in heap zone to add time port! Aborting..."); + MIDISignOut(CMTclientID); + EXIT(1); + } + + /* Add an input port. */ + Init.portID = inputPortID; + Init.portType = midiPortTypeInput; + Init.timeBase = TimeRefNum; + Init.offsetTime = midiGetCurrent; + Init.readHook = NewMIDIReadHookProc(CMTreader); + Init.refCon = SetCurrentA5(); + C2PStrCpy("InputPort", Init.name); + TheErr = MIDIAddPort(CMTclientID, inputPortBuffSize, &InputRefNum, &Init); + /* Has a PatchBay connection been resolved? */ + if (TheErr == midiVConnectMade) { + GManualPatch = false; + } else if (TheErr == memFullErr) { + gprintf(ERROR, "Not enough room in heap zone to add input port! Aborting..."); + MIDISignOut(CMTclientID); + EXIT(1); + } + + /* Add an output port. */ + Init.portID = outputPortID; + Init.portType = midiPortTypeOutput; + Init.timeBase = TimeRefNum; + Init.offsetTime = midiGetCurrent; + Init.readHook = NULL; + Init.refCon = refCon0; + C2PStrCpy("OutputPort", Init.name); + TheErr = MIDIAddPort(CMTclientID, outputPortBuffSize, &OutputRefNum, &Init); + /* Has a PatchBay connection been resolved? */ + if (TheErr == midiVConnectMade) { + GManualPatch = false; + } else if (TheErr == memFullErr) { + printf("Not enough room in heap zone to add output port! Aborting..."); + MIDISignOut(CMTclientID); + EXIT(1); + } + + if (GManualPatch) { + PatchPorts(); /* connect ports as they were */ + } + /* to clean this up (later) call finish_midimgr() */ + cu_register((cu_fn_type) finish_midimgr, (cu_parm_type) finish_midimgr); + + /* Start our Clock. */ + MIDIStartTime(TimeRefNum); +} + + +/* The Read Hook Function. */ + +/* 1st 4 bytes of sysex message get saved here and enqueued later */ +char save_sysex_head[4]; +int save_sysex_head_x = 0; + +void sysex_insert(unsigned char data) { + if (save_sysex_head_x < 4) { + save_sysex_head[save_sysex_head_x++] = data; + } + xbuff[xbuftail++] = data; + xbuftail &= xbufmask; + if (xbuftail == xbufhead) { + set_error(SYSEXOVFL); + } + if (data == MIDI_EOX) { /* we're done with the message */ + *((long *) (((byte *) buff) + bufftail)) = *((long *)save_sysex_head); + bufftail = (bufftail + 4) & BUFF_MASK; + if (bufftail == buffhead) { + set_error(BUFFOVFL); + } + } +} + +/* Read all incomming MIDI data. */ + +pascal short CMTreader(MIDIPacket *ThePacketPtr, long TheRefCon) +{ + /* Set up our A5 world. */ + long SysA5 = SetA5(TheRefCon); + short RetVal = midiMorePacket, i, j; + unsigned char *mm_data = ThePacketPtr->data; + register byte data1 = mm_data[1]; + + if (midi_read_lock) { + /* Don't want to read packet now, get it later */ + /* DOES THIS REALLY WORK? WHAT WILL CAUSE AN INTERRUPT + * TO OCCUR LATER? THIS IS ONLY USED BY midi_flush, IS + * BASED ON THE MidiArp CODE FROM APPLE, AND IS UNTESTED - RBD + */ + RetVal = midiKeepPacket; + goto alldone; + } + + /* see if Packet is an error message */ + if (((ThePacketPtr->flags & midiTypeMask) == midiMgrType) && + *((short *) (&(ThePacketPtr->data))) < midiMaxErr) { + set_error(MIDIMGRERR); + goto alldone; + } + + /* filter out control changes */ + if (ctrlFilter) { + register int hibits = *mm_data & 0xF0; + if (hibits == 0xD0 || /* Chan Pressure */ + hibits == 0xE0 || /* Pitch Bend */ + hibits == 0xA0 || /* Poly Pressure */ + ((hibits == 0xB0) && /* Control change (don't count switches) */ + ((data1 < 64) || (data1 > 121)))) { + /* CONTROL MESSAGE HAS BEEN FILTERED */ + goto alldone; + } + } else if (realFilter) { + register int hibits = *mm_data & 0xF0; + if (hibits >= 0xF8) goto alldone; + } + + + /* if not a continuation, copy the data into cmt_data */ + /* The logic to detect a non-continued + * packet or a first packet is: "flags bit 1 is clear". + */ + if ((((ThePacketPtr->flags & midiContMask) == midiNoCont)) && + (*mm_data != MIDI_SYSEX)) { + register byte *cmt_data = ((byte *) buff) + bufftail; + *((long *) cmt_data) = *((long *) mm_data); + + bufftail = (bufftail + 4) & BUFF_MASK; + if (bufftail == buffhead) { + /* filled buffer faster than client emptied it */ + set_error(BUFFOVFL); + } + } + + /* see if we have a sysex message to copy to buffer */ + if (xbuff && !exclFilter && + ((ThePacketPtr->flags & midiContMask) || *mm_data == MIDI_SYSEX)) { + int i; + register byte *x_data = xbuff + xbuftail; + + /* iterate over data in message */ + /* NOTE: in the previous implementation, I thought Sysex messages were + * always starting at the beginning of the buffer, but that didn't work. + * This implementation assumes nothing -- it is slower because of additional + * testing and parsing inside the loop, but seems to work. + */ + for (i = ThePacketPtr->len - 6; i > 0; i--) { + if (xbuf_flush) { /* we're searching for beginning of message */ + if (*mm_data == MIDI_SYSEX) { + xbuf_flush = false; + sysex_insert(MIDI_SYSEX); + } + } else { /* we're scanning to the end of the message */ + if (*mm_data == MIDI_SYSEX) { /* found it, insert proper EOX */ + sysex_insert(MIDI_EOX); + sysex_insert(MIDI_SYSEX); + } else if (*mm_data == MIDI_EOX) { /* found it */ + sysex_insert(MIDI_EOX); + xbuf_flush = true; + } else sysex_insert(*mm_data); + + } + mm_data++; + } + } +alldone: + + /* Restore the systems A5 world. */ + SetA5(SysA5); + + return(RetVal); +} + + +/* Sign out from the MIDI Manager. */ +void finish_midimgr(void) +{ + if (GManualPatch && patch_flag) { + SavePatch(timePortID, timePortResInfoID, "timePortInfo"); + SavePatch(inputPortID, inputPortResInfoID, "inputPortInfo"); + SavePatch(outputPortID, outputPortResInfoID, "outputPortInfo"); + } + MIDISignOut(CMTclientID); +} + + + +/* Alert user to Resource Manager Error. */ +void +ReportResError(char *Msg) +{ + OSErr TheErr; + char Buf[256]; + + if ( (TheErr = ResError()) != noErr) { + gprintf(ERROR, "ResError %d: %s...Aborting.", TheErr, Msg); + EXIT(1); + } else { + /* gprintf(ERROR, "%s OK\n", Msg); */ + } +} + + +/**************************************************************************** +* error handling +* Effect: +* various error conditions are flagged by setting bits in +* the global midi_error_flags. it is up to the client to clear this +* word when necessary. +****************************************************************************/ + +private void set_error(int bit) +{ + midi_error_flags |= (1 << bit); +} + + +void midi_show_errors() +{ + if (midi_error_flags & (1<numIDs; i++) { + OSType id = (*clients)->list[i]; + gprintf(TRANS, "%d: %c%c%c%c\n", i, (char) (id>>24), + (char) ((id >> 16) & 0xFF), (char) ((id >> 8) & 0xFF), + (char) (id & 0xFF)); + } + ports = MIDIGetPorts('amdr'); + HLock((Handle) ports); + for (i = 0; i < (*ports)->numIDs; i++) { + OSType id = (*ports)->list[i]; + gprintf(TRANS, "%d: %c%c%c%c\n", i, (char) (id>>24), + (char) ((id >> 16) & 0xFF), (char) ((id >> 8) & 0xFF), + (char) (id & 0xFF)); + } + HUnlock((Handle) ports); + HUnlock((Handle) clients); +#endif + /* the work starts here */ + err = MIDIConnectData('CMT ', 'Cout', 'amdr', 'Aout'); + /* gprintf(TRANS, "Connected CMT.Cout to amdr.Aout: %d\n", err); */ + err = MIDIConnectData('amdr', 'Ain ', 'CMT ', 'Bin '); + /* gprintf(TRANS, "Connected amdr.Ain to CMT.Bin: %d\n", err); */ + + return; + } + HLock((Handle) PortInfoH); + PortInfoP = *PortInfoH; + if (GetHandleSize((Handle) PortInfoH) != 0) + { + /* Were we supposed to be sync'd to another client? */ + if (PortInfoP->timeBase.clientID != noClient) + { + /* Yes, so make that client our time base. */ + TheErr = MIDIConnectTime( + PortInfoP->timeBase.clientID, + PortInfoP->timeBase.portID, + CMTclientID, + timePortID + ); +#ifdef IGNORE + /* Is the client still signed in? */ + if (TheErr != midiVConnectErr) + { + /* Yes, so set our sync mode to external. */ + MIDISetSync(ArpGlobals.TimeRefNum, midiExternalSync); + } +#endif + + } + /* Were we somebody else's time base? */ + for (i=0; inumConnects; i++) + { + MIDIConnectTime(CMTclientID, + timePortID, + PortInfoP->cList[i].clientID, + PortInfoP->cList[i].portID); + } + } + HUnlock((Handle) PortInfoH); + ReleaseResource((Handle) PortInfoH); + ReportResError("PatchPorts/ReleaseResource()"); + + /* SET UP INPUT PORT CONNECTIONS. */ + PortInfoH = (MIDIPortInfoHdl) GetResource(portResType, inputPortResInfoID); + if (PortInfoH == NULL) + { + ReportResError("PatchPorts/GetResource()"); + } + HLock((Handle) PortInfoH); + PortInfoP = *PortInfoH; + if (GetHandleSize((Handle) PortInfoH) != 0) + { + /* Were we connected to anyone? */ + for (i=0; inumConnects; i++) + { + MIDIConnectData(CMTclientID, + inputPortID, + PortInfoP->cList[i].clientID, + PortInfoP->cList[i].portID); + } + } + HUnlock((Handle) PortInfoH); + ReleaseResource((Handle) PortInfoH); + ReportResError("PatchPorts/GetResource()"); + + /* SET UP OUTPUT PORT CONNECTIONS. */ + PortInfoH = (MIDIPortInfoHdl) GetResource(portResType, outputPortResInfoID); + if (PortInfoH == NULL) + { + ReportResError("PatchPorts/GetResource()"); + } + HLock((Handle) PortInfoH); + PortInfoP = *PortInfoH; + if (GetHandleSize((Handle) PortInfoH) != 0) { + /* Were we connected to anyone? */ + for (i=0; inumConnects; i++) + { + MIDIConnectData(CMTclientID, + outputPortID, + PortInfoP->cList[i].clientID, + PortInfoP->cList[i].portID); + } + } + HUnlock((Handle) PortInfoH); + ReleaseResource((Handle) PortInfoH); + ReportResError("PatchPorts/ReleaseResource()"); + +} + +/* Save current port connections (port info records) */ +/* to application's 'port' resource. */ +void +SavePatch(OSType PortID, short PortInfoResID, char *PortInfoResName) +{ + Handle PortResH; /* Handle to ptch resource. */ + CursHandle WatchCurs; + + WatchCurs = GetCursor(watchCursor); + HLock((Handle) WatchCurs); + SetCursor(*WatchCurs); + HUnlock((Handle) WatchCurs); + + + /* Remove existing port info resource. */ + PortResH = GetResource(portResType, PortInfoResID); + /* gprintf(TRANS, "PortResH: %lx, *PortResH: %lx\n", PortResH, *PortResH); */ + if (PortResH) { + ReportResError("SavePatch/GetResource()"); + RmveResource(PortResH); + ReportResError("SavePatch/RmveResource()"); + DisposHandle(PortResH); + UpdateResFile(CurResFile()); + ReportResError("SavePatch/UpdateResFile()"); + } + + /* Get new configurateion. */ + PortResH = (Handle) MIDIGetPortInfo(CMTclientID, PortID); + + /* Save new configurateion. */ + CtoPstr(PortInfoResName); + AddResource(PortResH, portResType, PortInfoResID, + (ConstStr255Param) PortInfoResName); + PtoCstr((unsigned char *) PortInfoResName); + + ReportResError("SavePatch/AddResource()"); + WriteResource(PortResH); + ReportResError("SavePatch/WriteResource()"); + UpdateResFile(CurResFile()); + ReportResError("SavePatch/UpdateResFile()"); + ReleaseResource(PortResH); + ReportResError("SavePatch/ReleaseResource()"); + + InitCursor(); +} +#endif /* NYQUIST */ diff --git a/cmt/midimgr.h b/cmt/midimgr.h new file mode 100644 index 0000000..790fc06 --- /dev/null +++ b/cmt/midimgr.h @@ -0,0 +1,14 @@ +#define portResType 'port' +#define timePortResInfoID 128 +#define inputPortResInfoID 129 +#define outputPortResInfoID 130 + + + +extern short InputRefNum; /* Input port reference number. */ +extern short OutputRefNum; /* Output port reference number. */ +extern short TimeRefNum; /* Time base port reference number. */ + +void setup_midimgr(void); +void finish_midimgr(void); +void midi_show_errors(); diff --git a/cmt/moxc.c b/cmt/moxc.c new file mode 100644 index 0000000..f62d65d --- /dev/null +++ b/cmt/moxc.c @@ -0,0 +1,669 @@ +/* MOXC -- a C version of Collinge's MOXIE language */ +/* Copyright 1989 Carnegie Mellon University */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 31-Dec-85 | Modified for use with midi +* 5-Feb-86 | Added m_rest and m_restuntil allowing rests at top level +* 28-May-86 | Added command line parsing +* 4-Jun-86 | changed keyevent to separate calls for each event type +* 10-Jul-86 | put loop in mainscore with prompt to play and replay +* 03-Jun-88 | modified for portability (AMIGA) -JCD +* 07-Jul-89 | time bases -RBD +* 31-Jan-90 | GWL : cleaned up for LATTICE +* 30-Jun-90 | RBD : further changes +* 2-Apr-91 | JDW : further changes +* 4-Mar-91 | GWL : DOS allows odd inst addrs +* 10-Oct-94 | nix : posicionador tridimensionale interface +* 28-Apr-03 | DM : true->TRUE, false->FALSE +*****************************************************************************/ + +#include "switches.h" + +#ifdef AMIGA +#ifdef AZTEC +#include "functions.h" +#else +#include "amiga.h" +#endif +#include "exec/exec.h" +#include "cmtcmd.h" + +extern long event_mask; /* imported from midifns.c */ +#endif +extern int abort_flag; /*DMH: taken out of ifdef AMIGA for moxcrun*/ + +#include "stdio.h" +#include "cext.h" +#include "userio.h" +#include "midifns.h" + +#include "cmdline.h" +#include "midicode.h" +#include "timebase.h" +#include "moxc.h" + +#ifdef AMIGA /*DMH: only AMIGA cares about AMIGA's "proportional controllers"*/ +#include "prop1.h" +#endif +#ifdef POSICIONADOR_3D +#include "pos3d.h" +#include "pos3dbuf.h" +#endif /* POSICIONADOR_3D */ + +extern char *app_syntax; + +/*************************************************************************** +* +* IMPORTS: +* asciievent(k) user-defined action for terminal input +* bendchange(ch, val) user-defined pitch bend handler +* ctrlchange(ch, c, val) user-defined control change handler +* keydown(ch, p, v) user-defined MIDI note on handler +* keyup(ch, p) user-defined MIDI note off handler +* mainscore() user-defined first action(s) +* musicfns lots of time and io functions +* peddown(ch) user-defined pedal down handler +* pedup(ch) user-defined pedal up handler +* touchchange(ch, val) user-defined aftertouch handler +* app_syntax string defining extra command line options +* +* EXPORTS: +* +* cause(delay, routine, p1, p2, ..., p8) +* moxcdone -- set to TRUE to quit +* eventtime -- ideallized current time +* +*****************************************************************************/ + +#define SAFEMOXC TRUE +#define BREAKKEY 0x03 + +int moxcdone; /* flag to halt execution */ +time_type eventtime; /* time of current call -- used to avoid */ + /* timing errors due to finite execution speed */ +time_type virttime; /* virtual time of current call */ +timebase_type timebase; /* time base of current call */ +int mididecode = TRUE; /* whether to decode messages or just call midievent */ + +int debug = FALSE; +int moxcdebug = FALSE; +time_type next_wakeup; +timebase_type default_base; + +#ifdef AMIGA +int pub_port_signal; +struct MsgPort pub_port; +#endif + +/***************************************************************************** +* Routines local to this module +*****************************************************************************/ + +private void callrun(); +private void decode(); +private void moxcterm(); + +/**************************************************************************** +* callallcancel +* Inputs: +* timebase_queue +* Effect: +* return all calls to free list +* Implementation: +* If timebase_queue is not empty, there's a pending call. Remove the call +* (not necessarily the timebase) and repeat. +****************************************************************************/ + +void callallcancel() +{ + if (moxcdebug) gprintf(GDEBUG, "cancel all calls\n"); + while (timebase_queue) { + timebase = timebase_queue; + timebase_queue = timebase->next; + while (timebase->heap_size > 0) { + call_free(remove_call(timebase)); + } + insert_base(timebase); + } +} + +/* catchup -- bring current timebase up to date by running its calls */ +/**/ +void catchup() +{ + register call_type call; + /* Remember where we're going in virtual time because setting the + * rate will also modify timebase->virt_base. We don't want catchup + * to stop short: + */ + time_type target_time = timebase->virt_base; + /* remember timebase here because it's possible that a call will do + * a timebase_use() and change it: + */ + register timebase_type my_base = timebase; + + while (my_base->heap_size != 0 && + (my_base->heap[1]->u.e.time < target_time)) { + /* eventtime is the real time at which something was scheduled */ + eventtime = (my_base->next_time) >> 8; + call = remove_call(my_base); + virttime = call->u.e.time; + (*(call->u.e.routine))(CALLARGS(call)); + call_free(call); + } + /* now that we've possibly pulled events out of the timebase, adjust + * the position in the timebase queue (and possibly remove it). + */ + remove_base(my_base); + insert_base(my_base); +} + + + +/**************************************************************************** +* cause +* Inputs: +* delay_type (long) delay: time before this call should occur +* int (*routine)(): routine that implements the call +* int p1 through p8: parameters to pass to routine +* Effect: +* builds a call and puts it in pending queue for later scheduling +****************************************************************************/ + +#ifndef DOTS_FOR_ARGS +void cause(delay, routine, p) + delay_type delay; + int (*routine)(); + call_args_node p; +#else +#include + +void cause(delay_type delay, ...) +/* note: the routine parameter is not checked because any routine type can + be passed as a parameter, but in the call struct it's an int (*)() + */ +#endif +{ + register call_type call = call_alloc(); +#ifdef DOTS_FOR_ARGS + va_list xp; +#endif + + if (!call) { + gprintf(ERROR, "cause: out of memory\n"); + EXIT(1); + } + +#ifdef DOTS_FOR_ARGS + call->u.e.time = virttime + delay; + call->u.e.priority = 128; /* default priority */ + va_start(xp, delay); + call->u.e.routine = (int (*)()) va_arg(xp, long *); + call->u.e.p = va_arg(xp, call_args_node); + va_end(xp); +#else + call->u.e.time = virttime + delay; + call->u.e.priority = 128; /* default priority */ + call->u.e.routine = routine; + call->u.e.p = p; +#endif +#ifdef SAFEMOXC + if (call->u.e.routine == 0) { + gprintf(ERROR,"cause called with NULL routine\n"); + EXIT(1); +#ifndef DOS /* IBM allows odd addresses */ +#if (__APPLE__ != 1 || __i386__ != 1) /* Intel Mac allows odd addresses */ + } else if (((long) call->u.e.routine) & 1) { + gprintf(ERROR, "cause called with bad routine address: 0x%lx\n", + call->u.e.routine); +#ifndef GCC_MODEL_CPU +#define GCC_MODEL_CPU "GCC_MODEL_CPU is undefined for this compilation" +#endif + gprintf(ERROR, GCC_MODEL_CPU); + EXIT(1); +#endif +#endif + } +#endif + /* put call in default queue */ + callinsert(timebase, call); + if (moxcdebug) { + gprintf(GDEBUG,"(cause) call is pending on timebase 0x%x:\n", timebase); + callshow(call); + } +} + +/**************************************************************************** +* causepri +* Inputs: +* int delay: time before this call should occur +* int pri: priority, lowest priority goes first +* int (*routine)(): routine that implements the call +* int p1 through p8: parameters to pass to routine +* Effect: +* builds a call and puts it in pending queue for later scheduling +****************************************************************************/ + +#ifndef DOTS_FOR_ARGS +void causepri(delay, pri, routine, p) + delay_type delay; + int pri; + int (*routine)(); + call_args_node p; +#else +/* already included stdarg.h */ + +void causepri(delay_type delay, int pri, ...) +#endif +{ + register call_type call = call_alloc(); +#ifdef DOTS_FOR_ARGS + va_list xp; +#endif + + if (!call) { + gprintf(ERROR, "cause: out of memory\n"); + EXIT(1); + } + +#ifdef DOTS_FOR_ARGS + call->u.e.time = virttime + delay; + call->u.e.priority = pri; /* default priority */ + va_start(xp, pri); + call->u.e.routine = (int (*)()) va_arg(xp, long *); + call->u.e.p = va_arg(xp, call_args_node); + va_end(xp); +#else + call->u.e.time = virttime + delay; + call->u.e.priority = pri; /* default priority */ + call->u.e.routine = routine; + call->u.e.p = p; +#endif +#ifdef SAFEMOXC + if (call->u.e.routine == 0) { + gprintf(ERROR,"cause called with NULL routine\n"); + EXIT(1); +#ifndef DOS /* IBM allows odd addresses */ +#if (__APPLE__ != 1 || __i386__ != 1) /* Intel Mac allows odd addresses */ + } else if (((long) call->u.e.routine) & 1) { + gprintf(ERROR, "causepri called with bad routine address: 0x%lx\n", + call->u.e.routine); + EXIT(1); +#endif +#endif + } +#endif + /* put call in default queue */ + callinsert(timebase, call); + if (moxcdebug) { + gprintf(GDEBUG,"(cause) call is pending:"); + callshow(call); + } +} + +/**************************************************************************** +* callrun +* Inputs: +* call_type call: the call to execute +* Effect: +* executes the previously scheduled call call and deallocates it +****************************************************************************/ + +private void callrun() +{ + call_type call; + if (moxcdebug) { + gprintf(GDEBUG,"(callrun) running a call: \n"); + } + /* remove from head of queue */ + while (!timebase_queue) gprintf(TRANS, "callrun fatal error\n"); + timebase = timebase_queue; + timebase_queue = timebase->next; + + if (debug) gprintf(TRANS, "callrun time %ld\n", timebase->next_time); + eventtime = (timebase->next_time) >> 8; /* real time of the call */ + + /* remove first call from timebase */ + call = remove_call(timebase); + if (debug) gprintf(TRANS, "callrun call %lx\n", (ulong)call); + insert_base(timebase); + virttime = call->u.e.time; /* virtual time of the call */ + if (moxcdebug) callshow(call); + (*(call->u.e.routine))(CALLARGS(call)); + call_free(call); +} + +/**************************************************************************** +* m_restuntil +* Inputs: +* int time: call time to rest until +* Effect: +* Waits until the specified time has been reached (absolute time). +* Other "caused" calls will take place during the rest provided +* this routine is called from "mainscore" (see m_rest description). +****************************************************************************/ +void m_restuntil(time) + time_type time; +{ + time = virt_to_real(timebase, time); + while(time > gettime()) { + moxcwait(time); + } +} + + +/**************************************************************************** +* m_rest +* Inputs: +* int time: Amount of time to rest +* Effect: +* Waits until the amount of time specified has lapsed +* Assumes: +* Must not be called from a "caused" routine. Must only be called +* from "mainscore" or a routine called directly or indirectly from +* "mainscore" without using "cause". +****************************************************************************/ + +void m_rest(time) + time_type time; +{ + m_restuntil(time + real_to_virt(timebase, gettime())); +} + +/**************************************************************************** +* moxcinit +* Inputs: +* int argc: number of command line arguments +* char * argv: command line argument array +* Effect: initializes moxc system +****************************************************************************/ + +boolean moxcinit(argc, argv) + int argc; + char * argv[]; +{ + meminit(); + io_init(); +#ifdef AMIGA + pub_port_signal = AllocSignal(-1L); + pub_port.mp_Node.ln_Type = NT_MSGPORT; + pub_port.mp_SigBit = pub_port_signal; + pub_port.mp_SigTask = FindTask(0L); + pub_port.mp_Flags = PA_SIGNAL; + pub_port.mp_Node.ln_Name = "CMTcmdport"; + pub_port.mp_MsgList.lh_Head = + (struct Node *)&pub_port.mp_MsgList.lh_Tail; + pub_port.mp_MsgList.lh_TailPred = + (struct Node *)&pub_port.mp_MsgList.lh_Head; + event_mask |= (1L << pub_port_signal); + AddPort(&pub_port); +#endif + cu_register((cu_fn_type) moxcterm, NULL); + cl_syntax(midifns_syntax); + cl_syntax("debugEnable verbose debugging;\ + moxcEnable moxc debug mode;"); + cl_syntax(app_syntax); + + if (!cl_init(argv, argc)) { + /* make sure user gets to read the error message(s): */ + gprintf(TRANS, "Type anything to exit..."); +#ifdef DOS + wait_ascii(); +#else + ggetchar(); +#endif + return FALSE; + } + debug = cl_switch("debug"); + moxcdebug = cl_switch("moxc"); + timebase = default_base = timebase_create(100); + default_base->rate = 2560L; + + eventtime = 0L; + next_wakeup = MAXTIME; + musicinit(); +#ifdef POSICIONADOR_3D + ptInit(); +#endif + moxcdone = 0; + return TRUE; +} + + +/**************************************************************************** +* moxcwait +* Input: +* -1 => wait for next keyboard or midi event or queued event +* 0 => don't wait +* T => wait up to T for next keyboard or midi event or queued event +* (this is used by m_restuntil) +* Assume: there is work to do (npending > 0 || evqueue) ?? +* Effect: dispatch on user inputs, cause calls +****************************************************************************/ + +void moxcwait(dateoftimeout) + time_type dateoftimeout; +{ + time_type maxtime = dateoftimeout; + + if (timebase_queue) { + if ((timebase_queue->next_time >> 8) < maxtime) + maxtime = (timebase_queue->next_time) >> 8; + } + eventwait(maxtime); + decode(); +} + + +/**************************************************************************** +* decode +* Effect: dispatch on user inputs, cause calls +****************************************************************************/ + +private void decode() +{ + /* It is important that midi_data is on a word boundary because we + copy to it by doing a word transfer. + */ + byte midi_data[4]; + time_type now; + byte code; + char k; +#ifdef AMIGA + struct cmd_msg *cmd; +#endif + + now = gettime(); + timebase = default_base; + eventtime = now; + virttime = 0L; + +/* gprintf(GDEBUG, "decode at time %ld\n", now); */ + +/********************************************** +* poll for and decode midi keyboard input +***********************************************/ + + while (getbuf(FALSE, midi_data)) { + /* only divide if necessary, divides take 100us on 8MHz 68000: */ + if (virttime == 0) + virttime = real_to_virt(default_base, now); + + /* short-circuit midi decoding */ + if (!mididecode) { + midievent(midi_data); + continue; + } + + code = midi_data[0] & MIDI_CODE_MASK; + if (code == MIDI_ON_NOTE) { + if (midi_data[2] == 0) { /* velocity 0 -> note off */ + keyup(1+(midi_data[0] & MIDI_CHN_MASK), midi_data[1]); + } else { + keydown((midi_data[0] & MIDI_CHN_MASK)+1, + midi_data[1], midi_data[2]); + } + } else if (code == MIDI_OFF_NOTE) { + keyup((midi_data[0] & MIDI_CHN_MASK)+1, midi_data[1]); + } else if (code == MIDI_TOUCH) { + touchchange((midi_data[0] & MIDI_CHN_MASK)+1,midi_data[1]); + } else if (code == MIDI_BEND) { + bendchange((midi_data[0] & MIDI_CHN_MASK)+1, + midi_data[1] + (midi_data[2] << 7)); + } else if (code == MIDI_CTRL && midi_data[1] == SUSTAIN) { + if (midi_data[2] == 0) pedup((midi_data[0] & MIDI_CHN_MASK) + 1); + else peddown((midi_data[0] & MIDI_CHN_MASK) + 1); + } else if (code == MIDI_CTRL) { + ctrlchange((midi_data[0] & MIDI_CHN_MASK) + 1, + midi_data[1], midi_data[2]); + } else if (code == MIDI_CH_PROGRAM) { + prgmchange((midi_data[0] & MIDI_CHN_MASK) + 1, midi_data[1] + 1); +/* think C midi driver doesn't handle sysex the way the Amiga drivers do (yet) */ +#ifndef MACINTOSH + } else if (code == MIDI_SYSEX) { + sysex(); +#endif + } + } + +/********************************************** +* poll for ASCII keyboard input +***********************************************/ + while (get_ascii(&k)) { + virttime = real_to_virt(default_base, now); + asciievent(k); + /* if user doesn't handle abort char in asciievent, + we should exit now to avoid an infinite loop */ + if (abort_flag) EXIT(1); + } + +#ifdef POSICIONADOR_3D +/********************************************** +* poll for posicionador tridimensionale input +**********************************************/ + { + pt_value pt_data; + while (ptGetValue(&pt_data)) { + /* only divide if necessary, divides take 100us on 8MHz 68000: */ + if (virttime == 0) + virttime = real_to_virt(default_base, now); + ptevent(&pt_data); + } + } +#endif /* POSICIONADOR_3D */ + +#ifdef AMIGA +/********************************************** +* poll for proportional controller port +**********************************************/ + if (prop_1_events) { + int events; + + Disable(); + events = prop_1_events; + prop_1_events = 0; + Enable(); + + if (events & BUTTON_1_RIGHT_CHANGE) + buttonchange(3, prop_1_right_button); + if (events & BUTTON_1_LEFT_CHANGE) + buttonchange(2, prop_1_left_button); + if (events & PROP_1_LEFT_CHANGE) + propchange(2, prop_1_left_data); + if (events & PROP_1_RIGHT_CHANGE) + propchange(3, prop_1_right_data); + } + +/********************************************** +* poll for input from public command port +***********************************************/ + + while (cmd = (struct cmd_msg *) GetMsg(&pub_port)) { + struct symb_descr *desc = &HASHENTRY(lookup(cmd->symbol_name)); +/* gprintf(TRANS, "got %lx (%s) from pub_port\n", cmd, cmd->symbol_name); */ + virttime = real_to_virt(default_base, now); + if (!desc) { + gprintf(TRANS, "Error, symbol %s undefined.\n", cmd->symbol_name); + } else if (desc->symb_type != cmd->symb_type) { + gprintf(TRANS, "Error, wrong type for symbol %s\n", + cmd->symbol_name); + } else if (cmd->symb_type == fn_symb_type) { +/* gprintf(TRANS, "Calling routine\n"); */ + (*(desc->ptr.routine))( + (int) cmd->the_args[0], (int) cmd->the_args[1], + (int) cmd->the_args[2], (int) cmd->the_args[3], + (int) cmd->the_args[4], (int) cmd->the_args[5], + (int) cmd->the_args[6], (int) cmd->the_args[7] + ); + } else if (cmd->symb_type == var_symb_type) { + *(desc->ptr.intptr) = (int) cmd->the_args[0]; + } else if (cmd->symb_type == vec_symb_type) { + if (cmd->the_args[0] >= desc->size) { + gprintf(TRANS, "Error: Vector %s is of size %d\n", + cmd->symbol_name, desc->size); + } else { + (desc->ptr.intptr)[cmd->the_args[0]] = cmd->the_args[1]; +/* gprintf(TRANS, "vec: setting %lx\n", + &(desc->ptr.intptr)[cmd->the_args[0]]); */ + } + } else gprintf(TRANS, "Symbol Type Error\n"); + ReplyMsg(&(cmd->msg)); + } +#endif +/********************************************** +* poll for next call in queue +***********************************************/ + now = (now + 1) << 8; /* shift because next_time is also scaled, + * add 256 because next_time has added priority */ + if (debug) + gprintf(TRANS, "now %ld next_time %ld\n", + now, (timebase_queue ? timebase_queue->next_time : 1234)); + /* give pending events priority, but every 100 events, loop to allow + input processing (user may want to give a "quit" command) */ + for (k = 0; + k < 100 && timebase_queue && (now > timebase_queue->next_time); + k++) { + callrun(); + } +/******************* +* flush text output +********************/ +#ifdef MACINTOSH_OR_UNIX + gflush(); +#endif +} + + +/**************************************************************************** +* quit +* Effect: tells moxc to shut down +****************************************************************************/ + +void quit() +{ + moxcdone = TRUE; +} + +/* moxcrun -- schedule events until done */ +/**/ +void moxcrun() +{ + moxcdone = FALSE; + while (!moxcdone && !abort_flag) { /* test for finish */ + if (!timebase_queue) moxcdone = TRUE; + else moxcwait(MAXTIME); /* do work */ + } +} + +/* moxcterm -- clean up after moxcinit */ +/**/ +private void moxcterm() +{ +#ifdef AMIGA + FreeSignal((long) pub_port_signal); + RemPort(&pub_port); +#endif +} diff --git a/cmt/moxc.h b/cmt/moxc.h new file mode 100644 index 0000000..975ebb9 --- /dev/null +++ b/cmt/moxc.h @@ -0,0 +1,44 @@ +/* moxc.h -- functions exported by moxie.c */ +/* Copyright 1989 Carnegie Mellon University */ + +#define maxparms 8 + +extern timebase_type timebase; +extern time_type eventtime, virttime; +extern int debug; +extern int mididecode; +extern int moxcdone; + +void catchup(void); +void callallcancel(void); +#ifdef DOTS_FOR_ARGS +void cause(delay_type delay, ...); +void causepri(delay_type delay, int pri, ...); +#else +void cause(); +void causepri(); +#endif +void m_rest(time_type time); +void m_restuntil(time_type time); +void quit(void); +boolean moxcinit(int argc, char * argv[]); +void moxcrun(void); +void moxcwait(time_type dateoftimeout); + +void asciievent(char k); +void bendchange(int chan, int value); +void coda(void); +void ctrlchange(int chan, int ctrl, int value); +void keydown(int chan, int key, int vel); +void keyup(int chan, int key); +void mainscore(void); +void midievent(byte midi_data[4]); +void peddown(int chan); +void pedup(int chan); +void prgmchange(int chan, int prgm); +void touchchange(int chan, int value); +#ifdef AMIGA +void buttonchange(int number, int value); +void propchange(int number, int value); +#endif +void sysex(void); diff --git a/cmt/musiprog.h b/cmt/musiprog.h new file mode 100644 index 0000000..ddd9f95 --- /dev/null +++ b/cmt/musiprog.h @@ -0,0 +1,31 @@ +/* musiprog.h -- include file for cmt application programs */ + +#include "stdio.h" +#include "cext.h" +#include "midifns.h" +#include "userio.h" +#include "timebase.h" +#include "moxc.h" + +/* + * override the definition of l_rest - l_rest is not recommended because + * it stops polling for input. If you really want to use it, use #undef + * to make it visible. + */ +#define l_rest(d) m_rest(d) +#define l_restuntil(t) m_restuntil(t) + +/* + * The default implementation of rest() and restuntil() poll for + * input during the rest. You might call rest() or restuntil() from + * mainscore(), but it is generally a bad idea to rest at all. If + * you are in a rest(), you get an event, e.g. keydown(), and you + * make a nested call to rest(), the original rest will be locked out + * until the nested one returns. It's better to use cause(). + */ +#define rest(x) l_rest( (long) x ) +#define restuntil(x) l_restuntil( (long) x) + +#define repeat(var, count) {int var; for (var=1; var <= count; var++) { +#define endrep ;}} + diff --git a/cmt/pitch.h b/cmt/pitch.h new file mode 100644 index 0000000..ab6dd9c --- /dev/null +++ b/cmt/pitch.h @@ -0,0 +1,9 @@ +/* mbc code */ +/* Copyright 1989 Carnegie Mellon University */ + +typedef struct pitch_struct { + int ppitch; + int pbend; +} +pitch_table; +/* end */ diff --git a/cmt/record.c b/cmt/record.c new file mode 100644 index 0000000..44f2373 --- /dev/null +++ b/cmt/record.c @@ -0,0 +1,638 @@ +/* record.c -- keyboard to adagio recorder + * Copyright 1989 Carnegie Mellon University + * + * the interface consists of three routines: + * rec_init() -- initialization + * rec_event(byte *data) -- called to insert (record) midi data, + * -- returns FALSE if no more space + * rec_final() -- called to finish up + */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 27-Feb-86 | Created changelog +* | Use pedal information when computing durations (code taken +* | from transcribe.c) +* 23-Mar-86 | Determine size of transcription when rec_init is called. +* 21-May-86 | Major rewrite to use continuous controls (code taken +* | from transcribe.c) +* 1-Aug-87 | F.H. Changed rec_init() to new memory handling. +* 17-Oct-88 | JCD : portable version. +* 31-Jan-90 | GWL : cleaned up for LATTICE +* 30-Jun-90 | RBD : further changes +* 2-Apr-91 | JDW : further changes +* 28-Apr-03 | DM : changed for portability; true->TRUE, false->FALSE +*****************************************************************************/ + +#include "switches.h" + +#include +#include + +#include "cext.h" +#include "midifns.h" +#include "userio.h" +#include "midicode.h" +#include "record.h" +#include "cmdline.h" + +extern long space; /* how much space is left? */ + +int debug_rec = FALSE; /* verbose debug flag for this module */ + +long max_notes = -1L; /* -1 is flag that space must be allocated */ + +time_type previous_time; + +/**************************************************************** +* data structure notes: the midi stream is stored as an array +* of 4-byte records, each of which is either a time or midi +* data. Midi data always begins with a control byte (high +* order bit set), and it is assumed times are positive (high +* order bit clear), so the two are easy to distinguish +* IF THE COMPILER PUTS THESE BITS IN THE SAME PLACE. It looks +* like the high order byte of the time lines up with the last +* byte of a 4 byte array, so we will always set the high order +* bit of the last array byte when the first 3 bytes are filled +* with MIDI data. This is refered to as the "tag" bit. +* WARNING: Lattice C longs are UNSIGNED, therefore always +* positive. Test the high order bit with a mask. +****************************************************************/ + +#define MIDI_CMD_BIT 0x80 +#define HIGH_BIT 0x80000000 +#define istime(note) (!(((note)->when) & HIGH_BIT)) + +typedef union note_struct { + byte n[4]; + long when; +} +*note_type, note_node; + +private note_type event_buff; /* pointer to allocated buffer */ +private note_type next; /* pointer to next entry in buffer */ +private note_type last; /* pointer to last entry in buffer */ +private int pile_ups; /* inner loop iteration count */ +private int max_pile_up; /* maximum of pile_ups */ +private boolean fixed_octave; /* used to avoid many error messages */ + +/**************************************************************************** +* Routines local to this module +****************************************************************************/ +private void bend_filter(); +private void byteorder(); +private void ctrl_filter(); +private int event_bend(); +private void filter(); +private long getdur(); +private long getnext(); +private char map_ctrl(); +private void output(); + +/**************************************************************************** +* bend_filter +* Inputs: +* note_type note: the current note +* note_type last: the last recorded event +* long now: the current time +* Effect: +* remove pitch bend events in same 0.01 sec time slot +* Implementation: +* If the current event is a pitch bend that bends again +* in the same time slot, make it a no-op by replacing it with +* the time. +****************************************************************************/ + +private void bend_filter(note, last, now) +note_type note; /* current note */ +note_type last; /* the last recorded event */ +long now; /* the current time */ +{ + /* first see if there is another bend in this time + * slot. + */ + note_type note2 = note + 1; + while (note2 < last) { + if (istime(note2) && (note2->when > now)) { + break; /* new time slot */ + } + else if (note->n[0] == note2->n[0]) { + note->when = now; + return; /* found another bend */ + } + note2++; + } +} + +/**************************************************************************** +* byteorder +* Effect: +* check out assumptions about byte order and placement +****************************************************************************/ + +private void byteorder() +{ + note_node test_event; + if ((sizeof(test_event) != 4) || + (sizeof(test_event.when) != 4) || + (sizeof(test_event.n[0]) != 1)) { + gprintf(ERROR, "implementation error: size problem\n"); + EXIT(1); + } + test_event.n[0] = 0x12; + test_event.n[1] = 0x34; + test_event.n[2] = 0x56; + test_event.n[3] = 0x78; + if ((test_event.when != 0x78563412) && + (test_event.when != 0x12345678)) { + gprintf(ERROR, "implementation error: layout problem\n"); + EXIT(1); + } +} + +/**************************************************************************** +* ctrl_filter +* Inputs: +* note_type note: the current note +* note_type last: the last recorded event +* long now: the current time +* Effect: +* remove ctrl change events in same 0.01 sec time slot +* Implementation: +* If the current event is a control change that changes again +* in the same time slot, make it a no-op by replacing it with +* the time. +****************************************************************************/ + +private void ctrl_filter(note, last, now) +note_type note; /* the current note */ +note_type last; /* the last recorded event */ +long now; /* the current time */ +{ + /* see if there is another control change in this time + * slot. + */ + note_type note2 = note+1; + while (note2 < last) { + if (istime(note2) && (note2->when > now)) { + break; /* new time slot */ + } + else if ((note->n[0] == note2->n[0]) && + (note->n[1] == note2->n[1])) { + note->when = now; + return; /* found another change */ + } + note2++; + } +} + +/**************************************************************************** +* event_bend +* Inputs: +* note_type note: pointer to a pitch bend event +* Outputs: +* returns int: an 8 bit pitch bend number +****************************************************************************/ + +private int event_bend(note) +note_type note; +{ + return((int) (((note->n[1]) >> 6) + ((note->n[2]) << 1))); +} + +/**************************************************************************** +* filter +* Inputs: +* note_type last: the last note recorded +* Effect: allow only one control change per time slot (0.01 sec) +* Implementation: +* call ctrl_filter and bend_filter to overwrite control changes with +* noop data (the current time is used as a noop) +****************************************************************************/ + +private void filter(last) +note_type last; +{ + note_type note; /* loop control variable */ + long now=0; /* last time seen */ + int command; /* command pointed to by note */ + + for (note = event_buff; note <= last; note++) { + if (istime(note)) { + now = note->when; + } + else { + command = note->n[0] & MIDI_CODE_MASK; + + if (command == MIDI_CTRL && + note->n[1] == SUSTAIN) { + /* do nothing */; + } + else if (command == MIDI_CTRL) { + ctrl_filter(note, last, now); + } + else if (command == MIDI_TOUCH) { + bend_filter(note, last, now); /* bend and touch use the */ + } + else if (command == MIDI_BEND) { /* same filter routines */ + bend_filter(note, last, now); + } + } + } +} + + +/**************************************************************************** +* getdur +* Inputs: +* int i: index of the note +* note_type last: pointer to the last event recorded +* int ped: TRUE if pedal is down at event i +* long now: the time at event i +* Outputs: +* returns long: the duration of note i +* Assumes: +* assumes i is a note +* Implementation: +* This is tricky because of pedal messages. The note is kept on by +* either the key or the pedal. Keep 2 flags, key and ped. Key is +* turned off when a key is released, ped goes off and on with pedal. +* Note ends when (1) both key and ped are FALSE, (2) key is +* pressed (this event will also start another note). +****************************************************************************/ + +private long getdur(i, last, ped, now) +int i; +note_type last; +int ped; +long now; +{ + int key = TRUE; /* flag that says if note is on */ + long start = now; + int chan = event_buff[i].n[0] & MIDI_CHN_MASK; + int pitch = event_buff[i].n[1]; + note_type note = &(event_buff[i+1]); + int noteon; /* TRUE if a noteon message received on chan */ + int keyon; /* TRUE if noteon message had non-zero velocity */ + + /* search from the next event (i+1) to the end of the buffer: + */ + for (; note < last; note++) { + if (istime(note)) { + now = note->when; + } + else { + noteon = keyon = FALSE; + if ((note->n[0] & MIDI_CHN_MASK) == chan) { + noteon = ((note->n[0] & MIDI_CODE_MASK) == MIDI_ON_NOTE) && + (note->n[1] == pitch); + keyon = noteon && (note->n[2] != 0); + if ((noteon && (note->n[2] == 0)) || + (((note->n[0] & MIDI_CODE_MASK) == MIDI_OFF_NOTE) && + (note->n[1] == pitch))) key = FALSE; + if (((note->n[0] & MIDI_CODE_MASK) == MIDI_CTRL) && + note->n[1] == SUSTAIN && note->n[2] == 127) ped = TRUE; + if (((note->n[0] & MIDI_CODE_MASK) == MIDI_CTRL) && + note->n[1] == SUSTAIN && note->n[2] == 0) ped = FALSE; + + if ((!key && !ped) || keyon) + return(now - start); + } + } + } + return(last->when - start); +} + +/**************************************************************************** +* getnext +* Inputs: +* int i: the index of the current note +* note_type last: pointer to last valid data +* long now: the current time +* Outputs: +* returns long: the time of the next note, program, or control change +* (returns time of last event if nothing else is found) +****************************************************************************/ + +private long getnext(i, last, now) +int i; /* the index of the current note */ +note_type last; /* pointer to last valid data */ +long now; /* the current time */ +{ + i++; /* advance to next item */ + for (; event_buff + i < last; i++) { + note_type note = &(event_buff[i]); + int cmd = note->n[0] & MIDI_CODE_MASK; + + if (istime(note)) { + now = note->when; + } + else if (((cmd == MIDI_ON_NOTE) && + (note->n[2] != 0)) /* note on */ || + (cmd == MIDI_CH_PROGRAM) /* program change */ || + ((cmd == MIDI_CTRL) && + (note->n[1] != SUSTAIN) /* control change */ ) || + (cmd == MIDI_TOUCH) || + (cmd == MIDI_BEND)) { + return(now); + } + } + return(last->when); +} + +/**************************************************************************** +* map_ctrl +* Inputs: +* int control: a midi control number +* Outputs: +* returns char: an adagio control change command letter, EOS if +* control change is not one of PORTARATE, PORTASWITCH, +* MODWHEEL, FOOT +****************************************************************************/ + +private char map_ctrl(control) +int control; +{ + switch (control) { +/* 'J' is no longer code for PORTARATE + case PORTARATE: + return 'J'; */ + case PORTASWITCH: + return 'K'; + case MODWHEEL: + return 'M'; + case VOLUME: + return 'X'; + default: + return EOS; + } +#ifdef LATTICE322 + return EOS; /* make Lattice C type checker happy */ +#endif +} + +/**************************************************************************** +* output +* Inputs: +* FILE *fp: an opened file pointer +* note_type last: the last data in the buffer +* boolean absflag: set to TRUE if first line of the adagio score should +* include the absolute time +* Effect: +* write adagio file using data in event_buff +* Implementation: +* NOTE: put all program changes in rests +* use N(ext) notation for all timing +* output no more than one continuous parameter change per +* clock tick for each continuous change parameter +****************************************************************************/ + +private void output(fp, last, absflag) +FILE *fp; +note_type last; +boolean absflag; +{ + int i; /* loop counter */ + int command; /* the current command */ + int voice; /* the midi channel of the current event */ + int last_velocity = -1; /* used to filter repeated Lnn attributes */ + int last_voice = 0; /* the default adagio channel (1) */ + int ped = FALSE; /* flag maintains state of pedal */ + int how_many = last - event_buff; + long now=0; /* the time of the next event */ + + if (fp == NULL) { + gprintf(ERROR, "internal error: output called with NULL file.\n"); + EXIT(1); + } + + if (debug_rec) + gprintf(GDEBUG,"hint: if file is not being closed, decrease MAXSPACE\n"); + + + fprintf(fp, "!MSEC\n"); /* times will be in milliseconds */ + /* set the initial absolute time, all other times are relative */ + + if (absflag) { + now = event_buff[0].when; + if (now < 0) { + fprintf(fp, "* First event took place at Adagio time %d,\n", + (int)now); + fprintf(fp, "* but Adagio cannot represent negative times,\n"); + fprintf(fp, "* so this entire score will be %d ms late\n", + (int)-now); + gprintf(TRANS, "First event took place at Adagio time %d!\n", + (int)now); + gprintf(TRANS, "All events times will be %d ms late\n", + (int)-now); + now = 0L; + } + fprintf(fp, "T%ld ", now); + } + + for (i = 0; i < how_many; i++) { + if (debug_rec) { + gprintf(GDEBUG,"ev %d: %x %x %x (%ld)\n", i, event_buff[i].n[0], + event_buff[i].n[1], event_buff[i].n[2], event_buff[i].when); + } + + if (istime(event_buff+i)) { + now = event_buff[i].when; + if (debug_rec) gprintf(GDEBUG,"i = %d, now = %ld\n", i, now); + } else { + boolean needs_voice = TRUE; + command = event_buff[i].n[0] & MIDI_CODE_MASK; + voice = event_buff[i].n[0] & MIDI_CHN_MASK; + + if (command == MIDI_ON_NOTE && event_buff[i].n[2] != 0) { + int velocity = event_buff[i].n[2]; + write_pitch(fp, event_buff[i].n[1]); + fprintf(fp, " U%ld", getdur(i, last, ped, now)); + if (last_velocity != velocity) { + fprintf(fp, " L%d", velocity); + last_velocity = velocity; + } + } else if (command == MIDI_CH_PROGRAM) { + fprintf(fp, "Z%d", event_buff[i].n[1] + 1); + } else if (command == MIDI_CTRL && + event_buff[i].n[1] == SUSTAIN) { + ped = (event_buff[i].n[2] != 0); + needs_voice = FALSE; + } else if (command == MIDI_CTRL) { + char c = map_ctrl(event_buff[i].n[1]); + if (c != EOS) fprintf(fp, "%c%d", c, event_buff[i].n[2]); + else fprintf(fp, "~%d(%d)", event_buff[i].n[1], event_buff[i].n[2]); + } else if (command == MIDI_TOUCH) { + fprintf(fp, "O%d", event_buff[i].n[1]); + } else if (command == MIDI_BEND) { + fprintf(fp, "Y%d", event_bend(&event_buff[i])); + } else if (command == MIDI_ON_NOTE || command == MIDI_OFF_NOTE) { + needs_voice = FALSE; /* ignore note-offs */ + } else { + gprintf(ERROR, "Command 0x%x ignored\n", command); + needs_voice = FALSE; + } + if (needs_voice) { + if (last_voice != voice) { + fprintf(fp, " V%d", voice + 1); + last_voice = voice; + } + fprintf(fp, " N%d", (int)(getnext(i, last, now) - now)); + fprintf(fp, "\n"); + } + } + } +} + + +/**************************************************************************** +* write_pitch +* Inputs: +* FILE *fp: an open file +* int p: a pitch number +* Effect: write out the pitch name for a given number +****************************************************************************/ + +void write_pitch(FILE *fp, int p) +{ + static char *ptos[] = { + "C", "CS", "D", "EF", "E", "F", "FS", "G", + "GS", "A", "BF", "B" }; + /* avoid negative numbers: adagio can't express lowest octave: */ + while (p < 12) { + if (!fixed_octave) { + gprintf(ERROR, "%s%s%s", + "A low note was transposed up an octave\n", + "(Adagio cannot express the lowest MIDI octave).\n", + "This message will appear only once.\n"); + fixed_octave = TRUE; + } + p += 12; + } + fprintf(fp, "%s%d", ptos[p % 12], (p / 12) - 1); +} + +/********************************************************************** +* rec_final +* Inputs: +* boolean absflag: output absolute time of first note if TRUE +* Effect: +* Write recorded data to a file +**********************************************************************/ + +void rec_final(FILE *fp, boolean absflag) +{ + next->when = gettime(); + last = next; + if (debug_rec) gprintf(GDEBUG,"max_pile_up = %d, ", max_pile_up); + gprintf(TRANS,"%ld times and events recorded.\n", + (long) (last - event_buff)); + filter(last); + output(fp, last, absflag); + fclose(fp); + FREE(event_buff); + max_notes = -1; +} + +/**************************************************************************** +* rec_init +* Inputs: +* char *file: pointer to file name from command line (if any) +* boolean bender: TRUE if pitch bend should be enabled +* Outputs: +* return TRUE if initialization succeeds +* Effect: +* prepares module to record midi input +****************************************************************************/ + +/* ENOUGH_ROOM says if we have room for 10000 events + 10000 timestamps = + * 20000 note_struct's, then that's "enough room" for recording a sequence. + * If more ram is available, it won't be used. If less is available, we'll + * use as much as we can get, minus "SPACE_FOR_PLAY", which leaves a little + * bit of spare ram in case Moxc or stdio need to allocate some space. + * For DOS, we limit recording space to 64K. + */ +#ifdef DOS +#define ENOUGH_ROOM 64000L +#else +#define ENOUGH_ROOM (20000L * sizeof(union note_struct)) +#endif + + +boolean rec_init(boolean bender) +{ + size_t biggestChunk, spaceForRecord; + + debug_rec = cl_switch("debug"); + byteorder(); + pile_ups = 0; + max_pile_up = 0; + previous_time = (unsigned) -1L; /* this will force putting in initial timestamp */ + fixed_octave = FALSE; + + if (max_notes == -1) { /* allocate space 1st time rec_init called */ + biggestChunk = AVAILMEM; + if (biggestChunk <= SPACE_FOR_PLAY) { + /* not enough memory; give up */ + return(FALSE); + } + else { + spaceForRecord = + MIN((biggestChunk - SPACE_FOR_PLAY), ENOUGH_ROOM); + /* leave SPACE_FOR_PLAY contiguous bytes of memory */ + } + max_notes = spaceForRecord / sizeof(note_node); + /* gprintf(GDEBUG,"max_notes = %d\n", max_notes);*/ + event_buff = (note_type) MALLOC(spaceForRecord); + if (event_buff == NULL) { + /* should never happen */ + gprintf(FATAL, "Implementation error (record.c): getting memory."); + return FALSE; + } + } + next = event_buff; + last = event_buff + max_notes - 2; /* it is critical that last not point + * to the very last storage loc */ + midi_cont(bender); + return((boolean)(max_notes > 10)); + /* it would be silly to record with only room enough for 10 notes! */ +} + + +/**************************************************************************** +* rec_event +* Inputs: +* long time: the current time +* long data: midi data to record +* Outputs: +* returns FALSE if there is no more memory +* Effect: reads and stores any input +* Implementation: +* time stamps and midi events share the same buffer of 4-byte events +* save time at most once per call to rec_poll +* save time only if it changes +****************************************************************************/ + +boolean rec_event(long *data, time_type time) +{ + /* can't allow negative time because sign bit distinguishes + * data from time: */ + if (time < 0) time = 0; + + if (previous_time != time) { + next++->when = previous_time = time; + if (next >= last) goto overflow; + } + + next->when = *data; + next++->n[3] = MIDI_CMD_BIT; /* set tag bit */ + if (next >= last) goto overflow; + return TRUE; + +overflow: + next = last; /* last doesn't really point to last storage */ + gprintf(ERROR, "No more memory.\n"); + return FALSE; +} diff --git a/cmt/record.h b/cmt/record.h new file mode 100644 index 0000000..de1479d --- /dev/null +++ b/cmt/record.h @@ -0,0 +1,6 @@ +/* Copyright 1989 Carnegie Mellon University */ + +boolean rec_init(boolean bender); +boolean rec_event(long *data, time_type time); +void rec_final(FILE *fp, boolean absflag); +void write_pitch(FILE *fp, int p); diff --git a/cmt/seq.c b/cmt/seq.c new file mode 100644 index 0000000..de54e47 --- /dev/null +++ b/cmt/seq.c @@ -0,0 +1,1199 @@ +/* seq.c -- implement adagio scores as abstract data type */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 2-Apr-91 | JDW : further changes +* 16-Feb-92 | GWL : use reg_timebase in seq_play() +* 28-Apr-03 | DM : false->FALSE, true->TRUE, portability changes +* 19-May-03 | RBD : no longer assume seq->current remains untouched between +* | note inserts +*****************************************************************************/ + +#include "stdio.h" +#include "cext.h" +#include "userio.h" +#include "midicode.h" +#include "midifns.h" +#include "timebase.h" +#include "moxc.h" +#include "seq.h" +#include "string.h" + +extern int moxcdebug; +extern timebase_type default_base; + +boolean seq_print = FALSE; /* debugging print switch */ + +seq_type sequence; /* this is a global to be accessed by routines called + * from the sequence */ + +/* clock state: */ +time_type clock_ticksize; /* millisec per tick shifted 16 bits */ +boolean clock_running = FALSE; /* TRUE if clock is running */ +boolean external_midi_clock = FALSE; +boolean suppress_midi_clock = FALSE; + +private void insert_event(seq_type, register event_type); +private void process_event(seq_type); + +private char *chunk_alloc(seq_type seq, int size); +private void clock_tick(seq_type seq, time_type fraction); +private void ramp_event(seq_type seq, event_type event, unsigned int value, + unsigned int to_value, int increment, time_type step, int n); +/*private*/ void send_macro(register unsigned char *ptr, int voice, + short parameter[], int parm_num, int value, int nline); + +/* chunk_alloc -- allocate data for a sequence */ +/* + * NOTE: This assumes one chunk is already allocated. + * The first chunk holds shared sequence information in + * the info struct, and by convention this is always in + * the first chunk. + */ +private char *chunk_alloc(seq_type seq, int size) +{ + chunk_type chunk = seq->chunklist->u.info.last_chunk; + /* gprintf(TRANS, "chunk_alloc: seq %lx size %d\n", seq, size); */ + if (size & 1) size++; /* make it even */ + if (chunk->free + size >= CHUNK_SIZE) { + chunk_type new_chunk = chunk_create(FALSE); + if (!new_chunk) + { + gprintf(FATAL, "Out of memory while reading seq\n"); + return NULL; + } + /* add new_chunk to chunk chain */ + seq->chunklist->u.info.last_chunk = new_chunk; + chunk->next = new_chunk; + chunk = new_chunk; + } + chunk->free += size; + return &(chunk->u.data[chunk->free - size]); +} + + +/* chunk_create -- create a new chunk for seq data */ +/* + * If this is the first chunk, set first_flag to reserve + * space for the info structure. + */ +chunk_type chunk_create(boolean first_flag) +{ + chunk_type result = (chunk_type) memget(sizeof(chunk_node)); + if (result) { + result->next = NULL; + result->u.info.refcount = 1; /* pre-initialize for caller */ + result->free = 0; + if (first_flag) { + result->free = sizeof(struct info_struct); + result->u.info.last_chunk = result; + result->u.info.dictionary = NULL; + result->u.info.eventlist = NULL; + result->u.info.ctrlcount = 0; + result->u.info.notecount = 0; + result->u.info.duration = 0; + result->u.info.used_mask = 0; + } + } + /* gprintf(TRANS, "chunk_create: got %lx (size %d)\n", */ + /* result, sizeof(chunk_node)); */ + return result; +} + +/* clock_tick -- advance the clock and send a tick */ +/**/ +private void clock_tick(seq_type seq, time_type fraction) +{ + int delay; + fraction += clock_ticksize; + delay = fraction >> 16; + fraction &= 0xFFFF; + if (seq->runflag && clock_ticksize && seq->note_enable) { + midi_clock(); + cause((delay_type)delay, clock_tick, seq, fraction); + } else { + clock_running = FALSE; + midi_stop(); + midi_clock(); /* stop takes effect on next clock, so provide one */ + } +} + +private void cycle(seq_type seq) +{ + seq_reset(seq); + seq_play(seq); +} + + + +/**************************************************************************** +* event_create +* Inputs: +* seq_type seq: the seq to hold the event +* int size: the size of the event in bytes +* time_type etime: the time of the event +* int eline: the line number of the event +* Returns: +* event_type: a new event structure or +* NULL if there is not enough memory left +* Effect: +* allocates memory from the chunk, then heap as needed +* Implementation: +* to reduce the per block storage overhead, we allocate memory in +* large chunks and do our own allocation. Allocate from first +* chunk first. If full, allocate a new chunk. +* WARNING: this implementation assumes that individual events are never freed!! +****************************************************************************/ + +private event_type event_create(seq, size, etime, eline) + seq_type seq; + int size; + time_type etime; + int eline; +{ + event_type result = (event_type) chunk_alloc(seq, size); + if (result) { + result->ntime = etime; + result->nline = eline; + /* since we know the time, we can insert now: */ + insert_event(seq, result); + seq_duration(seq) = MAX(seq_duration(seq), etime); + } + return result; +} + + +/* insert_call -- add a call event to the seq */ +/**/ +event_type insert_call(seq, ctime, cline, voice, addr, value, n) + seq_type seq; + time_type ctime; + int cline; + int voice; + int (*addr)(); + long value[SEQ_MAX_PARMS]; + int n; +{ + int i; + register event_type event = event_create(seq, callsize, ctime, cline); + if (seq_print) { + gprintf(TRANS, + "call(%lx): time %ld, line %d, voice %d, fn %lx,\n\tvalues:", + event, ctime, cline, voice, addr); + for (i = 0; i < n; i++) gprintf(TRANS, " %ld", value[i]); + gprintf(TRANS, "\n"); + } + if (event) { + seq_used_mask(seq) |= 1 << (voice - 1); + event->nvoice = ctrl_voice(ESC_CTRL, voice); + event->value = CALL_VALUE; + event->u.call.routine = addr; + /* save the arguments */ + for (i = 0; i < n; i++) event->u.call.args.a[i] = value[i]; + seq_ctrlcount(seq)++; + } + return event; +} + + +/* insert_clock -- add a clock cmd to the seq */ +/**/ +event_type insert_clock(seq, ctime, cline, ticksize) + seq_type seq; + time_type ctime; + int cline; + time_type ticksize; +{ + register event_type event = event_create(seq, clocksize, ctime, cline); + + if (seq_print) { + gprintf(TRANS, "clock(%lx): time %ld, line %d\n", event, ctime, cline); + } + if (event) { + event->nvoice = ctrl_voice(ESC_CTRL, 1); + event->value = CLOCK_VALUE; + event->u.clock.ticksize = ticksize; + seq_ctrlcount(seq)++; + } + return event; +} + + +/* insert_ctrl -- add a control to the seq */ +/**/ +event_type insert_ctrl(seq, ctime, cline, ctrl, voice, value) + seq_type seq; + time_type ctime; + int cline; + int ctrl; + int voice; + int value; +{ + register event_type event = event_create(seq, ctrlsize, ctime, cline); + if (seq_print) { + gprintf(TRANS, + "ctrl(%lx): time %ld, line %d, ctrl %d, voice %d, value %d\n", + event, ctime, cline, ctrl, voice, value); + } + if (event) { + seq_used_mask(seq) |= 1 << (voice - 1); + event->nvoice = ctrl_voice(ctrl, voice); + event->value = value; + seq_ctrlcount(seq)++; + } + return event; +} + + +/* insert_ctrlramp -- add a control ramp event to the seq */ +/**/ +event_type insert_ctrlramp(seq, rtime, rline, voice, step, dur, ctrl, v1, v2) + seq_type seq; + time_type rtime; + int rline; + int voice; + time_type step; + time_type dur; + int ctrl; + int v1, v2; +{ + register event_type event = event_create(seq, ctrlrampsize, rtime, rline); + if (seq_print) { + gprintf(TRANS, + "ctrlramp(%lx): time %ld, line %d, step %ld, dur %ld, ctrl %d, voice %d\n", + event, rtime, rline, step, dur, ctrl, voice); + gprintf(TRANS, "\tfrom %d to %d\n", v1, v2); + } + + if (event) { + seq_used_mask(seq) |= 1 << (voice - 1); + event->nvoice = ctrl_voice(ESC_CTRL, voice); + event->value = CTRLRAMP_VALUE; + if (dur <= 0) dur = 1L; /* don't allow zero duration */ + event->u.ramp.dur = dur; + event->u.ramp.ctrl = ctrl; + if (step <= 0) step = 1; /* don't allow zero step size */ + event->u.ramp.step = (short) step; + event->u.ramp.u.ctrl.from_value = v1; + event->u.ramp.u.ctrl.to_value = v2; + seq_ctrlcount(seq)++; + seq_duration(seq) = MAX(seq_duration(seq), rtime + dur); + } + return event; +} + + +/* insert_def -- add a definition to the dictionary */ +/**/ +def_type insert_def(seq, symbol, definition, deflen) + seq_type seq; + char *symbol; + unsigned char *definition; + int deflen; +{ + int i; + def_type defn = (def_type) chunk_alloc(seq, sizeof(def_node)); + defn->symbol = chunk_alloc(seq, strlen(symbol) + 1); + defn->definition = (unsigned char *) chunk_alloc(seq, deflen); + strcpy(defn->symbol, symbol); + for (i = 0; i < deflen; i++) { + defn->definition[i] = definition[i]; + } + defn->next = seq_dictionary(seq); + seq_dictionary(seq) = defn; + if (seq_print) { + gprintf(TRANS, "def(%ld): symbol %s defn \n", defn, symbol); + for (i = 0; i < deflen; i++) gprintf(TRANS, "%x", definition[i]); + gprintf(TRANS, "\n"); + } + return defn; +} + + +/* insert_deframp -- add a def ramp event to the seq */ +/**/ +event_type insert_deframp(seq, rtime, rline, voice, step, dur, + def, nparms, parms, parm_num, to_value) + seq_type seq; + time_type rtime; + int rline; + int voice; + time_type step; + time_type dur; + def_type def; + int nparms; /* number of parameters for macro */ + short parms[]; /* actual parameter vector */ + int parm_num; /* which of the actual parameters to ramp */ + int to_value; /* final destination of ramp */ +{ + register event_type event = event_create(seq, deframpsize, rtime, rline); + if (seq_print) { + int i; + gprintf(TRANS, + "deframp(%ld): time %ld, line %d, voice %d, step %ld, dur %ld\n", + event, rtime, rline, voice, step, dur); + gprintf(TRANS, "def %ld, parms"); + for (i = 0; i < nparms; i++) gprintf(TRANS, " %d", parms[i]); + gprintf(TRANS, "parm_num %d to %d\n", parm_num, to_value); + } + if (event) { + int i; + seq_used_mask(seq) |= 1 << (voice - 1); + event->nvoice = ctrl_voice(ESC_CTRL, voice); + event->value = DEFRAMP_VALUE; + if (dur <= 0) dur = 1L; /* don't allow zero duration */ + event->u.ramp.dur = dur; + event->u.ramp.ctrl = 0; + if (step <= 0) step = 1; /* don't allow zero step size */ + event->u.ramp.step = (short) step; + event->u.ramp.u.def.definition = def->definition; + for (i = 0; i < nmacroparms; i++) { + event->u.ramp.u.def.parameter[i] = (i < nparms ? parms[i] : 0); + } + event->u.ramp.u.def.parm_num = parm_num; + event->u.ramp.u.def.to_value = to_value; + seq_ctrlcount(seq)++; + seq_duration(seq) = MAX(seq_duration(seq), rtime + dur); + } + return event; +} + + +/**************************************************************************** +* insert_event +* Inputs: +* seq_type seq: where to put the event +* event_type event: the event to insert +* Effect: +* inserts event into the event list +* NOTE: it is inserted *after* previously inserted events with the same time +* Implementation: +* adagio files often contain many independent voices. Although each voice +* consists of events in sequence, the voices need not be inter-twined in +* the input file. Rather, all the events of voice 1 appear followed by all +* the events of voice 2, and so forth. As phase one merges these event +* sequences, it must make many passes over an increasingly long list of +* events: expensive if we always start from the beginning of the list! +* we can exploit the fact that each voice is sequential by starting the +* search for the proper point of insertion at the last event inserted. +* the variable "last_event" is used to remember this hint. We could +* also snapshot "last_event" in "ref_event" when a !tempo or !rate +* command occurs as another hint, but we don't. +****************************************************************************/ + +private void insert_event(seq, event) + seq_type seq; + register event_type event; +{ + event_type *evlptr = &(seq_eventlist(seq)); + if ((*evlptr == NULL) || + (event->ntime < (*evlptr)->ntime)) { + /* insert at the head of the list */ + event->next = *evlptr; + *evlptr = event; + seq->current = event; + } else { + /* insert somewhere after the head of the list + * do not assume: current is not NULL. Although we always leave + * it set, the client may access the sequence before the next + * insert. + */ + register event_type previous; + register event_type insert_before; + + if (!seq->current) { + seq->current = seq_eventlist(seq); + } + if (event->ntime >= seq->current->ntime) { + /* insertion point is after current */ + previous = seq->current; + insert_before = previous->next; + } else { + /* insertion point is before current; start at beginning */ + /* assume: not inserting at very head of list; that would + * have been taken care of above */ + previous = seq_events(seq); + insert_before = previous->next; + } + + while ((insert_before != NULL) && + (event->ntime >= insert_before->ntime)) { + previous = insert_before; + insert_before = insert_before->next; + } + previous->next = event; + event->next = insert_before; + seq->current = event; + } +} + + +/* insert_macctrl -- add a control to the seq */ +/**/ +event_type insert_macctrl(seq, ctime, cline, ctrl, voice, value) + seq_type seq; + time_type ctime; + int cline; + int ctrl; + int voice; + int value; +{ + register event_type event = event_create(seq, macctrlsize, ctime, cline); + if (seq_print) { + gprintf(TRANS, + "macctrl(%lx): time %ld, line %d, ctrl %d, voice %d, value %d\n", + event, ctime, cline, ctrl, voice, value); + } + if (event) { + seq_used_mask(seq) |= 1 << (voice - 1); + event->nvoice = ctrl_voice(ESC_CTRL, voice); + event->value = MACCTRL_VALUE; + event->u.macctrl.ctrl_number = ctrl; + event->u.macctrl.value = value; + seq_ctrlcount(seq)++; + } + return event; +} + + +/* insert_macro -- insert a macro call seq */ +/**/ +event_type insert_macro(seq, ctime, cline, def, voice, nparms, parms) + seq_type seq; + time_type ctime; + int cline; + def_type def; + int voice; + int nparms; + short *parms; +{ + register event_type event = event_create(seq, macrosize, ctime, cline); + if (seq_print) { + int i; + gprintf(TRANS, + "macro(%lx): time %ld, line %d, def %ld, voice %d, parms", + event, ctime, cline, def, voice); + for (i = 0; i < nparms; i++) gprintf(TRANS, " %d", parms[i]); + gprintf(TRANS, "\n"); + } + if (event) { + seq_used_mask(seq) |= 1 << (voice - 1); + event->nvoice = ctrl_voice(ESC_CTRL, voice); + event->value = MACRO_VALUE; + event->u.macro.definition = def->definition; + while (nparms-- > 0) { + event->u.macro.parameter[nparms] = parms[nparms]; + } + seq_ctrlcount(seq)++; + } + return event; +} + + +/* insert_note -- add a note to the seq */ +/**/ +event_type insert_note(seq, ntime, nline, voice, pitch, dur, loud) + seq_type seq; + time_type ntime; + int nline; + int voice; + int pitch; + time_type dur; + int loud; +{ + register event_type event = event_create(seq, notesize, ntime, nline); + + if (seq_print) { + gprintf(TRANS, + "note(%lx): time %ld, line %d, dur %ld, pitch %d, voice %d, loudness %d\n", + event, ntime, nline, dur, pitch, voice, loud); + } + + if (event) { + seq_used_mask(seq) |= 1 << (voice - 1); + event->nvoice = voice - 1; + event->value = pitch; + event->u.note.ndur = (dur << 8) + loud; + seq_notecount(seq)++; + seq_duration(seq) = MAX(seq_duration(seq), ntime + dur); + } + return event; +} + + +/* insert_seti -- add a seti event to the seq */ +/**/ +event_type insert_seti(seq, stime, sline, voice, addr, value) + seq_type seq; + time_type stime; + int sline; + int voice; + int *addr; + int value; +{ + register event_type event = event_create(seq, setisize, stime, sline); + if (seq_print) { + gprintf(TRANS, + "seti(%ld): time %ld, line %d, voice %d, addr %ld, value %d\n", + event, stime, sline, voice, addr, value); + } + if (event) { + event->nvoice = ctrl_voice(ESC_CTRL, voice); + event->value = SETI_VALUE; + event->u.seti.int_to_set = addr; + event->u.seti.value = value; + seq_ctrlcount(seq)++; + } + return event; +} + + +/* noop -- just returns, the default stopfunc for sequences */ +/**/ +void noop(seq_type seq) {} + + +private void process_event(seq) + seq_type seq; +{ + register event_type event; + if (!seq->runflag) return; + while ((event = seq->current) && (event->ntime <= virttime)) { + int voice; + /* process all current (and earlier) events */ + if (is_note(event)) { /*** play a note or rest ***/ + /* if this note is not a rest, play it and schedule an off event */ + if (event->value != NO_PITCH && + (seq_channel_mask(seq) & + (1 << ((voice = vc_voice(event->nvoice)) - 1)))) { + seq_noteon(seq, voice, event->value, + (int) event->u.note.ndur & 0xFF); + if (debug) { + gprintf(TRANS, "play pitch %d at %ld\n", + event->value, event->ntime); + } + seq_cause_noteoff(seq, (event->u.note.ndur) >> 8, + voice, event->value); + + } + } else { /*** send a control command ***/ + int n; + time_type step; + int delta; + long increment; + int voice = vc_voice(event->nvoice); + ulong enabled = seq_channel_mask(seq) & (1 << (voice - 1)); + + switch (vc_ctrl(event->nvoice)) { + case PSWITCH_CTRL: + if (!enabled) break; + seq_midi_ctrl(seq, voice, PORTASWITCH, event->value); + break; + case MODWHEEL_CTRL: + if (!enabled) break; + seq_midi_ctrl(seq, voice, MODWHEEL, event->value); + break; + case TOUCH_CTRL: + if (!enabled) break; + seq_midi_touch(seq, voice, event->value); + break; + case VOLUME_CTRL: + if (!enabled) break; + seq_midi_ctrl(seq, voice, VOLUME, event->value); + break; + case BEND_CTRL: + if (!enabled) break; + seq_midi_bend(seq, voice, (event->value << 6)); + break; + case PROGRAM_CTRL: + if (!enabled) break; + seq_midi_program(seq, voice, event->value + 1); + break; + case ESC_CTRL: + switch (event->value) { + case CALL_VALUE: + sequence = seq; + (*(event->u.call.routine))(event->u.call.args); + break; + case CLOCK_VALUE: + clock_ticksize = event->u.clock.ticksize; + if (!clock_running && !suppress_midi_clock && + !external_midi_clock) { + clock_running = TRUE; + midi_start(); + clock_tick(seq, 0L); + } + break; + case MACCTRL_VALUE: + if (!enabled) break; + seq_midi_ctrl(seq, voice, event->u.macctrl.ctrl_number, + event->u.macctrl.value); + break; + case MACRO_VALUE: { + if (!enabled) break; + send_macro(event->u.macro.definition, voice, + event->u.macro.parameter, -1, 0, + event->nline); + break; + } + case CTRLRAMP_VALUE: + case DEFRAMP_VALUE: { + int from, to; + if (!enabled) break; + + step = event->u.ramp.step; + if (event->value == CTRLRAMP_VALUE) { + from = event->u.ramp.u.ctrl.from_value; + to = event->u.ramp.u.ctrl.to_value; + } else { + from = event->u.ramp.u.def.parameter[ + event->u.ramp.u.def.parm_num]; + to = event->u.ramp.u.def.to_value; + } + delta = to - from; + increment = delta; + if (delta < 0) delta = -delta; + /* Note: Step is always non-zero */ + n = event->u.ramp.dur / step; + increment = (increment << 8) / n; + ramp_event(seq, event, from << 8, to << 8, + (int) increment, step, n); + seq->noteoff_count++; + break; + } + case SETI_VALUE: + *(event->u.seti.int_to_set) = event->u.seti.value; + break; + default: + gprintf(TRANS, "unexpected ESC_CTRL value\n"); + break; + } + break; + default: + gprintf(TRANS, "unexpected seq data\n"); + break; + } + } + seq->current = event->next; + } + if (seq->current) { + cause((delay_type)(event->ntime - virttime), process_event, seq); + } else if (seq->noteoff_count == 0 && seq->note_enable) { + /* if we're just advancing to a start point, note_enable will be + * FALSE and this won't get called: + */ + if (seq->stopfunc) { + (*(seq->stopfunc))(seq); + } + } +} + + +/* ramp_event -- generate a ramp */ +/**/ +private void ramp_event(seq, event, value, to_value, increment, step, n) + seq_type seq; + register event_type event; + unsigned int value; + unsigned int to_value; + int increment; + time_type step; + int n; +{ + if (seq->runflag) { + int voice = vc_voice(event->nvoice); +/* printf("ramp_event: value %d to_value %d increment %d step %d n %d time %d\n", + value, to_value, increment, step, n, virttime); */ + if (n == 0) value = to_value; + else { + causepri((delay_type)step, 5, ramp_event, seq, event, value + increment, + to_value, increment, step, n - 1); + } + if (event->value == CTRLRAMP_VALUE) { + int ctrl = event->u.ramp.ctrl; + if (ctrl == -TOUCH_CTRL) midi_touch(voice, value >> 8); + else if (ctrl == -BEND_CTRL) midi_bend(voice, value >> 2); + else midi_ctrl(voice, ctrl, value >> 8); + } else { /* must be DEFRAMP_VALUE */ + send_macro(event->u.ramp.u.def.definition, + vc_voice(event->nvoice), + event->u.ramp.u.def.parameter, + event->u.ramp.u.def.parm_num, value >> 8, + event->nline); + } + if (n == 0) seq_end_event(seq); + } +} + + +/* report_enabled_channels -- print out concise listing of channels */ +/* + * to fit on one line, write out ranges, e.g. 1-5 9-11 + */ +void report_enabled_channels(seq) + seq_type seq; +{ + ulong mask = seq_channel_mask(seq); + int i, range_open_at = 0; + + for (i = 1; i <= MAX_CHANNELS; i++) { + if (!range_open_at && (mask & 1)) { + gprintf(TRANS, " %d", i); + range_open_at = i; + } else if (range_open_at && !(mask & 1)) { + if (i > (range_open_at + 1)) { + gprintf(TRANS, "-%d", i - 1); + } + range_open_at = 0; /* FALSE */ + } + mask = mask >> 1; + } + if (range_open_at) gprintf(TRANS, "-%d", MAX_CHANNELS); +} + + +/* send_macro -- instantiate macro and send it */ +/* + * note: to support ramping, "value" is used in place of + * parameter["parm_num"] + */ +/*private*/ +void send_macro(ptr, voice, parameter, parm_num, value, nline) + register unsigned char *ptr; + int voice; + short parameter[]; + int parm_num; + int value; + int nline; +{ + register unsigned char code, *loc; + while ((code = *ptr++)) { + loc = ptr + *ptr; + ptr++; + if (code <= nmacroparms) { + code--; + *loc = (code == parm_num ? value : parameter[code]) & 0x7f; + } else if (code == nmacroparms + 1) { + /* take old high order bits and OR in 4 voice bits */ + *loc = (*loc & 0xF0) | ((voice - 1) & 0xF); + } else { + code -= (nmacroparms + 2); + *loc = ((code == parm_num ? value : parameter[code]) >> 7) & 0x7F; + } + } + if (ptr[1] == MIDI_SYSEX) { + midi_exclusive(ptr + 1); + } else { + /* make sure user didn't try to send more than 3 bytes. This test + * could be done at sequence read time, but it's tricky because the + * first byte could be a parameter, so in general you need to + * plug the actual parameters into the message and then do the test. + * Currently, this is the only place parameters are plugged in. + */ + if (*ptr > 3) { + gprintf(ERROR, + "Non-sysex macro longer than 3 bytes ignored, line %d.\n", + nline); + } else { + midi_write((int) *ptr, MIDI_PORT(voice), ptr[1], ptr[2], ptr[3]); + } + } +} + + +/* seq_alloc -- a utility function to allocate a seq struct */ +/**/ +seq_type seq_alloc() +{ + seq_type seq; + seq = (seq_type) memget(sizeof(seq_node)); + return seq; +} + + +/* seq_at_end -- set the function to be called at sequence end */ +/**/ +void seq_at_end(seq, fn) + seq_type seq; + void (*fn)(seq_type); +{ + if (!fn) fn = noop; + seq->stopfunc = fn; +} + + +/* seq_cause_noteoff_meth -- turn off a note in the future */ +/**/ +void seq_cause_noteoff_meth(seq_type seq, time_type delay, int voice, int pitch) +{ + if (seq->note_enable) { + pitch += seq->transpose; + while (pitch < 0) pitch += 12; + while (pitch > 127) pitch -= 12; + seq->noteoff_count++; + causepri((delay_type) delay, 10, seq->noteoff_fn, + seq, voice, pitch); + } +} + +/* seq_copy -- copy a sequence, share the eventlist */ +/**/ +seq_type seq_copy(from_seq) + seq_type from_seq; +{ + register seq_type seq = seq_init(seq_alloc(), FALSE); + if (!seq) return NULL; + seq->chunklist = from_seq->chunklist; + seq->current = seq_events(seq); + seq->chunklist->u.info.refcount++; + seq->transpose = from_seq->transpose; + seq->loudness = from_seq->loudness; + seq->rate = from_seq->rate; + seq->paused = from_seq->paused; + seq->noteoff_count = 0; + return seq; +} + + +/* seq_create -- create a seq structure and an initial event chunk */ +/**/ +seq_type seq_create() +{ + return seq_init(seq_alloc(), TRUE); +} + + +/* seq_cycle -- set parameters for cycling a sequence */ +/**/ +void seq_cycle(seq_type seq, boolean flag, time_type dur) +{ + seq->cycleflag = flag; + seq->cycledur = dur; +} + + +/* seq_end_event -- call this when an score-generated event ends */ +/* + * Assumes that noteoff_count was incremented when event started. + */ +void seq_end_event(seq) + seq_type seq; +{ + /*gprintf(TRANS, "nd");*/ + seq->noteoff_count--; + if (seq->current == NULL /* finished seq */ && + seq->noteoff_count == 0 /* finished noteoff's */ && + seq->runflag /* we've not been stopped */) { + if (seq->cycleflag) { + cause((delay_type) (seq->cycledur - virttime), cycle, seq); + } else if (seq->stopfunc) { + (*(seq->stopfunc))(seq); + } + } +} + + + +/**************************************************************************** +* seq_free_meth +* Input: a seq_type +* Effect: +* frees storage occupied by a seq +****************************************************************************/ + +private void seq_free_meth(seq) + seq_type seq; +{ + seq_free_chunks(seq); + if (seq->timebase) timebase_free(seq->timebase); + memfree((void *) seq, sizeof(seq_node)); +} + + +/* seq_free_chunks -- free storage for note list */ +/* + * NOTE: in its original form, this routine was perhaps more readable, + * but would not compile under Microsoft C V7.00 due to a compiler bug. + * I rewrote the code until the bug disappeared, hopefully without + * changing the semantics! If you change this code, make sure it still + * compiles under Microsoft C. + * + * This module frees chunks from a seq_type in preparation for freeing + * the seq_type itself. Reference counts are checked and chunks are + * only freed when the last reference is removed. + */ +public void seq_free_chunks(seq) + seq_type seq; +{ + chunk_type tail; + chunk_type head; + + head = seq->chunklist; + if (((head->u.info.refcount)--) != 0) return; + + while (head != NULL) { + tail = head->next; + memfree((void *) head, sizeof(chunk_node)); + head = tail; + seq->chunklist = head; + } +} + + +seq_type seq_init(seq, create_chunk) + seq_type seq; + int create_chunk; +{ + if (!seq || !(seq->timebase = timebase_create(50))) { + return NULL; + } + seq->chunklist = NULL; + if (create_chunk) { + seq->chunklist = chunk_create(TRUE); + if (!seq->chunklist) { + seq_free(seq); + return NULL; + } + } + seq->cause_noteoff_fn = seq_cause_noteoff_meth; + seq->midi_bend_fn = seq_midi_bend_meth; + seq->midi_ctrl_fn = seq_midi_ctrl_meth; + seq->midi_program_fn = seq_midi_program_meth; + seq->midi_touch_fn = seq_midi_touch_meth; + seq->noteoff_fn = seq_noteoff_meth; + seq->noteon_fn = seq_noteon_meth; + seq->free_fn = seq_free_meth; + seq->reset_fn = seq_reset_meth; + + seq->current = NULL; + seq->transpose = 0; + seq->loudness = 0; + seq->cycleflag = FALSE; + seq->cycledur = 0L; + seq->rate = 256L; + seq->paused = FALSE; + seq->stopfunc = noop; + seq->channel_mask = 0xFFFFFFFFL; + seq->runflag = seq->note_enable = FALSE; + return seq; +} + + +/* seq_midi_bend_meth -- send a midi bend */ +/**/ +void seq_midi_bend_meth(seq_type seq, int voice, int value) +{ + midi_bend(voice, value); +} + + +/* seq_midi_ctrl_meth -- send a midi ctrl change */ +/**/ +void seq_midi_ctrl_meth(seq_type seq, int voice, int ctrl, int value) +{ + midi_ctrl(voice, ctrl, value); +} + + +/* seq_midi_program_meth -- send a midi program change */ +/**/ +void seq_midi_program_meth(seq_type seq, int voice, int prog) +{ + midi_bend(voice, prog); +} + + +/* seq_midi_touch_meth -- send a midi touch */ +/**/ +void seq_midi_touch_meth(seq_type seq, int voice, int value) +{ + midi_touch(voice, value); +} + + +/* seq_noteoff_meth -- turn a seq note off */ +/**/ +void seq_noteoff_meth(seq_type seq, int voice, int pitch) +{ + midi_note(voice, pitch, 0); + /*gprintf(TRANS, "_e");*/ + seq_end_event(seq); +} + + +/* seq_noteon_meth -- play a note with transformations */ +/**/ +void seq_noteon_meth(seq_type seq, int chan, int pitch, int vel) +{ + if (seq->note_enable) { + pitch += seq->transpose; + while (pitch < 0) pitch += 12; + while (pitch > 127) pitch -= 12; + + vel += seq->loudness; + if (vel <= 0) vel = 1; + else if (vel > 127) vel = 127; + + midi_note(chan, pitch, vel); + } +} + + +/* seq_pause -- stop playing momentarily or resume playing */ +/**/ +time_type seq_pause(seq_type seq, boolean flag) +{ + if (!seq->paused && flag) { + seq->paused = TRUE; + seq->rate = seq->timebase->rate; + set_rate(seq->timebase, STOPRATE); + } else if (seq->paused && !flag) { + seq_play(seq); + } + return (time_type) seq->timebase->virt_base; +} + + +/* seq_play -- play a sequence from the current event forward */ +/**/ +void seq_play(seq) + seq_type seq; +{ + timebase_type prev_timebase = timebase; + register timebase_type reg_timebase = seq->timebase; + + if (!seq->runflag) { + seq_reset(seq); + } + if (!seq->paused) return; + eventtime = gettime(); + + /* assume that virt_base is correct virtual time as the result + of seq_start_time or seq_reset + */ + timebase = reg_timebase; + virttime = reg_timebase->virt_base; + /* note that set_rate will set reg_timebase->real_base to eventtime */ + set_rate(reg_timebase, seq->rate); + seq->paused = FALSE; /* in case the score had been paused; note that + seq_pause() has no effect if paused is TRUE */ + seq->runflag = TRUE; + seq->note_enable = TRUE; + + /* restore previous timebase */ + timebase_use(prev_timebase); +} + + +/* seq_reset_meth -- reset a sequence to start back at the first event */ +/**/ +void seq_reset_meth(seq_type seq) +{ + timebase_type old_timebase = timebase; + + if (seq->runflag) { + /* maybe this seq is already reset, and process_event is + * already scheduled. If so, don't schedule another one. + */ + if ((seq->timebase->virt_base == 0) && + (seq->timebase->rate == STOPRATE)) { + /* in case the reader just iterated through the list without + * cause'ing events, reset the event list + */ + seq->current = seq_events(seq); + return; + } + /* Otherwise, the seq is running, so stop it. */ + seq_stop(seq); + } + + timebase_use(seq->timebase); + set_rate(seq->timebase, STOPRATE); + set_virttime(seq->timebase, 0L); + seq->current = seq_events(seq); + seq->noteoff_count = 0L; + seq->runflag = TRUE; + seq->paused = TRUE; + if (seq->current) + cause((delay_type)(seq->current->ntime - virttime), process_event, seq); + timebase_use(old_timebase); +} + + +/* seq_set_loudness -- set the loudness offset of a sequence */ +/**/ +void seq_set_loudness(seq, loud) + seq_type seq; + int loud; +{ + seq->loudness = loud; +} + +/* seq_set_rate -- set the rate of a sequence */ +/**/ +void seq_set_rate(seq, rate) + seq_type seq; + time_type rate; +{ + seq->rate = rate; + if (!seq->paused) set_rate(seq->timebase, rate); +} + + +/* seq_set_transpose -- set the sequence transposition */ +/**/ +void seq_set_transpose(seq, trans) + seq_type seq; + int trans; +{ + seq->transpose = trans; +} + + +/* seq_start_time -- set the current pointer so the sequence starts here */ +/**/ +void seq_start_time(seq, start_time) + seq_type seq; + time_type start_time; +{ + timebase_type prev_timebase = timebase; + if (!seq->runflag) { + seq_reset(seq); + } + if (real_to_virt(seq->timebase, eventtime) > start_time) { + seq_reset(seq); + } + timebase_use(seq->timebase); + seq->note_enable = FALSE; + /* prime the pump */ + set_rate(timebase, STOPRATE); + set_virttime(timebase, start_time); + catchup(); + seq->note_enable = TRUE; + seq->paused = TRUE; + /* restore previous timebase */ + timebase_use(prev_timebase); +} + + +/* seq_stop -- stop a sequence, clear out all pending events */ +/**/ +void seq_stop(seq) + seq_type seq; +{ + timebase_type prev_timebase = timebase; + + if (seq->runflag) { + if (moxcdebug) + gprintf(TRANS, "seq_reset swap from timebase 0x%x to 0x%x\n", + timebase, seq->timebase); + timebase = seq->timebase; + seq->runflag = FALSE; + set_rate(timebase, STOPRATE); + set_virttime(timebase, MAXTIME); + catchup(); + } + timebase_use(prev_timebase); +} diff --git a/cmt/seq.h b/cmt/seq.h new file mode 100644 index 0000000..4177d2c --- /dev/null +++ b/cmt/seq.h @@ -0,0 +1,295 @@ +/* seq.h -- definitions for seq, the MIDI Toolkit sequence data type */ + +#define minpitch 0 +#define maxpitch 127 +#define NO_PITCH (maxpitch+1) +#define minprogram 1 +#define maxprogram 128 + +/* keep these two lines in sync */ +#define nmacroparms 4 +#define parm_expected_error "Parameter number [1-4] expected" + +#define seq_dflt_loud 127 +#define seq_dflt_voice 1 +#define seq_dflt_pitch 60 + +struct clock_struct { + time_type ticksize; +}; + + +struct ctrlramp_struct { + unsigned char from_value; + unsigned char to_value; +}; + + +struct deframp_struct { + unsigned char *definition; + short parameter[nmacroparms]; + unsigned char parm_num; + short to_value; +}; + + +struct macctrl_struct { + unsigned char ctrl_number; + unsigned char value; +}; + + +struct macro_struct { + unsigned char *definition; + short parameter[nmacroparms]; +}; + + +struct note_struct { + long ndur; /* duration */ + /* char nloud; loudness (MIDI velocity) now stored as low order byte + * of ndur + */ +}; + + +struct ramp_struct { + time_type dur; + short ctrl; /* encode pitch bend and after touch as negative */ + short step; + union { + struct ctrlramp_struct ctrl; + struct deframp_struct def; + } u; +}; + + +struct seti_struct { + int *int_to_set; + int value; +}; + + +#define SEQ_MAX_PARMS 8 +struct cause_struct { + int (*routine)(); + /* make a structure so we can copy by value */ + struct seq_arg_struct { + long a[SEQ_MAX_PARMS]; + } args; +}; + + +typedef struct event_struct { + struct event_struct *next; + time_type ntime; /* start time */ + short nline; /* line number from source code */ + unsigned char nvoice; /* adagio voice (MIDI Channel) + * if this is a control change, high order 4 bits + * contain the control number, otherwise high order + * 4 bits are 0 (see is_note macro below) + */ + unsigned char value; + /* this is a note pitch or a control value. It goes + * here rather than in the union to achieve word + * alignment (!). Also, value is used for extra commands + * such as call, seti, setv. + */ + union { + struct cause_struct call; + struct clock_struct clock; + struct macctrl_struct macctrl; + struct macro_struct macro; + struct note_struct note; + struct ramp_struct ramp; + struct seti_struct seti; + } u; +} event_node, *event_type; + +#define PSWITCH_CTRL 1 +#define MODWHEEL_CTRL 2 +#define TOUCH_CTRL 3 +#define VOLUME_CTRL 4 +#define BEND_CTRL 5 +#define PROGRAM_CTRL 6 +#define ESC_CTRL 7 + +#define CALL_VALUE 0 +#define CLOCK_VALUE 1 +#define MACCTRL_VALUE 2 +#define MACRO_VALUE 3 +#define CTRLRAMP_VALUE 4 +#define DEFRAMP_VALUE 5 +#define SETI_VALUE 6 + +#define commonsize (sizeof(struct event_struct) - sizeof(struct cause_struct)) +#define rampcommon (sizeof(struct ramp_struct) - sizeof(struct deframp_struct)) +#define ctrlsize commonsize +#define callsize (commonsize + sizeof(struct cause_struct)) +#define clocksize (commonsize + sizeof(struct clock_struct)) +#define ctrlrampsize (commonsize + rampcommon + sizeof(struct ctrlramp_struct)) +#define deframpsize (commonsize + sizeof(struct ramp_struct)) +#define macctrlsize (commonsize + sizeof(struct macctrl_struct)) +#define macrosize (commonsize + sizeof(struct macro_struct)) +#define notesize (commonsize + sizeof(struct note_struct)) +#define setisize (commonsize + sizeof(struct seti_struct)) +#define ctrl_voice(c, v) (((c) << 5) + ((v) - 1)) +#define vc_ctrl(v) ((v) >> 5) +#define vc_voice(v) (((v) & 0x1F) + 1) + +#define is_note(n) (((n)->nvoice & 0xE0) == 0) + +#define CHUNK_SIZE 2000 + +typedef struct def_struct { + struct def_struct *next; + char *symbol; + unsigned char *definition; +} def_node, *def_type; + + +typedef struct chunk_struct { + struct chunk_struct *next; + short free; + union { + char data[CHUNK_SIZE]; + struct info_struct { + short refcount; + struct chunk_struct *last_chunk; /* where to allocate memory */ + def_type dictionary; /* macro defns, routine addresses */ + event_type eventlist; /* first event in sequence */ + ulong used_mask; /* tells what channels are actually present */ + long ctrlcount; + long notecount; + time_type duration; /* time of the last event+dur in score */ + } info; + } u; +} chunk_node, *chunk_type; + + +typedef struct seq_struct { + void (*cause_noteoff_fn)(struct seq_struct *, time_type, int, int); + void (*midi_bend_fn)(struct seq_struct * seq, int voice, int value); + void (*midi_ctrl_fn)(struct seq_struct * seq, int voice, int ctrl, int value); + void (*midi_program_fn)(struct seq_struct * seq, int voice, int prog); + void (*midi_touch_fn)(struct seq_struct * seq, int voice, int value); + void (*noteoff_fn)(struct seq_struct * seq, int voice, int pitch); + void (*noteon_fn)(struct seq_struct * seq, int chan, int pitch, int vel); + void (*free_fn)(struct seq_struct * seq); + void (*reset_fn)(struct seq_struct * seq); + void (*stopfunc)(struct seq_struct *); + chunk_type chunklist; + /* event_type eventlist; + seq->eventlist is now seq->eventlist->chunklist */ + event_type current; + boolean runflag; /* normally true, set to false as a flag for + * processes started by score to terminate */ + boolean note_enable; /* normally true, set to false as a flag to + * suppress note output, e.g. when indexing + * to a particular time point */ + boolean cycleflag; /* normally false, set to true to make the + * sequence cycle every cycledur */ + int transpose; + int loudness; + time_type cycledur; + timebase_type timebase; + time_type rate; /* remembers rate across pauses */ + boolean paused; /* remembers if seq has been stopped or not */ + short noteoff_count; /* keeps track of pending events, such as + * note off commands. When this count goes + * to zero, the score is finished */ + ulong channel_mask; +} seq_node, *seq_type; + +extern seq_type sequence; + +chunk_type chunk_create(boolean first_flag); + +#define seq_cause_noteoff(seq, delay, voice, pitch) \ + (*(((seq_type) seq)->cause_noteoff_fn))(seq, delay, voice, pitch) +#define seq_midi_bend(seq, voice, value) \ + (*(((seq_type) seq)->midi_bend_fn))(seq, voice, value) +#define seq_midi_ctrl(seq, voice, ctrl, value) \ + (*(((seq_type) seq)->midi_ctrl_fn))(seq, voice, ctrl, value) +#define seq_midi_program(seq, voice, prog) \ + (*(((seq_type) seq)->midi_program_fn))(seq, voice, prog) +#define seq_midi_touch(seq, voice, value) \ + (*(((seq_type) seq)->midi_touch_fn))(seq, voice, value) +#define seq_noteoff(seq, voice, pitch) \ + (*(((seq_type) seq)->noteoff_fn))(seq, voice, pitch) +#define seq_noteon(seq, voice, pitch, vel) \ + (*(((seq_type) seq)->noteon_fn))(seq, voice, pitch, vel) +#define seq_free(seq) (*(((seq_type) seq)->free_fn))(seq) +#define seq_register(seq) \ + cu_register((cu_fn_type) (((seq_type) seq)->free_fn), seq) +#define seq_reset(seq) (*(((seq_type) seq)->reset_fn))(seq) + /* LISP: void (SEQ-RESET SEQ) */ + +extern boolean seq_print; /* debugging switch */ + +void seq_extensions(void); /* to be defined outside of seq -- user dependent */ +event_type insert_call(seq_type seq, time_type ctime, int cline, + int voice, int (*addr)(), long value[], int n); +event_type insert_clock(seq_type seq, time_type ctime, int cline, + time_type ticksize); +event_type insert_ctrl(seq_type seq, time_type ctime, int cline, int ctrl, + int voice, int value); + /* LISP: (SEQ-INSERT-CTRL SEQ FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM) */ +event_type insert_ctrlramp(seq_type seq, time_type rtime, int rline, int voice, + time_type step, time_type dur, int ctrl, int v1, int v2); + /* LISP: (SEQ-INSERT-RAMP SEQ FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM) */ +def_type insert_def(seq_type seq, char *symbol, unsigned char *definition, + int deflen); +event_type insert_deframp(seq_type seq, time_type rtime, int rline, int voice, + time_type step, time_type dur, def_type def, + int nparms, short parms[], int parm_num, int to_value); +event_type insert_macctrl(seq_type seq, time_type ctime, int cline, int ctrl, + int voice, int value); + /* LISP: (SEQ-INSERT-MACCTRL SEQ FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM) */ +event_type insert_macro(seq_type seq, time_type ctime, int cline, + def_type def, int voice, int nparms, short *parms); +event_type insert_note(seq_type seq, time_type ntime, int nline, int voice, + int pitch, time_type dur, int loud); + /* LISP: (SEQ-INSERT-NOTE SEQ FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM FIXNUM) */ +event_type insert_seti(seq_type seq, time_type stime, int sline, int voice, + int *addr, int value); +void noop(seq_type seq); +seq_type seq_alloc(void); +void seq_at_end(seq_type seq, void (*fn)(seq_type)); +void seq_cause_noteoff_meth(seq_type seq, time_type delay, int voice, int pitch); +#define seq_channel_mask(seq) ((seq)->channel_mask) +seq_type seq_copy(seq_type from_seq); /* LISP: (SEQ-COPY SEQ) */ +seq_type seq_create(void); /* LISP: (SEQ-CREATE) */ +void seq_cycle(seq_type seq, boolean flag, time_type dur); +#define seq_duration(seq) (((seq_type) seq)->chunklist->u.info.duration) +void seq_end_event(seq_type seq); +#define seq_events(seq) (((seq_type) seq)->chunklist ? \ + (((seq_type) seq)->chunklist->u.info.eventlist) : NULL) +#define seq_dictionary(seq) (seq)->chunklist->u.info.dictionary +#define seq_eventlist(seq) (seq)->chunklist->u.info.eventlist +#define seq_ctrlcount(seq) (seq)->chunklist->u.info.ctrlcount +#define seq_notecount(seq) (seq)->chunklist->u.info.notecount +#define seq_used_mask(seq) (seq)->chunklist->u.info.used_mask +void seq_free_chunks(seq_type seq); +seq_type seq_init(seq_type seq, int create_chunk); +#define seq_loudness(seq) (((seq_type) seq)->loudness) +void seq_midi_bend_meth(seq_type seq, int voice, int value); +void seq_midi_ctrl_meth(seq_type seq, int voice, int ctrl, int value); +void seq_midi_program_meth(seq_type seq, int voice, int prog); +void seq_midi_touch_meth(seq_type seq, int voice, int value); +void seq_noteon_meth(seq_type seq, int voice, int pitch, int vel); +void seq_noteoff_meth(seq_type seq, int chan, int pitch); +time_type seq_pause(seq_type seq, boolean flag); +void seq_play(seq_type seq); +#define seq_rate(seq) ((seq_type) seq)->rate +void seq_reset_meth(seq_type seq); +#define seq_runflag(seq) ((seq_type) seq)->runflag +#define seq_set_channel_mask(seq, cm) ((seq)->channel_mask) = (cm) +void seq_set_loudness(seq_type seq, int offset); +void seq_set_rate(seq_type seq, time_type rate); +#define seq_set_timebase(seq, tb) ((seq_type) seq)->timebase = (tb) +void seq_set_transpose(seq_type seq, int trans); +void seq_start_time(seq_type seq, time_type start_time); +void seq_stop(seq_type seq); +#define seq_timebase(seq) ((seq_type) seq)->timebase +#define seq_transpose(seq) ((seq_type) seq)->transpose diff --git a/cmt/seqdecls.h b/cmt/seqdecls.h new file mode 100644 index 0000000..654d12a --- /dev/null +++ b/cmt/seqdecls.h @@ -0,0 +1,11 @@ +/* This .h file declares everything you need to include seq.h */ +/* + * This file gets included by an interface to seq generated by intgen + */ +#include "switches.h" +#include "stdio.h" +#include "cext.h" +#include "userio.h" +#include "midifns.h" +#include "timebase.h" +#include "moxc.h" diff --git a/cmt/seqmread.c b/cmt/seqmread.c new file mode 100644 index 0000000..52f0c57 --- /dev/null +++ b/cmt/seqmread.c @@ -0,0 +1,448 @@ +/* + * seqmread.c + * + * Convert a MIDI file to a seq. + */ + +/* Copyright 1989 Carnegie Mellon University */ + +/***************************************************************************** +* Change Log +* Date | who : Change +*-----------+----------------------------------------------------------------- +* 17-Feb-92 | GWL : only one stdio.h +* : fix to satisfy compiler: + void returns, time_type giotime(), int filegetc() +*****************************************************************************/ + +#include "switches.h" +#include "stdio.h" +#include "cext.h" +#include "cmdline.h" +#include "midifns.h" /* to get time_type */ +#include "timebase.h" +#include "moxc.h" /* to get debug declared */ +#include "seq.h" +#include "seqread.h" /* to get scale */ +#include "seqmread.h" +#include "userio.h" +#include "ctype.h" + +#include "midifile.h" +#include "tempomap.h" + +int filegetc(); +void initfuncs(); +void prtime(); +void snding_free(); + +typedef struct snding_struct { + struct snding_struct *next; + event_type event_ptr; + int pitch; + int channel; +} snding_node, *snding_type; + +#define snding_alloc() (snding_type) memget(sizeof(snding_node)) +#define snding_free(s) memfree(s, sizeof(snding_node)) + +snding_type snding_list = NULL; + +tempomap_type the_tempomap; +event_type initial_clock; /* remember the first clock event */ +long prev_ticksize; /* remember the previous ticksize */ +int sysex_id = 0; + + +void smf_noteoff(); +void smf_error(); +void smf_header(); +void smf_trackstart(); +void smf_trackend(); +void smf_noteon(); +void smf_pressure(); +void smf_parameter(); +void smf_pitchbend(); +void smf_program(); +void smf_chanpressure(); +void smf_sysex(); +void smf_metamisc(); +void smf_metaseq(); +void smf_metaeot(); +void smf_timesig(); +void smf_smpte(); +void smf_tempo(); +void smf_keysig(); +void smf_metaspecial(); +void smf_metatext(); +void smf_arbitrary(); + +private seq_type the_score; + +static FILE *F; + +int filegetc() +{ +/* int temp = getc(F); + printf(" %x ", temp);*/ + return(int)(getc(F)); +} + +void seq_read_smf(seq, fp) + seq_type seq; + FILE *fp; +{ + F = fp; + initfuncs(); + sysex_id = 0; /* sysex in seq has to correspond to a symbol */ + the_score = seq; /* current sequence is a global within this module */ + if (!seq) return; + the_tempomap = tempomap_create(); + /* insert an initial clock to correspond to the default midifile tempo + (tempomap_create creates a corresponding initial entry in the tempomap) + (see smf_tempo for explanation of the scale() call) + */ + initial_clock = insert_clock(the_score, 0L, 0, 500L << 16); + /* scale(24 * 500000, 1 << 16, 24000) */ + if (!the_tempomap) return; + Mf_getc = filegetc; + midifile(); + /* fmac_close(F); -- do not close the file because the caller might try to + * close it (in fact XLISP insists on closing it as a side effect of + * garbage collection. + */ + gprintf(TRANS, "\nLoaded Midi file with %ld note(s), %ld ctrl(s).\n\n", + seq_notecount(seq), seq_ctrlcount(seq)); + seq_reset(seq); + while (snding_list) { + snding_type snding = snding_list; + snding_list = snding_list->next; + gprintf(TRANS, "Note-on (key %d, chan %d) has no matching noteoff\n", + snding->pitch, snding->channel + 1); + snding_free(snding); + } + tempomap_free(the_tempomap); +} + + +/* gio_time -- get the time in millisec for Adagio */ +/* + * Since Adagio times are (in their precise form) 1/256 ms, we want + * a similar time for midifiles, whose natural unit would be microseconds. + * We'll shift the microsecond time by 2 to get 1/250 ms = 4 us units + * and convert using the scale function when necessary. + * Real time is the time of the last tempo change (last_tempo_time) + * which is in 4us units + elapsed time. + * Elapsed time is the elapsed beats times the beat duration. + * Elapsed beats is Mf_currtime - last_tempo_beat. + * Beat duration is the specified tempo / division, where specified tempo + * is in microseconds, and division is parts per quarternote. + */ +unsigned long divisions = 24L; + +time_type gio_time() +{ + return (tempomap_lookup(the_tempomap, Mf_currtime) + 125L) / 250L; +} + + +void smf_header(format,ntrks,division) +{ +/* gprintf(TRANS, "Header format=%d ntrks=%d division=%d\n", + format,ntrks,division); */ + if (format > 1) gprintf(TRANS, + "Warning: format %d midi file may not work.\n", + format); + divisions = division; + /* adjust the initial tempochange */ + the_tempomap->entries->tempo = 500000L / division; +} + + +void smf_trackstart() +{ +/* gprintf(TRANS, "Track start\n"); */ +} + +void smf_trackend() +{ +/* gprintf(TRANS, "Track end\n"); */ +} + +void smf_noteon(chan,pitch,vol) +{ + snding_type snding; + if (vol == 0) { /* convert to a noteoff */ + smf_noteoff(chan, pitch, 0); + return; + } +/* prtime(); + gprintf(TRANS, "Note on, chan=%d pitch=%d vol=%d\n",chan+1,pitch,vol); +*/ + /* get ready to remember the sounding note */ + snding = snding_alloc(); + snding->next = snding_list; + snding_list = snding; + /* enter an event into score and remember it */ + snding->event_ptr = insert_note(the_score, gio_time(), 0, + chan + 1, pitch, 0L, vol); + snding->pitch = pitch; + snding->channel = chan; +} + +void smf_noteoff(chan,pitch,vol) +{ + snding_type *snding_ptr; + register snding_type snding; +/* prtime(); + gprintf(TRANS, "Note off, chan=%d pitch=%d vol=%d\n",chan+1,pitch,vol); +*/ /* search for the snding record */ + for (snding_ptr = &snding_list; + (snding = *snding_ptr) && + ((snding->pitch != pitch) || (snding->channel != chan)); + snding_ptr = &(snding->next)) /* printf("* search *\n") */; + if (!snding) { + gprintf(TRANS, "Note off %d, channel %d ignored: no note on\n", + pitch, chan + 1); + } else { + event_type event = snding->event_ptr; + event->u.note.ndur += (gio_time() - event->ntime) << 8; + /* free the snding record */ + *snding_ptr = snding->next; + snding_free(snding); + } +} + + +void smf_pressure(chan,pitch,press) +{ + prtime(); + gprintf(TRANS, "Pressure, chan=%d pitch=%d press=%d (IGNORED)\n", + chan + 1, pitch, press); +} + +void smf_parameter(chan,control,value) +{ + int ctrl = 0; +/* prtime(); + gprintf(TRANS, "Parameter, chan=%d c1=%d c2=%d\n",chan+1,control,value); + */ /* see if the control is one of the standard Adagio controls that + can be encoded in a special way. If not, ctrl remains at zero. + */ + switch (control) { + case PORTASWITCH: ctrl = PSWITCH_CTRL; break; + case MODWHEEL: ctrl = MODWHEEL_CTRL; break; + case VOLUME: ctrl = VOLUME_CTRL; break; + } + if (ctrl) /* then do special ctrl insert and save storage */ + insert_ctrl(the_score, gio_time(), 0, ctrl, chan + 1, value); + else insert_macctrl(the_score, gio_time(), 0, control, chan + 1, value); +} + + +/* smf_pitchbend -- handle a pitch bend event */ +/* + * NOTE: the midifile code from Tim Thompson has the msb and lsb bytes swapped. + * Thus the parameter msb is really the low order byte and lsb is high order. + */ +void smf_pitchbend(chan,msb,lsb) +{ +/* prtime(); + gprintf(TRANS, "Pitchbend, chan=%d msb=%d lsb=%d\n",chan+1,msb,lsb); */ + insert_ctrl(the_score, gio_time(), 0, BEND_CTRL, chan + 1, + ((lsb << 7) + msb) >> 6); +} + +void smf_program(chan,program) +{ +/* prtime(); + gprintf(TRANS, "Program, chan=%d program=%d\n",chan+1,program); */ + insert_ctrl(the_score, gio_time(), 0, PROGRAM_CTRL, chan + 1, program); +} + +void smf_chanpressure(chan,press) +{ +/* prtime(); + gprintf(TRANS, "Channel pressure, chan=%d pressure=%d\n",chan+1,press); + */ + insert_ctrl(the_score, gio_time(), 0, TOUCH_CTRL, chan + 1, press); +} + +void smf_sysex(leng,mess) +int leng; +char *mess; +{ + char symb[10]; + def_type defn; + int i; + sprintf(symb, "X%d", sysex_id++); + if (leng > 255) { + gprintf(TRANS, "sysex too long (%d bytes), ignored\n", leng - 2); + return; + } + /* need to end up with a prefix of [0][length], so add 2 to length; + note that this will copy past the end of the message -- this is + slightly dangerous and definitely crufty: + */ + defn = insert_def(the_score, symb, (unsigned char *) mess, leng + 2); + /* now fix up the definition by inserting the prefix bytes: */ + for (i = leng + 1; i > 1; i--) + defn->definition[i] = defn->definition[i - 2]; + defn->definition[0] = 0; + defn->definition[1] = leng; + insert_macro(the_score, gio_time(), 0, defn, 1, 0, NULL); +/* prtime(); + gprintf(TRANS, "Sysex, leng=%d (IGNORED)\n",leng); */ +} + +void smf_metamisc(type,leng,mess) +char *mess; +{ + prtime(); + gprintf(TRANS, + "Meta event, unrecognized, type=0x%02x leng=%d (IGNORED)\n", + type, leng); +} + +void smf_metaspecial(type,leng,mess) +char *mess; +{ + prtime(); + gprintf(TRANS, + "Meta event, sequencer-specific, type=0x%02x leng=%d (IGNORED)\n", + type, leng); +} + +void smf_metatext(type,leng,mess) +char *mess; +{ + static char *ttype[] = { + NULL, + "Text Event", /* type=0x01 */ + "Copyright Notice", /* type=0x02 */ + "Sequence/Track Name", + "Instrument Name", /* ... */ + "Lyric", + "Marker", + "Cue Point", /* type=0x07 */ + "Unrecognized" + }; + int unrecognized = (sizeof(ttype)/sizeof(char *)) - 1; + + if ( type < 1 || type > unrecognized ) + type = unrecognized; +} + +void smf_metaseq(num) +{ + prtime(); + gprintf(TRANS, "Meta event, sequence number = %d (IGNORED)\n",num); +} + +void smf_metaeot() +{ +/* prtime(); + gprintf(TRANS, "Meta event, end of track\n"); */ +} + +void smf_keysig(sf,mi) +{ +/* prtime(); + gprintf(TRANS, "Key signature, sharp/flats=%d minor=%d\n",sf,mi); */ +} + +/* smf_tempo -- handle a midifile tempo change */ +/* + * NOTE: if divisions is positive, it gives time units per quarter, and + * tempo is microsec per division. The product is microsec per quarter. + * To convert to ticksize (parameter to insert_clock), we divide by 24*1000 + * to get units of millisec and 24ths of quarter notes. insert_clock + * expects this to have a 16 bit fractional part. + */ +void smf_tempo(tempo) +long tempo; +{ + time_type ctime = gio_time(); + long ticksize = scale(tempo, 1024L, 375L); +/* (tempo / 24000) << 16; microsec/clock converted to ms/quarter, shifted 16*/ + +/* prtime(); + gprintf(TRANS, "Tempo, microseconds-per-MIDI-quarter-note = %ld\n",tempo); +*/ + tempomap_insert(the_tempomap, Mf_currtime, tempo / divisions); + if (ctime == 0) { + /* we already have a clock event at t=0 -> fix it */ + initial_clock->u.clock.ticksize = ticksize; + } else { /* we need a new one */ + /* NOTE: after the first clock, insert clock events 1/2 tick early + to make sure ticksize is set before clock_tick() wakes up and + reads it. + */ + insert_clock(the_score, ctime - (prev_ticksize >> 17), 0, ticksize); + prev_ticksize = ticksize; + } +} + +void smf_timesig(nn,dd,cc,bb) +{ +/* int denom = 1; + while ( dd-- > 0 ) + denom *= 2; + prtime(); + gprintf(TRANS, +"Time signature=%d/%d MIDI-clocks/click=%d 32nd-notes/24-MIDI-clocks=%d\n", + nn,denom,cc,bb); */ +} + +void smf_smpte(hr,mn,se,fr,ff) +{ + prtime(); + gprintf(TRANS, + "SMPTE, hour=%d minute=%d second=%d frame=%d fract-frame=%d (IGNORED)\n", + hr, mn, se, fr, ff); +} + +void smf_arbitrary(leng,mess) +char *mess; +{ + prtime(); + gprintf(TRANS, "Arbitrary bytes, leng=%d (IGNORED)\n",leng); +} + +void smf_error(msg) + char *msg; +{ + gprintf(ERROR, msg); +} + + +void prtime() +{ + gprintf(TRANS, "Time=%ld/%ld ",Mf_currtime, gio_time()); +} + +void initfuncs() +{ + Mf_error = smf_error; + Mf_header = smf_header; + Mf_starttrack = smf_trackstart; + Mf_endtrack = smf_trackend; + Mf_on = smf_noteon; + Mf_off = smf_noteoff; + Mf_pressure = smf_pressure; + Mf_controller = smf_parameter; + Mf_pitchbend = smf_pitchbend; + Mf_program = smf_program; + Mf_chanpressure = smf_chanpressure; + Mf_sysex = smf_sysex; + Mf_metamisc = smf_metamisc; + Mf_seqnum = smf_metaseq; + Mf_eot = smf_metaeot; + Mf_timesig = smf_timesig; + Mf_smpte = smf_smpte; + Mf_tempo = smf_tempo; + Mf_keysig = smf_keysig; + Mf_sqspecific = smf_metaspecial; + Mf_text = smf_metatext; + Mf_arbitrary = smf_arbitrary; +} diff --git a/cmt/seqmread.h b/cmt/seqmread.h new file mode 100644 index 0000000..a03da03 --- /dev/null +++ b/cmt/seqmread.h @@ -0,0 +1,4 @@ +/* seqmread.h -- midi file reader */ + +void seq_read_smf(seq_type seq, FILE *fp); /* LISP: (SEQ-READ-SMF SEQ FILE) */ + diff --git a/cmt/seqmwrite.c b/cmt/seqmwrite.c new file mode 100644 index 0000000..4e0b918 --- /dev/null +++ b/cmt/seqmwrite.c @@ -0,0 +1,658 @@ +/* created by DMH (damonhorowitz): write seq_type as standard midifile */ +/*************************************************************************** +* Change Log +* Date | Change +*-----------+--------------------------------------------------------------- +* 11-Mar-94 | Created Change Log +* 11-Mar-94 | PLu : Added private to function defs. +* 28-Apr-03 | DM : Change #include's for portability +****************************************************************************/ + +#include "switches.h" + +#include + +#include "cext.h" +#include "userio.h" +#include "midicode.h" +#include "mfmidi.h" +#include "midifns.h" +#include "timebase.h" +#include "moxc.h" +#include "seq.h" +#include "seqread.h" /* to get scale() */ +#include "seqmwrite.h" + +long chunk_size_marker; +int seti_counter; +extern time_type a_start_time; + +long last_event; /*time from last_clock_event to the last event*/ +time_type last_clock_event; +time_type last_tick_size; /* millisec per tick shifted 16 bits */ + +struct smf_write_seq { + seq_type seq; + int track; + FILE *outfile; + } smfw_seq; +extern seq_type sequence; /* this is a global to be accessed by + * routines called from the sequence */ +/* clock state: */ +extern time_type clock_ticksize; /* millisec per tick shifted 16 bits */ +extern boolean clock_running; /* TRUE if clock is running */ +extern boolean use_midi_clock; + +private void smfw_bend(); +private void smfw_cause_noteoff(); +private void smfw_ctrl(); +private void smfw_deltatime(); +private void smfw_dotrack(); +private void smfw_exclusive(); +private void smfw_noteoff(); +private void smfw_noteon(); +private void smfw_process_event(); +private void smfw_ramp_event(seq_type seq, event_type event, + unsigned int value, unsigned int to_value, int increment, + time_type step, int n); +private void smfw_send_macro(); +private void smfw_touch(seq_type seq, int voice, int value); +private void writevarlen(); + + +/* smfw_bend -- write a pitch bend to a midi file */ +/**/ +private void smfw_bend(seq_type seq, int voice, int value) +{ + if(debug) gprintf(TRANS, "smfw_bend %d\n", value); + smfw_deltatime(); + putc(MIDI_BEND | (voice - 1), smfw_seq.outfile); + putc(0xFF & ((value & 0x1) << 6) , smfw_seq.outfile); + putc(0xFF & (value >> 1), smfw_seq.outfile); +} + + +/* smfw_cause_noteoff -- schedule a noteoff for midi file */ +/* + * NOTE: this is called by smfw_process_event when it handles a note + * event node in a seq_type's event list. The ordinary moxc scheduler + * is used to "schedule" the noteoff in the future. In reality, the + * output is done as fast as possible (by attempting an infinite rate), + * so no real timing delays occur. The effect is to sort events by their + * specified time. + */ +private void smfw_cause_noteoff(seq, delay, voice, pitch) + seq_type seq; + time_type delay; + int voice; + int pitch; +{ + if(debug) gprintf(TRANS, "cause noteoff at %ld...", virttime + delay); + pitch += seq->transpose; + while (pitch <= 0) pitch += 12; + while (pitch >= 127) pitch -= 12; + seq->noteoff_count++; + causepri((delay_type) delay, 10, seq->noteoff_fn, + seq, voice, pitch); + +} + +private void smfw_clock_event(old_ticksize, new_ticksize) + time_type old_ticksize, new_ticksize; +{ + time_type temp_ticksize = new_ticksize; + new_ticksize = scale(new_ticksize, 375L, 1024L); +/* (new_ticksize >> 16) * 24000 ms/clock becomes us/midiquarter */ + + if(debug) gprintf(TRANS, "smfw_clock: write %ld (time:%ld) ->->->tempo %ld\n", + new_ticksize, virttime, 2500L / (new_ticksize / 24000)); + + /*use old ticksize to write the delta for the clock event*/ + last_tick_size = old_ticksize; + smfw_deltatime(); + last_tick_size = temp_ticksize;/* reset to = new_tick_size */ + putc(0xFF, smfw_seq.outfile); + putc(0x51, smfw_seq.outfile); + putc(0x03, smfw_seq.outfile); + putc((int) ((new_ticksize >> 16) & 0xFF), smfw_seq.outfile); + putc((int) ((new_ticksize >> 8) & 0xFF), smfw_seq.outfile); + putc((int) (new_ticksize & 0xFF), smfw_seq.outfile); + + last_clock_event = virttime; + last_event = 0L; + /*no time expired between last clockevent and last event(they are the same).*/ + /*next clock event will be exactly the next this_event from last_clock_event*/ +} + + +/* smfw_ctrl -- write a control change to a midi file */ +/**/ +private void smfw_ctrl(seq_type seq, int voice, int ctrl_name, int value) +{ + if(debug) gprintf(TRANS, "smfw_ctrl %d: %d\n", ctrl_name, value); + smfw_deltatime(); + putc(MIDI_CTRL | (voice - 1), smfw_seq.outfile); + putc(ctrl_name, smfw_seq.outfile); + putc(value, smfw_seq.outfile); +} + + +/* smfw_deltatime -- write the time difference between now an previous event */ +/**/ +private void smfw_deltatime() +{ + /* if last_ and clock_ are different, use last_ for clock deltatime*/ + time_type use_ticksize = (clock_ticksize != last_tick_size) ? + last_tick_size : clock_ticksize; + time_type this_event = virttime - last_clock_event; + if(debug) gprintf(TRANS, "delta! ticksize: %lu Lastev: %ld ThisevScaled: %lu Thisev: %lu ", + clock_ticksize, last_event, (this_event * ((2500L << 16) / use_ticksize)) / 100, + this_event); + + this_event = ((virttime - last_clock_event) * ((2500L << 16) / use_ticksize)) / 100; + + if(debug) gprintf(TRANS, "--- deltatime: %lu\n", this_event - last_event); + writevarlen((long) (this_event - last_event)); + + last_event = this_event; +} + + +/* smfw_dotrack -- write the remainder of a track */ +private void smfw_dotrack(seq) + seq_type seq; +{ + long end_marker; + timebase_type old_timebase = timebase; + unsigned long chunk_size; + + if (seq->runflag) { + if ((seq->timebase->virt_base == 0) && + (seq->timebase->rate == STOPRATE)) + /*we just set these last time through... do nothing*/; + seq_stop(seq); + } + timebase_use(seq->timebase); + set_rate(seq->timebase, STOPRATE); + set_virttime(seq->timebase, 0L); + seq->current = seq_events(seq); + seq->noteoff_count = 0L; + seq->runflag = TRUE; + seq->paused = TRUE; + last_clock_event = 0L; + last_event = 0L; + if(debug) gprintf(TRANS, "dotrack (reset) %d %ld (%lu) \n", + smfw_seq.track, last_event, virttime); + + if (seq->current) + cause((delay_type)(seq->current->ntime - virttime), smfw_process_event, + seq); + set_virttime(timebase, MAXTIME); + catchup(); + + putc(0x00, smfw_seq.outfile); + putc(0xFF, smfw_seq.outfile);/*end of track chunk*/ + putc(0x2F, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + end_marker = ftell(smfw_seq.outfile); + fseek(smfw_seq.outfile, chunk_size_marker, 0);/*go back to enter chunksize*/ + chunk_size = (end_marker - chunk_size_marker) - 4;/* - 4 for 4 size bytes*/ + if(debug) gprintf(TRANS, "bytes written in previous track: %ld \n\n", chunk_size); + putc((int) ((0xFF & (chunk_size >> 24))), smfw_seq.outfile); + putc((int) ((0xFF & (chunk_size >> 16))), smfw_seq.outfile); + putc((int) ((0xFF & (chunk_size >> 8))), smfw_seq.outfile); + putc((int) ((0xFF & chunk_size)), smfw_seq.outfile); + fseek(smfw_seq.outfile, end_marker, 0);/*return file pointer to end of track*/ + timebase_use(old_timebase); +} + + +/* smfw_exclusive -- write a system excl. msg to midi file */ +private void smfw_exclusive(length, msg) +int length; +unsigned char *msg; +{ + int length_count = 0; + + if(debug) gprintf(TRANS, "SYSEX (time:%ld)\n", virttime); + + smfw_deltatime(); + + while (length > length_count){ /* *(msg-1) != MIDI_EOX) { */ + putc(*msg++, smfw_seq.outfile); + length_count++; + } + if(*(--msg) != MIDI_EOX) gprintf(TRANS, "ERROR: no end of sysex\n"); +} + +private void smfw_msg_write(n,c1,c2,c3) + int n; + unsigned char c1,c2,c3; +{ + if(debug) gprintf(TRANS, "MSGWRITE %d bytes (time:%ld)\n", n, virttime); + smfw_deltatime(); + switch(n) { + case 1: putc(c1, smfw_seq.outfile); + break; + case 2: putc(c1, smfw_seq.outfile); + putc(c2, smfw_seq.outfile); + break; + case 3: putc(c1, smfw_seq.outfile); + putc(c2, smfw_seq.outfile); + putc(c3, smfw_seq.outfile); + break; + } +} + + +/* smfw_noteoff -- write noteoff to midi file */ +/**/ +private void smfw_noteoff(seq_type seq, int voice, int pitch) +{ + if(debug) gprintf(TRANS, "smfw_noteoff %d: %d (time:%ld)\n", voice, pitch, virttime); + smfw_deltatime(); + putc(NOTEOFF | (voice - 1), smfw_seq.outfile); + putc(pitch, smfw_seq.outfile); + putc(0x40, smfw_seq.outfile); +} + + +/* smfw_noteon -- write noteon to midi file */ +/* + * NOTE: the seq parameter is not used here, but is passed in by the + * seq_noteon macro, so we have to have a placeholder for it. + */ +private void smfw_noteon(seq, voice, pitch, vel) + seq_type seq; + int voice, pitch, vel; +{ + if(debug) gprintf(TRANS, "smfw_noteon %d: %d %d(time:%ld)\n", voice, pitch, vel, virttime); + smfw_deltatime(); + putc(NOTEON | (voice - 1), smfw_seq.outfile); + putc(pitch, smfw_seq.outfile); + putc(vel, smfw_seq.outfile); +} + + +/* smfw_process_event -- write a seq event to a midi file */ +/**/ +private void smfw_process_event(seq) + seq_type seq; +{ + register event_type event; + if (!seq->runflag) return; + while ((event = seq->current) && (event->ntime <= virttime)) { + unsigned int voice; + if ((vc_voice(event->nvoice) == smfw_seq.track) || /*if on current track*/ + (((vc_voice(event->nvoice) - 16) == smfw_seq.track) + && (smfw_seq.track > 0)) || + /* acknowledge clock change on all tracks*/ + (event->value == CLOCK_VALUE && vc_ctrl(event->nvoice) == ESC_CTRL)) { + + /* process all current (and earlier) events */ + if (is_note(event)) { /*** play a note or rest ***/ + /* if this note is not a rest, play it and schedule an off event */ + if (event->value != NO_PITCH && + (seq_channel_mask(seq) & + (1 << ((voice = vc_voice(event->nvoice)) - 1)))) { + seq_noteon(seq, voice, (0xFF & event->value), + (int) (event->u.note.ndur & 0xFF)); + + seq_cause_noteoff(seq, (event->u.note.ndur) >> 8, + voice, (0xFF & event->value)); + } + } else { /*** send a control command ***/ + int n; + time_type step; + int delta; + int increment; + int voice = vc_voice(event->nvoice); + ulong enabled = seq_channel_mask(seq) & (1 << (voice - 1)); + + switch (vc_ctrl(event->nvoice)) { + case PSWITCH_CTRL: + if (!enabled) break; + if(debug) gprintf(TRANS, "porta %d (time:%ld)... ", event->value, virttime); + seq_midi_ctrl(seq, voice, PORTASWITCH, 0xFF & event->value); + break; + case MODWHEEL_CTRL: + if (!enabled) break; + if(debug) gprintf(TRANS, "modw %d (time:%ld)...", event->value, virttime); + seq_midi_ctrl(seq, voice, MODWHEEL, 0xFF & event->value); + break; + case TOUCH_CTRL: + if (!enabled) break; + if(debug) gprintf(TRANS, "touch %d (time:%ld)... ", event->value, virttime); + seq_midi_touch(seq, voice, 0xFF & event->value); + break; + case VOLUME_CTRL: + if (!enabled) break; + if(debug) gprintf(TRANS, "ftvol %d (time:%ld)...", event->value, virttime); + seq_midi_ctrl(seq, voice, VOLUME, 0xFF & event->value); + break; + case BEND_CTRL: + if (!enabled) break; + if(debug) gprintf(TRANS, "bend %d (time:%ld)... ", event->value, virttime); + seq_midi_bend(seq, voice, event->value); + break; + case PROGRAM_CTRL: + if (!enabled) break; + if(debug) gprintf(TRANS, "prog %d (time:%ld)\n", event->value, virttime); + smfw_deltatime(); + putc(MIDI_CH_PROGRAM | (voice - 1), smfw_seq.outfile); + putc(0xFF & event->value, smfw_seq.outfile); + break; + case ESC_CTRL: + switch (event->value) { + time_type this_event; + case CALL_VALUE: /*called routine will write to midifile in execution */ + sequence = seq; + (*(event->u.call.routine))(event->u.call.args); + break; + case CLOCK_VALUE: + clock_ticksize = event->u.clock.ticksize; + if(debug) gprintf(TRANS, "clockevent! ticksize: %lu (time:%ld)\n", + clock_ticksize, virttime); + + if (virttime > 0) { /* any clock before this is already recorded in the header */ + if (smfw_seq.track == 0) { /* record clock event on tempo track = 0 */ + /* cause clock write in half a newtick, because it was written .5 tick early*/ + cause((delay_type) (clock_ticksize >> 17), smfw_clock_event, + last_tick_size, clock_ticksize); + last_tick_size = clock_ticksize; /*set new ticksize*/ + } else { /*not on tempo track*/ + this_event = ((virttime - last_clock_event) * + ((2500L << 16) / last_tick_size)) / 100; + if(debug) gprintf(TRANS, "track != 0: Lastev: %ld Thisev: %ld NewLast: %ld\n", + last_event, this_event, this_event - last_event); + last_event = 0L - (this_event - last_event); + last_clock_event = virttime; + /*last_event is negative, so will be ADDED to next this_event*/ + + last_tick_size = clock_ticksize; + } + } else if (debug) gprintf(TRANS, "IGNORED\n");/* if virttime <= 0 */ + break; + case MACCTRL_VALUE: + if (!enabled) break; + if (debug) gprintf(TRANS, "MACCTRL %d: %d (time:%ld)\n", + event->u.macctrl.ctrl_number, event->u.macctrl.value, virttime); + smfw_deltatime(); + putc(MIDI_CTRL | (voice - 1), smfw_seq.outfile); + putc(0xFF & event->u.macctrl.ctrl_number, smfw_seq.outfile); + putc(0xFF & event->u.macctrl.value, smfw_seq.outfile); + break; + case MACRO_VALUE: + if (!enabled) break; + if (debug) gprintf(TRANS, "MACRO sent to...\n"); + smfw_send_macro(event->u.macro.definition, + voice, event->u.macro.parameter, -1, 0); + break; + case CTRLRAMP_VALUE: + case DEFRAMP_VALUE: { + int from, to; + if (!enabled) break; + step = event->u.ramp.step; + if (event->value == CTRLRAMP_VALUE) { + if(debug) gprintf(TRANS, "CTRLRAMP (time:%ld)...", virttime); + from = event->u.ramp.u.ctrl.from_value; + to = event->u.ramp.u.ctrl.to_value; + } else { + if (debug) gprintf(TRANS, "DEFRAMP (time:%ld)...", virttime); + from = event->u.ramp.u.def.parameter[ + event->u.ramp.u.def.parm_num]; + to = event->u.ramp.u.def.to_value; + } + delta = to - from; + increment = delta; + if (delta < 0) delta = -delta; + /* RBD - Note: Step is always non-zero */ + n = event->u.ramp.dur / step; + increment = (increment << 8) / n; + smfw_ramp_event(seq, event, from << 8, to << 8, + increment, step, n); + seq->noteoff_count++; + break; + } + case SETI_VALUE: + seti_counter++; /*will be printed after writing is completed*/ + *(event->u.seti.int_to_set) = event->u.seti.value; + break; + default: + gprintf(TRANS, "unexpected ESC_CTRL value\n"); + break; + } + break; + default: + gprintf(TRANS, "unexpected seq data\n"); + break; + } + } + } + seq->current = event->next; + } + if (seq->current) { /* if there is an event: delay, and then process again */ + cause((delay_type)(event->ntime - virttime), smfw_process_event, seq); + } +} + +/* smfw_ramp_event -- generate a ramp to write*/ +private void smfw_ramp_event(seq, event, value, to_value, increment, step, n) + seq_type seq; + register event_type event; + unsigned int value; + unsigned int to_value; + int increment; + time_type step; + int n; +{ + if(debug) gprintf(TRANS, "ramp of %d: %d to %d\n", event->u.ramp.ctrl, value >> 8, + to_value >> 8); + if (seq->runflag) { + int voice = vc_voice(event->nvoice); + if (n == 0) value = to_value; + else cause((delay_type)step, smfw_ramp_event, seq, event, value + increment, + to_value, increment, step, n - 1); + if (event->value == CTRLRAMP_VALUE) { + int ctrl = event->u.ramp.ctrl; + if (ctrl == -TOUCH_CTRL) smfw_touch(seq, voice, value >> 8); + else if (ctrl == -BEND_CTRL) smfw_bend(seq, voice, value >> 8); + else smfw_ctrl(seq, voice, ctrl, value >> 8); + } else { /* must be DEFRAMP_VALUE */ + smfw_send_macro(event->u.ramp.u.def.definition, + vc_voice(event->nvoice), + event->u.ramp.u.def.parameter, + event->u.ramp.u.def.parm_num, value >> 8); + } + if (n == 0) seq_end_event(seq); + } +} + + +/* smfw_send_macro -- write msg to midi file from a seq "macro" event */ +/**/ +private void smfw_send_macro(ptr, voice, parameter, parm_num, value) + register unsigned char *ptr; + int voice; + short parameter[]; + int parm_num; + int value; +{ + register unsigned char code, *loc; + while ((code = *ptr++)) { + loc = ptr + *ptr; + ptr++; + if (code <= nmacroparms) { + code--; + *loc = (code == parm_num ? value : parameter[code]) & 0x7f; + } + else if (code == nmacroparms + 1) { + *loc = ((voice - 1) & 0xF) | *loc; + } + else { + code -= (nmacroparms + 2); + *loc = ((code == parm_num ? value : parameter[code]) >> 7) & 0x7F; + } + } + if (ptr[1] == MIDI_SYSEX) + smfw_exclusive(*ptr, ptr + 1); + else + smfw_msg_write(*ptr, ptr[1], ptr[2], ptr[3]); +} + + +/* smfw_touch -- write aftertouch msg to midi file */ +/**/ +private void smfw_touch(seq_type seq, int voice, int value) +{ + if(debug) gprintf(TRANS, "smfw_touch %d\n", value); + smfw_deltatime(); + putc(MIDI_TOUCH | (voice - 1), smfw_seq.outfile); + putc(value, smfw_seq.outfile); +} + + +void seq_write_smf(seq, outfile) + seq_type seq; + FILE *outfile; +{ + time_type put_tick_size; + int i; + /* ticksize is milliseconds << 16, and tickrate = 24*tempo + 60000ms/min / (24 * tempo) = 2500/tempo = 25 + 25 << 16 = 1638400 */ + time_type starting_ticksize = 1638400L; /*default midifile tempo 100*/ + int track_count = 0; + long track_count_marker; + register event_type event; + + seti_counter = 0; + + /*initialize the smfw_seq struct*/ + smfw_seq.outfile = outfile; + smfw_seq.seq = seq_copy(seq); + + smfw_seq.seq->cause_noteoff_fn = smfw_cause_noteoff; + smfw_seq.seq->midi_bend_fn = smfw_bend; + smfw_seq.seq->midi_ctrl_fn = smfw_ctrl; + smfw_seq.seq->midi_touch_fn = smfw_touch; + smfw_seq.seq->noteoff_fn = smfw_noteoff; + smfw_seq.seq->noteon_fn = smfw_noteon; + + event = seq_events(smfw_seq.seq); + + /* search for clock events up till start of score */ + /* careful: there may be no events at all */ + while(event && event->ntime <= 0){ + if(debug) gprintf(TRANS, "event (time:%ld)\n", event->ntime); + if(vc_ctrl(event->nvoice) == ESC_CTRL && event->value == CLOCK_VALUE) { + if(debug) gprintf(TRANS, "clock %lu at 0\n", event->u.clock.ticksize); + starting_ticksize = event->u.clock.ticksize; + break; + } + event = event->next; + } + + putc(0x4D, smfw_seq.outfile); /*header: MThd*/ + putc(0x54, smfw_seq.outfile); + putc(0x68, smfw_seq.outfile); + putc(0x64, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + putc(0x06, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + putc(0x01, smfw_seq.outfile); /*format 1 */ + putc(0x00, smfw_seq.outfile); + + track_count_marker = ftell(smfw_seq.outfile); /*number of tracks will be written later*/ + putc(0x00, smfw_seq.outfile); /*will be filled by track_count_marker*/ + + putc(0x02, smfw_seq.outfile);/*division resolution of 600*/ + putc(0x58, smfw_seq.outfile); + + for (i = 0; i < 17; i++) { /* for each track... */ + if (((seq_used_mask(smfw_seq.seq) >> (i - 1)) & 0x1) || (i == 0)) { + if (debug) gprintf(TRANS, "write track %d \n", i); + track_count++; + clock_ticksize = starting_ticksize; + last_tick_size = starting_ticksize; + putc(0x4D, smfw_seq.outfile);/*track header: MTrk*/ + putc(0x54, smfw_seq.outfile); + putc(0x72, smfw_seq.outfile); + putc(0x6B, smfw_seq.outfile); + + chunk_size_marker = ftell(smfw_seq.outfile); + /* size of chunk will be written later */ + /* will be filled by chunk_size_marker */ + putc(0x00, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + + if (i == 0) { /* tempo and time signature track */ + putc(0x00, smfw_seq.outfile);/* default time sig stuff*/ + putc(0xFF, smfw_seq.outfile); + putc(0x58, smfw_seq.outfile); + putc(0x04, smfw_seq.outfile); + putc(0x04, smfw_seq.outfile); + putc(0x02, smfw_seq.outfile); + putc(0x18, smfw_seq.outfile); + putc(0x08, smfw_seq.outfile); + putc(0x00, smfw_seq.outfile); + + /* TEMPO: inserted here in case default is used */ + putc(0xFF, smfw_seq.outfile); + putc(0x51, smfw_seq.outfile); + putc(0x03, smfw_seq.outfile); + /* ticksize is in ms<<16, so to get milliseconds per tick, it's + ticksize / 65536. To get beat durations, multiply by 24 + to get ticksize * 24 / 65536. To get microseconds, + multiply by 1000: ticksize * 24000 / 65536. Divide both + constants by 64 to get ticksize * 375 / 1024 = + microseconds per quarter note. + */ + put_tick_size = scale(clock_ticksize, 375L, 1024L); + putc((int) ((put_tick_size >> 16) & 0xFF), smfw_seq.outfile); + putc((int) ((put_tick_size >> 8) & 0xFF), smfw_seq.outfile); + putc((int) (put_tick_size & 0xFF), smfw_seq.outfile); + } + smfw_seq.track = i; + smfw_dotrack(smfw_seq.seq); + } + } + if (seti_counter) + gprintf(TRANS, "%d SETI events IGNORED!\n", seti_counter); + seq_stop(smfw_seq.seq); + /* go back and insert number of tracks */ + fseek(smfw_seq.outfile, track_count_marker, 0); + putc(0xFF & track_count, smfw_seq.outfile); + fclose(smfw_seq.outfile); +} + + +/* writevarlen -- write a variable length integer to midi file */ +/**/ +private void writevarlen(value) + register long value; +{ + register ulong buffer; + + if(debug) gprintf(TRANS, "variable length quantity..."); + + buffer = value & 0x7f; + + while((value >>= 7) > 0) { + buffer <<= 8; + buffer |= 0x80; + buffer += (value & 0x7f); + } + + for(;;) { + if(debug) gprintf(TRANS, " byte "); + putc((int) (buffer & 0xFF), smfw_seq.outfile); + if (buffer & 0x80) buffer >>= 8; + else break; + } + if(debug) gprintf(TRANS, "written!\n"); +} diff --git a/cmt/seqmwrite.h b/cmt/seqmwrite.h new file mode 100644 index 0000000..458336f --- /dev/null +++ b/cmt/seqmwrite.h @@ -0,0 +1,4 @@ +/* seqmwrite.h -- midi file writer */ + +void seq_write_smf(seq_type seq, FILE *outfile); /* LISP: (SEQ-WRITE-SMF SEQ FILE) */ + diff --git a/cmt/seqread.c b/cmt/seqread.c new file mode 100644 index 0000000..62d759d --- /dev/null +++ b/cmt/seqread.c @@ -0,0 +1,1890 @@ +/**************************************************************************** + seqread.c -- Phase 1 of adagio compilation... + + this module parses adagio programs and builds a linked list structure + consisting of notes and control changes in time order. + + Copyright 1989 Carnegie Mellon University +*****************************************************************************/ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 31-Dec-85 | Created changelog +* 31-Dec-85 | Add c:\ to include directives +* 31-Dec-85 | Added standard command scanner, metronome variable, need to add +* | cmdline_help procedure +* 31-Dec-85 | Call intr_init +* 31-Dec-85 | Set musictrace from command line via -trace +* 31-Dec-85 | Added -poll +* 1-Jan-86 | Put error messages out to stderr +* 1-Jan-86 | Set IsAT. Can be later overridden by -at and -xt switches, +* | currently only used for diagnostics (may be needed for +* | compatibles, who knows? In which case remove the tests which +* | confirm the type of processor) +* 1-Jan-86 | Removed dur-adjusted message +* 1-Jan-86 | Added miditrace +* 18-Jan-86 | Shortened durations by 1/200 s to avoid roundoff problems -- +* | see buildnote for details. +* 3-Mar-86 | Allow octave and accidentals in either order after pitch name. +* | Default octave is now one that gets nearest previous pitch, +* | the tritone (half an octave) interval is descending by default. +* | Special commands handled by table search, !Rate command added +* | to scale all times by a percentage (50 = half speed). +* 9-Mar-86 | Use space to limit amount of storage allocation. Otherwise +* | exhausting storage in phase1 caused phase2 to fail. +* 12-Mar-86 | Broke off command line parser into adagio.c, only parser remains +* 24-Mar-86 | Changed representation from note_struct to event_struct +* | Parse M, N, O, X, and Y as control change commands +* 23-May-86 | Added , and ; syntax: "," means "N0\n", ";" means "\n" +* 16-Jul-86 | modify to only call toupper/lower with upper/lower case as +* | parameter to be compatible with standard C functions +* 7-Aug-86 | fixed bug with default pitches and rests +* 5-Jul-87 | F.H: Introduced new memory handling from Mac version. +* | Changed: init() +* | ins_event() +* | ins_ctrl() +* | ins_note() +* | Deleted: reverse() +* | nalloc() +* | Introduced: event_alloc() +* | phase1_FreeMem() +* | system.h & system.c dependencies +* 10-Feb-88 | fixed parseend to accept blanks and tabs, +* | fixed rate scaling of durations +* 11-Jun-88 | commented out gprintf of \n to ERROR after parsing finished. +* 13-Oct-88 | JCD : exclusive AMIGA version. +* 13-Apr-89 | JCD : New portable version. +* 31-Jan-90 | GWL : Cleaned up for LATTICE +* 30-Jun-90 | RBD : further changes +* 2-Apr-91 | JDW : further changes +* 30-Jun-91 | RBD : parse '+' and '/' in durations, * after space is comment +* 28-Apr-03 | DM : changes for portability +*****************************************************************************/ + +#include "switches.h" + +#include +#include + +#include "cext.h" +#include "cmdline.h" +#include "midifns.h" /* to get time_type */ +#include "timebase.h" +#include "moxc.h" /* to get debug declared */ +#include "seq.h" +#include "seqread.h" +#include "userio.h" +/* ctype.h used to be included only by UNIX and AMIGA, + surely everyone wants this? */ +#include "ctype.h" + +#ifndef toupper +/* we're already taking precautions, so inline version of toupper is ok: */ +#define toupper(c) ((c)-'a'+'A') +/* CAUTION: AZTEC V5.0 defines an inline version of toupper called _toupper, + but they got it wrong! + */ +#endif + +/* cmtcmd.h references amiga message ports */ +#ifdef AMIGA +#ifdef LATTICE +#include "amiga.h" +#endif +#include "exec/exec.h" +#endif +#include "cmtcmd.h" + +/* public stuff */ +extern long space; /* remaining free bytes */ +extern int abort_flag; + +/**************************************************************************** + The following are used to simulate fixed point with the radix point + 8 bits from the right: +****************************************************************************/ + +#define precise(x) (((time_type) x) << 8) +#define seqround(x) ((((time_type) x) + 128) >> 8) +#define trunc(x) (((time_type) x) >> 8) + +#define nullstring(s) (s[0] == EOS) + + +/**************************************************************************** +* Routines local to this module: +****************************************************************************/ +private void do_a_rest(); +private time_type doabsdur(); +private int doabspitch(); +private void doclock(); +private void docomment(); +private void doctrl(); +private void dodef(); +private time_type dodur(); +private void doerror(); +private int doloud(); +void domacro(); +private void donextdur(); +private int dopitch(); +private void doprogram(); +private void dorate(); +private void doset(); +private void dospecial(); +private time_type dosymdur(); +private void dotempo(); +private void dotime(); +private void dovoice(); +private void fferror(); +private void init(); +private int issymbol(); +private void marker(); +private void parseend(); +private void parsefield(); +private boolean parsenote(); +private boolean parseparm(); +private int scan(); +private int scan1(); +private long scanint(); +private void scansymb(); +private long scansgnint(); + +/**************************************************************************** +* data structures for parser lookup tables +****************************************************************************/ + +struct durt { /* duration translation table */ + char symbol; + time_type value; +}; + +#define durtable_len 7 +struct durt durtable[durtable_len] = { + {'W', 4800L}, + {'H', 2400L}, + {'Q', 1200L}, + {'I', 600L}, + {'S', 300L}, + {'%', 150L}, + {'^', 75L} +}; + +struct loudt { /* loudness translation table */ + char symbol[4]; + int value; +}; + +struct loudt loudtable[] = { + {"PPP", 20}, + {"PP\0", 26}, + {"P\0\0", 34}, + {"MP\0", 44}, + {"MF\0", 58}, + {"F\0\0", 75}, + {"FF\0", 98}, + {"FFF", 127} +}; + +char too_many_error[] = "Too many parameters"; + +private char *ssymbols[] = {"TEMPO", "RATE", "CSEC", "MSEC", + "SETI", "SETV", "CALL", "RAMP", + "CLOCK", "DEF", "END"}; + +#define sym_tempo 0 +#define sym_rate 1 +#define sym_csec 2 +#define sym_msec 3 +#define sym_seti 4 +#define sym_setv 5 +#define sym_call 6 +#define sym_ramp 7 +#define sym_clock 8 +#define sym_def 9 +#define sym_end 10 + +/* number of symbols */ +#define sym_n 11 + +#define linesize 100 +private char line[linesize]; /* the input line */ +private char token[linesize]; /* a token scanned from the input line */ + +private boolean pitch_flag; /* set when a pitch is indicated */ +/* (if controls changes are given, only allocate a note event if + * a pitch was specified -- i.e. when pitch_flag is set) + */ +private boolean rest_flag; /* set when a rest (R) is found */ +/* this flag is NOT inherited by the next line */ + +private boolean symbolic_dur_flag; +/* TRUE if last dur was not absolute + * (if this is set, then the default duration is changed + * accordingly when the tempo is changed.) + */ + + +#define nctrl 8 + +private boolean ctrlflag[nctrl]; +/* TRUE if control change was present + * ctrlflag[0] TRUE if ANY control change + * was present + */ +private int ctrlval[nctrl]; +/* the new value of the control */ +#define nmacroctrl 10 +short macctrlx; /* index into the following: */ +short macctrlnum[nmacroctrl]; /* macro ctrl number, e.g. for ~4(67), or + * number of parameters for a symbolic macro */ +short macctrlparmx[nmacroctrl]; /* ctrl value for ctrl change, or index of + * parameters for symbolic macro */ +short macctrlparms[nmacroctrl*nmacroparms]; /* parameters for symbolic macros */ +short macctrlnextparm; +def_type macctrldef[nmacroctrl]; /* definition for symbolic macro */ + +private time_type time_scale; /* 1000 if centisec, 100 if millisec */ +/* note: user_specified_time * (time_scale / rate) = millisec */ + + + +/**************************************************************************** +* +* variables private to this module +* +****************************************************************************/ + +private boolean end_flag = FALSE; /* set "true" when "!END" is seen */ + +/**************************************************************************** +* state variables +* Because each line of an Adagio score inherits properties from the previous +* line, it makes sense to implement the parser as a collection of routines +* that make small changes to some global state. For example, pitch is a +* global variable. When the field G4 is encountered, the dopitch routine +* assigns the pitch number for G4 to the variable pitch. After all fields +* are processed, these variables describe the current note and contain the +* default parameters for the next note as well. +* +* Global variables that are used in this way by the parsing rountines are: +****************************************************************************/ +private int +linex, /* index of the next character to be scanned */ +lineno, /* current line number */ +fieldx, /* index of the current character within a field */ +pitch, /* pitch of note */ +loud, /* loudness of note */ +voice, /* voice (midi channel) of note */ +artic; /* articulation (a percentage of duration) */ + +private boolean ndurp; /* set when a next (N) is indicated */ +/* (next time defaults to the current time plus duration unless + * overridden by a next (N) command whose presence is signalled + * by ndurp.) + */ + +private time_type +thetime, /* the starting time of the note */ +rate, /* time rate -- scales time and duration, default = 100 */ +ntime, /* the starting time of the next note */ +dur, /* the duration of the note */ +tempo, /* the current tempo */ +start, /* the reference time (time of last !tempo or !rate cmd) */ +ticksize; /* set by !clock command, zero for no clock */ + +private int pitchtable[7] = { + 69, 71, 60, 62, 64, 65, 67 }; + +extern char score_na[name_length]; + +private seq_type the_score; /* this is the score we are parsing */ + + +/* def_append -- append a byte to the current definition */ +/* + * The def data structure: + * [code][offset][code][offset]...[0][length][data][data][data]... + * where code is 1:nmacroparms for %n, + * nmacroparms+1 for %v, + * nmacroparms+2:nmacroparms*2+1 for ^n + * and offset is the byte offset (from the offset byte) to the data + * where the parameter should be substituted + * and length is the number of data bytes + */ +boolean def_append(def, nparms, data) + unsigned char def[]; + int nparms; + int data; +{ + int base = (nparms << 1) + 1; /* this byte is the length */ + /* first parameter has to be able to reference last byte: */ + if ((def[base])++ >= (254 - (nparms << 1))) { + fferror("Data too long"); + return FALSE; + } + def[base + def[base]] = data; + return TRUE; +} + + +def_type def_lookup(symbol) + char *symbol; +{ + def_type defn = seq_dictionary(the_score); + while (defn) { + if (strcmp(defn->symbol, symbol) == 0) { + return defn; + } + defn = defn->next; + } + return NULL; +} + + +void def_parm(def, nparms, code) + unsigned char def[]; + int nparms; + int code; +{ + int i, j; + /* in order to insert a 2-byte parameter descriptor, the offsets from + * previous descriptors (that precede the data) need to be increased by 2: + */ + for (i = 1; i < (nparms << 1); i += 2) { + def[i] += 2; + } + /* now i is index of length; work backwards from the last byte, moving + * everything up by 2 bytes to make room for the new descriptor: + */ + for (j = i + def[i] + 2; j > i; j--) { + def[j] = def[j - 2]; + } + /* now i is index of offset; insert the descriptor code (first byte) + * and the offset to the parameter location in the message (second byte) + */ + def[i - 1] = code; + def[i] = def[i + 2] + 2; +} + +/**************************************************************************** +* do_a_rest +* Effect: parses a rest (R) command +****************************************************************************/ + +private void do_a_rest() +{ + if (token[fieldx]) + fferror("Nothing expected after rest"); + rest_flag = TRUE; +} + +/**************************************************************************** +* doabsdur +* Effect: parses an absolute dur (U) command +****************************************************************************/ + +private time_type doabsdur() +{ + time_type result=1000L; + register char c; + if (isdigit(token[fieldx])) { + result = precise(scanint()); + /* allow comma or paren for use in parameter lists */ + if ((c = token[fieldx]) && (c != ',') && (c != ')') && (c != '+')) { + fferror("U must be followed by digits only"); + } + if (time_scale == 1000) result *= 10; /* convert to ms */ + } else fferror("No digit after U"); + return result; +} + +/**************************************************************************** +* doabspitch +* Effect: parses an absolute pitch (P) command +****************************************************************************/ + +private int doabspitch() +{ + int result = 60; + int startx = fieldx; + register char c; + int savex; + if (isdigit (token[fieldx])) { + result = (int) scanint(); + /* allow comma or paren for abspitch in parameter */ + if ((c = token[fieldx]) && c != ',' && c != ')') + fferror("P must be followed by digits only"); + else if (result < minpitch) { + savex = fieldx; + fieldx = startx; + fferror("Minimum pitch of 0 will be used"); + result = minpitch; + fieldx = savex; + } else if (result > maxpitch) { + savex = fieldx; + fieldx = startx; + fferror("Maximum pitch of 127 will be used"); + result = maxpitch; + fieldx = savex; + } + } else fferror("No digits after P"); + return result; +} + + +/* doartic -- compute an articulation factor */ +/* + NOTE: artic is a percentage that scales the duration + of notes but not the time to the next note onset. It + is applied to the final computed duration after all + other scaling is applied. + */ +private void doartic() +{ + if (isdigit(token[fieldx])) { + artic = (int) scanint(); + if (token[fieldx]) + fferror("Only digits were expected here"); + } else fferror("No digits after /"); +} + + +/* docall -- parse a call in the form !CALL fn(p1,p2,p3) */ +/**/ +private void docall() +{ + boolean error_flag = TRUE; + ndurp = FALSE; + + linex += scan(); + + if (token[0] == 0) fferror("Function name expected"); + else { + char symbol[100]; + struct symb_descr *desc; + long value[SEQ_MAX_PARMS]; + int i=0; + + scansymb(symbol); + if (fieldx == 1) fferror("Routine name expected"); + else if (token[fieldx] != '(') fferror("Open paren expected"); + else { + desc = &HASHENTRY(lookup(symbol)); + if (!desc->symb_type) { + fieldx = 0; + fferror("Function not defined"); + } else if (desc->symb_type != fn_symb_type) { + fieldx = 0; + gprintf(TRANS, "desc->symb_type is %d\n", desc->symb_type); + fferror("This is not a function"); + } else { + error_flag = FALSE; + fieldx++; /* skip over paren */ + for (i = 0; i < SEQ_MAX_PARMS; i++) value[i] = 0; + i = 0; + /* note that no params "()" is legal */ + while (i < SEQ_MAX_PARMS && token[fieldx] != ')' && + parseparm(&value[i])) { + i++; + if (token[fieldx] == ',') { + fieldx++; + } else if (token[fieldx] != ')') { + fferror("Unexpected character"); + error_flag = TRUE; + break; + } + } + fieldx++; + if (i > SEQ_MAX_PARMS) fferror("Too many parameters"); + } + while (TRUE) { + linex += scan(); + if (nullstring(token)) { + break; + } + switch (token[0]) { + case 'T': + fieldx = 1; + dotime(); + break; + case 'V': + fieldx = 1; + dovoice(); + break; + case 'N': + fieldx = 1; + donextdur(); + break; + default: + fferror("Unexpected character"); + } + } + if (!error_flag) + insert_call(the_score, seqround(thetime), lineno, voice, + desc->ptr.routine, value, i); + /* advance the time only if an N field was given */ + if (ndurp) thetime += ntime; + } + } +} + + +/* doclock -- insert a clock command */ +/* + * derivation: if there is no previous clock running, then start the + * clock on time. Otherwise, start the clock half a tick early. + * ticksize = (beattime / 24) = ((60sec/tempo)/24) = + * ((60000ms/tempo)/24) = (60000/24)/tempo = 2500/tempo + */ +private void doclock() +{ + int oldticksize = ticksize; + ticksize = (2500L << 16) / tempo; + insert_clock(the_score, seqround(thetime) - (oldticksize >> 17), + lineno, ticksize); +} + + +/**************************************************************************** +* docomment +* Effect: parses a comment (*) command +****************************************************************************/ + +private void docomment() +{ + line[linex] = '\n'; /* force end of line to skip comment line */ + line[linex+1] = EOS; +} + +/**************************************************************************** +* doctrl +* Inputs: +* n: control number +* Effect: parses a control (K, M, O, X, or Y) command +****************************************************************************/ + +private void doctrl(n) +int n; +{ + ctrlval[n] = (int) scanint(); + if (token[fieldx]) { + fferror("Only digits expected here"); + } else { + ctrlflag[n] = TRUE; + ctrlflag[0] = TRUE; /* ctrlflag[0] set if any flag is set */ + } +} + + +private void dodef() +{ + /* maximum def size is 256 + 9 parms * 2 + 2 = 276 */ + unsigned char def[280]; + char symbol[100]; + int nparms = 0; + int nibcount = 0; + int data = 0; + register char c; + + linex += scan(); + + if (!token[0]) fferror("Symbol expected"); + else { + strcpy(symbol, token); + def[0] = def[1] = 0; + while (TRUE) { + linex += scan1(&line[linex]); + c = token[0]; + if (!c) { + linex--; + if (nibcount & 1) { + fferror("Expected pairs of hex digits: one missing"); + return; + } + break; + } else if (c == ' ' || c == '\t' || c == '\n') continue; + else if (isdigit(c)) { + data = (data << 4) + (c - '0'); + nibcount++; + if (!(nibcount & 1)) { + if (!def_append(def, nparms, data)) + return; + data = 0; + } + } else if ('A' <= c && c <= 'F') { + data = (data << 4) + (c - 'A') + 10; + nibcount++; + if (!(nibcount & 1)) { + if (!def_append(def, nparms, data)) + return; + data = 0; + } + } else if (c == 'V') { + data = data << 4; + nibcount++; + /* v without a leading nibble is equivalent to 0v: */ + if (nibcount & 1) nibcount++; + if (!def_append(def, nparms, data)) + return; + def_parm(def, nparms++, nmacroparms+1); + } else if (c == '%') { + linex += scan1(&line[linex]); + c = token[0]; + if (c < '1' || c > ('0' + nmacroparms)) { + fferror(parm_expected_error); + break; + } + if (!def_append(def, nparms, 0)) + return; + def_parm(def, nparms++, c - '0'); + } else if (c == '^') { + linex += scan1(&line[linex]); + c = token[0]; + if (c < '1' || c > ('0' + nmacroparms)) { + fferror(parm_expected_error); + break; + } + if (!def_append(def, nparms, 0)) + return; + def_parm(def, nparms++, (c - '0') + nmacroparms + 1); + } else { /* something unexpected here -- just exit */ + linex--; + fferror("Unexpected data"); + return; + } + } + insert_def(the_score, symbol, def, + (nparms << 1) + def[(nparms << 1) + 1] + 2); + } +} + +/**************************************************************************** +* dodur +* Effect: parses a duration (sum of dosymdur and/or doabsdur) +* sets symbolic_dur_flag (according to the first addend in mixed arithmetic) +* +* Returns: duration in "precise" units +****************************************************************************/ +private time_type dodur() +{ + time_type result = 0L; + symbolic_dur_flag = TRUE; + + if (token[fieldx-1] == 'U') { + result = doabsdur(); + symbolic_dur_flag = FALSE; + } else result = dosymdur(); + while (token[fieldx] == '+') { + fieldx += 2; + if (token[fieldx-1] == 'U') result += doabsdur(); + else result += dosymdur(); + } + return scale(result, 100L, rate); +} + +/**************************************************************************** +* doerror +* Effect: parse an unrecognized field by reporting an error +****************************************************************************/ + +private void doerror() +{ + fieldx = 0; + fferror("Bad field"); +} + +/**************************************************************************** +* doloud +* Effect: parse a loudness (L) command +****************************************************************************/ + +private int doloud() +{ + int i, j; + int result; + int oldfieldx = fieldx; + int newfieldx; + char symbol[100]; + + if (!token[fieldx] || token[fieldx]==')' || token[fieldx]==',') { + fferror("L must be followed by loudness indication"); + return 100; + } + if (isdigit(token[fieldx])) { + result = (int) scanint(); + newfieldx = fieldx; + if (token[fieldx] && token[fieldx]!=')' && token[fieldx]!=',') + fferror("Digits expected after L"); + else if (result > 127) { + fieldx = oldfieldx; + fferror("Maximum loudness of 127 will be used"); + fieldx = newfieldx; + result = 127; + } else if (result == 0) { + fieldx = oldfieldx; + fferror("Minimum loudness of 1 will be used"); + fieldx = newfieldx; + result = 1; + } + return result; + } + scansymb(symbol); + newfieldx = fieldx; + if ((i = strlen(symbol)) > 3 ) { /* maximum is 3, e.g. "ppp" */ + fieldx = oldfieldx; + fferror("Loudness field too long"); + fieldx = newfieldx; + return 100; + } + symbol[i + 1] = '\0'; /* pad short symbols with 0 */ + /* e.g. "p\0" -> "p\0\0" */ + for (i = 0; i <= 7; i++) { /* loop through possibilities */ + for (j = 0; j <= 2; j++) { /* test 3 characters */ + if (symbol[j] != loudtable[i].symbol[j]) + break; + } + if (j == 3) { + return loudtable[i].value; + } + } + fieldx = oldfieldx; + fferror("Bad loudness indication"); + fieldx = newfieldx; + return 100; +} + + +void domacro() +{ + int control_num; + int value; + if (isdigit(token[1])) { + control_num = (int) scanint(); + if (token[fieldx] == '(') { + fieldx++; + if (!isdigit(token[fieldx])) { + fferror("Control value expected"); + } else { + value = (int) scanint(); + if (token[fieldx] != ')') { + fferror("Missing close paren"); + } else { + fieldx++; + if (token[fieldx]) + fferror("Nothing expected after paren"); + else if (macctrlx < nmacroctrl - 1) { + macctrlnum[macctrlx] = control_num; + macctrlparmx[macctrlx] = value; + macctrldef[macctrlx] = NULL; + macctrlx++; + } else fferror("Too many controls"); + } + } + } else fferror("Missing paren"); + } else { + def_type def; + char symbol[100]; + scansymb(symbol); + if (fieldx == 1) fferror("Macro name expected"); + else if (token[fieldx] != '(') fferror("Open paren expected"); + else { + fieldx++; + def = def_lookup(symbol); + if (!def) { + fieldx = 1; + fferror("Undefined macro"); + } else { + long val; + macctrlnum[macctrlx] = 0; + macctrlparmx[macctrlx] = macctrlnextparm; + macctrldef[macctrlx] = def; + while (token[fieldx] != ')' && parseparm(&val)) { + macctrlparms[macctrlnextparm++] = (short) val; + macctrlnum[macctrlx]++; + if (token[fieldx] == ',') { + fieldx++; + } else if (token[fieldx] != ')') { + fferror("Unexpected character"); + break; + } + } + fieldx++; + macctrlx++; + } + } + } +} + + +/**************************************************************************** +* donextdur +* Effect: parse a next (N) command +* Implementation: +* The syntax is N followed by a duration, so save dur and use dosymdur() +* to parse the duration field. +* The form N is parsed directly with scanint(). +****************************************************************************/ + +private void donextdur() +{ + ndurp = TRUE; /* flag that N was given */ + if (isdigit(token[fieldx])) { + ntime = precise(scanint()); + ntime = scale(ntime, (ulong)time_scale, rate); + if (token[fieldx]) + fferror("Only digits were expected here"); + } else { + fieldx++; + ntime = dodur(); + } +} + +/**************************************************************************** +* dopitch +* Effect: parses a pitch command +****************************************************************************/ + +private int dopitch() +{ + int p, octave=0; + int octflag = FALSE; /* set if octave is specified */ + int oldfieldx = fieldx; + + p = pitchtable[token[fieldx-1]-'A']; + while (TRUE) { + if (token[fieldx] == 'S') { /* sharp */ + p++; + fieldx++; + } + else if (token[fieldx] == 'N') { /* skip */ + fieldx++; + } + else if (token[fieldx] == 'F') { /* flat */ + p--; + fieldx++; + } + else if (isdigit(token[fieldx]) && !octflag) { /* octave */ + octave = (int) scanint(); + octflag = TRUE; + } + else break; /* none of the above */ + } + if (octflag) p = (p-48) + 12 * octave; /* adjust p to given octave */ + else { /* adjust p to note nearest the default pitch */ + int octdiff = (p + 126 - pitch) / 12; + p = p + 120 - (octdiff * 12); + } + if (p > maxpitch) { /* pitch in range? */ + int newfield = fieldx; + fieldx = oldfieldx; + fferror("Pitch too high"); + fieldx = newfield; + p = maxpitch; + } + /* We really should test for end-of-field, but we don't know if we're + in a parameter list, so comma may or may not be legal */ + return p; +} + +/**************************************************************************** +* doprogram +* Effect: parses a program change (Z) command +****************************************************************************/ + +private void doprogram() +{ + register int program = (int) scanint(); + ctrlflag[PROGRAM_CTRL] = ctrlflag[0] = TRUE; + if (token[fieldx]) { + fferror("Z must be followed by digits only"); + } else if (program < minprogram) { + fieldx = 1; + fferror("Minimum program of 1 will be used"); + program = minprogram; + } else if (program > maxprogram) { + fieldx = 1; + fferror("Maximum program of 128 will be used"); + program = maxprogram; + } + ctrlval[PROGRAM_CTRL] = program - 1; +} + + +private void doramp() +{ + int values[2]; + time_type stepsize = 100L; /* default 10 per second */ + int index = 0; + ndurp = FALSE; + values[0] = values[1] = 0; + while (TRUE) { + linex += scan(); + fieldx = 1; + if (nullstring(token)) { + break; + } else if (index == 2) { /* must be stepsize in dur syntax */ + stepsize = dodur(); + } else { + int ctrlx = 0; + static int ctrl_map[] = { -BEND_CTRL, VOLUME, -TOUCH_CTRL, MODWHEEL }; + + switch (token[0]) { + case 'M': ctrlx++; /* modwheel */ + case 'O': ctrlx++; /* aftertouch */ + case 'X': ctrlx++; /* volume */ + case 'Y': /* pitch bend */ + + if (index < 2) { + macctrlnum[index] = ctrl_map[ctrlx]; + macctrlparmx[index] = (int) scanint(); + if (token[fieldx]) + fferror("Only digits expected here"); + macctrldef[index] = NULL; + } else fferror("Unexpected control"); + break; + case '~': + if (index < 2) { + domacro(); + if (token[fieldx]) fferror("Unexpected character"); + } else fferror("Unexpected control"); + break; + case 'T': + if (index < 2) fferror("Control expected"); + dotime(); + break; + case 'V': + if (index < 2) fferror("Control expected"); + dovoice(); + break; + case 'N': + if (index < 2) fferror("Control expected"); + donextdur(); + break; + default: + if (index < 2) fferror("Control expected"); + dur = dodur(); + break; + } + if (index == 1 && (macctrlnum[0] != macctrlnum[1] || + macctrldef[0] != macctrldef[1])) { + fferror("Controls do not match"); + } + } + index++; + } + if (index < 3) fferror("Expected 2 controls and step size"); + else { + if (macctrldef[0]) { + int i, j, n; + n = 0; + i = macctrlparmx[0]; + j = macctrlparmx[1]; + while (n < macctrlnum[0]) { + if (macctrlparms[i] != macctrlparms[j]) break; + n++; i++; j++; + } + if (n >= macctrlnum[0]) n = 0; + /* Note: duration shortened to prevent overlap with next ramp */ + insert_deframp(the_score, seqround(thetime), lineno, voice, + seqround(stepsize), trunc(dur) - 1, macctrldef[0], macctrlnum[0], + macctrlparms + macctrlparmx[0], n, macctrlparms[j]); + } else { + /* Note: duration shortened to prevent overlap with next ramp */ + insert_ctrlramp(the_score, seqround(thetime), lineno, voice, + seqround(stepsize), trunc(dur) - 1, + macctrlnum[0], macctrlparmx[0], macctrlparmx[1]); + } + } + /* advance the time only if an N field was given */ + if (ndurp) thetime += ntime; + else thetime += dur; +} + + +/**************************************************************************** +* dorate +* Effect: parses a !rate command +****************************************************************************/ + +private void dorate() +{ + linex += scan(); + if (!token[0]) + fferror("rate number expected"); + else { + long oldrate = rate; + rate = (int) scanint(); + if (token[fieldx]) + fferror("Only digits expected here"); + if (rate == 0) { + fieldx = 0; + fferror("Rate 100 will be used here"); + rate = 100L; + } + start = thetime; + /* adjust dur in case it is inherited by next note */ + dur = (dur * oldrate); + dur = dur / rate; + } +} + + +private void doset(vec_flag) + boolean vec_flag; +{ + ndurp = FALSE; + linex += scan(); + if (!token[0]) fferror("Variable name expected"); + else { + struct symb_descr *desc = &HASHENTRY(lookup(token)); + if (!desc->symb_type) fferror("Called function not defined"); + else if (vec_flag && (desc->symb_type != vec_symb_type)) { + fferror("This is not an array"); + } else if (!vec_flag && (desc->symb_type != var_symb_type)) { + fferror("This is not a variable"); + } else { + int numargs = 1 + vec_flag; + int value[2]; + int i; + int *address = desc->ptr.intptr; + value[0] = value[1] = 0; + i = 0; + while (TRUE) { + linex += scan(); + if (nullstring(token)) { + break; + } else if (isdigit(token[0]) || token[0] == '-' || + token[0] == '+') { + if (i < numargs) { + value[i++] = (int) scansgnint(); + if (token[fieldx]) + fferror("Only digits expected here"); + } else fferror(too_many_error); + } else { + switch (token[0]) { + case 'T': + fieldx = 1; + dotime(); + break; + case 'V': + fieldx = 1; + dovoice(); + break; + case 'N': + fieldx = 1; + donextdur(); + break; + default: + fieldx++; + if (i < numargs) { + value[i++] = seqround(dodur()); + } else fferror(too_many_error); + break; + } + } + } + if (vec_flag && i != 2) fferror("No index given"); + if (vec_flag) { + if (value[0] >= desc->size) { + fferror("Subscript out of bounds"); + return; + } + /* reduce to the seti case: */ + address += value[0]; /* compute the vector address */ + value[0] = value[1]; /* set up value[] and i as if */ + i--; /* this were seti, not setv */ + } + if (i != 1) fferror("No value given"); + insert_seti(the_score, seqround(thetime), lineno, voice, + address, value[0]); + /* advance the time only if an N field was given */ + if (ndurp) thetime += ntime; + } + } +} + +/**************************************************************************** +* dospecial +* Effect: parses special (those starting with "!") commands +****************************************************************************/ + +private void dospecial() +{ + switch (issymbol()) { + case sym_tempo: + dotempo(); + break; + case sym_rate: + dorate(); + break; + case sym_csec: + /* adjust dur for inheritance by next note */ + dur = (dur * 1000L) / time_scale; + time_scale = 1000L; + break; + case sym_msec: + dur = (dur * 100L) / time_scale; + time_scale = 100L; + break; + case sym_seti: + doset(FALSE); + break; + case sym_setv: + doset(TRUE); + break; + case sym_call: + docall(); + break; + case sym_ramp: + doramp(); + break; + case sym_clock: + doclock(); + break; + case sym_def: + dodef(); + break; + case sym_end: + end_flag = TRUE; + break; + default: + fferror("Special command expected"); + } + parseend(); /* flush the rest of the line */ +} + +/**************************************************************************** +* dosymdur +* Effect: parses a duration (^, %, S, I, Q, H, or W) command +****************************************************************************/ + +private time_type dosymdur() +{ + int i, dotcnt = 0; + long dotfactor; + time_type result = 0; + + for (i = 0; i < durtable_len; i++) { + if (durtable[i].symbol == token[fieldx-1]) { + /* the shift right is because durs are stored doubled because + * otherwise a 64th note would have the value 75/2: */ + result = precise(durtable[i].value) >> 1; + break; + } + } + if (i == durtable_len) { + fieldx--; + fferror("Duration expected: one of W, H, Q, I, S, %, or ^"); + return 0L; + } + while (token[fieldx]) { + if (token[fieldx] == 'T') { /* triplet notation */ + result = (result * 2) / 3; /* lose a bit but avoid scale() */ + fieldx++; + } + else if (token[fieldx] == '.') { /* dotted notation */ + dotcnt++; + fieldx++; + } + else if (token[fieldx] == '/') { + long divisor; + fieldx++; + divisor = scanint(); + if (divisor > 0) result = result / divisor; + else fferror("non-zero integer expected"); + } + else if (isdigit(token[fieldx])) { /* numbers are multipliers */ + result = result * scanint(); + } + else break; + } + dotfactor = 1L; + for (i=1; i<=dotcnt; i++) + dotfactor = dotfactor * 2; + result = (2 * result) - (result / dotfactor); + + return scale(result, 100L, tempo); /* time in milliseconds */ +} + +/**************************************************************************** +* dotempo +* Effect: parses a !tempo command +****************************************************************************/ + +private void dotempo() +{ + linex += scan(); + if (!token[0]) + fferror("Tempo number expected"); + else { + long oldtempo = tempo; + tempo = scanint(); + if (token[fieldx]) + fferror("Only digits expected here"); + if (tempo == 0) { + fieldx = 0; + fferror("Tempo 100 will be used here"); + tempo = 100L; + } + start = thetime; + /* adjust dur in case it is inherited by next note */ + if (symbolic_dur_flag) { + dur = (dur * oldtempo); + dur = dur / tempo; + } + } +} + +/**************************************************************************** +* dotime +* Effect: parses a time (T) command +* Implementation: see implementation of donextdur() +****************************************************************************/ + +private void dotime() +{ + if (isdigit(token[fieldx])) { + thetime = precise(scanint()); + thetime = scale(thetime, (ulong)time_scale, rate); + if (token[fieldx] ) + fferror("Only digits were expected here"); + } else { + fieldx++; + thetime = dodur(); + } + thetime += start; /* time is relative to start */ +} + +/**************************************************************************** +* dovoice +* Effect: parse a voice (V) command (the voice is the MIDI channel) +****************************************************************************/ + +private void dovoice() +{ + if (isdigit(token[fieldx])) { + voice = (int) scanint(); + if (token[fieldx]) + fferror("V must be followed by digits only"); + if (voice > MAX_CHANNELS) { + char msg[40]; + sprintf(msg, "number too high, using %d instead", MAX_CHANNELS); + fferror(msg); + voice = MAX_CHANNELS; + } + else if (voice < 1) { + fferror("number too low, using 1 instead"); + voice = 1; + } + } + else fferror("No digit after V"); +} + +/**************************************************************************** +* fferror +* Inputs: +* char *s: an error message string +* Effect: +* prints the line with the error +* puts a cursor (^) at the error location +* prints the error message (s) +* Implementation: +* this routine prints a carat under the character that +* was copied into token[fieldx]. E.g. if fieldx = 0, the +* carat will point to the first character in the field. +****************************************************************************/ + +private void fferror(s) + char *s; +{ + gprintf(ERROR, "%3d | %s", lineno, line); + marker(linex-strlen(token)+fieldx+1+6); + gprintf(ERROR, "Error: %s.\n", s); +} + +/**************************************************************************** +* init +* Effect: +* initializes the state variables +****************************************************************************/ + +private void init() +{ + int i; + + end_flag = FALSE; + + /* initial (default) values for all state variables */ + symbolic_dur_flag = TRUE; /* default dur is symbolic */ + for (i = 0; i < nctrl; i++) { + /* no initial control changes */ + ctrlflag[i] = FALSE; + ctrlval[i] = 0; + } + + lineno = 0; + pitch = seq_dflt_pitch; + loud = seq_dflt_loud; + voice = seq_dflt_voice; + time_scale = 1000L; + tempo = 100L; + rate = 100L; + dur = precise(600); /* default dur is quarter note */ + thetime = precise(0); + start = thetime; + ntime = 0L; + ticksize = 0L; + artic = 100; +} + +/**************************************************************************** +* ins_a_note +* Returns: +* boolean: TRUE on success, FALSE if not enough memory +* Effect: +* note events (if any) corresponding to the current line are inserted +* Implementation: +* if a note on should occur after a note off and doesn't, and the +* two notes have the same pitch, then the note off can cancel the +* note on. to make it unlikely that roundoff will cause this situation, +* dur is decreased by one half of a clock tick before rounding. +* also, phase2 gives precedence to note-offs that are simultaneous +* with note-ons. +****************************************************************************/ + +private boolean ins_a_note() +{ + long the_dur = (trunc(dur) * artic + 50) / 100; + int the_pitch = pitch; + event_type note; + if (rest_flag) the_pitch = NO_PITCH; + note = insert_note(the_score, seqround(thetime), lineno, voice, + the_pitch, the_dur, loud); + if (!note) return FALSE; + return TRUE; /* success! */ +} + +/**************************************************************************** +* ins_ctrls +* Returns: +* boolean: TRUE on success, FALSE if not enough memory +* Effect: +* control events corresponding to current line are inserted in score +* Implementation: +* ctrlflag[i] is TRUE if control i was specified in this line, so +* insert one control change for each ctrlflag[i] that is TRUE +****************************************************************************/ + +private boolean ins_ctrls() +{ + int i; + event_type ctrl; + + for (i = 1; i < nctrl; i++) { + if (ctrlflag[i]) { + ctrl = insert_ctrl(the_score, seqround(thetime), lineno, i, voice, + ctrlval[i]); + if (!ctrl) return FALSE; + ctrlflag[i] = FALSE; + ctrlval[i] = 0; + } + } + return TRUE; /* success! */ +} + +/**************************************************************************** +* issymbol +* Outputs: returns symbol number, or -1 if no match +* Assumes: token[1] has the symbol to look up (token[0] == '!') +****************************************************************************/ + +private int issymbol() +{ + int i, symb_num; + char *sym; + + for (symb_num = 0; symb_num < sym_n; symb_num++) { + sym = ssymbols[symb_num]; + i = 1; + while (TRUE) { + if (token[i] != *sym) break; + if (*sym == 0) return symb_num; + sym++; + i++; + } + } + return -1; +} + +/**************************************************************************** +* marker +* Inputs: +* int count: the number of characters to indent +* Effect: +* prints a carat (^) at the position specified on file stderr +****************************************************************************/ + +private void marker(count) +int count; +{ + int i; + char s[128]; + for (i=0; i<(count-1); s[i++]=' ') /* */ ; + s[count-1] = '^'; + s[count] = '\0'; + gprintf(ERROR,"%s\n",s); +} + +/***************************************************************** +* parseend +* Effect: +* parse the note terminator, either ",", ";", EOS or "\n" +* +****************************************************************/ + +private void parseend() +{ + boolean done = FALSE; + while (!done) { + linex += scan1(&line[linex]); + switch (token[0]) { + case ',': + ndurp = TRUE; /* switch that next time was specified */ + ntime = 0L; + done = TRUE; + break; + case ';': + case '\n': + case EOS: + done = TRUE; + break; + case ' ': + case '\t': + break; /* skip over blanks and scan1 again */ + default: + fferror("Unexpected token"); + linex += scan(); /* flush the token */ + break; + } + } +} + +/**************************************************************************** +* parsefield +* Effect: looks at first character of token and calls a parsing routine +* +****************************************************************************/ + +private void parsefield() +{ + fieldx = 1; + switch (token[0]) { + case 'T' : + dotime(); + break; + case 'U': + case 'W': + case 'H': + case 'Q': + case 'S': + case 'I': + case '%': + case '^': + dur = dodur(); + break; + case 'R': + do_a_rest(); + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + pitch = dopitch(); + pitch_flag = TRUE; + break; + case 'P': + pitch = doabspitch(); + pitch_flag = TRUE; + break; + case 'L': + loud = doloud(); + break; + case 'N': + donextdur(); + break; +/* case 'J': + * doctrl(1); + * break; + */ + case 'K': + doctrl(PSWITCH_CTRL); + break; + case 'M': + doctrl(MODWHEEL_CTRL); + break; + case 'O': + doctrl(TOUCH_CTRL); + break; + case 'X': + doctrl(VOLUME_CTRL); + break; + case 'Y': + doctrl(BEND_CTRL); + break; + case 'Z': + doprogram(); + break; + case 'V': + dovoice(); + break; + case '~': + domacro(); + break; + case '*': + docomment(); + break; + case '#': + doartic(); + break; + default : + doerror(); + break; + } +} + +/**************************************************************************** +* parsenote +* Effect: +* parses a note line -- control events (if any) and note event (if +* present) are inserted into score +* Assumes: +* line contains a string to be parsed +****************************************************************************/ + +private boolean parsenote() +{ + boolean out_of_memory = FALSE; + int i; + + ndurp = FALSE; + rest_flag = FALSE; + + /* this loop reads tokens for a note */ + while (token[0]) { + parsefield(); + linex += scan(); + } + + parseend(); /* take care of note terminator */ + + /* + * insert ctrl's first so that will come before the note. + */ + if (ctrlflag[0]) { + out_of_memory |= !ins_ctrls(); + /* don't reset ctrlflag[0], it's used below */ + } + + /* + * insert macro's + */ + for (i = 0; i < macctrlx; i++) { + event_type ctrl; + if (macctrldef[i] == NULL) { + ctrl = insert_macctrl(the_score, seqround(thetime), lineno, + macctrlnum[i], voice, macctrlparmx[i]); + } else { + ctrl = insert_macro(the_score, seqround(thetime), lineno, + macctrldef[i], voice, macctrlnum[i], + &(macctrlparms[macctrlparmx[i]])); + } + out_of_memory |= (ctrl == NULL); + } + + /* insert a note if + * (1) a pitch was specified OR + * (2) no control was specified and this is not a rest + * (it's a pitch by default) + * + * NOTE: program changes during rests are advised since + * synthesizers may not be able to process a program + * change followed immediately by a note-on. In fact, this + * is why we insert notes whose pitch is NO_PITCH -- so that + * the program change can be processed during the rest. + */ + if (pitch_flag || + (!ctrlflag[0] && !rest_flag && (macctrlx == 0))) { + out_of_memory |= !ins_a_note(); + } + + if (ndurp) thetime += ntime; + else thetime += dur; + + return out_of_memory; +} + + +private boolean parseparm(valptr) + long *valptr; +{ + register char c = token[fieldx]; + if (isdigit(c) || c == '-') { + *valptr = scansgnint(); + return TRUE; + } else { + switch (c) { + case 'P': + fieldx++; + *valptr = doabspitch(); + return TRUE; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + fieldx++; + *valptr = dopitch(); + return TRUE; + case 'U': + case 'W': + case 'H': + case 'Q': + case 'I': + case 'S': + case '%': + case '^': + fieldx++; + *valptr = seqround(dodur()); + return TRUE; + case 'L': + fieldx++; + *valptr = doloud(); + return TRUE; + case '\'': + fieldx++; + *valptr = token[fieldx]; + fieldx++; + if (token[fieldx] != '\'') { + fferror("single quote expected"); + } + fieldx++; + return TRUE; + default: + fferror("Parameter expected"); + return FALSE; + } + } +} + + + +/**************************************************************************** +* scale +* Inputs: +* time_type x +* int (ulong?) n, d +* Outputs: +* returns time_type: result of scaling x by n/d +****************************************************************************/ + +public time_type scale(x, n, d) + ulong x; + ulong n, d; +{ + ulong lo = (x & 0xFFFFL) * n; + ulong hi = (x >> 16) * n; + ulong res = hi / d; + lo = (((hi - (res * d)) << 16) + lo + (d >> 1)) / d; + return (time_type)( (res << 16) + lo ); +} + +/**************************************************************************** +* scan +* Inputs: +* char *start: the string to scan +* Outputs: +* returns int: the index of the next char in start to scan +* Effect: +* skips over leading blanks +* copies characters from start into token, converting to upper case +* scanning stops on delimiter: one of space, tab, newline, semicolon +****************************************************************************/ + +private int scan() +{ + char *start = line + linex; + register char c; + register int i = 0; + register int j = 0; + register int parens = 0; + + while (((c = start[i]) == ' ') || (c == '\t')) i++; + + while ((c = start[i]) != ' ' && c != '\n' && c != '\t' && c != EOS && + (c != ',' || token[0] == '~' || parens > 0) && c != ';') { + + if (islower(start[i])) token[j] = toupper(start[i]); + else token[j] = start[i]; + if (c == '(') parens++; + else if (c == ')') parens--; + j++; + i++; + } + token[j] = '\0'; + + fieldx = 0; + if (parens) fferror("Unbalanced parens"); + + return i; +} + +/**************************************************************************** +* scan1 +* Inputs: +* char *start: the string to scan +* Outputs: +* returns int: the index of the next char in start to scan +* Effect: +* copies one char from start into token, converting to upper case +****************************************************************************/ + +private int scan1(start) +char *start; +{ + int i = 0; + + token[0] = *start; + if (islower(token[0])) token[0] = toupper(token[0]); + + if (!nullstring(token)) { + token[1] = '\0'; + i = 1; + } + fieldx = 0; + return i; +} + +/**************************************************************************** +* scanint +* Outputs: +* returns long: the scanned integer +* Effect: +* scans an unsigned long from token, starting at fieldx +* fieldx is incremented to end of the integer +****************************************************************************/ + +private long scanint() +{ + long i = 0; + char c; + while ((c = token[fieldx])) { + if (isdigit(c)) { + i = (i*10) + (c - '0'); + fieldx++; + } else return i; + } + return i; +} + +private long scansgnint() +{ + if (token[fieldx] == '-') { + fieldx++; + return -scanint(); + } else { + if (token[fieldx] == '+') { + fieldx++; + } + return scanint(); + } +} + + +/* scansymb -- scan a symbol from the token */ +/**/ +private void scansymb(str) + char *str; +{ + char c; + while ((c = token[fieldx])) { + if (isdigit(c) || isalpha(c) || c == '_') { + *str++ = c; + fieldx++; + } else break; + } + *str = EOS; +} + +/**************************************************************************** +* seq_read +* Inputs: +* seq_type seq: the sequence to receive the score +* FILE *fp: input file +* Outputs: +* none +* Effect: +* parses score from input file and builds score data structure +****************************************************************************/ + +void seq_read(seq, fp) + seq_type seq; + FILE *fp; +{ + boolean out_of_memory = FALSE; /* set when no more memory */ + /* printf("seq_read: chunklist is 0x%x\n", seq->chunklist); */ + the_score = seq; /* current sequence is a global within this module */ + if (!seq) return; + init(); + lineno = 0; + + /* make sure line is well terminated or scan might run off the end */ + line[linesize - 1] = EOS; + line[linesize - 2] = '\n'; + + /* this loop reads lines */ + while ((fgets(line, linesize - 2, fp) != NULL) && !out_of_memory && + !check_aborted() && !end_flag) { + lineno++; + linex = 0; + /* this loop reads notes from a line */ + while ((line[linex] != EOS) && !out_of_memory) { + /* loop invariant: line[linex] is first char of next note */ + ctrlflag[0] = FALSE; /* other ctrlflags are reset by ins_ctrls() */ + macctrlx = 0; + macctrlnextparm = 0; + pitch_flag = FALSE; + linex += scan(); + if (!nullstring(token)) { + if (token[0] == '*') docomment(); + else if (token[0] == '!') dospecial(); + else out_of_memory = parsenote(); + } + else parseend(); + } + } + + if (out_of_memory) { + gprintf(ERROR, "Out of note memory at line %d,\n", lineno-1); + gprintf(ERROR, " the rest of your file will be ignored.\n"); + } + + if (check_aborted()) { + gprintf(ERROR, "User aborted score input,\n"); + gprintf(ERROR, " the rest of your file will be ignored.\n"); + if (abort_flag == BREAK_LEVEL) abort_flag = 0; + } + + /* fclose(fp); -- don't close the file; if you do, Nyquist's garbage + collector will close Nyquist's copy, and closing the file twice + in Linux will crash Nyquist */ + + gprintf(TRANS, "\nLoaded Adagio file with %ld note(s), %ld ctrl(s).\n\n", + seq_notecount(the_score), seq_ctrlcount(the_score)); +} diff --git a/cmt/seqread.h b/cmt/seqread.h new file mode 100644 index 0000000..1348574 --- /dev/null +++ b/cmt/seqread.h @@ -0,0 +1,7 @@ +/* seqread.h -- header file for users of seqread.c */ +/* Copyright 1989 Carnegie Mellon University */ + +#define name_length 255 +void seq_read(seq_type seq, FILE *fp); /* LISP: (SEQ-READ SEQ FILE) */ +time_type scale(ulong, ulong, ulong); /*now public for smf_write, smf_read*/ + diff --git a/cmt/seqwrite.c b/cmt/seqwrite.c new file mode 100644 index 0000000..fde0746 --- /dev/null +++ b/cmt/seqwrite.c @@ -0,0 +1,282 @@ +/* seqwrite -- write a seq in Adagio format to a file */ +/*************************************************************************** +* Change Log +* Date | Change +*-----------+-------------------------------------------------------------- +* 11-Mar-94 | Created Change Log +* 11-Mar-94 | PLu : Added private to function defs. +* 28-Apr-03 | DM : changed for portability, true->TRUE, false->FALSE +****************************************************************************/ + +#include "switches.h" + +#include + +#include "cext.h" +#include "midifns.h" +#include "timebase.h" +#include "seq.h" +#include "seqwrite.h" +#include "userio.h" +#include "record.h" + +private boolean next_event_time(); +private void write_event(); +private void write_velocity(FILE *f, int velocity); +private void write_voice(); +private void write_rest(FILE *f, event_type ev, boolean abs_flag); +private void write_time(); + +private boolean clock_started; +private long clock_half_tick; +private int new_tempo; +/* non-zero indicates a pending tempo change... */ +private time_type tempo_change_at; + +private int macro_count; +private int call_count; +private int deframp_count; +private int seti_count; + +private int last_velocity; +private int last_voice = seq_dflt_voice; + + +/* next_event_time -- get the time of the next event */ +/* + * NOTE: clock events are ignored (unless this is the first clock event) + */ +private boolean next_event_time(event, next_time) + event_type event; + time_type *next_time; +{ + while (event) { + if (vc_ctrl(event->nvoice) == ESC_CTRL && + event->value == CLOCK_VALUE && + clock_started) { + /* this is a clock event, ignore it: */ + event = event->next; + } else { + *next_time = event->ntime; + return TRUE; + } + } + return FALSE; +} + + +/* seq_write -- write a seq to a file */ +/* + * NOTE: if abs_flag, then write using absolute times ('T'), otherwise use + * relative timing ('N'). Also, only selected channels are written. + */ +void seq_write(seq_type seq, FILE *f, boolean abs_flag) +{ + event_type ev = seq_events(seq); + + last_velocity = seq_dflt_loud; + last_voice = seq_dflt_voice; + + fprintf(f, "!MSEC\n"); + clock_started = FALSE; + tempo_change_at = 0; + + macro_count = 0; + call_count = 0; + deframp_count = 0; + seti_count = 0; + + while (ev) { + write_event(seq, ev, f, abs_flag); + ev = ev->next; + } + if (macro_count) gprintf(TRANS, "%d macros ignored.\n", macro_count); + if (call_count) gprintf(TRANS, "%d calls ignored.\n", call_count); + if (deframp_count) gprintf(TRANS, "%d deframps ignored.\n", deframp_count); + if (seti_count) gprintf(TRANS, "%d setis ignored.\n", seti_count); +} + + +private char ctrl_letter[] = "?KMOXYZ"; + +/* write_event -- write a single event to a file */ +/**/ +private void write_event(seq, event, f, abs_flag) + seq_type seq; + event_type event; + FILE *f; + boolean abs_flag; +{ + int voice = vc_voice(event->nvoice); + + /* process all current (and earlier) events */ + if (is_note(event)) { /*** a note or rest ***/ + /* if this note is not a rest, write it */ + if (event->value != NO_PITCH && + (seq_channel_mask(seq) & + (1 << (voice - 1)))) { + write_pitch(f, event->value); + fprintf(f, " U%ld ", event->u.note.ndur >> 8); + write_velocity(f, (int) (event->u.note.ndur & 0xFF)); + write_voice(f, voice); + write_time(f, event, abs_flag); + } + } else { /*** a control command ***/ + switch (vc_ctrl(event->nvoice)) { + case PSWITCH_CTRL: + case MODWHEEL_CTRL: + case TOUCH_CTRL: + case VOLUME_CTRL: + case BEND_CTRL: + fprintf(f, "%c%d ", ctrl_letter[vc_ctrl(event->nvoice)], + event->value); + write_voice(f, voice); + write_time(f, event, abs_flag); + break; + case PROGRAM_CTRL: + fprintf(f, "Z%d ", event->value + 1); + write_voice(f, voice); + write_time(f, event, abs_flag); + break; + case ESC_CTRL: + switch (event->value) { + case CALL_VALUE: + call_count++; + write_rest(f, event, abs_flag); + /* !call's are not written because there isn't enough + * information. A future version of seq should store + * the hash table entry instead of the address of the + * routine (then we could get string name of the call) + * and the number of arguments. + */ + break; + case CLOCK_VALUE: + /* design for !clock: for absolute (absflag) files, put the + clocks (if any) at the end where they can be edited out + easily. For relative files, keep the clocks in-line. + On each clock, write a !tempo command inferred by the + clock and followed by the !clock. Because the clock + event comes before the actual tempo change, the chnage + must be delayed by a half tick except for the first one. + */ + if (abs_flag) break; + new_tempo = (2500L << 16) / event->u.clock.ticksize; + if (clock_started) { + tempo_change_at = event->ntime + clock_half_tick; + } else { + fprintf(f, "!tempo %d\n", new_tempo); + fprintf(f, "!clock\n"); + clock_started = TRUE; + } + clock_half_tick = (event->u.clock.ticksize) >> 17; + break; + case MACCTRL_VALUE: + fprintf(f, "~%d(%d) ", event->u.macctrl.ctrl_number, + event->u.macctrl.value); + write_voice(f, voice); + write_time(f, event, abs_flag); + break; + case MACRO_VALUE: + macro_count++; + write_rest(f, event, abs_flag); + /* macros are not written because there isn't enough + * information. A future version of seq should store + * the number of arguments in the event, or better yet, + * in the definition. Send complaints to RBD! + */ + break; + case CTRLRAMP_VALUE: + fprintf(f, "!ramp ~%d(%d) ~%d(%d) U%d U%d ", + event->u.ramp.ctrl, event->u.ramp.u.ctrl.from_value, + event->u.ramp.ctrl, event->u.ramp.u.ctrl.to_value, + (int)event->u.ramp.step, + (int)event->u.ramp.dur); + write_voice(f, voice); + write_time(f, event, abs_flag); + break; + case DEFRAMP_VALUE: + deframp_count++; + write_rest(f, event, abs_flag); + /* See MACRO_VALUE above for why this isn't implemented. */ + break; + case SETI_VALUE: + seti_count++; + write_rest(f, event, abs_flag); + /* !seti and !setv are not implemented -- a future version + * of seq should save more information so we can reconstruct + * the Adagio source command. + */ + break; + default: + gprintf(TRANS, "unexpected ESC_CTRL value\n"); + break; + } + break; + default: + gprintf(TRANS, "unexpected seq data\n"); + break; + } + } +} + + +/* write_rest -- write a rest (in place of an event) */ +/**/ +private void write_rest(FILE *f, event_type ev, boolean abs_flag) +{ + fprintf(f, "R "); + write_time(f, ev, abs_flag); +} + + +/* write_time -- write the final field on the line with N or T command */ +/**/ +private void write_time(f, event, abs_flag) + FILE *f; + event_type event; + boolean abs_flag; +{ + time_type next_time; + + if (abs_flag) { + fprintf(f, "T%ld\n", event->ntime); + return; + } + + if (next_event_time(event->next, &next_time)) { + if (tempo_change_at && (next_time >= tempo_change_at)) { + fprintf(f, "N%ld\n!TEMPO %d\n!CLOCK\nR U%ld\n", + tempo_change_at - event->ntime, + new_tempo, next_time - tempo_change_at); + tempo_change_at = 0; + } else { + fprintf(f, "N%ld\n", next_time - event->ntime); + } + } else { + fprintf(f, "\n"); + } +} + + +/* write_velocity -- write the velocity field */ +/**/ +private void write_velocity(FILE *f, int velocity) +{ + if (last_velocity != velocity) { + last_velocity = velocity; + fprintf(f, "L%d ", velocity); + } +} + + +/* write_voice -- write the voice field */ +/**/ +private void write_voice(f, voice) + FILE *f; + int voice; +{ + if (last_voice != voice) { + last_voice = voice; + fprintf(f, "V%d ", voice); + } +} diff --git a/cmt/seqwrite.h b/cmt/seqwrite.h new file mode 100644 index 0000000..3f9ab6b --- /dev/null +++ b/cmt/seqwrite.h @@ -0,0 +1,6 @@ +/* seqwrite.h -- write adagio format file */ +/* Copyright 1994 Carnegie Mellon University */ + +void seq_write(seq_type seq, FILE *f, boolean abs_flag); + /* LISP: (SEQ-WRITE SEQ FILE BOOLEAN) */ + diff --git a/cmt/swlogic.h b/cmt/swlogic.h new file mode 100644 index 0000000..e09bd6c --- /dev/null +++ b/cmt/swlogic.h @@ -0,0 +1,197 @@ +/******************************************************************** +* swlogic.h - switch logic, loaded from various versions of switch.h +* +* Copyright 1989 Carnegie Mellon University +* +*********************************************************************/ + +/* + * When included, one of the following should be defined: + * AZTEC (manx compiler, implies AMIGA) + * THINK_C (Think C compiler, implies Macintosh) + * __MWERKS__ (Metrowerks C compiler, implies Macintosh) + * LATTICE & DOS (Lattice compiler for IBM PC/AT/XT/CLONES) + * MICROSOFT & DOS (Microsoft compiler, implies IBM PC/AT/XT/CLONES) + * UNIX (emulator for UNIX) + * UNIX_ITC (ITC code for RS6000) + * UNIX_MACH (MACH ukernel system) + */ + +/*------------------------------------------*/ +/* Other switches that might be defined in switches.h are as follows: */ +/* APPLICATION, SPACE_FOR_PLAY, MAX_CHANNELS */ +/*------------------------------------------*/ + +/* We're moving toward the elimination of switches.h, so try to map + * predefined constants into our standard constants shown above: + */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm new conditional compilation structure + * 28Apr03 rbd remove macro redefinitions: MICROSOFT + */ + + + +/* Microsoft C compiler: */ +#ifdef _MSC_VER +#endif +#ifdef _MSDOS +#define DOS +#endif + +/* Quick C compiler: */ +#ifndef DOS +#ifdef MICROSOFT +#define DOS +#endif +#endif + +/* Borland C compiler: */ +#ifdef __BORLANDC__ +#define BORLAND +#define DOS +#endif + +/* Borland Turbo C compiler: */ +#ifdef __TURBOC__ +#define BORLAND] +#define DOS +#endif + +/* SGI systems */ +#ifdef sgi +#ifndef UNIX +#define UNIX +#endif +#define UNIX_IRIX +#define MAX_CHANNELS 32 +#endif + +/* APPLICATION -- define APPLICATION if you want to disable + * looking for command line switches in the midi interface. + * I think this feature is here for the Piano Tutor project + * and you should not define APPLICATION for CMU Midi Toolkit + * projects (APPLICATION is a poor choice of terms): + */ + + +/* memory space management (system dependent): + * SPACE_FOR_PLAY must be enough space to allow + * seq to play a score. This may include space for + * note-off events, I/O buffers, etc. + */ +#ifndef SPACE_FOR_PLAY +#define SPACE_FOR_PLAY 10000L +#endif + + +/* How many MIDI channels are there? MACINTOSH can use 2 ports, + * so it supports 32 channels. Others have one port, 16 channels. + * On the other hand, if you don't have all the MIDI ports plugged + * into MIDI interfaces, CMT will just hang, so I'll compile with + * just 16 channels. The 32 channel option for the Mac is untested. + */ +#ifndef MAX_CHANNELS +#define MAX_CHANNELS 16 +#endif + + +/*------------------------------------------*/ +/* Now we get to the "logic": define things as a function of what + * was defined in switches.h + */ + +#ifdef THINK_C +#define MACINTOSH +#endif + +#ifdef __MWERKS__ +#define MACINTOSH +#endif + +#ifdef MACINTOSH +#define MACINTOSH_OR_DOS +#define MACINTOSH_OR_UNIX +/* I don't know if THINK_C defines this and we need it for a few prototypes... */ +#ifndef __STDC__ +#define __STDC__ +#endif +#ifndef TAB_WIDTH +#define TAB_WIDTH 4 +#endif +#endif + +#ifndef TAB_WIDTH +#define TAB_WIDTH 8 +#endif + +/* + * If MIDIMGR is defined, compile for the Apple MIDI Manager + * (Non MIDI manager code is no longer supported) + */ +#ifdef MACINTOSH +/* under Nyquist, the MidiMgr is not used, so you can't + * receive or send Midi as in CMU MIDI Toolkit; however, + * much of CMU MIDI Toolkit is used for Midi file IO + */ +#ifndef NYQUIST +#define MIDIMGR +#endif +#define USE_VSPRINTF +#endif + +#ifdef BORLAND +#define DOS +#endif + +#ifdef LATTICE322 +#define DOS +#define OLD_PROTOTYPES +#endif + +#ifdef UNIX_ITC +#define UNIX +#define ITC +#endif + +#ifdef UNIX_MACH +#define UNIX +#define ITC +#endif + +/* USE_VSPRINTF says vsprintf() is defined */ +#ifdef ITC +#define USE_VSPRINTF +#endif +#ifdef AZTEC +#define USE_VSPRINTF +#endif + + +/* DOTS_FOR_ARGS says ANSI "..." notation is recognized */ +#ifdef __STDC__ +#define DOTS_FOR_ARGS +#endif +#ifdef UNIX_ITC +#define DOTS_FOR_ARGS +#endif +#ifdef BORLAND +#define DOTS_FOR_ARGS +#endif +#ifdef MICROSOFT +#define DOTS_FOR_ARGS +#endif + +#ifdef DOS +#define MACINTOSH_OR_DOS +#else +#define huge +#endif + +#ifdef UNIX +#define MACINTOSH_OR_UNIX +#endif + +#define SWITCHES diff --git a/cmt/tempomap.c b/cmt/tempomap.c new file mode 100644 index 0000000..e56b9bf --- /dev/null +++ b/cmt/tempomap.c @@ -0,0 +1,124 @@ +/* tempomap.c -- used by midifile reader to record and lookup time maps */ +/* + * This module is designed to provide tempo change list insert and + * lookup facilities. The exact interpretation of beat and tempo are + * defined in one function, elapsed_time, which takes a tempo and a + * number of beats, and returns time. + */ + +#include "cext.h" +#include "midifns.h" +#include "timebase.h" +#include "moxc.h" +#include "seq.h" +#include "tempomap.h" + +static time_type elapsed_time(); + +/* tempomap_create -- create a tempomap */ +/**/ +tempomap_type tempomap_create() +{ + tempochange_type tempochange = tempochange_alloc(); + tempomap_type tempomap = tempomap_alloc(); + tempomap->hint = tempomap->entries = tempochange; + tempochange->beat = 0L; + /* default tempo is 120 (= 50000microsec/beat) and 24 divisions/quarter */ + /* this may be overridden by a tempomap_insert */ + tempochange->tempo = 500000L / 24; + tempochange->rtime = 0L; + tempochange->next = NULL; + return tempomap; +} + + +/* tempomap_free -- deallocate storage for tempo map */ +/**/ +void tempomap_free(tm) + tempomap_type tm; +{ + while (tm->entries) { + tempochange_type tc = tm->entries; + tm->entries = tc->next; + tempochange_free(tc); + } + memfree(tm, sizeof(tempomap_node)); +} + + +/* tempomap_insert -- insert a tempo change into the map */ +/**/ +void tempomap_insert(tempomap, beat, tempo) + tempomap_type tempomap; + long beat; /* beat division number */ + long tempo; /* microseconds per beat division */ +{ + tempochange_type tempochange = tempochange_alloc(); + register tempochange_type prev; + register tempochange_type next; + + tempochange->tempo = tempo; + tempochange->beat = beat; + + if ((!(tempomap->hint->next)) || + (tempomap->hint->beat > beat)) + tempomap->hint = tempomap->entries; + + /* find the insert point */ + for (prev = tempomap->hint; + (next = prev->next) && (next->beat <= beat); + prev = next); + + /* make the insert */ + tempochange->next = next; + prev->next = tempochange; + tempomap->hint = prev; + + /* update the real time of each change */ + for (tempochange = prev; + tempochange->next; + tempochange = tempochange->next) { + tempochange->next->rtime = + tempochange->rtime + + elapsed_time(tempochange->tempo, + tempochange->next->beat - tempochange->beat); + } +} + + +/* tempomap_lookup -- convert beat to 4us time */ +/* + * The returned time is real time in units of 4us. + */ +time_type tempomap_lookup(tempomap, beat) + tempomap_type tempomap; + long beat; +{ + register tempochange_type prev; + register tempochange_type next; + + if ((!(tempomap->hint->next)) || + (tempomap->hint->beat > beat)) + tempomap->hint = tempomap->entries; + + /* find the last inflection point */ + for (prev = tempomap->hint; + (next = prev->next) && (next->beat <= beat); + prev = next); + + /* interpolate */ + return prev->rtime + + elapsed_time(prev->tempo, beat - prev->beat); +} + + +/* elapsed_time -- compute the real elapsed time at a given tempo */ +/* + * the time returned is in units of 4us. + */ +static time_type elapsed_time(tempo, beat) + long tempo; + long beat; +{ + return (time_type)((tempo * beat) >> 2); +} diff --git a/cmt/tempomap.h b/cmt/tempomap.h new file mode 100644 index 0000000..a437c25 --- /dev/null +++ b/cmt/tempomap.h @@ -0,0 +1,25 @@ +/* tempomap.h -- list of tempo changes */ + +typedef struct tempochange_struct { + struct tempochange_struct *next; + time_type rtime; + long beat; + long tempo; +} tempochange_node, *tempochange_type; + + +typedef struct tempomap_struct { + tempochange_type entries; + tempochange_type hint; +} tempomap_node, *tempomap_type; + + +#define tempochange_alloc() (tempochange_type) memget(sizeof(tempochange_node)) +#define tempochange_free(tc) memfree(tc, sizeof(tempochange_node)) +#define tempomap_alloc() (tempomap_type) memget(sizeof(tempomap_node)) +tempomap_type tempomap_create(void); +void tempomap_free(tempomap_type tm); +void tempomap_insert(tempomap_type tempomap, long beat, long tempo); +time_type tempomap_lookup(tempomap_type tempomap, long beat); + + diff --git a/cmt/timebase.c b/cmt/timebase.c new file mode 100644 index 0000000..0bb1713 --- /dev/null +++ b/cmt/timebase.c @@ -0,0 +1,322 @@ +/* timebase.c -- management of calls, time bases and heaps for moxc */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 2-Apr-91 | JDW : further changes +* 21-Mar-92 | GWL : abort recovery +* 28-Apr-03 | DM : true->TRUE +*****************************************************************************/ + + +#include "stdio.h" +#include "cext.h" +#include "userio.h" +#include "midifns.h" +#include "timebase.h" +#include "moxc.h" + + +timebase_type timebase_queue = NULL; /* waiting to run timebase queue */ +call_type callfree = NULL; /* free list */ + +private void fatal(); + + +/**************************************************************************** +* timebase_create +* Inputs: +* maxsize is the initial size of the heap +* Outputs: +* returns an initialized timebase_type +****************************************************************************/ + +timebase_type timebase_create(maxsize) + int maxsize; +{ + static char *error_msg = "Out of memory in timebase_create()"; + timebase_type base = (timebase_type) memget(sizeof(timebase_node)); + if (!base) fatal(error_msg); + base->next = NULL; + base->next_time = MAXTIME; + base->virt_base = 0L; + base->real_base = 0L; + base->rate = 256L; + base->heap_size = 0; + base->heap_max = maxsize; + base->heap = (call_type *) memget(sizeof(call_type) * maxsize); + if (!base->heap) fatal(error_msg); + return base; +} + +/**************************************************************************** +* callinsert +* Inputs: +* timebase_type base: the time base and heap +* call_type call: the call to insert in heap +* Outputs: + none +* Implementation: +* linear insertion; to be changed to heap +****************************************************************************/ + +void callinsert(base, call) + timebase_type base; + call_type call; +{ + int i; + register call_type *heap = base->heap; + + /* handle overflow -- this should never be executed if the user + * gives the right initial heap size + */ + base->heap_size++; + if (base->heap_size >= base->heap_max) { + call_type *new_heap = (call_type *) + memget((base->heap_max << 1) * sizeof(call_type)); + int i; + call_type *oldptr; + call_type *newptr; + if (!new_heap) { + gprintf(TRANS, "Out of space, can't allocate new heap\n"); + EXIT(1); + } + + oldptr = base->heap; + newptr = new_heap; + + for (i = base->heap_max; i > 0; i--) *newptr++ = *oldptr++; + memfree((char *) heap, base->heap_max * sizeof(call_type)); + base->heap = heap = new_heap; + base->heap_max = (base->heap_max << 1); + } + + /* now do the heap insert */ + i = base->heap_size; + while (i > 1) { + int parent = i >> 1; + if (heap[parent]->u.e.time < call->u.e.time || + (heap[parent]->u.e.time == call->u.e.time && + heap[parent]->u.e.priority <= call->u.e.priority)) break; + heap[i] = heap[parent]; + i = parent; + } + heap[i] = call; + + /* if next_time might change, reinsert base into queue */ + if (heap[1] == call) { + remove_base(base); + insert_base(base); + } +} + +/**************************************************************************** +* callshow +* Inputs: +* calltype call: the call to show +* Effect: +* prints a description of call +* Assumes: +* call is not null +****************************************************************************/ +void callshow(call) + call_type call; +{ + int i; + gprintf(TRANS,"address: %lx\n", (ulong)call); + gprintf(TRANS,"time: %ld\n", call->u.e.time); + gprintf(TRANS,"routine: %lx\n", (ulong)call->u.e.routine); + gprintf(TRANS,"parameters:"); + for (i = 0; i < MAX_CALL_ARGS; i++) { + gprintf(TRANS, " %d", call->u.e.p.arg[i]); + } + gprintf(TRANS, "\n"); +} + +/*************************************************************** +* fatal +* +* Input : msg: a message to be displayed +* Effect: print message and exit program +***************************************************************/ + +private void fatal(msg) + char *msg; +{ + gprintf(FATAL, msg); + EXIT(1); +} + +/*************************************************************** +* timebase_free +* +* Input : a time base +* Effect: deallocate the time base +***************************************************************/ + +void timebase_free(timebase) + timebase_type timebase; +{ + remove_base(timebase); + if (timebase->heap) { + memfree((char *) timebase->heap, + (timebase->heap_max * sizeof(call_type))); + } + memfree((char *) timebase, sizeof(timebase_node)); +} + +/*************************************************************** +* insert_base +* +* Input : a time base not in the list +* Effect: insert timebase at the appropriate spot in the list +* computes the next_time field from the top of the heap +***************************************************************/ + +void insert_base(timebase) + timebase_type timebase; +{ + register timebase_type *ptr = &timebase_queue; + register time_type next_time = MAXTIME; + /* compute next_time */ + if (timebase->heap_size != 0) { + register call_type call = timebase->heap[1]; + /* virt to real calculation */ + next_time = (virt_to_real_256(timebase, call->u.e.time) & + 0xFFFFFF00) + call->u.e.priority; +/* gprintf(TRANS, + "insert next_time is %ld, vt %ld, rb %ld, vb %ld rt %ld\n", + next_time, timebase->heap[1]->u.e.time, + timebase->real_base, timebase->virt_base, timebase->rate); + */ + } + timebase->next_time = next_time; + + if (next_time != MAXTIME) { + /* insert into the list */ + while (TRUE) { + if (! *ptr) { + *ptr = timebase; + timebase->next = NULL; + return; + } else if ((*ptr)->next_time >= next_time) { + timebase->next = *ptr; + *ptr = timebase; + return; + } else ptr = &((*ptr)->next); + } + } +} + +/*************************************************************** +* remove_base +* +* Input : timebase +* Effect: if timebase is in the queue, remove it +***************************************************************/ + +void remove_base(timebase) + timebase_type timebase; +{ + timebase_type *ptr = &timebase_queue; + while (*ptr) { + if (*ptr == timebase) { + *ptr = timebase->next; + return; + } else ptr = &((*ptr)->next); + } +} + +/*************************************************************** +* remove_call +* +* Input : a timebase -- passed as a global +* Assumes: a_timebase->heap_size > 0 +* Returns: the earliest call in the queue +* Effect: removes the earliest call in the queue +***************************************************************/ + +call_type remove_call(timebase_type a_timebase) +{ + register call_type *heap = a_timebase->heap; + call_type result = heap[1]; + register call_type large; + int i = 1; + int child = i << 1;; + large = heap[a_timebase->heap_size--]; + while (child <= a_timebase->heap_size) { + if (child + 1 <= a_timebase->heap_size) { + if (heap[child + 1]->u.e.time < heap[child]->u.e.time || + (heap[child + 1]->u.e.time == heap[child]->u.e.time && + heap[child + 1]->u.e.priority < heap[child]->u.e.priority)) + child++; + } + /* child is now the index of the least child */ + if (large->u.e.time < heap[child]->u.e.time || + (large->u.e.time == heap[child]->u.e.time && + large->u.e.priority <= heap[child]->u.e.priority)) break; + /* swap */ + heap[i] = heap[child]; + i = child; + child = i << 1; + } + heap[i] = large; + return result; +} + +/*************************************************************** +* set_rate +* +* Input : timebase and new rate +* Effect: makes the current rate of timebase be rate +***************************************************************/ + +void set_rate(base, rate) + timebase_type base; + time_type rate; +{ + if (base == timebase) base->virt_base = virttime; + else base->virt_base = real_to_virt(base, eventtime); + base->real_base = eventtime; + base->rate = rate; +/* gprintf(TRANS, "new real_base %ld virt_base %ld\n", + base->real_base, base->virt_base); + */ + remove_base(base); + insert_base(base); +} + +/*************************************************************** +* set_virttime +* +* Input : virtual time +* Effect: makes the current virtual time of timebase be vtime +***************************************************************/ + +void set_virttime(base, vtime) + timebase_type base; + time_type vtime; +{ + base->real_base = eventtime; + base->virt_base = vtime; + if (base == timebase) virttime = vtime; + remove_base(base); + insert_base(base); +} + +/*************************************************************** +* timebase_use +* +* Input : a timebase to use for scheduling +* Effect: sets up globals: timebase, virttime +***************************************************************/ + +void timebase_use(base) + register timebase_type base; +{ + if (timebase != base) { + timebase = base; + virttime = real_to_virt(base, eventtime); + } +} diff --git a/cmt/timebase.h b/cmt/timebase.h new file mode 100644 index 0000000..9da4e90 --- /dev/null +++ b/cmt/timebase.h @@ -0,0 +1,85 @@ +/* timebase.h -- management of calls, time bases and heaps for moxc */ + +#define STOPRATE 0xFFFFL + +/*************************************************************************** +* call structure +****************************************************************************/ + +/* ---NOTE!!! if you change MAX_CALL_ARGS, change CALLARGS macro below--- */ +#define MAX_CALL_ARGS 8 +typedef struct call_args_struct { + long arg[MAX_CALL_ARGS]; +} call_args_node; + +typedef struct call { + union { + struct { + time_type time; /* virtual time of this call */ + int priority; /* an 8-bit the priority, low priority first */ + int (*routine)(); /* who to call */ + call_args_node p; /* what to pass */ + } e; + struct call *p; /* used to link free calls */ + } u; +} *call_type, call_node; + +/* CALLARGS - given a call_type, this macro generates an argument list */ +/* + * NOTE: originally, I thought call->u.e.p (a structure), would do it, but + * Lattice C for the Amiga has a compiler bug, and even in places where the + * bug doesn't show up, the code generated for the structure passing is + * a sequence of two loops: one to copy data to a local area on the stack, + * and one to push this data (a byte at a time!) to the top of the stack. + * With Lattice (and perhaps others, I haven't checked), it's better to + * push the data in-line. + */ +#ifdef LATTICE +#define CARG(n) call->u.e.p.arg[n] +#define CALLARGS(call) CARG(0), CARG(1), CARG(2), CARG(3), \ + CARG(4), CARG(5), CARG(6), CARG(7) +#else +#define CALLARGS(call) call->u.e.p +#endif + +/*************************************************************************** +* timebase structure +****************************************************************************/ + +typedef struct timebase_struct { + struct timebase_struct *next; /* used for list */ + time_type next_time; + time_type virt_base; + time_type real_base; + time_type rate; /* ratio of real/virt time, STOPRATE or more is infinity */ + short heap_size; + short heap_max; + call_type *heap; +} timebase_node, *timebase_type; + +extern timebase_type timebase_queue; + +#define call_alloc() ((call_type) memget(sizeof(call_node))) +#define call_free(c) memfree((char *) (c), sizeof(call_node)) + +timebase_type timebase_create(int maxsize); +void callinsert(timebase_type base, call_type call); +void callshow(call_type call); +void timebase_free(timebase_type timebase); +void insert_base(timebase_type timebase); +void remove_base(timebase_type timebase); +call_type remove_call(timebase_type a_timebase); +void set_rate(timebase_type base, time_type rate); +void set_virttime(timebase_type base, time_type vtime); +void timebase_use(timebase_type base); + +#define real_to_virt(base, rtime) ((base)->rate == 0 ? MAXTIME : \ + ((base)->virt_base + (((rtime) - (base)->real_base) << 8) / (base)->rate)) + +#define virt_to_real(base, vtime) ((base)->rate >= STOPRATE ? \ + ((base)->virt_base > vtime ? (base)->real_base : MAXTIME) : \ + (base)->real_base + ((((vtime) - (base)->virt_base) * (base)->rate) >> 8)) + +#define virt_to_real_256(base, vtime) ((base)->rate >= STOPRATE ? \ + ((base)->virt_base > vtime ? (base)->real_base << 8 : MAXTIME) : \ + ((base)->real_base << 8) + ((((vtime) - (base)->virt_base) * (base)->rate))) diff --git a/cmt/userio.c b/cmt/userio.c new file mode 100644 index 0000000..e8d4fdb --- /dev/null +++ b/cmt/userio.c @@ -0,0 +1,1285 @@ +/* userio.c -- handy user interface functions */ +/* Copyright 1989 Carnegie Mellon University */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 21-May-86 | Created +* 11-Aug-87 | F.H: Added clear_abort(), stop() +* May-88 | JCD : AMIGA VERSION +* 11-Jun-88 | RBD: disable printing of GDEBUG messages +* 12-Oct-88 | JCD : EXCLUSIVE AMIGA VERSION +* 13-Apr-89 | JCD : New portable version. +* 5-Apr | JDW : Further changes +* 2-Mar-92 | GWL : Little changes to satisfy compiler +* 19-Nov-92 | JDZ : Mach tty io threads +* 28-Apr-03 | DM : portability changes. true->TRUE, false->FALSE +*****************************************************************************/ + +/* Notes on ascii input: + +Input is complicated because different systems have varying input models, +especially with regard to handling ^C. The CMT model handles ^C and ^G as +special characters, and these do not cause software interrupts. Also, the +lowest level of the CMT model does not support line editing: Every character +is acted upon immediately. This has two implications: +(1) CMT must "read ahead" looking for ^C and ^G characters. This is handled +by the check_aborted() procedure, which reads characters into the +type_ahead[] array. +(2) CMT must do its own line editing. This is handled by the ggets() routine. + +A number of functions support ascii input, only some of which are visible +to the application programmer. Let's start at the top-level and work down; +each of the following calls the routine below it: + +ggets() - gets a string with line editing support. This function is fairly +machine independent, except for some backspace-and-erase control character +code sequences. + +ggetchar() - gets a raw character. This function calls wait_ascii() + and echoes it. Note that it may return ABORT_CHAR or BREAK_CHAR. + +wait_ascii() - gets a raw character without echo and without character +code translation. wait_ascii() either polls get_ascii() or uses some +kind of system-dependent event waiting. Returns ABORT_CHAR or BREAK_CHAR +immediately if abort_flag has been set, regardless of whether there is +new ascii input. + +get_ascii() - checks to see if a character is available. (Using +check_aborted().) +The only dependency here is on the Amiga, we restart input when buffer goes +from full to non-full. + +check_aborted() - looks for input by calling ascii_input. If found, +put the input into the type_ahead[] buffer. Returns abort_flag. + +ascii_input() - lowest level of input; just gets a character if there is +one. Does conversion from RETURN (\r) to EOL (\n). The Amiga handles +this in-line directly in check_aborted(). + +Here's a quick summary: + +ggets = ggetchar + line editing & string building +ggetchar = wait_ascii + character echo +wait_ascii = get_ascii + wait for character +get_ascii = check_aborted + pull char from buffer +check_aborted = ascii_input + test for ^C,^G + put in buffer +ascii_input = poll for char + CR->EOL conversion + +*/ + +#include "switches.h" + +#include +#include +#if HAS_STDLIB_H +#include /* normal case */ +#endif + + +#ifdef MACINTOSH +# include "StandardFile.h" + /* added for ThinkC 7 */ +# ifdef THINK_C +# include +# endif +#endif + +#ifdef AMIGA + +# ifdef AZTEC +# include "functions.h" +# else /* LATTICE */ +# include "amiga.h" +# include "stdarg.h" +# endif + +# include "intuition/intuition.h" +# include "devices/console.h" +#endif + +#include "ctype.h" +#include "stdio.h" +#include "cext.h" +#include "userio.h" + +#ifdef MICROSOFT +#include "signal.h" +#endif + +#ifdef UNIX_MACH +#include +#include +extern char a_in; +extern int a_in_flag; +extern int i_am_running; +#ifdef RTMach +extern itc_mutex_t a_mutex; +extern itc_condition_t a_cond, a_in_cond; +#define A_LOCK() itc_mutex_lock(&a_mutex) +#define A_UNLOCK() itc_mutex_unlock(&a_mutex) +#else /* RTMach */ +extern struct mutex a_mutex; +extern struct condition a_cond, a_in_cond; +#define A_LOCK() mutex_lock(&a_mutex) +#define A_UNLOCK() mutex_unlock(&a_mutex) +#endif /* RTMach */ +#endif + +#ifdef DOTS_FOR_ARGS +#include +#endif + +#ifdef UNIX +#include +#include +#include "cmtio.h" +#ifdef _IBMR2 +#define NBBY 8 +#define OPEN_MAX 2000 +#endif +#include +#endif + +#ifdef linux +#include /* for FD_ZERO / FD_SET */ +#endif + +extern int debug; + +#ifdef NYQUIST +/* get definitions for stdputstr, etc. */ +#include "xlisp.h" +#endif + + +/**************************************************************************** +* +* routines private to this module +* +****************************************************************************/ + +int GetReadFileName(); +int GetWriteFileName(); + +#ifdef MACINTOSH +private void PtoC_StrCopy(char *p1, char *p2); +#endif + +#ifdef AMIGA + char ConGetChar(); + ConMayGetChar(); +private void ConRead(); +private void ConPutStr(); +private void ConPutChar(); +UBYTE ascii_signal(); +UBYTE KeybSig(); +#endif + + +/**************************************************************************** +* +* variables shared with other modules +* +****************************************************************************/ + +public int abort_flag; /* control C or control G equivalent */ +public int redirect_flag; /* check whether the I/O has been redirected-- + Added by Ning Hu Apr.2001*/ +/* extern void musicterm(); */ /*DMH: from macmidi.c, to allow abort_check*/ +public boolean ascii_input(); + +/**************************************************************************** +* +* variables private to this module +* +****************************************************************************/ + +#ifdef AMIGA +struct IntuitionBase *IntuitionBase; +private struct IOStdReq *ConOutReq; +private struct MsgPort *ConOutPort; +private struct IOStdReq *ConInReq; +private struct MsgPort *ConInPort; +private char KeyBuff[16]; +private struct Window *Window; +private struct NewWindow NewWindow = { + 0,11,640,189, + 0,1, + NULL, + SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH | + WINDOWSIZING, + NULL,NULL, + (STRPTR) "Carnegie Mellon University MIDI Toolkit for Commodore AMIGA", + NULL,NULL, + 100,25,640,200, + WBENCHSCREEN }; +#endif + +#ifdef MACINTOSH +private OSType io_file_type = 0x3F3F3F3F; /* '????' */ +private OSType io_file_creator = 0x3F3F3F3F; /* '????' */ +#endif + +#define type_ahead_max 100 +char type_ahead[100]; +int type_ahead_head = 0; +int type_ahead_tail = 0; +int type_ahead_count = 0; + + +#ifdef DOS +#ifdef BORLAND +int c_break(void) +{ + gprintf(TRANS, " BREAK "); + abort_flag = ABORT_LEVEL; + return 1; /* non-zero means do not exit program */ +} +#endif +#ifdef MICROSOFT +void c_break(int sig) +{ + abort_flag = ABORT_LEVEL; + /* The CTRL+C interrupt must be reset to our handler since + * by default it is reset to the system handler. + */ + signal(SIGINT, c_break); /* assume this succeeds */ +} +#endif +#endif + +#ifdef MACINTOSH +#ifdef NYQUIST +void FlushOutput (void); +#endif +#endif + +/* gflush -- flush output produced by gprintf, etc. */ +/**/ +void gflush(void) +{ +#ifdef MACINTOSH +#ifdef NYQUIST + FlushOutput(); +#else + fflush(stdout); /* make sure any prompts or errors have been output */ + fflush(STDERR); +#endif /* NYQUIST */ +#endif /* MACINTOSH */ +#ifdef UNIX + fflush(stdout); /* make sure any prompts or errors have been output */ + fflush(STDERR); +#endif +} + + +/**************************************************************************** +* io_init +* +* I added this init function for the AMIGA version. +* +* io_init : opens a window +* and exits if initialisation can not be done properly. +* registers cleanup calls to carefully deallocate resources. +* +* io_init is not amiga specific : the simplest version +* of io_init could be a clear screen statement for example, and a +* printf("Good bye !\n") on exit. +* +* for the Mac, it seems that ascii_input doesn't work unless getchar() is +* called first. I assume this is because getchar() initializes the ability +* of the window to process type-in, so there is probably a way to set this +* directly. If you figure it out, let me know. -RBD +* +*****************************************************************************/ + +void +io_init() +{ + +#ifdef AMIGA + int error; + + /* Window and console initialisation */ + IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",1L); + if (IntuitionBase == NULL) EXIT(1); + cu_register((cu_fn_type) CloseLibrary, IntuitionBase); + + ConOutPort = CreatePort("conoutport", 0L); + if (ConOutPort == NULL) EXIT(1); + cu_register((cu_fn_type) DeletePort, ConOutPort); + + ConOutReq = CreateStdIO(ConOutPort); + if (ConOutReq == NULL) EXIT(1); + cu_register((cu_fn_type) DeleteStdIO, ConOutReq); + + ConInPort = CreatePort("coninport", 0L); + if (ConInPort == NULL) EXIT(1); + cu_register((cu_fn_type) DeletePort, ConInPort); + + ConInReq = CreateStdIO(ConInPort); + if (ConInReq == NULL) EXIT(1); + cu_register((cu_fn_type) DeleteStdIO, ConInReq); + + Window = OpenWindow(&NewWindow); + if (Window == NULL) EXIT(1); + cu_register((cu_fn_type) CloseWindow, Window); + + ConOutReq->io_Data = (APTR)Window; + ConOutReq->io_Length = sizeof(*Window); + error = OpenDevice("console.device", 0L, (struct IORequest *) ConOutReq, 0L); + ConInReq->io_Device = ConOutReq->io_Device; + ConInReq->io_Unit = ConOutReq->io_Unit; + if (error != NULL) EXIT(1); + cu_register((cu_fn_type) CloseDevice, ConOutReq); + + ConInReq->io_Command = CMD_READ; + ConInReq->io_Data = (APTR)KeyBuff; + ConInReq->io_Length = 1; + SendIO((struct IORequest *) ConInReq); +#endif + +#ifdef UNIX +#ifndef BUFFERED_SYNCHRONOUS_INPUT + IOsetup(0 /* standard input */); + cu_register((cu_fn_type) IOcleanup, NULL); +#endif +#endif + +#ifdef MACINTOSH +#ifndef NYQUIST /* don't need this if we're in Nyquist */ + char s[100]; + printf("Type to start: "); + fgets(s, 100, stdin); +#endif /* NYQUIST */ +#endif + +#ifdef DOS +#ifdef MICROSOFT + if (signal(SIGINT, c_break) == SIG_ERR) { + gprintf(ERROR, "Couldn't set Ctrl C handler\n"); + EXIT(1); + } +#else +#ifdef BORLAND + ctrlbrk(c_break); +#else + ... we are in DOS, but neither MICROSOFT nor BORLAND, + please set up a control C handler here... +#endif +#endif +#endif +} + +#ifdef MACINTOSH + +/**************************************************************************** +* abort_check +* Effect: +* exit nicely if the aborted flag is set +****************************************************************************/ + +public void abort_check() +{ + if (abort_flag) clean_exit(); +} + + +/**************************************************************************** +* clean_exit +* Effect: +* clean up and exit +****************************************************************************/ + +public void clean_exit() +{ + gprintf(TRANS, "Exiting...\n"); + EXIT(1); +} + +#ifdef MPW +/**************************************************************************** +* cleanup_abort_handler +* Effect: +* shuts down abort watcher +****************************************************************************/ + +public void cleanup_abort_handler() +{ + (void) sigset(SIGINT, SIG_DFL); /* deactivate abort watcher */ +} + + +/**************************************************************************** +* init_abort_handler +* Effect: +* starts abort watcher +* aborted flag is set to FALSE +****************************************************************************/ + +public void init_abort_handler() +{ + abort_flag = FALSE; + (void) sigset(SIGINT, abort_watcher); /* activate abort watcher */ +} +#endif + +#endif + + +/**************************************************************************** +* askbool +* Inputs: +* char *prompt: string to prompt for user input +* int deflt: TRUE or FALSE default +* Returns: +* boolean: TRUE or FALSE as entered by user +* Effect: +* prompts user for yes or no input, returns result +****************************************************************************/ + +int askbool(prompt, deflt) +char *prompt; +int deflt; +{ +#define undefined -1 + char defchar; /* the default answer */ + char c; /* user input */ + char in_string[100]; + int result = -1; /* the result: -1 = undefined, 0 = FALSE, 1 = TRUE */ + if (deflt) defchar = 'y'; + else defchar = 'n'; + while (result == undefined) { + gprintf(TRANS, "%s? [%c]: ", prompt, defchar); + ggets(in_string); + c = in_string[0]; + if (islower(c)) c = toupper(c); + if (c == 'Y') result = TRUE; + else if (c == 'N') result = FALSE; + else if (c == EOS) result = deflt; + else if (abort_flag) result = deflt; + /* space before Please to separate from user's type-in: */ + else gprintf(TRANS, " Please type Y or N.\n"); + } + if (abort_flag == BREAK_LEVEL) { + abort_flag = 0; + result = deflt; + gprintf(TRANS, "\n"); + } + return result; +} + + +/**************************************************************************** +* fileopen +* Inputs: +* char *deflt: the default file name (e.g. from command line) +* char *extension: default extension +* char *mode: read ("r") or write ("w") +* char *prompt: prompt for user +* Returns: +* opened file pointer +* Effect: +* opens file, prompts for user input if necessary and warns about +* possible confusion. If deflt is a null string or NULL, the user will +* be prompted for a name. The routine loops until a file is opened. +* If the mode is "r", a check is made to see if the file exists +* with and without the extension. If both exist a warning is given. +* For mode "w", a check is made to see if the file will be overwritten. +* The extension is automatically added if the default or user-typed +* file has no "." At the bottom of the loop body, if no file has +* been opened, the user is prompted for another file name. +****************************************************************************/ + +char fileopen_name[100]; /* name of the opened file */ + +FILE *fileopen(deflt, extension, mode, prompt) + char *deflt; + char *extension; /* default extension */ + char *mode; /* read "r" or write "w" */ + char *prompt; /* prompt for user */ +{ + char extname[100]; /* trial name with extension added */ + FILE *fp = NULL; /* file corresponding to filename */ + FILE *fpext; /* file corresponding to extname */ + char *problem = NULL; /* tells user why he has to try again */ + + if (!deflt) deflt = ""; /* treat NULL as the empty string */ + strcpy(fileopen_name, deflt); + /* keep trying until a good file is found: */ + while (fp == NULL) { + /* avoid null file names: */ + while (strlen(fileopen_name) == 0) { +#ifndef MACINTOSH + gprintf(TRANS, "%s : ", prompt); + ggets(fileopen_name); + if (abort_flag) { + if (abort_flag == BREAK_LEVEL) { + abort_flag = 0; + /* type return since user didn't... */ + gprintf(TRANS, "\n"); + } + return NULL; + } +#else /* use Macintosh file dialog */ + if (mode[0] == 'r') { + if (!GetReadFileName(fileopen_name)) return NULL; + } else if (mode[0] == 'w') { + if (!(GetWriteFileName(fileopen_name, prompt))) return NULL; + } else { + gprintf(ERROR, "(fileopen) internal error: bad mode\n"); + } +#endif /* MACINTOSH */ + } + if (mode[0] == 'r') { + strcpy(extname, fileopen_name); + strcat(extname, "."); + strcat(extname, extension); + fp = fopen(fileopen_name, mode); + fpext = fopen(extname, mode); + if (fp != NULL && fpext != NULL) { + gprintf(TRANS, + "warning: both %s and %s exist. %s will be used.\n", + fileopen_name, extname, fileopen_name); + fclose(fpext); + } else if (fpext != NULL) { + fp = fpext; + strcpy(fileopen_name, extname); /* remember what was opened */ + } + if (fp == NULL) problem = "Couldn't find %s.\n"; + } else if (mode[0] == 'w') { + boolean added_extension = FALSE; + + /* add the extension if there is no '.' in the file name */ + if (!strchr(fileopen_name, '.')) { + strcat(fileopen_name, "."); + strcat(fileopen_name, extension); + added_extension = TRUE; + } + if (TRUE +#ifdef MACINTOSH + /* file open dialog already asked user to confirm unless we're + * adding an extension + */ + && added_extension +#endif + ) { + fp = fopen(fileopen_name, "r"); + if (fp != NULL) { + char question[100]; + fclose(fp); + strcpy(question, "OK to overwrite "); + strcat(question, fileopen_name); + if (!askbool(question, FALSE)) { + fp = NULL; + problem = "\n"; + goto tryagain; + } + } + } + fp = fopen(fileopen_name, mode); + if (fp == NULL) problem = "Couldn't create %s.\n"; + } + tryagain: + if (fp == NULL) { + gprintf(TRANS, problem, fileopen_name); + gprintf(TRANS,"Try again.\n"); + fileopen_name[0] = EOS; + } + } + return fp; +} + + +#ifdef MACINTOSH + +static int GetReadFileName(name) +char *name; +{ + static Point p = {100,100}; + SFReply loadfile; + SFTypeList mytypes; + + mytypes[0] = 0x54455854; /* 'TEXT' */ + mytypes[1] = 0x4D696469; /* 'Midi' */ + mytypes[2] = 0x3F3F3F3F; /* '????' */ +/* could put any filter here (i.e. giofilefileter) */ + SFGetFile(p, "\p", NULL, 3, mytypes, 0L, &loadfile); + if (loadfile.good) { + SetVol(0L,loadfile.vRefNum); + PtoC_StrCopy((char *) &loadfile.fName, name); + return(true); + } else return(false); +} + + +static int GetWriteFileName(fn, str) +char *fn, *str; +{ + static Point SFPwhere = { 106, 104 }; + unsigned char Pstr[100], Pfn[100]; + SFReply reply; + + strcpy((char *)Pstr, str); + CtoPstr((char *)Pstr); + strcpy((char *)Pfn, fn); + CtoPstr((char *)Pfn); + + SFPutFile(SFPwhere, (ConstStr255Param) Pstr, (ConstStr255Param) Pfn, + 0L, &reply); + if (reply.good) { + SetVol (0L,reply.vRefNum); + PtoC_StrCopy((char *) &reply.fName, fn); + return(true); + } + else return(false); +} + + +void PtoC_StrCopy(p1, p2) + register char *p1, *p2; +/* copies a pascal string from p1 to p2 */ +{ + register int len; + + len = *p1++; + while (--len>=0) *p2++=*p1++; + *p2 = '\0'; +} + + +boolean get_file_info(char *filename, OSType *file_type, OSType *file_creator) +{ + short rc; /* toolbox return code */ + FInfo fi; /* toolbox file info */ + char fn[101]; /* temporary file name */ + + strcpy(fn, filename); + CtoPstr(fn); + if (rc = GetFInfo((byte*)fn, 0, &fi)) { + gprintf(ERROR, "rc from GetFInfo=%d\n", rc); + gprintf(ERROR, "unable to get file type\n"); + *file_type = 0x3F3F3F3F; /* '????' */ + *file_creator = 0x3F3F3F3F; /* '????' */ + return FALSE; + } else /* set file type & creator */ { + if (debug) gprintf(TRANS, "File Type: '%.4s' File Creator: '%.4s'\n", + &fi.fdType, &fi.fdCreator ); + *file_type = fi.fdType; + *file_creator = fi.fdCreator; + } + return TRUE; +} + + +boolean put_file_info(char *filename, OSType file_type, OSType file_creator) +{ + short rc; /* toolbox return code */ + FInfo fi; /* toolbox file info */ + char fn[101]; /* temporary file name */ + + if (debug) gprintf(TRANS,"set file %s to become type '%.4s'\n", filename, &file_type); + strcpy(fn, filename); + CtoPstr(fn); + if (rc = GetFInfo((byte*)fn, 0, &fi)) { + gprintf(TRANS, "rc from GetFInfo=%d\n", rc); + gprintf(TRANS, "unable to set file type\n"); + } else /* set file type & creator */ { + if (debug) gprintf(TRANS, "File Type: '%.4s' File Creator: '%.4s'\n", + &fi.fdType, &fi.fdCreator ); + fi.fdType = file_type; + fi.fdCreator = file_creator; + if (rc=SetFInfo((byte*)fn, 0, &fi)) { + gprintf(TRANS, "rc from SetFInfo=%d\n", rc); + gprintf(TRANS, "unable to set file type\n"); + } else if (rc=GetFInfo((byte*)fn, 0, &fi)) { + gprintf(TRANS, "rc from GetFInfo=%d\n", rc); + gprintf(TRANS, "unable to verify file type\n"); + } else { + if (debug) gprintf(TRANS, "File Type: '%.4s' File Creator: '%.4s'\n", + &fi.fdType, &fi.fdCreator ); + } + } +} +#endif /* MACINTOSH */ + + + +#ifdef AMIGA +/*************************************************************** +* ascii_signal +* +* Input : none +* Ouput : none +* Return: the signal that will be raised on ascii input +* Effect: none +***************************************************************/ + +UBYTE ascii_signal() +{ + return ConInPort->mp_SigBit; +} +#endif + +/* check_aborted -- see if any characters are available, check for ctrl C */ + +int check_aborted() +{ + char in_c; +#ifdef AMIGA + if (GetMsg(ConInPort)) { + in_c = KeyBuff[0]; + if (in_c == '\r') in_c = '\n'; +#endif +#ifndef AMIGA /* DOS or MACINTOSH or UNIX */ + if (type_ahead_count < type_ahead_max && ascii_input(&in_c)) { +#endif + type_ahead[type_ahead_tail] = in_c; + if (in_c == ABORT_CHAR) abort_flag = ABORT_LEVEL; + else if (!abort_flag && in_c == BREAK_CHAR) + abort_flag = BREAK_LEVEL; + + /* go ahead and insert anything into buffer, including ^C, ^G: */ + type_ahead_count++; + type_ahead_tail++; + if (type_ahead_tail == type_ahead_max) type_ahead_tail = 0; + +#ifdef AMIGA + if (type_ahead_count < type_ahead_max) ConRead(); +#endif + } + return abort_flag; +} + + +/**************************************************************************** +* readln +* Inputs: +* FILE * fp: File to read from +* Effect: +* Reads and discards characters until a newline is seen +****************************************************************************/ + +void readln(fp) + register FILE *fp; +{ + register int c; + while (((c = getc(fp)) != '\n') && (c != EOF)) ; +} + + +/**************************************************************************** +* gprintf +* Inputs: +* int * handler: pointer to output handler (say, a window) +* or one of {TRANS, ERROR, FATAL, GDEBUG} from userio.h +* char * format: a null-terminated printf style format string +* int arg0 through arg14: a variable number of arguments for printf +* Effect: +* formats and outputs the specified information to an output handler. +* this is a system-independent approach to output. On +* a simple machine, it is like printf. on a more complex machine, +* output is directed to the appropriate window. +* Implementation +* Note that to handle the variable argument list, a number of different +* approaches are implemented. The first part of the implementation selects +* one of 4 ways to build temp1, a formatted string. The 4 ways arise from +* use or non-use of vsprintf, and use or non-use of ... in the arg list. +* After building temp1, non-Amiga systems write to stdout or stderr, +* whereas AMIGA writes to a special console. Why? Because the Amiga +* needs a new console so we can set up a signal upon character typein. +****************************************************************************/ + +#ifndef gprintf +#define GPRINTF_MESSAGE_LEN 512 +#ifdef USE_VSPRINTF +#ifdef DOTS_FOR_ARGS + +/* define with ... in arg list and use vsprintf to get temp1 */ +public void gprintf(long where, char *format, ...) +{ + char temp1[GPRINTF_MESSAGE_LEN]; +#ifdef AMIGA + char temp2[GPRINTF_MESSAGE_LEN]; +#endif + va_list ap; + + va_start(ap, format); + vsprintf(temp1, format, ap); + va_end(ap); + +#else /* !DOTS_FOR_ARGS */ + +/* define with va_alist and use vsprintf to get temp1 */ +public void gprintf(where, format, va_alist) +long where; +char *format; +va_dcl +{ + char temp1[GPRINTF_MESSAGE_LEN]; + va_list pvar; +/* this is a syntax error - if you don't have to remove this, */ +/* then this whole section of code is unnecessary. */ + va_start(pvar); + vsprintf(temp1, format, pvar); + va_end(pvar); + +#endif /* DOTS_FOR_ARGS */ + +#else /* !USE_VSPRINTF */ +#define MAX_GPRINTF_ARGS 10 +typedef struct gp_args_struct { + long arg[MAX_GPRINTF_ARGS]; +} gp_args_node; + +#ifdef DOTS_FOR_ARGS +/* use ... but not vsprintf */ +public void gprintf(long where, char *format, ...) +{ + char temp1[GPRINTF_MESSAGE_LEN]; +#ifdef AMIGA + char temp2[GPRINTF_MESSAGE_LEN]; +#endif + va_list ap; + gp_args_node args; + va_start(ap, format); + args = va_arg(ap, gp_args_node); + va_end(ap); +#else /* !DOTS_FOR_ARGS */ +/* don't use ... and don't use vsprintf */ +public void gprintf(where, format, args) + long where; + char *format; + gp_args_node args; +{ + char temp1[GPRINTF_MESSAGE_LEN]; +#ifdef AMIGA + char temp2[GPRINTF_MESSAGE_LEN]; +#endif /* AMIGA*/ +#endif /* DOTS_FOR_ARGS */ + + sprintf(temp1, format, args); + +#endif /* USE_VSPRINTF */ + +/* + * Now we've got formatted output in temp1. Write it out. + */ +#ifdef NYQUIST + switch ((long) where) { + case TRANS: + stdputstr(temp1); + break; + case ERROR: + errputstr(temp1); + break; + case FATAL: + errputstr("FATAL: "); + errputstr(temp1); + break; + case GDEBUG: + errputstr("DEBUG: "); + errputstr(temp1); + break; + default: + errputstr("UNKNOWN: "); + errputstr(temp1); + break; + } + gflush(); +#else /* not NYQUIST */ +#ifdef AMIGA + + switch((long) where) { + case TRANS: + strcpy(temp2, temp1); + break; + case ERROR: + strcpy(temp2, temp1); + break; + case FATAL: + strcpy(temp2, "FATAL: "); + strcat(temp2, temp1); + break; + case GDEBUG: + strcpy(temp2,"DEBUG: "); + strcat(temp2, temp1); + break; + default: + strcpy(temp2, "UNKNOWN: "); + strcat(temp2, temp1); + break; + } + ConOutReq->io_Command = CMD_WRITE; + ConOutReq->io_Data = (APTR)temp2; + ConOutReq->io_Length = -1; /* NULL terminated string */ + DoIO((struct IORequest *) ConOutReq); +#else /* not NYQUIST or AMIGA */ + switch(where) { + case TRANS: + printf("%s", temp1); + break; + case ERROR: + fprintf(STDERR, "%s", temp1); + break; + case GDEBUG: + fprintf(STDERR, "DEBUG %s", temp1); + break; + case FATAL: + fprintf(STDERR, "FATAL %s", temp1); + break; + default: + fprintf(STDERR, "UNKNOWN %s", temp1); + break; + } +#endif /* AMIGA */ +#endif /* NYQUIST */ +} + +#endif /* ifndef gprintf */ + + +/************************************************************************** +* gputchar +* General putchar +**************************************************************************/ + +#ifndef gputchar + +#ifdef AMIGA +public int gputchar(c) +int c; +{ + ConPutChar((char)c); + return(c); +} +#else +public int gputchar(c) +int c; +{ + putchar((char)c); + return(c); +} +#endif + +#endif /* ifndef gputchar */ + +/************************************************************************** +* ggetchar +* General getchar +**************************************************************************/ + +public int ggetchar() +{ +#ifdef BUFFERED_SYNCHRONOUS_INPUT + return getchar(); +#else + int key = wait_ascii(); + if (key != ABORT_CHAR && key != '\b') gputchar((char)key); + return(key); +#endif +} + + +/************************************************************************** +* ggets +* General gets +**************************************************************************/ + + +#ifndef ggets + +public char *ggets(str) + char *str; +{ + char *s = str; + int c; + + do { + c = ggetchar(); + if (c == '\b' /* backspace */) { + if (s != str) { + gputchar('\b'); + gputchar((int)' '); + gputchar('\b'); + s--; + } else { +#ifdef AMIGA + gputchar((int)0x9b); + gputchar((int)0x43); +#else + /* gputchar((int)' '); */ +#endif + gputchar((int)0x07); + } + } else *s++ = (char) c; + } while (c != (int) '\n' && !abort_flag); + + *(s-1) = EOS; + if (abort_flag) *str = EOS; + return str; +} + +#endif /* ifndef ggets */ + + +/**************************************************************************** +* get_ascii +* Returns: +* boolean: TRUE if a character was found +* int * c: pointer to int into which to store the character, if any +* Effect: +* polls (doesn't wait) for an ascii character and says if it got one +* the character is returned in *c. +****************************************************************************/ + +public boolean get_ascii(c) + char *c; +{ + check_aborted(); /* input buffer check */ + if (type_ahead_count == 0) return FALSE; +#ifdef AMIGA + /* if the buffer is full, then there is no outstanding read, restart it: */ + if (type_ahead_count == type_ahead_max) ConRead(); +#endif + type_ahead_count--; + *c = type_ahead[type_ahead_head++]; + if (type_ahead_head == type_ahead_max) type_ahead_head = 0; + return TRUE; +} + +#ifdef MACINTOSH /** Macintosh direct ascii input**/ +public boolean ascii_input(c) +char *c; +{ + EventRecord theEvent; + + (void) GetNextEvent((keyDownMask | autoKeyMask), &theEvent); + if ((theEvent.what == keyDown) || (theEvent.what == autoKey)) { + *c = theEvent.message & charCodeMask; + if (*c == '\r') *c = '\n'; + return(true); + } + else { + return(false); + } +} +#endif + +#ifdef WINDOWS +#include "conio.h" +#define kbhit _kbhit +#define getch _getch +#endif + +#ifdef DOS +public boolean ascii_input(c) +char *c; +{ + if (abort_flag == ABORT_LEVEL) { + *c=ABORT_CHAR; + return((boolean)TRUE); + } + if (kbhit()) { /* If the keyboard was hit */ + *c = getch(); /* Don't echo it */ +// printf("now break"); + if (*c == '\r') *c = '\n'; + return((boolean)TRUE); + } + return((boolean)FALSE); /* Keeps Lattice compiler happy */ +} +#endif + +#ifdef UNIX +public boolean ascii_input(c) +char *c; +{ +#ifdef UNIX_MACH + /* + * we can't read from stdin directly, because the ascii + * input thread is already doing so, so instead we'll + * wait for that thread to read a character and then take + * it + */ + boolean ret = FALSE; + + A_LOCK(); + if (a_in_flag) { + (*c) = a_in; + a_in_flag = 0; + ret = TRUE; + } + A_UNLOCK(); + if (ret) { +#ifdef RTMach + itc_condition_signal(&a_cond); +#else /* RTMach */ + condition_signal(&a_cond); +#endif /* RTMach */ + } + if ((*c) == '\r') + (*c) = '\n'; + return(ret); +#else /* UNIX_MACH */ +#ifndef BUFFERED_SYNCHRONOUS_INPUT + int input = IOgetchar(); + if (input != IOnochar) { + *c = input; + if (*c == '\r') *c = '\n'; + return TRUE; + } +#endif /* BUFFERED_SYNCHRONOUS_INPUT */ + return FALSE; +#endif /* UNIX_MACH */ +} +#endif + +#ifndef AMIGA /*DOS and MAC and UNIX */ +public void unget_ascii(char c) +{ + if (type_ahead_head == 0) type_ahead_head = type_ahead_max; + type_ahead_head--; + type_ahead[type_ahead_head] = c; + type_ahead_count++; +} + + +public boolean check_ascii() +{ + char c; + + if(get_ascii(&c)) { + unget_ascii(c); + return TRUE; + } + else return FALSE; +} +#endif + + +/**************************************************************************** +* wait_ascii +* Returns: +* int: character for key pressed +* Effect: +* waits for the user to type a key on the terminal keyboard +* (versus the synthesizer keyboard) and returns the key typed +****************************************************************************/ + +#ifdef MACINTOSH +public int wait_ascii() +{ + char key ; /* key typed */ + + if (abort_flag == ABORT_LEVEL) return ABORT_CHAR; + if (abort_flag == BREAK_LEVEL) return BREAK_CHAR; + gflush(); + while (!get_ascii(&key)) ; + return(key); +} +#endif + +#ifdef DOS +public int wait_ascii() +{ + char key ; /* key typed */ + + if (abort_flag == ABORT_LEVEL) return ABORT_CHAR; + if (abort_flag == BREAK_LEVEL) return BREAK_CHAR; + if (!get_ascii(&key)) { + key = _getch(); // block until we get an input + } + /* GWL - check for abort on previos line */ + return (int)key; +} +#endif + +#ifndef MACINTOSH +#ifndef DOS +public int wait_ascii() +{ +#ifdef UNIX /* was defined (UNIX) || defined(ITC) */ +#ifndef UNIX_MACH + fd_set readfds; +#endif /* !UNIX_MACH */ +#endif + char c; + struct rlimit file_limit; + + if (abort_flag == ABORT_LEVEL) return ABORT_CHAR; + if (abort_flag == BREAK_LEVEL) return BREAK_CHAR; + while (!get_ascii(&c)) { +#ifdef AMIGA + WaitPort(ConInPort); +#endif +#ifdef UNIX + fflush(stdout); +#ifdef UNIX_MACH + /* + * we can't select, since another thread is reading + * from stdin, and we don't want to have an input war + * so instead, the ascii input thread will signal + * a_in_cond when it gets input, so we just wait + * for that to happen + */ + A_LOCK(); +#ifdef RTMach + itc_condition_wait(&a_in_cond, &a_mutex); +#else /* RTMach */ + condition_wait(&a_in_cond, &a_mutex); +#endif /* RTMach */ + A_UNLOCK(); +#else /* UNIX_MACH */ + FD_ZERO(&readfds); + FD_SET(IOinputfd, &readfds); + gflush(); + getrlimit(RLIMIT_NOFILE, &file_limit); + select(file_limit.rlim_max+1, &readfds, 0, 0, NULL); +#endif /* !UNIX_MACH */ +#endif /* ifdef UNIX */ + } + return (int) c; +} +#endif +#endif + +#ifdef AMIGA +/****************************************************************** + AMIGA 2000. + Console IO Functions + JCD 25-Apr-88 +*******************************************************************/ + +UBYTE KeybSig() +{ + return ConInPort->mp_SigBit; +} + +private void ConPutChar(c) +char c; +{ + ConOutReq->io_Command = CMD_WRITE; + ConOutReq->io_Data = (APTR)&c; + ConOutReq->io_Length = 1; + DoIO((struct IORequest *) ConOutReq); +} + +private void ConPutStr(str) +char *str; +{ + ConOutReq->io_Command = CMD_WRITE; + ConOutReq->io_Data = (APTR)str; + ConOutReq->io_Length = -1; + DoIO((struct IORequest *) ConOutReq); +} + +private void ConRead() +{ + ConInReq->io_Command = CMD_READ; + ConInReq->io_Data = (APTR)KeyBuff; + ConInReq->io_Length = 1; + SendIO((struct IORequest *) ConInReq); +} +#endif diff --git a/cmt/userio.h b/cmt/userio.h new file mode 100644 index 0000000..7c05e96 --- /dev/null +++ b/cmt/userio.h @@ -0,0 +1,96 @@ +/* Copyright 1989 Carnegie Mellon University */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 5-Apr |JDW : Further changes +*****************************************************************************/ + +/* classes of output for gprintf */ +#ifdef MACINTOSH +#undef false +#undef true +#include +#define TRANS (long) 0 +#define ERROR (long) 1 +#define FATAL (long) 2 +#define GDEBUG (long) 3 +#endif + +#ifdef DONT_USE_CMT_IO +#define TRANS stdout +#define ERROR stdout +#define FATAL stdout +#define GDEBUG stdout +#endif + +#ifndef TRANS /* default */ +#define TRANS 0 +#define ERROR 1 +#define FATAL 2 +#define GDEBUG 3 +#endif + +#define CR '\n' +#define ABORT_CHAR 0x03 +#ifdef NYQUIST +#define BREAK_CHAR 0x02 +#else +#define BREAK_CHAR 0x07 +#endif + +#define BREAK_LEVEL 1 +#define ABORT_LEVEL 2 + +#define read_to_eol(ch) if (ch != CR) { char temp[100]; ggets(temp); } + +extern char fileopen_name[]; +extern int abort_flag; +extern int redirect_flag; /* added by Ning Hu, Apr 2001 */ + +boolean get_ascii(char *c); /* polls for an ascii character */ +#ifdef DOTS_FOR_ARGS +/* was (defined(ITC_MACH) && defined(__STDC__)) || defined(MACINTOSH) || defined(AZTEC) || (defined(AMIGA) && defined(LATTICE)) || defined(UNIX_ITC) */ +void gprintf(long where, char *format, ...); /* general printf */ +#else +void gprintf(); +#endif + +char *ggets(char *str); /* general gets */ +int wait_ascii(void); /* a waiting version of get_ascii */ +void clean_exit(void); /* exit the program after cleaning up */ +void io_init(void); /* overall initialization */ +void abort_check(void); /* exit if aborted */ + +int check_aborted(void); /* looks to see if user typed ctrl-C */ + +int askbool(char *prompt, int deflt); +FILE *fileopen(char *deflt, char *extension, char *mode, char *prompt); +void readln(FILE *fp); +void gflush(void); +int gputchar(int c); +int ggetchar(); +char *ggets(char *str); +boolean ascii_input(char *c); +void unget_ascii(char c); +boolean check_ascii(void); + +#ifdef MACINTOSH +boolean get_file_info(char *filename, OSType *file_type, OSType *file_creator); +boolean put_file_info(char *filename, OSType file_type, OSType file_creator); +#endif + +#ifdef DONT_USE_CMT_IO +#define ggetchar getchar +#define ggets gets +#define gprintf fprintf +#define gputchar putchar +#define gprintf fprintf +#define gputchar putchar +#endif + +#ifdef MICROSOFT +void c_break(int sig); +#endif + diff --git a/comp-ide.bat b/comp-ide.bat new file mode 100644 index 0000000..eb1be8b --- /dev/null +++ b/comp-ide.bat @@ -0,0 +1,12 @@ +rem comp-ide.bat -- compile the jnyqide on Windows: just type comp-ide +rem +rem On windows, we compile everything but SpecialMacHandler.java +rem +echo ****COMPILING JNYQIDE****************************** +cd jnyqide +ren SpecialMacHandler.java SpecialMacHandler.hidden +javac *.java +ren SpecialMacHandler.hidden SpecialMacHandler.java +cd .. +rem jnyqide\jNyqIDE.jar +jar -cfm jnyqide\jNyqIDE.jar jnyqide/manifest.txt jnyqide/*.class diff --git a/convert.dsp b/convert.dsp new file mode 100644 index 0000000..c986d12 --- /dev/null +++ b/convert.dsp @@ -0,0 +1,153 @@ +# Microsoft Developer Studio Project File - Name="convert" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=convert - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "convert.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "convert.mak" CFG="convert - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "convert - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "convert - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "convert - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "convert - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "convert___Win32_Debug" +# PROP BASE Intermediate_Dir "convert___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "f:\tmp\convert-debug" +# PROP Intermediate_Dir "f:\tmp\convert-debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "convert - Win32 Release" +# Name "convert - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\snd\audiowin32.c +# End Source File +# Begin Source File + +SOURCE=.\snd\convert.c +# End Source File +# Begin Source File + +SOURCE=.\snd\ieeecvt.c +# End Source File +# Begin Source File + +SOURCE=.\snd\snd.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndcvt.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndheader.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndwin32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\snd\audiowin32.h +# End Source File +# Begin Source File + +SOURCE=.\snd\ieeecvt.h +# End Source File +# Begin Source File + +SOURCE=.\snd\snd.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndconfig.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndhead.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndheader.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndwin32.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/convert.dsw b/convert.dsw new file mode 100644 index 0000000..9cdea3f --- /dev/null +++ b/convert.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "convert"=.\convert.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/demos/allewis/cell_aut.lsp b/demos/allewis/cell_aut.lsp new file mode 100644 index 0000000..3342843 --- /dev/null +++ b/demos/allewis/cell_aut.lsp @@ -0,0 +1,83 @@ +;; cell_aut.lsp -- cellular automata for sound generation +;; originally by Ann Lewis +;; revised by Roger B. Dannenberg +;; March 2004 + +;; compute-update-rule -- compute the output given a rule and 3 inputs +;; +(defun compute-update-rule (rule a b c) + ;; this is the most interesting part of the whole program + ;; the rule has 8 bits. Use a, b, c to index the rule bits + ;; and determine the result. To do this, we want a bit in + ;; the right position, e.g. if a=0,b=1,c=1, then the index + ;; is 011 = 3, and we want a bit pattern with "1" in position 3: + ;; 00001000. Note that this is 2^3 = a*2^4 + b*2^2 + c*2^1. So + ;; we can test a, b, and c and multiply by 16, 4, and 2 to get + ;; the right bit pattern. Then we can "and" it with rule to + ;; get either zero or a non-zero as the result. + (let ((abc 1)) + (cond (a (setf abc 16))) + (cond (b (setf abc (* abc 4)))) + (cond (c (setf abc (* abc 2)))) + (setf rule (logand rule abc)) + (> rule 0))) + + +;; the main cellular automata implementation +(defun cell-aut (sound-object-list duration update-rule iter) + (let (prev current array-len score (now 0.0) tmp) + ; create and initialize current and prev bit lists + (setf array-len (length sound-object-list)) + (setf prev (make-array array-len)) + (setf current (make-array array-len)) + (setf prev (make-array array-len)) + (setf (aref prev (/ array-len 2)) t) + ; create the score by computing iter generations of the automata + (dotimes (i iter) + (dotimes (j array-len) + (princ (if (aref prev j) " X" " 0")) + ; push a note on the list for each "true" in the prev array + (if (aref prev j) + (push (list now duration (nth j sound-object-list)) score))) + (terpri) + ; compute current from prev using update-rule + ; first do endpoints, wrap-around style + (setf (aref current 0) + (compute-update-rule update-rule + (aref prev (- array-len 1)) (aref prev 0) (aref prev 1))) + (setf (aref current (- array-len 1)) + (compute-update-rule update-rule + (aref prev (- array-len 2)) (aref prev (- array-len 1)) + (aref prev 0))) + + ; then loop through everything else + ; want to cycle from 1 to array-len-2 + (dotimes (j (- array-len 2)) + (setf (aref current (+ j 1)) + (compute-update-rule update-rule + (aref prev j) (aref prev (+ j 1)) (aref prev (+ j 2)))) +) + ; set prev to current + (setf tmp prev) + (setf prev current) + (setf current tmp) + ; increment the time + (setf now (+ now duration))) + ;; the score is now in reverse order, so fix it + (setf score (reverse score)) + ;; now we have a score, render it to sound and return it: + (timed-seq score)) +) + +(defun cell-aut-major-scale () + ;; for testing, this creates an 8-note scale + ;; requires (load "pianosyn") to get the piano library + (let (scale offsets) + (setf offsets '(0 2 4 5 7 9 11 12)) + (dolist (p offsets) + (push (list 'piano-note-2 (+ A3 p) 100) scale)) + (reverse scale))) + +(defun cell-aut-demo () + (require-from piano-note-2 "pianosyn.lsp") + (play (scale 0.5 (cell-aut (cell-aut-major-scale) 0.2 30 80)))) diff --git a/demos/allewis/cellularautomata.htm b/demos/allewis/cellularautomata.htm new file mode 100644 index 0000000..fe7d559 --- /dev/null +++ b/demos/allewis/cellularautomata.htm @@ -0,0 +1,79 @@ +Cellular Automata +

Cellular Automata Example

+

Ann Lewis and Roger B. Dannenberg

+

This example is based on a class project by Ann Lewis.This project harnesses + the power of cellular automata for algorithmic composition. Cellular automata + have been applied to graphics and visual patterns as well as music. In this + work, the automaton consists of an array of boxes, where each box is initialized + to either black or white (on/off, 0/1). At every step the next row/generation + (represented visually as below the previous array) is computed from the first + array using an update rule on each array element. An update rule (that defines + the automaton itself) is simply a function from the array element's parent, + and the parent's left and right neighbors. This concept is illustrated here: +

+
	A1 A2 A3 ... 
+	B1 B2 B3 ... 
+

Let B2 be the element whose value is being computed. B2 is therefore dependent + on the values of A1, A2, and A3 only. An example of an update rule would be:

+
if A1 = A3 and A2 = 1 then B2 = 1, else B2 = 0
+

There are 2 possible values for each of A1, A2, and A3 which means there are + 2^3 = 8 possible configurations. And there are 2^8 = 256 possible functions + from A1, A2, and A3 to B2. Therefore there are only 256 possible update rules. + Note that the number of possible update rules is not dependent on the number + of elements in the array. The rules can be numbered from 0 to 255. In the picture + below, rule 30 is used to generate a series of rows, starting with a single + "one" in the first row.

+

+

Instead of B1 = 1 indicating that a box be colored black and B1 = 0 indicated + that a box be colored white, in the music model this will correspond to turning + certain sound objects on and off. For example, here we have an array of oscillators. +

+
Osc 60 Osc 65 Osc 67 Osc 70 Osc 75 Osc 76 Osc 79
+

If only the 1st and 3rd elements are "turned on" this would result in the + chord (sum (Osc 60) (Osc 67)). So each array, or level of the automata would + correspond to a chord, and the chord progression would change over time as the + automata developed.

+

This feature very versatile, so the user can specify the basic sound array, + the duration of each step, and which combining function to bring the activated + sounds together. This design allows the user to use any expression to create + sounds.

+

The main function, cell-aut, takes the following parameters:

+
    +
  1. an array of sound objects, specified using expressions to be evaluated
  2. +
  3. the duration of each time step (also the duration for computing sound objects)
  4. +
  5. the update rule to use on array evolution, specified by number (0 - 255)
  6. +
  7. the number of iterations/generations the automata should allow itself to + grow
  8. +
+

Some interesting rules to try are Wolram's two most famous rules: 30 (chaotic) + and 90 (fractal patterns).

+

Algorithm Outline

+

Here is an outline of the algorithm implemented in cell-aut.lsp.

+
    +
  1. create and initialize "current" and "previous" bit lists -- these should + have the same length as the sound array the user gave this function) -- potentially + there could be a feature here allowing the user to specify the initial state + of the array. +
  2. create and initialize the list of sounds to return +
  3. loop iter times +
      +
    1. get the list of currently activated sounds from the "previous" bit list + and extract the corresponding sounds from the sound array +
    2. combine this set of sounds with the combining function (specified by + the user), and add the resulting sound to the output list +
    3. compute the "current" bit list from the "previous" bit list using the + update rule iterated over all the elements -- this wraps around so that + endpoints are treated as being adjacent to each other +
    4. set the "previous" bit array to the "current" bit array +
    5. (end loop) +
    +
  4. return the output list of sounds +
+

Demo

+

The file demos/allewis/cell_aut.lsp includes the function cell-aut-demo + defined as follows:

+
(defun cell-aut-demo () 
+  (play (scale 0.5 (cell-aut (cell-aut-major-scale) 0.2 30 80))))
+

so you can run this to hear an example output from the cell-aut + function.

+

 

diff --git a/demos/allewis/cmusic_pres.ppt b/demos/allewis/cmusic_pres.ppt new file mode 100644 index 0000000..e3114c7 Binary files /dev/null and b/demos/allewis/cmusic_pres.ppt differ diff --git a/demos/allewis/rule30.jpg b/demos/allewis/rule30.jpg new file mode 100644 index 0000000..575eeb3 Binary files /dev/null and b/demos/allewis/rule30.jpg differ diff --git a/demos/arp.sal b/demos/arp.sal new file mode 100644 index 0000000..20e145a --- /dev/null +++ b/demos/arp.sal @@ -0,0 +1,99 @@ +;; arpeggiation examples +;; Roger B. Dannenberg + +;; An arpeggiator is a function that plays sequences of pitches in a pattern +;; The typical patterns are very much like the palindrome pattern generator +;; in Nyquist, so this example shows how to make arpeggiation patterns. + +;; A simple arpeggiation of a major-7th chord +;; +define function arp1() + begin + with pat = make-palindrome(list(c4, e4, g4, b4)) + exec score-play(score-gen(score-len: 17, ioi: 0.2, pitch: next(pat))) + end + +;; This will play the simple arpeggio: +;exec arp1() + +;; We can make an upward only arpeggiator using the cycle pattern: +;; +define function arp2() + begin + with pat = make-cycle(list(c4, e4, g4, b4)) + exec score-play(score-gen(score-len: 17, ioi: 0.2, pitch: next(pat))) + end + +;; This will play it: +;exec arp2() + +;; Arpeggios might sound a bit nicer with some legato or overlap, which +;; is easy to do by changing the duration (dur:) parameter: +;; +define function arp3() + begin + with pat = make-cycle(list(c4, e4, g4, b4)) + exec score-play(score-gen(score-len: 17, ioi: 0.2, dur: 0.4, + pitch: next(pat))) + end + +;; This will play it: +;exec arp3() + +;; It might be more useful to add some parameters. They are: +;; +;; pitches -- a list of pitches to arpeggiate +;; reps -- how many notes to generate +;; ioi -- inter-onset interval +;; dur -- a keyword parameter (optional), an ioi multiplier. Use 1 +;; to make the duration equal the ioi, use 2 for double the ioi +;; instr -- a keyword parameter (must be quoted), naming an instrument +;; +;; Any parameter may be a pattern. +;; Returns a score +;; +define function arp4(pitches, len, ioi, dur: 1, instr: quote(note)) + begin + with n = next(len), + pat = make-cycle(next(pitches)) + return score-gen(score-len: n, ioi: next(ioi), dur: next(dur), + name: next(instr), pitch: next(pat)) + end + +;; Since arp4 returns a score, you can play it like this: +; exec score-play(arp4(list(c4, e4, g4, b4, c5), 20, 0.15, 3)) + +;; This will play the simple arpeggio: +;exec arp4() + +;; Note: it might be nice to extend the parameters to let the user select +;; the arpeggiation style (up, down, up-down, up-down with elision), but +;; these can be specified just by writing out the full pattern, e.g. to +;; get up-down with elision, write list(c4, e4, g4, b4, c5, b4, g4, e4), +;; so I won't add that feature. + +;; Makeing sequences of arpeggios + +;; First define some pitch patterns: +define variable c7 = list(c4, e4, g4, bf4, c5, bf4, g4, e4), + bf7 = list(bf3, d4, f4, af4, bf4, af4, f4, d4), + af7 = list(af3, c4, ef4, gf4, af4, gf4, ef4, c4), + g7 = list(g3, b3, d4, f4, g4, f4, d4, b3) + +;; now call arp4 to make some scores and splice them together + +define function arp-seq() + begin + with score = nil + loop + for pitches in list(c7, bf7, af7, g7, c7) + for len in list(16, 16, 16, 16, 33) + set score = score-append(score, arp4(pitches, len, 0.13, 3)) + end + return score + end + +;; make the score and play it +exec score-play(arp-seq()) + + diff --git a/demos/arpeggiator.htm b/demos/arpeggiator.htm new file mode 100644 index 0000000..7ee0f35 --- /dev/null +++ b/demos/arpeggiator.htm @@ -0,0 +1,31 @@ + + + + + + Untitled Document + + +

+Arpeggiator Tutorial

+This page describes an arpeggiator example in Nyquist. +

What does it do?

+An arpeggiator plays a sequence of pitches over and over, usually +outlining a chord. +

How does it work?

+The file arp.sal has example code to create +arpeggiator effects. There are comments in the code to describe how it +works.
+

How can I use it?

+
SAL> load "arp.sal"
+Or, open demos/arp.sal using the Nyquist IDE and load the file with the +load button.
+
+You should hear a short piece. There are simpler examples in the code +-- read the comments in the code to see all the examples and to find +commands to try them out.
+
+ + diff --git a/demos/bandfx.htm b/demos/bandfx.htm new file mode 100644 index 0000000..862af9c --- /dev/null +++ b/demos/bandfx.htm @@ -0,0 +1,59 @@ + + + + + + Untitled Document + + + +

+Multiple Band Effects Tutorial

+This page describes how to use the bandfx library in Nyquist. +

+What does it do?

+The idea is very simple: separate the incoming signal into different frequency +bands. Apply an effect to each frequency band. +
For example, apply a delay, with longer delays at higher frequencies. +Then sum the outputs of the effects. In the delay example, +
the result will be something like a filter sweep -- the low frequencies +come out first, followed by increasingly higher frequencies. +

+How does it work?

+Frequency bands are separated using Nyquist's reson +filter. Although reson is not perfect for this job, it has the nice +
feature that there is a complementary areson filter that returns everything +removed by reson. We split off the lowest +
frequency band with reson, then apply areson to get the remainder of +the signal. We pass this through another reson +
tuned to the second band and use another areson to get the remainder. +Using a series of filters, we pull off all the +
band except for the last one, which is just whatever is left over. +

The function separate-into-bands constructs an array of frequency bands. +The function reconstruct-from-bands sums an +
array of frequency bands back into a single channel. Different functions +apply effects to the frequency band representation. +
Consult the code (see lib/bandfx.lsp) for details. You can use the +code as a template for creating your own multiple band effects. +

+How can I use it?

+ +
> (load "bandfx")
+ +
> (f2)
+ +
> (f3)
+ +
> (f4)
+ +
> (f5)
+The commands shown above will play some examples that are included in lib/bandfx.lsp. +You can read the code for +
a description of the functions and to see examples of their use. The +functions are also described in the Nyquist manual +
(see "multiple band effects" in the index). +

The manual also describes some ways this library might be extended. +Please contribute some examples if you find these effects useful. +
  + + diff --git a/demos/beginclip.jpg b/demos/beginclip.jpg new file mode 100644 index 0000000..feae664 Binary files /dev/null and b/demos/beginclip.jpg differ diff --git a/demos/demo-snd.aiff b/demos/demo-snd.aiff new file mode 100644 index 0000000..6ab7265 Binary files /dev/null and b/demos/demo-snd.aiff differ diff --git a/demos/demo.mid b/demos/demo.mid new file mode 100644 index 0000000..472dc6b Binary files /dev/null and b/demos/demo.mid differ diff --git a/demos/distortion.htm b/demos/distortion.htm new file mode 100644 index 0000000..915fa0d --- /dev/null +++ b/demos/distortion.htm @@ -0,0 +1,118 @@ + + + + + + Untitled Document + + + +

+Distortion Tutorial

+This page describes how to use the Nyquist shape function to achieve distortion. +

+Terminology

+First, some terminology: +
Clipping means that you limit the amplitude of samples, +e.g. +

sample_out = min(sample_in, 1.0),

+or, observing that you might want to limit negative excursions as well +as positive ones: +
sample_out = max(min(sample_in, 1.0), -1.0).
+This type of clipping is called hard clipping because the transition +from an undistorted one to a maximum or minimum value is instantaneous, +as if the signal hit a brick wall and can go no more. +

As you might guess, you can also have soft clipping where the +transition is more gradual, and that's what this tutorial is about. +

Before discussing soft clipping, let's introduce a few other terms. +Since clipping seems to be a way of limiting the values of +the signal or compressing the range of the signal, you might think +that clipping is a form of compressing or limiting; however, these terms +have special meanings in the audio processing world. +

Compression, or dynamics compression (not to +be confused with data compression) is a way of reducing the overall +range of soft to loud.
+To do dynamics compression, you generally detect the intensity or peak +level of a sound over a time scale of a few milliseconds, and then construct +a relatively smooth amplitude control that you apply to the signal. For +compression, the amplification goes down as the intensity of the input +goes up, so loud passages get (relatively) softer and soft passages get +(relatively) louder. (Dynamics expansion does just the opposite.) Limiters +work like compressors, but are designed to eliminate peaks -- conceptually, +there is no real difference, and products are often sold as "compressor/limiters". +See nyquist/lib/compress.lsp for an implementation. +

In some ways, soft clipping is like dynamics compression. Both reduce +the gain at high levels, but dynamics compression operates relatively slowly, +effectively turning the volume knob up and down, whereas clipping operates +on a sample-by-sample basis. The effect of clipping is to distort the input. +

In Nyquist, you use the shape function to implement clipping. shape +applies a function to each sample, where the function is specified by a +sound. The following is a typical function for soft clipping: +

+Notice how the function is essentially y=x at small amplitudes, so there +is no distortion for small signals, but at large input values, the function +becomes very non-linear. Also, notice that this is similar to the behavior +of real-life amplifiers, where small signals are undistorted, but at some +point, the power limits of the amplifier clip the output signal. +

The Nyquist shape function is allows you to specify any function you +like using a sound. Therefore you can use any of the Nyquist primitives +to construct the function. Since a sound is a function of time, where time +must be non-negative, how do you specify a shape function over a range +that includes negative values? The trick is that shape takes an offset +parameter that shifts the whole function to the left (in the -y direction). +Note also that whereas a Nyquist sound is generally regarded as a function +of time, shape treats the sound as just a real-valued function. +

The typical way to use shape is to create some increasing signal over +the interval [0,2] that crosses zero at 1.0. Then you give 1.0 as the offset +(3rd parameter). The result will look something like the graph above. +

Implementation

+In the figure above, I used a sine function to generate the smooth curve. Here is an implementation of distortion in Nyquist using the sine curve: +
+
(setf distortion 
+      (osc (hz-to-step 0.25) 2.01 *SINE-TABLE* -90.0))
+(defun distort (snd)
+    (shape snd distortion 1.0)) 
+
+(play (distort (mult 15.0 (ramp 4) (osc c4 4))))
+
+
+

Even though I am an expert, and I have done this before, it still took +me a few tries to get right. Here's a step-by-step explanation: +

    +
  • I used osc to generate a sinusoid so I could control the initial phase. +
  • I set the osc duration to 2 because I want the table to go from +0 to 2 (after which we'll shift it back to [-1, +1]), but 2 is not enough because the interval [0,2] is closed, which +means I need one extra sample. I used 2.01 to be conservative. +
  • I specified *SINE-TABLE*, the default value, because the table +parameter comes before the phase parameter. +
  • I specified the phase to get the sine curve to go through zero +in the middle of the generated function. +
  • I assigned this to the variable distortion so I could plot it; try: +
    (s-plot (force-srate 100 distortion))
    +
  • Finally, I put in a tone that ramps up from zero to 15 in amplitude +to cause some serious clipping. The output amplitude is limited to 1. +
+

Note that the input to shape is pre-clipped to the range +[-1, +1] so you only need to specify the table from [0, 2] if the origin (third parameter to shape) is 1.0. If you specify a little extra, as +in this example, it will be ignored. +

The Output

+

+Look +at the generated waveform to observe the soft clipping effect. Here we see the beginning of the output, where the input amplitude is low and there is very little distortion: +

+

+ +
+But when the input amplitude becomes large, the clipping becomes substantial. This plot is at the same scale, but taken from a later portion of the generated output. Remember that the input at this point is a high-amplitude sinusoid:

+

+ +
+Also notice +that the distortion is symetrical, so it generates even harmonics. If you +put in an asymetric function, you'll get odd harmonics too. Note that at +soft levels, I actually get some gain from this function. +

Generated by Roger Dannenberg (roger.dannenberg@cs.cmu.edu) Feb, +2004. + + + diff --git a/demos/examples.lsp b/demos/examples.lsp new file mode 100644 index 0000000..58fd9ae --- /dev/null +++ b/demos/examples.lsp @@ -0,0 +1,424 @@ +;; examples.lsp -- these are from the Nyquist Manual examples + +(defun ex1 () + (play (osc 60))) + +(defun ex2 () + (play (scale 0.5 (osc 60)))) + +; build-harmonic is already defined in nyquist.lsp +; +;(defun build-harmonic (n) (snd-sine 0 n tablesize 1)) + +(defun mkwave () + (setf *table* (sim (scale 0.5 (build-harmonic 1.0 2048)) + (scale 0.25 (build-harmonic 2.0 2048)) + (scale 0.125 (build-harmonic 3.0 2048)) + (scale 0.062 (build-harmonic 4.0 2048)))) + (setf *table* (list *table* (hz-to-step 1) T))) + +(cond ((not (boundp '*mkwave*)) + (mkwave) + (setf *mkwave* t))) + +(defun note (pitch dur) + (osc pitch dur *table*)) + +(defun ex3 () + (play (seq (note c4 i) + (note d4 i) + (note f4 i) + (note g4 i) + (note d4 q)))) + +(defun env-note (p) + (mult (note p 1.0) + (env 0.05 0.1 0.5 1.0 0.5 0.4))) + +(defun ex4 () + (play (env-note c4))) + + +(defun ex5 () + (play (seq (stretch 0.25 + (seq (env-note c4) + (env-note d4))) + (stretch 0.5 + (seq (env-note f4) + (env-note g4))) + (env-note c4)))) + +(defun ex6 () + (play (seq (note c4 q) (note d4 i)))) + + +(defun ex7 () + (play (scale 0.5 (sim (note c4 q) (note d4 i))))) + +;; previous versions could not get current-path to locate demo-snd.aiff... +;(format t "~%examples.lsp tries to load demo-snd.aiff from the~%") +;(format t "default sound file directory, which is stored in~%") +;(format t "the variable *default-sf-dir*. The current value is:~%") +;(format t "\"~A\". If you get an error immediately, you should~%" +; *default-sf-dir*) +;(format t "either set *default-sf-dir* or copy demo-snd.aiff~%") +;(format t "where Nyquist will find it.~%") + +(display "examples.lsp" (current-path)) + +(if (not (boundp 'a-snd)) + (setf a-snd (s-read (strcat (current-path) + "demo-snd.aiff")))) + +(defun ex8 () + (play a-snd)) + +(defun ex9 () + (play (seq (cue a-snd) (cue a-snd)))) + +(defun ex10 () + (play (sim (at 0.0 (cue a-snd)) + (at 0.7 (cue a-snd)) + (at 1.0 (cue a-snd)) + (at 1.2 (cue a-snd))))) + +(defun ex11 () + (play (sim (cue a-snd) + (loud 6.0 (at 3.0 (cue a-snd)))))) + +(defun ex12 () + (play (loud 6.0 (sim (at 0.0 (cue a-snd)) + (at 0.7 (cue a-snd)))))) + +(defun snds (dly) + (sim (at 0.0 (cue a-snd)) + (at 0.7 (cue a-snd)) + (at 1.0 (cue a-snd)) + (at (+ 1.2 dly) (cue a-snd)))) + +(defun ex13 () + (play (snds 0.1))) + +(defun ex14 () + (play (loud 0.25 (stretch 0.9 (snds 0.3))))) + +(defun ex15 () + (play (sound-srate-abs 44100.0 (osc c4)))) + +(defun tone-seq () + (seqrep (i 16) + (stretch 0.25 (osc-note c4)))) + +(defun pitch-rise () (stretch 4.0 (scale 16 (ramp)))) + +(defun chromatic-scale () + (transpose (pitch-rise) (tone-seq))) + +(defun ex16 () + (play (chromatic-scale))) + +(defun ex17 () + (play (sustain (stretch 4 (sum 0.2 (ramp))) + (chromatic-scale)))) + +(defun warper () + (pwl .25 .4 .75 .6 1.0 1.0 2.0 2.0 2.0)) + +(defun warp4 () (stretch 4 (scale 4 (warper)))) + +(defun ex18 () + (play (warp (warp4) (tone-seq)))) + +; note: as explained in the manual, the following is NOT +; the solution to a fixed duration/variable tempo sequence: +; +(defun tone-seq-2 () + (seqrep (i 16) + (stretch-abs 0.25 (osc-note c4)))) + +(defun ex19 () + (play (warp (warp4) (tone-seq-2)))) + +; here is the proper solution (vs. ex19): +; +(defun tone-seq-3 () + (seqrep (i 16) + (set-logical-stop + (stretch-abs 0.25 (osc-note c4)) + 0.25))) + +(defun ex20 () + (play (warp (warp4) (tone-seq-3)))) + +(defun ex21 () + (play (warp (warp4) + (transpose (pitch-rise) (tone-seq))))) + +(defun ex22 () + (play (warp (warp4) + (transpose (control-warp (get-warp) + (warp-abs nil (pitch-rise))) + (tone-seq))))) + +(defun ex23 () + (play (force-srate *default-sound-srate* (stretch 3.0 (sound a-snd))))) + +(defun down () + (force-srate *default-sound-srate* + (seq (stretch 0.2 (sound a-snd)) + (stretch 0.3 (sound a-snd)) + (stretch 0.4 (sound a-snd)) + (stretch 0.5 (sound a-snd)) + (stretch 0.6 (sound a-snd))))) + +(defun ex24 () (play (down))) + +(defun up () + (force-srate *default-sound-srate* + (seq (stretch 0.5 (sound a-snd)) + (stretch 0.4 (sound a-snd)) + (stretch 0.3 (sound a-snd)) + (stretch 0.2 (sound a-snd))))) + +(defun ex25 () + (play (seq (down) (up) (down)))) + +(defun ex26 () + (s-save a-snd 1000000000 "./a-snd-file.snd") + (play-file "./a-snd-file.snd") + (system "rm ./a-snd-file.snd")) + +(defun ex27 () + (setf my-sound-file "./a-snd-file.snd") + (s-save a-snd 1000000000 my-sound-file) + (play-file my-sound-file) + (system (strcat "rm " my-sound-file))) + +(defun ex28 () + ; normalize in memory. First, assign the sound to a variable so + ; it will be retained: + (setf mysound (sim (osc c4) (osc c5))) + ; now compute the maximum value (ny:all is a 1 giga-samples, you may want a + ; smaller constant if you have less than 4GB of memory :-): + (setf mymax (snd-max mysound NY:ALL)) + (display "Computed max" mymax) + ; now write out and play the sound from memory with a scale factor: + (play (scale (/ 1.0 mymax) mysound))) + +(defun ex29 () + ; if you don't have space in memory, here's how to do it: + (defun myscore () (sim (osc c4) (osc c5))) + ; compute the maximum, don't forget the quote!: + (setf mymax (snd-max '(myscore) NY:ALL)) + (display "Computed max" mymax) + ; now we know the max, but we don't have a the sound (it was garbage + ; collected and never existed all at once in memory). Compute the sound + ; again, this time with a scale factor:] + (play (scale (/ 1.0 mymax) (myscore)))) + +(defun ex30 () + (play (fmosc c4 (pwl 0.1)))) + +(defun ex31 () + (play (fmosc c4 (pwl 0.5)))) + +(defun ex32 () + (play (fmosc c4 (pwl 0.5 (step-to-hz c4) 0.501)))) + +(defun ex33 () + (setf *fm-voice* (list + (extract 0.110204 0.13932 (cue a-snd)) + 24.848422 + T)) + (play (fmosc cs2 (pwl 0.5 (step-to-hz cs2) 0.501) + *fm-voice* 0.0))) + +(defun sweep (delay pitch-1 sweep-time pitch-2 hold-time) + (let ((interval (- (step-to-hz pitch-2) + (step-to-hz pitch-1)))) + (pwl delay 0.0 + ; sweep from pitch 1 to pitch 2 + (+ delay sweep-time) interval + ; hold until about 1 sample from the end + (+ delay sweep-time hold-time -0.0005) interval + ; quickly ramp to zero (pwl always does this, + ; so make it short) + (+ delay sweep-time hold-time)))) + + +(defun ex34 () + (play (fmosc cs2 (sweep 0.1 cs2 0.6 gs2 0.5) + *fm-voice* 0.0))) + +(defun ex35 () + (play (fmosc cs2 (scale 10.0 (lfo 6.0)) + *fm-voice* 0.0))) + +(defun ex36 () + (let (modulator) + (setf modulator (mult (pwl 1.0 1000.0 1.0005) + (osc c4))) + (play (fmosc c4 modulator)))) + +;;; FINDING ZERO CROSSINGS, SND-SAMPLES + +(setf max-samples-for-zeros 1000) + +(defun zeros (snd) + ; start by getting the samples, only take 1000 samples max + (prog ((s (snd-samples snd max-samples-for-zeros)) + newsign sign n len result result2 starttime srate) + ; go through the array looking for zero crossings + (setf len (length s)) + ; stop if there are no samples + (if (= len 0) (return nil)) + (setf sign (> 0.0 (aref s 0))) + ; get the start time and sample rate of the sound for use below + (setf starttime (car (snd-extent snd max-samples-for-zeros))) + (setf srate (snd-srate snd)) + (setf n 1) + loop + (if (>= n len) (go done)) + (setf newsign (> 0.0 (aref s n))) + (if (not (eq sign newsign)) (setf result (cons n result))) + (setf sign newsign) + (setf n (1+ n)) + (go loop) + done ; now we have the zero crossings, convert them to times + (dolist (num result) + ; return the time of the zero crossing, which is the start time + of the snd plus the sample number / srate + + (setf result2 (cons (+ starttime (/ num srate)) + result2))) + + (return result2))) + +(defun ex37 () + ; extract a short piece of this sample + (setf short (extract 0.1 0.14 (cue a-snd))) + (setf z (zeros short)) + (format t "Zero crossings from a-snd: ~A~%" z)) + + +; find the differences between zero crossings reported by zeros +; print the result in terms of samples for readability +; +(defun periods (lis short) + (prog (result prev srate) + (if (null lis) (return nil)) + (setf srate (snd-srate short)) + loop + (setf prev (car lis)) + (setf lis (cdr lis)) + (if (null lis) (return (reverse result))) + (setf result (cons (* srate (- (car lis) prev)) result)) + (go loop))) + +(defun ex38 () + ; ex38 depends upon z, set by (ex37) + (cond ((not (boundp 'z)) (ex37))) + (setf p (periods z short)) + (format t "The intervals (in samples) between zero crossings are: ~%~A~%" p)) + + +; build a wavetable using zero crossing information +; +; I interactively played with the data and decided to extract from the +; 5th period to the 21st period (these had 86 and 87 samples each and +; seem to indicate some kind of periodicity). The 1st period measures +; from the zeroth zero crossing to the first, so the 5th period measures +; from the 4th zero crossing to the 5th. I'll arbitrarily take +; the 4th and 20th zero crossing times (the 5th and 20th should work as +; well), and from the data, this looks like 2 waveform periods. +; This is very clear if you plot the data. +; +; arguments are: +; snd - the sound to extract from +; zeros - the result of (zeros snd) +; start - the number of the starting zero crossing +; stop - the number of the ending zero crossing +; n - number of periods contained in the extracted sound +; +(defun extract-table (snd zeros start stop n) + (let (starttime extent hz) + ; Start by shifting snd to time zero: + (setf starttime (car (snd-extent snd max-samples-for-zeros))) + (setf snd (at (- starttime) (cue snd))) + + (format t "~A~%" snd) + ; also get the start and stop times and shift them: + (setf start (- (nth start zeros) starttime)) + (setf stop (- (nth stop zeros) starttime)) + + (format t "table ~A start ~A stop ~A~%" snd start stop) + + ; now extract the samples of interest, note that we are + ; overwriting our pointer to the snd argument + (setf snd (extract start stop (cue snd))) + (format t "table now ~A~%" snd) + + ; now we need to figure out the pitch this sound would represent + ; when played at its samplerate. The pitch in hz is 1 / duration, + ; and duration is the extent of the sound / n. Therefore, take + ; n/extent + (setf extent (snd-extent snd max-samples-for-zeros)) + (setf hz (/ n (- (cadr extent) (car extent)))) + ; an osc table is a list of the sound, pitch number, and T (periodic) + (list snd (hz-to-step hz) T))) + + +(defun ex39 () + ; try it out + (setf *a-voice* (extract-table short z 4 20 2)) + ; now use the table with an oscillator + (play (osc c3 1.0 *a-voice* ))) + +(defun ex40 () + ; play it at its normal pitch + (play (osc (cadr *a-voice*) 1.0 *a-voice*))) + +(defun ex41 () + (play (noise))) + +(defun ex42 () + (play (lp (noise) 1000.0))) + +(defun ex43 () + (play (hp (noise) 1000.0))) + +; low pass sweep from 100 hz to 2000 hz +(defun ex44 () + (play (lp (noise) (pwl 0.0 100.0 1.0 2000.0 1.0)))) + +; high pass sweep from 50 hz to 4000 hz +(defun ex45 () + (play (hp (noise) (pwl 0.0 50.0 1.0 4000.0 1.0)))) + +; band pass at 500 hz, 20 hz bandwidth +(defun ex46 () + (play (reson (scale 10.0 (noise)) 500.0 20.0 1))) + +; band pass sweep from 100 to 1000 hz, 20 hz bandwidth +(defun ex47 () + (play (reson (scale 0.04 (noise)) + (pwl 0.0 200.0 1.0 1000.0 1.0) 20.0))) + +(format t "\nType (ex1) through (ex47) to run these examples.\n") +(format t "See demos/stktest.lsp for more simple sound examples.\n") +(format t "\nI'm turning off Auto-normalization. See AUTONORM-ON\n") +(format t "in the documentation for an explanation:\n\n") +(autonorm-off) + +(defun ex-all () + (format t + "Warning: turning automatic normalization feature off~%") + (autonorm-off) + (dotimes (i 47) + (let ((j (+ i 1)) fn) + (setf fn (intern (format nil "EX~A" j))) + (setf fn (list fn)) + (format t "~A~%" fn) + (eval fn)))) + +(format t "\n(ex-all) will compute and play all examples for testing purposes.\n") diff --git a/demos/examples.sal b/demos/examples.sal new file mode 100644 index 0000000..c746628 --- /dev/null +++ b/demos/examples.sal @@ -0,0 +1,518 @@ +;; examples.lsp -- these are from the Nyquist Manual examples + +define function ex1() + play osc(60) + +define function ex2() + play 0.5 * osc(60) + +; build-harmonic is already defined in nyquist.lsp +; +;(defun build-harmonic (n) (snd-sine 0 n tablesize 1)) + +define function mkwave() + begin + set *table* = 0.5 * build-harmonic(1.0, 2048) + + 0.25 * build-harmonic(2.0, 2048) + + 0.125 * build-harmonic(3.0, 2048) + + 0.0625 * build-harmonic(4.0, 2048) + set *table* = list(*table*, hz-to-step(1.0), #t) + end + + +if ! boundp(quote(*mkwave*)) then + begin + exec mkwave() + set *mkwave* = #t + end + + +define function my-note(pitch, dur) + return osc(pitch, dur, *table*) + + +define function ex3() + play seq(my-note(c4, i), my-note(d4, i), my-note(f4, i), + my-note(g4, i), my-note(d4, q)) + + +define function env-note(p) + return my-note(p, 1.0) * + env(0.05, 0.1, 0.5, 1.0, 0.5, 0.4) + + +define function ex4() + play env-note(c4) + + +define function ex5() + play seq(seq(env-note(c4), env-note(d4)) ~ 0.25, + seq(env-note(f4), env-note(g4)) ~ 0.5, + env-note(c4)) + + +define function ex6() + play seq(my-note(c4, q), my-note(d4, i)) + + +define function ex7() + play 0.5 * sim(my-note(c4, q), my-note(d4, i)) + +;; previous versions could not get current-path to locate demo-snd.aiff... +;(format t "~%examples.lsp tries to load demo-snd.aiff from the~%") +;(format t "default sound file directory, which is stored in~%") +;(format t "the variable *default-sf-dir*. The current value is:~%") +;(format t "\"~A\". If you get an error immediately, you should~%" +; *default-sf-dir*) +;(format t "either set *default-sf-dir* or copy demo-snd.aiff~%") +;(format t "where Nyquist will find it.~%") + +set a-snd = s-read(strcat(current-path(), "demo-snd.aiff")) + + +define function ex8() + play a-snd + + +define function ex9() + play seq(cue(a-snd), cue(a-snd)) + + +define function ex10() + play sim(cue(a-snd) @ 0.0, + cue(a-snd) @ 0.7, + cue(a-snd) @ 1.0, + cue(a-snd) @ 1.2) + + +define function ex11() + play sim(cue(a-snd), + loud(6.0, cue(a-snd) @ 3)) + + +define function ex12() + play loud(6.0, sim(cue(a-snd) @ 0.0, + cue(a-snd) @ 0.7)) + + +define function snds(dly) + return sim(cue(a-snd) @ 0.0, + cue(a-snd) @ 0.7, + cue(a-snd) @ 1.0, + cue(a-snd) @ (1.2 + dly)) + + +define function ex13() + play snds(0.1) + + +define function ex14() + play loud(0.25, snds(0.3) ~ 0.9) + + +define function ex15() + play sound-srate-abs(44100.0, osc(c4)) + + +define function tone-seq() + return seqrep(i, 16, + osc-note(c4) ~ 0.25) + + +define function pitch-rise() + ; pitch-rise turns tone-seq into a chromatic scale + ; through transposition + ; override sustain to avoid changing ramp duration + return sustain-abs(1.0, 16 * ramp() ~ 4) + + +define function chromatic-scale() + return transpose(pitch-rise(), tone-seq()) + + +define function ex16() + play chromatic-scale() + + +define function ex17() + play sustain((0.2 + ramp()) ~ 4, + chromatic-scale()) + + +define function warper() + ; between 0 and 1, warper goes slow/fast/slow, then + ; it adds extra 1-to-1 mapping from 1 to 2, which is + ; just "padding" to avoid numerical problems near 1.0 + return pwl(0.25, .4, .75, .6, 1.0, 1.0, 2.0, 2.0, 2.0) + + +define function warp4() + ; stretch by 4 and scale by 4: now we're warping + ; a 4 second sequence within a 4 second duration + return 4 * warper() ~ 4 + + +define function ex18() + play warp(warp4(), tone-seq()) + + +; note: as explained in the manual, the following is NOT +; the solution to a fixed duration/variable tempo sequence: +; +define function tone-seq-2 () + return seqrep(i, 16, + osc-note(c4) ~~ 0.25) + + +define function ex19() + play warp(warp4(), tone-seq-2()) + +; here is the proper solution (vs. ex19): +; +define function tone-seq-3() + return seqrep(i, 16, + set-logical-stop(osc-note(c4) ~~ 0.25, 0.25)) + + +define function ex20() + play warp(warp4(), tone-seq-3()) + + +define function ex21() + play warp(warp4(), + transpose(pitch-rise(), tone-seq())) + + +define function ex22() + play warp(warp4(), + transpose(control-warp(get-warp(), + warp-abs(nil, pitch-rise())), + tone-seq())) + + +if not(boundp(quote(a-snd))) then + set a-snd = s-read("demo-snd.aiff") + + +define function ex23() + play force-srate(*default-sound-srate*, sound(a-snd) ~ 3.0) + +define function down() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.2, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.6)) + + +define function ex24() + play down() + +define function up() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.5, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.2)) + + +define function ex25() + play seq(down(), up(), down()) + + +define function ex26() + begin + exec s-save(a-snd, 1000000000, "./a-snd-file.snd") + play "./a-snd-file.snd" + exec system("rm ./a-snd-file.snd") + end + + +define function ex27() + begin + set my-sound-file = "./a-snd-file.snd" + exec s-save(a-snd, 1000000000, my-sound-file) + exec play-file(my-sound-file) + exec system(strcat("rm ", my-sound-file)) + end + + +; note that Nyquist's "Autonorm" facility probably makes this example +; superfluous +define function ex28() + begin + ; normalize in memory. First, assign the sound to a variable so + ; it will be retained: + set mysound = sim(osc(c4), osc(c5)) + ; now compute the maximum value (ny:all is a 1 giga-samples, you may want a + ; smaller constant if you have less than 4GB of memory :-): + set mymax = snd-max(mysound, NY:ALL) + display "Computed max", mymax + ; now write out and play the sound from memory with a scale factor: + play mysound * (0.9 / mymax) + end + + +define function myscore() + return sim(osc(c4), osc(c5)) + + +define function ex29() + begin + ; if you don't have space in memory, here's how to do it: + ; Compute the maximum. This is a bit tricky in SAL because snd-max + ; is looking for an expression (in LISP) to evaluate, not a sound. + ; Use list and quote to create the LISP expression '(myscore): + set mymax = snd-max(list(quote(myscore)), NY:ALL) + display "Computed max", mymax + ; now we know the max, but we don't have a the sound (it was garbage + ; collected and never existed all at once in memory). Compute the sound + ; again, this time with a scale factor:] + play myscore() * (0.9 / mymax) + end + + +define function ex30() + play fmosc(c4, pwl(0.1)) + + +define function ex31() + play fmosc(c4, pwl(0.5)) + + +define function ex32() + play fmosc(c4, pwl(0.5, step-to-hz(c4), 0.501)) + + +define function ex33() + begin + set *fm-voice* = list(extract(0.110204, 0.13932, cue(a-snd)), + 24.848422, + #T) + play fmosc(cs2, pwl(0.5, step-to-hz(cs2), 0.501), + *fm-voice*, 0.0) + end + + +define function sweep(delay, pitch-1, sweep-time, pitch-2, hold-time) + begin + with interval = step-to-hz(pitch-2) - step-to-hz(pitch-1) + return pwl(delay, 0.0, + ; sweep from pitch 1 to pitch 2 + delay + sweep-time, interval, + ; hold until about 1 sample from the end + delay + sweep-time + hold-time - 0.0005, interval, + ; quickly ramp to zero (pwl always does this, + ; so make it short) + delay + sweep-time + hold-time) + end + + +define function ex34() + play fmosc(cs2, sweep(0.1, cs2, 0.6, gs2, 0.5), + *fm-voice*, 0.0) + + +define function ex35() + play fmosc(cs2, 10.0 * lfo(6.0), *fm-voice*, 0.0) + + +define function ex36() + begin + with modulator + set modulator = pwl(1.0, 1000.0, 1.0005) * + osc(c4) + play fmosc(c4, modulator) + end + + +;;; FINDING ZERO CROSSINGS, SND-SAMPLES + +set max-samples-for-zeros = 1000 + +define function zeros(snd) + begin + ; start by getting the samples, only take 1000 samples max + with s = snd-samples(snd, max-samples-for-zeros), + newsign, sign, n, len, result, result2, starttime, srate + ; go through the array looking for zero crossings + set len = length(s) + ; stop if there are no samples + if len = 0 then return nil + set sign = 0.0 > s[0] + ; get the start time and sample rate of the sound for use below + set starttime = car(snd-extent(snd, max-samples-for-zeros)) + set srate = snd-srate(snd) + set n = 1 + loop + until n >= len + set newsign = 0.0 > s[n] + if not(eq(sign, newsign)) then + set result = cons(n, result) + set sign = newsign + set n += 1 + end + ; now we have the zero crossings, convert them to times + loop + with result2 = nil + for num in result + ; return the time of the zero crossing, which is the start time + ; of the snd plus the sample number / srate + set result2 = cons(starttime + num / srate, result2) + finally return result2 + end + end + + +define function ex37() + begin + ; extract a short piece of this sample + set short = extract(0.1, 0.14, cue(a-snd)) + set z = zeros(short) + exec format(t, "Zero crossings from a-snd: ~A~%", z) + end + + +; find the differences between zero crossings reported by zeros +; print the result in terms of samples for readability +; +define function periods(lis, short) + begin + with result, prev, srate + if null(lis) then return nil + set srate = snd-srate(short) + loop + set prev = car(lis) + set lis = cdr(lis) + if null(lis) then return reverse(result) + set result = cons(srate * car(lis) - prev, result) + end + end + +define function ex38() + ; ex38 depends upon z, set by (ex37) + begin + if not(boundp(quote(z))) then exec ex37() + set p = periods(z, short) + exec format(t, + "The intervals (in samples) between zero crossings are: ~%~A~%", + p) + end + + +; build a wavetable using zero crossing information +; +; I interactively played with the data and decided to extract from the +; 5th period to the 21st period (these had 86 and 87 samples each and +; seem to indicate some kind of periodicity). The 1st period measures +; from the zeroth zero crossing to the first, so the 5th period measures +; from the 4th zero crossing to the 5th. I'll arbitrarily take +; the 4th and 20th zero crossing times (the 5th and 20th should work as +; well), and from the data, this looks like 2 waveform periods. +; This is very clear if you plot the data. +; +; arguments are: +; snd - the sound to extract from +; zeros - the result of (zeros snd) +; start - the number of the starting zero crossing +; stop - the number of the ending zero crossing +; n - number of periods contained in the extracted sound +; +define function extract-table(snd, zeros, start, stop, n) + begin + with starttime, extent, hz + ; Start by shifting snd to time zero: + set starttime = car(snd-extent(snd, max-samples-for-zeros)) + set snd = cue(snd) @ - starttime + + exec format(t, "~A~%", snd) + ; also get the start and stop times and shift them: + set start = nth(start, zeros) - starttime + set stop = nth(stop, zeros) - starttime + + exec format(t, "table ~A start ~A stop ~A~%", snd, start, stop) + + ; now extract the samples of interest, note that we are + ; overwriting our pointer to the snd argument + set snd = extract(start, stop, cue(snd)) + exec format(t, "table now ~A~%", snd) + + ; now we need to figure out the pitch this sound would represent + ; when played at its samplerate. The pitch in hz is 1 / duration, + ; and duration is the extent of the sound / n. Therefore, take + ; n/extent + set extent = snd-extent(snd, max-samples-for-zeros) + set hz = n / (cadr(extent) - car(extent)) + ; an osc table is a list of the sound, pitch number, and T (periodic) + return list(snd, hz-to-step(hz), #t) + end + + +define function ex39() + begin + ; try it out + set *a-voice* = extract-table(short, z, 4, 20, 2) + ; now use the table with an oscillator + play osc(c3, 1.0, *a-voice*) + end + + +define function ex40() + ; play it at its normal pitch + play osc(cadr(*a-voice*), 1.0, *a-voice*) + + +define function ex41() + play noise() + + +define function ex42() + play lp(noise(), 1000.0) + + +define function ex43() + play hp(noise(), 1000.0) * 0.5 + + +; low pass sweep from 100 hz to 2000 hz +define function ex44() + play lp(noise(), pwl(0.0, 100.0, 1.0, 2000.0, 1.0)) + + +; high pass sweep from 50 hz to 4000 hz +define function ex45() + play hp(noise(), pwl(0.0, 50.0, 1.0, 4000.0, 1.0)) * 0.5 + + +; band pass at 500 hz, 20 hz bandwidth +define function ex46() + play reson(10.0 * noise(), 500.0, 20.0, 1) + + +; band pass sweep from 100 to 1000 hz, 20 hz bandwidth +define function ex47() + play reson(0.04 * noise(), + pwl(0.0, 200.0, 1.0, 1000.0, 1.0), + 20.0) + + +exec format(t, "\nType (ex1) through (ex47) to run these examples.\n") +exec format(t, "See demos/stktest.lsp for more simple sound examples.\n") +exec format(t, "\nI'm turning off Auto-normalization. See AUTONORM-ON\n") +exec format(t, "in the documentation for an explanation:\n\n") +exec autonorm-off() + +define function ex-all () + begin + exec format(t, "Warning: turning automatic normalization feature off~%") + exec autonorm-off() + loop + for i from 1 to 47 + for fn = list(intern(format(nil, "EX~A", i))) + exec format(t, "~A~%", fn) + exec eval(fn) + end + end + + +exec format(t, "\n\"exec ex-all()\" in SAL or (ex-all) in Lisp will compute and play all examples for testing purposes.\n") diff --git a/demos/examples_home.htm b/demos/examples_home.htm new file mode 100644 index 0000000..7339a5f --- /dev/null +++ b/demos/examples_home.htm @@ -0,0 +1,116 @@ + + + + + + Nyquist Examples and Tutorials + + +

+Nyquist Examples and Tutorials

+ + + diff --git a/demos/fft_demo.lsp b/demos/fft_demo.lsp new file mode 100644 index 0000000..f0e0f73 --- /dev/null +++ b/demos/fft_demo.lsp @@ -0,0 +1,176 @@ +;; this code is extracted from fft_tutorial.htm +;; +;; Roger B. Dannenberg, 2001 +;; +;; Please see fft_tutorial.htm for more in-depth comments and explanations. +;; + +(setf fft1-class (send class :new '(sound length skip))) + +(send fft1-class :answer :next '() '( + (snd-fft sound length skip nil))) + +(send fft1-class :answer :isnew '(snd len skp) '( + (setf sound snd) + (setf length len) + (setf skip skp))) + +(defun make-fft1-iterator (sound length skip) + (send fft1-class :new (snd-copy sound) length skip)) + +;; create a 1-second sinusoid with points samples at cycles hz: +(defun short-sine (points cycles) + (control-srate-abs points (lfo cycles))) + +(defun fft-test () + (let (fft-iter) + ;; signal will have 4 cycles in 32 points: + (setf fft-iter (make-fft1-iterator (short-sine 32 4) 32 32)) + (display "fft-test" (send fft-iter :next)))) + +(defun ifft-test () + (let (fft-iter ifft-snd) + (setf fft-iter (make-fft1-iterator (short-sine 32 4) 32 32)) + (setf ifft-snd (snd-ifft 0 32 fft-iter 32 NIL)) + (display "fft-ifft" (snd-length ifft-snd 200)) + (display "fft-ifft" (snd-samples ifft-snd 200)) )) + +(defun file-fft1 (filename frame-length skip) + (make-fft1-iterator (s-read filename) frame-length skip)) + +(defun play-fft1 (iterator skip) + (play (snd-ifft 0 *sound-srate* iterator skip NIL))) + +;; a convenient sound file name (change this to one of your soundfiles): +(setf sfn "/Users/rbd/class/icm2009/sounds/talking.wav") + +(defun file-test () (play-fft1 (file-fft1 sfn 512 512) 512)) + + +(setf fft-hp-class (send class :new '(source bins))) + +(send fft-hp-class :answer :next '() '( + (let ((frame (send source :next))) + (cond (frame + (dotimes (i bins) + (setf (aref frame i) 0.0)))) + frame))) + +(send fft-hp-class :answer :isnew '(s b) '( + (setf source s) + (setf bins b))) + +(defun make-fft-hp (source bins) + (send fft-hp-class :new source bins)) + +(defun hp-test () + (play-fft1 (make-fft-hp (file-fft1 sfn 512 512) 11) 512)) + +(defun fm-tone (step mi1 mi2 mi3) + (let ((hz (step-to-hz step))) + (setf mi1 (* mi1 hz)) + (setf mi2 (* mi2 hz)) + (setf mi3 (* mi3 hz)) + (fmosc c4 (partial step + (control-srate-abs *sound-srate* + (pwl 0 mi1 0.5 mi2 1 mi3 1)))))) + +(defun mod-snd (sfn) + ; to get duration of file, open it and look at the 6th element + ; of the extra return values in *rslt* + (stretch (nth 6 (progn (s-read sfn) *rslt*)) + (sum + (fm-tone c3 15 20 15) ;; adjust FM parameters here + (fm-tone d3 15 20 15) ;; adjust FM parameters here + (fm-tone e3 15 20 15)))) ;; adjust FM parameters here + +(setf fft-modulator-class (send class :new '(src1 src2))) + +(send fft-modulator-class :answer :isnew '(s1 s2) '( + (setf src1 s1) + (setf src2 s2))) + +(send fft-modulator-class :answer :next '() '( + (let ((frame1 (send src1 :next)) + (frame2 (send src2 :next)) + n half_n) + (cond ((and frame1 frame2) + ; multiply frame2 by the amplitude coefficients of frame1 + (setf (aref frame2 0) (* (aref frame2 0) (aref frame1 0))) ;; DC + (setf n (- (length frame1) 1)) + ; Subtracted 1 because we already took care of DC component + (setf half_n (/ n 2)) ; integer divide + (dotimes (i half_n) + (let* ((i2 (+ i i 2)) + (i2m1 (- i2 1)) + (amp (sqrt (+ (* (aref frame1 i2m1) (aref frame1 i2m1)) + (* (aref frame1 i2) (aref frame1 i2)))))) + (setf (aref frame2 i2m1) (* (aref frame2 i2m1) amp)) + (setf (aref frame2 i2) (* (aref frame2 i2) amp)))) + (cond ((= n (+ half_n half_n 2)) ;; n is even -> nyquist component + (setf (aref frame2 n) (* (aref frame2 n) (aref frame1 n))))) + frame2) + (t nil))))) + +(defun make-fft-modulator (src1 src2) + (send fft-modulator-class :new src1 src2)) + +(defun mod-test () + (let ((fs 512)) ;; frame size + (play-fft1 (make-fft-modulator + (file-fft1 sfn fs fs) + (make-fft1-iterator (mod-snd sfn) fs fs)) + fs))) + +(defun raised-cosine () + (scale 0.5 + (sum (const 1) + (lfo (/ 1.0 (get-duration 1)) 1 *sine-table* 270)))) + +(defun fft-window (frame-size) + (control-srate-abs frame-size (raised-cosine))) + +(defun play-fft (iterator frame-size skip) + (play (snd-ifft 0 *sound-srate* iterator + skip (fft-window frame-size)))) + + +(defun mod-test-w () + (let ((fs 512)) ;; frame size + (play-fft (make-fft-modulator + (file-fft1 sfn fs (/ fs 2)) + (make-fft1-iterator (mod-snd sfn) fs (/ fs 2))) + fs (/ fs 2)))) + + +(setf fft-class (send class :new '(sound length skip window))) + +(send fft-class :answer :next '() '( + (snd-fft sound length skip window))) + +(send fft-class :answer :isnew '(snd len skp) '( + (setf sound snd) + (setf length len) + (setf skip skp) + (setf window (fft-window len)) )) + +(defun make-fft-iterator (sound length skip) + (send fft-class :new (snd-copy sound) length skip)) + +(defun file-fft (filename frame-length skip) + (make-fft-iterator (s-read filename) frame-length skip)) + +(defun mod-test-ww () + (let ((fs 512)) ;; frame size + (play-fft (make-fft-modulator + (file-fft sfn fs (/ fs 2)) + (make-fft-iterator (mod-snd sfn) fs (/ fs 2))) + fs (/ fs 2)))) + +(defun mod-test-wws () + (let ((fs 1024)) ;; frame size + (play-fft (make-fft-modulator + (file-fft sfn fs (/ fs 16)) + (make-fft1-iterator (mod-snd sfn) fs (/ fs 16))) + fs (/ fs 2)))) + diff --git a/demos/fft_tutorial.htm b/demos/fft_tutorial.htm new file mode 100644 index 0000000..08cc91b --- /dev/null +++ b/demos/fft_tutorial.htm @@ -0,0 +1,553 @@ + + + + + + +Nyquist FFT and Inverse FFT Tutorial + + + + +

Nyquist FFT and Inverse FFT Tutorial

+ +

Nyquist provides functions for FFT and inverse FFT operations on streams of audio data. +Because sounds can be of any length, but an FFT operates on a fixed amount of data, FFT +processing is typically done in short blocks or windows that move through the audio. Thus, +a stream of samples is converted in to a sequence of FFT frames representing short-term +spectra.

+ +

Nyquist does not have a special data type corresponding to a sequence of FFT frames. +This would be nice, but it would mean creating a large set of operations suitable for +processing frame sequences. Another approach, and perhaps the most "pure" would +be to convert a single sound into a multichannel sound, with one channel per bin of the +FFT.

+ +

Instead, Nyquist violates its "pure" functional model and resorts to objects +for FFT processing. A sequence of frames is represented by an XLISP object. Whenever you +send the selector :next to the object, you get back either NIL, indicating the +end of the sequence, or you get an array of FFT coefficients.

+ +

The Nyquist function FFT (mnemonic, isn't it?) returns one of the frame sequence +generating objects. You can pass any frame sequence generating object to another function, +IFFT, and turn the sequence back into audio.

+ +

With  FFT and IFFT, you can create all sorts of interesting processes. The main +idea is to create intermediate objects that both accept and generate sequences of frames. +These objects can operate on the frames to implement the desired spectral-domain +processes. Examples of this will follow, but first, let's try something simpler.

+ +

Simple FFT Example

+

[Special thanks to James Valenti for detailed comments and explanations + about this code. -RBD]

+ +

Just to convince ourselves that this works and to explore the FFT function, let's +perform an FFT on a sinusoid. To make the outcome predictable, we will use 32 samples of +sinusoid with a period of 8 samples. If we take a 32-point FFT, the spectrum should show a +strong 4th harmonic (there are 4 8-sample periods) and zero everywhere else.

+ +

Before the test, we will introduce a simple function to create an FFT sequence + generating object, which is called an iterator: The function is called make-fft1-iterator, + and creates an object of class fft1-class (I am using fft1 + rather than fft because this is a simplified version that will be improved + later). Objects of this class will have the fields sound, length, + and skip. Create the class by sending class (the super class + of all classes) a :new message to create a new class that will be a + sub-class of class:

+ +
(setf fft1-class (send class :new '(sound length skip)))
+
+Add a method named :next to the fft1-class. The method will have a formal +argument list of () and the code body of (snd-fft sound length skip +nil), so this is simply a wrapper for calling snd-fft which has +takes as parameters: the source sound, the fft length, the number of samples to +advance for each fft, and the sound to use as a window function (in this case, +no windowing is indicated by nil.) Each time snd-fft is called, +it will advance by skip to the next set of samples. The function (and +thus the :next method) will return an array containing the results of +the next short-time fft: +
+(send fft1-class :answer :next '() '(
+    (snd-fft sound length skip nil)))
+
+Add a method named :isnew to the fft1-class. This is a +"standard" method that is called automatically to initialize a new object +of the class when the :new method is sent to the class. Any +parameters sent to :new are passed on to :isnew, and in +this case the formal parameter list is (snd len skp) and the body +of the function is three setf's that copy the parameters into the +fields (or instance variables) of the new object, which are named +sound, length, and skip: + +
+(send fft1-class :answer :isnew '(snd len skp) '(
+    (setf sound snd)
+    (setf length len)
+    (setf skip skp)))
+
+Make a new function named make-fft1-iterator +to create an fft1-iterator with the parameters +sound, length, and skip. The +function makes a new object by sending the :new +message to the fft1-class. Because fft1-class +consumes the sound (by calling snd-fft), this function +copies the sound with snd-copy to avoid any unexpected +side effects on the sound parameter. +
+(defun make-fft1-iterator (sound length skip)
+  (send fft1-class :new (snd-copy sound) length skip))
+ +

For test data, create a sinusoid. lfo generates a +one second sinusoid. +The control-srate-abs transformation changes the sample rate +generated by the lfo to points and since the duration +is one second, there will be exactly points samples +generated. The cycles parameter is the frequency of the +sinusoid, so a value of 1 will generate one cycle (in one second) and +a value of 2 will generate 2 cycles in one second, etc.

+ +
;; create a 1-second sinusoid with points samples at cycles hz:
+(defun short-sine (points cycles)
+  (control-srate-abs points (lfo cycles)))
+
+In the fft-test function, the let introduces a list of +local variables (just fft-iterfft-iter, it will be ignored by this +function. Inside the let, fft-iter is set to a newly +created instance of fft1-iterator, initialized with a signal +that has 4 cycles of a sinusoid in 32 points, with an fft length of 32 +samples and a skip of 32 samples (zero overlap): +
+(defun fft-test ()
+  (let (fft-iter)
+    ;; signal will have 4 cycles in 32 points:
+    (setf fft-iter (make-fft1-iterator (short-sine 32 4) 32 32))
+    (display "fft-test" (send fft-iter :next))))
+ +

Running this prints an array of nearly-zero values except for the 9th element (index +8), which is -1. The layout is as follows: + +

    +
  • the DC component goes in array element 0
  • +
  • the Cosine part is in elements 2i - 1
  • +
  • the Sine part is in elements 2i
  • +
  • the Nyquist frequency component is in the last element
  • +
+The output should look like this: +
+> (load "fft1.lsp")
+;loading "fft1.lsp"
+;[ gc: total 20640, 3360 free; samples 12 KB, 7KB free ]
+;fft-test : (SEND FFT-ITER :NEXT) = #(1.53076e-017 0 0 0 0 0 0 -3.06152e-017
+; -1 0 0 0 0 0 0 3.06152e-017
+; 0 0 0 0 0 0 0 -3.06152e-017
+; 8.9407e-008 0 0 0 0 0 0 1.53076e-017)
+;T
+;>
+
+

Thus, the element at index 8 is the 4th Sine component, indicating a 4th harmonic as +expected.

+ +

Simple Inverse FFT Example

+ +

Now, let's try to reverse the FFT and recover the sinusoid. We will use the + snd-ifft function, which takes five parameters: +

    +
  • the starting time of the resulting sound
  • +
  • the sample rate of the resulting sound
  • +
  • the iterator object, which will be called to obtain short term spectra (frames)
  • +
  • the step-size, how many samples to advance for each frame
  • +
  • the window (or NIL), by which each frame is multiplied after the IFFT
  • +
+

The result returned from snd-ifft is a sound which is assigned here to local + variable ifft-snd. In this case, the sound will have a start time of 0, a sample + rate of 32, the spectral frames (actually just one frame) will be obtained by + sending the :next message to fft-iter, the skip between successive + frames is 32, and no windowing is applied.

+
(defun ifft-test ()
+  (let (fft-iter ifft-snd)
+    (setf fft-iter (make-fft1-iterator (short-sine 32 4) 32 32))
+    (setf ifft-snd (snd-ifft 0 32 fft-iter 32 NIL))
+    (display "fft-ifft" (snd-length ifft-snd 200))
+    (display "fft-ifft" (snd-samples ifft-snd 200))
+    ifft-snd )) ; return the sound
+ +

Now call the function:

+
(ifft-test)
+

Looking at the printed samples, you can see that the result is a close approximation + to the expected sinusoid. Since ifft-test returns a sound, you can + call (play (ifft-test)), but in this case you won't hear much because + the sound is only 32 samples, and there may also be problems trying to play + a sound that is only sampled at 32 samples per second.

+ +

Exercise: Modify short-sine to produce a cosine and observe the +difference in the FFT. Confirm that the IFFT reproduces the original cosine. (Hint: the +parameters to LFO should be: (lfo cycles 1.0 *sine-table* 90.0), +indicating frequency, duration, the waveform, and the initial phase, respectively.)

+ +

Sequence of FFT Frames

+ +

Let's create an FFT iterator that reads sounds from a file. This is similar + to what was done before, but here, s-read is used to read samples instead + of using lfo to compute samples:

+ +
(defun file-fft1 (filename frame-length skip)
+  (make-fft1-iterator (s-read filename) frame-length skip))
+ +

And here is a function to recover the sound file from spectral frames and play + it. The sound will start at time 0, at the sample rate *sound-srate*, + using iterator to generate successive spectral frames, advancing skip + samples between fft's, and no windowing. Note: *sound-srate* is a global + variable from Nyquist that is the default sample rate for sounds. It can be + read directly, but you should only modify it by calling sound-srate-abs:

+ +
(defun play-fft1 (iterator skip)
+  (play (snd-ifft 0 *sound-srate* iterator skip NIL)))
+ +

Define a filename for testing. Remember that the backslash (\) character + is the escape character for XLisp strings, so you need to type two backslashes + to denote one backslash character. Windows will also accept forward slashes + (/) as a separator, and the forward slash does not need to be escaped. + Be sure to test this with a mono file at the default sample rate of 44100:

+ +
;; a convenient sound file name (change this to one of your mono soundfiles):
+(setf sfn "D:\\brain\\outro\\soup.wav")
+
+Define a function to call play-fft1 using sfn as the input function +for analysis, a frame length (fft size) of 512, and a skip size of 512 (no overlap). +The start time (0), sample rate (*sound-srate*) and windowing function +(none) are hard-coded in play-fft1. +
(defun file-test () (play-fft1 (file-fft1 sfn 512 512) 512))
+ +

If you do not hear your original file, try playing the original file by typing + (play-file sfn), and make sure the file is a mono file at 44,100 Hz + sample rate (to match *sound-srate* used in play-fft1). Check + out the file by typing (sf-info sfn).

+

You can try different skip parameters, e.g. to play the sound at double speed, + try this:

+
(play-fft1 (file-fft1 sfn 512 512) 256)
+

XLisp and Garbage Collection

+

In the previous example, you may have noticed a lot of messages that look something +like the following:

+ +
[ gc: total 18640, 3114 free; samples 49KB, 39KB free ]
+ +

What the gc: Messages Mean

+ +

These messages are printed whenever the garbage collector runs to reclaim memory that +was allocated but is no longer in use by the program. The memory found by the garbage +collector is reused in future computation to avoid allocating more memory than is +necessary. The particular message here says that 18640 "cells" have been +allocated. Each cell is 10 bytes, so there are 186,400 bytes, or about 186KB used to store +XLisp programs and data. This does not include the XLisp interpreter, Nyquist functions, +and system libraries, that take an additional 500KB or so. It also does not include audio +samples, which are stored separately. Of the 18640 cells, 3114 were free after garbage +collection. Of the 49KB of audio data (samples) allocated by Nyquist, 39KB were free for +reuse after after garbage collection.

+ +

Making GC More Effective

+ +

Nyquist and XLisp do a pretty good job of effective, automatic garbage collection, but +since XLisp was designed to run on small machines, it favors using a minimal amount of +memory, and this may result in frequent garbage collections. FFT processing, in +particular, makes heavy use of XLisp, since every floating point number in every FFT frame +requires the allocation of a 10-byte cell. When you are processing with FFTs, you can +often gain some speed by telling XLisp to allocate more memory cells. Do this by calling expand:

+ +
(expand 100)
+ +

The parameter tells how many additional internal blocks of memory to allocate. Each +block is 2000 cells, or about 20KB, so if the parameter is 100, you will allocate about +2MB. After allocating memory, the next garbage collection might look like:

+ +
[ gc: total 218640, 204298 free; samples 49KB, 44KB free ]
+ +

Notice that now, garbage collection frees a higher proportion of memory than before +  (204298 out of 218640 cells). Garbage collection is more efficient when there is a +higher proportion of memory to free.

+ +

On the other hand, you should not allocate more memory than necessary. If you allocate +too much, parts of Nyquist and other programs will be paged out of RAM and onto your disk +drive. Since Nyquist must access all of its memory for every garbage collection, it is +very inefficient to have any of that memory reside on disk.

+ +

Should you always expand memory? Almost all non-FFT audio processing uses special data +structures that are outside of XLisp and are managed without the use of the garbage +collector. Since audio processing normally takes over 95% of the execution time, you +normally do not have to worry much about the efficiency of XLisp.

+ +

Simple Spectral Processing

+ +

The main purpose of FFT and IFFT functions is to enable processing in the spectral + domain. Let's create a very simple example in which certain frequencies are + set to zero, creating a filter effect. (Note that this is not a very good way + to create filters because of boundary effects.) We need to create an object + that will access an FFT iterator to get frames, and that will serve as an iterator + to deliver frames. The code is as follows:

+ +
(setf fft-hp-class (send class :new '(source bins)))
+
+(send fft-hp-class :answer :next '() '(
+  ; get a new frame of fft coefficients from source
+  (let ((frame (send source :next))) ; creates local variable - frame
+    ; a note about let:
+    ; the first list after let names new local variables
+    ; the following lists (below) are expressions to be evaluated
+    ;
+    ; if frame is nil, there are no more frames to process
+    (cond (frame
+           ; if frame is not nil, then do the following
+           (dotimes (i bins)
+             ; set all the bins from 0 to bins-1 (these are low frequency bins) to zero
+             ; the order of coefficients is:
+             ;    DC coefficient
+             ;    first real
+             ;    first imaginary
+             ;    second real
+             ;    second imaginary
+             ;    ...
+             ;    if the length is even, then last is the real
+             ;       coefficient of the Nyquist frequency
+             ;
+             ; (Note: aref gets the ith element of the array)
+             (setf (aref frame i) 0.0)))) ; end of cond
+    frame))) ; frame is the last expression of the let, so it is the return value
+
+Create an fft-hp-class method called :isnew to initialize the +fft-hp-class class variables source and bins. The source +will be a file-fft. +

A refresher as to what goes on with file-fft: file-fft1 reads a file +into a sound variable and calls make-fft1-iterator. Then +make-fft1-iterator returns an fft-1 class by sending +fft1-class :new with a copy of the sound. It makes this copy because +it will have skip samples removed every invocation of +fft1-class:next because this method calls snd-fft which +removes the samples every time a new fft frame is calculated. +

+(send fft-hp-class :answer :isnew '(s b) '(
+    (setf source s)
+    (setf bins b)))
+
+This is a function to make and return an instance of the fft-hp-class +class. +
+(defun make-fft-hp (source bins)
+  ; Send the fft-hp-calss a :new message to create a new instance of the class
+  ; and to initialize the instance with the values of source and bins
+  ; Returns an object that responds to the :next message by getting the next
+  ; fft frame, zeroing the low frequencies, and returning the frame.
+  (send fft-hp-class :new source bins))
+
+In play-fft1, fft frames from make-fft-hp are converted +back into audio. The audio is reconstructed using a skip of 512. +
+(defun hp-test ()
+  (play-fft1 (make-fft-hp (file-fft1 sfn 512 512) 11) 512))
+ +

Note that make-fft-hp takes a parameter, bins, that tells how many +coefficients of the FFT to zero. At 44,100 Hz, the frame rate is 44100/512 = 86.13 Hz, and +this corresponds to the first bin (coefficients at locations 1 and 2). Since we specified +11 for the bins parameter, this will zero the DC component and 5 complex pairs, +representing frequencies up to 86.12 * 5 = 430.7 Hz. (If you are trying this on a laptop +computer with small speakers, or if you are using a sound without low frequencies, you may +want to increase the number of bins in hp-test from 11 to 30 to make the effect +really obvious.)

+ +

You will notice some raspy sounds in the output. Since the FFT frames are not smoothed +by any window or overlapped, there are serious windowing artifacts that are easily heard. +We will look at ways to reduce this problem later.

+ +

Spectral Modulation

+ +

An interesting effect is to let one spectrum modulate another one. By multiplying the +amplitude spectrum of one signal onto that of another, one can superimpose the two +signals. (Note that adding spectra is simply a way to mix them and is equivalent to +addition in the time domain.)

+ +

Let's create a bright FM sound to serve as a spectral modulation "carrier". +First, create the FM sound. This sound has an initial, middle, and fiinal modulation index +as well as a (constant) pitch:

+ +
(defun fm-tone (step mi1 mi2 mi3)
+  (let ((hz (step-to-hz step)))
+    (setf mi1 (* mi1 hz))
+    (setf mi2 (* mi2 hz))
+    (setf mi3 (* mi3 hz))
+    (fmosc c4 (partial step 
+                       (control-srate-abs *sound-srate* 
+                         (pwl 0 mi1 0.5 mi2 1 mi3 1))))))
+ +

The modulated sound will be a cluster of three FM tones. You could use just one tone, +but I have had better luck with chords or noise. You want to make sure the signal has +plenty of amplitude at many frequencies; otherwise, the spectral modulation will not have +anything to modulate.

+ +
(defun mod-snd ()
+  (sum
+    (fm-tone c3 15 20 15)   ;; adjust FM parameters here
+    (fm-tone d3 15 20 15)   ;; adjust FM parameters here
+    (fm-tone e3 15 20 15))) ;; adjust FM parameters here
+ +

Next, we need a class to do the modulation. As before, objects of this class respond to +the :next message. In this case, the :next method sends  :next +to both sources. It then multiplies the coefficients of one by the computed amplitude +spectrum of the other.

+ +
(setf fft-modulator-class (send class :new '(src1 src2)))
+
+(send fft-modulator-class :answer :isnew '(s1 s2) '(
+    (setf src1 s1)
+    (setf src2 s2)))
+
+(send fft-modulator-class :answer :next '() '(
+  (let ((frame1 (send src1 :next))
+        (frame2 (send src2 :next))
+        n half_n)
+    (cond ((and frame1 frame2)
+           ; multiply frame2 by the amplitude coefficients of frame1
+           (setf (aref frame2 0) (* (aref frame2 0) (aref frame1 0))) ;; DC
+           (setf n (- (length frame1) 1))
+           ; Subtracted 1 because we already took care of DC component
+           (setf half_n (/ n 2)) ; integer divide
+           (dotimes (i half_n)
+             (let* ((i2 (+ i i 2))
+                    (i2m1 (- i2 1))
+                    (amp (sqrt (+ (* (aref frame1 i2m1) (aref frame1 i2m1))
+                                  (* (aref frame1 i2)   (aref frame1 i2))))))
+                (setf (aref frame2 i2m1) (* (aref frame2 i2m1) amp))
+                (setf (aref frame2 i2) (* (aref frame2 i2) amp))))
+           (cond ((= n (+ half_n half_n 2)) ;; n is even -> nyquist component
+                  (setf (aref frame2 n) (* (aref frame2 n) (aref frame1 n)))))
+           frame2)
+          (t nil)))))
+
+(defun make-fft-modulator (src1 src2)
+  (send fft-modulator-class :new src1 src2))
+ +

The code for  :next is longer than you might expect, but it is basically +just a vector multiplication. Lisp is not ideal for numerical algorithms like this. The +following code will test the new class:

+ +
(defun mod-test ()
+  (let ((fs 512)) ;; frame size
+    (play-fft1 (make-fft-modulator 
+                 (file-fft1 sfn fs fs)
+                 (make-fft1-iterator (mod-snd) fs fs))
+               fs)))
+ +

Here, we pass in iterators for the sound stored in a file and for the modulated sound. +This example seems to work best if the sound in the file is a voice. You can also try +stretching the speech by reducing the step parameter to file-fft and by making +the modulated sound longer. You might also try different sizes of FFTs using the frame +size (fs) parameter. If the FFT frame size is too big, you will resolve +individual harmonics of the voice, and if it is too small, you will not resolve formants. +256 and 512 seem to be good numbers when working at 44,100 Hz sampling rates.

+ +

Smoothing Windows

+ +

In the previous examples, and especially in the last one, a lot of buzzing and noise is +created because the boundaries of the FFT frames are no longer continuous when the +spectrum is altered. To reduce the buzzing effect, we can multiply the frame by a +smoothing window before reconstructing the time domain signal. We can also use a smoothing +window on the input side, before taking the FFT. For now, we will try just a smoothing +window on the IFFT side.

+ +

The smoothing window will be a raised cosine pulse, although other window shapes could +be used. The following code implements a raised cosine. (A raised cosine is a smooth +bell-shaped curve that rises from zero to 1 and back again. The curve is one period of a +sinusoid or cosine, but "raised" so that its minimum value is at zero.) The lfo +function computes a sine curve, so we use an initial phase of 270 degrees to get the +proper shape:

+ +
(defun raised-cosine ()
+  (scale 0.5 
+    (sum (const 1) 
+         (lfo (/ 1.0 (get-duration 1)) 1 *sine-table* 270))))
+ +

Next, we need a function to create a window of the proper length. The sample rate of +the window does not matter because the FFT and IFFT functions will simply take the proper +number of samples (without any interpolation or resampling). Therefore, we will use the frame-size +as the sample rate, insuring that there are frame-size samples:

+ +
(defun fft-window (frame-size)
+  (control-srate-abs frame-size (raised-cosine)))
+ +

Now we can pass in a window to the IFFT. Let's redo the spectral modulation example +with smoothing windows on the IFFT side. First, we will rewrite play-fft to use +windowing:

+ +
(defun play-fft (iterator frame-size skip)
+  (play (snd-ifft 0 *sound-srate* iterator 
+                  skip (fft-window frame-size))))
+ +

Now, we can rewrite mod-test:

+ +
(defun mod-test-w ()
+  (let ((fs 512)) ;; frame size
+    (play-fft (make-fft-modulator 
+                (file-fft1 sfn fs (/ fs 2))
+                (make-fft1-iterator (mod-snd) fs (/ fs 2)))
+              fs (/ fs 2))))
+ +

Notice that we reduced the step size to half the frame size. This is because we want +the windows to overlap by 50%, creating a nice cross-fade from one frame to the next.

+ +

You might guess that the square windowing on the analysis (FFT) side is injecting high +frequencies into the spectrum. We can introduce windowing there too. We can modify make-fft-iterator +to use a window. This will require changes to fft1-class, so we will use the name +fft-class:

+ +
(setf fft-class (send class :new '(sound length skip window)))
+
+(send fft-class :answer :next '() '(
+    (snd-fft sound length skip window)))
+
+(send fft-class :answer :isnew '(snd len skp) '(
+    (setf sound snd)
+    (setf length len)
+    (setf skip skp)
+    (setf window (fft-window len)) ))
+
+(defun make-fft-iterator (sound length skip)
+  (send fft-class :new (snd-copy sound) length skip))
+ +

Now, we can rewrite file-fft to use windowing:

+ +
(defun file-fft (filename frame-length skip)
+  (make-fft-iterator (s-read filename) frame-length skip))
+ +

Now, we can rewrite mod-test yet again:

+ +
(defun mod-test-ww ()
+  (let ((fs 512)) ;; frame size
+    (play-fft (make-fft-modulator 
+                (file-fft sfn fs (/ fs 2))
+                (make-fft-iterator (mod-snd) fs (/ fs 2)))
+              fs (/ fs 2))))
+ +

This version seems to have less definition for speech input than the previous one. It +might be that some windowing artifacts in the right places are actually beneficial! In +fact, some simple experiments indicate that, in this example, the speech sounds better +when the (mod-snd) sound is analyzed without windowing. This probably creates more noise +to be modulated by the speech signal, so more speech information gets through.

+ +

We can also stretch the result by taking smaller steps during the analysis (FFT) stage +so that more frames are generated. I will also increase the frame size to obtain fewer +frames/second.

+ +
(defun mod-test-wws ()
+  (let ((fs 1024)) ;; frame size
+    (play-fft (make-fft-modulator 
+                (file-fft sfn fs (/ fs 16))
+                (make-fft1-iterator (mod-snd) fs (/ fs 16)))
+              fs (/ fs 2))))
+ +

Acknowledgments

+ +

Cort Lippe and Zack Settel have explored cross synthesis and other effects with FFTs +extensively, and their work inspired these examples.

+ + + diff --git a/demos/largeclip.jpg b/demos/largeclip.jpg new file mode 100644 index 0000000..6b745e9 Binary files /dev/null and b/demos/largeclip.jpg differ diff --git a/demos/lpc-exmpl.dat b/demos/lpc-exmpl.dat new file mode 100644 index 0000000..66332d3 --- /dev/null +++ b/demos/lpc-exmpl.dat @@ -0,0 +1,162 @@ +(0.0205328 0.000539653 0.162119 #(0.0172437 -0.00206371 0.0199834 0.0140023 -0.107106 0.105376 -0.014147 -0.0456254 -0.035733 0.000526876 0.024559 -0.077979 0.0379572 0.0550832 0.0251978 -0.0158793 0.000201547 0.0183836 0.0120267 -0.0145289 0.0270053 0.0215023 -0.0674045 0.0868633 -0.0759818 0.0123872 -0.100426 0.0670379 0.153223 -0.160887 0.0200027 0.00857184 -0.0319345 0.0372642 -0.039906 0.0370124 -0.0406953 0.0916241 -0.0794324 0.0994091 -0.152256 0.122422 -0.131096 0.143904 -0.182573 0.107067 -0.216319 0.338997 -0.171402 1.04299)) +(0.0746031 0.000883533 0.108826 #(0.043002 -0.0168565 0.0116234 -0.031321 -0.0728684 0.134856 0.0052372 -0.0477521 -0.0767405 0.0307031 0.00286882 -0.0188694 -0.0103552 0.0410824 -0.00991496 0.0129631 -0.0070764 0.0446677 -0.0316206 0.0103328 -0.00314631 0.0721652 -0.028264 0.0429488 -0.0757499 0.0355948 -0.124679 0.0341884 0.147169 -0.115948 0.0350534 -0.022784 0.00255128 0.000132609 0.00266292 0.0235752 -0.0270638 0.00319338 -0.0405898 0.0510949 -0.0525406 0.112875 -0.120262 0.103579 -0.140658 0.030511 -0.195171 0.226418 -0.194436 1.19625)) +(7.90651 0.00254103 0.0179272 #(0.0298438 -0.0150177 0.00856811 0.00178307 -0.156251 0.141521 0.0377321 -0.00862076 0.0358013 -0.0526648 -0.0746482 0.0176761 0.0180553 0.0110547 -0.0149859 -0.00274912 0.00753696 0.0570906 -0.00985159 -0.0460384 -0.0312089 0.0275762 -0.00179828 0.0498972 -0.0462076 0.111785 -0.101277 -0.0429219 0.135046 -0.118618 0.0320909 0.0152628 0.00229011 0.000619642 -0.00148223 0.0698463 -0.0192731 -0.061608 -0.105966 0.00760205 -0.0556964 0.172818 -0.0018539 0.14807 -0.115714 0.0485711 -0.341883 0.118442 -0.644804 1.76356)) +(16.8204 0.00353871 0.0145046 #(0.0242379 0.0163801 -0.0441124 0.0515951 -0.165318 0.0553254 0.118888 -0.00888211 0.0686623 -0.103195 -0.109872 0.0873954 -0.00312068 -0.0157818 0.00793753 -0.0102677 0.0385871 0.0402539 0.0275778 -0.124176 -0.0224998 -0.0083091 0.139262 -0.0326057 -0.0686154 0.152026 -0.0710961 -0.100093 0.0921394 -0.0886168 0.0962788 0.0235546 -0.0835561 0.0289921 -0.0519826 0.0819953 0.0677047 -0.04636 -0.154177 0.0188317 -0.0733893 0.18706 -0.117089 0.276443 -0.188078 0.136406 -0.348012 0.354862 -1.21044 2.05642)) +(15.7527 0.00488585 0.0176113 #(0.0410332 -0.0212341 -0.0186016 0.0139835 -0.10253 0.0317464 0.098534 0.0577219 -0.00603218 -0.119189 -0.0560336 0.0600247 0.00563636 -0.00741701 -0.022568 0.0551003 0.0172174 -0.0145449 0.0377798 -0.0774387 -0.0623132 0.0156745 0.116856 0.0167625 -0.0740776 0.0976961 -0.0589157 -0.0592283 0.0621122 -0.0668073 0.0672344 0.0433492 -0.0724394 -0.0149194 -0.0174723 0.0940844 0.0192709 -0.037947 -0.145742 0.0166333 -0.0382952 0.137928 -0.0235971 0.142885 -0.0641163 -0.0401743 -0.14418 0.182686 -1.00692 1.93978)) +(16.3531 0.0136897 0.0289333 #(-0.024896 0.016421 0.00786502 -0.0118406 0.00603457 0.0343453 0.0250988 -0.00670104 -0.0483285 -0.0402459 0.00284676 0.0223309 0.00649693 -0.0116516 0.00923614 0.0111503 -0.000440774 -0.0275555 0.00682401 -0.0125723 0.00263826 0.0153074 0.0242379 0.0142031 0.0060273 0.0192062 -0.0368178 0.00965019 0.0058204 -0.00736851 0.0414994 0.00440613 -0.0394615 -0.0217087 0.0132956 0.0116567 -0.024931 -0.0592983 -0.0327111 0.00831445 0.0282831 0.0678891 0.00450369 0.00915988 -0.0181229 -0.0469828 -0.0555707 -0.0913728 -0.228273 1.41019)) +(22.7776 0.0128829 0.0237823 #(-0.0244512 0.00852192 0.00355279 0.0100932 -0.00419528 0.0237172 0.0103759 -0.0137028 -0.0251104 -0.0134613 -0.000615256 0.00165147 -0.00407305 -0.00344569 -0.00120993 0.0089017 0.000495352 -0.000238208 0.00294549 0.00112805 0.00425276 0.0266437 0.0165051 -0.0296654 -0.00157895 0.0406957 -0.0203225 0.000875471 0.0187371 -0.00604564 0.0124178 0.00848914 -0.00870932 -0.0345038 -0.0166086 -0.00777551 -0.0127552 -0.0198208 -0.018883 0.00170381 0.0281818 0.0335668 0.00621638 0.000123257 -0.0400046 -0.0251494 -0.0599436 -0.0484318 -0.0953316 1.26394)) +(25.9418 0.014063 0.023283 #(-0.0146976 0.0123669 -0.00238331 -0.00566441 0.000213927 0.0251708 0.0058586 -0.0152624 -0.0096643 0.000380473 -0.00692432 -0.0103325 -0.00570062 -0.00779317 -0.00373097 -0.00244446 0.0232326 0.00687431 -0.0123666 0.0136142 0.000873428 0.01297 0.00157535 -0.0189359 0.0103542 0.0149338 -0.00232667 0.018195 0.0122806 0.000705099 0.0180465 -0.00723085 -0.0333543 -0.0209618 -0.00258482 -0.00346647 -0.0161793 -0.00443528 -0.0107334 -0.00729346 0.0212632 0.017004 -0.0134609 -0.0122188 -0.0266593 -0.0240987 -0.0584669 -0.0204726 -0.0728998 1.23429)) +(26.411 0.0454326 0.0414755 #(-0.0109339 -0.0010968 -0.0010053 0.00617609 0.00306015 0.000136934 0.00372594 -0.00564924 -0.00591968 -0.00522412 -0.00509402 -3.17432e-006 -0.00446083 0.00456961 0.00243643 0.00451923 0.00334826 0.00559344 0.00805774 0.000849614 0.00365901 -0.000214671 -0.00258062 0.00132718 0.00916179 0.00321858 -0.00441098 0.00674969 0.00362521 0.00233835 0.00103611 -0.00365412 -0.0110665 -0.0113001 -0.00483079 -0.00471838 -0.0072024 -0.0112189 -0.00842469 -0.00122134 0.00258161 -0.00404681 -0.0108012 -0.0163903 -0.0156165 -0.0101237 -0.0119205 -0.0127908 -0.0241693 1.1353)) +(26.023 0.0171174 0.0256472 #(-0.00659148 -0.0022813 0.00245043 0.0119932 0.00673879 0.0106215 0.000193227 -0.0118672 -0.00229731 -8.44562e-005 -0.010244 -0.0224172 -0.0074773 0.00139424 0.00442344 -0.00372009 0.00631038 0.00399001 0.00074413 0.00143648 0.0117816 0.0167116 -0.011429 0.00660101 -0.0154429 0.0245051 0.00954568 0.00221017 0.00972422 0.00691179 0.00198784 0.00641321 -0.0164092 -0.0286664 -0.00348171 -0.00646432 -0.0149224 -0.00929398 0.000946284 -0.00786511 0.0105857 0.0116371 -0.0208869 -0.0167969 -0.039235 -0.0416232 -0.0188724 -0.0395318 -0.0672928 1.2529)) +(20.1471 0.0413173 0.0452855 #(0.0028042 0.00238915 0.00320531 0.00204744 -0.00128491 -0.000625469 0.00121502 -0.00053792 -0.00926453 -0.00168529 -0.0176347 -0.00451895 0.000996928 0.00430582 0.00194222 -0.00398466 0.00259957 0.00390882 0.0116503 0.00167209 -0.001884 0.00309071 0.00380416 0.00551039 0.0052082 0.00707811 -0.00293764 0.0110331 0.0118179 0.000155053 0.0029885 -0.0120471 -0.00528422 -0.0186305 -0.00389795 -0.01138 -0.0130287 -0.0114016 -0.00348096 0.00720399 -0.00393767 -0.00782219 -0.00889679 -0.0106665 -0.0241594 -0.0212916 -0.0261109 -0.0222356 -0.042137 1.1898)) +(15.5487 0.0153078 0.0313768 #(0.0038797 -0.00898583 -0.00129375 0.0135476 0.00658722 0.0365788 0.00343157 -0.0308747 -0.0106992 -0.00551437 0.00041832 -0.0139702 -0.0154675 -0.0119801 -0.00961124 0.0151818 0.00235315 -0.00360607 -0.00300882 0.0133151 0.00953059 0.00235415 -1.91313e-005 0.00280704 0.0099642 0.0205634 0.00397632 0.00529698 0.023866 -0.00799138 0.0100504 0.0079582 -0.0250386 -0.029848 -0.0097943 -0.00418491 -0.0133331 -0.0233978 -0.00335522 0.0048438 0.0168547 0.0205229 -0.0161785 -0.0256227 -0.0427417 -0.0322054 -0.0493791 -0.0330071 -0.0981295 1.29245)) +(19.0253 0.00596731 0.0177102 #(-0.0146168 -0.0100904 0.00214927 0.0184939 0.01049 0.0612408 -0.00438104 -0.0265871 -0.026429 0.00668405 0.0269023 -0.0263329 -0.0230587 -0.0429497 0.00384385 0.0294333 -0.00318107 -0.0136982 -0.00792112 0.0090845 0.0366004 -0.0174499 -0.00897093 -0.00784815 -0.00441435 0.0551205 -0.0163865 0.00471411 0.0446577 -0.0132054 0.0401863 0.0217569 -0.0372981 -0.0637524 -0.0140608 0.0379691 -0.012396 -0.0571539 -0.0387487 0.0285809 0.0555209 0.0533837 -0.020053 -0.00430533 -0.102708 -0.0554588 -0.0775484 0.00345876 -0.257812 1.45669)) +(24.3361 0.00252815 0.0101924 #(-0.0257512 -0.0008726 0.0176086 0.0124685 -0.0534896 0.100064 0.0398205 -0.0701561 -0.0307596 0.00460567 0.0732452 -0.00591591 -0.0655563 -0.0244842 0.0128442 0.0333025 -0.0171489 -0.0529101 -0.0145168 -0.00558627 0.0716373 0.0169233 -0.00522713 0.00671804 -0.0615778 0.0634442 -0.0921752 0.00951979 0.120483 -0.077487 0.0914363 0.104565 -0.0653618 -0.089458 -0.0420491 0.0741933 -0.0368942 -0.0224205 -0.159684 0.0706304 0.0604807 0.156387 -0.0368354 0.00141878 -0.11703 -0.0250188 -0.215087 0.140998 -0.528956 1.65826)) +(25.4722 0.00168582 0.00813527 #(-0.0361914 0.0503908 -0.052739 0.0874611 -0.161167 0.205034 -0.030822 -0.0297436 -0.0881124 0.0515133 0.029009 0.0911085 -0.133234 0.00447612 -0.0102752 0.0672411 -0.0743354 0.0278325 -0.088049 0.0254583 0.00378763 0.110739 -0.0335123 0.0437825 -0.111471 0.143021 -0.205556 0.0105061 0.178276 -0.139079 0.108138 0.100769 -0.0514441 -0.061891 -0.0335699 0.078663 -0.0342434 -0.0322647 -0.218112 0.133516 -0.053587 0.327015 -0.200594 0.23237 -0.331232 0.175309 -0.44634 0.403636 -0.874447 1.84189)) +(24.4789 0.00660193 0.0164225 #(-0.0129511 0.000294328 -0.0197443 0.0228973 0.0144379 0.0576108 -0.00978518 -0.00793303 -0.0138883 -0.0222251 0.0319748 -0.0148723 -0.0204648 -0.0414119 -0.0116904 0.010987 -0.0113676 0.0117234 -0.00638076 0.0237907 0.020048 0.00399678 -0.00498899 -0.00973827 -0.00584135 0.0192609 -0.0220209 0.0192987 0.0427776 -0.0141488 0.0260689 0.053246 -0.0359298 -0.0407085 -0.0153808 0.000894089 -0.0255827 -0.0505249 -0.0252819 0.0272812 0.0597201 0.0367404 0.00457889 -0.0014007 -0.0717525 -0.0699291 -0.107446 -0.0187547 -0.27242 1.49509)) +(26.2758 0.0176864 0.0259442 #(0.0033549 -0.00945348 0.0065972 0.011377 0.00754275 0.0138938 0.00853247 0.000314037 -0.00732074 -0.0137922 -0.008441 -0.0188535 -0.0266481 -0.0205979 0.00421144 0.0117094 0.0169971 -0.0179554 -0.00098244 0.035148 0.00857569 -0.0052743 -0.000887931 0.00311146 -0.00552477 0.00948484 -0.000848823 0.0254957 0.0295882 -0.0096005 0.019213 0.00984905 -0.0239854 -0.0251062 -0.0378088 -0.00656597 -0.0252241 -0.0322219 0.024789 0.0259035 0.0228412 0.0272441 -0.00713364 -0.0104557 -0.0465321 -0.0714479 -0.0841954 -0.0538046 -0.134946 1.37684)) +(33.8769 0.00801222 0.0153789 #(-0.00258214 -0.00821759 0.0196898 -0.000392261 0.0140521 0.00440578 -0.0286329 0.000567736 0.0125327 0.00426797 -0.0066993 0.0334311 -0.0281124 -0.0422645 -0.0221943 0.0377913 -0.00618192 -0.0265775 -0.00448782 0.027992 0.0456436 0.00158737 -0.0145791 -0.00474223 -0.0115839 0.0136965 -0.0283794 0.032301 0.000935378 -0.0386639 0.0497046 0.0790239 -0.0338661 -0.0499984 -0.00571791 0.0381896 -0.0512542 -0.0879677 -0.0317509 0.0295627 0.0690141 0.0544617 0.0545729 0.0472211 -0.0781932 -0.090823 -0.112884 -0.113677 -0.42381 1.68183)) +(47.5854 0.03461 0.0269689 #(0.00703504 0.0042176 -0.007448 0.00601103 0.00320568 0.00838487 0.0062723 -0.0120179 0.000336154 0.000458805 -0.00549983 -0.000896449 -0.0239517 -0.0277963 -0.00199031 0.00441657 0.0118858 -0.00555538 0.0186382 0.000599233 0.0253149 0.00947596 -0.0151058 -0.0109278 -0.00257833 0.0161187 -0.000843106 0.0151509 0.00682266 0.00837561 0.0212141 0.019091 -0.0166389 -0.0383569 -0.0276626 -0.0067535 -0.0278646 -0.0358582 -0.00485826 0.02398 0.0407189 0.0544763 0.0300379 -0.00650959 -0.0404744 -0.0715788 -0.100036 -0.13855 -0.218292 1.50233)) +(67.1502 0.0503262 0.0273762 #(0.00163764 0.00156368 0.000896518 -0.00356924 0.0146311 0.0115155 0.000718131 -0.010003 -0.00103783 0.00202199 -0.00199034 -0.0161105 -0.0194743 -0.0104963 -0.00591896 0.0121449 0.00486055 -0.00401805 0.00316407 0.00376875 0.0156482 0.00483055 -0.00410957 -0.00432992 -0.00485066 0.0143753 0.00558336 0.0130507 0.00596937 0.00550279 0.0213288 0.00884339 -0.00423094 -0.0320471 -0.0225288 -0.0132194 -0.0288979 -0.0323811 -0.0196434 0.0287962 0.0448142 0.0421381 0.0389864 -0.00463365 -0.0331114 -0.0584344 -0.112601 -0.149007 -0.247096 1.5331)) +(87.0259 0.146162 0.040982 #(0.0066813 0.0031666 0.00524609 -0.0082533 -0.00391559 0.0131647 0.0226346 0.00201689 -0.0300066 -0.0164448 0.00249676 0.012122 -0.0120514 -0.0290936 -0.00477291 0.0062677 0.00679358 0.00355967 0.0074764 0.00641204 0.00203213 -0.000103927 0.00208319 0.00592471 -0.00531212 -0.00286345 0.0194362 0.0235452 0.0145299 0.000873052 0.0170015 0.00926635 -0.0249864 -0.0345525 -0.026674 -0.0209155 -0.0204941 -0.0180144 -0.000742368 0.0206704 0.0347392 0.0281013 0.0231078 0.00568184 -0.0455544 -0.0687793 -0.0774324 -0.112311 -0.16092 1.413)) +(103.805 0.0839127 0.0284317 #(0.0305305 -0.0232935 -0.0123279 -0.00539001 0.00241112 0.0181144 0.0198195 -0.0119952 -0.00946969 -0.00768942 0.0176179 0.0159392 -0.0270933 -0.0533804 -0.0238979 0.042285 0.0419821 -0.0130642 -0.02037 0.00470052 0.0265474 0.00800111 -0.0193407 -0.00539329 -0.00768145 -0.00352887 0.00818424 0.0306883 0.00191179 -0.011258 0.0201576 0.0424102 0.000582659 -0.0480861 -0.0335357 0.00238416 -0.000149278 -0.0762318 -0.0235003 0.0537691 0.0525345 0.0284459 0.0125174 0.044311 -0.0359816 -0.0879433 -0.0942918 -0.141744 -0.328099 1.59425)) +(124.841 0.162496 0.036078 #(0.0154669 -9.72884e-006 -0.0101342 -0.00793859 0.0059567 0.0228617 0.00768918 -0.0107367 -0.0153092 -0.00690622 0.00137529 0.00756771 -0.0173113 -0.0348903 -0.015329 0.0277865 0.0313134 0.00105124 -0.0143057 -0.00667794 0.011448 0.00558312 -0.00253005 0.000195594 -0.00582771 0.00497205 0.0183721 0.0241788 0.0151434 -0.0120356 0.00834879 0.019273 -0.0189529 -0.0436641 -0.017064 0.0110478 -0.0142619 -0.0454921 -0.0275606 0.0195142 0.0430997 0.0479311 0.0369613 0.00241956 -0.049964 -0.0670036 -0.063226 -0.132439 -0.269048 1.51163)) +(180.716 0.293325 0.040288 #(0.0258335 -0.0119538 -0.0193954 -0.00626257 0.0234294 0.0231874 0.0109882 -0.0140674 -0.0204807 -0.0175573 0.000633931 0.000397377 -0.011624 -0.022438 -0.0107618 0.0178291 0.0325036 0.0112156 -0.0171066 -0.00548084 0.00984786 -0.00170732 -0.00485124 -0.00691943 -0.00247698 0.0118085 0.0178137 0.0244233 0.0229053 0.003698 -0.0103266 -0.00441229 -0.00122563 -0.0243714 -0.0381239 -0.0309188 -0.0100181 -0.00337076 -0.00420997 0.0204227 0.0439681 0.0382338 0.00823855 -0.0138448 -0.0326542 -0.0661078 -0.097244 -0.115524 -0.154429 1.42031)) +(234.118 0.205985 0.029662 #(0.0192157 -0.0031935 -0.00784433 -0.00677489 0.00286156 0.0114244 0.0199407 0.00873447 -0.0210833 -0.0382217 0.00335562 0.018978 -0.0148748 -0.0242473 -0.0051396 0.0205883 0.00181457 -0.0139292 0.0109887 0.0201683 0.00322887 -0.00941825 -0.00196576 0.0112985 -0.0102269 -0.0019795 0.0216591 0.0239712 0.00292886 -0.0126777 0.0229174 0.0228922 -0.0279371 -0.0544655 -0.0105665 0.0201515 -0.0232041 -0.0500812 -0.0122807 0.0286273 0.0377097 0.0333467 0.0362003 0.00682096 -0.0421918 -0.0623608 -0.0697533 -0.142768 -0.286476 1.53382)) +(240.477 0.393671 0.0404604 #(0.0141351 -0.00376777 -0.0127499 0.00507208 0.0136482 0.0136646 0.00963351 -0.00969488 -0.0204225 -0.0195809 -0.00608936 0.0113476 -0.00348937 -0.0263493 -0.00860379 0.0196824 0.0270435 0.00279308 -0.0216122 -0.00311376 0.0167268 0.0026715 -0.00951989 -0.00655211 -0.000521916 0.00286717 0.0195184 0.0369098 0.0212964 -0.00938696 -0.00852238 0.0157752 -0.010538 -0.0511757 -0.0367333 -0.00701777 -0.00496757 -0.0218476 -0.00180121 0.0358277 0.0423497 0.0250602 0.0161893 -0.00886896 -0.0517459 -0.0757613 -0.0763744 -0.0986088 -0.163602 1.41088)) +(208.983 0.298555 0.0377969 #(0.0164121 0.0048719 -0.0123277 -0.0082839 0.00553303 0.0215874 0.00343585 -0.0106931 -0.0143605 -0.0149133 -0.000867135 0.00882374 -0.00160873 -0.0229544 -0.0199348 0.0112933 0.0268215 0.00930974 -0.0129465 0.00684308 0.00823984 -0.00100629 -0.00874536 -0.0125536 0.0018266 0.00222032 0.0179517 0.0318532 0.0216125 -0.00395573 0.00757547 0.000995567 -0.0228842 -0.0368795 -0.018438 -0.00111154 -0.0249076 -0.0299492 0.000929623 0.034715 0.0335621 0.0270658 0.0181262 -0.000710647 -0.0431774 -0.0595626 -0.0734814 -0.128686 -0.215031 1.46608)) +(169.872 0.295057 0.0416766 #(0.0319486 -0.0152698 -0.0178871 -0.00121978 0.0101795 0.0113419 0.00466058 -0.0163847 -0.00962441 -0.00255257 0.0034453 0.00333557 -0.00638092 -0.0185545 -0.0171695 0.00620859 0.027439 0.00889597 -0.00634335 0.00222882 0.00733991 0.00272018 -0.00324214 -0.00743471 -0.0202102 -0.0144455 0.0143375 0.0353734 0.03177 0.0180433 0.00470567 0.00350029 -0.0211588 -0.0400762 -0.0312031 -0.00502416 -0.0137467 -0.0287056 -0.00591527 0.0317417 0.0557392 0.030424 0.00295205 -0.00796262 -0.0331349 -0.0705161 -0.0935693 -0.117755 -0.17632 1.44112)) +(198.736 0.583121 0.0541678 #(0.0239533 -0.0108176 -0.0102808 0.00564068 0.0150349 0.00994732 -0.00604523 -0.00984589 -0.0142772 -0.0121714 -0.00415331 -9.11199e-005 -0.00732939 -0.0188397 -0.00379378 0.0155464 0.0238681 0.0102193 -0.00649659 -0.0166725 -0.00159701 0.0168372 0.00555774 -0.0076568 -0.0152812 0.00621925 0.0304524 0.0302777 0.0179796 -7.1259e-005 -0.0110991 -0.0120554 -0.0207771 -0.0196221 -0.019649 -0.0276093 -0.0267218 -0.00462518 0.0217483 0.0300955 0.0254635 0.0179527 0.00908021 -0.0147737 -0.0434505 -0.0549393 -0.067622 -0.0980195 -0.11752 1.34832)) +(235.893 0.196632 0.0288715 #(0.0304126 -0.0184424 -0.0165599 -0.000407823 0.00801631 0.0195737 0.0118165 -0.00905007 -0.0134561 -0.0135 -0.00394936 0.00567199 0.00352691 -0.0209869 -0.0335421 0.00501761 0.033716 0.0178405 0.00147093 -0.011718 -0.00133608 -0.00135017 0.00902945 0.00737444 -0.0033788 -0.00925621 -0.0209713 0.0180258 0.0548861 0.0175237 -0.0085279 -0.00515863 -0.0139746 -0.031351 -0.0115241 0.00705294 -0.0364894 -0.0527857 -0.0113735 0.0463322 0.0573369 0.0344311 0.019218 0.00187843 -0.0302693 -0.0656353 -0.0907326 -0.155003 -0.284321 1.55441)) +(250.351 0.920652 0.0606419 #(0.0221283 -0.00175026 -0.00689412 0.000872708 0.00825388 0.00110956 -0.00632789 -0.0125022 -0.0104057 -0.00936074 -0.00616766 0.00522704 0.000860839 -0.00548061 -0.0014818 0.00943791 0.00798624 0.000154997 -0.00816161 -0.00716682 0.000403966 0.00149304 0.00596023 0.00691071 0.00706264 0.0106029 0.0144444 0.01869 0.0103569 -0.00377258 -0.00598677 -0.011182 -0.0229358 -0.0277385 -0.0171593 -0.00963866 -0.0130767 -0.00448601 0.01284 0.0232398 0.0183027 0.00684207 0.000345183 -0.017907 -0.0388241 -0.0491714 -0.0555385 -0.0671155 -0.080383 1.27961)) +(265.144 0.37479 0.037597 #(0.0178487 0.0013791 -0.0116388 -0.00507206 0.0138357 0.0176418 0.0040927 -0.0179262 -0.017936 -0.00558455 0.00209339 -0.00600955 -0.011245 -0.00868085 -0.00205561 0.000295947 0.0125599 0.0156985 -0.00318278 -0.0132323 -0.000274777 0.00777626 -0.00183865 0.00266585 0.0125194 0.00603461 -0.00305746 0.0220627 0.0328774 0.00937883 -0.00296813 -0.0139498 -0.023661 -0.0265224 -0.0152562 -0.00981502 -0.0187505 -0.0249964 -0.00613381 0.0245956 0.0383716 0.0292479 -0.00259061 -0.00982094 -0.0297847 -0.0422148 -0.0701577 -0.115859 -0.177598 1.41175)) +(250.53 0.735674 0.0541892 #(0.0238545 -0.00486949 -0.00173591 0.00252099 0.00404998 0.00118642 -0.00418862 -0.0123793 -0.0138166 -0.00838696 -0.00266911 -0.000717441 -0.00433613 -0.00087901 3.08753e-005 0.00695944 0.00812309 0.00161619 -0.00106495 -0.00230766 -0.00318343 -0.00717512 0.00130251 0.0107457 0.00679086 0.00860716 0.0173261 0.0173051 0.0100283 0.00988019 0.00145606 -0.0181773 -0.0255863 -0.0227028 -0.0191551 -0.0156616 -0.0149123 -0.00943028 0.00703709 0.0185155 0.0208948 0.0180594 0.00541843 -0.016114 -0.0379061 -0.0507604 -0.0578965 -0.0768728 -0.0909356 1.29924)) +(197.598 0.485401 0.0495631 #(0.0248193 -0.00306678 -0.00667275 -0.0014236 0.0114491 0.0091926 -0.0023926 -0.0167224 -0.0201609 -0.00339142 -0.00311447 -0.00213343 -0.00661917 -0.00708419 0.00117074 0.0105285 0.010503 0.000885714 -0.00157855 -0.00449273 -0.0024985 -0.000379483 -0.0043849 0.0022342 0.0114984 0.0120889 0.0118227 0.0206663 0.0203387 0.01268 -0.00367646 -0.0148372 -0.0196786 -0.0256279 -0.0246386 -0.0201119 -0.0148319 -0.00916508 -0.00126804 0.0198383 0.0319355 0.0159117 0.00101828 -0.0089909 -0.0292361 -0.0476222 -0.0687146 -0.089934 -0.113823 1.33378)) +(125.124 0.316632 0.0503045 #(0.0130568 -0.00225892 0.00216152 0.0102169 0.00996052 -0.00255912 -0.0097279 -0.0196243 -0.00656228 -0.000937932 -6.12063e-005 -0.000608431 -0.00526008 -0.00223335 0.00268855 0.00317693 0.00183598 0.00660908 0.00583385 -0.00116981 -0.00278075 -0.00730575 -0.0127456 -0.00600758 0.00295042 0.00742113 0.0148913 0.0264792 0.0296855 0.00264396 -0.00385496 -0.00327753 -0.023196 -0.0218689 -0.015055 -0.00831472 -0.0139174 -0.0128882 -0.000967953 0.012294 0.0210776 0.0214656 0.0105105 -0.0134574 -0.0314187 -0.0453388 -0.0664272 -0.107779 -0.148171 1.37876)) +(71.37 0.227496 0.0564585 #(-0.0142429 0.012727 0.0152038 0.013247 0.0124478 0.00703828 -0.0126102 -0.0229412 -0.0168578 -0.00561364 0.00559436 0.00298623 -0.0049227 -0.00038521 -0.00127981 0.00423441 0.000763587 0.00976382 0.0108994 0.00630644 -0.00368733 -0.0148032 -0.023322 -0.0161698 -0.000889858 0.011531 0.0186532 0.0329139 0.0305486 0.00665483 -0.0125951 -0.0144017 -0.0205354 -0.0305956 -0.0183857 -0.000585577 0.0114074 0.00891327 0.00153785 0.00446643 0.00473343 0.015059 0.0101803 -0.0146464 -0.0351526 -0.0511088 -0.0647666 -0.0850186 -0.118079 1.33668)) +(40.4377 0.0852366 0.0459113 #(-0.0335089 0.029908 0.0183897 0.0176984 0.0101193 0.00829117 -0.0170098 -0.0268985 -0.022606 0.00232026 0.0189546 -0.0045041 -0.00575308 -0.0100939 0.00425405 0.00177554 0.00632439 0.0070991 0.0135077 0.0172888 -0.00309632 -0.0159993 -0.0288205 -0.0254887 -0.0108957 0.00733041 0.0214328 0.0301479 0.0306404 0.0070994 -0.0123194 -0.025963 -0.0100594 -0.00332728 -0.00658321 -0.000959254 0.00177248 0.00985076 -0.0049481 -0.00260225 0.00144116 0.00476165 0.00342908 -0.0128849 -0.0221734 -0.0326228 -0.0534822 -0.0924536 -0.143692 1.34984)) +(27.3832 0.070801 0.0508484 #(-0.0140748 0.0135211 0.0169284 0.0134048 0.00664361 -0.000844623 -0.025384 -0.00976012 0.00801802 0.00636203 -0.00289115 -0.0127367 0.000562452 0.00700169 0.00416503 0.00548033 0.00503239 0.00518513 0.00212309 -0.00811506 -0.0249022 -0.0165552 -0.00808011 -0.0032732 -0.00323997 0.0128592 0.0143886 0.0210239 0.0149843 -0.0102482 -0.00523455 -0.0127067 -0.00629629 -0.0118239 -0.00186732 0.00661671 0.000807708 0.0076143 -0.00151332 -0.0141276 0.000588052 0.013716 -0.00222398 -0.0188076 -0.0188453 -0.0187286 -0.0391334 -0.0564238 -0.0793644 1.23514)) +(30.7375 0.040934 0.0364929 #(-0.0243691 0.00812592 0.015261 0.01097 0.0205355 0.0101767 -0.0151796 -0.0251579 0.00184063 0.0088331 0.00252205 0.000583772 -0.00157531 -0.000798763 0.00905121 0.00117476 0.00355867 -0.00185548 0.00468458 -0.00729399 -0.0289016 -0.0190386 0.00930854 -0.00472978 -0.0131431 -0.00543118 0.00841419 0.0272355 0.0256443 -0.00636553 -0.00757628 -0.00558504 -0.000516058 -0.00121443 -0.0138289 0.00110727 0.00668947 0.00434654 -0.00919808 -0.0198922 0.00235468 0.0144602 -0.000975259 -0.0245124 -0.0246625 -0.015985 -0.0371288 -0.0397989 -0.0669062 1.22136)) +(42.0859 0.00626129 0.0121973 #(-0.0734655 0.0296172 0.013634 0.0452539 0.00702914 0.057469 -0.0232954 -0.0727147 -0.0229838 0.0545064 0.022556 -0.0378221 -0.0116609 -0.0131154 0.0381253 0.0259823 -0.0219215 -0.0248628 0.0469329 -0.00591986 0.0161304 -0.0248895 -0.0474258 -0.0134104 -0.011063 0.0414246 -0.0607445 0.0508991 0.0641952 0.00526139 -0.0600509 0.00150282 0.00627574 -0.070137 0.0242186 0.0169948 0.0408282 0.0438345 -0.0204922 -0.0610643 -0.0804496 0.0966152 0.0588874 -0.0136561 -0.0697122 0.00834575 -0.047428 -0.0855743 -0.478215 1.63444)) +(48.3822 0.0133138 0.0165886 #(-0.0991241 0.0620696 0.0256428 0.0325504 0.030601 0.0200286 -0.0346818 -0.0543453 -0.000353481 0.0292389 0.0225596 -0.0231814 -0.0230041 -0.00406665 0.0324386 0.00882869 -0.0235801 0.0419879 0.00354304 -0.0088214 0.00179125 -0.0386059 -0.020162 -0.0161291 -0.0274193 0.0200131 0.00125343 0.0450822 0.0571638 -0.0335057 -0.0273933 -0.0201817 -0.0220575 -0.0085605 -0.000251926 0.0202286 0.0402841 0.0305421 -0.0148375 -0.0251732 -0.04472 0.0420287 0.0255921 -0.0131808 -0.0380019 -0.0228509 -0.0479855 -0.104387 -0.277699 1.47947)) +(52.3586 0.0659523 0.0354912 #(-0.0350294 0.0226496 0.0266707 0.0151374 0.00559978 -0.00178336 -0.0131273 -0.00792491 0.00702189 0.00803718 0.000224972 -0.0104286 -0.0107735 0.000890825 0.000619345 0.00514007 -0.000477151 0.00445113 0.0122391 0.00292333 -0.0091859 -0.0264601 -0.0178257 -0.00867586 0.00144957 0.00389939 -0.00103973 0.00526759 0.0114127 0.00266532 -0.0114983 -0.0129203 -0.0101913 0.00682779 0.023871 0.0120872 0.00875099 0.0033859 -0.00336156 -0.00727741 -0.00798061 0.00279848 -0.00798744 -0.0160221 -0.02748 -0.0249909 -0.0413176 -0.0503363 -0.0665837 1.23408)) +(57.2864 0.0998289 0.0417448 #(-0.0107891 0.0182459 0.0133387 0.00654529 0.00351746 -0.0028236 -0.00652551 -0.00276973 0.00189705 0.00363537 -0.00543967 -0.00428984 -4.74181e-005 0.00728144 -0.000418819 -0.00318095 0.00296512 0.00149376 0.00209253 -0.0105876 -0.0105755 -0.00732988 -0.0124828 -0.00540931 -0.00364074 0.00253872 -0.000591894 0.0020125 0.00672111 -0.0103777 -0.00817489 -0.00341224 0.00892754 0.00393065 0.00183264 0.0170761 0.0103609 0.0093558 -0.00221637 -0.00689539 -0.00883095 -0.00260063 -0.00561736 -0.0152408 -0.0198652 -0.0251051 -0.0359384 -0.043327 -0.0516084 1.19939)) +(63.2886 0.0659521 0.0322813 #(-0.0395131 0.0278336 0.0226114 0.0208169 0.00156559 -0.00586198 -0.00373168 -0.0129797 -0.000442788 0.00591266 0.00384389 -0.00649693 -0.000432298 0.00820201 0.00205019 -0.00693928 -0.00561469 0.00651516 0.00426545 -0.00287469 -0.0195372 -0.0148713 -0.00282639 -0.00135895 0.00476877 0.00385195 -0.00114983 0.00160519 0.0150339 -0.00888809 -0.0157333 -0.00871617 -0.00192295 0.00638566 0.00653376 0.0147419 0.00964909 0.00830972 -0.00471322 -0.00721979 -0.00854983 -0.00297041 0.000582071 -0.00321452 -0.0251575 -0.0448269 -0.0465566 -0.0617166 -0.0814745 1.26877)) +(68.2143 0.127344 0.0432067 #(-0.00650372 0.0166661 0.0110006 0.0046084 -0.000191608 -0.000655383 -0.0075612 -0.00289214 0.00188358 0.00579054 0.000329202 -0.00681358 -0.00225101 -0.000353251 0.0031628 -0.0053415 -0.000525401 0.00656196 0.00272409 0.00256422 -0.0160209 -0.0140322 -0.00207772 -0.00301927 -0.000189949 -0.00236457 0.00311191 0.00706533 -0.000524762 -0.00984277 -0.0108244 -0.00768298 0.000888997 0.00214318 0.0071796 0.0118653 0.0159322 0.00963205 -0.00200409 -0.0107815 -0.00688397 0.000662548 0.00124322 -0.0216095 -0.024252 -0.0275861 -0.0290191 -0.0455658 -0.0594961 1.20854)) +(74.5766 0.00960274 0.0113474 #(-0.0930925 0.0474147 0.0783675 0.00847634 -0.0083235 0.0389507 -0.0156469 -0.0811489 -0.00383005 0.0271399 0.0027488 -0.0036905 -0.0380551 0.0424861 0.036423 -0.0258928 -0.0261861 0.00709007 0.0423739 0.0478494 -0.0457433 -0.0682701 -0.0230027 0.0330979 0.0021217 -0.00664132 -0.0268997 0.0548632 0.100473 -0.0711387 -0.0110561 -0.0158289 -0.0476065 -0.0351137 0.00284219 0.0323319 0.0313311 0.0736398 0.0142766 -0.10177 -0.0582263 0.0770375 0.0914699 0.0357695 -0.12508 -0.0345359 -0.0237482 -0.0585581 -0.687455 1.80702)) +(89.851 0.0668036 0.0272671 #(-0.047951 0.0391961 0.0312392 0.0264315 0.0152606 -0.0229461 -0.0203805 -0.0182092 -0.00178092 0.00435629 -0.00460121 -0.00718773 -0.00219992 0.00637422 0.00988643 0.00875952 0.00355863 0.0092556 -0.00376029 -0.00369781 -0.0084366 -0.0248106 -0.00997018 -0.00992863 -0.00298569 0.00552284 0.0193635 0.0324098 0.00560115 -0.0147652 -0.0174123 -0.0176175 -0.017063 -0.00976483 0.00645685 0.0115746 0.0243375 0.0212918 0.0038104 -0.00756 0.00845826 0.00991446 0.00809276 -0.000765567 -0.0407473 -0.0481121 -0.0785197 -0.118162 -0.175228 1.42139)) +(111.491 0.0612596 0.0234406 #(-0.071768 0.0568083 0.0427606 0.0216603 -0.00175519 0.00236969 -0.0168044 -0.027955 -0.00413897 0.00759891 0.00307185 -0.0137154 -0.021489 0.00188837 0.0194342 0.0167963 0.0109949 -0.00132022 0.0129203 0.00409717 -0.016515 -0.035451 -0.0211164 -0.0147696 -0.00623048 0.017651 0.0231703 0.0352329 0.0277801 -0.0201851 -0.0270755 -0.0333369 -0.0135395 -0.0048966 -0.00213377 0.01776 0.0243864 0.0268 0.00479255 -0.0136091 0.00196506 0.0109521 0.0263541 0.00149658 -0.0351393 -0.0414662 -0.0804536 -0.15343 -0.262886 1.52039)) +(131.563 0.0385887 0.0171263 #(-0.0518673 0.0134846 0.0263128 0.0468026 0.024454 0.0220736 -0.0400596 -0.0676488 -0.0114445 0.0413724 0.0448596 -0.0289181 -0.0607654 0.00419211 0.039212 0.0198165 -0.0106986 -0.00978497 0.0268256 0.0153281 -0.014289 -0.0258232 -0.021492 0.00140582 -0.0194537 -0.0176859 0.00346931 0.0616223 0.0476843 0.000242224 -0.0396149 -0.0480542 -0.0287999 0.00734256 0.00921102 0.0219239 0.0281868 0.0214498 0.0045841 -0.0526773 -0.0290021 0.0477786 0.066508 -0.00482082 -0.060896 0.00723903 0.00689539 -0.17291 -0.656903 1.81153)) +(151.886 0.102626 0.0259939 #(-0.070856 0.0486957 0.0480601 0.0368429 0.0182886 -0.00829156 -0.0513057 -0.0475156 -0.00697538 0.0443591 0.0264049 -0.0186967 -0.046636 -0.00991082 0.0358113 0.0296259 -0.00965236 -0.00183771 0.0116684 0.0166791 -0.0164862 -0.0397139 -0.0181811 -0.0084272 -0.01239 -0.000257272 0.0267701 0.0470878 0.0342028 -0.0154802 -0.0370322 -0.0415501 -0.0235126 1.97047e-005 0.0225005 0.0265028 0.0239742 0.0125777 -0.00895148 -0.0232263 -0.000947537 0.0428729 0.0258008 -0.0298816 -0.037036 -0.00471161 -0.0249833 -0.174155 -0.397768 1.60503)) +(165.11 0.169794 0.0320682 #(-0.0409658 0.0441689 0.0293712 0.0214998 0.0154116 -0.00248447 -0.0422952 -0.0478381 -0.00388453 0.0270632 0.0266513 -0.00557179 -0.022944 -0.0116277 0.0116475 0.0182246 0.00737678 -0.00598205 -0.00128794 0.00345216 -0.00394256 -0.00695017 -0.0256291 -0.0322332 -0.012631 0.0176517 0.0309905 0.0230604 0.0224319 -0.0106256 -0.0268479 -0.0207674 -0.00587152 -0.00570336 -0.00197812 0.0122906 0.0205968 0.031643 0.00252642 -0.0332331 -0.00542228 0.0405915 0.0309338 -0.0143715 -0.0384462 -0.0185082 -0.0347614 -0.166035 -0.349634 1.55773)) +(177.174 0.178624 0.0317519 #(-0.0375195 0.0292643 0.0300942 0.0307154 0.0193178 -0.00509529 -0.0345436 -0.0373165 -0.0172528 0.0236766 0.0201161 -0.0183973 -0.0276741 0.00996924 0.0330329 0.0152227 -0.00951397 -0.0122329 -0.00113485 0.0194899 -0.0119267 -0.0292984 -0.015638 -0.0142287 -0.0148578 -0.000859865 0.0260062 0.0534978 0.0402742 -0.0219816 -0.040437 -0.0341774 -0.0049463 -0.0116811 -0.0123897 0.0190348 0.0504628 0.0449273 -0.00894907 -0.0495895 -0.0187866 0.0407222 0.046073 -0.00801632 -0.0446076 -0.0182126 -0.03077 -0.167466 -0.369669 1.57394)) +(179.99 0.221245 0.03506 #(-0.037004 0.0260371 0.0372679 0.0497295 0.0157299 -0.0244911 -0.0537488 -0.0510671 0.00512908 0.05199 0.0203676 -0.0338469 -0.0238147 0.0127183 0.0230843 0.00442021 -0.0115414 0.00421587 0.0188467 -0.00272606 -0.0256457 -0.0344065 -0.0104499 -0.00267908 -0.00204974 0.00352165 0.02398 0.0343543 0.0255179 -0.0152773 -0.0303301 -0.0266642 -0.0139434 -0.00355751 -0.0084824 0.0107571 0.0423518 0.0526576 -0.00233367 -0.0445417 -0.0249914 0.0319504 0.0506834 -0.0160456 -0.0561795 -0.0084321 -0.00738221 -0.153557 -0.379863 1.55632)) +(166.887 0.252327 0.038884 #(-0.0419053 0.0366535 0.0498127 0.0359369 0.00208074 -0.0250268 -0.0524974 -0.0402762 0.00682585 0.0354895 0.0297739 -0.0147708 -0.0304251 -0.00374599 0.0183841 0.0130221 0.00121661 0.00411938 0.00494517 0.000507366 -0.0263356 -0.0463632 -0.0168647 0.0149596 0.0144969 0.00307392 0.0082568 0.0288554 0.0295293 -0.00737698 -0.0363064 -0.0244228 -0.0110509 -0.00137184 -0.01354 0.00159516 0.0392046 0.0550105 0.0155153 -0.0394186 -0.0271276 0.0202588 0.0342747 -0.0055672 -0.0407041 -0.0119139 -0.0198007 -0.157004 -0.344951 1.53129)) +(164.943 0.182476 0.0332611 #(-0.0614847 0.034366 0.0618075 0.0440773 0.010115 -0.0176925 -0.0502932 -0.0698586 -0.0117179 0.0583499 0.0553452 -0.0141319 -0.052825 -0.00920142 0.0291995 0.0159293 -0.00586749 -0.00306322 0.0226316 0.00427445 -0.0340741 -0.0437776 -0.0123615 0.00698813 0.00470649 0.00949797 0.00789906 0.0335011 0.0219034 -0.00266724 -0.0265675 -0.030155 -0.0143053 -0.0093868 -0.00158663 0.0163901 0.0203923 0.0417646 0.0187303 -0.0392964 -0.037276 0.0437944 0.0678762 -0.016769 -0.0789091 -0.0197703 0.0398731 -0.156601 -0.511722 1.65878)) +(176.99 0.261053 0.0384053 #(-0.06 0.056536 0.045999 0.0280942 0.0117416 -0.0124533 -0.0449422 -0.0463361 -0.00718186 0.0308653 0.0198448 -0.0192072 -0.0242862 0.0065568 0.031481 0.0162032 -0.00801501 -0.00216827 0.0134013 -0.00587761 -0.0383848 -0.0362193 -0.0129257 0.0157857 0.00474063 -0.00184301 0.0202611 0.041013 0.0198278 -0.0191734 -0.029208 -0.0221024 -0.0116136 -0.0121702 -0.00611537 0.0173498 0.0404119 0.0315245 -0.00593292 -0.0237962 -0.000431722 0.0439062 0.0334822 -0.0297822 -0.0607389 -0.0164012 -0.00830834 -0.154607 -0.362478 1.54998)) +(176.048 0.159462 0.0300963 #(-0.0377232 0.0103334 0.036835 0.0488153 0.0179723 -0.00819109 -0.0460628 -0.0619188 -0.00111458 0.0446256 0.032363 -0.00836746 -0.0360712 -0.00850298 0.0216202 0.0175984 -0.000914048 -0.0173185 0.00126597 0.0264074 -0.00629105 -0.043736 -0.017196 0.00494882 -0.000320422 -0.012511 0.00430157 0.0466093 0.0305521 -0.0031329 -0.0376142 -0.024873 0.00750779 -0.012678 -0.0104912 0.00134055 0.0376222 0.0412994 -0.0218273 -0.0452171 -0.0128663 0.072725 0.0680508 -0.0173601 -0.0684261 -0.0212582 0.0188153 -0.175166 -0.561992 1.72452)) +(171.946 0.2352 0.0369847 #(-0.0512015 0.0329072 0.0503361 0.0280294 0.00184622 -0.0107644 -0.0348259 -0.0337681 0.00209173 0.0265416 0.028044 -0.0189349 -0.0371111 -0.000802031 0.0279831 0.0122725 -0.00874739 -0.00112342 0.0180879 0.000223799 -0.0259366 -0.0351892 -0.00449204 0.00197593 -0.0162875 -0.011366 0.0181628 0.0541492 0.0395807 -0.0167336 -0.0418708 -0.0160073 -0.00774302 -0.00128406 -0.00712924 -0.00703709 0.0178146 0.0397532 0.00726889 -0.0174794 -0.00498909 0.0427668 0.0408804 -0.0175914 -0.0525046 -0.0244365 -0.014682 -0.171468 -0.395718 1.59284)) +(185.859 0.163683 0.0296764 #(-0.0468658 0.0116617 0.0555765 0.036102 0.0116869 -0.0136073 -0.0419413 -0.0311445 -0.015847 0.0536179 0.0374088 -0.0318291 -0.0562696 -0.0204646 0.0520056 0.0366832 -0.00267281 -0.0268453 0.00390152 0.0151844 -0.0141306 -0.026449 -0.00214409 -0.00146158 -0.0202671 -0.0306729 0.00986482 0.0542944 0.0595679 0.00293662 -0.0374089 -0.0316308 -0.0279362 -0.00383883 -0.00461755 -0.00381387 0.0302674 0.0462364 0.00234255 -0.0420869 -0.0176493 0.0621579 0.0781717 -0.0259631 -0.0837177 -0.0197173 0.0222038 -0.172749 -0.543442 1.71216)) +(211.324 0.258974 0.0350069 #(-0.0303184 0.0212199 0.0351346 0.0323836 0.0108293 -0.0194528 -0.0440712 -0.0258231 0.0179244 0.0423101 0.00743043 -0.040367 -0.0363898 0.0067014 0.0337238 0.0109171 -0.0145224 -0.00777405 0.0187512 0.010748 -0.0157507 -0.020169 -0.00503133 -0.00636303 -0.0319918 -0.0279937 0.0172805 0.0607111 0.0519986 -0.00764891 -0.0419867 -0.0321224 0.0100713 0.00236086 -0.0196657 -0.0170583 0.0223451 0.0362193 0.000122523 -0.0184589 0.0140273 0.0644042 0.0497302 -0.0380606 -0.0744375 -0.0264989 -0.0209174 -0.164711 -0.384479 1.59087)) +(230.546 0.254813 0.0332454 #(-0.0214216 0.00872379 0.0339929 0.0315809 0.0174031 -0.0232373 -0.0489485 -0.0241287 0.0209643 0.0453702 0.0190406 -0.0440306 -0.0441669 -0.00157853 0.0268724 0.0234296 -0.000401617 -0.0057701 0.000344993 -0.0054568 -0.0178071 0.0024068 0.0155485 0.000746876 -0.0375718 -0.0484998 0.00853225 0.0571187 0.0551759 -0.0142224 -0.0451274 -0.0277836 0.0263546 0.0402985 -0.0197452 -0.0401687 -0.00351748 0.0313089 0.00705256 -0.0369839 -0.00653953 0.0851077 0.0978434 -0.0156217 -0.102129 -0.0527658 0.00792703 -0.158984 -0.494505 1.67382)) +(251.512 0.22152 0.0296775 #(0.00271906 -0.0125085 0.0301646 0.0306547 0.00855251 -0.0179234 -0.0350287 -0.0305762 0.00779454 0.053486 0.0394365 -0.0393962 -0.0650717 -0.0198502 0.0326874 0.039916 -0.0010092 -0.0179188 0.00205602 -0.00398159 -0.00877683 0.0106262 0.0187416 -0.0120917 -0.0564597 -0.0545574 0.0119312 0.0765 0.0649359 -0.0149672 -0.0521681 -0.0268912 0.0228738 0.0277597 -0.00505434 -0.0391086 -0.000955081 0.0337932 -0.00277864 -0.0493297 -0.0119853 0.100552 0.124828 -0.0159932 -0.127861 -0.0612138 0.0295559 -0.144989 -0.555044 1.70991)) +(254.186 0.155867 0.0247629 #(0.011018 -0.035849 0.0315776 0.0392745 0.01848 -0.0184897 -0.0290829 -0.049739 -0.000114797 0.0517803 0.04403 -0.0251357 -0.0530782 -0.0079027 0.0214459 0.0319004 -0.0185972 -0.0210457 -0.00556451 0.0118538 0.000887009 0.0257463 0.0265477 -0.0284303 -0.0724463 -0.0721507 0.0469847 0.0785231 0.069301 -0.026447 -0.064972 -0.032767 0.00653783 0.0563972 0.0303594 -0.0350536 -0.0475477 0.0379776 0.00958391 -0.0490296 -0.0492565 0.0859668 0.161288 -0.000991608 -0.140484 -0.0439296 0.0763862 -0.147115 -0.750695 1.84834)) +(225.37 0.0803291 0.0188794 #(0.0290101 -0.0687017 0.0407707 0.0383633 -0.0152389 0.00254714 0.0114647 -0.0328925 -0.021924 0.00257726 0.0623568 -0.00416147 -0.0660898 -0.0300196 0.0572706 0.0552422 -0.027837 -0.0653128 0.00149151 0.0264922 -0.00315019 0.0193053 0.0486365 0.00427569 -0.0987687 -0.0861261 0.00501995 0.0945006 0.109231 -0.0131216 -0.077788 -0.0512939 -0.00858637 0.0620822 0.041699 -0.0369608 -0.0380424 0.0273551 0.0409665 -0.0644617 -0.0854918 0.0805598 0.178136 0.0300991 -0.186435 -0.0584791 0.205418 -0.075875 -1.13303 2.07226)) +(198.485 0.0417265 0.0144991 #(0.0414603 -0.0623938 0.0061811 0.0288222 -0.0158102 0.0252802 0.00307337 -0.00304176 0.00367747 -0.0489033 0.0357009 0.0204158 -0.0552591 -0.0256414 0.0346049 0.0958179 -0.0284009 -0.100873 -0.00722169 0.0205522 0.0295442 0.033256 0.0421494 0.00768483 -0.110423 -0.0846969 -0.0244979 0.0889337 0.157045 0.00102777 -0.0813333 -0.0900497 -0.0138341 0.0341514 0.0721558 0.00377355 -0.033424 0.010766 0.0245269 -0.0515001 -0.119286 0.0335791 0.213235 0.125951 -0.204453 -0.179761 0.270221 0.202002 -1.65027 2.32378)) +(171.548 0.1509 0.0296587 #(0.0250778 -0.0426171 0.00843798 0.0396997 0.0226322 -0.0146932 -0.0283293 -0.01936 0.0069322 0.0354412 0.0250028 -0.0357834 -0.0414478 -0.0136723 0.0292158 0.020287 -0.00117164 -0.00726955 -0.00706735 0.000159039 -0.00407658 0.0190887 0.0257392 -0.0278326 -0.0682253 -0.0552612 0.0202806 0.0931883 0.0784599 -0.037487 -0.082894 -0.0424946 0.0518775 0.0627942 0.000169138 -0.0458972 -0.0190695 0.0107115 -0.00659794 -0.0314802 0.00511231 0.0991288 0.0788463 -0.0108271 -0.0699992 -0.0146887 -0.00873203 -0.228192 -0.553044 1.75651)) +(138.651 0.0571929 0.02031 #(0.0213914 -0.0306978 0.00848927 0.0130779 0.00721775 0.00427365 0.00961346 -0.0314829 -0.018867 0.036295 0.03503 -0.0305203 -0.0463152 -0.0107846 0.0382213 0.0409777 -0.0373991 -0.0384969 0.0128019 0.00295524 0.0157249 0.0419502 0.0294107 -0.0318793 -0.11091 -0.0681277 0.0179675 0.131618 0.114326 -0.0427296 -0.109902 -0.0736138 0.0191553 0.091943 0.0543933 -0.0340794 -0.0436619 0.00746334 -0.0066161 -0.0679531 -0.0238454 0.0924077 0.161235 0.0122723 -0.139703 -0.0326624 0.115233 -0.166794 -0.931623 1.99133)) +(113.308 0.193753 0.0413518 #(-0.0270571 0.018724 0.0316812 0.0297654 0.00202789 -0.0163134 -0.0290023 -0.0123064 0.0176842 0.0233915 -0.00357253 -0.0336344 -0.0271282 0.00653117 0.0284495 0.0179925 -0.004167 -0.0157728 -0.00964692 0.000267421 0.00122534 0.0146035 0.00149512 -0.0396562 -0.058053 -0.0255875 0.0451789 0.0754793 0.044493 -0.0379303 -0.0597916 -0.015322 0.0420665 0.0354546 -0.0132543 -0.0383832 -0.0285421 0.000937585 0.0195054 0.0265873 0.0502106 0.0593278 0.0136192 -0.0502636 -0.0466451 -0.0180557 -0.0524014 -0.164365 -0.318595 1.53476)) +(103.037 0.0623253 0.0245944 #(-0.00724495 -0.00593484 0.0107629 0.0261896 0.0129414 0.00340164 -0.0251773 -0.0270683 0.00747135 0.0385192 0.018441 -0.0377958 -0.0304305 0.00450653 0.0229534 0.00567204 -0.0264594 -0.0176736 0.000876183 0.0471199 0.0172663 0.0124283 0.00241253 -0.0617734 -0.103682 -0.0406255 0.0578767 0.121063 0.0822661 -0.0454017 -0.102194 -0.042812 0.0321046 0.0833275 0.00602523 -0.0478943 -0.043304 0.000262387 0.00598665 -0.00374976 0.0385322 0.079333 0.0654235 -0.0354309 -0.092082 0.00159915 0.0131218 -0.204327 -0.571633 1.75234)) +(92.5577 0.120027 0.0360108 #(-0.0398489 0.0324612 0.0367935 0.0220619 0.00704562 -0.0272926 -0.0200099 -0.00659618 0.0169783 0.015708 -0.00599385 -0.0153675 -0.0128987 0.0082064 0.0102226 -0.000522355 -0.00199441 -0.00674596 -0.00220103 -0.00689017 -0.00809083 0.00336812 -0.0126411 -0.0439452 -0.04063 0.00361202 0.0505336 0.0555444 0.02238 -0.0310165 -0.038806 -0.00364963 0.0180895 0.00954 -0.00503501 -0.0195219 -0.0205427 0.00318622 0.0185383 0.0345637 0.0376351 0.0372337 0.00566722 -0.0260961 -0.0314731 -0.0229805 -0.0612615 -0.148592 -0.24421 1.45165)) +(66.5989 0.0842179 0.0355606 #(-0.0384904 0.0427509 0.0324356 0.0194716 -0.00585732 -0.0144022 -0.0118444 -0.00525952 0.0111836 0.00537657 -0.00948216 -0.00957872 -0.000929858 0.00996204 0.00650146 0.00151737 -0.00610687 -0.00883977 -0.0111524 -0.00821151 -0.0121669 -0.00254634 -0.0339117 -0.0355781 -0.013952 0.0280202 0.0436449 0.0292268 0.00874941 -0.0239858 -0.0194654 -0.00890681 0.0037191 -0.00475951 -0.00518569 -0.00236431 0.00776458 0.0118334 0.0107269 0.0178917 0.0261446 0.0384696 0.0138593 -0.0230752 -0.043364 -0.0319342 -0.0459236 -0.112816 -0.180369 1.35766)) +(42.7254 0.0264534 0.0248827 #(-0.0413135 0.0213958 0.036281 0.0248983 -0.0151715 -0.0222269 -0.00567853 0.00505671 0.017208 0.024368 -0.0203921 -0.0162792 0.000440382 0.0151094 0.0109901 -0.000613158 -0.00984668 -0.00906093 -0.00789341 0.00260445 0.0124987 -0.0123556 -0.0457957 -0.0562666 -0.0106157 0.0486385 0.0540115 0.0360568 -0.00307563 -0.0466828 -0.0306841 0.00913136 0.0174993 0.00528422 -0.0273256 -0.0166686 0.00261137 0.0230377 0.0120899 -0.00600584 0.0223933 0.0459099 0.00977329 -0.0223494 -0.0479412 -0.0230021 -0.0404154 -0.102133 -0.204478 1.38436)) +(30.9113 0.0516676 0.0408837 #(-0.014936 0.00941983 0.0118751 0.000575508 0.00581291 -0.00413739 -0.012136 0.0103523 0.00720992 0.0100773 -0.000124851 -0.00765056 0.00255218 0.000894253 0.00544408 0.000794387 -0.00215897 -0.00898489 -0.0117924 -0.00653947 -0.0064785 -0.00840759 -0.0105823 -0.0100678 0.000175767 0.0102663 0.00786819 0.0237505 -0.00215373 -0.0266525 -0.00900966 -0.00600343 -0.0028658 -0.00373159 -0.00238924 -0.00278976 -0.00429102 -0.00212087 0.00253061 0.0127614 0.0230914 0.0151189 0.00146143 -0.0117057 -0.00462498 -0.00318648 -0.0265484 -0.0369997 -0.0675645 1.14867)) +(15.3693 0.00836665 0.0233319 #(-0.0341159 0.00806944 0.0216334 0.0174292 -0.0149921 0.016248 -0.0180928 -0.00306738 0.0350942 0.00513288 -0.00769301 0.00579646 -0.0107035 0.0131971 0.00589453 -0.00674269 0.00261838 -0.00786856 -0.00176616 0.00564664 -0.0345646 -0.0240044 -0.0148234 -0.0133658 -0.00412353 0.0369617 0.00196105 0.0368174 0.00564198 -0.0501549 -0.0297051 0.0178704 0.0210161 -0.0155626 -0.00837293 -0.0178571 0.00812323 0.00816448 0.00151141 0.0221456 -0.00390799 0.026406 0.0064334 -0.00797861 -0.0261832 0.013857 -0.0837799 -0.0591936 -0.120175 1.27127)) +(7.76696 0.0131245 0.041107 #(-0.0123117 0.00617644 -0.00098044 0.00751582 -0.00251782 -0.00337365 -0.00106648 -0.00202962 0.024234 0.000865013 -0.000377017 0.00388929 -0.00333191 0.0133695 -0.00022004 -0.00378028 -0.00320862 -0.00759729 0.010062 -0.0256383 -0.0192849 -0.0214377 -0.0114302 -0.00124626 0.00155824 0.0193932 0.00236924 0.0225305 0.00325289 -0.026002 -0.0156565 0.0123504 0.013013 -0.00652565 -0.00493443 -0.0110295 -0.00472477 0.0120849 0.0080524 0.00918786 -0.00908903 0.0273415 -0.00444183 -0.0233399 -0.0047778 -0.00719849 -0.0426428 -0.018549 -0.0650151 1.15688)) +(8.89632 0.0142545 0.0400286 #(-0.00575181 0.0168131 -0.000191827 -0.023498 -0.00423681 0.025755 -0.0183111 -0.00376236 0.0252077 0.008183 -0.0122062 -0.003721 0.00288939 0.0148372 0.00886276 0.00423061 -0.00963574 0.000873132 0.00541097 -0.0280967 -0.00998672 -0.0238806 -0.0217161 -0.00753574 0.000230236 0.0280799 -0.00512027 0.00849866 0.0322065 -0.0343016 -0.00927757 0.00120511 0.0135002 -0.00237087 -0.0093355 -0.00156968 -0.00792312 0.012794 0.00838747 -0.0119611 0.00605868 -0.00193377 0.0117903 0.00816965 -0.0157005 -0.000300004 -0.0367019 -0.0246368 -0.0709357 1.15223)) +(9.78194 0.0170927 0.0418016 #(-0.0124638 0.0024989 -0.00185738 -0.00369259 -0.00329147 0.0015451 0.00184027 0.00970003 0.0141567 0.0120678 0.00775671 -0.00277263 0.00105104 0.000310846 0.00513042 -0.0141369 -0.008812 0.00521768 -0.00206552 -0.00604551 -0.0120649 -0.0176494 -0.0204137 -0.0115251 0.00627893 0.0162767 0.0108663 0.00560173 0.00467505 -0.02242 -0.0112209 0.000456198 0.00829053 2.30481e-005 0.00913467 -0.00846952 0.00517986 0.00864013 -0.00133154 0.00581594 -0.00610526 0.00869507 0.00727336 -0.00365842 -0.0143366 -0.0169279 -0.0336561 -0.0311221 -0.071088 1.16895)) +(11.5445 0.0160741 0.0373143 #(-0.0249007 -0.00275895 -0.000517276 0.00756758 -0.00172192 0.0176724 0.00486407 0.00102775 0.0190812 0.027876 -0.00029893 -0.00443258 -0.00532617 -0.0133783 -0.00615458 -0.00822798 -0.00903328 0.00488343 0.0122464 -0.0119956 -0.0122127 -0.0164293 -0.0183456 -0.00082874 -0.00101657 0.00939199 0.0092591 0.0164931 -0.0114048 -0.0252425 -0.0161846 -0.00699262 0.00668263 0.0180297 0.000800448 0.00638066 0.00681553 0.0168308 0.0103385 -0.00081722 -0.00148622 0.00392006 -0.00755191 -0.0011792 -0.0241647 -0.0123012 -0.0393747 -0.0402423 -0.0754633 1.19146)) +(13.3295 0.0127553 0.0309342 #(-0.0231698 0.0191559 -0.0139377 0.0092944 0.0121271 -0.000232179 -0.0124583 0.0134314 0.0164421 0.024357 -7.36386e-005 -0.0199401 -0.00337023 0.0151218 -0.00455778 -0.0115682 -0.0172743 0.000976708 0.017724 -0.0074562 -0.0285266 -0.0151716 -0.030822 0.00497904 0.00790638 0.0099445 0.0162362 0.0264739 0.0175367 -0.0501894 -0.0343044 -0.00901378 0.014952 0.0105903 -0.0101648 -0.000755211 0.0171476 0.0293293 0.00838466 -0.0102206 0.00315026 0.0306831 -0.00269206 0.00531439 -0.0326658 -0.0252288 -0.0474296 -0.0704353 -0.143764 1.28812)) +(15.3429 0.0120405 0.0280135 #(-0.0309064 0.0271264 0.0147487 0.00498133 0.00106183 0.0147637 -0.040844 -0.0169095 0.0389369 0.0194572 -0.00221378 -0.0170094 -0.00138509 0.0162374 0.00582746 -0.0230331 -0.0117961 -0.00156591 0.0229133 0.027122 -0.0540262 -0.0410968 -0.013133 -0.00158327 -0.0109391 0.0261228 0.0330272 0.0405228 0.0323432 -0.0623613 -0.0561195 -0.00527043 0.00668445 0.0267738 -0.00936441 -0.0283996 0.0234758 0.0255722 0.014511 -0.0129606 0.00174176 0.0403901 0.0353441 -0.000116604 -0.0455759 -0.0479024 -0.0481118 -0.0843258 -0.209947 1.37135)) +(17.6721 0.019402 0.0331344 #(-0.0350609 0.0339703 0.0145886 0.000690795 0.000922172 0.00738286 -0.01517 -0.0088783 0.0201723 0.0122574 -0.0158588 -0.0119165 -0.0019645 0.020945 -0.000870479 -0.0108681 -0.00586048 0.00538485 0.0104022 -0.00321434 -0.0157964 -0.0469299 -0.0215821 -0.00373954 0.00283885 0.0148254 0.0275313 0.0364303 0.0161417 -0.0308895 -0.0417433 -0.00377748 0.0165364 0.00397155 -0.0227846 -0.0260575 0.00618754 0.0551286 0.0147865 -0.0176932 0.00941883 0.0495573 0.031147 -0.00860301 -0.0380403 -0.0458936 -0.0610949 -0.096874 -0.18716 1.3588)) +(20.0442 0.0140521 0.0264774 #(-0.0709867 0.0453836 0.0460421 0.0146813 -0.0179832 0.00433517 -0.0165851 -0.00628279 0.0245804 0.0150767 -0.0114593 -0.0368579 0.00386748 0.0248403 0.00774181 -0.0237615 -0.0110972 0.00908011 0.0143327 0.012267 0.00781146 -0.0256289 -0.0705544 -0.0244927 -0.0213969 0.0392408 0.0426976 0.0769561 0.011974 -0.0784876 -0.0580746 0.0130622 0.0449024 0.0142022 -0.0384532 -0.0269607 0.00680663 0.0207385 0.0149218 -0.0149792 0.0278171 0.0648385 0.0568704 -0.00419316 -0.0892845 -0.0271809 -0.0635848 -0.137194 -0.290703 1.49428)) +(22.8017 0.0273646 0.0346427 #(-0.0720317 0.0448821 0.0348815 0.0233662 -0.000985435 0.00226309 -0.0135519 -0.0209769 0.0167468 0.0101012 -0.0194102 -0.00439263 0.00504041 0.0156837 0.00598467 -0.0264652 -0.0115608 0.0185426 -0.0068165 0.0100013 -0.00188157 -0.018496 -0.0458203 -0.0312296 -0.00116534 0.0335279 0.0330629 0.0395021 0.0183978 -0.0427994 -0.0459782 0.0054253 0.0243994 -0.00582722 -0.0111125 -0.0241409 0.0054475 0.0251814 0.00891366 -0.000905372 0.0228307 0.0523174 0.0382179 -0.00320691 -0.0354807 -0.0419394 -0.0835182 -0.139596 -0.249583 1.45587)) +(26.3474 0.0219953 0.0288932 #(-0.0765435 0.0426832 0.0419785 0.0283921 0.00340572 -0.00535423 -0.0212032 -0.0116924 0.00206213 0.00816488 -0.0127589 0.00934433 0.0163962 0.00930891 -0.00568188 -0.0355663 -0.0130979 0.0042239 0.0221761 0.0294585 -0.00590132 -0.0300225 -0.0529725 -0.04428 -0.00514512 0.0547305 0.0372759 0.0478592 0.0239117 -0.0702372 -0.0687804 0.0195622 0.0191373 0.0223794 0.0135526 -0.038104 -0.00282542 0.00433172 0.00929822 -0.00582157 0.0154465 0.0665377 0.0342229 0.00927136 -0.0205276 -0.0192793 -0.0956723 -0.177253 -0.343554 1.56045)) +(30.1984 0.030065 0.0315528 #(-0.0979213 0.0706986 0.0397353 0.027229 -0.00146723 -0.00438662 -0.0236935 -0.0188674 0.00900385 0.011066 0.00529251 -0.00704211 0.00609007 0.00670222 0.011048 -0.0216173 -0.0263168 0.00421382 0.0169606 0.0205924 -0.018071 -0.0136472 -0.0356033 -0.0382373 0.00240587 0.00751786 0.0412371 0.0584634 0.033329 -0.0663578 -0.0641406 -0.00811986 0.0285871 0.0444783 -0.00260303 -0.0335565 -0.018181 0.00985673 0.00558086 0.0118218 0.023386 0.0433098 0.0400329 0.0116843 -0.0148176 -0.058095 -0.0779079 -0.157939 -0.31358 1.52513)) +(32.1428 0.0318259 0.0314665 #(-0.0775589 0.051683 0.0288251 0.0187194 0.00984706 0.00338128 -0.0202275 -0.00651548 0.0136416 -0.00760369 0.00215332 -0.0233182 0.0134451 0.0247162 -0.00404254 -0.0118734 -0.018538 0.0113604 0.00736548 0.00204067 -0.0115196 -0.0197442 -0.0154772 -0.0363295 -0.0150368 0.0175515 0.0394107 0.053815 0.00585165 -0.0330152 -0.054677 -0.0159929 0.0341672 0.015965 -0.00299163 -0.0189119 -0.0067154 0.0143037 -0.000256563 -0.00532035 0.0260945 0.0429435 0.0476952 0.0109455 -0.0235557 -0.0298008 -0.0826709 -0.176099 -0.325686 1.54201)) +(31.4202 0.0318335 0.0318301 #(-0.0971744 0.0647286 0.0577288 0.0197214 -0.00649152 -0.0216951 -0.0189122 0.00437908 0.0284074 -0.000966733 -0.0171446 -0.0107114 0.00440035 0.0142388 0.00532634 -0.0126468 -0.02169 0.00523199 0.0297256 2.45184e-005 -0.00810739 -0.0215433 -0.0335994 -0.053856 -0.00465438 0.037238 0.0491757 0.0548962 0.014561 -0.073022 -0.0403319 -0.0130117 0.00834094 0.0434427 -0.00417276 -0.0078477 -0.0118494 0.00744896 -0.00313036 -0.0123154 0.0214602 0.059643 0.056315 0.00853147 -0.0377529 -0.0250175 -0.0860953 -0.178818 -0.327932 1.55029)) +(32.4444 0.0301064 0.0304621 #(-0.0807 0.057348 0.0412646 0.0366669 -0.00996071 -0.0130091 -0.0387371 -0.00774177 0.0350818 0.0241313 -0.0154081 -0.0231186 0.00127267 0.0151109 -0.000317825 -0.0114935 -0.0136006 -0.00971232 0.0131985 0.0123626 0.0233086 -0.0265093 -0.0606854 -0.0258504 -0.0165391 0.0251411 0.0470309 0.053574 0.0180307 -0.0502542 -0.0485886 -0.0164236 0.019835 0.0329606 -0.00101179 -0.0302517 -0.0018849 0.0308459 -0.00743693 -0.0159462 0.0094627 0.0539938 0.0554317 0.0208811 -0.0307534 -0.0204858 -0.0821197 -0.181269 -0.37734 1.5857)) +(40.9172 0.0650495 0.0398721 #(-0.0572582 0.0414552 0.0350494 0.0183922 0.00440463 -0.00850967 -0.00613651 -0.0179503 -0.00262387 0.0195232 -0.0131559 -0.00454892 0.00177392 0.0065445 0.00194393 -0.00781929 -0.00616173 -0.00313379 -0.000702812 -0.00178652 -0.014563 -0.0209123 -0.0269462 -0.0162782 0.00491859 0.0228838 0.0258315 0.027738 0.00459301 -0.0176909 -0.0295674 -0.0017052 0.0107792 -0.00448647 -0.00151116 -0.00392171 -0.00643332 0.00597558 0.0150378 0.0149934 0.0222908 0.0451681 0.0323751 0.00353828 -0.0263688 -0.050642 -0.0923144 -0.142247 -0.194605 1.40832)) +(42.9245 0.0380718 0.0297817 #(-0.0619835 0.0538987 0.0254833 0.0191851 0.000713942 -0.00965684 -0.0114323 -0.0178469 0.0175577 0.0131995 -0.0072923 -0.00832834 -0.00811007 0.00959091 0.00557504 -0.00996733 -0.00855112 -0.00974844 0.00913783 0.0117909 -0.0045425 -0.0256592 -0.0292943 -0.0307577 -0.00238131 0.0201101 0.0259082 0.0446931 0.0181626 -0.0452096 -0.0297406 -0.0143662 0.023201 0.0203186 -0.00421108 -0.0211625 -0.00441318 0.019116 0.000645667 -0.00607597 0.0221206 0.0483723 0.0479185 0.015123 -0.02304 -0.0353189 -0.100976 -0.171954 -0.291149 1.51649)) +(35.4435 0.0741689 0.0457449 #(-0.0592469 0.0408393 0.0310192 0.0213087 0.000897261 -0.0097075 -0.0127374 0.00034184 0.00697528 0.00416767 -0.00709337 -0.00543548 -0.00262597 -0.000460251 0.00462508 -0.000103108 -0.00210094 -0.000600998 -0.0064083 -0.00812498 -0.0110879 -0.014929 -0.0210607 -0.0126928 -0.00625044 0.0121755 0.0253735 0.0353037 0.00209597 -0.0177743 -0.0179092 -0.0111032 0.00635534 -0.000694276 -0.00804003 -0.00382186 0.00598897 0.00926817 0.00874331 0.0115986 0.0207321 0.0434171 0.0317387 0.00501884 -0.0295828 -0.0488442 -0.0859817 -0.140721 -0.179372 1.38875)) +(31.5655 0.0508454 0.0401347 #(-0.0590031 0.0481201 0.0415922 0.0145118 -0.00625927 -0.010634 -0.022698 0.00794115 0.0129372 0.011031 -0.00684227 -0.0269145 0.000574552 0.0097944 0.00870401 -0.0154143 -0.00608816 -0.00337432 0.00658044 -0.000562268 -0.0114323 -0.0168882 -0.0267139 -0.0354475 -0.00491647 0.0324642 0.0368173 0.0353376 5.39129e-005 -0.039796 -0.021031 -0.00123375 0.0136188 -0.00348024 -0.00871654 0.00380723 0.0164729 0.0135323 -0.00439517 -0.0080045 0.0109003 0.0528155 0.0444091 0.0206946 -0.0118078 -0.0443984 -0.10415 -0.168437 -0.257971 1.47706)) +(30.9527 0.0382595 0.0351577 #(-0.0677928 0.0651594 0.0430938 0.00356799 -0.0158889 0.000628987 -0.0127898 -0.00558382 0.0158968 -0.00226313 -0.00538957 -0.00778266 0.00155987 0.00443769 0.00375692 -0.0105507 -0.0224075 0.00426307 0.00792974 0.000294564 -0.000787178 -0.0161313 -0.0342735 -0.0403149 -0.00675935 0.0293195 0.0435918 0.0478281 0.00545949 -0.0534773 -0.037442 -0.0111263 0.0321929 0.020819 -0.00755799 -0.00482975 -0.00528935 0.0154923 0.00365394 -0.00549552 0.0121106 0.053678 0.0478409 0.019575 -0.0286409 -0.0335462 -0.0765612 -0.177995 -0.331 1.53233)) +(31.4075 0.0364452 0.0340646 #(-0.0649986 0.0576299 0.0324902 0.00773543 -0.00458665 0.00495247 -0.0191388 0.000145591 0.000613326 0.00395394 0.000636622 -0.0207581 0.00467082 0.0155624 0.0110861 -0.0131649 -0.0232556 -0.00176555 0.00395216 0.00802351 -0.00893858 -0.021152 -0.016588 -0.0283998 -0.0138537 0.0249458 0.0287153 0.0452579 0.0204232 -0.053952 -0.0535749 0.00280977 0.0440965 0.0328232 -0.0150095 -0.0388665 -0.0096805 0.0162576 0.0154429 -0.00290426 0.029801 0.0596534 0.0460045 -0.00865289 -0.0497685 -0.0141297 -0.0805603 -0.160605 -0.335686 1.53526)) +(31.6576 0.0348485 0.0331782 #(-0.0618954 0.0523533 0.0235303 0.0153525 0.00172889 -0.00168407 -0.0110182 -0.0142045 0.0170727 1.99435e-006 0.0017121 -0.0190737 -0.0111033 0.0169703 0.0280168 -0.01063 -0.0322064 0.00426402 -0.00485 0.0146215 -0.00758876 -0.0226077 -0.0252398 -0.0189545 -0.00568113 0.00980641 0.0269183 0.0392206 0.0257317 -0.0475402 -0.0534524 0.00178895 0.0586262 0.0278462 -0.0327184 -0.0414883 -0.0120922 0.029826 0.0131607 0.00598402 0.00931486 0.0642811 0.057244 -0.00679361 -0.0464739 -0.04173 -0.072625 -0.161229 -0.31275 1.52407)) +(34.7383 0.0559897 0.0401467 #(-0.0415582 0.026703 0.0259679 0.0111422 0.00204608 -0.00618647 -0.00950887 0.0120808 0.0102095 -0.00150538 -0.0114168 -0.0193223 -0.00463892 0.0133971 0.0187653 -0.00583736 -0.0127744 -0.0100488 0.0111868 0.0106626 -0.0205418 -0.0312655 -0.0304695 -0.0160161 -0.00137347 0.0194299 0.0309445 0.0366569 0.00705069 -0.0166283 -0.0404884 -0.00764167 0.0169512 0.0132674 -0.00907035 -0.0275286 -0.0054365 0.0307347 0.0158178 0.00474018 0.0264909 0.0460957 0.0291759 -0.00850643 -0.0359522 -0.0586856 -0.0731063 -0.11696 -0.205816 1.40186)) +(36.4119 0.0463771 0.0356887 #(-0.0389951 0.0307876 0.0205879 0.00908905 0.00555359 -0.0121034 -0.00687764 0.00752914 0.0176609 0.00566536 -0.0208413 -0.0229413 0.00156059 0.00543264 0.00694066 0.00249693 -0.00335328 0.000401892 0.0138262 0.00128668 -0.0283111 -0.0256373 -0.0237493 -0.0291584 -0.00703129 0.0152271 0.0393229 0.0452958 0.0231804 -0.0291094 -0.0417306 -0.00489797 0.0160917 0.000583816 -0.0194554 -0.0235409 0.00563181 0.0393978 0.0237208 -0.00447947 0.0171657 0.0551852 0.0282278 -0.022097 -0.0371377 -0.0598215 -0.0687185 -0.118988 -0.195594 1.40087)) +(31.5195 0.0823719 0.0511211 #(-0.0506811 0.032627 0.0260271 0.0133287 0.00707792 -0.00716418 -0.00792555 -0.00164158 4.37169e-005 0.00655899 -0.00403331 -0.00510847 -0.00250636 0.00465444 0.012035 0.0010902 -0.00567664 -0.00723898 -0.00466529 -0.00771452 -0.0268553 -0.0264261 -0.00282889 0.000687852 0.00062155 0.00777579 0.0113666 0.0250398 0.020167 -0.0104087 -0.0261586 -0.0112883 -0.00423545 0.0070317 -0.000811418 -0.0200803 0.00317688 0.0237687 0.0201803 0.0121356 0.0175142 0.033371 0.0253085 -0.00456846 -0.0415392 -0.0596395 -0.0783815 -0.0936876 -0.114877 1.30627)) +(25.4029 0.0602808 0.0487134 #(-0.0551556 0.0394576 0.0270103 0.0236226 0.00186073 -0.00761447 -0.00740441 -0.00712806 0.00591052 -0.00309897 -0.00157216 -0.0120145 -0.00111416 0.0139671 0.00880658 -0.0012513 0.00244409 -0.0133322 -0.00925009 0.00123142 -0.034305 -0.0168858 -0.00914378 -0.0110158 0.000306792 0.0116358 0.0236282 0.0251389 0.00218792 -0.00727665 -0.0207191 -0.00825958 0.00274023 -0.00288428 -0.00666814 -0.0172675 0.00904082 0.0154382 0.0150386 0.0254515 0.0314402 0.0294853 0.0295901 -0.00445611 -0.0469681 -0.0574121 -0.0877862 -0.106583 -0.135491 1.339)) +(22.7468 0.078061 0.0585811 #(-0.04486 0.0298865 0.0293551 0.0157202 0.00558635 -0.00166327 -0.0153884 -0.00699228 0.00676223 0.00247051 -0.00958823 -0.00736895 0.00134663 0.00697311 0.0112086 -0.000206178 -0.00881016 -0.00624388 -0.00932781 -0.0197023 -0.0190608 -0.011131 -0.0120463 0.000508607 0.00205883 0.0130596 0.00678453 0.017637 0.0173591 -0.00929612 -0.0146321 -0.00917131 -0.0076256 0.0010683 -0.00392937 -0.00849227 0.006057 0.0173038 0.0170559 0.0185356 0.0307804 0.0321241 0.0197208 -0.00024348 -0.0379323 -0.0627024 -0.0771216 -0.096205 -0.116027 1.29578)) +(22.8884 0.0716601 0.055954 #(-0.0482403 0.0307585 0.0275873 0.0182651 0.000529184 -0.0022478 -0.00768153 -0.00720601 0.00320312 0.000542559 -0.00613952 -0.00509576 0.000853576 0.00746592 0.00241067 0.00149092 -0.0103518 -0.00548361 0.00260866 -0.00854271 -0.0165325 -0.024049 -0.0159926 -0.0106845 0.00539235 0.0217353 0.013189 0.0138549 0.0113874 -0.00669787 -0.0144154 -0.00952096 -0.00989752 0.000984178 -0.00567269 -0.0075391 0.00597343 0.0157336 0.0231019 0.0212661 0.0260539 0.0267702 0.0234177 -0.00360673 -0.0411499 -0.0479637 -0.0797028 -0.101779 -0.123467 1.30416)) +(25.0679 0.0404904 0.04019 #(-0.0569264 0.0393012 0.0442286 0.0105388 -0.0280166 0.0130403 -0.000293758 0.00097423 0.0019422 -0.0135517 -0.0129558 -0.00137247 0.0176797 0.0111486 -0.00223964 -0.00550807 -0.00602055 -0.00683842 -0.0111893 0.0040559 -0.00320025 -0.0210676 -0.0166252 -0.0273107 -0.00925243 0.0352852 0.0153395 0.028238 0.0100151 -0.0296035 -0.0250562 0.00185137 0.0255143 0.00681541 -0.0269629 -0.0225865 0.00339151 0.0176583 0.0135256 0.0128693 0.0308694 0.0396139 0.0268478 -0.00453411 -0.0321182 -0.0411832 -0.0894552 -0.13549 -0.18868 1.40068)) +(26.172 0.0414675 0.0398048 #(-0.0630411 0.0445934 0.0340673 0.0179641 -0.0126086 -0.000847251 0.000227371 0.00106207 0.0131494 -0.0118745 -0.0160848 -0.00908814 0.00502605 0.0118554 0.0134411 0.006348 -0.0203072 1.60219e-005 -0.0092216 -0.0131313 0.00614179 -0.023434 -0.0225044 -0.0205765 -0.00759216 0.0190882 0.0216325 0.0341826 0.0139076 -0.0241181 -0.0163891 -0.0082327 0.0124357 -0.00390939 -0.0224453 -0.0154005 0.00127452 0.0147405 0.0170827 0.0260113 0.0421892 0.0303767 0.0235349 -0.0138023 -0.0474366 -0.0434775 -0.0753137 -0.111706 -0.172436 1.36862)) +(24.9425 0.0127896 0.0226443 #(-0.0733194 0.0354206 0.0577736 0.0308347 -0.0289842 -0.00604918 -0.014531 -0.0101977 0.0240066 0.0242339 -0.0217081 -0.0255996 0.00547605 0.0210583 0.0282309 -0.0144568 -0.0284572 -0.0338683 0.0165173 0.0371958 0.00744609 0.00585112 -0.0600074 -0.0549116 0.000340121 0.0385451 -0.00124994 0.0513382 0.0555081 -0.0592178 -0.0733577 -0.0170409 0.0586459 0.0553344 -0.0225186 -0.0556362 -0.0233135 0.0506938 -0.00436045 -0.0332437 0.00902178 0.0879455 0.0599741 -0.000640262 -0.0442607 -0.0220114 -0.0610923 -0.165358 -0.458725 1.64915)) +(22.7641 0.0174743 0.027706 #(-0.0584102 0.0459445 0.031618 0.0172284 -0.0102017 -0.00307119 -0.0147159 -0.0128069 0.0192186 0.0263737 -0.0162587 -0.0214138 -0.00164627 0.0164729 0.0190751 -0.00745766 -0.0243652 -0.0185078 -0.0136905 0.043886 0.0129518 -0.0298972 -0.0265289 -0.0403765 -0.00958069 0.0232809 0.0161453 0.044125 0.0361099 -0.0522329 -0.0619475 -0.000899218 0.0508566 0.0368301 -0.0180012 -0.0430501 -0.00970191 0.00226846 0.0163143 0.00440859 0.00654716 0.0745107 0.0559268 -0.0237278 -0.0297872 -0.0202482 -0.0711893 -0.150335 -0.394529 1.58051)) +(19.5777 0.0125371 0.0253057 #(-0.0826795 0.0683275 0.0428367 0.02936 -0.021953 -0.0169267 -0.0348315 -0.00679442 0.025703 0.045118 -0.00592805 -0.0419876 -0.00936561 0.0199536 0.035517 -0.0131276 -0.0408877 -0.0219309 0.0500002 -0.0214081 0.0310525 -0.0126166 -0.046124 -0.0345309 -0.027267 0.0407647 0.00779675 0.0551954 0.0525408 -0.0538993 -0.0680158 -0.0475148 0.0549138 0.0610506 0.00643009 -0.0500036 -0.0294172 0.0234389 0.0124404 -0.0212963 0.0223014 0.0563873 0.0415865 0.0218463 -0.0398211 0.00419091 -0.103894 -0.150699 -0.43171 1.62141)) +(18.2418 0.0253117 0.0372501 #(-0.0607523 0.0562677 0.0384613 0.00424439 -0.0162383 -0.00801906 -0.00889723 -0.00153158 0.0178735 0.00687857 -0.00841403 -0.0109761 -0.000752748 0.0188549 0.0145737 -0.0116472 -0.0244779 -0.0102738 0.00684694 -0.00289441 -0.0144796 -0.0119951 -0.0216497 -0.0176858 0.000835 0.00693356 0.0142641 0.0338318 0.0169442 -0.0304174 -0.03766 -0.00345847 0.0310024 0.00119207 -0.0121249 -0.0113758 -0.00784907 0.0241519 0.0161341 0.0165755 0.0178807 0.0323894 0.0223039 0.0113459 -0.0211709 -0.0354951 -0.0753201 -0.130449 -0.212926 1.39061)) +(18.2633 0.0252861 0.0372093 #(-0.045203 0.0314978 0.0349495 0.00211169 -0.00893727 0.00352343 -0.0123056 -0.00291805 0.0126091 0.00904179 -0.00646769 -0.0145041 -0.00502528 0.0120276 0.0164997 -0.0114284 -0.0165834 -0.00612101 0.0129625 0.0025109 -0.0220033 -0.00506117 -0.0341916 -0.0253116 0.0116913 0.0206707 0.00947406 0.0215501 0.018648 -0.0253815 -0.0210033 -0.00128285 0.00803003 0.00165846 -0.00961188 -0.0112029 -0.00390969 0.018762 0.0176612 0.0141336 0.0162613 0.0423988 0.0169786 0.00664183 -0.0149723 -0.0514017 -0.0758318 -0.125953 -0.214712 1.39864)) +(17.5015 0.0281862 0.0401311 #(-0.0467037 0.0285618 0.0290192 0.00889659 0.00523947 -0.0106185 -0.00584188 0.00343646 0.0078645 0.00378798 -0.0136156 -0.012084 0.00284047 0.0112584 0.00930852 -0.0112164 -0.00383024 -0.00982824 0.0153711 -0.00475254 -0.018373 -0.0203009 -0.0232701 -0.0175478 0.00286289 0.0183034 0.0126237 0.036949 0.00550275 -0.0201175 -0.0171514 0.000764537 0.00264071 -0.0167697 -0.00575089 -0.00377642 -0.00121029 0.0205625 0.019458 0.00863159 0.025104 0.0386815 0.0262647 -0.00411803 -0.0406888 -0.0471502 -0.083648 -0.103756 -0.174039 1.36212)) +(17.2526 0.0295366 0.0413764 #(-0.0459645 0.0347026 0.0174516 0.0140821 0.00442935 -0.00595253 0.000786888 -0.00770935 0.00586936 0.00240675 0.00201615 -0.0114029 -0.00715992 0.0219725 0.00668619 -0.00508303 -0.0104611 -0.00929612 -0.00120529 -0.00989537 -0.0169932 -0.0133932 -0.0188951 -0.000876892 -0.000297876 0.000200907 0.0129674 0.0262989 0.00787067 -0.0241803 -0.0115058 -0.000143185 0.0150916 0.0138443 -0.0335769 -0.0206819 -0.00174932 0.0245576 0.0198266 0.017498 0.020447 0.0325335 0.0246589 0.00835593 -0.033657 -0.0520807 -0.0742558 -0.105502 -0.158577 1.3385)) +(17.7939 0.0194564 0.0330671 #(-0.0393023 0.0249954 0.0281254 0.00881808 -0.0170303 -0.000254086 -0.0238422 0.0104953 0.0267727 0.0218212 -0.00832039 -0.0378733 -0.00966003 0.0208957 0.0258569 0.00523595 -0.0125616 -0.0198685 -0.00261361 0.0267587 -0.00756953 -0.0295961 -0.0220904 -0.0216108 -0.022352 0.010996 0.018242 0.0477541 0.0378138 -0.0342758 -0.0460006 -0.0110206 0.0200271 0.0216202 -0.0010694 -0.0481358 -0.00989713 0.0183853 0.0178495 0.0123016 0.00932306 0.0462944 0.0355045 0.00738312 -0.0433972 -0.0431022 -0.0752448 -0.111662 -0.22808 1.41783)) +(16.2645 0.0198753 0.0349571 #(-0.0444276 0.0359794 0.0176339 0.0166024 -0.00509977 -0.00228653 -0.0161215 0.0145134 0.0174299 0.000749843 -0.00504707 -0.026946 -0.00241593 0.0172678 0.024325 -0.00596551 -0.0248575 -0.0135324 0.0111395 0.00225044 -0.0129778 -0.0134113 -0.0270257 -0.0234719 -0.000202711 0.0218519 0.00693315 0.0315688 0.0147574 -0.0374582 -0.0197909 -0.0087806 0.0357156 0.00379843 -0.0129535 -0.0288524 -0.0066429 0.02112 0.00394448 0.0222445 0.0191879 0.0458149 0.0290641 0.00188522 -0.0291704 -0.0394177 -0.0755161 -0.123621 -0.231673 1.41693)) +(13.9843 0.0203448 0.0381422 #(-0.0406508 0.0247845 0.0280528 0.016247 -0.00667394 0.00575473 -0.00883099 -0.00538796 0.0124414 0.00246849 -0.0144231 -0.0122821 5.65498e-006 0.0240839 0.00861459 -0.00217033 -0.0235125 -0.0168742 0.0055966 -0.00328378 -0.00988276 -0.0124962 -0.0202922 -0.0046567 0.00286656 0.0025336 0.000137633 0.0296567 0.0200221 -0.0189908 -0.0237597 -0.000666055 0.0173422 0.0148898 -0.028545 -0.0280338 -0.00862389 0.0107104 0.0292579 0.0223673 0.0356336 0.027171 0.0365469 -0.00876548 -0.0413912 -0.0440555 -0.0862704 -0.0992445 -0.175119 1.36053)) +(13.7519 0.0318418 0.0481192 #(-0.0439203 0.0286811 0.019099 0.0131209 0.00116507 0.00239283 -0.00349781 -0.00764389 0.00731754 0.00111961 -0.0119648 -0.0166307 0.0112826 0.0209392 0.00437699 0.00510248 -0.00768695 -0.0223086 -0.0103192 -0.00707175 -0.0131623 -0.0187769 0.00250121 -0.00532104 -0.0114664 0.00451569 0.0158921 0.0267952 0.00829616 -0.0112708 -0.0156018 -0.00644018 0.00364066 -0.00682353 -0.0102232 -0.0152849 -0.00104906 0.0131723 0.0312335 0.0306407 0.0224566 0.0393104 0.00734389 -0.0167909 -0.0521184 -0.0325935 -0.0547162 -0.0785076 -0.107318 1.25643)) +(14.1001 0.036371 0.0507887 #(-0.0416909 0.0311513 0.0216856 0.010757 0.0023053 -0.00539498 -0.0122303 -0.00307753 0.0143497 -0.0013006 -0.00140553 -0.0114054 0.00277976 0.0180154 0.00290372 -0.000693336 -0.0231679 -0.00686742 -0.00978564 -0.00577415 -0.00821437 -0.0128852 -0.00872088 -0.0119665 0.00729519 0.00605096 0.00574081 0.0229577 0.00811213 -0.0167 -0.00908976 0.00335362 -0.00364028 -0.00150706 -0.00937789 -0.0185555 -0.000902989 0.0273121 0.0204276 0.0180267 0.0271863 0.0347298 0.0131781 -0.0189297 -0.042958 -0.0488664 -0.0552135 -0.0687342 -0.0978135 1.24792)) +(14.2751 0.0340747 0.048857 #(-0.0375261 0.024581 0.0173357 0.0105803 0.00152478 5.81223e-005 -0.0049663 0.000233414 -0.0059578 0.0172982 -0.0123975 -0.0121001 0.00817213 0.00614464 0.0063125 0.00277281 -0.0072908 -0.00298882 -0.00532286 -0.0151193 -0.0130224 -0.0190079 -0.00477871 -0.00682809 -0.00484661 0.0136435 0.0106479 0.0201277 0.016766 -0.0148155 -0.0230016 0.0010569 0.00368719 -0.00836747 -0.0108471 -0.0115598 -0.000523546 0.020508 0.0238148 0.0105346 0.0278912 0.030346 0.015747 -0.00584426 -0.0429999 -0.0557868 -0.0671162 -0.0745447 -0.115248 1.28424)) +(15.2833 0.022009 0.0379483 #(-0.0444502 0.0319226 0.0206898 0.00408402 0.0038444 0.00518289 -0.0102187 0.00644884 0.0154201 0.00243678 -0.0155881 -0.0226183 -0.00535144 0.0143481 0.0263679 -0.00816404 -0.00439294 -0.00726711 0.00245852 -0.0075432 -0.0210695 -0.022927 -0.0121272 -0.00257655 -0.0142863 0.0116892 0.0195945 0.0314798 0.0171628 -0.026222 -0.0236029 -0.00279915 0.0139127 -0.00411994 -0.0220793 -0.0223499 0.0130053 0.0163297 0.014851 0.0168635 0.030113 0.0393203 0.0185481 -0.0032677 -0.0508295 -0.049786 -0.0681459 -0.100596 -0.141854 1.3324)) +(16.2369 0.0167683 0.0321361 #(-0.0461453 0.0336128 0.0171639 0.00638196 0.00304988 0.00700732 -0.0124934 -0.0014443 0.0229149 0.00812651 -0.0156464 -0.027978 0.00155632 0.0148617 0.0236262 -0.0053183 -0.0306435 0.0156539 0.00576177 -0.00936416 -0.019092 -0.0214782 -0.0106117 -0.0139679 -0.00487678 0.0153928 -0.000839796 0.0328364 0.0370444 -0.0267438 -0.0258321 -0.0084227 0.00140206 0.0170352 -0.0249207 -0.0137748 0.00622318 0.00877071 0.0176743 0.0140944 0.0160371 0.0299227 0.0280204 0.00486572 -0.0471303 -0.0549004 -0.0792787 -0.0862093 -0.156202 1.34944)) +(15.8715 0.00862119 0.0233064 #(-0.0416665 0.0196847 0.0351245 0.00540738 0.000268711 0.000455022 -0.00585776 -0.00906765 0.019069 0.0231938 -0.0242396 -0.0320143 0.00375507 0.0115636 0.0160781 -0.00497688 0.0104297 -0.0136434 0.0112971 0.000516813 -0.0335269 -0.00981996 -0.0165414 -0.0128344 -0.00386654 0.0142686 -0.0124378 0.0254652 0.0577827 -0.0404511 -0.0399016 0.00257038 0.0284287 0.00205934 -0.00698707 -0.0282862 -0.0129552 0.0375839 -0.00052652 -0.00139833 0.010455 0.0601005 0.027725 0.00917528 -0.0452916 -0.0495308 -0.114218 -0.0824053 -0.228428 1.43507)) +(14.8358 0.0137405 0.030433 #(-0.035238 0.0325776 0.00811017 0.00564153 0.00956963 0.00160376 -0.00735718 -0.0106363 0.00927161 0.0156551 -0.014077 -0.0256614 0.00892661 0.0141185 0.0219964 0.00497017 -0.0213388 -0.00393183 0.00307147 -0.00527207 -0.00932004 -0.0149748 -0.0293915 -0.0137217 0.0110029 0.00820573 -0.00731358 0.0228706 0.0342061 -0.0270083 -0.0231551 -0.00456665 0.0112681 -0.00073322 -0.00608638 -0.0299522 0.00616215 0.0218085 0.0147894 0.01267 0.0171617 0.0382049 0.0155666 0.00222878 -0.0301421 -0.0626113 -0.101723 -0.0618076 -0.14028 1.33014)) +(12.9037 0.0170322 0.0363311 #(-0.0361427 0.0205666 0.0172627 0.017552 -0.00678439 0.00380304 -0.00573859 0.00913126 0.0155822 -0.00543546 -0.00759378 -0.0190302 -0.00357661 0.0192382 0.00804061 0.000652122 0.000361389 -0.0179953 -0.00446666 0.00560995 -0.0184849 -0.0113776 -0.0232038 -0.00865374 -0.000620224 0.00406897 0.00305195 0.0334702 0.0202773 -0.0270967 -0.0247178 0.00910172 -0.000104248 0.000138012 -0.0102208 -0.0169238 0.00120545 0.0203969 0.0133169 0.0181668 0.0202681 0.0266863 0.021128 -0.0131285 -0.0365628 -0.0378504 -0.0756192 -0.0782206 -0.137483 1.31255)) +(10.7606 0.0176641 0.0405161 #(-0.0483414 0.0247989 0.0315676 0.00585319 -0.00234617 0.009571 0.00527321 -0.010687 0.0163059 0.00885164 -0.0125577 -0.0134762 -0.00967633 0.0164184 0.00952228 -0.00630756 -0.0123339 0.00271924 -0.00671046 -0.0020015 -0.00886391 -0.0281787 -0.0135787 -0.0134191 0.00144693 0.00931767 0.000242524 0.0183011 0.0329657 -0.0164957 -0.0380229 0.00540505 0.0215291 -0.00189809 -0.0201857 -0.0100815 0.00201447 0.0118938 0.00726428 0.0202927 0.0107608 0.0392477 0.0177106 -0.00825438 -0.0278289 -0.0360925 -0.0803767 -0.0690058 -0.118693 1.27992)) +(9.692 0.0163592 0.0410842 #(-0.0435487 0.0238735 0.0221766 0.0130095 -0.0102838 0.0102648 -0.00263138 0.00405493 0.0139175 0.00368894 -0.0144828 -0.0187693 0.000191167 0.0191079 0.0188621 -0.00391941 -0.0163057 -0.0108496 0.0112138 -0.0054916 -0.0242603 -0.0107545 -0.03524 -0.00986785 0.00436468 0.0159444 0.00288566 0.0280451 0.0177601 -0.0226378 -0.0232638 -0.00458616 0.0132367 -0.00669003 -0.00879428 -0.0174804 -0.00444567 0.0183938 0.0174463 0.0192643 0.0206223 0.0364433 0.00547454 0.00493223 -0.0256411 -0.0374557 -0.0770796 -0.0699102 -0.107736 1.2591)) +(10.6083 0.0116637 0.0331585 #(-0.0339536 0.0239064 0.0193139 -0.00206308 -0.00420809 0.0162964 -0.00446401 -0.00723342 0.032238 0.00872946 -0.0187994 -0.0242643 -0.0134408 0.0259891 0.0161434 0.00132369 -0.0197008 -0.00519451 0.00655926 -0.00738285 -0.0172127 -0.0237242 -0.0212511 -0.0206254 0.0103538 0.0122223 -0.00456432 0.0447003 0.0352811 -0.0406705 -0.0316736 0.00797188 0.00656864 -0.0115901 -0.0027629 -0.0128048 -0.00570429 0.0118761 0.0188073 0.0222462 0.0124456 0.0410702 0.00791332 -0.00379496 -0.0170523 -0.0476136 -0.0781826 -0.0542285 -0.143112 1.28919)) +(13.6333 0.00775797 0.0238547 #(-0.0364152 0.0291058 0.0227928 0.00502204 -0.0253292 0.048831 -0.0291211 -0.014896 0.0320535 0.00774532 0.000503408 -0.0316866 -0.00546139 0.0360913 0.00840064 -0.0208066 -0.0145649 0.000116066 0.00307052 -0.0122648 -0.0118387 -0.0277435 -0.0112472 -0.0110968 0.0148855 -0.00123177 -0.021587 0.0284518 0.0631961 -0.0358807 -0.0443364 0.00976814 0.00940558 0.00815862 -0.0182798 -0.0167586 0.0109045 0.0136983 0.0074112 0.00384714 0.0165089 0.0481128 0.0182451 0.00169633 -0.0279793 -0.0379538 -0.093019 -0.0760834 -0.15798 1.33196)) +(14.9529 0.0090799 0.0246421 #(-0.0173912 0.0117589 0.0215592 -0.000100125 -0.00958332 0.0178238 -0.0220747 0.00944662 0.0241577 0.0100921 -0.0118245 -0.0308733 -0.0111011 0.0260419 0.0364623 -0.0174218 -0.0250652 -0.02109 0.0203074 0.00684312 -0.0399599 -0.0207732 -0.0171705 -0.0007063 0.00839398 0.0148383 -0.0116208 0.0395184 0.0320917 -0.0477367 -0.0288544 -0.013006 0.0343035 0.0151606 -0.0250012 -0.0238014 0.010687 0.0287551 0.00443121 -0.00885899 0.0187292 0.0305535 0.0398672 0.0256628 -0.0622547 -0.0391768 -0.0803045 -0.063373 -0.174028 1.33167)) +(15.4713 0.0103036 0.0258065 #(-0.0317778 0.0220012 0.023046 0.0107401 -0.00700271 0.0157947 -0.0168062 -0.0275037 0.0367403 0.0183112 -0.0155777 -0.0184876 0.00537082 0.00657688 0.00920857 -0.00738122 -0.0258576 -0.00495231 0.0158989 0.0138713 -0.0316929 -0.0372503 -0.00456503 0.00398878 -8.80907e-005 0.00931697 -0.0254795 0.0441872 0.0447222 -0.0413425 -0.0365677 -0.00544457 0.0244433 0.0112955 -0.0182531 -0.0124006 0.00266321 0.0168735 0.014526 -0.0109792 0.0141278 0.0440501 0.000770168 0.0424379 -0.0278247 -0.0526684 -0.0777227 -0.0873046 -0.175866 1.34552)) +(14.1187 0.00916422 0.0254771 #(-0.045858 0.0400202 0.0205128 0.00743514 -0.00145771 0.00837235 -0.0248272 -0.00172827 0.0233621 0.0100241 -0.0135858 -0.0126684 -0.00336266 0.0149539 0.0171219 -0.016675 -0.0227132 -0.000102549 0.020379 0.00582718 -0.016864 -0.0320013 -0.0340711 0.00940389 -0.00660789 0.0171697 -0.029894 0.0563412 0.0606243 -0.07549 -0.0483998 -0.000330146 0.0359239 0.0257492 -0.00142432 -0.0289091 -0.0018749 0.012466 0.00260386 -0.0152575 0.00862908 0.053457 0.03697 0.0345913 -0.0435553 -0.039316 -0.0996627 -0.0778146 -0.205904 1.3743)) +(12.5142 0.0109789 0.0296196 #(-0.0372881 0.0196089 0.0233113 0.000903561 -0.0047855 0.0192033 -0.00402685 -0.00304796 0.0072131 0.000961789 -0.00506267 -0.0118756 0.00342084 0.015397 0.00417627 0.00558174 -0.014547 -0.00178372 -0.00917506 0.0153024 -0.021183 -0.0321192 -0.0190146 -0.0116695 0.0083767 0.00252157 0.0031781 0.03148 0.0255226 -0.0305256 -0.0148153 0.00160903 0.010152 0.00196973 -0.0133266 -0.0138634 -0.0111339 0.0246016 0.00657759 0.0046415 0.0102237 0.0405588 0.0267124 -0.0205946 -0.0262742 -0.0302408 -0.0733365 -0.0751875 -0.141942 1.30887)) +(13.1881 0.0149057 0.033619 #(-0.0392646 0.0235916 0.0113109 0.0165674 0.000356377 0.0096727 -0.00454504 -0.0118521 0.0189847 5.30982e-006 -0.00576891 -0.00829558 -0.00267612 0.0116296 0.0180062 -0.00463104 -0.015852 -0.0119515 0.00220159 0.00224108 -0.027798 -0.0126524 -0.0149994 -0.00157439 -0.00384594 0.00016854 0.00338744 0.0262442 0.0138858 -0.0262235 -0.0060537 -0.000456936 0.0188089 0.00153812 -0.0108762 -0.0196819 -0.00571758 0.0244648 0.0111209 0.00558558 0.0127132 0.0348169 0.015571 -0.0175171 -0.0217261 -0.045869 -0.0708379 -0.0505154 -0.114525 1.26721)) +(12.7999 0.015072 0.0343149 #(-0.0333835 0.0122214 0.0259325 -0.000845576 -0.00411607 0.0249855 -0.00362802 -0.00123161 0.00374519 0.00881159 -0.00779002 -0.0221836 -0.00150112 0.0259934 0.00794084 -0.00206094 -0.0134564 -0.00876726 -0.00201227 -0.0224425 0.00930002 -0.0259136 -0.0165928 -0.00342897 -0.00262414 0.00704048 -0.00242533 0.0235934 0.0114056 -0.0151016 -0.0109616 0.00159531 0.0111167 -0.000793585 -0.00855475 -0.0193289 0.00818316 0.0173823 0.00418687 0.0104691 0.0231481 0.0104235 0.0158543 -0.00351913 -0.0424822 -0.0357488 -0.0522538 -0.0381995 -0.0936292 1.22602)) +(12.2473 0.0193377 0.0397359 #(-0.0208312 0.0113622 0.0107963 0.0102407 -0.0113957 0.00688707 0.00914879 -0.00983215 0.00520417 0.00334524 -0.0068846 -0.004754 -0.00291994 0.0137996 0.0146112 -0.00155131 -0.0176285 0.00365784 -0.0104858 -0.0192718 -0.000923549 -0.0131308 -0.0111267 -0.00719019 0.000579761 0.0111471 -0.00676168 0.0234209 0.0115352 -0.0168934 0.0025673 -0.00926516 0.00685466 -0.00665536 -0.00981694 0.000390394 0.00485606 0.00488992 0.00723448 0.0167406 0.00949511 0.00968203 0.0148381 -0.0192989 -0.0238238 -0.0274632 -0.0505583 -0.0318813 -0.0690697 1.18902)) +(12.5963 0.016594 0.0362957 #(-0.022897 0.0164408 0.00922307 0.00712825 0.00029965 0.0126678 -0.00781488 -0.00903336 0.00276701 0.00841422 -0.00438664 -0.00758085 0.00516114 0.00530365 0.00871018 -0.00177273 -0.00100205 -0.00497492 -0.00829477 -0.00643409 -0.0175788 -0.016037 -0.0116676 -0.00203718 -0.000523905 0.0101769 -0.00147634 0.0081845 0.0146411 -0.0119274 -0.00436797 -0.000224399 -0.00513704 -0.00984378 0.0115129 -0.0102507 0.00516442 0.00549147 0.00572397 0.0118901 0.0113157 0.0218897 0.00945389 -0.0113134 -0.0298536 -0.0302538 -0.053088 -0.0372686 -0.0642578 1.19366)) +(13.5525 0.01008 0.0272723 #(-0.0123657 0.0053427 0.019458 -0.0176663 -0.0176549 0.0404966 -0.00390325 -0.00579765 0.00887555 0.00317001 0.00172718 -0.00829583 0.010417 0.0153962 -0.00556122 -0.00680748 -0.00745445 -0.00852993 -0.00462103 -0.0159715 -0.000628177 -0.0183191 -0.0147015 -0.00193298 -0.00415885 0.0236506 -0.0098982 0.015603 0.0132994 -0.0134173 -0.00543716 0.00140853 -0.000410987 -0.0155814 -0.00399504 -0.000352762 -0.00284362 0.0100352 0.0139833 0.0156556 0.00280102 0.00782334 -5.04827e-005 -0.0182239 -0.0189623 -0.0239327 -0.0540221 -0.0168124 -0.0578101 1.18215)) +(12.068 0.00596845 0.0222389 #(-0.00770466 -0.00247063 0.020446 -0.00341433 -0.0175267 0.0299728 -0.00334073 -0.021708 0.0222189 0.00349176 -0.00219307 0.000507939 -0.000906229 0.0251413 -0.00347692 -0.0193672 -0.008356 0.0107288 -0.00522202 -0.0373399 0.0110019 0.00334983 -0.0260176 -0.00508717 0.0076833 0.0123874 -0.0218113 0.0217126 0.0137616 -0.0343426 0.00107652 -0.0108971 0.00723602 -0.0140256 0.00945629 0.008111 -0.013161 0.0263409 0.00322294 0.0169951 0.0125402 0.00634017 -0.0281478 0.00833678 -0.0210252 -0.0480639 -0.0657505 0.00962592 -0.0670183 1.193)) +(8.95623 0.00286173 0.0178752 #(-0.0299596 -0.00271054 0.0316405 0.00830122 -0.0430843 0.052154 0.00778072 -0.0218403 0.015222 0.00900955 0.000450335 -0.0294424 0.0109118 0.0305165 0.0185617 -0.0211344 -0.00754338 0.000348268 -0.015125 0.000259483 -0.00953378 0.00744751 -0.0392438 -0.0133562 -0.0140394 0.0473366 -0.0574915 0.0274957 0.0739216 -0.0633229 -0.00625577 -0.00332914 0.0318236 -0.039495 -0.0259531 0.0239393 -0.0180297 0.0156937 0.0245471 0.0241233 0.00445331 0.0143366 -0.0112595 0.0136985 -0.0568217 -0.0400073 -0.106216 0.040655 -0.0915969 1.22924)) +(6.49921 0.00445611 0.0261847 #(-0.0170517 -0.0101715 0.0184278 0.00588615 -0.0192503 0.0377397 -0.00414877 -0.0237132 0.0261238 0.0049736 -0.00638682 0.00527185 -0.00923617 0.0111306 0.0255296 -0.0039067 -0.0151077 0.00377979 7.06266e-005 -0.0208127 0.00467839 -0.022734 -0.0168833 -0.00336075 -0.01055 0.033853 -0.0379811 0.010155 0.0492233 -0.0412482 -0.00933746 -0.0204949 0.0208357 0.00125835 -0.0115378 -0.000968487 0.00445165 0.00835097 0.00622662 0.0115168 0.000545416 0.00342692 -0.00927968 0.0260598 -0.0528268 -0.0332704 -0.0524391 0.0325668 -0.0789734 1.17526)) +(5.25729 0.00395311 0.0274213 #(-0.0240403 0.0205123 0.0153895 -0.0123595 -0.0220413 0.0554869 -0.00704868 -0.0433425 0.0501927 -0.00331648 -0.0181042 -0.0055328 -0.0079657 0.0218988 0.0184512 0.000216515 -0.0131423 -0.00679136 0.0172376 -0.0200239 0.00385909 -0.0187232 -0.0339574 -0.0205053 0.00639417 0.0217717 -0.022982 0.0227078 0.0735146 -0.0648862 -0.0373938 0.00153798 0.00527095 0.0142592 -0.0107342 -0.0298141 0.00548001 0.0163492 -0.00212356 0.00278833 0.0101466 0.0397622 0.0149 0.023642 -0.01529 -0.0428728 -0.0909119 0.00412615 -0.130688 1.23334)) +(4.64889 0.00405787 0.0295443 #(-0.0083154 0.00615811 0.0229795 -0.0118895 -0.011159 0.0234972 -0.00391371 -0.0106054 0.0152195 0.0045161 -0.0309345 -0.0133451 0.0142733 0.0022754 0.0224104 0.00053866 -0.0105869 0.014126 -0.00594441 -0.016928 0.000217074 -0.00374499 -0.0370543 -0.0101543 -0.0131152 0.0467066 -0.0290259 0.0361985 0.048131 -0.0712857 -0.010248 0.0200725 -0.00527912 -0.033853 0.00625684 -0.0132771 -0.00059062 0.00807303 0.0207666 -0.005388 0.00403096 0.0390784 0.0263475 0.00420176 -0.0247701 -0.0169901 -0.0981137 0.00202813 -0.122794 1.22287)) +(4.2687 0.00527028 0.0351374 #(0.0119431 0.000370011 0.00297805 -0.0086345 -0.00619318 0.0209268 -0.0214211 -0.00264095 0.000795118 0.0018904 0.00504403 -0.00221174 0.000734628 0.0115394 0.00269348 0.00862158 -0.0112626 0.0128954 -0.0100209 -0.0261409 -0.00341844 -0.00612675 -0.023003 0.0109423 -0.00282099 0.0203828 -0.0265252 0.0270202 0.0322998 -0.0362086 -0.00119129 -0.0153138 -0.00350063 0.00240223 -0.0210972 -0.00135233 -0.00711855 0.000712969 0.0123906 -0.00078104 0.000209776 0.0312843 -0.00727613 0.0274143 -0.0141633 -0.0350039 -0.0442454 0.0167168 -0.0482093 1.11671)) +(5.08667 0.00434494 0.0292264 #(-0.00272251 0.00941567 0.00822995 -0.014127 -0.00472909 0.0256388 -0.0205545 -0.00637778 -0.0112651 0.0378657 -0.0158337 -0.00984417 0.00216444 0.030978 -0.00207667 -0.00625094 -0.00241573 0.000887676 -0.0113091 -0.0167408 -0.00726853 -0.00532588 -0.0106122 0.000375745 -0.00057362 0.0254724 -0.018358 0.0306097 0.0326059 -0.0225176 -0.0471872 0.00568396 -0.0101327 -0.0167238 -0.0112461 -0.0017848 -0.00424018 0.0120333 0.0037898 0.0135469 0.0227388 0.0193921 -0.0318962 0.0246949 -0.0262602 -0.0227707 -0.0672516 0.0572928 -0.0571018 1.11738)) +(5.64243 0.00660276 0.0342082 #(0.00180166 0.00187813 0.00574493 -0.000219231 -0.0214208 0.0292124 -0.0171232 -0.0116133 0.0143524 -0.0080191 0.00040181 -0.000264368 0.00500117 0.0156718 0.00494422 0.00107104 -0.0174182 0.00156305 -0.00116767 -0.0143132 -0.00873124 0.00879861 -0.0235025 -0.00555377 0.0159542 0.0120798 -0.00968709 0.0101018 0.0241207 -0.0283285 -0.00464771 0.00488285 -0.0317064 0.000691314 -0.0122031 -0.0076785 0.00264264 0.00947001 0.0122303 0.00967777 0.0183964 0.00361356 -0.0121287 0.0116267 -0.0186891 -0.0143781 -0.0485434 0.0242676 -0.0335089 1.09521)) +(4.34906 0.00506972 0.0341424 #(0.0023974 -0.00279862 0.0120042 -0.00157989 -0.0157521 0.0239786 -0.0126398 -0.0135926 -0.0020871 0.00151955 -0.00174203 -0.00773394 0.0159697 0.00780768 0.021657 0.00663021 -0.0142795 0.00149963 -0.00494957 -0.00158777 -0.0254905 -0.0117564 -0.017529 -0.00628616 0.00849666 0.00422017 -0.0116558 0.0310608 0.0345892 -0.0316539 -0.0132967 -0.00584913 0.00354922 -0.0173338 -0.0110622 -0.0096414 0.00859083 -0.0039589 0.0226801 0.0154026 0.00896204 0.0230092 0.00481482 0.00292927 -0.0234833 -0.0254714 -0.0981472 0.0441442 -0.0688532 1.14897)) +(2.61565 0.00474862 0.0426083 #(0.00879548 -0.00707132 0.0105265 0.00589761 -0.0181165 0.0122799 0.000610275 -0.0196829 -0.011157 0.0120507 -0.0115164 -0.0105635 0.0167566 0.0110644 0.0208706 0.00165262 0.00444448 -0.00889109 -0.00448973 -0.00204069 -0.0176097 -0.0204983 -0.00444134 -0.0102928 -0.000729621 0.00828533 -0.0156112 0.0249824 0.046813 -0.034427 -0.0110774 -0.0109798 -0.00690826 -0.00195731 -0.0157386 -0.00195138 0.00642795 -0.00283065 0.0119922 0.0211103 0.0124749 0.0247881 0.0132657 -0.00455936 -0.0371286 -0.0106291 -0.0739445 0.0263266 -0.0843839 1.15059)) +(2.02703 0.00255318 0.0354904 #(0.0134249 -0.00506588 0.00680395 0.0105582 -0.0323818 0.0493337 -0.0217674 -0.0241798 0.00928927 -0.023553 0.0104105 -0.0160771 0.00235487 0.00839372 0.0312377 0.00805041 0.000414273 -0.0136668 -0.0141831 0.0145558 -0.01835 -0.0176581 0.00780919 -0.0178566 -0.00798348 0.0228851 -0.0520132 0.0414188 0.066511 -0.0612651 0.00654983 -0.0331677 0.0129804 -0.0240143 0.0167766 -0.000209965 -0.0232557 0.0166038 0.0163538 0.0123617 -0.00410349 0.0241719 -0.00992855 0.0157116 -0.0186285 -0.0253129 -0.0767908 0.0521641 -0.0693304 1.12793)) +(2.64432 0.00171959 0.0255009 #(-0.0191815 0.0127539 0.0107323 0.00105373 -0.0253985 0.0548691 -0.00350344 -0.0407332 0.00805417 -0.00516293 0.0269923 -0.0481122 0.045745 -0.00949443 0.029402 0.00253762 -0.0224486 0.00621702 -0.0126075 -0.000360755 -0.0107886 -0.00802914 -0.0263488 -0.00418882 0.00777657 0.0122917 -0.0655835 0.0318259 0.0745041 -0.046913 -0.0178272 -0.014913 0.00287156 -0.0266232 0.016267 0.00797917 0.00580041 0.0114133 0.00738462 0.0441676 -0.0136994 0.0335519 -0.0324743 0.0188773 -0.0348701 -0.0234333 -0.174669 0.177908 -0.0964444 1.12857)) +(3.49525 0.0028907 0.0287582 #(-0.022997 0.00390569 0.0195987 -0.00368246 -0.0249804 0.0205793 -0.000749982 -0.0146779 0.0253093 -0.027436 -0.00506964 0.0229678 0.0122114 -0.00660955 0.0289347 0.00446956 -0.0240813 0.0124458 -0.000533498 -0.0357979 -0.00426894 0.00482643 -0.0216519 0.00376066 -0.0166858 0.0254196 -0.047756 0.0296842 0.05304 -0.053725 0.0233847 -0.00627376 -0.0327575 0.0242391 -0.00986949 0.0018908 0.0199183 -0.001377 0.00140167 0.0246927 0.00391399 0.00494078 -0.0242442 0.0174991 -0.0272264 -0.0343578 -0.0611368 0.0862893 -0.0566336 1.08269)) +(3.59173 0.00241115 0.0259096 #(-0.0280463 0.00239539 0.0275002 -0.0139323 -0.0348279 0.0607939 -0.0263654 -0.0111383 0.00125177 0.0134574 -0.0201514 0.0256755 0.0152298 -0.0129894 0.040595 -0.0242227 0.0223003 -0.0198948 -0.00945686 -0.0104881 -0.0149074 0.000106048 -0.0155021 0.00164234 -0.0275243 0.0334275 -0.0597113 0.0490029 0.0458835 -0.0406038 -0.00296535 0.00162114 0.00027736 -0.0194494 0.0124248 -0.00222679 0.0104655 -0.00167292 0.00815926 0.0283748 -0.0225562 0.0143205 -0.0188394 0.00579293 -0.0147764 -0.0167599 -0.050156 0.0847534 -0.0659405 1.07315)) +(2.26719 0.00255288 0.0335561 #(-0.0136514 -0.00925972 0.0167188 -0.00485284 -0.0336646 0.0412232 -0.000246899 -0.0298077 0.00712888 0.0134616 0.0103107 -0.00485241 -0.00127703 0.0164119 0.0132654 -0.019095 0.00456902 -0.00259853 -0.000275873 -0.0127027 -0.00593184 0.0101047 -0.0413224 0.018843 -0.0107773 0.0150738 -0.0289957 0.0254439 0.0380609 -0.0406301 -0.00392326 0.0172783 -0.00857435 -0.0223009 0.00749708 -0.0165367 0.0238457 0.018136 -0.00458933 0.00245699 0.00172918 0.00670983 -0.024566 0.00660529 -0.0205404 0.00950086 -0.0578217 0.0939725 -0.0510117 1.04425)) +(0.609353 0.00163717 0.0518337 #(0.00316256 -0.0122567 0.00518264 0.0126123 -0.0397706 0.0392831 0.0116002 -0.0471934 0.00805918 -0.00560564 0.000558784 -0.00409364 -0.00452707 -0.00113856 0.0257756 -0.00932488 0.00381936 -0.00247659 0.00301922 0.00335715 -0.00619763 0.0345422 -0.0321831 0.00519092 -0.00104381 -0.021393 -0.028818 0.0308446 0.0615516 -0.0569711 -0.0213437 0.00541473 0.00891156 -0.00345845 -0.00526036 -0.0140875 0.0217332 0.0150425 0.00302012 0.000750344 -0.0227373 0.0355403 -0.0606219 0.0543924 -0.0197096 0.0106198 -0.0761164 0.133679 -0.0540805 1.00403)) +(0.116473 0.000738204 0.0796116 #(-0.0020667 -0.00708028 0.00649903 0.00525495 -0.0577545 0.0708488 0.0241519 -0.0957537 0.0444855 0.00816514 -0.0260424 -0.00887706 0.0161092 -0.00643925 0.0365329 -0.0114855 -0.0214506 0.00323551 4.06337e-005 0.00984418 0.00579543 0.0340158 -0.0244511 -0.00303321 -0.0329481 0.0117391 -0.0672089 0.0657941 0.120411 -0.0823802 -0.0449917 0.00125354 0.00608117 -0.0209081 -0.0254859 0.0413741 -0.00546445 0.0228035 -0.0102555 0.0282721 -0.0411615 0.0264412 -0.0625765 0.0651369 -0.0960416 0.0914793 -0.12826 0.244372 -0.0968032 0.978677)) +(0.0472545 0.000482073 0.101003 #(-0.0132409 -0.00177229 -0.00651967 0.0181785 -0.057867 0.0886454 -0.0060562 -0.0415304 -0.00604645 0.00809692 -0.0261498 0.0308232 -0.0207518 0.039377 0.0286866 -0.00414628 -0.101779 0.0925687 -0.0566329 0.0285281 -0.0124488 0.0429751 -0.0231868 0.00492606 -0.0382182 0.0353667 -0.0854897 0.072105 0.138783 -0.152908 0.0118608 -0.0236536 0.0280545 -0.0358662 -0.00158007 0.0410328 -0.0307116 0.0351427 -0.0487812 0.0650863 -0.105127 0.0931477 -0.118991 0.157664 -0.204664 0.186411 -0.180145 0.351459 -0.130844 0.92427)) +(0.0200657 0.000490229 0.156305 #(-0.0167117 0.0226238 -0.0290179 0.0310399 -0.05596 0.0754746 -0.00102182 -0.0240663 -0.00557826 -0.00226293 0.00760277 0.00121096 -0.0371931 0.0368175 0.00439128 -0.00121828 -0.0701961 0.0851828 -0.0429475 0.0221135 -0.0202851 0.0294757 0.0173632 -0.014941 0.0101552 -0.0156045 -0.0714142 0.0373879 0.140392 -0.155288 0.0474913 -0.015392 0.010226 -0.0506144 0.00775825 0.0425248 -0.0111819 0.0198418 -0.0465491 0.0473969 -0.0958641 0.069069 -0.0800155 0.135248 -0.167486 0.159519 -0.163318 0.341011 -0.122999 0.899713)) +(0.0189561 0.000463645 0.156394 #(0.0136824 -0.010146 -0.00340101 0.00501791 -0.052312 0.0825702 -0.0198587 -0.00941267 0.00742931 -0.00822124 -0.00559287 0.0070671 -0.0295775 0.0163785 -0.000200317 -0.0124918 -0.0388802 0.0517694 -0.0148913 -0.0019372 0.0130002 0.0529274 -0.051331 0.0468511 -0.0493757 0.0488883 -0.0877978 0.0390208 0.120372 -0.130924 0.00454228 0.0284801 -0.0370236 -0.0207961 0.00413483 0.0556726 -0.0461664 0.043992 -0.0572133 0.0680651 -0.129146 0.0933036 -0.0903923 0.0963898 -0.115223 0.173486 -0.16108 0.327376 -0.109485 0.877362)) +(0.0157623 0.000457797 0.170422 #(0.00679172 0.0179331 -0.0180012 0.00985177 -0.0710897 0.0804711 -0.0138887 -0.00160079 -0.0130131 -0.0116605 -0.00195402 0.0102408 0.00544203 -0.00882841 -0.00664669 -0.000185585 -0.0333044 0.0571107 -0.0324269 0.00482369 0.00173713 0.0817342 -0.0689869 0.0314419 -0.0416472 0.0452527 -0.104628 0.0733021 0.109757 -0.112525 -0.040671 0.0457447 -0.033124 0.0189072 -0.0182032 0.0382207 -0.0430175 0.0633007 -0.0880582 0.0891837 -0.145313 0.126151 -0.130188 0.133809 -0.156576 0.210072 -0.192572 0.343954 -0.102867 0.867452)) +(0.0193939 0.000457706 0.153625 #(-0.00460792 0.0355563 -0.0550596 0.043009 -0.0897849 0.0978742 -0.0187992 0.00582897 -0.0109002 0.000631806 -0.0163601 0.0133513 -0.0165699 0.0221935 -0.0312557 0.04581 -0.0629084 0.0434437 -0.0167021 0.0323193 -0.0250667 0.0627469 -0.0306966 -0.00490861 -0.0368386 0.0217197 -0.0728413 0.0668549 0.145474 -0.169416 0.0122649 0.00448438 0.013949 -0.0353851 0.020688 0.00875267 -0.0340474 0.0569403 -0.0747049 0.0865628 -0.127027 0.0997718 -0.118786 0.172951 -0.208013 0.216935 -0.215728 0.401293 -0.19069 0.923122)) +(0.0267348 0.000456167 0.130624 #(0.0221721 0.012707 -0.0342673 0.0498141 -0.125798 0.0945948 -0.009383 -0.0118047 -0.00833615 0.0354772 -0.041698 0.0220065 -0.043747 0.0427328 -0.0334768 0.0279624 -0.0268537 0.00968139 0.00111546 0.0377293 -0.0348329 0.0808209 -0.0457136 0.00457449 -0.0453242 -0.0107467 -0.0188348 0.0300905 0.173791 -0.194862 0.0537233 -0.0419804 0.0496971 -0.0701674 0.0499813 -0.00747099 -0.0222291 0.0273433 -0.0549461 0.0661543 -0.122178 0.0944649 -0.101576 0.17229 -0.189446 0.207714 -0.21558 0.418696 -0.215629 0.931565)) +(0.0200745 0.000471228 0.153212 #(0.0163527 0.00660207 -0.0143944 0.046632 -0.126296 0.118434 -0.0369965 -0.00451566 -0.0201182 0.0417401 -0.0308534 -0.00543496 -0.0172945 0.0438493 -0.0319897 -0.0176332 -0.00909391 0.00684448 0.00776292 0.0226499 -0.00129345 0.0597638 -0.057499 0.0439582 -0.0376084 -0.009205 -0.0282326 0.0349981 0.136497 -0.137021 0.0108061 -0.0220325 0.0138336 -0.0341895 0.00554748 0.0125278 -0.0174402 0.0430164 -0.0595981 0.048263 -0.112704 0.102835 -0.101221 0.15651 -0.167554 0.189205 -0.200076 0.383302 -0.1668 0.902884)) +(0.0178948 0.000884452 0.222317 #(-0.00627428 0.017076 -0.0217517 0.0596357 -0.115011 0.137658 -0.140797 0.0413646 -0.025147 0.0409271 -0.0298679 0.0230878 -0.00804102 0.0133819 -0.0343905 0.081481 -0.0160831 0.031044 -0.0362416 0.0814956 -0.0892642 -0.0230409 -0.0232022 0.112084 -0.0729296 -0.0349948 0.00901226 -0.0373362 0.140441 -0.0702999 -0.00257567 -0.0348515 -0.00258082 0.0140751 -0.0718087 0.0880132 -0.061838 0.0690842 -0.118292 0.142831 -0.185955 0.190591 -0.155962 0.45873 -0.106312 0.127302 -0.523777 0.419269 -0.501987 1.22411)) +(0.014956 0.000914502 0.247278 #(-0.023965 0.0260125 -0.0174047 0.0515138 -0.0830966 0.07056 -0.0839288 -0.00253678 0.0274258 -0.000953763 -0.00370321 0.0051892 0.0273904 -0.020619 -0.0100326 0.0564985 0.00785514 0.0225726 -0.0248022 0.0636671 -0.0849298 -0.0493795 0.0247842 0.0783257 -0.054683 -0.0485245 0.00161631 -0.0165824 0.139226 -0.0743001 -0.00122059 -0.0566757 0.0247024 0.00172735 -0.0647441 0.0783151 -0.0575751 0.0609131 -0.105484 0.127889 -0.170536 0.193175 -0.164876 0.462587 -0.105663 0.112055 -0.495609 0.396188 -0.497893 1.21815)) +(0.00871568 0.000567858 0.255252 #(-0.0124666 0.0309579 -0.00109739 0.0135459 -0.057433 0.0477187 -0.0502651 0.00271826 0.0372547 0.0164188 -0.0446111 -0.0127535 -0.0377459 0.05085 -0.0332468 0.0648767 -0.0421368 0.0453716 -0.00560286 0.010505 -0.0502685 0.0272348 -0.0168195 0.0334298 -0.045445 0.0609193 -0.0939262 0.0603289 0.127758 -0.127759 -0.0161537 -0.0241133 0.0220789 0.0501327 -0.0297039 0.0276074 -0.0749799 0.0195223 -0.134458 0.0784379 -0.103965 0.143044 -0.0238226 0.243323 -0.14168 0.124602 -0.245754 0.281028 -0.225522 0.993662)) +(0.0086891 0.000454286 0.228653 #(0.000182833 -0.00254678 0.0082363 -0.0153415 -0.0299224 0.0849131 -0.0489407 0.00623273 0.00330074 0.015936 -0.0400408 -0.020401 -0.0247914 0.0710104 -0.015902 0.00164445 -0.0397469 0.0223963 0.0144133 0.00597068 -0.0101367 0.0517253 -0.0400181 0.0204692 -0.0703128 0.0792271 -0.0877888 0.0647522 0.100521 -0.114483 -0.00566729 -0.0255629 0.0314529 0.0182582 -0.0152464 0.0337968 -0.0685177 0.0350596 -0.0735331 0.0771414 -0.107742 0.0609778 -0.0612328 0.122617 -0.132552 0.162598 -0.143835 0.327107 -0.115002 0.855719)) diff --git a/demos/lpc_tutorial.htm b/demos/lpc_tutorial.htm new file mode 100644 index 0000000..a6af640 --- /dev/null +++ b/demos/lpc_tutorial.htm @@ -0,0 +1,186 @@ + + + + + + Nyquist FFT and Inverse FFT Tutorial + + + +

+Nyquist LPC Analysis and Synthesis

+Nyquist provides functions for LPC analysis and synthesis on streams of +audio data. For analysis, the audio stream is broken into successive frames, +each of which is analyzed, resulting in a small set of coefficients. For +synthesis, these frames control a time-varying filter which can be applied +to an audio signal. +

As with FFT frames, Nyquist does not have a special data type corresponding +to a sequence of LPC frames. Instead, a sequence of frames is represented +by an XLISP object. Whenever you send the selector :next to the +object, you get back either NIL, indicating the end of the sequence, or +you get an LPC frame. (Note that FFT frames and LPC frames are not compatible.) +

This tutorial is based on the file lpcdemo.lsp in the demos +folder fo the Nyquist release. Not every line is covered, but this tutorial +should give you a pretty full explanation of how to use LPC in Nyquist. +

+Preliminaries

+Before using LPC functions, you must load the LPC library: +
(load "lpc")
+At the top of lpcdemo.lsp, you see the following lines: +
(setf *lpc-path* (current-path))
+(setf *lpc-data* (strcat *lpc-path* "lpc-exmpl.dat"))
+The (current-path) function call returns the full file system +path to the file being loaded (lpcdemo.lsp). We save this into +*lpc-path* +so we can find other related files later, even if the current directory +is changed. *lpc-data* is one of the file names we will use later. +

+LPC Analysis

+Another file we want is a-snd-file.snd, a very short vocal sound +that is part of the Nyquist release (it is also used by examples.lsp). +To get this file, we concatenate it with the path we obtained above. The +resulting full path can be passed to s-read to read the sound. +Find the expressions in the following function that build a file name and +read the file as a sound: +
(defun do-lpc-analysis ()
+  (let ((myfile (strcat *lpc-path* "a-snd-file.snd")))
+    (save-lpc-file (make-lpanal-iterator (s-read *myfile*) 0.08 0.04 50)
+                   "temp.dat")))
+You can analyze a sound using make-lpanal-iterator. This function +takes a sound, a frame size, a step size, and the number of poles. In do-lpc-analysis +(above), we used 0.08 seconds, 0.04 seconds, and 50 poles for these parameters. +The result of make-lpanal-iterator is an object that will deliver +LPC frames on demand. In this function, we will grab all of the frames +and write them to a file using save-lpc-file. The data is written +to "temp.dat". You should run this function and look at the file, +which contains ASCII data. Later, we will use this data to filter a sound. +

Since a-snd-file.snd is a very short and uninteresting sound, +we will use a different set of LPC frames in the following synthesis examples. +The data is in lpc-exmpl.dat, and the full path for this file +was computed earlier and stored in *lpc-data*. +

The first example will just show how to read the LPC data file using +make-lpc-file-iterator, +which takes the file name as a parameter. You can print some frame data +using show-lpc-data as shown in the following: +

(defun ex-1 () 
+  (show-lpc-data (make-lpc-file-iterator *lpc-data*) 100 120 NIL))
+The additional parameters to show-lpc-data are the starting frame +(100), the ending frame (120), and a flag (NIL)  indicating +whether to print filter coefficients. If you want to look a little closer +at the inner workings of this code, you can send a :next message +to an LPC iterator object as follows: +
(setf iterator (make-lpc-file-iterator *lpc-data*))
+(send iterator :next)
+This will return the first frame of the LPC analysis. Send :next +again  to get the next frame. +

+LPC Synthesis With Fixed All-Pole Filter

+The next example creates a sequence of vowel sounds. The vowel filters +are based on the +
30th, 60th, and 100th frames taken from the file lpc-exmpl.dat. +We use make-lpc-file-iterator as before to read the LPC frames +from the file, but we use nth-frame to get the desired frames. +

The function allpoles-from-lpc constructs a filter from the +frame and applies it to a sound. In this case, the source sound is created +by buzz with a little vibrato provided by lfo: +
  +

(defun ex-4 () 
+  (play (seq
+          (allpoles-from-lpc (buzz 12 f2 (lfo 5.0 4.0)) 
+                             (nth-frame (make-lpc-file-iterator *lpc-data*)
+                                        30))
+          (allpoles-from-lpc (buzz 12 f2 (lfo 5.1 4.0)) 
+                             (nth-frame (make-lpc-file-iterator *lpc-data*)
+                                        60))
+          (allpoles-from-lpc (buzz 12 g2 (lfo 5.3 4.0))  
+                             (nth-frame (make-lpc-file-iterator *lpc-data*)
+                                        100)) )))
+Rather than iterate through a file to find the desired frame, you can also +just store the desired frames as in the following: +
(setf a-lpcdata
+  '(63.2144 0.674387 0.103287
+    #(-0.0381026 0.00804115 0.0109905 0.0145117 0.00199174 
+      -0.00129314 0.0171826 0.0181176 0.00179391 -0.0114089 
+      -0.0120949 -0.000410595 -0.0122539 -0.0209354 -0.00804976 
+      -0.00345041 -0.00409532 -0.00227011 0.014224 0.0135451
+      0.0056023 -0.00651142 -0.00564953 -0.0168921 -0.0377939
+      -0.0449506 -0.0355592 -0.0339316 -0.0454434 1.19336)))
+ +
(setf e-lpcdata
+  '(40.7157 0.149753 0.0606467
+    #(0.0244574 -0.0225545 -0.0172724 -0.0122709 -0.0042946
+      0.00886974 0.0121516 0.0120936 0.00197545 -0.00582163
+      -0.018367 -0.0201546 -0.00440599 0.00638936 0.0166275
+      0.0185066 0.00890464 -0.00158013 -0.00494974 -0.00479037
+      0.0130814 0.0138648 -0.0022018 -0.021368 -0.0343532 
+      -0.0312712 -0.0574975 -0.0918824 -0.112016 1.31398)))
+ +
(setf i-lpcdata
+  '(5.5391 0.0321825 0.0762238 
+    #(-0.0341124 -0.0149688 -0.00585657 -0.0111572 0.00769712
+      0.0190367 0.00885366 0.0112762 0.0118286 -0.00059044 
+      -0.0140864 -0.0123688 -0.0151128 0.00214354 -0.00810219 
+      -0.00538188 0.00631382 0.020771 0.0356498 0.0295531
+      0.0242797 0.0124296 0.00445127 -0.013062 -0.0387178 
+      -0.0527783 -0.0685511 -0.076575 -0.0846335 1.24521)))
+The following function applies a filter to noise: +
(defun noise-vocal (lpcdata dur)
+  (allpoles-from-lpc (noise dur) lpcdata))
+Combining this with our definitions of different frames, we can write a +little sequence +
of vowel sounds: +
(defun ex-5 ()
+  (play
+    (seq (noise-vocal a-lpcdata 1)
+         (noise-vocal e-lpcdata 1)
+         (noise-vocal i-lpcdata 1))))
+We can do the same thing using a buzz sound rather than noise: +
(defun buzz-vocal (lpcdata dur)
+  (allpoles-from-lpc (buzz 16 e2 (const 0.0 dur))
+                     lpcdata))
+ +
(defun ex-6 ()
+  (play
+     (seq (buzz-vocal a-lpcdata 1)
+          (buzz-vocal e-lpcdata 1)
+          (buzz-vocal i-lpcdata 1))))
+ +

+Time-Varying LPC Filter

+The most interesting LPC effect is to use a sequence of frames to drive +a time-varying all-pole filter. If the frames were analyzed from a vocal +source, then the resulting filter will transfer the speech articulation +(or at least some of it) to another sound. The time-varying LPC filter +is called lpreson. +

Here, the LPC data from *lpc-data* is used to modulate noise: +

(defun ex-7a ()
+  ;; parameters are sound, lpc-iterator, skiptime
+  (lpreson (noise 6.5) (make-lpc-file-iterator *lpc-data*) 0.04))
+ +
(defun ex-7 ()
+  (play (ex-7a)))
+The same thing can be done to filter a buzz sound. This example generates +some vocal-like sounds in two-part harmony: +
(defun ex-8a (p dur)
+  (lpreson (buzz 16 p (scale 1.5 (lfo 3.0 dur))) 
+           (make-lpc-file-iterator +*lpc-data*)
+           0.04))
+
+(defun ex-8 ()
+  (play
+    (sim (seq (ex-8a c4 1) (ex-8a g3 1) (ex-8a a3 1) (ex-8a +b3 1) (ex-8a c4 1))
+         (seq (ex-8a c2 2) (ex-8a +f2 1) (ex-8a g2 1) (ex-8a e2 1)))))
+
+Note that you can change the skiptime parameter to lpreson +to change the rate at which the filter moves through the frames. The result +is to caues the speech articulations to go faster or slower. +

More examples can be found in lpcdemo.lsp. +

+Acknowledgments

+Pedro J. Morales created the LPC functions for Nyquist and wrote lpcdemo.lsp +on which this tutorial is based. + + diff --git a/demos/lpcdemo.lsp b/demos/lpcdemo.lsp new file mode 100644 index 0000000..b78c0f9 --- /dev/null +++ b/demos/lpcdemo.lsp @@ -0,0 +1,263 @@ +;;; LPC demo 1 +;;; Pedro J. Morales. +;;; February, 04 +;;; Roger B. Dannenberg +;;; July, 04 + +; where is the file lpc-exmpl.dat +(setf *lpc-path* (current-path)) +(setf *lpc-data* (strcat *lpc-path* "lpc-exmpl.dat")) + + +; this file generated by Nyquist will be loaded by Octave (or Matlab) +(setf *default-octave-file* (strcat *lpc-path* "nyquist.dat")) + +; make sure lpc.lsp is loaded +(if (not (fboundp 'lpreson)) (load "lpc.lsp")) + +; file-io tools ======================================================== + + +(defun octave-1 (outf data varname datatype &optional (n 1000)) + (prog ((points (case datatype + (SND (snd-samples data (1+ n))) + (ARR data))) + len) + (setf len (length points)) + (cond ((> len n) + (setf len n) + (format t "WARNING: DATA TRUNCATED TO ~A POINTS~%" len))) + (format outf "# name: ~A\n" varname) + (format outf "# type: matrix\n# rows: 1\n# columns: ~A\n " len) + (dotimes (i len) + (format outf "~A " (aref points i))) + (format outf "\n"))) + +(defun octave (data-lists) ; (data varname datatype &optional (n 1000)) + (prog ((filename *default-octave-file*) + outf) + (setf outf (open filename :direction :output)) + (cond ((null outf) + (format t "octave: could not open ~A!~%" filename) + (return nil))) + (format t "octave: writing ~A ... ~%" filename) + (cond ((null outf) + (format t "octave: could not open ~A!~%" filename) + (return nil))) + ;(format t "octave: writing ~A ... ~%" filename) + (dolist (l data-lists) + (apply #'octave-1 (cons outf l))) + (close outf))) + + +; LPANAL ====================================================== + +; get lpc data --------------------------------------------------- + + +(defun do-lpc-analysis () + (let ((myfile (strcat *lpc-path* "a-snd-file.snd"))) + (save-lpc-file (make-lpanal-iterator (s-read *myfile*) 0.08 0.04 50) + "temp.dat"))) + + +; SHOW-LPC-DATA ------------------------------------------------ +; show values of LPC analysis frames ---------------------------- + + +(defun ex-1 () + ; do not show filter coefs + (show-lpc-data (make-lpc-file-iterator *lpc-data*) 100 120 NIL)) + + +; ------- SAVE-FILE-DATA --------------------------------------- +(defun ex-2 () + (save-lpc-file (make-lpc-file-iterator *lpc-data*) "temp2.dat")) + + +;----------- LPC-FREQ ------------------------------------------ +; LPC-FREQ. Show frequency response of ALLPOLES filter. +; NEEDS MATLAB or OCTAVE +; + +(defun ex-3 () + (lpc-freq "frm70" (make-lpc-file-iterator *lpc-data*) 70)) + + +; in MATLAB/OCTAVE: +; >> load -force nyquist.dat +; >> [H,W] = freqz(1, frm70, 512); +; >> plot(W,20*log10(abs(H))); + + +;------------------------------------------------------------------------- +; LPC-STABILITY Check for Stability of LPC filters +; NEEDS MATLAB/OCTAVE + +; EXAMPLE + +; (ex-3) + +; in MATLAB/OCTAVE: +; >> load -force nyquist.dat +; >> find(abs(roots(frm70)) > 1) +; if any abs root is > 1.0 then UNSTABLE + +;-------------------------------------------------------------------------- +; ALLPOLES LPC allpoles filter +; WARNING: this is a static filter +; for LPC resynthesis a dynamic LPC filter is needed + + +; EXAMPLE + +(defun ex-4 () + (play (seq + (allpoles-from-lpc (buzz 12 f2 (lfo 5.0 4.0)) + (nth-frame (make-lpc-file-iterator *lpc-data*) + 30)) + (allpoles-from-lpc (buzz 12 f2 (lfo 5.1 4.0)) + (nth-frame (make-lpc-file-iterator *lpc-data*) + 60)) + (allpoles-from-lpc (buzz 12 g2 (lfo 5.3 4.0)) + (nth-frame (make-lpc-file-iterator *lpc-data*) + 100)) ))) + + +(setf a-lpcdata +'(63.2144 0.674387 0.103287 + #(-0.0381026 0.00804115 0.0109905 0.0145117 0.00199174 -0.00129314 0.0171826 + 0.0181176 0.00179391 -0.0114089 -0.0120949 -0.000410595 -0.0122539 + -0.0209354 -0.00804976 -0.00345041 -0.00409532 -0.00227011 0.014224 0.0135451 + 0.0056023 -0.00651142 -0.00564953 -0.0168921 -0.0377939 -0.0449506 -0.0355592 + -0.0339316 -0.0454434 1.19336))) + +(setf e-lpcdata +'(40.7157 0.149753 0.0606467 + #(0.0244574 -0.0225545 -0.0172724 -0.0122709 -0.0042946 0.00886974 0.0121516 0.0120936 + 0.00197545 -0.00582163 -0.018367 -0.0201546 -0.00440599 0.00638936 0.0166275 0.0185066 + 0.00890464 -0.00158013 -0.00494974 -0.00479037 0.0130814 0.0138648 -0.0022018 -0.021368 + -0.0343532 -0.0312712 -0.0574975 -0.0918824 -0.112016 1.31398))) + + +(setf i-lpcdata +'(5.5391 0.0321825 0.0762238 #(-0.0341124 -0.0149688 -0.00585657 -0.0111572 + 0.00769712 0.0190367 0.00885366 0.0112762 0.0118286 -0.00059044 -0.0140864 -0.0123688 + -0.0151128 0.00214354 -0.00810219 -0.00538188 0.00631382 0.020771 0.0356498 0.0295531 + 0.0242797 0.0124296 0.00445127 -0.013062 -0.0387178 -0.0527783 -0.0685511 -0.076575 + -0.0846335 1.24521))) + +(defun noise-vocal (lpcdata dur) + (allpoles-from-lpc (noise dur) lpcdata)) + +(defun ex-5 () + (play + (seq (noise-vocal a-lpcdata 1) + (noise-vocal e-lpcdata 1) + (noise-vocal i-lpcdata 1)))) + +(defun buzz-vocal (lpcdata dur) + (allpoles-from-lpc (buzz 16 e2 (const 0.0 dur)) + lpcdata)) + +(defun ex-6 () + (play + (seq (buzz-vocal a-lpcdata 1) + (buzz-vocal e-lpcdata 1) + (buzz-vocal i-lpcdata 1)))) + + +; ---- LPRESON ------------------------------------------------------------ +; +(defun ex-7a () + ;; parameters are sound, lpc-iterator, skiptime + (lpreson (noise 6.5) (make-lpc-file-iterator *lpc-data*) 0.04)) + +(defun ex-7 () + (play (ex-7a))) + +(defun ex-8a (p dur) + (lpreson (buzz 16 p (scale 1.5 (lfo 3.0 dur))) + (make-lpc-file-iterator *lpc-data*) + 0.04)) + +(defun ex-8 () + (play + (sim (seq (ex-8a c4 1) (ex-8a g3 1) (ex-8a a3 1) (ex-8a b3 1) (ex-8a c4 1)) + (seq (ex-8a c2 2) (ex-8a f2 1) (ex-8a g2 1) (ex-8a e2 1))))) + +(defun noalias-buzz (p nmax) + (min + (round (/ *sound-srate* (* 2.0 (step-to-hz p)))) + nmax)) + +(defun ex-9a (p dur skiptime) + (mult (env 0.01 0.01 0.1 1.0 1.0 1.0 dur) + (lpreson (buzz (noalias-buzz p 16) p (scale 1.5 (lfo 3.0 dur))) + (make-lpc-file-iterator *lpc-data*) + skiptime))) + + +(defun ex-9b (stretch skiptime) + (play + (sim (seq (ex-9a c4 (* 1 stretch) skiptime) + (ex-9a g3 (* 1 stretch) skiptime) + (ex-9a a3 (* 1 stretch) skiptime) + (ex-9a b3 (* 1 stretch) skiptime) + (ex-9a c4 (* 1 stretch) skiptime)) + (seq (ex-9a c2 (* 2 stretch) skiptime) + (ex-9a f2 (* 1 stretch) skiptime) + (ex-9a g2 (* 1 stretch) skiptime) + (ex-9a e2 (* 1 stretch) skiptime))))) + + +(defun ex-9 () + (ex-9b 1.0 0.04)) + +(defun ex-10 () + (ex-9b 1.0 0.02)) + +(defun ex-11 () + (ex-9b 2.0 0.04)) + +(defun ex-12 () + (ex-9b 0.5 0.02)) + +(defun ex-13 () + (ex-9b 4 0.02)) + +(defun ex-14a (p dur skiptime) + (mult (env 0.01 0.01 0.1 1.0 1.0 1.0 dur) + (lpreson (osc-saw (sim (step-to-hz (+ p 0)) (scale 1.5 (lfo 3.0 dur)))) + (make-lpc-file-iterator *lpc-data*) + skiptime))) + +(defun ex-14b (stretch skiptime) + (play + (sim (seq (ex-14a c4 (* 1 stretch) skiptime) + (ex-14a g3 (* 1 stretch) skiptime) + (ex-14a a3 (* 1 stretch) skiptime) + (ex-14a b3 (* 1 stretch) skiptime) + (ex-14a c4 (* 1 stretch) skiptime)) + (seq (ex-14a c2 (* 2 stretch) skiptime) + (ex-14a f2 (* 1 stretch) skiptime) + (ex-14a g2 (* 1 stretch) skiptime) + (ex-14a e2 (* 1 stretch) skiptime))))) + + +(defun ex-14 () + (ex-14b 1 0.04)) + +(defun ex-15 () + (ex-14b 4 0.02)) + +(defun ex-16 () + (ex-14b 8 0.08)) + + + + + + + + diff --git a/demos/mateos/bell.lsp b/demos/mateos/bell.lsp new file mode 100644 index 0000000..ead4aa5 --- /dev/null +++ b/demos/mateos/bell.lsp @@ -0,0 +1,33 @@ +;; BELL INSTRUMENT +;; Daniel Mateos - danielma@andrew.cmu.edu +;; Instrument by Hans Mikelson, imported from CSOUND +;; Website: http://www.adp-gmbh.ch/csound/instruments/ +;; Modified by Roger Dannenberg, Nov. 2005 +;; see also: demos/pmorales/b3.lsp, +;; demos/pmorales/e2.lsp, and +;; demos/pmoraels/partial.lsp +;; This bell is closely related to FM-BELL in e2.lsp + +;; DMHM-BELL -- an FM bell sound +;; +;; so named to avoid naming conflicts with other bells +;; +(defun dmhm-bell (pitch) + (let ((imax 10) ; max amplitude + (ifq1 (hz-to-step (* (step-to-hz pitch) 5))) ; partials + (ifq2 (hz-to-step (* (step-to-hz pitch) 7))) + (aenv (pwevr 1 1 0.0001)) ; amplitude envelope + (adyn (mult (* imax ifq2) (pwevr 1 1 0.001)))) ; dynamics envelope + (mult aenv ; create a carrier modulated signal + (fmosc ifq1 (mult adyn (osc ifq2)))))) + + +;; Let's play this bell!! +;; +;; type (dmhm-bell-test) to play an example +;; +(defun dmhm-bell-test () + (play (stretch 10 (dmhm-bell g1)))) + + + diff --git a/demos/mateos/gong.lsp b/demos/mateos/gong.lsp new file mode 100644 index 0000000..103c8eb --- /dev/null +++ b/demos/mateos/gong.lsp @@ -0,0 +1,64 @@ +;; GONG INSTRUMENT (TAM TAM) +;; Daniel Mateos - danielma@andrew.cmu.edu +;; Instrument by Hans Mikelson, imported from CSOUND +;; Website: http://www.adp-gmbh.ch/csound/instruments/ +;; Modified by Roger Dannenberg, Nov. 2005 +;; See also: demos/pmorales/b1.lsp + + +;; DMHM-GONG -- an additive synthesis gong sound +;; +;; so named to avoid naming conflicts with other gongs +;; +(defun dmhm-gong (pitch) + (let* ((ifrq (step-to-hz pitch)) + ;; frequencies of partials + (ifrq1 (* 1.0000 ifrq)) + (ifrq2 (* 1.1541 ifrq)) + (ifrq3 (* 1.6041 ifrq)) + (ifrq4 (* 1.5208 ifrq)) + (ifrq5 (* 1.4166 ifrq)) + (ifrq6 (* 2.7916 ifrq)) + (ifrq7 (* 3.3833 ifrq)) + + ;; amplitude of partials + (iamp1 1.0000) + (iamp2 0.8333) + (iamp3 0.6667) + (iamp4 1.0000) + (iamp5 0.3333) + (iamp6 0.3333) + (iamp7 0.3333) + + ;; main envelope + (envelope (pwevr 1 1 0.001)) + + ;; partial envelopes + (aenv1 (mult iamp1 envelope)) + (aenv2 (mult iamp2 envelope)) + (aenv3 (mult iamp3 envelope)) + (aenv4 (mult iamp4 envelope)) + (aenv5 (mult iamp5 envelope)) + (aenv6 (mult iamp6 envelope)) + (aenv7 (mult iamp7 envelope))) + + ;; sum the partials + (scale 0.25 ; normalize to about 1.0 + (sim + (partial (hz-to-step ifrq1) aenv1) + (partial (hz-to-step ifrq2) aenv2) + (partial (hz-to-step ifrq3) aenv3) + (partial (hz-to-step ifrq4) aenv4) + (partial (hz-to-step ifrq5) aenv5) + (partial (hz-to-step ifrq6) aenv6) + (partial (hz-to-step ifrq7) aenv7) + )))) + +;; Let's play something! +;; +;; type (dmhm-gong-test) to play an example +;; +(defun dmhm-gong-test + (autonorm-off) + (play (stretch 10 (dmhm-gong a3)))) + diff --git a/demos/mateos/organ.lsp b/demos/mateos/organ.lsp new file mode 100644 index 0000000..fea0b7e --- /dev/null +++ b/demos/mateos/organ.lsp @@ -0,0 +1,58 @@ +;; Daniel Mateos - danielma@andrew.cmu.edu +;; Instrument by Hans Mikelson, +;; imported from CSOUND +;; Website: http://www.adp-gmbh.ch/csound/instruments/organ01.html +;; This instrument really sounds as a real organ!! +;; Modified by Roger Dannenberg, Nov. 2005 + + +;; Sound overtones +(defun dmhm-overtones (freq) + (sim + (scale 0.8 (hzosc freq)) + (scale 0.8 (hzosc (* freq 2))) + (scale 0.8 (hzosc (* freq 2.9966))) + (scale 0.8 (hzosc (* freq 4))) + (scale 0.3 (hzosc (* freq 5.9932))) + (scale 0.2 (hzosc (* freq 8))) + (scale 0.1 (hzosc (* freq 10.0794))) + (scale 0.1 (hzosc (* freq 11.9864))) + (scale 0.4 (hzosc (* freq 16))))) + + +(defun dmhm-organ (pitch) + (mult 0.1 ;; normalize to about 1 + (env 0.1 0 0.1 1 1 1) + (dmhm-overtones (step-to-hz pitch)))) + + +;; DMHM-ORGAN-TEST -- a small test program/demo +;; +;; The same score used by the CSOUND example. +;; +(defun dmhm-organ-test () + (autonorm-off) + (play + (sim + (at 0 + (stretch 1.98 + (sim + (dmhm-organ c3) + (dmhm-organ e3) + (dmhm-organ g3) + (dmhm-organ as3)))) + + (at 2 + (stretch 1.98 + (sim + (dmhm-organ c3) + (dmhm-organ ds3) + (dmhm-organ f3) + (dmhm-organ a3)))) + + (at 4 (stretch 1.98 (dmhm-organ c3))) + (at 4 (stretch 0.1 (dmhm-organ ds3))) + (at 4.1 (stretch 1.88 (dmhm-organ e3))) + (at 4 (stretch 1.98 (dmhm-organ g3)))))) + + diff --git a/demos/mateos/tuba.lsp b/demos/mateos/tuba.lsp new file mode 100644 index 0000000..51b44cb --- /dev/null +++ b/demos/mateos/tuba.lsp @@ -0,0 +1,94 @@ +;; By Daniel Mateos - Feb 2005 +;; This FM sound is similar to that of the tuba. +;; Therefore, intended mainly for low register. +;; It is built upon a FM 8 parallel oscillator circuit. +;; The attack will remain constant whatever the enviroment. +;; Also, it is properly prepared for transposition. +;; Modified by Roger Dannenberg, Nov 2005 + +;; Variable amplitude & frequency oscillator +(defun tuba-osc (amp freq) + (mult amp (hzosc freq))) + + +;; Parallel 8 oscillators FM +(defun tuba-eight-osc (acar fcar amod1 fmod1 amod2 fmod2 amod3 fmod3 + amod4 fmod4 amod5 fmod5 amod6 fmod6 amod7 fmod7 amod8 fmod8) + (tuba-osc acar (sim fcar + (tuba-osc amod1 fmod1) + (tuba-osc amod2 fmod2) + (tuba-osc amod3 fmod3) + (tuba-osc amod4 fmod4) + (tuba-osc amod5 fmod5) + (tuba-osc amod6 fmod6) + (tuba-osc amod7 fmod7) + (tuba-osc amod8 fmod8)))) + + +;; Define amplitude envelope of each modulator +(defun tuba-amod (numb) + (seq + (stretch-abs 1 (pwl (/ numb 10) 100)) + (pwl 0 100 (- 1 (/ numb 10))))) + + +;; Defines Amplitud envelope of carrier +(defun tuba-acar () + (seq + (stretch-abs 1 (pwl 0.1 0.8)) + (pwl 0 0.8 0.7 0.8 0.9))) + + +;; Defines frequency of each modulator +(defun tuba-fmod (numb fcar) + (case numb + (1 (- fcar 2)) + (2 (- (* fcar 4) 3)) + (3 (- (* fcar 3) 2)) + (4 (- (* fcar 5) 2)) + (5 (- (* fcar 6) 2)) + (6 (- (* fcar 7) 2)) + (7 (- (* fcar 8) 2)) + (8 (- (* fcar 9) 2)))) + + +;; DMHM-TUBA -- a tuba-like FM sound +;; +;; named dmhm-tuba to avoid name conflicts with other (possible) tubas +;; +(defun dmhm-tuba (fcar) + (setf transp (float (get-transpose))) + (cond ((> transp 0.0) + (setf fcar (float fcar)) + (setf fcar (* fcar (expt 2.0 (/ transp 12.0)))) )) + (cond ((< transp 0.0) + (setf transp (* -1.0 transp)) + (setf fcar (float fcar)) + (setf fcar (/ fcar (expt 2.0 (/ transp 12.0)))) )) + (scale 0.8 ; normalize + (lp + (hp + (transpose-abs 0 + (tuba-eight-osc (tuba-acar) fcar + (tuba-amod 1) (tuba-fmod 1 fcar) + (tuba-amod 2) (tuba-fmod 2 fcar) + (tuba-amod 3) (tuba-fmod 3 fcar) + (tuba-amod 4) (tuba-fmod 4 fcar) + (tuba-amod 5) (tuba-fmod 5 fcar) + (tuba-amod 6) (tuba-fmod 6 fcar) + (tuba-amod 7) (tuba-fmod 7 fcar) + (tuba-amod 8) (tuba-fmod 8 fcar)) ) + 10) + 22000))) + +;; DMHM-TUBA-TEST -- play a sample of dm-tuba instrument +;; +(defun dmhm-tuba-test () + (autonorm-off) + (play + (seq + (dm-tuba 70 ) + (stretch 5 (dm-tuba 70)) + (loud -10 (dm-tuba 70)) + (transpose -10 (stretch 3 (dm-tuba 70)))))) + diff --git a/demos/midi_tutorial.htm b/demos/midi_tutorial.htm new file mode 100644 index 0000000..3f0f4a8 --- /dev/null +++ b/demos/midi_tutorial.htm @@ -0,0 +1,2 @@ + + Midi Tutorial

Midi Tutorial

Nyquist can read and write midi files. Midi files are read into and written from a special XLisp data type called a SEQ, which is short for "sequence". (This is not part of standard XLisp, but rather part of Nyquist.) Nyquist can examine the contents of a SEQ type, modify the SEQ by adding or deleting Midi notes and other messages. Finally, and perhaps most importantly, Nyquist can use the data in a SEQ type along with a sound behavior to generate sound. In other words, Nyquist can become a Midi synthesizer.

The SEQ Type

To create a SEQ data object:

> (setf my-seq (seq-create))
#<SEQ:0x7a6f60>
> (type-of my-seq)
SEQ
>

Reading a Midi File

Once you have a sequence, you can read Midi data into it from a file. You do this in three steps. First, you open the file in binary mode (using open-binary, a Nyquist extension to XLisp). Then you read from the file. Finally, you (normally) close the file.

(setf midi-file (open-binary "demo.mid"))
(seq-read-smf my-seq midi-file)
(close midi-file)

Writing a Midi File

A sequence can be written to a file. First you open the file as a binary output file; then you write it; then you close it.

(setf midi-file (open-binary "copy.mid" :direction :output))
(seq-write-smf my-seq midi-file t)
(close midi-file)

The result will not be a bit-for-bit copy of the original Midi file because the SEQ representation is not a complete representation of the Midi data. For example, the Midi file can contain headers and meta-data that is not captured by Nyquist. Nevertheless, the resulting Midi file should sound the same if you play it with a sequencer or Midi file player.

Writing a Text Representation

One very handy feature of the SEQ datatype is that it was originally developed for a text-based representation of files called the Adagio Score Language, or just "Adagio." You can write an Adagio file from a sequence by opening a text file and calling seq-write.

(setf gio-file (open "copy.gio" :direction :output))
(seq-write my-seq gio-file)
(close gio-file)

The basic format of the Adagio file is pretty intuitive, but you can find the full description in the CMU Midi Toolkit manual or in a chapter of the Nyquist manual, including the online version in HTML.

Reading an Adagio File

Because Adagio is text, you can easily edit them or compose your own Adagio file. You should be aware that Adagio supports numerical parameters, where pitch and duration are just numbers, and symbolic parameter, where a pitch might be Bf4 (for B-flat above middle-C) and a duration might be QT (for a quarter note triplet). Symbolic parameters are especially convenient for manual entry of data. Once you have an Adagio file, you can create a sequence from it in Nyquist:

(setf seq-2 (seq-create))
(setf gio-file (open "demo.gio"))
(seq-read seq-2 gio-file)
(close gio-file)

Adding Notes to a SEQ Type

Although not originally intended for this purpose, XLisp and Nyquist form a powerful language for generating Midi files. These can then be played using a Midi synthesizer or using Nyquist, as will be illustrated later.

To add notes to a sequence, you call seq-insert-note as illustrated in this routine, called midinote. Since seq-insert-note requires integer parameters, with time in milliseconds, midinote performes some conversions and limiting to keep data in range:

(defun midinote (seq time dur voice pitch vel)
  (setf time (round (* time 1000)))
  (setf dur (round (* dur 1000)))
  (setf pitch (round pitch))
  (setf vel (round vel))
  (seq-insert-note seq time 0 (1+ voice) pitch dur vel))

Now, let's add some notes to a sequence:

(defun test ()
  (setf *seq* (seq-create))
  (midinote *seq* 0.0 1.0 1 c4 100)
  (midinote *seq* 1.0 0.5 1 d4 100)
  (midinote *seq* 2.0 0.8 1 a4 100)
  (setf seqfile (open-binary "test.mid" :direction :output))
  (seq-write-smf *seq* seqfile)
  (close seqfile))

A Larger Example

This example illustrates the creation of random note onset times using the Poisson distribution. One way to generate this distribution, as seen here, is to create uniformly distributed random times, and then sort these. The function that creates times and then quantizes them to 24ths of a beat is shown here. The len parameter is the number of times, and the average-ioi parameter is the average inter-onset-interval, the average time interval between two adjacent times:

;; create list of random times and sort it
;; dur in ms.
(defun poisson-gen (len average-ioi)
  (let ((dur (* len average-ioi)) poisson-list)
    (dotimes (i len)
	     (push (* dur (random 10000) 0.0001) 
                   poisson-list))
    (setf poisson-list (sort poisson-list #'<))
    (display "initial list" poisson-list)
    ;; map list to 24ths:
    (setf poisson-list
          (quantize-times-to-24ths poisson-list)) ))

We add a few functions to help express time in terms of beats:

(defun set-tempo (tempo)
  (setf qtr (/ 60.0 tempo))
  (setf 8th (* qtr 0.5))
  (setf half (* qtr 2))
  (setf whole (* qtr 4))
  (setf 16th (* qtr 0.25)))

(if (not (boundp 'qtr)) (set-tempo 100))

(defun quantize-times-to-24ths (list)
  (mapcar #'quantize-time-to-24ths list))

(defun quantize-time-to-24ths (time)
  (* (/ qtr 24.0)
     (round (* 24 (/ time qtr)))))

Now, let's create Midi notes using Poisson-based onset times:

(defun melody (seq onsets)
  (dolist (onset onsets)
    (midinote seq onset 16th 1 (+ 48 (random 24)) 100)))

(defun poisson-melody ()
  (setf *seq* (seq-create))
  (melody *seq* (poisson-gen 50 8th)) ;; adds notes to *seq*
  (setf seqfile (open-binary "pois.mid" :direction :output))
  (seq-write-smf *seq* seqfile)
  (close seqfile))

After evaluating (poisson-melody), you can play the file "pois.mid" to hear the result. The times are quantized to 24th notes at a tempo of 100, so you can even use a notation editor to display the result in common music notation.

Synthesizing a Midi File

To synthesize sound from a Midi file, use the seq-midi control construct. This behavior reads the data in the seq object and for each note, creates an instance of the behavior you provide. You will need an instrument, so let's define a simple FM instrument to play the notes of the Midi data:

(defun fm-note (p)
  (mult (pwl 0.01 1 .5 1 1)
        (fmosc p
               (mult (step-to-hz p)
                     (pwl 0.01 6 0.5 4 1)
                     (osc p)))))

Now let's use fm-note to play the previously defined poisson-melody, which was saved in the variable *seq*:

(play (seq-midi *seq* (note (chan pitch vel) (a-note pitch))))

The seq-midi construct automatically uses time transformations to place notes at the proper time and to stretch them to the indicated duration. In addition, it sets the chan, pitch, and vel parameters according to the Midi data before invoking your behavior. In this simple example, we ignored chan and vel, but we used pitch to get the right pitch. You might write a more complicated behavior that uses chan to select different synthesis algorithms according to the Midi channel.

The syntax for the seq-midi construct may be a little confusing. The symbol note appears to be a function call, but it is not. It is really there to say that the following parameter list and behavior expression apply to Midi notes. There can be other terms for other Midi messages, e.g.

(seq-midi my-seq
   (note (chan pitch velocity) (my-note pitch velocity))
   (ctrl (chan control value) (...))
   (bend (chan value) (...))
   (touch (chan value) (...))
   (prgm (chan value) (setf (aref my-prgm chan) value))

Examining SEQ Data

In the lib folder of the standard Nyquist installation, there is a file called midishow.lsp. If you load this, you can call some functions that help you examine SEQ data. Try the following (after running poisson-melody above).

(load "midishow")
(midi-show *seq*)

You will see a printout of the data inside the SEQ data object. Unlike Midi, which stores note-on and note-off messages separately, the SEQ structure saves notes as a single message that includes a duration. This is translated to and from Midi format when you write and read Midi files.

You can also examine a Midi file by calling:

(midi-show-file "demo.mid")

This function can take an optional second argument specifying an opened text file if you want to write the data to a file rather than standard (console) output:

(midi-show-file "demo.mid" (open "dump.txt" :direction :output))
(gc)

What is going on here? I did not save the opened file, but rather passed it directly to midi-show-file. Therefore, I did not have a value to pass to the close function. However, I know that files are closed by the garbage collector when there are no more references to them, so I simply called the garbage collector (gc) to run and close the file.



diff --git a/demos/osc-test.lsp b/demos/osc-test.lsp new file mode 100644 index 0000000..103c5e6 --- /dev/null +++ b/demos/osc-test.lsp @@ -0,0 +1,90 @@ +(load "nyinit.lsp") +(osc-enable t) +(autonorm-off) +(snd-set-latency 0.1) + +;; TEST 1 -- using hzosc +(defun hzosc-osc () + (hzosc (sum 500 (mult 500 (lp (snd-slider 0 (local-to-global 0) + *default-sound-srate* 10) 2.0))))) + + +; (play (hzosc-osc)) + + +;; TEST 2 -- using granular synthesis +(if (not (boundp '*granfile*)) + (load "gran.lsp")) + + +;; this is modified from gran.lsp to allow pitch-dev to be continuous +;; +(defun sf-granulate (filename grain-dur grain-dev ioi ioi-dev pitch-dev-factor + &optional (file-start 0) (file-end 0)) + (let (orig n env actual-grain-dur step-size + (avg-ioi (+ ioi (/ ioi-dev 2.0))) + (file-dur (sf-dur filename)) + (dur (get-duration 1))) + (setf n (truncate (/ dur avg-ioi))) + (cond ((< file-dur file-start) + (error "sf-granulate: file-start is after end of file!")) + ((< file-dur file-end) + (error "sf-granulate: file-end (offset) exceeds file duration!")) + ((< file-dur (+ file-start file-end)) + (error "sf-granulate: file-start + file-end > file duration!"))) + (setf file-dur (- file-dur file-start file-end)) + (setf step-size (/ file-dur n)) + ;(display "sf-granulate" step-size file-dur n) + (stretch-abs 1.0 (let () + (seqrep (i n) (let () + (setf actual-grain-dur (real-random grain-dur (+ grain-dur grain-dev))) + (setf env (stretch actual-grain-dur (one-minus-cosine))) + (force-srate *sound-srate* + (stretch (real-random (+ 0.1 (* pitch-dev-factor (get-slider-value 0))) + 1) + (sound2 + (set-logical-stop + (mult (cue env) + (s-read filename + :time-offset (+ file-start (* step-size i)) + :dur actual-grain-dur)) + (real-random ioi (+ ioi ioi-dev)))))))))))) + + +(defun gran-osc () + (scale 0.8 + (stretch 4 ; total is stretch * 10 seconds, i.e. 4 -> 40s + (simrep (i 4) + (sf-granulate *granfile* 0.04 0.0 0.02 0.001 10 0 0))))) + +;(play (gran-osc)) + +;; TEST 3 - piano sequence + +(defun piano-osc () + (if (not (fboundp 'piano-note)) + (load "pianosyn")) + (seqrep (i 200) (piano-note (+ 0.05 (* 0.2 (get-slider-value 1))) + (round (+ (real-random c1 c2) + (* (get-slider-value 0) 60))) + 100))) + +;; TEST 4 - minimoog filter sweep + +(defun moog-osc () + (setf *moog-dur* 10) + (let ((cutoff (lp (snd-slider 0 (local-to-global 0) + *default-sound-srate* *moog-dur*) 2.0)) + bandwidth) + (setf cutoff (scale 2000 cutoff)) + (setf cutoff (snd-maxv cutoff (const 20 *moog-dur*))) + (mult (pwl 1 1 (- *moog-dur* 1) 1 *moog-dur*) + (scale 2 (reson (stretch *moog-dur* (osc-saw 50)) + cutoff (mult cutoff 0.1) 2))))) + +; (scale 1000 (ramp 5)))) ; (* 1000.0 (get-slider-value 0)))) + +(format t "(play (hzosc-osc)) -- play oscillator controlled by slider 0\n") +(format t "(play (gran-osc)) -- play granular synthesis controlled by slider 0\n") +(format t "(play (piano-osc)) -- play piano sequence controlled by slider 0, duration by slider 1\n") +(format t "(play (moog-osc)) -- play minimoog with filter controlled by slider 0\n") \ No newline at end of file diff --git a/demos/piano.htm b/demos/piano.htm new file mode 100644 index 0000000..ca5d72e --- /dev/null +++ b/demos/piano.htm @@ -0,0 +1,2 @@ + + Untitled Document

Piano Synthesizer Tutorial

This page describes how to use the piano synthesizer in Nyquist.

First, load the file "pianosyn.lsp" to initialize the synthesizer. The file is in the "lib" directory.

>(load "pianosyn")

After the piano synthesizer has been initialized and returns, you can use the functions provided by the synthesizer program to generate piano sounds.

The functions are shown as below:

Generate a single note

Use the function:

(piano_note duration step dynamic)

  • duration represents the duration of the note in seconds.
  • step represents the pitch of note, and uses step values as in all Nyquist functions. For example, value 60 is middle C (C4).
  • dynamic means the dynamics of the note, and it ranges from 0 to 127. In a midi file, it is used as the velocity of the note.
This behavior returns a sound. You can use (play (piano_note...)) or (s_save (piano_note...)...) to play or save the sound.

Examples:

> (play (piano_note 4 60 100))
The command above will generate and immediately play a C4 note that lasts 4 seconds, velocity at 100.

Synthesize piano music according to a midi file

To convert a midi file to sound, use the function:

(piano_midi midi_file_name)

  • midi_file_name is a string representing the name of the midi file.
This behavior will generate sound according to the score of the midi file. It generates stereo sound, and the sample rate is the default sound sample rate.

Convert midi file to sound file

To convert a midi file to a sound file using the piano synthesizer, use the function:

(piano_midi2file midi_file_name sound_file_ name)

  • midi_file_name is a string representing the name of the midi file.
  • sound_file_name is a string representing the name of the sound file.
This command will generate a sound file according to the score of the midi file and play it at the same time. It generates stereo sound, and the sample rate is the default sound sample rate.

Example:

>(piano_midi2file "demo.mid" "demo.wav")
"demo.mid" is the name of the midi file. It saves the output sound into "demo.wav", and plays it when generating the output.

Generated by Ning Hu(ning_hu@cmu.edu) Mar.22, 2001 diff --git a/demos/pitch_change.htm b/demos/pitch_change.htm new file mode 100644 index 0000000..43852e7 --- /dev/null +++ b/demos/pitch_change.htm @@ -0,0 +1,83 @@ + + + +Pitch Change by Resampling Tutorial + + + + +

Pitch Change by Resampling Tutorial

+ +

Roger Dannenberg

+

+This tutorial shows how to change the pitch of a sound using resampling. +In this example, a source sound is resampled to effectively play the sound +faster and/or slower. This changes the perceived pitch. It also makes the +sound play faster and/or slower, so the original duration is not preserved. +

+To control the playback speed, a control function is used. The function +specifies the pitch shift in steps, so if the function is zero, there is +no change. If the signal is 1, the signal is shifted up one half-step. +If the signal is -2, the signal is shifted down a whole-step, etc. +

+The control signal can of course change over time. The control signal +time corresponds to time in the resulting sound. Thus, if the control +signal jumps from 0 to 5 at time 3, the resulting sound will jump up +a musical fourth (5 half-steps) at time 3. This may or may not be time +3 in the source sound. + +

+The code implements VARIABLE-RESAMPLE which takes two parameters: +

    +
  • steps -- the pitch control function +
  • snd -- the source sound to be resampled +
+The function works as follows: +First, steps is converted to ratio, which is the speed change expressed +as a ratio. E.g. when steps is 12 (an octave), ratio will be 2 (a 2:1 ratio) +Second, ratio is integrated to get map. The map is a function from real +time to the score. Note that the slope of the map at any time determines +the amount of speedup. +Finally, SND-COMPOSE is used to map the source sound according to the +tempo map. Because SND-COMPOSE is defined to output the sample rate +of the map, we coerce the sample rate of map to *sound-srate*. +

+This function could be improved by adding code to handle stereo inputs. +Also, this function should really be implemented using snd-resamplev, +which uses a high-quality resampling algorithm. Unfortunately, there +a bug in snd-resamplev, so until the bug is fixed, snd-compose actually +sounds better. +

+The resulting sound ends whenever either steps or snd come to an end. +To control duration, you may want to make sure that the source sound +is much longer than the control function. That way, even if you speed +it up, it will still last long enough to exhaust the control function, +and you know by design how long that is. You can also apply an +envelope to the result to trim it to a known length. +

+So, here finally is the implementation: +

+(defun variable-resample (steps snd)
+  (let ((p1 (/ (log 2.0) 12))  ; p1 helps convert steps to a ratio
+        ratio map)
+    (setf ratio (s-exp (mult steps p1))) ; pitch ratio
+    (setf map (integrate ratio)) ; map from real-time to sound time
+    (snd-compose snd (force-srate *sound-srate* map))))
+
+Here is an example: the PWL control function is initially zero (no +transposition), but starting at time 1.0, it rises to 2.0 in 0.1s +where it remains until time 3.0. The function ends at time 3.0. +The sound to be modified in this case is a simple sinusoid with a +duration of 8. In this case, the PWL function finishes at 3.0s, well +before the OSC sound comes to an end. +
+(play
+       (variable-resample (pwl 1.0 0.0 1.1 2.0 3.0 2.0 3.0) (osc c4 8.0)))
+
+Note that you can replace (osc c4 8.0) with any sound, including one +read from a sound file using S-READ. + + + + + diff --git a/demos/pmorales/a4.lsp b/demos/pmorales/a4.lsp new file mode 100644 index 0000000..6c39f22 --- /dev/null +++ b/demos/pmorales/a4.lsp @@ -0,0 +1,25 @@ +;;; SIMPLE SYNTHESIS +;;; Waveform + Envelope. Modulating the envelope with noise +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun shiver (dur frq noise-percent noise-frq) + (mult (osc frq dur) + (sum (pwlv 5e-2 300e-3 1.0 (- dur 300e-3) 1.0 dur 2e-3) + (mult (/ noise-percent 100.0) (randi1 noise-frq dur))))) + +; when noise-percent is too big (> 40), there is a click risk at the +; beginning and the end of the note +; this would be avoided if randi function were multiplied by a smooth envelope +; WARNING: randi1 is defined in PJMG.LSP + +(defun shiver-demo () + (ss (seq (shiver 1 c5 20 40) + (shiver 1 b4 50 40) + (shiver 1 a4 80 40) + (shiver 1 g4 20 300) + (shiver 1 f4 50 300) + (shiver 1 d4 80 300)))) diff --git a/demos/pmorales/a5.lsp b/demos/pmorales/a5.lsp new file mode 100644 index 0000000..33ef37e --- /dev/null +++ b/demos/pmorales/a5.lsp @@ -0,0 +1,20 @@ +;;; SIMPLE SYNTHESIS +;;; Waveform + Envelope. Modulating the frequency +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun whiny (dur frq) + (let ((lfo-f (step-to-hz frq))) + (mult (pwl 0.1 1 (- dur 0.1) 1 dur) + (fmosc frq (pwl (* 0.1 dur) (/ lfo-f -2.0) + (* 0.25 dur) (* lfo-f 2.0) + (* 0.3 dur) (* lfo-f 1.5) + (* 0.7 dur) (* lfo-f -7.0 (/ 8.0)) + dur (* lfo-f -15.0 (/ 16.0)) + ))))) + +(defun whiny-demo () (ss (whiny 10 a5))) + diff --git a/demos/pmorales/a6.lsp b/demos/pmorales/a6.lsp new file mode 100644 index 0000000..a50334f --- /dev/null +++ b/demos/pmorales/a6.lsp @@ -0,0 +1,33 @@ +;;; SIMPLE SYNTHESIS +;;; Waveform + Envelope. Modulating the frequency, 2 +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun saw-table () + (setf *saw-table* (pwlv 1.0 1.0 0.0)) + (setf *saw-table* (list *saw-table* (hz-to-step 1) T))) + +(if (not (boundp '*saw-table*)) (saw-table)) + +(defun cheap (frq-randi frq dur lfor lfoi) + (mult (randi1 frq-randi dur) + (fmosc frq (mult (const lfoi dur) + (osc (hz-to-step lfor) dur *saw-table*))))) + + +(defun callas (dur frq vib-r vib-w) + (mult (pwl 0.1 1.0 (- dur 0.1) 1.0 dur) + (fmosc frq (mult (const vib-w dur) + (sine (hz-to-step vib-r) dur))))) + +(defun callas-demo () + (ss (seq (sim (at 0.0 (cheap 80 a4 6.5 3 1000)) + (at 2.5 (cheap 150 a5 6.5 3 750))) + (callas 1 a4 5 24) + (callas 0.5 e5 5 24) (callas 0.5 f5 5 24) (callas 1 a5 5 24) + (callas 1 c6 5 24) (callas 1 e6 5 24) + (callas 1 g4 5 24) (callas 1 f4 5 24) + (callas 3 e4 5 24)))) diff --git a/demos/pmorales/b1.lsp b/demos/pmorales/b1.lsp new file mode 100644 index 0000000..1938ad5 --- /dev/null +++ b/demos/pmorales/b1.lsp @@ -0,0 +1,60 @@ +;;; ADDITIVE SYNTHESIS +;;; Gong like sounds +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + + +(defun add-partial (dur frq scal) + (amosc (hz-to-step frq) (pwev scal dur (* scal 1e-2)))) + +(defun gong-1 () + (sim (add-partial 4 240 3.0) + (add-partial 4 277 2.5) + (add-partial 4 385 2.0) + (add-partial 4 605 3.0) + (add-partial 4 340 1.0) + (add-partial 4 670 1.0) + (add-partial 4 812 1.0))) + +(defun add-partial-2 (frq scal) + (amosc (hz-to-step frq) (pwev scal (/ (* 6 240) frq) (* scal 1e-2)))) + +(defun gong-2 () + (sim (add-partial-2 240 3.0) + (add-partial-2 277 2.5) + (add-partial-2 385 2.0) + (add-partial-2 605 3.0) + (add-partial-2 340 1.0) + (add-partial-2 670 1.0) + (add-partial-2 812 1.0))) + +(defun add-partial-3 (frq fratio dur amp) + (amosc (hz-to-step (* frq fratio)) (pwev amp (/ dur fratio) (* amp 1e-2)))) + +(defun gong-3 (frq dur) + (sim (add-partial-3 frq 1.0 dur 2.0) + (add-partial-3 frq 2.0 dur 2.0) + (add-partial-3 frq 2.4 dur 2.0) + (add-partial-3 frq 3.0 dur 2.0) + (add-partial-3 frq 4.5 dur 3.0) + (add-partial-3 frq 5.33 dur 3.0) + (add-partial-3 frq 6.0 dur 3.0))) + + +(defun gong-3-melody () + (sim (at 0.0 (gong-3 329 5)) + (at 0.2 (gong-3 360 6)) + (at 0.4 (gong-3 380 5)) + (at 0.6 (gong-3 300 8)) + (at 0.8 (gong-3 430 4)) + (at 2.0 (gong-3 640 4)) + (at 2.2 (gong-3 610 5)) + (at 2.4 (gong-3 580 4)) + (at 2.6 (gong-3 660 5)))) + +(defun gong-3-demo () (ss (gong-3-melody))) + + diff --git a/demos/pmorales/b10.lsp b/demos/pmorales/b10.lsp new file mode 100644 index 0000000..70a6941 --- /dev/null +++ b/demos/pmorales/b10.lsp @@ -0,0 +1,63 @@ +;;; ADDITIVE SYNTHESIS +;;; Sinus Chaos +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun env31 () + (pwlv 0.99 25e-3 0.99 225e-3 0.318 275e-3 0.318 475e-3 0.99 500e-3 0.99)) + +(defun env32 () + (pwlv 0.377 250e-3 0.99 500e-3 0.377)) + +(defun env33 () + (pwlv 0.5 20e-3 0.5 225e-3 0.99 250e-3 0.99 480e-3 0.5 500e-3 0.5)) + +(defun env34 () + (pwlv 0.333 25e-3 0.333 225e-3 0.999 275e-3 0.999 475e-3 0.333 500e-3 0.333)) + +(defun make-env31 () + (setf *env31* (list (env31) (hz-to-step 2) T))) + +(defun make-env32 () + (setf *env32* (list (env32) (hz-to-step 2) T))) + +(defun make-env33 () + (setf *env33* (list (env33) (hz-to-step 2) T))) + +(defun make-env34 () + (setf *env34* (list (env34) (hz-to-step 2) T))) + +(if (not (boundp '*env31*)) (make-env31)) +(if (not (boundp '*env32*)) (make-env32)) +(if (not (boundp '*env33*)) (make-env33)) +(if (not (boundp '*env34*)) (make-env34)) + +(defun make-table12 () + (setf *table12* (sim (build-harmonic 21.0 2048) + (build-harmonic 29.0 2048) + (build-harmonic 39.0 2048))) + (setf *table12* (list *table12* (hz-to-step 1) T))) + +(if (not (boundp '*table12*)) (make-table12)) + + +(defun chaos-partial (amp rate frq dur env &optional (table *table*)) + (scale amp (fmosc (hz-to-step 1e-3) + (scale frq (osc (hz-to-step rate) dur env)) table))) + +(defun partial2 (amp frandi rate frq dur env) + (mult (randi1 frandi dur) + (scale amp (fmosc (hz-to-step 1e-3) + (scale frq (osc (hz-to-step rate) dur env)))))) + +(ss + (sim + (chaos-partial 4.5 0.12 880.0 24 *env31*) + (partial2 4.0 200.0 0.17 1660.0 24 *env32*) + (chaos-partial 1.2 0.05 200.0 24 *env33*) + (chaos-partial 0.7 0.33 2400.0 24 *env34*) + + )) diff --git a/demos/pmorales/b2.lsp b/demos/pmorales/b2.lsp new file mode 100644 index 0000000..c529cd1 --- /dev/null +++ b/demos/pmorales/b2.lsp @@ -0,0 +1,45 @@ +;;; ADDITIVE SYNTHESIS +;;; Risset's Spectral Analysis of a Chord +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +; Probar con las dos envolventes +;(defun sac-env (dur) +; (let ((xx (pwl (/ dur 2) 1.0 dur))) +; (mult xx xx))) + +(defun sac-env (dur) + (pwev 1.0 dur 5e-2)) + +(defun attk-list (offset num-harms &optional (out-list (list 0.0))) + (if (= num-harms 0) (reverse out-list) + (attk-list offset (1- num-harms) (cons (+ offset (car out-list)) out-list)))) + + +(defun sac (frq dur offset-entry num-harm) + (mapcar #'(lambda (xhrm xoff) + (at xoff (amosc (hz-to-step (* (step-to-hz frq) xhrm)) (sac-env dur)))) + (attk-list -1 (1- num-harm) (list num-harm)) + (attk-list offset-entry (1- num-harm)))) + +(defun sac-left-right (l) + (do* ((i 0 (1+ i)) + (left () (if (evenp i) (cons (nth i l) left) left)) + (right () (if (oddp i) (cons (nth i l) right) right))) + ((= i (1- (length l))) (vector (apply #'sim left) (apply #'sim right))))) + +(defun st-sac (frq dur offset-entry num-harm) + (sac-left-right (sac frq dur offset-entry (1+ num-harm)))) + +(defun st-sac-sequence () + (scale 0.17 (sim (at 0.0 (st-sac as6 7.5 2.5 5)) + (at 0.01 (st-sac b5 7.5 2.5 5)) + (at 3.75 (st-sac e5 3.75 1.25 9)) + (at 3.76 (st-sac g5 3.75 1.25 9)) + (at 5.5 (st-sac d4 2 1.0 11)) + (at 5.51 (st-sac gs3 2 1.0 11))))) + +(defun st-sac-demo () (ss (st-sac-sequence))) diff --git a/demos/pmorales/b3.lsp b/demos/pmorales/b3.lsp new file mode 100644 index 0000000..c4c7b33 --- /dev/null +++ b/demos/pmorales/b3.lsp @@ -0,0 +1,40 @@ +;;; ADDITIVE SYNTHESIS +;;; Risset Bell +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun bell-partial (amp dur frq) + (amosc (hz-to-step frq) (pwev amp dur (* amp 12e-5)))) + +(defun risset-bell (amp dur frq) + (sim + (bell-partial amp dur (* frq .56)) + (bell-partial (* amp .67) (* dur .9) (+ (* frq .56) 1)) + (bell-partial (* amp 1.35) (* dur .65) (* frq .92)) + (bell-partial (* amp 1.8) (* dur .55) (+ (* frq .92) 1.7)) + (bell-partial (* amp 2.67) (* dur .325) (* frq 1.19)) + (bell-partial (* amp 1.67) (* dur .35) (* frq 1.7)) + (bell-partial (* amp 1.46) (* dur .25) (* frq 2.0)) + (bell-partial (* amp 1.33) (* dur .2) (* frq 2.74)) + (bell-partial (* amp 1.33) (* dur .15) (* frq 3.0)) + (bell-partial amp (* dur .1) (* frq 3.76)) + (bell-partial (* amp 1.33) (* dur .075) (* frq 4.07)))) + + +(defun risset-bell-sequence () + (sim (at 0.0 (risset-bell 1.0 4.0 999.0)) + (at 2.0 (risset-bell 1.0 4.0 633.0)) + (at 4.0 (risset-bell 1.0 4.0 211.0)) + (at 6.0 (risset-bell 1.0 4.0 999.0)) + (at 8.0 (risset-bell 0.7 20.0 633.0)) + (at 10.0 (risset-bell 0.7 20.0 211.0)) + (at 12.0 (risset-bell 0.7 20.0 999.0)) + (at 14.0 (risset-bell 0.7 20.0 80.0)))) + +(defun risset-bell-demo () (ss (m))) + + + diff --git a/demos/pmorales/b5.lsp b/demos/pmorales/b5.lsp new file mode 100644 index 0000000..30e568d --- /dev/null +++ b/demos/pmorales/b5.lsp @@ -0,0 +1,19 @@ +;;; ADDITIVE SYNTHESIS +;;; Continuous pitch control by LFO +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun lfo-pitch-control () + (pwlv 0.25 0.6 0.25 1.4 0.5 2.0 0.25 2.2 0.25 3.4 0.5 3.8 0.75 7.0 -0.2)) + +(defun starship (frq scl) + (apply #'sim + (mapcar #'(lambda (offset) + (fmosc (hz-to-step (+ frq offset)) + (scale scl (lfo-pitch-control)))) + '(0.0 4.5 9.4 23.0 39.0 84.0)))) + +(defun starship-demo () (ss (starship 200.0 1000.0)) ) diff --git a/demos/pmorales/b7.lsp b/demos/pmorales/b7.lsp new file mode 100644 index 0000000..4a0a2fe --- /dev/null +++ b/demos/pmorales/b7.lsp @@ -0,0 +1,40 @@ +;;; ADDITIVE SYNTHESIS +;;; Risset Tibetan +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun tibetan-wave () + (setf *tibetan-table* + (sim (scale 0.3 (build-harmonic 1 2048)) + (scale 0.1 (build-harmonic 5 2048)) + (scale 0.1 (build-harmonic 6 2048)) + (scale 0.1 (build-harmonic 7 2048)) + (scale 0.1 (build-harmonic 6 2048)) + (scale 0.1 (build-harmonic 8 2048)) + (scale 0.1 (build-harmonic 9 2048)))) + (setf *tibetan-table* (list *tibetan-table* (hz-to-step 1) T))) + +(if (not (boundp '*tibetan-table*)) (tibetan-wave)) + +(defun tibetan (frq offset dur rise dec) + (mult (pwl rise 1.0 (- dur dec) 1.0 dur) + (apply #'sim + (mapcar #'(lambda (off) + (osc (hz-to-step (+ frq (* off offset))) dur *tibetan-table*)) + '(0 1 2 3 4 -1 -2 -3 -4))))) + +(defun tibetan-sequence () + (scale 0.1 (vector (sim (at 0.0 (tibetan 110 0.03 35 0.07 21)) + (at 20.0 (tibetan 110 0.04 20 2 4)) + (at 28.0 (tibetan 220 0.04 30 3 6)) + (at 32.1 (tibetan 110 0.03 23 2.3 4.6))) + (sim (at 5.0 (tibetan 55 0.02 20 0.04 12)) + (at 20.0 (tibetan 220 0.05 15 1.5 3)) + (at 32.0 (tibetan 110 0.025 26 2.6 5.2)) + (at 36.0 (tibetan 55 0.01 22 0.04 13)))))) + +(defun tibetan-demo () (play (tibetan-sequence))) + diff --git a/demos/pmorales/b8.lsp b/demos/pmorales/b8.lsp new file mode 100644 index 0000000..f4536a6 --- /dev/null +++ b/demos/pmorales/b8.lsp @@ -0,0 +1,51 @@ +;;; ADDITIVE SYNTHESIS +;;; Risset Drum +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(defun drum-env (amp dur) + (pwev amp dur (* 12e-5 amp))) + +(defun noise-component (amp dur central-frq noise-frq) + (amosc (hz-to-step central-frq) + (mult (drum-env (/ amp 2) dur) + (randi1 noise-frq dur)))) + +(defun fund-component (amp dur frq) + (amosc (hz-to-step frq) + (drum-env (/ amp 2.5) dur))) + +(defun drum-inh-wave () + (setf *drum-inh-table* + (sim (build-harmonic 10 2048) + (scale 1.5 (build-harmonic 16 2048)) + (scale 2.0 (build-harmonic 22 2048)) + (scale 1.5 (build-harmonic 23 2048)))) + (setf *drum-inh-table* (list *drum-inh-table* (hz-to-step 1) T))) + +(if (not (boundp '*drum-inh-table*)) (drum-inh-wave)) + +(defun inh-component (amp dur frq) + (amosc (hz-to-step (/ frq 10)) + (drum-env (/ amp 6.0) dur) + *drum-inh-table*)) + +(defun risset-drum (amp dur frq) + (sim (noise-component amp dur 500 400) + (inh-component amp dur frq) + (fund-component amp dur frq))) + +(defun risset-drum-sequence () + (sim + (at 0.0 (risset-drum 1.0 3.0 100.0)) + (at 0.5 (risset-drum 1.0 1.0 50.0)) + (at 1.0 (risset-drum 1.0 1.0 75.0)) + (at 1.2 (risset-drum 1.0 1.0 200.0)) + (at 1.4 (risset-drum 1.0 3.0 300.0)) + (at 1.8 (risset-drum 1.0 6.0 500.0)))) + +(defun risset-drum-demo () (ss (risset-drum-sequence))) + diff --git a/demos/pmorales/b9.lsp b/demos/pmorales/b9.lsp new file mode 100644 index 0000000..908ffaa --- /dev/null +++ b/demos/pmorales/b9.lsp @@ -0,0 +1,42 @@ +;;; ADDITIVE SYNTHESIS +;;; Risset Endless +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + +(setf *twopi* (* 2 pi)) + +(defun bell-table () + (setf *bell-table* (make-array 512)) + (dotimes (i 512) + (setf (aref *bell-table* i) + (exp (* -4.8283 (- 1 (cos (* *twopi* (- i 255.5) (/ 511.0)))))))) + (setf *bell-table* (snd-from-array 0.0 512 *bell-table*)) + (setf *bell-table* (list *bell-table* (hz-to-step 1.0) T))) + +(if (not (boundp '*bell-table*)) (bell-table)) + +(defun frq-table () + (setf *frq-table* + (list (sim (pwe 1.0 16e-4) (const -1.0 1.0)) (hz-to-step 1.0) T))) + +(if (not (boundp '*frq-table*)) (frq-table)) + +(defun endless-partial () + (mult (osc (hz-to-step 0.025) 40 *bell-table*) + (fmosc (hz-to-step 16000) (scale 16000 + (osc (hz-to-step 0.025) 40 *frq-table*))))) + +(setf *endless-partial* (endless-partial)) + +(defun risset-endless () + (scale 0.25 (apply #'sim (mapcar #'(lambda (x) + (at x (cue *endless-partial*))) + '(0.0 2.0 4.0 6.0 8.0 10.0 12.0 + 14.0 16.0 18.0 20.0))))) + +(defun risset-endless-demo () (ss (risset-endless))) + + diff --git a/demos/pmorales/buzz.lsp b/demos/pmorales/buzz.lsp new file mode 100644 index 0000000..90b8b96 --- /dev/null +++ b/demos/pmorales/buzz.lsp @@ -0,0 +1,88 @@ +;;; BUZZ generator for Nyquist +;;; Pedro J. Morales. Albacete, Spain. Jule, 2001 +;;; pmorales@iele-ab.uclm.es + +; tested on Nyquist IDE 3.0 under Windows + + +; Summation formula taken from F. Richard Moore "Elements of Computer Music" +; section 3.4 page 273 +(defun buzz-aux (harm len) + (let ((frq (/ *sound-srate* len))) + (scale (/ 1.0 harm) + (mult (osc (hz-to-step (* (+ 1 harm) 0.5 frq)) (/ 1.0 frq)) + (osc (hz-to-step (* harm 0.5 frq))(/ 1.0 frq)) + (clip (recip (osc (hz-to-step (* 0.5 frq)) (/ 1.0 frq))) + 10000))))) + +; A table implies a constant spectrum. +; If you need another spectrum try to change the number of harmonics +(defun make-buzz-table (harm &optional (len 2047)) + (list (buzz-aux harm len) + (hz-to-step (/ *sound-srate* len)) + T)) + +; This function calculates de maximun number of harmonics +; without aliasing +(defun num-harm (pitch) + (truncate (/ *sound-srate* 2.0 (step-to-hz pitch)))) + +; Constant frequency buzz oscillator +; Number of harmonics is optional. If it is not +; specified then the waveform is calculated with maximum +; number of harmonics without aliasing +(defun buzz (pitch dur &optional harm) + (unless harm (setf harm (num-harm pitch))) + (osc pitch dur (make-buzz-table harm))) + +; vibrato buzz +(defun vib-buzz (pitch dur &optional harm) + (unless harm (setf harm (num-harm pitch))) + (fmosc pitch (scale 10 (lfo 6 dur)) (make-buzz-table harm))) + +; buzz in fm oscillator form +(defun fmbuzz (pitch modulator harm) + (fmosc pitch modulator (make-buzz-table harm))) + +; filter with three formants intended for vowel synthesis +; (this synthesis algorithm may be improved by means of finer +; control of parameters) + +(defun formants (beh f1 f2 f3) + (sim (reson beh f1 100 2) + (reson beh f2 100 2) + (reson beh f3 100 2))) + +; vowels formants data taken from John R. Pierce "Los sonidos de la Musica" +; (Scientific American, spanish edition) +(defun ah (pitch dur) ; Hawed foneme + (mult (pwl 0.2 1 (- dur 0.4) 1 dur) + (formants (vib-buzz pitch dur) 570 840 2410))) + +(defun eh (pitch dur) ; Head foneme + (mult (pwl 0.2 1 (- dur 0.4) 1 dur) + (formants (vib-buzz pitch dur) 530 1840 2480))) + +(defun eeh (pitch dur) ; Heed foneme + (mult (pwl 0.2 1 (- dur 0.4) 1 dur) + (formants (vib-buzz pitch dur) 270 2290 3010))) + +(defun ooh (pitch dur) ; Who'd foneme + (mult (pwl 0.2 1 (- dur 0.4) 1 dur) + (formants (vib-buzz pitch dur) 300 870 2240))) + +(defun buzz-demo () + (seq (ah c3 1)(eeh c3 1)(ooh c3 1) + (ah c2 1)(eeh c2 1)(ooh c2 1) + (ah c4 1)(eeh c4 1)(ooh c4 1) + (ah d4 1)(eeh d4 1)(ooh d4 1) + (ah g4 1)(eeh g4 1)(ooh g4 1) + (ah c5 1)(eeh c5 1)(ooh c5 1) + (ah c4 1)(eh b3 0.5)(ah c4 0.5) + (eeh e4 1)(eeh d4 1)(ah c4 3))) + +; TEST +(defun buzz-test () (play (buzz-demo))) + +; (buzz-test) + diff --git a/demos/pmorales/c1.lsp b/demos/pmorales/c1.lsp new file mode 100644 index 0000000..68177e8 --- /dev/null +++ b/demos/pmorales/c1.lsp @@ -0,0 +1,32 @@ +;;; ADDITIVE SYNTHESIS +;;; Random Signals +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + + +(defun simple-noise () + (mult (noise 4.0) + (pwl 0.4 1.0 3.6 1.0 4.0))) + +(defun simple-randi (frandi) + (mult (randi1 frandi 4.0) + (pwl 0.4 1.0 3.6 1.0 4.0))) + +(defun tenney (frandi frq dur) + (amosc (hz-to-step frq) + (mult (randi1 frandi dur) (pwl 0.4 1.0 (- dur 0.4) 1.0 dur)))) + + + +;(ss (seq (simple-noise) (simple-randi 200) (simple-randi 400))) + +(defun tenny-sequence () + (seq (tenney 200.0 400.0 4.0) + (tenney 800.0 300.0 2.0) + (tenney 400.0 1600.0 4.0))) + +(defun tenny-demo () (ss (tenny-sequence))) + diff --git a/demos/pmorales/d1.lsp b/demos/pmorales/d1.lsp new file mode 100644 index 0000000..50ab42c --- /dev/null +++ b/demos/pmorales/d1.lsp @@ -0,0 +1,43 @@ +;;; Simple KARPLUS-STRONG +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + + +; NYQUIST code for simple Karplus-Strong algorithm + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + + +(setf ks-class + (send class :new '(cnt total-cnt z-1output output delay-line len total-len))) + +(send ks-class :answer :isnew '(pitch dur) + '((setf len (round (/ *sound-srate* (step-to-hz pitch)))) + (setf total-len (* *sound-srate* dur)) + (setf delay-line (snd-samples (noise (/ (step-to-hz pitch))) len)) + (setf cnt 0) + (setf total-cnt 0) + (setf z-1output 0.0) + (setf output 0.0))) + +(send ks-class :answer :next '() + '((setf output (aref delay-line cnt)) + (setf (aref delay-line cnt) (/ (+ output z-1output) 2.0)) + (setf z-1output output) + (setf cnt (if (= (1- len) cnt) 0 (1+ cnt))) + (setf total-cnt (1+ total-cnt)) + (if (= total-cnt total-len) NIL output))) + +(defun ks (pitch dur) + (let (obj (d (get-duration dur))) + (setf obj (send ks-class :new pitch d)) + (snd-fromobject *rslt* *sound-srate* obj))) + +(defun ks-env (pitch dur) + (mult (pwe dur 0.064) + (ks pitch dur))) + +;(ss (seq (ks a4 1.0) (ks b4 1.0) (ks c5 3.0))) + +(ss (seq (ks-env a3 1.0) (ks-env b3 1.0))) diff --git a/demos/pmorales/e2.lsp b/demos/pmorales/e2.lsp new file mode 100644 index 0000000..48c0dfa --- /dev/null +++ b/demos/pmorales/e2.lsp @@ -0,0 +1,157 @@ +;;; FM +;;; Chowning Dynamic Spectral Evolution +;;; coded by Pedro Jose Morales +;;; pmorales@iele-ab.uclm.es + +;;; WARNING: needs REVERB.LSP + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) +(if (not (fboundp 'reverb)) (load "reverb")) + + +; Chowning BELL ----------------------------------------------------- +(defun exp-env (amp dur) + (scale amp (pwe dur 64e-4))) + +(defun fm-bell (frq cm-ratio imax dur amp) + (mult (exp-env amp dur) + (fmosc (hz-to-step frq) + (mult (exp-env (* imax (/ frq cm-ratio)) dur) + (osc (hz-to-step (/ frq cm-ratio)) dur))))) + +; Chowning WOOD-DRUM ------------------------------------------------ +(defun wood-env (amp dur) + (scale amp (pwev 0.8 (* dur 0.2) 1.0 (* dur 0.25) 1.0 dur 64e-4))) + +(defun wood-mod-env (amp dur) + (scale amp (pwlv 1.0 (* 0.2 dur) 0.0 dur))) + +(defun fm-wood-drum (frq cm-ratio imax dur amp) + (mult (wood-env amp dur) + (fmosc (hz-to-step frq) + (mult (wood-mod-env (* imax (/ frq cm-ratio)) dur) + (osc (hz-to-step (/ frq cm-ratio)) dur))))) + +; Chowning BRASS ---------------------------------------------------- +(defun brass-env (amp dur) + (scale amp (pwl 0.1 1.0 0.2 0.8 (- dur 0.1) 0.7 dur))) + +(defun fm-brass (pitch cm-ratio imax dur amp) + (let ((frq (step-to-hz pitch))) + (mult (brass-env amp dur) + (fmosc pitch + (mult (brass-env (* imax (/ frq cm-ratio)) dur) + (osc (hz-to-step (/ frq cm-ratio)) dur)))))) + +; Chowning CLARINET ------------------------------------------------- +(defun clar-env (amp dur) + (scale amp (pwev 64e-4 0.1 1.0 (- dur 0.1) 1.0 dur 64e-4))) + +(defun clar-mod-env (vmax vmin dur) + (pwev vmax (* dur 0.3) vmin dur vmin)) + +(defun fm-clar (pitch cm-ratio imax imin dur amp) + (let ((frq (step-to-hz pitch))) + (mult (clar-env amp dur) + (fmosc pitch + (mult (scale (/ frq cm-ratio) (clar-mod-env imax imin dur)) + (osc (hz-to-step (/ frq cm-ratio)) dur)))))) + +; Chowning VARIABLE FM INSTRUMENT ----------------------------------- +; este instrumento hay que mejorarlo + +(defun variable-fm-env (amp break mid dur) + (scale amp (pwev (* mid 64e-4) break mid dur (* mid 64e-4)))) + +(defun variable-mod-osc (index frq kdyn mid break dur) + (amosc (hz-to-step frq) + (scale (* index frq) (pwlv kdyn break mid dur)))) + +(defun variable-fm-inst (amp break mid dur kdyn index frq cm-ratio) + (mult (variable-fm-env amp break mid dur) + (fmosc (hz-to-step frq) + (variable-mod-osc index (/ frq cm-ratio) kdyn mid break dur)))) + + +(defun variable-fm-rev-st (amp break mid dur kdyn index frq cm-ratio coefrev) + (let ((snd (variable-fm-inst amp break mid dur kdyn index frq cm-ratio))) + (sim (cue snd) (scale coefrev (reverb snd dur))))) + +;(ss (seq (fm-bell 100.0 (/ 5.0 7.0) 10 10 1.0) +; (fm-bell 150.0 (/ 5.0 7.0) 7 10 1.0) +; (fm-bell 200.0 (/ 5.0 7.0) 15 7 1.0))) + +(defun fm-w-d (pitch) + (fm-wood-drum (step-to-hz pitch) (/ 16.0 11.0) 25 0.2 1.0)) + +;(ss (seq (fm-w-d a2) (fm-w-d b2) (fm-w-d c3) (fm-w-d d3) (fm-w-d e3) +; (fm-w-d f3) (fm-w-d g3) (fm-w-d a3) +; (fm-w-d a1) (fm-w-d b1) (fm-w-d c2) (fm-w-d d2) (fm-w-d e2) +; (fm-w-d f2) (fm-w-d g2) (fm-w-d a2))) + +(defun fm-br (pitch) + (fm-brass pitch 1.0 5 0.6 1.0)) + +;(ss (seq (fm-br c4) (fm-br d4) (fm-br e4) (fm-br f4) (fm-br g4) +; (fm-br a4) (fm-br b4) (fm-br c5))) + +(defun fm-c (pitch) + (fm-clar pitch (/ 3.0 2.0) 5 2 0.5 1.0)) + +;(ss (seq (fm-c c5) (fm-c d5) (fm-c e5) (fm-c f5) (fm-c g5) +; (fm-c a5) (fm-c b5) (fm-c c6))) + +(defun v-fm (pitch break mid dur rev) + (variable-fm-rev-st 1.0 break mid dur 0.8 20.0 (step-to-hz pitch) (/ 7.0 5.0) rev)) + +;(ss (sim (at 0.0 (v-fm a4 0.7 0.2 3.0 0.5)) +; (at 1.5 (v-fm e6 0.2 0.3 3.0 0.4)) +; (at 3.0 (v-fm d5 2.0 0.6 4.0 0.4)) +; (at 6.0 (v-fm d6 0.01 0.7 3.0 0.5)))) + +; Double Carrier Brass ---------------------------------------------- + +(defun dc-env (dur) + (pwl (* dur 0.1) 1.0 (* dur 0.2) 0.8 (* dur 0.9) 0.7 dur)) + +(defun dc-modulator (frq dur imax imin) + (amosc (hz-to-step frq) + (sim (scale (* frq (- imax imin)) (dc-env dur)) + (const (* frq imin) dur)))) + +(defun dc-fm1 (frq1 dur amp modulator) + (scale amp + (mult (dc-env dur) + (fmosc (hz-to-step frq1) modulator)))) + +(defun dc-fm2 (frq1 dur cm-ratio index-ratio amp amp-ratio modulator) + (scale (* amp amp-ratio) + (mult (dc-env dur) + (fmosc (hz-to-step (/ frq1 cm-ratio)) + (scale index-ratio modulator))))) + +(defun double-carrier (dur frq cm-ratio amp amp-ratio imax imin index-ratio) + (let ((modulator (dc-modulator (/ frq cm-ratio) dur imax imin))) + (sim (dc-fm1 frq dur amp modulator) + (dc-fm2 frq dur cm-ratio index-ratio amp amp-ratio modulator)))) + +;(ss (double-carrier 0.6 440.0 1.0 1.0 0.5 3 1 (/ 3.0 1.5))) + +; Double Carrier Trumpet -------------------------------------------- + +(defun port-env (dur) + (pwlv -1.0 (* 0.25 dur) 0.1 (* 0.5 dur) 0.0 dur)) + + +(defun chowning-fm-demo () + (ss (seq (fm-bell 100.0 (/ 5.0 7.0) 10 10 1.0) + (fm-bell 150.0 (/ 5.0 7.0) 7 10 1.0) + (fm-bell 200.0 (/ 5.0 7.0) 15 7 1.0) + (fm-w-d a2) (fm-w-d b2) (fm-w-d c3) (fm-w-d d3) (fm-w-d e3) + (fm-w-d f3) (fm-w-d g3) (fm-w-d a3) + (fm-w-d a1) (fm-w-d b1) (fm-w-d c2) (fm-w-d d2) (fm-w-d e2) + (fm-w-d f2) (fm-w-d g2) (fm-w-d a2) + (fm-br c4) (fm-br d4) (fm-br e4) (fm-br f4) (fm-br g4) + (fm-br a4) (fm-br b4) (fm-br c5) + (double-carrier 0.6 440.0 1.0 1.0 0.5 3 1 (/ 3.0 1.5))))) diff --git a/demos/pmorales/ks.lsp b/demos/pmorales/ks.lsp new file mode 100644 index 0000000..8000f32 --- /dev/null +++ b/demos/pmorales/ks.lsp @@ -0,0 +1,33 @@ +;;; DSP in Nyquist +;;; Karplus-Strong Algorithm +;;; Coded by Pedro J. Morales. +;;; e-mail: pmorales@iele-ab.uclm.es + +(load "pjmg.lsp") + +(setf ks-class (send class :new + '(cnt total-cnt last-output current-output string len total-len))) + +(send ks-class :answer :isnew '(pitch dur) + '((setf len (round (/ *sound-srate* (step-to-hz pitch)))) + (setf total-len (* *sound-srate* dur)) + (setf string (snd-samples (noise (/ (step-to-hz pitch))) len)) + (setf cnt 0) + (setf total-cnt 0) + (setf last-output 0.0) + (setf current-output 0.0))) + +(send ks-class :answer :next '() + '((setf current-output (aref string cnt)) + (setf (aref string cnt) (/ (+ current-output last-output) 2.0)) + (setf last-output current-output) + (setf cnt (if (= (1- len) cnt) 0 (1+ cnt))) + (setf total-cnt (1+ total-cnt)) + (if (= total-cnt total-len) NIL current-output))) + +(defun ks (pitch dur) + (let (obj) + (setf obj (send ks-class :new pitch dur)) + (snd-fromobject 0.0 *sound-srate* obj))) + +(ss (seq (ks e2 2)(ks a2 2)(ks d3 2)(ks g3 2)(ks b3 2)(ks e4 2))) diff --git a/demos/pmorales/partial.lsp b/demos/pmorales/partial.lsp new file mode 100644 index 0000000..8619f8c --- /dev/null +++ b/demos/pmorales/partial.lsp @@ -0,0 +1,30 @@ +;;; PARTIAL + +(setf *pmorales-path* (current-path)) +(load (strcat *pmorales-path* "pjmg.lsp")) + + +(defun klin (fr coef) + (mult (sine (hz-to-step (* 300.0 fr coef)) 2.0) (pwev 3.0 3.0 1e-2))) + +(defun klines (coef) + (sim (at 0.0 (klin 6.0 coef)) + (at 0.3 (klin 7.0 coef)) + (at 0.5 (klin 5.5 coef)) + (at 0.7 (klin 6.5 coef)))) + +(defun bell-sequence () + (sim (mult (sine (hz-to-step (* 300.0 (/ 3.14 5))) 6.0) (scale 4.0 (pwe 6.0 1e-2))) + (mult (sine (hz-to-step 300.0) 6.0) (pwl 2.0 0.75 3.0 1.0 4.0 0.75 5.0 0.2 6.0)) + (mult (sine (hz-to-step (* 300.0 1.57)) 6.0) (pwl 3.0 0.75 4.0 0.5 5.0)) + (mult (sine (hz-to-step (* 300.0 3.14)) 6.0) (pwl 2.5 0.5 4.0)) + (at 0.5 (scale 2.0 (mult (sine (hz-to-step (* 300.0 6.3)) 6.0) (pwe 3.0 5e-3)))) + (at 2.0 (scale 2.0 (mult (sine (hz-to-step (* 300.0 9.12)) 6.0) (pwe 3.0 1e-2)))) + (at 0.7 (scale 2.0 (mult (sine (hz-to-step (* 300.0 15.7)) 6.0) (pwe 4.0 2e-2)))) + (at 3.0 (klines 1.0)) + (at 4.0 (klines 1.5)) + (at 1.0 (mult (sine (hz-to-step (+ (* 300.0 6.3) 20.0)) 6.0) + (scale 5e-3 (pwe 2.0 1000.0 4.0)))) +)) + +(defun bell-demo () (ss (scale 0.1 (bell-sequence)))) diff --git a/demos/pmorales/phm.lsp b/demos/pmorales/phm.lsp new file mode 100644 index 0000000..bd206d0 --- /dev/null +++ b/demos/pmorales/phm.lsp @@ -0,0 +1,79 @@ +;;; DSP in Nyquist +;;; Flute Physical Modelling +;;; Based on Nicky Hind CLM Tutorial +;;; (Based on Perry Cook Flute Physical Modelling) +;;; Coded by Pedro J. Morales +;;; e-mail: pmorales @iele-ab.uclm.es + +(load "pjmg.lsp") + +;; DELAY LINE + +(setf dl-class (send class :new '(cnt line len output))) + +(send dl-class :answer :isnew '(init-len) + '((setf cnt 0) + (setf len init-len) + (setf line (make-array len)) + (dotimes (i len) (setf (aref line i) 0.0)))) + +(send dl-class :answer :next '(val) + '((setf output (aref line cnt)) + (setf (aref line cnt) val) + (setf cnt (if (= cnt (1- len)) 0 (1+ cnt))) + output)) + +(defun make-delay-line (len) + (send dl-class :new len)) + +(defun delay-line (dl-obj val) + (send dl-obj :next val)) + +; UNA EXCITACION + +(defun flute-exc (noise-lev vib-amount vib-rate atk dec dur) + (let ((current-flow (sim (pwl atk 0.55 (- dur dec) 0.55 dur) ;puede variar 0.5 .. 0.8 + (scale vib-amount (lfo vib-rate dur))))) + (sim current-flow + (scale noise-lev (mult current-flow (lp (noise dur) (/ *sound-srate* 2.0))))))) + +;; FLUTE PHYSICAL MODELLING +(setf flute-class (send class :new '(sum1 sum1-output freq dur bore-delay emb-delay + period-samples out-sig last-sig current-bore))) + +(defun cubic-polynomial (x) (- x (expt x 3.0))) + +(send flute-class :answer :isnew '(exc emb-size ifreq idur) + '((setf sum1 exc) + (setf freq (step-to-hz ifreq)) + (setf period-samples (round (/ *sound-srate* freq))) + (setf bore-delay (make-delay-line period-samples)) + (setf emb-delay (make-delay-line (round (* emb-size period-samples)))) + (setf last-sig 0.0))) + +(send flute-class :answer :next '() + '((setf sum1-output (snd-fetch sum1)) + (when sum1-output + (progn + (setf current-bore (delay-line bore-delay last-sig)) + (setf out-sig + (+ (* 0.7 (+ (* 0.55 current-bore) + (cubic-polynomial (delay-line emb-delay (+ sum1-output + (* 0.5 current-bore)))))) + (* 0.3 last-sig))) + (setf last-sig out-sig))))) + + +(defun flute (freq dur &key (noise-lev 0.0356) (atk 0.05) (dec 0.1) (emb-size 0.5) + (vib-amount 0.015) (vib-rate 5)) + (let (obj) + (setf obj (send flute-class :new + (flute-exc noise-lev vib-amount vib-rate atk dec dur) emb-size freq dur)) + (hp (snd-fromobject 0.0 *sound-srate* obj) 20.0))) + +(ss (seq (flute a4 0.5 :dec 0.01) + (flute b4 0.5 :dec 0.01) + (flute c5 0.5 :dec 0.01) + (flute gs4 1.0))) + + diff --git a/demos/pmorales/pjmg.lsp b/demos/pmorales/pjmg.lsp new file mode 100644 index 0000000..b949dd6 --- /dev/null +++ b/demos/pmorales/pjmg.lsp @@ -0,0 +1,40 @@ +;;; PJMG.LSP +;;; Rutinas para Nyquist + +; Some utilities and functions not defined in +; the released version of Nyquist + + +(defun set-current-file (cf) + (setf *CURRENT-FILE* cf)) + +(defun l () (load *CURRENT-FILE*)) + +;; A comment by Dannenberg on the following function: +;; This function takes an expression for a sound and +;; finds its peak value. This forces a computation of all +;; samples, which are saved in memory (4 bytes per sample). +;; The samples are then normalized and written to a file. +;; This should be fine for short examples, but is not +;; recommended for general use because you may run out +;; of memory. See the manual for more notes on normalization. +;; +(defun ss (m) + (let ((m-max (peak m NY:ALL))) + (s-save (scale (/ 1.0 m-max) m) NY:ALL *default-sound-file* + :play *soundenable*))) + +(defun randi1 (fr dur) + (let ((d (get-duration dur))) + (snd-white *rslt* fr d))) + +(defun randi2 (fr dur) + (at 0.0 (snd-white 0.0 fr dur))) + +(defun randh1 (fr dur) + (let ((d (get-duration dur))) + (snd-compose (noise d) (quantize (ramp d) (round (* fr d)))))) + +(defun rndh2 (fr dur) + (at 0.0 (snd-compose (noise dur) + (quantize (ramp dur) (round (* fr dur)))))) diff --git a/demos/pmorales/readme.txt b/demos/pmorales/readme.txt new file mode 100644 index 0000000..fc662f0 --- /dev/null +++ b/demos/pmorales/readme.txt @@ -0,0 +1,27 @@ +Here there are a few sounds for Nyquist that +I have coded for learning. Mostly are based +on examples from Amsterdam Catalogue of +CSound Computer Instruments,and some others +are based on Computer Music Journal +articles, Dodge & Jerse and F. R. Moore +books. + +Karplus-Strong and Physical Modelling are +implemented in Lisp. + +Albacete, Spain, 2 June 2.000 + +Pedro J. Morales. +pmorales@iele-ab.uclm.es + +---------------------------------------- + +Please see examples_home.htm in the parent +folder for an index to these files. + +Note that there are "helper" functions in +pjmg.lsp that you may need to load before +you run the code in these other files. + +Roger B. Dannenberg +rbd@cs.cmu.edu diff --git a/demos/probability_distributions.htm b/demos/probability_distributions.htm new file mode 100644 index 0000000..6ba06c7 --- /dev/null +++ b/demos/probability_distributions.htm @@ -0,0 +1,137 @@ + + + + Probability Distributions + + +

Probability Distribution Generators

+

+ +

Andreas Pfenning and Roger B. Dannenberg

+ +

This page describes some uses of probability distribution +functions that are defined in lib/distributions.lsp, so +be sure to (load "distributions") before trying these +examples. See the manual for more details. + +

A probability distribution generator outputs a single +number based the particular distribution and the input parameters. These +functions were created to supplement the uniform random generator (real-random). +There are two types of distributions: continuous +and discrete. For either distribution, +looking at the diagrams will show you the likely range of outputs. In +a continuous distribution, the likelihood of returning a value between +two points on the x-axis is equal to the area under the curve between those +two points. Every continuous distribution +has the property that the total area under the curve = 1. In +a discrete distribution, only integers >= 0 are allowed as output. Each +one of these numbers has a probability of being returned which is equal +to the height of the bar in the diagram. For +the user's convenience, many distributions have optional bounds that come +in useful for certain applications. + +

Example 1 – Varying time with a continuous +distribution generator

+ +

One of the most common distributions found in algorithmic +composition is known as the Poisson process. This +consists of a sequence of notes or events separated by an amount +of time determined by an exponential distribution. The resulting +sequence of events has the following property: every +point in time is equally likely to be that start of a note. Another +property is that, the probability of an event happening in the next +unit of time is completely independent of how long it has been since +the previous event. These distributions are naturally occuring when +events happen randomly without any coordination. + +

The following +is just one example how to use the exponential distribution. The +first input parameter, .25, spreads the distribution out so that higher +values are more likely. The second +input is optional and is an upper bound on the output. + +

(play (seqrep (i 20)
+        (pluck c4 (* 0.5 (exponential-dist .25 2.0)))))
+
+ +

Example 2 – Varying pitch with a discrete distribution +generator

+ +

Discrete distribution generators are useful for changing +pitch (to integer values). Constraining the output to +a whole number means that every pitch is going to be in the chromatic scale. In +the case of the binomial distribution, both parameters together determine +the mean. One way to get feel for +how the different parameters affect the distribution is to print values +as you generate them. Distribution +parameters may require some tweaking to produce a desired affect. In +some cases, altering the parameters can yield unexpected and interesting +sounds. + +

(defun try-binomial ()
+  (play (seqrep (i 20)
+          (pluck (+ (binomial-dist 6 .5) c4) 0.1))))
+
+ + +

Example 3 – Using granular synthesis with pitch +distribution

+ +

In granular synthesis, interesting sounds can be made +by having a pitch vary according to some distribution other than +the simple uniform distribution. In lib/dist-test.lsp, +there is a a granular synthesis function that can take in any distribution +(within the bounds of granular synthesis) and vary the pitch of the tone +based on that distribution. To do +this, you pass in a parameterless function as a parameter. Since most +distribution functions take parameters, it is necessary to create +a continuation as shown below using a lambda expression. + +

(defun make-gamma (nu high)
+  (lambda () (gamma-dist nu high)))
+
+ +

Here, make-gamma takes two parameters and returns a +function with no parameters. This no-parameter function +remembers the values of nu and high and +will call gamma-dist with these. For example, try +

(apply (make-gamma 2 5.0) nil)
+(The apply function applies a function to a list of +arguments; in this case the list is nil, so there are no arguments.) +This example just makes the function and uses it once, so there's +not much point, but in the granular synthesis example, the +function will be called many times. Unlike passing a number as +a parameter, passing a function means that the granular synthesis +function can call the function for every grain, resulting in a +new value for each grain. (Be sure to load dist-test.lsp +before running this example.) + +
(defun try-pitch-dist ()
+  (play (stretch 4 
+          (simrep (i 4)
+            (pitch-dist-granulate "demos/demo-snd.aiff" 0.04 0.0 0.02 0.001
+                                  (make-gamma 2 5.0) 0 0)))))
+
+ +

Example 4 – Using granular synthesis with grain +length distribution

+ +

The length of grains can also be made to vary by a +distribution passed in as a continuation. Here +is an example. +

+(defun make-gauss (xmu sigma low high)
+  (lambda ()(gaussian-dist xmu sigma low high)))
+
+(defun try-len-dist ()
+  (play (stretch 4
+          (simrep (i 2)
+	    (len-dist-granulate "demos/demo-snd.aiff"
+	      (make-gauss 0.0 1.0 0.1 .5) 0.02 0.001 2.0 0 0)))))
+
+ +

A Challenge

+Can you come up with a set of examples that clearly illustrates different distributions through sound? (I would love to add more examples here. -RBD) + + + diff --git a/demos/rhythm_tutorial.htm b/demos/rhythm_tutorial.htm new file mode 100644 index 0000000..d6c6313 --- /dev/null +++ b/demos/rhythm_tutorial.htm @@ -0,0 +1,2 @@ + + Rhythmic Pattern Tutorial

Rhythmic Pattern Tutorial

This example illustrates a very simple percussion sound created with noise and using the sound to generate a rhythm.

The sound is created by filtering noise. The filter is controlled using the piece-wise linear function (pwl):

(defun pulse (dur)
  (stretch dur (hp (noise) (pwl 0 15 0.2 6000 0.6 15000 0.75 7))))

A sequence of sounds is constructed and repeated in the following code. Notice that each time through the pattern,
the scale factor is increased by 0.1, giving the whole sequence a crescendo:

(defun pulsepat (&optional (rep 16)) 
  (seqrep (i rep)
    (stretch 0.2
      (scale (* i 0.1)
        (seq (pulse 1) (pulse 1) (pulse 2) (pulse 2))))))

(play (pulsepat 17))

Pitched Patterns

This example uses the ring function from the Vinal Scratch Tutorial. When the pitch parameter is increased, we hear a kind of electronic bass sound. Try this:

(play (ring 0.4 30 1.2))

These notes can be combined to create a pattern. The techno function creates a short pattern of 3 notes repeated any number of times:

(defun techno (rep)
  (seqrep (i rep) 
    (scale 0.8
      (sim
	(scale 0.8 (at 0.0 (ring 0.4 30 1.2)))
	(scale 0.6 (at 0.2 (ring 0.2 30 0.9)))
	(scale 0.7 (at 0.3 (ring 0.1 30 1.1))) ))))

Try this:

(play (techno 3))

The following combines and transposes rhythmic segments to create a bass line:

(play (seqrep (i 2)
        (seq (techno 2)
             (transpose 5 (techno 2))
             (transpose -2 (techno 1))
             (transpose 3 (techno 1))
             (techno 2))))

Layers for Richer Texture

Sounds can often be combined with time and pitch offsets to create richer textures. The following layers two sequences based on the same techno function:

(play (sim
        (scale 0.4
          (at 0.0
            (seqrep (i 2)
              (seq (techno 2)
                   (transpose 5 (techno 2))
                   (transpose -2 (techno 1))
                   (transpose 3 (techno 1))
                   (techno 2)))))
	(scale 0.2
          (at 0.1
            (seqrep (i 2)
              (seq (transpose 2 (techno 2))
                   (transpose 7 (techno 2))
                   (transpose -4 (techno 1))
                   (transpose 5 (techno 1))
                   (transpose -2 (techno 2)))) ))))

Note that the second layer is almost but not exactly a transposition of the first layer. If it were an exact transposition, it would make sense to encapsulate the first layer in a function and call it twice. The following variation is much more concise, but it does not compute exactly the same sound:

(defun bass-line ()
  (seqrep (i 2)
    (seq (techno 2)
         (transpose 5 (techno 2))
         (transpose -2 (techno 1))
         (transpose 3 (techno 1))
         (techno 2))))
(play (sim (scale 0.4 (bass-line))
           (scale 0.2 
             (at 0.1 (transpose 2 (bass-line))))))

Another Example

This example also uses the ring function from the Vinal Scratch Tutorial.

(play (seqrep (i 17) 
        (lp (scale (+ (* i 0.05 ) 0.3) 
              (seq (transpose -4 (ring 0.1 32 0.6)) 
                   (transpose -5 (ring 0.05 20 0.2)) 
                   (transpose (* 2 i) (ring 0.1 27 0.5)) 
                   (transpose -3 (ring 0.05 22 0.1)) 
                   (transpose (* i 3) (ring 0.1 28 0.4)) 
                   (ring 0.05 31 0.7)))
            (* 100 i))))

This play 17 repetitions of a sound. Each time, the sound is a bit louder, the low-pass frequency is raised by 100 Hz, and two of the transpositions are increased. This creates a rhythmic and evolving sound.


 

diff --git a/demos/scratch_tutorial.htm b/demos/scratch_tutorial.htm new file mode 100644 index 0000000..c26c22e --- /dev/null +++ b/demos/scratch_tutorial.htm @@ -0,0 +1,93 @@ + + + + +Vinal Scratch Tutorial + + + + + +

Vinal Scratch Tutorial

+ +

This sound reminds me of the effect of dragging a needle across a vinal record.

+ +
(defun ring (dur pch scl)
+  (let ((modstep1 (hz-to-step (* (step-to-hz pch) (sqrt 2.0))))
+        (modstep2 (hz-to-step (* (step-to-hz pch) (sqrt 11.0)))))
+    (stretch dur 
+      (mult 
+        (env 0.05 0.1 0.2 1 0.6 0.24 1)
+        (fmosc pch (mult 
+	             (pwl 0.07 1800 0.15 1000 0.4 680 0.8 240 1 100 1) 
+		     scl 
+                     (osc modstep1)
+                     (osc modstep2) ))) )))
+ +

The following plays an example sound from this function:

+ +
(play (ring 7.1 (hz-to-step 1) 1.2))
+ +

Here is a brief description of how this function works: The sound is created by an FM +oscillator. The modulation comes from two sinusoids operating at low frequencies +multiplied together. The sinusoids are not harmonically related, so an irregular pulse is +generated by their product. This is scaled further by a piece-wise linear envelope that +adds more variation. To make the sinusoids inharmonically related, their frequencies are +scaled by the square root of 2 and the square root of 11. The variables modstep1 +and modstep2 are initialized to these computed frequencies.

+ +

The following example combines several instances of ring with different +parameters:

+ +
(play (sim (scale 0.15 (at 2.9 (ring 7.1 (hz-to-step 1) 1.2)))
+	   (scale 0.175 (at 4.9 (ring 5.1 (hz-to-step 2) 1.414)))
+	   (scale 0.2 (at 6.9 (ring 3.1 (hz-to-step 4) 1.8)))))
+
+ +

Other Sounds Using Ring

+ +

The same ring function can be used to achieve other sounds. Listen to +these examples:

+ +
(play (sim 
+        (scale 0.35 (at 1.5 (ring 4 1 1)))
+	(scale 0.325 (at 4 (ring 4 4 2)))
+	(scale 0.3 (at 7.5 (ring 4 10 4))) ))
+ +

These instances use a higher pitch parameter than the previous ones.
+

+ +

Another Related Sound

+ +

The following creates a sound using FM and a wave table derived from a vocal sound.

+ +
(defun vocrap (&optional (pch 16) (dur 1))
+  (if (not (boundp '*voc-table1*)) (mk-voc1-table))
+  (fmosc pch (stretch dur (pwl 0 3 0.1 -20 0.2 20 0.3 30
+                               0.4 -10 0.5 15 0.6 0
+                               0.8 -30 1 60 1)) *voc-table1*))
+ +

This function uses a special test to make sure that *voc-table1* is +initialized. If it is not, it would be an error to read or test it, but you can query to +find out if the variable is bound or unbound. (Global variables become bound when you +assign a value to them.) The boundp function takes an atom (note the use of +the single quote to denote an atom, the name of the variable, rather then the variable's +value) and returns true if the variable is bound.

+ +

Here is the definition for mk-voc1-table. You might have to replace the +filename depending upon how your system is configured.:

+ +
(defun mk-voc1-table ()
+    (if (not (boundp 'voc-snd1))
+        (setf voc-snd1 (s-read "./test/voc1.snd")))
+    (setf *voc-table1* (list voc-snd1 16 T)))
+ +

The following shows one way to invoke vocrap:

+ +
(play (seqrep (i 4) (vocrap)))
+ +
+
+ + + diff --git a/demos/sdl/ej2.lsp b/demos/sdl/ej2.lsp new file mode 100755 index 0000000..630a41f --- /dev/null +++ b/demos/sdl/ej2.lsp @@ -0,0 +1,66 @@ +;; SDL. ejemplo +;; BWV 1069 +;; pmorales. Junio, 2007 + + +(setf *autonorm-type* 'previous) + +(load "sdl") + +(defun analog-saw (pitch dur atk rel det reson-freq) + (let ((hz (step-to-hz pitch))) + (reson + (mult 0.5 + (sum -0.1 (pwev 0.1 atk 1 dur 0.8 (+ dur rel) 0.1)) + (sum (stretch (+ dur rel) (osc-saw hz)) + (stretch (+ dur rel) (osc-saw (+ hz det))))) + (sum (* 3 hz) (mult (* 8 hz) (sum -0.1 (pwev 1.1 (+ dur rel) 0.1)))) + reson-freq 1))) + +(defun sint1 (&key pitch (idur 1) (din 1) (reson 1000)) + (scale din (analog-saw pitch idur 0.002 .3 3 reson))) + +(setf voz-1 + '((TF 1) + (INIT-INSTR "i1" sint1) (INSTRUMENT "i1") (ATTR :mm 100) + (ATTR :idur 0.1)(PWL-POINT :reson 1000) + 2 (:c4 1) :d4 (:e4 2) :c4 :g4 :e4 :a4 (:g4 1) :f4 + (ATTR :idur 0.5)(:g4 4)(ATTR :idur 0.15) + (:a4 1) :c5 :f4 :a4 :g4 :f4 :e4 :g4 :f4 :a4 :d4 :f4 :e4 :d4 :c4 :d4 :e4 :f4 (:g4 2) + :a3 :c4 :d4 :f4 + :g3 :b3 :c4 :e4 (:f3 1) :e4 :d4 :c4 :g3 :d4 :c4 :b3 + (ATTR :idur 0.5) (LABEL :t1)(:c4 4) 2 + (PWL-POINT :reson 2000) + (ATTR :idur 0.1) (:g3 1) :f3 :e3 :f3 :d3 :e3 (:c3 2) (:c4 3) + (:b3 1) :a3 :b3 (:c4 2) :a4 :b3 :g4 :a3 :f#4 + (:g3 1) :c4 :b3 :a3 :g3 :f3 :e3 :d3 :c3 :b3 :a3 :g3 :f#3 :e3 :d3 :c3 :b2 :a3 :g3 :f#3 + :e3 :d3 :c3 :b2 :a2 :g3 :f#3 :e3 :d3 :c3 :b2 :a2 :g2 :g3 :b3 :d4 + (ATTR :idur 0.5) (:e4 4) 1 + (ATTR :idur 0.2)(:f3 1) :a3 :c4 (ATTR :idur 2)(:d4 4) + (PWL-POINT :reson 4000) +)) + +(setf voz-2 + '((TF 1) + (INIT-INSTR "i1" sint1) (INSTRUMENT "i1") (ATTR :mm 100) + (ATTR :idur 0.15) (PWL-POINT :reson 1000) + (AT-LABEL :t1)2 (:g4 1) :a4 (:b4 2) :g4 + :c5 :b4 :e5 (:d5 1) :c5 + (ATTR :idur 2)(:d5 4) + (PWL-POINT :reson 1000) + (ATTR :idur 0.1) (:e5 1) :g5 :c5 :e5 :d5 :c5 :b4 :d5 :c5 :e5 :a4 :c5 + :b4 :a4 :g4 :a4 :b4 :c5 (:d5 2) :e4 :g4 :a4 :c5 :d4 :f#4 :g4 :b4 + (:c4 1) :b4 :a4 :g4 :d4 :a4 :g4 :f#4 (:g4 4) + 1 (:c5 1) :e5 :g5 + (ATTR :idur 1)(:a5 5) + (PWL-POINT :reson 4000) + (ATTR :idur 0.8)(:b4 1) :d5 :f5 + (ATTR :idur 1)(:g5 5))) + +(setf *my-time-labels* (sdl->timelabels voz-1)) + +(defun vox-1 () (timed-seq (sdl:normalize-score-duration (sdl->score voz-1)))) +(defun vox-2 () (timed-seq (sdl:normalize-score-duration (sdl->score voz-2 *my-time-labels*)))) + +(play (sim (vox-1) (vox-2))) +I diff --git a/demos/sdl/inv-08.lsp b/demos/sdl/inv-08.lsp new file mode 100644 index 0000000..f702d2d --- /dev/null +++ b/demos/sdl/inv-08.lsp @@ -0,0 +1,180 @@ +; ********************************************* +; Inventio # 8 a 2 voci BWV 779. J. S. Bach. +; Score Description Library example +; Translated from a previous lambda Music score +; by Pedro J. Morales. +; Junio, 2005 +; Revised: July 25 2007 +; Nyquist 2.37 +; ********************************************* + +(load "sdl") + +(setf *autonorm-type* 'previous) + + +(defun analog-saw (pitch dur atk rel det reson-freq) + (let ((hz (step-to-hz pitch))) + (set-logical-stop + (reson + (mult 0.5 + (sum -0.1 (pwev 0.1 atk 1 dur 0.8 (+ dur rel) 0.1)) + (sum (stretch (+ dur rel) (osc-saw hz)) + ; (scale 0.5 (stretch (+ dur rel) (osc-saw (* 2 hz)))) + (stretch (+ dur rel) (osc-saw (+ hz det))))) + (sum (* 3 hz) (mult (* 8 hz) (sum -0.1 (pwev 1.1 (+ dur rel) 0.1)))) + reson-freq 1) + dur))) + + +(defun xan2 (&key pitch) + (analog-saw pitch 0.001 0.02 2.0 2 4000)) + +(defun xan3 (&key pitch (rel 2.5) (atk 0.02)(reson 4000)(din 1)) + (scale din (analog-saw pitch 0.001 atk rel 3 reson))) + + +; SCORE -------------------------------------------------------------------- + +(setf voz-1 + '((ATTR :mm 120.0) ; 140? + (INIT-INSTR "i1" xan3) (INSTRUMENT "i1") + (PWL-POINT :rel 1.5)(ATTR :atk 0.005) + (DELTA 2) (f4 2) a4 f4 c5 f4 +(PWL-POINT :rel 2.5) +f5 (e5 1) d5 c5 d5 c5 :bb4 a4 :bb4 a4 g4 (f4 2) + a4 c5 a4 f5 c5 +; linea 2 + (PWL-POINT :rel 1.0) + (a5 1) c6 :bb5 c6 a5 c6 :bb5 c6 a5 c6 :bb5 c6 + :f5 :a5 :g5 :a5 :f5 :a5 :g5 :a5 :f5 :a5 :g5 :a5 + :d5 :f5 :e5 :f5 :d5 :f5 :e5 :f5 :d5 :f5 :e5 :f5 +; linea 3 + (PWL-POINT :rel 3.0) + (MRK n5) + (:b4 2) :g4 :d5 :b4 :f5 :d5 + (MRK n6) + (:g5 1) :a5 :g5 :f5 :e5 :f5 :e5 :d5 :c5 :d5 :c5 :bb4 + (:a4 2) + (MRK n7) + (:d5 1) :c5 :b4 :c5 :b4 :a4 :g4 :a4 :g4 :f4 +; linea 4 + :e4 :f4 :e4 :d4 (MRK n8)(:c4 2) + (:c5 1) :b4 (:c5 2) + (PWL-POINT :rel 4) + :e4 (PWL-POINT :rel 2) :f4 :c5 :e4 :c5 :d4 :b4 (MRK n9) + (PWL-POINT :rel 1.5)(:c5 4) 4 (MRK n10) 4 +; linea 5 + 2 (:c5 2) :e5 :c5 :g5 :c5 :c6 (:b5 1) :a5 :g5 :a5 :g5 :f5 :e5 :f5 :e5 + (MRK n11) :d5 :c5 :bb4 :c5 :a5 + :c5 :a5 :bb4 :a5 :c5 :a5 :a4 :a5 +; linea 6 + (PWL-POINT :rel 2.5) + (:bb4 2)(PWL-POINT :rel 2) :g4 :bb4 :g4 :d5 :g4 :g5 (:f5 1) :eb5 :d5 :eb5 :d5 :c5 :bb4 :c5 :bb4 :a4 (:g4 2) :bb4 :d5 :bb4 :g5 :d5 +; linea 7 + (PWL-POINT :rel 3) + :bb5 :c#5 :bb5 :c#5 :bb5 :c#5 + (MRK n12) + :d5 :a4 :f5 :d5 :a5 :f5 + (MRK n12b) + (:g5 1) :f5 :g5 :bb5 :c5 :bb5 :d5 :bb5 :e5 :bb5 :c5 :bb5 +; linea 8 + (MRK n12c) + :f5 :e5 :f5 :a5 :b4 :a5 :c#5 :a5 :d5 :a5 :b4 :a5 + :e5 :d5 :e5 :g5 :a4 :g5 :b4 :g5 :c#5 :g5 :a4 :g5 + (MRK n13) + (:f5 2) :d5 :bb4 :d5 :g4 :f5 +; linea 9 + (MRK n14) + :e5 :c5 :a4 :c5 :f4 :eb5 + (MRK n15) + (:d5 1) :f5 :eb5 :f5 :d5 :f5 :eb5 :f5 :d5 :f5 :eb5 :f5 + (MRK n16) + :bb4 :d5 :c5 :d5 :bb4 :d5 :c5 :d5 :bb4 :d5 :c5 + (PWL-POINT :rel 3) :d5 + (PWL-POINT :rel 1) +; linea 10 + (MRK n17) + :g4 :bb4 :a4 :bb4 :g4 :bb4 :a4 :bb4 :g4 :bb4 :a4 (PWL-POINT :rel 1.5) :bb4 + (MRK n18) + (PWL-POINT :rel 2) + (:e4 2) :c4 :g4 :e4 :bb4 :g4 + (MRK n19) + (:c5 1) :d5 :c5 :bb4 :a4 :bb4 :a4 :g4 :f4 :g4 :f4 :eb4 +; linea 11 + (:d4 2) + (PWL-POINT :rel 4) + (MRK n20) + (:g4 1) :f4 :e4 :f4 :e4 :d4 :c4 :d4 :c4 :bb3 :a3 :bb3 :a3 :g3 + (:f3 2) (PWL-POINT :rel 2) + (MRK n21) + (:f4 1) :e4 (:f4 2) (MRK rall) :a3 +; rallentando + (:bb3 2.2) (:f4 2.4) (:a3 2.6) (PWL-POINT :rel 1) (:f4 2.8) + (MRK n22) (PWL-POINT :rel 3.2) + (:g3 3) (:e4 3.4) (MRK final)(DUR 4) (PWL-POINT :rel 5)(ATTR :din 0.5)(CH :a3 :c4 :f4))) +(setf voz-2 + + '((ATTR :mm 120.0) + (INIT-INSTR "i1" xan3) (INSTRUMENT "i1") + (PWL-POINT :reson 100)(PWL-POINT :rel 1)(PWL-POINT :din 2.5) + (CHN 6)(PATCH 47) (DELTA 12)(DELTA 2) (:f3 2) :a3 :f3 :c4 :f3 + (PWL-POINT :rel 1.5)(PWL-POINT :reson 500)(PWL-POINT :din 3) + :f4 (:e4 1) :d4 :c4 :d4 :c4 :bb3 :a3 :bb3 :a3 :g3 + (PWL-POINT :din 1.5) +; linea 2 + (:f3 2) :a3 :c4 :a3 :f4 :c4 (:a4 1) :c5 :bb4 :c5 :a4 :c5 :bb4 :c5 :a4 :c5 :bb4 :c5 + :f4 :a4 :g4 :a4 :f4 :a4 :g4 :a4 :f4 :a4 :g4 :a4 +; linea 3 + (PWL-POINT :reson 2500) + :d4 :f4 :e4 :f4 :d4 :f4 :e4 :f4 :d4 :f4 :e4 :f4 + (:b3 2) :g3 :c4 :g3 :e4 :c4 + (PWL-POINT :rel 2) + (:f4 1) :g4 :f4 :e4 :d4 :e4 :d4 :c4 :b3 :c4 :b3 :a3 +; linea 4 + (PWL-POINT :din 1)(PWL-POINT :rel 2) + (:g3 2) (:c4 1) :b3 :a3 :b3 :a3 :g3 :f3 :g3 :f3 :e3 :d3 :e3 :d3 :c3 :g3 :f3 :e3 :f3 (:g3 2) :g2 + (PWL-POINT :rel 1.5)(PWL-POINT :reson 300)(PWL-POINT :din 3) + 2 :c3 (PWL-POINT :rel 2) :e3 :c3 :g3 :c3 +; linea 5 + (PWL-POINT :rel 2.5) + (PWL-POINT :rel 1.5)(PWL-POINT :reson 500) + :c4 (:b3 1) :a3 :g3 :a3 :g3 :f3 :e3 :f3 :e3 :d3 + (:c3 2) :e3 :g3 :e3 :c4 :g3 :eb4 :f#3 :eb4 :f#3 :eb4 :f#3 +; linea 6 + :g3 (:f3 1) :eb3 :d3 :eb3 :d3 :c3 :bb2 :c3 :bb2 :a2 + (PWL-POINT :rel 1.5)(PWL-POINT :din 1) + (:g2 2) :g3 :bb3 :g3 :d4 :g3 :g4 (:f4 1) :eb4 :d4 :eb4 :d4 :c4 :bb3 :c4 :bb3 :a3 +; linea 7 + (PWL-POINT :rel 1.5)(PWL-POINT :reson 1500)(PWL-POINT :din 2) + :g3 :f3 :g3 :e4 :g3 :e4 :f3 :e4 :g3 :e4 :e3 :e4 + :f3 :e3 :f3 :d4 :f3 :d4 :e3 :d4 :f3 :d4 :d3 :d4 + (:bb3 2) :g3 :e3 :g3 :c3 :e3 +; linea 8 + :a3 :f3 :d3 :f3 :b2 :d3 :g3 :e3 :c#3 :e3 :a2 (PWL-POINT :rel 1) :c#3 + (PWL-POINT :rel 1.5) + (:d2 1) :d3 :c3 :d3 :g2 :d3 :a2 :d3 :bb2 :d3 :g2 (PWL-POINT :din 1.) :d3 +; linea 9 + (PWL-POINT :din 1.)(PWL-POINT :rel 2)(PWL-POINT :reson 2000) + :c2 :c3 :bb2 :c3 :f2 :c3 :g2 :c3 :a2 :c3 :f2 :c3 + (:bb2 2) :d3 :f3 :d3 :bb3 :f3 + (PWL-POINT :din 2)(PWL-POINT :reson 1000) + (:d4 1) :f4 :eb4 :f4 :d4 :f4 :eb4 :f4 :d4 :f4 :eb4 :f4 +; linea 10 + :bb3 :d4 :c4 :d4 :bb3 :d4 :c4 :d4 :bb3 :d4 :c4 :d4 + :g3 :bb3 :a3 :bb3 :g3 :bb3 :a3 :bb3 :g3 :bb3 :a3 :bb3 + (:e3 2) :c3 :f3 :c3 :a3 :f3 +; linea 11 + (:bb3 1) :c4 :bb3 :a3 + :g3 :a3 :g3 :f3 :e3 :f3 :e3 :d3 (:c3 2) + (:f3 1) :e3 :d3 :e3 :d3 :c3 :bb2 :c3 :bb2 :a2 + (:g2 1.1) :a2 (:g2 1.2) :f2 + (:c3 1.3) :bb2 (:a2 1.4) :bb2 (:c3 3.2) + (PWL-POINT :din 1) + (PWL-POINT :rel 2)(PWL-POINT :reson 3500) (:c2 3.4) (PWL-POINT :rel 4)(:f2 4))) + + +(play + (sum + (scale 1 (timed-seq (sdl->score voz-1))) + (timed-seq (sdl->score voz-2)))) diff --git a/demos/sequence_example.htm b/demos/sequence_example.htm new file mode 100644 index 0000000..7d29683 --- /dev/null +++ b/demos/sequence_example.htm @@ -0,0 +1,52 @@ + + + + + +Sequence Example + + + + +

Sequence Example

+ +

A sequence of notes is often specified by a "note list," consisting of times, +durations, other transformations, and a parameterized behavior to generate the sound. The +following is an example:

+ +
(defun ringpat1 () 
+  (scale 0.8 
+    (sim
+      (scale 0.6 (at 0.0 (ring 0.6 45 2)))
+      (scale 0.5 (at 0.2 (ring 0.8 40 1.5)))
+      (scale 0.8 (at 0.6 (ring 1 44 1)))
+      (scale 0.7 (at 0.8 (ring 1.2 32 0.8))) 
+    )))
+ +

Notice that there are 4 sounds. The sounds are shifted in time using the at +transformation, and all four sounds are combined using the sim construction. +Because of the time shifts, the sounds do not take place simultaneously, but they may +overlap somewhat.

+ +

Durations are specified by the first parameter to ring, so no stretch +transformations are used here. Each sound is individually scaled.

+ +

To play this sound, you need the ring function from Vinal Scratch Tutorial. Then you can type:

+ +
(play (ringpat1))
+ +

Try the following combination, which plays a short and long version of ringpat1 +at about the same time:

+ +
(play (sim
+        (scale 1.0 (at 0.0 (ringpat1)))
+        (scale 0.7 (at 0.05 (stretch 1.5 (ringpat1)))) ))
+ +
+
+
+
+ + + diff --git a/demos/shepard.lsp b/demos/shepard.lsp new file mode 100644 index 0000000..8c528c5 --- /dev/null +++ b/demos/shepard.lsp @@ -0,0 +1,195 @@ +; Shepard tones and paradoxes + +; to use try +; (playscale (majorscale 60)) +; (playscale (minorscale 60)) +; (playscale (chromascale 60)) +; (playparadoxscale (chromascale 60)) + +; for shepard sweeps, try +; (play (sheptone-sweep 60 60 2 72 60 12 4)) + +; the signature of sheptone-sweep should tell what the parameters do +; (defun sheptone-sweep (pitch-1 centerpitch-1 duration pitch-2 centerpitch-2 +; overtonesemi overtones +; &optional (wavetable *sine-table*)) + +; Some notes about how this works: +; Shepard tones consist of harmonics that are an octave apart, thus +; the ratios are 1, 2, 4, 8, 16, etc. Note that the pitch is ambiguous +; in the sense that there could be a missing fundamental at 0.5, 0.25, etc. +; The other trick is that the spectral shape is constant. The amplitude +; of each harmonic is a function of its absolute frequency. Here, the +; shape is triangular so that as the frequency sweeps upward, harmonics +; (which are ramping up in frequency) fade in, reach a maximum, and fade out. +; +; In this implementation, each harmonic is generated using an FM oscillator +; controlled by a frequency ramp. The harmonic is multiplied by an envelope +; to implement the spectral shape function. The envelope is computed by +; running the frequency control (with some scaling) into a SHAPE function +; that uses a triangular table to implement the spectral shape. +; +; Warning: Although I have not analyzed this code too carefully, I (RBD) +; believe that the oscillators keep sweeping up to higher and higher +; frequencies even after the amplitude drops to zero. This is not only +; wasteful, but when oscillators start to alias, they run slower. If you +; generate a very long Shepard tone with harmonics spanning many octaves, +; the run time could get to be very large. A better implementation would +; start the harmonics when they enter the non-zero part of the spectral +; envelope and end them when they leave it. + + +(setf *onepi* 3.141592654) +(setf *twopi* (* 2 pi)) +(setf *halfpi* (/ pi 2)) + + +; envshaper is a raised cosine curve used to control +; the spectral shape. Its domain is 0 to 2 +; it transforms (0 2) into 0 1 +; it has to be used like +; (shape s (envshaper) 1) + +(defun envshaper () + (mult (sum 1 (hzosc (const (/ 1.0 2.0) 2) *table* 270)) 0.5)) + + +; some utility functions + +;; ISEQ-HELPER -- generates an integer sequence +(defun iseq-helper (a b) + (let ((mylist '())) + (dotimes (i (1+ (- b a)) (reverse mylist)) + (setf mylist (cons (+ a i) mylist))))) + +;; ISEQ -- sequence of integers from a to b +(defun iseq (a b) + (if (> a b) (reverse (iseq-helper b a)) + (iseq-helper a b))) + + +(defun floor (x) + (if (< x 0) + (1- (truncate x)) + (truncate x))) + + + +; the main part + +(defun sheptone-sweep-helper (pitch-1 centerpitch-1 + duration + pitch-2 centerpitch-2 + overtonesemi overtones + &optional (wavetable *sine-table*)) + (let ((mytone (const 0 duration)) + (maxovertones (+ (floor (/ (float (max (abs (- pitch-1 centerpitch-2)) + (abs (- pitch-1 centerpitch-2)))) + overtonesemi)) + overtones 2)) + (ampshaper (envshaper))) + ;; synthesize and sum maxovertones partials + (dolist (i (iseq (- maxovertones) maxovertones) mytone) + (progn + ;; partials start at pitch-1, spaced by overtonesemi (normally 12) + (setf startpitch (+ pitch-1 (* i overtonesemi))) + ;; partials end at pitch-2 + offset + (setf endpitch (+ pitch-2 (* i overtonesemi))) + ;; f is the frequency modulation (in hz) + (setf f (pwe 0 (step-to-hz startpitch) + duration (step-to-hz endpitch))) + ;; p is the pitch in steps + (setf p (pwl 0 startpitch duration endpitch)) + ;; c is the centerpitch curve + ;; (probably we could compute this outside the loop) + (setf c (pwl 0 centerpitch-1 duration centerpitch-2)) + ;; normwidthfactor is used to map pitch curves into the spectral shape + ;; function (range 0 to 2) + (setf normwidthfactor (/ 1.0 (* overtones overtonesemi))) + ;; a is the amplitude envelope: f(p - c) + (setf a (shape (mult (diff p c) normwidthfactor) + ampshaper 1)) + ;; voice is one partial + (setf voice (mult a (hzosc f wavetable))) + ;; sum the partials into mytone + (setf mytone (sum mytone voice)) + ) + ))) + + +(defun sheptone-sweep (pitch-1 centerpitch-1 duration pitch-2 centerpitch-2 + overtonesemi overtones + &optional (wavetable *sine-table*)) + (normalize ;; note: you might not want to normalize as is done here + ;; use an envelope to get a smooth start and stop + (mult (sheptone-sweep-helper pitch-1 centerpitch-1 + duration + pitch-2 centerpitch-2 + overtonesemi overtones wavetable) + (env 0.05 0 0.05 1 1 1 duration)))) + + +;; SHEPTONE is a special case of sheptone-sweep. +;; The spectral centroid and pitch is constant. +(defun sheptone (pitch centerpitch duration + overtonesemi overtones + &optional (wavetable *sine-table*)) + (sheptone-sweep pitch centerpitch duration pitch centerpitch + overtonesemi overtones + wavetable)) + +(defun majorscale (basepitch) + (mapcar (lambda (x) (+ basepitch x)) '(0 2 4 5 7 9 11 12))) + +(defun minorscale (basepitch) + (mapcar (lambda (x) (+ basepitch x)) '(0 2 3 5 7 8 10 12))) + +(defun chromascale (basepitch) + (mapcar (lambda (x) (+ basepitch x)) (iseq 0 12))) + + +;; MAKE-TABLE turns a function of 0-1 into a lookup table +(defun make-table (func-exp points) + (let ((table (make-array points))) + (dotimes (i points) + (setf (aref table i) + (funcall func-exp (/ (float i) (float points))))) + (list (snd-from-array 0.0 points table) (hz-to-step 1) T) + )) + + +(defun erich-wave (skew) + (make-table + (lambda (x) (if (< (abs skew) 0.000001) (sin (* *twopi* x)) + (* + (/ (sin (* *twopi* x)) (- (/ 1.0 skew) + (cos (* *twopi* x)))) + (/ (sqrt (- 1.0 (* skew skew))) skew)))) + 2048)) + + +;; NORMALIZE -- normalize a sound +;; +(defun normalize (s &optional (maxvol 0.8) (maxlen 44100)) + (let* ((mysound s) + (vol (peak mysound maxlen))) + (scale (/ (float maxvol) vol) mysound))) + +(defun playsafe (s) + (play (normalize s))) + +;; PLAYSCALE uses SHEPTONE to synthesize a scale that goes up on every +;; step, but never actually ends up an octave higher +;; +(defun playscale (scaleseq &optional (duration 1) (wavetable *sine-table*)) + (mapcar (lambda (x) (play (sheptone x 60 duration 12 4 wavetable))) + scaleseq)) + + +;; PLAYPARADOXSCALE uses sheptone to go up by half steps, yet end up +;; an octave lower than it starts +;; +(defun playparadoxscale (scaleseq + &optional (duration 1) (wavetable *sine-table*)) + (mapcar (lambda (x y) (play (sheptone x y duration 12 4 wavetable))) + scaleseq (reverse scaleseq))) diff --git a/demos/shepard.ny b/demos/shepard.ny new file mode 100644 index 0000000..2bd10a6 --- /dev/null +++ b/demos/shepard.ny @@ -0,0 +1,139 @@ +;nyquist plug-in +;version 1 +;type generate +;name "Shephard glissando" +;action"Creating Shephard glissando" +;info "Shephard-Risset glissando\nwritten by Erich Neuwirth" +;control pitch1 "Start pitch" real "MIDInote" 60 24 96 +;control pitch2 "End pitch" real "MIDInote" 72 24 96 +;control cpitch1 "Start filter pitch" real "MIDInote" 60 24 96 +;control cpitch2 "End filter pitch" real "MIDInote" 60 24 96 +;control overtonesemi "Overtone interval" real "MIDInote" 12 3 24 +;control overtones "Overtones" int "" 4 1 8 +;control duration "Duration" real "seconds" 1.5 0.3 30 +;control skew "Tone skewness" real "" 0.0 0.0 0.99 + +(setf overtones (truncate overtones)) + +(setf *onepi* 3.141592654) +(setf *twopi* (* 2 pi)) +(setf *halfpi* (/ pi 2)) + + +(defun make-table (func-exp points) + (let ((table (make-array points))) + (dotimes (i points) + (setf (aref table i) + (funcall func-exp (/ (float i) (float points))))) + (list (snd-from-array 0.0 points table) (hz-to-step 1) T) + )) + + +(defun erich-wave (skew) + (make-table + (lambda (x) (if (< (abs skew) 0.000001) (sin (* *twopi* x)) + (* + (/ (sin (* *twopi* x)) (- (/ 1.0 skew) + (cos (* *twopi* x)))) + (/ ( + sqrt (- 1.0 (* skew skew))) skew)))) + 2048)) + + +(defun pitchenv (pitch centerpitch halfwidth) + (let ((xarg (abs (/ (- (float pitch) centerpitch) halfwidth)))) + (if (> xarg 1) 0 + (/ (+ (cos (* *onepi* xarg)) 1.0) 2.0)) + )) + + + + +; envshaper is shifted from 0 to 2 +; it transforms (0 2) into 0 1 +; to use it as envelope distorter, it has to be used like +; (shape s (envshaper) 1) + +(defun envshaper () + (mult (sum 1 (hzosc (const (/ 1.0 2.0) 2) *table* 270)) 0.5)) + + +; some utility functions + +(defun normalize (s &optional (maxvol 0.8) (maxlen 44100)) + (let* ((mysound s) + (vol (peak mysound maxlen))) + (scale (/ (float maxvol) vol) mysound))) + + +(defun buffer (s t1 duration t2) + (let ((timebase (hzosc (pwl (+ duration t1 t2))))) + (sim timebase (at t1 (cue s))))) + + +(defun iseq-helper (a b) + (let ((mylist '())) + (dotimes (i (1+ (- b a)) (reverse mylist)) + (setf mylist (cons (+ a i) mylist))))) + + +(defun iseq (a b) + (if (> a b) (reverse (iseq-helper b a)) + (iseq-helper a b))) + + +(defun floor (x) + (if (< x 0) + (1- (truncate x)) + (truncate x))) + +(defun realrem (x mod) + (- (float x) (* (floor (/ (float x) (float mod))) (float mod)))) + + +(defun sheptone-sweep-helper (pitch-1 centerpitch-1 + duration + pitch-2 centerpitch-2 + overtonesemi overtones + &optional (wavetable *sine-table*)) + (let ((mytone (const 0 duration)) + (maxovertones (+ (floor (/ (float (max (abs (- pitch-1 centerpitch-2)) + (abs (- pitch-1 centerpitch-2)))) + overtonesemi)) + overtones 2)) + (ampshaper (envshaper)) + ) + (dolist (i (iseq (- maxovertones) maxovertones) mytone) + (progn + (setf startpitch (+ pitch-1 (* i overtonesemi))) + (setf endpitch (+ pitch-2 (* i overtonesemi))) + (setf f (pwe 0 (step-to-hz startpitch) + duration (step-to-hz endpitch))) + (setf p (pwl 0 startpitch duration endpitch)) + (setf c (pwl 0 centerpitch-1 duration centerpitch-2)) + (setf normwidthfactor (/ 1.0 (* overtones overtonesemi))) + (setf a (shape (mult (diff p c) normwidthfactor) + ampshaper 1)) + (setf voice (mult a (hzosc f wavetable))) + (setf mytone (sum mytone voice)) + ) + ))) + + + +(defun sheptone-sweep (pitch-1 centerpitch-1 duration pitch-2 centerpitch-2 + overtonesemi overtones + &optional (wavetable *sine-table*)) + (normalize + (mult (sheptone-sweep-helper pitch-1 centerpitch-1 + duration + pitch-2 centerpitch-2 + overtonesemi overtones wavetable) + (env 0.05 0 0.05 1 1 1 duration))) + ) + + +(setf result (buffer (sheptone-sweep pitch1 cpitch1 + duration pitch2 cpitch2 overtonesemi overtones) 0.1 duration 0.2)) + +result diff --git a/demos/softclip.gif b/demos/softclip.gif new file mode 100644 index 0000000..3881970 Binary files /dev/null and b/demos/softclip.gif differ diff --git a/demos/softclip.jpg b/demos/softclip.jpg new file mode 100644 index 0000000..9d8bf53 Binary files /dev/null and b/demos/softclip.jpg differ diff --git a/demos/stktest.lsp b/demos/stktest.lsp new file mode 100644 index 0000000..c83d296 --- /dev/null +++ b/demos/stktest.lsp @@ -0,0 +1,407 @@ +;; stktest.lsp -- test the STK instruments + +(autonorm-on) + +(print "Type (makedemo number) with number ranging from 1 to 17") +(print "Type (all-stk-demos) to hear them all") + +(defun makedemo (n) + (case n + (1 (progn (nrev-demo)(print "NRev Demo"))) + (2 (progn (jcrev-demo)(print "JCRev Demo"))) + (3 (progn (prcrev-demo)(print "PRCRev Demo"))) + (4 (progn (stkchorus-demo)(print "Chorus Demo"))) + (5 (progn (pitshift-demo) (print "Pitch Shift Demo"))) + (6 (progn (flute-demo)(print "Flute Demo"))) + (7 (progn (flute-freq-demo)(print "Flute Freq Demo"))) + (8 (progn (flute-all-demo)(print "Flute All Demo"))) + (9 (progn (bowed-demo 0.4)(print "Bowed Instrument Demo"))) + (10 (progn (bowed-freq-demo)(print "Bowed Freq Instrument Demo"))) + (11 (progn (mandolin-demo)(print "Mandolin Demo"))) + (12 (progn (wg-uniform-bar-demo) (print "Uniform Bar Wave Guide Demo"))) + (13 (progn (wg-tuned-bar-demo)(print "Tuned Bar Wave Guide Demo"))) + (14 (progn (wg-glass-harm-demo)(print "Glass Harmonica Wave Guide Demo"))) + (15 (progn (wg-tibetan-bowl-demo)(print "Tibetan Bowl Prayer Wave Guide Demo"))) + (16 (progn (modalbar-demo)(print "Modal Bar Demo"))) + (17 (progn (sitar-demo) (print "Sitar Demo"))) + (18 (progn (clarinet-example-1) (print "Clarinet Demo 1"))) + (19 (progn (clarinet-example-2) (print "Clarinet Demo 2"))) + (20 (progn (clarinet-example-3) (print "Clarinet Demo 3"))) + (21 (progn (clarinet-example-4) (print "Clarinet Demo 4"))) + (22 (progn (clarinet-example-5) (print "Clarinet Demo 5"))) + (23 (progn (sax-example-1) (print "Sax Demo 1"))) + (24 (progn (sax-example-2) (print "Sax Demo 2"))) + (t (error "number ranges from 1 to 24")))) + + +(defun all-stk-demos () + (dotimes (i 24) (makedemo (1+ i)))) + + + +;;; ******************************** +;;; +;;; EFFECTS DEMOS +;;; +;;; ******************************** + + +; design of a tubular-bell-like sound + +(setf *pi-over-2* (/ 3.141592 2)) + +(defun pan-fun-l (x) + (* (/ (sqrt 2.0)) (- (cos (* x *pi-over-2*)) (sin (* x *pi-over-2*))))) + +(defun pan-fun-r (x) + (* (/ (sqrt 2.0)) (+ (cos (* x *pi-over-2*)) (sin (* x *pi-over-2*))))) + +(defun pan-snd (snd pan) + (vector (scale (pan-fun-l pan) snd) + (scale (pan-fun-r pan) snd))) + + +(defun tub-partial (scale-factor freq-factor time-factor pitch dur) + (scale scale-factor (mult (sim -1.0 (pwev 10 (* dur time-factor) 1)) + (osc (hz-to-step (* freq-factor (step-to-hz pitch))) + (* dur time-factor))))) + +(defun tubular (pitch dur) + (let ((hz (step-to-hz pitch))) + (sim (tub-partial 0.1 1.0 1.0 pitch dur) + (tub-partial 0.06 2.76 0.8 pitch dur) + (tub-partial 0.04 5.4 0.7 pitch dur) + (tub-partial 0.03 8.93 0.4 pitch dur) + (tub-partial 0.02 13.34 0.2 pitch dur) + (tub-partial 0.01 18.64 0.1 pitch dur) + (tub-partial 0.005 31.87 0.05 pitch dur)))) + +(defun ktubular (&key pitch idur pan dyn) + (pan-snd (scale dyn (tubular pitch idur)) pan)) + +; (if rev (nrev snd 4 0.25) +; snd))) + +; algorithmic score by means of Xmusic + +(setf pitches1 (make-cycle (list c5 g4 e4 c4) :for 8)) +(setf pitches2 (make-cycle (list c5 a4 f4 d4) :for 8)) +(setf *pitches* (make-cycle (list pitches1 pitches2) :for 6)) + +(setf *ioi* (make-cycle (list 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.6))) +(setf *pan* (make-cycle (list 0 -0.2 0.2 -0.4 0.4 -0.45 0.45 -0.1 0.1 -0.25 0.25 -0.3 0.3))) +(setf *dyn* (make-cycle (list 1 1 1 1 1 1 1 1.2 2 2 1 2 1 2 1 2 ))) + +(setf my-score (score-gen :name 'ktubular :dur 1 :idur 2 + :ioi 0.2 + :pitch (next *pitches*) + :dyn (next *dyn*) + :pan (next *pan*) + :score-len 16)) + + +(defun nrev-demo () + (play (seq (timed-seq my-score) + (nrev (timed-seq my-score) 4.0 0.25)))) + +;(nrev-demo) + +(defun jcrev-demo () + (play (seq (timed-seq my-score) + (jcrev (timed-seq my-score) 4.0 0.25)))) + +;(jcrev-demo) + +(defun prcrev-demo () + (play (seq (timed-seq my-score) + (prcrev (timed-seq my-score) 4.0 0.25)))) + +;(prcrev-demo) + + +(defun stkchorus-demo () + (play (seq (timed-seq my-score) + (stkchorus (timed-seq my-score) 0.1 0.2 0.5)))) + +;(stkchorus-demo) + +(defun pitshift-demo () + (play (seq (timed-seq my-score) + (pitshift (timed-seq my-score) 2.0 0.9) + (pitshift (timed-seq my-score) 0.4 0.7) + (pitshift (timed-seq my-score) 6.0 0.7)))) + +;(pitshift-demo) + + +; ******************************************* +; +; INSTRUMENTS DEMOS +; +; ******************************************* + + +(defun env1 (d) + (pwl 0.1 0.7 (- d 0.3) 0.5 d)) + +(defun flute-demo () + (play + (seq (flute e5 (env1 1)) + (flute c5 (env1 1)) + (flute g4 (env1 2))))) + +;(flute-demo) + +(defun env2 (ampl d) + (scale ampl (mult (pwlv 0.0 1.0 0.0 d 1.0) (lfo 5 d)))) +(defun flute-freq-demo () + (play (flute-freq c5 (env1 6) (env2 8 6)))) + +;(flute-freq-demo) + +(defun env3 (d) + (pwl (* d 0.5) 20 d)) +(defun flute-all-demo () + (play (flute-all c5 (env1 6) (env3 6) 6 0.2 0.5 0.06))) + +;(flute-all-demo) + +(defun bow-env (d) + (pwl 0.05 0.5 (- d 0.1) 0.3 d)) + +(defun bowed-demo (d) + (play (seq (bowed g4 (bow-env d)) + (bowed d5 (bow-env d)) + (bowed b5 (bow-env d)) + (bowed a5 (bow-env d)) + (bowed b5 (bow-env d)) + (bowed d5 (bow-env d)) + (bowed b5 (bow-env d)) + (bowed d5 (bow-env d)) + (bowed g4 (bow-env d))))) + +;(bowed-demo 0.4) + +(defun bowed-freq-demo () + (play (bowed-freq c3 (bow-env 10) (env2 5 10)))) + +;(bowed-freq-demo) + +(defun mandolin-demo () + (play (seq (mandolin c4 1.0) + (mandolin c4 1.0 2.0) + (mandolin c4 1.0 3.0) + (mandolin c4 1.0 4.0) + (mandolin c4 1.0 5.0) + (mandolin c4 1.0 6.0) + (mandolin c4 1.0 7.0) + (mandolin c4 1.0 8.0) + (mandolin c4 1.0 9.0) + (mandolin c4 1.0 10.0) + (mandolin c4 1.0 11.0) + (mandolin c4 1.0 12.0) + (mandolin c4 1.0 13.0) + (mandolin c4 1.0 14.0) + (mandolin c4 1.0 15.0) + (mandolin c4 1.0 16.0) + (mandolin c4 1.0 17.0) + (mandolin c4 1.0 18.0) + (mandolin c4 1.0 19.0) + (mandolin c4 1.0 20.0) + (mandolin c4 1.0 25.0) + (mandolin c4 1.0 30.0) + (mandolin c4 1.0 35.0) + (mandolin c4 1.0 40.0) + (mandolin c4 1.0 45.0) + (mandolin c4 1.0 50.0) + (mandolin c4 1.0 55.0) + (mandolin c4 1.0 60.0) + (mandolin c4 1.0 65.0)))) + +;(mandolin-demo) + +(defun wg-env (d) + (pwlv 1 d 1)) + +(defun wg-uniform-bar-demo () + (play (seq (wg-uniform-bar c4 (wg-env 0.2)) + (wg-uniform-bar g3 (wg-env 0.2)) + (wg-uniform-bar c4 (wg-env 0.2)) + (wg-uniform-bar e4 (wg-env 0.2)) + (wg-uniform-bar g4 (wg-env 2.2))))) + +;(wg-uniform-bar-demo) + +(defun wg-tuned-bar-demo () + (play (seq (wg-tuned-bar c4 (wg-env 0.2)) + (wg-tuned-bar g3 (wg-env 0.2)) + (wg-tuned-bar c4 (wg-env 0.2)) + (wg-tuned-bar e4 (wg-env 0.2)) + (wg-tuned-bar g4 (wg-env 0.2))))) + +;(wg-tuned-bar-demo) + +(defun wg-glass-harm-demo () + (play (seq (wg-glass-harm c4 (wg-env 0.2)) + (wg-glass-harm g3 (wg-env 0.2)) + (wg-glass-harm c4 (wg-env 0.2)) + (wg-glass-harm e4 (wg-env 0.2)) + (wg-glass-harm g4 (wg-env 1.2))))) + +;(wg-glass-harm-demo) + +(defun wg-tibetan-bowl-demo () + (play (seq (wg-tibetan-bowl c4 (wg-env 0.2)) + (wg-tibetan-bowl ef4 (wg-env 0.2)) + (wg-tibetan-bowl fs4 (wg-env 0.2)) + (wg-tibetan-bowl a4 (wg-env 2.0))))) + +;(wg-tibetan-bowl-demo) + +(defun modalbar-demo-1 (prst) + (seq (modalbar prst c4 0.2) + (modalbar prst g3 0.2) + (modalbar prst c4 0.2) + (modalbar prst e4 0.2) + (modalbar prst g4 1.0))) + +(defun modalbar-demo () + (play (seq (modalbar-demo-1 'MARIMBA) + (modalbar-demo-1 'VIBRAPHONE) + (modalbar-demo-1 'AGOGO) + (modalbar-demo-1 'WOOD1) + (modalbar-demo-1 'RESO) + (modalbar-demo-1 'WOOD2) + (modalbar-demo-1 'BEATS) + (modalbar-demo-1 'TWO-FIXED) + (modalbar-demo-1 'CLUMP)))) + +;(modalbar-demo) + +(defun sitar-demo () + (play (seq (sitar c3 0.6) + (sitar g3 1.2) + (sitar fs3 0.4) + (sitar g3 0.4) + (sitar af3 0.6) + (sitar ef3 2.0)))) + +;(sitar-demo) + + +;; simple clarinet sound +(defun clarinet-example-1 () + (play (clarinet bf3 (stk-breath-env 1 0.2 0.1)))) + +;; clarinet sound with frequency sweep (glissando) +(defun clarinet-example-2 () + (play (clarinet-freq bf3 (stk-breath-env 3 0.2 0.1) (pwl 1.5 80 3 80 3)))) + +;; clarinet sound with change in breath pressure +(defun clarinet-example-3 () + (play (clarinet bf3 (prod (pwl 0 1 1.5 0.9 3 1 3) (stk-breath-env 3 0.2 0.1))))) + +;; clarinet sound using initial frequency sweep and built-in vibrato effect +(defun clarinet-example-4 () + (play (clarinet-all bf3 (stk-breath-env 3 0.5 0.05) (pwl 0.3 80 3 80 3) 5.7 0.5 0 0))) + +;; clarinet sound with increasing then decreasing reed stiffness +(defun clarinet-example-5 () + (play (clarinet-all bf3 (stk-breath-env 3 0.5 0.05) 0 0 0 (pwl 1.5 0.75 3) 0))) + +;; clarinet sound with increasing noise, with vibrato +(defun clarinet-example-6 () + (play (clarinet-all bf3 (stk-breath-env 3 0.5 0.05) 0 5.7 0.5 0 (pwl 3 1 3)))) + +;(print "clarinet-example-1") +;(clarinet-example-1) +;(print "clarinet-example-2") +;(clarinet-example-2) +;(print "clarinet-example-3") +;(clarinet-example-3) +;(print "clarinet-example-4") +;(clarinet-example-4) +;(print "clarinet-example-5") +;(clarinet-example-5) +;(print "clarinet-example-6") +;(clarinet-example-6) + + +(defun sax-example-1 () + (scale 0.5 + (timed-seq '( + (0.0 1 (sax g3 (stk-breath-env 2 0.2 0.2))) + (2.0 1 (sax-freq c4 (stk-breath-env 4 0.6 0.6) + (scale 100 (mult (pwl 0 0.95 4 1.3 4))))) + ))) +) + +(defun sax-example-2 () + (scale 0.5 + (timed-seq + '( + (0.0 1 (sax-freq + bf3 + (eight-sixteenths-env) + (freqenv 1 bf3 (list 0 bf3 0.125 af4 0.25 g4 0.375 d4 + 0.5 f4 0.625 ef4 0.75 d4 0.875 ef4)))) + (1.0 1 (sax-freq + e4 + (eight-sixteenths-env) + (freqenv 1 e4 (list 0 e4 0.125 c4 0.25 a3 0.375 e3 + 0.5 fs3 0.625 e3 0.75 fs3 0.875 e4)))) + (2.0 1 (sax-freq + d4 + (eight-sixteenths-env) + (freqenv 1 d4 (list 0 d4 0.125 c4 0.25 b3 0.375 a3 + 0.5 g3 0.625 a3 0.75 b3 0.875 d4)))) + (3.0 1 (sax-freq + ef4 + (eight-sixteenths-env) + (freqenv 1 ef4 (list 0 ef4 0.125 cs4 0.25 b3 0.375 bf3 + 0.625 gf3 0.75 af3 0.875 bf4)))))))) + +(defun eight-sixteenths-env () + (mult (envbreaks 1 (list 0.125 0.25 0.375 0.5 0.625 0.75 0.875)) + (stk-breath-env 1 1 1))) + +(defun hzdiff (step1 step2) + (- (step-to-hz step2) (step-to-hz step1))) + +;; create a piecewise-constant (stairstep) function to control frequencies +;; timesteplist is (time0 step0 time1 step1 etc.) +;; +(defun freqenv (dur step timesteplist) + (let ((finalenv nil) hzdiff (tslist timesteplist) currt currs) + (do () ((null tslist)) + (setf currt (car tslist)) + (setf currs (cadr tslist)) + (setf tslist (cdr (cdr tslist))) + + (setf finalenv (append finalenv + (list currt + (hzdiff step currs) + (if (null tslist) dur (car tslist)) + (hzdiff step currs)) + ))) + (setf finalenv (append finalenv (list dur))) + (pwl-list finalenv))) + +;; create a breath envelope where pressure goes to zero at designated points +;; dur is overall duration +;; breaklist is places where pressure dips to zero during a 20ms window +;; +(defun envbreaks (dur breaklist) + (let ((finalenv nil)) + (dolist (breakpt breaklist) + (setf finalenv (append finalenv (list (- breakpt 0.01) 1 + (- breakpt 0.001) 0 + breakpt 1)))) + (setf finalenv (append (list 0 1) finalenv (list dur))) + (pwl-list finalenv))) + +;(print "sax-example-1") +;(play (sax-example-1)) +;(print "sax-example-2") +;(play (sax-example-2)) + diff --git a/demos/voice_synthesis.htm b/demos/voice_synthesis.htm new file mode 100644 index 0000000..4f9b922 --- /dev/null +++ b/demos/voice_synthesis.htm @@ -0,0 +1,290 @@ + + + +Voice Synthesis Tutorial + + + + +

Voice Synthesis Tutorial

+ +

Nyquist voice synthesis instrument by Eduardo Reck Miranda.

+ +
;---------------------------------------------------------------------------
+; Nyquist voice synthesis instrument by Eduardo Reck Miranda
+;
+; Implements a geometrical articulator for tongue position (h p) and 
+; lips rouding (r) 
+;
+;---------------------------------------------------------------------------
+; Geometrical articulator: the following FORMx functions estimates the formant
+; values from the positions of the three articulators p h and r, where:
+; p = horizontal position of the tongue: 0.0 = front and 1.0 = back 
+; h = vertical position of the tongue: 0.0 = low and 1.0 = high
+; r = rounding of the lips: 0.0 = spread -> 1.0 rounded
+;---------------------------------------------------------------------------
+; FORM1: converts p-h-r articulators to first formant frequency
+;---------------------------------------------------------------------------
+(defmacro form1 (p h r)
+  `(+ (* (+ (* (+ (- 392) (* 392 ,r)) (expt ,h 2))
+            (* (- 596 (* 668 ,r)) ,h) 
+            (+ (- 146) (* 166 ,r))) 
+         (expt ,p 2))
+ 
+      (* (+ (* (- 348    (* 348 ,r)) (expt ,h 2)) 
+            (* (+ (- 494) (* 606 ,r)) ,h) 
+            (- 141 (* 175 ,r)))
+         ,p)
+ 
+      (+ (* (- 340 (* 72 ,r)) (expt ,h 2)) 
+         (* (+ (- 796) (* 108 ,r)) ,h)
+         (- 708 (* 38 ,r)))
+      ))
+
+;---------------------------------------------------------------------------
+; FORM2: converts p-h-r articulators to second formant frequency
+;---------------------------------------------------------------------------
+(defmacro form2 (p h r)
+  `(+ (* (+ (* (+ (- 1200) (* 1208 ,r)) (expt ,h 2))
+            (* (- 1320 (* 1328 ,r)) ,h) 
+            (- 118 (* 158 ,r))) 
+         (expt ,p 2))
+ 
+      (* (+ (* (- 1864 (* 1488 ,r)) (expt ,h 2)) 
+            (* (+ (- 2644) (* 1510 ,r)) ,h) 
+            (+ (- 561) (* 221 ,r)))
+         ,p)
+ 
+      (+ (* (+ (- 670) (* 490 ,r)) (expt ,h 2)) 
+         (* (- 1355  (* 697 ,r)) ,h)
+         (- 1517 (* 117 ,r)))
+      ))
+
+;---------------------------------------------------------------------------
+; FORM3: converts p-h-r articulators to third formant frequency
+;---------------------------------------------------------------------------
+(defmacro form3 (p h r)
+  `(+ (* (+ (* (- 604 (* 604 ,r)) (expt ,h 2))
+            (* (- 1038 (* 1178 ,r)) ,h) 
+            (+ 246 (* 566 ,r))) 
+         (expt ,p 2))
+ 
+      (* (+ (* (+  (- 1150) (* 1262 ,r)) (expt ,h 2)) 
+            (* (+ (- 1443) (* 1313 ,r)) ,h) 
+            (- (- 317) (* 483 ,r)))
+         ,p)
+ 
+      (+ (* (- 1130 (* 836 ,r)) (expt ,h 2)) 
+         (* (+ (- 315)  (* 44 ,r)) ,h)
+         (- 2427 (* 127 ,r)))
+      ))
+
+
+;---------------------------------------------------------------------------
+; FORM4: converts p-h-r articulators to fourth formant frequency
+;---------------------------------------------------------------------------
+(defmacro form4 (p h r)
+  `(+ (* (+ (* (+ (- 1120) (* 16 ,r)) (expt ,h 2))
+            (* (- 1696 (* 180 ,r)) ,h) 
+            (+ 500 (* 522 ,r))) 
+         (expt ,p 2))
+ 
+      (* (+ (* (+  (- 140) (* 240 ,r)) (expt ,h 2)) 
+            (* (+ (- 578) (* 214 ,r)) ,h) 
+            (- (- 692) (* 419 ,r)))
+         ,p)
+ 
+      (+ (* (- 1480 (* 602 ,r)) (expt ,h 2)) 
+         (* (+ (- 1220)  (* 289 ,r)) ,h)
+         (- 3678 (* 178 ,r)))
+      ))
+
+;---------------------------------------------------------------------------
+; ADSR-SMOOTH: a standard ADSR envelope
+;---------------------------------------------------------------------------
+(defun adsr-smooth (signal dur)
+	 (mult signal (env 0.1 0.2 0.5  1.0  0.8  0.4 dur)))
+;---------------------------------------------------------------------------
+; VIBRATO: generates vibrato
+; vib-rate = vibrato rate in Hz
+; dur = duration in seconds
+;---------------------------------------------------------------------------
+(defun vibrato (vib-rate dur)
+	(osc (hz-to-step vib-rate) dur))
+
+;---------------------------------------------------------------------------
+; PULSE-TABLE: build table for generating a pulse signal
+; harm = number of harmonics
+;---------------------------------------------------------------------------
+(defun pulse-table (harm)
+  (abs-env ;prevent any timewarping in the following
+    (let ((table (build-harmonic 1 2048)))
+      (cond ((> harm 1) ;sum remaining harmonics
+		 (setf harm (- harm 1))
+             (dotimes (i harm)
+               (setf table (sum table (build-harmonic (1+ i) 2048))))))
+      table)))
+
+;---------------------------------------------------------------------------
+; PULSE-WITH-VIBRATO: generate pulse with vibrato
+; step = pitch in steps
+; duration = duration in seconds
+; vib-rate = vibrato rate in Hz
+;---------------------------------------------------------------------------
+(defun pulse-with-vibrato (step duration vib-rate)
+  (let (harm freq)
+    (setf freq (step-to-hz step))
+    (setf harm (truncate (/ 22050 (* 2 freq))))
+    (setf table (scale (/ 1.0 harm) (pulse-table harm)))
+    (fmosc step (vibrato vib-rate duration) (list table (hz-to-step 1) t))))
+
+;---------------------------------------------------------------------------
+; VOICING-SOURCE: generate voicing source: pulse with vibrato + LPFs
+; step = pitch in steps
+; duration = duration in seconds
+; vib-rate = vibrato rate in Hz
+;---------------------------------------------------------------------------
+(defun voicing-source (step duration vib-rate)
+	(lp
+	  (lp 
+	    (pulse-with-vibrato step duration vib-rate) 
+		(*  1.414 (* 2 (step-to-hz step)))) 
+		(*  1.414 (* 4 (step-to-hz step)))))
+	
+;---------------------------------------------------------------------------
+; NOISE-SOURCE: generate noise source: noise + offset oscillator + LPF
+; step = pitch in steps
+; duration = duration in seconds
+; vib-rate = vibrato rate in Hz
+;---------------------------------------------------------------------------
+(defun noise-source (step duration vib-rate)
+	(lp 
+	  (sum 
+		(noise duration)
+		(fmosc step (vibrato vib-rate duration))) 8000))
+
+;---------------------------------------------------------------------------
+; SOURCE: generate source signal: voicing + noise sources
+; freq = fundamental frequency in Hz
+; duration = duration in seconds
+; vib-rate = vibrato rate in Hz
+; voicing-scale = percentage of voicing in the resulting signal (0.0 -> 1.0)
+; noise-scale = percentage of noise in the resulting signal (0.0 -> 1.0)
+;---------------------------------------------------------------------------
+(defun source (freq duration vib-rate voicing-scale noise-scale)
+	(sum
+		(scale voicing-scale (voicing-source (hz-to-step freq) duration vib-rate))
+		(scale noise-scale (noise-source (hz-to-step freq) duration vib-rate))))
+
+
+;---------------------------------------------------------------------------
+; MAKE-SPECTRUM: formant filters
+; freq = fundamental frequency in Hz
+; dur = duration in seconds
+; vib-rate = vibrato rate in Hz
+; v-scale = amplitude scaling for the voicing source
+; n-scale = amplitude scaling for the noise source 
+; p = horizontal position of the tongue (0.0 = front -> 1.0 = back) 
+; h = vertical position of the tongue (0.0 = low -> 1.0 = high)
+; r = rouding of the lips (0.0 = spread -> 1.0 = rounded)
+;---------------------------------------------------------------------------
+(defun make-spectrum (freq dur vib-rate v-scale n-scale p h r)
+	(let ((src (source freq dur vib-rate v-scale n-scale)))
+ 		(setf spectrum
+  			(sim	
+   				(reson src (form1 p h r) 50 1)
+   				(reson (scale-db (- 10) src) (form2 p h r) 70 1)
+   				(reson (scale-db (- 14) src) (form3 p h r) 110 1)
+   				(reson (scale-db (- 20) src) (form4 p h r) 250 1)))))
+			
+;---------------------------------------------------------------------------
+; SYNTHESISE: the synthesise function
+; Simplified version of the instrument used by the agents discussed in Chapter 6.
+; f0 = pitch frequency
+; w1 = amplitude of voicing source (min = 0.0 max = 1.0)
+; w2 = amplitude of noise source (min = 0.0 max = 1.0)
+; a = horizontal position of the tongue (0.0 = front -> 1.0 = back) 
+; b = vertical position of the tongue (0.0 = low -> 1.0 = high)
+; c = rouding of the lips (0.0 = spread -> 1.0 = rounded)
+; fm = vibrato rate (in Hz)
+; h = duration in seconds
+;---------------------------------------------------------------------------
+(defun synthesise (f0 w1 w2 a b c fm h)
+	(adsr-smooth (make-spectrum f0 h fm w1 w2 a b c) h))
+		
+;=== The code for the instrument ends here ===
+
+;---------------------------------------------------------------------------
+; Test the SYNTHESISE function with different positions of the articulators
+;
+; Running steps:
+; 1 - run Nyquist
+; 2 - load "articulator.lsp"
+; 3 - type (play (vowel-1)) to synthesise the first test, and so on
+;---------------------------------------------------------------------------
+(defun vowel-1 ()
+	(synthesise 220 1.0 0.005 0.0 0.0 0.0 5.6 1.0))
+
+(defun vowel-2 ()
+	(synthesise 220 1.0 0.005 0.0 0.0 1.0 5.6 1.0))
+
+(defun vowel-3 ()
+	(synthesise 220 1.0 0.005 0.5 0.0 0.0 5.6 1.0))
+
+(defun vowel-4 ()
+	(synthesise 220 1.0 0.005 0.5 0.0 1.0 5.6 1.0))
+
+(defun vowel-5 ()
+	(synthesise 220 1.0 0.005 1.0 0.0 0.0 5.6 1.0))
+
+(defun vowel-6 ()
+	(synthesise 220 1.0 0.005 1.0 0.0 1.0 5.6 1.0))
+
+(defun vowel-7 ()
+	(synthesise 220 1.0 0.005 0.0 0.5 0.0 5.6 1.0))
+
+(defun vowel-8 ()
+	(synthesise 220 1.0 0.005 0.0 0.5 1.0 5.6 1.0))
+
+(defun vowel-9 ()
+	(synthesise 220 1.0 0.005 0.5 0.5 0.0 5.6 1.0))
+
+(defun vowel-10 ()
+	(synthesise 220 1.0 0.005 0.5 0.5 1.0 5.6 1.0))
+
+(defun vowel-11 ()
+	(synthesise 220 1.0 0.005 1.0 0.5 0.0 5.6 1.0))
+
+(defun vowel-12 ()
+	(synthesise 220 1.0 0.005 1.0 0.5 1.0 5.6 1.0))
+
+(defun vowel-13 ()
+	(synthesise 220 1.0 0.005 0.0 1.0 0.0 5.6 1.0))
+
+(defun vowel-14 ()
+	(synthesise 220 1.0 0.005 0.0 1.0 1.0 5.6 1.0))
+
+(defun vowel-15 ()
+	(synthesise 220 1.0 0.005 0.5 1.0 0.0 5.6 1.0))
+
+(defun vowel-16 ()
+	(synthesise 220 1.0 0.005 0.5 1.0 1.0 5.6 1.0))
+
+(defun vowel-17 ()
+	(synthesise 220 1.0 0.005 1.0 1.0 0.0 5.6 1.0))
+
+(defun vowel-18 ()
+	(synthesise 220 1.0 0.005 1.0 1.0 1.0 5.6 1.0))
+ 
+;; play everything
+(defun vowel-n (n) (funcall (intern (format nil "VOWEL-~A" n))))
+
+(defun play-all-vowels ()
+  (autonorm-off)
+  (dotimes (i 18) (play (scale 20 (vowel-n (1+ i)))))
+  (autonorm-on))
+
+; (play-all-vowels) will play everything in sequence
+
+ + diff --git a/demos/warble_tutorial.htm b/demos/warble_tutorial.htm new file mode 100644 index 0000000..15b08f8 --- /dev/null +++ b/demos/warble_tutorial.htm @@ -0,0 +1,76 @@ + + + + + +Warble Tutorial + + + + +

Warble Tutorial

+ +

The warble function by Alex illustrates the use of AM and FM oscillators to create an +"analog" electronic synthesizer sound.

+ +
(defun warble (&optional (dur 1) (pch 60))
+  (stretch dur 
+    (sum (mult
+           (env 0.017 0.1 0.004 1 0.7 0.8 1)
+           (amosc pch (fmosc (hz-to-step 8) 
+                             (pwl 0 4 0.2 -4 0.56 9 0.7 0 1 -8 1))))
+         (mult (stretch 0.96 (env 0.2 0.09 0.07 0.92 0.8 0.6 1))
+               (amosc pch (fmosc (* pch 1.414) 
+                                 (pwl 0.2 80 0.5 4 0.9 1120 1 200 1)))))))
+ +

This sound is the sum of two components. To find the two components, look for (mult +...). Each of these components is the product of an envelope and an AM oscillator. +The first one modulates the AM oscillator with a low frequency (about 8 Hz) sinusoid +produced by an FM oscillator. The modulator varies in frequency according to a piece-wise +linear envelope.

+ +

The second component is similar, but uses a much higher modulating frequency in the +audio range, producing a ring-modulation effect. Another piece-wise linear envelope sweeps +the modulator frequency by as much as 1120 Hz.

+ +

Thicker Texture

+ +

A thicker texture can be obtained by playing copies of warble together with slight +parameter changes. Here is an example:

+ +
(defun thicker ()
+  (sim (scale 0.5 (at 0.00 (warble 8 48)))
+       (scale 0.3 (at 0.05 (warble 8.05 47.9)))))
+ +


+Another FM Sound

+ +

The following produces another analog-sounding FM texture:

+ +
(defun mod (dur) 
+  (stretch dur
+    (mult (pwl 0 1000 .2 200 .5 8000 1 100 1)
+	  (fmosc c4 (pwl 0 1 .5 3.25 1 .74 1)))))
+
+(defun blurp (dur)
+  (fmosc c3 (mult (osc 07 dur) (mod dur))))
+ +

This example relies on a combination of AM and FM: the output is from an FM oscillator, +but its modulator is formed by multiplying (AM) two oscillators. The first is low +frequency (about 12 Hz), giving a warbling sound, and the second, generated by (mod +dur), is another FM oscillator. It appears that the modulation generated by the +piece-wise linear function is almost insignificant. You might try scaling the expression +(pwl 0 1 .5 3.25 1 .74 1) in mod by varying amounts to see what happens.

+ +

The original duration of blurp was 3.1 (seconds), but longer versions are +interesting and reveal more detail.

+ +

Yet Another Sound

+ +

See Other Sounds Using Ring in Vinal Scratch +Tutorial for another example.

+ +
+
+/body> + diff --git a/demos/wind_tutorial.htm b/demos/wind_tutorial.htm new file mode 100644 index 0000000..531724f --- /dev/null +++ b/demos/wind_tutorial.htm @@ -0,0 +1,43 @@ + + + +Wind Tutorial + + + + +

Wind Tutorial

+ +

This page describes a "wind" effect created by Alex. The basic function is as +follows:

+ +
(defun wind (&optional (dur 3) (scal 3) (cps 590) (bw 40))
+  (stretch dur
+    (mult (env 0.07 0.08 0.1 1 0.6 0.8 1)
+	  (sum 
+	    (reson (scale scal (noise)) cps bw 2)
+	    (reson (scale (mult scal 1.13) (noise)) 
+                   (mult cps (pwl 0 0.74 0.2 0.96 0.5 0.8 0.75 1.16 0.9 0.97 1 0.74 1))
+                   (mult bw 1.042)
+                   2)))))
+ +

The basic idea is to use bandpassed noise to create the sound of wind. In this example, +two bandpass filters are added together. The first uses a fixed center frequency and +bandwidth, and the second uses a piece-wise linear function to control the center +frequency. The entire sound is multiplied by an envelope and stretched to the desired +duration. Note how several optional parameters can be used to change the default behavior.

+ +

A slight elaboration of the wind function uses several copies of wind in sequence with +slight overlap:

+ +
(defun multiwind ()
+  (simrep (i 4) (at (* i 2.9) (wind))))
+ +

One problem with this approach is that the wind sound becomes periodic. This could be +solved by using noise or random numbers to generate the center frequency variation rather +than a fixed envelope.

+ +

 

+ + + diff --git a/doc/arcsine-fig.gif b/doc/arcsine-fig.gif new file mode 100644 index 0000000..ef9526c Binary files /dev/null and b/doc/arcsine-fig.gif differ diff --git a/doc/bernoulli-fig.gif b/doc/bernoulli-fig.gif new file mode 100644 index 0000000..a0d8567 Binary files /dev/null and b/doc/bernoulli-fig.gif differ diff --git a/doc/beta-fig.gif b/doc/beta-fig.gif new file mode 100644 index 0000000..13a2f00 Binary files /dev/null and b/doc/beta-fig.gif differ diff --git a/doc/bilateral-fig.gif b/doc/bilateral-fig.gif new file mode 100644 index 0000000..48d90c6 Binary files /dev/null and b/doc/bilateral-fig.gif differ diff --git a/doc/binomial-fig.gif b/doc/binomial-fig.gif new file mode 100644 index 0000000..55c769e Binary files /dev/null and b/doc/binomial-fig.gif differ diff --git a/doc/cauchy-fig.gif b/doc/cauchy-fig.gif new file mode 100644 index 0000000..ffbe42e Binary files /dev/null and b/doc/cauchy-fig.gif differ diff --git a/doc/exponential-fig.gif b/doc/exponential-fig.gif new file mode 100644 index 0000000..3dc5b2d Binary files /dev/null and b/doc/exponential-fig.gif differ diff --git a/doc/fig1.gif b/doc/fig1.gif new file mode 100644 index 0000000..db395c4 Binary files /dev/null and b/doc/fig1.gif differ diff --git a/doc/fig2.gif b/doc/fig2.gif new file mode 100644 index 0000000..f9de373 Binary files /dev/null and b/doc/fig2.gif differ diff --git a/doc/fig3.gif b/doc/fig3.gif new file mode 100644 index 0000000..45f99e3 Binary files /dev/null and b/doc/fig3.gif differ diff --git a/doc/fig4.gif b/doc/fig4.gif new file mode 100644 index 0000000..be409e4 Binary files /dev/null and b/doc/fig4.gif differ diff --git a/doc/fig5.gif b/doc/fig5.gif new file mode 100644 index 0000000..e2f9c10 Binary files /dev/null and b/doc/fig5.gif differ diff --git a/doc/fig6.gif b/doc/fig6.gif new file mode 100644 index 0000000..3829403 Binary files /dev/null and b/doc/fig6.gif differ diff --git a/doc/foot.html b/doc/foot.html new file mode 100644 index 0000000..572b18b --- /dev/null +++ b/doc/foot.html @@ -0,0 +1,49 @@ +Footnotes + +

Footnotes

+ 1. Most behaviors will stop at time 1, warped according to *warp* to some real time, but this is by convention and is not a direct specification. +

+ 2. Since XLISP does not support multiple value returns, multiple value returns are simulated by having the function assign additional return values in a list to the global variable *rslt*. Since this is a global, it should be inspected or copied immediately after the function return to insure that return values are not overwritten by another function. +

+ 3. This +is probably a mistake since sample rate is implied by sound. This parameter +may be removed in a future release. +

+ 4. This +is probably a mistake since sample rate is implied by sound. This parameter +may be removed in a future release. +

+ 5. This is probably a mistake since sample rate is implied +by sound. This parameter may be removed in a future release. +

+ 6. To be consistent, a blank line ought to specify zero attributes and +generate a note that inherits all of its attributes from the previous one. +Adagio is intentionally inconsistent in this respect. +

+ 7. My TX816 Owner's Manual gives an incorrect format for the +change parameter sysex command (according to the manual, there is no data +in the message!) I am assuming that the data should be the last byte before +the EOX and that there is no byte count. If you are reading this, assume +that I have not tested this guess, nor have I tested this example. +

+ 8. This is not part of standard XLISP nor is it built-in. Nyquist defines it though. +

+ 9. This is not a standard XLISP 2.0 function. +

+ 10. This is not a standard XLISP 2.0 function. +

+ 11. This is not a standard XLISP 2.0 function. +

+ 12. This is not a standard XLISP 2.0 function. +

+ 13. This is not a standard XLISP 2.0 function. +

+ 14. This is not a standard XLISP 2.0 function. +

+ 15. This is not a standard XLISP 2.0 function. +

+ 16. This is not a standard XLISP 2.0 function. +

+ 17. This is not a standard XLISP 2.0 function. +

+ diff --git a/doc/gamma-fig.gif b/doc/gamma-fig.gif new file mode 100644 index 0000000..60ca9ab Binary files /dev/null and b/doc/gamma-fig.gif differ diff --git a/doc/gaussian-fig.gif b/doc/gaussian-fig.gif new file mode 100644 index 0000000..a1b7a2d Binary files /dev/null and b/doc/gaussian-fig.gif differ diff --git a/doc/geometric-fig.gif b/doc/geometric-fig.gif new file mode 100644 index 0000000..c779ca6 Binary files /dev/null and b/doc/geometric-fig.gif differ diff --git a/doc/guide.html b/doc/guide.html new file mode 100644 index 0000000..0212d52 --- /dev/null +++ b/doc/guide.html @@ -0,0 +1,1949 @@ +Links +

+!-~ +A +B +C +D +E +F +G +H +
+I +J +K +L +M +N +O +P +Q +
+R +S +T +U +V +W +X +Y +Z +
+

+ +

Table of Contents

+
+

Index

+

!-~

+TOP
+! 1 2
+!=
+!call
+!clock
+!csec
+!def
+!end
+!msec
+!ramp
+!rate
+!seti
+!setv
+!tempo
+# (adagio articulation)
+#?, sal
+#define'd macros
+#f
+#t
+%
+% (adagio thirtysecond note)
+&
+&=
+* 1 2
+*=
+*a4-hertz* 1 2
+*applyhook*
+*audio-markers*
+*autonorm*
+*autonorm-max-samples*
+*autonorm-previous-peak*
+*autonorm-target*
+*autonorm-type*
+*autonormflag*
+*breakenable* 1 2 3 4
+*control-srate* 1 2 3
+*debug-io*
+*default-control-srate*
+*default-plot-file*
+*default-sf-bits*
+*default-sf-dir* 1 2
+*default-sf-format*
+*default-sf-srate* 1 2
+*default-sound-srate*
+*error-output*
+*evalhook*
+*file-separator*
+*float-format*
+*gc-flag*
+*gc-hook*
+*integer-format*
+*loud*
+*obarray*
+*print-case*
+*readtable* 1 2
+*rslt* 1 2
+*sound-srate* 1 2 3
+*soundenable*
+*standard-input*
+*standard-output*
+*start*
+*stop*
+*sustain*
+*table*
+*trace-output*
+*tracelimit* 1 2
+*tracelist*
+*tracenable* 1 2 3
+*transpose*
+*unbound*
+*warp* 1 2 3
++ 1 2
++=
+, (adagio)
+- 1 2
+. (adagio)
+/ 1 2
+/=
+1+
+1-
+:answer
+:class
+:isa
+:isnew 1 2
+:new
+:show
+; (adagio)
+< 1 2
+<= 1 2 3
+= 1 2
+> 1 2
+>= 1 2 3
+@
+@=
+@@
+^
+^ (adagio sixtyfourth note)
+^=
+|
+~
+~ (adagio)
+~=
+~~
+

A

+TOP
+*a4-hertz* 1 2
+A440
+Abs
+Abs-env
+Absolute stretch, sal
+Absolute time shift, sal
+Absolute value 1 2
+Access samples
+Accidentals
+Accumulate +pattern
+Accumulation pattern
+Adagio
+# (adagio articulation)
+^ (adagio sixtyfourth note)
+% (adagio thirtysecond note)
+~ (adagio)
+; (adagio)
+, (adagio)
+. (adagio)
+Add +offset to sound
+Add to file samples
+Add-action-to-workspace
+Add-to-workspace
+Additive synthesis, gongs
+Address-of
+Aftertouch
+Agc
+Algorithmic composition
+All pass filter
+Alloc
+Allpass2
+Allpoles-from-lpc
+Alpass
+Alpass filter
+Amosc
+Analog synthesizer
+And
+:answer
+Append
+Apply
+Apply-banded-bass-boost
+Apply-banded-delay
+Apply-banded-treble-boost
+*applyhook*
+Approximation
+Arc-sine-dist
+Arcsine distribution
+Aref
+Areson
+Args
+Arguments to a lisp function
+Arithmetic functions
+Arpeggiator
+Array from sound
+Array functions
+Array notation, sal
+Arrayp
+Articulation 1 2
+Assoc
+Asterisk
+At
+At transformation
+At, sal
+At-abs
+At-abs, sal
+Atan
+Atom
+Atone
+Attributes
+Audio markers
+*audio-markers*
+Automatic gain control
+*autonorm*
+*autonorm-max-samples*
+Autonorm-off 1 2 3
+Autonorm-on 1 2 3
+*autonorm-previous-peak*
+*autonorm-target*
+*autonorm-type*
+*autonormflag*
+Average
+

B

+TOP
+Backquote
+Backward
+Baktrace
+Banded bass boost
+Banded delay
+Banded treble boost
+Bandfx.lsp
+Bandpass filter
+Bandpass2
+Bartok
+Begin
+Behavioral abstraction
+Behaviors
+Bell sound 1 2
+Bernoulli distribution
+Bernoulli-dist
+Beta distribution
+Beta-dist
+Big endian
+Bigendianp
+Bilateral exponential distribution
+Bilateral-exponential-dist
+Binary files
+Binomial distribution
+Binomial-dist
+Biquad
+Biquad-m
+Bitwise logical functions
+Blank
+Block
+Both-case-p
+Boundp
+Bowed
+Bowed-freq
+Brass sound
+Break 1 2
+Break button
+*breakenable* 1 2 3 4
+Browse button
+Browser, jnyqide
+Build-harmonic 1 2
+Button bar
+Buzz
+

C

+TOP
+!call
+Call command
+Car
+Case 1 2
+Case-insensitive
+Catch
+Cauchy distribution
+Cauchy-dist
+Cdr
+Cerror
+Change directory
+Char
+Char-code
+Char-downcase
+Char-equalp
+Char-greaterp
+Char-int
+Char-lessp
+Char-not-equalp
+Char-not-greaterp
+Char-not-lessp
+Char-upcase
+Char/=
+Char<
+Char<=
+Char=
+Char>
+Char>=
+Character functions
+Characterp
+Chdir, sal
+Chorus 1 2 3 4 5
+Clarinet 1 2 3
+Clarinet sound
+Clarinet-all
+Clarinet-freq
+Class
+:class
+Class class
+Clean-up
+Clip 1 2 3
+Clipping repair
+!clock
+Clock
+Clock command
+Close
+Co-termination
+Code-char
+Comb
+Comb filter
+Combination
+Command loop
+Commas
+Comment 1 2
+Comments
+Compose
+Compress
+Compress-map
+Compressor
+Concatenate strings
+Cond
+Conditional expression, sal
+Configure nyquist
+Congen
+Cons
+Console, xlisp
+Consp
+Const
+Constant function
+Continue
+Continuous-control-warp
+Continuous-sound-warp
+Contour generator
+Control
+Control change
+Control characters, xlisp
+Control constructs
+Control-a
+*control-srate* 1 2 3
+Control-srate-abs
+Control-warp
+Convert sound to array
+Convolution
+Convolve
+Copier +pattern
+Cos
+!csec
+Cue
+Cue-file
+Current-path
+Cxxr
+Cxxxr
+Cxxxxr
+Cycle pattern
+

D

+TOP
+Darwiinremoteosc
+Data types
+Db-average
+Db-to-linear
+Db0
+Db1
+Db10
+*debug-io*
+Debugging 1 2 3 4 5
+Decf
+Decrement
+!def
+Default
+Default +durations
+Default sample rate
+Default sound file directory
+Default time
+*default-control-srate*
+*default-plot-file*
+*default-sf-bits*
+*default-sf-dir* 1 2
+*default-sf-format*
+*default-sf-srate* 1 2
+*default-sound-srate*
+Define function
+Define variable
+#define'd macros
+Defining behaviors
+Defmacro
+Defun
+Delay
+Delay, +variable
+Delay, variable
+Delete
+Delete-if
+Delete-if-not
+Demos, bell sound
+Demos, distortion
+Demos, drum machine
+Demos, drum sound
+Demos, fft
+Demos, fm
+Demos, fm synthesis
+Demos, formants
+Demos, gong sound
+Demos, lpc
+Demos, midi
+Demos, piano
+Demos, pitch change
+Demos, rhythmic pattern
+Demos, ring modulation
+Demos, sample-by-sample
+Demos, scratch tutorial
+Demos, shepard tones
+Demos, spectral analysis of a chord
+Demos, voice synthesis
+Demos, wind sound
+Derivative
+Describe
+Destructive list functions
+Developing code
+Diff
+Difference
+Difference of sounds
+Digit-char
+Digit-char-p
+Directory listing
+Directory, default sound file
+Display statement, sal
+Distortion tutorial
+Distributions, probability
+Division
+Do
+Do*
+Dolby pro-logic
+Dolby surround
+Dolist
+Doppler effect
+Dot
+Dotimes
+Dotted durations
+Dribble
+Drum
+Drum +samples
+Drum machine 1 2
+Drum sound
+Drum-loop
+Dsp in lisp 1 2
+Dtmf
+Dtmf-tone
+Dubugging
+Duration 1 2
+Duration notation
+Duration of +another sound
+Dx7
+Dynamic markings
+

E

+TOP
+Echo
+Echoenabled
+Editor for envelopes
+Effect, + reverberation 1 2
+Effect, +reverberation
+Effect, chorus 1 2 3
+Effect, flange
+Effect, pitch shift 1 2
+Effect, reverberation 1 2
+Effect, stereo
+Effect, stereo pan
+Effect, swap channels
+Effect, widen
+Effects, phaser
+Eighth note 1 2
+Elapsed audio time
+Emacs, using nyquist with
+Empty list
+!end
+End
+End command
+Endian
+Endless tones
+Endp
+Env 1 2
+Env-note
+Envedit button
+Envelope
+Envelope editor
+Envelope follower 1 2
+Envelope generator
+Envelopes
+Environment
+Environment variables
+Eq
+Eq button
+Eq-band
+Eq-highshelf
+Eq-lowshelf
+Eql
+Equal
+Equalization 1 2 3 4
+Equalization editor
+Error
+Error handling
+*error-output*
+Errors
+Errset
+Estimate frequency
+Eval
+Eval pattern
+Evalhook
+*evalhook*
+Evaluation functions
+Evaluator
+Evenp
+Event-dur
+Event-end
+Event-expression
+Event-get-attr
+Event-has-attr
+Event-set-attr
+Event-set-dur
+Event-set-expression
+Event-set-time
+Event-time
+Exclamation point
+Exec statement, sal
+Exit
+Exit statement, sal
+Exp
+Exp-dec
+Expand
+Exponent
+Exponential
+Exponential distribution
+Exponential envelope
+Exponential-dist
+Expr-get-attr
+Expr-has-attr
+Expr-set-attr
+Expression pattern
+Expressions, sal
+Expt
+Extending xlisp
+Extract
+Extract-abs
+

F

+TOP
+#f
+F (adagio dynamic)
+F (adagio flat)
+Fast fourier transform tutorial
+Fboundp
+Feedback fm oscillator
+Feedback-delay
+Feel factor
+Ff (adagio dynamic)
+Fff (adagio dynamic)
+Fft
+Fft tutorial
+File i/o functions 1 2
+*file-separator*
+Filep
+Filter example
+Finally clause, sal
+Find string
+Find-in-xlisp-path
+Fir filter
+First
+First derivative
+Flange
+Flange effect
+Flat
+Flatc
+Flatsize
+Flet
+Float
+*float-format*
+Floatp
+Flute
+Flute sound
+Flute-all
+Flute-freq
+Fm synthesis
+Fmfb
+Fmlfo
+Fmosc
+Fn button
+Follow
+Follower
+Force-srate
+Format
+Fourth
+Frequency analysis
+Frequency modulation
+Full path name
+Funcall
+Function
+Function calls, sal
+Function, sal
+Fundamenal frequency +estimation
+

G

+TOP
+Gain
+Gamma-dist
+Gate 1 2
+Gaussian distribution
+Gaussian-dist
+Gc
+*gc-flag*
+*gc-hook*
+Gcd
+Gen05
+Gensym
+Geometric distribution
+Geometric-dist
+Get
+Get char
+Get-duration
+Get-env
+Get-lambda-expression
+Get-loud
+Get-output-stream-list
+Get-output-stream-string
+Get-slider-value
+Get-sustain
+Get-temp-path
+Get-transpose
+Get-user
+Get-warp
+Getenv
+Global variables
+Global variables, sal
+Go
+Gong sounds
+Granular synthesis
+Graphical envelope editor
+Graphical equalization
+Graphical equalizer
+Grindef
+

H

+TOP
+H
+H (adagio half note)
+Half note 1 2
+Harmonic
+Hash
+Hd
+Header file format
+Heap pattern
+High-pass filter
+Highpass2
+Highpass4
+Highpass6
+Highpass8
+Hp
+Ht
+Hyperbolic-cosine-dist
+Hz-to-step
+Hzosc
+

I

+TOP
+I
+I (adagio eight note)
+Iannis xenakis
+Id
+Ide
+If
+If statement, sal
+Ifft
+Incf
+Increment
+Info
+Info button
+Input from a file
+Input/output functions
+Installation
+Int-char
+*integer-format*
+Integerp
+Integrate
+Integrated development environment
+Intern
+Interoperability, sal and lisp
+Interpolate
+Intersection
+Intgen
+Inverse
+Inverse fft
+:isa
+:isnew 1 2
+It
+

J

+TOP
+Jcrev
+Jitter
+

K

+TOP
+K (adagio control)
+Karplus-strong
+Karplus-strong synthesis
+Keyword parameters
+

L

+TOP
+Labels
+Lambda
+Lambda lists
+Last
+Latency
+Legato 1 2
+Length
+Length pattern
+Length-of-beat
+Let
+Let*
+Lexical conventions
+Lf
+Lf (adagio dynamic)
+Lff
+Lff (adagio dynamic)
+Lfff
+Lfff (adagio dynamic)
+Lfo
+Libraries
+Limit
+Limiter
+Line pattern
+Linear distribution
+Linear interpolation
+Linear prediction
+Linear prediction tutorial
+Linear-dist
+Linear-to-db
+Lisp button
+Lisp dsp 1 2
+Lisp include files
+List
+List directory
+List functions
+Listdir
+Listing of lisp function
+Listp
+Little endian
+Lmf
+Lmf (adagio dynamic)
+Lmp
+Lmp (adagio dynamic)
+Load
+Load button
+Load file conditionally
+Load statement, sal
+Local-to-global
+Log
+Log function
+Logand
+Logical-stop
+Logior
+Logistic distribution
+Logistic-dist
+Lognot
+Logorithm
+Logxor
+Loop
+Loop examples, sal
+Loop statement, sal
+Looping constructs
+Loud
+*loud*
+Loud-abs
+Loudness 1 2
+Low-frequency oscillator
+Low-pass filter 1 2
+Lower-case-p
+Lowpass2
+Lowpass4
+Lowpass6
+Lowpass8
+Lp 1 2
+Lp (adagio dynamic)
+Lpc
+Lpc tutorial
+Lpc-frame-err 1 2
+Lpc-frame-filter-coefs 1 2
+Lpc-frame-rms1 1 2
+Lpc-frame-rms2 1 2
+Lpp
+Lpp (adagio dynamic)
+Lppp
+Lppp (adagio dynamic)
+Lpreson
+

M

+TOP
+M (adagio control)
+Macroexpand
+Macroexpand-1
+Macrolet
+Make-accumulate
+Make-accumulation
+Make-array
+Make-copier
+Make-cycle
+Make-eval
+Make-heap
+Make-length
+Make-line
+Make-lpanal-iterator
+Make-lpc-file-iterator
+Make-markov
+Make-palindrome
+Make-product
+Make-random
+Make-string-input-stream
+Make-string-output-stream
+Make-sum
+Make-symbol
+Make-window
+Maketable
+Mandolin
+Manipulation of scores
+Mapc
+Mapcar
+Mapl
+Maplist
+Mark button
+Markers, audio
+Markov analysis
+Markov pattern
+Markov-create-rules
+Max
+Maximum 1 2
+Maximum amplitude 1 2
+Maximum of two sounds
+Member
+Memory +usage
+Mf (adagio dynamic)
+Middle c
+Midi
+Midi clock
+Midi file 1 2 3
+Midi program
+Midi-show
+Midi-show-file
+Mikrokosmos
+Min
+Minimoog
+Minimum 1 2
+Minusp
+Mix
+Mix to file
+Mkwave
+Modalbar
+Modulation wheel
+Modulo (rem
+Mono to stereo
+Moog
+Moving average
+Mp (adagio dynamic)
+!msec
+Mult 1 2 3
+Multichannel sounds
+Multiple band effects
+Multiple commands
+Multiple tempi
+Multiplication
+Multiply signals
+My-note
+

N

+TOP
+N (adagio next)
+Natural
+Natural log
+Nband
+Nband-range
+Nconc
+Nested transformations
+:new
+Newfile button
+Next adagio command
+Next in pattern
+Next pattern
+Nintendo wiimote
+Noise
+Noise gate
+Noise-gate
+Normalization
+Not
+Not enough memory for normalization
+Notch filter
+Notch2
+Note list
+Nrev
+Nstring-downcase
+Nstring-upcase
+Nth
+Nthcdr
+Null
+Numberp
+Ny:all
+Nyquistide
+

O

+TOP
+O (adagio control)
+*obarray*
+Object
+Object class
+Objectp
+Objects
+Octave specification 1 2
+Oddp
+Offset
+Offset to a sound
+Omissions
+Oneshot
+Open 1 2
+Open sound control 1 2
+Open-binary
+Openfile button
+Or
+Osc 1 2 3
+Osc-enable
+Osc-note
+Osc-pulse
+Osc-saw
+Osc-tri
+Output samples to file
+Output to a file
+Overlap
+Overwrite samples
+

P

+TOP
+P (adagio dynamic)
+P (adagio pitch)
+Palindrome pattern
+Pan 1 2
+Pan, stereo
+Parameters, keyword
+Params-scale
+Params-transpose
+Partial
+Path, +current
+Pattern, +length
+Pattern, +window
+Pattern, accumulate
+Pattern, accumulation
+Pattern, copier
+Pattern, cycle
+Pattern, eval
+Pattern, expression
+Pattern, heap
+Pattern, line
+Pattern, markov
+Pattern, palindrome
+Pattern, product
+Pattern, random
+Pattern, sum
+Patternp
+Peak
+Peak amplitude
+Peak, maximum amplitude
+Peek
+Peek-char
+Period +estimation
+Phaser
+Physical model
+Piano synthesizer
+Piano synthesizer tutorial
+Piano-midi
+Piano-midi2file
+Piano-note
+Piano-note-2
+Piece-wise
+Piece-wise linear
+Pitch 1 2
+Pitch bend
+Pitch detection
+Pitch notation
+Pitch shift 1 2
+Pitch shifting
+Pitshift
+Pl-center
+Pl-doppler
+Pl-left
+Pl-pan2d
+Pl-position
+Pl-rear
+Pl-right
+Play 1 2
+Play in reverse
+Play-file
+Plot
+Pluck
+Plucked string
+Plusp
+Poisson distribution
+Poisson-dist
+Poke
+Polyrhythm
+Pop
+Portamento switch
+Power
+Pp (adagio dynamic)
+Ppp (adagio dynamic)
+Pprint
+Prcrev
+Predicate functions
+Preset
+Prin1
+Princ
+Print
+Print midi file
+Print statement, sal
+*print-case*
+Probability distributions
+Prod 1 2
+Product
+Product pattern
+Profile
+Profiling
+Prog
+Prog*
+Prog1
+Prog2
+Progn
+Program
+Program change
+Progv
+Prologic
+Property list functions
+Psetq
+Pulse oscillator
+Pulse-width modulation
+Push
+Putprop
+Pwe
+Pwe-list
+Pwer
+Pwer-list
+Pwev
+Pwev-list
+Pwevr
+Pwevr-list
+Pwl
+Pwl-list
+Pwlr
+Pwlr-list
+Pwlv
+Pwlv-list
+Pwlvr
+Pwlvr-list
+

Q

+TOP
+Q
+Q (adagio quarter note)
+Qd
+Qt
+Quantize
+Quarter note 1 2
+Quote
+

R

+TOP
+R (adagio rest)
+!ramp
+Ramp
+Random 1 2 3
+Random pattern
+!rate
+Rate 1 2
+Read
+Read directory
+Read macros
+Read samples
+Read samples from file
+Read samples in reverse
+Read-byte
+Read-char
+Read-float
+Read-int
+Read-line
+*readtable* 1 2
+Readtables
+Real-random
+Recip
+Reciprocal
+Rem
+Remainder
+Remove
+Remove-if
+Remove-if-not
+Remprop
+Replace file samples
+Replay button
+Require-from
+Resample
+Resampling 1 2
+Rescaling
+Resolution
+Reson
+Rest 1 2
+Restore
+Rests
+Return
+Return statement, sal
+Return-from
+Reverb 1 2 3 4 5
+Reverse
+Reverse, sound
+Ring modulation
+Risset
+Rms 1 2
+Room
+Rplaca
+Rplacd
+Rrandom
+*rslt* 1 2
+

S

+TOP
+S
+S (adagio sharp)
+S (adagio sixteenth note)
+S-abs
+S-add-to
+S-exp
+S-log
+S-max 1 2
+S-min 1 2
+S-overwrite
+S-plot
+S-print-tree
+S-read
+S-read-reverse
+S-rest
+S-reverse
+S-save
+S-sqrt
+#?, sal
+Sal
+Sal and lisp
+Sal button
+Sal expressions
+Sample interpolation 1 2
+Sample rate, forcing
+Sample rates
+Sampler
+Samples 1 2
+Samples, +reading
+Sampling rate 1 2
+Save
+Save samples to file
+Save-lpc-file
+Save-workspace
+Savefile button
+Saving sound files
+Sawtooth oscillator
+Sawtooth wave
+Sax 1 2 3
+Sax-all
+Sax-freq
+Scale
+Scale-db
+Scale-srate
+Scan directory
+Score
+Score manipulation
+Score, musical
+Score-adjacent-events
+Score-append
+Score-apply
+Score-filter
+Score-filter-length
+Score-filter-overlap
+Score-gen 1 2 3
+Score-get-begin
+Score-get-end
+Score-indexof
+Score-last-indexof
+Score-merge
+Score-must-have-begin-end
+Score-play
+Score-print
+Score-randomize-start
+Score-read-smf
+Score-repeat
+Score-scale
+Score-select
+Score-set-begin
+Score-set-end
+Score-shift
+Score-sort
+Score-sorted
+Score-stretch
+Score-stretch-to-length
+Score-sustain
+Score-transpose
+Score-voice
+Score-write-smf
+Scratch sound
+Sd
+Second
+Sections, adagio
+Self
+Semicolon, adagio
+Seq
+Seqrep
+Sequence_example.htm
+Sequences 1 2
+Sequential behavior
+Set
+Set intersection
+Set statement, sal
+Set union
+Set-control-srate 1 2
+Set-difference
+Set-logical-stop
+Set-pitch-names
+Set-sound-srate 1 2
+Setdir
+Setf
+!seti
+Seti commnad
+Setq
+Setup nyquist
+Setup-console
+!setv
+Setv command
+Sf-granulate
+Sf-info
+Shape
+Sharp
+Shepard tones 1 2
+Shift-time
+:show
+Show midi file
+Show-lpc-data
+Signal composition 1 2
+Signal multiplication
+Signal-start
+Signal-stop
+Sim 1 2
+Simrep
+Simultaneous behavior
+Sin
+Sine
+Siosc
+Sitar
+Sixteenth note 1 2
+Sixtyfourth note
+Slope
+Smooth
+Snd-abs
+Snd-add
+Snd-allpoles
+Snd-alpass
+Snd-alpasscv
+Snd-alpassvv
+Snd-amosc
+Snd-areson
+Snd-aresoncv
+Snd-aresonvc
+Snd-aresonvv
+Snd-atone
+Snd-atonev
+Snd-avg
+Snd-bandedwg
+Snd-biquad
+Snd-bowed
+Snd-bowed-freq
+Snd-buzz
+Snd-chase
+Snd-clarinet
+Snd-clarinet-all
+Snd-clarinet-freq
+Snd-clip
+Snd-compose
+Snd-congen
+Snd-const
+Snd-convolve
+Snd-copy
+Snd-coterm
+Snd-delay
+Snd-delaycv
+Snd-down
+Snd-exp
+Snd-extent
+Snd-fetch
+Snd-fetch-array
+Snd-fft
+Snd-flatten
+Snd-flute
+Snd-flute-all
+Snd-flute-freq
+Snd-fmfb
+Snd-fmfbv
+Snd-fmosc
+Snd-follow
+Snd-from-array
+Snd-fromarraystream
+Snd-fromobject
+Snd-gate
+Snd-ifft
+Snd-inverse
+Snd-length
+Snd-log
+Snd-lpanal
+Snd-lpreson
+Snd-mandolin
+Snd-max
+Snd-maxsamp
+Snd-maxv
+Snd-modalbar
+Snd-multiseq
+Snd-normalize
+Snd-offset
+Snd-oneshot
+Snd-osc
+Snd-overwrite
+Snd-partial
+Snd-play
+Snd-pluck
+Snd-print
+Snd-print-tree 1 2
+Snd-prod
+Snd-pwl
+Snd-quantize
+Snd-read
+Snd-recip
+Snd-resample
+Snd-resamplev
+Snd-reson
+Snd-resoncv
+Snd-resonvc
+Snd-resonvv
+Snd-samples
+Snd-save
+Snd-sax
+Snd-sax-all
+Snd-sax-freq
+Snd-scale
+Snd-seq
+Snd-set-latency
+Snd-set-logical-stop
+Snd-shape
+Snd-sine
+Snd-siosc
+Snd-sitar
+Snd-slider
+Snd-sqrt
+Snd-srate
+Snd-sref
+Snd-stkchorus
+Snd-stkpitshift
+Snd-stkrev
+Snd-stop-time
+Snd-t0
+Snd-tapf
+Snd-tapv
+Snd-time
+Snd-tone
+Snd-tonev
+Snd-trigger
+Snd-up
+Snd-white
+Snd-xform
+Snd-yin
+Snd-zero
+Soften-clipping
+Sort
+Sound
+Sound browser, jnyqide
+Sound file directory default
+Sound file i/o
+Sound file info
+Sound from lisp data
+Sound, accessing point
+Sound, creating from array
+Sound-off 1 2
+Sound-on 1 2
+*sound-srate* 1 2 3
+Sound-srate-abs
+Sound-warp
+*soundenable*
+Soundfilename
+Soundp
+Sounds
+Sounds vs. behaviors
+Span
+Spatialization
+Special command
+Spectral interpolation
+Speed-dial
+Splines
+Sqrt
+Square oscillator
+Square root 1 2
+Srate
+Sref
+Sref-inverse
+St
+Stacatto
+Staccato
+Stack trace
+Standard midi file
+*standard-input*
+*standard-output*
+*start*
+Statements, sal
+Stats
+Step-to-hz
+Stereo
+Stereo pan
+Stereo panning
+Stereo-chorus
+Stereoize
+Stk banded waveguide
+Stk bowed 1 2
+Stk bowed string
+Stk bowed-freq
+Stk chorus 1 2
+Stk clarinet 1 2 3 4 5
+Stk flute 1 2 3 4 5 6
+Stk glass harmonica
+Stk jcreverb
+Stk mandolin
+Stk mandolon
+Stk modal bar 1 2
+Stk nreverb
+Stk pitch shift 1 2
+Stk prcreverb
+Stk reverb
+Stk sax 1 2 3 4
+Stk sitar 1 2
+Stk tibetan bowl
+Stk tuned bar
+Stk uniform bar
+Stkchorus
+Stochastic functions
+*stop*
+Strcat
+Streamp
+Stretch 1 2
+Stretch transformation
+Stretch, sal
+Stretch-abs
+Stretching sampled sounds
+String
+String functions
+String stream functions
+String synthesis
+String-downcase
+String-equalp
+String-greaterp
+String-left-trim
+String-lessp
+String-not-equalp
+String-not-greaterp
+String-not-lessp
+String-right-trim
+String-search
+String-trim
+String-upcase
+String/=
+String<
+String<=
+String=
+String>
+String>=
+Stringp
+Sublis
+Subseq
+Subset
+Subsetp
+Subst
+Suggestions
+Sum
+Sum +pattern
+Surround sound
+Sustain
+*sustain*
+Sustain-abs
+Swap channels
+Swapchannels
+Symbol functions
+Symbol-function
+Symbol-name
+Symbol-plist
+Symbol-value
+Symbolp
+Symbols
+Synchronization
+System functions
+

T

+TOP
+T
+#t
+T (adagio triplet)
+Table
+Table memory
+*table*
+Tagbody
+Tan
+Tap
+Tapped delay
+Tapv
+Temp file 1 2
+!tempo
+Tempo 1 2
+Temporary files
+Temporary sound files directory
+Terpri
+The format function
+The program feature
+Third
+Thirtysecond note
+Threshold
+Throw
+Time 1 2 3
+Time shift, sal
+Time structure
+Time units
+Timed-seq
+Tone
+Top button
+Top-level
+Touch tone
+Trace
+*trace-output*
+*tracelimit* 1 2
+*tracelist*
+*tracenable* 1 2 3
+Transformation environment
+Transformations 1 2
+Transpose
+*transpose*
+Transpose-abs
+Triangle oscillator
+Triangle wave
+Trigger
+Trill
+Triplet
+Triplet durations
+Truncate
+Tuba
+Tuning
+Tutorial, fm
+Type-of
+

U

+TOP
+U
+*unbound*
+Uniform random 1 2
+Union
+Unless
+Untrace
+Unwind-protect
+Upic
+Upper-case-p
+User name
+

V

+TOP
+V (adagio voice)
+Variable delay 1 2 3
+Variable-resample function
+Vector
+Velocity
+Vinal scratch
+Vocal sound
+Voice 1 2
+Voice synthesis
+Volume
+

W

+TOP
+W
+W (adagio whole note)
+Warble
+Warp
+*warp* 1 2 3
+Warp-abs
+Waveforms 1 2
+Waveshaping
+Wavetables 1 2
+Wd
+Wg-glass-harm
+Wg-tibetan-bowl
+Wg-tuned-bar
+Wg-uniform-bar
+When 1 2
+While
+Whole note 1 2
+Widen
+Wii controller
+Wind sound
+Wind_tutorial.htm
+Window initialization
+Window pattern
+With statement, sal
+Wood drum sound
+Workspace 1 2
+Write samples to file
+Write-byte
+Write-char
+Write-float
+Write-int
+Wt
+

X

+TOP
+X (adagio control)
+Xenakis
+Xlisp command loop
+Xlisp data types
+Xlisp evaluator
+Xlisp lexical conventions
+Xmusic
+

Y

+TOP
+Y (adagio control)
+Yin
+

Z

+TOP
+Z (adagio program) 1 2
+Zerop
+ diff --git a/doc/home.html b/doc/home.html new file mode 100644 index 0000000..32e6f46 --- /dev/null +++ b/doc/home.html @@ -0,0 +1,7 @@ +Nyquist Reference Manual + + + +<body><p>This browser does not support frames. +<p><a href=title.html>The no-frames version is here.</a> +</body> diff --git a/doc/hyperbolic-fig.gif b/doc/hyperbolic-fig.gif new file mode 100644 index 0000000..1290195 Binary files /dev/null and b/doc/hyperbolic-fig.gif differ diff --git a/doc/indx.html b/doc/indx.html new file mode 100644 index 0000000..bd94f57 --- /dev/null +++ b/doc/indx.html @@ -0,0 +1,1611 @@ +Previous Section | Table of Contents | Title Page +
+Index +

Index

+

!-~

+TOP
+! 1 2
+!=
+!call
+!clock
+!csec
+!def
+!end
+!msec
+!ramp
+!rate
+!seti
+!setv
+!tempo
+# (adagio articulation)
+#?, sal
+#define'd macros
+#f
+#t
+%
+% (adagio thirtysecond note)
+&
+&=
+* 1 2
+*=
+*a4-hertz* 1 2
+*applyhook*
+*audio-markers*
+*autonorm*
+*autonorm-max-samples*
+*autonorm-previous-peak*
+*autonorm-target*
+*autonorm-type*
+*autonormflag*
+*breakenable* 1 2 3 4
+*control-srate* 1 2 3
+*debug-io*
+*default-control-srate*
+*default-plot-file*
+*default-sf-bits*
+*default-sf-dir* 1 2
+*default-sf-format*
+*default-sf-srate* 1 2
+*default-sound-srate*
+*error-output*
+*evalhook*
+*file-separator*
+*float-format*
+*gc-flag*
+*gc-hook*
+*integer-format*
+*loud*
+*obarray*
+*print-case*
+*readtable* 1 2
+*rslt* 1 2
+*sound-srate* 1 2 3
+*soundenable*
+*standard-input*
+*standard-output*
+*start*
+*stop*
+*sustain*
+*table*
+*trace-output*
+*tracelimit* 1 2
+*tracelist*
+*tracenable* 1 2 3
+*transpose*
+*unbound*
+*warp* 1 2 3
++ 1 2
++=
+, (adagio)
+- 1 2
+. (adagio)
+/ 1 2
+/=
+1+
+1-
+:answer
+:class
+:isa
+:isnew 1 2
+:new
+:show
+; (adagio)
+< 1 2
+<= 1 2 3
+= 1 2
+> 1 2
+>= 1 2 3
+@
+@=
+@@
+^
+^ (adagio sixtyfourth note)
+^=
+|
+~
+~ (adagio)
+~=
+~~
+

A

+TOP
+*a4-hertz* 1 2
+A440
+Abs
+Abs-env
+Absolute stretch, sal
+Absolute time shift, sal
+Absolute value 1 2
+Access samples
+Accidentals
+Accumulate +pattern
+Accumulation pattern
+Adagio
+# (adagio articulation)
+^ (adagio sixtyfourth note)
+% (adagio thirtysecond note)
+~ (adagio)
+; (adagio)
+, (adagio)
+. (adagio)
+Add +offset to sound
+Add to file samples
+Add-action-to-workspace
+Add-to-workspace
+Additive synthesis, gongs
+Address-of
+Aftertouch
+Agc
+Algorithmic composition
+All pass filter
+Alloc
+Allpass2
+Allpoles-from-lpc
+Alpass
+Alpass filter
+Amosc
+Analog synthesizer
+And
+:answer
+Append
+Apply
+Apply-banded-bass-boost
+Apply-banded-delay
+Apply-banded-treble-boost
+*applyhook*
+Approximation
+Arc-sine-dist
+Arcsine distribution
+Aref
+Areson
+Args
+Arguments to a lisp function
+Arithmetic functions
+Arpeggiator
+Array from sound
+Array functions
+Array notation, sal
+Arrayp
+Articulation 1 2
+Assoc
+Asterisk
+At
+At transformation
+At, sal
+At-abs
+At-abs, sal
+Atan
+Atom
+Atone
+Attributes
+Audio markers
+*audio-markers*
+Automatic gain control
+*autonorm*
+*autonorm-max-samples*
+Autonorm-off 1 2 3
+Autonorm-on 1 2 3
+*autonorm-previous-peak*
+*autonorm-target*
+*autonorm-type*
+*autonormflag*
+Average
+

B

+TOP
+Backquote
+Backward
+Baktrace
+Banded bass boost
+Banded delay
+Banded treble boost
+Bandfx.lsp
+Bandpass filter
+Bandpass2
+Bartok
+Begin
+Behavioral abstraction
+Behaviors
+Bell sound 1 2
+Bernoulli distribution
+Bernoulli-dist
+Beta distribution
+Beta-dist
+Big endian
+Bigendianp
+Bilateral exponential distribution
+Bilateral-exponential-dist
+Binary files
+Binomial distribution
+Binomial-dist
+Biquad
+Biquad-m
+Bitwise logical functions
+Blank
+Block
+Both-case-p
+Boundp
+Bowed
+Bowed-freq
+Brass sound
+Break 1 2
+Break button
+*breakenable* 1 2 3 4
+Browse button
+Browser, jnyqide
+Build-harmonic 1 2
+Button bar
+Buzz
+

C

+TOP
+!call
+Call command
+Car
+Case 1 2
+Case-insensitive
+Catch
+Cauchy distribution
+Cauchy-dist
+Cdr
+Cerror
+Change directory
+Char
+Char-code
+Char-downcase
+Char-equalp
+Char-greaterp
+Char-int
+Char-lessp
+Char-not-equalp
+Char-not-greaterp
+Char-not-lessp
+Char-upcase
+Char/=
+Char<
+Char<=
+Char=
+Char>
+Char>=
+Character functions
+Characterp
+Chdir, sal
+Chorus 1 2 3 4 5
+Clarinet 1 2 3
+Clarinet sound
+Clarinet-all
+Clarinet-freq
+Class
+:class
+Class class
+Clean-up
+Clip 1 2 3
+Clipping repair
+!clock
+Clock
+Clock command
+Close
+Co-termination
+Code-char
+Comb
+Comb filter
+Combination
+Command loop
+Commas
+Comment 1 2
+Comments
+Compose
+Compress
+Compress-map
+Compressor
+Concatenate strings
+Cond
+Conditional expression, sal
+Configure nyquist
+Congen
+Cons
+Console, xlisp
+Consp
+Const
+Constant function
+Continue
+Continuous-control-warp
+Continuous-sound-warp
+Contour generator
+Control
+Control change
+Control characters, xlisp
+Control constructs
+Control-a
+*control-srate* 1 2 3
+Control-srate-abs
+Control-warp
+Convert sound to array
+Convolution
+Convolve
+Copier +pattern
+Cos
+!csec
+Cue
+Cue-file
+Current-path
+Cxxr
+Cxxxr
+Cxxxxr
+Cycle pattern
+

D

+TOP
+Darwiinremoteosc
+Data types
+Db-average
+Db-to-linear
+Db0
+Db1
+Db10
+*debug-io*
+Debugging 1 2 3 4 5
+Decf
+Decrement
+!def
+Default
+Default +durations
+Default sample rate
+Default sound file directory
+Default time
+*default-control-srate*
+*default-plot-file*
+*default-sf-bits*
+*default-sf-dir* 1 2
+*default-sf-format*
+*default-sf-srate* 1 2
+*default-sound-srate*
+Define function
+Define variable
+#define'd macros
+Defining behaviors
+Defmacro
+Defun
+Delay
+Delay, +variable
+Delay, variable
+Delete
+Delete-if
+Delete-if-not
+Demos, bell sound
+Demos, distortion
+Demos, drum machine
+Demos, drum sound
+Demos, fft
+Demos, fm
+Demos, fm synthesis
+Demos, formants
+Demos, gong sound
+Demos, lpc
+Demos, midi
+Demos, piano
+Demos, pitch change
+Demos, rhythmic pattern
+Demos, ring modulation
+Demos, sample-by-sample
+Demos, scratch tutorial
+Demos, shepard tones
+Demos, spectral analysis of a chord
+Demos, voice synthesis
+Demos, wind sound
+Derivative
+Describe
+Destructive list functions
+Developing code
+Diff
+Difference
+Difference of sounds
+Digit-char
+Digit-char-p
+Directory listing
+Directory, default sound file
+Display statement, sal
+Distortion tutorial
+Distributions, probability
+Division
+Do
+Do*
+Dolby pro-logic
+Dolby surround
+Dolist
+Doppler effect
+Dot
+Dotimes
+Dotted durations
+Dribble
+Drum
+Drum +samples
+Drum machine 1 2
+Drum sound
+Drum-loop
+Dsp in lisp 1 2
+Dtmf
+Dtmf-tone
+Dubugging
+Duration 1 2
+Duration notation
+Duration of +another sound
+Dx7
+Dynamic markings
+

E

+TOP
+Echo
+Echoenabled
+Editor for envelopes
+Effect, + reverberation 1 2
+Effect, +reverberation
+Effect, chorus 1 2 3
+Effect, flange
+Effect, pitch shift 1 2
+Effect, reverberation 1 2
+Effect, stereo
+Effect, stereo pan
+Effect, swap channels
+Effect, widen
+Effects, phaser
+Eighth note 1 2
+Elapsed audio time
+Emacs, using nyquist with
+Empty list
+!end
+End
+End command
+Endian
+Endless tones
+Endp
+Env 1 2
+Env-note
+Envedit button
+Envelope
+Envelope editor
+Envelope follower 1 2
+Envelope generator
+Envelopes
+Environment
+Environment variables
+Eq
+Eq button
+Eq-band
+Eq-highshelf
+Eq-lowshelf
+Eql
+Equal
+Equalization 1 2 3 4
+Equalization editor
+Error
+Error handling
+*error-output*
+Errors
+Errset
+Estimate frequency
+Eval
+Eval pattern
+Evalhook
+*evalhook*
+Evaluation functions
+Evaluator
+Evenp
+Event-dur
+Event-end
+Event-expression
+Event-get-attr
+Event-has-attr
+Event-set-attr
+Event-set-dur
+Event-set-expression
+Event-set-time
+Event-time
+Exclamation point
+Exec statement, sal
+Exit
+Exit statement, sal
+Exp
+Exp-dec
+Expand
+Exponent
+Exponential
+Exponential distribution
+Exponential envelope
+Exponential-dist
+Expr-get-attr
+Expr-has-attr
+Expr-set-attr
+Expression pattern
+Expressions, sal
+Expt
+Extending xlisp
+Extract
+Extract-abs
+

F

+TOP
+#f
+F (adagio dynamic)
+F (adagio flat)
+Fast fourier transform tutorial
+Fboundp
+Feedback fm oscillator
+Feedback-delay
+Feel factor
+Ff (adagio dynamic)
+Fff (adagio dynamic)
+Fft
+Fft tutorial
+File i/o functions 1 2
+*file-separator*
+Filep
+Filter example
+Finally clause, sal
+Find string
+Find-in-xlisp-path
+Fir filter
+First
+First derivative
+Flange
+Flange effect
+Flat
+Flatc
+Flatsize
+Flet
+Float
+*float-format*
+Floatp
+Flute
+Flute sound
+Flute-all
+Flute-freq
+Fm synthesis
+Fmfb
+Fmlfo
+Fmosc
+Fn button
+Follow
+Follower
+Force-srate
+Format
+Fourth
+Frequency analysis
+Frequency modulation
+Full path name
+Funcall
+Function
+Function calls, sal
+Function, sal
+Fundamenal frequency +estimation
+

G

+TOP
+Gain
+Gamma-dist
+Gate 1 2
+Gaussian distribution
+Gaussian-dist
+Gc
+*gc-flag*
+*gc-hook*
+Gcd
+Gen05
+Gensym
+Geometric distribution
+Geometric-dist
+Get
+Get char
+Get-duration
+Get-env
+Get-lambda-expression
+Get-loud
+Get-output-stream-list
+Get-output-stream-string
+Get-slider-value
+Get-sustain
+Get-temp-path
+Get-transpose
+Get-user
+Get-warp
+Getenv
+Global variables
+Global variables, sal
+Go
+Gong sounds
+Granular synthesis
+Graphical envelope editor
+Graphical equalization
+Graphical equalizer
+Grindef
+

H

+TOP
+H
+H (adagio half note)
+Half note 1 2
+Harmonic
+Hash
+Hd
+Header file format
+Heap pattern
+High-pass filter
+Highpass2
+Highpass4
+Highpass6
+Highpass8
+Hp
+Ht
+Hyperbolic-cosine-dist
+Hz-to-step
+Hzosc
+

I

+TOP
+I
+I (adagio eight note)
+Iannis xenakis
+Id
+Ide
+If
+If statement, sal
+Ifft
+Incf
+Increment
+Info
+Info button
+Input from a file
+Input/output functions
+Installation
+Int-char
+*integer-format*
+Integerp
+Integrate
+Integrated development environment
+Intern
+Interoperability, sal and lisp
+Interpolate
+Intersection
+Intgen
+Inverse
+Inverse fft
+:isa
+:isnew 1 2
+It
+

J

+TOP
+Jcrev
+Jitter
+

K

+TOP
+K (adagio control)
+Karplus-strong
+Karplus-strong synthesis
+Keyword parameters
+

L

+TOP
+Labels
+Lambda
+Lambda lists
+Last
+Latency
+Legato 1 2
+Length
+Length pattern
+Length-of-beat
+Let
+Let*
+Lexical conventions
+Lf
+Lf (adagio dynamic)
+Lff
+Lff (adagio dynamic)
+Lfff
+Lfff (adagio dynamic)
+Lfo
+Libraries
+Limit
+Limiter
+Line pattern
+Linear distribution
+Linear interpolation
+Linear prediction
+Linear prediction tutorial
+Linear-dist
+Linear-to-db
+Lisp button
+Lisp dsp 1 2
+Lisp include files
+List
+List directory
+List functions
+Listdir
+Listing of lisp function
+Listp
+Little endian
+Lmf
+Lmf (adagio dynamic)
+Lmp
+Lmp (adagio dynamic)
+Load
+Load button
+Load file conditionally
+Load statement, sal
+Local-to-global
+Log
+Log function
+Logand
+Logical-stop
+Logior
+Logistic distribution
+Logistic-dist
+Lognot
+Logorithm
+Logxor
+Loop
+Loop examples, sal
+Loop statement, sal
+Looping constructs
+Loud
+*loud*
+Loud-abs
+Loudness 1 2
+Low-frequency oscillator
+Low-pass filter 1 2
+Lower-case-p
+Lowpass2
+Lowpass4
+Lowpass6
+Lowpass8
+Lp 1 2
+Lp (adagio dynamic)
+Lpc
+Lpc tutorial
+Lpc-frame-err 1 2
+Lpc-frame-filter-coefs 1 2
+Lpc-frame-rms1 1 2
+Lpc-frame-rms2 1 2
+Lpp
+Lpp (adagio dynamic)
+Lppp
+Lppp (adagio dynamic)
+Lpreson
+

M

+TOP
+M (adagio control)
+Macroexpand
+Macroexpand-1
+Macrolet
+Make-accumulate
+Make-accumulation
+Make-array
+Make-copier
+Make-cycle
+Make-eval
+Make-heap
+Make-length
+Make-line
+Make-lpanal-iterator
+Make-lpc-file-iterator
+Make-markov
+Make-palindrome
+Make-product
+Make-random
+Make-string-input-stream
+Make-string-output-stream
+Make-sum
+Make-symbol
+Make-window
+Maketable
+Mandolin
+Manipulation of scores
+Mapc
+Mapcar
+Mapl
+Maplist
+Mark button
+Markers, audio
+Markov analysis
+Markov pattern
+Markov-create-rules
+Max
+Maximum 1 2
+Maximum amplitude 1 2
+Maximum of two sounds
+Member
+Memory +usage
+Mf (adagio dynamic)
+Middle c
+Midi
+Midi clock
+Midi file 1 2 3
+Midi program
+Midi-show
+Midi-show-file
+Mikrokosmos
+Min
+Minimoog
+Minimum 1 2
+Minusp
+Mix
+Mix to file
+Mkwave
+Modalbar
+Modulation wheel
+Modulo (rem
+Mono to stereo
+Moog
+Moving average
+Mp (adagio dynamic)
+!msec
+Mult 1 2 3
+Multichannel sounds
+Multiple band effects
+Multiple commands
+Multiple tempi
+Multiplication
+Multiply signals
+My-note
+

N

+TOP
+N (adagio next)
+Natural
+Natural log
+Nband
+Nband-range
+Nconc
+Nested transformations
+:new
+Newfile button
+Next adagio command
+Next in pattern
+Next pattern
+Nintendo wiimote
+Noise
+Noise gate
+Noise-gate
+Normalization
+Not
+Not enough memory for normalization
+Notch filter
+Notch2
+Note list
+Nrev
+Nstring-downcase
+Nstring-upcase
+Nth
+Nthcdr
+Null
+Numberp
+Ny:all
+Nyquistide
+

O

+TOP
+O (adagio control)
+*obarray*
+Object
+Object class
+Objectp
+Objects
+Octave specification 1 2
+Oddp
+Offset
+Offset to a sound
+Omissions
+Oneshot
+Open 1 2
+Open sound control 1 2
+Open-binary
+Openfile button
+Or
+Osc 1 2 3
+Osc-enable
+Osc-note
+Osc-pulse
+Osc-saw
+Osc-tri
+Output samples to file
+Output to a file
+Overlap
+Overwrite samples
+

P

+TOP
+P (adagio dynamic)
+P (adagio pitch)
+Palindrome pattern
+Pan 1 2
+Pan, stereo
+Parameters, keyword
+Params-scale
+Params-transpose
+Partial
+Path, +current
+Pattern, +length
+Pattern, +window
+Pattern, accumulate
+Pattern, accumulation
+Pattern, copier
+Pattern, cycle
+Pattern, eval
+Pattern, expression
+Pattern, heap
+Pattern, line
+Pattern, markov
+Pattern, palindrome
+Pattern, product
+Pattern, random
+Pattern, sum
+Patternp
+Peak
+Peak amplitude
+Peak, maximum amplitude
+Peek
+Peek-char
+Period +estimation
+Phaser
+Physical model
+Piano synthesizer
+Piano synthesizer tutorial
+Piano-midi
+Piano-midi2file
+Piano-note
+Piano-note-2
+Piece-wise
+Piece-wise linear
+Pitch 1 2
+Pitch bend
+Pitch detection
+Pitch notation
+Pitch shift 1 2
+Pitch shifting
+Pitshift
+Pl-center
+Pl-doppler
+Pl-left
+Pl-pan2d
+Pl-position
+Pl-rear
+Pl-right
+Play 1 2
+Play in reverse
+Play-file
+Plot
+Pluck
+Plucked string
+Plusp
+Poisson distribution
+Poisson-dist
+Poke
+Polyrhythm
+Pop
+Portamento switch
+Power
+Pp (adagio dynamic)
+Ppp (adagio dynamic)
+Pprint
+Prcrev
+Predicate functions
+Preset
+Prin1
+Princ
+Print
+Print midi file
+Print statement, sal
+*print-case*
+Probability distributions
+Prod 1 2
+Product
+Product pattern
+Profile
+Profiling
+Prog
+Prog*
+Prog1
+Prog2
+Progn
+Program
+Program change
+Progv
+Prologic
+Property list functions
+Psetq
+Pulse oscillator
+Pulse-width modulation
+Push
+Putprop
+Pwe
+Pwe-list
+Pwer
+Pwer-list
+Pwev
+Pwev-list
+Pwevr
+Pwevr-list
+Pwl
+Pwl-list
+Pwlr
+Pwlr-list
+Pwlv
+Pwlv-list
+Pwlvr
+Pwlvr-list
+

Q

+TOP
+Q
+Q (adagio quarter note)
+Qd
+Qt
+Quantize
+Quarter note 1 2
+Quote
+

R

+TOP
+R (adagio rest)
+!ramp
+Ramp
+Random 1 2 3
+Random pattern
+!rate
+Rate 1 2
+Read
+Read directory
+Read macros
+Read samples
+Read samples from file
+Read samples in reverse
+Read-byte
+Read-char
+Read-float
+Read-int
+Read-line
+*readtable* 1 2
+Readtables
+Real-random
+Recip
+Reciprocal
+Rem
+Remainder
+Remove
+Remove-if
+Remove-if-not
+Remprop
+Replace file samples
+Replay button
+Require-from
+Resample
+Resampling 1 2
+Rescaling
+Resolution
+Reson
+Rest 1 2
+Restore
+Rests
+Return
+Return statement, sal
+Return-from
+Reverb 1 2 3 4 5
+Reverse
+Reverse, sound
+Ring modulation
+Risset
+Rms 1 2
+Room
+Rplaca
+Rplacd
+Rrandom
+*rslt* 1 2
+

S

+TOP
+S
+S (adagio sharp)
+S (adagio sixteenth note)
+S-abs
+S-add-to
+S-exp
+S-log
+S-max 1 2
+S-min 1 2
+S-overwrite
+S-plot
+S-print-tree
+S-read
+S-read-reverse
+S-rest
+S-reverse
+S-save
+S-sqrt
+#?, sal
+Sal
+Sal and lisp
+Sal button
+Sal expressions
+Sample interpolation 1 2
+Sample rate, forcing
+Sample rates
+Sampler
+Samples 1 2
+Samples, +reading
+Sampling rate 1 2
+Save
+Save samples to file
+Save-lpc-file
+Save-workspace
+Savefile button
+Saving sound files
+Sawtooth oscillator
+Sawtooth wave
+Sax 1 2 3
+Sax-all
+Sax-freq
+Scale
+Scale-db
+Scale-srate
+Scan directory
+Score
+Score manipulation
+Score, musical
+Score-adjacent-events
+Score-append
+Score-apply
+Score-filter
+Score-filter-length
+Score-filter-overlap
+Score-gen 1 2 3
+Score-get-begin
+Score-get-end
+Score-indexof
+Score-last-indexof
+Score-merge
+Score-must-have-begin-end
+Score-play
+Score-print
+Score-randomize-start
+Score-read-smf
+Score-repeat
+Score-scale
+Score-select
+Score-set-begin
+Score-set-end
+Score-shift
+Score-sort
+Score-sorted
+Score-stretch
+Score-stretch-to-length
+Score-sustain
+Score-transpose
+Score-voice
+Score-write-smf
+Scratch sound
+Sd
+Second
+Sections, adagio
+Self
+Semicolon, adagio
+Seq
+Seqrep
+Sequence_example.htm
+Sequences 1 2
+Sequential behavior
+Set
+Set intersection
+Set statement, sal
+Set union
+Set-control-srate 1 2
+Set-difference
+Set-logical-stop
+Set-pitch-names
+Set-sound-srate 1 2
+Setdir
+Setf
+!seti
+Seti commnad
+Setq
+Setup nyquist
+Setup-console
+!setv
+Setv command
+Sf-granulate
+Sf-info
+Shape
+Sharp
+Shepard tones 1 2
+Shift-time
+:show
+Show midi file
+Show-lpc-data
+Signal composition 1 2
+Signal multiplication
+Signal-start
+Signal-stop
+Sim 1 2
+Simrep
+Simultaneous behavior
+Sin
+Sine
+Siosc
+Sitar
+Sixteenth note 1 2
+Sixtyfourth note
+Slope
+Smooth
+Snd-abs
+Snd-add
+Snd-allpoles
+Snd-alpass
+Snd-alpasscv
+Snd-alpassvv
+Snd-amosc
+Snd-areson
+Snd-aresoncv
+Snd-aresonvc
+Snd-aresonvv
+Snd-atone
+Snd-atonev
+Snd-avg
+Snd-bandedwg
+Snd-biquad
+Snd-bowed
+Snd-bowed-freq
+Snd-buzz
+Snd-chase
+Snd-clarinet
+Snd-clarinet-all
+Snd-clarinet-freq
+Snd-clip
+Snd-compose
+Snd-congen
+Snd-const
+Snd-convolve
+Snd-copy
+Snd-coterm
+Snd-delay
+Snd-delaycv
+Snd-down
+Snd-exp
+Snd-extent
+Snd-fetch
+Snd-fetch-array
+Snd-fft
+Snd-flatten
+Snd-flute
+Snd-flute-all
+Snd-flute-freq
+Snd-fmfb
+Snd-fmfbv
+Snd-fmosc
+Snd-follow
+Snd-from-array
+Snd-fromarraystream
+Snd-fromobject
+Snd-gate
+Snd-ifft
+Snd-inverse
+Snd-length
+Snd-log
+Snd-lpanal
+Snd-lpreson
+Snd-mandolin
+Snd-max
+Snd-maxsamp
+Snd-maxv
+Snd-modalbar
+Snd-multiseq
+Snd-normalize
+Snd-offset
+Snd-oneshot
+Snd-osc
+Snd-overwrite
+Snd-partial
+Snd-play
+Snd-pluck
+Snd-print
+Snd-print-tree 1 2
+Snd-prod
+Snd-pwl
+Snd-quantize
+Snd-read
+Snd-recip
+Snd-resample
+Snd-resamplev
+Snd-reson
+Snd-resoncv
+Snd-resonvc
+Snd-resonvv
+Snd-samples
+Snd-save
+Snd-sax
+Snd-sax-all
+Snd-sax-freq
+Snd-scale
+Snd-seq
+Snd-set-latency
+Snd-set-logical-stop
+Snd-shape
+Snd-sine
+Snd-siosc
+Snd-sitar
+Snd-slider
+Snd-sqrt
+Snd-srate
+Snd-sref
+Snd-stkchorus
+Snd-stkpitshift
+Snd-stkrev
+Snd-stop-time
+Snd-t0
+Snd-tapf
+Snd-tapv
+Snd-time
+Snd-tone
+Snd-tonev
+Snd-trigger
+Snd-up
+Snd-white
+Snd-xform
+Snd-yin
+Snd-zero
+Soften-clipping
+Sort
+Sound
+Sound browser, jnyqide
+Sound file directory default
+Sound file i/o
+Sound file info
+Sound from lisp data
+Sound, accessing point
+Sound, creating from array
+Sound-off 1 2
+Sound-on 1 2
+*sound-srate* 1 2 3
+Sound-srate-abs
+Sound-warp
+*soundenable*
+Soundfilename
+Soundp
+Sounds
+Sounds vs. behaviors
+Span
+Spatialization
+Special command
+Spectral interpolation
+Speed-dial
+Splines
+Sqrt
+Square oscillator
+Square root 1 2
+Srate
+Sref
+Sref-inverse
+St
+Stacatto
+Staccato
+Stack trace
+Standard midi file
+*standard-input*
+*standard-output*
+*start*
+Statements, sal
+Stats
+Step-to-hz
+Stereo
+Stereo pan
+Stereo panning
+Stereo-chorus
+Stereoize
+Stk banded waveguide
+Stk bowed 1 2
+Stk bowed string
+Stk bowed-freq
+Stk chorus 1 2
+Stk clarinet 1 2 3 4 5
+Stk flute 1 2 3 4 5 6
+Stk glass harmonica
+Stk jcreverb
+Stk mandolin
+Stk mandolon
+Stk modal bar 1 2
+Stk nreverb
+Stk pitch shift 1 2
+Stk prcreverb
+Stk reverb
+Stk sax 1 2 3 4
+Stk sitar 1 2
+Stk tibetan bowl
+Stk tuned bar
+Stk uniform bar
+Stkchorus
+Stochastic functions
+*stop*
+Strcat
+Streamp
+Stretch 1 2
+Stretch transformation
+Stretch, sal
+Stretch-abs
+Stretching sampled sounds
+String
+String functions
+String stream functions
+String synthesis
+String-downcase
+String-equalp
+String-greaterp
+String-left-trim
+String-lessp
+String-not-equalp
+String-not-greaterp
+String-not-lessp
+String-right-trim
+String-search
+String-trim
+String-upcase
+String/=
+String<
+String<=
+String=
+String>
+String>=
+Stringp
+Sublis
+Subseq
+Subset
+Subsetp
+Subst
+Suggestions
+Sum
+Sum +pattern
+Surround sound
+Sustain
+*sustain*
+Sustain-abs
+Swap channels
+Swapchannels
+Symbol functions
+Symbol-function
+Symbol-name
+Symbol-plist
+Symbol-value
+Symbolp
+Symbols
+Synchronization
+System functions
+

T

+TOP
+T
+#t
+T (adagio triplet)
+Table
+Table memory
+*table*
+Tagbody
+Tan
+Tap
+Tapped delay
+Tapv
+Temp file 1 2
+!tempo
+Tempo 1 2
+Temporary files
+Temporary sound files directory
+Terpri
+The format function
+The program feature
+Third
+Thirtysecond note
+Threshold
+Throw
+Time 1 2 3
+Time shift, sal
+Time structure
+Time units
+Timed-seq
+Tone
+Top button
+Top-level
+Touch tone
+Trace
+*trace-output*
+*tracelimit* 1 2
+*tracelist*
+*tracenable* 1 2 3
+Transformation environment
+Transformations 1 2
+Transpose
+*transpose*
+Transpose-abs
+Triangle oscillator
+Triangle wave
+Trigger
+Trill
+Triplet
+Triplet durations
+Truncate
+Tuba
+Tuning
+Tutorial, fm
+Type-of
+

U

+TOP
+U
+*unbound*
+Uniform random 1 2
+Union
+Unless
+Untrace
+Unwind-protect
+Upic
+Upper-case-p
+User name
+

V

+TOP
+V (adagio voice)
+Variable delay 1 2 3
+Variable-resample function
+Vector
+Velocity
+Vinal scratch
+Vocal sound
+Voice 1 2
+Voice synthesis
+Volume
+

W

+TOP
+W
+W (adagio whole note)
+Warble
+Warp
+*warp* 1 2 3
+Warp-abs
+Waveforms 1 2
+Waveshaping
+Wavetables 1 2
+Wd
+Wg-glass-harm
+Wg-tibetan-bowl
+Wg-tuned-bar
+Wg-uniform-bar
+When 1 2
+While
+Whole note 1 2
+Widen
+Wii controller
+Wind sound
+Wind_tutorial.htm
+Window initialization
+Window pattern
+With statement, sal
+Wood drum sound
+Workspace 1 2
+Write samples to file
+Write-byte
+Write-char
+Write-float
+Write-int
+Wt
+

X

+TOP
+X (adagio control)
+Xenakis
+Xlisp command loop
+Xlisp data types
+Xlisp evaluator
+Xlisp lexical conventions
+Xmusic
+

Y

+TOP
+Y (adagio control)
+Yin
+

Z

+TOP
+Z (adagio program) 1 2
+Zerop
+
+Previous Section | Table of Contents | Title Page diff --git a/doc/linear-fig.gif b/doc/linear-fig.gif new file mode 100644 index 0000000..83f39c5 Binary files /dev/null and b/doc/linear-fig.gif differ diff --git a/doc/logistic-fig.gif b/doc/logistic-fig.gif new file mode 100644 index 0000000..6ab3f99 Binary files /dev/null and b/doc/logistic-fig.gif differ diff --git a/doc/moog-fig.gif b/doc/moog-fig.gif new file mode 100644 index 0000000..a550eee Binary files /dev/null and b/doc/moog-fig.gif differ diff --git a/doc/musicbib.html b/doc/musicbib.html new file mode 100644 index 0000000..84e26ea --- /dev/null +++ b/doc/musicbib.html @@ -0,0 +1,13 @@ +References + +Table of Contents | Index | Title Page +
+

References

+ +Touretzky, D. (1983) A Gentle Introduction to Symbolic Computation. New York: Harper and Row. +

+ +Dannenberg, R. and C. Frayley. (1989) ``Fugue: A Signal Manipulation System with Lazy Evaluation and Behavioral Abstraction.'' In 1989 International Computer Music Conference, San Francisco: Computer Musici Association, (October 1989), pp 76-79. +


+Table of Contents | Index | Title Page + diff --git a/doc/nyqman.txt b/doc/nyqman.txt new file mode 100644 index 0000000..3aaea01 --- /dev/null +++ b/doc/nyqman.txt @@ -0,0 +1,13387 @@ + + + + + + + + + + + + + + + + NYQUIST REFERENCE MANUAL + + Version 3.05 + + + Copyright 2011 by Roger B. Dannenberg + 14 March 2011 + + + + + + + + + + + + Carnegie Mellon University + + School of Computer Science + + Pittsburgh, PA 15213, U.S.A. + . +Preface + This manual is a guide for users of Nyquist, a language for composition and +sound synthesis. Nyquist grew out of a series of research projects, notably +the languages Arctic and Canon. Along with Nyquist, these languages promote a +functional style of programming and incorporate time into the language +semantics. + + Please help by noting any errors, omissions, or suggestions you may have. +You can send your suggestions to Dannenberg@CS.CMU.EDU (internet) via computer +mail, or by campus mail to Roger B. Dannenberg, School of Computer Science, or +by ordinary mail to Roger B. Dannenberg, School of Computer Science, Carnegie +Mellon University, 5000 Forbes Ave., Pittsburgh, PA 15213-3890, USA. + + Nyquist is a successor to Fugue, a language originally implemented by Chris +Fraley, and extended by George Polly and Roger Dannenberg. Peter Velikonja and +Dean Rubine were early users, and they proved the value as well as discovered +some early problems of the system. This led to Nyquist, a reimplementation of +Fugue by Roger Dannenberg with help from Joe Newcomer and Cliff Mercer. Ning Hu +ported Zheng (Geoffrey) Hua and Jim Beauchamp's piano synthesizer to Nyquist +and also built NyqIDE, the Nyquist Integrated Development Environment for +Windows. Dave Mowatt contributed the original version of NyquistIDE, the +cross-platform interactive development environment. Dominic Mazzoni made a +special version of Nyquist that runs within the Audacity audio editor, giving +Nyquist a new interface and introducing Nyquist to many new users. + + Many others have since contributed to Nyquist. Chris Tchou and Morgan Green +worked on the Windows port. Eli Brandt contributed a number of filters and +other synthesis functions. Pedro J. Morales, Eduardo Reck Miranda, Ann Lewis, +and Erich Neuwirth have all contributed nyquist examples found in the demos +folder of the Nyquist distribution. Philip Yam ported some synthesis functions +from Perry Cook and Gary Scavone's STK to Nyquist. Pedro Morales ported many +more STK instruments to Nyquist. Dave Borel wrote the Dolby Pro-Logic encoding +library and Adam Hartman wrote stereo and spatialization effects. Stephen +Mangiat wrote the MiniMoog emulator. Phil Light recorded the drum samples and +wrote drum machine software. The Xmusic library, particularly the pattern +specification, was inspired by Rick Taube's Common Music. The functions for +generating probability distributions were implemented by Andreas Pfenning. + + Starting with Version 3, Nyquist supports a version of SAL, providing an +alternative to Lisp syntax. SAL was designed by Rick Taube, and the SAL +implementation in Nyquist is based on Taube's original implementation as part +of his Common Music system. + + The current NyquistIDE includes contributions from many. Chris Yealy and +Derek D'Souza implemented early versions of the envelope editor. Daren Makuck +and Michael Rivera wrote the original equalizer editor. Priyanka Raghavan +implemented the sound browser. Dmitry Portnoy wrote the original "UPIC" editor. + + Many others have made contributions, offered suggestions, and found bugs. If +you were expecting to find your name here, I apologize for the omission, and +please let me know. + + I also wish to acknowledge support from CMU, Yamaha, and IBM for this work. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +. +1. Introduction and Overview + Nyquist is a language for sound synthesis and music composition. Unlike +score languages that tend to deal only with events, or signal processing +languages that tend to deal only with signals and synthesis, Nyquist handles +both in a single integrated system. Nyquist is also flexible and easy to use +because it is based on an interactive Lisp interpreter. + + With Nyquist, you can design instruments by combining functions (much as you +would using the orchestra languages of Music V, cmusic, or Csound). You can +call upon these instruments and generate a sound just by typing a simple +expression. You can combine simple expressions into complex ones to create a +whole composition. + + Nyquist runs under Linux, Apple Mac OS X, Microsoft Windows NT, 2000, XP, and +Vista, and it produces sound files or directly generates audio. Recent +versions have also run on AIX, NeXT, SGI, DEC pmax, and Sun Sparc machines. +(Makefiles for many of these are included, but out-of-date). Let me know if +you have problems with any of these machines. + + To use Nyquist, you should have a basic knowledge of Lisp. An excellent text +by Touretzky is recommended [Touretzky 84]. Appendix IV is the reference +manual for XLISP, of which Nyquist is a superset. Starting with Version 3, +Nyquist supports a variant of SAL, which is also available in Common Music. +Since there are some differences, one should generally call this implementation +``Nyquist SAL;'' however, in this manual, I will just call it ``SAL.'' SAL +offers most of the capabilities of Lisp, but it uses an Algol-like syntax that +may be more familiar to programmers with experience in Java, C, Basic, etc. + +1.1. Installation + Nyquist is a C++ program intended to run under various operating systems +including Unix, Mac OS X, and Windows. Nyquist is based on Lisp, but it +includes its own Lisp interpreter (a modified version of XLISP), so you do not +need to install some other Lisp to run Nyquist. Other Lisp systems are not +compatible with Nyquist. + + Most Nyquist users run Nyquist under the Nyquist IDE, which is written in +Java and depends on the Java runtime system. Most systems already have Java, +but if you do not, you will need to install it. When you install the Nyquist +IDE, you will automatically get Nyquist and a set of runtime libraries. + + There are generally two ways to install Nyquist: + + - Get a pre-compiled version of the Nyquist IDE for Windows or Mac OS + X. The Windows version comes packaged in an installer that installs + and configures the Nyquist IDE. The Mac OS X version unpacks to a + complete OS X application. + + - Compile from sources. There is one set of sources for Mac, Windows, + and Unix. Instructions for building applications from the sources + are provided in the files sys/win/README.txt, sys/mac/README.txt, and + sys/unix/README.txt. + + You can download source code and precompiled versions from the Nyquist +project on SourceForge (http://sourceforge.net/projects/nyquist). The latest +source code can be obtained via Subversion (svn) using the following: + + svn co https://nyquist.svn.sourceforge.net/svnroot/nyquist/trunk nyquis + +or by checking out nyquist using a graphical interface svn client such as +TortoiseSVN for Windows. + +1.2. Using NyquistIDE + The program named NyquistIDE is an ``integrated development environment'' for +Nyquist. When you run NyquistIDE, it starts the Nyquist program and displays +all Nyquist output in a window. NyquistIDE helps you by providing a Lisp and +SAL editor, hints for command completion and function parameters, some +graphical interfaces for editing envelopes and graphical equalizers, and a +panel of buttons for common operations. A more complete description of +NyquistIDE is in Chapter 2. + + For now, all you really need to know is that you can enter Nyquist commands +by typing into the upper left window. When you type return, the expression you +typed is sent to Nyquist, and the results appear in the window below. You can +edit files by clicking on the New File or Open File buttons. After editing some +text, you can load the text into Nyquist by clicking the Load button. +NyquistIDE always saves the file first; then it tells Nyquist to load the file. +You will be prompted for a file name the first time you load a new file. + +1.3. Using SAL + SAL mode means that Nyquist reads and evaluates SAL commands rather than +Lisp. The SAL mode prompt is "SAL> " while the Lisp mode prompt is "> ". When +Nyquist starts it normally enters SAL mode automatically, but certain errors +may exit SAL mode. You can reenter SAL mode by typing the Lisp expression +(sal). + + In SAL mode, you type commands in the SAL programming language. Nyquist reads +the commands, compiles them into Lisp, and evaluates the commands. Commands can +be entered manually by typing into the upper left text box in NyquistIDE. + +1.4. Helpful Hints + Under Win95 and Win98, the console sometimes locks up. Activating another +window and then reactivating the Nyquist window should unlock the output. (We +suggest you use JNyqIDE, the interactive development environment rather than a +console window.) + + You can cut and paste text into Nyquist, but for serious work, you will want +to use the Lisp load command. To save even more time, write a function to load +your working file, e.g. (defun l () (load "myfile.lsp")). Then you can type (l) +to (re)load your file. + + Using SAL, you can type + + define function l () load "myfile.lsp" + +and then + + exec l() + +to (re)load the file. + + The Emacs editor is free GNU software and will help you balance parentheses +if you use Lisp mode. In fact, you can run nyquist (without the IDE) as a +subprocess to Emacs. A helful discussion is at //http://www.audacity- +forum.de/download/edgar/nyquist/nyquist-doc/examples/emacs/main.html. If you +use Emacs, there is also a SAL mode (the file is sal-mode.el) included with the +Common Music distribution, which you can find on the Web at sourceforge.net. + + The NyquistIDE also runs Nyquist as a subprocess and has built-in Lisp and +SAL editors. If your editor does not help you balance parentheses, you may find +yourself counting parens and searching for unbalanced expressions. If you are +confused or desperate and using Lisp syntax, try the :print t option of the +load function. By looking at the expressions printed, you should be able to +tell where the last unbalanced expression starts. Alternatively, type +(file-sexprs) and type the lisp file name at the prompt. This function will +read and print expressions from the file, reporting an error when an extra +paren or end-of-file is reached unexpectedly. + +1.5. Using Lisp + Lisp mode means that Nyquist reads and evaluates Nyquist expressions in Lisp +syntax. Since Nyquist is build on a Lisp interpreter, this is the ``native'' or +machine language of Nyquist, and certain errors and functions may break out of +the SAL interpreter, leaving you with a prompt for a Lisp expression. +Alternatively, you can exit SAL simply by typing exit to get a Lisp prompt (> +). Commands can be entered manually by typing into the upper left text box in +NyquistIDE. + +1.6. Examples + We will begin with some simple Nyquist programs. Throughout the manual, we +will assume SAL mode and give examples in SAL, but it should be emphasized that +all of these examples can be performed using Lisp syntax. See Section 6.2 on +the relationship between SAL and Lisp. + + Detailed explanations of the functions used in these examples will be +presented in later chapters, so at this point, you should just read these +examples to get a sense of how Nyquist is used and what it can do. The details +will come later. Most of these examples can be found in the file +nyquist/demos/examples.sal. Corresponding Lisp syntax examples are in the file +nyquist/demos/examples.lsp. + + Our first example makes and plays a sound: + + ;; Making a sound. + play osc(60) ; generate a loud sine wave + +This example is about the simplest way to create a sound with Nyquist. The osc +function generates a sound using a table-lookup oscillator. There are a number +of optional parameters, but the default is to compute a sinusoid with an +amplitude of 1.0. The parameter 60 designates a pitch of middle C. (Pitch +specification will be described in greater detail later.) The result of the +osc function is a sound. To hear a sound, you must use the play command, which +plays the file through the machine's D/A converters. It also writes a +soundfile in case the computation cannot keep up with real time. You can then +(re)play the file by typing: + + exec r() + +This (r) function is a general way to ``replay'' the last thing written by +play. + 15 + Note: when Nyquist plays a sound, it scales the signal by 2 -1 and (by +default) converts to a 16-bit integer format. A signal like (osc 60), which +ranges from +1 to -1, will play as a full-scale 16-bit audio signal. + + + +1.6.1. Waveforms + Our next example will be presented in several steps. The goal is to create a +sound using a wavetable consisting of several harmonics as opposed to a simple +sinusoid. In order to build a table, we will use a function that computes a +single harmonic and add harmonics to form a wavetable. An oscillator will be +used to compute the harmonics. + + The function mkwave calls upon build-harmonic to generate a total of four +harmonics with amplitudes 0.5, 0.25, 0.125, and 0.0625. These are scaled and +added (using +) to create a waveform which is bound temporarily to *table*. + + A complete Nyquist waveform is a list consisting of a sound, a pitch, and T, +indicating a periodic waveform. The pitch gives the nominal pitch of the +sound. (This is implicit in a single cycle wave table, but a sampled sound may +have many periods of the fundamental.) Pitch is expressed in half-steps, where +middle C is 60 steps, as in MIDI pitch numbers. The list of sound, pitch, and +T is formed in the last line of mkwave: since build-harmonic computes signals +with a duration of one second, the fundamental is 1 Hz, and the hz-to-step +function converts to pitch (in units of steps) as required. + + define function mkwave() + begin + set *table* = 0.5 * build-harmonic(1.0, 2048) + + 0.25 * build-harmonic(2.0, 2048) + + 0.125 * build-harmonic(3.0, 2048) + + 0.0625 * build-harmonic(4.0, 2048) + set *table* = list(*table*, hz-to-step(1.0), #t) + end + + Now that we have defined a function, the last step of this example is to +build the wave. The following code calls mkwave the first time the code is +executed (loaded from a file). The second time, the variable *mkwave* will be +true, so mkwave will not be invoked: + + if ! fboundp(quote(*mkwave*)) then + begin + exec mkwave() + set *mkwave* = #t + end + + + +1.6.2. Wavetables + When Nyquist starts, several waveforms are created and stored in global +variables for convenience. They are: *sine-table*, *saw-table*, and +*tri-table*, implementing sinusoid, sawtooth, and triangle waves, respectively. +The variable *table* is initialized to *sine-table*, and it is *table* that +forms the default wave table for many Nyquist oscillator behaviors. If you want +a proper, band-limited waveform, you should construct it yourself, but if you +do not understand this sentence and/or you do not mind a bit of aliasing, give +*saw-table* and *tri-table* a try. + + Note that in Lisp and SAL, global variables often start and end with +asterisks (*). These are not special syntax, they just happen to be legal +characters for names, and their use is purely a convention. + + + +1.6.3. Sequences + Finally, we define my-note to use the waveform, and play several notes in a +simple score. Note that the function my-note has only one command (a return +command), so it is not necessary to use begin and end. These are only necessary +when the function body consists of a sequence of statements: + + define function my-note(pitch, dur) + return osc(pitch, dur, *table*) + + play seq(my-note(c4, i), my-note(d4, i), my-note(f4, i), + my-note(g4, i), my-note(d4, q)) + + +Here, my-note is defined to take pitch and duration as parameters; it calls osc +to do the work of generating a waveform, using *table* as a wave table. + + The seq function is used to invoke a sequence of behaviors. Each note is +started at the time the previous note finishes. The parameters to my-note are +predefined in Nyquist: c4 is middle C, i (for eIghth note) is 0.5, and q (for +Quarter note) is 1.0. See Section 1.7 for a complete description. The result +is the sum of all the computed sounds. + + Sequences can also be constructed using the at transformation to specify time +offsets. See sequence_example.htmdemos, sequence for more examples and +explanation. + + + +1.6.4. Envelopes + The next example will illustrate the use of envelopes. In Nyquist, envelopes +are just ordinary sounds (although they normally have a low sample rate). An +envelope is applied to another sound by multiplication using the mult function. +The code shows the definition of env-note, defined in terms of the note +function in the previous example. In env-note, a 4-phase envelope is generated +using the env function, which is illustrated in Figure 1. + + + + + + + + + + + + + + + + Figure 1: An envelope generated by the env function. + + + ; env-note produces an enveloped note. The duration + ; defaults to 1.0, but stretch can be used to change + ; the duration. + ; Uses my-note, defined above. + ; + define function env-note(p) + return my-note(p, 1.0) * + env(0.05, 0.1, 0.5, 1.0, 0.5, 0.4) + + ; try it out: + ; + play env-note(c4) + +While this example shows a smooth envelope multiplied by an audio signal, you +can also multiply audio signals to achieve what is often called ring +modulation. See the code and description in demos/scratch_tutorial.htm for an +interesting use of ring modulation to create ``scratch'' sounds. + + In the next example, The stretch operator (~)is used to modify durations: + + ; now use stretch to play different durations + ; + play seq(seq(env-note(c4), env-note(d4)) ~ 0.25, + seq(env-note(f4), env-note(g4)) ~ 0.5, + env-note(c4)) + + In addition to stretch, there are a number of transformations supported by +Nyquist, and transformations of abstract behaviors is perhaps the fundamental +idea behind Nyquist. Chapter 3 is devoted to explaining this concept, and +further elaboration can be found elsewhere [Dannenberg 89]. + + + +1.6.5. Piece-wise Linear Functions + It is often convenient to construct signals in Nyquist using a list of (time, +value) breakpoints which are linearly interpolated to form a smooth signal. +Envelopes created by env are a special case of the more general piece-wise +linear functions created by pwl. Since pwl is used in some examples later on, +we will take a look at pwl now. The pwl function takes a list of parameters +which denote (time, value) pairs. There is an implicit initial (time, value) +pair of (0, 0), and an implicit final value of 0. There should always be an +odd number of parameters, since the final value (but not the final time) is +implicit. Here are some examples: + + ; symetric rise to 10 (at time 1) and fall back to 0 (at time 2): + ; + pwl(1, 10, 2) + + ; a square pulse of height 10 and duration 5. + ; Note that the first pair (0, 10) overrides the default initial + ; point of (0, 0). Also, there are two points specified at time 5: + ; (5, 10) and (5, 0). (The last 0 is implicit). The conflict is + ; automatically resolved by pushing the (5, 10) breakpoint back to + ; the previous sample, so the actual time will be 5 - 1/sr, where + ; sr is the sample rate. + ; + pwl(0, 10, 5, 10, 5) + + ; a constant function with the value zero over the time interval + ; 0 to 3.5. This is a very degenerate form of pwl. Recall that there + ; is an implicit initial point at (0, 0) and a final implicit value of + ; 0, so this is really specifying two breakpoints: (0, 0) and (3.5, 0): + ; + pwl(3.5) + + ; a linear ramp from 0 to 10 and duration 1. + ; Note the ramp returns to zero at time 1. As with the square pulse + ; above, the breakpoint (1, 10) is pushed back to the previous sample. + ; + pwl(1, 10, 1) + + ; If you really want a linear ramp to reach its final value at the + ; specified time, you need to make a signal that is one sample longer. + ; The RAMP function does this: + ; + ramp(10) ; ramp from 0 to 10 with duration 1 + one sample period + ; + ; RAMP is based on PWL; it is defined in nyquist.lsp. + ; + +1.7. Predefined Constants + For convenience and readability, Nyquist pre-defines some constants, mostly +based on the notation of the Adagio score language, as follows: + + - Dynamics Note: these dynamics values are subject to change. + + lppp = -12.0 (dB) + lpp = -9.0 + lp = -6.0 + lmp = -3.0 + lmf = 3.0 + lf = 6.0 + lff = 9.0 + lfff = 12.0 + dB0 = 1.00 + dB1 = 1.122 + dB10 = 3.1623 + + - Durations + + s = Sixteenth = 0.25 + i = eIghth = 0.5 + q = Quarter = 1.0 + h = Half = 2.0 + w = Whole = 4.0 + sd, id, qd, hd, wd = dotted durations. + st, it, qt, ht, wt = triplet durations. + + - PitchesPitches are based on an A4 of 440Hz. To achieve a different + tuning, set *A4-Hertz* to the desired frequency for A4, and call + (set-pitch-names). This will recompute the names listed below with a + different tuning. In all cases, the pitch value 69.0 corresponds + exactly to 440Hz, but fractional values are allowed, so for example, + if you set *A4-Hertz* to 444 (Hz), then the symbol A4 will be bound + to 69.1567, and C4 (middle C), which is normally 60.0, will be + 60.1567. + + c0 = 12.0 + cs0, df0 = 13.0 + d0 = 14.0 + ds0, ef0 = 15.0 + e0 = 16.0 + f0 = 17.0 + fs0, gf0 = 18.0 + g0 = 19.0 + gs0, af0 = 20.0 + a0 = 21.0 + as0, bf0 = 22.0 + b0 = 23.0 + c1 ... b1 = 24.0 ... 35.0 + c2 ... b2 = 36.0 ... 47.0 + c3 ... b3 = 48.0 ... 59.0 + c4 ... b4 = 60.0 ... 71.0 + c5 ... b5 = 72.0 ... 83.0 + c6 ... b6 = 84.0 ... 95.0 + c7 ... b7 = 96.0 ... 107.0 + c8 ... b8 = 108.0 ... 119.0 + + - Miscellaneous + + ny:all = ``all the samples'' (i.e. a big number) = 1000000000 + +1.8. More Examples + More examples can be found in the directory demos, part of the standard +Nyquist release. The file demos/examples_home.htm is an index to all the demo +descriptions. In this directory, you will find the following and more: + + - How to make arpeggios (demos/arpeggiator.htm and arp.sal + + - Gong sounds by additive synthesis(demos/pmorales/b1.lsp and + demos/mateos/gong.lsp + + - Risset's spectral analysis of a chord (demos/pmorales/b2.lsp) + + - Bell sounds (demos/pmorales/b3.lsp, demos/pmorales/e2.lsp, + demos/pmorales/partial.lsp, and demos/mateos/bell.lsp) + + - Drum sounds by Risset (demos/pmorales/b8.lsp + + - Shepard tones (demos/shepard.lsp and demos/pmorales/b9.lsp) + + - Random signals (demos/pmorales/c1.lsp) + + - Buzz with formant filters (demos/pmorales/buzz.lsp + + - Computing samples directly in Lisp (using Karplus-Strong and physical + modelling as examples) (demos/pmorales/d1.lsp + + - FM Synthesis examples, including bell, wood drum, brass sounds, tuba + sound (demos/mateos/tuba.lsp and clarinet sounds + (demos/pmorales/e2.lsp + + - Rhythmic patterns (demos/rhythm_tutorial.htm + + - Drum Samples and Drum Machine (demos/plight/drum.lsp. (See Section + 14.13). +2. The NyquistIDE Program + The NyquistIDE program combines many helpful functions and interfaces to help +you get the most out of Nyquist. NyquistIDE is implemented in Java, and you +will need the Java runtime system or development system installed on your +computer to use NyquistIDE. The best way to learn about NyquistIDE is to just +use it. This chapter introduces some of the less obvious features. If you are +confused by something and you do not find the information you need here, please +contact the author. + +2.1. NyquistIDE Overview + The NyquistIDE runs the command-line version of Nyquist as a subtask, so +everything that works in Nyquist should work when using the NyquistIDE and +vice-versa. Input to Nyquist is usually entered in the top left window of the +NyquistIDE. When you type return, if the expression or statement appears to be +complete, the expression you typed is sent to Nyquist. Output from Nyquist +appears in a window below. You cannot type into or edit the output window text. + + The normal way to use the NyquistIDE is to create or open one or more files. +You edit these files and then click the Load button. To load a file, NyquistIDE +saves the file, sets the current directory of Nyquist to that of the file, then +issues a load command to Nyquist. In this case and several others, you may +notice that NyquistIDE sends expressions to Nyquist automatically for +evaluation. You can always see the commands and their results in the output +window. + + Notice that when you load a selected file window, NyquistIDE uses setdir to +change Nyquist's current directory. This helps to keep the two programs in +sync. Normally, you should keep all the files of a project in the same +directory and avoid manually changing Nyquist's current directory (i.e. avoid +calling setdir in your code). + + Arranging windows in the NyquistIDE can be time-consuming, and depending on +the operating system, it is possible for a window to get into a position where +you cannot drag it to a new position. The Window:Tile menu command can be used +to automatically lay out windows in a rational way. There is a preference +setting to determine the height of the completion list relative to the height +of the output window. + +2.2. The Button Bar + There are a number of buttons with frequently-used operations. These are: + + - Info M Print information about Nyquist memory utilization, including + the number of free cons cells, the number of garbage collections, the + total number of cons cells, the total amount of sample buffer memory, + and the amount of memory in free sample buffers. + + - Break M Send a break character to XLISP. This can be used to enter + the debugger (the break loop) while a program is running. Resume by + typing (co). + + - SAL/Lisp M Switch modes. The button names the mode (SAL or Lisp) you + will switch to, not the current mode. For example, if you are in Lisp + mode and want to type a SAL command, click the SAL button first. + + - Top M Enters (top) into Nyquist. If the XLISP prompt is 1> or some + other integer followed by ``>'', clicking the Top button will exit + the debug loop and return to the top-level prompt. + + - Replay M Enters (r) into Nyquist. This command replays the last + computed sound. + + - F2-F12 M Enters (f2) etc. into Nyquist. These commands are not + built-in, and allow users to define their own custom actions. + + - Browse M Equivalent to the Window:Browse menu item. (See Section + 2.4.) + + - EQ M Equivalent to the Window:EQ menu item. (See Section 2.6.) + + - EnvEdit M Equivalent to the Window:Envelope Edit menu item. (See + Section 2.5.) + + - NewFile M Equivalent to the File:New menu item. Opens a new file + editing window for creating and loading a Lisp or SAL program file. + + - OpenFile M Equivalent to the File:Open menu item. Opens an existing + Lisp or SAL program file for editing and loading. + + - SaveFile M Equivalent to the File:Save menu item (found on the + editing window's menu bar). Saves the contents of an editing window + to its associated file. + + - Load M Equivalent to the File:Load menu item (found on the editing + window's menu bar). Performs a Save operation, then sends a command + to Nyquist that loads the file as a program. + + - Mark M Sends a Control-A to Nyquist. While playing a sound, this + displays and records the approximate time in the audio stream. (See + Section 7.5 for more detail.) + +2.3. Command Completion + To help with programming, NyquistIDE maintains a command-completion window. +As you type the first letters of function names, NyquistIDE lists matching +functions and their parameters in the Completion List window. If you click on +an entry in this window, the displayed expression will replace the incompletely +typed function name. A preference allows you to match initial letters or any +substring of the complete function name. This is controlled by the ``Use full +search for code completion'' preference. + + In addition, if you right click (or under Mac OS X, hold down the Alt/Option +key and click) on an entry, NyquistIDE will display documentation for the +function. Documentation can come from a local copy or from the online copy +(determined by the ``Use online manual instead of local copy'' preference). +Documentation can be displayed within the NyquistIDE window or in an external +browser (determined by the ``Use window in NyquistIDE for help browser'' +preference.) Currently, the external browser option does not seem to locate +documentation properly, but this should be fixed in the future. + +2.4. Browser + If you click on the Browse button or use the Window:Browse menu command, +NyquistIDE will display a browser window that is pre-loaded with a number of +Nyquist commands to create sounds. You can adjust parameters, audition the +sounds, and capture the expression that creates the sound. In many cases, the +expression checks to see if necessary functions are defined, loading files if +necessary before playing the sound. If you want to use a sound in your own +program, you can often simplify things by explicitly loading the required file +just once at the beginning of your file. + + Since Nyquist now supports a mix of Lisp and SAL, you may find yourself in +the position of having code from the browser in one language while you are +working in the other. The best way to handle this is to put the code for the +sound you want into a function defined in a Lisp (.lsp) or SAL (.sal) file. +Load the file (from Lisp, use the sal-load command to load a SAL file), and +call the function from the language of your choice. + +2.5. Envelope Editor + The envelope editor allows you graphically to design and edit piece-wise +linear and exponential envelopes. The editor maintains a list of envelopes and +you select the one to edit or delete using the drop down list in the Saved +Envelopes List area. The current envelope appears in the Graphical Envelope +Editor area. You can click to add or drag points. Alternatively, you can use +the Envelope Points window to select and edit any breakpoint by typing +coordinates. The duration of the envelope is controlled by the Stop field in +the Range area, and the vertical axis is controlled by the Min and Max fields. + + When you click the Save button, all envelopes are written to Nyquist. You +can then use the envelope by treating the envelope name as a function. For +example, if you define an envelope named ``fast-attack,'' then you can create +the envelope within a Nyquist SAL program by writing the expression +fast-attack(). + + These edited envelopes are saved to a file named workspace.lsp in the +current directory. The workspace is Nyquist's mechanism for saving data of all +kinds (see Section 13.4.5). The normal way to work with workspaces is to (1) +load the workspace, i.e. load "workspace", as soon as you start Nyquist; (2) +invoke the envelope editor to change values in the workspace; and (3) save the +workspace at any time, especially before you exit NyquistIDE. If you follow +these steps, envelopes will be preserved from session to session, and the +entire collection of envelopes will appear in the editor. Be sure to make +backups of your workspace.lsp file along with your other project files. + + The envelope editor can create linear and exponential envelopes. Use the Type +pull-down menu to select the type you want. Envelopes can be created using +default starting and ending values using pwl or pwe, or you can specify the +initial values using pwlv or pwev. The envelope editor uses pwl or pwe if no +point is explicitly entered as the initial or final point. To create a pwlv or +pwev function, create a point and drag it to the leftmost or rightmost edge of +the graphical editing window. You will see the automatically generated default +starting or ending point disappear from the graph. + + Exponential envelopes should never decay to zero. If you enter a zero +amplitude, you will see that the envelope remains at zero to the next +breakpoint. To get an exponential decay to ``silence,'' try using an amplitude +of about 0.001 (about -60dB). To enter small values like this, you can type +them into the Amplitude box and click ``Update Point.'' + + The Load button refreshes the editor from data saved in the Nyquist process. +Normally, there is no need to use this because the editor automatically loads +data when you open it. + +2.6. Equalizer Editor + The Equalizer Editor provides a graphical EQ interface for creating and +adjusting equalizers. Unlike the envelope editor, where you can type any +envelope name, equalizers are named eq-0, eq-1, etc., and you select the +equalizer to edit using a pull-down menu. The Set button should be use to +record changes. + +2.7. UPIC Editor + The UPIC Editor is inspired by the UPIC system by Iannis Xenakis at the +Centre d'Edudes de Mathematique et Automatique Musicales (CEMaMu). The UPIC +Editor is accessed by the ``Upic Edit'' menu item in the ``Window'' menu of the +NyquistIDE. Once opened, you can draw pitch contours in the main panel by +pressing the left mouse button and dragging with the mouse down. Contours +represent tones in a frequency vs. time coordinate system. Any contour can be +deleted by right-clicking (or shift-clicking on an Apple computer) to select +the contour (indicated by the color red), and typing the Delete key. + + A collection of contours can be saved to a file and later retrieved using the +items in the File menu (use the File menu in the UPIC Editor window, not in the +main NyquistIDE window.) The file is a SAL program in a special format that can +be parsed by the UPIC Editor. The file can also be loaded into Nyquist using +the File:Load menu item, or by executing a load command in Nyquist. + + The panel at the top of the editor offers control over various parameters. +The Name box is a Nyquist variable name. This name takes effect when you save a +file from the UPIC Editor. The variable name is stored in the file so that when +a UPIC Editor-generated file is loaded into Nyquist, the data is assigned to +this variable name. The data is a list of contours, where each contour +specifies a waveform, an envelope, and a list of time-frequency coordinates. + + The next item in the panel is the Waveform box. The Waveform box names a +waveform for a contour. Default waveforms are sinusoid, triangle, and sawtooth, +but you can type in your own names. The currently selected waveform is stored +with the contour when it is created (entered by drawing). You cannot change or +edit the waveform name associated with a contour once the contour is created, +but you can always delete the contour and replace it. The Envelope box names an +envelope for a contour. The envelope names a Nyquist function. The default, +upic-env is a trapezoid shape with an onset time and offset time of 10ms. As +with waveforms, the envelope is stored with each contour when the contour is +created and cannot be edited. + + The Stop Time box gives the duration of the drawing area in seconds. The Min +Freq box gives the minimum frequency (at the bottom of the drawing area), and +the Max Freq box gives the maximum frequency (at the top of the drawing area). +The vertical frequency axis can use a linear scale corresponding to frequency +in Hertz or a logarithmic scale corresponding to semitones. The ``linear'' +checkbox selects the linear scale. When any of these parameters (described in +this paragraph and delimited by the border labeled ``Range'' on the control +panel) is changed, you must press the Update Range button for the change to +take effect. + + The Background menu lets you display a grid that indicates pitch locations. +The ``C's'' item draws a line at C in every visible octave. E.g. middle C is +about 260 Hz, so a reference line will be drawn near 260 Hz. Lines will be +drawn around 130 Hz (an octave below middle C), and around 520 Hz (an octave +above middle C), etc. The ``GrandStaff'' menu item draws reference lines for +each line of the grand staff commonly used for piano music. The pitches are G2, +B2, D3, F3, A3, E4, G4, B4, D5, and F5. Finally, you can load a picture using +the Background:Load Picture... menu item. Then, the Background:Show Picture +menu item toggles whether the picture is displayed or not. This feature allows +you to trace an image. (For example, see the Sonic Self-Portrait at +http://www.cs.cmu.edu/~rbd.) You may wish to use an image editor to lighten the +image so that superimposed contours will be more visible. + + Each change to the Range data, background choice, and each entry of a contour +is an action that you can undo or redo with the Undo and Redo buttons. + + To convert UPIC data into sound, first load upic.sal and load a file +generated by the UPIC Editor. Now, suppose the variable name used is upicdata. +You can play the data by writing + + play upic(upicdata) + +If you created your own names for waveforms or envelopes, you must be sure that +these exist before calling the upic function. Each waveform must be the name of +a variable which is set to a Nyquist wave table. (See Section 1.6.1 for +information on how to create a wave table.) Also, each envelope must name a +function with no parameters that will return an amplitude envelope. The +following is the built-in definition for upic-env: + + define function upic-env() + return env(0.01, 0.01, 0.01, 1, 1, 1) + +To make a custom envelope function named upic-smooth with a 0.2 second attack +and a 0.3 second decay, you could write: + + define function upic-smooth() + return env(0.2, 0.01, 0.3, 1, 1, 1) +3. Behavioral Abstraction + In Nyquist, all functions are subject to transformations. You can think of +transformations as additional parameters to every function, and functions are +free to use these additional parameters in any way. The set of transformation +parameters is captured in what is referred to as the transformation +environment. (Note that the term environment is heavily overloaded in computer +science. This is yet another usage of the term.) + + Behavioral abstraction is the ability of functions to adapt their behavior to +the transformation environment. This environment may contain certain abstract +notions, such as loudness, stretching a sound in time, etc. These notions will +mean different things to different functions. For example, an oscillator +should produce more periods of oscillation in order to stretch its output. An +envelope, on the other hand, might only change the duration of the sustain +portion of the envelope in order to stretch. Stretching a sample could mean +resampling it to change its duration by the appropriate amount. + + Thus, transformations in Nyquist are not simply operations on signals. For +example, if I want to stretch a note, it does not make sense to compute the +note first and then stretch the signal. Doing so would cause a drop in the +pitch. Instead, a transformation modifies the transformation environment in +which the note is computed. Think of transformations as making requests to +functions. It is up to the function to carry out the request. Since the +function is always in complete control, it is possible to perform +transformations with ``intelligence;'' that is, the function can perform an +appropriate transformation, such as maintaining the desired pitch and +stretching only the ''sustain'' portion of an envelope to obtain a longer note. + +3.1. The Environment + The transformation environment consists of a set of special variables. These +variables should not be read directly and should never be set directly by the +programmer. Instead, there are functions to read them, and they are +automatically set and restored by transformation operators, which will be +described below. + + The transformation environment consists of the following elements. Although +each element has a ``standard interpretation,'' the designer of an instrument +or the composer of a complex behavior is free to interpret the environment in +any way. For example, a change in *loud* may change timbre more than +amplitude, and *transpose* may be ignored by percussion instruments: + +*warp* Time transformation, including time shift, time stretch, and + continuous time warp. The value of *warp* is interpreted as a + function from logical (local score) time to physical (global + real) time. Do not access *warp* directly. Instead, use + local-to-global(t) to convert from a logical (local) time to + real (global) time. Most often, you will call local-to- + global(0). Several transformation operators operate on *warp*, + including at (@), stretch (~), and warp. See also + get-duration() and get-warp(). + +*loud* Loudness, expressed in decibels. The default (nominal) + loudness is 0.0 dB (no change). Do not access *loud* directly. + Instead, use get-loud() to get the current value of *loud* and + either loud or loud-abs to modify it. + +*transpose* Pitch transposition, expressed in semitones. (Default: 0.0). + Do not access *transpose* directly. Instead, use + get-transpose() to get the current value of *transpose* and + either transpose or transpose-abs to modify it. + +*sustain* The ``sustain,'' ``articulation,'' ``duty factor,'' or amount + by which to separate or overlap sequential notes. For example, + staccato might be expressed with a *sustain* of 0.5, while very + legato playing might be expressed with a *sustain* of 1.2. + Specifically, *sustain* stretches the duration of notes + (sustain) without affecting the inter-onset time (the rhythm). + Do not access *sustain* directly. Instead, use get-sustain() + to get the current value of *sustain* and either sustain or + sustain-abs to modify it. + +*start* Start time of a clipping region. Note: unlike the previous + elements of the environment, *start* has a precise + interpretation: no sound should be generated before *start*. + This is implemented in all the low-level sound functions, so it + can generally be ignored. You can read *start* directly, but + use extract or extract-abs to modify it. Note 2: Due to some + internal confusion between the specified starting time and the + actual starting time of a signal after clipping, *start* is not + fully implemented. + +*stop* Stop time of clipping region. By analogy to *start*, no sound + should be generated after this time. *start* and *stop* allow + a composer to preview a small section of a work without + computing it from beginning to end. You can read *stop* + directly, but use extract or extract-abs to modify it. Note: + Due to some internal confusion between the specified starting + time and the actual starting time of a signal after clipping, + *stop* is not fully implemented. + +*control-srate* Sample rate of control signals. This environment element + provides the default sample rate for control signals. There is + no formal distinction between a control signal and an audio + signal. You can read *control-srate* directly, but use + control-srate or control-srate-abs to modify it. + +*sound-srate* Sample rate of musical sounds. This environment element + provides the default sample rate for musical sounds. You can + read *sound-srate* directly, but use sound-srate or + sound-srate-abs to modify it. + +3.2. Sequential Behavior + Previous examples have shown the use of seq, the sequential behavior +operator. We can now explain seq in terms of transformations. Consider the +simple expression: + + play seq(my-note(c4, q), my-note(d4, i)) + +The idea is to create the first note at time 0, and to start the next note when +the first one finishes. This is all accomplished by manipulating the +environment. In particular, *warp* is modified so that what is locally time 0 +for the second note is transformed, or warped, to the logical stop time of the +first note. + + One way to understand this in detail is to imagine how it might be executed: +first, *warp* is set to an initial value that has no effect on time, and +my-note(c4, q) is evaluated. A sound is returned and saved. The sound has an +ending time, which in this case will be 1.0 because the duration q is 1.0. +This ending time, 1.0, is used to construct a new *warp* that has the effect of +shifting time by 1.0. The second note is evaluated, and will start at time 1. +The sound that is returned is now added to the first sound to form a composite +sound, whose duration will be 2.0. *warp* is restored to its initial value. + + Notice that the semantics of seq can be expressed in terms of +transformations. To generalize, the operational rule for seq is: evaluate the +first behavior according to the current *warp*. Evaluate each successive +behavior with *warp* modified to shift the new note's starting time to the +ending time of the previous behavior. Restore *warp* to its original value and +return a sound which is the sum of the results. + + In the Nyquist implementation, audio samples are only computed when they are +needed, and the second part of the seq is not evaluated until the ending time +(called the logical stop time) of the first part. It is still the case that +when the second part is evaluated, it will see *warp* bound to the ending time +of the first part. + + A language detail: Even though Nyquist defers evaluation of the second part +of the seq, the expression can reference variables according to ordinary +Lisp/SAL scope rules. This is because the seq captures the expression in a +closure, which retains all of the variable bindings. + +3.3. Simultaneous Behavior + Another operator is sim, which invokes multiple behaviors at the same time. +For example, + + play 0.5 * sim(my-note(c4, q), my-note(d4, i)) + +will play both notes starting at the same time. + + The operational rule for sim is: evaluate each behavior at the current *warp* +and return the sum of the results. (In SAL, the sim function applied to sounds +is equivalent to adding them with the infix + operator. The following section +illustrates two concepts: first, a sound is not a behavior, and second, the sim +operator and and the at transformation can be used to place sounds in time. + +3.4. Sounds vs. Behaviors + The following example loads a sound from a file in the current directory and +stores it in a-snd: + + ; load a sound + ; + set a-snd = s-read(strcat(current-path(), "demo-snd.aiff")) + + ; play it + ; + play a-snd + + One might then be tempted to write the following: + + play seq(a-snd, a-snd) ;WRONG! + +Why is this wrong? Recall that seq works by modifying *warp*, not by operating +on sounds. So, seq will proceed by evaluating a-snd with different values of +*warp*. However, the result of evaluating a-snd (a variable) is always the +same sound, regardless of the environment; in this case, the second a-snd +should start at time 0.0, just like the first. In this case, after the first +sound ends, Nyquist is unable to ``back up'' to time zero, so in fact, this +will play two sounds in sequence, but that is a result of an implementation +detail rather than correct program execution. In fact, a future version of +Nyquist might (correctly) stop and report an error when it detects that the +second sound in the sequence has a real start time that is before the requested +one. + + How then do we obtain a sequence of two sounds properly? What we really need +here is a behavior that transforms a given sound according to the current +transformation environment. That job is performed by cue. For example, the +following will behave as expected, producing a sequence of two sounds: + + play seq(cue(a-snd), cue(a-snd)) + +This example is correct because the second expression will shift the sound +stored in a-snd to start at the end time of the first expression. + + The lesson here is very important: sounds are not behaviors! Behaviors are +computations that generate sounds according to the transformation environment. +Once a sound has been generated, it can be stored, copied, added to other +sounds, and used in many other operations, but sounds are not subject to +transformations. To transform a sound, use cue, sound, or control. The +differences between these operations are discussed later. For now, here is a +``cue sheet'' style score that plays 4 copies of a-snd: + ; use sim and at to place sounds in time + ; + play sim(cue(a-snd) @ 0.0, + cue(a-snd) @ 0.7, + cue(a-snd) @ 1.0, + cue(a-snd) @ 1.2) + +3.5. The At Transformation + The second concept introduced by the previous example is the @ operation, +which shifts the *warp* component of the environment. For example, + + cue(a-snd) @ 0.7 + +can be explained operationally as follows: modify *warp* by shifting it by 0.7 +and evaluate cue(a-snd). Return the resulting sound after restoring *warp* to +its original value. Notice how @ is used inside a sim construct to locate +copies of a-snd in time. This is the standard way to represent a note-list or +a cue-sheet in Nyquist. + + This also explains why sounds need to be cue'd in order to be shifted in time +or arranged in sequence. If this were not the case, then sim would take all of +its parameters (a set of sounds) and line them up to start at the same time. +But cue(a-snd) @ 0.7 is just a sound, so sim would ``undo'' the effect of @, +making all of the sounds in the previous example start simultaneously, in spite +of the @! Since sim respects the intrinsic starting times of sounds, a special +operation, cue, is needed to create a new sound with a new starting time. + +3.6. The Stretch Transformation + In addition to At (denoted in SAL by the @ operator, the Stretch +transformation is very important. It appeared in the introduction, and it is +denoted in SAL by the ~ operator (or in LISP by the stretch special form). +Stretch also operates on the *warp* component of the environment. For example, + + osc(c4) ~ 3 + +does the following: modify *warp*, scaling the degree of "stretch" by 3, and +evaluate osc(c4). The osc behavior uses the stretch factor to determime the +duration, so it will return a sound that is 3 seconds long. Restore *warp* to +its original value. Like At, Stretch only affects behaviors. a-snd ~ 10 is +equivalent to a-snd because a-snd is a sound, not a behavior. Behaviors are +functions that compute sounds according to the environment and return a sound. + +3.7. Nested Transformations + Transformations can be combined using nested expressions. For example, + + sim(cue(a-snd), + loud(6.0, cue(a-snd) @ 3)) + +scales the amplitude as well as shifts the second entrance of a-snd. + + Why use loud instead of simply multiplying a-snd by some scale factor? Using +loud gives the behavior the chance to implement the abstract property loudness +in an appropriate way, e.g. by including timbral changes. In this case, the +behavior is cue, which implements loudness by simple amplitude scaling, so the +result is equivalent to multiplication by db-to-linear(6.0). + + Transformations can also be applied to groups of behaviors: + + loud(6.0, sim(cue(a-snd) @ 0.0, + cue(a-snd) @ 0.7)) + +3.8. Defining Behaviors + Groups of behaviors can be named using define (we already saw this in the +definitions of my-note and env-note). Here is another example of a behavior +definition and its use. The definition has one parameter: + + define function snds(dly) + return sim(cue(a-snd) @ 0.0, + cue(a-snd) @ 0.7, + cue(a-snd) @ 1.0, + cue(a-snd) @ (1.2 + dly)) + + play snds(0.1) + play loud(0.25, snds(0.3) ~ 0.9) + +In the last line, snds is transformed: the transformations will apply to the +cue behaviors within snds. The loud transformation will scale the sounds by +0.25, and the stretch (~) will apply to the shift (@) amounts 0.0, 0.7, 1.0, +and 1.2 + dly. The sounds themselves (copies of a-snd) will not be stretched +because cue never stretches sounds. + + Section 7.3 describes the full set of transformations. + +3.9. Overriding Default Transformations + In Nyquist, behaviors are the important abstraction mechanism. A behavior +represents a class of related functions or sounds. For example, a behavior can +represent a musical note. When a note is stretched, it usually means that the +tone sustains for more oscillations, but if the ``note'' is a drum roll, the +note sustains by more repetitions of the component drum strokes. The concept of +sustain is so fundamental that we do not really think of different note +durations as being different instances of an abstract behavior, but in a music +programming language, we need a way to model these abtract behaviors. As the +tone and drum roll examples show, there is no one right way to ``stretch,'' so +the language must allow users to define exactly what it means to stretch. By +extension, the Nyquist programmer can define how all of the transformations +affect different behaviors. + + To make programming easier, almost all Nyquist sounds are constructed from +primitive behaviors that obey the environment in obvious ways: Stretch +transformations make things longer and At transformations shift things in time. +But sometimes you have to override the default behaviors. Maybe the attack +phase of an envelope should not stretch when the note is stretched, or maybe +when you stretch a trill, you should get more notes rather than a slower trill. + + To override default behaviors, you almost always follow the same programming +pattern: first, capture the environment in a local variable; then, use one of +the absolute transformations to ``turn off'' the environment's effect and +compute the sound as desired. The following example creates a very simple +envelope with a fixed rise time to illustrate the technique. + + define function two-phase-env(rise-time) + begin + with dur = get-duration(1) + return pwl(rise-time, 1, dur) ~~ 1.0 + end + +To ``capture the environment in a local variable,'' a with construct is used to +create the local variable dur and set it to the value of get-duration(1), which +answers the question: ``If I apply use the environment to stretch something +whose nominal duration is 1, what is the resulting duration?'' (Since time +transformations can involve continuous time deformations, this question is not +as simple as it may sound, so please use the provided function rather than +peeking inside the *warp* structure and trying to do it yourself.) Next, we +``turn off'' stretching using the stretch-abs form, which in SAL is denoted by +the ~~ operator. Finally, we are ready to compute the envelope using pwl. +Here, we use absolute durations. The first breakpoint is at rise-time, so the +attack time is given by the rise-time parameter. The pwl decays back to zero at +time dur, so the overall duration matches the duration expected from the +environment encountered by this instance of two-phase-env. Note, however, that +since the pwl is evaluated in a different environment established by ~~, it is +not stretched (or perhaps more accurately, it is stretched by 1.0). This is +good because it means rise-time will not be stretched, but we must be careful +to extend the envelope to dur so that it has the expected duration. + +3.10. Sample Rates + The global environment contains *sound-srate* and *control-srate*, which +determine the sample rates of sounds and control signals. These can be +overridden at any point by the transformations sound-srate-abs and +control-srate-abs; for example, + + sound-srate-abs(44100.0, osc(c4) + +will compute a tone using a 44.1Khz sample rate even if the default rate is set +to something different. + + As with other components of the environment, you should never change +*sound-srate* or *control-srate* directly. The global environment is +determined by two additional variables: *default-sound-srate* and *default- +control-srate*. You can add lines like the following to your init.lsp file to +change the default global environment: + + (setf *default-sound-srate* 44100.0) + (setf *default-control-srate* 1102.5) + +You can also do this using preferences in NyquistIDE. If you have already +started Nyquist and want to change the defaults, the preferences or the +following functions can be used: + + exec set-control-srate(1102.5)exec set-sound-srate(22050.0) + +These modify the default values and reinitialize the Nyquist environment. +4. Continuous Transformations and Time Warps + Nyquist transformations were discussed in the previous chapter, but all of +the examples used scalar values. For example, we saw the loud transformation +used to change loudness by a fixed amount. What if we want to specify a +crescendo, where the loudness changes gradually over time? + + It turns out that all transformations can accept signals as well as numbers, +so transformations can be continuous over time. This raises some interesting +questions about how to interpret continuous transformations. Should a loudness +transformation apply to the internal details of a note or only affect the +initial loudness? It might seem unnatural for a decaying piano note to perform +a crescendo. On the other hand, a sustained trumpet sound should probably +crescendo continuously. In the case of time warping (tempo changes), it might +be best for a drum roll to maintain a steady rate, a trill may or may not +change rates with tempo, and a run of sixteenth notes will surely change its +rate. + + These issues are complex, and Nyquist cannot hope to automatically do the +right thing in all cases. However, the concept of behavioral abstraction +provides an elegant solution. Since transformations merely modify the +environment, behaviors are not forced to implement any particular style of +transformation. Nyquist is designed so that the default transformation is +usually the right one, but it is always possible to override the default +transformation to achieve a particular effect. + +4.1. Simple Transformations + The ``simple'' transformations affect some parameter, but have no effect on +time itself. The simple transformations that support continuously changing +parameters are: sustain, loud, and transpose. + + As a first example, Let us use transpose to create a chromatic scale. First +define a sequence of tones at a steady pitch. The seqrep ``function'' works +like seq except that it creates copies of a sound by evaluating an expression +multiple times. Here, i takes on 16 values from 0 to 15, and the expression for +the sound could potentially use i. Technically, seqrep is not really a +function but an abbreviation for a special kind of loop construct. + + define function tone-seq() + return seqrep(i, 16, + osc-note(c4) ~ 0.25) + +Now define a linearly increasing ramp to serve as a transposition function: +define function pitch-rise() return sustain-abs(1.0, 16 * ramp() ~ 4) This ramp +has a duration of 4 seconds, and over that interval it rises from 0 to 16 +(corresponding to the 16 semitones we want to transpose). The ramp is inside a +sustain-abs transformation, which prevents a sustain transformation from having +any effect on the ramp. (One of the drawbacks of behavioral abstraction is that +built-in behaviors sometimes do the wrong thing implicitly, requiring some +explicit correction to turn off the unwanted transformation.) Now, pitch-rise +is used to transpose tone-seq: define function chromatic-scale() return +transpose(pitch-rise(), tone-seq()) + + Similar transformations can be constructed to change the sustain or ``duty +factor'' of notes and their loudness. The following expression plays the +chromatic-scale behavior with increasing note durations. The rhythm is +unchanged, but the note length changes from staccato to legato: play +sustain((0.2 + ramp()) ~ 4, chromatic-scale()) The resulting sustain function +will ramp from 0.2 to 1.2. A sustain of 1.2 denotes a 20 percent overlap +between notes. The sum has a stretch factor of 4, so it will extend over the 4 +second duration of chromatic-scale. + + If you try this, you will discover that the chromatic-scale no longer plays a +chromatic scale. You will hear the first 4 notes going up in intervals of 5 +semitones (perfect fourths) followed by repeated pitches. What is happening is +that the sustain operation applies to pitch-rise in addition to tone-seq, so +now the 4s ramp from 0 to 16 becomes a 0.8s ramp. To fix this problem, we need +to shield pitch-rise from the effect of sustain using the sustain-abs +transformation. Here is a corrected version of chromatic-scale: define +function chromatic-scale() return transpose(sustain-abs(1, pitch-rise()), +tone-seq()) + + What do these transformations mean? How did the system know to produce a +pitch rise rather than a continuous glissando? This all relates to the idea of +behavioral abstraction. It is possible to design sounds that do glissando +under the transpose transform, and you can even make sounds that ignore +transpose altogether. As explained in Chapter 3, the transformations modify +the environment, and behaviors can reference the environment to determine what +signals to generate. All built-in functions, such as osc, have a default +behavior. + + The default behavior for sound primitives under transpose, sustain, and loud +transformations is to sample the environment at the beginning of the note. +Transposition is not quantized to semitones or any other scale, but in our +example, we arranged for the transposition to work out to integer numbers of +semitones, so we obtained a chromatic scale anyway. + + Transposition only applies to the oscillator and sampling primitives osc, +partial, sampler, sine, fmosc, and amosc. Sustain applies to osc, env, ramp, +and pwl. (Note that partial, amosc, and fmosc get their durations from the +modulation signal, so they may indirectly depend upon the sustain.) Loud +applies to osc, sampler, cue, sound, fmosc, and amosc. (But not pwl or env.) + +4.2. Time Warps + The most interesting transformations have to do with transforming time +itself. The warp transformation provides a mapping function from logical +(score) time to real time. The slope of this function tells us how many units +of real time are covered by one unit of score time. This is proportional to +1/tempo. A higher slope corresponds to a slower tempo. + + To demonstrate warp, we will define a time warp function using pwl: + + define function warper() + return pwl(0.25, .4, .75, .6, 1.0, 1.0, 2.0, 2.0, 2.0) + +This function has an initial slope of .4/.25 = 1.6. It may be easier to think +in reciprocal terms: the initial tempo is .25/.4 = .625. Between 0.25 and +0.75, the tempo is .5/.2 = 2.5, and from 0.75 to 1.0, the tempo is again .625. +It is important for warp functions to completely span the interval of interest +(in our case it will be 0 to 1), and it is safest to extend a bit beyond the +interval, so we extend the function on to 2.0 with a tempo of 1.0. Next, we +stretch and scale the warper function to cover 4 seconds of score time and 4 +seconds of real time: + + define function warp4() + return 4 * warper() ~ 4 + + + + + + + + + + + + + + + + + + + + + + + + Figure 2: The result of (warp4), intended to map 4 seconds of score + time into 4 seconds of real time. The function extends beyond 4 + seconds (the dashed lines) to make sure the function is well-defined + at location (4, 4). Nyquist sounds are ordinarily open on the + right. + + + Figure 2 shows a plot of this warp function. Now, we can warp the tempo of +the tone-seq defined above using warp4: + + play warp(warp4(), tone-seq()) + +Figure 3 shows the result graphically. Notice that the durations of the tones +are warped as well as their onsets. Envelopes are not shown in detail in the +figure. Because of the way env is defined, the tones will have constant attack +and decay times, and the sustain will be adjusted to fit the available time. + + + + + + + + + + + + + + + Figure 3: When (warp4) is applied to (tone-seq-2), the note onsets + and durations are warped. + + +4.3. Abstract Time Warps + We have seen a number of examples where the default behavior did the ``right +thing,'' making the code straightforward. This is not always the case. +Suppose we want to warp the note onsets but not the durations. We will first +look at an incorrect solution and discuss the error. Then we will look at a +slightly more complex (but correct) solution. + + The default behavior for most Nyquist built-in functions is to sample the +time warp function at the nominal starting and ending score times of the +primitive. For many built-in functions, including osc, the starting logical +time is 0 and the ending logical time is 1, so the time warp function is +evaluated at these points to yield real starting and stopping times, say 15.23 +and 16.79. The difference (e.g. 1.56) becomes the signal duration, and there +is no internal time warping. The pwl function behaves a little differently. +Here, each breakpoint is warped individually, but the resulting function is +linear between the breakpoints. + + A consequence of the default behavior is that notes stretch when the tempo +slows down. Returning to our example, recall that we want to warp only the +note onset times and not the duration. One would think that the following +would work: + + define function tone-seq-2 () + return seqrep(i, 16, + osc-note(c4) ~~ 0.25) + + play warp(warp4(), tone-seq-2()) +Here, we have redefined tone-seq, renaming it to tone-seq-2 and changing the +stretch (~) to absolute stretch (~~). The absolute stretch should override the +warp function and produce a fixed duration. + + If you play the example, you will hear steady sixteenths and no tempo +changes. What is wrong? In a sense, the ``fix'' works too well. Recall that +sequences (including seqrep) determine the starting time of the next note from +the logical stop time of the previous sound in the sequence. When we forced +the stretch to 0.25, we also forced the logical stop time to 0.25 real seconds +from the beginning, so every note starts 0.25 seconds after the previous one, +resulting in a constant tempo. + + Now let us design a proper solution. The trick is to use absolute stretch +(~~) as before to control the duration, but to restore the logical stop time to +a value that results in the proper inter-onset time interval: + + define function tone-seq-3() + return seqrep(i, 16, + set-logical-stop(osc-note(c4) ~~ 0.25, 0.25)) + + play warp(warp4(), tone-seq-3()) + +Notice the addition of set-logical-stop enclosing the absolute stretch (~~) +expression to set the logical stop time. A possible point of confusion here is +that the logical stop time is set to 0.25, the same number given to ~~! How +does setting the logical stop time to 0.25 result in a tempo change? When used +within a warp transformation, the second argument to set-logical-stop refers to +score time rather than real time. Therefore, the score duration of 0.25 is +warped into real time, producing tempo changes according to the enviroment. +Figure 4 illustrates the result graphically. + + + + + + + + + + + + + + + Figure 4: When (warp4) is applied to (tone-seq-3), the note onsets + are warped, but not the duration, which remains a constant 0.25 + seconds. In the fast middle section, this causes notes to overlap. + Nyquist will sum (mix) them. + + +4.4. Nested Transformations + Transformations can be nested. In particular, a simple transformation such +as transpose can be nested within a time warp transformation. Suppose we want +to warp our chromatic scale example with the warp4 time warp function. As in +the previous section, we will show an erroneous simple solution followed by a +correct one. + + The simplest approach to a nested transformation is to simply combine them +and hope for the best: + + play warp(warp4(), + transpose(pitch-rise(), tone-seq())) + +This example will not work the way you might expect. Here is why: the warp +transformation applies to the (pitch-rise) expression, which is implemented +using the ramp function. The default behavior of ramp is to interpolate +linearly (in real time) between two points. Thus, the ``warped'' ramp function +will not truly reflect the internal details of the intended time warp. When +the notes are moving faster, they will be closer together in pitch, and the +result is not chromatic. What we need is a way to properly compose the warp +and ramp functions. If we continuously warp the ramp function in the same way +as the note sequence, a chromatic scale should be obtained. This will lead to +a correct solution. + + Here is the modified code to properly warp a transposed sequence. Note that +the original sequence is used without modification. The only complication is +producing a properly warped transposition function: + + play warp(warp4(), + transpose( + control-warp(get-warp(), + warp-abs(nil, pitch-rise())), + tone-seq())) + +To properly warp the pitch-rise transposition function, we use control-warp, +which applies a warp function to a function of score time, yielding a function +of real time. We need to pass the desired function to control-warp, so we +fetch it from the environment with get-warp(). Finally, since the warping is +done here, we want to shield the pitch-rise expression from further warping, so +we enclose it in warp-abs(nil, ...). + + An aside: This last example illustrates a difficulty in the design of +Nyquist. To support behavioral abstraction universally, we must rely upon +behaviors to ``do the right thing.'' In this case, we would like the ramp +function to warp continuously according to the environment. But this is +inefficient and unnecessary in many other cases where ramp and especially pwl +are used. (pwl warps its breakpoints, but still interpolates linearly between +them.) Also, if the default behavior of primitives is to warp in a continuous +manner, this makes it difficult to build custom abstract behaviors. The final +vote is not in. +5. More Examples + This chapter explores Nyquist through additional examples. The reader may +wish to browse through these and move on to Chapter 7, which is a reference +section describing Nyquist functions. + +5.1. Stretching Sampled Sounds + This example illustrates how to stretch a sound, resampling it in the +process. Because sounds in Nyquist are values that contain the sample rate, +start time, etc., use sound to convert a sound into a behavior that can be +stretched, e.g. sound(a-snd). This behavior stretches a sound according to the +stretch factor in the environment, set using stretch. For accuracy and +efficiency, Nyquist does not resample a stretched sound until absolutely +necessary. The force-srate function is used to resample the result so that we +end up with a ``normal'' sample rate that is playable on ordinary sound cards. + + ; if a-snd is not loaded, load sound sample: + ; + if not(boundp(quote(a-snd))) then + set a-snd = s-read("demo-snd.aiff") + + ; the SOUND operator shifts, stretches, clips and scales + ; a sound according to the current environment + ; + define function ex23() + play force-srate(*default-sound-srate*, sound(a-snd) ~ 3.0) + + define function down() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.2, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.6)) + play down() + + ; that was so much fun, let's go back up: + ; + define function up() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.5, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.2)) + + ; and write a sequence + ; + play seq(down(), up(), down()) + + Notice the use of the sound behavior as opposed to cue. The cue behavior +shifts and scales its sound according to *warp* and *loud*, but it does not +change the duration or resample the sound. In contrast, sound not only shifts +and scales its sound, but it also stretches it by resampling or changing the +effective sample rate according to *warp*. If *warp* is a continuous warping +function, then the sound will be stretched by time-varying amounts. (The +*transpose* element of the environment is ignored by both cue and sound.) + + Note: sound may use linear interpolation rather than a high-quality +resampling algorithm. In some cases, this may introduce errors audible as +noise. Use resample (see Section 7.2.2) for high-quality interpolation. + + In the functions up and down, the *warp* is set by stretch (~), which simply +scales time by a constant scale factor. In this case, sound can ``stretch'' the +signal simply by changing the sample rate without any further computation. When +seq tries to add the signals together, it discovers the sample rates do not +match and uses linear interpolation to adjust all sample rates to match that of +the first sound in the sequence. The result of seq is then converted using +force-srate to convert the sample rate, again using linear interpolation. It +would be slightly better, from a computational standpoint, to apply force-srate +individually to each stretched sound rather than applying force-srate after +seq. + + Notice that the overall duration of sound(a-snd) ~ 0.5 will be half the +duration of a-snd. + +5.2. Saving Sound Files + So far, we have used the play command to play a sound. The play command +works by writing a sound to a file while simultaneously playing it. This can +be done one step at a time, and it is often convenient to save a sound to a +particular file for later use: + + ; write the sample to a file, + ; the file name can be any Unix filename. Prepending a "./" tells + ; s-save to not prepend *default-sf-dir* + ; + exec s-save(a-snd, 1000000000, "./a-snd-file.snd") + + ; play a file + ; play command normally expects an expression for a sound + ; but if you pass it a string, it will open and play a + ; sound file + play "./a-snd-file.snd" + + ; delete the file (do this with care!) + ; only works under Unix (not Windows) + exec system("rm ./a-snd-file.snd") + + ; now let's do it using a variable as the file name + ; + set my-sound-file = "./a-snd-file.snd" + + exec s-save(a-snd, 1000000000, my-sound-file) + + ; play-file is a function to open and play a sound file + exec play-file(my-sound-file) + + exec system(strcat("rm ", my-sound-file)) + +This example shows how s-save can be used to save a sound to a file. + + This example also shows how the system function can be used to invoke Unix +shell commands, such as a command to play a file or remove it. Finally, notice +that strcat can be used to concatenate a command name to a file name to create +a complete command that is then passed to system. (This is convenient if the +sound file name is stored in a parameter or variable.) + +5.3. Memory Space and Normalization + Sound samples take up lots of memory, and often, there is not enough primary +(RAM) memory to hold a complete composition. For this reason, Nyquist can +compute sounds incrementally, saving the final result on disk. However, +Nyquist can also save sounds in memory so that they can be reused efficiently. +In general, if a sound is saved in a global variable, memory will be allocated +as needed to save and reuse it. + + The standard way to compute a sound and write it to disk is to pass an +expression to the play command: + + play my-composition() + + Often it is nice to normalize sounds so that they use the full available +dynamic range of 16 bits. Nyquist has an automated facility to help with +normalization. By default, Nyquist computes up to 1 million samples (using +about 4MB of memory) looking for the peak. The entire sound is normalized so +that this peak will not cause clipping. If the sound has less than 1 million +samples, or if the first million samples are a good indication of the overall +peak, then the signal will not clip. + + With this automated normalization technique, you can choose the desired peak +value by setting *autonorm-target*, which is initialized to 0.9. The number of +samples examined is *autonorm-max-samples*, initially 1 million. You can turn +this feature off by executing: + + exec autonorm-off() + +and turn it back on by typing: + + exec autonorm-on() + +This normalization technique is in effect when *autonorm-type* is +quote(lookahead), which is the default. + + An alternative normalization method uses the peak value from the previous +call to play. After playing a file, Nyquist can adjust an internal scale factor +so that if you play the same file again, the peak amplitude will be +*autonorm-target*, which is initialized to 0.9. This can be useful if you want +to carefully normalize a big sound that does not have its peak near the +beginning. To select this style of normalization, set *autonorm-type* to the +(quoted) atom quote(previous). + + You can also create your own normalization method in Nyquist. The peak +function computes the maximum value of a sound. The peak value is also +returned from the play macro. You can normalize in memory if you have enough +memory; otherwise you can compute the sound twice. The two techniques are +illustrated here: + + ; normalize in memory. First, assign the sound to a variable so + ; it will be retained: + set mysound = sim(osc(c4), osc(c5)) + ; now compute the maximum value (ny:all is 1 giga-samples, you may want + ; smaller constant if you have less than 4GB of memory: + set mymax = snd-max(mysound, NY:ALL) + display "Computed max", mymax + ; now write out and play the sound from memory with a scale factor: + play mysound * (0.9 / mymax) + + ; if you don't have space in memory, here's how to do it: + define function myscore() + return sim(osc(c4), osc(c5)) + ; compute the maximum: + set mymax = snd-max(list(quote(myscore)), NY:ALL) + display "Computed max", mymax + ; now we know the max, but we don't have a the sound (it was garbage + ; collected and never existed all at once in memory). Compute the soun + ; again, this time with a scale factor: + play myscore() * (0.9 / mymax) + + You can also write a sound as a floating point file. This file can then be +converted to 16-bit integer with the proper scaling applied. If a long +computation was involved, it should be much faster to scale the saved sound +file than to recompute the sound from scratch. Although not implemented yet in +Nyquist, some header formats can store maximum amplitudes, and some soundfile +player programs can rescale floating point files on the fly, allowing +normalized soundfile playback without an extra normalization pass (but at a +cost of twice the disk space of 16-bit samples). You can use Nyquist to +rescale a floating point file and convert it to 16-bit samples for playback. + +5.4. Frequency Modulation + The next example uses the Nyquist frequency modulation behavior fmosc to +generate various sounds. The parameters to fmosc are: + + fmosc(pitch modulator table phase) +Note that pitch is the number of half-steps, e.g. c4 has the value of 60 which +is middle-C, and phase is in degrees. Only the first two parameters are +required: + + ; make a short sine tone with no frequency modulation + ; + play fmosc(c4, pwl(0.1)) + + ; make a longer sine tone -- note that the duration of + ; the modulator determines the duration of the tone + ; + play fmosc(c4, pwl(0.5)) + +In the example above, pwl (for Piece-Wise Linear) is used to generate sounds +that are zero for the durations of 0.1 and 0.5 seconds, respectively. In +effect, we are using an FM oscillator with no modulation input, and the result +is a sine tone. The duration of the modulation determines the duration of the +generated tone (when the modulation signal ends, the oscillator stops). + + The next example uses a more interesting modulation function, a ramp from +zero to C , expressed in hz. More explanation of pwl is in order. This + 4 +operation constructs a piece-wise linear function sampled at the +*control-srate*. The first breakpoint is always at (0, 0), so the first two +parameters give the time and value of the second breakpoint, the second two +parameters give the time and value of the third breakpoint, and so on. The +last breakpoint has a value of 0, so only the time of the last breakpoint is +given. In this case, we want the ramp to end at C , so we cheat a bit by + 4 +having the ramp return to zero ``almost'' instantaneously between times 0.5 and +0.501. + + The pwl behavior always expects an odd number of parameters. The resulting +function is shifted and stretched linearly according to *warp* in the +environment. Now, here is the example: + + ; make a frequency sweep of one octave; the piece-wise linear function + ; sweeps from 0 to (step-to-hz c4) because, when added to the c4 + ; fundamental, this will double the frequency and cause an octave sweep + ; + play fmosc(c4, pwl(0.5, step-to-hz(c4), 0.501)) + + The same idea can be applied to a non-sinusoidal carrier. Here, we assume +that *fm-voice* is predefined (the next section shows how to define it): + + ; do the same thing with a non-sine table + ; + play fmosc(cs2, pwl(0.5, step-to-hz(cs2), 0.501), + *fm-voice*, 0.0) + + The next example shows how a function can be used to make a special frequency +modulation contour. In this case the contour generates a sweep from a starting +pitch to a destination pitch: + + ; make a function to give a frequency sweep, starting + ; after seconds, then sweeping from + ; to in seconds and then + ; holding at for seconds. + ; + define function sweep(delay, pitch-1, sweep-time, + pitch-2, hold-time) + begin + with interval = step-to-hz(pitch-2) - step-to-hz(pitch-1) + return pwl(delay, 0.0, + ; sweep from pitch 1 to pitch 2 + delay + sweep-time, interval, + ; hold until about 1 sample from the end + delay + sweep-time + hold-time - 0.0005, + interval, + ; quickly ramp to zero (pwl always does this, + ; so make it short) + delay + sweep-time + hold-time) + end + + + ; now try it out + ; + play fmosc(cs2, sweep(0.1, cs2, 0.6, gs2, 0.5), + *fm-voice*, 0.0) + + FM can be used for vibrato as well as frequency sweeps. Here, we use the lfo +function to generate vibrato. The lfo operation is similar to osc, except it +generates sounds at the *control-srate*, and the parameter is hz rather than a +pitch: + + play fmosc(cs2, 10.0 * lfo(6.0), *fm-voice*, 0.0) + + What kind of manual would this be without the obligatory FM sound? Here, a +sinusoidal modulator (frequency C ) is multiplied by a slowly increasing ramp + 4 +from zero to 1000.0. + + set modulator = pwl(1.0, 1000.0, 1.0005) * + osc(c4) + ; make the sound + play fmosc(c4, modulator) + + For more simple examples of FM in Nyquist, see demos/warble_tutorial.htm. +Another interesting FM sound reminiscent of ``scratching'' can be found with a +detailed explanation in demos/scratch_tutorial.htm.. + +5.5. Building a Wavetable + In Section 1.6.1, we saw how to synthesize a wavetable. A wavetable for osc +also can be extracted from any sound. This is especially interesting if the +sound is digitized from some external sound source and loaded using the s-read +function. Recall that a table is a list consisting of a sound, the pitch of +that sound, and T (meaning the sound is periodic). + + In the following, a sound is first read from the file demo-snd.nh. Then, the +extract function is used to extract the portion of the sound between 0.110204 +and 0.13932 seconds. (These numbers might be obtained by first plotting the +sound and estimating the beginning and end of a period, or by using some +software to look for good zero crossings.) The result of extract becomes the +first element of a list. The next element is the pitch (24.848422), and the +last element is T. The list is assigned to *fm-voice*. + + if not(boundp(quote(a-snd))) then + set a-snd = s-read("demo-snd.aiff") + + set *fm-voice* = list(extract(0.110204, 0.13932, cue(a-snd)), + 24.848422, + #T) + + The file demos/examples.sal contains an extensive example of how to locate +zero-crossings, extract a period, build a waveform, and generate a tone from +it. (See ex37 through ex40 in the file.) + +5.6. Filter Examples + Nyquist provides a variety of filters. All of these filters take either real +numbers or signals as parameters. If you pass a signal as a filter parameter, +the filter coefficients are recomputed at the sample rate of the control +signal. Since filter coefficients are generally expensive to compute, you may +want to select filter control rates carefully. Use control-srate-abs (Section +7.3) to specify the default control sample rate, or use force-srate (Section +7.2.2) to resample a signal before passing it to a filter. + + Before presenting examples, let's generate some unfiltered white noise: + + play noise() + +Now low-pass filter the noise with a 1000Hz cutoff: + + play lp(noise(), 1000.0) + +The high-pass filter is the inverse of the low-pass: + + play hp(noise(), 1000.0) + + Here is a low-pass filter sweep from 100Hz to 2000Hz: + + play lp(noise(), pwl(0.0, 100.0, 1.0, 2000.0, 1.0)) + +And a high-pass sweep from 50Hz to 4000Hz: + + play hp(noise(), pwl(0.0, 50.0, 1.0, 4000.0, 1.0)) + + The band-pass filter takes a center frequency and a bandwidth parameter. +This example has a 500Hz center frequency with a 20Hz bandwidth. The scale +factor is necessary because, due to the resonant peak of the filter, the signal +amplitude exceeds 1.0: + + play reson(10.0 * noise(), 500.0, 20.0, 1) + +In the next example, the center frequency is swept from 100 to 1000Hz, using a +constant 20Hz bandwidth: + + play reson(0.04 * noise(), + pwl(0.0, 200.0, 1.0, 1000.0, 1.0), + 20.0) + + For another example with explanations, see demos/wind_tutorial.htm. + +5.7. DSP in Lisp + In almost any signal processing system, the vast majority of computation +takes place in the inner loops of DSP algorithms, and Nyquist is designed so +that these time-consuming inner loops are in highly-optimized machine code +rather than relatively slow interpreted lisp code. As a result, Nyquist +typically spends 95% of its time in these inner loops; the overhead of using a +Lisp interpreter is negligible. + + The drawback is that Nyquist must provide the DSP operations you need, or you +are out of luck. When Nyquist is found lacking, you can either write a new +primitive signal operation, or you can perform DSP in Lisp code. Neither option +is recommended for inexperienced programmers. Instructions for extending +Nyquist are given in Appendix I. This section describes the process of writing +a new signal processing function in Lisp. + + Before implementing a new DSP function, you should decide which approach is +best. First, figure out how much of the new function can be implemented using +existing Nyquist functions. For example, you might think that a tapped-delay +line would require a new function, but in fact, it can be implemented by +composing sound transformations to accomplish delays, scale factors for +attenuation, and additions to combine the intermediate results. This can all +be packaged into a new Lisp function, making it easy to use. If the function +relies on built-in DSP primitives, it will execute very efficiently. + + Assuming that built-in functions cannot be used, try to define a new +operation that will be both simple and general. Usually, it makes sense to +implement only the kernel of what you need, combining it with existing +functions to build a complete instrument or operation. For example, if you +want to implement a physical model that requires a varying breath pressure with +noise and vibrato, plan to use Nyquist functions to add a basic pressure +envelope to noise and vibrato signals to come up with a composite pressure +signal. Pass that signal into the physical model rather than synthesizing the +envelope, noise, and vibrato within the model. This not only simplifies the +model, but gives you the flexibility to use all of Nyquist's operations to +synthesize a suitable breath pressure signal. + + Having designed the new ``kernel'' DSP operation that must be implemented, +decide whether to use C or Lisp. (At present, SAL is not a good option because +it has no support for object-oriented programming.) To use C, you must have a +C compiler, the full source code for Nyquist, and you must learn about +extending Nyquist by reading Appendix I. This is the more complex approach, but +the result will be very efficient. A C implementation will deal properly with +sounds that are not time-aligned or matched in sample rates. To use Lisp, you +must learn something about the XLISP object system, and the result will be +about 50 times slower than C. Also, it is more difficult to deal with time +alignment and differences in sample rates. The remainder of this section gives +an example of a Lisp version of snd-prod to illustrate how to write DSP +functions for Nyquist in Lisp. + + The snd-prod function is the low-level multiply routine. It has two sound +parameters and returns a sound which is the product of the two. To keep things +simple, we will assume that two sounds to be multiplied have a matched sample +rate and matching start times. The DSP algorithm for each output sample is +simply to fetch a sample from each sound, multiply them, and return the +product. + + To implement snd-prod in Lisp, three components are required: + + 1. An object is used to store the two parameter sounds. This object + will be called upon to yield samples of the result sound; + + 2. Within the object, the snd-fetch routine is used to fetch samples + from the two input sounds as needed; + + 3. The result must be of type SOUND, so snd-fromobject is used to + create the result sound. + + The combined solution will work as follows: The result is a value of type +sound that retains a reference to the object. When Nyquist needs samples from +the sound, it invokes the sound's ``fetch'' function, which in turn sends an +XLISP message to the object. The object will use snd-fetch to get a sample from +each stored sound, multiply the samples, and return a result. + + Thus the goal is to design an XLISP object that, in response to a :next +message will return a proper sequence of samples. When the sound reaches the +termination time, simply return NIL. + + The XLISP manual (see Appendix IV describes the object system, but in a very +terse style, so this example will include some explanation of how the object +system is used. First, we need to define a class for the objects that will +compute sound products. Every class is a subclass of class class, and you +create a subclass by sending :new to a class. + + (setf product-class (send class :new '(s1 s2))) + +The parameter '(s1 s2) says that the new class will have two instance +variables, s1 and s2. In other words, every object which is an instance of +class product-class will have its own copy of these two variables. + + Next, we will define the :next method for product-class: + + (send product-class :answer :next '() + '((let ((f1 (snd-fetch s1)) + (f2 (snd-fetch s2))) + (cond ((and f1 f2) + (* f1 f2)) + (t nil))))) + +The :answer message is used to insert a new method into our new product-class. +The method is described in three parts: the name (:next), a parameter list +(empty in this case), and a list of expressions to be evaluated. In this case, +we fetch samples from s1 and s2. If both are numbers, we return their product. +If either is NIL, we terminate the sound by returning nil. + + The :next method assumes that s1 and s2 hold the sounds to be multiplied. +These must be installed when the object is created. Objects are created by +sending :new to a class. A new object is created, and any parameters passed to +:new are then sent in a :isnew message to the new object. Here is the :isnew +definition for product-class: + + (send product-class :answer :isnew '(p1 p2) + '((setf s1 (snd-copy p1)) + (setf s2 (snd-copy p2)))) + +Take careful note of the use of snd-copy in this initialization. The sounds s1 +and s2 are modified when accessed by snd-fetch in the :next method defined +above, but this destroys the illusion that sounds are immutable values. The +solution is to copy the sounds before accessing them; the original sounds are +therefore unchanged. (This copy also takes place implicitly in most Nyquist +sound functions.) + + To make this code safer for general use, we should add checks that s1 and s2 +are sounds with identical starting times and sample rates; otherwise, an +incorrect result might be computed. + + Now we are ready to write snd-product, an approximate replacement for +snd-prod: + + (defun snd-product (s1 s2) + (let (obj) + (setf obj (send product-class :new s1 s2)) + (snd-fromobject (snd-t0 s1) (snd-srate s1) obj))) + +This code first creates obj, an instance of product-class, to hold s1 and s2. +Then, it uses obj to create a sound using snd-fromobject. This sound is +returned from snd-product. Note that in snd-fromobject, you must also specify +the starting time and sample rate as the first two parameters. These are copied +from s1, again assuming that s1 and s2 have matching starting times and sample +rates. + + Note that in more elaborate DSP algorithms we could expect the object to have +a number of instance variables to hold things such as previous samples, +waveform tables, and other parameters. +6. SAL + Nyquist supports two languages: XLISP and SAL. In some sense, XLISP and SAL +are the same language, but with differing syntax. This chapter describes SAL: +how it works, SAL syntax and semantics, and the relationship between SAL and +XLISP, and differences between Nyquist SAL and Common Music SAL. + + Nyquist SAL is based on Rick Taube's SAL language, which is part of Common +Music. SAL offers the power of Lisp but features a simple, Algol-like syntax. +SAL is implemented in Lisp: Lisp code translates SAL into a Lisp program and +uses the underlying Lisp engine to evaluate the program. Aside from the +translation time, which is quite fast, SAL programs execute at about the same +speed as the corresponding Lisp program. (Nyquist SAL programs run just +slightly slower than XLISP because of some runtime debugging support +automatically added to user programs by the SAL compiler.) + + From the user's perspective, these implementation details are hidden. You can +enter SAL mode from XLISP by typing (SAL) to the XLISP prompt. The SAL input +prompt (SAL> ) will be displayed. From that point on, you simply type SAL +commands, and they will be executed. By setting a preference in the NyquistIDE +program, SAL mode will be entered automatically. + + It is possible to encounter errors that will take you from the SAL +interpreter to an XLISP prompt. In general, the way to get back to SAL is by +typing (top) to get back to the top level XLISP interpreter and reset the +Nyquist environment. Then type (sal) to restart the SAL interpreter. + +6.1. SAL Syntax and Semantics + The most unusual feature of SAL syntax is that identifiers are Lisp-like, +including names such as ``play-file'' and even ``*warp*.'' In SAL, most +operators must be separated from identifiers by white space. For example, +play-file is one identifier, but play - file is an expression for ``play minus +file,'' where play and file are two separate identifiers. Fortunately, no +spaces are needed around commas and parentheses. + + In SAL, whitespace (any sequence of space, newline, or tab characters) is +sometimes necessary to separate lexical tokens, but otherwise, spaces and +indentation are ignored. To make SAL readable, it is strongly advised that you +indent SAL programs as in the examples here. The NyquistIDE program is +purposely insistent about SAL indentation, so if you use it to edit SAL +programs, your indentation should be both beautiful and consistent. + + As in Lisp (but very unlike C or Java), comments are indicated by semicolons. +Any text from an unquoted semicolon to the end of the line is ignored. + + ; this is a comment + ; comments are ignored by the compiler + print "Hello World" ; this is a SAL statement + + As in Lisp, identifiers are translated to upper-case, making SAL +case-insensitive. For example, the function name autonorm can be typed in lower +case or as AUTONORM, AutoNorm, or even AuToNoRm. All forms denote the same +function. The recommended approach is to write programs in all lower case. + + SAL is organized around statements, most of which contain expressions. We +will begin with expressions and then look at statements. + + + +6.1.1. Expressions + + +6.1.1.1. Simple Expressions + As in XLISP, simple expressions include: + + - integers (FIXNUM's), such as 1215, + + - floats (FLONUM's) such as 12.15, + + - strings (STRING's) such as "Magna Carta", and + + - symbols (SYMBOL's) such as magna-carta. A symbol with a leading colon + (:) evaluates to itself as in Lisp. Otherwise, a symbol denotes + either a local variable, a formal parameter, or a global variable. As + in Lisp, variables do not have data types or type declarations. The + type of a variable is determined at runtime by its value. + + Additional simple expressions in SAL are: + + - lists such as {c 60 e 64}. Note that there are no commas to separate + list elements, and symbols in lists are not evaluated as variables + but stand for themselves. Lists may contain numbers, booleans, + symbols, strings, and other lists. + + - Booleans: SAL interprets #t as true and #fas false. (As far as the + SAL compiler is concerned, t and nil are just variables. Since these + are the Lisp versions of true and false, they are interchangeable + with #t and #f, respectively.) + +A curious property of Lisp and Sal is that false and the empty list are the +same value. Since SAL is based on Lisp, #f and {} (the empty list) are equal. + + +6.1.1.2. Operators + Expressions can be formed with unary and binary operators using infix +notation. The operators are: + + - + - addition, including sounds + + - - - subtraction, including sounds + + - * - multiplication, including sounds + + - / - division (due to divide-by-zero problems, does not operate on + sounds) + + - % - modulus (remainder after division) + + - ^ - exponentiation + + - = - equal (using Lisp eql) + + - != - not equal + + - > - greater than + + - < - less than + + - >= - greater than or equal + + - <= - less than or equal + + - ~= - general equality (using Lisp equal) + + - & - logical and + + - | - logical or + + - ! - logical not (unary) + + - @ - time shift + + - @@ - time shift to absolute time + + - ~ - time stretch + + - ~~ - time stretch to absolute stretch factor + +Again, remember that operators must be delimited from their operands using +spaces or parentheses. Operator precedence is based on the following levels of +precedence: + + @ @@ ~ ~~ + ^ + / * + % - + + ~= <= >= > ~= = + ! + & + | + + +6.1.1.3. Function Calls + A function call is a function name followed by zero or more comma-delimited +argument expressions enclosed within parentheses: + + list() + piano-note(2.0, c4 + interval, 100) + +Some functions use named parameters, in which case the name of the argument +with a colon precedes the argument expression. + + s-save(my-snd(), ny:all, "tmp.wav", play: #t, bits: 16) + + +6.1.1.4. Array Notation + An array reference is a variable identifier followed by an index expression +in square brackets, e.g.: + + x[23] + y[i] + + +6.1.1.5. Conditional Values + The special operator #? evaluates the first argument expression. If the +result is true, the second expression is evaluated and its value is returned. +If false, the third expression is evaluated and returned (or false is returned +if there is no third expression): + + #?(random(2) = 0, unison, major-third) + #?(pitch >= c4, pitch - c4) ; returns false if pitch < c4 + + + +6.1.2. SAL Statements + SAL compiles and evaluates statements one at a time. You can type statements +at the SAL prompt or load a file containing SAL statements. SAL statements are +described below. The syntax is indicated at the beginning of each statement +type description: this font indicates literal terms such as keywords, the +italic font indicates a place-holder for some other statement or expression. +Bracket [like this] indicate optional (zero or one) syntax elements, while +braces with a plus {like this}+ indicate one or more occurrences of a syntax +element. Braces with a star {like this}* indicate zero or more occurrences of a +syntax element: { non-terminal }* is equivalent to [ {non-terminal}+ ]. + + +6.1.2.1. begin and end + begin [with-stmt] {statement}+ end + + A begin-end statement consists of a sequence of statements surrounded by the +begin and end keywords. This form is often used for function definitions and +after then or else where the syntax demands a single statement but you want to +perform more than one action. Variables may be declared using an optional with +statement immediately after begin. For example: + + begin + with db = 12.0, + linear = db-to-linear(db) + print db, "dB represents a factor of", linear + set scale-factor = linear + end + + +6.1.2.2. chdir + chdir expression + + The chdir statement changes the working directory. This statement is provided +for compatibility with Common Music SAL, but it really should be avoided if you +use NyquistIDE. The expression following the chdir keyword should evaluate to a +string that is a directory path name. Note that literal strings themselves are +valid expressions. + + chdir "/Users/rbd/tmp" + + +6.1.2.3. define variable + [define] variable name [= expression] {, name [= expression]}* + + Global variables can be declared and initialized. A list of variable names, +each with an optional initialization follows the define variable keywords. +(Since variable is a keyword, define is redundant and optional in Nyquist SAL, +but required in Common Music SAL.) If the initialization part is omitted, the +variable is initialized to false. Global variables do not really need to be +declared: just using the name implicitly creates the corresponding variable. +However, it is an error to use a global variable that has not been initialized; +define variable is a good way to introduce a variable (or constant) with an +initial value into your program. + + define variable transposition = 2, + print-debugging-info, ; initially false + output-file-name = "salmon.wav" + + +6.1.2.4. define function + [define] function name ( [parameter], {, parameter}* ) statement + + Before a function be called from an expression (as described above), it must +be defined. A function definition gives the function name, a list of +parameters, and a statement. When a function is called, the actual parameter +expressions are evaluated from left to right and the formal parameters of the +function definition are set to these values. Then, statement is evaluated. + + The formal parameters may be positional parameters that are matched with +actual parameters by position from left to right. Syntactically, these are +symbols and these symbols are essentially local variables that exist only until +statement completes or a return statement causes the function evaluation to +end. As in Lisp, parameters are passed by value, so assigning a new value to a +formal parameter has no effect on the actual value. However, lists and arrays +are not copied, so internal changes to a list or array produce observable side +effects. + + Alternatively, formal parameters may be keyword parameters. Here the +parameter is actually a pair: a keyword parameter, which is a symbol followed +by a colon, and a default value, given by any expression. Within the body of +the function, the keyword parameter is named by a symbol whose name matches the +keyword parameter except there is no final colon. + + define function foo(x: 1, y: bar(2, 3)) + display "foo", x, y + + exec foo(x: 6, y: 7) + +In this example, x is bound to the value 6 and y is bound to the value 7, so +the example prints ``foo : X = 6, Y = 7''. Note that while the keyword +parameters are x: and y:, the corresponding variable names in the function body +are x and y, respectively. + + The parameters are meaningful only within the lexical (static) scope of +statement. They are not accessible from within other functions even if they are +called by this function. + + Use a begin-end statement if the body of the function should contain more +than one statement or you need to define local variables. Use a return +statement to return a value from the function. If statement completes without a +return, the value false is returned. + + +6.1.2.5. display + display string {, expression}* + + The display statement is handy for debugging. At present, it is only +implemented in Nyquist SAL. When executed, display prints the string followed +by a colon and then, for each expression, the expression and its value are +printed, after the last expression, a newline is printed. For example, + + display "In function foo", bar, baz + +prints + + In function foo : bar = 23, baz = 5.3 + +SAL may print the expressions using Lisp syntax, e.g. if the expression is +``bar + baz,'' do not be surprised if the output is ``(sum bar baz) = 28.3.'' + + +6.1.2.6. exec + exec expression + + Unlike most other programming languages, you cannot simply type an expression +as a statement. If you want to evaluate an expression, e.g. call a function, +you must use an exec statement. The statement simply evaluates the expression. +For example, + + exec set-sound-srate(22050.0) ; change default sample rate + + +6.1.2.7. if + if test-expr then true-stmt [else false-stmt] + + An if statement evaluates the expression test-expr. If it is true, it +evaluates the statement true-stmt. If false, the statement false-stmt is +evaluated. Use a begin-end statement to evaluate more than one statement in +then then or else parts. + + if x < 0 then x = -x ; x gets its absoute value + + if x > upper-bound then + begin + print "x too big, setting to", upper-bound + x = upper-bound + end + else + if x < lower-bound then + begin + print "x too small, setting to", lower-bound + x = lower-bound + end + +Notice in this example that the else part is another if statement. An if may +also be the then part of another if, so there could be two possible if's with +which to associate an else. An else clause always associates with the closest +previous if that does not already have an else clause. + + +6.1.2.8. when + when test statement + + The when statement is similar to if, but there is no else clause. + + when *debug-flag* print "you are here" + + +6.1.2.9. unless + unless test statement + + The unless statement is similar to when (and if) but the statement is +executed when the test expression is false. + + unless count = 0 set average = sum / count + + +6.1.2.10. load + load expression + + The load command loads a file named by expression, which must evauate to a +string path name for the file. To load a file, SAL interprets each statement in +the file, stopping when the end of the file or an error is encountered. If the +file ends in .lsp, the file is assumed to contain Lisp expressions, which are +evaluated by the XLISP interpreter. In general, SAL files should end with the +extension .sal. + + +6.1.2.11. loop + loop [with-stmt] {stepping}* {stopping* action+ [finally] end + + The loop statement is by far the most complex statement in SAL, but it offers +great flexibility for just about any kind of iteration. The basic function of a +loop is to repeatedly evaluate a sequence of action's which are statements. +Before the loop begins, local variables may be declared in with-stmt, a with +statement. + + The stepping clauses do several things. They introduce and initialize +additional local variables similar to the with-stmt. However, these local +variables are updated to new values after the action's. In addition, some +stepping clauses have associated stopping conditions, which are tested on each +iteration before evaluating the action's. + + There are also stopping clauses that provide additional tests to stop the +iteration. These are also evaluated and tested on each iteration before +evaluating the action's. + + When some stepping or stopping condition causes the iteration to stop, the +finally clause is evaluated (if present). Local variables and their values can +still be accessed in the finally clause. After the finally clause, the loop +statement completes. + + The stepping clauses are the following: + +repeat expression + Sets the number of iterations to the value of expression, which + should be an integer (FIXNUM). + +for var = expression [ then expr2 ] + Introduces a new local variable named var and initializes it to + expression. Before each subsequent iteration, var is set to the + value of expr2. If the then part is omitted, expression is + re-evaluated and assigned to var on each subsequent iteration. + Note that this differs from a with-stmt where expressions are + evaluated and variables are only assigned their values once. + +for var in expression + Evaluates expression to obtain a list and creates a new local + variable initialized to the first element of the list. After + each iteration, var is assigned the next element of the list. + Iteration stops when var has assumed all values from the list. + If the list is initially empty, the loop action's are not + evaluated (there are zero iterations). + +for var [from from-expr] [[to | below | downto | above] to-expr] [by step-expr] + Introduces a new local variable named var and intialized to the + value of the expression from-expr (with a default value of 0). + After each iteration of the loop, var is incremented by the + value of step-expr (with a default value of 1). The iteration + ends when var is greater than the value of to-expr if there is + a to clause, greater than or equal to the value of to-expr if + there is a below clause, less than the value of to-expr if + there is a downto clause, or less than or equal to the value of + to-expr if there is a above clause. (In the cases of downto and + above, the default increment value is -1. If there is no to, + below, downto, above, or below clause, no interation stop test + is created for this stepping clause. + + The stopping clauses are the following: + +while expression + The iterations are stopped when expression evaluates to false. + Anything not false is considered to mean true. + +until expression + The iterations are stopped when expression evaluates to true. + + The finally clause is defined as follows: + +finally statement + The statement is evaluated when one of the stepping or stopping + clauses ends the loop. As always, statement may be a begin-end + statement. If an action evaluates a return statement, the + finally statement is not executed. + + Loops often fall into common patterns, such as iteratiing a fixed number of +times, performing an operation on some range of integers, collecting results in +a list, and linearly searching for a solution. These forms are illustrated in +the examples below. + + ; iterate 10 times + loop + repeat 10 + print random(100) + end + + ; print even numbers from 10 to 20 + ; note that 20 is printed. On the next iteration, + ; i = 22, so i >= 22, so the loop exits. + loop + for i from 10 to 22 by 2 + print i + end + + ; collect even numbers in a list + loop + with lis + for i = 0 to 10 by 2 + set lis @= i ; push integers on front of list, + ; which is much faster than append, + ; but list is built in reverse + finally result = reverse(lis) + end + ; now, the variable result has a list of evens + + ; find the first even number in a list + result = #f ; #f means "false" + loop + for elem in lis + until evenp(elem) + finally result = elem + end + ; result has first even value in lis (or it is #f) + + +6.1.2.12. print + print expr {, expr}* + + The print statement prints the values separated by spaces and followed by a +newline. [Note that in the original SAL, the newline is printed before the +values, not after.] + + print "The value of x is", x + + +6.1.2.13. return + return expression + + The return statement can only be used inside a function. It evaluates +expression and then the function returns the value of the expression to its +caller. + + +6.1.2.14. set + set var op expression {, var op expression}* + + The set statement changes the value of a variable var according to the +operator op and the value of the expression. The operators are: + += The value of expression is assigned to var. + ++= The value of expression is added to var. + +*= The value of var is multiplied by the value of the expression. + +&= The value of expression is inserted as the last element of the + list referenced by var. If var is the empty list (denoted by + #f), then var is assigned a newly constructed list of one + element, the value of expression. + +^= The value of expression, a list, is appended to the list + referenced by var. If var is the empty list (denoted by #f), + then var is assigned the (list) value of expression. + +@= Pushes the value of expression onto the front of the list + referenced by var. If var is empty (denoted by #f), then var is + assigned a newly constructed list of one element, the value of + expression. + +<= Sets the new value of var to the minimum of the old value of + var and the value of expression. + +>= Sets the new value of var to the maximum of the old value of + var and the value of expression. + + ; example from Rick Taube's SAL description + loop + with a, b = 0, c = 1, d = {}, e = {}, f = -1, g = 0 + for i below 5 + set a = i, b += 1, c *= 2, d &= i, e @= i, f <= i, g >= i + finally display "results", a, b, c, d, e, f, g + end + + +6.1.2.15. with + with var [= expression] {, var [= expression]}* + + The with statement declares and initializes local variables. It can appear +only after begin or loop. If the expression is omitted, the initial value is +false. The variables are visible only inside the begin-end or loop statement +where the with statement appears. Even in loop's the variables are intialized +only when the loop is entered, not on each iteration. + + +6.1.2.16. exit + exit [nyquist] + + The exit statement is unique to Nyquist SAL. It returns from SAL mode to the +XLISP interpreter. (Return to SAL mode by typing ``(sal)''). If nyquist is +included in the statement, then the entire Nyquist process will exit. + +6.2. Interoperability of SAL and XLISP + When SAL evaluatas command or loads files, it translates SAL into XLISP. You +can think of SAL as a program that translates everything you write into XLISP +and entering it for you. Thus, when you define a SAL function, the function +actually exists as an XLISP function (created using Lisp's defun special form). +When you set or evaluate global variables in SAL, these are exactly the same +Lisp global variables. Thus, XLISP functions can call SAL functions and +vice-versa. At run time, everything is Lisp. + + + +6.2.1. Function Calls + In general, there is a very simple translation from SAL to Lisp syntax and +back. A function call is SAL, for example, + + osc(g4, 2.0) + +is translated to Lisp by moving the open parenthesis in front of the function +name and removing the commas: + + (osc g4 2.0) + +Similarly, if you want to translate a Lisp function call to SAL, just reverse +the translation. + + + +6.2.2. Symbols and Functions + SAL translates keywords with trailing colons (such as foo:) into Lisp +keywords with leading colons (such as :foo), but SAL keywords are not treated +as expressions as they are in Lisp. You cannot write open("myfile.txt", +direction: output:) because SAL expects an expression after direction. A +special form keyword is defined to generate a Lisp keyword as an expression. +The argument is the keyword without a colon, e.g. open("myfile.txt", +direction: keyword(output)). Alternatively, you can write the Lisp-style +keyword with the leading colon, e.g. open("myfile.txt", direction: :output). + + In Nyquist SAL, the hash character (#), can be used as a prefix to a Lisp +function name. For example, the following command is not legal because print is +a SAL command name, not a legal function name: set v = append(print(a), +print(b)). (Here the intent is to print arguments to append). However, you can +use the hash character to access the Lisp print function: set v = +append(#print(a), #print(b)). + + + +6.2.3. Playing Tricks On the SAL Compiler + In many cases, the close coupling between SAL and XLISP gives SAL unexpected +expressive power. A good example is seqrep. This is a special looping construct +in Nyquist, implemented as a macro in XLISP. In Lisp, you would write something +like: + + (seqrep (i 10) (pluck c4)) + +One might expect SAL would have to define a special seqrep statement to express +this, but since statements do not return values, this approach would be +problematic. The solution (which is already fully implemented in Nyquist) is to +define a new macro sal-seqrep that is equivalent to seqrep except that it is +called as follows: + + (sal-seqrep i 10 (pluck c4)) + +The SAL compiler automatically translates the identifier seqrep to sal-seqrep. +Now, in SAL, you can just write + + seqrep(i, 10, pluck(c4)) + +which is translated in a pretty much semantics-unaware fashion to + + (sal-seqrep i 10 (pluck c4)) + +and viola!, we have Nyquist control constructs in SAL even though SAL is +completely unaware that seqrep is actually a special form. +7. Nyquist Functions + This chapter provides a language reference for Nyquist. Operations are +categorized by functionality and abstraction level. Nyquist is implemented in +two important levels: the ``high level'' supports behavioral abstraction, which +means that operations like stretch and at can be applied. These functions are +the ones that typical users are expected to use, and most of these functions +are written in XLISP. + + The ``low-level'' primitives directly operate on sounds, but know nothing of +environmental variables (such as *warp*, etc.). The names of most of these +low-level functions start with ``snd-''. In general, programmers should avoid +any function with the ``snd-'' prefix. Instead, use the ``high-level'' +functions, which know about the environment and react appropriately. The names +of high-level functions do not have prefixes like the low-level functions. + + There are certain low-level operations that apply directly to sounds (as +opposed to behaviors) and are relatively ``safe'' for ordinary use. These are +marked as such. + + Nyquist uses both linear frequency and equal-temperament pitch numbers to +specify repetition rates. Frequency is always specified in either cycles per +second (hz), or pitch numbers, also referred to as ``steps,'' as in steps of +the chromatic scale. Steps are floating point numbers such that 60 = Middle C, +61 = C#, 61.23 is C# plus 23 cents, etc. The mapping from pitch number to +frequency is the standard exponential conversion, and fractional pitch numbers + (pitch-69)/12 +are allowed: frequency=440*2 . There are many predefined pitch +names. By default these are tuned in equal temperament, with A4 = 440Hz, but +these may be changed. (See Section 1.7). + +7.1. Sounds + A sound is a primitive data type in Nyquist. Sounds can be created, passed +as parameters, garbage collected, printed, and set to variables just like +strings, atoms, numbers, and other data types. + + + +7.1.1. What is a Sound? + Sounds have 5 components: + + - srate M the sample rate of the sound. + + - samples M the samples. + + - signal-start M the time of the first sample. + + - signal-stop M the time of one past the last sample. + + - logical-stop M the time at which the sound logically ends, e.g. a + sound may end at the beginning of a decay. This value defaults to + signal-stop, but may be set to any value. + +It may seem that there should be logical-start to indicate the logical or +perceptual beginning of a sound as well as a logical-stop to indicate the +logical ending of a sound. In practice, only logical-stop is needed; this +attribute tells when the next sound should begin to form a sequence of sounds. +In this respect, Nyquist sounds are asymmetric: it is possible to compute +sequences forward in time by aligning the logical start of each sound with the +logical-stop of the previous one, but one cannot compute ``backwards'', +aligning the logical end of each sound with the logical start of its successor. +The root of this asymmetry is the fact that when we invoke a behavior, we say +when to start, and the result of the behavior tells us its logical duration. +There is no way to invoke a behavior with a direct specification of when to +stop[Most behaviors will stop at time 1, warped according to *warp* to some +real time, but this is by convention and is not a direct specification.]. + + Note: there is no way to enforce the intended ``perceptual'' interpretation +of logical-stop. As far as Nyquist is concerned, these are just numbers to +guide the alignment of sounds within various control constructs. + + + +7.1.2. Multichannel Sounds + Multichannel sounds are represented by Lisp arrays of sounds. To create an +array of sounds the XLISP vector function is useful. Most low-level Nyquist +functions (the ones starting with snd-) do not operate on multichannel sounds. +Most high-level functions do operate on multichannel sounds. + + + +7.1.3. Accessing and Creating Sound + Several functions display information concerning a sound and can be used to +query the components of a sound. There are functions that access samples in a +sound and functions that construct sounds from samples. + +sref(sound, time) [SAL] +(sref sound time) [LISP] + Accesses sound at the point time, which is a local time. If time does not + correspond to a sample time, then the nearest samples are linearly + interpolated to form the result. To access a particular sample, either + convert the sound to an array (see snd-samples below), or use snd-srate + and snd-t0 (see below) to find the sample rate and starting time, and + compute a time (t) from the sample number (n):t=(n/srate)+t0 Thus, the + th + lisp code to access the n sample of a sound would look like: (sref + sound (global-to-local (+ (/ n (snd-srate sound)) (snd-t0 sound)))) Here + is why sref interprets its time argument as a local time: + + > (sref (ramp 1) 0.5) ; evaluate a ramp at time 0.5 + 0.5 + > (at 2.0 (sref (ramp 1) 0.5)) ; ramp is shifted to start at 2.0 + ; the time, 0.5, is shifted to 2.5 + 0.5 + + If you were to use snd-sref, which treats time as global, instead of sref, + which treats time as local, then the first example above would return the + same answer (0.5), but the second example would return 0. Why? Because + the (ramp 1) behavior would be shifted to start at time 2.0, but the + resulting sound would be evaluated at global time 0.5. By definition, + sounds have a value of zero before their start time. + +sref-inverse(sound, value) [SAL] +(sref-inverse sound value) [LISP] + Search sound for the first point at which it achieves value and return the + corresponding (linearly interpolated) time. If no inverse exists, an + error is raised. This function is used by Nyquist in the implementation + of time warping. + +snd-from-array(t0, sr, array) [SAL] +(snd-from-array t0 sr array) [LISP] + Converts a lisp array of FLONUMs into a sound with starting time t0 and + sample rate sr. Safe for ordinary use. Be aware that arrays of + floating-point samples use 14 bytes per sample, and an additional 4 bytes + per sample are allocated by this function to create a sound type. + +snd-fromarraystream(t0, sr, object) [SAL] +(snd-fromarraystream t0 sr object) [LISP] + Creates a sound for which samples come from object. The starting time is + t0 (a FLONUM), and the sample rate is sr. The object is an XLISP object + (see Section IV.11 for information on objects.) A sound is returned. When + the sound needs samples, they are generated by sending the message :next + to object. If object returns NIL, the sound terminates. Otherwise, object + must return an array of FLONUMs. The values in these arrays are + concatenated to form the samples of the resulting sound. There is no + provision for object to specify the logical stop time of the sound, so the + logical stop time is the termination time. + +snd-fromobject(t0, sr, object) [SAL] +(snd-fromobject t0 sr object) [LISP] + Creates a sound for which samples come from object. The starting time is + t0 (a FLONUM), and the sample rate is sr. The object is an XLISP object + (see Section IV.11 for information on objects. A sound is returned. When + the sound needs samples, they are generated by sending the message :next + to object. If object returns NIL, the sound terminates. Otherwise, object + must return a FLONUM. There is no provision for object to specify the + logical stop time of the sound, so the logical stop time is the + termination time. + +snd-extent(sound, maxsamples) [SAL] +(snd-extent sound maxsamples) [LISP] + Returns a list of two numbers: the starting time of sound and the + terminate time of sound. Finding the terminate time requires that samples + be computed. Like most Nyquist functions, this is non-destructive, so + memory will be allocated to preserve the sound samples. If the sound is + very long or infinite, this may exhaust all memory, so the maxsamples + parameter specifies a limit on how many samples to compute. If this limit + is reached, the terminate time will be (incorrectly) based on the sound + having maxsamples samples. This function is safe for ordinary use. + +snd-fetch(sound) [SAL] +(snd-fetch sound) [LISP] + Reads samples sequentially from sound. This returns a FLONUM after each + call, or NIL when sound terminates. Note: snd-fetch modifies sound; it is + strongly recommended to copy sound using snd-copy and access only the copy + with snd-fetch. + +snd-fetch-array(sound, len, step) [SAL] +(snd-fetch-array sound len step) [LISP] + Reads sequential arrays of samples from sound, returning either an array + of FLONUMs or NIL when the sound terminates. The len parameter, a FIXNUM, + indicates how many samples should be returned in the result array. After + the array is returned, sound is modified by skipping over step (a FIXNUM) + samples. If step equals len, then every sample is returned once. If step + is less than len, each returned array will overlap the previous one, so + some samples will be returned more than once. If step is greater than len, + then some samples will be skipped and not returned in any array. The step + and len may change at each call, but in the current implementation, an + internal buffer is allocated for sound on the first call, so subsequent + calls may not specify a greater len than the first. When an array is + returned, it will have len samples. If necessary, snd-fetch-array will + read zeros beyond the end of the sound to fill the array. When this + happens, *rslt* is set to a FIXNUM number of samples in the array that + were read from the sound before the physical stop time of the sound. If + all samples in the array are ``valid'' samples from the sound (coming from + the sound before the sound terminates), *rslt* is set to NIL. The *rslt* + variable is global and used to return extra results from other functions, + so programs should not assume *rslt* is valid after subsequent function + calls. Note: snd-fetch-array modifies sound; it is strongly recommended to + copy sound using snd-copy and access only the copy with snd-fetch-array. + +snd-flatten(sound, maxlen) [SAL] +(snd-flatten sound maxlen) [LISP] + This function is identical to snd-length. You would use this function to + force samples to be computed in memory. Normally, this is not a good thing + to do, but here is one appropriate use: In the case of sounds intended for + wavetables, the unevaluated sound may be larger than the evaluated (and + typically short) one. Calling snd-flatten will compute the samples and + allow the unit generators to be freed in the next garbage collection. + Note: If a sound is computed from many instances of table-lookup + oscillators, calling snd-flatten will free the oscillators and their + tables. Calling (stats) will print how many total bytes have been + allocated to tables. + +snd-length(sound, maxlen) [SAL] +(snd-length sound maxlen) [LISP] + Counts the number of samples in sound up to the physical stop time. If + the sound has more than maxlen samples, maxlen is returned. Calling this + function will cause all samples of the sound to be computed and saved in + memory (about 4 bytes per sample). Otherwise, this function is safe for + ordinary use. + +snd-maxsamp(sound) [SAL] +(snd-maxsamp sound) [LISP] + Computes the maximum of the absolute value of the samples in sound. + Calling this function will cause samples to be computed and saved in + memory. (This function should have a maxlen parameter to allow + self-defense against sounds that would exhaust available memory.) + Otherwise, this function is safe for ordinary use. This function will + probably be removed in a future version. See peak, a replacement ( page + 30). + +snd-play(expression) [SAL] +(snd-play expression) [LISP] + Evaluates expression to obtain a sound or array of sounds, computes all of + the samples (without retaining them in memory), and returns. Originally, + this was a placeholder for a facility to play samples directly to an audio + output device, but playback is now accomplished by s-save. Meanwhile, + since this function does not save samples in memory or write them to a + disk, it is useful in determining how much time is spent calculating + samples. See s-save (Section 7.5) for saving samples to a file, and play + (Section 7.5) to play a sound. This function is safe for ordinary use. + +snd-print-tree(sound) [SAL] +(snd-print-tree sound) [LISP] + Prints an ascii representation of the internal data structures + representing a sound. This is useful for debugging Nyquist. This + function is safe for ordinary use. + +snd-samples(sound, limit) [SAL] +(snd-samples sound limit) [LISP] + Converts the samples into a lisp array. The data is taken directly from + the samples, ignoring shifts. For example, if the sound starts at 3.0 + seconds, the first sample will refer to time 3.0, not time 0.0. A maximum + of limit samples is returned. This function is safe for ordinary use, but + like snd-from-array, it requires a total of slightly over 18 bytes per + sample. + +snd-srate(sound) [SAL] +(snd-srate sound) [LISP] + Returns the sample rate of the sound. Safe for ordinary use. + +snd-time(sound) [SAL] +(snd-time sound) [LISP] + Returns the start time of the sound. This will probably go away in a + future version, so use snd-t0 instead. + +snd-t0(sound) [SAL] +(snd-t0 sound) [LISP] + Returns the time of the first sample of the sound. Note that Nyquist + operators such as add always copy the sound and are allowed to shift the + copy up to one half sample period in either direction to align the samples + of two operands. Safe for ordinary use. + +snd-print(expression, maxlen) [SAL] +(snd-print expression maxlen) [LISP] + Evaluates expression to yield a sound or an array of sounds, then prints + up to maxlen samples to the screen (stdout). This is similar to snd-save, + but samples appear in text on the screen instead of in binary in a file. + This function is intended for debugging. Safe for ordinary use. + +snd-set-logical-stop(sound, time) [SAL] +(snd-set-logical-stop sound time) [LISP] + Returns a sound which is sound, except that the logical stop of the sound + occurs at time. Note: do not call this function. When defining a + behavior, use set-logical-stop or set-logical-stop-abs instead. + +snd-sref(sound, time) [SAL] +(snd-sref sound time) [LISP] + Evaluates sound at the global time given by time. Safe for ordinary use, + but normally, you should call sref instead. + +snd-stop-time(sound) [SAL] +(snd-stop-time sound) [LISP] + Returns the stop time of sound. Sounds can be ``clipped'' or truncated at + a particular time. This function returns that time or MAX-STOP-TIME if he + programmer has not specified a stop time for the sound. Safe for ordinary + use. + +soundp(sound) [SAL] +(soundp sound) [LISP] + Returns true iff sound is a SOUND. Safe for ordinary use. + +stats() [SAL] +(stats) [LISP] + Prints the memory usage status. See also the XLISP mem function. Safe + for ordinary use. This is the only way to find out how much memory is + being used by table-lookup oscillator instances. + + + +7.1.4. Miscellaneous Functions + These are all safe and recommended for ordinary use. + +db-to-linear(x) [SAL] +(db-to-linear x) [LISP] + Returns the conversion of x from decibels to linear. 0dB is converted to + 1. 20dB represents a linear factor of 10. If x is a sound, each sample is + converted and a sound is returned. If x is a multichannel sound, each + channel is converted and a multichannel sound (array) is returned. Note: + With sounds, conversion is only performed on actual samples, not on the + implicit zeros before the beginning and after the termination of the + sound. Sample rates, start times, etc. are taken from x. + +follow(sound, floor, risetime, falltime, lookahead) [SAL] +(follow sound floor risetime falltime lookahead) [LISP] + An envelope follower intended as a commponent for compressor and limiter + functions. The basic goal of this function is to generate a smooth signal + that rides on the peaks of the input signal. The usual objective is to + produce an amplitude envelope given a low-sample rate (control rate) + signal representing local RMS measurements. The first argument is the + input signal. The floor is the minimum output value. The risetime is the + time (in seconds) it takes for the output to rise (exponentially) from + floor to unity (1.0) and the falltime is the time it takes for the output + to fall (exponentially) from unity to floor. The algorithm looks ahead for + peaks and will begin to increase the output signal according to risetime + in anticipation of a peak. The amount of anticipation (in seconds) is + given by lookahead. The algorithm is as follows: the output value is + allowed to increase according to risetime or decrease according to + falltime. If the next input sample is in this range, that sample is simply + output as the next output sample. If the next input sample is too large, + the algorithm goes back in time as far as necessary to compute an envelope + that rises according to risetime to meet the new value. The algorithm will + only work backward as far as lookahead. If that is not far enough, then + there is a final forward pass computing a rising signal from the earliest + output sample. In this case, the output signal will be at least + momentarily less than the input signal and will continue to rise + exponentially until it intersects the input signal. If the input signal + falls faster than indicated by falltime, the output fall rate will be + limited by falltime, and the fall in output will stop when the output + reaches floor. This algorithm can make two passes througth the buffer on + sharply rising inputs, so it is not particularly fast. With short buffers + and low sample rates this should not matter. See snd-avg for a function + that can help to generate a low-sample-rate input for follow. See + snd-chase in Section 7.6.3 for a related filter. + +gate(sound, lookahead, risetime, falltime, floor, threshold) [SAL] +(gate sound lookahead risetime falltime floor threshold) [LISP] + Generate an exponential rise and decay intended for noise gate + implementation. The decay starts when the signal drops below threshold and + stays there for longer than lookahead (a FLONUM in seconds). (The signal + begins to drop when the signal crosses threshold, not after lookahead.) + Decay continues until the value reaches floor (a FLONUM), at which point + the decay stops and the output value is held constant. Either during the + decay or after the floor is reached, if the signal goes above threshold, + then the ouptut value will rise to unity (1.0) at the point the signal + crosses the threshold. Because of internal lookahead, the signal actually + begins to rise before the signal crosses threshold. The rise is a + constant-rate exponential and set so that a rise from floor to unity + occurs in risetime. Similary, the fall is a constant-rate exponential such + that a fall from unity to floor takes falltime. + +hz-to-step(freq) [SAL] +(hz-to-step freq) [LISP] + Returns a step number for freq (in hz), which can be either a number of a + SOUND. The result has the same type as the argument. See also step-to-hz + (below). + +linear-to-db(x) [SAL] +(linear-to-db x) [LISP] + Returns the conversion of x from linear to decibels. 1 is converted to 0. + 0 is converted to -INF (a special IEEE floating point value.) A factor of + 10 represents a 20dB change. If x is a sound, each sample is converted + and a sound is returned. If x is a multichannel sound, each channel is + converted and a multichannel sound (array) is returned. Note: With + sounds, conversion is only performed on actual samples, not on the + implicit zeros before the beginning and after the termination of the + sound. Start times, sample rates, etc. are taken from x. + +log(x) [SAL] +(log x) [LISP] + Calculates the natural log of x (a FLONUM). (See s-log for a version that + operates on signals.) + +set-control-srate(rate) [SAL] +(set-control-srate rate) [LISP] + Sets the default sampling rate for control signals to rate by setting + *default-control-srate* and reinitializing the environment. Do not call + this within any synthesis function (see the control-srate-abs + transformation, Section 7.3). + +set-sound-srate(rate) [SAL] +(set-sound-srate rate) [LISP] + Sets the default sampling rate for audio signals to rate by setting + *default-sound-srate* and reinitializing the environment. Do not call + this within any synthesis function (see the sound-srate-abs + transformation, Section 7.3). + +set-pitch-names() [SAL] +(set-pitch-names) [LIS] + Initializes pitch variables (c0, cs0, df0, d0, ... b0, c1, ... b7). A440 + (the default tuning) is represented by the step 69.0, so the variable a4 + (fourth octave A) is set to 69.0. You can change the tuning by setting + *A4-Hertz* to a value (in Hertz) and calling set-pitch-names to + reinitialize the pitch variables. Note that this will result in + non-integer step values. It does not alter the mapping from step values + to frequency. There is no built-in provision for stretched scales or + non-equal temperament, although users can write or compute any desired + fractional step values. + +step-to-hz(pitch) [SAL] +(step-to-hz pitch) [LISP] + Returns a frequency in hz for pitch, a step number or a SOUND type + representing a time-varying step number. The result is a FLONUM if pitch + is a number, and a SOUND if pitch is a SOUND. See also hz-to-step (above). + +get-duration(dur) [SAL] +(get-duration dur) [LISP] + Gets the actual duration of of something starting at a local time of 0 and + ending at a local time of dur times the current sustain. For convenience, + *rslt* is set to the global time corresponding to local time zero. + +get-loud() [SAL] +(get-loud) [LISP] + Gets the current value of the *loud* environment variable. If *loud* is a + signal, it is evaluated at local time 0 and a number (FLONUM) is returned. + +get-sustain() [SAL] +(get-sustain) [LISP] + Gets the current value of the *sustain* environment variable. If + *sustain* is a signal, it is evaluated at local time 0 and a number + (FLONUM) is returned. + +get-transpose() [SAL] +(get-transpose) [LISP] + Gets the current value of the *transpose* environment variable. If + *transpose* is a signal, it is evaluated at local time 0 and a number + (FLONUM) is returned. + +get-warp() [SAL] +(get-warp) [LISP] + Gets a function corresponding to the current value of the *warp* + environment variable. For efficiency, *warp* is stored in three parts + representing a shift, a scale factor, and a continuous warp function. + Get-warp is used to retrieve a signal that maps logical time to real time. + This signal combines the information of all three components of *warp* + into a single signal. If the continuous warp function component is not + present (indicating that the time warp is a simple combination of at and + stretch transformations), an error is raised. This function is mainly for + internal system use. In the future, get-warp will probably be + reimplemented to always return a signal and never raise an error. + +LOCAL-to-global(local-time) [SAL] +(local-to-global local-time) [LISP] + Converts a score (local) time to a real (global) time according to the + current environment. + +osc-enable(flag) [SAL] +(osc-enable flag) [LISP] + Enable or disable Open Sound Control. (See Appendix II.) Enabling + creates a socket and a service that listens for UDP packets on port 7770. + Currently, only two messages are accepted by Nyquist. The first is of the + form /slider with an integer index and a floating point value. These set + internal slider values accessed by the snd-slider function. The second is + of the form /wii/orientation with two floating point values. This message + is a special case to support the DarwiinRemoteOsc program which can relay + data from a Nintendo WiiMote device to Nyquist via OSC. The two + orientation values control sliders 0 and 1. Disabling terminates the + service (polling for messages) and closes the socket. The previous state + of enablement is returned, e.g. if OSC is enabled and flag is nil, OSC is + disabled and T (true) is returned because OSC was enabled at the time of + the call. This function only exists if Nyquist is compiled with the + compiler flag OSC. Otherwise, the function exists but always returns the + symbol DISABLED. Consider lowering the audio latency using snd-set- + latency. Warning: there is the potential for network-based attacks using + OSC. It is tempting to add the ability to evaluate XLISP expressions sent + via OSC, but this would create unlimited and unprotected access to OSC + clients. For now, it is unlikely that an attacker could do more than + manipulate slider values. + +snd-set-latency(latency) [SAL] +(snd-set-latency latency) [LISP] + Set the latency requested when Nyquist plays sound to latency, a FLONUM. + The previous value is returned. The default is 0.3 seconds. To avoid + glitches, the latency should be greater than the time required for garbage + collection and message printing and any other system activity external to + Nyquist. + +7.2. Behaviors + + + +7.2.1. Using Previously Created Sounds + These behaviors take a sound and transform that sound according to the +environment. These are useful when writing code to make a high-level function +from a low-level function, or when cuing sounds which were previously created: + +cue(sound) [SAL] +(cue sound) [LISP] + Applies *loud*, the starting time from *warp*, *start*, and *stop* to + sound. + +cue-file(filename) [SAL] +(cue-file filename) [LISP] + Same as cue, except the sound comes from the named file, samples from + which are coerced to the current default *sound-srate* sample rate. + +sound(sound) [SAL] +(sound sound) [LISP] + Applies *loud*, *warp*, *start*, and *stop* to sound. + +control(sound) [SAL] +(control sound) [LISP] + This function is identical to sound, but by convention is used when sound + is a control signal rather than an audio signal. + + + +7.2.2. Sound Synthesis + These functions provide musically interesting creation behaviors that react +to their environment; these are the ``unit generators'' of Nyquist: + +const(value [, duration]) [SAL] +(const value [duration]) [LISP] + Creates a constant function at the *control-srate*. Every sample has the + given value, and the default duration is 1.0. See also s-rest, which is + equivalent to calling const with zero, and note that you can pass scalar + constants (numbers) to sim, sum, and mult where they are handled more + efficiently than constant functions. + +env(t , t , t , l , l , l , [dur]) [SAL] + 1 2 4 1 2 3 +(env t t t l l l dur) [LISP] + 1 2 4 1 2 3 + Creates a 4-phase envelope. t is the duration of phase i, and l is the + i i + final level of phase i. t is implied by the duration dur, and l is 0.0. + 3 4 + If dur is not supplied, then 1.0 is assumed. The envelope duration is the + product of dur, *stretch*, and *sustain*. If t + t + 2ms + t is + 1 2 4 + greater than the envelope duration, then a two-phase envelope is + substituted that has an attack/release time ratio of t /t . The sample + 1 4 + rate of the returned sound is *control-srate*. (See pwl for a more + general piece-wise linear function generator.) The effect of time warping + is to warp the starting time and ending time. The intermediate + breakpoints are then computed as described above. + +exp-dec(hold, halfdec, length) [SAL] +(exp-dec hold halfdec length) [LISP] + This convenient envelope shape is a special case of pwev (see Section + 7.2.2.2). The envelope starts at 1 and is constant for hold seconds. It + then decays with a half life of halfdec seconds until length. (The total + duration is length.) In other words, the amplitude falls by half each + halfdec seconds. When stretched, this envelope scales linearly, which + means the hold time increases and the half decay time increases. + +force-srate(srate, sound) [SAL] +(force-srate srate sound) [LISP] + Returns a sound which is up- or down-sampled to srate. Interpolation is + linear, and no prefiltering is applied in the down-sample case, so + aliasing may occur. See also resample. + +lfo(freq [, duration, table, phase]) [SAL] +(lfo freq duration table phase) [LISP] + Just like osc (below) except this computes at the *control-srate* and + frequency is specified in Hz. Phase is specified in degrees. The + *transpose* and *sustain* is not applied. The effect of time warping is + to warp the starting and ending times. The signal itself will have a + constant unwarped frequency. + +fmlfo(freq [, table, phase]) [SAL] +(fmlfo freq [table phase]) [LISP] + A low-frequency oscillator that computes at the *control-srate* using a + sound to specify a time-varying frequency in Hz. Phase is a FLONUM in + degrees. The duration of the result is determined by freq. + +maketable(sound) [SAL] +(maketable sound) [LISP] + Assumes that the samples in sound constitute one period of a wavetable, + and returns a wavetable suitable for use as the table argument to the osc + function (see below). Currently, tables are limited to 1,000,000 samples. + This limit is the compile-time constant max_table_len set in sound.h. + +build-harmonic(n, table-size) [SAL] +(build-harmonic n table-size) [LISP] + Intended for constructing wavetables, this function returns a sound of + length table-size samples containing n periods of a sinusoid. These can + be scaled and summed to form a waveform with the desired harmonic content. + See page 1 for an example. + +control-warp(warp-fn, signal, [wrate]) [SAL] +(control-warp warp-fn signal wrate) [LISP] + Applies a warp function warp-fn to signal using function composition. If + wrate is omitted, linear interpolation is used. warp-fn is a mapping from + score (logical) time to real time, and signal is a function from score + time to real values. The result is a function from real time to real + values at a sample rate of *control-srate*. See sound-warp for an + explanation of wrate and high-quality warping. + +mult(beh , beh , ...) [SAL] + 1 2 +(mult beh beh ...) [LISP] + 1 2 + Returns the product of behaviors. The arguments may also be numbers, in + which case simple multiplication is performed. If a number and sound are + mixed, the scale function is used to scale the sound by the number. When + sounds are multiplied, the resulting sample rate is the maximum sample + rate of the factors. + +prod(beh , beh , ...) [SAL] + 1 2 +(prod beh beh ...) [LISP] + 1 2 + Same as mult. + +pan(sound, where) [SAL] +(pan sound where) [LISP] + Pans sound (a behavior) according to where (another behavior or a number). + Sound must be monophonic. Where may be a monophonic sound (e.g. (ramp) or + simply a number (e.g. 0.5). In either case, where should range from 0 to + 1, where 0 means pan completely left, and 1 means pan completely right. + For intermediate values, the sound to each channel is scaled linearly. + Presently, pan does not check its arguments carefully. + +prod(beh , beh , ...) [SAL] + 1 2 +(prod beh beh ...) [LISP] + 1 2 + Same as mult. + +resample(sound, srate) [SAL] +(resample sound srate) [LISP] + Similar to force-srate, except high-quality interpolation is used to + prefilter and reconstruct the signal at the new sample rate. Also, the + result is scaled by 0.95 to reduce problems with clipping. (See also + sound-warp.) + +scale(scale, sound) [SAL] +(scale scale sound) [LISP] + Scales the amplitude of sound by the factor scale. Identical function to + snd-scale, except that it handles multichannel sounds. Sample rates, + start times, etc. are taken from sound. + +scale-db(db, sound) [SAL] +(scale-db db sound) [LISP] + Scales the amplitude of sound by the factor db, expressed in decibels. + Sample rates, start times, etc. are taken from sound. + +scale-srate(sound, scale) [SAL] +(scale-srate sound scale) [LISP] + Scales the sample rate of sound by scale factor. This has the effect of + linearly shrinking or stretching time (the sound is not upsampled or + downsampled). This is a special case of snd-xform (see Section 7.6.2). + +shift-time(sound, shift) [SAL] +(shift-time sound shift) [LISP] + Shift sound by shift seconds. If the sound is f(t), then the result is + f(t-shift). See Figure 5. This is a special case of snd-xform (see + Section 7.6.2). + + + + + + + + + + + + + + + + + + + + + + Figure 5: The shift-time function shifts a sound in time according + to its shift argument. + + +sound-warp(warp-fn, signal [, wrate]) [SAL] +(sound-warp warp-fn signal [wrate]) [LISP] + Applies a warp function warp-fn to signal using function composition. If + the optional parameter wrate is omitted or NIL, linear interpolation is + used. Otherwise, high-quality sample interpolation is used, and the + result is scaled by 0.95 to reduce problems with clipping (interpolated + samples can exceed the peak values of the input samples.) warp-fn is a + mapping from score (logical) time to real time, and signal is a function + from score time to real values. The result is a function from real time + to real values at a sample rate of *sound-srate*. See also control-warp. + + If wrate is not NIL, it must be a number. The parameter indicates that + high-quality resampling should be used and specifies the sample rate for + the inverse of warp-fn. Use the lowest number you can. (See below for + details.) Note that high-quality resampling is much slower than linear + interpolation. + + To perform high-quality resampling by a fixed ratio, as opposed to a + variable ratio allowed in sound-warp, use scale-srate to stretch or shrink + the sound, and then resample to restore the original sample rate. + + Sound-warp and control-warp both take the inverse of warp-fn to get a + function from real time to score time. Each sample of this inverse is thus + a score time; signal is evaluated at each of these score times to yield a + value, which is the desired result. The sample rate of the inverse warp + function is somewhat arbitrary. With linear interpolation, the inverse + warp function sample rate is taken to be the output sample rate. Note, + however, that the samples of the inverse warp function are stored as + 32-bit floats, so they have limited precision. Since these floats + represent sample times, rounding can be a problem. Rounding in this case + is equivalent to adding jitter to the sample times. Nyquist ignores this + problem for ordinary warping, but for high-quality warping, the jitter + cannot be ignored. + + The solution is to use a rather low sample rate for the inverse warp + function. Sound-warp can then linearly interpolate this signal using + double-precision floats to minimize jitter between samples. The sample + rate is a compromise: a low sample rate minimizes jitter, while a high + sample rate does a better job of capturing detail (e.g. rapid + fluctuations) in the warp function. A good rule of thumb is to use at most + 1,000 to 10,000 samples for the inverse warp function. For example, if the + result will be 1 minute of sound, use a sample rate of 3000 samples / 60 + seconds = 50 samples/second. Because Nyquist has no advance information + about the warp function, the inverse warp function sample rate must be + provided as a parameter. When in doubt, just try something and let your + ears be the judge. + +integrate(signal) [SAL] +(integrate signal) [LISP] + Computes the integral of signal. The start time, sample rate, etc. are + taken from signal. + +slope(signal) [SAL] +(slope signal) [LISP] + Computes the first derivative (slope) of signal. The start time, sample + rate, etc. are taken from signal. + + +7.2.2.1. Oscillators + +osc(pitch [, duration, table, phase]) [SAL] +(osc pitch [duration table phase]) [LISP] + Returns a sound which is the table oscillated at pitch for the given + duration, starting with the phase (in degrees). Defaults are: duration + 1.0 (second), table *table*, phase 0.0. The default value of *table* is a + sinusoid. Duration is stretched by *warp* and *sustain*, amplitude is + nominally 1, but scaled by *loudness*, the start time is logical time 0, + transformed by *warp*, and the sample rate is *sound-srate*. The effect + of time-warping is to warp the starting and ending times only; the signal + has a constant unwarped frequency. Note 1: table is a list of the form + + (sound pitch-number periodic) + + where the first element is a sound, the second is the pitch of the sound + (this is not redundant, because the sound may represent any number of + periods), and the third element is T if the sound is one period of a + periodic signal, or nil if the sound is a sample that should not be + looped. The maximum table size is set by max_table_len in sound.h, and is + currently set to 1,000,000. Note 2: in the current implementation, it is + assumed that the output should be periodic. See snd-down and snd-up for + resampling one-shot sounds to a desired sample rate. A future version of + osc will handle both cases. Note 3: When osc is called, memory is + allocated for the table, and samples are copied from the sound (the first + element of the list which is the table parameter) to the memory. Every + instance of osc has a private copy of the table, so the total storage can + become large in some cases, for example in granular synthesis with many + instances of osc. In some cases, it may make sense to use snd-flatten (see + Section 7.1.3) to cause the sound to be fully realized, after which the + osc and its table memory can be reclaimed by garbage collection. The + partial function (see below) does not need a private table and does not + use much space. + +partial(pitch, env) [SAL] +(partial pitch env) [LISP] + Returns a sinusoid at the indicated pitch; the sound is multiplied by env. + The start time and duration are taken from env, which is of course subject + to transformations. The sample rate is *sound-srate*. The partial + function is faster than osc. + +sine(pitch [, duration]) [SAL] +(sine pitch [duration]) [LISP] + Returns a sinusoid at the indicated pitch. The sample rate is + *sound-srate*. This function is like osc with respect to transformations. + The sine function is faster than osc. + +hzosc(hz [, table, phase]) [SAL] +(hzosc hz [table phase]) [LISP] + Returns a sound which is the table oscillated at hz starting at phase + degrees. The default table is *table* and the default phase is 0.0. The + default duration is 1.0, but this is stretched as in osc (see above). The + hz parameter may be a SOUND, in which case the duration of the result is + the duration of hz. The sample rate is *sound-srate*. + +osc-saw(hz) [SAL] +(osc-saw hz) [LISP] + Returns a sawtooth waveshape at the indicated frequency (in Hertz). The + sample rate is *sound-srate*. The hz parameter may be a sound as in hzosc + (see above). + +osc-tri(hz) [SAL] +(osc-tri hz) [LISP] + Returns a triangle waveshape at the indicated frequency (in Hertz). The + sample rate is *sound-srate*. The hz parameter may be a sound as in hzosc + (see above). + +osc-pulse(hz, bias [, compare-shape]) [SAL] +(osc-pulse hz bias [compare-shape]) [LISP] + Returns a square pulse with variable width at the indicated frequency (in + Hertz). The bias parameter controls the pulse width and should be between + -1 and +1, giving a pulse width from 0% (always at -1) to 100% (always at + +1). When bias is zero, a square wave is generated. Bias may be a SOUND to + create varying pulse width. If bias changes rapidly, strange effects may + occur. The optional compare-shape defaults to a hard step at zero, but + other shapes may be used to achieve non-square pulses. The osc-pulse + behavior is written in terms of other behaviors and defined in the file + nyquist.lsp using just a few lines of code. Read the code for the complete + story. + +amosc(pitch, modulation [, table, phase]) [SAL] +(amosc pitch modulation [table phase]) [LISP] + Returns a sound which is table oscillated at pitch. The output is + multiplied by modulation for the duration of the sound modulation. + osc-table defaults to *table*, and phase is the starting phase (default + 0.0 degrees) within osc-table. The sample rate is *sound-srate*. + +fmosc(pitch, modulation [, table, phase]) [SAL] +(fmosc pitch modulation [table phase]) [LISP] + Returns a sound which is table oscillated at pitch plus modulation for the + duration of the sound modulation. osc-table defaults to *table*, and + phase is the starting phase (default 0.0 degrees) within osc-table. The + modulation is expressed in hz, e.g. a sinusoid modulation signal with an + amplitude of 1.0 (2.0 peak to peak), will cause a +/N 1.0 hz frequency + deviation in sound. Negative frequencies are correctly handled. The + sample rate is *sound-srate*. + +fmfb(pitch, index [, dur]) [SAL] +(fmfb pitch index [dur]) [LISP] + Returns a sound generated by feedback FM synthesis. The pitch parameter + (given in the usual half-step units) controls the fundamental frequency. + The index is the amount of feedback, which may be a SOUND or a FLONUM. If + index is a FLONUM, dur must be provided (a FLONUM) to specify the + duration. Otherwise, dur is ignored if present and the duration is + determined by that of index. The sample rate is *sound-srate*. A sinusoid + table is used. If index is below 1.1, this generates a sawtooth-like + waveform. + +buzz(n, pitch, modulation) [SAL] +(buzz n pitch modulation) [LISP] + Returns a sound with n harmonics of equal amplitude and a total amplitude + of 1.0, using a well-known function of two cosines. If n (an integer) is + less than 1, it is set to 1. Aliasing will occur if n is too large. The + duration is determined by the duration of the sound modulation, which is a + frequency modulation term expressed in Hz (see Section 7.2.2.1). Negative + frequencies are correctly handled. The sample rate is *sound-srate*. + +pluck(pitch [, duration, final-amplitude]) [SAL] +(pluck pitch [duration final-amplitude]) [LISP] + Returns a sound at the given pitch created using a modified Karplus-Strong + plucked string algorithm. The tone decays from an amplitude of about 1.0 + to about final-amplitude in duration seconds. The default values are to + decay to 0.001 (-60dB) in 1 second. The sample rate is *sound-srate*. + +siosc(pitch, modulation, tables) [SAL] +(siosc pitch modulation tables) [LISP] + Returns a sound constructed by interpolating through a succession of + periodic waveforms. The frequency is given (in half steps) by pitch to + which a modulation signal (in hz) is added, exactly as in fmosc. The + tables specify a list of waveforms as follows: (table0 time1 table2 ... + timeN tableN), where each table is a sound representing one period. Each + time is a time interval measured from the starting time. The time is + scaled by the nominal duration (computed using (local-to-global + (get-sustain))) to get the actual time. Note that this implies linear + stretching rather than continuous timewarping of the interpolation or the + breakpoints. The waveform is table0 at the starting time, table1 after + time1 (scaled as described), and so on. The duration and logical stop time + is given by modulation. If modulation is shorter than timeN, then the full + sequence of waveforms is not used. If modulation is longer than timeN, + tableN is used after timeN without further interpolation. + +sampler(pitch, modulation [, sample, npoints]) [SAL] +(sampler pitch modulation [sample npoints]) [LISP] + Returns a sound constructed by reading a sample from beginning to end and + then splicing on copies of the same sound from a loop point to the end. + The pitch and modulation parameters are used as in fmosc described above. + The optional sample (which defaults to the global variable *table* is a + list of the form + + (sound pitch-number loop-start) + + where the first element is a sound containing the sample, the second is + the pitch of the sample, and the third element is the time of the loop + point. If the loop point is not in the bounds of the sound, it is set to + zero. The optional npoints specifies how many points should be used for + sample interpolation. Currently this parameter defaults to 2 and only + 2-point (linear) interpolation is implemented. It is an error to modulate + such that the frequency is negative. Note also that the loop point may be + fractional. The sample rate is *sound-srate*. + + +7.2.2.2. Piece-wise Approximations + There are a number of related behaviors for piece-wise approximations to +functions. The simplest of these, pwl was mentioned earlier in the manual. It +takes a list of breakpoints, assuming an initial point at (0, 0), and a final +value of 0. An analogous piece-wise exponential function, pwe, is provided. +Its implicit starting and stopping values are 1 rather than 0. Each of these +has variants. You can specify the initial and final values (instead of taking +the default). You can specify time in intervals rather than cummulative time. +Finally, you can pass a list rather than an argument list. This leads to 16 +versions: + + Piece-wise Linear Functions: + Cummulative Time: + Default initial point at (0, 0), final value at 0: + pwl + pwl-list + Explicit initial value: + pwlv + pwlv-list + Relative Time: + Default initial point at (0, 0), final value at 0: + pwlr + pwlr-list + Explicit initial value: + pwlvr + pwlvr-list + Piece-wise Exponential Functions: + Cummulative Time: + Default initial point at (0, 1), final value at 1: + pwe + pwe-list + Explicit initial value: + pwev + pwev-list + Relative Time: + Default initial point at (0, 1), final value at 1: + pwer + pwer-list + Explicit initial value: + pwevr + pwevr-list + +All of these functions are implemented in terms of pwl (see nyquist.lsp for the +implementations. There are infinite opportunities for errors in these +functions: if you leave off a data point, try to specify points in reverse +order, try to create an exponential that goes to zero or negative values, or +many other bad things, the behavior is not well-defined. Nyquist should not +crash, but Nyquist does not necessarily attempt to report errors at this time. + +pwl(t , l , t , l , ... t ) [SAL] + 1 1 2 2 n +(pwl t l t l ... t ) [LISP] + 1 1 2 2 n + Creates a piece-wise linear envelope with breakpoints at (0, 0), (t , l ), + 1 1 + (t , l ), ... (t , 0). The breakpoint times are scaled linearly by the + 2 2 n + value of *sustain* (if *sustain* is a SOUND, it is evaluated once at the + starting time of the envelope). Each breakpoint time is then mapped + according to *warp*. The result is a linear interpolation (unwarped) + between the breakpoints. The sample rate is *control-srate*. Breakpoint + times are quantized to the nearest sample time. If you specify one or + more breakpoints withing one sample period, pwl attempts to give a good + approximation to the specified function. In particular, if two + breakpoints are simultaneous, pwl will move one of them to an adjacent + sample, producing a steepest possible step in the signal. The exact + details of this ``breakpoint munging'' is subject to change in future + versions. Please report any cases where breakpoint lists give unexpected + behaviors. The author will try to apply the ``principle of least + surprise'' to the design. Note that the times are relative to 0; they are + not durations of each envelope segment. + +pwl-list(breakpoints) [SAL] +(pwl-list breakpoints) [LISP] + If you have a list of breakpoints, you can use apply to apply the pwl + function to the breakpoints, but if the list is very long (hundreds or + thousands of points), you might get a stack overflow because XLISP has a + fixed-size argument stack. Instead, call pwl-list, passing one argument, + the list of breakpoints. + +pwlv(l , t , l , t , t , ... t , l ) [SAL] + 1 2 2 3 3 n n +(pwlv l t l t t ... t l ) [LISP] + 1 2 2 3 3 n n + Creates a piece-wise linear envelope with breakpoints at (0, l ), (t , + 1 2 + l ), etc., ending with (t , l . Otherwise, the behavior is like that of + 2 n n + pwl. + +pwlv-list(breakpoints) [SAL] +(pwlv-list breakpoints) [LISP] + A version of pwlv that takes a single list of breakpoints as its argument. + See pwl-list above for the rationale. + +pwlr(i , l , i , l , ... i ) [SAL] + 1 1 2 2 n +(pwlr i l i l ... i ) [LISP] + 1 1 2 2 n + Creates a piece-wise linear envelope with breakpoints at (0, 0), (t , l ), + 1 1 + (t , l ), ... (t , 0), where t is the sum of i through i . In other + 2 2 n j 1 j + words, the breakpoint times are specified in terms of intervals rather + than cummulative time. Otherwise, the behavior is like that of pwl. + +pwlr-list(breakpoints) [SAL] +(pwlr-list breakpoints) [LISP] + A version of pwlr that takes a single list of breakpoints as its argument. + See pwl-list above for the rationale. + +pwlvr(l , i , l , i , i , ... i , l ) [SAL] + 1 2 2 3 3 n n +(pwlvr l i l i i ... i l ) [LISP] + 1 2 2 3 3 n n + Creates a piece-wise linear envelope with breakpoints at (0, l ), (t , + 1 2 + l ), etc., ending with (t , l , where t is the sum of i through i . In + 2 n n j 2 j + other words, the breakpoint times are specified in terms of intervals + rather than cummulative time. Otherwise, the behavior is like that of + pwlv. + +pwlvr-list(breakpoints) [SAL] +(pwlvr-list breakpoints) [LISP] + A version of pwlvr that takes a single list of breakpoints as its + argument. See pwl-list above for the rationale. + +pwe(t , l , t , l , ... t ) [SAL] + 1 1 2 2 n +(pwe t l t l ... t ) [LISP] + 1 1 2 2 n + Creates a piece-wise exponential envelope with breakpoints at (0, 1), (t , + 1 + l ), (t , l ), ... (t , 1). Exponential segments means that the ratio of + 1 2 2 n + values from sample to sample is constant within the segment. (The current + implementation actually takes the log of each value, computes a piece-wise + exponential from the points using pwl, then exponentiates each resulting + sample. A faster implementation is certainly possible!) Breakpoint + values (l ) must be greater than zero. Otherwise, this function is + j + similar to pwl, including stretch by *sustain*, mapping according to + *warp*, sample rate based on *control-srate*, and "breakpoint munging" + (see pwl described above). Default initial and final values are of + dubious value with exponentials. See pwev below for the function you are + probably looking for. + +pwe-list(breakpoints) [SAL] +(pwe-list breakpoints) [LISP] + A version of pwe that takes a single list of breakpoints as its argument. + See pwl-list above for the rationale. + +pwev(l , t , l , t , t , ... t , l ) [SAL] + 1 2 2 3 3 n n +(pwev l t l t t ... t l ) [LISP] + 1 2 2 3 3 n n + Creates a piece-wise exponential envelope with breakpoints at (0, l ), + 1 + (t , l ), etc., ending with (t , l ). Otherwise, the behavior is like + 2 2 n n + that of pwe. + +pwev-list(breakpoints) [SAL] +(pwev-list breakpoints) [LISP] + A version of pwev that takes a single list of breakpoints as its argument. + See pwl-list above for the rationale. + +pwer(i , l , i , l , ... i ) [SAL] + 1 1 2 2 n +(pwer i l i l ... i ) [LISP] + 1 1 2 2 n + Creates a piece-wise exponential envelope with breakpoints at (0, 1), (t , + 1 + l ), (t , l ), ... (t , 1), where t is the sum of i through i . In + 1 2 2 n j 1 j + other words, the breakpoint times are specified in terms of intervals + rather than cummulative time. Otherwise, the behavior is like that of + pwe. Consider using pwerv instead of this one. + +pwer-list(breakpoints) [SAL] +(pwer-list breakpoints) [LISP] + A version of pwer that takes a single list of breakpoints as its argument. + See pwl-list above for the rationale. + +pwevr(l , i , l , i , i , ... i , l ) [SAL] + 1 2 2 3 3 n n +(pwevr l i l i i ... i l ) [LISP] + 1 2 2 3 3 n n + Creates a piece-wise exponential envelope with breakpoints at (0, l ), + 1 + (t , l ), etc., ending with (t , l , where t is the sum of i through i . + 2 2 n n j 2 j + In other words, the breakpoint times are specified in terms of intervals + rather than cummulative time. Otherwise, the behavior is like that of + pwev. Note that this is similar to the csound GEN05 generator. Which is + uglier, GEN05 or pwevr? + +pwevr-list(breakpoints) [SAL] +(pwevr-list breakpoints) [LISP] + A version of pwevr that takes a single list of breakpoints as its + argument. See pwl-list above for the rationale. + + +7.2.2.3. Filter Behaviors + +alpass(sound, decay, hz [, minhz]) [SAL] +(alpass sound decay hz [minhz]) [LISP] + Applies an all-pass filter to sound. This all-pass filter creates a delay + effect without the resonances of a comb filter. The decay time of the + filter is given by decay. The hz parameter must be a number or sound + greater than zero. It is used to compute delay, which is then rounded to + the nearest integer number of samples (so the frequency is not always + exact. Higher sampling rates yield better delay resolution.) The decay + may be a sound or a number. In either case, it must also be positive. + (Implementation note: an exponentiation is needed to convert decay into + the feedback parameter, and exponentiation is typically more + time-consuming than the filter operation itself. To get high performance, + provide decay at a low sample rate.) The resulting sound will have the + start time, sample rate, etc. of sound. If hz is of type SOUND, the delay + may be time-varying. Linear interpolation is then used for fractional + sample delay, but it should be noted that linear interpolation implies a + low-pass transfer function. Thus, this filter may behave differently with + a constant SOUND than it does with a FLONUM value for hz. In addition, if + hz is of type SOUND, then minhz is required. The hz parameter will be + clipped to be greater than minhz, placing an upper bound on the delay + buffer length. + +comb(sound, decay, hz) [SAL] +(comb sound decay hz) [LISP] + Applies a comb filter to sound. A comb filter emphasizes (resonates at) + frequencies that are multiples of a hz. The decay time of the resonance is + given by decay. This is a variation on feedback-delay (see below). The + hz parameter must be a number greater than zero. It is used to compute + delay, which is then rounded to the nearest integer number of samples (so + the frequency is not always exact. Higher sampling rates yield better + delay resolution.) The decay may be a sound or a number. In either case, + it must also be positive. (Implementation note: an exponentiation is + needed to convert decay into the feedback parameter for feedback-delay, + and exponentiation is typically more time-consuming than the filter + operation itself. To get high performance, provide decay at a low sample + rate.) The resulting sound will have the start time, sample rate, etc. of + sound. + +congen(gate, risetime, falltime) [SAL] +(congen gate risetime falltime) [LISP] + Implements an analog synthesizer-style contour generator. The input gate + normally goes from 0.0 to 1.0 to create an attack and from 1.0 to 0.0 to + start a release. During the attack (output is increasing), the output + converges half-way to gate in risetime (a FLONUM) seconds. During the + decay, the half-time is falltime seconds. The sample rate, start time, + logical stop, and terminate time all come from gate. If you want a nice + decay, be sure that the gate goes to zero and stays there for awhile + before gate terminates, because congen (and all Nyquist sounds) go + immediately to zero at termination time. For example, you can use pwl to + build a pulse followed by some zero time: + + (pwl 0 1 duty 1 duty 0 1) + + Assuming duty is less than 1.0, this will be a pulse of duration duty + followed by zero for a total duration of 1.0. + + (congen (pwl 0 1 duty 1 duty 0 1) 0.01 0.05) + + will have a duration of 1.0 because that is the termination time of the + pwl input. The decaying release of the resulting envelope will be + truncated to zero at time 1.0. (Since the decay is theoretically infinite, + there is no way to avoid truncation, although you could multiply by + another envelope that smoothly truncates to zero in the last millisecond + or two to get both an exponential decay and a smooth final transition to + zero.) + +convolve(sound, response) [SAL] +(convolve sound response) [LISP] + Convolves two signals. The first can be any length, but the computation + time per sample and the total space required are proportional to the + length of response. + +feedback-delay(sound, delay, feedback) [SAL] +(feedback-delay sound delay feedback) [LISP] + Applies feedback delay to sound. The delay must be a number (in seconds). + It is rounded to the nearest sample to determine the length of the delay. + The sample rate is the maximum from sound and feedback (if feedback is + also a sound). The amound of feedback should be less than one to avoid an + exponential increase in amplitude. The start time and stop time, and + logical stop time are taken from sound. Since output is truncated at the + stop time of sound, you may want to append some silence to sound to give + the filter time to decay. + +lp(sound, cutoff) [SAL] +(lp sound cutoff) [LISP] + Filters sound using a first-order Butterworth low-pass filter. Cutoff may + be a float or a signal (for time-varying filtering) and expresses hertz. + Filter coefficients (requiring trig functions) are recomputed at the + sample rate of cutoff. The resulting sample rate, start time, etc. are + taken from sound. + +tone(sound, cutoff) [SAL] +(tone sound cutoff) [LISP] + No longer defined; use lp instead, or define it by adding (setfn tone lp) + to your program. + +hp(sound, cutoff) [SAL] +(hp sound cutoff) [LISP] + Filters sound using a first-order Butterworth high-pass filter. Cutoff + may be a float or a signal (for time-varying filtering) and expresses + hertz. Filter coefficients (requiring trig functions) are recomputed at + the sample rate of cutoff. This filter is an exact complement of lp. + +atone(sound, cutoff) [SAL] +(atone sound cutoff) [LISP] + No longer defined; use hp instead, or define it by adding (setfn atone hp) + to your program. + +reson(sound, center, bandwidth, n) [SAL] +(reson sound center bandwidth n) [LISP] + Apply a resonating filter to sound with center frequency center (in + hertz), which may be a float or a signal. Bandwidth is the filter + bandwidth (in hertz), which may also be a signal. Filter coefficients + (requiring trig functions) are recomputed at each new sample of either + center or bandwidth, and coefficients are not interpolated. The last + parameter n specifies the type of normalization as in Csound: A value of 1 + specifies a peak amplitude response of 1.0; all frequencies other than hz + are attenuated. A value of 2 specifies the overall RMS value of the + amplitude response is 1.0; thus filtered white noise would retain the same + power. A value of zero specifies no scaling. The resulting sample rate, + start time, etc. are taken from sound. + +One application of reson is to simulate resonances in the human vocal tract. + See demos/voice_synthesis.htmfor sample code and documentation. + +areson(sound, center, bandwidth, n) [SAL] +(areson sound center bandwidth n) [LISP] + The areson filter is an exact complement of reson such that if both are + applied to the same signal with the same parameters, the sum of the + results yeilds the original signal. + +shape(signal, table, origin) [SAL] +(shape signal table origin) [LISP] + A waveshaping function. Use table as a function; apply the function to + each sample of signal to yield a new sound. Signal should range from -1 + to +1. Anything beyond these bounds is clipped. Table is also a sound, + but it is converted into a lookup table (similar to table-lookup + oscillators). The origin is a FLONUM and gives the time which should be + considered the origin of table. (This is important because table cannot + have values at negative times, but signal will often have negative values. + The origin gives an offset so that you can produce suitable tables.) The + output at time t is: + + table(origin + clip(signal(t)) + + where clip(x) = max(1, min(-1, x)). (E.g. if table is a signal defined + over the interval [0, 2], then origin should be 1.0. The value of table + at time 1.0 will be output when the input signal is zero.) The output has + the same start time, sample rate, etc. as signal. The shape function will + also accept multichannel signals and tables. + +Further discussion and examples can be found in demos/distortion.htm. The + shape function is also used to map frequency to amplitude to achieve a + spectral envelope for Shepard tones in demos/shepard.lsp. + +biquad(signal, b0, b1, b2, a0, a1, a2) [SAL] +(biquad signal b0 b1 b2 a0 a1 a2) [LISP] + A fixed-parameter biquad filter. All filter coefficients are FLONUMs. See + also lowpass2, highpass2, bandpass2, notch2, allpass2, eq-lowshelf, + eq-highshelf, eq-band, lowpass4, lowpass6, highpass4, and highpass8 in + this section for convenient variations based on the same filter. The + equations for the filter are: z = s + a1 * z + a2 * z , and y = z + n n n-1 n-2 n n + * b0 + z * b1 + z * b2. + n-1 n-2 +biquad-m(signal, b0, b1, b2, a0, a1, a2) [SAL] +(biquad-m signal b0 b1 b2 a0 a1 a2) [LISP] + A fixed-parameter biquad filter with Matlab sign conventions for a0, a1, + and a2. All filter coefficients are FLONUMs. + +lowpass2(signal, hz [, q]) [SAL] +(lowpass2 signal hz [q]) [LISP] + A fixed-parameter, second-order lowpass filter based on snd-biquad. The + cutoff frequency is given by hz (a FLONUM) and an optional Q factor is + given by q (a FLONUM). + +highpass2(signal, hz [, q]) [SAL] +(highpass2 signal hz [q]) [LISP] + A fixed-parameter, second-order highpass filter based on snd-biquad. The + cutoff frequency is given by hz (a FLONUM) and an optional Q factor is + given by q (a FLONUM). + +bandpass2(signal, hz [, q]) [SAL] +(bandpass2 signal hz [q]) [LISP] + A fixed-parameter, second-order bandpass filter based on snd-biquad. The + center frequency is given by hz (a FLONUM) and an optional Q factor is + given by q (a FLONUM). + +notch2(signal, hz [, q]) [SAL] +(notch2 signal hz [q]) [LISP] + A fixed-parameter, second-order notch filter based on snd-biquad. The + center frequency is given by hz (a FLONUM) and an optional Q factor is + given by q (a FLONUM). + +allpass2(signal, hz [, q]) [SAL] +(allpass2 signal hz [q]) [LISP] + A fixed-parameter, second-order allpass filter based on snd-biquad. The + frequency is given by hz (a FLONUM) and an optional Q factor is given by q + (a FLONUM). + +eq-lowshelf(signal, hz, gain [, slope]) [SAL] +(eq-lowshelf signal hz gain [slope]) [LISP] + A fixed-parameter, second-order bass shelving equalization (EQ) filter + based on snd-biquad. The hz parameter (a FLONUM)is the halfway point in + the transition, and gain (a FLONUM) is the bass boost (or cut) in dB. The + optional slope (a FLONUM) is 1.0 by default, and response becomes peaky at + values greater than 1.0. + +eq-highshelf(signal, hz, gain [, slope]) [SAL] +(eq-highshelf signal hz gain [slope]) [LISP] + A fixed-parameter, second-order treble shelving equalization (EQ) filter + based on snd-biquad. The hz parameter (a FLONUM)is the halfway point in + the transition, and gain (a FLONUM) is the treble boost (or cut) in dB. + The optional slope (a FLONUM) is 1.0 by default, and response becomes + peaky at values greater than 1.0. + +eq-band(signal, hz, gain, width) [SAL] +(eq-band signal hz gain width) [LISP] + A fixed- or variable-parameter, second-order midrange equalization (EQ) + filter based on snd-biquad, snd-eqbandcv and snd-eqbandvvv. The hz + parameter (a FLONUM) is the center frequency, gain (a FLONUM) is the boost + (or cut) in dB, and width (a FLONUM) is the half-gain width in octaves. + Alternatively, hz, gain, and width may be SOUNDs, but they must all have + the same sample rate, e.g. they should all run at the control rate or at + the sample rate. + +lowpass4(signal, hz) [SAL] +(lowpass4 signal hz) [LISP] + A four-pole Butterworth lowpass filter. The cutoff frequency is hz (a + FLONUM). + +lowpass6(signal, hz) [SAL] +(lowpass6 signal hz) [LISP] + A six-pole Butterworth lowpass filter. The cutoff frequency is hz (a + FLONUM). + +lowpass8(signal, hz) [SAL] +(lowpass8 signal hz) [LISP] + An eight-pole Butterworth lowpass filter. The cutoff frequency is hz (a + FLONUM). + +highpass4(signal, hz) [SAL] +(highpass4 signal hz) [LISP] + A four-pole Butterworth highpass filter. The cutoff frequency is hz (a + FLONUM). + +highpass6(signal, hz) [SAL] +(highpass6 signal hz) [LISP] + A six-pole Butterworth highpass filter. The cutoff frequency is hz (a + FLONUM). + +highpass8(signal, hz) [SAL] +(highpass8 signal hz) [LISP] + An eight-pole Butterworth highpass filter. The cutoff frequency is hz (a + FLONUM). + +tapv(sound, offset, vardelay, maxdelay) [SAL] +(tapv sound offset vardelay maxdelay) [LISP] + A delay line with a variable position tap. Identical to snd-tapv. See it + for details (7.6.2). + + +7.2.2.4. Effects + +nrev(sound, decay, mix) [SAL] +(nrev sound decay mix) [LISP] +jcrev(sound, decay, mix) [SAL] +(jcrev sound decay mix) [LISP] +prcrev(sound, decay, mix) [SAL] +(prcrev sound decay mix) [LISP] +These reverbs (nrev, jcrev, and prcrev) are implemented in STK (running within + Nyquist). nrev derives from Common Music's NRev, which consists of 6 comb + filters followed by 3 allpass filters, a lowpass filter, and another + allpass in series followed by two allpass filters in parallel. jcrev is + the John Chowning reverberator which is based on the use of networks of + simple allpass and comb delay filters. This reverb implements three series + allpass units, followed by four parallel comb filters, and two + decorrelation delay lines in parallel at the output. prcrev is a Perry + Cook's reverberator which is based on the Chowning/Moorer/Schroeder + reverberators using networks of simple allpass and comb delay filters. + This one implements two series allpass units and two parallel comb + filters. The sound input may be single or multi-channel. The decay time + is in seconds, and mix sets the mixture of input sound reverb sound, where + 0.0 means input only (dry) and 1.0 means reverb only (wet). + +stkchorus(sound, depth, freq, mix [, delay]) [SAL] +(stkchorus sound depth freq mix [delay]) [LISP] + Chorus implemented in STK. The input sound can be single or multi-channel. + The FLONUM parameters depth and freq set the modulation depth from 0 to 1 + and modulation frequency (in Hz), and mix sets the mixture of input sound + and chorused sound, where 0.0 means input sound only (dry) and 1.0 means + chorused sound only (wet). The parameter delay is a FIXNUM representing + the median desired delay length in samples. + +pitshift(sound, shift, mix) [SAL] +(pitshift sound shift mix) [LISP] + A pitch shifter implemented in STK. The input sound, a single-channel or + multi-channel SOUND is pitch-shifted by shift, a FLONUM ratio. A value of + 1.0 means no shift. The parameter mix sets the mixture of input and + shifted sounds. A value of 0.0 means input only (dry) and a value of 1.0 + means shifted sound only (wet). + + +7.2.2.5. Physical Models + +clarinet(step, breath-env) [SAL] +(clarinet step breath-env) [LISP] + A physical model of a clarinet from STK. The step parameter is a FLONUM + that controls the tube length, and the breath-env (a SOUND) controls the + air pressure and also determines the length of the resulting sound. The + breath-env signal should range from zero to one. + +clarinet-freq(step, breath-env, freq-env) [SAL] +(clarinet-freq step breath-env freq-env) [LISP] + A variation of clarinet that includes a variable frequency control, + freq-env, which specifies frequency deviation in Hz. The duration of the + resulting sound is the minimum duration of breath-env and freq-env. These + parameters may be of type FLONUM or SOUND. FLONUMs are coerced into SOUNDs + with a nominal duration arbitrarily set to 30. + +clarinet-all(step, breath-env, freq-env, vibrato-freq, vibrato-gain, + reed-stiffness, noise) [SAL] +(clarinet-all step breath-env freq-env vibrato-freq vibrato-gain reed-stiffness + noise) [LISP] + A variation of clarinet-freq that includes controls vibrato-freq (a FLONUM + for vibrato frequency in Hertz), vibrato-gain (a FLONUM for the amount of + amplitude vibrato), reed-stiffness (a FLONUM or SOUND controlling reed + stiffness in the clarinet model), and noise (a FLONUM or SOUND controlling + noise amplitude in the input air pressure). The vibrato-gain is a number + from zero to one, where zero indicates no vibrato, and one indicates a + plus/minus 50% change in breath envelope values. Similarly, the noise + parameter ranges from zero to one where zero means no noise and one means + white noise with a peak amplitude of plus/minus 40% of the breath-env. The + reed-stiffness parameter varies from zero to one. The duration of the + resulting sound is the minimum duration of breath-env, freq-env, + reed-stiffness, and noise. As with clarinet-freq, these parameters may be + either FLONUMs or SOUNDs, and FLONUMs are coerced to sounds with a nominal + duration of 30. + +sax(step, breath-env) [SAL] +(sax step breath-env) [LISP] + A physical model of a sax from STK. The step parameter is a FLONUM that + controls the tube length, and the breath-env controls the air pressure and + also determines the length of the resulting sound. The breath-env signal + should range from zero to one. + +sax-freq(step, breath-env, freq-env) [SAL] +(sax-freq step breath-env freq-env) [LISP] + A variation of sax that includes a variable frequency control, freq-env, + which specifies frequency deviation in Hz. The duration of the resulting + sound is the minimum duration of breath-env and freq-env. These parameters + may be of type FLONUM or SOUND. FLONUMs are coerced into SOUNDs with a + nominal duration arbitrarily set to 30. + +sax-all(step, breath-env, freq-env, vibrato-freq, vibrato-gain, reed-stiffness, + noise, blow-pos, reed-table-offset) [SAL] +(sax-all step breath-env freq-env vibrato-freq vibrato-gain reed-stiffness + noise blow-pos reed-table-offset) [LISP] + A variation of sax-freq that includes controls vibrato-freq (a FLONUM for + vibrato frequency in Hertz), vibrato-gain (a FLONUM for the amount of + amplitude vibrato), reed-stiffness (a SOUND controlling reed stiffness in + the sax model), noise (a SOUND controlling noise amplitude in the input + air pressure), blow-pos (a SOUND controlling the point of excitation of + the air column), and reed-table-offset (a SOUND controlling a parameter of + the reed model). The vibrato-gain is a number from zero to one, where zero + indicates no vibrato, and one indicates a plus/minus 50% change in breath + envelope values. Similarly, the noise parameter ranges from zero to one + where zero means no noise and one means white noise with a peak amplitude + of plus/minus 40% of the breath-env. The reed-stiffness, blow-pos, and + reed-table-offset parameters all vary from zero to one. The duration of + the resulting sound is the minimum duration of breath-env, freq-env, + reed-stiffness, noise, breath-env, blow-pos, and reed-table-offset. As + with sax-freq, these parameters may be either FLONUMs or SOUNDs, and + FLONUMs are coerced to sounds with a nominal duration of 30. + +flute(step, breath-env) [SAL] +(flute step breath-env) [LISP] + A physical model of a flute from STK. The step parameter is a FLONUM that + controls the tube length, and the breath-env controls the air pressure and + also determines the starting time and length of the resulting sound. The + breath-env signal should range from zero to one. + +flute-freq(step, breath-env, freq-env) [SAL] +(flute-freq step breath-env freq-env) [LISP] + A variation of flute that includes a variable frequency control, freq-env, + which specifies frequency deviation in Hz. The duration of the resulting + sound is the minimum duration of breath-env and freq-env. These parameters + may be of type FLONUM or SOUND. FLONUMs are coerced into SOUNDs with a + nominal duration arbitrary set to 30. + +flute-all(step, breath-env, freq-env, vibrato-freq, vibrato-gain, jet-delay, + noise) [SAL] +(flute-all step breath-env freq-env vibrato-freq vibrato-gain jet-delay noise) + [LISP] + A variation of clarinet-freq that includes controls vibrato-freq (a FLONUM + for vibrato frequency in Hz), vibrato-gain (a FLONUM for the amount of + amplitude vibrato), jet-delay (a FLONUM or SOUND controlling jet delay in + the flute model), and noise (a FLONUM or SOUND controlling noise amplitude + in the input air pressure). The vibrato-gain is a number from zero to one + where zero means no vibrato, and one indicates a plus/minus 50% change in + breath envelope values. Similarly, the noise parameter ranges from zero to + one, where zero means no noise and one means white noise with a peak + amplitude of plus/minus 40% of the breath-env. The jet-delay is a ratio + that controls a delay length from the flute model, and therefore it + changes the pitch of the resulting sound. A value of 0.5 will maintain the + pitch indicated by the step parameter. The duration of the resulting sound + is the minimum duration of breath-env, freq-env, jet-delay, and noise. + These parameters may be either FLONUMs or SOUNDs, and FLONUMs are coerced + to sounds with a nominal duration of 30. + +bowed(step, bowpress-env) [SAL] +(bowed step bowpress-env) [LISP] + A physical model of a bowed string instrument from STK. The step parameter + is a FLONUM that controls the string length, and the bowpress-env controls + the bow pressure and also determines the duration of the resulting sound. + The bowpress-env signal should range from zero to one. + +bowed-freq(step, bowpress-env, freq-env) [SAL] +(bowed-freq step bowpress-env freq-env) [LISP] + A variation of bowed that includes a variable frequency control, freq-env, + which specifies frequency deviation in Hz. The duration of the resulting + sound is the minimum duration of bowpress-env and freq-env. These + parameters may be of type FLONUM or SOUND. FLONUMs are coerced into + SOUNDs with a nominal duration arbitrarily set to 30s. + +mandolin(step, dur, &optional detune) [SAL] +(mandolin step dur detune) [LISP] + A physical model of a plucked double-string instrument from STK. The step + parameter is a FLONUM wich specifies the desired pitch, dur means the + duration of the resulting sound and detune is a FLONUM that controls the + relative detune of the two strings. A value of 1.0 means unison. The + default value is 4.0. Note: body-size (see snd-mandolin does not seem to + work correctly, so a default value is always used by mandolin. + +wg-uniform-bar(step, bowpress-env) [SAL] +(wg-uniform-bar step bowpress-env) [LISP] +wg-tuned-bar(step, bowpress-env) [SAL] +(wg-tuned-bar step bowpress-env) [LISP] +wg-glass-harm(step, bowpress-env) [SAL] +(wg-glass-harm step bowpress-env) [LISP] +wg-tibetan-bowl(step, bowpress-env) [SAL] +(wg-tibetan-bowl step bowpress-env) [LISP] + These sounds are presets for a Banded Wave Guide Percussion instrument + implemented in STK. The parameter step is a FLONUM that controls the + resultant pitch, and bowpress-env is a SOUND ranging from zero to one that + controls a parameter of the model. In addition, bowpress-env determines + the duration of the resulting sound. (Note: The bowpress-env does not + seems influence the timbral quality of the resulting sound). + +modalbar(preset, step, dur) [SAL] +(modalbar preset step dur) [LISP] + A physical model of a struck bar instrument implemented in STK. The + parameter preset is one of the symbols MARIMBA, VIBRAPHONE, AGOGO, WOOD1, + RESO, WOOD2, BEATS, TWO-FIXED, or CLUMP. The symbol must be quoted, e.g. + for SAL syntax use quote(marimba), and for Lisp syntax use 'marimba. The + parameter step is a FLONUM that sets the pitch (in steps), and dur is the + duration in seconds. + +sitar(step, dur) [SAL] +(sitar step dur) [LISP] + A sitar physical model implemented in STK. The parameter step is a FLONUM + that sets the pitch, and dur is the duration. + + +7.2.2.6. More Behaviors + +clip(sound, peak) [SAL] +(clip sound peak) [LISP] + Hard limit sound to the given peak, a positive number. The samples of + sound are constrained between an upper value of peak and a lower value of + N()peak. If sound is a number, clip will return sound limited by peak. If + sound is a multichannel sound, clip returns a multichannel sound where + each channel is clipped. The result has the type, sample rate, starting + time, etc. of sound. + +s-abs(sound) [SAL] +(s-abs sound) [LISP] + A generalized absolute value function. If sound is a SOUND, compute the + absolute value of each sample. If sound is a number, just compute the + absolute value. If sound is a multichannel sound, return a multichannel + sound with s-abs applied to each element. The result has the type, sample + rate, starting time, etc. of sound. + +s-sqrt(sound) [SAL] +(s-sqrt sound) [LISP] + A generalized square root function. If sound is a SOUND, compute the + square root of each sample. If sound is a number, just compute the square + root. If sound is a multichannel sound, return a multichannel sound with + s-sqrt applied to each element. The result has the type, sample rate, + starting time, etc. of sound. In taking square roots, if an input sample + is less than zero, the corresponding output sample is zero. This is done + because the square root of a negative number is undefined. + +s-exp(sound) [SAL] +(s-exp sound) [LISP] + x + A generalized exponential function. If sound is a SOUND, compute e for + x + each sample x. If sound is a number x, just compute e . If sound is a + multichannel sound, return a multichannel sound with s-exp applied to each + element. The result has the type, sample rate, starting time, etc. of + sound. + +s-log(sound) [SAL] +(s-log sound) [LISP] + A generalized natural log function. If sound is a SOUND, compute ln(x) + for each sample x. If sound is a number x, just compute ln(x). If sound + is a multichannel sound, return a multichannel sound with s-log applied to + each element. The result has the type, sample rate, starting time, etc. + of sound. Note that the ln of 0 is undefined (some implementations return + negative infinity), so use this function with care. + +s-max(sound1, sound2) [SAL] +(s-max sound1 sound2) [LISP] + Compute the maximum of two functions, sound1 and sound2. This function + also accepts numbers and multichannel sounds and returns the corresponding + data type. The start time of the result is the maximum of the start times + of sound1 and sound2. The logical stop time and physical stop time of the + result is the minimum of the logical stop and physical stop times + respectively of sound1 and sound2. Note, therefore, that the result value + is zero except within the bounds of both input sounds. + +s-min(sound1, sound2) [SAL] +(s-min sound1 sound2) [LISP] + Compute the minimum of two functions, sound1 and sound2. This function + also accepts numbers and multichannel sounds and returns the corresponding + data type. The start time of the result is the maximum of the start times + of sound1 and sound2. The logical stop time and physical stop time of the + result is the minimum of the logical stop and physical stop times + respectively of sound1 and sound2. Note, therefore, that the result value + is zero except within the bounds of both input sounds. + +osc-note(pitch [, duration, env, loud, table]) [SAL] +(osc-note pitch [duration env loud table]) [LISP] + Same as osc, but osc-note multiplies the result by env. The env may be a + sound, or a list supplying (t t t l l l ). The result has a sample + 1 2 4 1 2 3 + rate of *sound-srate*. + +quantize(sound, steps) [SAL] +(quantize sound steps) [LISP] + Quantizes sound as follows: sound is multiplied by steps and rounded to + the nearest integer. The result is then divided by steps. For example, if + steps is 127, then a signal that ranges from -1 to +1 will be quantized to + 255 levels (127 less than zero, 127 greater than zero, and zero itself). + This would match the quantization Nyquist performs when writing a signal + to an 8-bit audio file. The sound may be multi-channel. + +ramp([duration]) [SAL] +(ramp [duration]) [LISP] + Returns a linear ramp from 0 to 1 over duration (default is 1). The + function actually reaches 1 at duration, and therefore has one extra + sample, making the total duration be duration + 1/*Control-srate*. See + Figure 6 for more detail. Ramp is unaffected by the sustain + transformation. The effect of time warping is to warp the starting and + ending times only. The ramp itself is unwarped (linear). The sample rate + is *control-srate*. + +rms(sound [, rate, window-size]) [SAL] +(rms sound [rate window-size]) [LISP] + Computes the RMS of sound using a square window of size window-size. The + result has a sample rate of rate. The default value of rate is 100 Hz, and + the default window size is 1/rate seconds (converted to samples). The rate + is a FLONUM and window-size is a FIXNUM. + + + + + + + + + + + + + + + + + + Figure 6: Ramps generated by pwl and ramp functions. The pwl + version ramps toward the breakpoint (1, 1), but in order to ramp + back to zero at breakpoint (1, 0), the function never reaches an + amplitude of 1. If used at the beginning of a seq construct, the + next sound will begin at time 1. The ramp version actually reaches + breakpoint (1, 1); notice that it is one sample longer than the pwl + version. If used in a sequence, the next sound after ramp would + start at time 1 + P, where P is the sample period. + + +recip(sound) [SAL] +(recip sound) [LISP] + A generalized reciprocal function. If sound is a SOUND, compute 1/x for + each sample x. If sound is a number x, just compute 1/x. If sound is a + multichannel sound, return a multichannel sound with recip applied to each + element. The result has the type, sample rate, starting time, etc. of + sound. Note that the reciprocal of 0 is undefined (some implementations + return infinity), so use this function with care on sounds. Division of + sounds is accomplished by multiplying by the reciprocal. Again, be + careful not to divide by zero. + +s-rest([duration]) [SAL] +(s-rest [duration]) [LISP] + Create silence (zero samples) for the given duration at the sample rate + *sound-srate*. Default duration is 1.0 sec, and the sound is transformed + in time according to *warp*. Note: rest is a Lisp function that is + equivalent to cdr. Be careful to use s-rest when you need a sound! + +noise([duration]) [SAL] +(noise duration) [LISP] + Generate noise with the given duration. Duration (default is 1.0) is + transformed according to *warp*. The sample rate is *sound-srate* and the + amplitude is +/- *loud*. + +yin(sound, minstep, maxstep, stepsize) [SAL] +(yin sound minstep maxstep stepsize) [LISP] + Fundamental frequency estimation (pitch detection. Use the YIN algorithm + to estimate the fundamental frequency of sound, which must be a SOUND. + The minstep, a FLONUM, is the minimum frequency considered (in steps), + maxstep, a FLONUM, is the maximum frequency considered (in steps), and + stepsize, a FIXNUM, is the desired hop size. The result is a ``stereo'' + signal, i.e. an array of two SOUNDs, both at the same sample rate, which + is approximately the sample rate of sound divided by stepsize. The first + SOUND consists of frequency estimates. The second sound consists of values + that measure the confidence or reliability of the frequency estimate. A + small value (less than 0.1) indicates fairly high confidence. A larger + value indicates lower confidence. This number can also be thought of as a + ratio of non-periodic power to periodic power. When the number is low, it + means the signal is highly periodic at that point in time, so the period + estimate will be reliable. Hint #1: See Alain de Cheveigne and Hideki + Kawahara's article "YIN, a Fundamental Frequency Estimator for Speech and + Music" in the Journal of the Acoustic Society of America, April 2002 for + details on the yin algorithm. Hint #2: Typically, the stepsize should be + at least the expected number of samples in one period so that the + fundamental frequency estimates are calculated at a rate far below the + sample rate of the signal. Frequency does not change rapidly and the yin + algorithm is fairly slow. To optimize speed, you may want to use less than + 44.1 kHz sample rates for input sounds. Yin uses interpolation to achieve + potentially fractional-sample-accurate estimates, so higher sample rates + do not necessarily help the algorithm and definitely slow it down. The + 2 + computation time is O(n ) per estimate, where n is the number of samples + in the longest period considered. Therefore, each increase of minstep by + 12 (an octave) gives you a factor of 4 speedup, and each decrease of the + sample rate of sound by a factor of two gives you another factor of 4 + speedup. Finally, the number of estimates is inversely proportional to + stepsize. Hint #3: Use snd-srate (see Section 7.1.3) to get the exact + sample rate of the result, which will be the sample rate of sound divided + by stepsize. E.g. (snd-srate (aref yin-output 0)), where yin-output is a + result returned by yin, will be the sample rate of the estimates. + +7.3. Transformations + These functions change the environment that is seen by other high-level +functions. Note that these changes are usually relative to the current +environment. There are also ``absolute'' versions of each transformation +function, with the exception of seq, seqrep, sim, and simrep. The ``absolute'' +versions (starting or ending with ``abs'') do not look at the current +environment, but rather set an environment variable to a specific value. In +this way, sections of code can be insulated from external transformations. + +abs-env(beh) [SAL] +(abs-env beh) [LISP] + Compute beh in the default environment. This is useful for computing + waveform tables and signals that are ``outside'' of time. For example, + (at 10.0 (abs-env (my-beh))) is equivalent to (abs-env (my-beh)) because + abs-env forces the default environment. Or in SAL, we would say + abs-env(my-beh()) @ 10 is equivalent to abs-env(my-beh()). + +at(time, beh) [SAL] +(at time beh) [LISP] + Evaluate beh with *warp* shifted by time. In SAL, you can use the infix + operator @ as in beh @ time. To discover how the environment is shifting + time, use local-to-global(time). Most commonly, you call local-to- + global(0) to find when a sound created in the current environment will + start, expressed in absolute (global) terms. This can be regarded as the + ``current time.'' + +at-abs(time, beh) [SAL] +(at-abs time beh) [LISP] + Evaluate beh with *warp* shifted so that local time 0 maps to time. In + SAL, you can use the infix operator @@ as in beh @@ time. + +continuous-control-warp(beh) [SAL] +(continuous-control-warp beh) [LISP] + Applies the current warp environment to the signal returned by beh. The + result has the default control sample rate *control-srate*. Linear + interpolation is currently used. Implementation: beh is first evaluated + without any shifting, stretching, or warping. The result is functionally + composed with the inverse of the environment's warp function. + +continuous-sound-warp(beh) [SAL] +(continuous-sound-warp beh) [LISP] + Applies the current warp environment to the signal returned by beh. The + result has the default sound sample rate *sound-srate*. Linear + interpolation is currently used. See continuous-control-warp for + implementation notes. + +control-srate-abs(srate, beh) [SAL] +(control-srate-abs srate beh) [LISP] + Evaluate beh with *control-srate*set to sample rate srate. Note: there is + no ``relative'' version of this function. + +extract(start, stop, beh) [SAL] +(extract start stop beh) [LISP] + Returns a sound which is the portion of beh between start and stop. Note + that this is done relative to the current *warp*. The result is shifted + to start according to *warp*, so normally the result will start without a + delay of start. + +extract-abs(start, stop, beh) [SAL] +(extract-abs start stop beh) [LISP] + Returns a sound which is the portion of beh between start and stop, + independent of the current *warp*. The result is shifted to start + according to *warp*. + +loud(volume, beh) [SAL] +(loud volume beh) [LISP] + Evaluates beh with *loud* incremented by volume. (Recall that *loud* is in + decibels, so increment is the proper operation.) + +loud-abs(volume, beh) [SAL] +(loud-abs volume beh) [LISP] + Evaluates beh with *loud* set to volume. + +sound-srate-abs(srate, beh) [SAL] +(sound-srate-abs srate beh) [LISP] + Evaluate beh with *sound-srate* set to sample rate srate. Note: there is + no ``relative'' version of this function. + +stretch(factor, beh) [SAL] +(stretch factor beh) [LISP] + Evaluates beh with *warp* scaled by factor. The effect is to ``stretch'' + the result of beh (under the current environment) by factor. See Chapter + 4 for more information. Use get-duration(dur) to get the nominal actual + duration of a behavior that locally has a duration of dur. Here, + ``nominal'' means what would be expected if the behavior obeys the shift, + stretch, and warp components of the environment. (Any behavior is free to + deviate from the nominal timing. For example, a percussion sound might + have a fixed duration independent of the stretch factor.) Also, ``actual'' + means global or absolute time, and ``locally'' means within the + environment where get-duration is called. get-duration works by mapping + the current time (local time 0) using local-to-global to obtain an actual + start time, and mapping dur to obtain an actual end time. The difference + is returned. + +stretch-abs(factor, beh) [SAL] +(stretch-abs factor beh) [LISP] + Evaluates beh with *warp* set to a linear time transformation where each + unit of logical time maps to factor units of real time. The effect is to + stretch the nominal behavior of beh (under the default global environment) + by factor. See Chapter 4 for more information. + +sustain(factor, beh) [SAL] +(sustain factor beh) [LISP] + Evaluates beh with *sustain* scaled by factor. The effect is to + ``stretch'' the result of beh (under the current environment) by factor; + however, the logical stop times are not stretched. Therefore, the overall + duration of a sequence is not changed, and sounds will tend to overlap if + *sustain* is greater than one (legato) and be separated by silence if + *sustain* is less than one. + +sustain-abs(factor, beh) [SAL] +(sustain-abs factor beh) [LISP] + Evaluates beh with *sustain* set to factor. (See sustain, above.) + +transpose(amount, beh) [SAL] +(transpose amount beh) [LISP] + Evaluates beh with *transpose* shifted by amount. The effect is relative + transposition by amount semitones. + +transpose-abs(amount, beh) [SAL] +(transpose-abs amount beh) [LISP] + Evaluates beh with *transpose* set to amount. The effect is the + transposition of the nominal pitches in beh (under the default global + environment) by amount. + +warp(fn, beh) [SAL] +(warp fn beh) [LISP] + Evaluates beh with *warp* modified by fn. The idea is that beh and fn are + written in the same time system, and fn warps that time system to local + time. The current environment already contains a mapping from local time + to global (real) time. The value of *warp* in effect when beh is + evaluated is the functional composition of the initial *warp* with fn. + +warp-abs(fn, beh) [SAL] +(warp-abs fn beh) [LISP] + Evaluates beh with *warp* set to fn. In other words, the current *warp* + is ignored and not composed with fn to form the new *warp*. + +7.4. Combination and Time Structure + These behaviors combine component behaviors into structures, including +sequences (melodies), simultaneous sounds (chords), and structures based on +iteration. + +seq(beh [, beh , ...]) [SAL] + 1 2 +(seq beh [beh ...]) [LISP] + 1 2 + Evaluates the first behavior beh according to *time* and each successive + 1 + behavior at the logical-stop time of the previous one. The results are + summed to form a sound whose logical-stop is the logical-stop of the last + behavior in the sequence. Each behavior can result in a multichannel + sound, in which case, the logical stop time is considered to be the + maximum logical stop time of any channel. The number of channels in the + result is the number of channels of the first behavior. If other + behaviors return fewer channels, new channels are created containing + constant zero signals until the required number of channels is obtained. + If other behaviors return a simple sound rather than multichannel sounds, + the sound is automatically assigned to the first channel of a multichannel + sound that is then filled out with zero signals. If another behavior + returns more channels than the first behavior, the error is reported and + the computation is stopped. Sample rates are converted up or down to + match the sample rate of the first sound in a sequence. + +seqrep(var, limit, beh) [SAL] +(seqrep var limit beh) [LISP] + Iteratively evaluates beh with the atom var set with values from 0 to + limit-1, inclusive. These sounds are placed sequentially in time as if by + seq. The symbol var is a read-only local variable to beh. Assignments are + not restricted or detected, but may cause a run-time error or crash. In + LISP, the syntax is (seqrep (var limit) beh). + +sim([beh , beh , ...]) [SAL] + 1 2 +(sim [beh beh ...]) [LISP] + 1 2 + Returns a sound which is the sum of the given behaviors evaluated with + current value of *warp*. If behaviors return multiple channel sounds, the + corresponding channels are added. If the number of channels does not + match, the result has the maximum. For example, if a two-channel sound + [L, R] is added to a four-channel sound [C1, C2, C3, C4], the result is [L + + C1, R + C2, C3, C4]. Arguments to sim may also be numbers. If all + arguments are numbers, sim is equivalent (although slower than) the + + function. If a number is added to a sound, snd-offset is used to add the + number to each sample of the sound. The result of adding a number to two + or more sounds with different durations is not defined. Use const to + coerce a number to a sound of a specified duration. An important + limitation of sim is that it cannot handle hundreds of behaviors due to a + stack size limitation in XLISP. To compute hundreds of sounds (e.g. + notes) at specified times, see timed-seq, below. See also sum below. + +simrep(var, limit, beh) [SAL] +(simrep var limit beh) [LISP] + Iteratively evaluates beh with the atom var set with values from 0 to + limit-1, inclusive. These sounds are then placed simultaneously in time + as if by sim. In LISP, the syntax is (seqrep (var limit) beh). + +trigger(s, beh) [SAL] +(trigger s beh) [LISP] + Returns a sound which is the sum of instances of the behavior beh. One + instance is created each time SOUND s makes a transition from less than or + equal to zero to greater than zero. (If the first sample of s is greater + than zero, an instance is created immediately.) The sample rate of s and + all behaviors must be the same, and the behaviors must be (monophonic) + SOUNDs. This function is particularly designed to allow behaviors to be + invoked in real time by making s a function of a Nyquist slider, which can + be controlled by a graphical interface or by OSC messages. See snd-slider + in Section 7.6.1. + +set-logical-stop(beh, time) [SAL] +(set-logical-stop beh time) [LISP] + Returns a sound with time as the logical stop time. + +sum(a [, b, ...]) [SAL] +(sum a [b ...]) [LISP] + Returns the sum of a, b, ..., allowing mixed addition of sounds, + multichannel sounds and numbers. Identical to sim. In SAL, use the infix + ``+'' operator. + +mult(a [, b, ...]) [SAL] +(mult a [b ...]) [LISP] + Returns the product of a, b, ..., allowing mixed multiplication of sounds, + multichannel sounds and numbers. + +diff(a, b) [SAL] +(diff a b) [LISP] + Returns the difference between a and b. This function is defined as (sum a + (prod -1 b)). + +timed-seq(score) [SAL] +(timed-seq score) [LISP] + Computes sounds from a note list or ``score.'' The score is of the form: + `((time1 stretch1 beh1) (time2 stretch2 beh2) ...), where timeN is the + starting time, stretchN is the stretch factor, and behN is the behavior. + Note that score is normally a quoted list! The times must be in increasing + order, and each behN is evaluated using lisp's eval, so the behN behaviors + cannot refer to local parameters or local variables. The advantage of this + form over seq is that the behaviors are evaluated one-at-a-time which can + take much less stack space and overall memory. One special ``behavior'' + expression is interpreted directly by timed-seq: (SCORE-BEGIN-END) is + ignored, not evaluated as a function. Normally, this special behavior is + placed at time 0 and has two parameters: the score start time and the + score end time. These are used in Xmusic functions. If the behavior has a + :pitch keyword parameter which is a list, the list represents a chord, and + the expression is replaced by a set of behaviors, one for each note in the + chord. It follows that if :pitch is nil, the behavior represents a rest + and is ignored. + +7.5. Sound File Input and Output + +play sound [SAL] +(play sound) [LISP] + Play the sound through the DAC. Note that play is a command in SAL. In + XLISP, it is a function, so the syntax is (play sound), and in SAL, you + can call the XLISP function as #play(sound). The play command or function + writes a file and plays it. The details of this are system-dependent, but + play is defined in the file system.lsp. The variable *default-sf-dir* + names a directory into which to save a sound file. Be careful not to call + play or sound-play within a function and then invoke that function from + another play command. + +By default, Nyquist will try to normalize sounds using the method named by + *autonorm-type*, which is 'lookahead by default. The lookahead method + precomputes and buffers *autonorm-max-samples* samples, finds the peak + value, and normalizes accordingly. The 'previous method bases the + normalization of the current sound on the peak value of the (entire) + previous sound. This might be good if you are working with long sounds + that start rather softly. See Section 5.3 for more details. + +If you want precise control over output levels, you should turn this feature + off by typing (using SAL syntax): + + autonorm-off() + + Reenable the automatic normalization feature by typing: + + autonorm-on() + + Play normally produces real-time output. The default is to send audio + data to the DAC as it is computed in addition to saving samples in a file. + If computation is slower than real-time, output will be choppy, but since + the samples end up in a file, you can type (r) to replay the stored sound. + Real-time playback can be disabled by (using SAL syntax): + + sound-off() + + and reenabled by: + + sound-on() + + Disabling real-time playback has no effect on (play-file) or (r). + +While sounds are playing, typing control-A to Nyquist will push the estimated + elapsed audio time onto the head of the list stored in *audio-markers*. + Because samples are computed in blocks and because there is latency + between sample computation and sample playback, the elapsed time may not + be too accurate, and the computed elapsed time may not advance after all + samples have been computed but the sound is still playing. + +play-file(filename) [SAL] +(play-file filename) [LISP] + Play the contents of a sound file named by filename. The s-read function + is used to read the file, and unless filename specifies an absolute path + or starts with ``.'', it will be read from *default-sf-dir*. + +autonorm-on() [SAL] +(autonorm-on) [LISP] + Enable automatic adjustment of a scale factor applied to sounds computed + using the play command. + +autonorm-off() [SAL] +(autonorm-off) [LISP] + Disable automatic adjustment of a scale factor applied to sounds computed + using the play command. + +sound-on() [SAL] +(sound-on) [LISP] + Enable real-time audio output when sound is computed by the the play + command. + +sound-off() [SAL] +(sound-off) [LISP] + Disable real-time audio output when sound is computed by the the play + command. + +s-save(expression, maxlen, filename, format: format, mode: mode, bits: bits, + swap: flag, play: play) [SAL] +(s-save expression maxlen filename :format format :mode mode :bits bits :swap + flag :play play) [LISP] + Evaluates the expression, which should result in a sound or an array of + sounds, and writes the result to the given filename. A FLONUM is returned + giving the maximum absolute value of all samples written. (This is useful + for normalizing sounds and detecting sample overflow.) If play is not NIL, + the sound will be output through the computer's audio output system. + (play: [SAL] or :play [LISP] is not implemented on all systems; if it is + implemented, and filename is NIL, then this will play the file without + also writing a file.) The latency (length of audio buffering) used to + play the sound is 0.3s by default, but see snd-set-latency. If a + multichannel sound (array) is written, the channels are up-sampled to the + highest rate in any channel so that all channels have the same sample + rate. The maximum number of samples written per channel is given by + maxlen, which allows writing the initial part of a very long or infinite + sound. A header is written according to format, samples are encoded + according to mode, using bits bits/sample, and bytes are swapped if flag + is not NIL. Defaults for these are *default-sf-format*, *default-sf- + mode*, and *default-sf-bits*. The default for flag is NIL. The bits + parameter may be 8, 16, or 32. The values for the format and mode options + are described below: + + Format + +snd-head-none The format is unknown and should be determined by reading + the file. + +snd-head-raw A raw format file has no header. + +snd-head-AIFF AIFF format header. + +snd-head-IRCAM IRCAM format header. + +snd-head-NeXT 1024-byte NeXT/SUN format header followed by IRCAM header + ala CMIX. Note that the NeXT/SUN format has a + header-length field, so it really is legal to have a large + header, even though the normal minimal header is only 24 + bytes. The additional space leaves room for maximum + amplitudes, which can be used for normalizing floating- + point soundfiles, and for other data. Nyquist follows the + CMIX convention of placing an IRCAM format header + immediately after the NeXT-style header. + +snd-head-Wave Microsoft Wave format header. + +snd-head-* See sndfnint.lsp for more formats. + + Mode + +snd-mode-adpcm ADPCM mode (not supported). + +snd-mode-pcm signed binary PCM mode. + +snd-mode-ulaw 8-bit U-Law mode. + +snd-mode-alaw 8-bit A-Law mode (not supported). + +snd-mode-float 32-bit floating point mode. + +snd-mode-upcm unsigned binary PCM mode. + +snd-mode-* See sndfnint.lsp for more modes. + + The defaults for format, mode, and bits are as follows: + +NeXT and Sun machines: + snd-head-NeXT, snd-mode-pcm, 16 + +SGI and Macintosh machines: + snd-head-AIFF, snd-mode-pcm, 16 + +s-read(filename, time-offset: offset, srate: sr, dur: dur, nchans: chans, + format: format, mode: mode, bits: n, swap: flag) [SAL] +(s-read filename :time-offset offset :srate sr :dur dur :nchans chans :format + format :mode mode :bits n :swap flag) [LISP] + Reads a sound from filename. The global *default-sf-dir* applies. If a + header is detected, the header is used to determine the format of the + file, and header information overrides format information provided by + keywords (except for time-offset: and dur:). + + s-read("mysound.snd", srate: 44100) + + specifies a sample rate of 44100 hz, but if the file has a header + specifying 22050 hz, the resulting sample rate will be 22050. The + parameters are: + + - offset M the amount of time (in seconds) to skip from the + beginning of the file. The default is 0.0. + + - sr M the sample rate of the samples in the file. Default is + *default-sf-srate* , which is normally 44100. + + - dur M the maximum duration in seconds to read. Default is + 10000. + + - chans M the number of channels to read. It is assumed that + samples from each channel are interleaved. Default is 1. + + - format M the header format. See s-save for details. Default is + *default-sf-format*, although this parameter is currently + ignored. + + - mode M the sample representation, e.g. PCM or float. See s-save + for details. Default is *default-sf-format*. + + - n M the number of bits per sample. See s-save for details. + Default is *default-sf-bits*. + + - flag M (T or NIL) swap byte order of each sample. Default is + NIL. + + If there is an error, for example if offset is greater than the length of + the file, then NIL is returned rather than a sound. Information about the + sound is also returned by s-read through *rslt*[Since XLISP does not + support multiple value returns, multiple value returns are simulated by + having the function assign additional return values in a list to the + global variable *rslt*. Since this is a global, it should be inspected or + copied immediately after the function return to insure that return values + are not overwritten by another function.]. The list assigned to *rslt* is + of the form: (format channels mode bits samplerate duration flags + byte-offset), which are defined as follows: + + - format M the header format. See s-save for details. + + - channels M the number of channels. + + - mode M the sample representation, e.g. PCM or float. See s-save + for details. + + - bits M the number of bits per sample. + + - samplerate M the sample rate, expressed as a FLONUM. + + - duration M the duration of the sound, in seconds. + + - flags M The values for format, channels, mode, bits, samplerate, + and duration are initially just the values passed in as + parameters or default values to s-read. If a value is actually + read from the sound file header, a flag is set. The flags are: + snd-head-format, snd-head-channels, snd-head-mode, snd-head- + bits, snd-head-srate, and snd-head-dur. For example, + + (let ((flags (caddr (cddddr *rslt*)))) + (not (zerop (logand flags snd-head-srate)))) + + tells whether the sample rate was specified in the file. See + also sf-info below. + + - byte-offset M the byte offset into the file of the first sample + to be read (this is used by the s-overwrite and s-add-to + functions). + +s-add-to(expression, maxlen, filename [, offset]) [SAL] +(s-add-to expression maxlen filename [offset]) [LISP] + Evaluates the expression, which should result in a sound or an array of + sounds, and adds the result to the given filename. The global + *default-sf-dir* applies. A FLONUM is returned, giving the maximum + absolute value of all samples written. The sample rate(s) of expression + must match those of the file. The maximum number of samples written per + channel is given by maxlen, which allows writing the initial part of a + very long or infinite sound. If offset is specified, the new sound is + added to the file beginning at an offset from the beginning (in seconds). + The file is extended if necessary to accommodate the new addition, but if + offset falls outside of the original file, the file is not modified. (If + necessary, use s-add-to to extend the file with zeros.) The file must be + a recognized sound file with a header (not a raw sound file). + +s-overwrite(expression, maxlen, filename [, offset]) [SAL] +(s-overwrite expression maxlen filename [offset]) [LISP] + Evaluates the expression, which should result in a sound or an array of + sounds, and replaces samples in the given filename. The global + *default-sf-dir* applies. A FLONUM is returned, giving the maximum + absolute value of all samples written. The sample rate(s) of expression + must match those of the file. The maximum number of samples written per + channel is given by maxlen, which allows writing the initial part of a + very long or infinite sound. If offset is specified, the new sound is + written to the file beginning at an offset from the beginning (in + seconds). The file is extended if necessary to accommodate the new insert, + but if offset falls outside of the original file, the file is not + modified. (If necessary, use s-add-to to extend the file with zeros.) The + file must be a recognized sound file with a header (not a raw sound file). + +sf-info(filename) [SAL] +(sf-info filename) [LISP] + Prints information about a sound file. The parameter filename is a string. + The file is assumed to be in *default-sf-dir* (see soundfilename below) + unless the filename begins with ``.'' or ``/''. The source for this + function is in the runtime and provides an example of how to determine + sound file parameters. + +soundfilename(name) [SAL] +(soundfilename name) [LISP] + Converts a string name to a soundfile name. If name begins with ``.'' or + ``/'', the name is returned without alteration. Otherwise, a path taken + from *default-sf-dir* is prepended to name. The s-plot, s-read, and + s-save functions all use soundfilename translate filenames. + +s-plot(sound [, dur, n]) [SAL] +(s-plot sound [dur n]) [LISP] + Plots sound in a window. This function was designed to run a plot program + on a Unix workstation, but now is primarily used with NyquistIDE, which + has self-contained plotting. Normally, time/value pairs in ascii are + written to points.dat and system-dependent code (or the NyquistIDE + program) takes it from there. If the sound is longer than the optional dur + (default is 2 seconds), only the first dur seconds are plotted. If there + are more than n samples to be plotted, the signal is interpolated to have + n samples before plotting. The data file used is *default-plot-file*: + +*default-plot-file* + The file containing the data points, defaults to "points.dat". + +s-print-tree(sound) [SAL] +(s-print-tree sound) [LISP] + Prints an ascii representation of the internal data structures + representing a sound. This is useful for debugging Nyquist. Identical to + snd-print-tree. + +7.6. Low-level Functions + Nyquist includes many low-level functions that are used to implement the +functions and behaviors described in previous sections. For completeness, these +functions are described here. Remember that these are low-level functions that +are not intended for normal use. Unless you are trying to understand the inner +workings of Nyquist, you can skip this section. + + + +7.6.1. Creating Sounds + The basic operations that create sounds are described here. + +snd-const(value, t0, srate, duration) [SAL] +(snd-const value t0 srate duration) [LISP] + Returns a sound with constant value, starting at t0 with the given + duration, at the sample rate srate. You might want to use pwl (see + Section 7.2.2.2) instead. + +snd-read(filename, offset, t0, format, channels, mode, bits, swap, sr, dur) + [SAL] +(snd-read filename offset t0 format channels mode bits swap sr dur) [LISP] + Loads a sound from a file with name filename. Files are assumed to + consist of a header followed by frames consisting of one sample from each + channel. The format specifies the type of header, but this information is + currently ignored. Nyquist looks for a number of header formats and + automatically figures out which format to read. If a header can be + identified, the header is first read from the file. Then, the file + pointer is advanced by the indicated offset (in seconds). If there is an + unrecognized header, Nyquist will assume the file has no header. If the + header size is a multiple of the frame size (bytes/sample * + number-of-channels), you can use offset to skip over the header. To skip + N bytes, use an offset of: + + (/ (float N) sr (/ bits 8) channels) + + If the header is not a multiple of the frame size, either write a header + or contact the author (dannenberg@cs.cmu.edu) for assistance. Nyquist + will round offset to the nearest sample. The resulting sound will start + at time t0. If a header is found, the file will be interpreted according + to the header information. If no header was found, channels tells how + many channels there are, the samples are encoded according to mode, the + sample length is bits, and sr is the sample rate. The swap flag is 0 or + 1, where 1 means to swap sample bytes. The duration to be read (in + seconds) is given by dur. If dur is longer than the data in the file, + then a shorter duration will be returned. If the file contains one + channel, a sound is returned. If the file contains 2 or more channels, an + array of sounds is returned. Note: you probably want to call s-read (see + Section 7.5) instead of snd-read. Also, see Section 7.5 for information + on the mode and format parameters. + +snd-save(expression, maxlen, filename, format, mode, bits, swap, play) [SAL] +(snd-save expression maxlen filename format mode bits swap play) [LISP] + Evaluates the expression, which should result in a sound or an array of + sounds, and writes the result to the given filename. If a multichannel + sound (array) is written, the channels are up-sampled to the highest rate + in any channel so that all channels have the same sample rate. The + maximum number of samples written per channel is given by maxlen, which + allows writing the initial part of a very long or infinite sound. A header + is written according to format, samples are encoded according to mode, + using bits bits/sample, and swapping bytes if swap is 1 (otherwise it + should be 0). If play is not null, the audio is played in real time (to + the extent possible) as it is computed. The peak value of the sound is + returned. In addition, the symbol *RSLT* is bound to a list containing the + sample rate, number of channels, and duration (in that order) of the saved + sound. Note: you probably want to call s-save (see Section 7.5) instead. + The format and mode parameters are described in Section 7.5. + +snd-overwrite(expression, maxlen, filename, offset, format, mode, bits, swap) + [SAL] +(snd-overwrite expression maxlen filename offset format mode bits swap) [LISP] + Evaluates the expression, which should result in a sound or an array of + sounds, and replaces samples in the given filename, writing the first + frame at a time of offset seconds. The offset must be less than or equal + to the duration of the existing file. The duration of the written samples + may be greater than that of the file, in which case the file is extended + as necessary. The sample rate(s) of expression and the number of channels + must match those of the file. If format is SND-HEAD-RAW, then the file + format is given by mode (see snd-save, bits (per channel), swap (1 means + to swap bytes and 0 means write them in the native byte order), and the + number of channels and sample rate of the sound returned by evaluating + expression. If the file is a known audio file format, format should be + SND-HEAD-NONE, and the other parameters are ignored. Up to a maximum of + maxlen samples will be written per channel. The peak value of the sound is + returned. In addition, the symbol *RSLT* is bound to a list containing + the duration of the written sound (which may not be the duration of the + sound file). Use s-add-to (in Section 7.5 or s-overwrite (in Section 7.5 + instead of this function. + +snd-coterm(s1, s2) [SAL] +(snd-coterm s1 s2) [LISP] + Returns a copy of s1, except the start time is the maximum of the start + times of s1 and s2, and the termination time is the minimum of s1 and s2. + (After the termination time, the sound is zero as if s1 is gated by s2.) + Some rationale follows: In order to implement s-add-to, we need to read + from the target sound file, add the sounds to a new sound, and overwrite + the result back into the file. We only want to write as many samples into + the file as there are samples in the new sound. However, if we are adding + in samples read from the file, the result of a snd-add in Nyquist will + have the maximum duration of either sound. Therefore, we may read to the + end of the file. What we need is a way to truncate the read, but we + cannot easily do that, because we do not know in advance how long the new + sound will be. The solution is to use snd-coterm, which will allow us to + truncate the sound that is read from the file (s1) according to the + duration of the new sound (s2). When this truncated sound is added to the + new sound, the result will have only the duration of the new sound, and + this can be used to overwrite the file. This function is used in the + implementation of s-add-to, which is defined in runtime/fileio.lsp. + +(snd-from-array ...) [SAL] +(snd-from-array ...) [LISP] + See page 17. + +snd-white(t0, sr, d) [SAL] +(snd-white t0 sr d) [LISP] + Generate white noise, starting at t0, with sample rate sr, and duration d. + You probably want to use noise (see Section 7.2.2.6). + +snd-zero(t0, srate) [SAL] +(snd-zero t0 srate) [LISP] + Creates a sound that is zero everywhere, starts at t0, and has sample rate + srate. The logical stop time is immediate, i.e. also at t0. You probably + want to use pwl (see Section 7.2.2.2) instead. + +get-slider-value(index) [SAL] +(get-slider-value index) [LISP] + Return the current value of the slider named by index (an integer index + into the array of sliders). Note that this ``slider'' is just a floating + point value in an array. Sliders can be changed by OSC messages (see + osc-enable) and by sending character sequences to Nyquist's standard + input. (Normally, these character sequences would not be typed but + generated by the NyquistIDE interactive development environment, which + runs Nyquist as a sub-process, and which present the user with graphical + sliders.) + +snd-slider(index, t0, srate, duration) [SAL] +(snd-slider index t0 srate duration) [LISP] + Create a sound controlled by the slider named by index (an integer index + into the array of sliders; see get-slider-value for more information). + The function returns a sound. Since Nyquist sounds are computed in blocks + of samples, and each block is computed at once, each block will contain + copies of the current slider value. To obtain reasonable responsiveness, + slider sounds should have high (audio) sample rates so that the block rate + will be reasonably high. Also, consider lowering the audio latency using + snd-set-latency. To ``trigger'' a Nyquist behavior using slider input, see + the trigger function in Section 7.4. + + + +7.6.2. Signal Operations + This next set of functions take sounds as arguments, operate on them, and +return a sound. + +snd-abs(sound) [SAL] +(snd-abs sound) [LISP] + Computes a new sound where each sample is the absolute value of the + corresponding sample in sound. You should probably use s-abs instead. (See + Section 7.2.2.6.) + +snd-sqrt(sound) [SAL] +(snd-sqrt sound) [LISP] + Computes a new sound where each sample is the square root of the + corresponding sample in sound. If a sample is negative, it is taken to be + zero to avoid raising a floating point error. You should probably use + s-sqrt instead. (See Section 7.2.2.6.) + +snd-add(sound1, sound) [SAL] +(snd-add sound1 sound) [LISP] + Adds two sounds. The resulting start time is the minimum of the two + parameter start times, the logical stop time is the maximum of the two + parameter stop times, and the sample rate is the maximum of the two + parameter sample rates. Use sim or sum instead of snd-add (see Section + 7.4). + +snd-offset(sound, offset) [SAL] +(snd-offset sound offset) [LISP] + Add an offset to a sound. The resulting start time, logical stop time, + stop time, and sample rate are those of sound. Use sum instead (see + Section 7.4). + +snd-avg(sound, blocksize, stepsize, operation) [SAL] +(snd-avg sound blocksize stepsize operation) [LISP] + Computes the averages or peak values of blocks of samples. Each output + sample is an average or peak of blocksize (a fixnum) adjacent samples from + the input sound. After each average or peak is taken, the input is + advanced by stepsize, a fixnum which may be greater or less than + blocksize. The output sample rate is the sound (input) sample rate + divided by stepsize. This function is useful for computing + low-sample-rate rms or peak amplitude signals for input to snd-gate or + snd-follow. To select the operation, operation should be one of + OP-AVERAGE or OP-PEAK. (These are global lisp variables; the actual + operation parameter is an integer.) For RMS computation, see rms in + Section 7.2.2.6. + +snd-clip(sound, peak) [SAL] +(snd-clip sound peak) [LISP] + Hard limit sound to the given peak, a positive number. The samples of + sound are constrained between an upper value of peak and a lower value of + N()peak. Use clip instead (see Section 7.2.2.6). + +snd-compose(f, g) [SAL] +(snd-compose f g) [LISP] + Compose two signals, i.e. compute f(g(t)), where f and g are sounds. This + function is used primarily to implement time warping, but it can be used + in other applications such as frequency modulation. For each sample x in + g, snd-compose looks up the value of f(x) using linear interpolation. The + resulting sample rate, start time, etc. are taken from g. The sound f is + used in effect as a lookup table, but it is assumed that g is + non-decreasing, so that f is accessed in time order. This allows samples + of f to be computed and discarded incrementally. If in fact g decreases, + the current sample of g is replaced by the previous one, forcing g into + compliance with the non-decreasing restriction. See also sref, shape, and + snd-resample. + +For an extended example that uses snd-compose for variable pitch shifting, see + demos/pitch_change.htm. + +snd-tapv(sound, offset, vardelay, maxdelay) [SAL] +(snd-tapv sound offset vardelay maxdelay) [LISP] + A variable delay: sound is delayed by the sum of offset (a FIXNUM or + FLONUM) and vardelay (a SOUND). The specified delay is adjusted to lie in + the range of zero to maxdelay seconds to yield the actual delay, and the + delay is implemented using linear interpolation. This function was + designed specifically for use in a chorus effect: the offset is set to + half of maxdelay, and the vardelay input is a slow sinusoid. The maximum + delay is limited to maxdelay, which determines the length of a fixed-sized + buffer. The function tapv is equivalent and preferred (see Section + 7.2.2.3). + +snd-tapf(sound, offset, vardelay, maxdelay) [SAL] +(snd-tapf sound offset vardelay maxdelay) [LISP] + A variable delay like snd-tapv except there is no linear interpolation. By + eliminating interpolation, the output is an exact copy of the input with + no filtering or distortion. On the other hand, delays jump by samples + causing samples to double or skip even when the delay is changed smoothly. + +snd-copy(sound) [SAL] +(snd-copy sound) [LISP] + Makes a copy of sound. Since operators always make (logical) copies of + their sound parameters, this function should never be needed. This + function is here for debugging. + +snd-down(srate, sound) [SAL] +(snd-down srate sound) [LISP] + Linear interpolation of samples down to the given sample rate srate, which + must be lower than the sample rate of sound. Do not call this function. + Nyquist performs sample-rate conversion automatically as needed. If you + want to force a conversion, call force-srate (see Section 7.2.2). + +snd-exp(sound) [SAL] +(snd-exp sound) [LISP] + Compute the exponential of each sample of sound. Use s-exp instead (see + Section 7.2.2.6). + +snd-follow(sound, floor, risetime, falltime, lookahead) [SAL] +(snd-follow sound floor risetime falltime lookahead) [LISP] + An envelope follower. The basic goal of this function is to generate a + smooth signal that rides on the peaks of the input signal. The usual + objective is to produce an amplitude envelope given a low-sample rate + (control rate) signal representing local RMS measurements. The first + argument is the input signal. The floor is the minimum output value. The + risetime is the time (in seconds) it takes for the output to rise + (exponentially) from floor to unity (1.0) and the falltime is the time it + takes for the output to fall (exponentially) from unity to floor. The + algorithm looks ahead for peaks and will begin to increase the output + signal according to risetime in anticipation of a peak. The amount of + anticipation (in sampless) is given by lookahead. The algorithm is as + follows: the output value is allowed to increase according to risetime or + decrease according to falltime. If the next input sample is in this range, + that sample is simply output as the next output sample. If the next input + sample is too large, the algorithm goes back in time as far as necessary + to compute an envelope that rises according to risetime to meet the new + value. The algorithm will only work backward as far as lookahead. If that + is not far enough, then there is a final forward pass computing a rising + signal from the earliest output sample. In this case, the output signal + will be at least momentarily less than the input signal and will continue + to rise exponentially until it intersects the input signal. If the input + signal falls faster than indicated by falltime, the output fall rate will + be limited by falltime, and the fall in output will stop when the output + reaches floor. This algorithm can make two passes througth the buffer on + sharply rising inputs, so it is not particularly fast. With short buffers + and low sample rates this should not matter. See snd-avg above for a + function that can help to generate a low-sample-rate input for snd-follow. + See snd-chase in Section 7.6.3 for a related filter. + +snd-gate(sound, lookahead, risetime, falltime, floor, threshold) [SAL] +(snd-gate sound lookahead risetime falltime floor threshold) [LISP] + This function generates an exponential rise and decay intended for noise + gate implementation. The decay starts when the signal drops below + threshold and stays there for longer than lookahead. Decay continues until + the value reaches floor, at which point the decay stops and the output + value is held constant. Either during the decay or after the floor is + reached, if the signal goes above threshold, then the output value will + rise to unity (1.0) at the point the signal crosses the threshold. Again, + look-ahead is used, so the rise actually starts before the signal crosses + the threshold. The rise is a constant-rate exponential and set so that a + rise from floor to unity occurs in risetime. Similarly, the fall is a + constant-rate exponential such that a fall from unity to floor takes + falltime. The result is delayed by lookahead, so the output is not + actually synchronized with the input. To compensate, you should drop the + initial lookahead of samples. Thus, snd-gate is not recommended for direct + use. Use gate instead (see Section 7.1.4). + +snd-inverse(signal, start, srate) [SAL] +(snd-inverse signal start srate) [LISP] + Compute the function inverse of signal, that is, compute g(t) such that + signal(g(t)) = t. This function assumes that signal is non-decreasing, it + uses linear interpolation, the resulting sample rate is srate, and the + result is shifted to have a starting time of start. If signal decreases, + the true inverse may be undefined, so we define snd-inverse operationally + as follows: for each output time point t, scan ahead in signal until the + value of signal exceeds t. Interpolate to find an exact time point x from + signal and output x at time t. This function is intended for internal + system use in implementing time warps. + +snd-log(sound) [SAL] +(snd-log sound) [LISP] + Compute the natural logorithm of each sample of sound. Use s-log instead + (see Section 7.2.2.6). + +peak(expression, maxlen) [SAL] +(peak expression maxlen) [LISP] + Compute the maximum absolute value of the amplitude of a sound. The sound + is created by evaluating expression (as in s-save). Only the first maxlen + samples are evaluated. The expression is automatically quoted (peak is a + macro), so do not quote this parameter. If expression is a variable, then + the global binding of that variable will be used. Also, since the + variable retains a reference to the sound, the sound will be evaluated and + left in memory. See Section 5.3 on page 10 for examples. + +snd-max(expression, maxlen) [SAL] +(snd-max expression maxlen) [LISP] + Compute the maximum absolute value of the amplitude of a sound. The sound + is created by evaluating expression (as in snd-save), which is therefore + normally quoted by the caller. At most maxlen samples are computed. The + result is the maximum of the absolute values of the samples. Notes: It is + recommended to use peak (see above) instead. If you want to find the + maximum of a sound bound to a local variable and it is acceptable to save + the samples in memory, then this is probably the function to call. + Otherwise, use peak. + +snd-maxv(sound1, sound2) [SAL] +(snd-maxv sound1 sound2) [LISP] + Compute the maximum of sound1 and sound2 on a sample-by-sample basis. The + resulting sound has its start time at the maximum of the input start times + and a logical stop at the minimum logical stop of the inputs. The physical + stop time is the minimum of the physical stop times of the two sounds. + Note that this violates the ``normal'' interpretation that sounds are zero + outside their start and stop times. For example, even if sound1 extends + beyond sound2 and is greater than zero, the result value in this extension + will be zero because it will be after the physical stop time, whereas if + we simply treated sound2 as zero in this region and took the maximum, we + would get a non-zero result. Use s-max instead (see Section 7.2.2.6). + +snd-normalize(sound) [SAL] +(snd-normalize sound) [LISP] + Internally, sounds are stored with a scale factor that applies to all + samples of the sound. All operators that take sound arguments take this + scale factor into account (although it is not always necessary to perform + an actual multiply per sample), so you should never need to call this + function. This function multiplies each sample of a sound by its scale + factor, returning a sound that represents the same signal, but whose scale + factor is 1.0. + +snd-oneshot(sound, threshold, ontime) [SAL] +(snd-oneshot sound threshold ontime) [LISP] + Computes a new sound that is zero except where sound exceeds threshold. + From these points, the result is 1.0 until sound remains below threshold + for ontime (in seconds). The result has the same sample rate, start time, + logical stop time, and duration as sound. + +snd-prod(sound1, sound2) [SAL] +(snd-prod sound1 sound2) [LISP] + Computes the product of sound1 and sound2. The resulting sound has its + start time at the maximum of the input start times and a logical stop at + the minimum logical stop of the inputs. Do not use this function. Use + mult or prod instead (see Section 7.2.2). Sample rate, start time, etc. + are taken from sound. + +snd-pwl(t0, sr, lis) [SAL] +(snd-pwl t0 sr lis) [LISP] + Computes a piece-wise linear function according to the breakpoints in lis. + The starting time is t0, and the sample rate is sr. The breakpoints are + passed in an XLISP list (of type LVAL) where the list alternates sample + numbers (FIXNUMs, computed in samples from the beginning of the pwl + function) and values (the value of the pwl function, given as a FLONUM). + There is an implicit starting point of (0, 0). The list must contain an + odd number of points, the omitted last value being implicitly zero (0). + The list is assumed to be well-formed. Do not call this function. Use + pwl instead (see Section 7.2.2.2). + +snd-quantize(sound, steps) [SAL] +(snd-quantize sound steps) [LISP] + Quantizes a sound. See Section 7.2.2.6 for details. + +snd-recip(sound) [SAL] +(snd-recip sound) [LISP] + Compute the reciprocal of each sample of sound. Use recip instead (see + Section 7.2.2.6). + +snd-resample(f, rate) [SAL] +(snd-resample f rate) [LISP] + Resample sound f using high-quality interpolation, yielding a new sound + with the specified rate. The result is scaled by 0.95 because often, in + resampling, interpolated values exceed the original sample values, and + this could lead to clipping. The resulting start time, etc. are taken + from f. Use resample instead. + +snd-resamplev(f, rate, g) [SAL] +(snd-resamplev f rate g) [LISP] + Compose two signals, i.e. compute f(g(t)), where f and g are sounds. The + result has sample rate given by rate. At each time t (according to the + rate), g is linearly interpolated to yield an increasing sequence of + high-precision score-time values. f is then interpolated at each value to + yield a result sample. If in fact g decreases, the current sample of g is + replaced by the previous one, forcing g into compliance with the + non-decreasing restriction. The result is scaled by 0.95 because often, + in resampling, interpolated values exceed the original sample values, and + this could lead to clipping. Note that if g has a high sample rate, this + may introduce unwanted jitter into sample times. See sound-warp for a + detailed discussion. See snd-compose for a fast, low-quality alternative + to this function. Normally, you should use sound-warp instead of this + function. + +snd-scale(scale, sound) [SAL] +(snd-scale scale sound) [LISP] + Scales the amplitude of sound by the factor scale. Use scale instead (see + Section 7.2.2). + +snd-shape(signal, table, origin) [SAL] +(snd-shape signal table origin) [LISP] + A waveshaping function. This is the primitive upon which shape is based. + The snd-shape function is like shape except that signal and table must be + (single-channel) sounds. Use shape instead (see Section 7.2.2.3). + +snd-up(srate, sound) [SAL] +(snd-up srate sound) [LISP] + Increases sample rate by linear interpolation. The sound is the signal to + be up-sampled, and srate is the output sample rate. Do not call this + function. Nyquist performs sample-rate conversion automatically as + needed. If you want to force a conversion, call force-srate (see Section + 7.2.2). + +snd-xform(sound, sr, time, start, stop, scale) [SAL] +(snd-xform sound sr time start stop scale) [LISP] + Makes a copy of sound and then alters it in the following order: (1) the + start time (snd-t0) of the sound is shifted to time, (1) the sound is + stretched as a result of setting the sample rate to sr (the start time is + unchanged by this), (3) the sound is clipped from start to stop, (4) if + start is greater than time, the sound is shifted shifted by time - start, + so that the start time is time, (5) the sound is scaled by scale. An + empty (zero) sound at time will be returned if all samples are clipped. + Normally, you should accomplish all this using transformations. A + transformation applied to a sound has no effect, so use cue to create a + transformable sound (see Section 7.2.1). + +snd-yin(sound, minstep, maxstep, rate) [SAL] +(snd-yin sound minstep maxstep rate) [LISP] + Identical to yin. See Section 7.2.2.6. + + + +7.6.3. Filters + These are also ``Signal Operators,'' the subject of the previous section, but +there are so many filter functions, they are documented in this special +section. + + Some filters allow time-varying filter parameters. In these functions, +filter coefficients are calculated at the sample rate of the filter parameter, +and coefficients are not interpolated. + +snd-alpass(sound, delay, feedback) [SAL] +(snd-alpass sound delay feedback) [LISP] + An all-pass filter. This produces a repeating echo effect without the + resonances of snd-delay. The feedback should be less than one to avoid + exponential amplitude blowup. Delay is rounded to the nearest sample. + You should use alpass instead (see Section 7.2.2.3). + +snd-alpasscv(sound, delay, feedback) [SAL] +(snd-alpasscv sound delay feedback) [LISP] + An all-pass filter with variable feedback. This is just like snd-alpass + except feedback is a sound. You should use alpass instead (see Section + 7.2.2.3). + +snd-alpassvv(sound, delay, feedback, maxdelay) [SAL] +(snd-alpassvv sound delay feedback maxdelay) [LISP] + An all-pass filter with variable feedback and delay. This is just like + snd-alpass except feedback and delay are sounds, and there is an + additional FLONUM parameter, maxdelay, that gives an upper bound on the + value of delay. Note: delay must remain between zero and maxdelay. If not, + results are undefined, and Nyquist may crash. You should use alpass + instead (see Section 7.2.2.3). + +snd-areson(sound, hz, bw, normalization) [SAL] +(snd-areson sound hz bw normalization) [LISP] + A notch filter modeled after the areson unit generator in Csound. The + snd-areson filter is an exact complement of snd-reson such that if both + are applied to the same signal with the same parameters, the sum of the + results yeilds the original signal. Note that because of this + complementary design, the power is not normalized as in snd-reson. See + snd-reson for details on normalization. You should use areson instead + (see Section 7.2.2.3). + +snd-aresoncv(sound, hz, bw, normalization) [SAL] +(snd-aresoncv sound hz bw normalization) [LISP] + This function is identical to snd-areson except the bw (bandwidth) + parameter is a sound. Filter coefficients are updated at the sample rate + of bw. The ``cv'' suffix stands for Constant, Variable, indicating that + hz and bw are constant (a number) and variable (a sound), respectively. + This naming convention is used throughout. You should use areson instead + (see Section 7.2.2.3). + +snd-aresonvc(sound, hz, bw, normalization) [SAL] +(snd-aresonvc sound hz bw normalization) [LISP] + This function is identical to snd-areson except the hz (center frequency) + parameter is a sound. Filter coefficients are updated at the sample rate + of hz. You should use areson instead (see Section 7.2.2.3). + +snd-aresonvv(sound, hz, bw, normalization) [SAL] +(snd-aresonvv sound hz bw normalization) [LISP] + This function is identical to snd-areson except both hz (center frequency) + and bw (bandwidth) are sounds. Filter coefficients are updated at the + next sample of either hz or bw. You should use areson instead (see + Section 7.2.2.3). + +snd-atone(sound, hz) [SAL] +(snd-atone sound hz) [LISP] + A high-pass filter modeled after the atone unit generator in Csound. The + snd-atone filter is an exact complement of snd-tone such that if both are + applied to the same signal with the same parameters, the sum of the + results yeilds the original signal. You should use hp instead (see + Section 7.2.2.3). + +snd-atonev(sound, hz) [SAL] +(snd-atonev sound hz) [LISP] + This is just like snd-atone except that the hz cutoff frequency is a + sound. Filter coefficients are updated at the sample rate of hz. You + should use hp instead (see Section 7.2.2.3). + +snd-biquad(sound, b0, b1, b2, a1, a2, z1init, z2init) [SAL] +(snd-biquad sound b0 b1 b2 a1 a2 z1init z2init) [LISP] + A general second order IIR filter, where a0 is assumed to be unity. For a1 + and a2, the sign convention is opposite to that of Matlab. All parameters + except the input sound are of type FLONUM. You should probably use one of + lowpass2, highpass2, bandpass2, notch2, allpass2, eq-lowshelf, eq- + highshelf, eq-band, lowpass4, lowpass6, lowpass8, highpass4, highpass6, or + highpass8, which are all based on snd-biquad and described in Section + 7.2.2.3. For completeness, you will also find biquad and biquad-m + described in that section. + +snd-chase(sound, risetime, falltime) [SAL] +(snd-chase sound risetime falltime) [LISP] + A slew rate limiter. The output ``chases'' the input at rates determined + by risetime and falltime. If the input changes too fast, the output will + lag behind the input. This is a form of lowpass filter, but it was created + to turn hard-switching square waves into smoother control signals that + could be used for linear crossfades. If the input switches from 0 to 1, + the output will linearly rise to 1 in risetime seconds. If the input + switches from 1 to 0, the output will linearly fall to 0 in falltime + seconds. The generated slope is constant; the transition is linear; this + is not an exponential rise or fall. The risetime and falltime must be + scalar constants; complain to the author if this is not adequate. The + snd-chase function is safe for ordinary use. See snd-follow in Section + 7.6.2 for a related function. + +snd-congen(gate, risetime, falltime) [SAL] +(snd-congen gate risetime falltime) [LISP] + A simple ``contour generator'' based on analog synthesizers. The gate is + a sound that normally steps from 0.0 to 1.0 at the start of an envelop and + goes from 1.0 back to 0.0 at the beginning of the release. At each sample, + the output converges to the input exponentially. If gate is greater than + the output, e.g. the attack, then the output converges half-way to the + output in risetime. If the gate is less than the output, the half-time is + falltime. The sample rate, starting time, logical-stop-time, and + terminate time are taken from gate. You should use congen instead (see + Section 7.2.2.3. + +snd-convolve(sound, response) [SAL] +(snd-convolve sound response) [LISP] + Convolves sound by response using a simple O(N x M) algorithm. The sound + can be any length, but the response is computed and stored in a table. The + required compuation time per sample and total space are proportional to + the length of response. Use convolve instead (see Section 7.2.2.3). + +snd-delay(sound, delay, feedback) [SAL] +(snd-delay sound delay feedback) [LISP] + Feedback delay. The output, initially sound, is recursively delayed by + delay, scaled by feedback, and added to itself, producing an repeating + echo effect. The feedback should be less than one to avoid exponential + amplitude blowup. Delay is rounded to the nearest sample. You should use + feedback-delay instead (see Section 7.2.2.3) + +snd-delaycv(sound, delay, feedback) [SAL] +(snd-delaycv sound delay feedback) [LISP] + Feedback delay with variable feedback. This is just like snd-delay except + feedback is a sound. You should use feedback-delay instead (see Section + 7.2.2.3). + +snd-reson(sound, hz, bw, normalization) [SAL] +(snd-reson sound hz bw normalization) [LISP] + A second-order resonating (bandpass) filter with center frequency hz and + bandwidth bw, modeled after the reson unit generator in Csound. The + normalization parameter must be an integer and (like in Csound) specifies + a scaling factor. A value of 1 specifies a peak amplitude response of + 1.0; all frequencies other than hz are attenuated. A value of 2 specifies + the overall RMS value of the amplitude response is 1.0; thus filtered + white noise would retain the same power. A value of zero specifies no + scaling. The result sample rate, start time, etc. are takend from sound. + You should use reson instead (see Section 7.2.2.3). + +snd-resoncv(sound, hz, bw, normalization) [SAL] +(snd-resoncv sound hz bw normalization) [LISP] + This function is identical to snd-reson except bw (bandwidth) is a sound. + Filter coefficients are updated at the sample rate of bw. You should use + reson instead (see Section 7.2.2.3). + +snd-resonvc(sound, hz, bw, normalization) [SAL] +(snd-resonvc sound hz bw normalization) [LISP] + This function is identical to snd-reson except hz (center frequency) is a + sound. Filter coefficients are updated at the sample rate of hz. You + should use reson instead (see Section 7.2.2.3). + +snd-resonvv(sound, hz, bw, normalization) [SAL] +(snd-resonvv sound hz bw normalization) [LISP] + This function is identical to snd-reson except botth hz (center frequency) + and bw (bandwidth) are sounds. Filter coefficients are updated at the + next sample from either hz or bw. You should use reson instead (see + Section 7.2.2.3). + +snd-stkchorus(sound, delay, depth, freq, mix, sr) [SAL] +(snd-stkchorus sound delay depth freq mix sr) [LISP] + A chorus implemented in STK. The parameter delay is a FIXNUM representing + the median desired delay length in samples. A typical value is 6000. The + FLONUM parameters depth and freq set the modulation depth (from 0 to 1) + and modulation frequency (in Hz), mix sets the mixture of input sound and + chorused sound, where a value of 0.0 means input sound only (dry) and a + value of 1.0 means chorused sound only (wet). The parameter sr is the + desired sample rate of the resulting sound[This is probably a mistake + since sample rate is implied by sound. This parameter may be removed in a + future release.] You should use pitshift instead (see Section 7.2.2.4). + +snd-stkpitshift(sound, shift, mix, sr) [SAL] +(snd-stkpitshift sound shift mix sr) [LISP] + A pitch shifter implemented in STK. The sound is shifted in pitch by + shift, a FLONUM representing the shift factor. A value of 1.0 means no + shift. The parameter mix sets the mixture of input and shifted sounds. A + value of 0.0 means input only (dry) and a value of 1.0 means shifted sound + only (wet). The sr is the desired sampling frequency.[This is probably a + mistake since sample rate is implied by sound. This parameter may be + removed in a future release.] You should use pitshift instead (see Section + 7.2.2.4). + +snd-stkrev(rev-type, sound, decay, mix, sr) [SAL] +(snd-stkrev rev-type sound decay mix sr) [LISP] + A reverb implemented in STK. The parameter rev-type is a FIXNUM ranging + from zero to two and selects the type of reverb. Zero selects NRev type, + one selects JCRev, and two selects PRCRev. The input sound is processed by + the reverb with a decay time in seconds (a FLONUM). The mix, a FLONUM, + sets the mixture of dry input and reverb output. A value of 0.0 means + input only (dry) and a value of 1.0 means reverb only (wet). The sample + rate is sr[This is probably a mistake since sample rate is implied by + sound. This parameter may be removed in a future release.] You should use + nrev, jcrev or prcrev instead (see Section 7.2.2.4). + +snd-tone(sound, hz) [SAL] +(snd-tone sound hz) [LISP] + A first-order recursive low-pass filter, based on the tone unit generator + of Csound. The hz parameter is the cutoff frequency, the response curve's + half-power point. The result sample rate, start time, etc. are takend + from sound. You should use lp instead (see Section 7.2.2.3). + +snd-tonev(sound, hz) [SAL] +(snd-tonev sound hz) [LISP] + This function is identical to snd-tone except hz (cutoff frequency) is a + sound. The filter coefficients are updated at the sample rate of hz. You + should use lp instead (see Section 7.2.2.3). + + + +7.6.4. Table-Lookup Oscillator Functions + These functions all use a sound to describe one period of a periodic +waveform. In the current implementation, the sound samples are copied to an +array (the waveform table) when the function is called. To make a table-lookup +oscillator generate a specific pitch, we need to have several pieces of +information: + + - A waveform to put into the table. This comes from the sound + parameter. + + - The length (in samples) of the waveform. This is obtained by reading + samples (starting at the sound's start time, not necessarily at time + zero) until the physical stop time of the sound. (If you read the + waveform from a file or generate it with functions like sim and sine, + then the physical and logical stop times will be the same and will + correspond to the duration you specified, rounded to the nearest + sample.) + + - The intrinsic sample rate of the waveform. This sample rate is + simply the sample rate property of sound. + + - The pitch of the waveform. This is supplied by the step parameter + and indicates the pitch (in steps) of sound. You might expect that + the pitch would be related to the period (length) of sound, but there + is the interesting case that synthesis based on sampling often loops + over multiple periods. This means that the fundamental frequency of + a generated tone may be some multiple of the looping rate. In + Nyquist, you always specify the perceived pitch of the looped sound + if the sound is played at the sound's own sample rate. + + - The desired pitch. This is specified by the hz parameter in Hertz + (cycles per second) in these low-level functions. Note that this is + not necessarily the ``loop'' rate at which the table is scanned. + Instead, Nyquist figures what sample rate conversion would be + necessary to ``transpose'' from the step which specifies the original + pitch of sound to hz, which gives the desired pitch. The mixed use + of steps and Hertz came about because it seemed that sample tables + would be tagged with steps (``I sampled a middle-C''), whereas + frequency deviation in the fmosc function is linear, thus calling for + a specification in Hertz. + + - The desired sample rate. This is given by the sr parameter in Hertz. + + Other parameters common to all of these oscillator functions are: + + - t0, the starting time, and + + - phase, the starting phase in degrees. Note that if the step + parameter indicates that the table holds more than one fundamental + period, then a starting phase of 360 will be different than a + starting phase of 0. + +snd-amosc(sound, step, sr, hz, t0, am, phase) [SAL] +(snd-amosc sound step sr hz t0 am phase) [LISP] + An oscillator with amplitude modulation. The sound am specifies the + amplitude and the logical stop time. The physical stop time is also that + of am. You should use amosc instead (see Section 7.2.2.1). + +snd-fmosc(s, step, sr, hz, t0, fm, phase) [SAL] +(snd-fmosc s step sr hz t0 fm phase) [LISP] + A Frequency Modulation oscillator. The sound fm specifies frequency + deviation (in Hertz) from hz. You should use fmosc instead (see Section + 7.2.2.1). + +snd-fmfb(t0, hz, sr, index, dur) [SAL] +(snd-fmfb t0 hz sr index dur) [LISP] + A Feedback FM oscillator. The resulting sound starts at t0, has a + fundamental frequency of hz, a sample rate of sr, and a duration of dur + seconds. The index is a FLONUM that specifies the amount of feedback. You + should use fmfb instead (see Section 7.2.2.1). + +snd-fmfbv(t0, hz, sr, index) +(snd-fmfv t0 hz sr index) [LISP] + A Feedback FM oscillator. The resulting sound starts at t0, has a + fundamental frequency of hz, and a sample rate of sr. The index is a SOUND + that specifies the amount of feedback and determines the duration. You + should use fmfb instead (see Section 7.2.2.1). + +snd-buzz(n, sr, hz, t0, fm) [SAL] +(snd-buzz n sr hz t0 fm) [LISP] + A buzz oscillator, which generates n harmonics of equal amplitude. The fm + specifies frequency deviation (in Hertz) from hz. You should use buzz + instead (see Section 7.2.2.1). + +snd-pluck(sr, hz, t0, d, final-amp) [SAL] +(snd-pluck sr hz t0 d final-amp) [LISP] + A Karplus-Strong plucked string oscillator with sample rate sr, + fundamental frequency hz, starting time t0, duration d, initial amplitude + approximately 1.0 (not exact because the string is initialized with random + values) and final amplitude approximately final-amp. You should use pluck + instead (see Section 7.2.2.1). + +snd-osc(s, step, sr, hz, t0, d, phase) [SAL] +(snd-osc s step sr hz t0 d phase) [LISP] + A simple table lookup oscillator with fixed frequency. The duration is d + seconds. You should use osc instead (see Section 7.2.2.1). + +snd-partial(sr, hz, t0, env) [SAL] +(snd-partial sr hz t0 env) [LISP] + This is a special case of snd-amosc that generates a sinusoid starting at + phase 0 degrees. The env parameter gives the envelope or any other + amplitude modulation. You should use partial instead (see Section + 7.2.2.1). + +snd-sine(t0, hz, sr, d) [SAL] +(snd-sine t0 hz sr d) [LISP] + This is a special case of snd-osc that always generates a sinusoid with + initial phase of 0 degrees. You should use sine instead (see Section + 7.2.2.1). + +snd-siosc(tables, sr, hz, t0, fm) [SAL] +(snd-siosc tables sr hz t0 fm) [LISP] + A Spectral Interpolation Oscillator with frequency modulation. The tables + is a list of sounds and sample counts as follows: (table0 count1 table1 + ... countN tableN). The initial waveform is given by table0, which is + interpolated linearly to table1 over the first count1 samples. From count1 + to count2 samples, the waveform is interpolated from table1 to table2, and + so on. If more than countN samples are generated, tableN is used for the + remainder of the sound. The duration and logical stop time of the sound is + taken from fm, which specified frequency modulation (deviation) in Hertz. + You should use siosc instead (see Section 7.2.2.1). + + + +7.6.5. Physical Model Functions + These functions perform some sort of physically-based modeling synthesis. + +(snd-bandedwg freq bowpress-env preset sr) +(snd-bandedwg freq bowpress-env preset sr) [LISP] + A Banded Wave Guide Percussion instrument implemented in STK. The + parameter freq is a FLONUM in Hz, bowpress-env is a SOUND that ranges from + zero to one, preset is a FIXNUM, and sr is the desired sample rate in Hz. + Currently, there are four presets: uniform-bar (0), tuned-bar (1), + glass-harmonica (2), and tibetan-bowl (3). You should use wg-uniform-bar, + wg-tuned-bar, wg-glass-harm, or wg-tibetan-bowl instead (see Section + 7.2.2.5). + +snd-bowed(freq, bowpress-env, sr) [SAL] +(snd-bowed freq bowpress-env sr) [LISP] + A bowed string instrument implemented in STK. The freq is a FLONUM in + Hertz, bowpress-env is a SOUND that ranges from z ero to one, and sr is + the desired sample rate (a FLONUM). You should use bowed instead (see + Section 7.2.2.5). + +snd-bowed-freq(freq, bowpress-env, freq-env, sr) [SAL] +(snd-bowed-freq freq bowpress-env freq-env sr) [LISP] + A bowed model just like snd-bowed but with an additional parameter for + continuous frequency control. You should use bowed-freq instead (see + Section 7.2.2.5). + +snd-clarinet(freq, breath-env, sr) [SAL] +(snd-clarinet freq breath-env sr) [LISP] + A clarinet model implemented in STK. The freq is a FLONUM in Hertz, + breath-env is a SOUND that ranges from zero to one, and sr is the desired + sample rate (a FLONUM). You should use clarinet instead (see Section + 7.2.2.5). + +snd-clarinet-freq(freq, breath-env, freq-env, sr) [SAL] +(snd-clarinet-freq freq breath-env freq-env sr) [LISP] + A clarinet model just like snd-clarinet but with an additional parameter + for continuous frequency control. You should use clarinet-freq instead + (see Section 7.2.2.5). + +snd-clarinet-all(freq, vibrato-freq, vibrato-gain, freq-env, breath-env, + reed-stiffness, noise, sr) [SAL] +(snd-clarinet-all freq vibrato-freq vibrato-gain freq-env breath-env + reed-stiffness noise sr) [LISP] + A clarinet model just like snd-clarinet-freq but with additional + parameters for vibrato generation and continuous control of reed stiffness + and breath noise. You should use clarinet-all instead (see Section + 7.2.2.5). + +snd-flute(freq, breath-env, sr) [SAL] +(snd-flute freq breath-env sr) [LISP] + A flute implemented in STK. The freq is a FLONUM in Hertz, breath-env is a + SOUND that ranges from zero to one, and sr is the desired sample rate (a + FLONUM). You should use flute instead (see Section 7.2.2.5). + +snd-flute-freq(freq, breath-env, freq-env, sr) [SAL] +(snd-flute-freq freq breath-env freq-env sr) [LISP] + A flute model just like snd-flute but with an additional parameter for + continuous frequency control. You should use flute-freq instead (see + Section 7.2.2.5). + +snd-flute-all(freq, vibrato-freq, vibrato-gain, freq-env, breath-env, + jet-delay, noise, sr) [SAL] +(snd-flute-all freq vibrato-freq vibrato-gain freq-env breath-env jet-delay + noise sr) [LISP] + A flute model just like snd-flute-freq but with additional parameters for + vibrato generation and continuous control of breath noise. You should use + flute-all instead (see Section 7.2.2.5). + +snd-mandolin(t0, freq, dur, body-size, detune, sr) [SAL] +(snd-mandolin t0 freq dur body-size detune sr) [LISP] + A plucked double-string instrument model implemented in STK. The t0 + parameter is the starting time (in seconds), freq is a FLONUM in Hz, + body-size and detune are FLONUMs, and sr is the desired sample rate. You + should use mandolin instead (see Section 7.2.2.5). + +snd-modalbar(t0, freq, preset, dur, sr) [SAL] +(snd-modalbar t0 freq preset dur sr) [LISP] + Struck bar instrument model implemented in STK. The parameter t0 is the + starting time (in seconds), freq is a FLONUM in Hz, preset is a FIXNUM + ranging from 0 to 8, dur is a FLONUM that sets the duration (in seconds) + and sr is the desired sample rate. You should use modalbar instead (see + Section 7.2.2.5). + +snd-sax(freq, breath-env, sr) [SAL] +(snd-sax freq breath-env sr) [LISP] + A sax model implemented in STK. The freq is a FLONUM in Hertz, breath-env + is a SOUND that ranges from zero to one, and sr is the desired sample rate + (a FLONUM). You should use sax instead (see Section 7.2.2.5). + +snd-sax-freq(freq, freq-env, breath-env, sr) [SAL] +(snd-sax-freq freq freq-env breath-env sr) [LISP] + A sax model just like snd-sax but with an additional parameter for + continuous frequency control. You should use sax-freq instead (see Section + 7.2.2.5). + +snd-sax-all(freq, vibrato-freq, vibrato-gain, freq-env, breath-env, + reed-stiffness, noise, blow-pos, reed-table-offset, sr) [SAL] +(snd-sax-all freq vibrato-freq vibrato-gain freq-env breath-env reed-stiffness + noise blow-pos reed-table-offset sr) [LISP] + A sax model just like snd-sax-freq but with additional parameters for + vibrato generation and continuous control of reed stiffness, breath noise, + excitation position, and reed table offset. You should use sax-all + instead (see Section 7.2.2.5). + +snd-sitar(t0, freq, dur, sr) [SAL] +(snd-sitar t0 freq dur sr) [LISP] + A sitar model implemented in STK. The parameter t0 is the starting time, + freq is a FLONUM (in Hz), E dur sets the duration and sr is the sample + rate (in Hz) of the resulting sound. You should use sitar instead (see + Section 7.2.2.5). + + + +7.6.6. Sequence Support Functions + The next two functions are used to implement Nyquist's seq construct. + +snd-seq(sound, closure) [SAL] +(snd-seq sound closure) [LISP] + This function returns sound until the logical stop time of sound. Then, + the XLISP closure is evaluated, passing it the logical stop time of sound + as a parameter. The closure must return a sound, which is then added to + sound. (An add is used so that sound can continue past its logical stop + if desired.) Do not call this function. See seq in Section 7.4. + +snd-multiseq(array, closure) [SAL] +(snd-multiseq array closure) [LISP] + This function is similar to snd-seq except the first parameter is a + multichannel sound rather than a single sound. A multichannel sound is + simply an XLISP array of sounds. An array of sounds is returned which is + the sum of array and another array of sounds returned by closure. The + closure is passed the logical stop time of the multichannel sound, which + is the maximum logical stop time of any element of array. Do not call + this function. See seq in Section 7.4. + +snd-trigger(s, closure) [SAL] +(snd-trigger s closure) [LISP] + This is one of the only ways in which a behavior instance can be created + by changes in a signal. When s (a SOUND) makes a transition from less than + or equal to zero to greater than zero, the closure, which takes a starting + time parameter, is evaluated. The closure must return a SOUND. The sum of + all these sounds is returned. If there are no sounds, the result will be + zero. The stop time of the result is the maximum stop time of s and all + sounds returned by the closure. The sample rate of the return value is the + sample rate of s, and the sounds returned by the closure must all have + that same sample rate. Do not call this function. See trigger in Section + 7.4. + +An implementation note: There is no way to have snd-trigger return a + multichannel sound. An alternative implementation would be a built-in + function to scan ahead in a sound to find the time of the next zero + crossing. This could be combined with some LISP code similar to seq to + sum up instances of the closure. However, this would force arbitrary + look-ahead and therefore would not work with real-time inputs, which was + the motivation for snd-trigger in the first place. +8. Nyquist Globals + There are many global variables in Nyquist. A convention in Lisp is to place +asterisks (*) around global variables, e.g. *table*. This is only a convention, +and the asterisks are just like any other letter as far as variable names are +concerned. Here are some globals users should know about: + +*table* Default table used by osc and other oscillators. + +*A4-Hertz* Frequency of A4 in Hertz.. Note: you must call + (set-pitch-names) to recompute pitches after changing + *A4-Hertz*. + +*autonorm* The normalization factor to be applied to the next sound + when *autonorm-type* is 'previous. See Sections 5.3 and + 7.5. + +*autonormflag* Enables the automatic normalization feature of the play + command. You should use (autonorm-on) and (autonorm-off) + rather than setting *autonormflag* directly. See Sections + 5.3 and 7.5. + +*autonorm-max-samples* + Specifies how many samples will be computed searching for a + peak value when *autonorm-type* is 'lookahead. See Sections + 5.3 and 7.5. + +*autonorm-previous-peak* + The peak of the previous sound generated by play. This is + used to compute the scale factor for the next sound when + *autonorm-type* is 'previous. See Sections 5.3 and 7.5. + +*autonorm-target* The target peak amplitude for the autonorm feature. The + default value is 0.9. See Sections 5.3 and 7.5. + +*autonorm-type* Determines how the autonorm feature is implemented. Valid + values are 'lookahead (the default) and 'previous. See + Sections 5.3 and 7.5. + +*breakenable* Controls whether XLISP enters a break loop when an error is + encountered. See Section IV.14. + +*control-srate* Part of the environment, establishes the control sample + rate. See Section 3.1 for details. + +*default-sf-bits* The default bits-per-sample for sound files. Typically 16. + +*default-sf-dir* The default sound file directory. Unless you give a full + path for a file, audio files are assumed to be in this + directory. (Applies to many functions that deal with sound + files. Check the function description to see if + *default-sf-dir* applies.) + +*default-sf-format* The default sound file format. When you write a file, this + will be the default format: AIFF for Mac and most Unix + systems, NeXT for NeXT systems, and WAV for Win32. + +*default-sf-srate* The default sample rate for sound files. Typically 44100.0, + but often set to 22050.0 for speed in non-critical tasks. + +*default-control-srate* + Default value for *control-srate*. This value is restored + when you execute (top) to pop out of a debugging session. + Change it by calling (set-control-srate value). + +*default-sound-srate* + Default value for *sound-srate*. This value is restored + when you execute (top) to pop out of a debugging session. + Change it by calling (set-sound-srate value). + +*file-separator* The character that separates directories in a path, e.g. + ``/'' for Unix, ``:'' for Mac, and ``\'' for Win32. This + is normally set in system.lsp. + +*rslt* When a function returns more than one value, *rslt* is set + to a list of the ``extra'' values. This provides a + make-shift version of the multiple-value-return facility in + Common Lisp. + +*sound-srate* Part of the environment, establishes the audio sample rate. + See Section 3.1 for details. + +*soundenable* Controls whether writes to a sound file will also be played + as audio. Set this variable by calling (sound-on) or + (sound-off). + +*tracenable* Controls whether XLISP prints a backtrace when an error is + encountered. + +XLISP variables See Section IV.14 for a list of global variables defined by + XLISP. + +Environment variables + See Section 3.1 for definitions of variables used in the + environment for behaviors. In general, you should never set + or access these variables directly. + +Various constants See Section 1.7 for definitions of predefined constants for + loudness, duration, and pitch. +9. Time/Frequency Transformation + Nyquist provides functions for FFT and inverse FFT operations on streams of +audio data. Because sounds can be of any length, but an FFT operates on a +fixed amount of data, FFT processing is typically done in short blocks or +windows that move through the audio. Thus, a stream of samples is converted in +to a sequence of FFT frames representing short-term spectra. + + Nyquist does not have a special data type corresponding to a sequence of FFT +frames. This would be nice, but it would require creating a large set of +operations suitable for processing frame sequences. Another approach, and +perhaps the most ``pure'' would be to convert a single sound into a +multichannel sound, with one channel per bin of the FFT. + + Instead, Nyquist violates its ``pure'' functional model and resorts to +objects for FFT processing. A sequence of frames is represented by an XLISP +object. Whenever you send the selector :next to the object, you get back either +NIL, indicating the end of the sequence, or you get an array of FFT +coefficients. + + The Nyquist function snd-fft (mnemonic, isn't it?) returns one of the frame +sequence generating objects. You can pass any frame sequence generating object +to another function, snd-ifft, and turn the sequence back into audio. + + With snd-fft and snd-ifft, you can create all sorts of interesting processes. +The main idea is to create intermediate objects that both accept and generate +sequences of frames. These objects can operate on the frames to implement the +desired spectral-domain processes. Examples of this can be found in the file +fft_tutorial.htm, which is part of the standard Nyquist release. The +documentation for snd-fft and snd-ifft follows. + +snd-fft(sound, length, skip, window) [SAL] +(snd-fft sound length skip window) [LISP] + This function performs an FFT on the first samples in sound and returns a + Lisp array of FLONUMs. The function modifies the sound, violating the + normal rule that sounds are immutable in Nyquist, so it is advised that + you copy the sound using snd-copy if there are any other references to + sound. The length of the FFT is specified by length, a FIXNUM (integer) + which must be a power of 2. After each FFT, the sound is advanced by skip + samples, also of type FIXNUM. Overlapping FFTs, where skip is less than + length, are allowed. If window is not NIL, it must be a sound. The first + length samples of window are multiplied by length samples of sound before + performing the FFT. When there are no more samples in sound to transform, + this function returns NIL. The coefficients in the returned array, in + order, are the DC coefficient, the first real, the first imaginary, the + second real, the second imaginary, etc. The last array element + corresponds to the real coefficient at the Nyquist frequency. + +snd-ifft(time, srate, iterator, skip, window) [SAL] +(snd-ifft time srate iterator skip window) [LISP] + This function performs an IFFT on a sequence of spectral frames obtained + from iterator and returns a sound. The start time of the sound is given by + time. Typically, this would be computed by calling (local-to-global 0). + The sample rate is given by srate. Typically, this would be *sound-srate*, + but it might also depend upon the sample rate of the sound from which the + spectral frames were derived. To obtain each frame, the function sends the + message :next to the iterator object, using XLISP's primitives for objects + and message passing. The object should return an array in the same format + as obtained from snd-fft, and the object should return NIL when the end of + the sound is reached. After each frame is inverse transformed into the + time domain, it is added to the resulting sound. Each successive frame is + added with a sample offset specified by skip relative to the previous + frame. This must be an integer greater than zero. If window is not NIL, it + must be a sound. This window signal is multiplied by the inverse + transformed frame before the frame is added to the output sound. The + length of each frame should be the same power of 2. The length is implied + by the array returned by iterator, so it does not appear as a parameter. + This length is also the number of samples used from window. Extra samples + are ignored, and window is padded with zeros if necessary, so be sure + window is the right length. The resulting sound is computed on demand as + with other Nyquist sounds, so :next messages are sent to iterator only + when new frames are needed. One should be careful not to reuse or modify + iterator once it is passed to snd-ifft. +10. MIDI, Adagio, and Sequences + Nyquist includes facilities to read and write MIDI files as well as an ASCII +text-based score representation language, Adagio. XLISP and Nyquist can be used +to generate MIDI files using compositional algorithms. (See also Section 13.) +A tutorial on using the Adadio representation and MIDI can be found in +demos/midi_tutorial.htm. The Adagio language is described below. Adagio was +originally developed as part of the CMU MIDI Toolkit, which included a program +to record and play MIDI using the Adagio representation. Some of the MIDI +features of Adagio may not be useful within Nyquist. + + Nyquist offers a number of different score representations, and you may find +this confusing. In general, MIDI files are a common way to exchange music +performance data, especially with sequencers and score notation systems. The +demos/midi_tutorial.htm examples show how to get the most precise control when +generating MIDI data. Adagio is most useful as a text-based score entry +language, and it is certainly more compact than Lisp expressions for MIDI-like +data. The Xmusic library (Chapter 13) is best for algorithmic generation of +music and score manipulation. There are functions to convert between the +Adagio, MIDI sequence data, and Xmusic score representations. + + Adagio is an easy-to-use, non-procedural notation for scores. In Adagio, +text commands are used to specify each note. If you are new to Adagio, you may +want to glance at the examples in Section 10.3 starting on page 37 before +reading any further. + + A note is described in Adagio by a set of attributes, and any attribute not +specified is ``inherited'' from the previous line. Attributes may appear in +any order and must be separated by one or more blanks. An attribute may not +contain any blanks. The attributes are: time, pitch, loudness, voice number, +duration, and articulation. + + Adagio has been used to program a variety of hardware and software +synthesizers, and the Adagio compiler can be easily adapted to new +environments. Although not originally intended for MIDI, Adagio works quite +well as a representation for MIDI scores. Adagio has been extended to allow +MIDI controller data such as modulation wheels, pitch bend, and volume, MIDI +program commands to change timbre, and System Exclusive messages. + + A note command in Adagio must be separated from other notes. Usually, notes +are distinguished by writing each one on a separate line. Notes can also be +separated by using a comma or semicolon as will be described below. + + Besides notes, there are several other types of commands: + + 1. An asterisk (*) in column one (or immediately after a comma, + semicolon, or space) indicates that the rest of the line is a + comment. The line is ignored by Adagio, and is therefore a good way + to insert text to be read by people. Here are some examples: + + * This is a comment. + T150 G4 * This is a comment too! + T150 G4 ;* So is this. + + 2. An empty command (a blank line, for example) is ignored as if it + were a comment(To be consistent, a blank line ought to specify zero + attributes and generate a note that inherits all of its attributes + from the previous one. Adagio is intentionally inconsistent in this + respect.). + + 3. An exclamation point (!) in column one (or immediately after a comma + or semicolon) indicates a special command. A special command does + not generate a note. Special commands follow the ``!'' with no + intervening spaces and extend to the end of the line, for example: + + !TEMPO 100 + + 4. Control change commands are used to control parameters like pitch + bend, modulation, and program (timbre). Control change commands can + be specified along with notes or by themselves. A command that + specifies control changes without specifying a pitch will not + produce a note. + + Adagio is insensitive to case, thus ``A'' is equivalent to ``a'', and you can +mix upper and lower case letters freely. + +10.1. Specifying Attributes + A note is indicated by a set of attributes. Attributes are indicated by a +string of characters with no intervening spaces because spaces separate +attributes. The attributes are described below. + th + The default unit of time is a centisecond (100 's), but this can be changed + th +to a millisecond (1000 's) using the !MSEC command and reset to centiseconds +with !CSEC (see Section 10.4.1). In the descriptions below, the term ``time +unit'' will be used to mean whichever convention is currently in effect. + + + +10.1.1. Time + The time attribute specifies when to start the note. A time is specified by +a ``T'' followed by a number representing time units or by a duration +(durations are described below). Examples: + + T150 ** 1.5 sec (or .15 sec) + TQ3 ** 3 quarter note's duration + +If no time is specified, the default time is the sum of the time and duration +attributes of the previous note. (But see Section 10.1.4.) Time is measured +relative to the time of the most recent Tempo or Rate command. (See the +examples in Section 10.3 for some clarification of this point.) + + + +10.1.2. Pitch + The pitch attribute specifies what frequency to produce. Standard scale +pitches are named by name, using S for sharp, F for flat, and (optionally) N +for natural. For example, C and CN represent the same pitch, as do FS and GF +(F sharp and G flat). Note that there are no bar lines, and accidentals to not +carry forward to any other notes as in common practice notation. + + Octaves are specified by number. C4 is middle C, and B3 is a half step lower. +F5 is the top line of the treble clef, etc. (Adagio octave numbering follows +the ISO standard, but note that this is not universal. In particular, Yamaha +refers to middle C as C3.) Accidentals can go before or after the octave +number, so FS3 and F3S have the same meaning. + + An alternate notation for pitch is Pn, where n is an integer representing the +pitch.Middle C (C4) is equivalent to P60, CS4 is P61, etc. + + If you do not specify an octave, Adagio will choose one for you. This is +done by picking the octave that will make the current pitch as close to the +previous pitch as possible. In the case of augmented fourths or diminished +fifths, there are two equally good choices. Adagio chooses the lower octave. + + + +10.1.3. Duration + Duration is specified by a letter indicating a number of beats, followed by +one or several modifiers. The basic duration codes are: + + W (whole, 4 beats), + H (half, 2 beats), + Q (quarter, 1 beat), + I (eighth, 1/2 beat), + S (sixteenth, 1/4 beat), + % (thirtysecond, 1/8 beat), and + ^ (sixtyfourth, 1/16 beat). + +Note that E is a pitch, so eighth-notes use the duration code I. The default +tempo is 100 beats per minute (see Section 10.1.10). These codes may be +followed by a T (triplet), indicating a duration of 2/3 the normal. A dot (.) +after a duration code extends it by half to 3/2 the normal. An integer after a +note multiplies its duration by the indicated value (the result is still just +one note). Finally, a slash followed by an integer divides the duration by the +integer. Like all attributes, duration attributes may not have embedded +spaces. Examples: + + Q 1 beat (quarter note) + QT 2/3 beat (quarter triplet) + W. 6 beats(dotted whole note) + ST6 1 beat (6 sixteenth triplets) + H5 10 beats(5 half notes) + Q3/7 3/7 beats + + th +A duration may be noted by Un, where n is an integer indicating 100 's of a + th +second (or 1000 's), see Section 10.4.1. For example, U25 is twenty-five time +units. + + Durations may be combined using a plus sign: + + Q+IT ** a quarter tied to an eighth triplet + Q/7+W+Q2/7 ** a 7th beat tied to a whole tied to 2/7th beat + Q+U10 ** a quarter plus 10 time units + + + +10.1.4. Next Time + The time of the next command (the next command in the Adagio program text) is +normally the time of the current note command plus the duration of the current +note. This can be overridden by a field consisting of the letter N followed by +a number indicating time units, or followed by a duration as described above. +The next note will then start at the time of the current note plus the duration +specified after N. If the next note has an explicit time attribute (T), then +the specified time will override the one based on the previous note. Examples: + + N0 ** start the next note at the same time as this one + N50 ** start the next note 0.5 seconds after this one + NQT ** start the next note 2/3 beat after the current one + NU10+Q ** start after 0.1 seconds plus a quarter + +A comma has an effect similar to N0 and is explained in Section 10.4.2. +Articulation effects such as staccato can be produced using N, but it is more +convenient to use the articulation attribute described in Section 10.1.6. + + + +10.1.5. Rest + Rests are obtained by including the field R in a note command. The effect of +an R field is to omit the note that would otherwise occur as the result of the +current note command. In all other respects, the command is processed just +like any other line. This means that attributes such as duration, loudness, +and pitch can be specified, and anything specified will be inherited by the +note in the next command. Normally, a rest will include just R and a duration. +The fact that a note command specifies a rest is not inherited. For example: + + R H ** a half (two beat) rest + RH ** illegal, R must be separated from H by space(s) +Because some synthesizers (e.g. a DX7) cannot change programs (presets) +rapidly, it may be desirable to change programs in a rest so that the +synthesizer will be ready to play by the end of the rest. See Section 10.1.9 +for an example. + + + +10.1.6. Articulation + Articulation in Adagio refers to the percentage of time a note is on relative +to the indicated duration. For example, to play a note staccato, you would +normally play the note about half of its indicated duration. In Adagio, +articulation is indicated by # followed by an integer number indicating a +percentage. The articulation attribute does not affect the time of the next +command. This example plays two staccato quarter notes: + + C Q #50 + D + +To produce overlapping notes, the articulation may be greater than 100. +Be aware that overlapping notes on the same pitch can be a problem for some +synthesizers. The following example illustrates this potential problem: + + !TEMPO 60 + C Q #160 * starts at time 0, ends at 1.6 sec + D I * starts at time 1, ends at 1.8 sec + C Q * starts at time 1.5, ends at 3.1 sec? + +At one beat per second (tempo 60), these three notes will start at times 0, 1, +and 1.5 seconds, respectively. Since these notes have an articulation of 160, +each will be on 160% of its nominal duration, so the first note (C) will remain +on until 1.6 seconds. But the third note (another C) will start at time 1.5 +seconds. Thus, the second C will be started before the first one ends. +Depending on the synthesizer, this may cancel the first C or play a second C in +unison. In either case, a note-off message will be sent at time 1.6 seconds. +If this cancels the second C, its actual duration will be 0.1 rather than 1.6 +seconds as intended. A final note-off will be sent at time 3.1 seconds. + + + +10.1.7. Loudness + Loudness is indicated by an L followed by a dynamic marking from the +following: PPP, PP, P, MP, MF, F, FF, FFF. Alternatively, a number from 1 to +127 may be used. The loudness attribute is the MIDI note velocity. (Note that +a MIDI velocity of 0 means ``note-off,'' so the minimum loudness is 1.) The +dynamicmarkings are translated into numbers as follows: + + Lppp 20 Lmf 58 + Lpp 26 Lf 75 + Lp 34 Lff 98 + Lmp 44 Lfff 127 + + + +10.1.8. Voice + The voice attribute tells which of the 16 MIDI channels to use for the note. +The voice attribute consists of a V followed by an integer from 1 (the default) +to 16. +There is a limit to how many notes can be played at the same time on a given +voice (MIDI channel). Since the limit depends upon the synthesizer, Adagio +cannot tell you when you exceed the limit. Similarly, Adagio cannot tell +whether your synthesizer is set up to respond to a given channel, so there is +no guarantee that what you write will actually be heard. + + + +10.1.9. Timbre (MIDI Program) + A MIDI program (synthesizer preset) can be selected using the attribute Zn, +where n is the program number (from 1 to 128). Notice that in MIDI, changing +the program on a given channel will affect all notes on that channel and +possibly others. Adagio treats MIDI program changes as a form of control +change. +For many synthesizers, you will not be able to change programs at the start of +a note or during a note. Change the program during a rest instead. For +example: + + R I Z23 V4 ** change MIDI channel 4 to program 23 during rest + A4 ** play a note on channel 4 + +Check how your synthesizer interprets program numbers. For example, the +cartridge programs on a DX7 can be accessed by adding 32 to the cartridge +program number. Cartridge program number 10 is specified by Z42. + As in MIDI, the Adagio timbre is a property of the voice (MIDI channel), so +the timbre will not be inherited by notes on a different channel; to change the +timbre on multiple voices (channels), you must explicitly notate each change. + + + +10.1.10. Tempo + The length of a beat may be changed using a Tempo command: + + !TEMPO n + +where n indicates beats per minute. The exclamation mark tells Adagio that +this is a special command line rather than a note definition. A special +command takes the place of a note specification. No other attributes should be +written on a line with a special command. The !TEMPO command is associated +with a time, computed as if the !TEMPO command were a note. The time attribute +(T) of all succeeding notes is now measured relative to the time of the !TEMPO +command. The new tempo starts at the !TEMPO command time and affects all +succeeding notes. Durations specified in time units (for example U58, N15) are +not affected by the !TEMPO command, and numerical times (for example T851) are +computed relative to the time of the last !TEMPO command. + + The !TEMPO command is fairly clever about default durations. If the last +duration specified before the !TEMPO command is symbolic (using one of ^,%, S, +I, Q, H, or W ), then the default duration for the node after the !TEMPO +command will be modified according to the tempo change. Consider the following +tempo change: + + !TEMPO 60 + A4 H + !TEMPO 120 + G + +In this example, the first note will last 2 seconds (2 beats at 60 beats per +minute). The second note inherits the duration (H) from the first note, but at +120 beats per minute, the second note will last only 1 second. If the duration +had been specified U200 (also a duration of 2 seconds), the second note would +also last 2 seconds because the !TEMPO command does not affect times or +durations specified numerically in time units. If the duration is the sum of a +symbolic and a numeric specification, the inherited duration after a !TEMPO +command is undefined. + + + +10.1.11. Rate + The !RATE command scales all times including those specified in hundredths of +seconds. A rate of 100 means no change, 200 means twice as fast, and 50 means +half as fast. For example, to make a piece play 10% faster, you can add the +following command at the beginning of the score: + + !RATE 110 + +!RATE and !TEMPO commands combine, so + + !RATE 200 + !TEMPO 70 + +will play 70 beats per minute at double the normal speed, or 140 beats per +minute. Like !TEMPO, the time of the !RATE command is added to the time +attribute of all following notes up to the next !TEMPO or !RATE command. + + Two !RATE commands do not combine, so a !RATE command only affects the rate +until the next !RATE command. + + Although !TEMPO and !RATE can occur in the middle of a note (using N, T, +etc.) they do not affect a note already specified. This property allows +multiple tempi to exist simultaneously (see Section 10.4.4). + +10.2. Default Attributes + If an attribute is omitted, the previous one is used by default (with the +exception of the time attribute). The default values for the first note, which +are inherited by succeeding notes until something else is specified, are given +below in Adagio notation: + + Time T0 + Pitch C4 + Duration Q + Articulation #100 + Loudness LFFF + Voice V1 + Tempo !TEMPO 100 + Rate !RATE 100 + +Control changes (including timbre or MIDI program, specified by Z) have no +default value and are only sent as specified in the score. + + Important: the rules for determining when a command will play a note are as +follows (and this has changed slightly from previous versions): + + 1. If a special (!) command or nothing is specified, e.g. a blank line, + do not play a note. + + 2. If R (for ``rest'') is specified, do not play a note. + + 3. Otherwise, if a pitch is specified, do play a note. + + 4. Otherwise, if no control changes (or program changes) are specified + (so this is a command with non-pitch attributes and no control + changes), do play a note. + +Another way to say this is ``Special commands and commands with rests (R) do +not play notes. Otherwise, play a note if a pitch is specified or if no +control is specified.'' + +10.3. Examples + The following plays the first two bars of ``Happy Birthday''. Note that +Adagio knows nothing of bar lines, so the fact that the first note occurs on +beat 3 or that the meter is three-four is of no consequence: + + *Example 1 ** Happy Birthday tune (C major) + !TEMPO 120 + G4 I. LF + G4 S + A4 Q + G4 + C5 + B4 H + +The time attribute for the first note is zero (0). The second note will occur +a dotted eighth later, etc. Notice that no timbre or rate was specified. +Adagio will provide reasonable default values of 1 and 100, respectively. + + The following example plays the first four bars of an exercise from Bartok's +Mikrokosmos (Vol. 1, No. 12). An extra quarter note is inserted at the +beginning of each voice in order to allow time to change MIDI programs. The +right hand part is played on voice (MIDI channel) 1 and the left hand part on +voice 2. Notice the specification of the time attribute to indicate that voice +2 starts at time 0. Also, default octaves are used to reduce typing. + + *Example 2 ** Bartok + *voice 1, right hand + R Q Z10 V1 ** extra rest for program change + A4 H + B Q + C + D H + C + D Q + C + B + A + B + C + D + R + + *voice 2, left hand + T0 R Q Z15 V2 ** extra rest for program change + G3 H + F Q + E + D H + E + D Q + E + F + G + F + E + D + R + + The next example is the same piece expressed in a different manner, +illustrating the interaction between the !TEMPO command and the time attribute. +Recall that the time attribute is measured relative to the time of the last +!TEMPO command: + + *Example 3 ** 4 measures in 2 sections + !Tempo 100 + *Voice 1, Measures 1 & 2 + R Q Z10 V1 + A4 H + B Q + C + D H + C + + *Voice 2, Measures 1 & 2 + T0 R Q Z15 V2 + G3 H + F Q + E + D H + E H + + !TEMPO 100 + *Voice 1, Measures 3 & 4 + * note that Z10 is still in effect for V1 + V1 D4 Q + C + B + A + B + C + D + R + + *Voice 2, Measures 3 & 4 + T0 V2 D3 Q + E + F + G + F + E + D + R + + The piece is written in 4 sections. The first plays a rest followed by two +measures, starting at time 0. The next section changes the time back to zero +and plays two measures of the left hand part (voice 2). The next command +(!TEMPO 100) sets the tempo to 100 (it already is) and sets the reference time +to be two measures into the piece. Therefore, the next note (D4) will begin +measure 3. The D3 that begins the last group of notes has a T0 attribute, so +it will also start at measure 3. Notice how the !TEMPO command can serve to +divide a piece into sections. + + The last example will show yet another way to express the same piece of music +using the ``Next'' attribute. Only the first bar of music is given. + + *Example 4 ** use of the Next attribute + !Tempo 100 + R Q Z10 V1 N0 + R Q Z15 V2 + + A4 H V1 N0 + G3 V2 + + B4 Q V1 N0 + F3 V2 + + C4 Q V1 N0 + E3 V2 + +Here, each pair of lines represents two simultaneous notes. The N0 attribute +forces the second line to start at the same time as the first line of each +pair. Because of the large intervals, octave numbers (3 and 4) are necessary +to override the default octave for these pitches. + +10.4. Advanced Features + Beyond the simple notation described above, Adagio supports a number of +features. (See also the next chapter.) + + + +10.4.1. Time Units and Resolution + th + The default time unit is 10ms (ten milliseconds or one centisecond or 100 + th +of a second), but it is possible to change the basic unit to 1ms, or 1000 of +a second. The time unit can be specified by: + + th + !CSEC centisecond time units = 100 + th + !MSEC millisecond time units = 1000 + +The time unit remains in effect until the next !CSEC or !MSEC command. + + + +10.4.2. Multiple Notes Per Line + Notes can be separated by commas or semicolons as well as by starting a new +line. A comma is equivalent to typing N0 and starting a new line. In other +words, the next note after a comma will start at the same time as the note +before the comma. In general, use commas to separate the notes of a chord. + + A semicolon is equivalent to starting a new line. In general, use semicolons +to group notes in a melody. Here is yet another rendition of the Bartok: + + *Example 5 ** use of semicolons + !Tempo 100 + R Q Z10 V1 + A4 H; B Q; C; D H; C; D Q; C; B; A; B; C; D; R + + T0 R Q Z15 V2 + G3 H; F Q; E; D H; E; D Q; E; F; G; F; E; D; R + +This example is similar to Example 2, except semicolons are used. Note how +semicolons make the two lines of music stand out. The next example is similar +to Example 4, except commas are used and four bars are notated. The music +below is treated as a sequence of 2-note chords, with each chord on a separate +line: + + *Example 6 ** use of commas + !Tempo 100 + R Q Z10 V1, R Q Z15 V2 + A4 H V1, G3 V2 + B4 Q V1, F3 V2 + C4 V1, E3 V2 + D4 H V1, D3 V2 + C4 V1, E3 V2 + D4 Q V1, D3 V2 + C4 V1, E3 V2 + B4 V1, F3 V2 + A4 V1, G3 V2 + B4 V1, F3 V2 + C4 V1, E3 V2 + D4 V1, D3 V2 + R + + + +10.4.3. Control Change Commands + Any control change can be specified using the syntax ``~n(v)'', where n is +the controller number (0 - 127), and v is the value. In addition, Adagio has +some special syntax for some of the commonly used control changes (note that +Pitch bend, Aftertouch, and MIDI Program Change are technically not MIDI +control changes but have their own special message format and status bytes): + + K Portamento switch + + M Modulation wheel + + O Aftertouch + + X Volume + + Y Pitch bend + Z Program Change + + +The letter listed beside each control function is the Adagio command letter. +For example, M23 is the command for setting the modulation wheel to 23. Except +for pitch bend, the portamento switch, and MIDI Program Change, all values +range from 0 to 127. Pitch bend is ``off'' or centered at 128, and has a range +from 0 to 255 (MIDI allows for more precision, but Adagio does not). Turn on +portamento with K127 and off with K0. Programs are numbered 1 to 128 to +correspond to synthesizer displays. + + About volume: Midi volume is just a control, and the Midi standard does not +say what it means. Typically it does what the volume pedal does; that is, it +scales the amplitude in a continuously changeable fashion. In contrast, Midi +velocity, which is controlled by the L (loudness) attribute, is part of a Midi +note-on command and is fixed for the duration of the note. Typically, these two +ways of controlling loudness and amplitude operate independently. In some +low-cost synthesizers the numbers seem to be added together internally and +volume changes are ignored after the note starts. + + About pitch bend: Midi pitch bend is a number from 0 to 16383, where 8192 is +the center position. To convert to Midi, Adagio simply multiplies your number +by 64, giving values from 0 to 16320. Note that Y128 translates exactly to +8192. The meaning of pitch bend depends upon your synthesizer and its setting. +Most synthesizers let you specify a ``pitch bend range.'' A range of one +semitone means that Y255 will produce a bend of approximately one semitone up, +and Y0 will bend one semitone down. If the range is 12 semitones, then the +same Y255 will bend an octave. Typically, pitch bend is exponential, so each +increment in the pitch bend value will bend an equal number of cents in pitch. + + Control changes can be part of a note specification or independent. In the +following example, a middle C is played with a modulation wheel setting of 50 +and a pitch bend of 120. Then, at 10 unit intervals, the pitch bend is +decreased by 10. The last line sets the portamento time (controller 5) to 80: + + *Example 7 + C4 LMF M50 Y120 U100 N10 + Y110 N10; Y100 N10; Y90 N10; Y80 N10 + Y70 N10; Y60 N10; Y50 N10 + ~5(80) + + See Section 10.2 on page 37 for rules on whether or not a command will play a +note. + + + +10.4.4. Multiple Tempi + Writing a piece with multiple tempi requires no new commands; you just have +to be clever in the use of Tempo and Time. The following plays a 7 note +diatonic scale on voice 1, and a 12 note chromatic scale on voice 2: + + *Example 8 ** multiple tempi + !TEMPO 70 + V1 C4; D; E; F; G; A; B + T0 R N0 + + !TEMPO 120 + V2 C4; CS; D; DS; E; F; FS; G; GS; A; AS; B + + !TEMPO 100 + V1 C5, V2 C5 + +The third line plays the 7-note diatonic scale on voice 1. The next line +contains the tricky part: notice that the time is set back to zero, there is a +rest, and a next (N) attribute is used to specify that the next default time +will be at the same time as the current one. This is tricky because a !TEMPO +command cannot have a time (T0) attribute, and a T0 by itself would create a +note with a duration. T0 R N0 says: ``go to time 0, do not play a note, and do +not advance the time before the next command''. Thus, the time of the !TEMPO +120 command is zero. After the 12 note scale, the tempo is changed to 100 and +a final note is played on each voice. A little arithmetic will show that 7 +notes at tempo 70 and 12 notes at tempo 120 each take 6 seconds, so the final +notes (C5) of each scale will happen at the same time. + + + +10.4.5. MIDI Synchronization + The Adagio program (but not Nyquist) can synchronize with external devices +using MIDI real time messages. Thus, Adagio has a !CLOCK command. This command +is currently of no use to Nyquist users but is documented here for completeness +(it's part of the language syntax even if it does not do anything). + + Since Adagio supports multiple tempi, and Midi clock is based on beats, it is +necessary to be explicit in the score about where the clock should start and +what is the duration of a quarter note. The !CLOCK command in Adagio turns on +a 24 pulse-per-quarter (PPQ) clock at the current tempo and time: + + !TEMPO 100 + !CLOCK + +A !CLOCK command must also be inserted for each tempo change that is to be +reflected in the Midi clock. Typically, each !TEMPO command will be followed +by a !CLOCK command. +Clock commands and thus tempo changes can take place at arbitrary times. It is + th +assumed that tempo changes on an exact 24 of a beat subdivision (for example, +exactly on a beat). If not, the tempo change will take place on the nearest + th +exact 24 of a beat subdivision. This may be earlier or later than the +requested time. + + + +10.4.6. System Exclusive Messages + Adagio has a definition facility that makes it possible to send system +exclusive parameters. Often, there are parameters on Midi synthesizers that +can only be controlled by system exclusive messages. Examples include the FM +ratio and LFO rate on a DX7 synthesizer. The following example defines a macro +for the DX7 LFO rate and then shows how the macro is used to set the LFO rate +for a B-flat whole note in the score. The macro definition is given in +hexadecimal, except v is replaced by the channel (voice) and %1 is replaced by +the first parameter. A macro is invoked by writing ``~'' followed by the macro +name and a list of parameters: + + !DEF LFO F0 43 0v 01 09 %1 F7 + Bf5 W ~LFO(25) + + In general, the !DEF command can define any single MIDI message including a +system exclusive message. The message must be complete (including the status +byte), and each !DEF must correspond to just one message. The symbol following +!DEF can be any name consisting of alphanumeric characters. Following the name +is a hexadecimal string (with optional spaces), all on one line. Embedded in +the string may be the following special characters: + +v Insert the 4-bit voice (MIDI channel) number. If v occurs in + the place of a high-order hexadecimal digit, replace v with 0v + so that the channel number is always placed in the low-order 4 + bits of a data byte. In other words, v is padded if necessary + to fall into the low-order bits. + +%n Insert a data byte with the low-order 7 bits of parameter + number n. Parameters are numbered 1 through 9. If the + parameter value is greater than 127, the high-order bits are + discarded. + +^n Insert a data byte with bits 7 through 13 of parameter number + n. In other words, shift the value right 7 places then clear + all but the first 7 bits. Note that 14-bit numbers can be + encoded by referencing the same parameter twice; for example, + %4^4 will insert the low-order followed by the high-order parts + of parameter 4 into two successive data bytes. + + Parameters are separated by commas, but there may be no spaces. The maximum +number of parameters allowed is 9. Here is an example of definitions to send a +full-resolution pitch bend command and to send a system exclusive command to +change a DX7 parameter[My TX816 Owner's Manual gives an incorrect format for +the change parameter sysex command (according to the manual, there is no data +in the message!) I am assuming that the data should be the last byte before +the EOX and that there is no byte count. If you are reading this, assume that +I have not tested this guess, nor have I tested this example.]. + + * Define macro for pitch bend commands: + !DEF bend Ev %1 ^1 + + A ~bend(8192) ** 8192 is "pitch bend off" + + * Change the LFO SPEED: + * SYSEX = F0, Yamaha = 43, Substatus/Channel = 1v, + * Group# = 01, Parameter# = 9, Data = 0-99, EOX = F7 + !DEF lfospeed F0 43 1v 01 09 %1 F7 + + * now use the definitions: + G4 ~bend(7567) N40 + ~lfospeed(30) N35 + + + + +10.4.7. Control Ramps + The !RAMP command can specify a smooth control change from one value to +another. It consists of a specification of the starting and ending values of +some control change, a duration specifying how often to send a new value, and a +duration specifying the total length of the ramp. + + !RAMP X10 X100 Q W2 + !RAMP ~23(10) ~23(50) U20 W + !RAMP ~lfo(15) ~lfo(35) U10 + +The first line says to ramp the volume control (controller number 7) from 10 to +100, changing at each quarter note for the duration of two whole notes. The +second line says to ramp controller number 23 from value 10 to value 50, +sending a new control change message every 20 time units. The overall duration +of the ramp should be equivalent to a whole note (W). As shown in the third +line, even system exclusive messages controlled by parameters can be specified. +If the system exclusive message has more than one parameter, only one parameter +may be ``ramped''; the others must remain the same. For example, the following +would ramp the second parameter: + + !RAMP ~mysysex(4,23,75) ~mysysex(4,100,75) U10 W + +A rather curious and extreme use of macros and ramps is illustrated in the +following example. The noteon macro starts a note, and noteoff ends it. Ramps +can now be used to emit a series of notes with changing pitches or velocities. +Since Adagio has no idea that these macros are turning on notes, it is up to +the programmer to turn them off! + + !DEF noteon 9v %1 %2 + !DEF noteoff 8v %1 %2 + ~noteon(48,125) + ~noteoff(48,126) + * turn on some notes + !RAMP ~noteon(36,125) ~noteon(60,125) Q W NW + * turn them off + !RAMP ~noteoff(60,50) ~noteoff(36,50) Q W NW + + + +10.4.8. The !End Command + The special command !END marks the end of a score. Everything beyond that is +ignored, for example: + + * this is a score + C; D; E; F; G W + !END + since the score has ended, this text will be ignored + + + +10.4.9. Calling C Routines + It is possible to call C routines from within Adagio scores when using +specially linked versions, but this feature is disabled in Nyquist. The syntax +is described here for completeness. + + The !CALL command calls a C routine that can in turn invoke a complex +sequence of operations. Below is a call to a trill routine, which is a +standard routine in Adagio. The parameters are the base pitch of the trill, +the total duration of the trill, the interval in semitones, the duration of +each note of the trill, and the loudness. Notice that both numbers and Adagio +notation can be used as parameters: + + !CALL trill(A5,W,2,S,Lmf) T278 V1 + +The parameter list should have no spaces, and parameters are separated by +commas. Following the close parenthesis, you may specify other attributes such +as the starting time and voice as shown in the example above. + + A parameter may be an Adagio pitch specification, an Adagio duration, an +Adagio loudness, a number, or an ASCII character within single quotes, e.g. 'a' +is equivalent to 97 because 97 is the decimal encoding of ``a'' in ASCII. + + The !CALL may be followed by a limited set of attributes. These are time +(T), voice (V), and next time (N). The !CALL is made at the current time if no +time is specified, and the time of the next adagio command is the time of the +!CALL unless a next time is specified. In other words, the default is N0. + + + +10.4.10. Setting C Variables + In addition to calling C routines, there is another way in which scores can +communicate with C. As with !CALL, specific C code must be linked before these +commands can be used, and this is not supported in Nyquist. The !SETI command +sets an integer variable to a value, and the !SETV command sets an element of +an integer array. For example, the next line sets the variable delay to 200 +and sets transposition[5] to -4 at time 200: + + !SETI delay 200 + !SETV transposition 5 -4 T200 + +As with the !CALL command, these commands perform their operations at +particular times according to their place in the Adagio score. This makes it +very easy to implement time-varying parameters that control various aspects of +an interactive music system. +11. Linear Prediction Analysis and Synthesis + Nyquist provides functions to perform Linear Prediction Coding (LPC) analysis +and synthesis. In simple terms, LPC analysis assumes that a sound is the result +of an all-pole filter applied to a source with a flat spectrum. LPC is good for +characterizing the general spectral shape of a signal, which may be +time-varying as in speech sounds. For synthesis, any source can be filtered, +allowing the general spectral shape of one signal (used in analysis) to be +applied to any source (used in synthesis). A popular effect is to give +vowel-like spectra to musical tones, creating an artificial (or sometimes +natural) singing voice. + + Examples of LPC analysis and synthesis can be found in the file +lpc_tutorial.htm, which is part of the standard Nyquist release. + + As with FFT processing, LPC analysis takes a sound as input and returns a +stream of frames. Frames are returned from an object using the :next selector +just as with FFT frames. An LPC frame is a list consisting of: RMS1, the +energy of the input signal, RMS2, the energy of the residual signal, ERR, the +square root of RMS1/RMS2, and FILTER-COEFS, an array of filter coefficients. To +make code more readable and to avoid code dependence on the exact format of a +frame, the functions lpc-frame-rms1, lpc-frame-rms2, lpc-frame-err, and +lpc-frame-filter-coefs can be applied to a frame to obtain the respective +fields. + + The z transform of the filter is H(z) = 1/A(z), where A(z) is a polynomial of +the form A(z) = 1 + a z + a z + ... + a z. The FILTER-COEFS array has the form + 1 2 p +#(a a ... a a a ). + p p-1 3 2 1 + The file lpc.lsp defines some useful classes and functions. The file is not +automatically loaded with Nyquist, so you must execute (load "lpc") before +using them. + +11.1. LPC Classes and Functions + +make-lpanal-iterator(sound, framedur, skiptime, npoles) [SAL] +(make-lpanal-iterator sound framedur skiptime npoles) [LISP] + Makes an iterator object, an instance of lpanal-class, that returns LPC + frames from successive frames of samples in sound. The duration (in + seconds) of each frame is given by framedur, a FLONUM. The skip size (in + seconds) between successive frames is given by skiptime, a FLONUM. Typical + values for framedur and skiptime are 0.08 and 0.04, giving 25 frames per + second and a 50% frame overlap. The number of poles is given by npoles, a + FIXNUM. The result is an object that responds to the :next selector by + returning a frame as described above. NIL is returned when sound + terminates. (Note that one or more of the last analysis windows may be + padded with zeros. NIL is only returned when the corresponding window + would begin after the termination time of the sound.) + +make-lpc-file-iterator(filename) [SAL] +(make-lpc-file-iterator filename) [LISP] + Another way to get LPC frames is to read them from a file. This function + opens an ASCII file containing LPC frames and creates an iterator object, + an instance of class lpc-file-class to access them. Create a file using + save-lpc-file (see below). + +save-lpc-file(lpc-iterator, filename) [SAL] +(save-lpc-file lpc-iterator filename) [LISP] + Create a file containing LPC frames. This file can be read by + make-lpc-file-iterator (see above). + +show-lpc-data(lpc-iterator, iniframe, endframe [, poles?]) [SAL] +(show-lpc-data lpc-iterator iniframe endframe [poles?]) [LISP] + Print values of LPC frames from an LPC iterator object. The object is + lpc-iterator, which is typically an instance of lpanal-class or + lpc-file-class. Frames are numbered from zero, and only files starting at + iniframe (a FIXNUM) and ending before endframe (also a FIXNUM) are + printed. By default, only the values for RMS1, RMS2, and ERR are printed, + but if optional parameter poles? is non-NIL, then the LPC coefficients are + also printed. + +allpoles-from-lpc(snd, lpc-frame) [SAL] +(allpoles-from-lpc snd lpc-frame) [LISP] + A single LPC frame defines a filter. Use allpoles-from-lpc to apply this + filter to snd, a SOUND. To obtain lpc-frame, a LIST containing an LPC + frame, either send :next to an LPC iterator, or use nth-frame (see below). + The result is a SOUND whose duration is the same as that of snd. + +lpreson(snd, lpc-iterator, skiptime) [SAL] +(lpreson snd lpc-iterator skiptime) [LISP] + Implements a time-varying all-pole filter controlled by a sequence of LPC + frames from an iterator. The SOUND to be filtered is snd, and the source + of LPC frames is lpc-iterator, typically an instance of lpanal-class or + lpc-file-class. The frame period (in seconds) is given by skiptime (a + FLONUM). This number does not have to agree with the skiptime used to + analyze the frames. (Greater values will cause the filter evolution slow + down, and smaller values will cause it to speed up.) The result is a + SOUND. The duration of the result is the minimum of the duration of snd + and that of the sequence of frames. + +lpc-frame-rms1(frame) [SAL] +(lpc-frame-rms1 frame) [LISP] + Get the energy of the input signal from a frame. + +lpc-frame-rms2(frame) [SAL] +(lpc-frame-rms2 frame) [LISP] + Get the energy of the residual from a frame. + +lpc-frame-err(frame) [SAL] +(lpc-frame-err frame) [LISP] + Get the square root of RMS1/RMS2 from a frame. + +lpc-frame-filter-coefs(frame) [SAL] +(lpc-frame-filter-coefs frame) [LISP] + Get the filter coefficients from a frame. + +11.2. Low-level LPC Functions + The lowest-level Nyquist functions for LPC are + + - snd-lpanal for analysis, + + - snd-allpoles, an all-pole filter with fixed coefficients, and + + - snd-lpreson, an all-pole filter that takes frames from an LPC + iterator. + +snd-lpanal(samps, npoles) [SAL] +(snd-lpanal samps npoles) [LISP] + Compute an LPC frame with npoles (a FIXNUM) poles from an ARRAY of samples + (FLONUMS). Note that snd-fetch-array can be used to fetch a sequence of + frames from a sound. Ordinarily, you should not use this function. Use + make-lpanal-iterator instead. + +snd-allpoles(snd, lpc-coefs, gain) [SAL] +(snd-allpoles snd lpc-coefs gain) [LISP] + A fixed all-pole filter. The input is snd, a SOUND. The filter + coefficients are given by lpc-coefs (an ARRAY), and the filter gain is + given by gain, a FLONUM. The result is a SOUND whose duration matches + that of snd. Ordinarily, you should use allpoles-from-lpc instead (see + above). + +snd-lpreson(snd, lpc-iterator, skiptime) [SAL] +(snd-lpreson snd lpc-iterator skiptime) [LISP] + This function is identical to lpreson (see above). +12. Developing and Debugging in Nyquist + There are a number of tools, functions, and techniques that can help to debug +Nyquist programs. Since these are described in many places throughout this +manual, this chapter brings together many suggestions and techniques for +developing code and debugging. You really should read this chapter before you +spend too much time with Nyquist. Many problems that you will certainly run +into are addressed here. + +12.1. Debugging + Probably the most important debugging tool is the backtrace. There are two +kinds of backtrace: one for SAL, and one for Lisp. + + SAL mode is actually just an XLISP function (sal) that reads input and +evaluates it. When SAL encounters an error, it normally prints a trace of the +SAL stack (all the active functions written in SAL), exists the current +command, and reads the next command. + + If you call XLISP functions from SAL, including most Nyquist sound processing +functions, and an error occurs within these XLISP functions, you will only see +the SAL function that called the XLISP functions listed in the stack trace. +Sometimes you need more details. + + When Nyquist encounters an error when it is not running SAL, it normally +suspends execution and prints an error message. To find out where in the +program the error occurred and how you got there, start by typing (bt). This +will print out the last several function calls and their arguments, which is +usually sufficient to see what is going on. + + In order for (bt) to work, you must have a couple of global variables set: +*tracenable* is ordinarily set to NIL. If it is true, then a backtrace is +automatically printed when an error occurs; *breakenable* must be set to T, as +it enables the execution to be suspended when an error is encountered. If +*breakenable* is NIL (false), then execution stops when an error occurs but the +stack is not saved and you cannot get a backtrace. Finally, bt is just a macro +to save typing. The actual backtrace function is baktrace, which takes an +integer argument telling how many levels to print. All of these things are set +up by default when you start Nyquist. + + To get this XLISP backtrace behavior when SAL encounters an error, you need +to have *breakenable* set while SAL is running. The best way to do this is to +run within the NyquistIDE program, open the Preferences dialog, and choose the +desired settings, e.g. ``Enable XLISP break on SAL error.'' + + Since Nyquist sounds are executed with a lazy evaluation scheme, some errors +are encountered when samples are being generated. In this case, it may not be +clear which expression is in error. Sometimes, it is best to explore a function +or set of functions by examining intermediate results. Any expression that +yields a sound can be assigned to a variable and examined using one or more of: +s-plot, snd-print-tree, and of course play. The snd-print-tree function prints +a lot of detail about the inner representaion of the sound. Keep in mind that +if you assign a sound to a global variable and then look at the samples (e.g. +with play or s-plot), the samples will be retained in memory. At 4 bytes per +sample, a big sound may use all of your memory and cause a crash. + + Another technique is to use low sample rates so that it is easier to plot +results or look at samples directly. The calls: + + set-sound-srate(100) + set-control-srate(100) + +set the default sample rates to 100, which is too slow for audio, but useful +for examining programs and results. The function + + snd-samples(sound, limit) + +will convert up to limit samples from sound into a Lisp array. This is another +way to look at results in detail. + + The trace function is sometimes useful. It prints the name of a function and +its arguments everytimg the function is called, and the result is printed when +the function exits. To trace the osc function, type: + + trace(osc) + +and to stop tracing, type untrace(osc). + + If a variable needs a value or a function is undefined, and if *breakenable* +was set, you will get a prompt where you can fix the error (by setting the +variable or loading the function definition) and keep going. At the debug (or +break) prompt, your input must be in XLISP, not SAL syntax. Use (co), short for +(continue) to reevaluate the variable or function and continue execution. + + When you finish debugging a particular call, you can ``pop'' up to the top +level by typing (top), a short name for (top-level). There is a button named +"Top" in the NyquistIDE that takes you back to the top level (ready to accept +XLISP expressions), and another button named "SAL" that puts you back in SAL +mode. + +12.2. Useful Functions + +grindef(name) [SAL] +(grindef name) [LISP] + Prints a formatted listing of a lisp function. This is often useful to + quickly inspect a function without searching for it in source files. Do + not forget to quote the name, e.g. (grindef 'prod). + +args(name) [SAL] +(args name) [LISP] + Similar to grindef, this function prints the arguments to a function. This + may be faster than looking up a function in the documentation if you just + need a reminder. For example, (args 'lp) prints ``(LP S C),'' which may + help you to remember that the arguments are a sound (S) followed by the + cutoff (C) frequency. + + The following functions are useful short-cuts that might have been included +in XLISP. They are so useful that they are defined as part of Nyquist. + +incf(symbol) [SAL] +(incf symbol) [LISP] + Increment symbol by one. This is a macro, and symbol can be anything that + can be set by setf. Typically, symbol is a variable: ``(incf i),'' but + symbol can also be an array element: ``(incf (aref myarray i)).'' + +decf(symbol) [SAL] +(decf symbol) [LISP] + Decrement symbol by one. (See incf, above.) + +push(val, lis) [SAL] +(push val lis) [LISP] + Push val onto lis (a Lisp list). This is a macro that is equivalent to + writing (in Lisp) (setf lis (cons val lis)). + +pop(lis) [SAL] +(pop lis) [LISP] + Remove (pop) the first item from lis (a Lisp list). This is a macro that + is equivalent to writing (in Lisp) (setf lis (cdr lis)). Note that the + remaining list is returned, not the head of the list that has been popped. + Retrieve the head of the list (i.e. the top of the stack) using first or, + equivalently, car. + + The following macros are useful control constructs. + +while(test, expr1, expr2, ...) [SAL] +(while test expr1 expr2 ...) [LISP] + A conventional ``while'' loop. If test is true, evaluate expressions + (expr1, expr2, etc.) and repeat. If test is false, return. This expression + evaluates to NIL unless the expression (return expr) is evaluated, in + which case the value of expr is returned. In SAL, the loop statement is + preferred. + +when(test, action) [SAL] +(when test action) [LISP] + A conventional ``if-then'' statement. If test is true, action is evaluated + and returned. Otherwise, NIL is returned. (Use if or cond to implement + ``if-then-else'' and more complex conditional forms. + + It is often necessary to load a file only if it has not already been loaded. +For example, the pianosyn library loads very slowly, so if some other file +already loaded it, it would be good to avoid loading it again. How can you load +a file once? Nyquist does not keep track of files that are loaded, but you must +be loading a file to define some function, so the idea is to tell Nyquist "I +require function from file"; if the function does not yet exist, Nyquist +satisfies the requirement by loading the file. + +require-from(fnsymbol, filename [, path]) [SAL] +(require-from fnsymbol filename [path]) [LISP] + Tests whether fnsymbol, an unquoted function name, is defined. If not, + filename, a STRING, is loaded. Normally fnsymbol is a function that will + be called from within the current file, and filename is the file that + defines fnsymbol. The path, if a STRING, is prepended to filename. If + path is t (true), then the directory of the current file is used as the + path. + + Sometimes it is important to load files relative to the current file. For +example, the lib/piano.lsp library loads data files from the lib/piano +directory, but how can we find out the full path of lib? The solution is: + +current-path() [SAL] +(current-path) [LISP] + Returns the full path name of the file that is currently being loaded (see + load). Returns NIL if no file is being loaded. + + Finally, there are some helpful math functions: + +real-random(from, to) [SAL] +(real-random from to) [LISP] + Returns a random FLONUM between from and to. (See also rrandom, which is + equivalent to (real-random 0 1)). + +power(x, y) [SAL] +(power x y) [LISP] + Returns x raised to the y power. +13. Xmusic and Algorithmic Composition + Several Nyquist libraries offer support for algorithmic composition. Xmusic +is a library for generating sequences and patterns of data. Included in Xmusic +is the score-gen macro which helps to generate scores from patterns. Another +important facility is the distributions.lsp library, containing many different +random number generators. + +13.1. Xmusic Basics + Xmusic is inspired by and based on Common Music by Rick Taube. Currently, +Xmusic only implements patterns and some simple support for scores to be +realized as sound by Nyquist. In contrast, Common Music supports MIDI and +various other synthesis languages and includes a graphical interface, some +visualization tools, and many other features. Common Music runs in Common Lisp +and Scheme, but not XLISP, which is the base language for Nyquist. + + Xmusic patterns are objects that generate data streams. For example, the +cycle-class of objects generate cyclical patterns such as "1 2 3 1 2 3 1 2 3 +...", or "1 2 3 4 3 2 1 2 3 4 ...". Patterns can be used to specify pitch +sequences, rhythm, loudness, and other parameters. + + Xmusic functions are automatically loaded when you start Nyquist. To use a +pattern object, you first create the pattern, e.g. + + set pitch-source = make-cycle(list(c4, d4, e4, f4)) + +After creating the pattern, you can access it repeatedly with next to generate +data, e.g. + + play seqrep(i, 13, pluck(next(pitch-source), 0.2)) + +This will create a sequence of notes with the following pitches: c, d, e, f, c, +d, e, f, c, d, e, f, c. If you evaluate this again, the pitch sequence will +continue, starting on "d". + + It is very important not to confuse the creation of a sequence with its +access. Consider this example: + + play seqrep(i, 13, + pluck(next(make-cycle(list(c4, d4, e4, f4))), 0.2)) + +This looks very much like the previous example, but it only repeats notes on +middle-C. The reason is that every time pluck is evaluated, make-cycle is +called and creates a new pattern object. After the first item of the pattern is +extracted with next, the cycle is not used again, and no other items are +generated. + + To summarize this important point, there are two steps to using a pattern. +First, the pattern is created and stored in a variable using setf. Second, the +pattern is accessed (multiple times) using next. + + Patterns can be nested, that is, you can write patterns of patterns. In +general, the next function does not return patterns. Instead, if the next item +in a pattern is a (nested) pattern, next recursively gets the next item of the +nested pattern. + + While you might expect that each call to next would advance the top-level +pattern to the next item, and descend recursively if necessary to the +inner-most nesting level, this is not how next works. Instead, next remembers +the last top-level item, and if it was a pattern, next continues to generate +items from that same inner pattern until the end of the inner pattern's period +is reached. The next paragraph explains the concept of the period. + + The data returned by a pattern object is structured into logical groups +called periods. You can get an entire period (as a list) by calling +next(pattern, t). For example: + + set pitch-source = make-cycle(list(c4, d4, e4, f4)) + print next(pitch-source, t) + +This prints the list (60 62 64 65), which is one period of the cycle. + + You can also get explicit markers that delineate periods by calling +send(pattern, :next). In this case, the value returned is either the next item +of the pattern, or the symbol +eop+ if the end of a period has been reached. +What determines a period? This is up to the specific pattern class, so see the +documentation for specifics. You can override the ``natural'' period using the +keyword for:, e.g. + + set pitch-source = make-cycle(list(c4, d4, e4, f4), for: 3) + print next(pitch-source, t) + print next(pitch-source, t) + +This prints the lists (60 62 64) (65 60 62). Notice that these periods just +restructure the stream of items into groups of 3. + + Nested patterns are probably easier to understand by example than by +specification. Here is a simple nested pattern of cycles: + + set cycle-1 = make-cycle({a b c}) + set cycle-2 = make-cycle({x y z}) + set cycle-3 = make-cycle(list(cycle-1, cycle-2)) + exec dotimes(i, 9, format(t, "~A ", next(cycle-3))) + +This will print "A B C X Y Z A B C". Notice that the inner-most cycles cycle-1 +and cycle-2 generate a period of items before the top-level cycle-3 advances to +the next pattern. + + Before describing specific pattern classes, there are several optional +parameters that apply in the creating of any pattern object. These are: + +for: The length of a period. This overrides the default by + providing a numerical length. The value of this optional + parameter may be a pattern that generates a sequence of + integers that determine the length of each successive + period. A period length may not be negative, but it may be + zero. + +name: A pattern object may be given a name. This is useful if the + trace: option is used. + +trace: If non-null, this optional parameter causes information + about the pattern to be printed each time an item is + generated from the pattern. + + The built-in pattern classes are described in the following section. + +13.2. Pattern Classes + + + +13.2.1. cycle + The cycle-class iterates repeatedly through a list of items. For example, +two periods of make-cycle({a b c}) would be (A B C) (A B C). + +make-cycle(items, for: for, name: name, trace: trace) [SAL] +(make-cycle items :for for :name name :trace trace) [LISP] + Make a cycle pattern that iterates over items. The default period length + is the length of items. (See above for a description of the optional + parameters.) If items is a pattern, a period of the pattern becomes the + list from which items are generated. The list is replaced every period of + the cycle. + + + +13.2.2. line + The line-class is similar to the cycle class, but when it reaches the end of +the list of items, it simply repeats the last item in the list. For example, +two periods of make-line({a b c}) would be (A B C) (C C C). + +make-line(items, for: for, name: name, trace: trace) [SAL] +(make-line items :for for :name name :trace trace) [LISP] + Make a line pattern that iterates over items. The default period length is + the length of items. As with make-cycle, items may be a pattern. (See + above for a description of the optional parameters.) + + + +13.2.3. random + The random-class generates items at random from a list. The default selection +is uniform random with replacement, but items may be further specified with a +weight, a minimum repetition count, and a maximum repetition count. Weights +give the relative probability of the selection of the item (with a default +weight of one). The minimum count specifies how many times an item, once +selected at random, will be repeated. The maximum count specifies the maximum +number of times an item can be selected in a row. If an item has been +generated n times in succession, and the maximum is equal to n, then the item +is disqualified in the next random selection. Weights (but not currently +minima and maxima) can be patterns. The patterns (thus the weights) are +recomputed every period. + +make-random(items, for: for, name: name, trace: trace) [SAL] +(make-random items :for for :name name :trace trace) [LISP] + Make a random pattern that selects from items. Any (or all) element(s) of + items may be lists of the following form: (value :weight weight :min + mincount :max maxcount), where value is the item (or pattern) to be + generated, weight is the (optional) relative probability of selecting this + item, mincount is the (optional) minimum number of repetitions when this + item is selected, and maxcount is the (optional) maximum number of + repetitions allowed before selecting some other item. The default period + length is the length of items. If items is a pattern, a period from that + pattern becomes the list from which random selections are made, and a new + list is generated every period. + + + +13.2.4. palindrome + The palindrome-class repeatedly traverses a list forwards and then backwards. +For example, two periods of make-palindrome({a b c}) would be (A B C C B A) (A +B C C B A). The elide: keyword parameter controls whether the first and/or +last elements are repeated: + + make-palindrome({a b c}, elide: nil) + ;; generates A B C C B A A B C C B A ... + + make-palindrome({a b c}, elide: t) + ;; generates A B C B A B C B ... + + make-palindrome({a b c}, elide: :first) + ;; generates A B C C B A B C C B ... + + make-palindrome({a b c}, elide: :last) + ;; generates A B C B A A B C B A ... + +make-palindrome(items, elide: elide, for: for, name: name, trace: trace) [SAL] +(make-palindrome items :elide elide :for for :name name :trace trace) [LISP] + Generate items from list alternating in-order and reverse-order + sequencing. The keyword parameter elide can have the values :first, :last, + t, or nil to control repetition of the first and last elements. The elide + parameter can also be a pattern, in which case it is evaluated every + period. One period is one complete forward and backward traversal of the + list. If items is a pattern, a period from that pattern becomes the list + from which random selections are made, and a new list is generated every + period. + + + +13.2.5. heap + The heap-class selects items in random order from a list without replacement, +which means that all items are generated once before any item is repeated. For +example, two periods of make-heap({a b c}) might be (C A B) (B A C). Normally, +repetitions can occur even if all list elements are distinct. This happens when +the last element of a period is chosen first in the next period. To avoid +repetitions, the max: keyword argument can be set to 1. The max: keyword only +controls repetitions from the end of one period to the beginning of the next. +If the list contains more than one copy of the same value, it may be repeated +within a period regardless of the value of max:. + +make-heap(items, for: for, max: max, name: name, trace: trace) [SAL] +(make-heap items :for for :max max :name name :trace trace) [LISP] + Generate items randomly from list without replacement. If max is 1, the + first element of a new period will not be the same as the last element of + the previous period, avoiding repetition. The default value of max is 2, + meaning repetition is allowed. The period length is the length of items. + If items is a pattern, a period from that pattern becomes the list from + which random selections are made, and a new list is generated every + period. + + + +13.2.6. accumulation + The accumulation-class takes a list of values and returns the first, followed +by the first two, followed by the first three, etc. In other words, for each +list item, return all items from the first through the item. For example, if +the list is (A B C), each generated period is (A A B A B C). + +make-accumulation(items, name: name, trace: trace) [SAL] +(make-accumulation items :name name :trace trace) [LISP] + For each item, generate items from the first to the item including the + 2 + item. The period length is (n + n) / 2 where n is the length of items. + If items is a pattern, a period from that pattern becomes the list from + which items are generated, and a new list is generated every period. Note + that this is similar in name but different from make-accumulate. + + + +13.2.7. copier +The copier-class makes copies of periods from a sub-pattern. For example, + three periods of make-copier(make-cycle({a b c}, for: 1), repeat: 2, + merge: t) would be (A A) (B B) (C C). Note that entire periods (not + individual items) are repeated, so in this example the for: keyword was + used to force periods to be of length one so that each item is repeated by + the repeat: count. + +make-copier(sub-pattern, repeat: repeat, merge: merge, for: for, name: name, + trace: trace) [SAL] +(make-copier sub-pattern :repeat repeat :merge merge :for for :name name :trace + trace) [LISP] + Generate a period from sub-pattern and repeat it repeat times. If merge is + false (the default), each repetition of a period from sub-pattern results + in a period by default. If merge is true (non-null), then all repeat + repetitions of the period are merged into one result period by default. If + the for: keyword is used, the same items are generated, but the items are + grouped into periods determined by the for: parameter. If the for: + parameter is a pattern, it is evaluated every result period. The repeat + and merge values may be patterns that return a repeat count and a boolean + value, respectively. If so, these patterns are evaluated initially and + after each repeat copies are made (independent of the for: keyword + parameter, if any). The repeat value returned by a pattern can also be + negative. A negative number indicates how many periods of sub-pattern to + skip. After skipping these patterns, new repeat and merge values are + generated. + + + +13.2.8. accumulate + The accumulate-class forms the sum of numbers returned by another pattern. +For example, each period of make-accumulate(make-cycle({1 2 -3})) is (1 3 0). +The default output period length is the length of the input period. + +make-accumulate(sub-pattern, for: for, max: maximum, min: minimum, name: name, + trace: trace) [SAL] +(make-accumulate sub-pattern :for for :max maximum :min minimum :name name + :trace trace) [LISP] + Keep a running sum of numbers generated by sub-pattern. The default period + lengths match the period lengths from sub-pattern. If maximum (a pattern + or a number) is specified, and the running sum exceeds maximum, the + running sum is reset to maximum. If minimum (a pattern or a number) is + specified, and the running sum falls below minimum, the running sum is + reset to minimum. If minimum is greater than maximum, the running sum will + be set to one of the two values. Note that this is similar in name but not + in function to make-accumulation. + + + +13.2.9. sum + The sum-class forms the sum of numbers, one from each of two other patterns. +For example, each period of make-sum(make-cycle({1 2 3}), make-cycle({4 5 6})) +is (5 7 9). The default output period length is the length of the input period +of the first argument. Therefore, the first argument must be a pattern, but the +second argument can be a pattern or a number. + +make-sum(x, y, for: for, name: name, trace: trace) [SAL] +(make-sum x y :for for :name name :trace trace) [LISP] + Form sums of items (which must be numbers) from pattern x and pattern or + number y. The default period lengths match the period lengths from x. + + + +13.2.10. product + The product-class forms the product of numbers, one from each of two other +patterns. For example, each period of make-product(make-cycle({1 2 3}), +make-cycle({4 5 6})) is (4 10 18). The default output period length is the +length of the input period of the first argument. Therefore, the first argument +must be a pattern, but the second argument can be a pattern or a number. + +make-product(x, y, for: for, name: name, trace: trace) [SAL] +(make-product x y :for for :name name :trace trace) [LISP] + Form products of items (which must be numbers) from pattern x and pattern + or number y. The default period lengths match the period lengths from x. + + + +13.2.11. eval + The eval-class evaluates an expression to produce each output item. The +default output period length is 1. + +make-eval(expr, for: for, name: name, trace: trace) [SAL] +(make-eval expr :for for :name name :trace trace) [LISP] + Evaluate expr to generate each item. If expr is a pattern, each item is + generated by getting the next item from expr and evaluating it. + + + +13.2.12. length + The length-class generates periods of a specified length from another +pattern. This is similar to using the for: keyword, but for many patterns, the +for: parameter alters the points at which other patterns are generated. For +example, if the palindrome pattern has an elide: pattern parameter, the value +will be computed every period. If there is also a for: parameter with a value +of 2, then elide: will be recomputed every 2 items. In contrast, if the +palindrome (without a for: parameter) is embedded in a length pattern with a +lenght of 2, then the periods will all be of length 2, but the items will come +from default periods of the palindrome, and therefore the elide: values will be +recomputed at the beginnings of default palindrome periods. + +make-length(pattern, length-pattern, name: name, trace: trace) [SAL] +(make-length pattern length-pattern :name name :trace trace) [LISP] + Make a pattern of class length-class that regroups items generated by a + pattern according to pattern lengths given by length-pattern. Note that + length-pattern is not optional: There is no default pattern length and no + for: keyword. + + + +13.2.13. window + The window-class groups items from another pattern by using a sliding window. +If the skip value is 1, each output period is formed by dropping the first item +of the previous perioda and appending the next item from the pattern. The skip +value and the output period length can change every period. For a simple +example, if the period length is 3 and the skip value is 1, and the input +pattern generates the sequence A, B, C, ..., then the output periods will be (A +B C), (B C D), (C D E), (D E F), .... + +make-window(pattern, length-pattern, skip-pattern, name: name, trace: trace) + [SAL] +(make-window pattern length-pattern skip-pattern :name name :trace trace) + [LISP] + Make a pattern of class window-class that regroups items generated by a + pattern according to pattern lengths given by length-pattern and where the + period advances by the number of items given by skip-pattern. Note that + length-pattern is not optional: There is no default pattern length and no + for: keyword. + + + +13.2.14. markov + The markov-class generates items from a Markov model. A Markov model +generates a sequence of states according to rules which specify possible future +states given the most recent states in the past. For example, states might be +pitches, and each pitch might lead to a choice of pitches for the next state. +In the markov-class, states can be either symbols or numbers, but not arbitrary +values or patterns. This makes it easier to specify rules. However, symbols +can be mapped to arbitrary values including pattern objects, and these become +the actual generated items. By default, all future states are weighted +equally, but weights may be associated with future states. A Markov model must +be initialized with a sequence of past states using the past: keyword. The +most common form of Markov model is a "first order Markov model" in which the +future item depends only upon one past item. However, higher order models where +the future items depend on two or more past items are possible. A "zero-order" +Markov model, which depends on no past states, is essentially equivalent to the +random pattern. As an example of a first-order Markov pattern, two periods of +make-markov({{a -> b c} {b -> c} {c -> a}}, past: {a}) might be (C A C) (A B +C). + +make-markov(rules, past: past, produces: produces, for: for, name: name, trace: + trace) [SAL] +(make-markov rules past :produces produces :for for :name name :trace trace) + [LISP] + Generate a sequence of items from a Markov process. The rules parameter + has the form: (prev1 prev2 ... prevn -> next1 next2 ... nextn) where + prev1 through prevn represent a sequence of most recent (past) states. The + symbol * is treated specially: it matches any previous state. If prev1 + through prevn (which may be just one state as in the example above) match + the previously generated states, this rule applies. Note that every rule + must specify the same number of previous states; this number is known as + the order of the Markov model. The first rule in rules that applies is + used to select the next state. If no rule applies, the next state is NIL + (which is a valid state that can be used in rules). Assuming a rule + applies, the list of possible next states is specified by next1 through + nextn. Notice that these are alternative choices for the next state, not a + sequence of future states, and each rule can have any number of choices. + Each choice may be the state itself (a symbol or a number), or the choice + may be a list consisting of the state and a weight. The weight may be + given by a pattern, in which case the next item of the pattern is obtained + every time the rule is applied. For example, this rules says that if the + previous states were A and B, the next state can be A with a weight of 0.5 + or C with an implied weight of 1: (A B -> (A 0.5) C). The default length + of the period is the length of rules. The past parameter must be provided. + It is a list of states whose length matches the order of the Markov model. + The keyword parameter produces may be used to map from state symbols or + numbers to other values or patterns. The parameter is a list of + alternating symbols and values. For example, to map A to 69 and B to 71, + use list(quote(a), 69, quote(b), 71). You can also map symbols to + patterns, for example list(quote(a), make-cycle({57 69}), quote(b), + make-random({59 71})). The next item of the pattern is is generated each + time the Markov model generates the corresponding state. Finally, the + produces keyword can be eval:, which means to evaluate the Markov model + state. This could be useful if states are Nyquist global variables such as + C4, CS4, D4, ]..., which evaluate to numerical values (60, 61, 62, .... + +markov-create-rules(sequence, order [, generalize]) [SAL] +(markov-create-rules sequence order [generalize]) [LISP] + Generate a set of rules suitable for the make-markov function. The + sequence is a ``typical'' sequence of states, and order is the order of + the Markov model. It is often the case that a sample sequence will not + have a transition from the last state to any other state, so the generated + Markov model can reach a ``dead end'' where no rule applies. This might + lead to an infinite stream of NIL's. To avoid this, the optional parameter + generalize can be set to t (true), indicating that there should be a + fallback rule that matches any previous states and whose future states are + weighted according to their frequency in sequence. For example, if + sequence contains 5 A's, 5 B's and 10 G's, the default rule will be (* -> + (A 5) (B 5) (G 10)). This rule will be appended to the end so it will only + apply if no other rule does. + +13.3. Random Number Generators + The distributions.lsp library implements random number generators that return +random values with various probability distributions. Without this library, you +can generate random numbers with uniform distributions. In a uniform +distribution, all values are equally likely. To generate a random integer in +some range, use random. To generate a real number (FLONUM) in some range, use +real-random (or rrandom if the range is 0-1). But there are other interesting +distributions. For example, the Gaussian distribution is often used to model +real-world errors and fluctuations where values are clustered around some +central value and large deviations are more unlikely than small ones. See +Dennis Lorrain, "A Panoply of Stochastic 'Canons'," Computer Music Journal vol. +4, no. 1, 1980, pp. 53-81. + + In most of the random number generators described below, there are optional +parameters to indicate a maximum and/or minimum value. These can be used to +truncate the distribution. For example, if you basically want a Gaussian +distribution, but you never want a value greater than 5, you can specify 5 as +the maximum value. The upper and lower bounds are implemented simply by +drawing a random number from the full distribution repeatedly until a number +falling into the desired range is obtained. Therefore, if you select an +acceptable range that is unlikely, it may take Nyquist a long time to find each +acceptable random number. The intended use of the upper and lower bounds is to +weed out values that are already fairly unlikely. + +linear-dist(g) [SAL] +(linear-dist g) [LISP] + Return a FLONUM value from a linear distribution, where the probability of + a value decreases linearly from zero to g which must be greater than zero. + (See Figure 7.) The linear distribution is useful for generating for + generating time and pitch intervals. + + + + + + + + + + + + + + + + + + + Figure 7: The Linear Distribution, g = 1. + + +exponential-dist(delta [, high]) [SAL] +(exponential-dist delta [high]) [LISP] + Return a FLONUM value from an exponential distribution. The initial + downward slope is steeper with larger values of delta, which must be + greater than zero. (See Figure 8. The optional high parameter puts an + artificial upper bound on the return value. The exponential distribution + generates values greater than 0, and can be used to generate time + intervals. Natural random intervals such as the time intervals between the + release of atomic particles or the passing of yellow volkswagons in + traffic have exponential distributions. The exponential distribution is + memory-less: knowing that a random number from this distribution is + greater than some value (e.g. a note duration is at least 1 second) tells + you nothing new about how soon the note will end. This is a continuous + distribution, but geometric-dist (described below) implements the discrete + form. + + + + + + + + + + + + + + + + + + + Figure 8: The Exponential Distribution, delta = 1. + + +gamma-dist(nu [, high]) [SAL] +(gamma-dist nu [high]) [LISP] + Return a FLONUM value from a Gamma distribution. The value is greater than + zero, has a mean of nu (a FIXNUM greater than zero), and a mode (peak) of + around nu - 1. The optional high parameter puts an artificial upper bound + on the return value. + + + + + + + + + + + + + + + + + + + Figure 9: The Gamma Distribution, nu = 4. + + +bilateral-exponential-dist(xmu, tau [, low, high]) [SAL] +(bilateral-exponential-dist xmu tau [low high]) [LISP] + Returns a FLONUM value from a bilateral exponential distribution, where + xmu is the center of the double exponential and tau controls the spread of + the distribution. A larger tau gives a wider distribution (greater + variance), and tau must be greater than zero. The low and high parameters + give optional artificial bounds on the minimum and maximum output values, + respectively. This distribution is similar to the exponential, except it + is centered at 0 and can output negative values as well. Like the + exponential, it can be used to generate time intervals; however, it might + be necessary to add a lower bound so as not to compute a negative time + interval. + + + + + + + + + + + + + + + + + + + Figure 10: The Bilateral Exponential Distribution. + + +cauchy-dist(tau [, low, high]) [SAL] +(cauchy-dist tau [low high]) [LISP] + Returns a FLONUM from the Cauchy distribution, a symetric distribution + with a high peak at zero and a width (variance) that increases with + parameter tau, which must be greater than zero. The low and high + parameters give optional artificial bounds on the minimum and maximum + output values, respectively. + + + + + + + + + + + + + + + + + + + Figure 11: The Cauchy Distribution, tau = 1. + + +hyperbolic-cosine-dist([low, high]) [SAL] +(hyperbolic-cosine-dist [low high)] [LISP] + Returns a FLONUM value from the hyperbolic cosine distribution, a symetric + distribution with its peak at zero. The low and high parameters give + optional artificial bounds on the minimum and maximum output values, + respectively. + + + + + + + + + + + + + + + + + + + Figure 12: The Hyperbolic Cosine Distribution. + + +logistic-dist(alpha, beta [, low, high]) [SAL] +(logistic-dist alpha beta [low high]) [LISP] + Returns a FLONUM value from the logistic distribution, which is symetric + about the mean. The alpha parameter primarily affects dispersion + (variance), with larger values resulting in values closer to the mean + (less variance), and the beta parameter primarily influences the mean. The + low and high parameters give optional artificial bounds on the minimum and + maximum output values, respectively. + + + + + + + + + + + + + + + + + + + Figure 13: The Logistic Distribution, alpha = 1, beta = 2. + + +arc-sine-dist() [SAL] +(arc-sine-dist) [LISP] + Returns a FLONUM value from the arc sine distribution, which outputs + values between 0 and 1. It is symetric about the mean of 1/2, but is more + likely to generate values closer to 0 and 1. + + + + + + + + + + + + + + + + + + + Figure 14: The Arc Sine Distribution. + + +gaussian-dist(xmu, sigma [, low, high]) [SAL] +(gaussian-dist xmu sigma [low high]) [LISP] + Returns a FLONUM value from the Gaussian or Gauss-Laplace distribution, a + linear function of the normal distribution. It is symetric about the mean + of xmu, with a standard deviation of sigma, which must be greater than + zero. The low and high parameters give optional artificial bounds on the + minimum and maximum output values, respectively. + + + + + + + + + + + + + + + + + + + Figure 15: The Gauss-Laplace (Gaussian) Distribution, xmu = 0, sigma + = 1. + + +beta-dist(a, b) [SAL] +(beta-dist a b) [LISP] + Returns a FLONUM value from the Beta distribution. This distribution + outputs values between 0 and 1, with outputs more likely to be close to 0 + or 1. The parameter a controls the height (probability) of the right side + of the distribution (at 1) and b controls the height of the left side (at + 0). The distribution is symetric about 1/2 when a = b. + + + + + + + + + + + + + + + + + + + Figure 16: The Beta Distribution, alpha = .5, beta = .25. + + +bernoulli-dist(px1 [, x1, x2]) [SAL] +(bernoulli-dist px1 [x1 x2]) [LISP] + Returns either x1 (default value is 1) with probability px1 or x2 (default + value is 0) with probability 1 - px1. The value of px1 should be between 0 + and 1. By convention, a result of x1 is viewed as a success while x2 is + viewed as a failure. + + + + + + + + + + + + + + + + + + + + + + + + + Figure 17: The Bernoulli Distribution, px1 = .75. + + +binomial-dist(n, p) [SAL] +(binomial-dist n p) [LISP] + Returns a FIXNUM value from the binomial distribution, where n is the + number of Bernoulli trials run (a FIXNUM) and p is the probability of + success in the Bernoulli trial (a FLONUM from 0 to 1). The mean is the + product of n and p. + + + + + + + + + + + + + + + + + + + + + + + + + Figure 18: The Binomial Distribution, n = 5, p = .5. + + +geometric-dist(p) [SAL] +(geometric-dist p) [LISP] + Returns a FIXNUM value from the geometric distribution, which is defined + as the number of failures before a success is achieved in a Bernoulli + trial with probability of success p (a FLONUM from 0 to 1). + + + + + + + + + + + + + + + + + + + + + + + + + Figure 19: The Geometric Distribution, p = .4. + + +poisson-dist(delta) [SAL] +(poisson-dist delta) [LISP] + Returns a FIXNUM value from the Poisson distribution with a mean of delta + (a FIXNUM). The Poisson distribution is often used to generate a sequence + of time intervals, resulting in random but often pleasing rhythms. + + + + + + + + + + + + + + + + + + + + + + + + + Figure 20: The Poisson Distribution, delta = 3. + + +13.4. Score Generation and Manipulation + A common application of pattern generators is to specify parameters for +notes. (It should be understood that ``notes'' in this context means any +Nyquist behavior, whether it represents a conventional note, an abstract sound +object, or even some micro-sound event that is just a low-level component of a +hierarchical sound organization. Similarly, ``score'' should be taken to mean a +specification for a sequence of these ``notes.'') The score-gen macro (defined +by loading xm.lsp) establishes a convention for representing scores and for +generating them using patterns. + + The timed-seq macro, described in Section 7.4, already provides a way to +represent a ``score'' as a list of expressions. The Xmusic representation goes +a bit further by specifying that all notes are specified by an alternation of +keywords and values, where some keywords have specific meanings and +interpretations. + + The basic idea of score-gen is you provide a template for notes in a score as +a set of keywords and values. For example, + + set pitch-pattern = make-cycle(list(c4, d4, e4, f4)) + score-gen(dur: 0.4, name: quote(my-sound), + pitch: next(pitch-pattern), score-len: 9) + +generates a score of 9 notes as follows: + + ((0 0 (SCORE-BEGIN-END 0 3.6)) + (0 0.4 (MY-SOUND :PITCH 60)) + (0.4 0.4 (MY-SOUND :PITCH 62)) + (0.8 0.4 (MY-SOUND :PITCH 64)) + (1.2 0.4 (MY-SOUND :PITCH 65)) + (1.6 0.4 (MY-SOUND :PITCH 60)) + (2 0.4 (MY-SOUND :PITCH 62)) + (2.4 0.4 (MY-SOUND :PITCH 64)) + (2.8 0.4 (MY-SOUND :PITCH 65)) + (3.2 0.4 (MY-SOUND :PITCH 60))) + +The use of keywords like :PITCH helps to make scores readable and easy to +process without specific knowledge of about the functions called in the score. +For example, one could write a transpose operation to transform all the :pitch +parameters in a score without having to know that pitch is the first parameter +of pluck and the second parameter of piano-note. Keyword parameters are also +used to give flexibility to note specification with score-gen. Since this +approach requires the use of keywords, the next section is a brief explanation +of how to define functions that use keyword parameters. + + + +13.4.1. Keyword Parameters + Keyword parameters are parameters whose presence is indicated by a special +symbol, called a keyword, followed by the actual parameter. Keyword parameters +in SAL have default values that are used if no actual parameter is provided by +the caller of the function. (See Appendix IV to learn about keywords in XLISP.) + + To specify that a parameter is a keyword parameter, use a keyword symbol (one +that ends in a colon) followed by a default value. For example, here is a +function that accepts keyword parameters and invokes the pluck function: + + define function k-pluck(pitch: 60, dur: 1) + return pluck(pitch, dur) + +Now, we can call k-pluck with keyword parameters. The keywords are simply the +formal parameter names with a prepended colon character (:pitch and :dur in +this example), so a function call would look like: + + pluck(pitch: c3, dur: 3) + +Usually, it is best to give keyword parameters useful default values. That way, +if a parameter such as dur: is missing, a reasonable default value (1) can be +used automatically. It is never an error to omit a keyword parameter, but the +called function can check to see if a keyword parameter was supplied or not. +Because of default values, we can call k-pluck(pitch: c3) with no duration, +k-pluck(dur: 3) with only a duration, or even k-pluck() with no parameters. + + In XLISP, there is additional syntax to specify an alternate symbol to be +used as the keyword and to allow the called function to determine whether or +not a keyword parameter was supplied, but these features are little-used. See +the XLISP manual for details. + + + +13.4.2. Using score-gen + The score-gen macro computes a score based on keyword parameters. Some +keywords have a special meaning, while others are not interpreted but merely +placed in the score. The resulting score can be synthesized using timed-seq +(see Section 7.4). + + The form of a call to score-gen is simply: + +score-gen(k1: e1, k2: e2, ...) [SAL] +(score-gen :k1 e1 :k2 e2 ...) [LISP] + where the k's are keywords and the e's are expressions. A score is + generated by evaluating the expressions once for each note and + constructing a list of keyword-value pairs. A number of keywords have + special interpretations. The rules for interpreting these parameters will + be explained through a set of "How do I ..." questions below. + + How many notes will be generated? The keyword parameter score-len: specifies +an upper bound on the number of notes. (Note: in LISP syntax, keywords are +always preceded by colons, so you would write :score-len instead.) The keyword +score-dur: specifies an upper bound on the starting time of the last note in +the score. (To be more precise, the score-dur: bound is reached when the +default starting time of the next note is greater than or equal to the +score-dur: value. This definition is necessary because note times are not +strictly increasing.) When either bound is reached, score generation ends. At +least one of these two parameters must be specified or an error is raised. +These keyword parameters are evaluated just once and are not copied into the +parameter lists of generated notes. + + What is the duration of generated notes? The keyword dur: defaults to 1 and +specifies the nominal duration in seconds. Since the generated note list is +compatible with timed-seq, the starting time and duration (to be precise, the +stretch factor) are not passed as parameters to the notes. Instead, they +control the Nyquist environment in which the note will be evaluated. + + What is the start time of a note? The default start time of the first note is +zero. Given a note, the default start time of the next note is the start time +plus the inter-onset time, which is given by the ioi: parameter. If no ioi: +parameter is specified, the inter-onset time defaults to the duration, given by +dur:. In all cases, the default start time of a note can be overridden by the +keyword parameter time:. + + When does the score begin and end? The behavior SCORE-BEGIN-END contains the +beginning and ending of the score (these are used for score manipulations, e.g. +when scores are merged, their begin times can be aligned.) When timed-seq is +used to synthesize a score, the SCORE-BEGIN-END marker is not evaluated. The +score-gen macro inserts a ``note'' of the form (0 0 (SCORE-BEGIN-END begin-time +end-time)) at the time given by the begin: keyword, with begin-time and +end-time determined by the begin: and end: keyword parameters, respectively. +If the begin: keyword is not provided, the score begins at zero. If the end: +keyword is not provided, the score ends at the default start time of what would +be the next note after the last note in the score (as described in the previous +paragraph). Note: if time: is used to compute note starting times, and these +times are not increasing, it is strongly advised to use end: to specify an end +time for the score, because the default end time may be anywhere in the middle +of the generated sequence. + + What function is called to synthesize the note? The name: parameter names +the function. Like other parameters, the value can be any expression, including +something like next(fn-name-pattern), allowing function names to be recomputed +for each note. The default value is note. + + Can I make parameters depend upon the starting time or the duration of the +note? Parameter expressions can use the variable sg:time to access the start +time of the note, sg:ioi to access the inter-onset time, and sg:dur to access +the duration (stretch factor) of the note. Also, sg:count counts how many notes +have been computed so far, starting at 0. The order of computation is: sg:time +first, then sg:ioi and sg:dur, so for example, an expression to compute sg:dur +can depend on sg:ioi. + + Can parameters depend on each other? The keyword pre: introduces an +expression that is evaluated before each note, and post: provides an expression +to be evaluated after each note. The pre: expression can assign one or more +global variables which are then used in one or more expressions for parameters. + + How do I debug score-gen expressions? You can set the trace: parameter to +true (t) to enable a print statement for each generated note. + + How can I save scores generated by score-gen that I like? If the keyword +parameter save: is set to a symbol, the global variable named by the symbol is +set to the value of the generated sequence. Of course, the value returned by +score-gen is just an ordinary list that can be saved like any other value. + + In summary, the following keywords have special interpretations in score-gen: +begin:, end:, time:, dur:, name:, ioi:, trace:, save:, score-len:, score-dur:, +pre:, post:. All other keyword parameters are expressions that are evaluated +once for each note and become the parameters of the notes. + + + +13.4.3. Score Manipulation + Nyquist encourages the representation of music as executable programs, or +behaviors, and there are various ways to modify behaviors, including time +stretching, transposition, etc. An alternative to composing executable programs +is to manipulate scores as editable data. Each approach has its strengths and +weaknesses. This section describes functions intended to manipulate Xmusic +scores as generated by, or at least in the form generated by, score-gen. Recall +that this means scores are lists of events (e.g. notes), where events are +three-element lists of the form (time duration expression, and where expression +is a standard lisp function call where all parameters are keyword parameters. +In addition, the first ``note'' may be the special SCORE-BEGIN-END expression. +If this is missing, the score begins at zero and ends at the end of the last +note. + + For convenience, a set of functions is offered to access properties of events +(or notes) in scores. Although lisp functions such as car, cadr, and caddr can +be used, code is more readable when more mnemonic functions are used to access +events. + +event-time(event) [SAL] +(event-time event) [LISP] + Retrieve the time field from an event. + +event-set-time(event, time) [SAL] +(event-set-time event time) [LISP] + Construct a new event where the time of event is replaced by time. + +event-dur(event) [SAL] +(event-dur event) [LISP] + Retrieve the duration (i.e. the stretch factor) field from an event. + +event-set-dur(event, dur) [SAL] +(event-set-dur event dur) [LISP] + Construct a new event where the duration (or stretch factor) of event is + replaced by dur. + +event-expression(event) [SAL] +(event-expression event) [LISP] + Retrieve the expression field from an event. + +event-set-expression(event, dur) [SAL] +(event-set-expression event dur) [LISP] + Construct a new event where the expression of event is replaced by + expression. + +event-end(event) [SAL] +(event-end event) [LISP] + Retrieve the end time of event, its time plus its duration. + +expr-has-attr(expression, attribute) [SAL] +(expr-has-attr expression attribute) [LISP] + Test whether a score event expression has the given attribute. + +expr-get-attr(expression, attribute [, default]) [SAL] +(expr-get-attr expression attribute [default]) [LISP] + Get the value of the given attribute from a score event expression. If + attribute is not present, return default if specified, and otherwise nil. + +expr-set-attr(expr, attribute, value) [SAL] +(expr-set-attr expr attribute value) [LISP] + Construct a new expression identical to expr except that the attribute has + value. + +event-has-attr(event, attribute) [SAL] +(event-has-attr event attribute) [LISP] + Test whether a given score event's expression has the given attribute. + +event-get-attr(event, attribute, [default]) [SAL] +(event-get-attr event attribute [default]) [LISP] + Get the value of the given attribute from a score event's expression. If + attribute is not present, return default if specified, and otherwise nil. + +event-set-attr(event, attribute, value) [SAL] +(event-set-attr event attribute value) [LISP] + Construct a new event identical to event except that the attribute has + value. + + Functions are provided to shift the starting times of notes, stretch times +and durations, stretch only durations, add an offset to a keyword parameter, +scale a keyword parameter, and other manipulations. Functions are also provided +to extract ranges of notes, notes that match criteria, and to combine scores. +Most of these functions (listed below in detail) share a set of keyword +parameters that optionally limit the range over which the transformation +operates. The from-index: and to-index: parameters specify the index of the +first note and the index of the last note to be changed. If these numbers are +negative, they are offsets from the end of the score, e.g. -1 denotes the last +note of the score. The from-time: and to-time: indicate a range of starting +times of notes that will be affected by the manipulation. Only notes whose time +is greater than or equal to the from-time and strictly less than the to-time +are modified. If both index and time ranges are specified, only notes that +satisfy both constraints are selected. (Note: in LISP syntax, colons precede +the keyword, so use :from-index, :to-index, :from-time, and :to-time.) + +score-sorted(score) [SAL] +(score-sorted score) [LISP] + Test if score is sorted. + +score-sort(score [, copy-flag]) [SAL] +(score-sort score [copy-flag]) [LISP] + Sort the notes in a score into start-time order. If copy-flag is nil, this + is a destructive operation which should only be performed if the top-level + score list is a fresh copy that is not shared by any other variables. (The + copy-flag is intended for internal system use only.) For the following + operations, it is assumed that scores are sorted, and all operations + return a sorted score. + +score-shift(score, offset, from-index: i, to-index: j, from-time: x, to-time: + y) [SAL] +(score-shift score offset :from-index i :to-index j :from-time x :to-time y) + [LISP] + Add a constant offset to the starting time of a set of notes in score. By + default, all notes are modified, but the range of notes can be limited + with the keyword parameters. The begin time of the score is not changed, + but the end time is increased by offset. The original score is not + modified, and a new score is returned. + +score-stretch(score, factor, dur: dur-flag, time: time-flag, from-index: i, + to-index: j, from-time: x, to-time: y) [SAL] +(score-stretch score factor :dur dur-flag :time time-flag :from-index i + :to-index j :from-time x :to-time y) [LISP] + Stretch note times and durations by factor. The default dur-flag is + non-null, but if dur-flag is null, the original durations are retained and + only times are stretched. Similarly, the default time-flag is non-null, + but if time-flag is null, the original times are retained and only + durations are stretched. If both dur-flag and time-flag are null, the + score is not changed. If a range of notes is specified, times are scaled + within that range, and notes after the range are shifted so that the + stretched region does not create a "hole" or overlap with notes that + follow. If the range begins or ends with a time (via from-time: and + to-time:), time stretching takes place over the indicated time interval + independent of whether any notes are present or where they start. In other + words, the ``rests'' are stretched along with the notes. The original + score is not modified, and a new score is returned. + +score-transpose(score, keyword, amount, from-index: i, to-index: j, from-time: + x, to-time: y) [SAL] +(score-transpose score keyword amount :from-index i :to-index j :from-time x + :to-time y) [LISP] + For each note in the score and in any indicated range, if there is a + keyword parameter matching keyword and the parameter value is a number, + increment the parameter value by amount. For example, to tranpose up by a + whole step, write (score-transpose 2 :pitch score). The original score is + not modified, and a new score is returned. + +score-scale(score, keyword, amount, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL] +(score-scale score keyword amount :from-index i :to-index j :from-time x + :to-time y) [LISP] + For each note in the score and in any indicated range, if there is a + keyword parameter matching keyword and the parameter value is a number, + multiply the parameter value by amount. The original score is not + modified, and a new score is returned. + +score-sustain(score, factor, from-index: i, to-index: j, from-time: x, to-time: + y) [SAL] +(score-sustain score factor :from-index i :to-index j :from-time x :to-time y) + [LISP] + For each note in the score and in any indicated range, multiply the + duration (stretch factor) by amount. This can be used to make notes sound + more legato or staccato, and does not change their starting times. The + original score is not modified, and a new score is returned. + +score-voice(score, replacement-list, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL] +(score-voice score replacement-list :from-index i :to-index j :from-time x + :to-time y) [LISP] + For each note in the score and in any indicated range, replace the + behavior (function) name using replacement-list, which has the format: + ((old1 new1) (old2 new2) ...), where oldi indicates a current behavior + name and newi is the replacement. If oldi is *, it matches anything. For + example, to replace my-note-1 by trombone and my-note-2 by horn, use + score-voice(score, {{my-note-1 trombone} {my-note-2 horn}}). To replace + all instruments with piano, use score-voice(score, {{* piano}}). The + original score is not modified, and a new score is returned. + +score-merge(score1, score2, ...) [SAL] +(score-merge score1 score2 ...) [LISP] + Create a new score containing all the notes of the parameters, which are + all scores. The resulting notes retain their original times and durations. + The merged score begin time is the minimum of the begin times of the + parameters and the merged score end time is the maximum of the end times + of the parameters. The original scores are not modified, and a new score + is returned. + +score-append(score1, score2, ...) [SAL] +(score-append score1 score2 ...) [LISP] + Create a new score containing all the notes of the parameters, which are + all scores. The begin time of the first score is unaltered. The begin time + of each other score is aligned to the end time of the previous score; + thus, scores are ``spliced'' in sequence. The original scores are not + modified, and a new score is returned. + +score-select(score, predicate, from-index: i, to-index: j, from-time: x, + to-time: y, reject: flag) [SAL] +(score-select score predicate :from-index i :to-index j :from-time x :to-time y + :reject flag) [LISP] + Select (or reject) notes to form a new score. Notes are selected if they + fall into the given ranges of index and time and they satisfy predicate, a + function of three parameters that is applied to the start time, duration, + and the expression of the note. Alternatively, predicate may be t, + indicating that all notes in range are to be selected. The selected notes + along with the existing score begin and end markers, are combined to form + a new score. Alternatively, if the reject: parameter is non-null, the + notes not selected form the new score (in other words the selected notes + are rejected or removed to form the new score). The original score is not + modified, and a new score is returned. + +score-set-begin(score, time) [SAL] +(score-set-begin score time) [LISP] + The begin time from the score's SCORE-BEGIN-END marker is set to time. The + original score is not modified, and a new score is returned. + +score-get-begin(score) [SAL] +(score-get-begin score) [LISP] + Return the begin time of the score. + +score-set-end(score, time) [SAL] +(score-set-end score time) [LISP] + The end time from the score's SCORE-BEGIN-END marker is set to time. The + original score is not modified, and a new score is returned. + +score-get-end(score) [SAL] +(score-get-end score) [LISP] + Return the end time of the score. + +score-must-have-begin-end(score) [SAL] +(score-must-have-begin-end score) [LISP] + If score does not have a begin and end time, construct a score with a + SCORE-BEGIN-END expression and return it. If score already has a begin and + end time, just return the score. The orignal score is not modified. + +score-filter-length(score, cutoff) [SAL] +(score-filter-length score cutoff) [LISP] + Remove notes that extend beyond the cutoff time. This is similar to + score-select, but the here, events are removed when their nominal ending + time (start time plus duration) exceeds the cutoff, whereas the to-time: + parameter is compared to the note's start time. The original score is not + modified, and a new score is returned. + +score-repeat(score, n) [SAL] +(score-repeat score n) [LISP] + Make a sequence of n copies of score. Each copy is shifted to that it's + begin time aligns with the end time of the previous copy, as in + score-append. The original score is not modified, and a new score is + returned. + +score-stretch-to-length(score, length) [SAL] +(score-stretch-to-length score length) [LISP] + Stretch the score so that the end time of the score is the score's begin + time plus length. The original score is not modified, and a new score is + returned. + +score-filter-overlap(score) [SAL] +(score-filter-overlap score) [LISP] + Remove overlapping notes (based on the note start time and duration), + giving priority to the positional order within the note list (which is + also time order). The original score is not modified, and a new score is + returned. + +score-print(score) [SAL] +(score-print score) [LISP] + Print a score with one note per line. Returns nil. + +score-play(score) [SAL] +(score-play score) [LISP] + Play score using timed-seq to convert the score to a sound, and play to + play the sound. + +score-adjacent-events(score, function, from-index: i, to-index: j, from-time: + x, to-time: y) [SAL] +(score-adjacent-events score function :from-index i :to-index j :from-time x + :to-time y) [LISP] + Call (function A B C), where A, B, and C are consecutive notes in the + score. The result replaces B. If the result is nil, B is deleted, and the + next call will be (function A C D), etc. The first call is to (function + nil A B) and the last is to (function Y Z nil). If there is just one note + in the score, (function nil A nil) is called. Function calls are not made + if the note is outside of the indicated range. This function allows notes + and their parameters to be adjusted according to their immediate context. + The original score is not modified, and a new score is returned. + +score-apply(score, function, from-index: i, to-index: j, from-time: x, to-time: + y) [SAL] +(score-apply score function :from-index i :to-index j :from-time x :to-time y) + [LISP] + Replace each note in the score with the result of (function time dur + expression) (in Lisp) or function(time, dur, expression) (in SAL), where + time, dur, and expression are the time, duration, and expression of the + note. If a range is indicated, only notes in the range are replaced. The + original score is not modified, and a new score is returned. + +score-indexof(score, function, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL] +(score-indexof score function :from-index i :to-index j :from-time x :to-time + y) [LISP] + Return the index (position) of the first score event (in range) for which + applying function using (function time dur expression) returns true. + +score-last-indexof(score, function, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL] +(score-last-indexof score function :from-index i :to-index j :from-time x + :to-time y) [LISP] + Return the index (position) of the last score event (in range) for which + applying function using (function time dur expression) returns true. + +score-randomize-start(score, amt, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL] +(score-randomize-start score amt :from-index i :to-index j :from-time x + :to-time y) [LISP] + Alter the start times of notes by a random amount up to plus or minus amt. + The original score is not modified, and a new score is returned. + + + +13.4.4. Xmusic and Standard MIDI Files + Nyquist has a general facility to read and write MIDI files. You can even +translate to and from a text representation, as described in Chapter 10. It is +also useful sometimes to read notes from Standard MIDI Files into Xmusic scores +and vice versa. At present, Xmusic only translates notes, ignoring the various +controls, program changes, pitch bends, and other messages. + + MIDI notes are translated to Xmusic score events as follows: + + (time dur (NOTE :chan channel :pitch keynum :vel velocity)), + +where channel, keynum, and velocity come directly from the MIDI message +(channels are numbered starting from zero). Note also that note-off messages +are implied by the stretch factor dur which is duration in seconds. + +score-read-smf(filename) [SAL] +(score-read-smf filename) [LISP] + Read a standard MIDI file from filename. Return an Xmusic score, or nil if + the file could not be opened. The start time is zero, and the end time is + the maximum end time of all notes. A very limited interface is offered to + extract MIDI program numbers from the file: The global variable *rslt* is + set to a list of MIDI program numbers for each channel. E.g. if *rslt* is + (0 20 77), then program for channel 0 is 0, for channel 1 is 20, and for + channel 2 is 77. Program changes were not found on other channels. The + default program number is 0, so in this example, it is not known whether + the program 0 on channel 0 is the result of a real MIDI program change + command or just a default value. If more than one program change exists + on a channel, the last program number is recorded and returned, so this + information will only be completely correct when the MIDI file sends + single program change per channel before any notes are played. This, + however, is a fairly common practice. Note that the list returned as + *rslt* can be passed to score-write-smf, described below. + +score-write-smf(score, filename, [programs]) [SAL] +(score-write-smf score filename programs) [LISP] + Write a standard MIDI file to filename with notes in score. In this + function, every event in the score with a pitch: attribute, regardless of + the ``instrument'' (or function name), generates a MIDI note, using the + chan: attribute for the channel (default 0) and the vel: attribute for + velocity (default 100). There is no facility (in the current + implementation) to issue control changes, but to allow different + instruments, MIDI programs may be set in two ways. The simplest is to + associate programs with channels using the optional programs parameter, + which is simply a list of up to 16 MIDI program numbers. Corresponding + program change commands are added to the beginning of the MIDI file. If + programs has less than 16 elements, program change commands are only sent + on the first n channels. The second way to issue MIDI program changes is + to add a program: keyword parameter to a note in the score. Typically, the + note will have a pitch: of nil so that no actual MIDI note-on message is + generated. If program changes and notes have the same starting times, + their relative playback order is undefined, and the note may be cut off by + an immediately following program change. Therefore, program changes should + occur slightly, e.g. 1 ms, before any notes. Program numbers and channels + are numbered starting at zero, matching the internal MIDI representation. + This may be one less than displayed on MIDI hardware, sequencers, etc. + + + +13.4.5. Workspaces + When working with scores, you may find it necessary to save them in files +between work sessions. This is not an issue with functions because they are +normally edited in files and loaded from them. In contrast, scores are created +as Lisp data, and unless you take care to save them, they will be destroyed +when you exit the Nyquist program. + + A simple mechanism called a workspace has been created to manage scores (and +any other Lisp data, for that matter). A workspace is just a set of lisp +global variables. These variables are stored in the file workspace.lsp. For +simplicity, there is only one workspace, and no backups or versions are +maintained, but the user is free to make backups and copies of workspace.lsp. +To help remember what each variable is for, you can also associate and retrieve +a text string with each variable. The following functions manage workspaces. + + In addition, when a workspace is loaded, you can request that functions be +called. For example, the workspace might store descriptions of a graphical +interface. When the workspace is loaded, a function might run to convert saved +data into a graphical interface. (This is how sliders are saved by the IDE.) + +add-to-workspace(symbol) [SAL] +(add-to-workspace symbol) [LISP] + Adds a global variable to the workspace. The symbol should be a (quoted) + symbol. + +save-workspace() [SAL] +(save-workspace) [LISP] + All global variables in the workspace are saved to workspace.lsp (in the + current directory), overwriting the previous file. + +describe(symbol [, description]) [SAL] +(describe symbol [description)] [LISP] + If description, a text string, is present, associate description with the + variable named by the symbol. If symbol is not already in the workspace, + it is added. If description is omitted, the function returns the current + description (from a previous call) for symbol. + +add-action-to-workspace(symbol) [SAL] +(add-action-to-workspace symbol) [LISP] + Requests that the function named by symbol be called when the workspace is + loaded (if the function is defined). + + To restore a workspace, use the command load "workspace". This restores the +values of the workspace variables to the values they had when save-workspace +was last called. It also restores the documentation strings, if set, by +describe. If you load two or more workspace.lsp files, the variables will be +merged into a single workspace. The current set of workspace variables are +saved in the list *workspace*. To clear the workspace, set *workspace* to nil. +This does not delete any variables, but means that no variables will be saved +by save-workspace until variables are added again. + + Functions to be called are saved in the list *workspace-actions*. to clear +the functions, set *workspace-actions* to nil. Restore functions to the list +with add-action-to-workspace. + + + +13.4.6. Utility Functions + This chapter concludes with details of various utility functions for score +manipulation. + +patternp(expression) [SAL] +(patternp expression) [LISP] + Test if expression is an Xmusic pattern. + +params-transpose(params, keyword, amount) [SAL] +(params-transpose params keyword amount) [LISP] + Add a transposition amount to a score event parameter. The params + parameter is a list of keyword/value pairs (not preceded by a function + name). The keyword is the keyword of the value to be altered, and amount + is a number to be added to the value. If no matching keyword is present in + params, then params is returned. Otherwise, a new parameter list is + constructed and returned. The original params is not changed. + +params-scale(params, keyword, amount) [SAL] +(params-scale params keyword amount) [LISP] + Scale a score event parameter by some factor. This is like + params-transpose, only using multiplication. The params list is a list of + keyword/value pairs, keyword is the parameter keyword, and amount is the + scale factor. + +interpolate(x, x1, y1, x2, y2) [SAL] +(interpolate x x1 y1 x2 y2) [LISP] + Linearly interpolate (or extrapolate) between points (x1, y1) and (x2, y2) + to compute the y value corresponding to x. + +intersection(a, b) [SAL] +(intersection a b) [LISP] + Compute the set intersection of lists a and b. + +union(a, b) [SAL] +(union a b) [LISP] + Compute the set union of lists a and b. + +set-difference(a, b) [SAL] +(set-difference a b) [LISP] + Compute the set of all elements that are in a but not in b. + +subsetp(a, b) [SAL] +(subsetp a b) [LISP] + Returns true iff a is a subset of b, that is, each element of a is a + member of b. +14. Nyquist Libraries + Nyquist is always growing with new functions. Functions that are most +fundamental are added to the core language. These functions are automatically +loaded when you start Nyquist, and they are documented in the preceding +chapters. Other functions seem less central and are implemented as lisp files +that you can load. These are called library functions, and they are described +here. + + To use a library function, you must first load the library, e.g. (load +"pianosyn") loads the piano synthesis library. The libraries are all located in +the lib directory, and you should therefore include this directory on your +XLISPPATH variable. (See Section 1.) Each library is documented in one of the +following sections. When you load the library described by the section, all +functions documented in that section become available. + +14.1. Piano Synthesizer + The piano synthesizer (library name is pianosyn.lsp) generates realistic +piano tones using a multiple wavetable implementation by Zheng (Geoffrey) Hua +and Jim Beauchamp, University of Illinois. Please see the notice about +acknowledgements that prints when you load the file. Further informations and +example code can be found in demos/piano.htm. There are several useful +functions in this library: + +piano-note(duration, step, dynamic) [SAL] +(piano-note duration step dynamic) [LISP] + Synthesizes a piano tone. Duration is the duration to the point of key + release, after which there is a rapid decay. Step is the pitch in half + steps, and dynamic is approximately equivalent to a MIDI key velocity + parameter. Use a value near 100 for a loud sound and near 10 for a soft + sound. + +piano-note-2(step, dynamic) [SAL] +(piano-note-2 step dynamic) [LISP] + Similar to piano-note except the duration is nominally 1.0. + +piano-midi(midi-file-name) [SAL] +(piano-midi midi-file-name) [LISP] + Use the piano synthesizer to play a MIDI file. The file name (a string) is + given by midi-file-name. + +piano-midi2file(midi-file-name, sound-file-name) [SAL] +(piano-midi2file midi-file-name sound-file-name) [LISP] + Use the piano synthesizer to play a MIDI file. The MIDI file is given by + midi-file-name and the (monophonic) result is written to the file named + sound-file-name. + +14.2. Dymanics Compression + To use these functions, load the file compress.lsp. This library implements a +compressor originally intended for noisy speech audio, but usable in a variety +of situations. There are actually two compressors that can be used in series. +The first, compress, is a fairly standard one: it detects signal level with an +RMS detector and uses table-lookup to determine how much gain to place on the +original signal at that point. One bit of cleverness here is that the RMS +envelope is ``followed'' or enveloped using snd-follow, which does look-ahead +to anticipate peaks before they happen. + + The other interesting feature is compress-map, which builds a map in terms of +compression and expansion. For speech, the recommended procedure is to figure +out the noise floor on the signal you are compressing (for example, look at the +signal where the speaker is not talking). Use a compression map that leaves +the noise alone and boosts signals that are well above the noise floor. Alas, +the compress-map function is not written in these terms, so some +head-scratching is involved, but the results are quite good. + + The second compressor is called agc, and it implements automatic gain control +that keeps peaks at or below 1.0. By combining compress and agc, you can +process poorly recorded speech for playback on low-quality speakers in noisy +environments. The compress function modulates the short-term gain to to +minimize the total dynamic range, keeping the speech at a generally loud level, +and the agc function rides the long-term gain to set the overall level without +clipping. + +compress-map(compress-ratio, compress-threshold, expand-ratio, expand-ratio, + limit: limit, transition: transition) [SAL] +(compress-map compress-ratio compress-threshold expand-ratio expand-ratio + :limit limit :transition transition]) [LISP] + Construct a map for the compress function. The map consists of two parts: + a compression part and an expansion part. The intended use is to compress + everything above compress-threshold by compress-ratio, and to downward + expand everything below expand-ratio by expand-ratio. Thresholds are in + dB and ratios are dB-per-dB. 0dB corresponds to a peak amplitude of 1.0 + or rms amplitude of 0.7 If the input goes above 0dB, the output can + optionally be limited by setting limit: (a keyword parameter) to T. This + effectively changes the compression ratio to infinity at 0dB. If limit: + is nil (the default), then the compression-ratio continues to apply above + 0dB. + +Another keyword parameter, transition:, sets the amount below the thresholds + (in dB) that a smooth transition starts. The default is 0, meaning that + there is no smooth transition. The smooth transition is a 2nd-order + polynomial that matches the slopes of the straight-line compression curve + and interpolates between them. + +It is assumed that expand-threshold <= compress-threshold <= 0 The gain is + unity at 0dB so if compression-ratio > 1, then gain will be greater than + unity below 0dB. + +The result returned by this function is a sound for use in the shape function. + The sound maps input dB to gain. Time 1.0 corresponds to 0dB, time 0.0 + corresponds to -100 dB, and time 2.0 corresponds to +100dB, so this is a + 100hz ``sample rate'' sound. The sound gives gain in dB. + +db-average(input) [SAL] +(db-average input) [LISP] + Compute the average amplitude of input in dB. + +compress(input, map, rise-time, fall-time [, lookahead]) [SAL] +(compress input map rise-time fall-time [lookahead)] [LISP] + Compress input using map, a compression curve probably generated by + compress-map (see above). Adjustments in gain have the given rise-time and + fall-time. Lookahead tells how far ahead to look at the signal, and is + rise-time by default. + +agc(input, range, rise-time, fall-time [, lookahead]) [SAL] +(agc input range rise-time fall-time [lookahead]) [LISP] + An automatic gain control applied to input. The maximum gain in dB is + range. Peaks are attenuated to 1.0, and gain is controlled with the given + rise-time and fall-time. The look-ahead time default is rise-time. + +14.3. Clipping Softener + This library, in soften.lsp, was written to improve the quality of poorly +recorded speech. In recordings of speech, extreme clipping generates harsh high +frequency noise. This can sound particulary bad on small speakers that will +emphasize high frequencies. This problem can be ameliorated by low-pass +filtering regions where clipping occurs. The effect is to dull the harsh +clipping. Intelligibility is not affected by much, and the result can be much +more pleasant on the ears. Clipping is detected simply by looking for large +signal values. Assuming 8-bit recording, this level is set to 126/127. + + The function works by cross-fading between the normal signal and a filtered +signal as opposed to changing filter coefficients. + +soften-clipping(snd, cutoff) [SAL] +(soften-clipping snd cutoff) [LISP] + Filter the loud regions of a signal where clipping is likely to have + generated additional high frequencies. The input signal is snd and cutoff + is the filter cutoff frequency (4 kHz is recommended for speech). + +14.4. Graphical Equalizer + There's nothing really ``graphical'' about this library (grapheq.lsp), but +this is a common term for multi-band equalizers. This implementation uses +Nyquist's eq-band function to split the incoming signal into different +frequency bands. Bands are spaced geometrically, e.g. each band could be one +octave, meaning that each successive band has twice the bandwidth. An +interesting possibility is using computed control functions to make the +equalization change over time. + +nband-range(input, gains, lowf, highf) [SAL] +(nband-range input gains lowf highf) [LISP] + A graphical equalizer applied to input (a SOUND). The gain controls and + number of bands is given by gains, an ARRAY of SOUNDs (in other words, a + Nyquist multichannel SOUND). Any sound in the array may be replaced by a + FLONUM. The bands are geometrically equally spaced from the lowest + frequency lowf to the highest frequency highf (both are FLONUMs). + +nband(input, gains) [SAL] +(nband input gains) [LISP] + A graphical equalizer, identical to nband-range with a range of 20 to + 20,000 Hz. + +14.5. Sound Reversal + The reverse.lsp library implements functions to play sounds in reverse. + +s-reverse(snd) [SAL] +(s-reverse snd) [LISP] + Reverses snd (a SOUND). Sound must be shorter than *max-reverse-samples*, + which is currently initialized to 25 million samples. Reversal allocates + about 4 bytes per sample. This function uses XLISP in the inner sample + loop, so do not be surprised if it calls the garbage collector a lot and + runs slowly. The result starts at the starting time given by the current + environment (not necessarily the starting time of snd). If snd has + multiple channels, a multiple channel, reversed sound is returned. + +s-read-reverse(filename, time-offset: offset, srate: sr, dur: dur, nchans: + chans, format: format, mode: mode, bits: n, swap: flag) [SAL] +(s-read-reverse filename :time-offset offset :srate sr :dur dur :nchans chans + :format format :mode mode :bits n :swap flag) [LISP] + This function is identical to s-read (see 7.5), except it reads the + indicated samples in reverse. Like s-reverse (see above), it uses XLISP in + the inner loop, so it is slow. Unlike s-reverse, s-read-reverse uses a + fixed amount of memory that is independent of how many samples are + computed. Multiple channels are handled. + +14.6. Time Delay Functions + The time-delay-fns.lsp library implements chorus, phaser, and flange effects. + +phaser(snd) [SAL] +(phaser snd) [LISP] + A phaser effect applied to snd (a SOUND). There are no parameters, but + feel free to modify the source code of this one-liner. + +flange(snd) [SAL] +(flange snd) [LISP] + A flange effect applied to snd. To vary the rate and other parameters, see + the source code. + +stereo-chorus(snd) [SAL] +(stereo-chorus snd) [LISP] + A chorus effect applied to snd, a SOUND (monophonic). The output is a + stereo sound. All parameters are built-in, but see the simple source code + to make modifications. + +chorus(snd, maxdepth, depth, rate, saturation) [SAL] +(chorus snd maxdepth depth rate saturation) [LISP] + A chorus effect applied to snd. All parameters may be arrays as usual. The + maxdepth is a FLONUM giving twice the maximum value of depth, which may be + a FLONUM or a SOUND. The chorus is implemented as a variable delay + modulated by a sinusoid running at rate Hz (a FLONUM). The sinusoid is + scaled by depth and offset by maxdepth/2. The delayed signal is mixed with + the original, and saturation gives the fraction of the delayed signal + (from 0 to 1) in the mix. A reasonable choice of parameter values is + maxdepth = 0.05, depth = 0.025, rate = 0.5, and saturation = 0.5. + +14.7. Multiple Band Effects + The bandfx.lsp library implements several effects based on multiple frequency +bands. The idea is to separate a signal into different frequency bands, apply a +slightly different effect to each band, and sum the effected bands back +together to form the result. This file includes its own set of examples. After +loading the file, try f2(), f3(), f4(), and f5() to hear them. + + There is much room for expansion and experimentation with this library. Other +effects might include distortion in certain bands (for example, there are +commercial effects that add distortion to low frequencies to enhance the sound +of the bass), separating bands into different channels for stereo or +multi-channel effects, adding frequency-dependent reverb, and performing +dynamic compression, limiting, or noise gate functions on each band. There are +also opportunities for cross-synthesis: using the content of bands extracted +from one signal to modify the bands of another. The simplest of these would be +to apply amplitude envelopes of one sound to another. Please contact us +(dannenberg@cs.cmu.edu) if you are interested in working on this library. + +apply-banded-delay(s, lowp, highp, num-bands, lowd, highd, fb, wet) [SAL] +(apply-banded-delay s lowp highp num-bands lowd highd fb wet) [LISP] + Separates input SOUND s into FIXNUM num-bands bands from a low frequency + of lowp to a high frequency of highp (these are FLONUMS that specify + steps, not Hz), and applies a delay to each band. The delay for the lowest + band is given by the FLONUM lowd (in seconds) and the delay for the + highest band is given by the FLONUM highd. The delays for other bands are + linearly interpolated between these values. Each delay has feedback gain + controlled by FLONUM fb. The delayed bands are scaled by FLONUM wet, and + the original sound is scaled by 1 - wet. All are summed to form the + result, a SOUND. + +apply-banded-bass-boost(s, lowp, highp, num-bands, num-boost, gain) [SAL] +(apply-banded-bass-boost s lowp highp num-bands num-boost gain) [LISP] + Applies a boost to low frequencies. Separates input SOUND s into FIXNUM + num-bands bands from a low frequency of lowp to a high frequency of highp + (these are FLONUMS that specify steps, not Hz), and scales the lowest + num-boost (a FIXNUM) bands by gain, a FLONUM. The bands are summed to form + the result, a SOUND. + +apply-banded-treble-boost(s, lowp, highp, num-bands, num-boost, gain) [SAL] +(apply-banded-treble-boost s lowp highp num-bands num-boost gain) [LISP] + Applies a boost to high frequencies. Separates input SOUND s into FIXNUM + num-bands bands from a low frequency of lowp to a high frequency of highp + (these are FLONUMS that specify steps, not Hz), and scales the highest + num-boost (a FIXNUM) bands by gain, a FLONUM. The bands are summed to form + the result, a SOUND. + +14.8. Granular Synthesis + Some granular synthesis functions are implemented in the gran.lsp library +file. There are many variations and control schemes one could adopt for +granular synthesis, so it is impossible to create a single universal granular +synthesis function. One of the advantages of Nyquist is the integration of +control and synthesis functions, and users are encouraged to build their own +granular synthesis functions incorporating their own control schemes. The +gran.lsp file includes many comments and is intended to be a useful starting +point. Another possibility is to construct a score with an event for each +grain. Estimate a few hundred bytes per score event (obviously, size depends on +the number of parameters) and avoid using all of your computer's memory. + +sf-granulate(filename, grain-dur, grain-dev, ioi, ioi-dev, pitch-dev, + [file-start, file-end]) [SAL] +(sf-granulate filename grain-dur grain-dev ioi ioi-dev pitch-dev [file-start + file-end]) [LISP] + Granular synthesis using a sound file named filename as the source for + grains. Grains are extracted from a sound file named by filename by + stepping through the file in equal increments. Each grain duration is the + sum of grain-dur and a random number from 0 to grain-dev. Grains are then + multiplied by a raised cosine smoothing window and resampled at a ratio + between 1.0 and pitch-dev. If pitch-dev is greater than one, grains are + stretched and the pitch (if any) goes down. If pitch-dev is less than one, + grains are shortened and the pitch goes up. Grains are then output with an + inter-onset interval between successive grains (which may overlap) + determined by the sum of ioi and a random number from 0 to ioi-dev. The + duration of the resulting sound is determined by the stretch factor (not + by the sound file). The number of grains is the total sound duration + (determined by the stretch factor) divided by the mean inter-onset + interval, which is ioi + ioi-dev * 0.5. The grains are taken from + equally-spaced starting points in filename, and depending on grain size + and number, the grains may or may not overlap. The output duration will + simply be the sum of the inter-onset intervals and the duration of the + last grain. If ioi-dev is non-zero, the output duration will vary, but the + expected value of the duration is the stretch factor. To achieve a rich + granular synthesis effect, it is often a good idea to sum four or more + copies of sf-granulate together. (See the gran-test function in gran.lsp.) + +14.9. MIDI Utilities + The midishow.lsp library has functions that can print the contents fo MIDI +files. This intended as a debugging aid. + +midi-show-file(file-name) [SAL] +(midi-show-file file-name) [LISP] + Print the contents of a MIDI file to the console. + +midi-show(the-seq [, out-file]) [SAL] +(midi-show the-seq [out-file]) [LISP] + Print the contents of the sequence the-seq to the file out-file (whose + default value is the console.) + +14.10. Reverberation + The reverb.lsp library implements artificial reverberation. + +reverb(snd, time) [SAL] +(reverb snd time) [LISP] + Artificial reverberation applied to snd with a decay time of time. + +14.11. DTMF Encoding + The dtmf.lsp library implements DTMF encoding. DTMF is the ``touch tone'' +code used by telephones. + +dtmf-tone(key, len, space) [SAL] +(dtmf-tone key len space) [LISP] + Generate a single DTMF tone. The key parameter is either a digit (a FIXNUM + from 0 through 9) or the atom STAR or POUND. The duration of the done is + given by len (a FLONUM) and the tone is followed by silence of duration + space (a FLONUM). + +speed-dial(thelist) [SAL] +(speed-dial thelist) [LISP] + Generates a sequence of DTMF tones using the keys in thelist (a LIST of + keys as described above under dtmf-tone). The duration of each tone is 0.2 + seconds, and the space between tones is 0.1 second. Use stretch to change + the ``dialing'' speed. + +14.12. Dolby Surround(R), Stereo and Spatialization Effects + The spatial.lsp library implements various functions for stereo manipulation +and spatialization. It also includes some functions for Dolby Pro-Logic +panning, which encodes left, right, center, and surround channels into stereo. +The stereo signal can then be played through a Dolby decoder to drive a +surround speaker array. This library has a somewhat simplified encoder, so you +should certainly test the output. Consider using a high-end encoder for +critical work. There are a number of functions in spatial.lsp for testing. See +the source code for comments about these. + +stereoize(snd) [SAL] +(stereoize snd) [LISP] + Convert a mono sound, snd, to stereo. Four bands of equalization and some + delay are used to create a stereo effect. + +widen(snd, amt) [SAL] +(widen snd amt) [LISP] + Artificially widen the stereo field in snd, a two-channel sound. The + amount of widening is amt, which varies from 0 (snd is unchanged) to 1 + (maximum widening). The amt can be a SOUND or a number. + +span(snd, amt) [SAL] +(span snd amt) [LISP] + Pan the virtual center channel of a stereo sound, snd, by amt, where 0 + pans all the way to the left, while 1 pans all the way to the right. The + amt can be a SOUND or a number. + +swapchannels(snd) [SAL] +(swapchannels snd) [LISP] + Swap left and right channels in snd, a stereo sound. + +prologic(l, c, r, s) [SAL] +(prologic l c r s) [LISP] + Encode four monaural SOUNDs representing the front-left, front-center, + front-right, and rear channels, respectively. The return value is a + stereo sound, which is a Dolby-encoded mix of the four input sounds. + +pl-left(snd) [SAL] +(pl-left snd) [LISP] + Produce a Dolby-encoded (stereo) signal with snd, a SOUND, encoded as the + front left channel. + +pl-center(snd) [SAL] +(pl-center snd) [LISP] + Produce a Dolby-encoded (stereo) signal with snd, a SOUND, encoded as the + front center channel. + +pl-right(snd) [SAL] +(pl-right snd) [LISP] + Produce a Dolby-encoded (stereo) signal with snd, a SOUND, encoded as the + front right channel. + +pl-rear(snd) [SAL] +(pl-rear snd) [LISP] + Produce a Dolby-encoded (stereo) signal with snd, a SOUND, encoded as the + rear, or surround, channel. + +pl-pan2d(snd, x, y) [SAL] +(pl-pan2d snd x y) [LISP] + Comparable to Nyquist's existing pan function, pl-pan2d provides not only + left-to-right panning, but front-to-back panning as well. The function + accepts three parameters: snd is the (monophonic) input SOUND, x is a + left-to-right position, and y is a front-to-back position. Both position + parameters may be numbers or SOUNDs. An x value of 0 means left, and 1 + means right. Intermediate values map linearly between these extremes. + Similarly, a y value of 0 causes the sound to play entirely through the + front speakers(s), while 1 causes it to play entirely through the rear. + Intermediate values map linearly. Note that, although there are usually + two rear speakers in Pro-Logic systems, they are both driven by the same + signal. Therefore any sound that is panned totally to the rear will be + played over both rear speakers. For example, it is not possible to play a + sound exclusively through the rear left speaker. + +pl-position(snd, x, y, config) [SAL] +(pl-position snd x y config) [LISP] + The position function builds upon speaker panning to allow more abstract + placement of sounds. Like pl-pan2d, it accepts a (monaural) input sound as + well as left-to-right (x) and front-to-back (y) coordinates, which may be + FLONUMs or SOUNDs. A fourth parameter config specifies the distance from + listeners to the speakers (in meters). Current settings assume this to be + constant for all speakers, but this assumption can be changed easily (see + comments in the code for more detail). There are several important + differences between pl-position and pl-pan2d. First, pl-position uses a + Cartesian coordinate system that allows x and y coordinates outside of the + range (0, 1). This model assumes a listener position of (0,0). Each + speaker has a predefined position as well. The input sound's position, + relative to the listener, is given by the vector (x,y). + +pl-doppler(snd, r) [SAL] +(pl-doppler snd r) [LISP] + Pitch-shift moving sounds according to the equation: fr = f0((c+vr)/c), + where fr is the output frequency, f0 is the emitted (source) frequency, c + is the speed of sound (assumed to be 344.31 m/s), and vr is the speed at + which the emitter approaches the receiver. (vr is the first derivative of + parameter r, the distance from the listener in meters. + +14.13. Drum Machine + The drum machine software in demos/plight deserves further explanation. to +use the software, load the code by evaluating: + + load "../demos/plight/drum.lsp" + exec load-props-file(strcat(*plight-drum-path*, + "beats.props")) + exec create-drum-patches() + exec create-patterns() + + Drum sounds and patterns are specified in the beats.props file (or whatever +name you give to load-props-file). This file contains two types of +specifications. First, there are sound file specifications. Sound files are +located by a line of the form: + + set sound-directory = "kit/" + +This gives the name of the sound file directory, relative to the beats.props +file. Then, for each sound file, there should be a line of the form: + + track.2.5 = big-tom-5.wav + +This says that on track 2, a velocity value of 5 means to play the sound file +big-tom-5.wav. (Tracks and velocity values are described below.) The +beats.props file contains specifications for all the sound files in +demos/plight/kit using 8 tracks. If you make your own specifications file, +tracks should be numbered consecutively from 1, and velocities should be in the +range of 1 to 9. + + The second set of specifications is of beat patterns. A beat pattern is given +by a line in the following form: + + beats.5 = 2--32--43-4-5--- + +The number after beats is just a pattern number. Each pattern is given a unique +number. After the equal sign, the digits and dashes are velocity values where a +dash means ``no sound.'' Beat patterns should be numbered consecutively from 1. + + Once data is loaded, there are several functions to access drum patterns and +create drum sounds (described below). The demos/plight/drums.lsp file contains +an example function plight-drum-example to play some drums. There is also the +file demos/plight/beats.props to serve as an example of how to specify sound +files and beat patterns. + +drum(tracknum, patternnum, bpm) [SAL] +(drum tracknum patternnum bpm) [LISP] + Create a sound by playing drums sounds associated with track tracknum (a + FIXNUM) using pattern patternnum. The tempo is given by bpm in beats per + minute. Normally patterns are a sequence of sixteenth notes, so the tempo + is in sixteenth notes per minute. For example, if patternnum is 10, then + use the pattern specified for beats.10. If the third character of this + pattern is 3 and tracknum is 5, then on the third beat, play the soundfile + assigned to track.5.3. This function returns a SOUND. + +drum-loop(snd, duration, numtimes) [SAL] +(drum-loop snd duration numtimes) [LISP] + Repeat the sound given by snd numtimes times. The repetitions occur at a + time offset of duration, regardless of the actual duration of snd. A SOUND + is returned. + +length-of-beat(bpm) [SAL] +(length-of-beat bpm) [LISP] + Given a tempo of bpm, return the duration of the beat in seconds. Note + that this software has no real notion of beat. A ``beat'' is just the + duration of each character in the beat pattern strings. This function + returns a FLONUM. + +14.14. Minimoog-inspired Synthesis + The moog.lsp library gives the Nyquist user easy access to ``classic'' +synthesizer sounds through an emulation of the Minimoog Synthesizer. Unlike +modular Moogs that were very large, the Minimoog was the first successful and +commonly used portable synthesizer. The trademark filter attack was unique and +easily recognizable. The goal of this Nyquist instrument is not only to provide +the user with default sounds, but also to give control over many of the +``knobs'' found on the Minimoog. In this implementation, these parameters are +controlled using keywords. The input to the moog instrument is a user-defined +sequence of notes, durations, and articulations that simulate notes played on a +keyboard. These are translated into control voltages that drive multiple +oscillators, similar to the Voltage Controlled Oscillator or VCO found in the +original analog Moog. + + The basic functionality of the Minimoog has been implemented, including the +often-used "glide". The glide feature essentially low-pass filters the control +voltage sequence in order to create sweeps between notes. Figure 21 is a +simplified schematic of the data flow in the Moog. The control lines have been +omitted. + + + + + + + + + + + + + + + + + + + Figure 21: System diagram for Minimoog emulator. + + + The most recognizable feature of the Minimoog is its resonant filter, a +Four-Pole Ladder Filter invented by Robert Moog. It is simply implemented in a +circuit with four transistors and provides an outstanding 24 dB/octave rolloff. +It is modeled here using the built-in Nyquist resonant filter. One of the Moog +filter features is a constant Q, or center frequency to bandwidth ratio. This +is implemented and the user can control the Q. + + The user can control many parameters using keywords. Their default values, +acceptable ranges, and descriptions are shown below. The defaults were obtained +by experimenting with the official Minimoog software synthesizer by Arturia. + + + +14.14.1. Oscillator Parameters + range-osc1 (2) +range-osc2 (1) +range-osc3 (3) +These parameters control the octave of each oscillator. A value of 1 +corresponds to the octave indicated by the input note. A value of 3 is two +octaves above the fundamental. The allowable range is 1 to 7. + + detun2 (-.035861) +detun3 (.0768) +Detuning of two oscillators adds depth to the sound. A value of 1 corresponds +to an increase of a single semitone and a -1 corresponds to a decrease in a +semitone. The range is -1 to 1. + + shape-osc1 (*saw-table*) +shape-osc2 (*saw-table*) +shape-osc3 (*saw-table*) +Oscilators can use any wave shape. The default sawtooth waveform is a built-in +Nyquist variable. Other waveforms can be defined by the user. + + volume-osc1 (1) +volume-osc2 (1) +volume-osc3 (1) +These parameters control the relative volume of each oscillator. The range is +any FLONUM greater than or equal to zero. + + + +14.14.2. Noise Parameters + noiselevel (.05) +This parameter controls the relative volume of the noise source. The range is +any FLONUM greater than or equal to zero. + + + +14.14.3. Filter Parameters + filter-cutoff (768) +The cutoff frequency of the filter in given in Hz. The range is zero to 20,000 +Hz. + + Q (2) +Q is the ratio of center frequency to bandwidth. It is held constant by making +the bandwidth a function of frequency. The range is any FLONUM greater than +zero. + + contour (.65) +Contour controls the range of the transient frequency sweep from a high to low +cutoff frequency when a note is played. The high frequency is proportional to +contour. A contour of 0 removes this sweep. The range is 0 to 1. + + filter-attack (.0001) +Filter attack controls the attack time of the filter, i.e. the time to reach +the high cutoff frequency. The range is any FLONUM greater than zero (seconds). + + filter-decay (.5) +Filter decay controls the decay time of the filter, i.e. the time of the sweep +from the high to low cutoff frequency. The range is any FLONUM greater than +zero (seconds). + + filter-sustain (.8) +Filter sustain controls the percentage of the filter cutoff frequency that the +filter settles on following the sweep. The range is 0 to 1. + + + +14.14.4. Amplitude Parameters + amp-attack (.01) +This parameter controls the amplitude envelope attack time, i.e. the time to +reach maximum amplitude. The range is any FLONUM greater than zero (seconds). + + amp-decay (1) +This parameter controls the amplitude envelope decay time, i.e. the time +between the maximum and sustain volumes. The range is any FLONUM greater than +zero (seconds). + + amp-sustain (1) +This parameter controls the amplitude envelope sustain volume, a fraction of +the maximum. The range is 0 to 1. + + amp-release (0) +This parameter controls the amplitude envelope release time, i.e. the time it +takes between the sustain volume and 0 once the note ends. The duration +controls the overall length of the sound. The range of amp-release is any +FLONUM greater than zero (seconds). + + + +14.14.5. Other Parameters + glide (0) +Glide controls the low-pass filter on the control voltages. This models the +glide knob on a Minimoog. A higher value corresponds to a lower cutoff +frequency and hence a longer "glide" between notes. A value of 0 corresponds to +no glide. The range is zero to 10. + + + +14.14.6. Input Format + A single note or a series of notes can be input to the Moog instrument by +defining a list with the following format: + + list(list(frequency, duration, articulation), ... ) + +where frequency is a FLONUM in steps, duration is the duration of each note in +seconds (regardless of the release time of the amplifier), and articulation is +a percentage of the duration that a sound will be played, representing the +amount of time that a key is pressed. The filter and amplitude envelopes are +only triggered if a note is played when the articulation of the previous note +is less than 1, or a key is not down at the same time. This Moog instrument is +a monophonic instrument, so only one note can sound at a time. The release +section of the amplifier is triggered when the articulation is less than 1 at +the time (duration * articulation). + + + +14.14.7. Sample Code/Sounds + Sound 1 (default parameters): + + set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99} + {29 .5 .99} {31 2 1}} + play moog(s) + + + Sound 2 (articulation, with amplitude release): + + set s = {{24 .5 .5} {26 .5 1} {28 .5 .25} {29 .5 1} {31 1 .8}} + play moog(s, amp-release: .2) + + + Sound 3 (glide): + + set s = {{24 .5 .5} {38 .5 1} {40 .5 .25} + {53 .5 1} {55 2 1} {31 2 .8} {36 2 .8}} + play moog(s, amp-release: .2, glide: .5) + + + Sound 4 (keyword parameters): Filter attack and decay are purposely longer +than notes being played with articulation equal to 1. + + set s = {{20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1} + {20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1}} + play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*, + filter-attack: 2, filter-decay: 2, + filter-cutoff: 300, contour: .8, glide: .2, Q: 8) + + + Sound 5: This example illustrates the ability to completely define a new +synthesizer with different parameters creating a drastically different sound. +Sine waves are used for wavetables. There is a high value for glide. + + define function my-moog(freq) + return moog(freq, + range-osc1: 3, range-osc2: 2, range-osc3: 4, + detun2: -.043155, detun3: .015016, + noiselevel: 0, + filter-cutoff: 400, Q: .1, contour: .0000001, + filter-attack: 0, filter-decay: .01, filter-sustain: 1, + shape-osc1: *sine-table*, shape-osc2: *sine-table*, + shape-osc3: *sine-table*, volume-osc1: 1, volume-osc2: 1, + volume-osc3: .1, amp-attack: .1, amp-decay: 0, + amp-sustain: 1, amp-release: .3, glide: 2) + + set s = {{80 .4 .75} {28 .2 1} {70 .5 1} {38 1 .5}} + play my-moog(s) + + + Sound 6: This example has another variation on the default parameters. + + set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99} + {29 .5 .99} {31 2 1}} + play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*, + filter-attack: .5, contour: .5) +I. Extending Nyquist + WARNING: Nyquist sound functions look almost like a human wrote them; they +even have a fair number of comments for human readers. Don't be fooled: +virtually all Nyquist functions are written by a special translator. If you +try to write a new function by hand, you will probably not succeed, and even if +you do, you will waste a great deal of time. (End of Warning.) + +I.1. Translating Descriptions to C Code + The translator code used to extend Nyquist resides in the trnsrc directory. +This directory also contains a special init.lsp, so if you start XLisp or +Nyquist in this directory, it will automatically read init.lsp, which in turn +will load the translator code (which resides in several files). + + Also in the trnsrc directory are a number of .alg files, which contain the +source code for the translator (more on these will follow), and a number of +corresponding .h and .c files. + + To translate a .alg file to .c and .h files, you start XLisp or Nyquist in +the trnsrc directory and type + + (translate "prod") + +where "prod" should really be replaced by the filename (without a suffix) you +want to translate. Be sure you have a saved, working copy of Nyquist or Xlisp +before you recompile! + + Note: On the Macintosh, just run Nyquist out of the runtime directory and +then use the Load menu command to load init.lsp from the trnsrc directory. +This will load the translation code and change Nyquist's current directory to +trnsrc so that commands like (translate "prod") will work. + +I.2. Rebuilding Nyquist + After generating prod.c and prod.h, you need to recompile Nyquist. For Unix +systems, you will want to generate a new Makefile. Modify transfiles.lsp in +your main Nyquist directory, run Xlisp or Nyquist and load makefile.lsp. +Follow the instructions to set your machine type, etc., and execute (makesrc) +and (makefile). + +I.3. Accessing the New Function + The new Lisp function will generally be named with a snd- prefix, e.g. +snd-prod. You can test this by running Nyquist. Debugging is usually a +combination of calling the code from within the interpreter, reading the +generated code when things go wrong, and using a C debugger to step through the +inner loop of the generated code. An approach I like is to set the default +sample rate to 10 hertz. Then, a one-second sound has only 10 samples, which +are easy to print and study on a text console. + + For some functions, you must write some Lisp code to impose ordinary Nyquist +behaviors such as stretching and time shifting. A good approach is to find +some structurally similar functions and see how they are implemented. Most of +the Lisp code for Nyquist is in nyquist.lsp. + + Finally, do not forget to write up some documentation. Also, contributions +are welcome. Send your .alg file, documentation, Lisp support functions for +nyquist.lsp, and examples or test programs to rbd@cs.cmu.edu. I will either +put them in the next release or make them available at a public ftp site. + +I.4. Why Translation? + Many of the Nyquist signal processing operations are similar in form, but +they differ in details. This code is complicated by many factors: Nyquist uses +lazy evaluation, so the operator must check to see that input samples are +available before trying to access them. Nyquist signals can have different +sample rates, different block sizes, different block boundaries, and different +start times, all of which must be taken into account. The number of software +tests is enormous. (This may sound like a lot of overhead, but the overhead is +amortized over many iterations of the inner loop. Of course setting up the +inner loop to run efficiently is one more programming task.) + + The main idea behind the translation is that all of the checks and setup code +are similar and relatively easy to generate automatically. Programmers often +use macros for this sort of task, but the C macro processor is too limited for +the complex translation required here. To tell the translator how to generate +code, you write .alg files, which provide many details about the operation in a +declarative style. For example, the code generator can make some optimizations +if you declare that two input signals are commutative (they can be exchanged +with one another). The main part of the .alg file is the inner loop which is +the heart of the signal processing code. + +I.5. Writing a .alg File + WARNING: Translation relies heavily on string substitution, which is fragile. +In particular, variables with names that are substrings of other variables will +cause problems. For example if you declare STATE variables "phase" and +"iphase", then the translator will globally substitute "phase_reg" for "phase", +converting "phase" to "phase_reg" and iphase" to "iphase_reg". Then it will +substitute "iphase_reg" for iphase" which will convert the existing +"iphase_reg" to "iphase_reg_reg". This will be confusing and will not compile. +(End of WARNING) + + To give you some idea how functions are specified, here is the specification +for snd-prod, which generates over 250 lines of C code: + + (PROD-ALG + (NAME "prod") + (ARGUMENTS ("sound_type" "s1") ("sound_type" "s2")) + (START (MAX s1 s2)) + (COMMUTATIVE (s1 s2)) + (INNER-LOOP "output = s1 * s2") + (LINEAR s1 s2) + (TERMINATE (MIN s1 s2)) + (LOGICAL-STOP (MIN s1 s2)) + ) + +A .alg file is always of the form: + + (name + (attribute value) + (attribute value) + ... + ) + +There should be just one of these algorithms descriptions per file. The name +field is arbitrary: it is a Lisp symbol whose property list is used to save the +following attribute/value pairs. There are many attributes described below. +For more examples, see the .alg files in the trnsrc directory. + + Understanding what the attributes do is not easy, so here are three +recommendations for implementors. First, if there is an existing Nyquist +operator that is structurally similar to something you want to implement, make +a copy of the corresponding .alg file and work from there. In some cases, you +can merely rename the parameters and substitute a new inner loop. Second, read +the generated code, especially the generated inner loop. It may not all make +sense, but sometimes you can spot obvious errors and work your way back to the +error in the .alg file. Third, if you know where something bad is generated, +see if you can find where the code is generated. (The code generator files are +listed in init.lsp.) This code is poorly written and poorly documented, but in +some cases it is fairly straightforward to determine what attribute in the .alg +file is responsible for the erroneous output. + +I.6. Attributes + Here are the attributes used for code generation. Attributes and values may +be specified in any order. + +(NAME "string") specifies a base name for many identifiers. In particular, the + generated filenames will be string.c and string.h, and the + XLisp function generated will be snd-string. + +(ARGUMENTS arglist) + describes the arguments to be passed from XLisp. Arglist has + the form: (type1 name1) (type2 name2) ..., where type and name + are strings in double quotes, e.g. ("sound_type" "s") specifies + a SOUND parameter named s. Note that arglist is not surrounded + by parentheses. As seen in this example, the type names and + parameter names are C identifiers. Since the parameters are + passed in from XLisp, they must be chosen from a restricted + set. Valid type names are: "sound_type", "rate_type", + "double", "long", "string", and "LVAL". + +(STATE statelist) + describes additional state (variables) needed to perform the + computation. A statelist is similar to an arglist (see + ARGUMENTS above), and has the form: (type1 name1 init1 [TEMP]) + (type2 name2 init2 [TEMP]) .... The types and names are as in + arglist, and the "inits" are double-quoted initial values. + Initial values may be any C expression. State is initialized + in the order implied by statelist when the operation is first + called from XLisp. If TEMP is omitted the state is preserved + in a structure until the sound computation completes. + Otherwise, the state variable only exists at state + initialization time. + +(INNER-LOOP innerloop-code) + describes the inner loop, written as C code. The innerloop-code + is in double quotes, and may extend over multiple lines. To + make generated code extra-beautiful, prefix each line of + innerloop-code with 12 spaces. Temporary variables should not + be declared at the beginning of innerloop-code. Use the + INNER-LOOP-LOCALS attribute instead. Within innerloop-code, + each ARGUMENT of type sound_type must be referenced exactly one + time. If you need to use a signal value twice, assign it once + to a temporary and use the temporary twice. The inner loop + must also assign one time to the psuedo-variable output. The + model here is that the name of a sound argument denotes the + value of the corresponding signal at the current output sample + time. The inner loop code will be called once for each output + sample. In practice, the code generator will substitute some + expression for each signal name. For example, prod.alg + specifies + + (INNER-LOOP "output = s1 * s2") + + (s1 and s2 are ARGUMENTS.) This expands to the following inner + loop in prod.c: + + *out_ptr_reg++ = *s1_ptr_reg++ * *s2_ptr_reg++; + + In cases where arguments have different sample rates, sample + interpolation is in-lined, and the expressions can get very + complex. The translator is currently very simple-minded about + substituting access code in the place of parameter names, and + this is a frequent source of bugs. Simple string substitution + is performed, so you must not use a parameter or state name + that is a substring of another. For example, if two sound + parameters were named s and s2, the translator might substitute + for ``s'' in two places rather than one. If this problem + occurs, you will almost certainly get a C compiler syntax + error. The fix is to use ``more unique'' parameter and state + variable names. + +(INNER-LOOP-LOCALS "innerloop-code") + The innerloop-code contains C declarations of local variables + set and referenced in the inner loop. + +(SAMPLE-RATE "expr") + specifies the output sample rate; expr can be any C expression, + including a parameter from the ARGUMENTS list. You can also + write (SAMPLE-RATE (MAX name1 name2 ...)) where names are + unquoted names of arguments. + +(SUPPORT-HEADER "c-code") + specifies arbitrary C code to be inserted in the generated .h + file. The code typically contains auxiliarly function + declarations and definitions of constants. + +(SUPPORT-FUNCTIONS "c-code") + specifies arbitrary C code to be inserted in the generated .c + file. The code typically contains auxiliarly functions and + definitions of constants. + +(FINALIZATION "c-code") + specifies code to execute when the sound has been fully + computed and the state variables are about to be decallocated. + This is the place to deallocate buffer memory, etc. + +(CONSTANT "name1" "name2" ...) + specifies state variables that do not change value in the inner + loop. The values of state variables are loaded into registers + before entering the inner loop so that access will be fast + within the loop. On exiting the inner loop, the final register + values are preserved in a ``suspension'' structure. If state + values do not change in the inner loop, this CONSTANT + declaration can eliminate the overhead of storing these + registers. + +(START spec) specifies when the output sound should start (a sound is zero + and no processing is done before the start time). The spec can + take several forms: (MIN name1 name2 ...) means the start time + is the minimum of the start times of input signals name1, + name2, .... Note that these names are not quoted. + +(TERMINATE spec) + specifies when the output sound terminates (a sound is zero + after this termination time and no more samples are computed). + The spec can take several forms: (MIN name1 name2 ...) means + the terminate time is the minimum of the terminate times of + input arguments name1, name2, .... Note that these names are + not quoted. To terminate at the time of a single argument s1, + specify (MIN s1). To terminate after a specific duration, use + (AFTER "c-expr"), where c-expr is a C variable or expression. + To terminate at a particular time, use (AT "c-expr"). spec may + also be COMPUTED, which means to use the maximum sample rate of + any input signal. + +(LOGICAL-STOP spec) + specifies the logical stop time of the output sound. This spec + is just like the one for TERMINATE. If no LOGICAL-STOP + attribute is present, the logical stop will coincide with the + terminate time. + +(ALWAYS-SCALE name1 name2 ...) + says that the named sound arguments (not in quotes) should + always be multiplied by a scale factor. This is a space-time + tradeoff. When Nyquist sounds are scaled, the scale factor is + merely stored in a structure. It is the responsibility of the + user of the samples to actually scale them (unless the scale + factor is exactly 1.0). The default is to generate code with + and without scaling and to select the appropriate code at run + N + time. If there are N signal inputs, this will generate 2 + versions of the code. To avoid this code explosion, use the + ALWAYS-SCALE attribute. + +(INLINE-INTERPOLATION T) + specifies that sample rate interpolation should be performed + in-line in the inner loop. There are two forms of sample rate + interpolation. One is intended for use when the rate change is + large and many points will be interpolated. This form uses a + divide instruction and some setup at the low sample rate, but + the inner loop overhead is just an add. The other form, + intended for less drastic sample rate changes, performs + interpolation with 2 multiplies and several adds per sample at + the high sample rate. Nyquist generates various inner loops + and selects the appropriate one at run-time. If + INLINE-INTERPOLATION is not set, then much less code is + generated and interpolation is performed as necessary by + instantiating a separate signal processing operation. + +(STEP-FUNCTION name1 name2 ...) + Normally all argument signals are linearly interpolated to the + output sample rate. The linear interpolation can be turned off + with this attribute. This is used, for example, in Nyquist + variable filters so that filter coefficients are computed at + low sample rates. In fact, this attribute was added for the + special case of filters. + +(DEPENDS spec1 spec2 ...) + Specifies dependencies. This attribute was also introduced to + handle the case of filter coefficients (but may have other + applications.) Use it when a state variable is a function of a + potentially low-sample-rate input where the input is in the + STEP-FUNCTION list. Consider a filter coefficient that depends + upon an input signal such as bandwidth. In this case, you want + to compute the filter coefficient only when the input signal + changes rather than every output sample, since output may occur + at a much higher sample rate. A spec is of the form + + ("name" "arg" "expr" [TEMP "type"]) + + which is interpreted as follows: name depends upon arg; when + arg changes, recompute expr and assign it to name. The name + must be declared as a STATE variable unless TEMP is present, in + which case name is not preserved and is used only to compute + other state. Variables are updated in the order of the DEPENDS + list. + +(FORCE-INTO-REGISTER name1 name2 ...) + causes name1, name2, ... to be loaded into registers before + entering the inner loop. If the inner loop references a state + variable or argument, this happens automatically. Use this + attribute only if references are ``hidden'' in a #define'd + macro or referenced in a DEPENDS specification. + +(NOT-REGISTER name1 name2 ...) + specifies state and arguments that should not be loaded into + registers before entering an inner loop. This is sometimes an + optimization for infrequently accessed state. + +(NOT-IN-INNER-LOOP "name1" "name2" ...) + says that certain arguments are not used in the inner loop. + Nyquist assumes all arguments are used in the inner loop, so + specify them here if not. For example, tables are passed into + functions as sounds, but these sounds are not read + sample-by-sample in the inner loop, so they should be listed + here. + +(MAINTAIN ("name1" "expr1") ("name2" "expr2") ... ) + Sometimes the IBM XLC compiler generates better loop code if a + variable referenced in the loop is not referenced outside of + the loop after the loop exit. Technically, optimization is + better when variables are dead upon loop exit. Sometimes, there + is an efficient way to compute the final value of a state + variable without actually referencing it, in which case the + variable and the computation method are given as a pair in the + MAINTAIN attribute. This suppresses a store of the value of + the named variable, making it a dead variable. Where the store + would have been, the expression is computed and assigned to the + named variable. See partial.alg for an example. This + optimization is never necessary and is only for fine-tuning. + +(LINEAR name1 name2 ...) + specifies that named arguments (without quotes) are linear with + respect to the output. What this really means is that it is + numerically OK to eliminate a scale factor from the named + argument and store it in the output sound descriptor, avoiding + a potential multiply in this inner loop. For example, both + arguments to snd-prod (signal multiplication) are ``linear.'' + The inner loop has a single multiplication operator to multiply + samples vs. a potential 3 multiplies if each sample were also + scaled. To handle scale factors on the input signals, the + scale factors are automatically multiplied and the product + becomes the scale factor of the resulting output. (This + effectively ``passes the buck'' to some other, or perhaps more + than one, signal processing function, which is not always + optimal. On the other hand, it works great if you multiply a + number of scaled signals together: all the scale factors are + ultimately handled with a single multiply.) + +(INTERNAL-SCALING name1 name2 ...) + indicates that scaling is handled in code that is hidden from + the code generator for name1, name2, ..., which are sound + arguments. Although it is the responsibility of the reader of + samples to apply any given scale factor, sometimes scaling can + be had for free. For example, the snd-recip operation computes + the reciprocal of the input samples by peforming a division. + The simple approach would be to specify an inner loop of output + = 1.0/s1, where s1 is the input. With scaling, this would + generate an inner loop something like this: + + *output++ = 1.0 / (s1_scale_factor * *s1++); + + but a much better approach would be the following: + + *output++ = my_scale_factor / *s1++ + + where my_scale_factor is initialized to 1.0 / s1->scale. + Working backward from the desired inner loop to the .alg inner + loop specification, a first attempt might be to specify: + + (INNER-LOOP "output = my_scale_factor / s1") + + but this will generate the following: + + *output++=my_scale_factor/(s1_scale_factor * *s1++); + + Since the code generator does not know that scaling is handled + elsewhere, the scaling is done twice! The solution is to put + s1 in the INTERNAL-SCALING list, which essentially means ``I've + already incorporated scaling into the algorithm, so suppress + the multiplication by a scale factor.'' + +(COMMUTATIVE (name1 name2 ...)) + specifies that the results will not be affected by + interchanging any of the listed arguments. When arguments are + commutative, Nyquist rearranges them at run-time into + decreasing order of sample rates. If interpolation is in-line, + this can dramatically reduce the amount of code generated to + handle all the different cases. The prime example is prod.alg. + +(TYPE-CHECK "code") + specifies checking code to be inserted after argument type + checking at initialization time. See downproto.alg for an + example where a check is made to guarantee that the output + sample rate is not greater than the input sample rate. + Otherwise an error is raised. + +I.7. Generated Names + The resulting .c file defines a number of procedures. The procedures that do +actual sample computation are named something like name_interp-spec_FETCH, +where name is the NAME attribute from the .alg file, and interp-spec is an +interpolation specification composed of a string of the following letters: n, +s, i, and r. One letter corresponds to each sound argument, indicating no +interpolation (r), scaling only (s), ordinary linear interpolation with scaling +(i), and ramp (incremental) interpolation with scaling (r). The code generator +determines all the combinations of n, s, i, and r that are necessary and +generates a separate fetch function for each. + + Another function is name_toss_fetch, which is called when sounds are not +time-aligned and some initial samples must be discarded from one or more +inputs. + + The function that creates a sound is snd_make_name. This is where state +allocation and initialization takes place. The proper fetch function is +selected based on the sample rates and scale factors of the sound arguments, +and a sound_type is returned. + + Since Nyquist is a functional language, sound operations are not normally +allowed to modify their arguments through side effects, but even reading +samples from a sound_type causes side effects. To hide these from the Nyquist +programmer, sound_type arguments are first copied (this only copies a small +structure. The samples themselves are on a shared list). The function snd_name +performs the necessary copies and calls snd_make_name. It is the snd_name +function that is called by XLisp. The XLisp name for the function is SND-NAME. +Notice that the underscore in C is converted to a dash in XLisp. Also, XLisp +converts identifiers to upper case when they are read, so normally, you would +type snd-name to call the function. + +I.8. Scalar Arguments + If you want the option of passing either a number (scalar) or a signal as one +of the arguments, you have two choices, neither of which is automated. Choice +1 is to coerce the constant into a signal from within XLisp. The naming +convention would be to DEFUN a new function named NAME or S-NAME for ordinary +use. The NAME function tests the arguments using XLisp functions such as +TYPE-OF, NUMBERP, and SOUNDP. Any number is converted to a SOUND, e.g. using +CONST. Then SND-NAME is called with all sound arguments. The disadvantage of +this scheme is that scalars are expanded into a sample stream, which is slower +than having a special inner loop where the scalar is simply kept in a register, +avoiding loads, stores, and addressing overhead. + + Choice 2 is to generate a different sound operator for each case. The naming +convention here is to append a string of c's and v's, indicating constant +(scalar) or variable (signal) inputs. For example, the reson operator comes in +four variations: reson, resoncv, resonvc, and resonvv. The resonvc version +implements a resonating filter with a variable center frequency (a sound type) +and a constant bandwidth (a FLONUM). The RESON function in Nyquist is an +ordinary Lisp function that checks types and calls one of SND-RESON, +SND-RESONCV, SND-RESONVC, or SND-RESONVV. + + Since each of these SND- functions performs further selection of +implementation based on sample rates and the need for scaling, there are 25 +different functions for computing RESON! So far, however, Nyquist is smaller +than Common Lisp and it's about half the size of Microsoft Word. Hopefully, +exponential growth in memory density will outpace linear (as a function of +programming effort) growth of Nyquist. +II. Open Sound Control and Nyquist + Open Sound Control (OSC) is a simple protocol for communicating music control +parameters between software applications and across networks. For more +information, see http://www.cnmat.berkeley.edu/OpenSoundControl/. The Nyquist +implementation of Open Sound Control is simple: an array of floats can be set +by OSC messages and read by Nyquist functions. That is about all there is to +it. + + Note: Open Sound Control must be enabled by calling osc-enable(t). If this +fails under Windows, see the installation instructions in sys/win/README.txt +regarding SystemRoot. + + To control something in (near) real-time, you need to access a slider value +as if it a signal, or more properly, a Nyquist SOUND type. The function +snd-slider, described in Section 7.6.1, takes a slider number and returns a +SOUND type representing the current value of the slider. To fully understand +this function, you need to know something about how Nyquist is actually +computing sounds. + + Sounds are normally computed on demand. So the result returned by snd-slider +does not immediately compute any samples. Samples are only computed when +something tries to use this signal. At that time, the slider value is read. +Normally, if the slider is used to control a sound, you will hear changes in +the sound pretty soon after the slider value changes. However, one thing that +can interfere with this is that SOUND samples are computed in blocks of about +1000 samples. When the slider value is read, the same value is used to fill a +block of 1000 samples, so even if the sample rate is 44,100 Hz, the effective +slider sample rate is 44,100/1000, or 44.1 Hz. If you give the slider a very +low sample rate, say 1000, then slider value changes will only be noticed by +Nyquist approximately once per second. For this reason, you should normally use +the audio sample rate (typically 44,100 Hz) for the rate of the snd-slider +output SOUND. (Yes, this is terribly wasteful to represent each slider value +with 1000 samples, but Nyquist was not designed for low-latency computation, +and this is an expedient work-around.) + + In addition to reading sliders as continually changing SOUNDs, you can get +the slider value as a Lisp FLONUM (a floating point number) using +get-slider-value, described in Section 7.6.1. This might be useful if you are +computing a sequence of many notes (or other sound events) and want to apply +the current slider value to the whole note or sound event. + + Note that if you store the value returned by snd-slider in a variable, you +will capture the history of the slider changes. This will take a lot of memory, +so be careful. + + Suppose you write a simple expression such as (hzosc (mult 1000 (snd-slider 0 +...))) (or in SAL, hzosc(1000 * snd-slider(0 ...))) to control an oscillator +frequency with a slider. How long does this sound last? The duration of hzosc +is the duration of the frequency control, so what is the duration of a slider? +To avoid infinitely long signals, you must specify a duration as one of the +parameters of snd-slider. + + You might be thinking, what if I just want to tell the slider when to stop? +At present, you cannot do that, but in the future there should be a function +that stops when its input goes to zero. Then, moving a slider to zero could end +the signal (and if you multiplied a complex sound by one of these ending +functions, everything in the sound would end and be garbage collected). + + Another thing you might want to do with interactive control is start some +sound. The trigger function computes an instance of a behavior each time an +input SOUND goes from zero to greater-than-zero. This could be used, for +example, to create a sequence of notes. + + The snd-slider function has some parameters that may be unfamiliar. The +second parameter, t0, is the starting time of the sound. This should normally +be local-to-global(0), an expression that computes the instantiation time of +the current expression. This will often be zero, but if you call snd-slider +from inside a seq or seq-rep, the starting time may not be zero. + + The srate parameter is the sample rate to return. This should normally be the +audio sample rate you are working with, which is typically *default-sound- +srate*. + +II.1. Sending Open Sound Control Messages + A variety of programs support OSC. The only OSC message interpreted by +Nyquist has an address of /slider, and two parameters: an integer slider number +and a float value, nominally from 0.0 to 1.0. + + Two small programs are included in the Nyquist distribution for sending OSC +messages. (Both can be found in the same directory as the nyquist executable.) +The first one, osc-test-client sends a sequence of messages that just cause +slider 0 to ramp slowly up and down. If you run this on a command line, you can +use "?" or "h" to get help information. There is an interactive mode that lets +you send each OSC message by typing RETURN. + +II.2. The ser-to-osc Program + The second program is ser-to-osc, a program that reads serial input (for +example from a PIC-based microcontroller) and sends OSC messages. Run this +command-line program from a shell (a terminal window under OS X or Linux; use +the CMD program under Windows). You must name the serial input device on the +command line, e.g. under OS X, you might run: + + ./ser-to-osc /dev/tty.usbserial-0000103D + +(Note that the program name is preceded by ``./". This tells the shell exactly +where to find the executable program in case the current directory is not on +the search path for executable programs.) Under Windows, you might run: + + ser-to-osc com4 + +(Note that you do not type ``./'' in front of a windows program.) + + To use ser-to-osc, you will have to find the serial device. On the Macintosh +and Linux, try the following: + + ls /dev/*usb* + +This will list all serial devices with ``usb'' in their names. Probably, one +will be a name similar to /dev/tty.usbserial-0000103D. The ser-to-osc program +will echo data that it receives, so you should know if things are working +correctly. + + Under Windows, open Control Panel from the Start menu, and open the System +control panel. Select the Hardware tab and click the Device Manager button. +Look in the device list under Ports (COM & LPT). When you plug in your serial +or USB device, you should see a new entry appear, e.g. COM4. This is the device +name you need. + + The format for the serial input is: any non-whitespace character(s), a slider +number, a slider value, and a newline (control-j or ASCII 0x0A). These fields +need to be separated by tabs or spaces. An optional carriage return (control-m +or ASCII 0x0D) preceding the ASCII 0x0A is ignored. The slider number should be +in decimal, and theh slider value is a decimal number from 0 to 255. This is +scaled to the range 0.0 to 1.0 (so an input of 255 translates to 1.0). + + There is a simple test program in demos/osc-test.lsp you can run to try out +control with Open Sound Control. There are two examples in that file. One uses +snd-slider to control the frequency of an oscillator. The other uses +get-slider-value to control the pitch of grains in a granular synthesis +process. +III. Intgen + This documentation describes Intgen, a program for generating XLISP to C +interfaces. Intgen works by scanning .h files with special comments in them. +Intgen builds stubs that implement XLISP SUBR's. When the SUBR is called, +arguments are type-checked and passed to the C routine declared in the .h file. +Results are converted into the appropriate XLISP type and returned to the +calling XLISP function. Intgen lets you add C functions into the XLISP +environment with very little effort. + + The interface generator will take as command-line input: + + - the name of the .c file to generate (do not include the .c extension; + e.g. write xlexten, not xlexten.c); + + - a list of .h files. + +Alternatively, the command line may specify a command file from which to read +file names. The command file name should be preceded by "@", for example: + + intgen @sndfns.cl + +reads sndfns.cl to get the command-line input. Only one level of indirection +is allowed. + + The output is: + + - a single .c file with one SUBR defined for each designated routine in + a .h file. + + - a .h file that declares each new C routine. E.g. if the .c file is + named xlexten.c, this file will be named xlextendefs.h; + + - a .h file that extends the SUBR table used by Xlisp. E.g. if the .c + file is named xlexten.c, then this file is named xlextenptrs.h; + + - a .lsp file with lisp initialization expressions copied from the .h + files. This file is only generated if at least one initialization + expression is encountered. + + For example, the command line + + intgen seint ~setypes.h access.h + +generates the file seint.c, using declarations in setypes.h and access.h. +Normally, the .h files are included by the generated file using #include +commands. A ~ before a file means do not include the .h file. (This may be +useful if you extend xlisp.h, which will be included anyway). Also generated +will be setintdefs.h and seintptrs.h. + + + +III.0.1. Extending Xlisp + Any number of .h files may be named on the command line to Intgen, and Intgen +will make a single .c file with interface routines for all of the .h files. On +the other hand, it is not necessary to put all of the extensions to Xlisp into +a single interface file. For example, you can run Intgen once to build +interfaces to window manager routines, and again to build interfaces to a new +data type. Both interfaces can be linked into Xlisp. + + To use the generated files, you must compile the .c files and link them with +all of the standard Xlisp object files. In addition, you must edit the file +localdefs.h to contain an #include for each *defs.h file, and edit the file +localptrs.h to include each *ptrs.h file. For example, suppose you run Intgen +to build soundint.c, fugueint.c, and tableint.c. You would then edit +localdefs.h to contain the following: + + #include "soundintdefs.h" + #include "fugueintdefs.h" + #include "tableintdefs.h" + +and edit localptrs.h to contain: + + #include "soundintptrs.h" + #include "fugueintptrs.h" + #include "tableintptrs.h" + +These localdefs.h and localptrs.h files are in turn included by xlftab.c which +is where Xlisp builds a table of SUBRs. + + To summarize, building an interface requires just a few simple steps: + + - Write C code to be called by Xlisp interface routines. This C code + does the real work, and in most cases is completely independent of + Xlisp. + + - Add comments to .h files to tell Intgen which routines to build + interfaces to, and to specify the types of the arguments. + + - Run Intgen to build interface routines. + + - Edit localptrs.h and localdefs.h to include generated .h files. + + - Compile and link Xlisp, including the new C code. + +III.1. Header file format + Each routine to be interfaced with Xlisp must be declared as follows: + + type-name routine-name(); /* LISP: (func-name type type ...) */ + 1 2 +The comment may be on the line following the declaration, but the declaration +and the comment must each be on no more than one line. The characters LISP: at +the beginning of the comment mark routines to put in the interface. The +comment also gives the type and number of arguments. The function, when +accessed from lisp will be known as func-name, which need not bear any +relationship to routine-name. By convention, underscores in the C routine-name +should be converted to dashes in func-name, and func-name should be in all +capitals. None of this is enforced or automated though. + + Legal type_names are: + +LVAL returns an Xlisp datum. + +atom_type equivalent to LVAL, but the result is expected to be an atom. + +value_type a value as used in Dannenberg's score editor. + +event_type an event as used in Dannenberg's score editor. + +int interface will convert int to Xlisp FIXNUM. + +boolean interface will convert int to T or nil. + +float or double interface converts to FLONUM. + +char * or string or string_type + interface converts to STRING. The result string will be copied + into the XLISP heap. + +void interface will return nil. + + It is easy to extend this list. Any unrecognized type will be coerced to an +int and then returned as a FIXNUM, and a warning will be issued. + + The ``*'' after char must be followed by routine-name with no intervening +space. + + Parameter types may be any of the following: + +FIXNUM C routine expects an int. + +FLONUM or FLOAT C routine expects a double. + +STRING C routine expects char *, the string is not copied. + +VALUE C routine expects a value_type. (Not applicable to Fugue.) + +EVENT C routine expects an event_type. (Not applicable to Fugue.) + +ANY C routine expects LVAL. + +ATOM C routine expects LVAL which is a lisp atom. + +FILE C routine expects FILE *. + +SOUND C routine expects a SoundPtr. + + Any of these may be followed by ``*'': FIXNUM*, FLONUM*, STRING*, ANY*, +FILE*, indicating C routine expects int *, double *, char **, LVAL *, or FILE +** . This is basically a mechanism for returning more than one value, not a +mechanism for clobbering XLisp values. In this spirit, the interface copies +the value (an int, double, char *, LVAL, or FILE *) to a local variable and +passes the address of that variable to the C routine. On return, a list of +resulting ``*'' parameters is constructed and bound to the global XLisp symbol +*RSLT*. (Strings are copied.) If the C routine is void, then the result list +is also returned by the corresponding XLisp function. + + Note 1: this does not support C routines like strcpy that modify strings, +because the C routine gets a pointer to the string in the XLisp heap. However, +you can always add an intermediate routine that allocates space and then calls +strcpy, or whatever. + + Note 2: it follows that a new XLisp STRING will be created for each STRING* +parameter. + + Note 3: putting results on a (global!) symbol seems a bit unstructured, but +note that one could write a multiple-value binding macro that hides this +ugliness from the user if desired. In practice, I find that pulling the extra +result values from *RSLT* when needed is perfectly acceptable. + + For parameters that are result values only, the character ``^'' may be +substituted for ``*''. In this case, the parameter is not to be passed in the +XLisp calling site. However, the address of an initialized local variable of +the given type is passed to the corresponding C function, and the resulting +value is passed back through *RSLT* as ordinary result parameter as described +above. The local variables are initialized to zero or NULL. + +III.2. Using #define'd macros + If a comment of the form: + + /* LISP: type-name (routine-name-2 type-1 type-2 ...) */ + +appears on a line by itself and there was a #define on the previous line, then +the preceding #define is treated as a C routine, e.g. + + #define leftshift(val, count) ((val) << (count)) + /* LISP: int (LOGSHIFT INT INT) */ + +will implement the LeLisp function LOGSHIFT. + + The type-name following ``LISP:'' should have no spaces, e.g. use ANY*, not +ANY *. + +III.3. Lisp Include Files + Include files often define constants that we would like to have around in the +Lisp world, but which are easier to initialize just by loading a text file. +Therefore, a comment of the form: + + /* LISP-SRC: (any lisp expression) */ + +will cause Intgen to open a file name.lsp and append + + (any lisp expression) + +to name.lsp, where name is the interface name passed on the command line. If +none of the include files examined have comments of this form, then no name.lsp +file is generated. Note: the LISP-SRC comment must be on a new line. + +III.4. Example + This file was used for testing Intgen. It uses a trick (ok, it's a hack) to +interface to a standard library macro (tolower). Since tolower is already +defined, the macro ToLower is defined just to give Intgen a name to call. Two +other routines, strlen and tough, are interfaced as well. + + /* igtest.h -- test interface for intgen */ + + #define ToLower(c) tolower(c) + /* LISP: int (TOLOWER FIXNUM) */ + + int strlen(); /* LISP: (STRLEN STRING) */ + + void tough(); + /* LISP: (TOUGH FIXNUM* FLONUM* STRING ANY FIXNUM) */ + +III.5. More Details + Intgen has some compiler switches to enable/disable the use of certain types, +including VALUE and EVENT types used by Dannenberg's score editing work, the +SOUND type used by Fugue, and DEXT and SEXT types added for Dale Amon. +Enabling all of these is not likely to cause problems, and the chances of an +accidental use of these types getting through the compiler and linker seems +very small. +IV. XLISP: An Object-oriented Lisp + + Version 2.0 + + February 6, 1988 + + by + David Michael Betz + 127 Taylor Road + Peterborough, NH 03458 + + Copyright (c) 1988, by David Michael Betz + All Rights Reserved + Permission is granted for unrestricted non-commercial use +IV.1. Introduction + XLISP is an experimental programming language combining some of the features +of Common Lisp with an object-oriented extension capability. It was +implemented to allow experimentation with object-oriented programming on small +computers. + + Implementations of XLISP run on virtually every operating system. XLISP is +completely written in the programming language C and is easily extended with +user written built-in functions and classes. It is available in source form to +non-commercial users. + + Many Common Lisp functions are built into XLISP. In addition, XLISP defines +the objects Object and Class as primitives. Object is the only class that has +no superclass and hence is the root of the class hierarchy tree. Class is the +class of which all classes are instances (it is the only object that is an +instance of itself). + + This document is a brief description of XLISP. It assumes some knowledge of +LISP and some understanding of the concepts of object-oriented programming. + + I recommend the book Lisp by Winston and Horn and published by Addison Wesley +for learning Lisp. The first edition of this book is based on MacLisp and the +second edition is based on Common Lisp. + + You will probably also need a copy of Common Lisp: The Language by Guy +L. Steele, Jr., published by Digital Press to use as a reference for some of +the Common Lisp functions that are described only briefly in this document. + +IV.2. A Note From The Author + If you have any problems with XLISP, feel free to contact me [me being David +Betz - RBD] for help or advice. Please remember that since XLISP is available +in source form in a high level language, many users [e.g. that Dannenberg +fellow - RBD] have been making versions available on a variety of machines. If +you call to report a problem with a specific version, I may not be able to help +you if that version runs on a machine to which I don't have access. Please +have the version number of the version that you are running readily accessible +before calling me. + + If you find a bug in XLISP, first try to fix the bug yourself using the +source code provided. If you are successful in fixing the bug, send the bug +report along with the fix to me. If you don't have access to a C compiler or +are unable to fix a bug, please send the bug report to me and I'll try to fix +it. + + Any suggestions for improvements will be welcomed. Feel free to extend the +language in whatever way suits your needs. However, PLEASE DO NOT RELEASE +ENHANCED VERSIONS WITHOUT CHECKING WITH ME FIRST!! I would like to be the +clearing house for new features added to XLISP. If you want to add features +for your own personal use, go ahead. But, if you want to distribute your +enhanced version, contact me first. Please remember that the goal of XLISP is +to provide a language to learn and experiment with LISP and object-oriented +programming on small computers. I don't want it to get so big that it requires +megabytes of memory to run. + +IV.3. XLISP Command Loop + When XLISP is started, it first tries to load the workspace xlisp.wks from +the current directory. If that file doesn't exist, XLISP builds an initial +workspace, empty except for the built-in functions and symbols. + + Then XLISP attempts to load init.lsp from the current directory. It then +loads any files named as parameters on the command line (after appending .lsp +to their names). + + XLISP then issues the following prompt: + + > + +This indicates that XLISP is waiting for an expression to be typed. + + When a complete expression has been entered, XLISP attempts to evaluate that +expression. If the expression evaluates successfully, XLISP prints the result +and then returns to the initial prompt waiting for another expression to be +typed. + +IV.4. Special Characters + When XLISP is running from a console, some control characters invoke +operations: + + - Backspace and Delete characters erase the previous character on the + input line (if any). + + - Control-U erases the entire input line. + + - Control-C executes the TOP-LEVEL function. + + - Control-G executes the CLEAN-UP function. + + - Control-P executes the CONTINUE function. + + - Control-B stops execution and enters the break command loop. + Execution can be continued by typing Control-P or (CONTINUE). + + - Control-E turns on character echoing (Linux and Mac OS X only). + + - Control-F turns off character echoing (Linux and Mac OS X only). + + - Control-T evaluates the INFO function. + +IV.5. Break Command Loop + When XLISP encounters an error while evaluating an expression, it attempts to +handle the error in the following way: + + If the symbol *breakenable* is true, the message corresponding to the error +is printed. If the error is correctable, the correction message is printed. + + If the symbol *tracenable* is true, a trace back is printed. The number of +entries printed depends on the value of the symbol *tracelimit*. If this +symbol is set to something other than a number, the entire trace back stack is +printed. + + XLISP then enters a read/eval/print loop to allow the user to examine the +state of the interpreter in the context of the error. This loop differs from +the normal top-level read/eval/print loop in that if the user invokes the +function continue, XLISP will continue from a correctable error. If the user +invokes the function clean-up, XLISP will abort the break loop and return to +the top level or the next lower numbered break loop. When in a break loop, +XLISP prefixes the break level to the normal prompt. + + If the symbol *breakenable* is nil, XLISP looks for a surrounding errset +function. If one is found, XLISP examines the value of the print flag. If +this flag is true, the error message is printed. In any case, XLISP causes the +errset function call to return nil. + + If there is no surrounding errset function, XLISP prints the error message +and returns to the top level. + +IV.6. Data Types + There are several different data types available to XLISP programmers. + + - lists + + - symbols + + - strings + + - integers + + - characters + + - floats + + - objects + + - arrays + + - streams + + - subrs (built-in functions) + + - fsubrs (special forms) + + - closures (user defined functions) + +IV.7. The Evaluator + The process of evaluation in XLISP: + + - Strings, integers, characters, floats, objects, arrays, streams, + subrs, fsubrs and closures evaluate to themselves. + + - Symbols act as variables and are evaluated by retrieving the value + associated with their current binding. + + - Lists are evaluated by examining the first element of the list and + then taking one of the following actions: + + * If it is a symbol, the functional binding of the symbol is + retrieved. + + * If it is a lambda expression, a closure is constructed for the + function described by the lambda expression. + + * If it is a subr, fsubr or closure, it stands for itself. + + * Any other value is an error. + + Then, the value produced by the previous step is examined: + + * If it is a subr or closure, the remaining list elements are + evaluated and the subr or closure is called with these evaluated + expressions as arguments. + + * If it is an fsubr, the fsubr is called using the remaining list + elements as arguments (unevaluated). + + * If it is a macro, the macro is expanded using the remaining list + elements as arguments (unevaluated). The macro expansion is + then evaluated in place of the original macro call. + +IV.8. Lexical Conventions + The following conventions must be followed when entering XLISP programs: + + Comments in XLISP code begin with a semi-colon character and continue to the +end of the line. + + Symbol names in XLISP can consist of any sequence of non-blank printable +characters except the following: + + ( ) ' ` , " ; + +Uppercase and lowercase characters are not distinguished within symbol names. +All lowercase characters are mapped to uppercase on input. + + Integer literals consist of a sequence of digits optionally beginning with a ++ or -. The range of values an integer can represent is limited by the size of +a C long on the machine on which XLISP is running. + + Floating point literals consist of a sequence of digits optionally beginning +with a + or - and including an embedded decimal point. The range of values a +floating point number can represent is limited by the size of a C float (double +on machines with 32 bit addresses) on the machine on which XLISP is running. + + Literal strings are sequences of characters surrounded by double quotes. +Within quoted strings the ``\'' character is used to allow non-printable +characters to be included. The codes recognized are: + + - \\ means the character ``\'' + + - \n means newline + + - \t means tab + + - \r means return + + - \f means form feed + + - \nnn means the character whose octal code is nnn + +IV.9. Readtables + The behavior of the reader is controlled by a data structure called a +readtable. The reader uses the symbol *readtable* to locate the current +readtable. This table controls the interpretation of input characters. It is +an array with 128 entries, one for each of the ASCII character codes. Each +entry contains one of the following things: + + - NIL M Indicating an invalid character + + - :CONSTITUENT M Indicating a symbol constituent + + - :WHITE-SPACE M Indicating a whitespace character + + - (:TMACRO . fun) M Terminating readmacro + + - (:NMACRO . fun) M Non-terminating readmacro + + - :SESCAPE M Single escape character ('\') + + - :MESCAPE M Multiple escape character ('|') + + In the case of :TMACRO and :NMACRO, the fun component is a function. This +can either be a built-in readmacro function or a lambda expression. The +function should take two parameters. The first is the input stream and the +second is the character that caused the invocation of the readmacro. The +readmacro function should return NIL to indicate that the character should be +treated as white space or a value consed with NIL to indicate that the +readmacro should be treated as an occurence of the specified value. Of course, +the readmacro code is free to read additional characters from the input stream. + + XLISP defines several useful read macros: + + - ' == (quote ) + + - #' == (function ) + + - #(...) == an array of the specified expressions + + - #x == a hexadecimal number (0-9,A-F) + + - #o == an octal number (0-7) + + - #b == a binary number (0-1) + + - #\ == the ASCII code of the character + + - #| ... |# == a comment + + - #: == an uninterned symbol + + - ` == (backquote ) + + - , == (comma ) + + - ,@ == (comma-at ) + +IV.10. Lambda Lists + There are several forms in XLISP that require that a ``lambda list'' be +specified. A lambda list is a definition of the arguments accepted by a +function. There are four different types of arguments. + + The lambda list starts with required arguments. Required arguments must be +specified in every call to the function. + + The required arguments are followed by the &optional arguments. Optional +arguments may be provided or omitted in a call. An initialization expression +may be specified to provide a default value for an &optional argument if it is +omitted from a call. If no initialization expression is specified, an omitted +argument is initialized to NIL. It is also possible to provide the name of a +supplied-p variable that can be used to determine if a call provided a value +for the argument or if the initialization expression was used. If specified, +the supplied- p variable will be bound to T if a value was specified in the +call and NIL if the default value was used. + + The &optional arguments are followed by the &rest argument. The &rest +argument gets bound to the remainder of the argument list after the required +and &optional arguments have been removed. + + The &rest argument is followed by the &key arguments. When a keyword +argument is passed to a function, a pair of values appears in the argument +list. The first expression in the pair should evaluate to a keyword symbol (a +symbol that begins with a ``:''). The value of the second expression is the +value of the keyword argument. Like &optional arguments, &key arguments can +have initialization expressions and supplied-p variables. In addition, it is +possible to specify the keyword to be used in a function call. If no keyword +is specified, the keyword obtained by adding a ``:'' to the beginning of the +keyword argument symbol is used. In other words, if the keyword argument +symbol is foo, the keyword will be :foo. + + The &key arguments are followed by the &aux variables. These are local +variables that are bound during the evaluation of the function body. It is +possible to have initialization expressions for the &aux variables. + + Here is the complete syntax for lambda lists: + + (rarg... + [&optional [oarg | (oarg [init [svar]])]...] + [&rest rarg] + [&key + [karg | ([karg | (key karg)] [init [svar]])]... + &allow-other-keys] + [&aux + [aux | (aux [init])]...]) + + where: + + rarg is a required argument symbol + oarg is an &optional argument symbol + rarg is the &rest argument symbol + karg is a &key argument symbol + key is a keyword symbol + aux is an auxiliary variable symbol + init is an initialization expression + svar is a supplied-p variable symbol + +IV.11. Objects + Definitions: + + - selector M a symbol used to select an appropriate method + + - message M a selector and a list of actual arguments + + - method M the code that implements a message + +Since XLISP was created to provide a simple basis for experimenting with +object-oriented programming, one of the primitive data types included is +object. In XLISP, an object consists of a data structure containing a pointer +to the object's class as well as an array containing the values of the object's +instance variables. + + Officially, there is no way to see inside an object (look at the values of +its instance variables). The only way to communicate with an object is by +sending it a message. + + You can send a message to an object using the send function. This function +takes the object as its first argument, the message selector as its second +argument (which must be a symbol) and the message arguments as its remaining +arguments. + + The send function determines the class of the receiving object and attempts +to find a method corresponding to the message selector in the set of messages +defined for that class. If the message is not found in the object's class and +the class has a super-class, the search continues by looking at the messages +defined for the super-class. This process continues from one super-class to +the next until a method for the message is found. If no method is found, an +error occurs. + + When a method is found, the evaluator binds the receiving object to the +symbol self and evaluates the method using the remaining elements of the +original list as arguments to the method. These arguments are always evaluated +prior to being bound to their corresponding formal arguments. The result of +evaluating the method becomes the result of the expression. + + Within the body of a method, a message can be sent to the current object by +calling the (send self ...). The method lookup starts with the object's class +regardless of the class containing the current method. + + Sometimes it is desirable to invoke a general method in a superclass even +when it is overridden by a more specific method in a subclass. This can be +accomplished by calling send-super, which begins the method lookup in the +superclass of the class defining the current method rather than in the class of +the current object. + + The send-super function takes a selector as its first argument (which must be +a symbol) and the message arguments as its remaining arguments. Notice that +send-super can only be sent from within a method, and the target of the message +is always the current object (self). (send-super ...) is similar to (send self +...) except that method lookup begins in the superclass of the class containing +the current method rather than the class of the current object. +IV.12. The ``Object'' Class + Object M the top of the class hierarchy. + + Messages: +:show M show an object's instance variables. + returns M the object + +:class M return the class of an object + returns M the class of the object + +:isa class M test if object inherits from class + returns M t if object is an instance of class or a subclass of class, + otherwise nil + +:isnew M the default object initialization routine + returns M the object + +IV.13. The ``Class'' Class + Class M class of all object classes (including itself) + + Messages: +:new M create a new instance of a class + returns M the new class object + +:isnew ivars [cvars [super]] M initialize a new class + ivars M the list of instance variable symbols + cvars M the list of class variable symbols + super M the superclass (default is object) + returns M the new class object + +:answer msg fargs code M add a message to a class + msg M the message symbol + fargs M the formal argument list (lambda list) + code M a list of executable expressions + returns M the object + + When a new instance of a class is created by sending the message :new to an +existing class, the message :isnew followed by whatever parameters were passed +to the :new message is sent to the newly created object. + + When a new class is created by sending the :new message to the object Class, +an optional parameter may be specified indicating the superclass of the new +class. If this parameter is omitted, the new class will be a subclass of +Object. A class inherits all instance variables, class variables, and methods +from its super-class. + +IV.14. Profiling + The Xlisp 2.0 release has been extended with a profiling facility, which +counts how many times and where eval is executed. A separate count is +maintained for each named function, closure, or macro, and a count indicates an +eval in the immediately (lexically) enclosing named function, closure, or +macro. Thus, the count gives an indication of the amount of time spent in a +function, not counting nested function calls. The list of all functions +executed is maintained on the global *profile* variable. These functions in +turn have *profile* properties, which maintain the counts. The profile system +merely increments counters and puts symbols on the *profile* list. It is up to +the user to initialize data and gather results. Profiling is turned on or off +with the profile function. Unfortunately, methods cannot be profiled with this +facility. + +IV.15. Symbols + + - self M the current object (within a method context) + + - *obarray* M the object hash table + + - *standard-input* M the standard input stream + + - *standard-output* M the standard output stream + + - *error-output* M the error output stream + + - *trace-output* M the trace output stream + + - *debug-io* M the debug i/o stream + + - *breakenable* M flag controlling entering break loop on errors + + - *tracelist* M list of names of functions to trace + + - *tracenable* M enable trace back printout on errors + + - *tracelimit* M number of levels of trace back information + + - *evalhook* M user substitute for the evaluator function + + - *applyhook* M (not yet implemented) + + - *readtable* M the current readtable + + - *unbound* M indicator for unbound symbols + + - *gc-flag* M controls the printing of gc messages + + - *gc-hook* M function to call after garbage collection + + - *integer-format* M format for printing integers (``%d'' or ``%ld'') + + - *float-format* M format for printing floats (``%g'') + + - *print-case* M symbol output case (:upcase or :downcase) + + There are several symbols maintained by the read/eval/print loop. The +symbols +, ++, and +++ are bound to the most recent three input expressions. +The symbols *, ** and *** are bound to the most recent three results. The +symbol - is bound to the expression currently being evaluated. It becomes the +value of + at the end of the evaluation. + +IV.16. Evaluation Functions +eval(expr) [SAL] +(eval expr) [LISP] M evaluate an xlisp expression + expr M the expression to be evaluated + returns M the result of evaluating the expression + +apply(fun, args) [SAL] +(apply fun args) [LISP] M apply a function to a list of arguments + fun M the function to apply (or function symbol) + args M the argument list + returns M the result of applying the function to the arguments + +funcall(fun, arg...) [SAL] +(funcall fun arg...) [LISP] M call a function with arguments + fun M the function to call (or function symbol) + arg M arguments to pass to the function + returns M the result of calling the function with the arguments + +quote(expr) [SAL] +(quote expr) [LISP] M return an expression unevaluated + expr M the expression to be quoted (quoted) + returns M expr unevaluated + +function(expr) [SAL] +(function expr) [LISP] M get the functional interpretation + expr M the symbol or lambda expression (quoted) + returns M the functional interpretation + +backquote(expr) [SAL] +(backquote expr) [LISP] M fill in a template + expr M the template + returns M a copy of the template with comma and comma-at + expressions expanded + +lambda(args, expr...) [SAL] +(lambda args expr...) [LISP] M make a function closure + args M formal argument list (lambda list) (quoted) + expr M expressions of the function body + returns M the function closure + +get-lambda-expression(closure) [SAL] +(get-lambda-expression closure) [LISP] M get the lambda expression + closure M the closure + returns M the original lambda expression + +macroexpand(form) [SAL] +(macroexpand form) [LISP] M recursively expand macro calls + form M the form to expand + returns M the macro expansion + +macroexpand-1(form) [SAL] +(macroexpand-1 form) [LISP] M expand a macro call + form M the macro call form + returns M the macro expansion + + +IV.17. Symbol Functions +set(sym, expr) [SAL] +(set sym expr) [LISP] M set the value of a symbol + sym M the symbol being set + expr M the new value + returns M the new value + +setq([sym, expr]...) [SAL] +(setq [sym expr]...) [LISP] M set the value of a symbol + sym M the symbol being set (quoted) + expr M the new value + returns M the new value + +psetq([sym, expr]...) [SAL] +(psetq [sym expr]...) [LISP] M parallel version of setq + sym M the symbol being set (quoted) + expr M the new value + returns M the new value + +setf([place, expr]...) [SAL] +(setf [place expr]...) [LISP] M set the value of a field + place M the field specifier (quoted): + sym M set value of a symbol + (car expr) M set car of a cons node + (cdr expr) M set cdr of a cons node + (nth n expr) M set nth car of a list + (aref expr n) M set nth element of an array + (get sym prop) M set value of a property + (symbol-value sym) M set value of a symbol + (symbol-function sym) M set functional value of a symbol + (symbol-plist sym) M set property list of a symbol + expr M the new value + returns M the new value + +(defun sym fargs expr...) [LISP] M define a function +(defmacro sym fargs expr...) [LISP] M define a macro + sym M symbol being defined (quoted) + fargs M formal argument list (lambda list) (quoted) + expr M expressions constituting the body of the + function (quoted) returns M the function symbol + +gensym([tag]) [SAL] +(gensym [tag]) [LISP] M generate a symbol + tag M string or number + returns M the new symbol + +intern(pname) [SAL] +(intern pname) [LISP] M make an interned symbol + pname M the symbol's print name string + returns M the new symbol + +make-symbol(pname) [SAL] +(make-symbol pname) [LISP] M make an uninterned symbol + pname M the symbol's print name string + returns M the new symbol + +symbol-name(sym) [SAL] +(symbol-name sym) [LISP] M get the print name of a symbol + sym M the symbol + returns M the symbol's print name + +symbol-value(sym) [SAL] +(symbol-value sym) [LISP] M get the value of a symbol + sym M the symbol + returns M the symbol's value + +symbol-function(sym) [SAL] +(symbol-function sym) [LISP] M get the functional value of a symbol + sym M the symbol + returns M the symbol's functional value + +symbol-plist(sym) [SAL] +(symbol-plist sym) [LISP] M get the property list of a symbol + sym M the symbol + returns M the symbol's property list + +hash(sym, n) [SAL] +(hash sym n) [LISP] M compute the hash index for a symbol + sym M the symbol or string + n M the table size (integer) + returns M the hash index (integer) + + +IV.18. Property List Functions +get(sym, prop) [SAL] +(get sym prop) [LISP] M get the value of a property + sym M the symbol + prop M the property symbol + returns M the property value or nil + +putprop(sym, val, prop) [SAL] +(putprop sym val prop) [LISP] M put a property onto a property list + sym M the symbol + val M the property value + prop M the property symbol + returns M the property value + +remprop(sym, prop) [SAL] +(remprop sym prop) [LISP] M remove a property + sym M the symbol + prop M the property symbol + returns M nil + + +IV.19. Array Functions +aref(array, n) [SAL] +(aref array n) [LISP] M get the nth element of an array + array M the array + n M the array index (integer) + returns M the value of the array element + +make-array(size) [SAL] +(make-array size) [LISP] M make a new array + size M the size of the new array (integer) + returns M the new array + +vector(expr...) [SAL] +(vector expr...) [LISP] M make an initialized vector + expr M the vector elements + returns M the new vector + + +IV.20. List Functions +car(expr) [SAL] +(car expr) [LISP] M return the car of a list node + expr M the list node + returns M the car of the list node + +cdr(expr) [SAL] +(cdr expr) [LISP] M return the cdr of a list node + expr M the list node + returns M the cdr of the list node + +cxxr(expr) [SAL] +(cxxr expr) [LISP] M all cxxr combinations + +cxxxr(expr) [SAL] +(cxxxr expr) [LISP] M all cxxxr combinations + +cxxxxr(expr) [SAL] +(cxxxxr expr) [LISP] M all cxxxxr combinations + +first(expr) [SAL] +(first expr) [LISP] M a synonym for car + +second(expr) [SAL] +(second expr) [LISP] M a synonym for cadr + +third(expr) [SAL] +(third expr) [LISP] M a synonym for caddr + +fourth(expr) [SAL] +(fourth expr) [LISP] M a synonym for cadddr + +rest(expr) [SAL] +(rest expr) [LISP] M a synonym for cdr + +cons(expr1, expr2) [SAL] +(cons expr1 expr2) [LISP] M construct a new list node + expr1 M the car of the new list node + expr2 M the cdr of the new list node + returns M the new list node + +list(expr...) [SAL] +(list expr...) [LISP] M create a list of values + expr M expressions to be combined into a list + returns M the new list + +append(expr...) [SAL] +(append expr...) [LISP] M append lists + expr M lists whose elements are to be appended + returns M the new list + +reverse(expr) [SAL] +(reverse expr) [LISP] M reverse a list + expr M the list to reverse + returns M a new list in the reverse order + +last(list) [SAL] +(last list) [LISP] M return the last list node of a list + list M the list + returns M the last list node in the list + +member(expr, list, test: test, test-not: test-not) [SAL] +(member expr list &key :test :test-not) [LISP] M find an expression in a list + expr M the expression to find + list M the list to search + :test M the test function (defaults to eql) + :test-not M the test function (sense inverted) + returns M the remainder of the list starting with the expression + +assoc(expr, alist, test: test, test-not: test-not) [SAL] +(assoc expr alist &key :test :test-not) [LISP] M find an expression in an + a-list + expr M the expression to find + alist M the association list + :test M the test function (defaults to eql) + :test-not M the test function (sense inverted) + returns M the alist entry or nil + +remove(expr, list, test: test, test-not: test-not) [SAL] +(remove expr list &key :test :test-not) [LISP] M remove elements from a list + expr M the element to remove + list M the list + :test M the test function (defaults to eql) + :test-not M the test function (sense inverted) + returns M copy of list with matching expressions removed + +remove-if(test, list) [SAL] +(remove-if test list) [LISP] M remove elements that pass test + test M the test predicate + list M the list + returns M copy of list with matching elements removed + +remove-if-not(test, list) [SAL] +(remove-if-not test list) [LISP] M remove elements that fail test + test M the test predicate + list M the list + returns M copy of list with non-matching elements removed + +length(expr) [SAL] +(length expr) [LISP] M find the length of a list, vector or string + expr M the list, vector or string + returns M the length of the list, vector or string + +nth(n, list) [SAL] +(nth n list) [LISP] M return the nth element of a list + n M the number of the element to return (zero origin) + list M the list + returns M the nth element or nil if the list isn't that long + +nthcdr(n, list) [SAL] +(nthcdr n list) [LISP] M return the nth cdr of a list + n M the number of the element to return (zero origin) + list M the list + returns M the nth cdr or nil if the list isn't that long + +mapc(fcn, list1, list...) [SAL] +(mapc fcn list1 list...) [LISP] M apply function to successive cars + fcn M the function or function name + listn M a list for each argument of the function + returns M the first list of arguments + +mapcar(fcn, list1, list...) [SAL] +(mapcar fcn list1 list...) [LISP] M apply function to successive cars + fcn M the function or function name + listn M a list for each argument of the function + returns M a list of the values returned + +mapl(fcn, list1, list...) [SAL] +(mapl fcn list1 list...) [LISP] M apply function to successive cdrs + fcn M the function or function name + listn M a list for each argument of the function + returns M the first list of arguments + +maplist(fcn, list1, list...) [SAL] +(maplist fcn list1 list...) [LISP] M apply function to successive cdrs + fcn M the function or function name + listn M a list for each argument of the function + returns M a list of the values returned + +subst(to, from, expr, test: test, test-not: test-not) [SAL] +(subst to from expr &key :test :test-not) [LISP] M substitute expressions + to M the new expression + from M the old expression + expr M the expression in which to do the substitutions + :test M the test function (defaults to eql) + :test-not M the test function (sense inverted) + returns M the expression with substitutions + +sublis(alist, expr, test: test, test-not: test-not) [SAL] +(sublis alist expr &key :test :test-not) [LISP] M substitute with an a-list + alist M the association list + expr M the expression in which to do the substitutions + :test M the test function (defaults to eql) + :test-not M the test function (sense inverted) + returns M the expression with substitutions + + +IV.21. Destructive List Functions +rplaca(list, expr) [SAL] +(rplaca list expr) [LISP] M replace the car of a list node + list M the list node + expr M the new value for the car of the list node + returns M the list node after updating the car + +rplacd(list, expr) [SAL] +(rplacd list expr) [LISP] M replace the cdr of a list node + list M the list node + expr M the new value for the cdr of the list node + returns M the list node after updating the cdr + +nconc(list...) [SAL] +(nconc list...) [LISP] M destructively concatenate lists + list M lists to concatenate + returns M the result of concatenating the lists + +delete(expr, test: test, test-not: test-not) [SAL] +(delete expr &key :test :test-not) [LISP] M delete elements from a list + expr M the element to delete + list M the list + :test M the test function (defaults to eql) + :test-not M the test function (sense inverted) + returns M the list with the matching expressions deleted + +delete-if(test, list) [SAL] +(delete-if test list) [LISP] M delete elements that pass test + test M the test predicate + list M the list + returns M the list with matching elements deleted + +delete-if-not(test, list) [SAL] +(delete-if-not test list) [LISP] M delete elements that fail test + test M the test predicate + list M the list + returns M the list with non-matching elements deleted + +sort(list, test) [SAL] +(sort list test) [LISP] M sort a list + list M the list to sort + test M the comparison function + returns M the sorted list + + +IV.22. Predicate Functions +atom(expr) [SAL] +(atom expr) [LISP] M is this an atom? + expr M the expression to check + returns M t if the value is an atom, nil otherwise + +symbolp(expr) [SAL] +(symbolp expr) [LISP] M is this a symbol? + expr M the expression to check + returns M t if the expression is a symbol, nil otherwise + +numberp(expr) [SAL] +(numberp expr) [LISP] M is this a number? + expr M the expression to check + returns M t if the expression is a number, nil otherwise + +null(expr) [SAL] +(null expr) [LISP] M is this an empty list? + expr M the list to check + returns M t if the list is empty, nil otherwise + +not(expr) [SAL] +(not expr) [LISP] M is this false? + expr M the expression to check + return M t if the value is nil, nil otherwise + +listp(expr) [SAL] +(listp expr) [LISP] M is this a list? + expr M the expression to check + returns M t if the value is a cons or nil, nil otherwise + +endp(list) [SAL] +(endp list) [LISP] M is this the end of a list + list M the list + returns M t if the value is nil, nil otherwise + +consp(expr) [SAL] +(consp expr) [LISP] M is this a non-empty list? + expr M the expression to check + returns M t if the value is a cons, nil otherwise + +integerp(expr) [SAL] +(integerp expr) [LISP] M is this an integer? + expr M the expression to check + returns M t if the value is an integer, nil otherwise + +floatp(expr) [SAL] +(floatp expr) [LISP] M is this a float? + expr M the expression to check + returns M t if the value is a float, nil otherwise + +stringp(expr) [SAL] +(stringp expr) [LISP] M is this a string? + expr M the expression to check + returns M t if the value is a string, nil otherwise + +characterp(expr) [SAL] +(characterp expr) [LISP] M is this a character? + expr M the expression to check + returns M t if the value is a character, nil otherwise + +arrayp(expr) [SAL] +(arrayp expr) [LISP] M is this an array? + expr M the expression to check + returns M t if the value is an array, nil otherwise + +streamp(expr) [SAL] +(streamp expr) [LISP] M is this a stream? + expr M the expression to check + returns M t if the value is a stream, nil otherwise + +objectp(expr) [SAL] +(objectp expr) [LISP] M is this an object? + expr M the expression to check + returns M t if the value is an object, nil otherwise + +filep(expr) [SAL] +(filep expr) [LISP](This is not part of standard XLISP nor is it built-in. + Nyquist defines it though.) M is this a file? + expr M the expression to check + returns M t if the value is an object, nil otherwise + +boundp(sym) [SAL] +(boundp sym) [LISP] M is a value bound to this symbol? + sym M the symbol + returns M t if a value is bound to the symbol, nil otherwise + +fboundp(sym) [SAL] +(fboundp sym) [LISP] M is a functional value bound to this symbol? + sym M the symbol + returns M t if a functional value is bound to the symbol, + nil otherwise + +minusp(expr) [SAL] +(minusp expr) [LISP] M is this number negative? + expr M the number to test + returns M t if the number is negative, nil otherwise + +zerop(expr) [SAL] +(zerop expr) [LISP] M is this number zero? + expr M the number to test + returns M t if the number is zero, nil otherwise + +plusp(expr) [SAL] +(plusp expr) [LISP] M is this number positive? + expr M the number to test + returns M t if the number is positive, nil otherwise + +evenp(expr) [SAL] +(evenp expr) [LISP] M is this integer even? + expr M the integer to test + returns M t if the integer is even, nil otherwise + +oddp(expr) [SAL] +(oddp expr) [LISP] M is this integer odd? + expr M the integer to test + returns M t if the integer is odd, nil otherwise + +eq(expr1, expr2) [SAL] +(eq expr1 expr2) [LISP] M are the expressions identical? + expr1 M the first expression + expr2 M the second expression + returns M t if they are equal, nil otherwise + +eql(expr1, expr2) [SAL] +(eql expr1 expr2) [LISP] M are the expressions identical? (works with all + numbers) + expr1 M the first expression + expr2 M the second expression + returns M t if they are equal, nil otherwise + +equal(expr1, expr2) [SAL] +(equal expr1 expr2) [LISP] M are the expressions equal? + expr1 M the first expression + expr2 M the second expression + returns M t if they are equal, nil otherwise + + +IV.23. Control Constructs +(cond pair...) [LISP] M evaluate conditionally + pair M pair consisting of: + (pred expr...) + where: + pred M is a predicate expression + expr M evaluated if the predicate is not nil + returns M the value of the first expression whose predicate is not nil + +and(expr...) [SAL] +(and expr...) [LISP] M the logical and of a list of expressions + expr M the expressions to be anded + returns M nil if any expression evaluates to nil, otherwise the value of + the last expression (evaluation of expressions stops after the first + expression that evaluates to nil) + +or(expr...) [SAL] +(or expr...) [LISP] M the logical or of a list of expressions + expr M the expressions to be ored + returns M nil if all expressions evaluate to nil, otherwise the value of + the first non-nil expression (evaluation of expressions stops after + the first expression that does not evaluate to nil) + +if(texpr, expr1[, expr2]) [SAL] +(if texpr expr1 [expr2]) [LISP] M evaluate expressions conditionally + texpr M the test expression + expr1 M the expression to be evaluated if texpr is non-nil + expr2 M the expression to be evaluated if texpr is nil + returns M the value of the selected expression + +when(texpr, expr...) [SAL] +(when texpr expr...) [LISP] M evaluate only when a condition is true + texpr M the test expression + expr M the expression(s) to be evaluated if texpr is non-nil + returns M the value of the last expression or nil + +unless(texpr, expr...) [SAL] +(unless texpr expr...) [LISP] M evaluate only when a condition is false + texpr M the test expression + expr M the expression(s) to be evaluated if texpr is nil + returns M the value of the last expression or nil + +(case expr case...) [LISP] M select by case + expr M the selection expression + case M pair consisting of: + (value expr...) + where: + value M is a single expression or a list of expressions (unevaluated) + expr M are expressions to execute if the case matches + returns M the value of the last expression of the matching case + +(let (binding...) expr...) [LISP] M create local bindings +(let* (binding...) expr...) [LISP] M let with sequential binding + binding M the variable bindings each of which is either: + 1) a symbol (which is initialized to nil) + 2) a list whose car is a symbol and whose cadr is an initialization + expression + expr M the expressions to be evaluated + returns M the value of the last expression + +(flet (binding...) expr...) [LISP] M create local functions +(labels (binding...) expr...) [LISP] M flet with recursive functions +(macrolet (binding...) expr...) [LISP] M create local macros + binding M the function bindings each of which is: + (sym fargs expr...) + where: + sym M the function/macro name + fargs M formal argument list (lambda list) + expr M expressions constituting the body of the function/macro + expr M the expressions to be evaluated + returns M the value of the last expression + +catch(sym, expr...) [SAL] +(catch sym expr...) [LISP] M evaluate expressions and catch throws + sym M the catch tag + expr M expressions to evaluate + returns M the value of the last expression the throw expression + +throw(sym[, expr]) [SAL] +(throw sym [expr]) [LISP] M throw to a catch + sym M the catch tag + expr M the value for the catch to return (defaults to nil) + returns M never returns + +unwind-protect(expr, cexpr...) [SAL] +(unwind-protect expr cexpr...) [LISP] M protect evaluation of an expression + expr M the expression to protect + cexpr M the cleanup expressions + returns M the value of the expression + Note: unwind-protect guarantees to execute the cleanup expressions even + if a non-local exit terminates the evaluation of the protected + expression + + +IV.24. Looping Constructs +(loop expr...) [LISP] M basic looping form + expr M the body of the loop + returns M never returns (must use non-local exit) + +(do (binding...) (texpr rexpr...) expr...) [LISP] (do* (binding...) (texpr + rexpr...) expr...) [LISP] + binding M the variable bindings each of which is either: + 1) a symbol (which is initialized to nil) + 2) a list of the form: (sym init [step]) where: + sym M is the symbol to bind + init M is the initial value of the symbol + step M is a step expression + texpr M the termination test expression + rexpr M result expressions (the default is nil) + expr M the body of the loop (treated like an implicit prog) + returns M the value of the last result expression + +(dolist (sym expr [rexpr]) expr...) [LISP] M loop through a list + sym M the symbol to bind to each list element + expr M the list expression + rexpr M the result expression (the default is nil) + expr M the body of the loop (treated like an implicit prog) + +(dotimes (sym expr [rexpr]) expr...) [LISP] M loop from zero to n-1 + sym M the symbol to bind to each value from 0 to n-1 + expr M the number of times to loop + rexpr M the result expression (the default is nil) + expr M the body of the loop (treated like an implicit prog) + + +IV.25. The Program Feature +(prog (binding...) expr...) [LISP] M the program feature +(prog* (binding...) expr...) [LISP] M prog with sequential binding + binding M the variable bindings each of which is either: + 1) a symbol (which is initialized to nil) + 2) a list whose car is a symbol and whose cadr is an initialization + expression + expr M expressions to evaluate or tags (symbols) + returns M nil or the argument passed to the return function + +block(name, expr...) [SAL] +(block name expr...) [LISP] M named block + name M the block name (symbol) + expr M the block body + returns M the value of the last expression + +(return [expr]) [LISP] M cause a prog construct to return a value + expr M the value (defaults to nil) + returns M never returns + +return-from(name[, value]) [SAL] +(return-from name [value]) [LISP] M return from a named block + name M the block name (symbol) + value M the value to return (defaults to nil) + returns M never returns + +tagbody(expr...) [SAL] +(tagbody expr...) [LISP] M block with labels + expr M expression(s) to evaluate or tags (symbols) + returns M nil + +go(sym) [SAL] +(go sym) [LISP] M go to a tag within a tagbody or prog + sym M the tag (quoted) + returns M never returns + +(progv slist vlist expr...) [LISP] M dynamically bind symbols + slist M list of symbols + vlist M list of values to bind to the symbols + expr M expression(s) to evaluate + returns M the value of the last expression + +prog1(expr1, expr...) [SAL] +(prog1 expr1 expr...) [LISP] M execute expressions sequentially + expr1 M the first expression to evaluate + expr M the remaining expressions to evaluate + returns M the value of the first expression + +prog2(expr1, expr2, expr...) [SAL] +(prog2 expr1 expr2 expr...) [LISP] M execute expressions sequentially + expr1 M the first expression to evaluate + expr2 M the second expression to evaluate + expr M the remaining expressions to evaluate + returns M the value of the second expression + +progn(expr...) [SAL] +(progn expr...) [LISP] M execute expressions sequentially + expr M the expressions to evaluate + returns M the value of the last expression (or nil) + + +IV.26. Debugging and Error Handling +trace(sym) [SAL] +(trace sym) [LISP] M add a function to the trace list + sym M the function to add (quoted) + returns M the trace list + +untrace(sym) [SAL] +(untrace sym) [LISP] M remove a function from the trace list + sym M the function to remove (quoted) + returns M the trace list + +error(emsg[, arg]) [SAL] +(error emsg [arg]) [LISP] M signal a non-correctable error + emsg M the error message string + arg M the argument expression (printed after the message) + returns M never returns + +cerror(cmsg, emsg[, arg]) [SAL] +(cerror cmsg emsg [arg]) [LISP] M signal a correctable error + cmsg M the continue message string + emsg M the error message string + arg M the argument expression (printed after the message) + returns M nil when continued from the break loop + +break([bmsg[, arg]]) [SAL] +(break [bmsg [arg]]) [LISP] M enter a break loop + bmsg M the break message string (defaults to **break**) + arg M the argument expression (printed after the message) + returns M nil when continued from the break loop + +(clean-up) [LISP] M clean-up after an error + returns M never returns + +(top-level) [LISP] M clean-up after an error and return to the top level + returns M never returns + +(continue) [LISP] M continue from a correctable error + returns M never returns + +(errset expr [pflag]) [LISP] M trap errors + expr M the expression to execute + pflag M flag to control printing of the error message + returns M the value of the last expression consed with nil + or nil on error + +(baktrace [n]) [LISP] M print n levels of trace back information + n M the number of levels (defaults to all levels) + returns M nil + +(evalhook expr ehook ahook [env]) [LISP] M evaluate with hooks + expr M the expression to evaluate + ehook M the value for *evalhook* + ahook M the value for *applyhook* + env M the environment (default is nil) + returns M the result of evaluating the expression + +profile(flag) [SAL] +(profile flag) [LISP](This is not a standard XLISP 2.0 function.) M turn + profiling on or off. + flag M nil turns profiling off, otherwise on + returns M the previous state of profiling. + + +IV.27. Arithmetic Functions +truncate(expr) [SAL] +(truncate expr) [LISP] M truncates a floating point number to an integer + expr M the number + returns M the result of truncating the number + +float(expr) [SAL] +(float expr) [LISP] M converts an integer to a floating point number + expr M the number + returns M the result of floating the integer + +(+ expr...) [LISP] M add a list of numbers + expr M the numbers + returns M the result of the addition + +(- expr...) [LISP] M subtract a list of numbers or negate a single number + expr M the numbers + returns M the result of the subtraction + +(* expr...) [LISP] M multiply a list of numbers + expr M the numbers + returns M the result of the multiplication + +(/ expr...) [LISP] M divide a list of numbers + expr M the numbers + returns M the result of the division + +(1+ expr) [LISP] M add one to a number + expr M the number + returns M the number plus one + +(1- expr) [LISP] M subtract one from a number + expr M the number + returns M the number minus one + +rem(expr...) [SAL] +(rem function) expr...) [LISP] M remainder of a list of numbers + expr M the numbers + returns M the result of the remainder operation + +min(expr...) [SAL] +(min expr...) [LISP] M the smallest of a list of numbers + expr M the expressions to be checked + returns M the smallest number in the list + +max(expr...) [SAL] +(max expr...) [LISP] M the largest of a list of numbers + expr M the expressions to be checked + returns M the largest number in the list + +abs(expr) [SAL] +(abs expr) [LISP] M the absolute value of a number + expr M the number + returns M the absolute value of the number + +gcd(n1, n2...) [SAL] +(gcd n1 n2...) [LISP] M compute the greatest common divisor + n1 M the first number (integer) + n2 M the second number(s) (integer) + returns M the greatest common divisor + +random(n) [SAL] +(random n) [LISP] M compute a random number between 0 and n-1 inclusive + n M the upper bound (integer) + returns M a random number + +rrandom() [SAL] +(rrandom) [LISP] M compute a random real number between 0 and 1 inclusive + returns M a random floating point number + +sin(expr) [SAL] +(sin expr) [LISP] M compute the sine of a number + expr M the floating point number + returns M the sine of the number + +cos(expr) [SAL] +(cos expr) [LISP] M compute the cosine of a number + expr M the floating point number + returns M the cosine of the number + +tan(expr) [SAL] +(tan expr) [LISP] M compute the tangent of a number + expr M the floating point number + returns M the tangent of the number + +atan(expr[, expr2]) [SAL] +(atan expr [expr2]) [LISP](This is not a standard XLISP 2.0 function.) M + compute the arctangent + expr M the value of x + expr2 M the value of y (default value is 1.0) + returns M the arctangent of x/y + +expt(x-expr, y-expr) [SAL] +(expt x-expr y-expr) [LISP] M compute x to the y power + x-expr M the floating point number + y-expr M the floating point exponent + returns M x to the y power + +exp(x-expr) [SAL] +(exp x-expr) [LISP] M compute e to the x power + x-expr M the floating point number + returns M e to the x power + +sqrt(expr) [SAL] +(sqrt expr) [LISP] M compute the square root of a number + expr M the floating point number + returns M the square root of the number + +(< n1 n2...) [LISP] M test for less than +(<= n1 n2...) [LISP] M test for less than or equal to +(= n1 n2...) [LISP] M test for equal to +(/= n1 n2...) [LISP] M test for not equal to +(>= n1 n2...) [LISP] M test for greater than or equal to +(> n1 n2...) [LISP] M test for greater than + n1 M the first number to compare + n2 M the second number to compare + returns M t if the results of comparing n1 with n2, n2 with n3, etc., are + all true. + + +IV.28. Bitwise Logical Functions +logand(expr...) [SAL] +(logand expr...) [LISP] M the bitwise and of a list of numbers + expr M the numbers + returns M the result of the and operation + +logior(expr...) [SAL] +(logior expr...) [LISP] M the bitwise inclusive or of a list of numbers + expr M the numbers + returns M the result of the inclusive or operation + +logxor(expr...) [SAL] +(logxor expr...) [LISP] M the bitwise exclusive or of a list of numbers + expr M the numbers + returns M the result of the exclusive or operation + +lognot(expr) [SAL] +(lognot expr) [LISP] M the bitwise not of a number + expr M the number + returns M the bitwise inversion of number + + +IV.29. String Functions +string(expr) [SAL] +(string expr) [LISP] M make a string from a value + expr M an integer (which is first converted into its ASCII character + value), string, character, or symbol + returns M the string representation of the argument + +string-search(pat, str, start: start, end: end) [SAL] +(string-search pat str &key :start :end) [LISP](This is not a standard XLISP + 2.0 function.) M search for pattern in string + pat M a string to search for + str M the string to be searched + :start M the starting offset in str + :end M the ending offset + 1 + returns M index of pat in str or NIL if not found + +string-trim(bag, str) [SAL] +(string-trim bag str) [LISP] M trim both ends of a string + bag M a string containing characters to trim + str M the string to trim + returns M a trimed copy of the string + +string-left-trim(bag, str) [SAL] +(string-left-trim bag str) [LISP] M trim the left end of a string + bag M a string containing characters to trim + str M the string to trim + returns M a trimed copy of the string + +string-right-trim(bag, str) [SAL] +(string-right-trim bag str) [LISP] M trim the right end of a string + bag M a string containing characters to trim + str M the string to trim + returns M a trimed copy of the string + +string-upcase(str, start: start, end: end) [SAL] +(string-upcase str &key :start :end) [LISP] M convert to uppercase + str M the string + :start M the starting offset + :end M the ending offset + 1 + returns M a converted copy of the string + +string-downcase(str, start: start, end: end) [SAL] +(string-downcase str &key :start :end) [LISP] M convert to lowercase + str M the string + :start M the starting offset + :end M the ending offset + 1 + returns M a converted copy of the string + +nstring-upcase(str, start: start, end: end) [SAL] +(nstring-upcase str &key :start :end) [LISP] M convert to uppercase + str M the string + :start M the starting offset + :end M the ending offset + 1 + returns M the converted string (not a copy) + +nstring-downcase(str, start: start, end: end) [SAL] +(nstring-downcase str &key :start :end) [LISP] M convert to lowercase + str M the string + :start M the starting offset + :end M the ending offset + 1 + returns M the converted string (not a copy) + +strcat(expr...) [SAL] +(strcat expr...) [LISP] M concatenate strings + expr M the strings to concatenate + returns M the result of concatenating the strings + +subseq(string, start[, end]) [SAL] +(subseq string start [end]) [LISP] M extract a substring + string M the string + start M the starting position (zero origin) + end M the ending position + 1 (defaults to end) + returns M substring between start and end + +string<(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) + [SAL] +(string< str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string<=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) + [SAL] +(string<= str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) + [SAL] +(string= str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string/=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) + [SAL] +(string/= str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string>=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) + [SAL] +(string>= str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string>(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) + [SAL] +(string> str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + str1 M the first string to compare + str2 M the second string to compare + :start1 M first substring starting offset + :end1 M first substring ending offset + 1 + :start2 M second substring starting offset + :end2 M second substring ending offset + 1 + returns M t if predicate is true, nil otherwise + Note: case is significant with these comparison functions. + +string-lessp(str1, str2, start1: start1, end1: end1, start2: start2, end2: + end2) [SAL] +(string-lessp str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string-not-greaterp(str1, str2, start1: start1, end1: end1, start2: start2, + end2: end2) [SAL] +(string-not-greaterp str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string-equalp(str1, str2, start1: start1, end1: end1, start2: start2, end2: + end2) [SAL] +(string-equalp str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string-not-equalp(str1, str2, start1: start1, end1: end1, start2: start2, end2: + end2) [SAL] +(string-not-equalp str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string-not-lessp(str1, str2, start1: start1, end1: end1, start2: start2, end2: + end2) [SAL] +(string-not-lessp str1 str2 &key :start1 :end1 :start2 :end2) [LISP] +string-greaterp(str1, str2, start1: start1, end1: end1, start2: start2, end2: + end2) [SAL] +(string-greaterp str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + str1 M the first string to compare + str2 M the second string to compare + :start1 M first substring starting offset + :end1 M first substring ending offset + 1 + :start2 M second substring starting offset + :end2 M second substring ending offset + 1 + returns M t if predicate is true, nil otherwise + Note: case is not significant with these comparison functions. + + +IV.30. Character Functions +char(string, index) [SAL] +(char string index) [LISP] M extract a character from a string + string M the string + index M the string index (zero relative) + returns M the ascii code of the character + +upper-case-p(chr) [SAL] +(upper-case-p chr) [LISP] M is this an upper case character? + chr M the character + returns M t if the character is upper case, nil otherwise + +lower-case-p(chr) [SAL] +(lower-case-p chr) [LISP] M is this a lower case character? + chr M the character + returns M t if the character is lower case, nil otherwise + +both-case-p(chr) [SAL] +(both-case-p chr) [LISP] M is this an alphabetic (either case) character? + chr M the character + returns M t if the character is alphabetic, nil otherwise + +digit-char-p(chr) [SAL] +(digit-char-p chr) [LISP] M is this a digit character? + chr M the character + returns M the digit weight if character is a digit, nil otherwise + +char-code(chr) [SAL] +(char-code chr) [LISP] M get the ascii code of a character + chr M the character + returns M the ascii character code (integer) + +code-char(code) [SAL] +(code-char code) [LISP] M get the character with a specified ascii code + code M the ascii code (integer) + returns M the character with that code or nil + +char-upcase(chr) [SAL] +(char-upcase chr) [LISP] M convert a character to upper case + chr M the character + returns M the upper case character + +char-downcase(chr) [SAL] +(char-downcase chr) [LISP] M convert a character to lower case + chr M the character + returns M the lower case character + +digit-char(n) [SAL] +(digit-char n) [LISP] M convert a digit weight to a digit + n M the digit weight (integer) + returns M the digit character or nil + +char-int(chr) [SAL] +(char-int chr) [LISP] M convert a character to an integer + chr M the character + returns M the ascii character code + +int-char(int) [SAL] +(int-char int) [LISP] M convert an integer to a character + int M the ascii character code + returns M the character with that code + +char<(chr1, chr2...) [SAL] +(char< chr1 chr2...) [LISP] +char<=(chr1, chr2...) [SAL] +(char<= chr1 chr2...) [LISP] +char=(chr1, chr2...) [SAL] +(char= chr1 chr2...) [LISP] +char/=(chr1, chr2...) [SAL] +(char/= chr1 chr2...) [LISP] +char>=(chr1, chr2...) [SAL] +(char>= chr1 chr2...) [LISP] +char>(chr1, chr2...) [SAL] +(char> chr1 chr2...) [LISP] + chr1 M the first character to compare + chr2 M the second character(s) to compare + returns M t if predicate is true, nil otherwise + Note: case is significant with these comparison functions. + +char-lessp(chr1, chr2...) [SAL] +(char-lessp chr1 chr2...) [LISP] +char-not-greaterp(chr1, chr2...) [SAL] +(char-not-greaterp chr1 chr2...) [LISP] +char-equalp(chr1, chr2...) [SAL] +(char-equalp chr1 chr2...) [LISP] +char-not-equalp(chr1, chr2...) [SAL] +(char-not-equalp chr1 chr2...) [LISP] +char-not-lessp(chr1, chr2...) [SAL] +(char-not-lessp chr1 chr2...) [LISP] +char-greaterp(chr1, chr2...) [SAL] +(char-greaterp chr1 chr2...) [LISP] + chr1 M the first string to compare + chr2 M the second string(s) to compare + returns M t if predicate is true, nil otherwise + Note: case is not significant with these comparison functions. + + +IV.31. Input/Output Functions +read([stream[, eof[, rflag]]]) [SAL] +(read [stream [eof [rflag]]]) [LISP] M read an expression + stream M the input stream (default is standard input) + eof M the value to return on end of file (default is nil) + rflag M recursive read flag (default is nil) + returns M the expression read + +(print expr [stream]) [LISP] M print an expression on a new line + expr M the expression to be printed + stream M the output stream (default is standard output) + returns M the expression + +prin1(expr[, stream]) [SAL] +(prin1 expr [stream]) [LISP] M print an expression + expr M the expression to be printed + stream M the output stream (default is standard output) + returns M the expression + +princ(expr[, stream]) [SAL] +(princ expr [stream]) [LISP] M print an expression without quoting + expr M the expressions to be printed + stream M the output stream (default is standard output) + returns M the expression + +pprint(expr[, stream]) [SAL] +(pprint expr [stream]) [LISP] M pretty print an expression + expr M the expressions to be printed + stream M the output stream (default is standard output) + returns M the expression + +terpri([stream]) [SAL] +(terpri [stream]) [LISP] M terminate the current print line + stream M the output stream (default is standard output) + returns M nil + +flatsize(expr) [SAL] +(flatsize expr) [LISP] M length of printed representation using prin1 + expr M the expression + returns M the length + +flatc(expr) [SAL] +(flatc expr) [LISP] M length of printed representation using princ + expr M the expression + returns M the length + + +IV.32. The Format Function +format(stream, fmt, arg...) [SAL] +(format stream fmt arg...) [LISP] M do formated +output + stream M the output stream + fmt M the format string + arg M the format arguments + returns M output string if stream is nil, nil otherwise + + The format string can contain characters that should be copied directly to +the output and formatting directives. The formatting directives are: + + ~A M print next argument using princ + ~S M print next argument using prin1 + ~% M start a new line + ~~ M print a tilde character + ~ M ignore this one newline and white space on the + next line up to the first non-white-space character or newline. This + allows strings to continue across multiple lines + +IV.33. File I/O Functions + Note that files are ordinarily opened as text. Binary files (such as standard +midi files) must be opened with open-binary on non-unix systems. +open(fname, direction: direction) [SAL] +(open fname &key :direction) [LISP] M open a file stream + fname M the file name string or symbol + :direction M :input or :output (default is :input) + returns M a stream + +open-binary(fname, direction: direction) [SAL] +(open-binary fname &key :direction) [LISP] M open a binary file stream + fname M the file name string or symbol + :direction M :input or :output (default is :input) + returns M a stream + +close(stream) [SAL] +(close stream) [LISP] M close a file stream + stream M the stream + returns M nil + +setdir(path[, verbose]) [SAL] +(setdir path [verbose]) [LISP](This is not a standard XLISP 2.0 function.) M + set current directory + path M the path of the new directory + verbose M print error message if current directory cannot be changed to + path + returns M the resulting full path, e.g. (setdir ".") gets the current + working directory, or nil if an error occurs + +listdir(path) [SAL] +(listdir path) [LISP](This is not a standard XLISP 2.0 function.) M get a + directory listing + path M the path of the directory to be listed + returns M list of filenames in the directory + +get-temp-path() [SAL] +(get-temp-path) [LISP](This is not a standard XLISP 2.0 function.) M get a path + where a temporary file can be created. Under Windows, this is based on + environment variables. If XLISP is running as a sub-process to Java, the + environment may not exist, in which case the default result is the + unfortunate choice c:\windows\. + returns M the resulting full path as a string + +get-user() [SAL] +(get-user) [LISP](This is not a standard XLISP 2.0 function.) M get the user + ID. In Unix systems (including OS X and Linux), this is the value of the + USER environment variable. In Windows, this is currently just ``nyquist'', + which is also returned if the environment variable cannot be accessed. + This function is used to avoid the case of two users creating files of the + same name in the same temp directory. + returns M the string naming the user + +find-in-xlisp-path(filename) [SAL] +(find-in-xlisp-path filename) [LISP](This is not a standard XLISP 2.0 + function.) M search the XLISP search path (e.g. XLISPPATH from the + environment) for filename. If filename is not found as is, and there is no + file extension, append ".lsp" to filename and search again. The current + directory is not searched. + filename M the name of the file to search for + returns M a full path name to the first occurrence found + +read-char([stream]) [SAL] +(read-char [stream]) [LISP] M read a character from a stream + stream M the input stream (default is standard input) + returns M the character + +peek-char([flag[, stream]]) [SAL] +(peek-char [flag [stream]]) [LISP] M peek at the next character + flag M flag for skipping white space (default is nil) + stream M the input stream (default is standard input) + returns M the character (integer) + +write-char(ch[, stream]) [SAL] +(write-char ch [stream]) [LISP] M write a character to a stream + ch M the character to write + stream M the output stream (default is standard output) + returns M the character + +read-int([stream[, length]]) [SAL] +(read-int [stream [length]]) [LISP] M read a binary integer from a stream + stream M the input stream (default is standard input) + length M the length of the integer in bytes (default is 4) + returns M the integer + Note: Integers are assumed to be big-endian (high-order byte first) and + signed, regardless of the platform. To read little-endian format, use + a negative number for the length, e.g. -4 indicates a 4-bytes, + low-order byte first. The file should be opened in binary mode. + +write-int(ch[, stream[, length]]) [SAL] +(write-int ch [stream [length]]) [LISP] M write a binary integer to a stream + ch M the character to write + stream M the output stream (default is standard output) + length M the length of the integer in bytes (default is 4) + returns M the integer + Note: Integers are assumed to be big-endian (high-order byte first) and + signed, regardless of the platform. To write in little-endian format, + use a negative number for the length, e.g. -4 indicates a 4-bytes, + low-order byte first. The file should be opened in binary mode. + +read-float([stream[, length]]) [SAL] +(read-float [stream [length]]) [LISP] M read a binary floating-point number + from a stream + stream M the input stream (default is standard input) + length M the length of the float in bytes (default is 4, legal values are + -4, -8, 4, and 8) + returns M the integer + Note: Floats are assumed to be big-endian (high-order byte first) and + signed, regardless of the platform. To read little-endian format, use + a negative number for the length, e.g. -4 indicates a 4-bytes, + low-order byte first. The file should be opened in binary mode. + +write-float(ch[, stream[, length]]) [SAL] +(write-float ch [stream [length]]) [LISP] M write a binary floating-point + number to a stream + ch M the character to write + stream M the output stream (default is standard output) + length M the length of the float in bytes (default is 4, legal values are + -4, -8, 4, and 8) + returns M the integer + Note: Floats are assumed to be big-endian (high-order byte first) and + signed, regardless of the platform. To write in little-endian format, + use a negative number for the length, e.g. -4 indicates a 4-bytes, + low-order byte first. The file should be opened in binary mode. + +read-line([stream]) [SAL] +(read-line [stream]) [LISP] M read a line from a stream + stream M the input stream (default is standard input) + returns M the string + +read-byte([stream]) [SAL] +(read-byte [stream]) [LISP] M read a byte from a stream + stream M the input stream (default is standard input) + returns M the byte (integer) + +write-byte(byte[, stream]) [SAL] +(write-byte byte [stream]) [LISP] M write a byte to a stream + byte M the byte to write (integer) + stream M the output stream (default is standard output) + returns M the byte (integer) + + +IV.34. String Stream Functions + These functions operate on unnamed streams. An unnamed output stream +collects characters sent to it when it is used as the destination of any output +function. The functions get-output-stream-string and get-output-stream-list +return a string or a list of characters. + + An unnamed input stream is setup with the make-string-input-stream function +and returns each character of the string when it is used as the source of any +input function. + +make-string-input-stream(str[, start[, end]]) [SAL] +(make-string-input-stream str [start [end]]) [LISP] + str M the string + start M the starting offset + end M the ending offset + 1 + returns M an unnamed stream that reads from the string + +make-string-output-stream)() [SAL] +(make-string-output-stream) [LISP] + returns M an unnamed output stream + +get-output-stream-string(stream) [SAL] +(get-output-stream-string stream) [LISP] + stream M the output stream + returns M the output so far as a string + Note: the output stream is emptied by this function + +get-output-stream-list(stream) [SAL] +(get-output-stream-list stream) [LISP] + stream M the output stream + returns M the output so far as a list + Note: the output stream is emptied by this function + + +IV.35. System Functions + Note: the load function first tries to load a file from the current +directory. A .lsp extension is added if there is not already an alphanumeric +extension following a period. If that fails, XLISP searches the path, which is +obtained from the XLISPPATH environment variable in Unix and +HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under Win32. (The Macintosh +version has no search path.) +get-env(name) [SAL] +(get-env name) [LISP] M get from an environment variable + name M the name of the environment variable + returns M string value of the environment variable, nil if variable does + not exist + +(load fname &key :verbose :print) [LISP] M load a source file + fname M the filename string or symbol + :verbose M the verbose flag (default is t) + :print M the print flag (default is nil) + returns M the filename + +save(fname) [SAL] +(save fname) [LISP] M save workspace to a file + fname M the filename string or symbol + returns M t if workspace was written, nil otherwise + +restore(fname) [SAL] +(restore fname) [LISP] M restore workspace from a file + fname M the filename string or symbol + returns M nil on failure, otherwise never returns + +dribble([fname]) [SAL] +(dribble [fname]) [LISP] M create a file with a transcript of a session + fname M file name string or symbol (if missing, close current transcript) + returns M t if the transcript is opened, nil if it is closed + +gc() [SAL] +(gc) [LISP] M force garbage collection + returns M nil + +expand(num) [SAL] +(expand num) [LISP] M expand memory by adding segments + num M the number of segments to add + returns M the number of segments added + +alloc(num) [SAL] +(alloc num) [LISP] M change number of nodes to allocate in each segment + num M the number of nodes to allocate + returns M the old number of nodes to allocate + +info() [SAL] +(info) [LISP] M show information about memory usage. + returns M nil + +room() [SAL] +(room) [LISP] M show memory allocation statistics + returns M nil + +type-of(expr) [SAL] +(type-of expr) [LISP] M returns the type of the expression + expr M the expression to return the type of + returns M nil if the value is nil otherwise one of the symbols: + SYMBOL M for symbols + OBJECT M for objects + CONS M for conses + SUBR M for built-in functions + FSUBR M for special forms + CLOSURE M for defined functions + STRING M for strings + FIXNUM M for integers + FLONUM M for floating point numbers + CHARACTER M for characters + FILE-STREAM M for file pointers + UNNAMED-STREAM M for unnamed streams + ARRAY M for arrays + +peek(addrs) [SAL] +(peek addrs) [LISP] M peek at a location in memory + addrs M the address to peek at (integer) + returns M the value at the specified address (integer) + +poke(addrs, value) [SAL] +(poke addrs value) [LISP] M poke a value into memory + addrs M the address to poke (integer) + value M the value to poke into the address (integer) + returns M the value + +bigendianp() [SAL] +(bigendianp) [LISP] M is this a big-endian machine? + returns M T if this a big-endian architecture, storing the high-order byte + of an integer at the lowest byte address of the integer; otherwise, + NIL. (This is not a standard XLISP 2.0 function.) + +address-of(expr) [SAL] +(address-of expr) [LISP] M get the address of an xlisp node + expr M the node + returns M the address of the node (integer) + +exit() [SAL] +(exit) [LISP] M exit xlisp + returns M never returns + +setup-console() [SAL] +(setup-console) [LISP] M set default console attributes + returns M NIL + Note: Under Windows, Nyquist normally starts up in a medium-sized console + window with black text and a white background, with a window title of + ``Nyquist.'' This is normally accomplished by calling setup-console + in system.lsp. In Nyquist, you can avoid this behavior by setting + *setup-console* to NIL in your init.lsp file. If setup-console is not + called, Nyquist uses standard input and output as is. This is what + you want if you are running Nyquist inside of emacs, for example. + +echoenabled(flag) [SAL] +(echoenabled flag) [LISP] M turn console input echoing on or off + flag M T to enable echo, NIL to disable + returns M NIL + Note: This function is only implemented under Linux and Mac OS X. If + Nyquist I/O is redirected through pipes, the Windows version does not + echo the input, but the Linux and Mac versions do. You can turn off + echoing with this function. Under windows it is defined to do + nothing. + +IV.36. File I/O Functions + + + +IV.36.1. Input from a File + To open a file for input, use the open function with the keyword argument +:direction set to :input. To open a file for output, use the open function +with the keyword argument :direction set to :output. The open function takes a +single required argument which is the name of the file to be opened. This name +can be in the form of a string or a symbol. The open function returns an +object of type FILE-STREAM if it succeeds in opening the specified file. It +returns the value nil if it fails. In order to manipulate the file, it is +necessary to save the value returned by the open function. This is usually +done by assigning it to a variable with the setq special form or by binding it +using let or let*. Here is an example: + + (setq fp (open "init.lsp" :direction :input)) + +Evaluating this expression will result in the file init.lsp being opened. The +file object that will be returned by the open function will be assigned to the +variable fp. + + It is now possible to use the file for input. To read an expression from the +file, just supply the value of the fp variable as the optional stream argument +to read. + + (read fp) + +Evaluating this expression will result in reading the first expression from the +file init.lsp. The expression will be returned as the result of the read +function. More expressions can be read from the file using further calls to +the read function. When there are no more expressions to read, the read +function will return nil (or whatever value was supplied as the second argument +to read). + + Once you are done reading from the file, you should close it. To close the +file, use the following expression: + + (close fp) + +Evaluating this expression will cause the file to be closed. + + + +IV.36.2. Output to a File + Writing to a file is pretty much the same as reading from one. You need to +open the file first. This time you should use the open function to indicate +that you will do output to the file. For example: + + (setq fp (open "test.dat" :direction :output)) + +Evaluating this expression will open the file test.dat for output. If the file +already exists, its current contents will be discarded. If it doesn't already +exist, it will be created. In any case, a FILE-STREAM object will be returned +by the OPEN function. This file object will be assigned to the fp variable. + + It is now possible to write to this file by supplying the value of the fp +variable as the optional stream parameter in the print function. + + (print "Hello there" fp) + +Evaluating this expression will result in the string ``Hello there'' being +written to the file test.dat. More data can be written to the file using the +same technique. + + Once you are done writing to the file, you should close it. Closing an +output file is just like closing an input file. + + (close fp) + +Evaluating this expression will close the output file and make it permanent. + + + +IV.36.3. A Slightly More Complicated File Example + This example shows how to open a file, read each Lisp expression from the +file and print it. It demonstrates the use of files and the use of the +optional stream argument to the read function. + + (do* ((fp (open "test.dat" :direction :input)) + (ex (read fp) (read fp))) + ((null ex) nil) + (print ex)) + REFERENCES + +[Dannenberg 89] + Dannenberg, R. B. and C. L. Fraley. Fugue: Composition and +Sound Synthesis With Lazy Evaluation and Behavioral Abstraction. In T. Wells +and D. Butler (editor), Proceedings of the 1989 International Computer Music +Conference, pages 76-79. International Computer Music Association, San +Francisco, 1989. + +[Touretzky 84] Touretzky, David S. LISP: a gentle introduction to symbolic +computation. Harper & Row, New York, 1984. +Index + + + Banded treble boost 52 Digit-char 69 +! 13, 36 Bandfx.lsp 52 Digit-char-p 69 +!= 13 Bandpass filter 23 Directory listing 70 +!Call 40 Bandpass2 23 Directory, default sound +!Clock 39 Bartok 38 file 27 +!csec 38 Begin 13 Display statement, sal +!Def 39 Behavioral abstraction 6 14 +!End 40 Behaviors 19 Distortion tutorial 23 +!msec 38 Bell sound 3 Distributions, probability +!Ramp 39 Bernoulli distribution 45 +!Rate 37 46 Division 25 +!Seti 40 Bernoulli-dist 46 Do 67 +!Setv 40 Beta distribution 46 Do* 67 +!Tempo 37 Beta-dist 46 Dolby Pro-Logic 52 + Big endian 71 Dolby Surround 52 +# (Adagio articulation)Bigendianp 71 Dolist 67 + 37 Bilateral exponentialDoppler effect 53 +#?, sal 13 distribution 45 Dot 36 +#define'd macros 59 Bilateral-exponential-distDotimes 67 +#f 13 45 Dotted durations 2 +#t 13 Binary files 70 Dribble 71 + Binomial distribution 46Drum samples 3 +% (Adagio thirtysecondBinomial-dist 46 Drum 53 + note) 36 Biquad 23 Drum machine 3, 53 +% 13 Biquad-m 23 Drum sound 3 + Bitwise Logical FunctionsDrum-loop 53 +& 13 68 DSP in Lisp 3, 11 +&= 15 Blank 36 Dtmf 52 + Block 67 Dtmf-tone 52 +* 13, 68 Both-case-p 69 Dubugging 29 +*= 15 Boundp 66 Duration 36 +*A4-Hertz* 19, 34 Bowed 24 Duration notation 2 +*applyhook* 64 Bowed-freq 24 Duration of another sound +*audio-markers* 27 Brass sound 3 28 +*autonorm* 34 Break 62, 68 DX7 36 +*autonorm-max-samples* Break button 4 Dynamic markings 37 + 34 Browse button 4 +*autonorm-previous-peak* Browser, jnyqide 4 Echo 22 + 34 Build-harmonic 1, 19 Echoenabled 71 +*autonorm-target* 34 Button bar 4 Editor for envelopes 4 +*autonorm-type* 34 Buzz 21 Effect, reverberation +*autonormflag* 34 23, 23 +*breakenable* 34, 62, 64Call command 40 Effect, chorus 23, 31, +*control-srate* 6, 26,Car 65 52 + 34 Case 36, 67 Effect, flange 51 +*debug-io* 64 Case-insensitive 13 Effect, pitch shift 24, +*default-control-srate* Catch 67 31 + 34 Cauchy distribution 45 Effect, reverberation +*default-plot-file* 28 Cauchy-dist 45 31, 52 +*default-sf-bits* 34 Cdr 65 Effect, stereo 52 +*default-sf-dir* 27, 34 Cerror 68 Effect, stereo pan 52 +*default-sf-format* 34 Change directory 70 Effect, swap channels 52 +*default-sf-srate* 27,Char 69 Effect, widen 52 + 34 Char-code 69 Effects, phaser 51 +*default-sound-srate* 34Char-downcase 69 EIghth note 2, 36 +*error-output* 64 Char-equalp 70 Elapsed audio time 27 +*evalhook* 64 Char-greaterp 70 Emacs, using Nyquist with +*file-separator* 34 Char-int 69 71 +*float-format* 64 Char-lessp 70 Empty list 13 +*gc-flag* 64 Char-not-equalp 70 End 13 +*gc-hook* 64 Char-not-greaterp 70 End command 40 +*integer-format* 64 Char-not-lessp 70 Endian 71 +*loud* 6 Char-upcase 69 Endless tones 3 +*obarray* 64 Char/= 70 Endp 66 +*print-case* 64 Char< 70 Env 2, 19 +*readtable* 63, 64 Char<= 70 Env-note 2 +*rslt* 34, 59 Char= 70 Envedit button 4 +*sound-srate* 6, 26, 34 Char> 70 Envelope 2 +*soundenable* 34 Char>= 70 Envelope editor 4 +*standard-input* 64 Character Functions 69 Envelope follower 18, 29 +*standard-output* 64 Characterp 66 Envelope generator 22 +*start* 6 Chdir, sal 14 Envelopes 2 +*stop* 6 Chorus 23, 29, 31, 51,Environment 6 +*sustain* 6 52 Environment variables 71 +*table* 34 Clarinet 24 Eq 67 +*trace-output* 64 Clarinet sound 3 Eq button 4 +*tracelimit* 62, 64 Clarinet-all 24 Eq-band 23 +*tracelist* 64 Clarinet-freq 24 Eq-highshelf 23 +*tracenable* 34, 62, 64 Class 64 Eq-lowshelf 23 +*transpose* 6 Class class 64 Eql 67 +*unbound* 64 Clean-up 68 Equal 67 +*warp* 6, 25 Clip 10, 24, 29 Equalization 23, 51 + Clipping repair 51 Equalization editor 4 ++ 13, 68 Clock 39 Error 68 ++= 15 Clock command 39 Error Handling 68 + Close 70 Errors iii +, (Adagio) 38 Co-termination 28 Errset 68 + Code-char 69 Estimate frequency 25 +- 13, 68 Comb 22 Eval 64 + Comb filter 22 Eval pattern 44 +. (Adagio) 36 Combination 26 Evalhook 68 + Command Loop 62 Evaluation functions 64 +/ 13, 68 Commas 38 Evaluator 62 +/= 68 Comment 36 Evenp 66 + Comments 13 Event-dur 48 +1+ 68 Compose 29 Event-end 48 +1- 68 Compress 51 Event-expression 48 + Compress-map 51 Event-get-attr 48 +:answer 64 Compressor 18 Event-has-attr 48 +:class 64 Concatenate strings 69 Event-set-attr 48 +:isa 64 Cond 67 Event-set-dur 48 +:isnew 64 Conditional expression,Event-set-expression 48 +:new 64 sal 13 Event-set-time 48 +:show 64 Configure nyquist 1 Event-time 48 + Congen 22 Exclamation point 36 +; (Adagio) 38 Cons 65 Exec statement, sal 14 + Console, XLISP 71 Exit 71 +< 13, 68 Consp 66 Exit statement, sal 15 +<= 13, 15, 68 Const 19 Exp 68 + Constant function 19 Exp-dec 19 += 13, 68 Continue 68 Expand 71 + Continuous-control-warp Exponent 42 +> 13, 68 25 Exponential 25 +>= 13, 15, 68 Continuous-sound-warp 26Exponential distribution + Contour generator 22 45 +@ 13 Control 19 Exponential envelope 19 +@= 15 Control change 38 Exponential-dist 45 +@@ 13 Control characters, XLISPExpr-get-attr 48 + 62 Expr-has-attr 48 +A440 19 Control Constructs 67 Expr-set-attr 48 +Abs 68 Control-A 27 Expression pattern 44 +Abs-env 25 Control-srate-abs 26 Expressions, sal 13 +Absolute stretch, sal 13Control-warp 19 Expt 68 +Absolute time shift, salConvert sound to arrayExtending Xlisp 59 + 13 18 Extract 26 +Absolute value 24, 29 Convolution 22 Extract-abs 26 +Access samples 17 Convolve 22 +Accidentals 36 Copier pattern 44 F (Adagio dynamic) 37 +Accumulate pattern 44 Cos 68 F (Adagio Flat) 36 +Accumulation pattern 44 Cue 19 Fast fourier transform +Adagio 36 Cue-file 19 tutorial 35 +Add offset to sound 29 Current-path 42 Fboundp 66 +Add to file samples 28 Cxxr 65 Feedback FM Oscillator +Add-action-to-workspace Cxxxr 65 21 + 50 Cxxxxr 65 Feedback-delay 22 +Add-to-workspace 50 Cycle pattern 43 Feel factor 49 +Additive synthesis, gongs FF (Adagio dynamic) 37 + 3 DarwiinRemoteOsc 19 FFF (Adagio dynamic) 37 +Address-of 71 Data Types 62 Fft 35 +Aftertouch 38 Db-average 51 Fft tutorial 35 +Agc 51 Db-to-linear 18 File I/O Functions 70, +Algorithmic CompositionDB0 2 72 + 43 DB1 2 Filep 66 +All pass filter 22 DB10 2 Filter example 11 +Alloc 71 Debugging 18, 28, 42, 68Finally clause, sal 15 +Allpass2 23 Decf 42 Find string 69 +Allpoles-from-lpc 41 Decrement 42 Find-in-xlisp-path 70 +Alpass 22 Default durations 37 FIR filter 22 +Alpass filter 22 Default 37 First 65 +Amosc 21 Default sample rate 7 First derivative 20 +Analog synthesizer 53 Default sound fileFlange 51 +And 67 directory 27 Flange effect 51 +Append 65 Default time 36 Flat 36 +Apply 64 Define function 14 Flatc 70 +Apply-banded-bass-boost Define variable 14 Flatsize 70 + 52 Defining Behaviors 7 Flet 67 +Apply-banded-delay 52 Defmacro 64 Float 68 +Apply-banded-treble-boost Defun 64 Floatp 66 + 52 Delay 22 Flute 24 +Approximation 21 Delay, variable 29, 29 Flute sound 3 +Arc-sine-dist 46 Delete 66 Flute-all 24 +Arcsine distribution 46 Delete-if 66 Flute-freq 24 +Aref 65 Delete-if-not 66 FM synthesis 11 +Areson 23 Demos, bell sound 3 Fmfb 21 +Args 42 Demos, distortion 23 Fmlfo 19 +Arguments to a lispDemos, drum machine 3 Fmosc 21 + function 42 Demos, drum sound 3 Fn button 4 +Arithmetic Functions 68 Demos, fft 35 Follow 18 +Arpeggiator 3 Demos, FM 11 Follower 29 +Array from sound 18 Demos, FM synthesis 3 Force-srate 19 +Array Functions 65 Demos, formants 3 Format 70 +Array notation, sal 13 Demos, gong sound 3 Fourth 65 +Arrayp 66 Demos, lpc 41 Frequency analysis 25 +Articulation 36, 37 Demos, midi 36 Frequency Modulation 10 +Assoc 65 Demos, piano 51 Full path name 42 +Asterisk 36 Demos, pitch change 29 Funcall 64 +At 25 Demos, rhythmic patternFunction 64 +At Transformation 7 3 Function calls, sal 13 +At, sal 13 Demos, ring modulation 2Function, sal 14 +At-abs 25 Demos, sample-by-sampleFundamenal frequency +At-abs, sal 13 3 estimation 25 +Atan 68 Demos, scratch tutorial +Atom 66 11 Gain 51 +Atone 23 Demos, Shepard tones 23 Gamma-dist 45 +Attributes 36 Demos, spectral analysisGate 18, 29 +Audio markers 27 of a chord 3 Gaussian distribution 46 +Automatic gain controlDemos, voice synthesisGaussian-dist 46 + 51 23 Gc 71 +Autonorm-off 10, 27 Demos, wind sound 11 Gcd 68 +Autonorm-on 10, 27 Derivative 20 GEN05 22 +Average 29 Describe 50 Gensym 65 + Destructive List FunctionsGeometric distribution +Backquote 64 66 46 +Backward 51 Developing code 42 Geometric-dist 46 +Baktrace 68 Diff 26 Get 65 +Banded bass boost 52 Difference 50 Get char 70 +Banded delay 52 Difference of sounds 26 Get-duration 19 +Get-env 71 Make-sum 44 Prod 20 +Get-lambda-expression 64Make-symbol 65 Product 26 +Get-loud 19 Make-window 44 Product pattern 44 +Get-output-stream-list Maketable 19 Profile 68 + 71 Mandolin 24 Profiling 64 +Get-output-stream-string Manipulation of scoresProg 67 + 71 48 Prog* 67 +Get-slider-value 29 Mapc 66 Prog1 67 +Get-sustain 19 Mapcar 66 Prog2 67 +Get-temp-path 70 Mapl 66 Progn 68 +Get-transpose 19 Maplist 66 Program 38 +Get-user 70 Mark button 4 Program change 36 +Get-warp 19 Markers, audio 27 Progv 67 +Getenv 71 Markov analysis 45 Prologic 52 +Global Variables 34 Markov pattern 44 Property List Functions +Global variables, sal 14Markov-create-rules 45 65 +Go 67 Max 68 Psetq 64 +Gong sounds 3 Maximum 25, 68 Pulse oscillator 21 +Granular synthesis 52 Maximum amplitude 10, 30Pulse-width modulation +Graphical envelope editorMaximum of two sounds 30 21 + 4 Member 65 Push 42 +Graphical equalization 4Memory usage 18 Putprop 65 +Graphical equalizer 51 MF (Adagio dynamic) 37 Pwe 22 +Grindef 42 Middle C 36 Pwe-list 22 + MIDI 36 Pwer 22 +H (Adagio Half note) 36 MIDI Clock 39 Pwer-list 22 +H 2 MIDI file 49, 50 Pwev 22 +Half note 2, 36 MIDI program 37 Pwev-list 22 +Harmonic 19 Midi-show 52 Pwevr 22 +Hash 65 Midi-show-file 52 Pwevr-list 22 +Hd 2 Mikrokosmos 38 Pwl 21 +Header file format 59 Min 68 Pwl-list 21 +Heap pattern 44 Minimoog 53 Pwlr 21 +High-pass filter 23 Minimum 25, 68 Pwlr-list 22 +Highpass2 23 Minusp 66 Pwlv 21 +Highpass4 23 Mix 26 Pwlv-list 21 +Highpass6 23 Mix to file 28 Pwlvr 22 +Highpass8 23 Mkwave 1 Pwlvr-list 22 +Hp 23 Modalbar 24 +Ht 2 Modulation wheel 38 Q (Adagio Quarter note) +Hyperbolic-cosine-dist Modulo (rem 68 36 + 45 Mono to stereo 52 Q 2 +Hz-to-step 18 Moog 53 Qd 2 +Hzosc 20 Moving average 29 Qt 2 + MP (Adagio dynamic) 37 Quantize 25 +I (Adagio eIght note) 36Mult 2, 19, 26 Quarter note 2, 36 +I 2 Multichannel Sounds 17 Quote 64 +Iannis Xenakis 4 Multiple band effects 52 +Id 2 Multiple commands 38 R (Adagio Rest) 36 +IDE 1 Multiple tempi 39 Ramp 25 +If 67 Multiplication 30 Random 42, 45, 68 +If statement, sal 14 Multiply signals 26 Random pattern 43 +Ifft 35 My-note 2 Rate 36, 37 +Incf 42 Read 70 +Increment 42 N (Adagio Next) 36 Read directory 70 +Info 71 Natural 36 Read macros 63 +Info button 4 Natural log 25 Read samples 17 +Input from a File 72 Nband 51 Read samples from file +Input/Output FunctionsNband-range 51 27 + 70 Nconc 66 Read samples in reverse +Installation 1 Nested Transformations 7 51 +Int-char 70 Newfile button 4 Read-byte 71 +Integerp 66 Next Adagio command 36 Read-char 70 +Integrate 20 Next in pattern 43 Read-float 71 +Integrated DevelopmentNext pattern 43 Read-int 70 + Environment 1 Nintendo WiiMote 19 Read-line 71 +Intern 65 Noise 25 Readtables 63 +Interoperability, sal andNoise gate 29 Real-random 42 + lisp 15 Noise-gate 18 Recip 25 +Interpolate 50 Normalization 10 Reciprocal 25 +Intersection 50 Not 66 Rem 68 +Intgen 59 Not enough memory forRemainder 68 +Inverse 30 normalization 10Remove 65 +Inverse fft 35 Notch filter 23 Remove-if 65 +It 2 Notch2 23 Remove-if-not 65 + Note list 26 Remprop 65 +Jcrev 23 Nrev 23 Replace file samples 28 +Jitter 49 Nstring-downcase 69 Replay button 4 + Nstring-upcase 69 Require-from 42 +K (Adagio control) 38 Nth 65 Resample 20 +Karplus-Strong 21 Nthcdr 65 Resampling 19, 29 +Karplus-Strong synthesisNull 66 Rescaling 10 + 3 Numberp 66 Resolution 38 +Keyword parameters 47 Ny:all 3 Reson 23 + NyquistIDE 1 Rest 25, 65 +Labels 67 Restore 71 +Lambda 64 O (Adagio control) 38 Rests 36 +Lambda Lists 63 Object 64 Return 67 +Last 65 Object Class 64 Return statement, sal 15 +Latency 19 Objectp 66 Return-from 67 +Legato 26, 37 Objects 63 Reverb 23, 31, 52 +Length 65 Octave specification 36 Reverse 65 +Length pattern 44 Oddp 67 Reverse, sound 51 +Length-of-beat 53 Offset 49 Ring modulation 2 +Let 67 Offset to a sound 29 Risset 3 +Let* 67 Omissions iii Rms 25, 29 +Lexical conventions 62 Oneshot 30 Room 71 +LF (Adagio dynamic) 37 Open 70 Rplaca 66 +Lf 2 Open sound control 19,Rplacd 66 +LFF (Adagio dynamic) 37 58 Rrandom 68 +Lff 2 Open-binary 70 +LFFF (Adagio dynamic) 37Openfile button 4 S (Adagio Sharp) 36 +Lfff 2 Or 67 S (Adagio Sixteenth note) +Lfo 19 Osc 1, 19, 20 36 +Libraries 51 Osc-enable 19 S 2 +Limit 24 Osc-note 25 S-abs 24 +Limiter 18 Osc-pulse 21 S-add-to 28 +Line pattern 43 Osc-saw 20 S-exp 25 +Linear distribution 45 Osc-tri 21 S-log 25 +Linear interpolation 50 Output samples to fileS-max 10, 25 +Linear Prediction 41 27 S-min 10, 25 +Linear prediction tutorialOutput to a File 72 S-overwrite 28 + 41 Overlap 26 S-plot 28 +Linear-dist 45 Overwrite samples 28 S-print-tree 28 +Linear-to-db 18 S-read 27 +Lisp button 4 P (Adagio dynamic) 37 S-read-reverse 51 +Lisp DSP 3, 11 P (Adagio Pitch) 36 S-rest 25 +Lisp Include Files 60 Palindrome pattern 43 S-reverse 51 +List 65 Pan 20, 52 S-save 27 +List directory 70 Pan, stereo 52 S-sqrt 24 +List Functions 65 Parameters, keyword 47 SAL 13 +Listdir 70 Params-scale 50 Sal and lisp 15 +Listing of lisp functionParams-transpose 50 SAL button 4 + 42 Partial 20 Sal expressions 13 +Listp 66 Path, current 42 Sample interpolation 30 +Little endian 71 Pattern, length 44 Sample rate, forcing 19 +LMF (Adagio dynamic) 37 Pattern, window 44 Sample rates 7 +Lmf 2 Pattern, accumulate 44 Sampler 21 +LMP (Adagio dynamic) 37 Pattern, accumulation 44Samples 17, 18 +Lmp 2 Pattern, copier 44 Samples, reading 17 +Load 71 Pattern, cycle 43 Sampling rate 18 +Load button 4 Pattern, eval 44 Save 71 +Load file conditionallyPattern, expression 44 Save samples to file 27 + 42 Pattern, heap 44 Save-lpc-file 41 +Load statement, sal 14 Pattern, line 43 Save-workspace 50 +Local-to-global 19 Pattern, markov 44 Savefile button 4 +Log 18 Pattern, palindrome 43 Saving Sound Files 10 +Log function 18 Pattern, product 44 Sawtooth oscillator 20 +Logand 68 Pattern, random 43 Sawtooth wave 2 +Logical-stop 17 Pattern, sum 44 Sax 24 +Logior 69 Patternp 50 Sax-all 24 +Logistic distribution 46Peak 30 Sax-freq 24 +Logistic-dist 46 Peak amplitude 10 Scale 20 +Lognot 69 Peak, maximum amplitudeScale-db 20 +Logorithm 25 30 Scale-srate 20 +Logxor 69 Peek 71 Scan directory 70 +Loop 67 Peek-char 70 Score 26 +Loop examples, sal 15 Period estimation 25 Score manipulation 48 +Loop statement, sal 14 Phaser 51 Score, musical 2 +Looping Constructs 67 Physical model 3 Score-adjacent-events 49 +Loud 26 Piano synthesizer 51 Score-append 49 +Loud-abs 26 Piano synthesizer tutorialScore-apply 49 +Loudness 36, 37 51 Score-filter 49 +Low-frequency oscillatorPiano-midi 51 Score-filter-length 49 + 19 Piano-midi2file 51 Score-filter-overlap 49 +Low-pass filter 22, 31 Piano-note 51 Score-gen 47 +Lower-case-p 69 Piano-note-2 51 Score-get-begin 49 +Lowpass2 23 Piece-wise 21 Score-get-end 49 +Lowpass4 23 Piece-wise linear 30 Score-indexof 49 +Lowpass6 23 Pitch 36 Score-last-indexof 49 +Lowpass8 23 Pitch bend 38 Score-merge 49 +LP (Adagio dynamic) 37 Pitch detection 25 Score-must-have-begin-end +Lp 2, 22 Pitch notation 2 49 +LPC 41 Pitch shift 24, 31 Score-play 49 +Lpc tutorial 41 Pitch shifting 29 Score-print 49 +Lpc-frame-err 41 Pitshift 24 Score-randomize-start 49 +Lpc-frame-filter-coefs Pl-center 52 Score-read-smf 49 + 41 Pl-doppler 53 Score-repeat 49 +Lpc-frame-rms1 41 Pl-left 52 Score-scale 49 +Lpc-frame-rms2 41 Pl-pan2d 52 Score-select 49 +LPP (Adagio dynamic) 37 Pl-position 53 Score-set-begin 49 +Lpp 2 Pl-rear 52 Score-set-end 49 +LPPP (Adagio dynamic) 37Pl-right 52 Score-shift 48 +Lppp 2 Play 1, 27 Score-sort 48 +Lpreson 41 Play in reverse 51 Score-sorted 48 + Play-file 27 Score-stretch 48 +M (Adagio control) 38 Plot 28 Score-stretch-to-length +Macroexpand 64 Pluck 21 49 +Macroexpand-1 64 Plucked string 21 Score-sustain 49 +Macrolet 67 Plusp 66 Score-transpose 48 +Make-accumulate 44 Poisson distribution 47 Score-voice 49 +Make-accumulation 44 Poisson-dist 47 Score-write-smf 50 +Make-array 65 Poke 71 Scratch sound 11 +Make-copier 44 Polyrhythm 39 Sd 2 +Make-cycle 43 Pop 42 Second 65 +Make-eval 44 Portamento switch 38 Sections, Adagio 38 +Make-heap 44 Power 42 Self 64 +Make-length 44 PP (Adagio dynamic) 37 Semicolon, Adagio 38 +Make-line 43 PPP (Adagio dynamic) 37 Seq 26 +Make-lpanal-iterator 41 Pprint 70 Seqrep 26 +Make-lpc-file-iterator Prcrev 23 Sequences 2, 36 + 41 Predicate Functions 66 Sequence_example.htm 2 +Make-markov 44 Preset 37 Sequential behavior 6 +Make-palindrome 43 Prin1 70 Set 64 +Make-product 44 Princ 70 Set intersection 50 +Make-random 43 Print 70 Set statement, sal 15 +Make-string-input-stream Print midi file 52 Set union 50 + 71 Print statement, sal 15 Set-control-srate 7, 18 +Make-string-output-stream Probability distributionsSet-difference 50 + 71 45 Set-logical-stop 26 +Set-pitch-names 18 Stk clarinet 24, 32 ~= 13 +Set-sound-srate 7, 18 STK flute 24, 32 ~~ 13 +Setdir 70 STK glass harmonica 24 +Setf 64 STK jcreverb 23 +Seti commnad 40 STK mandolin 32 +Setq 64 STK mandolon 24 +Setup nyquist 1 STK modal bar 24, 32 +Setup-console 71 STK nreverb 23 +Setv command 40 STK pitch shift 24, 31 +Sf-granulate 52 STK prcreverb 23 +Sf-info 28 STK reverb 31 +Shape 23 Stk sax 24, 32 +Sharp 36 STK sitar 24, 33 +Shepard tones 3, 23 STK tibetan bowl 24 +Shift-time 20 STK tuned bar 24 +Show midi file 52 STK uniform bar 24 +Show-lpc-data 41 Stkchorus 23 +Signal composition 29,Stochastic functions 45 + 30 Strcat 69 +Signal multiplication 30Streamp 66 +Signal-start 17 Stretch 2, 26 +Signal-stop 17 Stretch Transformation 7 +Sim 1, 26 Stretch, sal 13 +Simrep 26 Stretch-abs 26 +Simultaneous Behavior 6 Stretching Sampled Sounds +Sin 68 10 +Sine 20 String 69 +Siosc 21 String Functions 69 +Sitar 24 String Stream Functions +Sixteenth note 2, 36 71 +Sixtyfourth note 36 String synthesis 21 +Slope 20 String-downcase 69 +Smooth 20 String-equalp 69 +Snd-abs 29 String-greaterp 69 +Snd-add 29 String-left-trim 69 +Snd-allpoles 41 String-lessp 69 +Snd-alpass 30 String-not-equalp 69 +Snd-alpasscv 30 String-not-greaterp 69 +Snd-alpassvv 30 String-not-lessp 69 +Snd-amosc 32 String-right-trim 69 +Snd-areson 30 String-search 69 +Snd-aresoncv 31 String-trim 69 +Snd-aresonvc 31 String-upcase 69 +Snd-aresonvv 31 String/= 69 +Snd-atone 31 String< 69 +Snd-atonev 31 String<= 69 +Snd-avg 29 String= 69 +Snd-bandedwg 32 String> 69 +Snd-biquad 31 String>= 69 +Snd-bowed 32 Stringp 66 +Snd-bowed-freq 32 Sublis 66 +Snd-buzz 32 Subseq 69 +Snd-chase 31 Subset 50 +Snd-clarinet 32 Subsetp 50 +Snd-clarinet-all 32 Subst 66 +Snd-clarinet-freq 32 Suggestions iii +Snd-clip 29 Sum pattern 44 +Snd-compose 29 Sum 26 +Snd-congen 31 Surround Sound 52 +Snd-const 28 Sustain 26 +Snd-convolve 31 Sustain-abs 26 +Snd-copy 29 Swap channels 52 +Snd-coterm 28 Swapchannels 52 +Snd-delay 31 Symbol Functions 64 +Snd-delaycv 31 Symbol-function 65 +Snd-down 29 Symbol-name 65 +Snd-exp 29 Symbol-plist 65 +Snd-extent 17 Symbol-value 65 +Snd-fetch 17 Symbolp 66 +Snd-fetch-array 17 Symbols 64 +Snd-fft 35 Synchronization 39 +Snd-flatten 17 System Functions 71 +Snd-flute 32 +Snd-flute-all 32 T (Adagio Triplet) 36 +Snd-flute-freq 32 T 36 +Snd-fmfb 32 Table 23 +Snd-fmfbv 32 Table memory 18 +Snd-fmosc 32 Tagbody 67 +Snd-follow 29 Tan 68 +Snd-from-array 17 Tap 29 +Snd-fromarraystream 17 Tapped delay 23 +Snd-fromobject 17 Tapv 23 +Snd-gate 29 Temp file 70 +Snd-ifft 35 Tempo 36, 37 +Snd-inverse 30 Temporary files 70 +Snd-length 18 Temporary sound files +Snd-log 30 directory 27 +Snd-lpanal 41 Terpri 70 +Snd-lpreson 41 The Format Function 70 +Snd-mandolin 32 The Program Feature 67 +Snd-max 30 Third 65 +Snd-maxsamp 18 Thirtysecond note 36 +Snd-maxv 30 Threshold 30 +Snd-modalbar 32 Throw 67 +Snd-multiseq 33 Time 36, 37 +Snd-normalize 30 Time shift, sal 13 +Snd-offset 29 Time Structure 26 +Snd-oneshot 30 Time units 38 +Snd-osc 32 Timed-seq 26 +Snd-overwrite 28 Tone 23 +Snd-partial 32 Top button 4 +Snd-play 18 Top-level 68 +Snd-pluck 32 Touch tone 52 +Snd-print 18 Trace 68 +Snd-print-tree 18, 28 Transformation environment +Snd-prod 30 6 +Snd-pwl 30 Transformations 6, 25 +Snd-quantize 30 Transpose 26 +Snd-read 28 Transpose-abs 26 +Snd-recip 30 Triangle oscillator 21 +Snd-resample 30 Triangle wave 2 +Snd-resamplev 30 Trigger 26 +Snd-reson 31 Trill 40 +Snd-resoncv 31 Triplet 36 +Snd-resonvc 31 Triplet durations 2 +Snd-resonvv 31 Truncate 68 +Snd-samples 18 Tuba 3 +Snd-save 28 Tuning 19 +Snd-sax 32 Tutorial, FM 11 +Snd-sax-all 33 Type-of 71 +Snd-sax-freq 32 +Snd-scale 30 U 36 +Snd-seq 33 Uniform random 42, 68 +Snd-set-latency 19 Union 50 +Snd-set-logical-stop 18 Unless 67 +Snd-shape 30 Untrace 68 +Snd-sine 32 Unwind-protect 67 +Snd-siosc 32 UPIC 4 +Snd-sitar 33 Upper-case-p 69 +Snd-slider 29 User name 70 +Snd-sqrt 29 +Snd-srate 18 V (Adagio Voice) 37 +Snd-sref 18 Variable delay 23, 29 +Snd-stkchorus 31 Variable-resample function +Snd-stkpitshift 31 29 +Snd-stkrev 31 Vector 65 +Snd-stop-time 18 Velocity 37 +Snd-t0 18 Vinal scratch 11 +Snd-tapf 29 Vocal sound 3 +Snd-tapv 29 Voice 36, 37 +Snd-time 18 Voice synthesis 23 +Snd-tone 31 Volume 38 +Snd-tonev 31 +Snd-trigger 33 W (Adagio Whole note) 36 +Snd-up 30 W 2 +Snd-white 29 Warble 11 +Snd-xform 30 Warp 26 +Snd-yin 30 Warp-abs 26 +Snd-zero 29 Waveforms 2, 19 +Soften-clipping 51 Waveshaping 23 +Sort 66 Wavetables 2, 19 +Sound 19 Wd 2 + accessing point 17 Wg-glass-harm 24 + creating from arrayWg-tibetan-bowl 24 + 17 Wg-tuned-bar 24 +Sound browser, jnyqide 4Wg-uniform-bar 24 +Sound file directoryWhen 42, 67 + default 27 While 42 +Sound file I/O 27 Whole note 2, 36 +Sound file info 28 Widen 52 +Sound from Lisp data 17 Wii Controller 19 +Sound-off 27 Wind sound 11 +Sound-on 27 Window initialization 71 +Sound-srate-abs 26 Window pattern 44 +Sound-warp 20 Wind_tutorial.htm 11 +Soundfilename 28 With statement, sal 15 +Soundp 18 Wood drum sound 3 +Sounds 17 Workspace 4, 50 +Sounds vs. Behaviors 6 Write samples to file 27 +Span 52 Write-byte 71 +Spatialization 52 Write-char 70 +Special command 36 Write-float 71 +Spectral interpolationWrite-int 70 + 21 Wt 2 +Speed-dial 52 +Splines 21 X (Adagio control) 38 +Sqrt 68 Xenakis 4 +Square oscillator 21 XLISP Command Loop 62 +Square root 24, 29 XLISP Data Types 62 +Srate 17 XLISP evaluator 62 +Sref 17 XLISP Lexical Conventions +Sref-inverse 17 62 +St 2 Xmusic 43 +Stacatto 26 +Staccato 37 Y (Adagio control) 38 +Stack trace 68 Yin 25 +Standard MIDI File 49 +Statements, sal 13 Z (Adagio program) 37, +Stats 18 38 +Step-to-hz 19 Zerop 66 +Stereo 52 +Stereo pan 52 ^ (Adagio sixtyfourth +Stereo panning 20 note) 36 +Stereo-chorus 51 ^ 13 +Stereoize 52 ^= 15 +STK banded waveguide 32 +Stk bowed 32 | 13 +STK bowed string 24 +STK bowed-freq 24 ~ (Adagio) 38 +STK chorus 23, 31 ~ 13 + Table of Contents + +Preface iii + +1. Introduction and Overview 1 + + 1.1. Installation 1 + 1.2. Using NyquistIDE 1 + 1.3. Using SAL 1 + 1.4. Helpful Hints 1 + 1.5. Using Lisp 1 + 1.6. Examples 1 + 1.6.1. Waveforms 1 + 1.6.2. Wavetables 2 + 1.6.3. Sequences 2 + 1.6.4. Envelopes 2 + 1.6.5. Piece-wise Linear Functions 2 + 1.7. Predefined Constants 2 + 1.8. More Examples 3 + +2. The NyquistIDE Program 4 + + 2.1. NyquistIDE Overview 4 + 2.2. The Button Bar 4 + 2.3. Command Completion 4 + 2.4. Browser 4 + 2.5. Envelope Editor 4 + 2.6. Equalizer Editor 4 + 2.7. UPIC Editor 4 + +3. Behavioral Abstraction 6 + + 3.1. The Environment 6 + 3.2. Sequential Behavior 6 + 3.3. Simultaneous Behavior 6 + 3.4. Sounds vs. Behaviors 6 + 3.5. The At Transformation 7 + 3.6. The Stretch Transformation 7 + 3.7. Nested Transformations 7 + 3.8. Defining Behaviors 7 + 3.9. Overriding Default Transformations 7 + 3.10. Sample Rates 7 + +4. Continuous Transformations and Time Warps 8 + + 4.1. Simple Transformations 8 + 4.2. Time Warps 8 + 4.3. Abstract Time Warps 8 + 4.4. Nested Transformations 9 + +5. More Examples 10 + + 5.1. Stretching Sampled Sounds 10 + 5.2. Saving Sound Files 10 + 5.3. Memory Space and Normalization 10 + 5.4. Frequency Modulation 10 + 5.5. Building a Wavetable 11 + 5.6. Filter Examples 11 + 5.7. DSP in Lisp 11 + +6. SAL 13 + + 6.1. SAL Syntax and Semantics 13 + 6.1.1. Expressions 13 + 6.1.1.1. Simple Expressions 13 + 6.1.1.2. Operators 13 + 6.1.1.3. Function Calls 13 + 6.1.1.4. Array Notation 13 + 6.1.1.5. Conditional Values 13 + 6.1.2. SAL Statements 13 + 6.1.2.1. begin and end 13 + 6.1.2.2. chdir 14 + 6.1.2.3. define variable 14 + 6.1.2.4. define function 14 + 6.1.2.5. display 14 + 6.1.2.6. exec 14 + 6.1.2.7. if 14 + 6.1.2.8. when 14 + 6.1.2.9. unless 14 + 6.1.2.10. load 14 + 6.1.2.11. loop 14 + 6.1.2.12. print 15 + 6.1.2.13. return 15 + 6.1.2.14. set 15 + 6.1.2.15. with 15 + 6.1.2.16. exit 15 + 6.2. Interoperability of SAL and XLISP 15 + 6.2.1. Function Calls 15 + 6.2.2. Symbols and Functions 15 + 6.2.3. Playing Tricks On the SAL Compiler 16 + +7. Nyquist Functions 17 + + 7.1. Sounds 17 + 7.1.1. What is a Sound? 17 + 7.1.2. Multichannel Sounds 17 + 7.1.3. Accessing and Creating Sound 17 + 7.1.4. Miscellaneous Functions 18 + 7.2. Behaviors 19 + 7.2.1. Using Previously Created Sounds 19 + 7.2.2. Sound Synthesis 19 + 7.2.2.1. Oscillators 20 + 7.2.2.2. Piece-wise Approximations 21 + 7.2.2.3. Filter Behaviors 22 + 7.2.2.4. Effects 23 + 7.2.2.5. Physical Models 24 + 7.2.2.6. More Behaviors 24 + 7.3. Transformations 25 + 7.4. Combination and Time Structure 26 + 7.5. Sound File Input and Output 27 + 7.6. Low-level Functions 28 + 7.6.1. Creating Sounds 28 + 7.6.2. Signal Operations 29 + 7.6.3. Filters 30 + 7.6.4. Table-Lookup Oscillator Functions 31 + 7.6.5. Physical Model Functions 32 + 7.6.6. Sequence Support Functions 33 + +8. Nyquist Globals 34 + +9. Time/Frequency Transformation 35 + +10. MIDI, Adagio, and Sequences 36 + + 10.1. Specifying Attributes 36 + 10.1.1. Time 36 + 10.1.2. Pitch 36 + 10.1.3. Duration 36 + 10.1.4. Next Time 36 + 10.1.5. Rest 36 + 10.1.6. Articulation 37 + 10.1.7. Loudness 37 + 10.1.8. Voice 37 + 10.1.9. Timbre (MIDI Program) 37 + 10.1.10. Tempo 37 + 10.1.11. Rate 37 + 10.2. Default Attributes 37 + 10.3. Examples 37 + 10.4. Advanced Features 38 + 10.4.1. Time Units and Resolution 38 + 10.4.2. Multiple Notes Per Line 38 + 10.4.3. Control Change Commands 38 + 10.4.4. Multiple Tempi 39 + 10.4.5. MIDI Synchronization 39 + 10.4.6. System Exclusive Messages 39 + 10.4.7. Control Ramps 39 + 10.4.8. The !End Command 40 + 10.4.9. Calling C Routines 40 + 10.4.10. Setting C Variables 40 + +11. Linear Prediction Analysis and Synthesis 41 + + 11.1. LPC Classes and Functions 41 + 11.2. Low-level LPC Functions 41 + +12. Developing and Debugging in Nyquist 42 + + 12.1. Debugging 42 + 12.2. Useful Functions 42 + +13. Xmusic and Algorithmic Composition 43 + + 13.1. Xmusic Basics 43 + 13.2. Pattern Classes 43 + 13.2.1. cycle 43 + 13.2.2. line 43 + 13.2.3. random 43 + 13.2.4. palindrome 43 + 13.2.5. heap 44 + 13.2.6. accumulation 44 + 13.2.7. copier 44 + 13.2.8. accumulate 44 + 13.2.9. sum 44 + 13.2.10. product 44 + 13.2.11. eval 44 + 13.2.12. length 44 + 13.2.13. window 44 + 13.2.14. markov 44 + 13.3. Random Number Generators 45 + 13.4. Score Generation and Manipulation 47 + 13.4.1. Keyword Parameters 47 + 13.4.2. Using score-gen 47 + 13.4.3. Score Manipulation 48 + 13.4.4. Xmusic and Standard MIDI Files 49 + 13.4.5. Workspaces 50 + 13.4.6. Utility Functions 50 + +14. Nyquist Libraries 51 + + 14.1. Piano Synthesizer 51 + 14.2. Dymanics Compression 51 + 14.3. Clipping Softener 51 + 14.4. Graphical Equalizer 51 + 14.5. Sound Reversal 51 + 14.6. Time Delay Functions 51 + 14.7. Multiple Band Effects 52 + 14.8. Granular Synthesis 52 + 14.9. MIDI Utilities 52 + 14.10. Reverberation 52 + 14.11. DTMF Encoding 52 + 14.12. Dolby Surround(R), Stereo and Spatialization Effects 52 + 14.13. Drum Machine 53 + 14.14. Minimoog-inspired Synthesis 53 + 14.14.1. Oscillator Parameters 53 + 14.14.2. Noise Parameters 53 + 14.14.3. Filter Parameters 53 + 14.14.4. Amplitude Parameters 54 + 14.14.5. Other Parameters 54 + 14.14.6. Input Format 54 + 14.14.7. Sample Code/Sounds 54 + +I. Extending Nyquist 55 + + I.1. Translating Descriptions to C Code 55 + I.2. Rebuilding Nyquist 55 + I.3. Accessing the New Function 55 + I.4. Why Translation? 55 + I.5. Writing a .alg File 55 + I.6. Attributes 55 + I.7. Generated Names 57 + I.8. Scalar Arguments 57 + +II. Open Sound Control and Nyquist 58 + + II.1. Sending Open Sound Control Messages 58 + II.2. The ser-to-osc Program 58 + +III. Intgen 59 + + III.0.1. Extending Xlisp 59 + III.1. Header file format 59 + III.2. Using #define'd macros 59 + III.3. Lisp Include Files 60 + III.4. Example 60 + III.5. More Details 60 + +IV. XLISP: An Object-oriented Lisp 61 + + IV.1. Introduction 62 + IV.2. A Note From The Author 62 + IV.3. XLISP Command Loop 62 + IV.4. Special Characters 62 + IV.5. Break Command Loop 62 + IV.6. Data Types 62 + IV.7. The Evaluator 62 + IV.8. Lexical Conventions 62 + IV.9. Readtables 63 + IV.10. Lambda Lists 63 + IV.11. Objects 63 + IV.12. The ``Object'' Class 64 + IV.13. The ``Class'' Class 64 + IV.14. Profiling 64 + IV.15. Symbols 64 + IV.16. Evaluation Functions 64 + IV.17. Symbol Functions 64 + IV.18. Property List Functions 65 + IV.19. Array Functions 65 + IV.20. List Functions 65 + IV.21. Destructive List Functions 66 + IV.22. Predicate Functions 66 + IV.23. Control Constructs 67 + IV.24. Looping Constructs 67 + IV.25. The Program Feature 67 + IV.26. Debugging and Error Handling 68 + IV.27. Arithmetic Functions 68 + IV.28. Bitwise Logical Functions 68 + IV.29. String Functions 69 + IV.30. Character Functions 69 + IV.31. Input/Output Functions 70 + IV.32. The Format Function 70 + IV.33. File I/O Functions 70 + IV.34. String Stream Functions 71 + IV.35. System Functions 71 + IV.36. File I/O Functions 72 + IV.36.1. Input from a File 72 + IV.36.2. Output to a File 72 + IV.36.3. A Slightly More Complicated File Example 72 + +Index 74 + List of Figures + Figure 1: An envelope generated by the env function. 2 + Figure 2: The result of (warp4), intended to map 4 seconds of score 8 + time into 4 seconds of real time. The function extends + beyond 4 seconds (the dashed lines) to make sure the + function is well-defined at location (4, 4). Nyquist + sounds are ordinarily open on the right. + Figure 3: When (warp4) is applied to (tone-seq-2), the note onsets 8 + and durations are warped. + Figure 4: When (warp4) is applied to (tone-seq-3), the note onsets 9 + are warped, but not the duration, which remains a constant + 0.25 seconds. In the fast middle section, this causes + notes to overlap. Nyquist will sum (mix) them. + Figure 5: The shift-time function shifts a sound in time according to 20 + its shift argument. + Figure 6: Ramps generated by pwl and ramp functions. The pwl version 25 + ramps toward the breakpoint (1, 1), but in order to ramp + back to zero at breakpoint (1, 0), the function never + reaches an amplitude of 1. If used at the beginning of a + seq construct, the next sound will begin at time 1. The + ramp version actually reaches breakpoint (1, 1); notice + that it is one sample longer than the pwl version. If used + in a sequence, the next sound after ramp would start at + time 1 + P, where P is the sample period. + Figure 7: The Linear Distribution, g = 1. 45 + Figure 8: The Exponential Distribution, delta = 1. 45 + Figure 9: The Gamma Distribution, nu = 4. 45 + Figure 10: The Bilateral Exponential Distribution. 45 + Figure 11: The Cauchy Distribution, tau = 1. 46 + Figure 12: The Hyperbolic Cosine Distribution. 46 + Figure 13: The Logistic Distribution, alpha = 1, beta = 2. 46 + Figure 14: The Arc Sine Distribution. 46 + Figure 15: The Gauss-Laplace (Gaussian) Distribution, xmu = 0, sigma 46 + = 1. + Figure 16: The Beta Distribution, alpha = .5, beta = .25. 46 + Figure 17: The Bernoulli Distribution, px1 = .75. 46 + Figure 18: The Binomial Distribution, n = 5, p = .5. 47 + Figure 19: The Geometric Distribution, p = .4. 47 + Figure 20: The Poisson Distribution, delta = 3. 47 + Figure 21: System diagram for Minimoog emulator. 53 diff --git a/doc/nyquistman.pdf b/doc/nyquistman.pdf new file mode 100644 index 0000000..b98a59c Binary files /dev/null and b/doc/nyquistman.pdf differ diff --git a/doc/part1.html b/doc/part1.html new file mode 100644 index 0000000..26c767e --- /dev/null +++ b/doc/part1.html @@ -0,0 +1,72 @@ +Preface + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Preface

+This manual is a guide for users of Nyquist, a language for composition and +sound synthesis. Nyquist grew out of a series of research projects, notably +the languages Arctic and Canon. Along with Nyquist, these languages promote a +functional style of programming and incorporate time into the language +semantics. +

+Please help by noting any errors, omissions, +or suggestions you may have. You can send your +suggestions to Dannenberg@CS.CMU.EDU (internet) via computer mail, or by +campus mail to Roger B. Dannenberg, School of Computer Science, or by +ordinary mail to Roger B. Dannenberg, School of Computer Science, Carnegie +Mellon University, 5000 Forbes Ave., Pittsburgh, PA 15213-3890, USA. +

+Nyquist is a successor to Fugue, a language originally implemented by Chris +Fraley, and extended by George Polly and Roger Dannenberg. Peter Velikonja +and Dean Rubine were early users, and they proved the value as well as +discovered some early problems of the system. This led to Nyquist, a +reimplementation of Fugue by Roger Dannenberg with help from Joe Newcomer +and Cliff Mercer. Ning Hu ported Zheng (Geoffrey) Hua and Jim Beauchamp's +piano synthesizer to Nyquist and also built NyqIDE, the Nyquist Integrated +Development Environment for Windows. Dave Mowatt contributed the original +version of NyquistIDE, the cross-platform interactive development environment. +Dominic Mazzoni made a special version of Nyquist that runs +within the Audacity audio editor, giving Nyquist a new interface and +introducing Nyquist to many new users. +

+Many others have since contributed to Nyquist. +Chris Tchou and Morgan Green worked on the Windows port. Eli Brandt contributed +a number of filters and other synthesis functions. Pedro J. Morales, +Eduardo Reck Miranda, Ann Lewis, and Erich Neuwirth have all contributed +nyquist examples found in the demos folder of the Nyquist distribution. +Philip Yam ported some +synthesis functions from Perry Cook and Gary Scavone's STK to Nyquist. +Pedro Morales ported many more STK instruments to Nyquist. +Dave Borel wrote the Dolby Pro-Logic encoding library and Adam Hartman wrote +stereo and spatialization effects. Stephen Mangiat wrote the MiniMoog +emulator. Phil Light recorded the drum samples and wrote drum +machine software. The Xmusic library, particularly the pattern specification, +was inspired by Rick Taube's Common Music. The functions for generating +probability distributions were implemented by Andreas Pfenning. +

+Starting with Version 3, Nyquist supports a version of SAL, providing +an alternative to Lisp syntax. SAL was designed by Rick Taube, and the +SAL implementation in Nyquist is based on Taube's original implementation +as part of his Common Music system. +

+The current NyquistIDE includes contributions from many. Chris Yealy and +Derek D'Souza implemented early versions of the envelope editor. Daren +Makuck and Michael Rivera wrote the original equalizer editor. +Priyanka Raghavan implemented the sound browser. Dmitry Portnoy wrote the +original "UPIC" editor. +

+Many others have made contributions, offered suggestions, and found bugs. +If you were expecting to find your name here, I apologize for the omission, +and please let me know. +

+I also wish to acknowledge support from CMU, Yamaha, and IBM for this work. + + +

+ + + + +


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part10.html b/doc/part10.html new file mode 100644 index 0000000..0e67dc8 --- /dev/null +++ b/doc/part10.html @@ -0,0 +1,77 @@ +Time/Frequency Transformation + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Time/Frequency Transformation

+Nyquist provides functions for FFT and inverse FFT operations on streams of audio data. +Because sounds can be of any length, but an FFT operates on a fixed amount of data, FFT +processing is typically done in short blocks or windows that move through the audio. Thus, +a stream of samples is converted in to a sequence of FFT frames representing short-term +spectra. +

+Nyquist does not have a special data type corresponding to a sequence of FFT frames. +This would be nice, but it would require creating a large set of operations suitable for +processing frame sequences. Another approach, and perhaps the most "pure" would +be to convert a single sound into a multichannel sound, with one channel per bin of the +FFT. +

+Instead, Nyquist violates its "pure" functional model and resorts to objects +for FFT processing. A sequence of frames is represented by an XLISP object. Whenever you +send the selector :next to the object, you get back either NIL, indicating the +end of the sequence, or you get an array of FFT coefficients. +

+The Nyquist function snd-fft (mnemonic, isn't it?) returns one of the frame sequence +generating objects. You can pass any frame sequence generating object to another function, +snd-ifft, and turn the sequence back into audio. +

+With snd-fft and snd-ifft, you can create all sorts of interesting processes. The main +idea is to create intermediate objects that both accept and generate sequences of frames. +These objects can operate on the frames to implement the desired spectral-domain +processes. Examples of this can be found in the file +fft_tutorial.htm, +which is part of the standard Nyquist release. The documentation for snd-fft and +snd-ifft follows. +

+

+
+snd-fft(sound, length, skip, window) [SAL]
+ +(snd-fft sound length skip window) [LISP]
This +function performs an FFT on the first samples in sound and returns a Lisp array of FLONUMs. +The function modifies the sound, violating the normal rule that sounds are immutable in Nyquist, so +it is advised that you copy the sound using snd-copy if there are any other references to +sound. The length of the FFT is specified by length, a FIXNUM (integer) which must +be a power of 2. After +each FFT, the sound is advanced by skip samples, also of type FIXNUM. Overlapping FFTs, +where skip is less than length, are allowed. If window is not NIL, it must be a sound. +The first length samples of window are multiplied by length samples of sound before +performing the FFT. When there are no more samples in sound to transform, +this function returns NIL. The coefficients in the returned array, in order, are the DC coefficient, +the first real, the first imaginary, the second real, the second imaginary, etc. +The last array element corresponds to the real coefficient at the Nyquist frequency.

+
snd-ifft(time, srate, iterator, skip, window) [SAL]
+ +(snd-ifft time srate iterator skip window) [LISP]
This function performs an IFFT on a sequence of spectral frames obtained from iterator +and returns a sound. The start time of the sound is given by time. Typically, this would be computed +by calling (local-to-global 0). The sample rate is given by srate. Typically, this would +be *sound-srate*, but it might also depend upon the sample rate of the sound from which the +spectral frames were derived. To obtain each frame, the function sends the message :next to the +iterator object, using XLISP's primitives for objects and message passing. The object should return +an array in the same format as obtained from snd-fft, and the object should return NIL +when the end of the sound is reached. After each frame is inverse transformed into the time domain, it is +added to the resulting sound. Each successive frame is added with a sample offset specified by skip +relative to the previous frame. This must be an integer greater than zero. If window is +not NIL, it must be a sound. This window signal is multiplied by the inverse transformed frame +before the frame is added to the output sound. The length of each frame should be the same power of 2. +The length +is implied by the array returned by iterator, so it does not appear as a parameter. This length +is also the number of samples used from window. Extra samples are ignored, and window is padded +with zeros if necessary, so be sure window is the right length. The resulting sound is computed on +demand as with other Nyquist sounds, so :next messages are sent to iterator only when new +frames are needed. One should be careful not to reuse or modify iterator once it is passed to +snd-ifft. +
+

+


+
Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part11.html b/doc/part11.html new file mode 100644 index 0000000..6fbf090 --- /dev/null +++ b/doc/part11.html @@ -0,0 +1,899 @@ +MIDI, Adagio, and Sequences + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

MIDI, Adagio, and Sequences

+ + +Nyquist includes facilities to read and write MIDI files as well as an ASCII +text-based score representation language, Adagio. XLISP and Nyquist can be +used to generate MIDI files using compositional algorithms. (See also Section "Xmusic and Algorithmic Composition".) +A tutorial on using the Adadio representation and MIDI can be found in +demos/midi_tutorial.htm. The Adagio language is +described below. Adagio was originally developed as part of the CMU MIDI +Toolkit, which included a program to record and play MIDI using the +Adagio representation. Some of the MIDI features of Adagio may not be +useful within Nyquist. +

+Nyquist offers a number of different score representations, and you may +find this confusing. In general, MIDI files are a common way to exchange +music performance data, especially with sequencers and score notation +systems. The demos/midi_tutorial.htm examples show how to get the most +precise control when generating MIDI data. Adagio is most useful as a +text-based score entry language, and it is certainly more compact +than Lisp expressions for MIDI-like data. The Xmusic library +(Chapter "Xmusic and Algorithmic Composition") is best for algorithmic generation of music +and score manipulation. There are functions to convert between the +Adagio, MIDI sequence data, and Xmusic score representations. +

+ +Adagio is an easy-to-use, non-procedural notation +for scores. In Adagio, text commands are used to specify each +note. If you are new to Adagio, you may want to glance at the +examples in Section "Examples" starting on page +"Examples" before reading any further. +

+A note is described in Adagio by a set of attributes, and +any attribute not specified is "inherited" from the previous line. +Attributes may appear in any order and must be separated by one or more +blanks. An attribute may not contain any blanks. The attributes are: +time, pitch, loudness, +voice number, duration, and articulation. +

+Adagio has been used to program a variety of hardware and software +synthesizers, and the Adagio compiler can be easily adapted to new +environments. Although not originally intended for MIDI, Adagio works quite +well as a representation for MIDI scores. Adagio has been extended to allow MIDI controller +data such as modulation wheels, pitch bend, and volume, MIDI program commands to change timbre, and System Exclusive messages. +

+A note command in Adagio must be separated from other notes. Usually, +notes are distinguished by writing each one on a separate line. +Notes can also be separated by using a comma or semicolon as will +be described below. +

+Besides notes, there are several other types of commands: +

    +
  1. +An asterisk (*) in column one (or immediately after a comma, +semicolon, or space) indicates that the rest of the line is a +comment. The line is ignored by Adagio, and is therefore a +good way to insert text to be read by people. Here are some examples: +
    +* This is a comment.
    +T150 G4  * This is a comment too!
    +T150 G4  ;* So is this.
    +
    + +
  2. An empty command (a blank line, for example) is ignored as if it +were a comment (Footnote 6) . +
  3. An exclamation point (!) in column one (or +immediately after a comma or semicolon) indicates a special +command. A special command does not generate a note. +Special commands follow the "!" with no intervening spaces and extend to the end of the line, for example: +
    +!TEMPO 100
    +
    + +
  4. Control change commands are used to control parameters like +pitch bend, modulation, and program (timbre). Control +change commands can be specified along with notes or by +themselves. +A command that specifies control changes without specifying +a pitch will not produce a note. +
+

+Adagio is insensitive to case, +thus "A" is equivalent to "a", and you +can mix upper and lower case letters freely. +

+

Specifying Attributes

+A note is indicated by a set of attributes. Attributes are indicated by a string of characters with no intervening spaces because spaces separate attributes. The attributes are described below. +

+The default unit of time is a centisecond +(100^(th)'s), but this can be changed to a millisecond (1000^(th)'s) using the !MSEC command and reset to centiseconds with !CSEC (see Section "Time Units and Resolution"). In the descriptions below, the term "time unit" will be used to mean whichever convention is currently in effect. +

+

Time

The time attribute specifies when to start the note. A time is +specified by a "T" followed by a number representing time units + or by a duration (durations are described below). Examples: +
+T150	** 1.5 sec (or .15 sec)
+TQ3	** 3 quarter note's duration
+
+ +If no time is specified, the default time
is the sum of +the time and duration attributes of the previous note. (But see Section +"Next Time".) Time is measured relative to the time of the +most recent Tempo or Rate command. (See the +examples in Section +"Examples" for some clarification of this point.) +

+

Pitch

The pitch attribute specifies what frequency to produce. +Standard scale pitches are named by name, using S for sharp, + F for flat, +and (optionally) N for natural. +For example, C and CN represent the same pitch, as do FS and GF (F sharp and G flat). Note that there are no bar lines, and accidentals to not carry forward to any other notes as in common practice notation. +

+Octaves are specified by +number. C4 is middle C, and B3 is a half step lower. F5 is the top line of +the treble clef, etc. (Adagio octave numbering follows the ISO standard, but note that this is not universal. In particular, Yamaha refers to middle C as C3.) Accidentals can go before or after +the octave number, so FS3 and F3S have the same meaning. +

+An alternate +notation for pitch is Pn, where n is an integer representing the pitch. +Middle C (C4) is equivalent to P60, CS4 is P61, etc. +

+If you do not specify an octave, +Adagio will choose one for you. This +is done by picking the octave that will make the current pitch as close +to the previous pitch as possible. In the case of augmented fourths + or diminished fifths, there are two equally good choices. Adagio +chooses the lower octave. +

+

Duration

Duration is specified by a letter indicating a number of +beats, followed by one or several modifiers. The basic duration codes are: +
+W (whole, 4 beats),
+ +H
(half, 2 beats),
+ +Q
(quarter, 1 beat),
+ +I
(eighth, 1/2 beat),
+ +S
(sixteenth, 1/4 beat),
+ +%
(thirtysecond, 1/8 beat), and
+ +^
(sixtyfourth, 1/16 beat).
+ +
+Note that E is a pitch, so eighth-notes use the duration code I. +The default tempo is 100 beats per +minute (see Section "Tempo"). These codes may be followed by a T +(triplet), indicating a duration of 2/3 the normal. A dot (.) after a +duration code extends it by half to 3/2 the normal. An integer +after a note multiplies its duration by the indicated value (the result is +still just one note). Finally, a slash followed by an integer divides +the duration by the integer. Like all attributes, duration attributes may not have embedded spaces. Examples: +
+ + +Q1 beat (quarter note)
+ +QT2/3 beat (quarter triplet)
+ +W.6 beats(dotted whole note)
+ +ST61 beat (6 sixteenth triplets)
+ +H510 beats(5 half notes)
+ +Q3/73/7 beats
+ +
+A duration may be noted by Un
, where n is an integer +indicating 100^(th)'s of a second +(or 1000^(th)'s), see Section "Time Units and Resolution". +For example, U25 is twenty-five time units. +

+Durations may be combined using a plus sign: +

+Q+IT	    ** a quarter tied to an eighth triplet
+Q/7+W+Q2/7  ** a 7th beat tied to a whole tied to 2/7th beat
+Q+U10	    ** a quarter plus 10 time units
+
+ +

+

Next Time

+ +The time of the next command (the next command in the Adagio +program text) is +normally the time of the current note command +plus the duration of the current note. +This can be overridden by a field consisting of the letter N +followed by a number indicating time units, or followed by a +duration as described above. The next note will then start at the time of +the current note plus the duration specified after N. If the next note +has an explicit time attribute (T), then the specified time will override +the one based on the previous note. Examples: +
+N0	** start the next note at the same time as this one
+N50	** start the next note 0.5 seconds after this one
+NQT	** start the next note 2/3 beat after the current one
+NU10+Q  ** start after 0.1 seconds plus a quarter
+
+ +A comma has an effect similar to N0 and is explained in Section
"Multiple Notes Per Line". Articulation effects such as staccato can be produced using N, but it is more convenient to use the articulation attribute described in Section "Articulation". +

+

Rest

+Rests are obtained by including the field R in a +note command. The effect of an R field is to omit the note that would +otherwise occur as the result of the current note command. In all other +respects, the command is processed just like any other line. This means that +attributes such as duration, loudness, and pitch can be specified, and +anything specified will be inherited by the note in the next command. +Normally, a rest will include just R and a duration. The fact that a +note command specifies a rest is not inherited. For example: +
+R H	** a half (two beat) rest
+RH	** illegal, R must be separated from H by space(s)
+
+ +Because some synthesizers (e.g. a DX7
) cannot change programs + +(presets) rapidly, it may be desirable to change programs in +a rest so that the synthesizer will be ready to play by +the end of the rest. See Section "Timbre (MIDI Program)" for an example. +

+

Articulation

+ +Articulation in Adagio refers to the +percentage of time a note is on relative to the indicated duration. For +example, to play a note staccato, you would normally play the note about +half of its indicated duration. In Adagio, articulation is indicated by +# followed by an integer number indicating a percentage. The +articulation attribute does not affect the time of the next command. This +example plays two staccato quarter notes: +
+C Q #50
+D
+
+ +To produce overlapping notes, the articulation may be greater than 100. +

+ +Be aware that overlapping notes on the same pitch can be a problem for some synthesizers. The following example illustrates this potential problem: +

+!TEMPO 60
+C Q #160   * starts at time 0,   ends at 1.6 sec
+D I        * starts at time 1,   ends at 1.8 sec
+C Q        * starts at time 1.5, ends at 3.1 sec?
+
+ +At one beat per second (tempo 60), these three notes will start at times 0, 1, and 1.5 seconds, respectively. Since these notes have an articulation of 160, each will be on 160% of its nominal duration, so the first note (C) will remain on until 1.6 seconds. But the third note (another C) will start at time 1.5 seconds. Thus, the second C will be started before the first one ends. Depending on the synthesizer, this may cancel the first C or play a second C in unison. In either case, a note-off message will be sent at time 1.6 seconds. If this cancels the second C, its actual duration will be 0.1 rather than 1.6 seconds as intended. A final note-off will be sent at time 3.1 seconds. + + +

+

Loudness

Loudness is indicated by an L +followed by a dynamic marking from the following: PPP, +PP, P, MP, MF, F, +FF, FFF. Alternatively, a number from 1 to 127 may be +used. The loudness attribute is the MIDI note velocity. (Note that a MIDI velocity of 0 means "note-off," so the minimum loudness is 1.) The +dynamic +markings are translated into numbers as follows: +
+ + +Lppp20Lmf58
+ +Lpp26Lf75
+ +Lp34Lff98
+ +Lmp44Lfff127
+ +
+

+

Voice

The voice attribute tells which of the 16 MIDI channels to use +for the note. The voice attribute consists of a V followed by +an integer from 1 (the default) to 16. + +There is a limit to how many notes +can be played at the same time on a given voice (MIDI channel). Since the +limit depends upon the synthesizer, Adagio cannot tell you when you exceed +the limit. Similarly, Adagio cannot tell whether your synthesizer is set up +to respond to a given channel, so there is no guarantee that what you write +will actually be heard. + + +

+

Timbre (MIDI Program)

+ +A MIDI program (synthesizer preset) can be +selected using the attribute Zn, where n +is the program number (from 1 to 128). +Notice that in MIDI, changing the program on a given channel will affect +all notes on that channel and possibly others. Adagio treats MIDI program changes as a form of control change. + +For many synthesizers, you will not be +able to change programs at the start of a note or during a note. Change the +program during a rest instead. For example: +
+R I Z23 V4	** change MIDI channel 4 to program 23 during rest
+A4		** play a note on channel 4
+
+ +Check how your synthesizer interprets program numbers. For example, +the cartridge programs on a DX7 can be accessed by adding 32 to the +cartridge program number. Cartridge program number 10 +is specified by Z42. +
+ +

+As in MIDI, the Adagio timbre is a property of the voice (MIDI channel), so +the timbre will not be inherited by notes on a different channel; +to change the timbre on multiple voices (channels), you must explicitly +notate each change. +

+

Tempo

+ +The length of a beat may be changed using a Tempo command: +
+!TEMPO n
+
+ +where n indicates beats per minute. The exclamation mark tells Adagio that +this is a special command line rather than a note definition. A special +command takes the place of a note specification. +No other attributes should be written on a line with a special command. +The !TEMPO command is associated with a time, computed as if the !TEMPO command were a note. The time
attribute (T) of all +succeeding notes is now measured relative to the time of the !TEMPO command. The new tempo starts at the !TEMPO command time and +affects all succeeding notes. +Durations specified in time units (for example U58, N15) are not affected by the !TEMPO command, and numerical times (for example T851) are computed relative to the time of the last !TEMPO command. +

+The !TEMPO command is fairly clever about default durations. If the last duration specified before the !TEMPO command is +symbolic (using one of ^,%, S, I, Q, H, or W ), then the default duration for the +node after the !TEMPO command will be modified according to the tempo change. +Consider the following tempo change: +

+!TEMPO 60
+A4 H
+!TEMPO 120
+G
+
+ +In this example, the first note will last 2 seconds (2 beats at 60 +beats per minute). The second note inherits the duration (H) from +the first note, but at 120 beats per minute, the second note will last +only 1 second. If the duration had been specified U200 (also a +duration of 2 seconds), the second note would also last 2 seconds because the !TEMPO command does not affect times or durations specified numerically in time units. If the duration is the sum of a symbolic and a numeric specification, the inherited duration after a !TEMPO command is undefined. +

+

Rate

+The !RATE command scales all times including those specified in +hundredths of seconds. A rate of 100 means no change, 200 means twice as +fast, and 50 means half as fast. For example, to make a piece play 10% +faster, you can add the following command at the beginning of the score: +
+!RATE 110
+
+ +!RATE and !TEMPO commands combine, so +
+!RATE 200
+!TEMPO 70
+
+ +will play 70 beats per minute at double the normal speed, or 140 beats +per minute. Like !TEMPO, the time of the !RATE command is added to the +time attribute of all following notes up to the next !TEMPO or !RATE +command. +

+Two !RATE commands do not combine, so a !RATE command only affects the rate until the next !RATE command. +

+Although !TEMPO and !RATE can occur in the middle of a note (using N, T, etc.) they do not affect a note already specified. This property allows multiple tempi to exist simultaneously (see Section "Multiple Tempi"). +

+

Default Attributes

+ +If an attribute is omitted, the previous one is used by +default (with the exception of the time attribute). The +default values for the first note, which are inherited by succeeding notes +until something else is specified, are given below in Adagio notation: +
+ + +Time T0
+ +Pitch C4
+ +Duration Q
+ +Articulation #100
+ +Loudness LFFF
+ +Voice V1
+ +Tempo !TEMPO 100
+ +Rate !RATE 100
+ +
+Control changes (including timbre or MIDI program, specified by Z) have no default value and are only sent as specified in the score. +

+Important: the rules for determining when a command will play a note are as follows (and this has changed slightly from previous versions): +

    +
  1. +If a special (!) command or nothing is specified, e.g. a blank line, do not play a note. +
  2. If R (for "rest") is specified, do not play a note. +
  3. Otherwise, if a pitch is specified, do play a note. +
  4. Otherwise, if no control changes (or program changes) are specified (so this is a command with non-pitch attributes and no control changes), do play a note. +
+Another way to say this is "Special commands and commands with rests (R) do not play notes. Otherwise, play a note if a pitch is specified or if no control is specified." +

+

Examples

+ +The following plays the first two bars of "Happy Birthday". Note that +Adagio knows nothing of bar lines, so the fact that the first note occurs +on beat 3 or that the meter is three-four is of no consequence: +
+*Example 1 ** Happy Birthday tune (C major)
+!TEMPO 120
+G4 I. LF
+G4 S
+A4 Q
+G4
+C5
+B4 H
+
+ +The time attribute for the first note is zero (0). The second note +will occur a dotted eighth later, etc. +Notice that no timbre or rate was specified. +Adagio will provide reasonable default +values of 1 and 100, respectively. +

+The following example plays the first four bars of an exercise from +Bartok's Mikrokosmos (Vol. 1, No. 12). +An extra quarter note is inserted at the beginning of each voice in order to +allow time to change MIDI programs. The right hand part is played on voice +(MIDI channel) 1 and the left hand part on voice 2. Notice the +specification of the time attribute to indicate that voice 2 starts at time +0. Also, default octaves are used to reduce typing. +

+*Example 2 ** Bartok
+*voice 1, right hand
+R Q Z10 V1   ** extra rest for program change
+A4 H
+B Q
+C
+D H
+C
+D Q
+C
+B
+A
+B
+C
+D
+R
+

+*voice 2, left hand +T0 R Q Z15 V2 ** extra rest for program change +G3 H +F Q +E +D H +E +D Q +E +F +G +F +E +D +R +

+ +

+The next example is the same piece expressed in a different manner, +illustrating the interaction +between the !TEMPO command and the time attribute. Recall that the +time attribute is measured relative to the time of the last !TEMPO command: +

+*Example 3 ** 4 measures in 2 sections
+!Tempo 100
+*Voice 1, Measures 1 & 2
+R Q Z10 V1
+A4 H
+B Q
+C
+D H
+C
+

+*Voice 2, Measures 1 & 2 +T0 R Q Z15 V2 +G3 H +F Q +E +D H +E H +

+!TEMPO 100 +*Voice 1, Measures 3 & 4 +* note that Z10 is still in effect for V1 +V1 D4 Q +C +B +A +B +C +D +R +

+*Voice 2, Measures 3 & 4 +T0 V2 D3 Q +E +F +G +F +E +D +R +

+ +

+The piece is written in 4 sections. The first +plays a rest followed by two measures, starting +at time 0. The next section changes the time back to +zero and plays two measures of the left hand part (voice 2). +The next +command (!TEMPO 100) sets the tempo to 100 (it already is) +and sets the reference time to +be two measures into the piece. Therefore, the next note +(D4) will begin measure 3. The D3 that begins the last +group of notes has a T0 attribute, so it will also start at measure +3. Notice how the !TEMPO command can serve to divide a piece into +sections. +

+The last example will show yet another way to express the same piece of +music using the "Next" attribute. Only the first bar of music is +given. +

+*Example 4 ** use of the Next attribute
+!Tempo 100
+R Q Z10 V1 N0
+R Q Z15 V2
+

+A4 H V1 N0 +G3 V2 +

+B4 Q V1 N0 +F3 V2 +

+C4 Q V1 N0 +E3 V2 +

+ +Here, each pair of +lines represents two simultaneous notes. The N0 attribute +forces the second line to start at the same time as the first line of each +pair. Because of the large intervals, octave numbers (3 and 4) are +necessary to override the default octave for these pitches. +

+

Advanced Features

+Beyond the simple notation described above, Adagio supports a number of +features. (See also the next chapter.) +

+

Time Units and Resolution

+ +The default time unit is 10ms (ten milliseconds or one centisecond or +100^(th) of a second), but it is +possible to change the basic unit to 1ms, or 1000^(th) of a second. +The time unit can be specified by: +
+ + +!CSECcentisecond time units = 100^(th)
+ +!MSEC
millisecond time units = 1000^(th)
+ +
+The time unit remains in effect until the next !CSEC or !MSEC command. +

+

Multiple Notes Per Line

+ + +Notes can be separated by commas or +semicolons as well as by starting a new line. A comma is +equivalent to typing N0 and starting a new line. In other words, the next note after a comma will start at the same time as the note before the comma. In general, use commas to separate the notes of a chord. +

+A semicolon is equivalent to starting a new line. In general, use semicolons to group notes in a melody. Here is yet another rendition of the Bartok: +

+*Example 5 ** use of semicolons
+!Tempo 100
+R Q Z10 V1
+A4 H; B Q; C; D H; C; D Q; C; B; A; B; C; D; R
+

+T0 R Q Z15 V2 +G3 H; F Q; E; D H; E; D Q; E; F; G; F; E; D; R +

+ +This example is similar to Example 2, except semicolons are used. Note how semicolons make the two lines of music stand out. +The next example is similar to Example 4, except commas are used +and four bars are notated. The music below is treated as a sequence of 2-note chords, with each chord on a separate line: +
+*Example 6 ** use of commas
+!Tempo 100
+R Q Z10 V1, R Q Z15 V2
+A4 H V1, G3 V2
+B4 Q V1, F3 V2
+C4   V1, E3 V2
+D4 H V1, D3 V2
+C4   V1, E3 V2
+D4 Q V1, D3 V2
+C4   V1, E3 V2
+B4   V1, F3 V2
+A4   V1, G3 V2
+B4   V1, F3 V2
+C4   V1, E3 V2
+D4   V1, D3 V2
+R
+
+ +

+

Control Change Commands

+ +Any control change can be specified using +the syntax "~n(v)", where n is the controller number (0 - 127), and +v is the value. In addition, Adagio has some special syntax for +some of the commonly used control changes (note that Pitch bend, Aftertouch, and MIDI Program Change are technically not MIDI control changes but have their own +special message format and status bytes): +
+ +
+ +KPortamento switch

+ +MModulation wheel

+ +OAftertouch

+ +XVolume

+ +YPitch bend

+ +ZProgram Change

+ +
+The letter listed beside each control function is the Adagio command +letter. For example, M23 is the command for setting the modulation +wheel to 23. Except for pitch bend, the portamento switch, and MIDI Program Change, all +values range from 0 to 127. Pitch bend is "off" or centered at +128, and has a range from 0 to 255 (MIDI allows for more precision, but +Adagio does not). Turn on portamento with K127 and off with K0. Programs are numbered 1 to 128 to correspond to synthesizer displays. +

+About volume: Midi volume is just a control, and the Midi standard does not say what it means. Typically it does what the volume pedal does; that is, it scales the amplitude in a continuously changeable fashion. In contrast, Midi velocity, which is controlled by the L (loudness) attribute, is part of a Midi note-on command and is fixed for the duration of the note. Typically, these two ways of controlling loudness and amplitude operate independently. In some low-cost synthesizers the numbers seem to be added together internally and volume changes are ignored after the note starts. +

+About pitch bend: Midi pitch bend is a number from 0 to 16383, where 8192 is the center position. To convert to Midi, Adagio simply multiplies your number by 64, giving values from 0 to 16320. Note that Y128 translates exactly to 8192. The meaning of pitch bend depends upon your synthesizer and its setting. Most synthesizers let you specify a "pitch bend range." A range of one semitone means that Y255 will produce a bend of approximately one semitone up, and Y0 will bend one semitone down. If the range is 12 semitones, then the same Y255 will bend an octave. Typically, pitch bend is exponential, so each increment in the pitch bend value will bend an equal number of cents in pitch. +

+Control changes can be part of a note specification or independent. +In the following example, a middle C is played with a modulation +wheel setting of 50 and a pitch bend of 120. Then, at 10 unit +intervals, the pitch bend is decreased by 10. The last line sets the +portamento time (controller 5) to 80: +

+*Example 7
+C4 LMF M50 Y120 U100 N10
+Y110 N10; Y100 N10; Y90 N10; Y80 N10
+Y70 N10; Y60 N10; Y50 N10
+~5(80)
+
+ +

+See Section "Default Attributes" on page "Default Attributes" for rules on whether or not a command will play a note. +

+

Multiple Tempi

+ + +Writing a piece with multiple tempi requires no new commands; you +just have to be clever in the use of Tempo and Time. The following +plays a 7 note diatonic scale on voice 1, and a 12 note chromatic +scale on voice 2: +
+*Example 8 ** multiple tempi
+!TEMPO 70
+V1 C4; D; E; F; G; A; B
+T0 R N0
+

+!TEMPO 120 +V2 C4; CS; D; DS; E; F; FS; G; GS; A; AS; B +

+!TEMPO 100 +V1 C5, V2 C5 +

+ +The third line plays the 7-note diatonic scale on voice 1. The +next line contains the tricky part: notice that the time is +set back to zero, there is a rest, and a next (N) attribute is used +to specify that the next default time will be at the same time as +the current one. This is tricky because a !TEMPO command cannot have a time (T0) attribute, and a T0 by itself would create a note with a duration. T0 R N0 says: "go to time 0, do not play a note, and do not advance the time before the next command". +Thus, the time of the !TEMPO 120 command is zero. +After the 12 note scale, the tempo is changed to 100 and a final note +is played on each voice. A little arithmetic will show that 7 notes +at tempo 70 and 12 notes at tempo 120 each take 6 seconds, so the +final notes (C5) of each scale will happen at the same time. + +

MIDI Synchronization

+ +

+The Adagio program (but not Nyquist) can synchronize with external devices using MIDI real time messages. Thus, Adagio has a !CLOCK command. This command is currently of no use to Nyquist users but is documented here for completeness (it's part of the language syntax even if it does not do anything). +

+Since Adagio supports multiple tempi, and Midi clock is +based on beats, it is necessary to be explicit in the score about where the +clock should start and what is the duration of a quarter note. The +!CLOCK command in Adagio turns on a 24 pulse-per-quarter (PPQ) clock at +the current tempo and time: +

+!TEMPO 100
+!CLOCK
+
+ +A !CLOCK command must also be inserted for each tempo change that is to be +reflected in the Midi clock. Typically, each !TEMPO command will be followed by a !CLOCK command. + +Clock commands and thus tempo +changes can take place at arbitrary times. It is assumed that tempo changes +on an exact 24^(th) of a beat subdivision (for example, exactly on a +beat). If not, the tempo change will take place on the nearest exact +24^(th) of a beat subdivision. This may be earlier or later than the +requested time. + + +

+

System Exclusive Messages

+ +Adagio has a definition facility that makes it possible to send system +exclusive parameters. Often, there are parameters on Midi +synthesizers that can only be controlled by system exclusive messages. +Examples include the FM ratio and LFO rate on a DX7 synthesizer. The +following example defines a macro for the DX7 LFO rate and then shows how +the macro is used to set the LFO rate for a B-flat whole note in the score. +The macro definition is given in hexadecimal, except v is replaced by +the channel (voice) and %1 is replaced by the first parameter. +A macro is invoked by writing "~" followed by the macro name and a +list of parameters: +
+!DEF LFO F0 43 0v 01 09 %1 F7
+Bf5 W ~LFO(25)
+
+ +

+In general, the !DEF command can define any single MIDI message including +a system exclusive +message. The message must be complete (including the status byte), and each !DEF must correspond to just one message. +The symbol following !DEF can be any name consisting of +alphanumeric characters. Following the name is a hexadecimal string +(with optional spaces), all on one line. Embedded in the string may +be the following special characters: +

+
+v
Insert the 4-bit voice (MIDI channel) number. If v occurs in the +place of a high-order hexadecimal digit, replace v with 0v so that +the channel number is always placed in the low-order 4 bits of a data byte. In other words, v is padded if necessary to fall into the low-order bits.

+
%n
Insert a data byte with the low-order 7 bits of +parameter number n. Parameters are numbered 1 through 9. +If the +parameter value is greater than 127, the high-order bits are discarded.

+
^n
Insert a data byte with bits 7 through 13 of parameter number +n. In other words, shift the value right 7 places then clear all +but the first 7 bits. Note that 14-bit numbers can be encoded by +referencing the same parameter twice; for example, %4^4 will +insert the low-order followed by the high-order parts of parameter 4 +into two successive data bytes. +
+

+Parameters are separated by commas, but there may be no spaces. The +maximum number of parameters allowed is 9. Here +is an example of definitions to send a full-resolution pitch +bend command and to send a system exclusive command to change a DX7 +parameter (Footnote 7) . +

+

+* Define macro for pitch bend commands:
+!DEF bend Ev %1 ^1
+

+A ~bend(8192) ** 8192 is "pitch bend off" +

+* Change the LFO SPEED: +* SYSEX = F0, Yamaha = 43, Substatus/Channel = 1v, +* Group# = 01, Parameter# = 9, Data = 0-99, EOX = F7 +!DEF lfospeed F0 43 1v 01 09 %1 F7 +

+* now use the definitions: +G4 ~bend(7567) N40 +~lfospeed(30) N35 +

+

+

Control Ramps

+ +The !RAMP command can specify a smooth control change from one +value to another. It consists of a specification of the starting and +ending values of some control change, a duration specifying how often +to send a new value, and a duration specifying the total length of the ramp. +
+!RAMP X10 X100 Q W2
+!RAMP ~23(10) ~23(50) U20 W
+!RAMP ~lfo(15) ~lfo(35) U10
+
+ +The first line says to ramp the volume control (controller number 7) +from 10 to 100, changing at each quarter note for the duration of two +whole notes. +The second line says to ramp controller number 23 from value 10 to value 50, +sending a new control change message every 20 time units. The overall +duration of the ramp should be equivalent to a whole note (W). +As shown in the third line, even system exclusive messages controlled by +parameters can be specified. If the system exclusive message has more +than one parameter, only one parameter may be "ramped"; the others must +remain the same. For example, the following would ramp the second parameter: +
+!RAMP ~mysysex(4,23,75) ~mysysex(4,100,75) U10 W
+
+ +

+ +A rather curious and extreme use of macros and ramps is illustrated in the +following example. The noteon macro starts a note, and noteoff ends it. Ramps can now be used to emit a series of notes with changing pitches or velocities. Since Adagio has no idea that these macros are turning on notes, it is up to the programmer to turn them off! +

+!DEF noteon 9v %1 %2
+!DEF noteoff 8v %1 %2
+~noteon(48,125)
+~noteoff(48,126)
+* turn on some notes
+!RAMP ~noteon(36,125) ~noteon(60,125) Q W NW
+* turn them off
+!RAMP ~noteoff(60,50) ~noteoff(36,50) Q W NW
+
+ + + +

+

The !End Command

+ +The special command !END marks the end of a score. Everything beyond that +is ignored, for example: +
+* this is a score
+C; D; E; F; G W
+!END
+since the score has ended, this text will be ignored
+
+ +

+

Calling C Routines

+ +It is possible to call C routines from within Adagio scores when using +specially linked versions, but this feature is disabled in Nyquist. The +syntax is described here for completeness. +

+The !CALL command calls a C routine that can in turn invoke a +complex sequence of operations. Below is a call to a trill routine, +which is a standard routine in Adagio. The parameters are the base +pitch of the trill, the total duration of the trill, the interval in semitones, the +duration of each note of the trill, and the loudness. Notice +that both numbers and Adagio notation can be used as parameters: +

+!CALL trill(A5,W,2,S,Lmf)  T278 V1
+
+ +The parameter list should have no spaces, and parameters are separated +by commas. Following the close parenthesis, you may specify other +attributes such as the starting time and voice as shown in the example above. +

+A parameter may be an Adagio pitch specification, an Adagio duration, +an Adagio loudness, a number, or an ASCII character within single +quotes, e.g. 'a' is equivalent to 97 because 97 is the decimal +encoding of "a" in ASCII. +

+The !CALL may be followed by a limited set of attributes. These are time (T), voice (V), and next time (N). The !CALL is made at the current time if no time is specified, and the time of the next adagio command is the time of the !CALL unless a next time is specified. In other words, the default is N0. +

+

Setting C Variables

+In addition to calling C routines, there is another way in which scores +can communicate with C. As with !CALL, specific C code must be linked before these commands can be used, and this is not supported in Nyquist. +The !SETI command sets an integer variable +to a value, and the !SETV command sets an element of an integer array. +For example, the next line sets the variable delay to 200 and sets +transposition[5] to -4 at time 200: +
+!SETI delay 200
+!SETV transposition 5 -4  T200
+
+ +As with the !CALL command, these commands perform their operations at +particular times according to their place in the Adagio score. This makes +it very easy to implement time-varying parameters that control various +aspects of an interactive music system. +

+


+
Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part12.html b/doc/part12.html new file mode 100644 index 0000000..d3d38e2 --- /dev/null +++ b/doc/part12.html @@ -0,0 +1,157 @@ +Linear Prediction Analysis and Synthesis + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Linear Prediction Analysis and Synthesis

+ +Nyquist provides functions to perform Linear Prediction Coding (LPC) +analysis and synthesis. In simple terms, LPC analysis assumes that a +sound is the result of an all-pole filter applied to a source with a +flat spectrum. LPC is good for characterizing the general spectral +shape of a signal, which may be time-varying as in speech sounds. +For synthesis, any source can be filtered, allowing the general +spectral shape of one signal (used in analysis) to be applied to +any source (used in synthesis). A popular effect is to give vowel-like +spectra to musical tones, creating an artificial (or sometimes natural) +singing voice. +

+Examples of LPC analysis and synthesis can be found in the file +lpc_tutorial.htm, +which is part of the standard Nyquist release. +

+As with FFT processing, LPC analysis takes a sound as input and returns +a stream of frames. Frames are returned from an object using the :next +selector just as with FFT frames. An LPC frame is a list consisting of: +RMS1, the energy of the input signal, RMS2, the energy of the +residual signal, ERR, the square root of RMS1/RMS2, and +FILTER-COEFS, an array of filter coefficients. To make code more +readable and to avoid code dependence on the exact format of a frame, +the functions lpc-frame-rms1, +lpc-frame-rms2, +lpc-frame-err, and +lpc-frame-filter-coefs can be +applied to a frame to obtain the respective fields. +

+The z transform +of the filter is H(z) = 1/A(z), where A(z) is a +polynomial of the form A(z) = 1 + a1z + +a2z + ... + apz. The FILTER-COEFS array has +the form #(ap ap-1 ... a3 +a2 a1). +

+The file lpc.lsp defines some useful classes and functions. The file +is not automatically loaded with Nyquist, so you must execute +(load "lpc") before using them. +

+

LPC Classes and Functions

+
+
+make-lpanal-iterator(sound, framedur, skiptime, npoles) [SAL]
+ +(make-lpanal-iterator sound framedur skiptime npoles) [LISP]
Makes an iterator +object, an instance of lpanal-class, +that returns LPC frames from successive frames of samples in +sound. The duration (in seconds) +of each frame is given by framedur, a +FLONUM. The skip size (in seconds) between successive frames +is given by skiptime, a FLONUM. Typical values for +framedur and skiptime are 0.08 and 0.04, giving 25 frames +per second and a 50% frame overlap. The number of poles is given +by npoles, a FIXNUM. The result is an object that +responds to the :next selector by returning a frame as +described above. NIL is returned when sound terminates. +(Note that one or more of the last analysis windows may be +padded with zeros. NIL is only returned when the corresponding +window would begin after the termination time of the sound.)

+
make-lpc-file-iterator(filename) [SAL]
+ +(make-lpc-file-iterator filename) [LISP]
Another way to get LPC frames is to read them from a + file. This function opens an ASCII file containing LPC frames and + creates an iterator object, an instance of class lpc-file-class + to access them. Create a file using save-lpc-file (see below).

+
save-lpc-file(lpc-iterator, filename) [SAL]
+ +(save-lpc-file lpc-iterator filename) [LISP]
Create a file containing LPC frames. +This file can be read by make-lpc-file-iterator (see above).

+
show-lpc-data(lpc-iterator, +iniframe, endframe [, poles?]) [SAL]
+ +(show-lpc-data lpc-iterator iniframe endframe + [poles?]) [LISP]
Print values of LPC +frames from an LPC iterator object. The object is lpc-iterator, +which is typically an instance of lpanal-class or +lpc-file-class. Frames are numbered from zero, and only +files starting at iniframe (a FIXNUM) and ending before +endframe (also a FIXNUM) are printed. By default, only +the values for RMS1, RMS2, and ERR are printed, but +if optional parameter poles? is non-NIL, then +the LPC coefficients are also printed.

+
allpoles-from-lpc(snd, lpc-frame) [SAL]
+ +(allpoles-from-lpc snd lpc-frame) [LISP]
A single LPC frame defines a filter. +Use allpoles-from-lpc to apply this filter to snd, +a SOUND. To obtain lpc-frame, a LIST + containing an LPC frame, either send :next to an + LPC iterator, or use nth-frame (see below). The result + is a SOUND whose duration is the same as that of snd.

+
lpreson(snd, lpc-iterator, +skiptime) [SAL]
+ +(lpreson snd lpc-iterator skiptime) [LISP]
Implements a time-varying all-pole filter +controlled by a sequence of LPC frames from an iterator. The +SOUND to be filtered is snd, and the source of +LPC frames is lpc-iterator, typically an instance of +lpanal-class or lpc-file-class. The frame +period (in seconds) is given by skiptime (a FLONUM). +This number does not have to agree with the skiptime used +to analyze the frames. (Greater values will cause the filter +evolution slow down, and smaller values will cause it to +speed up.) The result is a SOUND. The duration of the +result is the minimum of the duration of snd and that of +the sequence of frames.

+
lpc-frame-rms1(frame) [SAL]
+ +(lpc-frame-rms1 frame) [LISP]
Get the energy of the input signal from a frame.

+
lpc-frame-rms2(frame) [SAL]
+ +(lpc-frame-rms2 frame) [LISP]
Get the energy of the residual from a frame.

+
lpc-frame-err(frame) [SAL]
+ +(lpc-frame-err frame) [LISP]
Get the square root of RMS1/RMS2 from a frame.

+
lpc-frame-filter-coefs(frame) [SAL]
+ +(lpc-frame-filter-coefs frame) [LISP]
Get the filter coefficients from a frame.

+

Low-level LPC Functions

+The lowest-level Nyquist functions for LPC are +
    +
  • +snd-lpanal for analysis, +
  • snd-allpoles, an all-pole filter with fixed coefficients, and +
  • snd-lpreson, an all-pole filter that takes frames from an LPC iterator. +
+

+

+
+snd-lpanal(samps, npoles) [SAL]
+ +(snd-lpanal samps npoles) [LISP]
Compute +an LPC frame with npoles (a FIXNUM) poles from an +ARRAY of samples (FLONUMS). Note that snd-fetch-array +can be used to fetch a sequence of frames from a sound. Ordinarily, you +should not use this function. Use make-lpanal-iterator instead.

+
snd-allpoles(snd, lpc-coefs, gain) [SAL]
+ +(snd-allpoles snd lpc-coefs gain) [LISP]
A fixed all-pole filter. The input is +snd, a SOUND. The filter coefficients are given by lpc-coefs +(an ARRAY), and the filter gain is given by gain, a FLONUM. +The result is a SOUND whose duration matches that of snd. +Ordinarily, you should use allpoles-from-lpc instead (see above).

+
snd-lpreson(snd, lpc-iterator, +skiptime) [SAL]
+ +(snd-lpreson snd lpc-iterator skiptime) [LISP]
This function is identical to lpreson (see above). +
+

+


+
Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part13.html b/doc/part13.html new file mode 100644 index 0000000..ab205ea --- /dev/null +++ b/doc/part13.html @@ -0,0 +1,218 @@ +Developing and Debugging in Nyquist + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Developing and Debugging in Nyquist

+ +There are a number of tools, functions, and techniques that can help to debug Nyquist programs. Since these are described in many places +throughout this manual, this chapter brings together many suggestions and techniques for developing code and debugging. You really +should read this chapter before you spend too much time with Nyquist. Many problems that you will certainly run into are addressed here. +

+

Debugging

+Probably the most important debugging tool is the backtrace. There are +two kinds of backtrace: one for SAL, and one for Lisp. +

+SAL mode is actually just an XLISP function (sal) that reads +input and evaluates it. When SAL encounters an error, it normally +prints a trace of the SAL stack (all the active functions written in SAL), +exists the current command, and reads the next command. +

+If you call XLISP functions from SAL, including most Nyquist sound +processing functions, and an error occurs within these XLISP functions, +you will only see the SAL function that called the XLISP functions +listed in the stack trace. Sometimes you need more details. +

+When Nyquist encounters an error when it is not running SAL, it +normally suspends execution and prints an +error message. To find out where in the program the error occurred +and how you got there, start by typing (bt). This will print +out the last several function calls and their arguments, which is +usually sufficient to see what is going on. +

+In order for (bt) to work, you must have a couple of global +variables set: *tracenable* is ordinarily set to NIL. +If it is true, then a backtrace is automatically printed when an +error occurs; *breakenable* must be set to T, as +it enables the execution to be suspended when an error is +encountered. If *breakenable* is NIL (false), +then execution stops when an error occurs but the stack is +not saved and you cannot get a backtrace. Finally, bt +is just a macro to save typing. The actual backtrace function +is baktrace, which takes an integer argument telling how +many levels to print. All of these things are set up by default +when you start Nyquist. +

+To get this XLISP backtrace behavior when SAL encounters an error, +you need to have *breakenable* set while SAL is running. The +best way to do this is to run within the NyquistIDE program, +open the Preferences dialog, and choose the desired settings, e.g. +"Enable XLISP break on SAL error." +

+Since Nyquist sounds are executed with a lazy evaluation scheme, some +errors are encountered when samples are being generated. In this +case, it may not be clear which expression is in error. Sometimes, it +is best to explore a function or set of functions by examining +intermediate results. Any expression that yields a sound can be +assigned to a variable and examined using one or more of: +s-plot, snd-print-tree, and of course play. The +snd-print-tree function prints a lot of detail about the inner +representaion of the sound. Keep in mind that if you assign a sound +to a global variable and then look at the samples (e.g. with +play or s-plot), the samples will be retained in +memory. At 4 bytes per sample, a big sound may use all of your +memory and cause a crash. +

+Another technique is to use low sample rates so that it is easier to +plot results or look at samples directly. The calls: +

+set-sound-srate(100)
+set-control-srate(100)
+
+ +set the default sample rates to 100, which is too slow for audio, but useful for examining programs and results. The function +
+snd-samples(sound, limit)
+
+ +will convert up to limit samples from sound into a Lisp +array. This is another way to look at results in detail. +

+The trace function is sometimes useful. It prints the name of +a function and its arguments everytimg the function is called, and the +result is printed when the function exits. To trace the osc function, +type: +

+trace(osc)
+
+ +and to stop tracing, type untrace(osc). +

+If a variable needs a value or a function is undefined, and if *breakenable* was set, you will get a prompt where you can fix +the error (by setting the variable or loading the function definition) +and keep going. At the debug (or break) prompt, your input must +be in XLISP, not SAL syntax. Use (co), short for (continue) to +reevaluate the variable or function and continue execution. +

+When you finish debugging a particular call, you can "pop" +up to the top level by typing (top), a short name for (top-level). +There is a button named "Top" in the NyquistIDE that takes you back to the +top level (ready to accept XLISP expressions), +and another button named "SAL" that puts you back in SAL mode. +

+

Useful Functions

+
+
+grindef(name) [SAL]
+ +(grindef name) [LISP]
Prints +a formatted listing of a lisp function. This is often useful to quickly inspect +a function without searching for it in source files. Do not forget to quote the +name, e.g. (grindef 'prod).

+
args(name) [SAL]
+ +(args name) [LISP]
Similar +to grindef, this function prints the arguments to a function. This may +be faster than looking up a function in the documentation if you just need a +reminder. For example, (args 'lp) prints "(LP S C)," which may help you +to remember that the arguments are a sound (S) followed by the cutoff (C) +frequency. +
+

+The following functions are useful short-cuts that might have been included in +XLISP. They are so useful that they are defined as part of Nyquist. +

+

+
+incf(symbol) [SAL]
+ +(incf symbol) [LISP]
Increment symbol +by one. This is a macro, and symbol can be anything that can be set by +setf. Typically, symbol is a variable: "(incf i)," but +symbol can also be an array element: "(incf (aref myarray i))."

+
decf(symbol) [SAL]
+ +(decf symbol) [LISP]
Decrement symbol +by one. (See incf, above.)

+
push(val, lis) [SAL]
+ +(push val lis) [LISP]
Push val onto lis (a Lisp +list). This is a macro that is equivalent to writing (in Lisp) +(setf lis (cons val lis)).

+
pop(lis) [SAL]
+ +(pop lis) [LISP]
Remove (pop) the first item from lis (a +Lisp list). This is a macro that is equivalent to writing (in Lisp) +(setf lis (cdr lis)). Note that the remaining list is returned, +not the head of the list that has been popped. Retrieve the head of the list +(i.e. the top of the stack) using first or, equivalently, car. +
+

+The following macros are useful control constructs. +

+

+
+while(test, expr1, expr2, ...) [SAL]
+ +(while test expr1 expr2 ...) [LISP]
A conventional +"while" loop. If test is true, evaluate expressions + (expr1, expr2, etc.) and repeat. If test is false, return. This + expression evaluates to NIL unless the expression (return expr) + is evaluated, in which case the value of expr is returned. In SAL, the + loop statement is preferred.

+
when(test, action) [SAL]
+ +(when test action) [LISP]
A conventional "if-then" +statement. If test is true, action is evaluated and returned. Otherwise, +NIL is returned. (Use if or cond to implement + "if-then-else" and more complex conditional forms. +
+

+It is often necessary to load a file only if it has not already been +loaded. For example, the pianosyn library loads very slowly, so if +some other file already loaded it, it would be good to avoid loading it +again. How can you load a file once? Nyquist does not keep track of files +that are loaded, but you must be loading a file to define some function, +so the idea is to tell Nyquist "I require function from file"; if +the function does not yet exist, Nyquist satisfies the requirement by loading +the file. +

+
+require-from(fnsymbol, +filename [, path]) [SAL]
+ +(require-from fnsymbol filename [path]) [LISP]
Tests whether fnsymbol, an unquoted +function name, is defined. If +not, filename, a STRING, +is loaded. Normally fnsymbol is a function that will be called from +within the current file, and filename is the file that defines +fnsymbol. The path, if a STRING, is prepended to filename. +If path is t (true), then the directory of the current file is +used as the path. +
+

+Sometimes it is important to load files relative to the current file. For example, +the lib/piano.lsp library loads data files from the lib/piano directory, +but how can we find out the full path of lib? The solution is: +

+
+current-path() [SAL]
+ +(current-path) [LISP]
Returns the full path name of the file that is +currently being loaded (see load). Returns NIL if no file is being loaded. +
+

+Finally, there are some helpful math functions: +

+
+real-random(from, to) [SAL]
+ +(real-random from to) [LISP]
Returns a random FLONUM between from and to. (See also rrandom, which is equivalent to (real-random 0 1)).

+
power(x, y) [SAL]
+ +(power x y) [LISP]
Returns x raised to +the y power. +
+

+


+
Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part14.html b/doc/part14.html new file mode 100644 index 0000000..aa9503b --- /dev/null +++ b/doc/part14.html @@ -0,0 +1,1495 @@ +Xmusic and Algorithmic Composition + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Xmusic and Algorithmic Composition

+ + +Several Nyquist libraries offer support for algorithmic composition. Xmusic +is a library for generating sequences and patterns of data. Included in Xmusic +is the score-gen macro which helps to generate scores from patterns. +Another important facility is the distributions.lsp library, +containing many different random number generators. +

+

Xmusic Basics

+Xmusic is inspired by and based on Common Music by Rick Taube. Currently, +Xmusic only implements patterns and some simple support for scores to be +realized as sound by Nyquist. In contrast, Common Music supports MIDI and +various other synthesis languages and includes a graphical interface, some +visualization tools, and many other features. Common Music runs in Common +Lisp and Scheme, but not XLISP, which is the base language for Nyquist. +

+Xmusic patterns are objects that generate data streams. For example, +the cycle-class of objects generate cyclical patterns such as +"1 2 3 1 2 3 1 2 3 ...", or "1 2 3 4 3 2 1 2 3 4 ...". Patterns can +be used to specify pitch sequences, rhythm, loudness, and other parameters. +

+Xmusic functions are automatically loaded when you start Nyquist. +To use a pattern object, you first create the pattern, e.g. +

+set pitch-source = make-cycle(list(c4, d4, e4, f4))
+
+ +After creating the pattern, you can access it repeatedly +with next to generate data, e.g. +
+play seqrep(i, 13, pluck(next(pitch-source), 0.2))
+
+ +This will create a sequence of notes with the following pitches: c, d, +e, f, c, d, e, f, c, d, e, f, c. If you evaluate this again, the +pitch sequence will continue, starting on "d". +

+It is very important not to confuse the creation of a sequence with +its access. Consider this example: +

+play seqrep(i, 13,
+         pluck(next(make-cycle(list(c4, d4, e4, f4))), 0.2))
+
+ +This looks very much like the previous example, but it only repeats notes +on middle-C. The reason is that every time pluck is evaluated, +make-cycle is called and creates a new pattern object. After the +first item of the pattern is extracted with next, the cycle is not +used again, and no other items are generated. +

+To summarize this important point, there are two steps to using a pattern. +First, the pattern is created and stored in a +variable using setf. Second, the pattern is accessed (multiple +times) using next. +

+Patterns can be nested, that is, you can write patterns of patterns. +In general, the next function does not return patterns. Instead, +if the next item in a pattern is a (nested) pattern, next recursively +gets the next item of the nested pattern. +

+While you might expect that each call to next would advance the +top-level pattern to the next item, and descend recursively if necessary +to the inner-most nesting level, this is not how next works. Instead, +next remembers the last top-level item, and if it was a pattern, +next continues to generate items from that same inner pattern +until the end of the inner pattern's period is reached. The next +paragraph explains the concept of the period. +

+The data returned by a pattern object is structured into logical groups +called periods. You can get an entire period (as a list) by calling +next(pattern, t). For example: +

+set pitch-source = make-cycle(list(c4, d4, e4, f4))
+print next(pitch-source, t)
+
+ +This prints the list (60 62 64 65), which is one period +of the cycle. +

+You can also get explicit markers that +delineate periods by calling send(pattern, :next). In this +case, the value returned is either the next item of the pattern, or the +symbol +eop+ if the end of a period has been reached. What +determines a period? This is up to the specific pattern class, so see the +documentation for specifics. You can override the "natural" period +using the keyword for:, e.g. +

+set pitch-source = make-cycle(list(c4, d4, e4, f4), for: 3)
+print next(pitch-source, t)
+print next(pitch-source, t)
+
+ +This prints the lists (60 62 64) (65 60 62). Notice that +these periods just restructure the stream of items +into groups of 3. +

+Nested patterns are probably easier to understand by example than by +specification. Here is a simple nested pattern of cycles: +

+set cycle-1 = make-cycle({a b c})
+set cycle-2 = make-cycle({x y z})
+set cycle-3 = make-cycle(list(cycle-1, cycle-2))
+exec dotimes(i, 9, format(t, "~A ", next(cycle-3)))
+
+ +This will print "A B C X Y Z A B C". Notice that the inner-most +cycles cycle-1 and cycle-2 generate a period of items +before the top-level cycle-3 advances to the next pattern. +

+Before describing specific pattern classes, there are several optional +parameters that apply in the creating of any pattern object. These are: +

+
+for:
The length of a period. This overrides the default +by providing a numerical length. The value of this optional +parameter may be a pattern that generates a sequence of integers +that determine the length of each successive period. A period +length may not be negative, but it may be zero.

+
name:
A pattern object may be given a name. This is useful +if the trace: option is used.

+
trace:
If non-null, this optional parameter causes information +about the pattern to be printed each time an item is generated +from the pattern.

+
+The built-in pattern classes are described in the following section. +

+

Pattern Classes

+

cycle

+The cycle-class iterates repeatedly through a list of items. +For example, two periods of make-cycle({a b c}) would be +(A B C) (A B C). +

+

+
+make-cycle(items, for: for, name: name, trace: trace) [SAL]
+ +(make-cycle items :for for :name name + :trace trace) [LISP]
Make a cycle +pattern that iterates over items. The default period length is the +length of items. (See above for a description of the +optional parameters.) If items is a pattern, a period of the +pattern becomes the list from which items are generated. The +list is replaced every period of the cycle. +
+

+

line

+The line-class is similar to the cycle class, but when it reaches the +end of the list of items, it simply repeats the last item in the list. +For example, two periods of make-line({a b c}) would be +(A B C) (C C C). +

+

+
+make-line(items, for: for, name: name, trace: trace) [SAL]
+ +(make-line items :for for :name name :trace trace) [LISP]
Make a line +pattern that iterates over items. The default period length is the +length of items. As with make-cycle, items may be a +pattern. (See above for a description of the optional parameters.) +
+

+

random

+The random-class generates items at random from a list. The default +selection is uniform random with replacement, but items may be further +specified with a weight, a minimum repetition count, and a maximum +repetition count. Weights give the relative probability of the selection +of the item (with a default weight of one). The minimum count specifies how +many times an item, once selected at random, will be repeated. The maximum +count specifies the maximum number of times an item can be selected in a row. +If an item has been generated n times in succession, and the maximum +is equal to n, then the item is disqualified in the next random selection. +Weights (but not currently minima and maxima) can be patterns. The patterns +(thus the weights) are recomputed every period. +

+

+
+make-random(items, for: for, name: name, trace: trace) [SAL]
+ +(make-random items :for for :name name :trace trace) [LISP]
Make a random +pattern that selects from items. Any (or all) element(s) of items +may be lists of the following form: (value :weight weight +:min mincount :max maxcount), where value is the item +(or pattern) to be generated, weight is the (optional) +relative probability of +selecting this item, mincount is the (optional) minimum number of repetitions +when this item is selected, and maxcount is the (optional) maximum number of +repetitions allowed before selecting some other item. The default period +length is the length of items. If items is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +
+

+

palindrome

+The palindrome-class repeatedly traverses a list forwards and then +backwards. For example, two periods of make-palindrome({a b c}) +would be (A B C C B A) (A B C C B A). The elide: +keyword parameter controls whether the first and/or last elements are +repeated: +
+make-palindrome({a b c}, elide: nil)
+     ;; generates A B C C B A A B C C B A ...
+

+make-palindrome({a b c}, elide: t) + ;; generates A B C B A B C B ... +

+make-palindrome({a b c}, elide: :first) + ;; generates A B C C B A B C C B ... +

+make-palindrome({a b c}, elide: :last) + ;; generates A B C B A A B C B A ... +

+ +

+

+
+make-palindrome(items, elide: elide, for: for, name: name, trace: trace) [SAL]
+ +(make-palindrome items :elide elide :for for :name name :trace trace) [LISP]
Generate items +from list alternating in-order and reverse-order sequencing. The keyword +parameter elide can have the values :first, :last, +t, or nil to control repetition of the first and last elements. +The elide parameter can also be a pattern, in which case it is evaluated +every period. One period is one complete forward and backward traversal +of the list. If items is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +
+

+

heap

+The heap-class selects items in random order from a list + without replacement, which means that all items are generated once before +any item is repeated. For example, two periods of make-heap({a b c}) + might be (C A B) (B A C). Normally, repetitions can occur +even if all list elements are distinct. This happens when the last element +of a period is chosen first in the next period. To avoid repetitions, the +max: keyword argument can be set to 1. The max: keyword only +controls repetitions from the end of one period to the beginning of the next. +If the list contains more than one copy of the same value, it may be repeated +within a period regardless of the value of max:. +

+

+
+make-heap(items, for: for, max: max, name: name, trace: trace) [SAL]
+ +(make-heap items :for for :max max :name name :trace trace) [LISP]
Generate items +randomly from list without replacement. If max is 1, the first element of +a new period will not be the same as the last element of the previous period, +avoiding repetition. The default value of max is 2, meaning repetition is +allowed. The period length is the length +of items. If items is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +
+

+

accumulation

+The accumulation-class takes a list of values and returns +the first, followed by the first two, followed by the first three, +etc. In other words, for each list item, return all items from the +first through the item. For example, if the list is (A B C), each +generated period is (A A B A B C). +

+

+
+make-accumulation(items, name: name, trace: trace) [SAL]
+ +(make-accumulation items :name name :trace trace) [LISP]
For each item, generate items from the first to +the item including the item. The period length is (n^(2) + n) / 2 +where n is the length of items. If items is a pattern, a period +from that pattern becomes the list from which items are generated, +and a new list is generated every period. Note that this is similar in +name but different from make-accumulate.

+

copier

+The copier-class makes copies of periods from a sub-pattern. +For example, three periods +of make-copier(make-cycle({a b c}, for: 1), repeat: 2, merge: t) +would be (A A) (B B) (C C). Note that entire periods (not +individual items) are repeated, so in this example the for: +keyword was used to force periods to be of length one so that +each item is repeated by the repeat: count.

+
make-copier(sub-pattern, repeat: repeat, merge: merge, for: for, name: name, trace: trace) [SAL]
+ +(make-copier sub-pattern :repeat repeat :merge merge :for for :name name :trace trace) [LISP]
Generate a period +from sub-pattern and repeat it repeat times. If merge is false +(the default), each repetition of a period from sub-pattern results +in a period by default. If merge is true (non-null), then all + repeat repetitions of the period are merged into one result +period by default. If the for: keyword is used, the same items +are generated, but the items are grouped into periods determined by +the for: parameter. If the for: parameter is a pattern, +it is evaluated every result period. The repeat and merge values +may be patterns that return a repeat count and a boolean value, respectively. +If so, these patterns are evaluated initially and after each repeat + copies are made (independent of the for: keyword parameter, if any). +The repeat value returned by a pattern can also be negative. A negative +number indicates how many periods of sub-pattern to skip. After skipping +these patterns, new repeat and merge values are generated. +
+

+

accumulate

+The accumulate-class forms the sum of numbers returned by another +pattern. For example, each period +of make-accumulate(make-cycle({1 2 -3})) is (1 3 0). +The default output period length is the length of the input period. +

+

+
+make-accumulate(sub-pattern, for: for, max: maximum, min: minimum, name: name, trace: trace) [SAL]
+ +(make-accumulate sub-pattern :for for :max maximum :min minimum :name name :trace trace) [LISP]
Keep +a running sum of numbers generated by sub-pattern. The default +period lengths match the period lengths from sub-pattern. If maximum (a pattern or a number) is specified, and the running sum exceeds maximum, the running sum is reset to maximum. If minimum (a pattern or a number) is specified, and the running sum falls below minimum, the running sum is reset to minimum. If minimum is greater than maximum, the running sum will be set to one of the two values. Note that this is similar in name but not in function to +make-accumulation. +
+

+

sum

+The sum-class forms the sum of numbers, one from each of two other +patterns. For example, each period +of make-sum(make-cycle({1 2 3}), make-cycle({4 5 6})) +is (5 7 9). +The default output period length is the length of the input period of the +first argument. Therefore, the first argument must be a pattern, but the +second argument can be a pattern or a number. +

+

+
+make-sum(x, y, for: for, name: name, trace: trace) [SAL]
+ +(make-sum x y :for for :name name :trace trace) [LISP]
Form +sums of items (which must be numbers) from pattern + x and pattern or number y. The default +period lengths match the period lengths from x. +
+

+

product

+The product-class forms the product of numbers, one +from each of two other +patterns. For example, each period +of make-product(make-cycle({1 2 3}), make-cycle({4 5 6})) +is (4 10 18). +The default output period length is the length of the input period of the +first argument. Therefore, the first argument must be a pattern, but the +second argument can be a pattern or a number. +

+

+
+make-product(x, y, for: for, name: name, trace: trace) [SAL]
+ +(make-product x y :for for :name name :trace trace) [LISP]
Form +products of items (which must be numbers) from pattern + x and pattern or number y. The default +period lengths match the period lengths from x. +
+

+

eval

+The eval-class evaluates an expression to produce each output item. +The default output period length is 1. +

+

+
+make-eval(expr, for: for, name: name, trace: trace) [SAL]
+ +(make-eval expr :for for :name name :trace trace) [LISP]
Evaluate +expr to generate each item. If expr is a pattern, each item is generated by getting the next item from expr and evaluating it. +
+

+

length

+The length-class generates periods of a specified length from +another pattern. This is similar to using the for: keyword, but +for many patterns, the for: parameter alters the points at which +other patterns are generated. For example, if the palindrome pattern +has an elide: pattern parameter, the value will be computed every +period. If there is also a for: parameter with a value of 2, then +elide: will be recomputed every 2 items. In contrast, if the +palindrome (without a for: parameter) is embedded in a length +pattern with a lenght of 2, then the periods will all be of length 2, but +the items will come from default periods of the palindrome, and therefore +the elide: values will be recomputed at the beginnings of +default palindrome periods. +

+

+
+make-length(pattern, length-pattern, +name: name, trace: trace) [SAL]
+ +(make-length pattern length-pattern :name name :trace trace) [LISP]
Make a pattern of class +length-class that regroups items generated by a +pattern according to pattern lengths given by length-pattern. +Note that length-pattern is not optional: There is no default +pattern length and no for: keyword. +
+

+

window

+The window-class groups items from another pattern by using a sliding +window. If the skip value is 1, each output period is formed +by dropping the first item of the previous perioda and appending the next item +from the pattern. The skip value and the output period length can change +every period. For a simple example, if the period length is 3 and the +skip value is 1, and the input pattern generates the sequence A, B, C, ..., +then the output periods will be (A B C), (B C D), (C D E), (D E F), .... +

+

+
+make-window(pattern, length-pattern, +skip-pattern, name: name, trace: trace) [SAL]
+ +(make-window pattern length-pattern skip-pattern :name name :trace trace) [LISP]
Make + a pattern of class +window-class that regroups items generated by a +pattern according to pattern lengths given by length-pattern +and where the period advances by the number of items given by +skip-pattern. +Note that length-pattern is not optional: There is no default +pattern length and no for: keyword. +
+

+

markov

+The markov-class generates items from a Markov model. A Markov model +generates a sequence of states according to rules which specify possible +future states +given the most recent states in the past. For example, states might be +pitches, and each pitch might lead to a choice of pitches for the next state. +In the markov-class, states can be either symbols or numbers, but +not arbitrary values or patterns. This makes it easier to specify rules. +However, symbols can be mapped to arbitrary values including pattern +objects, and these become the actual generated items. +By default, all future states are weighted equally, but weights +may be associated with future states. A Markov model must be +initialized with +a sequence of past states using the past: keyword. +The most common form of Markov model is a "first +order Markov model" in which the future item depends only upon one +past item. However, higher order models where the future items depend on +two or more past items are possible. A "zero-order" Markov model, which +depends on no past states, is essentially equivalent to the random pattern. +As an example of a first-order Markov pattern, +two periods of make-markov({{a -> b c} {b -> c} {c -> a}}, past: {a}) +might be (C A C) (A B C). +

+

+
+make-markov(rules, past: past, produces: produces, for: for, name: name, trace: trace) [SAL]
+ +(make-markov rules past :produces produces :for for :name name :trace trace) [LISP]
Generate a sequence +of items from a Markov process. The rules parameter has the form: +(prev1 prev2 ... prevn -> next1 next2 ... nextn) +where prev1 through prevn represent a sequence of most recent +(past) states. The symbol * is treated specially: it matches any +previous state. If prev1 through prevn (which may be just one state +as in the example above) match the previously generated states, this +rule applies. Note that every rule must specify the same number of previous +states; this number is known as the order of the Markov model. +The first rule in rules that applies is used to select the +next state. If no rule applies, the next state is NIL (which is +a valid state that can be used in rules). +Assuming a rule applies, the list of possible next +states is specified by next1 +through nextn. Notice that these are alternative choices for the +next state, not a sequence of future states, and each rule can have +any number of choices. Each choice may be the state +itself (a symbol or a number), or the choice may be a list consisting of +the state and a weight. The weight may be given by a pattern, in which +case the next item of the pattern is obtained every time the rule is +applied. For example, this rules says that if the previous states were +A and B, the next state can be A with a weight of 0.5 or C with an +implied weight of 1: (A B -> (A 0.5) C). The +default length of the period is the length of rules. The +past parameter must be provided. It is a list of states whose length +matches the order of the Markov model. The keyword parameter produces +may be used to map from state symbols or numbers to other values or +patterns. The parameter is a list of alternating symbols and values. For +example, to map A to 69 and B to 71, use list(quote(a), 69, quote(b), 71). + You can +also map symbols to patterns, for example +list(quote(a), make-cycle({57 69}), quote(b), make-random({59 71})). The +next item of the pattern is is generated each time the Markov model generates +the corresponding state. Finally, the produces keyword can be +eval:, which means to evaluate the Markov model state. This could +be useful if states are Nyquist global variables such as +C4, CS4, D4, ]..., which evaluate to numerical +values (60, 61, 62, ....

+
markov-create-rules(sequence, order [, generalize]) [SAL]
+ +(markov-create-rules sequence order [generalize]) [LISP]
Generate a set of rules suitable for the +make-markov function. The sequence is a "typical" sequence +of states, and order is the order of the Markov model. It is often the +case that a sample sequence will not have a transition from the last state +to any other state, so the generated Markov model can reach a "dead end" +where no rule applies. This might lead to an infinite stream of NIL's. To +avoid this, the optional parameter generalize can be set to t +(true), indicating that there should be a fallback rule that matches any +previous states and whose future states are weighted according to their +frequency in sequence. For example, if sequence contains 5 A's, 5 B's and +10 G's, the default rule will be (* -> (A 5) (B 5) (G 10)). This +rule will be appended to the end so it will only apply if no other rule does. +
+

+

Random Number Generators

+ +The distributions.lsp library implements random number generators that return random values with various probability distributions. Without this library, you can generate random numbers with uniform distributions. In a uniform distribution, all values are equally likely. To generate a random integer in some range, use random. To generate a real number (FLONUM) in some range, use real-random (or rrandom if the range is 0-1). But there are other interesting distributions. For example, the Gaussian distribution is often used to model +real-world errors and fluctuations where values are clustered around some central value and large deviations are more unlikely than small ones. See Dennis Lorrain, "A Panoply of Stochastic 'Canons'," Computer Music Journal vol. 4, no. 1, 1980, pp. 53-81. +

+In most of the random number generators described below, there are optional parameters to indicate a maximum and/or minimum value. These can be used to truncate the distribution. For example, if you basically want a Gaussian distribution, but you never want a value greater than 5, you can specify 5 as the maximum value. +The upper and lower bounds are implemented simply by drawing a random number from the full distribution repeatedly until a number falling into the desired range is obtained. Therefore, if you select an acceptable range that is unlikely, it may take Nyquist a long time to find each acceptable random number. The intended use of the upper and lower bounds is to weed out values that are already fairly unlikely. +

+

+
+linear-dist(g) [SAL]
+ +(linear-dist g) [LISP]
Return a FLONUM value from a linear distribution, where the probability of a value decreases linearly from zero to g which must be greater than zero. (See Figure 7.) The linear distribution is useful for generating for generating time and pitch intervals. +
+

+


+
+

+ +

+Figure 7: The Linear Distribution, g = 1. + +


+

+

+
+exponential-dist(delta [, high]) [SAL]
+ +(exponential-dist delta [high]) [LISP]
Return a FLONUM value from an exponential distribution. The initial downward slope is steeper with larger values of delta, which must be greater than zero. (See Figure 8. The optional high parameter puts an artificial upper bound on the return value. +The exponential distribution generates values greater +than 0, and can be used to generate time intervals. Natural random intervals such as the time intervals between the release of atomic particles or the passing of yellow volkswagons in traffic have exponential distributions. The +exponential distribution is memory-less: knowing that a random number from this distribution is greater than some value (e.g. a note duration is at least 1 second) tells you nothing new about how soon the note will end. This +is a continuous distribution, but geometric-dist (described below) implements the discrete form. +
+

+


+
+

+ +

+Figure 8: The Exponential Distribution, delta = 1. + +


+

+

+
+gamma-dist(nu [, high]) [SAL]
+ +(gamma-dist nu [high]) [LISP]
Return a FLONUM value from a Gamma distribution. The value is greater than zero, has a mean of nu (a FIXNUM greater than zero), and a mode (peak) of around nu - 1. + The optional high parameter puts an artificial upper bound on the return value. +
+

+


+
+

+ +

+Figure 9: The Gamma Distribution, nu = 4. + +


+

+

+
+bilateral-exponential-dist(xmu, + tau [, low, high]) [SAL]
+ +(bilateral-exponential-dist xmu tau [low high]) [LISP]
Returns a FLONUM value from a bilateral exponential distribution, where xmu is the center of the double exponential and tau controls the spread of the distribution. A larger tau gives a wider distribution (greater variance), and tau must be greater than zero. The low and high parameters give optional artificial bounds on the minimum and maximum output values, respectively. +This distribution is similar to the exponential, except +it is centered at 0 and can output negative values as well. Like +the exponential, it can be used to generate time intervals; however, it might be necessary to add a lower bound so as not to compute a negative time interval. +
+

+


+
+

+ +

+Figure 10: The Bilateral Exponential Distribution. + +


+

+

+
+cauchy-dist(tau [, low, high]) [SAL]
+ +(cauchy-dist tau [low high]) [LISP]
Returns a FLONUM from the Cauchy distribution, a symetric distribution with a high peak at zero and a width (variance) that increases with parameter tau, which must be greater than zero. The low and high parameters give optional artificial bounds on the minimum and maximum output values, respectively. +
+

+


+
+

+ +

+Figure 11: The Cauchy Distribution, tau = 1. + +


+

+

+
+hyperbolic-cosine-dist([low, high]) [SAL]
+ +(hyperbolic-cosine-dist [low high)] [LISP]
Returns a FLONUM value from the hyperbolic cosine distribution, a symetric distribution with its peak at zero. The low and high parameters give optional artificial bounds on the minimum and maximum output values, respectively. +
+

+


+
+

+ +

+Figure 12: The Hyperbolic Cosine Distribution. + +


+

+

+
+logistic-dist(alpha, beta [, low, high]) [SAL]
+ +(logistic-dist alpha beta [low high]) [LISP]
Returns a FLONUM value from the logistic distribution, which is symetric about the mean. The alpha parameter primarily affects dispersion (variance), with larger values resulting in values closer to the mean (less variance), and the beta parameter primarily influences the mean. The low and high parameters give optional artificial bounds on the minimum and maximum output values, respectively. +
+

+


+
+

+ +

+Figure 13: The Logistic Distribution, alpha = 1, beta = 2. + +


+

+

+
+arc-sine-dist() [SAL]
+ +(arc-sine-dist) [LISP]
Returns a FLONUM value from the arc sine distribution, which outputs values between 0 and 1. It is symetric about the mean of 1/2, but is more likely to generate values closer to 0 and 1. +
+

+


+
+

+ +

+Figure 14: The Arc Sine Distribution. + +


+

+

+
+gaussian-dist(xmu, sigma [, low, high]) [SAL]
+ +(gaussian-dist xmu sigma [low high]) [LISP]
Returns a FLONUM value from the Gaussian or Gauss-Laplace distribution, a linear function of the normal distribution. It is symetric about the mean of xmu, with a standard deviation of sigma, which must be greater than zero. The low and high parameters give optional artificial bounds on the minimum and maximum output values, respectively. +
+

+


+
+

+ +

+Figure 15: The Gauss-Laplace (Gaussian) Distribution, xmu = 0, sigma = 1. + +


+

+

+
+beta-dist(a, b) [SAL]
+ +(beta-dist a b) [LISP]
Returns a FLONUM value from the Beta distribution. This distribution outputs values between 0 and 1, with outputs more likely to be close to 0 or 1. The parameter a controls the height (probability) of the right side of the distribution (at 1) and b controls the height of the left side (at 0). The distribution is symetric about 1/2 when a = b. +
+

+


+
+

+ +

+Figure 16: The Beta Distribution, alpha = .5, beta = .25. + +


+

+

+
+bernoulli-dist(px1 [, x1, x2]) [SAL]
+ +(bernoulli-dist px1 [x1 x2]) [LISP]
Returns either x1 (default value is 1) with probability px1 or x2 (default value is 0) with probability 1 - px1. The value of px1 should be between 0 and 1. By +convention, a result of x1 is viewed as a success while x2 is viewed as +a failure. +
+

+


+
+

+ +

+Figure 17: The Bernoulli Distribution, px1 = .75. + +


+

+

+
+binomial-dist(n, p) [SAL]
+ +(binomial-dist n p) [LISP]
Returns a FIXNUM value from the binomial distribution, where n is the number of Bernoulli trials run (a FIXNUM) and p is the probability of success in the Bernoulli trial (a FLONUM from 0 to 1). The mean is the product of n and p. +
+

+


+
+

+ +

+Figure 18: The Binomial Distribution, n = 5, p = .5. + +


+

+

+
+geometric-dist(p) [SAL]
+ +(geometric-dist p) [LISP]
Returns a FIXNUM value from the geometric distribution, which is defined as the number of failures before a success is achieved in a Bernoulli trial with probability of success p (a FLONUM from 0 to 1). +
+

+


+
+

+ +

+Figure 19: The Geometric Distribution, p = .4. + +


+

+

+
+poisson-dist(delta) [SAL]
+ +(poisson-dist delta) [LISP]
Returns a FIXNUM value from the Poisson distribution with a mean of delta (a FIXNUM). The Poisson distribution is often used to generate a sequence of time intervals, resulting in random but often pleasing rhythms. +
+

+


+
+

+ +

+Figure 20: The Poisson Distribution, delta = 3. + +


+

+

Score Generation and Manipulation

A common application of pattern generators is to specify parameters +for notes. (It should be understood that "notes" in this context +means any Nyquist behavior, whether it represents a conventional note, +an abstract sound object, or even some micro-sound event that is just +a low-level component of a hierarchical sound organization. Similarly, +"score" should be taken to mean a specification for a +sequence of these "notes.") +The score-gen macro (defined by +loading xm.lsp) establishes a convention for representing +scores and for generating them using patterns. +

+The timed-seq macro, described in Section "Combination and Time Structure", +already provides a way to represent a "score" as a list of expressions. +The Xmusic representation goes a bit further by specifying that +all notes are specified by an alternation of keywords and values, where +some keywords have specific meanings and interpretations. +

+The basic idea of score-gen is you provide a template for notes in +a score as a set of keywords and values. For example, +

+set pitch-pattern = make-cycle(list(c4, d4, e4, f4))
+score-gen(dur: 0.4, name: quote(my-sound),
+          pitch: next(pitch-pattern), score-len: 9)
+
+ +generates a score of 9 notes as follows: +
+((0 0 (SCORE-BEGIN-END 0 3.6))
+ (0 0.4 (MY-SOUND :PITCH 60))
+ (0.4 0.4 (MY-SOUND :PITCH 62))
+ (0.8 0.4 (MY-SOUND :PITCH 64))
+ (1.2 0.4 (MY-SOUND :PITCH 65))
+ (1.6 0.4 (MY-SOUND :PITCH 60))
+ (2 0.4 (MY-SOUND :PITCH 62))
+ (2.4 0.4 (MY-SOUND :PITCH 64))
+ (2.8 0.4 (MY-SOUND :PITCH 65))
+ (3.2 0.4 (MY-SOUND :PITCH 60)))
+
+ +The use of keywords like :PITCH helps to make scores +readable and easy to process without specific knowledge of +about the functions called in the score. For example, one +could write a transpose operation to transform all the +:pitch parameters in a score without having to know +that pitch is the first parameter of pluck and the +second parameter of piano-note. Keyword parameters are +also used to give flexibility to note specification with +score-gen. Since this approach requires the use of +keywords, the next section +is a brief explanation of how to define functions that use +keyword parameters. +

+

Keyword Parameters

+ + +Keyword parameters are parameters whose presence is +indicated by a special symbol, called a keyword, followed +by the actual parameter. Keyword parameters in SAL have +default values that are used if no actual parameter is +provided by the caller of the function. (See Appendix + "XLISP: An Object-oriented Lisp" to learn about keywords in XLISP.) +

+To specify that a parameter is a keyword parameter, +use a keyword symbol (one that ends in a colon) followed +by a default value. + For example, here is a function that +accepts keyword parameters and invokes the pluck +function: +

+define function k-pluck(pitch: 60, dur: 1)
+  return pluck(pitch, dur)
+
+ +Now, we can call k-pluck with keyword parameters. The +keywords are simply the formal parameter names with +a prepended colon character (:pitch and :dur +in this example), so a function call would look like: +
+pluck(pitch: c3, dur: 3)
+
+ +Usually, it is best to give keyword parameters useful +default values. That way, if a parameter such as dur: +is missing, a reasonable default value (1) can be used +automatically. +It is never an error to omit a keyword parameter, but the +called function can check to see if a keyword parameter +was supplied or not. +Because of default values, we can call +k-pluck(pitch: c3) with no duration, +k-pluck(dur: 3) with only a duration, +or even k-pluck() with no parameters. +

+In XLISP, there is additional syntax to specify an alternate symbol +to be used as the keyword and to allow the called function +to determine whether or not a keyword parameter was +supplied, but these features are little-used. See the XLISP +manual for details. +

+

Using score-gen

+The score-gen macro computes a score based on keyword parameters. +Some keywords have a special meaning, while others are not interpreted +but merely placed in the score. The resulting score can be synthesized +using timed-seq (see Section "Combination and Time Structure"). +

+The form of a call to score-gen is simply: +

+
+score-gen(k1: e1, k2: e2, ...) [SAL]
+ +(score-gen :k1 e1 :k2 e2 ...) [LISP]
where the k's +are keywords and the e's are +expressions. A score is generated by evaluating the expressions once for +each note and constructing a list of keyword-value pairs. A number +of keywords have special interpretations. The rules for interpreting +these parameters will be explained through a set of "How do I ..." +questions below. +
+

+How many notes will be generated? The keyword +parameter score-len: specifies an upper bound on the number +of notes. (Note: in LISP syntax, keywords +are always preceded by colons, so you would write +:score-len instead.) The keyword score-dur: specifies an upper bound +on the starting time of the last note in the score. (To be more +precise, the score-dur: bound is reached when the +default starting time of the next note is greater than or equal +to the score-dur: value. This definition is necessary because +note times are not strictly increasing.) When either bound +is reached, score generation ends. At least one of these two +parameters must be specified or an error is raised. These keyword +parameters are evaluated just once and are not copied into the +parameter lists of generated notes. +

+What is the duration of generated notes? The +keyword dur: defaults to 1 and specifies the nominal duration +in seconds. Since the generated note list is compatible with +timed-seq, the starting time and duration (to be precise, the +stretch factor) are not passed as parameters to the notes. Instead, +they control the Nyquist environment in which the note will be evaluated. +

+What is the start time of a note? The default start time of the +first note is zero. Given a note, the default start time of the next note is +the start time plus the inter-onset time, which is given by the ioi: +parameter. If no ioi: parameter is specified, the inter-onset time +defaults to the duration, given by dur:. In all cases, the default +start time of a note can be overridden by the keyword parameter time:. +

+When does the score begin and end? The behavior SCORE-BEGIN-END +contains the beginning and ending of the +score (these are used for score manipulations, e.g. when scores are merged, +their begin times can be aligned.) When timed-seq is used to +synthesize a score, the SCORE-BEGIN-END marker is +not evaluated. The score-gen macro inserts a "note" of the form +(0 0 (SCORE-BEGIN-END begin-time end-time)) +at the time given by the begin: keyword, with begin-time and +end-time determined by the begin: and end: +keyword parameters, respectively. If the begin: keyword is not +provided, the score begins at zero. If the end: keyword +is not provided, the score ends at the default start time +of what would be the next note after the last note in the score +(as described in the previous paragraph). Note: if time: is used to +compute note starting times, and these times are not increasing, it is +strongly advised to use end: to specify an end time for the score, +because the default end time may be anywhere in the middle of the +generated sequence. +

+What function is called to synthesize the note? The name: +parameter names the function. Like other parameters, the value can be any +expression, including something like next(fn-name-pattern), +allowing function names to be recomputed for each note. The default value +is note. +

+Can I make parameters depend upon the starting time or the duration +of the note? Parameter expressions can use the variable sg:time +to access the start time of the note, sg:ioi to access the +inter-onset time, and sg:dur to access the +duration (stretch factor) of the note. Also, sg:count counts how +many notes have been computed so far, starting at 0. The order of +computation is: sg:time first, then sg:ioi and sg:dur, +so for example, an expression to compute sg:dur can +depend on sg:ioi. +

+Can parameters depend on each other? The keyword pre: +introduces an expression that is evaluated before each note, and +post: provides an expression to be evaluated after each note. +The pre: expression can assign one or more global variables +which are then used in one or more expressions for parameters. +

+How do I debug score-gen expressions? You can set the +trace: parameter to true (t) to enable a print statement +for each generated note. +

+How can I save scores generated by score-gen that I like? If the +keyword parameter save: is set to a symbol, the global variable +named by the symbol is set to the value of the generated sequence. Of +course, the value returned by score-gen is just an ordinary list that +can be saved like any other value. +

+In summary, the following keywords have special interpretations +in score-gen: +begin:, end:, time:, dur:, name:, +ioi:, trace:, +save:, score-len:, score-dur:, pre:, post:. + All other keyword +parameters are expressions that are evaluated once for each note +and become the parameters of the notes. +

+

Score Manipulation

+ +Nyquist encourages the representation of music as +executable programs, or behaviors, and there are various +ways to modify behaviors, including time stretching, +transposition, etc. An alternative to composing executable +programs is to manipulate scores as editable data. Each +approach has its strengths and weaknesses. This section +describes functions intended to manipulate Xmusic scores +as generated by, or at least in the form generated by, +score-gen. Recall that this means scores are lists +of events (e.g. notes), where events are three-element lists of the form +(time duration expression, and where expression +is a standard lisp function call where all parameters are +keyword parameters. In addition, the first "note" may be +the special SCORE-BEGIN-END expression. If this is +missing, the score begins at zero and ends at the end of the +last note. +

+For convenience, a set of functions is offered to access properties +of events (or notes) in scores. Although lisp functions such as +car, cadr, and caddr can be used, code is more +readable when more mnemonic functions are used to access events. +

+

+
+event-time(event) [SAL]
+ +(event-time event) [LISP]
Retrieve the time field from +an event.

+
event-set-time(event, time) [SAL]
+ +(event-set-time event time) [LISP]
Construct +a new event where the time of event is replaced by time.

+
event-dur(event) [SAL]
+ +(event-dur event) [LISP]
Retrieve the duration +(i.e. the stretch factor) field from an event.

+
event-set-dur(event, dur) [SAL]
+ +(event-set-dur event dur) [LISP]
Construct +a new event where the duration (or stretch factor) of event is +replaced by dur.

+
event-expression(event) [SAL]
+ +(event-expression event) [LISP]
Retrieve the expression +field from an event.

+
event-set-expression(event, +dur) [SAL]
+ +(event-set-expression event dur) [LISP]
Construct +a new event where the expression of event is replaced by expression.

+
event-end(event) [SAL]
+ +(event-end event) [LISP]
Retrieve the end time +of event, its time plus its duration.

+
expr-has-attr(expression, attribute) [SAL]
+ +(expr-has-attr expression attribute) [LISP]
Test +whether a score event expression has the given attribute.

+
expr-get-attr(expression, attribute [, default]) [SAL]
+ +(expr-get-attr expression attribute [default]) [LISP]
Get the value of the given attribute from a score event +expression. If attribute is not present, return default if +specified, and otherwise nil.

+
expr-set-attr(expr, attribute, value) [SAL]
+ +(expr-set-attr expr attribute value) [LISP]
Construct a new expression identical to expr except that the attribute has value.

+
event-has-attr(event, attribute) [SAL]
+ +(event-has-attr event attribute) [LISP]
Test +whether a given score event's expression has the given attribute.

+
event-get-attr(event, attribute, +[default]) [SAL]
+ +(event-get-attr event attribute [default]) [LISP]
Get the value of the given attribute from a score +event's expression. If attribute is not present, return default if +specified, and otherwise nil.

+
event-set-attr(event, attribute, value) [SAL]
+ +(event-set-attr event attribute value) [LISP]
Construct a new event identical to event except that the attribute has value.

+
Functions are provided to shift the starting times of notes, +stretch times and durations, stretch only durations, +add an offset to a keyword parameter, scale a keyword parameter, and +other manipulations. Functions are also provided to extract +ranges of notes, notes that match criteria, and to combine scores. +Most of these functions (listed below in detail) +share a set of keyword parameters that optionally limit the range over which +the transformation operates. The from-index: and to-index: +parameters specify the index of the first note and the index of the +last note to be changed. If these numbers are negative, they are offsets +from the end of the score, e.g. -1 denotes the last note of the score. The +from-time: and to-time: indicate a range of starting times +of notes that will be affected by the manipulation. Only notes whose time +is greater than or equal to the from-time and strictly less than + the to-time are modified. If both index and time ranges are specified, +only notes that satisfy both constraints are selected. (Note: in +LISP syntax, colons precede the keyword, so use +:from-index, :to-index, :from-time, and :to-time.) +

+

+
+score-sorted(score) [SAL]
+ +(score-sorted score) [LISP]
Test if score is sorted.

+
score-sort(score [, copy-flag]) [SAL]
+ +(score-sort score [copy-flag]) [LISP]
Sort + the notes in a +score into start-time order. If copy-flag is nil, this is a destructive +operation which should only be performed if the top-level score list +is a fresh copy that is not shared by any other variables. (The +copy-flag is intended for internal system use only.) + For the following operations, it is assumed +that scores are sorted, and all operations return a sorted score.

+
score-shift(score, offset, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL]
+ +(score-shift score offset + :from-index i :to-index j :from-time x + :to-time y) [LISP]
Add a constant +offset to the starting time of a set of notes in score. By default, +all notes are modified, but the range of notes can be limited with the +keyword parameters. The begin time of the score is not changed, but the +end time is increased by offset. +The original score is not modified, and a new score is returned.

+
score-stretch(score, factor, dur: dur-flag, time: time-flag, from-index: i, + to-index: j, from-time: x, to-time: y) [SAL]
+ +(score-stretch score factor + :dur dur-flag :time time-flag :from-index i + :to-index j :from-time x :to-time y) [LISP]
Stretch +note times and durations by factor. The default dur-flag is +non-null, but if dur-flag is null, the original durations are retained +and only times are stretched. Similarly, the default time-flag is +non-null, but if time-flag is null, the original times are retained +and only durations are stretched. If both dur-flag and time-flag +are null, the score is not changed. If a range +of notes is specified, times are scaled within that range, and +notes after the range are shifted so that the stretched region does not +create a "hole" or overlap with notes that follow. If the range begins +or ends with a time (via from-time: and to-time:), time +stretching +takes place over the indicated time interval independent of whether +any notes are present or where they start. In other words, the +"rests" are stretched along with the notes. +The original score is not modified, and a new score is returned.

+
score-transpose(score, + keyword, amount, from-index: i, to-index: j, + from-time: x, to-time: y) [SAL]
+ +(score-transpose score + keyword amount :from-index i :to-index j + :from-time x :to-time y) [LISP]
For + each note in the score and in any indicated range, if there is a keyword + parameter matching keyword and the +parameter value is a number, increment +the parameter value by amount. For example, to tranpose up by a whole +step, write (score-transpose 2 :pitch score). The +original score is not modified, and a new score +is returned.

+
score-scale(score, keyword, amount, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL]
+ +(score-scale score keyword amount + :from-index i :to-index j :from-time x + :to-time y) [LISP]
For each note +in the score and in any indicated range, if there is a keyword +parameter matching keyword and the +parameter value is a number, multiply +the parameter value by amount. The original score is not modified, +and a new score is returned.

+
score-sustain(score, factor, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL]
+ +(score-sustain score factor + :from-index i :to-index j :from-time x + :to-time y) [LISP]
For each note +in the score and in any indicated range, multiply +the duration (stretch factor) by amount. This can be used to +make notes sound more legato or staccato, and does not change their +starting times. The original score is not modified, and +a new score is returned.

+
score-voice(score, + replacement-list, from-index: i, to-index: j, + from-time: x, to-time: y) [SAL]
+ +(score-voice score + replacement-list :from-index i :to-index j + :from-time x :to-time y) [LISP]
For each note +in the score and in any indicated range, replace the behavior (function) +name using replacement-list, which has the format: +((old1 new1) (old2 new2) ...), where oldi indicates +a current behavior name and newi is the replacement. If oldi +is *, it matches anything. For example, to +replace my-note-1 by trombone and my-note-2 by +horn, use score-voice(score, {{my-note-1 trombone} +{my-note-2 horn}}). To replace all instruments with +piano, use score-voice(score, {{* piano}}). +The original score is not modified, and a + new score is returned.

+
score-merge(score1, score2, ...) [SAL]
+ +(score-merge score1 score2 ...) [LISP]
Create +a new score containing all the notes of the parameters, which are all +scores. The resulting notes retain their original times and durations. The +merged score begin time is the minimum of the begin times of the parameters +and the merged score end time is the maximum of the end times of +the parameters. The original scores are not modified, and a new +score is returned.

+
score-append(score1, score2, ...) [SAL]
+ +(score-append score1 score2 ...) [LISP]
Create +a new score containing all the notes of the parameters, which are all +scores. The begin time of the first score is unaltered. The begin time of + each other score is aligned to the end time of the +previous score; thus, scores are "spliced" in sequence. The original +scores are not modified, and a new score is returned.

+
score-select(score, + predicate, from-index: i, to-index: j, from-time: x, + to-time: y, reject: flag) [SAL]
+ +(score-select score + predicate :from-index i :to-index j :from-time x + :to-time y :reject flag) [LISP]
Select (or reject) +notes to form a new score. Notes are selected if they fall into the +given ranges of index and time and they satisfy predicate, a function +of three parameters that is applied to the start time, duration, and the +expression of the note. Alternatively, predicate may be t, +indicating that all notes in range are to be selected. +The selected notes along with the existing score begin and end markers, are combined to form a new score. Alternatively, if +the reject: parameter is non-null, the notes not selected form + the new score (in other words the selected notes are rejected or removed to + form the new score). The original score is not modified, and a + new score is returned.

+
score-set-begin(score, time) [SAL]
+ +(score-set-begin score time) [LISP]
The begin +time + from the score's SCORE-BEGIN-END marker is set to time. The +original score is not modified, and a new score is returned.

+
score-get-begin(score) [SAL]
+ +(score-get-begin score) [LISP]
Return the begin +time of the score.

+
score-set-end(score, time) [SAL]
+ +(score-set-end score time) [LISP]
The end time + from the score's SCORE-BEGIN-END marker is set to time. The +original score is not modified, and a new score is returned.

+
score-get-end(score) [SAL]
+ +(score-get-end score) [LISP]
Return the end +time of the score.

+
score-must-have-begin-end(score) [SAL]
+ +(score-must-have-begin-end score) [LISP]
If + score does not have a begin and end time, construct a score with a + SCORE-BEGIN-END expression and return it. If score already has a begin +and end time, just return the score. The orignal score is not modified.

+
score-filter-length(score, +cutoff) [SAL]
+ +(score-filter-length score cutoff) [LISP]
Remove notes that extend beyond the cutoff time. This +is similar to score-select, but the here, events are removed when +their nominal ending time (start time plus duration) exceeds the cutoff, +whereas the to-time: parameter is compared to the note's start time. +The original score is not modified, and a new score is returned.

+
score-repeat(score, n) [SAL]
+ +(score-repeat score n) [LISP]
Make a sequence +of n copies of score. Each copy is shifted to that it's begin +time aligns with the end time of the previous copy, as in score-append. +The original score is not modified, and a new score is returned.

+
score-stretch-to-length(score, +length) [SAL]
+ +(score-stretch-to-length score length) [LISP]
Stretch the score so that the end time of the score is +the score's begin time plus length. +The original score is not modified, and a new score is returned.

+
score-filter-overlap(score) [SAL]
+ +(score-filter-overlap score) [LISP]
Remove +overlapping notes (based on the note start time and duration), giving +priority to the +positional order within the note list (which is also time order). +The original score is not modified, +and a new score is returned.

+
score-print(score) [SAL]
+ +(score-print score) [LISP]
Print a score with +one note per line. Returns nil.

+
score-play(score) [SAL]
+ +(score-play score) [LISP]
Play score +using timed-seq to convert the score to a sound, and + play to play the sound.

+
score-adjacent-events(score, + function, + from-index: i, to-index: j, + from-time: x, to-time: y) [SAL]
+ +(score-adjacent-events score function :from-index i :to-index j :from-time x :to-time y) [LISP]
Call + (function A B C), where +A, B, and C are consecutive notes in the score. The result +replaces B. If the result is nil, B is deleted, and the +next call will be (function A C D), etc. The first call is +to (function nil A B) and the last is to +(function Y Z nil). If there is just one note in the +score, (function nil A nil) is called. Function calls +are not made if the note is outside of the indicated range. +This function +allows notes and their parameters to be adjusted according to their +immediate context. The original score is not modified, +and a new score is returned.

+
score-apply(score, function, + from-index: i, to-index: j, from-time: x, to-time: y) +[SAL]
+ +(score-apply score function :from-index i :to-index j :from-time x :to-time y) [LISP]
Replace +each note in the score with the result of + (function time dur expression) (in Lisp) or + function(time, dur, expression) (in SAL), +where time, dur, +and expression are the time, duration, and expression of the note. +If a range is indicated, only notes in the range are replaced. +The original score is not modified, and a new score is returned.

+
score-indexof(score, function, + from-index: i, to-index: j, from-time: x, to-time: y) [SAL]
+ +(score-indexof score function :from-index i :to-index j :from-time x :to-time y) [LISP]
Return the index (position) +of the first score event (in range) for which applying function +using (function time dur expression) returns true.

+
score-last-indexof(score, + function, from-index: i, to-index: j, from-time: x, +to-time: y) [SAL]
+ +(score-last-indexof score function + :from-index i :to-index j :from-time x :to-time y) [LISP]
Return the index (position) +of the last score event (in range) for which applying function +using (function time dur expression) returns true.

+
score-randomize-start(score, amt, from-index: i, to-index: j, from-time: x, + to-time: y) [SAL]
+ +(score-randomize-start score amt + :from-index i :to-index j :from-time x + :to-time y) [LISP]
Alter the start times of notes by a +random amount up to plus or minus amt. +The original score is not modified, and a new score is returned. +
+

+

Xmusic and Standard MIDI Files

+ +Nyquist has a general facility to read and write MIDI files. +You can even translate to and from a text representation, as described +in Chapter "MIDI, Adagio, and Sequences". It is also useful sometimes to read notes +from Standard MIDI Files into Xmusic scores and vice versa. At present, +Xmusic only translates notes, ignoring the various controls, program +changes, pitch bends, and other messages. +

+MIDI notes are translated to Xmusic score events as follows: +

+(time dur (NOTE :chan channel :pitch keynum :vel velocity)),
+ +
+where channel, keynum, and velocity come directly +from the MIDI message (channels are numbered starting from zero). +Note also that note-off messages are implied by the stretch factor +dur which is duration in seconds. +

+

+
+score-read-smf(filename) [SAL]
+ +(score-read-smf filename) [LISP]
Read a +standard MIDI file from filename. Return an Xmusic score, or nil +if the file could not be opened. The +start time is zero, and the end time is the maximum end time of all +notes. A very limited interface is offered to extract MIDI program numbers +from the file: The global variable *rslt* is set to a list of MIDI +program numbers for each channel. E.g. if *rslt* is (0 20 77), +then program for channel 0 is 0, for channel 1 is 20, and for channel 2 is 77. +Program changes were not found on other channels. The default program number is +0, so in this example, it is not known whether the program 0 on channel 0 +is the result of a real MIDI program change command or just a default value. +If more than one program change exists on a channel, the last program +number is recorded and returned, so this information will only be completely +correct when the MIDI file sends single program change per channel before +any notes are played. This, however, is a fairly common practice. Note that +the list returned as *rslt* can be passed +to score-write-smf, described below.

+
score-write-smf(score, filename, +[programs]) [SAL]
+ +(score-write-smf score filename programs) [LISP]
Write a standard MIDI file to filename +with notes in score. In this function, +every event in the score with a pitch: attribute, regardless of the +"instrument" (or function name), generates a +MIDI note, using the chan: attribute for the channel (default 0) and +the vel: attribute for velocity (default 100). There is no facility +(in the current implementation) to issue control changes, but to allow +different instruments, MIDI programs may be set in two ways. The simplest is +to associate programs with channels using +the optional programs parameter, which is simply a list of up to 16 MIDI +program numbers. Corresponding program change commands are added to the +beginning of the MIDI file. If programs has less than 16 elements, program +change commands are only sent on the first n channels. The second way to +issue MIDI program changes is to add a program: keyword parameter to +a note in the score. Typically, the note will have a pitch: of +nil so that no actual MIDI note-on message is generated. If program +changes and notes have the same starting times, their relative playback +order is undefined, and the note may be cut off by an immediately +following program change. Therefore, program changes should occur slightly, +e.g. 1 ms, before any notes. Program numbers and channels are numbered +starting at zero, matching the internal MIDI representation. This may be +one less than displayed on MIDI hardware, sequencers, etc. +
+

+

Workspaces

+ + +When working with scores, you may find it necessary to save +them in files between work sessions. This is not an issue +with functions because they are +normally edited in files and loaded from them. In contrast, +scores are created as Lisp data, and unless you take care to +save them, they will be destroyed when you exit the Nyquist +program. +

+A simple mechanism called a workspace has been created +to manage scores (and any other Lisp data, for that matter). +A workspace is just a set of lisp global variables. These +variables are stored in the file workspace.lsp. +For simplicity, there is only one workspace, and no backups +or versions are maintained, but the user is free to make +backups and copies of workspace.lsp. +To help remember what each variable is for, you can also +associate and retrieve a text string with each variable. +The following functions manage workspaces. +

+In addition, when a workspace is loaded, you can request that +functions be called. For example, the workspace might store +descriptions of a graphical interface. When the workspace is +loaded, a function might run to convert saved data into a +graphical interface. (This is how sliders are saved by the IDE.) +

+

+
+add-to-workspace(symbol) [SAL]
+ +(add-to-workspace symbol) [LISP]
Adds +a global variable to the workspace. The symbol should be a (quoted) +symbol.

+
save-workspace() [SAL]
+ +(save-workspace) [LISP]
All global variables +in the workspace are saved to workspace.lsp (in the current +directory), overwriting the previous file.

+
describe(symbol [, description]) + [SAL]
+ +(describe symbol [description)] [LISP]
If description, a text string, is present, +associate description with the variable named by the +symbol. If symbol is not already in the workspace, +it is added. If description is omitted, the function returns +the current description (from a previous call) for symbol.

+
add-action-to-workspace(symbol) [SAL]
+ +(add-action-to-workspace symbol) [LISP]
Requests that the function named by symbol be +called when the workspace is loaded (if the function is defined). +
+

+To restore a workspace, use the command load "workspace". This restores +the values of the workspace variables to the values they had when +save-workspace was last called. It also restores the documentation +strings, if set, by describe. If you load two or more +workspace.lsp files, the variables will be merged into a +single workspace. The current set of workspace variables are saved in +the list *workspace*. To clear the workspace, set *workspace* +to nil. This does not delete any variables, but means that +no variables will be saved by save-workspace until variables are +added again. +

+Functions to be called are saved in the list *workspace-actions*. +to clear the functions, set *workspace-actions* to nil. +Restore functions to the list with add-action-to-workspace. +

+

Utility Functions

+This chapter concludes with details of various utility functions for score +manipulation. +

+

+
+patternp(expression) [SAL]
+ +(patternp expression) [LISP]
Test if expression is +an Xmusic pattern.

+
params-transpose(params, keyword, + amount) [SAL]
+ +(params-transpose params keyword amount) [LISP]
Add a transposition amount to a score event parameter. The +params +parameter is a list of keyword/value pairs (not preceded by a function name). +The keyword is the keyword of the value to be altered, and amount +is a number to be added to the value. If no matching keyword is present +in params, then params is returned. Otherwise, a new parameter +list is constructed and returned. The original params is not changed.

+
params-scale(params, keyword, + amount) [SAL]
+ +(params-scale params keyword amount) [LISP]
Scale a score event parameter by some factor. This is like + params-transpose, only using multiplication. The params +list is a list of +keyword/value pairs, keyword is the parameter keyword, +and amount is the scale factor.

+
interpolate(x, x1, y1, x2, y2) [SAL]
+ +(interpolate x x1 y1 x2 y2) [LISP]
Linearly interpolate (or extrapolate) + between points +(x1, y1) and (x2, y2) to compute the y value + corresponding to x.

+
intersection(a, + b) [SAL]
+ +(intersection a b) [LISP]
Compute the set intersection of lists a and b.

+
union(a, b) [SAL]
+ +(union a b) [LISP]
Compute +the set union of lists a and b.

+
set-difference(a, + b) [SAL]
+ +(set-difference a b) [LISP]
Compute the set of all elements that are in a but not in b.

+
subsetp(a, b) [SAL]
+ +(subsetp a b) [LISP]
Returns true iff +a is a subset of b, that is, each element of a is a member +of b. +
+

+


+
Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part15.html b/doc/part15.html new file mode 100644 index 0000000..69d8fbf --- /dev/null +++ b/doc/part15.html @@ -0,0 +1,840 @@ +Nyquist Libraries + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Nyquist Libraries

+ +Nyquist is always growing with new functions. Functions that are most fundamental +are added to the core language. These functions are automatically loaded when you +start Nyquist, and they are documented in the preceding chapters. Other functions seem +less central and are implemented as lisp files that you can load. These are called +library functions, and they are described here. +

+To use a library function, you +must first load the library, e.g. (load "pianosyn") loads the piano synthesis +library. The libraries are all located in the lib directory, and you +should therefore include this directory on your XLISPPATH variable. (See +Section "Introduction and Overview".) Each library is documented in one of the following +sections. When you load the library described by the section, all functions +documented in that section become available. +

+

Piano Synthesizer

+The piano synthesizer (library name is pianosyn.lsp) generates +realistic piano tones using a multiple wavetable implementation by Zheng (Geoffrey) +Hua and Jim Beauchamp, University of Illinois. Please see the notice about +acknowledgements that prints when you load the file. Further informations and +example code can be found in +demos/piano.htm. +There are several useful functions in this library: +
+
+piano-note(duration, step, + dynamic) [SAL]
+ +(piano-note duration step dynamic) [LISP]
Synthesizes a piano tone. Duration is the duration to the point of +key release, after which there is a rapid decay. Step is the pitch in half +steps, and dynamic is approximately equivalent to a MIDI key velocity +parameter. Use a value near 100 for a loud sound and near 10 for a soft sound.

+
piano-note-2(step, dynamic) [SAL]
+ +(piano-note-2 step dynamic) [LISP]
Similar to piano-note except the duration is nominally 1.0.

+
piano-midi(midi-file-name) [SAL]
+ +(piano-midi midi-file-name) [LISP]
Use the piano synthesizer +to play a MIDI file. The file name (a string) is given by midi-file-name.

+
piano-midi2file(midi-file-name, +sound-file-name) [SAL]
+ +(piano-midi2file midi-file-name sound-file-name) [LISP]
Use the piano synthesizer to play a MIDI file. The MIDI file +is given by midi-file-name and the (monophonic) result is written to the file +named sound-file-name. +
+

+

Dymanics Compression

+To use these functions, load the file compress.lsp. This library +implements a compressor originally intended for noisy speech audio, but +usable in a variety of situations. +There are actually two compressors that can be used in +series. The first, compress, is +a fairly standard one: it detects signal level with an RMS +detector and uses table-lookup to determine how much gain +to place on the original signal at that point. One bit of +cleverness here is that the RMS envelope is "followed" or +enveloped using snd-follow, which does look-ahead to anticipate +peaks before they happen. +

+The other interesting feature is compress-map, which builds +a map in terms of compression and expansion. For speech, the recommended +procedure is to figure out the noise floor on the signal you are compressing +(for example, look at the signal where the speaker is not talking). +Use a compression map that leaves the noise alone and boosts +signals that are well above the noise floor. Alas, the compress-map +function is not written in these terms, so some head-scratching is +involved, but the results are quite good. +

+The second compressor is called agc, and it implements automatic gain +control that keeps peaks at or below 1.0. By combining compress and +agc, you can process poorly recorded speech for playback on low-quality +speakers in noisy environments. The compress function modulates the +short-term gain to to minimize the total dynamic range, keeping the speech at +a generally loud level, and the agc function rides the long-term gain +to set the overall level without clipping. +

+

+
+compress-map(compress-ratio, +compress-threshold, +expand-ratio, expand-ratio, limit: limit, transition: +transition) [SAL]
+ +(compress-map compress-ratio compress-threshold + expand-ratio expand-ratio :limit limit :transition + transition]) [LISP]
Construct +a map for the compress function. The map consists of two parts: a compression +part and an expansion part. +The intended use is to compress everything above compress-threshold by +compress-ratio, and to downward expand everything below expand-ratio +by expand-ratio. Thresholds are in dB and ratios are dB-per-dB. +0dB corresponds to a peak amplitude of 1.0 or rms amplitude of 0.7 +If the input goes above 0dB, the output can optionally be limited +by setting limit: (a keyword parameter) to T. +This effectively changes +the compression ratio to infinity at 0dB. If limit: is nil +(the default), then the compression-ratio continues to apply above 0dB.

+
Another keyword parameter, transition:, sets the amount below the +thresholds (in dB) that a smooth transition starts. The default is 0, +meaning that there is no smooth transition. The smooth transition is a +2nd-order polynomial that matches the slopes of the straight-line compression +curve and interpolates between them.

+
It is assumed that expand-threshold <= compress-threshold <= 0 +The gain is unity at 0dB so if compression-ratio > 1, then gain +will be greater than unity below 0dB.

+
The result returned by this function is a sound for use in the shape +function. The sound maps input +dB to gain. Time 1.0 corresponds to 0dB, time 0.0 corresponds to +-100 dB, and time 2.0 corresponds to +100dB, so this is a +100hz "sample rate" sound. The sound gives gain in dB.

+
db-average(input) [SAL]
+ +(db-average input) [LISP]
Compute the average amplitude +of input in dB.

+
compress(input, map, rise-time, fall-time [, lookahead]) [SAL]
+ +(compress input map rise-time fall-time + [lookahead)] [LISP]
Compress +input using map, a compression curve +probably generated by compress-map (see above). Adjustments in gain have +the given rise-time and fall-time. Lookahead tells how far ahead to look +at the signal, and is rise-time by default.

+
agc(input, +range, rise-time, fall-time [, lookahead]) [SAL]
+ +(agc input range rise-time fall-time + [lookahead]) [LISP]
An automatic +gain control applied to input. The maximum gain in dB is range. Peaks +are attenuated to 1.0, and gain is controlled with the given rise-time and +fall-time. The look-ahead time default is rise-time. +
+

+

Clipping Softener

+This library, in soften.lsp, was written to improve the quality of +poorly recorded speech. In recordings of speech, extreme clipping generates +harsh high frequency noise. This can sound particulary bad on small speakers +that will emphasize high frequencies. This problem can be ameliorated by +low-pass filtering regions where clipping occurs. The effect is to dull the +harsh clipping. Intelligibility is not affected by much, and the result can +be much more pleasant on the ears. Clipping is detected simply by looking for +large signal values. Assuming 8-bit recording, this level is set to 126/127. +

+The function works by cross-fading between the normal signal and a filtered +signal as opposed to changing filter coefficients. +

+

+
+soften-clipping(snd, +cutoff) [SAL]
+ +(soften-clipping snd cutoff) [LISP]
Filter the loud regions of a signal where clipping is likely +to have generated additional high frequencies. The input signal is snd +and cutoff is the filter cutoff frequency +(4 kHz is recommended for speech). +
+

+

Graphical Equalizer

+There's nothing really "graphical" about this library (grapheq.lsp), but +this is a common term for multi-band equalizers. This implementation uses +Nyquist's eq-band function to split the incoming signal into different +frequency bands. Bands are spaced geometrically, e.g. each band could be one +octave, meaning that each successive band has twice the bandwidth. An interesting +possibility is using computed control functions to make the equalization change +over time. +

+

+
+nband-range(input, gains, lowf, highf) [SAL]
+ +(nband-range input gains lowf highf) [LISP]
A graphical equalizer applied to +input (a SOUND). The gain controls and number of bands is given by gains, an +ARRAY of SOUNDs (in other words, a Nyquist multichannel SOUND). Any sound in the +array may be replaced by a FLONUM. The bands are +geometrically equally spaced from the lowest frequency lowf to the +highest frequency highf (both are FLONUMs).

+
nband(input, gains) [SAL]
+ +(nband input gains) [LISP]
A graphical equalizer, identical +to nband-range with a range of 20 to 20,000 Hz. +
+

+

Sound Reversal

+The reverse.lsp library implements functions to play sounds in reverse. +

+

+
+s-reverse(snd) [SAL]
+ +(s-reverse snd) [LISP]
Reverses snd (a SOUND). Sound must be shorter +than *max-reverse-samples*, which is currently initialized to +25 million samples. Reversal allocates about 4 bytes per sample. This function +uses XLISP in the inner sample loop, so do not be surprised if it calls the +garbage collector a lot and runs slowly. The result starts at the starting +time given by the current environment (not necessarily the starting time +of snd). If snd has multiple channels, a multiple channel, +reversed sound is returned.

+
s-read-reverse(filename, time-offset: offset, srate: sr, dur: dur, nchans: chans, format: format, mode: mode, bits: n, swap: flag) [SAL]
+ +(s-read-reverse filename :time-offset offset + :srate sr :dur dur :nchans chans :format format :mode mode :bits n :swap flag) [LISP]
This function is identical to s-read (see "Sound File Input and Output"), except it reads the indicated samples in reverse. Like +s-reverse (see above), it uses XLISP in the inner loop, so it is slow. +Unlike s-reverse, s-read-reverse uses a fixed amount of +memory that is independent of how many samples are computed. Multiple channels +are handled. +
+

+

Time Delay Functions

+The time-delay-fns.lsp library implements chorus, phaser, and flange effects. +

+

+
+phaser(snd) [SAL]
+ +(phaser snd) [LISP]
A phaser effect +applied to snd (a SOUND). There are no parameters, +but feel free to modify the source code of this one-liner.

+
flange(snd) [SAL]
+ +(flange snd) [LISP]
A flange effect +applied to snd. To vary the rate and other parameters, see the source code.

+
stereo-chorus(snd) [SAL]
+ +(stereo-chorus snd) [LISP]
A chorus effect applied to snd, +a SOUND (monophonic). The output is a stereo sound. All parameters are built-in, +but see the simple source code to make modifications.

+
chorus(snd, maxdepth, depth, rate, +saturation) [SAL]
+ +(chorus snd maxdepth depth rate saturation) [LISP]
A chorus effect applied to snd. All parameters may be arrays +as usual. The maxdepth is a FLONUM giving twice the maximum value of depth, +which may be a FLONUM or a SOUND. The chorus is implemented as a variable delay +modulated by a sinusoid running at rate Hz (a FLONUM). The sinusoid is +scaled by depth and offset by maxdepth/2. The delayed signal is mixed +with the original, and saturation gives the fraction of the delayed signal +(from 0 to 1) in the mix. A reasonable choice of parameter values is +maxdepth = 0.05, depth = 0.025, rate = 0.5, and saturation = 0.5. +
+

+

Multiple Band Effects

+ +The bandfx.lsp library implements several effects based on multiple +frequency bands. The idea is to separate a signal into different frequency +bands, apply a slightly different effect to each band, and sum the effected +bands back together to form the result. This file includes its own set of +examples. After loading the file, try f2(), f3(), f4(), +and f5() to hear them. +

+There is much room for expansion and experimentation with this library. Other +effects might include distortion in certain bands (for example, there are +commercial effects that add distortion to low frequencies to enhance the sound +of the bass), separating bands into different channels for stereo or multi-channel +effects, adding frequency-dependent reverb, and performing dynamic compression, +limiting, or noise gate functions on each band. There are also opportunities for +cross-synthesis: using the content of bands extracted from one signal to modify +the bands of another. The simplest of these would be to apply amplitude envelopes +of one sound to another. Please contact us (dannenberg@cs.cmu.edu) if you +are interested in working on this library. +

+

+
+apply-banded-delay(s, lowp, highp, num-bands, lowd, highd, fb, wet) [SAL]
+ +(apply-banded-delay s lowp highp num-bands lowd highd fb wet) [LISP]
Separates +input SOUND s into FIXNUM num-bands bands from a low frequency +of lowp to a high frequency of highp (these are FLONUMS that specify +steps, not Hz), and applies a delay to each band. The delay for the lowest band is +given by the FLONUM lowd (in seconds) and the delay for the highest band +is given by the FLONUM highd. The delays for other bands are linearly +interpolated between these values. Each delay has feedback gain controlled by +FLONUM fb. The delayed bands are scaled by FLONUM wet, and +the original sound is scaled by 1 - wet. All are summed to form the result, +a SOUND.

+
apply-banded-bass-boost(s, lowp, highp, num-bands, num-boost, gain) [SAL]
+ +(apply-banded-bass-boost s lowp highp num-bands num-boost gain) [LISP]
Applies a boost to +low frequencies. Separates +input SOUND s into FIXNUM num-bands bands from a low frequency +of lowp to a high frequency of highp (these are FLONUMS that specify +steps, not Hz), and scales the lowest num-boost (a FIXNUM) bands by gain, +a FLONUM. The bands are summed to form the result, a SOUND.

+
apply-banded-treble-boost(s, lowp, highp, num-bands, num-boost, gain) [SAL]
+ +(apply-banded-treble-boost s lowp highp num-bands num-boost gain) [LISP]
Applies a boost to +high frequencies. Separates +input SOUND s into FIXNUM num-bands bands from a low frequency +of lowp to a high frequency of highp (these are FLONUMS that specify +steps, not Hz), and scales the highest num-boost (a FIXNUM) bands by gain, +a FLONUM. The bands are summed to form the result, a SOUND. +
+

+

Granular Synthesis

+Some granular synthesis functions are implemented in the gran.lsp library +file. There are many variations and control schemes one could adopt for granular +synthesis, so it is impossible to create a single universal granular synthesis +function. One of the advantages of Nyquist is the integration of control and +synthesis functions, and users are encouraged to build their own granular synthesis +functions incorporating their own control schemes. The gran.lsp file +includes many comments and is intended to be a useful starting point. Another +possibility is to construct a score with an event for each grain. Estimate a +few hundred bytes per score event (obviously, size depends on the number of +parameters) and avoid using all of your computer's memory. +

+

+
+sf-granulate(filename, grain-dur, grain-dev, ioi, ioi-dev, pitch-dev, +[file-start, file-end]) [SAL]
+ +(sf-granulate filename grain-dur grain-dev ioi ioi-dev pitch-dev [file-start file-end]) [LISP]
Granular synthesis using a sound file +named filename as the source for grains. Grains are extracted from +a sound file named by filename by stepping through the file in equal +increments. Each grain duration is the +sum of grain-dur and a random number from 0 to grain-dev. Grains are +then multiplied by a raised cosine smoothing window and resampled at a ratio +between 1.0 and pitch-dev. If pitch-dev is greater than one, grains are +stretched and the pitch (if any) goes down. If pitch-dev is less than one, +grains are shortened and the pitch goes up. Grains are then output +with an +inter-onset interval between successive grains (which may overlap) +determined by the sum of +ioi and a random number from 0 to ioi-dev. +The duration of the resulting sound is determined by +the stretch factor (not by the sound file). The number of grains is +the total sound duration (determined by the stretch factor) +divided by the mean inter-onset interval, +which is ioi + ioi-dev * 0.5. +The grains are taken from equally-spaced starting points in filename, +and depending on grain size and number, the grains may or may not overlap. +The output duration will simply be the sum of the inter-onset intervals +and the duration of the last grain. If ioi-dev is non-zero, the +output duration will vary, but the expected value of the duration is +the stretch factor. +To achieve a rich granular synthesis effect, it is often a good idea to +sum four or more copies of sf-granulate together. (See the gran-test +function in gran.lsp.) +
+

+

MIDI Utilities

+The midishow.lsp library has functions that can print the contents fo MIDI +files. This intended as a debugging aid. +

+

+
+midi-show-file(file-name) [SAL]
+ +(midi-show-file file-name) [LISP]
Print the contents of a MIDI file to the console.

+
midi-show(the-seq [, out-file]) [SAL]
+ +(midi-show the-seq [out-file]) [LISP]
Print the +contents of the sequence the-seq to the file out-file (whose default value +is the console.) +
+

+

Reverberation

+The reverb.lsp library implements artificial reverberation. +

+

+
+reverb(snd, +time) [SAL]
+ +(reverb snd time) [LISP]
Artificial reverberation applied to snd with a decay time of +time. +
+

+

DTMF Encoding

+ +The dtmf.lsp library implements DTMF encoding. DTMF is the +"touch tone" code used by telephones. +

+

+
+dtmf-tone(key, len, space) [SAL]
+ +(dtmf-tone key len space) [LISP]
Generate a +single DTMF tone. The key parameter is either a digit (a FIXNUM +from 0 through 9) or the atom STAR or POUND. The duration of +the done is given by len (a FLONUM) and the tone is followed by +silence of duration space (a FLONUM).

+
speed-dial(thelist) [SAL]
+ +(speed-dial thelist) [LISP]
Generates a sequence +of DTMF tones using the keys in thelist (a LIST of keys as +described above under dtmf-tone). The duration of each tone is 0.2 +seconds, and the space between tones is 0.1 second. Use stretch to +change the "dialing" speed. +
+

+

Dolby Surround(R), Stereo and Spatialization Effects

+The spatial.lsp library implements various functions for stereo +manipulation and spatialization. It also includes some functions for +Dolby Pro-Logic panning, which encodes left, right, center, and surround +channels into stereo. The stereo signal can then be played through +a Dolby decoder to drive a surround speaker array. This library has +a somewhat simplified encoder, so you should certainly test the +output. Consider using a high-end encoder for critical work. There +are a number of functions in spatial.lsp for testing. See the +source code for comments about these. +

+

+
+stereoize(snd) [SAL]
+ +(stereoize snd) [LISP]
Convert a mono sound, snd, to stereo. Four bands of +equalization and some delay are used to create a stereo effect.

+
widen(snd, amt) [SAL]
+ +(widen snd amt) [LISP]
Artificially +widen the stereo field in snd, a two-channel sound. The amount of widening +is amt, which varies from 0 (snd is unchanged) to 1 (maximum widening). +The amt can be a SOUND or a number.

+
span(snd, amt) [SAL]
+ +(span snd amt) [LISP]
Pan the virtual center channel of a stereo sound, snd, +by amt, where 0 pans all the way to the left, while 1 pans all the way +to the right. The amt can be a SOUND or a number.

+
swapchannels(snd) [SAL]
+ +(swapchannels snd) [LISP]
Swap left and right channels in snd, a stereo sound.

+
prologic(l, c, +r, s) [SAL]
+ +(prologic l c r s) [LISP]
Encode four monaural SOUNDs representing the front-left, +front-center, front-right, and rear channels, respectively. +The return value is a stereo sound, which is a Dolby-encoded mix of the +four input sounds.

+
pl-left(snd) [SAL]
+ +(pl-left snd) [LISP]
Produce a Dolby-encoded (stereo) +signal with snd, a SOUND, encoded as the front left channel.

+
pl-center(snd) [SAL]
+ +(pl-center snd) [LISP]
Produce a Dolby-encoded (stereo) +signal with snd, a SOUND, encoded as the front center channel.

+
pl-right(snd) [SAL]
+ +(pl-right snd) [LISP]
Produce a Dolby-encoded (stereo) +signal with snd, a SOUND, encoded as the front right channel.

+
pl-rear(snd) [SAL]
+ +(pl-rear snd) [LISP]
Produce a Dolby-encoded (stereo) +signal with snd, a SOUND, encoded as the rear, or surround, channel.

+
pl-pan2d(snd, x, y) [SAL]
+ +(pl-pan2d snd x y) [LISP]
Comparable to Nyquist's +existing pan function, pl-pan2d provides not only left-to-right +panning, but front-to-back panning as well. The function +accepts three parameters: snd is the (monophonic) input SOUND, +x is a left-to-right position, and y is a front-to-back position. +Both position parameters may be numbers or SOUNDs. An x value +of 0 means left, and 1 means right. Intermediate values map linearly +between these extremes. Similarly, a y value of 0 causes the sound +to play entirely through the front speakers(s), while 1 causes it to play +entirely through the rear. Intermediate values map linearly. +Note that, although there are usually two rear speakers in Pro-Logic systems, +they are both driven by the same signal. Therefore any sound that is +panned totally to the rear will be played over both rear speakers. For +example, it is not possible to play a sound exclusively through the +rear left speaker.

+
pl-position(snd, x, y, config) [SAL]
+ +(pl-position snd x y config) [LISP]
The +position function builds upon speaker panning to allow more abstract +placement of sounds. Like pl-pan2d, it accepts a (monaural) input +sound as well as left-to-right (x) and front-to-back (y) coordinates, +which may be FLONUMs or SOUNDs. A fourth parameter config +specifies the distance from listeners to the speakers (in meters). Current +settings assume this to be constant for all speakers, but this assumption +can be changed easily (see comments in the code for more detail). +There are several important differences between pl-position and +pl-pan2d. First, pl-position uses a Cartesian coordinate +system that allows x and y coordinates outside of the +range (0, 1). This model assumes a listener position of (0,0). Each speaker +has a predefined position as well. The input sound's position, +relative to the listener, is given by the vector (x,y).

+
pl-doppler(snd, +r) [SAL]
+ +(pl-doppler snd r) [LISP]
Pitch-shift moving sounds according to the equation: fr = +f0((c+vr)/c), where fr is the output frequency, +f0 is the emitted (source) +frequency, c is the speed of sound (assumed to be 344.31 m/s), and +vr is the speed at which the emitter approaches the receiver. (vr +is the first derivative of parameter r, the distance from the listener +in meters.

+

Drum Machine

+The drum machine software in demos/plight deserves further explanation. +to use the software, load the code by evaluating: +
+load "../demos/plight/drum.lsp"
+exec load-props-file(strcat(*plight-drum-path*, 
+                            "beats.props"))
+exec create-drum-patches()
+exec create-patterns()
+
+ +

+Drum sounds and patterns are specified in the beats.props file (or +whatever name you give to load-props-file). This file +contains two types of specifications. First, there are sound file specifications. +Sound files are located by a line of the form: +

+set sound-directory = "kit/"
+
+ +This gives the name of the sound file directory, relative to the + beats.props file. Then, for each sound file, there should be a line of +the form: +
+track.2.5 = big-tom-5.wav
+
+ +This says that on track 2, a velocity value of 5 means to play the sound file + big-tom-5.wav. (Tracks and velocity values are described below.) +The beats.props file contains specifications for all the sound files +in demos/plight/kit using 8 tracks. If you make your own specifications +file, tracks should be numbered consecutively from 1, and velocities should be +in the range of 1 to 9. +

+The second set of specifications is of beat patterns. A beat pattern is given +by a line in the following form: +

+beats.5 = 2--32--43-4-5---
+
+ +The number after beats is just a pattern number. Each pattern +is given a unique number. After the equal sign, the digits and dashes are +velocity values where a dash means "no sound." Beat patterns should be +numbered consecutively from 1. +

+Once data is loaded, there are several functions to access drum patterns and +create drum sounds (described below). The demos/plight/drums.lsp file +contains an example function plight-drum-example to play some drums. +There is also the file demos/plight/beats.props to serve as an +example of how to specify sound files and beat patterns. +

+

+
+drum(tracknum, patternnum, bpm) [SAL]
+ +(drum tracknum patternnum bpm) [LISP]
Create +a sound by playing drums sounds associated with track tracknum (a +FIXNUM) using pattern patternnum. The tempo is given by bpm in +beats per minute. Normally patterns are a sequence of sixteenth notes, so +the tempo is in sixteenth notes per minute. For example, +if patternnum is 10, +then use the pattern specified for beats.10. If the third character +of this pattern is 3 and tracknum is 5, then on the third beat, play +the soundfile assigned to track.5.3. This function returns a SOUND.

+
drum-loop(snd, duration, numtimes) [SAL]
+ +(drum-loop snd duration numtimes) [LISP]
Repeat the sound given by snd numtimes times. The repetitions occur at a time offset of duration, regardless of the actual duration of snd. A SOUND is returned.

+
length-of-beat(bpm) [SAL]
+ +(length-of-beat bpm) [LISP]
Given a tempo of +bpm, return the duration of the beat in seconds. Note that this software +has no real notion of beat. A "beat" is just the duration of each character +in the beat pattern strings. This function returns a FLONUM. +
+

+

Minimoog-inspired Synthesis

+The moog.lsp library gives the Nyquist user easy access to "classic" +synthesizer sounds through an emulation of the Minimoog Synthesizer. +Unlike modular Moogs that were very large, the Minimoog was the first +successful and commonly used portable synthesizer. The trademark filter attack +was unique and easily recognizable. The goal of this Nyquist instrument is not +only to provide the user with default sounds, but also to give control over +many of the "knobs" found on the Minimoog. In this implementation, these +parameters are controlled using keywords. The input to the moog +instrument is a user-defined sequence of notes, durations, and articulations +that simulate notes played on a keyboard. These are translated into +control voltages that drive multiple oscillators, similar to the Voltage +Controlled Oscillator or VCO found in the original analog Moog. +

+The basic functionality of the Minimoog has been implemented, including the +often-used "glide". The glide feature essentially low-pass filters the control +voltage sequence in order to create sweeps between notes. +Figure 21 is a simplified schematic of the data flow in the Moog. +The control lines have been omitted. +

+


+
+

+ +

+Figure 21: System diagram for Minimoog emulator. + +


+

+The most recognizable feature of the Minimoog is its resonant filter, a +Four-Pole Ladder Filter invented by Robert Moog. It is simply implemented +in a circuit with four transistors and provides an outstanding 24 dB/octave +rolloff. It is modeled here using the built-in Nyquist resonant filter. +One of the Moog filter features is a constant Q, or center frequency to +bandwidth ratio. This is implemented and the user can control the Q. +

+The user can control many parameters using keywords. Their default values, +acceptable ranges, and descriptions are shown below. The defaults were +obtained by experimenting with the official Minimoog software synthesizer +by Arturia. +

+

Oscillator Parameters

+range-osc1 (2)
+ +range-osc2 (1)
+ +range-osc3 (3)
+ +These parameters control the octave of each oscillator. A value of 1 +corresponds to the octave indicated by the input note. A value of 3 +is two octaves above the fundamental. The allowable range is 1 to 7. +

+detun2 (-.035861)
+ +detun3 (.0768)
+ +Detuning of two oscillators adds depth to the sound. A value of 1 corresponds +to an increase of a single semitone and a -1 corresponds to a decrease +in a semitone. The range is -1 to 1. +

+shape-osc1 (*saw-table*)
+ +shape-osc2 (*saw-table*)
+ +shape-osc3 (*saw-table*)
+ +Oscilators can use any wave shape. The default sawtooth waveform is +a built-in Nyquist variable. Other waveforms can be defined by the user. +

+volume-osc1 (1)
+ +volume-osc2 (1)
+ +volume-osc3 (1)
+ +These parameters control the relative volume of each oscillator. The range +is any FLONUM greater than or equal to zero. +

+

Noise Parameters

+noiselevel (.05)
+ +This parameter controls the relative volume of the noise source. The range +is any FLONUM greater than or equal to zero. + +

Filter Parameters

+filter-cutoff (768)
+ +The cutoff frequency of the filter in given in Hz. The range is zero +to 20,000 Hz. +

+Q (2)
+ +Q is the ratio of center frequency to bandwidth. It is held constant by +making the bandwidth a function of frequency. The range is any +FLONUM greater than zero. +

+contour (.65)
+ +Contour controls the range of the transient frequency sweep from a high +to low cutoff frequency when a note is played. The high frequency is +proportional to contour. A contour of 0 removes this sweep. The range +is 0 to 1. +

+filter-attack (.0001)
+ +Filter attack controls the attack time of the filter, i.e. the time to +reach the high cutoff frequency. The range is any FLONUM greater +than zero (seconds). +

+filter-decay (.5)
+ +Filter decay controls the decay time of the filter, i.e. the time of the +sweep from the high to low cutoff frequency. The range is +any FLONUM greater than zero (seconds). +

+filter-sustain (.8)
+ +Filter sustain controls the percentage of the filter cutoff frequency that +the filter settles on following the sweep. The range is 0 to 1. + +

Amplitude Parameters

+amp-attack (.01)
+ +This parameter controls the amplitude envelope attack time, i.e. the time to +reach maximum amplitude. The range is +any FLONUM greater than zero (seconds). +

+amp-decay (1)
+ +This parameter controls the amplitude envelope decay time, i.e. the time +between the maximum and sustain volumes. The range is +any FLONUM greater than zero (seconds). +

+amp-sustain (1)
+ +This parameter controls the amplitude envelope sustain volume, a fraction +of the maximum. The range is 0 to 1. +

+amp-release (0)
+ +This parameter controls the amplitude envelope release time, i.e. the time +it takes between the sustain volume and 0 once the note ends. +The duration controls the overall length of the sound. The range of amp-release is any FLONUM greater than zero (seconds). +

+

Other Parameters

+glide (0)
+ +Glide controls the low-pass filter on the control voltages. This models the +glide knob on a Minimoog. A higher value corresponds to a lower cutoff +frequency and hence a longer "glide" between notes. A value of 0 +corresponds to no glide. The range is zero to 10. +

+

Input Format

+A single note or a series of notes can be input to the Moog instrument +by defining a list with the following format: +
+list(list(frequency, duration, articulation), ... )
+
+ +where frequency is a FLONUM in steps, duration is the duration +of each note in seconds (regardless of the release time of the amplifier), +and articulation is a percentage of the duration that a sound will be +played, representing the amount of time that a key is pressed. The filter +and amplitude envelopes are only triggered if a note is played when +the articulation of the previous note is less than 1, or a key is not down at +the same time. This Moog instrument is a monophonic instrument, so only +one note can sound at a time. The release section of the amplifier is +triggered when the articulation is less than 1 at the time +(duration * articulation). +

+

Sample Code/Sounds

Sound 1 (default parameters): +
+ +set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99}
+ + {29 .5 .99} {31 2 1}}
+ +play moog(s)
+ +
+
+

+Sound 2 (articulation, with amplitude release): +

+ +set s = {{24 .5 .5} {26 .5 1} {28 .5 .25} {29 .5 1} {31 1 .8}}
+ +play moog(s, amp-release: .2)
+ +
+
+

+Sound 3 (glide): +

+ +set s = {{24 .5 .5} {38 .5 1} {40 .5 .25}
+ + {53 .5 1} {55 2 1} {31 2 .8} {36 2 .8}}
+ +play moog(s, amp-release: .2, glide: .5)
+ +
+
+

+Sound 4 (keyword parameters): Filter attack and decay are purposely +longer than notes being played with articulation equal to 1. +

+ +set s = {{20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1}
+ + {20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1}}
+ +play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*,
+ + filter-attack: 2, filter-decay: 2,
+ + filter-cutoff: 300, contour: .8, glide: .2, Q: 8)
+ +
+
+

+Sound 5: This example illustrates the ability to completely define a new +synthesizer with different parameters creating a drastically different +sound. Sine waves are used for wavetables. There is a high value for glide. +

+ +define function my-moog(freq)
+ + return moog(freq,
+ + range-osc1: 3, range-osc2: 2, range-osc3: 4,
+ + detun2: -.043155, detun3: .015016,
+ + noiselevel: 0,
+ + filter-cutoff: 400, Q: .1, contour: .0000001,
+ + filter-attack: 0, filter-decay: .01, filter-sustain: 1,
+ + shape-osc1: *sine-table*, shape-osc2: *sine-table*,
+ + shape-osc3: *sine-table*, volume-osc1: 1, volume-osc2: 1,
+ + volume-osc3: .1, amp-attack: .1, amp-decay: 0,
+ + amp-sustain: 1, amp-release: .3, glide: 2) +

+set s = {{80 .4 .75} {28 .2 1} {70 .5 1} {38 1 .5}}
+ +play my-moog(s)
+ +
+

+

+Sound 6: This example has another variation on the default + parameters. +

+ +set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99}
+ + {29 .5 .99} {31 2 1}}
+ +play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*,
+ + filter-attack: .5, contour: .5)
+ +
+
+

+ + +


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part16.html b/doc/part16.html new file mode 100644 index 0000000..1c1f732 --- /dev/null +++ b/doc/part16.html @@ -0,0 +1,422 @@ +Previous Section | Next Section | Table of Contents | Index | Title Page +
+Appendix 1: Extending Nyquist +

Appendix 1: Extending Nyquist

+ +WARNING: +Nyquist sound functions look almost like a human wrote them; they even have +a fair number of comments for human readers. Don't be fooled: virtually all +Nyquist functions are written by a special translator. If you try to write +a new function by hand, you will probably not succeed, and even if you do, +you will waste a great deal of time. (End of Warning.) +

+

Translating Descriptions to C Code

The translator code used to extend Nyquist resides in the trnsrc +directory. This directory also contains a special init.lsp, so if +you start XLisp or Nyquist in this directory, it will automatically read +init.lsp, which in turn will load the translator code (which resides +in several files). +

+Also in the trnsrc directory are a number of .alg files, which +contain the source code for the translator (more on these will follow), and +a number of corresponding .h and .c files. +

+To translate a .alg file to .c and .h files, you start +XLisp or Nyquist in the trnsrc directory and type +

+(translate "prod")
+
+ +where "prod" should really be replaced by the filename (without a +suffix) you want to translate. Be sure you have a saved, working copy of +Nyquist or Xlisp before you recompile! +

+Note: On the Macintosh, just run Nyquist out of the runtime directory and then use the Load menu command to load init.lsp from the trnsrc directory. This will load the translation code and change Nyquist's current directory to trnsrc so that commands like (translate "prod") will work. +

+

Rebuilding Nyquist

After generating prod.c and +prod.h, you need to recompile Nyquist. For Unix systems, you will +want to generate a new Makefile. Modify transfiles.lsp in your main +Nyquist directory, run Xlisp or Nyquist and load makefile.lsp. +Follow the instructions to set your machine type, etc., and +execute (makesrc) and (makefile). +

+

Accessing the New Function

The new Lisp function will generally be named with a snd- prefix, +e.g. snd-prod. You can test this by running Nyquist. Debugging is +usually a combination of calling the code from within the interpreter, +reading the generated code when things go wrong, and using a C debugger to +step through the inner loop of the generated code. An approach I like is to +set the default sample rate to 10 hertz. Then, a one-second sound has only +10 samples, which are easy to print and study on a text console. +

+For some functions, +you must write some Lisp code to impose +ordinary Nyquist behaviors such as stretching and time shifting. A +good approach is to find some structurally similar functions and see how +they are implemented. Most of the Lisp code for Nyquist is in +nyquist.lsp. +

+Finally, do not forget to write up some documentation. Also, contributions are +welcome. Send your .alg file, documentation, Lisp support +functions for nyquist.lsp, and examples or test programs +to rbd@cs.cmu.edu. I will either put them in the next release or +make them available at a public ftp site. +

+

Why Translation?

+Many of the Nyquist signal processing operations are similar in form, but +they differ in details. This code is complicated by many factors: Nyquist +uses lazy evaluation, so the operator must check to see that input samples +are available before trying to access them. Nyquist signals can have +different sample rates, different block sizes, different block boundaries, +and different start times, all of which must be taken into account. The +number of software tests is enormous. (This may sound like a lot of +overhead, but the overhead is amortized over many iterations of the inner +loop. Of course setting up the inner loop to run efficiently is one more +programming task.) +

+The main idea behind the translation is that all of the checks and setup +code are similar and relatively easy to generate automatically. Programmers +often use macros for this sort of task, but the C macro processor is too +limited for the complex translation required here. To tell the translator +how to generate code, you write .alg files, which provide many +details about the operation in a declarative style. For example, the code +generator can make some optimizations if you declare that two input signals +are commutative (they can be exchanged with one another). The main part of +the .alg file is the inner loop which is the heart of the signal +processing code. +

+

Writing a .alg File

+WARNING: Translation relies heavily on string substitution, which +is fragile. In particular, variables with names that are substrings of +other variables will cause problems. For example if you declare STATE +variables "phase" and "iphase", then the translator will globally +substitute "phase_reg" for "phase", converting "phase" to "phase_reg" +and iphase" to "iphase_reg". Then it will substitute "iphase_reg" for +iphase" which will convert the existing "iphase_reg" to +"iphase_reg_reg". This will be confusing and will not compile. +(End of WARNING) +

+To give you some idea how functions are specified, here is the +specification for snd-prod, which generates over 250 lines of C code: +

+(PROD-ALG
+  (NAME "prod")
+  (ARGUMENTS ("sound_type" "s1") ("sound_type" "s2"))
+  (START (MAX s1 s2))
+  (COMMUTATIVE (s1 s2))
+  (INNER-LOOP "output = s1 * s2")
+  (LINEAR s1 s2)
+  (TERMINATE (MIN s1 s2))
+  (LOGICAL-STOP (MIN s1 s2))
+)
+
+ +A .alg file is always of the form: +
+(name
+  (attribute value)
+  (attribute value)
+  ...
+)
+
+ +There should be just one of these algorithms descriptions per file. +The name field is arbitrary: it is a Lisp symbol whose property list is +used to save the following attribute/value pairs. There are many +attributes described below. For more examples, see the .alg files in +the trnsrc directory. +

+Understanding what the attributes do is not +easy, so here are three recommendations for implementors. First, if there is +an existing Nyquist operator that is structurally similar to something you +want to implement, make a copy of the corresponding .alg file and +work from there. In some cases, you can merely rename the parameters and +substitute a new inner loop. Second, read the generated code, especially +the generated inner loop. It may not all make sense, but sometimes you can +spot obvious errors and work your way back to the error in the .alg +file. Third, if you know where something bad is generated, see if you can +find where the code is generated. (The code generator files are listed in +init.lsp.) This code is poorly written and poorly documented, but in +some cases it is fairly straightforward to determine what attribute in the +.alg file is responsible for the erroneous output. +

+

Attributes

+Here are the attributes used for code generation. Attributes and values may +be specified in any order. +
+
+(NAME "string")
specifies a base name for many identifiers. In +particular, the generated filenames will be string.c and +string.h, and the XLisp function generated will be +snd-string.

+
(ARGUMENTS arglist)
describes the arguments to be passed from +XLisp. Arglist has the form: (type1 name1) (type2 +name2) ..., where type and name are strings in double quotes, +e.g. ("sound_type" "s") specifies a SOUND parameter named s. Note that arglist is not surrounded by parentheses. As seen +in this example, the type names and parameter names are C identifiers. Since +the parameters are passed in from XLisp, they must be chosen from a +restricted set. Valid type names are: "sound_type", "rate_type", "double", +"long", "string", and "LVAL".

+
(STATE statelist)
describes additional state (variables) needed +to perform the computation. A statelist is similar to an arglist +(see ARGUMENTS above), and has the form: (type1 name1 +init1 [TEMP]) (type2 name2 init2 [TEMP]) .... +The types and names are as +in arglist, and the "inits" are double-quoted initial values. Initial +values may be any C expression. State is initialized in the order implied by +statelist when the operation is first called from XLisp. If TEMP +is omitted the state is preserved in a structure until the sound computation +completes. Otherwise, the state variable only exists at state +initialization time.

+
(INNER-LOOP innerloop-code)
describes the inner loop, written as +C code. The innerloop-code is in double quotes, and may extend over +multiple lines. To make generated code extra-beautiful, prefix each line of +innerloop-code with 12 spaces. Temporary variables should not +be declared at the beginning of innerloop-code. Use the +INNER-LOOP-LOCALS attribute instead. Within innerloop-code, +each ARGUMENT of type sound_type must be referenced exactly one +time. If you need to use a signal value twice, assign it once to a +temporary and use the temporary twice. The inner loop must also assign +one time to the psuedo-variable output. The model here is that the +name of a sound argument denotes the value of the corresponding signal at +the current output sample time. The inner loop code will be called once for +each output sample. In practice, the code generator will substitute some +expression for each signal name. For example, +prod.alg specifies +
(INNER-LOOP "output = s1 * s2")
+(s1 and s2 are ARGUMENTS.) This expands to the +following inner loop in prod.c: +
*out_ptr_reg++ = *s1_ptr_reg++ * *s2_ptr_reg++;
+In cases where arguments have different sample rates, sample interpolation +is in-lined, and the expressions can get very complex. The translator is +currently very simple-minded about substituting access code in the place of +parameter names, and this is a frequent source of bugs. Simple string +substitution is performed, so you must not use a parameter or state name +that is a substring of another. For example, if two sound parameters were +named s and s2, the translator might substitute for "s" in two +places rather than one. If this problem occurs, you will almost certainly +get a C compiler syntax error. The fix is to use "more unique" parameter +and state variable names.

+
(INNER-LOOP-LOCALS "innerloop-code")
The innerloop-code +contains C declarations of local variables set and referenced in the inner +loop.

+
(SAMPLE-RATE "expr")
specifies the output sample rate; expr +can be any C expression, including a parameter from the ARGUMENTS +list. You can also write (SAMPLE-RATE (MAX name1 name2 ...)) +where names are unquoted names of arguments.

+
(SUPPORT-HEADER "c-code")
specifies arbitrary C code to be +inserted in the generated .h file. The code typically contains +auxiliarly function declarations and definitions of constants.

+
(SUPPORT-FUNCTIONS "c-code")
specifies arbitrary C code to be +inserted in the generated .c file. The code typically contains +auxiliarly functions and definitions of constants.

+
(FINALIZATION "c-code")
specifies code to execute when the sound +has been fully computed and the state variables are about to be +decallocated. This is the place to deallocate buffer memory, etc.

+
(CONSTANT "name1" "name2" ...)
specifies state variables that +do not change value in the inner loop. The values of state +variables are loaded into registers before entering the inner loop so that +access will be fast within the loop. On exiting the inner loop, the final +register values are preserved in a "suspension" structure. If state +values do not change in the inner loop, this CONSTANT declaration can +eliminate the overhead of storing these registers.

+
(START spec)
specifies when the output sound should start (a +sound is zero and no processing is done before the start time). The spec +can take several forms: (MIN name1 name2 ...) means the start +time is the minimum of the start times of input signals name1, +name2, .... Note that these names are not quoted.

+
(TERMINATE spec)
specifies when the output +sound terminates (a sound is +zero after this termination time and no more samples are computed). The +spec can take several forms: (MIN name1 name2 ...) means +the terminate time is the minimum of the terminate times of input arguments +name1, name2, .... Note that these names are not quoted. To +terminate at the time of a single argument s1, specify (MIN +s1). To terminate after a specific duration, use (AFTER "c-expr"), +where c-expr is a C variable or expression. To terminate at a +particular time, use (AT "c-expr"). spec may also be +COMPUTED, which means to use the maximum sample rate of any input +signal.

+
(LOGICAL-STOP spec)
specifies the logical stop time of the output +sound. This spec is just like the one for TERMINATE. If no +LOGICAL-STOP attribute is present, the logical stop will coincide +with the terminate time.

+
(ALWAYS-SCALE name1 name2 ...)
says that the named sound +arguments (not in quotes) should always be multiplied by a scale factor. +This is a space-time tradeoff. When Nyquist sounds are scaled, the scale +factor is merely stored in a structure. It is the responsibility of +the user of the samples to actually scale them (unless the scale factor is +exactly 1.0). The default is to generate code with and without scaling and +to select the appropriate code at run time. If there are N signal inputs, +this will generate 2^(N) versions of the code. To avoid this code +explosion, use the ALWAYS-SCALE attribute.

+
(INLINE-INTERPOLATION T)
specifies that sample rate interpolation +should be performed in-line in the inner loop. There are two forms of sample +rate interpolation. One is intended for use when the rate change is large +and many points will be interpolated. This form uses a divide instruction +and some setup at the low sample rate, +but the inner loop overhead is just an add. The +other form, intended for less drastic sample rate changes, performs +interpolation with 2 multiplies and several adds per sample at the high +sample rate. Nyquist generates various inner loops and selects the +appropriate one at run-time. If INLINE-INTERPOLATION is not set, +then much less code is generated and interpolation is performed as necessary +by instantiating a separate signal processing operation.

+
(STEP-FUNCTION name1 name2 ...)
Normally all argument +signals are +linearly interpolated to the output sample rate. The linear interpolation +can be turned off with this attribute. This is used, for example, in Nyquist +variable filters so that filter coefficients are computed at low sample +rates. In fact, this attribute was added for the special case of filters.

+
(DEPENDS spec1 spec2 ...)
Specifies dependencies. This +attribute was also introduced to handle the case of filter coefficients (but +may have other applications.) Use it when a state variable is a function of +a potentially low-sample-rate input where the input is in the +STEP-FUNCTION list. Consider a filter coefficient that depends upon +an input signal such as bandwidth. In this case, you want to compute the +filter coefficient only when the input signal changes rather than every +output sample, since output may occur at a much higher sample rate. A +spec is of the form +
("name" "arg" "expr" [TEMP "type"])
+which is interpreted as follows: name depends upon arg; when arg +changes, recompute expr and assign it to name. The name must be +declared as a STATE variable unless TEMP is present, in which +case name is not preserved and is used only to compute other state. +Variables are updated in the order of the DEPENDS list.

+
(FORCE-INTO-REGISTER name1 name2 ...)
causes name1, +name2, ... to be loaded into registers before entering the inner loop. +If the inner loop references a state variable or argument, this happens +automatically. Use this attribute only if references are "hidden" in a +#define'd macro or referenced in a DEPENDS specification.

+
(NOT-REGISTER name1 name2 ...)
specifies state and arguments +that should not be loaded into registers before entering an inner loop. +This is sometimes an optimization for infrequently accessed state.

+
(NOT-IN-INNER-LOOP "name1" "name2" ...)
says that certain +arguments are not used in the inner loop. Nyquist assumes all arguments +are used in the inner loop, so specify them here if not. For example, +tables are passed into functions as sounds, but these sounds are not read +sample-by-sample in the inner loop, so they should be listed here.

+
(MAINTAIN ("name1" "expr1") ("name2" "expr2") ... +)
Sometimes the IBM XLC compiler generates better loop code if a variable +referenced in the loop is not referenced outside of the loop after the loop +exit. Technically, optimization is better when variables are dead upon loop +exit. Sometimes, there is an efficient way to compute the final value of a +state variable without actually referencing it, in which case the variable +and the computation method are given as a pair in the MAINTAIN +attribute. This suppresses a store of the value of the named variable, +making it a dead variable. Where the store would have been, the expression +is computed and assigned to the named variable. See partial.alg for +an example. This optimization is never necessary and is only for +fine-tuning.

+
(LINEAR name1 name2 ...)
specifies that named arguments +(without quotes) are linear with respect to the output. What this +really means is that it is numerically OK to eliminate a scale factor from +the named argument and store it in the output sound descriptor, avoiding a +potential multiply in this inner loop. For example, both arguments to +snd-prod (signal multiplication) are "linear." The inner loop has +a single multiplication operator to multiply samples vs. a potential 3 +multiplies if each sample were also scaled. To handle scale factors on the +input signals, the scale factors are automatically multiplied and the +product becomes the scale factor of the resulting output. (This effectively +"passes the buck" to some other, or perhaps more than one, signal +processing function, which is not always optimal. On the other hand, it +works great if you multiply a number of scaled signals together: all the +scale factors are ultimately handled with a single multiply.)

+
(INTERNAL-SCALING name1 name2 ...)
indicates that scaling is +handled in code that is hidden from the code generator for name1, +name2, ..., which are sound arguments. Although it is the responsibility +of the reader of samples to apply any given scale factor, sometimes scaling +can be had for free. For example, the snd-recip operation computes +the reciprocal of the input samples by peforming a division. The simple +approach would be to specify an inner loop of output = 1.0/s1, where +s1 is the input. With scaling, this would generate an inner loop +something like this: +
*output++ = 1.0 / (s1_scale_factor * *s1++);
+but a much better approach would be the following: +
*output++ = my_scale_factor / *s1++
+where my_scale_factor is initialized to 1.0 / s1->scale. +Working backward from the desired inner loop to the .alg inner loop +specification, a first attempt might be to specify: +
(INNER-LOOP "output = my_scale_factor / s1")
+but this will generate the following: +
*output++=my_scale_factor/(s1_scale_factor * *s1++);
+Since the code generator does not know that scaling is handled elsewhere, +the scaling is done twice! The solution is to put s1 in the +INTERNAL-SCALING list, which essentially means "I've already +incorporated scaling into the algorithm, so suppress the multiplication by a +scale factor."

+
(COMMUTATIVE (name1 name2 ...))
specifies that the results +will not be affected by interchanging any of the listed arguments. When +arguments are commutative, Nyquist rearranges them at run-time into +decreasing order of sample rates. If interpolation is in-line, this can +dramatically reduce the amount of code generated to handle all the different +cases. The prime example is prod.alg.

+
(TYPE-CHECK "code")
specifies checking code to be inserted after +argument type checking at initialization time. See downproto.alg for +an example where a check is made to guarantee that the output sample rate is +not greater than the input sample rate. Otherwise an error is raised.

+

Generated Names

+The resulting .c file defines a number of procedures. The procedures +that do actual sample computation are named something like +name_interp-spec_FETCH, where name is the NAME +attribute from the .alg file, and interp-spec is an interpolation +specification composed of a string of the following letters: n, s, i, and r. +One letter corresponds to each sound argument, indicating no interpolation +(r), scaling only (s), ordinary linear interpolation with scaling (i), and +ramp (incremental) interpolation with scaling (r). The code generator +determines all the combinations of n, s, i, and r that are necessary and +generates a separate fetch function for each. +

+Another function is name_toss_fetch, which is called when sounds +are not time-aligned and some initial samples must be discarded from one or +more inputs. +

+The function that creates a sound is snd_make_name. This is +where state allocation and initialization takes place. The proper fetch +function is selected based on the sample rates and scale factors of the +sound arguments, and a sound_type is returned. +

+Since Nyquist is a functional language, sound operations are not normally allowed to +modify their arguments through side effects, but even reading samples from a +sound_type causes side effects. To hide these from the Nyquist +programmer, sound_type arguments are first copied (this only copies a small structure. The samples themselves are on a shared list). The function +snd_name performs the necessary copies and calls +snd_make_name. It is the snd_name function that is +called by XLisp. The XLisp name for the function is SND-NAME. +Notice that the underscore in C is converted to a dash in XLisp. Also, +XLisp converts identifiers to upper case when they are read, so normally, +you would type snd-name to call the function. +

+

Scalar Arguments

+If you want the option of passing either a number (scalar) or a signal as +one of the arguments, you have two choices, neither of which is automated. +Choice 1 is to coerce the constant into a signal from within XLisp. The +naming convention would be to DEFUN a new function named +NAME or S-NAME for ordinary use. The NAME function tests +the arguments using XLisp functions such as TYPE-OF, NUMBERP, +and SOUNDP. Any number is converted to a SOUND, e.g. using +CONST. Then SND-NAME is called with all sound arguments. +The disadvantage of this scheme is that scalars are expanded into a sample +stream, which is slower than having a special inner loop where the scalar +is simply kept in a register, avoiding loads, stores, and addressing +overhead. +

+Choice 2 is to generate a different sound operator for each case. The +naming convention here is to append a string of c's and v's, indicating +constant (scalar) or variable (signal) inputs. For example, the +reson operator comes in four variations: reson, +resoncv, resonvc, and resonvv. The resonvc +version implements a resonating filter with a variable center frequency (a +sound type) and a constant bandwidth (a FLONUM). The RESON +function in Nyquist is an ordinary Lisp function that checks types and calls +one of SND-RESON, SND-RESONCV, SND-RESONVC, or +SND-RESONVV. +

+Since each of these SND- functions performs further selection of +implementation based on sample rates and the need for scaling, there are 25 +different functions for computing RESON! So far, however, Nyquist is +smaller than Common Lisp and it's about half the size of Microsoft Word. +Hopefully, exponential growth in memory density will outpace linear (as a +function of programming effort) growth of Nyquist. +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part17.html b/doc/part17.html new file mode 100644 index 0000000..c4fba1a --- /dev/null +++ b/doc/part17.html @@ -0,0 +1,71 @@ +Previous Section | Next Section | Table of Contents | Index | Title Page +
+Appendix 2: Open Sound Control and Nyquist +

Appendix 2: Open Sound Control and Nyquist

+ +Open Sound Control (OSC) is a simple protocol for communicating music +control parameters between software applications and across +networks. For more information, see http://www.cnmat.berkeley.edu/OpenSoundControl/. The +Nyquist implementation of Open Sound Control is simple: an array of +floats can be set by OSC messages and read by Nyquist functions. That +is about all there is to it. +

+Note: Open Sound Control must be enabled by calling +osc-enable(t). If this fails under Windows, see the +installation instructions in sys/win/README.txt regarding +SystemRoot. +

+To control something in (near) real-time, you need to access a slider value as if it a signal, or more properly, a Nyquist SOUND type. The function snd-slider, described in Section "Creating Sounds", takes a slider number and returns a SOUND type representing the current value of the slider. To fully understand this function, you need to know something about how Nyquist is actually computing sounds. +

+Sounds are normally computed on demand. So the result returned by snd-slider does not immediately compute any samples. Samples are only computed when something tries to use this signal. At that time, the slider value is read. Normally, if the slider is used to control a sound, you will hear changes in the sound pretty soon after the slider value changes. However, one thing that can interfere with this is that SOUND samples are computed in blocks of about 1000 samples. When the slider value is read, the same value is used to fill a block of 1000 samples, so even if the sample rate is 44,100 Hz, the effective slider sample rate is 44,100/1000, or 44.1 Hz. If you give the slider a very low sample rate, say 1000, then slider value changes will only be noticed by Nyquist approximately once per second. For this reason, you should normally use the audio sample rate (typically 44,100 Hz) for the rate of the snd-slider output SOUND. (Yes, this is terribly wasteful to represent each slider value with 1000 samples, but Nyquist was not designed for low-latency computation, and this is an expedient work-around.) +

+In addition to reading sliders as continually changing SOUNDs, you can get the slider value as a Lisp FLONUM (a floating point number) using get-slider-value, described in Section "Creating Sounds". This might be useful if you are computing a sequence of many notes (or other sound events) and want to apply the current slider value to the whole note or sound event. +

+Note that if you store the value returned by snd-slider in a variable, you will capture the history of the slider changes. This will take a lot of memory, so be careful. +

+Suppose you write a simple expression such as (hzosc (mult 1000 (snd-slider 0 ...))) (or in SAL, hzosc(1000 * snd-slider(0 ...))) to control an oscillator frequency with a slider. How long does this sound last? The duration of hzosc is the duration of the frequency control, so what is the duration of a slider? To avoid infinitely long signals, you must specify a duration as one of the parameters of snd-slider. +

+You might be thinking, what if I just want to tell the slider when to stop? At present, you cannot do that, but in the future there should be a function that stops when its input goes to zero. Then, moving a slider to zero could end the signal (and if you multiplied a complex sound by one of these ending functions, everything in the sound would end and be garbage collected). +

+Another thing you might want to do with interactive control is start some sound. The trigger function computes an instance of a behavior each time an input SOUND goes from zero to greater-than-zero. This could be used, for example, to create a sequence of notes. +

+The snd-slider function has some parameters that may be unfamiliar. The second parameter, t0, is the starting time of the sound. This should normally be local-to-global(0), an expression that computes the instantiation time of the current expression. This will often be zero, but if you call snd-slider from inside a seq or seq-rep, the starting time may not be zero. +

+The srate parameter is the sample rate to return. This should normally be the audio sample rate you are working with, which is typically *default-sound-srate*. +

+

Sending Open Sound Control Messages

+A variety of programs support OSC. The only OSC message interpreted by Nyquist has an address of /slider, and two parameters: an integer slider number and a float value, nominally from 0.0 to 1.0. +

+Two small programs are included in the Nyquist distribution for sending OSC messages. (Both can be found in the same directory as the nyquist executable.) The first one, osc-test-client sends a sequence of messages that just cause slider 0 to ramp slowly up and down. If you run this on a command line, you can use "?" or "h" to get help information. There is an interactive mode that lets you send each OSC message by typing RETURN. +

+

The ser-to-osc Program

+The second program is ser-to-osc, a program that reads serial input (for example from a PIC-based microcontroller) and sends OSC messages. Run this command-line program from a shell (a terminal window under OS X or Linux; use the CMD program under Windows). You must name the serial input device on the command line, e.g. under OS X, you might run: +
+./ser-to-osc /dev/tty.usbserial-0000103D
+ +
+(Note that the program name is preceded by "./". This tells the shell exactly where to find the executable program in case the current directory is not on the search path for executable programs.) +Under Windows, you might run: +
+ser-to-osc com4
+ +
+(Note that you do not type "./" in front of a windows program.) +

+To use ser-to-osc, you will have to find the serial device. On the Macintosh and Linux, try the following: +

+ls /dev/*usb*
+ +
+This will list all serial devices with "usb" in their names. Probably, one will be a name similar to /dev/tty.usbserial-0000103D. The ser-to-osc program will echo data that it receives, so you should know if things are working correctly. +

+Under Windows, open Control Panel from the Start menu, and open the System control panel. Select the Hardware tab and click the Device Manager button. Look in the device list under Ports (COM & LPT). When you plug in your serial or USB device, you should see a new entry appear, e.g. COM4. This is the device name you need. +

+The format for the serial input is: any non-whitespace character(s), a slider number, a slider value, and a newline (control-j or ASCII 0x0A). These fields need to be separated by tabs or spaces. An optional carriage return (control-m or ASCII 0x0D) preceding the ASCII 0x0A is ignored. The slider number should be in decimal, and theh slider value is a decimal number from 0 to 255. This is scaled to the range 0.0 to 1.0 (so an input of 255 translates to 1.0). +

+There is a simple test program in demos/osc-test.lsp you can run to try out control with Open Sound Control. There are two examples in that file. One uses snd-slider to control the frequency of an oscillator. The other uses get-slider-value to control the pitch of grains in a granular synthesis process. +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part18.html b/doc/part18.html new file mode 100644 index 0000000..83dcfad --- /dev/null +++ b/doc/part18.html @@ -0,0 +1,238 @@ +Previous Section | Next Section | Table of Contents | Index | Title Page +
+Appendix 3: Intgen +

Appendix 3: Intgen

+ + +This documentation describes Intgen, a program for generating XLISP to C +interfaces. Intgen works by scanning .h files with special comments in +them. Intgen builds stubs that implement XLISP SUBR's. When the SUBR is +called, arguments are type-checked and passed to the C routine declared in +the .h file. Results are converted into the appropriate XLISP type and +returned to the calling XLISP function. Intgen lets you add C functions +into the XLISP environment with very little effort. +

+The interface generator will take as command-line input: +

    +
  • +the name of the .c file to generate (do not include the .c extension; e.g. write +xlexten, not xlexten.c); +
  • a list of .h files. +
+Alternatively, the command line may specify a command file from which to read file names. The command file name should be preceded by "@", for example: +
+intgen @sndfns.cl
+
+ +reads sndfns.cl to get the command-line input. Only one level of indirection is allowed. +

+The output is: +

    +
  • +a single .c file with one SUBR defined for each designated +routine in a .h file. +
  • a .h file that declares each new C routine. E.g. if the .c file is named xlexten.c, this file will be named xlextendefs.h; +
  • a .h file that extends the SUBR table used by Xlisp. E.g. if the .c file is named xlexten.c, then this file is named xlextenptrs.h; +
  • a .lsp file with lisp initialization expressions copied from the +.h +files. This file is only generated if at least one initialization expression is encountered. +
+

+For example, the command line +

+intgen seint ~setypes.h access.h
+
+ +generates the file seint.c, using declarations in setypes.h +and access.h. Normally, the .h files are included by the +generated file using #include commands. A ~ before a file +means do not include the .h file. (This may be useful if you extend +xlisp.h, which will be included anyway). Also generated will be +setintdefs.h and seintptrs.h. +

+

Extending Xlisp

+Any number of .h files may be named on the command line to Intgen, +and Intgen will make a single .c file with interface routines for all +of the .h files. On the other hand, it is not necessary to put all +of the extensions to Xlisp into a single interface file. For example, you +can run Intgen once to build interfaces to window manager routines, and +again to build interfaces to a new data type. Both interfaces can be linked +into Xlisp. +

+To use the generated files, you must compile the .c files and link +them with all of the standard Xlisp object files. In addition, you must +edit the file localdefs.h to contain an #include for each +*defs.h file, and edit the file localptrs.h to include each +*ptrs.h file. For example, suppose you run Intgen to build +soundint.c, fugueint.c, and tableint.c. You would then +edit localdefs.h to contain the following: +

+#include "soundintdefs.h"
+#include "fugueintdefs.h"
+#include "tableintdefs.h"
+
+ +and edit localptrs.h to contain: +
+#include "soundintptrs.h"
+#include "fugueintptrs.h"
+#include "tableintptrs.h"
+
+ +These localdefs.h and localptrs.h files are in turn included +by xlftab.c which is where Xlisp builds a table of SUBRs. +

+To summarize, building an interface requires just a few simple steps: +

    +
  • +Write C code to be called by Xlisp interface routines. This C code does the +real work, and in most cases is completely independent of Xlisp. +
  • Add comments to .h files to tell Intgen which routines to build +interfaces to, and to specify the types of the arguments. +
  • Run Intgen to build interface routines. +
  • Edit localptrs.h and localdefs.h to include generated +.h files. +
  • Compile and link Xlisp, including the new C code. +
+

+

Header file format

Each routine to be interfaced with Xlisp must be declared as +follows: +
+type-name routine-name(); /* LISP: (func-name type1 type2 ...) */
+
+ +The comment may be on the line following the declaration, but the +declaration and the comment must each be on no more than one line. +The characters LISP: at the beginning of the comment mark routines +to put in the interface. The comment also gives the +type and number of arguments. The function, when accessed from lisp will +be known as func-name, which need not bear any relationship to +routine-name. By convention, underscores in the C routine-name +should be converted to dashes in func-name, and func-name should be in +all capitals. None of this is enforced or automated though. +

+Legal type_names are: +

+
+LVAL
returns an Xlisp datum.

+
atom_type
equivalent to LVAL, but the result is expected to +be an atom.

+
value_type
a value as used in Dannenberg's score editor.

+
event_type
an event as used in Dannenberg's score editor.

+
int
interface will convert int to Xlisp FIXNUM.

+
boolean
interface will convert int to T or nil.

+
float or double
interface converts to FLONUM.

+
char * or string or string_type
interface converts to STRING. The result string will be copied into the XLISP heap.

+
void
interface will return nil. +
+

+It is easy to extend this list. Any unrecognized type will +be coerced to an int and then returned as a FIXNUM, and a warning will be +issued. +

+The "*" after char must be followed by routine-name with +no intervening space. +

+Parameter types may be any of the following: +

+
+FIXNUM
C routine expects an int.

+
FLONUM or FLOAT
C routine expects a double.

+
STRING
C routine expects char *, the string is not copied.

+
VALUE
C routine expects a value_type. (Not applicable to Fugue.)

+
EVENT
C routine expects an event_type. (Not applicable to Fugue.)

+
ANY
C routine expects LVAL.

+
ATOM
C routine expects LVAL which is a lisp atom.

+
FILE
C routine expects FILE *.

+
SOUND
C routine expects a SoundPtr.

+
+Any of these may be followed by "*": FIXNUM*, FLONUM*, STRING*, ANY*, FILE*, +indicating C routine expects int *, double *, char **, LVAL *, or FILE ** . +This is basically a mechanism for returning more than one value, not +a mechanism for clobbering XLisp values. In this spirit, the interface +copies the value (an int, double, char *, LVAL, or FILE *) to a local variable +and passes the address of that variable to the C routine. On return, +a list of resulting "*" parameters is constructed and bound to the +global XLisp symbol *RSLT*
. (Strings are copied.) If the C routine is void, then the result list is also returned by the corresponding XLisp function. +

+Note 1: this does not support C routines like strcpy that modify strings, +because the C routine gets a pointer to the string in the XLisp heap. +However, you can always add an intermediate routine that allocates +space and then calls strcpy, or whatever. +

+Note 2: it follows that a new XLisp STRING will be created for each STRING* parameter. +

+Note 3: putting results on a (global!) symbol seems a bit unstructured, but note that one could write a multiple-value binding macro that hides this ugliness from the user if desired. In practice, I find that pulling the extra result values from *RSLT* when needed is perfectly acceptable. +

+For parameters that are result values only, the character "^" may +be substituted for "*". In this case, the parameter is not to be passed in the XLisp calling site. +However, the address of an initialized +local variable of the given type is passed to the corresponding +C function, and the resulting value is passed back through *RSLT* as +ordinary result parameter as described above. +The local variables are initialized to zero or NULL. +

+

Using #define'd macros

+If a comment of the form: +
+/* LISP: type-name (routine-name-2 type-1 type-2 ...) */
+
+ +appears on a line by itself and there was a #define on the previous +line, then the preceding #define is treated as a C routine, e.g. +
+#define leftshift(val, count) ((val) << (count))
+/* LISP: int (LOGSHIFT INT INT) */
+
+ +will implement the LeLisp function LOGSHIFT. +

+The type-name following "LISP:" should have no spaces, e.g. use ANY*, not +ANY *. +

+

Lisp Include Files

+Include files often define constants that we would like to have around +in the Lisp world, but which are easier to initialize just by loading +a text file. Therefore, a comment of the form: +
+/* LISP-SRC: (any lisp expression) */
+
+ +will cause Intgen to open a file name.lsp and append +
+(any lisp expression)
+
+ +to name.lsp, where name is the interface name passed on the command line. If none of the include files examined have comments of +this form, then no name.lsp file is generated. +Note: the LISP-SRC comment must be on a new line. +

+

Example

+This file was used for testing Intgen. It uses a trick (ok, it's a hack) to interface +to a standard library macro (tolower). Since tolower is already +defined, the macro ToLower is defined just to give Intgen a name +to call. Two other routines, strlen and tough, are interfaced as +well. +
+/* igtest.h -- test interface for intgen */
+

+#define ToLower(c) tolower(c) +/* LISP: int (TOLOWER FIXNUM) */ +

+int strlen(); /* LISP: (STRLEN STRING) */ +

+void tough(); + /* LISP: (TOUGH FIXNUM* FLONUM* STRING ANY FIXNUM) */ +

+ +

+

More Details

Intgen has some compiler switches to enable/disable the use of certain types, including +VALUE and EVENT types used by Dannenberg's score editing work, the SOUND type used by Fugue, and DEXT and SEXT types added for Dale Amon. +Enabling all of these is not likely to cause problems, +and the chances of an accidental use of these types getting through +the compiler and linker seems very small. + +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part19.html b/doc/part19.html new file mode 100644 index 0000000..9806485 --- /dev/null +++ b/doc/part19.html @@ -0,0 +1,2704 @@ +Previous Section | Next Section (Index) | Table of Contents | Title Page +
+Appendix 4: XLISP: An Object-oriented Lisp +

Appendix 4: XLISP: An Object-oriented Lisp

+ +
Version 2.0 +

+February 6, 1988 +

+by
+ +David Michael Betz
+ +127 Taylor Road
+ +Peterborough, NH 03458 +

+Copyright (c) 1988, by David Michael Betz
+ +All Rights Reserved
+ +Permission is granted for unrestricted non-commercial use
+ +

+ + + + + + +

Introduction

+ XLISP is an experimental programming language combining some of + the features of Common Lisp with an object-oriented extension + capability. It was implemented to allow experimentation with + object-oriented programming on small computers. +

+ Implementations of XLISP run on virtually every operating system. + XLISP is completely written in the programming language + C and is easily extended with user written built-in functions + and classes. It is available in source form to non-commercial + users. +

+ Many Common Lisp functions are built into XLISP. In addition, + XLISP defines the objects Object and Class as primitives. + Object is the only class that has no superclass and hence is + the root of the class hierarchy tree. Class is the class of + which all classes are instances (it is the only object that is + an instance of itself). +

+ This document is a brief description of XLISP. It assumes some + knowledge of LISP and some understanding of the concepts of + object-oriented programming. +

+ I recommend the book Lisp by Winston and Horn and published by + Addison Wesley for learning Lisp. The first edition of this + book is based on MacLisp and the second edition is based on + Common Lisp. +

+ You will probably also need a copy of Common Lisp: The + Language by Guy L. Steele, Jr., published by Digital Press to + use as a reference for some of the Common Lisp functions that + are described only briefly in this document. +

+

A Note From The Author

If you have any problems with XLISP, feel free to contact me [me being David Betz - RBD] for + help or advice. Please remember that since XLISP is available + in source form in a high level language, many users [e.g. that Dannenberg fellow - RBD] have been + making versions available on a variety of machines. If you call + to report a problem with a specific version, I may not be able + to help you if that version runs on a machine to which I don't + have access. Please have the version number of the version that + you are running readily accessible before calling me. +

+ If you find a bug in XLISP, first try to fix the bug yourself + using the source code provided. If you are successful in fixing + the bug, send the bug report along with the fix to me. If you + don't have access to a C compiler or are unable to fix a bug, + please send the bug report to me and I'll try to fix it. +

+ Any suggestions for improvements will be welcomed. Feel free to + extend the language in whatever way suits your needs. However, + PLEASE DO NOT RELEASE ENHANCED VERSIONS WITHOUT CHECKING WITH ME + FIRST!! I would like to be the clearing house for new features + added to XLISP. If you want to add features for your own + personal use, go ahead. But, if you want to distribute your + enhanced version, contact me first. Please remember that the + goal of XLISP is to provide a language to learn and experiment + with LISP and object-oriented programming on small computers. I + don't want it to get so big that it requires megabytes of memory + to run. +

+

XLISP Command Loop

When XLISP is started, it first tries to load the workspace + xlisp.wks from the current directory. If that file doesn't + exist, XLISP builds an initial workspace, empty except for the + built-in functions and symbols. +

+ Then XLISP attempts to load init.lsp from the current + directory. It then loads any files named as parameters on the + command line (after appending .lsp to their names). +

+ XLISP then issues the following prompt: +

+        >
+
+ + This indicates that XLISP is waiting for an expression to be + typed. +

+ When a complete expression has been entered, XLISP attempts to + evaluate that expression. If the expression evaluates + successfully, XLISP prints the result and then returns to the + initial prompt waiting for another expression to be typed. +

+

Special Characters

When XLISP is running from a console, some control characters invoke operations: +
    +
  • +Backspace and Delete characters erase the previous character on the input line (if any). +
  • Control-U erases the entire input line. +
  • Control-C executes the TOP-LEVEL function. +
  • Control-G executes the CLEAN-UP function. +
  • Control-P executes the CONTINUE function. +
  • Control-B stops execution and enters the break command loop. Execution can be continued by typing Control-P or (CONTINUE). +
  • Control-E turns on character echoing (Linux and Mac OS X only). +
  • Control-F turns off character echoing (Linux and Mac OS X only). +
  • Control-T evaluates the INFO function. +
+

+

Break Command Loop

When XLISP encounters an error while evaluating an expression, + it attempts to handle the error in the following way: +

+ If the symbol *breakenable* is + true, the message corresponding to the error is printed. If + the error is correctable, the correction message is printed. +

+ If the symbol *tracenable* is true, a trace back is printed. + The number of entries printed depends on the value of the symbol + *tracelimit*. If this symbol is set to something other than a + number, the entire trace back stack is printed. +

+ XLISP then enters a read/eval/print loop to allow the user to + examine the state of the interpreter in the context of the + error. This loop differs from the normal top-level + read/eval/print loop in that if the user invokes the function + continue, XLISP will continue from a correctable error. If + the user invokes the function clean-up, XLISP will abort the + break loop and return to the top level or the next lower + numbered break loop. When in a break loop, XLISP prefixes the + break level to the normal prompt. +

+ If the symbol *breakenable* is nil, XLISP looks for a + surrounding errset function. If one is found, XLISP examines + the value of the print flag. If this flag is true, the error + message is printed. In any case, XLISP causes the errset + function call to return nil. +

+ If there is no surrounding errset function, XLISP prints the + error message and returns to the top level. +

+

Data Types

There are several different data types available to XLISP + programmers. +

+

    +
  • +lists +
  • symbols +
  • strings +
  • integers +
  • characters +
  • floats +
  • objects +
  • arrays +
  • streams +
  • subrs (built-in functions) +
  • fsubrs (special forms) +
  • closures (user defined functions) +
+

+

The Evaluator

The process of evaluation in XLISP: +
    +
  • + Strings, integers, characters, floats, objects, arrays, streams, + subrs, fsubrs and closures evaluate to themselves. +
  • Symbols act as variables and are evaluated by retrieving the + value associated with their current binding. +
  • Lists are evaluated by examining the first element of the list + and then taking one of the following actions: +
      +
    • + If it is a symbol, the functional binding of the symbol is + retrieved. +
    • If it is a lambda expression, a closure is constructed for + the function described by the lambda expression. +
    • If it is a subr, fsubr or closure, it stands for itself. +
    • Any other value is an error. +
    + Then, the value produced by the previous step is examined: +
      +
    • + If it is a subr or closure, the remaining list elements are + evaluated and the subr or closure is called with these + evaluated expressions as arguments. +
    • If it is an fsubr, the fsubr is called using the remaining + list elements as arguments (unevaluated). +
    • If it is a macro, the macro is expanded using the remaining + list elements as arguments (unevaluated). The macro + expansion is then evaluated in place of the original macro + call. +
    +
+

+

Lexical Conventions

The following conventions must be followed when entering XLISP + programs: +

+ Comments in XLISP code begin with a semi-colon character and + continue to the end of the line. +

+ Symbol names in XLISP can consist of any sequence of non-blank + printable characters except the following: +

+                ( ) ' ` , " ;
+
+ + Uppercase and lowercase characters are not distinguished within + symbol names. All lowercase characters are mapped to uppercase + on input. +

+ Integer literals consist of a sequence of digits optionally + beginning with a + or -. The range of values an integer can + represent is limited by the size of a C long on the machine on + which XLISP is running. +

+ Floating point literals consist of a sequence of digits + optionally beginning with a + or - and including an embedded + decimal point. The range of values a floating point number can + represent is limited by the size of a C float (double on + machines with 32 bit addresses) on the machine on which XLISP is + running. +

+ Literal strings are sequences of characters surrounded by double + quotes. Within quoted strings the "\" character is used to + allow non-printable characters to be included. The codes + recognized are: +

    +
  • +\\ means the character "\" +
  • \n means newline +
  • \t means tab +
  • \r means return +
  • \f means form feed +
  • \nnn means the character whose octal code is nnn +
+

+

Readtables

The behavior of the reader is controlled by a data structure + called a readtable. The reader uses the symbol *readtable* to + locate the current readtable. This table controls the + interpretation of input characters. It is an array with 128 + entries, one for each of the ASCII character codes. Each entry + contains one of the following things: +
    +
  • + NIL - Indicating an invalid character +
  • :CONSTITUENT - Indicating a symbol constituent +
  • :WHITE-SPACE - Indicating a whitespace character +
  • (:TMACRO . fun) - Terminating readmacro +
  • (:NMACRO . fun) - Non-terminating readmacro +
  • :SESCAPE - Single escape character ('\') +
  • :MESCAPE - Multiple escape character ('|') +
+

+ In the case of :TMACRO and :NMACRO, the fun component is a + function. This can either be a built-in readmacro function or a + lambda expression. The function should take two parameters. + The first is the input stream and the second is the character + that caused the invocation of the readmacro. The readmacro + function should return NIL to indicate that the character should + be treated as white space or a value consed with NIL to indicate + that the readmacro should be treated as an occurence of the + specified value. Of course, the readmacro code is free to read + additional characters from the input stream. +

+ XLISP defines several useful read macros: +

+

Lambda Lists

There are several forms in XLISP that require that a "lambda + list" be specified. A lambda list is a definition of the + arguments accepted by a function. There are four different + types of arguments. +

+ The lambda list starts with required arguments. Required + arguments must be specified in every call to the function. +

+ The required arguments are followed by the &optional arguments. + Optional arguments may be provided or omitted in a call. An + initialization expression may be specified to provide a default + value for an &optional argument if it is omitted from a call. + If no initialization expression is specified, an omitted + argument is initialized to NIL. It is also possible to provide + the name of a supplied-p variable that can be used to + determine if a call provided a value for the argument or if the + initialization expression was used. If specified, the supplied- + p variable will be bound to T if a value was specified in the + call and NIL if the default value was used. +

+ The &optional arguments are followed by the &rest argument. The + &rest argument gets bound to the remainder of the argument list + after the required and &optional arguments have been removed. +

+ The &rest argument is followed by the &key arguments. When a + keyword argument is passed to a function, a pair of values + appears in the argument list. The first expression in the pair + should evaluate to a keyword symbol (a symbol that begins with a + ":"). The value of the second expression is the value of the + keyword argument. Like &optional arguments, &key arguments can + have initialization expressions and supplied-p variables. In + addition, it is possible to specify the keyword to be used in a + function call. If no keyword is specified, the keyword obtained + by adding a ":" to the beginning of the keyword argument symbol + is used. In other words, if the keyword argument symbol is + foo, the keyword will be :foo. +

+ The &key arguments are followed by the &aux variables. These + are local variables that are bound during the evaluation of the + function body. It is possible to have initialization + expressions for the &aux variables. +

+ Here is the complete syntax for lambda lists: +

+ (rarg...
+ + [&optional [oarg | (oarg [init [svar]])]...]
+ + [&rest rarg]
+ + [&key
+ + [karg | ([karg | (key karg)] [init [svar]])]...
+ + &allow-other-keys]
+ + [&aux
+ + [aux | (aux [init])]...]) +

+ where: +

+ rarg is a required argument symbol
+ + oarg is an &optional argument symbol
+ + rarg is the &rest argument symbol
+ + karg is a &key argument symbol
+ + key is a keyword symbol
+ + aux is an auxiliary variable symbol
+ + init is an initialization expression
+ + svar is a supplied-p variable symbol
+ +

+

+

Objects

Definitions: +
    +
  • +selector - a symbol used to select an appropriate method +
  • message - a selector and a list of actual arguments +
  • method - the code that implements a message +
+ Since XLISP was created to provide a simple basis for + experimenting with object-oriented programming, one of the + primitive data types included is object. In XLISP, an object + consists of a data structure containing a pointer to the + object's class as well as an array containing the values of the + object's instance variables. +

+ Officially, there is no way to see inside an object (look at the + values of its instance variables). The only way to communicate + with an object is by sending it a message. +

+ You can send a message to an object using the send function. + This function takes the object as its first argument, the + message selector as its second argument (which must be a symbol) + and the message arguments as its remaining arguments. +

+ The send function determines the class of the receiving object + and attempts to find a method corresponding to the message + selector in the set of messages defined for that class. If the + message is not found in the object's class and the class has a + super-class, the search continues by looking at the messages + defined for the super-class. This process continues from one + super-class to the next until a method for the message is found. + If no method is found, an error occurs. +

+ When a method is found, the evaluator binds the receiving object + to the symbol self and evaluates the method using the + remaining elements of the original list as arguments to the + method. These arguments are always evaluated prior to being + bound to their corresponding formal arguments. The result of + evaluating the method becomes the result of the expression. +

+ Within the body of a method, a message can be sent to the current + object by calling the (send self ...). The method lookup + starts with the object's class regardless of the class containing + the current method. +

+ Sometimes it is desirable to invoke a general method in a superclass + even when it is overridden by a more specific method in a subclass. + This can be accomplished by calling send-super, which begins + the method lookup in the superclass of the class defining the current + method rather than in the class of the current object. +

+ The send-super function takes a selector as its first argument + (which must be a symbol) and the message arguments as its remaining + arguments. Notice that send-super can only be sent from within + a method, and the target of the message is always the current object + (self). (send-super ...) is similar to + (send self ...) except that method lookup begins in the + superclass of the class containing the current method + rather than the class of the current object. +

+

The "Object" Class

Object - the top of the class hierarchy. +

+Messages: +

+
+:show - show an object's instance variables. +
+returns - the object + +
+
:class - return the class of an object +
+returns - the class of the object + +
+
:isa class - test if object inherits from class +
+returns - t if object is an instance of class or a subclass of class, otherwise nil + +
+
:isnew - the default object initialization routine +
+returns - the object + +
+

+

The "Class" Class

Class - class of all object classes (including itself) +

+ Messages: +

+

+
+ :new - create a new instance of a class +
+ returns - the new class object + +
+
:isnew ivars [cvars [super]] - initialize a new class +
+ ivars - the list of instance variable symbols
+ cvars - the list of class variable symbols
+ super - the superclass (default is object)
+ returns - the new class object + +
+
:answer msg fargs code - add a message to a class +
+ msg - the message symbol
+ fargs - the formal argument list (lambda list)
+ code - a list of executable expressions
+ returns - the object + +
+
+
+

+ When a new instance of a class is created by sending the message + :new to an existing class, the message :isnew followed by + whatever parameters were passed to the :new message is sent to + the newly created object. +

+ When a new class is created by sending the :new message to the + object Class, an optional parameter may be specified + indicating the superclass of the new class. If this parameter + is omitted, the new class will be a subclass of Object. A + class inherits all instance variables, class variables, and + methods from its super-class. +

+

Profiling

+The Xlisp 2.0 release has been extended with a profiling facility, which counts how many times and where eval is executed. A separate count is maintained for each named function, closure, or macro, and a count indicates an eval in the immediately (lexically) enclosing named function, closure, or macro. Thus, the count gives an indication of the amount of time spent in a function, not counting nested function calls. The list of all functions executed is maintained on the global *profile* variable. These functions in turn have *profile* properties, which maintain the counts. The profile system merely increments counters and puts symbols on the *profile* list. It is up to the user to initialize data and gather results. Profiling is turned on or off with the profile function. Unfortunately, methods cannot be profiled with this facility. +

+ +

Symbols

+ +

+ There are several symbols maintained by the read/eval/print + loop. The symbols +, ++, and +++ are bound to the most + recent three input expressions. The symbols *, ** and *** + are bound to the most recent three results. The symbol - is + bound to the expression currently being evaluated. It becomes + the value of + at the end of the evaluation. +

Evaluation Functions

+
+
+ eval(expr) [SAL]
+ (eval
expr) [LISP] - evaluate an xlisp expression + +
+ expr - the expression to be evaluated
+ returns - the result of evaluating the expression + +
+
apply(fun, args) [SAL]
+ (apply
fun args) [LISP] - apply a function to a list of arguments + +
+ fun - the function to apply (or function symbol)
+ args - the argument list
+ returns - the result of applying the function to the arguments + +
+
funcall(fun, arg...) [SAL]
+ (funcall
fun arg...) [LISP] - call a function with arguments + +
+ fun - the function to call (or function symbol)
+ arg - arguments to pass to the function
+ returns - the result of calling the function with the arguments + +
+
quote(expr) [SAL]
+ (quote
expr) [LISP] - return an expression unevaluated + +
+ expr - the expression to be quoted (quoted)
+ returns - expr unevaluated + +
+
function(expr) [SAL]
+ (function
expr) [LISP] - get the functional interpretation +
+ expr - the symbol or lambda expression (quoted)
+ returns - the functional interpretation
+ +
backquote(expr) [SAL]
+ (backquote
expr) [LISP] - fill in a template +
+ expr - the template
+ returns - a copy of the template with comma and comma-at
+ expressions expanded + +
+
lambda(args, expr...) [SAL]
+ (lambda
args expr...) [LISP] - make a function closure +
+ args - formal argument list (lambda list) (quoted)
+ expr - expressions of the function body
+ returns - the function closure
+ +
get-lambda-expression(closure) [SAL]
+ (get-lambda-expression
closure) [LISP] - get the lambda expression +
+ closure - the closure
+ returns - the original lambda expression
+ +
macroexpand(form) [SAL]
+ (macroexpand
form) [LISP] - recursively expand macro calls +
+ form - the form to expand
+ returns - the macro expansion
+ +
macroexpand-1(form) [SAL]
+ (macroexpand-1
form) [LISP] - expand a macro call +
+ form - the macro call form
+ returns - the macro expansion
+ +
+

Symbol Functions

+
+
+ set(sym, expr) [SAL]
+ (set
sym expr) [LISP] - set the value of a symbol + +
+ sym - the symbol being set
+ expr - the new value
+ returns - the new value
+ +
setq([sym, expr]...) [SAL]
+ (setq
[sym expr]...) [LISP] - set the value of a symbol + +
+ sym - the symbol being set (quoted)
+ expr - the new value
+ returns - the new value
+ +
psetq([sym, expr]...) [SAL]
+ (psetq
[sym expr]...) [LISP] - parallel version of setq + +
+ sym - the symbol being set (quoted)
+ expr - the new value
+ returns - the new value
+ +
setf([place, expr]...) [SAL]
+ (setf
[place expr]...) [LISP] - set the value of a field + +
+ place - the field specifier (quoted):
+
+ sym - set value of a symbol
+ (car expr) - set car of a cons node
+ (cdr expr) - set cdr of a cons node
+ (nth n expr) - set nth car of a list
+ (aref expr n) - set nth element of an array
+ (get sym prop) - set value of a property
+ (symbol-value sym) - set value of a symbol
+ (symbol-function sym) - set functional value of a symbol
+ (symbol-plist sym) - set property list of a symbol
+
+ expr - the new value
+ returns - the new value
+ +
+ + (defun sym fargs expr...) [LISP] - define a function
+ + (defmacro
sym fargs expr...) [LISP] - define a macro + +
+ sym - symbol being defined (quoted)
+ fargs - formal argument list (lambda list) (quoted)
+ expr - expressions constituting the body of the
+ function (quoted) + returns - the function symbol
+ +
gensym([tag]) [SAL]
+ (gensym
[tag]) [LISP] - generate a symbol + +
+ tag - string or number
+ returns - the new symbol
+ +
intern(pname) [SAL]
+ (intern
pname) [LISP] - make an interned symbol + +
+ pname - the symbol's print name string
+ returns - the new symbol
+ +
make-symbol(pname) [SAL]
+ (make-symbol
pname) [LISP] - make an uninterned symbol + +
+ pname - the symbol's print name string
+ returns - the new symbol
+ +
symbol-name(sym) [SAL]
+ (symbol-name
sym) [LISP] - get the print name of a symbol + +
+ sym - the symbol
+ returns - the symbol's print name
+ +
symbol-value(sym) [SAL]
+ (symbol-value
sym) [LISP] - get the value of a symbol + +
+ sym - the symbol
+ returns - the symbol's value
+ +
symbol-function(sym) [SAL]
+ (symbol-function
sym) [LISP] - get the functional value of a symbol + +
+ sym - the symbol
+ returns - the symbol's functional value
+ +
symbol-plist(sym) [SAL]
+ (symbol-plist
sym) [LISP] - get the property list of a symbol + +
+ sym - the symbol
+ returns - the symbol's property list
+ +
hash(sym, n) [SAL]
+ (hash
sym n) [LISP] - compute the hash index for a symbol + +
+ sym - the symbol or string
+ n - the table size (integer)
+ returns - the hash index (integer)
+ +
+

Property List Functions

+
+
+ get(sym, prop) [SAL]
+ (get
sym prop) [LISP] - get the value of a property + +
+ sym - the symbol
+ prop - the property symbol
+ returns - the property value or nil
+ +
putprop(sym, val, prop) [SAL]
+ (putprop
sym val prop) [LISP] - put a property onto a property list + +
+ sym - the symbol
+ val - the property value
+ prop - the property symbol
+ returns - the property value
+ +
remprop(sym, prop) [SAL]
+ (remprop
sym prop) [LISP] - remove a property + +
+ sym - the symbol
+ prop - the property symbol
+ returns - nil
+ +
+

Array Functions

+
+
+ aref(array, n) [SAL]
+ (aref
array n) [LISP] - get the nth element of an array + +
+ array - the array
+ n - the array index (integer)
+ returns - the value of the array element
+ +
make-array(size) [SAL]
+ (make-array
size) [LISP] - make a new array + +
+ size - the size of the new array (integer)
+ returns - the new array
+ +
vector(expr...) [SAL]
+ (vector
expr...) [LISP] - make an initialized vector + +
+ expr - the vector elements
+ returns - the new vector
+ +
+

List Functions

+
+
+ car(expr) [SAL]
+ (car
expr) [LISP] - return the car of a list node + +
+ expr - the list node
+ returns - the car of the list node
+ +
cdr(expr) [SAL]
+ (cdr
expr) [LISP] - return the cdr of a list node + +
+ expr - the list node
+ returns - the cdr of the list node
+ +
cxxr(expr) [SAL]
+ (cxxr
expr) [LISP] - all cxxr combinations + +
+ +
+
cxxxr(expr) [SAL]
+ (cxxxr
expr) [LISP] - all cxxxr combinations + +
+ +
+
cxxxxr(expr) [SAL]
+ (cxxxxr
expr) [LISP] - all cxxxxr combinations + +
+ +
+
first(expr) [SAL]
+ (first
expr) [LISP] - a synonym for car + +
+ +
+
second(expr) [SAL]
+ (second
expr) [LISP] - a synonym for cadr + +
+ +
+
third(expr) [SAL]
+ (third
expr) [LISP] - a synonym for caddr + +
+ +
+
fourth(expr) [SAL]
+ (fourth
expr) [LISP] - a synonym for cadddr + +
+ +
+
rest(expr) [SAL]
+ (rest
expr) [LISP] - a synonym for cdr + +
+ +
+
cons(expr1, expr2) [SAL]
+ (cons
expr1 expr2) [LISP] - construct a new list node + +
+ expr1 - the car of the new list node
+ expr2 - the cdr of the new list node
+ returns - the new list node
+ +
list(expr...) [SAL]
+ (list
expr...) [LISP] - create a list of values + +
+ expr - expressions to be combined into a list
+ returns - the new list
+ +
append(expr...) [SAL]
+ (append
expr...) [LISP] - append lists + +
+ expr - lists whose elements are to be appended
+ returns - the new list
+ +
reverse(expr) [SAL]
+ (reverse
expr) [LISP] - reverse a list + +
+ expr - the list to reverse
+ returns - a new list in the reverse order
+ +
last(list) [SAL]
+ (last
list) [LISP] - return the last list node of a list + +
+ list - the list
+ returns - the last list node in the list
+ +
member(expr, list, test: test, test-not: test-not) [SAL]
+ (member
expr list &key :test :test-not) [LISP] - find an expression in a list + +
+ expr - the expression to find
+ list - the list to search
+ :test - the test function (defaults to eql)
+ :test-not - the test function (sense inverted)
+ returns - the remainder of the list starting with the expression
+ +
assoc(expr, alist, test: test, test-not: test-not) [SAL]
+ (assoc
expr alist &key :test :test-not) [LISP] - find an expression in an a-list + +
+ expr - the expression to find
+ alist - the association list
+ :test - the test function (defaults to eql)
+ :test-not - the test function (sense inverted)
+ returns - the alist entry or nil
+ +
remove(expr, list, test: test, test-not: test-not) [SAL]
+ (remove
expr list &key :test :test-not) [LISP] - remove elements from a list + +
+ expr - the element to remove
+ list - the list
+ :test - the test function (defaults to eql)
+ :test-not - the test function (sense inverted)
+ returns - copy of list with matching expressions removed
+ +
remove-if(test, list) [SAL]
+ (remove-if
test list) [LISP] - remove elements that pass test + +
+ test - the test predicate
+ list - the list
+ returns - copy of list with matching elements removed
+ +
remove-if-not(test, list) [SAL]
+ (remove-if-not
test list) [LISP] - remove elements that fail test + +
+ test - the test predicate
+ list - the list
+ returns - copy of list with non-matching elements removed
+ +
length(expr) [SAL]
+ (length
expr) [LISP] - find the length of a list, vector or string + +
+ expr - the list, vector or string
+ returns - the length of the list, vector or string
+ +
nth(n, list) [SAL]
+ (nth
n list) [LISP] - return the nth element of a list + +
+ n - the number of the element to return (zero origin)
+ list - the list
+ returns - the nth element or nil if the list isn't that long
+ +
nthcdr(n, list) [SAL]
+ (nthcdr
n list) [LISP] - return the nth cdr of a list + +
+ n - the number of the element to return (zero origin)
+ list - the list
+ returns - the nth cdr or nil if the list isn't that long
+ +
mapc(fcn, list1, list...) [SAL]
+ (mapc
fcn list1 list...) [LISP] - apply function to successive cars + +
+ fcn - the function or function name
+ listn - a list for each argument of the function
+ returns - the first list of arguments
+ +
mapcar(fcn, list1, list...) [SAL]
+ (mapcar
fcn list1 list...) [LISP] - apply function to successive cars + +
+ fcn - the function or function name
+ listn - a list for each argument of the function
+ returns - a list of the values returned
+ +
mapl(fcn, list1, list...) [SAL]
+ (mapl
fcn list1 list...) [LISP] - apply function to successive cdrs + +
+ fcn - the function or function name
+ listn - a list for each argument of the function
+ returns - the first list of arguments
+ +
maplist(fcn, list1, list...) [SAL]
+ (maplist
fcn list1 list...) [LISP] - apply function to successive cdrs + +
+ fcn - the function or function name
+ listn - a list for each argument of the function
+ returns - a list of the values returned
+ +
subst(to, from, expr, test: test, test-not: test-not) [SAL]
+ (subst
to from expr &key :test :test-not) [LISP] - substitute expressions + +
+ to - the new expression
+ from - the old expression
+ expr - the expression in which to do the substitutions
+ :test - the test function (defaults to eql)
+ :test-not - the test function (sense inverted)
+ returns - the expression with substitutions
+ +
sublis(alist, expr, test: test, test-not: test-not) [SAL]
+ (sublis
alist expr &key :test :test-not) [LISP] - substitute with an a-list + +
+ alist - the association list
+ expr - the expression in which to do the substitutions
+ :test - the test function (defaults to eql)
+ :test-not - the test function (sense inverted)
+ returns - the expression with substitutions
+ +
+

Destructive List Functions

+
+
+ rplaca(list, expr) [SAL]
+ (rplaca
list expr) [LISP] - replace the car of a list node + +
+ list - the list node
+ expr - the new value for the car of the list node
+ returns - the list node after updating the car
+ +
rplacd(list, expr) [SAL]
+ (rplacd
list expr) [LISP] - replace the cdr of a list node + +
+ list - the list node
+ expr - the new value for the cdr of the list node
+ returns - the list node after updating the cdr
+ +
nconc(list...) [SAL]
+ (nconc
list...) [LISP] - destructively concatenate lists + +
+ list - lists to concatenate
+ returns - the result of concatenating the lists
+ +
delete(expr, test: test, test-not: test-not) [SAL]
+ (delete
expr &key :test :test-not) [LISP] - delete elements from a list + +
+ expr - the element to delete
+ list - the list
+ :test - the test function (defaults to eql)
+ :test-not - the test function (sense inverted)
+ returns - the list with the matching expressions deleted
+ +
delete-if(test, list) [SAL]
+ (delete-if
test list) [LISP] - delete elements that pass test + +
+ test - the test predicate
+ list - the list
+ returns - the list with matching elements deleted
+ +
delete-if-not(test, list) [SAL]
+ (delete-if-not
test list) [LISP] - delete elements that fail test + +
+ test - the test predicate
+ list - the list
+ returns - the list with non-matching elements deleted
+ +
sort(list, test) [SAL]
+ (sort
list test) [LISP] - sort a list + +
+ list - the list to sort
+ test - the comparison function
+ returns - the sorted list
+ +
+

Predicate Functions

+
+
+ atom(expr) [SAL]
+ (atom
expr) [LISP] - is this an atom? + +
+ expr - the expression to check
+ returns - t if the value is an atom, nil otherwise
+ +
symbolp(expr) [SAL]
+ (symbolp
expr) [LISP] - is this a symbol? + +
+ expr - the expression to check
+ returns - t if the expression is a symbol, nil otherwise
+ +
numberp(expr) [SAL]
+ (numberp
expr) [LISP] - is this a number? + +
+ expr - the expression to check
+ returns - t if the expression is a number, nil otherwise
+ +
null(expr) [SAL]
+ (null
expr) [LISP] - is this an empty list? + +
+ expr - the list to check
+ returns - t if the list is empty, nil otherwise
+ +
not(expr) [SAL]
+ (not
expr) [LISP] - is this false? + +
+ expr - the expression to check
+ return - t if the value is nil, nil otherwise
+ +
listp(expr) [SAL]
+ (listp
expr) [LISP] - is this a list? + +
+ expr - the expression to check
+ returns - t if the value is a cons or nil, nil otherwise
+ +
endp(list) [SAL]
+ (endp
list) [LISP] - is this the end of a list + +
+ list - the list
+ returns - t if the value is nil, nil otherwise
+ +
consp(expr) [SAL]
+ (consp
expr) [LISP] - is this a non-empty list? + +
+ expr - the expression to check
+ returns - t if the value is a cons, nil otherwise
+ +
integerp(expr) [SAL]
+ (integerp
expr) [LISP] - is this an integer? + +
+ expr - the expression to check
+ returns - t if the value is an integer, nil otherwise
+ +
floatp(expr) [SAL]
+ (floatp
expr) [LISP] - is this a float? + +
+ expr - the expression to check
+ returns - t if the value is a float, nil otherwise
+ +
stringp(expr) [SAL]
+ (stringp
expr) [LISP] - is this a string? + +
+ expr - the expression to check
+ returns - t if the value is a string, nil otherwise
+ +
characterp(expr) [SAL]
+ (characterp
expr) [LISP] - is this a character? + +
+ expr - the expression to check
+ returns - t if the value is a character, nil otherwise
+ +
arrayp(expr) [SAL]
+ (arrayp
expr) [LISP] - is this an array? + +
+ expr - the expression to check
+ returns - t if the value is an array, nil otherwise
+ +
streamp(expr) [SAL]
+ (streamp
expr) [LISP] - is this a stream? + +
+ expr - the expression to check
+ returns - t if the value is a stream, nil otherwise
+ +
objectp(expr) [SAL]
+ (objectp
expr) [LISP] - is this an object? + +
+ expr - the expression to check
+ returns - t if the value is an object, nil otherwise
+ +
filep(expr) [SAL]
+ (filep
expr) [LISP] (Footnote 8) - is this a file? + +
+ expr - the expression to check
+ returns - t if the value is an object, nil otherwise
+ +
boundp(sym) [SAL]
+ (boundp sym) [LISP] - is a value bound to this symbol? + +
+ sym - the symbol
+ returns - t if a value is bound to the symbol, nil otherwise
+ +
fboundp(sym) [SAL]
+ (fboundp
sym) [LISP] - is a functional value bound to this symbol? + +
+ sym - the symbol
+ returns - t if a functional value is bound to the symbol,
+ nil otherwise + +
+
minusp(expr) [SAL]
+ (minusp
expr) [LISP] - is this number negative? + +
+ expr - the number to test
+ returns - t if the number is negative, nil otherwise
+ +
zerop(expr) [SAL]
+ (zerop
expr) [LISP] - is this number zero? + +
+ expr - the number to test
+ returns - t if the number is zero, nil otherwise
+ +
plusp(expr) [SAL]
+ (plusp
expr) [LISP] - is this number positive? + +
+ expr - the number to test
+ returns - t if the number is positive, nil otherwise
+ +
evenp(expr) [SAL]
+ (evenp
expr) [LISP] - is this integer even? + +
+ expr - the integer to test
+ returns - t if the integer is even, nil otherwise
+ +
oddp(expr) [SAL]
+ (oddp
expr) [LISP] - is this integer odd? + +
+ expr - the integer to test
+ returns - t if the integer is odd, nil otherwise
+ +
eq(expr1, expr2) [SAL]
+ (eq
expr1 expr2) [LISP] - are the expressions identical? + +
+ expr1 - the first expression
+ expr2 - the second expression
+ returns - t if they are equal, nil otherwise
+ +
eql(expr1, expr2) [SAL]
+ (eql
expr1 expr2) [LISP] - are the expressions identical? (works with all numbers) + +
+ expr1 - the first expression
+ expr2 - the second expression
+ returns - t if they are equal, nil otherwise
+ +
equal(expr1, expr2) [SAL]
+ (equal
expr1 expr2) [LISP] - are the expressions equal? + +
+ expr1 - the first expression
+ expr2 - the second expression
+ returns - t if they are equal, nil otherwise
+ +
+

Control Constructs

+
+
+ (cond pair...) [LISP] - evaluate conditionally +
+ pair - pair consisting of:
+
+ (pred expr...) +
+ where: +
+ pred - is a predicate expression
+ expr - evaluated if the predicate + is not nil +
+returns - the value of the first expression whose predicate is not +nil + +
+
and(expr...) [SAL]
+ (and
expr...) [LISP] - the logical and of a list of expressions + +
+ expr - the expressions to be anded
+ returns - nil if any expression evaluates to nil, + otherwise the value of the last expression + (evaluation of expressions stops after the first + expression that evaluates to nil) + +
+
or(expr...) [SAL]
+ (or
expr...) [LISP] - the logical or of a list of expressions + +
+ expr - the expressions to be ored
+ returns - nil if all expressions evaluate to nil, + otherwise the value of the first non-nil expression + (evaluation of expressions stops after the first + expression that does not evaluate to nil) + +
+
if(texpr, expr1[, expr2]) [SAL]
+ (if
texpr expr1 [expr2]) [LISP] - evaluate expressions conditionally + +
+ texpr - the test expression
+ expr1 - the expression to be evaluated if texpr is non-nil
+ expr2 - the expression to be evaluated if texpr is nil
+ returns - the value of the selected expression
+ +
when(texpr, expr...) [SAL]
+ (when
texpr expr...) [LISP] - evaluate only when a condition is true + +
+ texpr - the test expression
+ expr - the expression(s) to be evaluated if texpr is non-nil
+ returns - the value of the last expression or nil + +
+
unless(texpr, expr...) [SAL]
+ (unless
texpr expr...) [LISP] - evaluate only when a condition is false + +
+ texpr - the test expression
+ expr - the expression(s) to be evaluated if texpr is nil
+ returns - the value of the last expression or nil
+ +
(case expr case...) [LISP] - select by case +
+ expr - the selection expression
+ case - pair consisting of:
+
+ (value expr...) +
+ where: +
+ value - is a single expression or a list of + expressions (unevaluated)
+ expr - are expressions to execute if the + case matches +
+ returns - the value of the last expression of the matching case
+ +
+ + (let (binding...) expr...) [LISP] - create local bindings
+ + (let*
(binding...) expr...) [LISP] - let with sequential binding + +
+ binding - the variable bindings each of which is either:
+
+ 1) a symbol (which is initialized to nil)
+ 2) a list whose car is a symbol and whose cadr + is an initialization expression +
+ expr - the expressions to be evaluated
+ returns - the value of the last expression
+ +
+ + (flet (binding...) expr...) [LISP] - create local functions
+ + (labels
(binding...) expr...) [LISP] - flet with recursive functions
+ + (macrolet
(binding...) expr...) [LISP] - create local macros + +
+ binding - the function bindings each of which is:
+
+ (sym fargs expr...) +
+ where: +
+ sym - the function/macro name
+ fargs - formal argument list (lambda list)
+ expr - expressions constituting the body of + the function/macro +
+ expr - the expressions to be evaluated
+ returns - the value of the last expression + +
+
catch(sym, expr...) [SAL]
+ (catch
sym expr...) [LISP] - evaluate expressions and catch throws + +
+ sym - the catch tag
+ expr - expressions to evaluate
+ returns - the value of the last expression the throw expression
+ +
throw(sym[, expr]) [SAL]
+ (throw
sym [expr]) [LISP] - throw to a catch + +
+ sym - the catch tag
+ expr - the value for the catch to return (defaults to nil)
+ returns - never returns
+ +
unwind-protect(expr, cexpr...) [SAL]
+ (unwind-protect
expr cexpr...) [LISP] - protect evaluation of an expression + +
+ expr - the expression to protect
+ cexpr - the cleanup expressions
+ returns - the value of the expression
+ Note: unwind-protect guarantees to execute the cleanup expressions + even if a non-local exit terminates the evaluation of the + protected expression + +
+
+
+

+

Looping Constructs

+
+
+ (loop expr...) [LISP] - basic looping form +
+ expr - the body of the loop
+ returns - never returns (must use non-local exit)
+ +
+ + (do (binding...) (texpr rexpr...) expr...) [LISP] + + (do* (binding...) (texpr rexpr...) expr...) [LISP] + +
+ binding - the variable bindings each of which is either:
+
+ 1) a symbol (which is initialized to nil)
+ 2) a list of the form: (sym init [step]) + where: +
+ sym - is the symbol to bind
+ init - is the initial value of the symbol
+ step - is a step expression
+
+
+ texpr - the termination test expression
+ rexpr - result expressions (the default is nil)
+ expr - the body of the loop (treated like an implicit prog)
+ returns - the value of the last result expression
+ +
(dolist (sym expr [rexpr]) expr...) [LISP] - loop through a list +
+ sym - the symbol to bind to each list element
+ expr - the list expression
+ rexpr - the result expression (the default is nil)
+ expr - the body of the loop (treated like an implicit prog)
+ +
(dotimes (sym expr [rexpr]) expr...) [LISP] - loop from zero to n-1 +
+ sym - the symbol to bind to each value from 0 to n-1
+ expr - the number of times to loop
+ rexpr - the result expression (the default is nil)
+ expr - the body of the loop (treated like an implicit prog)
+ +
+

The Program Feature

+
+
+ +(prog (binding...) expr...) [LISP] - the program feature
+ +(prog*
(binding...) expr...) [LISP] - prog with sequential binding + +
+ binding - the variable bindings each of which is either:
+
+ 1) a symbol (which is initialized to nil)
+ 2) a list whose car is a symbol and whose cadr + is an initialization expression +
+ expr - expressions to evaluate or tags (symbols)
+ returns - nil or the argument passed to the return function
+ +
block(name, expr...) [SAL]
+ (block
name expr...) [LISP] - named block + +
+ name - the block name (symbol)
+ expr - the block body
+ returns - the value of the last expression
+ +
(return [expr]) [LISP] - cause a prog construct to return a value +
+ expr - the value (defaults to nil)
+ returns - never returns
+ +
return-from(name[, value]) [SAL]
+ (return-from
name [value]) [LISP] - return from a named block + +
+ name - the block name (symbol)
+ value - the value to return (defaults to nil)
+ returns - never returns
+ +
tagbody(expr...) [SAL]
+ (tagbody
expr...) [LISP] - block with labels + +
+ expr - expression(s) to evaluate or tags (symbols)
+ returns - nil
+ +
go(sym) [SAL]
+ (go
sym) [LISP] - go to a tag within a tagbody or prog + +
+ sym - the tag (quoted)
+ returns - never returns
+ +
(progv slist vlist expr...) [LISP] - dynamically bind symbols +
+ slist - list of symbols
+ vlist - list of values to bind to the symbols
+ expr - expression(s) to evaluate
+ returns - the value of the last expression
+ +
prog1(expr1, expr...) [SAL]
+ (prog1
expr1 expr...) [LISP] - execute expressions sequentially + +
+ expr1 - the first expression to evaluate
+ expr - the remaining expressions to evaluate
+ returns - the value of the first expression
+ +
prog2(expr1, expr2, expr...) [SAL]
+ (prog2
expr1 expr2 expr...) [LISP] - execute expressions sequentially + +
+ expr1 - the first expression to evaluate
+ expr2 - the second expression to evaluate
+ expr - the remaining expressions to evaluate
+ returns - the value of the second expression
+ +
progn(expr...) [SAL]
+ (progn
expr...) [LISP] - execute expressions sequentially + +
+ expr - the expressions to evaluate
+ returns - the value of the last expression (or nil)
+ +
+

Debugging and Error Handling

+
+
+ trace(sym) [SAL]
+ (trace
sym) [LISP] - add a function to the trace list + +
+ sym - the function to add (quoted)
+ returns - the trace list
+ +
untrace(sym) [SAL]
+ (untrace
sym) [LISP] - remove a function from the trace list + +
+ sym - the function to remove (quoted)
+ returns - the trace list
+ +
error(emsg[, arg]) [SAL]
+ (error
emsg [arg]) [LISP] - signal a non-correctable error + +
+ emsg - the error message string
+ arg - the argument expression (printed after the message)
+ returns - never returns
+ +
cerror(cmsg, emsg[, arg]) [SAL]
+ (cerror
cmsg emsg [arg]) [LISP] - signal a correctable error + +
+ cmsg - the continue message string
+ emsg - the error message string
+ arg - the argument expression (printed after the message)
+ returns - nil when continued from the break loop
+ +
break([bmsg[, arg]]) [SAL]
+ (break
[bmsg [arg]]) [LISP] - enter a break loop + +
+ bmsg - the break message string (defaults to **break**)
+ arg - the argument expression (printed after the message)
+ returns - nil when continued from the break loop
+ +
(clean-up) [LISP] - clean-up after an error +
+ returns - never returns
+ +
(top-level) [LISP] - clean-up after an error and return to the top level +
+ returns - never returns
+ +
(continue) [LISP] - continue from a correctable error +
+ returns - never returns
+ +
(errset expr [pflag]) [LISP] - trap errors +
+ expr - the expression to execute
+ pflag - flag to control printing of the error message
+ returns - the value of the last expression consed with nil
+ or nil on error + +
+
(baktrace [n]) [LISP] - print n levels of trace back information +
+ n - the number of levels (defaults to all levels)
+ returns - nil
+ +
(evalhook expr ehook ahook [env]) [LISP] - evaluate with hooks +
+ expr - the expression to evaluate
+ ehook - the value for *evalhook*
+ ahook - the value for *applyhook*
+ env - the environment (default is nil)
+ returns - the result of evaluating the expression
+ +
profile(flag) [SAL]
+ (profile
flag) [LISP] (Footnote 9) - turn profiling on or off. + +
+ flag - nil turns profiling off, otherwise on
+ returns - the previous state of profiling.
+ +
+

Arithmetic Functions

+
+
+ truncate(expr) [SAL]
+ (truncate
expr) [LISP] - truncates a floating point number to an integer + +
+ expr - the number
+ returns - the result of truncating the number
+ +
float(expr) [SAL]
+ (float
expr) [LISP] - converts an integer to a floating point number + +
+ expr - the number
+ returns - the result of floating the integer
+ +
(+ expr...) [LISP] - add a list of numbers +
+ expr - the numbers
+ returns - the result of the addition
+ +
(- expr...) [LISP] - subtract a list of numbers or negate a single number +
+ expr - the numbers
+ returns - the result of the subtraction
+ +
(* expr...) [LISP] - multiply a list of numbers +
+ expr - the numbers
+ returns - the result of the multiplication
+ +
(/ expr...) [LISP] - divide a list of numbers +
+ expr - the numbers
+ returns - the result of the division
+ +
(1+ expr) [LISP] - add one to a number +
+ expr - the number
+ returns - the number plus one
+ +
(1- expr) [LISP] - subtract one from a number +
+ expr - the number
+ returns - the number minus one
+ +
rem(expr...) [SAL]
+ (rem
function) expr...) [LISP] - remainder of a list of numbers + +
+ expr - the numbers
+ returns - the result of the remainder operation
+ +
min(expr...) [SAL]
+ (min
expr...) [LISP] - the smallest of a list of numbers + +
+ expr - the expressions to be checked
+ returns - the smallest number in the list
+ +
max(expr...) [SAL]
+ (max
expr...) [LISP] - the largest of a list of numbers + +
+ expr - the expressions to be checked
+ returns - the largest number in the list
+ +
abs(expr) [SAL]
+ (abs
expr) [LISP] - the absolute value of a number + +
+ expr - the number
+ returns - the absolute value of the number
+ +
gcd(n1, n2...) [SAL]
+ (gcd
n1 n2...) [LISP] - compute the greatest common divisor + +
+ n1 - the first number (integer)
+ n2 - the second number(s) (integer)
+ returns - the greatest common divisor
+ +
random(n) [SAL]
+ (random
n) [LISP] - compute a random number between 0 and n-1 inclusive + +
+ n - the upper bound (integer)
+ returns - a random number
+ +
rrandom() [SAL]
+ (rrandom
) [LISP] - compute a random real number between 0 and 1 inclusive + +
+ returns - a random floating point number
+ +
sin(expr) [SAL]
+ (sin
expr) [LISP] - compute the sine of a number + +
+ expr - the floating point number
+ returns - the sine of the number
+ +
cos(expr) [SAL]
+ (cos
expr) [LISP] - compute the cosine of a number + +
+ expr - the floating point number
+ returns - the cosine of the number
+ +
tan(expr) [SAL]
+ (tan
expr) [LISP] - compute the tangent of a number + +
+ expr - the floating point number
+ returns - the tangent of the number
+ +
atan(expr[, expr2]) [SAL]
+ (atan
expr [expr2]) [LISP] (Footnote 10) - compute the arctangent + +
+ expr - the value of x
+ expr2 - the value of y (default value is 1.0)
+ returns - the arctangent of x/y
+ +
expt(x-expr, y-expr) [SAL]
+ (expt x-expr y-expr) [LISP] - compute x to the y power + +
+ x-expr - the floating point number
+ y-expr - the floating point exponent
+ returns - x to the y power
+ +
exp(x-expr) [SAL]
+ (exp
x-expr) [LISP] - compute e to the x power + +
+ x-expr - the floating point number
+ returns - e to the x power
+ +
sqrt(expr) [SAL]
+ (sqrt
expr) [LISP] - compute the square root of a number + +
+ expr - the floating point number
+ returns - the square root of the number
+ +
+ +(< n1 n2...) [LISP] - test for less than
+(<=
n1 n2...) [LISP] - test for less than or equal to
+(=
n1 n2...) [LISP] - test for equal to
+(/=
n1 n2...) [LISP] - test for not equal to
+(>=
n1 n2...) [LISP] - test for greater than or equal to
+(>
n1 n2...) [LISP] - test for greater than + +
+ n1 - the first number to compare
+ n2 - the second number to compare
+returns - t if the results of comparing n1 with n2, +n2 with n3, etc., are all true.
+ +
+

Bitwise Logical Functions

+
+
+ logand(expr...) [SAL]
+ (logand
expr...) [LISP] - the bitwise and of a list of numbers + +
+ expr - the numbers
+ returns - the result of the and operation
+ +
logior(expr...) [SAL]
+ (logior
expr...) [LISP] - the bitwise inclusive or of a list of numbers + +
+ expr - the numbers
+ returns - the result of the inclusive or operation
+ +
logxor(expr...) [SAL]
+ (logxor
expr...) [LISP] - the bitwise exclusive or of a list of numbers + +
+ expr - the numbers
+ returns - the result of the exclusive or operation
+ +
lognot(expr) [SAL]
+ (lognot
expr) [LISP] - the bitwise not of a number + +
+ expr - the number
+ returns - the bitwise inversion of number
+ +
+

String Functions

+
+
+ string(expr) [SAL]
+ (string
expr) [LISP] - make a string from a value + +
+ expr - an integer (which is first converted into its ASCII character value), string, character, or symbol
+ returns - the string representation of the argument
+ +
string-search(pat, str, start: start, end: end) [SAL]
+ (string-search
pat str &key :start :end) [LISP] (Footnote 11) - search for pattern in string + +
+ pat - a string to search for
+ str - the string to be searched
+ :start - the starting offset in str
+ :end - the ending offset + 1
+ returns - index of pat in str or NIL if not found
+ +
string-trim(bag, str) [SAL]
+ (string-trim bag str) [LISP] - trim both ends of a string + +
+ bag - a string containing characters to trim
+ str - the string to trim
+ returns - a trimed copy of the string
+ +
string-left-trim(bag, str) [SAL]
+ (string-left-trim
bag str) [LISP] - trim the left end of a string + +
+ bag - a string containing characters to trim
+ str - the string to trim
+ returns - a trimed copy of the string
+ +
string-right-trim(bag, str) [SAL]
+ (string-right-trim
bag str) [LISP] - trim the right end of a string + +
+ bag - a string containing characters to trim
+ str - the string to trim
+ returns - a trimed copy of the string
+ +
string-upcase(str, start: start, end: end) [SAL]
+ (string-upcase
str &key :start :end) [LISP] - convert to uppercase + +
+ str - the string
+ :start - the starting offset
+ :end - the ending offset + 1
+ returns - a converted copy of the string
+ +
string-downcase(str, start: start, end: end) [SAL]
+ (string-downcase
str &key :start :end) [LISP] - convert to lowercase + +
+ str - the string
+ :start - the starting offset
+ :end - the ending offset + 1
+ returns - a converted copy of the string
+ +
nstring-upcase(str, start: start, end: end) [SAL]
+ (nstring-upcase
str &key :start :end) [LISP] - convert to uppercase + +
+ str - the string
+ :start - the starting offset
+ :end - the ending offset + 1
+ returns - the converted string (not a copy)
+ +
nstring-downcase(str, start: start, end: end) [SAL]
+ (nstring-downcase
str &key :start :end) [LISP] - convert to lowercase + +
+ str - the string
+ :start - the starting offset
+ :end - the ending offset + 1
+ returns - the converted string (not a copy)
+ +
strcat(expr...) [SAL]
+ (strcat
expr...) [LISP] - concatenate strings + +
+ expr - the strings to concatenate
+ returns - the result of concatenating the strings
+ +
subseq(string, start[, end]) [SAL]
+ (subseq
string start [end]) [LISP] - extract a substring + +
+ string - the string
+ start - the starting position (zero origin)
+ end - the ending position + 1 (defaults to end)
+ returns - substring between start and end
+ +
+ + string<(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string<
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + + + string<=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string<=
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+ string=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string=
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+ string/=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string/=
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+ string>=(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string>=
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+ string>(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string>
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + + +
+ str1 - the first string to compare
+ str2 - the second string to compare
+ :start1 - first substring starting offset
+ :end1 - first substring ending offset + 1
+ :start2 - second substring starting offset
+ :end2 - second substring ending offset + 1
+ returns - t if predicate is true, nil otherwise
+ Note: case is significant with these comparison functions. + +
+
+ +string-lessp(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string-lessp
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+string-not-greaterp(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string-not-greaterp
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+string-equalp(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string-equalp
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+string-not-equalp(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string-not-equalp
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+string-not-lessp(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string-not-lessp
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + +
+string-greaterp(str1, str2, start1: start1, end1: end1, start2: start2, end2: end2) [SAL]
+ (string-greaterp
str1 str2 &key :start1 :end1 :start2 :end2) [LISP] + + +
+ str1 - the first string to compare
+ str2 - the second string to compare
+ :start1 - first substring starting offset
+ :end1 - first substring ending offset + 1
+ :start2 - second substring starting offset
+ :end2 - second substring ending offset + 1
+ returns - t if predicate is true, nil otherwise
+ Note: case is not significant with these comparison functions. + +
+
+
+

+

Character Functions

+
+
+ char(string, index) [SAL]
+ (char
string index) [LISP] - extract a character from a string + +
+ string - the string
+ index - the string index (zero relative)
+ returns - the ascii code of the character
+ +
upper-case-p(chr) [SAL]
+ (upper-case-p
chr) [LISP] - is this an upper case character? + +
+ chr - the character
+ returns - t if the character is upper case, nil otherwise
+ +
lower-case-p(chr) [SAL]
+ (lower-case-p
chr) [LISP] - is this a lower case character? + +
+ chr - the character
+ returns - t if the character is lower case, nil otherwise
+ +
both-case-p(chr) [SAL]
+ (both-case-p
chr) [LISP] - is this an alphabetic (either case) character? + +
+ chr - the character
+ returns - t if the character is alphabetic, nil otherwise
+ +
digit-char-p(chr) [SAL]
+ (digit-char-p
chr) [LISP] - is this a digit character? + +
+ chr - the character
+ returns - the digit weight if character is a digit, nil otherwise
+ +
char-code(chr) [SAL]
+ (char-code
chr) [LISP] - get the ascii code of a character + +
+ chr - the character
+ returns - the ascii character code (integer)
+ +
code-char(code) [SAL]
+ (code-char
code) [LISP] - get the character with a specified ascii code + +
+ code - the ascii code (integer)
+ returns - the character with that code or nil
+ +
char-upcase(chr) [SAL]
+ (char-upcase
chr) [LISP] - convert a character to upper case + +
+ chr - the character
+ returns - the upper case character
+ +
char-downcase(chr) [SAL]
+ (char-downcase
chr) [LISP] - convert a character to lower case + +
+ chr - the character
+ returns - the lower case character
+ +
digit-char(n) [SAL]
+ (digit-char
n) [LISP] - convert a digit weight to a digit + +
+ n - the digit weight (integer)
+ returns - the digit character or nil
+ +
char-int(chr) [SAL]
+ (char-int
chr) [LISP] - convert a character to an integer + +
+ chr - the character
+ returns - the ascii character code
+ +
int-char(int) [SAL]
+ (int-char
int) [LISP] - convert an integer to a character + +
+ int - the ascii character code
+ returns - the character with that code
+ +
+ + char<(chr1, chr2...) [SAL]
+ (char<
chr1 chr2...) [LISP] + +
+ char<=(chr1, chr2...) [SAL]
+ (char<=
chr1 chr2...) [LISP] + +
+ char=(chr1, chr2...) [SAL]
+ (char=
chr1 chr2...) [LISP] + +
+ char/=(chr1, chr2...) [SAL]
+ (char/=
chr1 chr2...) [LISP] + +
+ char>=(chr1, chr2...) [SAL]
+ (char>=
chr1 chr2...) [LISP] + +
+ char>(chr1, chr2...) [SAL]
+ (char>
chr1 chr2...) [LISP] + + +
+ chr1 - the first character to compare
+ chr2 - the second character(s) to compare
+ returns - t if predicate is true, nil otherwise
+ Note: case is significant with these comparison functions. + +
+
+ +char-lessp(chr1, chr2...) [SAL]
+ (char-lessp
chr1 chr2...) [LISP] + +
+char-not-greaterp(chr1, chr2...) [SAL]
+ (char-not-greaterp
chr1 chr2...) [LISP] + +
+char-equalp(chr1, chr2...) [SAL]
+ (char-equalp
chr1 chr2...) [LISP] + +
+char-not-equalp(chr1, chr2...) [SAL]
+ (char-not-equalp
chr1 chr2...) [LISP] + +
+char-not-lessp(chr1, chr2...) [SAL]
+ (char-not-lessp
chr1 chr2...) [LISP] + +
+char-greaterp(chr1, chr2...) [SAL]
+ (char-greaterp
chr1 chr2...) [LISP] + + +
+chr1 - the first string to compare
+chr2 - the second string(s) to compare
+returns - t if predicate is true, nil otherwise
+ Note: case is not significant with these comparison functions. + +
+
+
+

+

Input/Output Functions

+
+
+ read([stream[, eof[, rflag]]]) [SAL]
+ (read
[stream [eof [rflag]]]) [LISP] - read an expression + +
+ stream - the input stream (default is standard input)
+ eof - the value to return on end of file (default is nil)
+ rflag - recursive read flag (default is nil)
+ returns - the expression read
+ +
(print expr [stream]) [LISP] - print an expression on a new line +
+ expr - the expression to be printed
+ stream - the output stream (default is standard output)
+ returns - the expression
+ +
prin1(expr[, stream]) [SAL]
+ (prin1
expr [stream]) [LISP] - print an expression + +
+ expr - the expression to be printed
+ stream - the output stream (default is standard output)
+ returns - the expression
+ +
princ(expr[, stream]) [SAL]
+ (princ
expr [stream]) [LISP] - print an expression without quoting + +
+ expr - the expressions to be printed
+ stream - the output stream (default is standard output)
+ returns - the expression
+ +
pprint(expr[, stream]) [SAL]
+ (pprint
expr [stream]) [LISP] - pretty print an expression + +
+ expr - the expressions to be printed
+ stream - the output stream (default is standard output)
+ returns - the expression
+ +
terpri([stream]) [SAL]
+ (terpri
[stream]) [LISP] - terminate the current print line + +
+ stream - the output stream (default is standard output)
+ returns - nil
+ +
flatsize(expr) [SAL]
+ (flatsize
expr) [LISP] - length of printed representation using prin1 + +
+ expr - the expression
+ returns - the length
+ +
flatc(expr) [SAL]
+ (flatc
expr) [LISP] - length of printed representation using princ + +
+ expr - the expression
+ returns - the length + +
+
+
+

+

The Format Function

+
+
+format(stream, fmt, arg...) [SAL]
+ (format
stream fmt arg...) [LISP] - do formated + +output +
+ stream - the output stream
+ fmt - the format string
+ arg - the format arguments
+ returns - output string if stream is nil, nil otherwise
+ +
+
+ The format string can contain characters that should be copied + directly to the output and formatting directives. The + formatting directives are: +
+~A - print next argument using princ
+ +~S - print next argument using prin1
+ +~% - start a new line
+ +~~ - print a tilde character
+ +~<newline> - ignore this one newline and white space on the
+ +next line up to the first non-white-space character or newline. This
+ +allows strings to continue across multiple lines
+ +
+

+

File I/O Functions

+Note that files are ordinarily opened as text. Binary files (such as standard midi files) must be opened with open-binary on non-unix systems. +
+
+ open(fname, direction: direction) [SAL]
+ (open
fname &key :direction) [LISP] - open a file stream + +
+ fname - the file name string or symbol
+ :direction - :input or :output (default is :input)
+ returns - a stream
+ +
+ open-binary(fname, direction: direction) [SAL]
+ (open-binary
fname &key :direction) [LISP] - open a binary file stream + +
+ fname - the file name string or symbol
+ :direction - :input or :output (default is :input)
+ returns - a stream
+ +
close(stream) [SAL]
+ (close
stream) [LISP] - close a file stream + +
+ stream - the stream
+ returns - nil
+ +
setdir(path[, verbose]) [SAL]
+ (setdir
path [verbose]) [LISP] (Footnote 12) - set current directory + +
+ path - the path of the new directory
+ verbose - print error message if current directory cannot be changed to path
+ returns - the resulting full path, e.g. (setdir ".") gets the current working directory, or nil if an error occurs
+ +
listdir(path) [SAL]
+ (listdir path) [LISP] (Footnote 13) - get a directory listing + +
+ path - the path of the directory to be listed
+ returns - list of filenames in the directory
+ +
get-temp-path() [SAL]
+ (get-temp-path) [LISP] (Footnote 14) - get a path where a temporary file can be created. Under Windows, this is based on environment variables. If XLISP is running as a sub-process to Java, the environment may not exist, in which case the default result is the unfortunate choice c:\windows\. + +
+ returns - the resulting full path as a string
+ +
get-user() [SAL]
+ (get-user) [LISP] (Footnote 15) - get the user ID. In Unix systems (including OS X and Linux), this is the value of the USER environment variable. In Windows, this is currently just "nyquist", which is also returned if the environment variable cannot be accessed. This function is used to avoid the case of two users creating files of the same name in the same temp directory. + +
+ returns - the string naming the user
+ +
+ find-in-xlisp-path(filename) [SAL]
+ (find-in-xlisp-path filename) [LISP] (Footnote 16) - search the XLISP search path (e.g. XLISPPATH from the environment) for filename. If filename is not found as is, and there is no file extension, append ".lsp" to filename and search again. The current directory is not searched. + +
+ filename - the name of the file to search for
+ returns - a full path name to the first occurrence found
+ +
read-char([stream]) [SAL]
+ (read-char [stream]) [LISP] - read a character from a stream + +
+ stream - the input stream (default is standard input)
+ returns - the character
+ +
peek-char([flag[, stream]]) [SAL]
+ (peek-char
[flag [stream]]) [LISP] - peek at the next character + +
+ flag - flag for skipping white space (default is nil)
+ stream - the input stream (default is standard input)
+ returns - the character (integer)
+ +
write-char(ch[, stream]) [SAL]
+ (write-char
ch [stream]) [LISP] - write a character to a stream + +
+ ch - the character to write
+ stream - the output stream (default is standard output)
+ returns - the character
+ +
read-int([stream[, length]]) [SAL]
+ (read-int
[stream [length]]) [LISP] - read a binary integer from a stream + +
+ stream - the input stream (default is standard input)
+ length - the length of the integer in bytes (default is 4)
+ returns - the integer
+Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
+ +
write-int(ch[, stream[, length]]) [SAL]
+ (write-int
ch [stream [length]]) [LISP] - write a binary integer to a stream + +
+ ch - the character to write
+ stream - the output stream (default is standard output)
+ length - the length of the integer in bytes (default is 4)
+ returns - the integer
+Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
+ +
read-float([stream[, length]]) [SAL]
+ (read-float
[stream [length]]) [LISP] - read a binary floating-point number from a stream + +
+ stream - the input stream (default is standard input)
+ length - the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8)
+ returns - the integer
+Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
+ +
write-float(ch[, stream[, length]]) [SAL]
+ (write-float
ch [stream [length]]) [LISP] - write a binary floating-point number to a stream + +
+ ch - the character to write
+ stream - the output stream (default is standard output)
+ length - the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8)
+ returns - the integer
+Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
+ +
read-line([stream]) [SAL]
+ (read-line
[stream]) [LISP] - read a line from a stream + +
+ stream - the input stream (default is standard input)
+ returns - the string
+ +
read-byte([stream]) [SAL]
+ (read-byte
[stream]) [LISP] - read a byte from a stream + +
+ stream - the input stream (default is standard input)
+ returns - the byte (integer)
+ +
write-byte(byte[, stream]) [SAL]
+ (write-byte
byte [stream]) [LISP] - write a byte to a stream + +
+ byte - the byte to write (integer)
+ stream - the output stream (default is standard output)
+ returns - the byte (integer)
+ +
+

String Stream Functions

+ These functions operate on unnamed streams. An unnamed output + stream collects characters sent to it when it is used as the + destination of any output function. The functions +get-output-stream-string and get-output-stream-list return a string or a list of characters. +

+An unnamed input stream is setup with the + make-string-input-stream function and returns each character of the string when + it is used as the source of any input function. +

+

+
+
+ make-string-input-stream(str[, start[, end]]) [SAL]
+ (make-string-input-stream
str [start [end]]) [LISP] + +
+ str - the string
+ start - the starting offset
+ end - the ending offset + 1
+ returns - an unnamed stream that reads from the string
+ +
make-string-output-stream)() [SAL]
+ (make-string-output-stream) [LISP]
+ +
+ returns - an unnamed output stream
+ +
get-output-stream-string(stream) [SAL]
+ (get-output-stream-string
stream) [LISP] + +
+ stream - the output stream
+ returns - the output so far as a string
+ Note: the output stream is emptied by this function + +
+
get-output-stream-list(stream) [SAL]
+ (get-output-stream-list
stream) [LISP] + +
+ stream - the output stream
+ returns - the output so far as a list
+ Note: the output stream is emptied by this function + +
+
+
+

+

System Functions

+Note: the load function first tries to load a file from the current directory. A .lsp extension is added if there is not already an alphanumeric extension following a period. If that fails, XLISP searches the path, which is obtained from the XLISPPATH environment variable in Unix and HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under Win32. (The Macintosh version has no search path.) +

+

+
+ get-env(name) [SAL]
+ (get-env
name) [LISP] - get from an environment variable + +
+ name - the name of the environment variable
+ returns - string value of the environment variable, nil if variable does not exist
+ +
(load fname &key :verbose :print) [LISP] - load a source file +
+ fname - the filename string or symbol
+ :verbose - the verbose flag (default is t)
+ :print - the print flag (default is nil)
+ returns - the filename
+ +
save(fname) [SAL]
+ (save
fname) [LISP] - save workspace to a file + +
+ fname - the filename string or symbol
+ returns - t if workspace was written, nil otherwise
+ +
restore(fname) [SAL]
+ (restore
fname) [LISP] - restore workspace from a file + +
+ fname - the filename string or symbol
+ returns - nil on failure, otherwise never returns
+ +
dribble([fname]) [SAL]
+ (dribble
[fname]) [LISP] - create a file with a transcript of a session + +
+ fname - file name string or symbol + (if missing, close current transcript)
+ returns - t if the transcript is opened, nil if it is closed
+ +
gc() [SAL]
+ (gc
) [LISP] - force garbage collection + +
+ returns - nil
+ +
expand(num) [SAL]
+ (expand
num) [LISP] - expand memory by adding segments + +
+ num - the number of segments to add
+ returns - the number of segments added
+ +
alloc(num) [SAL]
+ (alloc
num) [LISP] - change number of nodes to allocate in each segment + +
+ num - the number of nodes to allocate
+ returns - the old number of nodes to allocate
+ +
info() [SAL]
+ (info
) [LISP] - show information about memory usage. + +
+ returns - nil
+ +
room() [SAL]
+ (room
) [LISP] - show memory allocation statistics + +
+ returns - nil
+ +
type-of(expr) [SAL]
+ (type-of
expr) [LISP] - returns the type of the expression + +
+ expr - the expression to return the type of
+ returns - nil if the value is nil otherwise one of the symbols:
+
+ SYMBOL - for symbols
+ OBJECT - for objects
+ CONS - for conses
+ SUBR - for built-in functions
+ FSUBR - for special forms
+ CLOSURE - for defined functions
+ STRING - for strings
+ FIXNUM - for integers
+ FLONUM - for floating point numbers
+ CHARACTER - for characters
+ FILE-STREAM - for file pointers
+ UNNAMED-STREAM - for unnamed streams
+ ARRAY - for arrays
+
+ +
peek(addrs) [SAL]
+ (peek
addrs) [LISP] - peek at a location in memory + +
+ addrs - the address to peek at (integer)
+ returns - the value at the specified address (integer)
+ +
poke(addrs, value) [SAL]
+ (poke
addrs value) [LISP] - poke a value into memory + +
+ addrs - the address to poke (integer)
+ value - the value to poke into the address (integer)
+ returns - the value
+ +
bigendianp() [SAL]
+ (bigendianp
) [LISP] - is this a big-endian machine? + +
+ returns - T if this a big-endian architecture, storing the high-order byte of an integer at the lowest byte address of the integer; otherwise, NIL. + (Footnote 17)
+ +
address-of(expr) [SAL]
+ (address-of expr) [LISP] - get the address of an xlisp node + +
+ expr - the node
+ returns - the address of the node (integer)
+ +
exit() [SAL]
+ (exit
) [LISP] - exit xlisp + +
+ returns - never returns
+ +
setup-console() [SAL]
+ (setup-console
) [LISP] - set default console attributes + +
+ returns - NIL
+Note: Under Windows, Nyquist normally starts up in a medium-sized console window with black text and a white background, with a window title of "Nyquist." This is normally accomplished by calling setup-console in system.lsp. In Nyquist, you can avoid this behavior by setting *setup-console* to NIL in your init.lsp file. If setup-console is not called, Nyquist uses standard input and output as is. This is what you want if you are running Nyquist inside of emacs, for example.

+ +
echoenabled(flag) [SAL]
+ (echoenabled
flag) [LISP] - turn console input echoing on or off + +
+ flag - T to enable echo, NIL to disable
+ returns - NIL
+Note: This function is only implemented under Linux and Mac OS X. If Nyquist I/O is redirected through pipes, +the Windows version does not echo the input, but the Linux and Mac versions do. You can turn off echoing with +this function. Under windows it is defined to do nothing.
+ +

File I/O Functions

Input from a File

To open a file for input, use the open function with the keyword +argument :direction set to :input. To open a file for output, +use the open function with the keyword argument :direction set +to :output. The open function takes a single required argument which +is the name of the file to be opened. This name can be in the form of a +string or a symbol. The open function returns an object of type +FILE-STREAM if it succeeds in opening the specified file. It returns the +value nil if it fails. In order to manipulate the file, it is +necessary to save the value returned by the open function. This is +usually done by assigning it to a variable with the setq special form or by +binding it using let or let*. Here is an example: +
+(setq fp (open "init.lsp" :direction :input))
+
+ + Evaluating this expression will result in the file init.lsp + being opened. The file object that will be returned by the open + function will be assigned to the variable fp. +

+ It is now possible to use the file for input. To read an + expression from the file, just supply the value of the fp + variable as the optional stream argument to read. +

+(read fp)
+
+ + Evaluating this expression will result in reading the first + expression from the file init.lsp. The expression will be + returned as the result of the read function. More expressions + can be read from the file using further calls to the read + function. When there are no more expressions to read, the read + function will return nil (or whatever value was supplied as the + second argument to read). +

+ Once you are done reading from the file, you should close it. + To close the file, use the following expression: +

+(close fp)
+
+ + Evaluating this expression will cause the file to be closed. +

+

Output to a File

Writing to a file is pretty much the same as reading from one. + You need to open the file first. This time you should use the + open function to indicate that you will do output to the file. + For example: +
+(setq fp (open "test.dat" :direction :output))
+
+ + Evaluating this expression will open the file test.dat for + output. If the file already exists, its current contents will + be discarded. If it doesn't already exist, it will be created. + In any case, a FILE-STREAM object will be returned by the OPEN + function. This file object will be assigned to the fp + variable. +

+ It is now possible to write to this file by supplying the value + of the fp variable as the optional stream parameter in the print function. +

+(print "Hello there" fp)
+
+ + Evaluating this expression will result in the string "Hello + there" being written to the file test.dat. More data can be + written to the file using the same technique. +

+ Once you are done writing to the file, you should close it. + Closing an output file is just like closing an input file. +

+(close fp)
+
+ + Evaluating this expression will close the output file and make + it permanent. +

+

A Slightly More Complicated File Example

This example shows how to open a file, read each Lisp expression + from the file and print it. It demonstrates the use of files + and the use of the optional stream argument to the read + function. +
+(do* ((fp (open "test.dat" :direction :input))
+      (ex (read fp) (read fp)))
+     ((null ex) nil)
+  (print ex))
+
+ +

+ +


+Previous Section | Next Section (Index) | Table of Contents | Title Page + diff --git a/doc/part2.html b/doc/part2.html new file mode 100644 index 0000000..794df52 --- /dev/null +++ b/doc/part2.html @@ -0,0 +1,491 @@ +Introduction and Overview + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Introduction and Overview

Nyquist is a language for sound synthesis and music composition. Unlike score +languages that tend to deal only with events, or signal processing languages +that tend to deal only with signals and synthesis, Nyquist handles both in a +single integrated system. Nyquist is also flexible and easy to use because it +is based on an interactive Lisp interpreter. +

+With Nyquist, you can design instruments by combining functions (much as you +would using the orchestra languages of Music V, cmusic, or Csound). You can +call upon these instruments and generate a sound just by typing a simple +expression. You can combine simple expressions into complex ones to create +a whole composition. +

+Nyquist runs under Linux, Apple Mac OS X, Microsoft Windows NT, +2000, XP, and Vista, +and it produces sound files or directly generates audio. +Recent versions have also run on AIX, NeXT, SGI, DEC pmax, and Sun Sparc +machines. (Makefiles for many of these are included, but out-of-date). +Let me know if you have problems with +any of these machines. +

+To use Nyquist, you should have a basic knowledge of Lisp. An excellent text +by Touretzky is recommended (Touretzky 1984). Appendix "XLISP: An Object-oriented Lisp" is +the reference manual for XLISP, of which Nyquist is a superset. Starting with +Version 3, Nyquist supports a variant of SAL, which is also available in +Common Music. Since there are some differences, one should generally call this +implementation "Nyquist SAL;" however, in this manual, I will just call it +"SAL." SAL offers most of the capabilities of Lisp, but it uses an Algol-like +syntax that may be more familiar to programmers with experience in Java, C, +Basic, etc. +

+ +

Installation

+ +Nyquist is a C++ program intended to run under various operating systems +including Unix, Mac OS X, and Windows. Nyquist is based on Lisp, but it +includes its own Lisp interpreter (a modified version of XLISP), so you +do not need to install some other Lisp to run Nyquist. Other +Lisp systems are not compatible with Nyquist. +

+Most Nyquist users run Nyquist under the Nyquist IDE, which is written in Java +and depends on the Java runtime system. Most systems already have Java, but if +you do not, you will need to install it. When you install the Nyquist IDE, +you will automatically get Nyquist and a set of runtime libraries. +

+There are generally two ways to install Nyquist: +

    +
  • +Get a pre-compiled version of the Nyquist IDE for Windows or Mac OS X. The +Windows version comes packaged in an installer that installs and +configures the Nyquist IDE. The Mac OS X version +unpacks to a complete OS X application. +
  • Compile from sources. There is one set of sources for Mac, Windows, and Unix. +Instructions for building applications from the sources are provided in +the files sys/win/README.txt, sys/mac/README.txt, and +sys/unix/README.txt. +
+

+You can download source code and precompiled versions from the Nyquist project +on SourceForge (http://sourceforge.net/projects/nyquist). The latest +source code can be obtained via Subversion (svn) using the following: +

+svn co https://nyquist.svn.sourceforge.net/svnroot/nyquist/trunk nyquist
+
+ +or by checking out nyquist using a graphical interface svn client such as +TortoiseSVN for Windows. +

+

Using NyquistIDE

+The program named NyquistIDE is an "integrated development environment" for Nyquist. When you run NyquistIDE, it starts the Nyquist program and displays all Nyquist output in a window. NyquistIDE helps you by providing a Lisp and SAL editor, hints for command completion and function parameters, some graphical interfaces for editing envelopes and graphical equalizers, and a panel of buttons for common operations. A more complete description of NyquistIDE is in Chapter "The NyquistIDE Program". +

+For now, all you really need to know is that you can enter Nyquist commands by typing into the upper left window. When you type return, the expression you typed is sent to Nyquist, and the results appear in the window below. You can edit files by clicking on the New File or Open File buttons. After editing some text, you can load the text into Nyquist by clicking the Load button. NyquistIDE always saves the file first; then it tells Nyquist to load the file. You will be prompted for a file name the first time you load a new file. +

+

Using SAL

+SAL mode means that Nyquist reads and evaluates SAL commands rather than Lisp. The SAL mode prompt is "SAL> " while the Lisp mode prompt is "> ". +When Nyquist starts it normally enters SAL mode automatically, but certain errors may exit SAL mode. You can reenter SAL mode by typing the Lisp expression (sal). +

+In SAL mode, you type commands in the SAL programming language. Nyquist reads the commands, compiles them into Lisp, and evaluates the commands. Commands can be entered manually by typing into the upper left text box in NyquistIDE. +

+

Helpful Hints

+Under Win95 and Win98, the console sometimes locks up. Activating another window and then reactivating the Nyquist window should unlock the output. +(We suggest you use JNyqIDE, the interactive development environment rather than a console window.) +

+You can cut and paste text into Nyquist, but for serious work, you will want to use the Lisp load command. To save even more time, write a +function to load your working file, e.g. (defun l () (load "myfile.lsp")). Then you can type (l) to (re)load your file. +

+Using SAL, you can type +

+define function l () load "myfile.lsp"
+
+ +and then +
+exec l()
+
+ +to (re)load the file. +

+The Emacs editor is free GNU software and will help you balance parentheses if you use Lisp mode. In fact, you can run nyquist (without the IDE) as a subprocess to Emacs. A helful discussion is at //http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/examples/emacs/main.html. If you use Emacs, there is also a SAL mode (the file is sal-mode.el) included with the Common Music distribution, which you can find on the Web at sourceforge.net. +

+The NyquistIDE also runs Nyquist as a subprocess and has +built-in Lisp and SAL editors. If your editor does not help you balance parentheses, you may find yourself counting parens and searching for unbalanced +expressions. If you are confused or desperate and using Lisp syntax, +try the +:print t +option of the load function. By looking at the expressions printed, +you should be able to tell where the last unbalanced expression starts. +Alternatively, type (file-sexprs) and type the lisp file name at +the prompt. This function will read and print +expressions from the file, reporting an error when an extra paren or end-of-file is reached unexpectedly. +

+

Using Lisp

+Lisp mode means that Nyquist reads and evaluates Nyquist expressions in +Lisp syntax. Since Nyquist is build on a Lisp interpreter, this is the +"native" or machine language of Nyquist, and certain errors and functions +may break out of the SAL interpreter, leaving you with a prompt for a Lisp +expression. Alternatively, you can exit SAL simply by typing exit to +get a Lisp prompt (> ). Commands can be entered manually by typing + into the upper left text box in NyquistIDE. +

+

Examples

+We will begin with some simple Nyquist programs. Throughout the manual, +we will assume SAL mode and give examples in SAL, but it should be +emphasized that all of these examples can be performed using Lisp +syntax. See Section "Interoperability of SAL and XLISP" on the relationship between +SAL and Lisp. +

+Detailed explanations of the functions used in these examples will be +presented in later chapters, so at this point, you should just read these +examples to get a sense of how Nyquist is used and what it can do. The +details will come later. Most of these examples can be found in the +file nyquist/demos/examples.sal. Corresponding Lisp syntax +examples are in the file nyquist/demos/examples.lsp. +

+Our first example makes and plays a sound: +

+;; Making a sound.
+play osc(60) ; generate a loud sine wave
+ 
+ +This example is about the simplest way to create a sound with Nyquist. The +osc function generates a sound using a table-lookup oscillator. +There are a number of optional parameters, but the default is to compute a +sinusoid with an amplitude of 1.0. The parameter 60 designates a +pitch of middle C. (Pitch specification will be described in greater detail +later.) The result of the osc function is a sound. To hear a sound, +you must use the play command, which plays the file through the machine's D/A converters. It also writes a soundfile in case the computation cannot keep up with real time. You can then (re)play the file by typing: +
+exec r()
+
+ +This (r) function is a general way to "replay" the last thing written by play. +

+Note: when Nyquist plays a sound, it scales the signal by 2^(15)-1 and (by default) converts to a 16-bit integer format. A signal like (osc 60), which ranges from +1 to -1, will play as a full-scale 16-bit audio signal. +

+

Waveforms

+ +Our next example will be presented in several steps. The goal is to create a +sound using a +wavetable consisting of several harmonics as opposed to a simple sinusoid. +In order to build a table, we will use a function that computes a single +harmonic and add harmonics to form a wavetable. An oscillator +will be used to compute the harmonics. +

+The function +mkwave calls upon +build-harmonic to generate a total of four +harmonics with amplitudes 0.5, 0.25, 0.125, and 0.0625. +These are scaled and added (using +) to +create a waveform which is bound temporarily to *table*. +

+A complete Nyquist waveform is a list consisting of a sound, a pitch, + and T, indicating a periodic waveform. The pitch gives the +nominal pitch of the sound. (This is implicit in a single cycle wave +table, but a sampled sound may have many periods of the fundamental.) +Pitch is expressed in half-steps, where middle C is 60 steps, as in MIDI +pitch numbers. +The list of sound, pitch, and T is formed in the last line of +mkwave: since build-harmonic computes signals with a duration +of one second, the fundamental is 1 Hz, and the hz-to-step function +converts to pitch (in units of steps) as required. +

+

+define function mkwave()
+  begin
+    set *table* = 0.5 * build-harmonic(1.0, 2048) +
+                  0.25 * build-harmonic(2.0, 2048) +
+                  0.125 * build-harmonic(3.0, 2048) +
+                  0.0625 * build-harmonic(4.0, 2048)
+    set *table* = list(*table*, hz-to-step(1.0), #t)
+  end
+
+ +

+Now that we have defined a function, the last step of this example is to +build the wave. The following code calls +mkwave the first time the code is executed (loaded from a file). The second time, the variable *mkwave* will be true, so mkwave will not be invoked: +

+if ! fboundp(quote(*mkwave*)) then
+  begin
+    exec mkwave()
+    set *mkwave* = #t
+  end
+
+ +

+

Wavetables

+When Nyquist starts, several waveforms are created and stored in global variables for convenience. They are: *sine-table*, *saw-table*, and *tri-table*, implementing sinusoid, sawtooth, and triangle waves, respectively. The variable *table* is initialized to *sine-table*, and it is *table* that forms the default wave table for many Nyquist oscillator behaviors. If you want a proper, band-limited waveform, you should construct it yourself, but if you do not understand this sentence and/or you do not mind a bit of aliasing, give *saw-table* and *tri-table* a try. +

+Note that in Lisp and SAL, global variables often start and end with asterisks (*). These are not special syntax, they just happen to be legal characters for names, and their use is purely a convention. +

+

Sequences

+Finally, we define my-note to use the waveform, and play several notes +in a simple score. Note that the function my-note has only one command +(a return command), so it is not necessary to use begin and +end. These are only necessary when the function body consists of a +sequence of statements: +
+define function my-note(pitch, dur)
+  return osc(pitch, dur, *table*)
+

+play seq(my-note(c4, i), my-note(d4, i), my-note(f4, i), + my-note(g4, i), my-note(d4, q)) +

+

+ +Here, my-note is defined to take pitch and duration as parameters; +it calls osc to do the work of generating a waveform, using +*table* as a wave table. +

+The seq function is used to invoke a sequence of behaviors. Each +note is started at the time the previous note finishes. The parameters to +my-note are predefined in Nyquist: c4 is middle C, i (for +eIghth note) is 0.5, and q (for Quarter note) is 1.0. See Section +"Predefined Constants" for a complete description. The result is the sum of +all the computed sounds. +

+Sequences can also be constructed using the at transformation to +specify time offsets. See +sequence_example.htm +demos, sequence for more examples and explanation. +

+

Envelopes

+The next example will illustrate the use of envelopes. In Nyquist, +envelopes are just ordinary sounds (although they normally have a low sample +rate). An envelope is applied to another sound by +multiplication using the mult function. The code shows +the definition of env-note, defined in terms of the +note function in the previous example. In env-note, a 4-phase +envelope is generated using the env function, which is +illustrated in Figure 1. +

+


+
+

+ +

+Figure 1: An envelope generated by the env function. + +


+

+

+; env-note produces an enveloped note.  The duration
+;   defaults to 1.0, but stretch can be used to change
+;   the duration.
+;   Uses my-note, defined above.
+;
+define function env-note(p)
+  return my-note(p, 1.0) *
+         env(0.05, 0.1, 0.5, 1.0, 0.5, 0.4)
+

+; try it out: +; +play env-note(c4) +

+ +While this example shows a smooth envelope multiplied by an audio signal, +you can also multiply audio signals to achieve +what is often called ring modulation. See +the code and description in +demos/scratch_tutorial.htm for an +interesting use of ring modulation to create "scratch" sounds. +

+In the next example, The stretch operator (~) +is used to modify durations: +

+; now use stretch to play different durations
+;
+play seq(seq(env-note(c4), env-note(d4)) ~ 0.25,
+         seq(env-note(f4), env-note(g4)) ~ 0.5,
+         env-note(c4))
+
+ +

+In addition to stretch, there are a number of transformations supported + by Nyquist, +and transformations of abstract behaviors is perhaps the fundamental +idea behind Nyquist. Chapter "Behavioral Abstraction" is devoted to +explaining this concept, and further elaboration can be found elsewhere + (Dannenberg and Frayley 1989). +

+

Piece-wise Linear Functions

+It is often convenient to construct signals in Nyquist using a list of +(time, value) breakpoints which are linearly interpolated to form a smooth +signal. Envelopes created by env are a special case of the more +general piece-wise linear functions created by pwl. Since pwl +is used in some examples later on, we will take a look at pwl +now. The pwl function takes a list of parameters which denote (time, +value) pairs. There is an implicit initial (time, value) pair of (0, 0), +and an implicit final value of 0. There should always be an odd number of +parameters, since the final value (but not the final time) is implicit. +Here are some examples: +
+; symetric rise to 10 (at time 1) and fall back to 0 (at time 2):
+;
+pwl(1, 10, 2)
+

+; a square pulse of height 10 and duration 5. +; Note that the first pair (0, 10) overrides the default initial +; point of (0, 0). Also, there are two points specified at time 5: +; (5, 10) and (5, 0). (The last 0 is implicit). The conflict is +; automatically resolved by pushing the (5, 10) breakpoint back to +; the previous sample, so the actual time will be 5 - 1/sr, where +; sr is the sample rate. +; +pwl(0, 10, 5, 10, 5) +

+; a constant function with the value zero over the time interval +; 0 to 3.5. This is a very degenerate form of pwl. Recall that there +; is an implicit initial point at (0, 0) and a final implicit value of +; 0, so this is really specifying two breakpoints: (0, 0) and (3.5, 0): +; +pwl(3.5) +

+; a linear ramp from 0 to 10 and duration 1. +; Note the ramp returns to zero at time 1. As with the square pulse +; above, the breakpoint (1, 10) is pushed back to the previous sample. +; +pwl(1, 10, 1) +

+; If you really want a linear ramp to reach its final value at the +; specified time, you need to make a signal that is one sample longer. +; The RAMP function does this: +; +ramp(10) ; ramp from 0 to 10 with duration 1 + one sample period +; +; RAMP is based on PWL; it is defined in nyquist.lsp. +; +

+ +

+

Predefined Constants

+ +For convenience and readability, Nyquist pre-defines some constants, mostly +based on the notation of the Adagio score language, as follows: + +

+

More Examples

+More examples can be found in the directory demos, part of the standard +Nyquist release. The file demos/examples_home.htm is an index to all the demo descriptions. In this directory, you will find the following and more: + +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part3.html b/doc/part3.html new file mode 100644 index 0000000..07b9e52 --- /dev/null +++ b/doc/part3.html @@ -0,0 +1,266 @@ +The NyquistIDE Program + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

The NyquistIDE Program

+ +The NyquistIDE program combines many helpful functions and interfaces to help you get the most out of Nyquist. NyquistIDE is implemented in Java, and you will need the Java runtime system or development system installed on your computer to use NyquistIDE. The best way to learn about NyquistIDE is to just use it. This chapter introduces some of the less obvious features. If you are confused by something and you do not find the information you need here, please contact the author. +

+

NyquistIDE Overview

+The NyquistIDE runs the command-line version of Nyquist as a subtask, so everything that works in Nyquist should work when using the NyquistIDE and vice-versa. Input to Nyquist is usually entered in the top left window of the NyquistIDE. When you type return, if the expression or statement appears to be complete, the expression you typed is sent to Nyquist. Output from Nyquist appears in a window below. You cannot type into or edit the output window text. +

+The normal way to use the NyquistIDE is to create or open one or more files. You edit these files and then click the Load button. To load a file, NyquistIDE saves the file, sets the current directory of Nyquist to that of the file, then issues a load command to Nyquist. In this case and several others, you may notice that NyquistIDE sends expressions to Nyquist automatically for evaluation. You can always see the commands and their results in the output window. +

+Notice that when you load a selected file window, NyquistIDE uses setdir to change Nyquist's current directory. This helps to keep the two programs in sync. Normally, you should keep all the files of a project in the same directory and avoid manually changing Nyquist's current directory (i.e. avoid calling setdir in your code). +

+Arranging windows in the NyquistIDE can be time-consuming, and depending on the +operating system, it is possible for a window to get into a position where you +cannot drag it to a new position. The Window:Tile menu command can be used +to automatically lay out windows in a rational way. There is a preference +setting to determine the height of the completion list relative to the height of the output +window. +

+

The Button Bar

+ +There are a number of buttons with frequently-used operations. These are: +

Command Completion

+To help with programming, NyquistIDE maintains a command-completion window. +As you type the first letters of function names, NyquistIDE lists matching +functions and their parameters in the Completion List window. If you click +on an entry in this window, the displayed expression will replace the +incompletely typed function name. A preference allows you to match initial +letters or any substring of the complete function name. This is controlled +by the "Use full search for code completion" preference. +

+In addition, if you right click (or under Mac OS X, hold down the Alt/Option +key and click) on an entry, NyquistIDE will display documentation for the function. +Documentation can come from a local copy or from the online copy (determined +by the "Use online manual instead of local copy" preference). Documentation +can be displayed within the NyquistIDE window or in an external browser (determined +by the "Use window in NyquistIDE for help browser" preference.) Currently, the +external browser option does not seem to locate documentation properly, but +this should be fixed in the future. +

+

Browser

+ + +If you click on the Browse button or use the Window:Browse menu command, +NyquistIDE will display a browser window that is pre-loaded with a number of + Nyquist commands to create sounds. You can adjust parameters, audition +the sounds, and capture the expression that creates the sound. In many +cases, the expression checks to see if necessary functions are defined, +loading files if necessary before playing the sound. If you want to use +a sound in your own program, you can often simplify things by explicitly +loading the required file just once at the beginning of your file. +

+Since Nyquist now supports a mix of Lisp and SAL, you may find yourself in +the position of having code from the browser in one language while you are +working in the other. The best way to handle this is to put the code for +the sound you want into a function defined in a Lisp (.lsp) or SAL +(.sal) file. Load the file (from Lisp, use the sal-load +command to load a SAL file), and call the function from the language of +your choice. +

+

Envelope Editor

+ + + + +The envelope editor allows you graphically to design and edit piece-wise +linear and exponential envelopes. The editor maintains a list of envelopes +and you select the one to edit or delete using the drop down list in the +Saved Envelopes List area. The current envelope appears in the Graphical +Envelope Editor area. You can click to add or drag points. Alternatively, +you can use the Envelope Points window to select and edit any breakpoint +by typing coordinates. The duration of the envelope is controlled by the +Stop field in the Range area, and the vertical axis is controlled by the +Min and Max fields. +

+When you click the Save button, all envelopes are written to Nyquist. +You can then use the envelope by treating the envelope name as a function. +For example, if you define an envelope named "fast-attack," then you +can create the envelope within a Nyquist SAL program by writing +the expression fast-attack(). +

+These edited envelopes are saved to a file named workspace.lsp + in +the current directory. The workspace is Nyquist's mechanism for saving +data of all kinds (see Section "Workspaces"). The normal way to +work with workspaces is to (1) load the workspace, i.e. + load "workspace", as soon as you start Nyquist; (2) invoke +the envelope editor to change values in the workspace; and (3) save the +workspace at any time, especially before you exit NyquistIDE. If you follow +these steps, envelopes will be preserved from session to session, and +the entire collection of envelopes will appear in the editor. Be +sure to make backups of your workspace.lsp file along with your +other project files. +

+The envelope editor can create linear and exponential envelopes. Use the +Type pull-down menu to select the type you want. Envelopes can be created +using default starting and ending values using pwl or pwe, +or you can specify the initial values using pwlv or pwev. +The envelope editor uses pwl or pwe if no point is explicitly +entered as the initial or final point. To create a pwlv or pwev +function, create a point and drag it to the leftmost or rightmost edge +of the graphical editing window. You will see the automatically +generated default starting or ending +point disappear from the graph. +

+Exponential envelopes should never decay to zero. If you enter a zero +amplitude, you will see that the envelope remains at zero to the next +breakpoint. To get an exponential decay to "silence," try using an +amplitude of about 0.001 (about -60dB). To enter small values like +this, you can type them into the Amplitude box and click "Update Point." +

+The Load button refreshes the editor from data saved in the Nyquist +process. Normally, there is no need to use this because the editor +automatically loads data when you open it. +

+

Equalizer Editor

+ +The Equalizer Editor provides a graphical EQ interface for creating and +adjusting equalizers. Unlike the envelope editor, where you can type +any envelope name, equalizers are named eq-0, eq-1, etc., +and you select the equalizer to edit using a pull-down menu. The Set +button should be use to record changes. +

+

UPIC Editor

+The +UPIC Editor is inspired by the UPIC system by Iannis Xenakis at the Centre +d'Edudes de Mathematique et Automatique Musicales (CEMaMu). The UPIC Editor +is accessed by the "Upic Edit" menu item in the "Window" menu of the +NyquistIDE. Once opened, you can draw pitch contours in the main panel by +pressing the left mouse button and dragging with the mouse down. Contours +represent tones in a frequency vs. time coordinate system. Any contour can be +deleted by right-clicking (or shift-clicking on an Apple computer) to +select the contour (indicated by the color red), and typing the Delete key. +

+A collection of contours can be saved to a file and later retrieved using the +items in the File menu (use the File menu in the UPIC Editor window, not in +the main NyquistIDE window.) The file is a SAL program in a special format +that can be parsed by the UPIC Editor. The file can also be loaded +into Nyquist using the File:Load menu item, or by executing a load command +in Nyquist. +

+The panel at the top of the editor offers control over various parameters. +The Name box is a Nyquist variable name. This name takes effect when you +save a file from the UPIC Editor. The variable name is stored in the +file so that when a UPIC Editor-generated file +is loaded into Nyquist, the data is assigned to this variable name. +The data is +a list of contours, where each contour specifies a waveform, an envelope, +and a list of time-frequency coordinates. +

+The next item in the panel is the Waveform box. The Waveform box names a +waveform for a contour. Default waveforms are sinusoid, triangle, and +sawtooth, but you can type in your own names. The currently selected +waveform is stored with the contour when it is created (entered by +drawing). You cannot change or edit the waveform name associated with +a contour once the contour is created, but you can always delete the +contour and replace it. The Envelope box names an envelope for a +contour. The envelope names a Nyquist function. The default, upic-env +is a trapezoid shape with an onset time and offset time of 10ms. As with +waveforms, the envelope is stored with each contour when the contour is +created and cannot be edited. +

+The Stop Time box gives the duration of the drawing area in seconds. +The Min Freq box gives the minimum frequency (at the bottom of the +drawing area), and the Max Freq box gives the maximum frequency (at the +top of the drawing area). The vertical frequency axis can use a linear +scale corresponding to frequency in Hertz or a logarithmic scale +corresponding to semitones. The "linear" checkbox selects the linear +scale. When any of these parameters (described in this paragraph and +delimited by the border labeled "Range" on the control panel) is changed, +you must press the Update Range button for the change to take effect. +

+The Background menu lets you display a grid that indicates pitch locations. +The "C's" item draws a line at C in every visible octave. E.g. middle C +is about 260 Hz, so a reference line will be drawn near 260 Hz. +Lines will be drawn around 130 Hz (an octave below middle C), and around +520 Hz (an octave above middle C), etc. The "GrandStaff" menu item +draws reference lines for each line of the grand staff commonly used +for piano music. The pitches are G2, B2, D3, F3, A3, E4, G4, B4, D5, and +F5. Finally, you can load a picture using the +Background:Load Picture... menu item. Then, the Background:Show Picture +menu item toggles whether the picture is displayed or not. This feature +allows you to trace an image. (For example, see the Sonic Self-Portrait +at http://www.cs.cmu.edu/~rbd.) You may wish to use an image editor +to lighten the image so that superimposed contours will be more visible. +

+Each change to the Range data, background choice, and each entry of a +contour is an action that you can undo or redo with the Undo and Redo +buttons. +

+To convert UPIC data into sound, first load upic.sal and load +a file generated by the UPIC Editor. Now, suppose the variable name +used is upicdata. You can play the data by writing +

+play upic(upicdata)
+
+ +If you created your own names for waveforms or envelopes, you must be +sure that these exist before calling the upic function. Each +waveform must be the name of a variable which is set to a Nyquist +wave table. (See Section
"Waveforms" for information on how +to create a wave table.) Also, each envelope must name a function with +no parameters that will return an amplitude envelope. The following is +the built-in definition for upic-env: +
+define function upic-env()
+  return env(0.01, 0.01, 0.01, 1, 1, 1)
+
+ +To make a custom envelope function named upic-smooth with a 0.2 + second attack and a 0.3 second decay, you could write: +
+define function upic-smooth()
+  return env(0.2, 0.01, 0.3, 1, 1, 1)
+
+ +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part4.html b/doc/part4.html new file mode 100644 index 0000000..f83f30b --- /dev/null +++ b/doc/part4.html @@ -0,0 +1,429 @@ +Behavioral Abstraction + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Behavioral Abstraction

+ +In Nyquist, all functions are subject to +transformations. You can think of transformations as +additional parameters to every function, and functions are free to use these +additional parameters in any way. The set of transformation parameters is +captured in what is referred to as the transformation +environment. (Note that the term +environment is heavily overloaded in computer science. This is yet +another usage of the term.) +

+Behavioral abstraction is the ability of functions to adapt their behavior +to the transformation environment. This environment may contain certain +abstract notions, such as loudness, stretching a sound in time, etc. These +notions will mean different things to different functions. For example, an +oscillator should produce more periods of oscillation in order to stretch +its output. An envelope, on the other hand, might only change the +duration of the sustain portion of the envelope in order to stretch. +Stretching a sample could mean resampling it to change its duration by the +appropriate amount. +

+Thus, transformations in Nyquist are not simply operations on signals. For +example, if I want to stretch a note, it does not make sense to compute the +note first and then stretch the signal. Doing so would cause a drop in the +pitch. Instead, a transformation modifies the transformation +environment in which the note is computed. Think of transformations as +making requests to functions. It is up to the function to carry out the +request. Since the function is always in complete control, it is possible +to perform transformations with "intelligence;" that is, the function can +perform an appropriate transformation, such as maintaining the desired pitch +and stretching only the "sustain" portion +of an envelope to obtain a longer note. +

+

The Environment

+ +The transformation environment consists of a set of special variables. +These variables should not be read directly and should never be set +directly by the programmer. Instead, there are functions to read them, and +they are automatically set and restored by +transformation operators, which will be described below. +

+The transformation environment consists of the following elements. Although +each element has a "standard interpretation," the designer of an +instrument or the composer of a complex behavior is free to interpret the +environment in any way. For example, a change in *loud* may change +timbre more than amplitude, and *transpose* may be ignored by +percussion instruments: +

+

+
+ *warp*
Time transformation, including time shift, +time stretch, and continuous time warp. The value of *warp* is +interpreted as a function from logical (local score) time to physical +(global real) time. Do not access *warp* directly. Instead, use +local-to-global(t) to + convert from a logical (local) time to real (global) time. Most often, +you will call local-to-global(0). Several transformation operators +operate on *warp*, including at (@), stretch (~), +and warp. See also get-duration() and get-warp().

+
*loud*
Loudness, expressed in decibels. The default +(nominal) loudness is 0.0 dB (no change). Do not access *loud* +directly. Instead, use get-loud() to get the current value of +*loud* and either loud or loud-abs to modify it.

+
*transpose*
Pitch transposition, +expressed in +semitones. (Default: 0.0). Do not access *transpose* directly. +Instead, use get-transpose() to get the current value of +*transpose* and either transpose or transpose-abs to +modify it.

+
*sustain*
The "sustain," +"articulation," "duty factor," or amount by which to +separate or overlap sequential notes. For +example, staccato might be expressed with a *sustain* of 0.5, while very +legato playing might be expressed with a *sustain* of 1.2. +Specifically, *sustain* stretches the duration of notes (sustain) +without affecting the inter-onset time (the rhythm). Do not access +*sustain* directly. Instead, use get-sustain() to get the +current value of *sustain* and either sustain or +sustain-abs to modify it.

+
*start*
Start +time of a clipping region. Note: +unlike the previous elements of the environment, *start* has a +precise interpretation: no sound should be generated before *start*. +This is implemented in all the low-level sound functions, so it can +generally be ignored. You can read *start* directly, but use +extract or extract-abs to modify it. Note 2: Due +to some internal confusion between the specified starting time and +the actual starting time of a signal after clipping, *start* +is not fully implemented.

+
*stop*
Stop time of clipping +region. By analogy to +*start*, no sound should be generated after this time. +*start* and +*stop* allow a composer to preview a small section of a work +without computing it from beginning to end. You can read *stop* +directly, but use extract or extract-abs to modify it. + Note: Due to some internal confusion between the specified +starting time and the actual starting time of a signal after +clipping, *stop* is not fully implemented.

+
*control-srate*
Sample +rate of control signals. This environment +element provides the default sample rate for control signals. There is no +formal distinction between a control signal and an audio signal. +You can read *control-srate* directly, but +use control-srate or control-srate-abs to modify it.

+
*sound-srate*
Sample +rate of musical sounds. This environment element provides the +default sample rate for musical sounds. You can +read *sound-srate* directly, but use sound-srate +or sound-srate-abs to modify it.

+

Sequential Behavior

+Previous examples have shown the use of seq, the sequential behavior +operator. We can now explain seq in terms of transformations. +Consider the simple expression: +
+play seq(my-note(c4, q), my-note(d4, i))
+
+ +The idea is to create the first note at time 0, and to start the next +note when the first one finishes. This is all accomplished by manipulating +the environment. In particular, *warp* is modified so that what is +locally time 0 for the second note is transformed, or warped, to the logical +stop time of the first note. +

+One way to understand this in detail is to imagine how it +might be executed: first, *warp* is set to an initial value that has no +effect on time, and my-note(c4, q) is evaluated. A sound is returned and +saved. The sound has an ending time, which in this case will be 1.0 +because the duration q is 1.0. This ending time, 1.0, +is used to construct a new *warp* that has the effect of shifting +time by 1.0. The second note is evaluated, and will start +at time 1. The sound that is +returned is now added to the first sound to form a composite sound, whose +duration will be 2.0. *warp* is restored to its initial value. +

+Notice that the semantics of seq can be expressed in terms of +transformations. To generalize, the operational rule for seq is: +evaluate the first behavior according to the current *warp*. +Evaluate each successive behavior with *warp* modified to shift the +new note's starting time to the ending time of the previous behavior. +Restore *warp* to its original value and return a sound which is the +sum of the results. +

+In the Nyquist implementation, audio samples are only computed when they are +needed, and the second part of the seq is not evaluated until the +ending time (called the logical stop time) of the first part. It is still +the case that when the second part is evaluated, it will see *warp* +bound to the ending time of the first part. +

+A language detail: Even though Nyquist defers evaluation of the second part of the seq, the expression can reference variables according to ordinary +Lisp/SAL scope rules. This is because the seq captures the expression in a closure, which retains all of the variable bindings. +

+

Simultaneous Behavior

+Another operator is sim, which invokes multiple behaviors at the same +time. For example, +
+play 0.5 * sim(my-note(c4, q), my-note(d4, i))
+
+ +will play both notes starting at the same time. +

+The operational rule for sim is: evaluate each behavior at the +current *warp* and return the sum of the results. (In SAL, the +sim function applied to sounds is equivalent to adding them +with the infix + operator. The following section +illustrates two concepts: first, a sound is not a +behavior, and second, the sim operator and and the at +transformation can be used to place sounds in time. +

+

Sounds vs. Behaviors

+The following example loads a sound from a file in the current directory and stores it in a-snd: +
+; load a sound
+;
+set a-snd = s-read(strcat(current-path(), "demo-snd.aiff"))
+

+; play it +; +play a-snd +

+ +

+One +might then be tempted to write the following: +

+play seq(a-snd, a-snd)  ;WRONG!
+
+ +Why is this wrong? Recall +that seq works by modifying *warp*, not by operating on +sounds. So, seq will proceed by evaluating a-snd with +different values of *warp*. However, the result of evaluating +a-snd (a variable) is always the same sound, regardless of the +environment; in this case, the second a-snd should start at time +0.0, just like the first. In this case, after the first sound ends, + Nyquist is unable to "back up" to time zero, so in fact, this will +play two sounds in sequence, but that is a result of an implementation +detail rather than correct program execution. In fact, a future version of +Nyquist might (correctly) stop and report an error when it detects that the +second sound in the sequence has a real start time that is before the +requested one. +

+How then do we obtain a sequence of two sounds properly? +What we really need here is a +behavior that transforms a given sound according to the current +transformation environment. That job is performed by cue. For +example, the following will behave as expected, producing a sequence of two +sounds: +

+play seq(cue(a-snd), cue(a-snd))
+
+ +This example is correct because the second expression will shift the sound + stored in a-snd to start at the end time of the first expression. +

+The lesson here is very important: sounds are not behaviors! Behaviors +are computations that generate sounds according to the transformation +environment. Once a sound has been generated, it can be stored, copied, +added to other sounds, and used in many other operations, but sounds are +not subject to transformations. To transform a sound, use cue, +sound, or control. The differences between these operations +are discussed later. For now, here is a "cue sheet" style score that +plays 4 copies of a-snd: +

+

+; use sim and at to place sounds in time
+;
+play sim(cue(a-snd) @ 0.0,
+         cue(a-snd) @ 0.7,
+         cue(a-snd) @ 1.0,
+         cue(a-snd) @ 1.2)
+
+ +

+

The At Transformation

+The second concept introduced by the previous example is the @ +operation, which shifts the *warp* component of the environment. For +example, +
+cue(a-snd) @ 0.7
+
+ +can be explained operationally as follows: modify *warp* by shifting +it by 0.7 and evaluate cue(a-snd). Return the resulting sound +after restoring *warp* to its original value. Notice how @ +is used inside a sim construct to locate copies of a-snd in +time. This is the standard way to represent a note-list or a cue-sheet in +Nyquist. +

+This also explains why sounds need to be cue'd in order to be shifted +in time or arranged in sequence. If this were not the case, then sim +would take all of its parameters (a set of sounds) and line them up to start +at the same time. But cue(a-snd) @ 0.7 is just a sound, so +sim would "undo" the effect of @, making all of the sounds +in the previous example start simultaneously, in spite of the @! +Since sim respects the intrinsic starting times of sounds, a special +operation, cue, is needed to create a new sound with a new starting +time. +

+

The Stretch Transformation

+In addition to At (denoted in SAL by the @ operator, the Stretch +transformation is very important. It appeared in the introduction, and +it is denoted in SAL by the ~ operator (or in LISP by the stretch +special form). Stretch also operates on the *warp* component of +the environment. For example, +
+osc(c4) ~ 3
+
+ +does the following: modify *warp*, scaling the degree of +"stretch" by 3, and evaluate osc(c4). The osc behavior +uses the stretch factor to determime the duration, so it will return +a sound that is 3 seconds long. Restore *warp* to its original +value. Like At, Stretch only affects behaviors. a-snd ~ 10 is +equivalent to a-snd because a-snd is a sound, not a +behavior. Behaviors are functions that compute sounds according to +the environment and return a sound. +

+

Nested Transformations

+Transformations can be combined using nested expressions. For example, +
+sim(cue(a-snd),
+    loud(6.0, cue(a-snd) @ 3))
+
+ +scales the amplitude as well as shifts the second entrance of a-snd. +

+Why use loud instead of simply multiplying a-snd by some +scale factor? Using loud gives +the behavior the chance to implement the abstract +property loudness in an appropriate way, e.g. by including timbral +changes. In this case, the behavior is cue, which implements +loudness by simple amplitude scaling, so the result is equivalent +to multiplication by db-to-linear(6.0). +

+Transformations can also be applied to groups of behaviors: +

+loud(6.0, sim(cue(a-snd) @ 0.0,
+              cue(a-snd) @ 0.7))
+
+ +

+

Defining Behaviors

+Groups of behaviors can be named using define (we already saw this +in the definitions of my-note and env-note). Here is another example +of a behavior definition and its use. The definition has one parameter: +
+define function snds(dly)
+  return sim(cue(a-snd) @ 0.0,
+             cue(a-snd) @ 0.7,
+             cue(a-snd) @ 1.0,
+             cue(a-snd) @ (1.2 + dly))
+

+play snds(0.1) +play loud(0.25, snds(0.3) ~ 0.9) +

+ +In the last line, snds is transformed: the transformations will apply +to the cue behaviors within snds. The loud +transformation will scale the sounds by 0.25, and the stretch +(~) will +apply to the shift (@) amounts 0.0, 0.7, 1.0, +and 1.2 + dly. The sounds themselves (copies of a-snd) will +not be stretched because cue never stretches sounds. +

+Section "Transformations" describes the full set of transformations. +

+

Overriding Default Transformations

+In Nyquist, behaviors are the important abstraction mechanism. +A behavior represents a class of related functions or sounds. For example, +a behavior can represent a musical note. When a note is stretched, it +usually means that the tone sustains for more oscillations, but if the +"note" is a drum roll, the note sustains by more repetitions of the +component drum strokes. The concept of sustain is so fundamental that +we do not really think of different note durations as being different +instances of an abstract behavior, but in a music programming language, +we need a way to model these abtract behaviors. As the tone and drum +roll examples show, there is no one right way to "stretch," so the +language must allow users to define exactly what it means to stretch. +By extension, the Nyquist programmer can define how all of the +transformations affect different behaviors. +

+To make programming easier, almost all Nyquist sounds are constructed +from primitive behaviors that obey the environment in obvious ways: +Stretch transformations make things longer and At transformations shift +things in time. But sometimes you have to override the default behaviors. +Maybe the attack phase of an envelope should not stretch when the note +is stretched, or maybe when you stretch a trill, you should get more +notes rather than a slower trill. +

+To override default behaviors, you almost always follow the same +programming pattern: first, capture the environment in a local variable; +then, use one of the absolute transformations to "turn off" the +environment's effect and compute the sound as desired. The following +example creates a very simple envelope with a fixed rise time to +illustrate the technique. +

+define function two-phase-env(rise-time)
+  begin
+    with dur = get-duration(1)
+    return pwl(rise-time, 1, dur) ~~ 1.0
+  end
+
+ +To "capture the environment in a local variable," a with +construct is used to create the local variable dur and set +it to the value of get-duration(1), which answers the question: +"If I apply use the environment to stretch something whose nominal +duration is 1, what is the resulting duration?" (Since time transformations +can involve continuous time deformations, this question is not as +simple as it may sound, so please use the provided function rather +than peeking inside the *warp* structure and trying to do it +yourself.) Next, we "turn off" stretching using the stretch-abs +form, which in SAL is denoted by the ~~ operator. +Finally, we are ready to compute the envelope using pwl. Here, +we use absolute durations. The first breakpoint is at rise-time, +so the attack time is given by the rise-time parameter. The +pwl decays back to zero at time dur, so the overall +duration matches the duration expected from the environment encountered +by this instance of two-phase-env. Note, however, that since +the pwl is evaluated in a different environment established +by ~~, it is not stretched (or perhaps more accurately, it is +stretched by 1.0). This is good because it means rise-time will +not be stretched, but we must be careful to extend the envelope to +dur so that it has the expected duration. +

+

Sample Rates

+ +The global environment contains *sound-srate* and +*control-srate*, which determine the sample rates of sounds and +control signals. These can be overridden at any point by the +transformations sound-srate-abs and control-srate-abs; for +example, +
+sound-srate-abs(44100.0, osc(c4)
+
+ +will compute a tone using a 44.1Khz sample rate even if the default rate +is set to something different. +

+ +As with other components of the environment, you should never change +*sound-srate* or *control-srate* directly. + The global environment is determined by two additional +variables: *default-sound-srate* and *default-control-srate*. +You can add lines like the following to your init.lsp file to change +the default global environment: +

+(setf *default-sound-srate* 44100.0)
+(setf *default-control-srate* 1102.5)
+
+ +You can also do this using preferences in NyquistIDE. +If you have already started Nyquist and want to change the defaults, the +preferences or the following functions can be used: +
+exec set-control-srate(1102.5)
+exec set-sound-srate(22050.0)
+
+ +These modify the default values and reinitialize the Nyquist environment. +

+


+
Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part5.html b/doc/part5.html new file mode 100644 index 0000000..5216541 --- /dev/null +++ b/doc/part5.html @@ -0,0 +1,313 @@ +Continuous Transformations and Time Warps + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Continuous Transformations and Time Warps

+ +Nyquist transformations were discussed in the previous chapter, but all of +the examples used scalar values. For example, we saw the loud +transformation used to change loudness by a fixed amount. What if we want +to specify a crescendo, where the loudness changes gradually over time? +

+It turns out that all transformations can accept signals as well as numbers, +so transformations can be continuous over time. This raises some +interesting questions about how to interpret continuous transformations. +Should a loudness transformation apply to the internal details of a note or +only affect the initial loudness? It might seem unnatural for a decaying +piano note to perform a crescendo. On the other hand, a sustained +trumpet sound should probably crescendo continuously. In the case of time +warping (tempo changes), it might be best for a drum roll to maintain a +steady rate, a trill may or may not change rates with tempo, and a run of +sixteenth notes will surely change its rate. +

+These issues are complex, and Nyquist cannot hope to automatically do the +right thing in all cases. However, the concept of behavioral abstraction +provides an elegant solution. Since transformations merely modify the +environment, behaviors are not forced to implement any particular style of +transformation. Nyquist is designed so that the default transformation is +usually the right one, but it is always possible to override the default +transformation to achieve a particular effect. +

+

Simple Transformations

+The "simple" transformations affect some parameter, but have no effect on time itself. The simple transformations that support continuously changing parameters are: sustain, loud, and transpose. +

+As a first example, Let us use transpose to create a chromatic scale. +First define a sequence of tones at a steady pitch. The seqrep +"function" works like seq except that it creates copies of a sound +by evaluating an expression multiple times. Here, i takes on 16 values +from 0 to 15, and the expression for the sound could potentially use i. +Technically, seqrep is not really a function but an abbreviation for +a special kind of loop construct. +

+define function tone-seq()
+  return seqrep(i, 16,
+                osc-note(c4) ~ 0.25)
+
+ +Now define a linearly increasing ramp to serve as a transposition function: + +define function pitch-rise() + return sustain-abs(1.0, 16 * ramp() ~ 4) + +This ramp has a duration of 4 seconds, and over that interval it rises from +0 to 16 (corresponding to the 16 semitones we want to transpose). The ramp +is inside a sustain-abs transformation, which prevents a sustain +transformation from having any effect on the ramp. (One of the drawbacks of +behavioral abstraction is that built-in behaviors sometimes do the wrong +thing implicitly, requiring some explicit correction to turn off the +unwanted transformation.) Now, +pitch-rise is used to transpose tone-seq: + +define function chromatic-scale() + return transpose(pitch-rise(), tone-seq()) + +

+Similar transformations can be constructed to change the sustain or "duty +factor" of notes and their loudness. The following expression plays the +chromatic-scale behavior with increasing note durations. The +rhythm is unchanged, but the note length changes from staccato to legato: + +play sustain((0.2 + ramp()) ~ 4, + chromatic-scale()) + +The resulting sustain function will ramp from 0.2 to 1.2. A sustain of 1.2 +denotes a 20 percent overlap between notes. The sum has a stretch +factor of 4, so it will extend over the 4 second duration of +chromatic-scale. +

+If you try this, you will discover that the chromatic-scale no longer +plays a chromatic scale. You will hear the first 4 notes going up in intervals +of 5 semitones (perfect fourths) followed by repeated pitches. What +is happening is that the sustain operation applies to +pitch-rise in addition to tone-seq, so now the 4s +ramp from 0 to 16 becomes a 0.8s ramp. To fix this problem, we need to +shield pitch-rise from the effect of sustain using the +sustain-abs transformation. Here is a corrected version of +chromatic-scale: + +define function chromatic-scale() + return transpose(sustain-abs(1, pitch-rise()), tone-seq()) + +

+What do these transformations mean? How did the system know to produce a +pitch rise rather than a continuous glissando? This all relates to the idea +of behavioral abstraction. It is possible to design sounds that do +glissando under the transpose transform, and you can even make sounds that +ignore transpose altogether. As explained in Chapter +"Behavioral Abstraction", the transformations modify the +environment, and behaviors can reference the environment to determine what +signals to generate. All built-in functions, such as osc, have a +default behavior. +

+The default behavior for sound primitives under transpose, +sustain, and loud transformations is +to sample the environment at the beginning of the +note. Transposition is not quantized to semitones or any other scale, +but in our example, we arranged for the transposition to work out to integer +numbers of semitones, so we obtained a chromatic scale anyway. +

+Transposition only applies to the oscillator and sampling primitives +osc, partial, sampler, sine, fmosc, +and amosc. Sustain applies to osc, env, ramp, +and pwl. (Note that partial, amosc, and +fmosc get their durations +from the modulation signal, so they may indirectly depend upon the sustain.) +Loud applies to osc, sampler, cue, sound, +fmosc, and amosc. (But not pwl or env.) +

+

Time Warps

+The most interesting transformations have to do with transforming time +itself. The warp transformation provides a mapping function from +logical (score) time to real time. The slope of this function tells us how +many units of real time are covered by one unit of score time. This is +proportional to 1/tempo. A higher slope corresponds to a slower tempo. +

+To demonstrate warp, we will define a time warp function using +pwl: +

+define function warper()
+  return pwl(0.25, .4, .75, .6, 1.0, 1.0, 2.0, 2.0, 2.0)
+
+ +This function has an initial slope of .4/.25 = 1.6. It may be easier to +think in reciprocal terms: the initial tempo is .25/.4 = .625. Between 0.25 +and 0.75, the tempo is .5/.2 = 2.5, and from 0.75 to 1.0, the tempo is again +.625. It is important for warp functions to completely span the interval of +interest (in our case it will be 0 to 1), and it is safest to extend a bit +beyond the interval, so we extend the function on to 2.0 with a +tempo of 1.0. Next, we stretch and scale the warper function to +cover 4 seconds of score time and 4 seconds of real time: +
+define function warp4()
+  return 4 * warper() ~ 4
+
+ +

+


+
+

+ +

+Figure 2: The result of (warp4), intended to map 4 seconds of +score time into 4 seconds of real time. The function extends beyond 4 +seconds (the dashed lines) to make sure the function is well-defined at +location (4, 4). Nyquist sounds are ordinarily open on the right. + +


+

+Figure 2 shows a plot of this warp function. Now, we can +warp the tempo of the tone-seq defined above using warp4: +

+play warp(warp4(), tone-seq())
+
+ +Figure 3 shows the result graphically. Notice that the +durations of the tones are warped as well as their onsets. Envelopes are +not shown in detail in the figure. Because of the way env is +defined, the tones will have constant attack and decay times, and the +sustain will be adjusted to fit the available time. +

+


+
+

+ +

+Figure 3: When (warp4) is applied to (tone-seq-2), the note onsets and durations are warped. + +


+

+

Abstract Time Warps

+We have seen a number of examples where the default behavior did the +"right thing," making the code straightforward. This is not always the +case. Suppose we want to warp the note onsets but not the durations. We +will first look at an incorrect solution and discuss the error. Then we +will look at a slightly more complex (but correct) solution. +

+The default behavior for most Nyquist built-in functions is to sample the +time warp function at the nominal starting and ending score times of the +primitive. For many built-in functions, including osc, the starting +logical time is 0 and the ending logical time is 1, so the time warp +function is evaluated at these points to yield real starting and stopping +times, say 15.23 and 16.79. The difference (e.g. 1.56) becomes the signal +duration, and there is no internal time warping. The pwl function +behaves a little differently. Here, each breakpoint is warped individually, +but the resulting function is linear between the breakpoints. +

+A consequence of the default behavior is that notes stretch when the tempo +slows down. Returning to our example, recall that we want to warp only the +note onset times and not the duration. One would think that the following +would work: +

+define function tone-seq-2 ()
+  return seqrep(i, 16,
+                osc-note(c4) ~~ 0.25)
+

+play warp(warp4(), tone-seq-2()) +

+ +Here, we have redefined tone-seq, renaming it to tone-seq-2 +and changing the stretch (~) to absolute stretch (~~). The +absolute stretch should override the warp function and produce a fixed +duration. +

+If you play the example, you will hear steady +sixteenths and no tempo changes. What is wrong? In a sense, the "fix" +works too well. Recall that sequences (including seqrep) determine +the starting time of the next note from the logical stop time of the +previous sound in the sequence. When we forced the stretch to 0.25, we also +forced the logical stop time to 0.25 real seconds from the beginning, so +every note starts 0.25 seconds after the previous one, resulting in a +constant tempo. +

+Now let us design a proper solution. The trick is to use absolute +stretch (~~) +as before to control the duration, but to restore the logical stop time to a +value that results in the proper inter-onset time interval: +

+define function tone-seq-3()
+  return seqrep(i, 16,
+                set-logical-stop(osc-note(c4) ~~ 0.25, 0.25))
+

+play warp(warp4(), tone-seq-3()) +

+ +Notice the addition of set-logical-stop enclosing the +absolute stretch (~~) expression to set the logical + stop time. A possible +point of confusion here is that the logical stop time is set to 0.25, the +same number given to ~~! How does setting the logical stop +time to 0.25 result in a tempo change? When used within a warp +transformation, the second argument to set-logical-stop refers to +score time rather than real time. Therefore, the score duration of +0.25 is warped into real time, producing tempo changes according to the +enviroment. Figure 4 illustrates the result graphically. +

+


+
+

+ +

+Figure 4: When (warp4) is applied +to (tone-seq-3), the note onsets are warped, but not the duration, +which remains a constant 0.25 seconds. In the fast middle section, this +causes notes to overlap. Nyquist will sum (mix) them. + +


+

+

Nested Transformations

+Transformations can be nested. In particular, a simple transformation such +as transpose can be nested within a time warp transformation. Suppose we +want to warp our chromatic scale example with the warp4 time warp +function. As in the previous section, we will show an erroneous simple +solution followed by a correct one. +

+The simplest approach to a nested transformation is to simply combine them +and hope for the best: +

+play warp(warp4(),
+          transpose(pitch-rise(), tone-seq()))
+
+ +This example will not work the way you might expect. Here is why: the warp +transformation applies to the (pitch-rise) expression, which is +implemented using the ramp function. The default +behavior of ramp is to interpolate linearly (in real time) between two points. +Thus, the "warped" ramp function will not truly reflect the internal +details of the intended time warp. When the notes are moving faster, they +will be closer together in pitch, and the result is not chromatic. +What we need is a way to properly +compose the warp and ramp functions. If we continuously warp the ramp function +in the same way as the note sequence, a chromatic scale should be obtained. +This will lead to a correct solution. +

+Here is the modified code to properly warp a transposed sequence. Note that +the original sequence is used without modification. The only complication +is producing a properly warped transposition function: +

+  play warp(warp4(),
+            transpose(
+              control-warp(get-warp(),
+                           warp-abs(nil, pitch-rise())),
+              tone-seq()))
+
+ +To properly warp the pitch-rise transposition function, we use +control-warp, which applies a warp function to a function of score time, +yielding a function of real time. We need to pass the desired function +to control-warp, so we fetch it from the environment with +get-warp(). Finally, since the warping is done here, we want to +shield the pitch-rise expression from further warping, so we enclose +it in warp-abs(nil, ...). +

+ An aside: This last example illustrates a difficulty in the design of +Nyquist. To support behavioral abstraction universally, we must rely upon +behaviors to "do the right thing." In this case, we would like the +ramp function to warp continuously according to the environment. But +this is inefficient and unnecessary in many other cases where ramp +and especially pwl are used. (pwl warps its breakpoints, but still interpolates linearly between them.) Also, if the default behavior of +primitives is to warp in a continuous manner, this makes it difficult to +build custom abstract behaviors. The final vote is not in. +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part6.html b/doc/part6.html new file mode 100644 index 0000000..a903acc --- /dev/null +++ b/doc/part6.html @@ -0,0 +1,573 @@ +More Examples + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

More Examples

This chapter explores Nyquist through additional examples. The reader may +wish to browse through these and move on to Chapter "Nyquist Functions", which +is a reference section describing Nyquist functions. +

+

Stretching Sampled Sounds

This example illustrates how to stretch a sound, resampling it in the process. +Because sounds in Nyquist are values that contain the sample rate, start +time, etc., use sound to convert a sound into a behavior that can be +stretched, e.g. sound(a-snd). This behavior stretches a sound according +to the stretch factor in the environment, set using stretch. For +accuracy and efficiency, Nyquist does not resample a stretched sound until +absolutely necessary. The force-srate function is used to resample +the result so that we end up with a "normal" sample rate that is playable +on ordinary sound cards. +

+

+; if a-snd is not loaded, load sound sample:
+;
+if not(boundp(quote(a-snd))) then
+  set a-snd = s-read("demo-snd.aiff")
+

+; the SOUND operator shifts, stretches, clips and scales +; a sound according to the current environment +; +define function ex23() + play force-srate(*default-sound-srate*, sound(a-snd) ~ 3.0) +

+define function down() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.2, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.6)) +play down() +

+; that was so much fun, let's go back up: +; +define function up() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.5, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.2)) +

+; and write a sequence +; +play seq(down(), up(), down()) +

+ +

+Notice the use of the sound behavior as opposed to cue. The +cue behavior shifts and scales its sound according to *warp* +and *loud*, but it does not change the duration or resample the +sound. In contrast, sound not only shifts and scales its sound, but +it also stretches it by resampling or changing the effective sample rate + according to *warp*. If +*warp* is a continuous warping function, then the sound will be +stretched by time-varying amounts. +(The *transpose* element of the environment is +ignored by both cue and sound.) +

+Note: sound may use linear interpolation rather than a high-quality resampling algorithm. In some cases, this may introduce errors audible as noise. Use resample (see Section "Sound Synthesis") for high-quality interpolation. +

+In the functions up and down, the *warp* is set by +stretch (~), which simply scales time by a constant scale factor. In this case, +sound can "stretch" the signal simply by changing the sample rate without +any further computation. When seq tries to add the signals together, it +discovers the sample rates do not match and uses linear interpolation to adjust +all sample rates to match that of the first sound in the sequence. The result of +seq is then converted using force-srate to convert the sample rate, +again using linear interpolation. +It would be slightly better, from a computational +standpoint, to apply force-srate individually +to each stretched sound rather +than applying force-srate after seq. +

+Notice that the overall duration of sound(a-snd) ~ 0.5 will +be half the duration of a-snd. +

+

Saving Sound Files

So far, we have used the play command to play a sound. The +play command works by writing a sound to a file while +simultaneously playing it. +This can be done one step at a time, and +it is often convenient to save a sound to a particular file for later use: +
+; write the sample to a file, 
+;    the file name can be any Unix filename.  Prepending a "./" tells
+;    s-save to not prepend *default-sf-dir*
+;
+exec s-save(a-snd, 1000000000, "./a-snd-file.snd")
+

+; play a file +; play command normally expects an expression for a sound +; but if you pass it a string, it will open and play a +; sound file +play "./a-snd-file.snd" +

+; delete the file (do this with care!) +; only works under Unix (not Windows) +exec system("rm ./a-snd-file.snd") +

+; now let's do it using a variable as the file name +; +set my-sound-file = "./a-snd-file.snd" +

+exec s-save(a-snd, 1000000000, my-sound-file) +

+; play-file is a function to open and play a sound file +exec play-file(my-sound-file) +

+exec system(strcat("rm ", my-sound-file)) +

+ +This example shows how s-save can be used to save a sound to a file. +

+This example also shows how the system function can be used to invoke +Unix shell commands, such as a command to play a file or remove it. +Finally, notice that strcat can be used to concatenate a command name +to a file name to create a complete command that is then passed to +system. (This is convenient if the sound file name is stored in a +parameter or variable.) +

+

Memory Space and Normalization

+ + +Sound samples take up lots of memory, and often, there is not enough primary (RAM) memory to hold a complete composition. For this reason, Nyquist can compute sounds incrementally, saving the final result on disk. However, Nyquist can also save sounds in memory so that they can be reused efficiently. In general, if a sound is saved in a global variable, memory will be allocated as needed to save and reuse it. +

+The standard way to compute a sound and write it to disk is to pass an expression to the play command: +

+play my-composition()
+
+ +

+ +Often it is nice to normalize sounds so that they use the full available +dynamic range of 16 bits. Nyquist has an automated facility to help with +normalization. By default, Nyquist computes up to 1 million samples (using +about 4MB of memory) looking for the peak. The entire sound is normalized so +that this peak will not cause clipping. If the sound has less than 1 million +samples, or if the first million samples are a good indication of the overall +peak, then the signal will not clip. +

+With this automated normalization technique, you can choose the desired +peak value by setting *autonorm-target*, which is initialized to 0.9. +The number of samples examined is *autonorm-max-samples*, initially +1 million. You can turn this feature off by executing: +

+exec autonorm-off()
+
+ +and turn it back on by typing: +
+exec autonorm-on()
+
+ +This normalization technique is in effect when *autonorm-type* is +quote(lookahead), which is the default. +

+An alternative normalization method uses the peak value from the previous +call to play. After playing a file, Nyquist can adjust an internal +scale factor so that if you play the same file again, the peak amplitude +will be *autonorm-target*, which is initialized to 0.9. This can +be useful if you want to carefully normalize a big sound that does not +have its peak near the beginning. To select this style of normalization, +set *autonorm-type* to the (quoted) atom quote(previous). +

+You can also create your own normalization method in Nyquist. +The peak function computes the maximum value of a sound. +The peak value is also returned from the play macro. You can +normalize in memory if you have enough memory; otherwise you can compute +the sound twice. The two techniques are illustrated here: +

+; normalize in memory.  First, assign the sound to a variable so
+; it will be retained:
+set mysound = sim(osc(c4), osc(c5))
+; now compute the maximum value (ny:all is 1 giga-samples, you may want a
+; smaller constant if you have less than 4GB of memory:
+set mymax = snd-max(mysound, NY:ALL)
+display "Computed max", mymax
+; now write out and play the sound from memory with a scale factor:
+play mysound * (0.9 / mymax)
+

+; if you don't have space in memory, here's how to do it: +define function myscore() + return sim(osc(c4), osc(c5)) +; compute the maximum: +set mymax = snd-max(list(quote(myscore)), NY:ALL) +display "Computed max", mymax +; now we know the max, but we don't have a the sound (it was garbage +; collected and never existed all at once in memory). Compute the sound +; again, this time with a scale factor: +play myscore() * (0.9 / mymax) +

+ +

+You can also write a sound as a floating point file. This +file can then be converted to 16-bit integer with the proper scaling +applied. If a long computation was involved, it should be much faster +to scale the saved sound file than to recompute the sound from scratch. +Although not implemented yet in Nyquist, some header formats can +store maximum amplitudes, and some soundfile player programs can +rescale floating point files on the fly, allowing normalized +soundfile playback without an extra normalization pass (but at a cost +of twice the disk space of 16-bit samples). +You can use Nyquist to rescale a floating point file and +convert it to 16-bit samples for playback. +

+

Frequency Modulation

+The next example uses the Nyquist frequency modulation behavior fmosc +to generate various sounds. The parameters to fmosc are: +
+fmosc(pitch modulator table phase)
+
+ +Note that pitch is the number of half-steps, e.g. c4 has the value of 60 which is middle-C, and phase is in degrees. Only the first two parameters are required: +
+; make a short sine tone with no frequency modulation
+;
+play fmosc(c4, pwl(0.1))
+

+; make a longer sine tone -- note that the duration of +; the modulator determines the duration of the tone +; +play fmosc(c4, pwl(0.5)) +

+ +In the example above, pwl (for Piece-Wise Linear) is used to generate +sounds that are zero for the durations of 0.1 and 0.5 seconds, +respectively. In effect, we are using an FM oscillator with no modulation +input, and the result is a sine tone. The duration of the modulation +determines the duration of the generated tone (when the modulation signal +ends, the oscillator stops). +

+The next example uses a more interesting modulation function, a ramp from +zero to C4, expressed in hz. More explanation of pwl is in +order. This operation constructs a piece-wise linear function sampled at +the *control-srate*. The first breakpoint is always at (0, +0), so the first two parameters give the time and value of the second +breakpoint, the second two parameters give the time and value of the third +breakpoint, and so on. The last breakpoint has a value of 0, so only +the time of the last breakpoint is given. In this case, we want the ramp to +end at C4, so we cheat a bit by having the ramp return to zero +"almost" instantaneously between times 0.5 and 0.501. +

+The pwl behavior always expects an odd number of parameters. The +resulting function is shifted and stretched linearly according to +*warp* in the environment. Now, here is the example: +

+; make a frequency sweep of one octave; the piece-wise linear function
+; sweeps from 0 to (step-to-hz c4) because, when added to the c4
+; fundamental, this will double the frequency and cause an octave sweep.
+;
+play fmosc(c4, pwl(0.5, step-to-hz(c4),  0.501))
+
+ +

+The same idea can be applied to a non-sinusoidal carrier. Here, we assume that *fm-voice* is predefined (the next section shows how to define it): +

+; do the same thing with a non-sine table
+;
+play fmosc(cs2, pwl(0.5, step-to-hz(cs2), 0.501),
+           *fm-voice*, 0.0)
+
+ +

+The next example shows how a function can be used to make a special +frequency modulation contour. In this case the contour generates a sweep +from a starting pitch to a destination pitch: +

+; make a function to give a frequency sweep, starting
+; after <delay> seconds, then sweeping from <pitch-1>
+; to <pitch-2> in <sweep-time> seconds and then
+; holding at <pitch-2> for <hold-time> seconds.
+;
+define function sweep(delay, pitch-1, sweep-time, 
+                      pitch-2, hold-time)
+  begin
+    with interval = step-to-hz(pitch-2) - step-to-hz(pitch-1)
+    return pwl(delay, 0.0,
+               ; sweep from pitch 1 to pitch 2
+               delay + sweep-time, interval,
+               ; hold until about 1 sample from the end
+               delay + sweep-time + hold-time - 0.0005, 
+               interval,
+               ; quickly ramp to zero (pwl always does this,
+               ;    so make it short)
+               delay + sweep-time + hold-time)
+  end
+

+; now try it out +; +play fmosc(cs2, sweep(0.1, cs2, 0.6, gs2, 0.5), + *fm-voice*, 0.0) +

+ +

+FM can be used for vibrato as well as frequency sweeps. Here, we use the +lfo function to generate vibrato. The lfo operation is +similar to osc, except it generates sounds at the +*control-srate*, and the parameter is hz rather than a pitch: +

+play fmosc(cs2, 10.0 * lfo(6.0), *fm-voice*, 0.0)
+
+ +

+What kind of manual would this be without the obligatory FM sound? Here, a +sinusoidal modulator (frequency C4) is multiplied by a slowly increasing +ramp from zero to 1000.0. +

+set modulator = pwl(1.0, 1000.0, 1.0005) * 
+                osc(c4)
+; make the sound
+play fmosc(c4, modulator)
+
+ +

+For more simple examples of FM in Nyquist, see + +demos/warble_tutorial.htm. Another interesting FM sound +reminiscent of "scratching" can be found with a detailed explanation +in demos/scratch_tutorial.htm. +. +

+

Building a Wavetable

+In Section "Waveforms", we saw how to synthesize a wavetable. A +wavetable for osc also can be extracted from any sound. This is +especially interesting if the sound is digitized from some external sound +source and loaded using the s-read function. Recall that a table +is a list consisting of a sound, the pitch of that sound, and T (meaning the +sound is periodic). +

+In the following, a sound is first read from the file demo-snd.nh. +Then, the extract function is used +to extract the portion of the sound between 0.110204 and 0.13932 seconds. +(These numbers might be obtained by first plotting the sound and estimating +the beginning and end of a period, or by using some software to look for +good zero crossings.) The result of extract becomes the first +element of a list. The next element is the pitch (24.848422), and the last +element is T. The list is assigned to *fm-voice*. +

+if not(boundp(quote(a-snd))) then
+  set a-snd = s-read("demo-snd.aiff")
+

+set *fm-voice* = list(extract(0.110204, 0.13932, cue(a-snd)), + 24.848422, + #T) +

+ +

+The file +demos/examples.sal contains an extensive example of how to locate +zero-crossings, extract a period, build a waveform, and generate a tone from it. (See ex37 through ex40 in the file.) +

+

Filter Examples

Nyquist provides a variety of filters. All of these filters take either +real numbers or signals as parameters. If you pass a signal as a filter +parameter, the filter coefficients are recomputed at the sample rate of the +control signal. Since filter coefficients are generally expensive to +compute, you may want to select filter control rates carefully. Use +control-srate-abs (Section "Transformations") to specify +the default control sample rate, or use force-srate (Section +"Sound Synthesis") to resample a signal before passing it to a filter. +

+Before presenting examples, let's generate some unfiltered white noise: +

+play noise()
+
+ +Now low-pass filter the noise with a 1000Hz cutoff: +
+play lp(noise(), 1000.0)
+
+ +The high-pass filter is the inverse of the low-pass: +
+play hp(noise(), 1000.0)
+
+ +

+Here is a low-pass filter sweep from 100Hz to 2000Hz: +

+play lp(noise(), pwl(0.0, 100.0, 1.0, 2000.0, 1.0))
+
+ +And a high-pass sweep from 50Hz to 4000Hz: +
+play hp(noise(), pwl(0.0, 50.0, 1.0, 4000.0, 1.0))
+
+ +

+The band-pass filter takes a center frequency and a bandwidth parameter. +This example has a 500Hz center frequency with a 20Hz bandwidth. The scale +factor is necessary because, due to the resonant peak of the filter, the +signal amplitude exceeds 1.0: +

  
+play reson(10.0 * noise(), 500.0, 20.0, 1)
+
+ +In the next example, the center frequency is swept from 100 to 1000Hz, using a constant 20Hz bandwidth: +
+play reson(0.04 * noise(),
+           pwl(0.0, 200.0, 1.0, 1000.0, 1.0),
+           20.0)
+
+ +

+For another example with explanations, see + + +demos/wind_tutorial.htm. +

+

DSP in Lisp

+In almost any +signal processing system, the vast majority of computation +takes place in the inner loops of DSP algorithms, and Nyquist is designed so +that these time-consuming inner loops are in highly-optimized +machine code rather than relatively slow interpreted lisp code. As a result, +Nyquist typically spends 95% of its time in these inner loops; the overhead +of using a Lisp interpreter is negligible. +

+The drawback is that Nyquist must provide the DSP operations you need, or +you are out of luck. When Nyquist is found lacking, you can either write a +new primitive signal operation, or you can perform DSP in Lisp code. Neither +option is recommended for inexperienced programmers. Instructions for +extending Nyquist are given in Appendix "Extending Nyquist". This section +describes the process of writing a new signal processing function in Lisp. +

+Before implementing a new DSP function, you should decide which approach is +best. First, figure out how much of the new function can be implemented +using existing Nyquist functions. For example, you might think that a +tapped-delay line would require a new function, but in fact, it can be +implemented by composing sound transformations to accomplish delays, scale +factors for attenuation, and additions to combine the intermediate results. +This can all be packaged into a new Lisp function, making it easy to use. +If the function relies on built-in DSP primitives, it will execute very +efficiently. +

+Assuming that built-in functions cannot be used, try to define a new +operation that will be both simple and general. Usually, it makes sense to +implement only the kernel of what you need, combining it with existing +functions to build a complete instrument or operation. For example, if you +want to implement a physical model that requires a varying breath pressure +with noise and vibrato, plan to use Nyquist functions to add a basic +pressure envelope to noise and vibrato signals to come up with a composite +pressure signal. Pass that signal into the physical model rather than +synthesizing the envelope, noise, and vibrato within the model. This not +only simplifies the model, but gives you the flexibility to use all of +Nyquist's operations to synthesize a suitable breath pressure signal. +

+Having designed the new "kernel" DSP operation that must be implemented, +decide whether to use C or Lisp. (At present, SAL is not a good option +because it has no support for object-oriented programming.) +To use C, you must have a C compiler, the +full source code for Nyquist, and you must learn about extending Nyquist by +reading Appendix "Extending Nyquist". This is the more complex approach, but +the result will be very efficient. A C implementation will deal properly +with sounds that are not time-aligned or matched in sample rates. +To use Lisp, you must learn something +about the XLISP object system, and the result will be about 50 times slower +than C. Also, it is more difficult to deal with time alignment and +differences in sample rates. +The remainder of this section gives an example of a Lisp version of +snd-prod to illustrate how to write DSP functions for Nyquist in Lisp. +

+The snd-prod function is the low-level multiply routine. It has two +sound parameters and returns a sound which is the product of the two. To +keep things simple, we will assume that two sounds to be multiplied have a +matched sample rate and matching start times. The DSP algorithm for each +output sample is simply to fetch a sample from each sound, multiply them, +and return the product. +

+To implement snd-prod in Lisp, three components are required: +

    +
  1. +An object is used to store the two parameter sounds. This object will be +called upon to yield samples of the result sound; +
  2. Within the object, the snd-fetch routine is used to fetch samples +from the two input sounds as needed; +
  3. The result must be of type SOUND, so snd-fromobject is used +to create the result sound. +
+

+The combined solution will work as follows: The result is a value of type +sound that retains a reference to the object. When Nyquist needs +samples from the sound, it invokes the sound's "fetch" function, which in +turn sends an XLISP message to the object. The object will use +snd-fetch to get a sample from each stored sound, multiply the +samples, and return a result. +

+Thus the goal is to design an XLISP object that, in response to a +:next message will return a proper sequence of samples. When the +sound reaches the termination time, simply return NIL. +

+The XLISP manual (see Appendix "XLISP: An Object-oriented Lisp" describes the object system, +but in a very terse style, so this example will include some explanation of +how the object system is used. First, we need to define a class for the +objects that will compute sound products. Every class is a subclass of class +class, and you create a subclass by sending :new to a class. +

+(setf product-class (send class :new '(s1 s2)))
+
+ +The parameter '(s1 s2) says that the new class will have two instance +variables, s1 and s2. In other words, every object which is an +instance of class product-class will have its own copy of +these two variables. +

+Next, we will define the :next method for product-class: +

+(send product-class :answer :next '()
+  '((let ((f1 (snd-fetch s1))
+          (f2 (snd-fetch s2)))
+      (cond ((and f1 f2)
+             (* f1 f2))
+            (t nil)))))
+
+ +The :answer message is used to insert a new method into our new +product-class. The method is described in three parts: the name +(:next), a parameter list (empty in this case), and a list of +expressions to be evaluated. In this case, we fetch samples from s1 +and s2. If both are numbers, we return their product. If either is +NIL, we terminate the sound by returning nil. +

+The :next method assumes that s1 and s2 hold the sounds +to be multiplied. These must be installed when the object is created. +Objects are created by sending :new to a class. A new object is +created, and any parameters passed to :new are then sent in a +:isnew message to the new object. Here is the :isnew +definition for product-class: +

+(send product-class :answer :isnew '(p1 p2) 
+  '((setf s1 (snd-copy p1))
+    (setf s2 (snd-copy p2))))
+
+ +Take careful note of the use of snd-copy in this initialization. The +sounds s1 and s2 are modified when accessed by +snd-fetch in the :next method defined above, but this destroys +the illusion that sounds are immutable values. The solution is to copy the +sounds before accessing them; the original sounds are therefore unchanged. +(This copy also takes place implicitly in most Nyquist sound functions.) +

+To make this code safer for general use, we should add checks that s1 +and s2 are sounds with identical starting times and sample rates; +otherwise, an incorrect result might be computed. +

+Now we are ready to write snd-product, an approximate replacement for +snd-prod: +

+(defun snd-product (s1 s2)
+  (let (obj)
+    (setf obj (send product-class :new s1 s2))
+    (snd-fromobject (snd-t0 s1) (snd-srate s1) obj)))
+
+ +This code first creates obj, an instance of product-class, to +hold s1 and s2. Then, it uses obj to create a sound +using snd-fromobject. This sound is returned from +snd-product. Note that in snd-fromobject, you must also +specify the starting time and sample rate as the first two parameters. These +are copied from s1, again assuming that s1 and s2 have +matching starting times and sample rates. +

+Note that in more elaborate DSP algorithms we could expect the object to +have a number of instance variables to hold things such as previous samples, +waveform tables, and other parameters. +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part7.html b/doc/part7.html new file mode 100644 index 0000000..820e758 --- /dev/null +++ b/doc/part7.html @@ -0,0 +1,673 @@ +SAL + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

SAL

+ +Nyquist supports two languages: XLISP and SAL. In some sense, XLISP and SAL +are the same language, but with differing syntax. This chapter describes SAL: how it works, SAL syntax and semantics, and the relationship between SAL and XLISP, and differences between Nyquist SAL and Common Music SAL. +

+Nyquist SAL is based on Rick Taube's SAL language, which is +part of Common Music. SAL offers the power +of Lisp but features a simple, Algol-like syntax. SAL is implemented +in Lisp: Lisp code translates SAL into a Lisp program and uses the +underlying Lisp engine to evaluate the program. Aside from the translation +time, which is quite fast, SAL programs execute at about the same speed as +the corresponding Lisp program. (Nyquist SAL programs run just + slightly slower than XLISP +because of some runtime debugging support automatically added to +user programs by the SAL compiler.) +

+From the user's perspective, these implementation details are hidden. You +can enter SAL mode from XLISP by typing (SAL) to the XLISP prompt. +The SAL input prompt (SAL> ) will be displayed. From that point on, +you simply type SAL commands, and they will be executed. By setting a +preference in the NyquistIDE program, SAL mode will be entered automatically. +

+It is possible to encounter errors that will take you from the SAL interpreter +to an XLISP prompt. In general, the way to get back to SAL is by typing +(top) to get back to the top level XLISP interpreter and reset the +Nyquist environment. Then type (sal) to restart the SAL interpreter. +

+

SAL Syntax and Semantics

+ + The most unusual feature of SAL syntax is that identifiers +are Lisp-like, including names such as "play-file" and even "*warp*." +In SAL, most operators must be separated from identifiers by white space. +For example, play-file is one identifier, but play - file +is an expression for "play minus file," where play and file are +two separate identifiers. Fortunately, no spaces are needed around commas +and parentheses. +

+In SAL, whitespace (any sequence of space, newline, or tab characters) +is sometimes necessary to separate lexical tokens, but +otherwise, spaces and indentation are ignored. To make SAL readable, +it is strongly advised that you indent SAL programs as in the examples +here. The NyquistIDE program is purposely insistent about SAL indentation, +so if you use it to edit SAL programs, your indentation should be +both beautiful and consistent. +

+As in Lisp (but very unlike C or Java), comments +are indicated by +semicolons. Any text from an unquoted semicolon to the end of the +line is ignored. +

+

+; this is a comment
+; comments are ignored by the compiler
+print "Hello World" ; this is a SAL statement
+
+ +

+As in Lisp, identifiers are translated to upper-case, making SAL +case-insensitive. For example, the function name autonorm can +be typed in lower case or as AUTONORM, AutoNorm, or even +AuToNoRm. All forms denote the same function. The recommended +approach is to write programs in all lower case. +

+SAL is organized around statements, most of which +contain expressions. We will begin with expressions and then look at +statements. +

+

Expressions

+ +
Simple Expressions
+As in XLISP, simple expressions include: +
    +
  • +integers (FIXNUM's), such as 1215, +
  • floats (FLONUM's) such as 12.15, +
  • strings (STRING's) such as "Magna Carta", and +
  • symbols (SYMBOL's) such as magna-carta. A symbol with a leading colon +(:) evaluates to itself as in Lisp. Otherwise, a symbol denotes either +a local variable, a formal parameter, or a global variable. As in Lisp, +variables do not have data types or type declarations. The type of a +variable is determined at runtime by its value. +
+

+Additional simple expressions in SAL are: +

+A curious property of Lisp and Sal is that false and the empty list are +the same value. Since SAL is based on Lisp, #f and {} (the empty +list) are equal. +

+

Operators
+Expressions can be formed with unary and binary operators using infix notation. The operators are: + +Again, remember that operators must be delimited from their operands using +spaces or parentheses. Operator precedence is based on the following levels of +precedence: +
+@ @@ ~ ~~
+^
+/ * 
+% - +
+~= <= >= > ~= =
+!
+&
+|
+
+ +

+

Function Calls
+ +A function call is a function name followed by zero or more comma-delimited +argument expressions +enclosed within parentheses: +
+list()
+piano-note(2.0, c4 + interval, 100)
+
+ +Some functions use named parameters, +in which case the name of the argument with a colon precedes the argument +expression. +
+s-save(my-snd(), ny:all, "tmp.wav", play: #t, bits: 16)
+
+ +

+

Array Notation
+ +An array reference is a variable identifier followed by an index expression +in square brackets, e.g.: +
+x[23] + y[i]
+
+ +

+

Conditional Values
+ + +The special operator #? evaluates the first argument expression. +If the result is true, the second expression is evaluated and +its value is returned. If false, the third expression is evaluated +and returned (or false is returned if there is no third expression): +
+#?(random(2) = 0, unison, major-third)
+#?(pitch >= c4, pitch - c4) ; returns false if pitch < c4
+
+ +

+

SAL Statements

+ +SAL compiles and evaluates statements one at a time. You can type +statements at the SAL prompt or load a file containing SAL statements. +SAL statements are described below. The syntax is indicated at the +beginning of each statement type description: this font indicates +literal terms such as keywords, the italic font indicates a +place-holder for some other statement or expression. Bracket [like this] +indicate optional (zero or one) syntax elements, while braces with a plus +{like this}+ indicate one or more occurrences of a syntax element. Braces +with a star {like this}* indicate zero or more occurrences of a syntax element: { non-terminal }* is equivalent to [ {non-terminal}+ ]. +

+

begin and end
+ +begin [with-stmt] {statement}+ end +

+A begin-end statement +consists of a sequence of statements surrounded by +the begin and end keywords. This form is often used for function +definitions and after then or else where the syntax demands a +single statement but you want to perform more than one action. Variables may be +declared using an optional with statement immediately after begin. +For example: +

+begin
+  with db = 12.0,
+       linear = db-to-linear(db)
+  print db, "dB represents a factor of", linear
+  set scale-factor = linear
+end  
+
+ +

+

chdir
+ +chdir expression +

+The chdir statement changes the working directory. This statement +is provided for compatibility with Common Music SAL, but it really +should be avoided if you use NyquistIDE. The expression following the +chdir keyword should evaluate to a string that is a directory +path name. Note that literal strings themselves are valid expressions. +

+chdir "/Users/rbd/tmp"
+
+ +

+

define variable
+ +[define] variable name [= expression] {, name [= expression]}* +

+Global variables can be declared and initialized. A list of variable names, +each with an optional initialization follows the define variable +keywords. (Since variable is a keyword, define is redundant +and optional in Nyquist SAL, but required in Common Music SAL.) +If the initialization part is omitted, the variable is initialized +to false. Global variables do not really need to be declared: just using the +name implicitly creates the corresponding variable. However, it is an error +to use a global variable that has not been initialized; +define variable is a good way to introduce a variable (or constant) +with an initial value into your program. +

+

+define variable transposition = 2,
+                print-debugging-info, ; initially false
+                output-file-name = "salmon.wav"
+
+ +

+

define function
+ +[define] function name ( [parameter], {, parameter}* ) statement +

+Before a function be called from an expression (as described above), it must +be defined. A function definition gives the function name, a list of +parameters, and a statement. When a function is called, the actual +parameter expressions are evaluated from left to right and the formal parameters +of the function definition are set to these values. Then, statement is +evaluated. +

+The formal parameters may be positional parameters that are matched with +actual parameters by position from left to right. Syntactically, these are +symbols and these symbols +are essentially local variables that exist only until statement completes +or a return statement causes the function evaluation to end. As in Lisp, +parameters are passed by value, so assigning a new value to a formal parameter +has no effect on the actual value. However, lists and arrays are not copied, +so internal changes to a list or array produce observable side effects. +

+Alternatively, formal parameters may be keyword parameters. Here the parameter +is actually a pair: a keyword parameter, which is a symbol followed by a colon, +and a default value, given by any expression. Within the body of the function, +the keyword parameter is named by a symbol whose name matches the keyword +parameter except there is no final colon. +

+define function foo(x: 1, y: bar(2, 3))
+    display "foo", x, y
+

+exec foo(x: 6, y: 7) +

+ +In this example, x is bound to the value 6 and y is bound to +the value 7, so the example prints "foo : X = 6, Y = 7". Note that +while the keyword parameters are x: and y:, the corresponding +variable names in the function body are x and y, respectively. +

+The parameters are meaningful only within the lexical (static) scope of +statement. They are not accessible from within other +functions even if they are called by this function. +

+Use a begin-end statement if the body of the function should +contain more than one statement or you need to define local variables. Use +a return statement to return a value from the function. If statement +completes without a return, the value false is returned. +

+

display
+ +display string {, expression}* +

+The display statement is handy for debugging. At present, it is only +implemented in Nyquist SAL. When executed, display prints the string +followed by a colon and then, for each expression, the expression and its +value are printed, after the last expression, a newline is printed. For example, +

+display "In function foo", bar, baz
+
+ +prints +
+In function foo : bar = 23, baz = 5.3
+
+ +SAL may print the expressions using Lisp syntax, e.g. if the expression is +"bar + baz," do not be surprised if the output is "(sum bar baz) = 28.3." +

+

exec
+ +exec expression +

+Unlike most other programming languages, you cannot simply type an expression as +a statement. If you want to evaluate an expression, e.g. call a function, +you must use an exec statement. The statement simply evaluates +the expression. For example, +

+exec set-sound-srate(22050.0) ; change default sample rate
+
+ +

+

if
+ +if test-expr then true-stmt [else false-stmt] +

+An if statement evaluates the expression test-expr. If it is true, +it evaluates the statement true-stmt. If false, the statement +false-stmt is evaluated. Use a begin-end statement +to evaluate more than one statement in then then or else +parts. +

+

+if x < 0 then x = -x ; x gets its absoute value
+

+if x > upper-bound then + begin + print "x too big, setting to", upper-bound + x = upper-bound + end +else + if x < lower-bound then + begin + print "x too small, setting to", lower-bound + x = lower-bound + end +

+ +Notice in this example that the else part is another if +statement. An if may also be the then part of another +if, so there could be two possible if's with which to +associate an else. An else clause always associates +with the closest previous if that does not already have an +else clause. +

+

when
+when test statement +

+The when statement is similar to if, but there is no else clause. +

+

+when *debug-flag* print "you are here"
+
+ +

+

unless
+unless test statement +

+The unless statement is similar to when (and if) but the +statement is executed when the test expression is false. +

+

+unless count = 0 set average = sum / count
+
+ +

+

load
+ +load expression +

+The load command loads a file named by expression, which must +evauate to a string path name for the file. To load a file, SAL interprets +each statement in the file, stopping when the end of the file or an error +is encountered. If the file ends in .lsp, the file is assumed to +contain Lisp expressions, which are evaluated by the XLISP interpreter. +In general, SAL files should end with the extension .sal. +

+

loop
+ +loop [with-stmt] {stepping}* {stopping* action+ [finally] end +

+The loop statement is by far the most complex statement in SAL, but +it offers great flexibility for just about any kind of iteration. The basic +function of a loop is to repeatedly evaluate a sequence of action's which +are statements. Before the loop begins, local variables may be declared in +with-stmt, a with statement. +

+The stepping clauses do several +things. They introduce and initialize additional local variables similar +to the with-stmt. +However, these local variables are updated to new values after the action's. +In addition, some stepping clauses have associated stopping conditions, +which are tested on each iteration before evaluating the action's. +

+There are also stopping clauses that provide additional tests to +stop the iteration. These are also evaluated and tested +on each iteration before evaluating the action's. +

+When some stepping or stopping condition causes the iteration to stop, +the finally clause is evaluated (if present). Local variables and their +values can still be accessed in the finally clause. After the finally +clause, the loop statement completes. +

+The stepping clauses are the following: +

+
+repeat expression
Sets the number of iterations to the value of expression, which should be an integer (FIXNUM).

+
for var = expression [ then expr2 ]
Introduces a new local +variable named var and initializes it to expression. Before each subsequent +iteration, var is set to the value of expr2. If the then part is +omitted, expression is re-evaluated and assigned to var +on each subsequent iteration. Note that this differs from a with-stmt where +expressions are evaluated and variables are only assigned their values once.

+
for var in expression
Evaluates expression to +obtain a list and creates a new local variable initialized to the first element +of the list. After each iteration, var is assigned the next element of the +list. Iteration stops when var has assumed all values from the list. If the +list is initially empty, the loop action's are not evaluated (there are zero +iterations).

+
for var [from from-expr] [[to | below | downto | above] to-expr] [by step-expr]
Introduces a new local variable named var and intialized +to the value of the expression from-expr (with a default value of 0). After +each iteration of the loop, var is incremented by the value +of step-expr (with a default value of 1). +The iteration ends when var is greater than +the value of to-expr if there is a to clause, +greater than or equal to the value of to-expr +if there is a below clause, +less than the value of to-expr if there is a downto clause, +or less than or equal to the value of to-expr if there is a above +clause. (In the cases of downto and above, the default increment value +is -1. If there +is no to, below, downto, above, or below clause, no interation stop test is created for this +stepping clause. +
+

+The stopping clauses are the following: +

+
+while expression
The iterations are stopped when expression evaluates to false. Anything not false is considered to mean true.

+
until expression
The iterations are stopped when expression evaluates to true. +
+

+The finally clause is defined as follows: + +

+
+finally statement
The statement is evaluated when one of the +stepping or stopping clauses ends the loop. As always, statement may +be a begin-end statement. If an action evaluates a return +statement, the finally statement is not executed. +
+

+Loops often fall into common patterns, such as iteratiing a fixed number of +times, performing an operation on some range of integers, collecting results +in a list, and linearly searching for a solution. These forms are illustrated +in the examples below. +

+

+; iterate 10 times
+loop
+  repeat 10
+  print random(100)
+end
+

+; print even numbers from 10 to 20 +; note that 20 is printed. On the next iteration, +; i = 22, so i >= 22, so the loop exits. +loop + for i from 10 to 22 by 2 + print i +end +

+; collect even numbers in a list +loop + with lis + for i = 0 to 10 by 2 + set lis @= i ; push integers on front of list, + ; which is much faster than append, + ; but list is built in reverse + finally result = reverse(lis) +end +; now, the variable result has a list of evens +

+; find the first even number in a list +result = #f ; #f means "false" +loop + for elem in lis + until evenp(elem) + finally result = elem +end +; result has first even value in lis (or it is #f) +

+ +

+

print
+ +print expr {, expr}* +

+The print statement prints the values separated by +spaces and followed by a newline. [Note that in the original +SAL, the newline is printed before the values, not after.] +

+

+print "The value of x is", x
+
+ +

+

return
+ +return expression +

+The return statement can only be used inside a function. It evaluates +expression and then the function returns the value of the expression +to its caller. +

+

set
+ +set var op expression {, var op expression}* +

+The set statement changes the value of a variable var according +to the operator op and the value of the expression. The operators are: +

+
+=
The value of expression is assigned to var.

+
+=
The value of expression is added to var.

+
*=
The value of var is multiplied by the value of the expression.

+
&=
The value of expression is inserted as the last element of +the list referenced by var. If var is the empty list (denoted by #f), +then var is assigned a newly constructed list of one element, the value +of expression.

+
^=
The value of expression, a list, is appended to the list referenced +by var. If var is the empty list (denoted by #f), then var +is assigned the (list) value of expression.

+
@=
Pushes the value of expression onto the front of the list +referenced by var. If var is empty (denoted by #f), then var +is assigned a newly constructed list of one element, the value of expression.

+
<=
Sets the new value of var to the minimum of the old value +of var and the value of expression.

+
>=
Sets the new value of var to the maximum of the old value +of var and the value of expression. +
+

+

+; example from Rick Taube's SAL description
+loop
+  with a, b = 0, c = 1, d = {}, e = {}, f = -1, g = 0
+  for i below 5
+  set a = i, b += 1, c *= 2, d &= i, e @= i, f <= i, g >= i
+  finally display "results", a, b, c, d, e, f, g
+end
+
+ +

+

with
+ +with var [= expression] {, var [= expression]}* +

+The with statement declares and initializes local variables. It +can appear only after begin or loop. If the expression is +omitted, the initial value is false. The variables are visible only +inside the begin-end or loop statement where the +with statement appears. Even in loop's the variables +are intialized only when the loop is entered, not on each iteration. +

+

exit
+ +exit [nyquist] +

+The exit statement is unique to Nyquist SAL. It returns from SAL +mode to the XLISP interpreter. (Return to SAL mode by typing "(sal)"). +If nyquist is included in the statement, then the entire Nyquist +process will exit. +

+

Interoperability of SAL and XLISP

+ + +When SAL evaluatas command or loads files, it translates SAL into XLISP. +You can think of SAL as a program that translates everything you write +into XLISP and entering it for you. Thus, when you define a SAL function, +the function actually exists as an XLISP function (created using +Lisp's defun special form). When you set or evaluate global variables +in SAL, these are exactly the same Lisp global variables. Thus, XLISP +functions can call SAL functions and vice-versa. At run time, +everything is Lisp. +

+

Function Calls

+In general, there is a very simple translation from SAL to Lisp syntax +and back. A function call is SAL, for example, +
+osc(g4, 2.0)
+
+ +is translated to Lisp by moving the open parenthesis in front of the +function name and removing the commas: +
+(osc g4 2.0)
+
+ +Similarly, if you want to translate a Lisp function call to SAL, just +reverse the translation. +

+

Symbols and Functions

+SAL translates keywords with trailing colons (such as foo:) +into Lisp keywords with leading colons (such as :foo), but +SAL keywords are not treated as expressions as they are in Lisp. +You cannot write open("myfile.txt", direction: output:) +because SAL expects an expression after direction. A special form +keyword is defined to generate a Lisp keyword as an +expression. The argument is the keyword without a colon, e.g. +open("myfile.txt", direction: keyword(output)). Alternatively, +you can write the Lisp-style keyword with the leading colon, e.g. +open("myfile.txt", direction: :output). +

+In Nyquist SAL, the hash character (#), can be used as a prefix to a +Lisp function name. For example, the following command is not legal +because print is a SAL command name, not a legal function name: +set v = append(print(a), print(b)). (Here the intent is to print +arguments to append). However, you can use the hash character to access +the Lisp print function: set v = append(#print(a), #print(b)). +

+

Playing Tricks On the SAL Compiler

+In many cases, the close coupling between SAL and XLISP gives SAL +unexpected expressive power. A good example is seqrep. This +is a special looping construct in Nyquist, implemented as a macro in +XLISP. In Lisp, you would write something like: +
+(seqrep (i 10) (pluck c4))
+
+ +One might expect SAL would have to define a special seqrep +statement to express this, but since statements do not return values, +this approach would be problematic. The solution (which is already +fully implemented in Nyquist) is to define a +new macro sal-seqrep that is equivalent to seqrep +except that it is called as follows: +
+(sal-seqrep i 10 (pluck c4))
+
+ +The SAL compiler automatically translates the identifier seqrep to + sal-seqrep. Now, in SAL, you can just write +
+seqrep(i, 10, pluck(c4))
+
+ +which is translated in a pretty much semantics-unaware fashion to +
+(sal-seqrep i 10 (pluck c4))
+
+ +and viola!, we have Nyquist control constructs in SAL even though SAL +is completely unaware that seqrep is actually a special form. +

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part8.html b/doc/part8.html new file mode 100644 index 0000000..91db1a5 --- /dev/null +++ b/doc/part8.html @@ -0,0 +1,2823 @@ +Nyquist Functions + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Nyquist Functions

+ +This chapter provides a language reference for Nyquist. Operations +are categorized by functionality and abstraction level. +Nyquist is implemented in two important levels: the "high level" supports +behavioral abstraction, which means that operations like stretch and +at can be applied. These functions are the ones that typical users +are expected to use, and most of these functions are written in XLISP. +

+The "low-level" primitives directly operate on sounds, but know nothing of +environmental variables (such as *warp*, etc.). The +names of most of these low-level functions start with "snd-". In +general, programmers should avoid any function with the "snd-" +prefix. Instead, use the "high-level" functions, which know about the +environment and react appropriately. The names of high-level functions +do not have prefixes like the low-level functions. +

+There are certain low-level operations that apply directly to sounds (as +opposed to behaviors) and are relatively "safe" for ordinary use. These +are marked as such. +

+Nyquist uses both linear frequency and equal-temperament pitch numbers to +specify repetition rates. Frequency is always specified in either cycles +per second (hz), or pitch numbers, also referred to as "steps," as in +steps of the chromatic scale. Steps are floating point numbers such that 60 += Middle C, 61 = C#, 61.23 is C# plus 23 cents, etc. The mapping from pitch +number to frequency is the standard exponential conversion, and fractional +pitch numbers are allowed: + +

frequency = 440 * 2^((pitch - 69)/12)
+There are many +predefined pitch names. By default these are tuned in equal temperament, +with A4 = 440Hz, but these may be changed. (See Section "Predefined Constants"). +

+

Sounds

+A sound is a primitive data type in Nyquist. Sounds can be created, passed +as parameters, garbage collected, printed, and set to variables just like +strings, atoms, numbers, and other data types. +

+

What is a Sound?

+Sounds have 5 components: + +It may seem that there should be logical-start to indicate the +logical or perceptual beginning of a sound as well as a logical-stop +to indicate the logical ending of a sound. In practice, only +logical-stop is needed; this attribute tells when the next sound +should begin to form a sequence of sounds. In this respect, Nyquist sounds +are asymmetric: it is possible to compute sequences forward in time by +aligning the logical start of each sound with the logical-stop of the +previous one, but one cannot compute "backwards", aligning the logical end +of each sound with the logical start of its successor. The root of this +asymmetry is the fact that when we invoke a behavior, we say when to start, +and the result of the behavior tells us its logical duration. There is no +way to invoke a behavior with a direct specification of when to +stop (Footnote 1) . +

+Note: there is no way to enforce the +intended "perceptual" interpretation of +logical-stop. As far as Nyquist is concerned, these are just numbers to +guide the alignment of sounds within various control constructs. +

+

Multichannel Sounds

+ +Multichannel sounds are represented by Lisp arrays of sounds. To create an +array of sounds the XLISP vector function is useful. Most low-level +Nyquist functions (the ones starting with snd-) do not operate on +multichannel sounds. Most high-level functions do operate on multichannel +sounds. +

+

Accessing and Creating Sound

+ +Several functions display information concerning a sound and can be used to +query the components of a sound. There are functions that access samples in +a sound and functions that construct sounds from samples. +

+

+
+sref(sound, time) [SAL]
+ +(sref sound time) [LISP]
Accesses sound at +the point time, which is a local time. If time does not +correspond to a sample time, then the nearest samples are linearly +interpolated to form the result. To access a particular sample, either +convert the sound to an array (see snd-samples below), or use +snd-srate and snd-t0 (see below) to find the sample rate +and starting time, and compute a time (t) from the sample number (n): + +
t = (n / srate) + t0
+Thus, the lisp code to access the n^(th) sample of a sound would look like: + +(sref sound (global-to-local (+ (/ n (snd-srate sound)) (snd-t0 sound)))) + +Here is why sref interprets its time argument as a local time: +
+> (sref (ramp 1) 0.5) ; evaluate a ramp at time 0.5
+0.5
+> (at 2.0 (sref (ramp 1) 0.5)) ; ramp is shifted to start at 2.0
+		; the time, 0.5, is shifted to 2.5
+0.5
+
+ +If you were to use snd-sref, which treats time as global, instead of sref, which treats time as local, then the first example above would return the same answer (0.5), but the second example would return 0. Why? Because the (ramp 1) behavior would be shifted to start at time 2.0, but the resulting sound would be evaluated at global time 0.5. By definition, sounds have a value of zero before their start time.

+
sref-inverse(sound, value) [SAL]
+ +(sref-inverse sound value) [LISP]
Search sound for the first point at which it achieves value and return the corresponding (linearly interpolated) time. If no inverse exists, an error is raised. This function is used by Nyquist in the implementation of time warping.

+
+snd-from-array(t0, sr, +array) [SAL]
+ +(snd-from-array t0 sr array) [LISP]
Converts a lisp array of FLONUMs into a sound with starting +time t0 and sample rate sr. Safe for ordinary use. Be aware that +arrays of floating-point samples use 14 bytes per sample, and an additional +4 bytes per sample are allocated by this function to create a sound type.

+
snd-fromarraystream(t0, sr, object) [SAL]
+ +(snd-fromarraystream t0 sr object) [LISP]
Creates a sound for which samples come from +object. The starting time is t0 (a FLONUM), and the sample rate is +sr. The object is an XLISP object (see Section "Objects" for +information on objects.) A sound is returned. When the sound needs samples, +they are generated by sending the message :next to object. If +object returns NIL, the sound terminates. Otherwise, object +must return an array of FLONUMs. The values in these arrays are +concatenated to form the samples of the resulting sound. +There is no provision for object to specify the +logical stop time of the sound, so the logical stop time is the termination +time.

+
snd-fromobject(t0, sr, object) [SAL]
+ +(snd-fromobject t0 sr object) [LISP]
Creates a sound for which samples come from +object. The starting time is t0 (a FLONUM), and the sample rate is +sr. The object is an XLISP object (see Section "Objects" for +information on objects. A sound is returned. When the sound needs samples, +they are generated by sending the message :next to object. If +object returns NIL, the sound terminates. Otherwise, object +must return a FLONUM. There is no provision for object to specify the +logical stop time of the sound, so the logical stop time is the termination +time.

+
snd-extent(sound, maxsamples) [SAL]
+ +(snd-extent sound maxsamples) [LISP]
Returns a list of two numbers: the starting time of sound and the terminate time of sound. Finding the terminate time requires that samples be computed. Like most Nyquist functions, this is non-destructive, so memory will be allocated to preserve the sound samples. If the sound is very long or infinite, this may exhaust all memory, so the maxsamples parameter specifies a limit on how many samples to compute. If this limit is reached, the terminate time will be (incorrectly) based on the sound having maxsamples samples. This function is safe for ordinary use.

+
snd-fetch(sound) [SAL]
+ +(snd-fetch sound) [LISP]
Reads samples +sequentially from sound. This returns a FLONUM after each call, or +NIL when sound terminates. Note: snd-fetch modifies +sound; it is strongly recommended to copy sound using +snd-copy and access only the copy with snd-fetch.

+
snd-fetch-array(sound, len, +step) [SAL]
+ +(snd-fetch-array sound len step) +[LISP]
Reads +sequential arrays of samples from sound, returning either an array +of FLONUMs or NIL when the sound terminates. The len +parameter, a FIXNUM, indicates how many samples should be +returned in the result array. After the array is returned, sound +is modified by skipping over step (a FIXNUM) samples. If +step equals len, then every sample is returned once. If +step is less than len, each returned array will overlap the +previous one, so some samples will be returned more than once. If +step is greater than len, then some samples will be skipped +and not returned in any array. The step and len may change at +each call, but in the current implementation, an internal buffer is +allocated for sound on the first call, so subsequent calls may not +specify a greater len than the first. When an array is returned, +it will have len samples. If necessary, snd-fetch-array +will read zeros beyond the end of the sound to fill the array. When +this happens, *rslt* is set to a FIXNUM number of samples in +the array that were read from the sound before the physical stop time +of the sound. If all samples in the array are "valid" samples from +the sound (coming from the sound before the sound +terminates), *rslt* is set to NIL. The *rslt* +variable is global and used to return extra results from other +functions, so programs should not assume *rslt* is valid after +subsequent function calls. Note: snd-fetch-array modifies +sound; it is strongly recommended to copy sound using +snd-copy and access only the copy with snd-fetch-array.

+
snd-flatten(sound, maxlen) [SAL]
+ +(snd-flatten sound maxlen) [LISP]
This function is identical +to snd-length. You would use this function to force samples to be computed in memory. Normally, this is not a good thing to do, but here is one appropriate use: In the case of sounds intended for wavetables, the unevaluated +sound may be larger than the evaluated (and typically short) one. +Calling snd-flatten will compute the samples and allow the unit generators to be freed in the next garbage collection. Note: If a sound is computed from many instances of table-lookup oscillators, calling snd-flatten will free the oscillators and their tables. Calling (stats) will print how many total bytes have been allocated to tables.

+
snd-length(sound, maxlen) [SAL]
+ +(snd-length sound maxlen) [LISP]
Counts the +number of samples in sound up to the physical stop time. If the sound +has more than maxlen samples, maxlen is returned. Calling this +function will cause all samples of the sound to be computed and saved in +memory (about 4 bytes per sample). Otherwise, this function is safe for ordinary use.

+
snd-maxsamp(sound) [SAL]
+ +(snd-maxsamp sound) [LISP]
Computes the maximum of +the absolute value of the samples in sound. Calling this function will +cause samples to be computed and saved in memory. (This function should +have a maxlen parameter to allow self-defense against sounds that would +exhaust available memory.) Otherwise, this function is safe for ordinary use. +This function will probably be removed in a future version. See peak, a replacement ("Signal Operations").

+
snd-play(expression) [SAL]
+ +(snd-play expression) [LISP]
Evaluates expression +to obtain a sound or array of sounds, computes all of the samples (without +retaining them in memory), and returns. Originally, this was a placeholder +for a facility to play samples directly to an audio output device, but +playback is now accomplished by s-save. +Meanwhile, since this +function does not save samples in memory or write them to a disk, it is +useful in determining how much time is spent calculating samples. See +s-save (Section "Sound File Input and Output") for saving samples to a file, and + play (Section "Sound File Input and Output") to play a sound. This function is +safe for ordinary use.

+
snd-print-tree(sound) [SAL]
+ +(snd-print-tree sound) [LISP]
Prints an ascii +representation of the internal data structures representing a sound. This +is useful for debugging Nyquist. This function is +safe for ordinary use.

+
snd-samples(sound, limit) [SAL]
+ +(snd-samples sound limit) [LISP]
Converts the +samples into a lisp array. The data is taken directly from the samples, +ignoring shifts. For example, if the sound starts at 3.0 seconds, the first +sample will refer to time 3.0, not time 0.0. A maximum of limit samples +is returned. This function is safe for ordinary use, but like +snd-from-array, it requires a total of slightly over 18 bytes per +sample.

+
snd-srate(sound) [SAL]
+ +(snd-srate sound) [LISP]
Returns the sample rate of +the sound. Safe for ordinary use.

+
snd-time(sound) [SAL]
+ +(snd-time sound) [LISP]
Returns the start time of the +sound. This will probably go away in a future version, so use snd-t0 +instead.

+
snd-t0(sound) [SAL]
+ +(snd-t0 sound) [LISP]
Returns the time of the +first sample of the sound. Note that Nyquist operators such as add always +copy the sound and are allowed to shift the copy up to one half sample +period in either direction to align the samples of two operands. Safe for +ordinary use.

+
snd-print(expression, maxlen) [SAL]
+ +(snd-print expression maxlen) [LISP]
Evaluates +expression to yield a sound or an array of sounds, then prints up to +maxlen samples to the screen (stdout). This is similar to +snd-save, but samples appear in text on the screen instead of in +binary in a file. This function is intended for debugging. +Safe for ordinary use.

+
snd-set-logical-stop(sound, +time) [SAL]
+ +(snd-set-logical-stop sound time) [LISP]
Returns a sound which is +sound, except that the logical stop of the sound occurs at time. + Note: do not call this function. When defining a behavior, use +set-logical-stop or set-logical-stop-abs instead.

+
snd-sref(sound, time) [SAL]
+ +(snd-sref sound time) [LISP]
Evaluates sound +at the global time given by time. Safe for ordinary use, but normally, you should +call sref instead.

+
snd-stop-time(sound) [SAL]
+ +(snd-stop-time sound) [LISP]
Returns the stop time of sound. +Sounds can be "clipped" or truncated at a particular time. This function +returns that time or MAX-STOP-TIME if he programmer has not specified a stop +time for the sound. Safe for ordinary use.

+
soundp(sound) [SAL]
+ +(soundp sound) [LISP]
Returns true iff sound is a +SOUND. Safe for ordinary use.

+
stats() [SAL]
+ +(stats) [LISP]
Prints the memory usage status. +See also the +XLISP mem function. Safe for ordinary use. This is the only way to find out how much memory is being used by table-lookup oscillator instances.

+

Miscellaneous Functions

+These are all safe and recommended for ordinary use. +

+

+
+db-to-linear(x) [SAL]
+ +(db-to-linear x) [LISP]
Returns the conversion of x from decibels to linear. 0dB is converted to 1. 20dB represents a linear factor of 10. If x is a sound, each sample is converted and a sound is returned. If x is a multichannel sound, each channel is converted and a multichannel sound (array) is returned. Note: With sounds, conversion is only performed on actual samples, not on the implicit zeros before the beginning and after the termination of the sound. Sample rates, start times, etc. are taken from x.

+
follow(sound, floor, risetime, falltime, lookahead) [SAL]
+ +(follow sound floor risetime falltime lookahead) [LISP]
An envelope follower intended as a commponent for compressor and limiter functions. The basic goal of this function is to generate a smooth signal +that rides on the peaks of the input signal. The usual objective is to +produce an amplitude envelope given a low-sample rate (control rate) +signal representing local RMS measurements. The first argument is the +input signal. The floor is the minimum output value. The risetime +is the time (in seconds) it takes for the output to rise (exponentially) +from floor to unity (1.0) and the falltime is the time it takes +for the output to fall (exponentially) from unity to floor. The +algorithm looks ahead for peaks and will begin to increase the output +signal according to risetime in anticipation of a peak. The amount +of anticipation (in seconds) is given by lookahead. The algorithm +is as follows: the output value is allowed to increase according to +risetime or decrease according to falltime. If the next input +sample is in this range, that sample is simply output as the next output +sample. If the next input sample is too large, the algorithm goes back in +time as far as necessary to compute an envelope that rises according to +risetime to meet the new value. The algorithm will only work backward +as far as lookahead. If that is not far enough, then there is a final +forward pass computing a rising signal from the earliest output sample. In +this case, the output signal will be at least momentarily less than the +input signal and will continue to rise exponentially until it intersects +the input signal. If the input signal falls faster than indicated by +falltime, the output fall rate will be limited by falltime, +and the fall in output will stop when the output reaches floor. +This algorithm can make two passes througth the buffer on sharply rising +inputs, so it is not particularly fast. With short buffers and low sample +rates this should not matter. See snd-avg for a function that +can help to generate a low-sample-rate input for follow. +See snd-chase in Section "Filters" for a related filter.

+
+gate(sound, +lookahead, risetime, falltime, floor, +threshold) [SAL]
+ +(gate sound lookahead risetime falltime floor threshold) [LISP]
Generate an exponential rise and decay intended +for noise gate implementation. The decay starts when the signal drops +below threshold and stays there for longer than lookahead (a +FLONUM in seconds). (The signal begins to drop when the signal +crosses threshold, not after lookahead.) Decay continues until +the value reaches floor (a FLONUM), at which point the decay +stops and the output value is held constant. Either during the decay or +after the floor is reached, if the signal goes above threshold, then +the ouptut value will rise to unity (1.0) at the point the signal crosses +the threshold. Because of internal lookahead, the signal actually begins +to rise before the signal crosses threshold. The rise is a +constant-rate exponential and set so that a rise from floor to unity +occurs in risetime. Similary, the fall is a constant-rate exponential +such that a fall from unity to floor takes falltime.

+
hz-to-step(freq) [SAL]
+ +(hz-to-step freq) [LISP]
Returns a step number for freq (in hz), which can be either a number of a SOUND. The result has the same type as the argument. See also step-to-hz (below).

+
linear-to-db(x) [SAL]
+ +(linear-to-db x) [LISP]
Returns the conversion of x from linear to decibels. 1 is converted to 0. 0 is converted to -INF (a special IEEE floating point value.) A factor of 10 represents a 20dB change. If x is a sound, each sample is converted and a sound is returned. If x is a multichannel sound, each channel is converted and a multichannel sound (array) is returned. Note: With sounds, conversion is only performed on actual samples, not on the implicit zeros before the beginning and after the termination of the sound. Start times, sample rates, etc. are taken from x.

+
log(x) [SAL]
+ +(log x) [LISP]
Calculates the natural log of x (a FLONUM). (See s-log for a version that operates on signals.)

+
set-control-srate(rate) [SAL]
+ +(set-control-srate rate) [LISP]
Sets the default sampling rate for control signals to rate by setting *default-control-srate* and reinitializing the environment. Do not call this within any synthesis function (see the control-srate-abs transformation, Section "Transformations").

+
set-sound-srate(rate) [SAL]
+ +(set-sound-srate rate) [LISP]
Sets the default sampling rate for audio signals to rate by setting *default-sound-srate* and reinitializing the environment. Do not call this within any synthesis function (see the sound-srate-abs transformation, Section "Transformations").

+
set-pitch-names() [SAL]
+ +(set-pitch-names) [LIS]
Initializes pitch +variables (c0, cs0, df0, d0, ... b0, + c1, ... b7). A440 (the default tuning) is represented by + the step 69.0, so the variable a4 (fourth octave A) is set to 69.0. +You can change the tuning by +setting *A4-Hertz* to a +value (in Hertz) and calling set-pitch-names to reinitialize the pitch +variables. Note that this will result in non-integer step values. It does not +alter the mapping from step values to frequency. There is no built-in +provision for stretched scales or non-equal temperament, although users +can write or compute any desired fractional step values.

+
step-to-hz(pitch) [SAL]
+ +(step-to-hz pitch) [LISP]
Returns a frequency in hz +for pitch, a step number or a SOUND type representing a time-varying step number. The result is a FLONUM if pitch is a number, and a SOUND if pitch is a SOUND. See also hz-to-step (above).

+
get-duration(dur) [SAL]
+ +(get-duration dur) [LISP]
Gets the actual duration of of something starting at a local time of 0 and ending at a local time of dur times the current sustain. For convenience, *rslt* is set to the global time corresponding to local time zero.

+
get-loud() [SAL]
+ +(get-loud) [LISP]
Gets the current value of the *loud* environment variable. If *loud* is a signal, it is evaluated at local time 0 and a number (FLONUM) is returned.

+
get-sustain() [SAL]
+ +(get-sustain) [LISP]
Gets the current value of the *sustain* environment variable. If *sustain* is a signal, it is evaluated at local time 0 and a number (FLONUM) is returned.

+
get-transpose() [SAL]
+ +(get-transpose) [LISP]
Gets the current value of the *transpose* environment variable. If *transpose* is a signal, it is evaluated at local time 0 and a number (FLONUM) is returned.

+
get-warp() [SAL]
+ +(get-warp) [LISP]
Gets a function corresponding to +the current value of the *warp* environment variable. For +efficiency, *warp* is stored in three parts representing a shift, + a scale factor, and a continuous warp function. Get-warp is used + to retrieve a signal that maps logical time to real time. This signal +combines the information of all three components of *warp* into +a single signal. If the continuous warp function component is not present + (indicating that the time warp is a simple combination of at + and stretch transformations), an error is raised. This +function is mainly for internal system use. In the future, + get-warp will probably be reimplemented to always return + a signal and never raise an error.

+
LOCAL-to-global(local-time) [SAL]
+ +(local-to-global local-time) [LISP]
Converts a score (local) time to a real (global) time according to the current environment.

+
osc-enable(flag) [SAL]
+ +(osc-enable flag) [LISP]
Enable or disable Open Sound Control. +(See Appendix "Open Sound Control and Nyquist".) +Enabling creates a socket and a service that listens for UDP +packets on port 7770. Currently, only two messages are accepted +by Nyquist. The first is of the form /slider +with an integer index and a floating point value. These set internal +slider values accessed by the snd-slider +function. The second is of the form /wii/orientation with +two floating point values. This message is a special case to +support the DarwiinRemoteOsc program + which can relay data from +a Nintendo WiiMote + device to Nyquist via OSC. The two orientation +values control sliders 0 and 1. +Disabling terminates the service (polling for messages) +and closes the socket. The previous state of enablement +is returned, e.g. if OSC is enabled and flag is nil, +OSC is disabled and T (true) is returned because OSC +was enabled at the time of the call. This function only exists +if Nyquist is compiled with the compiler flag OSC. +Otherwise, the function +exists but always returns the symbol DISABLED. Consider +lowering the audio latency using snd-set-latency. +Warning: there is the potential for +network-based attacks using OSC. It is tempting to add the +ability to evaluate XLISP expressions sent via OSC, but +this would create +unlimited and unprotected access to OSC clients. For now, +it is unlikely that an attacker could do more than +manipulate slider values.

+
snd-set-latency(latency) [SAL]
+ +(snd-set-latency latency) [LISP]
Set the latency requested when Nyquist plays sound to + latency, a FLONUM. The previous value is returned. The default is 0.3 seconds. To avoid glitches, the latency should be +greater than the time required for garbage collection and message printing and any other system activity external to Nyquist. +
+

+

Behaviors

+

Using Previously Created Sounds

+ +These behaviors take a sound and transform that sound according to the +environment. These are useful when writing code to make +a high-level function from a low-level function, or when cuing sounds +which were previously created: +
+
+cue(sound) [SAL]
+ +(cue sound) [LISP]
Applies *loud*, the starting time from *warp*, *start*, + and *stop* to sound.

+
cue-file(filename) [SAL]
+ +(cue-file filename) [LISP]
Same as cue, except +the sound comes from the named file, samples from which are coerced to the current default *sound-srate* sample rate.

+
sound(sound) [SAL]
+ +(sound sound) [LISP]
Applies *loud*, *warp*, +*start*, and *stop* to sound.

+
control(sound) [SAL]
+ +(control sound) [LISP]
This function is identical to +sound, but by convention is used when sound is a control signal +rather than an audio signal. +
+

+

Sound Synthesis

These functions provide musically interesting creation behaviors that +react to their environment; these are the "unit generators" of Nyquist: +

+

+
+const(value [, duration]) [SAL]
+ +(const value [duration]) [LISP]
Creates a constant function at the *control-srate*. Every sample has the given value, and the default duration is 1.0. See also s-rest, which is equivalent to calling const with zero, and note that you can pass scalar constants (numbers) to sim, sum, and mult where they are handled more efficiently than constant functions.

+
env(t1, t2, t4, l1, l2, l3, +[dur]) [SAL]
+ +(env t1 t2 t4 l1 l2 l3 dur) [LISP]
Creates a 4-phase envelope. +ti is the duration of phase i, and li +is the final level of phase i. t3 is implied by the duration +dur, and l4 is 0.0. If dur is not supplied, then +1.0 is assumed. The envelope duration is the product of dur, +*stretch*, and *sustain*. If +t1 + t2 + 2ms + t4 is greater than the envelope +duration, then a two-phase envelope is +substituted that has an attack/release time ratio of t1/t4. +The sample rate of the returned sound is *control-srate*. (See +pwl for a more general piece-wise linear function generator.) +The effect of time warping is to warp the starting time and ending time. +The intermediate breakpoints are then computed as described above.

+
exp-dec(hold, halfdec, length) [SAL]
+ +(exp-dec hold halfdec length) [LISP]
This convenient envelope shape is a special case of pwev (see Section "Piece-wise Approximations"). The envelope starts at 1 and is constant for hold seconds. It then decays with a half life of halfdec seconds until length. (The total duration is length.) In other words, the amplitude falls by half each halfdec seconds. When stretched, this envelope scales linearly, which means the hold time increases and the half decay time increases.

+
+force-srate(srate, sound) [SAL]
+ +(force-srate srate sound) [LISP]
Returns a sound which is up- or +down-sampled to srate. Interpolation is linear, and no prefiltering is +applied in the down-sample case, so aliasing may occur. See also +resample.

+
lfo(freq [, duration, table, phase]) [SAL]
+ +(lfo freq duration table phase) [LISP]
Just +like osc (below) +except this computes at the *control-srate* and frequency +is specified in Hz. Phase is specified in degrees. + The *transpose* and *sustain* is not +applied. The effect of time warping is to warp the starting and ending +times. The signal itself will have a constant unwarped frequency.

+
fmlfo(freq [, table, phase]) [SAL]
+ +(fmlfo freq [table phase]) [LISP]
A low-frequency oscillator +that computes at the *control-srate* using a sound to specify a time-varying +frequency in Hz. Phase is a FLONUM in degrees. The duration of the result is determined by freq.

+
maketable(sound) [SAL]
+ +(maketable sound) [LISP]
Assumes that +the samples in sound constitute one period of a wavetable, and returns a wavetable +suitable for use as the table argument to the osc function (see +below). Currently, tables are limited to 1,000,000 samples. This limit is the compile-time constant max_table_len set in sound.h.

+
build-harmonic(n, table-size) [SAL]
+ +(build-harmonic n table-size) [LISP]
Intended for +constructing wavetables, this function returns a sound of length table-size +samples containing n periods of a sinusoid. These can be scaled and +summed to form a waveform with the desired harmonic content. See "Waveforms" for an example.

+
control-warp(warp-fn, signal, [wrate]) [SAL]
+ +(control-warp warp-fn signal wrate) [LISP]
Applies a +warp function warp-fn to signal using function composition. If wrate is omitted, linear +interpolation is used. warp-fn is a mapping from score (logical) time +to real time, and signal is a function from score time to real values. +The result is a function from real time to real values at a sample rate of +*control-srate*. See sound-warp for an explanation of +wrate and high-quality warping.

+
+mult(beh1, beh2, ...) [SAL]
+ +(mult beh1 beh2 ...) [LISP]
Returns the product of +behaviors. The arguments may also be numbers, in which case simple multiplication is performed. If a number and sound are mixed, the scale function is used to scale the sound by the number. When sounds are multiplied, the resulting sample rate is the maximum sample rate of the factors.

+
prod(beh1, beh2, ...) [SAL]
+ +(prod beh1 beh2 ...) [LISP]
Same as mult.

+
+pan(sound, where) [SAL]
+ +(pan sound where) [LISP]
Pans sound (a behavior) according to where (another behavior or a number). Sound must be monophonic. Where may be a monophonic sound (e.g. (ramp) or simply a number (e.g. 0.5). In either case, where should range from 0 to 1, where 0 means pan completely left, and 1 means pan completely right. For intermediate values, the sound to each channel is scaled linearly. Presently, pan does not check its arguments carefully.

+
prod(beh1, beh2, ...) [SAL]
+ +(prod beh1 beh2 ...) [LISP]
Same as mult.

+
+resample(sound, srate) [SAL]
+ +(resample sound srate) [LISP]
Similar to force-srate, except +high-quality interpolation is used to prefilter and reconstruct the signal +at the new sample rate. Also, the result is scaled by 0.95 to reduce problems with +clipping. (See also sound-warp.)

+
+scale(scale, sound) [SAL]
+ +(scale scale sound) [LISP]
Scales the amplitude of sound by the factor scale. Identical function to snd-scale, except that it handles multichannel sounds. Sample rates, start times, etc. are taken from sound.

+
scale-db(db, sound) [SAL]
+ +(scale-db db sound) [LISP]
Scales the amplitude of sound by the factor db, expressed in decibels. Sample rates, start times, etc. are taken from sound.

+
scale-srate(sound, scale) [SAL]
+ +(scale-srate sound scale) [LISP]
Scales the sample rate of sound by scale factor. This has the effect of linearly shrinking or stretching time (the sound is not upsampled or downsampled). This is a special case of snd-xform (see Section "Signal Operations").

+
shift-time(sound, shift) [SAL]
+ +(shift-time sound shift) [LISP]
Shift sound +by shift seconds. If the sound is + +f(t), then the result is + +f(t - shift). +See Figure 5. This is a special +case of snd-xform (see Section "Signal Operations"). +
+

+


+
+

+ +

+Figure 5: The shift-time function shifts a sound in time +according to its shift argument. + +


+

+

+
+sound-warp(warp-fn, signal [, wrate]) [SAL]
+ +(sound-warp warp-fn signal [wrate]) [LISP]
Applies a +warp function warp-fn to signal using function composition. If the optional parameter wrate is omitted or NIL, linear +interpolation is used. Otherwise, high-quality sample interpolation is used, and the +result is scaled by 0.95 to reduce problems with clipping (interpolated samples can +exceed the peak values of the input samples.) +warp-fn is a mapping from score (logical) time +to real time, and signal is a function from score time to real values. +The result is a function from real time to real values at a sample rate of *sound-srate*. +See also control-warp. +

+
+If wrate is not NIL, it must be a number. The parameter indicates that +high-quality resampling should be used and specifies the sample rate for the +inverse of warp-fn. Use the lowest number you can. + (See below for details.) Note that high-quality resampling is +much slower than linear interpolation. +

+
+To perform high-quality resampling by a fixed ratio, as opposed to a +variable ratio allowed in sound-warp, use scale-srate to +stretch or shrink the sound, and then resample to restore the +original sample rate. +

+
+Sound-warp and control-warp both take the inverse of +warp-fn to get a function from real time to score time. Each sample +of this inverse is thus a score time; signal is evaluated at each of +these score times to yield a value, which is the desired result. The +sample rate of the inverse warp function is somewhat arbitrary. With linear +interpolation, the inverse warp function sample rate is taken to be the +output sample rate. Note, however, that the samples of the inverse warp +function are stored as 32-bit floats, so they have limited precision. Since +these floats represent sample times, rounding can be a problem. Rounding +in this case is equivalent to adding jitter to the sample times. Nyquist +ignores this problem for ordinary warping, but for high-quality warping, the +jitter cannot be ignored. +

+
+The solution is to use a rather low sample rate +for the inverse warp function. Sound-warp can then linearly +interpolate this signal using double-precision floats to minimize jitter +between samples. The sample rate is a compromise: a low sample rate +minimizes jitter, while a high sample rate does a better job of capturing +detail (e.g. rapid fluctuations) in the warp function. A good rule of thumb +is to use at most 1,000 to 10,000 samples for the inverse warp function. For +example, if the result will be 1 minute of sound, use a sample rate of +3000 samples / 60 seconds = 50 samples/second. Because Nyquist has no +advance information about the warp function, the inverse warp function +sample rate must be provided as a parameter. When in doubt, just try +something and let your ears be the judge.

+
integrate(signal) [SAL]
+ +(integrate signal) [LISP]
Computes the integral of signal. The start time, sample rate, etc. are taken from signal.

+
slope(signal) [SAL]
+ +(slope signal) [LISP]
Computes the first derivative (slope) of signal. The start time, sample rate, etc. are taken from signal. +
+

+

Oscillators
+ +
+
+osc(pitch [, duration, table, phase]) [SAL]
+ +(osc pitch [duration table phase]) [LISP]
Returns +a sound which +is the table oscillated at pitch for the given duration, +starting with the phase (in degrees). +Defaults are: duration 1.0 +(second), table *table*, +phase 0.0. The default value of *table* is a sinusoid. Duration is stretched by *warp* and +*sustain*, amplitude is nominally 1, but scaled by *loudness*, the start time is logical time 0, transformed by *warp*, and the sample rate is *sound-srate*. +The effect of time-warping is to warp the starting and ending times only; the +signal has a constant unwarped frequency. + Note 1: table is a list of the form +
+(sound pitch-number periodic)
+ +
+where the first element is a sound, the second is the pitch of the sound +(this is not redundant, because the sound may represent any number of +periods), and the third element is T if the sound is one period of +a periodic signal, or nil if the sound is a sample that should not +be looped. The maximum table size is set by max_table_len in sound.h, and is currently set to 1,000,000. +Note 2: in the current implementation, it is assumed that the +output should be periodic. See snd-down and snd-up for resampling one-shot sounds to a desired sample rate. A future version of osc +will handle both cases. +Note 3: When osc is called, memory is allocated for the table, and samples are copied from the sound (the first element of the list which is the table parameter) to the memory. Every instance of osc has a private copy of the table, so the total storage can become large in some cases, for example in granular synthesis with many instances of osc. In some cases, it may make sense to use snd-flatten (see Section
"Accessing and Creating Sound") to cause the sound to be fully realized, after which the osc and its table memory can be reclaimed by garbage collection. The partial function (see below) does not need a private table and does not use much space.

+
+partial(pitch, env) [SAL]
+ +(partial pitch env) [LISP]
Returns a sinusoid at +the indicated pitch; the sound is multiplied by env. The start time and +duration are taken from env, which is of course subject to +transformations. The sample rate is *sound-srate*. The partial +function is faster than osc.

+
+sine(pitch [, duration]) [SAL]
+ +(sine pitch [duration]) [LISP]
Returns a sinusoid at +the indicated pitch. The sample rate is *sound-srate*. +This function is like osc with +respect to transformations. The sine function is faster than +osc.

+
hzosc(hz [, table, phase]) [SAL]
+ +(hzosc hz [table phase]) [LISP]
Returns a sound which is the table oscillated at hz starting at phase degrees. The default table is *table* and the default phase is 0.0. The default duration is 1.0, but this is stretched as in osc (see above). The hz parameter may be a SOUND, in which case the duration of the result is the duration of hz. The sample rate is *sound-srate*.

+
osc-saw(hz) [SAL]
+ +(osc-saw hz) [LISP]
Returns a sawtooth waveshape at the indicated frequency (in Hertz). The sample rate is *sound-srate*. The hz parameter may be a sound as in hzosc (see above).

+
osc-tri(hz) [SAL]
+ +(osc-tri hz) [LISP]
Returns a triangle waveshape at the indicated frequency (in Hertz). The sample rate is *sound-srate*. The hz parameter may be a sound as in hzosc (see above).

+
osc-pulse(hz, bias [, compare-shape]) [SAL]
+ +(osc-pulse hz bias [compare-shape]) [LISP]
Returns a square pulse with variable width at the indicated frequency (in Hertz). The bias parameter controls the pulse width and should be between -1 and +1, giving a pulse width from 0% (always at -1) to 100% (always at +1). When bias is zero, a square wave is generated. Bias may be a SOUND to create varying pulse width. If bias changes rapidly, strange effects may occur. The optional compare-shape defaults to a hard step at zero, but other shapes may be used to achieve non-square pulses. The osc-pulse behavior is written in terms of other behaviors and defined in the file nyquist.lsp using just a few lines of code. Read the code for the complete story.

+
+amosc(pitch, modulation [, table, +phase]) [SAL]
+ +(amosc pitch modulation [table phase]) [LISP]
Returns a +sound which is table oscillated at pitch. The output +is multiplied by modulation +for the duration of the sound modulation. +osc-table defaults to +*table*, and phase is the starting phase (default 0.0 degrees) +within osc-table. The sample rate is *sound-srate*.

+
+fmosc(pitch, modulation [, table, +phase]) [SAL]
+ +(fmosc pitch modulation [table phase]) [LISP]
Returns a +sound which is table oscillated at pitch plus modulation +for the duration of the sound modulation. +osc-table defaults to +*table*, and phase is the starting phase (default 0.0 degrees) +within osc-table. The modulation +is expressed in hz, e.g. a sinusoid modulation signal with an +amplitude of 1.0 (2.0 peak to peak), will cause a +/- 1.0 hz +frequency deviation in sound. Negative frequencies are correctly +handled. The sample rate is *sound-srate*.

+
+fmfb(pitch, index [, dur]) [SAL]
+ +(fmfb pitch index [dur]) [LISP]
Returns +a sound generated by feedback FM synthesis. The pitch parameter +(given in the usual half-step units) +controls the fundamental frequency. The index is the amount of +feedback, which may be a SOUND or a FLONUM. If index is +a FLONUM, dur must be provided (a FLONUM) to specify +the duration. Otherwise, dur is ignored if present and the duration is +determined by that of index. The sample rate is *sound-srate*. +A sinusoid table is used. +If index is below 1.1, this generates a sawtooth-like waveform.

+
+buzz(n, pitch, modulation) [SAL]
+ +(buzz n pitch modulation) [LISP]
Returns a +sound with n harmonics of equal amplitude and a total amplitude +of 1.0, using a well-known function of two cosines. If n (an integer) +is less than 1, it is set to 1. Aliasing will occur if n is too large. +The duration is +determined by the duration of the sound modulation, which is a +frequency modulation term expressed in Hz (see Section "Oscillators"). +Negative frequencies are correctly handled. +The sample rate is *sound-srate*.

+
+pluck(pitch [, duration, final-amplitude]) [SAL]
+ +(pluck pitch [duration final-amplitude]) [LISP]
Returns a sound at the +given pitch created using a modified Karplus-Strong plucked string +algorithm. The tone decays from an amplitude of about 1.0 to about +final-amplitude in duration seconds. The default values are to +decay to 0.001 (-60dB) in 1 second. The sample rate is *sound-srate*.

+
+siosc(pitch, +modulation, tables) [SAL]
+ +(siosc pitch modulation tables) [LISP]
Returns a sound constructed by +interpolating through a succession of periodic waveforms. The frequency is +given (in half steps) by pitch to which a modulation signal (in hz) +is added, exactly as in fmosc. The tables specify a list of +waveforms as follows: (table0 time1 table2 ... timeN +tableN), where each table is a sound representing one period. Each +time is a time interval measured from the starting time. The time is +scaled by the nominal duration (computed using (local-to-global +(get-sustain))) to get the actual time. Note that this implies linear +stretching rather than continuous timewarping of the interpolation or the +breakpoints. The waveform is table0 at the starting time, table1 +after time1 (scaled as described), and so on. The duration and logical +stop time is given by modulation. If modulation is shorter than +timeN, then the full sequence of waveforms is not used. If +modulation is longer than timeN, tableN is used after timeN +without further interpolation.

+
+sampler(pitch, modulation + [, sample, npoints]) [SAL]
+ +(sampler pitch modulation [sample npoints]) [LISP]
Returns a sound constructed by reading a sample from +beginning to end and then splicing on copies of the same sound from +a loop point to the end. +The pitch and modulation parameters are used as in fmosc +described above. The optional sample (which defaults to the global +variable *table* is a list of the form +
+(sound pitch-number loop-start)
+ +
+where the first element is a sound containing the sample, the second is the +pitch of the sample, and the third element is the time of the loop point. If +the loop point is not in the bounds of the sound, it is set to zero. +The optional npoints specifies how many points should be used for sample +interpolation. Currently this parameter defaults to 2 and only 2-point +(linear) interpolation is implemented. It is an error to modulate such that the frequency +is negative. Note also that the loop point may be fractional. +The sample rate is *sound-srate*. +
+

+

Piece-wise Approximations
+ +There are a number of related behaviors for piece-wise approximations to functions. The simplest of these, pwl was mentioned earlier in the manual. It takes a list of breakpoints, assuming an initial point at (0, 0), and a final value of 0. An analogous piece-wise exponential function, pwe, is provided. Its implicit starting and stopping values are 1 rather than 0. Each of these has variants. You can specify the initial and final values (instead of taking the default). You can specify time in intervals rather than cummulative time. Finally, you can pass a list rather than an argument list. This leads to 16 versions: +
+
Piece-wise Linear Functions:
+	Cummulative Time:
+		Default initial point at (0, 0), final value at 0:
+			pwl
+			pwl-list
+		Explicit initial value:
+			pwlv
+			pwlv-list
+	Relative Time:
+		Default initial point at (0, 0), final value at 0:
+			pwlr
+			pwlr-list
+		Explicit initial value:
+			pwlvr
+			pwlvr-list
+

+Piece-wise Exponential Functions: + Cummulative Time: + Default initial point at (0, 1), final value at 1: + pwe + pwe-list + Explicit initial value: + pwev + pwev-list + Relative Time: + Default initial point at (0, 1), final value at 1: + pwer + pwer-list + Explicit initial value: + pwevr + pwevr-list +

+All of these functions are implemented in terms of pwl (see nyquist.lsp for the implementations. There are infinite opportunities for errors in these functions: if you leave off a data point, try to specify points in reverse order, try to create an exponential that goes to zero or negative values, or many other bad things, the behavior is not well-defined. Nyquist should not crash, but Nyquist does not necessarily attempt to report errors at this time. +

+

+
+ +pwl(t1, l1, t2, l2, ... tn) [SAL]
+ +(pwl t1 l1 t2 l2 ... tn) [LISP]
Creates +a piece-wise linear envelope with breakpoints at (0, 0), (t1, +l1), (t2, l2), ... (tn, 0). The breakpoint +times are scaled linearly by the value of *sustain* (if +*sustain* is a SOUND, it is evaluated once at the starting +time of the envelope). Each breakpoint time is then mapped according to +*warp*. The result is a linear interpolation (unwarped) between +the breakpoints. The sample rate is *control-srate*. Breakpoint +times are quantized to the nearest sample time. If you specify one or more +breakpoints withing one sample period, pwl attempts to give a good +approximation to the specified function. In particular, if two breakpoints +are simultaneous, pwl will move one of them to an adjacent sample, +producing a steepest possible step in the signal. The exact details of this +"breakpoint munging" is subject to change in future versions. Please report +any cases where breakpoint lists give unexpected behaviors. The author will +try to apply the "principle of least surprise" to the design. Note that +the times are relative to 0; they are not durations of each envelope +segment.

+
pwl-list(breakpoints) [SAL]
+ +(pwl-list breakpoints) [LISP]
If you have a list of +breakpoints, you can use apply to apply the pwl function to +the breakpoints, but if the list is very long (hundreds or thousands of +points), you might get a stack overflow because XLISP has a fixed-size +argument stack. Instead, call pwl-list, passing one argument, the +list of breakpoints.

+
pwlv(l1, t2, l2, t3, t3, ... tn, ln) [SAL]
+ +(pwlv l1 t2 l2 t3 t3 ... tn ln) [LISP]
Creates +a piece-wise linear envelope with breakpoints at (0, l1), (t2, l2), etc., ending with (tn, ln. Otherwise, the behavior is like that of pwl.

+
pwlv-list(breakpoints) [SAL]
+ +(pwlv-list breakpoints) [LISP]
A version of pwlv that takes a single list of breakpoints as its argument. See pwl-list above for the rationale.

+
pwlr(i1, l1, i2, l2, ... in) [SAL]
+ +(pwlr i1 l1 i2 l2 ... in) [LISP]
Creates +a piece-wise linear envelope with breakpoints at (0, 0), (t1, +l1), (t2, l2), ... (tn, 0), where tj is the sum of i1 through ij. In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of pwl.

+
pwlr-list(breakpoints) [SAL]
+ +(pwlr-list breakpoints) [LISP]
A version of pwlr that takes a single list of breakpoints as its argument. See pwl-list above for the rationale.

+
pwlvr(l1, i2, l2, i3, i3, ... in, ln) [SAL]
+ +(pwlvr l1 i2 l2 i3 i3 ... in ln) [LISP]
Creates +a piece-wise linear envelope with breakpoints at (0, l1), (t2, l2), etc., ending with (tn, ln, where tj is the sum of i2 through ij. In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of pwlv.

+
pwlvr-list(breakpoints) [SAL]
+ +(pwlvr-list breakpoints) [LISP]
A version of pwlvr that takes a single list of breakpoints as its argument. See pwl-list above for the rationale.

+
pwe(t1, l1, t2, l2, ... tn) [SAL]
+ +(pwe t1 l1 t2 l2 ... tn) [LISP]
Creates +a piece-wise exponential envelope with breakpoints at (0, 1), (t1, +l1), (t2, l2), ... (tn, 1). Exponential segments means that the ratio of values from sample to sample is constant within the segment. (The current implementation actually takes the log of each value, computes a piece-wise exponential from the points using pwl, then exponentiates each resulting sample. A faster implementation is certainly possible!) Breakpoint values (lj) must be greater than zero. Otherwise, this function is similar to pwl, including stretch by *sustain*, mapping according to *warp*, sample rate based on *control-srate*, and "breakpoint munging" (see pwl described above). Default initial and final values are of dubious value with exponentials. See pwev below for the function you are probably looking for.

+
pwe-list(breakpoints) [SAL]
+ +(pwe-list breakpoints) [LISP]
A version of pwe that takes a single list of breakpoints as its argument. See pwl-list above for the rationale.

+
+pwev(l1, t2, l2, t3, t3, ... tn, ln) [SAL]
+ +(pwev l1 t2 l2 t3 t3 ... tn ln) [LISP]
Creates +a piece-wise exponential envelope with breakpoints at (0, l1), (t2, l2), etc., ending with (tn, ln). Otherwise, the behavior is like that of pwe.

+
pwev-list(breakpoints) [SAL]
+ +(pwev-list breakpoints) [LISP]
A version of pwev that takes a single list of breakpoints as its argument. See pwl-list above for the rationale.

+
pwer(i1, l1, i2, l2, ... in) [SAL]
+ +(pwer i1 l1 i2 l2 ... in) [LISP]
Creates +a piece-wise exponential envelope with breakpoints at (0, 1), (t1, +l1), (t2, l2), ... (tn, 1), where tj is the sum of i1 through ij. In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of pwe. Consider using pwerv instead of this one.

+
pwer-list(breakpoints) [SAL]
+ +(pwer-list breakpoints) [LISP]
A version of pwer that takes a single list of breakpoints as its argument. See pwl-list above for the rationale.

+
pwevr(l1, i2, l2, i3, i3, ... in, ln) [SAL]
+ +(pwevr l1 i2 l2 i3 i3 ... in ln) [LISP]
Creates +a piece-wise exponential envelope with breakpoints at (0, l1), (t2, l2), etc., ending with (tn, ln, where tj is the sum of i2 through ij. In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of pwev. Note that this is similar to the csound GEN05 generator. Which is uglier, GEN05 or pwevr?

+
pwevr-list(breakpoints) [SAL]
+ +(pwevr-list breakpoints) [LISP]
A version of pwevr that takes a single list of breakpoints as its argument. See pwl-list above for the rationale. +
+
Filter Behaviors
+
+
+ +alpass(sound, decay, hz [, minhz]) [SAL]
+ +(alpass sound decay hz [minhz]) [LISP]
Applies an all-pass filter to sound. This all-pass filter creates a delay effect without the resonances of a comb filter. The decay time of the filter is given by decay. The hz parameter must be a number or sound greater than zero. It is used to compute delay, which is then rounded to the nearest integer number of samples (so the frequency is not always exact. Higher sampling rates yield better delay resolution.) The decay may be a sound or a number. In either case, it must also be positive. (Implementation note: an exponentiation is needed to convert decay into the feedback parameter, and exponentiation is typically more time-consuming than the filter operation itself. To get high performance, provide decay at a low sample rate.) The resulting sound will have the start time, sample rate, etc. of sound. If hz is of type SOUND, the delay may be time-varying. Linear interpolation is then used for fractional sample delay, but it should be noted that linear interpolation implies a low-pass transfer function. Thus, this filter may behave differently with a constant SOUND than it does with a FLONUM value for hz. In addition, if hz is of type SOUND, then minhz is required. The hz parameter will be clipped to be greater than minhz, placing an upper bound on the delay buffer length.

+
+comb(sound, decay, hz) [SAL]
+ +(comb sound decay hz) [LISP]
Applies a comb filter to sound. A comb filter emphasizes (resonates at) frequencies that are multiples of a hz. The decay time of the resonance is given by decay. This is a variation on feedback-delay (see below). The hz parameter must be a number greater than zero. It is used to compute delay, which is then rounded to the nearest integer number of samples (so the frequency is not always exact. Higher sampling rates yield better delay resolution.) The decay may be a sound or a number. In either case, it must also be positive. (Implementation note: an exponentiation is needed to convert decay into the feedback parameter for feedback-delay, and exponentiation is typically more time-consuming than the filter operation itself. To get high performance, provide decay at a low sample rate.) The resulting sound will have the start time, sample rate, etc. of sound.

+
+congen(gate, risetime, falltime) [SAL]
+ +(congen gate risetime falltime) [LISP]
Implements an analog synthesizer-style contour generator. The input gate normally goes from 0.0 to 1.0 to create an attack and from 1.0 to 0.0 to start a release. During the attack (output is increasing), the output converges half-way to gate in risetime (a FLONUM) seconds. During the decay, the half-time is falltime seconds. The sample rate, start time, logical stop, and terminate time all come from gate. If you want a nice decay, be sure that the gate goes to zero and stays there for awhile before gate terminates, because congen (and all Nyquist sounds) go immediately to zero at termination time. For example, you can use pwl to build a pulse followed by some zero time: +
+(pwl 0 1 duty 1 duty 0 1)
+
+ +Assuming duty is less than 1.0, this will be a pulse of duration duty followed by zero for a total duration of 1.0. +
+(congen (pwl 0 1 duty 1 duty 0 1) 0.01 0.05)
+
+ +will have a duration of 1.0 because that is the termination time of the pwl input. The decaying release of the resulting envelope will be truncated to zero at time 1.0. (Since the decay is theoretically infinite, there is no way to avoid truncation, although you could multiply by another envelope that smoothly truncates to zero in the last millisecond or two to get both an exponential decay and a smooth final transition to zero.)

+
+convolve(sound, +response) [SAL]
+ +(convolve sound response) [LISP]
Convolves two signals. The first can be any length, but the +computation time per sample and the total space required are proportional to +the length of response.

+
+feedback-delay(sound, delay, feedback) [SAL]
+ +(feedback-delay sound delay feedback) [LISP]
Applies feedback delay to sound. The delay must be a number (in seconds). It is rounded to the nearest sample to determine the length of the delay. The sample rate is the maximum from sound and feedback (if feedback is also a sound). The amound of feedback should be less than one to avoid an exponential increase in amplitude. The start time and stop time, and logical stop time are taken from sound. Since output is truncated at the stop time of sound, you may want to append some silence to sound to give the filter time to decay.

+
+lp(sound, cutoff) [SAL]
+ +(lp sound cutoff) [LISP]
Filters sound +using a first-order Butterworth low-pass filter. Cutoff may be a float +or a signal (for time-varying filtering) and expresses hertz. Filter +coefficients (requiring trig functions) are recomputed at the sample rate of +cutoff. The resulting sample rate, start time, etc. are taken from sound.

+
tone(sound, cutoff) [SAL]
+ +(tone sound cutoff) [LISP]
No longer defined; use lp instead, or define it by adding (setfn tone lp) to your program.

+
+hp(sound, cutoff) [SAL]
+ +(hp sound cutoff) [LISP]
Filters sound +using a first-order Butterworth high-pass filter. Cutoff may be a +float or a signal (for time-varying filtering) and expresses hertz. Filter +coefficients (requiring trig functions) are recomputed at the sample rate of +cutoff. This filter is an exact complement of lp.

+
atone(sound, cutoff) [SAL]
+ +(atone sound cutoff) [LISP]
No longer defined; use hp instead, or define it by adding (setfn atone hp) to your program.

+
+reson(sound, center, bandwidth, n) [SAL]
+ +(reson sound center bandwidth n) [LISP]
Apply +a resonating filter to sound with center frequency center (in hertz), +which may be a float or a signal. Bandwidth is the filter bandwidth (in +hertz), which may also be a signal. Filter coefficients (requiring trig +functions) are recomputed at each new sample of either center or +bandwidth, and coefficients are not interpolated. The last +parameter n specifies the type of normalization as in Csound: A value of 1 specifies a peak amplitude +response of 1.0; all frequencies other than hz are attenuated. A +value of 2 specifies the overall RMS value of the amplitude response +is 1.0; thus filtered white noise would retain the same power. A value of +zero specifies no scaling. The resulting sample rate, start time, etc. are taken from sound.

+
One application of reson is to simulate resonances in the human vocal tract. +See demos/voice_synthesis.htm +for sample code and documentation.

+
+areson(sound, center, bandwidth, n) [SAL]
+ +(areson sound center bandwidth n) [LISP]
The areson filter is an exact +complement of reson such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal.

+
+shape(signal, table, origin) [SAL]
+ +(shape signal table origin) [LISP]
A waveshaping function. Use table as a function; apply the function to each sample of signal to yield a new sound. Signal should range from -1 to +1. Anything beyond these bounds is clipped. Table is also a sound, but it is converted into a lookup table (similar to table-lookup oscillators). The origin is a FLONUM and gives the time which should be considered the origin of table. (This is important because table cannot have values at negative times, but signal will often have negative values. The origin gives an offset so that you can produce suitable tables.) The output at time t is: +
+table(origin + clip(signal(t))
+ +
+where clip(x) = max(1, min(-1, x)). +(E.g. if table is a signal defined over the interval [0, 2], then origin should be 1.0. The value of table at time 1.0 will be output when the input signal is zero.) The output has the same start time, sample rate, etc. as signal. The shape function will also accept multichannel signals and tables.

+
Further discussion and examples can be found in +demos/distortion.htm. +The shape +function is also used to map frequency to amplitude to achieve a spectral envelope for +Shepard tones in demos/shepard.lsp.

+
+biquad(signal, b0, b1, b2, a0, a1, a2) [SAL]
+ +(biquad signal b0 b1 b2 a0 a1 a2) [LISP]
A fixed-parameter biquad filter. All filter coefficients are FLONUMs. See also lowpass2, highpass2, bandpass2, notch2, allpass2, eq-lowshelf, eq-highshelf, eq-band, lowpass4, lowpass6, highpass4, and highpass8 in this section for convenient variations based on the same filter. The equations for the filter are: zn = sn + a1 * zn-1 + a2 * zn-2, and yn = zn * b0 + zn-1 * b1 + zn-2 * b2.

+
+biquad-m(signal, b0, b1, b2, a0, a1, a2) [SAL]
+ +(biquad-m signal b0 b1 b2 a0 a1 a2) [LISP]
A fixed-parameter biquad filter with Matlab sign conventions for a0, a1, and a2. All filter coefficients are FLONUMs.

+
+lowpass2(signal, hz [, q]) [SAL]
+ +(lowpass2 signal hz [q]) [LISP]
A fixed-parameter, second-order lowpass filter based on snd-biquad. The cutoff frequency is given by hz (a FLONUM) and an optional Q factor is given by q (a FLONUM).

+
+highpass2(signal, hz [, q]) [SAL]
+ +(highpass2 signal hz [q]) [LISP]
A fixed-parameter, second-order highpass filter based on snd-biquad. The cutoff frequency is given by hz (a FLONUM) and an optional Q factor is given by q (a FLONUM).

+
+bandpass2(signal, hz [, q]) [SAL]
+ +(bandpass2 signal hz [q]) [LISP]
A fixed-parameter, second-order bandpass filter based on snd-biquad. The center frequency is given by hz (a FLONUM) and an optional Q factor is given by q (a FLONUM).

+
+notch2(signal, hz [, q]) [SAL]
+ +(notch2 signal hz [q]) [LISP]
A fixed-parameter, second-order notch filter based on snd-biquad. The center frequency is given by hz (a FLONUM) and an optional Q factor is given by q (a FLONUM).

+
+allpass2(signal, hz [, q]) [SAL]
+ +(allpass2 signal hz [q]) [LISP]
A fixed-parameter, second-order allpass filter based on snd-biquad. The frequency is given by hz (a FLONUM) and an optional Q factor is given by q (a FLONUM).

+
+eq-lowshelf(signal, hz, gain [, slope]) [SAL]
+ +(eq-lowshelf signal hz gain [slope]) [LISP]
A fixed-parameter, second-order bass shelving equalization (EQ) filter based on snd-biquad. The hz parameter (a FLONUM)is the halfway point in the transition, and gain (a FLONUM) is the bass boost (or cut) in dB. The optional slope (a FLONUM) is 1.0 by default, and response becomes peaky at values greater than 1.0.

+
+eq-highshelf(signal, hz, gain [, slope]) [SAL]
+ +(eq-highshelf signal hz gain [slope]) [LISP]
A fixed-parameter, second-order treble shelving equalization (EQ) filter based on snd-biquad. The hz parameter (a FLONUM)is the halfway point in the transition, and gain (a FLONUM) is the treble boost (or cut) in dB. The optional slope (a FLONUM) is 1.0 by default, and response becomes peaky at values greater than 1.0.

+
+eq-band(signal, hz, gain, width) [SAL]
+ +(eq-band signal hz gain width) [LISP]
A fixed- or variable-parameter, second-order midrange equalization (EQ) filter based on snd-biquad, snd-eqbandcv and snd-eqbandvvv. The hz parameter (a FLONUM) is the center frequency, gain (a FLONUM) is the boost (or cut) in dB, and width (a FLONUM) is the half-gain width in octaves. Alternatively, hz, gain, and width may be SOUNDs, but they must all have the same sample rate, e.g. they should all run at the control rate or at the sample rate.

+
+lowpass4(signal, hz) [SAL]
+ +(lowpass4 signal hz) [LISP]
A four-pole Butterworth lowpass filter. The cutoff frequency is hz (a FLONUM).

+
+lowpass6(signal, hz) [SAL]
+ +(lowpass6 signal hz) [LISP]
A six-pole Butterworth lowpass filter. The cutoff frequency is hz (a FLONUM).

+
+lowpass8(signal, hz) [SAL]
+ +(lowpass8 signal hz) [LISP]
An eight-pole Butterworth lowpass filter. The cutoff frequency is hz (a FLONUM).

+
+highpass4(signal, hz) [SAL]
+ +(highpass4 signal hz) [LISP]
A four-pole Butterworth highpass filter. The cutoff frequency is hz (a FLONUM).

+
+highpass6(signal, hz) [SAL]
+ +(highpass6 signal hz) [LISP]
A six-pole Butterworth highpass filter. The cutoff frequency is hz (a FLONUM).

+
+highpass8(signal, hz) [SAL]
+ +(highpass8 signal hz) [LISP]
An eight-pole Butterworth highpass filter. The cutoff frequency is hz (a FLONUM).

+
+tapv(sound, offset, +vardelay, maxdelay) [SAL]
+ +(tapv sound offset vardelay maxdelay) [LISP]
A delay line with a variable position tap. +Identical to snd-tapv. See it for details ("Signal Operations").

+
Effects
+
+
+ +nrev(sound, decay, mix) [SAL]
+ +(nrev sound decay mix) [LISP]

+
jcrev(sound, decay, mix) [SAL]
+ +(jcrev sound decay mix) [LISP]

+
prcrev(sound, decay, mix) [SAL]
+ +(prcrev sound decay mix) [LISP] +These reverbs (nrev, jcrev, and prcrev) are implemented +in STK (running within Nyquist). nrev derives from Common Music's +NRev, which consists of 6 comb filters followed by 3 allpass filters, a + lowpass filter, and another allpass in series followed by two allpass +filters in parallel. jcrev is the John Chowning +reverberator which is based on the use of networks of simple allpass +and comb delay filters. This reverb implements three series allpass units, +followed by four parallel comb filters, and two decorrelation delay +lines in parallel at the output. prcrev is a Perry Cook's +reverberator which is based on the Chowning/Moorer/Schroeder +reverberators using networks of simple allpass and comb delay filters. +This one implements two series allpass units and two parallel comb filters. +The sound input may be single or multi-channel. The decay time is +in seconds, and mix sets the mixture of input sound reverb sound, +where 0.0 means input only (dry) and 1.0 means reverb only (wet).

+
+stkchorus(sound, depth, freq, mix [, delay]) [SAL]
+ +(stkchorus sound depth freq mix [delay]) [LISP]
Chorus +implemented in STK. The input sound can be single or multi-channel. +The FLONUM parameters depth and freq set +the modulation +depth from 0 to 1 +and modulation frequency (in Hz), and mix sets the mixture +of input sound and chorused sound, where 0.0 means input sound only (dry) +and 1.0 means chorused sound only (wet). The parameter delay is a + FIXNUM representing the median desired delay length in samples.

+
+pitshift(sound, shift, mix) [SAL]
+ +(pitshift sound shift mix) [LISP]
A pitch + shifter implemented in STK. The input sound, a single-channel + or multi-channel SOUND is pitch-shifted by shift, +a FLONUM ratio. A value of 1.0 means no shift. The parameter mix + sets the mixture of input and shifted sounds. A value of 0.0 +means input only (dry) +and a value of 1.0 means shifted sound only (wet). +
+

+

Physical Models
+
+
+ +clarinet(step, breath-env) [SAL]
+ +(clarinet step breath-env) [LISP]
A +physical model of a clarinet from STK. The step parameter is a FLONUM +that controls the tube length, and the breath-env (a SOUND) +controls the air pressure +and also determines the length of the resulting sound. The breath-env signal +should range from zero to one.

+
clarinet-freq(step, breath-env, freq-env) [SAL]
+ +(clarinet-freq step breath-env freq-env) [LISP]
A variation of clarinet +that includes a variable frequency control, freq-env, which specifies +frequency deviation in Hz. The duration of the resulting sound is the minimum +duration of breath-env and freq-env. These parameters may be of type +FLONUM or SOUND. FLONUMs are coerced into SOUNDs +with a nominal duration arbitrarily set to 30.

+
clarinet-all(step, breath-env, freq-env, vibrato-freq, vibrato-gain, +reed-stiffness, noise) [SAL]
+ +(clarinet-all step breath-env freq-env vibrato-freq vibrato-gain reed-stiffness noise) [LISP]
A variation of clarinet-freq +that includes controls vibrato-freq (a FLONUM for vibrato frequency in Hertz), +vibrato-gain (a FLONUM for the amount of amplitude vibrato), +reed-stiffness (a FLONUM or SOUND controlling reed stiffness in the clarinet +model), and noise (a FLONUM or SOUND controlling noise amplitude in the input +air pressure). The vibrato-gain is a number from zero to one, where zero +indicates no vibrato, and one indicates a plus/minus 50% change in breath +envelope values. Similarly, the noise parameter ranges from zero to one where +zero means no noise and one means white noise with a peak amplitude of +plus/minus 40% of the breath-env. The reed-stiffness parameter varies +from zero to one. +The duration of the resulting sound is the minimum duration of +breath-env, freq-env, reed-stiffness, and noise. As with +clarinet-freq, these parameters may be either FLONUMs or +SOUNDs, and FLONUMs are coerced to sounds with a nominal +duration of 30.

+
+sax(step, breath-env) [SAL]
+ +(sax step breath-env) [LISP]
A +physical model of a sax from STK. The step parameter is a FLONUM +that controls the tube length, and the breath-env controls the air pressure +and also determines the length of the resulting sound. The breath-env signal +should range from zero to one.

+
sax-freq(step, breath-env, freq-env) [SAL]
+ +(sax-freq step breath-env freq-env) [LISP]
A variation of sax +that includes a variable frequency control, freq-env, which specifies +frequency deviation in Hz. The duration of the resulting sound is the minimum +duration of breath-env and freq-env. These parameters may be of type +FLONUM or SOUND. FLONUMs are coerced into SOUNDs +with a nominal duration arbitrarily set to 30.

+
sax-all(step, breath-env, freq-env, vibrato-freq, vibrato-gain, +reed-stiffness, noise, blow-pos, reed-table-offset) [SAL]
+ +(sax-all step breath-env freq-env vibrato-freq vibrato-gain reed-stiffness noise blow-pos reed-table-offset) [LISP]
A variation of + sax-freq +that includes controls vibrato-freq (a FLONUM for vibrato frequency in Hertz), +vibrato-gain (a FLONUM for the amount of amplitude vibrato), +reed-stiffness (a SOUND controlling reed stiffness in the sax +model), noise (a SOUND controlling noise amplitude in the input +air pressure), blow-pos (a SOUND controlling the point of excitation +of the air column), and reed-table-offset (a SOUND controlling a +parameter of the reed model). The vibrato-gain is a number from zero to one, where zero +indicates no vibrato, and one indicates a plus/minus 50% change in breath +envelope values. Similarly, the noise parameter ranges from zero to one where +zero means no noise and one means white noise with a peak amplitude of +plus/minus 40% of the breath-env. The reed-stiffness, blow-pos, and +reed-table-offset parameters all vary from zero to one. +The duration of the resulting sound is the minimum duration of +breath-env, freq-env, reed-stiffness, noise, breath-env, + blow-pos, and reed-table-offset. As with +sax-freq, these parameters may be either FLONUMs or +SOUNDs, and FLONUMs are coerced to sounds with a nominal +duration of 30.

+
+flute(step, breath-env) [SAL]
+ +(flute step breath-env) [LISP]
A physical model of a flute from STK. +The step parameter is a FLONUM that controls the tube +length, and the breath-env +controls the air pressure and also determines the starting time and +length of the resulting sound. The breath-env signal should + range from zero to one.

+
flute-freq(step, breath-env, freq-env) [SAL]
+ +(flute-freq step breath-env freq-env) [LISP]
A variation of flute + that includes a variable frequency control, freq-env, which + specifies frequency deviation in Hz. The duration of the +resulting sound is the minimum duration of breath-env and +freq-env. These parameters may be of type FLONUM or + SOUND. FLONUMs are coerced into SOUNDs with a +nominal duration arbitrary set to 30.

+
flute-all(step, breath-env, freq-env, vibrato-freq, + vibrato-gain, jet-delay, noise) [SAL]
+ +(flute-all step breath-env freq-env vibrato-freq vibrato-gain jet-delay noise) [LISP]
A variation of +clarinet-freq that includes controls vibrato-freq (a +FLONUM for vibrato frequency in Hz), vibrato-gain (a + FLONUM for the amount of amplitude vibrato), jet-delay + (a FLONUM or SOUND controlling jet delay in the + flute model), and +noise (a FLONUM or SOUND controlling noise amplitude +in the input air pressure). The vibrato-gain is a number from zero + to one where zero means no vibrato, and one indicates a plus/minus +50% change in breath envelope values. Similarly, the noise parameter + ranges from zero to one, where zero means no noise and one means white +noise with a peak amplitude of + plus/minus 40% of the breath-env. The jet-delay is a ratio + that controls a delay length from the flute model, and therefore it +changes the pitch of the resulting sound. A value of 0.5 will maintain +the pitch indicated by the step parameter. The duration of the +resulting sound is the minimum duration of breath-env, freq-env, +jet-delay, and noise. These parameters may be either +FLONUMs or SOUNDs, and FLONUMs are coerced + to sounds with a nominal duration of 30. + + +bowed(step, bowpress-env) [SAL]
+ +(bowed step bowpress-env) [LISP]
A physical model of a bowed string + instrument from STK. The step parameter is a FLONUM + that controls the string length, + and the bowpress-env controls the bow pressure and also +determines the duration of the resulting sound. The bowpress-env + signal should range from zero to one.

+
bowed-freq(step, bowpress-env, freq-env) [SAL]
+ +(bowed-freq step bowpress-env freq-env) [LISP]
A variation of bowed + that includes a variable frequency control, freq-env, which + specifies frequency deviation in Hz. The duration of the resulting + sound is the minimum duration of bowpress-env and freq-env. +These parameters may be of type FLONUM or SOUND. +FLONUMs are coerced into SOUNDs + with a nominal duration arbitrarily set to 30s.

+
+mandolin(step, dur, &optional detune) [SAL]
+ +(mandolin step dur detune) [LISP]
A physical model of a + plucked double-string instrument from STK. The step parameter + is a FLONUM wich specifies the desired pitch, dur + means the duration of the resulting sound and detune is a +FLONUM that controls the relative detune of the two strings. +A value of 1.0 means unison. The default value is 4.0. +Note: body-size (see snd-mandolin does not seem to + work correctly, so a default value is always used + by mandolin.

+
+wg-uniform-bar(step, bowpress-env) [SAL]
+ +(wg-uniform-bar step bowpress-env) [LISP]

+
wg-tuned-bar(step, bowpress-env) [SAL]
+ +(wg-tuned-bar step bowpress-env) [LISP]

+
wg-glass-harm(step, bowpress-env) [SAL]
+ +(wg-glass-harm step bowpress-env) [LISP]

+
wg-tibetan-bowl(step, bowpress-env) [SAL]
+ +(wg-tibetan-bowl step bowpress-env) [LISP]
These +sounds are presets for a Banded Wave Guide Percussion instrument implemented in STK. +The parameter step is a FLONUM + that controls the resultant pitch, and bowpress-env is a SOUND ranging +from zero to one that controls a parameter of the model. In addition, +bowpress-env determines the duration of the resulting sound. +(Note: The bowpress-env does not seems influence the timbral +quality of the resulting sound).

+
+modalbar(preset, step, dur) [SAL]
+ +(modalbar preset step dur) [LISP]
A physical model of a struck bar + instrument implemented in STK. The parameter preset is one of the +symbols +MARIMBA, VIBRAPHONE, AGOGO, WOOD1, +RESO, WOOD2, BEATS, TWO-FIXED, or +CLUMP. The symbol must be quoted, e.g. for SAL syntax use +quote(marimba), and for Lisp syntax use 'marimba. +The parameter step is a FLONUM that +sets the pitch (in steps), and dur is the duration in seconds.

+
+sitar(step, dur) [SAL]
+ +(sitar step dur) [LISP]
A sitar physical model implemented in STK. +The parameter step is a FLONUM that sets the pitch, + and dur is the duration. +
+

+

More Behaviors
+
+
+ +clip(sound, peak) [SAL]
+ +(clip sound peak) [LISP]
Hard limit sound +to the given peak, a positive number. The samples of sound are constrained between an upper value +of peak and a lower value of -peak. If sound is a number, clip will return sound limited by peak. If sound is a multichannel sound, clip returns a multichannel sound where each channel is clipped. The result has the type, sample rate, starting time, etc. of sound.

+
+s-abs(sound) [SAL]
+ +(s-abs sound) [LISP]
A generalized absolute value function. If sound is a SOUND, compute the absolute value of each sample. If sound is a number, just compute the absolute value. If sound is a multichannel sound, return a multichannel sound with s-abs applied to each element. The result has the type, sample rate, starting time, etc. of sound.

+
+s-sqrt(sound) [SAL]
+ +(s-sqrt sound) [LISP]
A generalized square root function. If sound is a SOUND, compute the square root of each sample. If sound is a number, just compute the square root. If sound is a multichannel sound, return a multichannel sound with s-sqrt applied to each element. The result has the type, sample rate, starting time, etc. of sound. In taking square roots, if an input sample is less than zero, the corresponding output sample is zero. This is done because the square root of a negative number is undefined.

+
+s-exp(sound) [SAL]
+ +(s-exp sound) [LISP]
A generalized exponential function. If sound is a SOUND, compute e^(x) for each sample x. If sound is a number x, just compute e^(x). If sound is a multichannel sound, return a multichannel sound with s-exp applied to each element. The result has the type, sample rate, starting time, etc. of sound.

+
+s-log(sound) [SAL]
+ +(s-log sound) [LISP]
A generalized natural log function. If sound is a SOUND, compute ln(x) for each sample x. If sound is a number x, just compute ln(x). If sound is a multichannel sound, return a multichannel sound with s-log applied to each element. The result has the type, sample rate, starting time, etc. of sound. Note that the ln of 0 is undefined (some implementations return negative infinity), so use this function with care.

+
+s-max(sound1, sound2) [SAL]
+ +(s-max sound1 sound2) [LISP]
Compute the maximum of two functions, sound1 and sound2. This function also accepts numbers and multichannel sounds and returns the corresponding data type. The start time of the result is the maximum of the start times of sound1 and sound2. The logical stop time and physical stop time of the result is the minimum of the logical stop and physical stop times respectively of sound1 and sound2. Note, therefore, that the result value is zero except within the bounds of both input sounds.

+
s-min(sound1, sound2) [SAL]
+ +(s-min sound1 sound2) [LISP]
Compute the minimum of two functions, sound1 and sound2. This function also accepts numbers and multichannel sounds and returns the corresponding data type. The start time of the result is the maximum of the start times of sound1 and sound2. The logical stop time and physical stop time of the result is the minimum of the logical stop and physical stop times respectively of sound1 and sound2. Note, therefore, that the result value is zero except within the bounds of both input sounds.

+
osc-note(pitch [, duration, env, loud, +table]) [SAL]
+ +(osc-note pitch [duration env loud table]) [LISP]
Same as osc, but osc-note +multiplies the result by env. The env may be a sound, +or a list supplying (t1 t2 +t4 l1 l2 l3). The result has a sample rate of *sound-srate*.

+
+quantize(sound, steps) [SAL]
+ +(quantize sound steps) [LISP]
Quantizes sound as follows: sound is multiplied by steps and rounded to the nearest integer. The result is then divided by steps. For example, if steps is 127, then a signal that ranges from -1 to +1 will be quantized to 255 levels (127 less than zero, 127 greater than zero, and zero itself). This would match the quantization Nyquist performs when writing a signal to an 8-bit audio file. The sound may be multi-channel.

+
ramp([duration]) [SAL]
+ +(ramp [duration]) [LISP]
Returns a +linear ramp from 0 to 1 +over duration (default is 1). The function actually reaches 1 at +duration, and therefore has one extra sample, making the total duration +be duration + 1/*Control-srate*. See Figure 6 for +more detail. Ramp is unaffected by the sustain transformation. The +effect of time warping is to warp the starting and ending times only. The +ramp itself is unwarped (linear). The sample rate is *control-srate*.

+
+rms(sound [, rate, window-size]) [SAL]
+ +(rms sound [rate window-size]) [LISP]
Computes the RMS of sound using a square window of size window-size. The result has a sample rate of rate. The default value of rate is 100 Hz, and the default window size is 1/rate seconds (converted to samples). The rate is a FLONUM and window-size is a FIXNUM. +
+

+


+
+

+ +

+Figure 6: Ramps generated by pwl and ramp functions. The +pwl version ramps toward the breakpoint (1, 1), but in order to ramp +back to zero at breakpoint (1, 0), the function never reaches an amplitude +of 1. If used at the beginning of a seq construct, the next sound +will begin at time 1. The ramp version actually reaches breakpoint +(1, 1); notice that it is one sample longer than the pwl version. If +used in a sequence, the next sound after ramp would start at time 1 + +P, where P is the sample period. + +


+

+

+
+ +recip(sound) [SAL]
+ +(recip sound) [LISP]
A generalized reciprocal function. +If sound is a SOUND, compute 1/x for each sample x. If sound is a number x, just compute 1/x. If sound is a multichannel sound, return a multichannel sound with recip applied to each element. The result has the type, sample rate, starting time, etc. of sound. Note that the reciprocal of 0 is undefined (some implementations return infinity), so use this function with care on sounds. Division of sounds is accomplished by multiplying by the reciprocal. Again, be careful not to divide by zero.

+
s-rest([duration]) [SAL]
+ +(s-rest [duration]) [LISP]
Create silence (zero samples) +for the given +duration at the sample rate *sound-srate*. +Default duration is 1.0 sec, and the sound is transformed in time according +to *warp*. Note: rest is a Lisp function that is equivalent to cdr. Be careful to use s-rest when you need a sound!

+
+noise([duration]) [SAL]
+ +(noise duration) [LISP]
Generate noise with the given +duration. Duration (default is 1.0) +is transformed according to *warp*. The +sample rate is *sound-srate* and the amplitude is +/- *loud*.

+
+yin(sound, minstep, maxstep, stepsize) [SAL]
+ +(yin sound minstep maxstep stepsize) [LISP]
Fundamental +frequency estimation (pitch detection. Use the YIN algorithm to estimate +the fundamental frequency of sound, which must be a SOUND. +The minstep, a FLONUM, is the minimum frequency considered (in steps), +maxstep, a FLONUM, is the maximum frequency considered (in steps), and +stepsize, a FIXNUM, is the desired hop size. The result is +a "stereo" signal, +i.e. an array of two SOUNDs, both at the same sample rate, which is +approximately the sample rate of sound divided by stepsize. +The first SOUND consists of frequency estimates. The second sound consists +of values that measure the confidence or reliability of the frequency estimate. +A small value (less than 0.1) indicates fairly high confidence. A larger value +indicates lower confidence. This number can also be thought of as a ratio of +non-periodic power to periodic power. When the number is low, it means the signal +is highly periodic at that point in time, so the period estimate will be +reliable. +Hint #1: See +Alain de Cheveigne and Hideki Kawahara's article "YIN, a Fundamental Frequency +Estimator for Speech and Music" in the Journal of the +Acoustic Society of America, April 2002 for details on the yin algorithm. +Hint #2: Typically, the stepsize should be at least the expected number +of samples in one period so that the +fundamental frequency estimates are calculated at a rate far below +the sample rate of the signal. Frequency does not change rapidly and +the yin algorithm is fairly slow. To optimize speed, +you may want to use less than 44.1 kHz sample rates for input sounds. Yin +uses interpolation to achieve potentially fractional-sample-accurate estimates, +so higher sample rates do not necessarily help the algorithm and definitely +slow it down. The computation time is O(n^(2)) per estimate, +where n is the number +of samples in the longest period considered. Therefore, each increase +of minstep by 12 (an octave) gives you a factor of 4 speedup, and +each decrease of the sample rate of sound by a factor of +two gives you another factor of 4 speedup. Finally, the number of estimates is +inversely proportional to stepsize. +Hint #3: Use snd-srate (see Section "Accessing and Creating Sound") to get +the exact sample rate of the result, which will be the sample rate of + sound divided by stepsize. +E.g. (snd-srate (aref yin-output 0)), +where yin-output is a result returned by yin, will be the +sample rate of the estimates.

+

Transformations

+ +These functions change the environment that is seen by other high-level +functions. Note that these changes are usually relative to the +current environment. There are also "absolute" versions of each +transformation function, with the exception of seq, + seqrep, sim, and simrep. The +"absolute" versions (starting or ending with "abs") do not look at the +current environment, but rather set an environment variable to a specific value. +In this way, sections of code can be insulated from external +transformations. +

+

+
+abs-env(beh) [SAL]
+ +(abs-env beh) [LISP]
Compute beh in the default environment. +This is useful for computing waveform tables and signals that are +"outside" of +time. For example, (at 10.0 (abs-env (my-beh))) is equivalent to +(abs-env (my-beh)) because abs-env forces the default environment. Or in SAL, we would say abs-env(my-beh()) @ 10 is equivalent to abs-env(my-beh()).

+
at(time, beh) [SAL]
+ +(at time beh) [LISP]
Evaluate beh with +*warp* shifted by time. In SAL, you can use the infix +operator @ as in beh @ time. To discover how the +environment is shifting time, use local-to-global(time). Most +commonly, you call local-to-global(0) to find when a sound created +in the current environment will start, expressed in absolute (global) terms. +This can be regarded as the "current time."

+
at-abs(time, beh) [SAL]
+ +(at-abs time beh) [LISP]
Evaluate beh with +*warp* shifted so that local time 0 maps to time. In SAL, you can use the infix operator @@ as in beh @@ time.

+
+continuous-control-warp(beh) [SAL]
+ +(continuous-control-warp beh) [LISP]
Applies the current warp environment to the signal returned by beh. The result has the default control sample rate *control-srate*. Linear interpolation is currently used. Implementation: beh is first evaluated without any shifting, stretching, or warping. The result is functionally composed with the inverse of the environment's warp function.

+
+continuous-sound-warp(beh) [SAL]
+ +(continuous-sound-warp beh) [LISP]
Applies the current warp environment to the signal returned by beh. The result has the default sound sample rate *sound-srate*. Linear interpolation is currently used. See continuous-control-warp for implementation notes.

+
+control-srate-abs(srate, +beh) [SAL]
+ +(control-srate-abs srate beh) [LISP]
Evaluate beh with *control-srate* +set to sample rate srate. Note: there is no "relative" version of +this function.

+
extract(start, stop, beh) [SAL]
+ +(extract start stop beh) [LISP]
Returns a sound +which is the portion of +beh between start and stop. Note that this is done +relative to the current *warp*. The result is shifted +to start according to *warp*, so normally the result will start without a delay of start.

+
extract-abs(start, stop, beh) [SAL]
+ +(extract-abs start stop beh) [LISP]
Returns a sound which +is the portion of +beh between start and stop, independent of the +current *warp*. The result is shifted +to start according to *warp*.

+
loud(volume, beh) [SAL]
+ +(loud volume beh) [LISP]
Evaluates beh with *loud* +incremented by volume. (Recall that *loud* is in decibels, so increment is the proper operation.)

+
loud-abs(volume, beh) [SAL]
+ +(loud-abs volume beh) [LISP]
Evaluates beh with *loud* +set to volume.

+
+sound-srate-abs(srate, beh) [SAL]
+ +(sound-srate-abs srate beh) [LISP]
Evaluate beh with *sound-srate* set to sample rate srate. Note: there is no "relative" version of this function.

+
stretch(factor, beh) [SAL]
+ +(stretch factor beh) [LISP]
Evaluates beh with +*warp* scaled by factor. The effect is to "stretch" the result +of beh (under the current environment) by factor. See Chapter +"Continuous Transformations and Time Warps" for more information. Use get-duration(dur) to +get the nominal actual duration of a behavior that locally has a duration +of dur. Here, "nominal" means what would be expected if the behavior +obeys the shift, stretch, and warp components of the environment. (Any +behavior is free to deviate from the nominal timing. For example, a percussion +sound might have a fixed duration independent of the stretch factor.) Also, +"actual" means global or absolute time, and "locally" means within the +environment where get-duration is called. get-duration works +by mapping the current time (local time 0) using local-to-global to +obtain an actual start time, and mapping dur to obtain an actual end time. +The difference is returned.

+
stretch-abs(factor, beh) [SAL]
+ +(stretch-abs factor beh) [LISP]
Evaluates beh with *warp* set to a linear time transformation where each unit of logical time maps to factor units of real time. The effect is to stretch the nominal behavior of beh (under the default global environment) by factor. See Chapter "Continuous Transformations and Time Warps" for more information.

+
sustain(factor, beh) [SAL]
+ +(sustain factor beh) [LISP]
Evaluates beh with *sustain* scaled by factor. The effect is to "stretch" the result of beh (under the current environment) by factor; however, the logical stop times are not stretched. Therefore, the overall duration of a sequence is not changed, and sounds will tend to overlap if *sustain* is greater than one (legato) and be separated by silence if *sustain* is less than one.

+
sustain-abs(factor, beh) [SAL]
+ +(sustain-abs factor beh) [LISP]
Evaluates beh with *sustain* set to factor. (See sustain, above.)

+
transpose(amount, beh) [SAL]
+ +(transpose amount beh) [LISP]
Evaluates beh with +*transpose* shifted by amount. The effect is relative transposition by amount semitones.

+
transpose-abs(amount, beh) [SAL]
+ +(transpose-abs amount beh) [LISP]
Evaluates beh with +*transpose* set to amount. The effect is the transposition of the nominal pitches in beh (under the default global environment) by amount.

+
warp(fn, beh) [SAL]
+ +(warp fn beh) [LISP]
Evaluates beh with *warp* modified by fn. The idea is that beh and fn are written in the same time system, and fn warps that time system to local time. The current environment already contains a mapping from local time to global (real) time. The value of *warp* in effect when beh is evaluated is the functional composition of the initial *warp* with fn.

+
warp-abs(fn, beh) [SAL]
+ +(warp-abs fn beh) [LISP]
Evaluates beh with *warp* set to fn. In other words, the current *warp* is ignored and not composed with fn to form the new *warp*. +
+

+

Combination and Time Structure

+These behaviors combine component behaviors into structures, including +sequences (melodies), simultaneous sounds (chords), and structures based +on iteration. +

+

+
+ + seq(beh1 [, beh2, ...]) [SAL]
+ +(seq beh1 [beh2 ...]) [LISP]
Evaluates the first behavior +beh1 according to *time* and each successive behavior at the +logical-stop time of the previous one. The results are summed to form a +sound whose logical-stop is +the logical-stop of the last behavior in the sequence. Each behavior +can result in a multichannel sound, in which case, the logical stop time is +considered to be the maximum logical stop time of any channel. The number +of channels in the result is the number of channels of the first behavior. +If other behaviors return fewer channels, new channels are created containing +constant zero signals until the required number of channels is obtained. If +other behaviors return a simple sound rather than multichannel sounds, the +sound is automatically assigned to the first channel of a multichannel sound +that is then filled out with zero signals. If another behavior returns more +channels than the first behavior, the error is reported and the computation +is stopped. Sample rates are converted up or down to match the sample rate of the first sound in a sequence.

+
seqrep(var, limit, beh) [SAL]
+ +(seqrep var limit beh) [LISP]
Iteratively +evaluates beh with the atom +var set with values from 0 to limit-1, inclusive. These sounds +are placed sequentially in time as if by seq. The symbol var is +a read-only local variable to beh. Assignments are not restricted +or detected, but may cause a run-time error or crash. In LISP, the syntax is + (seqrep (var limit) beh).

+
+sim([beh1, beh2, ...]) [SAL]
+ +(sim [beh1 beh2 ...]) [LISP]
Returns a sound which is the +sum of the given behaviors evaluated with current value of *warp*. +If behaviors return multiple channel sounds, the corresponding channels are +added. If the number of channels does not match, the result has the +maximum. For example, if a two-channel sound [L, R] is added to a four-channel +sound [C1, C2, C3, C4], the result is [L + C1, R + C2, C3, C4]. Arguments to sim may also be numbers. If all arguments are numbers, sim is equivalent (although slower than) the + function. If a number is added to a sound, snd-offset is used to add the number to each sample of the sound. The result of adding a number to two or more sounds with different durations is not defined. Use const to coerce a number to a sound of a specified duration. An important limitation of sim is that it cannot handle hundreds of behaviors due to a stack size limitation in XLISP. To compute hundreds of sounds (e.g. notes) at specified times, see timed-seq, below. +See also sum below.

+
simrep(var, limit, beh) [SAL]
+ +(simrep var limit beh) [LISP]
Iteratively +evaluates beh with the atom +var set with values from 0 to limit-1, inclusive. These sounds +are then placed simultaneously in time as if by sim. +In LISP, the syntax is + (seqrep (var limit) beh).

+
+trigger(s, beh) [SAL]
+ +(trigger s beh) [LISP]
Returns a sound which is the +sum of instances of the behavior beh. One instance is created each time +SOUND s makes a transition from less than or equal to zero to +greater than zero. (If the first sample of s is greater than zero, an +instance is created immediately.) The sample rate of s and all behaviors +must be the same, and the behaviors must be (monophonic) SOUNDs. +This function is particularly designed to allow behaviors to be invoked +in real time by making s a function of a Nyquist slider, which can be +controlled by a graphical interface or by OSC messages. See snd-slider +in Section "Creating Sounds".

+
set-logical-stop(beh, time) [SAL]
+ +(set-logical-stop beh time) [LISP]
Returns a sound with time as +the logical stop time.

+
sum(a [, b, ...]) [SAL]
+ +(sum a [b ...]) [LISP]
Returns the sum of a, b, ..., allowing mixed addition of sounds, multichannel sounds and numbers. Identical to sim. In SAL, use the infix "+" operator.

+
mult(a [, b, ...]) [SAL]
+ +(mult a [b ...]) [LISP]
Returns the product of a, b, ..., allowing mixed multiplication of sounds, multichannel sounds and numbers.

+
diff(a, b) [SAL]
+ +(diff a b) [LISP]
Returns the difference between a and b. This function is defined as (sum a (prod -1 b)).

+
+timed-seq(score) [SAL]
+ +(timed-seq score) [LISP]
Computes sounds from a note list or "score." The score +is of the form: `((time1 stretch1 beh1) (time2 +stretch2 beh2) ...), where timeN is the starting time, +stretchN is the stretch factor, and behN is the behavior. Note +that score is normally a quoted list! The times must be in +increasing order, and each behN is evaluated using lisp's eval, +so the behN behaviors cannot refer to local parameters or local +variables. The advantage of this form over seq is that the +behaviors are evaluated one-at-a-time which can take much less stack +space and overall memory. One special "behavior" expression is +interpreted directly by timed-seq: (SCORE-BEGIN-END) +is ignored, not evaluated as a function. Normally, this special +behavior is placed at time 0 and has two parameters: the score +start time and the score end time. These are used in Xmusic +functions. If the behavior has a :pitch keyword parameter +which is a list, the list represents a chord, and the expression is +replaced by a set of behaviors, one for each note in the chord. +It follows that if :pitch is nil, the behavior +represents a rest and is ignored.

+

Sound File Input and Output

+ +
+
+ +play sound [SAL]
+ +(play sound) [LISP]
Play the sound +through the DAC. +Note that play is a command in SAL. In XLISP, it is a function, +so the syntax is (play sound), and in SAL, you can call the +XLISP function as #play(sound). +The play command or function +writes a file and plays it. The details of this +are system-dependent, but play is defined in the file +system.lsp. The variable *default-sf-dir* + names a directory into which to save a sound file. Be careful not to call play or sound-play within a function and then +invoke that function from another play command.

+
By default, Nyquist will try to normalize sounds using the method named by +*autonorm-type*, which is 'lookahead by default. +The lookahead method precomputes and buffers *autonorm-max-samples* +samples, finds the peak value, and normalizes accordingly. The +'previous method bases the normalization of the current sound on the peak value of the (entire) previous sound. This might be good if you are working with long sounds that start rather softly. See Section "Memory Space and Normalization" for more details.

+
If you want precise control over output levels, you should turn this feature off by typing (using SAL syntax): +
+autonorm-off()
+
+ +Reenable the automatic normalization feature by typing: +
+autonorm-on()
+
+ +Play normally produces real-time output. The default is to send audio data to the DAC as it is computed in addition to saving samples in a file. If computation is slower than real-time, output will be choppy, but since the samples end up in a file, you can type (r) to replay the stored sound. Real-time playback can be disabled by (using SAL syntax): +
+sound-off()
+
+ +and reenabled by: +
+sound-on()
+
+ +Disabling real-time playback has no effect on (play-file) or (r).

+
While sounds are playing, typing control-A to Nyquist will push the estimated +elapsed audio time onto the head of the list +stored in *audio-markers*. + +Because samples are computed in blocks and because there is latency +between sample computation and sample playback, the elapsed time may not +be too accurate, and the computed elapsed time may not advance after all +samples have been computed but the sound is still playing.

+
play-file(filename) [SAL]
+ +(play-file filename) [LISP]
Play the contents of a sound file named by filename. The s-read function is used to read the file, and unless +filename specifies an absolute path or starts with ".", it will be read from +*default-sf-dir*.

+
autonorm-on() [SAL]
+ +(autonorm-on) [LISP]
Enable automatic adjustment of a scale factor applied to sounds computed using the play command.

+
autonorm-off() [SAL]
+ +(autonorm-off) [LISP]
Disable automatic adjustment of a scale factor applied to sounds computed using the play command.

+
sound-on() [SAL]
+ +(sound-on) [LISP]
Enable real-time audio output when sound is computed by the the play command.

+
sound-off() [SAL]
+ +(sound-off) [LISP]
Disable real-time audio output when sound is computed by the the play command.

+
+s-save(expression, maxlen, +filename, format: format, mode: mode, bits: bits, swap: flag, play: play) [SAL]
+ +(s-save expression maxlen filename :format format :mode mode :bits bits :swap flag :play play) [LISP]
Evaluates the expression, which should result in a sound +or an array of sounds, and writes the result to the given filename. A +FLONUM is returned giving the maximum absolute value of all samples +written. (This is useful for normalizing sounds and detecting sample +overflow.) If play is not NIL, the sound will be output +through the computer's audio output system. (play: [SAL] +or :play [LISP] is not implemented on all systems; if it is implemented, and filename is NIL, then this will play the file without also writing a file.) +The latency (length of audio buffering) used to play the sound is 0.3s by default, but see snd-set-latency. +If +a multichannel sound (array) is written, the channels are up-sampled to the +highest rate in any channel so that all channels have the same sample rate. +The maximum number of samples written per channel is given by maxlen, +which allows writing the initial part of a very long or infinite sound. A +header is written according to format, samples are encoded according to +mode, using bits bits/sample, and bytes are swapped if flag is not NIL. Defaults for these are +*default-sf-format*, *default-sf-mode*, and +*default-sf-bits*. The default for flag is NIL. +The bits parameter may be 8, 16, or 32. The values for the format and mode options are described below: +
+Format +
+
+snd-head-none
The format is unknown and should be determined +by reading the file.

+
snd-head-raw
A raw format file has no header.

+
snd-head-AIFF
AIFF format header.

+
snd-head-IRCAM
IRCAM format header.

+
snd-head-NeXT
1024-byte NeXT/SUN format header followed by IRCAM +header ala CMIX. Note that the NeXT/SUN format has a header-length field, +so it really is legal to have a large header, even though the normal minimal +header is only 24 bytes. The additional space leaves room for maximum +amplitudes, which can be used for normalizing floating-point soundfiles, and +for other data. Nyquist follows the CMIX convention of placing an IRCAM +format header immediately after the NeXT-style header.

+
snd-head-Wave
Microsoft Wave format header.

+
snd-head-*
See sndfnint.lsp for more formats. +
+

+Mode +

+
+snd-mode-adpcm
ADPCM mode (not supported).

+
snd-mode-pcm
signed binary PCM mode.

+
snd-mode-ulaw
8-bit U-Law mode.

+
snd-mode-alaw
8-bit A-Law mode (not supported).

+
snd-mode-float
32-bit floating point mode.

+
snd-mode-upcm
unsigned binary PCM mode.

+
snd-mode-*
See sndfnint.lsp for more modes. +
+

+The defaults for format, mode, and bits are as follows: +

+
+NeXT and Sun machines:
snd-head-NeXT, snd-mode-pcm, +16

+
SGI and Macintosh machines:
snd-head-AIFF, snd-mode-pcm, 16

+
+
+ +s-read(filename, time-offset: offset, srate: sr, dur: dur, nchans: chans, + format: format, mode: mode, bits: n, swap: flag) [SAL]
+ +(s-read filename :time-offset offset :srate sr + :dur dur :nchans chans :format format :mode mode :bits n + :swap flag) [LISP]
Reads a sound from + filename. The global *default-sf-dir* applies. If a header is +detected, the header is used to determine the format +of the file, and header information overrides format information provided by +keywords (except for time-offset: and dur:). +
+s-read("mysound.snd", srate: 44100)
+
+ +specifies a sample rate of 44100 hz, but if the file has a header specifying 22050 hz, the resulting sample rate will be 22050. The parameters are: +
+If there is an error, for example if offset is greater than the length of the file, then NIL is returned rather than a sound. Information about the sound is also returned by s-read through *rslt* (Footnote 2) . The list assigned to *rslt* is of the form: (format channels mode bits samplerate duration flags byte-offset), which are defined as follows: +
    +
  • +format - the header format. See s-save for details. +
  • channels - the number of channels. +
  • mode - the sample representation, e.g. PCM or float. See s-save for details. +
  • bits - the number of bits per sample. +
  • samplerate - the sample rate, expressed as a FLONUM. +
  • duration - the duration of the sound, in seconds. +
  • flags - The values for format, channels, mode, bits, samplerate, and duration are initially just the values passed in as parameters or default values to s-read. If a value is actually read from the sound file header, a flag is set. The flags are: snd-head-format, snd-head-channels, snd-head-mode, snd-head-bits, snd-head-srate, and snd-head-dur. For example, +
    +(let ((flags (caddr (cddddr  *rslt*))))
    +  (not (zerop (logand flags snd-head-srate))))
    +
    + +tells whether the sample rate was specified in the file. See also sf-info below. +
  • byte-offset - the byte offset into the file of the first sample +to be read (this is used by the s-overwrite and s-add-to +functions). +


+
s-add-to(expression, maxlen, +filename [, offset]) [SAL]
+ +(s-add-to expression maxlen filename [offset]) [LISP]
Evaluates the expression, which should result in a sound +or an array of sounds, and adds the result to the given filename. +The global *default-sf-dir* applies. A FLONUM is returned, +giving the maximum absolute value of all samples written. The +sample rate(s) of expression must match those of the file. +The maximum number of samples written per channel is given by maxlen, +which allows writing the initial part of a very long or infinite sound. +If offset is specified, the new sound is added to the file beginning at +an offset from the beginning (in seconds). The file is extended if +necessary to accommodate the new addition, but if offset +falls outside of the original file, the file is not modified. (If necessary, +use s-add-to to extend the file with zeros.) +The file must be a recognized +sound file with a header (not a raw sound file).

+
s-overwrite(expression, maxlen, filename [, offset]) [SAL]
+ +(s-overwrite expression maxlen filename [offset]) [LISP]
Evaluates +the expression, which should result in a sound +or an array of sounds, and replaces samples in the given filename. +The global *default-sf-dir* applies. +A FLONUM is returned, giving the maximum absolute value of all +samples written. The +sample rate(s) of expression must match those of the file. +The maximum number of samples written per channel is given by maxlen, +which allows writing the initial part of a very long or infinite sound. +If offset is specified, the new sound is written to the file beginning at +an offset from the beginning (in seconds). The file is extended if +necessary to accommodate the new insert, but if offset falls outside of +the original file, the file is not modified. (If necessary, use +s-add-to to extend the file with zeros.) The file must be a recognized +sound file with a header (not a raw sound file).

+
sf-info(filename) [SAL]
+ +(sf-info filename) [LISP]
Prints information about a sound file. The parameter filename is a string. The file is assumed to be in *default-sf-dir* (see soundfilename below) unless the filename begins with "." or "/". The source for this function is in the runtime and provides an example of how to determine sound file parameters.

+
soundfilename(name) [SAL]
+ +(soundfilename name) [LISP]
Converts a string name to a soundfile name. If name begins with "." or "/", the name is returned without alteration. Otherwise, a path taken from *default-sf-dir* is prepended to name. The s-plot, s-read, and s-save functions all use soundfilename translate filenames.

+
s-plot(sound + [, dur, n]) [SAL]
+ +(s-plot sound + [dur n]) [LISP]
Plots sound in a window. This function was designed to run a plot program on a Unix workstation, but now is +primarily used with NyquistIDE, which has self-contained plotting. Normally, +time/value pairs in ascii are written to points.dat and system-dependent code +(or the NyquistIDE program) takes it from there. If the sound is +longer than the optional dur (default is 2 seconds), only the +first dur seconds are plotted. +If there are more than n samples to be plotted, the signal is interpolated +to have n samples before plotting. +The data file used is *default-plot-file*:

+
*default-plot-file*
The file containing the data points, defaults to "points.dat".

+
s-print-tree(sound) [SAL]
+ +(s-print-tree sound) [LISP]
Prints an ascii +representation of the internal data structures representing a sound. This +is useful for debugging Nyquist. Identical to snd-print-tree.

+

Low-level Functions

+Nyquist includes many low-level functions that are used to implement the functions and behaviors described in previous sections. For completeness, these functions are described here. Remember that +these are low-level functions that are not intended for normal use. Unless +you are trying to understand the inner workings of Nyquist, you can skip this section. +

+

Creating Sounds

+The basic operations that create sounds are described here. +

+

+
snd-const(value, t0, srate, +duration) [SAL]
+ +(snd-const value t0 srate duration) [LISP]
Returns a sound with constant value, starting at t0 +with the given duration, at the sample rate srate. You might want +to use pwl (see Section "Piece-wise Approximations") instead.

+
snd-read(filename, offset, t0, format, +channels, mode, bits, swap, sr, +dur) [SAL]
+ +(snd-read filename offset t0 format channels mode bits swap sr dur) [LISP]
Loads a sound from a file with name filename. Files are +assumed to consist of a header followed by frames consisting of one sample +from each channel. The format specifies the type of header, but this +information is currently ignored. Nyquist looks for a number of header +formats and automatically figures out which format to read. If a header can +be identified, the header is first read from the file. Then, the file +pointer is advanced by the indicated +offset (in seconds). If there is an unrecognized header, Nyquist will +assume the file has no header. If the header size is a multiple of the +frame size (bytes/sample * number-of-channels), you can use offset to +skip over the header. To skip N bytes, use an offset of: +
+(/ (float N) sr (/ bits 8) channels)
+
+ +If the header is not a multiple of the frame size, either write a header or +contact the author (dannenberg@cs.cmu.edu) for assistance. Nyquist will +round offset to the nearest sample. The resulting sound will start at +time t0. If a header is found, the file will be interpreted according +to the header information. If no header was found, channels tells how +many channels there are, the samples are encoded according to mode, the +sample length is bits, and sr is the sample rate. The swap flag is 0 or 1, where 1 means to swap sample bytes. The duration to +be read (in seconds) is given by dur. If dur is longer than the +data in the file, then a shorter duration will be returned. If the file +contains one channel, a sound is returned. If the file contains 2 or more +channels, an array of sounds is returned. Note: you probably want to +call s-read (see Section
"Sound File Input and Output") instead of +snd-read. Also, see Section "Sound File Input and Output" for information on the +mode and format parameters.

+
snd-save(expression, maxlen, +filename, format, mode, bits, swap, play) [SAL]
+ +(snd-save expression maxlen filename format mode bits swap play) [LISP]
Evaluates +the expression, which should result in a sound +or an array of sounds, and writes the result to the given filename. If +a multichannel sound (array) is written, the channels are up-sampled to the +highest rate in any channel so that all channels have the same sample rate. +The maximum number of samples written per channel is given by maxlen, +which allows writing the initial part of a very long or infinite sound. A +header is written according to format, samples are encoded according to +mode, using bits bits/sample, and swapping bytes if swap is 1 (otherwise it should be 0). +If play is not null, the audio is played in real time (to the extent possible) as it is computed. The peak value of the sound is returned. In addition, +the symbol *RSLT* is bound to a list containing the sample rate, +number of channels, and duration (in that order) of the saved sound. +Note: you probably want to call +s-save (see Section "Sound File Input and Output") instead. The format and +mode parameters are described in Section "Sound File Input and Output".

+
snd-overwrite(expression, maxlen, filename, offset, format, mode, bits, swap) [SAL]
+ +(snd-overwrite expression maxlen filename offset format mode bits swap) [LISP]
Evaluates +the expression, which should result in a sound +or an array of sounds, and replaces samples in the given filename, +writing the first frame at a time of offset seconds. The offset must +be less than or equal to the duration of the existing file. The +duration of the written samples may +be greater than that of the file, in which case the file is extended +as necessary. The +sample rate(s) of expression and the number of channels +must match those of the file. If format is + SND-HEAD-RAW, then the file +format is given by mode (see +snd-save, bits (per channel), swap (1 means to +swap bytes and 0 means write them in the native byte order), and the +number of channels and sample rate of the sound returned by evaluating +expression. If the +file is a known +audio file format, format should be SND-HEAD-NONE, and the +other parameters are ignored. Up to a maximum of maxlen +samples will be written per channel. The peak value of the sound is returned. +In addition, the symbol *RSLT* is bound to a list containing the +duration of the written sound (which may not be the duration of the sound +file). +Use s-add-to (in Section "Sound File Input and Output" or +s-overwrite (in Section "Sound File Input and Output" instead of this function.

+
snd-coterm(s1, s2) [SAL]
+ +(snd-coterm s1 s2) [LISP]
Returns a copy of s1, except the start +time is the maximum of the start times of s1 and s2, and the +termination time is the minimum of s1 and s2. (After the termination +time, the sound is zero as if s1 is gated by s2.) Some rationale +follows: In order to implement s-add-to, we need to read from the +target sound file, add the sounds to a new sound, and overwrite the result +back into the file. We only want to write as many samples into the file as +there are samples in the new sound. However, if we are adding +in samples read from +the file, the result of a snd-add in Nyquist will have the maximum +duration of either sound. Therefore, we may read to the end of the file. +What we need is a way to truncate the read, but we cannot easily do that, +because we do not know in advance how long the new sound will be. The +solution is to use snd-coterm, which will allow us to truncate the +sound that is read from the file (s1) according to the duration of the +new sound (s2). When this truncated sound is added to the new sound, +the result will have only the duration of the new sound, and this can be +used to overwrite the file. This function is used in the implementation of +s-add-to, which is defined in runtime/fileio.lsp.

+
(snd-from-array ...) [SAL]
+ +(snd-from-array ...) [LISP]
See "Accessing and Creating Sound".

+
snd-white(t0, sr, d) [SAL]
+ +(snd-white t0 sr d) [LISP]
Generate white noise, starting at +t0, with sample rate sr, and duration d. You probably want to +use noise (see Section "More Behaviors").

+
snd-zero(t0, srate) [SAL]
+ +(snd-zero t0 srate) [LISP]
Creates a sound that is +zero everywhere, starts at t0, and has sample rate srate. The +logical stop time is immediate, i.e. also at t0. You probably want +to use pwl (see Section "Piece-wise Approximations") instead.

+
get-slider-value(index) [SAL]
+ +(get-slider-value index) [LISP]
Return the current value of the slider +named by index (an integer index into the array of sliders). +Note that this "slider" is just a floating point +value in an array. Sliders can be changed by OSC messages (see osc-enable) and by sending character +sequences to Nyquist's standard input. (Normally, these character sequences would +not be typed but generated by the NyquistIDE interactive development environment, which +runs Nyquist as a sub-process, and which present the user with graphical sliders.)

+
snd-slider(index, t0, srate, duration) [SAL]
+ +(snd-slider index t0 srate duration) [LISP]
Create +a sound controlled by the slider named by index (an integer +index into the array of sliders; see get-slider-value for more information). +The function returns a sound. Since Nyquist sounds are computed in blocks of samples, +and each block is computed at once, each block will contain copies of the current slider +value. To obtain reasonable responsiveness, slider sounds should have high (audio) +sample rates so that the block rate will be reasonably high. Also, consider lowering the audio +latency using snd-set-latency. To "trigger" a Nyquist behavior using slider input, see the trigger function in Section "Combination and Time Structure".

+

Signal Operations

+This next set of functions take sounds as arguments, operate on them, and +return a sound. +

+

+
+snd-abs(sound) [SAL]
+ +(snd-abs sound) [LISP]
Computes a new +sound where each sample is the absolute value of the corresponding sample in +sound. You should probably use s-abs instead. (See Section "More Behaviors".)

+
snd-sqrt(sound) [SAL]
+ +(snd-sqrt sound) [LISP]
Computes a new +sound where each sample is the square root of the corresponding sample in +sound. If a sample is negative, it is taken to be zero to avoid raising a floating point error. You should probably use s-sqrt instead. (See Section "More Behaviors".)

+
snd-add(sound1, sound) [SAL]
+ +(snd-add sound1 sound) [LISP]
Adds two sounds. The +resulting start time is the minimum of the two parameter start times, the +logical stop time is the maximum of the two parameter stop times, and the +sample rate is the maximum of the two parameter sample rates. Use +sim or sum instead of snd-add (see Section "Combination and Time Structure").

+
snd-offset(sound, offset) [SAL]
+ +(snd-offset sound offset) [LISP]
Add an offset to a sound. The +resulting start time, logical stop time, stop time, and sample rate are +those of sound. Use sum instead (see Section "Combination and Time Structure").

+
snd-avg(sound, blocksize, stepsize, operation) [SAL]
+ +(snd-avg sound blocksize stepsize operation) [LISP]
Computes the averages +or peak values of blocks of samples. Each output sample is an average or +peak of blocksize (a fixnum) adjacent samples from the input sound. +After each average or peak is taken, the input is advanced by stepsize, +a fixnum which may be greater or less than blocksize. The output +sample rate is the sound (input) sample rate divided by stepsize. +This function is useful for computing low-sample-rate rms or peak +amplitude signals for input to snd-gate or snd-follow. +To select the operation, operation should be one of OP-AVERAGE +or OP-PEAK. (These are global lisp variables; the actual +operation parameter is an integer.) For RMS computation, see +rms in Section "More Behaviors".

+
snd-clip(sound, peak) [SAL]
+ +(snd-clip sound peak) [LISP]
Hard limit sound +to the given peak, a positive number. The samples of sound are constrained between an upper value +of peak and a lower value of -peak. Use clip instead (see Section "More Behaviors").

+
snd-compose(f, g) [SAL]
+ +(snd-compose f g) [LISP]
Compose two signals, i.e. +compute f(g(t)), where f and g are sounds. This function +is used primarily to implement time warping, but it can be used in other +applications such as frequency modulation. For each sample x in g, +snd-compose looks up the value of f(x) using linear +interpolation. The resulting sample rate, start time, etc. are taken from +g. The sound f is used in effect as a lookup table, but it is +assumed that g is non-decreasing, so that f is accessed in time +order. This allows samples of f to be computed and discarded +incrementally. If in fact g decreases, the current sample of g is +replaced by the previous one, forcing g into compliance with the +non-decreasing restriction. See also sref, shape, and +snd-resample.

+
For an extended example that uses snd-compose for variable pitch shifting, +see demos/pitch_change.htm. +

+
+snd-tapv(sound, offset, vardelay, maxdelay) [SAL]
+ +(snd-tapv sound offset vardelay maxdelay) [LISP]
A +variable delay: sound is delayed by the sum of offset (a FIXNUM or FLONUM) +and vardelay (a SOUND). The specified delay is adjusted to lie in the range +of zero to maxdelay seconds to yield the actual delay, and the delay is +implemented using linear interpolation. This function was designed specifically +for use in a chorus effect: the offset is set to half of maxdelay, and +the vardelay input is a slow sinusoid. The maximum delay is limited to +maxdelay, which determines the length of a fixed-sized buffer. The function +tapv is equivalent and preferred (see Section "Filter Behaviors").

+
snd-tapf(sound, offset, vardelay, maxdelay) [SAL]
+ +(snd-tapf sound offset vardelay maxdelay) [LISP]
A +variable delay like snd-tapv except there is no linear interpolation. By +eliminating interpolation, the output is an exact copy of the input with no filtering +or distortion. On the other hand, delays jump by samples causing samples to double or +skip even when the delay is changed smoothly.

+
snd-copy(sound) [SAL]
+ +(snd-copy sound) [LISP]
Makes a copy of sound. +Since operators always make (logical) copies of their sound parameters, this +function should never be needed. This function is here for debugging.

+
snd-down(srate, sound) [SAL]
+ +(snd-down srate sound) [LISP]
Linear interpolation +of samples down to the given sample rate srate, which must be lower than +the sample rate of sound. Do not call this function. Nyquist performs +sample-rate conversion automatically as needed. If you want to force a +conversion, call force-srate (see Section "Sound Synthesis").

+
snd-exp(sound) [SAL]
+ +(snd-exp sound) [LISP]
Compute the exponential of each sample of sound. Use s-exp instead (see Section "More Behaviors").

+
+snd-follow(sound, floor, risetime, falltime, lookahead) [SAL]
+ +(snd-follow sound floor risetime falltime lookahead) [LISP]
An envelope +follower. The basic goal of this function is to generate a smooth signal +that rides on the peaks of the input signal. The usual objective is to +produce an amplitude envelope given a low-sample rate (control rate) +signal representing local RMS measurements. The first argument is the +input signal. The floor is the minimum output value. The risetime is the time (in seconds) it takes for the output to rise (exponentially) from floor to unity (1.0) and the falltime is the time it takes for the output to fall (exponentially) from unity to floor. The algorithm looks ahead for peaks and will begin to increase the output signal according to risetime in anticipation of a peak. The amount of anticipation (in sampless) is given by lookahead. The algorithm is as follows: the output value is allowed to increase according to risetime or decrease according to falltime. If the next input sample is in this range, that sample is simply output as the next output sample. If the next input sample is too large, the algorithm goes back in time as far as necessary to compute an envelope that rises according to risetime to meet the new value. The algorithm will only work backward as far as lookahead. If that is not far enough, then there is a final forward pass computing a rising signal from the earliest output sample. In this case, the output signal will be at least momentarily less than the input signal and will continue to rise exponentially until it intersects the input signal. If the input signal falls faster than indicated by falltime, the output fall rate will be limited by falltime, and the fall in output will stop when the output reaches floor. This algorithm can make two passes througth the buffer on sharply rising inputs, so it is not particularly fast. With short buffers and low sample rates this should not matter. See snd-avg above for a function that can help to generate a low-sample-rate input for snd-follow. See snd-chase in Section "Filters" for a related filter.

+
snd-gate(sound, lookahead, risetime, falltime, floor, threshold) [SAL]
+ +(snd-gate sound lookahead risetime falltime floor threshold) [LISP]
This function generates an exponential rise and decay intended for noise gate implementation. The decay starts when the signal drops below threshold and stays there for longer than lookahead. Decay continues until the value reaches floor, at which point the decay stops and the output value is held constant. Either during the decay or after the floor is reached, if the signal goes above threshold, then the output value will rise to unity (1.0) at the point the signal crosses the threshold. Again, look-ahead is used, so the rise actually starts before the signal crosses the threshold. The rise is a constant-rate exponential and set so that a rise from floor to unity occurs in risetime. Similarly, the fall is a constant-rate exponential such that a fall from unity to floor takes falltime. The result is delayed by lookahead, so the output is not actually synchronized with the input. To compensate, you should drop the initial lookahead of samples. Thus, snd-gate is not recommended for direct use. Use gate instead (see Section "Miscellaneous Functions").

+
snd-inverse(signal, start, srate) [SAL]
+ +(snd-inverse signal start srate) [LISP]
Compute the function inverse of signal, that is, compute g(t) such that signal(g(t)) = t. This function assumes that signal is non-decreasing, it uses linear interpolation, the resulting sample rate is srate, and the result is shifted to have a starting time of start. If signal decreases, the true inverse may be undefined, so we define snd-inverse operationally as follows: for each output time point t, scan ahead in signal until the value of signal exceeds t. Interpolate to find an exact time point x from signal and output x at time t. This function is intended for internal system use in implementing time warps.

+
snd-log(sound) [SAL]
+ +(snd-log sound) [LISP]
Compute the natural logorithm of each sample of sound. Use s-log instead (see Section "More Behaviors").

+
+peak(expression, maxlen) [SAL]
+ +(peak expression maxlen) [LISP]
Compute the maximum absolute value of the amplitude of a sound. The sound is created by evaluating expression (as in s-save). Only the first maxlen samples are evaluated. The expression is automatically quoted (peak is a macro), so do not quote this parameter. If expression is a variable, then the global binding of that variable will be used. Also, since the variable retains a reference to the sound, the sound will be evaluated and left in memory. See Section "Memory Space and Normalization" on "Memory Space and Normalization" for examples.

+
+snd-max(expression, maxlen) [SAL]
+ +(snd-max expression maxlen) [LISP]
Compute the maximum absolute value of the amplitude of a sound. The sound is created by evaluating expression (as in snd-save), which is therefore normally quoted by the caller. At most maxlen samples are computed. The result is the maximum of the absolute values of the samples. Notes: It is recommended to use peak (see above) instead. If you want to find the maximum of a sound bound to a local variable and it is acceptable to save the samples in memory, then this is probably the function to call. Otherwise, use peak.

+
snd-maxv(sound1, sound2) [SAL]
+ +(snd-maxv sound1 sound2) [LISP]
Compute the maximum of sound1 and sound2 on a sample-by-sample basis. The resulting +sound has its start time at the maximum of the input start times and a logical stop +at the minimum logical stop of the inputs. The physical stop time is the minimum of +the physical stop times of the two sounds. Note that this violates the "normal" +interpretation that sounds are zero outside their start and stop times. For +example, even if sound1 extends beyond sound2 and is greater than zero, +the result +value in this extension will be zero because it will be after the physical stop time, +whereas if we simply treated sound2 as zero in this region and took the maximum, we +would get a non-zero result. Use s-max instead (see Section "More Behaviors").

+
snd-normalize(sound) [SAL]
+ +(snd-normalize sound) [LISP]
Internally, sounds +are stored with a scale factor that applies to all samples of the sound. +All operators that take sound arguments take this scale factor into account +(although it is not always necessary to perform an actual multiply per +sample), so you should never need to call this function. This function +multiplies each sample of a sound by its scale factor, returning a sound +that represents the same signal, but whose scale factor is 1.0.

+
snd-oneshot(sound, threshold, ontime) [SAL]
+ +(snd-oneshot sound threshold ontime) [LISP]
Computes a new sound that is zero +except where sound exceeds threshold. From these points, the result is +1.0 until sound remains below threshold for ontime (in seconds). +The result has the same sample rate, start time, logical stop time, and +duration as sound.

+
snd-prod(sound1, sound2) [SAL]
+ +(snd-prod sound1 sound2) [LISP]
Computes the +product of sound1 and sound2. The resulting sound has its start +time at the maximum of the input start times and a logical stop at the minimum +logical stop of the inputs. Do not use this function. Use mult or +prod instead (see Section "Sound Synthesis"). Sample rate, start time, etc. are taken from sound.

+
snd-pwl(t0, sr, +lis) [SAL]
+ +(snd-pwl t0 sr lis) [LISP]
Computes a piece-wise linear function according to the breakpoints +in lis. The starting time is t0, and the sample rate is sr. +The breakpoints are passed in an XLISP list (of type LVAL) where the +list alternates sample numbers (FIXNUMs, computed in samples +from the beginning of the pwl function) and values (the value of the pwl +function, given as a FLONUM). There is an implicit starting +point of (0, 0). The list must contain an odd number of points, the omitted +last +value being implicitly zero (0). The list is assumed to be well-formed. Do +not call this function. Use pwl instead (see Section "Piece-wise Approximations").

+
snd-quantize(sound, steps) [SAL]
+ +(snd-quantize sound steps) [LISP]
Quantizes a sound. See Section +"More Behaviors" for details.

+
snd-recip(sound) [SAL]
+ +(snd-recip sound) [LISP]
Compute the reciprocal of each sample of sound. Use recip instead (see Section "More Behaviors").

+
snd-resample(f, +rate) [SAL]
+ +(snd-resample f rate) [LISP]
Resample sound f using high-quality interpolation, yielding +a new sound with the specified rate. The result is scaled by 0.95 because often, +in resampling, interpolated values exceed the original sample values, and this +could lead to clipping. +The resulting start time, etc. are taken from +f. Use resample instead.

+
snd-resamplev(f, rate, g) [SAL]
+ +(snd-resamplev f rate g) [LISP]
Compose two +signals, i.e. compute f(g(t)), where f and g are +sounds. The result has sample rate given by rate. At each time t +(according to the rate), g is linearly interpolated to yield an +increasing sequence of high-precision score-time values. f is then +interpolated at each value to yield a result sample. If in fact g +decreases, the current sample of g is replaced by the previous one, +forcing g into compliance with the non-decreasing restriction. +The result is scaled by 0.95 because often, +in resampling, interpolated values exceed the original sample values, and this +could lead to clipping. Note that +if g has a high sample rate, this may introduce unwanted jitter into +sample times. See sound-warp for a detailed discussion. See +snd-compose for a fast, low-quality alternative to this function. +Normally, you should use sound-warp instead of this function.

+
snd-scale(scale, sound) [SAL]
+ +(snd-scale scale sound) [LISP]
Scales the amplitude of sound by the factor scale. Use scale instead (see Section +"Sound Synthesis").

+
snd-shape(signal, table, origin) [SAL]
+ +(snd-shape signal table origin) [LISP]
A waveshaping function. This is the primitive upon which shape is based. The snd-shape function is like shape except that signal and table must be (single-channel) sounds. Use shape instead (see Section "Filter Behaviors").

+
snd-up(srate, sound) [SAL]
+ +(snd-up srate sound) [LISP]
Increases sample rate by linear +interpolation. The sound is the signal to be up-sampled, and srate +is the output sample rate. Do not call this function. Nyquist performs +sample-rate conversion automatically as needed. If you want to force a +conversion, call force-srate (see Section "Sound Synthesis").

+
+snd-xform(sound, sr, time, start, +stop, scale) [SAL]
+ +(snd-xform sound sr time start stop scale) [LISP]
Makes a copy of sound and then alters it in +the following order: (1) the start time (snd-t0) of the sound is shifted to +time, (1) the sound is stretched as a result of setting the sample rate +to sr (the start time is unchanged by this), (3) the sound is clipped + from start to stop, (4) if start is greater than time, the sound is shifted +shifted by time - start, so that the start time is time, (5) the +sound is scaled by scale. An empty (zero) sound at time will be +returned if all samples are clipped. Normally, you should accomplish all +this using transformations. A transformation applied to a sound has no +effect, so use cue to create a transformable sound (see Section +"Using Previously Created Sounds").

+
+snd-yin(sound, minstep, maxstep, rate) [SAL]
+ +(snd-yin sound minstep maxstep rate) [LISP]
Identical to +yin. See Section "More Behaviors".

+

Filters

+These are also "Signal Operators," the subject of the previous section, +but there are so many filter functions, they are +documented in this special section. +

+Some filters allow time-varying filter parameters. In these functions, +filter coefficients are calculated at the sample rate of the filter +parameter, and coefficients are not interpolated. +

+

+
snd-alpass(sound, delay, feedback) [SAL]
+ +(snd-alpass sound delay feedback) [LISP]
An all-pass filter. This produces a repeating echo effect without the resonances of snd-delay. The feedback should be less than one to avoid exponential amplitude blowup. Delay is rounded to the nearest sample. You should use alpass instead (see Section "Filter Behaviors").

+
snd-alpasscv(sound, delay, +feedback) [SAL]
+ +(snd-alpasscv sound delay feedback) [LISP]
An all-pass filter with variable feedback. +This is just like snd-alpass except feedback is a sound. +You should use alpass instead (see Section "Filter Behaviors").

+
snd-alpassvv(sound, delay, feedback, maxdelay) [SAL]
+ +(snd-alpassvv sound delay feedback maxdelay) [LISP]
An all-pass filter with variable feedback and delay. This is just like snd-alpass except feedback and delay are sounds, and there is an additional FLONUM parameter, maxdelay, that gives an upper bound on the value of delay. Note: delay must remain between zero and maxdelay. If not, results are undefined, and Nyquist may crash. You should use alpass instead (see Section "Filter Behaviors").

+
snd-areson(sound, hz, bw, +normalization) [SAL]
+ +(snd-areson sound hz bw normalization) [LISP]
A notch filter modeled after the areson +unit generator in Csound. The snd-areson filter is an exact +complement of snd-reson such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. Note that because of this complementary design, +the power is not normalized as in snd-reson. See snd-reson +for details on normalization. You should use areson instead (see +Section "Filter Behaviors").

+
snd-aresoncv(sound, hz, bw, +normalization) [SAL]
+ +(snd-aresoncv sound hz bw normalization) [LISP]
This function is identical to snd-areson except +the bw (bandwidth) parameter is a sound. Filter coefficients are +updated at the sample rate of bw. The "cv" suffix stands for Constant, +Variable, indicating that hz and bw are constant (a number) and +variable (a sound), respectively. This naming convention is used throughout. +You should use areson instead (see +Section "Filter Behaviors").

+
snd-aresonvc(sound, hz, bw, +normalization) [SAL]
+ +(snd-aresonvc sound hz bw normalization) [LISP]
This function is identical to snd-areson except +the hz (center frequency) parameter is a sound. Filter coefficients are +updated at the sample rate of hz. +You should use areson instead (see +Section "Filter Behaviors").

+
snd-aresonvv(sound, hz, bw, +normalization) [SAL]
+ +(snd-aresonvv sound hz bw normalization) [LISP]
This function is identical to snd-areson except +both hz (center frequency) and bw (bandwidth) are sounds. Filter +coefficients are updated at the next sample of either hz or bw. +You should use areson instead (see +Section "Filter Behaviors").

+
snd-atone(sound, hz) [SAL]
+ +(snd-atone sound hz) [LISP]
A high-pass filter +modeled after the atone unit generator in Csound. The snd-atone filter is an exact +complement of snd-tone such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. You should use hp instead (see +Section "Filter Behaviors").

+
snd-atonev(sound, hz) [SAL]
+ +(snd-atonev sound hz) [LISP]
This is just like +snd-atone except that the hz cutoff frequency is a sound. Filter +coefficients are updated at the sample rate of hz. You should use +hp instead (see Section "Filter Behaviors").

+
snd-biquad(sound, b0, b1, b2, a1, a2, z1init, z2init) [SAL]
+ +(snd-biquad sound b0 b1 b2 a1 a2 z1init z2init) [LISP]
A general second order IIR filter, where a0 is assumed to be unity. For a1 and a2, the sign convention is opposite to that of Matlab. All parameters except the input sound are of type FLONUM. You should probably use one of lowpass2, highpass2, bandpass2, notch2, allpass2, eq-lowshelf, eq-highshelf, eq-band, lowpass4, lowpass6, lowpass8, highpass4, highpass6, or highpass8, which are all based on snd-biquad and described in Section "Filter Behaviors". For completeness, you will also find biquad and biquad-m described in that section.

+
+snd-chase(sound, risetime, falltime) [SAL]
+ +(snd-chase sound risetime falltime) [LISP]
A slew rate limiter. The output "chases" the input at rates determined by risetime and falltime. If the input changes too fast, the output will lag behind the input. This is a form of lowpass filter, but it was created to turn hard-switching square waves into smoother control signals that could be used for linear crossfades. If the input switches from 0 to 1, the output will linearly rise to 1 in risetime seconds. If the input switches from 1 to 0, the output will linearly fall to 0 in falltime seconds. The generated slope is constant; the transition is linear; this is not an exponential rise or fall. The risetime and falltime must be scalar constants; complain to the author if this is not adequate. The snd-chase function is safe for ordinary use. See snd-follow in Section "Signal Operations" for a related function.

+
snd-congen(gate, risetime, falltime) [SAL]
+ +(snd-congen gate risetime falltime) [LISP]
A simple "contour generator" based +on analog synthesizers. The gate is a sound that normally steps from 0.0 to 1.0 at the start of an envelop and goes from +1.0 back to 0.0 at the beginning of the release. At each sample, the output converges to the input exponentially. If gate is greater than the output, e.g. the attack, then the output converges half-way to the output in risetime. If the gate is less than the output, the half-time is falltime. The sample rate, starting time, logical-stop-time, and terminate time are taken from gate. You should use congen instead (see Section "Filter Behaviors".

+
snd-convolve(sound, response) [SAL]
+ +(snd-convolve sound response) [LISP]
Convolves +sound by response using a simple O(N x M) algorithm. The sound +can be any length, but the response is computed and stored in a table. The required compuation time per sample and total space are proportional to the +length of response. Use convolve instead (see Section +"Filter Behaviors").

+
snd-delay(sound, delay, feedback) [SAL]
+ +(snd-delay sound delay feedback) [LISP]
Feedback +delay. The output, initially sound, is recursively delayed by delay, scaled by feedback, and added to itself, producing an repeating echo effect. The feedback should be less than one to avoid exponential amplitude blowup. Delay is rounded to the nearest sample. You should use feedback-delay instead (see Section "Filter Behaviors")

+
snd-delaycv(sound, delay, +feedback) [SAL]
+ +(snd-delaycv sound delay feedback) [LISP]
Feedback delay with variable feedback. This is just like +snd-delay except feedback is a sound. You should use +feedback-delay instead (see Section "Filter Behaviors").

+
snd-reson(sound, hz, bw, normalization) [SAL]
+ +(snd-reson sound hz bw normalization) [LISP]
A +second-order resonating (bandpass) filter with center frequency hz and +bandwidth bw, modeled after the reson unit generator in Csound. +The normalization parameter must be an integer and (like in Csound) +specifies a scaling factor. A value of 1 specifies a peak amplitude +response of 1.0; all frequencies other than hz are attenuated. A +value of 2 specifies the overall RMS value of the amplitude response +is 1.0; thus filtered white noise would retain the same power. A value of +zero specifies no scaling. The result sample rate, start time, etc. are takend from sound. +You should use reson instead (see Section +"Filter Behaviors").

+
snd-resoncv(sound, hz, bw, +normalization) [SAL]
+ +(snd-resoncv sound hz bw normalization) [LISP]
This function is identical to snd-reson except +bw (bandwidth) is a sound. Filter coefficients are updated at the +sample rate of bw. You should use reson instead (see Section +"Filter Behaviors").

+
snd-resonvc(sound, hz, bw, +normalization) [SAL]
+ +(snd-resonvc sound hz bw normalization) [LISP]
This function is identical to snd-reson except +hz (center frequency) is a sound. Filter coefficients are updated at the +sample rate of hz. You should use reson instead (see Section +"Filter Behaviors").

+
snd-resonvv(sound, hz, bw, +normalization) [SAL]
+ +(snd-resonvv sound hz bw normalization) [LISP]
This function is identical to snd-reson except +botth hz (center frequency) and bw (bandwidth) are sounds. Filter +coefficients are updated at the next sample from either hz or bw. You should use reson instead (see Section +"Filter Behaviors").

+
snd-stkchorus(sound, delay, depth, freq, mix, +sr) [SAL]
+ +(snd-stkchorus sound delay depth freq mix sr) [LISP]
A chorus implemented in STK. The parameter delay is a FIXNUM +representing the median desired delay length in samples. A typical +value is 6000. The FLONUM parameters depth and freq set the modulation +depth (from 0 to 1) and modulation frequency (in Hz), mix sets the mixture +of input sound and chorused sound, where a value of 0.0 means input sound +only (dry) and a value of 1.0 means chorused sound only (wet). +The parameter sr is the desired sample rate of the resulting sound (Footnote 3) You should use pitshift instead +(see Section "Effects").

+
snd-stkpitshift(sound, shift, mix, sr) [SAL]
+ +(snd-stkpitshift sound shift mix sr) [LISP]
A +pitch shifter implemented in STK. The sound is shifted in pitch by +shift, a FLONUM representing the shift factor. A value of 1.0 means + no shift. The parameter mix sets the mixture of input and shifted sounds. +A value of 0.0 means input only (dry) and a value of 1.0 means shifted +sound only (wet). The sr is the desired sampling frequency. (Footnote 4) You should use pitshift instead +(see Section "Effects").

+
snd-stkrev(rev-type, sound, decay, mix, sr) [SAL]
+ +(snd-stkrev rev-type sound decay mix sr) [LISP]
A reverb +implemented in STK. The parameter rev-type is a FIXNUM ranging from zero to +two and selects the type of reverb. Zero selects NRev type, one selects JCRev, +and two selects PRCRev. The input sound is processed by the reverb with +a decay time in seconds (a FLONUM). The mix, a FLONUM, +sets the +mixture of dry input and reverb output. A value of 0.0 means input only (dry) +and a value of 1.0 means reverb only (wet). The sample rate +is sr (Footnote 5) You +should use nrev, jcrev or prcrev instead (see +Section "Effects").

+
snd-tone(sound, hz) [SAL]
+ +(snd-tone sound hz) [LISP]
A +first-order recursive low-pass filter, based on the tone unit generator +of Csound. The hz parameter is the cutoff frequency, the response +curve's half-power point. The result sample rate, start time, etc. are takend from sound. +You should use lp instead (see Section +"Filter Behaviors").

+
snd-tonev(sound, hz) [SAL]
+ +(snd-tonev sound hz) [LISP]
This function is +identical to snd-tone except hz (cutoff frequency) is a sound. +The filter coefficients are updated at the sample rate of hz. You +should use lp instead (see Section +"Filter Behaviors").

+

Table-Lookup Oscillator Functions

+These functions all use a sound to describe one period of a periodic +waveform. In the current implementation, the sound samples are copied to an +array (the waveform table) when the function is called. To make a +table-lookup oscillator generate a specific pitch, we need to have several +pieces of information: +
    +
  • +A waveform to put into the table. This comes from the sound parameter. +
  • The length (in samples) of the waveform. This is obtained by reading +samples (starting at the sound's start time, not necessarily at time zero) +until the physical stop time of the sound. (If you read the waveform from a +file or generate it with functions like sim and sine, then the +physical and logical stop times will be the same and will correspond to the +duration you specified, rounded to the nearest sample.) +
  • The intrinsic sample rate of the waveform. This sample rate is simply the +sample rate property of sound. +
  • The pitch of the waveform. This is supplied by the step parameter and +indicates the pitch (in steps) of sound. You might expect that the +pitch would be related to the period (length) of sound, but there is the +interesting case that synthesis based on sampling often loops over multiple +periods. This means that the fundamental frequency of a generated tone may +be some multiple of the looping rate. In Nyquist, you always specify the +perceived pitch of the looped sound if the sound is played at the +sound's own sample rate. +
  • The desired pitch. This is specified by the hz parameter +in Hertz (cycles per second) in these low-level functions. Note that this +is not necessarily the "loop" rate at which the table is scanned. +Instead, Nyquist figures what sample rate conversion would be necessary to +"transpose" from the step which specifies the original pitch of +sound to hz, which gives the desired pitch. The mixed use of steps +and Hertz came about because it seemed that sample tables would be tagged +with steps ("I sampled a middle-C"), whereas frequency deviation in the +fmosc function is linear, thus calling for a specification in Hertz. +
  • The desired sample rate. This is given by the sr parameter in Hertz. +
+

+Other parameters common to all of these oscillator functions are: +

    +
  • +t0, the starting time, and +
  • phase, the starting phase in degrees. Note that if the step +parameter indicates that the table holds more than one fundamental period, then a starting phase of 360 will be different than a starting phase of 0. +
+

+

+
+ snd-amosc(sound, step, sr, hz, t0, +am, phase) [SAL]
+ +(snd-amosc sound step sr hz t0 am phase) [LISP]
An oscillator with amplitude modulation. The sound +am specifies the amplitude and the logical stop time. The physical stop +time is also that of am. You should use amosc instead (see +Section "Oscillators").

+
snd-fmosc(s, step, sr, hz, t0, fm, +phase) [SAL]
+ +(snd-fmosc s step sr hz t0 fm phase) [LISP]
A Frequency Modulation oscillator. The sound fm specifies +frequency deviation (in Hertz) from hz. You should use fmosc +instead (see Section "Oscillators").

+
snd-fmfb(t0, hz, sr, index, dur) [SAL]
+ +(snd-fmfb t0 hz sr index dur) [LISP]
A Feedback FM oscillator. The resulting sound starts +at t0, has a fundamental frequency of hz, a sample rate of sr, +and a duration of dur seconds. The index is a FLONUM that +specifies the amount of feedback. You should use fmfb instead (see +Section "Oscillators").

+
snd-fmfbv(t0, hz, sr, index)
+ +(snd-fmfv t0 hz sr index) [LISP]
A + Feedback FM oscillator. The resulting sound starts +at t0, has a fundamental frequency of hz, and +a sample rate of sr. The index is a SOUND that +specifies the amount of feedback and determines the duration. +You should use fmfb instead (see Section "Oscillators").

+
snd-buzz(n, sr, hz, t0, fm) [SAL]
+ +(snd-buzz n sr hz t0 fm) [LISP]
A +buzz oscillator, which generates n harmonics of equal amplitude. +The fm specifies +frequency deviation (in Hertz) from hz. You should use buzz +instead (see Section "Oscillators").

+
snd-pluck(sr, hz, t0, d, + final-amp) [SAL]
+ +(snd-pluck sr hz t0 d final-amp) [LISP]
A Karplus-Strong plucked string oscillator with sample rate +sr, fundamental frequency hz, starting time t0, duration d, +initial amplitude approximately 1.0 (not exact because the string is +initialized with random values) and final amplitude approximately +final-amp. You should use pluck instead (see Section + "Oscillators").

+
snd-osc(s, step, sr, hz, t0, d, phase) [SAL]
+ +(snd-osc s step sr hz t0 d phase) [LISP]
A simple table lookup oscillator with fixed frequency. The duration +is d seconds. You should use osc instead (see Section +"Oscillators").

+
snd-partial(sr, hz, t0, env) [SAL]
+ +(snd-partial sr hz t0 env) [LISP]
This is a +special case of snd-amosc that generates a sinusoid starting at phase +0 degrees. The env parameter gives the envelope or any other amplitude +modulation. You should use partial instead (see Section +"Oscillators").

+
snd-sine(t0, hz, sr, d) [SAL]
+ +(snd-sine t0 hz sr d) [LISP]
This is a +special case of snd-osc that always generates a sinusoid with initial +phase of 0 degrees. You should use sine instead (see Section "Oscillators").

+
snd-siosc(tables, sr, hz, t0, +fm) [SAL]
+ +(snd-siosc tables sr hz t0 fm) [LISP]
A Spectral Interpolation Oscillator with frequency modulation. The +tables is a list of sounds and sample counts as follows: (table0 +count1 table1 ... countN tableN). The initial waveform is given by table0, which is interpolated linearly to table1 over the first +count1 samples. From count1 to count2 samples, the waveform is +interpolated from table1 to table2, and so on. If more than +countN samples are generated, tableN is used for the remainder of +the sound. The duration and logical stop time of the sound is taken from +fm, which specified frequency modulation (deviation) in Hertz. You +should use siosc instead (see Section "Oscillators").

+

Physical Model Functions

+These functions perform some sort of physically-based modeling synthesis. +
+
+(snd-bandedwg freq bowpress-env preset sr)
+ +(snd-bandedwg freq bowpress-env preset sr) [LISP]
A Banded Wave Guide +Percussion instrument implemented in STK. The parameter freq is a +FLONUM in Hz, bowpress-env is +a SOUND that ranges from zero to one, preset is a FIXNUM, +and sr is the desired sample rate in Hz. Currently, there are four +presets: uniform-bar (0), tuned-bar (1), glass-harmonica (2), and +tibetan-bowl (3). You should use wg-uniform-bar, wg-tuned-bar, + wg-glass-harm, or wg-tibetan-bowl instead (see Section +"Physical Models").

+
snd-bowed(freq, +bowpress-env, sr) [SAL]
+ +(snd-bowed freq bowpress-env sr) [LISP]
A bowed string instrument implemented in +STK. The freq is a FLONUM in Hertz, bowpress-env is a + SOUND that ranges from z +ero to one, and sr is the desired sample rate (a FLONUM). +You should use bowed instead (see Section "Physical Models").

+
snd-bowed-freq(freq, bowpress-env, freq-env, sr) [SAL]
+ +(snd-bowed-freq freq bowpress-env freq-env sr) [LISP]
A bowed model just like snd-bowed but with +an additional parameter for continuous frequency control. You should use +bowed-freq instead (see Section "Physical Models").

+
snd-clarinet(freq, breath-env, sr) [SAL]
+ +(snd-clarinet freq breath-env sr) [LISP]
A clarinet +model implemented in STK. The freq is a FLONUM in Hertz, + breath-env is +a SOUND that ranges from zero to one, and sr is the + desired sample +rate (a FLONUM). You should use clarinet instead + (see Section +"Physical Models").

+
snd-clarinet-freq(freq, breath-env, freq-env, sr) [SAL]
+ +(snd-clarinet-freq freq breath-env freq-env sr) [LISP]
A clarinet model just like snd-clarinet but with +an additional parameter for continuous frequency control. You should use +clarinet-freq instead (see Section "Physical Models").

+
snd-clarinet-all(freq, vibrato-freq, +vibrato-gain, freq-env, breath-env, +reed-stiffness, noise, sr) [SAL]
+ +(snd-clarinet-all freq vibrato-freq vibrato-gain freq-env breath-env reed-stiffness noise sr) [LISP]
A clarinet model just like +snd-clarinet-freq but with +additional parameters for vibrato generation and continuous control of +reed stiffness and breath noise. You should use +clarinet-all instead (see Section "Physical Models").

+
snd-flute(freq, + breath-env, sr) [SAL]
+ +(snd-flute freq breath-env sr) [LISP]
A flute implemented in STK. The freq is a +FLONUM in Hertz, breath-env is a SOUND + that ranges from zero to one, and sr is + the desired sample rate (a FLONUM). You should use flute + instead (see Section "Physical Models").

+
snd-flute-freq(freq, breath-env, +freq-env, sr) [SAL]
+ +(snd-flute-freq freq breath-env freq-env sr) [LISP]
A flute model just like snd-flute but with +an additional parameter for continuous frequency control. You should use +flute-freq instead (see Section "Physical Models").

+
snd-flute-all(freq, vibrato-freq, vibrato-gain, freq-env, breath-env, +jet-delay, noise, sr) [SAL]
+ +(snd-flute-all freq vibrato-freq vibrato-gain freq-env breath-env jet-delay noise sr) [LISP]
A flute model just like +snd-flute-freq but with +additional parameters for vibrato generation and continuous control of +breath noise. You should use +flute-all instead (see Section "Physical Models").

+
snd-mandolin(t0, freq, dur, body-size, detune, sr) [SAL]
+ +(snd-mandolin t0 freq dur body-size detune sr) [LISP]
A plucked + double-string instrument model implemented in STK. The t0 parameter + is the starting time (in seconds), freq is a FLONUM in + Hz, body-size and detune are FLONUMs, and sr + is the desired sample + rate. You should use mandolin instead (see Section "Physical Models").

+
snd-modalbar(t0, freq, preset, dur, sr) [SAL]
+ +(snd-modalbar t0 freq preset dur sr) [LISP]
Struck bar instrument + model implemented in STK. The parameter t0 is the starting +time (in seconds), freq is a FLONUM in Hz, + preset is a FIXNUM ranging from 0 to 8, dur is a +FLONUM that + sets the duration (in seconds) and sr is the desired sample rate. You +should use modalbar instead (see Section "Physical Models").

+
snd-sax(freq, breath-env, sr) [SAL]
+ +(snd-sax freq breath-env sr) [LISP]
A sax +model implemented in STK. The freq is a FLONUM in Hertz, breath-env is +a SOUND that ranges from zero to one, and sr is the desired sample +rate (a FLONUM). You should use sax instead (see Section +"Physical Models").

+
snd-sax-freq(freq, freq-env, breath-env, + sr) [SAL]
+ +(snd-sax-freq freq freq-env breath-env sr) [LISP]
A sax model just like snd-sax but with +an additional parameter for continuous frequency control. You should use +sax-freq instead (see Section "Physical Models").

+
snd-sax-all(freq, vibrato-freq, +vibrato-gain, freq-env, breath-env, +reed-stiffness, noise, blow-pos, reed-table-offset, sr) [SAL]
+ +(snd-sax-all freq vibrato-freq vibrato-gain freq-env breath-env reed-stiffness noise blow-pos reed-table-offset sr) [LISP]
A +sax model just like +snd-sax-freq but with +additional parameters for vibrato generation and continuous control of +reed stiffness, breath noise, excitation position, and reed table offset. + You should use +sax-all instead (see Section "Physical Models").

+
snd-sitar(t0, +freq, dur, sr) [SAL]
+ +(snd-sitar t0 freq dur sr) [LISP]
A sitar model implemented in STK. The parameter +t0 is the starting time, freq is a FLONUM (in Hz), E +dur sets the duration and sr is the sample rate (in Hz) +of the resulting sound. You should use sitar instead (see Section +"Physical Models").

+

Sequence Support Functions

+The next two functions are used to implement Nyquist's seq construct. +

+

+
+snd-seq(sound, closure) [SAL]
+ +(snd-seq sound closure) [LISP]
This function returns +sound until the logical stop time of sound. Then, the XLISP +closure +is evaluated, passing it the logical stop time of sound as a +parameter. The closure must return a sound, which is then added to +sound. (An add is used so that sound can continue past its logical +stop if desired.) Do not call this function. See seq in Section +"Combination and Time Structure".

+
snd-multiseq(array, closure) [SAL]
+ +(snd-multiseq array closure) [LISP]
This +function is similar to snd-seq except the first parameter is a +multichannel sound rather than a single sound. A multichannel sound is +simply an XLISP array of sounds. An array of sounds is returned which is +the sum of array and another array of sounds returned by closure. +The closure is passed the logical stop time of the multichannel sound, +which is the maximum logical stop time of any element of array. Do +not call this function. See seq in Section "Combination and Time Structure". +
+

+

+
+snd-trigger(s, closure) [SAL]
+ +(snd-trigger s closure) [LISP]
This is one of +the only ways in which a behavior instance can be created by changes in a +signal. When s (a SOUND) makes a transition from less than or +equal to zero to greater than zero, the closure, which takes a starting +time parameter, is evaluated. The closure must return a SOUND. The +sum of all these sounds is returned. If there are no sounds, the result will +be zero. The stop time of the result is the maximum stop time of s and +all sounds returned by the closure. The sample rate of the return value is +the sample rate of s, and the sounds returned by the closure must all +have that same sample rate. Do not call this function. +See trigger in Section "Combination and Time Structure".

+
An implementation note: There is no way to have snd-trigger return +a multichannel sound. An alternative implementation would be a built-in +function to scan ahead in a sound to find the time of the next zero crossing. +This could be combined with some LISP code similar to seq to sum up +instances of the closure. However, this would force arbitrary look-ahead +and therefore would not work with real-time inputs, which was the motivation +for snd-trigger in the first place. +
+

+


+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/part9.html b/doc/part9.html new file mode 100644 index 0000000..30a6b24 --- /dev/null +++ b/doc/part9.html @@ -0,0 +1,40 @@ +Nyquist Globals + +Previous Section | Next Section | Table of Contents | Index | Title Page +
+

Nyquist Globals

+ +There are many global variables in Nyquist. A convention in Lisp is to place asterisks (*) around global variables, e.g. *table*. This is only a convention, and the asterisks are just like any other letter as far as variable names are concerned. Here are some globals users should know about: +

+

+
+*table*
Default table used by osc and other oscillators.

+
*A4-Hertz*
Frequency of A4 in Hertz.. Note: you must call (set-pitch-names) to recompute pitches after changing *A4-Hertz*.

+
*autonorm*
The normalization factor to be applied to the next sound when *autonorm-type* is 'previous. See Sections "Memory Space and Normalization" and "Sound File Input and Output".

+
*autonormflag*
Enables the automatic normalization feature of the play command. You should use (autonorm-on) and (autonorm-off) rather than setting *autonormflag* directly. See Sections "Memory Space and Normalization" and "Sound File Input and Output".

+
*autonorm-max-samples*
Specifies how many samples will be computed searching for a peak value when *autonorm-type* is 'lookahead. See Sections "Memory Space and Normalization" and "Sound File Input and Output".

+
*autonorm-previous-peak*
The peak of the previous sound generated by play. This is used to compute the scale factor for the next sound when *autonorm-type* is 'previous. See Sections "Memory Space and Normalization" and "Sound File Input and Output".

+
*autonorm-target*
The target peak amplitude for the autonorm feature. The default value is 0.9. See Sections "Memory Space and Normalization" and "Sound File Input and Output".

+
*autonorm-type*
Determines how the autonorm feature is implemented. Valid values are 'lookahead (the default) and 'previous. See Sections "Memory Space and Normalization" and "Sound File Input and Output".

+
*breakenable*
Controls whether XLISP enters a break loop when an error is encountered. See Section "Profiling".

+
*control-srate*
Part of the environment, establishes the control sample rate. See Section "The Environment" for details.

+
*default-sf-bits*
The default bits-per-sample for sound files. Typically 16.

+
*default-sf-dir*
The default sound file directory. Unless you give a full path for a file, audio files are assumed to be in this directory. (Applies to many functions that deal with sound files. Check the function description to see if *default-sf-dir* applies.)

+
*default-sf-format*
The default sound file format. When you write a file, this will be the default format: AIFF for Mac and most Unix systems, NeXT for NeXT systems, and WAV for Win32.

+
*default-sf-srate*
The default sample rate for sound files. Typically 44100.0, but often set to 22050.0 for speed in non-critical tasks.

+
*default-control-srate*
Default value for *control-srate*. This value is restored when you execute (top) to pop out of a debugging session. Change it by calling (set-control-srate value).

+
*default-sound-srate*
Default value for *sound-srate*. This value is restored when you execute (top) to pop out of a debugging session. Change it by calling (set-sound-srate value).

+
*file-separator*
The character that separates directories in a path, +e.g. "/" for Unix, ":" for Mac, and "\" for Win32. +This is normally set in system.lsp.

+
*rslt*
When a function returns more than one value, *rslt* is set to a list of the "extra" values. This provides a make-shift version of the multiple-value-return facility in Common Lisp.

+
*sound-srate*
Part of the environment, establishes the audio sample rate. See Section "The Environment" for details.

+
*soundenable*
Controls whether writes to a sound file will also be played as audio. Set this variable by calling (sound-on) or (sound-off).

+
*tracenable*
Controls whether XLISP prints a backtrace when an error is encountered.

+
XLISP variables
See Section "Profiling" for a list of +global variables defined by XLISP.

+
Environment variables
See Section "The Environment" for definitions of variables used in the environment for behaviors. In general, you should never set or access these variables directly.

+
Various constants
See Section "Predefined Constants" for definitions of predefined constants for loudness, duration, and pitch.

+

+Previous Section | Next Section | Table of Contents | Index | Title Page + diff --git a/doc/poisson-fig.gif b/doc/poisson-fig.gif new file mode 100644 index 0000000..6e4b51b Binary files /dev/null and b/doc/poisson-fig.gif differ diff --git a/doc/sdl-man.pdf b/doc/sdl-man.pdf new file mode 100644 index 0000000..087c266 Binary files /dev/null and b/doc/sdl-man.pdf differ diff --git a/doc/title.html b/doc/title.html new file mode 100644 index 0000000..9acdcf1 --- /dev/null +++ b/doc/title.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Nyquist Reference Manual + + + + +

+ +

Nyquist Reference Manual

+Version 3.05 + +

+ +Copyright 2011 by Roger B. Dannenberg + + +

+
Carnegie Mellon University
+School of Computer Science
+Pittsburgh, PA 15213, U.S.A.
+ +

+ + + + + + + + +


+Next Section | Index |
+ +

Table of Contents

+
+
+Next Section | Table of Contents | Index | Title Page + diff --git a/docsrc/bib/music.bib b/docsrc/bib/music.bib new file mode 100644 index 0000000..13b1d7b --- /dev/null +++ b/docsrc/bib/music.bib @@ -0,0 +1,3465 @@ +@article(4CED + ,key "Abbot" + ,author "Abbot, Curtis" + ,title "The 4CED Program" + ,journal "Computer Music Journal" + ,Volume 5 + ,Number 1 + ,Month "Spring" + ,Year 1981 + ,Pages "13-33" + ) + +@book(surveys + ,key "Abbot" + ,editor "Abbot. C." + ,publisher "ACM" + ,title "Computing Surveys" + ,year 1985 + ,volume 17 + ,note "No. 2 (June)" + ) + +@book(abelson + ,key "Abelson" + ,author "Abelson, H. and G. J. Sussman, with J. Sussman" + ,title "Structure and Interpretation of Computer Programs" + ,publisher "MIT Press" + ,year 1985 + ) + +@inproceedings(Mach + ,author "Accetta, M., R. Baron, W. Bolosky, D. Golub, R. Rashid, A. Tevanian, M. Young" + ,title "Mach: A New Kernel Foundation for UNIX Development" + ,organization "Usenix" + ,booktitle "Proc. of Summer Usenix" + ,year 1986 + ,month July + ) + +@article(ashton + ,key "Ames" + ,author "Ames, C." + ,title "The ASHTON Score-Transcription Utility" + ,journal "Interface" + ,volume 14 + ,pages "165-173" + ,year 1985 + ) + +@book(hypertext89 + ,author "ACM" + ,key "ACM" + ,organization "ACM" + ,title "Hypertext '89 Proceedings" + ,publisher "ACM" + ,year 1989 + ) + +@inproceedings(rodet85 + ,key "Adrien" + ,author "Adrien, J-M, and X. Rodet" + ,title "Physical Models of Instruments: A Modular Approach, Application to Strings" + ,organization "Computer Music Association" + ,booktitle "Proceedings of the 1985 International Computer Music Conference" + ,year 1985 + ,pages "85-96" + ) + +@book(aho + ,author="Aho, Hopcroft, and Ullman" + ,title="The Design and Analysis of Computer Algorithms" + ,publisher="Addison Wesley" + ,key="Aho" + ,year=1974 + ) + +@inproceedings(Allen90 + ,key "Allen" + ,author "Allen, P. E. and R. B. Dannenberg" + ,title "Tracking Musical Beats in Real Time" + ,organization "International Computer Music Association" + ,booktitle "ICMC Glasgow 1990 Proceedings" + ,editor "S. Arnold and G. Hair" + ,year 1990 + ,pages "140-143" + ) + +@unpublished(Anderson85b + ,key "Anderson" + ,author "Anderson, D. P. and R. Kuivila" + ,title "Continuous Abstractions for Discrete Event Languages" + ,year "1985" + ) + +@article(Formula-TOCS + ,key "Anderson" + ,author "Anderson, D. P. and R. Kuivila" + ,title "A System for Computer Music Performance" + ,journal "ACM Transactions on Computer Systems" + ,volume 8 + ,number 1 + ,pages 56-82 + ,month February + ,year 1990 +) + +@article(Formula + ,key "Anderson" + ,author "Anderson, D. P. and R. Kuivila" + ,title "Accurately Timed Generation of Discrete Musical Events" + ,journal "Computer Music Journal" + ,volume 10 + ,number 3 + ,month "Fall" + ,year 1986 + ,pages "48-56" + ) + +@techreport(acme + ,key "Anderson" + ,title "Abstractions for Continuous Media in a Network Window System" + ,author "Anderson, D. P., R. Govindan, G. Homsy" + ,institution "Computer Science Division (EECS), U.C. at Berkeley" + ,number "UCB/CSD 90/596" + ,year 1990 +) + +@article(acmecomputer + ,key "Anderson" + ,title "A Continuous Media I/O Server and Its Synchronization Mechanism" + ,author "Anderson, D. P. and G. Homsy" + ,journal "Computer" + ,month "October" + ,pages "51-57" + ,year 1991 +) + + +@article(andrews + ,key Andrews + ,author "Andrews, G. R." + ,title "Concepts and Notations for Concurrent Programming" + ,journal "ACM Computing Surveys" + ,volume 15 + ,number 1 + ,month "March" + ,year 1983 + ,pages "3-43" + ) + + +@article(lisp-tutor + ,key = Anderson + ,author "Anderson, J. R., F. G. Conrad, and A. T. Corbett" + ,title "Skill acquisition and the LISP TUTOR" + ,journal "Cognitive Science" + ,volume 13 + ,number 4 + ,month "Oct-Dec" + ,year 1989 + ,pages "467-505" +) + +@misc(smdl + ,key="ANSI" + ,author="ANSI" + ,title="X3V1.8M/SD-7 Journal of Development, Standard Music Description Language, Part 2: Technical Description and Formal Definition" + ,howpublished="International Computer Music Association, San Francisco" + ) + + +@article(Lucid + ,key "Ashcroft" + ,author "Ashcroft, E. A. and W. W. Wadge" + ,title "Lucid, a Nonprocedural Language with Iteration" + ,journal "Communications of the ACM" + ,volume "20" + ,number "7" + ,month "July" + ,year "1977" + ,pages "519-526" + ) + +@inproceedings(Assayag + ,key "Assayag" + ,author "Assayag, G., and D. Timis" + ,title "A ToolBox for Music Notation" + ,pages "173-178" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ) + +@article(Backus + ,key "Backus" + ,author "Backus, John" + ,title "Can Programming Be Liberated from the von Neumann Style?" + ,journal "Communications of the ACM" + ,Volume 21 + ,Number 8 + ,Month "August" + ,Year 1978 + ,Pages "613-641" + ) + +@article(Baird93 + ,key "Baird" + ,author "Baird, B., D. Blevins, N. Zahler" + ,title "Artificial Intelligence and Music: Implementing an Interactive Computer Performer" + ,journal "Computer Music Journal" + ,volume 17 + ,number 2 + ,month "Summer" + ,year 1993 + ,pages "73-79" + ) + +@techreport(balaban + ,key "Balaban" + ,title "Music Structures: A Temporal-Hierarchical Representation + For Music" + ,author "Balaban, Mira" + ,institution "Ben Gurion University Department of Mathematics and + Computer Science" + ,number "FC-TR-021 MCS-313" + ,year 1989 + ) + +@article(Balzano80 + ,key="Balzano" + ,author="Balzano, G. J." + ,title="The Group-theoretic Description of 12-Fold and Microtonal +Pitch Systems" + ,journal="Computer Music Journal" + ,number="4" + ,year="1980" + ,volume="4" + ,pages="66-84" + ) + +@book(FMA + ,key="Benade" + ,author="Benade, A. H." + ,title="Fundamentals of Musical Acoustics" + ,publisher="Oxford University Press" + ,year="1976" + ) + +@inproceedings(berger + ,key "Berger" + ,author "Berger, Jonathan" + ,title "Theory and Practice: Chicken and Egg" + ,booktitle "The Arts and Technology II: A Symposium" + ,pages "24-30" + ,year 1989 + ,organization "Connecticut College" + ) + +@article(bentley, key="Bentley" + ,author="Bentley, Jon" + ,title="Programming Pearls" + ,journal="Communications of the ACM" + ,volume="28", number="3" + ,pages="245-250" + ,year=1985 + ) + +@unpublished(Betz + ,key "Betz" + ,author "Betz, David" + ,title "XLISP: An Experimental Object-oriented Language, Version 1.7" + ,date "June 2" + ,year 1986 + ,note "(program documentation)" + ) + +@Misc(Blackwood80 + ,key="Blackwood" + ,author="Blackwood, E." + ,title="Twelve Microtonal Etudes for Electronic Music Media" + ,howpublished="Stereo LP Recording available from Easley Blackwood, +5300 S. Shore Drive, Chicago, IL 60615" + ,note="score published by G. Schirmer" + ) + +@book(knowledgerep + ,key "Brachman" + ,author "Brachman, R. J., and H. J. Levesque, eds." + ,title "Readings in Knowledge Representation" + ,publisher "M. Kaufmann" + ,year 1985 + ,address "Los Altos, Calif." + ) + +@book(MultimediaInterfaceDesign + ,key "Blattner" + ,editors "Blattner, M. M. and R. B. Dannenberg" + ,title "Multimedia Interface Design" + ,publisher "ACM Press" + ,year 1992 +) + +@inproceedings(bilmes92 + ,key "Bilmes" + ,author "Bilmes, J." + ,title "A Model for Musical Rhythm" + ,organization "Computer Music Association" + ,booktitle = "ICMC Proceedings" + ,year = "1992" + ,pages "207-210" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ) + +@article(Blesser + ,key "Blesser" + ,author "Blesser, B. A." + ,title "Digitization of Audio: A Comprehensive Examination of Theory, +Implementation, and Current Practice" + ,journal "Journal of the Audio Engineering Society" + ,volume 26 + ,number 10 + ,pages "739-771" + ,year 1978 + ,month "October" + ) + +@inproceedings(Bloch + ,key "Bloch" + ,author "Bloch, J. J. and R. B. Dannenberg" + ,title "Real-Time Computer Accompaniment of Keyboard Performances" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the International Computer Music Conference 1985" + ,editor "B. Truax" + ,year 1985 + ,pages "279-290" + ) + +@inproceedings(bloom, + key = "Bloom", + Author = "Bloom, P. J.", + Publisher = "IEEE", + year = "1984", + title = "Use of Dynamic Programming for Automatic Synchronization of + Two Similar Speech Signals", + booktitle = "Proceedings of IEEE International + Conference on Acoustics, Speech, and Signal Processing", + Pages = "2.6.1-2.6.4") + +@inproceedings(BockerStructure + ,key = "Bocker" + ,Author = "Bocker, H.-D. and A. Mahling" + ,title = "What's in a Note?" + ,pages= "166-174" + ,booktitle = "Proceedings of the 14th International Computer Music Conference" + ,editor "C. Lischka and J. Fritsch" + ,year = "1988" + ,organization = "International Computer Music Association" + ) + +@article(Constraints + ,key = "Borning" + ,Author = "Borning, A." + ,Title = "The Programming Language Aspects of Thinglab: A Constraint-Oriented Simulation Laboratory" + ,Journal = "ACM Transactions on Programming Languages and Systems" + ,Volume 3 + ,Number 4 + ,month October + ,year 1981 + ,pages "353-387" + ) + +@inproceedings(midilisp, + key = "Boynton" + ,Author = "Boynton, L., P. Lavoie, Y. Orlarey, C. Rueda and David Wessel" + ,title = "MIDI-LISP: A Lisp Based Music Programming Environment for +the Macintosh" + ,pages= "183-186" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ) + + +@inproceedings(preformes, + key = "Boynton" + ,Author = "L. Boynton, J. Duthen, Y. Potard, and X. Rodet" + ,title = "Adding a Graphical Interface to FORMES." + ,pages= "105-108" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ) + +@inproceedings(brinkmanstructure + ,key = "Brinkman" + ,author = "Brinkman, A." + ,title = "A Data Structure for Computer Analysis of Musical Scores" + ,organization "Computer Music Association" + ,booktitle "Proceedings of the 1984 International Computer Music Conference" + ,year 1985 + ,pages "233-242" + ) + + +@inproceedings(brinkmanGraphs + ,key = "Brinkman" + ,author = "Brinkman, A." + ,title = "Computer-Graphic Tools for Music Analysis" + ,organization "Computer Music Association" + ,booktitle = "ICMC Montreal 1991 Proceedings" + ,year = "1991" + ,pages "53-56" + ,editor "B. Alphonse and B. Pennycook" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ) + + +@article(Buxton, + key = "Buxton", + Author = "Buxton, W., Reeves, W., Fedorkow, G., + Smith, K. C., and Baecker, R.", + Journal = "Computer Music Journal", + Title = "A Microcomputer-based Conducting System", + Year = "1980", + Month = "Spring", + Number = "4", + Pages = "8-21", + Volume = "4") + +@inbook(BuxtonViews + ,key = "Buxton", + ,Author = "Buxton, W., R. Sniderman, W. Reeves, R. Patel, and R. Baecker" + ,Title = "The Evolution of the SSSP Score-Editing Tools" + ,Year = "1985" + ,Booktitle "Foundations of Computer Music" + ,Pages = "376-402" + ,editor "C. Roads and J. Strawn" + ,publisher "MIT Press" + ) + + + +@inbook(BuxtonStructures + ,key = "Buxton", + ,Author = "Buxton, W., W. Reeves, R. Baecker, and L. Mezei" + ,Title = "The Use of Hierarchy and Instance in a Data Structure +for Computer Music" + ,Year = "1985" + ,Booktitle "Foundations of Computer Music" + ,Pages = "443-466" + ,editor "C. Roads and J. Strawn" + ,publisher "MIT Press" + ) + +@article(buxton-modeless + ,key "Buxton" + ,author "Buxton, William" + ,title "Lexical and pragmatic considerations of input structures" + ,journal "Computer Graphics" + ,volume 17 + ,number 1 + ,pages "31-36" + ,year 1983 + ) + +@inproceedings(buxton85 + ,key "Buxton" + ,author "Kitamura, J., W. Buxton, M. Snelgrove and K. C. Smith" + ,title "Music Synthesis by Simulation using a General-Purpose Signal Processing System" + ,organization "Computer Music Association" + ,booktitle "Proceedings of the 1985 International Computer Music Conference" + ,year 1985 + ,pages "155-158" + ) + +@inproceedings(accompchi + ,key "Buxton" + ,author "Buxton, W., Dannenberg, Roger B., Vercoe, Barry" + ,title "The Computer as Accompanist" + ,organization "ACM" + ,address "New York" + ,booktitle "Proceedings of the CHI'86 Human Factors in Computing Systems" + ,editor "M. Mantei and P. Orbeton" + ,year 1986 + ,pages "41-43" + ) + +@inproceedings(mabel + ,key = "Bartlett" + ,author = "Bartlett, M." + ,title="The Development of a Practical Live-Performance Music Language" + ,pages= "297-302" + ,booktitle = "Proceedings of the International Computer Music Conference 1985" + ,editor "B. Truax" + ,year = "1985" + ,organization = "International Computer Music Association" + ) + + + +@phdthesis(Byrd, + ,key = "Byrd" + ,author = "Byrd, Donald" + ,Title = "Music Notation by Computer" + ,school = "Computer Science Department, Indiana University" + ,year = 1984 + ,note = "Ann Arbor: University Microfilms (order no. DA8506091)" + ) + +@book(cage + ,key "Cage" + ,author "Cage, John" + ,title "Silence" + ,publisher "MIT Press" + ,address "Cambridge, MA" + ,year "1969" + ) + +@article(L0 + ,key "Cameron" + ,author "Cameron, E. J., D. M. Cohen, B. Gopinath, W. M. Keese II, + L. Ness, P. Uppaluru, and J. R. Vollaro" + ,title "The IC* Model of Parallel Computation and Programming Environment" + ,journal "IEEE Transactions on Software Engineering" + ,month "March" + ,year 1988 + ,pages "317-326" + ) + +@book(campbell + ,key "Campbell" + ,author "Campbell, R. H. and Habermann, A. N." + ,title "The Specification of Process Synchronization by Path Expressions" + ,series "Lecture Notes in Computer Science" + ,volume 16 + ,publisher "Springer Verlag" + ,address "New York" + ,year "1974" + ) + +@article(ptcurriculum + ,key "Capell" + ,author "Capell, P. and R. B. Dannenberg" + ,title "Instructional Design and Intelligent Tutoring: Theory and the Precision of Design" + ,journal "Journal of Artificial Intelligence in Education" + ,year "1993" + ,pages "95-121" + ,volume 4 + ,number 1 + ) + +@inproceedings(jdb + ,key = "Chabot" + ,author = "Chabot, Xavier, Roger Dannenberg, and Georges Bloch" + ,title="A Workstation in Live Performance: Composed Improvisation" + ,pages= "57-59" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ) + +@article(chadabe, key "Chadabe" + ,title "Interactive Composing: An Overview" + ,journal "Computer Music Journal" + ,author "Chadabe, Joel" + ,year "1984" + ,volume 8, number 1 + ,pages "22-27" + ) + +@article(play + , key "Chadabe" + ,title "An Introduction to the Play Program" + ,author "Chadabe, J., and R. Meyers" + ,journal "Computer Music Journal" + ,year "1978" + ,volume 2, number 1 + ,pages "12-18" + ) + +@article(Chafe, + key = "Chafe", + Author = "Chafe, Chris, Bernard Mont-Reynaud, and Loren Rush", + Journal = "Computer Music Journal", + Title = "Toward an Intelligent Editor of Digital Audio: Recognition + of Musical Constructs", + Year = "1982", + Month = "Spring", + Number = "1", + Pages = "30-41", + Volume = "6") + +@InProceedings(poly, + key = "Chafe" + ,Author = "Chafe, Chris, David Jaffe, Kyle Kashima, + Bernard Mont-Reynaud, and Julius Smith" + ,Organization = "International Computer Music Association", + ,year = "1985" + ,booktitle = "1985 Proceedings of the International Computer Music Conference", + ,title = "Techniques for Note Identification in Polyphonic Music" + ,pages "399-405" + ) + +@article(chowning + ,key "Chowning" + ,author "Chowning, J. M." + ,title "The Synthesis of Complex Audio Spectra by Means of Frequency +Modulation" + ,journal "Journal of the Audio Engineering Society" + ,Volume 21 + ,Number 7 + ,Month "September" + ,Year 1973 +) + +@inbook(clark + ,key "Clark" + ,author "Clark, E. F." + ,title "Expression and communication in musical performance" + ,booktitle "Music, Language, Speech and Brain" + ,series "Wenner-Gren International Symposium Series, Vol. 59" + ,year 1991 + ,editor "J. Sundberg, L. Nord, and R. Carlson" + ,pages "184-193" + ,publisher "Macmillan" + ,address "London" + ) + +@InProceedings(Clendinning, + key = "Clendinning", + Author = "Clendinning, J. and Dworak, P. E.", + Organization = "International Computer Music Association", + year = "1983", + booktitle = "1983 International Computer Music Conference Proceedings", + title = "Computer Pitch Recognition: A New Approach") + +@inbook(clynes + ,key = "Clynes" + ,author "Clynes, M." + ,booktitle "Action and Perception in Rhythm and Music" + ,title "What Can a Musician Learn About Music Performance From + Newly Discovered Microstructure Principles (PM and PAS)?" + ,publisher "Royal Swedish Academy of Music No. 55" + ,year 1987 + ,pages "201-233" + ) + +@inproceedings(FPFormes + ,key "Cointe" + ,author "Cointe, P. and X. Rodet" + ,title "Formes: an Object & Time Oriented System for Music Composition and Synthesis" + ,organization "ACM" + ,booktitle "1984 ACM Symposium on LISP and Functional Programming" + ,address "New York" + ,year 1984 + ,pages "85-95" + ) + +@inproceedings(Moxie + ,key = "Collinge" + ,author = "Collinge, D. J." + ,title = "MOXIE: A Language for Computer Music Performance" + ,pages = "217-220" + ,booktitle = "Proceedings of the International Computer Music Conference 1984" + ,editor = "W. Buxton" + ,year = "1985" + ,organization = "International Computer Music Association" + ) + +@inproceedings(Moxie88collinge + ,key = "Collinge" + ,author = "Collinge, D. J. and Scheidt, D. J." + ,title = "MOXIE for the Atari ST" + ,pages = "231-238" + ,booktitle = "Proceedings of the 14th International Computer Music Conference" + ,editor "C. Lischka and J. Fritsch" + ,year = "1988" + ,organization = "International Computer Music Association" + ) + +@inproceedings(Moxc88pennycook + ,key = Pennycook + ,author = "Pennycook, Bruce W." + ,title = "PRAESCIO-II: AMNESIA Toward Dynamic Tapeless Performance" + ,pages = "383-391" + ,booktitle = "Proceedings of the 14th International Computer Music Conference" + ,editor "C. Lischka and J. Fritsch" + ,year = "1988" + ,organization = "International Computer Music Association" + ) + +@article(Bradford + ,key = "Comerford" + ,author = "Comerford, P. J." + ,title = "Bradford musical instrument simulator" + ,pages = "364-372" + ,journal = "IEE Proc." + ,volume = "128, Pt. A" + ,number = 5 + ,month = "July" + ,year = 1981 + ) + +@book(ObjectiveC + ,key "Cox" + ,author "Cox, B. J." + ,title "Object-Oriented Programming: an evolutionary approach" + ,publisher "Addison-Wesley" + ,year 1987 + ,address "Reading, Mass." + ) + +@phdthesis(Dannenberg82 + ,key "Dannenberg" + ,author "Dannnenberg, Roger B." + ,title "Resource Sharing in a Network of Personal Computers" + ,school "Carnegie Mellon University" + ,year 1982 + ,note "School of Computer Science Report CMU-CS-82-152" + ) + +@inproceedings(teaching + ,key = "Dannenberg" + ,author = "Dannenberg, F. K., R. B. Dannenberg, + and P. Miller" + ,title = "Teaching Programming to Musicians" + ,pages = "114-122" + ,booktitle = "Proceedings Fourth Symposium on Small Computers in the Arts" + ,year = 1984 + ,editor = "D. Mansfield" + ,address = "Washington, D.C." + ,month = "October" + ,organization = "IEEE Computer Society" + ) + +@inproceedings(ArcticLisp + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Arctic: A Functional Language for Real-Time Control" + ,organization "ACM" + ,booktitle "1984 ACM Symposium on LISP and Functional Programming" + ,address "New York" + ,year 1984 + ,month "August" + ,pages "96-103" + ) + +@inproceedings(Dannenberg + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "An On-Line Algorithm for Real-Time Accompaniment" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the International Computer Music Conference 1984" + ,editor = "W. Buxton" + ,pages "193-198" + ,year 1984 + ) + +@InProceedings(Studio84 + ,author = "Dannenberg, Roger B., Paul McAvinney, and Marilyn T. Thomas" + ,key = "Dannenberg" + ,title = "Carnegie-Mellon University Studio Report" + ,booktitle = "Proceedings of the International Computer Music Conference 1984" + ,editor = "W. Buxton" + ,year = "1984" + ,organization = "International Computer Music Association" + ,pages = "281-286" +) + +@InProceedings(ArcticICMC + ,author = "Dannenberg, R. B. and P. McAvinney" + ,key = "Dannenberg" + ,title = "A Functional Approach to Real-Time Control" + ,booktitle = "Proceedings of the International Computer Music Conference 1984" + ,editor = "W. Buxton" + ,year = "1984" + ,organization = "International Computer Music Association" + ,pages = "5-15" + ) + +@inproceedings(Arctic86 + ,key "Dannenberg" + ,author "Dannenberg, Roger B." + ,title "Arctic: Functional Programming for Real-Time Systems" + ,organization "U. Hawaii/Western Periodicals" + ,editor "B. Shriver" + ,booktitle "Proceedings of the Nineteenth Hawaii International +Conference on System Sciences" + ,year 1986 + ,pages "216-226" + ) + +@article(ArcticIEEE + ,key "Dannenberg" + ,author "Dannenberg, Roger B." + ,title "Arctic: A Functional Language for Real-Time Control" + ,journal "IEEE Software" + ,month January + ,volume 3 + ,number 1 + ,year 1986 + ,pages "70-71" + ) + +@inproceedings(aep86 + ,key = "Dannenberg" + ,author = "Dannenberg, Roger B." + ,title = "Workstations for Computer Music at Carnegie Mellon" + ,pages = "109 - 117" + ,volume = "II" + ,booktitle = "1986 University AEP Conference" + ,editor = "F. Dwyer" + ,year = "1986" + ,organization = "IBM Academic Information Systems" + ,address = "472 Wheelers Farms Road, Milford, Connecticut 06460" + ) + +@inproceedings(cmt + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "The CMU MIDI Toolkit" + ,booktitle = "Proceedings of the 1986 + International Computer Music Conference" + ,year = "1986" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "53-56" + ) + +@inproceedings(musicrep + ,key = "Dannenberg" + ,author = "Dannenberg, R. B." + ,title = "A Structure for Representing, Displaying and Editing Music" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ,pages = "153-160" +) + +@manual(old-cmt-manual + ,key = "Dannenberg" + ,author "Dannenberg, R. B" + ,title "The CMU MIDI Toolkit" + ,year "1986" + ,publisher "Studio for Creative Inquiry, Carnegie Mellon University" + ) + +@manual(cmt-manual + ,key = "Dannenberg" + ,author "Dannenberg, R. B" + ,title "The CMU MIDI Toolkit" + ,year "1993" + ,publisher "School of Computer Science, Carnegie Mellon University" + ) + +@article(ArcticCMJ + ,key = "Dannenberg" + ,author = "Dannenberg, R. B., P. McAvinney, and D. Rubine" + ,title = "Arctic: A Functional Language for Real-Time Systems" + ,journal = "Computer Music Journal" + ,volume = "10" + ,number = "4" + ,month = "Winter" + ,year = "1986" + ,pages = "67-78" + ) + +@inproceedings(Dannenberg87 + ,key "Dannenberg" + ,title "Following an Improvisation in Real Time" + ,author "Dannenberg, R. B. and B. Mont-Reynaud" + ,booktitle "Proceedings of the 1987 International Computer Music + Conference" + ,editor "J. Beauchamp" + ,pages 241-248 + ,year 1987 + ,organization "International Computer Music Association" + ,address "San Francisco" + ) + +@inproceedings(ircamWorkbench + ,key "Dannenberg" + ,author "Dannenberg, Roger B." + ,title "Systemes pour Informatique Musicale a l'universite de + Carnegie Mellon" + ,editor "J.-B. Barriere, F. Armand, and C. Marquet" + ,booktitle "Actes du Symposium + Systemes Personnels et Informatique Musicale" + ,year 1987 + ,organization "IRCAM, Paris, France" + ) + +@article(JASA87 + ,key Dannenberg + ,author "Dannenberg, Roger B., Serra, Marie-Helen, Rubine, Dean" + ,title "Comprehensive study of analysis and synthesis of tones + by spectral interpolation" + ,journal "Journal of the Acoustical Society of America" + ,volume "Supplement 1, Vol 82" + ,month Fall + ,year 1987 + ,pages S69 + ) + +@inbook(workbench + ,key "Dannenberg" + ,author "Dannenberg, Roger B." + ,title "A Project in Computer Music: The Musician's Workbench" + ,address "Oxford, England" + ,pages "354-388" + ,booktitle "From Information to Knowledge" + ,publisher "Intellect Books, Publications from the Society of Conceptual and Content Analysis by Computer (SCCAC)" + ,year 1994. + ,editor "Ephraim Nissan and Klaus M. Schmidt" + ) + + +@inproceedings(Dannenberg88a + ,key "Dannenberg" + ,title "New Techniques for Enhanced Quality of Computer Accompaniment" + ,author "Dannenberg, R. B. and H. Mukaino" + ,booktitle = "Proceedings of the 14th International Computer Music Conference" + ,editor "C. Lischka and J. Fritsch" + ,year = "1988" + ,pages "243-249" + ,organization = "International Computer Music Association" + ,address "San Francisco" +) + +@inproceedings(animation89 + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Real Time Control For Interactive Computer Music and + Animation" + ,booktitle "The Arts and Technology II: A Symposium" + ,editor "N. Zahler" + ,address "New London, Conn." + ,organization "Connecticut College" + ,pages "85-94" + ,year 1989 + ) + +@inproceedings(realtime91 + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Software Support for Interactive Multimedia Performance" + ,booktitle "Proceedings of The Arts and Technology 3" + ,editor "D. Smalley, N. Zahler, and C. Luce" + ,organization "Connecticut College" + ,address "New London, Conn." + ,pages "85-94" + ,year 1991 + ) + +@article(animationInterface + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Software Support for Interactive Multimedia Performance" + ,journal "Interface Journal of New Music Research" + ,pages "213-228" + ,month August + ,Volume 22 + ,Number 3 + ,year 1993 + ) + + +@inbook(klangart + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Computerbegleitung und Musikverstehen" + ,booktitle "Neue Musiktechnologie" + ,editor "B. Enders" + ,pages "241-252" + ,publisher "Schott" + ,year "1993" + ,address "Mainz" + ) + +@inbook(dannenberg91 + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Recent work in real-time music understanding by computer" + ,booktitle "Music, Language, Speech and Brain" + ,series "Wenner-Gren International Symposium Series, Vol. 59" + ,year 1991 + ,editor "J. Sundberg, L. Nord, and R. Carlson" + ,pages "194-202" + ,publisher "Macmillan" + ,address "London" + ) + +@inproceedings(cmt-technique + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Software Techniques for Interactive Performance Systems" + ,booktitle "International Workshop on Man-Machine Interaction in +Live Performance" + ,editor "L. Tarabella" + ,address "Pisa" + ,organization "Scuola di Stude Superiori Universitari e di +Perfezionamento" + ,year "to appear") + + +@inproceedings(conducting + ,key "Dannenberg" + ,title "Practical Aspects of a MIDI Conducting Program" + ,author "Dannenberg, R. B. and K. Bookstein" + ,booktitle = "ICMC Montreal 1991 Proceedings" + ,year = "1991" + ,pages "537-540" + ,editor "B. Alphonse and B. Pennycook" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ) + +@inproceedings(resource-instance + ,key "Dannenberg" + ,title "The Resource-Instance Model of Music Representation" + ,author "Dannenberg, R. B., D. Rubine, T. Neuendorffer" + ,booktitle = "ICMC Montreal 1991 Proceedings" + ,year = "1991" + ,pages "428-432" + ,editor "B. Alphonse and B. Pennycook" + ,organization = "International Computer Music Association" + ,address "San Francisco" +) + + +@article(CanonCMJ + ,key = "Dannenberg" + ,author = "Dannenberg, R. B." + ,title = "The Canon Score Language" + ,journal = "Computer Music Journal" + ,volume = "13" + ,number = "1" + ,month = "Spring" + ,year = "1989" + ,pages = "47-56" + ) + +@inbook(schedulers + ,key "Dannenberg" + ,title "Real-Time Scheduling and Computer Accompaniment" + ,author "Dannenberg, Roger B." + ,booktitle "Current Directions in Computer Music Research" + ,pages "225-262" + ,series "System Development Foundation Benchmark Series" + ,editor "Mathews, M. V. and J. R. Pierce" + ,year 1989 + ,publisher "MIT Press" + ) + +@inbook(jdbC + ,key "Dannenberg" + ,title "@i(Jimmy Durante Boulevard)" + ,author "Dannenberg, Roger B." + ,booktitle "@r(Compact Disc accompanying) Current Directions in Computer Music Research" + ,series "System Development Foundation Benchmark Series" + ,editor "Mathews, M. V. and J. R. Pierce" + ,year 1989 + ,publisher "MIT Press" + ) + +@inproceedings(ICMCFugue + ,key "Dannenberg" + ,author "Dannenberg, R. B. and C. L. Fraley" + ,title "Fugue: Composition and Sound Synthesis With Lazy Evaluation + and Behavioral Abstraction" + ,booktitle = "Proceedings of the 1989 + International Computer Music Conference" + ,editor "T. Wells and D. Butler" + ,year = "1989" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "76-79" + ) + +@inproceedings(musrepissues + ,key "Dannenberg" + ,author "Dannenberg, Roger B." + ,title "Music Representation Issues: A Position Paper" + ,booktitle = "Proceedings of the 1989 + International Computer Music Conference" + ,year = "1989" + ,editor "T. Wells and D. Butler" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "73-75" + ) + +@inbook(musun89 + ,key Dannenberg + ,author "Dannenberg, Roger B." + ,title "Music Understanding" + ,booktitle "Computer Science Research Review 1987/1988" + ,publisher "Carnegie Mellon School of Computer Science" + ,editor "C. Copetas" + ,address "Pittsburgh, PA 15213, USA" + ,year 1989 + ,pages 19-28 + ) + + +@inproceedings(uist89 + ,key "Dannenberg" + ,author "Dannenberg, Roger B. and D. Amon" + ,title "A Gesture Based User Interface Prototyping System" + ,booktitle "Proceedings of the ACM SIGGRAPH Symposium on User Interface Software and + Technology" + ,year 1989 + ,address "New York" + ,pages "127-132" + ,organization "ACM" + ) + +@inproceedings(icmcmusrep + ,key "Dannenberg" + ,author "Dannenberg, R." + ,title "A Structure for Representing, Displaying, and Editing Music" + ,pages "153-160" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ) + +@article(spemusrep + ,key "Dannenberg" + ,author "Dannenberg, Roger B." + ,title "A Structure for Efficient Update, Incremental Redisplay and + Undo in Display-Oriented Editors" + ,journal "Software: Practice and Experience" + ,year 1990 + ,volume 20 + ,number 2 + ,month February + ,pages "109-132" + ) + +@article(tpl + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Extending Music Notation Through Programming" + ,journal "Contemporary Music Review" + ,year "to appear" + ) + +@article(ptinterface + ,key "Dannenberg" + ,author "Dannenberg, R. B., M. Sanchez, A. Joseph, P. Capell, R. Joseph, and R. Saul" + ,title "A Computer-Based Multi-Media Tutor for Beginning Piano + Students" + ,journal "Interface" + ,volume 19 + ,number "2-3" + ,pages "155-73" + ,year 1990 + ) + +@inproceedings(icmcptutor + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "An Expert System for Teaching Piano to Novices" + ,booktitle = "ICMC Glasgow 1990 Proceedings" + ,year = "1990" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "20-23" + ,editor "S. Arnold and G. Hair" + ) + +@inbook(accompvideo + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Computer Accompaniment and Following an Improvisation" + ,booktitle "The ICMA Video Review" + ,year "1991" + ,publisher "International Computer Music Association" + ,address "San Francisco" + ,volume 1 + ,note "(Video)" + ) + +@incollection(bash + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Expressing Temporal Behavior Declaratively" + ,booktitle "CMU Computer Science: a 25th Anniversary Commemorative", + ,year 1991 + ,publisher "Addison Wesley" + ,pages "47-68" + ) + +@inproceedings(nyquist + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "Real-Time Software Synthesis on Superscalar Architectures" + ,booktitle = "Proceedings of the 1992 ICMC" + ,year = "1992" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "174-177" + ) + +@article(IEEEFugue + ,key "Dannenberg" + ,author "Dannenberg, R. B., C. L. Fraley, and P. Velikonja" + ,title "Fugue: A Functional Language for Sound Synthesis" + ,journal "Computer" + ,month "July" + ,year "1991" + ,volume 24 + ,number 7 + ,pages "36-42" + ) + +@inbook(fuguechap + ,key "Dannenberg" + ,author "Dannenberg, R. B., C. L. Fraley, and P. Velikonja" + ,title "A Functional Language for Sound Synthesis with Behavioral Abstraction and Lazy Evaluation" + ,editors "Denis Baggi" + ,booktitle "Readings in Computer-Generated Music" + ,publisher "IEEE Computer Society Press" + ,address "Los Alamitos, CA" + ,year 1992 + ) + +@inbook(ptdialog + ,title "Human-Computer Interaction in the Piano Tutor" + ,author "Dannenberg, R. B. and R. L. Joseph" + ,pages "65-78" + ,key "Dannenberg" + ,editors "Blattner, M. M. and R. B. Dannenberg" + ,booktitle "Multimedia Interface Design" + ,publisher "ACM Press" + ,year 1992 +) + +@inproceedings(PianoTutor93 + ,key "Dannenberg" + ,author "Dannenberg, R. B., M. Sanchez, A. Joseph, R. Joseph, R. Saul, and P. Capell" + ,title "Results from the Piano Tutor Project" + ,booktitle "The Fourth Biennial Arts and Technology Symposium" + ,editor "D. Smalley, N. Zahler, and P. Galvani" + ,organization "Connecticut College" + ,address "New London, Conn." + ,pages "143-150" + ,year 1993 + ) + +@inproceedings(nyquist93 + ,key "Dannenberg" + ,author "Dannenberg, R. B." + ,title "The Implementation of Nyquist, A Sound Synthesis Language" + ,booktitle = "Proceedings of the 1993 ICMC" + ,year = "1993" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "168-171" + ) + +@inproceedings(realtimemusic + ,key "Dannenberg" + ,author "Dannenberg, R. B., and D. Jameson" + ,title "Real-Time Issues in Computer Music" + ,booktitle = "Proceedings of the Real-Time Systems Symposium" + ,year = "1993" + ,organization = "IEEE Computer Society" + ,pages "258-261" + ) + + +@inbook(CMUResearch + ,key "Dannenberg" + ,author "Dannenberg, R." + ,title "Computer Music at Carnegie Mellon University" + ,year 1993 + ,booktitle "Music Processing" + ,pages "303-333" + ,publisher "AR Editions" + ,address "Madison" + ) + +@techreport(machmediatr + ,key "Dannenberg" + ,author "Roger B. Dannenberg, David B. Anderson, Tom Neuendorffer, Dean Rubine, Jim Zelenka" + ,Title " Performance Measurements of the Multimedia Testbed on Mach 3.0: Experience Writing Real-Time Device Drivers, Servers, and Applications" + ,Number "CMU-CS-93-205" + ,Date "July 1993" + ,Institution "School of Computer Science, Carnegie Mellon University" + ) + + +@book(date + ,key "Date" + ,author "Date, C. J." + ,title "An Introduction to Database Systems" + ,publisher "Addison-Wesley" + ,address "Reading, Mass." + ,edition "5th ed." + ,year 1991 + ) + +@inproceedings(Decker + ,key "Decker" + ,author "Decker, S. and G. Kendall" + ,Organization = "International Computer Music Association" + ,year = "1984" + ,title = "A Modular Approach to Sound Synthesis Software" + ,booktitle = "Proceedings of the International Computer Music Conference 1984" + ,editor = "W. Buxton" + ,pages "243-250" + ) + + +@article(Dennis80 + ,key "Dennis" + ,author "Dennis, Jack B." + ,title "Data flow supercomputers" + ,journal "Computer" + ,volume 13 + ,number 11 + ,month "November" + ,year "1980" + ,pages "48-56" + ) + +@inproceedings(streams + ,key "Dennis" + ,author "Dennis, Jack B. and Weng, Ken K.-S." + ,title "An Abstract Implementation For Concurrent Computation With Streams" + ,organization "IEEE Computer Society" + ,year "1979" + ,booktitle "Proceedings of the 1979 International Conference on Parallel Processing" + ) + + +@book(depoli + ,key "DePoli" + ,title "Representations of Musical Signals" + ,editor "G. De Poli, A. Piccialli, and C. Roads" + ,publisher "MIT Press" + ,address "Cambridge, Mass." + ,year 1991 + ) + +@inproceedings(DesainGraphics + ,key "Desain" + ,author "Desain, P." + ,title "Graphical Programming in Computer Music, a Proposal" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ,pages = "161-166" + ) + +@article(desain89 + ,key "Desain" + ,author "Desain, Peter and Henkjan Honing" + ,title "Quantization of Musical Time: a connectionist approach" + ,journal "Computer Music Journal" + ,year 1989 + ,pages="56-66" + ,volume=13 + ,number=3 + ) + +@inproceedings(DesainTempo + ,key "Desain" + ,author "Desain, P. and H. Honing" + ,title "Tempo Curves Considered Harmful" + ,booktitle = "ICMC Montreal 1991 Proceedings" + ,year = "1991" + ,pages "143-149" + ,editor "B. Alphonce and B. Pennycook" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ) + +@inbook(DesainTempoChapter + ,key "Desain" + ,author "Desain, P. and H. Honing" + ,title "Tempo Curves Considered Harmful" + ,year 1992 + ,booktitle "Music, Mind, and Machine: Studies in Computer Music, Music Cognition, and Artificial Intelligence" + ,pages 25-40 + ,publisher "Thesis Publishers" + ,address "Amsterdam" + ) + +@techreport(DesainStructure + ,key "Desain" + ,author "Desain, P. and H. Honing" + ,title "Towards a calculus for expressive timing in music" + ,year = "1991" + ,institution = "Center for Knowledge Technology" + ,address = "Utrecht" + ) + +@article(timefunctions + ,key "Desain" + ,author "Desain, P. and H. Honing" + ,title "Time Functions Function Best as Functions of Multiple Times" + ,Journal = "Computer Music Journal" + ,Year = "1992" + ,Month = "Summer" + ,Number = "2" + ,Pages = "17-34" + ,Volume = "16") + + +@book(ada + ,key "DOD" + ,title "The Programming Language Ada Reference Manual" + ,author "American National Standards Institute, Inc." + ,publisher "Springer-Verlag" + ,volume 155 + ,series "Lecture Notes in Computer Science" + ,year 1983) + +@inproceedings(Donner + ,key "Donner" + ,author "Donner, Marc" + ,title "The Design of OWL - A Language for Walking" + ,organization "Sigplan" + ,booktitle "Sigplan Symposium on Prog. Lang. Issues In Software Systems" + ,year 1983 + ) + +@inproceedings(gist + ,key "Eckel" + ,author "Eckel, G., M. R. Iturbide" + ,title "The Development of GiST, a Granular Synthesis Toolkit Based on an Extension of the FOF Generator" + ,booktitle "Proceedings of the 1995 International Computer Music Conference" + ,publisher "International Computer Music Association" + ,year 1995 + ,pages "296-302" + ) + + +@manual(BarsAndPipes + ,key "Fey" + ,author "Fey, T. and M. J. Grey" + ,title "Using Bars and Pipes" + ,publisher "Blue Ribbon Bakery" + ,address "Decatur, Georgia" + ,year 1989 + ) + +@book(Field, + key = Field + ,Author = "Field, A. J., and P. G. Harrison" + ,Title = "Functional Programming" + ,publisher = "Addison-Wesley" + ,year 1988 + ) + +@book(Foerster + ,title = "Music By Computers" + ,year = "1969" + ,key = "Foerster" + ,editors = "Foerster, H. V., and J. W. Beauchamp" + ,publisher "John Wiley & Sons, Inc." + ) + +@article(Foster, + key = "Foster", + ,Author = "Foster, Scott, Schloss, W. Andrew, and Rockmore, A. Joseph" + ,Journal = "Computer Music Journal" + ,Title = "Toward an Intelligent Editor of Digital Audio: Signal + Processing Methods" + ,Year = "1982" + ,Month = "Spring" + ,Number = "1" + ,Pages = "42-51" + ,Volume = "6") + +@inproceedings(htm + ,key = "Freed" + ,author = "Freed, A." + ,title = "Codevelopment of User Interface, Control, and Digital Signal Processing with the HTM Environment" + ,booktitle = "Proceedings of the International Conference on Signal Processing Applications and Technology" + ,year 1994 + ) + +@inproceedings(Gibbs + ,key "Gibbs" + ,author "Gibbs, S." + ,title "Composite Multimedia and Active Objects" + ,organization "ACM/SIGPLAN" + ,booktitle "OOPSLA '91 Conference Proceedings" + ,pages "97-112" + ,year 1991 + ,publisher "ACM Press" + ,address "New York" + ,editor "A. Paepcke" +) + +@article(Glass + ,key "Glass" + ,author "Glass, Robert L." + ,title "Real-Time: The ``Lost World'' Of Software Debugging and Testing" + ,journal "Communications of the ACM" + ,volume 23 + ,number 5 + ,month "May" + ,year 1980 + ,pages "264-271" + ) + +@book(Smalltalk + ,key "Goldberg" + ,author "Goldberg, A. and D. Robson" + ,title "Smalltalk-80: the language and its implementation." + ,publisher "Addison-Wesley" + ,year 1983 + ) + +@inproceedings(Greenberg + ,key "Greenberg" + ,author "Greenberg, Gary" + ,title "Procedural Composition" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 1987 International Computer Music Conference" + ,editor "J. Beauchamp" + ,year 1987 + ,pages "25-32" + ) + +@inproceedings(Greenberg88 + ,key "Greenberg" + ,author "Greenberg, Gary" + ,title "Composing With Performer Objects" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 14th International Computer Music Conference" + ,editor "C. Lischka and J. Fritsch" + ,year 1988 + ,pages "142-149" + ) + +@phdthesis(Greytimbre + ,key "Grey" + ,author "Grey, J. M." + ,year 1975 + ,title "An Exploration of Musical Timbre" + ,school "Department of Psychology, Stanford University" + ,note "Department of Music Report STAN-M-2" + ) + +@inproceedings(Gross + ,key "Gross" + ,author "Gross, Dorothy" + ,Organization = "International Computer Music Association" + ,year = "1984" + ,title = "An Intelligent Ear-Training Lesson" + ,booktitle = "Proceedings of the International Computer Music Conference 1984" + ,editor = "W. Buxton" + ,pages "179-183" + ) + +@InProceedings(sonar, + key = "Haflich", + Author = "Haflich, Steven M. and Burns, Mark A.", + Organization = "International Computer Music Association", + year = "1983", + title = "Following a Conductor: The Engineering of an Input Device", + booktitle = "1983 International Computer Music Conference Proceedings") + +@article(Hagerman80 + ,key="Hagerman" + ,author="Hagerman, B. and Sundberg, J." + ,title="Fundamental Frequency Adjustment in Barbershop Singing" + ,journal="Speech Transmission Laboratory Quarterly Progress and Status Report" + ,year="1980" + ,month="April" + ,number="STL-QPSR 1/1980" + ) + +@manual(hamel + ,key Hamel + ,author "Hamel, K." + ,title "MusScribe Reference Manual" + ,year 1988 + ,organization "SoftCore Music Systems" + ,address "Richmond, BC, Canada" + ) + +@inproceedings(PATCHMIX + ,key = "Helmuth" + ,author = "Helmuth, M." + ,title = "PATCHMIX: A C++ X Graphical Interface to Cmix" + ,booktitle = "Proceedings of the 1990 International Computer Music Conference" + ,pages = "273-275" + ,publisher = "Computer Music Association" + ,year 1990 + ) + + +@inproceedings (HILD92, + key = "Hild", + author = "Hild, Hermann and Feulner, Johannes and Menzel, Wolfgang", + title = "HARMONET: A Neural Net for Harmonizing Chorales in the Style of J.S.Bach", + booktitle = "Advances in Neural Network Information Processing Systems (NIPS-4-)", + year = "1992", + editor = "Moody, J.E. and Hanson, S.J. and Lippmann,R.P.", + publisher = "Morgan Kaufmann" +) + +@book(Hiller59 + ,key "Hiller" + ,author "Hiller, L. and Isaacson, L." + ,title "Experimental Music: Composition with an Electronic + Computer" + ,publisher "McGraw Hill" + ,year 1959 + ,address "New York, N. Y." + ) + +@article(Hiller58 + ,key "Hiller" + ,author "Hiller, L. and Isaacson, L." + ,title "Musical composition with a high-speed digital computer" + ,journal "Journal of the Audio Engineering Society" + ,volume 6 + ,number 3 + ,month July + ,year 1958 + ,pages 154-160 + ) + +@book(Hindemith42 + ,key="Hindemith" + ,author="Hindemith, P." + ,title="Craft of Musical Composition, Book 1, Theoretical Part" + ,publisher="Schott" + ,year="1942" + ) + +@article(monitor + ,key "Hoare" + ,author "Hoare, C. A. R." + ,title "Monitors: An Operating System Structuring Concept" + ,journal "Communications of the ACM" + ,volume 17 + ,number 10 + ,pages "549-557" + ,month "October" + ,year "1974" + ,note "Erratum in @i(Communications of the ACM), 18(2) (Feb. 1975), p95" + ) + +@article(csp + ,key "Hoare" + ,author "Hoare, C. A. R." + ,title "Communicating Sequential Processes" + ,journal "Communications of the ACM" + ,volume 21 + ,number 8 + ,pages "666-677" + ,month "August" + ,year "1978" + ) + +@book(hofstetter + ,key "Hofstetter" + ,author "Hofstetter, F. T." + ,title "Computer Literacy for Musicians" + ,publisher "Prentice Hall" + ,address "Englewood Cliffs, NJ" + ,year 1988 +) + +@article(CPR + ,key "Hon" + ,author "Hon, D." + ,journal "Byte Magazine" + ,volume 7 + ,number 6 + ,title "Interactive Training in Cardiopulmonary Resuscitation" + ,month June + ,year 1982 + ) + +@inbook(honing90 + ,key "Honing" + ,author "Honing, H." + ,title "Issues in the Representation of Time and Structure in Music" + ,year 1992 + ,booktitle "Music, Mind, and Machine: Studies in Computer Music, Music Cognition, and Artificial Intelligence" + ,pages 25-40 + ,publisher "Thesis Publishers" + ,address "Amsterdam" + ,note "Also in Proceedings of the 1990 Music and the Cognitive Sciences Conference, Harwood Academic Publishers GmbH, 1992" + ) + +@book(horowitz + ,key "Horowitz" + ,author "Horowitz, E. and S. Sahni" + ,title "Fundamentals of Data Structures in Pascal" + ,publisher "Computer Science Press" + ,year 1976 +) + +@book(MIDISPEC + ,key = IMA + ,author "IMA" + ,title = "MIDI 1.0 Detailed Specification" + ,publisher "International MIDI Association" + ,address "Los Angeles, CA" + ,year 1989 + ) + +@book(APL + ,key "Ivers" + ,author "Iverson, K." + ,title "A Programming Language" + ,year 1962 + ,address "New York" + ,publisher "Wiley" + ) + +@article(Jaffe + , key "Jaffe" + ,author "Jaffe, David" + ,title "Ensemble Timing in Computer Music" + ,journal "Computer Music Journal" + ,pages "38-48" + ,volume 9, number 4 + ,year 1985 + ) + +@article(SoundKit, key "Jaffe" + ,author "Jaffe, D., and L. Boynton" + ,title "An Overview of the Sound and Music Kit for the NeXT Computer" + ,journal "Computer Music Journal" + ,pages "48-55" + ,volume 13, number 2 + ,year 1989 + ) + +@techreport(seqnet + ,key "Jordan" + ,author "Jordan, M. I." + ,title "Serial Order: A Parallel Distributed Processing Approach" + ,institution "Institute for Cognitive Science, UCSD" + ,year 1986 + ,number "8604" + ) + +@techreport(Actors + ,key "Kahn" + ,author "Kahn, K." + ,title "DIRECTOR Guide" + ,institution "MIT" + ,year 1979 + ,month "December" + ,number "MIT AI Laboratory Memo 482B" + ) + +@inproceedings(Katayose89 + ,key "Katayose" + ,author "Katayose, H., H. Kato, M. Imai, and S. Inokuchi" + ,title "An Approach to an Artificial Music Expert" + ,booktitle = "Proceedings of the 1989 + International Computer Music Conference" + ,editor "T. Wells and D. Butler" + ,year = "1989" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "139-146" + ) + +@book(knuth + ,key "Knuth" + ,author "Knuth, D." + ,title "The Art of Computer Programming" + ,volume 1 + ,publisher "Addison Wesley" + ,year 1975 + ) + +@article(ntp + ,key "Kolstad" + ,author "Kolstad, R." + ,title "The Network Time Protocol" + ,journal "UNIX Review" + ,volume 8 + ,pages "58-61" + ,month "December" + ,year 1990 + ) + +@article(cmjlisp + ,key "Kornfeld" + ,author "Kornfeld, W." + ,title "Machine Tongues VII: LISP" + ,journal "Computer Music Journal" + ,pages "6-12" + ,volume 4 + ,number 2 + ,year 1980 + ,month "Summer" + ) + +@book(Kernighan + ,key = "Kernighan" + ,author = "Kernighan, Brian M. and Richie, Dennis M." + ,title = "The C Programming Language" + ,publisher "Prentice-Hall" + ,address "Englewood Cliffs" + ,year = 1978 + ) + +@manual(krakowsky86 + ,key "krakowsky" + ,author "Krakowsky, Philippe, ed." + ,title "Object LOGO Reference Manual" + ,address "Cambridge Massachusetts" + ,year 1986 + ,organization "Coral Software" + ) + +@article(krumhanslReview + ,key "Krumhansl" + ,author "Krumhansl, C. L." + ,title "Music Psychology: Tonal Structures in Perception and Memory" + ,journal "Annual Review of Psychology" + ,year 1991 + ,publisher "Annual Reviews Inc." + ,pages "277-303" + ) + +@book(Cmix + ,key "Lansky" + ,author "Lansky, P." + ,title "CMIX" + ,year 1987 + ,publisher "Princeton Univ." + ) + +@article(lansky + ,key "Lansky" + ,author "Lansky, P. and K. Steiglitz" + ,title "The synthesis of timbral families by warped linear prediction" + ,journal "Computer Music Journal" + ,volume 5 + ,number 3 + ,pages "45-49" + ,month "Fall" + ,year 1981 + ) + +@article(Levitt84 + ,key "Levitt" + ,author "Levitt, D." + ,title "Machine Tongues X: Constraint Languages" + ,journal "Computer Music Journal" + ,pages "9-21" + ,month Spring + ,year 1984 + ,volume 8 + ,number 1 + ) + +@article(little + ,key "Little" + ,author "Little, T. D. C. and A. Ghafoor" + ,title "Spatio-Temporal Composition of Distributed Multimedia Objects for Value-Added Networks" + ,journal "Computer" + ,pages "42-50" + ,month "October" + ,year 1991 + ) + +@article(dvi + ,key "Ripley" + ,author "Ripley, G. D." + ,title "DVI - A Digital Multimedia Technology" + ,journal "CACM" + ,number 7 + ,volume 32 + ,month "July" + ,year "1989" + ,pages "811-822" + ) + +@inbook(LewisInterview + ,key "Roads" + ,author "Roads, Curtis" + ,title "Improvisation With George Lewis" + ,booktitle "Composers and the Computer" + ,editor "Roads, Curtis" + ,publisher "William Kaufmann" + ,address "Los Altos, CA" + ,chapter "5" + ,year 1985 + ,pages "74-87" + ,series "The Computer Music and Digital Audio Series" + ) + +@inproceedings(Lifton85 + ,key "Lifton" + ,author "Lifton, J." + ,title "Some Technical and Aesthetic Considerations in Software for + Live Interactive Performance" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the International Computer Music Conference 1985" + ,editor "B. Truax" + ,year 1985 + ,pages "303-306" + ) + + +@inproceedings(Lischka + ,key "Lischka" + ,author "Lischka, C." + ,title "Connectionist Models of Musical Thinking" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 1987 International Computer Music Conference" + ,editor "J. Beauchamp" + ,year 1987 + ,pages "190-196" + ) + +@book(lincoln + ,title = "The Computer and Music" + ,year = "1970" + ,editor = "Lincoln, H. B." + ,key = "Lincoln" + ,publisher = "Cornell University Press" + ,address = "Ithaca, N.Y." + ) + +@article(IMWArchitecture + ,key "Lindemann" + ,author "Lindemann, E., F. Dechelle, B. Smith, and M. Starkier" + ,title "The Architecture of the IRCAM Musical Workstation" + ,journal "Computer Music Journal" + ,volume "15" + ,number "3" + ,month "Fall" + ,year "1991" + ,pages "41-49" + ) + +@inproceedings(logemann89 + ,key "Logemann" + ,year 1989 + ,title "Experiments With a Gestural Controller" + ,author "G. Logemann" + ,booktitle "Proceedings of the 1989 International Computer Music + Conference" + ,editor "T. Wells and D. Butler" + ,pages "184-185" + ,year 1989 + ,organization "International Computer Music Association" + ) + + +@article(longuet + ,key "Longuet-Higgins" + ,year 1982 + ,title "The Perception of Musical Rhythms" + ,author "Longuet-Higgins, H. C. and C. S. Lee" + ,journal "Perception" + ,volume 11 + ,pages "115-128" + ) + +@article(LH76, + author"Longuet-Higgins, H. C.", + title="Perception of Melodies", + journal="Nature", + pages="646-653", + volume=263, + year=1976) + +@article(LH78, + author="Longuet-Higgins, H. C.", + title="The Perception of Music", + journal="Interdisciplinary Science Reviews", + pages="148-156", + volume=3, + number=2, + year=1978 +) + + +@article(MIDI + ,key = "Loy" + ,author = "Loy, G." + ,title = "Musicians Make a Standard: The MIDI Phenomenon" + ,journal = "Computer Music Journal" + ,volume = "9" + ,number = "4" + ,month = "Winter" + ,year = "1985" + ,pages = "8-26" + ) + +@inproceedings(hyperinstruments + ,key "Machover" + ,author "Machover, T. and Chung, J." + ,title "Hyperinstruments: Musically Intelligent and Interactive +Performance and Creativity Systems" + ,booktitle "Proceedings of the 1989 International Computer Music + Conference" + ,editor "T. Wells and D. Butler" + ,pages "186-190" + ,year 1989 + ,organization "International Computer Music Association" + ) + +@inproceedings(martens + ,key "Martens" + ,author "Martens, W. L." + ,title "PALETTE: An Environment for developing an individualized set of psychophysically scaled timbres" + ,booktitle "Proceedings of the 1985 International Computer Music + Conference" + ,editor "B. Truax" + ,pages "355-365" + ,year 1985 + ,organization "International Computer Music Association" + ) + + +@inproceedings(sampling + ,key "Massie" + ,author "Massie, D. C." + ,title "The Emulator II Computer Music Environment" + ,booktitle "Proceedings of the 1985 International Computer Music + Conference" + ,editor "B. Truax" + ,pages "111-118" + ,year 1985 + ,organization "International Computer Music Association" + ) + +@Article(Mathews63 + ,key = "Mathews" + ,author = "Mathews, M. V." + ,title = "The Digital Computer as a Musical Instrument" + ,journal = "Science" + ,volume = "142" + ,pages = "553-557" + ,year = "1963" + ) + +@book(Music5 + ,key "Mathews" + ,author "Mathews, M. V." + ,title "The Technology of Computer Music" + ,publisher "MIT Press" + ,year 1969 + ,address "Boston" + ) + +@article(groove + ,key "Mathews" + ,author "Mathews, M. V. and F. Richard Moore" + ,title "A Program to Compose, Store, and Edit Functions of Time" + ,journal "Communications of the ACM" + ,year 1970 + ,month December + ,volume 13 + ,number 12 + ,pages "715-721" + ) + +@article(seqdrum, + key = "Mathews", + Author = "Mathews, M. V. and C. Abbot", + Journal = "Computer Music Journal", + Title = "The Sequential Drum", + Year = "1980", + Month = "Winter", + Number = "4", + Pages = "45-59", + Volume = "4") + +@book(MP + ,key "Mathews" + ,title "Current Directions in Computer Music Research" + ,series "System Development Foundation Benchmark Series" + ,editor "Mathews, M. V. and Pierce, J. R." + ,year 1989 + ,publisher "MIT Press" + ) + +@article(mockingbird + ,key "Maxwell" + ,author "Maxwell, J. T., and S. M. Ornstein" + ,title "Mockingbird: A Composer's Amanuensis" + ,journal "Byte" + ,volume 9 + ,number 1 + ,year 1984 + ,pages "384-401" + ) + + +@article(OCCAM + ,key "May" + ,author "May, David" + ,title "OCCAM" + ,journal "Sigplan Notices" + ,volume 18 + ,number 4 + ,month "April" + ,year 1983 + ,pages "69-79" + ) + +@manual(MidiManager + ,key "Apple" + ,author "Apple Computer, Inc." + ,title "MIDI Management Tools, Version 2.0" + ,organization "Apple Programmers and Developers Association" + ,year 1990 + ) + +@book(McCarthy + ,key "McCarthy" + ,author "McCarthy, J." + ,title "LISP 1.5 Programmer's Manual" + ,publisher "M.I.T. Press" + ,address "Cambridge, Mass" + ,year "1965" + ) + +@mastersthesis(Mecca + ,key "Mecca" + ,author "Michael T. Mecca" + ,title "Tempo Following Behavior in Musical Accompaniment" + ,School "Department of Logic and Philosophy, Carnegie Mellon University" + ,Year 1993 + ,address "Pittsburgh" +) + +@book(moorebook + ,key = "Moore" + ,author = "Moore, F. R." + ,title = "Elements of Computer Music" + ,year = "1990" + ,publisher = "Prentice Hall" + ,address = "New Jersey" + ) + +@article(moorer + ,key "Moorer" + ,author "Moorer, J. A." + ,title "Signal Processing Aspects of Computer Music - A Survey" + ,journal "Proceedings of the IEEE" + ,volume 65 + ,number 8 + ,pages "1108-1137" + ,year 1977 + ,month "July" + ,note "A revised and updated version is included in @i(Digital Audio Signal Processing: An Anthology), ed. by John Strawn, William +Kaufmann, Inc., 1985." + ) + +@article(Val + ,key "McGraw" + ,author "McGraw, James R." + ,title "The VAL Language: Description and Analysis" + ,journal "ACM Transactions on Programming Languages and Systems" + ,volume 4 + ,number 1 + ,month "January" + ,year 1982 + ,pages "44-82" + ) + +@article(Cmusic, + key = "Moore", + Author = "Moore, F. R.", + Journal = "Computer Music Journal", + Title = "The Computer Audio Research Laboratory at UCSD", + Year = "1982", + Number = "6", + Pages = "18-29", + Volume = "1") + + +@book(Cmusic90, + key = "Moore", + Author = "Moore, F. R.", + Title = "Elements of Computer Music", + Publisher = "Prentice-Hall", + Year = "1990") + + +@PhDThesis(Moorer75 + ,key = "Moorer" + ,Author = "Moorer, J. A." + ,Year = 1975 + ,School = "Stanford University Department of Computer Science" + ,Title = "On the Segmentation and Analysis of Continuous Musical Sounds + by Digital Computer" + ) + +@article(Andrew + ,key = "Morris" + ,author = "Morris, James H., et. al." + ,title = "Andrew: A Distributed Personal Computing Environment" + ,journal = "Communications of the ACM" + ,volume = "29" + ,number = "3" + ,month = "March" + ,year = "1986" + ,pages = "184-201" + ) + +@Article(GarnetComputer + Key="Myers", + Author="Brad A. Myers, et al.", + Title="Garnet: Comprehensive Support for Graphical, Highly Interactive User Interfaces", + Journal="IEEE Computer", + Volume=23, + number=11, + Month=Nov, + year=1990, + pages="71-85") + +@article(NelsonMPL + ,key Nelson + ,author "Nelson, G." + ,title "MPL: A Program Library for Musical Data Processing" + ,journal "Creative Computing" + ,pages "76-81" + ,year "1977" + ,month "Mar.-Apr." + ) + +@article(Hytime + ,key "Newcomb" + ,author "Newcomb, S. R., N. A. Kipp, and V. T. Newcomb" + ,title "The HYTIME Multimedia/time-based document structuring language" + ,journal "Communications of the ACM" + ,volume 34 + ,month "November" + ,year 1991 + ,pages "67-83" + ) + +@article(SMDL-Computer + ,key "Newcomb" + ,author "Newcomb, S. R." + ,title "Standard Music Description Language Complies With Hypermedia Standard" + ,journal "Computer" + ,volume 24 + ,number 7 + ,month "July" + ,year 1991 + ,pages "76-80" + ) + +@manual(framekit + ,key = "Nyberg" + ,author = "Nyberg, Eric H." + ,title = "The FRAMEKIT User's Guide Version 2.0" + ,organization = "Computer Science Department, Carnegie Mellon University" + ,year = 1988) + + +@inproceedings(oppenheimNotation + ,key "Oppenheim" + ,title "The P-G-G Environment For Music Composition: A Proposal" + ,author "Oppenheim, D. V." + ,booktitle "Proceedings of the 1987 International Computer Music + Conference" + ,editor "J. Beauchamp" + ,pages 40-48 + ,year 1987 + ,organization "International Computer Music Association" + ,address "San Francisco" + ) + +@inproceedings(MLOGO + ,key "Orlarey" + ,author "Orlarey, Y." + ,title "MLOGO: A MIDI Composing Environment" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ,pages = "211-213" + ) + +@inproceedings(midishare + ,key "Orlarey" + ,author "Orlarey, Y., H. Lequay" + ,title "MidiShare, A Real Time Multi-tasks Software Module for Midi Applications" + ,booktitle "Proceedings of the 1989 International Computer Music + Conference" + ,editor "T. Wells and D. Butler" + ,pages "234-237" + ,year 1989 + ,organization "International Computer Music Association" + ) + + +@inproceedings(ATK + ,key "Palay" + ,author "Palay, A. J., F. Hansen, M. Kazar, M. Sherman, M. Wadlow, T. +Neuendorffer, Z. Stern, M. Bader, T. Peters" + ,title "The Andrew Toolkit - An Overview" + ,booktitle "Proceedings USENIX Technical Conference" + ,month "Winter" + ,year 1988 + ,pages "9-21" + ,organization "USENIX" +) + + + +@article(palmer + ,key "Palmer" + ,author "Palmer, C." + ,title "Mapping Musical Thought to Musical Performance" + ,journal "Journal of Experimental Psychology" + ,volume 15 + ,number 12 + ,month "Dec" + ,year 1989 + ) + + +@inproceedings(fminverse + ,key "Payne" + ,author "Payne, R. G." + ,title "A Microcomputer Based Analysis/Resynthesis Scheme +for Processing Sampled Sounds Using FM" + ,organization "Computer Music Association" + ,booktitle "Proceedings of the 1987 International Computer Music Conference" + ,year 1987 + ,pages "282-289" + ) + + +@book(Papoulis + ,key "Papoulis" + ,author "Papoulis, Athanasios" + ,title "The Fourier Integral And Its Applications" + ,year 1962 + ,publisher "McGraw-Hill" + ,address "New York" + ) + + +@article(HMSL + ,key "Polansky" + ,author "Polansky, L., P. Burk, and D. Rosenboom" + ,title "HMSL (Hierarchical Music Specification Language): A Theoretical Overview" + ,journal "Perspectives of New Music" + ,year 1990 + ,volume 28 + ,number 2 + ,month summer + ,pages "136-179" + ) + +@book(OOPBook + ,key "Pope" + ,author "Pope, S. T., editor" + ,title "The Well-Tempered Object: Musical Applications of Object-Oriented Software Technology" + ,address "Boston" + ,publisher "MIT Press" + ,year "1991" +) + +@inbook(Mode + ,author "Pope, S. T." + ,key "Pope" + ,title "Introduction to MODE: The Musical Object Development Environment" + ,booktitle "The Well-Tempered Object: Musical Applications of Object-Oriented Software Technology" + ,editor "S. T. Pope" + ,address "Boston" + ,publisher "MIT Press" + ,pages "83-106" + ,year "1991" +) + +@article(cmj-software-synthesis + ,author "Pope, S. T." + ,key "Pope" + ,title "Machine Tongues XV: Three Packages for Software Sound Synthesis" + ,journal "Computer Music Journal" + ,Volume 17 + ,Number 2 + ,Month "Summer" + ,Year "1993" + ,Pages "23-54" + ) + +@book(Pratt + ,author "Pratt, Terrence W." + ,key "Pratt" + ,title "Programming Languages: Design and Implementation" + ,year 1975 + ,publisher "Prentice-Hall" + ,address "Englewood Cliffs, N. J." + ) + +@inproceedings(MAXandX + ,key "Puckette" + ,author "Puckette, M." + ,title "Interprocess Communication and Timing in Real-time Computer Music Performance" + ,pages "43-46" + ,booktitle = "Proceedings of the International Computer Music Conference 1986" + ,editor "P. Berg" + ,year = "1986" + ,organization = "International Computer Music Association" + ) + + + +@inproceedings(Patcher + ,key "Puckette" + ,author "Puckette, M." + ,title "The Patcher" + ,booktitle "Proceedings of the 14th International Computer Music Conference" + ,editor "C. Lischka and J. Fritsch" + ,year 1988 + ,pages "420-429" + ,organization "International Computer Music Association" + ) + +@inproceedings(Explode + ,key "Puckette" + ,author "Puckette, M." + ,title "EXPLODE: a user interface for sequencing and score following" + ,booktitle "ICMC Glasgow 1990 Proceedings" + ,year = "1990" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "259-261" + ,editor "S. Arnold and G. Hair" + ) + +@manual(MaxManual + ,key = "Puckette" + ,author = "Puckette, M. and D. Zicarelli" + ,title = "MAX Development Package" + ,organization = "Opcode Systems, Inc." + ,year = 1991) + +@article(maxcmj + ,key "Puckette" + ,author "Puckette, M." + ,title "Combining Event and Signal Processing in the MAX +Graphical Programming Environment" , + ,journal "Computer Music Journal" + ,year 1991 + ,pages="68-77" + ,volume=15 + ,number=3 + ,month "Fall" + ) + + +@book(polson + ,key "Pohlmann" + ,author "Pohlmann, K. C." + ,title "The Compact Disc: a handbook of theory and use" + ,publisher "A-R Editions" + ,address "Madison, WI" + ,year 1992 +) + +@article(fts-cmj + ,key "Puckette" + ,author "M. Puckette" + ,title "FTS: A Real-Time Monitor for Multiprocessor Music Synthesis" + ,journal "Computer Music Journal" + ,year 1991 + ,volume 15 + ,number 3 + ,month "Fall" + ,pages "58-67" +) + + +@inproceedings(fts + ,key "Viara" + ,author "Viara, E., and M. Puckette" + ,title "A Real-Time Operating System for Computer Music" + ,year 1990 + ,booktitle "Proceedings of the 1990 +International Computer Music Conference" + ,pages "270-272" + ,organization "International Computer Music Association" + ) + +@inproceedings(reynaud85a + ,key "Reynaud" + ,title "Problem-solving Strategies in a Music Transcription System" + ,author "Mont-Reynaud, Bernard" + ,year 1985 + ,booktitle "IJCAI Proceedings" +) + +@inproceedings(reynaud85b, + ,key "Reynaud" + ,title "On Finding Rhythmic Patterns in Musical Lines" + ,author "Mont-Reynaud, Bernard and Mark Goldstein" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the International Computer Music Conference 1985" + ,editor "B. Truax" + ,year 1985 + ,pages "391-397" + ) + +@techreport(reynaud84 + ,key "Chowning" + ,author "Chowning, J., B. Mont-Reynaud, et. al." + ,title "An Intelligent System for the Analysis of Digitized Acoustic Signals" + ,institution "Stanford University" + ,year 1984 + ,number "STAN-M-15" + ) + +@inproceedings(Rogers + ,key "Rogers" + ,author "Rogers, J., J. Rockstroh, and P. Batstone" + ,title "Music-Time and Clock-Time Similarities Under Tempo Changes" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 1980 International Computer Music Conference" + ,year 1980 + ,pages "404-442" + ) + +@book(MIDIbook + ,key "Rothstein" + ,author "Rothstein, J." + ,title "MIDI: A Comprehensive Introduction" + ,publisher "A-R Editions" + ,address "Madison, WI" + ,year 1992 + ) + +@book(Rowe + ,key "Rowe" + ,author "Rowe, R." + ,title "Interactive Music Systems" + ,publisher "MIT Press" + ,year 1993 + ) + + +@inbook(ptvideo + ,key "Sanchez" + ,author "Sanchez, M., A. Joseph, R. B. Dannenberg, P. Capell, R. Saul, and R. Joseph" + ,title "The Piano Tutor" + ,series "ACM Siggraph Video Review" + ,year "1990" + ,publisher "ACM Siggraph" + ,address "c/o 1st Priority, Box 576, Itasca, IL 60143-0576" + ,booktitle " CHI '90 Technical Video Program - New Techniques" + ,volume "55" + ,note "(Video)" + ) + +@book(sankoff + ,key "Sankoff" + ,author "Sankoff, David and Joseph B. Kruskal, editors" + ,title "Time Warps, String Edits, and Macromolecules: + The Theory and Practice of Sequence Comparison." + ,publisher "Addison-Wesley" + ,address "Reading, Mass." + ,year 1983 + ) + +@article(KymaCMJ + ,key "Scaletti" + ,title "The Kyma/Platypus Computer Music Workstation" + ,author "Scaletti, C." + ,journal "Computer Music Journal" + ,volume 13 + ,number 2 + ,month "Summer" + ,year 1989 + ,pages "23-38" + ) + +@inproceedings(KymaOOPSLA + ,key "Scaletti" + ,title "An Interactive Graphic Environment for Object-Oriented +Music Composition and Sound Synthesis" + ,author "Scaletti, C., and E. Johnson" + ,booktitle "Proceedings of the 1988 Conference on Object-Oriented +Languages and Systems" + ,year 1988 + ,pages "18-26" + ,organization "ACM" + ) + +@inbook(Kyma + ,key "Scaletti" + ,author "Scaletti, C., and K. Hebel" + ,title "An Object-based Representation for Digital Audio Signals" + ,booktitle "Representations of Musical Signals" + ,editor "G. De Poli, A. Piccialli, and C. Roads" + ,publisher "MIT Press" + ,address "Cambridge, Mass." + ,year 1991 + ,pages "371-389" + ,chapter 11 + ) + +@inproceedings(scaletti92 + ,key "Scaletti" + ,author "Scaletti, C." + ,title "Polymorphic transformations in Kyma" + ,booktitle = "Proceedings of the 1992 ICMC" + ,year = "1992" + ,organization = "International Computer Music Association" + ,address "San Francisco" + ,pages "249-252" + ) + +@phdthesis(Schloss + ,key "Schloss" + ,author "Schloss, A." + ,title "On the Automatic Transcription of Percussive Music" + ,school "Department of Speech and Hearing, Stanford University" + ,year 1985 + ,note "Department of Music Technical Report STAN-M-27" + ,month June + ) + +@techreport(sisTR + ,key "Serra" + ,author "Serra, M., D. Rubine, R. B. Dannenberg" + ,title "A Comprehensive Study of the Analysis and Synthesis of + Tones by Spectral Interpolation" + ,institution "Carnegie Mellon" + ,number "CMU-CS-88-146" + ,year 1988 + ,month June + ) + +@inproceedings(sisicmc + ,key "Serra" + ,author "Serra, M., D. Rubine, R. B. Dannenberg" + ,title "The Analysis and Resynthesis of Tones via Spectral + Interpolation" + ,booktitle "Proceedings of the 14th International Computer Music + Conference" + ,editor "C. Lischka and J. Fritsch" + ,organization "International Computer Music Association" + ,year 1988 + ,pages "322-332" + ) + +@article(sisJAES + ,key Serra + ,author "Serra, M., D. Rubine, R. B. Dannenberg" + ,title "Analysis and Synthesis of Tones by Spectral Interpolation" + ,journal "Journal of the Audio Engineering Society" + ,year 1990 + ,volume 38 + ,number 3 + ,month March + ,year 1990 + ,pages 111-128 + ) + +@article(shepardspiral + ,key "Shepard" + ,author "Shepard, R. N." + ,title "Geometrical approximations to the structure of musical pitch" + ,journal "Psychological Review" + ,volume 89 + ,number 4 + ,year 1982 + ,pages "305-333" + ) + +@inbook(simon + ,key "Simon" + ,author "Simon, H. A. and Sumner, R. K." + ,title "Pattern in Music" + ,booktitle "Formal Representation of Human Judgment" + ,editor "B. Kleinmuntz" + ,address "New York" + ,publisher "Wiley" + ,year 1968 + ) + +@article(Auditeur + ,key "Simon" + ,author "Simon, H. A." + ,title "Perception du Pattern Musical par AUDITEUR" + ,Journal "Sciences de l'Art" + ,volume 2 + ,pages "28-34" + ,year 1968 + ) + +@book(slawson + ,key "Slawson" + ,author "Slawson, A. W." + ,title "Sound Color" + ,publisher "University of California Press" + ,address "Berkeley" + ,year 1985 + ) + +@book(Sleeman-brown + ,key = "Sleeman" + ,author = "Sleeman, D. and J. S. Brown (eds.)" + ,title = "Intelligent Tutoring Systems" + ,address = "New York" + ,publisher = "Academic Press" + ,year = 1982 + ) + +@inproceedings(smdl + ,key "Sloan" + ,author "D. Sloan" + ,title "Precis of the Standard Music Description Language" + ,organization "Computer Music Association" + ,booktitle "Proceedings of the 1989 International Computer Music Conference" + ,year 1989 + ,pages "296-302" + ) + +@inproceedings(arctic-runtime + ,key Dannenberg + ,author "Dannenberg, R. B." + ,title "A Run-time System for Arctic" + ,booktitle "ICMC Glasgow 1990 Proceedings" + ,organization "International Computer Music Association" + ,year 1990 + ,pages "185-187" + ) + + +@inproceedings(cmt-mexico + ,key Dannenberg + ,author "Dannenberg, R. B." + ,title "Recent Developments in the CMU MIDI Toolkit" + ,booktitle "Proceedings of the International Seminar + Ano 2000: Theoretical, Technological and Compositional + Alternatives" + ,organization "Universidad Nacional Autonoma de Mexico" + ,address "Mexico City" + ,editor "C. Sandoval" + ,year 1990 + ,pages "52-62" + ) + +@inproceedings(optimizingdsp + ,key "Thompson" + ,author "Thompson, N. and R. B. Dannenberg" + ,title "Optimizing Software Synthesis Performance" + ,booktitle "Proceedings of the 1995 International Computer Music Conference" + ,publisher "International Computer Music Association" + ,year 1995 + ,pages "235-6" + ) + +@inproceedings(W + ,key Dannenberg + ,author "Dannenberg, R. B. and D. Rubine" + ,title = "Toward Modular, Portable, Real-Time Software" + ,booktitle = "Proceedings of the 1995 International Computer Music Conference" + ,publisher "International Computer Music Association" + ,year 1995 + ,pages "65-72" + ) + + +@inproceedings(SampleRate + ,key Smith + ,author "Smith, Julius O. and Phil Gossett" + ,title "A Flexible Sampling-Rate Conversion Method" + ,booktitle "Proceedings of ICASSP, Vol. 2" + ,pages "19.4.1-19.4.4" + ,year 1984 + ) + +@inproceedings(Parshl + ,key "Smith" + ,author "Smith, Julius O. and Xavier Serra" + ,title "PARSHL: An Analysis/Synthesis Program for Non-Harmonic Sounds + Based on a Sinusoidal Representation" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 1987 International Computer Music + Conference" + ,editor "J. Beauchamp" + ,year 1987 + ,pages "290-297" + ) + +@inproceedings(Spiegel + ,key "Spiegel" + ,author "Spiegel, L." + ,title "Manipulations of Musical Patterns" + ,organization "IEEE Computer Society" + ,booktitle "Proceedings of the Symposium on Small Computers in the Arts" + ,year "1981" + ,pages "19-22" + ) + +@inproceedings(Taube + ,key "Taube" + ,author "Taube, H." + ,title "Common Music: A Compositional Language in Common Lisp and CLOS" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 1989 International Computer Music Conference" + ,editor "T. Wells and D. Butler" + ,year 1989 + ,pages "316-319" + ) + +@inproceedings(Vivace + ,key "Thomas" + ,author "Thomas, M. T." + ,title "Vivace: a rule based AI system for composition" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the International Computer Music Conference 1985" + ,editor "B. Truax" + ,year 1985 + ,pages "267-274" + ) + +@misc(Voice, + ,author "Thomas, Marilyn T. and Peter Monta" + ,key "Thomas" + ,title "MacVoice 1.0 User's Manual" + ,year "1986" + ,publisher "Kinko's Academic Courseware Exchange" + ,address "4141 State Street, Santa Barbara, CA 93110, (800) 235-6919" + ,note "published by Kinko's Academic Courseware Exchange" + ) + +@inproceedings(cantabile + ,key "Thomas" + ,author "Thomas, M. T., S. Chatterjee, Mark W. M." + ,title "Cantabile: A Rule-Based System For Composing Melody" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 1989 International Computer Music Conference" + ,editor "T. Wells and D. Butler" + ,year 1989 + ,pages "320-323" + ) + +@inproceedings(Animation + ,key "Reynolds" + ,author "Reynolds, C. U." + ,title "Computer Animation with Scripts and Actors" + ,organization "ACM" + ,booktitle "Proceedings of ACM SIGGRAPH Conference" + ,year 1982 + ,month "July" + ) + +@article(CMJAda + ,key "Roads" + ,author "Roads, C." + ,title "Machine Tongues VI: Ada" + ,journal "Compter Music Journal" + ,volume 3 + ,number 4 + ,month "Winter" + ,year 1980 + ,pages "6-8" + ) + +@inproceedings(Formes83 + ,key "Rodet" + ,author "Rodet, Xavier, Pierre Cointe, Jean-Baptiste Barriere, Yves Potard, B. Serpette, and J. J. Briot" + ,title "Applications and Developments of the FORMES programming environment" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 1983 International Computer Music Conference" + ,year 1983 + ) + +@article(Chant + ,key "Rodet" + ,author "Rodet, X., Y. Potard and Jean-Baptist Barriere" + ,journal "Computer Music Journal" + ,title "The CHANT Project: From Synthesis of the Singing Voice + to Synthesis in General" + ,year 1984 + ,volume 8 + ,number 3 + ,month "Fall" + ,pages "15-31" + ) + +@article(Formes84 + ,key "Rodet" + ,author "Rodet, X. and P. Cointe" + ,journal "Computer Music Journal" + ,title "FORMES: Composition and Scheduling of Processes" + ,year 1984 + ,volume 8 + ,number 3 + ,month "Fall" + ,pages "32-50" + ) + +@inproceedings(mercury + ,key "Rodet" + ,author "Rodet, Xavier and Gerhard Eckel" + ,year 1988 + ,title "Dynamic Patches: Implementation and Control in the + Sun-Mercury Workstation" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 14th International Computer Music + Conference" + ,editor "C. Lischka and J. Fritsch" + ,pages "82-89" + ) + +@phdthesis(rubenstein + ,key "Rubenstein" + ,author "Rubenstein, W. B." + ,year 1987 + ,Title "Data Management of Musical Information" + ,school "U. C. Berkeley" + ,note "Memorandom No. UCB/ERL M87/69" + ,month June + ) + +@techreport(arcticref + ,key "Rubine" + ,title "Arctic Programmer's Manual and Tutorial" + ,author "Rubine, D. and R. B. Dannenberg" + ,institution "Carnegie Mellon" + ,number "CMU-CS-87-110" + ,year 1987 + ) + +@inproceedings(videoharp + ,key "Rubine" + ,title "The VideoHarp" + ,author "Rubine, D. and P. McAvinney" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the 14th International Computer Music Conference" + ,year 1988 + ,pages "49-55" + ) + +@article(videoharpcmj + ,key "Rubine" + ,title "Programmable Finger-tracking Instrument Controllers" + ,author "Rubine, Dean and Paul McAvinney" + ,journal "Computer Music Journal" + ,year 1990 + ,month Spring + ,number 1 + ,volume 14 + ,pages "26-41" + ) + + +@phdthesis(rubinethesis + ,key "Rubine" + ,author "Rubine, D." + ,title "The Automatic Recognition of Gestures" + ,school "Carnegie Mellon University" + ,year 1991 + ) + +@incollection(rubine91c + ,key "Rubine" + ,author "Rubine, D." + ,title "Criteria for Gesture Recognition Technologies" + ,booktitle "Neural Networks and Pattern Recognition in Human +Computer Interaction" + ,publisher "Ellis Horwood" + ,address "Chichester, UK" + ,year "(to appear)" + ,editor "R. Beale and J. Finlay" + ) + +@inproceedings(rubine91b + ,key "Rubine" + ,author "Rubine, D." + ,title "Integrating Gesture Recognition and Direct Manipulation" + ,booktitle "Proceedings of the Summer 1991 Usenix Conference" + ,editor "C. Carr" + ,address "Berkeley, CA" + ,organization "USENIX Association" + ,year 1991 + ) + +@article(rubine91a + ,key "Rubine" + ,author "Rubine, D." + ,title "Specifying Gestures by Example" + ,journal "Computer Graphics" + ,volume 25 + ,number 4 + ,month July + ,year 1991 + ,note "(Proceedings of SIGGRAPH '91)" + ,organization "ACM SIGGRAPH" + ,address "New York" + ,pages "329-37" + ) + +@inCollection(Salamon + ,key "Salamon" + ,author "Salamon, F. P., Jr." + ,title "Real-Time Electronic Engine Control (EEC) Microprocessor Software Productivity" + ,booktitle "New Developments in Electronic Engine Management" + ,publisher "Society of Automotive Engineers" + ,address "400 Commonwealth Drive, Warrendale, PA 15096" + ,year 1984 + ,volume "SP-572" + ,pages "45-55" + ) + +@article(PianoTutor + ,author "Sanchez, Marta and Annabelle Joseph" + ,key "Sanchez" + ,journal "Accent on Research" + ,title "Piano Tutor" + ,year 1986 + ,month "Fall" + ,pages "7" + ,note "published by Carnegie Mellon University" + ) + +@article(scarborough89 + ,key "Scarborough" + ,author "Scarborough, D., B. O. Miller, and J. A. Jones" + ,title "Connectionist Models for Tonal Analysis" + ,journal "Computer Music Journal" + ,volume 13 + ,number 3 + ,month "Fall" + ,year 1989 + ,pages "49-55" + ) + +@article(marksweep + ,key "Schorr" + ,author "Schorr, H. and W. Waite" + ,year 1967 + ,title "An Efficient and Machine Independent Procedure for Garbage Collection in Various List Structures" + ,journal "Communications of the ACM" + ,volume 10 + ,number 8 + ,pages 501-506 + ) + +@article(PLA + ,key "Schottstaedt" + ,author "Schottstaedt, Bill" + ,title "Pla: A Composer's Idea of a Language" + ,journal "Computer Music Journal" + ,volume 7 + ,number 1 + ,month "Spring" + ,year 1983 + ,pages "11-20" + ) + +@article(Roads + ,key "Roads" + ,author "Roads, C." + ,title "Artificial Intelligence and Music" + ,journal "Computer Music Journal" + ,volume 4 + ,number 2 + ,year 1980 + ,month "Summer" + ,pages "13-25" + ) + +@techreport(nettalk + ,key = "Sejnowski" + ,Author = "Sejnowski, T. J. and C. R. Rosenberg" + ,Journal = "Complex Systems" + ,Title = "NETtalk: AParallel Network that Learns to Read Aloud" + ,Institution "Johns Hopkins University" + ,number "JHU/EECS-86/01" + ,Year = "1986" + ) + +@Article(snell, + key = "Snell", + Author = "Snell, John", + Journal = "Computer Music Journal", + Title = "The Lucasfilm Real-Time Console for Recording Studios and + Performance of Computer Music", + Year = "1982", + Month = "Fall", + Number = "3", + Pages = "33-45", + Volume = "6") + +@book(steele + ,key "Steele" + ,author "Steele, Guy L., Jr." + ,title "Common Lisp" + ,publisher "Digital Press" + ,year "1984") + +@article(stevens + ,key "Stevens" + ,author "Stevens, S. M." + ,title "Intelligent Interactive Video Simulation of a Code Inspection" + ,journal "Communications of the ACM" + ,volume 32 + ,number 7 + ,year 1989 + ,month "July" + ,pages "832-43" +) + +@misc(stone, + key = "Stone", + Title = "diffreg.c", + HowPublished = "Source code for the 4.1BSD Berkeley Unix@+(TM) + @i(diff) program.") + +@book(schrader + ,key = "Schrader" + ,author = "Schrader, B." + ,title = "Introduction to Electro-Acoustic Music" + ,year = "1982" + ,publisher = "Prentice Hall" + ,address = "New Jersey" + ) + +@article(Sundberg82 + ,key="Sundberg" + ,author="Sundberg, J." + ,title="In tune or not? A study of fundamental frequency in music practise" + ,journal="Speech Transmission Laboratory Quarterly Progress and Status Report" + ,year="1982" + ,month="April" + ,number="STL-QPSR 1/1982" + ) + +@article(Sundberg83 + ,key "Sundberg" + ,author "Sundberg, J., A. Askenfelt, L. Fryden" + ,title "Musical Performance: A Synthesis-by-Rule Approach" + ,journal "Computer Music Journal" + ,pages "37-43" + ,year 1983 + ,month "Spring" + ,volume 7 + ,number 1 + ) + +@inproceedings(Teitelbaum + ,key = "Teitelbaum" + ,author = "Teitelbaum, R." + ,title = "The Digital Piano and the Patch Control Language System" + ,pages = "213-216" + ,booktitle = "Proceedings of the International Computer Music Conference 1984" + ,editor = "W. Buxton" + ,year = "1985" + ,organization = "International Computer Music Association" + ) + +@article(Terhardt + ,key="Terhardt" + ,author="Terhardt, E." + ,title="Pitch, consonance, and harmony" + ,journal="Journal of the Acoustical Society of America" + ,year="1974" + ,number="55" + ,page="1061-69" + ) + +@article(Toddcmj + ,key "Todd" + ,author "Todd, P. M." + ,title "A Connectionist Approach to Algorithmic Composition" + ,journal "Computer Music Journal" + ,volume 13 + ,number 4 + ,month "Winter" + ,year 1989 + ,pages "27-43" + ) + +@InCollection(Koenig + ,key "Koenig" + ,author "Koenig, G. M." + ,title "Project 1" + ,BookTitle "Electronic Music Reports" + ,publisher "Institute of Sonology, Utrecht University" + ,month "July" + ,year "1970" + ,pages "32-44" + ) + +@article(ISP + ,key "Kopec" + ,author "Kopec, Gary E." + ,title "The Integrated Signal Processing System ISP" + ,journal "IEEE Transactions on Acoustics, Speech and Signal Processing" + ,month "August" + ,volume "ASSP-32" + ,number 4 + ,year 1984 + ,month "August" + ,pages "842-850" + ) + +@article(SRL, + ,key "Kopec" + ,author "Kopec, Gary E." + ,title "The Signal Representation Language SRL" + ,journal "IEEE Transactions on Acoustics, Speech and Signal Processing" + ,volume "ASSP-33" + ,number 4 + ,month "August" + ,year "1985" + ,pages "921-932" + ) + + +@article(Ternstrom82 + ,key="Ternstrom" + ,author="Ternstrom, S. and J. Sundberg" + ,title="Acoustical factors related to pitch precision in choir singing" + ,journal="Speech Transmission Laboratory Quarterly Progress and Status Report" + ,year="1982" + ,month="October" + ,number="STL-QPSR 2-3/1982" + ) + +@book(Todd + ,key "Todd" + ,author "Todd, P. M. and D. G. Loy" + ,title "Music and Connectionism" + ,publisher "MIT Press" + ,address "Boston" + ,year 1991 + ) + +@book(Touretzky + ,key "Touretzky" + ,author "Touretzky, David S." + ,title "LISP: a gentle introduction to symbolic computation" + ,address "New York" + ,publisher "Harper & Row" + ,year 1984 + ) + +@article(vanska + ,author "Vanska, L., R. J. Rosenberg and V. Pitkanen" + ,key "Vanska" + ,journal "Nuclear Instruments and Methods" + ,title "An Automatic Gamma Spectrometer For Activation Analysis" + ,year 1983 + ,volume 213 + ,pages "343-347" + ) + +@unpublished(spomin + ,author "Velikonja, P." + ,title "Spomin" + ,note "unpublished score." + ,year 1990 + ) + +@manual(Music11 + ,key "vercoe" + ,author "Vercoe, Barry" + ,title "Reference Manual for the MUSIC 11 Sound Synthesis Language" + ,year 1981 + ,organization "MIT Experimental Music Studio" + ) + +@inproceedings(Vercoe84 + ,key "Vercoe" + ,author "Vercoe, B." + ,fullauthor "Barry Vercoe" + ,title "The Synthetic Performer in the Context of Live Performance" + ,organization "Computer Music Association" + ,booktitle "Proceedings of the 1984 International Computer Music Conference" + ,pages "199-200" + ,year 1984 + ) + + +@inproceedings(Vercoe85 + ,key "Vercoe" + ,author "Vercoe, B. and M. Puckette" + ,title "Synthetic Rehearsal: Training the Synthetic Performer" + ,organization "International Computer Music Association" + ,booktitle "Proceedings of the International Computer Music Conference 1985" + ,editor "B. Truax" + ,year 1985 + ,pages "275-278" + ) + +@manual(Csound + ,key "vercoe" + ,author "Vercoe, B." + ,title "Csound: A Manual for the Audio Processing System and +Supporting Programs" + ,year 1986 + ,organization "MIT Media Lab" + ) + +@inproceedings(RTCsound + ,key "Vercoe" + ,author "Vercoe, B. and D. Ellis" + ,title "Real-Time CSOUND: Software Synthesis with Sensing and Control" + ,organization "International Computer Music Association" + ,booktitle "ICMC Glasgow 1990 Proceedings" + ,editor "S. Arnold and G. Hair" + ,year 1990 + ,pages "209-211" + ) + +@TechReport(Waibel81a, + key = "Waibel", + Author = "Waibel, A., N. Krishnan, R. Reddy", + Title = "Minimizing Computational Cost for + Dynamic Programming Algorithms", + Institution = "Carnegie-Mellon University + Department of Computer Science", + year = "1981", + Month = "June", + Number = "CMU-CS-81-124") + + +@TechReport(Waibel81b, + key = "Waibel", + Author = "Waibel, A. and B. Yegnanarayana", + Title = "Comparative Study of Nonlinear Time Warping Techniques + in Isolated Word Speech Recognition Systems", + Institution = "Carnegie-Mellon University + Department of Computer Science", + year = "1981", + Month = "June", + Number = "CMU-CS-81-125") + + +@techreport(ward + ,author = "Ward, Stephen A." + ,institution = "MIT" + ,key = "ward" + ,title = "An Approach to Real Time Computation" + ,year = "1978" + ) + +@inproceedings(waters + ,key "Waters" + ,author "Waters, S. and T. Ungvary" + ,title "The Sonogram: A Tool for Visual Documentation of Musical Structure" + ,organization "International Computer Music Association" + ,booktitle "ICMC Glasgow 1990 Proceedings" + ,editor "S. Arnold and G. Hair" + ,year 1990 + ,pages "159-162" + ) + +@techreport(Wawrzynek + ,key = "Wawrzynek" + ,author = "Wawrzynek, John and Tzu-Mu Lin" + ,institution = "California Institute of Technology" + ,title = "A Bit Serial Architecture for Multiplication and Interpolation" + ,year = "1983" + ,month = "January" + ,number = "5067:DF:83" + ) + +@article(Quicktime + ,key "Wayner" + ,author "Wayner, P." + ,title "Inside QUICKTIME" + ,journal "Byte" + ,volume 16 + ,year 1991 + ,month December + ,pages 189 +) + +@book(wenger + ,Key = "Wenger" + ,Author = "Wenger, E." + ,Title = "Artificial Intelligence and Tutoring Systems" + ,Publisher = "Morgan Kaufmann Publishers, Inc." + ,Year = 1987 + ) + +@inbook(wesseltimbre + ,key "Wessel" + ,author "Wessel, D. L." + ,title "Timbre Space as a Musical Control Structure" + ,booktitle "Foundations of Computer Music" + ,editor "C. Roads and J. Strawn" + ,pages "640-657" + ,year 1985 + ,publisher "MIT Press" + ,address "Cambridge, MA" + ,note "Originally published in @i(Computer Music Journal) 3(2):45-52, 1979" + ) + +@article(ModulaDesign + ,key "Wirth" + ,author "Wirth, N." + ,title "Design and implementation of Modula" + ,journal "Software, Practice and Experience" + ,volume 7 + ,number 1 + ,year 1977 + ,pages "67-84" + ) + +@article(MPC + ,key "Yager" + ,author "Yager, T." + ,title "The Multimedia PC: High-powered Sight and Sound on Your Desk" + ,journal "Byte" + ,volume 17 + ,year 1992 + ,month Feb + ,pages 217 +) + +@book(Xenakis + ,key "Xenakis" + ,author "Xenakis, I." + ,title "Formalized Music" + ,publisher "Indiana University Press" + ,address "Bloomington" + ,year 1971 + ) + +@misc(Xmedia + ,key = "DEC" + ,Title = "XMedia Tools, Version 1.1A" + ,Author = "Digital Equipment Corporation" + ,HowPublished = "Software Product Description SPD 36.55.02" + ,year 1992 + ) + +@inproceedings(CEDS + ,key "Zahler" + ,author "Zahler, N." + ,title "CEDS TO GROW A CAT: A Progress/Studio Report" + ,organization "International Computer Music Association" + ,booktitle "ICMC Montreal 1991 Proceedings" + ,editor "B. Alphonce and B. Pennycook" + ,year 1991 + ,pages "455-458" + ) diff --git a/docsrc/convert/convert.lsp b/docsrc/convert/convert.lsp new file mode 100644 index 0000000..a57ec82 --- /dev/null +++ b/docsrc/convert/convert.lsp @@ -0,0 +1,171 @@ +;; convert.lsp -- insert XLISP syntax definitions + +(defun alpha-char-p (c) + (let ((cc (char-code c))) + (or (and (>= cc (char-code #\a)) + (<= cc (char-code #\z))) + (and (>= cc (char-code #\A)) + (<= cc (char-code #\Z)))))) + +(defun get-token () + (prog ((token (read-char *inf*)) + (next-char (peek-char nil *inf*))) + (if (not token) (return token)) + (if (and token (not (alpha-char-p token)) (not (eql token #\@))) + (return (string token))) + (setf token (string token)) + (while (and next-char (alpha-char-p next-char)) + (setf token (strcat token (string (read-char *inf*)))) + (setf next-char (peek-char nil *inf*))) + (return token))) + + +(defun convert (infile outfile) + (setf *next-tokens* nil) + (setf paren-stack nil) + (let ((inf (open infile)) + (outf (open outfile :direction :output))) + (process inf outf) + (close inf) + (close outf))) + +(defun is-open-paren (tok) + (member tok '("(" "{" "[" "<") :test 'equal)) + +(defun open-paren () + (let ((tok (get-token))) + (cond ((is-open-paren tok) + (push tok paren-stack)) + (t + (display "open-paren got a surprise" tok))))) +; (push tok *next-tokens*) +; ;; if no open paren, then fake open and close +; (push #\( paren-stack) +; (push #\) *next-tokens*))))) + +(defun close-paren-p (tok) + (paren-match tok)) + + +(defun paren-match (p2) + (let ((p1 (car paren-stack))) + (or (and (equal p2 ")") + (equal p1 "(")) + (and (equal p2 "]") + (equal p1 "[")) + (and (equal p2 "}") + (equal p1 "{")) + (and (equal p2 ">") + (equal p1 "<"))))) + + +(defun starts-with-symbol-char (tok) + (let ((c (char tok 0))) + (or (alpha-char-p c) + (digit-char-p c) + (eql c #\-) + (eql c #\*)))) + +(defun get-fn-name (token-list) + (setf token-list (cdr token-list)) + (let ((fn-name "")) + (while (and token-list (starts-with-symbol-char (car token-list))) + (setf fn-name (strcat fn-name (car token-list))) + (setf token-list (cdr token-list))) + fn-name)) + +(defun get-args (token-list) + (prog (arg args) +loop + (setf token-list (cdr token-list)) + (cond ((and token-list (cdr token-list) (cddr token-list) + (equal (car token-list) "@i")) + (push (cadr token-list) paren-stack) + (setf token-list (cddr token-list)) ;; go to parameter name + (while paren-stack + (if (close-paren-p (car token-list)) (pop paren-stack) + (push (car token-list) arg)) + (setf token-list (cdr token-list))) + (push (reverse arg) args) + (setf arg nil)) + ((null token-list) + (return (reverse args)))) + (go loop))) + +(defun write-list-of-args (args) + (dolist (arg args) + (format *outf* " @i(") + (write-list-of-tokens arg) + (format *outf* ")"))) + +(defun write-list-of-tokens (toks) + (dolist (tok toks) + (format *outf* "~A" tok))) + + +;; this is a variable if there are no args and if there is no +;; back-to-back open/close paren pair as in foo(). +(defun is-variable-check (tokens) + (prog () +loop + (cond ((null (cdr tokens)) + (return t)) + ((and (equal (car tokens) "(") + (equal (cadr tokens) ")")) + (return nil))) + (setf tokens (cdr tokens)) + (go loop))) + + +(defun process-codef () + (let ((tok (get-token)) + token-list fn-name args) + (push tok paren-stack) + (push tok token-list) + (while (and tok paren-stack) + (setf tok (get-token)) + (if (is-open-paren tok) (push tok paren-stack) + (if (close-paren-p tok) (pop paren-stack))) + (push tok token-list)) + (setf token-list (reverse token-list)) + ;; now we have a list of tokens including brackets + (display "process-codef" token-list) + (setf fn-name (get-fn-name token-list)) + (setf args (get-args token-list)) + (setf is-var (and (null args) + (is-variable-check token-list))) + (display "parse" fn-name args) + (cond (is-var + (format *outf* "@codef") + (write-list-of-tokens token-list)) + (t + (format *outf* "@codef") + (write-list-of-tokens token-list) + (format *outf* " @c{[sal]}@*\n@altdef{@code[~A~A" + (if is-var "" "(") fn-name) + (write-list-of-args args) + (format *outf* "~A] @c{[lisp]}}" + (if is-var "" ")")))))) + + + +(defun process (inf outf) + (setf *inf* inf) + (setf *outf* outf) + (prog (tok) +loop + (setf tok (get-token)) + (cond ((null tok) + (return 'done)) + ((string= tok "@codef") + (process-codef)) + (t + (format *outf* "~A" tok))) + (go loop))) + +(defun l () (load "convert.lsp")) +(convert "nyquistman.mss" "nyquistman-out.mss") +;(convert "short.txt" "short-out.txt") + + + diff --git a/docsrc/convert/convert2.lsp b/docsrc/convert/convert2.lsp new file mode 100644 index 0000000..2ef9309 --- /dev/null +++ b/docsrc/convert/convert2.lsp @@ -0,0 +1,381 @@ +;; convert2.lsp -- insert XLISP syntax definitions to Nyquist manual AND SAL syntax +;; definitions into xlisp.mss + +(defun assert (co) (if co t (error "assertion error"))) + +(defun alpha-char-p (c) + (let ((cc (char-code c))) + (or (and (>= cc (char-code #\a)) + (<= cc (char-code #\z))) + (and (>= cc (char-code #\A)) + (<= cc (char-code #\Z)))))) + +(defun get-begin-end-token (begin-end) + (open-paren) + (let ((env-name (get-token)) + (close-tok (get-token))) + (cond ((paren-match close-tok) + (pop paren-stack) + (return (strcat begin-end "(" env-name ")"))) + (t + (display "get-begin-end-token failed" begin-end env-name close-tok))))) + +(defun get-token () + (prog ((token (read-char *inf*)) + (next-char (peek-char nil *inf*))) + (if (not token) (return token)) + (if (and token (not (alpha-char-p token)) (not (eql token #\@))) + (return (string token))) + (setf token (string token)) + (while (and next-char (alpha-char-p next-char)) + (setf token (strcat token (string (read-char *inf*)))) + (setf next-char (peek-char nil *inf*))) + (if (or (string= token "@begin") (string= token "@end")) + (return (get-begin-end-token token)) + (return token)))) + + +(defun convert (infile outfile) + (setf *next-tokens* nil) + (setf paren-stack nil) + (let ((inf (open infile)) + (outf (open outfile :direction :output))) + (process inf outf) + (close inf) + (close outf))) + +;; note: "<" has been omitted here to allow parsing of "<" as an operator +;; in XLISP documentation. "<" is not commonly used as scribe bracket, but +;; that could cause problems in some cases because this is not a full +;; scribe parser. +(defun is-open-paren (tok) + (member tok '("(" "{" "[") :test 'equal)) + +(defun open-paren () + (let ((tok (get-token))) + (cond ((is-open-paren tok) + (push tok paren-stack)) + (t + (display "open-paren got a surprise" tok))))) +; (push tok *next-tokens*) +; ;; if no open paren, then fake open and close +; (push #\( paren-stack) +; (push #\) *next-tokens*))))) + +(defun close-paren-p (tok) + (paren-match tok)) + + +(defun paren-match (p2) + (let ((p1 (car paren-stack))) + (or (and (equal p2 ")") + (equal p1 "(")) + (and (equal p2 "]") + (equal p1 "[")) + (and (equal p2 "}") + (equal p1 "{")) + (and (equal p2 ">") + (equal p1 "<"))))) + + +(defun starts-with-symbol-char (tok) + (let ((c (char tok 0))) + (or (alpha-char-p c) + (digit-char-p c) + (eql c #\-) + (eql c #\+) + (eql c #\*) + (eql c #\=) + (eql c #\/) + (eql c #\>) + (eql c #\<)))) + +(defun get-fn-name () + (setf *token-list* (cdr *token-list*)) + (let ((fn-name "")) + (while (and *token-list* + (or (starts-with-symbol-char (car *token-list*)) + (equal (car *token-list*) "@i") ; allow c@i(xx)r + (equal (car *token-list*) "(") + (equal (car *token-list*) ")"))) + (setf fn-name (strcat fn-name (car *token-list*))) + (setf *token-list* (cdr *token-list*))) + fn-name)) + +(defun get-symbol() + (let ((s "")) + (while (and *token-list* + (starts-with-symbol-char (car *token-list*))) + (setf s (strcat s (car *token-list*))) + (setf *token-list* (cdr *token-list*))) + s)) + +;; GET-ARG - *token-list* starts with open bracket (after @i). Get the +;; tokens between this and the close bracket. +(defun get-arg () + (let (arg) + (push (car *token-list*) paren-stack) + (setf *token-list* (cdr *token-list*)) ;; go to parameter name + (while paren-stack + (if (close-paren-p (car *token-list*)) (pop paren-stack)) + (push (car *token-list*) arg) + (setf *token-list* (cdr *token-list*))) + ;; take cdr to drop the close bracket + (reverse (cdr arg)))) + +(defun get-args () + (prog (args arg) +loop + (cond ((and *token-list* (cdr *token-list*) (cddr *token-list*) + (equal (car *token-list*) "@i")) + (setf *token-list* (cdr *token-list*)) + (push (get-arg) args)) + ((and (equal (car *token-list*) ".") + (equal (cadr *token-list*) ".") + (equal (caddr *token-list*) ".")) + (setf *token-list* (cdddr *token-list*)) + (push '("...") args)) + ((and *token-list* (cddr *token-list*) + (equal (car *token-list*) "&") + (equal (cadr *token-list*) "key") + (equal (caddr *token-list*) " ")) + (push '("&key ") args) + (setf *token-list* (cdddr *token-list*))) + ((and *token-list* (cdr *token-list*) + (equal (car *token-list*) ":")) + (setf arg '(":")) + (setf *token-list* (cdr *token-list*)) ; skip ":" + (push (get-symbol) arg) ;; keyword + (setf arg (reverse arg)) + (push arg args)) + (*token-list* + (push (list :meta (car *token-list*)) args) + (setf *token-list* (cdr *token-list*))) + ((null *token-list*) + (return (reverse args)))) + (go loop))) + +(defun write-list-of-args (args) + (let (need-space) + (dolist (arg args) + (cond ((equal arg '("...")) + (setf need-space t) + (format *outf* "@r(...)")) + ((and (consp arg) (equal (car arg) :meta)) + (setf need-space nil) + (format *outf* (cadr arg))) + ((and (consp arg) (or (equal (car arg) ":") + (equal (car arg) "&key "))) + (setf need-space nil) + (format *outf* "@t(") + (write-list-of-tokens arg) + (format *outf* ")")) + (t + ;; insert space between consecutive args + (if need-space (format *outf* "@t( )")) + (setf need-space t) + (format *outf* "@t(@i(") + (write-list-of-tokens arg) + (format *outf* "))")))))) + +(defun write-sal-args (args) + (let (need-comma) + (dolist (arg args) + (cond ((equal arg '("...")) + (format *outf* "@r(...)")) + ((and (consp arg) (equal (car arg) :meta) + (or (equal (cadr arg) "[") + (equal (cadr arg) "]"))) + (format *outf* (cadr arg))) + ((and (consp arg) (equal (car arg) :meta)) nil) ;; o.w. ignore meta + ((and (consp arg) (equal (car arg) "&key "))) + ((and (consp arg) (equal (car arg) ":")) ;; must be a keyword parm + ;; assumes this is not the first parameter + (format *outf* ", ~A: @i(~A)" + (cadr arg) (cadr arg))) + (t + (format *outf* "~A@i(" (if need-comma ", " "")) + (setf need-comma t) + (write-list-of-tokens arg) + (format *outf* ")")))))) + + +(defun write-list-of-tokens (toks) + (dolist (tok toks) + (format *outf* "~A" tok))) + + +;; this is a variable if there are no args and if there is no +;; back-to-back open/close paren pair as in foo(). +(defun is-variable-check (args) + (prog () +loop + (cond ((null (cdr args)) + (return t)) + ((and (equal (car args) '(:meta "(")) + (equal (cadr args) '(:meta ")"))) + (return nil)) + ((= (length (car args)) 1) + (return nil))) + (setf args (cdr args)) + (go loop))) + + +(defun get-balanced-token-list (tok) + (let (token-list) + (push tok paren-stack) + (push tok token-list) + (while (and tok paren-stack) + (setf tok (get-token)) + (if (is-open-paren tok) (push tok paren-stack) + (if (close-paren-p tok) (pop paren-stack))) + (push tok token-list)) + (setf token-list (reverse token-list)))) + + +(defun process-codef () + (let (fn-name args save-tokens) + (setf *token-list* (get-balanced-token-list (get-token))) + ;; now we have a list of tokens including brackets + (display "process-codef" *token-list*) + (setf save-tokens *token-list*) + (setf fn-name (get-fn-name)) + (setf args (get-args)) + (setf is-var (is-variable-check args)) + (display "parse" fn-name args is-var) + (cond (is-var + (format *outf* "@codef") + (write-list-of-tokens save-tokens)) + (t + (format *outf* "@codef") + (write-list-of-tokens *token-list*) + (format *outf* " @c{[sal]}@*\n@altdef{@code[(~A" fn-name) + (write-list-of-args args) + (format *outf* "] @c{[lisp]}}"))))) + + +(defun exclude-from-sal (name) + (or (equal name "*") + (equal name "/") + (equal name "+") + (equal name "-") + (equal name "cond") + (equal name "case") + (equal name "let") + (equal name "let*") + (equal name "prog") + (equal name "prog*") + (equal name "flet") + (equal name "labels") + (equal name "macrolet") + (equal name "defun") + (equal name "defmacro") + (equal name "do") + (equal name "do*") + (equal name "dolist") + (equal name "dotimes") + (equal name "return") + (equal name "loop") + (equal name "progv") + (equal name "clean-up") + (equal name "top-level") + (equal name "continue") + (equal name "errset") + (equal name "baktrace") + (equal name "evalhook") + (equal name "1+") + (equal name "1-") + (equal name "<") + (equal name "<=") + (equal name ">") + (equal name ">=") + (equal name "=") + (equal name "/=") + (equal name "print") + (equal name "load"))) + + +(defun process-fdescription () + (let (function-name args save-tokens (tok (get-token)) has-sal) + (format *outf* "@begin(fdescription)") + (while (and tok (not (equal tok "@end(fdescription)"))) + (cond ((equal tok "(") + (setf *token-list* (get-balanced-token-list tok)) + (assert (equal (first *token-list*) "(")) + (setf function-name (get-fn-name)) + (setf save-tokens *token-list*) + (setf args (get-args)) + (display "process-fdescription" save-tokens args) + (setf has-sal (not (exclude-from-sal function-name))) + (cond (has-sal + (format *outf* "@begin(fgroup)@xlcode{~A(" function-name) + (write-sal-args args) + (format *outf* ")} @c{[sal]}\n\n "))) + (format *outf* "@xlcode{(~A" function-name) + ;(setf save-tokens (reverse save-tokens)) + ;(cond ((equal (car save-tokens) ")") + ; (setf save-tokens (cons "@xlcode{)}" (cdr save-tokens)))) + ; (t + ; (display "MISSING CLOSE PAREN" save-tokens))) + ;(setf save-tokens (reverse save-tokens)) + ;(write-list-of-tokens save-tokens) + (write-list-of-args args) + (format *outf* "} @c{[lisp]}") + (setf tok (get-token)) + (format *outf* tok) + (display "process-fdescription" function-name args) + (while (not (equal tok "\n")) + (setf tok (get-token)) + (format *outf* tok)) + (cond (has-sal + (format *outf* "@end(fgroup)\n") + (setf has-sal nil))) + (setf tok (get-token))) + ((equal tok "@begin(pdescription)") + (format *outf* tok) + (scan-to "@end(pdescription)") + (setf tok (get-token))) + ((equal (char tok 0) #\@) + (format *outf* tok) + (cond ((equal (setf tok (get-token)) "(") + (write-list-of-tokens (get-balanced-token-list tok)) + (setf tok (get-token))))) + (t + (format *outf* tok) + (setf tok (get-token))))) + (if tok (format *outf* tok)))) + + +(defun scan-to (stop-tok) + (prog (tok) + loop + (setf tok (get-token)) + (format *outf* "~A" tok) + ;; handle nested pdescriptions + (if (equal tok "@begin(pdescription)") + (scan-to "@end(pdescription)")) + (if (equal tok stop-tok) (return)) + (go loop))) + +(defun process (inf outf) + (setf *inf* inf) + (setf *outf* outf) + (prog (tok) +loop + (setf tok (get-token)) + (cond ((null tok) + (return 'done)) + ((string= tok "@codef") + (process-codef)) + ((string= tok "@begin(fdescription)") + (process-fdescription)) + (t + (format *outf* "~A" tok))) + (go loop))) + +(defun l () (load "convert2.lsp")) +;(convert "xltest.mss" "xltest.out.mss") +(convert "../../xlisp/xlisp-no-sal.mss" "xlisp-out.mss") + + + diff --git a/docsrc/convert/init.lsp b/docsrc/convert/init.lsp new file mode 100644 index 0000000..be2ab47 --- /dev/null +++ b/docsrc/convert/init.lsp @@ -0,0 +1,9 @@ +; init.lsp -- default Nyquist startup file +(load "nyinit.lsp" :verbose nil) + +; add your customizations here: +; e.g. (setf *default-sf-dir* "...") + +;(load "convert.lsp") +(load "convert2.lsp") + diff --git a/docsrc/nyquist/adagio-nyquist.mss b/docsrc/nyquist/adagio-nyquist.mss new file mode 100644 index 0000000..91bf812 --- /dev/null +++ b/docsrc/nyquist/adagio-nyquist.mss @@ -0,0 +1,825 @@ +Adagio @Index(Adagio) is an easy-to-use, non-procedural notation +for scores. In Adagio, text commands are used to specify each +note. If you are new to Adagio, you may want to glance at the +examples in Section @ref(adag-examples-sec) starting on page +@pageref(adag-examples-sec) before reading any further. + +A note is described in Adagio by a set of attributes@Index(attributes), and +any attribute not specified is ``inherited'' from the previous line. +Attributes may appear in any order and must be separated by one or more +blanks. An attribute may not contain any blanks. The attributes are: +time@Index(time), pitch@Index(pitch), loudness@Index(loudness), +voice@Index(voice) number, duration@Index(duration), and articulation@Index(articulation). + +Adagio has been used to program a variety of hardware and software +synthesizers, and the Adagio compiler can be easily adapted to new +environments. Although not originally intended for MIDI, Adagio works quite +well as a representation for MIDI scores. Adagio has been extended to allow MIDI controller +data such as modulation wheels, pitch bend, and volume, MIDI program commands to change timbre, and System Exclusive messages. + +A note command in Adagio must be separated from other notes. Usually, +notes are distinguished by writing each one on a separate line. +Notes can also be separated by using a comma or semicolon as will +be described below. + +Besides notes, there are several other types of commands: +@begin(enumerate) +An asterisk@Index(asterisk) (@code(*)) in column one (or immediately after a comma, +semicolon, or space) indicates that the rest of the line is a +comment@Index(comment). The line is ignored by Adagio, and is therefore a +good way to insert text to be read by people. Here are some examples: +@begin(programexample) +* This is a comment. +T150 G4 * This is a comment too! +T150 G4 ;* So is this. +@end(programexample) + +An empty command (a blank@Index(blank) line, for example) is ignored as if it +were a comment@Index(comment)@foot(To be consistent, a blank line ought to specify zero attributes and +generate a note that inherits all of its attributes from the previous one. +Adagio is intentionally inconsistent in this respect.). + +An exclamation point@Index(exclamation point)@index(!) (!) in column one (or +immediately after a comma or semicolon) indicates a special +command@Index(special command). A special command does not generate a note. +Special commands follow the ``!'' with no intervening spaces and extend to the end of the line, for example: +@begin(programexample) +!TEMPO 100 +@end(programexample) + +Control change commands are used to control parameters like +pitch bend, modulation, and program (timbre). Control +change commands can be specified along with notes or by +themselves. +A command that specifies control changes without specifying +a pitch will not produce a note. +@end(enumerate) + +Adagio is insensitive to case@Index(case), +thus ``A'' is equivalent to ``a'', and you +can mix upper and lower case letters freely. + +@section[Specifying Attributes] +A note is indicated by a set of attributes. Attributes are indicated by a string of characters with no intervening spaces because spaces separate attributes. The attributes are described below. + +The default unit of time is a centisecond +(100@+[th]'s), but this can be changed to a millisecond (1000@+[th]'s) using the @code(!MSEC) command and reset to centiseconds with @code(!CSEC) (see Section @ref(millisec-sec)). In the descriptions below, the term ``time unit'' will be used to mean whichever convention is currently in effect. + +@subsection[Time] + +The time@Index(time) attribute specifies when to start the note. A time is +specified by a ``T@Index(T)'' followed by a number representing time units + or by a duration (durations are described below). Examples: +@begin(programexample) +T150 ** 1.5 sec (or .15 sec) +TQ3 ** 3 quarter note's duration +@end(programexample) +If no time is specified, the default time@Index(default time) is the sum of +the time and duration attributes of the previous note. (But see Section +@ref(next-time-sec).) Time is measured relative to the time of the +most recent Tempo@Index(Tempo) or Rate@Index(Rate) command. (See the +examples in Section +@ref(adag-examples-sec) for some clarification of this point.) + +@subsection[Pitch] + +The pitch@Index(pitch) attribute specifies what frequency to produce. +Standard scale pitches are named by name, using @code(S) for sharp@Index(sharp), + @code(F) for flat@Index(flat), +and (optionally) @code(N) for natural@Index(natural). +For example, @code(C) and @code(CN) represent the same pitch, as do @code(FS) and @code(GF) (F sharp and G flat). Note that there are no bar lines, and accidentals to not carry forward to any other notes as in common practice notation. + +Octaves@Index(octave specification) are specified by +number. @code(C4) is middle C, and @code(B3) is a half step lower. @code(F5) is the top line of +the treble clef, etc. (Adagio octave numbering follows the ISO standard, but note that this is not universal. In particular, Yamaha refers to middle C as C3.) Accidentals@Index(accidentals)@index[S (Adagio Sharp)]@index[F (Adagio Flat)] can go before or after +the octave number, so @code(FS3) and @code(F3S) have the same meaning. + +An alternate +notation for pitch is @code(P)@i(n), where @i(n) is an integer representing the pitch.@index[P (Adagio Pitch)] +Middle C@index(Middle C) (C4) is equivalent to @code(P60), @code(CS4) is @code(P61), etc. + +If you do not specify an octave@Index(octave specification), +Adagio will choose one for you. This +is done by picking the octave that will make the current pitch as close +to the previous pitch as possible. In the case of augmented fourths + or diminished fifths, there are two equally good choices. Adagio +chooses the lower octave. + +@subsection[Duration] + +Duration@Index(duration) is specified by a letter indicating a number of +beats, followed by one or several modifiers. The basic duration codes are: +@begin(display) +@code(W)@Index[W (Adagio Whole note)] (whole@index(whole note), 4 beats), +@code(H)@Index[H (Adagio Half note)] (half@index(half note), 2 beats), +@code(Q)@Index[Q (Adagio Quarter note)] (quarter@index(quarter note), 1 beat), +@code(I)@Index[I (Adagio eIght note)] (eighth@Index(eighth note), 1/2 beat), +@code(S)@Index[S (Adagio Sixteenth note)] (sixteenth@Index(sixteenth note), 1/4 beat), +@code(%)@Index[% (Adagio thirtysecond note)] (thirtysecond@index(thirtysecond note), 1/8 beat), and +@code(^)@index[^ (Adagio sixtyfourth note)] (sixtyfourth@index(sixtyfourth note), 1/16 beat). +@end(display) +Note that @code(E) is a pitch, so eighth-notes use the duration code @code(I). +The default tempo is 100 beats per +minute (see Section @ref(tempo-sec)). These codes may be followed by a @code(T) +(triplet@Index(triplet)@index[T (Adagio Triplet)]), indicating a duration of 2/3 the normal. A dot@Index(dot)@index[. (Adagio)] (@code(.)) after a +duration code extends it by half to 3/2 the normal. An integer +after a note multiplies its duration by the indicated value (the result is +still just one note). Finally, a slash followed by an integer divides +the duration by the integer. Like all attributes, duration attributes may not have embedded spaces. Examples: +@begin(display) +@tabclear +@tabset(.5 inches) +@code(Q)@\1 beat (quarter note) +@code(QT)@\2/3 beat (quarter triplet) +@code(W.)@\6 beats(dotted whole note) +@code(ST6)@\1 beat (6 sixteenth triplets) +@code(H5)@\10 beats(5 half notes) +@code(Q3/7)@\3/7 beats +@end(display) +A duration may be noted by @code(U)@i(n)@Index(U), where @i(n) is an integer +indicating 100@+[th]'s of a second +(or 1000@+[th]'s), see Section @ref(millisec-sec). +For example, @code(U25) is twenty-five time units. + +Durations may be combined using a plus sign: +@begin(programexample) +Q+IT ** a quarter tied to an eighth triplet +Q/7+W+Q2/7 ** a 7th beat tied to a whole tied to 2/7th beat +Q+U10 ** a quarter plus 10 time units +@end(programexample) + +@subsection(Next Time) +@label(next-time-sec) +The time of the next@Index(next Adagio command)@index[N (Adagio Next)] command (the next command in the Adagio +program text) is +normally the time of the current note command +plus the duration of the current note. +This can be overridden by a field consisting of the letter @code(N) +followed by a number indicating time units, or followed by a +duration as described above. The next note will then start at the time of +the current note plus the duration specified after @code(N). If the next note +has an explicit time attribute (@code(T)), then the specified time will override +the one based on the previous note. Examples: +@begin(programexample) +N0 ** start the next note at the same time as this one +N50 ** start the next note 0.5 seconds after this one +NQT ** start the next note 2/3 beat after the current one +NU10+Q ** start after 0.1 seconds plus a quarter +@end(programexample) +A comma has an effect similar to @code(N0) and is explained in Section @ref(comma-sec). Articulation effects such as @i(staccato) can be produced using @code(N), but it is more convenient to use the articulation attribute described in Section @ref(articulation-sec). + +@subsection(Rest) +Rests@Index(rests)@index[R (Adagio Rest)] are obtained by including the field @code(R) in a +note command. The effect of an @code(R) field is to omit the note that would +otherwise occur as the result of the current note command. In all other +respects, the command is processed just like any other line. This means that +attributes such as duration, loudness, and pitch can be specified, and +anything specified will be inherited by the note in the next command. +Normally, a rest will include just @code(R) and a duration. The fact that a +note command specifies a rest is not inherited. For example: +@begin(programexample) +R H ** a half (two beat) rest +RH ** illegal, R must be separated from H by space(s) +@end(programexample) +Because some synthesizers (e.g. a DX7@Index(DX7)) cannot change programs +@Index(program change) +(presets) rapidly, it may be desirable to change programs in +a rest so that the synthesizer will be ready to play by +the end of the rest. See Section @ref(adag-timbre-sec) for an example. + +@subsection[Articulation] +@label(articulation-sec) +Articulation@Index(articulation)@index(staccato)@index(legato) in Adagio refers to the +percentage of time a note is on relative to the indicated duration. For +example, to play a note @i(staccato), you would normally play the note about +half of its indicated duration. In Adagio, articulation is indicated by +@code(#)@index[# (Adagio articulation)] followed by an integer number indicating a percentage. The +articulation attribute does not affect the time of the next command. This +example plays two @i(staccato) quarter notes: +@begin(programexample) +C Q #50 +D +@end(programexample) +To produce overlapping notes, the articulation may be greater than 100. + +@begin(detail) +Be aware that overlapping notes on the same pitch can be a problem for some synthesizers. The following example illustrates this potential problem: +@begin(programexample) +!TEMPO 60 +C Q #160 * starts at time 0, ends at 1.6 sec +D I * starts at time 1, ends at 1.8 sec +C Q * starts at time 1.5, ends at 3.1 sec? +@end(programexample) +At one beat per second (tempo 60), these three notes will start at times 0, 1, and 1.5 seconds, respectively. Since these notes have an articulation of 160, each will be on 160% of its nominal duration, so the first note (C) will remain on until 1.6 seconds. But the third note (another C) will start at time 1.5 seconds. Thus, the second C will be started before the first one ends. Depending on the synthesizer, this may cancel the first C or play a second C in unison. In either case, a note-off message will be sent at time 1.6 seconds. If this cancels the second C, its actual duration will be 0.1 rather than 1.6 seconds as intended. A final note-off will be sent at time 3.1 seconds. +@end(detail) + +@subsection[Loudness] + +Loudness@Index(loudness)@index(velocity) is indicated by an @code(L) +followed by a dynamic marking from the following: @code(PPP)@Index[PPP (Adagio dynamic)]@Index[LPPP (Adagio dynamic)], +@code(PP)@Index[PP (Adagio dynamic)]@Index[LPP (Adagio dynamic)], @code(P)@Index[P (Adagio dynamic)]@Index[LP (Adagio dynamic)], @code(MP)@Index[MP (Adagio dynamic)]@Index[LMP (Adagio dynamic)], @code(MF)@Index[MF (Adagio dynamic)]@Index[LMF (Adagio dynamic)], @code(F)@Index[F (Adagio dynamic)]@Index[LF (Adagio dynamic)], +@code(FF)@Index[FF (Adagio dynamic)]@Index[LFF (Adagio dynamic)], @code(FFF)@Index[FFF (Adagio dynamic)]@Index[LFFF (Adagio dynamic)]. Alternatively, a number from 1 to 127 may be +used. The loudness attribute is the MIDI note velocity. (Note that a MIDI velocity of 0 means ``note-off,'' so the minimum loudness is 1.) The +dynamic@Index(dynamic markings) +markings are translated into numbers as follows: +@begin(display) +@tabclear +@tabset(0.8 in, 3 in, 3.8 in) +@code(Lppp)@\20@\@code(Lmf)@\58 +@code(Lpp)@\26@\@code(Lf)@\75 +@code(Lp)@\34@\@code(Lff)@\98 +@code(Lmp)@\44@\@code(Lfff)@\127 +@end(display) + +@subsection[Voice] + +The voice@Index(voice)@index[V (Adagio Voice)] attribute tells which of the 16 MIDI channels to use +for the note. The voice attribute consists of a @code(V) followed by +an integer from 1 (the default) to 16. +@begin(detail) +There is a limit to how many notes +can be played at the same time on a given voice (MIDI channel). Since the +limit depends upon the synthesizer, Adagio cannot tell you when you exceed +the limit. Similarly, Adagio cannot tell whether your synthesizer is set up +to respond to a given channel, so there is no guarantee that what you write +will actually be heard. +@end(detail) + +@subsection[Timbre (MIDI Program)] +@label(adag-timbre-sec) +A MIDI program@Index(MIDI program)@index[Z (Adagio program)] (synthesizer preset@Index(preset)) can be +selected using the attribute @code(Z)@i(n), where @i(n) +is the program number (from 1 to 128). +Notice that in MIDI, changing the program on a given channel will affect +@i(all) notes on that channel and possibly others. Adagio treats MIDI program changes as a form of control change. +@begin(detail) +For many synthesizers, you will not be +able to change programs at the start of a note or during a note. Change the +program during a rest instead. For example: +@begin(programexample) +R I Z23 V4 ** change MIDI channel 4 to program 23 during rest +A4 ** play a note on channel 4 +@end(programexample) +Check how your synthesizer interprets program numbers. For example, +the cartridge programs on a DX7 can be accessed by adding 32 to the +cartridge program number. Cartridge program number 10 +is specified by @code(Z42). +@end(detail) + +As in MIDI, the Adagio timbre is a property of the voice (MIDI channel), so +the timbre will not be inherited by notes on a different channel; +to change the timbre on multiple voices (channels), you must explicitly +notate each change. + +@subsection[Tempo] +@label(tempo-sec) +The length of a beat may be changed using a Tempo@Index(Tempo) command@index(!Tempo): +@begin(programexample) +!TEMPO @i(n) +@end(programexample) +where @i(n) indicates beats per minute. The exclamation mark tells Adagio that +this is a special command line rather than a note definition. A special +command takes the place of a note specification. +No other attributes should be written on a line with a special command. +The @code(!TEMPO) command is associated with a time, computed as if the @code(!TEMPO) command were a note. The time@Index(time) attribute (@code(T)) of all +succeeding notes is now measured relative to the time of the @code(!TEMPO) command. The new tempo starts at the @code(!TEMPO) command time and +affects all succeeding notes. +Durations specified in time units (for example @code(U58), @code(N15)) are not affected by the @code(!TEMPO) command, and numerical times (for example @code(T851)) are computed relative to the time of the last @code(!TEMPO) command. + +The @code(!TEMPO) command is fairly clever about default durations@Index(default +durations). If the last duration specified before the @code(!TEMPO) command is +symbolic (using one of @code(^),@code(%), @code(S), @code(I), @code(Q), @code(H), or @code(W) ), then the default duration for the +node after the @code(!TEMPO) command will be modified according to the tempo change. +Consider the following tempo change: +@begin(programexample) +!TEMPO 60 +A4 H +!TEMPO 120 +G +@end(programexample) +In this example, the first note will last 2 seconds (2 beats at 60 +beats per minute). The second note inherits the duration (H) from +the first note, but at 120 beats per minute, the second note will last +only 1 second. If the duration had been specified @code(U200) (also a +duration of 2 seconds), the second note would also last 2 seconds because the @code(!TEMPO) command does not affect times or durations specified numerically in time units. If the duration is the sum of a symbolic and a numeric specification, the inherited duration after a @code(!TEMPO) command is undefined. + +@subsection(Rate) +The @code(!RATE)@Index(rate)@index(!Rate) command scales all times including those specified in +hundredths of seconds. A rate of 100 means no change, 200 means twice as +fast, and 50 means half as fast. For example, to make a piece play 10% +faster, you can add the following command at the beginning of the score: +@begin(programexample) +!RATE 110 +@end(programexample) +@code(!RATE) and @code(!TEMPO) commands combine, so +@begin(programexample) +!RATE 200 +!TEMPO 70 +@end(programexample) +will play 70 beats per minute at double the normal speed, or 140 beats +per minute. Like @code(!TEMPO), the time of the @code(!RATE) command is added to the +time attribute of all following notes up to the next @code(!TEMPO) or @code(!RATE) +command. + +Two @code(!RATE) commands do not combine, so a @code(!RATE) command only affects the rate until the next @code(!RATE) command. + +Although @code(!TEMPO) and @code(!RATE) can occur in the middle of a note (using @code(N), @code(T), etc.) they do not affect a note already specified. This property allows multiple tempi to exist simultaneously (see Section @ref(multipletempi-sec)). + +@section[Default Attributes] +@label(default-sec) +If an attribute is omitted, the previous one is used by +default@Index(default) (with the exception of the time attribute). The +default values for the first note, which are inherited by succeeding notes +until something else is specified, are given below in Adagio notation: +@begin(display) +@tabclear +@tabset(1.5 inch) +Time @\@code(T0) +Pitch @\@code(C4) +Duration @\@code(Q) +Articulation @\@code(#100) +Loudness @\@code(LFFF) +Voice @\@code(V1) +Tempo @\@code(!TEMPO 100) +Rate @\@code(!RATE 100) +@end(display) +Control changes (including timbre or MIDI program, specified by @code(Z)) have no default value and are only sent as specified in the score. + +@p(Important:) the rules for determining when a command will play a note are as follows (and this has changed slightly from previous versions): +@begin(enumerate) +If a special (@code(!)) command or nothing is specified, e.g. a blank line, do @i(not) play a note. + +If @code(R) (for ``rest'') is specified, do @i(not) play a note. + +Otherwise, if a pitch is specified, @i(do) play a note. + +Otherwise, if no control changes (or program changes) are specified (so this is a command with non-pitch attributes and no control changes), @i(do) play a note. +@end(enumerate) +Another way to say this is ``Special commands and commands with rests (@code(R)) do not play notes. Otherwise, play a note if a pitch is specified or if no control is specified.'' + + +@section[Examples] +@label(adag-examples-sec) +The following plays the first two bars of ``Happy Birthday''. Note that +Adagio knows nothing of bar lines, so the fact that the first note occurs +on beat 3 or that the meter is three-four is of no consequence: +@begin(programexample) +*Example 1 ** Happy Birthday tune (C major) +!TEMPO 120 +G4 I. LF +G4 S +A4 Q +G4 +C5 +B4 H +@end(programexample) +The time attribute for the first note is zero (@code(0)). The second note +will occur a dotted eighth later, etc. +Notice that no timbre or rate was specified. +Adagio will provide reasonable default +values of 1 and 100, respectively. + +The following example plays the first four bars of an exercise from +Bartok@Index(Bartok)'s Mikrokosmos@Index(Mikrokosmos) (Vol. 1, No. 12). +An extra quarter note is inserted at the beginning of each voice in order to +allow time to change MIDI programs. The right hand part is played on voice +(MIDI channel) 1 and the left hand part on voice 2. Notice the +specification of the time attribute to indicate that voice 2 starts at time +0. Also, default octaves are used to reduce typing. +@begin(programexample) +*Example 2 ** Bartok +*voice 1, right hand +R Q Z10 V1 ** extra rest for program change +A4 H +B Q +C +D H +C +D Q +C +B +A +B +C +D +R + +*voice 2, left hand +T0 R Q Z15 V2 ** extra rest for program change +G3 H +F Q +E +D H +E +D Q +E +F +G +F +E +D +R +@end(programexample) + +The next example is the same piece expressed in a different manner, +illustrating the interaction +between the @code(!TEMPO) command and the time attribute. Recall that the +time attribute is measured relative to the time of the last @code(!TEMPO) command: +@begin(programexample) +*Example 3 ** 4 measures in 2 sections +!Tempo 100 +*Voice 1, Measures 1 & 2 +R Q Z10 V1 +A4 H +B Q +C +D H +C + +*Voice 2, Measures 1 & 2 +T0 R Q Z15 V2 +G3 H +F Q +E +D H +E H + +!TEMPO 100 +*Voice 1, Measures 3 & 4 +* note that Z10 is still in effect for V1 +V1 D4 Q +C +B +A +B +C +D +R + +*Voice 2, Measures 3 & 4 +T0 V2 D3 Q +E +F +G +F +E +D +R +@end(programexample) + +The piece is written in 4 sections. The first +plays a rest followed by two measures, starting +at time 0. The next section changes the time back to +zero and plays two measures of the left hand part (voice 2). +The next +command (!TEMPO 100) sets the tempo to 100 (it already is) +@i(and) sets the reference time to +be two measures into the piece. Therefore, the next note +@code((D4)) will begin measure 3. The @code(D3) that begins the last +group of notes has a @code(T0) attribute, so it will also start at measure +3. Notice how the @code(!TEMPO) command can serve to divide a piece into +sections@Index(sections, Adagio). + + +The last example will show yet another way to express the same piece of +music using the ``Next'' attribute. Only the first bar of music is +given. +@begin(programexample) +*Example 4 ** use of the Next attribute +!Tempo 100 +R Q Z10 V1 N0 +R Q Z15 V2 + +A4 H V1 N0 +G3 V2 + +B4 Q V1 N0 +F3 V2 + +C4 Q V1 N0 +E3 V2 +@end(programexample) +Here, each pair of +lines represents two simultaneous notes. The @code(N0) attribute +forces the second line to start at the same time as the first line of each +pair. Because of the large intervals, octave numbers (3 and 4) are +necessary to override the default octave for these pitches. + +@section(Advanced Features) +Beyond the simple notation described above, Adagio supports a number of +features. (See also the next chapter.) + +@subsection(Time Units and Resolution) +@label(millisec-sec)@index(time units)@index(resolution) +The default time unit is 10ms (ten milliseconds or one centisecond or +100@+(th) of a second), but it is +possible to change the basic unit to 1ms, or 1000@+(th) of a second. +The time unit can be specified by: +@begin(display) +@tabclear +@tabset(0.8 inches) +@t(!CSEC)@index(!csec)@\centisecond time units = 100@+(th) +@t(!MSEC)@index(!msec)@\millisecond time units = 1000@+(th) +@end(display) +The time unit remains in effect until the next @code(!CSEC) or @code(!MSEC) command. + +@subsection(Multiple Notes Per Line) +@label(comma-sec) +@index(multiple commands) +Notes can be separated by commas@Index(commas)@index[, (Adagio)] or +semicolons@Index(semicolon, Adagio)@index[; (Adagio)] as well as by starting a new line. A comma is +equivalent to typing @code(N0) and starting a new line. In other words, the next note after a comma will start at the same time as the note before the comma. In general, @i(use commas to separate the notes of a chord.) + +A semicolon is equivalent to starting a new line. In general, @i(use semicolons to group notes in a melody). Here is yet another rendition of the Bartok: +@begin(programexample) +*Example 5 ** use of semicolons +!Tempo 100 +R Q Z10 V1 +A4 H; B Q; C; D H; C; D Q; C; B; A; B; C; D; R + +T0 R Q Z15 V2 +G3 H; F Q; E; D H; E; D Q; E; F; G; F; E; D; R +@end(programexample) +This example is similar to Example 2, except semicolons are used. Note how semicolons make the two lines of music stand out. +The next example is similar to Example 4, except commas are used +and four bars are notated. The music below is treated as a sequence of 2-note chords, with each chord on a separate line: +@begin(programexample) +*Example 6 ** use of commas +!Tempo 100 +R Q Z10 V1, R Q Z15 V2 +A4 H V1, G3 V2 +B4 Q V1, F3 V2 +C4 V1, E3 V2 +D4 H V1, D3 V2 +C4 V1, E3 V2 +D4 Q V1, D3 V2 +C4 V1, E3 V2 +B4 V1, F3 V2 +A4 V1, G3 V2 +B4 V1, F3 V2 +C4 V1, E3 V2 +D4 V1, D3 V2 +R +@end(programexample) + +@subsection(Control Change Commands) +@index(Control change)@index[~ (Adagio)] +Any control change can be specified using +the syntax ``@t[~@i(n)(@i(v))]'', where @i(n) is the controller number (0 - 127), and +@i(v) is the value. In addition, Adagio has some special syntax for +some of the commonly used control changes (note that Pitch bend, Aftertouch, and MIDI Program Change are technically not MIDI control changes but have their own +special message format and status bytes): +@begin(display) +@tabclear +@tabset(0.5 inch) +K@\Portamento switch@Index(Portamento switch)@Index[K (Adagio control)]@* +M@\Modulation wheel@Index(Modulation wheel)@Index[M (Adagio control)]@* +O@\Aftertouch@Index(Aftertouch)@Index[O (Adagio control)]@* +X@\Volume@Index(Volume)@Index[X (Adagio control)]@* +Y@\Pitch bend@Index(Pitch bend)@Index[Y (Adagio control)]@* +Z@\Program Change@Index(Program)@Index[Z (Adagio program)]@* +@end(display) +The letter listed beside each control function is the Adagio command +letter. For example, @code(M23) is the command for setting the modulation +wheel to 23. Except for pitch bend, the portamento switch, and MIDI Program Change, all +values range from 0 to 127. Pitch bend is ``off'' or centered at +128, and has a range from 0 to 255 (MIDI allows for more precision, but +Adagio does not). Turn on portamento with @code(K127) and off with @code(K0). Programs are numbered 1 to 128 to correspond to synthesizer displays. + +@p(About volume:) Midi volume is just a control, and the Midi standard does not say what it means. Typically it does what the volume pedal does; that is, it scales the amplitude in a continuously changeable fashion. In contrast, Midi velocity, which is controlled by the @code(L) (loudness) attribute, is part of a Midi note-on command and is fixed for the duration of the note. Typically, these two ways of controlling loudness and amplitude operate independently. In some low-cost synthesizers the numbers seem to be added together internally and volume changes are ignored after the note starts. + +@p(About pitch bend:) Midi pitch bend is a number from 0 to 16383, where 8192 is the center position. To convert to Midi, Adagio simply multiplies your number by 64, giving values from 0 to 16320. Note that @code(Y128) translates exactly to 8192. The @i(meaning) of pitch bend depends upon your synthesizer and its setting. Most synthesizers let you specify a ``pitch bend range.'' A range of one semitone means that @code(Y255) will produce a bend of approximately one semitone up, and @code(Y0) will bend one semitone down. If the range is 12 semitones, then the same @code(Y255) will bend an octave. Typically, pitch bend is exponential, so each increment in the pitch bend value will bend an equal number of cents in pitch. + +Control changes can be part of a note specification or independent. +In the following example, a middle C is played with a modulation +wheel setting of 50 and a pitch bend of 120. Then, at 10 unit +intervals, the pitch bend is decreased by 10. The last line sets the +portamento time (controller 5) to 80: +@begin(programexample) +*Example 7 +C4 LMF M50 Y120 U100 N10 +Y110 N10; Y100 N10; Y90 N10; Y80 N10 +Y70 N10; Y60 N10; Y50 N10 +~5(80) +@end(programexample) + +See Section @ref(default-sec) on page @pageref(default-sec) for rules on whether or not a command will play a note. + +@subsection(Multiple Tempi)@Index(multiple tempi) +@label(multipletempi-sec) +@Index(polyrhythm) +Writing a piece with multiple tempi requires no new commands; you +just have to be clever in the use of Tempo and Time. The following +plays a 7 note diatonic scale on voice 1, and a 12 note chromatic +scale on voice 2: +@begin(programexample) +*Example 8 ** multiple tempi +!TEMPO 70 +V1 C4; D; E; F; G; A; B +T0 R N0 + +!TEMPO 120 +V2 C4; CS; D; DS; E; F; FS; G; GS; A; AS; B + +!TEMPO 100 +V1 C5, V2 C5 +@end(programexample) +The third line plays the 7-note diatonic scale on voice 1. The +next line contains the tricky part: notice that the time is +set back to zero, there is a rest, and a next (@code(N)) attribute is used +to specify that the next default time will be at the same time as +the current one. This is tricky because a @code(!TEMPO) command cannot have a time (@code(T0)) attribute, and a @code(T0) by itself would create a note with a duration. @code(T0 R N0) says: ``go to time 0, do not play a note, and do not advance the time before the next command''. +Thus, the time of the @code(!TEMPO 120) command is zero. +After the 12 note scale, the tempo is changed to 100 and a final note +is played on each voice. A little arithmetic will show that 7 notes +at tempo 70 and 12 notes at tempo 120 each take 6 seconds, so the +final notes (@code(C5)) of each scale will happen at the same time. + +@subsection(MIDI Synchronization) +@index(synchronization)@index(clock)@index(MIDI Clock)@index(clock command) + +The Adagio program (but not Nyquist) can synchronize with external devices using MIDI real time messages. Thus, Adagio has a @code(!CLOCK) command. This command is currently of no use to Nyquist users but is documented here for completeness (it's part of the language syntax even if it does not do anything). + +Since Adagio supports multiple tempi, and Midi clock is +based on beats, it is necessary to be explicit in the score about where the +clock should start and what is the duration of a quarter note. The +@code(!CLOCK) command@index(!Clock) in Adagio turns on a 24 pulse-per-quarter (PPQ) clock at +the current tempo and time: +@begin(programExample) +!TEMPO 100 +!CLOCK +@end(programexample) +A @code(!CLOCK) command must also be inserted for each tempo change that is to be +reflected in the Midi clock. Typically, each !TEMPO command will be followed by a !CLOCK command. +@begin(detail) +Clock commands and thus tempo +changes can take place at arbitrary times. It is assumed that tempo changes +on an exact 24@+(th) of a beat subdivision (for example, exactly on a +beat). If not, the tempo change will take place on the nearest exact +24@+(th) of a beat subdivision. This may be earlier or later than the +requested time. +@end(detail) + +@subsection[System Exclusive Messages] +@label(macro-sec) +Adagio has a definition facility that makes it possible to send system +exclusive parameters. Often, there are parameters on Midi +synthesizers that can only be controlled by system exclusive messages. +Examples include the FM ratio and LFO rate on a DX7 synthesizer. The +following example defines a macro for the DX7 LFO rate and then shows how +the macro is used to set the LFO rate for a B-flat whole note in the score. +The macro definition is given in hexadecimal, except @t(v) is replaced by +the channel (voice) and @t(%1) is replaced by the first parameter. +A macro is invoked by writing ``~'' followed by the macro name and a +list of parameters@index(!Def): +@begin(programexample) +!DEF LFO F0 43 0v 01 09 %1 F7 +Bf5 W ~LFO(25) +@end(programexample) + +In general, the @t(!DEF) command can define any single MIDI message including +a system exclusive +message. The message must be complete (including the status byte), and each @t(!DEF) must correspond to just one message. +The symbol following @t(!DEF) can be any name consisting of +alphanumeric characters. Following the name is a hexadecimal string +(with optional spaces), all on one line. Embedded in the string may +be the following special characters: +@begin(description) +@t(v)@\Insert the 4-bit voice (MIDI channel) number. If @t(v) occurs in the +place of a high-order hexadecimal digit, replace @t(v) with @t(0v) so that +the channel number is always placed in the low-order 4 bits of a data byte. In other words, @t(v) is padded if necessary to fall into the low-order bits. + +@t(%)@i(n)@\Insert a data byte with the low-order 7 bits of +parameter number @i(n). Parameters are numbered 1 through 9. +If the +parameter value is greater than 127, the high-order bits are discarded. + +@t(^)@i(n)@\Insert a data byte with bits 7 through 13 of parameter number +@i(n). In other words, shift the value right 7 places then clear all +but the first 7 bits. Note that 14-bit numbers can be encoded by +referencing the same parameter twice; for example, @t(%4^4) will +insert the low-order followed by the high-order parts of parameter 4 +into two successive data bytes. +@end(description) + +Parameters are separated by commas, but there may be no spaces. The +maximum number of parameters allowed is 9. Here +is an example of definitions to send a full-resolution pitch +bend command and to send a system exclusive command to change a DX7 +parameter@foot[My TX816 Owner's Manual gives an incorrect format for the +change parameter sysex command (according to the manual, there is no data +in the message!) I am assuming that the data should be the last byte before +the EOX and that there is no byte count. If you are reading this, assume +that I have not tested this guess, nor have I tested this example.]. + +@begin(programexample) +* Define macro for pitch bend commands: +!DEF bend Ev %1 ^1 + +A ~bend(8192) ** 8192 is "pitch bend off" + +* Change the LFO SPEED: +* SYSEX = F0, Yamaha = 43, Substatus/Channel = 1v, +* Group# = 01, Parameter# = 9, Data = 0-99, EOX = F7 +!DEF lfospeed F0 43 1v 01 09 %1 F7 + +* now use the definitions: +G4 ~bend(7567) N40 +~lfospeed(30) N35 + +@end(programexample) + + +@subsection(Control Ramps) +@label(macroramp-sec) +The @t(!RAMP) command@index(!Ramp) can specify a smooth control change from one +value to another. It consists of a specification of the starting and +ending values of some control change, a duration specifying how often +to send a new value, and a duration specifying the total length of the ramp. +@begin(programexample) +!RAMP X10 X100 Q W2 +!RAMP ~23(10) ~23(50) U20 W +!RAMP ~lfo(15) ~lfo(35) U10 +@end(programexample) +The first line says to ramp the volume control (controller number 7) +from 10 to 100, changing at each quarter note for the duration of two +whole notes. +The second line says to ramp controller number 23 from value 10 to value 50, +sending a new control change message every 20 time units. The overall +duration of the ramp should be equivalent to a whole note (@t(W)). +As shown in the third line, even system exclusive messages controlled by +parameters can be specified. If the system exclusive message has more +than one parameter, only one parameter may be ``ramped''; the others must +remain the same. For example, the following would ramp the second parameter: +@begin(programexample) +!RAMP ~mysysex(4,23,75) ~mysysex(4,100,75) U10 W +@end(programexample) + +@begin(detail) +A rather curious and extreme use of macros and ramps is illustrated in the +following example. The @t(noteon) macro starts a note, and @t(noteoff) ends it. Ramps can now be used to emit a series of notes with changing pitches or velocities. Since Adagio has no idea that these macros are turning on notes, it is up to the programmer to turn them off! +@begin(programexample) +!DEF noteon 9v %1 %2 +!DEF noteoff 8v %1 %2 +~noteon(48,125) +~noteoff(48,126) +* turn on some notes +!RAMP ~noteon(36,125) ~noteon(60,125) Q W NW +* turn them off +!RAMP ~noteoff(60,50) ~noteoff(36,50) Q W NW +@end(programexample) +@end(detail) + +@subsection(The !End Command) +@label(end-sec)@index(!End)@index(end command) +The special command @code(!END) marks the end of a score. Everything beyond that +is ignored, for example: +@begin(programexample) +* this is a score +C; D; E; F; G W +!END +since the score has ended, this text will be ignored +@end(programexample) + +@subsection(Calling C Routines) +@label(call-sec) +It is possible to call C routines from within Adagio scores when using +specially linked versions, but this feature is disabled in Nyquist. The +syntax is described here for completeness. + +The @code(!CALL) command@index(!Call)@index(Call command) calls a C routine that can in turn invoke a +complex sequence of operations. Below is a call to a trill@index(trill) routine, +which is a standard routine in Adagio. The parameters are the base +pitch of the trill, the total duration of the trill, the interval in semitones, the +duration of each note of the trill, and the loudness. Notice +that both numbers and Adagio notation can be used as parameters: +@begin(programexample) +!CALL trill(A5,W,2,S,Lmf) T278 V1 +@end(programexample) +@i(The parameter list should have no spaces), and parameters are separated +by commas. Following the close parenthesis, you may specify other +attributes such as the starting time and voice as shown in the example above. + +A parameter may be an Adagio pitch specification, an Adagio duration, +an Adagio loudness, a number, or an ASCII character within single +quotes, e.g. @t('a') is equivalent to @t(97) because 97 is the decimal +encoding of ``a'' in ASCII. + +The @code(!CALL) may be followed by a limited set of attributes. These are time (@t(T)), voice (@t(V)), and next time (@t(N)). The @code(!CALL) is made at the current time if no time is specified, and the time of the next adagio command is the time of the @code(!CALL) unless a next time is specified. In other words, the default is @t(N0). + +@subsection(Setting C Variables) +In addition to calling C routines, there is another way in which scores +can communicate with C. As with @code(!CALL), specific C code must be linked before these commands can be used, and this is not supported in Nyquist. +The @code(!SETI) command@index(!Seti)@index(seti commnad) sets an integer variable +to a value, and the @code(!SETV) command@index(!Setv)@index(setv command) sets an element of an integer array. +For example, the next line sets the variable @t(delay) to 200 and sets +@t(transposition[5]) to -4 at time 200: +@begin(programexample) +!SETI delay 200 +!SETV transposition 5 -4 T200 +@end(programexample) +As with the @code(!CALL) command, these commands perform their operations at +particular times according to their place in the Adagio score. This makes +it very easy to implement time-varying parameters that control various +aspects of an interactive music system. + diff --git a/docsrc/nyquist/adagio.mss b/docsrc/nyquist/adagio.mss new file mode 100644 index 0000000..b26e028 --- /dev/null +++ b/docsrc/nyquist/adagio.mss @@ -0,0 +1,840 @@ +Adagio @Index(Adagio) is an easy-to-use, non-procedural notation +for scores. In Adagio, text commands are used to specify each +note. If you are new to Adagio, you may want to glance at the +examples in Section @ref(adag-examples-sec) starting on page +@pageref(adag-examples-sec) before reading any further. + +A note is described in Adagio by a set of attributes@Index(attributes), and +any attribute not specified is ``inherited'' from the previous line. +Attributes may appear in any order and must be separated by one or more +blanks. An attribute may not contain any blanks. The attributes are: +time@Index(time), pitch@Index(pitch), loudness@Index(loudness), +voice@Index(voice) number, duration@Index(duration), and articulation@Index(articulation). + +Adagio has been used to program a variety of hardware and software +synthesizers, and the Adagio compiler can be easily adapted to new +environments. Although not originally intended for MIDI, Adagio works quite +well as a representation for MIDI scores. Adagio has been extended to allow MIDI controller +data such as modulation wheels, pitch bend, and volume, MIDI program commands to change timbre, and System Exclusive messages. + +A note command in Adagio must be separated from other notes. Usually, +notes are distinguished by writing each one on a separate line. +Notes can also be separated by using a comma or semicolon as will +be described below. + +Besides notes, there are several other types of commands: +@begin(enumerate) +An asterisk@Index(asterisk) (@code(*)) in column one (or immediately after a comma, +semicolon, or space) indicates that the rest of the line is a +comment@Index(comment). The line is ignored by Adagio, and is therefore a +good way to insert text to be read by people. Here are some examples: +@begin(programexample) +* This is a comment. +T150 G4 * This is a comment too! +T150 G4 ;* So is this. +@end(programexample) + +An empty command (a blank@Index(blank) line, for example) is ignored as if it +were a comment@Index(comment)@foot(To be consistent, a blank line ought to specify zero attributes and +generate a note that inherits all of its attributes from the previous one. +Adagio is intentionally inconsistent in this respect.). + +An exclamation point@Index(exclamation point)@index(!) (!) in column one (or +immediately after a comma or semicolon) indicates a special +command@Index(special command). A special command does not generate a note. +Special commands follow the ``!'' with no intervening spaces and extend to the end of the line, for example: +@begin(programexample) +!TEMPO 100 +@end(programexample) + +Control change commands are used to control parameters like +pitch bend, modulation, and program (timbre). Control +change commands can be specified along with notes or by +themselves. +A command that specifies control changes without specifying +a pitch will not produce a note. +@end(enumerate) + +Adagio is insensitive to case@Index(case), +thus ``A'' is equivalent to ``a'', and you +can mix upper and lower case letters freely. + +@section[Specifying Attributes] +A note is indicated by a set of attributes. Attributes are indicated by a string of characters with no intervening spaces because spaces separate attributes. The attributes are described below. + +The default unit of time is a centisecond +(100@+[th]'s), but this can be changed to a millisecond (1000@+[th]'s) using the @code(!MSEC) command and reset to centiseconds with @code(!CSEC) (see Section @ref(millisec-sec)). In the descriptions below, the term ``time unit'' will be used to mean whichever convention is currently in effect. + +@subsection[Time] + +The time@Index(time) attribute specifies when to start the note. A time is +specified by a ``T@Index(T)'' followed by a number representing time units + or by a duration (durations are described below). Examples: +@begin(programexample) +T150 ** 1.5 sec (or .15 sec) +TQ3 ** 3 quarter note's duration +@end(programexample) +If no time is specified, the default time@Index(default time) is the sum of +the time and duration attributes of the previous note. (But see Section +@ref(next-time-sec).) Time is measured relative to the time of the +most recent Tempo@Index(Tempo) or Rate@Index(Rate) command. (See the +examples in Section +@ref(adag-examples-sec) for some clarification of this point.) + +@subsection[Pitch] + +The pitch@Index(pitch) attribute specifies what frequency to produce. +Standard scale pitches are named by name, using @code(S) for sharp@Index(sharp), + @code(F) for flat@Index(flat), +and (optionally) @code(N) for natural@Index(natural). +For example, @code(C) and @code(CN) represent the same pitch, as do @code(FS) and @code(GF) (F sharp and G flat). Note that there are no bar lines, and accidentals to not carry forward to any other notes as in common practice notation. + +Octaves@Index(octave specification) are specified by +number. @code(C4) is middle C, and @code(B3) is a half step lower. @code(F5) is the top line of +the treble clef, etc. (Adagio octave numbering follows the ISO standard, but note that this is not universal. In particular, Yamaha refers to middle C as C3.) Accidentals@Index(accidentals)@index[S (Adagio Sharp)]@index[F (Adagio Flat)] can go before or after +the octave number, so @code(FS3) and @code(F3S) have the same meaning. + +An alternate +notation for pitch is @code(P)@i(n), where @i(n) is an integer representing the pitch.@index[P (Adagio Pitch)] +Middle C@index(Middle C) (C4) is equivalent to @code(P60), @code(CS4) is @code(P61), etc. + +If you do not specify an octave@Index(octave specification), +Adagio will choose one for you. This +is done by picking the octave that will make the current pitch as close +to the previous pitch as possible. In the case of augmented fourths + or diminished fifths, there are two equally good choices. Adagio +chooses the lower octave. + +@subsection[Duration] + +Duration@Index(duration) is specified by a letter indicating a number of +beats, followed by one or several modifiers. The basic duration codes are: +@begin(display) +@code(W)@Index[W (Adagio Whole note)] (whole@index(whole note), 4 beats), +@code(H)@Index[H (Adagio Half note)] (half@index(half note), 2 beats), +@code(Q)@Index[Q (Adagio Quarter note)] (quarter@index(quarter note), 1 beat), +@code(I)@Index[I (Adagio eIght note)] (eighth@Index(eighth note), 1/2 beat), +@code(S)@Index[S (Adagio Sixteenth note)] (sixteenth@Index(sixteenth note), 1/4 beat), +@code(%)@Index[% (Adagio thirtysecond note)] (thirtysecond@index(thirtysecond note), 1/8 beat), and +@code(^)@index[^ (Adagio sixtyfourth note)] (sixtyfourth@index(sixtyfourth note), 1/16 beat). +@end(display) +Note that @code(E) is a pitch, so eighth-notes use the duration code @code(I). +The default tempo is 100 beats per +minute (see Section @ref(tempo-sec)). These codes may be followed by a @code(T) +(triplet@Index(triplet)@index[T (Adagio Triplet)]), indicating a duration of 2/3 the normal. A dot@Index(dot)@index[. (Adagio)] (@code(.)) after a +duration code extends it by half to 3/2 the normal. An integer +after a note multiplies its duration by the indicated value (the result is +still just one note). Finally, a slash followed by an integer divides +the duration by the integer. Like all attributes, duration attributes may not have embedded spaces. Examples: +@begin(display) +@tabclear +@tabset(.5 inches) +@code(Q)@\1 beat (quarter note) +@code(QT)@\2/3 beat (quarter triplet) +@code(W.)@\6 beats(dotted whole note) +@code(ST6)@\1 beat (6 sixteenth triplets) +@code(H5)@\10 beats(5 half notes) +@code(Q3/7)@\3/7 beats +@end(display) +A duration may be noted by @code(U)@i(n)@Index(U), where @i(n) is an integer +indicating 100@+[th]'s of a second +(or 1000@+[th]'s), see Section @ref(millisec-sec). +For example, @code(U25) is twenty-five time units. + +Durations may be combined using a plus sign: +@begin(programexample) +Q+IT ** a quarter tied to an eighth triplet +Q/7+W+Q2/7 ** a 7th beat tied to a whole tied to 2/7th beat +Q+U10 ** a quarter plus 10 time units +@end(programexample) + +@subsection(Next Time) +@label(next-time-sec) +The time of the next@Index(next)@index[N (Adagio Next)] command (the next command in the Adagio +program text) is +normally the time of the current note command +plus the duration of the current note. +This can be overridden by a field consisting of the letter @code(N) +followed by a number indicating time units, or followed by a +duration as described above. The next note will then start at the time of +the current note plus the duration specified after @code(N). If the next note +has an explicit time attribute (@code(T)), then the specified time will override +the one based on the previous note. Examples: +@begin(programexample) +N0 ** start the next note at the same time as this one +N50 ** start the next note 0.5 seconds after this one +NQT ** start the next note 2/3 beat after the current one +NU10+Q ** start after 0.1 seconds plus a quarter +@end(programexample) +A comma has an effect similar to @code(N0) and is explained in Section @ref(comma-sec). Articulation effects such as @i(staccato) can be produced using @code(N), but it is more convenient to use the articulation attribute described in Section @ref(articulation-sec). + +@subsection(Rest) +Rests@Index(rests)@index[R (Adagio Rest)] are obtained by including the field @code(R) in a +note command. The effect of an @code(R) field is to omit the note that would +otherwise occur as the result of the current note command. In all other +respects, the command is processed just like any other line. This means that +attributes such as duration, loudness, and pitch can be specified, and +anything specified will be inherited by the note in the next command. +Normally, a rest will include just @code(R) and a duration. The fact that a +note command specifies a rest is not inherited. For example: +@begin(programexample) +R H ** a half (two beat) rest +RH ** illegal, R must be separated from H by space(s) +@end(programexample) +Because some synthesizers (e.g. a DX7@Index(DX7)) cannot change programs +@Index(program change) +(presets) rapidly, it may be desirable to change programs in +a rest so that the synthesizer will be ready to play by +the end of the rest. See Section @ref(adag-timbre-sec) for an example. + +@subsection[Articulation] +@label(articulation-sec) +Articulation@Index(articulation)@index(staccato)@index(legato) in Adagio refers to the +percentage of time a note is on relative to the indicated duration. For +example, to play a note @i(staccato), you would normally play the note about +half of its indicated duration. In Adagio, articulation is indicated by +@code(#)@index[# (Adagio articulation)] followed by an integer number indicating a percentage. The +articulation attribute does not affect the time of the next command. This +example plays two @i(staccato) quarter notes: +@begin(programexample) +C Q #50 +D +@end(programexample) +To produce overlapping notes, the articulation may be greater than 100. +@begin(detail) +Be aware that overlapping notes on the same pitch can be a problem for some synthesizers. The following example illustrates this potential problem: +@begin(programexample) +!TEMPO 60 +C Q #160 * starts at time 0, ends at 1.6 sec +D I * starts at time 1, ends at 1.8 sec +C Q * starts at time 1.5, ends at 3.1 sec? +@end(programexample) +At one beat per second (tempo 60), these three notes will start at times 0, 1, and 1.5 seconds, respectively. Since these notes have an articulation of 160, each will be on 160% of its nominal duration, so the first note (C) will remain on until 1.6 seconds. But the third note (another C) will start at time 1.5 seconds. Thus, the second C will be started before the first one ends. Depending on the synthesizer, this may cancel the first C or play a second C in unison. In either case, a note-off message will be sent at time 1.6 seconds. If this cancels the second C, its actual duration will be 0.1 rather than 1.6 seconds as intended. A final note-off will be sent at time 3.1 seconds. +@end(detail) + +@subsection[Loudness] + +Loudness@Index(loudness)@index(velocity) is indicated by an @code(L) +followed by a dynamic marking from the following: @code(PPP)@Index[PPP (Adagio dynamic)]@Index[LPPP (Adagio dynamic)], +@code(PP)@Index[PP (Adagio dynamic)]@Index[LPP (Adagio dynamic)], @code(P)@Index[P (Adagio dynamic)]@Index[LP (Adagio dynamic)], @code(MP)@Index[MP (Adagio dynamic)]@Index[LMP (Adagio dynamic)], @code(MF)@Index[MF (Adagio dynamic)]@Index[LMF (Adagio dynamic)], @code(F)@Index[F (Adagio dynamic)]@Index[LF (Adagio dynamic)], +@code(FF)@Index[FF (Adagio dynamic)]@Index[LFF (Adagio dynamic)], @code(FFF)@Index[FFF (Adagio dynamic)]@Index[LFFF (Adagio dynamic)]. Alternatively, a number from 1 to 127 may be +used. The loudness attribute is the MIDI note velocity. (Note that a MIDI velocity of 0 means ``note-off,'' so the minimum loudness is 1.) The +dynamic@Index(dynamic markings) +markings are translated into numbers as follows: +@begin(display) +@tabclear +@tabset(0.8 in, 3 in, 3.8 in) +@code(Lppp)@\20@\@code(Lmf)@\58 +@code(Lpp)@\26@\@code(Lf)@\75 +@code(Lp)@\34@\@code(Lff)@\98 +@code(Lmp)@\44@\@code(Lfff)@\127 +@end(display) + +@subsection[Voice] + +The voice@Index(voice)@index[V (Adagio Voice)] attribute tells which of the 16 MIDI channels to use +for the note. The voice attribute consists of a @code(V) followed by +an integer from 1 (the default) to 16. +@begin(detail) +There is a limit to how many notes +can be played at the same time on a given voice (MIDI channel). Since the +limit depends upon the synthesizer, Adagio cannot tell you when you exceed +the limit. Similarly, Adagio cannot tell whether your synthesizer is set up +to respond to a given channel, so there is no guarantee that what you write +will actually be heard. +@end(detail) + +@subsection[Timbre (MIDI Program)] +@label(adag-timbre-sec) +A MIDI program@Index(MIDI program)@index[Z (Adagio program)] (synthesizer preset@Index(preset)) can be +selected using the attribute @code(Z)@i(n), where @i(n) +is the program number (from 1 to 128). +Notice that in MIDI, changing the program on a given channel will affect +@i(all) notes on that channel and possibly others. Adagio treats MIDI program changes as a form of control change. +@begin(detail) +For many synthesizers, you will not be +able to change programs at the start of a note or during a note. Change the +program during a rest instead. For example: +@begin(programexample) +R I Z23 V4 ** change MIDI channel 4 to program 23 during rest +A4 ** play a note on channel 4 +@end(programexample) +Check how your synthesizer interprets program numbers. For example, +the cartridge programs on a DX7 can be accessed by adding 32 to the +cartridge program number. Cartridge program number 10 +is specified by @code(Z42). +@end(detail) + +As in MIDI, the Adagio timbre is a property of the voice (MIDI channel), so +the timbre will not be inherited by notes on a different channel; +to change the timbre on multiple voices (channels), you must explicitly +notate each change. + +@subsection[Tempo] +@label(tempo-sec) +The length of a beat may be changed using a Tempo@Index(Tempo) command@index(!Tempo): +@begin(programexample) +!TEMPO @i(n) +@end(programexample) +where @i(n) indicates beats per minute. The exclamation mark tells Adagio that +this is a special command line rather than a note definition. A special +command takes the place of a note specification. +No other attributes should be written on a line with a special command. +The @code(!TEMPO) command is associated with a time, computed as if the @code(!TEMPO) command were a note. The time@Index(time) attribute (@code(T)) of all +succeeding notes is now measured relative to the time of the @code(!TEMPO) command. The new tempo starts at the @code(!TEMPO) command time and +affects all succeeding notes. +Durations specified in time units (for example @code(U58), @code(N15)) are not affected by the @code(!TEMPO) command, and numerical times (for example @code(T851)) are computed relative to the time of the last @code(!TEMPO) command. + +The @code(!TEMPO) command is fairly clever about default durations@Index(default +durations). If the last duration specified before the @code(!TEMPO) command is +symbolic (using one of @code(^),@code(%), @code(S), @code(I), @code(Q), @code(H), or @code(W) ), then the default duration for the +node after the @code(!TEMPO) command will be modified according to the tempo change. +Consider the following tempo change: +@begin(programexample) +!TEMPO 60 +A4 H +!TEMPO 120 +G +@end(programexample) +In this example, the first note will last 2 seconds (2 beats at 60 +beats per minute). The second note inherits the duration (H) from +the first note, but at 120 beats per minute, the second note will last +only 1 second. If the duration had been specified @code(U200) (also a +duration of 2 seconds), the second note would also last 2 seconds because the @code(!TEMPO) command does not affect times or durations specified numerically in time units. If the duration is the sum of a symbolic and a numeric specification, the inherited duration after a @code(!TEMPO) command is undefined. + +@subsection(Rate) +The @code(!RATE)@Index(rate)@index(!Rate) command scales all times including those specified in +hundredths of seconds. A rate of 100 means no change, 200 means twice as +fast, and 50 means half as fast. For example, to make a piece play 10% +faster, you can add the following command at the beginning of the score: +@begin(programexample) +!RATE 110 +@end(programexample) +@code(!RATE) and @code(!TEMPO) commands combine, so +@begin(programexample) +!RATE 200 +!TEMPO 70 +@end(programexample) +will play 70 beats per minute at double the normal speed, or 140 beats +per minute. Like @code(!TEMPO), the time of the @code(!RATE) command is added to the +time attribute of all following notes up to the next @code(!TEMPO) or @code(!RATE) +command. + +Two @code(!RATE) commands do not combine, so a @code(!RATE) command only affects the rate until the next @code(!RATE) command. + +Although @code(!TEMPO) and @code(!RATE) can occur in the middle of a note (using @code(N), @code(T), etc.) they do not affect a note already specified. This property allows multiple tempi to exist simultaneously (see Section @ref(multipletempi-sec)). + +@section[Default Attributes] +@label(default-sec) +If an attribute is omitted, the previous one is used by +default@Index(default) (with the exception of the time attribute). The +default values for the first note, which are inherited by succeeding notes +until something else is specified, are given below in Adagio notation: +@begin(display) +@tabclear +@tabset(1.5 inch) +Time@\@code(T0) +Pitch@\@code(C4) +Duration@\@code(Q) +Articulation@\@code(#100) +Loudness@\@code(LFFF) +Voice@\@code(V1) +Tempo@\@code(!TEMPO 100) +Rate@\@code(!RATE 100) +@end(display) +Control changes (including timbre or MIDI program, specified by @code(Z)) have no default value and are only sent as specified in the score. + +@p(Important:) the rules for determining when a command will play a note are as follows (and this has changed slightly from previous versions): +@begin(enumerate) +If a special (@code(!)) command or nothing is specified, e.g. a blank line, do @i(not) play a note. + +If @code(R) (for ``rest'') is specified, do @i(not) play a note. + +Otherwise, if a pitch is specified, @i(do) play a note. + +Otherwise, if no control changes (or program changes) are specified (so this is a command with non-pitch attributes and no control changes), @i(do) play a note. +@end(enumerate) +Another way to say this is ``Special commands and commands with rests (@code(R)) do not play notes. Otherwise, play a note if a pitch is specified or if no control is specified.'' + + +@section[Examples] +@label(adag-examples-sec) +The following plays the first two bars of ``Happy Birthday''. Note that +Adagio knows nothing of bar lines, so the fact that the first note occurs +on beat 3 or that the meter is three-four is of no consequence: +@begin(programexample) +*Example 1 ** Happy Birthday tune (C major) +!TEMPO 120 +G4 I. LF +G4 S +A4 Q +G4 +C5 +B4 H +@end(programexample) +The time attribute for the first note is zero (@code(0)). The second note +will occur a dotted eighth later, etc. +Notice that no timbre or rate was specified. +Adagio will provide reasonable default +values of 1 and 100, respectively. + +The following example plays the first four bars of an exercise from +Bartok@Index(Bartok)'s Mikrokosmos@Index(Mikrokosmos) (Vol. 1, No. 12). +An extra quarter note is inserted at the beginning of each voice in order to +allow time to change MIDI programs. The right hand part is played on voice +(MIDI channel) 1 and the left hand part on voice 2. Notice the +specification of the time attribute to indicate that voice 2 starts at time +0. Also, default octaves are used to reduce typing. +@begin(programexample) +*Example 2 ** Bartok +*voice 1, right hand +R Q Z10 V1 ** extra rest for program change +A4 H +B Q +C +D H +C +D Q +C +B +A +B +C +D +R + +*voice 2, left hand +T0 R Q Z15 V2 ** extra rest for program change +G3 H +F Q +E +D H +E +D Q +E +F +G +F +E +D +R +@end(programexample) + +The next example is the same piece expressed in a different manner, +illustrating the interaction +between the @code(!TEMPO) command and the time attribute. Recall that the +time attribute is measured relative to the time of the last @code(!TEMPO) command: +@begin(programexample) +*Example 3 ** 4 measures in 2 sections +!Tempo 100 +*Voice 1, Measures 1 & 2 +R Q Z10 V1 +A4 H +B Q +C +D H +C + +*Voice 2, Measures 1 & 2 +T0 R Q Z15 V2 +G3 H +F Q +E +D H +E H + +!TEMPO 100 +*Voice 1, Measures 3 & 4 +* note that Z10 is still in effect for V1 +V1 D4 Q +C +B +A +B +C +D +R + +*Voice 2, Measures 3 & 4 +T0 V2 D3 Q +E +F +G +F +E +D +R +@end(programexample) + +The piece is written in 4 sections. The first +plays a rest followed by two measures, starting +at time 0. The next section changes the time back to +zero and plays two measures of the left hand part (voice 2). +The next +command (!TEMPO 100) sets the tempo to 100 (it already is) +@i(and) sets the reference time to +be two measures into the piece. Therefore, the next note +@code((D4)) will begin measure 3. The @code(D3) that begins the last +group of notes has a @code(T0) attribute, so it will also start at measure +3. Notice how the @code(!TEMPO) command can serve to divide a piece into +sections@Index(sections, Adagio). + + +The last example will show yet another way to express the same piece of +music using the ``Next'' attribute. Only the first bar of music is +given. +@begin(programexample) +*Example 4 ** use of the Next attribute +!Tempo 100 +R Q Z10 V1 N0 +R Q Z15 V2 + +A4 H V1 N0 +G3 V2 + +B4 Q V1 N0 +F3 V2 + +C4 Q V1 N0 +E3 V2 +@end(programexample) +Here, each pair of +lines represents two simultaneous notes. The @code(N0) attribute +forces the second line to start at the same time as the first line of each +pair. Because of the large intervals, octave numbers (3 and 4) are +necessary to override the default octave for these pitches. + +@section(Advanced Features) +Beyond the simple notation described above, Adagio supports a number of +features. (See also the next chapter.) + +@subsection(Time Units and Resolution) +@label(millisec-sec)@index(time units)@index(resolution) +The default time unit is 10ms (ten milliseconds or one centisecond or +100@+(th) of a second), but it is +possible to change the basic unit to 1ms, or 1000@+(th) of a second. +The time unit can be specified by: +@begin(display) +@tabclear +@tabset(0.8 inches) +@t(!CSEC)@index(!csec)@\centisecond time units = 100@+(th) +@t(!MSEC)@index(!msec)@\millisecond time units = 1000@+(th) +@end(display) +The time unit remains in effect until the next @code(!CSEC) or @code(!MSEC) command. + +@subsection(Multiple Notes Per Line) +@label(comma-sec) +@index(multiple commands) +Notes can be separated by commas@Index(commas)@index[, (Adagio)] or +semicolons@Index(semicolon, Adagio)@index[; (Adagio)] as well as by starting a new line. A comma is +equivalent to typing @code(N0) and starting a new line. In other words, the next note after a comma will start at the same time as the note before the comma. In general, @i(use commas to separate the notes of a chord.) + +A semicolon is equivalent to starting a new line. In general, @i(use semicolons to group notes in a melody). Here is yet another rendition of the Bartok: +@begin(programexample) +*Example 5 ** use of semicolons +!Tempo 100 +R Q Z10 V1 +A4 H; B Q; C; D H; C; D Q; C; B; A; B; C; D; R + +T0 R Q Z15 V2 +G3 H; F Q; E; D H; E; D Q; E; F; G; F; E; D; R +@end(programexample) +This example is similar to Example 2, except semicolons are used. Note how semicolons make the two lines of music stand out. +The next example is similar to Example 4, except commas are used +and four bars are notated. The music below is treated as a sequence of 2-note chords, with each chord on a separate line: +@begin(programexample) +*Example 6 ** use of commas +!Tempo 100 +R Q Z10 V1, R Q Z15 V2 +A4 H V1, G3 V2 +B4 Q V1, F3 V2 +C4 V1, E3 V2 +D4 H V1, D3 V2 +C4 V1, E3 V2 +D4 Q V1, D3 V2 +C4 V1, E3 V2 +B4 V1, F3 V2 +A4 V1, G3 V2 +B4 V1, F3 V2 +C4 V1, E3 V2 +D4 V1, D3 V2 +R +@end(programexample) + +@subsection(Control Change Commands) +@index(Control change)@index[~ (Adagio)] +Any control change can be specified using +the syntax ``@t[~@i(n)(@i(v))]'', where @i(n) is the controller number (0 - 127), and +@i(v) is the value. In addition, Adagio has some special syntax for +some of the commonly used control changes (note that Pitch bend, Aftertouch, and MIDI Program Change are technically not MIDI control changes but have their own +special message format and status bytes): +@begin(display) +@tabclear +@tabset(0.5 inch) +K@\Portamento switch@Index(Portamento switch)@Index[K (Adagio control)] +M@\Modulation wheel@Index(Modulation wheel)@Index[M (Adagio control)] +O@\Aftertouch@Index(Aftertouch)@Index[O (Adagio control)] +X@\Volume@Index(Volume)@Index[X (Adagio control)] +Y@\Pitch bend@Index(Pitch bend)@Index[Y (Adagio control)] +Z@\Program Change@Index(Program)@Index[Z (Adagio program)] +@end(display) +The letter listed beside each control function is the Adagio command +letter. For example, @code(M23) is the command for setting the modulation +wheel to 23. Except for pitch bend, the portamento switch, and MIDI Program Change, all +values range from 0 to 127. Pitch bend is ``off'' or centered at +128, and has a range from 0 to 255 (MIDI allows for more precision, but +Adagio does not). Turn on portamento with @code(K127) and off with @code(K0). Programs are numbered 1 to 128 to correspond to synthesizer displays. + +@p(About volume:) Midi volume is just a control, and the Midi standard does not say what it means. Typically it does what the volume pedal does; that is, it scales the amplitude in a continuously changeable fashion. In contrast, Midi velocity, which is controlled by the @code(L) (loudness) attribute, is part of a Midi note-on command and is fixed for the duration of the note. Typically, these two ways of controlling loudness and amplitude operate independently. In some low-cost synthesizers the numbers seem to be added together internally and volume changes are ignored after the note starts. + +@p(About pitch bend:) Midi pitch bend is a number from 0 to 16383, where 8192 is the center position. To convert to Midi, Adagio simply multiplies your number by 64, giving values from 0 to 16320. Note that @code(Y128) translates exactly to 8192. The @i(meaning) of pitch bend depends upon your synthesizer and its setting. Most synthesizers let you specify a ``pitch bend range.'' A range of one semitone means that @code(Y255) will produce a bend of approximately one semitone up, and @code(Y0) will bend one semitone down. If the range is 12 semitones, then the same @code(Y255) will bend an octave. Typically, pitch bend is exponential, so each increment in the pitch bend value will bend an equal number of cents in pitch. + +Control changes can be part of a note specification or independent. +In the following example, a middle C is played with a modulation +wheel setting of 50 and a pitch bend of 120. Then, at 10 unit +intervals, the pitch bend is decreased by 10. The last line sets the +portamento time (controller 5) to 80: +@begin(programexample) +*Example 7 +C4 LMF M50 Y120 U100 N10 +Y110 N10; Y100 N10; Y90 N10; Y80 N10; Y70 N10; Y60 N10; Y50 N10 +~5(80) +@end(programexample) + +See Section @ref(default-sec) on page @pageref(default-sec) for rules on whether or not a command will play a note. + +@subsection(Multiple Tempi)@Index(multiple tempi) +@label(multipletempi-sec) +@Index(polyrhythm) +Writing a piece with multiple tempi requires no new commands; you +just have to be clever in the use of Tempo and Time. The following +plays a 7 note diatonic scale on voice 1, and a 12 note chromatic +scale on voice 2: +@begin(programexample) +*Example 8 ** multiple tempi +!TEMPO 70 +V1 C4; D; E; F; G; A; B +T0 R N0 + +!TEMPO 120 +V2 C4; CS; D; DS; E; F; FS; G; GS; A; AS; B + +!TEMPO 100 +V1 C5, V2 C5 +@end(programexample) +The third line plays the 7-note diatonic scale on voice 1. The +next line contains the tricky part: notice that the time is +set back to zero, there is a rest, and a next (@code(N)) attribute is used +to specify that the next default time will be at the same time as +the current one. This is tricky because a @code(!TEMPO) command cannot have a time (@code(T0)) attribute, and a @code(T0) by itself would create a note with a duration. @code(T0 R N0) says: ``go to time 0, do not play a note, and do not advance the time before the next command''. +Thus, the time of the @code(!TEMPO 120) command is zero. +After the 12 note scale, the tempo is changed to 100 and a final note +is played on each voice. A little arithmetic will show that 7 notes +at tempo 70 and 12 notes at tempo 120 each take 6 seconds, so the +final notes (@code(C5)) of each scale will happen at the same time. + +@subsection(MIDI Synchronization) +@index(synchronization)@index(clock)@index(MIDI Clock)@index(clock command) + +The Adagio program can synchronize with external devices using MIDI real time messages. Adagio can act as either a master or slave. As a master, Midi +real time messages +are generated according to the score. As a slave, the program uses +incoming Midi messages to control the timebase against which notes and other +events are scheduled. In this way, an external device such as a drum +machine or other sequencer can start, stop, and control the tempo of Adagio +scores. @p(Note:) the current implementation of synchronization to an +external source is very simplistic; it effectively quantizes the score to +units of 1/24 of a beat. + +Since Adagio supports multiple tempi, and Midi clock is +based on beats, it is necessary to be explicit in the score about where the +clock should start and what is the duration of a quarter note. The +@code(!CLOCK) command@index(!Clock) in Adagio turns on a 24 pulse-per-quarter (PPQ) clock at +the current tempo and time: +@begin(programExample) +!TEMPO 100 +!CLOCK +@end(programexample) +A @code(!CLOCK) command must also be inserted for each tempo change that is to be +reflected in the Midi clock. Typically, each !TEMPO command will be followed by a !CLOCK command. +@begin(detail) +Clock commands and thus tempo +changes can take place at arbitrary times. It is assumed that tempo changes +on an exact 24@+(th) of a beat subdivision (for example, exactly on a +beat). If not, the tempo change will take place on the nearest exact +24@+(th) of a beat subdivision. This may be earlier or later than the +requested time. +@end(detail) + +To synchronize other systems, e.g. a drum machine, to Adagio, you should make the device a +``slave'' and start Adagio. Adagio will sent a MIDI Start message and 24 Timing Clock messages per quarter note. When you stop Adagio by typing either the space bar or by reaching the end of the score, Adagio will send a MIDI Stop message, which should stop the slave device. + +To synchronize Adagio to another system, type @code(c) to enable external clock synchronization (see Section @ref(adag-resp-sec)), and type +@c(RETURN) as if to start the Adagio score. Adagio will wait for a MIDI Start message and will then synchronize to MIDI Clock messages. A MIDI Stop message will stop the playback as if the space bar were typed. To synchronize one Adagio to another, be sure the ``slave'' is ready and waiting before starting the ``master''. + +@subsection[System Exclusive Messages] +@label(macro-sec) +Adagio has a definition facility that makes it possible to send system +exclusive parameters. Often, there are parameters on Midi +synthesizers that can only be controlled by system exclusive messages. +Examples include the FM ratio and LFO rate on a DX7 synthesizer. The +following example defines a macro for the DX7 LFO rate and then shows how +the macro is used to set the LFO rate for a B-flat whole note in the score. +The macro definition is given in hexadecimal, except @t(v) is replaced by +the channel (voice) and @t(%1) is replaced by the first parameter. +A macro is invoked by writing ``~'' followed by the macro name and a +list of parameters@index(!Def): +@begin(programexample) +!DEF LFO F0 43 0v 01 09 %1 F7 +Bf5 W ~LFO(25) +@end(programexample) + +In general, the @t(!DEF) command can define any single MIDI message including +a system exclusive +message. The message must be complete (including the status byte), and each @t(!DEF) must correspond to just one message. +The symbol following @t(!DEF) can be any name consisting of +alphanumeric characters. Following the name is a hexadecimal string +(with optional spaces), all on one line. Embedded in the string may +be the following special characters: +@begin(description) +@t(v)@\Insert the 4-bit voice (MIDI channel) number. If @t(v) occurs in the +place of a high-order hexadecimal digit, replace @t(v) with @t(0v) so that +the channel number is always placed in the low-order 4 bits of a data byte. In other words, @t(v) is padded if necessary to fall into the low-order bits. + +@t(%)@i(n)@\Insert a data byte with the low-order 7 bits of +parameter number @i(n). Parameters are numbered 1 through 9. +If the +parameter value is greater than 127, the high-order bits are discarded. + +@t(^)@i(n)@\Insert a data byte with bits 7 through 13 of parameter number +@i(n). In other words, shift the value right 7 places then clear all +but the first 7 bits. Note that 14-bit numbers can be encoded by +referencing the same parameter twice; for example, @t(%4^4) will +insert the low-order followed by the high-order parts of parameter 4 +into two successive data bytes. +@end(description) + +Parameters are separated by commas, but there may be no spaces. The +maximum number of parameters allowed is 9. Here +is an example of definitions to send a full-resolution pitch +bend command and to send a system exclusive command to change a DX7 +parameter@foot[My TX816 Owner's Manual gives an incorrect format for the +change parameter sysex command (according to the manual, there is no data +in the message!) I am assuming that the data should be the last byte before +the EOX and that there is no byte count. If you are reading this, assume +that I have not tested this guess, nor have I tested this example.]. + +@begin(programexample) +* Define macro for pitch bend commands: +!DEF bend Ev %1 ^1 + +A ~bend(8192) ** 8192 is "pitch bend off" + +* Change the LFO SPEED: +* SYSEX = F0, Yamaha = 43, Substatus/Channel = 1v, +* Group# = 01, Parameter# = 9, Data = 0-99, EOX = F7 +!DEF lfospeed F0 43 1v 01 09 %1 F7 + +* now use the definitions: +G4 ~bend(7567) N40 +~lfospeed(30) N35 + +@end(programexample) + + +@subsection(Control Ramps) +@label(macroramp-sec) +The @t(!RAMP) command@index(!Ramp) can specify a smooth control change from one +value to another. It consists of a specification of the starting and +ending values of some control change, a duration specifying how often +to send a new value, and a duration specifying the total length of the ramp. +@begin(programexample) +!RAMP X10 X100 Q W2 +!RAMP ~23(10) ~23(50) U20 W +!RAMP ~lfo(15) ~lfo(35) U10 +@end(programexample) +The first line says to ramp the volume control (controller number 7) +from 10 to 100, changing at each quarter note for the duration of two +whole notes. +The second line says to ramp controller number 23 from value 10 to value 50, +sending a new control change message every 20 time units. The overall +duration of the ramp should be equivalent to a whole note (@t(W)). +As shown in the third line, even system exclusive messages controlled by +parameters can be specified. If the system exclusive message has more +than one parameter, only one parameter may be ``ramped''; the others must +remain the same. For example, the following would ramp the second parameter: +@begin(programexample) +!RAMP ~mysysex(4,23,75) ~mysysex(4,100,75) U10 W +@end(programexample) + +@begin(detail) +A rather curious and extreme use of macros and ramps is illustrated in the +following example. The @t(noteon) macro starts a note, and @t(noteoff) ends it. Ramps can now be used to emit a series of notes with changing pitches or velocities. Since Adagio has no idea that these macros are turning on notes, it is up to the programmer to turn them off! +@begin(programexample) +!DEF noteon 9v %1 %2 +!DEF noteoff 8v %1 %2 +~noteon(48,125) +~noteoff(48,126) +* turn on some notes +!RAMP ~noteon(36,125) ~noteon(60,125) Q W NW +* turn them off +!RAMP ~noteoff(60,50) ~noteoff(36,50) Q W NW +@end(programexample) +@end(detail) + +@subsection(The !End Command) +@label(end-sec)@index(!End)@index(end command) +The special command @code(!END) marks the end of a score. Everything beyond that +is ignored, for example: +@begin(programexample) +* this is a score +C; D; E; F; G W +!END +since the score has ended, this text will be ignored +@end(programexample) +See Section @ref(seqread-sec) for a further discussion. + +@subsection(Calling C Routines) +@label(call-sec) +It is possible to call C routines from within Adagio scores. +The routine must be written in C, the name must be entered into a special +table, and the compiled routine must be linked into Adagio or some +application that uses Adagio sequences. Only the command syntax will be +described here. (See Section @ref(call-impl-sec) +for more information.) + +The @code(!CALL) command@index(!Call)@index(Call command) calls a C routine that can in turn invoke a +complex sequence of operations. Below is a call to a trill@index(trill) routine, +which is a standard routine in Adagio. The parameters are the base +pitch of the trill, the total duration of the trill, the interval in semitones, the +duration of each note of the trill, and the loudness. Notice +that both numbers and Adagio notation can be used as parameters: +@begin(programexample) +!CALL trill(A5,W,2,S,Lmf) T278 V1 +@end(programexample) +@i(The parameter list should have no spaces), and parameters are separated +by commas. Following the close parenthesis, you may specify other +attributes such as the starting time and voice as shown in the example above. + +A parameter may be an Adagio pitch specification, an Adagio duration, +an Adagio loudness, a number, or an ASCII character within single +quotes, e.g. @t('a') is equivalent to @t(97) because 97 is the decimal +encoding of ``a'' in ASCII. + +The @code(!CALL) may be followed by a limited set of attributes. These are time (@t(T)), voice (@t(V)), and next time (@t(N)). The @code(!CALL) is made at the current time if no time is specified, and the time of the next adagio command is the time of the @code(!CALL) unless a next time is specified. In other words, the default is @t(N0). + +@subsection(Setting C Variables) +In addition to calling C routines, there is another way in which scores +can communicate with C. As with @code(!CALL), specific C code must be linked before these commands can be used. (See Section @ref(set-sec) for details.) The @code(!SETI) command@index(!Seti)@index(seti commnad) sets an integer variable +to a value, and the @code(!SETV) command@index(!Setv)@index(setv command) sets an element of an integer array. +For example, the next line sets the variable @t(delay) to 200 and sets +@t(transposition[5]) to -4 at time 200: +@begin(programexample) +!SETI delay 200 +!SETV transposition 5 -4 T200 +@end(programexample) +As with the @code(!CALL) command, these commands perform their operations at +particular times according to their place in the Adagio score. This makes +it very easy to implement time-varying parameters that control various +aspects of an interactive music system. + diff --git a/docsrc/nyquist/arcsine-fig.ps b/docsrc/nyquist/arcsine-fig.ps new file mode 100644 index 0000000..b15c551 --- /dev/null +++ b/docsrc/nyquist/arcsine-fig.ps @@ -0,0 +1,64 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: arcsine-fig.ps +%%CreationDate: Wed Jul 13 12:12:47 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2413 ASCII Bytes +image +h>[NUO5Ks[!rq_]j8T2[s8N0#hiHgt!ri6"!rq/Mj8T2[s8N0#hk/s/!ri6"s8N(kj8T2[ +s8W-!!2&CrJ,fQKrrKmljo5>[rr<#u!PdORrrE#ss8W*"^Ye/Q!<)oss8N,7n)aQLrVlis +rrJbdjo5>Xrr<#u!PeBjrrDrqs8W*"^\d-m!;HKms8N,7rT4%Zn,E@errJbkjo5>1F* +J*?n4ci*kIs51Tks.AQU!WG=^rrrG[^]4>ol2LbZr;Qs#hiIg;r9=4]a8Gr=s51Tjrr=/,rrN$^ +r;Qiu#J^94-2rrBh2rrKn9oD\m]!'g;Zs8N)6qYpWr!'g2W!It^Ts8W*!^\Ig/_#495s82isJ+ipBrrA\_ +s8N)gs8W*!^Yo.lrrBgls8W*!^Yo.lrrBgls8W*!TA]bLrrBgls8W*!^Yo.lrrBgls8W*!^Yo.l +rrA\Ls8W*!^Yo.lrrBh3rrDfkrrE&qrrCsSrrDrnrrIWLs8O7WrVtdSs7cQ.qu>RQs7cPCqu>RQ +s6ou;qu>RPs6ou;rrN/Xi;`lZs8W*!^Yo.lrrBgls8W*!^Yo.lrrBgls5!_OrrN#rr;QeIn,<7e +n+lq^!r`.KrVlrss8Vrq!qlMArr3'!^X)lY!S@)ErrW&r^]"06rr<#prrMflrVlru^T[V9!S?rA +rrW&sJ,TBKrr<#prrMflrVlru^PDdf!S@#CrrW&r^]"06rr<#prrMfkrVlru^[M.$!S@#CrrW&r +^]"06rr<#prrW)QJ,TBJHcQ*b!Uk+.rrW/fJ,TBKpcnf7s*t~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/bernoulli-fig.ps b/docsrc/nyquist/bernoulli-fig.ps new file mode 100644 index 0000000..6a7cf3d --- /dev/null +++ b/docsrc/nyquist/bernoulli-fig.ps @@ -0,0 +1,1149 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: bernoulli-fig.ps +%%CreationDate: Wed Jul 13 12:13:35 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 312 364 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 348.98334526366023 translate +-20 775 translate +296.98582677165354 -348.98334526366023 scale +% Image geometry +297 349 8 +% Transformation matrix +[ 297 0 0 349 0 0 ] +% Strings to hold RGB-samples per scanline +/rstr 297 string def +/gstr 297 string def +/bstr 297 string def +{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop} +true 3 +%%BeginData: 45884 ASCII Bytes +colorimage +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +r;V +r;V +r;V +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`s_uKW7!IX.hs8N'&rr<'!!!)utr;["7d/X+G!;ZWqiJdX5rr<-#!!)`m"lYF?rr<&Ls8)cs +s7#pd_Z'T9qu;0~> +r;Q`s_uKW7!IX.hs8N'&rr<'!!!)utr;["7d/X+G!;ZWqiJdX5rr<-#!!)`m"lYF?rr<&Ls8)cs +s7#pd_Z'T9qu;0~> +r;Q`s_uKW7!IX.hs8N'&rr<'!!!)utr;["7d/X+G!;ZWqiJdX5rr<-#!!)`m"lYF?rr<&Ls8)cs +s7#pd_Z'T9qu;0~> +r;Q`s_uK`:s8N/Z!,19irr<-#!!)lqrrE*!!h',JpAb-mp](6npAb-mcMn+%!0$s2!1L\&!!)or +J,~> +r;Q`s_uK`:s8N/Z!,19irr<-#!!)lqrrE*!!h',JpAb-mp](6npAb-mcMn+%!0$s2!1L\&!!)or +J,~> +r;Q`s_uK`:s8N/Z!,19irr<-#!!)lqrrE*!!h',JpAb-mp](6npAb-mcMn+%!0$s2!1L\&!!)or +J,~> +r;Q`s_uK`:rr;uus8OIP!!'>)rr<%XI/a0Hd!SR7s8TB!!4)Y)!!*'!!!*$!!<3$!rr<&ts8N*! +rs\,lRf?!ZN'q)!76*fd/*eB +!!:MAI-gk;BE7;s]`?*frr<&rs*t~> +r;Q`s_uK`:rr;uus8OIP!!'>)rr<%XI/a0Hd!SR7s8TB!!4)Y)!!*'!!!*$!!<3$!rr<&ts8N*! +rs\,lRf?!ZN'q)!76*fd/*eB +!!:MAI-gk;BE7;s]`?*frr<&rs*t~> +r;Q`s_uK`:rr;uus8OIP!!'>)rr<%XI/a0Hd!SR7s8TB!!4)Y)!!*'!!!*$!!<3$!rr<&ts8N*! +rs\,lRf?!ZN'q)!76*fd/*eB +!!:MAI-gk;BE7;s]`?*frr<&rs*t~> +r;Q`s_uK`:s8OY/!4)X!2oeqqZ-Ek$,$>Ps8S#X9`U-grr<&rs*t~> +r;Q`s_uK`:s8OY/!4)X!2oeqqZ-Ek$,$>Ps8S#X9`U-grr<&rs*t~> +r;Q`s_uK`:s8OY/!4)X!2oeqqZ-Ek$,$>Ps8S#X9`U-grr<&rs*t~> +r;Q`s_uKW7$[hID9`Y4n!,2B4!<3#u!<<*!!#GTJ!<<'!B`A&4s8N'!rr<'!!!*$!!<)rt!<3#u +!!iN(!<5anI*hlmrrE*!rrE&urr=5B!!*'!!)3Fns8N'!rr<'!rr<'!BE8)4!,2B4!<<'!!;c`q +!<<'"!);n]s%WLm"cQ1?`rMRFrr<&rs*t~> +r;Q`s_uKW7$[hID9`Y4n!,2B4!<3#u!<<*!!#GTJ!<<'!B`A&4s8N'!rr<'!!!*$!!<)rt!<3#u +!!iN(!<5anI*hlmrrE*!rrE&urr=5B!!*'!!)3Fns8N'!rr<'!rr<'!BE8)4!,2B4!<<'!!;c`q +!<<'"!);n]s%WLm"cQ1?`rMRFrr<&rs*t~> +r;Q`s_uKW7$[hID9`Y4n!,2B4!<3#u!<<*!!#GTJ!<<'!B`A&4s8N'!rr<'!!!*$!!<)rt!<3#u +!!iN(!<5anI*hlmrrE*!rrE&urr=5B!!*'!!)3Fns8N'!rr<'!rr<'!BE8)4!,2B4!<<'!!;c`q +!<<'"!);n]s%WLm"cQ1?`rMRFrr<&rs*t~> +r;Q`s_uK`:s8N2S!,2E0!!<0#!<3#u!<<*!!#GS7!<<'!!<3$!s8N'!rr<'!!!*$!!<)rt!<3#u +!"f/1!<:D?!!#a?rr<'!rr<&us8N'%rr<'!s8;rts8N'5rr<'!rr<'!!!*'!!!*$!!<<'!!;c`q +!<<*!!<)rp!;ZWrf`8>Ss8N)9rr<&rs*t~> +r;Q`s_uK`:s8N2S!,2E0!!<0#!<3#u!<<*!!#GS7!<<'!!<3$!s8N'!rr<'!!!*$!!<)rt!<3#u +!"f/1!<:D?!!#a?rr<'!rr<&us8N'%rr<'!s8;rts8N'5rr<'!rr<'!!!*'!!!*$!!<<'!!;c`q +!<<*!!<)rp!;ZWrf`8>Ss8N)9rr<&rs*t~> +r;Q`s_uK`:s8N2S!,2E0!!<0#!<3#u!<<*!!#GS7!<<'!!<3$!s8N'!rr<'!!!*$!!<)rt!<3#u +!"f/1!<:D?!!#a?rr<'!rr<&us8N'%rr<'!s8;rts8N'5rr<'!rr<'!!!*'!!!*$!!<<'!!;c`q +!<<*!!<)rp!;ZWrf`8>Ss8N)9rr<&rs*t~> +r;Q`s_uK`:rr;uu!rkspr;Zcsrr;uus8W*!(B8%Js8N(4rr<'!rr<'!!!*$!!<3$!rVults8N8e +!1Nof!<3!*fr"gErr<'!rr<&us8N'Brr<'!rr>an!<<'!!<3$!s8N'!s(DE4rr?a4!!*'!!!)lq +rrE*!!<>j_rrT(ug%t^L!):?1!!)orJ,~> +r;Q`s_uK`:rr;uu!rkspr;Zcsrr;uus8W*!(B8%Js8N(4rr<'!rr<'!!!*$!!<3$!rVults8N8e +!1Nof!<3!*fr"gErr<'!rr<&us8N'Brr<'!rr>an!<<'!!<3$!s8N'!s(DE4rr?a4!!*'!!!)lq +rrE*!!<>j_rrT(ug%t^L!):?1!!)orJ,~> +r;Q`s_uK`:rr;uu!rkspr;Zcsrr;uus8W*!(B8%Js8N(4rr<'!rr<'!!!*$!!<3$!rVults8N8e +!1Nof!<3!*fr"gErr<'!rr<&us8N'Brr<'!rr>an!<<'!!<3$!s8N'!s(DE4rr?a4!!*'!!!)lq +rrE*!!<>j_rrT(ug%t^L!):?1!!)orJ,~> +r;Q`s_uK`:s8NMd!0$r`!6==(N;ikXrr;uus8W*!(B;&Ja2\1ns(DDs]`8'4!!*$!!<3$!rVult +s8Nb$!87AP!<7EHl0n[drr<'!rr<&us8N'Err<%sciBtW!9q/s!<3$!s8N'!s1JEQ`rNgQ!!*'! +!!*$!!<)rt!!B.G!2oGgrrE*!!b_T'rr3.L!9qi1ZGQVA!;leH~> +r;Q`s_uK`:s8NMd!0$r`!6==(N;ikXrr;uus8W*!(B;&Ja2\1ns(DDs]`8'4!!*$!!<3$!rVult +s8Nb$!87AP!<7EHl0n[drr<'!rr<&us8N'Err<%sciBtW!9q/s!<3$!s8N'!s1JEQ`rNgQ!!*'! +!!*$!!<)rt!!B.G!2oGgrrE*!!b_T'rr3.L!9qi1ZGQVA!;leH~> +r;Q`s_uK`:s8NMd!0$r`!6==(N;ikXrr;uus8W*!(B;&Ja2\1ns(DDs]`8'4!!*$!!<3$!rVult +s8Nb$!87AP!<7EHl0n[drr<'!rr<&us8N'Err<%sciBtW!9q/s!<3$!s8N'!s1JEQ`rNgQ!!*'! +!!*$!!<)rt!!B.G!2oGgrrE*!!b_T'rr3.L!9qi1ZGQVA!;leH~> +r;Q`s_uKW7$]O?Ms0>?!N;rnX!<3#u!<<*!!<<'5Z;"'!s8UG?B^#Ksrr<'!!!*$!!<)rr!#'&! +s8N'!s6uHW!.=&2ciAIn!!*#urr=>E!!(A?I/hPfB^#Kss3Lanrr<'!s0>?nZN'q)!<<'!!<3$! +rVult!lk;"o)J^is8W*!rVm#bMuWj`_>aK8qu;0~> +r;Q`s_uKW7$]O?Ms0>?!N;rnX!<3#u!<<*!!<<'5Z;"'!s8UG?B^#Ksrr<'!!!*$!!<)rr!#'&! +s8N'!s6uHW!.=&2ciAIn!!*#urr=>E!!(A?I/hPfB^#Kss3Lanrr<'!s0>?nZN'q)!<<'!!<3$! +rVult!lk;"o)J^is8W*!rVm#bMuWj`_>aK8qu;0~> +r;Q`s_uKW7$]O?Ms0>?!N;rnX!<3#u!<<*!!<<'5Z;"'!s8UG?B^#Ksrr<'!!!*$!!<)rr!#'&! +s8N'!s6uHW!.=&2ciAIn!!*#urr=>E!!(A?I/hPfB^#Kss3Lanrr<'!s0>?nZN'q)!<<'!!<3$! +rVult!lk;"o)J^is8W*!rVm#bMuWj`_>aK8qu;0~> +r;Q`sJcF$q!U4:rs8N(lrr<&rs*t~> +r;Q`sJcF$q!U4:rs8N(lrr<&rs*t~> +r;Q`sJcF$q!U4:rs8N(lrr<&rs*t~> +r;Q`sJcF$q!K?"9s8N(lrr<&rs*t~> +r;Q`sJcF$q!K?"9s8N(lrr<&rs*t~> +r;Q`sJcF$q!K?"9s8N(lrr<&rs*t~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sp&G!krr;rtJcC<$qYpNqqu;0~> +r;Q`sp&G!krr;rtJcC<$qYpNqqu;0~> +r;Q`sp&G!krr;rtJcC<$qYpNqqu;0~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGWI!!)orJ,~> +r;Q`sp&Fsj!WN0!rr<&rs8)eIJ<,6Vrr<&rs*t~> +r;Q`sp&Fsj!WN0!rr<&rs8)eIJ<,6Vrr<&rs*t~> +r;Q`sp&Fsj!WN0!rr<&rs8)eIJ<,6Vrr<&rs*t~> +r;Q`so)AakrrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`sp&G!ks8N'!rr2ruq#: +r;Q`sp&G!ks8N'!rr2ruq#: +r;Q`sp&G!ks8N'!rr2ruq#: +r;Q`spAY*mrr3$"rrE&u!!)orqZ)2_OMCjHq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)orqZ)2_OMCjHq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)orqZ)2_OMCjHq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNkbXFq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+pAjEm!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+pAjEm!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+pAjEm!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;ZWp!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;ZWp!9h2uJGK3F!;leH~> +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruqu?NnJ\\V-!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruqu?NnJ\\V-!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruqu?NnJ\\V-!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lr;Z`rp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&>!lr;Z`rp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&>!lr;Z`rp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAb'ks8N'!rr2ruq#: +r;Q`spAb'ks8N'!rr2ruq#: +r;Q`spAb'ks8N'!rr2ruq#: +r;Q`spAY*mrr3$"rrE&u!!)orqZ)2_ZbQP@q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)orqZ)2_ZbQP@q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)orqZ)2_ZbQP@q>UEpkeI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sp&Fsjs8W&up\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&Fsjs8W&up\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&Fsjs8W&up\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAb'ks8N'!rr2ruqu?NnJ\\V-!!)h_!!)5u!.anF!!)orJ,~> +r;Q`spAb'ks8N'!rr2ruqu?NnJ\\V-!!)h_!!)5u!.anF!!)orJ,~> +r;Q`spAb'ks8N'!rr2ruqu?NnJ\\V-!!)ip!!)5u!.anF!!)orJ,~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#: +r;Q`sp&>0qrrE*!!<2uu!;QQo!.hqj^]4B1R/d6N^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!.hqj^]4B1R/d6N^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!.hqj^]4B1rr<&_^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!.hqj^]4B1R/d6N^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!.hqj^]4B1R/d6N^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!.hqj^]4B1rr<&_^]8o\rr<&rs*t~> +r;Q`spAYUEpqu;0~> +r;Q`spAYUEpqu;0~> +r;Q`spAYUEpkeI1Kq>UEpqu;0~> +r;Q`spAb$j!WN0!rr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<%M^p1ZT!;ZWp!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^p1ZT!;ZWp!9h2uJGK3F!;leH~> +r;Q`soD\djrr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so)AakrrE&u!!)orqZ)2_ZbQP@q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ)2_ZbQP@q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ)2_ZbQP@q>UEpkeI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScZ+p>>q>UEpkeI1Kq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYJ\\P+!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4r+.J\]"8!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4r+.J\]"8!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4r+.J\]"8!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)r4!!)lq!!%Sc^VBgLq>UEpkeI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)r4!!)lq!!%Sc^VBgLq>UEpkeI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)r4!!)lq!!%Sc^VBgLq>UEpkeI1Kq>UEpqu;0~> +r;Q`soD\mms8N)urr<&rs8)fq^]4B2R/d5<^q[Yb!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&rs8)fq^]4B2R/d5<^q[Yb!;W#_!9h2uJGK3F!;leH~> +r;Q`soD\mms8N)urr<&rs8)fq^]4B2rr<%M^q[Yb!;ZWp!9h2uJGK3F!;leH~> +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`spAb$js8W&up\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3nr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrVuisp\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrVuisp\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrVuisp\t3nr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sp&G$lrr2rurr2ruq#: +r;Q`sp&G$lrr2rurr2ruq#: +r;Q`sp&G$lrr2rurr2ruq#: +r;Q`spAY0orrE&u!!*#u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`spAY0orrE&u!!*#u!!)fo!!)r4!!)k`!!%Sc^VBgLq3_3_keI1Kq>UEpqu;0~> +r;Q`spAY0orrE&u!!*#u!!)fo!!)r4!!)lq!!%Sc^VBgLq>UEpkeI1Kq>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruqu?NnrkJL6qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruqu?NnrkJL6qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruqu?NnrkJL6qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrVuisp\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrVuisp\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`so`"mkrVuisp\t3nr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sir8uYr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`sn,N@ep\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sn,N@ep\t3nr4i:4qO%<`J\]%9!!)h_!!)5u!.anF!!)orJ,~> +r;Q`sn,N@ep\t3nr4i:4qYpNqJ\]%9!!)ip!!)5u!.anF!!)orJ,~> +r;Q`snG`Igrr2ruq#: +r;Q`snG`Igrr2ruq#: +r;Q`snG`Igrr2ruq#: +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpr4i:4m_Af&q>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpr4i:4m_Af&q>UEpqu;0~> +r;Q`snG`Igrr2ruqu;3IM#dAO!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IM#dAO!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IM#dAO!!)orJ,~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`sn,N@ep\t3nmf*7emJd.dmf*7emJd.dmf*7emf*7emf*7emf*7emJd.dmf*7emJd.dmf*7e +q>UEpqu;0~> +r;Q`sn,N@ep\t3nmf*7emJd.dmf*7emJd.dmf*7emf*7emf*7emf*7emJd.dmf*7emJd.dmf*7e +q>UEpqu;0~> +r;Q`sn,N@ep\t3nmf*7emJd.dmf*7emJd.dmf*7emf*7emf*7emf*7emJd.dmf*7emJd.dmf*7e +q>UEpqu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`s])Vd1gA_-QgAh0QgAh0QW;chtqu;0~> +r;Q`s])Vd1gA_-QgAh0QgAh0QW;chtqu;0~> +r;Q`s])Vd1gA_-QgAh0QgAh0QW;chtqu;0~> +r;Q`sjT#5[gA_6Ts8N)Rs8N)SrrW9$rrCjS!s&B$!8RSS!71ZF!;leH~> +r;Q`sjT#5[gA_6Ts8N)Rs8N)SrrW9$rrCjS!s&B$!8RSS!71ZF!;leH~> +r;Q`sjT#5[gA_6Ts8N)Rs8N)SrrW9$rrCjS!s&B$!8RSS!71ZF!;leH~> +r;Q`sjo5G`s8N'!h#@?Srr2ruh#@EUrrCmT"9AK%!!(jT!s&B$!8RSS!71ZF!;leH~> +r;Q`sjo5G`s8N'!h#@?Srr2ruh#@EUrrCmT"9AK%!!(jT!s&B$!8RSS!71ZF!;leH~> +r;Q`sjo5G`s8N'!h#@?Srr2ruh#@EUrrCmT"9AK%!!(jT!s&B$!8RSS!71ZF!;leH~> +r;Q`sjo5;\rr;uuh>[HTrr2ruh#@EUs8W&ui;Wu]rrE*!!!(pV!W`9#r;baTrrCFG!!)orJ,~> +r;Q`sjo5;\rr;uuh>[HTrr2ruh#@EUs8W&ui;Wu]rrE*!!!(pV!W`9#r;baTrrCFG!!)orJ,~> +r;Q`sjo5;\rr;uuh>[HTrr2ruh#@EUs8W&ui;Wu]rrE*!!!(pV!W`9#r;baTrrCFG!!)orJ,~> +r;Q`sjo5;\rVlith>[HTrr3'#s8N)Vrr`?%rr<&Vs8E#trr<&Us8N)urr<&VrrN3#!7CfH!;leH~> +r;Q`sjo5;\rVlith>[HTrr3'#s8N)Vrr`?%rr<&Vs8E#trr<&Us8N)urr<&VrrN3#!7CfH!;leH~> +r;Q`sjo5;\rVlith>[HTrr3'#s8N)Vrr`?%rr<&Vs8E#trr<&Us8N)urr<&VrrN3#!7CfH!;leH~> +r;Q`sjo>>\rVlitgA_6Trr<&Us8E!!rrCsVrrE&u!!(jT!!*#u!!(gS!!(II!!)orJ,~> +r;Q`sjo>>\rVlitgA_6Trr<&Us8E!!rrCsVrrE&u!!(jT!!*#u!!(gS!!(II!!)orJ,~> +r;Q`sjo>>\rVlitgA_6Trr<&Us8E!!rrCsVrrE&u!!(jT!!*#u!!(gS!!(II!!)orJ,~> +r;Q`sjT#5[rr2rug]%?Urr<&Ts8N)Rs8N'#rr<&Ts8N*!rr<&Rrr<&Jrr<&rs*t~> +r;Q`sjT#5[rr2rug]%?Urr<&Ts8N)Rs8N'#rr<&Ts8N*!rr<&Rrr<&Jrr<&rs*t~> +r;Q`sjT#5[rr2rug]%?Urr<&Ts8N)Rs8N'#rr<&Ts8N*!rr<&Rrr<&Jrr<&rs*t~> +r;Q`sj8],Z!ri6#jT#5[q>^HpjT#5[qu6WriW&oXqYpNqirB#Yqu?Wqg&D$PeGfLKqu;0~> +r;Q`sj8],Z!ri6#jT#5[q>^HpjT#5[qu6WriW&oXqYpNqirB#Yqu?Wqg&D$PeGfLKqu;0~> +r;Q`sj8],Z!ri6#jT#5[q>^HpjT#5[qu6WriW&oXqYpNqirB#Yqu?Wqg&D$PeGfLKqu;0~> +r;Q`siVrlXj8T5^s8N'!qu6WrjSo>_s8N'!h>[TXs8N'!h>[TXs8N'!V#LDpqu;0~> +r;Q`siVrlXj8T5^s8N'!qu6WrjSo>_s8N'!h>[TXs8N'!h>[TXs8N'!V#LDpqu;0~> +r;Q`siVrlXj8T5^s8N'!qu6WrjSo>_s8N'!h>[TXs8N'!h>[TXs8N'!V#LDpqu;0~> +r;Q`s_Z'T9rr;uurr;uuj8T)Zrr;uus8W*!ir8uYrr;uus8W*!ir8uYrr;uus8W*!WW)ququ;0~> +r;Q`s_Z'T9rr;uurr;uuj8T)Zrr;uus8W*!ir8uYrr;uus8W*!ir8uYrr;uus8W*!WW)ququ;0~> +r;Q`s_Z'T9rr;uurr;uuj8T)Zrr;uus8W*!ir8uYrr;uus8W*!ir8uYrr;uus8W*!WW)ququ;0~> +r;Q`s_Z'T9rVlithZ!QUrVlithZ!QUrVlithZ!QUrVlitV>gMqqu;0~> +r;Q`s_Z'T9rVlithZ!QUrVlithZ!QUrVlithZ!QUrVlitV>gMqqu;0~> +r;Q`s_Z'T9rVlithZ!QUrVlithZ!QUrVlithZ!QUrVlitV>gMqqu;0~> +r;Q`s_Z0W9rVlithuE]VrVlithuE]VrVlithuE]VrVlitVZ-Vrqu;0~> +r;Q`s_Z0W9rVlithuE]VrVlithuE]VrVlithuE]VrVlitVZ-Vrqu;0~> +r;Q`s_Z0W9rVlithuE]VrVlithuE]VrVlithuE]VrVlitVZ-Vrqu;0~> +r;Q`s_>jN8rr2ruhZ*TUrr2ruhZ*TUrr2ruhZ*TUrr2ruVZ-Vrqu;0~> +r;Q`s_>jN8rr2ruhZ*TUrr2ruhZ*TUrr2ruhZ*TUrr2ruVZ-Vrqu;0~> +r;Q`s_>jN8rr2ruhZ*TUrr2ruhZ*TUrr2ruhZ*TUrr2ruVZ-Vrqu;0~> +r;Q`s_#OE7!ri6#h>dKT!ri6#h>dKT!ri6#h>dKT!ri6#VZ-Vrqu;0~> +r;Q`s_#OE7!ri6#h>dKT!ri6#h>dKT!ri6#h>dKT!ri6#VZ-Vrqu;0~> +r;Q`s_#OE7!ri6#h>dKT!ri6#h>dKT!ri6#h>dKT!ri6#VZ-Vrqu;0~> +r;Q`s^Ae05g&D$Pg&D$Pg&D$PV#LDpqu;0~> +r;Q`s^Ae05g&D$Pg&D$Pg&D$PV#LDpqu;0~> +r;Q`s^Ae05g&D$Pg&D$Pg&D$PV#LDpqu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;V +r;V +r;V +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/beta-fig.ps b/docsrc/nyquist/beta-fig.ps new file mode 100644 index 0000000..eb9cda6 --- /dev/null +++ b/docsrc/nyquist/beta-fig.ps @@ -0,0 +1,64 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: beta-fig.ps +%%CreationDate: Wed Jul 13 12:13:53 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +-40 760 translate +%0 176 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2392 ASCII Bytes +image +h>[QVIt-MY!ri6"!rfraj8T2[s8N0#It-MY!ri6"!rfqVj8T2[s8N0"^OP;D!ri6"!rmb"j8T2[ +s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[ +s8W-!!.X&/!ri6"s8N'`j8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[ +s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N'`j8T2[ +s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[ +s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N'`j8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[ +s8W-!!.X&/!ri6"s8N(Kj8T2[s8W-!!.X&/!ri6"s8N(Kj8T2[s8N0#5C__n!ri6"!ri4Lj8T2[ +s8N0"It-MY!ri6"!rfqVj8T2[s8N0"^OP;D!r`0!!rd\!j8T2Zs8W-!!.X&/!r`0!s8N(Kj8T2Z +s8W-!!.X&/!r`0!s8N(Kj8T2Zs8W-!!.X&/!r`0!s8N(Kj8T2Zs8W-!!.X&/!r`0!s8N'`j8T2Z +s8W-!!.X&/!r`0!s8N(Kj8T2Zs8W-!!.X&/!r`0!s8N(Kj8T2Zs8W-!!.X&/!r`0!s8N(Kj8T2Z +s8W-!!.X&/!r`0!s8N(Kj8T2Zs8W-!!.X&/!r`0!s8N'`j8T2Zs8W-!!.X&/!r`0!s8N(Kj8T2Z +s8W-!!.X&/!r`0!s8N(Kj8T2Zs8W-!!.X&/!r`0!s8N(Kj8T2Xs8W-!!.X&/!rN#ts8N(Kj8T2X +s8W-!!.X&/!rN#ts8N'`j8T2Xs8W-!!.X&/!rN#ts8N(Kj8T2Xs8W-!!.X&/!rN#ts8N(Kj8T2X +s8W-!!.X&/!rN#ts8N(Kj8T2Xs8N0#^OP;D!rN#t!rkK7j8T2Xs8N0"^OP;D!rN#t!ra8`j8T2X +s8N0#^OP;D!rN#t!rj?lj8T2Xs8W-!!.X&/!rN#ts8N(Kj8T2Xs8W-!!.X&/!r)`ps8N(Kj8T2T +s8W-!!.X&/!r)`ps8N(Kj8T2Ts8W-!!'fND!r)`ps8N'`j8T2Ts8W-!!'fND!r)`ps8N'`j8T2T +s8W-!!'fND!r)`ps8N'`j8T2Ls8W-!!'fND!q60hs8N'`j8T2Ls8W-!!'fND!q60hs8N'`j8T2L +s8W-!!'fND!q60hs8N'`j8T2Ls8W-!!'fND!oO%Xs8N'`j8T2[rVuot!.3i-!<)lrs8N(Gjo5>XrVuot!.3i-!;HHls8N(Ijo5>L +rVuot!.Eu/!2'5is8N(Jjo5=1rVuots*s53!;ucps8N+L^ZYUsoDJXgrrG@!kPkOCr;Zfs!Is"j +rrN+Kr;Zfs!Is:rrrDTds8W*"J,/=.!0@$Ws8N.Mr]f]J!Vh0As8W*#J,dRSrr<<#s8W*$J,f:n +m/I($q>^Kp"+U@NKC/[>n3?aKs8N4Os8W!-n,EFX&,?2)rr@QJrrVZi5P4sXrVup/p](9n!'gD] +!Pea1rrTt9!VHElrr@QGrrE&m!!#7Ss8W*!J)LA,rr@Q,s8W*!J)LA,rr@Q,s8W*!J)LA,rr@Q, +s8W*!J,K +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/bilateral-fig.ps b/docsrc/nyquist/bilateral-fig.ps new file mode 100644 index 0000000..c85e0c9 --- /dev/null +++ b/docsrc/nyquist/bilateral-fig.ps @@ -0,0 +1,65 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: bilateral-fig.ps +%%CreationDate: Wed Jul 13 12:14:08 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2463 ASCII Bytes +image +nG`Lfn,MtY!r)Khn,MtY!pfa_n,MtY!pf[]n,MtY"7,sc5Oe^DrrVN_rpTmXrrVr.rpTmVrrDuc +s7$$hr."59nG`OeJ+3L-rrN%InGi"X!W7H:s7$$hr."59nG`Oc^[V9mrrMu2nGi"X!W'S#s7$$h +qS2P"nG`Oc5Oe^BrrMu2nGi"X!VYF?s7$$hp>>B>nG`O_hsg[8rrMiNnGi"X!VTmis7$$hp@%MN +nG`O_n*pAHrrMQVnGi"X!UfFGs7$$hme?5NnG`OWp[J4PrrLu#nGi"X!T*S?s7$$hhY6O>o)Agd +rndPAs760llhnKonGi(Z"7,ftqsaXVrr_T^5!/96o)AgXrkA:!s760lpUi]enGi"X!Ik":s7$$h +If8d9nG`Ns760nrr;uts*sV>o)Aml +s8INJJ+EX1rrrB$rr<#5o)J:\"oJ?!s8Tk)s760nqu?Zqs1e.)o)Amjs8N&uht$grr`#qs8N#t!8mDJoD\pe +s8W)trrDNZs7?6mn,NFerr2ueoDeF^"7Q9irr2otn+6SNrr_0Ys8N#t!;H*boD\pMs8W)trrDfb +s7?6q^]4?5J,fQGoDeF^"2Fm9rr2otqt'jZrr[cNs8N#t!<)NhoD\oBs8W)trrE#hs7H6js8VE`r]gA]!5J4,p&>3is8VE`rqucrht@$B +rrqlks7`aHr;Qccp&F^b!8mbT!<2or!:TU\p&>$,rVllsr;Qckp&F^b!.XtI!<2or!;lHhp&>#A +rVlotJ,TBIrUp3arrE&rrrE&rrrE&ks7ZHmrVZZqrql]qJ+ip9rrDrorrE&qrrBh-s7ZHmp\b$k +rql]qhtI*DrrDNcrrE&qrrDN]s7ZHmhu*KSrql]qoCi4Xrr>:]rrN+Kr;QcqpAame!;u`o!<2lq +!WITCs7cNnoDAOfrqcWpTD/B[rrDNbrrE&prrDN^s7cNnTDSWgrqcWpoCr:[rrN+Kqu6ZqqYpQo +p]($g!;ZKk!WITGrrN+Kq#C-h!6=s9!<2fo!2'&dq#:=YqYpQpq>UHXq#C0i!;QBi!<2fo!;ZEi +q>UH8q>UHoq>UKp5Pb?Trr>:ZrrE&nrrC+8s8)`qnG*"`rqQKopj`/?qu6]r&,?/*rdX_C!/(.J +qu6YIp\t6mp\t9l&,ZD)rrMV=p\t6mpAY0_J,K?FrrN*0pAY-lp&>&C&,lP.rr`0!!It%I!:Tjc +!<2lq!:Tjc"o[ojJ,fNns82ufs*sqG^]"3$s*sqGhu$Lr;Qcqr;Z]p!2'2h!:0=X!3c>#!;ZQm +r;Qb(r;Qckp&>$Lr;Qcir;Z`q!TO^hrrN%Ap&>$Lr;Qcdr;Z]p!8m_S!:TU\!5JI3!<)iqr;QbX +r;QcWp&>#Qr;Qclr;YUQJ,~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/binomial-fig.ps b/docsrc/nyquist/binomial-fig.ps new file mode 100644 index 0000000..9aa5eed --- /dev/null +++ b/docsrc/nyquist/binomial-fig.ps @@ -0,0 +1,1197 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: binomial-fig.ps +%%CreationDate: Wed Jul 13 12:14:23 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 312 364 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 348.98334526366023 translate +-20 775 translate +296.98582677165354 -348.98334526366023 scale +% Image geometry +297 349 8 +% Transformation matrix +[ 297 0 0 349 0 0 ] +% Strings to hold RGB-samples per scanline +/rstr 297 string def +/gstr 297 string def +/bstr 297 string def +{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop} +true 3 +%%BeginData: 54218 ASCII Bytes +colorimage +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +r;V +r;V +r;V +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sc2[\A"FTJ6!!)3^rrDlprrE#tr;["7d/X+G!;ZX#iJdg:!!*$!!;6?qiJdg:!!(^P!:]md +j8T,KquFt@!!)orJ,~> +r;Q`sc2[\A"FTJ6!!)3^rrDlprrE#tr;["7d/X+G!;ZX#iJdg:!!*$!!;6?qiJdg:!!(^P!:]md +j8T,KquFt@!!)orJ,~> +r;Q`sc2[\A"FTJ6!!)3^rrDlprrE#tr;["7d/X+G!;ZX#iJdg:!!*$!!;6?qiJdg:!!(^P!:]md +j8T,KquFt@!!)orJ,~> +r;Q`sc2[eDs8N/Z!,1*drrE#trrE*!!h',JpAb-mr;Zcsp&G$lec,^(!1MjG!ndRBao;>@qu;0~> +r;Q`sc2[eDs8N/Z!,1*drrE#trrE*!!h',JpAb-mr;Zcsp&G$lec,^(!1MjG!ndRBao;>@qu;0~> +r;Q`sc2[eDs8N/Z!,1*drrE#trrE*!!h',JpAb-mr;Zcsp&G$lec,^(!1MjG!ndRBao;>@qu;0~> +r;Q`sc2[eDrr;uu./s8Irr<&GHqhufs0>?!ZN'q)!76*f]uNiAd/O(Gs65IB!,1'c!!)utrrE*!% +-[b\rr<'!l$NI2N9U9@%fZM/rr<&49oT,P!!*'!qZ%0,!!*'!Z:t>)rr<&GHqhuas8N'$d!SR7o +D\m*!6=j6rr<,I9mlF0!keTSao;>@qu;0~> +r;Q`sc2[eDrr;uu./s8Irr<&GHqhufs0>?!ZN'q)!76*f]uNiAd/O(Gs65IB!,1'c!!)utrrE*!% +-[b\rr<'!l$NI2N9U9@%fZM/rr<&49oT,P!!*'!qZ%0,!!*'!Z:t>)rr<&GHqhuas8N'$d!SR7o +D\m*!6=j6rr<,I9mlF0!keTSao;>@qu;0~> +r;Q`sc2[eDrr;uu./s8Irr<&GHqhufs0>?!ZN'q)!76*f]uNiAd/O(Gs65IB!,1'c!!)utrrE*!% +-[b\rr<'!l$NI2N9U9@%fZM/rr<&49oT,P!!*'!qZ%0,!!*'!Z:t>)rr<&GHqhuas8N'$d!SR7o +D\m*!6=j6rr<,I9mlF0!keTSao;>@qu;0~> +r;Q`sc2[eDs8OV.!4)V)!<3$!^$,Mks1JEQ`rNgQ!!'_%!!'=h!,2B4!<7H"s60MXrr<&ts8N)u +s8N'Srr<'!BE8(s!.=eH!<<'!!<3$!VoJe8rr<'!rr<'!!!*'!!!*&4!6<+[]`8&Gkl=HSs8N'$ +^$,MkrVu`prVm"Z!)3HPq>^Hp"/j0>Vu?Ym!;c]uMuZQPN6D5$!;leH~> +r;Q`sc2[eDs8OV.!4)V)!<3$!^$,Mks1JEQ`rNgQ!!'_%!!'=h!,2B4!<7H"s60MXrr<&ts8N)u +s8N'Srr<'!BE8(s!.=eH!<<'!!<3$!VoJe8rr<'!rr<'!!!*'!!!*&4!6<+[]`8&Gkl=HSs8N'$ +^$,MkrVu`prVm"Z!)3HPq>^Hp"/j0>Vu?Ym!;c]uMuZQPN6D5$!;leH~> +r;Q`sc2[eDs8OV.!4)V)!<3$!^$,Mks1JEQ`rNgQ!!'_%!!'=h!,2B4!<7H"s60MXrr<&ts8N)u +s8N'Srr<'!BE8(s!.=eH!<<'!!<3$!VoJe8rr<'!rr<'!!!*'!!!*&4!6<+[]`8&Gkl=HSs8N'$ +^$,MkrVu`prVm"Z!)3HPq>^Hp"/j0>Vu?Ym!;c]uMuZQPN6D5$!;leH~> +r;Q`sc2[\A.X^ac!!*$!!<<'!!<6^4s8N(4rr<'!rr<'!rr<'!!!*'!iNdh2!<3$!rVultrr;uu +#QFc(s%NK@d/O(F!<<*!!$V@B!<<'!:&b1ns8N'!rr<'!rr<'!BE8)4!,)?4s8N'!qZ$Qqs8W*! +oD\uQ:$K[uRem'a!<<'"!);t_"cQ1?`rMRPrr<&rs*t~> +r;Q`sc2[\A.X^ac!!*$!!<<'!!<6^4s8N(4rr<'!rr<'!rr<'!!!*'!iNdh2!<3$!rVultrr;uu +#QFc(s%NK@d/O(F!<<*!!$V@B!<<'!:&b1ns8N'!rr<'!rr<'!BE8)4!,)?4s8N'!qZ$Qqs8W*! +oD\uQ:$K[uRem'a!<<'"!);t_"cQ1?`rMRPrr<&rs*t~> +r;Q`sc2[\A.X^ac!!*$!!<<'!!<6^4s8N(4rr<'!rr<'!rr<'!!!*'!iNdh2!<3$!rVultrr;uu +#QFc(s%NK@d/O(F!<<*!!$V@B!<<'!:&b1ns8N'!rr<'!rr<'!BE8)4!,)?4s8N'!qZ$Qqs8W*! +oD\uQ:$K[uRem'a!<<'"!);t_"cQ1?`rMRPrr<&rs*t~> +r;Q`sc2[eDs8OV&!,2B4!<3$!s8N'!rr<'!rr<'!!!*'!!!*'!!!*$!!<:CGRcsePrr<&ts8N)u +s8N'Krr<'!cqOK?:!in?!<<'!!<3$!s8N'!rr<'!rr<'!!!*'!!!*$!!<<)t!<<*!!;c`q!<<*! +!<)rp!;ZZp!;c`q!<<*!!<)rp!;?Hm!6kHC!;leH~> +r;Q`sc2[eDs8OV&!,2B4!<3$!s8N'!rr<'!rr<'!!!*'!!!*'!!!*$!!<:CGRcsePrr<&ts8N)u +s8N'Krr<'!cqOK?:!in?!<<'!!<3$!s8N'!rr<'!rr<'!!!*'!!!*$!!<<)t!<<*!!;c`q!<<*! +!<)rp!;ZZp!;c`q!<<*!!<)rp!;?Hm!6kHC!;leH~> +r;Q`sc2[eDs8OV&!,2B4!<3$!s8N'!rr<'!rr<'!!!*'!!!*'!!!*$!!<:CGRcsePrr<&ts8N)u +s8N'Krr<'!cqOK?:!in?!<<'!!<3$!s8N'!rr<'!rr<'!!!*'!!!*$!!<<)t!<<*!!;c`q!<<*! +!<)rp!;ZZp!;c`q!<<*!!<)rp!;?Hm!6kHC!;leH~> +r;Q`sc2[eDrr;uu./s8Irr<'!rr<'!BE8)4!,2B4!<<'!!<<'!!<3$!rr<'!rr<'!!!)utrrE*! +"mH#Urr<&us")j$!) +r;Q`sc2[eDrr;uu./s8Irr<'!rr<'!BE8)4!,2B4!<<'!!<<'!!<3$!rr<'!rr<'!!!)utrrE*! +"mH#Urr<&us")j$!) +r;Q`sc2[eDrr;uu./s8Irr<'!rr<'!BE8)4!,2B4!<<'!!<<'!!<3$!rr<'!rr<'!!!)utrrE*! +"mH#Urr<&us")j$!) +r;Q`sc2[eDs8OV.!0$pX!<3$!s8N'!s1JEQ`rNgQ!!*'!!!*'!!!*$!!<5anl,Nc(rr<&ts8N*! +s#?GIg&D$Ps*Oh2n,R/%!!*'!!!*$!!2n0DVuLE1l+I&srr<'!rr<'!]`?*n!5/@4s8N'!rr<&t +s8N*!s8N)jrs3uPl-KF9rr<&ts8N'$VpGFAoDegj#60&Nl-KF9bl7YCqu;0~> +r;Q`sc2[eDs8OV.!0$pX!<3$!s8N'!s1JEQ`rNgQ!!*'!!!*'!!!*$!!<5anl,Nc(rr<&ts8N*! +s#?GIg&D$Ps*Oh2n,R/%!!*'!!!*$!!2n0DVuLE1l+I&srr<'!rr<'!]`?*n!5/@4s8N'!rr<&t +s8N*!s8N)jrs3uPl-KF9rr<&ts8N'$VpGFAoDegj#60&Nl-KF9bl7YCqu;0~> +r;Q`sc2[eDs8OV.!0$pX!<3$!s8N'!s1JEQ`rNgQ!!*'!!!*'!!!*$!!<5anl,Nc(rr<&ts8N*! +s#?GIg&D$Ps*Oh2n,R/%!!*'!!!*$!!2n0DVuLE1l+I&srr<'!rr<'!]`?*n!5/@4s8N'!rr<&t +s8N*!s8N)jrs3uPl-KF9rr<&ts8N'$VpGFAoDegj#60&Nl-KF9bl7YCqu;0~> +r;Q`sc2[\A.ZEWl!!*$!!<<'!!<<))9hhqnrr<'!rr<'!rr<'!!!*&G9hhnn!<3$!rVufr3,%"F +rr<'!n +r;Q`sc2[\A.ZEWl!!*$!!<<'!!<<))9hhqnrr<'!rr<'!rr<'!!!*&G9hhnn!<3$!rVufr3,%"F +rr<'!n +r;Q`sc2[\A.ZEWl!!*$!!<<'!!<<))9hhqnrr<'!rr<'!rr<'!!!*&G9hhnn!<3$!rVufr3,%"F +rr<'!n +r;Q`sJcFU,!U4:WrrM@trVultZ2Xe(qu;0~> +r;Q`sJcFU,!U4:WrrM@trVultZ2Xe(qu;0~> +r;Q`sJcFU,!U4:WrrM@trVultZ2Xe(qu;0~> +r;Q`sJcFU,!K?!srrJ);rVultZ2Xe(qu;0~> +r;Q`sJcFU,!K?!srrJ);rVultZ2Xe(qu;0~> +r;Q`sJcFU,!K?!srrJ);rVultZ2Xe(qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`soD\djrr;rtJcC<$qYpNqqu;0~> +r;Q`soD\djrr;rtJcC<$qYpNqqu;0~> +r;Q`soD\djrr;rtJcC<$qYpNqqu;0~> +r;Q`so`+pks8N'!rr2ruJcC<$qu6Wrqu;0~> +r;Q`so`+pks8N'!rr2ruJcC<$qu6Wrqu;0~> +r;Q`so`+pks8N'!rr2ruJcC<$qu6Wrqu;0~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s82fr!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s82fr!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s82fr!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s82fr!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s82fr!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s82fr!;leH~> +r;Q`spAY +r;Q`spAY +r;Q`spAY +r;Q`spAb$j!WN0!rr<&orr<%M^lH21JGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<%M^lH21JGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<%M^lH21JGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^lH21JGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^lH21JGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^lH21JGK3F!;leH~> +r;Q`soD\djrr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYJ\[;]!.anF!!)orJ,~> +r;Q`sir8uYS\XjtJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\XjtJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\XjtJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;osq#: +r;Q`sp&G!krr;osq#: +r;Q`sp&G!krr;osq#: +r;Q`spAY*mrr3'#s8N)lrr<%i^]4B.R/d5<_#M1MJGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<%i^]4B.R/d5<_#M1MJGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<%i^]4B.rr<%M_#M1MJGK3F!;leH~> +r;Q`so)AakrrD]k!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrD]k!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrD]k!!&S*!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`so`+pks8W#tp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`so`+pks8W#tp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`so`+pks8W#tp\t3nS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`so)A[ir;Q`squ?NnT>1F,p6bm\J\_<$!.anF!!)orJ,~> +r;Q`so)A[ir;Q`squ?NnT>1F,p6bm\J\_<$!.anF!!)orJ,~> +r;Q`so)A[ir;Q`squ?NnT>1F,pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`so)A[ir;Q`sq#: +r;Q`so)A[ir;Q`sq#: +r;Q`so)A[ir;Q`sq#: +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!&S*!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so)AakrrE&u!!)orqZ*8(!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ*8(!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ*8(!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!&S*!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!&S*!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;osq#: +r;Q`sp&G!krr;osq#: +r;Q`sp&G!krr;osq#: +r;Q`spAY*mrr3'#s8N)lrr<%i^]4B.R/d5<_#M1MJGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<%i^]4B.R/d5<_#M1MJGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<%i^]4B.rr<%M_#M1MJGK3F!;leH~> +r;Q`so)AakrrD]k!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrD]k!!&S*!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrD]k!!&S*!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`so)A^js8;rlrr<%i^]4B.R/d5<_#M1MJGK3F!;leH~> +r;Q`so)A^js8;rlrr<%i^]4B.R/d5<_#M1MJGK3F!;leH~> +r;Q`so)A^js8;rlrr<%i^]4B.rr<%M_#M1MJGK3F!;leH~> +r;Q`soD\djqu6Wrqu?NnT>1F,p6bm\J\_<$!.anF!!)orJ,~> +r;Q`soD\djqu6Wrqu?NnT>1F,p6bm\J\_<$!.anF!!)orJ,~> +r;Q`soD\djqu6Wrqu?NnT>1F,pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`so`"mkqYpNqq#: +r;Q`so`"mkqYpNqq#: +r;Q`so`"mkqYpNqq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`spAb$js8W&up\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3nS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3nS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uYS\P4*pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YO.>n%\o'p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YO.>n%\o'p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YO.>n%\o'pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]YFLIopGd[nA##(p6bm\J\_<$!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]YFLIp&>!lnA##(pAY*mJ\_<$!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'[I!!)\[!!)N(!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'[I!!)\[!!)N(!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'[I!!)]l!!)N(!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'[I!!)\[!!)N(!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'[I!!)\[!!)N(!!)_\!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'[I!!)]l!!)N(!!)`m!!%Scs1eVbq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ+@G!!)\[!!)N(!!)_\!!)K'o`1Pu!.anF!!)orJ,~> +r;Q`so)AakrrE&u!!)orqZ+@G!!)\[!!)N(!!)_\!!)K'o`1Pu!.anF!!)orJ,~> +r;Q`so)AakrrE&u!!)orqZ+@G!!)]l!!)N(!!)`m!!)K'o`1Pu!.anF!!)orJ,~> +r;Q`soD\mms8N)urr<&orr<&3^]4B-R/d6V^]4B.R/d6V^]4B.R/d5X^]8o\rr<&rs*t~> +r;Q`soD\mms8N)urr<&orr<&3^]4B-R/d6V^]4B.R/d6V^]4B.R/d5X^]8o\rr<&rs*t~> +r;Q`soD\mms8N)urr<&orr<&3^]4B-rr<&g^]4B.rr<&g^]4B.rr<%i^]8o\rr<&rs*t~> +r;Q`so`"mkrr2rurr2ruq#:UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sp&>!lrVlitrr2ruq#:UEpqu;0~> +r;Q`sp&>!lrVlitrr2ruq#:UEpqu;0~> +r;Q`sp&>!lrVlitrr2ruq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`spAb$js8W&up\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`spAb$js8W&up\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`spAb$js8W&up\t3n]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkrVufrq#:UEpqu;0~> +r;Q`so`"mkrVufrq#:UEpqu;0~> +r;Q`so`"mkrVufrq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sp&G$lrVlitp&>!l]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sp&G$lrVlitp&>!l]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sp&G$lrVlitp&>!l]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`spAY0orrE&u!!)Zk!!'[I!!)\[!!)N(!!)_\!!)N(!!)_\!!&S*!.anF!!)orJ,~> +r;Q`spAY0orrE&u!!)Zk!!'[I!!)\[!!)N(!!)_\!!)N(!!)_\!!&S*!.anF!!)orJ,~> +r;Q`spAY0orrE&u!!)Zk!!'[I!!)]l!!)N(!!)`m!!)N(!!)`m!!&S*!.anF!!)orJ,~> +r;Q`so`"mkrr;osp\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrr;osp\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrr;osp\t3n]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkqYpNqqu?Nn^;'^KopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkqYpNqqu?Nn^;'^KopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkqYpNqqu?Nn^;'^Kp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkqYpNqq#:UEpqu;0~> +r;Q`so`"mkqYpNqq#:UEpqu;0~> +r;Q`so`"mkqYpNqq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3n]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uY]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3n]YFLIopGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3n]YFLIp&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sp&G$lrr2rurr2ruq#:UEpqu;0~> +r;Q`sp&G$lrr2rurr2ruq#:UEpqu;0~> +r;Q`sp&G$lrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`spAY0orrE&u!!*#u!!)fo!!'[I!!)\[!!)N(!!)_\!!)N(!!)_\!!&S*!.anF!!)orJ,~> +r;Q`spAY0orrE&u!!*#u!!)fo!!'[I!!)\[!!)N(!!)_\!!)N(!!)_\!!&S*!.anF!!)orJ,~> +r;Q`spAY0orrE&u!!*#u!!)fo!!'[I!!)]l!!)N(!!)`m!!)N(!!)`m!!&S*!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruq#:UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruqu?Nngq`R_n%\o'opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruqu?Nngq`R_n%\o'opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruqu?Nngq`R_n%\o'p&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEp +qu;0~> +r;Q`so`"mkrVuisp\t3ng;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\n%ePq]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\n%ePq]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mn%ePq]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sn,N=dq#:UEp +qu;0~> +r;Q`sn,N=dq#:UEp +qu;0~> +r;Q`sn,N=dq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sn,E@fp&>!lg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,E@fp&>!lg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,E@fp&>!lg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`snG`Igo`"mkg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snG`Igo`"mkg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snG`Igo`"mkg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`snGiFep\t3ng;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snGiFep\t3ng;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snGiFep\t3ng;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sm/I%cqu?NngqWmip6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sm/I%cqu?NngqWmip6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sm/I%cqu?NngqWmipAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sm/I%cq#:UEp +qu;0~> +r;Q`sm/I%cq#:UEp +qu;0~> +r;Q`sm/I%cq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sn,N@ep\t3ng;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,N@ep\t3ng;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,N@ep\t3ng;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gpAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYq7uS%nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sir8uYq7uS%nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sir8uYq7uS%nA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[]YFMt +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[ +]YFMtq>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1opGd[nA##(p6bm\nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[ +]YFMtq>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1p&>!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!l +]YFMtq>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lnA##(pAY*mnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##( +p&>!l]YFMtq>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lq7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1q7lt1pAY*m +q7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1jM1`qj1kWpq>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lq7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1q7lt1pAY*m +q7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1jM1`qj1kWpq>UEpqu;0~> +r;Q`snG`Igrr2ruqu;3IM#dAO!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IM#dAO!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IM#dAO!!)orJ,~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)ZjSo2[j8T)ZjSo2[jSo2[j8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)ZjSo2[j8T)ZjSo2[jSo2[j8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)ZjSo2[j8T)ZjSo2[jSo2[j8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sec5UKjSo2[jT#2Zk5YD\jSo2[k5YA[k5YD\bPqPBqu;0~> +r;Q`sec5UKjSo2[jT#2Zk5YD\jSo2[k5YA[k5YD\bPqPBqu;0~> +r;Q`sec5UKjSo2[jT#2Zk5YD\jSo2[k5YA[k5YD\bPqPBqu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukl1V_rr2ruk5YG]k5PD]jSo2[rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukl1V_rr2ruk5YG]k5PD]jSo2[rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukl1V_rr2ruk5YG]k5PD]jSo2[rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)*[!!)3^!W`6#kPkM^j8T)ZaSu5?qu;0~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)*[!!)3^!W`6#kPkM^j8T)ZaSu5?qu;0~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)*[!!)3^!W`6#kPkM^j8T)ZaSu5?qu;0~> +r;Q`sf)G^Mrr2rujo5;\iVrlXk5YG]k5PJ_rrD6^r;c![r;b%@!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\iVrlXk5YG]k5PJ_rrD6^r;c![r;b%@!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\iVrlXk5YG]k5PJ_rrD6^r;c![r;b%@!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\ir8uYj8T)Zkl1_bs8N)Zrr<&^rr<&urr<&Crr<&rs*t~> +r;Q`sf)G^Mrr2rujo5;\ir8uYj8T)Zkl1_bs8N)Zrr<&^rr<&urr<&Crr<&rs*t~> +r;Q`sf)G^Mrr2rujo5;\ir8uYj8T)Zkl1_bs8N)Zrr<&^rr<&urr<&Crr<&rs*t~> +r;Q`sf)G^Mrr2rujo5;\j8T)Zir8uYkl:P\jSo2[kPkM^rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2rujo5;\j8T)Zir8uYkl:P\jSo2[kPkM^rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2rujo5;\j8T)Zir8uYkl:P\jSo2[kPkM^rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jo5;\rr2rujo5;\kPkM^rr2rukPkM^rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jo5;\rr2rujo5;\kPkM^rr2rukPkM^rr2rubl7YCqu;0~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jo5;\rr2rujo5;\kPkM^rr2rukPkM^rr2rubl7YCqu;0~> +r;Q`sec5UKjSo2[jo>5YkPtM]jSo2[k5YD\jo>;[bPqPBqu;0~> +r;Q`sec5UKjSo2[jo>5YkPtM]jSo2[k5YD\jo>;[bPqPBqu;0~> +r;Q`sec5UKjSo2[jo>5YkPtM]jSo2[k5YD\jo>;[bPqPBqu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;Q`sJcC<$jo5;\qu;0~> +r;V +r;V +r;V +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +JcC<$f`-I~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/cauchy-fig.ps b/docsrc/nyquist/cauchy-fig.ps new file mode 100644 index 0000000..3540ca6 --- /dev/null +++ b/docsrc/nyquist/cauchy-fig.ps @@ -0,0 +1,68 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: cauchy-fig.ps +%%CreationDate: Wed Jul 13 12:15:04 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2672 ASCII Bytes +image +nG`Lfn,MnW!<2HenG`Lfn,MnW!WITo)AgXqnDgos760llhS9lnGi(Z"7,f447N:@rr_T`If&X7o)Agd\UOMH +s7--hrW)ods7--grp]sXs8W&uIdmC-s8N#es7-*jrVlfcs7-*krVlhHnc/.Z"9&6!J+s760nqu?YFs*sV>o)Amjs8N&u +J+EX1rrr<"rr<#5o)J:\"oJ?!s8Tk)s760np](6ms1e.)o)Amfs8INJ^[hEqrrr/srr<#Uo)J:\ +"o&#qs8V!Is760nlhpb^s53DIo)AmZqYpNpht$grs/#YrVf%]s6oRZoD\p]li-n_rrDNZs7?6mhtO\\rr2ueoDeF^"5j.Y +rr2otp[eFVrr_0Ys8N#t!;H*boD]'1s8W(Js8Vufs7?6m^]4?5rr2uqoDeF^"2Fm9rr2otqt'jZ +rr[cNs8N#t!<)NhoD\oBs8W)trrE#hs7H$j +rVllsrVllso`+Ua!<)lr!<2or!.X\Ap&>$hrVlotJ,TBI^\.X"rrDrprrE&rrrBh,s7QBlp\k*l +rqucrht@$BrrDNdrrE&rrrDN\s7QBlhu3QTrqucrn+H_RrrBh4rrN+KrVlllp&F^b!5JL4!<2or +!;lHhp&>#ArVllsr;Qcqp&Fac!<2or!<2or!<)TjpAY-kr;Qcrr;Qcrp&Fac!;l]o!WITHrr@QB +s7ZHmp\b$krql]q^\7^$rrDNcrrE&qrrCsMs7ZHmn,31crql]qn+QeTrrCsSrrE&qrrDfes7ZHm +^\n*4rdXkG!;Z?gpAY,Br;Qcrqu6ZqpAame!;ufq!r)NiqYpPFp](!f!;l`p!pfgaqYpPfp](!f +!;HHl!pfgaqYpQap](!f!:Tmd"7,pb5PtH\p\4^^rrA\irrVNbrqcWpq=jparrN+KrVlrnY^ZHK +!WITDs7lToq>1*krqZQoTD8H]rrD6YrrE&orrD6Ws7lToTDJQgrdXeE!;lQkq>UKpJ,90FrqZQo +r:p:Zs7uZpa8,`8rqQKnch[V:rr>:ZrrE&nrrDTbs8)`qq"XjirdXbD!WITF +s8)`qa8#Z7rqHEmO8AnRrrN$^q#:?np\t6_qZ$Hm!/(%G!<2]l!!E,ur;QfeJ+rsCrq??mr#bk: +rVlor&,-#(rdXYA!9!eTrVlkMp&>$ko`"mnrVuls!T8J#rrE&jrrN$.rr<#u!T5'lrrE&irr_a$ +s8N0#p`K,-!<2Qh!q8GSnG`OgJ+3L-rrE&es7$$grpTmcrrE&qrrDNcrrE&qrrDNcrrE&rs!.R@ +s53hUp]&#,s6ou;qu>RQs7cQ.rVu?dJ,B9'rr;`m^]+<5hZ*ZVnG`Lfn,MnW!<2HenG`Lfn,MnW +!<2Heh>dEQ!5JI3!;H0d!8m_S!<2orr;Qa]r;Qc_p&>#qr;Qcpr;Z`q!WKk3rrDfdrrCsSrrDon +s8Dru`ZP0Z!W707rrCsSrrMnErVufq!5JI3!:TU\!5JI3!<2orr;Qa=r;QcWp&>#Qr;QfqJ,TE' +s*t~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/envfig.ps b/docsrc/nyquist/envfig.ps new file mode 100644 index 0000000..842ce33 --- /dev/null +++ b/docsrc/nyquist/envfig.ps @@ -0,0 +1,198 @@ +%!PS-Adobe-2.0 +%%Title: env-Layer#1 +%%Creator: MacDraw II 1.1v2 +%%CreationDate: Friday, July 19, 1991 +%%Pages: (atend) +%%BoundingBox: ? ? ? ? +%%PageBoundingBox: 125 130 2425 3170 +%%For: ' +%%IncludeProcSet: "(AppleDict md)" 68 0 +%%EndComments +%%EndProlog +%%BeginDocumentSetup +md begin + +T T -130 -125 3170 2425 100 300 300 1 F F F F T T T psu +(' ; document: env-Layer#1)jn +0 mf +od +%%EndDocumentSetup +%%Page: ? 1 +op +0 0 xl +1 1 pen +0 0 gm +(nc 0 0 3040 2300 6 rc)kp +0 setlinecap +currentscreen +3 1 roll pop pop 60 45 3 -1 roll setscreen +4 4 pen +73 36 gm +411 36 lin +411 1161 lin +2 setlinecap +0 0 pen +113 225 gm +113 225 lin +nc ct 39 0 put +8 8 pen +413 38 gm +bp +113 225 F qi +113 225 qc +263 338 qc +263 338 qc +300 975 qc +300 975 qc +413 1125 qc +413 1125 F qq +ef +9 ec +(nc 0 0 3040 2300 6 rc)kp +0 setlinecap +523 114 gm +1 setTxMode +0 fs +bu fc +{}mark T /Times-Roman /|______Times-Roman 0 rf +bn +42 fz +bu fc +2 F /|______Times-Roman fnt +bn +(t1)show +523 264 gm +(t2)show +523 1051 gm +(t4)show +4 4 pen +411 223 gm +0 gr +486 223 lin +411 36 gm +598 36 lin +411 336 gm +486 336 lin +411 973 gm +486 973 lin +411 1123 gm +598 1123 lin +111 186 gm +111 223 lin +111 114 gm +1 setTxMode +(L1)show +261 336 gm +0 gr +261 298 lin +261 226 gm +1 setTxMode +(L2)show +298 973 gm +0 gr +298 1011 lin +298 1051 gm +1 setTxMode +(L3)show +450 38 gm +0 gr +pr +450 38 pl +433 79 pl +450 79 pl +467 79 pl +450 38 pl +1 ep +450 225 gm +pr +450 225 pl +467 183 pl +450 183 pl +433 183 pl +450 225 pl +1 ep +448 77 gm +448 181 lin +450 225 gm +pr +450 225 pl +433 267 pl +450 267 pl +467 267 pl +450 225 pl +1 ep +450 338 gm +pr +450 338 pl +467 296 pl +450 296 pl +433 296 pl +450 338 pl +1 ep +448 265 gm +448 294 lin +450 975 gm +pr +450 975 pl +433 1017 pl +450 1017 pl +467 1017 pl +450 975 pl +1 ep +450 1125 gm +pr +450 1125 pl +467 1083 pl +450 1083 pl +433 1083 pl +450 1125 pl +1 ep +448 1015 gm +448 1081 lin +563 38 gm +pr +563 38 pl +545 79 pl +563 79 pl +580 79 pl +563 38 pl +1 ep +563 1125 gm +pr +563 1125 pl +580 1083 pl +563 1083 pl +545 1083 pl +563 1125 pl +1 ep +561 77 gm +561 1081 lin +601 526 gm +1 setTxMode +(dur)show +44 114 gm +1 fs +bu fc +{}mark T /Courier-Bold /|______Courier-Bold 0 rf +bn +50 fz +bu fc +2 F /|______Courier-Bold fnt +bn +(\(env )show +0 fs +bu fc +2 F /|______Times-Roman fnt +bn +(t1 t2 t4 l1 l2 l3 dur)show +1 fs +bu fc +2 F /|______Courier-Bold fnt +bn +(\))show +F T cp +%%Trailer +cd +end +%%Pages: 1 0 +%%EOF diff --git a/docsrc/nyquist/exponential-fig.ps b/docsrc/nyquist/exponential-fig.ps new file mode 100644 index 0000000..241da50 --- /dev/null +++ b/docsrc/nyquist/exponential-fig.ps @@ -0,0 +1,60 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: exponential-fig.ps +%%CreationDate: Wed Jul 13 12:15:23 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2136 ASCII Bytes +image +s8N)ri;WlYq>9+M!rr5ri;WlYrVPOQ!rr5oi;WlYrVPOQ!rqb8i;`iW!;YRQs8N)pi;`iW!;bXR +s8N)qi;`iW!;bXRs8N,qJ)UG-rrN"HiW&rX!W.B*s8W*"qnM+is8N,s^Z#4mrrN#3iW&rX!W1d5 +s8W*"qqpB4s8N,qn)=L +s8W*!q>:0ln)s`NrrDrnrrDfVs8W*!qtpBnqre"ZrrDrnrrE#\s8W*!qtpBnroa=]rrDrmrr>:I +s8W*!qtg1*kpZVYWrrDrmrrDr[s8W*!qtg($jqs".\rrDrlrrDu] +s8W*!qtU0kJ*R(6rrDrkrrBh!s8W*!qtU0kcg(N3htR$CrrDfYrrTCiqtU0kqli.%Cj88TN!;GgZs8N)rp\t6hli7"b!;lNj!WIT8s8W*!qtC$i +^[2"#rrDrirrCC3s8W*!qtC$ioBcMWrrDlgrrDu`s8W*!qt9sh+79+.rrDrhrrD6Ls8W*!qt9sh +q!J+]rrDrgrr=//s8W*!qt0mgj6lsIrrDrgrrDubs8W*!qt'gf+7K70rrDldrrD*Js8W*!qt'gg +r'0]Ns8N)ro)A^1nGiOg!;l?e!Vh07s8W*!qsj[dJard?rrDrdrrN*0o)Jai!;l9c!Ur>Fs8W*! +qsXOb_=R^,rrDl`rrN*(o`+sk!;l3a!Vcoms8W*!qsFCap]1$fs8N)rli-tc5PY9YrrDr]rrKn? +q>^Kp!;l$\!VcZks8W*!qtpBn^\n*3qtpBnJ,Kr;QcWr;Qcpqu6ZVr;Qfss5!^*~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/gamma-fig.ps b/docsrc/nyquist/gamma-fig.ps new file mode 100644 index 0000000..d4fed9d --- /dev/null +++ b/docsrc/nyquist/gamma-fig.ps @@ -0,0 +1,71 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: gamma-fig.ps +%%CreationDate: Wed Jul 13 12:15:43 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2956 ASCII Bytes +image +h>c=2rr2ueiW&oW!:SnHrr2ueiW&oW!:Ta`!;u-^rr2ueq>UK3#ODEhrrDN`rrKn1li6ta!9a4Y +"9*fLJ*d47rrDNarr`6"s1dq#rr2ueqYpZps8V!Cs8N#un,!%dp](9^m/R(b!:Tda"7Q9ip[%qZ +rrDNarr_0Ys820_rr2ueqYpZ4s8W&as8N#ukPG2\^]4?5m/R(b!:Tda!.Y"J!.XD9rr2uequ6Zq +rVll4mJm1c!:Tgb!<)lr!8m2D"93l.n,*+brVc`rn*U,WrkGZ*qu6ZnrVlllmJd:f^YeMWrrDfl +rrDr`rr`88hrjn:!;HHl!;l0`"9-'Mn,*+bn,<7drU'Ues*Kgqqu6ZbrVllsmJm1c!:Tgb!8m_S +!.XG:rr2uequ6ZRr;QbHmf3:d!:Tgb!5JI3!5It%rr2uequ6Z2r;QcSmf3:d!9a7Z!.XqH!:T@U +rr2uequ6YGr;Qckmf3:d!:Tgb!.XqH!;Gp]rr2uer;Qcrqu6Znmf3:d!:Tjc!<2lq!<)?crr2ue +r;Qcqqu6Zqmf3:d!:Tjc!<)fp!<2Edrr2u]r;QcqqYpPFn,NCe!:Tjc!;lWm!.XJ;rr2uer;Qco +qYpQ1n,NCe!:Tjc!;lWm!8m8Frr2uer;QckqYpQQn,NCe!:Tjc!;H?i!:TCVrr2uer;QccqYpQi +n,NCe!9a:[!:Tda!;Gs^rr2uer;QccqYpQmn,NCe!:Tjc!8mYQ!;l6brr2uer;QcSqYpQon,NCe +!:Tjc!5JC1!<2Herr2uer;Qc3qYpQpn,NCe!:Tjc!5J@0!.XMUH0nGiLf!:Tjc +!.XhE!5J%'rr2uer;QbHq>UHPnGiLf!:Tmd!<2cn!8m;G"5i8`n,<7drqQKnn*p>ZYP3P8rVllr +q#:?gnG`TopHS-FrrE#mrrDf_rr]J!hrjtrr2uerVll4pAY--o)J^h!:Tmd!.X_B +!8mAIrr2uerVlkIpAY-Mo)J^h!9a=\!.X_B!:TLYrr2uerVlkIpAY-eo)J^h!:Tpe!<2Zk!;H'a +rr2uerr2utp&>$ho)J^h!:Tpe!<2Zk!<)Kgrr2uerr2utp&>$ko)J^h!9a@]!<)Tj!<2Qhrr2ue +rr2uso`"o@oDegi!:Tpe!<)Qi!5J.*rr2uerr2uqo`"pKoD\pmJ"Q3/rrDrgrrCsJrr`88hs^RE +!;lEg!:TOZ"9-'mn,E=eqt0mgp[eCerkI@Rrr2umo`"pgoD\pl^YeMZrrDfcrrDrfrr`:J#OhZl +!;H-c!<)Nhrr2uerr2umo`"pjoDegi!:Tpe!:TOZ!.XY@rr2uerr2ueoD\g*o`+pj!:Tpe!:TOZ +!5J1+rr2u]rr2uUoD\gJo`+pj!:Tpe!8mDJ!:TR[rr2uerr2uUoD\gbo`+pj!:Tpe!5J.*!;H-c +rr2uerr2u5oD\gfo`+pj!:Tpe!5J.*!<)Qirr2uerr2tJoD\gio`+pj!9a@]!.XS>!.X\Arr2ue +rr2tJo)A]>p&G$k!:Tpe!.XS>!5J4,rr3)hs8W)grrCsLs8N$#n,NFenc&UXp&G$k"7Q9irpg!g +p\"Rcrr_`is8DKf!;lHhrr3)`s8W&frrE#js8N$#n,NFdnc&XhJ+ipArr_`is82Wn,NFFn,ECbp\tH$legn*s53;F!<)Zl#-[?"n,NF&n,ECep\tHSpV61ss1e"% +!'g8Yrr3)hs8Tk%rrCsOs8N$#n,NE;mf*:Uq#C?n"7Q9iJ+!=:oD&@brr_`is*sJ:!<)]mrr3&_ +s8MEc!<2cnrr3&gs8MBb!'g;Zrr3&gs8MBb!8mVPrr3&gs8Drr3&gs*s53!9*qW +rr3#froX4_rWiK'rr3#^roO.]pcnfXrrMTejSo7us8N$!n,)2G!W7HHrrMT_irB#X!UodBs8N$! +n'Ct4!;lZn!.XqH!:Tjc!;lZn!.Y"J+R_Mop]&#*s53hUn,In7s1eO4n,E@]s1eI2hud9M!;HBj!.XqH!71TC!;HEk!U%5mrrDB_rrN+K +r;Qc3r;Qc_r;Qfl?hjX$p\b$lrI=bF!2'2h!;HEk!V]srrrDfkrrN$^r;Qc#r;Qc_r;Qfl?hjX$ +n,*+bJ,Kc=2h>`!~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/gaussian-fig.ps b/docsrc/nyquist/gaussian-fig.ps new file mode 100644 index 0000000..d7285c2 --- /dev/null +++ b/docsrc/nyquist/gaussian-fig.ps @@ -0,0 +1,69 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: gaussian-fig.ps +%%CreationDate: Wed Jul 13 12:15:59 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2773 ASCII Bytes +image +nG`Lfn,MtY!r)]nn,MtY!pfd`n,MtY!pf^^n,MtY"7,`05Oe^Drr_Tdn3?FBo)Agd]PcWrs7$$h +cKF]snG`O'qsaXTrrKk2nGi"X!Ik":s7--hrW)ods7--hrW%E:s7-*jrVlfcs7-*krVlhHnc/.Z +"8i)tJ+o)Amls8INJJ+EX1rrrB$rr<"Jo)J:\"o\K#s8RT>s760nqu?Zqs1e.)o)Amj +s8N&u^[hEqrrr#mrr<#5o)J:\"loIYs8V!Is760nj8T&Xs53DIo)AmRrVf%]ht$grr`#qs8N#t!:TOZoD\p]s8W)trrDNZ +s7?6qn,NFeJ,fQ;oDeF^"7Q9irr2otp[eFVrr_0Ys8N#t!;H*boD\pMs8W)trrDfbs7?6mhuE`U +rr2umoDeF^"5ikOrr2otqt'jZrr^%%qYpKo!;lBfoD\p-li$h^rrDrfs7?6q^[(jt5QCc^oDeF^ +"+TY6rr2otrU^'\rr[cF\GlL-!<)NhoD\oBs8W)trrE#hs7?6mJ,fQJrr2utoDeI_!<2ut!<2ut +!<2Tio`"pjrr2utrr2utoDeI_!<2ut!WITJrr@Q@s7H$jrVllsrVllso`+Ua!<)lr!<2rs!<2Wjp&>$hrVllsr;QbHp&F^b!;l`p +!<2or!.X\Ap&>3ms8VihrqucrJ+`j7rrr/ss6KX_r;Qc3p&F^b"o&&sli$h\rrBh,s7QBrp](9Z +rVf%[rrBh,s7QBqn,NFRrVl`p!8mJLp&>3as8VhtIf03Ght@$BrrCsTrrE&rrrDN\s7QBlhu3QT +rqucrn+H_RrrCsTrrE&rrrDfds7QBl^]"04rqucrp\"RZrrBh4rrE&rrrDrhs7QBl^]"05rdXnH +!;lHhp&>#ArVllsr;Qcqp&F^b!.XtI!<2or!<)TjpAY-lr;Qcrr;Qcrp&Fac!<2or!<2or!<2Zk +pAY-kr;Qcrqu6YGpAajd!<)iq!<2lq!.X_BpAY-ir;Qcrqu6Z2pAajd!;l]o!WITHrrBh-s7ZHm +p\b$krql]qhtI*DrrDNcrrE&qrrCsMs7ZHmn,31crql]qn+QeTrrCsSrrE&qrrDN]s7ZHmhu*KS +rql]qp\+X\rrBh3rrE&qrrDris7ZHmJ,K1*krqZQo^\Ij(rrD6YrrE&orrCC?s7lTo+8Z!;rqZQonbE.[rrDumrrE&orrN*`q>^Bm#(Q[Q +KE(u?r;Qcrqu6lhs8Tn7s8Dlq,QI`Bn,In7J7&9Tn,In7s53hUp]&#,s6ou;pBSJ3s6ou;rrE&U +!!*&grrE&es7$$grpTmVrrE&es7$$grpTmCs8;lshu*KSp\"Odhu*KSrVZ]nrrA\hrrDBXrrB8# +rrDlms8;ls?i9p(p\"Odhu*KSp&+jgrrM-jrVlorGP1t9hu*KSnGN=arrCsSrrDN\rrBh3rrE#q +s8;lsO8T"Xj7WEPO8T"Xq#(0Js*t~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/geometric-fig.ps b/docsrc/nyquist/geometric-fig.ps new file mode 100644 index 0000000..484d708 --- /dev/null +++ b/docsrc/nyquist/geometric-fig.ps @@ -0,0 +1,1173 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: geometric-fig.ps +%%CreationDate: Wed Jul 13 12:16:14 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 313 363 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 348 translate +-20 775 translate +297.99999999999994 -348 scale +% Image geometry +298 348 8 +% Transformation matrix +[ 298 0 0 348 0 0 ] +% Strings to hold RGB-samples per scanline +/rstr 298 string def +/gstr 298 string def +/bstr 298 string def +{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop} +true 3 +%%BeginData: 48827 ASCII Bytes +colorimage +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +r;V +r;V +r;V +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`s^]+JrHiO/8nDO +r;Q`s^]+JrHiO/8nDO +r;Q`s^]+JrHiO/8nDO +r;Q`s_#FW'!1Nr@!.<`)rrDHdrrE*!!h',JpAb-mq#C?op&G$lec,]a!!'e6!!)orJ,~> +r;Q`s_#FW'!1Nr@!.<`)rrDHdrrE*!!h',JpAb-mq#C?op&G$lec,]a!!'e6!!)orJ,~> +r;Q`s_#FW'!1Nr@!.<`)rrDHdrrE*!!h',JpAb-mq#C?op&G$lec,]a!!'e6!!)orJ,~> +r;Q`s_#FJ)!9sC\"0qn,ZMsk>Z:t>)s8N'!d!SR$a%]:Ts8TA)!4)Y'!"T#/!/u=*!!*'!Z:t=X +l2CY^!<<'-kl@1P!!*&`HiO/*l2(GlN-tX*!<3$!]hOIcrr<'!s8)d-rr<'!s0>?!ZN'q)!76*f +d/*eB!!:MAI.[F@n7Ve%^]+96qu;0~> +r;Q`s_#FJ)!9sC\"0qn,ZMsk>Z:t>)s8N'!d!SR$a%]:Ts8TA)!4)Y'!"T#/!/u=*!!*'!Z:t=X +l2CY^!<<'-kl@1P!!*&`HiO/*l2(GlN-tX*!<3$!]hOIcrr<'!s8)d-rr<'!s0>?!ZN'q)!76*f +d/*eB!!:MAI.[F@n7Ve%^]+96qu;0~> +r;Q`s_#FJ)!9sC\"0qn,ZMsk>Z:t>)s8N'!d!SR$a%]:Ts8TA)!4)Y'!"T#/!/u=*!!*'!Z:t=X +l2CY^!<<'-kl@1P!!*&`HiO/*l2(GlN-tX*!<3$!]hOIcrr<'!s8)d-rr<'!s0>?!ZN'q)!76*f +d/*eB!!:MAI.[F@n7Ve%^]+96qu;0~> +r;Q`s_#FF0!;ldN]`?+"!58EG!6<+[^&J'4^$l"%ZKV@&s1JEQciCcZ!!*'!!!(^Prr<'!Z2hr0 +!0$mVrrE&urr>"X!!*%4!<;9`I/a0Hrr<&Ps8N'!rr<%s`rN%;!!*'!!!*$!!<<'!!<9_4a2\1n +rr<&4kl=HSs8N'%VoJe8s8)forr]1G!!'e6!!)orJ,~> +r;Q`s_#FF0!;ldN]`?+"!58EG!6<+[^&J'4^$l"%ZKV@&s1JEQciCcZ!!*'!!!(^Prr<'!Z2hr0 +!0$mVrrE&urr>"X!!*%4!<;9`I/a0Hrr<&Ps8N'!rr<%s`rN%;!!*'!!!*$!!<<'!!<9_4a2\1n +rr<&4kl=HSs8N'%VoJe8s8)forr]1G!!'e6!!)orJ,~> +r;Q`s_#FF0!;ldN]`?+"!58EG!6<+[^&J'4^$l"%ZKV@&s1JEQciCcZ!!*'!!!(^Prr<'!Z2hr0 +!0$mVrrE&urr>"X!!*%4!<;9`I/a0Hrr<&Ps8N'!rr<%s`rN%;!!*'!!!*$!!<<'!!<9_4a2\1n +rr<&4kl=HSs8N'%VoJe8s8)forr]1G!!'e6!!)orJ,~> +r;Q`s_#OE7s8W&u-N?d?s8N(4s(DE4rr?a4!!*'!!!*'!!!*$n!<<'!B`A&4s8N'!rr;uu!rksp +q>^Hprr;uu#QFc(s%NK@d/O(F!!<0#!<3#u!$_FC!<<'!:&b1ns8N'!rr<'!rr<'!BE8)4!,2B4 +!<<'!!;c`q!<<'"!)<1e"R1=6!!'e6!!)orJ,~> +r;Q`s_#OE7s8W&u-N?d?s8N(4s(DE4rr?a4!!*'!!!*'!!!*$n!<<'!B`A&4s8N'!rr;uu!rksp +q>^Hprr;uu#QFc(s%NK@d/O(F!!<0#!<3#u!$_FC!<<'!:&b1ns8N'!rr<'!rr<'!BE8)4!,2B4 +!<<'!!;c`q!<<'"!)<1e"R1=6!!'e6!!)orJ,~> +r;Q`s_#OE7s8W&u-N?d?s8N(4s(DE4rr?a4!!*'!!!*'!!!*$n!<<'!B`A&4s8N'!rr;uu!rksp +q>^Hprr;uu#QFc(s%NK@d/O(F!!<0#!<3#u!$_FC!<<'!:&b1ns8N'!rr<'!rr<'!BE8)4!,2B4 +!<<'!!;c`q!<<'"!)<1e"R1=6!!'e6!!)orJ,~> +r;Q`s_#FF0!<3#u!!*&r!##;3!<<'!!<3$!s8N'!s8N'!s8)d#rr<'!rr<&us8N'#rr<&ps8N)u +s8N'0rr<'!cqOK?:!in?!<3$!rr;uu,6%WCs8N'!rr<'!rr<'!!!*'!!!*$!!<<'!!<3$!s8N'! +qZ$Qqs8W*!!<;orrVm"ZiVrlX^]+96qu;0~> +r;Q`s_#FF0!<3#u!!*&r!##;3!<<'!!<3$!s8N'!s8N'!s8)d#rr<'!rr<&us8N'#rr<&ps8N)u +s8N'0rr<'!cqOK?:!in?!<3$!rr;uu,6%WCs8N'!rr<'!rr<'!!!*'!!!*$!!<<'!!<3$!s8N'! +qZ$Qqs8W*!!<;orrVm"ZiVrlX^]+96qu;0~> +r;Q`s_#FF0!<3#u!!*&r!##;3!<<'!!<3$!s8N'!s8N'!s8)d#rr<'!rr<&us8N'#rr<&ps8N)u +s8N'0rr<'!cqOK?:!in?!<3$!rr;uu,6%WCs8N'!rr<'!rr<'!!!*'!!!*$!!<<'!!<3$!s8N'! +qZ$Qqs8W*!!<;orrVm"ZiVrlX^]+96qu;0~> +r;Q`s_#F_0!9*tX!!*$n!;uj1BE8)4!,2B4!<<'!!<<'!!<5anr;Zcss8W*!rr;uu!rkspq>^Hp +s8N8e!1Nof!<3!)fr"gErr<'!!!*#urr=8C!!*'!!)jfs8)f3rr<&rs*t~> +r;Q`s_#F_0!9*tX!!*$n!;uj1BE8)4!,2B4!<<'!!<<'!!<5anr;Zcss8W*!rr;uu!rkspq>^Hp +s8N8e!1Nof!<3!)fr"gErr<'!!!*#urr=8C!!*'!!)jfs8)f3rr<&rs*t~> +r;Q`s_#F_0!9*tX!!*$n!;uj1BE8)4!,2B4!<<'!!<<'!!<5anr;Zcss8W*!rr;uu!rkspq>^Hp +s8N8e!1Nof!<3!)fr"gErr<'!!!*#urr=8C!!*'!!)jfs8)f3rr<&rs*t~> +r;Q`s_#H"N!1Nr$!!*&)!6==(N;pQka2\1nrr<'!rr<'!rr<'!Z2hr0!0$pX!<<'!!<3#u!!`J/ +!6==(I/X*F!<<'3RK2%@!!*%H!9rtQB`A&4rr<&us8N'Frr<%sciC!DBE7;1!!*$!!<<'!!<9_4 +a2\1nrr<'!rr<'!!!)utrrs8N)ts8N)6rr<&rs*t~> +r;Q`s_#H"N!1Nr$!!*&)!6==(N;pQka2\1nrr<'!rr<'!rr<'!Z2hr0!0$pX!<<'!!<3#u!!`J/ +!6==(I/X*F!<<'3RK2%@!!*%H!9rtQB`A&4rr<&us8N'Frr<%sciC!DBE7;1!!*$!!<<'!!<9_4 +a2\1nrr<'!rr<'!!!)utrrs8N)ts8N)6rr<&rs*t~> +r;Q`s_#H"N!1Nr$!!*&)!6==(N;pQka2\1nrr<'!rr<'!rr<'!Z2hr0!0$pX!<<'!!<3#u!!`J/ +!6==(I/X*F!<<'3RK2%@!!*%H!9rtQB`A&4rr<&us8N'Frr<%sciC!DBE7;1!!*$!!<<'!!<9_4 +a2\1nrr<'!rr<'!!!)utrrs8N)ts8N)6rr<&rs*t~> +r;Q`s^]+]#HiO/*d/X-O9`U.OruJC>9sXg!!!*'!!!*'!!!*'!Z:t=Xs8UFGI/a0Hrr;uus8N5- +!!%uBrVufr¬urr<'!n +r;Q`s^]+]#HiO/*d/X-O9`U.OruJC>9sXg!!!*'!!!*'!!!*'!Z:t=Xs8UFGI/a0Hrr;uus8N5- +!!%uBrVufr¬urr<'!n +r;Q`s^]+]#HiO/*d/X-O9`U.OruJC>9sXg!!!*'!!!*'!!!*'!Z:t=Xs8UFGI/a0Hrr;uus8N5- +!!%uBrVufr¬urr<'!n +r;Q`sJcEUe!U4:rs8N)"rr<&rs*t~> +r;Q`sJcEUe!U4:rs8N)"rr<&rs*t~> +r;Q`sJcEUe!U4:rs8N)"rr<&rs*t~> +r;Q`sJcEUe!K?"9s8N)"rr<&rs*t~> +r;Q`sJcEUe!K?"9s8N)"rr<&rs*t~> +r;Q`sJcEUe!K?"9s8N)"rr<&rs*t~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sp&G!krr;rtJcC<$q>UEpqu;0~> +r;Q`sp&G!krr;rtJcC<$q>UEpqu;0~> +r;Q`sp&G!krr;rtJcC<$q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGTH!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGTH!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!%TMJcGTH!!)orJ,~> +r;Q`spAY*mr;Q`srr2ruJcC<$qYpNqqu;0~> +r;Q`spAY*mr;Q`srr2ruJcC<$qYpNqqu;0~> +r;Q`spAY*mr;Q`srr2ruJcC<$qYpNqqu;0~> +r;Q`spAb'ks8N'!rr2ruJcC<$qYpNqqu;0~> +r;Q`spAb'ks8N'!rr2ruJcC<$qYpNqqu;0~> +r;Q`spAb'ks8N'!rr2ruJcC<$qYpNqqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)orqZ)1tNe$s*!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)orqZ)1tNe$s*!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)orqZ)1tNe$s*!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sp&Fsjs8W&up\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&Fsjs8W&up\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&Fsjs8W&up\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAY*mr;Q`srr2ruq#: +r;Q`spAb'ks8N'!rr2ruq#: +r;Q`spAb'ks8N'!rr2ruq#: +r;Q`spAb'ks8N'!rr2ruq#: +r;Q`so)AakrrE&u!!)orqZ)2_O2(aGq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ)2_O2(aGq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ)2_O2(aGq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYq7uS%J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7uS%J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7uS%J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#: +r;Q`so`+pks8N'!rr2ruq#:!lJ\\%r!.anF!!)orJ,~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!;XD1!;2`[!.hq\^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!;XD1!;2`[!.hq\^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!;XD1!;6?l!.hq\^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!;XD1!;2`[!.hq\^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!;XD1!;2`[!.hq\^]8o\rr<&rs*t~> +r;Q`sp&>0qrrE*!!<2uu!;QQo!;XD1!;6?l!.hq\^]8o\rr<&rs*t~> +r;Q`spAYUEpqu;0~> +r;Q`spAYUEpqu;0~> +r;Q`spAYUEpqu;0~> +r;Q`spAb$j!WN0!rr<&orr<&p^]4B-R/d5<^n\[FJGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<&p^]4B-R/d5<^n\[FJGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<&p^]4B-rr<%M^n\[FJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<&p^]4B-R/d5<^n\[FJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<&p^]4B-R/d5<^n\[FJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<&p^]4B-rr<%M^n\[FJGK3F!;leH~> +r;Q`soD\djrr;rtp\t3nq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nq7lt1opGd[J\\%r!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nq7lt1p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)]l!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)]l!!%ScUVHk[q>UEpqu;0~> +r;Q`so`+pks8N'!rr2ruqu?NnqnN13opGd[J\\%r!.anF!!)orJ,~> +r;Q`so`+pks8N'!rr2ruqu?NnqnN13opGd[J\\%r!.anF!!)orJ,~> +r;Q`so`+pks8N'!rr2ruqu?NnqnN13p&>!lJ\\%r!.anF!!)orJ,~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)]l!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)]l!!%ScUVHk[q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)\[!!%ScUVHk[q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)]l!!%ScUVHk[q>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nq7lt1opGd[nA+YrJ\]+;!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nq7lt1opGd[nA+YrJ\]+;!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nq7lt1p&>!lnA+YrJ\]+;!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sp&G!krr;rtp\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`sp&G!krr;rtp\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`sp&G!krr;rtp\t3nq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!)i1!!)]l!!)N(!!)]l!!%Sc_S?/%q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)]l!!)N(!!)]l!!%Sc_S?/%q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!)i1!!)]l!!)N(!!)]l!!%Sc_S?/%q>UEpqu;0~> +r;Q`soD\mms8N)urr<&rs8)fn^]4B-R/d6V^]4B-R/d5<^r!keJGK3F!;leH~> +r;Q`soD\mms8N)urr<&rs8)fn^]4B-R/d6V^]4B-R/d5<^r!keJGK3F!;leH~> +r;Q`soD\mms8N)urr<&rs8)fn^]4B-rr<&g^]4B-rr<%M^r!keJGK3F!;leH~> +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#:!lnA##(p&>!lJ\]. +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#: +r;Q`sp&>!lrVlitrr2ruq#:!lnA##(p&>!lJ\]. +r;Q`spAb$js8W&up\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`spAb$js8W&up\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`spAb$js8W&up\t3nq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[J\]. +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`so`"mkrVuisp\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`so`"mkrVuisp\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`so`"mkrVuisp\t3nq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sp&G$lrr2rurr2ruq#: +r;Q`sp&G$lrr2rurr2ruq#: +r;Q`sp&G$lrr2rurr2ruq#:!lnA##(p&>!lJ\]. +r;Q`spAY0orrE&u!!*#u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`spAY0orrE&u!!*#u!!)fo!!)i1!!)\[!!)N(!!)\[!!%Sc_S?/%q>UEpqu;0~> +r;Q`spAY0orrE&u!!*#u!!)fo!!)i1!!)]l!!)N(!!)]l!!%Sc_S?/%q>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#:!lnA##(p&>!lJ\]. +r;Q`so`"mkrr2rurr2ruqu?NnqnN13opGd[nA##(opGd[J\]. +r;Q`so`"mkrr2rurr2ruqu?NnqnN13opGd[nA##(opGd[J\]. +r;Q`so`"mkrr2rurr2ruqu?NnqnN13p&>!lnA##(p&>!lJ\]. +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#:!lnA##(p&>!lJ\]. +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#: +r;Q`so`"mkrr2rurr2ruq#:!lnA##(p&>!lJ\]. +r;Q`so`"mkrVuisp\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`so`"mkrVuisp\t3nq7lt1opGd[nA##(opGd[J\]. +r;Q`so`"mkrVuisp\t3nq7lt1p&>!lnA##(p&>!lJ\]. +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA+\sJ\^0Y!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA+\sJ\^0Y!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA+\sJ\^0Y!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA+Yrn%ePqS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA+Yrn%ePqS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA+Yrn%ePqS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA+VqnA+Yrg;!]= +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA+VqnA+Yrg;!]= +q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA+VqnA+Yrg;!]= +q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\g;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\g;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mg;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\g;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\g;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mg;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\g;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\g;!]=q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mg;!]=q>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[ +nA##(p6bm\nA+Vqq7lu\q>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[ +nA##(p6bm\nA+Vqq7lu\q>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l +nA##(pAY*mnA+Vqq7lu\q>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##( +p&>!lnA##(pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1pAY*m +q7lt1q7lt1p&>!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1q>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1pAY*m +q7lt1q7lt1p&>!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1q>UEpqu;0~> +r;Q`snG`Igrr2ruqu;3IL]I8N!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IL]I8N!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IL]I8N!!)orJ,~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)Zj8T)ZjSo2[jSo2[j8T)Zj8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)Zj8T)ZjSo2[jSo2[j8T)Zj8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)Zj8T)ZjSo2[jSo2[j8T)Zj8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sec5UKjSo2[jT#2Zjo>;[jo5;\jo>8Zk5YD\n,E@fr;Q`sjSo2[qu;0~> +r;Q`sec5UKjSo2[jT#2Zjo>;[jo5;\jo>8Zk5YD\n,E@fr;Q`sjSo2[qu;0~> +r;Q`sec5UKjSo2[jT#2Zjo>;[jo5;\jo>8Zk5YD\n,E@fr;Q`sjSo2[qu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukPkM^rr2rukPtP^jo5;\jSo2[rr2runGiLgrr;uujSo2[ +qu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukPkM^rr2rukPtP^jo5;\jSo2[rr2runGiLgrr;uujSo2[ +qu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukPkM^rr2rukPtP^jo5;\jSo2[rr2runGiLgrr;uujSo2[ +qu;0~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)'Z!!)6_!W`6#k5PD]j8T)Zm/R(crr;uus8W&us8N3%rrE*! +rW)Qi!!)orJ,~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)'Z!!)6_!W`6#k5PD]j8T)Zm/R(crr;uus8W&us8N3%rrE*! +rW)Qi!!)orJ,~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)'Z!!)6_!W`6#k5PD]j8T)Zm/R(crr;uus8W&us8N3%rrE*! +rW)Qi!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\iVrlXjo>>\kPkS`rrD3]r;c![r;c +r;Q`sf)G^Mrr2rujo5;\iVrlXjo>>\kPkS`rrD3]r;c![r;c +r;Q`sf)G^Mrr2rujo5;\iVrlXjo>>\kPkS`rrD3]r;c![r;c +r;Q`sf)G^Mrr2rujo5;\ir8uYir8uYl2Lhcs8N)Yrr<&^rr<&urr<&grs/W)!<3'!!<3&urrN3# +!<3#r!;-9k!;leH~> +r;Q`sf)G^Mrr2rujo5;\ir8uYir8uYl2Lhcs8N)Yrr<&^rr<&urr<&grs/W)!<3'!!<3&urrN3# +!<3#r!;-9k!;leH~> +r;Q`sf)G^Mrr2rujo5;\ir8uYir8uYl2Lhcs8N)Yrr<&^rr<&urr<&grs/W)!<3'!!<3&urrN3# +!<3#r!;-9k!;leH~> +r;Q`sf)G^Mrr2rujo5;\j8T)ZiVrlXl2UY]j8T)ZkPkM^rr2runG`aorrE'!rrE'!rr3$"rrE&u +!!)Ng!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\j8T)ZiVrlXl2UY]j8T)ZkPkM^rr2runG`aorrE'!rrE'!rr3$"rrE&u +!!)Ng!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\j8T)ZiVrlXl2UY]j8T)ZkPkM^rr2runG`aorrE'!rrE'!rr3$"rrE&u +!!)Ng!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jSo2[rr2ruk5PD]k5PD]rr2rukPkM^rr2runG`aos8N*!rrE'! +rr3$"rrE&u!!*#u!!)Zk!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jSo2[rr2ruk5PD]k5PD]rr2rukPkM^rr2runG`aos8N*!rrE'! +rr3$"rrE&u!!*#u!!)Zk!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jSo2[rr2ruk5PD]k5PD]rr2rukPkM^rr2runG`aos8N*!rrE'! +rr3$"rrE&u!!*#u!!)Zk!!)orJ,~> +r;Q`sec5UKjSo2[jo>5Yk5YD\jo5;\jo>;[jo>;[n,EXns8N*!rrE*!rW)uu!!)utrW)Qi!!)or +J,~> +r;Q`sec5UKjSo2[jo>5Yk5YD\jo5;\jo>;[jo>;[n,EXns8N*!rrE*!rW)uu!!)utrW)Qi!!)or +J,~> +r;Q`sec5UKjSo2[jo>5Yk5YD\jo5;\jo>;[jo>;[n,EXns8N*!rrE*!rW)uu!!)utrW)Qi!!)or +J,~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;V +r;V +r;V +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/hyperbolic-fig.ps b/docsrc/nyquist/hyperbolic-fig.ps new file mode 100644 index 0000000..0037d50 --- /dev/null +++ b/docsrc/nyquist/hyperbolic-fig.ps @@ -0,0 +1,70 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: hyperbolic-fig.ps +%%CreationDate: Wed Jul 13 12:16:30 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2868 ASCII Bytes +image +nG`Lfn,MnW!<2HenG`Lfn,MnW!WITs760nrVukHs*sV>o)Amls8N&u +^[hErs8W$#EW6"<^[hErs8Vou\,QF-^[hErrs&>sF8l4>ht$g=rs&>sIJuJ2ht$g=rs&>np&>!k +ht$g=rs&Ga49#9[n+-MLrrqlkrr<#eo)J:\"n2Kjs8VQYs760nn,NB:s7c*ao)AmNs8N&up[\@T +rrq<[rr<#mo)J:\"lK@Zs8Vues760n^]4<5s82Beo)Am.s8INJqssdXrrp1;rr<#so)J:\"b6RO +s8W&gs760nJ,fNJs8DNgo)AlCs8N&urUU![rs&K&s8INJrpp*\rs&K&s8N&urpp*\rs&K&s8N&u +rpp*\rr`6"s8N#t!.XV?oD\pks8W)trr@Q?s7?6qrVuosJ,fOuoDeF^"8i,urr2ot^[qKsrr`/m +rVlfr!5J.*oD\pilh^V[rrBh*s7?6mpZqeWrr2uUoDeF^#P[Q_r]gG_ht-m>rr`#]qu6Tp!8mDJ +oD\p]pUL5%rrDNZs7?6mn,NFerr2ueoDeF^"7Q9irr2otn+6SNrs.H]s8INJs6oRZoD\pMs8W)t +rrDfbs7?6mhuE`Urr2umoDeF^"2Fm9rr2otp[eFVrr^%9s8N#t!;lBfoD]'1s8W(Js8Vufs7?6m +J,fQJrr2uqoDeF^"+U@Nrr2otrU^'\rr[cNs8N#t!<)Nho`"pjrr2utrr2usoDeI_!<2ut"TEoN +s8MWio`"pjrr2utrr2utoDeI_!<)os!<2rs!.XY@o`"pirr2utrVlkIo`+R`!<)os!<2rs!5J1+ +o`"pgrr3#uJ,]HJ^\%Qurri5trc.r9rrCsKs7H$jrVllsr;QbH +p&F^b!;l`p!<2or!5J4,p&>$hrVllsr;Qc3p&F^b!;HHl!<2or!5J4,p&>$drVlotJ,TBIht@$B +rrDNdrrE&rrrCsLs7QBln,<7drqucrn+H_RrrCsTrrE&rrrDN\s7QBlhu3QTrqucrp\"RZrrBh4 +rrN+KrVlllp&F^b!5JL4!<2or!;lHhp&>2Fs8Vihrqucrqt:!^rrmoPs6KX_r;Qcqp&Fac!<2ut +!pfgar;Qcqp&Fac!<2ut"7,pb5Q1T^rq6UHlq#C-h!.XkF!<2fo!<)]mq>UHoq>UKpJ,90FrqQNhrrDlj +rrE&nrr@QEs7uZpp\FghrqQKnTDAN_rrDN`rrE&nrrD6Xs7uZpTDAKerqQKnq>('errN+Kq>UKp +J,0*ErqZTjrrDlirrE&mrr>:[s8)`qkP5&WrqHEmchd\$Mr;Z`q!/'tE!WITArr<<&s8N$!i.(G"!<2Wj!Vdc9s8W*"!$Ck5!<2Ti +"5k:$rriAss8W)qrrDNcrrE&qrrDNcrrrE%s56-A,QIZ@huRQs7cQ.rrE&U!!*&grrE&es7$$grpTmVrrE&es7$$grpTmCs8;ls^\n*3p\"Odhu*KSrqufo +rr>:]rrDBXrrB8#rrDups8DrurkJC2!;H0d!8m_S!;cWnrVlo<+8u3?r-.i6!8m_S!Vh0Cs8;ls +^\n*3n+H\\^\n*3rquforr=/=rrD*PrrA,XrrN%IrVt^RJ,~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/linear-fig.ps b/docsrc/nyquist/linear-fig.ps new file mode 100644 index 0000000..6b17165 --- /dev/null +++ b/docsrc/nyquist/linear-fig.ps @@ -0,0 +1,63 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: linear-fig.ps +%%CreationDate: Wed Jul 13 12:16:49 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2321 ASCII Bytes +image +s8N)ri;WlYrVPOQ!rr,oi;WlYrVPOQ!rr5oi;WlYqtT+L"98/n5N2YBrrN#SiW&rX!W2'=s8W*" +qt]4Ns8N,sro*nWrrW)t5N;_CrrW#rhr=\9rrW)tkMlOArrW)tqr7YUrrW)tr8RbVrr`/us*s)/ +s8N2us8S_Os8W*$qu?]bj8]/Z"8i,uoAflNrr`)ss8:pWs8N)rrr2s_jT#8[!;lcq!70a+s8N)r +rr2uijT#8[!;lcq!<)!Ys8N)rrr3#uJ*$_1rrDrprrBgqs8W*!qu-NpcfP3,rrDlnrrDfTs8W*! +qu-NpqrRkXrrDrprrDuYs8W*!qu$HoJ*-e2rrDrorrA\Rs8W*!qu$HokN;gErrDrorrDlWs8W*! +qu$HprdX,2s8N)pqu6YgkPtS^!;lZn!:T+Ns8N)rqu6ZfkPtS^!;lZn!<)*\s8N)rqu6]rJ*?n6 +TB#hFrrA\TrrV*HqtgUH@l2Ue`!;lTl!;#ITs8N)rq>UHnl2Ue`!;lTl!WIT6s8W*!qtU0k^Ztk!rrDlirrCC1 +s8W*!qtU0kpZheYrrDrkrrDl[s8W*!qtU0lrdX86s8N)rp\t6.li7"b!;lNj!71!2s8N)rp\t6f +li7"b!;lNj!;Ys\s8N)pp\t9nJ*d48rrDrirrBh#s8W*!qtC$icg:]3rrDrirrDZWs8W*!qtC$i +rTsRarrDrirrN+KmJm4d!;lHh!5Iq$s8N)rp&>$$jmJm4d!;lHh +!WIT:s8W*!qt0mg^[D.%rrDrgrrCC5s8W*!qt0mgp[8(]rrDrgrrDl_s8W*!qt0mhrdXD:s8N)p +oD\g*n,NFf!;lBf!71-6s8N)roD\gbn,NFf!;lBf!;Z*`s8N)roD\jjJ+3I>s7uQ_rrBh'rrW6! +qssaecg^r9s8DicrrDZ[rrW6!q""FbrUBggs8DicrrN+Knc&[jn9a^*!2&f]s8N)rnc&UPnc/Xh +!;lrrDrcrrBh)s8W*!q=+Cacgq,9rrDrcrrDZ]s8W*!qsaUcr:9mf +rrDrbrr>:Ts8W*!qsXObch%2:rrDrbrrDfbs8W*!qsXObq=FXdrrDrbrrE&is8W*!q:Vs8W*!qsFC`ht@$L +rrDr`rrD6Ts8W*!q:Xs8W*!qrrDr^rrDffs8W*!qs47^q=jph +rrDr^rrE&ms8W*!qs+1]5PY6[hrFV!rrCC?rrTCmqs+1]p\=aiYNPfJrrDlirrTD$q!.kZrqQKp +YNu)Mrr>:ZrrV'Oqs"+\htd('jrrDr\rrE&os8W*!qrn%[5PkE[ +rrDr[rrCsQs8W*!q<7hYkPG5YrrDr[rrDrms8W*!qrn%[r;-HnrrDrZrr>:\s8W*!qrdtZhu!HR +rrDrZrrD6Zs8W*!qrdtZqtpEnrrDrZrrDuos8W*!q<%\W5Q(Q]rrDrYrrCCCs8W*!qr[nYoDJXg +rrDrYrrDups8W*!qrRhXJ,TEIrrDrXrrA\is8W*!qrRhXn,<:drrDrXrrDZhs8W*!q;qVVr;HZq +rrDrWrr@QJs8W*!qrIbWTDnljrrDrWrrDNes8W*!qrIbWoD\dirrDrWrrE#ss8W*!qrIbZrdXtJ +s8N)rj8T1Qs8W-!!;Y[T!q60hs8N)rj8T2Ps8W-!!;kgV!r`0!s8N)rj8T2[J,fQK!;kdU!MBDl +rrDrUrrMTgs8N)rqu6Z2r;Qcoqu6YGr;Qckr;QfhJ,fNlqu>RQs7cQ.rVu?dJ,B9'rVu?dJ,B9' +rr;`m^]"3$r-nbIrnmbV!WW0"qr%MSrrDrSs8W*!qr%MSrrDrSs5!_NrrM$OrVlrts1eO4!Pdgr +rrN#rr;Qfqs7uZqYNu/e!rDp]rVln*hu3QVp&0C=rrN-!q>UK!p\k*nqYn8.rrHKQrVlokrqucs +rr;fo!O)7rrrW&r+8u3??e>8V!qlMArVlots7uZqYODGi!rDr3rVln*fDY^Np&0C=rrN-!q>UKP +j8JuZrU1j,rrKgZrVloqhYdBSpcmU7J,~> +%%EndData +%showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/linear-fig.ps.ORIGINAL b/docsrc/nyquist/linear-fig.ps.ORIGINAL new file mode 100644 index 0000000..5008114 --- /dev/null +++ b/docsrc/nyquist/linear-fig.ps.ORIGINAL @@ -0,0 +1,62 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: linear-fig.ps +%%CreationDate: Wed Jul 13 12:16:49 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +0 176 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2321 ASCII Bytes +image +s8N)ri;WlYrVPOQ!rr,oi;WlYrVPOQ!rr5oi;WlYqtT+L"98/n5N2YBrrN#SiW&rX!W2'=s8W*" +qt]4Ns8N,sro*nWrrW)t5N;_CrrW#rhr=\9rrW)tkMlOArrW)tqr7YUrrW)tr8RbVrr`/us*s)/ +s8N2us8S_Os8W*$qu?]bj8]/Z"8i,uoAflNrr`)ss8:pWs8N)rrr2s_jT#8[!;lcq!70a+s8N)r +rr2uijT#8[!;lcq!<)!Ys8N)rrr3#uJ*$_1rrDrprrBgqs8W*!qu-NpcfP3,rrDlnrrDfTs8W*! +qu-NpqrRkXrrDrprrDuYs8W*!qu$HoJ*-e2rrDrorrA\Rs8W*!qu$HokN;gErrDrorrDlWs8W*! +qu$HprdX,2s8N)pqu6YgkPtS^!;lZn!:T+Ns8N)rqu6ZfkPtS^!;lZn!<)*\s8N)rqu6]rJ*?n6 +TB#hFrrA\TrrV*HqtgUH@l2Ue`!;lTl!;#ITs8N)rq>UHnl2Ue`!;lTl!WIT6s8W*!qtU0k^Ztk!rrDlirrCC1 +s8W*!qtU0kpZheYrrDrkrrDl[s8W*!qtU0lrdX86s8N)rp\t6.li7"b!;lNj!71!2s8N)rp\t6f +li7"b!;lNj!;Ys\s8N)pp\t9nJ*d48rrDrirrBh#s8W*!qtC$icg:]3rrDrirrDZWs8W*!qtC$i +rTsRarrDrirrN+KmJm4d!;lHh!5Iq$s8N)rp&>$$jmJm4d!;lHh +!WIT:s8W*!qt0mg^[D.%rrDrgrrCC5s8W*!qt0mgp[8(]rrDrgrrDl_s8W*!qt0mhrdXD:s8N)p +oD\g*n,NFf!;lBf!71-6s8N)roD\gbn,NFf!;lBf!;Z*`s8N)roD\jjJ+3I>s7uQ_rrBh'rrW6! +qssaecg^r9s8DicrrDZ[rrW6!q""FbrUBggs8DicrrN+Knc&[jn9a^*!2&f]s8N)rnc&UPnc/Xh +!;lrrDrcrrBh)s8W*!q=+Cacgq,9rrDrcrrDZ]s8W*!qsaUcr:9mf +rrDrbrr>:Ts8W*!qsXObch%2:rrDrbrrDfbs8W*!qsXObq=FXdrrDrbrrE&is8W*!q:Vs8W*!qsFC`ht@$L +rrDr`rrD6Ts8W*!q:Xs8W*!qrrDr^rrDffs8W*!qs47^q=jph +rrDr^rrE&ms8W*!qs+1]5PY6[hrFV!rrCC?rrTCmqs+1]p\=aiYNPfJrrDlirrTD$q!.kZrqQKp +YNu)Mrr>:ZrrV'Oqs"+\htd('jrrDr\rrE&os8W*!qrn%[5PkE[ +rrDr[rrCsQs8W*!q<7hYkPG5YrrDr[rrDrms8W*!qrn%[r;-HnrrDrZrr>:\s8W*!qrdtZhu!HR +rrDrZrrD6Zs8W*!qrdtZqtpEnrrDrZrrDuos8W*!q<%\W5Q(Q]rrDrYrrCCCs8W*!qr[nYoDJXg +rrDrYrrDups8W*!qrRhXJ,TEIrrDrXrrA\is8W*!qrRhXn,<:drrDrXrrDZhs8W*!q;qVVr;HZq +rrDrWrr@QJs8W*!qrIbWTDnljrrDrWrrDNes8W*!qrIbWoD\dirrDrWrrE#ss8W*!qrIbZrdXtJ +s8N)rj8T1Qs8W-!!;Y[T!q60hs8N)rj8T2Ps8W-!!;kgV!r`0!s8N)rj8T2[J,fQK!;kdU!MBDl +rrDrUrrMTgs8N)rqu6Z2r;Qcoqu6YGr;Qckr;QfhJ,fNlqu>RQs7cQ.rVu?dJ,B9'rVu?dJ,B9' +rr;`m^]"3$r-nbIrnmbV!WW0"qr%MSrrDrSs8W*!qr%MSrrDrSs5!_NrrM$OrVlrts1eO4!Pdgr +rrN#rr;Qfqs7uZqYNu/e!rDp]rVln*hu3QVp&0C=rrN-!q>UK!p\k*nqYn8.rrHKQrVlokrqucs +rr;fo!O)7rrrW&r+8u3??e>8V!qlMArVlots7uZqYODGi!rDr3rVln*fDY^Np&0C=rrN-!q>UKP +j8JuZrU1j,rrKgZrVloqhYdBSpcmU7J,~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/logistic-fig.ps b/docsrc/nyquist/logistic-fig.ps new file mode 100644 index 0000000..bba10a3 --- /dev/null +++ b/docsrc/nyquist/logistic-fig.ps @@ -0,0 +1,69 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: logistic-fig.ps +%%CreationDate: Wed Jul 13 12:17:06 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 303 191 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 176 translate +-40 760 translate +288 -176 scale +% Image geometry +288 176 1 +% Transformation matrix +[ 288 0 0 176 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 2767 ASCII Bytes +image +li-tZo`+@Z"7Q,Jp[nLRrr^mG^\@C#mf*C@qk*WTs7$$lpcmC-n+$&MnG`[`T@`h@p[nLTs8MHg +ESpN_s7$$hhtR-M!;H-cnG`O(p\t0mp[nLTrrIWHrr2umo`+F\!It(IrrDZ_s7-*jrr;rrrrDfc +s7-*jrr;usrrDfcs7-*nrVunIs8Vics7-*nrVunIs8Vics7-*nqu?]2s8Vics7-*nqu?]2s8Vic +s7-*np](9Ns8V]_s7-*np](9Ns8Vics7-*nn,NFFs8Vics7-*nn,NFVs8Vics7-*nn,NFVs8Vic +s7-*nhuE`Fs8Vics7-*nhuE`Ns8V]_s7-*nhuE`Ns8Vics7-*n^]4?2s8Vics7-*n^]4?2s8Vic +s7-*nJ,fQGs8Vics7-*nJ,fQIs8Vics7-*nJ,fQIs8Vics760irr2p"rVuoho`+L^!<2ut"9/?# +p[nLVrrE&trr`9#s7c0co)A^grr3*"^[Lphs760irVc`t?e>&Es760irVc`t?gma]s760iqu-Nr ++7Jals760iqu-Nr+5chbs760ip\k*n]uTm>s760ip\k*nhuEHCs760ip\k*nhuEHCs760in,<7f +huEHCs760in,<7fn,N"Os760in,<7fn,N.Ss760ihu3QVn,N.Ss760ihu3QVp](![s760ihu3QV +p](![s760i^]"06qu?E_s760i^]"06qu?E_s760i^]"06qu?9[s760i^]"06rVuWas760iJ,TBK +rVuWas760iJ,TBKrVuWas760iJ,TBKrr;`bs7?6jrquctrr;`bs7?6jrquctrr;T^s7?6jrquct +rr;`bs7?6jrVQTqJ+rU8oD\ghqu6\Hp[nLWrrE#prrIWDo`+O_!<)fp!PeC$s7?6jqtpBo^\@C# +oD\gfqu6]3oCW(SrrDrnrrM$Oo`+O_!;HBj!T3YDs7?6jp\k*on+2V7o`+O_!;HHl"5!FBp[nLW +rrDflrr^mMO8&;HoD\gZrVluOqsX(Is7?6jn,<7gfDDcGo`+O_!:Tmd"7KXLp[nLWrrCsRs8Vic +s7?6jhu!HRp[nLWrrCsRs8Vics7?6j^\e$3qt'I[oD\g*qu6]op[nLWrrBh2rrN#ko`+O_!5JF2 +!WDcbs7?6jJ,B6HrV,saoD\f?qu6]qp[nLWrr@QGrrN,no`+R`!<2ip!WM]_s7H$jq#:Bh^\.X"rrDrkrrMl/p&F^b!;lQk!VbLEs7QBlp\=ahpYYZD +p&>$dq#:Bhn+H_RrrDN_rrM`[p&F^b!:T^_!Vc'Us7QBlht[6Op\"RZrrCsOs8Vids7QBl^\Ig0 +p\XX`p&>$,q#:Bhqt:!^rr@QDrrM`ip&F^b!.XeD!VcQcs7ZHmrqHEnp\sjcpAY-lp\t9grq6$drr2u5q#C-h!:TU\!;HKm!8mSOq#:?Op&>$drr2u]q#C-h +!5J4,!;HKm!;lQkq>UKpJ+`gAoD\airV6EgrrDlerrDfmrrN+Kq>^9j!;H-c!;HHl!2')eq>UH@ +o`"pcrVll\q>^9j!'g,U!;HHl!;ZHjqYpQnoD\gbrVlotJ,93ArrDZ^rrDfkrrA,Vs82fsrX\W# +!;$-g!:]jbqu6ZTo)A^aqu6X\qu?Qn!2&i^!;HBj!5\R4r;QfeJ+EU>p\XskrX\r,rVm!#&-)\, +rVllTrr2utrVlllrVm#8s8VQhrVn,Bqu?_H^[LporVqA^hs^I@rr7J_n+Z_Xs*qf@n,*"_!.Y"K +rnd\Us6K[bp[nLOrrDfcs6K[bp[nLOrrDfcs5!_RrrBh5rrDuqrrDflrr@QErr@QJrrE#rs8Drt +?iL'*qu-NpkPkJ^rkJ=0!WKk5rrDlns8Drt^]+65q>LUHorVllrrVuir!5JO5!;ZTn!9=(Y +!WG=[rrN*`rr2unrVt^RJ,~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/moog-fig.ps b/docsrc/nyquist/moog-fig.ps new file mode 100644 index 0000000..ba08a06 --- /dev/null +++ b/docsrc/nyquist/moog-fig.ps @@ -0,0 +1,2808 @@ +%!PS-Adobe-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: moog.ps +%%CreationDate: Tue Oct 11 08:13:23 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 1131 618 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456693 14.173228346456693 translate +% Translate to begin of first scanline +%0 603 translate +0 725 translate +1116 -603 scale +% Image geometry +1116 603 8 +% Transformation matrix +[ 1116 0 0 603 0 0 ] +% Strings to hold RGB-samples per scanline +/rstr 1116 string def +/gstr 1116 string def +/bstr 1116 string def +{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop} +true 3 +%%BeginData: 149912 ASCII Bytes +colorimage +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$VuHb#JUbC`_uG5~> +JcC<$JcC<$JcC<$VuHb#JUbC`_uG5~> +JcC<$JcC<$JcC<$VuHb#JUbC`_uG5~> +JcC<$JcC<$JcC<$VuHa(JH3Ca_uG5~> +JcC<$JcC<$JcC<$VuHa(JH3Ca_uG5~> +JcC<$JcC<$JcC<$VuHa(JH3Ca_uG5~> +JcC<$JcC<$JcC<$VuHg*!)S5r_LMRc_uG5~> +JcC<$JcC<$JcC<$VuHg*!)S5r_LMRc_uG5~> +JcC<$JcC<$JcC<$VuHg*!)S5r_LMRc_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +qZ$?kJcC<$JcC<$JcC<$[f6D9!2+oC_Z0W9_uG5~> +qZ$?kJcC<$JcC<$JcC<$[f6D9!2+oC_Z0W9_uG5~> +qZ$?kJcC<$JcC<$JcC<$[f6D9!2+oC_Z0W9_uG5~> +q>UHJr;ZiNcMmllJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q>UHJr;ZiNcMmllJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q>UHJr;ZiNcMmllJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q#C9mcMmp(!.k0$s+13$s+13$s69Ob?N?aMs2+g9!5nhe~> +q#C9mcMmp(!.k0$s+13$s+13$s69Ob?N?aMs2+g9!5nhe~> +q#C9mcMmp(!.k0$s+13$s+13$s69Ob?N?aMs2+g9!5nhe~> +q#C9mci4&o!!%TMJcC<$JcC<$JcG!7!abr#JcEUerrBt:J,~> +q#C9mci4&o!!%TMJcC<$JcC<$JcG!7!abr#JcEUerrBt:J,~> +q#C9mci4&o!!%TMJcC<$JcC<$JcG!7!abr#JcEUerrBt:J,~> +q#C9mdJj7+BDqm^s+13$s+13$s+147rrQO-TRm-[s8N):s*t~> +q#C9mdJj7+BDqm^s+13$s+13$s+147rrQO-TRm-[s8N):s*t~> +q#C9mdJj7+BDqm^s+13$s+13$s+147rrQO-TRm-[s8N):s*t~> +q#C9mrVucq"om8'!)1*)s82j"l"9uiZMjh$!<<)s!<<'!ReZr7s+13$s+13$s+14:rrQO-TRm-[ +s8N):s*t~> +q#C9mrVucq"om8'!)1*)s82j"l"9uiZMjh$!<<)s!<<'!ReZr7s+13$s+13$s+14:rrQO-TRm-[ +s8N):s*t~> +q#C9mrVucq"om8'!)1*)s82j"l"9uiZMjh$!<<)s!<<'!ReZr7s+13$s+13$s+14:rrQO-TRm-[ +s8N):s*t~> +q#C9mrVll^r;Zi'qu?`1rr2u_r;[#!s-`ofN;ihWl2:V^rrD<^!<)rr!.k0$s+13$s+13$s69Ob +?N?aMs2+g9!5nhe~> +q#C9mrVll^r;Zi'qu?`1rr2u_r;[#!s-`ofN;ihWl2:V^rrD<^!<)rr!.k0$s+13$s+13$s69Ob +?N?aMs2+g9!5nhe~> +q#C9mrVll^r;Zi'qu?`1rr2u_r;[#!s-`ofN;ihWl2:V^rrD<^!<)rr!.k0$s+13$s+13$s69Ob +?N?aMs2+g9!5nhe~> +q#C9mr;Z]q!b_#]rVuq2rVufr!q?6CrVurOrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC +_Z0W9_uG5~> +q#C9mr;Z]q!b_#]rVuq2rVufr!q?6CrVurOrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC +_Z0W9_uG5~> +q#C9mr;Z]q!b_#]rVuq2rVufr!q?6CrVurOrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC +_Z0W9_uG5~> +q#C9mr;Z]q!oa1Zr;cfrr;clt!:]sf!1Noer;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUe +rrBt:J,~> +q#C9mr;Z]q!oa1Zr;cfrr;clt!:]sf!1Noer;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUe +rrBt:J,~> +q#C9mr;Z]q!oa1Zr;cfrr;clt!:]sf!1Noer;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUe +rrBt:J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!,)<2r;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!,)<2r;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!,)<2r;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;osrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q#C9mr;Z]qrr;osrVufrrr;osrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q#C9mr;Z]qrr;osrVufrrr;osrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q#C9mr;Z]qrr;osrVufrrr;osrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q#C9mr;Z]qrr;osrVufrrr;osrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q#C9mr;Z]qrr;osrVufrrr;osrr;osrr;osrVufrJcC<$JcC<$JcC<$l2Lfl!2+oC_Z0W9_uG5~> +q#C9mr;Z]qrr;osrVufrrr;rt!,)<2r;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!,)<2r;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!,)<2r;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!1Noer;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!1Noer;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrrr;rt!1Noer;cisr;cfrr;_EKJcC<$JcC<$JcG!7!abr#JcEUerrBt: +J,~> +q#C9mr;Z]qrr;osrVufrs8N)XrVurFrr2t2rW!#Ys*XbFrVljkrW!#ad# +q#C9mr;Z]qrr;osrVufrs8N)XrVurFrr2t2rW!#Ys*XbFrVljkrW!#ad# +q#C9mr;Z]qrr;osrVufrs8N)XrVurFrr2t2rW!#Ys*XbFrVljkrW!#ad# +q>UHJr;ZiNrr2u_r;Zo`s8W#t!9sL_r;[#,s-`ofN;`bV^&.j1I/O$Fl2L\_ZMX\&fn'0Ss+13$ +s+13$s6Tae?N?aMs2+g9!5nhe~> +q>UHJr;ZiNrr2u_r;Zo`s8W#t!9sL_r;[#,s-`ofN;`bV^&.j1I/O$Fl2L\_ZMX\&fn'0Ss+13$ +s+13$s6Tae?N?aMs2+g9!5nhe~> +q>UHJr;ZiNrr2u_r;Zo`s8W#t!9sL_r;[#,s-`ofN;`bV^&.j1I/O$Fl2L\_ZMX\&fn'0Ss+13$ +s+13$s6Tae?N?aMs2+g9!5nhe~> +qZ$?ks8Vrrs8Vusrr;os"Rqi[9X=Qq"hdS0B;be-!<)p#]hAERfn'0Ss+13$s+13$s6K[d?N?aM +s2+g9!5nhe~> +qZ$?ks8Vrrs8Vusrr;os"Rqi[9X=Qq"hdS0B;be-!<)p#]hAERfn'0Ss+13$s+13$s6K[d?N?aM +s2+g9!5nhe~> +qZ$?ks8Vrrs8Vusrr;os"Rqi[9X=Qq"hdS0B;be-!<)p#]hAERfn'0Ss+13$s+13$s6K[d?N?aM +s2+g9!5nhe~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +i;``UJcC<$JcC<$JcC<$bl7`O!2+oC_Z0W9_uG5~> +iVroBr;Zi^JcC<$JcC<$JcC<$c2RiP!2+oC_Z0W9_uG5~> +iVroBr;Zi^JcC<$JcC<$JcC<$c2RiP!2+oC_Z0W9_uG5~> +iVroBr;Zi^JcC<$JcC<$JcC<$c2RiP!2+oC_Z0W9_uG5~> +iW&cTJcC<$JcC<$JcC<$c2RiP!2+oC_Z0W9_uG5~> +iW&cTJcC<$JcC<$JcC<$c2RiP!2+oC_Z0W9_uG5~> +iW&cTJcC<$JcC<$JcC<$c2RiP!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcC<$VuHg*!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcFp5s*TCt_uBdF!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcFp5s*TCt_uBdF!2+oC_Z0W9_uG5~> +JcC<$JcC<$JcFp5s*TCt_uBdF!2+oC_Z0W9_uG5~> +JcC<$JcC<$MuNdjrVusml1tAW!:^$gI"D=8rrQO-TRm-[s8N):s*t~> +JcC<$JcC<$MuNdjrVusml1tAW!:^$gI"D=8rrQO-TRm-[s8N):s*t~> +JcC<$JcC<$MuNdjrVusml1tAW!:^$gI"D=8rrQO-TRm-[s8N):s*t~> +JcC<$JcC<$M>m\:RK.a1rrUjRfn'1,rrQO-TRm-[s8N):s*t~> +JcC<$JcC<$M>m\:RK.a1rrUjRfn'1,rrQO-TRm-[s8N):s*t~> +JcC<$JcC<$M>m\:RK.a1rrUjRfn'1,rrQO-TRm-[s8N):s*t~> +g]%9:JcC<$JcC<$Y5eM%!1N]_!!%TM^&J/[B>=->!abr#JcEUerrBt:J,~> +g]%9:JcC<$JcC<$Y5eM%!1N]_!!%TM^&J/[B>=->!abr#JcEUerrBt:J,~> +g]%9:JcC<$JcC<$Y5eM%!1N]_!!%TM^&J/[B>=->!abr#JcEUerrBt:J,~> +h#@H=!*OmQJcC<$JcDqR!s"8[^%q[.!.k0`rrp.;!#9.]q#:D&!2+oC_Z0W9_uG5~> +h#@H=!*OmQJcC<$JcDqR!s"8[^%q[.!.k0`rrp.;!#9.]q#:D&!2+oC_Z0W9_uG5~> +h#@H=!*OmQJcC<$JcDqR!s"8[^%q[.!.k0`rrp.;!#9.]q#:D&!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR"9AIL!875K!!%TM^&J)Iqu?d5B>=?D!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcDqR"9AIL!875K!!%TM^&J)Iqu?d5B>=?D!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcDqR"9AIL!875K!!%TM^&J)Iqu?d5B>=?D!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcDqR"T\Se9MF^Jrr<&rrs%tj9E7banGW@hnAgstrVm&,9ME.a!;uj#l).2T +B>&lrkPkOsq#CI2B>=HG!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcDqR"T\Se9MF^Jrr<&rrs%tj9E7banGW@hnAgstrVm&,9ME.a!;uj#l).2T +B>&lrkPkOsq#CI2B>=HG!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcDqR"T\Se9MF^Jrr<&rrs%tj9E7banGW@hnAgstrVm&,9ME.a!;uj#l).2T +B>&lrkPkOsq#CI2B>=HG!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcDqR"T\T&f`6Esrr<&srs7j_^&S,c9MF.=rr[X]!!*#u#-trBs2P*>rVm,L +9[NguHiSQ]rrMSDJUdZK!+5F""Vk[b?N?aMs2+g9!5nhe~> +h#@Gj!'l,8JcC<$JcDqR"T\T&f`6Esrr<&srs7j_^&S,c9MF.=rr[X]!!*#u#-trBs2P*>rVm,L +9[NguHiSQ]rrMSDJUdZK!+5F""Vk[b?N?aMs2+g9!5nhe~> +h#@Gj!'l,8JcC<$JcDqR"T\T&f`6Esrr<&srs7j_^&S,c9MF.=rr[X]!!*#u#-trBs2P*>rVm,L +9[NguHiSQ]rrMSDJUdZK!+5F""Vk[b?N?aMs2+g9!5nhe~> +h#@Gj!'l,8JcC<$JcDqR!!*#u!lk;0r;Q`sr;Qe1^&@s5kl=EHrVultrr2slrVlo(!<3!"n4^n% +rr^pS!57h#!0;[2mJm;'!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!*#u!lk;0r;Q`sr;Qe1^&@s5kl=EHrVultrr2slrVlo(!<3!"n4^n% +rr^pS!57h#!0;[2mJm;'!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!*#u!lk;0r;Q`sr;Qe1^&@s5kl=EHrVultrr2slrVlo(!<3!"n4^n% +rr^pS!57h#!0;[2mJm;'!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)ut!iH%3rVlitrVlr>!9sF]!iH%(rVultrr3!!VuH\sn,WIf!N,qq +s8N'!I.%"8muN$LrdOoTp&G7DJ(J$-TRm-[s8N):s*t~> +h#@Gj!'l,8JcC<$JcDqR!!)ut!iH%3rVlitrVlr>!9sF]!iH%(rVultrr3!!VuH\sn,WIf!N,qq +s8N'!I.%"8muN$LrdOoTp&G7DJ(J$-TRm-[s8N):s*t~> +h#@Gj!'l,8JcC<$JcDqR!!)ut!iH%3rVlitrVlr>!9sF]!iH%(rVultrr3!!VuH\sn,WIf!N,qq +s8N'!I.%"8muN$LrdOoTp&G7DJ(J$-TRm-[s8N):s*t~> +h#@Gj!'l,8JcC<$JcDqR!!)rs!dk"$rr2rurVlnG!;lcti;dNhs8N)urr\\i9YL?'!,)',JcG!7 +!5J=0![iKLrr3%,!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)rs!dk"$rr2rurVlnG!;lcti;dNhs8N)urr\\i9YL?'!,)',JcG!7 +!5J=0![iKLrr3%,!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)rs!dk"$rr2rurVlnG!;lcti;dNhs8N)urr\\i9YL?'!,)',JcG!7 +!5J=0![iKLrr3%,!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)ors%EOZs8N)ts8N)qs8N)ts8N)trrebj!)0 +h#@Gj!'l,8JcC<$JcDqR!!)ors%EOZs8N)ts8N)qs8N)ts8N)trrebj!)0 +h#@Gj!'l,8JcC<$JcDqR!!)ors%EOZs8N)ts8N)qs8N)ts8N)trrebj!)0 +h#@Gj!'l,8JcC<$JcDqR!!)or"mJ^.s8N)ts8N)qs8N)ts8N)srsI__!!#^Ws8N'!n:CW!rrp.; +!%39Jq#:D&!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)or"mJ^.s8N)ts8N)qs8N)ts8N)srsI__!!#^Ws8N'!n:CW!rrp.; +!%39Jq#:D&!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)or"mJ^.s8N)ts8N)qs8N)ts8N)srsI__!!#^Ws8N'!n:CW!rrp.; +!%39Jq#:D&!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)lq"OI.;rrE#t!bVMdqu6ZsN;`eV!;c^$l$NJis8Q^3a8Gr +h#@Gj!'l,8JcC<$JcDqR!!)lq"OI.;rrE#t!bVMdqu6ZsN;`eV!;c^$l$NJis8Q^3a8Gr +h#@Gj!'l,8JcC<$JcDqR!!)lq"OI.;rrE#t!bVMdqu6ZsN;`eV!;c^$l$NJis8Q^3a8Gr +h#@Gj!'l,8JcC<$JcDqR!!)ip"2+]J!<)p!Z2gg#rrVEbd/F"E!<3!!!:^!f#Oh]ns8Sts9`4nk +]o7OBgA_4]!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)ip"2+]J!<)p!Z2gg#rrVEbd/F"E!<3!!!:^!f#Oh]ns8Sts9`4nk +]o7OBgA_4]!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)ip"2+]J!<)p!Z2gg#rrVEbd/F"E!<3!!!:^!f#Oh]ns8Sts9`4nk +]o7OBgA_4]!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDqR!!)fo!h')hr;Qgl!9*nV!PN.Ds8N)urrE,*rVm<,BE/"r!!$Zbs8UG> +d"25NrrQO-TRm-[s8N):s*t~> +h#@Gj!'l,8JcC<$JcDqR!!)fo!h')hr;Qgl!9*nV!PN.Ds8N)urrE,*rVm<,BE/"r!!$Zbs8UG> +d"25NrrQO-TRm-[s8N):s*t~> +h#@Gj!'l,8JcC<$JcDqR!!)fo!h')hr;Qgl!9*nV!PN.Ds8N)urrE,*rVm<,BE/"r!!$Zbs8UG> +d"25NrrQO-TRm-[s8N):s*t~> +h#@Gj!'l,8JcC<$JcDtS!ndS,q#:AB!;uj&fh>)ds8U,5l2CVkci='ms8N'!ZN's&!7:`F!7:TC +!2kDJg&D+\!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDtS!ndS,q#:AB!;uj&fh>)ds8U,5l2CVkci='ms8N'!ZN's&!7:`F!7:TC +!2kDJg&D+\!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDtS!ndS,q#:AB!;uj&fh>)ds8U,5l2CVkci='ms8N'!ZN's&!7:`F!7:TC +!2kDJg&D+\!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcE"TquHQm!Ure[rs%_V9E8_'nGWCa!!iN(l+L^0I+eGt"lYmM!.;J2s4I>Q +?N?aMs2+g9!5nhe~> +h#@Gj!'l,8JcC<$JcE"TquHQm!Ure[rs%_V9E8_'nGWCa!!iN(l+L^0I+eGt"lYmM!.;J2s4I>Q +?N?aMs2+g9!5nhe~> +h#@Gj!'l,8JcC<$JcE"TquHQm!Ure[rs%_V9E8_'nGWCa!!iN(l+L^0I+eGt"lYmM!.;J2s4I>Q +?N?aMs2+g9!5nhe~> +h#@Gj!'l,8JcC<$JcDMF!:YR>Y5\Q1!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDMF!:YR>Y5\Q1!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcDMF!:YR>Y5\Q1!2+oC_Z0W9_uG5~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'l,8JcC<$JcC<$JcF'r!abr#JcEUerrBt:J,~> +h#@Gj!'mpkJO&`j!4ROZJcC<$JcDkP!abr#JcEUerrBt:J,~> +h#@Gj!'mpkJO&`j!4ROZJcC<$JcDkP!abr#JcEUerrBt:J,~> +h#@Gj!'mpkJO&`j!4ROZJcC<$JcDkP!abr#JcEUerrBt:J,~> +h#@Gj!'mpkJH53?!2+oCJcC<$JcDkP!abr#JcEUerrBt:J,~> +h#@Gj!'mpkJH53?!2+oCJcC<$JcDkP!abr#JcEUerrBt:J,~> +h#@Gj!'mpkJH53?!2+oCJcC<$JcDkP!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<C?N?aMs+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<C?N?aMs+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<C?N?aMs+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=nh/c\.fs+13DrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=nh/c\.fs+13DrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=nh/c\.fs+13DrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=n^ApNMs+13DrrQO-TRm-[ +s8N):s*t~> +h#@Gj!'mpk!<=n^ApNMs+13DrrQO-TRm-[ +s8N):s*t~> +h#@Gj!'mpk!<=n^ApNMs+13DrrQO-TRm-[ +s8N):s*t~> +h#@Gj!'mpk!<=i!'l,8JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=i!'l,8JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=i!'l,8JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=F"H96k!!(dR +!l"_#JcC<$U&P1$!2+oC_Z0W9_uG5~> +h#@Gj!'mpk!<=F"H96k!!(dR +!l"_#JcC<$U&P1$!2+oC_Z0W9_uG5~> +h#@Gj!'mpk!<=F"H96k!!(dR +!l"_#JcC<$U&P1$!2+oC_Z0W9_uG5~> +h#@Gj!'mpk!<=i!'l,8 +JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=i!'l,8 +JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=i!'l,8 +JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=i!'l,8 +JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=i!'l,8 +JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<=i!'l,8 +JcDGD!abr#JcEUerrBt:J,~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=Aq[9W.CZrs8,7RK3B.B)o70s8N)RrrTq85_8rd +s.TGo?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=Aq[9W.CZrs8,7RK3B.B)o70s8N)RrrTq85_8rd +s.TGo?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=Aq[9W.CZrs8,7RK3B.B)o70s8N)RrrTq85_8rd +s.TGo?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=->l$NK:rVultr;RGp9YLK+fh>)ms8Q_E!!'=hiFdQ1s8N)R +rrTq85_8rds02M*TMV +h#@Gj!'mpk!<=->l$NK:rVultr;RGp9YLK+fh>)ms8Q_E!!'=hiFdQ1s8N)R +rrTq85_8rds02M*TMV +h#@Gj!'mpk!<=->l$NK:rVultr;RGp9YLK+fh>)ms8Q_E!!'=hiFdQ1s8N)R +rrTq85_8rds02M*TMV +h#@Gj!'nF$!9!ML!<=%k!q61`rVultr;Qe1^&@s5kl=EHrr;uu!7:68rrCgR!l"_# +JcC<$Yl=]rrW!!rT^V^V!abr#JcEUerrBt:J,~> +h#@Gj!'nF$!9!ML!<=%k!q61`rVultr;Qe1^&@s5kl=EHrr;uu!7:68rrCgR!l"_# +JcC<$Yl=]rrW!!rT^V^V!abr#JcEUerrBt:J,~> +h#@Gj!'nF$!9!ML!<=%k!q61`rVultr;Qe1^&@s5kl=EHrr;uu!7:68rrCgR!l"_# +JcC<$Yl=]rrW!!rT^V^V!abr#JcEUerrBt:J,~> +h#@Gj!'nF$"$e&LchIG?!$[!op&>)C!2/9M!+5U'!^N+8qZ$QqhuE]Vo`+pks8N*"VuH\sn,WIf +!keTurVlr`9RQj>rrDusrrDusrrE#ts*XbErrE#trrE#t!lk<*r;Qhr!4)V(rrDNfrrCgR!l"_# +JcC<$Yl=]rqZ$[oT^VgY!abr#JcEUerrBt:J,~> +h#@Gj!'nF$"$e&LchIG?!$[!op&>)C!2/9M!+5U'!^N+8qZ$QqhuE]Vo`+pks8N*"VuH\sn,WIf +!keTurVlr`9RQj>rrDusrrDusrrE#ts*XbErrE#trrE#t!lk<*r;Qhr!4)V(rrDNfrrCgR!l"_# +JcC<$Yl=]rqZ$[oT^VgY!abr#JcEUerrBt:J,~> +h#@Gj!'nF$"$e&LchIG?!$[!op&>)C!2/9M!+5U'!^N+8qZ$QqhuE]Vo`+pks8N*"VuH\sn,WIf +!keTurVlr`9RQj>rrDusrrDusrrE#ts*XbErrE#trrE#t!lk<*r;Qhr!4)V(rrDNfrrCgR!l"_# +JcC<$Yl=]rqZ$[oT^VgY!abr#JcEUerrBt:J,~> +h#@Gj!'nF$!'pM`![;U0qYpQr,(]derrRZMT]#hM?haU&5aU[4s8N)Vs8N)ks8N*!rr\\i9YL?' +!IOn@s8N)ss8N)ss8N)prrhi3HiO0Fs8N)trrIKIqu6`V!,)<2rrDNfrrCgR!l"_#JcC<$Yl=]r +p](OqT^Vp\?N?aMs2+g9!5nhe~> +h#@Gj!'nF$!'pM`![;U0qYpQr,(]derrRZMT]#hM?haU&5aU[4s8N)Vs8N)ks8N*!rr\\i9YL?' +!IOn@s8N)ss8N)ss8N)prrhi3HiO0Fs8N)trrIKIqu6`V!,)<2rrDNfrrCgR!l"_#JcC<$Yl=]r +p](OqT^Vp\?N?aMs2+g9!5nhe~> +h#@Gj!'nF$!'pM`![;U0qYpQr,(]derrRZMT]#hM?haU&5aU[4s8N)Vs8N)ks8N*!rr\\i9YL?' +!IOn@s8N)ss8N)ss8N)prrhi3HiO0Fs8N)trrIKIqu6`V!,)<2rrDNfrrCgR!l"_#JcC<$Yl=]r +p](OqT^Vp\?N?aMs2+g9!5nhe~> +h#@Gj!'nF$!'pD]![;U0rVllu,(]derrRZM9&Mr7(%hP15aU[6!!(pV!fR-DpAY3`!0$pW"I];j +9W.jhrrDcmrrDusrrDusrrDrr#2u"EZKV>hrVultrVultqZ$Qqrr;uun,NCfg]%Aj!'kLS5_22* +5QE2)!!H,k=ob4Hs2+g9!5nhe~> +h#@Gj!'nF$!'pD]![;U0rVllu,(]derrRZM9&Mr7(%hP15aU[6!!(pV!fR-DpAY3`!0$pW"I];j +9W.jhrrDcmrrDusrrDusrrDrr#2u"EZKV>hrVultrVultqZ$Qqrr;uun,NCfg]%Aj!'kLS5_22* +5QE2)!!H,k=ob4Hs2+g9!5nhe~> +h#@Gj!'nF$!'pD]![;U0rVllu,(]derrRZM9&Mr7(%hP15aU[6!!(pV!fR-DpAY3`!0$pW"I];j +9W.jhrrDcmrrDusrrDusrrDrr#2u"EZKV>hrVultrVultqZ$Qqrr;uun,NCfg]%Aj!'kLS5_22* +5QE2)!!H,k=ob4Hs2+g9!5nhe~> +h#@Gj!'nF$!'p;Z"X7p3rr=6os7QBnIfL53!!GQRpAb3NrrTJ+a7fN7f`9(krsI__!!#^Ws8N'! +l1b5X!;uls!;uls!;uiuZ2hT;s8N)ts8N)ts8N)qs8N)us8N)fs8N)RrrTq84b3Ta!29Gq'd +h#@Gj!'nF$!'p;Z"X7p3rr=6os7QBnIfL53!!GQRpAb3NrrTJ+a7fN7f`9(krsI__!!#^Ws8N'! +l1b5X!;uls!;uls!;uiuZ2hT;s8N)ts8N)ts8N)qs8N)us8N)fs8N)RrrTq84b3Ta!29Gq'd +h#@Gj!'nF$!'p;Z"X7p3rr=6os7QBnIfL53!!GQRpAb3NrrTJ+a7fN7f`9(krsI__!!#^Ws8N'! +l1b5X!;uls!;uls!;uiuZ2hT;s8N)ts8N)ts8N)qs8N)us8N)fs8N)RrrTq84b3Ta!29Gq'd +h#@Jk!%o"p!!4>E,(]derrRZMQ/KCW8G<)c5aU[5s8N)VrrVZiI.mR@VbHse#jH^:N;roj!6>$; +!Usb$s8N)ss8N)ss8N)trrTJ+a8Q& +h#@Jk!%o"p!!4>E,(]derrRZMQ/KCW8G<)c5aU[5s8N)VrrVZiI.mR@VbHse#jH^:N;roj!6>$; +!Usb$s8N)ss8N)ss8N)trrTJ+a8Q& +h#@Jk!%o"p!!4>E,(]derrRZMQ/KCW8G<)c5aU[5s8N)VrrVZiI.mR@VbHse#jH^:N;roj!6>$; +!Usb$s8N)ss8N)ss8N)trrTJ+a8Q& +h#@Jk!%o"p!!4>E,(]derrRZMT]#hM?hsa(5aU[2s8N)UrrTk6a8#Z9i;gptrrE,hrr35m!!*'! +VZ9EgrrKEorr;uur;Zcsr;ZcsrVultr;ZcsrVultrVlr)!2obp!pK^3rr;uun,NCfg]%>i!'l,8 +JcDtS!20/g!Yo(GrVlq+!2..-"2+[7^%VI.]`8&cQN-sb_uG5~> +h#@Jk!%o"p!!4>E,(]derrRZMT]#hM?hsa(5aU[2s8N)UrrTk6a8#Z9i;gptrrE,hrr35m!!*'! +VZ9EgrrKEorr;uur;Zcsr;ZcsrVultr;ZcsrVultrVlr)!2obp!pK^3rr;uun,NCfg]%>i!'l,8 +JcDtS!20/g!Yo(GrVlq+!2..-"2+[7^%VI.]`8&cQN-sb_uG5~> +h#@Jk!%o"p!!4>E,(]derrRZMT]#hM?hsa(5aU[2s8N)UrrTk6a8#Z9i;gptrrE,hrr35m!!*'! +VZ9EgrrKEorr;uur;Zcsr;ZcsrVultr;ZcsrVultrVlr)!2obp!pK^3rr;uun,NCfg]%>i!'l,8 +JcDtS!20/g!Yo(GrVlq+!2..-"2+[7^%VI.]`8&cQN-sb_uG5~> +h#@Gj!'nF$!'p;Z"X7p3rr=6os7QBnIfQ/"rr?F)!!5EPkP5)W!8[YVVbH(GrrV.QVu?Vr!4)S'% +01&@s6p!gI-L\2f`:"1s8N)ss8N)ss8N)ts8N'!nGWCe!<)rt!;uiu9E=&MrrKfGrVultn,NCfg +]%>i!'l,8JcDtS!208j!Yo(GqYpV(!2.+,rr<$mpAY2,!!&;arrBt:J,~> +h#@Gj!'nF$!'p;Z"X7p3rr=6os7QBnIfQ/"rr?F)!!5EPkP5)W!8[YVVbH(GrrV.QVu?Vr!4)S'% +01&@s6p!gI-L\2f`:"1s8N)ss8N)ss8N)ts8N'!nGWCe!<)rt!;uiu9E=&MrrKfGrVultn,NCfg +]%>i!'l,8JcDtS!208j!Yo(GqYpV(!2.+,rr<$mpAY2,!!&;arrBt:J,~> +h#@Gj!'nF$!'p;Z"X7p3rr=6os7QBnIfQ/"rr?F)!!5EPkP5)W!8[YVVbH(GrrV.QVu?Vr!4)S'% +01&@s6p!gI-L\2f`:"1s8N)ss8N)ss8N)ts8N'!nGWCe!<)rt!;uiu9E=&MrrKfGrVultn,NCfg +]%>i!'l,8JcDtS!208j!Yo(GqYpV(!2.+,rr<$mpAY2,!!&;arrBt:J,~> +h#@Gj!'nF$!'pD]!Yo\#rVllu,(]derrRZMT]#hQ?Na%Yasrr^:A!9*JJ"5s4[iS=G7^ApNMs+13Srretp'jn0=rrQO-TYLL/!2fh1q#:HCVZ6^^ +s8N):s*t~> +h#@Gj!'nF$!'pD]!Yo\#rVllu,(]derrRZMT]#hQ?Na%Yasrr^:A!9*JJ"5s4[iS=G7^ApNMs+13Srretp'jn0=rrQO-TYLL/!2fh1q#:HCVZ6^^ +s8N):s*t~> +h#@Gj!'nF$!'pD]!Yo\#rVllu,(]derrRZMT]#hQ?Na%Yasrr^:A!9*JJ"5s4[iS=G7^ApNMs+13Srretp'jn0=rrQO-TYLL/!2fh1q#:HCVZ6^^ +s8N):s*t~> +h#@Gj!'nF$!'pM`!Yo@_qYpQr,(]derrRZMT]#hNa63$nrrCgR!q +h#@Gj!'nF$!'pM`!Yo@_qYpQr,(]derrRZMT]#hNa63$nrrCgR!q +h#@Gj!'nF$!'pM`!Yo@_qYpQr,(]derrRZMT]#hNa63$nrrCgR!q +h#@Gj!'nF$"$dT6^\@a/!$[!op&>)C!2.[+ +h#@Gj!'nF$"$dT6^\@a/!$[!op&>)C!2.[+ +h#@Gj!'nF$"$dT6^\@a/!$[!op&>)C!2.[+ +h#@Gj!'nF$!8$lC!<= +h#@Gj!'nF$!8$lC!<= +h#@Gj!'nF$!8$lC!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=*Brr@HGs8N)r +s8N)rrr[WKN2QRQ!,)',rr;uu]`8!3_uG5~> +h#@Gj!'mpk!<=*Brr@HGs8N)r +s8N)rrr[WKN2QRQ!,)',rr;uu]`8!3_uG5~> +h#@Gj!'mpk!<=*Brr@HGs8N)r +s8N)rrr[WKN2QRQ!,)',rr;uu]`8!3_uG5~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=GrrDrr +rrDrr"H;Tc!.=_E!bVMRr;QfeBE%r2!5/@3!5nhe~> +h#@Gj!'mpk!<=GrrDrr +rrDrr"H;Tc!.=_E!bVMRr;QfeBE%r2!5/@3!5nhe~> +h#@Gj!'mpk!<=GrrDrr +rrDrr"H;Tc!.=_E!bVMRr;QfeBE%r2!5/@3!5nhe~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=8^&J'/!5AL5!5nhe~> +h#@Gj!'mpk!<=8^&J'/!5AL5!5nhe~> +h#@Gj!'mpk!<=8^&J'/!5AL5!5nhe~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=nh/c\.fs+13DrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=nh/c\.fs+13DrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=nh/c\.fs+13DrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=>1s8)fDs7lWrI&GrHrrRZMTRm,os+13$s/l;&?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=>1s8)fDs7lWrI&GrHrrRZMTRm,os+13$s/l;&?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=>1s8)fDs7lWrI&GrHrrRZMTRm,os+13$s/l;&?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=>0rr^pS!85]u$J>CZl2UeQcqFGdbl7`o!2+oCJcC<$JcDkP!abr#JcEUerrBt: +J,~> +h#@Gj!'mpk!<=>0rr^pS!85]u$J>CZl2UeQcqFGdbl7`o!2+oCJcC<$JcDkP!abr#JcEUerrBt: +J,~> +h#@Gj!'mpk!<=>0rr^pS!85]u$J>CZl2UeQcqFGdbl7`o!2+oCJcC<$JcDkP!abr#JcEUerrBt: +J,~> +h#@Gj!'mpk!<=>/s8N)Ds8N)rrrQg5g!0NuIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)Ds8N)rrrQg5g!0NuIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)Ds8N)rrrQg5g!0NuIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)Ds8N)rrrUOII*MZmIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)Ds8N)rrrUOII*MZmIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)Ds8N)rrrUOII*MZmIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)Ds8N)qs8N)DrrRZMTRm,os+13$s/l;&?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=>/s8N)Ds8N)qs8N)DrrRZMTRm,os+13$s/l;&?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=>/s8N)Ds8N)qs8N)DrrRZMTRm,os+13$s/l;&?N?aMs2+g9!5nhe~> +h#@Gj!'mpk!<=>/s8N)krs%tj9E7banG`FfN;WbVrrA#V!!;-Zs8DuuN;*AP!;c`q!<3!&iL3F? +!.;KXrro]%9YKZjrVm&,9ME.a!:9^eIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)krs%tj9E7banG`FfN;WbVrrA#V!!;-Zs8DuuN;*AP!;c`q!<3!&iL3F? +!.;KXrro]%9YKZjrVm&,9ME.a!:9^eIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)krs%tj9E7banG`FfN;WbVrrA#V!!;-Zs8DuuN;*AP!;c`q!<3!&iL3F? +!.;KXrro]%9YKZjrVm&,9ME.a!:9^eIfQ-ms+13$s+13PrrQO-TRm-[s8N):s*t~> +h#@Gj!'mpk!<=>/s8N)lrs7j_^&S,c9MF.=rrT(u!<)p"i;`l:rVlluZM+=u!;ld*i;e9*s3Lbd +s8V>2!4)V(#-trBs2P*>rr32.^&S,Q!!)Bc!e13CJcC<$JcC<$XoAH0!2+oC_Z.^X!>X#Zs*t~> +h#@Gj!'mpk!<=>/s8N)lrs7j_^&S,c9MF.=rrT(u!<)p"i;`l:rVlluZM+=u!;ld*i;e9*s3Lbd +s8V>2!4)V(#-trBs2P*>rr32.^&S,Q!!)Bc!e13CJcC<$JcC<$XoAH0!2+oC_Z.^X!>X#Zs*t~> +h#@Gj!'mpk!<=>/s8N)lrs7j_^&S,c9MF.=rrT(u!<)p"i;`l:rVlluZM+=u!;ld*i;e9*s3Lbd +s8V>2!4)V(#-trBs2P*>rr32.^&S,Q!!)Bc!e13CJcC<$JcC<$XoAH0!2+oC_Z.^X!>X#Zs*t~> +h#@Gj!'mpk!<=>/s8N)lrrHcGrVlua!)2n]rrQg5l2CV`Mu_6(rrMV%p&G$lqu6kJ!87DP9E>%k +!q61`rr2slrVlo(!<2uu9`=tlZ2j7k!e13CJcC<$JcC<$XoAH0!2+oC_Z.[W!3Q.uJ,~> +h#@Gj!'mpk!<=>/s8N)lrrHcGrVlua!)2n]rrQg5l2CV`Mu_6(rrMV%p&G$lqu6kJ!87DP9E>%k +!q61`rr2slrVlo(!<2uu9`=tlZ2j7k!e13CJcC<$JcC<$XoAH0!2+oC_Z.[W!3Q.uJ,~> +h#@Gj!'mpk!<=>/s8N)lrrHcGrVlua!)2n]rrQg5l2CV`Mu_6(rrMV%p&G$lqu6kJ!87DP9E>%k +!q61`rr2slrVlo(!<2uu9`=tlZ2j7k!e13CJcC<$JcC<$XoAH0!2+oC_Z.[W!3Q.uJ,~> +h#@Gj!'mpk!<=>/s8N)mrrU4@l2:P_VZ=%%rrTJ+ZMje)9E:O\rrL0Gp&G$l!7:`F"5.<\d/O(F +I/O$E!<3!!!2ohr!Up*grrE+trr3#g!:9^eIfQ-ms+13$s+13PrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=>/s8N)mrrU4@l2:P_VZ=%%rrTJ+ZMje)9E:O\rrL0Gp&G$l!7:`F"5.<\d/O(F +I/O$E!<3!!!2ohr!Up*grrE+trr3#g!:9^eIfQ-ms+13$s+13PrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=>/s8N)mrrU4@l2:P_VZ=%%rrTJ+ZMje)9E:O\rrL0Gp&G$l!7:`F"5.<\d/O(F +I/O$E!<3!!!2ohr!Up*grrE+trr3#g!:9^eIfQ-ms+13$s+13PrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=>/s8N)mrrIKIqu6`V!,)<2!pK\Yrr3)IZ2an(rrIN3p&Fmh!K>(orrhi3HiO0G +rr\\i9YL?'".B3`^$5OuIfQ-ms+13$s+13PrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=>/s8N)mrrIKIqu6`V!,)<2!pK\Yrr3)IZ2an(rrIN3p&Fmh!K>(orrhi3HiO0G +rr\\i9YL?'".B3`^$5OuIfQ-ms+13$s+13PrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=>/s8N)mrrIKIqu6`V!,)<2!pK\Yrr3)IZ2an(rrIN3p&Fmh!K>(orrhi3HiO0G +rr\\i9YL?'".B3`^$5OuIfQ-ms+13$s+13PrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=>/s8N)ms8N)qs8N)trsX8Tg&M)"n +h#@Gj!'mpk!<=>/s8N)ms8N)qs8N)trsX8Tg&M)"n +h#@Gj!'mpk!<=>/s8N)ms8N)qs8N)trsX8Tg&M)"n +h#@Gj!'mpk!<=>/s8N)ms8N)qs8N)trsZpJVuQ"Ms4IC@s2VG;s8N)lrrTJ+^&J'3!;uj#iMQYU +9^2NU"lZ?Z!)2YErrRZMTRm,os+13$s/l;&?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=>/s8N)ms8N)qs8N)trsZpJVuQ"Ms4IC@s2VG;s8N)lrrTJ+^&J'3!;uj#iMQYU +9^2NU"lZ?Z!)2YErrRZMTRm,os+13$s/l;&?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=>/s8N)ms8N)qs8N)trsZpJVuQ"Ms4IC@s2VG;s8N)lrrTJ+^&J'3!;uj#iMQYU +9^2NU"lZ?Z!)2YErrRZMTRm,os+13$s/l;&?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=>/s8N)qrs%sds8Q^3g&(dM!0$mV%.F6js/4QMs%EF^I-L;'rrDcm!jVgHrVult +qYpZ^HiT-&rr_M5!0$=F!e13CJcC<$JcC<$XoAH0!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=>/s8N)qrs%sds8Q^3g&(dM!0$mV%.F6js/4QMs%EF^I-L;'rrDcm!jVgHrVult +qYpZ^HiT-&rr_M5!0$=F!e13CJcC<$JcC<$XoAH0!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=>/s8N)qrs%sds8Q^3g&(dM!0$mV%.F6js/4QMs%EF^I-L;'rrDcm!jVgHrVult +qYpZ^HiT-&rr_M5!0$=F!e13CJcC<$JcC<$XoAH0!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=>/s8N)qrs#cfs8TA)Vu6PrklB*.rr\\id!Yim"/c.)I.RC +h#@Gj!'mpk!<=>/s8N)qrs#cfs8TA)Vu6PrklB*.rr\\id!Yim"/c.)I.RC +h#@Gj!'mpk!<=>/s8N)qrs#cfs8TA)Vu6PrklB*.rr\\id!Yim"/c.)I.RC +h#@Gj!'mpk!<=>/s8N)rrrV[`^&J$59E=&MrrKfGqu6cF!)1**rr^pS!6=^2rrDcmrr<&grVult +rr3!!ZMje,!,)?3!4)S'! +h#@Gj!'mpk!<=>/s8N)rrrV[`^&J$59E=&MrrKfGqu6cF!)1**rr^pS!6=^2rrDcmrr<&grVult +rr3!!ZMje,!,)?3!4)S'! +h#@Gj!'mpk!<=>/s8N)rrrV[`^&J$59E=&MrrKfGqu6cF!)1**rr^pS!6=^2rrDcmrr<&grVult +rr3!!ZMje,!,)?3!4)S'! +h#@Gj!'mpk!<=>0rr^pS!9*nV"5/&%g&D!Wfh>)ds8U,5l2(D]9E=S\rrPjonFZ__f`2$*p\u83 +!.=;9d$aq7n?W&o!4)Y)VZ>*Drr<&)s8Stsd-^i7IfQ-ms+14#rr?DW!5JR7^RY<*?N?aMs2+g9 +!6kHE?N@k +h#@Gj!'mpk!<=>0rr^pS!9*nV"5/&%g&D!Wfh>)ds8U,5l2(D]9E=S\rrPjonFZ__f`2$*p\u83 +!.=;9d$aq7n?W&o!4)Y)VZ>*Drr<&)s8Stsd-^i7IfQ-ms+14#rr?DW!5JR7^RY<*?N?aMs2+g9 +!6kHE?N@k +h#@Gj!'mpk!<=>0rr^pS!9*nV"5/&%g&D!Wfh>)ds8U,5l2(D]9E=S\rrPjonFZ__f`2$*p\u83 +!.=;9d$aq7n?W&o!4)Y)VZ>*Drr<&)s8Stsd-^i7IfQ-ms+14#rr?DW!5JR7^RY<*?N?aMs2+g9 +!6kHE?N@k +h#@Gj!'mpk!<=>1s7H?lnGW@kl'b9GB;b7prrK$Vr;Qf'I.[I9!;HL*VZ6^Ed/TO7N9U?Bl+L^0 +I+eN!"p!o$B)m>4m/I-:!2.[ +h#@Gj!'mpk!<=>1s7H?lnGW@kl'b9GB;b7prrK$Vr;Qf'I.[I9!;HL*VZ6^Ed/TO7N9U?Bl+L^0 +I+eN!"p!o$B)m>4m/I-:!2.[ +h#@Gj!'mpk!<=>1s7H?lnGW@kl'b9GB;b7prrK$Vr;Qf'I.[I9!;HL*VZ6^Ed/TO7N9U?Bl+L^0 +I+eN!"p!o$B)m>4m/I-:!2.[ +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=rrDoq"7U[ +h#@Gj!'mpk!<=rrDoq"7U[ +h#@Gj!'mpk!<=rrDoq"7U[ +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=rrDfn!_`UYoD\m=!!&8`!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=rrDfn!_`UYoD\m=!!&8`!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=rrDfn!_`UYoD\m=!!&8`!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<=rrDfn!oX-,rr35M9[NguHiSQms8N)trrVEb!<)p.i;`lXs*SGZ!56)Gs/,k1 +rr3OWB)hr3s*SGZ!56)Gs/,k1rVm)k9RQ@0iCs1Mdf0A6!5G'(!abr#JcEUerrC:C!abrBqu;0~> +h#@Gj!'mpk!<=rrDfn!oX-,rr35M9[NguHiSQms8N)trrVEb!<)p.i;`lXs*SGZ!56)Gs/,k1 +rr3OWB)hr3s*SGZ!56)Gs/,k1rVm)k9RQ@0iCs1Mdf0A6!5G'(!abr#JcEUerrC:C!abrBqu;0~> +h#@Gj!'mpk!<=rrDfn!oX-,rr35M9[NguHiSQms8N)trrVEb!<)p.i;`lXs*SGZ!56)Gs/,k1 +rr3OWB)hr3s*SGZ!56)Gs/,k1rVm)k9RQ@0iCs1Mdf0A6!5G'(!abr#JcEUerrC:C!abrBqu;0~> +h#@Gj!'mpk!<=!;?Hm!<<'#n4^n%rr^pS!58C3rrDusrrDusrrE#trr<&`rr3&h!,)60rrE#trr<&` +rr3&h!,)91!h',Yrr3&H!2n3D!^Hb#XoAEpi:?mL?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=!;?Hm!<<'#n4^n%rr^pS!58C3rrDusrrDusrrE#trr<&`rr3&h!,)60rrE#trr<&` +rr3&h!,)91!h',Yrr3&H!2n3D!^Hb#XoAEpi:?mL?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=!;?Hm!<<'#n4^n%rr^pS!58C3rrDusrrDusrrE#trr<&`rr3&h!,)60rrE#trr<&` +rr3&h!,)91!h',Yrr3&H!2n3D!^Hb#XoAEpi:?mL?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=s(>sE!4(kJB70:M!pK^3h>[KU +,1cbr?VmEaq#:D&!2.a>rrDcmrrE*!!N,qqs8N'!I/a0G!;uls!;uls!<)rt!;uls!;uls!<)rt +!;uls!<)rt!;uit!)1c>!^Hb#XoAMJ!%s>jp&>)#!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=s(>sE!4(kJB70:M!pK^3h>[KU +,1cbr?VmEaq#:D&!2.a>rrDcmrrE*!!N,qqs8N'!I/a0G!;uls!;uls!<)rt!;uls!;uls!<)rt +!;uls!<)rt!;uit!)1c>!^Hb#XoAMJ!%s>jp&>)#!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=s(>sE!4(kJB70:M!pK^3h>[KU +,1cbr?VmEaq#:D&!2.a>rrDcmrrE*!!N,qqs8N'!I/a0G!;uls!;uls!<)rt!;uls!;uls!<)rt +!;uls!<)rt!;uit!)1c>!^Hb#XoAMJ!%s>jp&>)#!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'mpk!<=%k!q61`rVultr;Qe1^&@s5kl=EHrr;uu!7:06!PN.$rrE*Df)G_WrW!!rT^VdX +!abr#dJs4HpAb-ms8N(3p]1 +h#@Gj!'mpk!<=%k!q61`rVultr;Qe1^&@s5kl=EHrr;uu!7:06!PN.$rrE*Df)G_WrW!!rT^VdX +!abr#dJs4HpAb-ms8N(3p]1 +h#@Gj!'mpk!<=%k!q61`rVultr;Qe1^&@s5kl=EHrr;uu!7:06!PN.$rrE*Df)G_WrW!!rT^VdX +!abr#dJs4HpAb-ms8N(3p]1 +h#@Gj!'mpk!<=!;HKti;ei:rr<&ms8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)trrT(ud/O%Hn,SEo +rrPFc^TIM9,5M9@/s"rfrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=!;HKti;ei:rr<&ms8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)trrT(ud/O%Hn,SEo +rrPFc^TIM9,5M9@/s"rfrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=!;HKti;ei:rr<&ms8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)trrT(ud/O%Hn,SEo +rrPFc^TIM9,5M9@/s"rfrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<=^Ao#C!!4d6 +i;W`X?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=^Ao#C!!4d6 +i;W`X?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=^Ao#C!!4d6 +i;W`X?N?aMs2+g9!6kHE?N@k +h#@Gj!'mpk!<=>-es8Q^3 +a8Gr +h#@Gj!'mpk!<=>-es8Q^3 +a8Gr +h#@Gj!'mpk!<=>-es8Q^3 +a8Gr +h#@Gj!'nF$!O(GSrrE*DJcGEC!e13Ci;WhN^[hC++opQZrrTJ+a7fN7f`9(krsI__!!#^Ws8N'! +l1b5X!;uls!;uls!;uiuZ2hT;s8N)ts8N)ts8N)qs8N)us8N)grrMAig&K"k!*%AGrrDio!dk!] +rr3%t!)3=j!POHks8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)trrVFYiQM6'mhGgTX[)OZ +#9n-5s8QF+TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!O(GSrrE*DJcGEC!e13Ci;WhN^[hC++opQZrrTJ+a7fN7f`9(krsI__!!#^Ws8N'! +l1b5X!;uls!;uls!;uiuZ2hT;s8N)ts8N)ts8N)qs8N)us8N)grrMAig&K"k!*%AGrrDio!dk!] +rr3%t!)3=j!POHks8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)trrVFYiQM6'mhGgTX[)OZ +#9n-5s8QF+TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!O(GSrrE*DJcGEC!e13Ci;WhN^[hC++opQZrrTJ+a7fN7f`9(krsI__!!#^Ws8N'! +l1b5X!;uls!;uls!;uiuZ2hT;s8N)ts8N)ts8N)qs8N)us8N)grrMAig&K"k!*%AGrrDio!dk!] +rr3%t!)3=j!POHks8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)trrVFYiQM6'mhGgTX[)OZ +#9n-5s8QF+TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$"@)r>O5Tg5!<=Pr;QfeBE%r2!;uls!;uls!<)p!Z2hrDs8N)ts8N)trrQg5g&(dM!0$pWrrDQg!6 +h#@Gj!'nF$"@)r>O5Tg5!<=Pr;QfeBE%r2!;uls!;uls!<)p!Z2hrDs8N)ts8N)trrQg5g&(dM!0$pWrrDQg!6 +h#@Gj!'nF$"@)r>O5Tg5!<=Pr;QfeBE%r2!;uls!;uls!<)p!Z2hrDs8N)ts8N)trrQg5g&(dM!0$pWrrDQg!6 +h#@Gj!'nF$!'pJ_!\TPlqu6Zs,(]derrRZMT]#hM5lCZa'kb;VrrOAEi8=P9]`?+JrrV-Za8Z)> +!:^!f#Oh]ns8Sts9`4nkZC:dmrrDusrrDusrrE#trrDusrrE#trrE#t!jVg(r;Qi_!7:`FrrDTh +!6>!:!577h!<==prr?F&!!am$fDkkX!2.d?"PEbTiUHjH"PK[Q9YL?'!7:TC!2oeq(46,@fo5t2 +]`=u1s1QGQ!,$]Zci=(!rr3)i!!(CFrs@$P!7:cGci=(!rr3)i!!(CFrr>ag!!&qErrPFc^TIM9 +,5_EB,&km(rrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'pJ_!\TPlqu6Zs,(]derrRZMT]#hM5lCZa'kb;VrrOAEi8=P9]`?+JrrV-Za8Z)> +!:^!f#Oh]ns8Sts9`4nkZC:dmrrDusrrDusrrE#trrDusrrE#trrE#t!jVg(r;Qi_!7:`FrrDTh +!6>!:!577h!<==prr?F&!!am$fDkkX!2.d?"PEbTiUHjH"PK[Q9YL?'!7:TC!2oeq(46,@fo5t2 +]`=u1s1QGQ!,$]Zci=(!rr3)i!!(CFrs@$P!7:cGci=(!rr3)i!!(CFrr>ag!!&qErrPFc^TIM9 +,5_EB,&km(rrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'pJ_!\TPlqu6Zs,(]derrRZMT]#hM5lCZa'kb;VrrOAEi8=P9]`?+JrrV-Za8Z)> +!:^!f#Oh]ns8Sts9`4nkZC:dmrrDusrrDusrrE#trrDusrrE#trrE#t!jVg(r;Qi_!7:`FrrDTh +!6>!:!577h!<==prr?F&!!am$fDkkX!2.d?"PEbTiUHjH"PK[Q9YL?'!7:TC!2oeq(46,@fo5t2 +]`=u1s1QGQ!,$]Zci=(!rr3)i!!(CFrs@$P!7:cGci=(!rr3)i!!(CFrr>ag!!&qErrPFc^TIM9 +,5_EB,&km(rrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'pA\!\TPlrr3!!,(]derrRZMT]#hM5l(H^'kb;YrrOAEi84J8VbH(GrrV.QVu?Vr +!4)S'%01&@s6p!gI-L\2f`:"1s8N)ss8N)ss8N)ts8N'!nGWCe!<)rt!;uiu9E=&MrrKfGrVult +o)A^1r;QifR[W+5!<==prr?F)!!4NtfDPXM?N?bJs7cQqB8jn+rrqAM!!%D[r;Ql`B)nk.rs>u) +!1N0P!1LstqZ-Zrqu?`so`5$lquHcs!ROO9!!&qFrrPFc^TIM>+ohTeE6n7X!abr#JcEUerrC:C +!abrBqu;0~> +h#@Gj!'nF$!'pA\!\TPlrr3!!,(]derrRZMT]#hM5l(H^'kb;YrrOAEi84J8VbH(GrrV.QVu?Vr +!4)S'%01&@s6p!gI-L\2f`:"1s8N)ss8N)ss8N)ts8N'!nGWCe!<)rt!;uiu9E=&MrrKfGrVult +o)A^1r;QifR[W+5!<==prr?F)!!4NtfDPXM?N?bJs7cQqB8jn+rrqAM!!%D[r;Ql`B)nk.rs>u) +!1N0P!1LstqZ-Zrqu?`so`5$lquHcs!ROO9!!&qFrrPFc^TIM>+ohTeE6n7X!abr#JcEUerrC:C +!abrBqu;0~> +h#@Gj!'nF$!'pA\!\TPlrr3!!,(]derrRZMT]#hM5l(H^'kb;YrrOAEi84J8VbH(GrrV.QVu?Vr +!4)S'%01&@s6p!gI-L\2f`:"1s8N)ss8N)ss8N)ts8N'!nGWCe!<)rt!;uiu9E=&MrrKfGrVult +o)A^1r;QifR[W+5!<==prr?F)!!4NtfDPXM?N?bJs7cQqB8jn+rrqAM!!%D[r;Ql`B)nk.rs>u) +!1N0P!1LstqZ-Zrqu?`so`5$lquHcs!ROO9!!&qFrrPFc^TIM>+ohTeE6n7X!abr#JcEUerrC:C +!abrBqu;0~> +h#@Jk!'nlJ^Aon\!!Fp8huFsPs7QBnIfO]NIfL\e!!3mJ^]+67+opQWrr]q7Vr@XT"50SGd/)ds8U,5l2L\b`rH+uo`"o=q#CEAhZ!TV,1cbs?N;I'fD5FJ?N?aMs8N$!fr+`I!pQT_df0A6 +!5GZ9!^L_NoD\l!!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Jk!'nlJ^Aon\!!Fp8huFsPs7QBnIfO]NIfL\e!!3mJ^]+67+opQWrr]q7Vr@XT"50SGd/)ds8U,5l2L\b`rH+uo`"o=q#CEAhZ!TV,1cbs?N;I'fD5FJ?N?aMs8N$!fr+`I!pQT_df0A6 +!5GZ9!^L_NoD\l!!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Jk!'nlJ^Aon\!!Fp8huFsPs7QBnIfO]NIfL\e!!3mJ^]+67+opQWrr]q7Vr@XT"50SGd/)ds8U,5l2L\b`rH+uo`"o=q#CEAhZ!TV,1cbs?N;I'fD5FJ?N?aMs8N$!fr+`I!pQT_df0A6 +!5GZ9!^L_NoD\l!!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!%5)Q!$[!op&>#Aci=4aO7sgui8">6n?S#P!!/&!qYpa"l+L^0I+eGt"lYmM!.[KU,1cbp\(C?R +!abr#JcGcM!q8nJq>UEpdf0A6!5G'(!abr#JcEUerrC:C!abrBqu;0~> +h#@Gj!%5)Q!$[!op&>#Aci=4aO7sgui8">6n?S#P!!/&!qYpa"l+L^0I+eGt"lYmM!.[KU,1cbp\(C?R +!abr#JcGcM!q8nJq>UEpdf0A6!5G'(!abr#JcEUerrC:C!abrBqu;0~> +h#@Gj!%5)Q!$[!op&>#Aci=4aO7sgui8">6n?S#P!!/&!qYpa"l+L^0I+eGt"lYmM!.[KU,1cbp\(C?R +!abr#JcGcM!q8nJq>UEpdf0A6!5G'(!abr#JcEUerrC:C!abrBqu;0~> +h#@Jk!&[Tj5QDPm!!)C!*S60!$_+:#:G#Qs8O8Ci.:pHrrE*Dao;EL!2+oCs8N+Y +!;ZWqn>F_7!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Jk!&[Tj5QDPm!!)C!*S60!$_+:#:G#Qs8O8Ci.:pHrrE*Dao;EL!2+oCs8N+Y +!;ZWqn>F_7!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Jk!&[Tj5QDPm!!)C!*S60!$_+:#:G#Qs8O8Ci.:pHrrE*Dao;EL!2+oCs8N+Y +!;ZWqn>F_7!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'nF$!'p>["r1LKs8N'CJcGEC!e13Ci;WdBq#CIDJ(OVu![7X&JcE[g!<==crrQO-TRm.C +s8N'!iVNQSVpYMG5QJQhrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'p>["r1LKs8N'CJcGEC!e13Ci;WdBq#CIDJ(OVu![7X&JcE[g!<==crrQO-TRm.C +s8N'!iVNQSVpYMG5QJQhrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'p>["r1LKs8N'CJcGEC!e13Ci;WdBq#CIDJ(OVu![7X&JcE[g!<==crrQO-TRm.C +s8N'!iVNQSVpYMG5QJQhrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'pD]!ElW(rrE*DJcGEC!e13Ci;WdBqu?dBE7apc![7X&JcE[g!<==crrQO-TRm.C +rrg[K!4(kgrrUlZl-]M45QJQhrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'pD]!ElW(rrE*DJcGEC!e13Ci;WdBqu?dBE7apc![7X&JcE[g!<==crrQO-TRm.C +rrg[K!4(kgrrUlZl-]M45QJQhrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'pD]!ElW(rrE*DJcGEC!e13Ci;WdBqu?dBE7apc![7X&JcE[g!<==crrQO-TRm.C +rrg[K!4(kgrrUlZl-]M45QJQhrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$!'pM`!a2GqqYpQr,(]derrRZMT]#hR5QCd.E6n7X![7X&JcE[g!<==crrQO-TRm.B +rs/&!HiO.?RaBC\!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'nF$!'pM`!a2GqqYpQr,(]derrRZMT]#hR5QCd.E6n7X![7X&JcE[g!<==crrQO-TRm.B +rs/&!HiO.?RaBC\!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'nF$!'pM`!a2GqqYpQr,(]derrRZMT]#hR5QCd.E6n7X![7X&JcE[g!<==crrQO-TRm.B +rs/&!HiO.?RaBC\!^Hb#SGrXt!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!'nF$"%ZRmp\4[g!$[!op&>)C!2/9M!afomoD\k9!8rG.`;]i<,0Bid?N?aMs2=p=5QJQh +rrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$"%ZRmp\4[g!$[!op&>)C!2/9M!afomoD\k9!8rG.`;]i<,0Bid?N?aMs2=p=5QJQh +rrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nF$"%ZRmp\4[g!$[!op&>)C!2/9M!afomoD\k9!8rG.`;]i<,0Bid?N?aMs2=p=5QJQh +rrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'mpk!<= +h#@Gj!'nI%"2@*fkP"oV!$[!op&>)C!2/KrrUOI!0mKb+opPmrrQO-TRm-[s8N)CrrQO- +^\e%]~> +h#@Gj!'nI%"2@*fkP"oV!$[!op&>)C!2/KrrUOI!0mKb+opPmrrQO-TRm-[s8N)CrrQO- +^\e%]~> +h#@Gj!'nI%"2@*fkP"oV!$[!op&>)C!2/KrrUOI!0mKb+opPmrrQO-TRm-[s8N)CrrQO- +^\e%]~> +h#@Gj!'nI%!5JL5!^N+8q>UHq,(]derrRZMT],nN^]"375aU[-rrOAEi8FV:Z2i8FrrUOIZMsk- +Z:ms*klCV\$b^0Q!0#V2s7"'t!;uls!;uls!;uj$iL3F?!.;KZrrA#U!!%uWrs%tj9E7banG`Fn +nAgsts2SaPZLe(tn,VG&rrE*Df)Gg7?a'/&!^Hb#dJs4Hp\t<#!4)S'"mMpY!,'"ErrA#U!!%uV +!<3#s!<<'*nAgsts5BCH!4)S'&+IW.!<<)ga-m#.iL0`HZMOS)Ve6!'Vsr%4![7X&T)Sk!!2+oC +_Z0W9bl7`O!5JF2J,~> +h#@Gj!'nI%!5JL5!^N+8q>UHq,(]derrRZMT],nN^]"375aU[-rrOAEi8FV:Z2i8FrrUOIZMsk- +Z:ms*klCV\$b^0Q!0#V2s7"'t!;uls!;uls!;uj$iL3F?!.;KZrrA#U!!%uWrs%tj9E7banG`Fn +nAgsts2SaPZLe(tn,VG&rrE*Df)Gg7?a'/&!^Hb#dJs4Hp\t<#!4)S'"mMpY!,'"ErrA#U!!%uV +!<3#s!<<'*nAgsts5BCH!4)S'&+IW.!<<)ga-m#.iL0`HZMOS)Ve6!'Vsr%4![7X&T)Sk!!2+oC +_Z0W9bl7`O!5JF2J,~> +h#@Gj!'nI%!5JL5!^N+8q>UHq,(]derrRZMT],nN^]"375aU[-rrOAEi8FV:Z2i8FrrUOIZMsk- +Z:ms*klCV\$b^0Q!0#V2s7"'t!;uls!;uls!;uj$iL3F?!.;KZrrA#U!!%uWrs%tj9E7banG`Fn +nAgsts2SaPZLe(tn,VG&rrE*Df)Gg7?a'/&!^Hb#dJs4Hp\t<#!4)S'"mMpY!,'"ErrA#U!!%uV +!<3#s!<<'*nAgsts5BCH!4)S'&+IW.!<<)ga-m#.iL0`HZMOS)Ve6!'Vsr%4![7X&T)Sk!!2+oC +_Z0W9bl7`O!5JF2J,~> +h#@Gj!'nI%!5JC2!^N+8r;Qct,(]derrRZMT],nN^\\!45aU[0rrOAEi8FV:HiW[0rsS&kI/j5P +^&S,Q!!)ut%I$Qls8V$X!7:anB)hr0s8N)ss8N)trs6sOa8c2(HiUJNs8N)srtFWj^&S,c9MF.> +s(>sE!4(kJB70=N!K=_HrrE*Df)Gp3!!!a@YPA,!5QJRHs8N)nrrV-ZI/a-NcqMgdiHtWQrVult +rVlr`!!)ut&)dKgs8RIZ!!'^Gs8Sts^&J$CHtNEZs8RIZ!!'^Gs8Sts^&@s8n4\6!s5?ZM!7LlK ++opPmrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nI%!5JC2!^N+8r;Qct,(]derrRZMT],nN^\\!45aU[0rrOAEi8FV:HiW[0rsS&kI/j5P +^&S,Q!!)ut%I$Qls8V$X!7:anB)hr0s8N)ss8N)trs6sOa8c2(HiUJNs8N)srtFWj^&S,c9MF.> +s(>sE!4(kJB70=N!K=_HrrE*Df)Gp3!!!a@YPA,!5QJRHs8N)nrrV-ZI/a-NcqMgdiHtWQrVult +rVlr`!!)ut&)dKgs8RIZ!!'^Gs8Sts^&J$CHtNEZs8RIZ!!'^Gs8Sts^&@s8n4\6!s5?ZM!7LlK ++opPmrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nI%!5JC2!^N+8r;Qct,(]derrRZMT],nN^\\!45aU[0rrOAEi8FV:HiW[0rsS&kI/j5P +^&S,Q!!)ut%I$Qls8V$X!7:anB)hr0s8N)ss8N)trs6sOa8c2(HiUJNs8N)srtFWj^&S,c9MF.> +s(>sE!4(kJB70=N!K=_HrrE*Df)Gp3!!!a@YPA,!5QJRHs8N)nrrV-ZI/a-NcqMgdiHtWQrVult +rVlr`!!)ut&)dKgs8RIZ!!'^Gs8Sts^&J$CHtNEZs8RIZ!!'^Gs8Sts^&@s8n4\6!s5?ZM!7LlK ++opPmrrQO-TRm-[s8N)CrrQO-^\e%]~> +h#@Gj!'nI%!5J:/#!eO!$^"o!9!bT!Yo(Gqu6^_!5Hq]rrDcmrrE*!!q8n(rr3)R!!'_3s8N)ss8N)ss8N)t +s8N'!l2L\an,R,!s8N)ts8N'!l2L\an,R,"rrSVhnG`FhciBujrrOAEi1BrM?N?aMs2+g9!6kHE +?N@k +h#@Gj!'nI%!5J:/#!eO!$^"o!9!bT!Yo(Gqu6^_!5Hq]rrDcmrrE*!!q8n(rr3)R!!'_3s8N)ss8N)ss8N)t +s8N'!l2L\an,R,!s8N)ts8N'!l2L\an,R,"rrSVhnG`FhciBujrrOAEi1BrM?N?aMs2+g9!6kHE +?N@k +h#@Gj!'nI%!5J:/#!eO!$^"o!9!bT!Yo(Gqu6^_!5Hq]rrDcmrrE*!!q8n(rr3)R!!'_3s8N)ss8N)ss8N)t +s8N'!l2L\an,R,!s8N)ts8N'!l2L\an,R,"rrSVhnG`FhciBujrrOAEi1BrM?N?aMs2+g9!6kHE +?N@k +h#@Gj!%5ZL!&!pE"$i1Q,(]derrRZM0&]%q0(f2L5aU[6ruqI$i;`fWo`+pks8N*"VuH\sn,WIf +!keTurVlr`9RQj>rrDusrrDusrrE#ts*XbErrE#trrE#t!lk<*r;Qhr!4)V(rrDThqu?aknD4*F +!$^"o!9!YQ!Yo(Grr3$b!5Hq]rrDcmrrE*!!N,qqs8N'!I/a0G!;uls!;uls!<)rt!;uls!;uls +!<)rt!;uls!<)rt!;uit!)1c>![7X&T)Sk!!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!%5ZL!&!pE"$i1Q,(]derrRZM0&]%q0(f2L5aU[6ruqI$i;`fWo`+pks8N*"VuH\sn,WIf +!keTurVlr`9RQj>rrDusrrDusrrE#ts*XbErrE#trrE#t!lk<*r;Qhr!4)V(rrDThqu?aknD4*F +!$^"o!9!YQ!Yo(Grr3$b!5Hq]rrDcmrrE*!!N,qqs8N'!I/a0G!;uls!;uls!<)rt!;uls!;uls +!<)rt!;uls!<)rt!;uit!)1c>![7X&T)Sk!!2+oC_Z0W9bl7`O!5JF2J,~> +h#@Gj!%5ZL!&!pE"$i1Q,(]derrRZM0&]%q0(f2L5aU[6ruqI$i;`fWo`+pks8N*"VuH\sn,WIf +!keTurVlr`9RQj>rrDusrrDusrrE#ts*XbErrE#trrE#t!lk<*r;Qhr!4)V(rrDThqu?aknD4*F +!$^"o!9!YQ!Yo(Grr3$b!5Hq]rrDcmrrE*!!N,qqs8N'!I/a0G!;uls!;uls!<)rt!;uls!;uls +!<)rt!;uls!<)rt!;uit!)1c>![7X&T)Sk!!2+oC_Z0W9bl7`O!5JF2J,~> +h#@ApYlFbJJcGEC!.W>q"^0d`+opQZs8N)ks8N*!rr\\i9YL?'!IOn@s8N)ss8N)ss8N)prrhi3 +HiO0Fs8N)trrIKIqu6`V!,)<2rrDQg"n9QF!!&qQrrE*7epd[=p&G72?`u]p^X<)]!;?Hm!<<'! +BD;K+s8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)ts8N)ss8N)GrrOAEi2lq[/mkgUrrQO- +TRm-[s8N)CrrQO-^\e%]~> +h#@ApYlFbJJcGEC!.W>q"^0d`+opQZs8N)ks8N*!rr\\i9YL?'!IOn@s8N)ss8N)ss8N)prrhi3 +HiO0Fs8N)trrIKIqu6`V!,)<2rrDQg"n9QF!!&qQrrE*7epd[=p&G72?`u]p^X<)]!;?Hm!<<'! +BD;K+s8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)ts8N)ss8N)GrrOAEi2lq[/mkgUrrQO- +TRm-[s8N)CrrQO-^\e%]~> +h#@ApYlFbJJcGEC!.W>q"^0d`+opQZs8N)ks8N*!rr\\i9YL?'!IOn@s8N)ss8N)ss8N)prrhi3 +HiO0Fs8N)trrIKIqu6`V!,)<2rrDQg"n9QF!!&qQrrE*7epd[=p&G72?`u]p^X<)]!;?Hm!<<'! +BD;K+s8N)ss8N)ss8N)ts8N)ss8N)ss8N)ts8N)ss8N)ts8N)ss8N)GrrOAEi2lq[/mkgUrrQO- +TRm-[s8N)CrrQO-^\e%]~> +g]%:]Qc$Q*CrrVZiN6qS++opQ& +rrjSH!#8kEq>UM'!2+oC_Z0W9bl7`O!5JF2J,~> +g]%:]Qc$Q*CrrVZiN6qS++opQ& +rrjSH!#8kEq>UM'!2+oC_Z0W9bl7`O!5JF2J,~> +g]%:]Qc$Q*CrrVZiN6qS++opQ& +rrjSH!#8kEq>UM'!2+oC_Z0W9bl7`O!5JF2J,~> +S,WK'q#CJ!Vt^2j!<= +S,WK'q#CJ!Vt^2j!<= +S,WK'q#CJ!Vt^2j!<= +S,WK'qu?e$Vt^)g!<=$;!Usb$s8N)ss8N)ss8N)trrTJ+a8Q&>-es8Q^3a8Gr +S,WK'qu?e$Vt^)g!<=$;!Usb$s8N)ss8N)ss8N)trrTJ+a8Q&>-es8Q^3a8Gr +S,WK'qu?e$Vt^)g!<=$;!Usb$s8N)ss8N)ss8N)trrTJ+a8Q&>-es8Q^3a8Gr +S,WZ,!!$0"p\=ah!$[!op&>)C!2/!:^!f#Oh]n +s8Sts9`4nkZC:dmrrDusrrDusrrE#trrDusrrE#trrE#t!jVg(r;Qi_!7:`FrrDEc!=?D!^Hb#dJs4Hq#:DC!58C3!iH#lr;Qf2N;ikW!;uls!;uls!<)rt!;uls!;uls +!<)rt!;uls!<)p!ktL'YrrO/?335C +S,WZ,!!$0"p\=ah!$[!op&>)C!2/!:^!f#Oh]n +s8Sts9`4nkZC:dmrrDusrrDusrrE#trrDusrrE#trrE#t!jVg(r;Qi_!7:`FrrDEc!=?D!^Hb#dJs4Hq#:DC!58C3!iH#lr;Qf2N;ikW!;uls!;uls!<)rt!;uls!;uls +!<)rt!;uls!<)p!ktL'YrrO/?335C +S,WZ,!!$0"p\=ah!$[!op&>)C!2/!:^!f#Oh]n +s8Sts9`4nkZC:dmrrDusrrDusrrE#trrDusrrE#trrE#t!jVg(r;Qi_!7:`FrrDEc!=?D!^Hb#dJs4Hq#:DC!58C3!iH#lr;Qf2N;ikW!;uls!;uls!<)rt!;uls!;uls +!<)rt!;uls!<)p!ktL'YrrO/?335C +S,WQJVt]la!<= +S,WQJVt]la!<= +S,WQJVt]la!<= +N;inY,(]derrRZMT[3W>+opQWrr]q7Vr@XT"50SGd/)ds8U,5l2L\b`rH+up&>;F9W..T +s1NgEh#@BT,1cbqk@_R&rrPFc^XE,bf`2$2nG`Fjfr"gD^&.g0d/*eCVu?W2HiW-YN;rpk!2oks +]uL*QB70a+!!(^Orr_`j!7:`F$.&YPd/X-m!!(^Orr_`j!7:`F!)31g!2n6E![7WBXM4`MpAbA" +VtXNuTRm-[s8N)CrrQO-^\e%]~> +N;inY,(]derrRZMT[3W>+opQWrr]q7Vr@XT"50SGd/)ds8U,5l2L\b`rH+up&>;F9W..T +s1NgEh#@BT,1cbqk@_R&rrPFc^XE,bf`2$2nG`Fjfr"gD^&.g0d/*eCVu?W2HiW-YN;rpk!2oks +]uL*QB70a+!!(^Orr_`j!7:`F$.&YPd/X-m!!(^Orr_`j!7:`F!)31g!2n6E![7WBXM4`MpAbA" +VtXNuTRm-[s8N)CrrQO-^\e%]~> +N;inY,(]derrRZMT[3W>+opQWrr]q7Vr@XT"50SGd/)ds8U,5l2L\b`rH+up&>;F9W..T +s1NgEh#@BT,1cbqk@_R&rrPFc^XE,bf`2$2nG`Fjfr"gD^&.g0d/*eCVu?W2HiW-YN;rpk!2oks +]uL*QB70a+!!(^Orr_`j!7:`F$.&YPd/X-m!!(^Orr_`j!7:`F!)31g!2n6E![7WBXM4`MpAbA" +VtXNuTRm-[s8N)CrrQO-^\e%]~> +N;inY,(]derrRZMT[3W>+opQVrrV\qN;`eXN5tep"p!o$B)m>4r;QrZRK*>8d/O(B!!*&r!!*&r +!<3!/VZ6^Ed/TO7N9UBBl":!orVm)dRS3]oVss]cqZ-?i#/+XL!)/j.gA_0R,00]b5QJRJs7cQq +B8jn+rrqAM!!%D[r;Ql`B)nk.rs>u)!1N0P!1LstqZ-Zrqu?`so`5$lquHcs!ROO9!!&qFrrOAE +i2lqY,5M9@=f;#nrrQO-TRm-[s8N)CrrQO-^\e%]~> +N;inY,(]derrRZMT[3W>+opQVrrV\qN;`eXN5tep"p!o$B)m>4r;QrZRK*>8d/O(B!!*&r!!*&r +!<3!/VZ6^Ed/TO7N9UBBl":!orVm)dRS3]oVss]cqZ-?i#/+XL!)/j.gA_0R,00]b5QJRJs7cQq +B8jn+rrqAM!!%D[r;Ql`B)nk.rs>u)!1N0P!1LstqZ-Zrqu?`so`5$lquHcs!ROO9!!&qFrrOAE +i2lqY,5M9@=f;#nrrQO-TRm-[s8N)CrrQO-^\e%]~> +N;inY,(]derrRZMT[3W>+opQVrrV\qN;`eXN5tep"p!o$B)m>4r;QrZRK*>8d/O(B!!*&r!!*&r +!<3!/VZ6^Ed/TO7N9UBBl":!orVm)dRS3]oVss]cqZ-?i#/+XL!)/j.gA_0R,00]b5QJRJs7cQq +B8jn+rrqAM!!%D[r;Ql`B)nk.rs>u)!1N0P!1LstqZ-Zrqu?`so`5$lquHcs!ROO9!!&qFrrOAE +i2lqY,5M9@=f;#nrrQO-TRm-[s8N)CrrQO-^\e%]~> +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=pUEpdf0@m!8ssY" +N;inY,(]derrRZMT[3W>+opPPs2=pUEpdf0@m!8ssY" +N;inY,(]derrRZMT[3W>+opPPs2=pUEpdf0@m!8ssY" +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+opPPs2=p +N;inY,(]derrRZMT[3W>+olS5J&Hg;!$]J`!^H`mJUbUf!Yk^nT)SeGJO$q7bl7`O!5JF2J,~> +N;inY,(]derrRZMT[3W>+olS5J&Hg;!$]J`!^H`mJUbUf!Yk^nT)SeGJO$q7bl7`O!5JF2J,~> +N;inY,(]derrRZMT[3W>+olS5J&Hg;!$]J`!^H`mJUbUf!Yk^nT)SeGJO$q7bl7`O!5JF2J,~> +N;inY,(]derrRZMT[3W<,(Ta1!!"4`rr><8!5JR7i.:oZs/#_s?N@k +N;inY,(]derrRZMT[3W<,(Ta1!!"4`rr><8!5JR7i.:oZs/#_s?N@k +N;inY,(]derrRZMT[3W<,(Ta1!!"4`rr><8!5JR7i.:oZs/#_s?N@k +N;inY,(]derrRZMT[3W +N;inY,(]derrRZMT[3W +N;inY,(]derrRZMT[3W +N;nG/nGiQ^JcC<$JcC<$JcC<$[/U27!5JF2J,~> +N;nG/nGiQ^JcC<$JcC<$JcC<$[/U27!5JF2J,~> +N;nG/nGiQ^JcC<$JcC<$JcC<$[/U27!5JF2J,~> +N;nG/nGiQ^JcC<$JcC<$JcC<$[/U27!5JF2J,~> +N;nG/nGiQ^JcC<$JcC<$JcC<$[/U27!5JF2J,~> +N;nG/nGiQ^JcC<$JcC<$JcC<$[/U27!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +JcC<$JcC<$JcC<$JcC<$Y5\Q1!5JF2J,~> +g]%?D:j7J?JU`6#JU`6#JU`6#JUc:$!\OJfqu;0~> +g]%?D:j7J?JU`6#JU`6#JU`6#JUc:$!\OJfqu;0~> +g]%?D:j7J?JU`6#JU`6#JU`6#JUc:$!\OJfqu;0~> +g]%8%JH16$JH16$JH16$JH16$df9BBqu;0~> +g]%8%JH16$JH16$JH16$JH16$df9BBqu;0~> +g]%8%JH16$JH16$JH16$JH16$df9BBqu;0~> +g]%>D!'l*bJU`6#JU`6#JU`6#JUc:$!I&_`s*t~> +g]%>D!'l*bJU`6#JU`6#JU`6#JUc:$!I&_`s*t~> +g]%>D!'l*bJU`6#JU`6#JU`6#JUc:$!I&_`s*t~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.TS"JcC<$JcC<$JcC<$JcF$qJ,~> +g]%>J!.VEV!2+lCb5_NlMuNd +g]%>J!.VEV!2+lCb5_NlMuNd +g]%>J!.VEV!2+lCb5_NlMuNd +g]%>J!.VEV!2+lCb5_NlMuNc$JH3jnJcC<$JcC<$s8RT~> +g]%>J!.VEV!2+lCb5_NlMuNc$JH3jnJcC<$JcC<$s8RT~> +g]%>J!.VEV!2+lCb5_NlMuNc$JH3jnJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!-!L=c[YrpJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!-!L=c[YrpJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!-!L=c[YrpJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#JcF'r!e13"MuNi&!8rG.ci="FJcC<$JcC<$s8RT~> +g]%>J!.VEV!h]O#fDkXH!b[J=K`;+'!.Tq,![7X&XT&Cla-m#+s8RK,rr_c2RK1b8rr@WMJcC<$ +JcGcMJ,~> +g]%>J!.VEV!h]O#fDkXH!b[J=K`;+'!.Tq,![7X&XT&Cla-m#+s8RK,rr_c2RK1b8rr@WMJcC<$ +JcGcMJ,~> +g]%>J!.VEV!h]O#fDkXH!b[J=K`;+'!.Tq,![7X&XT&Cla-m#+s8RK,rr_c2RK1b8rr@WMJcC<$ +JcGcMJ,~> +g]%>J!.VEV!h]O#f)Gg)!!)ut"5/V5N3`Han,V&>!e13"MuNi&!8uQ1!N1n-rr\3m!!)rss*Wl, +"+4_]!7CiH!.k0$s+13$s8W+L~> +g]%>J!.VEV!h]O#f)Gg)!!)ut"5/V5N3`Han,V&>!e13"MuNi&!8uQ1!N1n-rr\3m!!)rss*Wl, +"+4_]!7CiH!.k0$s+13$s8W+L~> +g]%>J!.VEV!h]O#f)Gg)!!)ut"5/V5N3`Han,V&>!e13"MuNi&!8uQ1!N1n-rr\3m!!)rss*Wl, +"+4_]!7CiH!.k0$s+13$s8W+L~> +g]%>J!.VEV!h]O#ec5XLqu6_d!55`=!RLhtrrRZMIuF=.+opQSs8N'!nC@R=!;6?mn,V\PrrCIH +rr@WMJcC<$JcGcMJ,~> +g]%>J!.VEV!h]O#ec5XLqu6_d!55`=!RLhtrrRZMIuF=.+opQSs8N'!nC@R=!;6?mn,V\PrrCIH +rr@WMJcC<$JcGcMJ,~> +g]%>J!.VEV!h]O#ec5XLqu6_d!55`=!RLhtrrRZMIuF=.+opQSs8N'!nC@R=!;6?mn,V\PrrCIH +rr@WMJcC<$JcGcMJ,~> +g]%>J!.VEV!h]O#ec5XLqu6`e!)0a!!La#>rrRZMIuF=.+opQTrr^:A!4(/TrrD`l!RLi1s8N)H +s8N(Ms+13$s+14Ms*t~> +g]%>J!.VEV!h]O#ec5XLqu6`e!)0a!!La#>rrRZMIuF=.+opQTrr^:A!4(/TrrD`l!RLi1s8N)H +s8N(Ms+13$s+14Ms*t~> +g]%>J!.VEV!h]O#ec5XLqu6`e!)0a!!La#>rrRZMIuF=.+opQTrr^:A!4(/TrrD`l!RLi1s8N)H +s8N(Ms+13$s+14Ms*t~> +g]%>J!.VEV!h]O#ec5XLqZ$Qq[/U3S!!(UM!e13"MuNi&!8uT2")$Qm9\'1C!;6?mRK2ROrrCIH +rr@WMJcC<$JcGcMJ,~> +g]%>J!.VEV!h]O#ec5XLqZ$Qq[/U3S!!(UM!e13"MuNi&!8uT2")$Qm9\'1C!;6?mRK2ROrrCIH +rr@WMJcC<$JcGcMJ,~> +g]%>J!.VEV!h]O#ec5XLqZ$Qq[/U3S!!(UM!e13"MuNi&!8uT2")$Qm9\'1C!;6?mRK2ROrrCIH +rr@WMJcC<$JcGcMJ,~> +g]%>J!.VEV!h]O#ec5XLqu6`V!,)3/"mMpY!,'"Crro]%9YKZjr;QujVb@(aVss]c$1Q!(!<;#H +!!'>&rs%GN9E5'?^&J$ +g]%>J!.VEV!h]O#ec5XLqu6`V!,)3/"mMpY!,'"Crro]%9YKZjr;QujVb@(aVss]c$1Q!(!<;#H +!!'>&rs%GN9E5'?^&J$ +g]%>J!.VEV!h]O#ec5XLqu6`V!,)3/"mMpY!,'"Crro]%9YKZjr;QujVb@(aVss]c$1Q!(!<;#H +!!'>&rs%GN9E5'?^&J$ +g]%>J!.VEV!h]O#ec5XLqu6_F!87;M#LH/ks5A>*I/a-MZG$;<`rH,s*SGZ +!56)Gs/,k1rr3_[!6>->l$NK:s8RIZ!!'^Gs8Sts^&A!2!7q/OIfOtVrrOAEi7n88VpPIj!0$dS +&Fd`/!<;;P!!&Jfs5BCH9X=Zt$1Q!(!<:Dn!)1*'s8N)urr_c2RK3?e!0$gU!0$jVrr;osqu6ku +9E:%9!!)rs"mMpY!,'"#s8N(Ms+13$s+14Ms*t~> +g]%>J!.VEV!h]O#ec5XLqu6_F!87;M#LH/ks5A>*I/a-MZG$;<`rH,s*SGZ +!56)Gs/,k1rr3_[!6>->l$NK:s8RIZ!!'^Gs8Sts^&A!2!7q/OIfOtVrrOAEi7n88VpPIj!0$dS +&Fd`/!<;;P!!&Jfs5BCH9X=Zt$1Q!(!<:Dn!)1*'s8N)urr_c2RK3?e!0$gU!0$jVrr;osqu6ku +9E:%9!!)rs"mMpY!,'"#s8N(Ms+13$s+14Ms*t~> +g]%>J!.VEV!h]O#ec5XLqu6_F!87;M#LH/ks5A>*I/a-MZG$;<`rH,s*SGZ +!56)Gs/,k1rr3_[!6>->l$NK:s8RIZ!!'^Gs8Sts^&A!2!7q/OIfOtVrrOAEi7n88VpPIj!0$dS +&Fd`/!<;;P!!&Jfs5BCH9X=Zt$1Q!(!<:Dn!)1*'s8N)urr_c2RK3?e!0$gU!0$jVrr;osqu6ku +9E:%9!!)rs"mMpY!,'"#s8N(Ms+13$s+14Ms*t~> +g]%>J!.VEV!h]O#ec5XLrr3,[Z:ms=r;Qif9ZR/4#2&tV^&S++rVlo(!<)ouB>+9D"6feZnG`If +!!)9_rrVZiBE%o39E>%k!q61`rVult!9sL_!q62&rVultf)Gf$!.Tq,![7X&g]%7drr3$n!:]mc +*dhT#!85'cs-`qH]tOIGVZ=F1s*SGZ!4'uOn +g]%>J!.VEV!h]O#ec5XLrr3,[Z:ms=r;Qif9ZR/4#2&tV^&S++rVlo(!<)ouB>+9D"6feZnG`If +!!)9_rrVZiBE%o39E>%k!q61`rVult!9sL_!q62&rVultf)Gf$!.Tq,![7X&g]%7drr3$n!:]mc +*dhT#!85'cs-`qH]tOIGVZ=F1s*SGZ!4'uOn +g]%>J!.VEV!h]O#ec5XLrr3,[Z:ms=r;Qif9ZR/4#2&tV^&S++rVlo(!<)ouB>+9D"6feZnG`If +!!)9_rrVZiBE%o39E>%k!q61`rVult!9sL_!q62&rVultf)Gf$!.Tq,![7X&g]%7drr3$n!:]mc +*dhT#!85'cs-`qH]tOIGVZ=F1s*SGZ!4'uOn +g]%>J!.VEV!h]O#ec5LH!dr&Xqu6\p!;uls!!I]LrrAtrrrMThrr3&?!9sF]!iH%(rr;uur;Zcs +rr<"Gr;ZcsrVultr;ZcsrVultf)Gf$!.Tq,![7X&h#@E%ZMsk*Z2h3+s8N'!l2L\bn,NIQrr3&h +!,)91rr<&`rVlq3!7:]ErrDusrrDusrrDusrrDusrrE#ts*XeF!lk9@rr3&h9ZR/4"5*YS^#&eh +!1 +g]%>J!.VEV!h]O#ec5LH!dr&Xqu6\p!;uls!!I]LrrAtrrrMThrr3&?!9sF]!iH%(rr;uur;Zcs +rr<"Gr;ZcsrVultr;ZcsrVultf)Gf$!.Tq,![7X&h#@E%ZMsk*Z2h3+s8N'!l2L\bn,NIQrr3&h +!,)91rr<&`rVlq3!7:]ErrDusrrDusrrDusrrDusrrE#ts*XeF!lk9@rr3&h9ZR/4"5*YS^#&eh +!1 +g]%>J!.VEV!h]O#ec5LH!dr&Xqu6\p!;uls!!I]LrrAtrrrMThrr3&?!9sF]!iH%(rr;uur;Zcs +rr<"Gr;ZcsrVultr;ZcsrVultf)Gf$!.Tq,![7X&h#@E%ZMsk*Z2h3+s8N'!l2L\bn,NIQrr3&h +!,)91rr<&`rVlq3!7:]ErrDusrrDusrrDusrrDusrrE#ts*XeF!lk9@rr3&h9ZR/4"5*YS^#&eh +!1 +g]%>J!.VEV!h]O#ec5XLs8N/R!0$aR!,)',s8N1i!)1*'rrIKIqu6`V!,)<2rrDusrrDoq"RsHZ +!!)utrrDusrrE#trrCXM!e13"RK!9=o`"t:!8uZ4!IXD9rrVZi9_n_g!;uls!;uls!<)rt!;uiu +ciBO5s8N)ss8N)ss8N)ss8N)ss8N)urrUOIg&:pPn,NIfrrK"tr;Zcs!. +g]%>J!.VEV!h]O#ec5XLs8N/R!0$aR!,)',s8N1i!)1*'rrIKIqu6`V!,)<2rrDusrrDoq"RsHZ +!!)utrrDusrrE#trrCXM!e13"RK!9=o`"t:!8uZ4!IXD9rrVZi9_n_g!;uls!;uls!<)rt!;uiu +ciBO5s8N)ss8N)ss8N)ss8N)ss8N)urrUOIg&:pPn,NIfrrK"tr;Zcs!. +g]%>J!.VEV!h]O#ec5XLs8N/R!0$aR!,)',s8N1i!)1*'rrIKIqu6`V!,)<2rrDusrrDoq"RsHZ +!!)utrrDusrrE#trrCXM!e13"RK!9=o`"t:!8uZ4!IXD9rrVZi9_n_g!;uls!;uls!<)rt!;uiu +ciBO5s8N)ss8N)ss8N)ss8N)ss8N)urrUOIg&:pPn,NIfrrK"tr;Zcs!. +g]%>J!.VEV!h]O#ec5XLrr3%t!587/rrDcm"I];j9W.jhrrDoqrrE&urrDusrrDus#2u"EZKV>h +rVultr;ZcsrVultf)Gf$!.UF:"$dT6^\@a0+opQWrrMA3r;QhG!7:TBrrDusrrDusrrE#trrDus +!q60irVultr;Zcsr;Zcsr;Zcsr;Zcsrr3"f!;lfr!<2uuBD;J`s8N(drr@QI!!4Ntf@U$1fh;C) +g&M**MuZQ)l2La2h#@A%JcC<$jo9i~> +g]%>J!.VEV!h]O#ec5XLrr3%t!587/rrDcm"I];j9W.jhrrDoqrrE&urrDusrrDus#2u"EZKV>h +rVultr;ZcsrVultf)Gf$!.UF:"$dT6^\@a0+opQWrrMA3r;QhG!7:TBrrDusrrDusrrE#trrDus +!q60irVultr;Zcsr;Zcsr;Zcsr;Zcsrr3"f!;lfr!<2uuBD;J`s8N(drr@QI!!4Ntf@U$1fh;C) +g&M**MuZQ)l2La2h#@A%JcC<$jo9i~> +g]%>J!.VEV!h]O#ec5XLrr3%t!587/rrDcm"I];j9W.jhrrDoqrrE&urrDusrrDus#2u"EZKV>h +rVultr;ZcsrVultf)Gf$!.UF:"$dT6^\@a0+opQWrrMA3r;QhG!7:TBrrDusrrDusrrE#trrDus +!q60irVultr;Zcsr;Zcsr;Zcsr;Zcsrr3"f!;lfr!<2uuBD;J`s8N(drr@QI!!4Ntf@U$1fh;C) +g&M**MuZQ)l2La2h#@A%JcC<$jo9i~> +g]%>J!.Vod"$f\Un+Zh`TE&?Ls8N)trrQg5iVWZT!!)N^rs@Y^!!#^Ws8N'!qZ$Qqrr;uur;Zcs +rVlr)!58C3rrE#trrDusrrE#trrCXM!e13"RK!7PrW!!7B>=[JQq#CD`qZ$Qqr;Zcs +r;ZcsrVultqu?ZrrVultr;Zcsr;Zcsr;Zcsr;Zcsrr;uuqu?Zrrr;uuf)PaMR/[/9q>^REO5Sdm +"4.#JVu-JrRK*?7li.!E!8[YUMu\G/JcFj3J,~> +g]%>J!.Vod"$f\Un+Zh`TE&?Ls8N)trrQg5iVWZT!!)N^rs@Y^!!#^Ws8N'!qZ$Qqrr;uur;Zcs +rVlr)!58C3rrE#trrDusrrE#trrCXM!e13"RK!7PrW!!7B>=[JQq#CD`qZ$Qqr;Zcs +r;ZcsrVultqu?ZrrVultr;Zcsr;Zcsr;Zcsr;Zcsrr;uuqu?Zrrr;uuf)PaMR/[/9q>^REO5Sdm +"4.#JVu-JrRK*?7li.!E!8[YUMu\G/JcFj3J,~> +g]%>J!.Vod"$f\Un+Zh`TE&?Ls8N)trrQg5iVWZT!!)N^rs@Y^!!#^Ws8N'!qZ$Qqrr;uur;Zcs +rVlr)!58C3rrE#trrDusrrE#trrCXM!e13"RK!7PrW!!7B>=[JQq#CD`qZ$Qqr;Zcs +r;ZcsrVultqu?ZrrVultr;Zcsr;Zcsr;Zcsr;Zcsrr;uuqu?Zrrr;uuf)PaMR/[/9q>^REO5Sdm +"4.#JVu-JrRK*?7li.!E!8[YUMu\G/JcFj3J,~> +g]%>J!.Vod!'pM`!`5QYqYpVi!+4:VrrE#t!oX,lqu6_1!6>$;!Usb!rs7k:!0$sXB)pW^rrE+Y +rr;uur;Zcsrr3&*!6>'=EF![7X&h>[IfqYpUj +!:]mcrrDusrrDusrrE#trrDrrrrE#trrDusrrDusrrDusrrDusrrE&urrDrrrrE&urr<&gfDkjN +R(iW.pAb7IO5Spq"5*YS9_n\j9E5(GmJd68!!(mU!djtJJcC<$jo9i~> +g]%>J!.Vod!'pM`!`5QYqYpVi!+4:VrrE#t!oX,lqu6_1!6>$;!Usb!rs7k:!0$sXB)pW^rrE+Y +rr;uur;Zcsrr3&*!6>'=EF![7X&h>[IfqYpUj +!:]mcrrDusrrDusrrE#trrDrrrrE#trrDusrrDusrrDusrrDusrrE&urrDrrrrE&urr<&gfDkjN +R(iW.pAb7IO5Spq"5*YS9_n\j9E5(GmJd68!!(mU!djtJJcC<$jo9i~> +g]%>J!.Vod!'pM`!`5QYqYpVi!+4:VrrE#t!oX,lqu6_1!6>$;!Usb!rs7k:!0$sXB)pW^rrE+Y +rr;uur;Zcsrr3&*!6>'=EF![7X&h>[IfqYpUj +!:]mcrrDusrrDusrrE#trrDrrrrE#trrDusrrDusrrDusrrDusrrE&urrDrrrrE&urr<&gfDkjN +R(iW.pAb7IO5Spq"5*YS9_n\j9E5(GmJd68!!(mU!djtJJcC<$jo9i~> +g]%>J!.Vod!'pD]!`5QYrVlql!+4:VrrDus!keT&r;Qhr!)3=j"hflprrDQfrs/#n!<<))!2obp +!pK^3rr;uur;Zcsrr;uur;ZcsrVultr;ZcsrVultf)Gf$!.UF:!'p;Z"r1dcruqI$hZ!W'Vu$Dp +VZ=F-s8N)ss8N)ss8N)ts8N)rrrE+YrVultr;Zcsr;Zcsr;Zcsr;Zcsrr3$n!9sF]rrE&u!bVMR +r;QfeBA`^hpP8eN/s#bdrrYpp!4)G#"0qn,9^hu^iFi,ii;Wi:BDqm^s+143s*t~> +g]%>J!.Vod!'pD]!`5QYrVlql!+4:VrrDus!keT&r;Qhr!)3=j"hflprrDQfrs/#n!<<))!2obp +!pK^3rr;uur;Zcsrr;uur;ZcsrVultr;ZcsrVultf)Gf$!.UF:!'p;Z"r1dcruqI$hZ!W'Vu$Dp +VZ=F-s8N)ss8N)ss8N)ts8N)rrrE+YrVultr;Zcsr;Zcsr;Zcsr;Zcsrr3$n!9sF]rrE&u!bVMR +r;QfeBA`^hpP8eN/s#bdrrYpp!4)G#"0qn,9^hu^iFi,ii;Wi:BDqm^s+143s*t~> +g]%>J!.Vod!'pD]!`5QYrVlql!+4:VrrDus!keT&r;Qhr!)3=j"hflprrDQfrs/#n!<<))!2obp +!pK^3rr;uur;Zcsrr;uur;ZcsrVultr;ZcsrVultf)Gf$!.UF:!'p;Z"r1dcruqI$hZ!W'Vu$Dp +VZ=F-s8N)ss8N)ss8N)ts8N)rrrE+YrVultr;Zcsr;Zcsr;Zcsr;Zcsrr3$n!9sF]rrE&u!bVMR +r;QfeBA`^hpP8eN/s#bdrrYpp!4)G#"0qn,9^hu^iFi,ii;Wi:BDqm^s+143s*t~> +g]%>J!.Vod!'p;Z##Lu]s.B@!ec5XLqu6_F!2oeq%I!imBA*=bcqMgdrrBA'rrE+4rr3$n!9*nV +!PN.Es8N)ss8N)us8N'!nGWCe!<)rt!;uls!<)rt!8%5Ok7rjS!u1e9i84J7I-LM-!pK\tqu?Zr +r;Zcsr;ZcsrVultr;QiO!6>' +g]%>J!.Vod!'p;Z##Lu]s.B@!ec5XLqu6_F!2oeq%I!imBA*=bcqMgdrrBA'rrE+4rr3$n!9*nV +!PN.Es8N)ss8N)us8N'!nGWCe!<)rt!;uls!<)rt!8%5Ok7rjS!u1e9i84J7I-LM-!pK\tqu?Zr +r;Zcsr;ZcsrVultr;QiO!6>' +g]%>J!.Vod!'p;Z##Lu]s.B@!ec5XLqu6_F!2oeq%I!imBA*=bcqMgdrrBA'rrE+4rr3$n!9*nV +!PN.Es8N)ss8N)us8N'!nGWCe!<)rt!;uls!<)rt!8%5Ok7rjS!u1e9i84J7I-LM-!pK\tqu?Zr +r;Zcsr;ZcsrVultr;QiO!6>' +g]%>J!$]/,"&NJ-?e55Zf`2$*r;Qoa!!%E"rr2uFqZ$Vorr;uu"g\1.VZ>*Crs7:O9[Nh> +a%Yasrr^UJ!87AO(%;2'd/X-D!.=;9d$aq7n?W)@!!(^Orr_`j!7:`F"FL4.fo4Yb!Tt2T!!=DF +!8uc7!SNG,rrRQJa8Gu;!;uls!;uls!<)rt!!(^NrrJ'Pr;Zcsr;Zcsr;Zcsr;QhG!:^!f!oX+Z +rr3&Y!)3@k!pK[brr3;h!!$Zbs8UG>d,+g&!1 +g]%>J!$]/,"&NJ-?e55Zf`2$*r;Qoa!!%E"rr2uFqZ$Vorr;uu"g\1.VZ>*Crs7:O9[Nh> +a%Yasrr^UJ!87AO(%;2'd/X-D!.=;9d$aq7n?W)@!!(^Orr_`j!7:`F"FL4.fo4Yb!Tt2T!!=DF +!8uc7!SNG,rrRQJa8Gu;!;uls!;uls!<)rt!!(^NrrJ'Pr;Zcsr;Zcsr;Zcsr;QhG!:^!f!oX+Z +rr3&Y!)3@k!pK[brr3;h!!$Zbs8UG>d,+g&!1 +g]%>J!$]/,"&NJ-?e55Zf`2$*r;Qoa!!%E"rr2uFqZ$Vorr;uu"g\1.VZ>*Crs7:O9[Nh> +a%Yasrr^UJ!87AO(%;2'd/X-D!.=;9d$aq7n?W)@!!(^Orr_`j!7:`F"FL4.fo4Yb!Tt2T!!=DF +!8uc7!SNG,rrRQJa8Gu;!;uls!;uls!<)rt!!(^NrrJ'Pr;Zcsr;Zcsr;Zcsr;QhG!:^!f!oX+Z +rr3&Y!)3@k!pK[brr3;h!!$Zbs8UG>d,+g&!1 +g]%8_ZN(%_!+4@XqZ-Qo!6>$<#iYg`iL0`HI(fLY"p!o$B)m>4r;QucRS3]oVss]cqZ-ZrquHcs +$)[b'I*hn^!0$1>!<<)s!<<'$l":!of`)#&!.UF:!'p;Z"sS$4ruqI$i;Wo49UbJHrr\2[!7:`F +"4.#Jg&D!Rkl:_:rr3)b!!(CFs8N''BA*=bVbH@Rrr^UJ!7:`F"4.#Jd/EtfHiW-YN;rpk!2oks +]uL*QB70aZVZ:Ags5BjU!,#sEs3UWC!2nZQrrAGd!.XkG!^N+8h#@@JrW)]mr;cisr;cisr;cfr +r;ccqr;Zogs4RAO!87AOr;cisr;cfrr;_EKJcFj3J,~> +g]%8_ZN(%_!+4@XqZ-Qo!6>$<#iYg`iL0`HI(fLY"p!o$B)m>4r;QucRS3]oVss]cqZ-ZrquHcs +$)[b'I*hn^!0$1>!<<)s!<<'$l":!of`)#&!.UF:!'p;Z"sS$4ruqI$i;Wo49UbJHrr\2[!7:`F +"4.#Jg&D!Rkl:_:rr3)b!!(CFs8N''BA*=bVbH@Rrr^UJ!7:`F"4.#Jd/EtfHiW-YN;rpk!2oks +]uL*QB70aZVZ:Ags5BjU!,#sEs3UWC!2nZQrrAGd!.XkG!^N+8h#@@JrW)]mr;cisr;cisr;cfr +r;ccqr;Zogs4RAO!87AOr;cisr;cfrr;_EKJcFj3J,~> +g]%8_ZN(%_!+4@XqZ-Qo!6>$<#iYg`iL0`HI(fLY"p!o$B)m>4r;QucRS3]oVss]cqZ-ZrquHcs +$)[b'I*hn^!0$1>!<<)s!<<'$l":!of`)#&!.UF:!'p;Z"sS$4ruqI$i;Wo49UbJHrr\2[!7:`F +"4.#Jg&D!Rkl:_:rr3)b!!(CFs8N''BA*=bVbH@Rrr^UJ!7:`F"4.#Jd/EtfHiW-YN;rpk!2oks +]uL*QB70aZVZ:Ags5BjU!,#sEs3UWC!2nZQrrAGd!.XkG!^N+8h#@@JrW)]mr;cisr;cisr;cfr +r;ccqr;Zogs4RAO!87AOr;cisr;cfrr;_EKJcFj3J,~> +g]%?LVolol!&"!G"]1l\TE&>Ms3L]HIfOtdrr>=]!!4?`ci*kF+opQ[rrA#V!!'_1rrD$T!!*&r +!<<)s!<<)s!<<*!!!VV7!!&JPrVu`p!<;orrr3)bB)nk.rs>u)!1N0P!1Lstrr3;OHiQj8rrAGd!.XtJ!^N+8g&M!Np](0lrr;osrr;osrVufrr;Z]qs8N)grVuqerr;os +rr;osrVufrJcC<$jo9i~> +g]%?LVolol!&"!G"]1l\TE&>Ms3L]HIfOtdrr>=]!!4?`ci*kF+opQ[rrA#V!!'_1rrD$T!!*&r +!<<)s!<<)s!<<*!!!VV7!!&JPrVu`p!<;orrr3)bB)nk.rs>u)!1N0P!1Lstrr3;OHiQj8rrAGd!.XtJ!^N+8g&M!Np](0lrr;osrr;osrVufrr;Z]qs8N)grVuqerr;os +rr;osrVufrJcC<$jo9i~> +g]%?LVolol!&"!G"]1l\TE&>Ms3L]HIfOtdrr>=]!!4?`ci*kF+opQ[rrA#V!!'_1rrD$T!!*&r +!<<)s!<<)s!<<*!!!VV7!!&JPrVu`p!<;orrr3)bB)nk.rs>u)!1N0P!1Lstrr3;OHiQj8rrAGd!.XtJ!^N+8g&M!Np](0lrr;osrr;osrVufrr;Z]qs8N)grVuqerr;os +rr;osrVufrJcC<$jo9i~> +Rf<@Qq>^RnT^Vm[!h]O#JcF'r!e13"RK!7PrW!!DE6nC\![7X&\GuR/RfEBfR/[8<5aUZbs8;rl +s8;rss8;rss8;rrs8;rqs8;rss8DuuBE%r0!<3#s!<)rr!.k0$s5j92~> +Rf<@Qq>^RnT^Vm[!h]O#JcF'r!e13"RK!7PrW!!DE6nC\![7X&\GuR/RfEBfR/[8<5aUZbs8;rl +s8;rss8;rss8;rrs8;rqs8;rss8DuuBE%r0!<3#s!<)rr!.k0$s5j92~> +Rf<@Qq>^RnT^Vm[!h]O#JcF'r!e13"RK!7PrW!!DE6nC\![7X&\GuR/RfEBfR/[8<5aUZbs8;rl +s8;rss8;rss8;rrs8;rqs8;rss8DuuBE%r0!<3#s!<)rr!.k0$s5j92~> +Rf<@Qr;ZmqT^VdX!h]O#JcF'r!e13"RK!@S,&km&rrOAEi4/ge!1Nrf!.k17rrA#W!!)NarrD<_ +!!%uWs8;rss8;rrs8;rqs8;rss8;rss8;rss8;rrs8;qKs+143s*t~> +Rf<@Qr;ZmqT^VdX!h]O#JcF'r!e13"RK!@S,&km&rrOAEi4/ge!1Nrf!.k17rrA#W!!)NarrD<_ +!!%uWs8;rss8;rrs8;rqs8;rss8;rss8;rss8;rrs8;qKs+143s*t~> +Rf<@Qr;ZmqT^VdX!h]O#JcF'r!e13"RK!@S,&km&rrOAEi4/ge!1Nrf!.k17rrA#W!!)NarrD<_ +!!%uWs8;rss8;rrs8;rqs8;rss8;rss8;rss8;rrs8;qKs+143s*t~> +Rf'=!9*bR!87>O!6>*= +r;cisr;cfrr;ccqr;cisr;cisr;cisr;cfrr;_EKJcFj3J,~> +Rf'=!9*bR!87>O!6>*= +r;cisr;cfrr;ccqr;cisr;cisr;cisr;cfrr;_EKJcFj3J,~> +Rf'=!9*bR!87>O!6>*= +r;cisr;cfrr;ccqr;cisr;cisr;cisr;cfrr;_EKJcFj3J,~> +RfMs3L]HIfOtVrrOAEi4/ge!1Nrf!.k16rrYpp!4)G#"0qn,9`>"i!<3#s!<)rr +!;ulq!<3#t!!$[2s8;rss8;rrs8;qKs+143s*t~> +RfMs3L]HIfOtVrrOAEi4/ge!1Nrf!.k16rrYpp!4)G#"0qn,9`>"i!<3#s!<)rr +!;ulq!<3#t!!$[2s8;rss8;rrs8;qKs+143s*t~> +RfMs3L]HIfOtVrrOAEi4/ge!1Nrf!.k16rrYpp!4)G#"0qn,9`>"i!<3#s!<)rr +!;ulq!<3#t!!$[2s8;rss8;rrs8;qKs+143s*t~> +N;isP!+1UOj!!(CEs8;rss8;rrs8;rq +s8;rss8DuuRf +N;isP!+1UOj!!(CEs8;rss8;rrs8;rq +s8;rss8DuuRf +N;isP!+1UOj!!(CEs8;rss8;rrs8;rq +s8;rss8DuuRf +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1P!)1c:rrBb1!!%EF!!)9_rrBA& +!!:jRs8;p$ZN$?n!0$mV!58:1!.=_F!9sL_!4)M&!82r'JcFs6J,~> +N;isP!+1P!)1c:rrBb1!!%EF!!)9_rrBA& +!!:jRs8;p$ZN$?n!0$mV!58:1!.=_F!9sL_!4)M&!82r'JcFs6J,~> +N;isP!+1P!)1c:rrBb1!!%EF!!)9_rrBA& +!!:jRs8;p$ZN$?n!0$mV!58:1!.=_F!9sL_!4)M&!82r'JcFs6J,~> +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+3)4s*XhG"7X@"!2fbtIfOtVrrOAEi.:pSs8N(Ms1JC1!.k0$s2b4j~> +N;isP!+3)4s*XhG"7X@"!2fbtIfOtVrrOAEi.:pSs8N(Ms1JC1!.k0$s2b4j~> +N;isP!+3)4s*XhG"7X@"!2fbtIfOtVrrOAEi.:pSs8N(Ms1JC1!.k0$s2b4j~> +N;isP!+3YDoDnmjs*XhG",pjm!2fbtIfOtVrrOAEi2$ATnAgstYlF_'JcEC_r;_EKJcEgkJ,~> +N;isP!+3YDoDnmjs*XhG",pjm!2fbtIfOtVrrOAEi2$ATnAgstYlF_'JcEC_r;_EKJcEgkJ,~> +N;isP!+3YDoDnmjs*XhG",pjm!2fbtIfOtVrrOAEi2$ATnAgstYlF_'JcEC_r;_EKJcEgkJ,~> +N;isP!+3VC!ndPRqu6`E9E=herrDus!Up)krrRZMIuF=.+opQSs7? +N;isP!+3VC!ndPRqu6`E9E=herrDus!Up)krrRZMIuF=.+opQSs7? +N;isP!+3VC!ndPRqu6`E9E=herrDus!Up)krrRZMIuF=.+opQSs7? +N;isP!+3SBrrDoq!PJL-s8N)srrLIHXoAHP!.Tq,![7X&f`)$+!!)or!oZfQfDkjNYlF_'JcEF` +qZ)3IJcEjlJ,~> +N;isP!+3SBrrDoq!PJL-s8N)srrLIHXoAHP!.Tq,![7X&f`)$+!!)or!oZfQfDkjNYlF_'JcEF` +qZ)3IJcEjlJ,~> +N;isP!+3SBrrDoq!PJL-s8N)srrLIHXoAHP!.Tq,![7X&f`)$+!!)or!oZfQfDkjNYlF_'JcEF` +qZ)3IJcEjlJ,~> +N;isP!+3SBrrDoq!Up*`s8N)srrJPgXoAHP!.Tq,![7X&fDkjNqYpTC!8%8N!3lM'!.k0$s+13$ +s8W+L~> +N;isP!+3SBrrDoq!Up*`s8N)srrJPgXoAHP!.Tq,![7X&fDkjNqYpTC!8%8N!3lM'!.k0$s+13$ +s8W+L~> +N;isP!+3SBrrDoq!Up*`s8N)srrJPgXoAHP!.Tq,![7X&fDkjNqYpTC!8%8N!3lM'!.k0$s+13$ +s8W+L~> +N;isP!+3SBrrDKerrE#t!mgoIXoAHP!.Tq,![7X&fDkjNqYpTc!8%8N!3lM'!.k0$s+13$s8W+L~> +N;isP!+3SBrrDKerrE#t!mgoIXoAHP!.Tq,![7X&fDkjNqYpTc!8%8N!3lM'!.k0$s+13$s8W+L~> +N;isP!+3SBrrDKerrE#t!mgoIXoAHP!.Tq,![7X&fDkjNqYpTc!8%8N!3lM'!.k0$s+13$s8W+L~> +N;isP!+3SBrrDfn"7X@"!;uls!<2uuN;NYUN;ih\l).2TB>+ +N;isP!+3SBrrDfn"7X@"!;uls!<2uuN;NYUN;ih\l).2TB>+ +N;isP!+3SBrrDfn"7X@"!;uls!<2uuN;NYUN;ih\l).2TB>+ +N;isP!+3SBrrE#t!Up*frr[X]!!)rsrrDusrrDus'$s>!s5A>*I/j4ZB)hq;l/?9&`W$!h!.Tq, +![7X&fDkjNpAYHga-m#.iL0`HZMsk(iVWZWiW&rW!!nP`s66FT!,'"Bs8N)rrs%tj9E7banG`Fo +nAgsts3Q,n9YL?'"mMpY!,'!rs8N(Ms+13$s+14Ms*t~> +N;isP!+3SBrrE#t!Up*frr[X]!!)rsrrDusrrDus'$s>!s5A>*I/j4ZB)hq;l/?9&`W$!h!.Tq, +![7X&fDkjNpAYHga-m#.iL0`HZMsk(iVWZWiW&rW!!nP`s66FT!,'"Bs8N)rrs%tj9E7banG`Fo +nAgsts3Q,n9YL?'"mMpY!,'!rs8N(Ms+13$s+14Ms*t~> +N;isP!+3SBrrE#t!Up*frr[X]!!)rsrrDusrrDus'$s>!s5A>*I/j4ZB)hq;l/?9&`W$!h!.Tq, +![7X&fDkjNpAYHga-m#.iL0`HZMsk(iVWZWiW&rW!!nP`s66FT!,'"Bs8N)rrs%tj9E7banG`Fo +nAgsts3Q,n9YL?'"mMpY!,'!rs8N(Ms+13$s+14Ms*t~> +N;isP!+3SBrrE#t!La#cs8N)ss8N)ss8N)trrV[`a8Z)@f`2#crr;uu!78R^!e13"MuNi&!8uK/ +rrDrr!!)ut$@HId!56)Gs/,k1rr3)iHiT-'rsO4Ps8UG>d/W'P!.=_ErrDus($SE*s8UbG9\KIG +HtNEZZI&X@RK/fTrs-nEd/W'P!. +N;isP!+3SBrrE#t!La#cs8N)ss8N)ss8N)trrV[`a8Z)@f`2#crr;uu!78R^!e13"MuNi&!8uK/ +rrDrr!!)ut$@HId!56)Gs/,k1rr3)iHiT-'rsO4Ps8UG>d/W'P!.=_ErrDus($SE*s8UbG9\KIG +HtNEZZI&X@RK/fTrs-nEd/W'P!. +N;isP!+3SBrrE#t!La#cs8N)ss8N)ss8N)trrV[`a8Z)@f`2#crr;uu!78R^!e13"MuNi&!8uK/ +rrDrr!!)ut$@HId!56)Gs/,k1rr3)iHiT-'rsO4Ps8UG>d/W'P!.=_ErrDus($SE*s8UbG9\KIG +HtNEZZI&X@RK/fTrs-nEd/W'P!. +N;isP!+3SBq#L +N;isP!+3SBq#L +N;isP!+3SBq#L +N;isP!+3SBrrE#t!PJL1s8N)ss8N)ss8N)trr?^,!<3#u!5SU9IfOtVrrOAEi7J#(!;lfr!;uls +!;uiuHiW.)rrq)Rs8Stsr;Zcs!.=bFrrE#t!lk<*r;Qhr!4)V(rrDus#1*@=s8Stsr;Zcs!. +N;isP!+3SBrrE#t!PJL1s8N)ss8N)ss8N)trr?^,!<3#u!5SU9IfOtVrrOAEi7J#(!;lfr!;uls +!;uiuHiW.)rrq)Rs8Stsr;Zcs!.=bFrrE#t!lk<*r;Qhr!4)V(rrDus#1*@=s8Stsr;Zcs!. +N;isP!+3SBrrE#t!PJL1s8N)ss8N)ss8N)trr?^,!<3#u!5SU9IfOtVrrOAEi7J#(!;lfr!;uls +!;uiuHiW.)rrq)Rs8Stsr;Zcs!.=bFrrE#t!lk<*r;Qhr!4)V(rrDus#1*@=s8Stsr;Zcs!. +N;isP!+3SBrrDus!!)orrrDusrrDusrrE#trrDcmrrBk7!e13"MuNi&!8uK/rrDus!PJL1s8N)s +s8N)srrUOIVuH]!Rb@`@BD;K*s8N)trrIKIqu6`V!,)<2rrDus"n2Kls8Qa,!8.>O!.k0$s+13$ +s8W+L~> +N;isP!+3SBrrDus!!)orrrDusrrDusrrE#trrDcmrrBk7!e13"MuNi&!8uK/rrDus!PJL1s8N)s +s8N)srrUOIVuH]!Rb@`@BD;K*s8N)trrIKIqu6`V!,)<2rrDus"n2Kls8Qa,!8.>O!.k0$s+13$ +s8W+L~> +N;isP!+3SBrrDus!!)orrrDusrrDusrrE#trrDcmrrBk7!e13"MuNi&!8uK/rrDus!PJL1s8N)s +s8N)srrUOIVuH]!Rb@`@BD;K*s8N)trrIKIqu6`V!,)<2rrDus"n2Kls8Qa,!8.>O!.k0$s+13$ +s8W+L~> +N;isP!+3SBrrD`lrrDusrrDusrrE#trr<&gp](6n_#FIc!.Tq,![7X&fDkjNqu6Wrqu?Zrr;Zcs +qu6Zs9`G%lBE%r2!;6Bl!<)rt!;c`q!<3#u!;lfr!<<*!!7:cG!.k0$s+13$s8W+L~> +N;isP!+3SBrrD`lrrDusrrDusrrE#trr<&gp](6n_#FIc!.Tq,![7X&fDkjNqu6Wrqu?Zrr;Zcs +qu6Zs9`G%lBE%r2!;6Bl!<)rt!;c`q!<3#u!;lfr!<<*!!7:cG!.k0$s+13$s8W+L~> +N;isP!+3SBrrD`lrrDusrrDusrrE#trr<&gp](6n_#FIc!.Tq,![7X&fDkjNqu6Wrqu?Zrr;Zcs +qu6Zs9`G%lBE%r2!;6Bl!<)rt!;c`q!<3#u!;lfr!<<*!!7:cG!.k0$s+13$s8W+L~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t!bVMRr;QfeBE%r2!5SU9IfOtVrrOAEi7J#/!;-*Da0P^Err<&gpAb-mrVultqZ$Qqrr;uuqu?Zrs8W*!!:\D9rr@WMJcC<$JcGcMJ,~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t!bVMRr;QfeBE%r2!5SU9IfOtVrrOAEi7J#/!;-*Da0P^Err<&gpAb-mrVultqZ$Qqrr;uuqu?Zrs8W*!!:\D9rr@WMJcC<$JcGcMJ,~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t!bVMRr;QfeBE%r2!5SU9IfOtVrrOAEi7J#/!;-*Da0P^Err<&gpAb-mrVultqZ$Qqrr;uuqu?Zrs8W*!!:\D9rr@WMJcC<$JcGcMJ,~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t!iH#lr;Qf2N;ikW!5SU9IfOtVrrOAEi7J#/!;-$;!UsaSs8N(M +s+13$s+14Ms*t~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t!iH#lr;Qf2N;ikW!5SU9IfOtVrrOAEi7J#/!;-$;!UsaSs8N(M +s+13$s+14Ms*t~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t!iH#lr;Qf2N;ikW!5SU9IfOtVrrOAEi7J#/!;-$;!UsaSs8N(M +s+13$s+14Ms*t~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t$0_EiBA*=bcqMgcs8N)7rrRZMIuF=.+opQQs8N)prrM)+ +rr;uur;ZcsqYpY1!76,lrrT(u9`4nk]o;pirrE#t!jVg(r;Qi_!7:`FrrDus#MB*ts8Sts9`4nk +]o:VDrr@WMJcC<$JcGcMJ,~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t$0_EiBA*=bcqMgcs8N)7rrRZMIuF=.+opQQs8N)prrM)+ +rr;uur;ZcsqYpY1!76,lrrT(u9`4nk]o;pirrE#t!jVg(r;Qi_!7:`FrrDus#MB*ts8Sts9`4nk +]o:VDrr@WMJcC<$JcGcMJ,~> +N;isP!+3SBrrD`lrrDusrrDusrrE#t$0_EiBA*=bcqMgcs8N)7rrRZMIuF=.+opQQs8N)prrM)+ +rr;uur;ZcsqYpY1!76,lrrT(u9`4nk]o;pirrE#t!jVg(r;Qi_!7:`FrrDus#MB*ts8Sts9`4nk +]o:VDrr@WMJcC<$JcGcMJ,~> +N;isP!+3VC"5*YSg%YLKci='mrr3)I!!(CErs*oOiRs1is3UWC!2ohr"31BAiPGNqIfOtVrrOAE +i7J#/!;ZWq9ZR/4rrDusrrDoq"2+[7d/EtNkl:]rg&M*!9[Nbd+JBu!.k0$s+13$s8W+L~> +N;isP!+3VC"5*YSg%YLKci='mrr3)I!!(CErs*oOiRs1is3UWC!2ohr"31BAiPGNqIfOtVrrOAE +i7J#/!;ZWq9ZR/4rrDusrrDoq"2+[7d/EtNkl:]rg&M*!9[Nbd+JBu!.k0$s+13$s8W+L~> +N;isP!+3VC"5*YSg%YLKci='mrr3)I!!(CErs*oOiRs1is3UWC!2ohr"31BAiPGNqIfOtVrrOAE +i7J#/!;ZWq9ZR/4rrDusrrDoq"2+[7d/EtNkl:]rg&M*!9[Nbd+JBu!.k0$s+13$s8W+L~> +N;isP!+3YDqZ-HlqZ$WrqZ-Wq"6jFuVu?W!iL0`HI(fOZqZ+M5!e13"MuNi&!8uN0"5*YSl2:P_ +fk1 +N;isP!+3YDqZ-HlqZ$WrqZ-Wq"6jFuVu?W!iL0`HI(fOZqZ+M5!e13"MuNi&!8uN0"5*YSl2:P_ +fk1 +N;isP!+3YDqZ-HlqZ$WrqZ-Wq"6jFuVu?W!iL0`HI(fOZqZ+M5!e13"MuNi&!8uN0"5*YSl2:P_ +fk1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!+1 +N;isP!(_[UcbBNg!.Tq,![7X&JcF'rrr@WMJcC<$JcGcMJ,~> +N;isP!(_[UcbBNg!.Tq,![7X&JcF'rrr@WMJcC<$JcGcMJ,~> +N;isP!(_[UcbBNg!.Tq,![7X&JcF'rrr@WMJcC<$JcGcMJ,~> +N;imNJH3jn!.Tq,![7V(JO%OHrr@WMJcC<$JcGcMJ,~> +N;imNJH3jn!.Tq,![7V(JO%OHrr@WMJcC<$JcGcMJ,~> +N;imNJH3jn!.Tq,![7V(JO%OHrr@WMJcC<$JcGcMJ,~> +N;imeJO%CD!2,8M!$Zsob5d+nJcC<$JcGcMJ,~> +N;imeJO%CD!2,8M!$Zsob5d+nJcC<$JcGcMJ,~> +N;imeJO%CD!2,8M!$Zsob5d+nJcC<$JcGcMJ,~> +JcC<$JcFU,!69Z*bJ/W.JcC<$JcGcMJ,~> +JcC<$JcFU,!69Z*bJ/W.JcC<$JcGcMJ,~> +JcC<$JcFU,!69Z*bJ/W.JcC<$JcGcMJ,~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +JcC<$JcC<$JcC<$JcC<$V>l&~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/nymanimpl.mss b/docsrc/nyquist/nymanimpl.mss new file mode 100644 index 0000000..28a9533 --- /dev/null +++ b/docsrc/nyquist/nymanimpl.mss @@ -0,0 +1,467 @@ +@part(Implementation,root "nyquistman2.mss") +@appendix(Extending Nyquist) +@label(extending-app) +@p(WARNING:) +Nyquist sound functions look almost like a human wrote them; they even have +a fair number of comments for human readers. Don't be fooled: virtually all +Nyquist functions are written by a special translator. If you try to write +a new function by hand, you will probably not succeed, and even if you do, +you will waste a great deal of time. (End of Warning.) + + +@section(Translating Descriptions to C Code) + +The translator code used to extend Nyquist resides in the @code(trnsrc) +directory. This directory also contains a special @code(init.lsp), so if +you start XLisp or Nyquist in this directory, it will automatically read +@code(init.lsp), which in turn will load the translator code (which resides +in several files). + +Also in the @code(trnsrc) directory are a number of @code(.alg) files, which +contain the source code for the translator (more on these will follow), and +a number of corresponding @code(.h) and @code(.c) files. + +To translate a @code(.alg) file to @code(.c) and @code(.h) files, you start +XLisp or Nyquist in the @code(trnsrc) directory and type +@begin(example) +(translate "prod") +@end(example) +where @code("prod") should really be replaced by the filename (without a +suffix) you want to translate. Be sure you have a saved, working copy of +Nyquist or Xlisp before you recompile! + +@p(Note:) On the Macintosh, just run Nyquist out of the @code(runtime) directory and then use the @code(Load) menu command to load @code(init.lsp) from the @code(trnsrc) directory. This will load the translation code and change Nyquist's current directory to @code(trnsrc) so that commands like @code[(translate "prod")] will work. + +@section(Rebuilding Nyquist) + +After generating @code(prod.c) and +@code(prod.h), you need to recompile Nyquist. For Unix systems, you will +want to generate a new Makefile. Modify @code(transfiles.lsp) in your main +Nyquist directory, run Xlisp or Nyquist and load @code(makefile.lsp). +Follow the instructions to set your machine type, etc., and +execute @code[(makesrc)] and @code[(makefile)]. + +@begin(comment) +@subsection(Special Macintosh Instructions) + +For the Code Warrior/Macintosh implementation, you will need to generate new Lisp-to-C interface files and then modify your project file. To generate Lisp-to-C interface files, first modify the file @code(:nyqsrc:sndfn.cl) to include your newly generated @code(.h) file. If you are not familiar with naming Macintosh folders, this file may look a bit odd. The initial colon in a file name means to start in the current folder. After that, colons separate folder and file names. For example, +@begin(example) +:tran:osc.h +@end(example) +means to start from the current directory, go to the @code(tran) directory, and there find the @code(osc.h) file. + +After modifying @code(sndfn.cl), run the @code(intgen) program, which must be in the top-level Nyquist directory (the parent directory to @code(nyqsrc) and @code(tran). (If you build the @code(intgen) program in @code(misc), copy it to the parent directory.) After starting @code(intgen), to the command line, type: +@begin(example) +@@:nyqsrc:sndfn.cl +@end(example) +which tells @code(intgen) to use the contents of the @code(sndfn.cl) file as a command line. Read about @code(intgen) in Appendix @ref(intgen-app). + +Next, add the @code(.c) file generated by @code(translate) (e.g. @code(prod.c)) to your Nyquist project and recompile Nyquist. +@end(comment) + +@section(Accessing the New Function) + +The new Lisp function will generally be named with a @code(snd-) prefix, +e.g. @code(snd-prod). You can test this by running Nyquist. Debugging is +usually a combination of calling the code from within the interpreter, +reading the generated code when things go wrong, and using a C debugger to +step through the inner loop of the generated code. An approach I like is to +set the default sample rate to 10 hertz. Then, a one-second sound has only +10 samples, which are easy to print and study on a text console. + +For some functions, +you must write some Lisp code to impose +ordinary Nyquist behaviors such as stretching and time shifting. A +good approach is to find some structurally similar functions and see how +they are implemented. Most of the Lisp code for Nyquist is in +@code(nyquist.lsp). + +Finally, do not forget to write up some documentation. Also, contributions are +welcome. Send your @code(.alg) file, documentation, Lisp support +functions for @code(nyquist.lsp), and examples or test programs +to @code(rbd@@cs.cmu.edu). I will either put them in the next release or +make them available at a public ftp site. + + +@section(Why Translation?) +Many of the Nyquist signal processing operations are similar in form, but +they differ in details. This code is complicated by many factors: Nyquist +uses lazy evaluation, so the operator must check to see that input samples +are available before trying to access them. Nyquist signals can have +different sample rates, different block sizes, different block boundaries, +and different start times, all of which must be taken into account. The +number of software tests is enormous. (This may sound like a lot of +overhead, but the overhead is amortized over many iterations of the inner +loop. Of course setting up the inner loop to run efficiently is one more +programming task.) + +The main idea behind the translation is that all of the checks and setup +code are similar and relatively easy to generate automatically. Programmers +often use macros for this sort of task, but the C macro processor is too +limited for the complex translation required here. To tell the translator +how to generate code, you write @code(.alg) files, which provide many +details about the operation in a declarative style. For example, the code +generator can make some optimizations if you declare that two input signals +are commutative (they can be exchanged with one another). The main part of +the @code(.alg) file is the inner loop which is the heart of the signal +processing code. + +@section(Writing a .alg File) +@p(WARNING:) Translation relies heavily on string substitution, which +is fragile. In particular, variables with names that are substrings of +other variables will cause problems. For example if you declare STATE +variables "phase" and "iphase", then the translator will globally +substitute "phase_reg" for "phase", converting "phase" to "phase_reg" +and iphase" to "iphase_reg". Then it will substitute "iphase_reg" for +iphase" which will convert the existing "iphase_reg" to +"iphase_reg_reg". This will be confusing and will not compile. +(End of WARNING) + +To give you some idea how functions are specified, here is the +specification for @code(snd-prod), which generates over 250 lines of C code: +@begin(example) +(PROD-ALG + (NAME "prod") + (ARGUMENTS ("sound_type" "s1") ("sound_type" "s2")) + (START (MAX s1 s2)) + (COMMUTATIVE (s1 s2)) + (INNER-LOOP "output = s1 * s2") + (LINEAR s1 s2) + (TERMINATE (MIN s1 s2)) + (LOGICAL-STOP (MIN s1 s2)) +) +@end(example) +A @code(.alg) file is always of the form: +@begin(example) +(@i(name) + (@i(attribute) @i(value)) + (@i(attribute) @i(value)) + ... +) +@end(example) +There should be just one of these algorithms descriptions per file. +The @i(name) field is arbitrary: it is a Lisp symbol whose property list is +used to save the following attribute/value pairs. There are many +attributes described below. For more examples, see the @code(.alg) files in +the @code(trnsrc) directory. + +Understanding what the attributes do is not +easy, so here are three recommendations for implementors. First, if there is +an existing Nyquist operator that is structurally similar to something you +want to implement, make a copy of the corresponding @code(.alg) file and +work from there. In some cases, you can merely rename the parameters and +substitute a new inner loop. Second, read the generated code, especially +the generated inner loop. It may not all make sense, but sometimes you can +spot obvious errors and work your way back to the error in the @code(.alg) +file. Third, if you know where something bad is generated, see if you can +find where the code is generated. (The code generator files are listed in +@code(init.lsp).) This code is poorly written and poorly documented, but in +some cases it is fairly straightforward to determine what attribute in the +@code(.alg) file is responsible for the erroneous output. + +@section(Attributes) +Here are the attributes used for code generation. Attributes and values may +be specified in any order. +@begin(description) +@code[(NAME "@i(string)")]@\specifies a base name for many identifiers. In +particular, the generated filenames will be @i(string)@code(.c) and +@i(string)@code(.h), and the XLisp function generated will be +@code(snd-)@i(string). + +@code[(ARGUMENTS @i(arglist))]@\describes the arguments to be passed from +XLisp. @i(Arglist) has the form: @code[(@i(type1) @i(name1)) (@i(type2) +@i(name2)) ...], where @i(type) and @i(name) are strings in double quotes, +e.g. ("sound_type" "s") specifies a SOUND parameter named @code(s). Note that @i(arglist) is not surrounded by parentheses. As seen +in this example, the type names and parameter names are C identifiers. Since +the parameters are passed in from XLisp, they must be chosen from a +restricted set. Valid type names are: @code("sound_type"), @code("rate_type"), @code("double"), +@code("long"), @code("string"), and @code("LVAL"). + + +@code[(STATE @i(statelist))]@\describes additional state (variables) needed +to perform the computation. A @i(statelist) is similar to an @i(arglist) +(see @code(ARGUMENTS) above), and has the form: @code{(@i(type1) @i(name1) +@i(init1) [TEMP]) (@i(type2) @i(name2) @i(init2) [TEMP]) ...}. +The types and names are as +in @i(arglist), and the "inits" are double-quoted initial values. Initial +values may be any C expression. State is initialized in the order implied by +@i(statelist) when the operation is first called from XLisp. If @code(TEMP) +is omitted the state is preserved in a structure until the sound computation +completes. Otherwise, the state variable only exists at state +initialization time. + +@code[(INNER-LOOP @i(innerloop-code))]@\describes the inner loop, written as +C code. The @i(innerloop-code) is in double quotes, and may extend over +multiple lines. To make generated code extra-beautiful, prefix each line of +@i(innerloop-code) with 12 spaces. Temporary variables should not +be declared at the beginning of @i(innerloop-code). Use the +@code(INNER-LOOP-LOCALS) attribute instead. Within @i(innerloop-code), +@i(each ARGUMENT of type sound_type) @p(must) @i(be referenced exactly one +time.) If you need to use a signal value twice, assign it once to a +temporary and use the temporary twice. The inner loop must also assign +@i(one) time to the psuedo-variable @i(output). The model here is that the +name of a sound argument denotes the value of the corresponding signal at +the current output sample time. The inner loop code will be called once for +each output sample. In practice, the code generator will substitute some +expression for each signal name. For example, +@code(prod.alg) specifies +@display[@code[(INNER-LOOP "output = s1 * s2")]] +(@code(s1) and @code(s2) are @code(ARGUMENTS).) This expands to the +following inner loop in @code(prod.c): +@display[@code[*out_ptr_reg++ = *s1_ptr_reg++ * *s2_ptr_reg++;]] +In cases where arguments have different sample rates, sample interpolation +is in-lined, and the expressions can get very complex. The translator is +currently very simple-minded about substituting access code in the place of +parameter names, and @i(this is a frequent source of bugs.) Simple string +substitution is performed, so @i(you must not use a parameter or state name +that is a substring of another). For example, if two sound parameters were +named @code(s) and @code(s2), the translator might substitute for ``s'' in two +places rather than one. If this problem occurs, you will almost certainly +get a C compiler syntax error. The fix is to use ``more unique'' parameter +and state variable names. + +@code[(INNER-LOOP-LOCALS "@i(innerloop-code)")]@\The @i(innerloop-code) +contains C declarations of local variables set and referenced in the inner +loop. + +@code[(SAMPLE-RATE "@i(expr)")]@\specifies the output sample rate; @i(expr) +can be any C expression, including a parameter from the @code(ARGUMENTS) +list. You can also write @code[(SAMPLE-RATE (MAX @i(name1) @i(name2) ...))] +where names are unquoted names of arguments. + +@code[(SUPPORT-HEADER "@i(c-code)")]@\specifies arbitrary C code to be +inserted in the generated @code(.h) file. The code typically contains +auxiliarly function declarations and definitions of constants. + +@code[(SUPPORT-FUNCTIONS "@i(c-code)")]@\specifies arbitrary C code to be +inserted in the generated @code(.c) file. The code typically contains +auxiliarly functions and definitions of constants. + +@code[(FINALIZATION "@i(c-code)")]@\specifies code to execute when the sound +has been fully computed and the state variables are about to be +decallocated. This is the place to deallocate buffer memory, etc. + +@code[(CONSTANT "@i(name1)" "@i(name2)" ...)]@\specifies state variables that +do not change value in the inner loop. The values of state +variables are loaded into registers before entering the inner loop so that +access will be fast within the loop. On exiting the inner loop, the final +register values are preserved in a ``suspension'' structure. If state +values do not change in the inner loop, this @code(CONSTANT) declaration can +eliminate the overhead of storing these registers. + +@code[(START @i(spec))]@\specifies when the output sound should start (a +sound is zero and no processing is done before the start time). The @i(spec) +can take several forms: @code[(MIN @i(name1) @i(name2) ...)] means the start +time is the minimum of the start times of input signals @i(name1), +@i(name2), .... Note that these names are not quoted. + +@code[(TERMINATE @i(spec))]@\specifies when the output +sound terminates (a sound is +zero after this termination time and no more samples are computed). The +@i(spec) can take several forms: @code[(MIN @i(name1) @i(name2) ...)] means +the terminate time is the minimum of the terminate times of input arguments +@i(name1), @i(name2), .... Note that these names are not quoted. To +terminate at the time of a single argument @code(s1), specify @code[(MIN +s1)]. To terminate after a specific duration, use @code[(AFTER "@i(c-expr)")], +where @i(c-expr) is a C variable or expression. To terminate at a +particular time, use @code[(AT "@i(c-expr)")]. @i(spec) may also be +@code(COMPUTED), which means to use the maximum sample rate of any input +signal. + +@code[(LOGICAL-STOP @i(spec))]@\specifies the logical stop time of the output +sound. This @i(spec) is just like the one for @code(TERMINATE). If no +@code(LOGICAL-STOP) attribute is present, the logical stop will coincide +with the terminate time. + +@code[(ALWAYS-SCALE @i(name1) @i(name2) ...)]@\says that the named sound +arguments (not in quotes) should always be multiplied by a scale factor. +This is a space-time tradeoff. When Nyquist sounds are scaled, the scale +factor is merely stored in a structure. It is the responsibility of +the user of the samples to actually scale them (unless the scale factor is +exactly 1.0). The default is to generate code with and without scaling and +to select the appropriate code at run time. If there are N signal inputs, +this will generate 2@+(N) versions of the code. To avoid this code +explosion, use the @code(ALWAYS-SCALE) attribute. + +@code[(INLINE-INTERPOLATION T)]@\specifies that sample rate interpolation +should be performed in-line in the inner loop. There are two forms of sample +rate interpolation. One is intended for use when the rate change is large +and many points will be interpolated. This form uses a divide instruction +and some setup at the low sample rate, +but the inner loop overhead is just an add. The +other form, intended for less drastic sample rate changes, performs +interpolation with 2 multiplies and several adds per sample at the high +sample rate. Nyquist generates various inner loops and selects the +appropriate one at run-time. If @code(INLINE-INTERPOLATION) is not set, +then much less code is generated and interpolation is performed as necessary +by instantiating a separate signal processing operation. + +@code[(STEP-FUNCTION @i(name1) @i(name2) ...)]@\Normally all argument +signals are +linearly interpolated to the output sample rate. The linear interpolation +can be turned off with this attribute. This is used, for example, in Nyquist +variable filters so that filter coefficients are computed at low sample +rates. In fact, this attribute was added for the special case of filters. + +@code[(DEPENDS @i(spec1) @i(spec2) ...)]@\Specifies dependencies. This +attribute was also introduced to handle the case of filter coefficients (but +may have other applications.) Use it when a state variable is a function of +a potentially low-sample-rate input where the input is in the +@code(STEP-FUNCTION) list. Consider a filter coefficient that depends upon +an input signal such as bandwidth. In this case, you want to compute the +filter coefficient only when the input signal changes rather than every +output sample, since output may occur at a much higher sample rate. A +@i(spec) is of the form +@display{@code{("@i(name)" "@i(arg)" "@i(expr)" [TEMP @i("type")])}} +which is interpreted as follows: @I(name) depends upon @i(arg); when @i(arg) +changes, recompute @i(expr) and assign it to @i(name). The @i(name) must be +declared as a @code(STATE) variable unless @code(TEMP) is present, in which +case @i(name) is not preserved and is used only to compute other state. +Variables are updated in the order of the @code(DEPENDS) list. + +@code[(FORCE-INTO-REGISTER @i(name1) @i(name2) ...)]@\causes @i(name1), +@i(name2), ... to be loaded into registers before entering the inner loop. +If the inner loop references a state variable or argument, this happens +automatically. Use this attribute only if references are ``hidden'' in a +@code(#define)'d macro or referenced in a @code(DEPENDS) specification. + +@code[(NOT-REGISTER @i(name1) @i(name2) ...)]@\specifies state and arguments +that should not be loaded into registers before entering an inner loop. +This is sometimes an optimization for infrequently accessed state. + +@code[(NOT-IN-INNER-LOOP "@i(name1)" "@i(name2)" ...)]@\says that certain +arguments are not used in the inner loop. Nyquist assumes all arguments +are used in the inner loop, so specify them here if not. For example, +tables are passed into functions as sounds, but these sounds are not read +sample-by-sample in the inner loop, so they should be listed here. + +@code[(MAINTAIN ("@i(name1)" "@i(expr1)") ("@i(name2)" "@i(expr2)") ... +)]@\Sometimes the IBM XLC compiler generates better loop code if a variable +referenced in the loop is not referenced outside of the loop after the loop +exit. Technically, optimization is better when variables are dead upon loop +exit. Sometimes, there is an efficient way to compute the final value of a +state variable without actually referencing it, in which case the variable +and the computation method are given as a pair in the @code(MAINTAIN) +attribute. This suppresses a store of the value of the named variable, +making it a dead variable. Where the store would have been, the expression +is computed and assigned to the named variable. See @code(partial.alg) for +an example. This optimization is never necessary and is only for +fine-tuning. + +@code[(LINEAR @i(name1) @i(name2) ...)]@\specifies that named arguments +(without quotes) are linear with respect to the output. What this +@i(really) means is that it is numerically OK to eliminate a scale factor from +the named argument and store it in the output sound descriptor, avoiding a +potential multiply in this inner loop. For example, both arguments to +@code(snd-prod) (signal multiplication) are ``linear.'' The inner loop has +a single multiplication operator to multiply samples vs. a potential 3 +multiplies if each sample were also scaled. To handle scale factors on the +input signals, the scale factors are automatically multiplied and the +product becomes the scale factor of the resulting output. (This effectively +``passes the buck'' to some other, or perhaps more than one, signal +processing function, which is not always optimal. On the other hand, it +works great if you multiply a number of scaled signals together: all the +scale factors are ultimately handled with a single multiply.) + +@code[(INTERNAL-SCALING @i(name1) @i(name2) ...)]@\indicates that scaling is +handled in code that is hidden from the code generator for @i(name1), +@i(name2), ..., which are sound arguments. Although it is the responsibility +of the reader of samples to apply any given scale factor, sometimes scaling +can be had for free. For example, the @code(snd-recip) operation computes +the reciprocal of the input samples by peforming a division. The simple +approach would be to specify an inner loop of @code[output = 1.0/s1], where +@code(s1) is the input. With scaling, this would generate an inner loop +something like this: +@display(@code[*output++ = 1.0 / (s1_scale_factor * *s1++);]) +but a much better approach would be the following: +@display(@code[*output++ = my_scale_factor / *s1++]) +where @code(my_scale_factor) is initialized to @code(1.0 / s1->scale). +Working backward from the desired inner loop to the @code(.alg) inner loop +specification, a first attempt might be to specify: +@display(@code[(INNER-LOOP "output = my_scale_factor / s1")]) +but this will generate the following: +@display(@code[*output++=my_scale_factor/(s1_scale_factor * *s1++);]) +Since the code generator does not know that scaling is handled elsewhere, +the scaling is done twice! The solution is to put @code(s1) in the +@code(INTERNAL-SCALING) list, which essentially means ``I've already +incorporated scaling into the algorithm, so suppress the multiplication by a +scale factor.'' + +@code[(COMMUTATIVE (@i(name1) @i(name2) ...))]@\specifies that the results +will not be affected by interchanging any of the listed arguments. When +arguments are commutative, Nyquist rearranges them at run-time into +decreasing order of sample rates. If interpolation is in-line, this can +dramatically reduce the amount of code generated to handle all the different +cases. The prime example is @code(prod.alg). + +@code[(TYPE-CHECK "@i(code)")]@\specifies checking code to be inserted after +argument type checking at initialization time. See @code(downproto.alg) for +an example where a check is made to guarantee that the output sample rate is +not greater than the input sample rate. Otherwise an error is raised. + +@end(description) + +@section(Generated Names) +The resulting @code(.c) file defines a number of procedures. The procedures +that do actual sample computation are named something like +@i(name)@c(_)@i(interp-spec)@c(_fetch), where @i(name) is the @c(NAME) +attribute from the @code(.alg) file, and @i(interp-spec) is an interpolation +specification composed of a string of the following letters: n, s, i, and r. +One letter corresponds to each sound argument, indicating no interpolation +(r), scaling only (s), ordinary linear interpolation with scaling (i), and +ramp (incremental) interpolation with scaling (r). The code generator +determines all the combinations of n, s, i, and r that are necessary and +generates a separate fetch function for each. + +Another function is @i(name)@code(_toss_fetch), which is called when sounds +are not time-aligned and some initial samples must be discarded from one or +more inputs. + +The function that creates a sound is @code(snd_make_)@i(name). This is +where state allocation and initialization takes place. The proper fetch +function is selected based on the sample rates and scale factors of the +sound arguments, and a @code(sound_type) is returned. + +Since Nyquist is a functional language, sound operations are not normally allowed to +modify their arguments through side effects, but even reading samples from a +@code(sound_type) causes side effects. To hide these from the Nyquist +programmer, @code(sound_type) arguments are first copied (this only copies a small structure. The samples themselves are on a shared list). The function +@code(snd_)@i(name) performs the necessary copies and calls +@code(snd_make_)@i(name). It is the @code(snd_)@i(name) function that is +called by XLisp. The XLisp name for the function is @code(SND-)@i(NAME). +Notice that the underscore in C is converted to a dash in XLisp. Also, +XLisp converts identifiers to upper case when they are read, so normally, +you would type @code(snd)-@i(name) to call the function. + +@section(Scalar Arguments) +If you want the option of passing either a number (scalar) or a signal as +one of the arguments, you have two choices, neither of which is automated. +Choice 1 is to coerce the constant into a signal from within XLisp. The +naming convention would be to @code(DEFUN) a new function named +@i(NAME) or @code(S-)@i(NAME) for ordinary use. The @i(NAME) function tests +the arguments using XLisp functions such as @code(TYPE-OF), @code(NUMBERP), +and @code(SOUNDP). Any number is converted to a @code(SOUND), e.g. using +@code(CONST). Then @code(SND-)@i(NAME) is called with all sound arguments. +The disadvantage of this scheme is that scalars are expanded into a sample +stream, which is slower than having a special inner loop where the scalar +is simply kept in a register, avoiding loads, stores, and addressing +overhead. + +Choice 2 is to generate a different sound operator for each case. The +naming convention here is to append a string of c's and v's, indicating +constant (scalar) or variable (signal) inputs. For example, the +@code(reson) operator comes in four variations: @code(reson), +@code(resoncv), @code(resonvc), and @code(resonvv). The @code(resonvc) +version implements a resonating filter with a variable center frequency (a +sound type) and a constant bandwidth (a @code(FLONUM)). The @code(RESON) +function in Nyquist is an ordinary Lisp function that checks types and calls +one of @code(SND-RESON), @code(SND-RESONCV), @code(SND-RESONVC), or +@code(SND-RESONVV). + +Since each of these @code(SND-) functions performs further selection of +implementation based on sample rates and the need for scaling, there are 25 +different functions for computing RESON! So far, however, Nyquist is +smaller than Common Lisp and it's about half the size of Microsoft Word. +Hopefully, exponential growth in memory density will outpace linear (as a +function of programming effort) growth of Nyquist. + diff --git a/docsrc/nyquist/nyquistman-sal-only.mss b/docsrc/nyquist/nyquistman-sal-only.mss new file mode 100644 index 0000000..de31218 --- /dev/null +++ b/docsrc/nyquist/nyquistman-sal-only.mss @@ -0,0 +1,8113 @@ +@device(mac52postscript) +@make(manual) +@libraryfile(mathematics10) +@libraryfile(picture) +@libraryfile(multilevelindex) +@style(font timesroman) +@style(fontscale 11) +@commandstring(dash @Y[M]) +@commandstring(subtract @Y[N]) +@commandstring(itemsep @Y[M]) +@Modify(indexenv, above=2 lines, leftmargin 8, columns=3, boxed) +@define(prg=i) +@define(detail=text, size 9, spacing 1.2, indent 0) +@define(code, FaceCode T, size 11) +@comment{codef is used to define a lisp function or variable -- + a processor uses this to extract completion hint info for jNyqIDE.} +@define(codef, FaceCode T, size 11) +@comment{pragma(define) is used to mark a term's point of definition -- + I tried to define(defn=index), but that didn't work in Scribe, + so the approach now is to mark definitions. In s2h, the + define pragma sets a flag that the NEXT index term is a definition. + The s2h.lsp processor uses this to map terms defined within codef + (which go into the completion list) to URLs for the help system.} +@define(smallcode, FaceCode T, size 8, spacing 0.8) @comment(was 10) +@define(rbdisplay = display, group) +@define(fndefs = description, leftmargin 0.5in, indent -0.5in) +@define(fdescription = text, leftmargin +0.5in, indent -0.5in, spread 1) +@define(pdescription = text, leftmargin +0.5in, indent -0.5in, spread 0) +@define(fgroup = text, indent -0.5in, spread 0) +@textform(html = []) +@textform(htmltitle = []) +@textform(pragma = []) +@use(bibliography = "../bib/music.bib") +@style(references ClosedAlphabetic) +@counter(dummy-counter) +@modify(FigureCounter,Within=dummy-counter, + Numbered <@@b[Figure@@ @1:@@ @@ ]@@$>, + Referenced "@1",Init 0) +@modify(TableCounter,Within=dummy-counter, + Numbered <@@b[Table@@ @1:@@ @@ ]@@$>, + Referenced "@1",Init 0) +@pageheading(left "", center "@value(page)", right "") +@include(../template/filcap.mss) + +@begin(comment) +@begin(figure) +@blankspace(0.3 inches) @comment(scribe doesn't leave enough space) +@center(@graphic((height = *** in, width = *** in, magnify = ***, + postscript = "***.ps")) +@fillcaption(***) +@tag(***) +@end(figure) +@end(comment) + +@html(Nyquist Reference Manual) +@htmltitle(Nyquist Reference Manual) +@begin(titlepage) +@begin(titlebox) +@blankspace(0.5 inch) +@majorheading(Nyquist Reference Manual) +@b(Version 3.04) +@blankspace(0.3 inch) +@b(Copyright 2011 by Roger B. Dannenberg) +@value(date) +@end(titlebox) +@pragma(startscribe) +@center(Carnegie Mellon University) +@center(School of Computer Science) +@center(Pittsburgh, PA 15213, U.S.A.) +@pragma(endscribe) +@html(
Carnegie Mellon University
+School of Computer Science
+Pittsburgh, PA 15213, U.S.A.
) +@blankspace(1 inch) +@end(titlepage) +@pragma(startscribe) +. +@pragma(endscribe) +@newpage +@pageheading(even, left "Page @Value(Page)", right "@c(Nyquist Manual)") +@pageheading(odd, left "@c[@title(chapter)]", right "Page @Value(page)") +@style(pagenumbers="@i") +@set(page=3) +@Unnumbered(Preface) +This manual is a guide for users of Nyquist, a language for composition and +sound synthesis. Nyquist grew out of a series of research projects, notably +the languages Arctic and Canon. Along with Nyquist, these languages promote a +functional style of programming and incorporate time into the language +semantics. + +Please help by noting any errors@Index(errors), omissions@Index(omissions), +or suggestions@Index(suggestions) you may have. You can send your +suggestions to Dannenberg@@CS.CMU.EDU (internet) via computer mail, or by +campus mail to Roger B. Dannenberg, School of Computer Science, or by +ordinary mail to Roger B. Dannenberg, School of Computer Science, Carnegie +Mellon University, 5000 Forbes Ave., Pittsburgh, PA 15213-3890, USA. + +Nyquist is a successor to Fugue, a language originally implemented by Chris +Fraley, and extended by George Polly and Roger Dannenberg. Peter Velikonja +and Dean Rubine were early users, and they proved the value as well as +discovered some early problems of the system. This led to Nyquist, a +reimplementation of Fugue by Roger Dannenberg with help from Joe Newcomer +and Cliff Mercer. Ning Hu ported Zheng (Geoffrey) Hua and Jim Beauchamp's +piano synthesizer to Nyquist and also built NyqIDE, the Nyquist Integrated +Development Environment for Windows. Dave Mowatt contributed the original +version of jNyqIDE, the cross-platform interactive development environment. +Dominic Mazzoni made a special version of Nyquist that runs +within the Audacity audio editor, giving Nyquist a new interface and +introducing Nyquist to many new users. + +Many others have since contributed to Nyquist. +Chris Tchou and Morgan Green worked on the Windows port. Eli Brandt contributed +a number of filters and other synthesis functions. Pedro J. Morales, +Eduardo Reck Miranda, Ann Lewis, and Erich Neuwirth have all contributed +nyquist examples found in the demos folder of the Nyquist distribution. +Philip Yam ported some +synthesis functions from Perry Cook and Gary Scavone's STK to Nyquist. +Pedro Morales ported many more STK instruments to Nyquist. +Dave Borel wrote the Dolby Pro-Logic encoding library and Adam Hartman wrote +stereo and spatialization effects. Stephen Mangiat wrote the MiniMoog +emulator. Phil Light recorded the drum samples and wrote drum +machine software. The Xmusic library, particularly the pattern specification, +was inspired by Rick Taube's Common Music. The functions for generating +probability distributions were implemented by Andreas Pfenning. + +Starting with Version 3, Nyquist supports a version of SAL, providing +an alternative to Lisp syntax. SAL was designed by Rick Taube, and the +SAL implementation in Nyquist is based on Taube's original implementation +as part of his Common Music system. + +The current jNyqIDE includes contributions from many. Chris Yealy and +Derek D'Souza implemented early versions of the envelope editor. Daren +Makuck and Michael Rivera wrote the original equalizer editor. +Priyanka Raghavan implemented the sound browser. + + +Many others have made contributions, offered suggestions, and found bugs. +If you were expecting to find your name here, I apologize for the omission, +and please let me know. + +I also wish to acknowledge support from CMU, Yamaha, and IBM for this work. +@newpage +@blankspace(5 inches) +@pragma(startscribe) +. +@pragma(endscribe) +@newpage +@set(page=1) +@style(pagenumbers="@1") + +@chapter(Introduction and Overview) + +Nyquist is a language for sound synthesis and music composition. Unlike score +languages that tend to deal only with events, or signal processing languages +that tend to deal only with signals and synthesis, Nyquist handles both in a +single integrated system. Nyquist is also flexible and easy to use because it +is based on an interactive Lisp interpreter. + +With Nyquist, you can design instruments by combining functions (much as you +would using the orchestra languages of Music V, cmusic, or Csound). You can +call upon these instruments and generate a sound just by typing a simple +expression. You can combine simple expressions into complex ones to create +a whole composition. + +Nyquist runs under Linux, Apple Mac OS X, Microsoft Windows NT, +2000, XP, and Vista, +and it produces sound files or directly generates audio. +Recent versions have also run on AIX, NeXT, SGI, DEC pmax, and Sun Sparc +machines. (Makefiles for many of these are included, but out-of-date). +Let me know if you have problems with +any of these machines. + +To use Nyquist, you should have a basic knowledge of Lisp. An excellent text +by Touretzky is recommended @cite(Touretzky). Appendix @ref(xlisp-app) is +the reference manual for XLISP, of which Nyquist is a superset. Starting with +Version 3, Nyquist supports a variant of SAL, which is also available in +Common Music. Since there are some differences, one should generally call this +implementation ``Nyquist SAL;'' however, in this manual, I will just call it +``SAL.'' SAL offers most of the capabilities of Lisp, but it uses an Algol-like +syntax that may be more familiar to programmers with experience in Java, C, +Basic, etc. + +@label(install-sec) +@section(Installation) +@index(installation)@index(configure nyquist)@index(setup nyquist) +Nyquist is a C program intended to run under various operating systems including Unix, MacOS, and Windows. +@subsection(Unix Installation) +For Unix systems, Nyquist is distributed as a compressed tar file named @code(nyqsrc3@i(nn).zip), +where @i(nn) is the version number (e.g. v3.01 was +in @code(nyqsrc301.zip)). To +install Nyquist, copy @code(nyqsrc3@i(nn).zip) to the +directory on your machine where you would like to install Nyquist, and type: +@begin(example) +gunzip nyqsrc3@i(nn).zip +cd nyquist +ln -s sys/unix/linux/Makefile Makefile +setenv XLISPPATH `pwd`/runtime:`pwd`/lib +make +@end(example) +The first line creates a @code(nyquist) directory and some subdirectories. The +second line (cd) changes directories to the new nyquist directory. The third line makes a link from the top-level directory to the Makefile for your +system. In place of @code(linux) in @code(sys/unix/linux/Makefile), you should +substitute your system type. Current systems are @code(next), @code(pmax), +@code(rs6k), @code(sgi), @code(linux), and @code(sparc). The @code(setenv) +command tells Nyquist where to search for lisp files to be loaded when a file +is not found in the current directory. The @code(runtime) directory should +always be on your @code(XLISPPATH) when you run Nyquist, so you may want to +set @code(XLISPPATH) in your shell startup file, e.g. @code(.cshrc). +Assuming the make completes successfully, you can run Nyquist as follows: +@begin(example) +./ny +@end(example) +When you get the prompt, you may begin typing expressions such as +the ones in the following ``Examples'' section. + +One you establish that Nyquist (ny) is working from the command line, you should +try using jNyqIDE, the Java-based Nyquist development environment. First, +make @code(jny) executable (do this only once when you install Nyquist): +@begin(example) +chmod +x jny +@end(example) +Then try running jNyqIDE by typing: +@begin(example) +./jny +@end(example) +If the jNyqIDE window does not appear, make sure you have Java installed (if not, +you probably already encountered errors when you ran @code(make)). You can also try recompiling the Java files: +@begin(example) +cd jnyqide +javac *.java +cd .. +@end(example) + +@p(Note:) With Linux and the Macintosh OS X, + jNyqIDE defines the environment passed to Nyquist. If you +set @code(XLISPPATH)@index(XLISPPATH)@index(search path) as shown above, it +will be passed along to Nyquist under jNyqIDE. If not, +a default XLISPPATH will have the @code(lib) and @code(runtime) directories only. +This does not apply to Windows because even though the environment is there, +the Windows version of Nyquist reads the @code(XLISPPATH) from the Registry. + +You can also specify the search path by creating the +file @code(nyquist/xlisppath), which should have colon-separated paths +on a single line of text. This file will override the environment +variable @code(XLISPPATH). + +It is good to have @code(USER) in the environment with your user ID. This string +is used to construct some file names. jNyqIDE will look for it in the environment. +You can also specify your user ID using the file @code(nyquist/user), but +if you have a shared installation of Nyquist, this will not be very useful. + +@p(Note:) Nyquist looks for the file @code(init.lsp) in the current +directory. If you look in the @code(init.lsp) in @code(runtime), you +will notice two things. First, @code(init.lsp) loads @code(nyquist.lsp) +from the Nyquist directory, and second, @code(init.lsp) loads @code(system.lsp) +which in turn defines the macro +@code(play). You may have to modify @code(system.lsp) to invoke +the right programs on your machine. + +@subsection(Win32 Installation) +The Win32 version of Nyquist is packaged as a compiled (runtime) system in an + executable installer. A source version is also available (the same source +download is for Win32, Mac OS X, and Linux). The source version is +intended for developers who +want to recompile Nyquist. +The contents of the source archive are extracted to the @code(C:\nyquist) +directory, +but you can put it anywhere you like. You can then open the workspace file, +nyquist.sln, using Microsoft +Visual C++. You can build and run the command line version of Nyquist +from within Visual C++. There is a batch file, @code(comp-ide.bat), for +bulding the Nyquist IDE. This requires the Java SDK from Sun Microsystems. + +The runtime version contain everything you need to run Nyquist, including the executable, +examples, and documentation, packaged as an executable installer program. +After executing the installer, just find Nyquist in your Start menu to run it. +You may begin typing expressions such as the ones in the following ``Examples'' section. + +@begin(comment) THIS STUFF IS OUT OF DATE +The Win32 version of Nyquist is packaged as n three versions: the source version +and two runtime versions. The source version is a superset of the runtime +version intended for developers who +want to recompile Nyquist. The source version exists as a @code(.zip) file, +so you need a utility like WinZip to unpack them. The +URL @code(http://www.winzip.com/) has information on this product. Typically, +the contents of the zip file are extracted to the @code(C:\nyquist) directory, +but you can put it anywhere you like. You can then open the workspace file, +nyquist.sln, using Microsoft +Visual C++. You can build and run the command line and the NyqWin versions of Nyquist +from within Visual C++. + +The runtime versions contain everything you need to run Nyquist, including the executable, +examples, and documentation. Each runtime version is packaged as an executable installer program. +I recommend @code(setupnyqiderun2xx.exe) (``2xx'' refers to the current version +number), a graphical interface written in +Java that runs nyquist.exe as +a separate process. This IDE has a simple lisp editor built in. Alternatively, +you can install @code(setupnyqwinrun2xx.exe), a different graphical +interface written in C++. Just copy the installer you want +to your system and run it. Then find Nyquist in your Start menu to run it. +You may begin typing expressions such as the ones in the following ``Examples'' section. +@end(comment) +@p(Optional:)@index(Registry)@index(xlisppath)@index(search path) Nyquist needs to know where to find the standard runtime files. The location of runtime files must be stored in the Registry. +The installers create a registry entry, but if +you move Nyquist or deal with different versions, you can edit the Registry manually as follows: +@begin(itemize) +Run the Registry editor. Under Windows NT, run @code(C:\WINNT\system32\regedt32.exe). Under Windows95, run @code(C:\WINDOWS\regedit.exe). + +Find and highlight the @code(SOFTWARE) key under @code(HKEY_LOCAL_MACHINE). + +Choose @code(Add key ...) from the @code(Edit) menu, type @code(CMU), and click the @code(OK) button. + +Highlight the new @code(CMU) key. + +Choose @code(Add key ...) from the @code(Edit) menu, type @code(Nyquist), and click the @code(OK) button. (Note that @code(CMU) and @code(Nyquist) are case sensitive.) + +Highlight the new @code(Nyquist) key. + +Choose @code(Add value ...) from the @code(Edit) menu, type @code(XLISPPATH), and click the @code(OK) button. (Under WinXP the menu item is @code(Edit:New:String Value), after which you need to select the new string name that appears in the right panel, select @code(Edit:Rename), and type @code(XLISPPATH).) + +In the String Edit box (select the @code(Edit:Modify) menu item in WinXP), +type a list of paths you want Nyquist to search for lisp files. For example, if you installed Nyquist as @code(C:\nyquist), then type: +@begin(example) +C:\nyquist\runtime,C:\nyquist\lib +@end(example) +The paths should be separated by a comma or semicolon and no space. The @code(runtime) path is essential, and the @code(lib) path may become essential in a future release. You can also add paths to personal libraries of Lisp and Nyquist code. + +Click the @code(OK) button of the string box and exit from the Registry Editor application. +@end(itemize) + +@paragraph(What if Nyquist functions are undefined?) +If you do not have administrative privileges for your machine, the installer may fail to set up the Registry entry that Nyquist uses to find initialization files. In this case, Nyquist will run a lisp interpreter, but many Nyquist functions will not be defined. If you can log in as administrator, do it and reinstall Nyquist. If you do not have permission, you can still run Nyquist as follows: + +Create a file named @code(init.lsp) in the same directory as Nyquist.exe (the default location is @code(C:\Program Files\Nyquist), but you may have installed it in some other location.) Put the following text in @code(init.lsp): +@begin(example) +@begin(smallcode) +(setf *search-path* "C:/Program Files/Nyquist/runtime,C:/Program Files/Nyquist/lib") +(load "C:/Program Files/Nyquist/runtime/init.lsp") +@end(smallcode) +@end(example) +@p(Note:) in the three places where you see @code(C:/Program Files/Nyquist), insert the full path where Nyquist is actually installed. Use forward slashes (@code(/)) rather than back slashes (@code(\)) to separate directories. For example, if Nyquist is installed at @code(D:\rbd\nyquist), then @code(init.lsp) should contain: +@begin(example) +@begin(smallcode) +(setf *search-path* "D:/rbd/nyquist/runtime,D:/rbd/nyquist/lib") +(load "d:/rbd/nyquist/runtime/init.lsp") +@end(smallcode) +@end(example) +The variable @code(*search-path*), if defined, is used in place of the registry to determine search paths for files. + +@paragraph(SystemRoot) +@index(SystemRoot) +(Ignore this paragraph if you are not planning to use Open Sound Control under Windows.) +If Nyquist prints an error message and quits when you enable Open Sound Control (using @code(osc-enable)), check to see if you have an environment variable @code(SystemRoot), e.g. type @code(set) to a command prompt and look for the value of @code(SystemRoot). The normal value is @code(C:\windows). If the value is something else, you should put the environment entry, for example: +@begin(example) +SystemRoot="D:\windows" +@end(example) +into a file named @code(systemroot) (no extension). Put this file in your @code(nyquist) directory. When you run @code(jNyqIDE), it will look for this file and pass the contents as an environment variable to Nyquist. The Nyquist process needs this to open a UDP socket, which is needed for Open Sound Control. + +@paragraph(The "java is not recognized" Error) +Sometimes, Nyquist will run directly from the installer, but then it will not start from the Windows Start menu. You can try running the + @code(nyquist/jnyqide.bat) program from a Windows shell. If that fails, and you see an error similar to "java is not recognized as in internal or external command error", the problem may be that paths are not set up properly to allow the Windows shell to find java. Right click on ``My Computer'' on the Windows +desktop and select ``Properties.'' Under the ``Advanced'' tap, press the ``Environment Variables'' button, and look for PATH under ``System Variables.'' Make sure the Java bin directory is on the path. If it is not, you will have to find your installation of Java and add the appropriate directory to the PATH variable, e.g. ``C:\Program Files\Java\jdk1.6.0\bin.'' + +@subsection(MacOS X Installation) +The OS X version of Nyquist is very similar to the Linux version, but it +is developed using Xcode, Apple's programming environment. With a little +work, you can use the Linux installation instructions to compile Nyquist, +but it might be simpler to just open the Xcode project that is included +in the Nyquist sources. + +You can also download a pre-compiled version of Nyquist for the Mac. +Just download @code(nyqosx2xx.tgz) to the desktop and open it to +extract the folder nyqosx2xx. (Again, "2xx" refers to the current +version number, e.g. v2.31 would be named with "231".) Open the folder +to find a Mac Application named jNyqIDE and a directory named +nyquist/doc. Documentation is in the nyquist/doc directory. + +The file jNyqIDE.app/Contents/Resources/Java/ny +is the command line executable (if you should need it). To run from the +command line, you will need to set the XLISPPATH environment variable as +with Linux. On the topic of the @code(XLISPPATH), note that this variable is +set by jNyqIDE when running with that application, overriding any other +value. You can extend the search path by creating the file @code(xlisppath) +in the same directory as the nyquist executable @code(ny). The +@code(xlisppath) file should have colon-separated paths +on a single line of text. + +@section(Using jNyqIDE)@index(jNyqIDE)@index(IDE)@index(Integrated Development Environment) +The program named jNyqIDE is an ``integrated development environment'' for Nyquist. When you run jNyqIDE, it starts the Nyquist program and displays all Nyquist output in a window. jNyqIDE helps you by providing a Lisp and SAL editor, hints for command completion and function parameters, some graphical interfaces for editing envelopes and graphical equalizers, and a panel of buttons for common operations. A more complete description of jNyqIDE is in Chapter @ref(jnyqide-chapter). + +For now, all you really need to know is that you can enter Nyquist commands by typing into the upper left window. When you type return, the expression you typed is sent to Nyquist, and the results appear in the window below. You can edit files by clicking on the New File or Open File buttons. After editing some text, you can load the text into Nyquist by clicking the Load button. jNyqIDE always saves the file first; then it tells Nyquist to load the file. You will be prompted for a file name the first time you load a new file. + +@section(Using SAL) +SAL mode means that Nyquist reads and evaluates SAL commands rather than Lisp. The SAL mode prompt is "@code(SAL> )" while the Lisp mode prompt is "@code(> )". +When Nyquist starts it normally enters SAL mode automatically, but certain errors may exit SAL mode. You can reenter SAL mode by typing the Lisp expression @code[(sal)]. + +In SAL mode, you type commands in the SAL programming language. Nyquist reads the commands, compiles them into Lisp, and evaluates the commands. Commands can be entered manually by typing into the upper left text box in jNyqIDE. + +@section(Helpful Hints) +Under Win95 and Win98, the console sometimes locks up. Activating another window and then reactivating the Nyquist window should unlock the output. +(We suggest you use JNyqIDE, the interactive development environment rather than a console window.) + +You can cut and paste text into Nyquist, but for serious work, you will want to use the Lisp @code(load) command. To save even more time, write a +function to load your working file, e.g. @code[(defun l () (load "myfile.lsp"))]. Then you can type @code[(l)] to (re)load your file. + +Using SAL, you can type +@begin(example) +define function l () load "myfile.lsp" +@end(example) +and then +@begin(example) +exec l() +@end(example) +to (re)load the file. + +The Emacs editor is free GNU software and will help you balance parentheses if you use Lisp mode. In fact, you can run nyquist (without the IDE) as a subprocess to Emacs. A helful discussion is at //http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/examples/emacs/main.html. If you use Emacs, there is also a SAL mode (the file is @code(sal-mode.el)) included with the Common Music distribution, which you can find on the Web at @code(sourceforge.net). + +The jNyqIDE also runs Nyquist as a subprocess and has +built-in Lisp and SAL editors. If your editor does not help you balance parentheses, you may find yourself counting parens and searching for unbalanced +expressions. If you are confused or desperate, try the @code(:print t) +option o fthe @code(load) command. By looking at the expressions printed, +you should be able to tell where the last unbalanced expression starts. +Alternatively, type @code[(file-sexprs)] and type the lisp file name at +the prompt. This function will read and print +expressions from the file, reporting an error when an extra paren or end-of-file is reached unexpectedly. + +@section(Using Lisp) +Lisp mode means that Nyquist reads and evaluates Nyquist expressions in +Lisp syntax. Since Nyquist is build on a Lisp interpreter, this is the +``native'' or machine language of Nyquist, and certain errors and functions +may break out of the SAL interpreter, leaving you with a prompt for a Lisp +expression. Alternatively, you can exit SAL simply by typing @code(exit) to +get a Lisp prompt (@code(> )). Commands can be entered manually by typing + into the upper left text box in jNyqIDE. + +@section(Examples) +We will begin with some simple Nyquist programs. Throughout the manual, +we will assume SAL mode and give examples in SAL, but it should be +emphasized that all of these examples can be performed using Lisp +syntax. See Section @ref(sal-vs-lisp-section) on the relationship between +SAL and Lisp. + +Detailed explanations of the functions used in these examples will be +presented in later chapters, so at this point, you should just read these +examples to get a sense of how Nyquist is used and what it can do. The +details will come later. Most of these examples can be found in the +file @code(nyquist/demos/examples.sal). Corresponding Lisp syntax +examples are in the file @code(nyquist/demos/examples.lsp). + +Our first example makes and plays a sound:@index(osc)@index(play) +@begin(example) +@i(;; Making a sound.) +play osc(60) ; generate a loud sine wave +@comment{(play (osc 60)) @i(; generate a loud sine wave)} @end(example) +This example is about the simplest way to create a sound with Nyquist. The +@code(osc) function generates a sound using a table-lookup oscillator. +There are a number of optional parameters, but the default is to compute a +sinusoid with an amplitude of 1.0. The parameter @code(60) designates a +pitch of middle C. (Pitch specification will be described in greater detail +later.) The result of the @code(osc) function is a sound. To hear a sound, +you must use the @code(play) command, which plays the file through the machine's D/A converters. It also writes a soundfile in case the computation cannot keep up with real time. You can then (re)play the file by typing: +@begin(example) +exec r() +@end(example) +This @code[(r)] function is a general way to ``replay'' the last thing written by @code(play). + +Note: when Nyquist plays a sound, it scales the signal by 2@+(15)-1 and (by default) converts to a 16-bit integer format. A signal like @code[(osc 60)], which ranges from +1 to -1, will play as a full-scale 16-bit audio signal. + +@subsection(Waveforms) +@label(waveform-sec) +Our next example will be presented in several steps. The goal is to create a +sound using a +wavetable consisting of several harmonics as opposed to a simple sinusoid. +In order to build a table, we will use a function that computes a single +harmonic and add harmonics to form a wavetable. An oscillator +will be used to compute the harmonics. + +@begin(comment) +Ordinarily, Nyquist programs are sample-rate independent, and time (in +seconds) is used rather than sample numbers to indicate regions of signals. +Since we want a wave-table with a certain integer number of samples, we need +to do some extra calculations to convert from time to samples. The +@code(build-harmonic) function (see Figure @ref(build-harmonic-fig)) +produces a signal with @code(n) periods in the course of 2048 samples using +the @code(snd-sine) function. + +@begin(figure) +@begin(example) +(defun build-harmonic (n tablesize) (snd-sine 0 n tablesize 1)) +@end(example) +@fillcaption(@code(build-harmonic) uses a low-level function, +@code(snd-sine), to construct a harmonic. The function parameters denote: +``compute a sinusoid starting at time zero, with frequency @i(n), a sample +rate of @i(tablesize) samples per second and a duration of 1 second.'' This signal +becomes a periodic waveform to be resampled by a table lookup oscillator, so +the choice of sample rate and duration is a matter of convenience. +@tag(build-harmonic-fig) +@end(figure) +@end(comment) + +The function +@code(mkwave@index(mkwave)) calls upon +@code(build-harmonic@index(build-harmonic)) to generate a total of four +harmonics with amplitudes 0.5, 0.25, 0.125, and 0.0625. +These are scaled and added (using @code(+@index(sim))) to +create a waveform which is bound temporarily to @code(*table*). + +A complete Nyquist waveform is a list consisting of a sound, a pitch, + and @code(T), indicating a periodic waveform. The pitch gives the +nominal pitch of the sound. (This is implicit in a single cycle wave +table, but a sampled sound may have many periods of the fundamental.) +Pitch is expressed in half-steps, where middle C is 60 steps, as in MIDI +pitch numbers. +The list of sound, pitch, and @code(T) is formed in the last line of +@code(mkwave): since @code(build-harmonic) computes signals with a duration +of one second, the fundamental is 1 Hz, and the @code(hz-to-step) function +converts to pitch (in units of steps) as required. + +@begin(example)@label(build-harmonic-example) +define function mkwave() + begin + set *table* = 0.5 * build-harmonic(1.0, 2048) + + 0.25 * build-harmonic(2.0, 2048) + + 0.125 * build-harmonic(3.0, 2048) + + 0.0625 * build-harmonic(4.0, 2048) + set *table* = list(*table*, hz-to-step(1.0), #t) + end +@end(example) + +Now that we have defined a function, the last step of this example is to +build the wave. The following code calls +@code(mkwave) the first time the code is executed (loaded from a file). The second time, the variable @code(*mkwave*) will be true, so @code(mkwave) will not be invoked: +@begin(example) +if ! fboundp(quote(*mkwave*)) then + begin + exec mkwave() + set *mkwave* = #t + end +@end(example) + +@subsection(Wavetables)@index(wavetables)@index(waveforms)@index(triangle wave)@index(sawtooth wave) +When Nyquist starts, several waveforms are created and stored in global variables for convenience. They are: @code(*sine-table*), @code(*saw-table*), and @code(*tri-table*), implementing sinusoid, sawtooth, and triangle waves, respectively. The variable @code(*table*) is initialized to @code(*sine-table*), and it is @code(*table*) that forms the default wave table for many Nyquist oscillator behaviors. If you want a proper, band-limited waveform, you should construct it yourself, but if you do not understand this sentence and/or you do not mind a bit of aliasing, give @code(*saw-table*) and @code(*tri-table*) a try. + +Note that in Lisp and SAL, global variables often start and end with asterisks (*). These are not special syntax, they just happen to be legal characters for names, and their use is purely a convention. + +@subsection(Sequences)@index(Sequences) +Finally, we define @code(my-note@index(my-note)) to use the waveform, and play several notes +in a simple score. Note that the function @code(my-note) has only one command +(a @code(return) command), so it is not necessary to use @code(begin) and +@code(end). These are only necessary when the function body consists of a +sequence of statements: +@begin(example) +define function my-note(pitch, dur) + return osc(pitch, dur, *table*) + +play seq(my-note(c4, i), my-note(d4, i), my-note(f4, i), + my-note(g4, i), my-note(d4, q)) + +@end(example) +Here, @code(my-note) is defined to take pitch and duration as parameters; +it calls @code(osc) to do the work of generating a waveform, using +@code(*table*) as a wave table. + +The @code(seq) function is used to invoke a sequence of behaviors. Each +note is started at the time the previous note finishes. The parameters to +@code(my-note) are predefined in Nyquist: @code(c4) is middle C, @code(i) (for +eIghth note) is 0.5, and @code(q) (for Quarter note) is 1.0. See Section +@ref(constants-sec) for a complete description. The result is the sum of +all the computed sounds. + +Sequences can also be constructed using the @code(at) transformation to +specify time offsets. See +@code(sequence_example.htm)@index(sequence_example.htm)@index(score, musical) +@code(demos, sequence) for more examples and explanation. + +@subsection(Envelopes)@index(Envelopes) +The next example will illustrate the use of envelopes. In Nyquist, +envelopes are just ordinary sounds (although they normally have a low sample +rate). An envelope@index(envelope) is applied to another sound by +multiplication using the @code(mult@index(mult)) function. The code shows +the definition of @code(env-note@index(env-note)), defined in terms of the +@code(note) function in the previous example. In @code(env-note), a 4-phase +envelope is generated using the @code(env@index(env)) function, which is +illustrated in Figure @ref(env-fig). + +@begin(figure) +@center(@graphic((height = 2 in, width = 3.75 in, magnify = 1, + postscript = "envfig.ps")) +@html(

) +@fillcaption(An envelope generated by the @code(env) function.) +@tag(env-fig) +@end(figure) + +@begin(Example) +@i[; env-note produces an enveloped note. The duration +; defaults to 1.0, but stretch can be used to change +; the duration. +; Uses my-note, defined above. +;] +define function env-note(p) + return my-note(p, 1.0) * + env(0.05, 0.1, 0.5, 1.0, 0.5, 0.4) + +@i[; try it out: +;] +play env-note(c4) +@end(example) +While this example shows a smooth envelope multiplied by an audio signal, +you can also multiply audio signals to achieve +what is often called @i(ring modulation)@index(ring modulation). See +the code and description in +@code(demos/scratch_tutorial.htm)@index(demos, ring modulation) for an +interesting use of ring modulation to create ``scratch'' sounds. + +In the next example, The @i(stretch) operator (@code(~))@index(stretch) +is used to modify durations: +@begin(example) +@i[; now use stretch to play different durations +;] +play seq(seq(env-note(c4), env-note(d4)) ~ 0.25, + seq(env-note(f4), env-note(g4)) ~ 0.5, + env-note(c4)) +@end(example) + +In addition to @i(stretch), there are a number of transformations supported + by Nyquist, +and transformations of abstract behaviors is perhaps @i(the) fundamental +idea behind Nyquist. Chapter @ref(behavioral-abstraction-sec) is devoted to +explaining this concept, and further elaboration can be found elsewhere +@cite(icmcfugue). + +@subsection(Piece-wise Linear Functions) +It is often convenient to construct signals in Nyquist using a list of +(time, value) breakpoints which are linearly interpolated to form a smooth +signal. Envelopes created by @code(env) are a special case of the more +general piece-wise linear functions created by @code(pwl). Since @code(pwl) +is used in some examples later on, we will take a look at @code(pwl) +now. The @code(pwl) function takes a list of parameters which denote (time, +value) pairs. There is an implicit initial (time, value) pair of (0, 0), +and an implicit final value of 0. There should always be an odd number of +parameters, since the final value (but not the final time) is implicit. +Here are some examples: +@begin(Example) +@i[; symetric rise to 10 (at time 1) and fall back to 0 (at time 2): +;] +pwl(1, 10, 2) + +@i[; a square pulse of height 10 and duration 5. +; Note that the first pair (0, 10) overrides the default initial +; point of (0, 0). Also, there are two points specified at time 5: +; (5, 10) and (5, 0). (The last 0 is implicit). The conflict is +; automatically resolved by pushing the (5, 10) breakpoint back to +; the previous sample, so the actual time will be 5 - 1/sr, where +; sr is the sample rate. +;] +pwl(0, 10, 5, 10, 5) + +@i[; a constant function with the value zero over the time interval +; 0 to 3.5. This is a very degenerate form of pwl. Recall that there +; is an implicit initial point at (0, 0) and a final implicit value of +; 0, so this is really specifying two breakpoints: (0, 0) and (3.5, 0): +;] +pwl(3.5) + +@i[; a linear ramp from 0 to 10 and duration 1. +; Note the ramp returns to zero at time 1. As with the square pulse +; above, the breakpoint (1, 10) is pushed back to the previous sample. +;] +pwl(1, 10, 1) + +@i[; If you really want a linear ramp to reach its final value at the +; specified time, you need to make a signal that is one sample longer. +; The RAMP function does this: +;] +ramp(10) @i[; ramp from 0 to 10 with duration 1 + one sample period +; +; RAMP is based on PWL; it is defined in @p(nyquist.lsp). +;] +@end(example) + +@section(Predefined Constants) +@label(constants-sec) +For convenience and readability, Nyquist pre-defines some constants, mostly +based on the notation of the Adagio score language, as follows: +@begin(itemize) +@b(Dynamics) +Note: these dynamics values are subject to change. +@begin(display) +@t(lppp@index(lppp)) = -12.0 (dB) +@t(lpp@index(lpp)) = -9.0 +@t(lp@index(lp)) = -6.0 +@t(lmp@index(lmp)) = -3.0 +@t(lmf@index(lmf)) = 3.0 +@t(lf@index(lf)) = 6.0 +@t(lff@index(lff)) = 9.0 +@t(lfff@index(lfff)) = 12.0 +@t(dB0@index(dB0)) = 1.00 +@t(dB1@index(dB1)) = 1.122 +@t(dB10@index(dB10)) = 3.1623 +@end(display) + +@b(Durations@index(duration notation)) +@begin(display) +@t(s@index(s)) = Sixteenth@index(Sixteenth note) = 0.25 +@t(i@index(i)) = eIghth@index(eIghth note) = 0.5 +@t(q@index(q)) = Quarter@index(quarter note) = 1.0 +@t(h@index(h)) = Half@index(half note) = 2.0 +@t(w@index(w)) = Whole@index(whole note) = 4.0 +@t(sd@index(sd), id@index(id), qd@index(qd), hd@index(hd), wd@index(wd)) = dotted durations@index(dotted durations). +@t(st@index(st), it@index(it), qt@index(qt), ht@index(ht), wt@index(wt)) = triplet@index(triplet durations) durations. +@end(display) + +@b(Pitches@index(pitch notation)) +Pitches are based on an A4 of 440Hz. To achieve a different tuning, +set @code(*A4-Hertz*) to the desired frequency for A4, and call +@code[(set-pitch-names)]. This will recompute the names listed below with a +different tuning. In all cases, the pitch value 69.0 corresponds exactly to +440Hz, but fractional values are allowed, so for example, if you set +@code(*A4-Hertz*) to 444 (Hz), then the symbol @code(A4) will be bound to +69.1567, and @code(C4) (middle C), which is normally 60.0, will be 60.1567. +@begin(display) +@t(c0) = 12.0 +@t(cs0, df0) = 13.0 +@t(d0) = 14.0 +@t(ds0, ef0) = 15.0 +@t(e0) = 16.0 +@t(f0) = 17.0 +@t(fs0, gf0) = 18.0 +@t(g0) = 19.0 +@t(gs0, af0) = 20.0 +@t(a0) = 21.0 +@t(as0, bf0) = 22.0 +@t(b0) = 23.0 +@t(c1) ... @t(b1) = 24.0 ... 35.0 +@t(c2) ... @t(b2) = 36.0 ... 47.0 +@t(c3) ... @t(b3) = 48.0 ... 59.0 +@t(c4) ... @t(b4) = 60.0 ... 71.0 +@t(c5) ... @t(b5) = 72.0 ... 83.0 +@t(c6) ... @t(b6) = 84.0 ... 95.0 +@t(c7) ... @t(b7) = 96.0 ... 107.0 +@t(c8) ... @t(b8) = 108.0 ... 119.0 +@end(display) + +@b(Miscellaneous) +@begin(display) +@codef(ny:all)@pragma(defn)@index(ny:all) = ``all the samples'' (i.e. a big number) = 1000000000 +@end(display) +@end(itemize) + +@section(More Examples) +More examples can be found in the directory @code(demos), part of the standard +Nyquist release. In this directory, you will find the following and more: +@begin(itemize) +Gong sounds by additive synthesis@index(additive synthesis, gongs) +(@code(demos/pmorales/b1.lsp) and @code(demos/mateos/gong.lsp)@index(Gong sounds)@index(demos, gong sound) + +Risset's spectral analysis of a chord +(@code(demos/pmorales/b2.lsp))@index(Risset)@index(demos, spectral analysis of a chord) + +Bell sounds +(@code(demos/pmorales/b3.lsp), @code(demos/pmorales/e2.lsp), @code(demos/pmorales/partial.lsp), and @code(demos/mateos/bell.lsp))@index(demos, bell sound)@index(bell sound) + +Drum sounds by Risset +(@code(demos/pmorales/b8.lsp)@index(demos, drum sound)@index(drum sound) + +Shepard tones (@code(demos/shepard.lsp) and @code(demos/pmorales/b9.lsp))@index(Shepard tones)@index(endless tones) + +Random signals (@code(demos/pmorales/c1.lsp)) + +Buzz with formant filters +(@code(demos/pmorales/buzz.lsp)@index(vocal sound)@index(demos, formants) + +Computing samples directly in Lisp (using Karplus-Strong and physical modelling +as examples) +(@code(demos/pmorales/d1.lsp)@index(demos, sample-by-sample)@index(DSP in Lisp)@index(Lisp DSP)@index(Karplus-Strong synthesis)@index(physical model)@index(flute sound) + +FM Synthesis examples, including bell@index(bell sound), wood drum@index(wood drum sound), +brass sounds@index(brass sound), tuba sound @index(tuba) (@code(demos/mateos/tuba.lsp) and clarinet sounds@index(clarinet sound) (@code(demos/pmorales/e2.lsp)@index(demos, FM synthesis) + +Rhythmic patterns (@code(demos/rhythm_tutorial.htm)@index(demos, rhythmic pattern) + +Drum Samples and Drum Machine (@code(demos/plight/drum.lsp)@index(demos, drum machine)@index(drum samples)@index(drum machine). +@end(itemize) + +@chapter(The jNyqIDE Program) +@label(jnyqide-chapter) +The jNyqIDE program combines many helpful functions and interfaces to help you get the most out of Nyquist. jNyqIDE is implemented in Java, and you will need the Java runtime system or development system installed on your computer to use jNyqIDE. The best way to learn about jNyqIDE is to just use it. This chapter introduces some of the less obvious features. If you are confused by something and you do not find the information you need here, please contact the author. + +@section(jNyqIDE Overview) +The jNyqIDE runs the command-line version of Nyquist as a subtask, so everything that works in Nyquist should work when using the jNyqIDE and vice-versa. Input to Nyquist is usually entered in the top left window of the jNyqIDE. When you type return, if the expression or statement appears to be complete, the expression you typed is sent to Nyquist. Output from Nyquist appears in a window below. You cannot type into or edit the output window text. + +The normal way to use the jNyqIDE is to create or open one or more files. You edit these files and then click the Load button. To load a file, jNyqIDE saves the file, sets the current directory of Nyquist to that of the file, then issues a @code(load) command to Nyquist. In this case and several others, you may notice that jNyqIDE sends expressions to Nyquist automatically for evaluation. You can always see the commands and their results in the output window. + +Notice that when you load a selected file window, jNyqIDE uses @code(setdir) to change Nyquist's current directory. This helps to keep the two programs in sync. Normally, you should keep all the files of a project in the same directory and avoid manually changing Nyquist's current directory (i.e. avoid calling @code(setdir) in your code). + +Arranging windows in the jNyqIDE can be time-consuming, and depending on the +operating system, it is possible for a window to get into a position where you +cannot drag it to a new position. The Window:Tile menu command can be used +to automatically lay out windows in a rational way. There is a preference +setting to determine the height of the completion list relative to the height of the output +window. + +@section(The Button Bar) +@index(button bar) +There are a number of buttons with frequently-used operations. These are: +@begin(itemize) +Info @itemsep @index(info button)Print information about Nyquist memory +utilization, including +the number of free cons cells, the number of garbage collections, +the total number of cons cells, the total amount of sample buffer memory, +and the amount of memory in free sample buffers. + +Break @itemsep @index(break button)Send a break character to XLISP. This +can be used to enter the debugger (the break loop) while a program is +running. Resume by typing @code[(co)]. + +SAL/Lisp @itemsep @index(SAL button)@index(Lisp button)Switch modes. +The button names the mode (SAL or Lisp) you will switch to, not the +current mode. For example, if you are in Lisp mode and want to type +a SAL command, click the SAL button first. + +Top @itemsep @index(top button)Enters @code[(top)] into Nyquist. +If the XLISP prompt is @code(1>) or +some other integer followed by ``@code(>)'', clicking the Top button +will exit the debug loop and return to the top-level prompt. + +Replay @itemsep @index(replay button)Enters @code[(r)] into Nyquist. +This command replays the last computed sound. + +F2-F12 @itemsep @index(Fn button)Enters @code[(f2)] etc. into Nyquist. +These commands are not built-in, and allow users to define their own +custom actions. + +Browse @itemsep @index(browse button)Equivalent to the Window:Browse +menu item. (See Section @ref(browser).) + +EQ @itemsep @index(eq button)Equivalent to the Window:EQ menu item. +(See Section @ref(eq-window-sec).) + +EnvEdit @itemsep @index(envedit button)Equivalent to the Window:Envelope Edit +menu item. (See Section @ref(envelope-editor-sec).) + +NewFile @itemsep @index(newfile button)Equivalent to the File:New menu +item. Opens a new file editing window for creating and +loading a Lisp or SAL program file. + +OpenFile @itemsep @index(openfile button)Equivalent to the File:Open menu +item. Opens an existing Lisp or SAL program file for editing and loading. + +SaveFile @itemsep @index(savefile button)Equivalent to the File:Save menu +item (found on the editing window's menu bar). Saves the contents +of an editing window to its associated file. + +Load @itemsep @index(load button)Equivalent to the File:Load menu +item (found on the editing window's menu bar). Performs a Save operation, +then sends a command to Nyquist that loads the file as a program. + +Mark @itemsep @index(mark button)Sends a Control-A to Nyquist. While +playing a sound, this displays and records the approximate time in the +audio stream. (See Section @ref(play-sec) for more detail.) + +@end(itemize) + +@section(Command Completion) +To help with programming, jNyqIDE maintains a command-completion window. +As you type the first letters of function names, jNyqIDE lists matching +functions and their parameters in the Completion List window. If you click +on an entry in this window, the displayed expression will replace the +incompletely typed function name. A preference allows you to match initial +letters or any substring of the complete function name. This is controlled +by the ``Use full search for code completion'' preference. + +In addition, if you right click (or under Mac OS X, hold down the Alt/Option +key and click) on an entry, jNyqIDE will display documentation for the function. +Documentation can come from a local copy or from the online copy (determined +by the ``Use online manual instead of local copy'' preference). Documentation +can be displayed within the jNyqIDE window or in an external browser (determined +by the ``Use window in jNyqIDE for help browser'' preference.) Currently, the +external browser option does not seem to locate documentation properly, but +this should be fixed in the future. + +@section(Browser) +@label(browser) +@index(browser, jnyqide)@index(sound browser, jnyqide) +If you click on the Browse button or use the Window:Browse menu command, +jNyqIDE will display a browser window that is pre-loaded with a number of + Nyquist commands to create sounds. You can adjust parameters, audition +the sounds, and capture the expression that creates the sound. In many +cases, the expression checks to see if necessary functions are defined, +loading files if necessary before playing the sound. If you want to use +a sound in your own program, you can often simplify things by explicitly +loading the required file just once at the beginning of your file. + +Since Nyquist now supports a mix of Lisp and SAL, you may find yourself in +the position of having code from the browser in one language while you are +working in the other. The best way to handle this is to put the code for +the sound you want into a function defined in a Lisp (@code(.lsp)) or SAL +(@code(.sal)) file. Load the file (from Lisp, use the @code(sal-load) +command to load a SAL file), and call the function from the language of +your choice. + +@section(Envelope Editor) +@label(envelope-editor-sec) +@index(envelope editor) +@index(editor for envelopes) +@index(graphical envelope editor) +The envelope editor allows you graphically to design and edit piece-wise +linear and exponential envelopes. The editor maintains a list of envelopes +and you select the one to edit or delete using the drop down list in the +Saved Envelopes List area. The current envelope appears in the Graphical +Envelope Editor area. You can click to add or drag points. Alternatively, +you can use the Envelope Points window to select and edit any breakpoint +by typing coordinates. The duration of the envelope is controlled by the +Stop field in the Range area, and the vertical axis is controlled by the +Min and Max fields. + +When you click the Save button, @i(all) envelopes are written to Nyquist. +You can then use the envelope by treating the envelope name as a function. +For example, if you define an envelope named ``fast-attack,'' then you +can create the envelope within a Nyquist SAL program by writing +the expression @code[fast-attack()]. + +These edited envelopes are saved to a file named @code(workspace.lsp) + @index(workspace) in +the current directory. The workspace is Nyquist's mechanism for saving +data of all kinds (see Section @ref(workspaces-sec)). The normal way to +work with workspaces is to (1) load the workspace, i.e. + @code[load "workspace"], as soon as you start Nyquist; (2) invoke +the envelope editor to change values in the workspace; and (3) save the +workspace at any time, especially before you exit jNyqIDE. If you follow +these steps, envelopes will be preserved from session to session, and +the entire collection of envelopes will appear in the editor. Be +sure to make backups of your @code(workspace.lsp) file along with your +other project files. + +The envelope editor can create linear and exponential envelopes. Use the +Type pull-down menu to select the type you want. Envelopes can be created +using default starting and ending values using @code(pwl) or @code(pwe), +or you can specify the initial values using @code(pwlv) or @code(pwev). +The envelope editor uses @code(pwl) or @code(pwe) if no point is explicitly +entered as the initial or final point. To create a @code(pwlv) or @code(pwev) +function, create a point and drag it to the leftmost or rightmost edge +of the graphical editing window. You will see the automatically +generated default starting or ending +point disappear from the graph. + +Exponential envelopes should never decay to zero. If you enter a zero +amplitude, you will see that the envelope remains at zero to the next +breakpoint. To get an exponential decay to ``silence,'' try using an +amplitude of about 0.001 (about -60dB). To enter small values like +this, you can type them into the Amplitude box and click ``Update Point.'' + +The Load button refreshes the editor from data saved in the Nyquist +process. Normally, there is no need to use this because the editor +automatically loads data when you open it. + +@section(Equalizer Editor) +@label(eq-window-sec)@index(equalization editor)@index(graphical equalization) +The Equalizer Editor provides a graphical EQ interface for creating and +adjusting equalizers. Unlike the envelope editor, where you can type +any envelope name, equalizers are named @code(eq-0), @code(eq-1), etc., +and you select the equalizer to edit using a pull-down menu. The @code(Set) +button should be use to record changes. + +@chapter(Behavioral Abstraction)@index(behavioral abstraction) +@label(behavioral-abstraction-sec) +In Nyquist, all functions are subject to +transformations@index(transformations). You can think of transformations as +additional parameters to every function, and functions are free to use these +additional parameters in any way. The set of transformation parameters is +captured in what is referred to as the @i(transformation +environment@index(transformation environment)). (Note that the term +@i(environment) is heavily overloaded in computer science. This is yet +another usage of the term.) + +Behavioral abstraction is the ability of functions to adapt their behavior +to the transformation environment. This environment may contain certain +abstract notions, such as loudness, stretching a sound in time, etc. These +notions will mean different things to different functions. For example, an +oscillator should produce more periods of oscillation in order to stretch +its output. An envelope, on the other hand, might only change the +duration of the sustain portion of the envelope in order to stretch. +Stretching a sample could mean resampling it to change its duration by the +appropriate amount. + +Thus, transformations in Nyquist are not simply operations on signals. For +example, if I want to stretch a note, it does not make sense to compute the +note first and then stretch the signal. Doing so would cause a drop in the +pitch. Instead, a transformation modifies the @i(transformation +environment) in which the note is computed. Think of transformations as +making requests to functions. It is up to the function to carry out the +request. Since the function is always in complete control, it is possible +to perform transformations with ``intelligence;'' that is, the function can +perform an appropriate transformation, such as maintaining the desired pitch +and stretching only the ''sustain'' portion +of an envelope to obtain a longer note. + +@section(The Environment)@index(environment) +@label(environment-sec) +The transformation environment consists of a set of special variables. +These variables should not be read directly and should @i(never) be set +directly by the programmer. Instead, there are functions to read them, and +they are automatically set and restored by +transformation operators, which will be described below. + +The transformation environment consists of the following elements. Although +each element has a ``standard interpretation,'' the designer of an +instrument or the composer of a complex behavior is free to interpret the +environment in any way. For example, a change in @code(*loud*) may change +timbre more than amplitude, and @code(*transpose*) may be ignored by +percussion instruments: + + +@begin(description) + @codef(*warp*@pragma(defn)@index(*warp*))@\Time transformation, including time shift, +time stretch, and continuous time warp. The value of @code[*warp*] is +interpreted as a function from logical (local score) time to physical +(global real) time. Do not access @code(*warp*) directly. Instead, use +@code[local-to-global(@i(t))] to + convert from a logical (local) time to real (global) time. Most often, +you will call @code[local-to-global(0)]. Several transformation operators +operate on @code[*warp*], including @i(at) (@code(@@)), @i(stretch) (@code(~)), +and @code(warp). + + @codef(*loud*@pragma(defn)@index(*loud*))@\Loudness, expressed in decibels. The default +(nominal) loudness is 0.0 dB (no change). Do not access @code(*loud*) +directly. Instead, use @code[get-loud()] to get the current value of +@code(*loud*) and either @code(loud) or @code(loud-abs) to modify it. + + @codef(*transpose*@pragma(defn)@index(*transpose*))@\Pitch transposition, +expressed in +semitones. (Default: 0.0). Do not access @code(*transpose*) directly. +Instead, use @code[get-transpose()] to get the current value of +@code(*transpose*) and either @code(transpose) or @code(transpose-abs) to +modify it. + + @codef(*sustain*@pragma(defn)@index(*sustain*))@\The ``sustain,'' +``articulation,'' ``duty factor,'' or amount by which to +separate or overlap sequential notes. For +example, staccato might be expressed with a @code(*sustain*) of 0.5, while very +legato playing might be expressed with a @code(*sustain*) of 1.2. +Specifically, @code(*sustain*) stretches the duration of notes (sustain) +without affecting the inter-onset time (the rhythm). Do not access +@code(*sustain*) directly. Instead, use @code[get-sustain()] to get the +current value of @code(*sustain*) and either @code(sustain) or +@code(sustain-abs) to modify it. + + @codef(*start*@pragma(defn)@index(*start*))@\Start +time of a clipping region. @i(Note:) +unlike the previous elements of the environment, @code(*start*) has a +precise interpretation: no sound should be generated before @code(*start*). +This is implemented in all the low-level sound functions, so it can +generally be ignored. You can read @code(*start*) directly, but use +@code(extract) or @code(extract-abs) to modify it. @p(Note 2:) Due +to some internal confusion between the specified starting time and +the actual starting time of a signal after clipping, @code(*start*) +is not fully implemented. + + @codef(*stop*@pragma(defn)@index(*stop*))@\Stop time of clipping +region. By analogy to +@code(*start*), no sound should be generated after this time. +@code(*start*) and +@code(*stop*) allow a composer to preview a small section of a work +without computing it from beginning to end. You can read @code(*stop*) +directly, but use @code(extract) or @code(extract-abs) to modify it. + @p(Note:) Due to some internal confusion between the specified +starting time and the actual starting time of a signal after +clipping, @code(*stop*) is not fully implemented. + +@codef(*control-srate*@pragma(defn)@index(*control-srate*))@\Sample +rate of control signals. This environment +element provides the default sample rate for control signals. There is no +formal distinction between a control signal and an audio signal. +You can read @code(*control-srate*) directly, but +use @code(control-srate) or @code(control-srate-abs) to modify it. + + @codef(*sound-srate*@pragma(defn)@index(*sound-srate*))@\Sample +rate of musical sounds. This environment element provides the +default sample rate for musical sounds. You can +read @code(*sound-srate*) directly, but use @code(sound-srate) +or @code(sound-srate-abs) to modify it. + +@end(description) + +@section(Sequential Behavior)@index(sequential behavior) +Previous examples have shown the use of @code(seq), the sequential behavior +operator. We can now explain @code(seq) in terms of transformations. +Consider the simple expression: +@begin(Example) +play seq(my-note(c4, q), my-note(d4, i)) +@end(example) +The idea is to create the first note at time 0, and to start the next +note when the first one finishes. This is all accomplished by manipulating +the environment. In particular, @code[*warp*] is modified so that what is +locally time 0 for the second note is transformed, or warped, to the logical +stop time of the first note. + +One way to understand this in detail is to imagine how it +might be executed: first, @code(*warp*) is set to an initial value that has no +effect on time, and @code[my-note(c4, q)] is evaluated. A sound is returned and +saved. The sound has an ending time, which in this case will be @code(1.0) +because the duration @code(q) is @code(1.0). This ending time, @code(1.0), +is used to construct a new @code[*warp*] that has the effect of shifting +time by 1.0. The second note is evaluated, and will start +at time 1. The sound that is +returned is now added to the first sound to form a composite sound, whose +duration will be @code(2.0). @code(*warp*) is restored to its initial value. + +Notice that the semantics of @code(seq) can be expressed in terms of +transformations. To generalize, the operational rule for @code(seq) is: +evaluate the first behavior according to the current @code(*warp*). +Evaluate each successive behavior with @code(*warp*) modified to shift the +new note's starting time to the ending time of the previous behavior. +Restore @code(*warp*) to its original value and return a sound which is the +sum of the results. + +In the Nyquist implementation, audio samples are only computed when they are +needed, and the second part of the @code(seq) is not evaluated until the +ending time (called the logical stop time) of the first part. It is still +the case that when the second part is evaluated, it will see @code(*warp*) +bound to the ending time of the first part. + +A language detail: Even though Nyquist defers evaluation of the second part of the @code(seq), the expression can reference variables according to ordinary +Lisp/SAL scope rules. This is because the @code(seq) captures the expression in a closure, which retains all of the variable bindings. + +@section(Simultaneous Behavior)@index(Simultaneous Behavior) +Another operator is @code(sim), which invokes multiple behaviors at the same +time. For example, +@begin(example) +play 0.5 * sim(my-note(c4, q), my-note(d4, i)) +@end(example) +will play both notes starting at the same time. + +The operational rule for @code(sim) is: evaluate each behavior at the +current @code(*warp*) and return the sum of the results. (In SAL, the +@code(sim) function applied to sounds is equivalent to adding them +with the infix @code(+) operator. The following section +illustrates two concepts: first, a @i(sound) is not a +@i(behavior), and second, the @code(sim) operator and and the @code(at) +transformation can be used to place sounds in time. + +@section(Sounds vs. Behaviors)@index(Sounds vs. Behaviors) +The following example loads a sound from a file in the current directory and stores it in @code(a-snd): +@begin(example) +@i[; load a sound +;] +set a-snd = s-read(strcat(current-path(), "demo-snd.aiff")) + +@i[; play it +;] +play a-snd +@end(example) + +One +might then be tempted to write the following: +@begin(example) +play seq(a-snd, a-snd) @i(;WRONG!) +@end(example) +Why is this wrong? Recall +that @code(seq) works by modifying @code(*warp*), not by operating on +sounds. So, @code(seq) will proceed by evaluating @code(a-snd) with +different values of @code(*warp*). However, the result of evaluating +@code(a-snd) (a variable) is always the same sound, regardless of the +environment; in this case, the second @code(a-snd) @i(should) start at time +@code(0.0), just like the first. In this case, after the first sound ends, + Nyquist is unable to ``back up'' to time zero, so in fact, this @i(will) +play two sounds in sequence, but that is a result of an implementation +detail rather than correct program execution. In fact, a future version of +Nyquist might (correctly) stop and report an error when it detects that the +second sound in the sequence has a real start time that is before the +requested one. + +How then do we obtain a sequence of two sounds properly? +What we really need here is a +behavior that transforms a given sound according to the current +transformation environment. That job is performed by @code(cue). For +example, the following will behave as expected, producing a sequence of two +sounds: +@begin(example) +play seq(cue(a-snd), cue(a-snd)) +@end(example) +This example is correct because the second expression will shift the sound + stored in @code(a-snd) to start at the end time of the first expression. + +The lesson here is very important: @p(sounds are not behaviors!) Behaviors +are computations that generate sounds according to the transformation +environment. Once a sound has been generated, it can be stored, copied, +added to other sounds, and used in many other operations, but sounds are +@i(not) subject to transformations. To transform a sound, use @code(cue), +@code(sound), or @code(control). The differences between these operations +are discussed later. For now, here is a ``cue sheet'' style score that +plays 4 copies of @code(a-snd): + +@begin(example) +@i[; use sim and at to place sounds in time +;] +play sim(cue(a-snd) @@ 0.0, + cue(a-snd) @@ 0.7, + cue(a-snd) @@ 1.0, + cue(a-snd) @@ 1.2) +@end(example) + +@section(The At Transformation)@index(At Transformation) +The second concept introduced by the previous example is the @code(@@) +operation, which shifts the @code(*warp*) component of the environment. For +example, +@begin(example) +cue(a-snd) @@ 0.7 +@end(example) +can be explained operationally as follows: modify @code[*warp*] by shifting +it by @code(0.7) and evaluate @code[cue(a-snd)]. Return the resulting sound +after restoring @code(*warp*) to its original value. Notice how @code(@@) +is used inside a @code(sim) construct to locate copies of @code(a-snd) in +time. This is the standard way to represent a note-list or a cue-sheet in +Nyquist. + +This also explains why sounds need to be @code(cue)'d in order to be shifted +in time or arranged in sequence. If this were not the case, then @code(sim) +would take all of its parameters (a set of sounds) and line them up to start +at the same time. But @code[cue(a-snd) @@ 0.7] is just a sound, so +@code(sim) would ``undo'' the effect of @code(@@), making all of the sounds +in the previous example start simultaneously, in spite of the @code(@@)! +Since @code(sim) respects the intrinsic starting times of sounds, a special +operation, @code(cue), is needed to create a new sound with a new starting +time. + +@section(The Stretch Transformation)@index(Stretch Transformation) +In addition to At (denoted in SAL by the @code(@@) operator, the Stretch +transformation is very important. It appeared in the introduction, and +it is denoted in SAL by the @code(~) operator (or in LISP by the @code(stretch) +special form). Stretch also operates on the @code(*warp*) component of +the environment. For example, +@begin(example) +osc(c4) ~ 3 +@end(example) +does the following: modify @code(*warp*), scaling the degree of +"stretch" by 3, and evaluate @code[osc(c4)]. The @code(osc) behavior +uses the stretch factor to determime the duration, so it will return +a sound that is 3 seconds long. Restore @code(*warp*) to its original +value. Like At, Stretch only affects behaviors. @code(a-snd ~ 10) is +equivalent to @code(a-snd) because @code(a-snd) is a sound, not a +behavior. Behaviors are functions that compute sounds according to +the environment and return a sound. + +@section(Nested Transformations)@index(Nested Transformations) +Transformations can be combined using nested expressions. For example, +@begin(example) +sim(cue(a-snd), + loud(6.0, cue(a-snd) @@ 3)) +@end(example) +scales the amplitude as well as shifts the second entrance of @code(a-snd). + +Why use @code(loud) instead of simply multiplying @code(a-snd) by some +scale factor? Using @code(loud) gives +the behavior the chance to implement the abstract +property @i(loudness) in an appropriate way, e.g. by including timbral +changes. In this case, the behavior is @code(cue), which implements +@i(loudness) by simple amplitude scaling, so the result is equivalent +to multiplication by @code(db-to-linear(6.0)). + +Transformations can also be applied to groups of behaviors: +@begin(example) +loud(6.0, sim(cue(a-snd) @@ 0.0, + cue(a-snd) @@ 0.7)) +@end(example) + +@section(Defining Behaviors)@index(Defining Behaviors) +Groups of behaviors can be named using @code(define) (we already saw this +in the definitions of @code(my-note) and @code(env-note)). Here is another example +of a behavior definition and its use. The definition has one parameter: +@begin(example) +define function snds(dly) + return sim(cue(a-snd) @@ 0.0, + cue(a-snd) @@ 0.7, + cue(a-snd) @@ 1.0, + cue(a-snd) @@ (1.2 + dly)) + +play snds(0.1) +play loud(0.25, snds(0.3) ~ 0.9) +@end(example) +In the last line, @code(snds) is transformed: the transformations will apply +to the @code(cue) behaviors within @code(snds). The @code(loud) +transformation will scale the sounds by @code(0.25), and the @i(stretch) +(@code(~)) will +apply to the shift (@code(@@)) amounts @code(0.0), @code(0.7), @code(1.0), +and @code[1.2 + dly]. The sounds themselves (copies of @code(a-snd)) will +not be stretched because @code(cue) never stretches sounds. + +Section @ref(transformations-sec) describes the full set of transformations. + +@section(Overriding Default Transformations) +In Nyquist, behaviors are @i(the) important abstraction mechanism. +A behavior represents a class of related functions or sounds. For example, +a behavior can represent a musical note. When a note is stretched, it +usually means that the tone sustains for more oscillations, but if the +``note'' is a drum roll, the note sustains by more repetitions of the +component drum strokes. The concept of sustain is so fundamental that +we do not really think of different note durations as being different +instances of an abstract behavior, but in a music programming language, +we need a way to model these abtract behaviors. As the tone and drum +roll examples show, there is no one right way to ``stretch,'' so the +language must allow users to define exactly what it means to stretch. +By extension, the Nyquist programmer can define how all of the +transformations affect different behaviors. + +To make programming easier, almost all Nyquist sounds are constructed +from primitive behaviors that obey the environment in obvious ways: +Stretch transformations make things longer and At transformations shift +things in time. But sometimes you have to override the default behaviors. +Maybe the attack phase of an envelope should not stretch when the note +is stretched, or maybe when you stretch a trill, you should get more +notes rather than a slower trill. + +To override default behaviors, you almost always follow the same +programming pattern: first, capture the environment in a local variable; +then, use one of the absolute transformations to ``turn off'' the +environment's effect and compute the sound as desired. The following +example creates a very simple envelope with a fixed rise time to +illustrate the technique. +@begin(example) +define function two-phase-env(rise-time) + begin + with dur = get-duration(1) + return pwl(rise-time, 1, dur) ~~ 1.0 + end +@end(example) +To ``capture the environment in a local variable,'' a @code(with) +construct is used to create the local variable @code(dur) and set +it to the value of @code[get-duration(1)], which answers the question: +``If I apply use the environment to stretch something whose nominal +duration is 1, what is the resulting duration?'' (Since time transformations +can involve continuous time deformations, this question is not as +simple as it may sound, so please use the provided function rather +than peeking inside the @code(*warp*) structure and trying to do it +yourself.) Next, we ``turn off'' stretching using the @code(stretch-abs) +form, which in SAL is denoted by the @code(~~) operator. +Finally, we are ready to compute the envelope using @code(pwl). Here, +we use absolute durations. The first breakpoint is at @code(rise-time), +so the attack time is given by the @code(rise-time) parameter. The +@code(pwl) decays back to zero at time @code(dur), so the overall +duration matches the duration expected from the environment encountered +by this instance of @code(two-phase-env). Note, however, that since +the @code(pwl) is evaluated in a different environment established +by @code(~~), it is not stretched (or perhaps more accurately, it is +stretched by 1.0). This is good because it means @code(rise-time) will +not be stretched, but we must be careful to extend the envelope to +@code(dur) so that it has the expected duration. + +@section(Sample Rates) +@index(sample rates) +The global environment contains @code(*sound-srate*) and +@code(*control-srate*), which determine the sample rates of sounds and +control signals. These can be overridden at any point by the +transformations @code(sound-srate-abs) and @code(control-srate-abs); for +example, +@begin(example) +sound-srate-abs(44100.0, osc(c4) +@end(example) +will compute a tone using a 44.1Khz sample rate even if the default rate +is set to something different. + +@index(default sample rate) +As with other components of the environment, you should @i(never) change +@code(*sound-srate*) or @code(*control-srate*) directly. + The global environment is determined by two additional +variables: @code(*default-sound-srate*) and @code(*default-control-srate*). +You can add lines like the following to your @code(init.lsp) file to change +the default global environment: +@begin(example) +(setf *default-sound-srate* 44100.0) +(setf *default-control-srate* 1102.5) +@end(example) +You can also do this using preferences in jNyqIDE. +If you have already started Nyquist and want to change the defaults, the +preferences or the following functions can be used: +@begin(example) +exec set-control-srate(1102.5)@index(set-control-srate) +exec set-sound-srate(22050.0)@index(set-sound-srate) +@end(example) +These modify the default values and reinitialize the Nyquist environment. + + +@chapter(Continuous Transformations and Time Warps) +@label(warp-chap) +Nyquist transformations were discussed in the previous chapter, but all of +the examples used scalar values. For example, we saw the @code[loud] +transformation used to change loudness by a fixed amount. What if we want +to specify a crescendo, where the loudness changes gradually over time? + +It turns out that all transformations can accept signals as well as numbers, +so transformations can be continuous over time. This raises some +interesting questions about how to interpret continuous transformations. +Should a loudness transformation apply to the internal details of a note or +only affect the initial loudness? It might seem unnatural for a decaying +piano note to perform a crescendo. On the other hand, a sustained +trumpet sound should probably crescendo continuously. In the case of time +warping (tempo changes), it might be best for a drum roll to maintain a +steady rate, a trill may or may not change rates with tempo, and a run of +sixteenth notes will surely change its rate. + +These issues are complex, and Nyquist cannot hope to automatically do the +right thing in all cases. However, the concept of behavioral abstraction +provides an elegant solution. Since transformations merely modify the +environment, behaviors are not forced to implement any particular style of +transformation. Nyquist is designed so that the default transformation is +usually the right one, but it is always possible to override the default +transformation to achieve a particular effect. + +@section(Simple Transformations) +The ``simple'' transformations affect some parameter, but have no effect on time itself. The simple transformations that support continuously changing parameters are: @code(sustain), @code(loud), and @code(transpose). + +As a first example, Let us use @code(transpose) to create a chromatic scale. +First define a sequence of tones at a steady pitch. The @code(seqrep) +``function'' works like @code(seq) except that it creates copies of a sound +by evaluating an expression multiple times. Here, @code(i) takes on 16 values +from 0 to 15, and the expression for the sound could potentially use @code(i). +Technically, @code(seqrep) is not really a function but an abbreviation for +a special kind of loop construct. +@begin(example) +define function tone-seq() + return seqrep(i, 16, + osc-note(c4) ~ 0.25) +@end(example) +Now define a linearly increasing ramp to serve as a transposition function: +@begin(code) +define function pitch-rise() + return sustain-abs(1.0, 16 * ramp() ~ 4) +@end(code) +This ramp has a duration of 4 seconds, and over that interval it rises from +0 to 16 (corresponding to the 16 semitones we want to transpose). The ramp +is inside a @code(sustain-abs) transformation, which prevents a @code(sustain) +transformation from having any effect on the ramp. (One of the drawbacks of +behavioral abstraction is that built-in behaviors sometimes do the wrong +thing implicitly, requiring some explicit correction to turn off the +unwanted transformation.) Now, +@code(pitch-rise) is used to transpose @code(tone-seq): +@begin(code) +define function chromatic-scale() + return transpose(pitch-rise(), tone-seq()) +@end(code) + +Similar transformations can be constructed to change the sustain or ``duty +factor'' of notes and their loudness. The following expression plays the +@code(chromatic-scale) behavior with increasing note durations. The +rhythm is unchanged, but the note length changes from staccato to legato: +@begin(code) +play sustain((0.2 + ramp()) ~ 4, + chromatic-scale()) +@end(code) +The resulting sustain function will ramp from 0.2 to 1.2. A sustain of 1.2 +denotes a 20 percent overlap between notes. The @code(sum) has a stretch +factor of 4, so it will extend over the 4 second duration of +@code(chromatic-scale). + +If you try this, you will discover that the @code(chromatic-scale) no longer +plays a chromatic scale. You will hear the first 4 notes going up in intervals +of 5 semitones (perfect fourths) followed by repeated pitches. What +is happening is that the @code(sustain) operation applies to +@code(pitch-rise) in addition to @code(tone-seq), so now the 4s +ramp from 0 to 16 becomes a 0.8s ramp. To fix this problem, we need to +shield @code(pitch-rise) from the effect of @code(sustain) using the +@code(sustain-abs) transformation. Here is a corrected version of +@code(chromatic-scale): +@begin(code) +define function chromatic-scale() + return transpose(sustain-abs(1, pitch-rise()), tone-seq()) +@end(code) + +What do these transformations mean? How did the system know to produce a +pitch rise rather than a continuous glissando? This all relates to the idea +of behavioral abstraction. It is possible to design sounds that @i(do) +glissando under the transpose transform, and you can even make sounds that +@i(ignore) transpose altogether. As explained in Chapter +@ref(behavioral-abstraction-sec), the transformations modify the +environment, and behaviors can reference the environment to determine what +signals to generate. All built-in functions, such as @code(osc), have a +default behavior. + +The default behavior for sound primitives under @code(transpose), +@code(sustain), and @code(loud) transformations is +to sample the environment at the beginning of the +note. Transposition is not quantized to semitones or any other scale, +but in our example, we arranged for the transposition to work out to integer +numbers of semitones, so we obtained a chromatic scale anyway. + +Transposition only applies to the oscillator and sampling primitives +@code(osc), @code(partial), @code(sampler), @code(sine), @code(fmosc), +and @code(amosc). Sustain applies to @code(osc), @code(env), @code(ramp), +and @code(pwl). (Note that @code(partial), @code(amosc), and +@code(fmosc) get their durations +from the modulation signal, so they may indirectly depend upon the sustain.) +Loud applies to @code(osc), @code(sampler), @code(cue), @code(sound), +@code(fmosc), and @code(amosc). (But not @code(pwl) or @code(env).) + + +@section(Time Warps) +The most interesting transformations have to do with transforming time +itself. The @code(warp) transformation provides a mapping function from +logical (score) time to real time. The slope of this function tells us how +many units of real time are covered by one unit of score time. This is +proportional to 1/tempo. A higher slope corresponds to a slower tempo. + +To demonstrate @code(warp), we will define a time warp function using +@code(pwl): +@begin(example) +define function warper() + return pwl(0.25, .4, .75, .6, 1.0, 1.0, 2.0, 2.0, 2.0) +@end(example) +This function has an initial slope of .4/.25 = 1.6. It may be easier to +think in reciprocal terms: the initial tempo is .25/.4 = .625. Between 0.25 +and 0.75, the tempo is .5/.2 = 2.5, and from 0.75 to 1.0, the tempo is again +.625. It is important for warp functions to completely span the interval of +interest (in our case it will be 0 to 1), and it is safest to extend a bit +beyond the interval, so we extend the function on to 2.0 with a +tempo of 1.0. Next, we stretch and scale the @code(warper) function to +cover 4 seconds of score time and 4 seconds of real time: +@begin(example) +define function warp4() + return 4 * warper() ~ 4 +@end(example) + +@begin(figure) +@center(@graphic((height = 3.25 in, width = 3.5 in, magnify = 0.5, + postscript = "warpfig.ps")) +@html(

) +@fillcaption{The result of @code[(warp4)], intended to map 4 seconds of +score time into 4 seconds of real time. The function extends beyond 4 +seconds (the dashed lines) to make sure the function is well-defined at +location (4, 4). Nyquist sounds are ordinarily open on the right.} +@tag(warp-fig) +@end(figure) + +Figure @ref(warp-fig) shows a plot of this warp function. Now, we can +warp the tempo of the @code(tone-seq) defined above using @code(warp4): +@begin(example) +play warp(warp4(), tone-seq()) +@end(example) +Figure @ref(warp-notes-fig) shows the result graphically. Notice that the +durations of the tones are warped as well as their onsets. Envelopes are +not shown in detail in the figure. Because of the way @code(env) is +defined, the tones will have constant attack and decay times, and the +sustain will be adjusted to fit the available time. + +@begin(figure) +@center(@graphic((height = 1.75 in, width = 6.75 in, magnify = 1.0, + postscript = "warpnotesfig.ps")) +@html(

) +@fillcaption[When @code{(warp4)} is applied to @code{(tone-seq-2)}, the note onsets and durations are warped.] +@tag(warp-notes-fig) +@end(figure) + +@section(Abstract Time Warps) +We have seen a number of examples where the default behavior did the +``right thing,'' making the code straightforward. This is not always the +case. Suppose we want to warp the note onsets but not the durations. We +will first look at an incorrect solution and discuss the error. Then we +will look at a slightly more complex (but correct) solution. + +The default behavior for most Nyquist built-in functions is to sample the +time warp function at the nominal starting and ending score times of the +primitive. For many built-in functions, including @code(osc), the starting +logical time is 0 and the ending logical time is 1, so the time warp +function is evaluated at these points to yield real starting and stopping +times, say 15.23 and 16.79. The difference (e.g. 1.56) becomes the signal +duration, and there is no internal time warping. The @code(pwl) function +behaves a little differently. Here, each breakpoint is warped individually, +but the resulting function is linear between the breakpoints. + +A consequence of the default behavior is that notes stretch when the tempo +slows down. Returning to our example, recall that we want to warp only the +note onset times and not the duration. One would think that the following +would work: +@begin(example) +define function tone-seq-2 () + return seqrep(i, 16, + osc-note(c4) ~~ 0.25) + +play warp(warp4(), tone-seq-2()) +@end(example) +Here, we have redefined @code(tone-seq), renaming it to @code(tone-seq-2) +and changing the stretch (@code(~)) to absolute stretch (@code(~~)). The +absolute stretch should override the warp function and produce a fixed +duration. + +If you play the example, you will hear steady +sixteenths and no tempo changes. What is wrong? In a sense, the ``fix'' +works too well. Recall that sequences (including @code(seqrep)) determine +the starting time of the next note from the logical stop time of the +previous sound in the sequence. When we forced the stretch to 0.25, we also +forced the logical stop time to 0.25 real seconds from the beginning, so +every note starts 0.25 seconds after the previous one, resulting in a +constant tempo. + +Now let us design a proper solution. The trick is to use absolute +stretch (@code(~~)) +as before to control the duration, but to restore the logical stop time to a +value that results in the proper inter-onset time interval: +@begin(example) +define function tone-seq-3() + return seqrep(i, 16, + set-logical-stop(osc-note(c4) ~~ 0.25, 0.25)) + +play warp(warp4(), tone-seq-3()) +@end(example) +Notice the addition of @code(set-logical-stop) enclosing the +absolute stretch (@code(~~)) expression to set the logical + stop time. A possible +point of confusion here is that the logical stop time is set to 0.25, the +same number given to @code(~~)! How does setting the logical stop +time to 0.25 result in a tempo change? When used within a @code(warp) +transformation, the second argument to @code(set-logical-stop) refers to +@i(score) time rather than @i(real) time. Therefore, the score duration of +0.25 is warped into real time, producing tempo changes according to the +enviroment. Figure @ref(warp-onset-fig) illustrates the result graphically. + +@begin(figure) +@center(@graphic((height = 1.75 in, width = 6.75 in, magnify = 1.0, + postscript = "warponsetfig.ps")) +@html(

) +@fillcaption[When @code[(warp4)] is applied +to @code[(tone-seq-3)], the note onsets are warped, but not the duration, +which remains a constant 0.25 seconds. In the fast middle section, this +causes notes to overlap. Nyquist will sum (mix) them.] +@tag(warp-onset-fig) +@end(figure) + +@section(Nested Transformations) +Transformations can be nested. In particular, a simple transformation such +as transpose can be nested within a time warp transformation. Suppose we +want to warp our chromatic scale example with the @code(warp4) time warp +function. As in the previous section, we will show an erroneous simple +solution followed by a correct one. + +The simplest approach to a nested transformation is to simply combine them +and hope for the best: +@begin(example) +play warp(warp4(), + transpose(pitch-rise(), tone-seq())) +@end(example) +This example will not work the way you might expect. Here is why: the warp +transformation applies to the @code[(pitch-rise)] expression, which is +implemented using the @code(ramp) function. The default +behavior of @code(ramp) is to interpolate linearly (in real time) between two points. +Thus, the ``warped'' @code(ramp) function will not truly reflect the internal +details of the intended time warp. When the notes are moving faster, they +will be closer together in pitch, and the result is not chromatic. +What we need is a way to properly +compose the warp and ramp functions. If we continuously warp the ramp function +in the same way as the note sequence, a chromatic scale should be obtained. +This will lead to a correct solution. + +Here is the modified code to properly warp a transposed sequence. Note that +the original sequence is used without modification. The only complication +is producing a properly warped transposition function: +@begin(example) + play warp(warp4(), + transpose( + control-warp(get-warp(), + warp-abs(nil, pitch-rise())), + tone-seq())) +@end(example) +To properly warp the @code(pitch-rise) transposition function, we use +@code(control-warp), which applies a warp function to a function of score time, +yielding a function of real time. We need to pass the desired function +to @code(control-warp), so we fetch it from the environment with +@code[get-warp()]. Finally, since the warping is done here, we want to +shield the @code(pitch-rise) expression from further warping, so we enclose +it in @code[warp-abs(nil, ...)]. + + @i(An aside:) This last example illustrates a difficulty in the design of +Nyquist. To support behavioral abstraction universally, we must rely upon +behaviors to ``do the right thing.'' In this case, we would like the +@code(ramp) function to warp continuously according to the environment. But +this is inefficient and unnecessary in many other cases where @code(ramp) +and especially @code(pwl) are used. (@code(pwl) warps its breakpoints, but still interpolates linearly between them.) Also, if the default behavior of +primitives is to warp in a continuous manner, this makes it difficult to +build custom abstract behaviors. The final vote is not in. + +@chapter(More Examples) + +This chapter explores Nyquist through additional examples. The reader may +wish to browse through these and move on to Chapter @ref(lisp-chap), which +is a reference section describing Nyquist functions. + +@section(Stretching Sampled Sounds)@index(Stretching Sampled Sounds) + +This example illustrates how to stretch a sound, resampling it in the process. +Because sounds in Nyquist are @i(values) that contain the sample rate, start +time, etc., use @code(sound) to convert a sound into a behavior that can be +stretched, e.g. @code[sound(a-snd)]. This behavior stretches a sound according +to the stretch factor in the environment, set using @code(stretch). For +accuracy and efficiency, Nyquist does not resample a stretched sound until +absolutely necessary. The @code(force-srate) function is used to resample +the result so that we end up with a ``normal'' sample rate that is playable +on ordinary sound cards. + +@begin(example) +@i[; if a-snd is not loaded, load sound sample: +;] +if not(boundp(quote(a-snd))) then + set a-snd = s-read("demo-snd.aiff") + +@i[; the SOUND operator shifts, stretches, clips and scales +; a sound according to the current environment +;] +define function ex23() + play force-srate(*default-sound-srate*, sound(a-snd) ~ 3.0) + +define function down() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.2, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.6)) +play down() + +@i[; that was so much fun, let's go back up: +;] +define function up() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.5, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.2)) + +@i[; and write a sequence +;] +play seq(down(), up(), down()) +@end(example) + +Notice the use of the @code(sound) behavior as opposed to @code(cue). The +@code(cue) behavior shifts and scales its sound according to @code(*warp*) +and @code(*loud*), but it does not change the duration or resample the +sound. In contrast, @code(sound) not only shifts and scales its sound, but +it also stretches it by resampling or changing the effective sample rate + according to @code(*warp*). If +@code[*warp*] is a continuous warping function, then the sound will be +stretched by time-varying amounts. +(The @code(*transpose*) element of the environment is +ignored by both @code(cue) and @code(sound).) + +@p(Note:) @code(sound) may use linear interpolation rather than a high-quality resampling algorithm. In some cases, this may introduce errors audible as noise. Use @code(resample) (see Section @ref(resample-sec)) for high-quality interpolation. + +In the functions @code(up) and @code(down), the @code(*warp*) is set by +@i(stretch) (@code(~)), which simply scales time by a constant scale factor. In this case, +@code(sound) can ``stretch'' the signal simply by changing the sample rate without +any further computation. When @code(seq) tries to add the signals together, it +discovers the sample rates do not match and uses linear interpolation to adjust +all sample rates to match that of the first sound in the sequence. The result of +@code(seq) is then converted using @code(force-srate) to convert the sample rate, +again using linear interpolation. +It would be slightly better, from a computational +standpoint, to apply @code(force-srate) individually +to each stretched sound rather +than applying @code(force-srate) after @code(seq). + +Notice that the overall duration of @code[sound(a-snd) ~ 0.5] will +be half the duration of @code(a-snd). + +@section(Saving Sound Files)@index(Saving Sound Files) + +So far, we have used the @code(play) command to play a sound. The +@code(play) command works by writing a sound to a file while +simultaneously playing it. +This can be done one step at a time, and +it is often convenient to save a sound to a particular file for later use: +@begin(example) +@i[; write the sample to a file, +; the file name can be any Unix filename. Prepending a "./" tells +; s-save to not prepend *default-sf-dir* +;] +exec s-save(a-snd, 1000000000, "./a-snd-file.snd") + +@i[; play a file +; play command normally expects an expression for a sound +; but if you pass it a string, it will open and play a +; sound file] +play "./a-snd-file.snd" + +@i[; delete the file (do this with care!) +; only works under Unix (not Windows)] +exec system("rm ./a-snd-file.snd") + +@i[; now let's do it using a variable as the file name +;] +set my-sound-file = "./a-snd-file.snd" + +exec s-save(a-snd, 1000000000, my-sound-file) + +@i[; play-file is a function to open and play a sound file] +exec play-file(my-sound-file) + +exec system(strcat("rm ", my-sound-file)) +@end(example) +This example shows how @code(s-save) can be used to save a sound to a file. + +This example also shows how the @code(system) function can be used to invoke +Unix shell commands, such as a command to play a file or remove it. +Finally, notice that @code(strcat) can be used to concatenate a command name +to a file name to create a complete command that is then passed to +@code(system). (This is convenient if the sound file name is stored in a +parameter or variable.) + +@section(Memory Space and Normalization) +@label(normalization-sec) +@index(normalization)@index(peak amplitude)@index(maximum amplitude)@index(clip)@index(s-max)@index(s-min)@index(rescaling)@index(not enough memory for normalization) +Sound samples take up lots of memory, and often, there is not enough primary (RAM) memory to hold a complete composition. For this reason, Nyquist can compute sounds incrementally, saving the final result on disk. @i(However,) Nyquist can also save sounds in memory so that they can be reused efficiently. In general, if a sound is saved in a global variable, memory will be allocated as needed to save and reuse it. + +The standard way to compute a sound and write it to disk is to pass an expression to the @code(play) command: +@begin(example) +play my-composition() +@end(example) + +@label(peak-ex-sec) +Often it is nice to @i(normalize) sounds so that they use the full available +dynamic range of 16 bits. Nyquist has an automated facility to help with +normalization. By default, Nyquist computes up to 1 million samples (using +about 4MB of memory) looking for the peak. The entire sound is normalized so +that this peak will not cause clipping. If the sound has less than 1 million +samples, or if the first million samples are a good indication of the overall +peak, then the signal will not clip. + +With this automated normalization technique, you can choose the desired +peak value by setting @code(*autonorm-target*), which is initialized to 0.9. +The number of samples examined is @code(*autonorm-max-samples*), initially +1 million. You can turn this feature off by executing: +@begin(example) +exec autonorm-off()@index(autonorm-off) +@end(example) +and turn it back on by typing: +@begin(example) +exec autonorm-on()@index(autonorm-on) +@end(example) +This normalization technique is in effect when @code(*autonorm-type*) is +@code(quote(lookahead)), which is the default. + +An alternative normalization method uses the peak value from the previous +call to @code(play). After playing a file, Nyquist can adjust an internal +scale factor so that if you play the same file again, the peak amplitude +will be @code(*autonorm-target*), which is initialized to 0.9. This can +be useful if you want to carefully normalize a big sound that does not +have its peak near the beginning. To select this style of normalization, +set @code(*autonorm-type*) to the (quoted) atom @code(quote(previous)). + +You can also create your own normalization method in Nyquist. +The @code(peak) function computes the maximum value of a sound. +The peak value is also returned from the @code(play) macro. You can +normalize in memory if you have enough memory; otherwise you can compute +the sound twice. The two techniques are illustrated here: +@begin(example) +@i[; normalize in memory. First, assign the sound to a variable so +; it will be retained:] +set mysound = sim(osc(c4), osc(c5)) +@i[; now compute the maximum value (ny:all is 1 giga-samples, you may want a +; smaller constant if you have less than 4GB of memory:] +set mymax = snd-max(mysound, NY:ALL) +display "Computed max", mymax +@i[; now write out and play the sound from memory with a scale factor:] +play mysound * (0.9 / mymax) + +@i[; if you don't have space in memory, here's how to do it:] +define function myscore() + return sim(osc(c4), osc(c5)) +@i[; compute the maximum:] +set mymax = snd-max(list(quote(myscore)), NY:ALL) +display "Computed max", mymax +@i[; now we know the max, but we don't have a the sound (it was garbage +; collected and never existed all at once in memory). Compute the sound +; again, this time with a scale factor:] +play myscore() * (0.9 / mymax) +@end(example) + +You can also write a sound as a floating point file. This +file can then be converted to 16-bit integer with the proper scaling +applied. If a long computation was involved, it should be much faster +to scale the saved sound file than to recompute the sound from scratch. +Although not implemented yet in Nyquist, some header formats can +store maximum amplitudes, and some soundfile player programs can +rescale floating point files on the fly, allowing normalized +soundfile playback without an extra normalization pass (but at a cost +of twice the disk space of 16-bit samples). +You can use Nyquist to rescale a floating point file and +convert it to 16-bit samples for playback. + +@section(Frequency Modulation)@index(Frequency Modulation) +The next example uses the Nyquist frequency modulation behavior @code(fmosc) +to generate various sounds. The parameters to @code(fmosc) are: +@begin(example) +fmosc(@i(pitch) @i(modulator) @i(table) @i(phase)) +@end(example) +Note that pitch is the number of half-steps, e.g. @code(c4) has the value of 60 which is middle-C, and phase is in degrees. Only the first two parameters are required: +@begin(example) +@i[; make a short sine tone with no frequency modulation +;] +play fmosc(c4, pwl(0.1)) + +@i[; make a longer sine tone -- note that the duration of +; the modulator determines the duration of the tone +;] +play fmosc(c4, pwl(0.5)) +@end(example) +In the example above, @code(pwl) (for Piece-Wise Linear) is used to generate +sounds that are zero for the durations of @code(0.1) and @code(0.5) seconds, +respectively. In effect, we are using an FM oscillator with no modulation +input, and the result is a sine tone. The duration of the modulation +determines the duration of the generated tone (when the modulation signal +ends, the oscillator stops). + +The next example uses a more interesting modulation function, a ramp from +zero to C@-(4), expressed in hz. More explanation of @code(pwl) is in +order. This operation constructs a piece-wise linear function sampled at +the @code(*control-srate*). The first breakpoint is always at @code[(0, +0)], so the first two parameters give the time and value of the second +breakpoint, the second two parameters give the time and value of the third +breakpoint, and so on. The last breakpoint has a value of @code(0), so only +the time of the last breakpoint is given. In this case, we want the ramp to +end at C@-(4), so we cheat a bit by having the ramp return to zero +``almost'' instantaneously between times @code(0.5) and @code(0.501). + +The @code(pwl) behavior always expects an odd number of parameters. The +resulting function is shifted and stretched linearly according to +@code[*warp*] in the environment. Now, here is the example: +@begin(example) +@i[; make a frequency sweep of one octave; the piece-wise linear function +; sweeps from 0 to (step-to-hz c4) because, when added to the c4 +; fundamental, this will double the frequency and cause an octave sweep. +;] +play fmosc(c4, pwl(0.5, step-to-hz(c4), 0.501)) +@end(Example) + +The same idea can be applied to a non-sinusoidal carrier. Here, we assume that @code(*fm-voice*) is predefined (the next section shows how to define it): +@begin(example) +@i[; do the same thing with a non-sine table +;] +play fmosc(cs2, pwl(0.5, step-to-hz(cs2), 0.501), + *fm-voice*, 0.0) +@end(example) + +The next example shows how a function can be used to make a special +frequency modulation contour. In this case the contour generates a sweep +from a starting pitch to a destination pitch: +@begin(example) +@i[; make a function to give a frequency sweep, starting +; after seconds, then sweeping from +; to in seconds and then +; holding at for seconds. +;] +define function sweep(delay, pitch-1, sweep-time, + pitch-2, hold-time) + begin + with interval = step-to-hz(pitch-2) - step-to-hz(pitch-1) + return pwl(delay, 0.0, + @i[; sweep from pitch 1 to pitch 2] + delay + sweep-time, interval, + @i[; hold until about 1 sample from the end] + delay + sweep-time + hold-time - 0.0005, + interval, + @i[; quickly ramp to zero (pwl always does this,] + @i[; so make it short)] + delay + sweep-time + hold-time) + end + + +@i[; now try it out +;] +play fmosc(cs2, sweep(0.1, cs2, 0.6, gs2, 0.5), + *fm-voice*, 0.0) +@end(example) + +FM can be used for vibrato as well as frequency sweeps. Here, we use the +@code(lfo) function to generate vibrato. The @code(lfo) operation is +similar to @code(osc), except it generates sounds at the +@code(*control-srate*), and the parameter is hz rather than a pitch: +@begin(example) +play fmosc(cs2, 10.0 * lfo(6.0), *fm-voice*, 0.0) +@end(Example) + +What kind of manual would this be without the obligatory FM sound? Here, a +sinusoidal modulator (frequency C@-(4)) is multiplied by a slowly increasing +ramp from zero to @code(1000.0). +@begin(example) +set modulator = pwl(1.0, 1000.0, 1.0005) * + osc(c4) +@i[; make the sound] +play fmosc(c4, modulator) +@end(example) + +For more simple examples of FM in Nyquist, see +@index(warble)@index(FM synthesis)@index(demos, FM)@index(tutorial, FM) +@code(demos/warble_tutorial.htm). Another interesting FM sound +reminiscent of ``scratching'' can be found with a detailed explanation +in @code(demos/scratch_tutorial.htm).@index(demos, scratch tutorial) +@index(vinal scratch)@index(scratch sound). + +@section(Building a Wavetable) +In Section @ref(waveform-sec), we saw how to synthesize a wavetable. A +wavetable for @code(osc) also can be extracted from any sound. This is +especially interesting if the sound is digitized from some external sound +source and loaded using the @code(s-read) function. Recall that a table +is a list consisting of a sound, the pitch of that sound, and T (meaning the +sound is periodic). + +In the following, a sound is first read from the file @code(demo-snd.nh). +Then, the @code(extract) function is used +to extract the portion of the sound between 0.110204 and 0.13932 seconds. +(These numbers might be obtained by first plotting the sound and estimating +the beginning and end of a period, or by using some software to look for +good zero crossings.) The result of @code(extract) becomes the first +element of a list. The next element is the pitch (24.848422), and the last +element is @code(T). The list is assigned to @code(*fm-voice*). +@begin(example) +if not(boundp(quote(a-snd))) then + set a-snd = s-read("demo-snd.aiff") + +set *fm-voice* = list(extract(0.110204, 0.13932, cue(a-snd)), + 24.848422, + #T) +@end(example) + +The file +@i(demos/examples.sal) contains an extensive example of how to locate +zero-crossings, extract a period, build a waveform, and generate a tone from it. (See @code(ex37) through @code(ex40) in the file.) + +@begin(comment) +The @code(maketable) command is also useful and is documented on page +@ref(maketable). If @code(sample) is the source sound, then the following +will extract 0.01 seconds (starting at time 0.2s) of audio and convert it +into a waveform named @code(mytable): +@begin(example) +(setf mytable (maketable (extract -abs 0.2 0.21 sample))) +@end(example) +Nyquist does not provide any pitch analysis or other help finding good splice points, so it is up to you to make sure the table you extract is a reasonable one. +@end(comment) + +@section(Filter Examples) + +Nyquist provides a variety of filters. All of these filters take either +real numbers or signals as parameters. If you pass a signal as a filter +parameter, the filter coefficients are recomputed at the sample rate of the +@i(control) signal. Since filter coefficients are generally expensive to +compute, you may want to select filter control rates carefully. Use +@code(control-srate-abs) (Section @ref(control-srate-abs-sec)) to specify +the default control sample rate, or use @code(force-srate) (Section +@ref(force-srate-sec)) to resample a signal before passing it to a filter. + +Before presenting examples, let's generate some unfiltered white noise: +@begin(example) +play noise() +@end(example) +Now low-pass filter the noise with a 1000Hz cutoff: +@begin(example) +play lp(noise(), 1000.0) +@end(example) +The high-pass filter is the inverse of the low-pass: +@begin(example) +play hp(noise(), 1000.0) +@end(example) + +Here is a low-pass filter sweep from 100Hz to 2000Hz: +@begin(example) +play lp(noise(), pwl(0.0, 100.0, 1.0, 2000.0, 1.0)) +@end(example) +And a high-pass sweep from 50Hz to 4000Hz: +@begin(example) +play hp(noise(), pwl(0.0, 50.0, 1.0, 4000.0, 1.0)) +@end(example) + +The band-pass filter takes a center frequency and a bandwidth parameter. +This example has a 500Hz center frequency with a 20Hz bandwidth. The scale +factor is necessary because, due to the resonant peak of the filter, the +signal amplitude exceeds 1.0: +@begin(example) +play reson(10.0 * noise(), 500.0, 20.0, 1) +@end(example) +In the next example, the center frequency is swept from 100 to 1000Hz, using a constant 20Hz bandwidth: +@begin(example) +play reson(0.04 * noise(), + pwl(0.0, 200.0, 1.0, 1000.0, 1.0), + 20.0) +@end(example) + +For another example with explanations, see +@index(wind_tutorial.htm)@index(wind sound)@index(filter example) +@index(demos, wind sound) +@code(demos/wind_tutorial.htm). + + +@section(DSP in Lisp) +@index(DSP in Lisp)@index(Lisp DSP)In almost any +signal processing system, the vast majority of computation +takes place in the inner loops of DSP algorithms, and Nyquist is designed so +that these time-consuming inner loops are in highly-optimized +machine code rather than relatively slow interpreted lisp code. As a result, +Nyquist typically spends 95% of its time in these inner loops; the overhead +of using a Lisp interpreter is negligible. + +The drawback is that Nyquist must provide the DSP operations you need, or +you are out of luck. When Nyquist is found lacking, you can either write a +new primitive signal operation, or you can perform DSP in Lisp code. Neither +option is recommended for inexperienced programmers. Instructions for +extending Nyquist are given in Appendix @ref(extending-app). This section +describes the process of writing a new signal processing function in Lisp. + +Before implementing a new DSP function, you should decide which approach is +best. First, figure out how much of the new function can be implemented +using existing Nyquist functions. For example, you might think that a +tapped-delay line would require a new function, but in fact, it can be +implemented by composing sound transformations to accomplish delays, scale +factors for attenuation, and additions to combine the intermediate results. +This can all be packaged into a new Lisp function, making it easy to use. +If the function relies on built-in DSP primitives, it will execute very +efficiently. + +Assuming that built-in functions cannot be used, try to define a new +operation that will be both simple and general. Usually, it makes sense to +implement only the kernel of what you need, combining it with existing +functions to build a complete instrument or operation. For example, if you +want to implement a physical model that requires a varying breath pressure +with noise and vibrato, plan to use Nyquist functions to add a basic +pressure envelope to noise and vibrato signals to come up with a composite +pressure signal. Pass that signal into the physical model rather than +synthesizing the envelope, noise, and vibrato within the model. This not +only simplifies the model, but gives you the flexibility to use all of +Nyquist's operations to synthesize a suitable breath pressure signal. + +Having designed the new ``kernel'' DSP operation that must be implemented, +decide whether to use C or Lisp. (At present, SAL is not a good option +because it has no support for object-oriented programming.) +To use C, you must have a C compiler, the +full source code for Nyquist, and you must learn about extending Nyquist by +reading Appendix @ref(extending-app). This is the more complex approach, but +the result will be very efficient. A C implementation will deal properly +with sounds that are not time-aligned or matched in sample rates. +To use Lisp, you must learn something +about the XLISP object system, and the result will be about 50 times slower +than C. Also, it is more difficult to deal with time alignment and +differences in sample rates. +The remainder of this section gives an example of a Lisp version of +@code(snd-prod) to illustrate how to write DSP functions for Nyquist in Lisp. + +The @code(snd-prod) function is the low-level multiply routine. It has two +sound parameters and returns a sound which is the product of the two. To +keep things simple, we will assume that two sounds to be multiplied have a +matched sample rate and matching start times. The DSP algorithm for each +output sample is simply to fetch a sample from each sound, multiply them, +and return the product. + +To implement @code(snd-prod) in Lisp, three components are required: +@begin(enumerate) +An object is used to store the two parameter sounds. This object will be +called upon to yield samples of the result sound; + +Within the object, the @code(snd-fetch) routine is used to fetch samples +from the two input sounds as needed; + +The result must be of type @code(SOUND), so @code(snd-fromobject) is used +to create the result sound. +@end(enumerate) + +The combined solution will work as follows: The result is a value of type +@code(sound) that retains a reference to the object. When Nyquist needs +samples from the sound, it invokes the sound's ``fetch'' function, which in +turn sends an XLISP message to the object. The object will use +@code(snd-fetch) to get a sample from each stored sound, multiply the +samples, and return a result. + +Thus the goal is to design an XLISP object that, in response to a +@code(:next) message will return a proper sequence of samples. When the +sound reaches the termination time, simply return @code(NIL). + +The XLISP manual (see Appendix @ref(XLISP-app) describes the object system, +but in a very terse style, so this example will include some explanation of +how the object system is used. First, we need to define a class for the +objects that will compute sound products. Every class is a subclass of class +@code(class), and you create a subclass by sending @code(:new) to a class. +@begin(example) +(setf product-class (send class :new '(s1 s2))) +@end(example) +The parameter @code['(s1 s2)] says that the new class will have two instance +variables, @code(s1) and @code(s2). In other words, every object which is an +instance of class @code(product-class) will have its own copy of +these two variables. + +Next, we will define the @code(:next) method for @code(product-class): +@begin(example) +(send product-class :answer :next '() + '((let ((f1 (snd-fetch s1)) + (f2 (snd-fetch s2))) + (cond ((and f1 f2) + (* f1 f2)) + (t nil))))) +@end(example) +The @code(:answer) message is used to insert a new method into our new +@code(product-class). The method is described in three parts: the name +(@code(:next)), a parameter list (empty in this case), and a list of +expressions to be evaluated. In this case, we fetch samples from @code(s1) +and @code(s2). If both are numbers, we return their product. If either is +@code(NIL), we terminate the sound by returning @code(nil). + +The @code(:next) method assumes that @code(s1) and @code(s2) hold the sounds +to be multiplied. These must be installed when the object is created. +Objects are created by sending @code(:new) to a class. A new object is +created, and any parameters passed to @code(:new) are then sent in a +@code(:isnew) message to the new object. Here is the @code(:isnew) +definition for @code(product-class): +@begin(example) +(send product-class :answer :isnew '(p1 p2) + '((setf s1 (snd-copy p1)) + (setf s2 (snd-copy p2)))) +@end(example) +Take careful note of the use of @code(snd-copy) in this initialization. The +sounds @code(s1) and @code(s2) are modified when accessed by +@code(snd-fetch) in the @code(:next) method defined above, but this destroys +the illusion that sounds are immutable values. The solution is to copy the +sounds before accessing them; the original sounds are therefore unchanged. +(This copy also takes place implicitly in most Nyquist sound functions.) + +To make this code safer for general use, we should add checks that @code(s1) +and @code(s2) are sounds with identical starting times and sample rates; +otherwise, an incorrect result might be computed. + +Now we are ready to write @code(snd-product), an approximate replacement for +@code(snd-prod): +@begin(example) +(defun snd-product (s1 s2) + (let (obj) + (setf obj (send product-class :new s1 s2)) + (snd-fromobject (snd-t0 s1) (snd-srate s1) obj))) +@end(example) +This code first creates @code(obj), an instance of @code(product-class), to +hold @code(s1) and @code(s2). Then, it uses @code(obj) to create a sound +using @code(snd-fromobject). This sound is returned from +@code(snd-product). Note that in @code(snd-fromobject), you must also +specify the starting time and sample rate as the first two parameters. These +are copied from @code(s1), again assuming that @code(s1) and @code(s2) have +matching starting times and sample rates. + +Note that in more elaborate DSP algorithms we could expect the object to +have a number of instance variables to hold things such as previous samples, +waveform tables, and other parameters. + +@chapter(SAL) +@label(SAL-chap) +Nyquist supports two languages: XLISP and SAL. In some sense, XLISP and SAL +are the same language, but with differing syntax. This chapter describes SAL: how it works, SAL syntax and semantics, and the relationship between SAL and XLISP, and differences between Nyquist SAL and Common Music SAL. + +Nyquist SAL is based on Rick Taube's SAL language, which is +part of Common Music. SAL offers the power +of Lisp but features a simple, Algol-like syntax. SAL is implemented +in Lisp: Lisp code translates SAL into a Lisp program and uses the +underlying Lisp engine to evaluate the program. Aside from the translation +time, which is quite fast, SAL programs execute at about the same speed as +the corresponding Lisp program. (Nyquist SAL programs run just + slightly slower than XLISP +because of some runtime debugging support automatically added to +user programs by the SAL compiler.) + +From the user's perspective, these implementation details are hidden. You +can enter SAL mode from XLISP by typing @code[(SAL)] to the XLISP prompt. +The SAL input prompt (@code(SAL> )) will be displayed. From that point on, +you simply type SAL commands, and they will be executed. By setting a +preference in the jNyqIDE program, SAL mode will be entered automatically. + +It is possible to encounter errors that will take you from the SAL interpreter +to an XLISP prompt. In general, the way to get back to SAL is by typing +@code[(top)] to get back to the top level XLISP interpreter and reset the +Nyquist environment. Then type @code[(sal)] to restart the SAL interpreter. + +@section(SAL Syntax and Semantics) +@index(SAL) + The most unusual feature of SAL syntax is that identifiers +are Lisp-like, including names such as ``play-file'' and even ``*warp*.'' +In SAL, most operators must be separated from identifiers by white space. +For example, @code(play-file) is one identifier, but @code(play - file) +is an expression for ``play minus file,'' where @code(play) and @code(file) are +two separate identifiers. Fortunately, no spaces are needed around commas +and parentheses. + +In SAL, whitespace (any sequence of space, newline, or tab characters) +is sometimes necessary to separate lexical tokens, but +otherwise, spaces and indentation are ignored. To make SAL readable, +it is @i(strongly) advised that you indent SAL programs as in the examples +here. The jNyqIDE program is purposely insistent about SAL indentation, +so if you use it to edit SAL programs, your indentation should be +both beautiful and consistent. + +As in Lisp (but very unlike C or Java), comments @index(comments) +are indicated by +semicolons. Any text from an unquoted semicolon to the end of the +line is ignored. + +@begin(example) +@i(; this is a comment) +@i(; comments are ignored by the compiler) +print "Hello World" @i(; this is a SAL statement) +@end(example) + +As in Lisp, identifiers are translated to upper-case, making SAL +case-insensitive@index(case-insensitive). For example, the function name @code(autonorm) can +be typed in lower case or as @code(AUTONORM), @code(AutoNorm), or even +@code(AuToNoRm). All forms denote the same function. The recommended +approach is to write programs in all lower case. + +SAL is organized around statements, most of which +contain expressions. We will begin with expressions and then look at +statements. + +@subsection(Expressions) +@index(sal expressions)@index(expressions, sal) +@paragraph(Simple Expressions) +As in XLISP, simple expressions include: +@begin(itemize) +integers (FIXNUM's), such as @code(1215), + +floats (FLONUM's) such as @code(12.15), + +strings (STRING's) such as @code("Magna Carta"), and + +symbols (SYMBOL's) such as @code(magna-carta). A symbol with a leading colon +(@code(:)) evaluates to itself as in Lisp. Otherwise, a symbol denotes either +a local variable, a formal parameter, or a global variable. As in Lisp, +variables do not have data types or type declarations. The type of a +variable is determined at runtime by its value. +@end(itemize) + +Additional simple expressions in SAL are: +@begin(itemize) +lists such as @code[{c 60 e 64}]. Note that there are no commas to separate list elements, and symbols in lists are not evaluated as variables but stand for themselves. Lists may contain numbers, booleans, symbols, strings, and other lists. + +Booleans: SAL interprets @code(#t)@index(#t) as true and @code(#f)@index(#f) +as false. (As far +as the SAL compiler is concerned, @code(t) and @code(nil) are just variables. +Since these are the Lisp versions of true and false, they are interchangeable +with @code(#t) and @code(#f), respectively.) +@end(itemize) +A curious property of Lisp and Sal is that @i(false) and the empty list are +the same value. Since SAL is based on Lisp, @code(#f) and @code({}) (the empty +list)@index(empty list) are equal. + +@paragraph(Operators) +Expressions can be formed with unary and binary operators using infix notation. The operators are: +@begin(itemize) +@index(+)@code(+) - addition, including sounds + +@index(-)@code(-) - subtraction, including sounds + +@index(*)@code(*) - multiplication, including sounds + +@index(/)@code(/) - division (due to divide-by-zero problems, does not operate on sounds) + +@index(%)@code(%) - modulus (remainder after division) + +@index(^)@code(^) - exponentiation + +@index(=)@code(=) - equal (using Lisp @code(eql)) + +@index(!=)@code(!=) - not equal + +@index(>)@code(>) - greater than + +@index(<)@code(<) - less than + +@index(>=)@code(>=) - greater than or equal + +@index(<=)@code(<=) - less than or equal + +@index(~=)@code(~=) - general equality (using Lisp @code(equal)) + +@index(&)@code(&) - logical and + +@index(|)@code(|) - logical or + +@index(!)@code(!) - logical not (unary) + +@index(@@)@index(time shift, sal)@index(at, sal)@code(@@) - time shift + +@index(@@@@)@index(absolute time shift, sal)@index(at-abs, sal)@code(@@@@) - time shift to absolute time + +@index(~)@index(stretch, sal)@code(~) - time stretch + +@index(~~)@index(absolute stretch, sal)@code(~~) - time stretch to absolute stretch factor +@end(itemize) +Again, remember that operators @i(must) be delimited from their operands using +spaces or parentheses. Operator precedence is based on the following levels of +precedence: +@begin(example) +@@ @@@@ ~ ~~ +^ +/ * +% - + +~= <= >= > ~= = +! +& +| +@end(example) + +@paragraph(Function Calls) +@index(function calls, sal) +A function call is a function name followed by zero or more comma-delimited +argument expressions +enclosed within parentheses: +@begin(example) +list() +piano-note(2.0, c4 + interval, 100) +@end(example) +Some functions use named parameters, +in which case the name of the argument with a colon precedes the argument +expression. +@begin(example) +s-save(my-snd(), ny:all, "tmp.wav", play: #t, bits: 16) +@end(example) + +@paragraph(Array Notation) +@index(array notation, sal) +An array reference is a variable identifier followed by an index expression +in square brackets, e.g.: +@begin(example) +x[23] + y[i] +@end(example) + +@paragraph(Conditional Values) +@index(conditional expression, sal) +@index(#?, sal) +The special operator @code(#?) evaluates the first argument expression. +If the result is @i(true), the second expression is evaluated and +its value is returned. If @i(false), the third expression is evaluated +and returned (or @i(false) is returned if there is no third expression): +@begin(example) +#?(random(2) = 0, unison, major-third) +#?(pitch >= c4, pitch - c4) ; returns false if pitch < c4 +@end(example) + +@subsection(SAL Statements) +@index(statements, sal) +SAL compiles and evaluates @i(statements) one at a time. You can type +statements at the SAL prompt or load a file containing SAL statements. +SAL statements are described below. The syntax is indicated at the +beginning of each statement type description: @code(this font) indicates +literal terms such as keywords, @i(the italic font) indicates a +place-holder for some other statement or expression. Bracket [like this] +indicate optional (zero or one) syntax elements, while braces with a plus +{like this}+ indicate one or more occurrences of a syntax element. Braces +with a star {like this}* indicate zero or more occurrences of a syntax element: { @i(non-terminal) }* is equivalent to [ {@i(non-terminal)}+ ]. + +@paragraph(begin and end) +@index(begin)@index(end) +@code(begin) [@i(with-stmt)] {@i(statement)}+ @code(end) + +A @code(begin)-@code(end) statement +consists of a sequence of statements surrounded by +the @code(begin) and @code(end) keywords. This form is often used for function +definitions and after @code(then) or @code(else) where the syntax demands a +single statement but you want to perform more than one action. Variables may be +declared using an optional @code(with) statement immediately after @code(begin). +For example: +@begin(example) +begin + with db = 12.0, + linear = db-to-linear(db) + print db, "dB represents a factor of", linear + set scale-factor = linear +end +@end(example) + +@paragraph(chdir) +@index(chdir, sal) +@code(chdir) @i(expression) + +The @code(chdir) statement changes the working directory. This statement +is provided for compatibility with Common Music SAL, but it really +should be avoided if you use jNyqIDE. The @i(expression) following the +@code(chdir) keyword should evaluate to a string that is a directory +path name. Note that literal strings themselves are valid expressions. +@begin(example) +chdir "/Users/rbd/tmp" +@end(example) + +@paragraph(define variable) +@index(global variables, sal)@index(define variable) +[@code(define)] @code(variable) @i(name) [= @i(expression)] {, @i(name) [= @i(expression)]}* + +Global variables can be declared and initialized. A list of variable names, +each with an optional initialization follows the @code(define variable) +keywords. (Since @code(variable) is a keyword, @code(define) is redundant +and optional in Nyquist SAL, but required in Common Music SAL.) +If the initialization part is omitted, the variable is initialized +to false. Global variables do not really need to be declared: just using the +name implicitly creates the corresponding variable. However, it is an error +to use a global variable that has not been initialized; +@code(define variable) is a good way to introduce a variable (or constant) +with an initial value into your program. + +@begin(example) +define variable transposition = 2, + print-debugging-info, @i(; initially false) + output-file-name = "salmon.wav" +@end(example) + +@paragraph(define function) +@index(function, sal)@index(define function) +[@code(define)] @code(function) @i(name) @code[(] [@i(parameter)], {, @i(parameter)}* @code[)] @i(statement) + +Before a function be called from an expression (as described above), it must +be defined. A function definition gives the function @i(name), a list of +@i(parameters), and a @i(statement). When a function is called, the actual +parameter expressions are evaluated from left to right and the formal parameters +of the function definition are set to these values. Then, @i(statement) is +evaluated. + +The formal parameters may be positional parameters that are matched with +actual parameters by position from left to right. Syntactically, these are +symbols and these symbols +are essentially local variables that exist only until @i(statement) completes +or a @code(return) statement causes the function evaluation to end. As in Lisp, +parameters are passed by value, so assigning a new value to a formal parameter +has no effect on the actual value. However, lists and arrays are not copied, +so internal changes to a list or array produce observable side effects. + +Alternatively, formal parameters may be keyword parameters. Here the @i(parameter) +is actually a pair: a keyword parameter, which is a symbol followed by a colon, +and a default value, given by any expression. Within the body of the function, +the keyword parameter is named by a symbol whose name matches the keyword +parameter except there is no final colon. +@begin(example) +define function foo(x: 1, y: bar(2, 3)) + display "foo", x, y + +exec foo(x: 6, y: 7) +@end(example) +In this example, @code(x) is bound to the value 6 and @code(y) is bound to +the value 7, so the example prints ``@code(foo : X = 6, Y = 7)''. Note that +while the keyword parameters are @code(x:) and @code(y:), the corresponding +variable names in the function body are @code(x) and @code(y), respectively. + +The @i(parameters) are meaningful only within the lexical (static) scope of +@i(statement). They are not accessible from within other +functions even if they are called by this function. + +Use a @code(begin)-@code(end) statement if the body of the function should +contain more than one statement or you need to define local variables. Use +a @code(return) statement to return a value from the function. If @i(statement) +completes without a @code(return), the value false is returned. + +@paragraph(display) +@index(display statement, sal) +@code(display) @i(string) {, @i(expression)}* + +The @code(display) statement is handy for debugging. At present, it is only +implemented in Nyquist SAL. When executed, @code(display) prints the @i(string) +followed by a colon and then, for each @i(expression), the expression and its +value are printed, after the last expression, a newline is printed. For example, +@begin(example) +display "In function foo", bar, baz +@end(example) +prints +@begin(example) +In function foo : bar = 23, baz = 5.3 +@end(example) +SAL may print the expressions using Lisp syntax, e.g. if the expression is +``bar + baz,'' do not be surprised if the output is ``@code[(sum bar baz) = 28.3].'' + +@paragraph(exec) +@index(exec statement, sal) +@code(exec) @i(expression) + +Unlike most other programming languages, you cannot simply type an expression as +a statement. If you want to evaluate an expression, e.g. call a function, +you must use an @code(exec) statement. The statement simply evaluates +the @i(expression). For example, +@begin(example) +exec set-sound-srate(22050.0) @i(; change default sample rate) +@end(example) + +@paragraph(if) +@index(if statement, sal) +@code(if) @i(test-expr) @code(then) @i(true-stmt) [@code(else) @i(false-stmt)] + +An @code(if) statement evaluates the expression @i(test-expr). If it is true, +it evaluates the statement @i(true-stmt). If false, the statement +@i(false-stmt) is evaluated. Use a @code(begin)-@code(end) statement +to evaluate more than one statement in then @code(then) or @code(else) +parts. + +@begin(example) +if x < 0 then x = -x @i(; x gets its absoute value) + +if x > upper-bound then + begin + print "x too big, setting to", upper-bound + x = upper-bound + end +else + if x < lower-bound then + begin + print "x too small, setting to", lower-bound + x = lower-bound + end +@end(example) +Notice in this example that the @code(else) part is another @code(if) +statement. An @code(if) may also be the @code(then) part of another +@code(if), so there could be two possible @code(if)'s with which to +associate an @code(else). An @code(else) clause always associates +with the closest previous @code(if) that does not already have an +@code(else) clause. + +@paragraph(when) +@code(when) @i(test) @i(statement) + +The @code(when) statement is similar to @code(if), but there is no @code(else) clause. + +@begin(example) +when *debug-flag* print "you are here" +@end(example) + +@paragraph(unless) +@code(unless) @i(test) @i(statement) + +The @code(unless) statement is similar to @code(when) (and @code(if)) but the +@i(statement) is executed when the @i(test) expression is @i(false). + +@begin(example) +unless count = 0 set average = sum / count +@end(example) + +@paragraph(load) +@index(load statement, sal) +@code(load) @i(expression) + +The @code(load) command loads a file named by @i(expression), which must +evauate to a string path name for the file. To load a file, SAL interprets +each statement in the file, stopping when the end of the file or an error +is encountered. If the file ends in @code(.lsp), the file is assumed to +contain Lisp expressions, which are evaluated by the XLISP interpreter. +In general, SAL files should end with the extension @code(.sal). + +@paragraph(loop) +@index(loop statement, sal) +@code(loop) [@i(with-stmt)] {@i(stepping)}* {@i(stopping)* @i(action)+ [@i(finally)] @code(end) + +The @code(loop) statement is by far the most complex statement in SAL, but +it offers great flexibility for just about any kind of iteration. The basic +function of a loop is to repeatedly evaluate a sequence of @i(action)'s which +are statements. Before the loop begins, local variables may be declared in +@i(with-stmt), a @code(with) statement. + +The @i(stepping) clauses do several +things. They introduce and initialize additional local variables similar +to the @i(with-stmt). +However, these local variables are updated to new values after the @i(action)'s. +In addition, some @i(stepping) clauses have associated stopping conditions, +which are tested on each iteration @i(before) evaluating the @i(action)'s. + +There are also @i(stopping) clauses that provide additional tests to +stop the iteration. These are also evaluated and tested +on each iteration before evaluating the @i(action)'s. + +When some @i(stepping) or @i(stopping) condition causes the iteration to stop, +the @i(finally) clause is evaluated (if present). Local variables and their +values can still be accessed in the @i(finally) clause. After the @i(finally) +clause, the @code(loop) statement completes. + +The @i(stepping) clauses are the following: +@begin(description) +@code(repeat) @i(expression)@\Sets the number of iterations to the value of @i(expression), which should be an integer (FIXNUM). + +@code(for) @i(var) = @i(expression) [ @code(then) @i(expr2) ]@\Introduces a new local +variable named @i(var) and initializes it to @i(expression). Before each subsequent +iteration, @i(var) is set to the value of @i(expr2). If the @code(then) part is +omitted, @i(expression) is re-evaluated and assigned to @i(var) +on each subsequent iteration. Note that this differs from a @i(with-stmt) where +expressions are evaluated and variables are only assigned their values once. + +@code(for) @i(var) @code(in) @i(expression)@\Evaluates @i(expression) to +obtain a list and creates a new local variable initialized to the first element +of the list. After each iteration, @i(var) is assigned the next element of the +list. Iteration stops when @i(var) has assumed all values from the list. If the +list is initially empty, the loop @i(action)'s are not evaluated (there are zero +iterations). + +@code(for) @i(var) [@code(from) @i(from-expr)] [[@code(to) | @code(below) | @code(downto) | @code(above)] @i(to-expr)] [@code(by) @i(step-expr)]@\Introduces a new local variable named @i(var) and intialized +to the value of the expression @i(from-expr) (with a default value of 0). After +each iteration of the loop, @i(var) is incremented by the value +of @i(step-expr) (with a default value of 1). +The iteration ends when @i(var) is greater than +the value of @i(to-expr) if there is a @code(to) clause, +greater than or equal to the value of @i(to-expr) +if there is a @code(below) clause, +less than the value of @i(to-expr) if there is a @code(downto) clause, +or less than or equal to the value of @i(to-expr) if there is a @code(above) +clause. (In the cases of @i(downto) and @i(above), the default increment value +is -1. If there +is no @code(to), @code(below), @code(downto), @code(above), or @code(below) clause, no interation stop test is created for this +stepping clause. +@end(description) + +The @i(stopping) clauses are the following: +@begin(description) +@code(while) @i(expression)@\The iterations are stopped when @i(expression) evaluates to @i(false). Anything not false is considered to mean true. + +@code(until) @i(expression)@\The iterations are stopped when @i(expression) evaluates to @i(true). +@end(description) + +The @i(finally) clause is defined as follows: +@index(finally clause, sal) +@begin(description) +@code(finally) @i(statement)@\The @i(statement) is evaluated when one of the +@i(stepping) or @i(stopping) clauses ends the loop. As always, @i(statement) may +be a @code(begin)-@code(end) statement. If an @i(action) evaluates a @code(return) +statement, the @code(finally) statement is not executed. +@end(description) + +@index(loop examples, sal)Loops often fall into common patterns, such as iteratiing a fixed number of +times, performing an operation on some range of integers, collecting results +in a list, and linearly searching for a solution. These forms are illustrated +in the examples below. + +@begin(example) +@i(; iterate 10 times) +loop + repeat 10 + print random(100) +end + +@i(; print even numbers from 10 to 20 +; note that 20 is printed. On the next iteration, +; i = 22, so i >= 22, so the loop exits.) +loop + for i from 10 to 22 by 2 + print i +end + +@i(; collect even numbers in a list) +loop + with lis + for i = 0 to 10 by 2 + set lis @@= i @i(; push integers on front of list,) + @i(; which is much faster than append,) + @i(; but list is built in reverse) + finally result = reverse(lis) +end +@i(; now, the variable result has a list of evens) + +@i(; find the first even number in a list) +result = #f @i(; #f means "false") +loop + for elem in lis + until evenp(elem) + finally result = elem +end +@i[; result has first even value in lis (or it is #f)] +@end(example) + +@paragraph(print) +@index(print statement, sal) +@code(print) @i(expr) {, @i(expr)}* + +The @code(print) statement prints the values separated by +spaces and followed by a newline. [Note that in the original +SAL, the newline is printed @i(before) the values, not after.] + + +@begin(example) +print "The value of x is", x +@end(example) + +@paragraph(return) +@index(return statement, sal) +@code(return) @i(expression) + +The @code(return) statement can only be used inside a function. It evaluates +@i(expression) and then the function returns the value of the expression +to its caller. + +@paragraph(set) +@index(set statement, sal) +@code(set) @i(var) @i(op) @i(expression) {, @i(var) @i(op) @i(expression)}* + +The @code(set) statement changes the value of a variable @i(var) according +to the operator @i(op) and the value of the @i(expression). The operators are: +@begin(description) +@code(=)@\The value of @i(expression) is assigned to @i(var). + +@index(+=)@code(+=)@\The value of @i(expression) is added to @i(var). + +@index(*=)@code(*=)@\The value of @i(var) is multiplied by the value of the expression. + +@index(&=)@code(&=)@\The value of @i(expression) is inserted as the last element of +the list referenced by @i(var). If @i(var) is the empty list (denoted by @code(#f)), +then @i(var) is assigned a newly constructed list of one element, the value +of @i(expression). + +@index(^=)@code(^=)@\The value of @i(expression), a list, is appended to the list referenced +by @i(var). If @i(var) is the empty list (denoted by @code(#f)), then @i(var) +is assigned the (list) value of @i(expression). + +@index(@@=)@code(@@=)@\Pushes the value of @i(expression) onto the front of the list +referenced by @i(var). If @i(var) is empty (denoted by @code(#f)), then @i(var) +is assigned a newly constructed list of one element, the value of @i(expression). + +@index(<=)@code(<=)@\Sets the new value of @i(var) to the minimum of the old value +of @i(var) and the value of @i(expression). + +@index(>=)@code(>=)@\Sets the new value of @i(var) to the maximum of the old value +of @i(var) and the value of @i(expression). +@end(description) + +@begin(example) +@i(; example from Rick Taube's SAL description) +loop + with a, b = 0, c = 1, d = {}, e = {}, f = -1, g = 0 + for i below 5 + set a = i, b += 1, c *= 2, d &= i, e @@= i, f <= i, g >= i + finally display "results", a, b, c, d, e, f, g +end +@end(example) + +@paragraph(with) +@index(with statement, sal) +@code(with) @i(var) [= @i(expression)] {, @i(var) [= @i(expression)]}* + +The @code(with) statement declares and initializes local variables. It +can appear only after @code(begin) or @code(loop). If the @i(expression) is +omitted, the initial value is @i(false). The variables are visible only +inside the @code(begin)-@code(end) or @code(loop) statement where the +@code(with) statement appears. Even in @code(loop)'s the variables +are intialized only when the loop is entered, not on each iteration. + +@paragraph(exit) +@index(exit statement, sal) +@code(exit) [@code(nyquist)] + +The @code(exit) statement is unique to Nyquist SAL. It returns from SAL +mode to the XLISP interpreter. (Return to SAL mode by typing ``@code[(sal)]''). +If @code(nyquist) is included in the statement, then the entire Nyquist +process will exit. + +@section(Interoperability of SAL and XLISP) +@index(sal and lisp)@index(interoperability, sal and lisp) +@label(sal-vs-lisp-section) +When SAL evaluatas command or loads files, it translates SAL into XLISP. +You can think of SAL as a program that translates everything you write +into XLISP and entering it for you. Thus, when you define a SAL function, +the function actually exists as an XLISP function (created using +Lisp's @code(defun) special form). When you set or evaluate global variables +in SAL, these are exactly the same Lisp global variables. Thus, XLISP +functions can call SAL functions and vice-versa. At run time, +everything is Lisp. + +@subsection(Function Calls) +In general, there is a very simple translation from SAL to Lisp syntax +and back. A function call is SAL, for example, +@begin(example) +osc(g4, 2.0) +@end(example) +is translated to Lisp by moving the open parenthesis in front of the +function name and removing the commas: +@begin(example) +(osc g4 2.0) +@end(example) +Similarly, if you want to translate a Lisp function call to SAL, just +reverse the translation. + +@subsection(Symbols and Functions) +SAL translates keywords with trailing colons (such as @code(foo:)) +into Lisp keywords with leading colons (such as @code(:foo)), but +SAL keywords are not treated as expressions as they are in Lisp. +You cannot write @code[open("myfile.txt", direction: output:)] +because SAL expects an expression after direction. A special form +@code(keyword) is defined to generate a Lisp keyword as an +expression. The argument is the keyword @i(without) a colon, e.g. +@code[open("myfile.txt", direction: keyword(output))]. Alternatively, +you can write the Lisp-style keyword with the leading colon, e.g. +@code[open("myfile.txt", direction: :output)]. + +In Nyquist SAL, the hash character (#), can be used as a prefix to a +Lisp function name. For example, the following command is not legal +because @code(print) is a SAL command name, not a legal function name: +@code[set v = append(print(a), print(b))]. (Here the intent is to print +arguments to append). However, you can use the hash character to access +the Lisp @code(print) function: @code[set v = append(#print(a), #print(b))]. + +@subsection(Playing Tricks On the SAL Compiler) +In many cases, the close coupling between SAL and XLISP gives SAL +unexpected expressive power. A good example is @code(seqrep). This +is a special looping construct in Nyquist, implemented as a macro in +XLISP. In Lisp, you would write something like: +@begin(example) +(seqrep (i 10) (pluck c4)) +@end(example) +One might expect SAL would have to define a special @code(seqrep) +statement to express this, but since statements do not return values, +this approach would be problematic. The solution (which is already +fully implemented in Nyquist) is to define a +new macro @code(sal-seqrep) that is equivalent to @code(seqrep) +except that it is called as follows: +@begin(example) +(sal-seqrep i 10 (pluck c4)) +@end(example) +The SAL compiler automatically translates the identifier @code(seqrep) to + @code(sal-seqrep). Now, in SAL, you can just write +@begin(example) +seqrep(i, 10, pluck(c4)) +@end(example) +which is translated in a pretty much semantics-unaware fashion to +@begin(example) +(sal-seqrep i 10 (pluck c4)) +@end(example) +and viola!, we have Nyquist control constructs in SAL even though SAL +is completely unaware that @code(seqrep) is actually a special form. + +@chapter(Nyquist Functions) +@label(lisp-chap) +This chapter provides a language reference for Nyquist. Operations +are categorized by functionality and abstraction level. +Nyquist is implemented in two important levels: the ``high level'' supports +behavioral abstraction, which means that operations like @code(stretch) and +@code(at) can be applied. These functions are the ones that typical users +are expected to use, and most of these functions are written in XLISP. + +The ``low-level'' primitives directly operate on sounds, but know nothing of +environmental variables (such as @code(*warp*), etc.). The +names of most of these low-level functions start with ``@code(snd-)''. In +general, programmers should avoid any function with the ``@code(snd-)'' +prefix. Instead, use the ``high-level'' functions, which know about the +environment and react appropriately. The names of high-level functions +do not have prefixes like the low-level functions. + +There are certain low-level operations that apply directly to sounds (as +opposed to behaviors) and are relatively ``safe'' for ordinary use. These +are marked as such. + +Nyquist uses both linear frequency and equal-temperament pitch numbers to +specify repetition rates. Frequency is always specified in either cycles +per second (hz), or pitch numbers, also referred to as ``steps,'' as in +steps of the chromatic scale. Steps are floating point numbers such that 60 += Middle C, 61 = C#, 61.23 is C# plus 23 cents, etc. The mapping from pitch +number to frequency is the standard exponential conversion, and fractional +pitch numbers are allowed: +@pragma(startscribe) +@math[frequency = 440 @mult 2@+{(pitch - 69)/12}]. +@pragma(endscribe) +@html[@center{frequency = 440 * 2^((pitch - 69)/12)}] +There are many +predefined pitch names. By default these are tuned in equal temperament, +with A4 = 440Hz, but these may be changed. (See Section @ref(constants-sec)). + +@section(Sounds)@index(Sounds) +A sound is a primitive data type in Nyquist. Sounds can be created, passed +as parameters, garbage collected, printed, and set to variables just like +strings, atoms, numbers, and other data types. + +@subsection(What is a Sound?) +Sounds have 5 components: +@begin(itemize) +@code(srate@index(srate)) @itemsep the sample rate of the sound. + +@code(samples@index(samples)) @itemsep the samples. + +@code(signal-start@index(signal-start)) @itemsep the time of the first sample. + +@code(signal-stop@index(signal-stop)) @itemsep the time of one past the last sample. + +@code(logical-stop@index(logical-stop)) @itemsep the time at which the sound logically ends, e.g. a +sound may end at the beginning of a decay. This value defaults +to @code(signal-stop), +but may be set to any value. +@end(itemize) +It may seem that there should be @code(logical-start) to indicate the +logical or perceptual beginning of a sound as well as a @code(logical-stop) +to indicate the logical ending of a sound. In practice, only +@code(logical-stop) is needed; this attribute tells when the next sound +should begin to form a sequence of sounds. In this respect, Nyquist sounds +are asymmetric: it is possible to compute sequences forward in time by +aligning the logical start of each sound with the @code(logical-stop) of the +previous one, but one cannot compute ``backwards'', aligning the logical end +of each sound with the logical start of its successor. The root of this +asymmetry is the fact that when we invoke a behavior, we say when to start, +and the result of the behavior tells us its logical duration. There is no +way to invoke a behavior with a direct specification of when to +stop@foot(Most behaviors will stop at time 1, warped according to @code(*warp*) to some real time, but this is by convention and is not a direct specification.). + +@p(Note:) there is no way to enforce the +intended ``perceptual'' interpretation of +@code(logical-stop). As far as Nyquist is concerned, these are just numbers to +guide the alignment of sounds within various control constructs. + +@subsection(Multichannel Sounds) +@index(Multichannel Sounds) +Multichannel sounds are represented by Lisp arrays of sounds. To create an +array of sounds the XLISP @code(vector) function is useful. Most low-level +Nyquist functions (the ones starting with @code(snd-)) do not operate on +multichannel sounds. Most high-level functions do operate on multichannel +sounds. + +@subsection(Accessing and Creating Sound) +@label(flatten-sec) +@label(snd-srate-sec) + +Several functions display information concerning a sound and can be used to +query the components of a sound. There are functions that access samples in +a sound and functions that construct sounds from samples. + +@begin(fndefs) +@codef[sref(@pragma(defn)@index(sref)@indexSecondary(primary="sound", +secondary="accessing point")@i(sound), @i(time))]@\Accesses @i(sound) at +the point @i(time), which is a local time. If @i(time) does not +correspond to a sample time, then the nearest samples are linearly +interpolated to form the result. To access a particular sample, either +convert the sound to an array (see @code(snd-samples) below), or use +@code(snd-srate) and @code(snd-t0) (see below) to find the sample rate +and starting time, and compute a time (@i(t)) from the sample number (@i(n)): +@pragma(startscribe) +@begin(math) +t = (n / srate) + t0 +@end(math) +@pragma(endscribe) +@html[
t = (n / srate) + t0
] +Thus, the lisp code to access the n@+(th) sample of a sound would look like: +@begin(code) +(sref sound (global-to-local (+ (/ n (snd-srate sound)) (snd-t0 sound)))) +@end(code) +Here is why @code(sref) interprets its time argument as a local time: +@begin(example) +> (sref (ramp 1) 0.5) @i(; evaluate a ramp at time 0.5) +0.5 +> (at 2.0 (sref (ramp 1) 0.5)) @i(; ramp is shifted to start at 2.0) + @i(; the time, 0.5, is shifted to 2.5) +0.5 +@end(example) +If you were to use @code(snd-sref), which treats time as global, instead of @code(sref), which treats time as local, then the first example above would return the same answer (0.5), but the second example would return 0. Why? Because the @code[(ramp 1)] behavior would be shifted to start at time 2.0, but the resulting sound would be evaluated at global time 0.5. By definition, sounds have a value of zero before their start time. + +@codef[sref-inverse(@pragma(defn)@index(sref-inverse)@i(sound), @i(value))]@\Search @i(sound) for the first point at which it achieves @i(value) and return the corresponding (linearly interpolated) time. If no inverse exists, an error is raised. This function is used by Nyquist in the implementation of time warping. + +@label(snd-from-array-sec) +@codef[snd-from-array(@IndexSecondary(primary="sound", + secondary = "creating from array")@pragma(defn)@index(snd-from-array)@i(t0), @i(sr), +@i(array))]@\Converts a lisp array of @code(FLONUM)s into a sound with starting +time @i(t0) and sample rate @i(sr). Safe for ordinary use. Be aware that +arrays of floating-point samples use 14 bytes per sample, and an additional +4 bytes per sample are allocated by this function to create a sound type. + +@codef[snd-fromarraystream(@pragma(defn)@index(snd-fromarraystream)@i(t0), @i(sr), @i(object))]@\Creates a sound for which samples come from +@i(object). The starting time is @i(t0) (a @code(FLONUM)), and the sample rate is +@i(sr). The @i(object) is an XLISP object (see Section @ref(objects-sec) for +information on objects.) A sound is returned. When the sound needs samples, +they are generated by sending the message @code(:next) to @i(object). If +@i(object) returns @code(NIL), the sound terminates. Otherwise, @i(object) +must return an array of @code(FLONUM)s. The values in these arrays are +concatenated to form the samples of the resulting sound. +There is no provision for @i(object) to specify the +logical stop time of the sound, so the logical stop time is the termination +time. + +@codef[snd-fromobject(@pragma(defn)@index(snd-fromobject)@index(sound from Lisp data)@i(t0), @i(sr), @i(object))]@\Creates a sound for which samples come from +@i(object). The starting time is @i(t0) (a @code(FLONUM)), and the sample rate is +@i(sr). The @i(object) is an XLISP object (see Section @ref(objects-sec) for +information on objects. A sound is returned. When the sound needs samples, +they are generated by sending the message @code(:next) to @i(object). If +@i(object) returns @code(NIL), the sound terminates. Otherwise, @i(object) +must return a @code(FLONUM). There is no provision for @i(object) to specify the +logical stop time of the sound, so the logical stop time is the termination +time. + +@codef[snd-extent(@pragma(defn)@index(snd-extent)@i(sound), @i(maxsamples))]@\Returns a list of two numbers: the starting time of @i(sound) and the terminate time of @i(sound). Finding the terminate time requires that samples be computed. Like most Nyquist functions, this is non-destructive, so memory will be allocated to preserve the sound samples. If the sound is very long or infinite, this may exhaust all memory, so the @i(maxsamples) parameter specifies a limit on how many samples to compute. If this limit is reached, the terminate time will be (incorrectly) based on the sound having @i(maxsamples) samples. This function is safe for ordinary use. + +@codef[snd-fetch(@index(access samples)@index(samples, +reading)@pragma(defn)@index(snd-fetch)@index(read samples)@i(sound))]@\Reads samples +sequentially from @i(sound). This returns a @code(FLONUM) after each call, or +@code(NIL) when @i(sound) terminates. @p(Note:) @code(snd-fetch) modifies +@i(sound); it is strongly recommended to copy @i(sound) using +@code(snd-copy) and access only the copy with @code(snd-fetch). + +@codef[snd-fetch-array(@pragma(defn)@index(snd-fetch-array)@i(sound), @i(len), +@i(step))]@\Reads sequential arrays of samples from @i(sound), returning +either an array of @code(FLONUM)s or @code(NIL) when the sound terminates. The +@i(len) parameter, a @code(FIXNUM), indicates how many samples should be returned +in the result array. After the array is returned, @i(sound) is modified by +skipping over @i(step) (a @code(FIXNUM)) samples. If @i(step) equals @i(len), then +every sample is returned once. If @i(step) is less than @i(len), each +returned array will overlap the previous one, so some samples will be +returned more than once. If @i(step) is greater than @i(len), then some +samples will be skipped and not returned in any array. The @i(step) +and @i(len) may change at each call, but in the current implementation, an +internal buffer is allocated for @i(sound) on the first call, so subsequent +calls may not specify a greater @i(len) than the first. @p(Note:) +@code(snd-fetch-array) modifies +@i(sound); it is strongly recommended to copy @i(sound) using +@code(snd-copy) and access only the copy with @code(snd-fetch-array). + +@codef[snd-flatten(@pragma(defn)@index(snd-flatten)@i(sound), @i(maxlen))]@\This function is identical +to @code(snd-length). You would use this function to force samples to be computed in memory. Normally, this is not a good thing to do, but here is one appropriate use: In the case of sounds intended for wavetables, the unevaluated +sound may be larger than the evaluated (and typically short) one. +Calling @code(snd-flatten) will compute the samples and allow the unit generators to be freed in the next garbage collection. @p(Note:) If a sound is computed from many instances of table-lookup oscillators, calling @code(snd-flatten) will free the oscillators and their tables. Calling @code[(stats)] will print how many total bytes have been allocated to tables. + + @codef[snd-length(@pragma(defn)@index(snd-length)@i(sound), @i(maxlen))]@\Counts the +number of samples in @i(sound) up to the physical stop time. If the sound +has more than @i(maxlen) samples, @i(maxlen) is returned. Calling this +function will cause all samples of the sound to be computed and saved in +memory (about 4 bytes per sample). Otherwise, this function is safe for ordinary use. + + @codef[snd-maxsamp(@pragma(defn)@index(snd-maxsamp)@i(sound))]@\Computes the maximum of +the absolute value of the samples in @i(sound). Calling this function will +cause samples to be computed and saved in memory. (This function should +have a @i(maxlen) parameter to allow self-defense against sounds that would +exhaust available memory.) Otherwise, this function is safe for ordinary use. +This function will probably be removed in a future version. See @code(peak), a replacement (@pragma(startref) page @pageref(peak-sec)). + + + @codef[snd-play(@pragma(defn)@index(snd-play)@i(expression))]@\Evaluates @i(expression) +to obtain a sound or array of sounds, computes all of the samples (without +retaining them in memory), and returns. Originally, this was a placeholder +for a facility to play samples directly to an audio output device, but +playback is now accomplished by @code(s-save). +Meanwhile, since this +function does not save samples in memory or write them to a disk, it is +useful in determining how much time is spent calculating samples. See +@code(s-save) (Section @ref(s-save-sec)) for saving samples to a file, and + @code(play) (Section @ref(play-sec)) to play a sound. This function is +safe for ordinary use. + +@codef[snd-print-tree(@pragma(defn)@index(snd-print-tree)@i(sound))]@\Prints an ascii +representation of the internal data structures representing a sound. This +is useful for debugging Nyquist. This function is +safe for ordinary use. + + @codef[snd-samples(@index(samples)@pragma(defn)@index(snd-samples)@index(array from sound)@index(convert sound to array)@i(sound), @i(limit))]@\Converts the +samples into a lisp array. The data is taken directly from the samples, +ignoring shifts. For example, if the sound starts at 3.0 seconds, the first +sample will refer to time 3.0, not time 0.0. A maximum of @i(limit) samples +is returned. This function is safe for ordinary use, but like +@code(snd-from-array), it requires a total of slightly over 18 bytes per +sample. + + @codef[snd-srate(@pragma(defn)@index(snd-srate)@i(sound))]@\Returns the sample rate of +the sound. Safe for ordinary use. + +@begin(comment) + @codef[snd-show(@pragma(defn)@index(snd-show)@i(sound))]@\Print the entire (internal) +structure of the sound for debugging. Safe for ordinary use. +@end(comment) + +@codef[snd-time(@pragma(defn)@index(snd-time)@i(sound))]@\Returns the start time of the +sound. This will probably go away in a future version, so use @code(snd-t0) +instead. + +@codef[snd-t0(@pragma(defn)@index(snd-t0)@i(sound))]@\Returns the time of the +first sample of the sound. Note that Nyquist operators such as add always +copy the sound and are allowed to shift the copy up to one half sample +period in either direction to align the samples of two operands. Safe for +ordinary use. + +@codef[snd-print(@pragma(defn)@index(snd-print)@i(expression), @i(maxlen))]@\Evaluates +@i(expression) to yield a sound or an array of sounds, then prints up to +@i(maxlen) samples to the screen (stdout). This is similar to +@code(snd-save), but samples appear in text on the screen instead of in +binary in a file. This function is intended for debugging@index(debugging). +Safe for ordinary use. + + @codef[snd-set-logical-stop(@pragma(defn)@index(snd-set-logical-stop)@i(sound), +@i(time))]@\Returns a sound which is +@i(sound), except that the logical stop of the sound occurs at @i(time). + @p(Note:) do not call this function. When defining a behavior, use +@code(set-logical-stop) or @code(set-logical-stop-abs) instead. + +@codef[snd-sref(@pragma(defn)@index(snd-sref)@i(sound), @i(time))]@\Evaluates @i(sound) +at the global time given by @i(time). Safe for ordinary use, but normally, you should +call @code(sref) instead. + + @codef[snd-stop-time(@pragma(defn)@index(snd-stop-time)@i(sound))]@\Returns the stop time of @i(sound). +Sounds can be ``clipped'' or truncated at a particular time. This function +returns that time or MAX-STOP-TIME if he programmer has not specified a stop +time for the sound. Safe for ordinary use. + +@codef[soundp(@pragma(defn)@index(soundp)@i(sound))]@\Returns true iff @i(sound) is a +SOUND. Safe for ordinary use. + +@codef[stats(@pragma(defn)@index(stats)@index(memory usage)@index(table memory))]@\Prints the memory usage status. See also the +XLISP @code(mem) function. Safe for ordinary use. This is the only way to find out how much memory is being used by table-lookup oscillator instances. + +@end(fndefs) + +@subsection(Miscellaneous Functions) +These are all safe and recommended for ordinary use. + +@begin(fndefs) +@codef[db-to-linear(@pragma(defn)@index(db-to-linear)@i(x))]@\Returns the conversion of @i(x) from decibels to linear. 0dB is converted to 1. 20dB represents a linear factor of 10. If @i(x) is a sound, each sample is converted and a sound is returned. If @i(x) is a multichannel sound, each channel is converted and a multichannel sound (array) is returned. @p(Note:) With sounds, conversion is only performed on actual samples, not on the implicit zeros before the beginning and after the termination of the sound. Sample rates, start times, etc. are taken from @i(x). + +@codef[follow(@pragma(defn)@index(follow)@index(envelope follower)@index(compressor)@index(limiter)@i(sound), @i(floor), @i(risetime), @i(falltime), @i(lookahead))]@\An envelope follower intended as a commponent for compressor and limiter functions. The basic goal of this function is to generate a smooth signal +that rides on the peaks of the input signal. The usual objective is to +produce an amplitude envelope given a low-sample rate (control rate) +signal representing local RMS measurements. The first argument is the +input signal. The @i(floor) is the minimum output value. The @i(risetime) +is the time (in seconds) it takes for the output to rise (exponentially) +from @i(floor) to unity (1.0) and the @i(falltime) is the time it takes +for the output to fall (exponentially) from unity to @i(floor). The +algorithm looks ahead for peaks and will begin to increase the output +signal according to @i(risetime) in anticipation of a peak. The amount +of anticipation (in seconds) is given by @i(lookahead). The algorithm +is as follows: the output value is allowed to increase according to +@i(risetime) or decrease according to @i(falltime). If the next input +sample is in this range, that sample is simply output as the next output +sample. If the next input sample is too large, the algorithm goes back in +time as far as necessary to compute an envelope that rises according to +@i(risetime) to meet the new value. The algorithm will only work backward +as far as @i(lookahead). If that is not far enough, then there is a final +forward pass computing a rising signal from the earliest output sample. In +this case, the output signal will be at least momentarily less than the +input signal and will continue to rise exponentially until it intersects +the input signal. If the input signal falls faster than indicated by +@i(falltime), the output fall rate will be limited by @i(falltime), +and the fall in output will stop when the output reaches @i(floor). +This algorithm can make two passes througth the buffer on sharply rising +inputs, so it is not particularly fast. With short buffers and low sample +rates this should not matter. See @code(snd-avg) for a function that +can help to generate a low-sample-rate input for @code(follow). +See @code(snd-chase) in Section @ref(snd-chase-sec) for a related filter. + +@label(gate-sec) +@codef[gate(@pragma(defn)@index(gate)@index(noise-gate)@i(sound), +@i(lookahead), @i(risetime), @i(falltime), @i(floor), +@i(threshold))]@\Generate an exponential rise and decay intended +for noise gate implementation. The decay starts when the signal drops +below @i(threshold) and stays there for longer than @i(lookahead) (a +@code(FLONUM) in seconds). (The signal begins to drop when the signal +crosses @i(threshold), not after @i(lookahead).) Decay continues until +the value reaches @i(floor) (a @code(FLONUM)), at which point the decay +stops and the output value is held constant. Either during the decay or +after the floor is reached, if the signal goes above @i(threshold), then +the ouptut value will rise to unity (1.0) at the point the signal crosses +the threshold. Because of internal lookahead, the signal actually begins +to rise before the signal crosses @i(threshold). The rise is a +constant-rate exponential and set so that a rise from @i(floor) to unity +occurs in @i(risetime). Similary, the fall is a constant-rate exponential +such that a fall from unity to @i(floor) takes @i(falltime). + +@codef[hz-to-step(@pragma(defn)@index(hz-to-step)@i(freq))]@\Returns a step number for @i(freq) (in hz), which can be either a number of a @code(SOUND). The result has the same type as the argument. See also @code(step-to-hz) (below). + +@codef[linear-to-db(@pragma(defn)@index(linear-to-db)@i(x))]@\Returns the conversion of @i(x) from linear to decibels. 1 is converted to 0. 0 is converted to -INF (a special IEEE floating point value.) A factor of 10 represents a 20dB change. If @i(x) is a sound, each sample is converted and a sound is returned. If @i(x) is a multichannel sound, each channel is converted and a multichannel sound (array) is returned. @p(Note:) With sounds, conversion is only performed on actual samples, not on the implicit zeros before the beginning and after the termination of the sound. Start times, sample rates, etc. are taken from @i(x). + +@codef[log(@index(log function)@pragma(defn)@index(log)@i(x))]@\Calculates the natural log of @i(x) (a @code(FLONUM)). (See @code(s-log) for a version that operates on signals.) + +@codef[set-control-srate(@pragma(defn)@index(set-control-srate)@index(sampling rate)@i(rate))]@\Sets the default sampling rate for control signals to @i(rate) by setting @code(*default-control-srate*) and reinitializing the environment. Do not call this within any synthesis function (see the @code(control-srate-abs) transformation, Section @ref(control-srate-abs-sec)). + +@codef[set-sound-srate(@pragma(defn)@index(set-sound-srate)@index(sampling rate)@i(rate))]@\Sets the default sampling rate for audio signals to @i(rate) by setting @code(*default-sound-srate*) and reinitializing the environment. Do not call this within any synthesis function (see the @code(sound-srate-abs) transformation, Section @ref(sound-srate-abs-sec)). + +@codef[set-pitch-names(@pragma(defn)@index(set-pitch-names))]@\Initializes pitch variables (@code(c0), @code(cs0), @code(df0), @code(d0), ... @code(b0), @code(c1), ... @code(b7)). A440 (the default tuning) is represented by the step 69.0, so the variable @code(a4) (fourth octave A) is set to 69.0. You can change the tuning by setting @code(*A4-Hertz*)@index(tuning)@index(A440)@index(*A4-Hertz*) to a value (in Hertz) and calling @code(set-pitch-names) to reinitialize the pitch variables. Note that this will result in non-integer step values. It does not alter the mapping from step values to frequency. There is no built-in provision for stretched scales or non-equal temperament, although users can write or compute any desired fractional step values. + + @codef[step-to-hz(@pragma(defn)@index(step-to-hz)@i(pitch))]@\Returns a frequency in hz +for @i(pitch), a step number or a @code(SOUND) type representing a time-varying step number. The result is a @code(FLONUM) if @i(pitch) is a number, and a @code(SOUND) if @i(pitch) is a @code(SOUND). See also @code(hz-to-step) (above). + + +@codef{get-duration(@pragma(defn)@index(get-duration)@i(dur))}@\Gets the actual duration of of something starting at a local time of 0 and ending at a local time of @i(dur) times the current sustain. For convenience, @code(*rslt*) is set to the global time corresponding to local time zero. + +@codef{get-loud(@pragma(defn)@index(get-loud))}@\Gets the current value of the @code(*loud*) environment variable. If @code(*loud*) is a signal, it is evaluated at local time 0 and a number (@code(FLONUM)) is returned. + +@codef{get-sustain(@pragma(defn)@index(get-sustain))}@\Gets the current value of the @code(*sustain*) environment variable. If @code(*sustain*) is a signal, it is evaluated at local time 0 and a number (@code(FLONUM)) is returned. + +@codef{get-transpose(@pragma(defn)@index(get-transpose))}@\Gets the current value of the @code(*transpose*) environment variable. If @code(*transpose*) is a signal, it is evaluated at local time 0 and a number (@code(FLONUM)) is returned. + +@codef{get-warp(@pragma(defn)@index(get-warp))}@\Gets a function corresponding to the current value of the @code(*warp*) environment variable. For efficiency, @code(*warp*) is stored in three parts representing a shift, a scale factor, and a continuous warp function. @code(Get-warp) is used to retrieve a signal that maps logical time to real time. This signal combines the information of all three components of @code(*warp*) into a single signal. If the continuous warp function component is not present (indicating that the time warp is a simple combination of @code(at) and @code(stretch) transformations), an error is raised. This function is mainly for internal system use. In the future, @code(get-warp) will probably be reimplemented to always return a signal and never raise an error. + +@codef{local-to-global(@pragma(defn)@index(local-to-global)@i(local-time))}@\Converts a score (local) time to a real (global) time according to the current environment. + +@codef{osc-enable(@pragma(defn)@index(osc-enable)@index(osc)@index(open sound control)@i(flag))}@\Enable or disable Open Sound Control. +(See Appendix @ref(osc-app).) +Enabling creates a socket and a service that listens for UDP +packets on port 7770. Currently, only two messages are accepted +by Nyquist. The first is of the form @code(/slider) +with an integer index and a floating point value. These set internal +slider values accessed by the @code(snd-slider) +function. The second is of the form @code(/wii/orientation) with +two floating point values. This message is a special case to +support the DarwiinRemoteOsc@index(DarwiinRemoteOsc) program + which can relay data from +a Nintendo@index(Nintendo WiiMote) WiiMote@index(Wii Controller) + device to Nyquist via OSC. The two orientation +values control sliders 0 and 1. +Disabling terminates the service (polling for messages) +and closes the socket. The @i(previous) state of enablement +is returned, e.g. if OSC is enabled and @i(flag) is @i(nil), +OSC is disabled and @code(T) (true) is returned because OSC +was enabled at the time of the call. This function only exists +if Nyquist is compiled with the compiler flag @code(OSC). +Otherwise, the function +exists but always returns the symbol @code(DISABLED). Consider +lowering the audio latency using @code(snd-set-latency). +@i(Warning:) there is the potential for +network-based attacks using OSC. It is tempting to add the +ability to evaluate XLISP expressions sent via OSC, but +this would create +unlimited and unprotected access to OSC clients. For now, +it is unlikely that an attacker could do more than +manipulate slider values. + +@codef{snd-set-latency(@index(latency)@pragma(defn)@index(snd-set-latency)@i(latency))}@\Set the latency requested when Nyquist plays sound to + @i(latency), a @code(FLONUM). The previous value is returned. The default is 0.3 seconds. To avoid glitches, the latency should be +greater than the time required for garbage collection and message printing and any other system activity external to Nyquist. +@end(fndefs) + +@section(Behaviors)@index(Behaviors) +@label(behavior-sec) + +@subsection(Using Previously Created Sounds) +@label(use-sounds-sec) +These behaviors take a sound and transform that sound according to the +environment. These are useful when writing code to make +a high-level function from a low-level function, or when cuing sounds +which were previously created: +@begin(fndefs) +@codef[cue(@pragma(defn)@index(cue)@i(sound))]@\Applies @code(*loud*), the starting time from @code(*warp*), @code(*start*), + and @code(*stop*) to @i(sound). + +@codef[cue-file(@pragma(defn)@index(cue-file)@i(filename))]@\Same as @code(cue), except +the sound comes from the named file, samples from which are coerced to the current default @code(*sound-srate*) sample rate. + +@codef[sound(@pragma(defn)@index(sound)@i(sound))]@\Applies @code(*loud*), @code(*warp*), +@code(*start*), and @code(*stop*) to @i(sound). + +@codef[control(@pragma(defn)@index(control)@i(sound))]@\This function is identical to +@code(sound), but by convention is used when @i(sound) is a control signal +rather than an audio signal. +@end(fndefs) + +@subsection(Sound Synthesis) + +These functions provide musically interesting creation behaviors that +react to their environment; these are the ``unit generators'' of Nyquist: + +@begin(fndefs) +@codef{const(@pragma(defn)@index(const)@index(constant function)@i(value)[ ,@i(duration)])}@\Creates a constant function at the @code(*control-srate*). Every sample has the given @i(value), and the default @i(duration) is 1.0. See also @code(s-rest), which is equivalent to calling @code(const) with zero, and note that you can pass scalar constants (numbers) to @code(sim), @code(sum), and @code(mult) where they are handled more efficiently than constant functions. + +@codef{env(@pragma(defn)@index(env)@i(t@-[1]), @i(t@-[2]), @i(t@-[4]), @i(l@-[1]), @i(l@-[2]), @i(l@-[3]), +[@i(dur)])}@\Creates a 4-phase envelope. +@i(t@-[@i(i)]) is the duration of phase @i(i), and @i(l@-[@i(i)]) +is the final level of phase @i(i). @i(t@-[3]) is implied by the duration +@i(dur), and @i(l@-[4]) is @code(0.0). If @i(dur) is not supplied, then +@code(1.0) is assumed. The envelope duration is the product of @i(dur), +@code(*stretch*), and @code(*sustain*). If +@i(t@-[1]) + @i(t@-[2]) + 2ms + @i(t@-[4]) is greater than the envelope +duration, then a two-phase envelope is +substituted that has an attack/release time ratio of @i(t@-[1])/@i(t@-[4]). +The sample rate of the returned sound is @code(*control-srate*). (See +@code(pwl) for a more general piece-wise linear function generator.) +The effect of time warping is to warp the starting time and ending time. +The intermediate breakpoints are then computed as described above. + + +@codef{exp-dec(@pragma(defn)@index(exp-dec)@index(exponential envelope)@i(hold), @i(halfdec), @i(length))}@\This convenient envelope shape is a special case of @code(pwev) (see Section @ref(pwev-sec)). The envelope starts at 1 and is constant for @i(hold) seconds. It then decays with a half life of @i(halfdec) seconds until @i(length). (The total duration is @i(length).) In other words, the amplitude falls by half each @i(halfdec) seconds. When stretched, this envelope scales linearly, which means the hold time increases and the half decay time increases. + + +@label(force-srate-sec) +@codef{force-srate(@pragma(defn)@index(force-srate)@index(sample rate, forcing)@index(resampling)@i(srate), @i(sound))}@\Returns a sound which is up- or +down-sampled to @i(srate). Interpolation is linear, and no prefiltering is +applied in the down-sample case, so aliasing may occur. See also +@code(resample). + + +@codef{lfo(@pragma(defn)@index(lfo)@index(low-frequency oscillator)@i(freq)[ ,@i(duration), @i(table), @i(phase)])}@\Just +like @code(osc) (below) +except this computes at the @code(*control-srate*) and frequency +is specified in Hz. Phase is specified in degrees. + The @code(*transpose*) and @code(*sustain*) is not +applied. The effect of time warping is to warp the starting and ending +times. The signal itself will have a constant unwarped frequency. + +@codef{fmlfo(@pragma(defn)@index(fmlfo)@i(freq)[ ,@i(table), @i(phase)])}@\A low-frequency oscillator +that computes at the @code(*control-srate*) using a sound to specify a time-varying +frequency in Hz. Phase is a @code(FLONUM) in degrees. The duration of the result is determined by @i(freq). + +@codef{maketable(@pragma(defn)@index(maketable)@label(maketable)@i(sound))}@\Assumes that +the samples in @i(sound) constitute one period of a wavetable, and returns a wavetable +suitable for use as the @i(table) argument to the @code(osc) function (see +below). Currently, tables are limited to 1,000,000 samples. This limit is the compile-time constant @code(max_table_len) set in @code(sound.h). + +@codef{build-harmonic(@pragma(defn)@index(build-harmonic)@index(harmonic)@i(n), @i(table-size))}@\Intended for +constructing wavetables@index(wavetables)@index(waveforms), this function returns a sound of length @i(table-size) +samples containing @i(n) periods of a sinusoid. These can be scaled and +summed to form a waveform with the desired harmonic content. See @pragma(startref) page @pageref(build-harmonic-example) for an example. + +@codef{control-warp(@pragma(defn)@index(control-warp)@i(warp-fn), @i(signal), [@i(wrate)])}@\Applies a +warp function @i(warp-fn) to @i(signal) using function composition. If @i(wrate) is omitted, linear +interpolation is used. @i(warp-fn) is a mapping from score (logical) time +to real time, and @i(signal) is a function from score time to real values. +The result is a function from real time to real values at a sample rate of +@code(*control-srate*). See @code(sound-warp) for an explanation of +@i(wrate) and high-quality warping. + +@label(mult-sec) +@codef{mult(@pragma(defn)@index(mult)@i(beh@-[1]), @i(beh@-[2]), ...)}@\Returns the product of +behaviors. The arguments may also be numbers, in which case simple multiplication is performed. If a number and sound are mixed, the @code(scale) function is used to scale the sound by the number. When sounds are multiplied, the resulting sample rate is the maximum sample rate of the factors. + +@codef{prod(@pragma(defn)@index(prod)@i(beh@-[1]), @i(beh@-[2]), ...)}@\Same as @code(mult). + +@label(pan-sec) +@codef{pan(@pragma(defn)@index(pan)@index(stereo panning)@i(sound), @i(where))}@\Pans @i(sound) (a behavior) according to @i(where) (another behavior or a number). @i(Sound) must be monophonic. @i(Where) may be a monophonic sound (e.g. @code[(ramp)] or simply a number (e.g. @code(0.5)). In either case, @i(where) should range from 0 to 1, where 0 means pan completely left, and 1 means pan completely right. For intermediate values, the sound to each channel is scaled linearly. Presently, @code(pan) does not check its arguments carefully. + +@codef{prod(@pragma(defn)@index(prod)@i(beh@-[1]), @i(beh@-[2]), ...)}@\Same as @code(mult). + +@label(resample-sec) +@codef{resample(@pragma(defn)@index(resample)@i(sound), @i(srate))}@\Similar to @code(force-srate), except +high-quality interpolation is used to prefilter and reconstruct the signal +at the new sample rate. Also, the result is scaled by 0.95 to reduce problems with +clipping. (See also @code(sound-warp).) + +@label(scale-sec) +@codef{scale(@pragma(defn)@index(scale)@i(scale), @i(sound))}@\Scales the amplitude of @i(sound) by the factor @i(scale). Identical function to @code(snd-scale), except that it handles multichannel sounds. Sample rates, start times, etc. are taken from @i(sound). + +@codef{scale-db(@pragma(defn)@index(scale-db)@i(db), @i(sound))}@\Scales the amplitude of @i(sound) by the factor @i(db), expressed in decibels. Sample rates, start times, etc. are taken from @i(sound). + +@codef[scale-srate(@pragma(defn)@index(scale-srate)@i(sound), @i(scale))]@\Scales the sample rate of @i(sound) by @i(scale) factor. This has the effect of linearly shrinking or stretching time (the sound is not upsampled or downsampled). This is a special case of @code(snd-xform) (see Section @ref(snd-xform-sec)). + +@codef[shift-time(@pragma(defn)@index(shift-time)@i(sound), @i(shift))]@\Shift @i(sound) +by @i(shift) seconds. If the sound is +@pragma(startscribe) +@math[f(t)], then the result is +@pragma(endscribe) +@html[f(t), then the result is] +@pragma(startscribe) +@math[f(t - shift)]. +@pragma(endscribe) +@html[f(t - shift).] +See Figure @ref(shift-time-fig). This is a special +case of @code(snd-xform) (see Section @ref(snd-xform-sec)). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3 in, width = 4.5 in, magnify = 0.75, + postscript = "shifttimefig.ps")) +@html(

) +@fillcaption(The @code(shift-time) function shifts a sound in time +according to its @i(shift) argument.) +@tag(shift-time-fig) +@end(figure) + +@begin(fndefs) +@codef{sound-warp(@pragma(defn)@index(sound-warp)@i(warp-fn), @i(signal)[ ,@i(wrate)])}@\Applies a +warp function @i(warp-fn) to @i(signal) using function composition. If the optional parameter @i(wrate) is omitted or NIL, linear +interpolation is used. Otherwise, high-quality sample interpolation is used, and the +result is scaled by 0.95 to reduce problems with clipping (interpolated samples can +exceed the peak values of the input samples.) +@i(warp-fn) is a mapping from score (logical) time +to real time, and @i(signal) is a function from score time to real values. +The result is a function from real time to real values at a sample rate of @code(*sound-srate*). +See also @code(control-warp). +@blankspace(1) +If @i(wrate) is not NIL, it must be a number. The parameter indicates that +high-quality resampling should be used and specifies the sample rate for the +inverse of @i(warp-fn). Use the lowest number you can. + (See below for details.) Note that high-quality resampling is +much slower than linear interpolation. +@blankspace(1) +To perform high-quality resampling by a fixed ratio, as opposed to a +variable ratio allowed in @code(sound-warp), use @code(scale-srate) to +stretch or shrink the sound, and then @code(resample) to restore the +original sample rate. +@blankspace(1) +@code(Sound-warp) and @code(control-warp) both take the inverse of +@i(warp-fn) to get a function from real time to score time. Each sample +of this inverse is thus a score time; @i(signal) is evaluated at each of +these score times to yield a value, which is the desired result. The +sample rate of the inverse warp function is somewhat arbitrary. With linear +interpolation, the inverse warp function sample rate is taken to be the +output sample rate. Note, however, that the samples of the inverse warp +function are stored as 32-bit floats, so they have limited precision. Since +these floats represent sample times, rounding can be a problem. Rounding +in this case is equivalent to adding jitter to the sample times. Nyquist +ignores this problem for ordinary warping, but for high-quality warping, the +jitter cannot be ignored. +@blankspace(1) +The solution is to use a rather low sample rate +for the inverse warp function. @code(Sound-warp) can then linearly +interpolate this signal using double-precision floats to minimize jitter +between samples. The sample rate is a compromise: a low sample rate +minimizes jitter, while a high sample rate does a better job of capturing +detail (e.g. rapid fluctuations) in the warp function. A good rule of thumb +is to use at most 1,000 to 10,000 samples for the inverse warp function. For +example, if the result will be 1 minute of sound, use a sample rate of +3000 samples / 60 seconds = 50 samples/second. Because Nyquist has no +advance information about the warp function, the inverse warp function +sample rate must be provided as a parameter. When in doubt, just try +something and let your ears be the judge. + +@codef[integrate(@pragma(defn)@index(integrate)@index(smooth)@i(signal))]@\Computes the integral of @i(signal). The start time, sample rate, etc. are taken from @i(signal). + +@codef[slope(@pragma(defn)@index(slope)@index(derivative)@index(first derivative)@i(signal))]@\Computes the first derivative (slope) of @i(signal). The start time, sample rate, etc. are taken from @i(signal). +@end(fndefs) + +@paragraph(Oscillators) +@label(osc-sec) +@begin(fndefs) +@codef{osc(@pragma(defn)@index(osc)@i(pitch)[, @i(duration), @i(table), @i(phase)])}@\Returns +a sound which +is the @i(table) oscillated at @i(pitch) for the given @i(duration), +starting with the @i(phase) (in degrees). +Defaults are: @i(duration) @code(1.0) +(second), @i(table) @code(*table*), +@i(phase) @code(0.0). The default value of @code(*table*) is a sinusoid. Duration is stretched by @code(*warp*) and +@code(*sustain*), amplitude is nominally 1, but scaled by @code(*loudness*), the start time is logical time 0, transformed by @code(*warp*), and the sample rate is @code(*sound-srate*). +The effect of time-warping is to warp the starting and ending times only; the +signal has a constant unwarped frequency. + @p(Note 1:) @i(table) is a list of the form +@begin(display) +(@i(sound) @i(pitch-number) @i(periodic)) +@end(display) +where the first element is a sound, the second is the pitch of the sound +(this is not redundant, because the sound may represent any number of +periods), and the third element is @code(T) if the sound is one period of +a periodic signal, or @code(nil) if the sound is a sample that should not +be looped. The maximum table size is set by @code(max_table_len) in @code(sound.h), and is currently set to 1,000,000. +@p(Note 2:) in the current implementation, it is assumed that the +output should be periodic. See @code(snd-down) and @code(snd-up) for resampling one-shot sounds to a desired sample rate. A future version of @code(osc) +will handle both cases. +@p(Note 3:) When @code(osc) is called, memory is allocated for the table, and samples are copied from the sound (the first element of the list which is the @i(table) parameter) to the memory. Every instance of @code(osc) has a private copy of the table, so the total storage can become large in some cases, for example in granular synthesis with many instances of @code(osc). In some cases, it may make sense to use @code(snd-flatten) (see Section @ref(flatten-sec)) to cause the sound to be fully realized, after which the @code(osc) and its table memory can be reclaimed by garbage collection. The @code(partial) function (see below) does not need a private table and does not use much space. + +@label(partial-sec) +@codef{partial(@pragma(defn)@index(partial)@i(pitch), @i(env))}@\Returns a sinusoid at +the indicated pitch; the sound is multiplied by @i(env). The start time and +duration are taken from @i(env), which is of course subject to +transformations. The sample rate is @code(*sound-srate*). The @code(partial) +function is faster than @code(osc). + +@label(sine-sec) +@codef{sine(@pragma(defn)@index(sine)@i(pitch)[ ,@i(duration)])}@\Returns a sinusoid at +the indicated pitch. The sample rate is @code(*sound-srate*). +This function is like @code(osc) with +respect to transformations. The @code(sine) function is faster than +@code(osc). + +@codef{hzosc(@pragma(defn)@index(hzosc)@i(hz)[ ,@i(table), @i(phase)])}@\Returns a sound which is the @i(table) oscillated at @i(hz) starting at @i(phase) degrees. The default @i(table) is @code(*table*) and the default @i(phase) is @i(0.0). The default duration is @code(1.0), but this is stretched as in @code(osc) (see above). The @i(hz) parameter may be a @code(SOUND), in which case the duration of the result is the duration of @i(hz). The sample rate is @code(*sound-srate*). + +@codef{osc-saw(@pragma(defn)@index(osc-saw)@index(sawtooth oscillator)@i(hz))}@\Returns a sawtooth waveshape at the indicated frequency (in Hertz). The sample rate is @code(*sound-srate*). The @i(hz) parameter may be a sound as in @i(hzosc) (see above). + +@codef{osc-tri(@pragma(defn)@index(osc-tri)@index(triangle oscillator)@i(hz))}@\Returns a triangle waveshape at the indicated frequency (in Hertz). The sample rate is @code(*sound-srate*). The @i(hz) parameter may be a sound as in @i(hzosc) (see above). + +@codef{osc-pulse(@pragma(defn)@index(osc-pulse)@index(square oscillator)@index(pulse oscillator)@index(pulse-width modulation)@i(hz), @i(bias)[ ,@i(compare-shape)])}@\Returns a square pulse with variable width at the indicated frequency (in Hertz). The @i(bias) parameter controls the pulse width and should be between @code(-1) and @code(+1), giving a pulse width from 0% (always at @code(-1)) to 100% (always at @code(+1)). When bias is zero, a square wave is generated. Bias may be a @code(SOUND) to create varying pulse width. If bias changes rapidly, strange effects may occur. The optional @i(compare-shape) defaults to a hard step at zero, but other shapes may be used to achieve non-square pulses. The @code(osc-pulse) behavior is written in terms of other behaviors and defined in the file @code(nyquist.lsp) using just a few lines of code. Read the code for the complete story. + +@label(amosc-sec) +@codef{amosc(@pragma(defn)@index(amosc)@i(pitch), @i(modulation)[ ,@i(table), +@i(phase)])}@\Returns a +sound which is @i(table) oscillated at @i(pitch). The output +is multiplied by @i(modulation) +for the duration of the sound @i(modulation). +@i(osc-table) defaults to +@code(*table*), and @i(phase) is the starting phase (default 0.0 degrees) +within @i(osc-table). The sample rate is @code(*sound-srate*). + +@label(fmosc-sec) +@codef{fmosc(@pragma(defn)@index(fmosc)@i(pitch), @i(modulation)[, @i(table), +@i(phase)])}@\Returns a +sound which is @i(table) oscillated at @i(pitch) plus @i(modulation) +for the duration of the sound @i(modulation). +@i(osc-table) defaults to +@code(*table*), and @i(phase) is the starting phase (default 0.0 degrees) +within @i(osc-table). The @i(modulation) +is expressed in hz, e.g. a sinusoid modulation signal with an +amplitude of 1.0 (2.0 peak to peak), will cause a +/@subtract 1.0 hz +frequency deviation in @i(sound). Negative frequencies are correctly +handled. The sample rate is @code(*sound-srate*). + +@label(fmfb-sec) +@codef{fmfb(@pragma(defn)@index(fmfb)@index(Feedback FM Oscillator)@i(pitch), @i(index)[ ,@i(dur)])}@\Returns +a sound generated by feedback FM synthesis. The @i(pitch) parameter +(given in the usual half-step units) +controls the fundamental frequency. The @i(index) is the amount of +feedback, which may be a @code(SOUND) or a @code(FLONUM). If @i(index) is +a @code(FLONUM), @i(dur) must be provided (a @code(FLONUM)) to specify +the duration. Otherwise, @i(dur) is ignored if present and the duration is +determined by that of @i(index). The sample rate is @code(*sound-srate*). +A sinusoid table is used. +If @i(index) is below 1.1, this generates a sawtooth-like waveform. + +@label(buzz-sec) +@codef{buzz(@pragma(defn)@index(buzz)@i(n), @i(pitch), @i(modulation))}@\Returns a +sound with @i(n) harmonics of equal amplitude and a total amplitude +of 1.0, using a well-known function of two cosines. If @i(n) (an integer) +is less than 1, it is set to 1. Aliasing will occur if @i(n) is too large. +The duration is +determined by the duration of the sound @i(modulation), which is a +frequency modulation term expressed in Hz (see Section @ref(fmosc-sec)). +Negative frequencies are correctly handled. +The sample rate is @code(*sound-srate*). + +@label(pluck-sec) +@codef{pluck(@pragma(defn)@index(pluck)@index(Karplus-Strong)@index(string synthesis) +@index(plucked string)@i(pitch)[ ,@i(duration)] [, @i(final-amplitude)])}@\Returns a sound at the +given @i(pitch) created using a modified Karplus-Strong plucked string +algorithm. The tone decays from an amplitude of about 1.0 to about +@i(final-amplitude) in @i(duration) seconds. The default values are to +decay to 0.001 (-60dB) in 1 second. The sample rate is @code(*sound-srate*). + +@label(siosc-sec) +@codef{siosc(@pragma(defn)@index(siosc)@index(spectral interpolation)@i(pitch), +@i(modulation), @i(tables))}@\Returns a sound constructed by +interpolating through a succession of periodic waveforms. The frequency is +given (in half steps) by @i(pitch) to which a @i(modulation) signal (in hz) +is added, exactly as in @code(fmosc). The @i(tables) specify a list of +waveforms as follows: (@i(table0) @i(time1) @i(table2) ... @i(timeN) +@i(tableN)), where each @i(table) is a sound representing one period. Each +@i(time) is a time interval measured from the starting time. The time is +scaled by the nominal duration (computed using @code[(local-to-global +(get-sustain))]) to get the actual time. Note that this implies linear +stretching rather than continuous timewarping of the interpolation or the +breakpoints. The waveform is @i(table0) at the starting time, @i(table1) +after @i(time1) (scaled as described), and so on. The duration and logical +stop time is given by @i(modulation). If @i(modulation) is shorter than +@i(timeN), then the full sequence of waveforms is not used. If +@i(modulation) is longer than @i(timeN), @i(tableN) is used after @i(timeN) +without further interpolation. + + +@label(sampler-sec) +@codef{sampler(@pragma(defn)@index(sampler)@i(pitch), @i(modulation)[ ,@i(sample), +@i(npoints)])}@\Returns a sound constructed by reading a sample from +beginning to end and then splicing on copies of the same sound from +a loop point to the end. +The @i(pitch) and @i(modulation) parameters are used as in @code(fmosc) +described above. The optional @i(sample) (which defaults to the global +variable @code(*table*) is a list of the form +@begin(display) +(@i(sound) @i(pitch-number) @i(loop-start)) +@end(display) +where the first element is a sound containing the sample, the second is the +pitch of the sample, and the third element is the time of the loop point. If +the loop point is not in the bounds of the sound, it is set to zero. +The optional @i(npoints) specifies how many points should be used for sample +interpolation. Currently this parameter defaults to 2 and only 2-point +(linear) interpolation is implemented. It is an error to modulate such that the frequency +is negative. Note also that the loop point may be fractional. +The sample rate is @code(*sound-srate*). +@end(fndefs) + +@paragraph(Piece-wise Approximations) +@index(piece-wise)@index(approximation)@index(splines) +There are a number of related behaviors for piece-wise approximations to functions. The simplest of these, @code(pwl) was mentioned earlier in the manual. It takes a list of breakpoints, assuming an initial point at (0, 0), and a final value of 0. An analogous piece-wise exponential function, @code(pwe), is provided. Its implicit starting and stopping values are 1 rather than 0. Each of these has variants. You can specify the initial and final values (instead of taking the default). You can specify time in intervals rather than cummulative time. Finally, you can pass a list rather than an argument list. This leads to 16 versions: +@pragma(startscribe) +@begin(display) +@tabclear +@tabset(0.4 inches, 0.8 inches, 1.2 inches) +Piece-wise Linear Functions: +@\Cummulative Time: +@\@\Default initial point at (0, 0), final value at 0: +@\@\@\@code(pwl) +@\@\@\@code(pwl-list) +@\@\Explicit initial value: +@\@\@\@code(pwlv) +@\@\@\@code(pwlv-list) +@\Relative Time: +@\@\Default initial point at (0, 0), final value at 0: +@\@\@\@code(pwlr) +@\@\@\@code(pwlr-list) +@\@\Explicit initial value: +@\@\@\@code(pwlvr) +@\@\@\@code(pwlvr-list) +Piece-wise Exponential Functions: +@\Cummulative Time: +@\@\Default initial point at (0, 1), final value at 1: +@\@\@\@code(pwe) +@\@\@\@code(pwe-list) +@\@\Explicit initial value: +@\@\@\@code(pwev) +@\@\@\@code(pwev-list) +@\Relative Time: +@\@\Default initial point at (0, 1), final value at 1: +@\@\@\@code(pwer) +@\@\@\@code(pwer-list) +@\@\Explicit initial value: +@\@\@\@code(pwevr) +@\@\@\@code(pwevr-list) +@end(display) +@pragma(endscribe) +@html[
Piece-wise Linear Functions:
+	Cummulative Time:
+		Default initial point at (0, 0), final value at 0:
+			pwl
+			pwl-list
+		Explicit initial value:
+			pwlv
+			pwlv-list
+	Relative Time:
+		Default initial point at (0, 0), final value at 0:
+			pwlr
+			pwlr-list
+		Explicit initial value:
+			pwlvr
+			pwlvr-list
+
+Piece-wise Exponential Functions:
+	Cummulative Time:
+		Default initial point at (0, 1), final value at 1:
+			pwe
+			pwe-list
+		Explicit initial value:
+			pwev
+			pwev-list
+	Relative Time:
+		Default initial point at (0, 1), final value at 1:
+			pwer
+			pwer-list
+		Explicit initial value:
+			pwevr
+			pwevr-list
+
] +All of these functions are implemented in terms of @code(pwl) (see @code(nyquist.lsp) for the implementations. There are infinite opportunities for errors in these functions: if you leave off a data point, try to specify points in reverse order, try to create an exponential that goes to zero or negative values, or many other bad things, the behavior is not well-defined. Nyquist should not crash, but Nyquist does not necessarily attempt to report errors at this time. + +@begin(fndefs) +@label(pwl-sec) +@codef{pwl(@pragma(defn)@index(pwl)@i(t@-[1]), @i(l@-[1]), @i(t@-[2]), @i(l@-[2]), ... @i(t@-[n]))}@\Creates +a piece-wise linear envelope with breakpoints at (0, 0), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 0). The breakpoint +times are scaled linearly by the value of @code(*sustain*) (if +@code(*sustain*) is a @code(SOUND), it is evaluated once at the starting +time of the envelope). Each breakpoint time is then mapped according to +@code(*warp*). The result is a linear interpolation (unwarped) between +the breakpoints. The sample rate is @code(*control-srate*). Breakpoint +times are quantized to the nearest sample time. If you specify one or more +breakpoints withing one sample period, @code(pwl) attempts to give a good +approximation to the specified function. In particular, if two breakpoints +are simultaneous, @code(pwl) will move one of them to an adjacent sample, +producing a steepest possible step in the signal. The exact details of this +``breakpoint munging'' is subject to change in future versions. Please report +any cases where breakpoint lists give unexpected behaviors. The author will +try to apply the ``principle of least surprise'' to the design. Note that +the times are relative to 0; they are not durations of each envelope +segment. + +@codef{pwl-list(@pragma(defn)@index(pwl-list)@i(breakpoints))}@\If you have a list of +breakpoints, you can use @code(apply) to apply the @code(pwl) function to +the breakpoints, but if the list is very long (hundreds or thousands of +points), you might get a stack overflow because XLISP has a fixed-size +argument stack. Instead, call @code(pwl-list), passing one argument, the +list of breakpoints. + +@codef{pwlv(@pragma(defn)@index(pwlv)@i(l@-[1]), @i(t@-[2]), @i(l@-[2]), @i(t@-[3]), @i(t@-[3]), ... @i(t@-[n]), @i(l@-[n]))}@\Creates +a piece-wise linear envelope with breakpoints at (0, l@-[1]), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n], @i(l@-[n])). Otherwise, the behavior is like that of @code(pwl). + +@codef{pwlv-list(@pragma(defn)@index(pwlv-list)@i(breakpoints))}@\A version of @code(pwlv) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwlr(@pragma(defn)@index(pwlr)@i(i@-[1]), @i(l@-[1]), @i(i@-[2]), @i(l@-[2]), ... @i(i@-[n]))}@\Creates +a piece-wise linear envelope with breakpoints at (0, 0), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 0), where @i(t@-[j]) is the sum of @i(i@-[1]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwl). + +@codef{pwlr-list(@pragma(defn)@index(pwlr-list)@i(breakpoints))}@\A version of @code(pwlr) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwlvr(@pragma(defn)@index(pwlvr)@i(l@-[1]), @i(i@-[2]), @i(l@-[2]), @i(i@-[3]), @i(i@-[3]), ... @i(i@-[n]), @i(l@-[n]))}@\Creates +a piece-wise linear envelope with breakpoints at (0, l@-[1]), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n], @i(l@-[n])), where @i(t@-[j]) is the sum of @i(i@-[2]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwlv). + +@codef{pwlvr-list(@pragma(defn)@index(pwlvr-list)@i(breakpoints))}@\A version of @code(pwlvr) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwe(@pragma(defn)@index(pwe)@i(t@-[1]), @i(l@-[1]), @i(t@-[2]), @i(l@-[2]), ... +@i(t@-[n]))}@\Creates +a piece-wise exponential envelope with breakpoints at (0, 1), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 1). Exponential segments means that the ratio of values from sample to sample is constant within the segment. (The current implementation actually takes the log of each value, computes a piece-wise exponential from the points using @code(pwl), then exponentiates each resulting sample. A faster implementation is certainly possible!) Breakpoint values (@i(l@-[j])) must be greater than zero. Otherwise, this function is similar to @code(pwl), including stretch by @code(*sustain*), mapping according to @code(*warp*), sample rate based on @code(*control-srate*), and "breakpoint munging" (see @code(pwl) described above). @i(Default initial and final values are of dubious value with exponentials. See @code(pwev) below for the function you are probably looking for.) + +@codef{pwe-list(@pragma(defn)@index(pwe-list)@i(breakpoints))}@\A version of @code(pwe) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@label(pwev-sec) +@codef{pwev(@pragma(defn)@index(pwev)@i(l@-[1]), @i(t@-[2]), @i(l@-[2]), @i(t@-[3]), @i(t@-[3]), ... @i(t@-[n]), @i(l@-[n]))}@\Creates +a piece-wise exponential envelope with breakpoints at (0, l@-[1]), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n], @i(l@-[n])). Otherwise, the behavior is like that of @code(pwe). + +@codef{pwev-list(@pragma(defn)@index(pwev-list)@i(breakpoints))}@\A version of @code(pwev) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwer(@pragma(defn)@index(pwer)@i(i@-[1]), @i(l@-[1]), @i(i@-[2]), @i(l@-[2]), ... @i(i@-[n]))}@\Creates +a piece-wise exponential envelope with breakpoints at (0, 1), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 1), where @i(t@-[j]) is the sum of @i(i@-[1]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwe). Consider using @code(pwerv) instead of this one. + +@codef{pwer-list(@pragma(defn)@index(pwer-list)@i(breakpoints))}@\A version of @code(pwer) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwevr(@index(GEN05)@pragma(defn)@index(pwevr)@i(l@-[1]), @i(i@-[2]), @i(l@-[2]), @i(i@-[3]), @i(i@-[3]), ... @i(i@-[n]), @i(l@-[n]))}@\Creates +a piece-wise exponential envelope with breakpoints at (0, l@-[1]), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n], @i(l@-[n])), where @i(t@-[j]) is the sum of @i(i@-[2]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwev). Note that this is similar to the csound GEN05 generator. Which is uglier, @i(GEN05) or @i(pwevr)? + +@codef{pwevr-list(@pragma(defn)@index(pwevr-list)@i(breakpoints))}@\A version of @code(pwevr) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. +@end(fndefs) +@paragraph(Filter Behaviors) +@begin(fndefs) +@label(alpass-sec) +@codef{alpass(@index(all pass filter)@index(alpass filter)@pragma(defn)@index(alpass)@i(sound), @i(decay), @i(hz)[ ,@i(minhz)])}@\Applies an all-pass filter to @i(sound). This all-pass filter creates a delay effect without the resonances of a comb filter. The decay time of the filter is given by @i(decay). The @i(hz) parameter must be a number or sound greater than zero. It is used to compute delay, which is then rounded to the nearest integer number of samples (so the frequency is not always exact. Higher sampling rates yield better delay resolution.) The @i(decay) may be a sound or a number. In either case, it must also be positive. (Implementation note: an exponentiation is needed to convert @i(decay) into the @i(feedback) parameter, and exponentiation is typically more time-consuming than the filter operation itself. To get high performance, provide @i(decay) at a low sample rate.) The resulting sound will have the start time, sample rate, etc. of @i(sound). If @i(hz) is of type @code(SOUND), the delay may be time-varying. Linear interpolation is then used for fractional sample delay, but it should be noted that linear interpolation implies a low-pass transfer function. Thus, this filter may behave differently with a constant @code(SOUND) than it does with a @code(FLONUM) value for @i(hz). In addition, if @i(hz) is of type @code(SOUND), then @i(minhz) is required. The @i(hz) parameter will be clipped to be greater than @i(minhz), placing an upper bound on the delay buffer length. + +@label(comb-sec) +@codef{comb(@pragma(defn)@index(comb)@index(comb filter)@i(sound), @i(decay), @i(hz))}@\Applies a comb filter to @i(sound). A comb filter emphasizes (resonates at) frequencies that are multiples of a @i(hz). The decay time of the resonance is given by @i(decay). This is a variation on @code(feedback-delay) (see below). The @i(hz) parameter must be a number greater than zero. It is used to compute delay, which is then rounded to the nearest integer number of samples (so the frequency is not always exact. Higher sampling rates yield better delay resolution.) The @i(decay) may be a sound or a number. In either case, it must also be positive. (Implementation note: an exponentiation is needed to convert @i(decay) into the @i(feedback) parameter for @code(feedback-delay), and exponentiation is typically more time-consuming than the filter operation itself. To get high performance, provide @i(decay) at a low sample rate.) The resulting sound will have the start time, sample rate, etc. of @i(sound). + +@label(congen-sec) +@codef{congen(@pragma(defn)@index(congen)@index(contour generator)@index(envelope generator)@i(gate), @i(risetime), @i(falltime))}@\Implements an analog synthesizer-style contour generator. The input @i(gate) normally goes from 0.0 to 1.0 to create an attack and from 1.0 to 0.0 to start a release. During the attack (output is increasing), the output converges half-way to @i(gate) in @i(risetime) (a @code(FLONUM)) seconds. During the decay, the half-time is @i(falltime) seconds. The sample rate, start time, logical stop, and terminate time all come from @i(gate). If you want a nice decay, be sure that the @i(gate) goes to zero and stays there for awhile before @i(gate) terminates, because @code(congen) (and all Nyquist sounds) go immediately to zero at termination time. For example, you can use @code(pwl) to build a pulse followed by some zero time: +@begin(example) +(pwl 0 1 duty 1 duty 0 1) +@end(example) +Assuming @i(duty) is less than 1.0, this will be a pulse of duration @i(duty) followed by zero for a total duration of 1.0. +@begin(example) +(congen (pwl 0 1 duty 1 duty 0 1) 0.01 0.05) +@end(example) +will have a duration of 1.0 because that is the termination time of the @code(pwl) input. The decaying release of the resulting envelope will be truncated to zero at time 1.0. (Since the decay is theoretically infinite, there is no way to avoid truncation, although you could multiply by another envelope that smoothly truncates to zero in the last millisecond or two to get both an exponential decay and a smooth final transition to zero.) + +@label(convolve-sec) +@codef{convolve(@pragma(defn)@index(convolve)@index(convolution)@index(FIR filter)@i(sound), +@i(response))}@\Convolves two signals. The first can be any length, but the +computation time per sample and the total space required are proportional to +the length of @i(response). + +@label(feedback-delay-sec) +@codef{feedback-delay(@pragma(defn)@index(feedback-delay)@index(delay)@index(echo)@i(sound), @i(delay), @i(feedback))}@\Applies feedback delay to @i(sound). The @i(delay) must be a number (in seconds). It is rounded to the nearest sample to determine the length of the delay. The sample rate is the maximum from @i(sound) and @i(feedback) (if feedback is also a sound). The amound of @i(feedback) should be less than one to avoid an exponential increase in amplitude. The start time and stop time, and logical stop time are taken from @i(sound). Since output is truncated at the stop time of @i(sound), you may want to append some silence to @i(sound) to give the filter time to decay. + +@label(lp-sec) +@codef{lp(@pragma(defn)@index(lp)@index(low-pass filter)@i(sound), @i(cutoff))}@\Filters @i(sound) +using a first-order Butterworth low-pass filter. @i(Cutoff) may be a float +or a signal (for time-varying filtering) and expresses hertz. Filter +coefficients (requiring trig functions) are recomputed at the sample rate of +@i(cutoff). The resulting sample rate, start time, etc. are taken from @i(sound). + +@codef{tone(@pragma(defn)@index(tone)@i(sound), @i(cutoff))}@\No longer defined; use @code(lp) instead, or define it by adding @code[(setfn tone lp)] to your program. + + +@label(hp-sec) +@codef{hp(@pragma(defn)@index(hp)@index(high-pass filter)@i(sound), @i(cutoff))}@\Filters @i(sound) +using a first-order Butterworth high-pass filter. @i(Cutoff) may be a +float or a signal (for time-varying filtering) and expresses hertz. Filter +coefficients (requiring trig functions) are recomputed at the sample rate of +@i(cutoff). This filter is an exact complement of @code(lp). + +@codef{atone(@pragma(defn)@index(atone)@i(sound), @i(cutoff))}@\No longer defined; use @code(hp) instead, or define it by adding @code[(setfn atone hp)] to your program. + +@label(reson-sec) +@codef{reson(@pragma(defn)@index(reson)@index(bandpass filter)@i(sound), @i(center), @i(bandwidth), @i(n))}@\Apply +a resonating filter to @i(sound) with center frequency @i(center) (in hertz), +which may be a float or a signal. @i(Bandwidth) is the filter bandwidth (in +hertz), which may also be a signal. Filter coefficients (requiring trig +functions) are recomputed at each new sample of either @i(center) or +@i(bandwidth), and coefficients are @i(not) interpolated. The last +parameter @i(n) specifies the type of normalization as in Csound: A value of 1 specifies a peak amplitude +response of 1.0; all frequencies other than @i(hz) are attenuated. A +value of 2 specifies the overall RMS value of the amplitude response +is 1.0; thus filtered white noise would retain the same power. A value of +zero specifies no scaling. The resulting sample rate, start time, etc. are taken from @i(sound). + +One application of @code(reson) is to simulate resonances in the human vocal tract. +See @code(demos/voice_synthesis.htm)@index(voice synthesis)@index(demos, voice synthesis) +for sample code and documentation. + +@label(areson-sec) +@codef{areson(@pragma(defn)@index(areson)@index(notch filter)@i(sound), @i(center), @i(bandwidth), @i(n))}@\The @code(areson) filter is an exact +complement of @code(reson) such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. + +@label(shape-sec) +@codef{shape(@pragma(defn)@index(shape)@index(waveshaping)@index(table)@i(signal), @i(table), @i(origin))}@\A waveshaping function. Use @i(table) as a function; apply the function to each sample of @i(signal) to yield a new sound. @i(Signal) should range from -1 to +1. Anything beyond these bounds is clipped. @i(Table) is also a sound, but it is converted into a lookup table (similar to table-lookup oscillators). The @i(origin) is a @code(FLONUM) and gives the time which should be considered the origin of @i(table). (This is important because @i(table) cannot have values at negative times, but @i(signal) will often have negative values. The @i(origin) gives an offset so that you can produce suitable tables.) The output at time @i(t) is: +@begin(display) +@i(table)(@i(origin) + clip(@i(signal)(@i(t))) +@end(display) +where clip(@i(x)) = @i(max)(1, @i(min)(-1, @i(x))). +(E.g. if @i(table) is a signal defined over the interval [0, 2], then @i(origin) should be 1.0. The value of @i(table) at time 1.0 will be output when the input signal is zero.) The output has the same start time, sample rate, etc. as @i(signal). The @code(shape) function will also accept multichannel @i(signal)s and @i(table)s. + +Further discussion and examples can be found in +@code(demos/distortion.htm)@index(distortion tutorial)@index(demos, distortion). +The @code(shape) +function is also used to map frequency to amplitude to achieve a spectral envelope for +Shepard tones in @code(demos/shepard.lsp).@index(Shepard tones)@index(demos, Shepard tones) + +@label(biquad-sec) +@codef{biquad(@pragma(defn)@index(biquad)@i(signal), @i(b0), @i(b1), @i(b2), @i(a0), @i(a1), @i(a2))}@\A fixed-parameter biquad filter. All filter coefficients are @code(FLONUM)s. See also @code(lowpass2), @code(highpass2), @code(bandpass2), @code(notch2), @code(allpass2), @code(eq-lowshelf), @code(eq-highshelf), @code(eq-band), @code(lowpass4), @code(lowpass6), @code(highpass4), and @code(highpass8) in this section for convenient variations based on the same filter. The equations for the filter are: z@-[n] = s@-[n] + a1 * z@-[n-1] + a2 * z@-[n-2], and y@-[n] = z@-[n] * b0 + z@-[n-1] * b1 + z@-[n-2] * b2. + +@label(biquad-m-sec) +@codef{biquad-m(@pragma(defn)@index(biquad-m)@i(signal), @i(b0), @i(b1), @i(b2), @i(a0), @i(a1), @i(a2))}@\A fixed-parameter biquad filter with Matlab sign conventions for @i(a0), @i(a1), and @i(a2). All filter coefficients are @code(FLONUM)s. + +@label(lowpass2-sec) +@codef{lowpass2(@pragma(defn)@index(lowpass2)@i(signal), @i(hz)[ ,@i(q)])}@\A fixed-parameter, second-order lowpass filter based on @code(snd-biquad). The cutoff frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(highpass2-sec) +@codef{highpass2(@pragma(defn)@index(highpass2)@i(signal), @i(hz)[ ,@i(q)])}@\A fixed-parameter, second-order highpass filter based on @code(snd-biquad). The cutoff frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(bandpass2-sec) +@codef{bandpass2(@pragma(defn)@index(bandpass2)@i(signal), @i(hz)[ ,@i(q)])}@\A fixed-parameter, second-order bandpass filter based on @code(snd-biquad). The center frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(notch2-sec) +@codef{notch2(@pragma(defn)@index(notch2)@i(signal), @i(hz)[ ,@i(q)])}@\A fixed-parameter, second-order notch filter based on @code(snd-biquad). The center frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(allpass2-sec) +@codef{allpass2(@pragma(defn)@index(allpass2)@i(signal), @i(hz)[ ,@i(q)])}@\A fixed-parameter, second-order allpass filter based on @code(snd-biquad). The frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(eq-lowshelf-sec) +@codef{eq-lowshelf(@pragma(defn)@index(eq-lowshelf)@index(equalization)@i(signal), @i(hz), @i(gain)[ ,@i(slope)])}@\A fixed-parameter, second-order bass shelving equalization (EQ) filter based on @code(snd-biquad). The @i(hz) parameter (a @code(FLONUM))is the halfway point in the transition, and @i(gain) (a @code(FLONUM)) is the bass boost (or cut) in dB. The optional @i(slope) (a @code(FLONUM)) is 1.0 by default, and response becomes peaky at values greater than 1.0. + +@label(eq-highshelf-sec) +@codef{eq-highshelf(@pragma(defn)@index(eq-highshelf)@index(equalization)@i(signal), @i(hz), @i(gain)[ ,@i(slope)])}@\A fixed-parameter, second-order treble shelving equalization (EQ) filter based on @code(snd-biquad). The @i(hz) parameter (a @code(FLONUM))is the halfway point in the transition, and @i(gain) (a @code(FLONUM)) is the treble boost (or cut) in dB. The optional @i(slope) (a @code(FLONUM)) is 1.0 by default, and response becomes peaky at values greater than 1.0. + +@label(eq-band-sec) +@codef{eq-band(@pragma(defn)@index(eq-band)@index(equalization)@i(signal), @i(hz), @i(gain), @i(width))}@\A fixed- or variable-parameter, second-order midrange equalization (EQ) filter based on @code(snd-biquad), @code(snd-eqbandcv) and @code(snd-eqbandvvv). The @i(hz) parameter (a @code(FLONUM)) is the center frequency, @i(gain) (a @code(FLONUM)) is the boost (or cut) in dB, and @i(width) (a @code(FLONUM)) is the half-gain width in octaves. Alternatively, @i(hz), @i(gain), and @i(width) may be @code(SOUND)s, but they must all have the same sample rate, e.g. they should all run at the control rate or at the sample rate. + +@label(lowpass4-sec) +@codef{lowpass4(@pragma(defn)@index(lowpass4)@i(signal), @i(hz))}@\A four-pole Butterworth lowpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(lowpass6-sec) +@codef{lowpass6(@pragma(defn)@index(lowpass6)@i(signal), @i(hz))}@\A six-pole Butterworth lowpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(lowpass8-sec) +@codef{lowpass8(@pragma(defn)@index(lowpass8)@i(signal), @i(hz))}@\An eight-pole Butterworth lowpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(highpass4-sec) +@codef{highpass4(@pragma(defn)@index(highpass4)@i(signal), @i(hz))}@\A four-pole Butterworth highpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(highpass6-sec) +@codef{highpass6(@pragma(defn)@index(highpass6)@i(signal), @i(hz))}@\A six-pole Butterworth highpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(highpass8-sec) +@codef{highpass8(@pragma(defn)@index(highpass8)@i(signal), @i(hz))}@\An eight-pole Butterworth highpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(tapv-sec) +@codef{tapv(@pragma(defn)@index(tapv)@index(variable delay)@index(tapped delay)@i(sound), @i(offset), +@i(vardelay), @i(maxdelay))}@\A delay line with a variable position tap. +Identical to @code(snd-tapv). See it for details (@ref(snd-tapv-sec)). + +@end(fndefs) + +@paragraph(Effects) +@begin(fndefs) +@label(stkrev-sec) +@codef{nrev(@pragma(defn)@index(nrev)@index(reverb)@index(effect, +reverberation)@index(STK nreverb)@i(sound), @i(decay), @i(mix))} + +@codef{jcrev(@pragma(defn)@index(jcrev)@index(reverb)@index(effect, + reverberation)@index(STK jcreverb)@i(sound), @i(decay), @i(mix))} + +@codef{prcrev(@pragma(defn)@index(prcrev)@index(reverb)@index(effect, + reverberation)@index(STK prcreverb)@i(sound), @i(decay), @i(mix))} +These reverbs (@code(nrev), @code(jcrev), and @code(prcrev)) are implemented +in STK (running within Nyquist). @code(nrev) derives from Common Music's +NRev, which consists of 6 comb filters followed by 3 allpass filters, a + lowpass filter, and another allpass in series followed by two allpass +filters in parallel. @code(jcrev) is the John Chowning +reverberator which is based on the use of networks of simple allpass +and comb delay filters. This reverb implements three series allpass units, +followed by four parallel comb filters, and two decorrelation delay +lines in parallel at the output. @code(prcrev) is a Perry Cook's +reverberator which is based on the Chowning/Moorer/Schroeder +reverberators using networks of simple allpass and comb delay filters. +This one implements two series allpass units and two parallel comb filters. +The @i(sound) input may be single or multi-channel. The @i(decay) time is +in seconds, and @i(mix) sets the mixture of input sound reverb sound, +where 0.0 means input only (dry) and 1.0 means reverb only (wet). + +@label(stkchorus-sec) +@codef{stkchorus(@pragma(defn)@index(stkchorus)@index(chorus)@index(effect, chorus)@index(STK chorus)@i(sound), @i(depth), @i(freq), @i(mix)[ ,@i(delay)])}@\Chorus +implemented in STK. The input @i(sound) can be single or multi-channel. +The @code(FLONUM) parameters @i(depth) and @i(freq) set +the modulation +depth from 0 to 1 +and modulation frequency (in Hz), and @i(mix) sets the mixture +of input sound and chorused sound, where 0.0 means input sound only (dry) +and 1.0 means chorused sound only (wet). The parameter @i(delay) is a + @code(FIXNUM) representing the median desired delay length in samples. + +@label(stkpitshift-sec) +@codef{pitshift(@pragma(defn)@index(pitshift)@index(pitch shift)@index(effect, pitch shift)@index(STK pitch shift)@i(sound), @i(shift), @i(mix))}@\A pitch + shifter implemented in STK. The input @i(sound), a single-channel + or multi-channel @code(SOUND) is pitch-shifted by @i(shift), +a @code(FLONUM) ratio. A value of 1.0 means no shift. The parameter @i(mix) + sets the mixture of input and shifted sounds. A value of 0.0 +means input only (dry) +and a value of 1.0 means shifted sound only (wet). +@end(fndefs) + +@paragraph(Physical Models) +@begin(fndefs) +@label(clarinet-sec) +@codef{clarinet(@pragma(defn)@index(clarinet)@index(stk clarinet)@i(step), @i(breath-env))}@\A +physical model of a clarinet from STK. The @i(step) parameter is a @code(FLONUM) +that controls the tube length, and the @i(breath-env) (a @code(SOUND)) +controls the air pressure +and also determines the length of the resulting sound. The @i(breath-env) signal +should range from zero to one. + +@codef{clarinet-freq(@index(clarinet)@pragma(defn)@index(clarinet-freq)@index(stk clarinet)@i(step), @i(breath-env), @i(freq-env))}@\A variation of @code(clarinet) +that includes a variable frequency control, @i(freq-env), which specifies +frequency deviation in Hz. The duration of the resulting sound is the minimum +duration of @i(breath-env) and @i(freq-env). These parameters may be of type +@code(FLONUM) or @code(SOUND). @code(FLONUM)s are coerced into @code(SOUND)s +with a nominal duration arbitrarily set to 30. + +@codef{clarinet-all(@index(clarinet)@pragma(defn)@index(clarinet-all)@index(stk clarinet)@i(step), @i(breath-env), @i(freq-env), @i(vibrato-freq), @i(vibrato-gain), +@i(reed-stiffness), @i(noise))}@\A variation of @code(clarinet-freq) +that includes controls @i(vibrato-freq) (a @code(FLONUM) for vibrato frequency in Hertz), +@i(vibrato-gain) (a @code(FLONUM) for the amount of amplitude vibrato), +@i(reed-stiffness) (a @code(FLONUM) or @code(SOUND) controlling reed stiffness in the clarinet +model), and @i(noise) (a @code(FLONUM) or @code(SOUND) controlling noise amplitude in the input +air pressure). The @i(vibrato-gain) is a number from zero to one, where zero +indicates no vibrato, and one indicates a plus/minus 50% change in breath +envelope values. Similarly, the @i(noise) parameter ranges from zero to one where +zero means no noise and one means white noise with a peak amplitude of +plus/minus 40% of the @i(breath-env). The @i(reed-stiffness) parameter varies +from zero to one. +The duration of the resulting sound is the minimum duration of +@i(breath-env), @i(freq-env), @i(reed-stiffness), and @i(noise). As with +@code(clarinet-freq), these parameters may be either @code(FLONUM)s or +@code(SOUND)s, and @code(FLONUM)s are coerced to sounds with a nominal +duration of 30. + +@label(sax-sec) +@codef{sax(@pragma(defn)@index(sax)@index(stk sax)@i(step), @i(breath-env))}@\A +physical model of a sax from STK. The @i(step) parameter is a @code(FLONUM) +that controls the tube length, and the @i(breath-env) controls the air pressure +and also determines the length of the resulting sound. The @i(breath-env) signal +should range from zero to one. + +@codef{sax-freq(@pragma(defn)@index(sax)@index(sax-freq)@index(stk sax)@i(step), @i(breath-env), @i(freq-env))}@\A variation of @code(sax) +that includes a variable frequency control, @i(freq-env), which specifies +frequency deviation in Hz. The duration of the resulting sound is the minimum +duration of @i(breath-env) and @i(freq-env). These parameters may be of type +@code(FLONUM) or @code(SOUND). @code(FLONUM)s are coerced into @code(SOUND)s +with a nominal duration arbitrarily set to 30. + +@codef{sax-all(@pragma(defn)@index(sax)@index(sax-all)@index(stk sax)@i(step), @i(breath-env), @i(freq-env), @i(vibrato-freq), @i(vibrato-gain), +@i(reed-stiffness), @i(noise), @i(blow-pos), @i(reed-table-offset))}@\A variation of + @code(sax-freq) +that includes controls @i(vibrato-freq) (a @code(FLONUM) for vibrato frequency in Hertz), +@i(vibrato-gain) (a @code(FLONUM) for the amount of amplitude vibrato), +@i(reed-stiffness) (a @code(SOUND) controlling reed stiffness in the sax +model), @i(noise) (a @code(SOUND) controlling noise amplitude in the input +air pressure), @i(blow-pos) (a @code(SOUND) controlling the point of excitation +of the air column), and @i(reed-table-offset) (a @code(SOUND) controlling a +parameter of the reed model). The @i(vibrato-gain) is a number from zero to one, where zero +indicates no vibrato, and one indicates a plus/minus 50% change in breath +envelope values. Similarly, the @i(noise) parameter ranges from zero to one where +zero means no noise and one means white noise with a peak amplitude of +plus/minus 40% of the @i(breath-env). The @i(reed-stiffness), @i(blow-pos), and +@i(reed-table-offset) parameters all vary from zero to one. +The duration of the resulting sound is the minimum duration of +@i(breath-env), @i(freq-env), @i(reed-stiffness), @i(noise), @i(breath-env), + @i(blow-pos), and @i(reed-table-offset). As with +@code(sax-freq), these parameters may be either @code(FLONUM)s or +@code(SOUND)s, and @code(FLONUM)s are coerced to sounds with a nominal +duration of 30. + +@label(flute-sec) +@codef{flute(@pragma(defn)@index(flute)@index(STK flute)@i(step), @i(breath-env))}@\A physical model of a flute from STK. +The @i(step) parameter is a @code(FLONUM) that controls the tube +length, and the @i(breath-env) +controls the air pressure and also determines the starting time and +length of the resulting sound. The @i(breath-env) signal should + range from zero to one. + +@codef{flute-freq(@pragma(defn)@index(flute-freq)@index(STK flute)@i(step), @i(breath-env), @i(freq-env))}@\A variation of @code(flute) + that includes a variable frequency control, @i(freq-env), which + specifies frequency deviation in Hz. The duration of the +resulting sound is the minimum duration of @i(breath-env) and +@i(freq-env). These parameters may be of type @code(FLONUM) or + @code(SOUND). @code(FLONUM)s are coerced into SOUNDs with a +nominal duration arbitrary set to 30. + +@codef{flute-all(@pragma(defn)@index(flute-all)@index(STK flute)@i(step), @i(breath-env), @i(freq-env), @i(vibrato-freq), + @i(vibrato-gain), @i(jet-delay), @i(noise))}@\A variation of +@code(clarinet-freq) that includes controls @i(vibrato-freq) (a +@code(FLONUM) for vibrato frequency in Hz), @i(vibrato-gain) (a + @code(FLONUM) for the amount of amplitude vibrato), @i(jet-delay) + (a @code(FLONUM) or @code(SOUND) controlling jet delay in the + flute model), and +noise (a @code(FLONUM) or @code(SOUND) controlling noise amplitude +in the input air pressure). The @i(vibrato-gain) is a number from zero + to one where zero means no vibrato, and one indicates a plus/minus +50% change in breath envelope values. Similarly, the @i(noise) parameter + ranges from zero to one, where zero means no noise and one means white +noise with a peak amplitude of + plus/minus 40% of the @i(breath-env). The @i(jet-delay) is a ratio + that controls a delay length from the flute model, and therefore it +changes the pitch of the resulting sound. A value of 0.5 will maintain +the pitch indicated by the step parameter. The duration of the +resulting sound is the minimum duration of @i(breath-env), @i(freq-env), +@i(jet-delay), and @i(noise). These parameters may be either +@code(FLONUM)s or @code(SOUND)s, and @code(FLONUM)s are coerced + to sounds with a nominal duration of 30. + +@label(bowed-sec) +@codef{bowed(@pragma(defn)@index(bowed)@index(STK bowed string)@i(step), @i(bowpress-env))}@\A physical model of a bowed string + instrument from STK. The @i(step) parameter is a @code(FLONUM) + that controls the string length, + and the @i(bowpress-env) controls the bow pressure and also +determines the duration of the resulting sound. The @i(bowpress-env) + signal should range from zero to one. + +@codef{bowed-freq(@pragma(defn)@index(bowed-freq)@index(STK bowed-freq)@i(step), @i(bowpress-env), @i(freq-env))}@\A variation of @code(bowed) + that includes a variable frequency control, @i(freq-env), which + specifies frequency deviation in Hz. The duration of the resulting + sound is the minimum duration of @i(bowpress-env) and @i(freq-env). +These parameters may be of type @code(FLONUM) or @code(SOUND). +@code(FLONUM)s are coerced into @code(SOUND)s + with a nominal duration arbitrarily set to 30s. + +@label(mandolin-sec) +@codef{mandolin(@pragma(defn)@index(mandolin)@index(STK mandolon)@i(step), @i(dur), &optional @i(detune))}@\A physical model of a + plucked double-string instrument from STK. The @i(step) parameter + is a @code(FLONUM) wich specifies the desired pitch, @i(dur) + means the duration of the resulting sound and detune is a +@code(FLONUM) that controls the relative detune of the two strings. +A value of 1.0 means unison. The default value is 4.0. +Note: @i(body-size) (see @code(snd-mandolin) does not seem to + work correctly, so a default value is always used + by @code(mandolin). + +@label(bandedwg-sec) +@codef{wg-uniform-bar(@pragma(defn)@index(wg-uniform-bar)@index(STK uniform bar)@i(step), @i(bowpress-env))} + +@codef{wg-tuned-bar(@pragma(defn)@index(wg-tuned-bar)@index(STK tuned bar)@i(step), @i(bowpress-env))} + +@codef{wg-glass-harm(@pragma(defn)@index(wg-glass-harm)@index(STK glass harmonica)@i(step), @i(bowpress-env))} + +@codef{wg-tibetan-bowl(@pragma(defn)@index(wg-tibetan-bowl)@index(STK tibetan bowl)@i(step), @i(bowpress-env))}@\These +sounds are presets for a Banded Wave Guide Percussion instrument implemented in STK. +The parameter @i(step) is a @code(FLONUM) + that controls the resultant pitch, and @i(bowpress-env) is a @code(SOUND) ranging +from zero to one that controls a parameter of the model. In addition, +@i(bowpress-env) determines the duration of the resulting sound. +(Note: The @i(bowpress-env) does not seems influence the timbral +quality of the resulting sound). + +@label(modalbar-sec) +@codef{modalbar(@pragma(defn)@index(modalbar)@index(STK modal bar)@i(preset), @i(step), @i(dur))}@\A physical model of a struck bar + instrument implemented in STK. The parameter @i(preset) is one of the +symbols +@code(MARIMBA), @code(VIBRAPHONE), @code(AGOGO), @code(WOOD1), +@code(RESO), @code(WOOD2), @code(BEATS), @code(TWO-FIXED), or +@code(CLUMP). The symbol must be quoted, e.g. for SAL syntax use +@code[quote(marimba)], and for Lisp syntax use @code('marimba). +The parameter @i(step) is a @code(FLONUM) that +sets the pitch (in steps), and @i(dur) is the duration in seconds. + +@label(sitar-sec) +@codef{sitar(@pragma(defn)@index(sitar)@index(STK sitar)@i(step), @i(dur))}@\A sitar physical model implemented in STK. +The parameter @i(step) is a @code(FLONUM) that sets the pitch, + and @i(dur) is the duration. +@end(fndefs) + +@paragraph(More Behaviors) +@begin(fndefs) +@label(clip-sec) +@codef{clip(@pragma(defn)@index(clip)@index(limit)@i(sound), @i(peak))}@\Hard limit @i(sound) +to the given @i(peak), a positive number. The samples of @i(sound) are constrained between an upper value +of @i(peak) and a lower value of @subtract()@i(peak). If @i(sound) is a number, @code(clip) will return @i(sound) limited by @i(peak). If @i(sound) is a multichannel sound, @code(clip) returns a multichannel sound where each channel is clipped. The result has the type, sample rate, starting time, etc. of @i(sound). + +@label(s-abs-sec) +@codef{s-abs(@pragma(defn)@index(s-abs)@index(absolute value)@i(sound))}@\A generalized absolute value function. If @i(sound) is a @code(SOUND), compute the absolute value of each sample. If @i(sound) is a number, just compute the absolute value. If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-abs) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). + +@label(s-sqrt-sec) +@codef{s-sqrt(@pragma(defn)@index(s-sqrt)@index(square root)@i(sound))}@\A generalized square root function. If @i(sound) is a @code(SOUND), compute the square root of each sample. If @i(sound) is a number, just compute the square root. If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-sqrt) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). In taking square roots, if an input sample is less than zero, the corresponding output sample is zero. This is done because the square root of a negative number is undefined. + +@label(s-exp-sec) +@codef{s-exp(@pragma(defn)@index(s-exp)@index(exponential)@i(sound))}@\A generalized exponential function. If @i(sound) is a @code(SOUND), compute @i(e)@+(@i(x)) for each sample @i(x). If @i(sound) is a number @i(x), just compute @i(e)@+(@i(x)). If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-exp) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). + +@label(s-log-sec) +@codef{s-log(@pragma(defn)@index(s-log)@index(logorithm)@index(natural log)@i(sound))}@\A generalized natural log function. If @i(sound) is a @code(SOUND), compute @i(ln)(@i(x)) for each sample @i(x). If @i(sound) is a number @i(x), just compute @i(ln)(@i(x)). If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-log) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). Note that the @i(ln) of 0 is undefined (some implementations return negative infinity), so use this function with care. + +@label(s-max-sec) +@codef{s-max(@pragma(defn)@index(s-max)@index(maximum)@i(sound1), @i(sound2))}@\Compute the maximum of two functions, @i(sound1) and @i(sound2). This function also accepts numbers and multichannel sounds and returns the corresponding data type. The start time of the result is the maximum of the start times of @i(sound1) and @i(sound2). The logical stop time and physical stop time of the result is the minimum of the logical stop and physical stop times respectively of @i(sound1) and @i(sound2). Note, therefore, that the result value is zero except within the bounds of @i(both) input sounds. + +@codef{s-min(@pragma(defn)@index(s-min)@index(minimum)@i(sound1), @i(sound2))}@\Compute the minimum of two functions, @i(sound1) and @i(sound2). This function also accepts numbers and multichannel sounds and returns the corresponding data type. The start time of the result is the maximum of the start times of @i(sound1) and @i(sound2). The logical stop time and physical stop time of the result is the minimum of the logical stop and physical stop times respectively of @i(sound1) and @i(sound2). Note, therefore, that the result value is zero except within the bounds of @i(both) input sounds. + +@codef{osc-note(@pragma(defn)@index(osc-note)@i(pitch)[ ,@i(duration), @i(env), @i(loud), +@i(table)])}@\Same as @code(osc), but @code(osc-note) +multiplies the result by @i(env). The @i(env) may be a sound, +or a list supplying (@i(t@-[1]) @i(t@-[2]) +@i(t@-[4]) @i(l@-[1]) @i(l@-[2]) @i(l@-[3])). The result has a sample rate of @code(*sound-srate*). + +@label(quantize-sec) +@codef{quantize(@pragma(defn)@index(quantize)@i(sound), @i(steps))}@\Quantizes @i(sound) as follows: @i(sound) is multiplied by @i(steps) and rounded to the nearest integer. The result is then divided by @i(steps). For example, if @i(steps) is 127, then a signal that ranges from -1 to +1 will be quantized to 255 levels (127 less than zero, 127 greater than zero, and zero itself). This would match the quantization Nyquist performs when writing a signal to an 8-bit audio file. The @i(sound) may be multi-channel. + +@codef{ramp(@pragma(defn)@index(ramp) [@i(duration)])}@\Returns a linear ramp from 0 to 1 +over @i(duration) (default is 1). The function actually reaches 1 at +@i(duration), and therefore has one extra sample, making the total duration +be @i(duration) + 1/@code(*Control-srate*). See Figure @ref(ramp-fig) for +more detail. Ramp is unaffected by the @code(sustain) transformation. The +effect of time warping is to warp the starting and ending times only. The +ramp itself is unwarped (linear). The sample rate is @code(*control-srate*). + +@label(rms-sec) +@codef{rms(@pragma(defn)@index(rms)@i(sound)[ ,@i(rate), @i(window-size)])}@\Computes the RMS of @i(sound) using a square window of size @i(window-size). The result has a sample rate of @i(rate). The default value of @i(rate) is 100 Hz, and the default window size is 1/rate seconds (converted to samples). The @i(rate) is a @code(FLONUM) and @i(window-size) is a @code(FIXNUM). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.37 in, width = 4.5 in, magnify = 0.75, + postscript = "rampfig.ps")) +@html(

) +@fillcaption[Ramps generated by @code(pwl) and @code(ramp) functions. The +@code(pwl) version ramps toward the breakpoint (1, 1), but in order to ramp +back to zero at breakpoint (1, 0), the function never reaches an amplitude +of 1. If used at the beginning of a @code(seq) construct, the next sound +will begin at time 1. The @code(ramp) version actually reaches breakpoint +(1, 1); notice that it is one sample longer than the @code(pwl) version. If +used in a sequence, the next sound after @code(ramp) would start at time 1 + +@i(P), where @i(P) is the sample period.] +@tag(ramp-fig) +@end(figure) + +@begin(fndefs) +@label(recip-sec) +@codef{recip(@pragma(defn)@index(recip)@index(reciprocal)@index(division)@i(sound))}@\A generalized reciprocal function. +If @i(sound) is a @code(SOUND), compute 1/@i(x) for each sample @i(x). If @i(sound) is a number @i(x), just compute 1/@i(x). If @i(sound) is a multichannel sound, return a multichannel sound with @code(recip) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). Note that the reciprocal of 0 is undefined (some implementations return infinity), so use this function with care on sounds. Division of sounds is accomplished by multiplying by the reciprocal. Again, be careful not to divide by zero. + +@codef{s-rest(@index(rest)@pragma(defn)@index(s-rest) [@i(duration)])}@\Create silence (zero samples) +for the given +@i(duration) at the sample rate @code(*sound-srate*). +Default duration is 1.0 sec, and the sound is transformed in time according +to @code[*warp*]. @p(Note:) @code(rest) is a Lisp function that is equivalent to @code(cdr). Be careful to use @code(s-rest) when you need a sound! + +@label(noise-sec) +@codef{noise(@pragma(defn)@index(noise) [@i(duration)])}@\Generate noise with the given +@i(duration). Duration (default is 1.0) +is transformed according to @code[*warp*]. The +sample rate is @code(*sound-srate*) and the amplitude is +/- @code(*loud*). + +@label(yin-sec) +@codef{yin(@pragma(defn)@index(yin)@index(pitch detection)@index(fundamenal frequency +estimation)@index(estimate frequency)@index(frequency analysis)@index(period +estimation)@i(sound), @i(minstep), @i(maxstep), @i(stepsize))}@\Fundamental +frequency estimation (pitch detection. Use the YIN algorithm to estimate +the fundamental frequency of @i(sound), which must be a @code(SOUND). +The @i(minstep), a @code(FLONUM), is the minimum frequency considered (in steps), +@i(maxstep), a @code(FLONUM), is the maximum frequency considered (in steps), and +@i(stepsize), a @code(FIXNUM), is the desired hop size. The result is +a ``stereo'' signal, +i.e. an array of two @code(SOUND)s, both at the same sample rate, which is +approximately the sample rate of @i(sound) divided by @i(stepsize). +The first @code(SOUND) consists of frequency estimates. The second sound consists +of values that measure the confidence or reliability of the frequency estimate. +A small value (less than 0.1) indicates fairly high confidence. A larger value +indicates lower confidence. This number can also be thought of as a ratio of +non-periodic power to periodic power. When the number is low, it means the signal +is highly periodic at that point in time, so the period estimate will be +reliable. +Hint #1: See +Alain de Cheveigne and Hideki Kawahara's article "YIN, a Fundamental Frequency +Estimator for Speech and Music" in the Journal of the +Acoustic Society of America, April 2002 for details on the yin algorithm. +Hint #2: Typically, the @i(stepsize) should be at least the expected number +of samples in one period so that the +fundamental frequency estimates are calculated at a rate far below +the sample rate of the signal. Frequency does not change rapidly and +the yin algorithm is fairly slow. To optimize speed, +you may want to use less than 44.1 kHz sample rates for input sounds. Yin +uses interpolation to achieve potentially fractional-sample-accurate estimates, +so higher sample rates do not necessarily help the algorithm and definitely +slow it down. The computation time is O(@i(n)@+(2)) per estimate, +where @i(n) is the number +of samples in the longest period considered. Therefore, each increase +of @i(minstep) by 12 (an octave) gives you a factor of 4 speedup, and +each decrease of the sample rate of @i(sound) by a factor of +two gives you another factor of 4 speedup. Finally, the number of estimates is +inversely proportional to @i(stepsize). +Hint #3: Use @code(snd-srate) (see Section @ref(snd-srate-sec)) to get +the exact sample rate of the result, which will be the sample rate of + @i(sound) divided by @i(stepsize). +E.g. @code{(snd-srate (aref yin-output 0))}, +where @code(yin-output) is a result returned by @code(yin), will be the +sample rate of the estimates. + +@end(fndefs) + +@section(Transformations)@index(Transformations) +@label(transformations-sec) +These functions change the environment that is seen by other high-level +functions. Note that these changes are usually relative to the +current environment. There are also ``absolute'' versions of each +transformation function, with the exception of @code(seq), + @code(seqrep), @code(sim), and @code(simrep). The +``absolute'' versions (starting or ending with ``abs'') do not look at the +current environment, but rather set an environment variable to a specific value. +In this way, sections of code can be insulated from external +transformations. + +@begin(fndefs) +@codef{abs-env(@pragma(defn)@index(abs-env)@i(beh))}@\Compute @i(beh) in the default environment. +This is useful for computing waveform tables and signals that are +``outside'' of +time. For example, @code[(at 10.0 (abs-env (my-beh)))] is equivalent to +@code[(abs-env (my-beh))] because @code(abs-env) forces the default environment. Or in SAL, we would say @code[abs-env(my-beh()) @@ 10] is equivalent to @code[abs-env(my-beh())]. + +@codef{at(@pragma(defn)@index(at)@i(time), @i(beh))}@\Evaluate @i(beh) with +@code(*warp*@index(*warp*)) shifted by @i(time). In SAL, you can use the infix +operator @code(@@) as in @code[@i(beh) @@ @i(time)]. To discover how the +environment is shifting time, use @code[local-to-global(@i(time))]. Most +commonly, you call @code[local-to-global(0)] to find when a sound created +in the current environment will start, expressed in absolute (global) terms. +This can be regarded as the ``current time.'' + +@codef{at-abs(@pragma(defn)@index(at-abs)@i(time), @i(beh))}@\Evaluate @i(beh) with +@code(*warp*@index(*warp*)) shifted so that local time 0 maps to @i(time). In SAL, you can use the infix operator @code[@@@@] as in @code[@i(beh) @@@@ @i(time)]. + +@label(continuous-control-warp) +@codef{continuous-control-warp(@pragma(defn)@index(continuous-control-warp)@i(beh))}@\Applies the current warp environment to the signal returned by @i(beh). The result has the default control sample rate @code(*control-srate*). Linear interpolation is currently used. Implementation: @i(beh) is first evaluated without any shifting, stretching, or warping. The result is functionally composed with the inverse of the environment's warp function. + +@label(continuous-sound-warp) +@codef{continuous-sound-warp(@pragma(defn)@index(continuous-sound-warp)@i(beh))}@\Applies the current warp environment to the signal returned by @i(beh). The result has the default sound sample rate @code(*sound-srate*). Linear interpolation is currently used. See @code(continuous-control-warp) for implementation notes. + +@label(control-srate-abs-sec) +@codef{control-srate-abs(@pragma(defn)@index(control-srate-abs)@i(srate), +@i(beh))}@\Evaluate @i(beh) with @code(*control-srate*@index(*control-srate*)) +set to sample rate @i(srate). @p(Note:) there is no ``relative'' version of +this function. + +@codef{extract(@pragma(defn)@index(extract)@i(start), @i(stop), @i(beh))}@\Returns a sound +which is the portion of +@i(beh) between @i(start) and @i(stop). Note that this is done +relative to the current @code(*warp*). The result is shifted +to start according to @code(*warp*), so normally the result will start without a delay of @i(start). + +@codef{extract-abs(@pragma(defn)@index(extract-abs)@i(start), @i(stop), @i(beh))}@\Returns a sound which +is the portion of +@i(beh) between @i(start) and @i(stop), independent of the +current @code(*warp*). The result is shifted +to start according to @code(*warp*). + +@codef{loud(@pragma(defn)@index(loud)@i(volume), @i(beh))}@\Evaluates @i(beh) with @code(*loud*) +incremented by @i(volume). (Recall that @code(*loud*) is in decibels, so increment is the proper operation.) + +@codef{loud-abs(@pragma(defn)@index(loud-abs)@i(volume), @i(beh))}@\Evaluates @i(beh) with @code(*loud*) +set to @i(volume). + +@label(sound-srate-abs-sec) +@codef{sound-srate-abs(@pragma(defn)@index(sound-srate-abs)@i(srate), @i(beh))}@\Evaluate @i(beh) with @code(*sound-srate*@index(*sound-srate*)) set to sample rate @i(srate). @p(Note:) there is no ``relative'' version of this function. + +@codef{stretch(@pragma(defn)@index(stretch)@i(factor), @i(beh))}@\Evaluates @i(beh) with +@code(*warp*) scaled by @i(factor). The effect is to ``stretch'' the result +of @i(beh) (under the current environment) by @i(factor). See Chapter +@ref(warp-chap) for more information. Use @code[get-duration(@i(dur))] to +get the nominal actual duration of a behavior that locally has a duration +of @i(dur). Here, ``nominal'' means what would be expected if the behavior +obeys the shift, stretch, and warp components of the environment. (Any +behavior is free to deviate from the nominal timing. For example, a percussion +sound might have a fixed duration independent of the stretch factor.) Also, +``actual'' means global or absolute time, and ``locally'' means within the +environment where @code[get-duration] is called. @code[get-duration] works +by mapping the current time (local time 0) using @code[local-to-global] to +obtain an actual start time, and mapping @i(dur) to obtain an actual end time. +The difference is returned. + +@codef{stretch-abs(@pragma(defn)@index(stretch-abs)@i(factor), @i(beh))}@\Evaluates @i(beh) with @code(*warp*) set to a linear time transformation where each unit of logical time maps to @i(factor) units of real time. The effect is to stretch the nominal behavior of @i(beh) (under the default global environment) by @i(factor). See Chapter @ref(warp-chap) for more information. + +@codef{sustain(@pragma(defn)@index(sustain)@index(legato)@index(overlap)@index(stacatto)@i(factor), @i(beh))}@\Evaluates @i(beh) with @code(*sustain*) scaled by @i(factor). The effect is to ``stretch'' the result of @i(beh) (under the current environment) by @i(factor); however, the logical stop times are not stretched. Therefore, the overall duration of a sequence is not changed, and sounds will tend to overlap if @code(*sustain*) is greater than one (legato) and be separated by silence if @code(*sustain*) is less than one. + +@codef{sustain-abs(@pragma(defn)@index(sustain-abs)@i(factor), @i(beh))}@\Evaluates @i(beh) with @code(*sustain*) set to @i(factor). (See @code(sustain), above.) + +@codef{transpose(@pragma(defn)@index(transpose)@i(amount), @i(beh))}@\Evaluates @i(beh) with +@code(*transpose*) shifted by @i(amount). The effect is relative transposition by @i(amount) semitones. + +@codef{transpose-abs(@pragma(defn)@index(transpose-abs)@i(amount), @i(beh))}@\Evaluates @i(beh) with +@code(*transpose*) set to @i(amount). The effect is the transposition of the nominal pitches in @i(beh) (under the default global environment) by @i(amount). + +@codef{warp(@pragma(defn)@index(warp)@i(fn), @i(beh))}@\Evaluates @i(beh) with @code(*warp*) modified by @i(fn). The idea is that @i(beh) and @i(fn) are written in the same time system, and @i(fn) warps that time system to local time. The current environment already contains a mapping from local time to global (real) time. The value of @code(*warp*) in effect when @i(beh) is evaluated is the functional composition of the initial @code(*warp*) with @i(fn). + +@codef{warp-abs(@pragma(defn)@index(warp-abs)@i(fn), @i(beh))}@\Evaluates @i(beh) with @code(*warp*) set to @i(fn). In other words, the current @code(*warp*) is ignored and not composed with @i(fn) to form the new @code(*warp*). +@end(fndefs) + +@section(Combination and Time Structure)@index(Combination)@index(Time Structure) +These behaviors combine component behaviors into structures, including +sequences (melodies), simultaneous sounds (chords), and structures based +on iteration. + +@begin(fndefs) +@label(seq-sec) + @codef{seq(@pragma(defn)@index(seq)@i(beh@-[1])[ ,@i(beh@-[2]), ...])}@\Evaluates the first behavior +@i(beh@-[1]) according to @code(*time*) and each successive behavior at the +@code(logical-stop) time of the previous one. The results are summed to form a +sound whose @code(logical-stop) is +the @code(logical-stop) of the last behavior in the sequence. Each behavior +can result in a multichannel sound, in which case, the logical stop time is +considered to be the maximum logical stop time of any channel. The number +of channels in the result is the number of channels of the first behavior. +If other behaviors return fewer channels, new channels are created containing +constant zero signals until the required number of channels is obtained. If +other behaviors return a simple sound rather than multichannel sounds, the +sound is automatically assigned to the first channel of a multichannel sound +that is then filled out with zero signals. If another behavior returns more +channels than the first behavior, the error is reported and the computation +is stopped. Sample rates are converted up or down to match the sample rate of the first sound in a sequence. + +@codef{seqrep(@pragma(defn)@index(seqrep)@i(var), @i(limit), @i(beh))}@\Iteratively +evaluates @i(beh) with the atom +@i(var) set with values from 0 to @i(limit)-1, inclusive. These sounds +are placed sequentially in time as if by @code(seq). The symbol @i(var) is +a @i(read-only) local variable to @i(beh). Assignments are not restricted +or detected, but may cause a run-time error or crash. In LISP, the syntax is + @code[(seqrep (@i(var) @i(limit)) @i(beh))]. + +@label(sim-sec) +@codef{sim(@pragma(defn)@index(sim)[@i(beh@-[1]), @i(beh@-[2]), ...])}@\Returns a sound which is the +sum of the given behaviors evaluated with current value of @code(*warp*). +If behaviors return multiple channel sounds, the corresponding channels are +added. If the number of channels does not match, the result has the +maximum. For example, if a two-channel sound [L, R] is added to a four-channel +sound [C1, C2, C3, C4], the result is [L + C1, R + C2, C3, C4]. Arguments to @code(sim) may also be numbers. If all arguments are numbers, @code(sim) is equivalent (although slower than) the @code(+) function. If a number is added to a sound, @code(snd-offset) is used to add the number to each sample of the sound. The result of adding a number to two or more sounds with different durations is not defined. Use @code(const) to coerce a number to a sound of a specified duration. An important limitation of @code(sim) is that it cannot handle hundreds of behaviors due to a stack size limitation in XLISP. To compute hundreds of sounds (e.g. notes) at specified times, see @code(timed-seq), below. +See also @code(sum) below. + +@codef{simrep(@pragma(defn)@index(simrep)@i(var), @i(limit), @i(beh))}@\Iteratively +evaluates @i(beh) with the atom +@i(var) set with values from 0 to @i(limit)-1, inclusive. These sounds +are then placed simultaneously in time as if by @code(sim). +In LISP, the syntax is + @code[(seqrep (@i(var) @i(limit)) @i(beh))]. + +@label(trigger-sec) +@codef[trigger(@pragma(defn)@index(trigger)@i(s), @i(beh))]@\Returns a sound which is the +sum of instances of the behavior @i(beh). One instance is created each time +@code(SOUND) @i(s) makes a transition from less than or equal to zero to +greater than zero. (If the first sample of @i(s) is greater than zero, an +instance is created immediately.) The sample rate of @i(s) and all behaviors +must be the same, and the behaviors must be (monophonic) @code(SOUND)s. +This function is particularly designed to allow behaviors to be invoked +in real time by making @i(s) a function of a Nyquist slider, which can be +controlled by a graphical interface or by OSC messages. See @code(snd-slider) +in Section @ref(snd-slider-sec). + +@codef[set-logical-stop(@pragma(defn)@index(set-logical-stop)@i(beh), @i(time))]@\Returns a sound with @i(time) as +the logical stop time. + +@codef{sum(@pragma(defn)@index(sum)@index(mix)@i(a)[ ,@i(b), @i(c), ...])}@\Returns the sum of @i(a), @i(b), @i(c), ..., allowing mixed addition of sounds, multichannel sounds and numbers. Identical to @i(sim). + +@codef{mult(@pragma(defn)@index(mult)@index(product)@index(multiply signals)@i(a)[ ,@i(b), @i(c), ...])}@\Returns the product of @i(a), @i(b), @i(c), ..., allowing mixed multiplication of sounds, multichannel sounds and numbers. + +@codef{diff(@pragma(defn)@index(diff)@index(difference of sounds)@i(a), @i(b))}@\Returns the difference between @i(a) and @i(b). This function is defined as @code[(sum a (prod -1 b))]. + +@label(timed-seq-sec) +@codef{timed-seq(@pragma(defn)@index(timed-seq)@index(score)@index(note list)@i(score))}@\Computes sounds from a note list or ``score.'' The @i(score) +is of the form: @code[`((@i(time1) @i(stretch1) @i(beh1)) (@i(time2) +@i(stretch2) @i(beh2)) ...)], where @i(timeN) is the starting time, +@i(stretchN) is the stretch factor, and @i(behN) is the behavior. Note +that @i(score) is normally a @i(quoted list)! The times must be in +increasing order, and each @i(behN) is evaluated using lisp's @code(eval), +so the @i(behN) behaviors cannot refer to local parameters or local +variables. The advantage of this form over @code(seq) is that the +behaviors are evaluated one-at-a-time which can take much less stack +space and overall memory. One special ``behavior'' expression is +interpreted directly by @code(timed-seq): @code[(SCORE-BEGIN-END)] +is ignored, not evaluated as a function. Normally, this special +behavior is placed at time 0 and has two parameters: the score +start time and the score end time. These are used in Xmusic +functions. If the behavior has a @code(:pitch) keyword parameter +which is a list, the list represents a chord, and the expression is +replaced by a set of behaviors, one for each note in the chord. +It follows that if @code(:pitch) is @code(nil), the behavior +represents a rest and is ignored. + +@end(fndefs) + + +@section(Sound File Input and Output) +@index(sound file I/O) +@begin(fndefs) +@label(play-sec) +@codef[play @pragma(defn)@index(play)@i(sound)]@\Play the sound +through the DAC. +Note that @code(play) is a command in SAL. In XLISP, it is a function, +so the syntax is @code[(play @i(sound))], and in SAL, you can call the +XLISP function as @code[#play(@i(sound))]. +The @code(play) command or function +writes a file and plays it. The details of this +are system-dependent, but @code(play) is defined in the file +@code(system.lsp). The variable @code(*default-sf-dir*)@index(sound file directory default)@index(directory, default sound file)@index(default sound file directory)@index(temporary sound files directory) +@index(*default-sf-dir*) names a directory into which to save a sound file. Be careful not to call @code(play) or @code(sound-play) within a function and then +invoke that function from another @code(play) command. + +By default, Nyquist will try to normalize sounds using the method named by +@code(*autonorm-type*), which is @code('lookahead) by default. +The @i(lookahead) method precomputes and buffers @code(*autonorm-max-samples*) +samples, finds the peak value, and normalizes accordingly. The +@code('previous) method bases the normalization of the current sound on the peak value of the (entire) previous sound. This might be good if you are working with long sounds that start rather softly. See Section @ref(peak-ex-sec) for more details. + +If you want precise control over output levels, you should turn this feature off by typing: +@begin(example) +autonorm-off()@index(autonorm-off) +@end(example) +Reenable the automatic normalization feature by typing: +@begin(example)@index(autonorm-on) +autonorm-on() +@end(example) + +Play normally produces real-time output. The default is to send audio data to the DAC as it is computed in addition to saving samples in a file. If computation is slower than real-time, output will be choppy, but since the samples end up in a file, you can type @code[(r)] to replay the stored sound. Real-time playback can be disabled by: +@begin(example) +sound-off()@index(sound-off) +@end(example) +and reenabled by: +@begin(example) +sound-on()@index(sound-on) +@end(example) +Disabling real-time playback has no effect on @code[(play-file)] or @code[(r)]. + +While sounds are playing, typing control-A@index(control-A) to Nyquist will push the estimated +elapsed@index(elapsed audio time) audio time onto the head of the list +stored in @code(*audio-markers*). +@index(*audio-markers*)@index(audio markers)@index(markers, audio) +Because samples are computed in blocks and because there is latency +between sample computation and sample playback, the elapsed time may not +be too accurate, and the computed elapsed time may not advance after all +samples have been computed but the sound is still playing. + +@codef[play-file(@pragma(defn)@index(play-file)@i(filename))]@\Play the contents of a sound file named by @i(filename). The @code(s-read) function is used to read the file, and unless +@i(filename) specifies an absolute path or starts with ``.'', it will be read from +@code(*default-sf-dir*). + +@codef[autonorm-on(@pragma(defn)@index(autonorm-on))]@\Enable automatic adjustment of a scale factor applied to sounds computed using the @code(play) command. + +@codef[autonorm-off(@pragma(defn)@index(autonorm-off))]@\Disable automatic adjustment of a scale factor applied to sounds computed using the @code(play) command. + +@codef[sound-on(@pragma(defn)@index(sound-on))]@\Enable real-time audio output when sound is computed by the the @code(play) command. + +@codef[sound-off(@pragma(defn)@index(sound-off))]@\Disable real-time audio output when sound is computed by the the @code(play) command. + +@label(s-save-sec) +@codef{s-save(@pragma(defn)@index(s-save)@index(save samples to file)@index(write samples to file)@index(output samples to file)@i(expression), @i(maxlen), +@i(filename)[ ,format: @i(format)] [, mode: @i(mode)] [, bits: @i(bits)] [, swap: @i(flag)] [, play: @i(play)])}@\@label(s-save)Evaluates the @i(expression), which should result in a sound +or an array of sounds, and writes the result to the given @i(filename). A +@code(FLONUM) is returned giving the maximum absolute value of all samples +written. (This is useful for normalizing sounds and detecting sample +overflow.) If @i(play) is not @code(NIL), the sound will be output through the computer's audio output system. (@i(:play) is not implemented on all systems; if it is implemented, and @i(filename) is @code(NIL), then this will play the file without also writing a file.) +The latency (length of audio buffering) used to play the sound is 0.3s by default, but see @code(snd-set-latency). +If +a multichannel sound (array) is written, the channels are up-sampled to the +highest rate in any channel so that all channels have the same sample rate. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. A +header is written according to @i(format), samples are encoded according to +@i(mode), using @i(bits) bits/sample, and bytes are swapped if @i(swap) is not NIL. Defaults for these are +@code(*default-sf-format*), @code(*default-sf-mode*), and +@code(*default-sf-bits*). The default for @i(swap) is NIL. +The @i(bits) parameter may be 8, 16, or 32. The values for the @i(format) and @i(mode) options are described below: +@end(fndefs) +@b(Format) +@begin(description, leftmargin +2 in, indent -2 in) +@code(snd-head-none)@\The format is unknown and should be determined +by reading the file. + +@code(snd-head-raw)@\A raw format file has no header. + +@code(snd-head-AIFF)@\AIFF format header. + +@code(snd-head-IRCAM)@\IRCAM format header. + +@code(snd-head-NeXT)@\1024-byte NeXT/SUN format header followed by IRCAM +header ala CMIX. Note that the NeXT/SUN format has a header-length field, +so it really is legal to have a large header, even though the normal minimal +header is only 24 bytes. The additional space leaves room for maximum +amplitudes, which can be used for normalizing floating-point soundfiles, and +for other data. Nyquist follows the CMIX convention of placing an IRCAM +format header immediately after the NeXT-style header. + +@code(snd-head-Wave)@\Microsoft Wave format header. + +@code(snd-head-*)@\See sndfnint.lsp for more formats. +@end(description) + +@b(Mode) +@begin(description, leftmargin +2 in, indent -2 in) +@code(snd-mode-adpcm)@\ADPCM mode (not supported). + +@code(snd-mode-pcm)@\signed binary PCM mode. + +@code(snd-mode-ulaw)@\8-bit U-Law mode. + +@code(snd-mode-alaw)@\8-bit A-Law mode (not supported). + +@code(snd-mode-float)@\32-bit floating point mode. + +@code(snd-mode-upcm)@\unsigned binary PCM mode. + +@code(snd-mode-*)@\See sndfnint.lsp for more modes. +@end(description) + +The defaults for format, mode, and bits are as follows: +@begin(description, leftmargin +2 in, indent -2 in) +NeXT and Sun machines:@\@code(snd-head-NeXT), @code(snd-mode-pcm), +@code(16) + +SGI and Macintosh machines:@\@code(snd-head-AIFF), @code(snd-mode-pcm), @code(16) + +@end(description) + +@begin(fndefs) +@label(s-read-sec) +@codef{s-read(@pragma(defn)@index(s-read)@index(read samples from file)@i(filename)[ ,time-offset: @i(offset)] [, srate: +@i(sr)] [, dur: @i(dur)] [, nchans: @i(chans)] [, format: @i(format)] [, mode: @i(mode),] [bits: @i(n)] [, swap: @i(flag)])}@\Reads a sound from + @i(filename). The global @code(*default-sf-dir*) applies. If a header is +detected, the header is used to determine the format +of the file, and header information overrides format information provided by +keywords (except for @code(:time-offset) and @code(:dur)). +@begin(example) +s-read("mysound.snd", srate: 44100) +@end(example) +specifies a sample rate of 44100 hz, but if the file has a header specifying 22050 hz, the resulting sample rate will be 22050. The parameters are: +@begin(itemize) + @code(:time-offset) @itemsep the amount of time (in seconds) to skip from +the beginning of the file. The default is 0.0. + +@code(:srate) @itemsep the sample rate of the samples in the file. Default is +@code(*default-sf-srate*) @index(*default-sf-srate*), which is normally 44100. + + @code(:dur) @itemsep the maximum duration in seconds to read. Default is +10000. + + @code(:nchans) @itemsep the number of channels to read. It is assumed that +samples from each channel are interleaved. Default is 1. + + @code(:format) @itemsep the header format. See @code(s-save) for details. +Default is @code(*default-sf-format*), although this parameter is currently +ignored. + + @code(:mode) @itemsep the sample representation, e.g. PCM or float. See +@code(s-save) for details. Default is @code(*default-sf-format*). + + @code(:bits) @itemsep the number of bits per sample. See @code(s-save) for +details. Default is @code(*default-sf-bits*). + + @code(:swap) @itemsep (T or NIL) swap byte order of each sample. Default is NIL. +@end(itemize) +If there is an error, for example if @code(:time-offset) is greater than the length of the file, then @code(NIL) is returned rather than a sound. Information about the sound is also returned by @code(s-read) through @code(*rslt*)@foot(Since XLISP does not support multiple value returns, multiple value returns are simulated by having the function assign additional return values in a list to the global variable @code(*rslt*). Since this is a global, it should be inspected or copied immediately after the function return to insure that return values are not overwritten by another function.). The list assigned to @code(*rslt*) is of the form: (@i(format) @i(channels) @i(mode) @i(bits) @i(samplerate) @i(duration) @i(flags) @i(byte-offset)), which are defined as follows: +@begin(itemize) +@i(format) @itemsep the header format. See @code(s-save) for details. + +@i(channels) @itemsep the number of channels. + +@i(mode) @itemsep the sample representation, e.g. PCM or float. See @code(s-save) for details. + +@i(bits) @itemsep the number of bits per sample. + +@i(samplerate) @itemsep the sample rate, expressed as a @code(FLONUM). + +@i(duration) @itemsep the duration of the sound, in seconds. + +@i(flags) @itemsep The values for @i(format), @i(channels), @i(mode), @i(bits), @i(samplerate), and @i(duration) are initially just the values passed in as parameters or default values to @code(s-read). If a value is actually read from the sound file header, a flag is set. The flags are: @code(snd-head-format), @code(snd-head-channels), @code(snd-head-mode), @code(snd-head-bits), @code(snd-head-srate), and @code(snd-head-dur). For example, +@begin(example) +(let ((flags (caddr (cddddr *rslt*)))) + (not (zerop (logand flags snd-head-srate)))) +@end(example) +tells whether the sample rate was specified in the file. See also @code(sf-info) below. + +@i(byte-offset) @itemsep the byte offset into the file of the first sample +to be read (this is used by the @code(s-overwrite) and @code(s-add-to) +functions). +@end(itemize) + +@codef{s-add-to(@pragma(defn)@index(s-add-to)@index(add to file samples)@index(mix to file)@i(expression), @i(maxlen), +@i(filename)[ ,@i(offset)])}@\@label(s-add-to-sec)Evaluates the @i(expression), which should result in a sound +or an array of sounds, and adds the result to the given @i(filename). +The global @code(*default-sf-dir*) applies. A @code(FLONUM) is returned, +giving the maximum absolute value of all samples written. The +sample rate(s) of @i(expression) must match those of the file. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. +If @i(offset) is specified, the new sound is added to the file beginning at +an @i(offset) from the beginning (in seconds). The file is extended if +necessary to accommodate the new addition, but if @i(offset) +falls outside of the original file, the file is not modified. (If necessary, +use @code(s-add-to) to extend the file with zeros.) +The file must be a recognized +sound file with a header (not a raw sound file). + + +@codef{s-overwrite(@pragma(defn)@index(s-overwrite)@index(replace file samples)@index(overwrite samples)@i(expression), @i(maxlen), @i(filename)[ ,@i(offset)])}@\@label(s-overwrite-sec)Evaluates +the @i(expression), which should result in a sound +or an array of sounds, and replaces samples in the given @i(filename). +The global @code(*default-sf-dir*) applies. +A @code(FLONUM) is returned, giving the maximum absolute value of all +samples written. The +sample rate(s) of @i(expression) must match those of the file. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. +If @i(offset) is specified, the new sound is written to the file beginning at +an @i(offset) from the beginning (in seconds). The file is extended if +necessary to accommodate the new insert, but if @i(offset) falls outside of +the original file, the file is not modified. (If necessary, use +@code(s-add-to) to extend the file with zeros.) The file must be a recognized +sound file with a header (not a raw sound file). + +@codef{sf-info(@pragma(defn)@index(sf-info)@index(sound file info)@i(filename))}@\Prints information about a sound file. The parameter @i(filename) is a string. The file is assumed to be in *default-sf-dir* (see @code(soundfilename) below) unless the filename begins with ``.'' or ``/''. The source for this function is in the @code(runtime) and provides an example of how to determine sound file parameters. + +@codef{soundfilename(@pragma(defn)@index(soundfilename)@i(name))}@\Converts a string @i(name) to a soundfile name. If @i(name) begins with ``.'' or ``/'', the name is returned without alteration. Otherwise, a path taken from @code(*default-sf-dir*) is prepended to @i(name). The @code(s-plot), @code(s-read), and @code(s-save) functions all use @code(soundfilename) translate filenames. + +@codef{s-plot(@pragma(defn)@index(s-plot)@i(sound)[, @i(n), @i(dur)])}@\Plots sound in a window. This function was designed to run a @code(plot) program on a Unix workstation, but now is +primarily used with @code(jNyqIDE), which has self-contained plotting. Normally, +time/value pairs in ascii are written to @code(points.dat) and system-dependent code +(or the @code(jNyqIDE) program) takes it from there. If the @i(sound) is +longer than the optional @i(dur) (default is 2 seconds), only the +first @i(dur) seconds are plotted. +If there are more than @i(n) samples to be plotted, the signal is interpolated +to have @i(n) samples before plotting. +The data file used is: +@begin(description, leftmargin +2 in, indent -2 in) +@codef(*default-plot-file*)@pragma(defn)@index(*default-plot-file*)@\The file containing the data points, defaults to "points.dat". +@end(description) + +@codef{s-print-tree(@pragma(defn)@index(s-print-tree)@index(snd-print-tree)@i(sound))}@\Prints an ascii +representation of the internal data structures representing a sound. This +is useful for debugging@index(debugging) Nyquist. Identical to @code(snd-print-tree). + +@end(fndefs) + +@section(Low-level Functions) +Nyquist includes many low-level functions that are used to implement the functions and behaviors described in previous sections. For completeness, these functions are described here. Remember that +these are low-level functions that are not intended for normal use. Unless +you are trying to understand the inner workings of Nyquist, you can skip this section. + +@subsection(Creating Sounds) +The basic operations that create sounds are described here. + +@begin(fndefs) + +@codef[snd-const(@pragma(defn)@index(snd-const)@i(value), @i(t0), @i(srate), +@i(duration))]@\Returns a sound with constant @i(value), starting at @i(t0) +with the given @i(duration), at the sample rate @i(srate). You might want +to use @code(pwl) (see Section @ref(pwl-sec)) instead. + +@codef[snd-read(@pragma(defn)@index(snd-read)@i(filename), @i(offset), @i(t0), @i(format), +@i(channels), @i(mode), @i(bits), @i(swap), @i(sr), +@i(dur))]@\Loads a sound from a file with name @i(filename). Files are +assumed to consist of a header followed by frames consisting of one sample +from each channel. The @i(format) specifies the type of header, but this +information is currently ignored. Nyquist looks for a number of header +formats and automatically figures out which format to read. If a header can +be identified, the header is first read from the file. Then, the file +pointer is advanced by the indicated +@i(offset) (in seconds). If there is an unrecognized header, Nyquist will +assume the file has no header. If the header size is a multiple of the +frame size (bytes/sample * number-of-channels), you can use @i(offset) to +skip over the header. To skip N bytes, use an @i(offset) of: +@begin(example) +(/ (float N) @i(sr) (/ @i(bits) 8) @i(channels)) +@end(example) +If the header is not a multiple of the frame size, either write a header or +contact the author (dannenberg@@cs.cmu.edu) for assistance. Nyquist will +round @i(offset) to the nearest sample. The resulting sound will start at +time @i(t0). If a header is found, the file will be interpreted according +to the header information. If no header was found, @i(channels) tells how +many channels there are, the samples are encoded according to @i(mode), the +sample length is @i(bits), and @i(sr) is the sample rate. The @i(swap) flag is 0 or 1, where 1 means to swap sample bytes. The duration to +be read (in seconds) is given by @i(dur). If @i(dur) is longer than the +data in the file, then a shorter duration will be returned. If the file +contains one channel, a sound is returned. If the file contains 2 or more +channels, an array of sounds is returned. @p(Note:) you probably want to +call @code(s-read) (see Section @ref(s-read-sec)) instead of +@code(snd-read). Also, see Section @ref(s-read-sec) for information on the +@i(mode) and @i(format) parameters. + +@codef[snd-save(@pragma(defn)@index(snd-save)@i(expression), @i(maxlen), +@i(filename), @i(format), @i(mode), @i(bits), @i(swap), @i(play))]@\@label(snd-save)Evaluates +the @i(expression), which should result in a sound +or an array of sounds, and writes the result to the given @i(filename). If +a multichannel sound (array) is written, the channels are up-sampled to the +highest rate in any channel so that all channels have the same sample rate. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. A +header is written according to @i(format), samples are encoded according to +@i(mode), using @i(bits) bits/sample, and swapping bytes if @i(swap) is 1 (otherwise it should be 0). +If @i(play) is not null, the audio is played in real time (to the extent possible) as it is computed. The peak value of the sound is returned. In addition, +the symbol @code(*RSLT*) is bound to a list containing the sample rate, +number of channels, and duration (in that order) of the saved sound. +@p(Note:) you probably want to call +@code(s-save) (see Section @ref(s-save-sec)) instead. The @i(format) and +@i(mode) parameters are described in Section @ref(s-save-sec). + +@codef[snd-overwrite(@pragma(defn)@index(snd-overwrite)@i(expression), @i(maxlen), @i(filename), @i(offset), @i(format), @i(mode), @i(bits), @i(swap))]@\@label(snd-overwrite-sec)Evaluates +the @i(expression), which should result in a sound +or an array of sounds, and replaces samples in the given @i(filename), +writing the first frame at a time of @i(offset) seconds. The @i(offset) must +be less than or equal to the duration of the existing file. The +duration of the written samples may +be greater than that of the file, in which case the file is extended +as necessary. The +sample rate(s) of @i(expression) and the number of channels +must match those of the file. If @i(format) is + @code(SND-HEAD-RAW), then the file +format is given by @i(mode) (see +@code(snd-save), @i(bits) (per channel), @i(swap) (1 means to +swap bytes and 0 means write them in the native byte order), and the +number of channels and sample rate of the sound returned by evaluating +@i(expression). If the +file is a known +audio file format, @i(format) should be @code(SND-HEAD-NONE), and the +other parameters are ignored. Up to a maximum of @i(maxlen) +samples will be written per channel. The peak value of the sound is returned. +In addition, the symbol @code(*RSLT*) is bound to a list containing the +duration of the written sound (which may not be the duration of the sound +file). +Use @code(s-add-to) (in Section @ref(s-add-to-sec) or +@code(s-overwrite) (in Section @ref(s-overwrite-sec) instead of this function. + +@codef[snd-coterm(@pragma(defn)@index(snd-coterm)@index(co-termination)@index(duration of +another sound)@i(s1), @i(s2))]@\Returns a copy of @i(s1), except the start +time is the maximum of the start times of @i(s1) and @i(s2), and the +termination time is the minimum of @i(s1) and @i(s2). (After the termination +time, the sound is zero as if @i(s1) is gated by @i(s2).) Some rationale +follows: In order to implement @code(s-add-to), we need to read from the +target sound file, add the sounds to a new sound, and overwrite the result +back into the file. We only want to write as many samples into the file as +there are samples in the new sound. However, if we are adding +in samples read from +the file, the result of a @code(snd-add) in Nyquist will have the maximum +duration of either sound. Therefore, we may read to the end of the file. +What we need is a way to truncate the read, but we cannot easily do that, +because we do not know in advance how long the new sound will be. The +solution is to use @code(snd-coterm), which will allow us to truncate the +sound that is read from the file (@i(s1)) according to the duration of the +new sound (@i(s2)). When this truncated sound is added to the new sound, +the result will have only the duration of the new sound, and this can be +used to overwrite the file. This function is used in the implementation of +@code(s-add-to), which is defined in @code(runtime/fileio.lsp). + +@codef[(snd-from-array @i(...))]@\See @pragma(startref) page @pageref(snd-from-array-sec). + +@codef[snd-white(@pragma(defn)@index(snd-white)@i(t0), @i(sr), @i(d))]@\Generate white noise, starting at +@i(t0), with sample rate @i(sr), and duration @i(d). You probably want to +use @code(noise) (see Section @ref(noise-sec)). + + @codef[snd-zero(@pragma(defn)@index(snd-zero)@i(t0), @i(srate))]@\Creates a sound that is +zero everywhere, starts at @i(t0), and has sample rate @i(srate). The +logical stop time is immediate, i.e. also at @i(t0). You probably want +to use @code(pwl) (see Section @ref(pwl-sec)) instead. + + @codef[get-slider-value(@pragma(defn)@index(get-slider-value)@i(index))]@\@label(get-slider-value-sec)Return the current value of the slider +named by @i(index) (an integer index into the array of sliders). +Note that this ``slider'' is just a floating point +value in an array. Sliders can be changed by OSC messages (see @code(osc-enable)) and by sending character +sequences to Nyquist's standard input. (Normally, these character sequences would +not be typed but generated by the jNyqIDE interactive development environment, which +runs Nyquist as a sub-process, and which present the user with graphical sliders.) + +@codef[snd-slider(@pragma(defn)@index(snd-slider)@i(index), @i(t0), @i(srate), @i(duration))]@\@label(snd-slider-sec)Create +a sound controlled by the slider named by @i(index) (an integer +index into the array of sliders; see @code(get-slider-value) for more information). +The function returns a sound. Since Nyquist sounds are computed in blocks of samples, +and each block is computed at once, each block will contain copies of the current slider +value. To obtain reasonable responsiveness, slider sounds should have high (audio) +sample rates so that the block rate will be reasonably high. Also, consider lowering the audio +latency using @code(snd-set-latency). To ``trigger'' a Nyquist behavior using slider input, see the @code(trigger) function in Section @ref(trigger-sec). + +@end(fndefs) + +@subsection(Signal Operations) +This next set of functions take sounds as arguments, operate on them, and +return a sound. + +@begin(fndefs) +@codef[snd-abs(@pragma(defn)@index(snd-abs)@index(absolute value)@i(sound))]@\Computes a new +sound where each sample is the absolute value of the corresponding sample in +@i(sound). You should probably use @code(s-abs) instead. (See Section @ref(s-abs-sec).) + +@codef[snd-sqrt(@pragma(defn)@index(snd-sqrt)@index(square root)@i(sound))]@\Computes a new +sound where each sample is the square root of the corresponding sample in +@i(sound). If a sample is negative, it is taken to be zero to avoid raising a floating point error. You should probably use @code(s-sqrt) instead. (See Section @ref(s-sqrt-sec).) + + @codef[snd-add(@pragma(defn)@index(snd-add)@i(sound1), @i(sound))]@\Adds two sounds. The +resulting start time is the minimum of the two parameter start times, the +logical stop time is the maximum of the two parameter stop times, and the +sample rate is the maximum of the two parameter sample rates. Use +@code(sim) or @code(sum) instead of @code(snd-add) (see Section @ref(sim-sec)). + +@codef[snd-offset(@pragma(defn)@index(snd-offset)@index(offset to a sound)@index(add +offset to sound)@i(sound), @i(offset))]@\Add an offset to a sound. The +resulting start time, logical stop time, stop time, and sample rate are +those of @i(sound). Use @code(sum) instead (see Section @ref(sim-sec)). + +@codef[snd-avg(@pragma(defn)@index(snd-avg)@index(moving average)@index(RMS)@index(average)@i(sound), @i(blocksize), @i(stepsize), @i(operation))]@\Computes the averages +or peak values of blocks of samples. Each output sample is an average or +peak of @i(blocksize) (a fixnum) adjacent samples from the input @i(sound). +After each average or peak is taken, the input is advanced by @i(stepsize), +a fixnum which may be greater or less than @i(blocksize). The output +sample rate is the @i(sound) (input) sample rate divided by @i(stepsize). +This function is useful for computing low-sample-rate rms or peak +amplitude signals for input to @code(snd-gate) or @code(snd-follow). +To select the operation, @i(operation) should be one of @code(OP-AVERAGE) +or @code(OP-PEAK). (These are global lisp variables; the actual +@i(operation) parameter is an integer.) For RMS computation, see +@code(rms) in Section @ref(rms-sec). + +@codef[snd-clip(@index(clip)@pragma(defn)@index(snd-clip)@i(sound), @i(peak))]@\Hard limit @i(sound) +to the given @i(peak), a positive number. The samples of @i(sound) are constrained between an upper value +of @i(peak) and a lower value of @subtract()@i(peak). Use @code(clip) instead (see Section @ref(clip-sec)). + +@codef[snd-compose(@index(compose)@index(signal composition)@pragma(defn)@index(snd-compose)@i(f), @i(g))]@\Compose two signals, i.e. +compute @i(f)(@i(g)(@i(t))), where @i(f) and @i(g) are sounds. This function +is used primarily to implement time warping, but it can be used in other +applications such as frequency modulation. For each sample @i(x) in @i(g), +@i(snd-compose) looks up the value of @i(f)(@i(x)) using linear +interpolation. The resulting sample rate, start time, etc. are taken from +@i(g). The sound @i(f) is used in effect as a lookup table, but it is +assumed that @i(g) is non-decreasing, so that @i(f) is accessed in time +order. This allows samples of @i(f) to be computed and discarded +incrementally. If in fact @i(g) decreases, the current sample of @i(g) is +replaced by the previous one, forcing @i(g) into compliance with the +non-decreasing restriction. See also @code(sref), @code(shape), and +@code(snd-resample). + +For an extended example that uses @code(snd-compose) for variable pitch shifting, +see @code(demos/pitch_change.htm).@index(demos, pitch change)@index(pitch shifting) +@index(variable-resample function)@index(resampling) + +@label(snd-tapv-sec) +@codef[snd-tapv(@pragma(defn)@index(snd-tapv)@index(tap)@index(variable delay)@index(delay, +variable)@index(chorus)@i(sound), @i(offset), @i(vardelay), @i(maxdelay))]@\A +variable delay: @i(sound) is delayed by the sum of @i(offset) (a @code(FIXNUM) or @code(FLONUM)) +and @i(vardelay) (a @code(SOUND)). The specified delay is adjusted to lie in the range +of zero to @i(maxdelay) seconds to yield the actual delay, and the delay is +implemented using linear interpolation. This function was designed specifically +for use in a chorus effect: the @i(offset) is set to half of @i(maxdelay), and +the @i(vardelay) input is a slow sinusoid. The maximum delay is limited to +@i(maxdelay), which determines the length of a fixed-sized buffer. The function +@code(tapv) is equivalent and preferred (see Section @ref(tapv-sec)). + +@codef[snd-tapf(@pragma(defn)@index(snd-tapf)@index(variable delay)@index(delay, variable)@i(sound), @i(offset), @i(vardelay), @i(maxdelay))]@\A +variable delay like @code(snd-tapv) except there is no linear interpolation. By +eliminating interpolation, the output is an exact copy of the input with no filtering +or distortion. On the other hand, delays jump by samples causing samples to double or +skip even when the delay is changed smoothly. + +@codef[snd-copy(@pragma(defn)@index(snd-copy)@i(sound))]@\Makes a copy of @i(sound). +Since operators always make (logical) copies of their sound parameters, this +function should never be needed. This function is here for debugging@index(dubugging). + +@codef[snd-down(@pragma(defn)@index(snd-down)@i(srate), @i(sound))]@\Linear interpolation +of samples down to the given sample rate @i(srate), which must be lower than +the sample rate of @i(sound). Do not call this function. Nyquist performs +sample-rate conversion automatically as needed. If you want to force a +conversion, call @code(force-srate) (see Section @ref(force-srate-sec)). + +@codef[snd-exp(@pragma(defn)@index(snd-exp)@i(sound))]@\Compute the exponential of each sample of @i(sound). Use @code(s-exp) instead (see Section @ref(s-exp-sec)). + +@label(snd-follow-sec) +@codef[snd-follow(@pragma(defn)@index(snd-follow)@index(follower)@index(envelope follower)@i(sound), @i(floor), @i(risetime), @i(falltime), @i(lookahead))]@\An envelope +follower. The basic goal of this function is to generate a smooth signal +that rides on the peaks of the input signal. The usual objective is to +produce an amplitude envelope given a low-sample rate (control rate) +signal representing local RMS measurements. The first argument is the +input signal. The @i(floor) is the minimum output value. The @i(risetime) is the time (in seconds) it takes for the output to rise (exponentially) from @i(floor) to unity (1.0) and the @i(falltime) is the time it takes for the output to fall (exponentially) from unity to @i(floor). The algorithm looks ahead for peaks and will begin to increase the output signal according to @i(risetime) in anticipation of a peak. The amount of anticipation (in sampless) is given by @i(lookahead). The algorithm is as follows: the output value is allowed to increase according to @i(risetime) or decrease according to @i(falltime). If the next input sample is in this range, that sample is simply output as the next output sample. If the next input sample is too large, the algorithm goes back in time as far as necessary to compute an envelope that rises according to @i(risetime) to meet the new value. The algorithm will only work backward as far as @i(lookahead). If that is not far enough, then there is a final forward pass computing a rising signal from the earliest output sample. In this case, the output signal will be at least momentarily less than the input signal and will continue to rise exponentially until it intersects the input signal. If the input signal falls faster than indicated by @i(falltime), the output fall rate will be limited by @i(falltime), and the fall in output will stop when the output reaches @i(floor). This algorithm can make two passes througth the buffer on sharply rising inputs, so it is not particularly fast. With short buffers and low sample rates this should not matter. See @code(snd-avg) above for a function that can help to generate a low-sample-rate input for @code(snd-follow). See @code(snd-chase) in Section @ref(snd-chase-sec) for a related filter. + +@codef[snd-gate(@pragma(defn)@index(snd-gate)@index(noise gate)@index(gate)@i(sound), @i(lookahead), @i(risetime), @i(falltime), @i(floor), @i(threshold))]@\This function generates an exponential rise and decay intended for noise gate implementation. The decay starts when the signal drops below threshold and stays there for longer than lookahead. Decay continues until the value reaches floor, at which point the decay stops and the output value is held constant. Either during the decay or after the floor is reached, if the signal goes above threshold, then the output value will rise to unity (1.0) at the point the signal crosses the threshold. Again, look-ahead is used, so the rise actually starts before the signal crosses the threshold. The rise is a constant-rate exponential and set so that a rise from @i(floor) to unity occurs in @i(risetime). Similarly, the fall is a constant-rate exponential such that a fall from unity to @i(floor) takes @i(falltime). The result is delayed by @i(lookahead), so the output is not actually synchronized with the input. To compensate, you should drop the initial @i(lookahead) of samples. Thus, @code(snd-gate) is not recommended for direct use. Use @code(gate) instead (see Section @ref(gate-sec)). + +@codef[snd-inverse(@index(inverse)@pragma(defn)@index(snd-inverse)@i(signal), @i(start), @i(srate))]@\Compute the function inverse of @i(signal), that is, compute @i(g)(@i(t)) such that @i(signal)(@i(g)(@i(t))) = @i(t). This function assumes that @i(signal) is non-decreasing, it uses linear interpolation, the resulting sample rate is @i(srate), and the result is shifted to have a starting time of @i(start). If @i(signal) decreases, the true inverse may be undefined, so we define @code(snd-inverse) operationally as follows: for each output time point @i(t), scan ahead in @i(signal) until the value of signal exceeds @i(t). Interpolate to find an exact time point @i(x) from @i(signal) and output @i(x) at time @i(t). This function is intended for internal system use in implementing time warps. + +@codef[snd-log(@pragma(defn)@index(snd-log)@i(sound))]@\Compute the natural logorithm of each sample of @i(sound). Use @code(s-log) instead (see Section @ref(s-log-sec)). + +@label(peak-sec) +@codef[peak(@index(peak, maximum amplitude)@pragma(defn)@index(peak)@i(expression), @i(maxlen))]@\Compute the maximum absolute value of the amplitude of a sound. The sound is created by evaluating @i(expression) (as in @code(s-save)). Only the first @i(maxlen) samples are evaluated. The @i(expression) is automatically quoted (@code(peak) is a macro), so do not quote this parameter. If @i(expression) is a variable, then the @i(global binding) of that variable will be used. Also, since the variable retains a reference to the sound, the sound will be evaluated and left in memory. See Section @ref(peak-ex-sec) on @pragma(startref) page @pageref(peak-ex-sec) for examples. + +@label(snd-max-sec) +@codef[snd-max(@pragma(defn)@index(snd-max)@index(maximum amplitude)@i(expression), @i(maxlen))]@\Compute the maximum absolute value of the amplitude of a sound. The sound is created by evaluating @i(expression) (as in @code(snd-save)), which is therefore normally quoted by the caller. At most @i(maxlen) samples are computed. The result is the maximum of the absolute values of the samples. @p(Notes:) It is recommended to use @code(peak) (see above) instead. If you want to find the maximum of a sound bound to a local variable and it is acceptable to save the samples in memory, then this is probably the function to call. Otherwise, use @code(peak). + +@codef[snd-maxv(@pragma(defn)@index(snd-maxv)@index(maximum of two sounds)@i(sound1), @i(sound2))]@\Compute the maximum of @i(sound1) and @i(sound2) on a sample-by-sample basis. The resulting +sound has its start time at the maximum of the input start times and a logical stop +at the minimum logical stop of the inputs. The physical stop time is the minimum of +the physical stop times of the two sounds. @i(Note that this violates the ``normal'' +interpretation that sounds are zero outside their start and stop times. For +example, even if) sound1 @i(extends beyond) sound2 @i(and is greater than zero, +the result +value in this extension will be zero because it will be after the physical stop time, +whereas if we simply treated) sound2 @i(as zero in this region and took the maximum, we +would get a non-zero result.) Use @code(s-max) instead (see Section @ref(s-max-sec)). + +@codef[snd-normalize(@pragma(defn)@index(snd-normalize)@i(sound))]@\Internally, sounds +are stored with a scale factor that applies to all samples of the sound. +All operators that take sound arguments take this scale factor into account +(although it is not always necessary to perform an actual multiply per +sample), so you should never need to call this function. This function +multiplies each sample of a sound by its scale factor, returning a sound +that represents the same signal, but whose scale factor is 1.0. + +@codef[snd-oneshot(@pragma(defn)@index(snd-oneshot)@index(oneshot)@index(threshold)@i(sound), @i(threshold), @i(ontime))]@\Computes a new sound that is zero +except where @i(sound) exceeds threshold. From these points, the result is +1.0 until @i(sound) remains below @i(threshold) for @i(ontime) (in seconds). +The result has the same sample rate, start time, logical stop time, and +duration as @i(sound). + +@codef[snd-prod(@pragma(defn)@index(snd-prod)@index(signal multiplication)@index(multiplication)@i(sound1), @i(sound2))]@\Computes the +product of @i(sound1) and @i(sound2). The resulting sound has its start +time at the maximum of the input start times and a logical stop at the minimum +logical stop of the inputs. Do not use this function. Use @code(mult) or +@code(prod) instead (see Section @ref(mult-sec)). Sample rate, start time, etc. are taken from @i(sound). + +@codef[snd-pwl(@pragma(defn)@index(snd-pwl)@index(piece-wise linear)@i(t0), @i(sr), +@i(lis))]@\Computes a piece-wise linear function according to the breakpoints +in @i(lis). The starting time is @i(t0), and the sample rate is @i(sr). +The breakpoints are passed in an XLISP list (of type @code(LVAL)) where the +list alternates sample numbers (@code(FIXNUM)s, computed in samples +from the beginning of the pwl function) and values (the value of the pwl +function, given as a @code(FLONUM)). There is an implicit starting +point of (0, 0). The list must contain an odd number of points, the omitted +last +value being implicitly zero (0). The list is assumed to be well-formed. Do +not call this function. Use @code(pwl) instead (see Section @ref(pwl-sec)). + +@codef[snd-quantize(@pragma(defn)@index(snd-quantize)@i(sound), @i(steps))]@\Quantizes a sound. See Section +@ref(quantize-sec) for details. + +@codef[snd-recip(@pragma(defn)@index(snd-recip)@i(sound))]@\Compute the reciprocal of each sample of @i(sound). Use @code(recip) instead (see Section @ref(recip-sec)). + +@codef[snd-resample(@pragma(defn)@index(snd-resample)@index(sample interpolation)@i(f), +@i(rate))]@\Resample sound @i(f) using high-quality interpolation, yielding +a new sound with the specified @i(rate). The result is scaled by 0.95 because often, +in resampling, interpolated values exceed the original sample values, and this +could lead to clipping. +The resulting start time, etc. are taken from +@i(f). Use @code(resample) instead. + +@codef[snd-resamplev(@pragma(defn)@index(snd-resamplev)@index(sample interpolation)@index(signal composition)@i(f), @i(rate), @i(g))]@\Compose two +signals, i.e. compute @i(f)(@i(g)(@i(t))), where @i(f) and @i(g) are +sounds. The result has sample rate given by @i(rate). At each time @i(t) +(according to the @i(rate)), @i(g) is linearly interpolated to yield an +increasing sequence of high-precision score-time values. @i(f) is then +interpolated at each value to yield a result sample. If in fact @i(g) +decreases, the current sample of @i(g) is replaced by the previous one, +forcing @i(g) into compliance with the non-decreasing restriction. +The result is scaled by 0.95 because often, +in resampling, interpolated values exceed the original sample values, and this +could lead to clipping. Note that +if @i(g) has a high sample rate, this may introduce unwanted jitter into +sample times. See @code(sound-warp) for a detailed discussion. See +@code(snd-compose) for a fast, low-quality alternative to this function. +Normally, you should use @code(sound-warp) instead of this function. + + +@codef[snd-scale(@pragma(defn)@index(snd-scale)@i(scale), @i(sound))]@\Scales the amplitude of @i(sound) by the factor @i(scale). Use @code(scale) instead (see Section +@ref(scale-sec)). + +@codef{snd-shape(@pragma(defn)@index(snd-shape)@i(signal), @i(table), @i(origin))}@\A waveshaping function. This is the primitive upon which @code(shape) is based. The @code(snd-shape) function is like @code(shape) except that @i(signal) and @i(table) must be (single-channel) sounds. Use @code(shape) instead (see Section @ref(shape-sec)). + +@codef[snd-up(@pragma(defn)@index(snd-up)@i(srate), @i(sound))]@\Increases sample rate by linear +interpolation. The @i(sound) is the signal to be up-sampled, and @i(srate) +is the output sample rate. Do not call this function. Nyquist performs +sample-rate conversion automatically as needed. If you want to force a +conversion, call @code(force-srate) (see Section @ref(force-srate-sec)). + +@label(snd-xform-sec) +@codef[snd-xform(@pragma(defn)@index(snd-xform)@i(sound), @i(sr), @i(time), @i(start), +@i(stop), @i(scale))]@\Makes a copy of @i(sound) and then alters it in +the following order: (1) the start time (@code(snd-t0)) of the sound is shifted to +@i(time), (1) the sound is stretched as a result of setting the sample rate +to @i(sr) (the start time is unchanged by this), (3) the sound is clipped + from @i(start) to @i(stop), (4) if @i(start) is greater than @i(time), the sound is shifted +shifted by @i(time) - @i(start), so that the start time is @i(time), (5) the +sound is scaled by @i(scale). An empty (zero) sound at @i(time) will be +returned if all samples are clipped. Normally, you should accomplish all +this using transformations. A transformation applied to a sound has no +effect, so use @code(cue) to create a transformable sound (see Section +@ref(use-sounds-sec)). + +@label(snd-yin-sec) +@codef{snd-yin(@pragma(defn)@index(snd-yin)@i(sound), @i(minstep), @i(maxstep), @i(rate))}@\Identical to +@code[yin]. See Section @ref(yin-sec). + +@end(fndefs) + +@subsection(Filters) +These are also ``Signal Operators,'' the subject of the previous section, +but there are so many filter functions, they are +documented in this special section. + +Some filters allow time-varying filter parameters. In these functions, +filter coefficients are calculated at the sample rate of the filter +parameter, and coefficients are not interpolated. + +@begin(fndefs) + +@codef[snd-alpass(@pragma(defn)@index(snd-alpass)@i(sound), @i(delay), @i(feedback))]@\An all-pass filter. This produces a repeating echo effect without the resonances of @code(snd-delay). The @i(feedback) should be less than one to avoid exponential amplitude blowup. Delay is rounded to the nearest sample. You should use @code(alpass) instead (see Section @ref(alpass-sec)). + +@codef[snd-alpasscv(@pragma(defn)@index(snd-alpasscv)@i(sound), @i(delay), +@i(feedback))]@\An all-pass filter with variable @i(feedback). +This is just like @i(snd-alpass) except @i(feedback) is a sound. +You should use @code(alpass) instead (see Section @ref(alpass-sec)). + +@codef[snd-alpassvv(@pragma(defn)@index(snd-alpassvv)@i(sound), @i(delay), @i(feedback), @i(maxdelay))]@\An all-pass filter with variable @i(feedback) and @i(delay). This is just like @i(snd-alpass) except @i(feedback) and @i(delay) are sounds, and there is an additional @code(FLONUM) parameter, @i(maxdelay), that gives an upper bound on the value of @i(delay). @p(Note:) @i(delay) must remain between zero and @i(maxdelay). If not, results are undefined, and Nyquist may crash. You should use @code(alpass) instead (see Section @ref(alpass-sec)). + +@codef[snd-areson(@pragma(defn)@index(snd-areson)@i(sound), @i(hz), @i(bw), +@i(normalization))]@\A notch filter modeled after the @code(areson) +unit generator in Csound. The @code(snd-areson) filter is an exact +complement of @code(snd-reson) such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. Note that because of this complementary design, +the power is not normalized as in @code(snd-reson). See @code(snd-reson) +for details on @i(normalization). You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-aresoncv(@pragma(defn)@index(snd-aresoncv)@i(sound), @i(hz), @i(bw), +@i(normalization))]@\This function is identical to @code(snd-areson) except +the @i(bw) (bandwidth) parameter is a sound. Filter coefficients are +updated at the sample rate of @i(bw). The ``@code(cv)'' suffix stands for Constant, +Variable, indicating that @i(hz) and @i(bw) are constant (a number) and +variable (a sound), respectively. This naming convention is used throughout. +You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-aresonvc(@pragma(defn)@index(snd-aresonvc)@i(sound), @i(hz), @i(bw), +@i(normalization))]@\This function is identical to @code(snd-areson) except +the @i(hz) (center frequency) parameter is a sound. Filter coefficients are +updated at the sample rate of @i(hz). +You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-aresonvv(@pragma(defn)@index(snd-aresonvv)@i(sound), @i(hz), @i(bw), +@i(normalization))]@\This function is identical to @code(snd-areson) except +both @i(hz) (center frequency) and @i(bw) (bandwidth) are sounds. Filter +coefficients are updated at the next sample of either @i(hz) or @i(bw). +You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-atone(@pragma(defn)@index(snd-atone)@i(sound), @i(hz))]@\A high-pass filter +modeled after the @code(atone) unit generator in Csound. The @code(snd-atone) filter is an exact +complement of @code(snd-tone) such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. You should use @code(hp) instead (see +Section @ref(hp-sec)). + +@codef[snd-atonev(@pragma(defn)@index(snd-atonev)@i(sound), @i(hz))]@\This is just like +@code(snd-atone) except that the @i(hz) cutoff frequency is a sound. Filter +coefficients are updated at the sample rate of @i(hz). You should use +@code(hp) instead (see Section @ref(hp-sec)). + +@codef[snd-biquad(@pragma(defn)@index(snd-biquad)@i(sound), @i(b0), @i(b1), @i(b2), @i(a1), @i(a2), @i(z1init), @i(z2init))]@\A general second order IIR filter, where @i(a0) is assumed to be unity. For @i(a1) and @i(a2), the sign convention is opposite to that of Matlab. All parameters except the input @i(sound) are of type @code(FLONUM). You should probably use one of @code(lowpass2), @code(highpass2), @code(bandpass2), @code(notch2), @code(allpass2), @code(eq-lowshelf), @code(eq-highshelf), @code(eq-band), @code(lowpass4), @code(lowpass6), @code(lowpass8), @code(highpass4), @code(highpass6), or @code(highpass8), which are all based on @code(snd-biquad) and described in Section @ref(lowpass2-sec). For completeness, you will also find @code(biquad) and @code(biquad-m) described in that section. + +@label(snd-chase-sec) +@codef[snd-chase(@pragma(defn)@index(snd-chase)@i(sound), @i(risetime), @i(falltime))]@\A slew rate limiter. The output ``chases'' the input at rates determined by @i(risetime) and @i(falltime). If the input changes too fast, the output will lag behind the input. This is a form of lowpass filter, but it was created to turn hard-switching square waves into smoother control signals that could be used for linear crossfades. If the input switches from 0 to 1, the output will linearly rise to 1 in @i(risetime) seconds. If the input switches from 1 to 0, the output will linearly fall to 0 in @i(falltime) seconds. The generated slope is constant; the transition is linear; this is not an exponential rise or fall. The @i(risetime) and @i(falltime) must be scalar constants; complain to the author if this is not adequate. The @code(snd-chase) function is safe for ordinary use. See @code(snd-follow) in Section @ref(snd-follow-sec) for a related function. + +@codef[snd-congen(@pragma(defn)@index(snd-congen)@i(gate), @i(risetime), @i(falltime))]@\A simple ``contour generator'' based +on analog synthesizers. The @i(gate) is a sound that normally steps from 0.0 to 1.0 at the start of an envelop and goes from +1.0 back to 0.0 at the beginning of the release. At each sample, the output converges to the input exponentially. If @i(gate) is greater than the output, e.g. the attack, then the output converges half-way to the output in @i(risetime). If the @i(gate) is less than the output, the half-time is @i(falltime). The sample rate, starting time, logical-stop-time, and terminate time are taken from @i(gate). You should use @code(congen) instead (see Section @ref(congen-sec). + +@codef[snd-convolve(@pragma(defn)@index(snd-convolve)@i(sound), @i(response))]@\Convolves +@i(sound) by @i(response) using a simple O(N x M) algorithm. The @i(sound) +can be any length, but the @i(response) is computed and stored in a table. The required compuation time per sample and total space are proportional to the +length of @i(response). Use @code(convolve) instead (see Section +@ref(convolve-sec)). + +@codef[snd-delay(@pragma(defn)@index(snd-delay)@i(sound), @i(delay), @i(feedback))]@\Feedback +delay. The output, initially @i(sound), is recursively delayed by @i(delay), scaled by @i(feedback), and added to itself, producing an repeating echo effect. The @i(feedback) should be less than one to avoid exponential amplitude blowup. Delay is rounded to the nearest sample. You should use @code(feedback-delay) instead (see Section @ref(feedback-delay-sec)) + +@codef[snd-delaycv(@pragma(defn)@index(snd-delaycv)@i(sound), @i(delay), +@i(feedback))]@\Feedback delay with variable @i(feedback). This is just like +@i(snd-delay) except @i(feedback) is a sound. You should use +@code(feedback-delay) instead (see Section @ref(feedback-delay-sec)). + +@codef[snd-reson(@pragma(defn)@index(snd-reson)@i(sound), @i(hz), @i(bw), @i(normalization))]@\A +second-order resonating (bandpass) filter with center frequency @i(hz) and +bandwidth @i(bw), modeled after the @code(reson) unit generator in Csound. +The @i(normalization) parameter must be an integer and (like in Csound) +specifies a scaling factor. A value of 1 specifies a peak amplitude +response of 1.0; all frequencies other than @i(hz) are attenuated. A +value of 2 specifies the overall RMS value of the amplitude response +is 1.0; thus filtered white noise would retain the same power. A value of +zero specifies no scaling. The result sample rate, start time, etc. are takend from @i(sound). +You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-resoncv(@pragma(defn)@index(snd-resoncv)@i(sound), @i(hz), @i(bw), +@i(normalization))]@\This function is identical to @code(snd-reson) except +@i(bw) (bandwidth) is a sound. Filter coefficients are updated at the +sample rate of @i(bw). You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-resonvc(@pragma(defn)@index(snd-resonvc)@i(sound), @i(hz), @i(bw), +@i(normalization))]@\This function is identical to @code(snd-reson) except +@i(hz) (center frequency) is a sound. Filter coefficients are updated at the +sample rate of @i(hz). You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-resonvv(@pragma(defn)@index(snd-resonvv)@i(sound), @i(hz), @i(bw), +@i(normalization))]@\This function is identical to @code(snd-reson) except +botth @i(hz) (center frequency) and @i(bw) (bandwidth) are sounds. Filter +coefficients are updated at the next sample from either @i(hz) or @i(bw). You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-stkchorus(@pragma(defn)@index(snd-stkchorus)@index(chorus)@index(effect, chorus)@index(STK chorus)@i(sound), @i(delay), @i(depth), @i(freq), @i(mix), +@i(sr))]@\A chorus implemented in STK. The parameter @i(delay) is a @code(FIXNUM) +representing the median desired delay length in samples. A typical +value is 6000. The @code(FLONUM) parameters @i(depth) and @i(freq) set the modulation +depth (from 0 to 1) and modulation frequency (in Hz), @i(mix) sets the mixture +of input sound and chorused sound, where a value of 0.0 means input sound +only (dry) and a value of 1.0 means chorused sound only (wet). +The parameter @i(sr) is the desired sample rate of the resulting sound@foot(This +is probably a mistake since sample rate is implied by @i(sound). This parameter +may be removed in a future release.) You should use @code(pitshift) instead +(see Section @ref(stkchorus-sec)). + +@codef[snd-stkpitshift(@pragma(defn)@index(snd-stkpitshift)@index(pitch shift)@index(effect, pitch shift)@index(STK pitch shift)@i(sound), @i(shift), @i(mix), @i(sr))]@\A +pitch shifter implemented in STK. The @i(sound) is shifted in pitch by +@i(shift), a @code(FLONUM) representing the shift factor. A value of 1.0 means + no shift. The parameter @i(mix) sets the mixture of input and shifted sounds. +A value of 0.0 means input only (dry) and a value of 1.0 means shifted +sound only (wet). The @i(sr) is the desired sampling frequency.@foot(This +is probably a mistake since sample rate is implied by @i(sound). This parameter +may be removed in a future release.) You should use @code(pitshift) instead +(see Section @ref(stkpitshift-sec)). + +@codef[snd-stkrev(@pragma(defn)@index(snd-stkrev)@index(reverb)@index(effect, reverberation)@index(STK reverb)@i(rev-type), @i(sound), @i(decay), @i(mix), @i(sr))]@\A reverb +implemented in STK. The parameter rev-type is a @code(FIXNUM) ranging from zero to +two and selects the type of reverb. Zero selects NRev type, one selects JCRev, +and two selects PRCRev. The input @i(sound) is processed by the reverb with +a @i(decay) time in seconds (a @code(FLONUM)). The @i(mix), a @code(FLONUM), +sets the +mixture of dry input and reverb output. A value of 0.0 means input only (dry) +and a value of 1.0 means reverb only (wet). The sample rate +is @i(sr)@foot(This is probably a mistake since sample rate is implied +by @i(sound). This parameter may be removed in a future release.) You +should use @code(nrev), @code(jcrev) or @code(prcrev) instead (see +Section @ref(stkrev-sec)). + +@codef[snd-tone(@pragma(defn)@index(snd-tone)@index(low-pass filter)@i(sound), @i(hz))]@\A +first-order recursive low-pass filter, based on the @i(tone) unit generator +of Csound. The @i(hz) parameter is the cutoff frequency, the response +curve's half-power point. The result sample rate, start time, etc. are takend from @i(sound). +You should use @code(lp) instead (see Section +@ref(lp-sec)). + +@codef[snd-tonev(@pragma(defn)@index(snd-tonev)@i(sound), @i(hz))]@\This function is +identical to @code(snd-tone) except @i(hz) (cutoff frequency) is a sound. +The filter coefficients are updated at the sample rate of @i(hz). You +should use @code(lp) instead (see Section +@ref(lp-sec)). + + +@end(fndefs) + + +@subsection(Table-Lookup Oscillator Functions) +These functions all use a sound to describe one period of a periodic +waveform. In the current implementation, the sound samples are copied to an +array (the waveform table) when the function is called. To make a +table-lookup oscillator generate a specific pitch, we need to have several +pieces of information: +@begin(itemize) +A waveform to put into the table. This comes from the @i(sound) parameter. + +The length (in samples) of the waveform. This is obtained by reading +samples (starting at the sound's start time, not necessarily at time zero) +until the physical stop time of the sound. (If you read the waveform from a +file or generate it with functions like @code(sim) and @code(sine), then the +physical and logical stop times will be the same and will correspond to the +duration you specified, rounded to the nearest sample.) + +The intrinsic sample rate of the waveform. This sample rate is simply the +sample rate property of @i(sound). + +The pitch of the waveform. This is supplied by the @i(step) parameter and +indicates the pitch (in steps) of @i(sound). You might expect that the +pitch would be related to the period (length) of @i(sound), but there is the +interesting case that synthesis based on sampling often loops over multiple +periods. This means that the fundamental frequency of a generated tone may +be some multiple of the looping rate. In Nyquist, you always specify the +perceived pitch of the looped @i(sound) if the sound is played at the +@i(sound)'s own sample rate. + +The desired pitch. This is specified by the @i(hz) parameter +in Hertz (cycles per second) in these low-level functions. Note that this +is not necessarily the ``loop'' rate at which the table is scanned. +Instead, Nyquist figures what sample rate conversion would be necessary to +``transpose'' from the @i(step) which specifies the original pitch of +@i(sound) to @i(hz), which gives the desired pitch. The mixed use of steps +and Hertz came about because it seemed that sample tables would be tagged +with steps (``I sampled a middle-C''), whereas frequency deviation in the +@code(fmosc) function is linear, thus calling for a specification in Hertz. + +The desired sample rate. This is given by the @i(sr) parameter in Hertz. +@end(itemize) + +Other parameters common to all of these oscillator functions are: +@begin(itemize) +@i(t0), the starting time, and + +@i(phase), the starting phase in degrees. Note that if the @i(step) +parameter indicates that the table holds more than one fundamental period, then a starting phase of 360 will be different than a starting phase of 0. +@end(itemize) + +@begin(fndefs) + @codef[snd-amosc(@pragma(defn)@index(snd-amosc)@i(sound), @i(step), @i(sr), @i(hz), @i(t0), +@i(am), @i(phase))]@\An oscillator with amplitude modulation. The sound +@i(am) specifies the amplitude and the logical stop time. The physical stop +time is also that of @i(am). You should use @code(amosc) instead (see +Section @ref(amosc-sec)). + +@codef[snd-fmosc(@pragma(defn)@index(snd-fmosc)@i(s), @i(step), @i(sr), @i(hz), @i(t0), @i(fm), +@i(phase))]@\A Frequency Modulation oscillator. The sound @i(fm) specifies +frequency deviation (in Hertz) from @i(hz). You should use @code(fmosc) +instead (see Section @ref(fmosc-sec)). + +@code[snd-fmfb(@pragma(defn)@index(snd-fmfb)@i(t0), @i(hz), @i(sr), +@i(index), @i(dur))]@\A Feedback FM oscillator. The resulting sound starts +at @i(t0), has a fundamental frequency of @i(hz), a sample rate of @i(sr), +and a duration of @i(dur) seconds. The @i(index) is a @code(FLONUM) that +specifies the amount of feedback. You should use @code(fmfb) instead (see +Section @ref(fmfb-sec)). + +@code[snd-fmfbv(@pragma(defn)@index(snd-fmfb)@i(t0), @i(hz), @i(sr), +@i(index))]@\A Feedback FM oscillator. The resulting sound starts +at @i(t0), has a fundamental frequency of @i(hz), and +a sample rate of @i(sr). The @i(index) is a @code(SOUND) that +specifies the amount of feedback and determines the duration. +You should use @code(fmfb) instead (see Section @ref(fmfb-sec)). + +@codef[snd-buzz(@pragma(defn)@index(snd-buzz)@i(n), @i(sr), @i(hz), @i(t0), @i(fm))]@\A +buzz oscillator, which generates @i(n) harmonics of equal amplitude. +The @i(fm) specifies +frequency deviation (in Hertz) from @i(hz). You should use @code(buzz) +instead (see Section @ref(buzz-sec)). + +@codef[snd-pluck(@pragma(defn)@index(snd-pluck)@i(sr), @i(hz), @i(t0), @i(d), + @i(final-amp))]@\A Karplus-Strong plucked string oscillator with sample rate +@i(sr), fundamental frequency @i(hz), starting time @i(t0), duration @i(d), +initial amplitude approximately 1.0 (not exact because the string is +initialized with random values) and final amplitude approximately +@i(final-amp). You should use @code(pluck) instead (see Section + @ref(pluck-sec)). + +@codef[snd-osc(@pragma(defn)@index(snd-osc)@i(s), @i(step), @i(sr), @i(hz), @i(t0), @i(d), @i(phase))]@\A simple table lookup oscillator with fixed frequency. The duration +is @i(d) seconds. You should use @code(osc) instead (see Section +@ref(osc-sec)). + +@codef[snd-partial(@pragma(defn)@index(snd-partial)@i(sr), @i(hz), @i(t0), @i(env))]@\This is a +special case of @code(snd-amosc) that generates a sinusoid starting at phase +0 degrees. The @i(env) parameter gives the envelope or any other amplitude +modulation. You should use @code(partial) instead (see Section +@ref(partial-sec)). + +@codef[snd-sine(@pragma(defn)@index(snd-sine)@i(t0), @i(hz), @i(sr), @i(d))]@\This is a +special case of @code(snd-osc) that always generates a sinusoid with initial +phase of 0 degrees. You should use @code(sine) instead (see Section @ref(sine-sec)). + +@codef[snd-siosc(@pragma(defn)@index(snd-siosc)@i(tables), @i(sr), @i(hz), @i(t0), +@i(fm))]@\A Spectral Interpolation Oscillator with frequency modulation. The +@i(tables) is a list of sounds and sample counts as follows: (@i(table0) +@i(count1) @i(table1) ... @i(countN) @i(tableN)). The initial waveform is given by @i(table0), which is interpolated linearly to @i(table1) over the first +@i(count1) samples. From @i(count1) to @i(count2) samples, the waveform is +interpolated from @i(table1) to @i(table2), and so on. If more than +@i(countN) samples are generated, @i(tableN) is used for the remainder of +the sound. The duration and logical stop time of the sound is taken from +@i(fm), which specified frequency modulation (deviation) in Hertz. You +should use @code(siosc) instead (see Section @ref(siosc-sec)). + +@end(fndefs) + +@subsection(Physical Model Functions) +These functions perform some sort of physically-based modeling synthesis. +@begin(fndefs) +@code[(snd-bandedwg@pragma(defn)@index(snd-bandedwg)@index(STK banded waveguide) @i(freq) @i(bowpress-env) @i(preset) @i(sr))]@\A Banded Wave Guide +Percussion instrument implemented in STK. The parameter @i(freq) is a +@code(FLONUM) in Hz, @i(bowpress-env) is +a @code(SOUND) that ranges from zero to one, @i(preset) is a @code(FIXNUM), +and @i(sr) is the desired sample rate in Hz. Currently, there are four +presets: uniform-bar (0), tuned-bar (1), glass-harmonica (2), and +tibetan-bowl (3). You should use @code(wg-uniform-bar), @code(wg-tuned-bar), + @code(wg-glass-harm), or @code(wg-tibetan-bowl) instead (see Section +@ref(bandedwg-sec)). + +@codef[snd-bowed(@pragma(defn)@index(snd-bowed)@index(stk bowed)@i(freq), +@i(bowpress-env), @i(sr))]@\A bowed string instrument implemented in +STK. The freq is a @code(FLONUM) in Hertz, bowpress-env is a + @code(SOUND) that ranges from z +ero to one, and sr is the desired sample rate (a @code(FLONUM)). +You should use bowed instead (see Section @ref(bowed-sec)). + +@codef[snd-bowed-freq(@pragma(defn)@index(snd-bowed-freq)@index(stk bowed)@i(freq), @i(bowpress-env), @i(freq-env), @i(sr))]@\A bowed model just like @code(snd-bowed) but with +an additional parameter for continuous frequency control. You should use +@code(bowed-freq) instead (see Section @ref(bowed-sec)). + +@codef[snd-clarinet(@pragma(defn)@index(snd-clarinet)@index(stk clarinet)@i(freq), @i(breath-env), @i(sr))]@\A clarinet +model implemented in STK. The @i(freq) is a @code(FLONUM) in Hertz, + @i(breath-env) is +a @code(SOUND) that ranges from zero to one, and @i(sr) is the + desired sample +rate (a @code(FLONUM)). You should use @code(clarinet) instead + (see Section +@ref(clarinet-sec)). + +@codef[snd-clarinet-freq(@pragma(defn)@index(snd-clarinet-freq)@index(STK clarinet)@i(freq), @i(breath-env), @i(freq-env), @i(sr))]@\A clarinet model just like @code(snd-clarinet) but with +an additional parameter for continuous frequency control. You should use +@code(clarinet-freq) instead (see Section @ref(clarinet-sec)). + +@codef[snd-clarinet-all(@pragma(defn)@index(snd-clarinet-all)@i(freq), @i(vibrato-freq), +@i(vibrato-gain), @i(freq-env), @i(breath-env), +@i(reed-stiffness), @i(noise), @i(sr))]@\A clarinet model just like +@code(snd-clarinet-freq) but with +additional parameters for vibrato generation and continuous control of +reed stiffness and breath noise. You should use +@code(clarinet-all) instead (see Section @ref(clarinet-sec)). + +@codef[snd-flute(@pragma(defn)@index(snd-flute)@index(stk flute)@i(freq), + @i(breath-env), @i(sr))]@\A flute implemented in STK. The @i(freq) is a +@code(FLONUM) in Hertz, @i(breath-env) is a @code(SOUND) + that ranges from zero to one, and @i(sr) is + the desired sample rate (a @code(FLONUM)). You should use @code(flute) + instead (see Section @ref(flute-sec)). + +@codef[snd-flute-freq(@pragma(defn)@index(snd-flute-freq)@index(stk flute)@i(freq), @i(breath-env), +@i(freq-env), @i(sr))]@\A flute model just like @code(snd-flute) but with +an additional parameter for continuous frequency control. You should use +@code(flute-freq) instead (see Section @ref(flute-sec)). + +@codef[snd-flute-all(@pragma(defn)@index(snd-flute-all)@index(stk flute)@i(freq), @i(vibrato-freq), @i(vibrato-gain), @i(freq-env), @i(breath-env), +@i(jet-delay), @i(noise), @i(sr))]@\A flute model just like +@code(snd-flute-freq) but with +additional parameters for vibrato generation and continuous control of +breath noise. You should use +@code(flute-all) instead (see Section @ref(flute-sec)). + +@codef[snd-mandolin(@pragma(defn)@index(snd-mandolin)@index(STK mandolin)@i(t0), @i(freq), @i(dur), @i(body-size), @i(detune), @i(sr))]@\A plucked + double-string instrument model implemented in STK. The @i(t0) parameter + is the starting time (in seconds), @i(freq) is a @code(FLONUM) in + Hz, @i(body-size) and @i(detune) are @code(FLONUM)s, and @code(sr) + is the desired sample + rate. You should use @code(mandolin) instead (see Section @ref(mandolin-sec)). + +@codef[snd-modalbar(@pragma(defn)@index(snd-modalbar)@index(STK modal bar)@i(t0), @i(freq), @i(preset), @i(dur), @i(sr))]@\Struck bar instrument + model implemented in STK. The parameter @i(t0) is the starting +time (in seconds), @i(freq) is a @code(FLONUM) in Hz, + @code(preset) is a @code(FIXNUM) ranging from 0 to 8, @i(dur) is a +@code(FLONUM) that + sets the duration (in seconds) and @i(sr) is the desired sample rate. You +should use @code(modalbar) instead (see Section @ref(modalbar-sec)). + +@codef[snd-sax(@pragma(defn)@index(snd-sax)@index(STK sax)@i(freq), @i(breath-env), @i(sr))]@\A sax +model implemented in STK. The @i(freq) is a @code(FLONUM) in Hertz, @i(breath-env) is +a @code(SOUND) that ranges from zero to one, and @i(sr) is the desired sample +rate (a @code(FLONUM)). You should use @code(sax) instead (see Section +@ref(sax-sec)). + +@codef[snd-sax-freq(@pragma(defn)@index(snd-sax-freq)@i(freq), @i(freq-env), @i(breath-env), + @i(sr))]@\A sax model just like @code(snd-sax) but with +an additional parameter for continuous frequency control. You should use +@code(sax-freq) instead (see Section @ref(sax-sec)). + +@codef[snd-sax-all(@pragma(defn)@index(snd-sax-all)@i(freq), @i(vibrato-freq), +@i(vibrato-gain), @i(freq-env), @i(breath-env), +@i(reed-stiffness), @i(noise), @i(blow-pos), @i(reed-table-offset), @i(sr))]@\A +sax model just like +@code(snd-sax-freq) but with +additional parameters for vibrato generation and continuous control of +reed stiffness, breath noise, excitation position, and reed table offset. + You should use +@code(sax-all) instead (see Section @ref(sax-sec)). + +@codef[snd-sitar(@pragma(defn)@index(snd-sitar)@index(STK sitar)@i(t0), +@i(freq), @i(dur), @i(sr))]@\A sitar model implemented in STK. The parameter +@i(t0) is the starting time, @i(freq) is a @code(FLONUM) (in Hz), E +@i(dur) sets the duration and @i(sr) is the sample rate (in Hz) +of the resulting sound. You should use @code(sitar) instead (see Section +@ref(sitar-sec)). + + +@end(fndefs) + + +@subsection(Sequence Support Functions) +The next two functions are used to implement Nyquist's @code(seq) construct. + +@begin(fndefs) +@codef[snd-seq(@pragma(defn)@index(snd-seq)@i(sound), @i(closure))]@\This function returns +@i(sound) until the logical stop time of @i(sound). Then, the XLISP +@i(closure) +is evaluated, passing it the logical stop time of @i(sound) as a +parameter. The closure must return a sound, which is then added to +@i(sound). (An add is used so that @i(sound) can continue past its logical +stop if desired.) Do not call this function. See @code(seq) in Section +@ref(seq-sec). + +@codef[snd-multiseq(@pragma(defn)@index(snd-multiseq)@i(array), @i(closure))]@\This +function is similar to @code(snd-seq) except the first parameter is a +multichannel sound rather than a single sound. A multichannel sound is +simply an XLISP array of sounds. An array of sounds is returned which is +the sum of @i(array) and another array of sounds returned by @i(closure). +The @i(closure) is passed the logical stop time of the multichannel sound, +which is the maximum logical stop time of any element of @i(array). Do +not call this function. See @code(seq) in Section @ref(seq-sec). +@end(fndefs) + +@codef[snd-trigger(@pragma(defn)@index(snd-trigger)@i(s), @i(closure))]@\This is one of +the only ways in which a behavior instance can be created by changes in a +signal. When @i(s) (a @code(SOUND)) makes a transition from less than or +equal to zero to greater than zero, the closure, which takes a starting +time parameter, is evaluated. The closure must return a @code(SOUND). The +sum of all these sounds is returned. If there are no sounds, the result will +be zero. The stop time of the result is the maximum stop time of @i(s) and +all sounds returned by the closure. The sample rate of the return value is +the sample rate of @i(s), and the sounds returned by the closure must all +have that same sample rate. Do not call this function. +See @code(trigger) in Section @ref(trigger-sec). + +An implementation note: There is no way to have @code(snd-trigger) return +a multichannel sound. An alternative implementation would be a built-in +function to scan ahead in a sound to find the time of the next zero crossing. +This could be combined with some LISP code similar to @code(seq) to sum up +instances of the closure. However, this would force arbitrary look-ahead +and therefore would not work with real-time inputs, which was the motivation +for @code(snd-trigger) in the first place. + +@chapter(Nyquist Globals) +@index(Global Variables) +There are many global variables in Nyquist. A convention in Lisp is to place asterisks (*) around global variables, e.g. @code(*table*). This is only a convention, and the asterisks are just like any other letter as far as variable names are concerned. Here are some globals users should know about: + +@begin(description, leftmargin +2 in, indent -2 in) +@codef(*table*)@index(*table*)@\Default table used by @code(osc) and other oscillators. + +@codef(*A4-Hertz*)@pragma(defn)@index(*a4-hertz*)@\Frequency of A4 in Hertz.. Note: you must call @code[(set-pitch-names)] to recompute pitches after changing @code(*A4-Hertz*). + +@codef(*autonorm*)@pragma(defn)@index(*autonorm*)@\The normalization factor to be applied to the next sound when @code(*autonorm-type*) is @code('previous). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonormflag*)@pragma(defn)@index(*autonormflag*)@\Enables the automatic normalization feature of the @code(play) command. You should use @code[(autonorm-on)] and @code[(autonorm-off)] rather than setting @code(*autonormflag*) directly. See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-max-samples*)@pragma(defn)@index(*autonorm-max-samples*)@\Specifies how many samples will be computed searching for a peak value when @code(*autonorm-type*) is @code('lookahead). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-previous-peak*)@pragma(defn)@index(*autonorm-previous-peak*)@\The peak of the previous sound generated by @code(play). This is used to compute the scale factor for the next sound when @code(*autonorm-type*) is @code('previous). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-target*)@pragma(defn)@index(*autonorm-target*)@\The target peak amplitude for the autonorm feature. The default value is 0.9. See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-type*)@pragma(defn)@index(*autonorm-type*)@\Determines how the autonorm feature is implemented. Valid values are @code('lookahead) (the default) and @code('previous). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*breakenable*)@pragma(defn)@index(*breakenable*)@\Controls whether XLISP enters a break loop when an error is encountered. See Section @ref(symbols-sec). + +@codef(*control-srate*)@pragma(defn)@index(*control-srate*)@\Part of the environment, establishes the control sample rate. See Section @ref(environment-sec) for details. + +@codef(*default-sf-bits*)@pragma(defn)@index(*default-sf-bits*)@\The default bits-per-sample for sound files. Typically 16. + +@codef(*default-sf-dir*)@pragma(defn)@index(*default-sf-dir*)@\The default sound file directory. Unless you give a full path for a file, audio files are assumed to be in this directory. (Applies to many functions that deal with sound files. Check the function description to see if @code(*default-sf-dir*) applies.) + +@codef(*default-sf-format*)@pragma(defn)@index(*default-sf-format*)@\The default sound file format. When you write a file, this will be the default format: AIFF for Mac and most Unix systems, NeXT for NeXT systems, and WAV for Win32. + +@codef(*default-sf-srate*)@pragma(defn)@index(*default-sf-srate*)@\The default sample rate for sound files. Typically 44100.0, but often set to 22050.0 for speed in non-critical tasks. + +@codef(*default-control-srate*)@pragma(defn)@index(*default-control-srate*)@\Default value for @code(*control-srate*). This value is restored when you execute @code[(top)] to pop out of a debugging session. Change it by calling @code[(set-control-srate @i(value))]. + +@codef(*default-sound-srate*)@pragma(defn)@index(*default-sound-srate*)@\Default value for @code(*sound-srate*). This value is restored when you execute @code[(top)] to pop out of a debugging session. Change it by calling @code[(set-sound-srate @i(value))]. + +@codef(*file-separator*)@pragma(defn)@index(*file-separator*)@\The character that separates directories in a path, +e.g. ``@code(/)'' for Unix, ``@code(:)'' for Mac, and ``@code(\)'' for Win32. +This is normally set in @code(system.lsp). + +@codef(*rslt*)@pragma(defn)@index(*rslt*)@\When a function returns more than one value, @code(*rslt*) is set to a list of the ``extra'' values. This provides a make-shift version of the @code(multiple-value-return) facility in Common Lisp. + +@codef(*sound-srate*)@pragma(defn)@index(*sound-srate*)@\Part of the environment, establishes the audio sample rate. See Section @ref(environment-sec) for details. + +@codef(*soundenable*)@pragma(defn)@index(*soundenable*)@\Controls whether writes to a sound file will also be played as audio. Set this variable by calling @code{(sound-on)} or @code{(sound-off)}. + +@codef(*tracenable*)@pragma(defn)@index(*tracenable*)@\Controls whether XLISP prints a backtrace when an error is encountered. + +@b(XLISP variables)@\See Section @ref(symbols-sec) for a list of +global variables defined by XLISP. + +@b(Environment variables)@\See Section @ref(environment-sec) for definitions of variables used in the environment for behaviors. In general, you should never set or access these variables directly. + +@b(Various constants)@\See Section @ref(constants-sec) for definitions of predefined constants for loudness, duration, and pitch. + +@end(description) + +@chapter(Time/Frequency Transformation) +Nyquist provides functions for FFT and inverse FFT operations on streams of audio data. +Because sounds can be of any length, but an FFT operates on a fixed amount of data, FFT +processing is typically done in short blocks or windows that move through the audio. Thus, +a stream of samples is converted in to a sequence of FFT frames representing short-term +spectra. + +Nyquist does not have a special data type corresponding to a sequence of FFT frames. +This would be nice, but it would require creating a large set of operations suitable for +processing frame sequences. Another approach, and perhaps the most ``pure'' would +be to convert a single sound into a multichannel sound, with one channel per bin of the +FFT. + +Instead, Nyquist violates its ``pure'' functional model and resorts to objects +for FFT processing. A sequence of frames is represented by an XLISP object. Whenever you +send the selector @code[:next] to the object, you get back either NIL, indicating the +end of the sequence, or you get an array of FFT coefficients. + +The Nyquist function @code[snd-fft] (mnemonic, isn't it?) returns one of the frame sequence +generating objects. You can pass any frame sequence generating object to another function, +@code[snd-ifft], and turn the sequence back into audio. + +With @code[snd-fft] and @code[snd-ifft], you can create all sorts of interesting processes. The main +idea is to create intermediate objects that both accept and generate sequences of frames. +These objects can operate on the frames to implement the desired spectral-domain +processes. Examples of this can be found in the file +@code[fft_tutorial.htm]@index(fft tutorial)@index(fast fourier transform tutorial)@index(demos, fft), +which is part of the standard Nyquist release. The documentation for @code[snd-fft] and +@code[snd-ifft] follows. + +@begin(fndefs) +@codef[snd-fft(@pragma(defn)@index(snd-fft)@index(fft)@i(sound), @i(length), @i(skip), @i(window))]@\This +function performs an FFT on the first samples in @i(sound) and returns a Lisp array of @code[FLONUM]s. +The function modifies the @i(sound), violating the normal rule that sounds are immutable in Nyquist, so +it is advised that you copy the sound using @code[snd-copy] if there are any other references to +@i(sound). The length of the FFT is specified by @i(length), a @code[FIXNUM] (integer) which must +be a power of 2. After +each FFT, the sound is advanced by @i(skip) samples, also of type @code[FIXNUM]. Overlapping FFTs, +where @i(skip) is less than @i(length), are allowed. If @i(window) is not @code[NIL], it must be a sound. +The first @i(length) samples of @i(window) are multiplied by @i(length) samples of @i(sound) before +performing the FFT. When there are no more samples in @i(sound) to transform, +this function returns @code[NIL]. The coefficients in the returned array, in order, are the DC coefficient, +the first real, the first imaginary, the second real, the second imaginary, etc. +The last array element corresponds to the real coefficient at the Nyquist frequency. + +@codef[snd-ifft(@pragma(defn)@index(snd-ifft)@index(ifft)@index(inverse fft)@i(time), @i(srate), @i(iterator), @i(skip), @i(window))]@\This function performs an IFFT on a sequence of spectral frames obtained from @i(iterator) +and returns a sound. The start time of the sound is given by @i(time). Typically, this would be computed +by calling @code[(local-to-global 0)]. The sample rate is given by @i(srate). Typically, this would +be @code[*sound-srate*], but it might also depend upon the sample rate of the sound from which the +spectral frames were derived. To obtain each frame, the function sends the message @code[:next] to the +@i(iterator) object, using XLISP's primitives for objects and message passing. The object should return +an array in the same format as obtained from @code[snd-fft], and the object should return @code[NIL] +when the end of the sound is reached. After each frame is inverse transformed into the time domain, it is +added to the resulting sound. Each successive frame is added with a sample offset specified by @i(skip) +relative to the previous frame. This must be an integer greater than zero. If @i(window) is +not @code[NIL], it must be a sound. This window signal is multiplied by the inverse transformed frame +before the frame is added to the output sound. The length of each frame should be the same power of 2. +The length +is implied by the array returned by @i(iterator), so it does not appear as a parameter. This length +is also the number of samples used from @i(window). Extra samples are ignored, and window is padded +with zeros if necessary, so be sure @i(window) is the right length. The resulting sound is computed on +demand as with other Nyquist sounds, so @code[:next] messages are sent to @i(iterator) only when new +frames are needed. One should be careful not to reuse or modify @i(iterator) once it is passed to +@code[snd-ifft]. +@end(fndefs) + +@chapter(MIDI, Adagio, and Sequences) +@label(adagio-chap) +@index(MIDI)@index(Sequences) +Nyquist includes facilities to read and write MIDI files as well as an ASCII +text-based score representation language, Adagio. XLISP and Nyquist can be +used to generate MIDI files using compositional algorithms. (See also Section @ref(xmusic-sec).) +A tutorial on using the Adadio representation and MIDI can be found in +@code(demos/midi_tutorial.htm)@index(demos, midi). The Adagio language is +described below. Adagio was originally developed as part of the CMU MIDI +Toolkit, which included a program to record and play MIDI using the +Adagio representation. Some of the MIDI features of Adagio may not be +useful within Nyquist. + +Nyquist offers a number of different score representations, and you may +find this confusing. In general, MIDI files are a common way to exchange +music performance data, especially with sequencers and score notation +systems. The @code(demos/midi_tutorial.htm) examples show how to get the most +precise control when generating MIDI data. Adagio is most useful as a +text-based score entry language, and it is certainly more compact +than Lisp expressions for MIDI-like data. The Xmusic library +(Chapter @ref(xmusic-sec)) is best for algorithmic generation of music +and score manipulation. There are functions to convert between the +Adagio, MIDI sequence data, and Xmusic score representations. + +@pragma(doinclude) +@include(adagio-nyquist.mss) + +@chapter(Linear Prediction Analysis and Synthesis) +@index(Linear Prediction)@index(LPC) +Nyquist provides functions to perform Linear Prediction Coding (LPC) +analysis and synthesis. In simple terms, LPC analysis assumes that a +sound is the result of an all-pole filter applied to a source with a +flat spectrum. LPC is good for characterizing the general spectral +shape of a signal, which may be time-varying as in speech sounds. +For synthesis, any source can be filtered, allowing the general +spectral shape of one signal (used in analysis) to be applied to +any source (used in synthesis). A popular effect is to give vowel-like +spectra to musical tones, creating an artificial (or sometimes natural) +singing voice. + +Examples of LPC analysis and synthesis can be found in the file +@code[lpc_tutorial.htm]@index(lpc tutorial)@index(linear prediction tutorial)@index(demos, lpc), +which is part of the standard Nyquist release. + +As with FFT processing, LPC analysis takes a sound as input and returns +a stream of frames. Frames are returned from an object using the @code(:next) +selector just as with FFT frames. An LPC frame is a list consisting of: +@i(RMS1), the energy of the input signal, @i(RMS2), the energy of the +residual signal, @i(ERR), the square root of @i(RMS1)/@i(RMS2), and +@i(FILTER-COEFS), an array of filter coefficients. To make code more +readable and to avoid code dependence on the exact format of a frame, +the functions @code(lpc-frame-rms1)@index(lpc-frame-rms1), +@code(lpc-frame-rms2)@index(lpc-frame-rms2), +@code(lpc-frame-err)@index(lpc-frame-err), and +@code(lpc-frame-filter-coefs)@index(lpc-frame-filter-coefs) can be +applied to a frame to obtain the respective fields. + +The @i(z) transform +of the filter is @i(H)(@i(z)) = 1/@i(A)(@i(z)), where @i(A)(@i(z)) is a +polynomial of the form @i(A)(@i(z)) = 1 + @i(a@-[1])@i(z) + +@i(a@-[2])@i(z) + ... + @i(a@-[p])@i(z). The @i(FILTER-COEFS) array has +the form @code[#(]@i(a@-[p]) @i(a@-[p-1]) ... @i(a@-[3]) +@i(a@-[2]) @i(a@-[1])@code[)]. + +The file @code(lpc.lsp) defines some useful classes and functions. The file +is @i(not) automatically loaded with Nyquist, so you must execute +@code[(load "lpc")] before using them. + +@section(LPC Classes and Functions) +@begin(fndefs) +@codef[make-lpanal-iterator(@pragma(defn)@index(make-lpanal-iterator)@i(sound), @i(framedur), @i(skiptime), @i(npoles))]@\Makes an iterator +object, an instance of @code(lpanal-class), +that returns LPC frames from successive frames of samples in +@i(sound). The duration (in seconds) +of each frame is given by @i(framedur), a +@code(FLONUM). The skip size (in seconds) between successive frames +is given by @i(skiptime), a @code(FLONUM). Typical values for +@i(framedur) and @i(skiptime) are 0.08 and 0.04, giving 25 frames +per second and a 50% frame overlap. The number of poles is given +by @i(npoles), a @code(FIXNUM). The result is an object that +responds to the @code(:next) selector by returning a frame as +described above. @code(NIL) is returned when @i(sound) terminates. +(Note that one or more of the last analysis windows may be +padded with zeros. @code(NIL) is only returned when the corresponding +window would begin after the termination time of the sound.) + +@codef[make-lpc-file-iterator(@pragma(defn)@index(make-lpc-file-iterator)@i(filename))]@\Another way to get LPC frames is to read them from a + file. This function opens an ASCII file containing LPC frames and + creates an iterator object, an instance of class @code(lpc-file-class) + to access them. Create a file using @code(save-lpc-file) (see below). + +@codef[save-lpc-file(@pragma(defn)@index(save-lpc-file)@i(lpc-iterator), @i(filename))]@\Create a file containing LPC frames. +This file can be read by @code[make-lpc-file-iterator] (see above). + +@codef{show-lpc-data(@pragma(defn)@index(show-lpc-data)@i(lpc-iterator), +@i(iniframe), @i(endframe)[ ,@i(poles?)])}@\Print values of LPC +frames from an LPC iterator object. The object is @i(lpc-iterator), +which is typically an instance of @code(lpanal-class) or +@code(lpc-file-class). Frames are numbered from zero, and only +files starting at @i(iniframe) (a @code[FIXNUM]) and ending before +@i(endframe) (also a @code[FIXNUM]) are printed. By default, only +the values for @i(RMS1), @i(RMS2), and @i(ERR) are printed, but +if optional parameter @i(poles?) is non-@code[NIL], then +the LPC coefficients are also printed. + +@codef[allpoles-from-lpc(@pragma(defn)@index(allpoles-from-lpc)@i(snd), @i(lpc-frame))]@\A single LPC frame defines a filter. +Use @code(allpoles-from-lpc) to apply this filter to @i(snd), +a @code(SOUND). To obtain @i(lpc-frame), a @code(LIST) + containing an LPC frame, either send @code(:next) to an + LPC iterator, or use @code(nth-frame) (see below). The result + is a @code(SOUND) whose duration is the same as that of @i(snd). + +@codef[lpreson(@pragma(defn)@index(lpreson)@i(snd), @i(lpc-iterator), +@i(skiptime))]@\Implements a time-varying all-pole filter +controlled by a sequence of LPC frames from an iterator. The +@code(SOUND) to be filtered is @i(snd), and the source of +LPC frames is @i(lpc-iterator), typically an instance of +@code(lpanal-class) or @code(lpc-file-class). The frame +period (in seconds) is given by @i(skiptime) (a @code(FLONUM)). +This number does not have to agree with the @i(skiptime) used +to analyze the frames. (Greater values will cause the filter +evolution slow down, and smaller values will cause it to +speed up.) The result is a @code(SOUND). The duration of the +result is the minimum of the duration of @i(snd) and that of +the sequence of frames. + +@codef[lpc-frame-rms1(@pragma(defn)@index(lpc-frame-rms1)@i(frame))]@\Get the energy of the input signal from a frame. + +@codef[lpc-frame-rms2(@pragma(defn)@index(lpc-frame-rms2)@i(frame))]@\Get the energy of the residual from a frame. + +@codef[lpc-frame-err(@pragma(defn)@index(lpc-frame-err)@i(frame))]@\Get the square root of @i(RMS1)/@i(RMS2) from a frame. + +@codef[lpc-frame-filter-coefs(@pragma(defn)@index(lpc-frame-filter-coefs)@i(frame))]@\Get the filter coefficients from a frame. + +@end(fndefs) + +@section(Low-level LPC Functions) +The lowest-level Nyquist functions for LPC are +@begin(itemize) +@code(snd-lpanal) for analysis, + +@code(snd-allpoles), an all-pole filter with fixed coefficients, and + +@code(snd-lpreson), an all-pole filter that takes frames from an LPC iterator. +@end(itemize) + +@begin(fndefs) +@codef[snd-lpanal(@pragma(defn)@index(snd-lpanal)@i(samps), @i(npoles))]@\Compute +an LPC frame with @i(npoles) (a @code(FIXNUM)) poles from an +@code(ARRAY) of samples (@code(FLONUMS)). Note that @code(snd-fetch-array) +can be used to fetch a sequence of frames from a sound. Ordinarily, you +should not use this function. Use @code(make-lpanal-iterator) instead. + +@codef[snd-allpoles(@pragma(defn)@index(snd-allpoles)@i(snd), @i(lpc-coefs), @i(gain))]@\A fixed all-pole filter. The input is +@i(snd), a @code(SOUND). The filter coefficients are given by @i(lpc-coefs) +(an @code(ARRAY)), and the filter gain is given by @i(gain), a @code(FLONUM). +The result is a @code(SOUND) whose duration matches that of @i(snd). +Ordinarily, you should use @code(allpoles-from-lpc) instead (see above). + +@codef[snd-lpreson(@pragma(defn)@index(snd-lpreson)@i(snd), @i(lpc-iterator), +@i(skiptime))]@\This function is identical to @code(lpreson) (see above). +@end(fndefs) + + +@chapter(Developing and Debugging in Nyquist) +@index(debugging)@index(developing code) +There are a number of tools, functions, and techniques that can help to debug Nyquist programs. Since these are described in many places +throughout this manual, this chapter brings together many suggestions and techniques for developing code and debugging. You @i(really) +should read this chapter before you spend too much time with Nyquist. Many problems that you will certainly run into are addressed here. + +@section(Debugging) +Probably the most important debugging tool is the backtrace. When +Nyquist encounters an error, it suspends execution and prints an +error message. To find out where in the program the error occurred +and how you got there, start by typing @code[(bt)]. This will print +out the last several function calls and their arguments, which is +usually sufficient to see what is going on. + +In order for @code[(bt)] to work, you must have a couple of global +variables set: @code(*tracenable*) is ordinarily set to @code(NIL). +If it is true, then a backtrace is automatically printed when an +error occurs; @code(*breakenable*) must be set to @code(T), as +it enables the execution to be suspended when an error is +encountered. If @code(*breakenable*) is @code(NIL) (false), +then execution stops when an error occurs but the stack is +not saved and you cannot get a backtrace. Finally, @code(bt) +is just a macro to save typing. The actual backtrace function +is @code(baktrace), which takes an integer argument telling how +many levels to print. All of these things are set up by default +when you start Nyquist. + +Since Nyquist sounds are executed with a lazy evaluation scheme, some +errors are encountered when samples are being generated. In this +case, it may not be clear which expression is in error. Sometimes, it +is best to explore a function or set of functions by examining +intermediate results. Any expression that yields a sound can be +assigned to a variable and examined using one or more of: +@code(s-plot), @code(snd-print-tree), and of course @code(play). The +@code(snd-print-tree) function prints a lot of detail about the inner +representaion of the sound. Keep in mind that if you assign a sound +to a global variable and then look at the samples (e.g. with +@code(play) or @code(s-plot)), the samples will be retained in +memory. At 4 bytes per sample, a big sound may use all of your +memory and cause a crash. + +Another technique is to use low sample rates so that it is easier to +plot results or look at samples directly. The calls: +@begin(example) +set-sound-srate(100) +set-control-srate(100) +@end(example) +set the default sample rates to 100, which is too slow for audio, but useful for examining programs and results. The function +@begin(example) +snd-samples(@i(sound), @i(limit)) +@end(example) +will convert up to @i(limit) samples from @i(sound) into a Lisp +array. This is another way to look at results in detail. + +The @code(trace) function is sometimes useful. It prints the name of +a function and its arguments everytimg the function is called, and the +result is printed when the function exits. To trace the osc function, +type: +@begin(example) +trace(osc) +@end(example) +and to stop tracing, type @code[untrace(osc)]. + +If a variable needs a value or a function is undefined, and if @code(*breakenable*) was set, you will get a prompt where you can fix +the error (by setting the variable or loading the function definition) +and keep going. At the debug (or break) prompt, your input must +be in XLISP, not SAL syntax. Use @code[(co)], short for @code[(continue)] to +reevaluate the variable or function and continue execution. + +When you finish debugging a particular call, you can ``pop'' +up to the top level by typing @code[(top)], a short name for @code[(top-level)]. +There is a button named "Top" in the NyquistIDE that takes you back to the +top level (ready to accept XLISP expressions), +and another button named "SAL" that puts you back in SAL mode. + +@section(Useful Functions) +@begin(fndefs) +@codef[grindef(@pragma(defn)@index(grindef)@index(listing of lisp function)@i(name))]@\Prints +a formatted listing of a lisp function. This is often useful to quickly inspect +a function without searching for it in source files. Do not forget to quote the +name, e.g. @code[(grindef 'prod)]. + +@codef[args(@pragma(defn)@index(args)@index(arguments to a lisp function)@i(name))]@\Similar +to @code(grindef), this function prints the arguments to a function. This may +be faster than looking up a function in the documentation if you just need a +reminder. For example, @code[(args 'lp)] prints ``(LP S C),'' which may help you +to remember that the arguments are a sound (S) followed by the cutoff (C) +frequency. +@end(fndefs) + +The following functions are useful short-cuts that might have been included in +XLISP. They are so useful that they are defined as part of Nyquist. + +@begin(fndefs) +@codef[incf(@pragma(defn)@index(incf)@index(increment)@i(symbol))]@\Increment @i(symbol) +by one. This is a macro, and @i(symbol) can be anything that can be set by +@code(setf). Typically, @i(symbol) is a variable: ``@code[(incf i)],'' but +@i(symbol) can also be an array element: ``@code[(incf (aref myarray i))].'' + +@codef[decf(@pragma(defn)@index(decf)@index(decrement)@i(symbol))]@\Decrement @i(symbol) +by one. (See @code(incf), above.) + +@codef[push(@pragma(defn)@index(push)@i(val), @i(lis))]@\Push @i(val) onto @i(lis) (a Lisp +list). This is a macro that is equivalent to writing +@code[(setf @i(lis) (cons @i(val) @i(lis)))]. + +@codef[pop(@pragma(defn)@index(pop)@i(lis))]@\Remove (pop) the first item from @i(lis) (a +Lisp list). This is a macro that is equivalent to writing +@code[(setf @i(lis) (cdr @i(lis)))]. Note that the remaining list is returned, +not the head of the list that has been popped. Retrieve the head of the list +(i.e. the top of the stack) using @code(first) or, equivalently, @code(car). +@end(fndefs) + +The following macros are useful control constructs. + +@begin(fndefs) +@codef[while(@pragma(defn)@index(while)@i(test), @i(stmt1), @i(stmt2), ...)]@\A conventional +``while'' loop. If @i(test) is true, perform the statements + (@i(stmt1), @i(stmt2), etc.) and repeat. If @i(test) is false, return. This + expression evaluates to NIL unless the expression @code[(return @i(expr))] + is evaluated, in which case the value of @i(expr) is returned. + +@codef[when(@pragma(defn)@index(when)@i(test), @i(action))]@\A conventional ``if-then'' +statement. If @i(test) is true, @i(action) is evaluated and returned. Otherwise, +NIL is returned. (Use @code(if) or @code(cond) to implement + ``if-then-else'' and more complex conditional forms. +@end(fndefs) + +It is often necessary to load a file @i(only if) it has not already been +loaded. For example, the @code(pianosyn) library loads very slowly, so if +some other file already loaded it, it would be good to avoid loading it +again. How can you load a file once? Nyquist does not keep track of files +that are loaded, but you must be loading a file to define some function, +so the idea is to tell Nyquist "I require @i(function) from @i(file)"; if +the function does not yet exist, Nyquist satisfies the requirement by loading +the file. +@begin(fndefs) +@codef{require-from(@pragma(defn)@index(require-from)@index(load file conditionally)@i(fnsymbol), +@i(filename) [, @i(path)])}@\Tests whether @i(fnsymbol), an unquoted +function name, is defined. If +not, @i(filename), a @code(STRING), +is loaded. Normally @i(fnsymbol) is a function that will be called from +within the current file, and @i(filename) is the file that defines +@i(fnsymbol). The @i(path), if a @code(STRING), is prepended to @i(filename). +If @i(path) is @code(t) (true), then the directory of the current file is +used as the path. +@end(fndefs) + +Sometimes it is important to load files relative to the current file. For example, +the @code(lib/piano.lsp) library loads data files from the @code(lib/piano) directory, +but how can we find out the full path of @code(lib)? The solution is: +@begin(fndefs) +@codef[current-path(@pragma(defn)@index(current-path)@index(path, +current)@index(full path name))]@\Returns the full path name of the file that is +currently being loaded (see @code(load)). Returns NIL if no file is being loaded. +@end(fndefs) + +Finally, there are some helpful math functions: +@begin(fndefs) +@codef[real-random(@index(random)@index(uniform random)@pragma(defn)@index(real-random)@i(from), @i(to))]@\Returns a random @code(FLONUM) between @i(from) and @i(to). (See also @code(rrandom), which is equivalent to @code((real-random 0 1))). + +@codef[power(@pragma(defn)@index(power)@index(exponent)@i(x), @i(y))]@\Returns @i(x) raised to +the @i(y) power. +@end(fndefs) + +@chapter(Xmusic and Algorithmic Composition) +@label(xmusic-sec) +@index(Xmusic)@index(Algorithmic Composition) +Several Nyquist libraries offer support for algorithmic composition. Xmusic +is a library for generating sequences and patterns of data. Included in Xmusic +is the @code(score-gen) macro which helps to generate scores from patterns. +Another important facility is the @code(distributions.lsp) library, +containing many different random number generators. + +@section(Xmusic Basics) +Xmusic is inspired by and based on Common Music by Rick Taube. Currently, +Xmusic only implements patterns and some simple support for scores to be +realized as sound by Nyquist. In contrast, Common Music supports MIDI and +various other synthesis languages and includes a graphical interface, some +visualization tools, and many other features. Common Music runs in Common +Lisp and Scheme, but not XLISP, which is the base language for Nyquist. + +Xmusic patterns are objects that generate data streams. For example, +the @code(cycle-class) of objects generate cyclical patterns such as +"1 2 3 1 2 3 1 2 3 ...", or "1 2 3 4 3 2 1 2 3 4 ...". Patterns can +be used to specify pitch sequences, rhythm, loudness, and other parameters. + +Xmusic functions are automatically loaded when you start Nyquist. +To use a pattern object, you first create the pattern, e.g. +@begin(example) +set pitch-source = make-cycle(list(c4, d4, e4, f4)) +@end(example) +After creating the pattern, you can access it repeatedly +with @code(next)@index(next in pattern) to generate data, e.g. +@begin(example) +play seqrep(i, 13, pluck(next(pitch-source), 0.2)) +@end(example) +This will create a sequence of notes with the following pitches: c, d, +e, f, c, d, e, f, c, d, e, f, c. If you evaluate this again, the +pitch sequence will continue, starting on "d". + +It is very important not to confuse the creation of a sequence with +its access. Consider this example: +@begin(example) +play seqrep(i, 13, + pluck(next(make-cycle(list(c4, d4, e4, f4))), 0.2)) +@end(example) +This looks very much like the previous example, but it only repeats notes +on middle-C. The reason is that every time @code(pluck) is evaluated, +@code(make-cycle) is called and creates a new pattern object. After the +first item of the pattern is extracted with @code(next), the cycle is not +used again, and no other items are generated. + +To summarize this important point, there are two steps to using a pattern. +First, the pattern is created and stored in a +variable using @code(setf). Second, the pattern is accessed (multiple +times) using @code(next). + +Patterns can be nested, that is, you can write patterns of patterns. +In general, the @code(next) function does not return patterns. Instead, +if the next item in a pattern is a (nested) pattern, @code(next) recursively +gets the next item of the nested pattern. + +While you might expect that each call to @code(next) would advance the +top-level pattern to the next item, and descend recursively if necessary +to the inner-most nesting level, this is not how @code(next) works. Instead, +@code(next) remembers the last top-level item, and if it was a pattern, +@code(next) continues to generate items from that same inner pattern +until the end of the inner pattern's @i(period) is reached. The next +paragraph explains the concept of the @i(period). + +The data returned by a pattern object is structured into logical groups +called @i(periods). You can get an entire period (as a list) by calling +@code[next(@i(pattern), t)]@index(next pattern). For example: +@begin(example) +set pitch-source = make-cycle(list(c4, d4, e4, f4)) +print next(pitch-source, t) +@end(example) +This prints the list @code[(60 62 64 65)], which is one period +of the cycle. + +You can also get explicit markers that +delineate periods by calling @code[send(@i(pattern), :next)]. In this +case, the value returned is either the next item of the pattern, or the +symbol @code(+eop+) if the end of a period has been reached. What +determines a period? This is up to the specific pattern class, so see the +documentation for specifics. You can override the ``natural'' period +using the keyword @code(:for), e.g. +@begin(example) +set pitch-source = make-cycle(list(c4, d4, e4, f4), for: 3) +print next(pitch-source, t) +print next(pitch-source, t) +@end(example) +This prints the lists @code[(60 62 64) (65 60 62)]. Notice that +these periods just restructure the stream of items +into groups of 3. + +Nested patterns are probably easier to understand by example than by +specification. Here is a simple nested pattern of cycles: +@begin(example) +set cycle-1 = make-cycle({a b c}) +set cycle-2 = make-cycle({x y z}) +set cycle-3 = make-cycle(list(cycle-1, cycle-2)) +exec dotimes(i, 9, format(t, "~A ", next(cycle-3))) +@end(example) +This will print "A B C X Y Z A B C". Notice that the inner-most +cycles @code(cycle-1) and @code(cycle-2) generate a period of items +before the top-level @code(cycle-3) advances to the next pattern. + +Before describing specific pattern classes, there are several optional +parameters that apply in the creating of any pattern object. These are: +@begin(description, leftmargin +2 in, indent -2 in) +@code(:for)@\The length of a period. This overrides the default +by providing a numerical length. The value of this optional +parameter may be a pattern that generates a sequence of integers +that determine the length of each successive period. A period +length may not be negative, but it may be zero. + +@code(:name)@\A pattern object may be given a name. This is useful +if the @code(:trace) option is used. + +@code(:trace)@\If non-null, this optional parameter causes information +about the pattern to be printed each time an item is generated +from the pattern. + +@end(description) +The built-in pattern classes are described in the following section. + +@section(Pattern Classes) +@subsection(cycle) +The @code(cycle-class) iterates repeatedly through a list of items. +For example, two periods of @code[make-cycle({a b c})] would be +@code[(A B C) (A B C)]. + +@begin(fndefs) +@codef{make-cycle(@pragma(defn)@index(make-cycle)@index(cycle pattern)@index(pattern, cycle)@i(items)[ ,for: @i(for)] [, name: @i(name),] +[trace: @i(trace)])}@\Make a cycle +pattern that iterates over @i(items). The default period length is the +length of @i(items). (See above for a description of the +optional parameters.) If @i(items) is a pattern, a period of the +pattern becomes the list from which items are generated. The +list is replaced every period of the cycle. +@end(fndefs) + +@subsection(line) +The @code(line-class) is similar to the cycle class, but when it reaches the +end of the list of items, it simply repeats the last item in the list. +For example, two periods of @code[make-line({a b c})] would be +@code[(A B C) (C C C)]. + +@begin(fndefs) +@codef{make-line(@pragma(defn)@index(make-line)@index(line pattern)@index(pattern, line)@i(items)[ ,for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Make a line +pattern that iterates over @i(items). The default period length is the +length of @i(items). As with @code(make-cycle), @i(items) may be a +pattern. (See above for a description of the optional parameters.) +@end(fndefs) + +@subsection(random) +The @code(random-class) generates items at random from a list. The default +selection is uniform random with replacement, but items may be further +specified with a weight, a minimum repetition count, and a maximum +repetition count. Weights give the relative probability of the selection +of the item (with a default weight of one). The minimum count specifies how +many times an item, once selected at random, will be repeated. The maximum +count specifies the maximum number of times an item can be selected in a row. +If an item has been generated @i(n) times in succession, and the maximum +is equal to @i(n), then the item is disqualified in the next random selection. +Weights (but not currently minima and maxima) can be patterns. The patterns +(thus the weights) are recomputed every period. + +@begin(fndefs) +@codef{make-random(@pragma(defn)@index(make-random)@index(random pattern)@index(pattern, random)@i(items)[ ,for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Make a random +pattern that selects from @i(items). Any (or all) element(s) of @i(items) +may be lists of the following form: @code{(@i(value) [:weight @i(weight)] +[:min @i(mincount)] [:max @i(maxcount)]}, where @i(value) is the item +(or pattern) to be generated, @i(weight) is the relative probability of +selecting this item, @i(mincount) is the minimum number of repetitions +when this item is selected, and @i(maxcount) is the maximum number of +repetitions allowed before selecting some other item. The default period +length is the length of @i(items). If @i(items) is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +@end(fndefs) + +@subsection(palindrome) +The @code(palindrome-class) repeatedly traverses a list forwards and then +backwards. For example, two periods of @code[make-palindrome({a b c})] +would be @code[(A B C C B A) (A B C C B A)]. The @code(:elide) +keyword parameter controls whether the first and/or last elements are +repeated: +@begin(example) +make-palindrome({a b c}, elide: nil) + ;; generates A B C C B A A B C C B A ... + +make-palindrome({a b c}, elide: t) + ;; generates A B C B A B C B ... + +make-palindrome({a b c}, elide: :first) + ;; generates A B C C B A B C C B ... + +make-palindrome({a b c}, elide: :last) + ;; generates A B C B A A B C B A ... +@end(example) + +@begin(fndefs) +@codef{make-palindrome(@pragma(defn)@index(make-palindrome)@index(palindrome pattern)@index(pattern, palindrome)@i(items)[ ,elide: @i(elide),] +[for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Generate items +from list alternating in-order and reverse-order sequencing. The keyword +parameter @i(elide) can have the values @code(:first), @code(:last), +@code(t), or @code(nil) to control repetition of the first and last elements. +The @i(elide) parameter can also be a pattern, in which case it is evaluated +every period. One period is one complete forward and backward traversal +of the list. If @i(items) is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +@end(fndefs) + +@subsection(heap) +The @code(heap-class) selects items in random order from a list + without replacement, which means that all items are generated once before +any item is repeated. For example, two periods of @code[make-heap({a b c})] + might be @code[(C A B) (B A C)]. Normally, repetitions can occur +even if all list elements are distinct. This happens when the last element +of a period is chosen first in the next period. To avoid repetitions, the +@code(:max) keyword argument can be set to 1. The @code(:max) keyword only +controls repetitions from the end of one period to the beginning of the next. +If the list contains more than one copy of the same value, it may be repeated +within a period regardless of the value of @code(:max). + +@begin(fndefs) +@codef{make-heap(@pragma(defn)@index(make-heap)@index(heap pattern)@index(pattern, heap)@i(items), +[for: @i(for)] [, max: @i(max)] [, name: @i(name)] [, trace: @i(trace)])}@\Generate items +randomly from list without replacement. If @i(max) is 1, the first element of +a new period will not be the same as the last element of the previous period, +avoiding repetition. The default value of @i(max) is 2, meaning repetition is +allowed. The period length is the length +of @i(items). If @i(items) is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +@end(fndefs) + +@subsection(accumulation) +The @code(accumulation-class) takes a list of values and returns +the first, followed by the first two, followed by the first three, +etc. In other words, for each list item, return all items from the +first through the item. For example, if the list is (A B C), each +generated period is (A A B A B C). + +@begin(fndefs) +@codef{make-accumulation(@pragma(defn)@index(make-accumulation)@index(accumulation pattern)@index(pattern, accumulation)@i(items)[ ,name: @i(name),] +[trace: @i(trace)])}@\For each item, generate items from the first to +the item including the item. The period length is (@i(n)@+(2) + @i(n)) / 2 +where @i(n) is the length of @i(items). If @i(items) is a pattern, a period +from that pattern becomes the list from which items are generated, +and a new list is generated every period. Note that this is similar in +name but different from @code(make-accumulate). + +@subsection(copier) +The @code(copier-class) makes copies of periods from a sub-pattern. +For example, three periods +of @code[make-copier(make-cycle({a b c}, for: 1), repeat: 2, merge: t)] +would be @code[(A A) (B B) (C C)]. Note that entire periods (not +individual items) are repeated, so in this example the @code(:for) +keyword was used to force periods to be of length one so that +each item is repeated by the @code(:repeat) count. + +@codef{make-copier(@pragma(defn)@index(make-copier)@index(copier +pattern)@index(pattern, copier)@i(sub-pattern)[ ,repeat: @i(repeat)] [, merge: @i(merge),] +[for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Generate a period +from @i(sub-pattern) and repeat it @i(repeat) times. If @i(merge) is false +(the default), each repetition of a period from @i(sub-pattern) results +in a period by default. If @i(merge) is true (non-null), then all + @i(repeat) repetitions of the period are merged into one result +period by default. If the @code(:for) keyword is used, the same items +are generated, but the items are grouped into periods determined by +the @code(:for) parameter. If the @code(:for) parameter is a pattern, +it is evaluated every result period. The @i(repeat) and @i(merge) values +may be patterns that return a repeat count and a boolean value, respectively. +If so, these patterns are evaluated initially and after each @i(repeat) + copies are made (independent of the @code(:for) keyword parameter, if any). +The @i(repeat) value returned by a pattern can also be negative. A negative +number indicates how many periods of @i(sub-pattern) to skip. After skipping +these patterns, new @i(repeat) and @i(merge) values are generated. +@end(fndefs) + +@subsection(accumulate) +The @code(accumulate-class) forms the sum of numbers returned by another +pattern. For example, each period +of @code[make-accumulate(make-cycle({1 2 -3}))] is @code[(1 3 0)]. +The default output period length is the length of the input period. + +@begin(fndefs) +@codef{make-accumulate(@pragma(defn)@index(make-accumulate)@index(accumulate +pattern)@index(pattern, accumulate)@i(sub-pattern)[ ,for: @i(for)] [, max: @i(maximum)] [, min: @i(minimum)] [, name: @i(name)] [, trace: @i(trace)])}@\Keep +a running sum of numbers generated by @i(sub-pattern). The default +period lengths match the period lengths from @i(sub-pattern). If @i(maximum) (a pattern or a number) is specified, and the running sum exceeds @i(maximum), the running sum is reset to @i(maximum). If @i(minimum) (a pattern or a number) is specified, and the running sum falls below @i(minimum), the running sum is reset to @i(minimum). If @i(minimum) is greater than @i(maximum), the running sum will be set to one of the two values. Note that this is similar in name but not in function to +@code(make-accumulation). +@end(fndefs) + +@subsection(sum) +The @code(sum-class) forms the sum of numbers, one from each of two other +patterns. For example, each period +of @code[make-sum(make-cycle({1 2 3}), make-cycle({4 5 6}))] +is @code[(5 7 9)]. +The default output period length is the length of the input period of the +first argument. Therefore, the first argument must be a pattern, but the +second argument can be a pattern or a number. + +@begin(fndefs) +@codef{make-sum(@pragma(defn)@index(make-sum)@index(sum +pattern)@index(pattern, sum)@i(x), @i(y)[ ,for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Form +sums of items (which must be numbers) from pattern + @i(x) and pattern or number @i(y). The default +period lengths match the period lengths from @i(x). +@end(fndefs) + +@subsection(product) +The @code(product-class) forms the product of numbers, one +from each of two other +patterns. For example, each period +of @code[make-product(make-cycle({1 2 3}), make-cycle({4 5 6}))] +is @code[(4 10 18)]. +The default output period length is the length of the input period of the +first argument. Therefore, the first argument must be a pattern, but the +second argument can be a pattern or a number. + +@begin(fndefs) +@codef{make-product(@pragma(defn)@index(make-product)@index(product pattern)@index(pattern, product)@i(x), @i(y)[ ,for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Form +products of items (which must be numbers) from pattern + @i(x) and pattern or number @i(y). The default +period lengths match the period lengths from @i(x). +@end(fndefs) + + +@subsection(eval) +The @code(eval-class) evaluates an expression to produce each output item. +The default output period length is 1. + +@begin(fndefs) +@codef{make-eval(@pragma(defn)@index(make-eval)@index(eval pattern)@index(pattern, eval)@index(expression pattern)@index(pattern, expression)@i(expr)[ ,for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Evaluate +@i(expr) to generate each item. If @i(expr) is a pattern, each item is generated by getting the next item from @i(expr) and evaluating it. +@end(fndefs) + + +@subsection(length) +The @code(length-class) generates periods of a specified length from +another pattern. This is similar to using the @code(:for) keyword, but +for many patterns, the @code(:for) parameter alters the points at which +other patterns are generated. For example, if the palindrome pattern +has an @code(:elide) pattern parameter, the value will be computed every +period. If there is also a @code(:for) parameter with a value of 2, then +@code(:elide) will be recomputed every 2 items. In contrast, if the +palindrome (without a @code(:for) parameter) is embedded in a @i(length) +pattern with a lenght of 2, then the periods will all be of length 2, but +the items will come from default periods of the palindrome, and therefore +the @code(:elide) values will be recomputed at the beginnings of +default palindrome periods. + +@begin(fndefs) +@codef{make-length(@index(length pattern)@index(pattern, +length)@pragma(defn)@index(make-length)@i(pattern), @i(length-pattern), +[name: @i(name)] [, trace: @i(trace)])}@\Make a pattern of class +@code(length-class) that regroups items generated by a +@i(pattern) according to pattern lengths given by @i(length-pattern). +Note that @i(length-pattern) is not optional: There is no default +pattern length and no @code(:for) keyword. +@end(fndefs) + +@subsection(window) +The @code(window-class) groups items from another pattern by using a sliding +window. If the @i(skip) value is 1, each output period is formed +by dropping the first item of the previous perioda and appending the next item +from the pattern. The @i(skip) value and the output period length can change +every period. For a simple example, if the period length is 3 and the +skip value is 1, and the input pattern generates the sequence A, B, C, ..., +then the output periods will be (A B C), (B C D), (C D E), (D E F), .... + +@begin(fndefs) +@codef{make-window(@index(window pattern)@index(pattern, +window)@pragma(defn)@index(make-window)@i(pattern), @i(length-pattern), +@i(skip-pattern)[ ,name: @i(name)] [, trace: @i(trace)])}@\Make + a pattern of class +@code(window-class) that regroups items generated by a +@i(pattern) according to pattern lengths given by @i(length-pattern) +and where the period advances by the number of items given by +@i(skip-pattern). +Note that @i(length-pattern) is not optional: There is no default +pattern length and no @code(:for) keyword. +@end(fndefs) + + +@subsection(markov) +The @code(markov-class) generates items from a Markov model. A Markov model +generates a sequence of @i(states) according to rules which specify possible +future states +given the most recent states in the past. For example, states might be +pitches, and each pitch might lead to a choice of pitches for the next state. +In the @code(markov-class), states can be either symbols or numbers, but +not arbitrary values or patterns. This makes it easier to specify rules. +However, symbols can be mapped to arbitrary values including pattern +objects, and these become the actual generated items. +By default, all future states are weighted equally, but weights +may be associated with future states. A Markov model must be +initialized with +a sequence of past states using the @code(:past) keyword. +The most common form of Markov model is a "first +order Markov model" in which the future item depends only upon one +past item. However, higher order models where the future items depend on +two or more past items are possible. A "zero-order" Markov model, which +depends on no past states, is essentially equivalent to the random pattern. +As an example of a first-order Markov pattern, +two periods of @code[make-markov({{a -> b c} {b -> c} {c -> a}}, past: {a})] +might be @code[(C A C) (A B C)]. + +@begin(fndefs) +@codef{make-markov(@pragma(defn)@index(make-markov)@index(markov pattern)@index(pattern, markov)@i(rules)[ ,past: @i(past)] [, produces: @i(produces),] +[for: @i(for)] [, name: @i(name)] [, trace: @i(trace)])}@\Generate a sequence +of items from a Markov process. The @i(rules) parameter has the form: +@code[(@i(prev1) @i(prev2) ... @i(prevn) -> @i(next1) @i(next2) ... @i(nextn))] +where @i(prev1) through @i(prevn) represent a sequence of most recent +(past) states. The symbol @code(*) is treated specially: it matches any +previous state. If @i(prev1) through @i(prevn) (which may be just one state +as in the example above) match the previously generated states, this +rule applies. Note that every rule must specify the same number of previous +states; this number is known as the order of the Markov model. +The first rule in @i(rules) that applies is used to select the +next state. If no rule applies, the next state is @code(NIL) (which is +a valid state that can be used in rules). +Assuming a rule applies, the list of possible next +states is specified by @i(next1) +through @i(nextn). Notice that these are alternative choices for the +next state, not a sequence of future states, and each rule can have +any number of choices. Each choice may be the state +itself (a symbol or a number), or the choice may be a list consisting of +the state and a weight. The weight may be given by a pattern, in which +case the next item of the pattern is obtained every time the rule is +applied. For example, this rules says that if the previous states were +A and B, the next state can be A with a weight of 0.5 or C with an +implied weight of 1: @code[(A B -> (A 0.5) C)]. The +default length of the period is the length of @i(rules). The +@i(past) parameter must be provided. It is a list of states whose length +matches the order of the Markov model. The keyword parameter @i(produces) +may be used to map from state symbols or numbers to other values or +patterns. The parameter is a list of alternating symbols and values. For +example, to map A to 69 and B to 71, use @code[list(quote(a), 69, quote(b), 71)]. + You can +also map symbols to patterns, for example +@code[list(quote(a), make-cycle({57 69}), quote(b), make-random({59 71}))]. The +next item of the pattern is is generated each time the Markov model generates +the corresponding state. Finally, the @i(produces) keyword can be +@code(:eval), which means to evaluate the Markov model state. This could +be useful if states are Nyquist global variables such as +@code(C4, CS4, D4, ]..., which evaluate to numerical +values (60, 61, 62, ...). + +@codef{markov-create-rules(@pragma(defn)@index(markov-create-rules)@index(markov analysis)@i(sequence), @i(order)[ ,@i(generalize)])}@\Generate a set of rules suitable for the +@code(make-markov) function. The @i(sequence) is a ``typical'' sequence +of states, and @i(order) is the order of the Markov model. It is often the +case that a sample sequence will not have a transition from the last state +to any other state, so the generated Markov model can reach a ``dead end'' +where no rule applies. This might lead to an infinite stream of NIL's. To +avoid this, the optional parameter @i(generalize) can be set to @code(t) +(true), indicating that there should be a fallback rule that matches any +previous states and whose future states are weighted according to their +frequency in @i(sequence). For example, if sequence contains 5 A's, 5 B's and +10 G's, the default rule will be @code[(* -> (A 5) (B 5) (G 10))]. This +rule will be appended to the end so it will only apply if no other rule does. +@end(fndefs) + +@section(Random Number Generators) +@index(random)@index(probability distributions)@index(distributions, probability)@index(stochastic functions) +The @code(distributions.lsp) library implements random number generators that return random values with various probability distributions. Without this library, you can generate random numbers with @i(uniform) distributions. In a uniform distribution, all values are equally likely. To generate a random integer in some range, use @code(random). To generate a real number (FLONUM) in some range, use @code(real-random) (or @code(rrandom) if the range is 0-1). But there are other interesting distributions. For example, the Gaussian distribution is often used to model +real-world errors and fluctuations where values are clustered around some central value and large deviations are more unlikely than small ones. See Dennis Lorrain, "A Panoply of Stochastic 'Canons'," @i(Computer Music Journal) vol. 4, no. 1, 1980, pp. 53-81. + +In most of the random number generators described below, there are optional parameters to indicate a maximum and/or minimum value. These can be used to truncate the distribution. For example, if you basically want a Gaussian distribution, but you never want a value greater than 5, you can specify 5 as the maximum value. +The upper and lower bounds are implemented simply by drawing a random number from the full distribution repeatedly until a number falling into the desired range is obtained. Therefore, if you select an acceptable range that is unlikely, it may take Nyquist a long time to find each acceptable random number. The intended use of the upper and lower bounds is to weed out values that are already fairly unlikely. + + +@begin(fndefs) +@codef[linear-dist(@pragma(defn)@index(linear-dist)@index(linear distribution)@i(g))]@\Return a @code(FLONUM) value from a linear distribution, where the probability of a value decreases linearly from zero to @i(g) which must be greater than zero. (See Figure @ref(linear-fig).) The linear distribution is useful for generating for generating time and pitch intervals. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "linear-fig.ps")) +@html(

) +@fillcaption(The Linear Distribution, @i(g) = 1.) +@tag(linear-fig) +@end(figure) + +@begin(fndefs) +@codef{exponential-dist(@pragma(defn)@index(exponential-dist)@index(exponential distribution)@i(delta)[ ,@i(high)])}@\Return a @code(FLONUM) value from an exponential distribution. The initial downward slope is steeper with larger values of @i(delta), which must be greater than zero. (See Figure @ref(exponential-fig). The optional @i(high) parameter puts an artificial upper bound on the return value. +The exponential distribution generates values greater +than 0, and can be used to generate time intervals. Natural random intervals such as the time intervals between the release of atomic particles or the passing of yellow volkswagons in traffic have exponential distributions. The +exponential distribution is memory-less: knowing that a random number from this distribution is greater than some value (e.g. a note duration is at least 1 second) tells you nothing new about how soon the note will end. This +is a continuous distribution, but @code(geometric-dist) (described below) implements the discrete form. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "exponential-fig.ps")) +@html(

) +@fillcaption(The Exponential Distribution, @i(delta) = 1.) +@tag(exponential-fig) +@end(figure) + +@begin(fndefs) +@codef{gamma-dist(@pragma(defn)@index(gamma-dist)@i(nu)[ ,@i(high)])}@\Return a @code(FLONUM) value from a Gamma distribution. The value is greater than zero, has a mean of @i(nu) (a @code(FIXNUM) greater than zero), and a mode (peak) of around @i(nu) - 1. + The optional @i(high) parameter puts an artificial upper bound on the return value. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "gamma-fig.ps")) +@html(

) +@fillcaption(The Gamma Distribution, @i(nu) = 4.) +@tag(gamma-fig) +@end(figure) + +@begin(fndefs) +@codef{bilateral-exponential-dist(@pragma(defn)@index(bilateral-exponential-dist)@index(bilateral exponential distribution)@i(xmu), + @i(tau)[ ,@i(low)] [, @i(high)])}@\Returns a @code(FLONUM) value from a bilateral exponential distribution, where @i(xmu) is the center of the double exponential and @i(tau) controls the spread of the distribution. A larger @i(tau) gives a wider distribution (greater variance), and @i(tau) must be greater than zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +This distribution is similar to the exponential, except +it is centered at 0 and can output negative values as well. Like +the exponential, it can be used to generate time intervals; however, it might be necessary to add a lower bound so as not to compute a negative time interval. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "bilateral-fig.ps")) +@html(

) +@fillcaption(The Bilateral Exponential Distribution.) +@tag(bilateral-fig) +@end(figure) + +@begin(fndefs) +@codef{cauchy-dist(@pragma(defn)@index(cauchy-dist)@index(cauchy distribution)@i(tau)[ ,@i(low)] [, @i(high)])}@\Returns a @code(FLONUM) from the Cauchy distribution, a symetric distribution with a high peak at zero and a width (variance) that increases with parameter @i(tau), which must be greater than zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "cauchy-fig.ps")) +@html(

) +@fillcaption(The Cauchy Distribution, @i(tau) = 1.) +@tag(cauchy-fig) +@end(figure) + +@begin(fndefs) +@codef{hyperbolic-cosine-dist(@pragma(defn)@index(hyperbolic-cosine-dist) [@i(low)] [, @i(high)])}@\Returns a @code(FLONUM) value from the hyperbolic cosine distribution, a symetric distribution with its peak at zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "hyperbolic-fig.ps")) +@html(

) +@fillcaption(The Hyperbolic Cosine Distribution.) +@tag(hyperbolic-fig) +@end(figure) + +@begin(fndefs) +@codef{logistic-dist(@pragma(defn)@index(logistic-dist)@index(logistic distribution)@i(alpha), @i(beta)[ ,@i(low)] [, @i(high)])}@\Returns a @code(FLONUM) value from the logistic distribution, which is symetric about the mean. The @i(alpha) parameter primarily affects dispersion (variance), with larger values resulting in values closer to the mean (less variance), and the @i(beta) parameter primarily influences the mean. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "logistic-fig.ps")) +@html(

) +@fillcaption(The Logistic Distribution, alpha = 1, beta = 2.) +@tag(logistic-fig) +@end(figure) + +@begin(fndefs) +@codef{arc-sine-dist(@pragma(defn)@index(arc-sine-dist)@index(arcsine distribution))}@\Returns a @code(FLONUM) value from the arc sine distribution, which outputs values between 0 and 1. It is symetric about the mean of 1/2, but is more likely to generate values closer to 0 and 1. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "arcsine-fig.ps")) +@html(

) +@fillcaption(The Arc Sine Distribution.) +@tag(arcsine-fig) +@end(figure) + +@begin(fndefs) +@codef{gaussian-dist(@index(Gaussian distribution)@pragma(defn)@index(gaussian-dist)@i(xmu), @i(sigma)[ ,@i(low)] [, @i(high)])}@\Returns a @code(FLONUM) value from the Gaussian or Gauss-Laplace distribution, a linear function of the normal distribution. It is symetric about the mean of @i(xmu), with a standard deviation of @i(sigma), which must be greater than zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "gaussian-fig.ps")) +@html(

) +@fillcaption{The Gauss-Laplace (Gaussian) Distribution, @i(xmu) = 0, @i(sigma) = 1.} +@tag(gaussian-fig) +@end(figure) + +@begin(fndefs) +@codef{beta-dist(@index(beta distribution)@pragma(defn)@index(beta-dist)@i(a), @i(b))}@\Returns a @code(FLONUM) value from the Beta distribution. This distribution outputs values between 0 and 1, with outputs more likely to be close to 0 or 1. The parameter @i(a) controls the height (probability) of the right side of the distribution (at 1) and @i(b) controls the height of the left side (at 0). The distribution is symetric about 1/2 when @i(a) = @i(b). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "beta-fig.ps")) +@html(

) +@fillcaption(The Beta Distribution, @i(alpha) = .5, @i(beta) = .25.) +@tag(beta-fig) +@end(figure) + +@begin(fndefs) +@codef{bernoulli-dist(@index(Bernoulli distribution)@pragma(defn)@index(bernoulli-dist)@i(px1)[ ,@i(x1)] [, @i(x2)])}@\Returns either @i(x1) (default value is 1) with probability @i(px1) or @i(x2) (default value is 0) with probability 1 - @i(px1). The value of @i(px1) should be between 0 and 1. By +convention, a result of @i(x1) is viewed as a success while @i(x2) is viewed as +a failure. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "bernoulli-fig.ps")) +@html(

) +@fillcaption(The Bernoulli Distribution, @i(px1) = .75.) +@tag(bernoulli-fig) +@end(figure) + +@begin(fndefs) +@code{(binomial-dist@index(binomial distribution)@pragma(defn)@index(binomial-dist) @i(n) @i(p)}@\Returns a @code(FIXNUM) value from the binomial distribution, where @i(n) is the number of Bernoulli trials run (a @code(FIXNUM)) and @i(p) is the probability of success in the Bernoulli trial (a @code(FLONUM) from 0 to 1). The mean is the product of @i(n) and @i(p). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "binomial-fig.ps")) +@html(

) +@fillcaption(The Binomial Distribution, @i(n) = 5, @i(p) = .5.) +@tag(binomial-fig) +@end(figure) + +@begin(fndefs) +@codef{geometric-dist(@index(geometric distribution)@pragma(defn)@index(geometric-dist)@i(p))}@\Returns a @code(FIXNUM) value from the geometric distribution, which is defined as the number of failures before a success is achieved in a Bernoulli trial with probability of success @i(p) (a @code(FLONUM) from 0 to 1). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "geometric-fig.ps")) +@html(

) +@fillcaption(The Geometric Distribution, @i(p) = .4.) +@tag(geometric-fig) +@end(figure) + +@begin(fndefs) +@codef{poisson-dist(@index(Poisson distribution)@pragma(defn)@index(poisson-dist)@i(delta))}@\Returns a @code(FIXNUM) value from the Poisson distribution with a mean of @i(delta) (a @code(FIXNUM)). The Poisson distribution is often used to generate a sequence of time intervals, resulting in random but often pleasing rhythms. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "poisson-fig.ps")) +@html(

) +@fillcaption(The Poisson Distribution, @i(delta) = 3.) +@tag(poisson-fig) +@end(figure) + +@begin(comment) +***************** +Note: this should remain out of Nyquist until the granulate code is cleaned up (why are there separate functions for pitch-dist and len-dist instead of a single function where any parameter can be specified by a closure?) +***************** +@begin(fndefs) +@codef{pitch-dist-granulate(@pragma(defn)@index(pitch-dist-granulate)@index(granular synthesis)@i(filename), @i(grain-dur), @i(grain-dev), @i(ioi), @i(ioi-dev), @i(pitch-dist)[ ,@i(file-start)] [, @i(file-end)])}@\*** need to write this *** + +@i(filename) @dash name of the file + +@i(dist) @dash the distribution that determines the length of the grains + +@i(ioi) @dash the basic inter-onset-interval for grains + +@i(ioi-dev) @dash ioi is actually: ioi + random(0, ioi-dev) + +@i(pitch-dev) @dash grains are resampled at rate between 1 and pitch-dev + +@i(file-start) @dash when to start reading the file (an offset from start). The +default is 0. + +@i(file-end) @dash when to stop reading the file (an offset from end) the +default is 0 + +returns @dash a set of sound grains created from the input file + +This is a granular +synthesis function based on the one by Roger B. Dannenberg. The +pitch of the grains will be based on the distribution you give to it. The +distribution must be passed in as a continuation. + +(len-dist-granulate @i(filename) @i(dist ioi ioi-dev) @i(pitch-dev) [@i(file-start)] [@i(file-end)]) + +@i(filename) @dash name of the file + +@i(grain-dur)– the duration of a grain + +@i(grain-dev)– grain dur is actually grain-dur + random(0, grain-dev) + +@i(ioi)– the basic inter-onset-interval for grains + +@i(ioi-dev)– ioi is actually: ioi + random(0, ioi-dev) + +@i(pitch-dist)– the distribution of the alteration in pitch to the grains. The +distribution values should be > 1. + +@i(file-start)– when to start reading the file (an offset from start). The +default is 0 + +@i(file-end)– when to stop reading the file (an offset from end). The +default is 0 + +returns– a set of sound grains created from the input file + +This is a granular +synthesis function based on the one by Roger B. Dannenberg. The +length of the grains will be based on the distribution you give to it. The +distribution must be passed in as a continuation. +@end(fndefs) +@end(comment) + +@section(Score Generation and Manipulation) + +A common application of pattern generators is to specify parameters +for notes. (It should be understood that ``notes'' in this context +means any Nyquist behavior, whether it represents a conventional note, +an abstract sound object, or even some micro-sound event that is just +a low-level component of a hierarchical sound organization. Similarly, +``score'' should be taken to mean a specification for a +sequence of these ``notes.'') +The @code(score-gen) macro (defined by +loading @code(xm.lsp)) establishes a convention for representing +scores and for generating them using patterns. + +The @code(timed-seq) macro, described in Section @ref(timed-seq-sec), +already provides a way to represent a ``score'' as a list of expressions. +The Xmusic representation goes a bit further by specifying that +@i(all notes are specified by an alternation of keywords and values, where +some keywords have specific meanings and interpretations.) + +The basic idea of @code(score-gen)@index(score-gen) is you provide a template for notes in +a score as a set of keywords and values. For example, +@begin(example) +set pitch-pattern = make-cycle(list(c4, d4, e4, f4)) +score-gen(dur: 0.4, name: quote(my-sound), + pitch: next(pitch-pattern), score-len: 9) +@end(example) +generates a score of 9 notes as follows: +@begin(example) +((0 0 (SCORE-BEGIN-END 0 3.6)) + (0 0.4 (MY-SOUND :PITCH 60)) + (0.4 0.4 (MY-SOUND :PITCH 62)) + (0.8 0.4 (MY-SOUND :PITCH 64)) + (1.2 0.4 (MY-SOUND :PITCH 65)) + (1.6 0.4 (MY-SOUND :PITCH 60)) + (2 0.4 (MY-SOUND :PITCH 62)) + (2.4 0.4 (MY-SOUND :PITCH 64)) + (2.8 0.4 (MY-SOUND :PITCH 65)) + (3.2 0.4 (MY-SOUND :PITCH 60))) +@end(example) +The use of keywords like @code(:PITCH) helps to make scores +readable and easy to process without specific knowledge of +about the functions called in the score. For example, one +could write a transpose operation to transform all the +@code(:pitch) parameters in a score without having to know +that pitch is the first parameter of @code(pluck) and the +second parameter of @code(piano-note). Keyword parameters are +also used to give flexibility to note specification with +@code(score-gen). Since this approach requires the use of +keywords, the next section +is a brief explanation of how to define functions that use +keyword parameters. + +@subsection(Keyword Parameters) +@index(keyword parameters) +@index(parameters, keyword) +Keyword parameters are parameters whose presence is +indicated by a special symbol, called a keyword, followed +by the actual parameter. Keyword parameters in SAL have +default values that are used if no actual parameter is +provided by the caller of the function. (See Appendix + @ref(xlisp-app) to learn about keywords in XLISP.) + +To specify that a parameter is a keyword parameter, +use a keyword symbol (one that ends in a colon) followed +by a default value. + For example, here is a function that +accepts keyword parameters and invokes the @code(pluck) +function: +@begin(example) +define function k-pluck(pitch: 60, dur: 1) + return pluck(pitch, dur) +@end(example) +Now, we can call k-pluck with keyword parameters. The +keywords are simply the formal parameter names with +a prepended colon character (@code(:pitch) and @code(:dur) +in this example), so a function call would look like: +@begin(example) +pluck(pitch: c3, dur: 3) +@end(example) +Usually, it is best to give keyword parameters useful +default values. That way, if a parameter such as @code(dur:) +is missing, a reasonable default value (1) can be used +automatically. +It is never an error to omit a keyword parameter, but the +called function can check to see if a keyword parameter +was supplied or not. +Because of default values, we can call +@code[k-pluck(pitch: c3)] with no duration, +@code[k-pluck(dur: 3)] with only a duration, +or even @code[k-pluck()] with no parameters. + +In XLISP, there is additional syntax to specify an alternate symbol +to be used as the keyword and to allow the called function +to determine whether or not a keyword parameter was +supplied, but these features are little-used. See the XLISP +manual for details. + +@subsection(Using score-gen)@pragma(defn)@index(score-gen) +The @code(score-gen) macro computes a score based on keyword parameters. +Some keywords have a special meaning, while others are not interpreted +but merely placed in the score. The resulting score can be synthesized +using @code(timed-seq) (see Section @ref(timed-seq-sec)). + +The form of a call to @code(score-gen) is simply: +@begin(fndefs) +@codef[score-gen(@pragma(defn)@index(score-gen)@i(k1:) @i(e1), @i(k2:) @i(e2), ... )]@\where the @i(k)'s +are keywords and the @i(e)'s are +expressions. A score is generated by evaluating the expressions once for +each note and constructing a list of keyword-value pairs. A number +of keywords have special interpretations. The rules for interpreting +these parameters will be explained through a set of "How do I ..." +questions below. +@end(fndefs) + +@i(How many notes will be generated?) The keyword +parameter @code(:score-len) specifies an upper bound on the number +of notes. The keyword @code(:score-dur) specifies an upper bound +on the starting time of the last note in the score. (To be more +precise, the @code(:score-dur) bound is reached when the +default starting time of the next note is greater than or equal +to the @code(:score-dur) value. This definition is necessary because +note times are not strictly increasing.) When either bound +is reached, score generation ends. At least one of these two +parameters must be specified or an error is raised. These keyword +parameters are evaluated just once and are not copied into the +parameter lists of generated notes. + +@i(What is the duration of generated notes?) The +keyword @code(:dur) defaults to 1 and specifies the nominal duration +in seconds. Since the generated note list is compatible with +@code(timed-seq), the starting time and duration (to be precise, the +@i(stretch factor)) are not passed as parameters to the notes. Instead, +they control the Nyquist environment in which the note will be evaluated. + +@i(What is the start time of a note?) The default start time of the +first note is zero. Given a note, the default start time of the next note is +the start time plus the inter-onset time, which is given by the @code(:ioi) +parameter. If no @code(:ioi) parameter is specified, the inter-onset time +defaults to the duration, given by @code(:dur). In all cases, the default +start time of a note can be overridden by the keyword parameter @code(:time). + +@i(When does the score begin and end?) The behavior @code[SCORE-BEGIN-END] +contains the beginning and ending of the +score (these are used for score manipulations, e.g. when scores are merged, +their begin times can be aligned.) When @code(timed-seq) is used to +synthesize a score, the @code(SCORE-BEGIN-END) marker is +not evaluated. The @code(score-gen) macro inserts a ``note'' of the form +@code[(0 0 (SCORE-BEGIN-END @i(begin-time) @i(end-time)))] +at the time given by the @code(:begin) keyword, with @i(begin-time) and +@i(end-time) determined by the @code(:begin) and @code(:end) +keyword parameters, respectively. If the @i(:begin) keyword is not +provided, the score begins at zero. If the @code(:end) keyword +is not provided, the score ends at the default start time +of what would be the next note after the last note in the score +(as described in the previous paragraph). Note: if @code(:time) is used to +compute note starting times, and these times are not increasing, it is +strongly advised to use @code(:end) to specify an end time for the score, +because the default end time may be anywhere in the middle of the +generated sequence. + +@i(What function is called to synthesize the note?) The @code(:name) +parameter names the function. Like other parameters, the value can be any +expression, including something like @code[next(fn-name-pattern)], +allowing function names to be recomputed for each note. The default value +is @code(note). + +@i(Can I make parameters depend upon the starting time or the duration +of the note?) Parameter expressions can use the variable @code(sg:time) +to access the start time of the note, @code(sg:ioi) to access the +inter-onset time, and @code(sg:dur) to access the +duration (stretch factor) of the note. Also, @code(sg:count) counts how +many notes have been computed so far, starting at 0. The order of +computation is: @code(sg:time) first, then @code(sg:ioi) and @code(sg:dur), +so for example, an expression to compute @code(sg:dur) can +depend on @code(sg:ioi). + +@i(Can parameters depend on each other?) The keyword @code(:pre) +introduces an expression that is evaluated before each note, and +@code(:post) provides an expression to be evaluated after each note. +The @code(:pre) expression can assign one or more global variables +which are then used in one or more expressions for parameters. + +@i(How do I debug @code(score-gen) expressions?) You can set the +@code(:trace) parameter to true (@code(t)) to enable a print statement +for each generated note. + +@i(How can I save scores generated by @code(score-gen) that I like?) If the +keyword parameter @code(:save) is set to a symbol, the global variable +named by the symbol is set to the value of the generated sequence. Of +course, the value returned by @code(score-gen) is just an ordinary list that +can be saved like any other value. + +In summary, the following keywords have special interpretations +in @code(score-gen): +@code(:begin), @code(:end), @code(:time), @code(:dur), @code(:name), +@code(:ioi), @code(:trace), +@code(:save), @code(:score-len), @code(:score-dur), @code(:pre), @code(:post). + All other keyword +parameters are expressions that are evaluated once for each note +and become the parameters of the notes. + +@subsection(Score Manipulation) +@index(score manipulation)@index(manipulation of scores) +Nyquist encourages the representation of music as +executable programs, or @i(behaviors), and there are various +ways to modify behaviors, including time stretching, +transposition, etc. An alternative to composing executable +programs is to manipulate scores as editable data. Each +approach has its strengths and weaknesses. This section +describes functions intended to manipulate Xmusic scores +as generated by, or at least in the form generated by, +@code(score-gen). Recall that this means scores are lists +of events (e.g. notes), where events are three-element lists of the form +(@i(time) @i(duration) @i(expression), and where @i(expression) +is a standard lisp function call where all parameters are +keyword parameters. In addition, the first ``note'' may be +the special @code(SCORE-BEGIN-END) expression. If this is +missing, the score begins at zero and ends at the end of the +last note. + +For convenience, a set of functions is offered to access properties +of events (or notes) in scores. Although lisp functions such as +@code(car), @code(cadr), and @code(caddr) can be used, code is more +readable when more mnemonic functions are used to access events. + +@begin(fndefs) +@codef[event-time(@pragma(defn)@index(event-time)@i(event))]@\Retrieve the time field from +an event. + +@codef[event-set-time(@pragma(defn)@index(event-set-time)@i(event), @i(time))]@\Construct +a new event where the time of @i(event) is replaced by @i(time). + +@codef[event-dur(@pragma(defn)@index(event-dur)@i(event))]@\Retrieve the duration +(i.e. the stretch factor) field from an event. + +@codef[event-set-dur(@pragma(defn)@index(event-set-dur)@i(event), @i(dur))]@\Construct +a new event where the duration (or stretch factor) of @i(event) is +replaced by @i(dur). + +@codef[event-expression(@pragma(defn)@index(event-expression)@i(event))]@\Retrieve the expression +field from an event. + +@codef[event-set-expression(@pragma(defn)@index(event-set-expression)@i(event), +@i(dur))]@\Construct +a new event where the expression of @i(event) is replaced by @i(expression). + +@codef[event-end(@pragma(defn)@index(event-end)@i(event))]@\Retrieve the end time +of @i(event), its time plus its duration. + +@codef[expr-has-attr(@pragma(defn)@index(expr-has-attr)@i(expression), @i(attribute))]@\Test +whether a score event @i(expression) has the given @i(attribute). + +@codef{expr-get-attr(@pragma(defn)@index(expr-get-attr)@i(expression), @i(attribute), +[@i(default)])}@\Get the value of the given @i(attribute) from a score event +@i(expression). If @i(attribute) is not present, return @i(default) if +specified, and otherwise @code(nil). + +@codef{expr-set-attr(@pragma(defn)@index(expr-set-attr)@i(expr), @i(attribute), @i(value))}@\Construct a new expression identical to @i(expr) except that the @i(attribute) has @i(value). + +@codef[event-has-attr(@pragma(defn)@index(event-has-attr)@i(event), @i(attribute))]@\Test +whether a given score @i(event)'s expression has the given @i(attribute). + +@codef{event-get-attr(@pragma(defn)@index(event-get-attr)@i(event), @i(attribute), +[@i(default)])}@\Get the value of the given @i(attribute) from a score +@i(event)'s expression. If @i(attribute) is not present, return @i(default) if +specified, and otherwise @code(nil). + +@codef{event-set-attr(@pragma(defn)@index(event-set-attr)@i(event), @i(attribute), @i(value))}@\Construct a new event identical to @i(event) except that the @i(attribute) has @i(value). + +@end(fndefs) + +Functions are provided to shift the starting times of notes, +stretch times and durations, stretch only durations, +add an offset to a keyword parameter, scale a keyword parameter, and +other manipulations. Functions are also provided to extract +ranges of notes, notes that match criteria, and to combine scores. +Most of these functions (listed below in detail) +share a set of keyword parameters that optionally limit the range over which +the transformation operates. The @code(:from-index) and @code(:to-index) +parameters specify the index of the first note and the index of the +last note to be changed. If these numbers are negative, they are offsets +from the end of the score, e.g. -1 denotes the last note of the score. The +@code(:from-time) and @code(:to-time) indicate a range of starting times +of notes that will be affected by the manipulation. Only notes whose time +is greater than or equal to the @i(from-time) and @i(strictly less than) + the @i(to-time) are modified. If both index and time ranges are specified, +only notes that satisfy @i(both) constraints are selected. + +@begin(fndefs) +@codef[score-sorted(@pragma(defn)@index(score-sorted)@i(score))]@\Test if @i(score) is sorted. + +@codef{score-sort(@pragma(defn)@index(score-sort)@i(score)[ ,@i(copy-flag)])}@\Sort + the notes in a +score into start-time order. If copy-flag is nil, this is a destructive +operation which should only be performed if the top-level score list +is a fresh copy that is not shared by any other variables. (The +@i(copy-flag) is intended for internal system use only.) + For the following operations, it is assumed +that scores are sorted, and all operations return a sorted score. + +@codef{score-shift(@pragma(defn)@index(score-shift)@i(score), @i(offset)[ ,from-index: @i(i),] +[to-index: @i(j)] [, from-time: @i(x)] [, to-time: @i(y)])}@\Add a constant +@i(offset) to the starting time of a set of notes in @i(score). By default, +all notes are modified, but the range of notes can be limited with the +keyword parameters. The begin time of the score is not changed, but the +end time is increased by @i(offset). +The original score is not modified, and a new score is returned. + +@codef{score-stretch(@pragma(defn)@index(score-stretch)@i(score), @i(factor), +[dur: @i(dur-flag)] [, time: @i(time-flag)] [, from-index: @i(i),] +[to-index: @i(j)] [, from-time: @i(x)] [, to-time: @i(y)])}@\Stretch +note times and durations by @i(factor). The default @i(dur-flag) is +non-null, but if @i(dur-flag) is null, the original durations are retained +and only times are stretched. Similarly, the default @i(time-flag) is +non-null, but if @i(time-flag) is null, the original times are retained +and only durations are stretched. If both @i(dur-flag) and @i(time-flag) +are null, the score is not changed. If a range +of notes is specified, times are scaled within that range, and +notes after the range are shifted so that the stretched region does not +create a "hole" or overlap with notes that follow. If the range begins +or ends with a time (via @code(:from-time) and @code(:to-time)), time +stretching +takes place over the indicated time interval independent of whether +any notes are present or where they start. In other words, the +``rests'' are stretched along with the notes. +The original score is not modified, and a new score is returned. + +@codef{score-transpose(@pragma(defn)@index(score-transpose)@i(score), +@i(keyword), @i(amount)[ ,from-index: @i(i),] +[to-index: @i(j)] [, from-time: @i(x)] [, to-time: @i(y)])}@\For each note +in the score and in any indicated range, if there is a keyword + parameter matching @i(keyword) and the +parameter value is a number, increment +the parameter value by @i(amount). For example, to tranpose up by a whole +step, write @code[(score-transpose 2 :pitch @i(score))]. The +original score is not modified, and a new score +is returned. + +@codef{score-scale(@pragma(defn)@index(score-scale)@i(score), @i(keyword), @i(amount), + [from-index: @i(i),] +[to-index: @i(j)] [, from-time: @i(x)] [, to-time: @i(y)])}@\For each note +in the score and in any indicated range, if there is a keyword +parameter matching @i(keyword) and the +parameter value is a number, multiply +the parameter value by @i(amount). The original score is not modified, +and a new score is returned. + +@codef{score-sustain(@pragma(defn)@index(score-sustain)@i(score), @i(factor), + [from-index: @i(i),] +[to-index: @i(j)] [, from-time: @i(x)] [, to-time: @i(y)])}@\For each note +in the score and in any indicated range, multiply +the duration (stretch factor) by @i(amount). This can be used to +make notes sound more legato or staccato, and does not change their +starting times. The original score is not modified, and +a new score is returned. + +@codef{score-voice(@pragma(defn)@index(score-voice)@i(score), @i(replacement-list), + [from-index: @i(i),] +[to-index: @i(j)] [, from-time: @i(x)] [, to-time: @i(y)])}@\For each note +in the score and in any indicated range, replace the behavior (function) +name using @i(replacement-list), which has the format: +@code[((@i(old1 new1)) (@i(old2 new2)) ...)], where @i(oldi) indicates +a current behavior name and @i(newi) is the replacement. If @i(oldi) +is @code(*), it matches anything. For example, to +replace @code(my-note-1) by @code(trombone) and @code(my-note-2) by +@code(horn), use @code[score-voice(@i(score), {{my-note-1 trombone} +{my-note-2 horn}})]. To replace all instruments with +@code(piano), use @code[score-voice(@i(score), {{* piano}})]. +The original score is not modified, and a + new score is returned. + +@codef{score-merge(@pragma(defn)@index(score-merge)@i(score1), @i(score2), ...)}@\Create +a new score containing all the notes of the parameters, which are all +scores. The resulting notes retain their original times and durations. The +merged score begin time is the minimum of the begin times of the parameters +and the merged score end time is the maximum of the end times of +the parameters. The original scores are not modified, and a new +score is returned. + +@codef{score-append(@pragma(defn)@index(score-append)@i(score1), @i(score2), ...)}@\Create +a new score containing all the notes of the parameters, which are all +scores. The begin time of the first score is unaltered. The begin time of + each other score is aligned to the end time of the +previous score; thus, scores are ``spliced'' in sequence. The original +scores are not modified, and a new score is returned. + +@codef{score-select(@pragma(defn)@index(score-select)@index(score-filter)@i(score), @i(predicate), + [from-index: @i(i)] [, to-index: @i(j),] +[from-time: @i(x)] [, to-time: @i(y)] [, reject: @i(flag)])}@\Select (or reject) +notes to form a new score. Notes are selected if they fall into the +given ranges of index and time @i(and) they satisfy @i(predicate), a function +of three parameters that is applied to the start time, duration, and the +expression of the note. Alternatively, @i(predicate) may be @code(t), +indicating that all notes in range are to be selected. +The selected notes along with the existing score begin and end markers, are combined to form a new score. Alternatively, if +the @code(:reject) parameter is non-null, the notes @i(not) selected form + the new score (in other words the selected notes are rejected or removed to + form the new score). The original score is not modified, and a + new score is returned. + +@codef{score-set-begin(@pragma(defn)@index(score-set-begin)@i(score), @i(time))}@\The begin +time + from the @i(score)'s @code(SCORE-BEGIN-END) marker is set to @i(time). The +original score is not modified, and a new score is returned. + +@codef{score-get-begin(@pragma(defn)@index(score-get-begin)@i(score))}@\Return the begin +time of the @i(score). + +@codef{score-set-end(@pragma(defn)@index(score-set-end)@i(score), @i(time))}@\The end time + from the @i(score)'s @code(SCORE-BEGIN-END) marker is set to @i(time). The +original score is not modified, and a new score is returned. + +@codef{score-get-end(@pragma(defn)@index(score-get-end)@i(score))}@\Return the end +time of the @i(score). + +@codef{score-must-have-begin-end(@pragma(defn)@index(score-must-have-begin-end)@i(score))}@\If + @i(score) does not have a begin and end time, construct a score with a + @code(SCORE-BEGIN-END) expression and return it. If score already has a begin +and end time, just return the score. The orignal score is not modified. + +@codef{score-filter-length(@pragma(defn)@index(score-filter-length)@i(score), +@i(cutoff))}@\Remove notes that extend beyond the @i(cutoff) time. This +is similar to @code(score-select), but the here, events are removed when +their nominal ending time (start time plus duration) exceeds the @i(cutoff), +whereas the @code(:to-time) parameter is compared to the note's start time. +The original score is not modified, and a new score is returned. + +@codef{score-repeat(@pragma(defn)@index(score-repeat)@i(score), @i(n))}@\Make a sequence +of @i(n) copies of @i(score). Each copy is shifted to that it's begin +time aligns with the end time of the previous copy, as in @code(score-append). +The original score is not modified, and a new score is returned. + +@codef{score-stretch-to-length(@pragma(defn)@index(score-stretch-to-length)@i(score), +@i(length))}@\Stretch the score so that the end time of the score is +the score's begin time plus @i(length). +The original score is not modified, and a new score is returned. + +@codef{score-filter-overlap(@pragma(defn)@index(score-filter-overlap)@i(score))}@\Remove +overlapping notes (based on the note start time and duration), giving +priority to the +positional order within the note list (which is also time order). +The original score is not modified, +and a new score is returned. + +@codef{score-print(@pragma(defn)@index(score-print)@i(score))}@\Print a score with +one note per line. Returns @code(nil). + +@codef{score-play(@pragma(defn)@index(score-play)@i(score))}@\Play @i(score) +using @code(timed-seq) to convert the score to a sound, and + @code(play) to play the sound. + +@codef{score-adjacent-events(@pragma(defn)@index(score-adjacent-events)@i(score), + @i(function), + [from-index: @i(i)] [, to-index: @i(j),] +[from-time: @i(x)] [, to-time: @i(y)])}@\Call + @code[(@i(function) @i(A) @i(B) @i(C))], where +@i(A), @i(B), and @i(C) are consecutive notes in the score. The result +replaces @i(B). If the result is @code(nil), @i(B) is deleted, and the +next call will be @code[(@i(function A C D))], etc. The first call is +to @code[(@i(function) nil @i(A B))] and the last is to +@code[(@i(function) @i(Y Z) nil)]. If there is just one note in the +score, @code[(@i(function) nil @i(A) nil)] is called. Function calls +are not made if the note is outside of the indicated range. +This function +allows notes and their parameters to be adjusted according to their +immediate context. The original score is not modified, +and a new score is returned. + +@codef{score-apply(@pragma(defn)@index(score-apply)@i(score), @i(function), + [from-index: @i(i)] [, to-index: @i(j),] +[from-time: @i(x)] [, to-time: @i(y)])}@\Replace +each note in the score with the result of + @code[(@i(function time dur expression))], where @i(time), @i(dur), +and @i(expression) are the time, duration, and expression of the note. +If a range is indicated, only notes in the range are replaced. +The original score is not modified, and a new score is returned. + +@codef{score-indexof(@pragma(defn)@index(score-indexof)@i(score), @i(function), + [from-index: @i(i)] [, to-index: @i(j),] +[from-time: @i(x)] [, to-time: @i(y)])}@\Return the index (position) +of the first score event (in range) for which applying @i(function) +using @code[(@i(function time dur expression))] returns true. + + +@codef{score-last-indexof(@pragma(defn)@index(score-last-indexof)@i(score), @i(function), + [from-index: @i(i)] [, to-index: @i(j),] +[from-time: @i(x)] [, to-time: @i(y)])}@\Return the index (position) +of the last score event (in range) for which applying @i(function) +using @code[(@i(function time dur expression))] returns true. + +@codef{score-randomize-start(@pragma(defn)@index(score-randomize-start)@index(jitter)@index(feel factor)@index(offset)@i(score), +@i(amt)[ ,from-index: @i(i)] [, to-index: @i(j),] +[from-time: @i(x)] [, to-time: @i(y)])}@\Alter the start times of notes by a +random amount up to plus or minus @i(amt). +The original score is not modified, and a new score is returned. +@end(fndefs) + +@subsection(Xmusic and Standard MIDI Files) +@index(MIDI file)@index(Standard MIDI File) +Nyquist has a general facility to read and write MIDI files. +You can even translate to and from a text representation, as described +in Chapter @ref(adagio-chap). It is also useful sometimes to read notes +from Standard MIDI Files into Xmusic scores and vice versa. At present, +Xmusic only translates notes, ignoring the various controls, program +changes, pitch bends, and other messages. + +MIDI notes are translated to Xmusic score events as follows: +@begin(display) +@code[(@i(time) @i(dur) (NOTE :chan @i(channel) :pitch @i(keynum) :vel @i(velocity)))], +@end(display) +where @i(channel), @i(keynum), and @i(velocity) come directly +from the MIDI message (channels are numbered starting from zero). +Note also that note-off messages are implied by the stretch factor +@i(dur) which is duration in seconds. + +@begin(fndefs) +@codef{score-read-smf(@pragma(defn)@index(score-read-smf)@index(midi file)@i(filename))}@\Read a +standard MIDI file from @i(filename). Return an Xmusic score, or @code(nil) +if the file could not be opened. The +start time is zero, and the end time is the maximum end time of all +notes. A very limited interface is offered to extract MIDI program numbers +from the file: The global variable @code(*rslt*) is set to a list of MIDI +program numbers for each channel. E.g. if @code(*rslt*) is @code[(0 20 77)], +then program for channel 0 is 0, for channel 1 is 20, and for channel 2 is 77. +Program changes were not found on other channels. The default program number is +0, so in this example, it is not known whether the program 0 on channel 0 +is the result of a real MIDI program change command or just a default value. +If more than one program change exists on a channel, the @i[last] program +number is recorded and returned, so this information will only be completely +correct when the MIDI file sends single program change per channel before +any notes are played. This, however, is a fairly common practice. Note that +the list returned as @code(*rslt*) can be passed +to @code(score-write-smf), described below. + +@codef{score-write-smf(@pragma(defn)@index(score-write-smf)@index(midi file)@i(score), @i(filename), +[@i(programs)])}@\Write a standard MIDI file to @i(filename) +with notes in @i(score). In this function, +@i(every) event in the score with a @code(:pitch) attribute, regardless of the +``instrument'' (or function name), generates a +MIDI note, using the @code(:chan) attribute for the channel (default 0) and +the @code(:vel) attribute for velocity (default 100). There is no facility +(in the current implementation) to issue control changes, but to allow +different instruments, MIDI programs may be set in two ways. The simplest is +to associate programs with channels using +the optional @i[programs] parameter, which is simply a list of up to 16 MIDI +program numbers. Corresponding program change commands are added to the +beginning of the MIDI file. If @i[programs] has less than 16 elements, program +change commands are only sent on the first @i[n] channels. The second way to +issue MIDI program changes is to add a @code(:program) keyword parameter to +a note in the score. Typically, the note will have a @code(:pitch) of +@code(nil) so that no actual MIDI note-on message is generated. If program +changes and notes have the same starting times, their relative playback +order is undefined, and the note may be cut off by an immediately +following program change. Therefore, program changes should occur slightly, +e.g. 1 ms, before any notes. @i(Program numbers and channels are numbered +starting at zero, matching the internal MIDI representation. This may be +one less than displayed on MIDI hardware, sequencers, etc.) +@end(fndefs) + +@subsection(Workspaces) +@label(workspaces-sec) +@index(workspace) +When working with scores, you may find it necessary to save +them in files between work sessions. This is not an issue +with functions because they are +normally edited in files and loaded from them. In contrast, +scores are created as Lisp data, and unless you take care to +save them, they will be destroyed when you exit the Nyquist +program. + +A simple mechanism called a workspace has been created +to manage scores (and any other Lisp data, for that matter). +A workspace is just a set of lisp global variables. These +variables are stored in the file @code(workspace.lsp). +For simplicity, there is only one workspace, and no backups +or versions are maintained, but the user is free to make +backups and copies of @code(workspace.lsp). +To help remember what each variable is for, you can also +associate and retrieve a text string with each variable. +The following functions manage workspaces. + +In addition, when a workspace is loaded, you can request that +functions be called. For example, the workspace might store +descriptions of a graphical interface. When the workspace is +loaded, a function might run to convert saved data into a +graphical interface. (This is how sliders are saved by the IDE.) + +@begin(fndefs) +@codef[add-to-workspace(@pragma(defn)@index(add-to-workspace)@i(symbol))]@\Adds +a global variable to the workspace. The @i(symbol) should be a (quoted) +symbol. + +@codef[save-workspace(@pragma(defn)@index(save-workspace))]@\All global variables +in the workspace are saved to @code(workspace.lsp) (in the current +directory), overwriting the previous file. + +@codef{describe(@pragma(defn)@index(describe)@i(symbol), +[@i(description)])}@\If @i(description), a text string, is present, +associate @i(description) with the variable named by the +@i(symbol). If @i(symbol) is not already in the workspace, +it is added. If @i(description) is omitted, the function returns +the current description (from a previous call) for @i(symbol). + +@codef{add-action-to-workspace(@pragma(defn)@index(add-action-to-workspace)@i(symbol))}@\Requests that the function named by @i(symbol) be +called when the workspace is loaded (if the function is defined). +@end(fndefs) + +To restore a workspace, use the command @code[load "workspace"]. This restores +the values of the workspace variables to the values they had when +@code(save-workspace) was last called. It also restores the documentation +strings, if set, by @code(describe). If you load two or more +@code(workspace.lsp) files, the variables will be merged into a +single workspace. The current set of workspace variables are saved in +the list @code(*workspace*). To clear the workspace, set @code(*workspace*) +to @code(nil). This does not delete any variables, but means that +no variables will be saved by @code(save-workspace) until variables are +added again. + +Functions to be called are saved in the list @code(*workspace-actions*). +to clear the functions, set @code(*workspace-actions*) to @code(nil). +Restore functions to the list with @code(add-action-to-workspace). + +@subsection(Utility Functions) +This chapter concludes with details of various utility functions for score +manipulation. + +@begin(fndefs) +@codef[patternp(@pragma(defn)@index(patternp)@i(expression))]@\Test if @i(expression) is +an Xmusic pattern. + +@codef[params-transpose(@pragma(defn)@index(params-transpose)@i(params), @i(keyword), + @i(amount))]@\Add a transposition amount to a score event parameter. The +@i(params) +parameter is a list of keyword/value pairs (not preceded by a function name). +The @i(keyword) is the keyword of the value to be altered, and @i(amount) +is a number to be added to the value. If no matching keyword is present +in @i(params), then @i(params) is returned. Otherwise, a new parameter +list is constructed and returned. The original @i(params) is not changed. + +@codef[params-scale(@pragma(defn)@index(params-scale)@i(params), @i(keyword), + @i(amount))]@\Scale a score event parameter by some factor. This is like + @code(params-transpose), only using multiplication. The @i(params) +list is a list of +keyword/value pairs, @i(keyword) is the parameter keyword, +and @i(amount) is the scale factor. + +@codef[interpolate(@pragma(defn)@index(interpolate)@index(linear interpolation)@i(x), @i(x1), @i(y1), @i(x2), @i(y2))]@\Linearly interpolate (or extrapolate) + between points +(@i(x1), @i(y1)) and (@i(x2), @i(y2)) to compute the y value + corresponding to @i(x). + +@codef[intersection(@pragma(defn)@index(intersection)@index(set intersection)@i(a), + @i(b))]@\Compute the set intersection of lists @i(a) and @i(b). + +@codef[union(@pragma(defn)@index(union)@index(set union)@i(a), @i(b))]@\Compute +the set union of lists @i(a) and @i(b). + +@codef[set-difference(@index(difference)@pragma(defn)@index(set-difference)@i(a), + @i(b))]@\Compute the set of all elements that are in @i(a) but not in @i(b). + +@codef[subsetp(@pragma(defn)@index(subsetp)@index(subset)@i(a), @i(b))]@\Returns true iff +@i(a) is a subset of @i(b), that is, each element of @i(a) is a member +of @i(b). +@end(fndefs) + +@chapter(Nyquist Libraries) +@index(libraries) +Nyquist is always growing with new functions. Functions that are most fundamental +are added to the core language. These functions are automatically loaded when you +start Nyquist, and they are documented in the preceding chapters. Other functions seem +less central and are implemented as lisp files that you can load. These are called +library functions, and they are described here. + +To use a library function, you +must first load the library, e.g. @code[(load "pianosyn")] loads the piano synthesis +library. The libraries are all located in the @code(lib) directory, and you +should therefore include this directory on your @code(XLISPPATH) variable. (See +Section @ref(install-sec).) Each library is documented in one of the following +sections. When you load the library described by the section, all functions +documented in that section become available. + +@section(Piano Synthesizer) +The piano synthesizer (library name is @code(pianosyn.lsp)) generates +realistic piano tones using a multiple wavetable implementation by Zheng (Geoffrey) +Hua and Jim Beauchamp, University of Illinois. Please see the notice about +acknowledgements that prints when you load the file. Further informations and +example code can be found in +@code(demos/piano.htm)@index(demos, piano)@index(piano synthesizer tutorial). +There are several useful functions in this library: +@begin(fndefs) +@codef[piano-note(@pragma(defn)@index(piano-note)@index(piano synthesizer)@i(duration), @i(step), + @i(dynamic))]@\Synthesizes a piano tone. @i(Duration) is the duration to the point of +key release, after which there is a rapid decay. @i(Step) is the pitch in half +steps, and @i(dynamic) is approximately equivalent to a MIDI key velocity +parameter. Use a value near 100 for a loud sound and near 10 for a soft sound. + +@codef[piano-note-2(@pragma(defn)@index(piano-note-2)@i(step), @i(dynamic))]@\Similar to @code(piano-note) except the duration is nominally 1.0. + +@codef[piano-midi(@pragma(defn)@index(piano-midi)@i(midi-file-name))]@\Use the piano synthesizer +to play a MIDI file. The file name (a string) is given by @i(midi-file-name). + +@codef[piano-midi2file(@pragma(defn)@index(piano-midi2file)@i(midi-file-name), +@i(sound-file-name))]@\Use the piano synthesizer to play a MIDI file. The MIDI file +is given by @i(midi-file-name) and the (monophonic) result is written to the file +named @i(sound-file-name). +@end(fndefs) + +@section(Dymanics Compression) +To use these functions, load the file @code(compress.lsp). This library +implements a compressor originally intended for noisy speech audio, but +usable in a variety of situations. +There are actually two compressors that can be used in +series. The first, @code(compress), is +a fairly standard one: it detects signal level with an RMS +detector and uses table-lookup to determine how much gain +to place on the original signal at that point. One bit of +cleverness here is that the RMS envelope is ``followed'' or +enveloped using @code(snd-follow), which does look-ahead to anticipate +peaks before they happen. + +The other interesting feature is @code(compress-map), which builds +a map in terms of compression and expansion. For speech, the recommended +procedure is to figure out the noise floor on the signal you are compressing +(for example, look at the signal where the speaker is not talking). +Use a compression map that leaves the noise alone and boosts +signals that are well above the noise floor. Alas, the @code(compress-map) +function is not written in these terms, so some head-scratching is +involved, but the results are quite good. + +The second compressor is called @code(agc), and it implements automatic gain +control that keeps peaks at or below 1.0. By combining @code(compress) and +@code(agc), you can process poorly recorded speech for playback on low-quality +speakers in noisy environments. The @code(compress) function modulates the +short-term gain to to minimize the total dynamic range, keeping the speech at +a generally loud level, and the @code(agc) function rides the long-term gain +to set the overall level without clipping. + +@begin(fndefs) +@codef{compress-map(@pragma(defn)@index(compress-map)@i(compress-ratio), +@i(compress-threshold), +@i(expand-ratio), @i(expand-ratio)[ ,limit: @i(limit)] [, transition: +@i(transition)])}@\Construct +a map for the compress function. The map consists of two parts: a compression +part and an expansion part. +The intended use is to compress everything above compress-threshold by +compress-ratio, and to downward expand everything below expand-ratio +by expand-ratio. Thresholds are in dB and ratios are dB-per-dB. +0dB corresponds to a peak amplitude of 1.0 or rms amplitude of 0.7 +If the input goes above 0dB, the output can optionally be limited +by setting @code(:limit) (a keyword parameter) to @code(T). +This effectively changes +the compression ratio to infinity at 0dB. If @code(:limit) is @code(nil) +(the default), then the compression-ratio continues to apply above 0dB. + +Another keyword parameter, @code(:transition), sets the amount below the +thresholds (in dB) that a smooth transition starts. The default is 0, +meaning that there is no smooth transition. The smooth transition is a +2nd-order polynomial that matches the slopes of the straight-line compression +curve and interpolates between them. + +It is assumed that expand-threshold <= compress-threshold <= 0 +The gain is unity at 0dB so if compression-ratio > 1, then gain +will be greater than unity below 0dB. + +The result returned by this function is a sound for use in the @code(shape) +function. The sound maps input +dB to gain. Time 1.0 corresponds to 0dB, time 0.0 corresponds to +-100 dB, and time 2.0 corresponds to +100dB, so this is a +100hz ``sample rate'' sound. The sound gives gain in dB. + +@codef[db-average(@pragma(defn)@index(db-average)@i(input))]@\Compute the average amplitude +of @i(input) in dB. + +@codef{compress(@pragma(defn)@index(compress)@i(input), @i(map), @i(rise-time), @i(fall-time), +[@i(lookahead)])}@\Compress +@i(input) using @i(map), a compression curve +probably generated by @code(compress-map) (see above). Adjustments in gain have +the given @i(rise-time) and @i(fall-time). Lookahead tells how far ahead to look +at the signal, and is @i(rise-time) by default. + +@codef{agc(@index(automatic gain control)@pragma(defn)@index(agc)@index(gain)@i(input), +@i(range), @i(rise-time), @i(fall-time)[ ,@i(lookahead)])}@\An automatic +gain control applied to @i(input). The maximum gain in dB is @i(range). Peaks +are attenuated to 1.0, and gain is controlled with the given @i(rise-time) and +@i(fall-time). The look-ahead time default is @i(rise-time). +@end(fndefs) + +@section(Clipping Softener) +This library, in @code(soften.lsp), was written to improve the quality of +poorly recorded speech. In recordings of speech, extreme clipping generates +harsh high frequency noise. This can sound particulary bad on small speakers +that will emphasize high frequencies. This problem can be ameliorated by +low-pass filtering regions where clipping occurs. The effect is to dull the +harsh clipping. Intelligibility is not affected by much, and the result can +be much more pleasant on the ears. Clipping is detected simply by looking for +large signal values. Assuming 8-bit recording, this level is set to 126/127. + +The function works by cross-fading between the normal signal and a filtered +signal as opposed to changing filter coefficients. + +@begin(fndefs) +@codef[soften-clipping(@pragma(defn)@index(soften-clipping)@index(clipping repair)@i(snd), +@i(cutoff))]@\Filter the loud regions of a signal where clipping is likely +to have generated additional high frequencies. The input signal is @i(snd) +and @i(cutoff) is the filter cutoff frequency +(4 kHz is recommended for speech). +@end(fndefs) + +@section(Graphical Equalizer) +There's nothing really ``graphical'' about this library (@code(grapheq.lsp)), but +this is a common term for multi-band equalizers. This implementation uses +Nyquist's @code(eq-band) function to split the incoming signal into different +frequency bands. Bands are spaced geometrically, e.g. each band could be one +octave, meaning that each successive band has twice the bandwidth. An interesting +possibility is using computed control functions to make the equalization change +over time. + +@begin(fndefs) +@codef[nband-range(@pragma(defn)@index(nband-range)@index(graphical equalizer)@index(equalization)@i(input), @i(gains), @i(lowf), @i(highf))]@\A graphical equalizer applied to +@i(input) (a @code(SOUND)). The gain controls and number of bands is given by @i(gains), an +ARRAY of @code(SOUND)s (in other words, a Nyquist multichannel @code(SOUND)). Any sound in the +array may be replaced by a @code(FLONUM). The bands are +geometrically equally spaced from the lowest frequency @i(lowf) to the +highest frequency @i(highf) (both are @code(FLONUM)s). + +@codef[nband(@pragma(defn)@index(nband)@i(input), @i(gains))]@\A graphical equalizer, identical +to @code(nband-range) with a range of 20 to 20,000 Hz. +@end(fndefs) + +@section(Sound Reversal) +The @code(reverse.lsp) library implements functions to play sounds in reverse. + +@begin(fndefs) +@codef[s-reverse(@index(reverse, sound)@pragma(defn)@index(s-reverse)@index(backward)@index(play in reverse)@i(snd))]@\Reverses @i(snd) (a @code(SOUND)). Sound must be shorter +than @code(*max-reverse-samples*), which is currently initialized to +25 million samples. Reversal allocates about 4 bytes per sample. This function +uses XLISP in the inner sample loop, so do not be surprised if it calls the +garbage collector a lot and runs slowly. The result starts at the starting +time given by the current environment (not necessarily the starting time +of @i(snd)). If @i(snd) has multiple channels, a multiple channel, +reversed sound is returned. + +@codef{s-read-reverse(@index(read samples in reverse)@pragma(defn)@index(s-read-reverse)@i(filename)[ ,time-offset: @i(offset)] [, srate: @i(sr)] [, dur: @i(dur)] [, nchans: @i(chans)] [, format: @i(format)] [, mode: @i(mode)] [, bits: @i(n)] [, swap: @i(flag)])}@\This function is identical to @code(s-read) (see @ref(s-read-sec)), except it reads the indicated samples in reverse. Like +@code(s-reverse) (see above), it uses XLISP in the inner loop, so it is slow. +Unlike @code(s-reverse), @code(s-read-reverse) uses a fixed amount of +memory that is independent of how many samples are computed. Multiple channels +are handled. +@end(fndefs) + +@section(Time Delay Functions) +The @code(time-delay-fns.lsp) library implements chorus, phaser, and flange effects. + +@begin(fndefs) +@codef[phaser(@pragma(defn)@index(phaser)@index(effects, phaser)@i(snd))]@\A phaser effect +applied to @i(snd) (a @code(SOUND)). There are no parameters, +but feel free to modify the source code of this one-liner. + +@codef[flange(@pragma(defn)@index(flange)@index(flange effect)@index(effect, flange)@i(snd))]@\A flange effect +applied to @i(snd). To vary the rate and other parameters, see the source code. + +@codef[stereo-chorus(@index(chorus)@pragma(defn)@index(stereo-chorus)@i(snd))]@\A chorus effect applied to @i(snd), +a @code(SOUND) (monophonic). The output is a stereo sound. All parameters are built-in, +but see the simple source code to make modifications. + +@codef[chorus(@pragma(defn)@index(chorus)@index(effect, chorus)@i(snd), @i(maxdepth), @i(depth), @i(rate), +@i(saturation))]@\A chorus effect applied to @i(snd). All parameters may be arrays +as usual. The @i(maxdepth) is a @code(FLONUM) giving twice the maximum value of @i(depth), +which may be a @code(FLONUM) or a @code(SOUND). The chorus is implemented as a variable delay +modulated by a sinusoid running at @i(rate) Hz (a @code(FLONUM)). The sinusoid is +scaled by @i(depth) and offset by @i(maxdepth)/2. The delayed signal is mixed +with the original, and @i(saturation) gives the fraction of the delayed signal +(from 0 to 1) in the mix. A reasonable choice of parameter values is +@i(maxdepth) = 0.05, @i(depth) = 0.025, @i(rate) = 0.5, and @i(saturation) = 0.5. +@end(fndefs) + +@section(Multiple Band Effects) +@index(multiple band effects)@index(bandfx.lsp) +The @code(bandfx.lsp) library implements several effects based on multiple +frequency bands. The idea is to separate a signal into different frequency +bands, apply a slightly different effect to each band, and sum the effected +bands back together to form the result. This file includes its own set of +examples. After loading the file, try @code[f2()], @code[f3()], @code[f4()], +and @code[f5()] to hear them. + +There is much room for expansion and experimentation with this library. Other +effects might include distortion in certain bands (for example, there are +commercial effects that add distortion to low frequencies to enhance the sound +of the bass), separating bands into different channels for stereo or multi-channel +effects, adding frequency-dependent reverb, and performing dynamic compression, +limiting, or noise gate functions on each band. There are also opportunities for +cross-synthesis: using the content of bands extracted from one signal to modify +the bands of another. The simplest of these would be to apply amplitude envelopes +of one sound to another. Please contact us (dannenberg@@cs.cmu.edu) if you +are interested in working on this library. + +@begin(fndefs) +@codef[apply-banded-delay( @index(banded delay)@pragma(defn)@index(apply-banded-delay)@i(s), @i(lowp), @i(highp), @i(num-bands), @i(lowd), @i(highd), @i(fb), @i(wet))]@\Separates +input @code(SOUND) @i(s) into @code(FIXNUM) @i(num-bands) bands from a low frequency +of @i(lowp) to a high frequency of @i(highp) (these are @code(FLONUMS) that specify +steps, not Hz), and applies a delay to each band. The delay for the lowest band is +given by the @code(FLONUM) @i(lowd) (in seconds) and the delay for the highest band +is given by the @code(FLONUM) @i(highd). The delays for other bands are linearly +interpolated between these values. Each delay has feedback gain controlled by +@code(FLONUM) @i(fb). The delayed bands are scaled by @code(FLONUM) @i(wet), and +the original sound is scaled by 1 - @i(wet). All are summed to form the result, +a @code(SOUND). + +@codef[apply-banded-bass-boost(@index(banded bass boost)@pragma(defn)@index(apply-banded-bass-boost)@i(s), @i(lowp), @i(highp), @i(num-bands), @i(num-boost), @i(gain))]@\Applies a boost to +low frequencies. Separates +input @code(SOUND) @i(s) into @code(FIXNUM) @i(num-bands) bands from a low frequency +of @i(lowp) to a high frequency of @i(highp) (these are @code(FLONUMS) that specify +steps, not Hz), and scales the lowest @i(num-boost) (a @code(FIXNUM)) bands by @i(gain), +a @code(FLONUM). The bands are summed to form the result, a @code(SOUND). + +@codef[apply-banded-treble-boost(@index(banded treble boost)@pragma(defn)@index(apply-banded-treble-boost)@i(s), @i(lowp), @i(highp), @i(num-bands), @i(num-boost), @i(gain))]@\Applies a boost to +high frequencies. Separates +input @code(SOUND) @i(s) into @code(FIXNUM) @i(num-bands) bands from a low frequency +of @i(lowp) to a high frequency of @i(highp) (these are @code(FLONUMS) that specify +steps, not Hz), and scales the highest @i(num-boost) (a @code(FIXNUM)) bands by @i(gain), +a @code(FLONUM). The bands are summed to form the result, a @code(SOUND). +@end(fndefs) + +@section(Granular Synthesis) +Some granular synthesis functions are implemented in the @code(gran.lsp) library +file. There are many variations and control schemes one could adopt for granular +synthesis, so it is impossible to create a single universal granular synthesis +function. One of the advantages of Nyquist is the integration of control and +synthesis functions, and users are encouraged to build their own granular synthesis +functions incorporating their own control schemes. The @code(gran.lsp) file +includes many comments and is intended to be a useful starting point. Another +possibility is to construct a score with an event for each grain. Estimate a +few hundred bytes per score event (obviously, size depends on the number of +parameters) and avoid using all of your computer's memory. + +@begin(fndefs) +@codef{sf-granulate(@index(granular synthesis)@pragma(defn)@index(sf-granulate)@i(filename), @i(grain-dur), @i(grain-dev), @i(ioi), @i(ioi-dev), @i(pitch-dev), +[@i(file-start)] [, @i(file-end)])}@\Granular synthesis using a sound file +named @i(filename) as the source for grains. Grains are extracted from +a sound file named by @i(filename) by stepping through the file in equal +increments. Each grain duration is the +sum of @i(grain-dur) and a random number from 0 to @i(grain-dev). Grains are +then multiplied by a raised cosine smoothing window and resampled at a ratio +between 1.0 and @i(pitch-dev). If @i(pitch-dev) is greater than one, grains are +stretched and the pitch (if any) goes down. If @i(pitch-dev) is less than one, +grains are shortened and the pitch goes up. Grains are then output +with an +inter-onset interval between successive grains (which may overlap) +determined by the sum of +@i(ioi) and a random number from 0 to @i(ioi-dev). +The duration of the resulting sound is determined by +the stretch factor (not by the sound file). The number of grains is +the total sound duration (determined by the stretch factor) +divided by the mean inter-onset interval, +which is @i(ioi) + @i(ioi-dev) * 0.5. +The grains are taken from equally-spaced starting points in @i(filename), +and depending on grain size and number, the grains may or may not overlap. +The output duration will simply be the sum of the inter-onset intervals +and the duration of the last grain. If @i(ioi-dev) is non-zero, the +output duration will vary, but the expected value of the duration is +the stretch factor. +To achieve a rich granular synthesis effect, it is often a good idea to +sum four or more copies of @code(sf-granulate) together. (See the @code(gran-test) +function in @code(gran.lsp).) +@end(fndefs) + +@section(MIDI Utilities) +The @code(midishow.lsp) library has functions that can print the contents fo MIDI +files. This intended as a debugging aid. + +@begin(fndefs) +@codef[midi-show-file(@pragma(defn)@index(midi-show-file)@index(print midi file)@index(show midi file)@i(file-name))]@\Print the contents of a MIDI file to the console. + +@codef{midi-show(@pragma(defn)@index(midi-show)@i(the-seq)[ ,@i(out-file)])}@\Print the +contents of the sequence @i(the-seq) to the file @i(out-file) (whose default value +is the console.) +@end(fndefs) + +@section(Reverberation) +The @code(reverb.lsp) library implements artificial reverberation. + +@begin(fndefs) +@codef[reverb(@pragma(defn)@index(reverb)@index(effect, reverberation)@i(snd), +@i(time))]@\Artificial reverberation applied to @i(snd) with a decay time of +@i(time). +@end(fndefs) + +@section(DTMF Encoding) +@index(dtmf)@index(touch tone) +The @code(dtmf.lsp) library implements DTMF encoding. DTMF is the +``touch tone'' code used by telephones. + +@begin(fndefs) +@codef[dtmf-tone(@pragma(defn)@index(dtmf-tone)@i(key), @i(len), @i(space))]@\Generate a +single DTMF tone. The @i(key) parameter is either a digit (a @code(FIXNUM) +from 0 through 9) or the atom @code(STAR) or @code(POUND). The duration of +the done is given by @i(len) (a @code(FLONUM)) and the tone is followed by +silence of duration @i(space) (a @code(FLONUM)). + +@codef[speed-dial(@pragma(defn)@index(speed-dial)@i(thelist))]@\Generates a sequence +of DTMF tones using the keys in @i(thelist) (a @code(LIST) of keys as +described above under @code(dtmf-tone)). The duration of each tone is 0.2 +seconds, and the space between tones is 0.1 second. Use @code(stretch) to +change the ``dialing'' speed. +@end(fndefs) + +@section[Dolby Surround(R), Stereo and Spatialization Effects] +@index(spatialization)@index(stereo)@index(pan)@index(Dolby Surround) + +The @code(spatial.lsp) library implements various functions for stereo +manipulation and spatialization. It also includes some functions for +Dolby Pro-Logic panning, which encodes left, right, center, and surround +channels into stereo. The stereo signal can then be played through +a Dolby decoder to drive a surround speaker array. This library has +a somewhat simplified encoder, so you should certainly test the +output. Consider using a high-end encoder for critical work. There +are a number of functions in @code(spatial.lsp) for testing. See the +source code for comments about these. + +@begin(fndefs) +@codef[stereoize(@pragma(defn)@index(stereoize)@index(mono to stereo)@index(effect, stereo)@i(snd))]@\Convert a mono sound, @i(snd), to stereo. Four bands of +equalization and some delay are used to create a stereo effect. + +@codef[widen(@pragma(defn)@index(widen)@index(effect, widen)@i(snd), @i(amt))]@\Artificially +widen the stereo field in @i(snd), a two-channel sound. The amount of widening +is @i(amt), which varies from 0 (@i(snd) is unchanged) to 1 (maximum widening). +The @i(amt) can be a @code(SOUND) or a number. + +@codef[span(@index(stereo pan)@index(pan, stereo)@index(effect, stereo pan)@pragma(defn)@index(span)@i(snd), @i(amt))]@\Pan the virtual center channel of a stereo sound, @i(snd), +by @i(amt), where 0 pans all the way to the left, while 1 pans all the way +to the right. The @i(amt) can be a @code(SOUND) or a number. + +@codef[swapchannels(@pragma(defn)@index(swapchannels)@index(swap channels)@index(effect, swap channels)@i(snd))]@\Swap left and right channels in @i(snd), a stereo sound. + +@codef[prologic(@pragma(defn)@index(prologic)@index(Dolby Pro-Logic)@index(Surround Sound)@i(l), @i(c), +@i(r), @i(s))]@\Encode four monaural @code(SOUND)s representing the front-left, +front-center, front-right, and rear channels, respectively. +The return value is a stereo sound, which is a Dolby-encoded mix of the +four input sounds. + +@codef[pl-left(@pragma(defn)@index(pl-left)@i(snd))]@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the front left channel. + +@codef[pl-center(@pragma(defn)@index(pl-center)@i(snd))]@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the front center channel. + +@codef[pl-right(@pragma(defn)@index(pl-right)@i(snd))]@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the front right channel. + +@codef[pl-rear(@pragma(defn)@index(pl-rear)@i(snd))]@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the rear, or surround, channel. + +@codef[pl-pan2d(@pragma(defn)@index(pl-pan2d)@i(snd), @i(x), @i(y))]@\Comparable to Nyquist's +existing pan function, @code(pl-pan2d) provides not only left-to-right +panning, but front-to-back panning as well. The function +accepts three parameters: @i(snd) is the (monophonic) input @code(SOUND), +@i(x) is a left-to-right position, and @i(y) is a front-to-back position. +Both position parameters may be numbers or @code(SOUND)s. An @i(x) value +of 0 means left, and 1 means right. Intermediate values map linearly +between these extremes. Similarly, a @i(y) value of 0 causes the sound +to play entirely through the front speakers(s), while 1 causes it to play +entirely through the rear. Intermediate values map linearly. +Note that, although there are usually two rear speakers in Pro-Logic systems, +they are both driven by the same signal. Therefore any sound that is +panned totally to the rear will be played over both rear speakers. For +example, it is not possible to play a sound exclusively through the +rear left speaker. + +@codef[pl-position(@pragma(defn)@index(pl-position)@i(snd), @i(x), @i(y), @i(config))]@\The +position function builds upon speaker panning to allow more abstract +placement of sounds. Like @code(pl-pan2d), it accepts a (monaural) input +sound as well as left-to-right (@i(x)) and front-to-back (@i(y)) coordinates, +which may be @code(FLONUM)s or @code(SOUND)s. A fourth parameter @i(config) +specifies the distance from listeners to the speakers (in meters). Current +settings assume this to be constant for all speakers, but this assumption +can be changed easily (see comments in the code for more detail). +There are several important differences between @code(pl-position) and +@code(pl-pan2d). First, @code(pl-position) uses a Cartesian coordinate +system that allows x and y coordinates outside of the +range (0, 1). This model assumes a listener position of (0,0). Each speaker +has a predefined position as well. The input sound's position, +relative to the listener, is given by the vector (@i(x),@i(y)). + +@codef[pl-doppler(@pragma(defn)@index(pl-doppler)@index(Doppler effect)@i(snd), +@i(r))]@\Pitch-shift moving sounds according to the equation: @i(fr) = +@i(f0)((@i(c)+@i(vr))/@i(c)), where @i(fr) is the output frequency, +@i(f0) is the emitted (source) +frequency, @i(c) is the speed of sound (assumed to be 344.31 m/s), and +@i(vr) is the speed at which the emitter approaches the receiver. (@i(vr) +is the first derivative of parameter @i(r), the distance from the listener +in meters. + +@end(fndefs) + +@section(Drum Machine) + +The drum machine software in @code(demos/plight) deserves further explanation. +to use the software, load the code by evaluating: +@begin(example) +load "../demos/plight/drum.lsp" +exec load-props-file(strcat(*plight-drum-path*, + "beats.props")) +exec create-drum-patches() +exec create-patterns() +@end(example) + +Drum sounds and patterns are specified in the @code(beats.props) file (or +whatever name you give to @code(load-props-file)). This file +contains two types of specifications. First, there are sound file specifications. +Sound files are located by a line of the form: +@begin(example) +set sound-directory = "kit/" +@end(example) +This gives the name of the sound file directory, relative to the + @code(beats.props) file. Then, for each sound file, there should be a line of +the form: +@begin(example) +track.2.5 = big-tom-5.wav +@end(example) +This says that on track 2, a velocity value of 5 means to play the sound file + @code(big-tom-5.wav). (Tracks and velocity values are described below.) +The @code(beats.props) file contains specifications for all the sound files +in @code(demos/plight/kit) using 8 tracks. If you make your own specifications +file, tracks should be numbered consecutively from 1, and velocities should be +in the range of 1 to 9. + +The second set of specifications is of beat patterns. A beat pattern is given +by a line in the following form: +@begin(example) +beats.5 = 2--32--43-4-5--- +@end(example) +The number after @code(beats) is just a pattern number. Each pattern +is given a unique number. After the equal sign, the digits and dashes are +velocity values where a dash means ``no sound.'' Beat patterns should be +numbered consecutively from 1. + +Once data is loaded, there are several functions to access drum patterns and +create drum sounds (described below). The @code(demos/plight/drums.lsp) file +contains an example function @code(plight-drum-example) to play some drums. +There is also the file @code(demos/plight/beats.props) to serve as an +example of how to specify sound files and beat patterns. + +@begin(fndefs) +@codef{drum(@pragma(defn)@index(drum)@i(tracknum), @i(patternnum), @i(bpm))}@\Create +a sound by playing drums sounds associated with track @i(tracknum) (a +FIXNUM) using pattern @i(patternnum). The tempo is given by @i(bpm) in +beats per minute. Normally patterns are a sequence of sixteenth notes, so +the tempo is in @i(sixteenth notes per minute). For example, +if @i(patternnum) is 10, +then use the pattern specified for @code(beats.10). If the third character +of this pattern is 3 and @i(tracknum) is 5, then on the third beat, play +the soundfile assigned to @code(track.5.3). This function returns a @code(SOUND). + +@codef{drum-loop(@pragma(defn)@index(drum-loop)@i(snd), @i(duration), @i(numtimes))}@\Repeat the sound given by @i(snd) @i(numtimes) times. The repetitions occur at a time offset of @i(duration), regardless of the actual duration of @i(snd). A @code(SOUND) is returned. + +@codef{length-of-beat(@pragma(defn)@index(length-of-beat)@i(bpm))}@\Given a tempo of +@i(bpm), return the duration of the beat in seconds. Note that this software +has no real notion of beat. A ``beat'' is just the duration of each character +in the beat pattern strings. This function returns a @code(FLONUM). +@end(fndefs) + + + +@section(Minimoog-inspired Synthesis) +@index(Moog)@index(Minimoog)@index(analog synthesizer) + +The @code(moog.lsp) library gives the Nyquist user easy access to ``classic'' +synthesizer sounds through an emulation of the Minimoog Synthesizer. +Unlike modular Moogs that were very large, the Minimoog was the first +successful and commonly used portable synthesizer. The trademark filter attack +was unique and easily recognizable. The goal of this Nyquist instrument is not +only to provide the user with default sounds, but also to give control over +many of the ``knobs'' found on the Minimoog. In this implementation, these +parameters are controlled using keywords. The input to the @code(moog) +instrument is a user-defined sequence of notes, durations, and articulations +that simulate notes played on a keyboard. These are translated into +control voltages that drive multiple oscillators, similar to the Voltage +Controlled Oscillator or VCO found in the original analog Moog. + +The basic functionality of the Minimoog has been implemented, including the +often-used "glide". The glide feature essentially low-pass filters the control +voltage sequence in order to create sweeps between notes. +Figure @ref(moog-fig) is a simplified schematic of the data flow in the Moog. +The control lines have been omitted. + +@begin(figure) +@center(@graphic((height = 2.514 in, width = 4.65 in, magnify = 0.3, + postscript = "moog-fig.ps")) +@html(

) +@fillcaption(System diagram for Minimoog emulator.) +@tag(moog-fig) +@end(figure) + +The most recognizable feature of the Minimoog is its resonant filter, a +Four-Pole Ladder Filter invented by Robert Moog. It is simply implemented +in a circuit with four transistors and provides an outstanding 24 dB/octave +rolloff. It is modeled here using the built-in Nyquist resonant filter. +One of the Moog filter features is a constant Q, or center frequency to +bandwidth ratio. This is implemented and the user can control the Q. + +The user can control many parameters using keywords. Their default values, +acceptable ranges, and descriptions are shown below. The defaults were +obtained by experimenting with the official Minimoog software synthesizer +by Arturia. + +@subsection(Oscillator Parameters) +@code(range-osc1) (2)@* +@code(range-osc2) (1)@* +@code(range-osc3) (3)@* +These parameters control the octave of each oscillator. A value of 1 +corresponds to the octave indicated by the input note. A value of 3 +is two octaves above the fundamental. The allowable range is 1 to 7. + +@code(detun2) (-.035861)@* +@code(detun3) (.0768)@* +Detuning of two oscillators adds depth to the sound. A value of 1 corresponds +to an increase of a single semitone and a -1 corresponds to a decrease +in a semitone. The range is -1 to 1. + +@code(shape-osc1) (@code(*saw-table*))@* +@code(shape-osc2) (@code(*saw-table*))@* +@code(shape-osc3) (@code(*saw-table*))@* +Oscilators can use any wave shape. The default sawtooth waveform is +a built-in Nyquist variable. Other waveforms can be defined by the user. + +@code(volume-osc1) (1)@* +@code(volume-osc2) (1)@* +@code(volume-osc3) (1)@* +These parameters control the relative volume of each oscillator. The range +is any @code(FLONUM) greater than or equal to zero. + +@subsection(Noise Parameters) +@code(noiselevel) (.05)@* +This parameter controls the relative volume of the noise source. The range +is any @code(FLONUM) greater than or equal to zero. + +@subsection(Filter Parameters) +@code(filter-cutoff) (768)@* +The cutoff frequency of the filter in given in Hz. The range is zero +to 20,000 Hz. + + +@code(Q) (2)@* +Q is the ratio of center frequency to bandwidth. It is held constant by +making the bandwidth a function of frequency. The range is any +@code(FLONUM) greater than zero. + +@code(contour) (.65)@* +Contour controls the range of the transient frequency sweep from a high +to low cutoff frequency when a note is played. The high frequency is +proportional to contour. A contour of 0 removes this sweep. The range +is 0 to 1. + +@code(filter-attack) (.0001)@* +Filter attack controls the attack time of the filter, i.e. the time to +reach the high cutoff frequency. The range is any @code(FLONUM) greater +than zero (seconds). + +@code(filter-decay) (.5)@* +Filter decay controls the decay time of the filter, i.e. the time of the +sweep from the high to low cutoff frequency. The range is +any @code(FLONUM) greater than zero (seconds). + +@code(filter-sustain) (.8)@* +Filter sustain controls the percentage of the filter cutoff frequency that +the filter settles on following the sweep. The range is 0 to 1. + +@subsection(Amplitude Parameters) +@code(amp-attack) (.01)@* +This parameter controls the amplitude envelope attack time, i.e. the time to +reach maximum amplitude. The range is +any @code(FLONUM) greater than zero (seconds). + +@code(amp-decay) (1)@* +This parameter controls the amplitude envelope decay time, i.e. the time +between the maximum and sustain volumes. The range is +any @code(FLONUM) greater than zero (seconds). + +@code(amp-sustain) (1)@* +This parameter controls the amplitude envelope sustain volume, a fraction +of the maximum. The range is 0 to 1. + +@code(amp-release) (0)@* +This parameter controls the amplitude envelope release time, i.e. the time +it takes between the sustain volume and 0 once the note ends. +The duration controls the overall length of the sound. The range of @code(amp-release) is any @code(FLONUM) greater than zero (seconds). + +@subsection(Other Parameters) +@code(glide) (0)@* +Glide controls the low-pass filter on the control voltages. This models the +glide knob on a Minimoog. A higher value corresponds to a lower cutoff +frequency and hence a longer "glide" between notes. A value of 0 +corresponds to no glide. The range is zero to 10. + +@subsection(Input Format) +A single note or a series of notes can be input to the Moog instrument +by defining a list with the following format: +@begin(display) +(list (list @i(frequency duration articulation)) ... ) +@end(display) +where @i(frequency) is a @code(FLONUM) in steps, @i(duration) is the duration +of each note in seconds (regardless of the release time of the amplifier), +and @i(articulation) is a percentage of the duration that a sound will be +played, representing the amount of time that a key is pressed. The filter +and amplitude envelopes are only triggered if a note is played when +the articulation of the previous note is less than 1, or a key is not down at +the same time. This Moog instrument is a monophonic instrument, so only +one note can sound at a time. The release section of the amplifier is +triggered when the articulation is less than 1 at the time +(@i(duration) * @i(articulation)). + +@subsection(Sample Code/Sounds) + +@b[Sound 1 (default parameters):] +@begin(display) +@begin(code) +set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99} + {29 .5 .99} {31 2 1}} +play moog(s) +@end(code) +@end(display) + +@b[Sound 2 (articulation, with amplitude release):] +@begin(display) +@begin(code) +set s = {{24 .5 .5} {26 .5 1} {28 .5 .25} {29 .5 1} {31 1 .8}} +play moog(s, amp-release: .2) +@end(code) +@end(display) + +@b[Sound 3 (glide):] +@begin(display) +@begin(code) +set s = {{24 .5 .5} {38 .5 1} {40 .5 .25} + {53 .5 1} {55 2 1} {31 2 .8} {36 2 .8}} +play moog(s, amp-release: .2, glide: .5) +@end(code) +@end(display) + +@b[Sound 4 (keyword parameters):] Filter attack and decay are purposely +longer than notes being played with articulation equal to 1. +@begin(display) +@begin(code) +set s = {{20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1} + {20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1}} +play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*, + filter-attack: 2, filter-decay: 2, + filter-cutoff: 300, contour: .8, glide: .2, Q: 8) +@end(code) +@end(display) + +@b[Sound 5:] This example illustrates the ability to completely define a new +synthesizer with different parameters creating a drastically different +sound. Sine waves are used for wavetables. There is a high value for glide. +@begin(display) +@begin(code) +define function my-moog(freq) + return moog(freq, + range-osc1: 3, range-osc2: 2, range-osc3: 4, + detun2: -.043155, detun3: .015016, + noiselevel: 0, + filter-cutoff: 400, Q: .1, contour: .0000001, + filter-attack: 0, filter-decay: .01, filter-sustain: 1, + shape-osc1: *sine-table*, shape-osc2: *sine-table*, + shape-osc3: *sine-table*, volume-osc1: 1, volume-osc2: 1, + volume-osc3: .1, amp-attack: .1, amp-decay: 0, + amp-sustain: 1, amp-release: .3, glide: 2) + +set s = {{80 .4 .75} {28 .2 1} {70 .5 1} {38 1 .5}} +play my-moog(s) +@end(code) +@end(display) + +@b[Sound 6:] This example has another variation on the default + parameters. +@begin(display) +@begin(code) +set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99} + {29 .5 .99} {31 2 1}} +play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*, + filter-attack: .5, contour: .5) +@end(code) +@end(display) + +@pragma(doinclude) +@include(nymanimpl.mss) + +@appendix(Open Sound Control and Nyquist)@index(Open Sound Control) +@label(osc-app) +Open Sound Control (OSC) is a simple protocol for communicating music control parameters between software applications and across networks. For more information, see +@html[]@code(http://www.cnmat.berkeley.edu/OpenSoundControl/)@html[]. The Nyquist implementation of Open Sound Control is simple: an array of floats can be set by OSC messages and read by Nyquist functions. That is about all there is to it. + +Note: Open Sound Control must be enabled by calling @code[osc-enable(t)]. If this fails under Windows, see the installation instructions regarding @code(SystemRoot). + +To control something in (near) real-time, you need to access a slider value as if it a signal, or more properly, a Nyquist @code(SOUND) type. The function @code(snd-slider), described in Section @ref(snd-slider-sec), takes a slider number and returns a @code(SOUND) type representing the current value of the slider. To fully understand this function, you need to know something about how Nyquist is actually computing sounds. + +Sounds are normally computed on demand. So the result returned by @code(snd-slider) does not immediately compute any samples. Samples are only computed when something tries to use this signal. At that time, the slider value is read. Normally, if the slider is used to control a sound, you will hear changes in the sound pretty soon after the slider value changes. However, one thing that can interfere with this is that @code(SOUND) samples are computed in blocks of about 1000 samples. When the slider value is read, the same value is used to fill a block of 1000 samples, so even if the sample rate is 44,100 Hz, the effective slider sample rate is 44,100/1000, or 44.1 Hz. If you give the slider a very low sample rate, say 1000, then slider value changes will only be noticed by Nyquist approximately once per second. For this reason, you should normally use the audio sample rate (typically 44,100 Hz) for the rate of the @code(snd-slider) output @code(SOUND). (Yes, this is terribly wasteful to represent each slider value with 1000 samples, but Nyquist was not designed for low-latency computation, and this is an expedient work-around.) + +In addition to reading sliders as continually changing @code(SOUND)s, you can get the slider value as a Lisp @code(FLONUM) (a floating point number) using @code(get-slider-value), described in Section @ref(get-slider-value-sec). This might be useful if you are computing a sequence of many notes (or other sound events) and want to apply the current slider value to the whole note or sound event. + +Note that if you store the value returned by @code(snd-slider) in a variable, you will capture the history of the slider changes. This will take a lot of memory, so be careful. + +Suppose you write a simple expression such as @code[(hzosc (mult 1000 (snd-slider 0 ...)))] to control an oscillator frequency with a slider. How long does this sound last? The duration of @code[hzosc] is the duration of the frequency control, so what is the duration of a slider? To avoid infinitely long signals, you must specify a duration as one of the parameters of @code[snd-slider]. + +You might be thinking, what if I just want to tell the slider when to stop? At present, you cannot do that, but in the future there should be a function that stops when its input goes to zero. Then, moving a slider to zero could end the signal (and if you multiplied a complex sound by one of these ending functions, everything in the sound would end and be garbage collected). + +Another thing you might want to do with interactive control is start some sound. The @code(trigger) function computes an instance of a behavior each time an input @code(SOUND) goes from zero to greater-than-zero. This could be used, for example, to create a sequence of notes. + +The @code(snd-slider) function has some parameters that may be unfamiliar. The second parameter, @i(t0), is the starting time of the sound. This should normally be @code[local-to-global(0)], an expression that computes the instantiation time of the current expression. This will often be zero, but if you call @code[snd-slider] from inside a @code(seq) or @code(seq-rep), the starting time may not be zero. + +The @i(srate) parameter is the sample rate to return. This should normally be the audio sample rate you are working with, which is typically @code[*default-sound-srate*]. + +@section(Sending Open Sound Control Messages) +A variety of programs support OSC. The only OSC message interpreted by Nyquist has an address of @code[/slider], and two parameters: an integer slider number and a float value, nominally from 0.0 to 1.0. + +Two small programs are included in the Nyquist distribution for sending OSC messages. (Both can be found in the same directory as the nyquist executable.) The first one, @code[osc-test-client] sends a sequence of messages that just cause slider 0 to ramp slowly up and down. If you run this on a command line, you can use "?" or "h" to get help information. There is an interactive mode that lets you send each OSC message by typing RETURN. + +@section(The ser-to-osc Program) +The second program is @code[ser-to-osc], a program that reads serial input (for example from a PIC-based microcontroller) and sends OSC messages. Run this command-line program from a shell (a terminal window under OS X or Linux; use the CMD program under Windows). You must name the serial input device on the command line, e.g. under OS X, you might run: +@begin(display) +@code(./ser-to-osc /dev/tty.usbserial-0000103D) +@end(display) +(Note that the program name is preceded by ``@code(./)". This tells the shell exactly where to find the executable program in case the current directory is not on the search path for executable programs.) +Under Windows, you might run: +@begin(display) +@code(ser-to-osc com4) +@end(display) +(Note that you do not type ``@code(./)'' in front of a windows program.) + +To use @code(ser-to-osc), you will have to find the serial device. On the Macintosh and Linux, try the following: +@begin(display) +@code(ls /dev/*usb*) +@end(display) +This will list all serial devices with ``usb'' in their names. Probably, one will be a name similar to @code(/dev/tty.usbserial-0000103D). The @code(ser-to-osc) program will echo data that it receives, so you should know if things are working correctly. + +Under Windows, open Control Panel from the Start menu, and open the System control panel. Select the Hardware tab and click the Device Manager button. Look in the device list under Ports (COM & LPT). When you plug in your serial or USB device, you should see a new entry appear, e.g. @code(COM4). This is the device name you need. + +The format for the serial input is: any non-whitespace character(s), a slider number, a slider value, and a newline (control-j or ASCII 0x0A). These fields need to be separated by tabs or spaces. An optional carriage return (control-m or ASCII 0x0D) preceding the ASCII 0x0A is ignored. The slider number should be in decimal, and theh slider value is a decimal number from 0 to 255. This is scaled to the range 0.0 to 1.0 (so an input of 255 translates to 1.0). + +There is a simple test program in @code[demos/osc-test.lsp] you can run to try out control with Open Sound Control. There are two examples in that file. One uses @code(snd-slider) to control the frequency of an oscillator. The other uses @code(get-slider-value) to control the pitch of grains in a granular synthesis process. + + +@appendix(Intgen)@index(Intgen) +@label(intgen-app) +@pragma(doinclude) +@include(../xlisp/intgen.mss) + +@appendix(XLISP: An Object-oriented Lisp) +@label(xlisp-app) +@begin(center) + +@b(Version 2.0) + +February 6, 1988 + +by +@b(David Michael Betz) +127 Taylor Road +Peterborough, NH 03458 + +Copyright (c) 1988, by David Michael Betz +All Rights Reserved +Permission is granted for unrestricted non-commercial use +@end(center) +@newpage +@pragma(doinclude) +@include(../xlisp/xlisp.mss) diff --git a/docsrc/nyquist/nyquistman.mss b/docsrc/nyquist/nyquistman.mss new file mode 100644 index 0000000..566f081 --- /dev/null +++ b/docsrc/nyquist/nyquistman.mss @@ -0,0 +1,8763 @@ +@device(mac52postscript) +@make(manual) +@libraryfile(mathematics10) +@libraryfile(picture) +@libraryfile(multilevelindex) +@style(font timesroman) +@style(fontscale 11) +@commandstring(dash @Y[M]) +@commandstring(subtract @Y[N]) +@commandstring(itemsep @Y[M]) +@Modify(indexenv, above=2 lines, leftmargin 8, columns=3, boxed) +@define(prg=i) +@define(detail=text, size 9, spacing 1.2, indent 0) +@define(code, FaceCode T, size 11) +@comment{codef is used to define a lisp function or variable -- + a processor uses this to extract completion hint info for NyquistIDE.} +@define(codef, FaceCode T, size 11) +@comment{pragma(define) is used to mark a term's point of definition -- + I tried to define(defn=index), but that didn't work in Scribe, + so the approach now is to mark definitions. In s2h, the + define pragma sets a flag that the NEXT index term is a definition. + The s2h.lsp processor uses this to map terms defined within codef + (which go into the completion list) to URLs for the help system.} +@define(smallcode, FaceCode T, size 8, spacing 0.8) @comment(was 10) +@define(rbdisplay = display, group) +@define(fndefs = description, leftmargin 0.5in, indent -0.5in) +@define(fdescription = text, leftmargin +0.5in, indent -0.5in, spread 1) +@define(pdescription = text, leftmargin +0.5in, indent -0.5in, spread 0) +@define(fgroup = text, indent -0.5in, spread 0) +@define(altdef = text, leftmargin +0.0in, indent -0.5in) +@textform(html = []) +@textform(htmltitle = []) +@textform(pragma = []) +@use(bibliography = "../bib/music.bib") +@style(references ClosedAlphabetic) +@counter(dummy-counter) +@modify(FigureCounter,Within=dummy-counter, + Numbered <@@b[Figure@@ @1:@@ @@ ]@@$>, + Referenced "@1",Init 0) +@modify(TableCounter,Within=dummy-counter, + Numbered <@@b[Table@@ @1:@@ @@ ]@@$>, + Referenced "@1",Init 0) +@pageheading(left "", center "@value(page)", right "") +@include(../template/filcap.mss) + +@begin(comment) +@begin(figure) +@blankspace(0.3 inches) @comment(scribe doesn't leave enough space) +@center(@graphic((height = *** in, width = *** in, magnify = ***, + postscript = "***.ps")) +@fillcaption(***) +@tag(***) +@end(figure) +@end(comment) + +@html(Nyquist Reference Manual) +@htmltitle(Nyquist Reference Manual) +@begin(titlepage) +@begin(titlebox) +@blankspace(0.5 inch) +@majorheading(Nyquist Reference Manual) +@b(Version 3.05) +@blankspace(0.3 inch) +@b(Copyright 2011 by Roger B. Dannenberg) +@value(date) +@end(titlebox) +@pragma(startscribe) +@center(Carnegie Mellon University) +@center(School of Computer Science) +@center(Pittsburgh, PA 15213, U.S.A.) +@pragma(endscribe) +@html(
Carnegie Mellon University
+School of Computer Science
+Pittsburgh, PA 15213, U.S.A.
) +@blankspace(1 inch) +@end(titlepage) +@pragma(startscribe) +. +@pragma(endscribe) +@newpage +@pageheading(even, left "Page @Value(Page)", right "@c(Nyquist Manual)") +@pageheading(odd, left "@c[@title(chapter)]", right "Page @Value(page)") +@style(pagenumbers="@i") +@set(page=3) +@Unnumbered(Preface) +This manual is a guide for users of Nyquist, a language for composition and +sound synthesis. Nyquist grew out of a series of research projects, notably +the languages Arctic and Canon. Along with Nyquist, these languages promote a +functional style of programming and incorporate time into the language +semantics. + +Please help by noting any errors@Index(errors), omissions@Index(omissions), +or suggestions@Index(suggestions) you may have. You can send your +suggestions to Dannenberg@@CS.CMU.EDU (internet) via computer mail, or by +campus mail to Roger B. Dannenberg, School of Computer Science, or by +ordinary mail to Roger B. Dannenberg, School of Computer Science, Carnegie +Mellon University, 5000 Forbes Ave., Pittsburgh, PA 15213-3890, USA. + +Nyquist is a successor to Fugue, a language originally implemented by Chris +Fraley, and extended by George Polly and Roger Dannenberg. Peter Velikonja +and Dean Rubine were early users, and they proved the value as well as +discovered some early problems of the system. This led to Nyquist, a +reimplementation of Fugue by Roger Dannenberg with help from Joe Newcomer +and Cliff Mercer. Ning Hu ported Zheng (Geoffrey) Hua and Jim Beauchamp's +piano synthesizer to Nyquist and also built NyqIDE, the Nyquist Integrated +Development Environment for Windows. Dave Mowatt contributed the original +version of NyquistIDE, the cross-platform interactive development environment. +Dominic Mazzoni made a special version of Nyquist that runs +within the Audacity audio editor, giving Nyquist a new interface and +introducing Nyquist to many new users. + +Many others have since contributed to Nyquist. +Chris Tchou and Morgan Green worked on the Windows port. Eli Brandt contributed +a number of filters and other synthesis functions. Pedro J. Morales, +Eduardo Reck Miranda, Ann Lewis, and Erich Neuwirth have all contributed +nyquist examples found in the demos folder of the Nyquist distribution. +Philip Yam ported some +synthesis functions from Perry Cook and Gary Scavone's STK to Nyquist. +Pedro Morales ported many more STK instruments to Nyquist. +Dave Borel wrote the Dolby Pro-Logic encoding library and Adam Hartman wrote +stereo and spatialization effects. Stephen Mangiat wrote the MiniMoog +emulator. Phil Light recorded the drum samples and wrote drum +machine software. The Xmusic library, particularly the pattern specification, +was inspired by Rick Taube's Common Music. The functions for generating +probability distributions were implemented by Andreas Pfenning. + +Starting with Version 3, Nyquist supports a version of SAL, providing +an alternative to Lisp syntax. SAL was designed by Rick Taube, and the +SAL implementation in Nyquist is based on Taube's original implementation +as part of his Common Music system. + +The current NyquistIDE includes contributions from many. Chris Yealy and +Derek D'Souza implemented early versions of the envelope editor. Daren +Makuck and Michael Rivera wrote the original equalizer editor. +Priyanka Raghavan implemented the sound browser. Dmitry Portnoy wrote the +original "UPIC" editor. + + +Many others have made contributions, offered suggestions, and found bugs. +If you were expecting to find your name here, I apologize for the omission, +and please let me know. + +I also wish to acknowledge support from CMU, Yamaha, and IBM for this work. +@newpage +@blankspace(5 inches) +@pragma(startscribe) +. +@pragma(endscribe) +@newpage +@set(page=1) +@style(pagenumbers="@1") + +@chapter(Introduction and Overview) + +Nyquist is a language for sound synthesis and music composition. Unlike score +languages that tend to deal only with events, or signal processing languages +that tend to deal only with signals and synthesis, Nyquist handles both in a +single integrated system. Nyquist is also flexible and easy to use because it +is based on an interactive Lisp interpreter. + +With Nyquist, you can design instruments by combining functions (much as you +would using the orchestra languages of Music V, cmusic, or Csound). You can +call upon these instruments and generate a sound just by typing a simple +expression. You can combine simple expressions into complex ones to create +a whole composition. + +Nyquist runs under Linux, Apple Mac OS X, Microsoft Windows NT, +2000, XP, and Vista, +and it produces sound files or directly generates audio. +Recent versions have also run on AIX, NeXT, SGI, DEC pmax, and Sun Sparc +machines. (Makefiles for many of these are included, but out-of-date). +Let me know if you have problems with +any of these machines. + +To use Nyquist, you should have a basic knowledge of Lisp. An excellent text +by Touretzky is recommended @cite(Touretzky). Appendix @ref(xlisp-app) is +the reference manual for XLISP, of which Nyquist is a superset. Starting with +Version 3, Nyquist supports a variant of SAL, which is also available in +Common Music. Since there are some differences, one should generally call this +implementation ``Nyquist SAL;'' however, in this manual, I will just call it +``SAL.'' SAL offers most of the capabilities of Lisp, but it uses an Algol-like +syntax that may be more familiar to programmers with experience in Java, C, +Basic, etc. + +@label(install-sec) +@section(Installation) +@index(installation)@index(configure nyquist)@index(setup nyquist) +Nyquist is a C++ program intended to run under various operating systems +including Unix, Mac OS X, and Windows. Nyquist is based on Lisp, but it +includes its own Lisp interpreter (a modified version of XLISP), so you +do not need to install some other Lisp to run Nyquist. Other +Lisp systems are not compatible with Nyquist. + +Most Nyquist users run Nyquist under the Nyquist IDE, which is written in Java +and depends on the Java runtime system. Most systems already have Java, but if +you do not, you will need to install it. When you install the Nyquist IDE, +you will automatically get Nyquist and a set of runtime libraries. + +There are generally two ways to install Nyquist: +@begin(itemize) +Get a pre-compiled version of the Nyquist IDE for Windows or Mac OS X. The +Windows version comes packaged in an installer that installs and +configures the Nyquist IDE. The Mac OS X version +unpacks to a complete OS X application. + +Compile from sources. There is one set of sources for Mac, Windows, and Unix. +Instructions for building applications from the sources are provided in +the files @code(sys/win/README.txt), @code(sys/mac/README.txt), and +@code(sys/unix/README.txt). +@end(itemize) + +You can download source code and precompiled versions from the Nyquist project +on SourceForge (@code(http://sourceforge.net/projects/nyquist)). The latest +source code can be obtained via Subversion (svn) using the following: +@begin(example) +svn co https://nyquist.svn.sourceforge.net/svnroot/nyquist/trunk nyquist +@end(example) +or by checking out nyquist using a graphical interface svn client such as +TortoiseSVN for Windows. + +@begin(comment) +@subsection(Unix Installation) +For Unix systems, Nyquist is distributed as a compressed tar file named @code(nyqsrc3@i(nn).zip), +where @i(nn) is the version number (e.g. v3.01 was +in @code(nyqsrc301.zip)). To +install Nyquist, copy @code(nyqsrc3@i(nn).zip) to the +directory on your machine where you would like to install Nyquist, and type: +@begin(example) +gunzip nyqsrc3@i(nn).zip +cd nyquist +ln -s sys/unix/linux/Makefile Makefile +setenv XLISPPATH `pwd`/runtime:`pwd`/lib +make +@end(example) +The first line creates a @code(nyquist) directory and some subdirectories. The +second line (cd) changes directories to the new nyquist directory. The third line makes a link from the top-level directory to the Makefile for your +system. In place of @code(linux) in @code(sys/unix/linux/Makefile), you should +substitute your system type. Current systems are @code(next), @code(pmax), +@code(rs6k), @code(sgi), @code(linux), and @code(sparc). The @code(setenv) +command tells Nyquist where to search for lisp files to be loaded when a file +is not found in the current directory. The @code(runtime) directory should +always be on your @code(XLISPPATH) when you run Nyquist, so you may want to +set @code(XLISPPATH) in your shell startup file, e.g. @code(.cshrc). +Assuming the make completes successfully, you can run Nyquist as follows: +@begin(example) +./ny +@end(example) +When you get the prompt, you may begin typing expressions such as +the ones in the following ``Examples'' section. + +One you establish that Nyquist (ny) is working from the command line, you should +try using NyquistIDE, the Java-based Nyquist development environment. First, +make @code(jny) executable (do this only once when you install Nyquist): +@begin(example) +chmod +x jny +@end(example) +Then try running NyquistIDE by typing: +@begin(example) +./jny +@end(example) +If the NyquistIDE window does not appear, make sure you have Java installed (if not, +you probably already encountered errors when you ran @code(make)). You can also try recompiling the Java files: +@begin(example) +cd jnyqide +javac *.java +cd .. +@end(example) + +@p(Note:) With Linux and the Macintosh OS X, + NyquistIDE defines the environment passed to Nyquist. If you +set @code(XLISPPATH)@index(XLISPPATH)@index(search path) as shown above, it +will be passed along to Nyquist under NyquistIDE. If not, +a default XLISPPATH will have the @code(lib) and @code(runtime) directories only. +This does not apply to Windows because even though the environment is there, +the Windows version of Nyquist reads the @code(XLISPPATH) from the Registry. + +You can also specify the search path by creating the +file @code(nyquist/xlisppath), which should have colon-separated paths +on a single line of text. This file will override the environment +variable @code(XLISPPATH). + +It is good to have @code(USER) in the environment with your user ID. This string +is used to construct some file names. NyquistIDE will look for it in the environment. +You can also specify your user ID using the file @code(nyquist/user), but +if you have a shared installation of Nyquist, this will not be very useful. + +@p(Note:) Nyquist looks for the file @code(init.lsp) in the current +directory. If you look in the @code(init.lsp) in @code(runtime), you +will notice two things. First, @code(init.lsp) loads @code(nyquist.lsp) +from the Nyquist directory, and second, @code(init.lsp) loads @code(system.lsp) +which in turn defines the macro +@code(play). You may have to modify @code(system.lsp) to invoke +the right programs on your machine. + +@subsection(Win32 Installation) +The Win32 version of Nyquist is packaged as a compiled (runtime) system in an + executable installer. A source version is also available (the same source +download is for Win32, Mac OS X, and Linux). The source version is +intended for developers who +want to recompile Nyquist. +The contents of the source archive are extracted to the @code(C:\nyquist) +directory, +but you can put it anywhere you like. You can then open the workspace file, +nyquist.sln, using Microsoft +Visual C++. You can build and run the command line version of Nyquist +from within Visual C++. There is a batch file, @code(comp-ide.bat), for +bulding the Nyquist IDE. This requires the Java SDK from Sun Microsystems. + +The runtime version contain everything you need to run Nyquist, including the executable, +examples, and documentation, packaged as an executable installer program. +After executing the installer, just find Nyquist in your Start menu to run it. +You may begin typing expressions such as the ones in the following ``Examples'' section. + +@p(Optional:)@index(Registry)@index(xlisppath)@index(search path) Nyquist needs to know where to find the standard runtime files. The location of runtime files must be stored in the Registry. +The installers create a registry entry, but if +you move Nyquist or deal with different versions, you can edit the Registry manually as follows: +@begin(itemize) +Run the Registry editor. Under Windows NT, run @code(C:\WINNT\system32\regedt32.exe). Under Windows95, run @code(C:\WINDOWS\regedit.exe). + +Find and highlight the @code(SOFTWARE) key under @code(HKEY_LOCAL_MACHINE). + +Choose @code(Add key ...) from the @code(Edit) menu, type @code(CMU), and click the @code(OK) button. + +Highlight the new @code(CMU) key. + +Choose @code(Add key ...) from the @code(Edit) menu, type @code(Nyquist), and click the @code(OK) button. (Note that @code(CMU) and @code(Nyquist) are case sensitive.) + +Highlight the new @code(Nyquist) key. + +Choose @code(Add value ...) from the @code(Edit) menu, type @code(XLISPPATH), and click the @code(OK) button. (Under WinXP the menu item is @code(Edit:New:String Value), after which you need to select the new string name that appears in the right panel, select @code(Edit:Rename), and type @code(XLISPPATH).) + +In the String Edit box (select the @code(Edit:Modify) menu item in WinXP), +type a list of paths you want Nyquist to search for lisp files. For example, if you installed Nyquist as @code(C:\nyquist), then type: +@begin(example) +C:\nyquist\runtime,C:\nyquist\lib +@end(example) +The paths should be separated by a comma or semicolon and no space. The @code(runtime) path is essential, and the @code(lib) path may become essential in a future release. You can also add paths to personal libraries of Lisp and Nyquist code. + +Click the @code(OK) button of the string box and exit from the Registry Editor application. +@end(itemize) + +@paragraph(What if Nyquist functions are undefined?) +If you do not have administrative privileges for your machine, the installer may fail to set up the Registry entry that Nyquist uses to find initialization files. In this case, Nyquist will run a lisp interpreter, but many Nyquist functions will not be defined. If you can log in as administrator, do it and reinstall Nyquist. If you do not have permission, you can still run Nyquist as follows: + +Create a file named @code(init.lsp) in the same directory as Nyquist.exe (the default location is @code(C:\Program Files\Nyquist), but you may have installed it in some other location.) Put the following text in @code(init.lsp): +@begin(example) +@begin(smallcode) +(setf *search-path* "C:/Program Files/Nyquist/runtime,C:/Program Files/Nyquist/lib") +(load "C:/Program Files/Nyquist/runtime/init.lsp") +@end(smallcode) +@end(example) +@p(Note:) in the three places where you see @code(C:/Program Files/Nyquist), insert the full path where Nyquist is actually installed. Use forward slashes (@code(/)) rather than back slashes (@code(\)) to separate directories. For example, if Nyquist is installed at @code(D:\rbd\nyquist), then @code(init.lsp) should contain: +@begin(example) +@begin(smallcode) +(setf *search-path* "D:/rbd/nyquist/runtime,D:/rbd/nyquist/lib") +(load "d:/rbd/nyquist/runtime/init.lsp") +@end(smallcode) +@end(example) +The variable @code(*search-path*), if defined, is used in place of the registry to determine search paths for files. + +@paragraph(SystemRoot) +@index(SystemRoot) +(Ignore this paragraph if you are not planning to use Open Sound Control under Windows.) +If Nyquist prints an error message and quits when you enable Open Sound Control (using @code(osc-enable)), check to see if you have an environment variable @code(SystemRoot), e.g. type @code(set) to a command prompt and look for the value of @code(SystemRoot). The normal value is @code(C:\windows). If the value is something else, you should put the environment entry, for example: +@begin(example) +SystemRoot="D:\windows" +@end(example) +into a file named @code(systemroot) (no extension). Put this file in your @code(nyquist) directory. When you run @code(NyquistIDE), it will look for this file and pass the contents as an environment variable to Nyquist. The Nyquist process needs this to open a UDP socket, which is needed for Open Sound Control. + +@paragraph(The "java is not recognized" Error) +Sometimes, Nyquist will run directly from the installer, but then it will not start from the Windows Start menu. You can try running the + @code(nyquist/jnyqide.bat) program from a Windows shell. If that fails, and you see an error similar to "java is not recognized as in internal or external command error", the problem may be that paths are not set up properly to allow the Windows shell to find java. Right click on ``My Computer'' on the Windows +desktop and select ``Properties.'' Under the ``Advanced'' tap, press the ``Environment Variables'' button, and look for PATH under ``System Variables.'' Make sure the Java bin directory is on the path. If it is not, you will have to find your installation of Java and add the appropriate directory to the PATH variable, e.g. ``C:\Program Files\Java\jdk1.6.0\bin.'' + +@subsection(MacOS X Installation) +The OS X version of Nyquist is very similar to the Linux version, but it +is developed using Xcode, Apple's programming environment. With a little +work, you can use the Linux installation instructions to compile Nyquist, +but it might be simpler to just open the Xcode project that is included +in the Nyquist sources. + +You can also download a pre-compiled version of Nyquist for the Mac. +Just download @code(nyqosx2xx.tgz) to the desktop and open it to +extract the folder nyqosx2xx. (Again, "2xx" refers to the current +version number, e.g. v2.31 would be named with "231".) Open the folder +to find a Mac Application named NyquistIDE and a directory named +nyquist/doc. Documentation is in the nyquist/doc directory. + +The file @code(NyquistIDE.app/Contents/Resources/Java/ny) +is the command line executable (if you should need it). To run from the +command line, you will need to set the XLISPPATH environment variable as +with Linux. On the topic of the @code(XLISPPATH), note that this variable is +set by NyquistIDE when running with that application, overriding any other +value. You can extend the search path by creating the file @code(xlisppath) +in the same directory as the nyquist executable @code(ny). The +@code(xlisppath) file should have colon-separated paths +on a single line of text. +@end(comment) + +@section(Using NyquistIDE)@index(NyquistIDE)@index(IDE)@index(Integrated Development Environment) +The program named NyquistIDE is an ``integrated development environment'' for Nyquist. When you run NyquistIDE, it starts the Nyquist program and displays all Nyquist output in a window. NyquistIDE helps you by providing a Lisp and SAL editor, hints for command completion and function parameters, some graphical interfaces for editing envelopes and graphical equalizers, and a panel of buttons for common operations. A more complete description of NyquistIDE is in Chapter @ref(jnyqide-chapter). + +For now, all you really need to know is that you can enter Nyquist commands by typing into the upper left window. When you type return, the expression you typed is sent to Nyquist, and the results appear in the window below. You can edit files by clicking on the New File or Open File buttons. After editing some text, you can load the text into Nyquist by clicking the Load button. NyquistIDE always saves the file first; then it tells Nyquist to load the file. You will be prompted for a file name the first time you load a new file. + +@section(Using SAL) +SAL mode means that Nyquist reads and evaluates SAL commands rather than Lisp. The SAL mode prompt is "@code(SAL> )" while the Lisp mode prompt is "@code(> )". +When Nyquist starts it normally enters SAL mode automatically, but certain errors may exit SAL mode. You can reenter SAL mode by typing the Lisp expression @code[(sal)]. + +In SAL mode, you type commands in the SAL programming language. Nyquist reads the commands, compiles them into Lisp, and evaluates the commands. Commands can be entered manually by typing into the upper left text box in NyquistIDE. + +@section(Helpful Hints) +Under Win95 and Win98, the console sometimes locks up. Activating another window and then reactivating the Nyquist window should unlock the output. +(We suggest you use JNyqIDE, the interactive development environment rather than a console window.) + +You can cut and paste text into Nyquist, but for serious work, you will want to use the Lisp @code(load) command. To save even more time, write a +function to load your working file, e.g. @code[(defun l () (load "myfile.lsp"))]. Then you can type @code[(l)] to (re)load your file. + +Using SAL, you can type +@begin(example) +define function l () load "myfile.lsp" +@end(example) +and then +@begin(example) +exec l() +@end(example) +to (re)load the file. + +The Emacs editor is free GNU software and will help you balance parentheses if you use Lisp mode. In fact, you can run nyquist (without the IDE) as a subprocess to Emacs. A helful discussion is at //http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/examples/emacs/main.html. If you use Emacs, there is also a SAL mode (the file is @code(sal-mode.el)) included with the Common Music distribution, which you can find on the Web at @code(sourceforge.net). + +The NyquistIDE also runs Nyquist as a subprocess and has +built-in Lisp and SAL editors. If your editor does not help you balance parentheses, you may find yourself counting parens and searching for unbalanced +expressions. If you are confused or desperate and using Lisp syntax, +try the +@code(:print t) +option of the @code(load) function. By looking at the expressions printed, +you should be able to tell where the last unbalanced expression starts. +Alternatively, type @code[(file-sexprs)] and type the lisp file name at +the prompt. This function will read and print +expressions from the file, reporting an error when an extra paren or end-of-file is reached unexpectedly. + +@section(Using Lisp) +Lisp mode means that Nyquist reads and evaluates Nyquist expressions in +Lisp syntax. Since Nyquist is build on a Lisp interpreter, this is the +``native'' or machine language of Nyquist, and certain errors and functions +may break out of the SAL interpreter, leaving you with a prompt for a Lisp +expression. Alternatively, you can exit SAL simply by typing @code(exit) to +get a Lisp prompt (@code(> )). Commands can be entered manually by typing + into the upper left text box in NyquistIDE. + +@section(Examples) +We will begin with some simple Nyquist programs. Throughout the manual, +we will assume SAL mode and give examples in SAL, but it should be +emphasized that all of these examples can be performed using Lisp +syntax. See Section @ref(sal-vs-lisp-section) on the relationship between +SAL and Lisp. + +Detailed explanations of the functions used in these examples will be +presented in later chapters, so at this point, you should just read these +examples to get a sense of how Nyquist is used and what it can do. The +details will come later. Most of these examples can be found in the +file @code(nyquist/demos/examples.sal). Corresponding Lisp syntax +examples are in the file @code(nyquist/demos/examples.lsp). + +Our first example makes and plays a sound:@index(osc)@index(play) +@begin(example) +@i(;; Making a sound.) +play osc(60) ; generate a loud sine wave +@comment{(play (osc 60)) @i(; generate a loud sine wave)} @end(example) +This example is about the simplest way to create a sound with Nyquist. The +@code(osc) function generates a sound using a table-lookup oscillator. +There are a number of optional parameters, but the default is to compute a +sinusoid with an amplitude of 1.0. The parameter @code(60) designates a +pitch of middle C. (Pitch specification will be described in greater detail +later.) The result of the @code(osc) function is a sound. To hear a sound, +you must use the @code(play) command, which plays the file through the machine's D/A converters. It also writes a soundfile in case the computation cannot keep up with real time. You can then (re)play the file by typing: +@begin(example) +exec r() +@end(example) +This @code[(r)] function is a general way to ``replay'' the last thing written by @code(play). + +Note: when Nyquist plays a sound, it scales the signal by 2@+(15)-1 and (by default) converts to a 16-bit integer format. A signal like @code[(osc 60)], which ranges from +1 to -1, will play as a full-scale 16-bit audio signal. + +@subsection(Waveforms) +@label(waveform-sec) +Our next example will be presented in several steps. The goal is to create a +sound using a +wavetable consisting of several harmonics as opposed to a simple sinusoid. +In order to build a table, we will use a function that computes a single +harmonic and add harmonics to form a wavetable. An oscillator +will be used to compute the harmonics. + +@begin(comment) +Ordinarily, Nyquist programs are sample-rate independent, and time (in +seconds) is used rather than sample numbers to indicate regions of signals. +Since we want a wave-table with a certain integer number of samples, we need +to do some extra calculations to convert from time to samples. The +@code(build-harmonic) function (see Figure @ref(build-harmonic-fig)) +produces a signal with @code(n) periods in the course of 2048 samples using +the @code(snd-sine) function. + +@begin(figure) +@begin(example) +(defun build-harmonic (n tablesize) (snd-sine 0 n tablesize 1)) +@end(example) +@fillcaption(@code(build-harmonic) uses a low-level function, +@code(snd-sine), to construct a harmonic. The function parameters denote: +``compute a sinusoid starting at time zero, with frequency @i(n), a sample +rate of @i(tablesize) samples per second and a duration of 1 second.'' This signal +becomes a periodic waveform to be resampled by a table lookup oscillator, so +the choice of sample rate and duration is a matter of convenience. +@tag(build-harmonic-fig) +@end(figure) +@end(comment) + +The function +@code(mkwave@index(mkwave)) calls upon +@code(build-harmonic@index(build-harmonic)) to generate a total of four +harmonics with amplitudes 0.5, 0.25, 0.125, and 0.0625. +These are scaled and added (using @code(+@index(sim))) to +create a waveform which is bound temporarily to @code(*table*). + +A complete Nyquist waveform is a list consisting of a sound, a pitch, + and @code(T), indicating a periodic waveform. The pitch gives the +nominal pitch of the sound. (This is implicit in a single cycle wave +table, but a sampled sound may have many periods of the fundamental.) +Pitch is expressed in half-steps, where middle C is 60 steps, as in MIDI +pitch numbers. +The list of sound, pitch, and @code(T) is formed in the last line of +@code(mkwave): since @code(build-harmonic) computes signals with a duration +of one second, the fundamental is 1 Hz, and the @code(hz-to-step) function +converts to pitch (in units of steps) as required. + +@begin(example)@label(build-harmonic-example) +define function mkwave() + begin + set *table* = 0.5 * build-harmonic(1.0, 2048) + + 0.25 * build-harmonic(2.0, 2048) + + 0.125 * build-harmonic(3.0, 2048) + + 0.0625 * build-harmonic(4.0, 2048) + set *table* = list(*table*, hz-to-step(1.0), #t) + end +@end(example) + +Now that we have defined a function, the last step of this example is to +build the wave. The following code calls +@code(mkwave) the first time the code is executed (loaded from a file). The second time, the variable @code(*mkwave*) will be true, so @code(mkwave) will not be invoked: +@begin(example) +if ! fboundp(quote(*mkwave*)) then + begin + exec mkwave() + set *mkwave* = #t + end +@end(example) + +@subsection(Wavetables)@index(wavetables)@index(waveforms)@index(triangle wave)@index(sawtooth wave) +When Nyquist starts, several waveforms are created and stored in global variables for convenience. They are: @code(*sine-table*), @code(*saw-table*), and @code(*tri-table*), implementing sinusoid, sawtooth, and triangle waves, respectively. The variable @code(*table*) is initialized to @code(*sine-table*), and it is @code(*table*) that forms the default wave table for many Nyquist oscillator behaviors. If you want a proper, band-limited waveform, you should construct it yourself, but if you do not understand this sentence and/or you do not mind a bit of aliasing, give @code(*saw-table*) and @code(*tri-table*) a try. + +Note that in Lisp and SAL, global variables often start and end with asterisks (*). These are not special syntax, they just happen to be legal characters for names, and their use is purely a convention. + +@subsection(Sequences)@index(Sequences) +Finally, we define @code(my-note@index(my-note)) to use the waveform, and play several notes +in a simple score. Note that the function @code(my-note) has only one command +(a @code(return) command), so it is not necessary to use @code(begin) and +@code(end). These are only necessary when the function body consists of a +sequence of statements: +@begin(example) +define function my-note(pitch, dur) + return osc(pitch, dur, *table*) + +play seq(my-note(c4, i), my-note(d4, i), my-note(f4, i), + my-note(g4, i), my-note(d4, q)) + +@end(example) +Here, @code(my-note) is defined to take pitch and duration as parameters; +it calls @code(osc) to do the work of generating a waveform, using +@code(*table*) as a wave table. + +The @code(seq) function is used to invoke a sequence of behaviors. Each +note is started at the time the previous note finishes. The parameters to +@code(my-note) are predefined in Nyquist: @code(c4) is middle C, @code(i) (for +eIghth note) is 0.5, and @code(q) (for Quarter note) is 1.0. See Section +@ref(constants-sec) for a complete description. The result is the sum of +all the computed sounds. + +Sequences can also be constructed using the @code(at) transformation to +specify time offsets. See +@code(sequence_example.htm)@index(sequence_example.htm)@index(score, musical) +@code(demos, sequence) for more examples and explanation. + +@subsection(Envelopes)@index(Envelopes) +The next example will illustrate the use of envelopes. In Nyquist, +envelopes are just ordinary sounds (although they normally have a low sample +rate). An envelope@index(envelope) is applied to another sound by +multiplication using the @code(mult@index(mult)) function. The code shows +the definition of @code(env-note@index(env-note)), defined in terms of the +@code(note) function in the previous example. In @code(env-note), a 4-phase +envelope is generated using the @code(env@index(env)) function, which is +illustrated in Figure @ref(env-fig). + +@begin(figure) +@center(@graphic((height = 2 in, width = 3.75 in, magnify = 1, + postscript = "envfig.ps")) +@html(

) +@fillcaption(An envelope generated by the @code(env) function.) +@tag(env-fig) +@end(figure) + +@begin(Example) +@i[; env-note produces an enveloped note. The duration +; defaults to 1.0, but stretch can be used to change +; the duration. +; Uses my-note, defined above. +;] +define function env-note(p) + return my-note(p, 1.0) * + env(0.05, 0.1, 0.5, 1.0, 0.5, 0.4) + +@i[; try it out: +;] +play env-note(c4) +@end(example) +While this example shows a smooth envelope multiplied by an audio signal, +you can also multiply audio signals to achieve +what is often called @i(ring modulation)@index(ring modulation). See +the code and description in +@code(demos/scratch_tutorial.htm)@index(demos, ring modulation) for an +interesting use of ring modulation to create ``scratch'' sounds. + +In the next example, The @i(stretch) operator (@code(~))@index(stretch) +is used to modify durations: +@begin(example) +@i[; now use stretch to play different durations +;] +play seq(seq(env-note(c4), env-note(d4)) ~ 0.25, + seq(env-note(f4), env-note(g4)) ~ 0.5, + env-note(c4)) +@end(example) + +In addition to @i(stretch), there are a number of transformations supported + by Nyquist, +and transformations of abstract behaviors is perhaps @i(the) fundamental +idea behind Nyquist. Chapter @ref(behavioral-abstraction-sec) is devoted to +explaining this concept, and further elaboration can be found elsewhere +@cite(icmcfugue). + +@subsection(Piece-wise Linear Functions) +It is often convenient to construct signals in Nyquist using a list of +(time, value) breakpoints which are linearly interpolated to form a smooth +signal. Envelopes created by @code(env) are a special case of the more +general piece-wise linear functions created by @code(pwl). Since @code(pwl) +is used in some examples later on, we will take a look at @code(pwl) +now. The @code(pwl) function takes a list of parameters which denote (time, +value) pairs. There is an implicit initial (time, value) pair of (0, 0), +and an implicit final value of 0. There should always be an odd number of +parameters, since the final value (but not the final time) is implicit. +Here are some examples: +@begin(Example) +@i[; symetric rise to 10 (at time 1) and fall back to 0 (at time 2): +;] +pwl(1, 10, 2) + +@i[; a square pulse of height 10 and duration 5. +; Note that the first pair (0, 10) overrides the default initial +; point of (0, 0). Also, there are two points specified at time 5: +; (5, 10) and (5, 0). (The last 0 is implicit). The conflict is +; automatically resolved by pushing the (5, 10) breakpoint back to +; the previous sample, so the actual time will be 5 - 1/sr, where +; sr is the sample rate. +;] +pwl(0, 10, 5, 10, 5) + +@i[; a constant function with the value zero over the time interval +; 0 to 3.5. This is a very degenerate form of pwl. Recall that there +; is an implicit initial point at (0, 0) and a final implicit value of +; 0, so this is really specifying two breakpoints: (0, 0) and (3.5, 0): +;] +pwl(3.5) + +@i[; a linear ramp from 0 to 10 and duration 1. +; Note the ramp returns to zero at time 1. As with the square pulse +; above, the breakpoint (1, 10) is pushed back to the previous sample. +;] +pwl(1, 10, 1) + +@i[; If you really want a linear ramp to reach its final value at the +; specified time, you need to make a signal that is one sample longer. +; The RAMP function does this: +;] +ramp(10) @i[; ramp from 0 to 10 with duration 1 + one sample period +; +; RAMP is based on PWL; it is defined in @p(nyquist.lsp). +;] +@end(example) + +@section(Predefined Constants) +@label(constants-sec) +For convenience and readability, Nyquist pre-defines some constants, mostly +based on the notation of the Adagio score language, as follows: +@begin(itemize) +@b(Dynamics) +Note: these dynamics values are subject to change. +@begin(display) +@t(lppp@index(lppp)) = -12.0 (dB) +@t(lpp@index(lpp)) = -9.0 +@t(lp@index(lp)) = -6.0 +@t(lmp@index(lmp)) = -3.0 +@t(lmf@index(lmf)) = 3.0 +@t(lf@index(lf)) = 6.0 +@t(lff@index(lff)) = 9.0 +@t(lfff@index(lfff)) = 12.0 +@t(dB0@index(dB0)) = 1.00 +@t(dB1@index(dB1)) = 1.122 +@t(dB10@index(dB10)) = 3.1623 +@end(display) + +@b(Durations@index(duration notation)) +@begin(display) +@t(s@index(s)) = Sixteenth@index(Sixteenth note) = 0.25 +@t(i@index(i)) = eIghth@index(eIghth note) = 0.5 +@t(q@index(q)) = Quarter@index(quarter note) = 1.0 +@t(h@index(h)) = Half@index(half note) = 2.0 +@t(w@index(w)) = Whole@index(whole note) = 4.0 +@t(sd@index(sd), id@index(id), qd@index(qd), hd@index(hd), wd@index(wd)) = dotted durations@index(dotted durations). +@t(st@index(st), it@index(it), qt@index(qt), ht@index(ht), wt@index(wt)) = triplet@index(triplet durations) durations. +@end(display) + +@b(Pitches@index(pitch notation)) +Pitches are based on an A4 of 440Hz. To achieve a different tuning, +set @code(*A4-Hertz*) to the desired frequency for A4, and call +@code[(set-pitch-names)]. This will recompute the names listed below with a +different tuning. In all cases, the pitch value 69.0 corresponds exactly to +440Hz, but fractional values are allowed, so for example, if you set +@code(*A4-Hertz*) to 444 (Hz), then the symbol @code(A4) will be bound to +69.1567, and @code(C4) (middle C), which is normally 60.0, will be 60.1567. +@begin(display) +@t(c0) = 12.0 +@t(cs0, df0) = 13.0 +@t(d0) = 14.0 +@t(ds0, ef0) = 15.0 +@t(e0) = 16.0 +@t(f0) = 17.0 +@t(fs0, gf0) = 18.0 +@t(g0) = 19.0 +@t(gs0, af0) = 20.0 +@t(a0) = 21.0 +@t(as0, bf0) = 22.0 +@t(b0) = 23.0 +@t(c1) ... @t(b1) = 24.0 ... 35.0 +@t(c2) ... @t(b2) = 36.0 ... 47.0 +@t(c3) ... @t(b3) = 48.0 ... 59.0 +@t(c4) ... @t(b4) = 60.0 ... 71.0 +@t(c5) ... @t(b5) = 72.0 ... 83.0 +@t(c6) ... @t(b6) = 84.0 ... 95.0 +@t(c7) ... @t(b7) = 96.0 ... 107.0 +@t(c8) ... @t(b8) = 108.0 ... 119.0 +@end(display) + +@b(Miscellaneous) +@begin(display) +@codef(ny:all)@pragma(defn)@index(ny:all) = ``all the samples'' (i.e. a big number) = 1000000000 +@end(display) +@end(itemize) + +@section(More Examples) +More examples can be found in the directory @code(demos), part of the standard +Nyquist release. The file @code(demos/examples_home.htm) is an index to all the demo descriptions. In this directory, you will find the following and more: +@begin(itemize) +How to make arpeggios (@code(demos/arpeggiator.htm) and @code(arp.sal)@index(arpeggiator) + +Gong sounds by additive synthesis@index(additive synthesis, gongs) +(@code(demos/pmorales/b1.lsp) and @code(demos/mateos/gong.lsp)@index(Gong sounds)@index(demos, gong sound) + +Risset's spectral analysis of a chord +(@code(demos/pmorales/b2.lsp))@index(Risset)@index(demos, spectral analysis of a chord) + +Bell sounds +(@code(demos/pmorales/b3.lsp), @code(demos/pmorales/e2.lsp), @code(demos/pmorales/partial.lsp), and @code(demos/mateos/bell.lsp))@index(demos, bell sound)@index(bell sound) + +Drum sounds by Risset +(@code(demos/pmorales/b8.lsp)@index(demos, drum sound)@index(drum sound) + +Shepard tones (@code(demos/shepard.lsp) and @code(demos/pmorales/b9.lsp))@index(Shepard tones)@index(endless tones) + +Random signals (@code(demos/pmorales/c1.lsp)) + +Buzz with formant filters +(@code(demos/pmorales/buzz.lsp)@index(vocal sound)@index(demos, formants) + +Computing samples directly in Lisp (using Karplus-Strong and physical modelling +as examples) +(@code(demos/pmorales/d1.lsp)@index(demos, sample-by-sample)@index(DSP in Lisp)@index(Lisp DSP)@index(Karplus-Strong synthesis)@index(physical model)@index(flute sound) + +FM Synthesis examples, including bell@index(bell sound), wood drum@index(wood drum sound), +brass sounds@index(brass sound), tuba sound @index(tuba) (@code(demos/mateos/tuba.lsp) and clarinet sounds@index(clarinet sound) (@code(demos/pmorales/e2.lsp)@index(demos, FM synthesis) + +Rhythmic patterns (@code(demos/rhythm_tutorial.htm)@index(demos, rhythmic pattern) + +Drum Samples and Drum Machine +(@code(demos/plight/drum.lsp)@index(demos, drum machine)@index(drum +samples)@index(drum machine). (See Section @ref(drum-machine-sec)). +@end(itemize) + +@chapter(The NyquistIDE Program) +@label(jnyqide-chapter) +The NyquistIDE program combines many helpful functions and interfaces to help you get the most out of Nyquist. NyquistIDE is implemented in Java, and you will need the Java runtime system or development system installed on your computer to use NyquistIDE. The best way to learn about NyquistIDE is to just use it. This chapter introduces some of the less obvious features. If you are confused by something and you do not find the information you need here, please contact the author. + +@section(NyquistIDE Overview) +The NyquistIDE runs the command-line version of Nyquist as a subtask, so everything that works in Nyquist should work when using the NyquistIDE and vice-versa. Input to Nyquist is usually entered in the top left window of the NyquistIDE. When you type return, if the expression or statement appears to be complete, the expression you typed is sent to Nyquist. Output from Nyquist appears in a window below. You cannot type into or edit the output window text. + +The normal way to use the NyquistIDE is to create or open one or more files. You edit these files and then click the Load button. To load a file, NyquistIDE saves the file, sets the current directory of Nyquist to that of the file, then issues a @code(load) command to Nyquist. In this case and several others, you may notice that NyquistIDE sends expressions to Nyquist automatically for evaluation. You can always see the commands and their results in the output window. + +Notice that when you load a selected file window, NyquistIDE uses @code(setdir) to change Nyquist's current directory. This helps to keep the two programs in sync. Normally, you should keep all the files of a project in the same directory and avoid manually changing Nyquist's current directory (i.e. avoid calling @code(setdir) in your code). + +Arranging windows in the NyquistIDE can be time-consuming, and depending on the +operating system, it is possible for a window to get into a position where you +cannot drag it to a new position. The Window:Tile menu command can be used +to automatically lay out windows in a rational way. There is a preference +setting to determine the height of the completion list relative to the height of the output +window. + +@section(The Button Bar) +@index(button bar) +There are a number of buttons with frequently-used operations. These are: +@begin(itemize) +Info @itemsep @index(info button)Print information about Nyquist memory +utilization, including +the number of free cons cells, the number of garbage collections, +the total number of cons cells, the total amount of sample buffer memory, +and the amount of memory in free sample buffers. + +Break @itemsep @index(break button)Send a break character to XLISP. This +can be used to enter the debugger (the break loop) while a program is +running. Resume by typing @code[(co)]. + +SAL/Lisp @itemsep @index(SAL button)@index(Lisp button)Switch modes. +The button names the mode (SAL or Lisp) you will switch to, not the +current mode. For example, if you are in Lisp mode and want to type +a SAL command, click the SAL button first. + +Top @itemsep @index(top button)Enters @code[(top)] into Nyquist. +If the XLISP prompt is @code(1>) or +some other integer followed by ``@code(>)'', clicking the Top button +will exit the debug loop and return to the top-level prompt. + +Replay @itemsep @index(replay button)Enters @code[(r)] into Nyquist. +This command replays the last computed sound. + +F2-F12 @itemsep @index(Fn button)Enters @code[(f2)] etc. into Nyquist. +These commands are not built-in, and allow users to define their own +custom actions. + +Browse @itemsep @index(browse button)Equivalent to the Window:Browse +menu item. (See Section @ref(browser).) + +EQ @itemsep @index(eq button)Equivalent to the Window:EQ menu item. +(See Section @ref(eq-window-sec).) + +EnvEdit @itemsep @index(envedit button)Equivalent to the Window:Envelope Edit +menu item. (See Section @ref(envelope-editor-sec).) + +NewFile @itemsep @index(newfile button)Equivalent to the File:New menu +item. Opens a new file editing window for creating and +loading a Lisp or SAL program file. + +OpenFile @itemsep @index(openfile button)Equivalent to the File:Open menu +item. Opens an existing Lisp or SAL program file for editing and loading. + +SaveFile @itemsep @index(savefile button)Equivalent to the File:Save menu +item (found on the editing window's menu bar). Saves the contents +of an editing window to its associated file. + +Load @itemsep @index(load button)Equivalent to the File:Load menu +item (found on the editing window's menu bar). Performs a Save operation, +then sends a command to Nyquist that loads the file as a program. + +Mark @itemsep @index(mark button)Sends a Control-A to Nyquist. While +playing a sound, this displays and records the approximate time in the +audio stream. (See Section @ref(play-sec) for more detail.) + +@end(itemize) + +@section(Command Completion) +To help with programming, NyquistIDE maintains a command-completion window. +As you type the first letters of function names, NyquistIDE lists matching +functions and their parameters in the Completion List window. If you click +on an entry in this window, the displayed expression will replace the +incompletely typed function name. A preference allows you to match initial +letters or any substring of the complete function name. This is controlled +by the ``Use full search for code completion'' preference. + +In addition, if you right click (or under Mac OS X, hold down the Alt/Option +key and click) on an entry, NyquistIDE will display documentation for the function. +Documentation can come from a local copy or from the online copy (determined +by the ``Use online manual instead of local copy'' preference). Documentation +can be displayed within the NyquistIDE window or in an external browser (determined +by the ``Use window in NyquistIDE for help browser'' preference.) Currently, the +external browser option does not seem to locate documentation properly, but +this should be fixed in the future. + +@section(Browser) +@label(browser) +@index(browser, jnyqide)@index(sound browser, jnyqide) +If you click on the Browse button or use the Window:Browse menu command, +NyquistIDE will display a browser window that is pre-loaded with a number of + Nyquist commands to create sounds. You can adjust parameters, audition +the sounds, and capture the expression that creates the sound. In many +cases, the expression checks to see if necessary functions are defined, +loading files if necessary before playing the sound. If you want to use +a sound in your own program, you can often simplify things by explicitly +loading the required file just once at the beginning of your file. + +Since Nyquist now supports a mix of Lisp and SAL, you may find yourself in +the position of having code from the browser in one language while you are +working in the other. The best way to handle this is to put the code for +the sound you want into a function defined in a Lisp (@code(.lsp)) or SAL +(@code(.sal)) file. Load the file (from Lisp, use the @code(sal-load) +command to load a SAL file), and call the function from the language of +your choice. + +@section(Envelope Editor) +@label(envelope-editor-sec) +@index(envelope editor) +@index(editor for envelopes) +@index(graphical envelope editor) +The envelope editor allows you graphically to design and edit piece-wise +linear and exponential envelopes. The editor maintains a list of envelopes +and you select the one to edit or delete using the drop down list in the +Saved Envelopes List area. The current envelope appears in the Graphical +Envelope Editor area. You can click to add or drag points. Alternatively, +you can use the Envelope Points window to select and edit any breakpoint +by typing coordinates. The duration of the envelope is controlled by the +Stop field in the Range area, and the vertical axis is controlled by the +Min and Max fields. + +When you click the Save button, @i(all) envelopes are written to Nyquist. +You can then use the envelope by treating the envelope name as a function. +For example, if you define an envelope named ``fast-attack,'' then you +can create the envelope within a Nyquist SAL program by writing +the expression @code[fast-attack()]. + +These edited envelopes are saved to a file named @code(workspace.lsp) + @index(workspace) in +the current directory. The workspace is Nyquist's mechanism for saving +data of all kinds (see Section @ref(workspaces-sec)). The normal way to +work with workspaces is to (1) load the workspace, i.e. + @code[load "workspace"], as soon as you start Nyquist; (2) invoke +the envelope editor to change values in the workspace; and (3) save the +workspace at any time, especially before you exit NyquistIDE. If you follow +these steps, envelopes will be preserved from session to session, and +the entire collection of envelopes will appear in the editor. Be +sure to make backups of your @code(workspace.lsp) file along with your +other project files. + +The envelope editor can create linear and exponential envelopes. Use the +Type pull-down menu to select the type you want. Envelopes can be created +using default starting and ending values using @code(pwl) or @code(pwe), +or you can specify the initial values using @code(pwlv) or @code(pwev). +The envelope editor uses @code(pwl) or @code(pwe) if no point is explicitly +entered as the initial or final point. To create a @code(pwlv) or @code(pwev) +function, create a point and drag it to the leftmost or rightmost edge +of the graphical editing window. You will see the automatically +generated default starting or ending +point disappear from the graph. + +Exponential envelopes should never decay to zero. If you enter a zero +amplitude, you will see that the envelope remains at zero to the next +breakpoint. To get an exponential decay to ``silence,'' try using an +amplitude of about 0.001 (about -60dB). To enter small values like +this, you can type them into the Amplitude box and click ``Update Point.'' + +The Load button refreshes the editor from data saved in the Nyquist +process. Normally, there is no need to use this because the editor +automatically loads data when you open it. + +@section(Equalizer Editor) +@label(eq-window-sec)@index(equalization editor)@index(graphical equalization) +The Equalizer Editor provides a graphical EQ interface for creating and +adjusting equalizers. Unlike the envelope editor, where you can type +any envelope name, equalizers are named @code(eq-0), @code(eq-1), etc., +and you select the equalizer to edit using a pull-down menu. The @code(Set) +button should be use to record changes. + +@section(UPIC Editor) +@label(upic-editor-sec)@index(UPIC)@index(Xenakis)@index(Iannis Xenakis)The +UPIC Editor is inspired by the UPIC system by Iannis Xenakis at the Centre +d'Edudes de Mathematique et Automatique Musicales (CEMaMu). The UPIC Editor +is accessed by the ``Upic Edit'' menu item in the ``Window'' menu of the +NyquistIDE. Once opened, you can draw pitch contours in the main panel by +pressing the left mouse button and dragging with the mouse down. Contours +represent tones in a frequency vs. time coordinate system. Any contour can be +deleted by right-clicking (or shift-clicking on an Apple computer) to +select the contour (indicated by the color red), and typing the Delete key. + +A collection of contours can be saved to a file and later retrieved using the +items in the File menu (use the File menu in the UPIC Editor window, not in +the main NyquistIDE window.) The file is a SAL program in a special format +that can be parsed by the UPIC Editor. The file can also be loaded +into Nyquist using the File:Load menu item, or by executing a load command +in Nyquist. + +The panel at the top of the editor offers control over various parameters. +The Name box is a Nyquist variable name. This name takes effect when you +save a file from the UPIC Editor. The variable name is stored in the +file so that when a UPIC Editor-generated file +is loaded into Nyquist, the data is assigned to this variable name. +The data is +a list of contours, where each contour specifies a waveform, an envelope, +and a list of time-frequency coordinates. + +The next item in the panel is the Waveform box. The Waveform box names a +waveform for a contour. Default waveforms are sinusoid, triangle, and +sawtooth, but you can type in your own names. The currently selected +waveform is stored with the contour when it is created (entered by +drawing). You cannot change or edit the waveform name associated with +a contour once the contour is created, but you can always delete the +contour and replace it. The Envelope box names an envelope for a +contour. The envelope names a Nyquist function. The default, @code(upic-env) +is a trapezoid shape with an onset time and offset time of 10ms. As with +waveforms, the envelope is stored with each contour when the contour is +created and cannot be edited. + +The Stop Time box gives the duration of the drawing area in seconds. +The Min Freq box gives the minimum frequency (at the bottom of the +drawing area), and the Max Freq box gives the maximum frequency (at the +top of the drawing area). The vertical frequency axis can use a linear +scale corresponding to frequency in Hertz or a logarithmic scale +corresponding to semitones. The ``linear'' checkbox selects the linear +scale. When @i(any) of these parameters (described in this paragraph and +delimited by the border labeled ``Range'' on the control panel) is changed, +you must press the Update Range button for the change to take effect. + +The Background menu lets you display a grid that indicates pitch locations. +The ``C's'' item draws a line at C in every visible octave. E.g. middle C +is about 260 Hz, so a reference line will be drawn near 260 Hz. +Lines will be drawn around 130 Hz (an octave below middle C), and around +520 Hz (an octave above middle C), etc. The ``GrandStaff'' menu item +draws reference lines for each line of the grand staff commonly used +for piano music. The pitches are G2, B2, D3, F3, A3, E4, G4, B4, D5, and +F5. Finally, you can load a picture using the +Background:Load Picture... menu item. Then, the Background:Show Picture +menu item toggles whether the picture is displayed or not. This feature +allows you to trace an image. (For example, see the Sonic Self-Portrait +at @code(http://www.cs.cmu.edu/~rbd).) You may wish to use an image editor +to lighten the image so that superimposed contours will be more visible. + +Each change to the Range data, background choice, and each entry of a +contour is an action that you can undo or redo with the Undo and Redo +buttons. + +To convert UPIC data into sound, first load @code(upic.sal) and load +a file generated by the UPIC Editor. Now, suppose the variable name +used is @code(upicdata). You can play the data by writing +@begin(example) +play upic(upicdata) +@end(example) +If you created your own names for waveforms or envelopes, you must be +sure that these exist before calling the @code(upic) function. Each +waveform must be the name of a variable which is set to a Nyquist +wave table. (See Section @ref(waveform-sec) for information on how +to create a wave table.) Also, each envelope must name a function with +no parameters that will return an amplitude envelope. The following is +the built-in definition for @code(upic-env): +@begin(example) +define function upic-env() + return env(0.01, 0.01, 0.01, 1, 1, 1) +@end(example) +To make a custom envelope function named @code(upic-smooth) with a 0.2 + second attack and a 0.3 second decay, you could write: +@begin(example) +define function upic-smooth() + return env(0.2, 0.01, 0.3, 1, 1, 1) +@end(example) + + +@chapter(Behavioral Abstraction)@index(behavioral abstraction) +@label(behavioral-abstraction-sec) +In Nyquist, all functions are subject to +transformations@index(transformations). You can think of transformations as +additional parameters to every function, and functions are free to use these +additional parameters in any way. The set of transformation parameters is +captured in what is referred to as the @i(transformation +environment@index(transformation environment)). (Note that the term +@i(environment) is heavily overloaded in computer science. This is yet +another usage of the term.) + +Behavioral abstraction is the ability of functions to adapt their behavior +to the transformation environment. This environment may contain certain +abstract notions, such as loudness, stretching a sound in time, etc. These +notions will mean different things to different functions. For example, an +oscillator should produce more periods of oscillation in order to stretch +its output. An envelope, on the other hand, might only change the +duration of the sustain portion of the envelope in order to stretch. +Stretching a sample could mean resampling it to change its duration by the +appropriate amount. + +Thus, transformations in Nyquist are not simply operations on signals. For +example, if I want to stretch a note, it does not make sense to compute the +note first and then stretch the signal. Doing so would cause a drop in the +pitch. Instead, a transformation modifies the @i(transformation +environment) in which the note is computed. Think of transformations as +making requests to functions. It is up to the function to carry out the +request. Since the function is always in complete control, it is possible +to perform transformations with ``intelligence;'' that is, the function can +perform an appropriate transformation, such as maintaining the desired pitch +and stretching only the ''sustain'' portion +of an envelope to obtain a longer note. + +@section(The Environment)@index(environment) +@label(environment-sec) +The transformation environment consists of a set of special variables. +These variables should not be read directly and should @i(never) be set +directly by the programmer. Instead, there are functions to read them, and +they are automatically set and restored by +transformation operators, which will be described below. + +The transformation environment consists of the following elements. Although +each element has a ``standard interpretation,'' the designer of an +instrument or the composer of a complex behavior is free to interpret the +environment in any way. For example, a change in @code(*loud*) may change +timbre more than amplitude, and @code(*transpose*) may be ignored by +percussion instruments: + + +@begin(description) + @codef(*warp*@pragma(defn)@index(*warp*))@\Time transformation, including time shift, +time stretch, and continuous time warp. The value of @code[*warp*] is +interpreted as a function from logical (local score) time to physical +(global real) time. Do not access @code(*warp*) directly. Instead, use +@code[local-to-global(@i(t))] to + convert from a logical (local) time to real (global) time. Most often, +you will call @code[local-to-global(0)]. Several transformation operators +operate on @code[*warp*], including @i(at) (@code(@@)), @i(stretch) (@code(~)), +and @code(warp). See also @code[get-duration()] and @code[get-warp()]. + + @codef(*loud*@pragma(defn)@index(*loud*))@\Loudness, expressed in decibels. The default +(nominal) loudness is 0.0 dB (no change). Do not access @code(*loud*) +directly. Instead, use @code[get-loud()] to get the current value of +@code(*loud*) and either @code(loud) or @code(loud-abs) to modify it. + + @codef(*transpose*@pragma(defn)@index(*transpose*))@\Pitch transposition, +expressed in +semitones. (Default: 0.0). Do not access @code(*transpose*) directly. +Instead, use @code[get-transpose()] to get the current value of +@code(*transpose*) and either @code(transpose) or @code(transpose-abs) to +modify it. + + @codef(*sustain*@pragma(defn)@index(*sustain*))@\The ``sustain,'' +``articulation,'' ``duty factor,'' or amount by which to +separate or overlap sequential notes. For +example, staccato might be expressed with a @code(*sustain*) of 0.5, while very +legato playing might be expressed with a @code(*sustain*) of 1.2. +Specifically, @code(*sustain*) stretches the duration of notes (sustain) +without affecting the inter-onset time (the rhythm). Do not access +@code(*sustain*) directly. Instead, use @code[get-sustain()] to get the +current value of @code(*sustain*) and either @code(sustain) or +@code(sustain-abs) to modify it. + + @codef(*start*@pragma(defn)@index(*start*))@\Start +time of a clipping region. @i(Note:) +unlike the previous elements of the environment, @code(*start*) has a +precise interpretation: no sound should be generated before @code(*start*). +This is implemented in all the low-level sound functions, so it can +generally be ignored. You can read @code(*start*) directly, but use +@code(extract) or @code(extract-abs) to modify it. @p(Note 2:) Due +to some internal confusion between the specified starting time and +the actual starting time of a signal after clipping, @code(*start*) +is not fully implemented. + + @codef(*stop*@pragma(defn)@index(*stop*))@\Stop time of clipping +region. By analogy to +@code(*start*), no sound should be generated after this time. +@code(*start*) and +@code(*stop*) allow a composer to preview a small section of a work +without computing it from beginning to end. You can read @code(*stop*) +directly, but use @code(extract) or @code(extract-abs) to modify it. + @p(Note:) Due to some internal confusion between the specified +starting time and the actual starting time of a signal after +clipping, @code(*stop*) is not fully implemented. + +@codef(*control-srate*@pragma(defn)@index(*control-srate*))@\Sample +rate of control signals. This environment +element provides the default sample rate for control signals. There is no +formal distinction between a control signal and an audio signal. +You can read @code(*control-srate*) directly, but +use @code(control-srate) or @code(control-srate-abs) to modify it. + + @codef(*sound-srate*@pragma(defn)@index(*sound-srate*))@\Sample +rate of musical sounds. This environment element provides the +default sample rate for musical sounds. You can +read @code(*sound-srate*) directly, but use @code(sound-srate) +or @code(sound-srate-abs) to modify it. + +@end(description) + +@section(Sequential Behavior)@index(sequential behavior) +Previous examples have shown the use of @code(seq), the sequential behavior +operator. We can now explain @code(seq) in terms of transformations. +Consider the simple expression: +@begin(Example) +play seq(my-note(c4, q), my-note(d4, i)) +@end(example) +The idea is to create the first note at time 0, and to start the next +note when the first one finishes. This is all accomplished by manipulating +the environment. In particular, @code[*warp*] is modified so that what is +locally time 0 for the second note is transformed, or warped, to the logical +stop time of the first note. + +One way to understand this in detail is to imagine how it +might be executed: first, @code(*warp*) is set to an initial value that has no +effect on time, and @code[my-note(c4, q)] is evaluated. A sound is returned and +saved. The sound has an ending time, which in this case will be @code(1.0) +because the duration @code(q) is @code(1.0). This ending time, @code(1.0), +is used to construct a new @code[*warp*] that has the effect of shifting +time by 1.0. The second note is evaluated, and will start +at time 1. The sound that is +returned is now added to the first sound to form a composite sound, whose +duration will be @code(2.0). @code(*warp*) is restored to its initial value. + +Notice that the semantics of @code(seq) can be expressed in terms of +transformations. To generalize, the operational rule for @code(seq) is: +evaluate the first behavior according to the current @code(*warp*). +Evaluate each successive behavior with @code(*warp*) modified to shift the +new note's starting time to the ending time of the previous behavior. +Restore @code(*warp*) to its original value and return a sound which is the +sum of the results. + +In the Nyquist implementation, audio samples are only computed when they are +needed, and the second part of the @code(seq) is not evaluated until the +ending time (called the logical stop time) of the first part. It is still +the case that when the second part is evaluated, it will see @code(*warp*) +bound to the ending time of the first part. + +A language detail: Even though Nyquist defers evaluation of the second part of the @code(seq), the expression can reference variables according to ordinary +Lisp/SAL scope rules. This is because the @code(seq) captures the expression in a closure, which retains all of the variable bindings. + +@section(Simultaneous Behavior)@index(Simultaneous Behavior) +Another operator is @code(sim), which invokes multiple behaviors at the same +time. For example, +@begin(example) +play 0.5 * sim(my-note(c4, q), my-note(d4, i)) +@end(example) +will play both notes starting at the same time. + +The operational rule for @code(sim) is: evaluate each behavior at the +current @code(*warp*) and return the sum of the results. (In SAL, the +@code(sim) function applied to sounds is equivalent to adding them +with the infix @code(+) operator. The following section +illustrates two concepts: first, a @i(sound) is not a +@i(behavior), and second, the @code(sim) operator and and the @code(at) +transformation can be used to place sounds in time. + +@section(Sounds vs. Behaviors)@index(Sounds vs. Behaviors) +The following example loads a sound from a file in the current directory and stores it in @code(a-snd): +@begin(example) +@i[; load a sound +;] +set a-snd = s-read(strcat(current-path(), "demo-snd.aiff")) + +@i[; play it +;] +play a-snd +@end(example) + +One +might then be tempted to write the following: +@begin(example) +play seq(a-snd, a-snd) @i(;WRONG!) +@end(example) +Why is this wrong? Recall +that @code(seq) works by modifying @code(*warp*), not by operating on +sounds. So, @code(seq) will proceed by evaluating @code(a-snd) with +different values of @code(*warp*). However, the result of evaluating +@code(a-snd) (a variable) is always the same sound, regardless of the +environment; in this case, the second @code(a-snd) @i(should) start at time +@code(0.0), just like the first. In this case, after the first sound ends, + Nyquist is unable to ``back up'' to time zero, so in fact, this @i(will) +play two sounds in sequence, but that is a result of an implementation +detail rather than correct program execution. In fact, a future version of +Nyquist might (correctly) stop and report an error when it detects that the +second sound in the sequence has a real start time that is before the +requested one. + +How then do we obtain a sequence of two sounds properly? +What we really need here is a +behavior that transforms a given sound according to the current +transformation environment. That job is performed by @code(cue). For +example, the following will behave as expected, producing a sequence of two +sounds: +@begin(example) +play seq(cue(a-snd), cue(a-snd)) +@end(example) +This example is correct because the second expression will shift the sound + stored in @code(a-snd) to start at the end time of the first expression. + +The lesson here is very important: @p(sounds are not behaviors!) Behaviors +are computations that generate sounds according to the transformation +environment. Once a sound has been generated, it can be stored, copied, +added to other sounds, and used in many other operations, but sounds are +@i(not) subject to transformations. To transform a sound, use @code(cue), +@code(sound), or @code(control). The differences between these operations +are discussed later. For now, here is a ``cue sheet'' style score that +plays 4 copies of @code(a-snd): + +@begin(example) +@i[; use sim and at to place sounds in time +;] +play sim(cue(a-snd) @@ 0.0, + cue(a-snd) @@ 0.7, + cue(a-snd) @@ 1.0, + cue(a-snd) @@ 1.2) +@end(example) + +@section(The At Transformation)@index(At Transformation) +The second concept introduced by the previous example is the @code(@@) +operation, which shifts the @code(*warp*) component of the environment. For +example, +@begin(example) +cue(a-snd) @@ 0.7 +@end(example) +can be explained operationally as follows: modify @code[*warp*] by shifting +it by @code(0.7) and evaluate @code[cue(a-snd)]. Return the resulting sound +after restoring @code(*warp*) to its original value. Notice how @code(@@) +is used inside a @code(sim) construct to locate copies of @code(a-snd) in +time. This is the standard way to represent a note-list or a cue-sheet in +Nyquist. + +This also explains why sounds need to be @code(cue)'d in order to be shifted +in time or arranged in sequence. If this were not the case, then @code(sim) +would take all of its parameters (a set of sounds) and line them up to start +at the same time. But @code[cue(a-snd) @@ 0.7] is just a sound, so +@code(sim) would ``undo'' the effect of @code(@@), making all of the sounds +in the previous example start simultaneously, in spite of the @code(@@)! +Since @code(sim) respects the intrinsic starting times of sounds, a special +operation, @code(cue), is needed to create a new sound with a new starting +time. + +@section(The Stretch Transformation)@index(Stretch Transformation) +In addition to At (denoted in SAL by the @code(@@) operator, the Stretch +transformation is very important. It appeared in the introduction, and +it is denoted in SAL by the @code(~) operator (or in LISP by the @code(stretch) +special form). Stretch also operates on the @code(*warp*) component of +the environment. For example, +@begin(example) +osc(c4) ~ 3 +@end(example) +does the following: modify @code(*warp*), scaling the degree of +"stretch" by 3, and evaluate @code[osc(c4)]. The @code(osc) behavior +uses the stretch factor to determime the duration, so it will return +a sound that is 3 seconds long. Restore @code(*warp*) to its original +value. Like At, Stretch only affects behaviors. @code(a-snd ~ 10) is +equivalent to @code(a-snd) because @code(a-snd) is a sound, not a +behavior. Behaviors are functions that compute sounds according to +the environment and return a sound. + +@section(Nested Transformations)@index(Nested Transformations) +Transformations can be combined using nested expressions. For example, +@begin(example) +sim(cue(a-snd), + loud(6.0, cue(a-snd) @@ 3)) +@end(example) +scales the amplitude as well as shifts the second entrance of @code(a-snd). + +Why use @code(loud) instead of simply multiplying @code(a-snd) by some +scale factor? Using @code(loud) gives +the behavior the chance to implement the abstract +property @i(loudness) in an appropriate way, e.g. by including timbral +changes. In this case, the behavior is @code(cue), which implements +@i(loudness) by simple amplitude scaling, so the result is equivalent +to multiplication by @code(db-to-linear(6.0)). + +Transformations can also be applied to groups of behaviors: +@begin(example) +loud(6.0, sim(cue(a-snd) @@ 0.0, + cue(a-snd) @@ 0.7)) +@end(example) + +@section(Defining Behaviors)@index(Defining Behaviors) +Groups of behaviors can be named using @code(define) (we already saw this +in the definitions of @code(my-note) and @code(env-note)). Here is another example +of a behavior definition and its use. The definition has one parameter: +@begin(example) +define function snds(dly) + return sim(cue(a-snd) @@ 0.0, + cue(a-snd) @@ 0.7, + cue(a-snd) @@ 1.0, + cue(a-snd) @@ (1.2 + dly)) + +play snds(0.1) +play loud(0.25, snds(0.3) ~ 0.9) +@end(example) +In the last line, @code(snds) is transformed: the transformations will apply +to the @code(cue) behaviors within @code(snds). The @code(loud) +transformation will scale the sounds by @code(0.25), and the @i(stretch) +(@code(~)) will +apply to the shift (@code(@@)) amounts @code(0.0), @code(0.7), @code(1.0), +and @code[1.2 + dly]. The sounds themselves (copies of @code(a-snd)) will +not be stretched because @code(cue) never stretches sounds. + +Section @ref(transformations-sec) describes the full set of transformations. + +@section(Overriding Default Transformations) +In Nyquist, behaviors are @i(the) important abstraction mechanism. +A behavior represents a class of related functions or sounds. For example, +a behavior can represent a musical note. When a note is stretched, it +usually means that the tone sustains for more oscillations, but if the +``note'' is a drum roll, the note sustains by more repetitions of the +component drum strokes. The concept of sustain is so fundamental that +we do not really think of different note durations as being different +instances of an abstract behavior, but in a music programming language, +we need a way to model these abtract behaviors. As the tone and drum +roll examples show, there is no one right way to ``stretch,'' so the +language must allow users to define exactly what it means to stretch. +By extension, the Nyquist programmer can define how all of the +transformations affect different behaviors. + +To make programming easier, almost all Nyquist sounds are constructed +from primitive behaviors that obey the environment in obvious ways: +Stretch transformations make things longer and At transformations shift +things in time. But sometimes you have to override the default behaviors. +Maybe the attack phase of an envelope should not stretch when the note +is stretched, or maybe when you stretch a trill, you should get more +notes rather than a slower trill. + +To override default behaviors, you almost always follow the same +programming pattern: first, capture the environment in a local variable; +then, use one of the absolute transformations to ``turn off'' the +environment's effect and compute the sound as desired. The following +example creates a very simple envelope with a fixed rise time to +illustrate the technique. +@begin(example) +define function two-phase-env(rise-time) + begin + with dur = get-duration(1) + return pwl(rise-time, 1, dur) ~~ 1.0 + end +@end(example) +To ``capture the environment in a local variable,'' a @code(with) +construct is used to create the local variable @code(dur) and set +it to the value of @code[get-duration(1)], which answers the question: +``If I apply use the environment to stretch something whose nominal +duration is 1, what is the resulting duration?'' (Since time transformations +can involve continuous time deformations, this question is not as +simple as it may sound, so please use the provided function rather +than peeking inside the @code(*warp*) structure and trying to do it +yourself.) Next, we ``turn off'' stretching using the @code(stretch-abs) +form, which in SAL is denoted by the @code(~~) operator. +Finally, we are ready to compute the envelope using @code(pwl). Here, +we use absolute durations. The first breakpoint is at @code(rise-time), +so the attack time is given by the @code(rise-time) parameter. The +@code(pwl) decays back to zero at time @code(dur), so the overall +duration matches the duration expected from the environment encountered +by this instance of @code(two-phase-env). Note, however, that since +the @code(pwl) is evaluated in a different environment established +by @code(~~), it is not stretched (or perhaps more accurately, it is +stretched by 1.0). This is good because it means @code(rise-time) will +not be stretched, but we must be careful to extend the envelope to +@code(dur) so that it has the expected duration. + +@section(Sample Rates) +@index(sample rates) +The global environment contains @code(*sound-srate*) and +@code(*control-srate*), which determine the sample rates of sounds and +control signals. These can be overridden at any point by the +transformations @code(sound-srate-abs) and @code(control-srate-abs); for +example, +@begin(example) +sound-srate-abs(44100.0, osc(c4) +@end(example) +will compute a tone using a 44.1Khz sample rate even if the default rate +is set to something different. + +@index(default sample rate) +As with other components of the environment, you should @i(never) change +@code(*sound-srate*) or @code(*control-srate*) directly. + The global environment is determined by two additional +variables: @code(*default-sound-srate*) and @code(*default-control-srate*). +You can add lines like the following to your @code(init.lsp) file to change +the default global environment: +@begin(example) +(setf *default-sound-srate* 44100.0) +(setf *default-control-srate* 1102.5) +@end(example) +You can also do this using preferences in NyquistIDE. +If you have already started Nyquist and want to change the defaults, the +preferences or the following functions can be used: +@begin(example) +exec set-control-srate(1102.5)@index(set-control-srate) +exec set-sound-srate(22050.0)@index(set-sound-srate) +@end(example) +These modify the default values and reinitialize the Nyquist environment. + + +@chapter(Continuous Transformations and Time Warps) +@label(warp-chap) +Nyquist transformations were discussed in the previous chapter, but all of +the examples used scalar values. For example, we saw the @code[loud] +transformation used to change loudness by a fixed amount. What if we want +to specify a crescendo, where the loudness changes gradually over time? + +It turns out that all transformations can accept signals as well as numbers, +so transformations can be continuous over time. This raises some +interesting questions about how to interpret continuous transformations. +Should a loudness transformation apply to the internal details of a note or +only affect the initial loudness? It might seem unnatural for a decaying +piano note to perform a crescendo. On the other hand, a sustained +trumpet sound should probably crescendo continuously. In the case of time +warping (tempo changes), it might be best for a drum roll to maintain a +steady rate, a trill may or may not change rates with tempo, and a run of +sixteenth notes will surely change its rate. + +These issues are complex, and Nyquist cannot hope to automatically do the +right thing in all cases. However, the concept of behavioral abstraction +provides an elegant solution. Since transformations merely modify the +environment, behaviors are not forced to implement any particular style of +transformation. Nyquist is designed so that the default transformation is +usually the right one, but it is always possible to override the default +transformation to achieve a particular effect. + +@section(Simple Transformations) +The ``simple'' transformations affect some parameter, but have no effect on time itself. The simple transformations that support continuously changing parameters are: @code(sustain), @code(loud), and @code(transpose). + +As a first example, Let us use @code(transpose) to create a chromatic scale. +First define a sequence of tones at a steady pitch. The @code(seqrep) +``function'' works like @code(seq) except that it creates copies of a sound +by evaluating an expression multiple times. Here, @code(i) takes on 16 values +from 0 to 15, and the expression for the sound could potentially use @code(i). +Technically, @code(seqrep) is not really a function but an abbreviation for +a special kind of loop construct. +@begin(example) +define function tone-seq() + return seqrep(i, 16, + osc-note(c4) ~ 0.25) +@end(example) +Now define a linearly increasing ramp to serve as a transposition function: +@begin(code) +define function pitch-rise() + return sustain-abs(1.0, 16 * ramp() ~ 4) +@end(code) +This ramp has a duration of 4 seconds, and over that interval it rises from +0 to 16 (corresponding to the 16 semitones we want to transpose). The ramp +is inside a @code(sustain-abs) transformation, which prevents a @code(sustain) +transformation from having any effect on the ramp. (One of the drawbacks of +behavioral abstraction is that built-in behaviors sometimes do the wrong +thing implicitly, requiring some explicit correction to turn off the +unwanted transformation.) Now, +@code(pitch-rise) is used to transpose @code(tone-seq): +@begin(code) +define function chromatic-scale() + return transpose(pitch-rise(), tone-seq()) +@end(code) + +Similar transformations can be constructed to change the sustain or ``duty +factor'' of notes and their loudness. The following expression plays the +@code(chromatic-scale) behavior with increasing note durations. The +rhythm is unchanged, but the note length changes from staccato to legato: +@begin(code) +play sustain((0.2 + ramp()) ~ 4, + chromatic-scale()) +@end(code) +The resulting sustain function will ramp from 0.2 to 1.2. A sustain of 1.2 +denotes a 20 percent overlap between notes. The @code(sum) has a stretch +factor of 4, so it will extend over the 4 second duration of +@code(chromatic-scale). + +If you try this, you will discover that the @code(chromatic-scale) no longer +plays a chromatic scale. You will hear the first 4 notes going up in intervals +of 5 semitones (perfect fourths) followed by repeated pitches. What +is happening is that the @code(sustain) operation applies to +@code(pitch-rise) in addition to @code(tone-seq), so now the 4s +ramp from 0 to 16 becomes a 0.8s ramp. To fix this problem, we need to +shield @code(pitch-rise) from the effect of @code(sustain) using the +@code(sustain-abs) transformation. Here is a corrected version of +@code(chromatic-scale): +@begin(code) +define function chromatic-scale() + return transpose(sustain-abs(1, pitch-rise()), tone-seq()) +@end(code) + +What do these transformations mean? How did the system know to produce a +pitch rise rather than a continuous glissando? This all relates to the idea +of behavioral abstraction. It is possible to design sounds that @i(do) +glissando under the transpose transform, and you can even make sounds that +@i(ignore) transpose altogether. As explained in Chapter +@ref(behavioral-abstraction-sec), the transformations modify the +environment, and behaviors can reference the environment to determine what +signals to generate. All built-in functions, such as @code(osc), have a +default behavior. + +The default behavior for sound primitives under @code(transpose), +@code(sustain), and @code(loud) transformations is +to sample the environment at the beginning of the +note. Transposition is not quantized to semitones or any other scale, +but in our example, we arranged for the transposition to work out to integer +numbers of semitones, so we obtained a chromatic scale anyway. + +Transposition only applies to the oscillator and sampling primitives +@code(osc), @code(partial), @code(sampler), @code(sine), @code(fmosc), +and @code(amosc). Sustain applies to @code(osc), @code(env), @code(ramp), +and @code(pwl). (Note that @code(partial), @code(amosc), and +@code(fmosc) get their durations +from the modulation signal, so they may indirectly depend upon the sustain.) +Loud applies to @code(osc), @code(sampler), @code(cue), @code(sound), +@code(fmosc), and @code(amosc). (But not @code(pwl) or @code(env).) + + +@section(Time Warps) +The most interesting transformations have to do with transforming time +itself. The @code(warp) transformation provides a mapping function from +logical (score) time to real time. The slope of this function tells us how +many units of real time are covered by one unit of score time. This is +proportional to 1/tempo. A higher slope corresponds to a slower tempo. + +To demonstrate @code(warp), we will define a time warp function using +@code(pwl): +@begin(example) +define function warper() + return pwl(0.25, .4, .75, .6, 1.0, 1.0, 2.0, 2.0, 2.0) +@end(example) +This function has an initial slope of .4/.25 = 1.6. It may be easier to +think in reciprocal terms: the initial tempo is .25/.4 = .625. Between 0.25 +and 0.75, the tempo is .5/.2 = 2.5, and from 0.75 to 1.0, the tempo is again +.625. It is important for warp functions to completely span the interval of +interest (in our case it will be 0 to 1), and it is safest to extend a bit +beyond the interval, so we extend the function on to 2.0 with a +tempo of 1.0. Next, we stretch and scale the @code(warper) function to +cover 4 seconds of score time and 4 seconds of real time: +@begin(example) +define function warp4() + return 4 * warper() ~ 4 +@end(example) + +@begin(figure) +@center(@graphic((height = 3.25 in, width = 3.5 in, magnify = 0.5, + postscript = "warpfig.ps")) +@html(

) +@fillcaption{The result of @code[(warp4)], intended to map 4 seconds of +score time into 4 seconds of real time. The function extends beyond 4 +seconds (the dashed lines) to make sure the function is well-defined at +location (4, 4). Nyquist sounds are ordinarily open on the right.} +@tag(warp-fig) +@end(figure) + +Figure @ref(warp-fig) shows a plot of this warp function. Now, we can +warp the tempo of the @code(tone-seq) defined above using @code(warp4): +@begin(example) +play warp(warp4(), tone-seq()) +@end(example) +Figure @ref(warp-notes-fig) shows the result graphically. Notice that the +durations of the tones are warped as well as their onsets. Envelopes are +not shown in detail in the figure. Because of the way @code(env) is +defined, the tones will have constant attack and decay times, and the +sustain will be adjusted to fit the available time. + +@begin(figure) +@center(@graphic((height = 1.75 in, width = 6.75 in, magnify = 1.0, + postscript = "warpnotesfig.ps")) +@html(

) +@fillcaption[When @code{(warp4)} is applied to @code{(tone-seq-2)}, the note onsets and durations are warped.] +@tag(warp-notes-fig) +@end(figure) + +@section(Abstract Time Warps) +We have seen a number of examples where the default behavior did the +``right thing,'' making the code straightforward. This is not always the +case. Suppose we want to warp the note onsets but not the durations. We +will first look at an incorrect solution and discuss the error. Then we +will look at a slightly more complex (but correct) solution. + +The default behavior for most Nyquist built-in functions is to sample the +time warp function at the nominal starting and ending score times of the +primitive. For many built-in functions, including @code(osc), the starting +logical time is 0 and the ending logical time is 1, so the time warp +function is evaluated at these points to yield real starting and stopping +times, say 15.23 and 16.79. The difference (e.g. 1.56) becomes the signal +duration, and there is no internal time warping. The @code(pwl) function +behaves a little differently. Here, each breakpoint is warped individually, +but the resulting function is linear between the breakpoints. + +A consequence of the default behavior is that notes stretch when the tempo +slows down. Returning to our example, recall that we want to warp only the +note onset times and not the duration. One would think that the following +would work: +@begin(example) +define function tone-seq-2 () + return seqrep(i, 16, + osc-note(c4) ~~ 0.25) + +play warp(warp4(), tone-seq-2()) +@end(example) +Here, we have redefined @code(tone-seq), renaming it to @code(tone-seq-2) +and changing the stretch (@code(~)) to absolute stretch (@code(~~)). The +absolute stretch should override the warp function and produce a fixed +duration. + +If you play the example, you will hear steady +sixteenths and no tempo changes. What is wrong? In a sense, the ``fix'' +works too well. Recall that sequences (including @code(seqrep)) determine +the starting time of the next note from the logical stop time of the +previous sound in the sequence. When we forced the stretch to 0.25, we also +forced the logical stop time to 0.25 real seconds from the beginning, so +every note starts 0.25 seconds after the previous one, resulting in a +constant tempo. + +Now let us design a proper solution. The trick is to use absolute +stretch (@code(~~)) +as before to control the duration, but to restore the logical stop time to a +value that results in the proper inter-onset time interval: +@begin(example) +define function tone-seq-3() + return seqrep(i, 16, + set-logical-stop(osc-note(c4) ~~ 0.25, 0.25)) + +play warp(warp4(), tone-seq-3()) +@end(example) +Notice the addition of @code(set-logical-stop) enclosing the +absolute stretch (@code(~~)) expression to set the logical + stop time. A possible +point of confusion here is that the logical stop time is set to 0.25, the +same number given to @code(~~)! How does setting the logical stop +time to 0.25 result in a tempo change? When used within a @code(warp) +transformation, the second argument to @code(set-logical-stop) refers to +@i(score) time rather than @i(real) time. Therefore, the score duration of +0.25 is warped into real time, producing tempo changes according to the +enviroment. Figure @ref(warp-onset-fig) illustrates the result graphically. + +@begin(figure) +@center(@graphic((height = 1.75 in, width = 6.75 in, magnify = 1.0, + postscript = "warponsetfig.ps")) +@html(

) +@fillcaption[When @code[(warp4)] is applied +to @code[(tone-seq-3)], the note onsets are warped, but not the duration, +which remains a constant 0.25 seconds. In the fast middle section, this +causes notes to overlap. Nyquist will sum (mix) them.] +@tag(warp-onset-fig) +@end(figure) + +@section(Nested Transformations) +Transformations can be nested. In particular, a simple transformation such +as transpose can be nested within a time warp transformation. Suppose we +want to warp our chromatic scale example with the @code(warp4) time warp +function. As in the previous section, we will show an erroneous simple +solution followed by a correct one. + +The simplest approach to a nested transformation is to simply combine them +and hope for the best: +@begin(example) +play warp(warp4(), + transpose(pitch-rise(), tone-seq())) +@end(example) +This example will not work the way you might expect. Here is why: the warp +transformation applies to the @code[(pitch-rise)] expression, which is +implemented using the @code(ramp) function. The default +behavior of @code(ramp) is to interpolate linearly (in real time) between two points. +Thus, the ``warped'' @code(ramp) function will not truly reflect the internal +details of the intended time warp. When the notes are moving faster, they +will be closer together in pitch, and the result is not chromatic. +What we need is a way to properly +compose the warp and ramp functions. If we continuously warp the ramp function +in the same way as the note sequence, a chromatic scale should be obtained. +This will lead to a correct solution. + +Here is the modified code to properly warp a transposed sequence. Note that +the original sequence is used without modification. The only complication +is producing a properly warped transposition function: +@begin(example) + play warp(warp4(), + transpose( + control-warp(get-warp(), + warp-abs(nil, pitch-rise())), + tone-seq())) +@end(example) +To properly warp the @code(pitch-rise) transposition function, we use +@code(control-warp), which applies a warp function to a function of score time, +yielding a function of real time. We need to pass the desired function +to @code(control-warp), so we fetch it from the environment with +@code[get-warp()]. Finally, since the warping is done here, we want to +shield the @code(pitch-rise) expression from further warping, so we enclose +it in @code[warp-abs(nil, ...)]. + + @i(An aside:) This last example illustrates a difficulty in the design of +Nyquist. To support behavioral abstraction universally, we must rely upon +behaviors to ``do the right thing.'' In this case, we would like the +@code(ramp) function to warp continuously according to the environment. But +this is inefficient and unnecessary in many other cases where @code(ramp) +and especially @code(pwl) are used. (@code(pwl) warps its breakpoints, but still interpolates linearly between them.) Also, if the default behavior of +primitives is to warp in a continuous manner, this makes it difficult to +build custom abstract behaviors. The final vote is not in. + +@chapter(More Examples) + +This chapter explores Nyquist through additional examples. The reader may +wish to browse through these and move on to Chapter @ref(lisp-chap), which +is a reference section describing Nyquist functions. + +@section(Stretching Sampled Sounds)@index(Stretching Sampled Sounds) + +This example illustrates how to stretch a sound, resampling it in the process. +Because sounds in Nyquist are @i(values) that contain the sample rate, start +time, etc., use @code(sound) to convert a sound into a behavior that can be +stretched, e.g. @code[sound(a-snd)]. This behavior stretches a sound according +to the stretch factor in the environment, set using @code(stretch). For +accuracy and efficiency, Nyquist does not resample a stretched sound until +absolutely necessary. The @code(force-srate) function is used to resample +the result so that we end up with a ``normal'' sample rate that is playable +on ordinary sound cards. + +@begin(example) +@i[; if a-snd is not loaded, load sound sample: +;] +if not(boundp(quote(a-snd))) then + set a-snd = s-read("demo-snd.aiff") + +@i[; the SOUND operator shifts, stretches, clips and scales +; a sound according to the current environment +;] +define function ex23() + play force-srate(*default-sound-srate*, sound(a-snd) ~ 3.0) + +define function down() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.2, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.6)) +play down() + +@i[; that was so much fun, let's go back up: +;] +define function up() + return force-srate(*default-sound-srate*, + seq(sound(a-snd) ~ 0.5, + sound(a-snd) ~ 0.4, + sound(a-snd) ~ 0.3, + sound(a-snd) ~ 0.2)) + +@i[; and write a sequence +;] +play seq(down(), up(), down()) +@end(example) + +Notice the use of the @code(sound) behavior as opposed to @code(cue). The +@code(cue) behavior shifts and scales its sound according to @code(*warp*) +and @code(*loud*), but it does not change the duration or resample the +sound. In contrast, @code(sound) not only shifts and scales its sound, but +it also stretches it by resampling or changing the effective sample rate + according to @code(*warp*). If +@code[*warp*] is a continuous warping function, then the sound will be +stretched by time-varying amounts. +(The @code(*transpose*) element of the environment is +ignored by both @code(cue) and @code(sound).) + +@p(Note:) @code(sound) may use linear interpolation rather than a high-quality resampling algorithm. In some cases, this may introduce errors audible as noise. Use @code(resample) (see Section @ref(resample-sec)) for high-quality interpolation. + +In the functions @code(up) and @code(down), the @code(*warp*) is set by +@i(stretch) (@code(~)), which simply scales time by a constant scale factor. In this case, +@code(sound) can ``stretch'' the signal simply by changing the sample rate without +any further computation. When @code(seq) tries to add the signals together, it +discovers the sample rates do not match and uses linear interpolation to adjust +all sample rates to match that of the first sound in the sequence. The result of +@code(seq) is then converted using @code(force-srate) to convert the sample rate, +again using linear interpolation. +It would be slightly better, from a computational +standpoint, to apply @code(force-srate) individually +to each stretched sound rather +than applying @code(force-srate) after @code(seq). + +Notice that the overall duration of @code[sound(a-snd) ~ 0.5] will +be half the duration of @code(a-snd). + +@section(Saving Sound Files)@index(Saving Sound Files) + +So far, we have used the @code(play) command to play a sound. The +@code(play) command works by writing a sound to a file while +simultaneously playing it. +This can be done one step at a time, and +it is often convenient to save a sound to a particular file for later use: +@begin(example) +@i[; write the sample to a file, +; the file name can be any Unix filename. Prepending a "./" tells +; s-save to not prepend *default-sf-dir* +;] +exec s-save(a-snd, 1000000000, "./a-snd-file.snd") + +@i[; play a file +; play command normally expects an expression for a sound +; but if you pass it a string, it will open and play a +; sound file] +play "./a-snd-file.snd" + +@i[; delete the file (do this with care!) +; only works under Unix (not Windows)] +exec system("rm ./a-snd-file.snd") + +@i[; now let's do it using a variable as the file name +;] +set my-sound-file = "./a-snd-file.snd" + +exec s-save(a-snd, 1000000000, my-sound-file) + +@i[; play-file is a function to open and play a sound file] +exec play-file(my-sound-file) + +exec system(strcat("rm ", my-sound-file)) +@end(example) +This example shows how @code(s-save) can be used to save a sound to a file. + +This example also shows how the @code(system) function can be used to invoke +Unix shell commands, such as a command to play a file or remove it. +Finally, notice that @code(strcat) can be used to concatenate a command name +to a file name to create a complete command that is then passed to +@code(system). (This is convenient if the sound file name is stored in a +parameter or variable.) + +@section(Memory Space and Normalization) +@label(normalization-sec) +@index(normalization)@index(peak amplitude)@index(maximum amplitude)@index(clip)@index(s-max)@index(s-min)@index(rescaling)@index(not enough memory for normalization) +Sound samples take up lots of memory, and often, there is not enough primary (RAM) memory to hold a complete composition. For this reason, Nyquist can compute sounds incrementally, saving the final result on disk. @i(However,) Nyquist can also save sounds in memory so that they can be reused efficiently. In general, if a sound is saved in a global variable, memory will be allocated as needed to save and reuse it. + +The standard way to compute a sound and write it to disk is to pass an expression to the @code(play) command: +@begin(example) +play my-composition() +@end(example) + +@label(peak-ex-sec) +Often it is nice to @i(normalize) sounds so that they use the full available +dynamic range of 16 bits. Nyquist has an automated facility to help with +normalization. By default, Nyquist computes up to 1 million samples (using +about 4MB of memory) looking for the peak. The entire sound is normalized so +that this peak will not cause clipping. If the sound has less than 1 million +samples, or if the first million samples are a good indication of the overall +peak, then the signal will not clip. + +With this automated normalization technique, you can choose the desired +peak value by setting @code(*autonorm-target*), which is initialized to 0.9. +The number of samples examined is @code(*autonorm-max-samples*), initially +1 million. You can turn this feature off by executing: +@begin(example) +exec autonorm-off()@index(autonorm-off) +@end(example) +and turn it back on by typing: +@begin(example) +exec autonorm-on()@index(autonorm-on) +@end(example) +This normalization technique is in effect when @code(*autonorm-type*) is +@code(quote(lookahead)), which is the default. + +An alternative normalization method uses the peak value from the previous +call to @code(play). After playing a file, Nyquist can adjust an internal +scale factor so that if you play the same file again, the peak amplitude +will be @code(*autonorm-target*), which is initialized to 0.9. This can +be useful if you want to carefully normalize a big sound that does not +have its peak near the beginning. To select this style of normalization, +set @code(*autonorm-type*) to the (quoted) atom @code(quote(previous)). + +You can also create your own normalization method in Nyquist. +The @code(peak) function computes the maximum value of a sound. +The peak value is also returned from the @code(play) macro. You can +normalize in memory if you have enough memory; otherwise you can compute +the sound twice. The two techniques are illustrated here: +@begin(example) +@i[; normalize in memory. First, assign the sound to a variable so +; it will be retained:] +set mysound = sim(osc(c4), osc(c5)) +@i[; now compute the maximum value (ny:all is 1 giga-samples, you may want a +; smaller constant if you have less than 4GB of memory:] +set mymax = snd-max(mysound, NY:ALL) +display "Computed max", mymax +@i[; now write out and play the sound from memory with a scale factor:] +play mysound * (0.9 / mymax) + +@i[; if you don't have space in memory, here's how to do it:] +define function myscore() + return sim(osc(c4), osc(c5)) +@i[; compute the maximum:] +set mymax = snd-max(list(quote(myscore)), NY:ALL) +display "Computed max", mymax +@i[; now we know the max, but we don't have a the sound (it was garbage +; collected and never existed all at once in memory). Compute the sound +; again, this time with a scale factor:] +play myscore() * (0.9 / mymax) +@end(example) + +You can also write a sound as a floating point file. This +file can then be converted to 16-bit integer with the proper scaling +applied. If a long computation was involved, it should be much faster +to scale the saved sound file than to recompute the sound from scratch. +Although not implemented yet in Nyquist, some header formats can +store maximum amplitudes, and some soundfile player programs can +rescale floating point files on the fly, allowing normalized +soundfile playback without an extra normalization pass (but at a cost +of twice the disk space of 16-bit samples). +You can use Nyquist to rescale a floating point file and +convert it to 16-bit samples for playback. + +@section(Frequency Modulation)@index(Frequency Modulation) +The next example uses the Nyquist frequency modulation behavior @code(fmosc) +to generate various sounds. The parameters to @code(fmosc) are: +@begin(example) +fmosc(@i(pitch) @i(modulator) @i(table) @i(phase)) +@end(example) +Note that pitch is the number of half-steps, e.g. @code(c4) has the value of 60 which is middle-C, and phase is in degrees. Only the first two parameters are required: +@begin(example) +@i[; make a short sine tone with no frequency modulation +;] +play fmosc(c4, pwl(0.1)) + +@i[; make a longer sine tone -- note that the duration of +; the modulator determines the duration of the tone +;] +play fmosc(c4, pwl(0.5)) +@end(example) +In the example above, @code(pwl) (for Piece-Wise Linear) is used to generate +sounds that are zero for the durations of @code(0.1) and @code(0.5) seconds, +respectively. In effect, we are using an FM oscillator with no modulation +input, and the result is a sine tone. The duration of the modulation +determines the duration of the generated tone (when the modulation signal +ends, the oscillator stops). + +The next example uses a more interesting modulation function, a ramp from +zero to C@-(4), expressed in hz. More explanation of @code(pwl) is in +order. This operation constructs a piece-wise linear function sampled at +the @code(*control-srate*). The first breakpoint is always at @code[(0, +0)], so the first two parameters give the time and value of the second +breakpoint, the second two parameters give the time and value of the third +breakpoint, and so on. The last breakpoint has a value of @code(0), so only +the time of the last breakpoint is given. In this case, we want the ramp to +end at C@-(4), so we cheat a bit by having the ramp return to zero +``almost'' instantaneously between times @code(0.5) and @code(0.501). + +The @code(pwl) behavior always expects an odd number of parameters. The +resulting function is shifted and stretched linearly according to +@code[*warp*] in the environment. Now, here is the example: +@begin(example) +@i[; make a frequency sweep of one octave; the piece-wise linear function +; sweeps from 0 to (step-to-hz c4) because, when added to the c4 +; fundamental, this will double the frequency and cause an octave sweep. +;] +play fmosc(c4, pwl(0.5, step-to-hz(c4), 0.501)) +@end(Example) + +The same idea can be applied to a non-sinusoidal carrier. Here, we assume that @code(*fm-voice*) is predefined (the next section shows how to define it): +@begin(example) +@i[; do the same thing with a non-sine table +;] +play fmosc(cs2, pwl(0.5, step-to-hz(cs2), 0.501), + *fm-voice*, 0.0) +@end(example) + +The next example shows how a function can be used to make a special +frequency modulation contour. In this case the contour generates a sweep +from a starting pitch to a destination pitch: +@begin(example) +@i[; make a function to give a frequency sweep, starting +; after seconds, then sweeping from +; to in seconds and then +; holding at for seconds. +;] +define function sweep(delay, pitch-1, sweep-time, + pitch-2, hold-time) + begin + with interval = step-to-hz(pitch-2) - step-to-hz(pitch-1) + return pwl(delay, 0.0, + @i[; sweep from pitch 1 to pitch 2] + delay + sweep-time, interval, + @i[; hold until about 1 sample from the end] + delay + sweep-time + hold-time - 0.0005, + interval, + @i[; quickly ramp to zero (pwl always does this,] + @i[; so make it short)] + delay + sweep-time + hold-time) + end + + +@i[; now try it out +;] +play fmosc(cs2, sweep(0.1, cs2, 0.6, gs2, 0.5), + *fm-voice*, 0.0) +@end(example) + +FM can be used for vibrato as well as frequency sweeps. Here, we use the +@code(lfo) function to generate vibrato. The @code(lfo) operation is +similar to @code(osc), except it generates sounds at the +@code(*control-srate*), and the parameter is hz rather than a pitch: +@begin(example) +play fmosc(cs2, 10.0 * lfo(6.0), *fm-voice*, 0.0) +@end(Example) + +What kind of manual would this be without the obligatory FM sound? Here, a +sinusoidal modulator (frequency C@-(4)) is multiplied by a slowly increasing +ramp from zero to @code(1000.0). +@begin(example) +set modulator = pwl(1.0, 1000.0, 1.0005) * + osc(c4) +@i[; make the sound] +play fmosc(c4, modulator) +@end(example) + +For more simple examples of FM in Nyquist, see +@index(warble)@index(FM synthesis)@index(demos, FM)@index(tutorial, FM) +@code(demos/warble_tutorial.htm). Another interesting FM sound +reminiscent of ``scratching'' can be found with a detailed explanation +in @code(demos/scratch_tutorial.htm).@index(demos, scratch tutorial) +@index(vinal scratch)@index(scratch sound). + +@section(Building a Wavetable) +In Section @ref(waveform-sec), we saw how to synthesize a wavetable. A +wavetable for @code(osc) also can be extracted from any sound. This is +especially interesting if the sound is digitized from some external sound +source and loaded using the @code(s-read) function. Recall that a table +is a list consisting of a sound, the pitch of that sound, and T (meaning the +sound is periodic). + +In the following, a sound is first read from the file @code(demo-snd.nh). +Then, the @code(extract) function is used +to extract the portion of the sound between 0.110204 and 0.13932 seconds. +(These numbers might be obtained by first plotting the sound and estimating +the beginning and end of a period, or by using some software to look for +good zero crossings.) The result of @code(extract) becomes the first +element of a list. The next element is the pitch (24.848422), and the last +element is @code(T). The list is assigned to @code(*fm-voice*). +@begin(example) +if not(boundp(quote(a-snd))) then + set a-snd = s-read("demo-snd.aiff") + +set *fm-voice* = list(extract(0.110204, 0.13932, cue(a-snd)), + 24.848422, + #T) +@end(example) + +The file +@i(demos/examples.sal) contains an extensive example of how to locate +zero-crossings, extract a period, build a waveform, and generate a tone from it. (See @code(ex37) through @code(ex40) in the file.) + +@begin(comment) +The @code(maketable) command is also useful and is documented on page +@ref(maketable). If @code(sample) is the source sound, then the following +will extract 0.01 seconds (starting at time 0.2s) of audio and convert it +into a waveform named @code(mytable): +@begin(example) +(setf mytable (maketable (extract -abs 0.2 0.21 sample))) +@end(example) +Nyquist does not provide any pitch analysis or other help finding good splice points, so it is up to you to make sure the table you extract is a reasonable one. +@end(comment) + +@section(Filter Examples) + +Nyquist provides a variety of filters. All of these filters take either +real numbers or signals as parameters. If you pass a signal as a filter +parameter, the filter coefficients are recomputed at the sample rate of the +@i(control) signal. Since filter coefficients are generally expensive to +compute, you may want to select filter control rates carefully. Use +@code(control-srate-abs) (Section @ref(control-srate-abs-sec)) to specify +the default control sample rate, or use @code(force-srate) (Section +@ref(force-srate-sec)) to resample a signal before passing it to a filter. + +Before presenting examples, let's generate some unfiltered white noise: +@begin(example) +play noise() +@end(example) +Now low-pass filter the noise with a 1000Hz cutoff: +@begin(example) +play lp(noise(), 1000.0) +@end(example) +The high-pass filter is the inverse of the low-pass: +@begin(example) +play hp(noise(), 1000.0) +@end(example) + +Here is a low-pass filter sweep from 100Hz to 2000Hz: +@begin(example) +play lp(noise(), pwl(0.0, 100.0, 1.0, 2000.0, 1.0)) +@end(example) +And a high-pass sweep from 50Hz to 4000Hz: +@begin(example) +play hp(noise(), pwl(0.0, 50.0, 1.0, 4000.0, 1.0)) +@end(example) + +The band-pass filter takes a center frequency and a bandwidth parameter. +This example has a 500Hz center frequency with a 20Hz bandwidth. The scale +factor is necessary because, due to the resonant peak of the filter, the +signal amplitude exceeds 1.0: +@begin(example) +play reson(10.0 * noise(), 500.0, 20.0, 1) +@end(example) +In the next example, the center frequency is swept from 100 to 1000Hz, using a constant 20Hz bandwidth: +@begin(example) +play reson(0.04 * noise(), + pwl(0.0, 200.0, 1.0, 1000.0, 1.0), + 20.0) +@end(example) + +For another example with explanations, see +@index(wind_tutorial.htm)@index(wind sound)@index(filter example) +@index(demos, wind sound) +@code(demos/wind_tutorial.htm). + + +@section(DSP in Lisp) +@index(DSP in Lisp)@index(Lisp DSP)In almost any +signal processing system, the vast majority of computation +takes place in the inner loops of DSP algorithms, and Nyquist is designed so +that these time-consuming inner loops are in highly-optimized +machine code rather than relatively slow interpreted lisp code. As a result, +Nyquist typically spends 95% of its time in these inner loops; the overhead +of using a Lisp interpreter is negligible. + +The drawback is that Nyquist must provide the DSP operations you need, or +you are out of luck. When Nyquist is found lacking, you can either write a +new primitive signal operation, or you can perform DSP in Lisp code. Neither +option is recommended for inexperienced programmers. Instructions for +extending Nyquist are given in Appendix @ref(extending-app). This section +describes the process of writing a new signal processing function in Lisp. + +Before implementing a new DSP function, you should decide which approach is +best. First, figure out how much of the new function can be implemented +using existing Nyquist functions. For example, you might think that a +tapped-delay line would require a new function, but in fact, it can be +implemented by composing sound transformations to accomplish delays, scale +factors for attenuation, and additions to combine the intermediate results. +This can all be packaged into a new Lisp function, making it easy to use. +If the function relies on built-in DSP primitives, it will execute very +efficiently. + +Assuming that built-in functions cannot be used, try to define a new +operation that will be both simple and general. Usually, it makes sense to +implement only the kernel of what you need, combining it with existing +functions to build a complete instrument or operation. For example, if you +want to implement a physical model that requires a varying breath pressure +with noise and vibrato, plan to use Nyquist functions to add a basic +pressure envelope to noise and vibrato signals to come up with a composite +pressure signal. Pass that signal into the physical model rather than +synthesizing the envelope, noise, and vibrato within the model. This not +only simplifies the model, but gives you the flexibility to use all of +Nyquist's operations to synthesize a suitable breath pressure signal. + +Having designed the new ``kernel'' DSP operation that must be implemented, +decide whether to use C or Lisp. (At present, SAL is not a good option +because it has no support for object-oriented programming.) +To use C, you must have a C compiler, the +full source code for Nyquist, and you must learn about extending Nyquist by +reading Appendix @ref(extending-app). This is the more complex approach, but +the result will be very efficient. A C implementation will deal properly +with sounds that are not time-aligned or matched in sample rates. +To use Lisp, you must learn something +about the XLISP object system, and the result will be about 50 times slower +than C. Also, it is more difficult to deal with time alignment and +differences in sample rates. +The remainder of this section gives an example of a Lisp version of +@code(snd-prod) to illustrate how to write DSP functions for Nyquist in Lisp. + +The @code(snd-prod) function is the low-level multiply routine. It has two +sound parameters and returns a sound which is the product of the two. To +keep things simple, we will assume that two sounds to be multiplied have a +matched sample rate and matching start times. The DSP algorithm for each +output sample is simply to fetch a sample from each sound, multiply them, +and return the product. + +To implement @code(snd-prod) in Lisp, three components are required: +@begin(enumerate) +An object is used to store the two parameter sounds. This object will be +called upon to yield samples of the result sound; + +Within the object, the @code(snd-fetch) routine is used to fetch samples +from the two input sounds as needed; + +The result must be of type @code(SOUND), so @code(snd-fromobject) is used +to create the result sound. +@end(enumerate) + +The combined solution will work as follows: The result is a value of type +@code(sound) that retains a reference to the object. When Nyquist needs +samples from the sound, it invokes the sound's ``fetch'' function, which in +turn sends an XLISP message to the object. The object will use +@code(snd-fetch) to get a sample from each stored sound, multiply the +samples, and return a result. + +Thus the goal is to design an XLISP object that, in response to a +@code(:next) message will return a proper sequence of samples. When the +sound reaches the termination time, simply return @code(NIL). + +The XLISP manual (see Appendix @ref(XLISP-app) describes the object system, +but in a very terse style, so this example will include some explanation of +how the object system is used. First, we need to define a class for the +objects that will compute sound products. Every class is a subclass of class +@code(class), and you create a subclass by sending @code(:new) to a class. +@begin(example) +(setf product-class (send class :new '(s1 s2))) +@end(example) +The parameter @code['(s1 s2)] says that the new class will have two instance +variables, @code(s1) and @code(s2). In other words, every object which is an +instance of class @code(product-class) will have its own copy of +these two variables. + +Next, we will define the @code(:next) method for @code(product-class): +@begin(example) +(send product-class :answer :next '() + '((let ((f1 (snd-fetch s1)) + (f2 (snd-fetch s2))) + (cond ((and f1 f2) + (* f1 f2)) + (t nil))))) +@end(example) +The @code(:answer) message is used to insert a new method into our new +@code(product-class). The method is described in three parts: the name +(@code(:next)), a parameter list (empty in this case), and a list of +expressions to be evaluated. In this case, we fetch samples from @code(s1) +and @code(s2). If both are numbers, we return their product. If either is +@code(NIL), we terminate the sound by returning @code(nil). + +The @code(:next) method assumes that @code(s1) and @code(s2) hold the sounds +to be multiplied. These must be installed when the object is created. +Objects are created by sending @code(:new) to a class. A new object is +created, and any parameters passed to @code(:new) are then sent in a +@code(:isnew) message to the new object. Here is the @code(:isnew) +definition for @code(product-class): +@begin(example) +(send product-class :answer :isnew '(p1 p2) + '((setf s1 (snd-copy p1)) + (setf s2 (snd-copy p2)))) +@end(example) +Take careful note of the use of @code(snd-copy) in this initialization. The +sounds @code(s1) and @code(s2) are modified when accessed by +@code(snd-fetch) in the @code(:next) method defined above, but this destroys +the illusion that sounds are immutable values. The solution is to copy the +sounds before accessing them; the original sounds are therefore unchanged. +(This copy also takes place implicitly in most Nyquist sound functions.) + +To make this code safer for general use, we should add checks that @code(s1) +and @code(s2) are sounds with identical starting times and sample rates; +otherwise, an incorrect result might be computed. + +Now we are ready to write @code(snd-product), an approximate replacement for +@code(snd-prod): +@begin(example) +(defun snd-product (s1 s2) + (let (obj) + (setf obj (send product-class :new s1 s2)) + (snd-fromobject (snd-t0 s1) (snd-srate s1) obj))) +@end(example) +This code first creates @code(obj), an instance of @code(product-class), to +hold @code(s1) and @code(s2). Then, it uses @code(obj) to create a sound +using @code(snd-fromobject). This sound is returned from +@code(snd-product). Note that in @code(snd-fromobject), you must also +specify the starting time and sample rate as the first two parameters. These +are copied from @code(s1), again assuming that @code(s1) and @code(s2) have +matching starting times and sample rates. + +Note that in more elaborate DSP algorithms we could expect the object to +have a number of instance variables to hold things such as previous samples, +waveform tables, and other parameters. + +@chapter(SAL) +@label(SAL-chap) +Nyquist supports two languages: XLISP and SAL. In some sense, XLISP and SAL +are the same language, but with differing syntax. This chapter describes SAL: how it works, SAL syntax and semantics, and the relationship between SAL and XLISP, and differences between Nyquist SAL and Common Music SAL. + +Nyquist SAL is based on Rick Taube's SAL language, which is +part of Common Music. SAL offers the power +of Lisp but features a simple, Algol-like syntax. SAL is implemented +in Lisp: Lisp code translates SAL into a Lisp program and uses the +underlying Lisp engine to evaluate the program. Aside from the translation +time, which is quite fast, SAL programs execute at about the same speed as +the corresponding Lisp program. (Nyquist SAL programs run just + slightly slower than XLISP +because of some runtime debugging support automatically added to +user programs by the SAL compiler.) + +From the user's perspective, these implementation details are hidden. You +can enter SAL mode from XLISP by typing @code[(SAL)] to the XLISP prompt. +The SAL input prompt (@code(SAL> )) will be displayed. From that point on, +you simply type SAL commands, and they will be executed. By setting a +preference in the NyquistIDE program, SAL mode will be entered automatically. + +It is possible to encounter errors that will take you from the SAL interpreter +to an XLISP prompt. In general, the way to get back to SAL is by typing +@code[(top)] to get back to the top level XLISP interpreter and reset the +Nyquist environment. Then type @code[(sal)] to restart the SAL interpreter. + +@section(SAL Syntax and Semantics) +@index(SAL) + The most unusual feature of SAL syntax is that identifiers +are Lisp-like, including names such as ``play-file'' and even ``*warp*.'' +In SAL, most operators must be separated from identifiers by white space. +For example, @code(play-file) is one identifier, but @code(play - file) +is an expression for ``play minus file,'' where @code(play) and @code(file) are +two separate identifiers. Fortunately, no spaces are needed around commas +and parentheses. + +In SAL, whitespace (any sequence of space, newline, or tab characters) +is sometimes necessary to separate lexical tokens, but +otherwise, spaces and indentation are ignored. To make SAL readable, +it is @i(strongly) advised that you indent SAL programs as in the examples +here. The NyquistIDE program is purposely insistent about SAL indentation, +so if you use it to edit SAL programs, your indentation should be +both beautiful and consistent. + +As in Lisp (but very unlike C or Java), comments @index(comments) +are indicated by +semicolons. Any text from an unquoted semicolon to the end of the +line is ignored. + +@begin(example) +@i(; this is a comment) +@i(; comments are ignored by the compiler) +print "Hello World" @i(; this is a SAL statement) +@end(example) + +As in Lisp, identifiers are translated to upper-case, making SAL +case-insensitive@index(case-insensitive). For example, the function name @code(autonorm) can +be typed in lower case or as @code(AUTONORM), @code(AutoNorm), or even +@code(AuToNoRm). All forms denote the same function. The recommended +approach is to write programs in all lower case. + +SAL is organized around statements, most of which +contain expressions. We will begin with expressions and then look at +statements. + +@subsection(Expressions) +@index(sal expressions)@index(expressions, sal) +@paragraph(Simple Expressions) +As in XLISP, simple expressions include: +@begin(itemize) +integers (FIXNUM's), such as @code(1215), + +floats (FLONUM's) such as @code(12.15), + +strings (STRING's) such as @code("Magna Carta"), and + +symbols (SYMBOL's) such as @code(magna-carta). A symbol with a leading colon +(@code(:)) evaluates to itself as in Lisp. Otherwise, a symbol denotes either +a local variable, a formal parameter, or a global variable. As in Lisp, +variables do not have data types or type declarations. The type of a +variable is determined at runtime by its value. +@end(itemize) + +Additional simple expressions in SAL are: +@begin(itemize) +lists such as @code[{c 60 e 64}]. Note that there are no commas to separate list elements, and symbols in lists are not evaluated as variables but stand for themselves. Lists may contain numbers, booleans, symbols, strings, and other lists. + +Booleans: SAL interprets @code(#t)@index(#t) as true and @code(#f)@index(#f) +as false. (As far +as the SAL compiler is concerned, @code(t) and @code(nil) are just variables. +Since these are the Lisp versions of true and false, they are interchangeable +with @code(#t) and @code(#f), respectively.) +@end(itemize) +A curious property of Lisp and Sal is that @i(false) and the empty list are +the same value. Since SAL is based on Lisp, @code(#f) and @code({}) (the empty +list)@index(empty list) are equal. + +@paragraph(Operators) +Expressions can be formed with unary and binary operators using infix notation. The operators are: +@begin(itemize) +@index(+)@code(+) - addition, including sounds + +@index(-)@code(-) - subtraction, including sounds + +@index(*)@code(*) - multiplication, including sounds + +@index(/)@code(/) - division (due to divide-by-zero problems, does not operate on sounds) + +@index(%)@code(%) - modulus (remainder after division) + +@index(^)@code(^) - exponentiation + +@index(=)@code(=) - equal (using Lisp @code(eql)) + +@index(!=)@code(!=) - not equal + +@index(>)@code(>) - greater than + +@index(<)@code(<) - less than + +@index(>=)@code(>=) - greater than or equal + +@index(<=)@code(<=) - less than or equal + +@index(~=)@code(~=) - general equality (using Lisp @code(equal)) + +@index(&)@code(&) - logical and + +@index(|)@code(|) - logical or + +@index(!)@code(!) - logical not (unary) + +@index(@@)@index(time shift, sal)@index(at, sal)@code(@@) - time shift + +@index(@@@@)@index(absolute time shift, sal)@index(at-abs, sal)@code(@@@@) - time shift to absolute time + +@index(~)@index(stretch, sal)@code(~) - time stretch + +@index(~~)@index(absolute stretch, sal)@code(~~) - time stretch to absolute stretch factor +@end(itemize) +Again, remember that operators @i(must) be delimited from their operands using +spaces or parentheses. Operator precedence is based on the following levels of +precedence: +@begin(example) +@@ @@@@ ~ ~~ +^ +/ * +% - + +~= <= >= > ~= = +! +& +| +@end(example) + +@paragraph(Function Calls) +@index(function calls, sal) +A function call is a function name followed by zero or more comma-delimited +argument expressions +enclosed within parentheses: +@begin(example) +list() +piano-note(2.0, c4 + interval, 100) +@end(example) +Some functions use named parameters, +in which case the name of the argument with a colon precedes the argument +expression. +@begin(example) +s-save(my-snd(), ny:all, "tmp.wav", play: #t, bits: 16) +@end(example) + +@paragraph(Array Notation) +@index(array notation, sal) +An array reference is a variable identifier followed by an index expression +in square brackets, e.g.: +@begin(example) +x[23] + y[i] +@end(example) + +@paragraph(Conditional Values) +@index(conditional expression, sal) +@index(#?, sal) +The special operator @code(#?) evaluates the first argument expression. +If the result is @i(true), the second expression is evaluated and +its value is returned. If @i(false), the third expression is evaluated +and returned (or @i(false) is returned if there is no third expression): +@begin(example) +#?(random(2) = 0, unison, major-third) +#?(pitch >= c4, pitch - c4) ; returns false if pitch < c4 +@end(example) + +@subsection(SAL Statements) +@index(statements, sal) +SAL compiles and evaluates @i(statements) one at a time. You can type +statements at the SAL prompt or load a file containing SAL statements. +SAL statements are described below. The syntax is indicated at the +beginning of each statement type description: @code(this font) indicates +literal terms such as keywords, @i(the italic font) indicates a +place-holder for some other statement or expression. Bracket [like this] +indicate optional (zero or one) syntax elements, while braces with a plus +{like this}+ indicate one or more occurrences of a syntax element. Braces +with a star {like this}* indicate zero or more occurrences of a syntax element: { @i(non-terminal) }* is equivalent to [ {@i(non-terminal)}+ ]. + +@paragraph(begin and end) +@index(begin)@index(end) +@code(begin) [@i(with-stmt)] {@i(statement)}+ @code(end) + +A @code(begin)-@code(end) statement +consists of a sequence of statements surrounded by +the @code(begin) and @code(end) keywords. This form is often used for function +definitions and after @code(then) or @code(else) where the syntax demands a +single statement but you want to perform more than one action. Variables may be +declared using an optional @code(with) statement immediately after @code(begin). +For example: +@begin(example) +begin + with db = 12.0, + linear = db-to-linear(db) + print db, "dB represents a factor of", linear + set scale-factor = linear +end +@end(example) + +@paragraph(chdir) +@index(chdir, sal) +@code(chdir) @i(expression) + +The @code(chdir) statement changes the working directory. This statement +is provided for compatibility with Common Music SAL, but it really +should be avoided if you use NyquistIDE. The @i(expression) following the +@code(chdir) keyword should evaluate to a string that is a directory +path name. Note that literal strings themselves are valid expressions. +@begin(example) +chdir "/Users/rbd/tmp" +@end(example) + +@paragraph(define variable) +@index(global variables, sal)@index(define variable) +[@code(define)] @code(variable) @i(name) [= @i(expression)] {, @i(name) [= @i(expression)]}* + +Global variables can be declared and initialized. A list of variable names, +each with an optional initialization follows the @code(define variable) +keywords. (Since @code(variable) is a keyword, @code(define) is redundant +and optional in Nyquist SAL, but required in Common Music SAL.) +If the initialization part is omitted, the variable is initialized +to false. Global variables do not really need to be declared: just using the +name implicitly creates the corresponding variable. However, it is an error +to use a global variable that has not been initialized; +@code(define variable) is a good way to introduce a variable (or constant) +with an initial value into your program. + +@begin(example) +define variable transposition = 2, + print-debugging-info, @i(; initially false) + output-file-name = "salmon.wav" +@end(example) + +@paragraph(define function) +@index(function, sal)@index(define function) +[@code(define)] @code(function) @i(name) @code[(] [@i(parameter)], {, @i(parameter)}* @code[)] @i(statement) + +Before a function be called from an expression (as described above), it must +be defined. A function definition gives the function @i(name), a list of +@i(parameters), and a @i(statement). When a function is called, the actual +parameter expressions are evaluated from left to right and the formal parameters +of the function definition are set to these values. Then, @i(statement) is +evaluated. + +The formal parameters may be positional parameters that are matched with +actual parameters by position from left to right. Syntactically, these are +symbols and these symbols +are essentially local variables that exist only until @i(statement) completes +or a @code(return) statement causes the function evaluation to end. As in Lisp, +parameters are passed by value, so assigning a new value to a formal parameter +has no effect on the actual value. However, lists and arrays are not copied, +so internal changes to a list or array produce observable side effects. + +Alternatively, formal parameters may be keyword parameters. Here the @i(parameter) +is actually a pair: a keyword parameter, which is a symbol followed by a colon, +and a default value, given by any expression. Within the body of the function, +the keyword parameter is named by a symbol whose name matches the keyword +parameter except there is no final colon. +@begin(example) +define function foo(x: 1, y: bar(2, 3)) + display "foo", x, y + +exec foo(x: 6, y: 7) +@end(example) +In this example, @code(x) is bound to the value 6 and @code(y) is bound to +the value 7, so the example prints ``@code(foo : X = 6, Y = 7)''. Note that +while the keyword parameters are @code(x:) and @code(y:), the corresponding +variable names in the function body are @code(x) and @code(y), respectively. + +The @i(parameters) are meaningful only within the lexical (static) scope of +@i(statement). They are not accessible from within other +functions even if they are called by this function. + +Use a @code(begin)-@code(end) statement if the body of the function should +contain more than one statement or you need to define local variables. Use +a @code(return) statement to return a value from the function. If @i(statement) +completes without a @code(return), the value false is returned. + +@paragraph(display) +@index(display statement, sal) +@code(display) @i(string) {, @i(expression)}* + +The @code(display) statement is handy for debugging. At present, it is only +implemented in Nyquist SAL. When executed, @code(display) prints the @i(string) +followed by a colon and then, for each @i(expression), the expression and its +value are printed, after the last expression, a newline is printed. For example, +@begin(example) +display "In function foo", bar, baz +@end(example) +prints +@begin(example) +In function foo : bar = 23, baz = 5.3 +@end(example) +SAL may print the expressions using Lisp syntax, e.g. if the expression is +``bar + baz,'' do not be surprised if the output is ``@code[(sum bar baz) = 28.3].'' + +@paragraph(exec) +@index(exec statement, sal) +@code(exec) @i(expression) + +Unlike most other programming languages, you cannot simply type an expression as +a statement. If you want to evaluate an expression, e.g. call a function, +you must use an @code(exec) statement. The statement simply evaluates +the @i(expression). For example, +@begin(example) +exec set-sound-srate(22050.0) @i(; change default sample rate) +@end(example) + +@paragraph(if) +@index(if statement, sal) +@code(if) @i(test-expr) @code(then) @i(true-stmt) [@code(else) @i(false-stmt)] + +An @code(if) statement evaluates the expression @i(test-expr). If it is true, +it evaluates the statement @i(true-stmt). If false, the statement +@i(false-stmt) is evaluated. Use a @code(begin)-@code(end) statement +to evaluate more than one statement in then @code(then) or @code(else) +parts. + +@begin(example) +if x < 0 then x = -x @i(; x gets its absoute value) + +if x > upper-bound then + begin + print "x too big, setting to", upper-bound + x = upper-bound + end +else + if x < lower-bound then + begin + print "x too small, setting to", lower-bound + x = lower-bound + end +@end(example) +Notice in this example that the @code(else) part is another @code(if) +statement. An @code(if) may also be the @code(then) part of another +@code(if), so there could be two possible @code(if)'s with which to +associate an @code(else). An @code(else) clause always associates +with the closest previous @code(if) that does not already have an +@code(else) clause. + +@paragraph(when) +@code(when) @i(test) @i(statement) + +The @code(when) statement is similar to @code(if), but there is no @code(else) clause. + +@begin(example) +when *debug-flag* print "you are here" +@end(example) + +@paragraph(unless) +@code(unless) @i(test) @i(statement) + +The @code(unless) statement is similar to @code(when) (and @code(if)) but the +@i(statement) is executed when the @i(test) expression is @i(false). + +@begin(example) +unless count = 0 set average = sum / count +@end(example) + +@paragraph(load) +@index(load statement, sal) +@code(load) @i(expression) + +The @code(load) command loads a file named by @i(expression), which must +evauate to a string path name for the file. To load a file, SAL interprets +each statement in the file, stopping when the end of the file or an error +is encountered. If the file ends in @code(.lsp), the file is assumed to +contain Lisp expressions, which are evaluated by the XLISP interpreter. +In general, SAL files should end with the extension @code(.sal). + +@paragraph(loop) +@index(loop statement, sal) +@code(loop) [@i(with-stmt)] {@i(stepping)}* {@i(stopping)* @i(action)+ [@i(finally)] @code(end) + +The @code(loop) statement is by far the most complex statement in SAL, but +it offers great flexibility for just about any kind of iteration. The basic +function of a loop is to repeatedly evaluate a sequence of @i(action)'s which +are statements. Before the loop begins, local variables may be declared in +@i(with-stmt), a @code(with) statement. + +The @i(stepping) clauses do several +things. They introduce and initialize additional local variables similar +to the @i(with-stmt). +However, these local variables are updated to new values after the @i(action)'s. +In addition, some @i(stepping) clauses have associated stopping conditions, +which are tested on each iteration @i(before) evaluating the @i(action)'s. + +There are also @i(stopping) clauses that provide additional tests to +stop the iteration. These are also evaluated and tested +on each iteration before evaluating the @i(action)'s. + +When some @i(stepping) or @i(stopping) condition causes the iteration to stop, +the @i(finally) clause is evaluated (if present). Local variables and their +values can still be accessed in the @i(finally) clause. After the @i(finally) +clause, the @code(loop) statement completes. + +The @i(stepping) clauses are the following: +@begin(description) +@code(repeat) @i(expression)@\Sets the number of iterations to the value of @i(expression), which should be an integer (FIXNUM). + +@code(for) @i(var) = @i(expression) [ @code(then) @i(expr2) ]@\Introduces a new local +variable named @i(var) and initializes it to @i(expression). Before each subsequent +iteration, @i(var) is set to the value of @i(expr2). If the @code(then) part is +omitted, @i(expression) is re-evaluated and assigned to @i(var) +on each subsequent iteration. Note that this differs from a @i(with-stmt) where +expressions are evaluated and variables are only assigned their values once. + +@code(for) @i(var) @code(in) @i(expression)@\Evaluates @i(expression) to +obtain a list and creates a new local variable initialized to the first element +of the list. After each iteration, @i(var) is assigned the next element of the +list. Iteration stops when @i(var) has assumed all values from the list. If the +list is initially empty, the loop @i(action)'s are not evaluated (there are zero +iterations). + +@code(for) @i(var) [@code(from) @i(from-expr)] [[@code(to) | @code(below) | @code(downto) | @code(above)] @i(to-expr)] [@code(by) @i(step-expr)]@\Introduces a new local variable named @i(var) and intialized +to the value of the expression @i(from-expr) (with a default value of 0). After +each iteration of the loop, @i(var) is incremented by the value +of @i(step-expr) (with a default value of 1). +The iteration ends when @i(var) is greater than +the value of @i(to-expr) if there is a @code(to) clause, +greater than or equal to the value of @i(to-expr) +if there is a @code(below) clause, +less than the value of @i(to-expr) if there is a @code(downto) clause, +or less than or equal to the value of @i(to-expr) if there is a @code(above) +clause. (In the cases of @i(downto) and @i(above), the default increment value +is -1. If there +is no @code(to), @code(below), @code(downto), @code(above), or @code(below) clause, no interation stop test is created for this +stepping clause. +@end(description) + +The @i(stopping) clauses are the following: +@begin(description) +@code(while) @i(expression)@\The iterations are stopped when @i(expression) evaluates to @i(false). Anything not false is considered to mean true. + +@code(until) @i(expression)@\The iterations are stopped when @i(expression) evaluates to @i(true). +@end(description) + +The @i(finally) clause is defined as follows: +@index(finally clause, sal) +@begin(description) +@code(finally) @i(statement)@\The @i(statement) is evaluated when one of the +@i(stepping) or @i(stopping) clauses ends the loop. As always, @i(statement) may +be a @code(begin)-@code(end) statement. If an @i(action) evaluates a @code(return) +statement, the @code(finally) statement is not executed. +@end(description) + +@index(loop examples, sal)Loops often fall into common patterns, such as iteratiing a fixed number of +times, performing an operation on some range of integers, collecting results +in a list, and linearly searching for a solution. These forms are illustrated +in the examples below. + +@begin(example) +@i(; iterate 10 times) +loop + repeat 10 + print random(100) +end + +@i(; print even numbers from 10 to 20 +; note that 20 is printed. On the next iteration, +; i = 22, so i >= 22, so the loop exits.) +loop + for i from 10 to 22 by 2 + print i +end + +@i(; collect even numbers in a list) +loop + with lis + for i = 0 to 10 by 2 + set lis @@= i @i(; push integers on front of list,) + @i(; which is much faster than append,) + @i(; but list is built in reverse) + finally result = reverse(lis) +end +@i(; now, the variable result has a list of evens) + +@i(; find the first even number in a list) +result = #f @i(; #f means "false") +loop + for elem in lis + until evenp(elem) + finally result = elem +end +@i[; result has first even value in lis (or it is #f)] +@end(example) + +@paragraph(print) +@index(print statement, sal) +@code(print) @i(expr) {, @i(expr)}* + +The @code(print) statement prints the values separated by +spaces and followed by a newline. [Note that in the original +SAL, the newline is printed @i(before) the values, not after.] + + +@begin(example) +print "The value of x is", x +@end(example) + +@paragraph(return) +@index(return statement, sal) +@code(return) @i(expression) + +The @code(return) statement can only be used inside a function. It evaluates +@i(expression) and then the function returns the value of the expression +to its caller. + +@paragraph(set) +@index(set statement, sal) +@code(set) @i(var) @i(op) @i(expression) {, @i(var) @i(op) @i(expression)}* + +The @code(set) statement changes the value of a variable @i(var) according +to the operator @i(op) and the value of the @i(expression). The operators are: +@begin(description) +@code(=)@\The value of @i(expression) is assigned to @i(var). + +@index(+=)@code(+=)@\The value of @i(expression) is added to @i(var). + +@index(*=)@code(*=)@\The value of @i(var) is multiplied by the value of the expression. + +@index(&=)@code(&=)@\The value of @i(expression) is inserted as the last element of +the list referenced by @i(var). If @i(var) is the empty list (denoted by @code(#f)), +then @i(var) is assigned a newly constructed list of one element, the value +of @i(expression). + +@index(^=)@code(^=)@\The value of @i(expression), a list, is appended to the list referenced +by @i(var). If @i(var) is the empty list (denoted by @code(#f)), then @i(var) +is assigned the (list) value of @i(expression). + +@index(@@=)@code(@@=)@\Pushes the value of @i(expression) onto the front of the list +referenced by @i(var). If @i(var) is empty (denoted by @code(#f)), then @i(var) +is assigned a newly constructed list of one element, the value of @i(expression). + +@index(<=)@code(<=)@\Sets the new value of @i(var) to the minimum of the old value +of @i(var) and the value of @i(expression). + +@index(>=)@code(>=)@\Sets the new value of @i(var) to the maximum of the old value +of @i(var) and the value of @i(expression). +@end(description) + +@begin(example) +@i(; example from Rick Taube's SAL description) +loop + with a, b = 0, c = 1, d = {}, e = {}, f = -1, g = 0 + for i below 5 + set a = i, b += 1, c *= 2, d &= i, e @@= i, f <= i, g >= i + finally display "results", a, b, c, d, e, f, g +end +@end(example) + +@paragraph(with) +@index(with statement, sal) +@code(with) @i(var) [= @i(expression)] {, @i(var) [= @i(expression)]}* + +The @code(with) statement declares and initializes local variables. It +can appear only after @code(begin) or @code(loop). If the @i(expression) is +omitted, the initial value is @i(false). The variables are visible only +inside the @code(begin)-@code(end) or @code(loop) statement where the +@code(with) statement appears. Even in @code(loop)'s the variables +are intialized only when the loop is entered, not on each iteration. + +@paragraph(exit) +@index(exit statement, sal) +@code(exit) [@code(nyquist)] + +The @code(exit) statement is unique to Nyquist SAL. It returns from SAL +mode to the XLISP interpreter. (Return to SAL mode by typing ``@code[(sal)]''). +If @code(nyquist) is included in the statement, then the entire Nyquist +process will exit. + +@section(Interoperability of SAL and XLISP) +@index(sal and lisp)@index(interoperability, sal and lisp) +@label(sal-vs-lisp-section) +When SAL evaluatas command or loads files, it translates SAL into XLISP. +You can think of SAL as a program that translates everything you write +into XLISP and entering it for you. Thus, when you define a SAL function, +the function actually exists as an XLISP function (created using +Lisp's @code(defun) special form). When you set or evaluate global variables +in SAL, these are exactly the same Lisp global variables. Thus, XLISP +functions can call SAL functions and vice-versa. At run time, +everything is Lisp. + +@subsection(Function Calls) +In general, there is a very simple translation from SAL to Lisp syntax +and back. A function call is SAL, for example, +@begin(example) +osc(g4, 2.0) +@end(example) +is translated to Lisp by moving the open parenthesis in front of the +function name and removing the commas: +@begin(example) +(osc g4 2.0) +@end(example) +Similarly, if you want to translate a Lisp function call to SAL, just +reverse the translation. + +@subsection(Symbols and Functions) +SAL translates keywords with trailing colons (such as @code(foo:)) +into Lisp keywords with leading colons (such as @code(:foo)), but +SAL keywords are not treated as expressions as they are in Lisp. +You cannot write @code[open("myfile.txt", direction: output:)] +because SAL expects an expression after direction. A special form +@code(keyword) is defined to generate a Lisp keyword as an +expression. The argument is the keyword @i(without) a colon, e.g. +@code[open("myfile.txt", direction: keyword(output))]. Alternatively, +you can write the Lisp-style keyword with the leading colon, e.g. +@code[open("myfile.txt", direction: :output)]. + +In Nyquist SAL, the hash character (#), can be used as a prefix to a +Lisp function name. For example, the following command is not legal +because @code(print) is a SAL command name, not a legal function name: +@code[set v = append(print(a), print(b))]. (Here the intent is to print +arguments to append). However, you can use the hash character to access +the Lisp @code(print) function: @code[set v = append(#print(a), #print(b))]. + +@subsection(Playing Tricks On the SAL Compiler) +In many cases, the close coupling between SAL and XLISP gives SAL +unexpected expressive power. A good example is @code(seqrep). This +is a special looping construct in Nyquist, implemented as a macro in +XLISP. In Lisp, you would write something like: +@begin(example) +(seqrep (i 10) (pluck c4)) +@end(example) +One might expect SAL would have to define a special @code(seqrep) +statement to express this, but since statements do not return values, +this approach would be problematic. The solution (which is already +fully implemented in Nyquist) is to define a +new macro @code(sal-seqrep) that is equivalent to @code(seqrep) +except that it is called as follows: +@begin(example) +(sal-seqrep i 10 (pluck c4)) +@end(example) +The SAL compiler automatically translates the identifier @code(seqrep) to + @code(sal-seqrep). Now, in SAL, you can just write +@begin(example) +seqrep(i, 10, pluck(c4)) +@end(example) +which is translated in a pretty much semantics-unaware fashion to +@begin(example) +(sal-seqrep i 10 (pluck c4)) +@end(example) +and viola!, we have Nyquist control constructs in SAL even though SAL +is completely unaware that @code(seqrep) is actually a special form. + +@chapter(Nyquist Functions) +@label(lisp-chap) +This chapter provides a language reference for Nyquist. Operations +are categorized by functionality and abstraction level. +Nyquist is implemented in two important levels: the ``high level'' supports +behavioral abstraction, which means that operations like @code(stretch) and +@code(at) can be applied. These functions are the ones that typical users +are expected to use, and most of these functions are written in XLISP. + +The ``low-level'' primitives directly operate on sounds, but know nothing of +environmental variables (such as @code(*warp*), etc.). The +names of most of these low-level functions start with ``@code(snd-)''. In +general, programmers should avoid any function with the ``@code(snd-)'' +prefix. Instead, use the ``high-level'' functions, which know about the +environment and react appropriately. The names of high-level functions +do not have prefixes like the low-level functions. + +There are certain low-level operations that apply directly to sounds (as +opposed to behaviors) and are relatively ``safe'' for ordinary use. These +are marked as such. + +Nyquist uses both linear frequency and equal-temperament pitch numbers to +specify repetition rates. Frequency is always specified in either cycles +per second (hz), or pitch numbers, also referred to as ``steps,'' as in +steps of the chromatic scale. Steps are floating point numbers such that 60 += Middle C, 61 = C#, 61.23 is C# plus 23 cents, etc. The mapping from pitch +number to frequency is the standard exponential conversion, and fractional +pitch numbers are allowed: +@pragma(startscribe) +@math[frequency = 440 @mult 2@+{(pitch - 69)/12}]. +@pragma(endscribe) +@html[@center{frequency = 440 * 2^((pitch - 69)/12)}] +There are many +predefined pitch names. By default these are tuned in equal temperament, +with A4 = 440Hz, but these may be changed. (See Section @ref(constants-sec)). + +@section(Sounds)@index(Sounds) +A sound is a primitive data type in Nyquist. Sounds can be created, passed +as parameters, garbage collected, printed, and set to variables just like +strings, atoms, numbers, and other data types. + +@subsection(What is a Sound?) +Sounds have 5 components: +@begin(itemize) +@code(srate@index(srate)) @itemsep the sample rate of the sound. + +@code(samples@index(samples)) @itemsep the samples. + +@code(signal-start@index(signal-start)) @itemsep the time of the first sample. + +@code(signal-stop@index(signal-stop)) @itemsep the time of one past the last sample. + +@code(logical-stop@index(logical-stop)) @itemsep the time at which the sound logically ends, e.g. a +sound may end at the beginning of a decay. This value defaults +to @code(signal-stop), +but may be set to any value. +@end(itemize) +It may seem that there should be @code(logical-start) to indicate the +logical or perceptual beginning of a sound as well as a @code(logical-stop) +to indicate the logical ending of a sound. In practice, only +@code(logical-stop) is needed; this attribute tells when the next sound +should begin to form a sequence of sounds. In this respect, Nyquist sounds +are asymmetric: it is possible to compute sequences forward in time by +aligning the logical start of each sound with the @code(logical-stop) of the +previous one, but one cannot compute ``backwards'', aligning the logical end +of each sound with the logical start of its successor. The root of this +asymmetry is the fact that when we invoke a behavior, we say when to start, +and the result of the behavior tells us its logical duration. There is no +way to invoke a behavior with a direct specification of when to +stop@foot(Most behaviors will stop at time 1, warped according to @code(*warp*) to some real time, but this is by convention and is not a direct specification.). + +@p(Note:) there is no way to enforce the +intended ``perceptual'' interpretation of +@code(logical-stop). As far as Nyquist is concerned, these are just numbers to +guide the alignment of sounds within various control constructs. + +@subsection(Multichannel Sounds) +@index(Multichannel Sounds) +Multichannel sounds are represented by Lisp arrays of sounds. To create an +array of sounds the XLISP @code(vector) function is useful. Most low-level +Nyquist functions (the ones starting with @code(snd-)) do not operate on +multichannel sounds. Most high-level functions do operate on multichannel +sounds. + +@subsection(Accessing and Creating Sound) +@label(flatten-sec) +@label(snd-srate-sec) + +Several functions display information concerning a sound and can be used to +query the components of a sound. There are functions that access samples in +a sound and functions that construct sounds from samples. + +@begin(fndefs) +@codef[sref(@pragma(defn)@index(sref)@indexSecondary(primary="sound", +secondary="accessing point")@i(sound), @i(time))] @c{[sal]}@* +@altdef{@code[(sref @i(sound) @i(time))] @c{[lisp]}}@\Accesses @i(sound) at +the point @i(time), which is a local time. If @i(time) does not +correspond to a sample time, then the nearest samples are linearly +interpolated to form the result. To access a particular sample, either +convert the sound to an array (see @code(snd-samples) below), or use +@code(snd-srate) and @code(snd-t0) (see below) to find the sample rate +and starting time, and compute a time (@i(t)) from the sample number (@i(n)): +@pragma(startscribe) +@begin(math) +t = (n / srate) + t0 +@end(math) +@pragma(endscribe) +@html[
t = (n / srate) + t0
] +Thus, the lisp code to access the n@+(th) sample of a sound would look like: +@begin(code) +(sref sound (global-to-local (+ (/ n (snd-srate sound)) (snd-t0 sound)))) +@end(code) +Here is why @code(sref) interprets its time argument as a local time: +@begin(example) +> (sref (ramp 1) 0.5) @i(; evaluate a ramp at time 0.5) +0.5 +> (at 2.0 (sref (ramp 1) 0.5)) @i(; ramp is shifted to start at 2.0) + @i(; the time, 0.5, is shifted to 2.5) +0.5 +@end(example) +If you were to use @code(snd-sref), which treats time as global, instead of @code(sref), which treats time as local, then the first example above would return the same answer (0.5), but the second example would return 0. Why? Because the @code[(ramp 1)] behavior would be shifted to start at time 2.0, but the resulting sound would be evaluated at global time 0.5. By definition, sounds have a value of zero before their start time. + +@codef[sref-inverse(@pragma(defn)@index(sref-inverse)@i(sound), @i(value))] @c{[sal]}@* +@altdef{@code[(sref-inverse @i(sound) @i(value))] @c{[lisp]}}@\Search @i(sound) for the first point at which it achieves @i(value) and return the corresponding (linearly interpolated) time. If no inverse exists, an error is raised. This function is used by Nyquist in the implementation of time warping. + +@label(snd-from-array-sec) +@codef[snd-from-array(@IndexSecondary(primary="sound", + secondary = "creating from array")@pragma(defn)@index(snd-from-array)@i(t0), @i(sr), +@i(array))] @c{[sal]}@* +@altdef{@code[(snd-from-array @i(t0) @i(sr) @i(array))] @c{[lisp]}}@\Converts a lisp array of @code(FLONUM)s into a sound with starting +time @i(t0) and sample rate @i(sr). Safe for ordinary use. Be aware that +arrays of floating-point samples use 14 bytes per sample, and an additional +4 bytes per sample are allocated by this function to create a sound type. + +@codef[snd-fromarraystream(@pragma(defn)@index(snd-fromarraystream)@i(t0), @i(sr), @i(object))] @c{[sal]}@* +@altdef{@code[(snd-fromarraystream @i(t0) @i(sr) @i(object))] @c{[lisp]}}@\Creates a sound for which samples come from +@i(object). The starting time is @i(t0) (a @code(FLONUM)), and the sample rate is +@i(sr). The @i(object) is an XLISP object (see Section @ref(objects-sec) for +information on objects.) A sound is returned. When the sound needs samples, +they are generated by sending the message @code(:next) to @i(object). If +@i(object) returns @code(NIL), the sound terminates. Otherwise, @i(object) +must return an array of @code(FLONUM)s. The values in these arrays are +concatenated to form the samples of the resulting sound. +There is no provision for @i(object) to specify the +logical stop time of the sound, so the logical stop time is the termination +time. + +@codef[snd-fromobject(@pragma(defn)@index(snd-fromobject)@index(sound from Lisp data)@i(t0), @i(sr), @i(object))] @c{[sal]}@* +@altdef{@code[(snd-fromobject @i(t0) @i(sr) @i(object))] @c{[lisp]}}@\Creates a sound for which samples come from +@i(object). The starting time is @i(t0) (a @code(FLONUM)), and the sample rate is +@i(sr). The @i(object) is an XLISP object (see Section @ref(objects-sec) for +information on objects. A sound is returned. When the sound needs samples, +they are generated by sending the message @code(:next) to @i(object). If +@i(object) returns @code(NIL), the sound terminates. Otherwise, @i(object) +must return a @code(FLONUM). There is no provision for @i(object) to specify the +logical stop time of the sound, so the logical stop time is the termination +time. + +@codef[snd-extent(@pragma(defn)@index(snd-extent)@i(sound), @i(maxsamples))] @c{[sal]}@* +@altdef{@code[(snd-extent @i(sound) @i(maxsamples))] @c{[lisp]}}@\Returns a list of two numbers: the starting time of @i(sound) and the terminate time of @i(sound). Finding the terminate time requires that samples be computed. Like most Nyquist functions, this is non-destructive, so memory will be allocated to preserve the sound samples. If the sound is very long or infinite, this may exhaust all memory, so the @i(maxsamples) parameter specifies a limit on how many samples to compute. If this limit is reached, the terminate time will be (incorrectly) based on the sound having @i(maxsamples) samples. This function is safe for ordinary use. + +@codef[snd-fetch(@index(access samples)@index(samples, +reading)@pragma(defn)@index(snd-fetch)@index(read samples)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-fetch @i(sound))] @c{[lisp]}}@\Reads samples +sequentially from @i(sound). This returns a @code(FLONUM) after each call, or +@code(NIL) when @i(sound) terminates. @p(Note:) @code(snd-fetch) modifies +@i(sound); it is strongly recommended to copy @i(sound) using +@code(snd-copy) and access only the copy with @code(snd-fetch). + +@codef[snd-fetch-array(@pragma(defn)@index(snd-fetch-array)@i(sound), @i(len), +@i(step))] @c{[sal]}@* +@altdef{@code[(snd-fetch-array @i(sound) @i(len) @i(step))] +@c{[lisp]}}@\Reads +sequential arrays of samples from @i(sound), returning either an array +of @code(FLONUM)s or @code(NIL) when the sound terminates. The @i(len) +parameter, a @code(FIXNUM), indicates how many samples should be +returned in the result array. After the array is returned, @i(sound) +is modified by skipping over @i(step) (a @code(FIXNUM)) samples. If +@i(step) equals @i(len), then every sample is returned once. If +@i(step) is less than @i(len), each returned array will overlap the +previous one, so some samples will be returned more than once. If +@i(step) is greater than @i(len), then some samples will be skipped +and not returned in any array. The @i(step) and @i(len) may change at +each call, but in the current implementation, an internal buffer is +allocated for @i(sound) on the first call, so subsequent calls may not +specify a greater @i(len) than the first. When an array is returned, +it will have @i(len) samples. If necessary, @code(snd-fetch-array) +will read zeros beyond the end of the sound to fill the array. When +this happens, @code(*rslt*) is set to a FIXNUM number of samples in +the array that were read from the sound before the physical stop time +of the sound. If all samples in the array are ``valid'' samples from +the sound (coming from the sound before the sound +terminates), @code(*rslt*) is set to @code(NIL). The @code(*rslt*) +variable is global and used to return extra results from other +functions, so programs should not assume @code(*rslt*) is valid after +subsequent function calls. @p(Note:) @code(snd-fetch-array) modifies +@i(sound); it is strongly recommended to copy @i(sound) using +@code(snd-copy) and access only the copy with @code(snd-fetch-array). + +@codef[snd-flatten(@pragma(defn)@index(snd-flatten)@i(sound), @i(maxlen))] @c{[sal]}@* +@altdef{@code[(snd-flatten @i(sound) @i(maxlen))] @c{[lisp]}}@\This function is identical +to @code(snd-length). You would use this function to force samples to be computed in memory. Normally, this is not a good thing to do, but here is one appropriate use: In the case of sounds intended for wavetables, the unevaluated +sound may be larger than the evaluated (and typically short) one. +Calling @code(snd-flatten) will compute the samples and allow the unit generators to be freed in the next garbage collection. @p(Note:) If a sound is computed from many instances of table-lookup oscillators, calling @code(snd-flatten) will free the oscillators and their tables. Calling @code[(stats)] will print how many total bytes have been allocated to tables. + + @codef[snd-length(@pragma(defn)@index(snd-length)@i(sound), @i(maxlen))] @c{[sal]}@* +@altdef{@code[(snd-length @i(sound) @i(maxlen))] @c{[lisp]}}@\Counts the +number of samples in @i(sound) up to the physical stop time. If the sound +has more than @i(maxlen) samples, @i(maxlen) is returned. Calling this +function will cause all samples of the sound to be computed and saved in +memory (about 4 bytes per sample). Otherwise, this function is safe for ordinary use. + + @codef[snd-maxsamp(@pragma(defn)@index(snd-maxsamp)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-maxsamp @i(sound))] @c{[lisp]}}@\Computes the maximum of +the absolute value of the samples in @i(sound). Calling this function will +cause samples to be computed and saved in memory. (This function should +have a @i(maxlen) parameter to allow self-defense against sounds that would +exhaust available memory.) Otherwise, this function is safe for ordinary use. +This function will probably be removed in a future version. See @code(peak), a replacement (@pragma(startref) page @pageref(peak-sec)). + + + @codef[snd-play(@pragma(defn)@index(snd-play)@i(expression))] @c{[sal]}@* +@altdef{@code[(snd-play @i(expression))] @c{[lisp]}}@\Evaluates @i(expression) +to obtain a sound or array of sounds, computes all of the samples (without +retaining them in memory), and returns. Originally, this was a placeholder +for a facility to play samples directly to an audio output device, but +playback is now accomplished by @code(s-save). +Meanwhile, since this +function does not save samples in memory or write them to a disk, it is +useful in determining how much time is spent calculating samples. See +@code(s-save) (Section @ref(s-save-sec)) for saving samples to a file, and + @code(play) (Section @ref(play-sec)) to play a sound. This function is +safe for ordinary use. + +@codef[snd-print-tree(@pragma(defn)@index(snd-print-tree)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-print-tree @i(sound))] @c{[lisp]}}@\Prints an ascii +representation of the internal data structures representing a sound. This +is useful for debugging Nyquist. This function is +safe for ordinary use. + + @codef[snd-samples(@index(samples)@pragma(defn)@index(snd-samples)@index(array from sound)@index(convert sound to array)@i(sound), @i(limit))] @c{[sal]}@* +@altdef{@code[(snd-samples @i(sound) @i(limit))] @c{[lisp]}}@\Converts the +samples into a lisp array. The data is taken directly from the samples, +ignoring shifts. For example, if the sound starts at 3.0 seconds, the first +sample will refer to time 3.0, not time 0.0. A maximum of @i(limit) samples +is returned. This function is safe for ordinary use, but like +@code(snd-from-array), it requires a total of slightly over 18 bytes per +sample. + + @codef[snd-srate(@pragma(defn)@index(snd-srate)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-srate @i(sound))] @c{[lisp]}}@\Returns the sample rate of +the sound. Safe for ordinary use. + +@begin(comment) + @codef[snd-show(@pragma(defn)@index(snd-show)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-show @i(sound))] @c{[lisp]}}@\Print the entire (internal) +structure of the sound for debugging. Safe for ordinary use. +@end(comment) + +@codef[snd-time(@pragma(defn)@index(snd-time)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-time @i(sound))] @c{[lisp]}}@\Returns the start time of the +sound. This will probably go away in a future version, so use @code(snd-t0) +instead. + +@codef[snd-t0(@pragma(defn)@index(snd-t0)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-t0 @i(sound))] @c{[lisp]}}@\Returns the time of the +first sample of the sound. Note that Nyquist operators such as add always +copy the sound and are allowed to shift the copy up to one half sample +period in either direction to align the samples of two operands. Safe for +ordinary use. + +@codef[snd-print(@pragma(defn)@index(snd-print)@i(expression), @i(maxlen))] @c{[sal]}@* +@altdef{@code[(snd-print @i(expression) @i(maxlen))] @c{[lisp]}}@\Evaluates +@i(expression) to yield a sound or an array of sounds, then prints up to +@i(maxlen) samples to the screen (stdout). This is similar to +@code(snd-save), but samples appear in text on the screen instead of in +binary in a file. This function is intended for debugging@index(debugging). +Safe for ordinary use. + + @codef[snd-set-logical-stop(@pragma(defn)@index(snd-set-logical-stop)@i(sound), +@i(time))] @c{[sal]}@* +@altdef{@code[(snd-set-logical-stop @i(sound) @i(time))] @c{[lisp]}}@\Returns a sound which is +@i(sound), except that the logical stop of the sound occurs at @i(time). + @p(Note:) do not call this function. When defining a behavior, use +@code(set-logical-stop) or @code(set-logical-stop-abs) instead. + +@codef[snd-sref(@pragma(defn)@index(snd-sref)@i(sound), @i(time))] @c{[sal]}@* +@altdef{@code[(snd-sref @i(sound) @i(time))] @c{[lisp]}}@\Evaluates @i(sound) +at the global time given by @i(time). Safe for ordinary use, but normally, you should +call @code(sref) instead. + + @codef[snd-stop-time(@pragma(defn)@index(snd-stop-time)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-stop-time @i(sound))] @c{[lisp]}}@\Returns the stop time of @i(sound). +Sounds can be ``clipped'' or truncated at a particular time. This function +returns that time or MAX-STOP-TIME if he programmer has not specified a stop +time for the sound. Safe for ordinary use. + +@codef[soundp(@pragma(defn)@index(soundp)@i(sound))] @c{[sal]}@* +@altdef{@code[(soundp @i(sound))] @c{[lisp]}}@\Returns true iff @i(sound) is a +SOUND. Safe for ordinary use. + +@codef[stats(@pragma(defn)@index(stats)@index(memory +usage)@index(table memory))] @c{[sal]}@* +@altdef{@code[(stats)] @c{[lisp]}}@\Prints the memory usage status. +See also the +XLISP @code(mem) function. Safe for ordinary use. This is the only way to find out how much memory is being used by table-lookup oscillator instances. + +@end(fndefs) + +@subsection(Miscellaneous Functions) +These are all safe and recommended for ordinary use. + +@begin(fndefs) +@codef[db-to-linear(@pragma(defn)@index(db-to-linear)@i(x))] @c{[sal]}@* +@altdef{@code[(db-to-linear @i(x))] @c{[lisp]}}@\Returns the conversion of @i(x) from decibels to linear. 0dB is converted to 1. 20dB represents a linear factor of 10. If @i(x) is a sound, each sample is converted and a sound is returned. If @i(x) is a multichannel sound, each channel is converted and a multichannel sound (array) is returned. @p(Note:) With sounds, conversion is only performed on actual samples, not on the implicit zeros before the beginning and after the termination of the sound. Sample rates, start times, etc. are taken from @i(x). + +@codef[follow(@pragma(defn)@index(follow)@index(envelope follower)@index(compressor)@index(limiter)@i(sound), @i(floor), @i(risetime), @i(falltime), @i(lookahead))] @c{[sal]}@* +@altdef{@code[(follow @i(sound) @i(floor) @i(risetime) @i(falltime) @i(lookahead))] @c{[lisp]}}@\An envelope follower intended as a commponent for compressor and limiter functions. The basic goal of this function is to generate a smooth signal +that rides on the peaks of the input signal. The usual objective is to +produce an amplitude envelope given a low-sample rate (control rate) +signal representing local RMS measurements. The first argument is the +input signal. The @i(floor) is the minimum output value. The @i(risetime) +is the time (in seconds) it takes for the output to rise (exponentially) +from @i(floor) to unity (1.0) and the @i(falltime) is the time it takes +for the output to fall (exponentially) from unity to @i(floor). The +algorithm looks ahead for peaks and will begin to increase the output +signal according to @i(risetime) in anticipation of a peak. The amount +of anticipation (in seconds) is given by @i(lookahead). The algorithm +is as follows: the output value is allowed to increase according to +@i(risetime) or decrease according to @i(falltime). If the next input +sample is in this range, that sample is simply output as the next output +sample. If the next input sample is too large, the algorithm goes back in +time as far as necessary to compute an envelope that rises according to +@i(risetime) to meet the new value. The algorithm will only work backward +as far as @i(lookahead). If that is not far enough, then there is a final +forward pass computing a rising signal from the earliest output sample. In +this case, the output signal will be at least momentarily less than the +input signal and will continue to rise exponentially until it intersects +the input signal. If the input signal falls faster than indicated by +@i(falltime), the output fall rate will be limited by @i(falltime), +and the fall in output will stop when the output reaches @i(floor). +This algorithm can make two passes througth the buffer on sharply rising +inputs, so it is not particularly fast. With short buffers and low sample +rates this should not matter. See @code(snd-avg) for a function that +can help to generate a low-sample-rate input for @code(follow). +See @code(snd-chase) in Section @ref(snd-chase-sec) for a related filter. + +@label(gate-sec) +@codef[gate(@pragma(defn)@index(gate)@index(noise-gate)@i(sound), +@i(lookahead), @i(risetime), @i(falltime), @i(floor), +@i(threshold))] @c{[sal]}@* +@altdef{@code[(gate @i(sound) @i(lookahead) @i(risetime) @i(falltime) @i(floor) @i(threshold))] @c{[lisp]}}@\Generate an exponential rise and decay intended +for noise gate implementation. The decay starts when the signal drops +below @i(threshold) and stays there for longer than @i(lookahead) (a +@code(FLONUM) in seconds). (The signal begins to drop when the signal +crosses @i(threshold), not after @i(lookahead).) Decay continues until +the value reaches @i(floor) (a @code(FLONUM)), at which point the decay +stops and the output value is held constant. Either during the decay or +after the floor is reached, if the signal goes above @i(threshold), then +the ouptut value will rise to unity (1.0) at the point the signal crosses +the threshold. Because of internal lookahead, the signal actually begins +to rise before the signal crosses @i(threshold). The rise is a +constant-rate exponential and set so that a rise from @i(floor) to unity +occurs in @i(risetime). Similary, the fall is a constant-rate exponential +such that a fall from unity to @i(floor) takes @i(falltime). + +@codef[hz-to-step(@pragma(defn)@index(hz-to-step)@i(freq))] @c{[sal]}@* +@altdef{@code[(hz-to-step @i(freq))] @c{[lisp]}}@\Returns a step number for @i(freq) (in hz), which can be either a number of a @code(SOUND). The result has the same type as the argument. See also @code(step-to-hz) (below). + +@codef[linear-to-db(@pragma(defn)@index(linear-to-db)@i(x))] @c{[sal]}@* +@altdef{@code[(linear-to-db @i(x))] @c{[lisp]}}@\Returns the conversion of @i(x) from linear to decibels. 1 is converted to 0. 0 is converted to -INF (a special IEEE floating point value.) A factor of 10 represents a 20dB change. If @i(x) is a sound, each sample is converted and a sound is returned. If @i(x) is a multichannel sound, each channel is converted and a multichannel sound (array) is returned. @p(Note:) With sounds, conversion is only performed on actual samples, not on the implicit zeros before the beginning and after the termination of the sound. Start times, sample rates, etc. are taken from @i(x). + +@codef[log(@index(log function)@pragma(defn)@index(log)@i(x))] @c{[sal]}@* +@altdef{@code[(log @i(x))] @c{[lisp]}}@\Calculates the natural log of @i(x) (a @code(FLONUM)). (See @code(s-log) for a version that operates on signals.) + +@codef[set-control-srate(@pragma(defn)@index(set-control-srate)@index(sampling rate)@i(rate))] @c{[sal]}@* +@altdef{@code[(set-control-srate @i(rate))] @c{[lisp]}}@\Sets the default sampling rate for control signals to @i(rate) by setting @code(*default-control-srate*) and reinitializing the environment. Do not call this within any synthesis function (see the @code(control-srate-abs) transformation, Section @ref(control-srate-abs-sec)). + +@codef[set-sound-srate(@pragma(defn)@index(set-sound-srate)@index(sampling rate)@i(rate))] @c{[sal]}@* +@altdef{@code[(set-sound-srate @i(rate))] @c{[lisp]}}@\Sets the default sampling rate for audio signals to @i(rate) by setting @code(*default-sound-srate*) and reinitializing the environment. Do not call this within any synthesis function (see the @code(sound-srate-abs) transformation, Section @ref(sound-srate-abs-sec)). + +@codef[set-pitch-names(@pragma(defn)@index(set-pitch-names))] @c{[sal]}@* +@altdef{@code[(set-pitch-names)] @c{[lis]}}@\Initializes pitch +variables (@code(c0), @code(cs0), @code(df0), @code(d0), ... @code(b0), + @code(c1), ... @code(b7)). A440 (the default tuning) is represented by + the step 69.0, so the variable @code(a4) (fourth octave A) is set to 69.0. +You can change the tuning by +setting @code(*A4-Hertz*)@index(tuning)@index(A440)@index(*A4-Hertz*) to a +value (in Hertz) and calling @code(set-pitch-names) to reinitialize the pitch +variables. Note that this will result in non-integer step values. It does not +alter the mapping from step values to frequency. There is no built-in +provision for stretched scales or non-equal temperament, although users +can write or compute any desired fractional step values. + + @codef[step-to-hz(@pragma(defn)@index(step-to-hz)@i(pitch))] @c{[sal]}@* +@altdef{@code[(step-to-hz @i(pitch))] @c{[lisp]}}@\Returns a frequency in hz +for @i(pitch), a step number or a @code(SOUND) type representing a time-varying step number. The result is a @code(FLONUM) if @i(pitch) is a number, and a @code(SOUND) if @i(pitch) is a @code(SOUND). See also @code(hz-to-step) (above). + + +@codef{get-duration(@pragma(defn)@index(get-duration)@i(dur))} @c{[sal]}@* +@altdef{@code[(get-duration @i(dur))] @c{[lisp]}}@\Gets the actual duration of of something starting at a local time of 0 and ending at a local time of @i(dur) times the current sustain. For convenience, @code(*rslt*) is set to the global time corresponding to local time zero. + +@codef{get-loud(@pragma(defn)@index(get-loud))} @c{[sal]}@* +@altdef{@code[(get-loud)] @c{[lisp]}}@\Gets the current value of the @code(*loud*) environment variable. If @code(*loud*) is a signal, it is evaluated at local time 0 and a number (@code(FLONUM)) is returned. + +@codef{get-sustain(@pragma(defn)@index(get-sustain))} @c{[sal]}@* +@altdef{@code[(get-sustain)] @c{[lisp]}}@\Gets the current value of the @code(*sustain*) environment variable. If @code(*sustain*) is a signal, it is evaluated at local time 0 and a number (@code(FLONUM)) is returned. + +@codef{get-transpose(@pragma(defn)@index(get-transpose))} @c{[sal]}@* +@altdef{@code[(get-transpose)] @c{[lisp]}}@\Gets the current value of the @code(*transpose*) environment variable. If @code(*transpose*) is a signal, it is evaluated at local time 0 and a number (@code(FLONUM)) is returned. + +@codef{get-warp(@pragma(defn)@index(get-warp))} @c{[sal]}@* +@altdef{@code[(get-warp)] @c{[lisp]}}@\Gets a function corresponding to +the current value of the @code(*warp*) environment variable. For +efficiency, @code(*warp*) is stored in three parts representing a shift, + a scale factor, and a continuous warp function. @code(Get-warp) is used + to retrieve a signal that maps logical time to real time. This signal +combines the information of all three components of @code(*warp*) into +a single signal. If the continuous warp function component is not present + (indicating that the time warp is a simple combination of @code(at) + and @code(stretch) transformations), an error is raised. This +function is mainly for internal system use. In the future, + @code(get-warp) will probably be reimplemented to always return + a signal and never raise an error. + +@CODEF{LOCAL-to-global(@pragma(defn)@index(local-to-global)@i(local-time))} @c{[sal]}@* +@altdef{@code[(local-to-global @i(local-time))] @c{[lisp]}}@\Converts a score (local) time to a real (global) time according to the current environment. + +@codef{osc-enable(@pragma(defn)@index(osc-enable)@index(osc)@index(open sound control)@i(flag))} @c{[sal]}@* +@altdef{@code[(osc-enable @i(flag))] @c{[lisp]}}@\Enable or disable Open Sound Control. +(See Appendix @ref(osc-app).) +Enabling creates a socket and a service that listens for UDP +packets on port 7770. Currently, only two messages are accepted +by Nyquist. The first is of the form @code(/slider) +with an integer index and a floating point value. These set internal +slider values accessed by the @code(snd-slider) +function. The second is of the form @code(/wii/orientation) with +two floating point values. This message is a special case to +support the DarwiinRemoteOsc@index(DarwiinRemoteOsc) program + which can relay data from +a Nintendo@index(Nintendo WiiMote) WiiMote@index(Wii Controller) + device to Nyquist via OSC. The two orientation +values control sliders 0 and 1. +Disabling terminates the service (polling for messages) +and closes the socket. The @i(previous) state of enablement +is returned, e.g. if OSC is enabled and @i(flag) is @i(nil), +OSC is disabled and @code(T) (true) is returned because OSC +was enabled at the time of the call. This function only exists +if Nyquist is compiled with the compiler flag @code(OSC). +Otherwise, the function +exists but always returns the symbol @code(DISABLED). Consider +lowering the audio latency using @code(snd-set-latency). +@i(Warning:) there is the potential for +network-based attacks using OSC. It is tempting to add the +ability to evaluate XLISP expressions sent via OSC, but +this would create +unlimited and unprotected access to OSC clients. For now, +it is unlikely that an attacker could do more than +manipulate slider values. + +@codef{snd-set-latency(@index(latency)@pragma(defn)@index(snd-set-latency)@i(latency))} @c{[sal]}@* +@altdef{@code[(snd-set-latency @i(latency))] @c{[lisp]}}@\Set the latency requested when Nyquist plays sound to + @i(latency), a @code(FLONUM). The previous value is returned. The default is 0.3 seconds. To avoid glitches, the latency should be +greater than the time required for garbage collection and message printing and any other system activity external to Nyquist. +@end(fndefs) + +@section(Behaviors)@index(Behaviors) +@label(behavior-sec) + +@subsection(Using Previously Created Sounds) +@label(use-sounds-sec) +These behaviors take a sound and transform that sound according to the +environment. These are useful when writing code to make +a high-level function from a low-level function, or when cuing sounds +which were previously created: +@begin(fndefs) +@codef[cue(@pragma(defn)@index(cue)@i(sound))] @c{[sal]}@* +@altdef{@code[(cue @i(sound))] @c{[lisp]}}@\Applies @code(*loud*), the starting time from @code(*warp*), @code(*start*), + and @code(*stop*) to @i(sound). + +@codef[cue-file(@pragma(defn)@index(cue-file)@i(filename))] @c{[sal]}@* +@altdef{@code[(cue-file @i(filename))] @c{[lisp]}}@\Same as @code(cue), except +the sound comes from the named file, samples from which are coerced to the current default @code(*sound-srate*) sample rate. + +@codef[sound(@pragma(defn)@index(sound)@i(sound))] @c{[sal]}@* +@altdef{@code[(sound @i(sound))] @c{[lisp]}}@\Applies @code(*loud*), @code(*warp*), +@code(*start*), and @code(*stop*) to @i(sound). + +@codef[control(@pragma(defn)@index(control)@i(sound))] @c{[sal]}@* +@altdef{@code[(control @i(sound))] @c{[lisp]}}@\This function is identical to +@code(sound), but by convention is used when @i(sound) is a control signal +rather than an audio signal. +@end(fndefs) + +@subsection(Sound Synthesis) + +These functions provide musically interesting creation behaviors that +react to their environment; these are the ``unit generators'' of Nyquist: + +@begin(fndefs) +@codef{const(@pragma(defn)@index(const)@index(constant function)@i(value) [, @i(duration)])} @c{[sal]}@* +@altdef{@code{(const @i(value) [@i(duration)])} @c{[lisp]}}@\Creates a constant function at the @code(*control-srate*). Every sample has the given @i(value), and the default @i(duration) is 1.0. See also @code(s-rest), which is equivalent to calling @code(const) with zero, and note that you can pass scalar constants (numbers) to @code(sim), @code(sum), and @code(mult) where they are handled more efficiently than constant functions. + +@codef{env(@pragma(defn)@index(env)@i(t@-[1]), @i(t@-[2]), @i(t@-[4]), @i(l@-[1]), @i(l@-[2]), @i(l@-[3]), +[@i(dur)])} @c{[sal]}@* +@altdef{@code[(env @i(t@-[1]) @i(t@-[2]) @i(t@-[4]) @i(l@-[1]) @i(l@-[2]) @i(l@-[3]) @i(dur))] @c{[lisp]}}@\Creates a 4-phase envelope. +@i(t@-[@i(i)]) is the duration of phase @i(i), and @i(l@-[@i(i)]) +is the final level of phase @i(i). @i(t@-[3]) is implied by the duration +@i(dur), and @i(l@-[4]) is @code(0.0). If @i(dur) is not supplied, then +@code(1.0) is assumed. The envelope duration is the product of @i(dur), +@code(*stretch*), and @code(*sustain*). If +@i(t@-[1]) + @i(t@-[2]) + 2ms + @i(t@-[4]) is greater than the envelope +duration, then a two-phase envelope is +substituted that has an attack/release time ratio of @i(t@-[1])/@i(t@-[4]). +The sample rate of the returned sound is @code(*control-srate*). (See +@code(pwl) for a more general piece-wise linear function generator.) +The effect of time warping is to warp the starting time and ending time. +The intermediate breakpoints are then computed as described above. + + +@codef{exp-dec(@pragma(defn)@index(exp-dec)@index(exponential envelope)@i(hold), @i(halfdec), @i(length))} @c{[sal]}@* +@altdef{@code[(exp-dec @i(hold) @i(halfdec) @i(length))] @c{[lisp]}}@\This convenient envelope shape is a special case of @code(pwev) (see Section @ref(pwev-sec)). The envelope starts at 1 and is constant for @i(hold) seconds. It then decays with a half life of @i(halfdec) seconds until @i(length). (The total duration is @i(length).) In other words, the amplitude falls by half each @i(halfdec) seconds. When stretched, this envelope scales linearly, which means the hold time increases and the half decay time increases. + + +@label(force-srate-sec) +@codef{force-srate(@pragma(defn)@index(force-srate)@index(sample rate, forcing)@index(resampling)@i(srate), @i(sound))} @c{[sal]}@* +@altdef{@code[(force-srate @i(srate) @i(sound))] @c{[lisp]}}@\Returns a sound which is up- or +down-sampled to @i(srate). Interpolation is linear, and no prefiltering is +applied in the down-sample case, so aliasing may occur. See also +@code(resample). + + +@codef{lfo(@pragma(defn)@index(lfo)@index(low-frequency oscillator)@i(freq) [, @i(duration), @i(table), @i(phase)])} @c{[sal]}@* +@altdef{@code[(lfo @i(freq) @i(duration) @i(table) @i(phase))] @c{[lisp]}}@\Just +like @code(osc) (below) +except this computes at the @code(*control-srate*) and frequency +is specified in Hz. Phase is specified in degrees. + The @code(*transpose*) and @code(*sustain*) is not +applied. The effect of time warping is to warp the starting and ending +times. The signal itself will have a constant unwarped frequency. + +@codef{fmlfo(@pragma(defn)@index(fmlfo)@i(freq) [, @i(table), @i(phase)])} @c{[sal]}@* +@altdef{@code{(fmlfo @i(freq) [@i(table) @i(phase)])} @c{[lisp]}}@\A low-frequency oscillator +that computes at the @code(*control-srate*) using a sound to specify a time-varying +frequency in Hz. Phase is a @code(FLONUM) in degrees. The duration of the result is determined by @i(freq). + +@codef{maketable(@pragma(defn)@index(maketable)@label(maketable)@i(sound))} @c{[sal]}@* +@altdef{@code[(maketable @i(sound))] @c{[lisp]}}@\Assumes that +the samples in @i(sound) constitute one period of a wavetable, and returns a wavetable +suitable for use as the @i(table) argument to the @code(osc) function (see +below). Currently, tables are limited to 1,000,000 samples. This limit is the compile-time constant @code(max_table_len) set in @code(sound.h). + +@codef{build-harmonic(@pragma(defn)@index(build-harmonic)@index(harmonic)@i(n), @i(table-size))} @c{[sal]}@* +@altdef{@code[(build-harmonic @i(n) @i(table-size))] @c{[lisp]}}@\Intended for +constructing wavetables@index(wavetables)@index(waveforms), this function returns a sound of length @i(table-size) +samples containing @i(n) periods of a sinusoid. These can be scaled and +summed to form a waveform with the desired harmonic content. See @pragma(startref) page @pageref(build-harmonic-example) for an example. + +@codef{control-warp(@pragma(defn)@index(control-warp)@i(warp-fn), @i(signal), [@i(wrate)])} @c{[sal]}@* +@altdef{@code[(control-warp @i(warp-fn) @i(signal) @i(wrate))] @c{[lisp]}}@\Applies a +warp function @i(warp-fn) to @i(signal) using function composition. If @i(wrate) is omitted, linear +interpolation is used. @i(warp-fn) is a mapping from score (logical) time +to real time, and @i(signal) is a function from score time to real values. +The result is a function from real time to real values at a sample rate of +@code(*control-srate*). See @code(sound-warp) for an explanation of +@i(wrate) and high-quality warping. + +@label(mult-sec) +@codef{mult(@pragma(defn)@index(mult)@i(beh@-[1]), @i(beh@-[2]), @r(...))} @c{[sal]}@* +@altdef{@code[(mult @i(beh@-[1]) @i(beh@-[2] @r(...)))] @c{[lisp]}}@\Returns the product of +behaviors. The arguments may also be numbers, in which case simple multiplication is performed. If a number and sound are mixed, the @code(scale) function is used to scale the sound by the number. When sounds are multiplied, the resulting sample rate is the maximum sample rate of the factors. + +@codef{prod(@pragma(defn)@index(prod)@i(beh@-[1]), @i(beh@-[2]), @r(...))} @c{[sal]}@* +@altdef{@code[(prod @i(beh@-[1]) @i(beh@-[2]) @r(...))] @c{[lisp]}}@\Same as @code(mult). + +@label(pan-sec) +@codef{pan(@pragma(defn)@index(pan)@index(stereo panning)@i(sound), @i(where))} @c{[sal]}@* +@altdef{@code[(pan @i(sound) @i(where))] @c{[lisp]}}@\Pans @i(sound) (a behavior) according to @i(where) (another behavior or a number). @i(Sound) must be monophonic. @i(Where) may be a monophonic sound (e.g. @code[(ramp)] or simply a number (e.g. @code(0.5)). In either case, @i(where) should range from 0 to 1, where 0 means pan completely left, and 1 means pan completely right. For intermediate values, the sound to each channel is scaled linearly. Presently, @code(pan) does not check its arguments carefully. + +@codef{prod(@pragma(defn)@index(prod)@i(beh@-[1]), @i(beh@-[2]), @r(...))} @c{[sal]}@* +@altdef{@code[(prod @i(beh@-[1]) @i(beh@-[2]) @r(...))] @c{[lisp]}}@\Same as @code(mult). + +@label(resample-sec) +@codef{resample(@pragma(defn)@index(resample)@i(sound), @i(srate))} @c{[sal]}@* +@altdef{@code[(resample @i(sound) @i(srate))] @c{[lisp]}}@\Similar to @code(force-srate), except +high-quality interpolation is used to prefilter and reconstruct the signal +at the new sample rate. Also, the result is scaled by 0.95 to reduce problems with +clipping. (See also @code(sound-warp).) + +@label(scale-sec) +@codef{scale(@pragma(defn)@index(scale)@i(scale), @i(sound))} @c{[sal]}@* +@altdef{@code[(scale @i(scale) @i(sound))] @c{[lisp]}}@\Scales the amplitude of @i(sound) by the factor @i(scale). Identical function to @code(snd-scale), except that it handles multichannel sounds. Sample rates, start times, etc. are taken from @i(sound). + +@codef{scale-db(@pragma(defn)@index(scale-db)@i(db), @i(sound))} @c{[sal]}@* +@altdef{@code[(scale-db @i(db) @i(sound))] @c{[lisp]}}@\Scales the amplitude of @i(sound) by the factor @i(db), expressed in decibels. Sample rates, start times, etc. are taken from @i(sound). + +@codef[scale-srate(@pragma(defn)@index(scale-srate)@i(sound), @i(scale))] @c{[sal]}@* +@altdef{@code[(scale-srate @i(sound) @i(scale))] @c{[lisp]}}@\Scales the sample rate of @i(sound) by @i(scale) factor. This has the effect of linearly shrinking or stretching time (the sound is not upsampled or downsampled). This is a special case of @code(snd-xform) (see Section @ref(snd-xform-sec)). + +@codef[shift-time(@pragma(defn)@index(shift-time)@i(sound), @i(shift))] @c{[sal]}@* +@altdef{@code[(shift-time @i(sound) @i(shift))] @c{[lisp]}}@\Shift @i(sound) +by @i(shift) seconds. If the sound is +@pragma(startscribe) +@math[f(t)], then the result is +@pragma(endscribe) +@html[f(t), then the result is] +@pragma(startscribe) +@math[f(t - shift)]. +@pragma(endscribe) +@html[f(t - shift).] +See Figure @ref(shift-time-fig). This is a special +case of @code(snd-xform) (see Section @ref(snd-xform-sec)). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3 in, width = 4.5 in, magnify = 0.75, + postscript = "shifttimefig.ps")) +@html(

) +@fillcaption(The @code(shift-time) function shifts a sound in time +according to its @i(shift) argument.) +@tag(shift-time-fig) +@end(figure) + +@begin(fndefs) +@codef{sound-warp(@pragma(defn)@index(sound-warp)@i(warp-fn), @i(signal) [, @i(wrate)])} @c{[sal]}@* +@altdef{@code{(sound-warp @i(warp-fn) @i(signal) [@i(wrate)])} @c{[lisp]}}@\Applies a +warp function @i(warp-fn) to @i(signal) using function composition. If the optional parameter @i(wrate) is omitted or NIL, linear +interpolation is used. Otherwise, high-quality sample interpolation is used, and the +result is scaled by 0.95 to reduce problems with clipping (interpolated samples can +exceed the peak values of the input samples.) +@i(warp-fn) is a mapping from score (logical) time +to real time, and @i(signal) is a function from score time to real values. +The result is a function from real time to real values at a sample rate of @code(*sound-srate*). +See also @code(control-warp). +@blankspace(1) +If @i(wrate) is not NIL, it must be a number. The parameter indicates that +high-quality resampling should be used and specifies the sample rate for the +inverse of @i(warp-fn). Use the lowest number you can. + (See below for details.) Note that high-quality resampling is +much slower than linear interpolation. +@blankspace(1) +To perform high-quality resampling by a fixed ratio, as opposed to a +variable ratio allowed in @code(sound-warp), use @code(scale-srate) to +stretch or shrink the sound, and then @code(resample) to restore the +original sample rate. +@blankspace(1) +@code(Sound-warp) and @code(control-warp) both take the inverse of +@i(warp-fn) to get a function from real time to score time. Each sample +of this inverse is thus a score time; @i(signal) is evaluated at each of +these score times to yield a value, which is the desired result. The +sample rate of the inverse warp function is somewhat arbitrary. With linear +interpolation, the inverse warp function sample rate is taken to be the +output sample rate. Note, however, that the samples of the inverse warp +function are stored as 32-bit floats, so they have limited precision. Since +these floats represent sample times, rounding can be a problem. Rounding +in this case is equivalent to adding jitter to the sample times. Nyquist +ignores this problem for ordinary warping, but for high-quality warping, the +jitter cannot be ignored. +@blankspace(1) +The solution is to use a rather low sample rate +for the inverse warp function. @code(Sound-warp) can then linearly +interpolate this signal using double-precision floats to minimize jitter +between samples. The sample rate is a compromise: a low sample rate +minimizes jitter, while a high sample rate does a better job of capturing +detail (e.g. rapid fluctuations) in the warp function. A good rule of thumb +is to use at most 1,000 to 10,000 samples for the inverse warp function. For +example, if the result will be 1 minute of sound, use a sample rate of +3000 samples / 60 seconds = 50 samples/second. Because Nyquist has no +advance information about the warp function, the inverse warp function +sample rate must be provided as a parameter. When in doubt, just try +something and let your ears be the judge. + +@codef[integrate(@pragma(defn)@index(integrate)@index(smooth)@i(signal))] @c{[sal]}@* +@altdef{@code[(integrate @i(signal))] @c{[lisp]}}@\Computes the integral of @i(signal). The start time, sample rate, etc. are taken from @i(signal). + +@codef[slope(@pragma(defn)@index(slope)@index(derivative)@index(first derivative)@i(signal))] @c{[sal]}@* +@altdef{@code[(slope @i(signal))] @c{[lisp]}}@\Computes the first derivative (slope) of @i(signal). The start time, sample rate, etc. are taken from @i(signal). +@end(fndefs) + +@paragraph(Oscillators) +@label(osc-sec) +@begin(fndefs) +@codef{osc(@pragma(defn)@index(osc)@i(pitch) [, @i(duration), @i(table), @i(phase)])} @c{[sal]}@* +@altdef{@code{(osc @i(pitch) [@i(duration) @i(table) @i(phase)])} @c{[lisp]}}@\Returns +a sound which +is the @i(table) oscillated at @i(pitch) for the given @i(duration), +starting with the @i(phase) (in degrees). +Defaults are: @i(duration) @code(1.0) +(second), @i(table) @code(*table*), +@i(phase) @code(0.0). The default value of @code(*table*) is a sinusoid. Duration is stretched by @code(*warp*) and +@code(*sustain*), amplitude is nominally 1, but scaled by @code(*loudness*), the start time is logical time 0, transformed by @code(*warp*), and the sample rate is @code(*sound-srate*). +The effect of time-warping is to warp the starting and ending times only; the +signal has a constant unwarped frequency. + @p(Note 1:) @i(table) is a list of the form +@begin(display) +(@i(sound) @i(pitch-number) @i(periodic)) +@end(display) +where the first element is a sound, the second is the pitch of the sound +(this is not redundant, because the sound may represent any number of +periods), and the third element is @code(T) if the sound is one period of +a periodic signal, or @code(nil) if the sound is a sample that should not +be looped. The maximum table size is set by @code(max_table_len) in @code(sound.h), and is currently set to 1,000,000. +@p(Note 2:) in the current implementation, it is assumed that the +output should be periodic. See @code(snd-down) and @code(snd-up) for resampling one-shot sounds to a desired sample rate. A future version of @code(osc) +will handle both cases. +@p(Note 3:) When @code(osc) is called, memory is allocated for the table, and samples are copied from the sound (the first element of the list which is the @i(table) parameter) to the memory. Every instance of @code(osc) has a private copy of the table, so the total storage can become large in some cases, for example in granular synthesis with many instances of @code(osc). In some cases, it may make sense to use @code(snd-flatten) (see Section @ref(flatten-sec)) to cause the sound to be fully realized, after which the @code(osc) and its table memory can be reclaimed by garbage collection. The @code(partial) function (see below) does not need a private table and does not use much space. + +@label(partial-sec) +@codef{partial(@pragma(defn)@index(partial)@i(pitch), @i(env))} @c{[sal]}@* +@altdef{@code[(partial @i(pitch) @i(env))] @c{[lisp]}}@\Returns a sinusoid at +the indicated pitch; the sound is multiplied by @i(env). The start time and +duration are taken from @i(env), which is of course subject to +transformations. The sample rate is @code(*sound-srate*). The @code(partial) +function is faster than @code(osc). + +@label(sine-sec) +@codef{sine(@pragma(defn)@index(sine)@i(pitch) [, @i(duration)])} @c{[sal]}@* +@altdef{@code{(sine @i(pitch) [@i(duration)])} @c{[lisp]}}@\Returns a sinusoid at +the indicated pitch. The sample rate is @code(*sound-srate*). +This function is like @code(osc) with +respect to transformations. The @code(sine) function is faster than +@code(osc). + +@codef{hzosc(@pragma(defn)@index(hzosc)@i(hz) [, @i(table), @i(phase)])} @c{[sal]}@* +@altdef{@code{(hzosc @i(hz) [@i(table) @i(phase)])} @c{[lisp]}}@\Returns a sound which is the @i(table) oscillated at @i(hz) starting at @i(phase) degrees. The default @i(table) is @code(*table*) and the default @i(phase) is @i(0.0). The default duration is @code(1.0), but this is stretched as in @code(osc) (see above). The @i(hz) parameter may be a @code(SOUND), in which case the duration of the result is the duration of @i(hz). The sample rate is @code(*sound-srate*). + +@codef{osc-saw(@pragma(defn)@index(osc-saw)@index(sawtooth oscillator)@i(hz))} @c{[sal]}@* +@altdef{@code[(osc-saw @i(hz))] @c{[lisp]}}@\Returns a sawtooth waveshape at the indicated frequency (in Hertz). The sample rate is @code(*sound-srate*). The @i(hz) parameter may be a sound as in @i(hzosc) (see above). + +@codef{osc-tri(@pragma(defn)@index(osc-tri)@index(triangle oscillator)@i(hz))} @c{[sal]}@* +@altdef{@code[(osc-tri @i(hz))] @c{[lisp]}}@\Returns a triangle waveshape at the indicated frequency (in Hertz). The sample rate is @code(*sound-srate*). The @i(hz) parameter may be a sound as in @i(hzosc) (see above). + +@codef{osc-pulse(@pragma(defn)@index(osc-pulse)@index(square oscillator)@index(pulse oscillator)@index(pulse-width modulation)@i(hz), @i(bias) [, @i(compare-shape)])} @c{[sal]}@* +@altdef{@code{(osc-pulse @i(hz) @i(bias) [@i(compare-shape)])} @c{[lisp]}}@\Returns a square pulse with variable width at the indicated frequency (in Hertz). The @i(bias) parameter controls the pulse width and should be between @code(-1) and @code(+1), giving a pulse width from 0% (always at @code(-1)) to 100% (always at @code(+1)). When bias is zero, a square wave is generated. Bias may be a @code(SOUND) to create varying pulse width. If bias changes rapidly, strange effects may occur. The optional @i(compare-shape) defaults to a hard step at zero, but other shapes may be used to achieve non-square pulses. The @code(osc-pulse) behavior is written in terms of other behaviors and defined in the file @code(nyquist.lsp) using just a few lines of code. Read the code for the complete story. + +@label(amosc-sec) +@codef{amosc(@pragma(defn)@index(amosc)@i(pitch), @i(modulation) [, @i(table), +@i(phase)])} @c{[sal]}@* +@altdef{@code{(amosc @i(pitch) @i(modulation) [@i(table) @i(phase)])} @c{[lisp]}}@\Returns a +sound which is @i(table) oscillated at @i(pitch). The output +is multiplied by @i(modulation) +for the duration of the sound @i(modulation). +@i(osc-table) defaults to +@code(*table*), and @i(phase) is the starting phase (default 0.0 degrees) +within @i(osc-table). The sample rate is @code(*sound-srate*). + +@label(fmosc-sec) +@codef{fmosc(@pragma(defn)@index(fmosc)@i(pitch), @i(modulation) [, @i(table), +@i(phase)])} @c{[sal]}@* +@altdef{@code{(fmosc @i(pitch) @i(modulation) [@i(table) @i(phase)])} @c{[lisp]}}@\Returns a +sound which is @i(table) oscillated at @i(pitch) plus @i(modulation) +for the duration of the sound @i(modulation). +@i(osc-table) defaults to +@code(*table*), and @i(phase) is the starting phase (default 0.0 degrees) +within @i(osc-table). The @i(modulation) +is expressed in hz, e.g. a sinusoid modulation signal with an +amplitude of 1.0 (2.0 peak to peak), will cause a +/@subtract 1.0 hz +frequency deviation in @i(sound). Negative frequencies are correctly +handled. The sample rate is @code(*sound-srate*). + +@label(fmfb-sec) +@codef{fmfb(@pragma(defn)@index(fmfb)@index(Feedback FM Oscillator)@i(pitch), @i(index) [, @i(dur)])} @c{[sal]}@* +@altdef{@code{(fmfb @i(pitch) @i(index) [@i(dur)])} @c{[lisp]}}@\Returns +a sound generated by feedback FM synthesis. The @i(pitch) parameter +(given in the usual half-step units) +controls the fundamental frequency. The @i(index) is the amount of +feedback, which may be a @code(SOUND) or a @code(FLONUM). If @i(index) is +a @code(FLONUM), @i(dur) must be provided (a @code(FLONUM)) to specify +the duration. Otherwise, @i(dur) is ignored if present and the duration is +determined by that of @i(index). The sample rate is @code(*sound-srate*). +A sinusoid table is used. +If @i(index) is below 1.1, this generates a sawtooth-like waveform. + +@label(buzz-sec) +@codef{buzz(@pragma(defn)@index(buzz)@i(n), @i(pitch), @i(modulation))} @c{[sal]}@* +@altdef{@code[(buzz @i(n) @i(pitch) @i(modulation))] @c{[lisp]}}@\Returns a +sound with @i(n) harmonics of equal amplitude and a total amplitude +of 1.0, using a well-known function of two cosines. If @i(n) (an integer) +is less than 1, it is set to 1. Aliasing will occur if @i(n) is too large. +The duration is +determined by the duration of the sound @i(modulation), which is a +frequency modulation term expressed in Hz (see Section @ref(fmosc-sec)). +Negative frequencies are correctly handled. +The sample rate is @code(*sound-srate*). + +@label(pluck-sec) +@codef{pluck(@pragma(defn)@index(pluck)@index(Karplus-Strong)@index(string synthesis)@index(plucked string)@i(pitch) [, @i(duration), @i(final-amplitude)])} @c{[sal]}@* +@altdef{@code{(pluck @i(pitch) [@i(duration) @i(final-amplitude)])} @c{[lisp]}}@\Returns a sound at the +given @i(pitch) created using a modified Karplus-Strong plucked string +algorithm. The tone decays from an amplitude of about 1.0 to about +@i(final-amplitude) in @i(duration) seconds. The default values are to +decay to 0.001 (-60dB) in 1 second. The sample rate is @code(*sound-srate*). + +@label(siosc-sec) +@codef{siosc(@pragma(defn)@index(siosc)@index(spectral interpolation)@i(pitch), +@i(modulation), @i(tables))} @c{[sal]}@* +@altdef{@code[(siosc @i(pitch) @i(modulation) @i(tables))] @c{[lisp]}}@\Returns a sound constructed by +interpolating through a succession of periodic waveforms. The frequency is +given (in half steps) by @i(pitch) to which a @i(modulation) signal (in hz) +is added, exactly as in @code(fmosc). The @i(tables) specify a list of +waveforms as follows: (@i(table0) @i(time1) @i(table2) ... @i(timeN) +@i(tableN)), where each @i(table) is a sound representing one period. Each +@i(time) is a time interval measured from the starting time. The time is +scaled by the nominal duration (computed using @code[(local-to-global +(get-sustain))]) to get the actual time. Note that this implies linear +stretching rather than continuous timewarping of the interpolation or the +breakpoints. The waveform is @i(table0) at the starting time, @i(table1) +after @i(time1) (scaled as described), and so on. The duration and logical +stop time is given by @i(modulation). If @i(modulation) is shorter than +@i(timeN), then the full sequence of waveforms is not used. If +@i(modulation) is longer than @i(timeN), @i(tableN) is used after @i(timeN) +without further interpolation. + + +@label(sampler-sec) +@codef{sampler(@pragma(defn)@index(sampler)@i(pitch), @i(modulation) + [, @i(sample), @i(npoints)])} @c{[sal]}@* +@altdef{@code{(sampler @i(pitch) @i(modulation) [@i(sample) @i(npoints)])} @c{[lisp]}}@\Returns a sound constructed by reading a sample from +beginning to end and then splicing on copies of the same sound from +a loop point to the end. +The @i(pitch) and @i(modulation) parameters are used as in @code(fmosc) +described above. The optional @i(sample) (which defaults to the global +variable @code(*table*) is a list of the form +@begin(display) +(@i(sound) @i(pitch-number) @i(loop-start)) +@end(display) +where the first element is a sound containing the sample, the second is the +pitch of the sample, and the third element is the time of the loop point. If +the loop point is not in the bounds of the sound, it is set to zero. +The optional @i(npoints) specifies how many points should be used for sample +interpolation. Currently this parameter defaults to 2 and only 2-point +(linear) interpolation is implemented. It is an error to modulate such that the frequency +is negative. Note also that the loop point may be fractional. +The sample rate is @code(*sound-srate*). +@end(fndefs) + +@paragraph(Piece-wise Approximations) +@index(piece-wise)@index(approximation)@index(splines) +There are a number of related behaviors for piece-wise approximations to functions. The simplest of these, @code(pwl) was mentioned earlier in the manual. It takes a list of breakpoints, assuming an initial point at (0, 0), and a final value of 0. An analogous piece-wise exponential function, @code(pwe), is provided. Its implicit starting and stopping values are 1 rather than 0. Each of these has variants. You can specify the initial and final values (instead of taking the default). You can specify time in intervals rather than cummulative time. Finally, you can pass a list rather than an argument list. This leads to 16 versions: +@pragma(startscribe) +@begin(display) +@tabclear +@tabset(0.4 inches, 0.8 inches, 1.2 inches) +Piece-wise Linear Functions: +@\Cummulative Time: +@\@\Default initial point at (0, 0), final value at 0: +@\@\@\@code(pwl) +@\@\@\@code(pwl-list) +@\@\Explicit initial value: +@\@\@\@code(pwlv) +@\@\@\@code(pwlv-list) +@\Relative Time: +@\@\Default initial point at (0, 0), final value at 0: +@\@\@\@code(pwlr) +@\@\@\@code(pwlr-list) +@\@\Explicit initial value: +@\@\@\@code(pwlvr) +@\@\@\@code(pwlvr-list) +Piece-wise Exponential Functions: +@\Cummulative Time: +@\@\Default initial point at (0, 1), final value at 1: +@\@\@\@code(pwe) +@\@\@\@code(pwe-list) +@\@\Explicit initial value: +@\@\@\@code(pwev) +@\@\@\@code(pwev-list) +@\Relative Time: +@\@\Default initial point at (0, 1), final value at 1: +@\@\@\@code(pwer) +@\@\@\@code(pwer-list) +@\@\Explicit initial value: +@\@\@\@code(pwevr) +@\@\@\@code(pwevr-list) +@end(display) +@pragma(endscribe) +@html[
Piece-wise Linear Functions:
+	Cummulative Time:
+		Default initial point at (0, 0), final value at 0:
+			pwl
+			pwl-list
+		Explicit initial value:
+			pwlv
+			pwlv-list
+	Relative Time:
+		Default initial point at (0, 0), final value at 0:
+			pwlr
+			pwlr-list
+		Explicit initial value:
+			pwlvr
+			pwlvr-list
+
+Piece-wise Exponential Functions:
+	Cummulative Time:
+		Default initial point at (0, 1), final value at 1:
+			pwe
+			pwe-list
+		Explicit initial value:
+			pwev
+			pwev-list
+	Relative Time:
+		Default initial point at (0, 1), final value at 1:
+			pwer
+			pwer-list
+		Explicit initial value:
+			pwevr
+			pwevr-list
+
] +All of these functions are implemented in terms of @code(pwl) (see @code(nyquist.lsp) for the implementations. There are infinite opportunities for errors in these functions: if you leave off a data point, try to specify points in reverse order, try to create an exponential that goes to zero or negative values, or many other bad things, the behavior is not well-defined. Nyquist should not crash, but Nyquist does not necessarily attempt to report errors at this time. + +@begin(fndefs) +@label(pwl-sec) +@codef{pwl(@pragma(defn)@index(pwl)@i(t@-[1]), @i(l@-[1]), @i(t@-[2]), @i(l@-[2]), @r(...) @i(t@-[n]))} @c{[sal]}@* +@altdef{@code[(pwl @i(t@-[1]) @i(l@-[1]) @i(t@-[2]) @i(l@-[2]) @r(...) @i(t@-[n]))] @c{[lisp]}}@\Creates +a piece-wise linear envelope with breakpoints at (0, 0), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 0). The breakpoint +times are scaled linearly by the value of @code(*sustain*) (if +@code(*sustain*) is a @code(SOUND), it is evaluated once at the starting +time of the envelope). Each breakpoint time is then mapped according to +@code(*warp*). The result is a linear interpolation (unwarped) between +the breakpoints. The sample rate is @code(*control-srate*). Breakpoint +times are quantized to the nearest sample time. If you specify one or more +breakpoints withing one sample period, @code(pwl) attempts to give a good +approximation to the specified function. In particular, if two breakpoints +are simultaneous, @code(pwl) will move one of them to an adjacent sample, +producing a steepest possible step in the signal. The exact details of this +``breakpoint munging'' is subject to change in future versions. Please report +any cases where breakpoint lists give unexpected behaviors. The author will +try to apply the ``principle of least surprise'' to the design. Note that +the times are relative to 0; they are not durations of each envelope +segment. + +@codef{pwl-list(@pragma(defn)@index(pwl-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwl-list @i(breakpoints))] @c{[lisp]}}@\If you have a list of +breakpoints, you can use @code(apply) to apply the @code(pwl) function to +the breakpoints, but if the list is very long (hundreds or thousands of +points), you might get a stack overflow because XLISP has a fixed-size +argument stack. Instead, call @code(pwl-list), passing one argument, the +list of breakpoints. + +@codef{pwlv(@pragma(defn)@index(pwlv)@i(l@-[1]), @i(t@-[2]), @i(l@-[2]), @i(t@-[3]), @i(t@-[3]), ... @i(t@-[n]), @i(l@-[n]))} @c{[sal]}@* +@altdef{@code[(pwlv @i(l@-[1]) @i(t@-[2]) @i(l@-[2]) @i(t@-[3]) @i(t@-[3]) @r(...) @i(t@-[n]) @i(l@-[n]))] @c{[lisp]}}@\Creates +a piece-wise linear envelope with breakpoints at (0, l@-[1]), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n], @i(l@-[n])). Otherwise, the behavior is like that of @code(pwl). + +@codef{pwlv-list(@pragma(defn)@index(pwlv-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwlv-list @i(breakpoints))] @c{[lisp]}}@\A version of @code(pwlv) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwlr(@pragma(defn)@index(pwlr)@i(i@-[1]), @i(l@-[1]), @i(i@-[2]), @i(l@-[2]), ... @i(i@-[n]))} @c{[sal]}@* +@altdef{@code[(pwlr @i(i@-[1]) @i(l@-[1]) @i(i@-[2]) @i(l@-[2]) @r(...) @i(i@-[n]))] @c{[lisp]}}@\Creates +a piece-wise linear envelope with breakpoints at (0, 0), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 0), where @i(t@-[j]) is the sum of @i(i@-[1]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwl). + +@codef{pwlr-list(@pragma(defn)@index(pwlr-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwlr-list @i(breakpoints))] @c{[lisp]}}@\A version of @code(pwlr) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwlvr(@pragma(defn)@index(pwlvr)@i(l@-[1]), @i(i@-[2]), @i(l@-[2]), @i(i@-[3]), @i(i@-[3]), ... @i(i@-[n]), @i(l@-[n]))} @c{[sal]}@* +@altdef{@code[(pwlvr @i(l@-[1]) @i(i@-[2]) @i(l@-[2]) @i(i@-[3]) @i(i@-[3]) @r(...) @i(i@-[n]) @i(l@-[n]))] @c{[lisp]}}@\Creates +a piece-wise linear envelope with breakpoints at (0, l@-[1]), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n], @i(l@-[n])), where @i(t@-[j]) is the sum of @i(i@-[2]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwlv). + +@codef{pwlvr-list(@pragma(defn)@index(pwlvr-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwlvr-list @i(breakpoints))] @c{[lisp]}}@\A version of @code(pwlvr) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwe(@pragma(defn)@index(pwe)@i(t@-[1]), @i(l@-[1]), @i(t@-[2]), @i(l@-[2]), @r(...) @i(t@-[n]))} @c{[sal]}@* +@altdef{@code[(pwe @i(t@-[1]) @i(l@-[1]) @i(t@-[2]) @i(l@-[2]) @r(...) @i(t@-[n]))] @c{[lisp]}}@\Creates +a piece-wise exponential envelope with breakpoints at (0, 1), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 1). Exponential segments means that the ratio of values from sample to sample is constant within the segment. (The current implementation actually takes the log of each value, computes a piece-wise exponential from the points using @code(pwl), then exponentiates each resulting sample. A faster implementation is certainly possible!) Breakpoint values (@i(l@-[j])) must be greater than zero. Otherwise, this function is similar to @code(pwl), including stretch by @code(*sustain*), mapping according to @code(*warp*), sample rate based on @code(*control-srate*), and "breakpoint munging" (see @code(pwl) described above). @i(Default initial and final values are of dubious value with exponentials. See @code(pwev) below for the function you are probably looking for.) + +@codef{pwe-list(@pragma(defn)@index(pwe-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwe-list @i(breakpoints))] @c{[lisp]}}@\A version of @code(pwe) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@label(pwev-sec) +@codef{pwev(@pragma(defn)@index(pwev)@i(l@-[1]), @i(t@-[2]), @i(l@-[2]), @i(t@-[3]), @i(t@-[3]), @r(...) @i(t@-[n]), @i(l@-[n]))} @c{[sal]}@* +@altdef{@code[(pwev @i(l@-[1]) @i(t@-[2]) @i(l@-[2]) @i(t@-[3]) @i(t@-[3]) @r(...) @i(t@-[n]) @i(l@-[n]))] @c{[lisp]}}@\Creates +a piece-wise exponential envelope with breakpoints at (0, @i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n]), @i(l@-[n])). Otherwise, the behavior is like that of @code(pwe). + +@codef{pwev-list(@pragma(defn)@index(pwev-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwev-list @i(breakpoints))] @c{[lisp]}}@\A version of @code(pwev) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwer(@pragma(defn)@index(pwer)@i(i@-[1]), @i(l@-[1]), @i(i@-[2]), @i(l@-[2]), @r(...) @i(i@-[n]))} @c{[sal]}@* +@altdef{@code[(pwer @i(i@-[1]) @i(l@-[1]) @i(i@-[2]) @i(l@-[2]) @r(...) @i(i@-[n]))] @c{[lisp]}}@\Creates +a piece-wise exponential envelope with breakpoints at (0, 1), (@i(t@-[1]), +@i(l@-[1])), (@i(t@-[2]), @i(l@-[2])), ... (@i(t@-[n]), 1), where @i(t@-[j]) is the sum of @i(i@-[1]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwe). Consider using @code(pwerv) instead of this one. + +@codef{pwer-list(@pragma(defn)@index(pwer-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwer-list @i(breakpoints))] @c{[lisp]}}@\A version of @code(pwer) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. + +@codef{pwevr(@index(GEN05)@pragma(defn)@index(pwevr)@i(l@-[1]), @i(i@-[2]), @i(l@-[2]), @i(i@-[3]), @i(i@-[3]), @r(...) @i(i@-[n]), @i(l@-[n]))} @c{[sal]}@* +@altdef{@code[(pwevr @i(l@-[1]) @i(i@-[2]) @i(l@-[2]) @i(i@-[3]) @i(i@-[3]) @r(...) @i(i@-[n]) @i(l@-[n]))] @c{[lisp]}}@\Creates +a piece-wise exponential envelope with breakpoints at (0, l@-[1]), (@i(t@-[2]), @i(l@-[2])), etc., ending with (@i(t@-[n], @i(l@-[n])), where @i(t@-[j]) is the sum of @i(i@-[2]) through @i(i@-[j]). In other words, the breakpoint times are specified in terms of intervals rather than cummulative time. Otherwise, the behavior is like that of @code(pwev). Note that this is similar to the csound GEN05 generator. Which is uglier, @i(GEN05) or @i(pwevr)? + +@codef{pwevr-list(@pragma(defn)@index(pwevr-list)@i(breakpoints))} @c{[sal]}@* +@altdef{@code[(pwevr-list @i(breakpoints))] @c{[lisp]}}@\A version of @code(pwevr) that takes a single list of breakpoints as its argument. See @code(pwl-list) above for the rationale. +@end(fndefs) +@paragraph(Filter Behaviors) +@begin(fndefs) +@label(alpass-sec) +@codef{alpass(@index(all pass filter)@index(alpass filter)@pragma(defn)@index(alpass)@i(sound), @i(decay), @i(hz) [, @i(minhz)])} @c{[sal]}@* +@altdef{@code{(alpass @i(sound) @i(decay) @i(hz) [@i(minhz)])} @c{[lisp]}}@\Applies an all-pass filter to @i(sound). This all-pass filter creates a delay effect without the resonances of a comb filter. The decay time of the filter is given by @i(decay). The @i(hz) parameter must be a number or sound greater than zero. It is used to compute delay, which is then rounded to the nearest integer number of samples (so the frequency is not always exact. Higher sampling rates yield better delay resolution.) The @i(decay) may be a sound or a number. In either case, it must also be positive. (Implementation note: an exponentiation is needed to convert @i(decay) into the @i(feedback) parameter, and exponentiation is typically more time-consuming than the filter operation itself. To get high performance, provide @i(decay) at a low sample rate.) The resulting sound will have the start time, sample rate, etc. of @i(sound). If @i(hz) is of type @code(SOUND), the delay may be time-varying. Linear interpolation is then used for fractional sample delay, but it should be noted that linear interpolation implies a low-pass transfer function. Thus, this filter may behave differently with a constant @code(SOUND) than it does with a @code(FLONUM) value for @i(hz). In addition, if @i(hz) is of type @code(SOUND), then @i(minhz) is required. The @i(hz) parameter will be clipped to be greater than @i(minhz), placing an upper bound on the delay buffer length. + +@label(comb-sec) +@codef{comb(@pragma(defn)@index(comb)@index(comb filter)@i(sound), @i(decay), @i(hz))} @c{[sal]}@* +@altdef{@code[(comb @i(sound) @i(decay) @i(hz))] @c{[lisp]}}@\Applies a comb filter to @i(sound). A comb filter emphasizes (resonates at) frequencies that are multiples of a @i(hz). The decay time of the resonance is given by @i(decay). This is a variation on @code(feedback-delay) (see below). The @i(hz) parameter must be a number greater than zero. It is used to compute delay, which is then rounded to the nearest integer number of samples (so the frequency is not always exact. Higher sampling rates yield better delay resolution.) The @i(decay) may be a sound or a number. In either case, it must also be positive. (Implementation note: an exponentiation is needed to convert @i(decay) into the @i(feedback) parameter for @code(feedback-delay), and exponentiation is typically more time-consuming than the filter operation itself. To get high performance, provide @i(decay) at a low sample rate.) The resulting sound will have the start time, sample rate, etc. of @i(sound). + +@label(congen-sec) +@codef{congen(@pragma(defn)@index(congen)@index(contour generator)@index(envelope generator)@i(gate), @i(risetime), @i(falltime))} @c{[sal]}@* +@altdef{@code[(congen @i(gate) @i(risetime) @i(falltime))] @c{[lisp]}}@\Implements an analog synthesizer-style contour generator. The input @i(gate) normally goes from 0.0 to 1.0 to create an attack and from 1.0 to 0.0 to start a release. During the attack (output is increasing), the output converges half-way to @i(gate) in @i(risetime) (a @code(FLONUM)) seconds. During the decay, the half-time is @i(falltime) seconds. The sample rate, start time, logical stop, and terminate time all come from @i(gate). If you want a nice decay, be sure that the @i(gate) goes to zero and stays there for awhile before @i(gate) terminates, because @code(congen) (and all Nyquist sounds) go immediately to zero at termination time. For example, you can use @code(pwl) to build a pulse followed by some zero time: +@begin(example) +(pwl 0 1 duty 1 duty 0 1) +@end(example) +Assuming @i(duty) is less than 1.0, this will be a pulse of duration @i(duty) followed by zero for a total duration of 1.0. +@begin(example) +(congen (pwl 0 1 duty 1 duty 0 1) 0.01 0.05) +@end(example) +will have a duration of 1.0 because that is the termination time of the @code(pwl) input. The decaying release of the resulting envelope will be truncated to zero at time 1.0. (Since the decay is theoretically infinite, there is no way to avoid truncation, although you could multiply by another envelope that smoothly truncates to zero in the last millisecond or two to get both an exponential decay and a smooth final transition to zero.) + +@label(convolve-sec) +@codef{convolve(@pragma(defn)@index(convolve)@index(convolution)@index(FIR filter)@i(sound), +@i(response))} @c{[sal]}@* +@altdef{@code[(convolve @i(sound) @i(response))] @c{[lisp]}}@\Convolves two signals. The first can be any length, but the +computation time per sample and the total space required are proportional to +the length of @i(response). + +@label(feedback-delay-sec) +@codef{feedback-delay(@pragma(defn)@index(feedback-delay)@index(delay)@index(echo)@i(sound), @i(delay), @i(feedback))} @c{[sal]}@* +@altdef{@code[(feedback-delay @i(sound) @i(delay) @i(feedback))] @c{[lisp]}}@\Applies feedback delay to @i(sound). The @i(delay) must be a number (in seconds). It is rounded to the nearest sample to determine the length of the delay. The sample rate is the maximum from @i(sound) and @i(feedback) (if feedback is also a sound). The amound of @i(feedback) should be less than one to avoid an exponential increase in amplitude. The start time and stop time, and logical stop time are taken from @i(sound). Since output is truncated at the stop time of @i(sound), you may want to append some silence to @i(sound) to give the filter time to decay. + +@label(lp-sec) +@codef{lp(@pragma(defn)@index(lp)@index(low-pass filter)@i(sound), @i(cutoff))} @c{[sal]}@* +@altdef{@code[(lp @i(sound) @i(cutoff))] @c{[lisp]}}@\Filters @i(sound) +using a first-order Butterworth low-pass filter. @i(Cutoff) may be a float +or a signal (for time-varying filtering) and expresses hertz. Filter +coefficients (requiring trig functions) are recomputed at the sample rate of +@i(cutoff). The resulting sample rate, start time, etc. are taken from @i(sound). + +@codef{tone(@pragma(defn)@index(tone)@i(sound), @i(cutoff))} @c{[sal]}@* +@altdef{@code[(tone @i(sound) @i(cutoff))] @c{[lisp]}}@\No longer defined; use @code(lp) instead, or define it by adding @code[(setfn tone lp)] to your program. + + +@label(hp-sec) +@codef{hp(@pragma(defn)@index(hp)@index(high-pass filter)@i(sound), @i(cutoff))} @c{[sal]}@* +@altdef{@code[(hp @i(sound) @i(cutoff))] @c{[lisp]}}@\Filters @i(sound) +using a first-order Butterworth high-pass filter. @i(Cutoff) may be a +float or a signal (for time-varying filtering) and expresses hertz. Filter +coefficients (requiring trig functions) are recomputed at the sample rate of +@i(cutoff). This filter is an exact complement of @code(lp). + +@codef{atone(@pragma(defn)@index(atone)@i(sound), @i(cutoff))} @c{[sal]}@* +@altdef{@code[(atone @i(sound) @i(cutoff))] @c{[lisp]}}@\No longer defined; use @code(hp) instead, or define it by adding @code[(setfn atone hp)] to your program. + +@label(reson-sec) +@codef{reson(@pragma(defn)@index(reson)@index(bandpass filter)@i(sound), @i(center), @i(bandwidth), @i(n))} @c{[sal]}@* +@altdef{@code[(reson @i(sound) @i(center) @i(bandwidth) @i(n))] @c{[lisp]}}@\Apply +a resonating filter to @i(sound) with center frequency @i(center) (in hertz), +which may be a float or a signal. @i(Bandwidth) is the filter bandwidth (in +hertz), which may also be a signal. Filter coefficients (requiring trig +functions) are recomputed at each new sample of either @i(center) or +@i(bandwidth), and coefficients are @i(not) interpolated. The last +parameter @i(n) specifies the type of normalization as in Csound: A value of 1 specifies a peak amplitude +response of 1.0; all frequencies other than @i(hz) are attenuated. A +value of 2 specifies the overall RMS value of the amplitude response +is 1.0; thus filtered white noise would retain the same power. A value of +zero specifies no scaling. The resulting sample rate, start time, etc. are taken from @i(sound). + +One application of @code(reson) is to simulate resonances in the human vocal tract. +See @code(demos/voice_synthesis.htm)@index(voice synthesis)@index(demos, voice synthesis) +for sample code and documentation. + +@label(areson-sec) +@codef{areson(@pragma(defn)@index(areson)@index(notch filter)@i(sound), @i(center), @i(bandwidth), @i(n))} @c{[sal]}@* +@altdef{@code[(areson @i(sound) @i(center) @i(bandwidth) @i(n))] @c{[lisp]}}@\The @code(areson) filter is an exact +complement of @code(reson) such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. + +@label(shape-sec) +@codef{shape(@pragma(defn)@index(shape)@index(waveshaping)@index(table)@i(signal), @i(table), @i(origin))} @c{[sal]}@* +@altdef{@code[(shape @i(signal) @i(table) @i(origin))] @c{[lisp]}}@\A waveshaping function. Use @i(table) as a function; apply the function to each sample of @i(signal) to yield a new sound. @i(Signal) should range from -1 to +1. Anything beyond these bounds is clipped. @i(Table) is also a sound, but it is converted into a lookup table (similar to table-lookup oscillators). The @i(origin) is a @code(FLONUM) and gives the time which should be considered the origin of @i(table). (This is important because @i(table) cannot have values at negative times, but @i(signal) will often have negative values. The @i(origin) gives an offset so that you can produce suitable tables.) The output at time @i(t) is: +@begin(display) +@i(table)(@i(origin) + clip(@i(signal)(@i(t))) +@end(display) +where clip(@i(x)) = @i(max)(1, @i(min)(-1, @i(x))). +(E.g. if @i(table) is a signal defined over the interval [0, 2], then @i(origin) should be 1.0. The value of @i(table) at time 1.0 will be output when the input signal is zero.) The output has the same start time, sample rate, etc. as @i(signal). The @code(shape) function will also accept multichannel @i(signal)s and @i(table)s. + +Further discussion and examples can be found in +@code(demos/distortion.htm)@index(distortion tutorial)@index(demos, distortion). +The @code(shape) +function is also used to map frequency to amplitude to achieve a spectral envelope for +Shepard tones in @code(demos/shepard.lsp).@index(Shepard tones)@index(demos, Shepard tones) + +@label(biquad-sec) +@codef{biquad(@pragma(defn)@index(biquad)@i(signal), @i(b0), @i(b1), @i(b2), @i(a0), @i(a1), @i(a2))} @c{[sal]}@* +@altdef{@code[(biquad @i(signal) @i(b0) @i(b1) @i(b2) @i(a0) @i(a1) @i(a2))] @c{[lisp]}}@\A fixed-parameter biquad filter. All filter coefficients are @code(FLONUM)s. See also @code(lowpass2), @code(highpass2), @code(bandpass2), @code(notch2), @code(allpass2), @code(eq-lowshelf), @code(eq-highshelf), @code(eq-band), @code(lowpass4), @code(lowpass6), @code(highpass4), and @code(highpass8) in this section for convenient variations based on the same filter. The equations for the filter are: z@-[n] = s@-[n] + a1 * z@-[n-1] + a2 * z@-[n-2], and y@-[n] = z@-[n] * b0 + z@-[n-1] * b1 + z@-[n-2] * b2. + +@label(biquad-m-sec) +@codef{biquad-m(@pragma(defn)@index(biquad-m)@i(signal), @i(b0), @i(b1), @i(b2), @i(a0), @i(a1), @i(a2))} @c{[sal]}@* +@altdef{@code[(biquad-m @i(signal) @i(b0) @i(b1) @i(b2) @i(a0) @i(a1) @i(a2))] @c{[lisp]}}@\A fixed-parameter biquad filter with Matlab sign conventions for @i(a0), @i(a1), and @i(a2). All filter coefficients are @code(FLONUM)s. + +@label(lowpass2-sec) +@codef{lowpass2(@pragma(defn)@index(lowpass2)@i(signal), @i(hz) [, @i(q)])} @c{[sal]}@* +@altdef{@code{(lowpass2 @i(signal) @i(hz) [@i(q)])} @c{[lisp]}}@\A fixed-parameter, second-order lowpass filter based on @code(snd-biquad). The cutoff frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(highpass2-sec) +@codef{highpass2(@pragma(defn)@index(highpass2)@i(signal), @i(hz) [, @i(q)])} @c{[sal]}@* +@altdef{@code{(highpass2 @i(signal) @i(hz) [@i(q)])} @c{[lisp]}}@\A fixed-parameter, second-order highpass filter based on @code(snd-biquad). The cutoff frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(bandpass2-sec) +@codef{bandpass2(@pragma(defn)@index(bandpass2)@i(signal), @i(hz) [, @i(q)])} @c{[sal]}@* +@altdef{@code{(bandpass2 @i(signal) @i(hz) [@i(q)])} @c{[lisp]}}@\A fixed-parameter, second-order bandpass filter based on @code(snd-biquad). The center frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(notch2-sec) +@codef{notch2(@pragma(defn)@index(notch2)@i(signal), @i(hz) [, @i(q)])} @c{[sal]}@* +@altdef{@code{(notch2 @i(signal) @i(hz) [@i(q)])} @c{[lisp]}}@\A fixed-parameter, second-order notch filter based on @code(snd-biquad). The center frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(allpass2-sec) +@codef{allpass2(@pragma(defn)@index(allpass2)@i(signal), @i(hz) [, @i(q)])} @c{[sal]}@* +@altdef{@code{(allpass2 @i(signal) @i(hz) [@i(q)])} @c{[lisp]}}@\A fixed-parameter, second-order allpass filter based on @code(snd-biquad). The frequency is given by @i(hz) (a @code(FLONUM)) and an optional Q factor is given by @i(q) (a @code(FLONUM)). + +@label(eq-lowshelf-sec) +@codef{eq-lowshelf(@pragma(defn)@index(eq-lowshelf)@index(equalization)@i(signal), @i(hz), @i(gain) [, @i(slope)])} @c{[sal]}@* +@altdef{@code{(eq-lowshelf @i(signal) @i(hz) @i(gain) [@i(slope)])} @c{[lisp]}}@\A fixed-parameter, second-order bass shelving equalization (EQ) filter based on @code(snd-biquad). The @i(hz) parameter (a @code(FLONUM))is the halfway point in the transition, and @i(gain) (a @code(FLONUM)) is the bass boost (or cut) in dB. The optional @i(slope) (a @code(FLONUM)) is 1.0 by default, and response becomes peaky at values greater than 1.0. + +@label(eq-highshelf-sec) +@codef{eq-highshelf(@pragma(defn)@index(eq-highshelf)@index(equalization)@i(signal), @i(hz), @i(gain) [, @i(slope)])} @c{[sal]}@* +@altdef{@code{(eq-highshelf @i(signal) @i(hz) @i(gain) [@i(slope)])} @c{[lisp]}}@\A fixed-parameter, second-order treble shelving equalization (EQ) filter based on @code(snd-biquad). The @i(hz) parameter (a @code(FLONUM))is the halfway point in the transition, and @i(gain) (a @code(FLONUM)) is the treble boost (or cut) in dB. The optional @i(slope) (a @code(FLONUM)) is 1.0 by default, and response becomes peaky at values greater than 1.0. + +@label(eq-band-sec) +@codef{eq-band(@pragma(defn)@index(eq-band)@index(equalization)@i(signal), @i(hz), @i(gain), @i(width))} @c{[sal]}@* +@altdef{@code[(eq-band @i(signal) @i(hz) @i(gain) @i(width))] @c{[lisp]}}@\A fixed- or variable-parameter, second-order midrange equalization (EQ) filter based on @code(snd-biquad), @code(snd-eqbandcv) and @code(snd-eqbandvvv). The @i(hz) parameter (a @code(FLONUM)) is the center frequency, @i(gain) (a @code(FLONUM)) is the boost (or cut) in dB, and @i(width) (a @code(FLONUM)) is the half-gain width in octaves. Alternatively, @i(hz), @i(gain), and @i(width) may be @code(SOUND)s, but they must all have the same sample rate, e.g. they should all run at the control rate or at the sample rate. + +@label(lowpass4-sec) +@codef{lowpass4(@pragma(defn)@index(lowpass4)@i(signal), @i(hz))} @c{[sal]}@* +@altdef{@code[(lowpass4 @i(signal) @i(hz))] @c{[lisp]}}@\A four-pole Butterworth lowpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(lowpass6-sec) +@codef{lowpass6(@pragma(defn)@index(lowpass6)@i(signal), @i(hz))} @c{[sal]}@* +@altdef{@code[(lowpass6 @i(signal) @i(hz))] @c{[lisp]}}@\A six-pole Butterworth lowpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(lowpass8-sec) +@codef{lowpass8(@pragma(defn)@index(lowpass8)@i(signal), @i(hz))} @c{[sal]}@* +@altdef{@code[(lowpass8 @i(signal) @i(hz))] @c{[lisp]}}@\An eight-pole Butterworth lowpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(highpass4-sec) +@codef{highpass4(@pragma(defn)@index(highpass4)@i(signal), @i(hz))} @c{[sal]}@* +@altdef{@code[(highpass4 @i(signal) @i(hz))] @c{[lisp]}}@\A four-pole Butterworth highpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(highpass6-sec) +@codef{highpass6(@pragma(defn)@index(highpass6)@i(signal), @i(hz))} @c{[sal]}@* +@altdef{@code[(highpass6 @i(signal) @i(hz))] @c{[lisp]}}@\A six-pole Butterworth highpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(highpass8-sec) +@codef{highpass8(@pragma(defn)@index(highpass8)@i(signal), @i(hz))} @c{[sal]}@* +@altdef{@code[(highpass8 @i(signal) @i(hz))] @c{[lisp]}}@\An eight-pole Butterworth highpass filter. The cutoff frequency is @i(hz) (a @code(FLONUM)). + +@label(tapv-sec) +@codef{tapv(@pragma(defn)@index(tapv)@index(variable delay)@index(tapped delay)@i(sound), @i(offset), +@i(vardelay), @i(maxdelay))} @c{[sal]}@* +@altdef{@code[(tapv @i(sound) @i(offset) @i(vardelay) @i(maxdelay))] @c{[lisp]}}@\A delay line with a variable position tap. +Identical to @code(snd-tapv). See it for details (@ref(snd-tapv-sec)). + +@end(fndefs) + +@paragraph(Effects) +@begin(fndefs) +@label(stkrev-sec) +@codef{nrev(@pragma(defn)@index(nrev)@index(reverb)@index(effect, +reverberation)@index(STK nreverb)@i(sound), @i(decay), @i(mix))} @c{[sal]}@* +@altdef{@code[(nrev @i(sound) @i(decay) @i(mix))] @c{[lisp]}} + +@codef{jcrev(@pragma(defn)@index(jcrev)@index(reverb)@index(effect, + reverberation)@index(STK jcreverb)@i(sound), @i(decay), @i(mix))} @c{[sal]}@* +@altdef{@code[(jcrev @i(sound) @i(decay) @i(mix))] @c{[lisp]}} + +@codef{prcrev(@pragma(defn)@index(prcrev)@index(reverb)@index(effect, + reverberation)@index(STK prcreverb)@i(sound), @i(decay), @i(mix))} @c{[sal]}@* +@altdef{@code[(prcrev @i(sound) @i(decay) @i(mix))] @c{[lisp]}} +These reverbs (@code(nrev), @code(jcrev), and @code(prcrev)) are implemented +in STK (running within Nyquist). @code(nrev) derives from Common Music's +NRev, which consists of 6 comb filters followed by 3 allpass filters, a + lowpass filter, and another allpass in series followed by two allpass +filters in parallel. @code(jcrev) is the John Chowning +reverberator which is based on the use of networks of simple allpass +and comb delay filters. This reverb implements three series allpass units, +followed by four parallel comb filters, and two decorrelation delay +lines in parallel at the output. @code(prcrev) is a Perry Cook's +reverberator which is based on the Chowning/Moorer/Schroeder +reverberators using networks of simple allpass and comb delay filters. +This one implements two series allpass units and two parallel comb filters. +The @i(sound) input may be single or multi-channel. The @i(decay) time is +in seconds, and @i(mix) sets the mixture of input sound reverb sound, +where 0.0 means input only (dry) and 1.0 means reverb only (wet). + +@label(stkchorus-sec) +@codef{stkchorus(@pragma(defn)@index(stkchorus)@index(chorus)@index(effect, chorus)@index(STK chorus)@i(sound), @i(depth), @i(freq), @i(mix) [, @i(delay)])} @c{[sal]}@* +@altdef{@code{(stkchorus @i(sound) @i(depth) @i(freq) @i(mix) [@i(delay)])} @c{[lisp]}}@\Chorus +implemented in STK. The input @i(sound) can be single or multi-channel. +The @code(FLONUM) parameters @i(depth) and @i(freq) set +the modulation +depth from 0 to 1 +and modulation frequency (in Hz), and @i(mix) sets the mixture +of input sound and chorused sound, where 0.0 means input sound only (dry) +and 1.0 means chorused sound only (wet). The parameter @i(delay) is a + @code(FIXNUM) representing the median desired delay length in samples. + +@label(stkpitshift-sec) +@codef{pitshift(@pragma(defn)@index(pitshift)@index(pitch shift)@index(effect, pitch shift)@index(STK pitch shift)@i(sound), @i(shift), @i(mix))} @c{[sal]}@* +@altdef{@code[(pitshift @i(sound) @i(shift) @i(mix))] @c{[lisp]}}@\A pitch + shifter implemented in STK. The input @i(sound), a single-channel + or multi-channel @code(SOUND) is pitch-shifted by @i(shift), +a @code(FLONUM) ratio. A value of 1.0 means no shift. The parameter @i(mix) + sets the mixture of input and shifted sounds. A value of 0.0 +means input only (dry) +and a value of 1.0 means shifted sound only (wet). +@end(fndefs) + +@paragraph(Physical Models) +@begin(fndefs) +@label(clarinet-sec) +@codef{clarinet(@pragma(defn)@index(clarinet)@index(stk clarinet)@i(step), @i(breath-env))} @c{[sal]}@* +@altdef{@code[(clarinet @i(step) @i(breath-env))] @c{[lisp]}}@\A +physical model of a clarinet from STK. The @i(step) parameter is a @code(FLONUM) +that controls the tube length, and the @i(breath-env) (a @code(SOUND)) +controls the air pressure +and also determines the length of the resulting sound. The @i(breath-env) signal +should range from zero to one. + +@codef{clarinet-freq(@index(clarinet)@pragma(defn)@index(clarinet-freq)@index(stk clarinet)@i(step), @i(breath-env), @i(freq-env))} @c{[sal]}@* +@altdef{@code[(clarinet-freq @i(step) @i(breath-env) @i(freq-env))] @c{[lisp]}}@\A variation of @code(clarinet) +that includes a variable frequency control, @i(freq-env), which specifies +frequency deviation in Hz. The duration of the resulting sound is the minimum +duration of @i(breath-env) and @i(freq-env). These parameters may be of type +@code(FLONUM) or @code(SOUND). @code(FLONUM)s are coerced into @code(SOUND)s +with a nominal duration arbitrarily set to 30. + +@codef{clarinet-all(@index(clarinet)@pragma(defn)@index(clarinet-all)@index(stk clarinet)@i(step), @i(breath-env), @i(freq-env), @i(vibrato-freq), @i(vibrato-gain), +@i(reed-stiffness), @i(noise))} @c{[sal]}@* +@altdef{@code[(clarinet-all @i(step) @i(breath-env) @i(freq-env) @i(vibrato-freq) @i(vibrato-gain) @i(reed-stiffness) @i(noise))] @c{[lisp]}}@\A variation of @code(clarinet-freq) +that includes controls @i(vibrato-freq) (a @code(FLONUM) for vibrato frequency in Hertz), +@i(vibrato-gain) (a @code(FLONUM) for the amount of amplitude vibrato), +@i(reed-stiffness) (a @code(FLONUM) or @code(SOUND) controlling reed stiffness in the clarinet +model), and @i(noise) (a @code(FLONUM) or @code(SOUND) controlling noise amplitude in the input +air pressure). The @i(vibrato-gain) is a number from zero to one, where zero +indicates no vibrato, and one indicates a plus/minus 50% change in breath +envelope values. Similarly, the @i(noise) parameter ranges from zero to one where +zero means no noise and one means white noise with a peak amplitude of +plus/minus 40% of the @i(breath-env). The @i(reed-stiffness) parameter varies +from zero to one. +The duration of the resulting sound is the minimum duration of +@i(breath-env), @i(freq-env), @i(reed-stiffness), and @i(noise). As with +@code(clarinet-freq), these parameters may be either @code(FLONUM)s or +@code(SOUND)s, and @code(FLONUM)s are coerced to sounds with a nominal +duration of 30. + +@label(sax-sec) +@codef{sax(@pragma(defn)@index(sax)@index(stk sax)@i(step), @i(breath-env))} @c{[sal]}@* +@altdef{@code[(sax @i(step) @i(breath-env))] @c{[lisp]}}@\A +physical model of a sax from STK. The @i(step) parameter is a @code(FLONUM) +that controls the tube length, and the @i(breath-env) controls the air pressure +and also determines the length of the resulting sound. The @i(breath-env) signal +should range from zero to one. + +@codef{sax-freq(@pragma(defn)@index(sax)@index(sax-freq)@index(stk sax)@i(step), @i(breath-env), @i(freq-env))} @c{[sal]}@* +@altdef{@code[(sax-freq @i(step) @i(breath-env) @i(freq-env))] @c{[lisp]}}@\A variation of @code(sax) +that includes a variable frequency control, @i(freq-env), which specifies +frequency deviation in Hz. The duration of the resulting sound is the minimum +duration of @i(breath-env) and @i(freq-env). These parameters may be of type +@code(FLONUM) or @code(SOUND). @code(FLONUM)s are coerced into @code(SOUND)s +with a nominal duration arbitrarily set to 30. + +@codef{sax-all(@pragma(defn)@index(sax)@index(sax-all)@index(stk sax)@i(step), @i(breath-env), @i(freq-env), @i(vibrato-freq), @i(vibrato-gain), +@i(reed-stiffness), @i(noise), @i(blow-pos), @i(reed-table-offset))} @c{[sal]}@* +@altdef{@code[(sax-all @i(step) @i(breath-env) @i(freq-env) @i(vibrato-freq) @i(vibrato-gain) @i(reed-stiffness) @i(noise) @i(blow-pos) @i(reed-table-offset))] @c{[lisp]}}@\A variation of + @code(sax-freq) +that includes controls @i(vibrato-freq) (a @code(FLONUM) for vibrato frequency in Hertz), +@i(vibrato-gain) (a @code(FLONUM) for the amount of amplitude vibrato), +@i(reed-stiffness) (a @code(SOUND) controlling reed stiffness in the sax +model), @i(noise) (a @code(SOUND) controlling noise amplitude in the input +air pressure), @i(blow-pos) (a @code(SOUND) controlling the point of excitation +of the air column), and @i(reed-table-offset) (a @code(SOUND) controlling a +parameter of the reed model). The @i(vibrato-gain) is a number from zero to one, where zero +indicates no vibrato, and one indicates a plus/minus 50% change in breath +envelope values. Similarly, the @i(noise) parameter ranges from zero to one where +zero means no noise and one means white noise with a peak amplitude of +plus/minus 40% of the @i(breath-env). The @i(reed-stiffness), @i(blow-pos), and +@i(reed-table-offset) parameters all vary from zero to one. +The duration of the resulting sound is the minimum duration of +@i(breath-env), @i(freq-env), @i(reed-stiffness), @i(noise), @i(breath-env), + @i(blow-pos), and @i(reed-table-offset). As with +@code(sax-freq), these parameters may be either @code(FLONUM)s or +@code(SOUND)s, and @code(FLONUM)s are coerced to sounds with a nominal +duration of 30. + +@label(flute-sec) +@codef{flute(@pragma(defn)@index(flute)@index(STK flute)@i(step), @i(breath-env))} @c{[sal]}@* +@altdef{@code[(flute @i(step) @i(breath-env))] @c{[lisp]}}@\A physical model of a flute from STK. +The @i(step) parameter is a @code(FLONUM) that controls the tube +length, and the @i(breath-env) +controls the air pressure and also determines the starting time and +length of the resulting sound. The @i(breath-env) signal should + range from zero to one. + +@codef{flute-freq(@pragma(defn)@index(flute-freq)@index(STK flute)@i(step), @i(breath-env), @i(freq-env))} @c{[sal]}@* +@altdef{@code[(flute-freq @i(step) @i(breath-env) @i(freq-env))] @c{[lisp]}}@\A variation of @code(flute) + that includes a variable frequency control, @i(freq-env), which + specifies frequency deviation in Hz. The duration of the +resulting sound is the minimum duration of @i(breath-env) and +@i(freq-env). These parameters may be of type @code(FLONUM) or + @code(SOUND). @code(FLONUM)s are coerced into SOUNDs with a +nominal duration arbitrary set to 30. + +@codef{flute-all(@pragma(defn)@index(flute-all)@index(STK flute)@i(step), @i(breath-env), @i(freq-env), @i(vibrato-freq), + @i(vibrato-gain), @i(jet-delay), @i(noise))} @c{[sal]}@* +@altdef{@code[(flute-all @i(step) @i(breath-env) @i(freq-env) @i(vibrato-freq) @i(vibrato-gain) @i(jet-delay) @i(noise))] @c{[lisp]}}@\A variation of +@code(clarinet-freq) that includes controls @i(vibrato-freq) (a +@code(FLONUM) for vibrato frequency in Hz), @i(vibrato-gain) (a + @code(FLONUM) for the amount of amplitude vibrato), @i(jet-delay) + (a @code(FLONUM) or @code(SOUND) controlling jet delay in the + flute model), and +noise (a @code(FLONUM) or @code(SOUND) controlling noise amplitude +in the input air pressure). The @i(vibrato-gain) is a number from zero + to one where zero means no vibrato, and one indicates a plus/minus +50% change in breath envelope values. Similarly, the @i(noise) parameter + ranges from zero to one, where zero means no noise and one means white +noise with a peak amplitude of + plus/minus 40% of the @i(breath-env). The @i(jet-delay) is a ratio + that controls a delay length from the flute model, and therefore it +changes the pitch of the resulting sound. A value of 0.5 will maintain +the pitch indicated by the step parameter. The duration of the +resulting sound is the minimum duration of @i(breath-env), @i(freq-env), +@i(jet-delay), and @i(noise). These parameters may be either +@code(FLONUM)s or @code(SOUND)s, and @code(FLONUM)s are coerced + to sounds with a nominal duration of 30. + +@label(bowed-sec) +@codef{bowed(@pragma(defn)@index(bowed)@index(STK bowed string)@i(step), @i(bowpress-env))} @c{[sal]}@* +@altdef{@code[(bowed @i(step) @i(bowpress-env))] @c{[lisp]}}@\A physical model of a bowed string + instrument from STK. The @i(step) parameter is a @code(FLONUM) + that controls the string length, + and the @i(bowpress-env) controls the bow pressure and also +determines the duration of the resulting sound. The @i(bowpress-env) + signal should range from zero to one. + +@codef{bowed-freq(@pragma(defn)@index(bowed-freq)@index(STK bowed-freq)@i(step), @i(bowpress-env), @i(freq-env))} @c{[sal]}@* +@altdef{@code[(bowed-freq @i(step) @i(bowpress-env) @i(freq-env))] @c{[lisp]}}@\A variation of @code(bowed) + that includes a variable frequency control, @i(freq-env), which + specifies frequency deviation in Hz. The duration of the resulting + sound is the minimum duration of @i(bowpress-env) and @i(freq-env). +These parameters may be of type @code(FLONUM) or @code(SOUND). +@code(FLONUM)s are coerced into @code(SOUND)s + with a nominal duration arbitrarily set to 30s. + +@label(mandolin-sec) +@codef{mandolin(@pragma(defn)@index(mandolin)@index(STK mandolon)@i(step), @i(dur), &optional @i(detune))} @c{[sal]}@* +@altdef{@code[(mandolin @i(step) @i(dur) @i(detune))] @c{[lisp]}}@\A physical model of a + plucked double-string instrument from STK. The @i(step) parameter + is a @code(FLONUM) wich specifies the desired pitch, @i(dur) + means the duration of the resulting sound and detune is a +@code(FLONUM) that controls the relative detune of the two strings. +A value of 1.0 means unison. The default value is 4.0. +Note: @i(body-size) (see @code(snd-mandolin) does not seem to + work correctly, so a default value is always used + by @code(mandolin). + +@label(bandedwg-sec) +@codef{wg-uniform-bar(@pragma(defn)@index(wg-uniform-bar)@index(STK uniform bar)@i(step), @i(bowpress-env))} @c{[sal]}@* +@altdef{@code[(wg-uniform-bar @i(step) @i(bowpress-env))] @c{[lisp]}} + +@codef{wg-tuned-bar(@pragma(defn)@index(wg-tuned-bar)@index(STK tuned bar)@i(step), @i(bowpress-env))} @c{[sal]}@* +@altdef{@code[(wg-tuned-bar @i(step) @i(bowpress-env))] @c{[lisp]}} + +@codef{wg-glass-harm(@pragma(defn)@index(wg-glass-harm)@index(STK glass harmonica)@i(step), @i(bowpress-env))} @c{[sal]}@* +@altdef{@code[(wg-glass-harm @i(step) @i(bowpress-env))] @c{[lisp]}} + +@codef{wg-tibetan-bowl(@pragma(defn)@index(wg-tibetan-bowl)@index(STK tibetan bowl)@i(step), @i(bowpress-env))} @c{[sal]}@* +@altdef{@code[(wg-tibetan-bowl @i(step) @i(bowpress-env))] @c{[lisp]}}@\These +sounds are presets for a Banded Wave Guide Percussion instrument implemented in STK. +The parameter @i(step) is a @code(FLONUM) + that controls the resultant pitch, and @i(bowpress-env) is a @code(SOUND) ranging +from zero to one that controls a parameter of the model. In addition, +@i(bowpress-env) determines the duration of the resulting sound. +(Note: The @i(bowpress-env) does not seems influence the timbral +quality of the resulting sound). + +@label(modalbar-sec) +@codef{modalbar(@pragma(defn)@index(modalbar)@index(STK modal bar)@i(preset), @i(step), @i(dur))} @c{[sal]}@* +@altdef{@code[(modalbar @i(preset) @i(step) @i(dur))] @c{[lisp]}}@\A physical model of a struck bar + instrument implemented in STK. The parameter @i(preset) is one of the +symbols +@code(MARIMBA), @code(VIBRAPHONE), @code(AGOGO), @code(WOOD1), +@code(RESO), @code(WOOD2), @code(BEATS), @code(TWO-FIXED), or +@code(CLUMP). The symbol must be quoted, e.g. for SAL syntax use +@code[quote(marimba)], and for Lisp syntax use @code('marimba). +The parameter @i(step) is a @code(FLONUM) that +sets the pitch (in steps), and @i(dur) is the duration in seconds. + +@label(sitar-sec) +@codef{sitar(@pragma(defn)@index(sitar)@index(STK sitar)@i(step), @i(dur))} @c{[sal]}@* +@altdef{@code[(sitar @i(step) @i(dur))] @c{[lisp]}}@\A sitar physical model implemented in STK. +The parameter @i(step) is a @code(FLONUM) that sets the pitch, + and @i(dur) is the duration. +@end(fndefs) + +@paragraph(More Behaviors) +@begin(fndefs) +@label(clip-sec) +@codef{clip(@pragma(defn)@index(clip)@index(limit)@i(sound), @i(peak))} @c{[sal]}@* +@altdef{@code[(clip @i(sound) @i(peak))] @c{[lisp]}}@\Hard limit @i(sound) +to the given @i(peak), a positive number. The samples of @i(sound) are constrained between an upper value +of @i(peak) and a lower value of @subtract()@i(peak). If @i(sound) is a number, @code(clip) will return @i(sound) limited by @i(peak). If @i(sound) is a multichannel sound, @code(clip) returns a multichannel sound where each channel is clipped. The result has the type, sample rate, starting time, etc. of @i(sound). + +@label(s-abs-sec) +@codef{s-abs(@pragma(defn)@index(s-abs)@index(absolute value)@i(sound))} @c{[sal]}@* +@altdef{@code[(s-abs @i(sound))] @c{[lisp]}}@\A generalized absolute value function. If @i(sound) is a @code(SOUND), compute the absolute value of each sample. If @i(sound) is a number, just compute the absolute value. If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-abs) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). + +@label(s-sqrt-sec) +@codef{s-sqrt(@pragma(defn)@index(s-sqrt)@index(square root)@i(sound))} @c{[sal]}@* +@altdef{@code[(s-sqrt @i(sound))] @c{[lisp]}}@\A generalized square root function. If @i(sound) is a @code(SOUND), compute the square root of each sample. If @i(sound) is a number, just compute the square root. If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-sqrt) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). In taking square roots, if an input sample is less than zero, the corresponding output sample is zero. This is done because the square root of a negative number is undefined. + +@label(s-exp-sec) +@codef{s-exp(@pragma(defn)@index(s-exp)@index(exponential)@i(sound))} @c{[sal]}@* +@altdef{@code[(s-exp @i(sound))] @c{[lisp]}}@\A generalized exponential function. If @i(sound) is a @code(SOUND), compute @i(e)@+(@i(x)) for each sample @i(x). If @i(sound) is a number @i(x), just compute @i(e)@+(@i(x)). If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-exp) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). + +@label(s-log-sec) +@codef{s-log(@pragma(defn)@index(s-log)@index(logorithm)@index(natural log)@i(sound))} @c{[sal]}@* +@altdef{@code[(s-log @i(sound))] @c{[lisp]}}@\A generalized natural log function. If @i(sound) is a @code(SOUND), compute @i(ln)(@i(x)) for each sample @i(x). If @i(sound) is a number @i(x), just compute @i(ln)(@i(x)). If @i(sound) is a multichannel sound, return a multichannel sound with @code(s-log) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). Note that the @i(ln) of 0 is undefined (some implementations return negative infinity), so use this function with care. + +@label(s-max-sec) +@codef{s-max(@pragma(defn)@index(s-max)@index(maximum)@i(sound1), @i(sound2))} @c{[sal]}@* +@altdef{@code[(s-max @i(sound1) @i(sound2))] @c{[lisp]}}@\Compute the maximum of two functions, @i(sound1) and @i(sound2). This function also accepts numbers and multichannel sounds and returns the corresponding data type. The start time of the result is the maximum of the start times of @i(sound1) and @i(sound2). The logical stop time and physical stop time of the result is the minimum of the logical stop and physical stop times respectively of @i(sound1) and @i(sound2). Note, therefore, that the result value is zero except within the bounds of @i(both) input sounds. + +@codef{s-min(@pragma(defn)@index(s-min)@index(minimum)@i(sound1), @i(sound2))} @c{[sal]}@* +@altdef{@code[(s-min @i(sound1) @i(sound2))] @c{[lisp]}}@\Compute the minimum of two functions, @i(sound1) and @i(sound2). This function also accepts numbers and multichannel sounds and returns the corresponding data type. The start time of the result is the maximum of the start times of @i(sound1) and @i(sound2). The logical stop time and physical stop time of the result is the minimum of the logical stop and physical stop times respectively of @i(sound1) and @i(sound2). Note, therefore, that the result value is zero except within the bounds of @i(both) input sounds. + +@codef{osc-note(@pragma(defn)@index(osc-note)@i(pitch) [, @i(duration), @i(env), @i(loud), +@i(table)])} @c{[sal]}@* +@altdef{@code{(osc-note @i(pitch) [@i(duration) @i(env) @i(loud) @i(table)])} @c{[lisp]}}@\Same as @code(osc), but @code(osc-note) +multiplies the result by @i(env). The @i(env) may be a sound, +or a list supplying (@i(t@-[1]) @i(t@-[2]) +@i(t@-[4]) @i(l@-[1]) @i(l@-[2]) @i(l@-[3])). The result has a sample rate of @code(*sound-srate*). + +@label(quantize-sec) +@codef{quantize(@pragma(defn)@index(quantize)@i(sound), @i(steps))} @c{[sal]}@* +@altdef{@code[(quantize @i(sound) @i(steps))] @c{[lisp]}}@\Quantizes @i(sound) as follows: @i(sound) is multiplied by @i(steps) and rounded to the nearest integer. The result is then divided by @i(steps). For example, if @i(steps) is 127, then a signal that ranges from -1 to +1 will be quantized to 255 levels (127 less than zero, 127 greater than zero, and zero itself). This would match the quantization Nyquist performs when writing a signal to an 8-bit audio file. The @i(sound) may be multi-channel. + +@codef{ramp(@pragma(defn)@index(ramp)[@i(duration)])} @c{[sal]}@* +@altdef{@code{(ramp [@i(duration)])} @c{[lisp]}}@\Returns a +linear ramp from 0 to 1 +over @i(duration) (default is 1). The function actually reaches 1 at +@i(duration), and therefore has one extra sample, making the total duration +be @i(duration) + 1/@code(*Control-srate*). See Figure @ref(ramp-fig) for +more detail. Ramp is unaffected by the @code(sustain) transformation. The +effect of time warping is to warp the starting and ending times only. The +ramp itself is unwarped (linear). The sample rate is @code(*control-srate*). + +@label(rms-sec) +@codef{rms(@pragma(defn)@index(rms)@i(sound) [, @i(rate), @i(window-size)])} @c{[sal]}@* +@altdef{@code{(rms @i(sound) [@i(rate) @i(window-size)])} @c{[lisp]}}@\Computes the RMS of @i(sound) using a square window of size @i(window-size). The result has a sample rate of @i(rate). The default value of @i(rate) is 100 Hz, and the default window size is 1/rate seconds (converted to samples). The @i(rate) is a @code(FLONUM) and @i(window-size) is a @code(FIXNUM). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.37 in, width = 4.5 in, magnify = 0.75, + postscript = "rampfig.ps")) +@html(

) +@fillcaption[Ramps generated by @code(pwl) and @code(ramp) functions. The +@code(pwl) version ramps toward the breakpoint (1, 1), but in order to ramp +back to zero at breakpoint (1, 0), the function never reaches an amplitude +of 1. If used at the beginning of a @code(seq) construct, the next sound +will begin at time 1. The @code(ramp) version actually reaches breakpoint +(1, 1); notice that it is one sample longer than the @code(pwl) version. If +used in a sequence, the next sound after @code(ramp) would start at time 1 + +@i(P), where @i(P) is the sample period.] +@tag(ramp-fig) +@end(figure) + +@begin(fndefs) +@label(recip-sec) +@codef{recip(@pragma(defn)@index(recip)@index(reciprocal)@index(division)@i(sound))} @c{[sal]}@* +@altdef{@code[(recip @i(sound))] @c{[lisp]}}@\A generalized reciprocal function. +If @i(sound) is a @code(SOUND), compute 1/@i(x) for each sample @i(x). If @i(sound) is a number @i(x), just compute 1/@i(x). If @i(sound) is a multichannel sound, return a multichannel sound with @code(recip) applied to each element. The result has the type, sample rate, starting time, etc. of @i(sound). Note that the reciprocal of 0 is undefined (some implementations return infinity), so use this function with care on sounds. Division of sounds is accomplished by multiplying by the reciprocal. Again, be careful not to divide by zero. + +@codef{s-rest(@index(rest)@pragma(defn)@index(s-rest)[@i(duration)])} @c{[sal]}@* +@altdef{@code{(s-rest [@i(duration)])} @c{[lisp]}}@\Create silence (zero samples) +for the given +@i(duration) at the sample rate @code(*sound-srate*). +Default duration is 1.0 sec, and the sound is transformed in time according +to @code[*warp*]. @p(Note:) @code(rest) is a Lisp function that is equivalent to @code(cdr). Be careful to use @code(s-rest) when you need a sound! + +@label(noise-sec) +@codef{noise(@pragma(defn)@index(noise)[@i(duration)])} @c{[sal]}@* +@altdef{@code[(noise @i(duration))] @c{[lisp]}}@\Generate noise with the given +@i(duration). Duration (default is 1.0) +is transformed according to @code[*warp*]. The +sample rate is @code(*sound-srate*) and the amplitude is +/- @code(*loud*). + +@label(yin-sec) +@codef{yin(@pragma(defn)@index(yin)@index(pitch detection)@index(fundamenal frequency +estimation)@index(estimate frequency)@index(frequency analysis)@index(period +estimation)@i(sound), @i(minstep), @i(maxstep), @i(stepsize))} @c{[sal]}@* +@altdef{@code[(yin @i(sound) @i(minstep) @i(maxstep) @i(stepsize))] @c{[lisp]}}@\Fundamental +frequency estimation (pitch detection. Use the YIN algorithm to estimate +the fundamental frequency of @i(sound), which must be a @code(SOUND). +The @i(minstep), a @code(FLONUM), is the minimum frequency considered (in steps), +@i(maxstep), a @code(FLONUM), is the maximum frequency considered (in steps), and +@i(stepsize), a @code(FIXNUM), is the desired hop size. The result is +a ``stereo'' signal, +i.e. an array of two @code(SOUND)s, both at the same sample rate, which is +approximately the sample rate of @i(sound) divided by @i(stepsize). +The first @code(SOUND) consists of frequency estimates. The second sound consists +of values that measure the confidence or reliability of the frequency estimate. +A small value (less than 0.1) indicates fairly high confidence. A larger value +indicates lower confidence. This number can also be thought of as a ratio of +non-periodic power to periodic power. When the number is low, it means the signal +is highly periodic at that point in time, so the period estimate will be +reliable. +Hint #1: See +Alain de Cheveigne and Hideki Kawahara's article "YIN, a Fundamental Frequency +Estimator for Speech and Music" in the Journal of the +Acoustic Society of America, April 2002 for details on the yin algorithm. +Hint #2: Typically, the @i(stepsize) should be at least the expected number +of samples in one period so that the +fundamental frequency estimates are calculated at a rate far below +the sample rate of the signal. Frequency does not change rapidly and +the yin algorithm is fairly slow. To optimize speed, +you may want to use less than 44.1 kHz sample rates for input sounds. Yin +uses interpolation to achieve potentially fractional-sample-accurate estimates, +so higher sample rates do not necessarily help the algorithm and definitely +slow it down. The computation time is O(@i(n)@+(2)) per estimate, +where @i(n) is the number +of samples in the longest period considered. Therefore, each increase +of @i(minstep) by 12 (an octave) gives you a factor of 4 speedup, and +each decrease of the sample rate of @i(sound) by a factor of +two gives you another factor of 4 speedup. Finally, the number of estimates is +inversely proportional to @i(stepsize). +Hint #3: Use @code(snd-srate) (see Section @ref(snd-srate-sec)) to get +the exact sample rate of the result, which will be the sample rate of + @i(sound) divided by @i(stepsize). +E.g. @code{(snd-srate (aref yin-output 0))}, +where @code(yin-output) is a result returned by @code(yin), will be the +sample rate of the estimates. + +@end(fndefs) + +@section(Transformations)@index(Transformations) +@label(transformations-sec) +These functions change the environment that is seen by other high-level +functions. Note that these changes are usually relative to the +current environment. There are also ``absolute'' versions of each +transformation function, with the exception of @code(seq), + @code(seqrep), @code(sim), and @code(simrep). The +``absolute'' versions (starting or ending with ``abs'') do not look at the +current environment, but rather set an environment variable to a specific value. +In this way, sections of code can be insulated from external +transformations. + +@begin(fndefs) +@codef{abs-env(@pragma(defn)@index(abs-env)@i(beh))} @c{[sal]}@* +@altdef{@code[(abs-env @i(beh))] @c{[lisp]}}@\Compute @i(beh) in the default environment. +This is useful for computing waveform tables and signals that are +``outside'' of +time. For example, @code[(at 10.0 (abs-env (my-beh)))] is equivalent to +@code[(abs-env (my-beh))] because @code(abs-env) forces the default environment. Or in SAL, we would say @code[abs-env(my-beh()) @@ 10] is equivalent to @code[abs-env(my-beh())]. + +@codef{at(@pragma(defn)@index(at)@i(time), @i(beh))} @c{[sal]}@* +@altdef{@code[(at @i(time) @i(beh))] @c{[lisp]}}@\Evaluate @i(beh) with +@code(*warp*@index(*warp*)) shifted by @i(time). In SAL, you can use the infix +operator @code(@@) as in @code[@i(beh) @@ @i(time)]. To discover how the +environment is shifting time, use @code[local-to-global(@i(time))]. Most +commonly, you call @code[local-to-global(0)] to find when a sound created +in the current environment will start, expressed in absolute (global) terms. +This can be regarded as the ``current time.'' + +@codef{at-abs(@pragma(defn)@index(at-abs)@i(time), @i(beh))} @c{[sal]}@* +@altdef{@code[(at-abs @i(time) @i(beh))] @c{[lisp]}}@\Evaluate @i(beh) with +@code(*warp*@index(*warp*)) shifted so that local time 0 maps to @i(time). In SAL, you can use the infix operator @code[@@@@] as in @code[@i(beh) @@@@ @i(time)]. + +@label(continuous-control-warp) +@codef{continuous-control-warp(@pragma(defn)@index(continuous-control-warp)@i(beh))} @c{[sal]}@* +@altdef{@code[(continuous-control-warp @i(beh))] @c{[lisp]}}@\Applies the current warp environment to the signal returned by @i(beh). The result has the default control sample rate @code(*control-srate*). Linear interpolation is currently used. Implementation: @i(beh) is first evaluated without any shifting, stretching, or warping. The result is functionally composed with the inverse of the environment's warp function. + +@label(continuous-sound-warp) +@codef{continuous-sound-warp(@pragma(defn)@index(continuous-sound-warp)@i(beh))} @c{[sal]}@* +@altdef{@code[(continuous-sound-warp @i(beh))] @c{[lisp]}}@\Applies the current warp environment to the signal returned by @i(beh). The result has the default sound sample rate @code(*sound-srate*). Linear interpolation is currently used. See @code(continuous-control-warp) for implementation notes. + +@label(control-srate-abs-sec) +@codef{control-srate-abs(@pragma(defn)@index(control-srate-abs)@i(srate), +@i(beh))} @c{[sal]}@* +@altdef{@code[(control-srate-abs @i(srate) @i(beh))] @c{[lisp]}}@\Evaluate @i(beh) with @code(*control-srate*@index(*control-srate*)) +set to sample rate @i(srate). @p(Note:) there is no ``relative'' version of +this function. + +@codef{extract(@pragma(defn)@index(extract)@i(start), @i(stop), @i(beh))} @c{[sal]}@* +@altdef{@code[(extract @i(start) @i(stop) @i(beh))] @c{[lisp]}}@\Returns a sound +which is the portion of +@i(beh) between @i(start) and @i(stop). Note that this is done +relative to the current @code(*warp*). The result is shifted +to start according to @code(*warp*), so normally the result will start without a delay of @i(start). + +@codef{extract-abs(@pragma(defn)@index(extract-abs)@i(start), @i(stop), @i(beh))} @c{[sal]}@* +@altdef{@code[(extract-abs @i(start) @i(stop) @i(beh))] @c{[lisp]}}@\Returns a sound which +is the portion of +@i(beh) between @i(start) and @i(stop), independent of the +current @code(*warp*). The result is shifted +to start according to @code(*warp*). + +@codef{loud(@pragma(defn)@index(loud)@i(volume), @i(beh))} @c{[sal]}@* +@altdef{@code[(loud @i(volume) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with @code(*loud*) +incremented by @i(volume). (Recall that @code(*loud*) is in decibels, so increment is the proper operation.) + +@codef{loud-abs(@pragma(defn)@index(loud-abs)@i(volume), @i(beh))} @c{[sal]}@* +@altdef{@code[(loud-abs @i(volume) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with @code(*loud*) +set to @i(volume). + +@label(sound-srate-abs-sec) +@codef{sound-srate-abs(@pragma(defn)@index(sound-srate-abs)@i(srate), @i(beh))} @c{[sal]}@* +@altdef{@code[(sound-srate-abs @i(srate) @i(beh))] @c{[lisp]}}@\Evaluate @i(beh) with @code(*sound-srate*@index(*sound-srate*)) set to sample rate @i(srate). @p(Note:) there is no ``relative'' version of this function. + +@codef{stretch(@pragma(defn)@index(stretch)@i(factor), @i(beh))} @c{[sal]}@* +@altdef{@code[(stretch @i(factor) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with +@code(*warp*) scaled by @i(factor). The effect is to ``stretch'' the result +of @i(beh) (under the current environment) by @i(factor). See Chapter +@ref(warp-chap) for more information. Use @code[get-duration(@i(dur))] to +get the nominal actual duration of a behavior that locally has a duration +of @i(dur). Here, ``nominal'' means what would be expected if the behavior +obeys the shift, stretch, and warp components of the environment. (Any +behavior is free to deviate from the nominal timing. For example, a percussion +sound might have a fixed duration independent of the stretch factor.) Also, +``actual'' means global or absolute time, and ``locally'' means within the +environment where @code[get-duration] is called. @code[get-duration] works +by mapping the current time (local time 0) using @code[local-to-global] to +obtain an actual start time, and mapping @i(dur) to obtain an actual end time. +The difference is returned. + +@codef{stretch-abs(@pragma(defn)@index(stretch-abs)@i(factor), @i(beh))} @c{[sal]}@* +@altdef{@code[(stretch-abs @i(factor) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with @code(*warp*) set to a linear time transformation where each unit of logical time maps to @i(factor) units of real time. The effect is to stretch the nominal behavior of @i(beh) (under the default global environment) by @i(factor). See Chapter @ref(warp-chap) for more information. + +@codef{sustain(@pragma(defn)@index(sustain)@index(legato)@index(overlap)@index(stacatto)@i(factor), @i(beh))} @c{[sal]}@* +@altdef{@code[(sustain @i(factor) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with @code(*sustain*) scaled by @i(factor). The effect is to ``stretch'' the result of @i(beh) (under the current environment) by @i(factor); however, the logical stop times are not stretched. Therefore, the overall duration of a sequence is not changed, and sounds will tend to overlap if @code(*sustain*) is greater than one (legato) and be separated by silence if @code(*sustain*) is less than one. + +@codef{sustain-abs(@pragma(defn)@index(sustain-abs)@i(factor), @i(beh))} @c{[sal]}@* +@altdef{@code[(sustain-abs @i(factor) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with @code(*sustain*) set to @i(factor). (See @code(sustain), above.) + +@codef{transpose(@pragma(defn)@index(transpose)@i(amount), @i(beh))} @c{[sal]}@* +@altdef{@code[(transpose @i(amount) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with +@code(*transpose*) shifted by @i(amount). The effect is relative transposition by @i(amount) semitones. + +@codef{transpose-abs(@pragma(defn)@index(transpose-abs)@i(amount), @i(beh))} @c{[sal]}@* +@altdef{@code[(transpose-abs @i(amount) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with +@code(*transpose*) set to @i(amount). The effect is the transposition of the nominal pitches in @i(beh) (under the default global environment) by @i(amount). + +@codef{warp(@pragma(defn)@index(warp)@i(fn), @i(beh))} @c{[sal]}@* +@altdef{@code[(warp @i(fn) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with @code(*warp*) modified by @i(fn). The idea is that @i(beh) and @i(fn) are written in the same time system, and @i(fn) warps that time system to local time. The current environment already contains a mapping from local time to global (real) time. The value of @code(*warp*) in effect when @i(beh) is evaluated is the functional composition of the initial @code(*warp*) with @i(fn). + +@codef{warp-abs(@pragma(defn)@index(warp-abs)@i(fn), @i(beh))} @c{[sal]}@* +@altdef{@code[(warp-abs @i(fn) @i(beh))] @c{[lisp]}}@\Evaluates @i(beh) with @code(*warp*) set to @i(fn). In other words, the current @code(*warp*) is ignored and not composed with @i(fn) to form the new @code(*warp*). +@end(fndefs) + +@section(Combination and Time Structure)@index(Combination)@index(Time Structure) +These behaviors combine component behaviors into structures, including +sequences (melodies), simultaneous sounds (chords), and structures based +on iteration. + +@begin(fndefs) +@label(seq-sec) + @codef{seq(@pragma(defn)@index(seq)@i(beh@-[1]) [, @i(beh@-[2]), @r(...)])} @c{[sal]}@* +@altdef{@code{(seq @i(beh@-[1]) [@i(beh@-[2]) @r(...)])} @c{[lisp]}}@\Evaluates the first behavior +@i(beh@-[1]) according to @code(*time*) and each successive behavior at the +@code(logical-stop) time of the previous one. The results are summed to form a +sound whose @code(logical-stop) is +the @code(logical-stop) of the last behavior in the sequence. Each behavior +can result in a multichannel sound, in which case, the logical stop time is +considered to be the maximum logical stop time of any channel. The number +of channels in the result is the number of channels of the first behavior. +If other behaviors return fewer channels, new channels are created containing +constant zero signals until the required number of channels is obtained. If +other behaviors return a simple sound rather than multichannel sounds, the +sound is automatically assigned to the first channel of a multichannel sound +that is then filled out with zero signals. If another behavior returns more +channels than the first behavior, the error is reported and the computation +is stopped. Sample rates are converted up or down to match the sample rate of the first sound in a sequence. + +@codef{seqrep(@pragma(defn)@index(seqrep)@i(var), @i(limit), @i(beh))} @c{[sal]}@* +@altdef{@code[(seqrep @i(var) @i(limit) @i(beh))] @c{[lisp]}}@\Iteratively +evaluates @i(beh) with the atom +@i(var) set with values from 0 to @i(limit)-1, inclusive. These sounds +are placed sequentially in time as if by @code(seq). The symbol @i(var) is +a @i(read-only) local variable to @i(beh). Assignments are not restricted +or detected, but may cause a run-time error or crash. In LISP, the syntax is + @code[(seqrep (@i(var) @i(limit)) @i(beh))]. + +@label(sim-sec) +@codef{sim(@pragma(defn)@index(sim)[@i(beh@-[1]), @i(beh@-[2]), @r(...)])} @c{[sal]}@* +@altdef{@code{(sim [@i(beh@-[1]) @i(beh@-[2]) @r(...)])} @c{[lisp]}}@\Returns a sound which is the +sum of the given behaviors evaluated with current value of @code(*warp*). +If behaviors return multiple channel sounds, the corresponding channels are +added. If the number of channels does not match, the result has the +maximum. For example, if a two-channel sound [L, R] is added to a four-channel +sound [C1, C2, C3, C4], the result is [L + C1, R + C2, C3, C4]. Arguments to @code(sim) may also be numbers. If all arguments are numbers, @code(sim) is equivalent (although slower than) the @code(+) function. If a number is added to a sound, @code(snd-offset) is used to add the number to each sample of the sound. The result of adding a number to two or more sounds with different durations is not defined. Use @code(const) to coerce a number to a sound of a specified duration. An important limitation of @code(sim) is that it cannot handle hundreds of behaviors due to a stack size limitation in XLISP. To compute hundreds of sounds (e.g. notes) at specified times, see @code(timed-seq), below. +See also @code(sum) below. + +@codef{simrep(@pragma(defn)@index(simrep)@i(var), @i(limit), @i(beh))} @c{[sal]}@* +@altdef{@code[(simrep @i(var) @i(limit) @i(beh))] @c{[lisp]}}@\Iteratively +evaluates @i(beh) with the atom +@i(var) set with values from 0 to @i(limit)-1, inclusive. These sounds +are then placed simultaneously in time as if by @code(sim). +In LISP, the syntax is + @code[(seqrep (@i(var) @i(limit)) @i(beh))]. + +@label(trigger-sec) +@codef[trigger(@pragma(defn)@index(trigger)@i(s), @i(beh))] @c{[sal]}@* +@altdef{@code[(trigger @i(s) @i(beh))] @c{[lisp]}}@\Returns a sound which is the +sum of instances of the behavior @i(beh). One instance is created each time +@code(SOUND) @i(s) makes a transition from less than or equal to zero to +greater than zero. (If the first sample of @i(s) is greater than zero, an +instance is created immediately.) The sample rate of @i(s) and all behaviors +must be the same, and the behaviors must be (monophonic) @code(SOUND)s. +This function is particularly designed to allow behaviors to be invoked +in real time by making @i(s) a function of a Nyquist slider, which can be +controlled by a graphical interface or by OSC messages. See @code(snd-slider) +in Section @ref(snd-slider-sec). + +@codef[set-logical-stop(@pragma(defn)@index(set-logical-stop)@i(beh), @i(time))] @c{[sal]}@* +@altdef{@code[(set-logical-stop @i(beh) @i(time))] @c{[lisp]}}@\Returns a sound with @i(time) as +the logical stop time. + +@codef{sum(@pragma(defn)@index(sum)@index(mix)@i(a) [, @i(b), @r(...)])} @c{[sal]}@* +@altdef{@code{(sum @i(a) [@i(b) @r(...)])} @c{[lisp]}}@\Returns the sum of @i(a), @i(b), ..., allowing mixed addition of sounds, multichannel sounds and numbers. Identical to @i(sim). In SAL, use the infix ``+'' operator. + +@codef{mult(@pragma(defn)@index(mult)@index(product)@index(multiply signals)@i(a) [, @i(b), @r(...)])} @c{[sal]}@* +@altdef{@code{(mult @i(a) [@i(b) @r(...)])} @c{[lisp]}}@\Returns the product of @i(a), @i(b), ..., allowing mixed multiplication of sounds, multichannel sounds and numbers. + +@codef{diff(@pragma(defn)@index(diff)@index(difference of sounds)@i(a), @i(b))} @c{[sal]}@* +@altdef{@code[(diff @i(a) @i(b))] @c{[lisp]}}@\Returns the difference between @i(a) and @i(b). This function is defined as @code[(sum a (prod -1 b))]. + +@label(timed-seq-sec) +@codef{timed-seq(@pragma(defn)@index(timed-seq)@index(score)@index(note list)@i(score))} @c{[sal]}@* +@altdef{@code[(timed-seq @i(score))] @c{[lisp]}}@\Computes sounds from a note list or ``score.'' The @i(score) +is of the form: @code[`((@i(time1) @i(stretch1) @i(beh1)) (@i(time2) +@i(stretch2) @i(beh2)) @r(...))], where @i(timeN) is the starting time, +@i(stretchN) is the stretch factor, and @i(behN) is the behavior. Note +that @i(score) is normally a @i(quoted list)! The times must be in +increasing order, and each @i(behN) is evaluated using lisp's @code(eval), +so the @i(behN) behaviors cannot refer to local parameters or local +variables. The advantage of this form over @code(seq) is that the +behaviors are evaluated one-at-a-time which can take much less stack +space and overall memory. One special ``behavior'' expression is +interpreted directly by @code(timed-seq): @code[(SCORE-BEGIN-END)] +is ignored, not evaluated as a function. Normally, this special +behavior is placed at time 0 and has two parameters: the score +start time and the score end time. These are used in Xmusic +functions. If the behavior has a @code(:pitch) keyword parameter +which is a list, the list represents a chord, and the expression is +replaced by a set of behaviors, one for each note in the chord. +It follows that if @code(:pitch) is @code(nil), the behavior +represents a rest and is ignored. + +@end(fndefs) + + +@section(Sound File Input and Output) +@index(sound file I/O) +@begin(fndefs) +@label(play-sec) +@codef[play @pragma(defn)@index(play)@i(sound)] @c{[sal]}@* +@altdef{@code[(play @i(sound))] @c{[lisp]}}@\Play the sound +through the DAC. +Note that @code(play) is a command in SAL. In XLISP, it is a function, +so the syntax is @code[(play @i(sound))], and in SAL, you can call the +XLISP function as @code[#play(@i(sound))]. +The @code(play) command or function +writes a file and plays it. The details of this +are system-dependent, but @code(play) is defined in the file +@code(system.lsp). The variable @code(*default-sf-dir*)@index(sound file directory default)@index(directory, default sound file)@index(default sound file directory)@index(temporary sound files directory) +@index(*default-sf-dir*) names a directory into which to save a sound file. Be careful not to call @code(play) or @code(sound-play) within a function and then +invoke that function from another @code(play) command. + +By default, Nyquist will try to normalize sounds using the method named by +@code(*autonorm-type*), which is @code('lookahead) by default. +The @i(lookahead) method precomputes and buffers @code(*autonorm-max-samples*) +samples, finds the peak value, and normalizes accordingly. The +@code('previous) method bases the normalization of the current sound on the peak value of the (entire) previous sound. This might be good if you are working with long sounds that start rather softly. See Section @ref(peak-ex-sec) for more details. + +If you want precise control over output levels, you should turn this feature off by typing (using SAL syntax): +@begin(example) +autonorm-off()@index(autonorm-off) +@end(example) +Reenable the automatic normalization feature by typing: +@begin(example) +autonorm-on()@index(autonorm-on) +@end(example) +Play normally produces real-time output. The default is to send audio data to the DAC as it is computed in addition to saving samples in a file. If computation is slower than real-time, output will be choppy, but since the samples end up in a file, you can type @code[(r)] to replay the stored sound. Real-time playback can be disabled by (using SAL syntax): +@begin(example) +sound-off()@index(sound-off) +@end(example) +and reenabled by: +@begin(example) +sound-on()@index(sound-on) +@end(example) +Disabling real-time playback has no effect on @code[(play-file)] or @code[(r)]. + +While sounds are playing, typing control-A@index(control-A) to Nyquist will push the estimated +elapsed@index(elapsed audio time) audio time onto the head of the list +stored in @code(*audio-markers*). +@index(*audio-markers*)@index(audio markers)@index(markers, audio) +Because samples are computed in blocks and because there is latency +between sample computation and sample playback, the elapsed time may not +be too accurate, and the computed elapsed time may not advance after all +samples have been computed but the sound is still playing. + +@codef[play-file(@pragma(defn)@index(play-file)@i(filename))] @c{[sal]}@* +@altdef{@code[(play-file @i(filename))] @c{[lisp]}}@\Play the contents of a sound file named by @i(filename). The @code(s-read) function is used to read the file, and unless +@i(filename) specifies an absolute path or starts with ``.'', it will be read from +@code(*default-sf-dir*). + +@codef[autonorm-on(@pragma(defn)@index(autonorm-on))] @c{[sal]}@* +@altdef{@code[(autonorm-on)] @c{[lisp]}}@\Enable automatic adjustment of a scale factor applied to sounds computed using the @code(play) command. + +@codef[autonorm-off(@pragma(defn)@index(autonorm-off))] @c{[sal]}@* +@altdef{@code[(autonorm-off)] @c{[lisp]}}@\Disable automatic adjustment of a scale factor applied to sounds computed using the @code(play) command. + +@codef[sound-on(@pragma(defn)@index(sound-on))] @c{[sal]}@* +@altdef{@code[(sound-on)] @c{[lisp]}}@\Enable real-time audio output when sound is computed by the the @code(play) command. + +@codef[sound-off(@pragma(defn)@index(sound-off))] @c{[sal]}@* +@altdef{@code[(sound-off)] @c{[lisp]}}@\Disable real-time audio output when sound is computed by the the @code(play) command. + +@label(s-save-sec) +@codef{s-save(@pragma(defn)@index(s-save)@index(save samples to file)@index(write samples to file)@index(output samples to file)@i(expression), @i(maxlen), +@i(filename), format: @i(format), mode: @i(mode), bits: @i(bits), swap: @i(flag), play: @i(play))} @c{[sal]}@* +@altdef{@code{(s-save @i(expression) @i(maxlen) @i(filename) :format @i(format) :mode @i(mode) :bits @i(bits) :swap @i(flag) :play @i(play))} @c{[lisp]}}@\@label(s-save)Evaluates the @i(expression), which should result in a sound +or an array of sounds, and writes the result to the given @i(filename). A +@code(FLONUM) is returned giving the maximum absolute value of all samples +written. (This is useful for normalizing sounds and detecting sample +overflow.) If @i(play) is not @code(NIL), the sound will be output +through the computer's audio output system. (@i(play:) @c{[sal]} +or @i(:play) @c{[lisp]} is not implemented on all systems; if it is implemented, and @i(filename) is @code(NIL), then this will play the file without also writing a file.) +The latency (length of audio buffering) used to play the sound is 0.3s by default, but see @code(snd-set-latency). +If +a multichannel sound (array) is written, the channels are up-sampled to the +highest rate in any channel so that all channels have the same sample rate. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. A +header is written according to @i(format), samples are encoded according to +@i(mode), using @i(bits) bits/sample, and bytes are swapped if @i(flag) is not NIL. Defaults for these are +@code(*default-sf-format*), @code(*default-sf-mode*), and +@code(*default-sf-bits*). The default for @i(flag) is NIL. +The @i(bits) parameter may be 8, 16, or 32. The values for the @i(format) and @i(mode) options are described below: +@end(fndefs) +@b(Format) +@begin(description, leftmargin +2 in, indent -2 in) +@code(snd-head-none)@\The format is unknown and should be determined +by reading the file. + +@code(snd-head-raw)@\A raw format file has no header. + +@code(snd-head-AIFF)@\AIFF format header. + +@code(snd-head-IRCAM)@\IRCAM format header. + +@code(snd-head-NeXT)@\1024-byte NeXT/SUN format header followed by IRCAM +header ala CMIX. Note that the NeXT/SUN format has a header-length field, +so it really is legal to have a large header, even though the normal minimal +header is only 24 bytes. The additional space leaves room for maximum +amplitudes, which can be used for normalizing floating-point soundfiles, and +for other data. Nyquist follows the CMIX convention of placing an IRCAM +format header immediately after the NeXT-style header. + +@code(snd-head-Wave)@\Microsoft Wave format header. + +@code(snd-head-*)@\See sndfnint.lsp for more formats. +@end(description) + +@b(Mode) +@begin(description, leftmargin +2 in, indent -2 in) +@code(snd-mode-adpcm)@\ADPCM mode (not supported). + +@code(snd-mode-pcm)@\signed binary PCM mode. + +@code(snd-mode-ulaw)@\8-bit U-Law mode. + +@code(snd-mode-alaw)@\8-bit A-Law mode (not supported). + +@code(snd-mode-float)@\32-bit floating point mode. + +@code(snd-mode-upcm)@\unsigned binary PCM mode. + +@code(snd-mode-*)@\See sndfnint.lsp for more modes. +@end(description) + +The defaults for format, mode, and bits are as follows: +@begin(description, leftmargin +2 in, indent -2 in) +NeXT and Sun machines:@\@code(snd-head-NeXT), @code(snd-mode-pcm), +@code(16) + +SGI and Macintosh machines:@\@code(snd-head-AIFF), @code(snd-mode-pcm), @code(16) + +@end(description) + +@begin(fndefs) +@label(s-read-sec) +@codef{s-read(@pragma(defn)@index(s-read)@index(read samples from file)@i(filename), time-offset: @i(offset), srate: @i(sr), dur: @i(dur), nchans: @i(chans), + format: @i(format), mode: @i(mode), bits: @i(n), swap: @i(flag))} @c{[sal]}@* +@altdef{@code{(s-read @i(filename) :time-offset @i(offset) :srate @i(sr) + :dur @i(dur) :nchans @i(chans) :format @i(format) :mode @i(mode) :bits @i(n) + :swap @i(flag))} @c{[lisp]}}@\Reads a sound from + @i(filename). The global @code(*default-sf-dir*) applies. If a header is +detected, the header is used to determine the format +of the file, and header information overrides format information provided by +keywords (except for @code(time-offset:) and @code(dur:)). +@begin(example) +s-read("mysound.snd", srate: 44100) +@end(example) +specifies a sample rate of 44100 hz, but if the file has a header specifying 22050 hz, the resulting sample rate will be 22050. The parameters are: +@begin(itemize) + @i(offset) @itemsep the amount of time (in seconds) to skip from +the beginning of the file. The default is 0.0. + +@i(sr) @itemsep the sample rate of the samples in the file. Default is +@code(*default-sf-srate*) @index(*default-sf-srate*), which is normally 44100. + + @i(dur) @itemsep the maximum duration in seconds to read. Default is +10000. + + @i(chans) @itemsep the number of channels to read. It is assumed that +samples from each channel are interleaved. Default is 1. + + @i(format) @itemsep the header format. See @code(s-save) for details. +Default is @code(*default-sf-format*), although this parameter is currently +ignored. + + @i(mode) @itemsep the sample representation, e.g. PCM or float. See +@code(s-save) for details. Default is @code(*default-sf-format*). + + @i(n) @itemsep the number of bits per sample. See @code(s-save) for +details. Default is @code(*default-sf-bits*). + + @i(flag) @itemsep (T or NIL) swap byte order of each sample. Default is NIL. +@end(itemize) +If there is an error, for example if @i(offset) is greater than the length of the file, then @code(NIL) is returned rather than a sound. Information about the sound is also returned by @code(s-read) through @code(*rslt*)@foot(Since XLISP does not support multiple value returns, multiple value returns are simulated by having the function assign additional return values in a list to the global variable @code(*rslt*). Since this is a global, it should be inspected or copied immediately after the function return to insure that return values are not overwritten by another function.). The list assigned to @code(*rslt*) is of the form: (@i(format) @i(channels) @i(mode) @i(bits) @i(samplerate) @i(duration) @i(flags) @i(byte-offset)), which are defined as follows: +@begin(itemize) +@i(format) @itemsep the header format. See @code(s-save) for details. + +@i(channels) @itemsep the number of channels. + +@i(mode) @itemsep the sample representation, e.g. PCM or float. See @code(s-save) for details. + +@i(bits) @itemsep the number of bits per sample. + +@i(samplerate) @itemsep the sample rate, expressed as a @code(FLONUM). + +@i(duration) @itemsep the duration of the sound, in seconds. + +@i(flags) @itemsep The values for @i(format), @i(channels), @i(mode), @i(bits), @i(samplerate), and @i(duration) are initially just the values passed in as parameters or default values to @code(s-read). If a value is actually read from the sound file header, a flag is set. The flags are: @code(snd-head-format), @code(snd-head-channels), @code(snd-head-mode), @code(snd-head-bits), @code(snd-head-srate), and @code(snd-head-dur). For example, +@begin(example) +(let ((flags (caddr (cddddr *rslt*)))) + (not (zerop (logand flags snd-head-srate)))) +@end(example) +tells whether the sample rate was specified in the file. See also @code(sf-info) below. + +@i(byte-offset) @itemsep the byte offset into the file of the first sample +to be read (this is used by the @code(s-overwrite) and @code(s-add-to) +functions). +@end(itemize) + +@codef{s-add-to(@pragma(defn)@index(s-add-to)@index(add to file samples)@index(mix to file)@i(expression), @i(maxlen), +@i(filename) [, @i(offset)])} @c{[sal]}@* +@altdef{@code{(s-add-to @i(expression) @i(maxlen) @i(filename) [@i(offset)])} @c{[lisp]}}@\@label(s-add-to-sec)Evaluates the @i(expression), which should result in a sound +or an array of sounds, and adds the result to the given @i(filename). +The global @code(*default-sf-dir*) applies. A @code(FLONUM) is returned, +giving the maximum absolute value of all samples written. The +sample rate(s) of @i(expression) must match those of the file. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. +If @i(offset) is specified, the new sound is added to the file beginning at +an @i(offset) from the beginning (in seconds). The file is extended if +necessary to accommodate the new addition, but if @i(offset) +falls outside of the original file, the file is not modified. (If necessary, +use @code(s-add-to) to extend the file with zeros.) +The file must be a recognized +sound file with a header (not a raw sound file). + + +@codef{s-overwrite(@pragma(defn)@index(s-overwrite)@index(replace file samples)@index(overwrite samples)@i(expression), @i(maxlen), @i(filename) [, @i(offset)])} @c{[sal]}@* +@altdef{@code{(s-overwrite @i(expression) @i(maxlen) @i(filename) [@i(offset)])} @c{[lisp]}}@\@label(s-overwrite-sec)Evaluates +the @i(expression), which should result in a sound +or an array of sounds, and replaces samples in the given @i(filename). +The global @code(*default-sf-dir*) applies. +A @code(FLONUM) is returned, giving the maximum absolute value of all +samples written. The +sample rate(s) of @i(expression) must match those of the file. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. +If @i(offset) is specified, the new sound is written to the file beginning at +an @i(offset) from the beginning (in seconds). The file is extended if +necessary to accommodate the new insert, but if @i(offset) falls outside of +the original file, the file is not modified. (If necessary, use +@code(s-add-to) to extend the file with zeros.) The file must be a recognized +sound file with a header (not a raw sound file). + +@codef{sf-info(@pragma(defn)@index(sf-info)@index(sound file info)@i(filename))} @c{[sal]}@* +@altdef{@code[(sf-info @i(filename))] @c{[lisp]}}@\Prints information about a sound file. The parameter @i(filename) is a string. The file is assumed to be in *default-sf-dir* (see @code(soundfilename) below) unless the filename begins with ``.'' or ``/''. The source for this function is in the @code(runtime) and provides an example of how to determine sound file parameters. + +@codef{soundfilename(@pragma(defn)@index(soundfilename)@i(name))} @c{[sal]}@* +@altdef{@code[(soundfilename @i(name))] @c{[lisp]}}@\Converts a string @i(name) to a soundfile name. If @i(name) begins with ``.'' or ``/'', the name is returned without alteration. Otherwise, a path taken from @code(*default-sf-dir*) is prepended to @i(name). The @code(s-plot), @code(s-read), and @code(s-save) functions all use @code(soundfilename) translate filenames. + +@codef{s-plot(@pragma(defn)@index(s-plot)@index(plot)@i(sound) + [, @i(dur), @i(n)])} @c{[sal]}@* +@altdef{@code{(s-plot @i(sound) + [@i(dur) @i(n)])} @c{[lisp]}}@\Plots sound in a window. This function was designed to run a @code(plot) program on a Unix workstation, but now is +primarily used with @code(NyquistIDE), which has self-contained plotting. Normally, +time/value pairs in ascii are written to @code(points.dat) and system-dependent code +(or the @code(NyquistIDE) program) takes it from there. If the @i(sound) is +longer than the optional @i(dur) (default is 2 seconds), only the +first @i(dur) seconds are plotted. +If there are more than @i(n) samples to be plotted, the signal is interpolated +to have @i(n) samples before plotting. +The data file used is @code(*default-plot-file*): + +@codef(*default-plot-file*)@pragma(defn)@index(*default-plot-file*)@\The file containing the data points, defaults to "points.dat". + +@codef{s-print-tree(@pragma(defn)@index(s-print-tree)@index(snd-print-tree)@i(sound))} @c{[sal]}@* +@altdef{@code[(s-print-tree @i(sound))] @c{[lisp]}}@\Prints an ascii +representation of the internal data structures representing a sound. This +is useful for debugging@index(debugging) Nyquist. Identical to @code(snd-print-tree). + +@end(fndefs) + +@section(Low-level Functions) +Nyquist includes many low-level functions that are used to implement the functions and behaviors described in previous sections. For completeness, these functions are described here. Remember that +these are low-level functions that are not intended for normal use. Unless +you are trying to understand the inner workings of Nyquist, you can skip this section. + +@subsection(Creating Sounds) +The basic operations that create sounds are described here. + +@begin(fndefs) + +@codef[snd-const(@pragma(defn)@index(snd-const)@i(value), @i(t0), @i(srate), +@i(duration))] @c{[sal]}@* +@altdef{@code[(snd-const @i(value) @i(t0) @i(srate) @i(duration))] @c{[lisp]}}@\Returns a sound with constant @i(value), starting at @i(t0) +with the given @i(duration), at the sample rate @i(srate). You might want +to use @code(pwl) (see Section @ref(pwl-sec)) instead. + +@codef[snd-read(@pragma(defn)@index(snd-read)@i(filename), @i(offset), @i(t0), @i(format), +@i(channels), @i(mode), @i(bits), @i(swap), @i(sr), +@i(dur))] @c{[sal]}@* +@altdef{@code[(snd-read @i(filename) @i(offset) @i(t0) @i(format) @i(channels) @i(mode) @i(bits) @i(swap) @i(sr) @i(dur))] @c{[lisp]}}@\Loads a sound from a file with name @i(filename). Files are +assumed to consist of a header followed by frames consisting of one sample +from each channel. The @i(format) specifies the type of header, but this +information is currently ignored. Nyquist looks for a number of header +formats and automatically figures out which format to read. If a header can +be identified, the header is first read from the file. Then, the file +pointer is advanced by the indicated +@i(offset) (in seconds). If there is an unrecognized header, Nyquist will +assume the file has no header. If the header size is a multiple of the +frame size (bytes/sample * number-of-channels), you can use @i(offset) to +skip over the header. To skip N bytes, use an @i(offset) of: +@begin(example) +(/ (float N) @i(sr) (/ @i(bits) 8) @i(channels)) +@end(example) +If the header is not a multiple of the frame size, either write a header or +contact the author (dannenberg@@cs.cmu.edu) for assistance. Nyquist will +round @i(offset) to the nearest sample. The resulting sound will start at +time @i(t0). If a header is found, the file will be interpreted according +to the header information. If no header was found, @i(channels) tells how +many channels there are, the samples are encoded according to @i(mode), the +sample length is @i(bits), and @i(sr) is the sample rate. The @i(swap) flag is 0 or 1, where 1 means to swap sample bytes. The duration to +be read (in seconds) is given by @i(dur). If @i(dur) is longer than the +data in the file, then a shorter duration will be returned. If the file +contains one channel, a sound is returned. If the file contains 2 or more +channels, an array of sounds is returned. @p(Note:) you probably want to +call @code(s-read) (see Section @ref(s-read-sec)) instead of +@code(snd-read). Also, see Section @ref(s-read-sec) for information on the +@i(mode) and @i(format) parameters. + +@codef[snd-save(@pragma(defn)@index(snd-save)@i(expression), @i(maxlen), +@i(filename), @i(format), @i(mode), @i(bits), @i(swap), @i(play))] @c{[sal]}@* +@altdef{@code[(snd-save @i(expression) @i(maxlen) @i(filename) @i(format) @i(mode) @i(bits) @i(swap) @i(play))] @c{[lisp]}}@\@label(snd-save)Evaluates +the @i(expression), which should result in a sound +or an array of sounds, and writes the result to the given @i(filename). If +a multichannel sound (array) is written, the channels are up-sampled to the +highest rate in any channel so that all channels have the same sample rate. +The maximum number of samples written per channel is given by @i(maxlen), +which allows writing the initial part of a very long or infinite sound. A +header is written according to @i(format), samples are encoded according to +@i(mode), using @i(bits) bits/sample, and swapping bytes if @i(swap) is 1 (otherwise it should be 0). +If @i(play) is not null, the audio is played in real time (to the extent possible) as it is computed. The peak value of the sound is returned. In addition, +the symbol @code(*RSLT*) is bound to a list containing the sample rate, +number of channels, and duration (in that order) of the saved sound. +@p(Note:) you probably want to call +@code(s-save) (see Section @ref(s-save-sec)) instead. The @i(format) and +@i(mode) parameters are described in Section @ref(s-save-sec). + +@codef[snd-overwrite(@pragma(defn)@index(snd-overwrite)@i(expression), @i(maxlen), @i(filename), @i(offset), @i(format), @i(mode), @i(bits), @i(swap))] @c{[sal]}@* +@altdef{@code[(snd-overwrite @i(expression) @i(maxlen) @i(filename) @i(offset) @i(format) @i(mode) @i(bits) @i(swap))] @c{[lisp]}}@\@label(snd-overwrite-sec)Evaluates +the @i(expression), which should result in a sound +or an array of sounds, and replaces samples in the given @i(filename), +writing the first frame at a time of @i(offset) seconds. The @i(offset) must +be less than or equal to the duration of the existing file. The +duration of the written samples may +be greater than that of the file, in which case the file is extended +as necessary. The +sample rate(s) of @i(expression) and the number of channels +must match those of the file. If @i(format) is + @code(SND-HEAD-RAW), then the file +format is given by @i(mode) (see +@code(snd-save), @i(bits) (per channel), @i(swap) (1 means to +swap bytes and 0 means write them in the native byte order), and the +number of channels and sample rate of the sound returned by evaluating +@i(expression). If the +file is a known +audio file format, @i(format) should be @code(SND-HEAD-NONE), and the +other parameters are ignored. Up to a maximum of @i(maxlen) +samples will be written per channel. The peak value of the sound is returned. +In addition, the symbol @code(*RSLT*) is bound to a list containing the +duration of the written sound (which may not be the duration of the sound +file). +Use @code(s-add-to) (in Section @ref(s-add-to-sec) or +@code(s-overwrite) (in Section @ref(s-overwrite-sec) instead of this function. + +@codef[snd-coterm(@pragma(defn)@index(snd-coterm)@index(co-termination)@index(duration of +another sound)@i(s1), @i(s2))] @c{[sal]}@* +@altdef{@code[(snd-coterm @i(s1) @i(s2))] @c{[lisp]}}@\Returns a copy of @i(s1), except the start +time is the maximum of the start times of @i(s1) and @i(s2), and the +termination time is the minimum of @i(s1) and @i(s2). (After the termination +time, the sound is zero as if @i(s1) is gated by @i(s2).) Some rationale +follows: In order to implement @code(s-add-to), we need to read from the +target sound file, add the sounds to a new sound, and overwrite the result +back into the file. We only want to write as many samples into the file as +there are samples in the new sound. However, if we are adding +in samples read from +the file, the result of a @code(snd-add) in Nyquist will have the maximum +duration of either sound. Therefore, we may read to the end of the file. +What we need is a way to truncate the read, but we cannot easily do that, +because we do not know in advance how long the new sound will be. The +solution is to use @code(snd-coterm), which will allow us to truncate the +sound that is read from the file (@i(s1)) according to the duration of the +new sound (@i(s2)). When this truncated sound is added to the new sound, +the result will have only the duration of the new sound, and this can be +used to overwrite the file. This function is used in the implementation of +@code(s-add-to), which is defined in @code(runtime/fileio.lsp). + +@code[(snd-from-array @r(...))] @c{[sal]}@* +@altdef{@code[(snd-from-array @r(...))] @c{[lisp]}}@\See @pragma(startref) page @pageref(snd-from-array-sec). + +@codef[snd-white(@pragma(defn)@index(snd-white)@i(t0), @i(sr), @i(d))] @c{[sal]}@* +@altdef{@code[(snd-white @i(t0) @i(sr) @i(d))] @c{[lisp]}}@\Generate white noise, starting at +@i(t0), with sample rate @i(sr), and duration @i(d). You probably want to +use @code(noise) (see Section @ref(noise-sec)). + + @codef[snd-zero(@pragma(defn)@index(snd-zero)@i(t0), @i(srate))] @c{[sal]}@* +@altdef{@code[(snd-zero @i(t0) @i(srate))] @c{[lisp]}}@\Creates a sound that is +zero everywhere, starts at @i(t0), and has sample rate @i(srate). The +logical stop time is immediate, i.e. also at @i(t0). You probably want +to use @code(pwl) (see Section @ref(pwl-sec)) instead. + + @codef[get-slider-value(@pragma(defn)@index(get-slider-value)@i(index))] @c{[sal]}@* +@altdef{@code[(get-slider-value @i(index))] @c{[lisp]}}@\@label(get-slider-value-sec)Return the current value of the slider +named by @i(index) (an integer index into the array of sliders). +Note that this ``slider'' is just a floating point +value in an array. Sliders can be changed by OSC messages (see @code(osc-enable)) and by sending character +sequences to Nyquist's standard input. (Normally, these character sequences would +not be typed but generated by the NyquistIDE interactive development environment, which +runs Nyquist as a sub-process, and which present the user with graphical sliders.) + +@codef[snd-slider(@pragma(defn)@index(snd-slider)@i(index), @i(t0), @i(srate), @i(duration))] @c{[sal]}@* +@altdef{@code[(snd-slider @i(index) @i(t0) @i(srate) @i(duration))] @c{[lisp]}}@\@label(snd-slider-sec)Create +a sound controlled by the slider named by @i(index) (an integer +index into the array of sliders; see @code(get-slider-value) for more information). +The function returns a sound. Since Nyquist sounds are computed in blocks of samples, +and each block is computed at once, each block will contain copies of the current slider +value. To obtain reasonable responsiveness, slider sounds should have high (audio) +sample rates so that the block rate will be reasonably high. Also, consider lowering the audio +latency using @code(snd-set-latency). To ``trigger'' a Nyquist behavior using slider input, see the @code(trigger) function in Section @ref(trigger-sec). + +@end(fndefs) + +@subsection(Signal Operations) +This next set of functions take sounds as arguments, operate on them, and +return a sound. + +@begin(fndefs) +@codef[snd-abs(@pragma(defn)@index(snd-abs)@index(absolute value)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-abs @i(sound))] @c{[lisp]}}@\Computes a new +sound where each sample is the absolute value of the corresponding sample in +@i(sound). You should probably use @code(s-abs) instead. (See Section @ref(s-abs-sec).) + +@codef[snd-sqrt(@pragma(defn)@index(snd-sqrt)@index(square root)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-sqrt @i(sound))] @c{[lisp]}}@\Computes a new +sound where each sample is the square root of the corresponding sample in +@i(sound). If a sample is negative, it is taken to be zero to avoid raising a floating point error. You should probably use @code(s-sqrt) instead. (See Section @ref(s-sqrt-sec).) + + @codef[snd-add(@pragma(defn)@index(snd-add)@i(sound1), @i(sound))] @c{[sal]}@* +@altdef{@code[(snd-add @i(sound1) @i(sound))] @c{[lisp]}}@\Adds two sounds. The +resulting start time is the minimum of the two parameter start times, the +logical stop time is the maximum of the two parameter stop times, and the +sample rate is the maximum of the two parameter sample rates. Use +@code(sim) or @code(sum) instead of @code(snd-add) (see Section @ref(sim-sec)). + +@codef[snd-offset(@pragma(defn)@index(snd-offset)@index(offset to a sound)@index(add +offset to sound)@i(sound), @i(offset))] @c{[sal]}@* +@altdef{@code[(snd-offset @i(sound) @i(offset))] @c{[lisp]}}@\Add an offset to a sound. The +resulting start time, logical stop time, stop time, and sample rate are +those of @i(sound). Use @code(sum) instead (see Section @ref(sim-sec)). + +@codef[snd-avg(@pragma(defn)@index(snd-avg)@index(moving average)@index(RMS)@index(average)@i(sound), @i(blocksize), @i(stepsize), @i(operation))] @c{[sal]}@* +@altdef{@code[(snd-avg @i(sound) @i(blocksize) @i(stepsize) @i(operation))] @c{[lisp]}}@\Computes the averages +or peak values of blocks of samples. Each output sample is an average or +peak of @i(blocksize) (a fixnum) adjacent samples from the input @i(sound). +After each average or peak is taken, the input is advanced by @i(stepsize), +a fixnum which may be greater or less than @i(blocksize). The output +sample rate is the @i(sound) (input) sample rate divided by @i(stepsize). +This function is useful for computing low-sample-rate rms or peak +amplitude signals for input to @code(snd-gate) or @code(snd-follow). +To select the operation, @i(operation) should be one of @code(OP-AVERAGE) +or @code(OP-PEAK). (These are global lisp variables; the actual +@i(operation) parameter is an integer.) For RMS computation, see +@code(rms) in Section @ref(rms-sec). + +@codef[snd-clip(@index(clip)@pragma(defn)@index(snd-clip)@i(sound), @i(peak))] @c{[sal]}@* +@altdef{@code[(snd-clip @i(sound) @i(peak))] @c{[lisp]}}@\Hard limit @i(sound) +to the given @i(peak), a positive number. The samples of @i(sound) are constrained between an upper value +of @i(peak) and a lower value of @subtract()@i(peak). Use @code(clip) instead (see Section @ref(clip-sec)). + +@codef[snd-compose(@index(compose)@index(signal composition)@pragma(defn)@index(snd-compose)@i(f), @i(g))] @c{[sal]}@* +@altdef{@code[(snd-compose @i(f) @i(g))] @c{[lisp]}}@\Compose two signals, i.e. +compute @i(f)(@i(g)(@i(t))), where @i(f) and @i(g) are sounds. This function +is used primarily to implement time warping, but it can be used in other +applications such as frequency modulation. For each sample @i(x) in @i(g), +@i(snd-compose) looks up the value of @i(f)(@i(x)) using linear +interpolation. The resulting sample rate, start time, etc. are taken from +@i(g). The sound @i(f) is used in effect as a lookup table, but it is +assumed that @i(g) is non-decreasing, so that @i(f) is accessed in time +order. This allows samples of @i(f) to be computed and discarded +incrementally. If in fact @i(g) decreases, the current sample of @i(g) is +replaced by the previous one, forcing @i(g) into compliance with the +non-decreasing restriction. See also @code(sref), @code(shape), and +@code(snd-resample). + +For an extended example that uses @code(snd-compose) for variable pitch shifting, +see @code(demos/pitch_change.htm).@index(demos, pitch change)@index(pitch shifting) +@index(variable-resample function)@index(resampling) + +@label(snd-tapv-sec) +@codef[snd-tapv(@pragma(defn)@index(snd-tapv)@index(tap)@index(variable delay)@index(delay, +variable)@index(chorus)@i(sound), @i(offset), @i(vardelay), @i(maxdelay))] @c{[sal]}@* +@altdef{@code[(snd-tapv @i(sound) @i(offset) @i(vardelay) @i(maxdelay))] @c{[lisp]}}@\A +variable delay: @i(sound) is delayed by the sum of @i(offset) (a @code(FIXNUM) or @code(FLONUM)) +and @i(vardelay) (a @code(SOUND)). The specified delay is adjusted to lie in the range +of zero to @i(maxdelay) seconds to yield the actual delay, and the delay is +implemented using linear interpolation. This function was designed specifically +for use in a chorus effect: the @i(offset) is set to half of @i(maxdelay), and +the @i(vardelay) input is a slow sinusoid. The maximum delay is limited to +@i(maxdelay), which determines the length of a fixed-sized buffer. The function +@code(tapv) is equivalent and preferred (see Section @ref(tapv-sec)). + +@codef[snd-tapf(@pragma(defn)@index(snd-tapf)@index(variable delay)@index(delay, variable)@i(sound), @i(offset), @i(vardelay), @i(maxdelay))] @c{[sal]}@* +@altdef{@code[(snd-tapf @i(sound) @i(offset) @i(vardelay) @i(maxdelay))] @c{[lisp]}}@\A +variable delay like @code(snd-tapv) except there is no linear interpolation. By +eliminating interpolation, the output is an exact copy of the input with no filtering +or distortion. On the other hand, delays jump by samples causing samples to double or +skip even when the delay is changed smoothly. + +@codef[snd-copy(@pragma(defn)@index(snd-copy)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-copy @i(sound))] @c{[lisp]}}@\Makes a copy of @i(sound). +Since operators always make (logical) copies of their sound parameters, this +function should never be needed. This function is here for debugging@index(dubugging). + +@codef[snd-down(@pragma(defn)@index(snd-down)@i(srate), @i(sound))] @c{[sal]}@* +@altdef{@code[(snd-down @i(srate) @i(sound))] @c{[lisp]}}@\Linear interpolation +of samples down to the given sample rate @i(srate), which must be lower than +the sample rate of @i(sound). Do not call this function. Nyquist performs +sample-rate conversion automatically as needed. If you want to force a +conversion, call @code(force-srate) (see Section @ref(force-srate-sec)). + +@codef[snd-exp(@pragma(defn)@index(snd-exp)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-exp @i(sound))] @c{[lisp]}}@\Compute the exponential of each sample of @i(sound). Use @code(s-exp) instead (see Section @ref(s-exp-sec)). + +@label(snd-follow-sec) +@codef[snd-follow(@pragma(defn)@index(snd-follow)@index(follower)@index(envelope follower)@i(sound), @i(floor), @i(risetime), @i(falltime), @i(lookahead))] @c{[sal]}@* +@altdef{@code[(snd-follow @i(sound) @i(floor) @i(risetime) @i(falltime) @i(lookahead))] @c{[lisp]}}@\An envelope +follower. The basic goal of this function is to generate a smooth signal +that rides on the peaks of the input signal. The usual objective is to +produce an amplitude envelope given a low-sample rate (control rate) +signal representing local RMS measurements. The first argument is the +input signal. The @i(floor) is the minimum output value. The @i(risetime) is the time (in seconds) it takes for the output to rise (exponentially) from @i(floor) to unity (1.0) and the @i(falltime) is the time it takes for the output to fall (exponentially) from unity to @i(floor). The algorithm looks ahead for peaks and will begin to increase the output signal according to @i(risetime) in anticipation of a peak. The amount of anticipation (in sampless) is given by @i(lookahead). The algorithm is as follows: the output value is allowed to increase according to @i(risetime) or decrease according to @i(falltime). If the next input sample is in this range, that sample is simply output as the next output sample. If the next input sample is too large, the algorithm goes back in time as far as necessary to compute an envelope that rises according to @i(risetime) to meet the new value. The algorithm will only work backward as far as @i(lookahead). If that is not far enough, then there is a final forward pass computing a rising signal from the earliest output sample. In this case, the output signal will be at least momentarily less than the input signal and will continue to rise exponentially until it intersects the input signal. If the input signal falls faster than indicated by @i(falltime), the output fall rate will be limited by @i(falltime), and the fall in output will stop when the output reaches @i(floor). This algorithm can make two passes througth the buffer on sharply rising inputs, so it is not particularly fast. With short buffers and low sample rates this should not matter. See @code(snd-avg) above for a function that can help to generate a low-sample-rate input for @code(snd-follow). See @code(snd-chase) in Section @ref(snd-chase-sec) for a related filter. + +@codef[snd-gate(@pragma(defn)@index(snd-gate)@index(noise gate)@index(gate)@i(sound), @i(lookahead), @i(risetime), @i(falltime), @i(floor), @i(threshold))] @c{[sal]}@* +@altdef{@code[(snd-gate @i(sound) @i(lookahead) @i(risetime) @i(falltime) @i(floor) @i(threshold))] @c{[lisp]}}@\This function generates an exponential rise and decay intended for noise gate implementation. The decay starts when the signal drops below threshold and stays there for longer than lookahead. Decay continues until the value reaches floor, at which point the decay stops and the output value is held constant. Either during the decay or after the floor is reached, if the signal goes above threshold, then the output value will rise to unity (1.0) at the point the signal crosses the threshold. Again, look-ahead is used, so the rise actually starts before the signal crosses the threshold. The rise is a constant-rate exponential and set so that a rise from @i(floor) to unity occurs in @i(risetime). Similarly, the fall is a constant-rate exponential such that a fall from unity to @i(floor) takes @i(falltime). The result is delayed by @i(lookahead), so the output is not actually synchronized with the input. To compensate, you should drop the initial @i(lookahead) of samples. Thus, @code(snd-gate) is not recommended for direct use. Use @code(gate) instead (see Section @ref(gate-sec)). + +@codef[snd-inverse(@index(inverse)@pragma(defn)@index(snd-inverse)@i(signal), @i(start), @i(srate))] @c{[sal]}@* +@altdef{@code[(snd-inverse @i(signal) @i(start) @i(srate))] @c{[lisp]}}@\Compute the function inverse of @i(signal), that is, compute @i(g)(@i(t)) such that @i(signal)(@i(g)(@i(t))) = @i(t). This function assumes that @i(signal) is non-decreasing, it uses linear interpolation, the resulting sample rate is @i(srate), and the result is shifted to have a starting time of @i(start). If @i(signal) decreases, the true inverse may be undefined, so we define @code(snd-inverse) operationally as follows: for each output time point @i(t), scan ahead in @i(signal) until the value of signal exceeds @i(t). Interpolate to find an exact time point @i(x) from @i(signal) and output @i(x) at time @i(t). This function is intended for internal system use in implementing time warps. + +@codef[snd-log(@pragma(defn)@index(snd-log)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-log @i(sound))] @c{[lisp]}}@\Compute the natural logorithm of each sample of @i(sound). Use @code(s-log) instead (see Section @ref(s-log-sec)). + +@label(peak-sec) +@codef[peak(@index(peak, maximum amplitude)@pragma(defn)@index(peak)@i(expression), @i(maxlen))] @c{[sal]}@* +@altdef{@code[(peak @i(expression) @i(maxlen))] @c{[lisp]}}@\Compute the maximum absolute value of the amplitude of a sound. The sound is created by evaluating @i(expression) (as in @code(s-save)). Only the first @i(maxlen) samples are evaluated. The @i(expression) is automatically quoted (@code(peak) is a macro), so do not quote this parameter. If @i(expression) is a variable, then the @i(global binding) of that variable will be used. Also, since the variable retains a reference to the sound, the sound will be evaluated and left in memory. See Section @ref(peak-ex-sec) on @pragma(startref) page @pageref(peak-ex-sec) for examples. + +@label(snd-max-sec) +@codef[snd-max(@pragma(defn)@index(snd-max)@index(maximum amplitude)@i(expression), @i(maxlen))] @c{[sal]}@* +@altdef{@code[(snd-max @i(expression) @i(maxlen))] @c{[lisp]}}@\Compute the maximum absolute value of the amplitude of a sound. The sound is created by evaluating @i(expression) (as in @code(snd-save)), which is therefore normally quoted by the caller. At most @i(maxlen) samples are computed. The result is the maximum of the absolute values of the samples. @p(Notes:) It is recommended to use @code(peak) (see above) instead. If you want to find the maximum of a sound bound to a local variable and it is acceptable to save the samples in memory, then this is probably the function to call. Otherwise, use @code(peak). + +@codef[snd-maxv(@pragma(defn)@index(snd-maxv)@index(maximum of two sounds)@i(sound1), @i(sound2))] @c{[sal]}@* +@altdef{@code[(snd-maxv @i(sound1) @i(sound2))] @c{[lisp]}}@\Compute the maximum of @i(sound1) and @i(sound2) on a sample-by-sample basis. The resulting +sound has its start time at the maximum of the input start times and a logical stop +at the minimum logical stop of the inputs. The physical stop time is the minimum of +the physical stop times of the two sounds. @i(Note that this violates the ``normal'' +interpretation that sounds are zero outside their start and stop times. For +example, even if) sound1 @i(extends beyond) sound2 @i(and is greater than zero, +the result +value in this extension will be zero because it will be after the physical stop time, +whereas if we simply treated) sound2 @i(as zero in this region and took the maximum, we +would get a non-zero result.) Use @code(s-max) instead (see Section @ref(s-max-sec)). + +@codef[snd-normalize(@pragma(defn)@index(snd-normalize)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-normalize @i(sound))] @c{[lisp]}}@\Internally, sounds +are stored with a scale factor that applies to all samples of the sound. +All operators that take sound arguments take this scale factor into account +(although it is not always necessary to perform an actual multiply per +sample), so you should never need to call this function. This function +multiplies each sample of a sound by its scale factor, returning a sound +that represents the same signal, but whose scale factor is 1.0. + +@codef[snd-oneshot(@pragma(defn)@index(snd-oneshot)@index(oneshot)@index(threshold)@i(sound), @i(threshold), @i(ontime))] @c{[sal]}@* +@altdef{@code[(snd-oneshot @i(sound) @i(threshold) @i(ontime))] @c{[lisp]}}@\Computes a new sound that is zero +except where @i(sound) exceeds threshold. From these points, the result is +1.0 until @i(sound) remains below @i(threshold) for @i(ontime) (in seconds). +The result has the same sample rate, start time, logical stop time, and +duration as @i(sound). + +@codef[snd-prod(@pragma(defn)@index(snd-prod)@index(signal multiplication)@index(multiplication)@i(sound1), @i(sound2))] @c{[sal]}@* +@altdef{@code[(snd-prod @i(sound1) @i(sound2))] @c{[lisp]}}@\Computes the +product of @i(sound1) and @i(sound2). The resulting sound has its start +time at the maximum of the input start times and a logical stop at the minimum +logical stop of the inputs. Do not use this function. Use @code(mult) or +@code(prod) instead (see Section @ref(mult-sec)). Sample rate, start time, etc. are taken from @i(sound). + +@codef[snd-pwl(@pragma(defn)@index(snd-pwl)@index(piece-wise linear)@i(t0), @i(sr), +@i(lis))] @c{[sal]}@* +@altdef{@code[(snd-pwl @i(t0) @i(sr) @i(lis))] @c{[lisp]}}@\Computes a piece-wise linear function according to the breakpoints +in @i(lis). The starting time is @i(t0), and the sample rate is @i(sr). +The breakpoints are passed in an XLISP list (of type @code(LVAL)) where the +list alternates sample numbers (@code(FIXNUM)s, computed in samples +from the beginning of the pwl function) and values (the value of the pwl +function, given as a @code(FLONUM)). There is an implicit starting +point of (0, 0). The list must contain an odd number of points, the omitted +last +value being implicitly zero (0). The list is assumed to be well-formed. Do +not call this function. Use @code(pwl) instead (see Section @ref(pwl-sec)). + +@codef[snd-quantize(@pragma(defn)@index(snd-quantize)@i(sound), @i(steps))] @c{[sal]}@* +@altdef{@code[(snd-quantize @i(sound) @i(steps))] @c{[lisp]}}@\Quantizes a sound. See Section +@ref(quantize-sec) for details. + +@codef[snd-recip(@pragma(defn)@index(snd-recip)@i(sound))] @c{[sal]}@* +@altdef{@code[(snd-recip @i(sound))] @c{[lisp]}}@\Compute the reciprocal of each sample of @i(sound). Use @code(recip) instead (see Section @ref(recip-sec)). + +@codef[snd-resample(@pragma(defn)@index(snd-resample)@index(sample interpolation)@i(f), +@i(rate))] @c{[sal]}@* +@altdef{@code[(snd-resample @i(f) @i(rate))] @c{[lisp]}}@\Resample sound @i(f) using high-quality interpolation, yielding +a new sound with the specified @i(rate). The result is scaled by 0.95 because often, +in resampling, interpolated values exceed the original sample values, and this +could lead to clipping. +The resulting start time, etc. are taken from +@i(f). Use @code(resample) instead. + +@codef[snd-resamplev(@pragma(defn)@index(snd-resamplev)@index(sample interpolation)@index(signal composition)@i(f), @i(rate), @i(g))] @c{[sal]}@* +@altdef{@code[(snd-resamplev @i(f) @i(rate) @i(g))] @c{[lisp]}}@\Compose two +signals, i.e. compute @i(f)(@i(g)(@i(t))), where @i(f) and @i(g) are +sounds. The result has sample rate given by @i(rate). At each time @i(t) +(according to the @i(rate)), @i(g) is linearly interpolated to yield an +increasing sequence of high-precision score-time values. @i(f) is then +interpolated at each value to yield a result sample. If in fact @i(g) +decreases, the current sample of @i(g) is replaced by the previous one, +forcing @i(g) into compliance with the non-decreasing restriction. +The result is scaled by 0.95 because often, +in resampling, interpolated values exceed the original sample values, and this +could lead to clipping. Note that +if @i(g) has a high sample rate, this may introduce unwanted jitter into +sample times. See @code(sound-warp) for a detailed discussion. See +@code(snd-compose) for a fast, low-quality alternative to this function. +Normally, you should use @code(sound-warp) instead of this function. + + +@codef[snd-scale(@pragma(defn)@index(snd-scale)@i(scale), @i(sound))] @c{[sal]}@* +@altdef{@code[(snd-scale @i(scale) @i(sound))] @c{[lisp]}}@\Scales the amplitude of @i(sound) by the factor @i(scale). Use @code(scale) instead (see Section +@ref(scale-sec)). + +@codef{snd-shape(@pragma(defn)@index(snd-shape)@i(signal), @i(table), @i(origin))} @c{[sal]}@* +@altdef{@code[(snd-shape @i(signal) @i(table) @i(origin))] @c{[lisp]}}@\A waveshaping function. This is the primitive upon which @code(shape) is based. The @code(snd-shape) function is like @code(shape) except that @i(signal) and @i(table) must be (single-channel) sounds. Use @code(shape) instead (see Section @ref(shape-sec)). + +@codef[snd-up(@pragma(defn)@index(snd-up)@i(srate), @i(sound))] @c{[sal]}@* +@altdef{@code[(snd-up @i(srate) @i(sound))] @c{[lisp]}}@\Increases sample rate by linear +interpolation. The @i(sound) is the signal to be up-sampled, and @i(srate) +is the output sample rate. Do not call this function. Nyquist performs +sample-rate conversion automatically as needed. If you want to force a +conversion, call @code(force-srate) (see Section @ref(force-srate-sec)). + +@label(snd-xform-sec) +@codef[snd-xform(@pragma(defn)@index(snd-xform)@i(sound), @i(sr), @i(time), @i(start), +@i(stop), @i(scale))] @c{[sal]}@* +@altdef{@code[(snd-xform @i(sound) @i(sr) @i(time) @i(start) @i(stop) @i(scale))] @c{[lisp]}}@\Makes a copy of @i(sound) and then alters it in +the following order: (1) the start time (@code(snd-t0)) of the sound is shifted to +@i(time), (1) the sound is stretched as a result of setting the sample rate +to @i(sr) (the start time is unchanged by this), (3) the sound is clipped + from @i(start) to @i(stop), (4) if @i(start) is greater than @i(time), the sound is shifted +shifted by @i(time) - @i(start), so that the start time is @i(time), (5) the +sound is scaled by @i(scale). An empty (zero) sound at @i(time) will be +returned if all samples are clipped. Normally, you should accomplish all +this using transformations. A transformation applied to a sound has no +effect, so use @code(cue) to create a transformable sound (see Section +@ref(use-sounds-sec)). + +@label(snd-yin-sec) +@codef{snd-yin(@pragma(defn)@index(snd-yin)@i(sound), @i(minstep), @i(maxstep), @i(rate))} @c{[sal]}@* +@altdef{@code[(snd-yin @i(sound) @i(minstep) @i(maxstep) @i(rate))] @c{[lisp]}}@\Identical to +@code[yin]. See Section @ref(yin-sec). + +@end(fndefs) + +@subsection(Filters) +These are also ``Signal Operators,'' the subject of the previous section, +but there are so many filter functions, they are +documented in this special section. + +Some filters allow time-varying filter parameters. In these functions, +filter coefficients are calculated at the sample rate of the filter +parameter, and coefficients are not interpolated. + +@begin(fndefs) + +@codef[snd-alpass(@pragma(defn)@index(snd-alpass)@i(sound), @i(delay), @i(feedback))] @c{[sal]}@* +@altdef{@code[(snd-alpass @i(sound) @i(delay) @i(feedback))] @c{[lisp]}}@\An all-pass filter. This produces a repeating echo effect without the resonances of @code(snd-delay). The @i(feedback) should be less than one to avoid exponential amplitude blowup. Delay is rounded to the nearest sample. You should use @code(alpass) instead (see Section @ref(alpass-sec)). + +@codef[snd-alpasscv(@pragma(defn)@index(snd-alpasscv)@i(sound), @i(delay), +@i(feedback))] @c{[sal]}@* +@altdef{@code[(snd-alpasscv @i(sound) @i(delay) @i(feedback))] @c{[lisp]}}@\An all-pass filter with variable @i(feedback). +This is just like @i(snd-alpass) except @i(feedback) is a sound. +You should use @code(alpass) instead (see Section @ref(alpass-sec)). + +@codef[snd-alpassvv(@pragma(defn)@index(snd-alpassvv)@i(sound), @i(delay), @i(feedback), @i(maxdelay))] @c{[sal]}@* +@altdef{@code[(snd-alpassvv @i(sound) @i(delay) @i(feedback) @i(maxdelay))] @c{[lisp]}}@\An all-pass filter with variable @i(feedback) and @i(delay). This is just like @i(snd-alpass) except @i(feedback) and @i(delay) are sounds, and there is an additional @code(FLONUM) parameter, @i(maxdelay), that gives an upper bound on the value of @i(delay). @p(Note:) @i(delay) must remain between zero and @i(maxdelay). If not, results are undefined, and Nyquist may crash. You should use @code(alpass) instead (see Section @ref(alpass-sec)). + +@codef[snd-areson(@pragma(defn)@index(snd-areson)@i(sound), @i(hz), @i(bw), +@i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-areson @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\A notch filter modeled after the @code(areson) +unit generator in Csound. The @code(snd-areson) filter is an exact +complement of @code(snd-reson) such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. Note that because of this complementary design, +the power is not normalized as in @code(snd-reson). See @code(snd-reson) +for details on @i(normalization). You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-aresoncv(@pragma(defn)@index(snd-aresoncv)@i(sound), @i(hz), @i(bw), +@i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-aresoncv @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\This function is identical to @code(snd-areson) except +the @i(bw) (bandwidth) parameter is a sound. Filter coefficients are +updated at the sample rate of @i(bw). The ``@code(cv)'' suffix stands for Constant, +Variable, indicating that @i(hz) and @i(bw) are constant (a number) and +variable (a sound), respectively. This naming convention is used throughout. +You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-aresonvc(@pragma(defn)@index(snd-aresonvc)@i(sound), @i(hz), @i(bw), +@i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-aresonvc @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\This function is identical to @code(snd-areson) except +the @i(hz) (center frequency) parameter is a sound. Filter coefficients are +updated at the sample rate of @i(hz). +You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-aresonvv(@pragma(defn)@index(snd-aresonvv)@i(sound), @i(hz), @i(bw), +@i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-aresonvv @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\This function is identical to @code(snd-areson) except +both @i(hz) (center frequency) and @i(bw) (bandwidth) are sounds. Filter +coefficients are updated at the next sample of either @i(hz) or @i(bw). +You should use @code(areson) instead (see +Section @ref(areson-sec)). + +@codef[snd-atone(@pragma(defn)@index(snd-atone)@i(sound), @i(hz))] @c{[sal]}@* +@altdef{@code[(snd-atone @i(sound) @i(hz))] @c{[lisp]}}@\A high-pass filter +modeled after the @code(atone) unit generator in Csound. The @code(snd-atone) filter is an exact +complement of @code(snd-tone) such that if both are applied to the +same signal with the same parameters, the sum of the results yeilds +the original signal. You should use @code(hp) instead (see +Section @ref(hp-sec)). + +@codef[snd-atonev(@pragma(defn)@index(snd-atonev)@i(sound), @i(hz))] @c{[sal]}@* +@altdef{@code[(snd-atonev @i(sound) @i(hz))] @c{[lisp]}}@\This is just like +@code(snd-atone) except that the @i(hz) cutoff frequency is a sound. Filter +coefficients are updated at the sample rate of @i(hz). You should use +@code(hp) instead (see Section @ref(hp-sec)). + +@codef[snd-biquad(@pragma(defn)@index(snd-biquad)@i(sound), @i(b0), @i(b1), @i(b2), @i(a1), @i(a2), @i(z1init), @i(z2init))] @c{[sal]}@* +@altdef{@code[(snd-biquad @i(sound) @i(b0) @i(b1) @i(b2) @i(a1) @i(a2) @i(z1init) @i(z2init))] @c{[lisp]}}@\A general second order IIR filter, where @i(a0) is assumed to be unity. For @i(a1) and @i(a2), the sign convention is opposite to that of Matlab. All parameters except the input @i(sound) are of type @code(FLONUM). You should probably use one of @code(lowpass2), @code(highpass2), @code(bandpass2), @code(notch2), @code(allpass2), @code(eq-lowshelf), @code(eq-highshelf), @code(eq-band), @code(lowpass4), @code(lowpass6), @code(lowpass8), @code(highpass4), @code(highpass6), or @code(highpass8), which are all based on @code(snd-biquad) and described in Section @ref(lowpass2-sec). For completeness, you will also find @code(biquad) and @code(biquad-m) described in that section. + +@label(snd-chase-sec) +@codef[snd-chase(@pragma(defn)@index(snd-chase)@i(sound), @i(risetime), @i(falltime))] @c{[sal]}@* +@altdef{@code[(snd-chase @i(sound) @i(risetime) @i(falltime))] @c{[lisp]}}@\A slew rate limiter. The output ``chases'' the input at rates determined by @i(risetime) and @i(falltime). If the input changes too fast, the output will lag behind the input. This is a form of lowpass filter, but it was created to turn hard-switching square waves into smoother control signals that could be used for linear crossfades. If the input switches from 0 to 1, the output will linearly rise to 1 in @i(risetime) seconds. If the input switches from 1 to 0, the output will linearly fall to 0 in @i(falltime) seconds. The generated slope is constant; the transition is linear; this is not an exponential rise or fall. The @i(risetime) and @i(falltime) must be scalar constants; complain to the author if this is not adequate. The @code(snd-chase) function is safe for ordinary use. See @code(snd-follow) in Section @ref(snd-follow-sec) for a related function. + +@codef[snd-congen(@pragma(defn)@index(snd-congen)@i(gate), @i(risetime), @i(falltime))] @c{[sal]}@* +@altdef{@code[(snd-congen @i(gate) @i(risetime) @i(falltime))] @c{[lisp]}}@\A simple ``contour generator'' based +on analog synthesizers. The @i(gate) is a sound that normally steps from 0.0 to 1.0 at the start of an envelop and goes from +1.0 back to 0.0 at the beginning of the release. At each sample, the output converges to the input exponentially. If @i(gate) is greater than the output, e.g. the attack, then the output converges half-way to the output in @i(risetime). If the @i(gate) is less than the output, the half-time is @i(falltime). The sample rate, starting time, logical-stop-time, and terminate time are taken from @i(gate). You should use @code(congen) instead (see Section @ref(congen-sec). + +@codef[snd-convolve(@pragma(defn)@index(snd-convolve)@i(sound), @i(response))] @c{[sal]}@* +@altdef{@code[(snd-convolve @i(sound) @i(response))] @c{[lisp]}}@\Convolves +@i(sound) by @i(response) using a simple O(N x M) algorithm. The @i(sound) +can be any length, but the @i(response) is computed and stored in a table. The required compuation time per sample and total space are proportional to the +length of @i(response). Use @code(convolve) instead (see Section +@ref(convolve-sec)). + +@codef[snd-delay(@pragma(defn)@index(snd-delay)@i(sound), @i(delay), @i(feedback))] @c{[sal]}@* +@altdef{@code[(snd-delay @i(sound) @i(delay) @i(feedback))] @c{[lisp]}}@\Feedback +delay. The output, initially @i(sound), is recursively delayed by @i(delay), scaled by @i(feedback), and added to itself, producing an repeating echo effect. The @i(feedback) should be less than one to avoid exponential amplitude blowup. Delay is rounded to the nearest sample. You should use @code(feedback-delay) instead (see Section @ref(feedback-delay-sec)) + +@codef[snd-delaycv(@pragma(defn)@index(snd-delaycv)@i(sound), @i(delay), +@i(feedback))] @c{[sal]}@* +@altdef{@code[(snd-delaycv @i(sound) @i(delay) @i(feedback))] @c{[lisp]}}@\Feedback delay with variable @i(feedback). This is just like +@i(snd-delay) except @i(feedback) is a sound. You should use +@code(feedback-delay) instead (see Section @ref(feedback-delay-sec)). + +@codef[snd-reson(@pragma(defn)@index(snd-reson)@i(sound), @i(hz), @i(bw), @i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-reson @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\A +second-order resonating (bandpass) filter with center frequency @i(hz) and +bandwidth @i(bw), modeled after the @code(reson) unit generator in Csound. +The @i(normalization) parameter must be an integer and (like in Csound) +specifies a scaling factor. A value of 1 specifies a peak amplitude +response of 1.0; all frequencies other than @i(hz) are attenuated. A +value of 2 specifies the overall RMS value of the amplitude response +is 1.0; thus filtered white noise would retain the same power. A value of +zero specifies no scaling. The result sample rate, start time, etc. are takend from @i(sound). +You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-resoncv(@pragma(defn)@index(snd-resoncv)@i(sound), @i(hz), @i(bw), +@i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-resoncv @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\This function is identical to @code(snd-reson) except +@i(bw) (bandwidth) is a sound. Filter coefficients are updated at the +sample rate of @i(bw). You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-resonvc(@pragma(defn)@index(snd-resonvc)@i(sound), @i(hz), @i(bw), +@i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-resonvc @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\This function is identical to @code(snd-reson) except +@i(hz) (center frequency) is a sound. Filter coefficients are updated at the +sample rate of @i(hz). You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-resonvv(@pragma(defn)@index(snd-resonvv)@i(sound), @i(hz), @i(bw), +@i(normalization))] @c{[sal]}@* +@altdef{@code[(snd-resonvv @i(sound) @i(hz) @i(bw) @i(normalization))] @c{[lisp]}}@\This function is identical to @code(snd-reson) except +botth @i(hz) (center frequency) and @i(bw) (bandwidth) are sounds. Filter +coefficients are updated at the next sample from either @i(hz) or @i(bw). You should use @code(reson) instead (see Section +@ref(reson-sec)). + +@codef[snd-stkchorus(@pragma(defn)@index(snd-stkchorus)@index(chorus)@index(effect, chorus)@index(STK chorus)@i(sound), @i(delay), @i(depth), @i(freq), @i(mix), +@i(sr))] @c{[sal]}@* +@altdef{@code[(snd-stkchorus @i(sound) @i(delay) @i(depth) @i(freq) @i(mix) @i(sr))] @c{[lisp]}}@\A chorus implemented in STK. The parameter @i(delay) is a @code(FIXNUM) +representing the median desired delay length in samples. A typical +value is 6000. The @code(FLONUM) parameters @i(depth) and @i(freq) set the modulation +depth (from 0 to 1) and modulation frequency (in Hz), @i(mix) sets the mixture +of input sound and chorused sound, where a value of 0.0 means input sound +only (dry) and a value of 1.0 means chorused sound only (wet). +The parameter @i(sr) is the desired sample rate of the resulting sound@foot(This +is probably a mistake since sample rate is implied by @i(sound). This parameter +may be removed in a future release.) You should use @code(pitshift) instead +(see Section @ref(stkchorus-sec)). + +@codef[snd-stkpitshift(@pragma(defn)@index(snd-stkpitshift)@index(pitch shift)@index(effect, pitch shift)@index(STK pitch shift)@i(sound), @i(shift), @i(mix), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-stkpitshift @i(sound) @i(shift) @i(mix) @i(sr))] @c{[lisp]}}@\A +pitch shifter implemented in STK. The @i(sound) is shifted in pitch by +@i(shift), a @code(FLONUM) representing the shift factor. A value of 1.0 means + no shift. The parameter @i(mix) sets the mixture of input and shifted sounds. +A value of 0.0 means input only (dry) and a value of 1.0 means shifted +sound only (wet). The @i(sr) is the desired sampling frequency.@foot(This +is probably a mistake since sample rate is implied by @i(sound). This parameter +may be removed in a future release.) You should use @code(pitshift) instead +(see Section @ref(stkpitshift-sec)). + +@codef[snd-stkrev(@pragma(defn)@index(snd-stkrev)@index(reverb)@index(effect, reverberation)@index(STK reverb)@i(rev-type), @i(sound), @i(decay), @i(mix), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-stkrev @i(rev-type) @i(sound) @i(decay) @i(mix) @i(sr))] @c{[lisp]}}@\A reverb +implemented in STK. The parameter rev-type is a @code(FIXNUM) ranging from zero to +two and selects the type of reverb. Zero selects NRev type, one selects JCRev, +and two selects PRCRev. The input @i(sound) is processed by the reverb with +a @i(decay) time in seconds (a @code(FLONUM)). The @i(mix), a @code(FLONUM), +sets the +mixture of dry input and reverb output. A value of 0.0 means input only (dry) +and a value of 1.0 means reverb only (wet). The sample rate +is @i(sr)@foot(This is probably a mistake since sample rate is implied +by @i(sound). This parameter may be removed in a future release.) You +should use @code(nrev), @code(jcrev) or @code(prcrev) instead (see +Section @ref(stkrev-sec)). + +@codef[snd-tone(@pragma(defn)@index(snd-tone)@index(low-pass filter)@i(sound), @i(hz))] @c{[sal]}@* +@altdef{@code[(snd-tone @i(sound) @i(hz))] @c{[lisp]}}@\A +first-order recursive low-pass filter, based on the @i(tone) unit generator +of Csound. The @i(hz) parameter is the cutoff frequency, the response +curve's half-power point. The result sample rate, start time, etc. are takend from @i(sound). +You should use @code(lp) instead (see Section +@ref(lp-sec)). + +@codef[snd-tonev(@pragma(defn)@index(snd-tonev)@i(sound), @i(hz))] @c{[sal]}@* +@altdef{@code[(snd-tonev @i(sound) @i(hz))] @c{[lisp]}}@\This function is +identical to @code(snd-tone) except @i(hz) (cutoff frequency) is a sound. +The filter coefficients are updated at the sample rate of @i(hz). You +should use @code(lp) instead (see Section +@ref(lp-sec)). + + +@end(fndefs) + + +@subsection(Table-Lookup Oscillator Functions) +These functions all use a sound to describe one period of a periodic +waveform. In the current implementation, the sound samples are copied to an +array (the waveform table) when the function is called. To make a +table-lookup oscillator generate a specific pitch, we need to have several +pieces of information: +@begin(itemize) +A waveform to put into the table. This comes from the @i(sound) parameter. + +The length (in samples) of the waveform. This is obtained by reading +samples (starting at the sound's start time, not necessarily at time zero) +until the physical stop time of the sound. (If you read the waveform from a +file or generate it with functions like @code(sim) and @code(sine), then the +physical and logical stop times will be the same and will correspond to the +duration you specified, rounded to the nearest sample.) + +The intrinsic sample rate of the waveform. This sample rate is simply the +sample rate property of @i(sound). + +The pitch of the waveform. This is supplied by the @i(step) parameter and +indicates the pitch (in steps) of @i(sound). You might expect that the +pitch would be related to the period (length) of @i(sound), but there is the +interesting case that synthesis based on sampling often loops over multiple +periods. This means that the fundamental frequency of a generated tone may +be some multiple of the looping rate. In Nyquist, you always specify the +perceived pitch of the looped @i(sound) if the sound is played at the +@i(sound)'s own sample rate. + +The desired pitch. This is specified by the @i(hz) parameter +in Hertz (cycles per second) in these low-level functions. Note that this +is not necessarily the ``loop'' rate at which the table is scanned. +Instead, Nyquist figures what sample rate conversion would be necessary to +``transpose'' from the @i(step) which specifies the original pitch of +@i(sound) to @i(hz), which gives the desired pitch. The mixed use of steps +and Hertz came about because it seemed that sample tables would be tagged +with steps (``I sampled a middle-C''), whereas frequency deviation in the +@code(fmosc) function is linear, thus calling for a specification in Hertz. + +The desired sample rate. This is given by the @i(sr) parameter in Hertz. +@end(itemize) + +Other parameters common to all of these oscillator functions are: +@begin(itemize) +@i(t0), the starting time, and + +@i(phase), the starting phase in degrees. Note that if the @i(step) +parameter indicates that the table holds more than one fundamental period, then a starting phase of 360 will be different than a starting phase of 0. +@end(itemize) + +@begin(fndefs) + @codef[snd-amosc(@pragma(defn)@index(snd-amosc)@i(sound), @i(step), @i(sr), @i(hz), @i(t0), +@i(am), @i(phase))] @c{[sal]}@* +@altdef{@code[(snd-amosc @i(sound) @i(step) @i(sr) @i(hz) @i(t0) @i(am) @i(phase))] @c{[lisp]}}@\An oscillator with amplitude modulation. The sound +@i(am) specifies the amplitude and the logical stop time. The physical stop +time is also that of @i(am). You should use @code(amosc) instead (see +Section @ref(amosc-sec)). + +@codef[snd-fmosc(@pragma(defn)@index(snd-fmosc)@i(s), @i(step), @i(sr), @i(hz), @i(t0), @i(fm), +@i(phase))] @c{[sal]}@* +@altdef{@code[(snd-fmosc @i(s) @i(step) @i(sr) @i(hz) @i(t0) @i(fm) @i(phase))] @c{[lisp]}}@\A Frequency Modulation oscillator. The sound @i(fm) specifies +frequency deviation (in Hertz) from @i(hz). You should use @code(fmosc) +instead (see Section @ref(fmosc-sec)). + +@codef[snd-fmfb(@pragma(defn)@index(snd-fmfb)@i(t0), @i(hz), @i(sr), @i(index), @i(dur))] @c{[sal]}@* +@altdef{@code[(snd-fmfb @i(t0) @i(hz) @i(sr) @i(index) @i(dur))] @c{[lisp]}}@\A Feedback FM oscillator. The resulting sound starts +at @i(t0), has a fundamental frequency of @i(hz), a sample rate of @i(sr), +and a duration of @i(dur) seconds. The @i(index) is a @code(FLONUM) that +specifies the amount of feedback. You should use @code(fmfb) instead (see +Section @ref(fmfb-sec)). + +@codef[snd-fmfbv(@pragma(defn)@index(snd-fmfbv)@i(t0), @i(hz), @i(sr), @i(index))]@* +@altdef{@code[(snd-fmfv @i(t0) @i(hz) @i(sr) @i(index))] @c{[lisp]}}@\A + Feedback FM oscillator. The resulting sound starts +at @i(t0), has a fundamental frequency of @i(hz), and +a sample rate of @i(sr). The @i(index) is a @code(SOUND) that +specifies the amount of feedback and determines the duration. +You should use @code(fmfb) instead (see Section @ref(fmfb-sec)). + +@codef[snd-buzz(@pragma(defn)@index(snd-buzz)@i(n), @i(sr), @i(hz), @i(t0), @i(fm))] @c{[sal]}@* +@altdef{@code[(snd-buzz @i(n) @i(sr) @i(hz) @i(t0) @i(fm))] @c{[lisp]}}@\A +buzz oscillator, which generates @i(n) harmonics of equal amplitude. +The @i(fm) specifies +frequency deviation (in Hertz) from @i(hz). You should use @code(buzz) +instead (see Section @ref(buzz-sec)). + +@codef[snd-pluck(@pragma(defn)@index(snd-pluck)@i(sr), @i(hz), @i(t0), @i(d), + @i(final-amp))] @c{[sal]}@* +@altdef{@code[(snd-pluck @i(sr) @i(hz) @i(t0) @i(d) @i(final-amp))] @c{[lisp]}}@\A Karplus-Strong plucked string oscillator with sample rate +@i(sr), fundamental frequency @i(hz), starting time @i(t0), duration @i(d), +initial amplitude approximately 1.0 (not exact because the string is +initialized with random values) and final amplitude approximately +@i(final-amp). You should use @code(pluck) instead (see Section + @ref(pluck-sec)). + +@codef[snd-osc(@pragma(defn)@index(snd-osc)@i(s), @i(step), @i(sr), @i(hz), @i(t0), @i(d), @i(phase))] @c{[sal]}@* +@altdef{@code[(snd-osc @i(s) @i(step) @i(sr) @i(hz) @i(t0) @i(d) @i(phase))] @c{[lisp]}}@\A simple table lookup oscillator with fixed frequency. The duration +is @i(d) seconds. You should use @code(osc) instead (see Section +@ref(osc-sec)). + +@codef[snd-partial(@pragma(defn)@index(snd-partial)@i(sr), @i(hz), @i(t0), @i(env))] @c{[sal]}@* +@altdef{@code[(snd-partial @i(sr) @i(hz) @i(t0) @i(env))] @c{[lisp]}}@\This is a +special case of @code(snd-amosc) that generates a sinusoid starting at phase +0 degrees. The @i(env) parameter gives the envelope or any other amplitude +modulation. You should use @code(partial) instead (see Section +@ref(partial-sec)). + +@codef[snd-sine(@pragma(defn)@index(snd-sine)@i(t0), @i(hz), @i(sr), @i(d))] @c{[sal]}@* +@altdef{@code[(snd-sine @i(t0) @i(hz) @i(sr) @i(d))] @c{[lisp]}}@\This is a +special case of @code(snd-osc) that always generates a sinusoid with initial +phase of 0 degrees. You should use @code(sine) instead (see Section @ref(sine-sec)). + +@codef[snd-siosc(@pragma(defn)@index(snd-siosc)@i(tables), @i(sr), @i(hz), @i(t0), +@i(fm))] @c{[sal]}@* +@altdef{@code[(snd-siosc @i(tables) @i(sr) @i(hz) @i(t0) @i(fm))] @c{[lisp]}}@\A Spectral Interpolation Oscillator with frequency modulation. The +@i(tables) is a list of sounds and sample counts as follows: (@i(table0) +@i(count1) @i(table1) ... @i(countN) @i(tableN)). The initial waveform is given by @i(table0), which is interpolated linearly to @i(table1) over the first +@i(count1) samples. From @i(count1) to @i(count2) samples, the waveform is +interpolated from @i(table1) to @i(table2), and so on. If more than +@i(countN) samples are generated, @i(tableN) is used for the remainder of +the sound. The duration and logical stop time of the sound is taken from +@i(fm), which specified frequency modulation (deviation) in Hertz. You +should use @code(siosc) instead (see Section @ref(siosc-sec)). + +@end(fndefs) + +@subsection(Physical Model Functions) +These functions perform some sort of physically-based modeling synthesis. +@begin(fndefs) +@codef[(snd-bandedwg@pragma(defn)@index(snd-bandedwg)@index(STK banded waveguide) @i(freq) @i(bowpress-env) @i(preset) @i(sr))]@* +@altdef{@code[(snd-bandedwg @i(freq) @i(bowpress-env) @i(preset) @i(sr))] @c{[lisp]}}@\A Banded Wave Guide +Percussion instrument implemented in STK. The parameter @i(freq) is a +@code(FLONUM) in Hz, @i(bowpress-env) is +a @code(SOUND) that ranges from zero to one, @i(preset) is a @code(FIXNUM), +and @i(sr) is the desired sample rate in Hz. Currently, there are four +presets: uniform-bar (0), tuned-bar (1), glass-harmonica (2), and +tibetan-bowl (3). You should use @code(wg-uniform-bar), @code(wg-tuned-bar), + @code(wg-glass-harm), or @code(wg-tibetan-bowl) instead (see Section +@ref(bandedwg-sec)). + +@codef[snd-bowed(@pragma(defn)@index(snd-bowed)@index(stk bowed)@i(freq), +@i(bowpress-env), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-bowed @i(freq) @i(bowpress-env) @i(sr))] @c{[lisp]}}@\A bowed string instrument implemented in +STK. The freq is a @code(FLONUM) in Hertz, bowpress-env is a + @code(SOUND) that ranges from z +ero to one, and sr is the desired sample rate (a @code(FLONUM)). +You should use bowed instead (see Section @ref(bowed-sec)). + +@codef[snd-bowed-freq(@pragma(defn)@index(snd-bowed-freq)@index(stk bowed)@i(freq), @i(bowpress-env), @i(freq-env), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-bowed-freq @i(freq) @i(bowpress-env) @i(freq-env) @i(sr))] @c{[lisp]}}@\A bowed model just like @code(snd-bowed) but with +an additional parameter for continuous frequency control. You should use +@code(bowed-freq) instead (see Section @ref(bowed-sec)). + +@codef[snd-clarinet(@pragma(defn)@index(snd-clarinet)@index(stk clarinet)@i(freq), @i(breath-env), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-clarinet @i(freq) @i(breath-env) @i(sr))] @c{[lisp]}}@\A clarinet +model implemented in STK. The @i(freq) is a @code(FLONUM) in Hertz, + @i(breath-env) is +a @code(SOUND) that ranges from zero to one, and @i(sr) is the + desired sample +rate (a @code(FLONUM)). You should use @code(clarinet) instead + (see Section +@ref(clarinet-sec)). + +@codef[snd-clarinet-freq(@pragma(defn)@index(snd-clarinet-freq)@index(STK clarinet)@i(freq), @i(breath-env), @i(freq-env), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-clarinet-freq @i(freq) @i(breath-env) @i(freq-env) @i(sr))] @c{[lisp]}}@\A clarinet model just like @code(snd-clarinet) but with +an additional parameter for continuous frequency control. You should use +@code(clarinet-freq) instead (see Section @ref(clarinet-sec)). + +@codef[snd-clarinet-all(@pragma(defn)@index(snd-clarinet-all)@i(freq), @i(vibrato-freq), +@i(vibrato-gain), @i(freq-env), @i(breath-env), +@i(reed-stiffness), @i(noise), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-clarinet-all @i(freq) @i(vibrato-freq) @i(vibrato-gain) @i(freq-env) @i(breath-env) @i(reed-stiffness) @i(noise) @i(sr))] @c{[lisp]}}@\A clarinet model just like +@code(snd-clarinet-freq) but with +additional parameters for vibrato generation and continuous control of +reed stiffness and breath noise. You should use +@code(clarinet-all) instead (see Section @ref(clarinet-sec)). + +@codef[snd-flute(@pragma(defn)@index(snd-flute)@index(stk flute)@i(freq), + @i(breath-env), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-flute @i(freq) @i(breath-env) @i(sr))] @c{[lisp]}}@\A flute implemented in STK. The @i(freq) is a +@code(FLONUM) in Hertz, @i(breath-env) is a @code(SOUND) + that ranges from zero to one, and @i(sr) is + the desired sample rate (a @code(FLONUM)). You should use @code(flute) + instead (see Section @ref(flute-sec)). + +@codef[snd-flute-freq(@pragma(defn)@index(snd-flute-freq)@index(stk flute)@i(freq), @i(breath-env), +@i(freq-env), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-flute-freq @i(freq) @i(breath-env) @i(freq-env) @i(sr))] @c{[lisp]}}@\A flute model just like @code(snd-flute) but with +an additional parameter for continuous frequency control. You should use +@code(flute-freq) instead (see Section @ref(flute-sec)). + +@codef[snd-flute-all(@pragma(defn)@index(snd-flute-all)@index(stk flute)@i(freq), @i(vibrato-freq), @i(vibrato-gain), @i(freq-env), @i(breath-env), +@i(jet-delay), @i(noise), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-flute-all @i(freq) @i(vibrato-freq) @i(vibrato-gain) @i(freq-env) @i(breath-env) @i(jet-delay) @i(noise) @i(sr))] @c{[lisp]}}@\A flute model just like +@code(snd-flute-freq) but with +additional parameters for vibrato generation and continuous control of +breath noise. You should use +@code(flute-all) instead (see Section @ref(flute-sec)). + +@codef[snd-mandolin(@pragma(defn)@index(snd-mandolin)@index(STK mandolin)@i(t0), @i(freq), @i(dur), @i(body-size), @i(detune), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-mandolin @i(t0) @i(freq) @i(dur) @i(body-size) @i(detune) @i(sr))] @c{[lisp]}}@\A plucked + double-string instrument model implemented in STK. The @i(t0) parameter + is the starting time (in seconds), @i(freq) is a @code(FLONUM) in + Hz, @i(body-size) and @i(detune) are @code(FLONUM)s, and @code(sr) + is the desired sample + rate. You should use @code(mandolin) instead (see Section @ref(mandolin-sec)). + +@codef[snd-modalbar(@pragma(defn)@index(snd-modalbar)@index(STK modal bar)@i(t0), @i(freq), @i(preset), @i(dur), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-modalbar @i(t0) @i(freq) @i(preset) @i(dur) @i(sr))] @c{[lisp]}}@\Struck bar instrument + model implemented in STK. The parameter @i(t0) is the starting +time (in seconds), @i(freq) is a @code(FLONUM) in Hz, + @code(preset) is a @code(FIXNUM) ranging from 0 to 8, @i(dur) is a +@code(FLONUM) that + sets the duration (in seconds) and @i(sr) is the desired sample rate. You +should use @code(modalbar) instead (see Section @ref(modalbar-sec)). + +@codef[snd-sax(@pragma(defn)@index(snd-sax)@index(STK sax)@i(freq), @i(breath-env), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-sax @i(freq) @i(breath-env) @i(sr))] @c{[lisp]}}@\A sax +model implemented in STK. The @i(freq) is a @code(FLONUM) in Hertz, @i(breath-env) is +a @code(SOUND) that ranges from zero to one, and @i(sr) is the desired sample +rate (a @code(FLONUM)). You should use @code(sax) instead (see Section +@ref(sax-sec)). + +@codef[snd-sax-freq(@pragma(defn)@index(snd-sax-freq)@i(freq), @i(freq-env), @i(breath-env), + @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-sax-freq @i(freq) @i(freq-env) @i(breath-env) @i(sr))] @c{[lisp]}}@\A sax model just like @code(snd-sax) but with +an additional parameter for continuous frequency control. You should use +@code(sax-freq) instead (see Section @ref(sax-sec)). + +@codef[snd-sax-all(@pragma(defn)@index(snd-sax-all)@i(freq), @i(vibrato-freq), +@i(vibrato-gain), @i(freq-env), @i(breath-env), +@i(reed-stiffness), @i(noise), @i(blow-pos), @i(reed-table-offset), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-sax-all @i(freq) @i(vibrato-freq) @i(vibrato-gain) @i(freq-env) @i(breath-env) @i(reed-stiffness) @i(noise) @i(blow-pos) @i(reed-table-offset) @i(sr))] @c{[lisp]}}@\A +sax model just like +@code(snd-sax-freq) but with +additional parameters for vibrato generation and continuous control of +reed stiffness, breath noise, excitation position, and reed table offset. + You should use +@code(sax-all) instead (see Section @ref(sax-sec)). + +@codef[snd-sitar(@pragma(defn)@index(snd-sitar)@index(STK sitar)@i(t0), +@i(freq), @i(dur), @i(sr))] @c{[sal]}@* +@altdef{@code[(snd-sitar @i(t0) @i(freq) @i(dur) @i(sr))] @c{[lisp]}}@\A sitar model implemented in STK. The parameter +@i(t0) is the starting time, @i(freq) is a @code(FLONUM) (in Hz), E +@i(dur) sets the duration and @i(sr) is the sample rate (in Hz) +of the resulting sound. You should use @code(sitar) instead (see Section +@ref(sitar-sec)). + + +@end(fndefs) + + +@subsection(Sequence Support Functions) +The next two functions are used to implement Nyquist's @code(seq) construct. + +@begin(fndefs) +@codef[snd-seq(@pragma(defn)@index(snd-seq)@i(sound), @i(closure))] @c{[sal]}@* +@altdef{@code[(snd-seq @i(sound) @i(closure))] @c{[lisp]}}@\This function returns +@i(sound) until the logical stop time of @i(sound). Then, the XLISP +@i(closure) +is evaluated, passing it the logical stop time of @i(sound) as a +parameter. The closure must return a sound, which is then added to +@i(sound). (An add is used so that @i(sound) can continue past its logical +stop if desired.) Do not call this function. See @code(seq) in Section +@ref(seq-sec). + +@codef[snd-multiseq(@pragma(defn)@index(snd-multiseq)@i(array), @i(closure))] @c{[sal]}@* +@altdef{@code[(snd-multiseq @i(array) @i(closure))] @c{[lisp]}}@\This +function is similar to @code(snd-seq) except the first parameter is a +multichannel sound rather than a single sound. A multichannel sound is +simply an XLISP array of sounds. An array of sounds is returned which is +the sum of @i(array) and another array of sounds returned by @i(closure). +The @i(closure) is passed the logical stop time of the multichannel sound, +which is the maximum logical stop time of any element of @i(array). Do +not call this function. See @code(seq) in Section @ref(seq-sec). +@end(fndefs) + +@begin(fndefs) +@codef[snd-trigger(@pragma(defn)@index(snd-trigger)@i(s), @i(closure))] @c{[sal]}@* +@altdef{@code[(snd-trigger @i(s) @i(closure))] @c{[lisp]}}@\This is one of +the only ways in which a behavior instance can be created by changes in a +signal. When @i(s) (a @code(SOUND)) makes a transition from less than or +equal to zero to greater than zero, the closure, which takes a starting +time parameter, is evaluated. The closure must return a @code(SOUND). The +sum of all these sounds is returned. If there are no sounds, the result will +be zero. The stop time of the result is the maximum stop time of @i(s) and +all sounds returned by the closure. The sample rate of the return value is +the sample rate of @i(s), and the sounds returned by the closure must all +have that same sample rate. Do not call this function. +See @code(trigger) in Section @ref(trigger-sec). + +An implementation note: There is no way to have @code(snd-trigger) return +a multichannel sound. An alternative implementation would be a built-in +function to scan ahead in a sound to find the time of the next zero crossing. +This could be combined with some LISP code similar to @code(seq) to sum up +instances of the closure. However, this would force arbitrary look-ahead +and therefore would not work with real-time inputs, which was the motivation +for @code(snd-trigger) in the first place. +@end(fndefs) + +@chapter(Nyquist Globals) +@index(Global Variables) +There are many global variables in Nyquist. A convention in Lisp is to place asterisks (*) around global variables, e.g. @code(*table*). This is only a convention, and the asterisks are just like any other letter as far as variable names are concerned. Here are some globals users should know about: + +@begin(description, leftmargin +2 in, indent -2 in) +@codef(*table*)@index(*table*)@\Default table used by @code(osc) and other oscillators. + +@codef(*A4-Hertz*)@pragma(defn)@index(*a4-hertz*)@\Frequency of A4 in Hertz.. Note: you must call @code[(set-pitch-names)] to recompute pitches after changing @code(*A4-Hertz*). + +@codef(*autonorm*)@pragma(defn)@index(*autonorm*)@\The normalization factor to be applied to the next sound when @code(*autonorm-type*) is @code('previous). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonormflag*)@pragma(defn)@index(*autonormflag*)@\Enables the automatic normalization feature of the @code(play) command. You should use @code[(autonorm-on)] and @code[(autonorm-off)] rather than setting @code(*autonormflag*) directly. See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-max-samples*)@pragma(defn)@index(*autonorm-max-samples*)@\Specifies how many samples will be computed searching for a peak value when @code(*autonorm-type*) is @code('lookahead). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-previous-peak*)@pragma(defn)@index(*autonorm-previous-peak*)@\The peak of the previous sound generated by @code(play). This is used to compute the scale factor for the next sound when @code(*autonorm-type*) is @code('previous). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-target*)@pragma(defn)@index(*autonorm-target*)@\The target peak amplitude for the autonorm feature. The default value is 0.9. See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*autonorm-type*)@pragma(defn)@index(*autonorm-type*)@\Determines how the autonorm feature is implemented. Valid values are @code('lookahead) (the default) and @code('previous). See Sections @ref(peak-ex-sec) and @ref(play-sec). + +@codef(*breakenable*)@pragma(defn)@index(*breakenable*)@\Controls whether XLISP enters a break loop when an error is encountered. See Section @ref(symbols-sec). + +@codef(*control-srate*)@pragma(defn)@index(*control-srate*)@\Part of the environment, establishes the control sample rate. See Section @ref(environment-sec) for details. + +@codef(*default-sf-bits*)@pragma(defn)@index(*default-sf-bits*)@\The default bits-per-sample for sound files. Typically 16. + +@codef(*default-sf-dir*)@pragma(defn)@index(*default-sf-dir*)@\The default sound file directory. Unless you give a full path for a file, audio files are assumed to be in this directory. (Applies to many functions that deal with sound files. Check the function description to see if @code(*default-sf-dir*) applies.) + +@codef(*default-sf-format*)@pragma(defn)@index(*default-sf-format*)@\The default sound file format. When you write a file, this will be the default format: AIFF for Mac and most Unix systems, NeXT for NeXT systems, and WAV for Win32. + +@codef(*default-sf-srate*)@pragma(defn)@index(*default-sf-srate*)@\The default sample rate for sound files. Typically 44100.0, but often set to 22050.0 for speed in non-critical tasks. + +@codef(*default-control-srate*)@pragma(defn)@index(*default-control-srate*)@\Default value for @code(*control-srate*). This value is restored when you execute @code[(top)] to pop out of a debugging session. Change it by calling @code[(set-control-srate @i(value))]. + +@codef(*default-sound-srate*)@pragma(defn)@index(*default-sound-srate*)@\Default value for @code(*sound-srate*). This value is restored when you execute @code[(top)] to pop out of a debugging session. Change it by calling @code[(set-sound-srate @i(value))]. + +@codef(*file-separator*)@pragma(defn)@index(*file-separator*)@\The character that separates directories in a path, +e.g. ``@code(/)'' for Unix, ``@code(:)'' for Mac, and ``@code(\)'' for Win32. +This is normally set in @code(system.lsp). + +@codef(*rslt*)@pragma(defn)@index(*rslt*)@\When a function returns more than one value, @code(*rslt*) is set to a list of the ``extra'' values. This provides a make-shift version of the @code(multiple-value-return) facility in Common Lisp. + +@codef(*sound-srate*)@pragma(defn)@index(*sound-srate*)@\Part of the environment, establishes the audio sample rate. See Section @ref(environment-sec) for details. + +@codef(*soundenable*)@pragma(defn)@index(*soundenable*)@\Controls whether writes to a sound file will also be played as audio. Set this variable by calling @code{(sound-on)} or @code{(sound-off)}. + +@codef(*tracenable*)@pragma(defn)@index(*tracenable*)@\Controls whether XLISP prints a backtrace when an error is encountered. + +@b(XLISP variables)@\See Section @ref(symbols-sec) for a list of +global variables defined by XLISP. + +@b(Environment variables)@\See Section @ref(environment-sec) for definitions of variables used in the environment for behaviors. In general, you should never set or access these variables directly. + +@b(Various constants)@\See Section @ref(constants-sec) for definitions of predefined constants for loudness, duration, and pitch. + +@end(description) + +@chapter(Time/Frequency Transformation) +Nyquist provides functions for FFT and inverse FFT operations on streams of audio data. +Because sounds can be of any length, but an FFT operates on a fixed amount of data, FFT +processing is typically done in short blocks or windows that move through the audio. Thus, +a stream of samples is converted in to a sequence of FFT frames representing short-term +spectra. + +Nyquist does not have a special data type corresponding to a sequence of FFT frames. +This would be nice, but it would require creating a large set of operations suitable for +processing frame sequences. Another approach, and perhaps the most ``pure'' would +be to convert a single sound into a multichannel sound, with one channel per bin of the +FFT. + +Instead, Nyquist violates its ``pure'' functional model and resorts to objects +for FFT processing. A sequence of frames is represented by an XLISP object. Whenever you +send the selector @code[:next] to the object, you get back either NIL, indicating the +end of the sequence, or you get an array of FFT coefficients. + +The Nyquist function @code[snd-fft] (mnemonic, isn't it?) returns one of the frame sequence +generating objects. You can pass any frame sequence generating object to another function, +@code[snd-ifft], and turn the sequence back into audio. + +With @code[snd-fft] and @code[snd-ifft], you can create all sorts of interesting processes. The main +idea is to create intermediate objects that both accept and generate sequences of frames. +These objects can operate on the frames to implement the desired spectral-domain +processes. Examples of this can be found in the file +@code[fft_tutorial.htm]@index(fft tutorial)@index(fast fourier transform tutorial)@index(demos, fft), +which is part of the standard Nyquist release. The documentation for @code[snd-fft] and +@code[snd-ifft] follows. + +@begin(fndefs) +@codef[snd-fft(@pragma(defn)@index(snd-fft)@index(fft)@i(sound), @i(length), @i(skip), @i(window))] @c{[sal]}@* +@altdef{@code[(snd-fft @i(sound) @i(length) @i(skip) @i(window))] @c{[lisp]}}@\This +function performs an FFT on the first samples in @i(sound) and returns a Lisp array of @code[FLONUM]s. +The function modifies the @i(sound), violating the normal rule that sounds are immutable in Nyquist, so +it is advised that you copy the sound using @code[snd-copy] if there are any other references to +@i(sound). The length of the FFT is specified by @i(length), a @code[FIXNUM] (integer) which must +be a power of 2. After +each FFT, the sound is advanced by @i(skip) samples, also of type @code[FIXNUM]. Overlapping FFTs, +where @i(skip) is less than @i(length), are allowed. If @i(window) is not @code[NIL], it must be a sound. +The first @i(length) samples of @i(window) are multiplied by @i(length) samples of @i(sound) before +performing the FFT. When there are no more samples in @i(sound) to transform, +this function returns @code[NIL]. The coefficients in the returned array, in order, are the DC coefficient, +the first real, the first imaginary, the second real, the second imaginary, etc. +The last array element corresponds to the real coefficient at the Nyquist frequency. + +@codef[snd-ifft(@pragma(defn)@index(snd-ifft)@index(ifft)@index(inverse fft)@i(time), @i(srate), @i(iterator), @i(skip), @i(window))] @c{[sal]}@* +@altdef{@code[(snd-ifft @i(time) @i(srate) @i(iterator) @i(skip) @i(window))] @c{[lisp]}}@\This function performs an IFFT on a sequence of spectral frames obtained from @i(iterator) +and returns a sound. The start time of the sound is given by @i(time). Typically, this would be computed +by calling @code[(local-to-global 0)]. The sample rate is given by @i(srate). Typically, this would +be @code[*sound-srate*], but it might also depend upon the sample rate of the sound from which the +spectral frames were derived. To obtain each frame, the function sends the message @code[:next] to the +@i(iterator) object, using XLISP's primitives for objects and message passing. The object should return +an array in the same format as obtained from @code[snd-fft], and the object should return @code[NIL] +when the end of the sound is reached. After each frame is inverse transformed into the time domain, it is +added to the resulting sound. Each successive frame is added with a sample offset specified by @i(skip) +relative to the previous frame. This must be an integer greater than zero. If @i(window) is +not @code[NIL], it must be a sound. This window signal is multiplied by the inverse transformed frame +before the frame is added to the output sound. The length of each frame should be the same power of 2. +The length +is implied by the array returned by @i(iterator), so it does not appear as a parameter. This length +is also the number of samples used from @i(window). Extra samples are ignored, and window is padded +with zeros if necessary, so be sure @i(window) is the right length. The resulting sound is computed on +demand as with other Nyquist sounds, so @code[:next] messages are sent to @i(iterator) only when new +frames are needed. One should be careful not to reuse or modify @i(iterator) once it is passed to +@code[snd-ifft]. +@end(fndefs) + +@chapter(MIDI, Adagio, and Sequences) +@label(adagio-chap) +@index(MIDI)@index(Sequences) +Nyquist includes facilities to read and write MIDI files as well as an ASCII +text-based score representation language, Adagio. XLISP and Nyquist can be +used to generate MIDI files using compositional algorithms. (See also Section @ref(xmusic-sec).) +A tutorial on using the Adadio representation and MIDI can be found in +@code(demos/midi_tutorial.htm)@index(demos, midi). The Adagio language is +described below. Adagio was originally developed as part of the CMU MIDI +Toolkit, which included a program to record and play MIDI using the +Adagio representation. Some of the MIDI features of Adagio may not be +useful within Nyquist. + +Nyquist offers a number of different score representations, and you may +find this confusing. In general, MIDI files are a common way to exchange +music performance data, especially with sequencers and score notation +systems. The @code(demos/midi_tutorial.htm) examples show how to get the most +precise control when generating MIDI data. Adagio is most useful as a +text-based score entry language, and it is certainly more compact +than Lisp expressions for MIDI-like data. The Xmusic library +(Chapter @ref(xmusic-sec)) is best for algorithmic generation of music +and score manipulation. There are functions to convert between the +Adagio, MIDI sequence data, and Xmusic score representations. + +@pragma(doinclude) +@include(adagio-nyquist.mss) + +@chapter(Linear Prediction Analysis and Synthesis) +@index(Linear Prediction)@index(LPC) +Nyquist provides functions to perform Linear Prediction Coding (LPC) +analysis and synthesis. In simple terms, LPC analysis assumes that a +sound is the result of an all-pole filter applied to a source with a +flat spectrum. LPC is good for characterizing the general spectral +shape of a signal, which may be time-varying as in speech sounds. +For synthesis, any source can be filtered, allowing the general +spectral shape of one signal (used in analysis) to be applied to +any source (used in synthesis). A popular effect is to give vowel-like +spectra to musical tones, creating an artificial (or sometimes natural) +singing voice. + +Examples of LPC analysis and synthesis can be found in the file +@code[lpc_tutorial.htm]@index(lpc tutorial)@index(linear prediction tutorial)@index(demos, lpc), +which is part of the standard Nyquist release. + +As with FFT processing, LPC analysis takes a sound as input and returns +a stream of frames. Frames are returned from an object using the @code(:next) +selector just as with FFT frames. An LPC frame is a list consisting of: +@i(RMS1), the energy of the input signal, @i(RMS2), the energy of the +residual signal, @i(ERR), the square root of @i(RMS1)/@i(RMS2), and +@i(FILTER-COEFS), an array of filter coefficients. To make code more +readable and to avoid code dependence on the exact format of a frame, +the functions @code(lpc-frame-rms1)@index(lpc-frame-rms1), +@code(lpc-frame-rms2)@index(lpc-frame-rms2), +@code(lpc-frame-err)@index(lpc-frame-err), and +@code(lpc-frame-filter-coefs)@index(lpc-frame-filter-coefs) can be +applied to a frame to obtain the respective fields. + +The @i(z) transform +of the filter is @i(H)(@i(z)) = 1/@i(A)(@i(z)), where @i(A)(@i(z)) is a +polynomial of the form @i(A)(@i(z)) = 1 + @i(a@-[1])@i(z) + +@i(a@-[2])@i(z) + ... + @i(a@-[p])@i(z). The @i(FILTER-COEFS) array has +the form @code[#(]@i(a@-[p]) @i(a@-[p-1]) ... @i(a@-[3]) +@i(a@-[2]) @i(a@-[1])@code[)]. + +The file @code(lpc.lsp) defines some useful classes and functions. The file +is @i(not) automatically loaded with Nyquist, so you must execute +@code[(load "lpc")] before using them. + +@section(LPC Classes and Functions) +@begin(fndefs) +@codef[make-lpanal-iterator(@pragma(defn)@index(make-lpanal-iterator)@i(sound), @i(framedur), @i(skiptime), @i(npoles))] @c{[sal]}@* +@altdef{@code[(make-lpanal-iterator @i(sound) @i(framedur) @i(skiptime) @i(npoles))] @c{[lisp]}}@\Makes an iterator +object, an instance of @code(lpanal-class), +that returns LPC frames from successive frames of samples in +@i(sound). The duration (in seconds) +of each frame is given by @i(framedur), a +@code(FLONUM). The skip size (in seconds) between successive frames +is given by @i(skiptime), a @code(FLONUM). Typical values for +@i(framedur) and @i(skiptime) are 0.08 and 0.04, giving 25 frames +per second and a 50% frame overlap. The number of poles is given +by @i(npoles), a @code(FIXNUM). The result is an object that +responds to the @code(:next) selector by returning a frame as +described above. @code(NIL) is returned when @i(sound) terminates. +(Note that one or more of the last analysis windows may be +padded with zeros. @code(NIL) is only returned when the corresponding +window would begin after the termination time of the sound.) + +@codef[make-lpc-file-iterator(@pragma(defn)@index(make-lpc-file-iterator)@i(filename))] @c{[sal]}@* +@altdef{@code[(make-lpc-file-iterator @i(filename))] @c{[lisp]}}@\Another way to get LPC frames is to read them from a + file. This function opens an ASCII file containing LPC frames and + creates an iterator object, an instance of class @code(lpc-file-class) + to access them. Create a file using @code(save-lpc-file) (see below). + +@codef[save-lpc-file(@pragma(defn)@index(save-lpc-file)@i(lpc-iterator), @i(filename))] @c{[sal]}@* +@altdef{@code[(save-lpc-file @i(lpc-iterator) @i(filename))] @c{[lisp]}}@\Create a file containing LPC frames. +This file can be read by @code[make-lpc-file-iterator] (see above). + +@codef{show-lpc-data(@pragma(defn)@index(show-lpc-data)@i(lpc-iterator), +@i(iniframe), @i(endframe) [, @i(poles?)])} @c{[sal]}@* +@altdef{@code{(show-lpc-data @i(lpc-iterator) @i(iniframe) @i(endframe) + [@i(poles?)])} @c{[lisp]}}@\Print values of LPC +frames from an LPC iterator object. The object is @i(lpc-iterator), +which is typically an instance of @code(lpanal-class) or +@code(lpc-file-class). Frames are numbered from zero, and only +files starting at @i(iniframe) (a @code[FIXNUM]) and ending before +@i(endframe) (also a @code[FIXNUM]) are printed. By default, only +the values for @i(RMS1), @i(RMS2), and @i(ERR) are printed, but +if optional parameter @i(poles?) is non-@code[NIL], then +the LPC coefficients are also printed. + +@codef[allpoles-from-lpc(@pragma(defn)@index(allpoles-from-lpc)@i(snd), @i(lpc-frame))] @c{[sal]}@* +@altdef{@code[(allpoles-from-lpc @i(snd) @i(lpc-frame))] @c{[lisp]}}@\A single LPC frame defines a filter. +Use @code(allpoles-from-lpc) to apply this filter to @i(snd), +a @code(SOUND). To obtain @i(lpc-frame), a @code(LIST) + containing an LPC frame, either send @code(:next) to an + LPC iterator, or use @code(nth-frame) (see below). The result + is a @code(SOUND) whose duration is the same as that of @i(snd). + +@codef[lpreson(@pragma(defn)@index(lpreson)@i(snd), @i(lpc-iterator), +@i(skiptime))] @c{[sal]}@* +@altdef{@code[(lpreson @i(snd) @i(lpc-iterator) @i(skiptime))] @c{[lisp]}}@\Implements a time-varying all-pole filter +controlled by a sequence of LPC frames from an iterator. The +@code(SOUND) to be filtered is @i(snd), and the source of +LPC frames is @i(lpc-iterator), typically an instance of +@code(lpanal-class) or @code(lpc-file-class). The frame +period (in seconds) is given by @i(skiptime) (a @code(FLONUM)). +This number does not have to agree with the @i(skiptime) used +to analyze the frames. (Greater values will cause the filter +evolution slow down, and smaller values will cause it to +speed up.) The result is a @code(SOUND). The duration of the +result is the minimum of the duration of @i(snd) and that of +the sequence of frames. + +@codef[lpc-frame-rms1(@pragma(defn)@index(lpc-frame-rms1)@i(frame))] @c{[sal]}@* +@altdef{@code[(lpc-frame-rms1 @i(frame))] @c{[lisp]}}@\Get the energy of the input signal from a frame. + +@codef[lpc-frame-rms2(@pragma(defn)@index(lpc-frame-rms2)@i(frame))] @c{[sal]}@* +@altdef{@code[(lpc-frame-rms2 @i(frame))] @c{[lisp]}}@\Get the energy of the residual from a frame. + +@codef[lpc-frame-err(@pragma(defn)@index(lpc-frame-err)@i(frame))] @c{[sal]}@* +@altdef{@code[(lpc-frame-err @i(frame))] @c{[lisp]}}@\Get the square root of @i(RMS1)/@i(RMS2) from a frame. + +@codef[lpc-frame-filter-coefs(@pragma(defn)@index(lpc-frame-filter-coefs)@i(frame))] @c{[sal]}@* +@altdef{@code[(lpc-frame-filter-coefs @i(frame))] @c{[lisp]}}@\Get the filter coefficients from a frame. + +@end(fndefs) + +@section(Low-level LPC Functions) +The lowest-level Nyquist functions for LPC are +@begin(itemize) +@code(snd-lpanal) for analysis, + +@code(snd-allpoles), an all-pole filter with fixed coefficients, and + +@code(snd-lpreson), an all-pole filter that takes frames from an LPC iterator. +@end(itemize) + +@begin(fndefs) +@codef[snd-lpanal(@pragma(defn)@index(snd-lpanal)@i(samps), @i(npoles))] @c{[sal]}@* +@altdef{@code[(snd-lpanal @i(samps) @i(npoles))] @c{[lisp]}}@\Compute +an LPC frame with @i(npoles) (a @code(FIXNUM)) poles from an +@code(ARRAY) of samples (@code(FLONUMS)). Note that @code(snd-fetch-array) +can be used to fetch a sequence of frames from a sound. Ordinarily, you +should not use this function. Use @code(make-lpanal-iterator) instead. + +@codef[snd-allpoles(@pragma(defn)@index(snd-allpoles)@i(snd), @i(lpc-coefs), @i(gain))] @c{[sal]}@* +@altdef{@code[(snd-allpoles @i(snd) @i(lpc-coefs) @i(gain))] @c{[lisp]}}@\A fixed all-pole filter. The input is +@i(snd), a @code(SOUND). The filter coefficients are given by @i(lpc-coefs) +(an @code(ARRAY)), and the filter gain is given by @i(gain), a @code(FLONUM). +The result is a @code(SOUND) whose duration matches that of @i(snd). +Ordinarily, you should use @code(allpoles-from-lpc) instead (see above). + +@codef[snd-lpreson(@pragma(defn)@index(snd-lpreson)@i(snd), @i(lpc-iterator), +@i(skiptime))] @c{[sal]}@* +@altdef{@code[(snd-lpreson @i(snd) @i(lpc-iterator) @i(skiptime))] @c{[lisp]}}@\This function is identical to @code(lpreson) (see above). +@end(fndefs) + + +@chapter(Developing and Debugging in Nyquist) +@index(debugging)@index(developing code) +There are a number of tools, functions, and techniques that can help to debug Nyquist programs. Since these are described in many places +throughout this manual, this chapter brings together many suggestions and techniques for developing code and debugging. You @i(really) +should read this chapter before you spend too much time with Nyquist. Many problems that you will certainly run into are addressed here. + +@section(Debugging) +Probably the most important debugging tool is the backtrace. There are +two kinds of backtrace: one for SAL, and one for Lisp. + +SAL mode is actually just an XLISP function (@code(sal)) that reads +input and evaluates it. When SAL encounters an error, it normally +prints a trace of the SAL stack (all the active functions written in SAL), +exists the current command, and reads the next command. + +If you call XLISP functions from SAL, including most Nyquist sound +processing functions, and an error occurs within these XLISP functions, +you will only see the SAL function that called the XLISP functions +listed in the stack trace. Sometimes you need more details. + +When Nyquist encounters an error when it is not running SAL, it +normally suspends execution and prints an +error message. To find out where in the program the error occurred +and how you got there, start by typing @code[(bt)]. This will print +out the last several function calls and their arguments, which is +usually sufficient to see what is going on. + +In order for @code[(bt)] to work, you must have a couple of global +variables set: @code(*tracenable*) is ordinarily set to @code(NIL). +If it is true, then a backtrace is automatically printed when an +error occurs; @code(*breakenable*) must be set to @code(T), as +it enables the execution to be suspended when an error is +encountered. If @code(*breakenable*) is @code(NIL) (false), +then execution stops when an error occurs but the stack is +not saved and you cannot get a backtrace. Finally, @code(bt) +is just a macro to save typing. The actual backtrace function +is @code(baktrace), which takes an integer argument telling how +many levels to print. All of these things are set up by default +when you start Nyquist. + +To get this XLISP backtrace behavior when SAL encounters an error, +you need to have @code(*breakenable*) set while SAL is running. The +best way to do this is to run within the NyquistIDE program, +open the Preferences dialog, and choose the desired settings, e.g. +``Enable XLISP break on SAL error.'' + +Since Nyquist sounds are executed with a lazy evaluation scheme, some +errors are encountered when samples are being generated. In this +case, it may not be clear which expression is in error. Sometimes, it +is best to explore a function or set of functions by examining +intermediate results. Any expression that yields a sound can be +assigned to a variable and examined using one or more of: +@code(s-plot), @code(snd-print-tree), and of course @code(play). The +@code(snd-print-tree) function prints a lot of detail about the inner +representaion of the sound. Keep in mind that if you assign a sound +to a global variable and then look at the samples (e.g. with +@code(play) or @code(s-plot)), the samples will be retained in +memory. At 4 bytes per sample, a big sound may use all of your +memory and cause a crash. + +Another technique is to use low sample rates so that it is easier to +plot results or look at samples directly. The calls: +@begin(example) +set-sound-srate(100) +set-control-srate(100) +@end(example) +set the default sample rates to 100, which is too slow for audio, but useful for examining programs and results. The function +@begin(example) +snd-samples(@i(sound), @i(limit)) +@end(example) +will convert up to @i(limit) samples from @i(sound) into a Lisp +array. This is another way to look at results in detail. + +The @code(trace) function is sometimes useful. It prints the name of +a function and its arguments everytimg the function is called, and the +result is printed when the function exits. To trace the osc function, +type: +@begin(example) +trace(osc) +@end(example) +and to stop tracing, type @code[untrace(osc)]. + +If a variable needs a value or a function is undefined, and if @code(*breakenable*) was set, you will get a prompt where you can fix +the error (by setting the variable or loading the function definition) +and keep going. At the debug (or break) prompt, your input must +be in XLISP, not SAL syntax. Use @code[(co)], short for @code[(continue)] to +reevaluate the variable or function and continue execution. + +When you finish debugging a particular call, you can ``pop'' +up to the top level by typing @code[(top)], a short name for @code[(top-level)]. +There is a button named "Top" in the NyquistIDE that takes you back to the +top level (ready to accept XLISP expressions), +and another button named "SAL" that puts you back in SAL mode. + +@section(Useful Functions) +@begin(fndefs) +@codef[grindef(@pragma(defn)@index(grindef)@index(listing of lisp function)@i(name))] @c{[sal]}@* +@altdef{@code[(grindef @i(name))] @c{[lisp]}}@\Prints +a formatted listing of a lisp function. This is often useful to quickly inspect +a function without searching for it in source files. Do not forget to quote the +name, e.g. @code[(grindef 'prod)]. + +@codef[args(@pragma(defn)@index(args)@index(arguments to a lisp function)@i(name))] @c{[sal]}@* +@altdef{@code[(args @i(name))] @c{[lisp]}}@\Similar +to @code(grindef), this function prints the arguments to a function. This may +be faster than looking up a function in the documentation if you just need a +reminder. For example, @code[(args 'lp)] prints ``(LP S C),'' which may help you +to remember that the arguments are a sound (S) followed by the cutoff (C) +frequency. +@end(fndefs) + +The following functions are useful short-cuts that might have been included in +XLISP. They are so useful that they are defined as part of Nyquist. + +@begin(fndefs) +@codef[incf(@pragma(defn)@index(incf)@index(increment)@i(symbol))] @c{[sal]}@* +@altdef{@code[(incf @i(symbol))] @c{[lisp]}}@\Increment @i(symbol) +by one. This is a macro, and @i(symbol) can be anything that can be set by +@code(setf). Typically, @i(symbol) is a variable: ``@code[(incf i)],'' but +@i(symbol) can also be an array element: ``@code[(incf (aref myarray i))].'' + +@codef[decf(@pragma(defn)@index(decf)@index(decrement)@i(symbol))] @c{[sal]}@* +@altdef{@code[(decf @i(symbol))] @c{[lisp]}}@\Decrement @i(symbol) +by one. (See @code(incf), above.) + +@codef[push(@pragma(defn)@index(push)@i(val), @i(lis))] @c{[sal]}@* +@altdef{@code[(push @i(val) @i(lis))] @c{[lisp]}}@\Push @i(val) onto @i(lis) (a Lisp +list). This is a macro that is equivalent to writing (in Lisp) +@code[(setf @i(lis) (cons @i(val) @i(lis)))]. + +@codef[pop(@pragma(defn)@index(pop)@i(lis))] @c{[sal]}@* +@altdef{@code[(pop @i(lis))] @c{[lisp]}}@\Remove (pop) the first item from @i(lis) (a +Lisp list). This is a macro that is equivalent to writing (in Lisp) +@code[(setf @i(lis) (cdr @i(lis)))]. Note that the remaining list is returned, +not the head of the list that has been popped. Retrieve the head of the list +(i.e. the top of the stack) using @code(first) or, equivalently, @code(car). +@end(fndefs) + +The following macros are useful control constructs. + +@begin(fndefs) +@codef[while(@pragma(defn)@index(while)@i(test), @i(expr1), @i(expr2), @r(...))] @c{[sal]}@* +@altdef{@code[(while @i(test) @i(expr1) @i(expr2) @r(...))] @c{[lisp]}}@\A conventional +``while'' loop. If @i(test) is true, evaluate expressions + (@i(expr1), @i(expr2), etc.) and repeat. If @i(test) is false, return. This + expression evaluates to NIL unless the expression @code[(return @i(expr))] + is evaluated, in which case the value of @i(expr) is returned. In SAL, the + loop statement is preferred. + +@codef[when(@pragma(defn)@index(when)@i(test), @i(action))] @c{[sal]}@* +@altdef{@code[(when @i(test) @i(action))] @c{[lisp]}}@\A conventional ``if-then'' +statement. If @i(test) is true, @i(action) is evaluated and returned. Otherwise, +NIL is returned. (Use @code(if) or @code(cond) to implement + ``if-then-else'' and more complex conditional forms. +@end(fndefs) + +It is often necessary to load a file @i(only if) it has not already been +loaded. For example, the @code(pianosyn) library loads very slowly, so if +some other file already loaded it, it would be good to avoid loading it +again. How can you load a file once? Nyquist does not keep track of files +that are loaded, but you must be loading a file to define some function, +so the idea is to tell Nyquist "I require @i(function) from @i(file)"; if +the function does not yet exist, Nyquist satisfies the requirement by loading +the file. +@begin(fndefs) +@codef{require-from(@pragma(defn)@index(require-from)@index(load file conditionally)@i(fnsymbol), +@i(filename) [, @i(path)])} @c{[sal]}@* +@altdef{@code{(require-from @i(fnsymbol) @i(filename) [@i(path)])} @c{[lisp]}}@\Tests whether @i(fnsymbol), an unquoted +function name, is defined. If +not, @i(filename), a @code(STRING), +is loaded. Normally @i(fnsymbol) is a function that will be called from +within the current file, and @i(filename) is the file that defines +@i(fnsymbol). The @i(path), if a @code(STRING), is prepended to @i(filename). +If @i(path) is @code(t) (true), then the directory of the current file is +used as the path. +@end(fndefs) + +Sometimes it is important to load files relative to the current file. For example, +the @code(lib/piano.lsp) library loads data files from the @code(lib/piano) directory, +but how can we find out the full path of @code(lib)? The solution is: +@begin(fndefs) +@codef[current-path(@pragma(defn)@index(current-path)@index(path, +current)@index(full path name))] @c{[sal]}@* +@altdef{@code[(current-path)] @c{[lisp]}}@\Returns the full path name of the file that is +currently being loaded (see @code(load)). Returns NIL if no file is being loaded. +@end(fndefs) + +Finally, there are some helpful math functions: +@begin(fndefs) +@codef[real-random(@index(random)@index(uniform random)@pragma(defn)@index(real-random)@i(from), @i(to))] @c{[sal]}@* +@altdef{@code[(real-random @i(from) @i(to))] @c{[lisp]}}@\Returns a random @code(FLONUM) between @i(from) and @i(to). (See also @code(rrandom), which is equivalent to @code((real-random 0 1))). + +@codef[power(@pragma(defn)@index(power)@index(exponent)@i(x), @i(y))] @c{[sal]}@* +@altdef{@code[(power @i(x) @i(y))] @c{[lisp]}}@\Returns @i(x) raised to +the @i(y) power. +@end(fndefs) + +@chapter(Xmusic and Algorithmic Composition) +@label(xmusic-sec) +@index(Xmusic)@index(Algorithmic Composition) +Several Nyquist libraries offer support for algorithmic composition. Xmusic +is a library for generating sequences and patterns of data. Included in Xmusic +is the @code(score-gen) macro which helps to generate scores from patterns. +Another important facility is the @code(distributions.lsp) library, +containing many different random number generators. + +@section(Xmusic Basics) +Xmusic is inspired by and based on Common Music by Rick Taube. Currently, +Xmusic only implements patterns and some simple support for scores to be +realized as sound by Nyquist. In contrast, Common Music supports MIDI and +various other synthesis languages and includes a graphical interface, some +visualization tools, and many other features. Common Music runs in Common +Lisp and Scheme, but not XLISP, which is the base language for Nyquist. + +Xmusic patterns are objects that generate data streams. For example, +the @code(cycle-class) of objects generate cyclical patterns such as +"1 2 3 1 2 3 1 2 3 ...", or "1 2 3 4 3 2 1 2 3 4 ...". Patterns can +be used to specify pitch sequences, rhythm, loudness, and other parameters. + +Xmusic functions are automatically loaded when you start Nyquist. +To use a pattern object, you first create the pattern, e.g. +@begin(example) +set pitch-source = make-cycle(list(c4, d4, e4, f4)) +@end(example) +After creating the pattern, you can access it repeatedly +with @code(next)@index(next in pattern) to generate data, e.g. +@begin(example) +play seqrep(i, 13, pluck(next(pitch-source), 0.2)) +@end(example) +This will create a sequence of notes with the following pitches: c, d, +e, f, c, d, e, f, c, d, e, f, c. If you evaluate this again, the +pitch sequence will continue, starting on "d". + +It is very important not to confuse the creation of a sequence with +its access. Consider this example: +@begin(example) +play seqrep(i, 13, + pluck(next(make-cycle(list(c4, d4, e4, f4))), 0.2)) +@end(example) +This looks very much like the previous example, but it only repeats notes +on middle-C. The reason is that every time @code(pluck) is evaluated, +@code(make-cycle) is called and creates a new pattern object. After the +first item of the pattern is extracted with @code(next), the cycle is not +used again, and no other items are generated. + +To summarize this important point, there are two steps to using a pattern. +First, the pattern is created and stored in a +variable using @code(setf). Second, the pattern is accessed (multiple +times) using @code(next). + +Patterns can be nested, that is, you can write patterns of patterns. +In general, the @code(next) function does not return patterns. Instead, +if the next item in a pattern is a (nested) pattern, @code(next) recursively +gets the next item of the nested pattern. + +While you might expect that each call to @code(next) would advance the +top-level pattern to the next item, and descend recursively if necessary +to the inner-most nesting level, this is not how @code(next) works. Instead, +@code(next) remembers the last top-level item, and if it was a pattern, +@code(next) continues to generate items from that same inner pattern +until the end of the inner pattern's @i(period) is reached. The next +paragraph explains the concept of the @i(period). + +The data returned by a pattern object is structured into logical groups +called @i(periods). You can get an entire period (as a list) by calling +@code[next(@i(pattern), t)]@index(next pattern). For example: +@begin(example) +set pitch-source = make-cycle(list(c4, d4, e4, f4)) +print next(pitch-source, t) +@end(example) +This prints the list @code[(60 62 64 65)], which is one period +of the cycle. + +You can also get explicit markers that +delineate periods by calling @code[send(@i(pattern), :next)]. In this +case, the value returned is either the next item of the pattern, or the +symbol @code(+eop+) if the end of a period has been reached. What +determines a period? This is up to the specific pattern class, so see the +documentation for specifics. You can override the ``natural'' period +using the keyword @code(for:), e.g. +@begin(example) +set pitch-source = make-cycle(list(c4, d4, e4, f4), for: 3) +print next(pitch-source, t) +print next(pitch-source, t) +@end(example) +This prints the lists @code[(60 62 64) (65 60 62)]. Notice that +these periods just restructure the stream of items +into groups of 3. + +Nested patterns are probably easier to understand by example than by +specification. Here is a simple nested pattern of cycles: +@begin(example) +set cycle-1 = make-cycle({a b c}) +set cycle-2 = make-cycle({x y z}) +set cycle-3 = make-cycle(list(cycle-1, cycle-2)) +exec dotimes(i, 9, format(t, "~A ", next(cycle-3))) +@end(example) +This will print "A B C X Y Z A B C". Notice that the inner-most +cycles @code(cycle-1) and @code(cycle-2) generate a period of items +before the top-level @code(cycle-3) advances to the next pattern. + +Before describing specific pattern classes, there are several optional +parameters that apply in the creating of any pattern object. These are: +@begin(description, leftmargin +2 in, indent -2 in) +@code(for:)@\The length of a period. This overrides the default +by providing a numerical length. The value of this optional +parameter may be a pattern that generates a sequence of integers +that determine the length of each successive period. A period +length may not be negative, but it may be zero. + +@code(name:)@\A pattern object may be given a name. This is useful +if the @code(trace:) option is used. + +@code(trace:)@\If non-null, this optional parameter causes information +about the pattern to be printed each time an item is generated +from the pattern. + +@end(description) +The built-in pattern classes are described in the following section. + +@section(Pattern Classes) +@subsection(cycle) +The @code(cycle-class) iterates repeatedly through a list of items. +For example, two periods of @code[make-cycle({a b c})] would be +@code[(A B C) (A B C)]. + +@begin(fndefs) +@codef{make-cycle(@pragma(defn)@index(make-cycle)@index(cycle pattern)@index(pattern, cycle)@i(items), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-cycle @i(items) :for @i(for) :name @i(name) + :trace @i(trace))} @c{[lisp]}}@\Make a cycle +pattern that iterates over @i(items). The default period length is the +length of @i(items). (See above for a description of the +optional parameters.) If @i(items) is a pattern, a period of the +pattern becomes the list from which items are generated. The +list is replaced every period of the cycle. +@end(fndefs) + +@subsection(line) +The @code(line-class) is similar to the cycle class, but when it reaches the +end of the list of items, it simply repeats the last item in the list. +For example, two periods of @code[make-line({a b c})] would be +@code[(A B C) (C C C)]. + +@begin(fndefs) +@codef{make-line(@pragma(defn)@index(make-line)@index(line pattern)@index(pattern, line)@i(items), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-line @i(items) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Make a line +pattern that iterates over @i(items). The default period length is the +length of @i(items). As with @code(make-cycle), @i(items) may be a +pattern. (See above for a description of the optional parameters.) +@end(fndefs) + +@subsection(random) +The @code(random-class) generates items at random from a list. The default +selection is uniform random with replacement, but items may be further +specified with a weight, a minimum repetition count, and a maximum +repetition count. Weights give the relative probability of the selection +of the item (with a default weight of one). The minimum count specifies how +many times an item, once selected at random, will be repeated. The maximum +count specifies the maximum number of times an item can be selected in a row. +If an item has been generated @i(n) times in succession, and the maximum +is equal to @i(n), then the item is disqualified in the next random selection. +Weights (but not currently minima and maxima) can be patterns. The patterns +(thus the weights) are recomputed every period. + +@begin(fndefs) +@codef{make-random(@pragma(defn)@index(make-random)@index(random pattern)@index(pattern, random)@i(items), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-random @i(items) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Make a random +pattern that selects from @i(items). Any (or all) element(s) of @i(items) +may be lists of the following form: @code{(@i(value) :weight @i(weight) +:min @i(mincount) :max @i(maxcount))}, where @i(value) is the item +(or pattern) to be generated, @i(weight) is the (optional) +relative probability of +selecting this item, @i(mincount) is the (optional) minimum number of repetitions +when this item is selected, and @i(maxcount) is the (optional) maximum number of +repetitions allowed before selecting some other item. The default period +length is the length of @i(items). If @i(items) is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +@end(fndefs) + +@subsection(palindrome) +The @code(palindrome-class) repeatedly traverses a list forwards and then +backwards. For example, two periods of @code[make-palindrome({a b c})] +would be @code[(A B C C B A) (A B C C B A)]. The @code(elide:) +keyword parameter controls whether the first and/or last elements are +repeated: +@begin(example) +make-palindrome({a b c}, elide: nil) + ;; generates A B C C B A A B C C B A ... + +make-palindrome({a b c}, elide: t) + ;; generates A B C B A B C B ... + +make-palindrome({a b c}, elide: :first) + ;; generates A B C C B A B C C B ... + +make-palindrome({a b c}, elide: :last) + ;; generates A B C B A A B C B A ... +@end(example) + +@begin(fndefs) +@codef{make-palindrome(@pragma(defn)@index(make-palindrome)@index(palindrome pattern)@index(pattern, palindrome)@i(items), elide: @i(elide), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-palindrome @i(items) :elide @i(elide) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Generate items +from list alternating in-order and reverse-order sequencing. The keyword +parameter @i(elide) can have the values @code(:first), @code(:last), +@code(t), or @code(nil) to control repetition of the first and last elements. +The @i(elide) parameter can also be a pattern, in which case it is evaluated +every period. One period is one complete forward and backward traversal +of the list. If @i(items) is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +@end(fndefs) + +@subsection(heap) +The @code(heap-class) selects items in random order from a list + without replacement, which means that all items are generated once before +any item is repeated. For example, two periods of @code[make-heap({a b c})] + might be @code[(C A B) (B A C)]. Normally, repetitions can occur +even if all list elements are distinct. This happens when the last element +of a period is chosen first in the next period. To avoid repetitions, the +@code(max:) keyword argument can be set to 1. The @code(max:) keyword only +controls repetitions from the end of one period to the beginning of the next. +If the list contains more than one copy of the same value, it may be repeated +within a period regardless of the value of @code(max:). + +@begin(fndefs) +@codef{make-heap(@pragma(defn)@index(make-heap)@index(heap pattern)@index(pattern, heap)@i(items), for: @i(for), max: @i(max), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-heap @i(items) :for @i(for) :max @i(max) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Generate items +randomly from list without replacement. If @i(max) is 1, the first element of +a new period will not be the same as the last element of the previous period, +avoiding repetition. The default value of @i(max) is 2, meaning repetition is +allowed. The period length is the length +of @i(items). If @i(items) is a pattern, a period +from that pattern becomes the list from which random selections are +made, and a new list is generated every period. +@end(fndefs) + +@subsection(accumulation) +The @code(accumulation-class) takes a list of values and returns +the first, followed by the first two, followed by the first three, +etc. In other words, for each list item, return all items from the +first through the item. For example, if the list is (A B C), each +generated period is (A A B A B C). + +@begin(fndefs) +@codef{make-accumulation(@pragma(defn)@index(make-accumulation)@index(accumulation pattern)@index(pattern, accumulation)@i(items), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-accumulation @i(items) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\For each item, generate items from the first to +the item including the item. The period length is (@i(n)@+(2) + @i(n)) / 2 +where @i(n) is the length of @i(items). If @i(items) is a pattern, a period +from that pattern becomes the list from which items are generated, +and a new list is generated every period. Note that this is similar in +name but different from @code(make-accumulate). + +@subsection(copier) +The @code(copier-class) makes copies of periods from a sub-pattern. +For example, three periods +of @code[make-copier(make-cycle({a b c}, for: 1), repeat: 2, merge: t)] +would be @code[(A A) (B B) (C C)]. Note that entire periods (not +individual items) are repeated, so in this example the @code(for:) +keyword was used to force periods to be of length one so that +each item is repeated by the @code(repeat:) count. + +@codef{make-copier(@pragma(defn)@index(make-copier)@index(copier +pattern)@index(pattern, copier)@i(sub-pattern), repeat: @i(repeat), merge: @i(merge), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-copier @i(sub-pattern) :repeat @i(repeat) :merge @i(merge) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Generate a period +from @i(sub-pattern) and repeat it @i(repeat) times. If @i(merge) is false +(the default), each repetition of a period from @i(sub-pattern) results +in a period by default. If @i(merge) is true (non-null), then all + @i(repeat) repetitions of the period are merged into one result +period by default. If the @code(for:) keyword is used, the same items +are generated, but the items are grouped into periods determined by +the @code(for:) parameter. If the @code(for:) parameter is a pattern, +it is evaluated every result period. The @i(repeat) and @i(merge) values +may be patterns that return a repeat count and a boolean value, respectively. +If so, these patterns are evaluated initially and after each @i(repeat) + copies are made (independent of the @code(for:) keyword parameter, if any). +The @i(repeat) value returned by a pattern can also be negative. A negative +number indicates how many periods of @i(sub-pattern) to skip. After skipping +these patterns, new @i(repeat) and @i(merge) values are generated. +@end(fndefs) + +@subsection(accumulate) +The @code(accumulate-class) forms the sum of numbers returned by another +pattern. For example, each period +of @code[make-accumulate(make-cycle({1 2 -3}))] is @code[(1 3 0)]. +The default output period length is the length of the input period. + +@begin(fndefs) +@codef{make-accumulate(@pragma(defn)@index(make-accumulate)@index(accumulate +pattern)@index(pattern, accumulate)@i(sub-pattern), for: @i(for), max: @i(maximum), min: @i(minimum), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-accumulate @i(sub-pattern) :for @i(for) :max @i(maximum) :min @i(minimum) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Keep +a running sum of numbers generated by @i(sub-pattern). The default +period lengths match the period lengths from @i(sub-pattern). If @i(maximum) (a pattern or a number) is specified, and the running sum exceeds @i(maximum), the running sum is reset to @i(maximum). If @i(minimum) (a pattern or a number) is specified, and the running sum falls below @i(minimum), the running sum is reset to @i(minimum). If @i(minimum) is greater than @i(maximum), the running sum will be set to one of the two values. Note that this is similar in name but not in function to +@code(make-accumulation). +@end(fndefs) + +@subsection(sum) +The @code(sum-class) forms the sum of numbers, one from each of two other +patterns. For example, each period +of @code[make-sum(make-cycle({1 2 3}), make-cycle({4 5 6}))] +is @code[(5 7 9)]. +The default output period length is the length of the input period of the +first argument. Therefore, the first argument must be a pattern, but the +second argument can be a pattern or a number. + +@begin(fndefs) +@codef{make-sum(@pragma(defn)@index(make-sum)@index(sum +pattern)@index(pattern, sum)@i(x), @i(y), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-sum @i(x) @i(y) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Form +sums of items (which must be numbers) from pattern + @i(x) and pattern or number @i(y). The default +period lengths match the period lengths from @i(x). +@end(fndefs) + +@subsection(product) +The @code(product-class) forms the product of numbers, one +from each of two other +patterns. For example, each period +of @code[make-product(make-cycle({1 2 3}), make-cycle({4 5 6}))] +is @code[(4 10 18)]. +The default output period length is the length of the input period of the +first argument. Therefore, the first argument must be a pattern, but the +second argument can be a pattern or a number. + +@begin(fndefs) +@codef{make-product(@pragma(defn)@index(make-product)@index(product pattern)@index(pattern, product)@i(x), @i(y), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-product @i(x) @i(y) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Form +products of items (which must be numbers) from pattern + @i(x) and pattern or number @i(y). The default +period lengths match the period lengths from @i(x). +@end(fndefs) + + +@subsection(eval) +The @code(eval-class) evaluates an expression to produce each output item. +The default output period length is 1. + +@begin(fndefs) +@codef{make-eval(@pragma(defn)@index(make-eval)@index(eval pattern)@index(pattern, eval)@index(expression pattern)@index(pattern, expression)@i(expr), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-eval @i(expr) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Evaluate +@i(expr) to generate each item. If @i(expr) is a pattern, each item is generated by getting the next item from @i(expr) and evaluating it. +@end(fndefs) + + +@subsection(length) +The @code(length-class) generates periods of a specified length from +another pattern. This is similar to using the @code(for:) keyword, but +for many patterns, the @code(for:) parameter alters the points at which +other patterns are generated. For example, if the palindrome pattern +has an @code(elide:) pattern parameter, the value will be computed every +period. If there is also a @code(for:) parameter with a value of 2, then +@code(elide:) will be recomputed every 2 items. In contrast, if the +palindrome (without a @code(for:) parameter) is embedded in a @i(length) +pattern with a lenght of 2, then the periods will all be of length 2, but +the items will come from default periods of the palindrome, and therefore +the @code(elide:) values will be recomputed at the beginnings of +default palindrome periods. + +@begin(fndefs) +@codef{make-length(@index(length pattern)@index(pattern, +length)@pragma(defn)@index(make-length)@i(pattern), @i(length-pattern), +name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-length @i(pattern) @i(length-pattern) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Make a pattern of class +@code(length-class) that regroups items generated by a +@i(pattern) according to pattern lengths given by @i(length-pattern). +Note that @i(length-pattern) is not optional: There is no default +pattern length and no @code(for:) keyword. +@end(fndefs) + +@subsection(window) +The @code(window-class) groups items from another pattern by using a sliding +window. If the @i(skip) value is 1, each output period is formed +by dropping the first item of the previous perioda and appending the next item +from the pattern. The @i(skip) value and the output period length can change +every period. For a simple example, if the period length is 3 and the +skip value is 1, and the input pattern generates the sequence A, B, C, ..., +then the output periods will be (A B C), (B C D), (C D E), (D E F), .... + +@begin(fndefs) +@codef{make-window(@index(window pattern)@index(pattern, +window)@pragma(defn)@index(make-window)@i(pattern), @i(length-pattern), +@i(skip-pattern), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-window @i(pattern) @i(length-pattern) @i(skip-pattern) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Make + a pattern of class +@code(window-class) that regroups items generated by a +@i(pattern) according to pattern lengths given by @i(length-pattern) +and where the period advances by the number of items given by +@i(skip-pattern). +Note that @i(length-pattern) is not optional: There is no default +pattern length and no @code(for:) keyword. +@end(fndefs) + + +@subsection(markov) +The @code(markov-class) generates items from a Markov model. A Markov model +generates a sequence of @i(states) according to rules which specify possible +future states +given the most recent states in the past. For example, states might be +pitches, and each pitch might lead to a choice of pitches for the next state. +In the @code(markov-class), states can be either symbols or numbers, but +not arbitrary values or patterns. This makes it easier to specify rules. +However, symbols can be mapped to arbitrary values including pattern +objects, and these become the actual generated items. +By default, all future states are weighted equally, but weights +may be associated with future states. A Markov model must be +initialized with +a sequence of past states using the @code(past:) keyword. +The most common form of Markov model is a "first +order Markov model" in which the future item depends only upon one +past item. However, higher order models where the future items depend on +two or more past items are possible. A "zero-order" Markov model, which +depends on no past states, is essentially equivalent to the random pattern. +As an example of a first-order Markov pattern, +two periods of @code[make-markov({{a -> b c} {b -> c} {c -> a}}, past: {a})] +might be @code[(C A C) (A B C)]. + +@begin(fndefs) +@codef{make-markov(@pragma(defn)@index(make-markov)@index(markov pattern)@index(pattern, markov)@i(rules), past: @i(past), produces: @i(produces), for: @i(for), name: @i(name), trace: @i(trace))} @c{[sal]}@* +@altdef{@code{(make-markov @i(rules) @i(past) :produces @i(produces) :for @i(for) :name @i(name) :trace @i(trace))} @c{[lisp]}}@\Generate a sequence +of items from a Markov process. The @i(rules) parameter has the form: +@code[(@i(prev1) @i(prev2) ... @i(prevn) -> @i(next1) @i(next2) ... @i(nextn))] +where @i(prev1) through @i(prevn) represent a sequence of most recent +(past) states. The symbol @code(*) is treated specially: it matches any +previous state. If @i(prev1) through @i(prevn) (which may be just one state +as in the example above) match the previously generated states, this +rule applies. Note that every rule must specify the same number of previous +states; this number is known as the order of the Markov model. +The first rule in @i(rules) that applies is used to select the +next state. If no rule applies, the next state is @code(NIL) (which is +a valid state that can be used in rules). +Assuming a rule applies, the list of possible next +states is specified by @i(next1) +through @i(nextn). Notice that these are alternative choices for the +next state, not a sequence of future states, and each rule can have +any number of choices. Each choice may be the state +itself (a symbol or a number), or the choice may be a list consisting of +the state and a weight. The weight may be given by a pattern, in which +case the next item of the pattern is obtained every time the rule is +applied. For example, this rules says that if the previous states were +A and B, the next state can be A with a weight of 0.5 or C with an +implied weight of 1: @code[(A B -> (A 0.5) C)]. The +default length of the period is the length of @i(rules). The +@i(past) parameter must be provided. It is a list of states whose length +matches the order of the Markov model. The keyword parameter @i(produces) +may be used to map from state symbols or numbers to other values or +patterns. The parameter is a list of alternating symbols and values. For +example, to map A to 69 and B to 71, use @code[list(quote(a), 69, quote(b), 71)]. + You can +also map symbols to patterns, for example +@code[list(quote(a), make-cycle({57 69}), quote(b), make-random({59 71}))]. The +next item of the pattern is is generated each time the Markov model generates +the corresponding state. Finally, the @i(produces) keyword can be +@code(eval:), which means to evaluate the Markov model state. This could +be useful if states are Nyquist global variables such as +@code(C4, CS4, D4, ]..., which evaluate to numerical +values (60, 61, 62, ...). + +@codef{markov-create-rules(@pragma(defn)@index(markov-create-rules)@index(markov analysis)@i(sequence), @i(order) [, @i(generalize)])} @c{[sal]}@* +@altdef{@code{(markov-create-rules @i(sequence) @i(order) [@i(generalize)])} @c{[lisp]}}@\Generate a set of rules suitable for the +@code(make-markov) function. The @i(sequence) is a ``typical'' sequence +of states, and @i(order) is the order of the Markov model. It is often the +case that a sample sequence will not have a transition from the last state +to any other state, so the generated Markov model can reach a ``dead end'' +where no rule applies. This might lead to an infinite stream of NIL's. To +avoid this, the optional parameter @i(generalize) can be set to @code(t) +(true), indicating that there should be a fallback rule that matches any +previous states and whose future states are weighted according to their +frequency in @i(sequence). For example, if sequence contains 5 A's, 5 B's and +10 G's, the default rule will be @code[(* -> (A 5) (B 5) (G 10))]. This +rule will be appended to the end so it will only apply if no other rule does. +@end(fndefs) + +@section(Random Number Generators) +@index(random)@index(probability distributions)@index(distributions, probability)@index(stochastic functions) +The @code(distributions.lsp) library implements random number generators that return random values with various probability distributions. Without this library, you can generate random numbers with @i(uniform) distributions. In a uniform distribution, all values are equally likely. To generate a random integer in some range, use @code(random). To generate a real number (FLONUM) in some range, use @code(real-random) (or @code(rrandom) if the range is 0-1). But there are other interesting distributions. For example, the Gaussian distribution is often used to model +real-world errors and fluctuations where values are clustered around some central value and large deviations are more unlikely than small ones. See Dennis Lorrain, "A Panoply of Stochastic 'Canons'," @i(Computer Music Journal) vol. 4, no. 1, 1980, pp. 53-81. + +In most of the random number generators described below, there are optional parameters to indicate a maximum and/or minimum value. These can be used to truncate the distribution. For example, if you basically want a Gaussian distribution, but you never want a value greater than 5, you can specify 5 as the maximum value. +The upper and lower bounds are implemented simply by drawing a random number from the full distribution repeatedly until a number falling into the desired range is obtained. Therefore, if you select an acceptable range that is unlikely, it may take Nyquist a long time to find each acceptable random number. The intended use of the upper and lower bounds is to weed out values that are already fairly unlikely. + + +@begin(fndefs) +@codef[linear-dist(@pragma(defn)@index(linear-dist)@index(linear distribution)@i(g))] @c{[sal]}@* +@altdef{@code[(linear-dist @i(g))] @c{[lisp]}}@\Return a @code(FLONUM) value from a linear distribution, where the probability of a value decreases linearly from zero to @i(g) which must be greater than zero. (See Figure @ref(linear-fig).) The linear distribution is useful for generating for generating time and pitch intervals. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "linear-fig.ps")) +@html(

) +@fillcaption(The Linear Distribution, @i(g) = 1.) +@tag(linear-fig) +@end(figure) + +@begin(fndefs) +@codef{exponential-dist(@pragma(defn)@index(exponential-dist)@index(exponential distribution)@i(delta) [, @i(high)])} @c{[sal]}@* +@altdef{@code{(exponential-dist @i(delta) [@i(high)])} @c{[lisp]}}@\Return a @code(FLONUM) value from an exponential distribution. The initial downward slope is steeper with larger values of @i(delta), which must be greater than zero. (See Figure @ref(exponential-fig). The optional @i(high) parameter puts an artificial upper bound on the return value. +The exponential distribution generates values greater +than 0, and can be used to generate time intervals. Natural random intervals such as the time intervals between the release of atomic particles or the passing of yellow volkswagons in traffic have exponential distributions. The +exponential distribution is memory-less: knowing that a random number from this distribution is greater than some value (e.g. a note duration is at least 1 second) tells you nothing new about how soon the note will end. This +is a continuous distribution, but @code(geometric-dist) (described below) implements the discrete form. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "exponential-fig.ps")) +@html(

) +@fillcaption(The Exponential Distribution, @i(delta) = 1.) +@tag(exponential-fig) +@end(figure) + +@begin(fndefs) +@codef{gamma-dist(@pragma(defn)@index(gamma-dist)@i(nu) [, @i(high)])} @c{[sal]}@* +@altdef{@code{(gamma-dist @i(nu) [@i(high)])} @c{[lisp]}}@\Return a @code(FLONUM) value from a Gamma distribution. The value is greater than zero, has a mean of @i(nu) (a @code(FIXNUM) greater than zero), and a mode (peak) of around @i(nu) - 1. + The optional @i(high) parameter puts an artificial upper bound on the return value. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "gamma-fig.ps")) +@html(

) +@fillcaption(The Gamma Distribution, @i(nu) = 4.) +@tag(gamma-fig) +@end(figure) + +@begin(fndefs) +@codef{bilateral-exponential-dist(@pragma(defn)@index(bilateral-exponential-dist)@index(bilateral exponential distribution)@i(xmu), + @i(tau) [, @i(low), @i(high)])} @c{[sal]}@* +@altdef{@code{(bilateral-exponential-dist @i(xmu) @i(tau) [@i(low) @i(high)])} @c{[lisp]}}@\Returns a @code(FLONUM) value from a bilateral exponential distribution, where @i(xmu) is the center of the double exponential and @i(tau) controls the spread of the distribution. A larger @i(tau) gives a wider distribution (greater variance), and @i(tau) must be greater than zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +This distribution is similar to the exponential, except +it is centered at 0 and can output negative values as well. Like +the exponential, it can be used to generate time intervals; however, it might be necessary to add a lower bound so as not to compute a negative time interval. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "bilateral-fig.ps")) +@html(

) +@fillcaption(The Bilateral Exponential Distribution.) +@tag(bilateral-fig) +@end(figure) + +@begin(fndefs) +@codef{cauchy-dist(@pragma(defn)@index(cauchy-dist)@index(cauchy distribution)@i(tau) [, @i(low), @i(high)])} @c{[sal]}@* +@altdef{@code{(cauchy-dist @i(tau) [@i(low) @i(high)])} @c{[lisp]}}@\Returns a @code(FLONUM) from the Cauchy distribution, a symetric distribution with a high peak at zero and a width (variance) that increases with parameter @i(tau), which must be greater than zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "cauchy-fig.ps")) +@html(

) +@fillcaption(The Cauchy Distribution, @i(tau) = 1.) +@tag(cauchy-fig) +@end(figure) + +@begin(fndefs) +@codef{hyperbolic-cosine-dist(@pragma(defn)@index(hyperbolic-cosine-dist)[@i(low), @i(high)])} @c{[sal]}@* +@altdef{@code[(hyperbolic-cosine-dist [@i(low) @i(high)])] @c{[lisp]}}@\Returns a @code(FLONUM) value from the hyperbolic cosine distribution, a symetric distribution with its peak at zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "hyperbolic-fig.ps")) +@html(

) +@fillcaption(The Hyperbolic Cosine Distribution.) +@tag(hyperbolic-fig) +@end(figure) + +@begin(fndefs) +@codef{logistic-dist(@pragma(defn)@index(logistic-dist)@index(logistic distribution)@i(alpha), @i(beta) [, @i(low), @i(high)])} @c{[sal]}@* +@altdef{@code{(logistic-dist @i(alpha) @i(beta) [@i(low) @i(high)])} @c{[lisp]}}@\Returns a @code(FLONUM) value from the logistic distribution, which is symetric about the mean. The @i(alpha) parameter primarily affects dispersion (variance), with larger values resulting in values closer to the mean (less variance), and the @i(beta) parameter primarily influences the mean. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "logistic-fig.ps")) +@html(

) +@fillcaption(The Logistic Distribution, alpha = 1, beta = 2.) +@tag(logistic-fig) +@end(figure) + +@begin(fndefs) +@codef{arc-sine-dist(@pragma(defn)@index(arc-sine-dist)@index(arcsine distribution))} @c{[sal]}@* +@altdef{@code{(arc-sine-dist)} @c{[lisp]}}@\Returns a @code(FLONUM) value from the arc sine distribution, which outputs values between 0 and 1. It is symetric about the mean of 1/2, but is more likely to generate values closer to 0 and 1. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "arcsine-fig.ps")) +@html(

) +@fillcaption(The Arc Sine Distribution.) +@tag(arcsine-fig) +@end(figure) + +@begin(fndefs) +@codef{gaussian-dist(@index(Gaussian distribution)@pragma(defn)@index(gaussian-dist)@i(xmu), @i(sigma) [, @i(low), @i(high)])} @c{[sal]}@* +@altdef{@code{(gaussian-dist @i(xmu) @i(sigma) [@i(low) @i(high)])} @c{[lisp]}}@\Returns a @code(FLONUM) value from the Gaussian or Gauss-Laplace distribution, a linear function of the normal distribution. It is symetric about the mean of @i(xmu), with a standard deviation of @i(sigma), which must be greater than zero. The @i(low) and @i(high) parameters give optional artificial bounds on the minimum and maximum output values, respectively. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "gaussian-fig.ps")) +@html(

) +@fillcaption{The Gauss-Laplace (Gaussian) Distribution, @i(xmu) = 0, @i(sigma) = 1.} +@tag(gaussian-fig) +@end(figure) + +@begin(fndefs) +@codef{beta-dist(@index(beta distribution)@pragma(defn)@index(beta-dist)@i(a), @i(b))} @c{[sal]}@* +@altdef{@code[(beta-dist @i(a) @i(b))] @c{[lisp]}}@\Returns a @code(FLONUM) value from the Beta distribution. This distribution outputs values between 0 and 1, with outputs more likely to be close to 0 or 1. The parameter @i(a) controls the height (probability) of the right side of the distribution (at 1) and @i(b) controls the height of the left side (at 0). The distribution is symetric about 1/2 when @i(a) = @i(b). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 2.5 in, width = 3.75 in, magnify = 1, + postscript = "beta-fig.ps")) +@html(

) +@fillcaption(The Beta Distribution, @i(alpha) = .5, @i(beta) = .25.) +@tag(beta-fig) +@end(figure) + +@begin(fndefs) +@codef{bernoulli-dist(@index(Bernoulli distribution)@pragma(defn)@index(bernoulli-dist)@i(px1) [, @i(x1), @i(x2)])} @c{[sal]}@* +@altdef{@code{(bernoulli-dist @i(px1) [@i(x1) @i(x2)])} @c{[lisp]}}@\Returns either @i(x1) (default value is 1) with probability @i(px1) or @i(x2) (default value is 0) with probability 1 - @i(px1). The value of @i(px1) should be between 0 and 1. By +convention, a result of @i(x1) is viewed as a success while @i(x2) is viewed as +a failure. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "bernoulli-fig.ps")) +@html(

) +@fillcaption(The Bernoulli Distribution, @i(px1) = .75.) +@tag(bernoulli-fig) +@end(figure) + +@begin(fndefs) +@codef{binomial-dist(@index(binomial distribution)@pragma(defn)@index(binomial-dist)@i(n), @i(p))} @c{[sal]}@* +@altdef{@code{(binomial-dist @i(n) @i(p))} @c{[lisp]}}@\Returns a @code(FIXNUM) value from the binomial distribution, where @i(n) is the number of Bernoulli trials run (a @code(FIXNUM)) and @i(p) is the probability of success in the Bernoulli trial (a @code(FLONUM) from 0 to 1). The mean is the product of @i(n) and @i(p). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "binomial-fig.ps")) +@html(

) +@fillcaption(The Binomial Distribution, @i(n) = 5, @i(p) = .5.) +@tag(binomial-fig) +@end(figure) + +@begin(fndefs) +@codef{geometric-dist(@index(geometric distribution)@pragma(defn)@index(geometric-dist)@i(p))} @c{[sal]}@* +@altdef{@code[(geometric-dist @i(p))] @c{[lisp]}}@\Returns a @code(FIXNUM) value from the geometric distribution, which is defined as the number of failures before a success is achieved in a Bernoulli trial with probability of success @i(p) (a @code(FLONUM) from 0 to 1). +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "geometric-fig.ps")) +@html(

) +@fillcaption(The Geometric Distribution, @i(p) = .4.) +@tag(geometric-fig) +@end(figure) + +@begin(fndefs) +@codef{poisson-dist(@index(Poisson distribution)@pragma(defn)@index(poisson-dist)@i(delta))} @c{[sal]}@* +@altdef{@code[(poisson-dist @i(delta))] @c{[lisp]}}@\Returns a @code(FIXNUM) value from the Poisson distribution with a mean of @i(delta) (a @code(FIXNUM)). The Poisson distribution is often used to generate a sequence of time intervals, resulting in random but often pleasing rhythms. +@end(fndefs) + +@begin(figure) +@center(@graphic((height = 3.5 in, width = 3.75 in, magnify = 0.75, + postscript = "poisson-fig.ps")) +@html(

) +@fillcaption(The Poisson Distribution, @i(delta) = 3.) +@tag(poisson-fig) +@end(figure) + +@begin(comment) +***************** +Note: this should remain out of Nyquist until the granulate code is cleaned up (why are there separate functions for pitch-dist and len-dist instead of a single function where any parameter can be specified by a closure?) +***************** +@begin(fndefs) +@codef{pitch-dist-granulate(@pragma(defn)@index(pitch-dist-granulate)@index(granular synthesis)@i(filename), @i(grain-dur), @i(grain-dev), @i(ioi), @i(ioi-dev), @i(pitch-dist) [, @i(file-start), @i(file-end)])} @c{[sal]}@* +@altdef{@code{(pitch-dist-granulate @i(filename) @i(grain-dur) @i(grain-dev) @i(ioi) @i(ioi-dev) @i(pitch-dist) [@i(file-start) @i(file-end)])} @c{[lisp]}}@\*** need to write this *** + +@i(filename) @dash name of the file + +@i(dist) @dash the distribution that determines the length of the grains + +@i(ioi) @dash the basic inter-onset-interval for grains + +@i(ioi-dev) @dash ioi is actually: ioi + random(0, ioi-dev) + +@i(pitch-dev) @dash grains are resampled at rate between 1 and pitch-dev + +@i(file-start) @dash when to start reading the file (an offset from start). The +default is 0. + +@i(file-end) @dash when to stop reading the file (an offset from end) the +default is 0 + +returns @dash a set of sound grains created from the input file + +This is a granular +synthesis function based on the one by Roger B. Dannenberg. The +pitch of the grains will be based on the distribution you give to it. The +distribution must be passed in as a continuation. + +(len-dist-granulate @i(filename) @i(dist ioi ioi-dev) @i(pitch-dev) [@i(file-start)@i(file-end)]) + +@i(filename) @dash name of the file + +@i(grain-dur) @dash the duration of a grain + +@i(grain-dev) @dash grain dur is actually grain-dur + random(0, grain-dev) + +@i(ioi) @dash the basic inter-onset-interval for grains + +@i(ioi-dev) @dash ioi is actually: ioi + random(0, ioi-dev) + +@i(pitch-dist) @dash the distribution of the alteration in pitch to the grains. The +distribution values should be > 1. + +@i(file-start) @dash when to start reading the file (an offset from start). The +default is 0 + +@i(file-end) @dash when to stop reading the file (an offset from end). The +default is 0 + +returns @dash a set of sound grains created from the input file + +This is a granular +synthesis function based on the one by Roger B. Dannenberg. The +length of the grains will be based on the distribution you give to it. The +distribution must be passed in as a continuation. +@end(fndefs) +@end(comment) + +@section(Score Generation and Manipulation) + +A common application of pattern generators is to specify parameters +for notes. (It should be understood that ``notes'' in this context +means any Nyquist behavior, whether it represents a conventional note, +an abstract sound object, or even some micro-sound event that is just +a low-level component of a hierarchical sound organization. Similarly, +``score'' should be taken to mean a specification for a +sequence of these ``notes.'') +The @code(score-gen) macro (defined by +loading @code(xm.lsp)) establishes a convention for representing +scores and for generating them using patterns. + +The @code(timed-seq) macro, described in Section @ref(timed-seq-sec), +already provides a way to represent a ``score'' as a list of expressions. +The Xmusic representation goes a bit further by specifying that +@i(all notes are specified by an alternation of keywords and values, where +some keywords have specific meanings and interpretations.) + +The basic idea of @code(score-gen)@index(score-gen) is you provide a template for notes in +a score as a set of keywords and values. For example, +@begin(example) +set pitch-pattern = make-cycle(list(c4, d4, e4, f4)) +score-gen(dur: 0.4, name: quote(my-sound), + pitch: next(pitch-pattern), score-len: 9) +@end(example) +generates a score of 9 notes as follows: +@begin(example) +((0 0 (SCORE-BEGIN-END 0 3.6)) + (0 0.4 (MY-SOUND :PITCH 60)) + (0.4 0.4 (MY-SOUND :PITCH 62)) + (0.8 0.4 (MY-SOUND :PITCH 64)) + (1.2 0.4 (MY-SOUND :PITCH 65)) + (1.6 0.4 (MY-SOUND :PITCH 60)) + (2 0.4 (MY-SOUND :PITCH 62)) + (2.4 0.4 (MY-SOUND :PITCH 64)) + (2.8 0.4 (MY-SOUND :PITCH 65)) + (3.2 0.4 (MY-SOUND :PITCH 60))) +@end(example) +The use of keywords like @code(:PITCH) helps to make scores +readable and easy to process without specific knowledge of +about the functions called in the score. For example, one +could write a transpose operation to transform all the +@code(:pitch) parameters in a score without having to know +that pitch is the first parameter of @code(pluck) and the +second parameter of @code(piano-note). Keyword parameters are +also used to give flexibility to note specification with +@code(score-gen). Since this approach requires the use of +keywords, the next section +is a brief explanation of how to define functions that use +keyword parameters. + +@subsection(Keyword Parameters) +@index(keyword parameters) +@index(parameters, keyword) +Keyword parameters are parameters whose presence is +indicated by a special symbol, called a keyword, followed +by the actual parameter. Keyword parameters in SAL have +default values that are used if no actual parameter is +provided by the caller of the function. (See Appendix + @ref(xlisp-app) to learn about keywords in XLISP.) + +To specify that a parameter is a keyword parameter, +use a keyword symbol (one that ends in a colon) followed +by a default value. + For example, here is a function that +accepts keyword parameters and invokes the @code(pluck) +function: +@begin(example) +define function k-pluck(pitch: 60, dur: 1) + return pluck(pitch, dur) +@end(example) +Now, we can call k-pluck with keyword parameters. The +keywords are simply the formal parameter names with +a prepended colon character (@code(:pitch) and @code(:dur) +in this example), so a function call would look like: +@begin(example) +pluck(pitch: c3, dur: 3) +@end(example) +Usually, it is best to give keyword parameters useful +default values. That way, if a parameter such as @code(dur:) +is missing, a reasonable default value (1) can be used +automatically. +It is never an error to omit a keyword parameter, but the +called function can check to see if a keyword parameter +was supplied or not. +Because of default values, we can call +@code[k-pluck(pitch: c3)] with no duration, +@code[k-pluck(dur: 3)] with only a duration, +or even @code[k-pluck()] with no parameters. + +In XLISP, there is additional syntax to specify an alternate symbol +to be used as the keyword and to allow the called function +to determine whether or not a keyword parameter was +supplied, but these features are little-used. See the XLISP +manual for details. + +@subsection(Using score-gen)@pragma(defn)@index(score-gen) +The @code(score-gen) macro computes a score based on keyword parameters. +Some keywords have a special meaning, while others are not interpreted +but merely placed in the score. The resulting score can be synthesized +using @code(timed-seq) (see Section @ref(timed-seq-sec)). + +The form of a call to @code(score-gen) is simply: +@begin(fndefs) +@codef[score-gen(@pragma(defn)@index(score-gen)@i(k1:) @i(e1), @i(k2:) @i(e2), @r(...))] @c{[sal]}@* +@altdef{@code[(score-gen @i(:k1) @i(e1) @i(:k2) @i(e2) @r(...))] @c{[lisp]}}@\where the @i(k)'s +are keywords and the @i(e)'s are +expressions. A score is generated by evaluating the expressions once for +each note and constructing a list of keyword-value pairs. A number +of keywords have special interpretations. The rules for interpreting +these parameters will be explained through a set of "How do I ..." +questions below. +@end(fndefs) + +@i(How many notes will be generated?) The keyword +parameter @code(score-len:) specifies an upper bound on the number +of notes. (Note: in LISP syntax, keywords +are always @i(preceded) by colons, so you would write +@code(:score-len) instead.) The keyword @code(score-dur:) specifies an upper bound +on the starting time of the last note in the score. (To be more +precise, the @code(score-dur:) bound is reached when the +default starting time of the next note is greater than or equal +to the @code(score-dur:) value. This definition is necessary because +note times are not strictly increasing.) When either bound +is reached, score generation ends. At least one of these two +parameters must be specified or an error is raised. These keyword +parameters are evaluated just once and are not copied into the +parameter lists of generated notes. + +@i(What is the duration of generated notes?) The +keyword @code(dur:) defaults to 1 and specifies the nominal duration +in seconds. Since the generated note list is compatible with +@code(timed-seq), the starting time and duration (to be precise, the +@i(stretch factor)) are not passed as parameters to the notes. Instead, +they control the Nyquist environment in which the note will be evaluated. + +@i(What is the start time of a note?) The default start time of the +first note is zero. Given a note, the default start time of the next note is +the start time plus the inter-onset time, which is given by the @code(ioi:) +parameter. If no @code(ioi:) parameter is specified, the inter-onset time +defaults to the duration, given by @code(dur:). In all cases, the default +start time of a note can be overridden by the keyword parameter @code(time:). + +@i(When does the score begin and end?) The behavior @code[SCORE-BEGIN-END] +contains the beginning and ending of the +score (these are used for score manipulations, e.g. when scores are merged, +their begin times can be aligned.) When @code(timed-seq) is used to +synthesize a score, the @code(SCORE-BEGIN-END) marker is +not evaluated. The @code(score-gen) macro inserts a ``note'' of the form +@code[(0 0 (SCORE-BEGIN-END @i(begin-time) @i(end-time)))] +at the time given by the @code(begin:) keyword, with @i(begin-time) and +@i(end-time) determined by the @code(begin:) and @code(end:) +keyword parameters, respectively. If the @i(begin:) keyword is not +provided, the score begins at zero. If the @code(end:) keyword +is not provided, the score ends at the default start time +of what would be the next note after the last note in the score +(as described in the previous paragraph). Note: if @code(time:) is used to +compute note starting times, and these times are not increasing, it is +strongly advised to use @code(end:) to specify an end time for the score, +because the default end time may be anywhere in the middle of the +generated sequence. + +@i(What function is called to synthesize the note?) The @code(name:) +parameter names the function. Like other parameters, the value can be any +expression, including something like @code[next(fn-name-pattern)], +allowing function names to be recomputed for each note. The default value +is @code(note). + +@i(Can I make parameters depend upon the starting time or the duration +of the note?) Parameter expressions can use the variable @code(sg:time) +to access the start time of the note, @code(sg:ioi) to access the +inter-onset time, and @code(sg:dur) to access the +duration (stretch factor) of the note. Also, @code(sg:count) counts how +many notes have been computed so far, starting at 0. The order of +computation is: @code(sg:time) first, then @code(sg:ioi) and @code(sg:dur), +so for example, an expression to compute @code(sg:dur) can +depend on @code(sg:ioi). + +@i(Can parameters depend on each other?) The keyword @code(pre:) +introduces an expression that is evaluated before each note, and +@code(post:) provides an expression to be evaluated after each note. +The @code(pre:) expression can assign one or more global variables +which are then used in one or more expressions for parameters. + +@i(How do I debug @code(score-gen) expressions?) You can set the +@code(trace:) parameter to true (@code(t)) to enable a print statement +for each generated note. + +@i(How can I save scores generated by @code(score-gen) that I like?) If the +keyword parameter @code(save:) is set to a symbol, the global variable +named by the symbol is set to the value of the generated sequence. Of +course, the value returned by @code(score-gen) is just an ordinary list that +can be saved like any other value. + +In summary, the following keywords have special interpretations +in @code(score-gen): +@code(begin:), @code(end:), @code(time:), @code(dur:), @code(name:), +@code(ioi:), @code(trace:), +@code(save:), @code(score-len:), @code(score-dur:), @code(pre:), @code(post:). + All other keyword +parameters are expressions that are evaluated once for each note +and become the parameters of the notes. + +@subsection(Score Manipulation) +@index(score manipulation)@index(manipulation of scores) +Nyquist encourages the representation of music as +executable programs, or @i(behaviors), and there are various +ways to modify behaviors, including time stretching, +transposition, etc. An alternative to composing executable +programs is to manipulate scores as editable data. Each +approach has its strengths and weaknesses. This section +describes functions intended to manipulate Xmusic scores +as generated by, or at least in the form generated by, +@code(score-gen). Recall that this means scores are lists +of events (e.g. notes), where events are three-element lists of the form +(@i(time) @i(duration) @i(expression), and where @i(expression) +is a standard lisp function call where all parameters are +keyword parameters. In addition, the first ``note'' may be +the special @code(SCORE-BEGIN-END) expression. If this is +missing, the score begins at zero and ends at the end of the +last note. + +For convenience, a set of functions is offered to access properties +of events (or notes) in scores. Although lisp functions such as +@code(car), @code(cadr), and @code(caddr) can be used, code is more +readable when more mnemonic functions are used to access events. + +@begin(fndefs) +@codef[event-time(@pragma(defn)@index(event-time)@i(event))] @c{[sal]}@* +@altdef{@code[(event-time @i(event))] @c{[lisp]}}@\Retrieve the time field from +an event. + +@codef[event-set-time(@pragma(defn)@index(event-set-time)@i(event), @i(time))] @c{[sal]}@* +@altdef{@code[(event-set-time @i(event) @i(time))] @c{[lisp]}}@\Construct +a new event where the time of @i(event) is replaced by @i(time). + +@codef[event-dur(@pragma(defn)@index(event-dur)@i(event))] @c{[sal]}@* +@altdef{@code[(event-dur @i(event))] @c{[lisp]}}@\Retrieve the duration +(i.e. the stretch factor) field from an event. + +@codef[event-set-dur(@pragma(defn)@index(event-set-dur)@i(event), @i(dur))] @c{[sal]}@* +@altdef{@code[(event-set-dur @i(event) @i(dur))] @c{[lisp]}}@\Construct +a new event where the duration (or stretch factor) of @i(event) is +replaced by @i(dur). + +@codef[event-expression(@pragma(defn)@index(event-expression)@i(event))] @c{[sal]}@* +@altdef{@code[(event-expression @i(event))] @c{[lisp]}}@\Retrieve the expression +field from an event. + +@codef[event-set-expression(@pragma(defn)@index(event-set-expression)@i(event), +@i(dur))] @c{[sal]}@* +@altdef{@code[(event-set-expression @i(event) @i(dur))] @c{[lisp]}}@\Construct +a new event where the expression of @i(event) is replaced by @i(expression). + +@codef[event-end(@pragma(defn)@index(event-end)@i(event))] @c{[sal]}@* +@altdef{@code[(event-end @i(event))] @c{[lisp]}}@\Retrieve the end time +of @i(event), its time plus its duration. + +@codef[expr-has-attr(@pragma(defn)@index(expr-has-attr)@i(expression), @i(attribute))] @c{[sal]}@* +@altdef{@code[(expr-has-attr @i(expression) @i(attribute))] @c{[lisp]}}@\Test +whether a score event @i(expression) has the given @i(attribute). + +@codef{expr-get-attr(@pragma(defn)@index(expr-get-attr)@i(expression), @i(attribute) [, @i(default)])} @c{[sal]}@* +@altdef{@code{(expr-get-attr @i(expression) @i(attribute) [@i(default)])} @c{[lisp]}}@\Get the value of the given @i(attribute) from a score event +@i(expression). If @i(attribute) is not present, return @i(default) if +specified, and otherwise @code(nil). + +@codef{expr-set-attr(@pragma(defn)@index(expr-set-attr)@i(expr), @i(attribute), @i(value))} @c{[sal]}@* +@altdef{@code[(expr-set-attr @i(expr) @i(attribute) @i(value))] @c{[lisp]}}@\Construct a new expression identical to @i(expr) except that the @i(attribute) has @i(value). + +@codef[event-has-attr(@pragma(defn)@index(event-has-attr)@i(event), @i(attribute))] @c{[sal]}@* +@altdef{@code[(event-has-attr @i(event) @i(attribute))] @c{[lisp]}}@\Test +whether a given score @i(event)'s expression has the given @i(attribute). + +@codef{event-get-attr(@pragma(defn)@index(event-get-attr)@i(event), @i(attribute), +[@i(default)])} @c{[sal]}@* +@altdef{@code{(event-get-attr @i(event) @i(attribute) [@i(default)])} @c{[lisp]}}@\Get the value of the given @i(attribute) from a score +@i(event)'s expression. If @i(attribute) is not present, return @i(default) if +specified, and otherwise @code(nil). + +@codef{event-set-attr(@pragma(defn)@index(event-set-attr)@i(event), @i(attribute), @i(value))} @c{[sal]}@* +@altdef{@code[(event-set-attr @i(event) @i(attribute) @i(value))] @c{[lisp]}}@\Construct a new event identical to @i(event) except that the @i(attribute) has @i(value). + +@end(fndefs) + +Functions are provided to shift the starting times of notes, +stretch times and durations, stretch only durations, +add an offset to a keyword parameter, scale a keyword parameter, and +other manipulations. Functions are also provided to extract +ranges of notes, notes that match criteria, and to combine scores. +Most of these functions (listed below in detail) +share a set of keyword parameters that optionally limit the range over which +the transformation operates. The @code(from-index:) and @code(to-index:) +parameters specify the index of the first note and the index of the +last note to be changed. If these numbers are negative, they are offsets +from the end of the score, e.g. -1 denotes the last note of the score. The +@code(from-time:) and @code(to-time:) indicate a range of starting times +of notes that will be affected by the manipulation. Only notes whose time +is greater than or equal to the @i(from-time) and @i(strictly less than) + the @i(to-time) are modified. If both index and time ranges are specified, +only notes that satisfy @i(both) constraints are selected. (Note: in +LISP syntax, colons @i(precede) the keyword, so use +@code(:from-index), @code(:to-index), @code(:from-time), and @code(:to-time).) + +@begin(fndefs) +@codef[score-sorted(@pragma(defn)@index(score-sorted)@i(score))] @c{[sal]}@* +@altdef{@code[(score-sorted @i(score))] @c{[lisp]}}@\Test if @i(score) is sorted. + +@codef{score-sort(@pragma(defn)@index(score-sort)@i(score) [, @i(copy-flag)])} @c{[sal]}@* +@altdef{@code{(score-sort @i(score) [@i(copy-flag)])} @c{[lisp]}}@\Sort + the notes in a +score into start-time order. If copy-flag is nil, this is a destructive +operation which should only be performed if the top-level score list +is a fresh copy that is not shared by any other variables. (The +@i(copy-flag) is intended for internal system use only.) + For the following operations, it is assumed +that scores are sorted, and all operations return a sorted score. + +@codef{score-shift(@pragma(defn)@index(score-shift)@i(score), @i(offset), from-index: @i(i), to-index: @i(j), from-time: @i(x), + to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-shift @i(score) @i(offset) + :from-index @i(i) :to-index @i(j) :from-time @i(x) + :to-time @i(y))} @c{[lisp]}}@\Add a constant +@i(offset) to the starting time of a set of notes in @i(score). By default, +all notes are modified, but the range of notes can be limited with the +keyword parameters. The begin time of the score is not changed, but the +end time is increased by @i(offset). +The original score is not modified, and a new score is returned. + +@codef{score-stretch(@pragma(defn)@index(score-stretch)@i(score), @i(factor), dur: @i(dur-flag), time: @i(time-flag), from-index: @i(i), + to-index: @i(j), from-time: @i(x), to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-stretch @i(score) @i(factor) + :dur @i(dur-flag) :time @i(time-flag) :from-index @i(i) + :to-index @i(j) :from-time @i(x) :to-time @i(y))} @c{[lisp]}}@\Stretch +note times and durations by @i(factor). The default @i(dur-flag) is +non-null, but if @i(dur-flag) is null, the original durations are retained +and only times are stretched. Similarly, the default @i(time-flag) is +non-null, but if @i(time-flag) is null, the original times are retained +and only durations are stretched. If both @i(dur-flag) and @i(time-flag) +are null, the score is not changed. If a range +of notes is specified, times are scaled within that range, and +notes after the range are shifted so that the stretched region does not +create a "hole" or overlap with notes that follow. If the range begins +or ends with a time (via @code(from-time:) and @code(to-time:)), time +stretching +takes place over the indicated time interval independent of whether +any notes are present or where they start. In other words, the +``rests'' are stretched along with the notes. +The original score is not modified, and a new score is returned. + +@codef{score-transpose(@pragma(defn)@index(score-transpose)@i(score), + @i(keyword), @i(amount), from-index: @i(i), to-index: @i(j), + from-time: @i(x), to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-transpose @i(score) + @i(keyword) @i(amount) :from-index @i(i) :to-index @i(j) + :from-time @i(x) :to-time @i(y))} @c{[lisp]}}@\For + each note in the score and in any indicated range, if there is a keyword + parameter matching @i(keyword) and the +parameter value is a number, increment +the parameter value by @i(amount). For example, to tranpose up by a whole +step, write @code[(score-transpose 2 :pitch @i(score))]. The +original score is not modified, and a new score +is returned. + +@codef{score-scale(@pragma(defn)@index(score-scale)@i(score), @i(keyword), @i(amount), from-index: @i(i), to-index: @i(j), from-time: @i(x), + to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-scale @i(score) @i(keyword) @i(amount) + :from-index @i(i) :to-index @i(j) :from-time @i(x) + :to-time @i(y))} @c{[lisp]}}@\For each note +in the score and in any indicated range, if there is a keyword +parameter matching @i(keyword) and the +parameter value is a number, multiply +the parameter value by @i(amount). The original score is not modified, +and a new score is returned. + +@codef{score-sustain(@pragma(defn)@index(score-sustain)@i(score), @i(factor), from-index: @i(i), to-index: @i(j), from-time: @i(x), + to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-sustain @i(score) @i(factor) + :from-index @i(i) :to-index @i(j) :from-time @i(x) + :to-time @i(y))} @c{[lisp]}}@\For each note +in the score and in any indicated range, multiply +the duration (stretch factor) by @i(amount). This can be used to +make notes sound more legato or staccato, and does not change their +starting times. The original score is not modified, and +a new score is returned. + +@codef{score-voice(@pragma(defn)@index(score-voice)@i(score), + @i(replacement-list), from-index: @i(i), to-index: @i(j), + from-time: @i(x), to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-voice @i(score) + @i(replacement-list) :from-index @i(i) :to-index @i(j) + :from-time @i(x) :to-time @i(y))} @c{[lisp]}}@\For each note +in the score and in any indicated range, replace the behavior (function) +name using @i(replacement-list), which has the format: +@code[((@i(old1 new1)) (@i(old2 new2)) @r(...))], where @i(oldi) indicates +a current behavior name and @i(newi) is the replacement. If @i(oldi) +is @code(*), it matches anything. For example, to +replace @code(my-note-1) by @code(trombone) and @code(my-note-2) by +@code(horn), use @code[score-voice(@i(score), {{my-note-1 trombone} +{my-note-2 horn}})]. To replace all instruments with +@code(piano), use @code[score-voice(@i(score), {{* piano}})]. +The original score is not modified, and a + new score is returned. + +@codef{score-merge(@pragma(defn)@index(score-merge)@i(score1), @i(score2), @r(...))} @c{[sal]}@* +@altdef{@code[(score-merge @i(score1) @i(score2) @r(...))] @c{[lisp]}}@\Create +a new score containing all the notes of the parameters, which are all +scores. The resulting notes retain their original times and durations. The +merged score begin time is the minimum of the begin times of the parameters +and the merged score end time is the maximum of the end times of +the parameters. The original scores are not modified, and a new +score is returned. + +@codef{score-append(@pragma(defn)@index(score-append)@i(score1), @i(score2), @r(...))} @c{[sal]}@* +@altdef{@code[(score-append @i(score1) @i(score2) @r(...))] @c{[lisp]}}@\Create +a new score containing all the notes of the parameters, which are all +scores. The begin time of the first score is unaltered. The begin time of + each other score is aligned to the end time of the +previous score; thus, scores are ``spliced'' in sequence. The original +scores are not modified, and a new score is returned. + +@codef{score-select(@pragma(defn)@index(score-select)@index(score-filter)@i(score), + @i(predicate), from-index: @i(i), to-index: @i(j), from-time: @i(x), + to-time: @i(y), reject: @i(flag))} @c{[sal]}@* +@altdef{@code{(score-select @i(score) + @i(predicate) :from-index @i(i) :to-index @i(j) :from-time @i(x) + :to-time @i(y) :reject @i(flag))} @c{[lisp]}}@\Select (or reject) +notes to form a new score. Notes are selected if they fall into the +given ranges of index and time @i(and) they satisfy @i(predicate), a function +of three parameters that is applied to the start time, duration, and the +expression of the note. Alternatively, @i(predicate) may be @code(t), +indicating that all notes in range are to be selected. +The selected notes along with the existing score begin and end markers, are combined to form a new score. Alternatively, if +the @code(reject:) parameter is non-null, the notes @i(not) selected form + the new score (in other words the selected notes are rejected or removed to + form the new score). The original score is not modified, and a + new score is returned. + +@codef{score-set-begin(@pragma(defn)@index(score-set-begin)@i(score), @i(time))} @c{[sal]}@* +@altdef{@code[(score-set-begin @i(score) @i(time))] @c{[lisp]}}@\The begin +time + from the @i(score)'s @code(SCORE-BEGIN-END) marker is set to @i(time). The +original score is not modified, and a new score is returned. + +@codef{score-get-begin(@pragma(defn)@index(score-get-begin)@i(score))} @c{[sal]}@* +@altdef{@code[(score-get-begin @i(score))] @c{[lisp]}}@\Return the begin +time of the @i(score). + +@codef{score-set-end(@pragma(defn)@index(score-set-end)@i(score), @i(time))} @c{[sal]}@* +@altdef{@code[(score-set-end @i(score) @i(time))] @c{[lisp]}}@\The end time + from the @i(score)'s @code(SCORE-BEGIN-END) marker is set to @i(time). The +original score is not modified, and a new score is returned. + +@codef{score-get-end(@pragma(defn)@index(score-get-end)@i(score))} @c{[sal]}@* +@altdef{@code[(score-get-end @i(score))] @c{[lisp]}}@\Return the end +time of the @i(score). + +@codef{score-must-have-begin-end(@pragma(defn)@index(score-must-have-begin-end)@i(score))} @c{[sal]}@* +@altdef{@code[(score-must-have-begin-end @i(score))] @c{[lisp]}}@\If + @i(score) does not have a begin and end time, construct a score with a + @code(SCORE-BEGIN-END) expression and return it. If score already has a begin +and end time, just return the score. The orignal score is not modified. + +@codef{score-filter-length(@pragma(defn)@index(score-filter-length)@i(score), +@i(cutoff))} @c{[sal]}@* +@altdef{@code[(score-filter-length @i(score) @i(cutoff))] @c{[lisp]}}@\Remove notes that extend beyond the @i(cutoff) time. This +is similar to @code(score-select), but the here, events are removed when +their nominal ending time (start time plus duration) exceeds the @i(cutoff), +whereas the @code(to-time:) parameter is compared to the note's start time. +The original score is not modified, and a new score is returned. + +@codef{score-repeat(@pragma(defn)@index(score-repeat)@i(score), @i(n))} @c{[sal]}@* +@altdef{@code[(score-repeat @i(score) @i(n))] @c{[lisp]}}@\Make a sequence +of @i(n) copies of @i(score). Each copy is shifted to that it's begin +time aligns with the end time of the previous copy, as in @code(score-append). +The original score is not modified, and a new score is returned. + +@codef{score-stretch-to-length(@pragma(defn)@index(score-stretch-to-length)@i(score), +@i(length))} @c{[sal]}@* +@altdef{@code[(score-stretch-to-length @i(score) @i(length))] @c{[lisp]}}@\Stretch the score so that the end time of the score is +the score's begin time plus @i(length). +The original score is not modified, and a new score is returned. + +@codef{score-filter-overlap(@pragma(defn)@index(score-filter-overlap)@i(score))} @c{[sal]}@* +@altdef{@code[(score-filter-overlap @i(score))] @c{[lisp]}}@\Remove +overlapping notes (based on the note start time and duration), giving +priority to the +positional order within the note list (which is also time order). +The original score is not modified, +and a new score is returned. + +@codef{score-print(@pragma(defn)@index(score-print)@i(score))} @c{[sal]}@* +@altdef{@code[(score-print @i(score))] @c{[lisp]}}@\Print a score with +one note per line. Returns @code(nil). + +@codef{score-play(@pragma(defn)@index(score-play)@i(score))} @c{[sal]}@* +@altdef{@code[(score-play @i(score))] @c{[lisp]}}@\Play @i(score) +using @code(timed-seq) to convert the score to a sound, and + @code(play) to play the sound. + +@codef{score-adjacent-events(@pragma(defn)@index(score-adjacent-events)@i(score), + @i(function), + from-index: @i(i), to-index: @i(j), + from-time: @i(x), to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-adjacent-events @i(score) @i(function) :from-index @i(i) :to-index @i(j) :from-time @i(x) :to-time @i(y))} @c{[lisp]}}@\Call + @code[(@i(function) @i(A) @i(B) @i(C))], where +@i(A), @i(B), and @i(C) are consecutive notes in the score. The result +replaces @i(B). If the result is @code(nil), @i(B) is deleted, and the +next call will be @code[(@i(function A C D))], etc. The first call is +to @code[(@i(function) nil @i(A B))] and the last is to +@code[(@i(function) @i(Y Z) nil)]. If there is just one note in the +score, @code[(@i(function) nil @i(A) nil)] is called. Function calls +are not made if the note is outside of the indicated range. +This function +allows notes and their parameters to be adjusted according to their +immediate context. The original score is not modified, +and a new score is returned. + +@codef{score-apply(@pragma(defn)@index(score-apply)@i(score), @i(function), + from-index: @i(i), to-index: @i(j), from-time: @i(x), to-time: @i(y))} +@c{[sal]}@* +@altdef{@code{(score-apply @i(score) @i(function) :from-index @i(i) :to-index @i(j) :from-time @i(x) :to-time @i(y))} @c{[lisp]}}@\Replace +each note in the score with the result of + @code[(@i(function time dur expression))] (in Lisp) or + @code[@i(function)(@i(time), @i(dur), @i(expression))] (in SAL), +where @i(time), @i(dur), +and @i(expression) are the time, duration, and expression of the note. +If a range is indicated, only notes in the range are replaced. +The original score is not modified, and a new score is returned. + +@codef{score-indexof(@pragma(defn)@index(score-indexof)@i(score), @i(function), + from-index: @i(i), to-index: @i(j), from-time: @i(x), to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-indexof @i(score) @i(function) :from-index @i(i) :to-index @i(j) :from-time @i(x) :to-time @i(y))} @c{[lisp]}}@\Return the index (position) +of the first score event (in range) for which applying @i(function) +using @code[(@i(function time dur expression))] returns true. + + +@codef{score-last-indexof(@pragma(defn)@index(score-last-indexof)@i(score), + @i(function), from-index: @i(i), to-index: @i(j), from-time: @i(x), +to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-last-indexof @i(score) @i(function) + :from-index @i(i) :to-index @i(j) :from-time @i(x) :to-time @i(y))} @c{[lisp]}}@\Return the index (position) +of the last score event (in range) for which applying @i(function) +using @code[(@i(function time dur expression))] returns true. + +@codef{score-randomize-start(@pragma(defn)@index(score-randomize-start)@index(jitter)@index(feel factor)@index(offset)@i(score), @i(amt), from-index: @i(i), to-index: @i(j), from-time: @i(x), + to-time: @i(y))} @c{[sal]}@* +@altdef{@code{(score-randomize-start @i(score) @i(amt) + :from-index @i(i) :to-index @i(j) :from-time @i(x) + :to-time @i(y))} @c{[lisp]}}@\Alter the start times of notes by a +random amount up to plus or minus @i(amt). +The original score is not modified, and a new score is returned. +@end(fndefs) + +@subsection(Xmusic and Standard MIDI Files) +@index(MIDI file)@index(Standard MIDI File) +Nyquist has a general facility to read and write MIDI files. +You can even translate to and from a text representation, as described +in Chapter @ref(adagio-chap). It is also useful sometimes to read notes +from Standard MIDI Files into Xmusic scores and vice versa. At present, +Xmusic only translates notes, ignoring the various controls, program +changes, pitch bends, and other messages. + +MIDI notes are translated to Xmusic score events as follows: +@begin(display) +@code[(@i(time) @i(dur) (NOTE :chan @i(channel) :pitch @i(keynum) :vel @i(velocity)))], +@end(display) +where @i(channel), @i(keynum), and @i(velocity) come directly +from the MIDI message (channels are numbered starting from zero). +Note also that note-off messages are implied by the stretch factor +@i(dur) which is duration in seconds. + +@begin(fndefs) +@codef{score-read-smf(@pragma(defn)@index(score-read-smf)@index(midi file)@i(filename))} @c{[sal]}@* +@altdef{@code[(score-read-smf @i(filename))] @c{[lisp]}}@\Read a +standard MIDI file from @i(filename). Return an Xmusic score, or @code(nil) +if the file could not be opened. The +start time is zero, and the end time is the maximum end time of all +notes. A very limited interface is offered to extract MIDI program numbers +from the file: The global variable @code(*rslt*) is set to a list of MIDI +program numbers for each channel. E.g. if @code(*rslt*) is @code[(0 20 77)], +then program for channel 0 is 0, for channel 1 is 20, and for channel 2 is 77. +Program changes were not found on other channels. The default program number is +0, so in this example, it is not known whether the program 0 on channel 0 +is the result of a real MIDI program change command or just a default value. +If more than one program change exists on a channel, the @i[last] program +number is recorded and returned, so this information will only be completely +correct when the MIDI file sends single program change per channel before +any notes are played. This, however, is a fairly common practice. Note that +the list returned as @code(*rslt*) can be passed +to @code(score-write-smf), described below. + +@codef{score-write-smf(@pragma(defn)@index(score-write-smf)@index(midi file)@i(score), @i(filename), +[@i(programs)])} @c{[sal]}@* +@altdef{@code[(score-write-smf @i(score) @i(filename) @i(programs))] @c{[lisp]}}@\Write a standard MIDI file to @i(filename) +with notes in @i(score). In this function, +@i(every) event in the score with a @code(pitch:) attribute, regardless of the +``instrument'' (or function name), generates a +MIDI note, using the @code(chan:) attribute for the channel (default 0) and +the @code(vel:) attribute for velocity (default 100). There is no facility +(in the current implementation) to issue control changes, but to allow +different instruments, MIDI programs may be set in two ways. The simplest is +to associate programs with channels using +the optional @i[programs] parameter, which is simply a list of up to 16 MIDI +program numbers. Corresponding program change commands are added to the +beginning of the MIDI file. If @i[programs] has less than 16 elements, program +change commands are only sent on the first @i[n] channels. The second way to +issue MIDI program changes is to add a @code(program:) keyword parameter to +a note in the score. Typically, the note will have a @code(pitch:) of +@code(nil) so that no actual MIDI note-on message is generated. If program +changes and notes have the same starting times, their relative playback +order is undefined, and the note may be cut off by an immediately +following program change. Therefore, program changes should occur slightly, +e.g. 1 ms, before any notes. @i(Program numbers and channels are numbered +starting at zero, matching the internal MIDI representation. This may be +one less than displayed on MIDI hardware, sequencers, etc.) +@end(fndefs) + +@subsection(Workspaces) +@label(workspaces-sec) +@index(workspace) +When working with scores, you may find it necessary to save +them in files between work sessions. This is not an issue +with functions because they are +normally edited in files and loaded from them. In contrast, +scores are created as Lisp data, and unless you take care to +save them, they will be destroyed when you exit the Nyquist +program. + +A simple mechanism called a workspace has been created +to manage scores (and any other Lisp data, for that matter). +A workspace is just a set of lisp global variables. These +variables are stored in the file @code(workspace.lsp). +For simplicity, there is only one workspace, and no backups +or versions are maintained, but the user is free to make +backups and copies of @code(workspace.lsp). +To help remember what each variable is for, you can also +associate and retrieve a text string with each variable. +The following functions manage workspaces. + +In addition, when a workspace is loaded, you can request that +functions be called. For example, the workspace might store +descriptions of a graphical interface. When the workspace is +loaded, a function might run to convert saved data into a +graphical interface. (This is how sliders are saved by the IDE.) + +@begin(fndefs) +@codef[add-to-workspace(@pragma(defn)@index(add-to-workspace)@i(symbol))] @c{[sal]}@* +@altdef{@code[(add-to-workspace @i(symbol))] @c{[lisp]}}@\Adds +a global variable to the workspace. The @i(symbol) should be a (quoted) +symbol. + +@codef[save-workspace(@pragma(defn)@index(save-workspace))] @c{[sal]}@* +@altdef{@code{(save-workspace)} @c{[lisp]}}@\All global variables +in the workspace are saved to @code(workspace.lsp) (in the current +directory), overwriting the previous file. + +@codef{describe(@pragma(defn)@index(describe)@i(symbol) [, @i(description)])} + @c{[sal]}@* +@altdef{@code[(describe @i(symbol) [@i(description)])] @c{[lisp]}}@\If @i(description), a text string, is present, +associate @i(description) with the variable named by the +@i(symbol). If @i(symbol) is not already in the workspace, +it is added. If @i(description) is omitted, the function returns +the current description (from a previous call) for @i(symbol). + +@codef{add-action-to-workspace(@pragma(defn)@index(add-action-to-workspace)@i(symbol))} @c{[sal]}@* +@altdef{@code[(add-action-to-workspace @i(symbol))] @c{[lisp]}}@\Requests that the function named by @i(symbol) be +called when the workspace is loaded (if the function is defined). +@end(fndefs) + +To restore a workspace, use the command @code[load "workspace"]. This restores +the values of the workspace variables to the values they had when +@code(save-workspace) was last called. It also restores the documentation +strings, if set, by @code(describe). If you load two or more +@code(workspace.lsp) files, the variables will be merged into a +single workspace. The current set of workspace variables are saved in +the list @code(*workspace*). To clear the workspace, set @code(*workspace*) +to @code(nil). This does not delete any variables, but means that +no variables will be saved by @code(save-workspace) until variables are +added again. + +Functions to be called are saved in the list @code(*workspace-actions*). +to clear the functions, set @code(*workspace-actions*) to @code(nil). +Restore functions to the list with @code(add-action-to-workspace). + +@subsection(Utility Functions) +This chapter concludes with details of various utility functions for score +manipulation. + +@begin(fndefs) +@codef[patternp(@pragma(defn)@index(patternp)@i(expression))] @c{[sal]}@* +@altdef{@code[(patternp @i(expression))] @c{[lisp]}}@\Test if @i(expression) is +an Xmusic pattern. + +@codef[params-transpose(@pragma(defn)@index(params-transpose)@i(params), @i(keyword), + @i(amount))] @c{[sal]}@* +@altdef{@code[(params-transpose @i(params) @i(keyword) @i(amount))] @c{[lisp]}}@\Add a transposition amount to a score event parameter. The +@i(params) +parameter is a list of keyword/value pairs (not preceded by a function name). +The @i(keyword) is the keyword of the value to be altered, and @i(amount) +is a number to be added to the value. If no matching keyword is present +in @i(params), then @i(params) is returned. Otherwise, a new parameter +list is constructed and returned. The original @i(params) is not changed. + +@codef[params-scale(@pragma(defn)@index(params-scale)@i(params), @i(keyword), + @i(amount))] @c{[sal]}@* +@altdef{@code[(params-scale @i(params) @i(keyword) @i(amount))] @c{[lisp]}}@\Scale a score event parameter by some factor. This is like + @code(params-transpose), only using multiplication. The @i(params) +list is a list of +keyword/value pairs, @i(keyword) is the parameter keyword, +and @i(amount) is the scale factor. + +@codef[interpolate(@pragma(defn)@index(interpolate)@index(linear interpolation)@i(x), @i(x1), @i(y1), @i(x2), @i(y2))] @c{[sal]}@* +@altdef{@code[(interpolate @i(x) @i(x1) @i(y1) @i(x2) @i(y2))] @c{[lisp]}}@\Linearly interpolate (or extrapolate) + between points +(@i(x1), @i(y1)) and (@i(x2), @i(y2)) to compute the y value + corresponding to @i(x). + +@codef[intersection(@pragma(defn)@index(intersection)@index(set intersection)@i(a), + @i(b))] @c{[sal]}@* +@altdef{@code[(intersection @i(a) @i(b))] @c{[lisp]}}@\Compute the set intersection of lists @i(a) and @i(b). + +@codef[union(@pragma(defn)@index(union)@index(set union)@i(a), @i(b))] @c{[sal]}@* +@altdef{@code[(union @i(a) @i(b))] @c{[lisp]}}@\Compute +the set union of lists @i(a) and @i(b). + +@codef[set-difference(@index(difference)@pragma(defn)@index(set-difference)@i(a), + @i(b))] @c{[sal]}@* +@altdef{@code[(set-difference @i(a) @i(b))] @c{[lisp]}}@\Compute the set of all elements that are in @i(a) but not in @i(b). + +@codef[subsetp(@pragma(defn)@index(subsetp)@index(subset)@i(a), @i(b))] @c{[sal]}@* +@altdef{@code[(subsetp @i(a) @i(b))] @c{[lisp]}}@\Returns true iff +@i(a) is a subset of @i(b), that is, each element of @i(a) is a member +of @i(b). +@end(fndefs) + +@chapter(Nyquist Libraries) +@index(libraries) +Nyquist is always growing with new functions. Functions that are most fundamental +are added to the core language. These functions are automatically loaded when you +start Nyquist, and they are documented in the preceding chapters. Other functions seem +less central and are implemented as lisp files that you can load. These are called +library functions, and they are described here. + +To use a library function, you +must first load the library, e.g. @code[(load "pianosyn")] loads the piano synthesis +library. The libraries are all located in the @code(lib) directory, and you +should therefore include this directory on your @code(XLISPPATH) variable. (See +Section @ref(install-sec).) Each library is documented in one of the following +sections. When you load the library described by the section, all functions +documented in that section become available. + +@section(Piano Synthesizer) +The piano synthesizer (library name is @code(pianosyn.lsp)) generates +realistic piano tones using a multiple wavetable implementation by Zheng (Geoffrey) +Hua and Jim Beauchamp, University of Illinois. Please see the notice about +acknowledgements that prints when you load the file. Further informations and +example code can be found in +@code(demos/piano.htm)@index(demos, piano)@index(piano synthesizer tutorial). +There are several useful functions in this library: +@begin(fndefs) +@codef[piano-note(@pragma(defn)@index(piano-note)@index(piano synthesizer)@i(duration), @i(step), + @i(dynamic))] @c{[sal]}@* +@altdef{@code[(piano-note @i(duration) @i(step) @i(dynamic))] @c{[lisp]}}@\Synthesizes a piano tone. @i(Duration) is the duration to the point of +key release, after which there is a rapid decay. @i(Step) is the pitch in half +steps, and @i(dynamic) is approximately equivalent to a MIDI key velocity +parameter. Use a value near 100 for a loud sound and near 10 for a soft sound. + +@codef[piano-note-2(@pragma(defn)@index(piano-note-2)@i(step), @i(dynamic))] @c{[sal]}@* +@altdef{@code[(piano-note-2 @i(step) @i(dynamic))] @c{[lisp]}}@\Similar to @code(piano-note) except the duration is nominally 1.0. + +@codef[piano-midi(@pragma(defn)@index(piano-midi)@i(midi-file-name))] @c{[sal]}@* +@altdef{@code[(piano-midi @i(midi-file-name))] @c{[lisp]}}@\Use the piano synthesizer +to play a MIDI file. The file name (a string) is given by @i(midi-file-name). + +@codef[piano-midi2file(@pragma(defn)@index(piano-midi2file)@i(midi-file-name), +@i(sound-file-name))] @c{[sal]}@* +@altdef{@code[(piano-midi2file @i(midi-file-name) @i(sound-file-name))] @c{[lisp]}}@\Use the piano synthesizer to play a MIDI file. The MIDI file +is given by @i(midi-file-name) and the (monophonic) result is written to the file +named @i(sound-file-name). +@end(fndefs) + +@section(Dymanics Compression) +To use these functions, load the file @code(compress.lsp). This library +implements a compressor originally intended for noisy speech audio, but +usable in a variety of situations. +There are actually two compressors that can be used in +series. The first, @code(compress), is +a fairly standard one: it detects signal level with an RMS +detector and uses table-lookup to determine how much gain +to place on the original signal at that point. One bit of +cleverness here is that the RMS envelope is ``followed'' or +enveloped using @code(snd-follow), which does look-ahead to anticipate +peaks before they happen. + +The other interesting feature is @code(compress-map), which builds +a map in terms of compression and expansion. For speech, the recommended +procedure is to figure out the noise floor on the signal you are compressing +(for example, look at the signal where the speaker is not talking). +Use a compression map that leaves the noise alone and boosts +signals that are well above the noise floor. Alas, the @code(compress-map) +function is not written in these terms, so some head-scratching is +involved, but the results are quite good. + +The second compressor is called @code(agc), and it implements automatic gain +control that keeps peaks at or below 1.0. By combining @code(compress) and +@code(agc), you can process poorly recorded speech for playback on low-quality +speakers in noisy environments. The @code(compress) function modulates the +short-term gain to to minimize the total dynamic range, keeping the speech at +a generally loud level, and the @code(agc) function rides the long-term gain +to set the overall level without clipping. + +@begin(fndefs) +@codef{compress-map(@pragma(defn)@index(compress-map)@i(compress-ratio), +@i(compress-threshold), +@i(expand-ratio), @i(expand-ratio), limit: @i(limit), transition: +@i(transition))} @c{[sal]}@* +@altdef{@code{(compress-map @i(compress-ratio) @i(compress-threshold) + @i(expand-ratio) @i(expand-ratio) :limit @i(limit) :transition + @i(transition)])} @c{[lisp]}}@\Construct +a map for the compress function. The map consists of two parts: a compression +part and an expansion part. +The intended use is to compress everything above compress-threshold by +compress-ratio, and to downward expand everything below expand-ratio +by expand-ratio. Thresholds are in dB and ratios are dB-per-dB. +0dB corresponds to a peak amplitude of 1.0 or rms amplitude of 0.7 +If the input goes above 0dB, the output can optionally be limited +by setting @code(limit:) (a keyword parameter) to @code(T). +This effectively changes +the compression ratio to infinity at 0dB. If @code(limit:) is @code(nil) +(the default), then the compression-ratio continues to apply above 0dB. + +Another keyword parameter, @code(transition:), sets the amount below the +thresholds (in dB) that a smooth transition starts. The default is 0, +meaning that there is no smooth transition. The smooth transition is a +2nd-order polynomial that matches the slopes of the straight-line compression +curve and interpolates between them. + +It is assumed that expand-threshold <= compress-threshold <= 0 +The gain is unity at 0dB so if compression-ratio > 1, then gain +will be greater than unity below 0dB. + +The result returned by this function is a sound for use in the @code(shape) +function. The sound maps input +dB to gain. Time 1.0 corresponds to 0dB, time 0.0 corresponds to +-100 dB, and time 2.0 corresponds to +100dB, so this is a +100hz ``sample rate'' sound. The sound gives gain in dB. + +@codef[db-average(@pragma(defn)@index(db-average)@i(input))] @c{[sal]}@* +@altdef{@code[(db-average @i(input))] @c{[lisp]}}@\Compute the average amplitude +of @i(input) in dB. + +@codef{compress(@pragma(defn)@index(compress)@i(input), @i(map), @i(rise-time), @i(fall-time) [, @i(lookahead)])} @c{[sal]}@* +@altdef{@code[(compress @i(input) @i(map) @i(rise-time) @i(fall-time) + [@i(lookahead)])] @c{[lisp]}}@\Compress +@i(input) using @i(map), a compression curve +probably generated by @code(compress-map) (see above). Adjustments in gain have +the given @i(rise-time) and @i(fall-time). Lookahead tells how far ahead to look +at the signal, and is @i(rise-time) by default. + +@codef{agc(@index(automatic gain control)@pragma(defn)@index(agc)@index(gain)@i(input), +@i(range), @i(rise-time), @i(fall-time) [, @i(lookahead)])} @c{[sal]}@* +@altdef{@code{(agc @i(input) @i(range) @i(rise-time) @i(fall-time) + [@i(lookahead)])} @c{[lisp]}}@\An automatic +gain control applied to @i(input). The maximum gain in dB is @i(range). Peaks +are attenuated to 1.0, and gain is controlled with the given @i(rise-time) and +@i(fall-time). The look-ahead time default is @i(rise-time). +@end(fndefs) + +@section(Clipping Softener) +This library, in @code(soften.lsp), was written to improve the quality of +poorly recorded speech. In recordings of speech, extreme clipping generates +harsh high frequency noise. This can sound particulary bad on small speakers +that will emphasize high frequencies. This problem can be ameliorated by +low-pass filtering regions where clipping occurs. The effect is to dull the +harsh clipping. Intelligibility is not affected by much, and the result can +be much more pleasant on the ears. Clipping is detected simply by looking for +large signal values. Assuming 8-bit recording, this level is set to 126/127. + +The function works by cross-fading between the normal signal and a filtered +signal as opposed to changing filter coefficients. + +@begin(fndefs) +@codef[soften-clipping(@pragma(defn)@index(soften-clipping)@index(clipping repair)@i(snd), +@i(cutoff))] @c{[sal]}@* +@altdef{@code[(soften-clipping @i(snd) @i(cutoff))] @c{[lisp]}}@\Filter the loud regions of a signal where clipping is likely +to have generated additional high frequencies. The input signal is @i(snd) +and @i(cutoff) is the filter cutoff frequency +(4 kHz is recommended for speech). +@end(fndefs) + +@section(Graphical Equalizer) +There's nothing really ``graphical'' about this library (@code(grapheq.lsp)), but +this is a common term for multi-band equalizers. This implementation uses +Nyquist's @code(eq-band) function to split the incoming signal into different +frequency bands. Bands are spaced geometrically, e.g. each band could be one +octave, meaning that each successive band has twice the bandwidth. An interesting +possibility is using computed control functions to make the equalization change +over time. + +@begin(fndefs) +@codef[nband-range(@pragma(defn)@index(nband-range)@index(graphical equalizer)@index(equalization)@i(input), @i(gains), @i(lowf), @i(highf))] @c{[sal]}@* +@altdef{@code[(nband-range @i(input) @i(gains) @i(lowf) @i(highf))] @c{[lisp]}}@\A graphical equalizer applied to +@i(input) (a @code(SOUND)). The gain controls and number of bands is given by @i(gains), an +ARRAY of @code(SOUND)s (in other words, a Nyquist multichannel @code(SOUND)). Any sound in the +array may be replaced by a @code(FLONUM). The bands are +geometrically equally spaced from the lowest frequency @i(lowf) to the +highest frequency @i(highf) (both are @code(FLONUM)s). + +@codef[nband(@pragma(defn)@index(nband)@i(input), @i(gains))] @c{[sal]}@* +@altdef{@code[(nband @i(input) @i(gains))] @c{[lisp]}}@\A graphical equalizer, identical +to @code(nband-range) with a range of 20 to 20,000 Hz. +@end(fndefs) + +@section(Sound Reversal) +The @code(reverse.lsp) library implements functions to play sounds in reverse. + +@begin(fndefs) +@codef[s-reverse(@index(reverse, sound)@pragma(defn)@index(s-reverse)@index(backward)@index(play in reverse)@i(snd))] @c{[sal]}@* +@altdef{@code[(s-reverse @i(snd))] @c{[lisp]}}@\Reverses @i(snd) (a @code(SOUND)). Sound must be shorter +than @code(*max-reverse-samples*), which is currently initialized to +25 million samples. Reversal allocates about 4 bytes per sample. This function +uses XLISP in the inner sample loop, so do not be surprised if it calls the +garbage collector a lot and runs slowly. The result starts at the starting +time given by the current environment (not necessarily the starting time +of @i(snd)). If @i(snd) has multiple channels, a multiple channel, +reversed sound is returned. + +@codef{s-read-reverse(@index(read samples in reverse)@pragma(defn)@index(s-read-reverse)@i(filename), time-offset: @i(offset), srate: @i(sr), dur: @i(dur), nchans: @i(chans), format: @i(format), mode: @i(mode), bits: @i(n), swap: @i(flag))} @c{[sal]}@* +@altdef{@code{(s-read-reverse @i(filename) :time-offset @i(offset) + :srate @i(sr) :dur @i(dur) :nchans @i(chans) :format @i(format) :mode @i(mode) :bits @i(n) :swap @i(flag))} @c{[lisp]}}@\This function is identical to @code(s-read) (see @ref(s-read-sec)), except it reads the indicated samples in reverse. Like +@code(s-reverse) (see above), it uses XLISP in the inner loop, so it is slow. +Unlike @code(s-reverse), @code(s-read-reverse) uses a fixed amount of +memory that is independent of how many samples are computed. Multiple channels +are handled. +@end(fndefs) + +@section(Time Delay Functions) +The @code(time-delay-fns.lsp) library implements chorus, phaser, and flange effects. + +@begin(fndefs) +@codef[phaser(@pragma(defn)@index(phaser)@index(effects, phaser)@i(snd))] @c{[sal]}@* +@altdef{@code[(phaser @i(snd))] @c{[lisp]}}@\A phaser effect +applied to @i(snd) (a @code(SOUND)). There are no parameters, +but feel free to modify the source code of this one-liner. + +@codef[flange(@pragma(defn)@index(flange)@index(flange effect)@index(effect, flange)@i(snd))] @c{[sal]}@* +@altdef{@code[(flange @i(snd))] @c{[lisp]}}@\A flange effect +applied to @i(snd). To vary the rate and other parameters, see the source code. + +@codef[stereo-chorus(@index(chorus)@pragma(defn)@index(stereo-chorus)@i(snd))] @c{[sal]}@* +@altdef{@code[(stereo-chorus @i(snd))] @c{[lisp]}}@\A chorus effect applied to @i(snd), +a @code(SOUND) (monophonic). The output is a stereo sound. All parameters are built-in, +but see the simple source code to make modifications. + +@codef[chorus(@pragma(defn)@index(chorus)@index(effect, chorus)@i(snd), @i(maxdepth), @i(depth), @i(rate), +@i(saturation))] @c{[sal]}@* +@altdef{@code[(chorus @i(snd) @i(maxdepth) @i(depth) @i(rate) @i(saturation))] @c{[lisp]}}@\A chorus effect applied to @i(snd). All parameters may be arrays +as usual. The @i(maxdepth) is a @code(FLONUM) giving twice the maximum value of @i(depth), +which may be a @code(FLONUM) or a @code(SOUND). The chorus is implemented as a variable delay +modulated by a sinusoid running at @i(rate) Hz (a @code(FLONUM)). The sinusoid is +scaled by @i(depth) and offset by @i(maxdepth)/2. The delayed signal is mixed +with the original, and @i(saturation) gives the fraction of the delayed signal +(from 0 to 1) in the mix. A reasonable choice of parameter values is +@i(maxdepth) = 0.05, @i(depth) = 0.025, @i(rate) = 0.5, and @i(saturation) = 0.5. +@end(fndefs) + +@section(Multiple Band Effects) +@index(multiple band effects)@index(bandfx.lsp) +The @code(bandfx.lsp) library implements several effects based on multiple +frequency bands. The idea is to separate a signal into different frequency +bands, apply a slightly different effect to each band, and sum the effected +bands back together to form the result. This file includes its own set of +examples. After loading the file, try @code[f2()], @code[f3()], @code[f4()], +and @code[f5()] to hear them. + +There is much room for expansion and experimentation with this library. Other +effects might include distortion in certain bands (for example, there are +commercial effects that add distortion to low frequencies to enhance the sound +of the bass), separating bands into different channels for stereo or multi-channel +effects, adding frequency-dependent reverb, and performing dynamic compression, +limiting, or noise gate functions on each band. There are also opportunities for +cross-synthesis: using the content of bands extracted from one signal to modify +the bands of another. The simplest of these would be to apply amplitude envelopes +of one sound to another. Please contact us (dannenberg@@cs.cmu.edu) if you +are interested in working on this library. + +@begin(fndefs) +@codef[apply-banded-delay(@index(banded delay)@pragma(defn)@index(apply-banded-delay)@i(s), @i(lowp), @i(highp), @i(num-bands), @i(lowd), @i(highd), @i(fb), @i(wet))] @c{[sal]}@* +@altdef{@code[(apply-banded-delay @i(s) @i(lowp) @i(highp) @i(num-bands) @i(lowd) @i(highd) @i(fb) @i(wet))] @c{[lisp]}}@\Separates +input @code(SOUND) @i(s) into @code(FIXNUM) @i(num-bands) bands from a low frequency +of @i(lowp) to a high frequency of @i(highp) (these are @code(FLONUMS) that specify +steps, not Hz), and applies a delay to each band. The delay for the lowest band is +given by the @code(FLONUM) @i(lowd) (in seconds) and the delay for the highest band +is given by the @code(FLONUM) @i(highd). The delays for other bands are linearly +interpolated between these values. Each delay has feedback gain controlled by +@code(FLONUM) @i(fb). The delayed bands are scaled by @code(FLONUM) @i(wet), and +the original sound is scaled by 1 - @i(wet). All are summed to form the result, +a @code(SOUND). + +@codef[apply-banded-bass-boost(@index(banded bass boost)@pragma(defn)@index(apply-banded-bass-boost)@i(s), @i(lowp), @i(highp), @i(num-bands), @i(num-boost), @i(gain))] @c{[sal]}@* +@altdef{@code[(apply-banded-bass-boost @i(s) @i(lowp) @i(highp) @i(num-bands) @i(num-boost) @i(gain))] @c{[lisp]}}@\Applies a boost to +low frequencies. Separates +input @code(SOUND) @i(s) into @code(FIXNUM) @i(num-bands) bands from a low frequency +of @i(lowp) to a high frequency of @i(highp) (these are @code(FLONUMS) that specify +steps, not Hz), and scales the lowest @i(num-boost) (a @code(FIXNUM)) bands by @i(gain), +a @code(FLONUM). The bands are summed to form the result, a @code(SOUND). + +@codef[apply-banded-treble-boost(@index(banded treble boost)@pragma(defn)@index(apply-banded-treble-boost)@i(s), @i(lowp), @i(highp), @i(num-bands), @i(num-boost), @i(gain))] @c{[sal]}@* +@altdef{@code[(apply-banded-treble-boost @i(s) @i(lowp) @i(highp) @i(num-bands) @i(num-boost) @i(gain))] @c{[lisp]}}@\Applies a boost to +high frequencies. Separates +input @code(SOUND) @i(s) into @code(FIXNUM) @i(num-bands) bands from a low frequency +of @i(lowp) to a high frequency of @i(highp) (these are @code(FLONUMS) that specify +steps, not Hz), and scales the highest @i(num-boost) (a @code(FIXNUM)) bands by @i(gain), +a @code(FLONUM). The bands are summed to form the result, a @code(SOUND). +@end(fndefs) + +@section(Granular Synthesis) +Some granular synthesis functions are implemented in the @code(gran.lsp) library +file. There are many variations and control schemes one could adopt for granular +synthesis, so it is impossible to create a single universal granular synthesis +function. One of the advantages of Nyquist is the integration of control and +synthesis functions, and users are encouraged to build their own granular synthesis +functions incorporating their own control schemes. The @code(gran.lsp) file +includes many comments and is intended to be a useful starting point. Another +possibility is to construct a score with an event for each grain. Estimate a +few hundred bytes per score event (obviously, size depends on the number of +parameters) and avoid using all of your computer's memory. + +@begin(fndefs) +@codef{sf-granulate(@index(granular synthesis)@pragma(defn)@index(sf-granulate)@i(filename), @i(grain-dur), @i(grain-dev), @i(ioi), @i(ioi-dev), @i(pitch-dev), +[@i(file-start), @i(file-end)])} @c{[sal]}@* +@altdef{@code{(sf-granulate @i(filename) @i(grain-dur) @i(grain-dev) @i(ioi) @i(ioi-dev) @i(pitch-dev) [@i(file-start) @i(file-end)])} @c{[lisp]}}@\Granular synthesis using a sound file +named @i(filename) as the source for grains. Grains are extracted from +a sound file named by @i(filename) by stepping through the file in equal +increments. Each grain duration is the +sum of @i(grain-dur) and a random number from 0 to @i(grain-dev). Grains are +then multiplied by a raised cosine smoothing window and resampled at a ratio +between 1.0 and @i(pitch-dev). If @i(pitch-dev) is greater than one, grains are +stretched and the pitch (if any) goes down. If @i(pitch-dev) is less than one, +grains are shortened and the pitch goes up. Grains are then output +with an +inter-onset interval between successive grains (which may overlap) +determined by the sum of +@i(ioi) and a random number from 0 to @i(ioi-dev). +The duration of the resulting sound is determined by +the stretch factor (not by the sound file). The number of grains is +the total sound duration (determined by the stretch factor) +divided by the mean inter-onset interval, +which is @i(ioi) + @i(ioi-dev) * 0.5. +The grains are taken from equally-spaced starting points in @i(filename), +and depending on grain size and number, the grains may or may not overlap. +The output duration will simply be the sum of the inter-onset intervals +and the duration of the last grain. If @i(ioi-dev) is non-zero, the +output duration will vary, but the expected value of the duration is +the stretch factor. +To achieve a rich granular synthesis effect, it is often a good idea to +sum four or more copies of @code(sf-granulate) together. (See the @code(gran-test) +function in @code(gran.lsp).) +@end(fndefs) + +@section(MIDI Utilities) +The @code(midishow.lsp) library has functions that can print the contents fo MIDI +files. This intended as a debugging aid. + +@begin(fndefs) +@codef[midi-show-file(@pragma(defn)@index(midi-show-file)@index(print midi file)@index(show midi file)@i(file-name))] @c{[sal]}@* +@altdef{@code[(midi-show-file @i(file-name))] @c{[lisp]}}@\Print the contents of a MIDI file to the console. + +@codef{midi-show(@pragma(defn)@index(midi-show)@i(the-seq) [, @i(out-file)])} @c{[sal]}@* +@altdef{@code{(midi-show @i(the-seq) [@i(out-file)])} @c{[lisp]}}@\Print the +contents of the sequence @i(the-seq) to the file @i(out-file) (whose default value +is the console.) +@end(fndefs) + +@section(Reverberation) +The @code(reverb.lsp) library implements artificial reverberation. + +@begin(fndefs) +@codef[reverb(@pragma(defn)@index(reverb)@index(effect, reverberation)@i(snd), +@i(time))] @c{[sal]}@* +@altdef{@code[(reverb @i(snd) @i(time))] @c{[lisp]}}@\Artificial reverberation applied to @i(snd) with a decay time of +@i(time). +@end(fndefs) + +@section(DTMF Encoding) +@index(dtmf)@index(touch tone) +The @code(dtmf.lsp) library implements DTMF encoding. DTMF is the +``touch tone'' code used by telephones. + +@begin(fndefs) +@codef[dtmf-tone(@pragma(defn)@index(dtmf-tone)@i(key), @i(len), @i(space))] @c{[sal]}@* +@altdef{@code[(dtmf-tone @i(key) @i(len) @i(space))] @c{[lisp]}}@\Generate a +single DTMF tone. The @i(key) parameter is either a digit (a @code(FIXNUM) +from 0 through 9) or the atom @code(STAR) or @code(POUND). The duration of +the done is given by @i(len) (a @code(FLONUM)) and the tone is followed by +silence of duration @i(space) (a @code(FLONUM)). + +@codef[speed-dial(@pragma(defn)@index(speed-dial)@i(thelist))] @c{[sal]}@* +@altdef{@code[(speed-dial @i(thelist))] @c{[lisp]}}@\Generates a sequence +of DTMF tones using the keys in @i(thelist) (a @code(LIST) of keys as +described above under @code(dtmf-tone)). The duration of each tone is 0.2 +seconds, and the space between tones is 0.1 second. Use @code(stretch) to +change the ``dialing'' speed. +@end(fndefs) + +@section[Dolby Surround(R), Stereo and Spatialization Effects] +@index(spatialization)@index(stereo)@index(pan)@index(Dolby Surround) + +The @code(spatial.lsp) library implements various functions for stereo +manipulation and spatialization. It also includes some functions for +Dolby Pro-Logic panning, which encodes left, right, center, and surround +channels into stereo. The stereo signal can then be played through +a Dolby decoder to drive a surround speaker array. This library has +a somewhat simplified encoder, so you should certainly test the +output. Consider using a high-end encoder for critical work. There +are a number of functions in @code(spatial.lsp) for testing. See the +source code for comments about these. + +@begin(fndefs) +@codef[stereoize(@pragma(defn)@index(stereoize)@index(mono to stereo)@index(effect, stereo)@i(snd))] @c{[sal]}@* +@altdef{@code[(stereoize @i(snd))] @c{[lisp]}}@\Convert a mono sound, @i(snd), to stereo. Four bands of +equalization and some delay are used to create a stereo effect. + +@codef[widen(@pragma(defn)@index(widen)@index(effect, widen)@i(snd), @i(amt))] @c{[sal]}@* +@altdef{@code[(widen @i(snd) @i(amt))] @c{[lisp]}}@\Artificially +widen the stereo field in @i(snd), a two-channel sound. The amount of widening +is @i(amt), which varies from 0 (@i(snd) is unchanged) to 1 (maximum widening). +The @i(amt) can be a @code(SOUND) or a number. + +@codef[span(@index(stereo pan)@index(pan, stereo)@index(effect, stereo pan)@pragma(defn)@index(span)@i(snd), @i(amt))] @c{[sal]}@* +@altdef{@code[(span @i(snd) @i(amt))] @c{[lisp]}}@\Pan the virtual center channel of a stereo sound, @i(snd), +by @i(amt), where 0 pans all the way to the left, while 1 pans all the way +to the right. The @i(amt) can be a @code(SOUND) or a number. + +@codef[swapchannels(@pragma(defn)@index(swapchannels)@index(swap channels)@index(effect, swap channels)@i(snd))] @c{[sal]}@* +@altdef{@code[(swapchannels @i(snd))] @c{[lisp]}}@\Swap left and right channels in @i(snd), a stereo sound. + +@codef[prologic(@pragma(defn)@index(prologic)@index(Dolby Pro-Logic)@index(Surround Sound)@i(l), @i(c), +@i(r), @i(s))] @c{[sal]}@* +@altdef{@code[(prologic @i(l) @i(c) @i(r) @i(s))] @c{[lisp]}}@\Encode four monaural @code(SOUND)s representing the front-left, +front-center, front-right, and rear channels, respectively. +The return value is a stereo sound, which is a Dolby-encoded mix of the +four input sounds. + +@codef[pl-left(@pragma(defn)@index(pl-left)@i(snd))] @c{[sal]}@* +@altdef{@code[(pl-left @i(snd))] @c{[lisp]}}@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the front left channel. + +@codef[pl-center(@pragma(defn)@index(pl-center)@i(snd))] @c{[sal]}@* +@altdef{@code[(pl-center @i(snd))] @c{[lisp]}}@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the front center channel. + +@codef[pl-right(@pragma(defn)@index(pl-right)@i(snd))] @c{[sal]}@* +@altdef{@code[(pl-right @i(snd))] @c{[lisp]}}@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the front right channel. + +@codef[pl-rear(@pragma(defn)@index(pl-rear)@i(snd))] @c{[sal]}@* +@altdef{@code[(pl-rear @i(snd))] @c{[lisp]}}@\Produce a Dolby-encoded (stereo) +signal with @i(snd), a @code(SOUND), encoded as the rear, or surround, channel. + +@codef[pl-pan2d(@pragma(defn)@index(pl-pan2d)@i(snd), @i(x), @i(y))] @c{[sal]}@* +@altdef{@code[(pl-pan2d @i(snd) @i(x) @i(y))] @c{[lisp]}}@\Comparable to Nyquist's +existing pan function, @code(pl-pan2d) provides not only left-to-right +panning, but front-to-back panning as well. The function +accepts three parameters: @i(snd) is the (monophonic) input @code(SOUND), +@i(x) is a left-to-right position, and @i(y) is a front-to-back position. +Both position parameters may be numbers or @code(SOUND)s. An @i(x) value +of 0 means left, and 1 means right. Intermediate values map linearly +between these extremes. Similarly, a @i(y) value of 0 causes the sound +to play entirely through the front speakers(s), while 1 causes it to play +entirely through the rear. Intermediate values map linearly. +Note that, although there are usually two rear speakers in Pro-Logic systems, +they are both driven by the same signal. Therefore any sound that is +panned totally to the rear will be played over both rear speakers. For +example, it is not possible to play a sound exclusively through the +rear left speaker. + +@codef[pl-position(@pragma(defn)@index(pl-position)@i(snd), @i(x), @i(y), @i(config))] @c{[sal]}@* +@altdef{@code[(pl-position @i(snd) @i(x) @i(y) @i(config))] @c{[lisp]}}@\The +position function builds upon speaker panning to allow more abstract +placement of sounds. Like @code(pl-pan2d), it accepts a (monaural) input +sound as well as left-to-right (@i(x)) and front-to-back (@i(y)) coordinates, +which may be @code(FLONUM)s or @code(SOUND)s. A fourth parameter @i(config) +specifies the distance from listeners to the speakers (in meters). Current +settings assume this to be constant for all speakers, but this assumption +can be changed easily (see comments in the code for more detail). +There are several important differences between @code(pl-position) and +@code(pl-pan2d). First, @code(pl-position) uses a Cartesian coordinate +system that allows x and y coordinates outside of the +range (0, 1). This model assumes a listener position of (0,0). Each speaker +has a predefined position as well. The input sound's position, +relative to the listener, is given by the vector (@i(x),@i(y)). + +@codef[pl-doppler(@pragma(defn)@index(pl-doppler)@index(Doppler effect)@i(snd), +@i(r))] @c{[sal]}@* +@altdef{@code[(pl-doppler @i(snd) @i(r))] @c{[lisp]}}@\Pitch-shift moving sounds according to the equation: @i(fr) = +@i(f0)((@i(c)+@i(vr))/@i(c)), where @i(fr) is the output frequency, +@i(f0) is the emitted (source) +frequency, @i(c) is the speed of sound (assumed to be 344.31 m/s), and +@i(vr) is the speed at which the emitter approaches the receiver. (@i(vr) +is the first derivative of parameter @i(r), the distance from the listener +in meters. + +@end(fndefs) + +@section(Drum Machine) +@label(drum-machine-sec)@index(drum machine) + +The drum machine software in @code(demos/plight) deserves further explanation. +to use the software, load the code by evaluating: +@begin(example) +load "../demos/plight/drum.lsp" +exec load-props-file(strcat(*plight-drum-path*, + "beats.props")) +exec create-drum-patches() +exec create-patterns() +@end(example) + +Drum sounds and patterns are specified in the @code(beats.props) file (or +whatever name you give to @code(load-props-file)). This file +contains two types of specifications. First, there are sound file specifications. +Sound files are located by a line of the form: +@begin(example) +set sound-directory = "kit/" +@end(example) +This gives the name of the sound file directory, relative to the + @code(beats.props) file. Then, for each sound file, there should be a line of +the form: +@begin(example) +track.2.5 = big-tom-5.wav +@end(example) +This says that on track 2, a velocity value of 5 means to play the sound file + @code(big-tom-5.wav). (Tracks and velocity values are described below.) +The @code(beats.props) file contains specifications for all the sound files +in @code(demos/plight/kit) using 8 tracks. If you make your own specifications +file, tracks should be numbered consecutively from 1, and velocities should be +in the range of 1 to 9. + +The second set of specifications is of beat patterns. A beat pattern is given +by a line in the following form: +@begin(example) +beats.5 = 2--32--43-4-5--- +@end(example) +The number after @code(beats) is just a pattern number. Each pattern +is given a unique number. After the equal sign, the digits and dashes are +velocity values where a dash means ``no sound.'' Beat patterns should be +numbered consecutively from 1. + +Once data is loaded, there are several functions to access drum patterns and +create drum sounds (described below). The @code(demos/plight/drums.lsp) file +contains an example function @code(plight-drum-example) to play some drums. +There is also the file @code(demos/plight/beats.props) to serve as an +example of how to specify sound files and beat patterns. + +@begin(fndefs) +@codef{drum(@pragma(defn)@index(drum)@i(tracknum), @i(patternnum), @i(bpm))} @c{[sal]}@* +@altdef{@code[(drum @i(tracknum) @i(patternnum) @i(bpm))] @c{[lisp]}}@\Create +a sound by playing drums sounds associated with track @i(tracknum) (a +FIXNUM) using pattern @i(patternnum). The tempo is given by @i(bpm) in +beats per minute. Normally patterns are a sequence of sixteenth notes, so +the tempo is in @i(sixteenth notes per minute). For example, +if @i(patternnum) is 10, +then use the pattern specified for @code(beats.10). If the third character +of this pattern is 3 and @i(tracknum) is 5, then on the third beat, play +the soundfile assigned to @code(track.5.3). This function returns a @code(SOUND). + +@codef{drum-loop(@pragma(defn)@index(drum-loop)@i(snd), @i(duration), @i(numtimes))} @c{[sal]}@* +@altdef{@code[(drum-loop @i(snd) @i(duration) @i(numtimes))] @c{[lisp]}}@\Repeat the sound given by @i(snd) @i(numtimes) times. The repetitions occur at a time offset of @i(duration), regardless of the actual duration of @i(snd). A @code(SOUND) is returned. + +@codef{length-of-beat(@pragma(defn)@index(length-of-beat)@i(bpm))} @c{[sal]}@* +@altdef{@code[(length-of-beat @i(bpm))] @c{[lisp]}}@\Given a tempo of +@i(bpm), return the duration of the beat in seconds. Note that this software +has no real notion of beat. A ``beat'' is just the duration of each character +in the beat pattern strings. This function returns a @code(FLONUM). +@end(fndefs) + + + +@section(Minimoog-inspired Synthesis) +@index(Moog)@index(Minimoog)@index(analog synthesizer) + +The @code(moog.lsp) library gives the Nyquist user easy access to ``classic'' +synthesizer sounds through an emulation of the Minimoog Synthesizer. +Unlike modular Moogs that were very large, the Minimoog was the first +successful and commonly used portable synthesizer. The trademark filter attack +was unique and easily recognizable. The goal of this Nyquist instrument is not +only to provide the user with default sounds, but also to give control over +many of the ``knobs'' found on the Minimoog. In this implementation, these +parameters are controlled using keywords. The input to the @code(moog) +instrument is a user-defined sequence of notes, durations, and articulations +that simulate notes played on a keyboard. These are translated into +control voltages that drive multiple oscillators, similar to the Voltage +Controlled Oscillator or VCO found in the original analog Moog. + +The basic functionality of the Minimoog has been implemented, including the +often-used "glide". The glide feature essentially low-pass filters the control +voltage sequence in order to create sweeps between notes. +Figure @ref(moog-fig) is a simplified schematic of the data flow in the Moog. +The control lines have been omitted. + +@begin(figure) +@center(@graphic((height = 2.514 in, width = 4.65 in, magnify = 0.3, + postscript = "moog-fig.ps")) +@html(

) +@fillcaption(System diagram for Minimoog emulator.) +@tag(moog-fig) +@end(figure) + +The most recognizable feature of the Minimoog is its resonant filter, a +Four-Pole Ladder Filter invented by Robert Moog. It is simply implemented +in a circuit with four transistors and provides an outstanding 24 dB/octave +rolloff. It is modeled here using the built-in Nyquist resonant filter. +One of the Moog filter features is a constant Q, or center frequency to +bandwidth ratio. This is implemented and the user can control the Q. + +The user can control many parameters using keywords. Their default values, +acceptable ranges, and descriptions are shown below. The defaults were +obtained by experimenting with the official Minimoog software synthesizer +by Arturia. + +@subsection(Oscillator Parameters) +@code(range-osc1) (2)@* +@code(range-osc2) (1)@* +@code(range-osc3) (3)@* +These parameters control the octave of each oscillator. A value of 1 +corresponds to the octave indicated by the input note. A value of 3 +is two octaves above the fundamental. The allowable range is 1 to 7. + +@code(detun2) (-.035861)@* +@code(detun3) (.0768)@* +Detuning of two oscillators adds depth to the sound. A value of 1 corresponds +to an increase of a single semitone and a -1 corresponds to a decrease +in a semitone. The range is -1 to 1. + +@code(shape-osc1) (@code(*saw-table*))@* +@code(shape-osc2) (@code(*saw-table*))@* +@code(shape-osc3) (@code(*saw-table*))@* +Oscilators can use any wave shape. The default sawtooth waveform is +a built-in Nyquist variable. Other waveforms can be defined by the user. + +@code(volume-osc1) (1)@* +@code(volume-osc2) (1)@* +@code(volume-osc3) (1)@* +These parameters control the relative volume of each oscillator. The range +is any @code(FLONUM) greater than or equal to zero. + +@subsection(Noise Parameters) +@code(noiselevel) (.05)@* +This parameter controls the relative volume of the noise source. The range +is any @code(FLONUM) greater than or equal to zero. + +@subsection(Filter Parameters) +@code(filter-cutoff) (768)@* +The cutoff frequency of the filter in given in Hz. The range is zero +to 20,000 Hz. + + +@code(Q) (2)@* +Q is the ratio of center frequency to bandwidth. It is held constant by +making the bandwidth a function of frequency. The range is any +@code(FLONUM) greater than zero. + +@code(contour) (.65)@* +Contour controls the range of the transient frequency sweep from a high +to low cutoff frequency when a note is played. The high frequency is +proportional to contour. A contour of 0 removes this sweep. The range +is 0 to 1. + +@code(filter-attack) (.0001)@* +Filter attack controls the attack time of the filter, i.e. the time to +reach the high cutoff frequency. The range is any @code(FLONUM) greater +than zero (seconds). + +@code(filter-decay) (.5)@* +Filter decay controls the decay time of the filter, i.e. the time of the +sweep from the high to low cutoff frequency. The range is +any @code(FLONUM) greater than zero (seconds). + +@code(filter-sustain) (.8)@* +Filter sustain controls the percentage of the filter cutoff frequency that +the filter settles on following the sweep. The range is 0 to 1. + +@subsection(Amplitude Parameters) +@code(amp-attack) (.01)@* +This parameter controls the amplitude envelope attack time, i.e. the time to +reach maximum amplitude. The range is +any @code(FLONUM) greater than zero (seconds). + +@code(amp-decay) (1)@* +This parameter controls the amplitude envelope decay time, i.e. the time +between the maximum and sustain volumes. The range is +any @code(FLONUM) greater than zero (seconds). + +@code(amp-sustain) (1)@* +This parameter controls the amplitude envelope sustain volume, a fraction +of the maximum. The range is 0 to 1. + +@code(amp-release) (0)@* +This parameter controls the amplitude envelope release time, i.e. the time +it takes between the sustain volume and 0 once the note ends. +The duration controls the overall length of the sound. The range of @code(amp-release) is any @code(FLONUM) greater than zero (seconds). + +@subsection(Other Parameters) +@code(glide) (0)@* +Glide controls the low-pass filter on the control voltages. This models the +glide knob on a Minimoog. A higher value corresponds to a lower cutoff +frequency and hence a longer "glide" between notes. A value of 0 +corresponds to no glide. The range is zero to 10. + +@subsection(Input Format) +A single note or a series of notes can be input to the Moog instrument +by defining a list with the following format: +@begin(example) +list(list(@i(frequency), @i(duration), @i(articulation)), @r(...) ) +@end(example) +where @i(frequency) is a @code(FLONUM) in steps, @i(duration) is the duration +of each note in seconds (regardless of the release time of the amplifier), +and @i(articulation) is a percentage of the duration that a sound will be +played, representing the amount of time that a key is pressed. The filter +and amplitude envelopes are only triggered if a note is played when +the articulation of the previous note is less than 1, or a key is not down at +the same time. This Moog instrument is a monophonic instrument, so only +one note can sound at a time. The release section of the amplifier is +triggered when the articulation is less than 1 at the time +(@i(duration) * @i(articulation)). + +@subsection(Sample Code/Sounds) + +@b[Sound 1 (default parameters):] +@begin(display) +@begin(code) +set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99} + {29 .5 .99} {31 2 1}} +play moog(s) +@end(code) +@end(display) + +@b[Sound 2 (articulation, with amplitude release):] +@begin(display) +@begin(code) +set s = {{24 .5 .5} {26 .5 1} {28 .5 .25} {29 .5 1} {31 1 .8}} +play moog(s, amp-release: .2) +@end(code) +@end(display) + +@b[Sound 3 (glide):] +@begin(display) +@begin(code) +set s = {{24 .5 .5} {38 .5 1} {40 .5 .25} + {53 .5 1} {55 2 1} {31 2 .8} {36 2 .8}} +play moog(s, amp-release: .2, glide: .5) +@end(code) +@end(display) + +@b[Sound 4 (keyword parameters):] Filter attack and decay are purposely +longer than notes being played with articulation equal to 1. +@begin(display) +@begin(code) +set s = {{20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1} + {20 .5 1} {27 .5 1} {26 .5 1} {21 .5 1}} +play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*, + filter-attack: 2, filter-decay: 2, + filter-cutoff: 300, contour: .8, glide: .2, Q: 8) +@end(code) +@end(display) + +@b[Sound 5:] This example illustrates the ability to completely define a new +synthesizer with different parameters creating a drastically different +sound. Sine waves are used for wavetables. There is a high value for glide. +@begin(display) +@begin(code) +define function my-moog(freq) + return moog(freq, + range-osc1: 3, range-osc2: 2, range-osc3: 4, + detun2: -.043155, detun3: .015016, + noiselevel: 0, + filter-cutoff: 400, Q: .1, contour: .0000001, + filter-attack: 0, filter-decay: .01, filter-sustain: 1, + shape-osc1: *sine-table*, shape-osc2: *sine-table*, + shape-osc3: *sine-table*, volume-osc1: 1, volume-osc2: 1, + volume-osc3: .1, amp-attack: .1, amp-decay: 0, + amp-sustain: 1, amp-release: .3, glide: 2) + +set s = {{80 .4 .75} {28 .2 1} {70 .5 1} {38 1 .5}} +play my-moog(s) +@end(code) +@end(display) + +@b[Sound 6:] This example has another variation on the default + parameters. +@begin(display) +@begin(code) +set s = {{24 .5 .99} {26 .5 .99} {28 .5 .99} + {29 .5 .99} {31 2 1}} +play moog(s, shape-osc1: *tri-table*, shape-osc2: *tri-table*, + filter-attack: .5, contour: .5) +@end(code) +@end(display) + +@pragma(doinclude) +@include(nymanimpl.mss) + +@appendix(Open Sound Control and Nyquist)@index(Open Sound Control) +@label(osc-app) +Open Sound Control (OSC) is a simple protocol for communicating music +control parameters between software applications and across +networks. For more information, see @html[]@code(http://www.cnmat.berkeley.edu/OpenSoundControl/)@html[]. The +Nyquist implementation of Open Sound Control is simple: an array of +floats can be set by OSC messages and read by Nyquist functions. That +is about all there is to it. + +Note: Open Sound Control must be enabled by calling +@code[osc-enable(t)]. If this fails under Windows, see the +installation instructions in @code(sys/win/README.txt) regarding +@code(SystemRoot). + +To control something in (near) real-time, you need to access a slider value as if it a signal, or more properly, a Nyquist @code(SOUND) type. The function @code(snd-slider), described in Section @ref(snd-slider-sec), takes a slider number and returns a @code(SOUND) type representing the current value of the slider. To fully understand this function, you need to know something about how Nyquist is actually computing sounds. + +Sounds are normally computed on demand. So the result returned by @code(snd-slider) does not immediately compute any samples. Samples are only computed when something tries to use this signal. At that time, the slider value is read. Normally, if the slider is used to control a sound, you will hear changes in the sound pretty soon after the slider value changes. However, one thing that can interfere with this is that @code(SOUND) samples are computed in blocks of about 1000 samples. When the slider value is read, the same value is used to fill a block of 1000 samples, so even if the sample rate is 44,100 Hz, the effective slider sample rate is 44,100/1000, or 44.1 Hz. If you give the slider a very low sample rate, say 1000, then slider value changes will only be noticed by Nyquist approximately once per second. For this reason, you should normally use the audio sample rate (typically 44,100 Hz) for the rate of the @code(snd-slider) output @code(SOUND). (Yes, this is terribly wasteful to represent each slider value with 1000 samples, but Nyquist was not designed for low-latency computation, and this is an expedient work-around.) + +In addition to reading sliders as continually changing @code(SOUND)s, you can get the slider value as a Lisp @code(FLONUM) (a floating point number) using @code(get-slider-value), described in Section @ref(get-slider-value-sec). This might be useful if you are computing a sequence of many notes (or other sound events) and want to apply the current slider value to the whole note or sound event. + +Note that if you store the value returned by @code(snd-slider) in a variable, you will capture the history of the slider changes. This will take a lot of memory, so be careful. + +Suppose you write a simple expression such as @code[(hzosc (mult 1000 (snd-slider 0 @r(...))))] (or in SAL, @code[hzosc(1000 * snd-slider(0 @r(...)))]) to control an oscillator frequency with a slider. How long does this sound last? The duration of @code[hzosc] is the duration of the frequency control, so what is the duration of a slider? To avoid infinitely long signals, you must specify a duration as one of the parameters of @code[snd-slider]. + +You might be thinking, what if I just want to tell the slider when to stop? At present, you cannot do that, but in the future there should be a function that stops when its input goes to zero. Then, moving a slider to zero could end the signal (and if you multiplied a complex sound by one of these ending functions, everything in the sound would end and be garbage collected). + +Another thing you might want to do with interactive control is start some sound. The @code(trigger) function computes an instance of a behavior each time an input @code(SOUND) goes from zero to greater-than-zero. This could be used, for example, to create a sequence of notes. + +The @code(snd-slider) function has some parameters that may be unfamiliar. The second parameter, @i(t0), is the starting time of the sound. This should normally be @code[local-to-global(0)], an expression that computes the instantiation time of the current expression. This will often be zero, but if you call @code[snd-slider] from inside a @code(seq) or @code(seq-rep), the starting time may not be zero. + +The @i(srate) parameter is the sample rate to return. This should normally be the audio sample rate you are working with, which is typically @code[*default-sound-srate*]. + +@section(Sending Open Sound Control Messages) +A variety of programs support OSC. The only OSC message interpreted by Nyquist has an address of @code[/slider], and two parameters: an integer slider number and a float value, nominally from 0.0 to 1.0. + +Two small programs are included in the Nyquist distribution for sending OSC messages. (Both can be found in the same directory as the nyquist executable.) The first one, @code[osc-test-client] sends a sequence of messages that just cause slider 0 to ramp slowly up and down. If you run this on a command line, you can use "?" or "h" to get help information. There is an interactive mode that lets you send each OSC message by typing RETURN. + +@section(The ser-to-osc Program) +The second program is @code[ser-to-osc], a program that reads serial input (for example from a PIC-based microcontroller) and sends OSC messages. Run this command-line program from a shell (a terminal window under OS X or Linux; use the CMD program under Windows). You must name the serial input device on the command line, e.g. under OS X, you might run: +@begin(display) +@code(./ser-to-osc /dev/tty.usbserial-0000103D) +@end(display) +(Note that the program name is preceded by ``@code(./)". This tells the shell exactly where to find the executable program in case the current directory is not on the search path for executable programs.) +Under Windows, you might run: +@begin(display) +@code(ser-to-osc com4) +@end(display) +(Note that you do not type ``@code(./)'' in front of a windows program.) + +To use @code(ser-to-osc), you will have to find the serial device. On the Macintosh and Linux, try the following: +@begin(display) +@code(ls /dev/*usb*) +@end(display) +This will list all serial devices with ``usb'' in their names. Probably, one will be a name similar to @code(/dev/tty.usbserial-0000103D). The @code(ser-to-osc) program will echo data that it receives, so you should know if things are working correctly. + +Under Windows, open Control Panel from the Start menu, and open the System control panel. Select the Hardware tab and click the Device Manager button. Look in the device list under Ports (COM & LPT). When you plug in your serial or USB device, you should see a new entry appear, e.g. @code(COM4). This is the device name you need. + +The format for the serial input is: any non-whitespace character(s), a slider number, a slider value, and a newline (control-j or ASCII 0x0A). These fields need to be separated by tabs or spaces. An optional carriage return (control-m or ASCII 0x0D) preceding the ASCII 0x0A is ignored. The slider number should be in decimal, and theh slider value is a decimal number from 0 to 255. This is scaled to the range 0.0 to 1.0 (so an input of 255 translates to 1.0). + +There is a simple test program in @code[demos/osc-test.lsp] you can run to try out control with Open Sound Control. There are two examples in that file. One uses @code(snd-slider) to control the frequency of an oscillator. The other uses @code(get-slider-value) to control the pitch of grains in a granular synthesis process. + + +@appendix(Intgen)@index(Intgen) +@label(intgen-app) +@pragma(doinclude) +@include(../xlisp/intgen.mss) + +@appendix(XLISP: An Object-oriented Lisp) +@label(xlisp-app) +@begin(center) + +@b(Version 2.0) + +February 6, 1988 + +by +@b(David Michael Betz) +127 Taylor Road +Peterborough, NH 03458 + +Copyright (c) 1988, by David Michael Betz +All Rights Reserved +Permission is granted for unrestricted non-commercial use +@end(center) +@newpage +@pragma(doinclude) +@include(../xlisp/xlisp.mss) diff --git a/docsrc/nyquist/poisson-fig.ps b/docsrc/nyquist/poisson-fig.ps new file mode 100644 index 0000000..67a3d07 --- /dev/null +++ b/docsrc/nyquist/poisson-fig.ps @@ -0,0 +1,1236 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner +%%Title: poisson-fig.ps +%%CreationDate: Wed Jul 13 12:17:22 2005 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 313 364 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228346456694 14.173228346456694 translate +% Translate to begin of first scanline +%0 349 translate +-20 775 translate +297.99999999999994 -349 scale +% Image geometry +298 349 8 +% Transformation matrix +[ 298 0 0 349 0 0 ] +% Strings to hold RGB-samples per scanline +/rstr 298 string def +/gstr 298 string def +/bstr 298 string def +{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop} +true 3 +%%BeginData: 55088 ASCII Bytes +colorimage +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +r;V +r;V +r;V +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`s`rGr:!1N]_rrD$Xr;["7d/X+G!;ZWqiJdX5rr<-#!!)`m"lYF?rr<&_s8N)ps8N'#s5Aq& +rrqYU!!%uB`W#o +r;Q`s`rGr:!1N]_rrD$Xr;["7d/X+G!;ZWqiJdX5rr<-#!!)`m"lYF?rr<&_s8N)ps8N'#s5Aq& +rrqYU!!%uB`W#o +r;Q`s`rGr:!1N]_rrD$Xr;["7d/X+G!;ZWqiJdX5rr<-#!!)`m"lYF?rr<&_s8N)ps8N'#s5Aq& +rrqYU!!%uB`W#o +r;Q`s`rH&=s8N/@!1MO>rrE*!!h',JpAb-mp](6npAb-mjT#5[q>^Hp!ri6#li.-W!9r_J9u[,4 +!;leH~> +r;Q`s`rH&=s8N/@!1MO>rrE*!!h',JpAb-mp](6npAb-mjT#5[q>^Hp!ri6#li.-W!9r_J9u[,4 +!;leH~> +r;Q`s`rH&=s8N/@!1MO>rrE*!!h',JpAb-mp](6npAb-mjT#5[q>^Hp!ri6#li.-W!9r_J9u[,4 +!;leH~> +r;Q`s`rH&=rr;uus8O=L9`VL!rr<'!l$NI2N9UB,HiO/*l2Udh9`VL!rr<&GHqhuds8N*!rs\,l +Rf?!ZN'q)!76*fd/!\MN+gQ< +!<<))!!'>)s8)d#s65IB!,1'TrrV-ZI)Z*c!;leH~> +r;Q`s`rH&=rr;uus8O=L9`VL!rr<'!l$NI2N9UB,HiO/*l2Udh9`VL!rr<&GHqhuds8N*!rs\,l +Rf?!ZN'q)!76*fd/!\MN+gQ< +!<<))!!'>)s8)d#s65IB!,1'TrrV-ZI)Z*c!;leH~> +r;Q`s`rH&=rr;uus8O=L9`VL!rr<'!l$NI2N9UB,HiO/*l2Udh9`VL!rr<&GHqhuds8N*!rs\,l +Rf?!ZN'q)!76*fd/!\MN+gQ< +!<<))!!'>)s8)d#s65IB!,1'TrrV-ZI)Z*c!;leH~> +r;Q`s`rH&=rr;uu-3(XYa2\1nrr<'!BE8(s!.=f[!<;9`I/gk[a2\1nrr<&4kl=HVs8N)us8N'X +rr<'!BE8(s!.=eH!<<'!!87DP!!*$!!2mj;VZ6_srr<'!!!*'!!!*&4!6<+[^&J'4^$,MkqYqJ3 +!6:u;!<9_4a3Xh"rr<'!!!*'!I+ePa!) +r;Q`s`rH&=rr;uu-3(XYa2\1nrr<'!BE8(s!.=f[!<;9`I/gk[a2\1nrr<&4kl=HVs8N)us8N'X +rr<'!BE8(s!.=eH!<<'!!87DP!!*$!!2mj;VZ6_srr<'!!!*'!!!*&4!6<+[^&J'4^$,MkqYqJ3 +!6:u;!<9_4a3Xh"rr<'!!!*'!I+ePa!) +r;Q`s`rH&=rr;uu-3(XYa2\1nrr<'!BE8(s!.=f[!<;9`I/gk[a2\1nrr<&4kl=HVs8N)us8N'X +rr<'!BE8(s!.=eH!<<'!!87DP!!*$!!2mj;VZ6_srr<'!!!*'!!!*&4!6<+[^&J'4^$,MkqYqJ3 +!6:u;!<9_4a3Xh"rr<'!!!*'!I+ePa!) +r;Q`s`rH&=s8N\E!2oj1!<<'!B`A&4s%NK@d/O%I9`TRfrr3C?!<<'!B`A&4s8N'!rVultrr;uu +#QFc(s%NK@d/O(F!<<*!!<3#u!$V@B!<<'!9`P1nrr<'!!!*'!!!*%4!<<'!B`A&4s8N'!qYq1& +!<<'!!<5ans8N(4rr<'!!!*#u"Q?Y6!!)Ng!lk;0`W#o +r;Q`s`rH&=s8N\E!2oj1!<<'!B`A&4s%NK@d/O%I9`TRfrr3C?!<<'!B`A&4s8N'!rVultrr;uu +#QFc(s%NK@d/O(F!<<*!!<3#u!$V@B!<<'!9`P1nrr<'!!!*'!!!*%4!<<'!B`A&4s8N'!qYq1& +!<<'!!<5ans8N(4rr<'!!!*#u"Q?Y6!!)Ng!lk;0`W#o +r;Q`s`rH&=s8N\E!2oj1!<<'!B`A&4s%NK@d/O%I9`TRfrr3C?!<<'!B`A&4s8N'!rVultrr;uu +#QFc(s%NK@d/O(F!<<*!!<3#u!$V@B!<<'!9`P1nrr<'!!!*'!!!*%4!<<'!B`A&4s8N'!qYq1& +!<<'!!<5ans8N(4rr<'!!!*#u"Q?Y6!!)Ng!lk;0`W#o +r;Q`s`rGr:-`@"E!!*'!!!*$!!<:D?!!#a?s3OI?!):i?!!*'!!!*$!!<<'!!<)rt!<3#u!"f/1 +!<:D?!!#a?rr<'!rr<&us8N'%rr<'!s8;rts8N'5rr<'!rr<'!!!*'!!!*$!!<<'!!;c`q!<<*! +!!*&r!"Jr.!<3$!s8UFGRcsePrVu`pq>^Hp`W#o +r;Q`s`rGr:-`@"E!!*'!!!*$!!<:D?!!#a?s3OI?!):i?!!*'!!!*$!!<<'!!<)rt!<3#u!"f/1 +!<:D?!!#a?rr<'!rr<&us8N'%rr<'!s8;rts8N'5rr<'!rr<'!!!*'!!!*$!!<<'!!;c`q!<<*! +!!*&r!"Jr.!<3$!s8UFGRcsePrVu`pq>^Hp`W#o +r;Q`s`rGr:-`@"E!!*'!!!*$!!<:D?!!#a?s3OI?!):i?!!*'!!!*$!!<<'!!<)rt!<3#u!"f/1 +!<:D?!!#a?rr<'!rr<&us8N'%rr<'!s8;rts8N'5rr<'!rr<'!!!*'!!!*$!!<<'!!;c`q!<<*! +!!*&r!"Jr.!<3$!s8UFGRcsePrVu`pq>^Hp`W#o +r;Q`s`rH&=qu6q8!<<'!B`A&4rr3)RVZ9Hjrt3q^!)an!<<'!!<3$!s8N'!s(DE4rr?a4!!*'!!!)lq#Yb=! +rr<'!9`Y+krrj5rr<&rs*t~> +r;Q`s`rH&=qu6q8!<<'!B`A&4rr3)RVZ9Hjrt3q^!)an!<<'!!<3$!s8N'!s(DE4rr?a4!!*'!!!)lq#Yb=! +rr<'!9`Y+krrj5rr<&rs*t~> +r;Q`s`rH&=qu6q8!<<'!B`A&4rr3)RVZ9Hjrt3q^!)an!<<'!!<3$!s8N'!s(DE4rr?a4!!*'!!!)lq#Yb=! +rr<'!9`Y+krrj5rr<&rs*t~> +r;Q`s`rH&=qu7qT!6<+[^&J'4s*Oh2n,R/%HiWF#!,2DG!6<+[^&J'4s8N'!rVults8Nb$!87AP +!<7EHl0n[drr<'!rr<&us8N'Err<%sciBtW!9q/s!<3$!s8N'!s1JEQ`rNgQ!!*'!!!*$!!<)p9 +VZ=cN!!*&)!6==(N;ikXrr<'!s%NLX`rH,2rrn>]l,Ne0`W#o +r;Q`s`rH&=qu7qT!6<+[^&J'4s*Oh2n,R/%HiWF#!,2DG!6<+[^&J'4s8N'!rVults8Nb$!87AP +!<7EHl0n[drr<'!rr<&us8N'Err<%sciBtW!9q/s!<3$!s8N'!s1JEQ`rNgQ!!*'!!!*$!!<)p9 +VZ=cN!!*&)!6==(N;ikXrr<'!s%NLX`rH,2rrn>]l,Ne0`W#o +r;Q`s`rH&=qu7qT!6<+[^&J'4s*Oh2n,R/%HiWF#!,2DG!6<+[^&J'4s8N'!rVults8Nb$!87AP +!<7EHl0n[drr<'!rr<&us8N'Err<%sciBtW!9q/s!<3$!s8N'!s1JEQ`rNgQ!!*'!!!*$!!<)p9 +VZ=cN!!*&)!6==(N;ikXrr<'!s%NLX`rH,2rrn>]l,Ne0`W#o +r;Q`s`rH&=qYqeG9hhqnrr<'!n8l2Udh9hhqnrr<'!rr<&ts8;p2B\EFc!!*&g +RK*>8l2T*1I/a0Hrr;uu,l[iEcqSofcqS3 +r;Q`s`rH&=qYqeG9hhqnrr<'!n8l2Udh9hhqnrr<'!rr<&ts8;p2B\EFc!!*&g +RK*>8l2T*1I/a0Hrr;uu,l[iEcqSofcqS3 +r;Q`s`rH&=qYqeG9hhqnrr<'!n8l2Udh9hhqnrr<'!rr<&ts8;p2B\EFc!!*&g +RK*>8l2T*1I/a0Hrr;uu,l[iEcqSofcqS3 +r;Q`sJcF:#!U49\rr<&rs*t~> +r;Q`sJcF:#!U49\rr<&rs*t~> +r;Q`sJcF:#!U49\rr<&rs*t~> +r;Q`sJcF:#!K?!#rr<&rs*t~> +r;Q`sJcF:#!K?!#rr<&rs*t~> +r;Q`sJcF:#!K?!#rr<&rs*t~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`soD\djrr;rtJcC<$q>UEpqu;0~> +r;Q`soD\djrr;rtJcC<$q>UEpqu;0~> +r;Q`soD\djrr;rtJcC<$q>UEpqu;0~> +r;Q`so`+pks8N'!rr2ruJcC<$qYpNqqu;0~> +r;Q`so`+pks8N'!rr2ruJcC<$qYpNqqu;0~> +r;Q`so`+pks8N'!rr2ruJcC<$qYpNqqu;0~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s8)`q!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s8)`q!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s8)`q!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s8)`q!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s8)`q!;leH~> +r;Q`sp&>0qrrE*!!<2uu!.k0$s8)`q!;leH~> +r;Q`spAY +r;Q`spAY +r;Q`spAY +r;Q`spAb$j!WN0!rr<&orr<%M^l?,0JGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<%M^l?,0JGK3F!;leH~> +r;Q`spAb$j!WN0!rr<&orr<%M^l?,0JGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^l?,0JGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^l?,0JGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<%M^l?,0JGK3F!;leH~> +r;Q`soD\djrr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`soD\djrr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sp&G!krr;osq#: +r;Q`sp&G!krr;osq#: +r;Q`sp&G!krr;osq#: +r;Q`spAY*mrr3'#s8N)lrr<%M^l?,0JGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<%M^l?,0JGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<%M^l?,0JGK3F!;leH~> +r;Q`so)AakrrD]k!!%ScNPGOEq>UEpqu;0~> +r;Q`so)AakrrD]k!!%ScNPGOEq>UEpqu;0~> +r;Q`so)AakrrD]k!!%ScNPGOEq>UEpqu;0~> +r;Q`so`+pks8W#tp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`so`+pks8W#tp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`so`+pks8W#tp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`so)A[ir;Q`squ?NnJ\[>^!.anF!!)orJ,~> +r;Q`so)A[ir;Q`squ?NnJ\[>^!.anF!!)orJ,~> +r;Q`so)A[ir;Q`squ?NnJ\[>^!.anF!!)orJ,~> +r;Q`so)A[ir;Q`sq#: +r;Q`so)A[ir;Q`sq#: +r;Q`so)A[ir;Q`sq#: +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!%ScNPGOEq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3nJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uYJ\[8\!.anF!!)orJ,~> +r;Q`sir8uY]>4%=J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>4%=J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>4%=J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`so`+pks8N'!rr2ruq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`so`+pks8N'!rr2ruq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`so`+pks8N'!rr2ruq#:+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`so)AakrrE&u!!)orqZ+=F!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ+=F!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ+=F!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`sp&G!krr;rtp\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;osq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;osq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;osq#:+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`spAY*mrr3'#s8N)lrr<&2^]4B.R/d5<^u3!.JGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<&2^]4B.R/d5<^u3!.JGK3F!;leH~> +r;Q`spAY*mrr3'#s8N)lrr<&2^]4B.rr<%M^u3!.JGK3F!;leH~> +r;Q`so)AakrrD]k!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrD]k!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrD]k!!'XH!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)A^js8;rlrr<&2^]4B.R/d5<^u3!.JGK3F!;leH~> +r;Q`so)A^js8;rlrr<&2^]4B.R/d5<^u3!.JGK3F!;leH~> +r;Q`so)A^js8;rlrr<&2^]4B.rr<%M^u3!.JGK3F!;leH~> +r;Q`soD\djqu6Wrqu?Nn]taUJp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`soD\djqu6Wrqu?Nn]taUJp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`soD\djqu6Wrqu?Nn]taUJpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`so`"mkqYpNqq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`so`"mkqYpNqq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`so`"mkqYpNqq#:+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#:+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#:+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3n]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHp6bm\J\^3Z!.anF!!)orJ,~> +r;Q`sp&G!krr;rtp\t3n]>+CHpAY*mJ\^3Z!.anF!!)orJ,~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`spAY*mrr3$"rrE&u!!)fo!!'XH!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)_\!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)fo!!'XH!!)`m!!%Sci4o>Cq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ+=F!!)_\!!)N(oDjHXrkJMaq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ+=F!!)_\!!)N(oDjHXrkJMaq>UEpqu;0~> +r;Q`so)AakrrE&u!!)orqZ+=F!!)`m!!)N(oDjHXrkJMaq>UEpqu;0~> +r;Q`soD\mms8N)urr<&orr<&2^]4B.R/d6V^]4B.R/d5<_#D+LJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<&2^]4B.R/d6V^]4B.R/d5<_#D+LJGK3F!;leH~> +r;Q`soD\mms8N)urr<&orr<&2^]4B.rr<&g^]4B.rr<%M_#D+LJGK3F!;leH~> +r;Q`so`"mkrr2rurr2ruq#:+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruq#:+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`so`"mkrr2rurr2ruq#:+CHpAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#:+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#:+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sp&>!lrVlitrr2ruq#:+CHpAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3n]>+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3n]>+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`spAb$js8W&up\t3n]>+CHpAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uY]>+CHp6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uY]>+CHpAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;*=\n%\o'p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;*=\n%\o'p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;*=\n%\o'pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`so`"mkrVufrq#: +r;Q`so`"mkrVufrq#: +r;Q`so`"mkrVufrq#:!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`sp&G$lrVlitp&>!lg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sp&G$lrVlitp&>!lg;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`sp&G$lrVlitp&>!lg;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`spAY0orrE&u!!)Zk!!(`g!!)\[!!)N(!!)_\!!)N(!!)_\!!%ScrkJMaq>UEpqu;0~> +r;Q`spAY0orrE&u!!)Zk!!(`g!!)\[!!)N(!!)_\!!)N(!!)_\!!%ScrkJMaq>UEpqu;0~> +r;Q`spAY0orrE&u!!)Zk!!(`g!!)]l!!)N(!!)`m!!)N(!!)`m!!%ScrkJMaq>UEpqu;0~> +r;Q`so`"mkrr;osp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`so`"mkrr;osp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\J\_9#!.anF!!)orJ,~> +r;Q`so`"mkrr;osp\t3ng;![gp&>!lnA##(pAY*mnA##(pAY*mJ\_9#!.anF!!)orJ,~> +r;Q`so`"mkqYpNqqu?NngqWmiopGd[nA##(p6bm\nA##(p6bm\n%ePqS\P5Uq>UEpqu;0~> +r;Q`so`"mkqYpNqqu?NngqWmiopGd[nA##(p6bm\nA##(p6bm\n%ePqS\P5Uq>UEpqu;0~> +r;Q`so`"mkqYpNqqu?NngqWmip&>!lnA##(pAY*mnA##(pAY*mn%ePqS\P5Uq>UEpqu;0~> +r;Q`so`"mkqYpNqq#:UEpqu;0~> +r;Q`so`"mkqYpNqq#:UEpqu;0~> +r;Q`so`"mkqYpNqq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEp +qu;0~> +r;Q`so`"mkrVuisp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sp&G$lrr2rurr2ruq#:UEp +qu;0~> +r;Q`sp&G$lrr2rurr2ruq#:UEp +qu;0~> +r;Q`sp&G$lrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEp +qu;0~> +r;Q`spAY0orrE&u!!*#u!!)fo!!(`g!!)\[!!)N(!!)_\!!)N(!!)_\!!)N(!!)\[!!&S*!.anF +!!)orJ,~> +r;Q`spAY0orrE&u!!*#u!!)fo!!(`g!!)\[!!)N(!!)_\!!)N(!!)_\!!)N(!!)\[!!&S*!.anF +!!)orJ,~> +r;Q`spAY0orrE&u!!*#u!!)fo!!(`g!!)]l!!)N(!!)`m!!)N(!!)`m!!)N(!!)]l!!&S*!.anF +!!)orJ,~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruqu?NngqWmiopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruqu?NngqWmiopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruqu?NngqWmip&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:UEp +qu;0~> +r;Q`so`"mkrr2rurr2ruq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEp +qu;0~> +r;Q`so`"mkrVuisp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`so`"mkrVuisp\t3ng;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[S\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lS\P5Uq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[n%ePq]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[n%ePq]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!ln%ePq]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sn,N=dq#:UEp +qu;0~> +r;Q`sn,N=dq#:UEp +qu;0~> +r;Q`sn,N=dq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sn,E@fp&>!lg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,E@fp&>!lg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,E@fp&>!lg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`snG`Igo`"mkg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snG`Igo`"mkg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snG`Igo`"mkg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`snGiFep\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snGiFep\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`snGiFep\t3ng;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sm/I%cqu?NngqWmiopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sm/I%cqu?NngqWmiopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sm/I%cqu?NngqWmip&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sm/I%cq#:UEp +qu;0~> +r;Q`sm/I%cq#:UEp +qu;0~> +r;Q`sm/I%cq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMt +q>UEpqu;0~> +r;Q`sn,N@ep\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,N@ep\t3ng;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEp +qu;0~> +r;Q`sn,N@ep\t3ng;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEp +qu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gopGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[]YFMtq>UEpqu;0~> +r;Q`sir8uYg;![gp&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l]YFMtq>UEpqu;0~> +r;Q`sir8uYq7uS%nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA+YrnA+Vq +q7lu\q>UEpqu;0~> +r;Q`sir8uYq7uS%nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA+YrnA+Vq +q7lu\q>UEpqu;0~> +r;Q`sir8uYq7uS%nA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA+YrnA+Vq +q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[nA##( +p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sir8uYq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!lnA##( +pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[ +nA##(p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1opGd[nA##(opGd[nA##(p6bm\nA##(p6bm\nA##(opGd[nA##(opGd[ +nA##(p6bm\nA##(opGd[q7lu\q>UEpqu;0~> +r;Q`sn,N@ep\t3nq7lt1p&>!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##(p&>!l +nA##(pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lnA##(p&>!lnA##(pAY*mnA##(pAY*mnA##(p&>!lnA##( +p&>!lnA##(pAY*mnA##(p&>!lq7lu\q>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1pAY*m +q7lt1q7lt1p&>!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1q>UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1pAY*m +q7lt1q7lt1p&>!lq7lt1q7lt1p&>!lq7lt1q7lt1pAY*mq7lt1q7lt1p&>!lq7lt1q>UEpqu;0~> +r;Q`snG`Igrr2ruqu;3IL]I8N!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IL]I8N!!)orJ,~> +r;Q`snG`Igrr2ruqu;3IL]I8N!!)orJ,~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`snG`Igrr2ruq#:UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)Zj8T)ZjSo2[jSo2[j8T)Zj8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)Zj8T)ZjSo2[jSo2[j8T)Zj8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sn,N@ep\t3nj8T)Zj8T)ZjSo2[jSo2[j8T)Zj8T)ZjSo2[j8T)Zq>UEpqu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sec5UKjSo2[jT#2Zjo>;[jo5;\jo>8Zk5YD\n,E@fr;Q`sjSo2[qu;0~> +r;Q`sec5UKjSo2[jT#2Zjo>;[jo5;\jo>8Zk5YD\n,E@fr;Q`sjSo2[qu;0~> +r;Q`sec5UKjSo2[jT#2Zjo>;[jo5;\jo>8Zk5YD\n,E@fr;Q`sjSo2[qu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukPkM^rr2rukPtP^jo5;\jSo2[rr2runGiLgrr;uujSo2[ +qu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukPkM^rr2rukPtP^jo5;\jSo2[rr2runGiLgrr;uujSo2[ +qu;0~> +r;Q`sf)G^Mrr2ruk5YG]jo5;\rr2rukPkM^rr2rukPtP^jo5;\jSo2[rr2runGiLgrr;uujSo2[ +qu;0~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)'Z!!)6_!W`6#k5PD]j8T)Zm/R(crr;uus8W&us8N3%rrE*! +rW)Qi!!)orJ,~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)'Z!!)6_!W`6#k5PD]j8T)Zm/R(crr;uus8W&us8N3%rrE*! +rW)Qi!!)orJ,~> +r;Q`sf)G^Mrr2rukPkS`rrD$X!!)'Z!!)6_!W`6#k5PD]j8T)Zm/R(crr;uus8W&us8N3%rrE*! +rW)Qi!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\iVrlXjo>>\kPkS`rrD3]r;c![r;c +r;Q`sf)G^Mrr2rujo5;\iVrlXjo>>\kPkS`rrD3]r;c![r;c +r;Q`sf)G^Mrr2rujo5;\iVrlXjo>>\kPkS`rrD3]r;c![r;c +r;Q`sf)G^Mrr2rujo5;\ir8uYir8uYl2Lhcs8N)Yrr<&^rr<&urr<&grs/W)!<3'!!<3&urrN3# +!<3#r!;-9k!;leH~> +r;Q`sf)G^Mrr2rujo5;\ir8uYir8uYl2Lhcs8N)Yrr<&^rr<&urr<&grs/W)!<3'!!<3&urrN3# +!<3#r!;-9k!;leH~> +r;Q`sf)G^Mrr2rujo5;\ir8uYir8uYl2Lhcs8N)Yrr<&^rr<&urr<&grs/W)!<3'!!<3&urrN3# +!<3#r!;-9k!;leH~> +r;Q`sf)G^Mrr2rujo5;\j8T)ZiVrlXl2UY]j8T)ZkPkM^rr2runG`aorrE'!rrE'!rr3$"rrE&u +!!)Ng!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\j8T)ZiVrlXl2UY]j8T)ZkPkM^rr2runG`aorrE'!rrE'!rr3$"rrE&u +!!)Ng!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\j8T)ZiVrlXl2UY]j8T)ZkPkM^rr2runG`aorrE'!rrE'!rr3$"rrE&u +!!)Ng!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jSo2[rr2ruk5PD]k5PD]rr2rukPkM^rr2runG`aos8N*!rrE'! +rr3$"rrE&u!!*#u!!)Zk!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jSo2[rr2ruk5PD]k5PD]rr2rukPkM^rr2runG`aos8N*!rrE'! +rr3$"rrE&u!!*#u!!)Zk!!)orJ,~> +r;Q`sf)G^Mrr2rujo5;\jSo2[jSo2[rr2ruk5PD]k5PD]rr2rukPkM^rr2runG`aos8N*!rrE'! +rr3$"rrE&u!!*#u!!)Zk!!)orJ,~> +r;Q`sec5UKjSo2[jo>5Yk5YD\jo5;\jo>;[jo>;[n,EXns8N*!rrE*!rW)uu!!)utrW)Qi!!)or +J,~> +r;Q`sec5UKjSo2[jo>5Yk5YD\jo5;\jo>;[jo>;[n,EXns8N*!rrE*!rW)uu!!)utrW)Qi!!)or +J,~> +r;Q`sec5UKjSo2[jo>5Yk5YD\jo5;\jo>;[jo>;[n,EXns8N*!rrE*!rW)uu!!)utrW)Qi!!)or +J,~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;Q`sJcC<$jSo2[qu;0~> +r;V +r;V +r;V +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +JcC<$fDg@~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/docsrc/nyquist/rampfig.ps b/docsrc/nyquist/rampfig.ps new file mode 100644 index 0000000..3cd9ba1 --- /dev/null +++ b/docsrc/nyquist/rampfig.ps @@ -0,0 +1,694 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 36 573 444 752 +%%Title: (rampfig-Layer#1) +%%Creator: (MacDraw II 1.1v2: LaserWriter 8 8.1.1) +%%CreationDate: (4:37 AM Sunday, January 24, 1904) +%%For: (Dannenberg) +%%Pages: 1 +%%DocumentFonts: Helvetica Courier +%%DocumentNeededFonts: Helvetica Courier +%%DocumentSuppliedFonts: +%%DocumentData: Clean7Bit +%%PageOrder: Ascend +%%Orientation: Portrait +%ADO_PaperArea: -129 -125 3171 2425 +%ADO_ImageableArea: 0 0 3042 2300 +%%EndComments +/md 154 dict def md begin +/currentpacking where {pop /sc_oldpacking currentpacking def true setpacking}if +%%BeginFile: adobe_psp_basic +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/bd{bind def}bind def +/xdf{exch def}bd +/xs{exch store}bd +/ld{load def}bd +/Z{0 def}bd +/T/true +/F/false +/:L/lineto +/lw/setlinewidth +/:M/moveto +/rl/rlineto +/rm/rmoveto +/:C/curveto +/:T/translate +/:K/closepath +/:mf/makefont +/gS/gsave +/gR/grestore +/np/newpath +14{ld}repeat +/$m matrix def +/av 81 def +/por true def +/normland false def +/psb-nosave{}bd +/pse-nosave{}bd +/us Z +/psb{/us save store}bd +/pse{us restore}bd +/level2 +/languagelevel where +{ +pop languagelevel 2 ge +}{ +false +}ifelse +def +/featurecleanup +{ +stopped +cleartomark +countdictstack exch sub dup 0 gt +{ +{end}repeat +}{ +pop +}ifelse +}bd +/noload Z +/startnoload +{ +{/noload save store}if +}bd +/endnoload +{ +{noload restore}if +}bd +level2 startnoload +/setjob +{ +statusdict/jobname 3 -1 roll put +}bd +/setcopies +{ +userdict/#copies 3 -1 roll put +}bd +level2 endnoload level2 not startnoload +/setjob +{ +1 dict begin/JobName xdf currentdict end setuserparams +}bd +/setcopies +{ +1 dict begin/NumCopies xdf currentdict end setpagedevice +}bd +level2 not endnoload +/pm Z +/mT Z +/sD Z +/realshowpage Z +/initializepage +{ +/pm save store mT concat +}bd +/endp +{ +pm restore showpage +}def +/$c/DeviceRGB def +/rectclip where +{ +pop/rC/rectclip ld +}{ +/rC +{ +np 4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +clip np +}bd +}ifelse +/rectfill where +{ +pop/rF/rectfill ld +}{ +/rF +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +fill +gR +}bd +}ifelse +/rectstroke where +{ +pop/rS/rectstroke ld +}{ +/rS +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +stroke +gR +}bd +}ifelse +%%EndFile +%%BeginFile: adobe_psp_colorspace_level1 +%%Copyright: Copyright 1991-1993 Adobe Systems Incorporated. All Rights Reserved. +/G/setgray ld +/:F/setrgbcolor ld +%%EndFile +%%BeginFile: adobe_psp_uniform_graphics +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/@a +{ +np :M 0 rl :L 0 exch rl 0 rl :L fill +}bd +/@b +{ +np :M 0 rl 0 exch rl :L 0 rl 0 exch rl fill +}bd +/arct where +{ +pop +}{ +/arct +{ +arcto pop pop pop pop +}bd +}ifelse +/x1 Z +/x2 Z +/y1 Z +/y2 Z +/rad Z +/@q +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +fill +}bd +/@s +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +:K +stroke +}bd +/@i +{ +np 0 360 arc fill +}bd +/@j +{ +gS +np +:T +scale +0 0 .5 0 360 arc +fill +gR +}bd +/@e +{ +np +0 360 arc +:K +stroke +}bd +/@f +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 0 360 arc +:K +$m setmatrix +stroke +}bd +/@k +{ +gS +np +:T +0 0 :M +0 0 5 2 roll +arc fill +gR +}bd +/@l +{ +gS +np +:T +0 0 :M +scale +0 0 .5 5 -2 roll arc +fill +gR +}bd +/@m +{ +np +arc +stroke +}bd +/@n +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 5 -2 roll arc +$m setmatrix +stroke +}bd +%%EndFile +%%BeginFile: adobe_psp_customps +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/$t Z +/$p Z +/$s Z +/$o 1. def +/2state? false def +/ps Z +level2 startnoload +/pushcolor/currentrgbcolor ld +/popcolor/setrgbcolor ld +/setcmykcolor where +{ +pop/currentcmykcolor where +{ +pop/pushcolor/currentcmykcolor ld +/popcolor/setcmykcolor ld +}if +}if +level2 endnoload level2 not startnoload +/pushcolor +{ +currentcolorspace $c eq +{ +currentcolor currentcolorspace true +}{ +currentcmykcolor false +}ifelse +}bd +/popcolor +{ +{ +setcolorspace setcolor +}{ +setcmykcolor +}ifelse +}bd +level2 not endnoload +/pushstatic +{ +ps +2state? +$o +$t +$p +$s +}bd +/popstatic +{ +/$s xs +/$p xs +/$t xs +/$o xs +/2state? xs +/ps xs +}bd +/pushgstate +{ +save errordict/nocurrentpoint{pop 0 0}put +currentpoint +3 -1 roll restore +pushcolor +currentlinewidth +currentlinecap +currentlinejoin +currentdash exch aload length +np clippath pathbbox +$m currentmatrix aload pop +}bd +/popgstate +{ +$m astore setmatrix +2 index sub exch +3 index sub exch +rC +array astore exch setdash +setlinejoin +setlinecap +lw +popcolor +np :M +}bd +/bu +{ +pushgstate +gR +pushgstate +2state? +{ +gR +pushgstate +}if +pushstatic +pm restore +mT concat +}bd +/bn +{ +/pm save store +popstatic +popgstate +gS +popgstate +2state? +{ +gS +popgstate +}if +}bd +/cpat{pop 64 div G 8{pop}repeat}bd +%%EndFile +%%BeginFile: adobe_psp_basic_text +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/S/show ld +/A{ +0.0 exch ashow +}bd +/R{ +0.0 exch 32 exch widthshow +}bd +/W{ +0.0 3 1 roll widthshow +}bd +/J{ +0.0 32 4 2 roll 0.0 exch awidthshow +}bd +/V{ +0.0 4 1 roll 0.0 exch awidthshow +}bd +/fcflg true def +/fc{ +fcflg{ +vmstatus exch sub 50000 lt{ +(%%[ Warning: Running out of memory ]%%\r)print flush/fcflg false store +}if pop +}if +}bd +/$f[1 0 0 -1 0 0]def +/:ff{$f :mf}bd +/MacEncoding StandardEncoding 256 array copy def +MacEncoding 39/quotesingle put +MacEncoding 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/space/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand +/Acircumflex/Ecircumflex/Aacute/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave +/Oacute/Ocircumflex/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +MacEncoding 128 128 getinterval astore pop +level2 startnoload +/copyfontdict +{ +findfont dup length dict +begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +}bd +level2 endnoload level2 not startnoload +/copyfontdict +{ +findfont dup length dict +copy +begin +}bd +level2 not endnoload +md/fontname known not{ +/fontname/customfont def +}if +/Encoding Z +/:mre +{ +copyfontdict +/Encoding MacEncoding def +fontname currentdict +end +definefont :ff def +}bd +/:bsr +{ +copyfontdict +/Encoding Encoding 256 array copy def +Encoding dup +}bd +/pd{put dup}bd +/:esr +{ +pop pop +fontname currentdict +end +definefont :ff def +}bd +/scf +{ +scalefont def +}bd +/scf-non +{ +$m scale :mf setfont +}bd +/ps Z +/fz{/ps xs}bd +/sf/setfont ld +/cF/currentfont ld +/mbf +{ +/makeblendedfont where +{ +pop +makeblendedfont +/ABlend exch definefont +}{ +pop +}ifelse +def +}def +%%EndFile +%%BeginFile: adobe_psp_dashes +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/:q/setdash ld +/:r{ +np +:M +:L +stroke +}bd +/nodash[]def +/qdenddash +{ +nodash 0 setdash +}bd +%%EndFile +/currentpacking where {pop sc_oldpacking setpacking}if +end % md +%%EndProlog +%%BeginSetup +md begin +/pT[1 0 0 -1 29.999 761.009]def/mT[.24 0 0 -.24 29.999 761.009]def +/sD 16 dict def +%%IncludeFont: Helvetica +%%IncludeFont: Courier +/f0_1/Helvetica :mre +/f0_58 f0_1 58 scf +/f1_1/Courier :mre +/f1_58 f1_1 58 scf +/Courier findfont[10 0 0 -10 0 0]:mf setfont +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +initializepage +%%EndPageSetup +gS 0 0 2300 3042 rC +0 0 :M +0 setlinecap +currentscreen +3 1 roll pop pop 60 45 3 -1 roll setscreen +np 150 38 :M +165 96 :L +150 96 :L +135 96 :L +150 38 :L +eofill +-4 -4 152 602 4 4 148 94 @b +np 750 600 :M +691 615 :L +691 600 :L +691 585 :L +750 600 :L +4 lw +eofill +148 602 -4 4 693 598 4 148 598 @a +-8 -8 154 604 8 8 559 184 @b +559 192 -8 8 604 596 8 559 184 @a +111 152 -4 4 152 148 4 111 148 @a +-4 -4 602 640 4 4 598 598 @b +[20.833 16.667 ] 0 :q +675 150 150 150 :r +39 179 :M +f0_58 sf +(1)S +47 634 :M +(0)S +572 709 :M +(1)S +[8.333 8.333 ] 0 :q +600 150 563 188 :r +600 600 600 150 :r +np 1125 38 :M +1140 96 :L +1125 96 :L +1110 96 :L +1125 38 :L +[] 0 :q +eofill +-4 -4 1127 602 4 4 1123 94 @b +np 1725 600 :M +1666 615 :L +1666 600 :L +1666 585 :L +1725 600 :L +eofill +1123 602 -4 4 1668 598 4 1123 598 @a +-8 -8 1129 604 8 8 1571 146 @b +1571 154 -8 8 1617 596 8 1571 146 @a +1086 152 -4 4 1127 148 4 1086 148 @a +-4 -4 1577 640 4 4 1573 598 @b +[20.833 16.667 ] 0 :q +1650 150 1125 150 :r +1014 179 :M +(1)S +1022 634 :M +(0)S +1547 709 :M +(1)S +151 763 :M +f1_58 sf +-.071(\(pwl 1 1 1\))A +1276 763 :M +-.15(\(ramp\))A +29 30 450.5 300 @j +[] 0 :q +29 30 450.5 300 @f +29 30 375.5 375 @j +29 30 375.5 375 @f +29 30 337.5 413 @j +29 30 337.5 413 @f +29 30 300.5 450 @j +29 30 300.5 450 @f +29 30 262.5 488 @j +29 30 262.5 488 @f +29 30 225.5 525 @j +29 30 225.5 525 @f +29 30 187.5 563 @j +29 30 187.5 563 @f +29 30 487.5 263 @j +29 30 487.5 263 @f +29 30 412.5 338 @j +29 30 412.5 338 @f +28 30 525 225 @j +28 30 525 225 @f +562.5 187.5 14.5 @i +562.5 187.5 14.5 @e +1 G +28 30 600 150 @j +0 G +8 lw +28 30 600 150 @f +1 G +28 30 600 600 @j +0 G +28 30 600 600 @f +28 30 150 600 @j +4 lw +28 30 150 600 @f +28 30 1125 600 @j +28 30 1125 600 @f +28 30 1200 525 @j +28 30 1200 525 @f +1162.5 562.5 14.5 @i +1162.5 562.5 14.5 @e +1237.5 487.5 14.5 @i +1237.5 487.5 14.5 @e +28 30 1275 450 @j +28 30 1275 450 @f +1312.5 412.5 14.5 @i +1312.5 412.5 14.5 @e +28 30 1350 375 @j +28 30 1350 375 @f +1387.5 337.5 14.5 @i +1387.5 337.5 14.5 @e +28 30 1425 300 @j +28 30 1425 300 @f +1462.5 262.5 14.5 @i +1462.5 262.5 14.5 @e +28 30 1500 225 @j +28 30 1500 225 @f +1537.5 187.5 14.5 @i +1537.5 187.5 14.5 @e +28 30 1575 150 @j +28 30 1575 150 @f +1 G +29 30 1612.5 600 @j +0 G +8 lw +29 30 1612.5 600 @f +4 lw +[20.833 16.667 ] 0 :q +1575 600 1575 150 :r +endp +%%Trailer +end % md +%%EOF diff --git a/docsrc/nyquist/shifttimefig.ps b/docsrc/nyquist/shifttimefig.ps new file mode 100644 index 0000000..ce457db --- /dev/null +++ b/docsrc/nyquist/shifttimefig.ps @@ -0,0 +1,643 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 35 522 418 752 +%%Title: (shifttimefig-Layer#1) +%%Creator: (MacDraw II 1.1v2: LaserWriter 8 8.1.1) +%%CreationDate: (10:26 PM Sunday, January 24, 1904) +%%For: (Dannenberg) +%%Pages: 1 +%%DocumentFonts: Courier +%%DocumentNeededFonts: Courier +%%DocumentSuppliedFonts: +%%DocumentData: Clean7Bit +%%PageOrder: Ascend +%%Orientation: Portrait +%ADO_PaperArea: -129 -125 3171 2425 +%ADO_ImageableArea: 0 0 3042 2300 +%%EndComments +/md 148 dict def md begin +/currentpacking where {pop /sc_oldpacking currentpacking def true setpacking}if +%%BeginFile: adobe_psp_basic +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/bd{bind def}bind def +/xdf{exch def}bd +/xs{exch store}bd +/ld{load def}bd +/Z{0 def}bd +/T/true +/F/false +/:L/lineto +/lw/setlinewidth +/:M/moveto +/rl/rlineto +/rm/rmoveto +/:C/curveto +/:T/translate +/:K/closepath +/:mf/makefont +/gS/gsave +/gR/grestore +/np/newpath +14{ld}repeat +/$m matrix def +/av 81 def +/por true def +/normland false def +/psb-nosave{}bd +/pse-nosave{}bd +/us Z +/psb{/us save store}bd +/pse{us restore}bd +/level2 +/languagelevel where +{ +pop languagelevel 2 ge +}{ +false +}ifelse +def +/featurecleanup +{ +stopped +cleartomark +countdictstack exch sub dup 0 gt +{ +{end}repeat +}{ +pop +}ifelse +}bd +/noload Z +/startnoload +{ +{/noload save store}if +}bd +/endnoload +{ +{noload restore}if +}bd +level2 startnoload +/setjob +{ +statusdict/jobname 3 -1 roll put +}bd +/setcopies +{ +userdict/#copies 3 -1 roll put +}bd +level2 endnoload level2 not startnoload +/setjob +{ +1 dict begin/JobName xdf currentdict end setuserparams +}bd +/setcopies +{ +1 dict begin/NumCopies xdf currentdict end setpagedevice +}bd +level2 not endnoload +/pm Z +/mT Z +/sD Z +/realshowpage Z +/initializepage +{ +/pm save store mT concat +}bd +/endp +{ +pm restore showpage +}def +/$c/DeviceRGB def +/rectclip where +{ +pop/rC/rectclip ld +}{ +/rC +{ +np 4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +clip np +}bd +}ifelse +/rectfill where +{ +pop/rF/rectfill ld +}{ +/rF +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +fill +gR +}bd +}ifelse +/rectstroke where +{ +pop/rS/rectstroke ld +}{ +/rS +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +stroke +gR +}bd +}ifelse +%%EndFile +%%BeginFile: adobe_psp_colorspace_level1 +%%Copyright: Copyright 1991-1993 Adobe Systems Incorporated. All Rights Reserved. +/G/setgray ld +/:F/setrgbcolor ld +%%EndFile +%%BeginFile: adobe_psp_uniform_graphics +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/@a +{ +np :M 0 rl :L 0 exch rl 0 rl :L fill +}bd +/@b +{ +np :M 0 rl 0 exch rl :L 0 rl 0 exch rl fill +}bd +/arct where +{ +pop +}{ +/arct +{ +arcto pop pop pop pop +}bd +}ifelse +/x1 Z +/x2 Z +/y1 Z +/y2 Z +/rad Z +/@q +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +fill +}bd +/@s +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +:K +stroke +}bd +/@i +{ +np 0 360 arc fill +}bd +/@j +{ +gS +np +:T +scale +0 0 .5 0 360 arc +fill +gR +}bd +/@e +{ +np +0 360 arc +:K +stroke +}bd +/@f +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 0 360 arc +:K +$m setmatrix +stroke +}bd +/@k +{ +gS +np +:T +0 0 :M +0 0 5 2 roll +arc fill +gR +}bd +/@l +{ +gS +np +:T +0 0 :M +scale +0 0 .5 5 -2 roll arc +fill +gR +}bd +/@m +{ +np +arc +stroke +}bd +/@n +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 5 -2 roll arc +$m setmatrix +stroke +}bd +%%EndFile +%%BeginFile: adobe_psp_customps +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/$t Z +/$p Z +/$s Z +/$o 1. def +/2state? false def +/ps Z +level2 startnoload +/pushcolor/currentrgbcolor ld +/popcolor/setrgbcolor ld +/setcmykcolor where +{ +pop/currentcmykcolor where +{ +pop/pushcolor/currentcmykcolor ld +/popcolor/setcmykcolor ld +}if +}if +level2 endnoload level2 not startnoload +/pushcolor +{ +currentcolorspace $c eq +{ +currentcolor currentcolorspace true +}{ +currentcmykcolor false +}ifelse +}bd +/popcolor +{ +{ +setcolorspace setcolor +}{ +setcmykcolor +}ifelse +}bd +level2 not endnoload +/pushstatic +{ +ps +2state? +$o +$t +$p +$s +}bd +/popstatic +{ +/$s xs +/$p xs +/$t xs +/$o xs +/2state? xs +/ps xs +}bd +/pushgstate +{ +save errordict/nocurrentpoint{pop 0 0}put +currentpoint +3 -1 roll restore +pushcolor +currentlinewidth +currentlinecap +currentlinejoin +currentdash exch aload length +np clippath pathbbox +$m currentmatrix aload pop +}bd +/popgstate +{ +$m astore setmatrix +2 index sub exch +3 index sub exch +rC +array astore exch setdash +setlinejoin +setlinecap +lw +popcolor +np :M +}bd +/bu +{ +pushgstate +gR +pushgstate +2state? +{ +gR +pushgstate +}if +pushstatic +pm restore +mT concat +}bd +/bn +{ +/pm save store +popstatic +popgstate +gS +popgstate +2state? +{ +gS +popgstate +}if +}bd +/cpat{pop 64 div G 8{pop}repeat}bd +%%EndFile +%%BeginFile: adobe_psp_basic_text +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/S/show ld +/A{ +0.0 exch ashow +}bd +/R{ +0.0 exch 32 exch widthshow +}bd +/W{ +0.0 3 1 roll widthshow +}bd +/J{ +0.0 32 4 2 roll 0.0 exch awidthshow +}bd +/V{ +0.0 4 1 roll 0.0 exch awidthshow +}bd +/fcflg true def +/fc{ +fcflg{ +vmstatus exch sub 50000 lt{ +(%%[ Warning: Running out of memory ]%%\r)print flush/fcflg false store +}if pop +}if +}bd +/$f[1 0 0 -1 0 0]def +/:ff{$f :mf}bd +/MacEncoding StandardEncoding 256 array copy def +MacEncoding 39/quotesingle put +MacEncoding 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/space/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand +/Acircumflex/Ecircumflex/Aacute/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave +/Oacute/Ocircumflex/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +MacEncoding 128 128 getinterval astore pop +level2 startnoload +/copyfontdict +{ +findfont dup length dict +begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +}bd +level2 endnoload level2 not startnoload +/copyfontdict +{ +findfont dup length dict +copy +begin +}bd +level2 not endnoload +md/fontname known not{ +/fontname/customfont def +}if +/Encoding Z +/:mre +{ +copyfontdict +/Encoding MacEncoding def +fontname currentdict +end +definefont :ff def +}bd +/:bsr +{ +copyfontdict +/Encoding Encoding 256 array copy def +Encoding dup +}bd +/pd{put dup}bd +/:esr +{ +pop pop +fontname currentdict +end +definefont :ff def +}bd +/scf +{ +scalefont def +}bd +/scf-non +{ +$m scale :mf setfont +}bd +/ps Z +/fz{/ps xs}bd +/sf/setfont ld +/cF/currentfont ld +/mbf +{ +/makeblendedfont where +{ +pop +makeblendedfont +/ABlend exch definefont +}{ +pop +}ifelse +def +}def +%%EndFile +/currentpacking where {pop sc_oldpacking setpacking}if +end % md +%%EndProlog +%%BeginSetup +md begin +/pT[1 0 0 -1 29.999 761.009]def/mT[.24 0 0 -.24 29.999 761.009]def +/sD 16 dict def +%%IncludeFont: Courier +/f0_1/Courier :mre +/f0_58 f0_1 58 scf +/Courier findfont[10 0 0 -10 0 0]:mf setfont +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +initializepage +%%EndPageSetup +gS 0 0 2300 3042 rC +0 0 :M +0 setlinecap +currentscreen +3 1 roll pop pop 60 45 3 -1 roll setscreen +np 38 38 :M +52 96 :L +38 96 :L +23 96 :L +38 38 :L +eofill +-4 -4 40 265 4 4 36 94 @b +np 1613 263 :M +1554 277 :L +1554 263 :L +1554 248 :L +1613 263 :L +4 lw +eofill +36 265 -4 4 1556 261 4 36 261 @a +36 261 :M +2 setlinecap +8 lw +44 263 :M +71.332 234.996 97.498 217.497 122.5 210.5 :C +147.498 203.497 167.664 202.83 183 208.5 :C +198.331 214.164 216.496 209.33 237.5 194 :C +258.497 178.664 277.995 165.498 296 154.5 :C +313.996 143.498 331.995 140.664 350 146 :C +367.995 151.331 382.494 157.497 393.5 164.5 :C +404.494 171.498 419.16 173.664 437.5 171 :C +455.827 168.331 471.826 173.83 485.5 187.5 :C +499.159 201.164 519.991 210.83 548 216.5 :C +575.992 222.163 595.491 222.997 606.5 219 :C +617.491 214.997 640.323 226.163 675 252.5 :C +709.657 278.83 735.655 296.495 753 305.5 :C +770.322 314.495 791.821 321.328 817.5 326 :C +843.154 330.662 866.486 324.995 887.5 309 :C +908.487 292.995 928.985 287.829 949 293.5 :C +968.986 299.162 985.318 300.329 998 297 :C +1010.652 293.662 1027.984 289.162 1050 283.5 :C +1071.984 277.829 1110.316 270.996 1165 263 :C +stroke +1083 275 :M +0 setlinecap +np 38 638 :M +52 696 :L +38 696 :L +23 696 :L +38 638 :L +eofill +-4 -4 40 865 4 4 36 694 @b +np 1613 863 :M +1554 877 :L +1554 863 :L +1554 848 :L +1613 863 :L +4 lw +eofill +36 865 -4 4 1556 861 4 36 861 @a +36 861 :M +2 setlinecap +8 lw +344 863 :M +371.328 834.987 397.493 817.488 422.5 810.5 :C +447.494 803.488 467.659 802.821 483 808.5 :C +498.326 814.154 516.492 809.321 537.5 794 :C +558.492 778.654 577.991 765.489 596 754.5 :C +613.991 743.488 631.99 740.655 650 746 :C +667.99 751.322 682.489 757.488 693.5 764.5 :C +704.489 771.488 719.155 773.655 737.5 771 :C +755.822 768.322 771.821 773.821 785.5 787.5 :C +799.155 801.155 819.987 810.821 848 816.5 :C +875.987 822.154 895.486 822.988 906.5 819 :C +917.486 814.987 940.318 826.153 975 852.5 :C +1009.652 878.821 1035.65 896.486 1053 905.5 :C +1070.317 914.486 1091.816 921.319 1117.5 926 :C +1143.15 930.653 1166.482 924.986 1187.5 909 :C +1208.482 892.986 1228.981 887.82 1249 893.5 :C +1268.981 899.153 1285.313 900.32 1298 897 :C +1310.647 893.653 1327.979 889.153 1350 883.5 :C +1371.98 877.82 1410.312 870.987 1465 863 :C +stroke +1383 875 :M +0 setlinecap +np 338 525 :M +268 542 :L +268 525 :L +268 508 :L +338 525 :L +eofill +37 529 -8 8 272 521 8 37 521 @a +-4 -4 40 565 4 4 36 486 @b +-4 -4 340 565 4 4 336 486 @b +39 375 :M +f0_58 sf +-.187(snd)A +1 G +71 492 171 62 rF +72 538 :M +0 G +(shift)S +30 975 :M +-.019(\(shift-time snd shift\))A +endp +%%Trailer +end % md +%%EOF diff --git a/docsrc/nyquist/test.ps b/docsrc/nyquist/test.ps new file mode 100644 index 0000000..7d35dc5 --- /dev/null +++ b/docsrc/nyquist/test.ps @@ -0,0 +1,1020 @@ +%!PS-Adobe-2.0 +%%Title: test.mss +%%DocumentFonts: (atend) +%%Creator: Roger Dannenberg and Scribe 7(1700) +%%CreationDate: 18 December 1996 16:16 +%%Pages: (atend) +%%EndComments +% PostScript Prelude for Scribe. +/BS {/SV save def 0.0 792.0 translate .01 -.01 scale} bind def +/ES {showpage SV restore} bind def +/SC {setrgbcolor} bind def +/FMTX matrix def +/RDF {WFT SLT 0.0 eq + {SSZ 0.0 0.0 SSZ neg 0.0 0.0 FMTX astore} + {SSZ 0.0 SLT neg sin SLT cos div SSZ mul SSZ neg 0.0 0.0 FMTX astore} + ifelse makefont setfont} bind def +/SLT 0.0 def +/SI { /SLT exch cvr def RDF} bind def +/WFT /Courier findfont def +/SF { /WFT exch findfont def RDF} bind def +/SSZ 1000.0 def +/SS { /SSZ exch 100.0 mul def RDF} bind def +/AF { /WFT exch findfont def /SSZ exch 100.0 mul def RDF} bind def +/MT /moveto load def +/XM {currentpoint exch pop moveto} bind def +/UL {gsave newpath moveto dup 2.0 div 0.0 exch rmoveto + setlinewidth 0.0 rlineto stroke grestore} bind def +/LH {gsave newpath moveto setlinewidth + 0.0 rlineto + gsave stroke grestore} bind def +/LV {gsave newpath moveto setlinewidth + 0.0 exch rlineto + gsave stroke grestore} bind def +/BX {gsave newpath moveto setlinewidth + exch + dup 0.0 rlineto + exch 0.0 exch neg rlineto + neg 0.0 rlineto + closepath + gsave stroke grestore} bind def +/BX1 {grestore} bind def +/BX2 {setlinewidth 1 setgray stroke grestore} bind def +/PB {/PV save def newpath 3 -1 roll sub translate + 100.0 -100.0 scale /showpage {} def} bind def +/PE {PV restore} bind def +/GB {/PV save def newpath translate rotate + div dup scale 100.0 -100.0 scale + /showpage {} def + /letter {} def + /lettersmall {} def + /note {} def + } bind def +/GE {PV restore} bind def +/FB {dict dup /FontMapDict exch def begin} bind def +/FM {cvn exch cvn exch def} bind def +/FE {end /original-findfont /findfont load def /findfont + {dup FontMapDict exch known{FontMapDict exch get} if + original-findfont} def} bind def +/BC {gsave moveto dup 0 exch rlineto exch 0 rlineto neg 0 exch rlineto closepath clip} bind def +/EC /grestore load def +/SH /show load def +/MX {exch show 0.0 rmoveto} bind def +/W {0 32 4 -1 roll widthshow} bind def +/WX {0 32 5 -1 roll widthshow 0.0 rmoveto} bind def +/RC {100.0 -100.0 scale +612.0 0.0 translate +-90.0 rotate +.01 -.01 scale} bind def +/URC {100.0 -100.0 scale +90.0 rotate +-612.0 0.0 translate +.01 -.01 scale} bind def +/RCC {100.0 -100.0 scale +0.0 -792.0 translate 90.0 rotate +.01 -.01 scale} bind def +/URCC {100.0 -100.0 scale +-90.0 rotate 0.0 792.0 translate +.01 -.01 scale} bind def + + +% Scribe Systems version of LaserPrep v5.2 +% All lines added/changed by Scribe Systems contain "%UNI" +% +%{appledict version #65 +% CopyRight Apple Computer, Inc. 1984,1985,1986,1987 All Rights Reserved. +systemdict/currentpacking known{currentpacking true setpacking}if +/LW{save statusdict/product get(LaserWriter)anchorsearch +exch pop{length 0 eq{1}{2}ifelse}{0}ifelse exch restore}bind def +/LW+{LW 2 eq}bind def +/ok{systemdict/statusdict known dup{LW 0 gt and}if}bind def +%UNI ok{statusdict begin 9 sccinteractive 3 ne exch 0 ne or{9 0 3 setsccinteractive}if end}if +/md 250 dict def md begin +/av 65 def +/T true def +/F false def +/mtx matrix def +/s75 75 string def +/s8 8 string def +/s1 ( ) def +/pxs 1 def +/pys 1 def +1 0 mtx defaultmatrix dtransform exch atan/pa exch def +/nlw .24 def +/ppr [-32 -29.52 762 582.48] def % default printable page rectangle +/pgs 1 def +/por true def +/xb 500 array def +/so true def +/fillflag false def +/pnm 1 def +/fmv true def +/sfl false def +/ma 0 def +/invertflag false def +/xflip false def +/yflip false def +/noflips true def +/scaleby96 false def +/fNote true def +/fBitStretch true def +/fg (Rvd\001\001\000\000\177) def +/bdf{bind def}bind def +/xdf{exch def}bdf +/xl{neg exch neg translate}bdf +/fp{pnsh 0 ne pnsv 0 ne and}bdf +/nop{}bdf/lnop[/nop load]cvx bdf +/vrb[ +{fp{gsave 1 setlinewidth pnsh pnsv scale stroke grestore}if newpath}bind +/eofill load +dup +/newpath load +2 index +dup +{clip newpath}bind +{}bind +dup +2 copy +]def +currentscreen/spf xdf/rot xdf/freq xdf +/doop{vrb exch get exec}bdf + +% psu - page setup called at begining of page +% args: smooth, por, bbs1, bbs2, bbey, bbex, scale, dpix, dpiy, pgs, +% invert, xflip, yflip, scaleby96, fBitStretch, fNote +% +% smooth is T if smoothing was selected in page setup, else F +% por is T for portrait orientation, F for landscape +% bbs2 seems to be offset for start of image area (in 72nds of an inch) +% bbs1 seems to be offset for start of image area (in 72nds of an inch) +% bbey is length (or end?) of printable area in 72nd of an inch +% bbex is width (or end?) of printable area in 72nd of an inch +% dpix is dots per inch of coordinate system +% dpiy is dots per inch of coordinate system +% scale is scale factor selected in page setup +% pgs is a small integer denoting paper cassette type (legal, a4, etc.) +% invert is T to reverse black/white +% xflip is T to rotate image horizontally +% yflip is T to rotate image vertically +% scaleby96 is T if "Precision Bitmap Graphics" requested +% fBitStretch is T if "Faster Bitmap Printing" requested +% fNote is T to use small imageable region, F to use large +/psu{ pop + /fNote xdf + /fBitStretch xdf + /scaleby96 xdf + pop F %UNI force yflip off + /yflip xdf + pop F %UNI force xflip off + /xflip xdf + pop F %UNI force black/white reversing off + /invertflag xdf + xflip yflip or{/noflips false def}if + /pgs xdf % set pgs + 2 index % get copy of scale + .72 mul exch div /pys xdf % pys = (.72 * scale) / dpiy + % S: smooth por bbs1 bbs2 bbey bbex scale dpix + div .72 mul /pxs xdf % pxs = .72 * (scale / dpix) + 2 index pxs mul 4 index pys mul neg translate %UNI xlate for scribe + ppr astore pop % put "bbs1 bbs2 bbey bbex" into ppr + pop T %UNI force portrait on + /por xdf % set por + pop F %UNI force smooth request off + sn and /so xdf % set "so" T if smooth req'd AND avail in LW +}bdf + +/txpose{ +%UNI don't change paper type +%UNI fNote{smalls}{bigs}ifelse pgs get exec + pxs pys scale + ppr aload pop + por + { + noflips{pop exch neg exch translate pop 1 -1 scale}if + xflip yflip and{ + pop exch neg exch translate + 180 rotate + 1 -1 scale + ppr 3 get + ppr 1 get neg sub neg + ppr 2 get + ppr 0 get neg sub neg + translate + }if + xflip yflip not and{ + pop exch neg exch translate pop + 180 rotate + ppr 3 get + ppr 1 get neg sub neg 0 + translate + }if + yflip xflip not and{ + ppr 1 get neg + ppr 0 get neg + translate + }if + } + { + noflips{translate pop pop 270 rotate 1 -1 scale}if + xflip yflip and{ + translate pop pop + 90 rotate + 1 -1 scale + ppr 3 get + ppr 1 get neg sub neg + ppr 2 get + ppr 0 get neg sub neg + translate + }if + xflip yflip not and{ + translate + pop pop 90 rotate + ppr 3 get + ppr 1 get neg sub neg 0 + translate + }if + yflip xflip not and{ + translate + pop pop 270 rotate + ppr 2 get + ppr 0 get neg sub neg 0 exch + translate + }if + } + ifelse + %UNI statusdict begin waittimeout 300 lt{/waittimeout 300 def}if end + scaleby96{ + ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy + translate + .96 dup scale + neg exch neg exch translate + }if +}bdf + +/fr{3 index 3 index xl ppr aload pop 3 -1 roll 2 mul add 3 1 roll exch 2 mul add +6 2 roll 3 -1 roll sub 3 1 roll exch sub 3 1 roll exch 3 -1 roll div 3 1 roll div exch scale}bdf +/lws{show}bdf +/tv{show pop pop}bdf +/obl{{0.212557 mul}{pop 0}ifelse}bdf +/sfd{ps fg 5 -1 roll get mul 100 div 0 ps 5 -1 roll obl ps neg 0 0 6a astore makefont setfont}bdf +/fnt{findfont sfd}bdf +/bt{sa 3 1 roll 3 index and put}bdf +/sa(\000\000\000\000\000\000\000\000\000\000)def +/fs{0 1 bt 1 2 bt 2 4 bt 3 8 bt 4 16 bt 5 32 bt 6 64 bt 7 128 bt sa exch 8 exch put}bdf +/mx1 matrix def +/mx2 matrix def +/mx3 matrix def +/bu{currentpoint currentgray currentlinewidth currentlinecap currentlinejoin currentdash exch aload length +fg 5 sfl{1}{0}ifelse put pnsv pnsh +2t aload pop 3a aload pop mx2 aload pop mx1 aload pop mtx currentmatrix aload pop +mx3 aload pop ps pm restore/ps xdf mx3 astore pop}bdf +/bn{/pm save def mx3 setmatrix newpath 0 0 moveto ct dup 39 get 0 exch getinterval cvx exec +mtx astore setmatrix mx1 astore pop mx2 astore pop 3a astore pop +2t astore pop/pnsh xdf/pnsv xdf gw +/sfl fg 5 get 0 ne def array astore exch setdash setlinejoin setlinecap +setlinewidth setgray moveto}bdf +/fc{save vmstatus exch sub 50000 lt +{(%%[|0|]%%)=print flush}if pop restore}bdf +/tc{32768 div add 3 1 roll 32768 div add 2t astore pop}bdf +/3a [0 0 0] def +/2t 2 array def +/tp{3a astore pop}bdf +/tt{mx2 currentmatrix pop currentpoint 2 copy 2t aload pop qa 2 copy translate 3a aload pop exch dup 0 eq +{pop}{1 eq{-1 1}{1 -1}ifelse scale}ifelse rotate pop neg exch neg exch translate moveto}bdf +/te{mx2 setmatrix}bdf +/th{3 -1 roll div 3 1 roll exch div 2 copy mx1 scale pop scale/sfl true def}bdf +/tu{1 1 mx1 itransform scale/sfl false def}bdf +/ts{1 1 mx1 transform scale/sfl true def}bdf +/fz{/ps xdf}bdf +/dv{dup 0 ne{div}{pop}ifelse}bdf +/pop4{pop pop pop pop}bdf +/it{sfl{mx1 itransform}if}bdf +/gm{exch it moveto}bdf/rm{it rmoveto}bdf +/lm{currentpoint sfl{mx1 transform}if exch pop sub 0 exch it rmoveto}bdf +/fm{statusdict/manualfeed known}bdf +/se{statusdict exch/manualfeed exch put}bdf +/mf{ +pop %UNI never allow manual feed +%UNI dup/ma exch def 0 gt{fm se/t1 5 st ok ma 1 gt and{/t2 0 st/t3 0 st statusdict/manualfeedtimeout 3600 put}if}if +}bdf +/jn{ +pop %UNI don't set job name +%UNI /statusdict where exch pop{statusdict exch/jobname exch put}if +}bdf +/pen{pnm mul/pnsh xdf pnm mul/pnsv xdf pnsh setlinewidth}bdf +/min{2 copy gt{exch}if pop}bdf +/max{2 copy lt{exch}if pop}bdf +/dh{fg 6 1 put array astore exch pop exch pop exch setdash}bdf +/ih[currentdash]def +/rh{fg 6 0 put ih aload pop setdash}bdf +/dl{gsave nlw pys div setlinewidth 0 setgray}bdf +/dlin{exch currentpoint currentlinewidth 2 div dup +translate newpath moveto lineto currentpoint stroke grestore moveto}bdf +/lin{fg 6 get 0 ne{exch lineto currentpoint 0 doop moveto} +{exch currentpoint/pnlv xdf/pnlh xdf gsave newpath/@1 xdf/@2 xdf fp{pnlh @2 lt{pnlv @1 ge +{pnlh pnlv moveto @2 @1 lineto pnsh 0 rlineto +0 pnsv rlineto pnlh pnsh add pnlv pnsv add lineto pnsh neg 0 rlineto} +{pnlh pnlv moveto pnsh 0 rlineto @2 pnsh add @1 lineto 0 pnsv rlineto +pnsh neg 0 rlineto pnlh pnlv pnsv add lineto}ifelse}{pnlv @1 gt +{@2 @1 moveto pnsh 0 rlineto pnlh pnsh add pnlv lineto 0 pnsv rlineto +pnsh neg 0 rlineto @2 @1 pnsv add lineto}{pnlh pnlv moveto pnsh 0 rlineto +0 pnsv rlineto @2 pnsh add @1 pnsv add lineto pnsh neg 0 rlineto +0 pnsv neg rlineto}ifelse}ifelse +closepath fill}if @2 @1 grestore moveto}ifelse}bdf +/gw{/pnm fg 3 get fg 4 get div def}bdf +/lw{fg exch 4 exch put fg exch 3 exch put gw pnsv pnsh pen}bdf +/barc{/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf +/@6 xdf/@7 xdf/@8 xdf gsave +@5 @7 add 2 div @6 @8 add 2 div translate newpath 0 0 moveto +@5 @7 sub @6 @8 sub mtx currentmatrix pop scale @1{newpath}if +0 0 0.5 @4 @3 arc @4 @3 sub abs 360 ge{closepath}if +mtx setmatrix @2 doop grestore}bdf +/ar{dup 0 eq barc}bdf +/ov{0 exch 360 exch true barc}bdf +/rc{/@t xdf currentpoint 6 2 roll newpath 4 copy 4 2 roll exch moveto +6 -1 roll lineto lineto lineto closepath @t doop moveto}bdf +/mup{dup pnsh 2 div le exch pnsv 2 div le or}bdf +/rr{/@1 xdf 2. div/@2 xdf 2. div/@3 xdf +/@4 xdf/@5 xdf/@6 xdf/@7 xdf +@7 @5 eq @6 @4 eq @2 mup or or{@7 @6 @5 @4 @1 rc} +{@4 @6 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@5 @7 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@1 0 eq{/@2 @2 pnsh 2 div 2 copy gt{sub def}{0 pop4}ifelse}if +currentpoint newpath +@4 @6 add 2. div @7 moveto +@4 @7 @4 @5 @2 arcto pop4 +@4 @5 @6 @5 @2 arcto pop4 +@6 @5 @6 @7 @2 arcto pop4 +@6 @7 @4 @7 @2 arcto pop4 +closepath @1 doop moveto}ifelse}bdf +/pr{gsave newpath/pl{exch moveto/pl{exch lineto}def}def}bdf +/pl{exch lineto}bdf +/ep{dup 0 eq{{moveto}{exch lin}{}{(%%[|1|]%%)= flush}pathforall +pop grestore}{doop grestore}ifelse currentpoint newpath moveto}bdf +/gr{64. div setgray}bdf +/pat{s8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi s8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}setscreen gr}bdf +/sg{freq rot/spf load setscreen gr}bdf +/dc{transform round .5 sub exch round .5 sub exch itransform}bdf +/sn{userdict/smooth4 known}bdf +/x8{3 bitshift}bdf +/x4{2 bitshift}bdf +/d4{-2 bitshift}bdf +/d8{-3 bitshift}bdf +/rb{15 add -4 bitshift 1 bitshift}bdf +/db{/@7 save def/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf/@6 @5 @3 4 add mul def +dc translate scale/xdbit 1 1 idtransform abs/ydbit exch def abs def{0 0 1 ydbit add 1 10 rc clip}if +@1 0 eq @1 4 eq or{1 setgray ydbit 0 1 ydbit add 1 2 rc}if +@1 3 eq @1 7 eq or{1}{0}ifelse setgray/@9 @1 0 eq @1 1 eq @1 3 eq or or invertflag xor def/@13 @6 def +@2 fBitStretch or{/@10 @4 x4 def/@11 @3 x4 def/@12 @10 rb def/@13 @12 @11 mul def/@15 1 1 dtransform abs/calcY 1 index def round cvi/@14 exch def +abs/calcX 1 index def round cvi scaleby96 not{1 add}if def/@16 @15 rb def/@17 @16 @14 mul def}if +sn @13 60000 lt and @2 fBitStretch or and{mtx currentmatrix dup 1 get exch 2 get 0. eq exch 0. eq and @17 60000 lt and fBitStretch and{@16 3 bitshift @14 @9 [calcX 0 0 calcY 0 0]{@17 string @13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4 +@10 @11 @12 dup string 5 index @15 @14 @16 dup string stretch}imagemask}{@12 x8 @11 @9 [@10 0 0 @11 0 0]{@13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4}imagemask}ifelse}{@5 3 bitshift @3 4 add @9 [@4 0 0 @3 0 2]{currentfile @6 string readhexstring pop}imagemask}ifelse +@7 restore}bdf +/wd 16 dict def +/mfont 14 dict def +/mdf{mfont wcheck not{/mfont 14 dict def}if mfont begin xdf end}bdf +/cf{{1 index/FID ne{def}{pop pop}ifelse}forall}bdf +/rf{/@1 exch def/@2 exch def +FontDirectory @2 known{cleartomark pop}{findfont dup begin dup length @1 add dict begin +cf {/Encoding macvec def}{Encoding dup length array copy/Encoding exch def +counttomark 2 idiv{Encoding 3 1 roll put}repeat}ifelse +pop +exec currentdict end end @2 exch definefont pop}ifelse}bdf +/bmbc{exch begin wd begin +/cr xdf +save +CharTable cr 6 mul 6 getinterval{}forall +/bitheight xdf/bitwidth xdf +.96 div/width xdf +Gkernmax add/XOffset xdf Gdescent add/YOffset xdf/rowbytes xdf +rowbytes 255 eq{0 0 0 0 0 0 setcachedevice} +{Gnormsize dup scale +width 0 XOffset YOffset bitwidth XOffset add bitheight YOffset add +setcachedevice +rowbytes 0 ne{ +XOffset YOffset translate newpath 0 0 moveto +bitwidth bitheight scale +sn{ +/xSmt bitwidth x4 def +/ySmt bitheight x4 def +/rSmt xSmt rb def +rSmt x8 ySmt true +[xSmt 0 0 ySmt neg 0 ySmt] +{rSmt ySmt mul string CharData cr get +1 index bitwidth bitheight rowbytes rSmt so smooth4} +}{rowbytes 3 bitshift bitheight 4 add true +[bitwidth 0 0 bitheight neg 0 bitheight 2 add] +{CharData cr get} +}ifelse +imagemask +}if +}ifelse +restore +end end +}bdf +/bb{.96 exch div/Gnormsize mdf 2 index +/Gkernmax mdf 1 index/Gdescent mdf +3 index div 4 1 roll +2 index div 1. 5 2 roll +exch div 4 1 roll +4 array astore/FontBBox mdf +}bdf +/cdf{mfont/CharData get 3 1 roll put}bdf +/bf{ +mfont begin +/FontType 3 def +/FontMatrix [1 0 0 1 0 0] def +/Encoding macvec def +/BuildChar/bmbc load def +end +mfont definefont pop +}bdf +/wi LW 1 eq{{gsave 0 0 0 0 0 0 0 0 moveto lineto lineto lineto closepath clip stringwidth grestore}bind}{/stringwidth load}ifelse def +/aps{0 get 124 eq}bdf +/xc{s75 cvs dup}bdf +/xp{put cvn}bdf +/scs{xc 3 67 put dup 0 95 xp}bdf +/sos{xc 3 79 xp}bdf +/sbs{xc 1 66 xp}bdf +/sis{xc 2 73 xp}bdf +/sob{xc 2 79 xp}bdf +/sss{xc 4 83 xp}bdf +/dd{exch 1 index add 3 1 roll add exch}bdf +/smc{moveto dup lws}bdf +/kwn{FontDirectory 1 index known{findfont exch pop}}bdf +/gl{1 currentgray sub setgray}bdf +/mm{/mfont 10 dict def mfont begin +/FontMatrix [1 0 0 1 0 0] def +/FontType 3 def +/Encoding macvec def +/df 4 index findfont def +/FontBBox [0 0 1 1] def +/xda xdf/mbc xdf +/BuildChar{wd begin/cr xdf/fd xdf/cs s1 dup 0 cr put def fd/mbc get exec end}def +exec end mfont definefont}bdf +/ac{dup scs kwn{exch findfont dup length 1 add dict begin +cf fmv{/Encoding macvec def}if/StrokeWidth nlw 1000 mul pys div ps div dup 12 lt{pop 12}if def +/PaintType 2 def currentdict /UniqueID known{/UniqueID UniqueID 16#A80000 xor def}if currentdict end definefont}ifelse}bdf +/mb{dup sbs kwn{exch{pop}{bbc}{}mm}ifelse sfd}bdf +/mo{dup sos kwn{exch{pop}{boc}{}mm}ifelse sfd}bdf +/ms{dup sss kwn{exch{pop}{bsc}{}mm}ifelse sfd}bdf +/ou{dup sos kwn{exch dup ac pop{scs findfont /df2 xdf}{aoc}{}mm}ifelse sfd}bdf +/su{dup sss kwn{exch dup ac pop{scs findfont /df2 xdf}{asc}{}mm}ifelse sfd}bdf +/ao{/fmv true def ou}bdf/as{/fmv true def su}bdf +/vo{/fmv false def ou}bdf/vs{/fmv false def su}bdf +/bbc{/da .03 def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da moveto lws}bdf +/boc{/da 1 ps div def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da smc gl da 2. div dup moveto lws}bdf +/bsc{/da 1 ps div def +/ds .05 def/da2 da 2. div def fd/df get setfont +gsave cs wi 1 index 0 ne{exch ds add da2 add exch}if grestore setcharwidth +cs ds da2 add .01 add 0 smc 0 ds da2 sub translate 0 0 smc +da 0 smc da da smc 0 da smc gl da 2. div dup moveto lws}bdf +/aoc{fd/df get setfont +gsave cs wi grestore setcharwidth +gl cs 0 0 smc fd/df2 get setfont gl 0 0 moveto lws}bdf +/asc{/da .05 def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs da .01 add 0 smc 0 da translate gl 0 0 smc gl fd/df2 get setfont 0 0 moveto lws}bdf +/st{1000 mul usertime add dup 2147483647 gt{2147483647 sub}if def}bdf +/the{usertime sub dup 0 lt exch -2147483648 gt and}bdf +/6a 6 array def +/2a 2 array def +/3q 3 array def +/qs{3 -1 roll sub exch 3 -1 roll sub exch}bdf +/qa{3 -1 roll add exch 3 -1 roll add exch}bdf +/qm{3 -1 roll 1 index mul 3 1 roll mul}bdf +/qn{6a exch get mul}bdf +/qA .166667 def/qB .833333 def/qC .5 def +/qx{6a astore pop +qA 0 qn qB 2 qn add qA 1 qn qB 3 qn add +qB 2 qn qA 4 qn add qB 3 qn qA 5 qn add +qC 2 qn qC 4 qn add qC 3 qn qC 5 qn add}bdf +/qp{6 copy 12 -2 roll pop pop}bdf +/qc{exch qp qx curveto}bdf +/qi{{exch 4 copy 2a astore aload pop qa .5 qm newpath moveto}{exch 2 copy 6 -2 roll 2 qm qs 4 2 roll}ifelse}bdf +/qq{{qc 2a aload pop qx curveto}{exch 4 copy qs qa qx curveto}ifelse}bdf +/pt{currentpoint newpath moveto}bdf +/qf{/fillflag true def}bdf +/ec{1 and 0 ne{0 doop}if grestore currentpoint newpath moveto/fillflag false def}bdf +/eu{currentpoint fp{0 ep}{grestore newpath}ifelse moveto/fillflag false def}bdf +/bp{currentpoint newpath 2 copy moveto}bdf +/ef{gsave fillflag{gsave eofill grestore}if}bdf +/sm{0 exch{@1 eq{1 add}if}forall}bdf +/lshow{4 1 roll exch/@1 exch def{1 index wi pop sub 1 index sm dv 0 @1 4 -1 roll widthshow}{1 index wi pop sub +1 index dup sm 10 mul exch length 1 sub add dv dup 10. mul 0 @1 4 -1 roll 0 6 -1 roll awidthshow}ifelse}bdf +/setTxMode{sa 9 2 index put 3 eq{1}{0}ifelse setgray}bdf +/SwToSym{{}mark false/Symbol/|______Symbol 0 rf 0 sa 6 get 0 ne{pop 1}{sa 7 get 0 eq{pop 2}if}ifelse +sa 1 get 0 ne/|______Symbol +sa 4 get 0 ne{vs}{sa 3 get 0 ne{vo}{fnt}ifelse}ifelse}bdf +/mc{0 3 1 roll transform neg exch pop}bdf +/ul{dup 0 ne sa 2 get 0 ne and{gsave 0 0 +/UnderlinePosition kif{mc}{ps -10 div}ifelse/UnderlineThickness kif{mc}{ps 15 div}ifelse +abs setlinewidth neg rmoveto +sa 4 get 0 ne{gsave currentlinewidth 2. div dup rmoveto currentpoint newpath moveto +2 copy rlineto stroke grestore}if +sa 3 get sa 4 get or 0 ne{gsave gl 2 copy rlineto stroke grestore rlineto strokepath nlw pys div setlinewidth}{rlineto}ifelse +stroke grestore}{pop}ifelse}bdf +/sgt{2 copy known{get true}{pop pop false}ifelse}bdf +/kif{currentfont dup/FontMatrix get exch/FontInfo sgt{true}{currentfont/df sgt +{dup/FontInfo sgt{3 1 roll/FontMatrix get mtx concatmatrix exch true}{pop pop pop false} +ifelse}{pop pop false}ifelse}ifelse{3 -1 roll sgt{exch true}{pop false}ifelse}{false}ifelse}bdf +/blank/Times-Roman findfont/CharStrings get/space get def +/macvec 256 array def +/NUL/SOH/STX/ETX/EOT/ENQ/ACK/BEL/BS/HT/LF/VT/FF/CR/SO/SI +/DLE/DC1/DC2/DC3/DC4/NAK/SYN/ETB/CAN/EM/SUB/ESC/FS/GS/RS/US +macvec 0 32 getinterval astore pop +macvec 32/Times-Roman findfont/Encoding get +32 96 getinterval putinterval macvec dup 39/quotesingle put 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/blank/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand/Acircumflex/Ecircumflex/Aacute +/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave/Oacute/Ocircumflex +/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +macvec 128 128 getinterval astore pop +{}mark true/Courier/|______Courier 0 rf +{/Metrics 21 dict begin/zero 600 def/one 600 def/two 600 def/three 600 def/four 600 def/five 600 def/six 600 def/seven 600 def/eight 600 def +/nine 600 def/comma 600 def/period 600 def/dollar 600 def/numbersign 600 def/percent 600 def/plus 600 def/hyphen 600 def/E 600 def/parenleft 600 def/parenright 600 def/space 600 def +currentdict end def currentdict/UniqueID known{/UniqueID 16#800000 def}if/FontBBox FontBBox 4 array astore def}mark true/Helvetica/|______Seattle 1 rf +/oldsettransfer/settransfer load def +/concatprocs{/proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def +newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx}def +/settransfer{currenttransfer concatprocs oldsettransfer}def +/PaintBlack{{1 exch sub}settransfer gsave newpath clippath 1 setgray fill grestore}def +/od{(Rvd\001\001\000\000\177) fg copy pop txpose +1 0 mtx defaultmatrix dtransform exch atan/pa exch def +newpath clippath mark +{transform{itransform moveto}}{transform{itransform lineto}} +{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform +{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}} +{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put +10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}bdf +/cd{}bdf +/op{/sfl false def/pm save def}bdf + +% two args, booleans +/cp{ +%UNI don't actually print page + pop pop %UNI ignore two args +%UNI not{userdict/#copies 0 put}if +%UNI ma 0 gt{{t1 the{exit}if}loop}if +%UNI {copypage}{showpage}ifelse + pm restore +}bdf +/px{0 3 1 roll tp tt}bdf +/psb{/us save def}bdf +/pse{us restore}bdf +/ct 40 string def +/nc{currentpoint initclip newpath gc{dup type dup/arraytype eq exch/packedarraytype eq or{exec}if} +forall clip newpath moveto}bdf +/kp{ct 0 2 index length 2 index 39 2 index put getinterval copy cvx exec mx3 currentmatrix pop}bdf +end % dict "md" + +%UNI don't initialize LaserWriter +%UNI LW 1 eq userdict/a4small known not and{/a4small +%UNI [[300 72 div 0 0 -300 72 div -120 3381] +%UNI 280 3255 +%UNI {statusdict/jobstate (printing) put 0 setblink +%UNI margins +%UNI exch 196 add exch 304 add 8 div round cvi frametoroket +%UNI statusdict/jobstate (busy) put +%UNI 1 setblink} +%UNI /framedevice load +%UNI 60 45{dup mul exch dup mul add 1.0 exch sub}/setscreen load +%UNI {}/settransfer load/initgraphics load/erasepage load]cvx +%UNI statusdict begin bind end readonly def}if +%UNI md begin/bigs[lnop lnop/legal load userdict/a4 known{/a4 load}{lnop}ifelse lnop lnop lnop lnop lnop]def +%UNI /smalls[lnop userdict/note known{/note load}{dup}ifelse lnop userdict/a4small known{/a4small load}{lnop}ifelse 2 index lnop lnop lnop lnop ]def end +systemdict/currentpacking known{setpacking}if +%UNI currentfile ok userdict/stretch known not and{eexec}{flushfile}ifelse + +%%EndProlog +%%Page: 0 1 +BS +0 SI +16 /Times-Bold AF +22526 20648 MT +(Nyquist Reference Manual)SH +11 SS +29022 22993 MT +(Version 2.0)SH +26562 26761 MT +(Roger B. Dannenberg)SH +/Times-Roman SF +27496 28138 MT +(18 December 1996)SH +25509 39635 MT +(Carnegie Mellon University)SH +25371 41387 MT +(School of Computer Science)SH +25140 43139 MT +(Pittsburgh, PA 15213, U.S.A.)SH +ES +%%Page: 1 2 +BS +0 SI +10 /Times-Roman AF +31430 4286 MT +(1)SH +11 SS +9280 7955 MT +(.)SH +ES +%%Page: iii 3 +BS +0 SI +8 /Times-Roman AF +8280 4286 MT +(PREFACE)SH +10 SS +52052 XM +(Page iii)SH +16 /Times-Bold AF +8280 8272 MT +(Preface)SH +11 /Times-Roman AF +9280 9649 MT +(This manual is a guide for users of Nyquist, a) +51 W( language for composition and sound synthesis. Nyquist)50 W +8280 11026 MT +(grew out of a series) +75 W( of research projects, notably the languages Arctic and Canon. Along with Nyquist,)76 W +8280 12403 MT +(these languages promote a functional style of programming and incorporate time into the language)261 W +8280 13780 MT +(semantics.)SH +9280 16259 MT +(Please help by noting any errors,) +267 W( omissions, or suggestions you may have. You can send your)268 W +8280 17636 MT +(suggestions to Dannenberg@CS.CMU.EDU \050internet\051 via computer mail, or by campus mail to Roger)147 W +8280 19013 MT +(B. Dannenberg, School of Computer Science, or by) +138 W( ordinary mail to Roger B. Dannenberg, School of)139 W +8280 20390 MT +(Computer Science, Carnegie Mellon University, 5000 Forbes Ave., Pittsburgh, PA 15213-3890, USA.)SH +9280 22869 MT +(Nyquist is a successor to Fugue, a language originally implemented by Chris Fraley,) +78 W( and extended by)77 W +8280 24246 MT +(George Polly and Roger Dannenberg. Peter Velikonja and Dean Rubine) +210 W( were early users, and they)211 W +8280 25623 MT +(proved the value as well as discovered some early problems of the system.) +221 W( This) +715 W( led to Nyquist, a)220 W +8280 27000 MT +(reimplementation of Fugue by Roger Dannenberg with help from Joe Newcomer and Cliff Mercer.)SH +9280 29479 MT +(I also wish to acknowledge support from CMU, Yamaha, and IBM for this work.)SH +ES +%%Page: iv 4 +BS +0 SI +10 /Times-Roman AF +6120 4286 MT +(Page iv)SH +8 SS +45696 XM +(NYQUIST MANUAL)SH +11 SS +6120 44577 MT +(.)SH +ES +%%Page: 1 5 +BS +0 SI +8 /Times-Roman AF +8280 4286 MT +(NYQUIST FUNCTIONS)SH +10 SS +52386 XM +(Page 1)SH +16 /Times-Bold AF +8280 8272 MT +(1. Nyquist Functions)SH +14 SS +8280 12090 MT +(1.1. Behaviors)SH +12 SS +8280 15774 MT +(1.1.1. Sound Synthesis)SH +11 /Times-Roman AF +9280 17151 MT +(These functions provide musically interesting) +74 W( creation behaviors that react to their environment; these)75 W +8280 18528 MT +(are the ``unit generators'' of Nyquist:)SH +/Courier SF +8280 20476 MT +(\050sound-warp)SH +/Times-Italic SF +16200 XM +(warp-fn signal)385 W +/Courier SF +23694 XM +([)SH +/Times-Italic SF +(wrate)SH +/Courier SF +(]\051)SH +/Times-Roman SF +11880 21672 MT +(Applies a warp function)50 W +/Times-Italic SF +22954 XM +(warp-fn)SH +/Times-Roman SF +26763 XM +(to)SH +/Times-Italic SF +27944 XM +(signal)SH +/Times-Roman SF +30959 XM +(using function composition. If) +50 W( the optional parameter)51 W +/Times-Italic SF +11880 22868 MT +(wrate)SH +/Times-Roman SF +14742 XM +(is omitted or NIL,) +81 W( linear interpolation is used.)80 W +/Times-Italic SF +36210 XM +(warp-fn)SH +/Times-Roman SF +40049 XM +(is a mapping from score \050logical\051)80 W +11880 24064 MT +(time to real) +39 W( time, and)40 W +/Times-Italic SF +21732 XM +(signal)SH +/Times-Roman SF +24737 XM +(is a function from score time to real values. The result is a function)40 W +11880 25260 MT +(from real time to real values at a sample rate of)SH +/Courier SF +32923 XM +(*sound-srate*)SH +/Times-Roman SF +(. See) +275 W( also)SH +/Courier SF +46238 XM +(control-warp)SH +/Times-Roman SF +(.)SH +11880 26456 MT +(If)SH +/Times-Italic SF +13004 XM +(wrate)SH +/Times-Roman SF +15902 XM +(is not NIL, it) +117 W( must be a number. The parameter indicates that high-quality resampling)116 W +11880 27652 MT +(should be used and specifies the sample rate for the inverse of)94 W +/Times-Italic SF +40558 XM +(warp-fn)SH +/Times-Roman SF +(. Use the lowest) +94 W( number)95 W +11880 28848 MT +(you can. \050See below for) +109 W( details.\051 Note that high-quality resampling is much slower than linear)108 W +11880 30044 MT +(interpolation.)SH +11880 31240 MT +(To perform) +138 W( high-quality resampling by a fixed ratio, as opposed to a variable ratio allowed in)139 W +/Courier SF +11880 32436 MT +(sound-warp)SH +/Times-Roman SF +(, use)249 W +/Courier SF +21269 XM +(scale-srate)SH +/Times-Roman SF +29053 XM +(to stretch) +249 W( or shrink the sound, and then)248 W +/Courier SF +48421 XM +(resample)SH +/Times-Roman SF +54224 XM +(to)SH +11880 33632 MT +(restore the original sample rate.)SH +/Courier SF +11880 36265 MT +(Sound-warp)SH +/Times-Roman SF +18783 XM +(and)SH +/Courier SF +20674 XM +(control-warp)SH +/Times-Roman SF +28897 XM +(both take the inverse of)28 W +/Times-Italic SF +39636 XM +(warp-fn)SH +/Times-Roman SF +43423 XM +(to get a function) +28 W( from real)29 W +11880 37461 MT +(time to score time. Each sample of this inverse) +33 W( is thus a score time;)32 W +/Times-Italic SF +42183 XM +(signal)SH +/Times-Roman SF +45180 XM +(is evaluated at each of)32 W +11880 38657 MT +(these score times to yield a value, which is) +17 W( the desired result. The sample rate of the inverse warp)18 W +11880 39853 MT +(function is somewhat arbitrary. With linear interpolation, the inverse warp function sample rate is)17 W +11880 41049 MT +(taken to be the output sample rate. Note,) +63 W( however, that the samples of the inverse warp function)64 W +11880 42245 MT +(are stored as 32-bit floats, so they have limited precision. Since) +171 W( these floats represent sample)170 W +11880 43441 MT +(times, rounding can) +190 W( be a problem. Rounding in this case is equivalent to adding jitter to the)191 W +11880 44637 MT +(sample times. Nyquist ignores this problem for ordinary) +110 W( warping, but for high-quality warping,)109 W +11880 45833 MT +(the jitter cannot be ignored.)SH +11880 47029 MT +(The solution is to use a) +59 W( rather low sample rate for the inverse warp function.)60 W +/Courier SF +46619 XM +(Sound-warp)SH +/Times-Roman SF +53554 XM +(can)SH +11880 48225 MT +(then linearly interpolate this signal using double-precision floats to minimize jitter between)275 W +11880 49421 MT +(samples. The) +205 W( sample rate is a compromise: a low sample rate minimizes jitter, while a high)206 W +11880 50617 MT +(sample rate) +76 W( does a better job of capturing detail \050e.g. rapid fluctuations\051 in the warp function. A)75 W +11880 51813 MT +(good rule of thumb is to use at) +69 W( most 1,000 to 10,000 samples for the inverse warp function. For)70 W +11880 53009 MT +(example, if the result will be 1 minute of sound, use a sample rate of 3000 samples / 60) +9 W( seconds =)8 W +11880 54205 MT +(50 samples/second. Because Nyquist has no advance information about) +153 W( the warp function, the)154 W +11880 55401 MT +(inverse warp function sample rate must be) +173 W( provided as a parameter. When in doubt, just try)172 W +11880 56597 MT +(something and let your ears be the judge.)SH +/Courier SF +8280 58292 MT +(\050slope)SH +/Times-Italic SF +12900 XM +(signal)SH +/Courier SF +(\051)SH +/Times-Roman SF +11880 59488 MT +(Computes the first derivative \050slope\051 of)100 W +/Times-Italic SF +30076 XM +(signal)SH +/Times-Roman SF +(. The) +475 W( start time, sample rate,) +100 W( etc. are taken from)99 W +/Times-Italic SF +11880 60684 MT +(signal)SH +/Times-Roman SF +(.)SH +ES +%%Page: 2 6 +BS +0 SI +10 /Times-Roman AF +6120 4286 MT +(Page 2)SH +8 SS +45696 XM +(NYQUIST MANUAL)SH +ES +%%Page: 3 7 +BS +0 SI +8 /Times-Roman AF +8280 4286 MT +(INDEX)SH +10 SS +52386 XM +(Page 3)SH +16 /Times-Bold AF +8280 8272 MT +(Index)SH +8 /Times-Roman AF +8280 10469 MT +(Behaviors 1)400 W +8280 12317 MT +(Errors iii)400 W +8280 14165 MT +(Omissions iii)400 W +8280 16013 MT +(Slope, derivative, first derivative) +SH( 1)400 W +8280 16937 MT +(Sound-warp 1)400 W +8280 17861 MT +(Suggestions iii)400 W +ES +%%Page: 4 8 +BS +0 SI +10 /Times-Roman AF +6120 4286 MT +(Page 4)SH +8 SS +45696 XM +(NYQUIST MANUAL)SH +ES +%%Page: i 9 +BS +0 SI +8 /Times-Roman AF +8280 4286 MT +(TABLE OF CONTENTS)SH +10 SS +52608 XM +(Page i)SH +16 /Times-Bold AF +25591 8272 MT +(Table of Contents)SH +12 SS +8280 9796 MT +(Preface)SH +54078 XM +(iii)SH +8280 11320 MT +(1. Nyquist Functions)SH +54480 XM +(1)SH +10 SS +9780 12710 MT +(1.1. Behaviors)SH +54580 XM +(1)SH +11780 13790 MT +(1.1.1. Sound Synthesis)SH +54580 XM +(1)SH +12 SS +8280 15314 MT +(Index)SH +54480 XM +(3)SH +ES +%%Trailer +%%Pages: 9 +%%DocumentFonts: Times-Roman Times-Bold Courier Times-Italic diff --git a/docsrc/nyquist/warpfig.ps b/docsrc/nyquist/warpfig.ps new file mode 100644 index 0000000..10015cd --- /dev/null +++ b/docsrc/nyquist/warpfig.ps @@ -0,0 +1,650 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 31 334 444 752 +%%Title: (warpfig-Layer#1) +%%Creator: (MacDraw II 1.1v2: LaserWriter 8 8.1.1) +%%CreationDate: (10:26 PM Sunday, January 24, 1904) +%%For: (Dannenberg) +%%Pages: 1 +%%DocumentFonts: Helvetica +%%DocumentNeededFonts: Helvetica +%%DocumentSuppliedFonts: +%%DocumentData: Clean7Bit +%%PageOrder: Ascend +%%Orientation: Portrait +%ADO_PaperArea: -129 -125 3171 2425 +%ADO_ImageableArea: 0 0 3042 2300 +%%EndComments +/md 153 dict def md begin +/currentpacking where {pop /sc_oldpacking currentpacking def true setpacking}if +%%BeginFile: adobe_psp_basic +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/bd{bind def}bind def +/xdf{exch def}bd +/xs{exch store}bd +/ld{load def}bd +/Z{0 def}bd +/T/true +/F/false +/:L/lineto +/lw/setlinewidth +/:M/moveto +/rl/rlineto +/rm/rmoveto +/:C/curveto +/:T/translate +/:K/closepath +/:mf/makefont +/gS/gsave +/gR/grestore +/np/newpath +14{ld}repeat +/$m matrix def +/av 81 def +/por true def +/normland false def +/psb-nosave{}bd +/pse-nosave{}bd +/us Z +/psb{/us save store}bd +/pse{us restore}bd +/level2 +/languagelevel where +{ +pop languagelevel 2 ge +}{ +false +}ifelse +def +/featurecleanup +{ +stopped +cleartomark +countdictstack exch sub dup 0 gt +{ +{end}repeat +}{ +pop +}ifelse +}bd +/noload Z +/startnoload +{ +{/noload save store}if +}bd +/endnoload +{ +{noload restore}if +}bd +level2 startnoload +/setjob +{ +statusdict/jobname 3 -1 roll put +}bd +/setcopies +{ +userdict/#copies 3 -1 roll put +}bd +level2 endnoload level2 not startnoload +/setjob +{ +1 dict begin/JobName xdf currentdict end setuserparams +}bd +/setcopies +{ +1 dict begin/NumCopies xdf currentdict end setpagedevice +}bd +level2 not endnoload +/pm Z +/mT Z +/sD Z +/realshowpage Z +/initializepage +{ +/pm save store mT concat +}bd +/endp +{ +pm restore showpage +}def +/$c/DeviceRGB def +/rectclip where +{ +pop/rC/rectclip ld +}{ +/rC +{ +np 4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +clip np +}bd +}ifelse +/rectfill where +{ +pop/rF/rectfill ld +}{ +/rF +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +fill +gR +}bd +}ifelse +/rectstroke where +{ +pop/rS/rectstroke ld +}{ +/rS +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +stroke +gR +}bd +}ifelse +%%EndFile +%%BeginFile: adobe_psp_colorspace_level1 +%%Copyright: Copyright 1991-1993 Adobe Systems Incorporated. All Rights Reserved. +/G/setgray ld +/:F/setrgbcolor ld +%%EndFile +%%BeginFile: adobe_psp_uniform_graphics +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/@a +{ +np :M 0 rl :L 0 exch rl 0 rl :L fill +}bd +/@b +{ +np :M 0 rl 0 exch rl :L 0 rl 0 exch rl fill +}bd +/arct where +{ +pop +}{ +/arct +{ +arcto pop pop pop pop +}bd +}ifelse +/x1 Z +/x2 Z +/y1 Z +/y2 Z +/rad Z +/@q +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +fill +}bd +/@s +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +:K +stroke +}bd +/@i +{ +np 0 360 arc fill +}bd +/@j +{ +gS +np +:T +scale +0 0 .5 0 360 arc +fill +gR +}bd +/@e +{ +np +0 360 arc +:K +stroke +}bd +/@f +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 0 360 arc +:K +$m setmatrix +stroke +}bd +/@k +{ +gS +np +:T +0 0 :M +0 0 5 2 roll +arc fill +gR +}bd +/@l +{ +gS +np +:T +0 0 :M +scale +0 0 .5 5 -2 roll arc +fill +gR +}bd +/@m +{ +np +arc +stroke +}bd +/@n +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 5 -2 roll arc +$m setmatrix +stroke +}bd +%%EndFile +%%BeginFile: adobe_psp_customps +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/$t Z +/$p Z +/$s Z +/$o 1. def +/2state? false def +/ps Z +level2 startnoload +/pushcolor/currentrgbcolor ld +/popcolor/setrgbcolor ld +/setcmykcolor where +{ +pop/currentcmykcolor where +{ +pop/pushcolor/currentcmykcolor ld +/popcolor/setcmykcolor ld +}if +}if +level2 endnoload level2 not startnoload +/pushcolor +{ +currentcolorspace $c eq +{ +currentcolor currentcolorspace true +}{ +currentcmykcolor false +}ifelse +}bd +/popcolor +{ +{ +setcolorspace setcolor +}{ +setcmykcolor +}ifelse +}bd +level2 not endnoload +/pushstatic +{ +ps +2state? +$o +$t +$p +$s +}bd +/popstatic +{ +/$s xs +/$p xs +/$t xs +/$o xs +/2state? xs +/ps xs +}bd +/pushgstate +{ +save errordict/nocurrentpoint{pop 0 0}put +currentpoint +3 -1 roll restore +pushcolor +currentlinewidth +currentlinecap +currentlinejoin +currentdash exch aload length +np clippath pathbbox +$m currentmatrix aload pop +}bd +/popgstate +{ +$m astore setmatrix +2 index sub exch +3 index sub exch +rC +array astore exch setdash +setlinejoin +setlinecap +lw +popcolor +np :M +}bd +/bu +{ +pushgstate +gR +pushgstate +2state? +{ +gR +pushgstate +}if +pushstatic +pm restore +mT concat +}bd +/bn +{ +/pm save store +popstatic +popgstate +gS +popgstate +2state? +{ +gS +popgstate +}if +}bd +/cpat{pop 64 div G 8{pop}repeat}bd +%%EndFile +%%BeginFile: adobe_psp_basic_text +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/S/show ld +/A{ +0.0 exch ashow +}bd +/R{ +0.0 exch 32 exch widthshow +}bd +/W{ +0.0 3 1 roll widthshow +}bd +/J{ +0.0 32 4 2 roll 0.0 exch awidthshow +}bd +/V{ +0.0 4 1 roll 0.0 exch awidthshow +}bd +/fcflg true def +/fc{ +fcflg{ +vmstatus exch sub 50000 lt{ +(%%[ Warning: Running out of memory ]%%\r)print flush/fcflg false store +}if pop +}if +}bd +/$f[1 0 0 -1 0 0]def +/:ff{$f :mf}bd +/MacEncoding StandardEncoding 256 array copy def +MacEncoding 39/quotesingle put +MacEncoding 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/space/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand +/Acircumflex/Ecircumflex/Aacute/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave +/Oacute/Ocircumflex/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +MacEncoding 128 128 getinterval astore pop +level2 startnoload +/copyfontdict +{ +findfont dup length dict +begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +}bd +level2 endnoload level2 not startnoload +/copyfontdict +{ +findfont dup length dict +copy +begin +}bd +level2 not endnoload +md/fontname known not{ +/fontname/customfont def +}if +/Encoding Z +/:mre +{ +copyfontdict +/Encoding MacEncoding def +fontname currentdict +end +definefont :ff def +}bd +/:bsr +{ +copyfontdict +/Encoding Encoding 256 array copy def +Encoding dup +}bd +/pd{put dup}bd +/:esr +{ +pop pop +fontname currentdict +end +definefont :ff def +}bd +/scf +{ +scalefont def +}bd +/scf-non +{ +$m scale :mf setfont +}bd +/ps Z +/fz{/ps xs}bd +/sf/setfont ld +/cF/currentfont ld +/mbf +{ +/makeblendedfont where +{ +pop +makeblendedfont +/ABlend exch definefont +}{ +pop +}ifelse +def +}def +%%EndFile +%%BeginFile: adobe_psp_dashes +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/:q/setdash ld +/:r{ +np +:M +:L +stroke +}bd +/nodash[]def +/qdenddash +{ +nodash 0 setdash +}bd +%%EndFile +/currentpacking where {pop sc_oldpacking setpacking}if +end % md +%%EndProlog +%%BeginSetup +md begin +/pT[1 0 0 -1 29.999 761.009]def/mT[.24 0 0 -.24 29.999 761.009]def +/sD 16 dict def +%%IncludeFont: Helvetica +/f0_1/Helvetica :mre +/f1_1 f0_1 1.04 scf +/f1_58 f1_1 58 scf +/Courier findfont[10 0 0 -10 0 0]:mf setfont +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +initializepage +%%EndPageSetup +gS 0 0 2300 3042 rC +0 0 :M +0 setlinecap +currentscreen +3 1 roll pop pop 60 45 3 -1 roll setscreen +np 113 38 :M +127 96 :L +113 96 :L +98 96 :L +113 38 :L +eofill +-4 -4 115 1652 4 4 111 94 @b +np 1725 1650 :M +1666 1665 :L +1666 1650 :L +1666 1635 :L +1725 1650 :L +4 lw +eofill +111 1652 -4 4 1668 1648 4 111 1648 @a +111 1648 :M +2 setlinecap +8 lw +113 1650 :M +237.663 1449.978 300 1350 300 1350 :C +300 1350 362.492 1324.981 487.5 1275 :C +612.494 1224.98 675 1200 675 1200 :C +675 1200 706.321 1149.985 769 1050 :C +831.655 949.983 863 900 863 900 :C +863 900 987.979 774.994 1238 525 :C +1487.983 274.99 1613 150 1613 150 :C +1613 150 1613 399.982 1613 900 :C +1613 1399.99 1613 1650 1613 1650 :C +stroke +1613 1650 :M +0 setlinecap +-4 -4 302 1690 4 4 298 1648 @b +-4 -4 490 1690 4 4 486 1648 @b +-4 -4 677 1690 4 4 673 1648 @b +-4 -4 865 1690 4 4 861 1648 @b +-4 -4 1052 1690 4 4 1048 1648 @b +-4 -4 1240 1690 4 4 1236 1648 @b +-4 -4 1427 1690 4 4 1423 1648 @b +-4 -4 1615 1690 4 4 1611 1648 @b +-4 -4 115 1690 4 4 111 1648 @b +93 1754 :M +f1_58 sf +(0)S +280 1754 :M +(1)S +468 1754 :M +(2)S +655 1754 :M +(3)S +843 1754 :M +(4)S +1030 1754 :M +(5)S +1218 1754 :M +(6)S +1405 1754 :M +(7)S +1593 1754 :M +(8)S +73 152 -4 4 115 148 4 73 148 @a +73 340 -4 4 115 336 4 73 336 @a +73 527 -4 4 115 523 4 73 523 @a +73 715 -4 4 115 711 4 73 711 @a +73 902 -4 4 115 898 4 73 898 @a +73 1090 -4 4 115 1086 4 73 1086 @a +73 1277 -4 4 115 1273 4 73 1273 @a +73 1465 -4 4 115 1461 4 73 1461 @a +73 1652 -4 4 115 1648 4 73 1648 @a +18 1679 :M +(0)S +18 1491 :M +(1)S +18 1304 :M +(2)S +18 1116 :M +(3)S +18 929 :M +(4)S +18 741 :M +(5)S +18 554 :M +(6)S +18 366 :M +(7)S +18 179 :M +(8)S +4 lw +[16.667 12.5 ] 0 :q +863 900 113 900 :r +863 1650 863 900 :r +endp +%%Trailer +end % md +%%EOF diff --git a/docsrc/nyquist/warpnotesfig.ps b/docsrc/nyquist/warpnotesfig.ps new file mode 100644 index 0000000..8757149 --- /dev/null +++ b/docsrc/nyquist/warpnotesfig.ps @@ -0,0 +1,851 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 31 670 426 755 +%%Title: (warpnotesfig-Layer#1) +%%Creator: (MacDraw II 1.1v2: LaserWriter 8 8.1.1) +%%CreationDate: (10:27 PM Sunday, January 24, 1904) +%%For: (Dannenberg) +%%Pages: 1 +%%DocumentFonts: Helvetica +%%DocumentNeededFonts: Helvetica +%%DocumentSuppliedFonts: +%%DocumentData: Clean7Bit +%%PageOrder: Ascend +%%Orientation: Portrait +%ADO_PaperArea: -129 -125 3171 2425 +%ADO_ImageableArea: 0 0 3042 2300 +%%EndComments +/md 149 dict def md begin +/currentpacking where {pop /sc_oldpacking currentpacking def true setpacking}if +%%BeginFile: adobe_psp_basic +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/bd{bind def}bind def +/xdf{exch def}bd +/xs{exch store}bd +/ld{load def}bd +/Z{0 def}bd +/T/true +/F/false +/:L/lineto +/lw/setlinewidth +/:M/moveto +/rl/rlineto +/rm/rmoveto +/:C/curveto +/:T/translate +/:K/closepath +/:mf/makefont +/gS/gsave +/gR/grestore +/np/newpath +14{ld}repeat +/$m matrix def +/av 81 def +/por true def +/normland false def +/psb-nosave{}bd +/pse-nosave{}bd +/us Z +/psb{/us save store}bd +/pse{us restore}bd +/level2 +/languagelevel where +{ +pop languagelevel 2 ge +}{ +false +}ifelse +def +/featurecleanup +{ +stopped +cleartomark +countdictstack exch sub dup 0 gt +{ +{end}repeat +}{ +pop +}ifelse +}bd +/noload Z +/startnoload +{ +{/noload save store}if +}bd +/endnoload +{ +{noload restore}if +}bd +level2 startnoload +/setjob +{ +statusdict/jobname 3 -1 roll put +}bd +/setcopies +{ +userdict/#copies 3 -1 roll put +}bd +level2 endnoload level2 not startnoload +/setjob +{ +1 dict begin/JobName xdf currentdict end setuserparams +}bd +/setcopies +{ +1 dict begin/NumCopies xdf currentdict end setpagedevice +}bd +level2 not endnoload +/pm Z +/mT Z +/sD Z +/realshowpage Z +/initializepage +{ +/pm save store mT concat +}bd +/endp +{ +pm restore showpage +}def +/$c/DeviceRGB def +/rectclip where +{ +pop/rC/rectclip ld +}{ +/rC +{ +np 4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +clip np +}bd +}ifelse +/rectfill where +{ +pop/rF/rectfill ld +}{ +/rF +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +fill +gR +}bd +}ifelse +/rectstroke where +{ +pop/rS/rectstroke ld +}{ +/rS +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +stroke +gR +}bd +}ifelse +%%EndFile +%%BeginFile: adobe_psp_colorspace_level1 +%%Copyright: Copyright 1991-1993 Adobe Systems Incorporated. All Rights Reserved. +/G/setgray ld +/:F/setrgbcolor ld +%%EndFile +%%BeginFile: adobe_psp_uniform_graphics +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/@a +{ +np :M 0 rl :L 0 exch rl 0 rl :L fill +}bd +/@b +{ +np :M 0 rl 0 exch rl :L 0 rl 0 exch rl fill +}bd +/arct where +{ +pop +}{ +/arct +{ +arcto pop pop pop pop +}bd +}ifelse +/x1 Z +/x2 Z +/y1 Z +/y2 Z +/rad Z +/@q +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +fill +}bd +/@s +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +:K +stroke +}bd +/@i +{ +np 0 360 arc fill +}bd +/@j +{ +gS +np +:T +scale +0 0 .5 0 360 arc +fill +gR +}bd +/@e +{ +np +0 360 arc +:K +stroke +}bd +/@f +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 0 360 arc +:K +$m setmatrix +stroke +}bd +/@k +{ +gS +np +:T +0 0 :M +0 0 5 2 roll +arc fill +gR +}bd +/@l +{ +gS +np +:T +0 0 :M +scale +0 0 .5 5 -2 roll arc +fill +gR +}bd +/@m +{ +np +arc +stroke +}bd +/@n +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 5 -2 roll arc +$m setmatrix +stroke +}bd +%%EndFile +%%BeginFile: adobe_psp_customps +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/$t Z +/$p Z +/$s Z +/$o 1. def +/2state? false def +/ps Z +level2 startnoload +/pushcolor/currentrgbcolor ld +/popcolor/setrgbcolor ld +/setcmykcolor where +{ +pop/currentcmykcolor where +{ +pop/pushcolor/currentcmykcolor ld +/popcolor/setcmykcolor ld +}if +}if +level2 endnoload level2 not startnoload +/pushcolor +{ +currentcolorspace $c eq +{ +currentcolor currentcolorspace true +}{ +currentcmykcolor false +}ifelse +}bd +/popcolor +{ +{ +setcolorspace setcolor +}{ +setcmykcolor +}ifelse +}bd +level2 not endnoload +/pushstatic +{ +ps +2state? +$o +$t +$p +$s +}bd +/popstatic +{ +/$s xs +/$p xs +/$t xs +/$o xs +/2state? xs +/ps xs +}bd +/pushgstate +{ +save errordict/nocurrentpoint{pop 0 0}put +currentpoint +3 -1 roll restore +pushcolor +currentlinewidth +currentlinecap +currentlinejoin +currentdash exch aload length +np clippath pathbbox +$m currentmatrix aload pop +}bd +/popgstate +{ +$m astore setmatrix +2 index sub exch +3 index sub exch +rC +array astore exch setdash +setlinejoin +setlinecap +lw +popcolor +np :M +}bd +/bu +{ +pushgstate +gR +pushgstate +2state? +{ +gR +pushgstate +}if +pushstatic +pm restore +mT concat +}bd +/bn +{ +/pm save store +popstatic +popgstate +gS +popgstate +2state? +{ +gS +popgstate +}if +}bd +/cpat{pop 64 div G 8{pop}repeat}bd +%%EndFile +%%BeginFile: adobe_psp_basic_text +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/S/show ld +/A{ +0.0 exch ashow +}bd +/R{ +0.0 exch 32 exch widthshow +}bd +/W{ +0.0 3 1 roll widthshow +}bd +/J{ +0.0 32 4 2 roll 0.0 exch awidthshow +}bd +/V{ +0.0 4 1 roll 0.0 exch awidthshow +}bd +/fcflg true def +/fc{ +fcflg{ +vmstatus exch sub 50000 lt{ +(%%[ Warning: Running out of memory ]%%\r)print flush/fcflg false store +}if pop +}if +}bd +/$f[1 0 0 -1 0 0]def +/:ff{$f :mf}bd +/MacEncoding StandardEncoding 256 array copy def +MacEncoding 39/quotesingle put +MacEncoding 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/space/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand +/Acircumflex/Ecircumflex/Aacute/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave +/Oacute/Ocircumflex/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +MacEncoding 128 128 getinterval astore pop +level2 startnoload +/copyfontdict +{ +findfont dup length dict +begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +}bd +level2 endnoload level2 not startnoload +/copyfontdict +{ +findfont dup length dict +copy +begin +}bd +level2 not endnoload +md/fontname known not{ +/fontname/customfont def +}if +/Encoding Z +/:mre +{ +copyfontdict +/Encoding MacEncoding def +fontname currentdict +end +definefont :ff def +}bd +/:bsr +{ +copyfontdict +/Encoding Encoding 256 array copy def +Encoding dup +}bd +/pd{put dup}bd +/:esr +{ +pop pop +fontname currentdict +end +definefont :ff def +}bd +/scf +{ +scalefont def +}bd +/scf-non +{ +$m scale :mf setfont +}bd +/ps Z +/fz{/ps xs}bd +/sf/setfont ld +/cF/currentfont ld +/mbf +{ +/makeblendedfont where +{ +pop +makeblendedfont +/ABlend exch definefont +}{ +pop +}ifelse +def +}def +%%EndFile +/currentpacking where {pop sc_oldpacking setpacking}if +end % md +%%EndProlog +%%BeginSetup +md begin +/pT[1 0 0 -1 29.999 761.009]def/mT[.24 0 0 -.24 29.999 761.009]def +/sD 16 dict def +%%IncludeFont: Helvetica +/f0_1/Helvetica :mre +/f1_1 f0_1 1.04 scf +/f1_50 f1_1 50 scf +/Courier findfont[10 0 0 -10 0 0]:mf setfont +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +initializepage +%%EndPageSetup +gS 0 0 2300 3042 rC +0 0 :M +0 setlinecap +currentscreen +3 1 roll pop pop 60 45 3 -1 roll setscreen +2 setlinecap +.75 G +1013 52.5 :M +1062.985 68.166 1088 76 1088 76 :C +1088 76 1062.985 83.832 1013 99.5 :C +962.984 115.165 938 123 938 123 :C +938 123 938 107.332 938 76 :C +938 44.665 938 29 938 29 :C +938 29 962.984 36.832 1013 52.5 :C +8 lw +:K +gS +eofill +gR +0 G +stroke +938 29 :M +0 setlinecap +2 setlinecap +.75 G +1163 52.5 :M +1212.983 68.166 1238 76 1238 76 :C +1238 76 1212.983 83.832 1163 99.5 :C +1112.982 115.165 1088 123 1088 123 :C +1088 123 1088 107.332 1088 76 :C +1088 44.665 1088 29 1088 29 :C +1088 29 1112.982 36.832 1163 52.5 :C +:K +gS +eofill +gR +0 G +stroke +1088 29 :M +0 setlinecap +2 setlinecap +.75 G +1313 52.5 :M +1362.98 68.166 1388 76 1388 76 :C +1388 76 1362.98 83.832 1313 99.5 :C +1262.98 115.165 1238 123 1238 123 :C +1238 123 1238 107.332 1238 76 :C +1238 44.665 1238 29 1238 29 :C +1238 29 1262.98 36.832 1313 52.5 :C +:K +gS +eofill +gR +0 G +stroke +1238 29 :M +0 setlinecap +2 setlinecap +.75 G +1463 52.5 :M +1512.978 68.166 1538 76 1538 76 :C +1538 76 1512.978 83.832 1463 99.5 :C +1412.977 115.165 1388 123 1388 123 :C +1388 123 1388 107.332 1388 76 :C +1388 44.665 1388 29 1388 29 :C +1388 29 1412.977 36.832 1463 52.5 :C +:K +gS +eofill +gR +0 G +stroke +1388 29 :M +0 setlinecap +np 1650 263 :M +1591 277 :L +1591 263 :L +1591 248 :L +1650 263 :L +eofill +36 265 -4 4 1593 261 4 36 261 @a +-4 -4 415 302 4 4 411 261 @b +-4 -4 602 302 4 4 598 261 @b +-4 -4 790 302 4 4 786 261 @b +-4 -4 977 302 4 4 973 261 @b +-4 -4 1165 302 4 4 1161 261 @b +-4 -4 1352 302 4 4 1348 261 @b +-4 -4 1540 302 4 4 1536 261 @b +18 358 :M +f1_50 sf +(0)S +393 358 :M +(1)S +768 358 :M +(2)S +1143 358 :M +(3)S +1518 358 :M +(4)S +4 lw +1551 358 :M +2 setlinecap +.75 G +919 52.5 :M +931.653 68.166 938 76 938 76 :C +938 76 931.653 83.832 919 99.5 :C +906.319 115.165 900 123 900 123 :C +900 123 900 107.332 900 76 :C +900 44.665 900 29 900 29 :C +900 29 906.319 36.832 919 52.5 :C +8 lw +:K +gS +eofill +gR +0 G +stroke +900 29 :M +0 setlinecap +-4 -4 227 302 4 4 223 261 @b +-4 -4 40 302 4 4 36 261 @b +4 lw +36 261 :M +2 setlinecap +.75 G +881.5 52.5 :M +893.82 68.166 900 76 900 76 :C +900 76 893.82 83.832 881.5 99.5 :C +869.153 115.165 863 123 863 123 :C +863 123 863 107.332 863 76 :C +863 44.665 863 29 863 29 :C +863 29 869.153 36.832 881.5 52.5 :C +8 lw +:K +gS +eofill +gR +0 G +stroke +863 29 :M +0 setlinecap +2 setlinecap +.75 G +844 52.5 :M +856.654 68.166 863 76 863 76 :C +863 76 856.654 83.832 844 99.5 :C +831.32 115.165 825 123 825 123 :C +825 123 825 107.332 825 76 :C +825 44.665 825 29 825 29 :C +825 29 831.32 36.832 844 52.5 :C +:K +gS +eofill +gR +0 G +stroke +825 29 :M +0 setlinecap +2 setlinecap +.75 G +806.5 52.5 :M +818.821 68.166 825 76 825 76 :C +825 76 818.821 83.832 806.5 99.5 :C +794.154 115.165 788 123 788 123 :C +788 123 788 107.332 788 76 :C +788 44.665 788 29 788 29 :C +788 29 794.154 36.832 806.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +788 29 :M +0 setlinecap +2 setlinecap +.75 G +769 52.5 :M +781.655 68.166 788 76 788 76 :C +788 76 781.655 83.832 769 99.5 :C +756.321 115.165 750 123 750 123 :C +750 123 750 107.332 750 76 :C +750 44.665 750 29 750 29 :C +750 29 756.321 36.832 769 52.5 :C +:K +gS +eofill +gR +0 G +stroke +750 29 :M +0 setlinecap +2 setlinecap +.75 G +731.5 52.5 :M +743.822 68.166 750 76 750 76 :C +750 76 743.822 83.832 731.5 99.5 :C +719.155 115.165 713 123 713 123 :C +713 123 713 107.332 713 76 :C +713 44.665 713 29 713 29 :C +713 29 719.155 36.832 731.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +713 29 :M +0 setlinecap +2 setlinecap +.75 G +694 52.5 :M +706.656 68.166 713 76 713 76 :C +713 76 706.656 83.832 694 99.5 :C +681.323 115.165 675 123 675 123 :C +675 123 675 107.332 675 76 :C +675 44.665 675 29 675 29 :C +675 29 681.323 36.832 694 52.5 :C +:K +gS +eofill +gR +0 G +stroke +675 29 :M +0 setlinecap +2 setlinecap +.75 G +656.5 52.5 :M +668.823 68.166 675 76 675 76 :C +675 76 668.823 83.832 656.5 99.5 :C +644.157 115.165 638 123 638 123 :C +638 123 638 107.332 638 76 :C +638 44.665 638 29 638 29 :C +638 29 644.157 36.832 656.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +638 29 :M +0 setlinecap +2 setlinecap +.75 G +113 52.5 :M +162.999 68.166 188 76 188 76 :C +188 76 162.999 83.832 113 99.5 :C +62.998 115.165 38 123 38 123 :C +38 123 38 107.332 38 76 :C +38 44.665 38 29 38 29 :C +38 29 62.998 36.832 113 52.5 :C +:K +gS +eofill +gR +0 G +stroke +38 29 :M +0 setlinecap +2 setlinecap +.75 G +263 52.5 :M +312.996 68.166 338 76 338 76 :C +338 76 312.996 83.832 263 99.5 :C +212.996 115.165 188 123 188 123 :C +188 123 188 107.332 188 76 :C +188 44.665 188 29 188 29 :C +188 29 212.996 36.832 263 52.5 :C +:K +gS +eofill +gR +0 G +stroke +188 29 :M +0 setlinecap +2 setlinecap +.75 G +413 52.5 :M +462.994 68.166 488 76 488 76 :C +488 76 462.994 83.832 413 99.5 :C +362.993 115.165 338 123 338 123 :C +338 123 338 107.332 338 76 :C +338 44.665 338 29 338 29 :C +338 29 362.993 36.832 413 52.5 :C +:K +gS +eofill +gR +0 G +stroke +338 29 :M +0 setlinecap +2 setlinecap +.75 G +563 52.5 :M +612.992 68.166 638 76 638 76 :C +638 76 612.992 83.832 563 99.5 :C +512.991 115.165 488 123 488 123 :C +488 123 488 107.332 488 76 :C +488 44.665 488 29 488 29 :C +488 29 512.991 36.832 563 52.5 :C +:K +gS +eofill +gR +0 G +stroke +488 29 :M +0 setlinecap +endp +%%Trailer +end % md +%%EOF diff --git a/docsrc/nyquist/warponsetfig.ps b/docsrc/nyquist/warponsetfig.ps new file mode 100644 index 0000000..76720cf --- /dev/null +++ b/docsrc/nyquist/warponsetfig.ps @@ -0,0 +1,864 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 31 670 426 755 +%%Title: (warponsetfig-Layer#1) +%%Creator: (MacDraw II 1.1v2: LaserWriter 8 8.1.1) +%%CreationDate: (10:28 PM Sunday, January 24, 1904) +%%For: (Dannenberg) +%%Pages: 1 +%%DocumentFonts: Helvetica +%%DocumentNeededFonts: Helvetica +%%DocumentSuppliedFonts: +%%DocumentData: Clean7Bit +%%PageOrder: Ascend +%%Orientation: Portrait +%ADO_PaperArea: -129 -125 3171 2425 +%ADO_ImageableArea: 0 0 3042 2300 +%%EndComments +/md 149 dict def md begin +/currentpacking where {pop /sc_oldpacking currentpacking def true setpacking}if +%%BeginFile: adobe_psp_basic +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/bd{bind def}bind def +/xdf{exch def}bd +/xs{exch store}bd +/ld{load def}bd +/Z{0 def}bd +/T/true +/F/false +/:L/lineto +/lw/setlinewidth +/:M/moveto +/rl/rlineto +/rm/rmoveto +/:C/curveto +/:T/translate +/:K/closepath +/:mf/makefont +/gS/gsave +/gR/grestore +/np/newpath +14{ld}repeat +/$m matrix def +/av 81 def +/por true def +/normland false def +/psb-nosave{}bd +/pse-nosave{}bd +/us Z +/psb{/us save store}bd +/pse{us restore}bd +/level2 +/languagelevel where +{ +pop languagelevel 2 ge +}{ +false +}ifelse +def +/featurecleanup +{ +stopped +cleartomark +countdictstack exch sub dup 0 gt +{ +{end}repeat +}{ +pop +}ifelse +}bd +/noload Z +/startnoload +{ +{/noload save store}if +}bd +/endnoload +{ +{noload restore}if +}bd +level2 startnoload +/setjob +{ +statusdict/jobname 3 -1 roll put +}bd +/setcopies +{ +userdict/#copies 3 -1 roll put +}bd +level2 endnoload level2 not startnoload +/setjob +{ +1 dict begin/JobName xdf currentdict end setuserparams +}bd +/setcopies +{ +1 dict begin/NumCopies xdf currentdict end setpagedevice +}bd +level2 not endnoload +/pm Z +/mT Z +/sD Z +/realshowpage Z +/initializepage +{ +/pm save store mT concat +}bd +/endp +{ +pm restore showpage +}def +/$c/DeviceRGB def +/rectclip where +{ +pop/rC/rectclip ld +}{ +/rC +{ +np 4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +clip np +}bd +}ifelse +/rectfill where +{ +pop/rF/rectfill ld +}{ +/rF +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +fill +gR +}bd +}ifelse +/rectstroke where +{ +pop/rS/rectstroke ld +}{ +/rS +{ +gS +np +4 2 roll +:M +1 index 0 rl +0 exch rl +neg 0 rl +:K +stroke +gR +}bd +}ifelse +%%EndFile +%%BeginFile: adobe_psp_colorspace_level1 +%%Copyright: Copyright 1991-1993 Adobe Systems Incorporated. All Rights Reserved. +/G/setgray ld +/:F/setrgbcolor ld +%%EndFile +%%BeginFile: adobe_psp_uniform_graphics +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/@a +{ +np :M 0 rl :L 0 exch rl 0 rl :L fill +}bd +/@b +{ +np :M 0 rl 0 exch rl :L 0 rl 0 exch rl fill +}bd +/arct where +{ +pop +}{ +/arct +{ +arcto pop pop pop pop +}bd +}ifelse +/x1 Z +/x2 Z +/y1 Z +/y2 Z +/rad Z +/@q +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +fill +}bd +/@s +{ +/rad xs +/y2 xs +/x2 xs +/y1 xs +/x1 xs +np +x2 x1 add 2 div y1 :M +x2 y1 x2 y2 rad arct +x2 y2 x1 y2 rad arct +x1 y2 x1 y1 rad arct +x1 y1 x2 y1 rad arct +:K +stroke +}bd +/@i +{ +np 0 360 arc fill +}bd +/@j +{ +gS +np +:T +scale +0 0 .5 0 360 arc +fill +gR +}bd +/@e +{ +np +0 360 arc +:K +stroke +}bd +/@f +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 0 360 arc +:K +$m setmatrix +stroke +}bd +/@k +{ +gS +np +:T +0 0 :M +0 0 5 2 roll +arc fill +gR +}bd +/@l +{ +gS +np +:T +0 0 :M +scale +0 0 .5 5 -2 roll arc +fill +gR +}bd +/@m +{ +np +arc +stroke +}bd +/@n +{ +np +$m currentmatrix +pop +:T +scale +0 0 .5 5 -2 roll arc +$m setmatrix +stroke +}bd +%%EndFile +%%BeginFile: adobe_psp_customps +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/$t Z +/$p Z +/$s Z +/$o 1. def +/2state? false def +/ps Z +level2 startnoload +/pushcolor/currentrgbcolor ld +/popcolor/setrgbcolor ld +/setcmykcolor where +{ +pop/currentcmykcolor where +{ +pop/pushcolor/currentcmykcolor ld +/popcolor/setcmykcolor ld +}if +}if +level2 endnoload level2 not startnoload +/pushcolor +{ +currentcolorspace $c eq +{ +currentcolor currentcolorspace true +}{ +currentcmykcolor false +}ifelse +}bd +/popcolor +{ +{ +setcolorspace setcolor +}{ +setcmykcolor +}ifelse +}bd +level2 not endnoload +/pushstatic +{ +ps +2state? +$o +$t +$p +$s +}bd +/popstatic +{ +/$s xs +/$p xs +/$t xs +/$o xs +/2state? xs +/ps xs +}bd +/pushgstate +{ +save errordict/nocurrentpoint{pop 0 0}put +currentpoint +3 -1 roll restore +pushcolor +currentlinewidth +currentlinecap +currentlinejoin +currentdash exch aload length +np clippath pathbbox +$m currentmatrix aload pop +}bd +/popgstate +{ +$m astore setmatrix +2 index sub exch +3 index sub exch +rC +array astore exch setdash +setlinejoin +setlinecap +lw +popcolor +np :M +}bd +/bu +{ +pushgstate +gR +pushgstate +2state? +{ +gR +pushgstate +}if +pushstatic +pm restore +mT concat +}bd +/bn +{ +/pm save store +popstatic +popgstate +gS +popgstate +2state? +{ +gS +popgstate +}if +}bd +/cpat{pop 64 div G 8{pop}repeat}bd +%%EndFile +%%BeginFile: adobe_psp_basic_text +%%Copyright: Copyright 1990-1993 Adobe Systems Incorporated. All Rights Reserved. +/S/show ld +/A{ +0.0 exch ashow +}bd +/R{ +0.0 exch 32 exch widthshow +}bd +/W{ +0.0 3 1 roll widthshow +}bd +/J{ +0.0 32 4 2 roll 0.0 exch awidthshow +}bd +/V{ +0.0 4 1 roll 0.0 exch awidthshow +}bd +/fcflg true def +/fc{ +fcflg{ +vmstatus exch sub 50000 lt{ +(%%[ Warning: Running out of memory ]%%\r)print flush/fcflg false store +}if pop +}if +}bd +/$f[1 0 0 -1 0 0]def +/:ff{$f :mf}bd +/MacEncoding StandardEncoding 256 array copy def +MacEncoding 39/quotesingle put +MacEncoding 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/space/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand +/Acircumflex/Ecircumflex/Aacute/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave +/Oacute/Ocircumflex/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +MacEncoding 128 128 getinterval astore pop +level2 startnoload +/copyfontdict +{ +findfont dup length dict +begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +}bd +level2 endnoload level2 not startnoload +/copyfontdict +{ +findfont dup length dict +copy +begin +}bd +level2 not endnoload +md/fontname known not{ +/fontname/customfont def +}if +/Encoding Z +/:mre +{ +copyfontdict +/Encoding MacEncoding def +fontname currentdict +end +definefont :ff def +}bd +/:bsr +{ +copyfontdict +/Encoding Encoding 256 array copy def +Encoding dup +}bd +/pd{put dup}bd +/:esr +{ +pop pop +fontname currentdict +end +definefont :ff def +}bd +/scf +{ +scalefont def +}bd +/scf-non +{ +$m scale :mf setfont +}bd +/ps Z +/fz{/ps xs}bd +/sf/setfont ld +/cF/currentfont ld +/mbf +{ +/makeblendedfont where +{ +pop +makeblendedfont +/ABlend exch definefont +}{ +pop +}ifelse +def +}def +%%EndFile +/currentpacking where {pop sc_oldpacking setpacking}if +end % md +%%EndProlog +%%BeginSetup +md begin +/pT[1 0 0 -1 29.999 761.009]def/mT[.24 0 0 -.24 29.999 761.009]def +/sD 16 dict def +%%IncludeFont: Helvetica +/f0_1/Helvetica :mre +/f1_1 f0_1 1.04 scf +/f1_50 f1_1 50 scf +/Courier findfont[10 0 0 -10 0 0]:mf setfont +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +initializepage +%%EndPageSetup +gS 0 0 2300 3042 rC +0 0 :M +0 setlinecap +currentscreen +3 1 roll pop pop 60 45 3 -1 roll setscreen +np 1650 263 :M +1591 277 :L +1591 263 :L +1591 248 :L +1650 263 :L +eofill +36 265 -4 4 1593 261 4 36 261 @a +-4 -4 415 302 4 4 411 261 @b +-4 -4 602 302 4 4 598 261 @b +-4 -4 790 302 4 4 786 261 @b +-4 -4 977 302 4 4 973 261 @b +-4 -4 1165 302 4 4 1161 261 @b +-4 -4 1352 302 4 4 1348 261 @b +-4 -4 1540 302 4 4 1536 261 @b +18 358 :M +f1_50 sf +(0)S +393 358 :M +(1)S +768 358 :M +(2)S +1143 358 :M +(3)S +1518 358 :M +(4)S +4 lw +1551 358 :M +2 setlinecap +.75 G +82.5 52.5 :M +112.166 68.166 127 76 127 76 :C +127 76 112.166 83.832 82.5 99.5 :C +52.832 115.165 38 123 38 123 :C +38 123 38 107.332 38 76 :C +38 44.665 38 29 38 29 :C +38 29 52.832 36.832 82.5 52.5 :C +8 lw +:K +gS +eofill +gR +0 G +stroke +38 29 :M +0 setlinecap +2 setlinecap +.75 G +232.5 52.5 :M +262.163 68.166 277 76 277 76 :C +277 76 262.163 83.832 232.5 99.5 :C +202.83 115.165 188 123 188 123 :C +188 123 188 107.332 188 76 :C +188 44.665 188 29 188 29 :C +188 29 202.83 36.832 232.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +188 29 :M +0 setlinecap +2 setlinecap +.75 G +382.5 52.5 :M +412.161 68.166 427 76 427 76 :C +427 76 412.161 83.832 382.5 99.5 :C +352.827 115.165 338 123 338 123 :C +338 123 338 107.332 338 76 :C +338 44.665 338 29 338 29 :C +338 29 352.827 36.832 382.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +338 29 :M +0 setlinecap +2 setlinecap +.75 G +532.5 52.5 :M +562.159 68.166 577 76 577 76 :C +577 76 562.159 83.832 532.5 99.5 :C +502.825 115.165 488 123 488 123 :C +488 123 488 107.332 488 76 :C +488 44.665 488 29 488 29 :C +488 29 502.825 36.832 532.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +488 29 :M +0 setlinecap +2 setlinecap +.75 G +682.5 52.5 :M +712.156 68.166 727 76 727 76 :C +727 76 712.156 83.832 682.5 99.5 :C +652.823 115.165 638 123 638 123 :C +638 123 638 107.332 638 76 :C +638 44.665 638 29 638 29 :C +638 29 652.823 36.832 682.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +638 29 :M +0 setlinecap +2 setlinecap +.75 G +720 52.5 :M +749.989 68.166 765 76 765 76 :C +765 76 749.989 83.832 720 99.5 :C +689.989 115.165 675 123 675 123 :C +675 123 675 107.332 675 76 :C +675 44.665 675 29 675 29 :C +675 29 689.989 36.832 720 52.5 :C +:K +gS +eofill +gR +0 G +stroke +675 29 :M +0 setlinecap +2 setlinecap +.75 G +757.5 52.5 :M +787.155 68.166 802 76 802 76 :C +802 76 787.155 83.832 757.5 99.5 :C +727.822 115.165 713 123 713 123 :C +713 123 713 107.332 713 76 :C +713 44.665 713 29 713 29 :C +713 29 727.822 36.832 757.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +713 29 :M +0 setlinecap +2 setlinecap +.75 G +795 52.5 :M +824.988 68.166 840 76 840 76 :C +840 76 824.988 83.832 795 99.5 :C +764.988 115.165 750 123 750 123 :C +750 123 750 107.332 750 76 :C +750 44.665 750 29 750 29 :C +750 29 764.988 36.832 795 52.5 :C +:K +gS +eofill +gR +0 G +stroke +750 29 :M +0 setlinecap +2 setlinecap +.75 G +832.5 52.5 :M +862.154 68.166 877 76 877 76 :C +877 76 862.154 83.832 832.5 99.5 :C +802.82 115.165 788 123 788 123 :C +788 123 788 107.332 788 76 :C +788 44.665 788 29 788 29 :C +788 29 802.82 36.832 832.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +788 29 :M +0 setlinecap +2 setlinecap +.75 G +870 52.5 :M +899.987 68.166 915 76 915 76 :C +915 76 899.987 83.832 870 99.5 :C +839.986 115.165 825 123 825 123 :C +825 123 825 107.332 825 76 :C +825 44.665 825 29 825 29 :C +825 29 839.986 36.832 870 52.5 :C +:K +gS +eofill +gR +0 G +stroke +825 29 :M +0 setlinecap +2 setlinecap +.75 G +907.5 52.5 :M +937.153 68.166 952 76 952 76 :C +952 76 937.153 83.832 907.5 99.5 :C +877.819 115.165 863 123 863 123 :C +863 123 863 107.332 863 76 :C +863 44.665 863 29 863 29 :C +863 29 877.819 36.832 907.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +863 29 :M +0 setlinecap +2 setlinecap +.75 G +945 52.5 :M +974.986 68.166 990 76 990 76 :C +990 76 974.986 83.832 945 99.5 :C +914.985 115.165 900 123 900 123 :C +900 123 900 107.332 900 76 :C +900 44.665 900 29 900 29 :C +900 29 914.985 36.832 945 52.5 :C +:K +gS +eofill +gR +0 G +stroke +900 29 :M +0 setlinecap +2 setlinecap +.75 G +982.5 52.5 :M +1012.152 68.166 1027 76 1027 76 :C +1027 76 1012.152 83.832 982.5 99.5 :C +952.818 115.165 938 123 938 123 :C +938 123 938 107.332 938 76 :C +938 44.665 938 29 938 29 :C +938 29 952.818 36.832 982.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +938 29 :M +0 setlinecap +2 setlinecap +.75 G +1132.5 52.5 :M +1162.15 68.166 1177 76 1177 76 :C +1177 76 1162.15 83.832 1132.5 99.5 :C +1102.816 115.165 1088 123 1088 123 :C +1088 123 1088 107.332 1088 76 :C +1088 44.665 1088 29 1088 29 :C +1088 29 1102.816 36.832 1132.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +1088 29 :M +0 setlinecap +2 setlinecap +.75 G +1282.5 52.5 :M +1312.147 68.166 1327 76 1327 76 :C +1327 76 1312.147 83.832 1282.5 99.5 :C +1252.814 115.165 1238 123 1238 123 :C +1238 123 1238 107.332 1238 76 :C +1238 44.665 1238 29 1238 29 :C +1238 29 1252.814 36.832 1282.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +1238 29 :M +0 setlinecap +2 setlinecap +.75 G +1432.5 52.5 :M +1462.145 68.166 1477 76 1477 76 :C +1477 76 1462.145 83.832 1432.5 99.5 :C +1402.811 115.165 1388 123 1388 123 :C +1388 123 1388 107.332 1388 76 :C +1388 44.665 1388 29 1388 29 :C +1388 29 1402.811 36.832 1432.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +1388 29 :M +0 setlinecap +2 setlinecap +.75 G +1432.5 52.5 :M +1462.145 68.166 1477 76 1477 76 :C +1477 76 1462.145 83.832 1432.5 99.5 :C +1402.811 115.165 1388 123 1388 123 :C +1388 123 1388 107.332 1388 76 :C +1388 44.665 1388 29 1388 29 :C +1388 29 1402.811 36.832 1432.5 52.5 :C +:K +gS +eofill +gR +0 G +stroke +1388 29 :M +0 setlinecap +-4 -4 227 302 4 4 223 261 @b +-4 -4 40 302 4 4 36 261 @b +endp +%%Trailer +end % md +%%EOF diff --git a/docsrc/s2h/citations.lsp b/docsrc/s2h/citations.lsp new file mode 100644 index 0000000..b7208aa --- /dev/null +++ b/docsrc/s2h/citations.lsp @@ -0,0 +1,21 @@ +(expand 100) + +(setf *citations* '( + (Anderson "../JITLBIB.HTM#anderson" "(Anderson 1985)") + (Beare "../JITLBIB.HTM#beare" "(Beare 1989)") + (Bloom "../JITLBIB.HTM#bloom" "(Bloom 1956)") + (Capell "../JITLBIB.HTM#capell" "(Capell 1995)") + (ptinterface "../JITLBIB.HTM#dannenberg" "(Dannenberg 1990)") + (Fletcher "../JITLBIB.HTM#fletcher" "(Fletcher 1990)") + (Ford "../JITLBIB.HTM#ford" "(Ford 1959)") + (Lehman "../JITLBIB.HTM#lehman" "(Lehman 1993)") + (Moore "../JITLBIB.HTM#moore96" "(Moore 1996)") + (Moore97 "../JITLBIB.HTM#moore97" "(Moore 1997)") + (Pflieger "../JITLBIB.HTM#pflieger" "(Pflieger 1961)") + (Russell "../JITLBIB.HTM#russel" "(Russell 1997)") + (Whittington "../JITLBIB.HTM#whittington" "(Whittington 1989)") + + (touretzky "musicbib.html#touretzky" "(Touretzky 1984)") + (icmcfugue "http://www.cs.cmu.edu/~rbd/bib-arctic.html#icmcfugue" "(Dannenberg and Frayley 1989)"))) + + diff --git a/docsrc/s2h/do-nyquist-manual.lsp b/docsrc/s2h/do-nyquist-manual.lsp new file mode 100644 index 0000000..87c9e5d --- /dev/null +++ b/docsrc/s2h/do-nyquist-manual.lsp @@ -0,0 +1,6 @@ +;; build html for nyquist manual +(load "s2h") +(expand 10) +;; sourcedir source destdir dest +(g "../nyquist" "nyquistman" "../../doc" "home" t) +(g "../nyquist" "nyquistman" "../../doc" "home" t) diff --git a/docsrc/s2h/s2h.lsp b/docsrc/s2h/s2h.lsp new file mode 100644 index 0000000..09490e3 --- /dev/null +++ b/docsrc/s2h/s2h.lsp @@ -0,0 +1,1642 @@ +; s2h -- scribe to html + +; MajorHeading = H1 +; Chapter, Unnumbered, Appendix = H2 +; Section = Heading = H3 +; SubSection = SubHeading = H4 +; Paragraph = H5 + +; Files: +; *dest* -- the title and table of contents +; part1.html -- for each unnumbered, chapter, appendix, +; at end of each part, link to: next part, +; index, and table of contents +; at beginning of each part, link to: prev part, +; next part, index, and table of contents +; indx.html -- the index (not "index", because that's a special name) +; title.html -- the title page and table of contents +; guide.html -- the table of contents and index for left frame +; home.html -- the top-level document with two frames, the actual name +; of this file is given by the dest parameter of (G ...) +; NyquistWords.txt -- completion list file + + +; Fancy control: +; add the following to Scribe file: +; @textform(html = []) +; @textform(htmltitle = []) +; @textform(pragma = []) +; To get a title, add this to the file: +; @html(Your Title Here) +; If you use frames, you should add this to the scribe document: +; @htmltitle(Your Title Here) +; This tells the translator the html title to use for the root +; html file. +; anything inside @html{...} is output directly to output html file +; anything in the @pragma{...} is executed as a command to this translator +; some pragma commands are: +; defn -- the next @index() marks a term's definition in the manual +; startscribe -- ignore scribe file starting here +; endscribe -- stop ignoring scribe file +; startref -- use text between here and an @ref or @pageref as link text +; doinclude -- process the next include file (default is to ignore) +; endcodef -- end a code definition (used for completion list) +; citations are translated to links according to data in citations.lsp +; (the actual bibliographic references must be hand-translated to HTML) +; alter *bgcolorinfo* to set background color of html documents +; set *8.3* to change from "indx.html" to "INDX.HTM" format for file names + +;; label-list shall look like this: +;; ((label-symbol "label text" file-name number) ...) +;; where label-symbol is the scribe label, +;; and the rest is used like this: +;; label text +(cond ((boundp '*label-list*) + (setf *previous-label-list* *label-list*))) +(setf *label-list* nil) + +;; number of parts must be obtained from previous pass +(cond ((boundp '*number-of-parts*) + (setf *previous-number-of-parts* *number-of-parts*))) +(setf *number-of-parts* nil) + +(cond ((not (boundp '*citations*)) + (load (strcat (current-path) "/citations.lsp")))) + +;; set this to trace parser input to help locate errors in input file +(cond ((not (boundp '*token-trace*)) + (setf *token-trace* nil))) + +(cond ((and (boundp '*inf*) *inf*) + (format t "closing *inf*\n") + (setf *inf* nil))) +(cond ((and (boundp '*footnotefile*) *footnotefile*) + (format t "closing *footnotefile*\n") + (close *footnotefile*) + (setf *footnotefile* nil))) +(cond ((and (boundp '*outf*) *outf*) + (setf *outf* nil))) + +;; when @pragma(defn) is seen, this flag is set to t, when +;; the following @index(...) is seen, the flag is cleared and +;; the index is entered as a definition of the term, meaning +;; the referenced location will go to the head of the list. +;; Later, when we want to find help for a term, we know that +;; the help information is located by the first entry in the +;; index for this term. +(setf definition-flag nil) + +(defun open-paren () + (let ((tok (get-token))) + (cond ((member tok '(#\( #\{ #\[ #\<)) + (push tok paren-stack)) + (t + (push tok *next-tokens*) + ;; if no open paren, then fake open and close + (push #\( paren-stack) + (push #\) *next-tokens*))))) + + +;; ((label-symbol "label text" file-name number) ...) +(defun write-label () + (let ((body (get-body "label" nil))) + (push (list (list-to-symbol body) *name-reference* + *file-name* *name-number*) + *label-list*))) + +(defun do-make () + (let ((what (get-body "make" nil))) + (setf what (string-upcase + (list-to-string what))) + (setf what (intern what)) + (cond ((member what '(manual article)) + (setf *document-type* what)) + (t + (format t "Unknown document type: ~A, assuming ARTICLE~%" what) + (setf *document-type* 'ARTICLE))))) + +(defun get-body (what spacesok) + (prog (tok body) +loop + (setf tok (get-token)) + (cond ((not (characterp tok)) + (format t "expected characters in ~A: ~A\n" what tok)) + ((paren-match tok) + (pop paren-stack) + (return (reverse body))) + ((and (not spacesok) (eql #\Space tok))) + ((null tok) + (format t "early end of file\n") + (break)) + (t + (push tok body))) + (go loop))) + + +(defun write-code () + (if *omit* nil (format *outf* "")) + (translate) + (if *omit* nil (format *outf* ""))) + +(defun write-codef () + (progv '(*codef*) '(t) (write-code) (codef-complete))) + +(defun write-quotation () + (format *outf* "
") + (translate) + (format *outf* "
")) + +(defun write-normal () + (format *outf* "") + (translate) + (format *outf* "")) + +(defun write-t () + (let (paren) + (format *outf* "") + (translate) + (format *outf* ""))) + +(defun list-to-string (body) + (let ((str "")) + (dolist (ch body) + (setf str (strcat str (string ch)))) + str)) + +(defun list-to-symbol (body) + (setf cmd (intern (string-upcase (list-to-string body))))) + +;; index-casify -- first letter upper, all others lower +;; +(defun index-casify (item) + (nstring-downcase item) + (nstring-upcase item :start 0 :end 1)) + +(defun enter-index-item (item def-flag) + (setf item (index-casify item)) + (setf *index-number* (1+ *index-number*)) + (let ((entry (assoc item *index-list* :test #'equal)) + (ref (list *file-name* *index-number*)) + front) + (cond ((and entry def-flag) + ;; put new reference at beginning of list + (rplacd entry (cons ref (cdr entry)))) + (entry + (nconc entry (list ref))) + (t + (push (list item ref) *index-list*))) + *index-number*)) + +(defun write-index (&optional def-flag) + (let (body str n) + (setf body (get-body "index" t)) + (setf str (list-to-string body)) + (if *token-trace* (format t "Index item: ~A~%" str)) + (setf n (enter-index-item str def-flag)) + (format *outf* "" n))) + +(defun index-sort-fn (a b) + (string< (car a) (car b))) + +(defun mysort (list) + (setf list (cons 'header list)) + (prog (first ptr result) +loop1 + (cond ((null (cdr list)) + (return result))) +; (display "loop1" list result) + (setf first list) + (setf ptr (cdr first)) +loop + (cond ((null (cdr ptr)) + (go gotone)) + ((index-sort-fn (cadr first) (cadr ptr)) + (setf first ptr))) + (setf ptr (cdr ptr)) + (go loop) +gotone + (push (cadr first) result) + (rplacd first (cddr first)) + (go loop1))) + +(cond ((not (boundp '*bgcolorinfo*)) + (setf *bgcolorinfo* " bgcolor=\"ffffff\""))) +(cond ((not (boundp '*8.3*)) + (setf *8.3* nil))) + +(defun html-file (namestring) + (cond (*8.3* + (setf namestring (string-upcase namestring)) + (cond ((> (length namestring) 8) + (setf namestring (subseq namestring 0 8)))) + (strcat namestring ".HTM")) + (t + (strcat namestring ".html")))) + +(defun generate-index-entry (entry target) + (let (n) + ;; if only one target for index entry, make the word be a link + (cond ((= 1 (length (cdr entry))) + (format *outf* "~A
~%" + (caadr entry) (cadadr entry) target (car entry))) + (t + (setf n 1) + ; (car entry) may have formatting commands... + (format *outf* "~A" (car entry)) + (dolist (ref (cdr entry)) + (format *outf* " ~A " + (car ref) (cadr ref) target n) + (setf n (1+ n))) + (format *outf* "
\n"))))) + +;; HAS-ALPHA - trim non-alpha from beginning of key and capitalize +;; returns: nil if no alpha chars, *rslt* = key without non-alpha prefix +;; +(defun has-alpha (key) + (while (and (> (length key) 0) + (not (both-case-p (char key 0)))) + (setf key (subseq key 1))) + (setf *rslt* key) + ;(display "non-alpha" key) + (cond ((> (length key) 0) + (setf *rslt* (index-casify *rslt*)) + t) + (t nil))) + + +;; FIX-NON-ALPHA -- duplicate non-alpha entries that have an alpha char +;; and make all entries have sort keys +(defun fix-non-alpha (lis) + (let (rslt) + (dolist (entry lis) + (setf key (car entry)) + (push (cons key entry) rslt) + (cond ((both-case-p (char key 0)) nil) ;; normal alpha key + ((has-alpha key) + (push (cons *rslt* entry) rslt)))) + rslt)) + + +;; GENERATE-INDEX -- generate the index and write to outf +;; +;; if frame-flag is provided, it signals that the output goes +;; to an already open file, which is in fact the value of frame-flag +;; This would be the second time generate-index is called, so the +;; preprocessing and sorting is not needed when frame-flag is a file +;; +(defun generate-index (&optional frame-flag) + (let (n target initial-char) + (setf *outf* (if frame-flag frame-flag + (open (strcat *dest-dir* (html-file "indx")) + :direction :output))) + (cond (frame-flag t) + (t + (incf *part-number*) + (display "generate-index top" *part-number*) + (write-chapter-links t t) + (setf *index-list* (fix-non-alpha *index-list*)) + (setf *index-list* (mysort *index-list*)) + (generate-index-chars) + (format *outf* "Index\n") + (format *outf* "" *bgcolorinfo*))) + (setf initial-char (car *index-chars*)) + (format *outf* "

Index

~%") + (setf target (if frame-flag " target=m" "")) + (format *outf* "

~A

~%" + initial-char initial-char) + (format *outf* "TOP
~%") + ;; generate all non-alpha entries + (dolist (entry *index-list*) + (cond ((both-case-p (char (car entry) 0))) + (t + (generate-index-entry (cdr entry) target)))) + ;; generate A - Z + (dolist (entry *index-list*) + ;; put headings for every new starting character + (let ((c (char (car entry) 0))) + (cond ((not (both-case-p c)) nil) ; ignore non-alphas here + ((eql initial-char (char (car entry) 0))) ; no change + (t + (setf initial-char (char (car entry) 0)) + (format *outf* "

~A

~%" + initial-char initial-char) + (format *outf* "TOP
~%"))) + (if (both-case-p c) + (generate-index-entry (cdr entry) target)))) + (cond (frame-flag t) + (t (display "generate-index bottom" *part-number*) + (write-chapter-links nil t) + (format t "closing indx.html\n") + (close *outf*))))) + + +;; GENERATE-TOC-2 -- generate table of contents body +;; +;; if frame-flag is t, generate html for left frame +;; output to *outf* +;; +(defun generate-toc-2 (lis &optional frame-flag) + (format *outf* "
    \n") + (dolist (lis1 lis) + (let (lis2 target) + (setf lis1 (reverse lis1)) + (setf lis2 (car lis1)) +; (display "part1" lis2) + (if frame-flag (setf target " target=\"m\"")) + (format *outf* "
  • ~A\n" + ;filename ;ref-number ;target ;name + (car lis2) (cadr lis2) target (caddr lis2)) + (setf lis2 (cdr lis1)) +; (display "part2" lis2) + (cond (lis2 + (generate-toc-2 lis2 frame-flag))))) + (format *outf* "
\n")) + + +(defun generate-toc (&optional frame-flag) + (format *outf* "\n") + (format *outf* "

Table of Contents

\n") + (generate-toc-2 (reverse *chapter-list*) frame-flag) + (cond (frame-flag t) + (t + (format *outf* "
" + (html-file "indx"))))) + + +(defun get-primary (str) + (get-string-after "primary" str)) + +(defun get-secondary (str) + (get-string-after "secondary" str)) + +(defun get-string-after (key str) + (let ((n (string-search key str)) + m) + (cond ((null n) + (format t "get-string-after could not find ~A in ~A~%" + key str) + (break))) + (setf n (+ n (length key))) + (display "a" n) + (setf n (string-search "\"" str :start n)) + (display "b" n) + (cond ((null n) + (format t "get-string-after: no quote after ~A in ~A~%" + key str) + (break))) + (setf n (1+ n)) + (setf m (string-search "\"" str :start n)) + (display "c" m) + (cond ((null m) + (format t + "get-string-after: no close quote after ~A in ~A~%" + key str) + (break))) + (subseq str n m))) + +(defun write-indexsecondary () + (let (body str n) + (setf body (get-body "secondaryindex" t)) + (setf str (list-to-string body)) + (if *token-trace* (format t "SecondaryIndex item: ~A~%" str)) + (setf str (strcat (get-primary str) ", " (get-secondary str))) + (setf n (enter-index-item str nil)) + (format *outf* "" str n))) + + +(defun read-begin-command () + (let (cmd n + (body (get-body "begin" nil))) + (setf cmd (list-to-string body)) + (setf n (string-search "," cmd)) + (cond (n + (format t + "warning: dropping parameters after comma in @begin(~A)~%" + cmd) + (setf cmd (subseq cmd 0 n)))) + (setf cmd (intern (string-upcase cmd))) + (push cmd paren-stack) + cmd)) + + +(defun read-end-command () + (let (cmd + (body (get-body "end" nil))) + (setf cmd (list-to-symbol body)) + (list 'end cmd))) + +(defun read-pragma-command () + (let ((body (get-body "end" nil)) cmd) + (setf cmd (list-to-symbol body)) + cmd)) + +(defun write-style (style) + (format *outf* "<~A>" style) + (translate) + (format *outf* "" style)) + +(defun write-bold-italic () + (format *outf* "") + (translate) + (format *outf* "")) + +(defun write-superscript () + (output-char #\^) + (output-char #\() + (translate) + (output-char #\))) + +(defun write-subscript () +; (output-char #\[) + (translate) +; (output-char #\]) + ) + +(defun write-dd () + (if (and *description* (not *omit*)) + (format *outf* "
"))) + +(defun write-description () + (format *outf* "
\n
") + (progv '(*description*) '(t) + (translate)) + (format *outf* "
")) + +(defun write-fdescription () + (format *outf* "
\n
") + (progv '(*fdescription*) '(t) + (progv '(*codef*) '(t) + (translate) + (codef-complete))) + (format *outf* "
")) + +(defun write-fgroup () + (progv '(*fgroup*) '(t) +; (format *outf* " enter fgroup ") + (translate))) +; (format *outf* " exit fgroup ") + +(defun write-pdescription () + (let ((pdesc *pdescription*)) + (if pdesc (format *outf* "
")) + (format *outf* "
") + (setf *pdescription* t) + (codef-complete) ;; finish preceding function completion string + (progv '(*codef*) '(nil) + (translate)) + (setf *codef* t) ;; turn back on for next definition + (if pdesc (format *outf* "
")) + (setf *pdescription* pdesc))) + +(defun close-paren-p (tok) + (or (and (listp tok) + (eq (car tok) 'end)) + (paren-match tok))) + + +(defun paren-match (p2) + (let ((p1 (car paren-stack))) + (or (and (eql p2 #\)) + (eql p1 #\()) + (and (eql p2 #\]) + (eql p1 #\[)) + (and (eql p2 #\}) + (eql p1 #\{)) + (and (eql p2 #\>) + (eql p1 #\<)) + (and (listp p2) + (eq (car p2) 'end) + (eq p1 (cadr p2)))))) + +(defun skip-it () + (let ((omit *omit*)) + (setf *omit* t) + (translate) + (setf *omit* omit))) + +(defun write-titlepage () + (translate)) + + +(defun write-titlebox () + (translate)) + +(defun write-majorheading () + (format *outf* "

") + (translate) + (format *outf* "

")) + +(defun write-h2 () + (format *outf* "

") + (translate) + (format *outf* "

")) + +(defun write-h3 () + (format *outf* "

") + (translate) + (format *outf* "

")) + +(defun write-h4 () + (format *outf* "

") + (translate) + (format *outf* "

")) + +(defun write-paragraph () + (let ((body (get-body "paragraph" t))) + (setf body (list-to-string body)) + (setf *name-reference* (format nil "\"~A\"" body)) + (setf *name-number* (1+ *name-number*)) + (push (list (list *file-name* *name-number* body)) *paragraph-list*) + (format *outf* "
~A
" *name-number* body))) + +(defun finish-subsection () + (push *paragraph-list* *subsection-list*) + (setf *paragraph-list* nil)) + +(defun write-subsection () + (let ((body (get-body "subsection" t))) + (setf body (list-to-string body)) + (setf *name-reference* (format nil "\"~A\"" body)) + (setf *name-number* (1+ *name-number*)) + (cond (*paragraph-list* + (finish-subsection))) + (setf *paragraph-list* + (list (list *file-name* *name-number* body))) + (format *outf* "

~A

" *name-number* body))) + + +(defun finish-section () + (cond (*paragraph-list* + (finish-subsection))) + (push *subsection-list* *section-list*) + (setf *subsection-list* nil)) + +(defun write-section () + (let ((body (get-body "section" t))) + (setf body (list-to-string body)) + (setf *name-reference* (format nil "\"~A\"" body)) + (setf *name-number* (1+ *name-number*)) + (cond (*subsection-list* + (finish-section))) + (setf *subsection-list* + (list (list *file-name* *name-number* body))) + (format *outf* "

~A

" *name-number* body))) + +(defun previous-part-file-name () + (cond ((> *part-number* 2) + (html-file (format nil "part~A" (- *part-number* 2)))) + (t *dest*))) + +;; called when new chapter is encountered, +;; lastflag = nil means write a Next Section link +(defun finish-chapter () + (cond (*subsection-list* + (finish-section))) + (push *section-list* *chapter-list*) + (setf *section-list* nil) + ; *dest* links get added after table of contents + (cond ((not (eq *outf* *rootf*)) + (write-chapter-links) + (format *outf* "\n") ))) + + +(defun write-title-page-links () + (format *outf* "
\n") + (let (name) + (setf name (html-file "part1")) + (format *outf* "Next Section | " name)) + (format *outf* "Index | " (html-file "indx")) + (format *outf* "
\n")) + + +(defun write-chapter-links (&optional top-flag index-flag title-flag) + (display "write-chapter-links" *part-number* *previous-number-of-parts*) + (let ((lastflag (eql *part-number* *previous-number-of-parts*))) + (if top-flag t (format *outf* "
\n")) + (cond ((not title-flag) + (format *outf* "Previous Section | " + (previous-part-file-name)))) + (cond (index-flag nil) + ((not lastflag) + (let (name) + (setf name (html-file (if title-flag "part1" + (format nil "part~A" *part-number*)))) + (format *outf* "Next Section | " name))) + (t + (format *outf* "Next Section (Index) | " + (html-file "indx")))) + (format *outf* "Table of Contents | " *dest*) + (cond ((and (not lastflag) (not index-flag)) + (format *outf* "Index | " (html-file "indx")))) + (format *outf* "Title Page\n" *dest*) + (if top-flag (format *outf* "
\n")))) + + +(defun set-html-title () + (setf *title* (get-body "htmltitle" t)) + (setf *title* (list-to-string *title*))) + + +(defun write-chapter () + (let ((body (get-body "chapter" t))) + ;(display "write-chapter" body) + (setf body (list-to-string body)) + (setf *name-reference* (format nil "\"~A\"" body)) + (setf *name-number* (1+ *name-number*)) + (cond (*section-list* + (finish-chapter))) + (cond ((eq *outf* *rootf*)) + (t + (format t "Closing ~A~%" *file-name*) + (close *outf*))) + (setf *file-name* (html-file (format nil "part~A" *part-number*))) + (setf *section-list* + (list (list *file-name* *name-number* body))) + (setf *outf* (open (strcat *dest-dir* *file-name*) + :direction :output)) + (setf *part-number* (1+ *part-number*)) + (format *outf* "~A\n\n" + body *bgcolorinfo*) + (write-chapter-links t) + (format *outf* "

~A

" *name-number* body))) + +(defun write-detail () + (format *outf* "") + (translate) + (format *outf* "\n")) + +(defun write-appendix () + (let ((body (get-body "appendix" t))) + (setf body (list-to-string body)) + (setf *name-reference* (format nil "\"~A\"" body)) + (setf body (format nil "Appendix ~A: ~A" *appendix-number* body)) + (setf *appendix-number* (1+ *appendix-number*)) + (setf *name-number* (1+ *name-number*)) + (cond (*section-list* + (finish-chapter))) + (cond ((eq *outf* *rootf*)) + (t + (format t "Closing ~A~%" *file-name*) + (close *outf*))) + (setf *file-name* (html-file (format nil "part~A" *part-number*))) + (setf *section-list* + (list (list *file-name* *name-number* body))) + (setf *outf* (open (strcat *dest-dir* *file-name*) + :direction :output)) + (setf *part-number* (1+ *part-number*)) + (write-chapter-links t) + (format *outf* "~A\n" body) + (format *outf* "

~A

" *name-number* body))) + + +(defun write-blankspace () + (cond (*fdescription* + ; what we want is

after pdescription environment + ; to set up the next fdescription, but we may have output one
+ ; after the last pdescription. By using (linebreak) we avoid a + ; third
which would output too much space. + (linebreak) + (format *outf* "
")) + (t + (paragraph))) + (get-body "blankspace" t)) + + +;(defun write-center () +; (linebreak) +; (translate) +; (linebreak)) + +(defun write-newpage () + (translate)) + +; ignore multiple calls in sequence +; +(defun paragraph () + (cond ((null *paragraph*) + (cond (*itemize* + (format *outf* "\n
  • ")) + (*description* + (format *outf* "

    \n
    ")) + ((or *pdescription* *fgroup*) + (linebreak)) + (*fdescription*) ; and not *pdescription*: no paragraph + (t + (format *outf* "\n

    \n"))) + (setf *paragraph* t)))) + +(defun linebreak () + (cond ((and (null *paragraph*) + (null *linebreak*)) + (format *outf* "
    \n") + (setf *linebreak* t)))) + +(defun write-smallcaps () + (let ((sc *smallcap*)) + (setf *smallcap* t) + (translate) + (setf *smallcap* sc))) + + +(defun write-cite () + (let (body link) + (setf body (get-body "cite" nil)) + (setf body (list-to-symbol body)) + (format t "Citation: ~A ~%" body) + (setf link (assoc body *citations*)) + (cond ((null link) + (format t "Undefined citation: ~A~%" body)) + (t + (format *outf* " ~A" + (cadr link) (caddr link)))))) + + +(defun write-ref () + (let ((body (get-body "ref" nil)) ref (file "")) + (cond (*startref* + (setf *startref* nil) + (setf *omit* nil))) + (setf body (list-to-symbol body)) + (setf ref (assoc body *previous-label-list*)) + (cond ((null ref) + (format t "warning: undefined label ~A~%" body)) + (t + (cond ((not (equal (caddr ref) *file-name*)) + (setf file (caddr ref)))) + (format *outf* "~A" + file (cadddr ref) (cadr ref)))))) + +(defun write-example () + (format *outf* "

    ")
    +  (translate)
    +  (format *outf* "
    \n")) + +(defun write-enumerate () + (let ((itemize *itemize*)) + (format *outf* "
      \n
    1. ") + (setf *itemize* t) + (translate) + (format *outf* "
    ") + (setf *itemize* itemize))) + +(defun write-itemize () + (let ((itemize *itemize*)) + (format *outf* "
      \n
    • ") + (setf *itemize* t) + (translate) + (format *outf* "
    ") + (setf *itemize* itemize))) + + + +(defun write-format () + (let ((display *display*)) + ; hopefully, we'll get a linebreak to separate the text as does scribe + (setf *display* t) + (translate) + (format *outf* "

    ~%") ; separate the text from what follows + (setf *display* display))) + +(defun write-display () + (let ((display *display*)) + (format *outf* "

    ") + (setf *display* t) + (setf *linebreak* t) ; it's automatic with blockquote, + ; so we do this to suppress an extra
    + (translate) + (format *outf* "
    ") + (setf *display* display))) + + +(defun write-figure () + (format *outf* "
    ") + (translate) + (format *outf* "
    ")) + + +(defun write-dash () + (get-body "dash" nil) + (output-char #\-)) + + +(defun write-html () + (setf *html* t) + (translate) + (setf *html* nil)) + +(defun write-foot () + (let ((outf *outf*) + (name (html-file "foot"))) + (format *outf* " (Footnote ~A) " + name *footnote-number* *footnote-number*) + (cond ((null *footnotefile*) + (setf *footnotefile* (open (strcat *dest-dir* name) :direction :output)) + (format *footnotefile* "Footnotes\n") + (format *footnotefile* "\n

    Footnotes

    \n" *bgcolorinfo*) + )) + (setf *outf* *footnotefile*) + (format *outf* " ~A. " *footnote-number* *footnote-number*) + (setf *footnote-number* (1+ *footnote-number*)) + (translate) + (format *outf* "\n

    \n") + (setf *outf* outf))) + + +(defun write-fillcaption () + (paragraph) + (format *outf* "Figure ~A: " *figure-number*) + (translate)) + + +(defun do-include () + (setf *include* t)) + +(defun write-include () + (let ((body (get-body "include" nil)) + file) + (cond (*include* + (setf *include* nil) + (setf body (list-to-string body)) + (setf file *inf*) + (setf *inf* (open (strcat *include-prefix* body))) + (cond ((null *inf*) + (format t "Could not open include file ~A\n" body) + (break)) + (t + (format t "Processing include file ~A\n" body) + (translate) + (format t "Closing include file ~A\n" body) + (close *inf*) + (setf *inf* file))) )))) + +(defun do-tag () + (let ((body (get-body "tag" nil))) + (push (list (list-to-symbol body) (format nil "~A" *figure-number*) + *file-name* *name-number*) + *label-list*) + (setf *figure-number* (1+ *figure-number*)) )) + + +(defun write-math () + (translate)) + +(defun write-underline () + (format *outf* "") + (translate) + (format *outf* "\n")) + +; initiated by @startscribe() +; and ended by @endscribe() +; +(defun do-startscribe () + (setf *omit* t)) + +(defun do-endscribe () + (setf *omit* nil)) + +(defun do-startref () + (setf *omit* t) + (setf *startref* t)) + +(defun write-title () + (translate)) + + +(defun do-comment () + ; skip everything until matching paren + (prog (tok) +loop + (setf tok (get-comment-token)) +; (display "do-comment" tok paren-stack) + (cond ((and (close-paren-p tok) + (paren-match tok)) +; (display "do-comment" paren-stack) + (pop paren-stack) +; (format t "do-comment done\n") + (return))) + (go loop))) + + +(defun output-char (c) + (cond (*omit* t) + (t + (cond ((and *smallcap* + (alpha-char-p c)) + (setf c (char-upcase c)))) + ; (display "output-char" *display*) + (cond ((and *display* (eql c #\Newline)) + (linebreak)) + ((member c '(#\Space #\Newline))) + (t + (setf *paragraph* nil) + (setf *linebreak* nil))) + (cond (*html*) ; no translation if we're in an @html(...) section + ((eq c #\<) + (write-char #\& *outf*) + (write-char #\l *outf*) + (write-char #\t *outf*) + (setf c #\;)) + ((eq c #\>) + (write-char #\& *outf*) + (write-char #\g *outf*) + (write-char #\t *outf*) + (setf c #\;)) + ((eq c #\&) + (write-char #\& *outf*) + (write-char #\a *outf*) + (write-char #\m *outf*) + (write-char #\p *outf*) + (setf c #\;))) + ; (display "output-char" c) + (write-char c *outf*)))) + + +(setf *translate-depth* 0) + +(defun translate () + (setf *translate-depth* (1+ *translate-depth*)) + (if *token-trace* (format t "(~A " *translate-depth*)) + (prog (tok) +loop + (setf tok (get-token)) + (cond ((and tok (symbolp tok) *token-trace*) + (format t "[~A]" tok))) + (cond ((null tok) (go ret)) + ((close-paren-p tok) + (cond ((paren-match tok) + (pop paren-stack)) + (t + (format t "unmatched end: ~A~%" tok) + (break))) + (go ret)) + ((eq tok 'altdef) + (translate)) + ((characterp tok) + ;; output completion hints file + (cond (*codef* (codef-char tok))) + (output-char tok)) + ((eq tok 'label) + (write-label)) + ((member tok '(code smallcode xlcode)) + (write-code)) + ((eq tok 'codef) + (write-codef)) + ((eq tok 'index) + (write-index definition-flag) + (setf definition-flag nil)) + ((eq tok 'indexsecondary) + (write-indexsecondary)) + ((eq tok 'indexdef) ;; this is obsolete now + (write-index t)) + ((eq tok 'r) + (write-normal)) + ((eq tok 'i) + (write-style "i")) + ((eq tok 'b) + (write-style "b")) + ((eq tok 'titlepage) + (write-titlepage)) + ((eq tok 'titlebox) + (write-titlebox)) + ((member tok '(majorheading chapnum)) ; chapnum is for Tomayko + (write-majorheading)) + ((member tok '(skip blankspace)) ; skip is for Tomayko + (write-blankspace)) + ((member tok '(verse center)) + (write-display)) ;; seems to be best substitute for center + ((eq tok 'format) + (write-format)) + ((eq tok 'newpage) + (write-newpage)) + ((eq tok 'c) + (write-smallcaps)) + ((member tok '(text quotation)) + (write-quotation)) + ((eq tok 't) + (write-t)) + ((eq tok 'title) + (write-title)) + ((eq tok 'htmltitle) + (set-html-title)) + ((member tok '(chapter unnumbered)) + (write-chapter)) + ((eq tok 'appendix) + (write-appendix)) + ((eq tok 'detail) + (write-detail)) + ((eq tok 'section) + (write-section)) + ((eq tok 'heading) + (write-h3)) + ((eq tok 'subsection) + (write-subsection)) + ((eq tok 'subheading) + (write-h4)) + ((eq tok 'paragraph) + (write-paragraph)) + ((eq tok 'cite) + (write-cite)) + ((member tok '(ref pageref)) + (write-ref)) + ((eq tok 'startref) + (do-startref)) + ((eq tok 'p) + (write-bold-italic)) + ((eq tok 'plus) + (write-superscript)) + ((eq tok 'minus) + (write-subscript)) + ((eq tok 'html) ; special way to insert html + (write-html)) + ((member tok '(example programexample)) + (write-example)) + ((eq tok 'figure) + (write-figure)) + ((eq tok 'fillcaption) + (write-fillcaption)) + ((eq tok 'tag) + (do-tag)) + ((eq tok 'doinclude) + (do-include)) + ((eq tok 'include) + (write-include)) + ((eq tok 'backslash) + (write-dd)) + ((eq tok 'math) + (write-math)) + ((member tok '(foot note)) ; note is for Tomayko + (codef-complete) + (setf *codef* nil) + (write-foot)) + ((member tok '(description fndefs)) + (write-description)) + ((eq tok 'fdescription) + (write-fdescription)) + ((eq tok 'pdescription) + (write-pdescription)) + ((eq tok 'fgroup) + (write-fgroup)) + ((eq tok 'itemize) + (write-itemize)) + ((eq tok 'enumerate) + (write-enumerate)) + ((eq tok 'display) + (write-display)) + ((member tok '(subtract itemsep dash ndash)) + (cond ((eq tok 'itemsep) + (codef-complete) + (setf *codef* nil))) ;; end completion string + (write-dash)) + ((eq tok 'star) + (linebreak)) + ((eq tok 'new-paragraph) + (paragraph)) + ((member tok '(y value definefont)) + (format t "warning: omitting @~A[] text\n" tok) + (skip-it)) + ((member tok '(one colon shout slash bar bibliography)) + (format t "ignoring ~A\n" tok)) + ((eq tok 'make) + (do-make)) + ((member tok '(device libraryfile style commandstring modify define use counter pageheading set graphic mult tabset tabclear textform part)) + (skip-it)) + ((eq tok 'comment) + (do-comment)) + ((eq tok 'defn) + (setf definition-flag t)) + ((eq tok 'startscribe) + (do-startscribe)) + ((eq tok 'endscribe) + (do-endscribe)) + ((eq tok 'endcodef) + (codef-complete)) + ((eq tok 'stopcodef) + (setf *codef* nil)) + ((eq tok 'startcodef) + (setf *codef* t)) + ((member tok '(u ux)) + (write-underline)) + ((member tok '(group flushleft)) ; ignore it, flushleft is for Tomayko + (translate)) + (t + (format t "unrecognized token: ~A~%" tok) + (break))) + (go loop) +ret + (if *token-trace* (format t ")")) + (setf *translate-depth* (- *translate-depth* 1)) + + )) + +(defun manualp () (eq *document-type* 'manual)) + + +(format t "To run, call:\n") +(format t " (g \"scribe source directory\" ; omit the trailing slash\n") +(format t " \"scribe file\" ; omit the .mss suffix\n") +(format t " \"html directory\" ; omit the trailing slash\n") +(format t " \"html root file\" ; omit the .html suffix\n") +(format t " [t]) ; optional flag generates html with frames\n") + +(defun g (sourcedir source destdir dest &optional frame-flag) + (setf *codef-capture* "") + (setf *codef-list* nil) + (setf *figure-number* 1) + (setf *index-number* 1) + (setf *appendix-number* 1) + (setf *footnotefile* nil) + (setf *footnote-number* 1) + (setf *name-number* 0) + (setf *name-reference* nil) + (setf *omit* nil) + (setf *html* nil) ; says we're in section to dump html literally + (setf *include* nil) ; process include or not? + (setf *next-tokens* nil) + (setf *smallcap* nil) + (setf *paragraph* t) + (setf *linebreak* t) + (setf *itemize* nil) + (setf *display* nil) + (setf *description* nil) + (setf *fdescription* nil) + (setf *fgroup* nil) + (setf *pdescription* nil) + (setf *codef* nil) ; says we're defining a function, add to completion list + ;; paragraph-list is initialized to: + ;; ((file number sectionname)) + ;; and after each paragraph, expands, e.g.: + ;; ((file number paragraphname) (file number sectionname)) + (setf *paragraph-list* nil) + ;; likewise, the subsection-list is initialized to: + ;; ((file number sectionname)) + ;; and after each subsection, expands, e.g.: + ;; (((file number paragraphname) (file number subsectionname)) + ;; (file number sectionname))) + (setf *subsection-list* nil) + ;; and so on... + (setf *section-list* nil) + (setf *chapter-list* nil) + ; *dest* is the root HTML file + (setf *dest* (if frame-flag + (html-file "title") + (html-file dest))) + ; *file-name* is the current HTML file + (setf *file-name* *dest*) + (format t "Destination HTML file: ~A~%" *file-name*) + (setf *part-number* 1) + + ; *startref* is set when @startref() is encountered, at which + ; point text is omitted until a reference is encountered, at + ; which point text is resumed. + (setf *startref* nil) + + ;; index-list shall look like this: + ;; (("key" "indexterm" (filename num) (filename num) ...) + ;; ("key" "indexterm" (filename num) (filename num) ...) ...) + ;; where key is the sortkey (usually indexterm) and indexterm is + ;; what gets printed. This allows non-alphabetic items to be sorted + ;; according to their first alphabetic character, e.g. *rslt* can + ;; be sorted as "rslt" as well as "*rslt*" + ;; + (setf *index-list* nil) + + (setf paren-stack nil) + + ;; run this twice to get labels right + ;; if *label-list* is NIL, it may be because we reloaded this file, + ;; in which case *previous-label-list* has already been copied from + ;; *label-list* + (cond (*label-list* + (setf *previous-label-list* *label-list*)) + ((not (boundp '*previous-label-list*)) + (setf *previous-label-list* nil))) + (cond (*number-of-parts* + (setf *previous-number-of-parts* *number-of-parts*))) + (cond ((not (boundp '*previous-number-of-parts*)) + (setf *previous-number-of-parts* 0))) + + (setf *inf* (open (strcat sourcedir "/" source ".mss"))) +; "test.mss")) +; "/afs/cs/user/rbd/doc/man/nyquist/nyquistman.mss")) + (setf *include-prefix* (strcat sourcedir "/")) + (setf *dest-dir* (strcat destdir "/")) + (setf *outf* (open (strcat *dest-dir* *file-name*) :direction :output)) + (setf *codef-file* (open (strcat *dest-dir* "NyquistWords.txt" ) + :direction :output)) + (setf *rootf* *outf*) + (display "g-before translate" *outf* *rootf* *inf*) + (translate) + (display "g-after translate" *outf* *rootf* *inf*) + (format t "g: closing *inf*\n") + (close *inf*) + (setf *inf* nil) + (format t "g: closing *outf*\n") + (finish-chapter) + (cond ((not (eq *outf* *rootf*)) + (close *outf*) + (setf *outf* nil))) + (cond (*footnotefile* + (format *footnotefile* "\n") + (close *footnotefile*))) + (setf *footnotefile* nil) + (setf *outf* *rootf*) + (display "g-before toc" *outf* *rootf* *inf*) + (setf *number-of-parts* *part-number*) + (cond ((manualp) + (setf *part-number* 1) ;; reset for title page + (write-title-page-links) + (generate-toc) + (write-chapter-links nil nil t))) + (format *rootf* "\n") + (format t "g: closing *rootf*\n") + (close *rootf*) + (setf *outf* (setf *rootf* nil)) + (cond ((manualp) + (setf *part-number* *number-of-parts*) ;; restore from above + (generate-index)) + ; if this is not a manual, there are no chapters, so there are no + ; links between chapters or table of contents, so index cannot be + ; reached, so index is not generated. This is bad if there really + ; are index terms!!!! + (*index-list* + (format t "WARNING: NO INDEX IS BEING GENERATED, THIS IS A BUG~%"))) + (cond (frame-flag + (if (not (manualp)) + (error "frame option only works with manual document types")) + (generate-home *title* (strcat *dest-dir* (html-file dest))) + (generate-guide (strcat *dest-dir* (html-file "guide"))) + )) + (codef-close) +) + + +(defun generate-home (title filename) + (let ((outf (open filename :direction :output))) + (format outf "~A~%" title) + (format outf "~%") + (format outf "~%") + (format outf + "~%") + (format outf "<body><p>This browser does not support frames.~%") + (format outf "<p><a href=title.html>The no-frames version is here.</a>~%") + (format outf "</body>~%") + (close outf))) + + +;; FIND-ALPHA-AND-NON-ALPHA -- sublist with only alpha chars +;; return the range of the rest in *rslt*, e.g. "!-~" +;; +(defun find-alpha-and-non-alpha (lis) + (let (prev first last rslt) + (dolist (c lis) + (cond ((eql prev c)) + (t + (setf prev c) + (cond ((both-case-p prev) + (push prev rslt)) + ((null first) + (setf first prev) + (setf last prev)) + (t + (setf last prev)))))) + (setf *rslt* (strcat (string first) "-" (string last))) + rslt)) + + +(defun generate-index-chars () + (let (term initial prev) + (setf *index-chars* nil) + ;; compute the list of characters for index + (dolist (entry *index-list*) + (setf term (car entry)) + (setf initial (char term 0)) + (cond ((eql prev (char term 0))) + (t + (setf prev initial) + (push prev *index-chars*)))) + (setf *index-chars* (reverse *index-chars*)) + (setf *index-chars* (find-alpha-and-non-alpha *index-chars*)) + (setf *index-chars* (reverse *index-chars*)) + (push *rslt* *index-chars*))) + + +(defun generate-guide (dest) + (let (term initial prev index-chars non-alpha) + (setf *outf* (open dest :direction :output)) + (format *outf* "Links~%") + (format *outf* "

    ~%") + (dotimes (n (length *index-chars*)) + (setf c (nth n *index-chars*)) + (format *outf* "~A~%" c c) + (if (zerop (rem (1+ n) 9)) + (format *outf* "
    ~%"))) + (format *outf* "

    ~%") + (generate-toc t) + (generate-index *outf*) + (format *outf* "~%") + (close *outf*))) + + +(defun alpha-char-p (c) + (let ((cc (char-code c))) + (or (and (>= cc (char-code #\a)) + (<= cc (char-code #\z))) + (and (>= cc (char-code #\A)) + (<= cc (char-code #\Z)))))) + + +(defun process-comment-at () + (let (c cmd) + (read-char *inf*) ; read the @ + (setf c (peek-char nil *inf*)) + (cond ((alpha-char-p c) + (setf cmd (read-command)) + (cond ((eq cmd 'end) + (open-paren) + (read-end-command)) + (t #\z)))))) + + +(defun process-at () + (let (c cmd) + (read-char *inf*) ; read the @ + (setf c (peek-char nil *inf*)) + (cond ((eql c #\@) (read-char *inf*)) + ((eql c #\\) (read-char *inf*) 'backslash) + ((eql c #\/) (read-char *inf*) 'slash) + ((eql c #\1) (read-char *inf*) 'one) + ((eql c #\+) (read-char *inf*) + (open-paren) + 'plus) + ((eql c #\*) (read-char *inf*) 'star) + ((eql c #\-) (read-char *inf*) + (open-paren) + 'minus) + ((eql c #\:) (read-char *inf*) 'colon) + ((eql c #\!) (read-char *inf*) 'shout) + ((eql c #\|) (read-char *inf*) 'bar) + ((alpha-char-p c) + (setf cmd (read-command)) + (cond ((eq cmd 'begin) + (open-paren) + (read-begin-command)) + ((eq cmd 'end) + (open-paren) + (read-end-command)) + ((eq cmd 'pragma) + (open-paren) + (read-pragma-command)) + (t + (open-paren) + cmd))) + (t (format t "unexpected char after @: ~A~%" c) + (break))))) + + +(defun process-newline () + (let (c) + (read-char *inf*) ; read the newline + (setf c (peek-char nil *inf*)) + (cond ((eql c #\Newline) + (while (eql (peek-char nil *inf*) #\Newline) + (read-char *inf*)) + 'new-paragraph) + (t #\Newline)))) + + +;; READ-COMMAND -- read command after an @ +; +(defun read-command () + (let ((command "")) + (while (alpha-char-p (peek-char nil *inf*)) + (setf command + (strcat command (string (read-char *inf*))))) + (intern (string-upcase command)))) + + + +;; (read-char *inf*)) + +(defun get-token () + (let ((c (peek-char nil *inf*)) + result) + + ;; allow others to force next token: + (cond (*next-tokens* + (setf result (car *next-tokens*)) + (setf *next-tokens* (cdr *next-tokens*))) + (t + (setf result + (cond ((eql c #\@) (process-at)) + ((eql c #\Newline) (process-newline)) + ((eql c #\`) ;; double `` -> " + (read-char *inf*) + (setf c (peek-char nil *inf*)) + (cond ((eql c #\`) + (read-char *inf*) + #\") + (t #\`))) + ((eql c #\') ;; double '' -> " + (read-char *inf*) + (setf c (peek-char nil *inf*)) + (cond ((eql c #\') + (read-char *inf*) + #\") + (t #\'))) + (t (read-char *inf*)))))) + (if *token-trace* (format t "->~A " result)) + result + )) + + +(defun get-comment-token () + (let ((c (peek-char nil *inf*)) + result) + (setf result + (cond ((eql c #\@) (process-comment-at)) + (t (read-char *inf*)))) + (if *token-trace* (format t "->~A " result)) + result + )) + +(defun codef-char (c) + (if (member c '(#\Newline #\Tab)) (setf c #\Space)) + (setf *codef-capture* (strcat *codef-capture* (string c)))) + +(defun codef-complete () +; (write-char #\) *codef-file*) + (let (index) + ;; remove [lisp] and [sal] and everything after it + (if (setf index (string-search "[lisp]" *codef-capture*)) + (setf *codef-capture* (subseq *codef-capture* 0 index))) + (if (setf index (string-search "[sal]" *codef-capture*)) + (setf *codef-capture* (subseq *codef-capture* 0 index))) + ;; trim extra blanks + (while (setf index (string-search " " *codef-capture*)) + (setf *codef-capture* (strcat (subseq *codef-capture* 0 index) + (subseq *codef-capture* (1+ index))))) + ;; replace "expr..." with "expr ..." Want to replace all occurences, + ;; so scan string, starting at previous spot + 2 (to get beyond the + ;; inserted space character) until nothing is found + (setf index 0) + (while (and (< (+ index 2) (length *codef-capture*)) + (setf index (string-search "..." *codef-capture* + :start (+ 2 index)))) + (cond ((and index (> index 0) + (not (eq (char *codef-capture* (1- index)) #\Space))) + (setf *codef-capture* + (strcat (subseq *codef-capture* 0 index) " " + (subseq *codef-capture* index)))))) + ;; trim blanks after open bracket/comma and before close paren + (while (setf index (string-search "[, " *codef-capture*)) + (setf index (+ 2 index)) + (setf *codef-capture* (strcat (subseq *codef-capture* 0 index) + (subseq *codef-capture* (1+ index))))) + (while (setf index (string-search " )" *codef-capture*)) + (setf *codef-capture* (strcat (subseq *codef-capture* 0 index) + (subseq *codef-capture* (1+ index))))) + ) + + ;; trim blanks + (setf *codef-capture* (string-trim " " *codef-capture*)) + ;; translate &key to example format + (cond ((or (string-search "&key" *codef-capture*) + (string-search "&optional" *codef-capture*)) + (setf *codef-capture* (codef-expand *codef-capture*)))) + (if (and (> (length *codef-capture*) 0) ; must be non-empty + (not (eq (char *codef-capture* 0) #\:))) ; ignore messages + (push (string-downcase + (convert-sal-to-lisp *codef-capture*)) + *codef-list*)) + ;; trim leading open paren + (if (and (> (length *codef-capture*) 0) + (eq (char *codef-capture* 0) #\()) + (setf *codef-capture* (subseq *codef-capture* 1))) + + (setf *codef-capture* "")) + + +(defun convert-sal-to-lisp (codef) + ;(format *codef-file* "sal-to-lisp |~A|~%" codef) + ;; some of these strings are already lisp. The SAL strings have an + ;; open paren after the function call + (cond ((eq (char codef 0) #\() + (setf codef (subseq codef 1))) + ((string-search "(" codef) + (setf codef (do-convert-sal-to-lisp codef)))) + codef) + +(defun do-convert-sal-to-lisp (codef) + ;; take out initial "(" and replace with space + ;; delete each subsequent comma + ;; for each colon, flip it to a keyword (key: -> :key) + (let ((p (string-search "(" codef))) + ;; replace "(" with " " + (setf codef (strcat (subseq codef 0 p) " " (subseq codef (1+ p)))) + ;; delete commas: + (setf p (string-search "," codef)) + (while p + (setf codef (strcat (subseq codef 0 p) (subseq codef (1+ p)))) + (setf p (string-search "," codef))) + ;; for each colon, flip it to a keyword + (setf p (string-search ":" codef)) + (while p + ;; back up + (setf q (1- p)) + (while (not (member (char codef q) '(#\Space #\[))) + (setf q (1- q))) + (incf q) + (setf codef (strcat (subseq codef 0 q) ":" + (subseq codef q p) (subseq codef (1+ p)))) + (setf p (string-search ":" codef :start (1+ p))) + '(display "do-cstl" p codef)) + codef)) + + +(defun split (s) + (let (rslt (token "") c) + (dotimes (i (length s)) + (setf c (char s i)) + (cond ((eq c #\Space) + (cond ((> (length token) 0) + (push token rslt) + (setf token "")))) + ((member c '(#\( #\))) + (cond ((> (length token) 0) + (push token rslt) + (setf token ""))) + (push (string c) rslt)) + (t + (setf token (strcat token (string c)))))) + (cond ((> (length token) 0) + (push token rslt))) + (reverse rslt))) + + +(defun colonize (word) + (if (eq (char word 0) #\:) + word + (strcat ":" word))) + +(defun uncolonize (word) + (if (eq (char word 0) #\:) + (subseq word 1) + word)) + + +(defun codef-expand (s) + (let (words (r "") mode (space "")) + (setf words (split s)) + (dolist (word words) + (cond ((equal word "&key") + (setf mode :key)) + ((equal word "&optional") + (setf mode :optional)) + ((equal word "(") + (setf r (strcat r space word)) + (setf space "")) + ((equal word ")") + (setf r (strcat r word)) + (setf space " ")) + ((eq mode :key) + (setf r (strcat r space "[" (colonize word) " " + (uncolonize word) "]")) + (setf space " ")) + ((eq mode :optional) + (setf r (strcat r space "[" word "]")) + (setf space " ")) + (t + (setf r (strcat r space word)) + (setf space " ")))) + r)) + +(defun find-url-for (item) + (let (i entry) + ;; first, extract the initial symbol from item + (setf i (string-search " " item)) + (cond (i (setf item (subseq item 0 i)))) + ;; trim trailing (or any) close parenthesis + (setf i (string-search ")" item)) + (cond (i (setf item (subseq item 0 i)))) + ;; fix the case/capitalization to match what's in *index-list* + (setf item (index-casify item)) + ;; look it up + (setf entry (assoc item *index-list* :test #'equal)) + ;; return the URL + (cond (entry + ;; entry has (sort-key, name, ref1, ref2, ...) + (setf entry (third entry)) ;; get first reference + (format nil "~A#index~A" (first entry) (second entry))) + (t + (format t "WARNING: ~A IS NOT IN INDEX~%" item) + "home.htm")))) + + +(defun codef-close () ;; called to close file + ;; nothing written yet + (let (url) + (setf *codef-list* (sort *codef-list* #'string<)) + (dolist (item *codef-list*) + (setf url (find-url-for item)) + (format *codef-file* "~A~%~A~%" item url)) + (close *codef-file*))) diff --git a/docsrc/scribe.htm b/docsrc/scribe.htm new file mode 100644 index 0000000..6b9e875 --- /dev/null +++ b/docsrc/scribe.htm @@ -0,0 +1,1523 @@ + + +Scribe + + + + + + + +
    + +
    + +

    Scribe

    + +
    + +
      +
    • @@ - insert an '@' sign
    • +
    • @+ - superscript
    • +
    • @− - subscript
    • +
    • @~ - unknown meaning
    • +
    • @\ - horizontal tabulator
    • +
    • @* - force a line break
    • +
    • @appendix - start appendix chapter
    • +
    • @b - bold text
    • +
    • @begin - start a region
    • + +
    • @blankspace - insert witepace with specific width
    • +
    • @c - small capitals
    • +
    • @caption - add text to an object
    • +
    • @chapter - start an numbered chapter
    • +
    • @center - centered text
    • +
    • @cite - cite an entry from the bibliograpy
    • +
    • @code - inline code example, use typewriter font
    • +
    • @codef - inline code example, use typewriter font
    • +
    • @commandstring - define printing commands [for CMU use only]
    • +
    • @comment - a comment, invisible in the final document
    • +
    • @dash - insert a horizontal dash with specific width
    • +
    • @define - define a command or a variable
    • +
    • @device - the printer device [for CMU use only]
    • +
    • @display - non-justified text
    • +
    • @end - end of a region
    • +
    • @fillcaption - add formatted text to an object
    • +
    • @foot - add a footnote
    • +
    • @graphic - insert a picture
    • +
    • @html - insert text in HTML only
    • +
    • @htmltitle - insert a HTML header with title (HTML only)
    • +
    • @i - italics
    • +
    • @include - read a different Scribe file
    • +
    • @index - index reference
    • +
    • @itemsep - insert a horizontal dash with specific width
    • +
    • @label - add a label to a section
    • +
    • @libraryfile - load Scribe library [for CMU use only]
    • +
    • @majorheading - document title
    • +
    • @make - printer output format [for CMU use only]
    • +
    • @math - render and insert a math formula
    • +
    • @mult - insert a multiplication sign
    • +
    • @modify - change internal Scribe settings [for CMU use only]
    • +
    • @newpage - force a page break
    • +
    • @p - bold italics
    • +
    • @pageheading - format of the page heading
    • +
    • @pageref - insert the page number of a @label
    • +
    • @paragraph - start a new paragraph
    • +
    • @parm - unknown meaning
    • +
    • @part - faciliates separate compilation of parts of a larger document
    • +
    • @pragma - control the 's2h.lsp' HTML converter
    • +
    • @ref - insert the section number of a @label
    • +
    • @section - start a section
    • +
    • @set - set a Scribe variable [for CMU use only]
    • +
    • @style - change a Scribe document preset [for CMU use only]
    • +
    • @subsection - start a sub-section
    • +
    • @subtract - insert a horizontal dash with specific width
    • +
    • @t - use typewriter font
    • +
    • @tabclear - reset tabulator settings
    • +
    • @tabset - define new tabulator settings
    • +
    • @tag - add a label to a figure or table
    • +
    • @textform - define a text-formatting Scribe command
    • +
    • @title - define the page heading title
    • +
    • @unnumbered - start an unnumbered chapter
    • +
    • @use - use a external database file
    • +
    • @value - insert the value of a command or a variable
    • +
    + +
    + +

    Table of Contents

    + +
    + +
      +
    1. Scribe - basic Syntax rules
    2. +
    3. General Settings - start of 'myquistman.mss'
    4. + +
    5. Command Definitions - Nyquist Scribe commands
    6. + +
    7. Inline Markup
    8. +
    9. Regions
    10. +
    11. Lists
    12. +
    13. Comments
    14. +
    15. Footnotes
    16. +
    17. Indexing
    18. +
    19. Headings
    20. +
    21. Title Page
    22. +
    23. Tab Stops and Whitespace
    24. +
    25. Line and Page Breaks
    26. +
    27. Cross References
    28. +
    29. Bibliography and Citation
    30. +
    31. Figures and Tables
    32. +
    + + + +
    + +

    Scribe

    + +
    + +

    Scribe is a markup language and word processing system. It +was designed and developed by Brian Reid of Carnegie Mellon +University around 1980.

    + + + +

    A source file prepared for input to Scribe consists primarily of plain +text. Paragraphs are separated by blank lines, and commands, if present, are +flagged with '@' signs. If you want an '@' +sign to appear within your output, you must type two of them +'@@'. A file containing no commands at all will work +just fine, it will yield simple justified paragraphed text. A +Scribe source file should be given the extension '.mss'. +Upper and lower case may be used interchangeably in any Scribe command.

    + +

    A perhaps confusing aspect of Scribe is that you get to use any bracket +as long as you close it with a matching one, so for example:

    + +
    +@i(This is italic.)
    +@i[This is also italic]
    +@i{This italic has (parentheses) but it's ok because there is no curly brace}
    +@begin(i)This form is allows [any] (brackets) {in} the text, but "at" (@@) must be escaped@end(i)
    +
    + +

    Legal delimiter pairs are:

    + +

    + + + + + + + + + + +
      (...) , [...] , <...> , "..."

    + +

    It doesn't really matter which delimiter is used as long as the closing +delimiter matches the opening limiter.

    + +

      Back to top

    + + + +
    + +

    General Settings

    + +
    + +

    Most of the definitions in this section affect the Scribe system at the +CMU only.

    + +
    +@device(mac52postscript)          @comment(printer device)
    +@make(manual)                     @comment(printer output format)
    +@libraryfile(mathematics10)
    +@libraryfile(picture)
    +@libraryfile(multilevelindex)
    +@style(font timesroman)           @comment(printer font)
    +@style(fontscale 11)              @comment(printer font size)
    +@commandstring(dash @Y[M])
    +@commandstring(subtract @Y[N])
    +@commandstring(itemsep @Y[M])
    +@Modify(indexenv, above=2 lines, leftmargin 8, columns=3, boxed)
    +@define(prg=i)
    +
    + + + +

    The '@commandstring' lines define three formatting directices:

    + +

    + + + + + + + + + + +
      @dash , @subtract , @itemsep  - a minus sign in HTML, but different widths in PDF

    + +

    [A block with + Command Definitions follows +here in the original file, moved to a separate paragraph below.]

    + +
    +@use(bibliography = "../bib/music.bib")
    +@style(references ClosedAlphabetic)
    +@counter(dummy-counter)
    +@modify(FigureCounter,Within=dummy-counter,
    +        Numbered <@@b[Figure@@ @1:@@ @@ ]@@$>,
    +        Referenced "@1",Init 0)
    +@modify(TableCounter,Within=dummy-counter,
    +        Numbered <@@b[Table@@ @1:@@ @@ ]@@$>,
    +        Referenced "@1",Init 0)
    +@pageheading(left "", center "@value(page)", right "")
    +@include(../template/filcap.mss)
    +
    + + + +

    Scribe commands for producing large documents:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
      @part(text)  - faciliates separate compilation of parts of a larger document.
      @use(text)  - tells Scribe to use a particular database file, used to include the bibliography file
      @include(text)  - read another Scribe file

    + + + +

    The @style Command

    + +

    The database entry for a document type presets the value of all Scribe +parameters. The '@style' command can be used to override these values. All +'@style' commands used in a document must come at the beginning. Styles +can't be changed in the middle of a document. Here is a list of '@style' +commands used in the Nymqust manual:

    + +
    +@style(font timesroman)
    +@style(fontscale 11)
    +@style(references ClosedAlphabetic)
    +@style(pagenumbers="@i")
    +@style(pagenumbers="@1")
    +
    + + + +

    Numbering Pages and Page Headings

    + +

    The page heading and footing areas are divided into three parts. A +'left' part, a 'center' part, and a 'right' part:

    + +
    +@pageheading(left "", center "@value(page)", right "")
    +@pageheading(even, left "Page @Value(Page)", right "@c(Nyquist Manual)")
    +@pageheading(odd, left "@c[@title(chapter)]", right "Page @Value(page)")
    +
    + +

    The text fields inside the quotes can contain anything, including Scribe +commands.

    + +

      Back to top

    + + + +
    + +

    Command Definitions

    + +
    + +

    The definitions in this section are used in the Scribe sources.

    + +
    +@define(detail=text, size 9, spacing 1.2, indent 0)
    +@define(code, FaceCode T, size 11)
    +@define(codef, FaceCode T, size 11)
    +@define(smallcode, FaceCode T, size 8, spacing 0.8) @comment(was 10)
    +@define(rbdisplay = display, group)
    +@define(fndefs = description, leftmargin 0.5in, indent -0.5in)
    +@define(fdescription = text, leftmargin +0.5in, indent -0.5in, spread 1)
    +@define(pdescription = text, leftmargin +0.5in, indent -0.5in, spread 0)
    +@define(fgroup = text, indent -0.5in, spread 0)
    +
    + +
      +
    • detail defines text with a small font
    • +
    • code and codef define text with a typewriter font
    • +
    • smallcode defines text with typewriter font, with a small font in PDF
    • +
    • 'rbdisplay' seems nowhere else to be used in the Nyquist manual
    • +
    • fndefs and fgroup define special PDF formatting parameters for function definitions
    • +
    • fdesription and pdescription define a special definition list format
    • +
    + +

    '@codef' is used to define a lisp function or variable. A +processor uses this to extract completion hint info for jNyqIDE.

    + + + +

    HTML Commands

    + +

    Three Scribe commands are added for the 's2h.lsp' HTML converter::

    + +
    +@textform(html = [])
    +@textform(htmltitle = [])
    +@textform(pragma = [])
    +
    + +

    The first two commands insert text in the HTML file only, but not in +the PDF:

    + + + +

    + + + + + + + + + + + + + + + +
      @html(text)  - insert HTML text
      @htmltitle(text)  - insert a HTML header with title

    + + + +

    The '@pragma' command controls the 's2h.lsp' HTML converter:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      @pragma(defn)  - the next @index marks a term's definition in the manual
      @pragma(startscribe)  - ignore scribe file starting here
      @pragma(endscribe)  - stop ignoring scribe file
      @pragma(startref)  - use text between here and an @ref or @pageref as link text
      @pragma(doinclude)  - process the next include file (default is to ignore)
      @pragma(endcodef)  - end a code definition (used for completion list)

    + +

    RBD: '@pragma(defn)' is used to mark a term's point of definition. +I tried to define(defn=index), but that didn't work in Scribe, +so the approach now is to mark definitions. In s2h, the 'defn' +pragma sets a flag that the NEXT index term is a definition. The +'s2h.lsp' processor uses this to map terms defined within 'codef' +(which go into the completion list) to URLs for the help system.

    + +

      Back to top

    + + + +
    + +

    Inline Markup

    + +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Scribe HTML 
      @b(text) → <b>text</b>  - bold
      @i(text) → <i>text</i>  - italics
      @p(text) → <b><i>text</i></b>  - bold + italics
      @t(text) → <tt>text</tt>  - typewriter font
      @c(text) → <small>text</small>  - small capitals
      @+(text) → <sup>text</sup>  - superscript
      @(text) → <sub>text</sub>  - subscript
     
    User-defined + Scribe commands:
      
      @code(text) → <code>text</code>  - code example inside text
      @codef(text) → <code>text</code>  - code example inside text
     
    Named entities:
     
      @mult → *  - insert a multiplication sign

    + +

      Back to top

    + + + +
    + +

    Regions

    + +
    + +

    Text-formatting Scribe commands can be written as +inline command or as a region command, delimited by +'@begin' and '@end':

    + +

    + + + + + + + + + + + + + + + +
      @command(text)  - inline command
     
      @begin(command)
    text
    @end(command)
      - region command

    + +

    The most often used Scribe region commands in the Nyquist manual are:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Scribe HTML 
      @begin(programexample)
    text
    @end(programexample)
     → <pre>
    text
    </pre>
      - code example, typewriter font
     
      @begin(example)
    text
    @end(example)
     → <pre>
    text
    </pre>
      - code example, typewriter font
     
      @begin(display)
    text
    @end(display)
     → <blockquote>
    text
    </blockquote>
      - normal text, non-justified, each line separate
     
      @display(text)  - same as above
     
    Scribe: The 'example' and 'display' inserts types + are very similar, they differ only in the type face that will be used. + In either 'example' or 'display' inserts, each line of the + manuscript will produce one line in the document. Since 'example' is for + showing examples of computer type-in and + type-out, it will appear in a typeface that is designed to + look like computer output. 'display' inserts will appear in the normal + body typeface. If the document is printed on a device that cannot change + fonts, then 'example' and 'display' will look nearly identical.
     
      @begin(center)
    text
    @end(center)
     → <center>
    text
    </center>
      - each line centered
     
      @center(text)  - same as above
     
    Scribe: The 'center' insert is similar to + 'display', except that it centers its lines rather than + left-justifying them. Like 'display', 'center' produces one + line in the document for each line of the manuscript file that is inside + the 'center'. If there is more than one line in a 'center' + insert, each line will be centered individually.
     
      @begin(detail)
    text
    @end(detail)
     → <small>
    text
    </small>
      - use small font
     
      @begin(code)
    text
    @end(code)
     → <code>
    text
    </code>
      - typewriter font
     
      @begin(smallcode)
    text
    @end(smallcode)
     → <code>
    text
    </code>
      - typewriter font, use small font in PDF

    + +

      Back to top

    + + + +
    + +

    Lists

    + +
    + + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Scribe HTML 
      @begin(itemize)
    item-1

    item-2

    item-3
    @end(itemize)
     → <ul>
    <li>item-1
    <li>item-2
    <li>item-3
    </ul>
      - unordered list
     
      @begin(enumerate)
    item-1

    item-2

    item-3
    @end(enumerate)
     → <ol>
    <li>item-1
    <li>item-2
    <li>item-3
    </ol>
      - ordered list
     
    Scribe: 'itemize' and 'enumerate' each expect a + sequence of paragraphs, separated by blank lines, and each justifies + those paragraphs into inset margins and puts a mark in front of each. + 'itemize' puts a tick-mark or a bullet in front of each + paragraph, while 'enumerate' puts a number in front of each.
     
      @begin(description)
    item-1@\text-1

    item-2@\text-2

    item-3@\text-3
    @end(description)
     → <dl>
    <dt>item-1<dd>text-1
    <dt>item-2<dd>text-2
    <dt>item-3<dd>text-3
    </dl>
      - definition list
     
    Scribe: A 'description' insert is + designed for the 'command description' style that is very common in + reference manuals. The first line of a 'description' insert + will be at the left margin, and the second and remaining lines will be + indented substantially, so that the word or phrase at the end of the head + of the description stands out. If three or more + blanks in a row are found in the first line of a 'description', they will + be taken as a signal to tab to the left margin provided that the left + margin has not been passed.
      
      @begin(fdescription)
    item
    @begin(pdescription)
    text-1

    text-2

    text-3
    @end(pdescription)
    @end(fdescription)
     → <dl>
    <dt>
    item
    <dd>
    text-1<br>
    text-2<br>
    text-3<br>
    </dl>
      - definition list

    + +

      Back to top

    + + + +
    + +

    Comments

    + +
    + +

    Comments produce no text in the final document and can be written as +inline or as region command:

    + + +

    + + + + + + + + + + + + + + + +
      @comment(text)  - inline comment
     
      @begin(comment)
    text
    @end(comment)
      - region comment

    + + +

      Nach oben

    + + + +
    + +

    Footnotes

    + +
    + +

    + + + + + + +
      @foot(text)  - footnote

    + +

      Back to top

    + + + +
    + +

    Indexing

    + +
    + +

    + + + + + + + + +
      @index(text) → <a name="indexXX">  - nothing will appear in the printed text, but the 'text' + will appear in the index together with the current page number.

    + +

      Back to top

    + + + +
    + +

    Headings

    + +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Scribe HTML 
      @majorheading(text) → <h1>text</h1>  - document title
     
      @unnumbered(text) → <h2>text</h2>  - unnumbered chapter (e.g. preface)
      @chapter(text) → <h2>text</h2>  - numbered chapter
      @appendix(text) → <h2>text</h2>  - appendix
     
    Scribe: Notice that 'unnumbered', 'chapter', and + 'appendix' cause Scribe to start at the top of a new page.
     
      @section(text) → <h3>text</h3>  - section
      @subsection(text) → <h4>text</h4>  - subsection
      @paragraph(text) → <h5>text</h5>  - paragraph

    + +

      Back to top

    + + + +
    + +

    Title Page

    + +
    + +

    + + + + + + + + + + + + + + + + + + + + + +
      @begin(titlepage)
    text
    @end(titlepage)
      - this will cause the title page to be a page by itself, + and text within the titlepage will be centered.
     
    Scribe: The title page for a technical report + usually has the title, author, and date of publication visible within a + box that will be reproduced on the cover of the report. The + 'titlebox' command can be used to put text in this + box:
     
      @begin(titlebox)
    text
    @end(titlebox)
      - this will produce a titlebox.

    + +

      Back to top

    + + + +
    + +

    Tab Stops and Whitespace

    + +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
      @tabclear  - clear all tabs
      @tabset(number unit)  - set tab width to 'number' of units, 'unit' should be 'inch' or 'inches'
      @\  - go to the right until the next tab. If there is no tab + stop to the right of the cursor position, then the cursor will be moved + to the right margin.

    + +
    +@tabset(.5 inches)
    +@tabset(0.8 in, 3 in, 3.8 in)
    +@tabset(1.5 inch)
    +@tabset(0.8 inches)
    +@tabset(0.5 inch)
    +
    + +

    + + + + + + + + + + + + + + + +
      @blankspace(number)  - forces a 'number' units of whitespace
      @blankspace(number unit)  - forces a 'number' units of whitespace, 'unit' should be 'inch' or 'inches'

    + +
    +@blankspace(0.3 inches)
    +@blankspace(0.5 inch)
    +@blankspace(0.3 inch)
    +@blankspace(1 inch)
    +@blankspace(5 inches)
    +@blankspace(1)
    +
    + +

      Back to top

    + + + +
    + +

    Line and Page Breaks

    + +
    + +

    + + + + + + + + + + + + + + + +
      @*  - force a line break
      @newpage  - force a page break

    + +

      Back to top

    + + + +
    + +

    Cross References

    + +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      @label(word)  - define a label (text reference to a section or page number)
      @ref(word)  - insert the section number of the label
      @pageref(word)  - insert the page number of the label
      @tag(word)  - define a tag (object reference to a figure or a table)

    + +

    Scribe: The difference between a 'label' and a tag is a bit +subtle. A section document has many different sequences of +numbers that identify the pieces of it. Pages are numbered +sequentially, chapters and sections are usually numbered independently of +the pages. Figures and tables are often numbered within a chapter, ignoring +section numbers. If you want to attach a codeword to the +section number of the section that contains a particular figure or table, +then use '@label'. If you want to attach a codeword to the figure or table, +rather than to the section that it is contained in, then use the '@tag' +command.

    + +

      Back to top

    + + + +
    + +

    Bibliography and Citation

    + +
    + +

    A bibliography is a labeled list of books, articles, or papers. A +citation is a marker in the text that refers to an entry in the +bibliography. Because Scribe selects and prints only those entries in a +bibliography that are actually cited in the text, a common bibliography file +may be used for many different documents. The bibliography file consists of +a series of entries, each with an identifier.

    + +
    +@book(Touretzky
    +        ,key "Touretzky"
    +        ,author "Touretzky, David S."
    +        ,title "LISP: a gentle introduction to symbolic computation"
    +        ,address "New York"
    +        ,publisher "Harper & Row"
    +        ,year 1984
    +        )
    +
    +@inproceedings(ICMCFugue
    +        ,key "Dannenberg"
    +        ,author "Dannenberg, R. B. and C. L. Fraley"
    +        ,title "Fugue: Composition and Sound Synthesis With Lazy Evaluation
    +        and Behavioral Abstraction"
    +        ,booktitle = "Proceedings of the 1989
    +                International Computer Music Conference"
    +        ,editor "T. Wells and D. Butler"
    +        ,year = "1989"
    +        ,organization = "International Computer Music Association"
    +        ,address "San Francisco"
    +        ,pages "76-79"
    +        )
    +
    + +

    Then just put a '@cite' command into the text at the spot where the +citation should appear:

    + +
    +@cite(Touretzky)
    +@cite(icmcfugue)
    +
    + +

    RBD: HTML citations are translated by 's2h.lsp' to +links according to data in 'docsrc/s2h/citations.lsp'. +The actual bibliographic references must be +hand-translated to HTML.

    + +

      Back to top

    + + + +
    + +

    Figures and Tables

    + +
    + +

    + + + + + + +
      @begin(figure)
    text
    @end(figure)
      - define a region to insert an object

    + +

    + + + + + + + + + + + + + + + +
      @graphic(text)  - insert a picture
      @math(text)  - insert a rendered math formula

    + +

    + + + + + + + + + + + + + + + +
      @caption(text)  - add text to an object
      @fillcaption(text)  - add formatted text to an object and modify object counters

    + +

    With the Scribe @tag command a label can +be added to an object. The best place to put the +@tag command is after the '@caption' or +'@fillcaption' command. If the @tag command +appears before the '@caption' or '@fillcaption' command, then the wrong +figure number will get assigned to the tag, because the number will not yet +have been incremented.

    + +

    The '@fillcaption' command is defined in the file +'docsrc/template/filcap.mss':

    + +
    +@textform[FillCaption="@begin(transparent)@modify(captionenv,fill,indent 0,
    +leftmargin +0.5 inch,rightmargin +0.5 inch)@modify(figurecounter,
    +numbered <@@b[Figure@@ @#@:-@1:@@ @@ ]>)@modify(tablecounter,
    +numbered <@@b[Figure@@ @#@:-@1:@@ @@ ]>)@caption<@parm<text>>@~
    +@end(transparent)"]
    +
    + +

    The exact meaning of the Scribe '@parm' and '@~' commands are currently +unknown.

    + +

      Back to top

    + + + +
    + +

    Formatting of the Nyquist Manual

    + +
    + +

    The 's2h.lsp' HTML converter assumes a number of definitions in Scribe +source, so for example, @dash is defined for +Scribe by:

    + +
    +@commandstring(dash @Y[M])
    +
    + +

    In the Scribe output this will create an 'em-dash' +(horizontal dash with a width of the letter 'm'), but the +'s2h.lsp' HTML converter will always translate @dash +to a hyphen character, regardless of the Scribe +@commandstring definition, which 's2h.lsp' ignores. +In other words, 's2h.lsp' is not written to handle any of the +mechanisms provided by Scribe to extend the command set, but there are some +built-in extensions such as @dash so +that 's2h.lsp' can translate Nyquist manuals.

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
       + + + + +
    @codef(name)
    +
      - @codef is used to define a + lisp function or variable. A processor uses this to extract + completion hint info for jNyqIDE.
     
       + + + + +
    @pragma(defn)
    +
      - @pragma(defn) tells 's2h.lsp' that + the next @index marks a term's definition in + the manual.
     
       + + + + +
    @index(term)
    +
      - @index is used to insert 'term' + in the manual's index.

    + +

    Although Scribe has no support for marking up why a location is indexed, +'s2h.lsp' uses @pragma(defn) before +@index(term) to indicate that this +location in the text provides the definition of 'term'. This information +helps 's2h.lsp' give priority to this location in the text in cases where +term may be indexed from multiple locations. In short, if you +define a term, you should insert:

    + +
    +@pragma(defn)@index(term)
    +
    + +

    at the beginning of the definition.

    + +

    Function definitions in the Nyquist manual should be documented like +this:

    + +
    +@begin(fndefs)
    +@codef[myfunction(@pragma(defn)@index(myfunction) ... parameters ...]@\Description of myfunction.
    +
    +@codef[myotherfn(@pragma(defn)@index(myotherfn) ... parameters ...]@\Description of myothernfn.
    +@end(fndefs)
    +
    + +

    Where one or more function definitions can be inside the +@begin(fndefs) and +@end(fndefs) brackets.

    + +

    Another style of documenting functions, used in the XLISP documentation +is to document the function and provide indented detailed descriptions of +each parameter and the return value. This style is shown here and uses +@fdescription and +@pdescription:

    + +
    +@begin(fdescription)
    +        (eval@pragma(defn)@index(eval) @i<expr>) @itemsep evaluate an xlisp expression
    +@begin(pdescription)
    +            @i<expr> @itemsep     the expression to be evaluated
    +
    +            returns @itemsep     the result of evaluating the expression
    +@end(pdescription)
    +@blankspace(1)
    +
    + +

      Back to top

    + +
    + +
    + + diff --git a/docsrc/sdl/part1.tex b/docsrc/sdl/part1.tex new file mode 100755 index 0000000..d0e8a92 --- /dev/null +++ b/docsrc/sdl/part1.tex @@ -0,0 +1,606 @@ +% Manual de SDL +% part1.tex +% pmorales. Junio, 2007 + + +\section{Introduction} + +Usually, Computer Music compositions are formally specified by means +of programming language algorithms. Owing to the fact that {\it Nyquist} is +actually an extension of Lisp, this language can be used for both +sound synthesis and algorithmic composition. + +In addition, Nyquist can be also employed for rendering music that is +described as a note sequence, for instance, a score in traditional +music notation. However, in this case, every note parameter has to be +specified which makes difficult to compose music confortably. + +The {\it Score Description Library} (SDL) is aimed at facilitating the +translation from traditional score notation to {\it Nyquist} source +code and also allowing a fine control over the performance and synthesis +parameters. + +\section{Description} +\subsection{\textit{SDL} score example} + +A SDL score is a quoted list in which the notes along with the pitch, duration attributes and other arguments related to timing and +synthesis parameters, are specified. + +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm] +; Begin of BWV 1069 + +(setf *my-sdl-score* + '((TF 1) + (INIT-INSTR "i1" sinte) (INSTRUMENT "i1") (PWL-POINT :mm 100) (ATTR :idur 0.1) + 2 (:c4 1) :d4 (:e4 2) :c4 :g4 :e4 :a4 (:g4 1) :f4 (:g4 4) + (:a4 1) :c5 :f4 :a4 :g4 :f4 :e4 :g4 :f4 :a4 :d4 :f4 :e4 :d4 :c4 :d4 :e4 :f4 (:g4 2) + :a3 :c4 :d4 :f4 + :g3 :b3 :c4 :e4 (:f3 1) :e4 :d4 :c4 :g3 :d4 :c4 :b3 (ATTR :idur 1) (LABEL :t1) + (:c4 4))) +\end{Verbatim} + +\begin{itemize} +\item \texttt{TF} stands for \textit{Time Factor}. All the durations will + be multiplied by this factor (default value is 1). +\item \texttt{INIT-INSTR} declares an instrument to be used in + synthesis. The first argument \textit{``i1''} is the instrument name in + the SDL score. The second one is the {\it Nyquist} function name + which defines the instrument. This function must be defined independently from + the score by means of an expression \mbox{\texttt{(defun sinte + \ldots)}} + + + +\item \texttt{INSTRUMENT} causes that all the notes from now on are + synthesized by the instrument \textit{``i1''} until a new instrument + is specified. + +\item \texttt{PWL-POINT} defines a piece wise linear function in order + to set the time-variable parameters. For instance, \texttt{:mm} takes + a value of \texttt{100} when the instruction is called. + + +\item \texttt{ATTR} sets the value of a constant parameter. The + parameter value is not changed until a new \texttt{ATTR} instruction + is reached. For example, the \texttt{:idur} parameter takes a + value of {\it 0.1} in every note until a new value is specified by a + new \texttt{ATTR}. + + +\item \texttt{2} defines a 2 beat rest. Two different time types can + be considered: a {\it score time} measured in beat and a {\it physical + time} measured in second. A quarter has a duration of 4 beats. + The physical time is computed according to the score time, {\it tempo} and Time Factor {\tt TF}. + +\item \texttt{(:c4 1)} represents a note given by a C4 pitch and a 1 + beat duration.(i.e, a sixteenth). Only pitch and duration are + specified. Pitch can be specified by using an alternative syntax. + Duration can be any {\it Lisp } expression. The rest of attributes the + needed for synthesis are provided by \texttt{ATTR} y + \texttt{PWL-POINT} instructions. + + +\item \texttt{:d4} is a D4 pitch note and inherited duration of 1 + beat. Rests do not alter the default duration. Changes in duration + are explicitly set by a note attribute. + +\item \texttt{LABEL} sets a time label aimed at synchronizing score + sections. {\tt LABEL} is related to the score time. Coincidence among + {\tt LABEL} references depends on the score {\it tempi} map. + Therefore, the user is responsible for controlling this issue. + +\end{itemize} + +\subsection{\textit{SDL} score processing} + A \textit{SDL} score is processed by using the \texttt{sdl->score} function. For example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(load ``sdl'') +(sdl->score *my-sdl-score*) + +=> ((0.3 0.15 (SINTE :PITCH 60 :MM 100 :IDUR 0.1)) + (0.45 0.15 (SINTE :PITCH 62 :MM 100 :IDUR 0.1)) + (0.6 0.3 (SINTE :PITCH 64 :MM 100 :IDUR 0.1)) + (0.9 0.3 (SINTE :PITCH 60 :MM 100 :IDUR 0.1)) + (1.2 0.3 (SINTE :PITCH 67 :MM 100 :IDUR 0.1)) + +ldots +) +\end{Verbatim} + + +As can be noticed, an {\it Xmusic} score is obtained as a result. + +Every {\it Xmusic} score event has three elements. The first one indicates the note starting time. The second one is the stretching factor and the third one is a call to the synthesis function. For instance, the first event: + +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm] +(0.3 0.15 (SINTE :PITCH 60 :MM 100 :IDUR 0.1)) +\end{Verbatim} +starts at {\tt 0.3} seconds; the stretching factor is {\tt 0.15} and the synthesis function call is \texttt{(sinte :pitch 60 :idur 0.1)}.\par + + +\texttt{:mm} argument is not a synthesis parameter but a control for {\it tempo}. Thus, {\tt sinte} implementation must not include any argument with this name. + + +The strecthing factor multiplies the note duration by the stretching value. For instance, for a sytnthesis function call returning a 1 second note and a stretching factor equals to {\tt 0.15} the overall note duration would be {\tt 0.15}. + +One of the most remarkable features of Nyquist is the +\textit{Behavioral Abstraction} which constitutes a framework for +addressing context-dependent transformations that includes stretching. + +Every synthesis function has a default behavior that properly works in +most of the situations. Nevertheless, this default behavior may not +be appropriated in some cases. Therefore, for instance, the amplitude +envelope attack of a sound may be changed by different strecthing factor +values which can be unsuitable for a harpsichord-like sound. + +To fix this problem, the synthesis function can be defined so that the +attack time is constant and independent form the stretching factor +\footnote{Extensive knowledge of Behavioral Abstraction is required to + perform this task}. + +Alternatively, all the stretching factors can be set to \texttt{1} and +a specific parameter can be used to indicate the specific duration of +any event. \texttt{:idur} parameter is used for this purpose. This +way, sound duration can be higher or lower allowing for several +articulation modes from {\it legato} to {\it stacatto}. The time-control +parameters can not be called \texttt{:dur} since this name is a {\it + Xmusic} reserved keyword. + + + + +\texttt{sdl:normalize-score-duration} is used to set the stretching +factors to 1 as is shown in the following example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] + +(sdl:normalize-score-duration (sdl->score *my-sdl-score*)) + +=> ((0.3 1 (SINTE :PITCH 60 :MM 100 :IDUR 0.1)) + (0.45 1 (SINTE :PITCH 62 :MM 100 :IDUR 0.1)) + (0.6 1 (SINTE :PITCH 64 :MM 100 :IDUR 0.1)) + (0.9 1 (SINTE :PITCH 60 :MM 100 :IDUR 0.1)) + (1.2 1 (SINTE :PITCH 67 :MM 100 :IDUR 0.1)) + +ldots + ) +\end{Verbatim} + +\subsection{\textit{SDL} score rendering} +Once a \textit{SDL} score has been translated to \textit{Xmusic} +format, a {\it Nyquist} {\it behavior} can be obtained by using the \texttt{timed-seq} function \footnote{It is also possible to use the \texttt{score-play} function in order to directly render the score} +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm] +(play (timed-seq (sdl:normalize-score-duration (sdl->score *my-sdl-score*)))) +\end{Verbatim} + + +\subsection{Synchronization} + +When dealing with complex scores it is suitable to split them into +smaller parts. Temporal references must be +established in order to synchronize all the parts involved. These +temporal reference can be set by using a \texttt{LABEL} +instruction. \texttt{sdl->timelabels} function is used to obtain the +temporal references list. This data is registered as a property list +of a symbol created on-the-fly. For example: + +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(setf *my-time-labels* (sdl->timelabels *my-sdl-score*)) +(print (symbol-plist *my-time-labels*)) + +=> (:T1 64) +\end{Verbatim} + +\texttt{AT-LABEL} instruction allow us to match the temporal label which has been +previously specified by \texttt{LABEL} and another time value from a +different score. The temporal references list must be sent, as an +argument, to the \texttt{sdl->score} function as can be seen in the following example: + +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm] +(setf *my-time-labels* (sdl->timelabels *my-sdl-score*)) + +(setf *voz-2* + '((TF 1) + (INIT-INSTR "i1" sinte) (INSTRUMENT "i1") (PWL-POINT :mm 100) (ATTR :idur 0.1) + (AT-LABEL :t1) + 2 (:g4 1) :a4 (:b4 2) :g4)) + +(sdl->score *voz-2* *my-time-labels*) + +=> ((9.9 0.15 (SINTE :PITCH 67 :MM 100 :IDUR 0.1)) + (10.05 0.15 (SINTE :PITCH 69 :MM 100 :IDUR 0.1)) + (10.2 0.3 (SINTE :PITCH 71 :MM 100 :IDUR 0.1)) + (10.5 0.3 (SINTE :PITCH 67 :MM 100 :IDUR 0.1))) +\end{Verbatim} + +\subsubsection*{Warnings} + +Users should notice that time labels are actually score times (measured in beats), whereas in \textit{Xmusic} scores the time is specified in seconds, which in turn are mapped from the score time, the \texttt{TF} parameter and the \textit{tempi} map. For that reason, time labels always coincide in score time, but they have to use the same \texttt{TF} parameter and \textit{tempi} map to achieve a coincidence in physical time. + +\section{Reference guide} +% Incluir ejemplos en los apartados que interese +\subsection{Overall \textit{SDL} score structure} +A \textit{SDL} score is a quoted list containing notes, rests or other elements related to synthesis and performance. +The following elements have to be present in any \textit{SDL} score: + +\begin{itemize} + \item One instrument initialization \texttt{INIT-INSTR}. + \item One instrument assignment \texttt{INSTRUMENT}. + \item One tempo specification \texttt{:mm}, by means of either \texttt{PWL-POINT} or \texttt{ATTR}. + \item One note, at least. +\end{itemize} +Examples: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm] +(setf *minimal-sco-1* '((INIT-INSTR "i1" xx) (INSTRUMENT "i1") (PWL-POINT :mm 100) + (:c4 2))) +(setf *minimal-sco-2* '((INIT-INSTR "i2" yy) (INSTRUMENT "i2") (ATTR :mm 100) :c4)) +\end{Verbatim} +Function \texttt{sdl->score} returns an error if the score does not have this basic data. + +\subsection{Pitch specification} +Pitches can be given by using: + +\begin{itemize} + \item A number. The standard MIDI pitch scale has been adopted here (60 = C4). No tempered pitches are allowed when using floating point numbers (FLONUM). + \item The standard \textit{Nyquist} symbols. Example: \texttt{cs4} = C4 sharp = 61. + \item The standard \textit{lambda~Music} symbols\footnote{A library for music composition developed by Pedro Morales in \textit{Common Lisp}} Pitches are represented by symbols starting with a colon. Sharps and flats are notated by \texttt{\#} and \texttt{b}. Examples: \texttt{:c4 :C4 :c\#4 :C\#4 :cb4 :Cb4} + \item Quoted symbols. Examples: \texttt{'c4 'cs4 'c\#4 'cb4} + \item Strings. Examples: \texttt{``c4'' ``cs4'' ``c\#4'' ``cb4''} +\end{itemize} +Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm] +(setf *pitches* (list 60 60.0 c4 'c4 C4 'C4 cs4 df4 :c4 :c#4 :cb4 :df4 + "c4" "cs4" "cb4" "c#4")) +(mapcar #'sdl:pitch-lex *pitches*) + +=> (60 60 60 60 60 60 61 61 60 61 59 62 60 61 59 61) +\end{Verbatim} + +\subsection{Durations}\label{duraciones} +Durations are measured in beats. A quarter worth 4~beats; a half, 8~beats, and so on. Fractional durations are allowed.\par +Durations can be given by: +\begin{itemize} + \item A number. + \item A \textit{Lisp} expression. Example: \texttt{(/ 4.0 3.0)} represents a third of a quarter, that is, an eighth triplet. +\end{itemize} + + +\subsubsection*{Physical time and score time} +Physical time (measured in seconds) is computed after score time (measured in beats), the \textit{time factor}, \texttt{TF} and the \textit{tempi} map (given by the parameter \texttt{:mm}). + +\subsubsection*{Global Time Factor} +It is given by the score instruction \texttt{TF}. Example: \texttt{(TF 2.0)} multiplies by 2.0 all the durations in the score, whereas \texttt{(TF 0.5)} does it by 0.5. \par +This instruction must appear only once in the score. Its default value is 1.0. +\subsubsection*{\textit{Tempi}} +\textit{Tempi} values are given by the parameter \texttt{:mm} whose value is set by means of the instructions \texttt{ATTR} or \texttt{PWL-POINT}. +\subsection{Notes} +There are two alternatives for specifying notes: +\begin{itemize} + \item By using a two-element list (pitch and duration). Example: \texttt{(:c4 4)} is a quarter \texttt{C4}. + \item By the pitch only. Duration is taken from the last note. +\end{itemize} +The default duration can be changed by means of the \texttt{DUR} instruction. + +\subsection{Rests} +Can be noted by: +\begin{itemize} + \item A number representing the amount of beats. + \item \texttt{DELTA} or \texttt{PAU} instructions\footnote{Both instructions are equivalent.}, indicating the duration by a number or by a \textit{Lisp} expression. +\end{itemize} +Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(setf *sco3* + '((TF 1.0) ; Overall Time Factor + (INIT-INSTR ``i1'' xx) ; Preamble. instr. init. + (INSTRUMENT ``i1'') ; instr. assign. + (ATTR :mm 60) ; metronome MM=60. 1 quarter = 1 sec. + (:c4 4) ; c4 quarter + 4 ; quarter rest + :d4 ; d4. duration = quarter (inherited) + (PAU 8) ; half rest + (:e4 (/ 4.0 3.0)) ; e4. eighth triplet + :e4 ; + :e4 ; + (DELTA (* 2 4)) ; half rest + (:f4 (* 2 1.5)) ; f4 duration = 3 = dotted eighth + (DUR 4) ; current duration = 4 (quarter) + :g4 ; g4 duration = quarter + (DUR (/ 4.0 3.0)) ; current duration = triplet eighth + :a4 :a4 :a4 ; a4 triplets +)) +\end{Verbatim} + +\subsection{Chords} +Polyphonic music can be achieved in \textit{SDL} by gathering several scores. Nevertheless, \textit{SDL} predefined instructions can be more appropriated in simple cases. \par +\texttt{CH} produces simultaneous notes, having the current duration. Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(setf *sco4* + '((TF 1.0) ; Overall Time Factor + (INIT-INSTR ``i1'' xx) ; preamble. init. instr. + (INSTRUMENT ``i1'') ; assign. instr. + (ATTR :mm 60) ; metronome MM=60. 1 quarter = 1 sec. + (:c4 4) ; c4 quarter + 4 ; quarter rest + (DUR 8) ; current duration = 8 = half + (CH :c4 :e4 :g4) ; three-note chord. duration = half + ; +\end{Verbatim} +\texttt{CH1} produces one note without increasing the time. Time increments can be indicated by the \texttt{DELTA} instruction. This way independent duration chords can be built for each note. Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(setf *sco5* + '((TF 1.0) ; Overall Time Factor + (INIT-INSTR ``i1'' xx) ; preamble. Init. instr. + (INSTRUMENT ``i1'') ; assign. instr. + (ATTR :mm 60) ; metronome MM=60. 1 quarter = 1 sec. + (:c4 4) ; c4 quarter + 4 ; quarter rest + (CH1 :c4 4) ; CHORD BEGINNING. c4 quarter + (CH1 :e4 8) ; e4 half. SIMULTANEOUS BEGINNING c4 + (:g4 4) ; g4 quarter. SIMULTANEOUS BEGINNING. c4, e4 + (:c5 4) ; c5 quarter. Starts when g4 ends + ; e4 keeps playing because of the half + ; duration + (CH1 :c4 8) ; Arpeggiated chord BEGINNING + (DELTA 0.2) ; time increases 0.2 beats + (CH1 :e4 (- 8 0.2)) ; e4 starts 0.2 beats after c4 + ; ends at the same time + (DELTA 0.2) ; time increases 0.2 beats + (CH1 :g4 (- 8 0.2 0.2)) ; g4. another arpeggio note + (:c5 (- 8 0.2 0.2 0.2)) ; c5 final arpeggio note + (:g3 4) ; g3 quarter after arpeggio +)) ; (total arpeggio duration = 8) +\end{Verbatim} + + \subsection{Instruments} +In every score notes must be tied to a synthesis instrument. \texttt{INIT-INSTR} is the instruction used for mapping the score instrument name to a \textit{Nyquist} function that implements the instrument itself.\par +The \texttt{INSTRUMENT} instruction assigns the instrument name to the notes. The current instrument can be set by a new \texttt{INSTRUMENT} instruction. Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(setf *sco6* + '((TF 1.0) + (INIT-INSTR ``i1'' flute) ; assign i1 instrument score name + ; to the +textbf[flute] function + (INSTRUMENT ``i1'') ; current instr. = i1 + (ATTR :mm 60) + (:c4 4) ; rendered by +textbf[flute] + 4 + (INIT-INSTR ``i2'' clarinet) ; assign i2 instrument score name + ; to the +textbf[clarinet] function + :d4 ; rendered by +textbf[flute] + (INSTRUMENT ``i2) ; current instr. = i2 + :e4 ; rendered by +textbf[clarinet] +)) +\end{Verbatim} + +\subsection{Attributes} +In \textit{SDL} scores, parameters for synthesis functions in \textit{Nyquist} are defined by \texttt{ATTR} and \texttt{PWL-POINT} instructions.\par +\begin{itemize} + \item \texttt{ATTR} has two arguments. The first one is the parameter name (starting with a colon). The second one is used just to set the parameter value. The current parameter value can be changed by another \texttt{ATTR} instruction. + \item \texttt{PWL-POINT} behaves like the \texttt{ATTR} instruction. The only difference is that a linear interpolation is performed between two consecutive \texttt{PWL-POINT} instructions. +\end{itemize} +It is not allowed to define the same attribute value by using both \texttt{ATTR} and \texttt{PWL-POINT} instructions. + +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(setf *sco7* + '((TF 1.0) + (INIT-INSTR ``i1'' flute) ; maps i1 to +textbf[flute] + (INSTRUMENT ``i1'') ; current instr. i1 (flute) + (:c4 4) ; mm = 100; rel = 4; decay = 3.2 + (ATTR :decay 3.2) ; + (:d4 4) ; mm = 100; rel = 4; decay = 5.1 + (ATTR :decay 5.1) + (:e4 4) ; mm = 100; rel = 4; decay = 5.1 + (PWL-POINT :rel 4.0) + (PWL-POINT :mm 100) + (:f4 4) ; mm = 100; rel = 4; decay = 5.1 + (:g4 4) ; mm = 100; rel = 5; decay = 5.1 + (:a4 4) ; mm = 100; rel = 6; decay = 5.1 + (PWL-POINT :rel 7.0) + (:b4 4) ; mm = 100; rel = 7; decay = 5.1 + (:c5 4) ; mm = 100; rel = 7; decay = 5.1 + (:d5 4) ; mm = 100; rel = 7; decay = 5.1 + (PWL-POINT :rel 7.0) + (:e5 4) ; mm = 100; rel = 7; decay = 5.1 +)) +\end{Verbatim} + + +\subsection{Tempi} +\texttt{ATTR} can be used in case of sharp tempo changes, whereas \texttt{PWL-POINT} performs gradual tempo changes. Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(setf *sco-8* + '((TF 1) + (INIT-INSTR "i1" flute) (INSTRUMENT "i1") + (:c4 4) + (PWL-POINT :mm 60) + :d4 :e4 :f4 :g4 + (PWL-POINT :mm 60) + :e5 :d5 :c5 :b4 :c5 + (PWL-POINT :mm 30))) + +(score-print (sdl->score *voz-8*)) + +=> ((0 1 (FLUTE :PITCH 60 :MM 60)) + (1 1 (FLUTE :PITCH 62 :MM 60)) + (2 1 (FLUTE :PITCH 64 :MM 60)) + (3 1 (FLUTE :PITCH 65 :MM 60)) + (4 1 (FLUTE :PITCH 67 :MM 60)) + (5 1 (FLUTE :PITCH 76 :MM 60)) + (6 1.11111 (FLUTE :PITCH 74 :MM 54)) ; ritardando + (7.11111 1.25 (FLUTE :PITCH 72 :MM 48)) + (8.36111 1.42857 (FLUTE :PITCH 71 :MM 42)) + (9.78968 1.66667 (FLUTE :PITCH 72 :MM 36)) +) +\end{Verbatim} +\subsection{Macros} +A basic macro implementation is available in \textit{SDL} which allows for a specification of repetitive structures such as tremeloes, etc. The \texttt{MAC} instruction is used for this purpose. The first argument is the name of a \textit{Lisp} function and the rest ones represents the arguments for this function. Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +; +textit[Nyquist] function that repeats an event n times + +(defun sdl-repeat (n quoted-event) + (let (result) + (dotimes (i n (apply #'append result)) + (push quoted-event result)))) + +; macro +textit[sdl-repeat] called from a score +; the sequence :f4 :g4 is repeated 4 times + +(setf *score* + '((TF 1.0) + (INIT-INSTR "i1" flute2)(INSTRUMENT "i1")(ATTR :mm 60) + (:e4 4) (MAC sdl-repeat 4 (:f4 :g4)))) + +(sdl->score *score*)) + +=> ((0 1 (FLUTE2 :PITCH 64 :MM 60)) + (1 1 (FLUTE2 :PITCH 65 :MM 60)) ; f4 repite 4 veces f4 g4 + (2 1 (FLUTE2 :PITCH 67 :MM 60)) ; g4 + (3 1 (FLUTE2 :PITCH 65 :MM 60)) ; f4 + (4 1 (FLUTE2 :PITCH 67 :MM 60)) ; g4 + (5 1 (FLUTE2 :PITCH 65 :MM 60)) ; f4 + (6 1 (FLUTE2 :PITCH 67 :MM 60)) ; g4 + (7 1 (FLUTE2 :PITCH 65 :MM 60)) ; f4 + (8 1 (FLUTE2 :PITCH 67 :MM 60)) ; g4 +) +\end{Verbatim} +Macros can be also used to control the parameter values through a \textit{Lisp} function instead of specifying them note by note. Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +; pitches controlled by logistic equation + +(setf *logistica* 0.3) +(setf *k* 3.97) + +(defun logistica () + (setf *logistica* (* *k* (- 1.0 *logistica*) *logistica*))) + +(defun call-logistica (n dur pitch-min pitch-interval) + (let (result) + (dotimes (i n (reverse result)) + (push (list (+ pitch-min (round (* (logistica) pitch-interval))) dur) + result)))) + +(setf *score2* + '((TF 1.0) + (INIT-INSTR "i1" flute2)(INSTRUMENT "i1")(ATTR :mm 60) + (:e4 4) (MAC call-logistica 5 4 30 15))) + +(score-print (sdl->score *score2*)) + +=> ((0 1 (FLUTE2 :PITCH 64 :MM 60)) + (1 1 (FLUTE2 :PITCH 43 :MM 60)) + (2 1 (FLUTE2 :PITCH 38 :MM 60)) + (3 1 (FLUTE2 :PITCH 45 :MM 60)) + (4 1 (FLUTE2 :PITCH 31 :MM 60)) + (5 1 (FLUTE2 :PITCH 34 :MM 60)) +) +\end{Verbatim} + +\subsection{\textit{SDL} Functions} +\texttt{FUN} instruction allows for defining score events through \textit{Lisp} functions. \par +\textbf{Warning:} The inclusion of attribute \texttt{:mm} is mandatory if the event to be generated is a note. Example: +\begin{Verbatim}[frame=single,fontsize=\small,numbers=left,numbersep=2mm, + commandchars=+\[\]] +(load "xm") + +(setf *my-durations* (make-heap (list 4 6 8))) + +(defun heap-durations (inicio pitch) + (let ((dur (next *my-durations*))) + (list inicio dur (list 'sinte-fun :pitch pitch :mm 60 :idur dur)))) + +(setf *score3* + '((TF 1.0) + (INIT-INSTR "i1" flute2)(INSTRUMENT "i1")(ATTR :mm 60) + (:e4 4) + (FUN #'heap-durations 1 :c4) + (FUN #'heap-durations 2 :d4) + (FUN #'heap-durations 3 :e4) + (FUN #'heap-durations 4 :c4) + (FUN #'heap-durations 7 :d4))) + +(sdl->score *score3*) + +=> ((0 1 (FLUTE2 :PITCH 64 :MM 60)) + (0.25 1.5 (SINTE-FUN :PITCH :C4 :MM 60 :IDUR 6)) + (0.5 1 (SINTE-FUN :PITCH :D4 :MM 60 :IDUR 4)) + (0.75 2 (SINTE-FUN :PITCH :E4 :MM 60 :IDUR 8)) + (1 1.5 (SINTE-FUN :PITCH :C4 :MM 60 :IDUR 6)) + (1.75 1 (SINTE-FUN :PITCH :D4 :MM 60 :IDUR 4)) +) +\end{Verbatim} + +\section{Reference summary} +\subsection{\textit{SDL} format for score instructions} + +\noindent\texttt{(TF args: time-factor)} \par +Overall Time Factor. All the durations in the score are multiplied by this factor.\\ + +\noindent\texttt{(TIME-IN-SECONDS)}\par +No arguments needed. Durations are measured in seconds when tempo is set to~60.\\ + +\noindent\texttt{(DUR lisp-expr)}\par +Sets the value of the current duration. Any \textit{Lisp} expression can be used as argument.\\ + +\noindent\texttt{(DELTA lisp-expr)}\par + Increases the time value.\\ + +\noindent\texttt{(PAU lisp-expr)}\par + The same as \texttt{DELTA}.\\ + +\noindent\texttt{(INIT-INSTR string function-name)}\par +Initializes an instrument. It maps the score name instrument \texttt{string} to the synthesis function \texttt{function-name}.\\ + +\noindent\texttt{(INSTRUMENT string)}\par + Sets the current instrument to \texttt{string}. The notes following this instruction are rendered by the instrument \texttt{string} until a new instrument is set.\\ + +\noindent\texttt{(ATTR :symbol lisp-expr)} \par +Sets \texttt{:symbol} value to \texttt{lisp-expr}. The first argument must start with a colon. The value for this attribute is kept until a new \texttt{ATTR} instruction is reached.\\ + +\noindent\texttt{(PWL-POINT :symbol lisp-expr)}\par + Behaves like \texttt{ATTR}. The only difference is that a linear interpolation is performed between two consecutive \texttt{PWL-POINT} instructions.\\ + +\noindent\texttt{(CH \&rest pitches)} \par +Produces a chord containing the pitches given by its argument and the current duration.\\ + +\noindent\texttt{(CH1 pitch duration)} \par +Produces a note whose pitch and duration are given by the arguments. Time is not increased, so that the next event starts at the same time.\\ + +\noindent\texttt{(FUN \#'function-name \&rest args)} \par +Calls the function \texttt{function-name} sending the arguments in the \texttt{args} list. The returning value must be an event to be added to an Xmusic score. This event has to be processed by the \textit{Nyquist} function \texttt{timed-seq}. Hence, the event must follow the format \texttt{(start-time stretching-factor synthesis-function-call)}\\ + +\noindent\texttt{(MAC macro-name \&rest args)} \par +Calls the function \texttt{macro-name} sending the arguments in the \texttt{args} list. The returning value must be \textit{SDL} code which replaces the call to the macro. \\ + +\noindent\texttt{number}\par + This is actually a rest of \texttt{number} beat duration.\\ + +\noindent\texttt{symbol}\par +A note whose pitch is given by \texttt{symbol} and with the current duration.\\ + +\noindent\texttt{(pitch dur)} \par +Note specified by pitch and dur arguments. + +\subsection{\textit{SDL} library functions} +\noindent\texttt{(sdl->score score-data \&optional time-marks)}\par +Produces an \textit{Xmusic} score consisting of a \mbox{\texttt{(onset-time stretch-factor synthesis-function)}} format event list.\par +\noindent\texttt{score-data} is a \textit{SDL} score. \texttt{time-marks} is a symbol whose property list contains the time labels to be referenced from \texttt{score-data}.\\ + +\noindent\texttt{(sdl->timelabels score-data \&optional time-marks)}\par +Returns a symbol whose property-list contains the time labels in \texttt{time-marks} added to \texttt{score-data} time labels. Sinchronicity can be ensured by using time labels. + +\noindent\texttt{(sdl:normalize-score-duration score)}\par +\texttt{score} is an \textit{Xmusic} score. This function sets all the event stretching factors to 1.0. This is intended for making synthesis parameters independent from notes duration. + +\section{\textit{lambda~Music} compatibility} +\textit{lambda Music} is a library developed in Common~Lisp and intended for MIDI rendering. Many scores from \textit{lambda~Music} can be converted to \textit{SDL} by introducing just minor changes. + +\section{Final remarks} +This library is just an attempt to facilitate the music transcription from traditional notation to synthesis in \textit{Nyquist}. Currently it is under development and therefore some features have to be improved. For instance, the inconsistency between physical and score time. In addition, an extended implementation of the macros should be considered. + diff --git a/docsrc/sdl/pjmcfg.sty b/docsrc/sdl/pjmcfg.sty new file mode 100755 index 0000000..f734661 --- /dev/null +++ b/docsrc/sdl/pjmcfg.sty @@ -0,0 +1,127 @@ +% ------------------------ +% PAQUETE DE CONFIGURACION +% EJERCICIO FINAL de LaTeX +% pjm. Junio, 2007 +% ------------------------ + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{pjmcfg}[2007/06/07 pjm] + + +% Estilo de pagina + +\newcommand{\ps@pjmx}{% + \renewcommand{\@oddhead}{\sffamily \rightmark \hfill \thepage} + \renewcommand{\@evenhead}{\sffamily \thepage \hfill Score Description Library} + \renewcommand{\@oddfoot}{} + \renewcommand{\@evenfoot}{} + \renewcommand{\sectionmark}[1]{% + \markright{\MakeUppercase{\thesection.\quad ##1}}}} + +% Dimensiones + +\setlength{\hoffset}{-1in} +\setlength{\oddsidemargin}{2cm} +\setlength{\evensidemargin}{2.5cm} +\setlength{\textwidth}{\paperwidth} +\addtolength{\textwidth}{-\oddsidemargin} +\addtolength{\textwidth}{-\evensidemargin} +\setlength{\voffset}{-1in} +\setlength{\topmargin}{2cm} +\setlength{\headsep}{0.5cm} +\setlength{\footskip}{1.5cm} +\setlength{\textheight}{\paperheight} +\addtolength{\textheight}{-2\topmargin} +\addtolength{\textheight}{-\footskip} + + +% Titulos de secciones + +\renewcommand{\section}{\@startsection{section}{1}{0ex}% + {-3.5ex plus -1ex minus -0.2ex}% + {2.3ex plus 0.2ex}% + {\normalfont\Large\bfseries\sffamily}} +\renewcommand{\subsection}{\@startsection{subsection}{2}{0ex}% + {-3.25ex plus -1ex minus -0.2ex}% + {1.5ex plus 0.2ex}% + {\normalfont\large\bfseries\sffamily}} +\renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{0ex}% + {-3.25ex plus -1ex minus -0.2ex}% + {1.5ex plus 0.2ex}% + {\normalfont\normalsize\bfseries\itshape}} + +% estos mantienen su configuracion por defecto +% \newcommand{\paragraph}{\@startsection{paragraph}{4}{0ex}% +% {3.25ex plus 1ex minus 0.2ex}% +% {-1em}% +% {\normalfont\normalsize\bfseries}} +% \newcommand{\subparagraph}{\@startsection{subparagraph}{5}{\parindent}% +% {3.25ex plus 1ex minus 0.2ex}% +% {-1em}% +% {\normalfont\normalsize\bfseries}} + + +% Leyenda de figuras y cuadros + +\renewcommand{\@makecaption}[2]{% + \vspace{\abovecaptionskip} + \sbox{\@tempboxa}{\textbf{#1}. #2}% + \ifdim \wd\@tempboxa >\linewidth + \textbf{#1}. #2\par + \else + \global\@minipagefalse + \makebox[\linewidth]{\hfil\usebox{\@tempboxa}\hfil}% + \fi + \vspace{\belowcaptionskip}} + + + +% Definicion de ordenes + + +% flecha para resaltar el inicio de un parrafo +\newcommand{\flecha}{\noindent\ding{'324}} + + +% ----------------------------------------------------------- +% \figura{nombre-fichero}{argumentos}{titulo}{etiqueta} +% Resultado: +% Inserta una figura. ``La figura~\ref{etiqueta} muestra...'' +% permite referenciar la figura desde el texto. +% Argumentos: width=Xcm,height=Ycm,angle=Z +% ------------------------------------------------------------ + +\newcommand{\figura}[4]{% + + \begin{figure}[ht] + \begin{center} + \includegraphics[#2]{#1} + \caption{#3} + \label{#4} + \end{center} + \end{figure} +} + +% Entornos + +% ----------------------------------------------------------- +% \begin{tabla}{titulo}{etiqueta} +% ... (contenido tabla) +% \end{tabla} +% Resultado: +% Inserta una tabla. +% Contenido de la tabla se define mediante el entorno 'tabular' +% ``Tabla~\ref{etiqueta}'' permite referenciar la tabla. +% ----------------------------------------------------------- + +\newenvironment{tabla}[2]{% + \begin{table}[ht] + \caption{#1} + \label{#2} + \begin{center}} + {\end{center} + \end{table}} + + +% fin del paquete +\endinput diff --git a/docsrc/sdl/sdl-man.tex b/docsrc/sdl/sdl-man.tex new file mode 100755 index 0000000..c101c3c --- /dev/null +++ b/docsrc/sdl/sdl-man.tex @@ -0,0 +1,87 @@ +\documentclass[a4paper,11pt,twoside,titlepage]{article} + +%\usepackage[T1]{fontenc} +%\usepackage[spanish]{babel} +\usepackage{graphicx} +\usepackage{makeidx} +\usepackage{amsmath} +\usepackage{pifont} +\usepackage{fancyvrb} +\usepackage{pjmcfg} + +% subordinacion de contadores +\numberwithin{figure}{section} +\numberwithin{table}{section} +\numberwithin{equation}{section} % AVISO: no hay ecuaciones numeradas en el texto + + +\makeindex + +\pagestyle{pjmx} + + + +\begin{document} + +% TITULO ----------------------------------------------------------------------- + +\begin{titlepage} + +% titulo + {\ \vfill \Huge\bfseries\sffamily \hfill Score Description Library\\[0.5cm] + \mdseries \mbox{} \hfill Reference Manual\\ + \rule{\textwidth}{1mm}} \\[0.2cm] +% autor + {\sffamily \mbox{} \hfill Pedro J. Morales.} \\ +{\sffamily \mbox{} \hfill English translation by Luis Rodr\'iguez and Pedro J. Morales.} \\ + + +% fecha + {\sffamily \hfill \today} \\[1cm] + +\end{titlepage} + +% REVERSO DEL TITULO EN BLANCO ------------------------------------------------ +\thispagestyle{empty} +\mbox{} +\pagebreak + + +% TABLA DE CONTENIDOS, FIGURAS, CUADROS --------------------------------------- + +% inicia contador de paginas (MANEJO DE CONTADORES) +\setcounter{page}{1} +% numeracion de paginas en roman +\renewcommand{\thepage}{\roman{page}} +% comando equivalente +% \pagenumbering{roman} + + +\tableofcontents +%\listoffigures +%\listoftables + +\newpage + +% INICIO DEL TEXTO ------------------------------------------------------------ + +% inicia contador de paginas +\setcounter{page}{1} +% las paginas se numeran en arabic +\renewcommand{\thepage}{\arabic{page}} +% comando equivalente +% \pagenumbering{arabic} + + +\input{part1} + + +% referencias +% \bibliographystyle{alpha} +% \bibliography{ejfinal} + + +% indice alfabetico +% \printindex + +\end{document} \ No newline at end of file diff --git a/docsrc/template/filcap.mss b/docsrc/template/filcap.mss new file mode 100644 index 0000000..2c1bb8a --- /dev/null +++ b/docsrc/template/filcap.mss @@ -0,0 +1,5 @@ +@textform[FillCaption="@begin(transparent)@modify(captionenv,fill,indent 0, +leftmargin +0.5 inch,rightmargin +0.5 inch)@modify(figurecounter, +numbered <@@b[Figure@@ @#@:-@1:@@ @@ ]>)@modify(tablecounter, +numbered <@@b[Figure@@ @#@:-@1:@@ @@ ]>)@caption<@parm>@~ +@end(transparent)"] diff --git a/docsrc/toafs.bat b/docsrc/toafs.bat new file mode 100644 index 0000000..3a84c9d --- /dev/null +++ b/docsrc/toafs.bat @@ -0,0 +1,5 @@ +copy nyquist\*.mss p:\doc\man\nyquist +copy nyquist\*.ps p:\doc\man\nyquist +copy bib\music.bib p:\doc\man\bib\music.bib +copy template\filcap.mss p:\doc\man\template\filcap.mss +copy xlisp\*.mss p:\doc\man\xlisp diff --git a/docsrc/toafs.sh b/docsrc/toafs.sh new file mode 100644 index 0000000..e2c30f6 --- /dev/null +++ b/docsrc/toafs.sh @@ -0,0 +1,5 @@ +scp nyquist/*.mss rbd@linux.gp.cs.cmu.edu:doc/man/nyquist +scp nyquist/*.ps rbd@linux.gp.cs.cmu.edu:doc/man/nyquist +scp bib/music.bib rbd@linux.gp.cs.cmu.edu:doc/man/bib/music.bib +scp template/filcap.mss rbd@linux.gp.cs.cmu.edu:doc/man/template/filcap.mss +scp xlisp/*.mss rbd@linux.gp.cs.cmu.edu:doc/man/xlisp diff --git a/docsrc/xlisp/intgen.mss b/docsrc/xlisp/intgen.mss new file mode 100644 index 0000000..dcd009d --- /dev/null +++ b/docsrc/xlisp/intgen.mss @@ -0,0 +1,241 @@ +This documentation describes Intgen, a program for generating XLISP to C +interfaces. Intgen works by scanning @code(.h) files with special comments in +them. Intgen builds stubs that implement XLISP SUBR's. When the SUBR is +called, arguments are type-checked and passed to the C routine declared in +the @code(.h) file. Results are converted into the appropriate XLISP type and +returned to the calling XLISP function. Intgen lets you add C functions +into the XLISP environment with very little effort. + +The interface generator will take as command-line input: +@begin(itemize) +the name of the @code(.c) file to generate (do not include the @code(.c) extension; e.g. write +@code(xlexten), not @code(xlexten.c)); + +a list of @code(.h) files. +@end(itemize) +Alternatively, the command line may specify a command file from which to read file names. The command file name should be preceded by "@@", for example: +@begin(example) +intgen @@sndfns.cl +@end(example) +reads sndfns.cl to get the command-line input. Only one level of indirection is allowed. + +The output is: +@begin(itemize) +a single @code(.c) file with one SUBR defined for each designated +routine in a @code(.h) file. + +a @code(.h) file that declares each new C routine. E.g. if the @code(.c) file is named @code(xlexten.c), this file will be named @code(xlextendefs.h); + +a @code(.h) file that extends the SUBR table used by Xlisp. E.g. if the @code(.c) file is named @code(xlexten.c), then this file is named @code(xlextenptrs.h); + +a @code(.lsp) file with lisp initialization expressions copied from the +@code(.h) +files. This file is only generated if at least one initialization expression is encountered. +@end(itemize) + +For example, the command line +@begin(example) +intgen seint ~setypes.h access.h +@end(example) +generates the file @code(seint.c), using declarations in @code(setypes.h) +and @code(access.h). Normally, the @code(.h) files are included by the +generated file using @code(#include) commands. A @code(~) before a file +means do not include the @code(.h) file. (This may be useful if you extend +@code(xlisp.h), which will be included anyway). Also generated will be +@code(setintdefs.h) and @code(seintptrs.h). + +@subsection(Extending Xlisp)@index(Extending Xlisp) +Any number of @code(.h) files may be named on the command line to Intgen, +and Intgen will make a single @code(.c) file with interface routines for all +of the @code(.h) files. On the other hand, it is not necessary to put all +of the extensions to Xlisp into a single interface file. For example, you +can run Intgen once to build interfaces to window manager routines, and +again to build interfaces to a new data type. Both interfaces can be linked +into Xlisp. + +To use the generated files, you must compile the @code(.c) files and link +them with all of the standard Xlisp object files. In addition, you must +edit the file @code(localdefs.h) to contain an @code(#include) for each +@code(*defs.h) file, and edit the file @code(localptrs.h) to include each +@code(*ptrs.h) file. For example, suppose you run Intgen to build +@code(soundint.c), @code(fugueint.c), and @code(tableint.c). You would then +edit @code(localdefs.h) to contain the following: +@begin(example) +#include "soundintdefs.h" +#include "fugueintdefs.h" +#include "tableintdefs.h" +@end(example) +and edit @code(localptrs.h) to contain: +@begin(example) +#include "soundintptrs.h" +#include "fugueintptrs.h" +#include "tableintptrs.h" +@end(example) +These @code(localdefs.h) and @code(localptrs.h) files are in turn included +by @code(xlftab.c) which is where Xlisp builds a table of SUBRs. + +To summarize, building an interface requires just a few simple steps: +@begin(itemize) +Write C code to be called by Xlisp interface routines. This C code does the +real work, and in most cases is completely independent of Xlisp. + +Add comments to @code(.h) files to tell Intgen which routines to build +interfaces to, and to specify the types of the arguments. + +Run Intgen to build interface routines. + +Edit @code(localptrs.h) and @code(localdefs.h) to include generated +@code(.h) files. + +Compile and link Xlisp, including the new C code. +@end(itemize) + +@section(Header file format)@index(Header file format) + +Each routine to be interfaced with Xlisp must be declared as +follows: +@begin(example) +@i(type-name) @i(routine-name)(); /* LISP: (@i(func-name) @i(type@-(1)) @i(type@-(2)) ...) */ +@end(example) +The comment may be on the line following the declaration, but the +declaration and the comment must each be on no more than one line. +The characters @code(LISP:) at the beginning of the comment mark routines +to put in the interface. The comment also gives the +type and number of arguments. The function, when accessed from lisp will +be known as @I(func-name), which need not bear any relationship to +@i(routine-name). By convention, underscores in the C @i(routine-name) +should be converted to dashes in @i(func-name), and @i(func-name) should be in +all capitals. None of this is enforced or automated though. + +Legal type_names are: +@begin(description) +@code(LVAL)@\returns an Xlisp datum. + +@code(atom_type)@\equivalent to @code(LVAL), but the result is expected to +be an atom. + +@code(value_type)@\a value as used in Dannenberg's score editor. + +@code(event_type)@\an event as used in Dannenberg's score editor. + +@code(int)@\interface will convert int to Xlisp @code(FIXNUM). + +@code(boolean)@\interface will convert int to @code( T) or @code(nil). + +@code(float) or @code(double)@\interface converts to @code(FLONUM). + +@code(char *) or @code(string) or @code(string_type)@\interface converts to @code(STRING). The result string will be copied into the XLISP heap. + + void@\interface will return @code(nil). +@end(description) + +It is easy to extend this list. Any unrecognized type will +be coerced to an @code(int) and then returned as a @code(FIXNUM), and a warning will be +issued. + +The ``@code(*)'' after char must be followed by @i(routine-name) with +no intervening space. + +Parameter types may be any of the following: +@begin(description) +@code(FIXNUM)@\C routine expects an int. + +@code(FLONUM) or @code(FLOAT)@\C routine expects a @code(double). + +@code(STRING)@\C routine expects @code(char *), the string is not copied. + +@code(VALUE)@\C routine expects a @code(value_type). (Not applicable to Fugue.) + +@code(EVENT)@\C routine expects an @code(event_type). (Not applicable to Fugue.) + +@code(ANY)@\C routine expects @code(LVAL). + +@code(ATOM)@\C routine expects @code(LVAL) which is a lisp atom. + +@code(FILE)@\C routine expects @code(FILE *). + +@code(SOUND)@\C routine expects a @code(SoundPtr). + +@end(description) +Any of these may be followed by ``@code(*)'': @code(FIXNUM*), @code(FLONUM*), @code(STRING*), @code(ANY*), @code(FILE*), +indicating C routine expects @code(int *), @code(double *), @code(char **), @code(LVAL *), or @code(FILE **) . +This is basically a mechanism for returning more than one value, @i(not) +a mechanism for clobbering XLisp values. In this spirit, the interface +copies the value (an @code(int), @code(double), @code(char *), @code(LVAL), or @code(FILE *)) to a local variable +and passes the address of that variable to the C routine. On return, +a list of resulting ``@code(*)'' parameters is constructed and bound to the +global XLisp symbol @code(*RSLT*@index(*RSLT*)). (Strings are copied.) If the C routine is void, then the result list is also returned by the corresponding XLisp function. + +Note 1: this does not support C routines like strcpy that modify strings, +because the C routine gets a pointer to the string in the XLisp heap. +However, you can always add an intermediate routine that allocates +space and then calls @code(strcpy), or whatever. + +Note 2: it follows that a new XLisp @code(STRING) will be created for each @code(STRING*) parameter. + +Note 3: putting results on a (global!) symbol seems a bit unstructured, but note that one could write a multiple-value binding macro that hides this ugliness from the user if desired. In practice, I find that pulling the extra result values from @code(*RSLT*) when needed is perfectly acceptable. + +For parameters that are result values only, the character ``@code(^)'' may +be substituted for ``@code(*)''. In this case, the parameter is @i(not) to be passed in the XLisp calling site. +However, the address of an initialized +local variable of the given type is passed to the corresponding +C function, and the resulting value is passed back through @code(*RSLT*) as +ordinary result parameter as described above. +The local variables are initialized to zero or @code(NULL). + +@section(Using #define'd macros)@index(#define'd macros) +If a comment of the form: +@begin(example) +/* LISP: @i(type-name) (@i(routine-name-2) @i(type-1) @i(type-2) ...) */ +@end(example) +appears on a line by itself and there was a @code(#define) on the previous +line, then the preceding @code(#define) is treated as a C routine, e.g. +@begin(example) +#define leftshift(val, count) ((val) << (count)) +/* LISP: int (LOGSHIFT INT INT) */ +@end(example) +will implement the LeLisp function @code(LOGSHIFT). + +The @i(type-name) following ``@code(LISP:)'' should have no spaces, e.g. use @code(ANY*), not +@code(ANY *). + +@section(Lisp Include Files)@index(Lisp Include Files) +Include files often define constants that we would like to have around +in the Lisp world, but which are easier to initialize just by loading +a text file. Therefore, a comment of the form: +@begin(example) +/* LISP-SRC: (any lisp expression) */ +@end(example) +will cause Intgen to open a file @i(name)@code(.lsp) and append +@begin(example) +(any lisp expression) +@end(example) +to @i(name)@code(.lsp), where @i(name) is the interface name passed on the command line. If none of the include files examined have comments of +this form, then no @i(name)@code(.lsp) file is generated. +@p(Note:) @i(the LISP-SRC comment must be on a new line.) + +@section(Example) +This file was used for testing Intgen. It uses a trick (ok, it's a hack) to interface +to a standard library macro (tolower). Since tolower is already +defined, the macro ToLower is defined just to give Intgen a name +to call. Two other routines, strlen and tough, are interfaced as +well. +@begin(example) +/* igtest.h -- test interface for intgen */ + +#define ToLower(c) tolower(c) +/* LISP: int (TOLOWER FIXNUM) */ + +int strlen(); /* LISP: (STRLEN STRING) */ + +void tough(); + /* LISP: (TOUGH FIXNUM* FLONUM* STRING ANY FIXNUM) */ +@end(example) + +@section(More Details) + +Intgen has some compiler switches to enable/disable the use of certain types, including +@code(VALUE) and @code(EVENT) types used by Dannenberg's score editing work, the @code(SOUND) type used by Fugue, and @code(DEXT) and @code(SEXT) types added for Dale Amon. +Enabling all of these is not likely to cause problems, +and the chances of an accidental use of these types getting through +the compiler and linker seems very small. diff --git a/docsrc/xlisp/xlisp-doc/README b/docsrc/xlisp/xlisp-doc/README new file mode 100644 index 0000000..d1249c9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/README @@ -0,0 +1,11 @@ +January 11, 2011 + +The XLISP dos in this directory still in an unfinished state. +The hyperlinking works, but many pages are still too messy. + +Just load "start.htm" into your web browser, everything else +is linked from there. + +In case of doubt write to: + +edgar-rft@web.de diff --git a/docsrc/xlisp/xlisp-doc/examples/apropos.htm b/docsrc/xlisp/xlisp-doc/examples/apropos.htm new file mode 100644 index 0000000..f0657b2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/apropos.htm @@ -0,0 +1,268 @@ + + +apropos + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    apropos

    + +
    + + + +

    + +
    + +

    (apropos &optional pattern type)

    + +

    The 'apropos' function searches the Nyquist/XLISP *obarray* for +matching symbol names containing 'pattern' and being of 'type'. It +prints a list of the results in alphabetical order.

    + +

    'pattern and 'type' can be given as symbols or strings. If +no 'pattern' is given, all symbol names are considered as matching. +If no 'type' is given, all symbol types are considered as +matching. With 'type', only the first letter is important. A +type of 'f' searches for symbols with a valid function value, while a +type of 'v' searches for symbols with a valid variable value.

    + + + +
    + +

    + +

    Examples:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       + + + + +
    (apropos)
    +
      - all symbols known by Nyquist
       + + + + +
    (apropos nil 'f)
    +
      - all bound functions known by Nyquist
       + + + + +
    (apropos nil 'v)
    +
      - all bound variables known by Nyquist
       + + + + +
    (apropos 'snd 'f)
    +
      - all function names containing 'snd'

    + +

    A method to introspect classes and objects:

    + +
    +(setq instance-var '*wrong-variable*)                 ; value outside the object
    +
    +(setq my-class (send class :new '(instance-var)))                ; class with instance variable
    +(send my-class :answer :isnew '() '((setq instance-var '*OK*)))  ; value inside an object
    +(send my-class :answer :eval '(list) '((eval list)))             ; evaluation method
    +
    +(setq my-object (send my-class :new))                 ; instance of my-class
    +(send my-object :eval 'instance-var)                  => *OK*
    +(send my-object :eval '(apropos 'instance-var 'v t))  => *WRONG-VARIABLE*
    +
    + +

    The first version works because the call to 'eval' happens inside the +object:

    + +
    +(send my-class :answer :eval '(list) '((eval list))) => *OK*
    +
    + +

    The second version doesn't work because the call to 'eval' happens +outside the object:

    + +
    +(defun external-function (list)
    +  (eval list))
    +
    +(send my-class :answer :eval '(list) '((external-function list))) => *WRONG-VARIABLE*
    +
    + +

    The call to 'apropos' doesn't work because 'apropos' is executed outside +the object:

    + +
    +(send my-object :eval '(apropos)) => *WRONG-VARIABLE*
    +
    + +

    The trick is to pass the Lisp code of 'apropos' as a list into the inside +of the object and 'apply' it there to the arguments:

    + +
    +(send my-class :answer :apropos '(args)
    +  '((apply (get-lambda-expression #'apropos) args)))
    +
    +(send my-object :apropos '(instance-var v t)) => *OK*
    +
    + +

    But this only works if all function that need access to internal instance +or class variables are executed inside the object. For example, if 'apropos' +calls a function that needs access to an internal instance variable, I +would get a 'unbound variable' error.

    + +

    Here is the code of the 'apropos' function:

    + +
    +(defun apropos (&optional pattern type)
    +  (let (result-list (*gc-flag* nil))
    +    ;; make sure 'pattern' is a string, either empty or upper-case
    +    (if pattern
    +        (setf pattern (string-upcase (string pattern)))
    +      (setf pattern ""))
    +    ;; take only the first letter of 'type' and make it an upper-case string
    +    (if type (setf type (string-upcase (subseq (string type) 0 1))))
    +    ;; go through all entries in the *obarray* symbol hash table
    +    (dotimes (i (length *obarray*))
    +      (let ((entry (aref *obarray* i)))  ; *obarray* is an array of lists
    +        ;; if the *obarray* entry is not an empty list
    +        (if entry
    +          ;; go through all elements of the *obarray* entry list
    +          ;; do not use 'dolist' because *obarray* contains *unbound*
    +          (dotimes (j (length entry))
    +            ;; convert the symbol to a string to enable pattern matching
    +            (let ((string (string (nth j entry))))
    +              ;; if the symbol string matches the search pattern
    +              (if (string-search pattern string)
    +                  ;; if a special symbol type to search for was given
    +                  (if type
    +                      ;; if a 'type' search was initiated and the current
    +                      ;; symbol has no 'type' value bound to it, do nothing
    +                      ;; and return from 'cond' without adding the symbol
    +                      ;; string to the result list
    +                      (cond ((and (string= type "F")  ; bound functions only
    +                                  (not (fboundp (nth j entry))))
    +                             nil)
    +                            ((and (string= type "V")  ; bound variables only
    +                                  (not (boundp (nth j entry))))
    +                             nil)
    +                            ;; if the symbol has passed all tests,
    +                            ;; add the symbol string to the result list
    +                            (t (setf result-list (cons string result-list))))
    +                    ;; if no special symbol type to search for had been given,
    +                    ;; but the symbol string had matched the search pattern,
    +                    ;; add the symbol string to the result list
    +                    (setf result-list (cons string result-list)))))))))
    +    ;; if the result list contains more than one element
    +    ;; make it become an alphabetically sorted list
    +    (if (> (length result-list) 1)
    +        (setf result-list (sort result-list 'string<)))
    +    ;; print a message according to the search type and pattern
    +    (cond ((and type (string= type "F")) (setf type "function"))
    +          ((and type (string= type "V")) (setf type "variable"))
    +          (t (setf type "symbol")))
    +    (if (string= pattern "")
    +        (format t "All ~a names known by Nyquist:~%" type)
    +        (format t "All ~a names containing pattern ~a:~%" type pattern))
    +    ;; print the search results
    +    (cond (result-list
    +           (let ((list-length (length result-list)))
    +             (format t ";; number of symbols: ~a~%" list-length)
    +             (dolist (i result-list) (format t "~a~%" i))
    +             (if (> list-length 20)
    +               (format t ";; number of symbols: ~a~%" list-length))))
    +          (t (format t "No matches found.")))))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/arrays.htm b/docsrc/xlisp/xlisp-doc/examples/arrays.htm new file mode 100644 index 0000000..6e258ff --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/arrays.htm @@ -0,0 +1,430 @@ + + +Arrays + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Arrays

    + +
    + +

    Arrays are also Sequences.

    + +
      +
    • make-array* - create multi-dimensional arrays
    • +
    • aref* - access multi-dimensional-arrays
    • +
    • vector* - make a one-dimensional array out of arbitrary Lisp expressions
    • +
    • array* - make a multi-dimensional array out of arbitrary Lisp expressions
    • +
    + + + +
    + +

    make-array*

    + +
    + +

    XLISP already has the +make-array +function to create one-dimensional arrays:

    + +

    + +
    +
    (make-array size)
    +
    size - the size [integer] of the array to be created
    +returns - the new array
    +
    + +

    + +

    Here is a function to create multi-dimensional arrays:

    + +

    + +
    +
    (make-array* size-1 [size-2 ...])
    +
    sizeN - the size [integer] of the N-th dimension in the array to be created
    +returns - the new array
    +
    + +

    + +
    +(defun make-array* (&rest dimensions-list)
    +  (cond ((null dimensions-list)
    +         (error "too few arguments"))
    +        ((and (null (rest dimensions-list))
    +              (eql 0 (first dimensions-list)))
    +         (make-array 0))
    +        (t (labels ((multi-vector (dimensions-list)
    +                      (let ((count (first dimensions-list)))
    +                        (if (not (and (integerp count) (plusp count)))
    +                            (error "not a positive integer" count)
    +                            (let ((rest (rest dimensions-list))
    +                                  (elements-list nil))
    +                              (dotimes (i count)
    +                                (push (when rest
    +                                        (multi-vector rest))
    +                                      elements-list))
    +                              (apply #'vector (reverse elements-list)))))))
    +             (multi-vector dimensions-list)))))
    +
    + +

    Examples:

    + +
    +(make-array* 2 3)    => #(#(NIL NIL NIL) #(NIL NIL NIL)))
    +(make-array* 2 2 1)  => #(#(#(NIL) #(NIL)) #(#(NIL) #(NIL)))
    +
    + +

    Like make-array it +is possible to create one-dimensional arrays with zero +elements:

    + +
    +(make-array* 0)  => #()
    +(make-array  0)  => #()
    +
    + +

    But it is not allowed to create multi-dimensional arrays +with zero-size dimensions:

    + +
    +(make-array* 1 0 1)  => error: not a positive integer - 0
    +
    + +

    Rationale: Multi-dimensional arrays are implemented as nested +vectors and a zero-element vector cannot hold the vector for +the subsequent dimension. We would need some additional +administration overhead to keep the subsequent dimensions accessible, but +this would break the compatibility to the build-in XLISP +aref function.

    + +

    More practical examples see 'aref*' below.

    + +

      Back to top

    + + + +
    + +

    aref*

    + +
    + +

    XLISP already has the aref function +to access elements in one-dimensional arrays:

    + +

    + +
    +
    (aref array dimension-1)
    +
    array - one-dimensional array
    +dimension-1 - element number in the first dimension
    +returns - the value of the array element
    +
    + +

    + +

    Here is a macro for accessing elements in multi-dimensional +arrays:

    + +

    + +
    +
    (aref* array dimension-1 [dimension-2 ...])
    +
    array - any-dimensional array
    +dimensionN - element number in the N-th dimension
    +returns - the value of the array element
    +
    + +

    + +
    +(defmacro aref* (array &rest index-list)
    +  (labels ((multi-aref (array-name index-list)
    +             (let ((index (first index-list)))
    +               (if (not (integerp index))
    +                   (error "not an integer" index)
    +                   (let ((rest (rest index-list))
    +                         (expansion-list (list 'aref)))
    +                     (push (if rest
    +                               (multi-aref array-name rest)
    +                               array-name)
    +                           expansion-list)
    +                     (push index expansion-list)
    +                     (reverse expansion-list))))))
    +    (multi-aref `,array (reverse `,index-list))))
    +
    + +

    The symbols inside the labels form +do not leak into the expansion, so 'aref*' also works with array names like +'array', 'array-name' 'index', 'index-list' or +'expansion-list'. Also the values of local or global variables +with these names are not changed.

    + +
    +(macroexpand-1 '(aref* a 1 2 3))  => (aref (aref (aref a 1) 2) 3)
    +
    + +

    Examples:

    + +
    +> (setq a (make-array* 2 3))
    +#(#(NIL NIL NIL) #(NIL NIL NIL)))
    +
    +> (setf (aref* a 0 1) "hello")
    +"hello"
    +
    +> a
    +#(#(NIL "hello" NIL) #(NIL NIL NIL))
    +
    +> (aref* a 0 1)
    +"hello"
    +
    + +

    'aref*' with only one 'dimension' argument behaves +like aref:

    + +
    +(aref* a 0)            => #(NIL "hello" NIL)
    +(aref  a 0)            => #(NIL "hello" NIL)
    +
    +(aref* (aref* a 0) 1)  => "hello"
    +(aref  (aref  a 0) 1)  => "hello"
    +
    +(aref* a 0 1)          => "hello"
    +(aref  a 0 1)          => error: too many arguments
    +
    + +

    'aref*' like aref also works +with setf to store +values in multi-dimensional arrays:

    + +
    +(setf (aref* (aref* a 0) 1) "1")  => "1" ; a => #(#(NIL "1" NIL) #(NIL NIL NIL)))
    +(setf (aref  (aref  a 0) 1) "2")  => "2" ; a => #(#(NIL "2" NIL) #(NIL NIL NIL)))
    +
    +(setf (aref* 0 1) "3")            => "3" ; a => #(#(NIL "3" NIL) #(NIL NIL NIL)))
    +(setf (aref  0 1) "4")            => error: too many arguments
    +
    + +

      Back to top

    + + + +
    + +

    vector*

    + +
    + +
    +(defun vector* (&rest items)
    +  (if (null items)
    +      (make-array 0)
    +      (let* ((end (length items))
    +             (result (make-array end)))
    +        (if (> end 1)
    +            (dotimes (index end)               ; more than one item
    +              (setf (aref result index)
    +                    (if (eq (nth index items) '*unbound*)
    +                        '*unbound*
    +                        (nth index items))))
    +            (if (eq (first items) '*unbound*)  ; one item only
    +                (setf (aref result 0) '*unbound*)
    +                (let ((item (first items)))
    +                  (case (type-of item)
    +                    (cons   (let ((end (length item)))
    +                              (setq result (make-array end))
    +                              (dotimes (index end)
    +                                (setf (aref result index)
    +                                      (if (eq (nth index item) '*unbound*)
    +                                          '*unbound*
    +                                          (nth index item))))))
    +                    (array  (let ((end (length item)))
    +                              (setq result (make-array end))
    +                              (dotimes (index end)
    +                                (setf (aref result index)
    +                                      (if (eq (aref item index) '*unbound*)
    +                                          '*unbound*
    +                                          (aref item index))))))
    +                    (string (let ((end (length item)))
    +                              (setq result (make-array end))
    +                              (dotimes (index end)
    +                                (setf (aref result index)
    +                                      (char item index)))))
    +                    (t      (setf (aref result 0) item))))))
    +        result)))
    +
    + +
    +(defun list* (&rest items)
    +  (if (null items)
    +      nil
    +      (let* ((end (length items))
    +             (result nil))
    +        (labels ((push-element (element)
    +                   (if (member (type-of element) '(array cons string))
    +                       (setq result (append (reverse (list* element)) result))
    +                       (push element result))))
    +          (dotimes (index end)
    +            (if (eq (nth index items) '*unbound*)
    +                (push '*unbound* result)
    +                (let ((item (nth index items)))
    +                  (case (type-of item)
    +                    (nil    (push item result))
    +                    (cons   (let ((end (length item)))
    +                              (when (not (consp (last item))) (incf end))
    +                              (dotimes (index end)
    +                                (if (eq (nth index item) '*unbound*)
    +                                    (push '*unbound* result)
    +                                    (push-element (nth index item))))))
    +                    (array  (let ((end (length item)))
    +                              (dotimes (index end)
    +                                (if (eq (aref item index) '*unbound*)
    +                                    (push '*unbound* result)
    +                                    (push-element (aref item index))))))
    +                    (string (let ((end (length item)))
    +                              (dotimes (index end)
    +                                (push (char item index) result))))
    +                    (t      (push item result))))))
    +          (reverse result)))))
    +
    + + +
    +(defun tree* (&rest items)
    +  (if (null items)
    +      nil
    +      (let* ((end (length items))
    +             (result nil))
    +        (labels ((push-element (element)
    +                   (if (member (type-of element) '(array cons string))
    +                       (push (reverse (list* element)) result)
    +                       (push element result))))
    +          (dotimes (index end)
    +            (if (eq (nth index items) '*unbound*)
    +                (push '*unbound* result)
    +                (let ((item (nth index items)))
    +                  (case (type-of item)
    +                    (nil    (push item result))
    +                    (cons   (let ((end (length item)))
    +                              (when (not (consp (last item))) (incf end))
    +                              (dotimes (index end)
    +                                (if (eq (nth index item) '*unbound*)
    +                                    (push '*unbound* result)
    +                                    (push-element (nth index item))))))
    +                    (array  (let ((end (length item)))
    +                              (dotimes (index end)
    +                                (if (eq (aref item index) '*unbound*)
    +                                    (push '*unbound* result)
    +                                    (push-element (aref item index))))))
    +                    (string (let ((end (length item)))
    +                              (dotimes (index end)
    +                                (push (char item index) result))))
    +                    (t      (push item result))))))
    +          (reverse result)))))
    +
    + + + + +

      Back to top

    + + + +
    + +

    array*

    + +
    + +
    +(defun array* (&rest items)
    +  (if (null items)
    +      (make-array 0)
    +      (let* ((end (length items))
    +             (result (make-array end)))
    +        (labels ((vector-element (element index)
    +                   (setf (aref result index)
    +                         (if (member (type-of element) '(cons string array))
    +                             (array* element)
    +                             element))))
    +          (dotimes (index end)
    +            (if (eq (nth index items) '*unbound*)
    +                (setf (aref result index) '*unbound*)
    +                (let ((item (nth index items)))
    +                  (case (type-of item)
    +                    (cons  (let ((end (length item)))
    +                             (dotimes (index end)
    +                               (if (eq (nth index item) '*unbound*)
    +                                   (strcat-element "*UNBOUND*")
    +                                   (strcat-element (nth index item))))))
    +                    (array (let ((end (length item)))
    +                             (dotimes (index end)
    +                               (if (eq (aref item index) '*unbound*)
    +                                   (strcat-element "*UNBOUND*")
    +                                   (strcat-element (aref item index))))))
    +                    (t     (strcat-element item))))))
    +          result))))
    +
    + + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/binary.htm b/docsrc/xlisp/xlisp-doc/examples/binary.htm new file mode 100644 index 0000000..3ae5d56 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/binary.htm @@ -0,0 +1,160 @@ + + +Binary Integer Numbers + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Binary Integer Numbers

    + +
    + +

    XLISP provides the #b +read-macro for binary numbers:

    + +
    +#b0    => 0       #b1000  => 8        #b100000  => 16
    +#b1    => 1       #b1001  => 9        #b100001  => 17
    +#b10   => 2       #b1010  => 10       #b100010  => 18
    +#b11   => 3       #b1011  => 11       #b100011  => 19
    +#b100  => 4       #b1100  => 12       #b100100  => 20
    +#b101  => 5       #b1101  => 13       #b100101  => 21
    +#b110  => 6       #b1110  => 14       #b100110  => 22
    +#b111  => 7       #b1111  => 15       #b100111  => 23
    +
    + +

    + +
    +
    (bin-string integer [all])
    +
    integer - an integer expression
    +all - a boolean expression
    +returns - the integer in binary form as string
    +
    + +

    + +
    +(defun bin-string (integer &optional all)
    +  (if (integerp integer)
    +      (let ((digits (or (dolist (bits '(16 32 64 128) nil)
    +                          (let ((fixnum (round (expt 2.0 (1- bits)))))
    +                            (and (plusp (1- fixnum))
    +                                 (minusp fixnum)
    +                                 (return bits))))
    +                        (error "integer limit not found")))
    +            (string ""))
    +        (dotimes (x digits)
    +          (let ((digit (logand (round (expt 2.0 x)) integer)))
    +            (setq string (strcat (if (zerop digit) "0" "1") string))))
    +        (format nil "~a" (if all string (string-left-trim "0" string))))
    +      (error "not an integer" integer)))
    +
    + +

    The 'bin-string' function converts the 'integer' argument +into binary form and returns is as a string. If the +optional 'all' argument is not given or +NIL, leading zeros are not included in +the string. If the optional 'all' argument is +non-NIL, all digits of the +internal representation of the 'integer' argument, including leading zeros, +are contained in the string. This is useful for debugging integer overflow +and bit-wise functions.

    + +

    + +
    +
    (bin integer [all])
    +
    integer - an integer expression
    +all - a boolean expression
    +prints - the integer in binary form
    +returns - the integer argument
    +
    + +

    + +
    +(defun bin (integer &optional all)
    +  (if (integerp integer)
    +      (format t "#b~a~%" (bin-string integer all))
    +      (format t ";; not an integer~%"))
    +  integer)
    +
    + +

    The 'bin' function prints the 'integer' argument in binary form on +the screen. Together with the +#b read-macro +this can be used for interactive binary computations.

    + +
    +> (bin 12345678)
    +#b101111000110000101001110
    +12345678
    +
    +> (bin 12345678 :all)
    +#b00000000101111000110000101001110
    +12345678
    +
    +> (bin 1.2345678)
    +;; not an integer
    +1.2345678
    +
    +> (bin (logand #b1011 #b1101))
    +#b1001
    +9
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/circular-lists.htm b/docsrc/xlisp/xlisp-doc/examples/circular-lists.htm new file mode 100644 index 0000000..48d7cdf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/circular-lists.htm @@ -0,0 +1,133 @@ + + +Circular Lists + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Circular Lists

    + +
    + + +
    + +

    Known XLISP Problems with Circular Lists

    + +
    + +

    Warning: do not try this with XLISP:

    + +
    +> (setq my-list (cons 'item nil))  ; create a 1-item list
    +(ITEM)
    +
    +> (setf (cdr my-list) my-list))    ; create the circle
    +ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM
    +ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM
    +ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM
    +ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ITEM ...
    +
    + +

    If you're lucky you can break the +loop. If not, then XLISP will print the ITEM forever.

    + +

      Back to top

    + + + +
    + +

    c-nth

    + +
    + +

    The 'c-nth' macro accesses a linear list as if it were +circular:

    + +
    +(defmacro c-nth (index list)
    +  `(nth ,(rem index (length list)) ,list))
    +
    + +

    Note that with every call to 'c-nth', the length of the list +will be computed again.

    + +

    Examples:

    + +
    +(c-nth 0 '(1 2 3))  => 1
    +(c-nth 1 '(1 2 3))  => 2
    +(c-nth 2 '(1 2 3))  => 3
    +(c-nth 3 '(1 2 3))  => 1
    +(c-nth 4 '(1 2 3))  => 2
    +(c-nth 5 '(1 2 3))  => 3
    +(c-nth 6 '(1 2 3))  => 1
    +(c-nth 7 '(1 2 3))  => 2
    +
    + +Because 'c-nth' is a macro expanding into a regular +nth form, 'c-nth' can be +used with setf: + +
    +(setq lst '(1 2 3))      => (1 2 3)
    +lst                      => (1 2 3)
    +(setf (c-nth 4 lst) 'x)  => X
    +lst                      => (1 X 3)
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp.htm new file mode 100644 index 0000000..add5cc7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp.htm @@ -0,0 +1,161 @@ + + +Common Lisp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Where is the Nyquist Common Lisp Library?

    + +
    + +

    Short answer - nowhere.

    + +

    Rationale:

    + +
      + +
    1. XLISP is a very simple Lisp. Many of the XLISP functions are just simple +wrappers around the underlying C functions. This makes XLISP, +as an interpreted language, run with reasonable speed. The main +advantage of XLISP over Common Lisp is that XLISP is much +smaller and therefore much easier to learn.

    2. + +
    3. The main trick of Nyquist is to use XLISP only in the initial setup +phase, where the Lisp code is parsed, to set-up the +low-level sound sample functions, written in C, +not in Lisp.

      + +

      The Nyquist low-level 'snd-...' +functions only look like Lisp functions, but they are direct wrappers around +C functions and behave like that. They do not provide type +contagion, instead they expect a correct number of arguments, given in +correct order with correct data types, and if not given exactly as expected, +chances are good that Nyquist will crash.

      + +

      In Nyquist, XLISP [slow] is used to make sure +that the low-level functions will be given the correct +arguments, while the low-level sound sample functions after the +initial setup phase will run in high-speed C, and not in Lisp +anymore.

    4. + +
    + +

    Because the Nyquist Common Lisp functions are running in +interpreted XLISP, they run slower than the built-in XLISP +functions. Because many Common Lisp functions do extensive +parsing and/or type checking on their arguments, they run many times +slower than XLISP. That's why overloading Nyquist with an extensive +Common Lisp layer makes not much sense.

    + +

      Back to top

    + + + +
    + +

    But why did you write so many Common Lisp functions?

    + +
    + +

    I usually work with Common Lisp for prototyping, so if I'm +porting code from Common Lisp to Nyquist:

    + +
      + +
    1. I first copy the Common Lisp code together with the +respective Nyquist Common Lisp functions from screen into a +Nyquist lisp file to see if the Common Lisp code works with +Nyquist at all. Many of the Nyquist Common Lisp +functions have argument tests to help with error tracking.

    2. + +
    3. When the Common Lisp code works with Nyquist I start to +strip out everything I don't need for the particular problem at hand, making +the Nyquist code run faster. Because this second step is highly depending on +the particular problem at hand, there probably never will be a general +solution for this.

    4. + +
    + +

    + +

    I have tried to keep the functions as self-contained as +possible, any dependencies to non-Nyquist functions are noted +directly below the code.

    + +

    + +

    There are many XLISP functions that behave exactly like their +Common Lisp counterparts, so I haven't written extra functions +for them.

    + +
      + +
    • If you already know Common Lisp then the Nyquist +Common Lisp functions may help to understand how XLISP +works.

    • + +
    • If you still don't know Common Lisp and maybe one day +you decide to learn more about it, then the Nyquist +Common Lisp functions may save you from learning everything +double.

    • + +
    + +

    In either case you can use the Nyquist Common Lisp functions +as a grab-bag for your own functions.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/ceiling.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/ceiling.htm new file mode 100644 index 0000000..a39f495 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/ceiling.htm @@ -0,0 +1,137 @@ + + +cl:ceiling + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:ceiling

    + +
    + +

    The cl:ceiling function +truncates an integer or +floating-point number toward positive infinity:

    + +

    + +
    +
    (cl:ceiling number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of truncating the result of number divided by divisor
     - the remainder of the truncate operation
    +
    + +

    + +
    +(defun cl:ceiling (number &optional (divisor
    +                                    (if (integerp number) 1 1.0)
    +                                    divisor-p))
    +  (let ((quotient
    +          (cond ((and (not divisor-p) (integerp number)) number)
    +                ((= number divisor) 1)
    +                (t (let ((i-quotient (/ (truncate number) (truncate divisor)))
    +                         (f-quotient (/ (float number) divisor)))
    +                     (if (or (= i-quotient f-quotient)  ; integer result
    +                             (not (plusp f-quotient)))
    +                          (truncate f-quotient)
    +                          (1+ (truncate f-quotient))))))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The cl:ceiling function computes a quotient that has +been truncated toward positive infinity. That is, the quotient +represents the smallest mathematical integer that is not smaller than the +mathematical result.

    + +

    The quotient is directly returned by the function, while a list:

    + +
    +(quotient remainder)
    +
    + +

    is stored in the Nyquist/XLISP +*rslt* variable and the +cl:*multiple-values* is set to + T  to signal that +Multiple Values are returned.

    + +See +Rounding and Truncation +for more details.

    + +

    Examples:

    + +
    +(cl:ceiling  3.5)  =>  4  ; *rslt* => ( 4 -0.5)
    +(cl:ceiling -3.5)  => -3  ; *rslt* => (-3 -0.5)
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/debug-mv.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/debug-mv.htm new file mode 100644 index 0000000..c61cb23 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/debug-mv.htm @@ -0,0 +1,110 @@ + + +cl:debug:mv + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:debug:mv

    + +
    + +

    The cl:debug:mv function can be used to debug +multiple value expressions:

    + +

    + +
    +
    (cl:debug:mv expr
    +
    expr - a Lisp expression, returning an arbitrary number of values
    +returns - the normal Lisp return value from evaluating expr
    +
    + +

    + +
    +(defun cl:debug:mv (expr)
    +  (setq cl:*multiple-values* nil)
    +  (let ((result (eval expr)))
    +    (format t ";; cl:*multiple-values* => ~a~%" cl:*multiple-values*)
    +    (format t ";; *rslt* => ~a~a~%" *rslt*
    +              (if cl:*multiple-values* "" " [invalid]"))
    +    result))
    +
    + +

    The cl:debug:mv function first sets the +cl:*multiple-values* +variable to NIL, then it +evaluates the expression. After evaluation it prints the values of the +cl:*multiple-values* +and *rslt* variables and +returns the normal Lisp return value from the evaluation.

    + +

    Example:

    + +
    +> (cl:debug:mv '(cl:values 1 2 3))
    +;; cl:*multiple-values* => T
    +;; *rslt* => (1 2 3)
    +1
    +
    +> (cl:debug:mv 1)
    +;; cl:*multiple-values* => NIL
    +;; *rslt* => (1 2 3) [invalid]
    +1
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/equalp.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/equalp.htm new file mode 100644 index 0000000..14835c5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/equalp.htm @@ -0,0 +1,162 @@ + + +cl:equalp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:equalp

    + +
    + +

    + +
    +
    (equalp expr1 expr2)
    +
    exprN - arbitrary Lisp expressions
    +returns -  T  if the expressions +are structurally equal, NIL otherwise
    +
    + +

    + +

    Two expressions are 'equalp':

    + +
      + +
    • If the expressions +are equal.

    • + +
    • If two numbers of arbitrary type are + = .

    • + +
    • If two characters are +char-equal.

    • + +
    • If two strings are string-equal.

    • + +
    • If the two cars in conses are +'equalp' and the two cdrs in conses +are 'equalp'.

    • + +
    • If two arrays have the same number of elements and dimensions, and +the corresponding elements in all dimensions are 'equalp'.

    • + +
    + +

    Note that only 'equalp' can compare arrays.

    + +
    +(defun cl:equalp (expr-1 expr-2)
    +  (or (equal expr-1 expr-2)
    +      (and (numberp expr-1) (numberp expr-2) (= expr-1 expr-2))
    +      (let ((type (type-of expr-1)))
    +        (when (eq type (type-of expr-2))
    +          (case type
    +            (character (char-equal expr-1 expr-2))
    +            (string    (string-equal expr-1 expr-2))
    +            (cons      (do ((x (first expr-1)
    +                               (if (consp expr-1) (first expr-1) expr-1))
    +                            (y (first expr-2)
    +                               (if (consp expr-2) (first expr-2) expr-2)))
    +                           ((or (null expr-1)
    +                                (null expr-2)
    +                                (not (equalp x y)))
    +                            (and (null expr-1)
    +                                 (null expr-2)))
    +                         (setq expr-1 (and (consp expr-1) (rest expr-1))
    +                               expr-2 (and (consp expr-2) (rest expr-2)))))
    +            (array     (let ((end (length expr-1)))
    +                         (when (eql end (length expr-2))
    +                           (dotimes (index end t)
    +                             (and (not (equalp (aref expr-1 index)
    +                                               (aref expr-2 index)))
    +                                  (return nil)))))))))))
    +
    + +

    cons: do is used instead of +recursion because XLISP has only two kilobytes stack size. The +(consp expr) tests are +necessary because in a dotted list the last +rest element is not a cons.

    + +

    Examples:

    + +
    +(cl:equalp 1 1.0)                            => T
    +(cl:equalp #\a #\A)                          => T
    +(cl:equalp "Abc" "aBc")                      => T
    +(cl:equalp '(1 #\a "Abc") '(1.0 #\A "aBc"))  => T
    +(cl:equalp #(1 #\a "Abc") #(1.0 #\A "aBc"))  => T
    +
    + +

    Nested expressions only match if the nesting matches:

    + +
    +(cl:equalp '(1 (2 3)) '(1.0 (2.0 3.0))  => T
    +(cl:equalp '(1 (2 3)) '((1.0 2.0) 3.0)  => NIL
    +(cl:equalp '((1 2) 3) '((1.0 2.0) 3.0)  => T
    +(cl:equalp '((1 2) 3) '(1.0 (2.0 3.0))  => NIL
    +
    + +

    A character does not match a string with the same character:

    + +
    +(cl:equalp #\a "a")  => NIL
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/exp.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/exp.htm new file mode 100644 index 0000000..707e28e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/exp.htm @@ -0,0 +1,92 @@ + + +cl:exp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:exp

    + +
    + +

    The cl:exp function does the same as the +Nyquist/XLISP exp function, but +also accepts integer numbers as argument:

    + +

    + +
    +
    (cl:exp power)
    +
    power - an integer or floating-point number
    +returns - the result of 'e' [2.7128] to the power of power
    +
    + +

    + +
    +(defun cl:exp (x)
    +  (exp (float x)))
    +
    + +

    See defun, +exp, +float.

    + +

    The cl:exp function computes 'e' +[2.7128] raised to the specified 'power' and returns the result as a +floating-point number.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/expt.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/expt.htm new file mode 100644 index 0000000..05e95ea --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/expt.htm @@ -0,0 +1,105 @@ + + +cl:expt + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:expt

    + +
    + +

    The cl:expt function computes the result of 'x' to +the power of 'y':

    + +

    + +
    +
    (cl:expt base power)
    +
    base - the base
    +power - the exponent
    +returns - the result of base to the power of power
    +
    + +

    + +
    +(defun cl:expt (x y)
    +  (let ((power (expt (float x) y)))
    +    (if (and (integerp x) (integerp y))
    +        (round power)
    +        power)))
    +
    + +

    See and, +defun, +expt, +float, + if , +integerp, +let, +power, +round.

    + +

    The cl:expt function accepts integer and floating +point numbers as arguments. If both arguments are integer +numbers, the result will be an integer number, if one or both +arguments are floating-point numbers, the result will be a +floating-point number. In contrast to the +Nyquist/XLISP expt function, the +'cl:expt' function accepts exactly two arguments.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/floor.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/floor.htm new file mode 100644 index 0000000..79e046c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/floor.htm @@ -0,0 +1,150 @@ + + +cl:floor + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:floor

    + +
    + +

    The cl:floor function +truncates an integer or +floating-point number toward negative infinity:

    + +

    + +
    +
    (cl:floor number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of truncating the result of number divided by divisor
     - the remainder of the truncate operation
    +
    + +

    + +
    +(defun cl:floor (number &optional (divisor
    +                                  (if (integerp number) 1 1.0)
    +                                  divisor-p))
    +  (let ((quotient
    +          (cond ((and (not divisor-p) (integerp number)) number)
    +                ((= number divisor) 1)
    +                (t (let ((i-quotient (/ (truncate number) (truncate divisor)))
    +                         (f-quotient (/ (float number) divisor)))
    +                     (if (or (= i-quotient f-quotient)  ; integer result
    +                             (not (minusp f-quotient)))
    +                          (truncate f-quotient)
    +                          (1- (truncate f-quotient))))))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The cl:floor function computes a quotient that has +been truncated toward negative infinity. That is, the quotient +represents the largest mathematical integer that is not larger than the +mathematical quotient.

    + +

    The quotient is directly returned by the function, while a list:

    + +
    +(quotient remainder)
    +
    + +

    is stored in the Nyquist/XLISP +*rslt* variable and the +cl:*multiple-values* is set to + T  to signal that +Multiple Values are returned.

    + +See +Rounding and Truncation +for more details.

    + +

    Examples:

    + +
    +(cl:floor  3.5)  =>  3  ; *rslt* => ( 3 0.5)
    +(cl:floor -3.5)  => -4  ; *rslt* => (-4 0.5)
    +
    + +

    See also:

    + + + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/global-multiple-values.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/global-multiple-values.htm new file mode 100644 index 0000000..5ca1757 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/global-multiple-values.htm @@ -0,0 +1,142 @@ + + +cl:*multiple-values* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:*multiple-values*

    + +
    + +

    The cl:*multiple-values* variable is used to signal +if a function has returned multiple values:

    + +

    + +
    +
    cl:*multiple-values*
    +
    returns -  T  if a +function returned multiple values
    +
    + +

    + +

    Test if a function has returned multiple values:

    + +
    +(setf cl:*multiple-values* nil)
    +(let ((result (function ...)))
    +  (if cl:*multiple-values*
    +      (do-something-with *rslt* ...)
    +      (do-something-with result ...))
    +  ... )
    +
    + +

    Do not use cl:*multiple-values* with +let like this:

    + +
    +(let ((cl:*multiple-values* nil)
    +      (result (function ...)))
    +  (if cl:*multiple-values*
    +      (do-something-with *rslt* ...)
    +      (do-something-with result ...))
    +  ... )
    +
    + +

    This doesn't work because 'function' is evaluated in the global XLISP +environment, where the lexical let +binding of the cl:*multiple-values* variable does not +exist, while the  if  form +inside the let form cannot see a +global change of the cl:*multiple-values* variable, +because the global value is shadowed by the lexical +let binding. +See Environment for more +details about variables.

    + +

    The XLISP progv special form can +be used to encapsulate a multiple value call while automatically restoring +the old values at the end like this:

    + +
    +(values 1 2 3)        => 1
    +
    +cl:*multiple-values*  => T
    +*rslt*                => (1 2 3)
    +
    +(progv '(cl:*multiple-values* *rslt*) '(nil nil)
    +  (let ((result (function ...)))
    +    (if cl:*multiple-values*
    +        (do-something-with *rslt* ...)
    +        (do-something-with result ...))))
    +
    +cl:*multiple-values*  => T
    +*rslt*                => (1 2 3)
    +
    + +

    + +

    Note: All functions returning multiple values set +cl:*multiple-values* to + T , but it's up to the +Lisp programmer to reset the variable +to NIL.

    + +

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/log.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/log.htm new file mode 100644 index 0000000..c7e5c5f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/log.htm @@ -0,0 +1,95 @@ + + +cl:log + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:log

    + +
    + +

    The cl:log function does the same as the +Nyquist/XLISP log function, but also +accepts integer numbers and has an optional 'base' argument:

    + +

    + +
    +
    (cl:log number [base])
    +
    number - an integer or floating-point number
    +base - an integer or floating-point number
    +returns - the the logarithm of number in base base
    +
    + +

    + +
    +(defun cl:log (number &optional base)
    +  (if base
    +      (if (zerop base)
    +          0.0
    +          (/ (log (float number)) (log (float base))))
    +      (log (float number))))
    +
    + +

    The 'cl:log' function returns the logarithm of 'number' in +base 'base'. If 'base' is not supplied its value is +'e', the base of the natural logarithms. If the 'base' +argument is zero, then 'cl:log' returns zero. The result is +always a floating-point number.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/mod.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/mod.htm new file mode 100644 index 0000000..9454d4e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/mod.htm @@ -0,0 +1,97 @@ + + +cl:mod + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:mod

    + +
    + +

    + +
    +
    (cl:mod number divisor)
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number
    +returns - the remainder of a cl:floor operation
    +
    + +

    + +
    +(defun cl:mod (number divisor)
    +  (if (= (abs number) (abs divisor))
    +      (if (and (integerp number) (integerp divisor)) 0 0.0)
    +      (let* ((i-quotient (/ (truncate number) (truncate divisor)))
    +             (f-quotient (/ (float number) divisor))
    +             (quotient (if (or (= i-quotient f-quotient)  ; integer result
    +                               (not (minusp f-quotient)))
    +                           (truncate f-quotient)
    +                           (1- (truncate f-quotient)))))
    +        (- number (* quotient divisor)))))
    +
    + +

    The cl:mod function performs the +cl:floor operation on its arguments and returns the +remainder of the cl:floor operation. The +result is either zero or an integer or floating-point +number with the same sign as the 'divisor' argument. If both +arguments are integer numbers, the cl:mod function is +equal to the mathematical modulus function.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-bind.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-bind.htm new file mode 100644 index 0000000..32fdadf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-bind.htm @@ -0,0 +1,193 @@ + + +cl:multiple-value-bind + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:multiple-value-bind

    + +
    + +

    The cl:multiple-value-bind macro creates new bindings +for a list of symbols and evaluates expressions that use these bindings:

    + +

    + +
    +
    (cl:multiple-value-bind symbols values [expr1 ...])
    +
    symbols - a list of symbols
    +values - a Lisp expression returning one or more values
    +exprN - arbitrary Lisp expressions
    +returns - the value[s] returned by the last expression
    +
    + +

    + +
    +(defmacro cl:multiple-value-bind (symbols expr &rest body)
    +  (and (or (not (consp symbols))
    +           (eq 'quote (first symbols))
    +           (dolist (symbol symbols)
    +             (or (symbolp symbol) (return t))))
    +       (error "not a list of symbols" symbols))
    +  (setq cl:*multiple-values* nil)
    +  (let* ((result (eval expr))
    +         (values (if cl:*multiple-values*
    +                     *rslt*
    +                     (list result)))
    +         (number-of-symbols (length symbols))
    +         (number-of-values  (length values))
    +         (bindings nil))
    +    (dotimes (index number-of-symbols)
    +      (push (if (< index number-of-values)
    +                (list (nth index symbols)
    +                      (list 'quote (nth index values)))
    +                (nth index symbols))
    +            bindings))
    +    (setq bindings (reverse bindings))
    +    `(let ,bindings ,@body)))
    +
    + +

    The 'values' expression is evaluated, and each of the symbols is bound to +the respective value returned by the evaluation. If there are +more symbols than values returned, extra values of +NIL are bound to the remaining +symbols. If there are more values than symbols, the extra +values are ignored. The symbols are bound to the values by +let, behaving like an +implicit progn.

    + +

    Before evaluating 'expr1', the +cl:*multiple-values* +variable is  T  +if evaluating the 'values' expression returned multiple values and +NIL with a normal return value.

    + +

    The cl:multiple-value-bind macro binds multiple +values to local let variables::

    + +
    +> (macroexpand-1 '(cl:multiple-value-bind (a b c)
    +                      (cl:values 1 2 3)
    +                    (list a b c)))
    +(LET ((A (QUOTE 1))
    +      (B (QUOTE 2))
    +      (C (QUOTE 3)))
    +  (LIST A B C))
    +
    + +

    The quotes are necessary to +prevent 'unbound variable' and 'unbound function' errors with symbols and +lists.

    + +

    Examples:

    + +

    1. The cl:multiple-value-bind macro binds +values returned by the cl:values function:

    + +
    +(defun multiple-value-function ()
    +  (cl:values 1 2 3))  ; multiple return values
    +
    +> (cl:multiple-value-bind (a b c)
    +      (multiple-value-function)
    +    (list a b c))
    +(1 2 3)
    +
    + +

    2. If there are no values returned in the Nyquist +*rslt* variable, the normal +function return value is bound to the first symbol and all remaining symbols +are bound to NIL:

    + +
    +(defun normal-lisp-function ()
    +  (+ 1 1))  ; normal return value
    +
    +> (cl:multiple-value-bind (a b c)
    +      (normal-lisp-function)
    +    (list a b c))
    +(2 NIL NIL)
    +
    + +

    3. If there are less values than symbols, the extra symbols are +bound to NIL:

    + +
    +(defun not-enough-values-function ()
    +  (cl:values 1 2))  ; multiple return values
    +
    +> (cl:multiple-value-bind (a b c)
    +      (not-enough-values-function)
    +    (list a b c))
    +(1 2 NIL)
    +
    + +

    4. If there are more values than symbols, the extra values are +ignored:

    + +
    +(defun too-many-values-function ()
    +  (cl:values 1 2 3 4 5))  ; multiple return values
    +
    +> (cl:multiple-value-bind (a b c)
    +      (too-many-values-function)
    +    (list a b c))
    +(1 2 3)
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-call.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-call.htm new file mode 100644 index 0000000..dba7c45 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-call.htm @@ -0,0 +1,119 @@ + + +cl:multiple-value-call + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:multiple-value-call

    + +
    + +

    The cl:multiple-value-call macro applies a function +to a list of return values:

    + +

    + +
    +
    (cl:multiple-value-call function [expr1 ...])
    +
    function - a Lisp expression evaluating to a function call
    +exprN - arbitrary Lisp expressions
    +returns - the values returned by the function
    +
    + +

    + +
    +(defmacro cl:multiple-value-call (function &rest exprs)
    +  (let (args)
    +    (dolist (expr exprs)
    +      (setq  cl:*multiple-values* nil)
    +      (let* ((result (eval expr)))
    +        (if cl:*multiple-values*
    +            (dolist (rslt *rslt*) (push rslt args))
    +            (push result args))))
    +    (setq args (reverse args))
    +    `(progn
    +       (setq cl:*multiple-values* nil)
    +       (apply ,function ',args)))
    +
    + +

    The cl:multiple-value-call macro first evaluates the +expressions and collects all return values in a single list, then the +'function' form is evaluated and the resulting function call is applied to +the list of values.

    + +

    Before applying the function to the list of values the +cl:*multiple-values* +variable is set to NIL, the final value of +cl:*multiple-values* +depends on the 'function' argument.

    + +

    Examples:

    + +
    +> (funcall #'+
    +    (cl:values 1 2)
    +    (cl:values 3 4))
    +4  ; (apply #'+ (1 3))
    +
    +> (cl:multiple-value-call #'+
    +    (cl:values 1 2)
    +    (cl:values 3 4))
    +10  ; (apply #'+ (1 2 3 4))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-list.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-list.htm new file mode 100644 index 0000000..6e3a374 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-list.htm @@ -0,0 +1,112 @@ + + +cl:multiple-value-list + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:multiple-value-list

    + +
    + +

    The cl:multiple-value-list macro evaluates a Lisp +expression and returns all values in a list:

    + +

    + +
    +
    (cl:multiple-value-list expr)
    +
    expr - an arbitrary Lisp expression
    +returns - all values in a list
    +
    + +

    + +
    +(defmacro cl:multiple-value-list (expr)
    +  (setq cl:*multiple-values* nil)
    +  (let ((result (eval expr)))
    +    (if cl:*multiple-values*
    +        '*rslt*
    +        `(list ,result))))
    +
    + +

    The cl:multiple-value-list macro first evaluates the +expression. If the evaluation returned multiple values, the +value of the *rslt* variable +is returned, otherwise the normal Lisp return value is returned in a list of +one element.

    + +

    The +cl:*multiple-values* +variable is  T  +if evaluating the expression returns multiple values and +NIL with a normal return value.

    + +

    Examples:

    + +
    +(cl:multiple-value-list 1)  => (1)      ; cl:*multiple-values* => NIL
    +                                        ; *rslt* => [invalid]
    +(cl:multiple-value-list
    +  (+ 1 1))                  => (2)      ; cl:*multiple-values* => NIL
    +                                        ; *rslt* => [invalid]
    +(cl:multiple-value-list
    +  (cl:values 1 2 3))        => (1 2 3)  ; cl:*multiple-values* => T
    +                                        ; *rslt* => (1 2 3)
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-prog1.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-prog1.htm new file mode 100644 index 0000000..d5f5fc6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-prog1.htm @@ -0,0 +1,106 @@ + + +cl:multiple-value-prog1 + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:multiple-value-prog1

    + +
    + +

    The cl:multiple-value-prog1 macro is like +prog1, but it can handle multiple +values:

    + +

    + +
    +
    (cl:multiple-value-prog1 expr1 [expr2 ...])
    +
    exprN - arbitrary Lisp expressions
    +returns - the values returned by the first expression
    +
    + +

    + +
    +(defmacro cl:multiple-value-prog1 (expr &rest body)
    +  (setq cl:*multiple-values* nil)
    +  (let* ((result (eval expr)))
    +    (if cl:*multiple-values*
    +        `(progn ,@body
    +                (setq *rslt* ',*rslt*
    +                      cl:*multiple-values* t)
    +                ',result)
    +        `(progn ,@body ',result))))
    +
    + +

    The cl:multiple-value-prog1 macro evaluates the first +expression and saves all the values returned by the evaluation. It +then evaluates each of the following expressions from left to right, +discarding their values. After the evaluation is finished, the +cl:*multiple-values* +and *rslt* variables are +restored and the primary value from evaluating the fist expression is +returned.

    + +

    The +cl:*multiple-values* +variable is  T  +if evaluating the first expression returns multiple values and +NIL with a normal return value.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-setq.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-setq.htm new file mode 100644 index 0000000..3a8b701 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-value-setq.htm @@ -0,0 +1,239 @@ + + +cl:multiple-value-setq + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:multiple-value-setq

    + +
    + +

    The cl:multiple-value-setq macro assigns multiple +values to multiple variables:

    + +

    + +
    +
    (cl:multiple-value-setq symbols expr)
    +
    symbols - a list of symbols
    +expr - a Lisp expression returning one or more values
    +returns - the primary value returned by evaluating the expression
    +
    + +

    + +
    +(defmacro cl:multiple-value-setq (symbols expr)
    +  (and (or (not (consp symbols))
    +           (eq 'quote (first symbols))
    +           (dolist (symbol symbols)
    +             (or (symbolp symbol) (return t))))
    +       (error "not a list of symbols" symbols))
    +  (setq cl:*multiple-values* nil)
    +  (let* ((result (eval expr))
    +         (values (if cl:*multiple-values*
    +                     *rslt*
    +                     (list result)))
    +         (number-of-symbols (length symbols))
    +         (number-of-values  (length values))
    +         (assignments (list 'setq)))
    +    (dotimes (index number-of-symbols)
    +      (push (nth index symbols) assignments)
    +      (push (when (< index number-of-values)
    +              (list 'quote (nth index values)))
    +            assignments))
    +    (setq assignments (reverse assignments))
    +    `(progn ,assignments ',result)))
    +
    + +

    The expression is evaluated, and each symbol is assigned to the +corresponding value returned by the evaluation. If there are +more symbols than values returned, +NIL is assigned to the extra symbols. +If there are more values than symbols, the extra values are +discarded.

    + +

    The +cl:*multiple-values* +variable is  T  +if evaluating the expression returns multiple values and +NIL with a normal return value.

    + +

    The cl:multiple-value-setq macro assigns multiple +values to multiple variables +using setq:

    + +
    +> (macroexpand-1 '(cl:multiple-value-setq (a b c)
    +                    (cl:values 1 2 3)))
    +(PROGN (SETQ A (QUOTE 1)
    +             B (QUOTE 2)
    +             C (QUOTE 3))
    +       (QUOTE 1))
    +
    + +

    The quotes are necessary to +prevent 'unbound variable' and 'unbound function' errors with symbols and +lists.

    + +

    Examples:

    + +

    1. The cl:multiple-value-setq macro assigns +values returned by the cl:values function:

    + +
    +(defun multiple-value-function ()
    +  (cl:values 1 2 3))  ; multiple return values
    +
    +> (let ((a 'A) (b 'B) (c 'C))
    +    (cl:multiple-value-setq (a b c)
    +      (multiple-value-function))
    +    (list a b c))
    +(1 2 3)
    +
    + +

    2. If there are no values returned in the Nyquist +*rslt* variable, the normal +function return value is assigned to the first symbol and all remaining +symbols are assigned +to NIL:

    + +
    +(defun normal-lisp-function ()
    +  (+ 1 1))  ; normal return value
    +
    +> (let ((a 'A) (b 'B) (c 'C))
    +    (cl:multiple-value-setq (a b c)
    +      (normal-lisp-function))
    +    (list a b c))
    +(2 NIL NIL)
    +
    + +

    3. If there are less values than symbols, the extra symbols are +assigned to NIL:

    + +
    +(defun not-enough-values-function ()
    +  (cl:values 1 2))  ; multiple return values
    +
    +> (let ((a 'A) (b 'B) (c 'C))
    +    (cl:multiple-value-setq (a b c)
    +      (not-enough-values-function))
    +    (list a b c))
    +(1 2 NIL)
    +
    + +

    4. If there are more values than symbols, the extra values are +ignored:

    + +
    +(defun too-many-values-function ()
    +  (cl:values 1 2 3 4 5))  ; multiple return values
    +
    +> (let ((a 'A) (b 'B) (c 'C))
    +    (cl:multiple-value-setq (a b c)
    +      (too-many-values-function))
    +    (list a b c))
    +(1 2 3)
    +
    + +

    5. Symbols not contained in the +cl:multiple-value-setq symbol-list are not +changed:

    + +
    +(defun multiple-value-function ()
    +  (cl:values 1 2 3))  ; multiple return values
    +
    +> (let ((a 'A) (b 'B) (c 'C) (d 'D) (e 'E))
    +    (cl:multiple-value-setq (a b c)
    +      (multiple-value-function))
    +    (list a b c d e))
    +(1 2 3 D E)
    +
    + +

    5. If no bindings exist, new variables will be created:

    + +
    +(defun multiple-value-function ()
    +  (cl:values 1 2 3))  ; multiple return values
    +
    +> (let ((c 'C) (d 'D) (e 'E))
    +    (cl:multiple-value-setq (a b c)
    +      (multiple-value-function))
    +    (list a b c d e))
    +(1 2 3 D E)
    +
    + +

    Caution: In the last example, two global variables 'a' and 'b' +were created, while the lexical let +variable 'c' was assigned to the value 3:

    + +
    +> (list a b)
    +(1 2)
    +
    +> (list a b c)
    +error: unbound variable - C
    +
    + +

    The lexical let binding of 'c' does +not exist in the global top-level. +See Environment for more +details about variables.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-values.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-values.htm new file mode 100644 index 0000000..d05df73 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/multiple-values.htm @@ -0,0 +1,181 @@ + + +Multiple Values + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Multiple Values

    + +
    + +
      +
    1. Multiple Values
    2. + +
    + + + +
    + +

    Multiple Values

    + +
    + +

    This is a port of the Common List framework for passing multiple values +from one place to another. It is most often used to return +multiple values from a function with +cl:values or to bind multiple values to multiple +variables with +cl:multiple-value-bind or +cl:multiple-value-setq.

    + +

    The multiple value functions and macros use the +Nyquist/XLISP +*rslt* variable to store the +values as a list, while the +cl:*multiple-values* +variable is used as a flag to indicate if a function has returned multiple +values.

    + +

    What happens if a normal Lisp function are given multiple +values?

    + +

    A normal Lisp function only sees the 'primary' return value, as returned +by every Lisp function. The additional return values +[including the primary return value] are stored in the +*rslt* variable and are only read +by the multiple value functions. This also means that with multiple values, +the most important value should always be returned as the first value, +because only the first value can be seen by a normal Lisp function. +See cl:values for examples.

    + +

    What happens if a function expecting multiple values is given a normal +Lisp return value?

    + +

    The first symbol will be set to the function's return value, while all +other symbol will be set to NIL. +No symbol will be left unset. All functions +expecting multiple values are protected against a wrong number of values. +If there are more symbols than values, then the extra symbols +are set to NIL, if there are more +values than symbols, the extra values will be ignored.

    + +

    + +

    Known Limitations

    + +

    1. In Nyquist/XLISP, cl:values cannot be +used as argument to setf. But +this is not a real problem, because the values are stored as a +simple list in the *rslt* +variable, where they can be manipulated with any arbitrary Lisp +functions, not only with +setf.

    + +

    2. In Common Lisp there exists the option to return +'no value' by calling the 'values' function with no arguments. +In Nyquist/XLISP there is no built-in way to +return 'no value' from a function. The symbol +*unbound* cannot be used for +this because in Common Lisp, if 'no value' is +assigned to a symbol as variable value, the new value will be +NIL and not +*unbound*.

    + +

    In Nyquist/XLISP, the cl:values function, if +called with no arguments, always returns +NIL, and the +*rslt* variable will be +set to NIL, too:

    + +
    +(cl:values)      => NIL  ; *rslt* = NIL
    +(cl:values nil)  => NIL  ; *rslt* = (NIL)
    +
    + +

    Maybe this observation helps to write a 'no values' test if +anybody really needs it.

    + +

    3. Neither in Common Lisp nor in Nyquist/XLISP is it +possibe to return nested multiple values:

    + +
    +(cl:values (1 (cl:values 2 3) 4)  => 1  ; *rslt* = (1 2 4)
    +
    + +

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/numbers.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/numbers.htm new file mode 100644 index 0000000..d1b684c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/numbers.htm @@ -0,0 +1,104 @@ + + +Numbers + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Numbers

    + +
    + +
      +
    1. Number Types
    2. +
    3. Integer Limits
    4. +
    + + + +
    + +

    Number Types

    + +
    + +

    In Nyquist/XLISP only two types of numers exist:

    + +
      +
    • fixnum - integer numbers
    • +
    • flonum - floating-point numbers
    • +
    + +

    In Nyquist/XLISP, there are no ratios or complex numbers. Even if the +math functions in this section are modelled after Common Lisp, +no attempt is made to emulate these numbers.

    + + + +
    + +

    Integer Limits

    + +
    + +
    +(setq *most-positive-fixnum*  2147483647)
    +(setq *most-negative-fixnum* -2147483648)
    +
    + +

    Note: these are the limits for 32-bit machines.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/rem.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/rem.htm new file mode 100644 index 0000000..aba20c5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/rem.htm @@ -0,0 +1,93 @@ + + +cl:rem + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:rem

    + +
    + +

    + +
    +
    (cl:rem number divisor)
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number
    +returns - the remainder of a cl:truncate operation
    +
    + +

    + +
    +(defun cl:rem (number divisor)
    +  (if (= (abs number) (abs divisor))
    +      (if (and (integerp number) (integerp divisor)) 0 0.0)
    +      (let ((quotient (truncate (/ (float number) divisor))))
    +        (- number (* quotient divisor)))))
    +
    + +

    The cl:rem function performs the +cl:truncate operation on its arguments and +returns the remainder of the cl:truncate +operation. The result is either zero or an integer or +floating-point number with the same sign as the 'number' +argument. If both arguments are integer numbers, the +cl:rem function is equal to the mathematical remainder +function.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/remainder-and-modulus.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/remainder-and-modulus.htm new file mode 100644 index 0000000..b7e89c4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/remainder-and-modulus.htm @@ -0,0 +1,93 @@ + + +Remainder and Modulus + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Remainder and Modulus

    + +
    + +

    The cl:mod and cl:rem +function are generalizations of the modulus and remainder functions.

    + +
      + +
    • The cl:mod function performs the +cl:floor operation on its arguments and returns the +remainder of the cl:floor operation.

    • + +
    • The cl:rem function performs the +cl:truncate operation on its arguments and returns +the remainder of the cl:truncate operation.

    • + +
    + +

    The cl:mod and +cl:rem functions are the modulus and remainder +functions when the 'number' and 'divisor' arguments both are integers.

    + +
    +(mod  13    4)  =>  1          (rem  13    4)  =>  1 
    +(mod -13    4)  =>  3          (rem -13    4)  => -1 
    +(mod  13   -4)  => -3          (rem  13   -4)  =>  1 
    +(mod -13   -4)  => -1          (rem -13   -4)  => -1 
    +(mod  13.4  1)  =>  0.4        (rem  13.4  1)  =>  0.4 
    +(mod -13.4  1)  =>  0.6        (rem -13.4  1)  => -0.4
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/round.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/round.htm new file mode 100644 index 0000000..cf0be2c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/round.htm @@ -0,0 +1,141 @@ + + +cl:round + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:round

    + +
    + +

    The cl:round function +truncates an integer or +floating-point number toward the next integer:

    + +

    + +
    +
    (cl:round number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of runding the result of number divided by divisor
     - the remainder of the round operation
    +
    + +

    + +
    +(defun cl:round (number &optional (divisor
    +                                  (if (integerp number) 1 1.0)
    +                                  divisor-p))
    +  (let* ((x (/ (float number) divisor))
    +         (quotient (cond ((and (not divisor-p) (integerp number)) number)
    +                         ((= number divisor) 1)
    +                         ((plusp x) (truncate (+ x 0.5)))
    +                         ((= (- x 0.5) (truncate (- x 0.5)))
    +                          (if (minusp x)
    +                              (1- (truncate x))
    +                              (truncate x)))
    +                         (t (truncate (- x 0.5))))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The cl:round function computes a quotient that has +been rounded to the nearest mathematical integer. If the +mathematical quotient is exactly halfway between two integers, [that is, it +has the form 'integer+1/2'], then the quotient has been rounded +to the even [divisible by two] integer.

    + +

    The quotient is directly returned by the function, while a list:

    + +
    +(quotient remainder)
    +
    + +

    is stored in the Nyquist/XLISP +*rslt* variable and the +cl:*multiple-values* is set to + T  to signal that +Multiple Values are returned.

    + +See +Rounding and Truncation +for more details.

    + +

    Examples:

    + +
    +(round  3.5)     =>  4
    +(round -3.5)     => -3
    +
    +(cl:round  3.5)  =>  4  ; *rslt* = ( 4 -0.5)
    +(cl:round -3.5)  => -4  ; *rslt* = (-4  0.5)
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/rounding-and-truncation.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/rounding-and-truncation.htm new file mode 100644 index 0000000..40eaebc --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/rounding-and-truncation.htm @@ -0,0 +1,179 @@ + + +Rounding and Truncation + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Rounding and Truncation

    + +
    + +

    The cl:round, +cl:truncate, +cl:ceiling and +cl:floor functions divide a number by a divisor, +returning a quotient and a remainder:

    + +

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    (cl:round number [divisor])  ⇒  quotient, remainder
    (cl:truncate number [divisor])  ⇒  quotient, remainder
    (cl:ceiling number [divisor])  ⇒  quotient, remainder
    (cl:floor number [divisor])  ⇒  quotient, remainder

    + +

      +quotient * divisor + remainder = number

    + +

    + +

    The 'quotient' always represents a mathematical integer. The +'remainder' is an integer if both 'number' and 'divisor' arguments +are integers, and a floating-point number if either the +'number' or the 'divisor' or both are floating-point +numbers.

    + +

    With Nyquist/XLISP, the 'quotient' is always directly returned by the +function, while a list:

    + +
    +(quotient remainder)
    +
    + +

    is stored in the Nyquist/XLISP +*rslt* variable and the +cl:*multiple-values* is set to + T  to signal that +Multiple Values are returned.

    + +Examples: + +
    +(cl:round     3.5)  =>  4  ; *rslt* = ( 4 -0.5)
    +(cl:truncate  3.5)  =>  3  ; *rslt* = ( 3  0.5)
    +(cl:ceiling   3.5)  =>  4  ; *rslt* = ( 4 -0.5)
    +(cl:floor     3.5)  =>  3  ; *rslt* = ( 3  0.5)
    +
    +(cl:round    -3.5)  => -4  ; *rslt* = (-4  0.5)
    +(cl:truncate -3.5)  => -3  ; *rslt* = (-3 -0.5)
    +(cl:ceiling  -3.5)  => -3  ; *rslt* = (-3 -0.5)
    +(cl:floor    -3.5)  => -4  ; *rslt* = (-4  0.5)
    +
    + +

    Force an integer division:

    + +
    +(cl:truncate 3.0 2.0)              => 1  ; Common Lisp
    +(/ (truncate 3.0) (truncate 2.0))  => 1  ; Nyquist/XLISP
    +(/ 3 2)                            => 1  ; integer division
    +
    + +

    + +

    Implementation Notes

    + +
    +(defun name (number &optional (divisor (if (integerp number) 1 1.0)))
    +  ... )
    +
    + +

    The integerp test in the +parameter list signals an error if the 'number' argument is not a number, +also the  /  +[division] function signals errors if the 'divisor' argument is zero +or not a number, so we do not explicitely need to test the arguments.

    + +

    The cl:ceiling and +cl:floor functions test if 'number' is +an integer multiple of 'divisor' by comparing the results of an integer +division and a floating-point division:

    + +
    +(let ((i-quotient (/ (truncate number) (truncate divisor)))
    +      (f-quotient (/ (float number) divisor)))
    +  (if (= i-quotient f-quotient)
    +        ...
    +
    + +

    I'm not sure if this really catches all cases [e.g. +regarding floating point precision], but have found no problems so +far.

    + +

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/sqrt.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/sqrt.htm new file mode 100644 index 0000000..b430da3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/sqrt.htm @@ -0,0 +1,92 @@ + + +cl:sqrt + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:sqrt

    + +
    + +

    The cl:sqrt function does the same as the +Nyquist/XLISP sqrt function, but +also accepts integer numbers as argument:

    + +

    + +
    +
    (cl:sqrt number)
    +
    number - an integer or floating-point number
    +returns - the square root of number
    +
    + +

    + +
    +(defun cl:sqrt (x)
    +  (sqrt (float x)))
    +
    + +

    See defun, +float, +sqrt.

    + +The cl:sqrt function computes the square root of its +argument and returns the result. as a floating-point +number.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/truncate.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/truncate.htm new file mode 100644 index 0000000..6032dd3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/truncate.htm @@ -0,0 +1,135 @@ + + +cl:truncate + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:truncate

    + +
    + +

    The cl:truncate function +truncates an integer or +floating-point number toward zero:

    + +

    + +
    +
    (cl:truncate number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of truncating the result of number divided by divisor
     - the remainder of the truncate operation
    +
    + +

    + +
    +(defun cl:truncate (number &optional (divisor (if (integerp number) 1 1.0)))
    +  (let ((quotient (truncate (/ (float number) divisor))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The cl:truncate function computes a quotient that has +been truncated towards zero. That is, the quotient represents +the mathematical integer of the same sign as the mathematical quotient, and +that has the greatest integral magnitude not greater than that of the +mathematical quotient.

    + +

    The quotient is directly returned by the function, while a list:

    + +
    +(quotient remainder)
    +
    + +

    is stored in the Nyquist/XLISP +*rslt* variable and the +cl:*multiple-values* is set to + T  to signal that +Multiple Values are returned.

    + +See +Rounding and Truncation +for more details.

    + +

    Examples:

    + +
    +(cl:truncate  3.5)  =>  0  ; *rslt* => ( 3  0.5)
    +(cl:truncate -3.5)  => -3  ; *rslt* => (-3 -0.5)
    +
    + +

    Force an integer division:

    + +
    +(cl:truncate 3.1 2.6)  => 1  ; *rslt* => (1 0.5)
    +(/ 3 2)                => 1
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/values-list.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/values-list.htm new file mode 100644 index 0000000..52fa6e6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/values-list.htm @@ -0,0 +1,113 @@ + + +cl:values-list + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:values-list

    + +
    + +

    The cl:values-list function returns the elements of a +list unevaluated as multiple values:

    + +

    + +
    +
    (cl:values-list list)
    +
    list - a list of values
    +returns - the elements of the list as multiple values
    +
    + +

    + +
    +(defun cl:values-list (list)
    +  (or (listp list) (error "not a list" list))
    +  (or (null list) (consp (last list)) (error "not a proper list" list))
    +  (setq *rslt* list
    +        cl:*multiple-values* t)
    +  (first list))
    +
    + +

    The unevaluated first value from the list is returned as the primary +return value, and the list is assigned to the Nyquist +*rslt* variable. If +an an empty list is given, NIL +is returned and the *rslt* +variable is set to NIL. +An error is signalled if the 'list' argument is not a list or +if the list does not end +with NIL.

    + +

    The +cl:*multiple-values* +variable is set to + T  to indicate that +multiple values are returned.

    + +

    Examples:

    + +
    +(cl:values-list nil)         => NIL  ; *rslt* = NIL
    +(cl:values-list '(1))        => 1    ; *rslt* = (1)
    +(cl:values-list '(1 2))      => 1    ; *rslt* = (1 2)
    +(cl:values-list '(1 2 3))    => 1    ; *rslt* = (1 2 3)
    +(cl:values-list '(1 2 . 3))  => error: not a proper list - (1 2 . 3)
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/common-lisp/values.htm b/docsrc/xlisp/xlisp-doc/examples/common-lisp/values.htm new file mode 100644 index 0000000..92a828e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/common-lisp/values.htm @@ -0,0 +1,160 @@ + + +cl:values + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cl:values

    + +
    + +

    The cl:values function evaluates all given Lisp +expressions and returns the results as multiple values:

    + +

    + +
    +
    (cl:values [expr1 ...])
    +
    exprN - an arbitrary Lisp expression
    +returns - the results of evaluating the expressions, as multiple values
    +
    + +

    + +
    +(defun cl:values (&rest exprs)
    +  (setq *rslt* exprs
    +        cl:*multiple-values* t)
    +  (first exprs))
    +
    + +

    The primary return value [the result from evaluating the +first expression] is returned by the cl:values function +and a list with the results of evaluating all expressions is assigned to the +Nyquist *rslt* variable. +If no expressions are given, +NIL is returned and the +*rslt* variable is set +to NIL.

    + +

    The +cl:*multiple-values* +variable is set +to  T  +to indicate that multiple values are returned.

    + +

    Examples:

    + +
    +(cl:values 1 2 3)  => 1        ; primary value
    +*rslt*             => (1 2 3)  ; all values
    +
    +(cl:values 'a 'b)  => A        ; primary value
    +*rslt*             => (A B)    ; all values
    +
    +> (cl:multiple-value-bind (a b c)
    +      (cl:values 1 2 3)
    +    (list a b c))
    +(1 2 3)
    +
    + +

    See +cl:multiple-value-bind, +list, +*rslt*.

    + +

    + +

    Known Limitations

    + +

    1. In Nyquist/XLISP, cl:values cannot be +used as argument to setf. But +this is not a real problem, because the values are stored as a +simple list in the *rslt* +variable, where they can be manipulated with any arbitrary Lisp +functions, not only with +setf.

    + +

    2. In Common Lisp there exists the option to return +'no value' by calling the 'values' function with no arguments. +In Nyquist/XLISP there is no built-in way to +return 'no value' from a function. The symbol +*unbound* cannot be used for +this because in Common Lisp, if 'no value' is +assigned to a symbol as variable value, the new value will be +NIL and not +*unbound*.

    + +

    In Nyquist/XLISP, the cl:values function, if called with no +arguments, always returns NIL, and the +*rslt* variable will be +set to NIL, too:

    + +
    +(cl:values)      => NIL    ; primary value
    +*rslt*           => NIL    ; all values
    +
    +(cl:values nil)  => NIL    ; primary value
    +*rslt*           => (NIL)  ; all values
    +
    + +

    Maybe this observation helps to write a 'no values' test if +anybody really needs it.

    + +

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/environment.htm b/docsrc/xlisp/xlisp-doc/examples/environment.htm new file mode 100644 index 0000000..13a362d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/environment.htm @@ -0,0 +1,1001 @@ + + +Environment + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Environment

    + +
    + +
      +
    1. *unbound*
    2. +
    3. Lexical Environment
    4. + +
    5. lboundp - [Macro] - has this symbol a lexical variable value bound to it?
    6. +
        +
      • valuep - [Macro] - has this symbol a valid variable value bound to it?
      • +
      +
    7. lfboundp - [Macro] - has this symbol a lexical function value bound to it?
    8. +
    9. lsymbol-value - [Macro] - get the lexical variable value
    10. +
    11. lsymbol-function - [Macro] - get the lexical flet, labels, or macrolet function value
    12. +
    13. lmacroexpand-1 - [Macro] - expand the first level of a a macrolet form
    14. +
    15. Known Problems
    16. +
    + + + +
    + +

    *unbound*

    + +
    + +

    A tricky problem with XLISP is that the symbol +*unbound* can be bound as a +value to any Lisp symbol, also to a lexical parameter variable if passed +as a value to a Lisp function:

    + +
    +(defun test (x)
    +  (print x))
    +
    +(test '*unbound*)  => error: unbound variable
    +
    + +

    The problem here is that the symbol +*unbound* has been bound to +the parameter variable 'x', so the expression (print x) +instead of printing "*UNBOUND*" now causes an 'unbound variable' +error. How can I test from inside of a function if the lexical +parameter variable 'x' is bound to the symbol +*unbound*? Unfortunately there +is no standard Lisp way to solve this problem.

    + +

      Back to top

    + + + +
    + +

    *obarray*

    + +
    + +

    A symbol in the *obarray* is protected from garbage collection.

    + +

      Back to top

    + + + +
    + +

    Lexical Environment

    + +
    + +

    Lisp parameter variables together with local variables bound with +let and +let* and functions defined by +flet and +labels are not interned in the +*obarray*, instead they are +stored in the local lexical environment, maintained via an internal +association list. The key for reading this list is the +*evalhook* variable and the +evalhook function.

    + +

    Here are two Nyquist macros from 'evalenv.lsp':

    + +
    +(defmacro getenv ()        ; return the current environment
    +  '(progv '(*evalhook*) (list #'(lambda (exp env) env))
    +     (eval nil)))
    +
    +(defmacro eval-env (arg)   ; evaluate in the current environment
    +  `(evalhook ,arg nil nil (getenv)))
    +
    + +

      Back to top

    + + + +
    + +

    getenv

    + +
    + +

    The 'getenv' macro returns the association list of the current lexical +environment:

    + +
    +(let ((v1 1)          ; first variable
    +      (v2 2))         ; second variable
    +  (flet ((f1 (a) a)   ; first function
    +         (f2 (b) b))  ; second function
    +    (getenv)))
    +
    +=> ((((V2 . 1) (V1 . 2))) ((F2 . #<Closure...>) (F1 . #<Closure...>)))
    +
    + +

    The asymmetric layout is produced by +print, the real structure of the +lexical environment is a cons of two +association lists:

    + +
    +(defmacro print-env ()
    +  (let ((env (gensym)))
    +    `(let ((,env (getenv)))
    +       (format t "(~s . ~s)~%" (car ,env) (cdr ,env)))))
    +
    + +

    Note: You could also use +print-cons instead of +format to print really all the +details of the list, but format is +enough for the examples here.

    + +
    +(let ((v1 1)          ; first variable
    +      (v2 2))         ; second variable
    +  (flet ((f1 (a) a)   ; first function
    +         (f2 (b) b))  ; second function
    +    (print-env)))
    +
    +((((V2 . 2) (V1 . 1))) . (((F2 . #<Closure...>) (F1 . #<Closure...>))))
    +
    + +

    The basic layout is:

    + +
    +((((V2 . value) (V1 . value))) . (((F2 . value) (F1 . value))))
    +
    +((<----- variable-list ----->) . (<----- function-list ----->))
    +
    +(car (getenv))  => (variable-list)
    +(cdr (getenv))  => (function-list)
    +
    + +

    The different levels of bindings are maintained via multiple +sublists:

    + +
    +(let ((v1 1))             ; first level variable
    +  (let ((v2 2))           ; second level variable
    +    (flet ((f1 (a) a))    ; first level function
    +      (flet ((f2 (b) b))  ; second level function
    +        (print-env)))))
    +
    +((((V2 . value)) ((V1 . value))) . (((F2 . value)) ((F1 . value))))
    +
    +(((<--level2-->) (<--level1-->)) . ((<--level2-->) (<--level1-->)))
    +((<------ variable-list ------>) . (<------ function-list ------>))
    +
    + +

    Variables appear always in the variable list, functions always in the +function list:

    + +
    +(let ((v1 1))             ; first level variable
    +  (flet ((f1 (a) a))      ; first level function
    +    (let ((v2 2))         ; second level variable
    +      (flet ((f2 (b) b))  ; second level function
    +        (print-env)))))
    +
    +((((V2 . value)) ((V1 . value))) . (((F2 . value)) ((F1 . value))))
    +
    +(((<--level2-->) (<--level1-->)) . ((<--level2-->) (<--level1-->)))
    +((<------ variable-list ------>) . (<------ function-list ------>))
    +
    + +

    The inner-most bindings always appear at the front of the +lists:

    + +
    +(let ((v1 1))             ; first level variable
    +  (let ((v2 2))           ; second level variable
    +    (flet ((f1 (a) a))    ; first level function
    +      (flet ((f2 (b) b))  ; second level function
    +        (let ((v3 3))     ; third level variable
    +          (print-env))))))
    +
    +((((V3 . value)) ((V2 . value)) ((V1 . value))) . (((F2 . value)) ((F1 . value))))
    +
    +(((<--level3-->) (<--level2-->) (<--level1-->)) . ((<--level2-->) (<--level1-->)))
    +((<------------- variable-list -------------->) . (<------ function-list ------>))
    +
    + +

    There may appear several variable bindings in the same sublist:

    + +
    +(let ((v1 1) (v2 2))      ; first level variables
    +  (flet ((f1 (a) a)       ; first level functions
    +         (f2 (b) b))
    +    (let ((v3 3))         ; second level variable
    +      (print-env))))
    +
    +((((V3 . value)) ((V2 . value) (V1 . value))) . (((F2 . value) (F1 . value))))
    +
    +(((<--level2-->) (<--------level1--------->)) . ((<---------level1-------->)))
    +((<------------ variable-list ------------->) . (<----- function-list ----->))
    +
    + +

    The basic principle is always the same:

    + +
    +(((level n ...) ... (level 1 variables)) . ((level n ...) ... (level 1 functions)))
    +
    +(car (getenv))  => ((level n ...) (level n-1 ...) ... (level 1 variables))
    +(cdr (getenv))  => ((level n ...) (level n-1 ...) ... (level 1 functions))
    +
    + +

    Also the function parameter variables appear in the the lexical +environment association list:

    + +
    +(defun test (parameter-var)
    +  (let ((local-var 'value))
    +    (print-env)))
    +
    +((((LOCAL-VAR . value)) ((PARAMETER-VAR . value))) . NIL)  ; NIL = no functions
    +
    +(((<-----level2------>) (<-------level1-------->)) . NIL)
    +((<--------------- variable-list --------------->) . NIL)
    +
    + +

    The variables bound by let appear +before the function's parameter variables, that's why +let bindings 'shadow' parameter variables +with the same name. The 'test' function name does not appear in +the environment list because the function name was +interned in the +*obarray* by +defun.

    + +

      Back to top

    + + + +
    + +

    eval-env

    + +
    + +

    This still doen't work:

    + +
    +(setq x 'global)        ; define a global variable 'x'
    +
    +(defun print-x ()       ; define a function PRINT-X in the global environment
    +  (print (getenv))      ; always prints ((NIL)), also with EVAL-ENV or EVALHOOK
    +  (print x))            ; always prints GLOBAL, also with EVAL-ENV or EVALHOOK
    +
    +(let ((x 'local))       ; create a lexical variable 'x'
    +  (print-x))            ; evaluate PRINT-X
    +=> GLOBAL               ; value from the environment, where PRINT-X was defined
    +
    +(let ((x 'local))       ; create a lexical variable 'x'
    +  (eval-env (print-x))  ; evaluate PRINT-X in the current environment
    +=> GLOBAL  ;wrong       ; value from the environment, where PRINT-X was called
    +
    +(let ((x 'local))       ; create a lexical variable 'x'
    +  (eval-env (funcall 'print-x))  ; evaluate PRINT-X in the current environment
    +=> GLOBAL  ;wrong       ; value from the environment, where PRINT-X was called
    +
    + +

      Back to top

    + + + +
    + +

    lboundp

    + +
    + +

    The 'lboundp' function tests if a valid variable value is bound to a +symbol in the current lexical environment:

    + +

    + +
    +
    (lboundp symbol)
    +
    symbol - a quoted lisp symbol
    +returns -  T  if a lexical +variable value is bound to the symbol, NIL otherwise
    +
    + +

    + +
    +(defmacro lboundp (symbol)
    +  (cond ((not (or (symbolp symbol)
    +                  (and (consp symbol)
    +                       (eq 'quote (car symbol))
    +                       (symbolp (cadr symbol)))))
    +         (error "bad argument type" symbol))
    +        ((and (consp symbol) (cddr symbol))
    +         (error "too many arguments"))
    +        (t (let ((a-cons (gensym)) (level (gensym)) (binding (gensym)))
    +             `(let ((,a-cons (dolist (,level (car (getenv)) nil)
    +                               (let ((,binding (assoc ,symbol ,level)))
    +                                 (when ,binding (return ,binding))))))
    +                (and ,a-cons (not (eq (cdr ,a-cons) '*unbound*))))))))
    +
    + +

    The XLISP boundp function only +can test global variables, interned in the +*obarray*, so it cannot be +used to test if a symbol has a variable value bound to it in the lexical +environment:

    + +
    +(defun test (x)    ; bad example
    +  (if (boundp 'x)  ; <- global test
    +      (print x)
    +      (print '*unbound*)))
    +
    +(test 'hello!)     => *UNBOUND*  ; bad result
    +(test 123)         => *UNBOUND*  ; bad result
    +
    +(setq x t)         => T          ; create a global variable 'x'
    +
    +(test 'hello!)     => 'HELLO!    ; OK
    +(test 123)         => 123        ; OK
    +(test '*unbound*)  => error: unbound variable - X  ; bad result
    +
    + +

    Here the same example with 'lboundp':

    + +
    +(defun test (x)     ; good example
    +  (if (lboundp 'x)  ; <- local test
    +      (print x)
    +      (print '*unbound*)))
    +
    +(test 'hello!)     => 'HELLO!    ; OK
    +(test 123)         => 123        ; OK
    +(test '*unbound*)  => *UNBOUND*  ; OK
    +
    + +

    The 'lboundp' function cannot test symbol values at the +top-level, because there is no lexical environment:

    + +
    +(setq x t)    => T   ; create a global variable 'x'
    +(lboundp 'x)  => NIL ; lexical test fails
    +(boundp 'x)   => T   ; global test succeeds
    +
    + +

      Back to top

    + + + +
    + +

    valuep

    + +
    + +

    The 'valuep' function tests if a valid variable value is bound to a +symbol at any level:

    + +
    +(defmacro valuep (symbol)
    +  (cond ((not (or (symbolp symbol)
    +                  (and (consp symbol)
    +                       (eq 'quote (car symbol))
    +                       (symbolp (cadr symbol)))))
    +         (error "bad argument type" ,symbol))
    +        ((and (consp symbol) (cddr symbol))
    +         (error "too many arguments"))
    +        (t (let ((a-cons (gensym)) (level (gensym)) (binding (gensym)))
    +             `(let ((,a-cons (dolist (,level (car (getenv)) nil)
    +                               (let ((,binding (assoc ,symbol ,level)))
    +                                 (when ,binding (return ,binding))))))
    +                (if ,a-cons
    +                    (not (eq (cdr ,a-cons) '*unbound*))
    +                    (boundp ,symbol)))))))
    +
    + +

    It's tricky to test if a symbol has a valid variable value bound to +it because if the symbol is bound to +*unbound* in a lexical +environment, it still shadows a symbol with the same name in the +*obarray*, making a possibly +existing global variable inaccessible, like shown in the examples +below.

    + +

    Note: The lexical environment must be tested first, because this +is the way how XLISP searches for symbol bindings.

    + +

    Examples:

    + +
    +(when (valuep 'x) x)  => NIL  ; no global binding of 'x' found
    +(setq x 'ok)          => OK   ; create a global variable 'x'
    +(when (valuep 'x) x)  => OK   ; global binding of 'x' found
    +
    +(let ((x 'local))             ; create a lexical variable 'x'
    +  (when (valuep 'x) x))       ; try to access the lexical variable
    +=> LOCAL                      ; lexical binding of 'x' found
    +
    + +

    XLISP problems with +*unbound* +lexical variables:

    + +
    +(setq x 'ok)          => OK   ; create a global variable 'x'
    +(when (valuep 'x) x)  => OK   ; global binding of 'x' found
    +
    +(let ((x '*unbound*))         ; create an unbound lexical variable 'x'
    +  (when (valuep 'x) x))       ; try to access the global variable
    +=> NIL                        ; global binding of 'x' NOT found
    +
    +(let ((x '*unbound*))         ; create an unbound lexical variable 'x'
    +  x)                          ; try to access the global variable
    +error: unbound variable - X
    +
    + +

    The 'valuep' function recognizes if a global variable value is shadowed +by an *unbound* lexical +variable and returns NIL if the global variable is inaccessible..

    + +

      Back to top

    + + + +
    + +

    lfboundp

    + +
    + +

    The 'lfboundp' function tests if a valid function value is bound to a +symbol in the current lexical environment:

    + +

    + +
    +
    (lfboundp symbol)
    +
    symbol - a quoted lisp symbol
    +returns -  T  if a lexical +function value is bound to the symbol, NIL otherwise
    +
    + +

    + +
    +(defmacro lfboundp (symbol)
    +  (cond ((not (or (symbolp symbol)
    +                  (and (consp symbol)
    +                       (eq 'quote (car symbol))
    +                       (symbolp (cadr symbol)))))
    +         (error "bad argument type" symbol))
    +        ((and (consp symbol) (cddr symbol))
    +         (error "too many arguments"))
    +        (t (let ((a-cons (gensym)) (level (gensym)) (binding (gensym)))
    +             `(let ((,a-cons (dolist (,level (cdr (getenv)) nil)
    +                               (let ((,binding (assoc ,symbol ,level)))
    +                                 (when ,binding (return ,binding))))))
    +                (and ,a-cons (not (eq (cdr ,a-cons) '*unbound*))))))))
    +
    + +

    The XLISP fboundp function only +works with symbols interned in the +*obarray*, so it cannot be +used to test if a symbol has a function value bound to it in the lexical +environment:

    + +
    +(flet ((my-function (x) 'hello))
    +  (fboundp 'my-function))   ; <- global test
    +=> NIL
    +
    +(flet ((my-function (x) 'hello))
    +  (lfboundp 'my-function))  ; <- local test
    +=> T
    +
    + +

    The 'lfboundp' function cannot test symbol function values at the +top-level, because there is no lexical environment:

    + +
    +(lfboundp 'car)  => NIL ; lexical test fails
    +(fboundp 'car)   => T   ; global test succeeds
    +
    + +

    Problems with *unbound* +lexical functions are less likely then with +*unbound* parameter +variables, because there is no buit-in way to bind a lexical +function to *unbound*.

    + +

    See also:

    + +
      +
    • suprp - is this a built-in function?
    • +
    • fsubrp - is this a built-in special form?
    • +
    • closurep - is this a user-defined function or macro?
    • +
    • functionp - is this a build-in or a user-defined function?
    • +
    • macrop - is this a user-defined macro?
    • +
    + +

      Back to top

    + + + +
    + +

    lsymbol-value

    + +
    + +

    The function 'lsymbol-value' returns a variable value from the lexical +environment:

    + +
    +(defmacro lsymbol-value (symbol)
    +  (cond ((not (or (symbolp symbol)
    +                  (and (consp symbol)
    +                       (eq 'quote (car symbol))
    +                       (symbolp (cadr symbol)))))
    +         (error "bad argument type" symbol))
    +        ((and (consp ,symbol) (cddr symbol))
    +         (error "too many arguments"))
    +        (t (let ((a-cons (gensym)) (level (gensym)) (binding (gensym)))
    +             `(let ((,a-cons (dolist (,level (car (getenv)) nil)
    +                               (let ((,binding (assoc ,symbol ,level)))
    +                                 (when ,binding (return ,binding))))))
    +                (when ,a-cons
    +                    (if (eq (cdr ,a-cons) '*unbound*)
    +                        '*unbound*
    +                        (cdr ,a-cons))))))))
    +
    + +

      Back to top

    + + + +
    + +

    lsymbol-function

    + +
    + +

    The function 'lsymbol-function' returns a function value from the lexical +environment:

    + +
    +(defmacro lsymbol-function (symbol)
    +  (cond ((not (or (symbolp symbol)
    +                  (and (consp symbol)
    +                       (eq 'quote (car symbol))
    +                       (symbolp (cadr symbol)))))
    +         (error "bad argument type" symbol))
    +        ((and (consp symbol) (cddr symbol))
    +         (error "too many arguments"))
    +        (t (let ((a-cons (gensym)) (level (gensym)) (binding (gensym)))
    +             `(let ((,a-cons (dolist (,level (cdr (getenv)) nil)
    +                               (let ((,binding (assoc ,symbol ,level)))
    +                                 (when ,binding (return ,binding))))))
    +                (when ,a-cons
    +                  (if (eq (cdr ,a-cons) '*unbound*)
    +                      '*unbound*
    +                      (cdr ,a-cons))))))))
    +
    + +

    The XLISP function +symbol-function +only works with symbols interned in the +*obarray*, so it cannot return +a function value, bound to a symbol in the lexical environment:

    + +
    +(flet ((my-function (x) 'hello))
    +  (symbol-function 'my-function))  ; <- searches the *obarray*
    +=> error: unbound function - MY-FUNCTION
    +
    +(flet ((my-function (x) 'hello))
    +  (lsymbol-function 'my-function)) ; <- searches the lexical environment
    +=> #<Closure-MY-FUNCTION...>
    +
    + +

      Back to top

    + + + +
    + +

    lmacroexpand-1

    + +
    + +
    +(defmacro with-static-env (&rest body)
    +  (let ((env (gensym)) (rval (gensym)))
    +    `(let ((,env (getenv)))  ; environment snapshot
    +       (progv '(*evalhook*)
    +              '((lambda (exp env)
    +                 (labels ((,rval (exp env) ; recursive eval
    +                            (format t "exp: ~a env: ~a ,env: ~a~%" exp env ,env)
    +                            (evalhook exp #',rval NIL ,env)))
    +                   (format t "exp: ~a env: ~a ,env: ~a~%" exp env ,env)
    +                   (evalhook exp #',rval NIL ,env))))
    +         ,@body))))
    +
    + +
    +(defmacro with-dynamic-env (&rest body)
    +  (let ((env (gensym)) (rval (gensym)))
    +    `(let ((,env (getenv)))  ; environment snapshot
    +       (progv '(*evalhook*)
    +              '((lambda (exp env)
    +                 (labels ((,rval (exp env) ; recursive eval
    +                            (format t "inner exp: ~a env: ~a~%" exp env)
    +                            (evalhook exp #',rval NIL env)))
    +                   (format t "outer exp: ~a env: ~a~%" exp env)
    +                   (evalhook exp #',rval NIL env))))
    +         ,@body))))
    +
    + +
    +(defun display-env (env &optional (exp nil exp-p))
    +  (flet ((display-bindings (name bindings)
    +    (format t " ~a bindings: ~s~%" name bindings)
    +    (let ((frame-counter 1))
    +      (dolist (frame bindings)
    +        (format t "  ~a frame ~a: ~a~%" name frame-counter frame)
    +        (let ((binding-counter 1))
    +          (dolist (binding frame)
    +            (when (consp binding)
    +              (format t "   ~a ~a: ~s - value: ~s~%"
    +                  name binding-counter (car binding) (cdr binding))
    +              (incf binding-counter))))
    +        (incf frame-counter)))))
    +    (when exp-p (format t "eval: ~s~%" exp))
    +    (format t "environment: ~s~%" env)
    +    (display-bindings "variable" (car env))
    +    (display-bindings "function" (cdr env))))
    +
    +(defmacro debug:env ()
    +  '(progv '(*evalhook*) '(nil)
    +     (display-env (getenv))))
    +
    +(defmacro debug:env ()
    +  '(progv '(*evalhook*) '((lambda (exp env)
    +                            (display-env env)))
    +     (eval nil)))
    +
    +(defmacro debug:env (&rest body)
    +  (when *evalhook*
    +    (format t "DEBUG:ENV ")
    +    (format t "*evalhook* was already modified~%"))
    +  (if (null body)
    +      '(progv '(*evalhook*) '((lambda (exp env)
    +                                (display-env env)))
    +         (eval nil))
    +      (let ((init (gensym)) (rval (gensym)))
    +        `(let ((,init (getenv)))  ; environment snapshot
    +           (progv '(*evalhook*)
    +                  '((lambda (exp env)
    +                     (labels ((,rval (exp env) ; recursive eval
    +                                (display-env env exp)
    +                                (evalhook exp #',rval nil env)))
    +                       (display-env ,init exp)
    +                       (evalhook exp #',rval nil ,init))))
    +             ,@body)))))
    +
    +(defmacro with-evalhook (&rest body)
    +  (let ((init (gensym)) (rval (gensym)) (hook (gensym)) debug)
    +    `(let ((,init (getenv)))  ; environment snapshot
    +       (progv '(*evalhook*)
    +              '((lambda (exp env)
    +                 (labels ((,rval (exp env)  ; recursive eval
    +                            ,(print *evalhook*)
    +                            ,(when T `(funcall ,*evalhook* exp env))
    +
    +                            (evalhook exp #',rval nil env)))
    +                   (evalhook exp #',rval nil ,init))))
    +         ,@body))))
    +
    +(defmacro with-current-environment (&rest body)
    +  (when *evalhook* (error "*evalhook* already modified"))
    +  (let ((init (gensym)) (rval (gensym)) debug)
    +    (when (eq :debug (car body)) (setq debug t body (cdr body)))
    +    `(let ((,init (getenv)))  ; environment snapshot
    +       (progv '(*evalhook*)
    +              '((lambda (exp env)
    +                 (labels ((,rval (exp env)  ; recursive eval
    +                            ;; append environment from snapshot
    +                            (setq env (cons (append (car env) (car ,init))
    +                                            (append (cdr env) (cdr ,init))))
    +                            ,(when debug '(display-env env exp))
    +                            (evalhook exp #',rval nil env)))
    +                   ;; start with environment snapshot
    +                   ,(when debug `(display-env ,init exp))
    +                   (evalhook exp #',rval nil ,init))))
    +         ,@body))))
    +
    +(defmacro with-env (&rest body)
    +  (let ((init (gensym)) (rval (gensym)))
    +    `(let ((,init (getenv)))  ; environment snapshot
    +       (progv '(*evalhook*)
    +              '((lambda (exp env)
    +                 (labels ((,rval (exp env) ; recursive eval
    +                            (display-env env exp)
    +                            (evalhook exp #',rval nil env)))
    +                   (display-env ,init exp)
    +                   (evalhook exp #',rval nil ,init))))
    +         ,@body))))
    +
    + +
    +(with-current-environment
    +  (debug:env
    +    body))
    +
    +(progv '(*evalhook)
    +       '((lambda (exp env)
    +           (labels ((rval (exp env)
    +                      (append-current-environment)
    +                      (debug:env ...)
    +                      (evalhook exp #'rval nil env)))
    +             (evalhook exp #'rval nil init)))))
    +
    +(debug:env
    +  (with-current-environment
    +    body))
    +
    +(progv '(*evalhook)
    +       '((lambda (exp env)
    +           (labels ((rval (exp env)
    +
    + +
    +(defmacro with-current-environment (&rest body)
    +  (when *evalhook* (error "*evalhook* already modified"))
    +  (let ((debug nil) (init (gensym)) (rval (gensym)))
    +    (when (eq :debug (car body)) (setq debug t body (cdr body)))
    +    `(let ((,init (getenv)))  ; environment snapshot
    +       (progv '(*evalhook*)
    +              '((lambda (exp env)
    +                 (labels ((,rval (exp env)  ; recursive eval
    +                            ,(cond (debug
    +                                    `(setq env
    +                                       (cons (append (car env) (car ,init))
    +                                             (append (cdr env) (cdr ,init))))
    +                                    '(display-env env exp)
    +                                    `(evalhook exp #',rval nil env))
    +                                   (t
    +                                    `(evalhook exp #',rval nil
    +                                       (cons (append (car env) (car ,init))
    +                                             (append (cdr env) (cdr ,init))))))))
    +                   ,(when debug `(display-env ,init exp))
    +                   (evalhook exp #',rval nil ,init))))
    +         ,@body))))
    +
    + +
    +(setq *rvalhook* nil)
    +
    +(defmacro with-current-environment (&rest body)
    +  (let ((init (gensym)))
    +    `(let ((,init (getenv)))
    +       (rval-env #'(lambda (exp env)
    +                     (cons exp (cons (append (car env) (car ,init))
    +                                     (append (cdr env) (cdr ,init)))))
    +                 ,@body))))
    +
    +(defmacro debug:env (&rest body)
    +  (rval-env #'(lambda (exp env)
    +                (display-env env exp)
    +                (cons exp env))
    +            ,@body))
    +
    +(defmacro run-rvalhooks ()
    +  (let ((func (gensym)) (result (gensym)))
    +    `(dolist (,func *rvalhook*)
    +       (format t "func: ~a~%" ,func)
    +       (format t "exp: ~a~%" exp)
    +       (format t "env: ~a~%" env)
    +       (let ((,result (eval (list ,func 'exp 'env) )))
    +         (format t "result: ~a~%" ,result)
    +         (format t "exp: ~a~%" exp)
    +         (format t "car: ~a~%" (car ,result))
    +         (format t "env: ~a~%" env)
    +         (format t "cdr: ~a~%" (cdr ,result))
    +         (setq exp (car ,result) env (cdr ,result)) 
    +  ))))
    +
    +(defmacro rval-env (function &rest body)
    +  (format t "function: ~a~%" function)
    +  (format t "body: ~a~%" body)
    +  (or *evalhook* (setq *rvalhook* nil))
    +  (format t "*rvalhook*: ~a~%" *rvalhook*)
    +  (if *rvalhook*
    +      `(prog2
    +         (push ,function *rvalhook*)
    +         (progn ,@body)
    +         (setq *rvalhook* (remove ,function *rvalhook*)))
    +      (let ((rval (gensym)) (func (gensym)) (result (gensym)))
    +        `(prog2
    +           (push ,function *rvalhook*)
    +           (progv '(*evalhook*)
    +                  `((lambda (exp env)
    +                      (print 'hallo)
    +                      (labels ((,rval (exp env)
    +                                 (run-rvalhooks)
    +                                 (evalhook exp #',rval nil env)))
    +                        ; (run-rvalhooks)
    +                        (evalhook exp #',rval nil env))))
    +             ,@body)
    +           (setq *rvalhook* (remove ,function *rvalhook*))))))
    +
    + +

    *rvalhook* must be a list of functions, each taking two arguments 'exp' +[the Lisp expressions to evaluate] and 'env' [the environment], returning +a cons of the format (exp . env).

    + +

    In case of an error, the +*evalhook* variable is +automatically reset by the XLISP +top-level function. +This means that if *evalhook* +is NIL and *rvalhook* is +non-NIL, then *rvalhook* is +invalid and must also be reset to NIL +before pushing the next function on it.

    + +
    +(defmacro lmacroexpand-1 (form)
    +  (if (not (and (consp form)
    +                (eq 'quote (car form))
    +                (symbolp (caadr form))))
    +      form  ; if the form isn't '(symbol ... )
    +      (let ((a-cons (gensym)) (l-expr (gensym)))
    +        `(let ((,a-cons (assoc ',(caadr form) (cadr (getenv)))))
    +           (if (null ,a-cons)  ; (caadr form) = macro-name
    +               ,form  ; if no lexical binding was found
    +               (let ((,l-expr (get-lambda-expression (cdr ,a-cons))))
    +                 (if (eq 'macro (car ,l-expr)) ; if l-expr is a macro
    +                     (with-current-environment
    +                       ;; create an *unbound* macro in the *obarray*
    +                       (eval (append '(defmacro *unbound*) (cdr ,l-expr)))
    +                       ;; expand the macro in the current environment
    +                       (eval (list 'macroexpand-1  ; (cdadr form) =
    +                                   (list 'quote    ; macro-arguments as list
    +                                         (cons '*unbound* ',(cdadr form))))))
    +                     ,form)))))))  ; if l-expr is not a macro
    +
    + +
    +(let ((x 1))
    +  (macrolet ((test (arg)
    +               `(progn
    +                  (print ,arg)
    +                  (print ,(eval x)))))
    +    (lmacroexpand-1 '(test 'hallo))))
    +=>
    +
    + +

      Back to top

    + + + +
    + +

    Known Problems

    + +
    + +

    A lexical variable with the symbol +*unbound* as a variable value +bound to it will continue to shadow a global variable with the same name, +even if the the lexical variable is 'unbound':

    + +
    +(setq x t)  => T        ; create a global variable 'x'
    +
    +(let ((x '*unbound*))   ; create an unbound lexical variable 'x'
    +  (print x))            ; try to print the global variable
    +error: unbound variable - X
    +
    + +

    Tested with Nyquist 3.03 in December 2010.

    + +

    Nyquist Bug: let* causes infinite recursion problems with either +progv, evalhook, or *evalhook* [still needs more investigation], so this +doesnt work:

    + +
    +(let* ((init (getenv)))
    +  (progv '(*evalhook*)
    +         '((lambda (exp env)
    +             (labels ((rval (exp env)
    +                        (print init)  ; <- causes infinite recursion
    +                        (evalhook exp #'rval nil env)))
    +               (evalhook exp #'rval nil init))))
    +    (eval nil)))
    +=> infinite recursion
    +
    + +while exactly the same form using let instead of let* works: + +
    +(let ((init (getenv)))
    +  (progv '(*evalhook*)
    +         '((lambda (exp env)
    +             (labels ((rval (exp env)
    +                        (print init)  ; <- no infinite recursion
    +                        (evalhook exp #'rval nil env)))
    +               (evalhook exp #'rval nil init))))
    +    (eval nil)))
    +(NIL)  ; PRINT output
    +=> NIL
    +
    + +

    Bug tested with Nyquist 3.03 in December 2010.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/evaluation.htm b/docsrc/xlisp/xlisp-doc/examples/evaluation.htm new file mode 100644 index 0000000..fc46780 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/evaluation.htm @@ -0,0 +1,131 @@ + + +Evaluation + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Evaluation

    + +
    + +
      +
    1. with-errset - evaluate expressions without entering the Break Loop
    2. +
    3. apply* and funcall* - work also with macros and special forms
    4. +
    + + + +
    + +

    with-errset

    + +
    + +

    Evaluate an expression without entering the +Break Loop +on error +or cerror:

    + +
    +(defmacro with-errset (expr &optional (print-flag nil))
    +  `(progv '(*breakenable*) '(nil)
    +     (errset ,expr ,print-flag)))
    +
    + +

    See defmacro, +errset, +nil, +&optional, +progv.

    + +

    Note: errset does not +protect against the break function.

    + +

      Back to top

    + + + +
    + +

    apply* and funcall*

    + +
    + +

    In Lisp, macros and special forms are no functions. This +means that apply and +funcall only work with functions of +type SUBR [built-in function] or CLOSURE [functions defined by +defun, flet, +labels, or lambda], but +with macros and special forms a 'bad function' +error is signalled. Here are two examples how to work around this +behaviour:

    + +
    +(defun apply* (function args)
    +  (eval (cons function args)))
    +
    +(defun funcall* (function args)
    +  (eval (cons function args)))
    +
    + +

    Warning: These functions can produce unwanted +side-effects because macros and special forms do +not need to conform to functional evaluation rules. Use them on your own +risk.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + + diff --git a/docsrc/xlisp/xlisp-doc/examples/examples.htm b/docsrc/xlisp/xlisp-doc/examples/examples.htm new file mode 100644 index 0000000..2140ebe --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/examples.htm @@ -0,0 +1,211 @@ +XLISP Examples + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    XLISP Examples

    + +
    + +

    Nyquist/XLISP

    + +
      +
    • Lists
    • +
        +
      • print-cons - print lists as dotted conses
      • +
      • dolist* - a dolist version that can iterate dotted lists
      • +
      +
    • Arrays
    • +
        +
      • make-array* - create multi-dimensional arrays
      • +
      • aref* - access multi-dimensional arrays
      • +
      +
    • Circular Access
    • +
        +
      • c-nth - circular list accessor
      • +
      • c-aref - circular array accessor
      • +
      +
    • Hash Tables
    • +
        +
      • make-hash-table - create a hash-table
      • +
      • puthash - store a key/value pair in a hash-table
      • +
      • gethash - get a value from a hash-table by using a key
      • +
      • remhash - remove a key/value pair from a hash-table
      • +
      • clrhash - remove all key/value pairs from a hash-table
      • +
      • hash-table-p - is this a hash-table?
      • +
      • hash-table-size - get the number of buckets
      • +
      • hash-table count - get the number of key/value pairs
      • +
      • hash-table-test - get the :test argument given to to make-hash-table
      • +
      • print-hash-table - print a hash-table in human-readable form
      • +
      +
    • Strings and Characters
    • + +
    • Sequences - lists, strings, and arrays
    • +
    • Predicates and Comparison
    • +
    • Files and Directories
    • +
    • Numbers
    • + +
    • Reader
    • +
        +
      • read-from-string
      • +
      • *readtable*
      • +
          +
        • print-readtable - print the XLISP *readtable* in human-readable form
        • +
        • get-macro-character
        • +
        • set-macro-character
        • +
        +
      +
    + + + + + +

    Common Lisp - written in Nyquist/XLISP

    + + + +
      +
    • Data and Control Flow
    • +
        +
      • Comparison
      • +
          +
        • eq - [Function] - test if arguments are identical
        • +
        • eql - [Function] - test if arguments are identical or same integer value
        • +
        • equal - [Function] - test if arguments are structurally equivalent
        • +
        • cl:equalp - [Function] - test arguments with 'equality' functions
        • +
        +
      • Multiple Values
      • +
          +
        • XLISP helpers
        • + +
        • Returning Multiple Values
        • +
            +
          • cl:values - [Function] - return results from evaluated arguments as multiple values
          • +
          • cl:values-list - [Function] - return multiple values from a list unevaluated
          • +
          +
        • Working with Multiple Values
        • + +
        +
      +
    • Numbers
    • + +
    • Conses
    • +
        +
      • List Membership
      • +
          +
        • cl:member - [Function] - test for membership in lists and sub-elements
        • +
        • cl:member-if - [Function] - search for the first element matching a predicate
        • +
        • cl:member-if-not - [Function] - search for the first element not matching a predicate
        • +
        +
      • Non-destructive Removal
      • +
          +
        • cl:remove
        • +
        • cl:remove-if
        • +
        • cl:remove-if-not
        • +
        +
      • Destructive Removal = Deletion
      • +
          +
        • cl:delete
        • +
        • cl:delete-if
        • +
        • cl:delete-if-not
        • +
        +
      • Lists as Sets
      • +
          +
        • cl:pushnew - [Macro] -
        • +
        • cl:union - [Function]
        • +
        • cl:intersection - [Function]
        • +
        • cl:set-difference - [Function]
        • +
        • cl:set-exclusive-or - [Function]
        • +
        • cl:subsetp - [Function]
        • +
        +
      +
    • Sequences
    • +
        +
      • Subsequences
      • +
          +
        • cl:subseq - subsequences of lists, strings, or arrays
        • +
        +
      • Properties of elements in sequences:
      • +
          +
        • cl:find
        • +
        • cl:count
        • +
        • cl:position
        • +
        +
      • Predicates for testing sequences:
      • +
          +
        • cl:every
        • +
        • cl:some
        • +
        • cl:notevery
        • +
        • cl:notany
        • +
        +
      • Functions to modify sequences:
      • +
          +
        • cl:map
        • +
        +
      +
    + + diff --git a/docsrc/xlisp/xlisp-doc/examples/files.htm b/docsrc/xlisp/xlisp-doc/examples/files.htm new file mode 100644 index 0000000..a43f4fe --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/files.htm @@ -0,0 +1,459 @@ + + +Files and Directories + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Files and Directories

    + +
    + +
      +
    • Interactive Functions
    • +
        +
      • pwd - returns the current working directory
      • +
      • cd - changes the current working directory
      • +
      +
    • Testing Files and Directories
    • + +
    • Testing Filenames
    • + +
    • System Environment Variables
    • + +
    + + + +
    + +

    pwd

    + +
    + +

    The 'pwd' function returns the current working directory:

    + +
    +(defun pwd ()
    +  (setdir "."))
    +
    + +

    Ok, this function does not belong to the masterpieces of computer +science, but (pwd) is much easier to remember than (setdir +".").

    + +

      Back to top

    + + + +
    + +

    cd

    + +
    + +

    The 'cd' function changes the current working directory. The +directory name must be given as a string:

    + +
    +(defun cd (string)
    +  (cond ((not (stringp string))
    +         (error "argument must be a string" string))
    +        ((string= "." string)
    +         (setdir "."))
    +        (t
    +         (let ((orig-dir (setdir "."))
    +               (new-dir  (setdir string)))
    +           (when (string/= orig-dir new-dir)
    +             new-dir)))))
    +
    + +

    Possible actions and return values are:

    + +
      + +
    • It the argument is not a string, then an error will be +raised.

    • + +
    • If the directory name is ".", then the name of the current +working directory is returned as a string. This is the same effect as if the +directory has been changed to itself.

    • + +
    • If the directory has successfully been changed to the given +directory, then the name of the new working directory is returned as a +string.

    • + +
    • If the given directory has not been found, then NIL [= +false] is returned.

    • + +
    + +

      Back to top

    + + + +
    + +

    directory-exists-p

    + +
    + +

    The 'directory-exists-p' function tests if a directory +exists. The directory name must be given as a string:

    + +
    +(defun directory-exists-p (string)
    +  (cond ((not (stringp string))
    +         (error "argument must be a string" string))
    +        ((string= "." string)
    +         (setdir "."))
    +        (t
    +         (let ((orig-dir (setdir "."))
    +               (new-dir  (setdir string)))
    +           (when (string/= orig-dir new-dir)
    +             (setdir orig-dir)
    +             new-dir)))))
    +
    + +

    Possible actions and return values are:

    + +
      + +
    • It the argument is not a string, then an error will be +raised.

    • + +
    • If the directory name is ".", then the absolute name of the +current working directory is returned as a string. This is not +a very useful test, but makes the return values consistent.

    • + +
    • If the directory has been found, then the absolute name of the +directory is returned as a string.

    • + +
    • If the directory has not been found, then NIL [= false] +is returned.

    • + +
    + +

    The 'directory-exists-p' function is nearly the same as the +cd function above. The only difference is +that the working directory will automatically be changed back to the initial +directory.

    + +

    On Unix, with soft-links, the absolute name of the target +directory [i.e. not the name of the link-file +itself, but the name of the directory the link points to] is +returned.

    + +

    + +

    Implementation Notes

    + +

    The Nyquist 'setdir' function always returns absolute directory names, +even if a relative directory name has been given as a string by the user. +That's why it's not possible to reliably compare the return value of +(setdir string) directly with 'string'. Instead the absolute +name of the initial working directory, returned by (setdir +"."), is compared to the absolute name, returned when +(setdir string) tries to change the directory. If +both return values are the same, then (setdir string) +has failed because the directory has not been found.

    + +

    If the directory string is ".", then this trick doesn't work, +because the initial directory is the same as the target directory, so even +if the directory has 'successfully' been changed to itself, both return +values still would be the same. This is one of the reasons why "." +has a separate 'cond' clause. The other reason is of course that it makes +not really much sense to change a directory to itself, that's why we save +the work and just return the absolute name of the current working +directory.

    + +

    + +

      Back to top

    + + + +
    + +

    file-exists-p

    + +
    + +

    The 'file-exists-p' function tests if a file exists. +The file name must be given as a string:

    + +
    +(defun file-exists-p (string)
    +  (if (not (stringp string))
    +      (error "argument must be a string" string)
    +      (unless (directory-exists-p string)
    +        (let (file-stream)
    +          (unwind-protect
    +            (setq file-stream (open string))
    +            (when file-stream (close file-stream)))
    +          (when file-stream string)))))
    +
    + +

    On Unix systems a directory is a special kind of file, so on Unix the +XLisp 'open' function can open directories, too. That's why we first must +make sure that no directory exists with the same name as the file that we +are looking for.

    + +

      Back to top

    + + + +
    + +

    filename-exists-p

    + +
    + +
    +(defun filename-exists-p (string)
    +  (if (not (stringp string))
    +      (error "argument must be a string" string)
    +      (or (directory-exists-p string)
    +          (file-exists-p string)))
    +
    + +

      Back to top

    + + + +
    + +

    absolute-filename-p

    + +
    + +

    The 'absolute-filename-p' function tests if a string is an absolute file +or directory name:

    + +
    +(defun absolute-filename-p (string)
    +  (if (not (stringp string))
    +      (error "argument must be a string" string)
    +      (let ((end (length string)))
    +        (when (or (and (>= end 1)  ; Unix "/..."
    +                       (char= #\/ (char string 0)))
    +                  (and (>= end 3)  ; Windows "[a-zA-Z]:[\/]..."
    +                       (let ((char (char string 0)))
    +                         ;; upper- or lowercase character a-z, A-Z
    +                         (and (> (char-code (char-downcase char)) 96)
    +                              (< (char-code (char-downcase char)) 123)))
    +                       (char= #\: (char string 1))
    +                       (let ((char (char string 2)))
    +                         (or (char= #\\ char)
    +                             (char= #\/ char)))))
    +          string))))
    +
    + + +

    Note that it is only tested whether the beginning of the string +matches the beginning of an absolute file or directory name. It +is not tested whether the string reperesents a meaningful name.

    + +

      Back to top

    + + + +
    + +

    System Environment Variables

    + + + +
    + +

    get-env

    + +
    + +

    [This function works only with Audacity 1.3.13 and +above.]

    + +

    + +
    + +

    (get-env "environment-variable")

    + + + + +
    + +

    + +

      Back to top

    + + + +
    + +

    windows-p

    + +
    + +

    [This function works only with Audacity 1.3.13 and +above.]

    + +

    The 'windows-p' function tests if the underlying operation +system is a Microsoft Windows[tm] system:

    + +
    +(defun windows-p ()
    +  (let* ((home (let ((drive (get-env "HOMEDRIVE"))
    +                     (path  (get-env "HOMEPATH")))
    +                 (if (and drive path)
    +                     (strcat drive path)
    +                     (get-env "UserProfile"))))
    +         (path (get-env "PATH")))
    +    (when home  ; if HOMEDRIVE + HOMEPATH or UserProfile exist
    +      (if path  ; search for Windows :\ drive-letter patterns
    +          (string-search ":\\" path)  
    +          (error "no PATH environment variable found")))))
    +
    + +

    Nquist has a *file-separator* variable, that could be used +much easier to detect the operation system:

    + +
    +(defun windows-p ()
    +  (char= *file-separator* #\\))
    +
    + +

      Back to top

    + + + +
    + +

    user-home-directory

    + +
    + +

    [This function works only with Audacity 1.3.13 and +above.]

    + +

    The 'user-home-directory' function returns the path to the +user's home directory on Linux, Mac, and Windows:

    + +
    +(defun user-home-directory ()
    +  (or (get-env "HOME")
    +      (let ((drive (get-env "HOMEDRIVE"))
    +            (path  (get-env "HOMEPATH")))
    +        (when (and drive path)
    +          (strcat drive path)))
    +      (get-env "UserProfile")))
    +
    + +

    If the user's home directory could be identified, then the path to the +home directory is returned as a string. If the user's home +directory could not be identified, then NIL [= false] is +returned.

    + +

    Examples:

    + +
    +(user-home-directory)  => "/home/edgar"                        ; Linux
    +(user-home-directory)  => "C:\\Documents and Settings\\Edgar"  ; Windows
    +
    + +

    On Windows there is no HOME variable defined by Windows itself, but most +programs will respect a HOME variable, if one had been defined by the user. +This means that on Windows, if a HOME variable exists, the HOME variable +will be used instead of HOMEDRIVE and HOMEPATH or 'UserProfile'.

    + +

      Back to top

    + + + +
    + +

    expand-tilde

    + +
    + +

    [This function works only with Audacity 1.3.13 and +above.]

    + +
    +(defun expand-filename (string)
    +  (cond ((not (stringp string))
    +         (error "argument must be a string" string))
    +        ((and (> (length string) 1)
    +                 (char= #\~ (char string 0))
    +                 (or (char= #\/ (char string 1))
    +                     (char= #\\ (char string 1))))
    +         (strcat (user-home-directory)
    +                 (subseq string 1)))
    +        (t string)))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + + diff --git a/docsrc/xlisp/xlisp-doc/examples/hash-tables.htm b/docsrc/xlisp/xlisp-doc/examples/hash-tables.htm new file mode 100644 index 0000000..3a74ffa --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/hash-tables.htm @@ -0,0 +1,496 @@ + + +Hash Tables + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Hash Tables

    + +
    + +

    The internal XLISP 'hash' function from 'xlsym.c':

    + +
    +/* hash - hash a symbol name string */
    +int hash(char *str, int len)
    +{
    +    int i;
    +    for (i = 0; *str; )
    +        i = (i << 2) ^ *str++;
    +    i %= len;
    +    return (i < 0 ? -i : i);
    +}
    +
    + +

    In XLISP this would look like:

    + +
    +(defun lisp-hash (string table-size)
    +  (let ((i 0))
    +    (dotimes (index (length string))
    +      (setq i (logxor (bsh i 2) (char-code (char string index)))))
    +    (setq i (rem i table-size))
    +    (if (minusp i) (- i) i)))
    +
    + +

    A hash function is a kind of random +number generator, where the same input always produces the same output +number. The XLISP hash +function computes equally distributed integer numbers in a given range from +the characters of an input string.

    + +

    A very simple example:

    + +
      + +
    1. We want to store 4 strings in 2 lists, +stored in 2 array elements:

      + +
      +> (setq my-array (make-array 2))
      +#(NIL NIL)  ; NIL NIL = two empty lists
      +
      + +

      If the array index is computed by the +hash function, then the equally +distributed numbers make sure that every list will contain approximately +the same number of strings:

      + +
      +> (dolist (string '("a" "b" "c" "d") my-array)
      +    (push string (aref my-array (hash string (length my-array)))))
      +#(("d" "b") ("c" "a"))
      +
      + +

      The order of the strings in the array was computed by the +hash function, it is not the same order +as given to dolist.

    2. + +
    3. If we now search for a string in the lists then the +hash function will tell us the number of +the array element with the list containing the string because the same input +string to the hash function always +produces the same output number, as long as the same +'table-size' [the same number of array elements] is used:

      + +
      +> (dolist (string '("a" "b" "c" "d"))
      +    (format t "~s = ~s~%" string
      +              (aref my-array (hash string (length my-array)))))
      +"a" = ("c" "a")
      +"b" = ("d" "b")
      +"c" = ("c" "a")
      +"d" = ("d" "b")
      +NIL
      +
      + +

      The hash function will always find +the correct list as long as the number of array elements has not +changed.

    4. + +
    + +

    The two main tasks of the hash +function are:

    + +
      + +
    1. Make sure that all lists contain approximately the same number of +elements, independent from the characters in the input strings, no matter if +the strings are very similar or completely different. With the +hash function it will nearly never +happen that one list contains all strings while all other lists are +empty.

    2. + +
    3. With the same 'name' and 'table-size' arguments the +hash function will always return exactly +the same integer number, so a string can always be found no matter in what +order the strings are stored in the lists of the array.

    4. + +
    + +

    Now we can find strings stored in lists, but we want to store and find +arbitrary things. Therefore we replace the ordinary lists with association +lists:

    + +
    +> (setq my-array (make-array 2))
    +#(() ())
    +
    +> (dolist (a-cons '(("a" . 1) ("b" . 2) ("c" . 3) ("d" . 4)) my-array)
    +    (push a-cons (aref my-array (hash (car a-cons) (length my-array)))))
    +#((("d" . 4) ("b" . 2)) (("c" . 3) ("a" . 1)))
    +
    + +

    We now have an array like this:

    + +

    + + + + + + + + + + + + + + + + + + + + + + +
    Array 
      0 Association List 1 → (("d" . 4) ("b" . 2))
      1 Association List 2 → (("c" . 3) ("a" . 1))

    + +

    The association lists give the flexibility to store an arbitrary number +of key/value pairs, we are not limited by the fixed number of +array elements, while the array together with the +hash function gives much more speed than +a single association list if we want to manage a big number of + key/value pairs.

    + +

    With a big number of key/value pairs it is faster to keep them in many +small association lists than in one single big list. Arrays +provide random access, where every element can be accessed in the same time, +while a list can only be searched from the beginning up to the matching +element. The longer the list, the slower the search +becomes.

    + +

    With the hash function we find the +association list containing the key:

    + +
    +> (dolist (key '("a" "b" "c" "d"))
    +    (format t "~s = ~s~%" key
    +              (aref my-array (hash key (length my-array)))))
    +"a" = (("c" . 3) ("a" . 1))
    +"b" = (("d" . 4) ("b" . 2))
    +"c" = (("c" . 3) ("a" . 1))
    +"d" = (("d" . 4) ("b" . 2))
    +NIL
    +
    + +

    With the assoc function we find the +key/value pair:

    + +
    +> (dolist (key '("a" "b" "c" "d"))
    +    (format t "~s = ~s~%" key
    +              (assoc key (aref my-array (hash key (length my-array)))
    +                     :test #'equal)))
    +"a" = ("a" . 1)
    +"b" = ("b" . 2)
    +"c" = ("c" . 3)
    +"d" = ("d" . 4)
    +NIL
    +
    + +

    With the cdr function we get the +value:

    + +
    +> (dolist (key '("a" "b" "c" "d"))
    +    (format t "~s = ~s~%" key
    +              (cdr (assoc key (aref my-array (hash key (length my-array)))
    +                          :test #'equal))))
    +"a" = 1
    +"b" = 2
    +"c" = 3
    +"d" = 4
    +NIL
    +
    + +

    And now we have our first working hash-table.

    + +

    But we still have one problem. The +hash function works only with +symbols or strings, while assoc can +also work with numbers, strings and even lists as 'key' argument. To +make our hash-table work with all types +assoc can handle, we must make the +hash function happy and convert the +'key' argument with format into a +string before computing the hash index:

    + +
    +> (setq my-array (make-array 2))
    +#(() ())
    +
    +> (dolist (a-cons '((#\x . 1) ((y z) . 2) (12 . 3) (6.5 . 4)) my-array)
    +    (push a-cons (aref my-array (hash (format nil "~s" (car a-cons))
    +                                      (length my-array)))))
    +#(((12 . 3) (#\x . 1)) ((6.5 . 4) ((Y Z) . 2)))
    +
    +> (dolist (key '(#\x (y z) 12 6.5))
    +    (format t "~s = ~s~%" key
    +              (cdr (assoc key (aref my-array (hash (format nil "~s" key)
    +                                                   (length my-array)))
    +                          :test #'equal))))
    +#\x = 1
    +(Y Z) = 2
    +12 = 3
    +6.5 = 4
    +NIL
    +
    + +

    Wonderful.

    + +

    A final quirk still needs to be solved. Maybe you have noticed the :test +argument to assoc. Like with all Lisp +functions providing :test arguments, the +assoc :test defaults to +eql [because +eq is unreliable with numbers, and +eql is faster +than equal], but +eql doesn't work with +floating-point numbers, strings and lists, so we had to +use equal.

    + +

    The typical Lisp solution is to provide a :test argument to the +'make-hash-table' function, so the programmer can choose which function to +use. The :test argument to 'make-hash-table' becomes a property +of the hash-table itself, so the :test only needs to be given +once, at the time when the hash-table is created, and not every +time the hash-table is accessed afterwards.

    + +

    We have the problem that hash-tables are no +built-in XLISP data type and we want use +make-hash-table in the same way +as make-array:

    + +
    +(setq my-hash-table (make-hash-table size :test #'equal))
    +
    + +

    Here the make-hash-table function has no access to the property list of +the 'my-hash-table' symbol, so the only solution is to make the +:test function become part of the hash-table itself:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Array 
      0 Test Function → the :test argument to + assoc
      1 Association List 1 → ((key1 . value1) + ... (keyN . valueN))
      2 Association List 2 → ((key1 . value1) + ... (keyN . valueN))
      3 Association List 3 → ((key1 . value1) + ... (keyN . valueN))
    ... 
      n Association List n → ((key1 . value1) + ... (keyN . valueN))

    + +

    This is the final layout of our hash-tables, so we can start +to implement the hash-table functions.

    + +

      Back to top

    + + + +
    + +

    make-hash-table

    + +
    + +
    +(defun make-hash-table (size &optional (test #'eql))
    +  (and (< size 1) (error "hash-table minimum size is 1" size))
    +  (let ((hash-table (make-array (1+ size))))
    +    (setf (aref hash-table 0) test)
    +    hash-table))
    +
    +(defun gethash (key hash-table)
    +  (let* ((size   (1- (length hash-table)))
    +         (index  (1+ (hash (format nil "~s" key) size)))
    +         (a-list (aref hash-table index))
    +         (test   (aref hash-table 0)))
    +    (cdr (assoc key a-list :test test))))
    +
    +(defun puthash (key value hash-table)
    +  (let* ((size   (1- (length hash-table)))
    +         (index  (1+ (hash (format nil "~s" key) size)))
    +         (a-list (aref hash-table index))
    +         (test   (aref hash-table 0))
    +         (a-cons (assoc key a-list :test test)))
    +    (setf (aref hash-table index)
    +          (cons (cons key value)
    +                (if a-cons
    +                    (remove-if #'(lambda (x)
    +                                   (funcall test key (car x)))
    +                               a-list)
    +                    a-list)))))
    +
    +(defun remhash (key hash-table)
    +  (let* ((size   (1- (length hash-table)))
    +         (index  (1+ (hash (format nil "~s" key) size)))
    +         (a-list (aref hash-table index))
    +         (test   (aref hash-table 0))
    +         (a-cons (assoc key a-list :test test)))
    +    (and a-cons
    +         (setf (aref hash-table index)
    +               (remove-if #'(lambda (x)
    +                              (funcall test key (car x)))
    +                          a-list)))
    +    a-cons))
    +
    +(defun clrhash (hash-table)
    +  (let ((size (1- (length hash-table))))
    +    (do ((index 1 (1+ index)))
    +        ((> index size))
    +      (setf (aref hash-table index) nil))
    +    hash-table))
    +
    +(defun hash-table-p (expr)
    +  (and (arrayp expr)             ; expression is an array
    +       (> (length expr) 1)       ; with more than one elements
    +       (fboundp (aref expr 0))   ; first element is a function
    +       (let ((size (1- (length expr))))   ; all other
    +         (do ((index 1 (1+ index)))       ; elements are lists
    +             ((or (> index size)
    +                  (not (listp (aref expr index))))
    +              (> index size))))))
    +
    +(defun hash-table-count (hash-table)
    +  (let ((size (1- (length hash-table)))
    +        (entries 0))
    +    (do ((index 1 (1+ index)))
    +        ((> index size))
    +      (setf entries (+ entries (length (aref hash-table index)))))
    +    entries))
    +
    +(defun hash-table-size (hash-table)
    +  (1- (length hash-table)))
    +
    +(defun hash-table-test (hash-table)
    +  (aref hash-table 0))
    +
    +(defun print-hash-table (hash-table)
    +  (if (not (arrayp hash-table))
    +      (format t ";; Not an array: ~s~%" hash-table)
    +      (dotimes (index (length hash-table))
    +        (let ((element (aref hash-table index)))
    +          (cond ((not (listp element))
    +                 (format t ";; array element ~a: ~s~%" index element))
    +                ((null element)
    +                 (format t ";; bucket ~a: ()~%" index))
    +                (t
    +                 (format t ";; bucket ~a:~%" index)
    +                 (let ((entry-counter 1))
    +                   (dolist (entry element)
    +                     (format t ";; ~a.~a: ~s~%" index entry-counter entry)
    +                     (incf entry-counter)))))))))
    +
    + + + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + + diff --git a/docsrc/xlisp/xlisp-doc/examples/hexadecimal.htm b/docsrc/xlisp/xlisp-doc/examples/hexadecimal.htm new file mode 100644 index 0000000..4b483b0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/hexadecimal.htm @@ -0,0 +1,151 @@ + + +Hexadecimal Integer Numbers + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Hexadecimal Integer Numbers

    + +
    + +

    XLISP provides the #x +read-macro for hexadecimal numbers:

    + +
    +#x0  => 0        #x8  => 8         #x10  => 16
    +#x1  => 1        #x9  => 9         #x11  => 17
    +#x2  => 2        #xa  => 10        #x12  => 18
    +#x3  => 3        #xb  => 11        #x13  => 19
    +#x4  => 4        #xc  => 12        #x14  => 20
    +#x5  => 5        #xd  => 13        #x15  => 21
    +#x6  => 6        #xe  => 14        #x16  => 22
    +#x7  => 7        #xf  => 15        #x17  => 23
    +
    + +

    + +
    +
    (hex-string integer [all])
    +
    integer - an integer expression
    +all - a boolean expression
    +returns - the integer in hexadecimal form as string
    +
    + +

    + +
    +(defun hex-string (integer &optional all)
    +  (if (integerp integer)
    +      (let ((fmt (if all
    +                     (or (dolist (bits '(16 32 64 128) nil)
    +                           (let ((fixnum (round (expt 2.0 (1- bits)))))
    +                             (and (plusp (1- fixnum))
    +                                  (minusp fixnum)
    +                                  (return (format nil "%.~ax" (/ bits 4))))))
    +                         (error "integer limit not found"))
    +                     "%x")))
    +        (progv '(*integer-format*) (list fmt)
    +          (format nil "~a" integer)))
    +      (error "not an integer" integer)))
    +
    + +

    The 'hex-string' function converts the 'integer' argument +into hexadecimal form and returns is as a string. If the +optional 'all' argument is not given or +NIL, leading zeros are not included in +the string. If the optional 'all' argument is +non-NIL, all digits of the +internal representation of the 'integer' argument, including leading zeros, +are contained in the string. This is useful for debugging integer overflow +and bit-wise functions.

    + +

    + +
    +
    (hex integer [all])
    +
    integer - an integer expression
    +all - a boolean expression
    +prints - the integer in hexadecimal form
    +returns - the integer argument
    +
    + +

    + +
    +(defun hex (integer &optional all)
    +  (if (integerp integer)
    +      (format t "#x~a~%" (hex-string integer all))
    +      (format t ";; not an integer~%"))
    +  integer)
    +
    + +

    The 'hex' function prints the 'integer' argument in hexadecimal form on +the screen. Together with the +#x read-macro +this can be used for interactive hexadecimal computations.

    + +
    +> (hex 12345678)
    +#xbc614e
    +12345678
    +
    +> (hex (+ #x1f #xa3))
    +#xc2
    +194
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/lists.htm b/docsrc/xlisp/xlisp-doc/examples/lists.htm new file mode 100644 index 0000000..34f9053 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/lists.htm @@ -0,0 +1,580 @@ + + +Lists + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Lists

    + +
    + +

    Lists are also Sequences.

    + + + + + +
    + +

    print-cons

    + +
    + +
    +(defun print-cons (item)
    +  (labels ((cons-string (item)
    +             (case (type-of item)
    +               (array      (let ((end (length item))
    +                                 (result ""))
    +                             (dotimes (index end)
    +                               (let ((string (cons-string (aref item index))))
    +                                 (setq result 
    +                                   (if (eql 0 index)
    +                                       (format nil "#(~a" string)
    +                                       (format nil "~a ~a" result string)))))
    +                             (format nil "~a)" result)))
    +               (character  (format nil "~s" item))
    +               (cons       (format nil "(~a . ~a)"
    +                                   (cons-string (car item))
    +                                   (cons-string (cdr item))))
    +               (string     (format nil "\"~a\"" item))
    +               (t          item))))
    +    (format t "~a~%" (cons-string item))
    +    item))
    +
    + +

    Examples:

    + +
    +> (print-cons '(1 2 3))
    +(1 . (2 . (3 . NIL)))
    +(1 2 3)
    +
    + +

    The 'print-cons' function is useful for debugging association lists, +where print often fails to display the +correct layout:

    + +
    +> (print-cons (cons '((1 . 2) (3 . 4)) '((a . b) (c . d))))
    +(((1 . 2) . ((3 . 4) . NIL)) . ((A . B) . ((C . D) . NIL)))
    +(((1 . 2) (3 . 4)) (A . B) (C . D))  ; <- output of PRINT
    +
    + +

    Do not think that print is bad, it +saves you from reading things like this:

    + +
    +> (print-cons '(defun hello-world ()
    +                 (print "Hello World!")))
    +(DEFUN . (HELLO-WORLD . (NIL . ((PRINT . ("Hello World!" . NIL)) . NIL))))
    +(DEFUN HELLO-WORLD NIL (PRINT "Hello World!"))  ; <- output of PRINT
    +
    + +

    Test this if you don't believe:

    + +
    +> (DEFUN . (HELLO-WORLD . (NIL . ((PRINT . ("Hello World!" . NIL)) . NIL))))
    +HELLO-WORLD
    +
    +> (hello-world)
    +"Hello World!"
    +
    + + +

      Back to top

    + + + +
    + +

    dolist*

    + +
    + +

    A dolist version that can iterate +dotted lists:

    + +
    +(defmacro dolist* (fargs &rest body)
    +  (let ((list (gensym)))
    +    `(let ((,list ,(second fargs)))
    +       (if (not (listp ,list))
    +           (error "not a list" ,list)
    +           (do ((,(first fargs) (first ,list)
    +                                (if (consp ,list) (first ,list) ,list)))
    +               ((null ,list))
    +             (setq ,list (and (consp ,list) (rest ,list)))
    +             ,@body)))))
    +
    + +
    +(dolist  (i '(1 2 3)) (print i))    ; prints 1 2 3
    +(dolist* (i '(1 2 3)) (print i))    ; prints 1 2 3
    +
    +(dolist  (i '(1 2 . 3)) (print i))  ; prints 1 2
    +(dolist* (i '(1 2 . 3)) (print i))  ; prints 1 2 3
    +
    + +

      Back to top

    + + + +
    + +

    cl:member

    + +
    + +

    XLISP already has the member +function to for search elements in lists:

    + +

    + +
    +
    (member expr list [{:test | :test-not} test])
    +
    expr - the expression to find [an atom or a list]
    +list - the list to search
    +test - optional test function, default is eql
    +returns - the remainder of the list starting with expr
    +
    + +

    + +The 'cl:member' function provides an additional :key argument for +accessing sub-elements in the list: + +

    + +
    +
    (cl:member expr list [{:test | :test-not} test :key key])
    +
    expr - the expression to find [an atom or a list]
    +list - the list to search
    +test - an optional test function, default is eql
    +key - an optional accessor function for sub-elements in the list
    +returns - the remainder of the list starting with expr
    +
    + +

    + +
    +(defun cl:member (expr list &key test test-not key)
    +  (and test test-not (error "both :TEST and :TEST-NOT specified"))
    +  (if key
    +      (cond (test
    +             (member expr list
    +               :test #'(lambda (x y)
    +                         (funcall test x (funcall key y)))))
    +            (test-not
    +             (member expr list
    +               :test-not #'(lambda (x y)
    +                             (funcall test-not x (funcall key y)))))
    +            (t (member expr list
    +                 :test #'(lambda (x y)
    +                           (eql x (funcall key y))))))
    +      (cond (test     (member expr list :test test))
    +            (test-not (member expr list :test-not test-not))
    +            (t        (member expr list)))))
    +
    + +

    Test if the number 4 matches the first or the second element in several +sublists:

    + +
    +(cl:member 4 '((1 2) (3 4) (5 6)) :key #'first)   => NIL            ; no match
    +(cl:member 4 '((1 2) (3 4) (5 6)) :key #'second)  => ((3 4) (5 6))  ; number found
    +
    + +

    Subtle differences between XLISP and Common Lisp:

    + +
    +;; Lisp Form              XLISP         Common Lisp
    +(member 1 '(1 2 . 3))  => (1 2 . 3)  => (1 2 . 3)
    +(member 2 '(1 2 . 3))  => (2 . 3)    => (2 . 3)
    +(member 3 '(1 2 . 3))  => NIL        => error: not a proper list
    +
    + + +

    Here is a 'cl:member' version that behaves error-conform to +Common Lisp but produces an unintelligible backtrace in case of +Lisp errors. I also have found no way how to macroexpand +macrolets, so debugging this function is a real pain.

    + +
    +(defun cl:member (expr list &key test test-not key)
    +  (and test test-not (error "both :TEST and :TEST-NOT specified"))
    +  (macrolet ((internal-loop (list)
    +    `(do ()
    +         ;; termination test
    +         ((or (not (consp list))
    +              ,(if key
    +                   (cond (test     `(funcall ,test ,expr (funcall ,key (car list))))
    +                         (test-not `(not (funcall ,test ,expr (funcall ,key (car list)))))
    +                         (t        `(eql ,expr (funcall ,key (car list)))))
    +                   (cond (test     `(funcall ,test ,expr (car list)))
    +                         (test-not `(not (funcall ,test ,expr (car list))))
    +                         (t        `(eql ,expr (car list))))))
    +          ;; return value
    +          (if (not (listp list))
    +              (error "a proper list must not end with" list)
    +              list))
    +        ;; body
    +        (setq list (cdr list)))))
    +     (internal-loop list)))
    +
    + +

      Back to top

    + + + +
    + +

    cl:member-if

    + +
    + +

    Here are two functions to search for elements that satisfy a given +predicate:

    + +

    + +
    +
    (member-if predicate list [:key key])
    +
    predicate - a test function with one argument
    +list - the list to search
    +key - optional accessor function for sub-elements in the list
    +returns - the remainder of the list starting with the first matching element
    +
    + +

    + +
    +(defun cl:member-if-not (predicate list &key key)
    +  (member nil list :test (if key
    +                             #'(lambda (x y)
    +                                 (funcall predicate (funcall key y)))
    +                             #'(lambda (x y)
    +                                 (funcall predicate y)))))))
    +
    + +

      Back to top

    + + + +
    + +

    cl:member-if-not

    + +
    + +

    + +
    +
    (member-if-not predicate list [:key key])
    +
    predicate - a test function with one argument
    +list - the list to search
    +key - optional accessor function for sub-elements in the list
    +returns - the remainder of the list starting with the first non-matching element
    +
    + +

    + +
    +(defun cl:member-if-not (predicate list &key key)
    +  (member nil list :test-not (if key
    +                                 #'(lambda (x y)
    +                                     (funcall predicate (funcall key y)))
    +                                 #'(lambda (x y)
    +                                     (funcall predicate y)))))))
    +
    + +

    Examples:

    + +
    +(cl:member-if     #'plusp  '(-2 -1 0 1 2))  => (1 2)    ; 1 = first positive number
    +(cl:member-if-not #'minusp '(-2 -1 0 1 2))  => (0 1 2)  ; 0 = first non-negative number
    +
    + +

    More test functions see Predicates.

    + +

      Back to top

    + + + +
    + +

    cl:list:accessor

    + +
    + +

    The 'lists as sets' functions have common :test, :test-not +and :key parameters:

    + +
    +(defmacro cl:list:accessor (test test-not &optional key)
    +  (if (and test test-not)
    +      (error "both :TEST and :TEST-NOT specified"))
    +      (if key
    +          (cond (test     `(lambda (x y)
    +                             (funcall ,test (funcall ,key x)
    +                                            (funcall ,key y))))
    +                (test-not `(lambda (x y)
    +                             (not (funcall ,test-not (funcall ,key x)
    +                                                     (funcall ,key y)))))
    +                (t        `(lambda (x y)
    +                             (eql (funcall ,key x) (funcall ,key y)))))
    +          (cond (test     `(lambda (x y)
    +                             (funcall ,test x y)))
    +                (test-not `(lambda (x y)
    +                             (not (funcall ,test-not x y))))
    +                (t        `(lambda (x y)
    +                             (eql x y))))))
    +
    + +

      Back to top

    + + + +
    + +

    cl:pushnew

    + +
    + +

      Back to top

    + + + +
    + +

    cl:union

    + +
    + + +

    + +
    +
    (union list1 list2 [{:test | :test-not} test :key key])
    +
    listN - a list of symbols or numbers
    +returns - the union of list1 and list2
    +
    + +

    + +
    +(defun union (a b)
    +  (let (result)
    +    (dolist (element a)
    +      (unless (member element result)
    +        (push element result)))
    +    (dolist (element b)
    +      (unless (member element result)
    +        (push element result)))
    +    result))
    +
    + +

    The 'cl:union' function returns a list that contains every element that +occurs in either 'list1' or 'list2'.

    + +

      Back to top

    + + + +
    + +

    cl:intersection

    + +
    + +

    + +
    +
    (intersection list1 list2 [{:test | :test-not} test :key key])
    +
    listN - a list of symbols or numbers
    +returns - the intersection of list1 and list2
    +
    + +

    + +
    +(defun intersection (a b)
    +  (let (result)
    +    (dolist (element a)
    +      (when (member element b)
    +        (push element result)))
    +    result))
    +
    + +

      Back to top

    + + + +
    + +

    cl:set-difference

    + +
    + +

    + +
    +
    (set-difference list1 list2)
    +
    listN - a list of symbols or numbers
    +returns - the set-difference of list1 and list2
    +
    + +

    + +
    +(defun set-difference (a b)
    +  (remove-if #'(lambda (element)
    +                 (member element b))
    +             a))
    +
    + +

    An element of list1 appears in the result if and only if it does not +match any element of list2.

    + +
    +(set-difference '(1 2 3) '(2 3 4)) => (1)
    +
    + +

      Back to top

    + + + +
    + +

    cl:set-exclusive-or

    + +
    + +

    The result contains precisely those elements of list1 and list2 that +appear in no matching pair.

    + +
    +(set-exclusive-or '(1 2 3) '(2 3 4)) => (1 4)
    +
    + +

      Back to top

    + + + +
    + +

    cl:subsetp

    + +
    + +

    + +
    +
    (subsetp list1 list2)
    +
    listN - a list of symbols or numbers
    +returns -  T  if list1 is a subset of list2, NIL otherwise
    +
    + +

    + +
    +(defun subsetp (a b)
    +  (let ((result t))
    +    (dolist (element a)
    +      (when (not (member element b)
    +        (setf result nil)
    +        (return))))
    +    result))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + + diff --git a/docsrc/xlisp/xlisp-doc/examples/macros.htm b/docsrc/xlisp/xlisp-doc/examples/macros.htm new file mode 100644 index 0000000..1781381 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/macros.htm @@ -0,0 +1,302 @@ + + +Macros + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Macro Programming

    + +
    + + + +

    + +

    Note: The best book for Lisp macro programming is Paul +Graham's 'On Lisp', available for free under:

    + + + +

    + + + +
    + +

    with-unique-names

    + +
    + +

    See http://www.cliki.net/WITH-UNIQUE-NAMES. This macro also appears in +Chapter 11 of Paul Graham's +On Lisp +under the name 'with-gensyms'.

    + +

    + +
    +
    (with-unique-names (symbols) body)
    +
    symbols - a list of Lisp symbols, representing variable names
    +body - some Lisp code to execute
    +returns - the body with all symbols bound to different +gensyms
    +
    + +

    + +

    The 'with-unique-names' macro helps to avoid name clashes in +Lisp macros.

    + +
    +(defmacro with-unique-names (symbols &rest body)
    +  `(let ,(mapcar #'(lambda (x) `(,x (gensym))) symbols) ,@body))
    +
    + +

    The 'with-unique-names' macro belongs to the category of +write-only code. No matter how you write it, it's +nearly impossible to understand its meaning by reading the macro definition. +It's easier to understand if you look at the macro +expansion:

    + +
    +> (macroexpand-1 '(with-unique-names (a b c)
    +                    `(let ((,a 1) (,b 2) (,c 3))
    +                       (list ,a ,b ,c))))
    +
    +(let ((a (gensym)) (b (gensym)) (c (gensym)))
    +  `(let ((,a 1) (,b 2) (,c 3))
    +     (list ,a ,b ,c)))
    +
    + +

    This translates in practice to the following idea:

    + +
    +(let ((a (gensym)) (b (gensym)) (c (gensym)))  ; outside the expansion
    +  `(let ((gensym1 1) (gensym2 2) (gensym3 3))  ; inside the expansion
    +     (list gensym1 gensym2 gensym3)))
    +
    + +

    The variable names 'a', 'b', and 'c' have been replaced inside the macro +expansion by three gensyms. This way a +variable name inside the macro expansion cannot accidentally collide with a +variable of the same name in the environment of the macro's expansion like +shown here:

    + +
    +(defmacro print-macro (x)         ; bad example
    +  `(let ((macro-var 'macro))
    +     (print ,x)))
    +
    +> (let ((local-var 'let))         ; this works
    +    (print local-var)
    +    (print-macro local-var))
    +LET  ; printed by PRINT
    +LET  ; printed by PRINT-MACRO
    +
    +> (let ((macro-var 'let))         ; this doesn't
    +    (print macro-var)
    +    (print-macro macro-var))
    +LET    ; printed by PRINT
    +MACRO  ; printed by PRINT-MACRO
    +
    + +

    The reason for this behaviour is that the 'print-macro' +expands to:

    + +
    +> (let ((local-var 'let))         ; this works
    +    (print local-var)
    +    (let ((macro-var 'macro))
    +      (print local-var)))
    +LET  ; LOCAL-VAR inside the first LET
    +LET  ; LOCAL-VAR inside the second LET
    +
    +> (let ((macro-var 'let))         ; this doesn't
    +    (print macro-var)
    +    (let ((macro-var 'macro))
    +      (print macro-var)))
    +LET    ; MACRO-VAR inside the first LET
    +MACRO  ; MACRO-VAR inside the second LET
    +
    + +

    Now the same example with unique names. Note the +comma before the +'macro-var' inside the +let form of the macro +definition:

    + +
    +(defmacro print-macro (x)         ; good example
    +  (with-unique-names (macro-var)
    +    `(let ((,macro-var 'macro))
    +       (print ,x))))
    +
    +> (let ((macro-var 'let))         ; now it works
    +    (print macro-var)
    +    (print-macro macro-var))
    +LET  ; printed by PRINT
    +LET  ; printed by PRINT-MACRO
    +
    + +

    The reason why it works is that the 'print-macro' now +expands to:

    + +
    +> (let ((macro-var 'let))         ; works
    +    (print macro-var)
    +    (let ((gensym 'macro))
    +      (print macro-var)))
    +LET  ; MACRO-VAR inside the first LET
    +LET  ; MACRO-VAR inside the second LET
    +
    + +Now 'macro-var' can even be used as a variable name +inside the macro definition without colliding with the +'macro-var' bound +by let: + +
    +(defmacro print-macro (x)         ; good example
    +  (with-unique-names (macro-var)
    +    `(let ((,macro-var 'macro))
    +       (print ,macro-var)
    +       (print ,x))))
    +
    +> (let ((macro-var 'let))         ; works
    +    (print macro-var)
    +    (print-macro macro-var))
    +LET     ; MACRO-VAR printed inside LET
    +MACRO   ; GENSYMed MACRO-VAR, printed inside PRINT-MACRO
    +LET     ; MACRO-VAR bound by LET, printed inside PRINT-MACRO
    +
    + +

    The expansion of the 'print-macro' shows why this works:

    + +
    +> (let ((macro-var 'let))         ; works
    +    (print macro-var)
    +    (let ((gensym 'macro))
    +      (print gensym)
    +      (print macro-var)))
    +LET     ; MACRO-VAR printed inside LET
    +MACRO   ; GENSYMed MACRO-VAR printed inside PRINT-MACRO
    +LET     ; MACRO-VAR bound by LET, printed inside PRINT-MACRO
    +
    + +

    You can give as many variable names as you like to +'with-unique-names', the +gensym management is done +automatically:

    + +
    +(defmacro print-macro (x y z)
    +  (with-unique-names (a b c)
    +    `(let ((,a 1) (,b 2) (,c 3))
    +       (format t "outside: a: ~a  b: ~a  c: ~a~%" ,x ,y ,z)
    +       (format t " inside: a: ~a  b: ~a  c: ~a~%" ,a ,b ,c))))
    +
    +> (let ((a 'a) (b 'b) (c 'c))
    +    (print-macro a b c))
    +outside: a: A  b: B  c: C
    + inside: a: 1  b: 2  c: 3
    +
    + +

    Two things you still have to care about:

    + +
      + +
    1. The 'unique names' should not use the same smbol names as the +parameter variables of the macro, otherwise you will have the same +'shadowing' effect like in ordinary Lisp functions. This is not a real +problem because when writing a macro you can see the parameter names before +your eyes, while you usually cannot see the variable names of the +environment, where the macro will be expanded. You also do not +have to care which variable names had been used in a macro if you call the +macro from arbitrary Lisp code, where you usually cannot see the code of the +macro definition.

    2. + +
    3. The local gensymed variables +now themselves must be expanded by writing a +comma in front of each when they appear +inside a backquote scope. +This sometimes can lead to tricky situations, because the +comma expansion of the symbol does not +produce the variable's value, instead it produces the name of the +gensym, which holds the value. +But this is a general phenomenon of +gensyms in Lisp macro programming +and not a bug of the 'with-unique-names' macro.

    4. + +
    + +

    The alternative would be writing:

    + +
    +(defmacro print-macro (x y z)
    +  (let ((a (gensym)) (b (gensym)) (c (gensym)))
    +    `(let ((,a 1) (,b 2) (,c 3))
    +       (format t "outside: a: ~a  b: ~a  c: ~a~%" ,x ,y ,z)
    +       (format t " inside: a: ~a  b: ~a  c: ~a~%" ,a ,b ,c))))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/math.htm b/docsrc/xlisp/xlisp-doc/examples/math.htm new file mode 100644 index 0000000..b1a6414 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/math.htm @@ -0,0 +1,824 @@ + + +Math + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Math

    + +
    + +
      +
    1. Number Types
    2. +
    3. Integer Limits
    4. +
    5. Rounding and Truncation
    6. + +
    7. Remainder and Modulus
    8. + +
    9. Power and Roots
    10. + +
    + +
    + +

    Number Types

    + +
    + +

    Nyquist/XLISP only knows two types of numers:

    + +
      +
    • fixnum - integer numbers
    • +
    • flonum - floating-point numbers
    • +
    + +

    In Nyquist/XLISP, there are no ratios or complex numbers. Even if the +math functions on this page are modelled after Common Lisp, no +attempt is made to emulate these numbers.

    + + + +
    + +

    Integer Limits

    + +
    + +
    +(setq *most-positive-fixnum*  2147483647)
    +(setq *most-negative-fixnum* -2147483648)
    +
    + +

    Note: these are the limits for 32-bit machines.

    + +
    +(defun fixnum-bits ()
    +  (dolist (bits '(15 31 63) nil)
    +    (let ((fixnum (round (expt 2.0 bits))))
    +      (and (plusp (1- fixnum))
    +           (minusp fixnum)
    +           (return (1+ bits))))))
    +
    + +
    +(defun fixnum-limits ()
    +  (if (dolist (bits '(15 31 63) nil)
    +        (let* ((negative (round (expt 2.0 bits)))
    +               (positive (1- negative)))
    +           (when (and (plusp  positive)
    +                      (minusp negative))
    +             (setq most-positive-fixnum positive
    +                   most-negative-fixnum negative)
    +             (return t))))
    +      most-positive-fixnum
    +      (error "fixnum limit not found")))
    +
    + +

      Back to top

    + + + +
    + +

    print-float

    + +
    + +

    The 'print-float' function prints +floating-point numbers ending in '.0' as +floating-point numbers and not as integers:

    + +
    +(defun print-float (item)
    +  (if (not (floatp item))
    +      item
    +      (let ((string (format nil "~a" item)))
    +        (if (not (string-search "." string))
    +            (strcat string ".0")
    +            string))))
    +
    + +

      Back to top

    + + + +
    + +

    divide-float

    + +
    + +

    An easy way to force a sequence of integers to be divided as floating +point numbers is to insert the number 1.0 after the first argument in the +list of arguments to the divider function or to explicitely convert the +first argument into a floating point number by using the XLISP float function:

    + +
    +(defun divide-float (&rest args)
    +  (if (null args)
    +      (error "too few arguments")
    +      (apply #'/ (cons (float (first args)) (rest args)))))
    +
    + +

    See apply, cons, +defun, error, +first, float, +if, null, +rest, +&rest.

    + +

    Examples:

    + +
    +(divide-float 1)    => 1.0
    +(divide-float 1 2)  => 0.5
    +
    + +

      Back to top

    + + + +
    + +

    Rounding and Truncation

    + +
    + +

    The cl:round, +cl:truncate, +cl:ceiling and +cl:floor functions divide a number by a divisor, +returning a quotient and a remainder:

    + +

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    (cl:round number [divisor])  ⇒  quotient, remainder
    (cl:truncate number [divisor])  ⇒  quotient, remainder
    (cl:ceiling number [divisor])  ⇒  quotient, remainder
    (cl:floor number [divisor])  ⇒  quotient, remainder

    + +

      +quotient * divisor + remainder = number

    + +

    + +

    The 'quotient' always represents a mathematical integer. The +'remainder' is an integer if both 'number' and 'divisor' arguments +are integers, and a floating-point number if either the +'number' or the 'divisor' or both are floating-point +numbers.

    + +

    With Nyquist/XLISP, the 'quotient' is always directly returned by the +function, while a list:

    + +
    +(quotient remainder)
    +
    + +

    is stored in the Nyquist/XLISP +*rslt* variable and the +cl:*multiple-values* is +set to  T  to signal that +Multiple Values are returned.

    + +Examples: + +
    +(cl:round     3.5)  =>  4  ; *rslt* = ( 4 -0.5)
    +(cl:truncate  3.5)  =>  3  ; *rslt* = ( 3  0.5)
    +(cl:ceiling   3.5)  =>  4  ; *rslt* = ( 4 -0.5)
    +(cl:floor     3.5)  =>  3  ; *rslt* = ( 3  0.5)
    +
    +(cl:round    -3.5)  => -4  ; *rslt* = (-4  0.5)
    +(cl:truncate -3.5)  => -3  ; *rslt* = (-3 -0.5)
    +(cl:ceiling  -3.5)  => -3  ; *rslt* = (-3 -0.5)
    +(cl:floor    -3.5)  => -4  ; *rslt* = (-4  0.5)
    +
    + +Force integer division: + +
    +(cl:truncate 3.0 2.0)              => 1
    +(/ (truncate 3.0) (truncate 2.0))  => 1
    +(/ 3 4)                            => 1
    +
    + +

    + +

    Implementation Notes

    + +
    +(defun name (number &optional (divisor (if (integerp number) 1 1.0)))
    +  ... )
    +
    + +

    The integerp test in the +parameter list signals an error if the 'number' argument is not a number, +also the  /  +[division] function signals errors if the 'divisor' argument is zero +or not a number, so we do not explicitely need to test the arguments.

    + +

    The cl:ceiling and cl:floor functions test if 'number' is an +integer multiple of 'divisor' by comparing the results of an integer +division and a floating-point division:

    + +
    +(let ((i-quotient (/ (truncate number) (truncate divisor)))
    +      (f-quotient (/ (float number) divisor)))
    +  (if (= i-quotient f-quotient)
    +        ...
    +
    + +

    I'm not sure if this really catches all cases [e.g. +regarding floating point precision], but have found no problems so +far.

    + +

    + +

      Back to top

    + + + +
    + +

    cl:round

    + +
    + +

    The 'cl:round' function truncates towards the next +integer:

    + +

    + +
    +
    (cl:round number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of runding the result of number divided by divisor
     - the remainder of the round operation
    +
    + +

    + +
    +(defun cl:round (number &optional (divisor
    +                                  (if (integerp number) 1 1.0)
    +                                  divisor-p))
    +  (let* ((x (/ (float number) divisor))
    +         (quotient (cond ((and (not divisor-p) (integerp number)) number)
    +                         ((= number divisor) 1)
    +                         ((plusp x) (truncate (+ x 0.5)))
    +                         ((= (- x 0.5) (truncate (- x 0.5)))
    +                          (if (minusp x)
    +                              (1- (truncate x))
    +                              (truncate x)))
    +                         (t (truncate (- x 0.5))))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The 'cl:round' function computes a quotient that has been rounded to the +nearest mathematical integer. If the mathematical quotient is +exactly halfway between two integers, [that is, it has the form +'integer+1/2'], then the quotient has been rounded to the even +[divisible by two] integer. See +Rounding and Truncation +above for more details.

    + +
    +(round  3.5)     =>  4
    +(round -3.5)     => -3
    +
    +(cl:round  3.5)  =>  4  ; *rslt* = ( 4 -0.5)
    +(cl:round -3.5)  => -4  ; *rslt* = (-4  0.5)
    +
    + +

      Back to top

    + + + +
    + +

    cl:truncate

    + +
    + +

    The 'cl:truncate' function truncates towards zero:

    + +

    + +
    +
    (cl:truncate number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of truncating the result of number divided by divisor
     - the remainder of the truncate operation
    +
    + +

    + +
    +(defun cl:truncate (number &optional (divisor (if (integerp number) 1 1.0)))
    +  (let ((quotient (truncate (/ (float number) divisor))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The 'cl:truncate' function computes a quotient that has been +truncated towards zero. That is, the quotient represents the mathematical +integer of the same sign as the mathematical quotient, and that has the +greatest integral magnitude not greater than that of the mathematical +quotient. See +Rounding and Truncation +above for more details.

    + +

      Back to top

    + + + +
    + +

    cl:ceiling

    + +
    + +

    The 'cl:ceiling' function truncates towards positive +infinity:

    + +

    + +
    +
    (cl:ceiling number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of truncating the result of number divided by divisor
     - the remainder of the truncate operation
    +
    + +

    + +
    +(defun cl:ceiling (number &optional (divisor
    +                                    (if (integerp number) 1 1.0)
    +                                    divisor-p))
    +  (let ((quotient
    +          (cond ((and (not divisor-p) (integerp number)) number)
    +                ((= number divisor) 1)
    +                (t (let ((i-quotient (/ (truncate number) (truncate divisor)))
    +                         (f-quotient (/ (float number) divisor)))
    +                     (if (or (= i-quotient f-quotient)  ; integer result
    +                             (not (plusp f-quotient)))
    +                          (truncate f-quotient)
    +                          (1+ (truncate f-quotient))))))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The 'cl:ceiling' function computes a quotient that has been +truncated toward positive infinity. That is, the quotient represents the +smallest mathematical integer that is not smaller than the mathematical +result. See +Rounding and Truncation +above for more details.

    + +

      Back to top

    + + + +
    + +

    cl:floor

    + +
    + +

    The 'cl:floor' function truncates towards negative infinity:

    + +

    + +
    +
    (cl:floor number [divisor])
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number, except zero
    + + + + + + + + + + + +
    returns - the result of truncating the result of number divided by divisor
     - the remainder of the truncate operation
    +
    + +

    + +
    +(defun cl:floor (number &optional (divisor
    +                                  (if (integerp number) 1 1.0)
    +                                  divisor-p))
    +  (let ((quotient
    +          (cond ((and (not divisor-p) (integerp number)) number)
    +                ((= number divisor) 1)
    +                (t (let ((i-quotient (/ (truncate number) (truncate divisor)))
    +                         (f-quotient (/ (float number) divisor)))
    +                     (if (or (= i-quotient f-quotient)  ; integer result
    +                             (not (minusp f-quotient)))
    +                          (truncate f-quotient)
    +                          (1- (truncate f-quotient))))))))
    +    (setq *rslt* (list quotient (- number (* quotient divisor)))
    +          cl:*multiple-values* t)
    +    quotient))
    +
    + +

    The 'cl:floor' function computes a quotient that has been +truncated toward negative infinity. That is, the quotient represents the +largest mathematical integer that is not larger than the mathematical +quotient. See +Rounding and Truncation +above for more details.

    + +

      Back to top

    + + + +
    + +

    Remainder and Modulus

    + +
    + +

    The cl:mod and cl:rem +function are generalizations of the modulus and remainder functions. +The cl:mod function performs the +cl:floor operation on its arguments and returns the +remainder of the cl:floor operation. +The cl:rem function performs the +cl:truncate operation on its arguments and returns +the remainder of the cl:truncate operation. +The cl:mod and +cl:rem functions are the modulus and remainder +functions when the 'number' and 'divisor' arguments both are integers.

    + +

      Back to top

    + + + +
    + +

    cl:rem

    + +
    + +

    + +
    +
    (cl:rem number divisor)
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number
    +returns - the remainder of a cl:truncate operation
    +
    + +

    + +
    +(defun cl:rem (number divisor)
    +  (if (= (abs number) (abs divisor))
    +      (if (and (integerp number) (integerp divisor)) 0 0.0)
    +      (let ((quotient (truncate (/ (float number) divisor))))
    +        (- number (* quotient divisor)))))
    +
    + +

    The 'cl:rem' function performs the +cl:truncate operation on its arguments and returns +the remainder of the cl:truncate operation. +The result is either zero or an integer or +floating-point number with the same sign as the 'number' +argument. If both arguments are integer numbers, the +'cl:rem' function is equal to the mathematical remainder +function.

    + +

      Back to top

    + + + +
    + +

    cl:mod

    + +
    + +

    + +
    +
    (cl:mod number divisor)
    +
    number - an integer or floating-point number
    +divisor - an integer or floating-point number
    +returns - the remainder of a cl:floor operation
    +
    + +

    + +
    +(defun cl:mod (number divisor)
    +  (if (= (abs number) (abs divisor))
    +      (if (and (integerp number) (integerp divisor)) 0 0.0)
    +      (let* ((i-quotient (/ (truncate number) (truncate divisor)))
    +             (f-quotient (/ (float number) divisor))
    +             (quotient (if (or (= i-quotient f-quotient)  ; integer result
    +                               (not (minusp f-quotient)))
    +                           (truncate f-quotient)
    +                           (1- (truncate f-quotient)))))
    +        (- number (* quotient divisor)))))
    +
    + +

    The 'cl:mod' function performs the +cl:floor operation on its arguments and returns the +remainder of the cl:floor operation. The +result is either zero or an integer or floating-point +number with the same sign as the 'divisor' argument. If both +arguments are integer numbers, the 'cl:rem' function is equal +to the mathematical modulus function.

    + +

      Back to top

    + + + +
    + +

    cl:exp

    + +
    + +

    The 'cl:exp' function does the same as the Nyquist/XLISP +exp function, but it also accepts +integer numbers as argument:

    + +

    + +
    +
    (cl:exp power)
    +
    power - an integer or floating-point number
    +returns - the result of 'e' [2.7128] to the power of power
    +
    + +

    + +
    +(defun cl:exp (x)
    +  (exp (float x)))
    +
    + +

    The 'cl:exp' function computes 'e' [2.7128] +raised to the specified 'power'. The result is always a +floating-point number.

    + +

      Back to top

    + + + +
    + +

    cl:expt

    + +
    + +

    The 'cl:expt' function computes the result of 'x' to the +power of 'y':

    + +

    + +
    +
    (cl:expt base power)
    +
    base - the base
    +power - the exponent
    +returns - the result of base to the power of power
    +
    + +

    + +
    +(defun cl:expt (x y)
    +  (let ((power (expt (float x) y)))
    +    (if (and (integerp x) (integerp y))
    +        (round power)
    +        power)))
    +
    + +

    See and, +defun, +expt, +float, + if , +integerp, +let, +power, +round.

    + +

    The 'cl:expt' function accepts integer and floating point +numbers as arguments. If both arguments are integer numbers, +the result will be an integer number, if one or both arguments +are floating-point numbers, the result will be a +floating-point number. In contrast to the +Nyquist/XLISP expt function, the +'cl:expt' function specifies exactly two arguments.

    + +

      Back to top

    + + + +
    + +

    cl:log

    + +
    + +

    The 'cl:log' function does the same as the Nyquist/XLISP +log function, but also accepts +integer numbers and has an optional 'base' argument:

    + +

    + +
    +
    (cl:log number [base])
    +
    number - an integer or floating-point number
    +base - an integer or floating-point number
    +returns - the the logarithm of number in base base
    +
    + +

    + +
    +(defun cl:log (number &optional base)
    +  (if base
    +      (if (zerop base)
    +          0.0
    +          (/ (log (float number)) (log (float base))))
    +      (log (float number))))
    +
    + +

    The 'cl:log' function returns the logarithm of 'number' in +base 'base'. If 'base' is not supplied its value is +'e', the base of the natural logarithms. If the 'base' +argument is zero, then 'cl:log' returns zero. The result is +always a floating-point number.

    + +

      Back to top

    + + + +
    + +

    cl:sqrt

    + +
    + +

    The 'cl:sqrt' function does the same as the Nyquist/XLISP +sqrt function, but it also accepts +integer numbers as argument:

    + +

    + +
    +
    (cl:sqrt number)
    +
    number - an integer or floating-point number
    +returns - the square root of number
    +
    + +

    + +
    +(defun cl:sqrt (x)
    +  (sqrt (float x)))
    +
    + +

    The result is always a floating-point +number.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/octal.htm b/docsrc/xlisp/xlisp-doc/examples/octal.htm new file mode 100644 index 0000000..f72ba4d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/octal.htm @@ -0,0 +1,148 @@ + + +Octal Integer Numbers + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Octal Integer Numbers

    + +
    + +

    XLISP provides the #o +read-macro for octal numbers:

    + +
    +#o0  => 0        #o10  => 8         #o20  => 16
    +#o1  => 1        #o11  => 9         #o21  => 17
    +#o2  => 2        #o12  => 10        #o22  => 18
    +#o3  => 3        #o13  => 11        #o23  => 19
    +#o4  => 4        #o14  => 12        #o24  => 20
    +#o5  => 5        #o15  => 13        #o25  => 21
    +#o6  => 6        #o16  => 14        #o26  => 22
    +#o7  => 7        #o17  => 15        #o27  => 23
    +
    + +

    + +
    +
    (oct-string integer [all])
    +
    integer - an integer expression
    +all - a boolean expression
    +returns - the integer in octal form as string
    +
    + +

    + +
    +(defun oct-string (integer &optional all)
    +  (if (integerp integer)
    +      (let ((fmt (if all
    +                     (or (dolist (bits '(16 32 64 128) nil)
    +                           (let ((fixnum (round (expt 2.0 (1- bits)))))
    +                             (and (plusp (1- fixnum))
    +                                  (minusp fixnum)
    +                                  (return (format nil "%.~ao"
    +                                                      (1+ (/ bits 3)))))))
    +                         (error "integer limit not found"))
    +                     "%o")))
    +        (progv '(*integer-format*) (list fmt)
    +          (format nil "~a" integer)))
    +      (error "not an integer" integer)))
    +
    + +

    The 'oct-string' function converts the 'integer' argument +into octal form and returns is as a string. If the +optional 'all' argument is not given or +NIL, leading zeros are not included in +the string. If the optional 'all' argument is +non-NIL, all digits of the +internal representation of the 'integer' argument, including leading zeros, +are contained in the string. This is useful for debugging integer overflow +and bit-wise functions.

    + +

    + +
    +
    (oct integer [all])
    +
    integer - an integer expression
    +all - a boolean expression
    +prints - the integer in octal form
    +returns - the integer argument
    +
    + +

    + +
    +(defun oct (integer &optional all)
    +  (if (integerp integer)
    +      (format t "#o~a~%" (oct-string integer all))
    +      (format t ";; not an integer~%"))
    +  integer)
    +
    + +

    The 'oct' function prints the 'integer' argument in octal form on +the screen. Together with the +#o read-macro +this can be used for interactive octal computations.

    + +
    +> (oct 12345678)
    +#o57060516
    +12345678
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/posix-chars.htm b/docsrc/xlisp/xlisp-doc/examples/posix-chars.htm new file mode 100644 index 0000000..9e6c4e0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/posix-chars.htm @@ -0,0 +1,459 @@ + + +Characters and Strings + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    POSIX Character Classes

    + +
    + +
      +
    1. POSIX Character Classes
    2. +
    3. Internal Functions
    4. +
    5. User Functions
    6. +
    + +
    + +

    POSIX Character Classes

    + +
    + +

    The functions on this page implement tests for the standard POSIX +character classes, where all functions return the tested character if the +test succeeds, or NIL if the test +fails.

    + +

    The built-in XLISP character test functions +upper-case-p, +lower-case-p, +both-case-p, +alphanumericp, return the +boolean values  T  or +NIL instead of the tested character, +while digit-char-p returns an +integer or NIL, what is +handy if you want to convert arbitrary Lisp symbols into numbers without +producing an error, but all this is impractical for writing a string +parser.

    + +

    The Internal Functions +do not check if the argument is a character and therefore are faster than +the User Functions. Also note +that XLISP is limited to ASCII characters, so there is no way to find out if +an unicode character is upper- or lowercase if the character code is greater +than ASCII 127.

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      POSIX  -  Internal  -  User Function
      [:alnum:]  -  char:alnum-p  -  alnum-character-p  - alphanumeric = [a-z], [A-Z], [0-9]
      [:alpha:]  -  char:alpha-p  -  alpha-character-p  - alphabetic = [a-z], [A-Z]
      [:blank:]  -  char:blank-p  -  blank-character-p  - space and horizontal-tab
      [:cntrl:]  -  char:cntrl-p  -  cntrl-character-p  - code-chars 0-31 and 127
      [:digit:]  -  char:digit-p  -  digit-character-p  - decimal = [0-9]
      [:graph:]  -  char:graph-p  -  graph-character-p  - graphical = alnum + punct
      [:lower:]  -  char:lower-p  -  lower-character-p  - lowercase = [a-z]
      [:print:]  -  char:print-p  -  print-character-p  - printable = alnum + punct + space
      [:punct:]  -  char:punct-p  -  punct-character-p  - punctuation marks
      [:space:]  -  char:space-p  -  space-character-p  - characters producing whitespace
      [:upper:]  -  char:upper-p  -  upper-character-p  - uppercase = [A-Z]
      [:xdigit:]  -  char:xdigit-p  -  xdigit-character-p  - hexadecimal = [0-9], [a-f], [A-F]

    + +

    The main difference is:

    + +
    +> (char:alnum-p 'nonsense-value)
    +error: bad argument type - NONSENSE-VALUE
    +
    +> (alnum-character-p 'nonsense-value)
    +NIL
    +
    + +

      Back to top

    + + + +
    + +

    Internal Functions

    + +
    + +

    The internal functions are based on built-in XLISP +functions, there are no external dependencies.

    + + + +
    +;; alphanumeric characters = a-z, A-z, 0-9
    +
    +(defun char:alnum-p (char)
    +  (and (alphanumericp char)
    +       char))
    +
    +;; alphabetic characters = a-z, A-Z
    +
    +(defun char:alpha-p (char)
    +  (and (both-char-p char)
    +       char))
    +
    +;; blanks = space and horizontal-tab
    +
    +(defun char:blank-p (char)
    +  (and (or (char= char #\Space)
    +           (char= char #\Tab))
    +       char))
    +
    +;; control characters = code-chars 0-31 and 127
    +
    +(defun char:cntrl-p (char)
    +  (let ((code (char-code char)))
    +    (and (or (<= 0 code 31)
    +             (= code 127))
    +         char)))
    +
    +;; decimal digits = 0-9
    +
    +(defun char:digit-p (char)
    +  (and (digit-char-p char)
    +       char))
    +
    +;; graphical characters = alnum + punct
    +
    +(defun char:graph-p (char)
    +  (and (<= 33 (char-code char) 126)
    +       char))
    +
    +;; lowercase characters = a-z
    +
    +(defun char:lower-p (char)
    +  (and (lower-case-p char)
    +       char))
    +
    +;; printable characters = alnum + punct + space
    +
    +(defun char:print-p (char)
    +  (and (<= 32 (char-code char) 126)
    +       char))
    +
    +;; punctuation marks
    +
    +(defun char:punct-p (char)
    +  (let ((code (char-code char)))
    +    (and (or (<=  33 code  47)   ;  ! " # $ % & ' ( ) * + , - . /
    +             (<=  58 code  64)   ;  : ; < = > ? @
    +             (<=  91 code  96)   ;  [ \ ] ^ _ `
    +             (<= 123 code 126))  ;  { | } ~
    +         char)))
    +
    +;; characters producing whitespace
    +;;
    +;;  9 = horizontal tab   10 = line feed         11 = vertical tab
    +;; 12 = form feed        13 = carriage return   32 = space
    +
    +(defun char:space-p (char)
    +  (and (member (char-code char) '(9 10 11 12 13 32))
    +       char))
    +
    +;; uppercase characters = A-Z
    +
    +(defun char:upper-p (char)
    +  (and (upper-case-p char)
    +       char))
    +
    +;; hexadecimal digits = 0-9, a-f, A-F
    +
    +(defun char:xdigit-p (char)
    +  (and (or (digit-char-p char)
    +           (let ((code (char-code char)))
    +             (or (<= 65 code  70)     ; A-Z
    +                 (<= 97 code 102))))  ; a-z
    +       char))
    +
    + +

      Back to top

    + + + +
    + +

    User Functions

    + +
    + +

    The user functions are based on the +Internal Functions above. +There are no other dependencies.

    + + + +
    +;; alphanumeric characters = a-z, A-z, 0-9
    +
    +(defun alnum-character-p (char)
    +  (and (characterp char)
    +       (char:alnum-p char)))
    +
    +;; alphabetic characters = a-z, A-Z
    +
    +(defun alpha-character-p (char)
    +  (and (characterp char)
    +       (char:alpha-p char)))
    +
    +;; blanks = space and horizontal-tab
    +
    +(defun blank-character-p (char)
    +  (and (characterp char)
    +       (char:blank-p char)))
    +
    +;; control characters = code-chars 0-31 and 127
    +
    +(defun cntrl-character-p (char)
    +  (and (characterp char)
    +       (char:cntrl-p char)))
    +
    +;; decimal digits = 0-9
    +
    +(defun digit-character-p (char)
    +  (and (characterp char)
    +       (char:digit-p char)))
    +
    +;; graphical characters = alnum + punct
    +
    +(defun graph-character-p (char)
    +  (and (characterp char)
    +       (char:graph-p char)))
    +
    +;; lowercase characters = a-z
    +
    +(defun lower-character-p (char)
    +  (and (characterp char)
    +       (char:lower-p char)))
    +
    +;; printable characters = alnum + punct + space
    +
    +(defun print-character-p (char)
    +  (and (characterp char)
    +       (char:print-p char)))
    +
    +;; punctuation marks
    +
    +(defun punct-character-p (char)
    +  (and (characterp char)
    +       (char:punct-p char)))
    +
    +;; characters producing whitespace
    +
    +(defun space-character-p (char)
    +  (and (characterp char)
    +       (char:space-p char)))
    +
    +;; uppercase characters = A-Z
    +
    +(defun upper-character-p (char)
    +  (and (characterp char)
    +       (char:upper-p char)))
    +
    +;; hexadecimal digits = 0-9, a-f, A-F
    +
    +(defun xdigit-character-p (char)
    +  (and (characterp char)
    +       (char:xdigit-p char)))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/predicates.htm b/docsrc/xlisp/xlisp-doc/examples/predicates.htm new file mode 100644 index 0000000..5846f2d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/predicates.htm @@ -0,0 +1,526 @@ + + +Predicates + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Predicates and Comparison

    + +
    + +

    Lisp has extensive support for run-time tests.

    + +

    Generalized Lisp Functions - slower than the build-ins, but no errors

    + +
      +
    1. Built-in XLISP Functions
    2. +
    3. Generalized Comparison - one or more arguments
    4. +
        +
      • equalp - compares expressions with 'equality' functions.
      • +
      +
    5. Symbol Predicates - one argument
    6. +
        +
      • variablep - is this a symbol with a variable value bound to it?
      • +
      • functionp - is this a function or a symbol with a function value bound to it?
      • +
      • specialp - is this a special form or a symbol with a special form bound to it?
      • +
      • macrop - is this a Lisp macro or a symbol with a Lisp macro bound to it?
      • +
      +
    7. Function Predicates - one argument
    8. +
        +
      • subrp - is this a build-in function?
      • +
      • fsubrp - is this a build-in special form?
      • +
      • closurep - is this a user-defined function?
      • +
      +
    9. Character Predicates - one argument
    10. + +
    + +

      Back to top

    + + + +
    + +

    Built-in XLISP Functions

    + +
    + +
      +
    1. Boolean Predicates - one argument [all types]
    2. +
        +
      • not - does this expression evaluate to false?
      • +
      +
    3. Generalized Comparison - two arguments [all types]
    4. +
        +
      • eq - are the expressions identical?
      • +
      • eql - are the expressions identical or equal numbers?
      • +
      • equal - do the printed expressions look the same?
      • +
      +
    5. Type Predicates - one argument [all types]
    6. +
        +
      • atom - is this an atom?
      • +
      • symbolp - is this a symbol?
      • +
          +
        • Symbol Predicates - one argument [error if not a symbol]
        • +
            +
          • boundp - has the symbol a variable value?
          • +
          • fboundp - has the symbol a function value?
          • +
          +
        +
      • numberp - is this a number?
      • +
          +
        • Number Predicates - one argument [error if not a number]
        • +
            +
          • plusp - is the number positive?
          • +
          • minusp - is the number negative?
          • +
          • zerop - is the number equal to zero?
          • +
          • integerp - is the number an integer?
          • +
              +
            • Integer Predicates - one argument [error if not an integer]
            • +
                +
              • evenp - is the integer even?
              • +
              • oddp - is the integer odd?
              • +
              +
            +
          • floatp - is the number a floating-point number?
          • +
          +
        • Numerical Comparison - one or more arguments [error if not numbers only]
        • +
            +
          •  <  - true if all numbers are monotonically increasing
          • +
          •  <=  - true if all numbers are monotonically nondecreasing
          • +
          •  =  - true if all all numbers are the same value
          • +
          •  /=  - true if no two numbers have the same value
          • +
          •  >=  - true if all numbers are monotonically nonincreasing
          • +
          •  >  - true if all numbers are monotonically decreasing
          • +
          +
        +
      • null - is this an empty list?
      • +
      • consp - is it a non-empty list?
      • +
      • listp - is this a list?
      • +
          +
        • List Predicates - one argument [error if not a list]
        • +
            +
          • endp - is this the end of a list?
          • +
          +
        +
      • stringp - is this a string?
      • +
          +
        • String Comparison - one or more arguments [error if not strings only]
        • +
            +
          • Case Sensitive
          • +
              +
            • string< - test for less than in ASCII ordering
            • +
            • string<= - test for less than or equal to in ASCII ordering
            • +
            • string= - test for equal to in ASCII ordering
            • +
            • string/= - test for not equal to in ASCII ordering
            • +
            • string>= - test for greater than or equal to in ASCII ordering
            • +
            • string> - test for greater than in ASCII ordering
            • +
            +
          • Case Insensitive
          • + +
          • See also Unicode examples.
          • +
          +
        +
      • characterp - is this a character?
      • +
          +
        • Character Predicates - one argument [error if not a character]
        • + +
        • Character Comparison - one or more arguments [error if not characters only]
        • +
            +
          • Case Sensitive
          • +
              +
            • char< - test for less than in ASCII ordering
            • +
            • char<= - test for less than or equal to in ASCII ordering
            • +
            • char= - test for equal to in ASCII ordering
            • +
            • char/= - test for not equal to in ASCII ordering
            • +
            • char>= - test for greater than or equal to in ASCII ordering
            • +
            • char> - test for greater than in ASCII ordering
            • +
            +
          • Case Insensitive
          • + +
          • See also Unicode examples.
          • +
          +
        +
      • arrayp - is this an array?
      • +
      • streamp - is this a stream?
      • +
      • objectp - is this an object?
      • +
      • filep - is this a file?
      • +
      • soundp - is this a sound?
      • +
      +
    + +

      Back to top

    + + + +
    + +

    equalp

    + +
    + +

    Two expressions are 'equalp':

    + +
      + +
    • If two numbers are + =  +numerical equal.

    • + +
    • If two characters are +char-equal.

    • + +
    • If two strings are string-equal.

    • + +
    • If the two cars in conses are +'equalp' and the two cdrs in conses +are 'equalp'.

    • + +
    • If two arrays have the same number of elements and dimensions, and +the corresponding elements in all dimensions are 'equalp'.

    • + +
    + +
    +(defun equalp (expr-1 expr-2)
    +  (or (equal expr-1 expr-2)
    +      (and (numberp expr-1) (numberp expr-2) (= expr-1 expr-2))
    +      (let ((type (type-of expr-1)))
    +        (when (eq type (type-of expr-2))
    +          (case type
    +            (character (char-equal expr-1 expr-2))
    +            (string    (string-equal expr-1 expr-2))
    +            (cons      (do ((x (first expr-1)
    +                               (if (consp expr-1) (first expr-1) expr-1))
    +                            (y (first expr-2)
    +                               (if (consp expr-2) (first expr-2) expr-2)))
    +                           ((or (null expr-1)
    +                                (null expr-2)
    +                                (not (equalp x y)))
    +                            (and (null expr-1)
    +                                 (null expr-2)))
    +                         (setq expr-1 (and (consp expr-1) (rest expr-1))
    +                               expr-2 (and (consp expr-2) (rest expr-2)))))
    +            (array     (let ((end (length expr-1)))
    +                         (when (eql end (length expr-2))
    +                           (dotimes (index end t)
    +                             (and (not (equalp (aref expr-1 index)
    +                                               (aref expr-2 index)))
    +                                  (return nil)))))))))))
    +
    + +

    cons: I used do instead of +recursion because XLISP has only two kilobytes stack size. The +(consp expr) tests are +necessary because in a dotted list the last +rest element is not a cons.

    + +

    Examples:

    + +
    +(equalp 1 1.0)                            => T
    +(equalp #\a #\A)                          => T
    +(equalp "Abc" "aBc")                      => T
    +(equalp '(1 #\a "Abc") '(1.0 #\A "aBc"))  => T
    +(equalp #(1 #\a "Abc") #(1.0 #\A "aBc"))  => T
    +
    + +

    Nested expressions only match if the nesting matches:

    + +
    +(equalp '(1 (2 3)) '(1.0 (2.0 3.0))  => T
    +(equalp '(1 (2 3)) '((1.0 2.0) 3.0)  => NIL
    +(equalp '((1 2) 3) '((1.0 2.0) 3.0)  => T
    +(equalp '((1 2) 3) '(1.0 (2.0 3.0))  => NIL
    +
    + +

    A character does not match a string with the same character:

    + +
    +(equalp #\a "a")  => NIL
    +
    + +

      Back to top

    + + + +
    + +

    variablep

    + +
    + +

    The 'variablep' macro tests if a Lisp expression evaluates to a symbol +with a valid variable value bound to it in the current global or lexical +environment:

    + +
    +(defmacro variablep (expr)
    +  `(and (symbolp ,expr)
    +        (valuep ,expr)))
    +
    + +

    Depends on valuep, see +and, +defmacro, +symbolp.

    + +

      Back to top

    + + + +
    + +

    functionp

    + +
    + +

    The 'functionp' macro tests if a Lisp expression eveluates to a function +or a symbol with a valid function value bound to it in the current global or +lexical environment:

    + +
    +(defmacro functionp (expr)
    +  `(case (type-of ,expr)
    +     (closure (eq 'lambda (car (get-lambda-expression ,expr))))
    +     (subr    t)
    +     (symbol  (and (or (lfboundp ,expr) (fboundp ,expr))
    +                   (functionp (function ,(if (consp expr) (cadr expr) expr)))))
    +     (t       nil)))
    +
    + +

    Depends on lfboundp, see +and, +cadr, +car, +case, +closure, +defmacro, +eq, +fboundp, +function, +get-lambda-expression, +lambda, +nil, +or, +subr, +symbol, + t , +type-of.

    + +

    The awkward (function ,(if (consp expr) (cadr expr) expr)) +construct is necessary because the +function special form needs a +pre-evaluated argument, what must be +done at macro-expansion time, so an additional +consp test is +needed if the 'expr' argument is a list at all, otherwise +cadr will produce an error.

    + +Examples: + +
    +(functionp #'car)  => T    ; subr = built-in function
    +(functionp  'car)  => T    ; symbol with a function value
    +
    +(functionp #'and)  => NIL  ; fsubr = built-in special form
    +(functionp "and")  => NIL  ; string
    +
    +(defun a () nil)   => A    ; closure = user-defined function
    +(functionp #'a)    => T    ; closure
    +(functionp  'a)    => T    ; symbol with a function value
    +
    +(setq b #'a)       => A    ; function A stored in variable B
    +(fboundp 'b)       => NIL  ; no function B found
    +(fboundp b)        => T    ; variable B evaluates to function A
    +
    +(functionp #'(lambda () nil))  => T    ; closure
    +(functionp  '(lambda () nil))  => NIL  ; list
    +(functionp   (lambda () nil))  => T    ; closure
    +
    +(functionp #'functionp)        => NIL  ; macro
    +
    +(let ((x nil))        ; lexical variable
    +  (functionp x))
    +=> NIL
    +
    +(flet ((y () nil))    ; lexical closure
    +  (functionp y))
    +=> T
    +
    +(labels ((z () nil))  ; lexical closure
    +  (functionp z))
    +=> T
    +
    + +

      Back to top

    + + + +
    + +

    specialp

    + +
    + +
    +(defmacro specialp (expr)
    +  `(case (type-of ,expr)
    +     (fsubr   t)
    +     (symbol  (and (or (lfboundp ,expr) (fboundp ,expr))
    +                   (functionp (function ,(if (consp expr) (cadr expr) expr)))))
    +     (t       nil)))
    +
    + +

      Back to top

    + + + +
    + +

    macrop

    + +
    + +
    +(defmacro macrop (expr)
    +  `(case (type-of ,expr)
    +     (closure (eq 'macro (car (get-lambda-expression ,expr))))
    +     (symbol  (and (or (lfboundp ,expr) (fboundp ,expr))
    +                   (macrop (function ,(if (consp expr) (cadr expr) expr)))))
    +     (t       nil)))
    +
    + +

      Back to top

    + + + +
    + +

    subrp

    + +
    + +

    The 'subrp' function returns T if the symbol is a build-in function.

    + +
    +(defun subrp (symbol)
    +  (eq 'subr (type-of symbol))) 
    +
    + +

      Back to top

    + + + +
    + +

    fsubrp

    + +
    + +

    The 'fsubrp' function returns T if the symbol is a build-in special +function.

    + +
    +(defun fsubrp (symbol)
    +  (eq 'fsubr (type-of symbol))) 
    +
    + +

      Back to top

    + + + +
    + +

    closurep

    + +
    + +

    The 'closurep' function returns T if the symbol is a user-defined +function.

    + +
    +(defun closurep (symbol)
    +  (eq 'closure (type-of symbol)))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + + diff --git a/docsrc/xlisp/xlisp-doc/examples/reader.htm b/docsrc/xlisp/xlisp-doc/examples/reader.htm new file mode 100644 index 0000000..8321c48 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/reader.htm @@ -0,0 +1,311 @@ + + +XLISP reader + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Reader

    + +
    + + + +
    + +

    read-from-string

    + +
    + +
    +(defun read-from-string (string)
    +  (read (make-string-input-stream string)))
    +
    + +

      Back to top

    + + + +
    + +

    *readtable*

    + +
    + +

    The *readtable* system +variable contains the reader table array. The table is +128 entries [0..127] for each of the +7-bit ASCII characters that XLISP +can read.

    + + + +

    See also the +Lexical Conventions +and Readtable sections in the +XLISP 2.0 manual.

    + + + +
    + +

    print-readtable

    + +
    + +
    +(defun print-readtable ()
    +  (dotimes (index 128)
    +    (format t "ASCII-~a ~a = ~a~%"
    +              (cond ((<=  0 index  9) (format nil "00~a" index))
    +                    ((<= 10 index 99) (format nil "0~a"  index))
    +                    (t index))
    +              (if (< 31 index 127)
    +                  (code-char index)
    +                  (case index
    +                    (0   "[null]                  ")
    +                    (1   "[start of heading]      ")
    +                    (2   "[start of text]         ")
    +                    (3   "[end of text]           ")
    +                    (4   "[end of transmission]   ")
    +                    (5   "[enquiry]               ")
    +                    (6   "[acknowledge]           ")
    +                    (7   "[terminal bell]         ")
    +                    (8   "[backspace]             ")
    +                    (9   "[horizontal tab]        ")
    +                    (10  "[line feed]             ")
    +                    (11  "[vertical tab]          ")
    +                    (12  "[form feed]             ")
    +                    (13  "[carriage return]       ")
    +                    (14  "[shift out]             ")
    +                    (15  "[shift in]              ")
    +                    (16  "[data link escape]      ")
    +                    (17  "[device control 1, xon] ")
    +                    (18  "[device control 2]      ")
    +                    (19  "[device control 3, xoff]")
    +                    (20  "[device control 4]      ")
    +                    (21  "[negative acknowledge]  ")
    +                    (22  "[synchronous idle]      ")
    +                    (23  "[end transmission block]")
    +                    (24  "[cancel line]           ")
    +                    (25  "[end of medium]         ")
    +                    (26  "[substitute]            ")
    +                    (27  "[escape]                ")
    +                    (28  "[file separator]        ")
    +                    (29  "[group separator]       ")
    +                    (30  "[record separator]      ")
    +                    (31  "[unit separator]        ")
    +                    (127 "[delete]")))
    +              (aref *readtable* index))))
    +
    + +
    + +

    get-macro-character

    + +
    + +

    + +
    +
    (get-macro-character char)
    +
    char - a character
    +returns - the code associated with the +*readtable* entry or +NIL
    +
    + +

    + +
    +(defun get-macro-character (char)
    +  (if (consp (aref *readtable* (char-code char)))
    +      (cdr (aref *readtable* (char-int char)))
    +      nil))
    +
    + +

    The 'get-macro-character' function returns the code that +will be executed when the specified character 'char' is encountered by the +XLISP reader.

    + +

    The 'get-macro-character' function will return a +NIL value if the table entry is +NIL , +:constituent , +:sescape , +:mescape or +:white-space. If the table entry is +:tmacro or +:nmacro , then the code +associated with the entry is returned. +:tmacro is used for a terminating +read-macro. :nmacro is used for a +non-terminating read-macro. 'get-macro-character' does not differentiate +whether the code returned is a +:tmacro or an +:nmacro.

    + +

    The function returned may be a built-in read-macro function or a user +defined lambda expression. The function +takes two parameters, an input stream specification, and an integer that is +the character value. The function should return +NIL if the character is 'white-space' or a +value consed with +NIL to return the value.

    + +

    Examples:

    + +
    +(get-macro-character #\()      => #<Subr-(null): #...>
    +(get-macro-character #\#)      => #<Subr-(null): #...>
    +(get-macro-character #\Space)  => NIL
    +
    + +

      Back to Top

    + + + +
    + +

    set-macro-character

    + +
    + +

    + +
    +
    (set-macro-character char function [termination-flag])
    +
    char - a character expression
    +function - a function definition
    +termination-flag - an expression, NIL or +non-NIL
    +returns - always returns  T 
    +
    + +

    + +
    +(defun set-macro-character (char function &optional terminate-p)
    +  (setf (aref *readtable* (char-code char))
    +        (cons (if terminate-p :tmacro :nmacro) function))
    +  t)
    +
    + +

    The 'set-macro-character' function installs the code that +will be executed when the specified character 'char' is encountered by the +XLISP reader.

    + +

    The 'set-macro-character' function only allows you to put in a +terminating read-macro function :tmacro or +a non-terminating read-macro-function +:nmacro. If the 'termflag' is present and +non-NIL , then the 'function' +will be put in *readtable* as a +:tmacro entry. If 'termflag' is not present +or NIL , then 'function' will +be put in *readtable* as a +:nmacro entry. The 'function' can be a +built-in read-macro function or a user defined +defun symbol or a +lambda expression.

    + +

    The 'function' takes two parameters, an input stream specification, and +an integer that is the character value. The 'function' should return +NIL if the character is 'white-space' or a +value consed with +NIL to return the value. The function +'set-macro-character' always returns + T .

    + +

    Examples:

    + +
    +> (print "hi") % comment
    +"hi"
    +"hi"
    +error: unbound variable - %       ; % is interpreted as a variable
    +
    +> (setq readtable-backup *readtable*)
    +#( ... very-long-value ... )
    +
    +> (set-macro-character #\% (get-macro-character #\;) t)
    +T
    +
    +> (print "hi") % comment
    +"hi"                              ; no error because
    +"hi"                              ; % is now a comment character
    +
    +> (setq *readtable* readtable-backup)
    +#( ... very-long-value ... )
    +
    + +

    Important: before manipulating the XLISP +*readtable* it's always a +good idea to store the original contents in some other variable.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/sequences.htm b/docsrc/xlisp/xlisp-doc/examples/sequences.htm new file mode 100644 index 0000000..fb69a4b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/sequences.htm @@ -0,0 +1,563 @@ + + +Sequences + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Sequences

    + +
    + +

    Sequences are Lists, +Strings, +or Arrays.

    + +
      +
    • sequencep - test if a Lisp object is a sequence
    • +
    • length - the length of a sequence
    • +
    • identity - do nothing, just return the value
    • +
    • cl:subseq - subsequences of lists, strings, or arrays
    • +
    • Properties of elements in sequences:
    • +
        +
      • find
      • +
      • count
      • +
      • position
      • +
      +
    • Predicates for testing sequences:
    • +
        +
      • every
      • +
      • some
      • +
      • notevery
      • +
      • notany
      • +
      +
    • Functions to modify sequences:
    • +
        +
      • map
      • +
      • flatten
      • +
      +
    + + + +
    + +

    sequencep

    + +
    + +

    The following example demonstrates how a XLISP expression can be tested +for being a sequence:

    + +
    +(defun sequencep (x)
    +  (and (lboundp 'x)                ; not *unbound*
    +       (or (and (listp x)          ; a list or NIL
    +                (consp (last x)))  ; but not a dotted list
    +           (stringp x)             ; or a string
    +           (arrayp x))))           ; or an array
    +
    + +

    Depends on lboundp, +see also and, +arrayp, +consp, +defun, +last, +listp, +or, +stringp.

    + +

      Back to top

    + + + +
    + +

    length

    + +
    + +

    XLISP already knows sequences, even if the manual doesn't explicitely +tell you:

    + +

    + +
    +
    (length expr)
    +
    expr - expression, evaluating to a list, string, or array
    +returns - the length of the list, string, or array
    +
    + +

    + +

      Back to top

    + + + +
    + +

    identity

    + +
    + +
    +(defun identity (x)
    +  x)
    +
    + +

    The 'identity' function is handy if a mapping function needs a 'do +nothing, just return the value' function.

    + +

      Back to top

    + + + +
    + +

    cl:subseq

    + +
    + +

    XLISP already has a subseq function +returning a subsequence of a string:

    + +

    + +
    +
    (subseq string start [end])
    +
    string - a string expression
    +start - the position of the first element, an integer
    +end - the position following last element, defaults to the end of the sequence
    +returns - the substring between start and end
    +
    + +

    + +

    The 'cl:subseq' function works like +subseq, but returns subsequences of +lists, strings, and arrays:

    + +

    + +
    +
    (cl:subseq sequence start [end])
    +
    sequence - a list, string, or array
    +start - the position of the first element, an integer
    +end - the position following last element, defaults to the end of the sequence
    +returns - the subsequence in the same type as sequence
    +
    + +

    + +

    The 'cl:subseq' function creates a sequence that is a copy of the +subsequence of 'sequence' bounded by 'start' and 'end'. 'cl:subseq' always +allocates a new sequence for a result, it never shares storage with an old +sequence. The resulting subsequence is always of the same type +as the input sequence.

    + +
    +(defun cl:subseq (sequence start &optional (end nil end-p))
    +  (let ((type (type-of sequence)))
    +    (if (not (member type '(nil cons string array)))
    +        (error "not a sequence" sequence)
    +        (let* ((length (length sequence))
    +               (end (or end length)))
    +          (cond ((or (> start length) (minusp start))
    +                 (error "start index out of bounds" start))
    +                ((and end-p (or (> end length) (minusp end)))
    +                 (error "end index out of bounds" end))
    +                ((> start end)
    +                 (error (format nil "bad range start ~a end ~a" start end)))
    +                (t (case type
    +                     (nil    nil)
    +                     (cons   (if (not (consp (last sequence)))
    +                                 ;; a dotted list is not a sequence
    +                                 (error "not a proper sequence" sequence)
    +                                 (if (>= start end)
    +                                     nil
    +                                     (nthcdr start
    +                                             (if end-p
    +                                                 (reverse
    +                                                   (nthcdr (- length end)
    +                                                     (reverse sequence)))
    +                                                 sequence)))))
    +                     (string (subseq sequence start end))
    +                     (array  (if (>= start end)
    +                                 (make-array 0)
    +                                 (let ((new-array (make-array (- end start))))
    +                                   (do ((n-index 0 (1+ n-index))
    +                                        (s-index start (1+ s-index)))
    +                                       ((>= s-index end))
    +                                     (setf (aref new-array n-index)
    +                                           (aref sequence s-index)))
    +                                   new-array))))))))))
    +
    + +

    Examples:

    + +
    +(cl:subseq "012345" 2)          => "2345"
    +(cl:subseq "012345" 3 5)        => "34"
    +
    +(cl:subseq '(0 1 2 3 4 5) 2)    => (2 3 4 5)
    +(cl:subseq '(0 1 2 3 4 5) 3 5)  => (3 4)
    +
    +(cl:subseq #(0 1 2 3 4 5) 2)    => #(2 3 4 5)
    +(cl:subseq #(0 1 2 3 4 5) 3 5)  => #(3 4)
    +
    + +

    In XLISP, neither subseq nor +'cl:subseq' can be used as arguments to +setf. +See cl:replace below how to replace +subsequences.

    + +

      Back to top

    + + + +
    + +

    cl:replace

    + +
    + +

    + +
    +
    (cl:replace sequence1 sequence2 &key start1 end1 start2 end2)
    +
    sequenceN - a list, string, or array
    +startN - the position of the first element in sequenceN, an integer
    +endN - the position following last element in sequenceN, defaults to the end of sequenceN
    +returns - the subsequence in the same type as sequence
    +
    + +

    + +

      Back to top

    + +
    + +

    map

    + +
    + +

    + +
    + +
    map result-type function sequence-1 [sequence-2 ...]
    +
    result-type - list, string, or array
    +function - a function, applied to each element of each sequenceN
    +sequenceN - a list, string, or array
    +returns - a sequence where each element is the result of applying the function to each element of each sequenceN
    +
    + +
    + +

    + +

    The 'sequence:string' function can handle lists and arrays containing not +only characters but also strings, because XLISP Unicode characters are +represented as strings.

    + +
    +(defun sequence:string (sequence)
    +  (if (stringp sequence)
    +      sequence
    +      (let ((result ""))
    +        (flet ((strcat-element (element)
    +                 (let ((string (cond ((stringp element) element)
    +                                     ((characterp element) (string element))
    +                                     (t (error "not a character or string"
    +                                               element)))))
    +                   (setq result (strcat result string)))))
    +          (case (type-of sequence)
    +            (array  (let ((end (length sequence)))
    +                      (dotimes (index end)
    +                        (if (eq (aref sequence index) '*unbound*)
    +                            (error "not a character or string" '*unbound*)
    +                            (strcat-element (aref sequence index))))))
    +            (cons   (let ((end (length sequence)))
    +                      (if (not (consp (last sequence)))
    +                          (error "not a proper sequence" sequence)
    +                          (dotimes (index end)
    +                            (if (eq (nth index sequence) '*unbound*)
    +                                (error "not a character or string" '*unbound*)
    +                                (strcat-element (nth index sequence)))))))
    +            (nil    nil)
    +            (t      (error "not a sequence" sequence)))
    +          result))))
    +
    +(defun list-to-string (list)
    +  (let ((string ""))
    +    (dolist (element list string)
    +      (setq string (strcat string (if (consp element)
    +                                      (list-to-string element)
    +                                      (format nil "~a" element)))))))
    +
    + +
    +(defun sequence:vector (sequence)
    +  (if (not (boundp 'sequence))
    +      (error "not a sequence" '*unbound*)
    +      (let ((type (type-of sequence)))
    +        (if (not (member type '(array cons nil string)))
    +            (error "not a sequence" sequence)
    +            (let* ((end (length sequence))
    +                   (result (make-array end)))
    +              (unless (zerop end)
    +                (case type
    +                  (array  (dotimes (index end)
    +                            (setf (aref result index)
    +                                  (if (eq (aref sequence index) '*unbound*)
    +                                      '*unbound*
    +                                      (aref sequence index)))))
    +                  (cons   (if (not (consp (last sequence)))
    +                              (error "not a proper sequence" sequence)
    +                              (dotimes (index end)
    +                                (setf (aref result index)
    +                                      (if (eq (nth index sequence) '*unbound*)
    +                                          '*unbound*
    +                                          (nth index sequence))))))
    +                  (string (dotimes (index end)
    +                            (setf (aref result index)
    +                                  (char sequence index))))))
    +              result)))))
    +
    + +
    +(defun sequence:array (sequence)
    +  (let ((type (type-of sequence)))
    +    (if (not (member type '(array cons nil string)))
    +        (error "not a sequence" sequence)
    +        (let* ((end (length sequence))
    +               (result (make-array end)))
    +          (if (zerop end)
    +              result
    +              (labels ((array-element (element index)
    +                         (setf (aref result index)
    +                               (if (or (consp element) (arrayp element))
    +                                   (sequence:array element)
    +                                   element))))
    +                (case type
    +                  (array  (dotimes (index end)
    +                            (if (eq (aref sequence index) '*unbound*)
    +                                (setf (aref result index) '*unbound*)
    +                                (array-element (aref sequence index) index))))
    +                  (cons   (if (not (consp (last sequence)))
    +                              (error "not a proper sequence" sequence)
    +                              (dotimes (index end)
    +                                (if (eq (nth index sequence) '*unbound*)
    +                                    (setf (aref result index) '*unbound*)
    +                                    (array-element (nth index sequence) index)))))
    +                  (string (dotimes (index end)
    +                            (setf (aref result index)
    +                                  (char sequence index)))))
    +                result))))))
    +
    +
    +(defun list-to-array (list)
    +  (let* ((end (length list))
    +         (array (make-array end)))
    +    (dotimes (index end array)
    +      (let ((element (nth index list)))
    +        (setf (aref array index) (if (consp element)
    +                                     (list-to-array element)
    +                                     element))))))
    +
    +(defun list-from-input (input)
    +  (let (result)
    +    (dolist (element input)  ; input is always a list
    +      (format t ";; ~s ~s~%" element (type-of element))
    +      (case (type-of element)
    +        (nil    (push element result))
    +        (cons   (if (consp (last element))
    +                    (push element result)
    +                    (error "not a proper list" element)))
    +        (array  (let (local (end (length element)))
    +                  (dotimes (index end)
    +                    (push (aref element index) local))
    +                  (push (reverse local) result)))
    +        (string (let (local (end (length element)))
    +                  (dotimes (index end)
    +                    (push (char element index) local))
    +                  (push (reverse local) result)))
    +        (t      (error "not a sequence" element))))
    +    (reverse result)))
    +
    +(defun list-from-input* (input &optional recursion-p)
    +  (let (result)
    +    (labels ((test (element)
    +               (if (member (type-of element) '(array cons string))
    +                   (list-from-input* element t)
    +                   (if (or recursion-p (null element))
    +                       element
    +                       (error "not a sequence" element)))))
    +      (format t ";; ~s~%" input)
    +      (case (type-of input)
    +        (nil     (push input result))
    +        (cons    (if (consp (last input))
    +                     (dolist (element input)
    +                       (push (test element) result))
    +                     (error "not a proper list" input)))
    +        (array   (let ((end (length input)))
    +                   (dotimes (index end)
    +                     (push (test (aref input index)) result))))
    +        (string  (let ((end (length input)))
    +                   (dotimes (index end)
    +                     (push (test (char input index)) result))))
    +        (t       (error "not a sequence" input)))
    +      (reverse result))))
    +
    +(defun map (result-type function &rest sequences)
    +  (if (not (member result-type '(list string array)))
    +      (error "invalid result type" result-type)
    +      (let* ((input-list (list-from-input sequences))
    +             (result (if function
    +                         (apply #'mapcar (cons function input-list))
    +                         (if (rest sequences)
    +                             input-list
    +                             (first input-list)))))
    +        (case result-type
    +          (list   result)
    +          (string (list-to-string result))
    +          (array  (list-to-array result))))))
    +
    +(defun mapcar* (function &rest lists)
    +  (unless (or (null lists)
    +              (dolist (list lists nil)
    +                (and (null list) (return t))))
    +    (let ((end (length lists))
    +          (result nil))
    +      (do ((stop nil) (recurse t t)) (stop)
    +        (let (local)
    +          (dotimes (index end)
    +            (let ((first (first (nth index lists)))
    +                  (rest  (rest  (nth index lists))))
    +              (push first local)
    +              (unless (consp first) (setq recurse nil))
    +              (setf (nth index lists) rest)
    +              (when (null rest) (setq stop t))))
    +          (setq local (reverse local))
    +          (format t ";; local: ~a~%" local)
    +          (format t ";; lists: ~a~%" lists)
    +          (format t ";; recurse: ~a~%" recurse)
    +          (if recurse
    +              (push (apply #'mapcar* (cons function local)) result)
    +              (push (apply function local) result))))
    +      (reverse result))))
    +
    +(defun map* (result-type function &rest sequences)
    +  (if (not (member result-type '(list string array)))
    +      (error "invalid result type" result-type)
    +      (let* ((input-list (list-from-input* sequences))
    +             (result (if function
    +                         (apply #'mapcar* (cons function input-list))
    +                         (if (rest sequences)
    +                             input-list
    +                             (first input-list)))))
    +        (format t ";; ~s~%" input-list)
    +        (case result-type
    +          (list   result)
    +          (string (list-to-string result))
    +          (array  (list-to-array result))))))
    +
    + +

      Back to top

    + + + +
    + +
    find item sequence &key from-end test test-not start end keyelement
    +
    find-if predicate sequence &key from-end start end key ⇒ element
    +
    find-if-not predicate sequence &key from-end start end key ⇒ element
    + +

    Search for an element of the sequence bounded by start and end that +satisfies the predicate or that satisfies the test or test-not, as +appropriate.

    + +
    count item sequence &key from-end start end key test test-not ⇒ n
    +
    count-if predicate sequence &key from-end start end key ⇒ n
    +
    count-if-not predicate sequence &key from-end start end key ⇒ n
    + +

    Count and return the number of elements in the sequence bounded by +start and end that satisfy the test.

    + +
    position item sequence &key from-end test test-not start end key ⇒ position
    +
    position-if predicate sequence &key from-end start end key ⇒ position
    +
    position-if-not predicate sequence &key from-end start end key ⇒ position
    + +

    Search sequence for an element that satisfies the test. The position +returned is the index within sequence of the leftmost (if from-end is true) +or of the rightmost (if from-end is false) element that satisfies the test; +otherwise nil is returned. The index returned is relative to the left-hand +end of the entire sequence, regardless of the value of start, end, or +from-end.

    + + + +
    +(defun list-find (element list &key from-end test test-not start end)
    +  (when from-end (setq list (reverse-list)))
    +  (first (cond (test (member element list :test test))
    +               (test-not (member element list :test-not test-not))
    +               (t (member element list)))))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/strings.htm b/docsrc/xlisp/xlisp-doc/examples/strings.htm new file mode 100644 index 0000000..1842c08 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/strings.htm @@ -0,0 +1,802 @@ + + +Characters and Strings + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Characters and Strings

    + +
    + +

    Strings are also Sequences.

    + + + + + +
    + +

    make-string

    + +
    + +
    +(defun make-string (length initial-element)
    +  (cond ((not (and (integerp length)
    +                   (plusp    length)))
    +         (error "not a positive integer" length))
    +        ((not (characterp initial-element))
    +         (error "not a character" initial-element))
    +        (t
    +         (let ((element (string initial-element))
    +               (string ""))
    +           (dotimes (x length)
    +             (setq string (strcat string element)))
    +           string))))
    +
    + +

      Back to top

    + + + +
    + +

    string*

    + +
    + +

    + +
    + +
    (string* [expr1 ...])
    +
    exprN - arbitrary Lisp expressions
    +returns - the expression[s], converted and concatenated into a single string
    +
    + +
    + +

    + +

    The 'string*' function tries to make a string out of everything:

    + +
    +(defun string* (&rest items)
    +  (if (null items)
    +      ""
    +      (let ((end (length items))
    +            (result ""))
    +        (labels ((strcat-element (element)
    +                   (let ((string (if (or (consp element) (arrayp element))
    +                                     (string* element)
    +                                     (format nil "~a" element))))
    +                     (setq result (strcat result string)))))
    +          (dotimes (index end)
    +            (if (eq (nth index items) '*unbound*)
    +                (strcat-element "*UNBOUND*")
    +                (let ((item (nth index items)))
    +                  (case (type-of item)
    +                    (cons  (let ((end (length item)))
    +                             (when (not (consp (last item))) (incf end))
    +                             (dotimes (index end)
    +                               (if (eq (nth index item) '*unbound*)
    +                                   (strcat-element "*UNBOUND*")
    +                                   (strcat-element (nth index item))))))
    +                    (array (let ((end (length item)))
    +                             (dotimes (index end)
    +                               (if (eq (aref item index) '*unbound*)
    +                                   (strcat-element "*UNBOUND*")
    +                                   (strcat-element (aref item index))))))
    +                    (t     (strcat-element item))))))
    +          result))))
    +
    + +

    Examples:

    + +
    +(string*)              => ""
    +
    +(string* #\A "B" 'c)   => "ABC"
    +(string* 1 2 3)        => "123"
    +
    +(string* 1 "st")       => "1st"
    +(string* "2" #\n #\d)  => "2nd"
    +
    +(setq a 3)             => 3
    +(string* 'a "=" a)     => "A=3"
    +
    + +

    Nested expressions will be flattened:

    + +
    +(string* #(1 (#\2) "3"))  => "123"
    +
    + +

    The result may contain nonsense:

    + +
    +(string* #'car)                    => "#<Subr-CAR: #8645768>"
    +(string* '(lambda (x) (print x)))  => "LAMBDAXPRINTX"
    +
    + +

      Back to top

    + + + +
    + +

    POSIX Character Classes

    + +
    + +

    The built-in XLISP character test functions +upper-case-p, +lower-case-p, +both-case-p, return the boolean +values  T  or +NIL instead of the tested character, +while digit-char-p returns an +integer or NIL, what is +handy if you want to convert arbitrary Lisp symbols into numbers without +producing an error, but all this is impractical for writing a string +parser.

    + +

    The following functions implement tests for the standard POSIX character +classes, where all functions return the tested character if the test +succeeds, or NIL if the test +fails. The 'internal' functions do not check if the argument is +a character and therefore are faster than the 'user' functions. Also note +that XLISP is limited to ASCII characters, so there is no way to find out if +an unicode character is upper- or lowercase if the character code is greater +than ASCII 127.

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      POSIX  -  Internal  -  User Function
      [:alnum:]  -  char:alnum-p  -  alnum-character-p  - alphanumeric = [a-z], [A-Z], [0-9]
      [:alpha:]  -  char:alpha-p  -  alpha-character-p  - alphabetic = [a-z], [A-Z]
      [:blank:]  -  char:blank-p  -  blank-character-p  - space and horizontal-tab
      [:cntrl:]  -  char:cntrl-p  -  cntrl-character-p  - code-chars 0-31 and 127
      [:digit:]  -  char:digit-p  -  digit-character-p  - decimal = [0-9]
      [:graph:]  -  char:graph-p  -  graph-character-p  - graphical = alnum + punct
      [:lower:]  -  char:lower-p  -  lower-character-p  - lowercase = [a-z]
      [:print:]  -  char:print-p  -  print-character-p  - printable = alnum + punct + space
      [:punct:]  -  char:punct-p  -  punct-character-p  - punctuation marks
      [:space:]  -  char:space-p  -  space-character-p  - characters producing whitespace
      [:upper:]  -  char:upper-p  -  upper-character-p  - uppercase = [A-Z]
      [:xdigit:]  -  char:xdigit-p  -  xdigit-character-p  - hexadecimal = [0-9], [a-f], [A-F]

    + +

    Internal Functions for POSIX character classes:

    + + + +
    +;; alphanumeric characters = a-z, A-z, 0-9
    +
    +(defun char:alnum-p (char)
    +  (and (alphanumericp char)
    +       char))
    +
    +;; alphabetic characters = a-z, A-Z
    +
    +(defun char:alpha-p (char)
    +  (and (both-char-p char)
    +       char))
    +
    +;; blanks = space and horizontal-tab
    +
    +(defun char:blank-p (char)
    +  (and (or (char= char #\Space)
    +           (char= char #\Tab))
    +       char))
    +
    +;; control characters = code-chars 0-31 and 127
    +
    +(defun char:cntrl-p (char)
    +  (let ((code (char-code char)))
    +    (and (or (<= 0 code 31)
    +             (= code 127))
    +         char)))
    +
    +;; decimal digits = 0-9
    +
    +(defun char:digit-p (char)
    +  (and (digit-char-p char)
    +       char))
    +
    +;; graphical characters = alnum + punct
    +
    +(defun char:graph-p (char)
    +  (and (<= 33 (char-code char) 126)
    +       char))
    +
    +;; lowercase characters = a-z
    +
    +(defun char:lower-p (char)
    +  (and (lower-case-p char)
    +       char))
    +
    +;; printable characters = alnum + punct + space
    +
    +(defun char:print-p (char)
    +  (and (<= 32 (char-code char) 126)
    +       char))
    +
    +;; punctuation marks
    +
    +(defun char:punct-p (char)
    +  (let ((code (char-code char)))
    +    (and (or (<=  33 code  47)   ;  ! " # $ % & ' ( ) * + , - . /
    +             (<=  58 code  64)   ;  : ; < = > ? @
    +             (<=  91 code  96)   ;  [ \ ] ^ _ `
    +             (<= 123 code 126))  ;  { | } ~
    +         char)))
    +
    +;; characters producing whitespace
    +;;
    +;;  9 = horizontal tab   10 = line feed         11 = vertical tab
    +;; 12 = form feed        13 = carriage return   32 = space
    +
    +(defun char:space-p (char)
    +  (and (member (char-code char) '(9 10 11 12 13 32))
    +       char))
    +
    +;; uppercase characters = A-Z
    +
    +(defun char:upper-p (char)
    +  (and (upper-case-p char)
    +       char))
    +
    +;; hexadecimal digits = 0-9, a-f, A-F
    +
    +(defun char:xdigit-p (char)
    +  (and (or (digit-char-p char)
    +           (let ((code (char-code char)))
    +             (or (<= 65 code  70)     ; A-Z
    +                 (<= 97 code 102))))  ; a-z
    +       char))
    +
    + +

    User Functions for POSIX character classes:

    + + + +
    +;; alphanumeric characters = a-z, A-z, 0-9
    +
    +(defun alnum-character-p (char)
    +  (and (characterp char)
    +       (char:alnum-p char)))
    +
    +;; alphabetic characters = a-z, A-Z
    +
    +(defun alpha-character-p (char)
    +  (and (characterp char)
    +       (char:alpha-p char)))
    +
    +;; blanks = space and horizontal-tab
    +
    +(defun blank-character-p (char)
    +  (and (characterp char)
    +       (char:blank-p char)))
    +
    +;; control characters = code-chars 0-31 and 127
    +
    +(defun cntrl-character-p (char)
    +  (and (characterp char)
    +       (char:cntrl-p char)))
    +
    +;; decimal digits = 0-9
    +
    +(defun digit-character-p (char)
    +  (and (characterp char)
    +       (char:digit-p char)))
    +
    +;; graphical characters = alnum + punct
    +
    +(defun graph-character-p (char)
    +  (and (characterp char)
    +       (char:graph-p char)))
    +
    +;; lowercase characters = a-z
    +
    +(defun lower-character-p (char)
    +  (and (characterp char)
    +       (char:lower-p char)))
    +
    +;; printable characters = alnum + punct + space
    +
    +(defun print-character-p (char)
    +  (and (characterp char)
    +       (char:print-p char)))
    +
    +;; punctuation marks
    +
    +(defun punct-character-p (char)
    +  (and (characterp char)
    +       (char:punct-p char)))
    +
    +;; characters producing whitespace
    +
    +(defun space-character-p (char)
    +  (and (characterp char)
    +       (char:space-p char)))
    +
    +;; uppercase characters = A-Z
    +
    +(defun upper-character-p (char)
    +  (and (characterp char)
    +       (char:upper-p char)))
    +
    +;; hexadecimal digits = 0-9, a-f, A-F
    +
    +(defun xdigit-character-p (char)
    +  (and (characterp char)
    +       (char:xdigit-p char)))
    +
    + +

      Back to top

    + + + +
    + +

    Unicode

    + +
    + +

    The UTF-8 functions may help to write custom UTF-8 string +access functions like UTF-8-SUBSEQ or +UTF-8-STRING-SEARCH with no need to care about the underlying +low-level octal sequences.

    + + + +

    In the list of "string-characters" every ASCII or UTF-8 character +from 1-byte to 4-byte is represented by its own list element:

    + +
    +(utf-8-string-to-list "hällö") => ("h" "\303\244" "l" "l" "\303\266")
    +                                    h       ä      l   l       ö
    +
    + +

    The list can be manipulated by standard Nyquist list functions and +then re-converted into a string by UTF-8-LIST-TO-STRING.

    + +Practical examples + +

    In Nyquist code, non-ASCII characters are represented by their +native bytes sequences, represented by escaped octal numbers:

    + +
    +(print "ä")  => "\303\244"  ; on UTF-8 systems
    +
    + +

    So for example matching the second "ä" from "hällo" in the list +above, represented by the octal sequence "\303\244":

    + +
    +(let ((string-list (utf-8-string-to-list "hällö")))
    +  (string= "ä" (nth 1 string-list)))  ; 0 = first, 1 = second element
    +=> T                                  ; T = true = identified
    +
    + +

    Advantage: The number of the element in the list is the same as the +number of the character in the string, independent from the number of bytes +in the underlying character encoding.

    + +;; The UTF-8 toolbox is intended to manipulate UTF-8 encoded file- +;; or directory names, typed in by the user or read from environment +;; variables, before they are given to SETDIR or OPEN. +;; +;; Information from the environment +;; +;; Because the encoding of the non-ASCII characters depends on the +;; underlying operation system [with non-unicode operation systems +;; there will be no UTF-8 encoding available], it's always better +;; to refer to strings from environment variables, user input, or +;; strings returned from the underlying file system, instead of +;; hand-coded strings in the Nyquist source code, for example: +;; +;; GET-ENV - can read strings from environment variables: +;; +;; (defun user-home-directory () +;; (or (get-env "HOME") ; Unix +;; (get-env "UserProfile"))) ; Windows +;; +;; On Windows, there is no HOME variable defined by Windows itself, +;; but most programs will respect a HOME variable, if one has been +;; defined by the user. That's why the HOME variable is read first. +;; +;; SETDIR - can test if a directory exists and return its name: +;; +;; (defun directory-exists-p (string) +;; (let ((orig-dir (setdir ".")) +;; (new-dir (setdir string))) +;; (when (string/= orig-dir new-dir) +;; (setdir orig-dir) +;; new-dir))) +;; +;; SETDIR always returns abloute direcory names, even if STRING is a +;; relative direcory name. That's why DIRECTORY-EXISTS-P first stores +;; the absolute name of the current working directory in the ORIG-DIR +;; variable and compares it then against the absolute directory name +;; returned by SETDIR when it tries to change the directory to STRING. +;; +;; OPEN - can test if a file exists and return its name: +;; +;; (defun file-exists-p (string) +;; (unless (directory-exists-p string) +;; (let (file-stream) +;; (unwind-protect +;; (setq file-stream (open string)) +;; (when file-stream (close file-stream))) +;; (when file-stream string)))) +;; +;; On Unix, a directory is a special kind of file, so the Nyquist/XLISP +;; OPEN function opens directories, too. That's why FILE-EXISTS-P first +;; must test and make sure that STRING is not the name of a directory. +;; +;;; Known bugs and limitations of the UTF-8 toolbox: +;; +;; The UTF-8 toolbox does not provide support for UTF-8 case-detection +;; or UTF-8 case-conversion. It cannot be detected if a UTF-8 character +;; is upper- or lowercase, it's also not possible to convert characters +;; from upper- to lowercase or vice versa. +;; +;; The library does not provide functions to compare UTF-8 characters +;; or to sort UTF-8 characters. +;; +;; The XLISP character functions do not work with UTF-8 octal sequences, +;; so matching must be done via XLISP's STRING= and STRING/= functions. +;; +;; The XLISP string comparison functions like STRING<, STRING>, etc. +;; do not work reliably with multibyte characters. +;; +;; The string matching and sorting algorithms of the Unicode Consortium +;; are too complex to be implemented in XLISP with reasonable speed. +;; +;; See: http://www.unicode.org/reports/tr10/ - string comparison +;; +;; The library is implemented in interpreted Lisp, so please do not +;; expect high-speed performance with advanced list manipulations. +;; +;; The library still has not been tested with ISO encoded systems. +;; + +

    UTF-8 Encoding - see also http://en.wikipedia.org/wiki/UTF-8

    + + +

    In an UTF-8 encoded character the first byte starts with:

    + +
    +;;    one-byte  0xxxxxxx -> legal char-codes   0 to 127  [UTF-8/ASCII]
    +;;    two-byte  110xxxxx -> legal char-codes 194 to 223  [UTF-8]
    +;;  three-byte  1110xxxx -> legal char-codes 224 to 239  [UTF-8]
    +;;   four-byte  11110xxx -> legal char-codes 240 to 244  [UTF-8]
    +;;
    +;; The second, third, and fourth characters start with:
    +;;
    +;;              10xxxxxx -> legal char-codes 128 to 191  [UTF-8]
    +
    + + +

    UTF-8-BYTE-P tests if a XLISP character is a valid UTF-8 byte

    + +
    +(defun utf-8-byte-p (char)
    +  (when (characterp char)
    +    (let ((code (char-code char)))
    +      (when (or (<=   0 code 191)
    +                (<= 194 code 244))  
    +        char))))
    +
    + +

    UTF-8-BYTES tries to determine from the XLISP character code +how many bytes the character has in UTF-8 encoding

    + +
    +(defun utf-8-bytes (char)
    +  (cond ((not (characterp char))
    +         (error "not a character" char))
    +        ((not (utf-8-byte-p char))
    +         (error "invalid UTF-8 byte" char))
    +        (t
    +         (let ((code (char-code char)))
    +           (cond ((<=   0 code 127) 1)  ; one byte [= ASCII]
    +                 ((<= 194 code 223) 2)  ; two bytes
    +                 ((<= 224 code 239) 3)  ; three bytes
    +                 ((<= 240 code 244) 4)  ; four bytes
    +                 (t (error "utf-8-bytes: not an UTF-8 identifer" char)))))))
    +
    + +

    UTF-8-STRING-TO-LIST converts a string containing ASCII or UTF-8 +characters from one to four bytes into a list, where:

    + +
      +
    • ASCII - ASCII string
    • +
    • UTF-8 - string of octal-sequences
    • +
    + +;; Every character (single-byte or multi-byte) is represented +;; by its own list element: +;; +;; (utf-8-string-to-list "hällö") => ("h" "\303\244" "l" "l" "\303\266") +;; h ä l l ö +;; +;; The list can be manipulated by standard XLISP list functions and +;; then re-converted into a string by UTF-8-LIST-TO-STRING below. + +
    +(defun utf-8-string-to-list (string)
    +  (cond
    +    ((not (stringp string))
    +     (error "utf-8-string-to-list: not a string" string))
    +    ((string= "" string) nil)
    +    (t
    +     (let ((end (length string))
    +           (list nil))
    +       (do ((index 0 (1+ index)))
    +           ((>= index end))
    +         (let* ((char (char string index))
    +                (bytes (1- (utf-8-bytes char)))
    +                (utf-8 (string char)))
    +           (dotimes (rest-of bytes) ; runs only if bytes > 0
    +             (incf index)
    +             (if (> index end)
    +                 (error "utf-8-string-to-list: index out of range" index)
    +                 (let ((byte (char string index)))
    +                   (if (not (utf-8-byte-p byte))
    +                       (error "utf-8-string-to-list: invalid UTF-8 byte" byte)
    +                       (setq utf-8 (strcat utf-8 (string byte)))))))
    +           (push utf-8 list)))
    +       (reverse list)))))
    +
    + +;; UTF-8-LIST-TO-STRING re-converts a list containing ASCII and +;; UTF-8 "string-characters" back to a XLISP string, intended +;; to be given to SETDIR or OPEN for file or directory operations. + +
    +(defun utf-8-list-to-string (list)
    +  (cond ((not (listp list))
    +         (error "utf-8-list-to-string: not a list" list))
    +        ((null list) "")
    +        (t
    +         (let ((result ""))
    +           (dolist (string list)
    +             (if (not (stringp string))
    +                 (error "utf-8-list-to-string: not a string" string)
    +                 (setq result (strcat result string))))
    +           result))))
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/xlisp/ash.htm b/docsrc/xlisp/xlisp-doc/examples/xlisp/ash.htm new file mode 100644 index 0000000..2d17d98 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/xlisp/ash.htm @@ -0,0 +1,130 @@ + + +ash + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    ash

    + +
    + +

    The 'ash' functio performs an 'arithmetic shift' operation:

    + +

    + +
    +
    (ash integer count)
    +
    integer - an integer expression
    +count - an integer expression
    +returns - the number shifted by count
    +
    + +

    + +
    +(defun ash (integer count)
    +  (or (integerp integer) (error "not an integer" integer))
    +  (or (integerp count)   (error "not an integer" count))
    +  (let* ((shift (* integer (expt 2.0 count)))
    +         (trunc (truncate shift)))
    +    ;; XLISP implementation of (FLOOR SHIFT)
    +    (if (or (plusp shift) (= shift trunc))
    +        trunc
    +        (1- trunc))))
    +
    + +

    The 'ash' functio performs an arithmetic shift operation on the binary +representation of the 'integer' argument, which is treated as if it were +binary. The 'integer' argument is shifted arithmetically to the +left by 'count' bit positions if 'count' is positive, or to the right by +'count' bit positions if 'count' is negative. The shifted value +of the same sign as 'integer' is returned.

    + +

    The 'ash' function performs the computation:

    + +
    +floor (integer * 2^count)
    +
    + +

    Logically, the 'ash' function moves all of the bits in integer to the +left, adding zero-bits at the right, or moves them to the +right, discarding bits.

    + +

    The 'ash' function is defined to behave as if integer were represented in +two's complement form, regardless of how integers are represented +internally.

    + +

    Examples:

    + +
    +(ash 16  1)  => 32
    +(ash 16  0)  => 16
    +(ash 16 -1)  => 8
    +
    + +
    +(defun debug:ash (integer count)
    +  (let ((shifted (ash integer count)))
    +    (format t "integer: ~a~%" (bin-string integer :all))
    +    (format t "shifted: ~a~%" (bin-string shifted :all))
    +    shifted))
    +
    + +

    See Binary Integer Numbers for +the 'bin-string' function.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/xlisp/bsh.htm b/docsrc/xlisp/xlisp-doc/examples/xlisp/bsh.htm new file mode 100644 index 0000000..31c8af6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/xlisp/bsh.htm @@ -0,0 +1,127 @@ + + +bsh + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    bsh

    + +
    + +

    The 'bsh' functio performs an 'binary shift' operation:

    + +

    + +
    +
    (bsh integer count)
    +
    integer - an integer expression
    +count - an integer expression
    +returns - the number shifted by count
    +
    + +

    + +
    +(defun bsh (integer count)
    +  (or (integerp integer) (error "not an integer" integer))
    +  (or (integerp count)   (error "not an integer" count))
    +  (if (zerop count)
    +      integer
    +      (let ((digits (or (dolist (bits '(16 32 64 128) nil)
    +                          (let ((fixnum (round (expt 2.0 (1- bits)))))
    +                            (and (plusp (1- fixnum))
    +                                 (minusp fixnum)
    +                                 (return bits))))
    +                        (error "integer limit not found")))
    +            (list nil)
    +            (string "#b"))
    +        (dotimes (x digits)
    +          (let ((digit (logand (round (expt 2.0 x)) integer)))
    +            (push (if (zerop digit) "0" "1") list)))
    +        (dotimes (x digits)
    +          (let ((digit (if (< -1 count digits) (nth count list) "0")))
    +            (setq string (strcat string digit))
    +            (incf count)))
    +        (eval (read (make-string-input-stream string))))))
    +
    + +

    The 'bsh' function performs a binary shift operation on the 'integer' +argument. The bits of the 'integer' argument is shifted to the +left by 'count' positions if 'count' is positive, or to the right by 'count' +positions if 'count' is negative. The missing bits are filled +with zeros.

    + +

    Examples:

    + +
    +(bsh 16  1)  =>
    +(bsh 16  0)  =>
    +(bsh 16 -1)  =>
    +
    + +
    +(defun debug:bsh (integer count)
    +  (let ((shifted (bsh integer count)))
    +    (format t "integer: ~a~%" (bin-string integer :all))
    +    (format t "shifted: ~a~%" (bin-string shifted :all))
    +    shifted))
    +
    + +

    See Binary Integer Numbers for +the 'bin-string' function.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/xlisp/ceiling.htm b/docsrc/xlisp/xlisp-doc/examples/xlisp/ceiling.htm new file mode 100644 index 0000000..a005ff1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/xlisp/ceiling.htm @@ -0,0 +1,103 @@ + + +ceiling + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    ceiling

    + +
    + +

    The 'ceiling' function +truncates an integer or +floating-point number toward positive infinity:

    + +

    + +
    +
    (ceiling number)
    +
    number - an integer or floating-point expression
    +returns - the integer result of truncating number
    +
    + +

    + +
    +(defun ceiling (number)
    +  (let ((trunc (truncate number)))
    +    (if (or (minusp number) (= number trunc))
    +        trunc
    +        (1+ trunc))))
    +
    + +

    The 'ceiling' function computes an integer number that has +been truncated toward positive infinity. That is, the result +represents the smallest mathematical integer that is not smaller than the +number given as argument.

    + +

    Examples:

    + +
    +(ceiling 3)    => 3      (ceiling -3)    => -3
    +(ceiling 3.0)  => 3      (ceiling -3.0)  => -3
    +(ceiling 3.1)  => 4      (ceiling -3.1)  => -3
    +(ceiling 3.5)  => 4      (ceiling -3.5)  => -3
    +(ceiling 3.9)  => 4      (ceiling -3.9)  => -3
    +(ceiling 4.0)  => 4      (ceiling -4.0)  => -4
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/examples/xlisp/floor.htm b/docsrc/xlisp/xlisp-doc/examples/xlisp/floor.htm new file mode 100644 index 0000000..5851166 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/examples/xlisp/floor.htm @@ -0,0 +1,103 @@ + + +floor + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    floor

    + +
    + +

    The 'floor' function +truncates an integer or +floating-point number toward negative infinity:

    + +

    + +
    +
    (floor number)
    +
    number - an integer or floating-point expression
    +returns - the integer result of truncating number
    +
    + +

    + +
    +(defun floor (number)
    +  (let ((trunc (truncate number)))
    +    (if (or (plusp number) (= number trunc))
    +        trunc
    +        (1- trunc))))
    +
    + +

    The 'floor' function computes an integer number that has been truncated +toward negative infinity. That is, the result represents the +largest mathematical integer that is not larger than the number given as +argument.

    + +

    Examples:

    + +
    +(floor 3)    => 3      (floor -3)    => -3
    +(floor 3.0)  => 3      (floor -3.0)  => -3
    +(floor 3.1)  => 3      (floor -3.1)  => -4
    +(floor 3.5)  => 3      (floor -3.5)  => -4
    +(floor 3.9)  => 3      (floor -3.9)  => -4
    +(floor 4.0)  => 4      (floor -4.0)  => -4
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/internals/c-printf.htm b/docsrc/xlisp/xlisp-doc/internals/c-printf.htm new file mode 100644 index 0000000..d5e552a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/internals/c-printf.htm @@ -0,0 +1,518 @@ + + +ANSI C 'printf' Format + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    ANSI C 'printf' Format

    + +
    + +

    Nyquist/XLISP: The +*float-format* and +*integer-format* +variables define format strings for the underlying 'sprintf' C +function. In C, the same format string specification is +used for 'fprint' [writes to a file], 'printf' [writes to +standard output] and 'sprintf' [writes to another string]. These three +functions are meant in the following text with 'the printf functions'.

    + +

    ANSI C: The printf functions write output under control of a +format string that specifies how subsequent arguments are converted for +output. If there are insufficient arguments for the format, the behavior is +undefined. If the format is exhausted while arguments remain, the excess +arguments are evaluated but are otherwise ignored. The printf functions +return when the end of the format string is encountered.

    + +

      Back to top

    + + + +
    + +

    Format String

    + +
    + +

    The format string is composed of zero or more directives, which are +ordinary characters [except "%"], which are copied +unchanged to the output stream, and conversion specifications, each of which +results in fetching zero or more subsequent arguments. Each conversion +specification is introduced by the character "%":

    + +
    +%[flags][field-with][precision][data-type]conversion-type
    +
    + +

    After the "%", the following appear in sequence:

    + +
      + +
    • Flags - Zero or more flags that modify +the meaning of the conversion specification.

    • + +
    • Field Width - An optional decimal integer +specifying a minimum field width. If the converted value has +fewer characters than the field width, it will be padded with spaces on the +left to the field width. The field is padded on the right if +the  −  flag has been +given, or padded with zeros if the + 0  flag had been +given. A negative integer, given as 'field width' +argument, is interpreted as a + −  flag followed by +a positive field width.

    • + +
    • Precision - An optional decimal integer that +gives the minimum number of digits to appear for +integer conversions, the number of digits to appear +after the +decimal-point character for floating-point + e  and + f  conversions, or the +maximum number of significant digits for the floating-point + g  conversion.

      + +

      The precision takes the form of a period character followed by an +optional decimal integer:

      + +
      +.[integer]
      +
      + +

      If the integer is omitted, it is treated as zero, a +negative precision argument is taken as if it were missing.

      + +

      Note: In C, the precision also specifies the +maximum number of characters to be written from a string in 's' +conversion, but "%s" should not be used in the XLISP +*float-format* or +*integer-format* +variables, otherwise XLISP will crash.

    • + + + +
    • Data Type - An optional character specifying a +data type to be used for the +conversion.

      + +

      XLISP: Nyquist/XLISP uses C 'long' signed integers +and C 'double' floats only, so with floating-point +numbers no special data type needs to +be given, while integer conversions should always be +prefixed by a 'l' [lowercase L], otherwise the printed +representation of integer numbers may be differently than the behaviour of +the Nyquist/XLISP functions.

    • + +
    • Conversion Type - A character that specifies the +conversion type to be +applied.

    • + +
    + +

    Not with Nyquist/XLISP: In C, a 'field +width' or 'precision', or both, may be indicated by an asterisk * +instead of a digit string. In this case, an int argument supplies the field +width or precision. The arguments specifying field width or precision, or +both, shall appear [in that order] before the argument [if any] to be +converted.

    + +

      Back to top

    + + + +
    + +

    Flags

    + +
    + +

    The flag characters and their meanings are:

    + +

    + +
    + + + +

    −  [minus sign character]

    + +

    The result of the conversion will be left-justified +within the field.

    + + + +

    +  [plus sign character]

    + +

    The result of a signed conversion will always begin with a plus or +minus sign.

    + + + +

    space  [space character]

    + +

    If the first character of a signed conversion is not a sign, or if a +signed conversion results in no characters, a space will be prepended to the +result. If the 'space' and + +  flags both appear, the +'space' flag will be ignored.

    + + + +

    #  [hash character]

    + +

    The result is to be converted to an 'alternate form':

    + +

    Octal Numbers - For o conversion, it increases the precision to force the +first digit of the result to be a zero.

    + +

    Hexadecimal Numbers - For x or X conversion, a nonzero result will have +0x or 0X prepended to it.

    + +

    Floating-point Numbers - For e, E, f, g, and G conversions, the result +will always contain a decimal-point character, even if no digits follow it +(normally, a decimal-point character appears in the result of these +conversions only if a digit follows it). For g and G conversions, trailing +zeros will not be removed from the result. For other conversions, the +behavior is undefined.

    + +
    + + + +

    0  [number zero character]

    + +

    For integer d, i, o, u, x, X, and floating-point e, E, f, g, G +conversions, leading zeros [following any indication of sign or base] are +used to pad to the field width. +No space padding is performed. +If the '0' and + −  flags both +appear, the '0' flag will be ignored. For integer d, i, o, u, +x, X conversions, if a precision is specified, +the '0' flag will be ignored. For other +conversions, the behavior is undefined.

    + +
    + +

    + +

      Back to top

    + + + +
    + +

    Data Type

    + +
    + +

    + +
    + +

    h  [lowercase H character]

    + +

    A following d, i, o, u, x, or X conversion specifier applies to a +short int or unsigned short int argument [the argument will have been +promoted according to the integral promotions, and its value shall be +converted to short int or unsigned short int before printing].

    + +

    A following n conversion specifier applies to a pointer to a short int +argument.

    + +

    l  [lowercase L character]

    + +

    A following d, i, o, u, x, or X conversion specifier applies to a +long int or unsigned long int argument.

    + +

    A following n conversion specifier applies to a pointer to a long int +argument.

    + +

    L  [uppercase L character]

    + +

    A following e, E, f, g, or G conversion specifier applies to a long +double argument.

    + +
    + +

    + +

    If an h, l, or L appears with any other conversion specifier, the +behavior is undefined.

    + +

      Back to top

    + + + +
    + +

    Conversion Type

    + +
    + +

    Integer conversion:

    + +

    + +
    + + + +

    d, i, o, u, x, +X

    + +

    The integer argument is converted to: + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      d → signed decimal
      i → signed decimal
      o → unsigned octal
      u → unsigned decimal
      x → unsigned hexadecimal, using 'abcdef'
      X → unsigned hexadecimal, using 'ABCDEF'

    + +

    The precision specifies the minimum number +of digits to appear. If the value being converted can be +represented in fewer digits, it will be expanded with leading zeros. The +default precision is 1. The result of converting a zero value +with an explicit precision of zero results in no characters.

    + +XLISP: Nyquist/XLISP uses C 'long' signed integers, so +the integer conversions should always be prefixed by a 'l' [lowercase +L] indicating a 'long int' C +data type, otherwise the printed +representation of integer numbers may be differently than the behaviour of +the Nyquist/XLISP functions.

    + +
    + +

    + +

    Floating-point conversion:

    + +

    + +
    + + + +

    f

    + +

    The floating-point argument of C data type +'double' is converted to decimal notation in the style:

    + +
    +[-]ddd.ddd
    +
    + +

    where the number of digits after the decimal-point character +is equal to the precision specification. +If the precision is missing, it is +taken as 6. If the +precision is explicitly zero, no +decimal-point character appears. If a +decimal-point character appears, at least one digit appears +before it. The value is rounded to the appropriate +number of digits.

    + + + +

    e, E

    + +

    The floating-point argument of C data type +'double' is converted in the style:

    + +
    +[-]d.ddde+-dd
    +
    + +

    where there is one digit before the decimal-point character +[which is nonzero if the argument is nonzero] and the number of digits after +it is equal to the precision. If +the precision is missing, it is taken +as 6. If the +precision is zero, no +decimal-point character appears. The value is +rounded to the appropriate number of digits. The exponent +always contains at least two digits. If the value is zero, the +exponent is zero. The "E" conversion specifier will +produce a number with 'E' instead of 'e' introducing the exponent.

    + + + +

    g, G

    + +

    The floating-point argument of C data type +'double' is converted in style  f  or + e  or in style + E  in the case of a "G" +conversion specifier, with the precision +specifying the number of significant digits. If an explicit +precision is zero, it is taken as +1. The style used depends on the value converted. +Style  e  will be used only if +the exponent resulting from such a conversion is less than -4 +or greater than or equal to the precision. +Trailing zeros are removed from the fractional portion of the result. +A decimal-point character appears only if it is followed by +a digit.

    + +
    + +

    + +

    Other conversion types defined in ANSI C, but not to +be used with the XLISP +*float-format* and +*integer-format* +variables, because XLISP will produce nonsense or just simply will crash:

    + +

    + +
    + +

    c

    + +

    The integer argument is converted to an 'unsigned char', +and the resulting character is written.

    + +

    XLISP: If the +*float-format* or +*integer-format* +variable is set to "%c", then with integers or +floating-point numbers, the lowest 8 bit of the +internal binary representation will be interpreted as an +ASCII character.

    + +

    s

    + +

    The argument shall be a pointer to an array of character type. +Characters from the array are written up to [but not including] a +terminating null character. If the +precision is specified, no more than that many +characters are written. If the +precision is not specified or is greater than +the size of the array, the array shall contain a null character.

    + +XLISP: If
    + +

    p

    + +

    The argument shall be a pointer to 'void'. The value of the pointer +is converted to a sequence of printable characters, in an +implementation-defined manner.

    + +

    n

    + +

    The argument shall be a pointer to an integer into which is written +the number of characters written to the output stream so far by this call to +the C 'fprintf' function. No argument is +converted.

    + +

    %

    + +

    A "%" is written. No argument is +converted. The complete conversion specification shall be +"%%".

    + +
    + +

    + +

    If a conversion specification is invalid, the behavior is undefined. +In no case does a nonexistent or small +field width cause truncation of a +field. If the result of a conversion is wider than the +field width, the field is expanded +to contain the conversion result.

    + +

    The minimum value for the maximum number of characters produced by +any single conversion shall be 509.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/internals/xlisp-internals.html b/docsrc/xlisp/xlisp-doc/internals/xlisp-internals.html new file mode 100644 index 0000000..2a7ffc0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/internals/xlisp-internals.html @@ -0,0 +1,1206 @@ +XLISP Internals + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    XLISP Internals

    + +
    + +

    92Jan14 jsp@glia.biostr.washington.edu [Jeff Prothero]. Public Domain.

    + +
    +                 +---------------------+
    +                 | xlisp 2.1 internals |
    +                 +---------------------+
    +
    +         "Trust the Source, Luke, trust the Source!"
    +
    + +
    + +

    Contents

    + +
    + +
      +
    1. Who should read this?
    2. +
    3. What is an LVAL?
    4. +
    5. What is the obarray?
    6. +
    7. The Interpreter Stacks
    8. +
    9. What is a context?
    10. +
    11. What is an environment?
    12. +
    13. How are XLISP entities stored and identified?
    14. +
    15. How are vectors implemented?
    16. +
    17. How are strings implemented?
    18. +
    19. How are symbols implemented?
    20. +
    21. How are closures implemented?
    22. +
    23. How are objects implemented?
    24. +
    25. How are classes implemented?
    26. +
    27. How is the class hierarchy laid out?
    28. +
    29. How do we look up the value of a variable?
    30. +
    31. How are function calls implemented?
    32. +
    33. How are message-sends implemented?
    34. +
    35. How is garbage collection implemented?
    36. +
    37. How are the source files laid out?
    38. +
    39. How do I add a new primitive fn to xlisp?
    40. +
    41. Minor Observations.
    42. +
    43. Acknowledgements. 
    44. +
    + + + +
    + +

    Who should read this ?

    + +
    + +

    Anyone poking through the C implementation of XLISP for the first time. +This is intended to provide a rough roadmap of the global XLISP structures +and algorithms. If you just want to write lisp code in XLISP, you don't need +to read this file. Go read the +XLISP 2.0 Manual, +the XLisp Objects Primer, +and the XLisp Language Reference, +in about that order. If you want to tinker with the XLISP implementation +code, you should *still* read those three before reading this. The following +isn't intended to be exhaustively precise, that's what the source code is +for. It is intended only to allow you a fighting change of understanding the +code the first time through [instead of the third time].

    + +

    At the bottom of the file you'll find an example of how to add new +primitive functions to XLISP.

    + +

      Back to top

    + + + +
    + +

    What is an LVAL ?

    + +
    + +

    An LVAL is the C type for a generic pointer to an XLISP +garbage-collectable something. [Cons cell, object, string, closure, symbol, +vector, whatever.] Virtually every variable in the interpreter is an LVAL. +Cons cells contain two LVAL slots, symbols contains four LVAL slots, +etc.

    + +

      Back to top

    + + + +
    + +

    What is the obarray ?

    + +
    + +

    The obarray is the XLISP symbol table. More precisely, it is a hashtable +mapping ASCII strings [symbol names] to symbols. [The name 'obarray' is +traditional but a bit of a misnomer, since it contains only XLISP symbols, +and in particular contains no XLISP objects.] It is used when converting +Lisp expressions from text to internal form. Since it is a root for the +garbage collector, it also serves to distinguish permanent global-variable +symbols from other symbols. You can permanently protect a symbol from the +garbage collector by entering it into the obarray. This is called +'interning' the symbol. The obarray is called 'obarray' in C and +*obarray* +in XLISP. It is physically implemented as a vector-valued symbol.

    + +

      Back to top

    + + + +
    + +

    The Interpreter Stacks

    + +
    + +

    XLISP uses two stacks, an 'evaluation stack' and an 'argument stack'. +Both are roots for the garbage collector. The evaluation stack is largely +private to the interpreter and protects internal values from garbage +collection, while the argument stack holds the conventional user-visible +stackframes.

    + +

    The evaluation stack is an 'edepth'-long array of LVAL allocated by +'xldmem.c:xlminit()'. It grows zeroward.

    + +

    'xlstkbase' points to the zero-near end of the evaluation stack.

    + +

    'xlstktop' points to the zero-far end of the evaluation stack, the +occupied part of the stack lies between 'xlstack' and 'xlstktop'. Note that +'xlstktop' is *NOT* the top of the stack in the conventional sense of +indicating the most recent entry on the stack. 'xlstktop' is a static bounds +pointer which never changes once the stack is allocated.

    + +

    'xlstack' starts at the zero-far end of the evaluation stack. '*xlstack' +is the most recent LVAL on the stack. The garbage collector marks everything +reachable from the evaluation stack [among other things], so we frequently +push things on this stack while C code is manipulating them. [Via +'xlsave()', 'xlprotect()', 'xlsave1()', 'xlprot1()'.]

    + +

    The argument stack is an 'adepth'-long array of LVAL. It also grows +zeroward. The evaluator pushes arguments on the argument stack at the start +of a function call [form evaluation]. Built-in functions usually eat them +directly off the stack. For user-lisp functions 'xleval.c:evfun()' pops them +off the stack and binds them to the appropriate symbols before beginning +execution of the function body proper.

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    xlargstkbase - is the zero-near end of argument stack.
     
    xlargstktop - is the zero-far end of argument stack. Like 'xlstktop', + 'xlargstktop' is a static bounds pointer which never changes after the + stack is allocated.
     
    *xlsp [stack pointer] - is the most recent item on the argument stack.
     
    *xlfp [frame pointer] - is the base of the current stackframe.

    + +

      Back to top

    + + + +
    + +

    What is a context ?

    + +
    + +

    A XLISP context is something like a checkpoint, recording a particular +point buried in the execution history so that we can abort or return back to +it. Contexts are used to implement call and return, catch and throw, +signals, gotos, and breaks. 'xlcontext' points to the chain of active +contexts, the top one being the second-newest active context. [The newest, +that is, the current, active context is implemented by the variables +'xlstack', 'xlenv', 'xlfenv', 'xldenv', 'xlcontext', 'xlargv', 'xlargc', +'xlfp', and 'xlsp'.] Context records are written by 'xljump.c:xlbegin()' and +read by 'xljump.c:xljump()'. Context records are C structures on the C +program stack. They are not in the dynamic memory pool or on the Lisp +execution or argument stacks.

    + +

      Back to top

    + + + +
    + +

    What is an environment ?

    + +
    + +

    An environment is basically a store of symbol-value pairs, used to +resolve variable references by the Lisp program. XLISP maintains three +environments, in the global variables 'xlenv', 'xlfenv' and 'xldenv'.

    + +

    Lisp supports two sorts of binding, 'lexical binding' and 'dynamic +binding'. Lexically bound variables are visible only in code textually +within their binding form. Dynamically bound variables are visible in any +code *called* from the binding form. [Either kind of binding may be shadowed +by other declarations, of course.] Historically, Lisp has been moving from +dynamic binding [which is easy for interpreters to handle], to lexical +binding [which is easy for humans and compilers to handle]. Almost all XLISP +binding forms are lexically scoped. The most important exception is +progv.

    + +

    'xlenv' and 'xlfenv' track lexical bindings. 'xlenv' and 'xlfenf' are +conceptually a single environment, although they are implemented separately. +They are linked-list stacks which are pushed when we enter a function and +popped when we exit it. We also switch 'xlenv+xlfenf' environments entirely +when we begin executing a new closure [user-function written in Lisp].

    + +

    The 'xlenv' environment is the most heavily used environment. It is used +to resolve everyday data references to local variables. It consists of a +list of frames [and objects]. Each frame is a list of symbol-value pairs. In +the case of an object, we check all the instance and class variables of the +object, then do the same for its superclass, until we run out of +superclasses.

    + +

    The 'xlfenv' environment is maintained strictly parallel to 'xlenv', but +is used to find function values instead of variable values. The separation +may be partly for lookup speed and partly for historical reasons. Merging +these two lists into a single list [while distinguishing function bindings +from variable bindings, of course] would slightly decrease fn enter/exit +overhead while increasing the overhead of looking up each variable or +function binding.

    + +

    When we send a message, we set 'xlenv' to the value it had when the +message closure was built, then push on (obj msg-class), where 'msg-class' +is the [super]class defining the method. [We also set 'xlfenv' to the value +'xlfenv' had when the method was built.] This makes the object instance +variables part of the environment, and saves the information needed to +correctly resolve references to class variables, and to implement +send-super.

    + +

    The 'xldenv' environment tracks dynamic bindings. It is a simple list of +symbol-value pairs, treated as a stack. +progv uses it to save the old +values of symbols it binds, and it is also used to save old values of +'s_evalhook' and 's_applyhook' +[*evalhook* and +*applyhook*]. These latter +mostly support the debug facilities.

    + +

    These environments are manipulated in C via the 'xlisp.h' macros +'xlframe(e)', 'xlbind(s,v)', 'xlfbind(s,v)', 'xlpbind(s,v,e)', +'xldbind(s,v)', 'xlunbind(e)'.

    + +

      Back to top

    + + + +
    + +

    How are XLISP entities stored and identified ?

    + +
    + +

    Conceptually, XLISP manages memory as a single array of fixed-size +objects. Keeping all objects the same size simplifies memory management +enormously, since any object can be allocated anywhere, and complex +compacting schemes aren't needed. Every LVAL pointer points somewhere in +this array. Every XLISP object has the basic format 'xldmem.h:typdef +struct node':

    + +
    +struct node {
    +    char n_type;
    +    char n_flags;
    +    LVAL car;
    +    LVAL cdr;
    +}
    +
    + +

    where 'n_type' is one of:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FREE  - a node on the freelist.
    SUBR  - a function implemented in C. [Needs evaluated arguments.]
    FSUBR  - a 'special form' implemented in C. [Needs unevaluated arguments.]
    CONS  - a regular lisp cons cell.
    SYMBOL  - a symbol.
    FIXNUM  - an integer.
    FLONUM  - a floating-point number.
    STRING  - a string.
    OBJECT  - any object, including + class objects.
    STREAM  - an input or output file.
    VECTOR  - a variable-size array of LVALs.
    CLOSURE  - result of defun + or lambda, a function + written in Lisp.
    CHAR  - an ASCII character.
    USTREAM  - an internal stream.
    STRUCT  - a structure.

    + +

    Messages may be sent only to nodes with a 'n_type' of OBJECT.

    + +

    Obviously, several of the above types won't fit in a fixed-size two-slot +node. The escape is to have them 'malloc()' some memory and have one of the +slots point to it. VECTOR is the archetype. For example, see +'xldmem.c:newvector()'. To some extent, this 'malloc()' hack simply exports +the memory fragmentation problem to the C 'malloc()/free()' routines. +However, it helps keep XLISP simple, and it has the happy side-effect of +unpinning the body of the vector, so that vectors can easily be expanded and +contracted.

    + +

    The garbage collector has special-case code for each of the above node +types, so it can find all LVAL slots and recycle any 'malloc()'-ed ram when +a node is garbage-collected.

    + +

    XLISP pre-allocates nodes for all ASCII characters, and for small +integers. These nodes are never garbage-collected.

    + +

    As a practical matter, allocating all nodes in a single array is not very +sensible. Instead, nodes are allocated as needed, in segments of one or two +thousand nodes, and the segments linked by a pointer chain rooted at +'xldmem.c:segs'.

    + +

      Back to top

    + + + +
    + +

    How are vectors implemented ?

    + +
    + +

    An XLISP vector is a generic array of LVAL slots. Vectors are also the +canonical illustration of XLISP's escape mechanism for node types which need +more than two LVAL slots [the maximum possible in the fixed-size nodes in +the dynamic memory pool]. The node CAR/CDR slots for a vector hold a size +field plus a pointer to a 'malloc()'-ed ram chunk, which is automatically +'free()'-ed when the vector is garbage-collected.

    + +

    'xldmem.h' defines macros for reading and writing vector fields and +slots, 'getsize()', 'getelement()' and 'setelement()'. It also defines +macros for accessing each of the other types of XLISP nodes.

    + +

      Back to top

    + + + +
    + +

    How are strings implemented ?

    + +
    + +

    Strings work much like vectors. The node has a pointer to a 'malloc()'-ed +ram chunk which is automatically 'free()'-ed when the string gets +garbage-collected.

    + +

      Back to top

    + + + +
    + +

    How are symbols implemented ?

    + +
    + +

    A symbol is a generic user-visible Lisp variable, with separate slots for +print name, value, function, and property list. Any or all of these slots +[including name] may be NIL.

    + +

    You create an XLISP symbol from C by calling 'xlmakesym(name)' or +'xlenter(name)' [to make a symbol and enter it in the obarray].

    + +

    You may create symbols from XLISP by explicitly calling +gensym, +make-symbol [uninterned symbols], +or intern [interned symbol]. +However, the Lisp reader will create symbols on sight, so most Lisp symbols +are created as side-effects of expressions like:

    + +
    +'name
    +
    + +

    A symbol is interned if it +is listed in the *obarray*. +Various parts of the system, like the Lisp reader, treat the +*obarray* +essentially as the list of all known symbols. It is unusual but occasionally +useful to create uninterned symbols. You can make +read create an uninterned +symbol by preceding it with '#:'. In XLISP, a newly created symbol has no +value unless its name begins with a ':', in which case it has itself for its +value. Handy for keywords and message selectors.]

    + +

    Most of the symbol-specific code in the interpreter is in 'xlsym.c'.

    + +

    Physically, a symbol is implemented like a four-slot vector [print name, +value, function, and property list].

    + +

    Random musing: Abstractly, the Lisp symbols plus cons cells [etc.] +constitute a single directed graph, and the symbols mark spots where normal +recursive evaluation should stop. Normal Lisp programming practice is to +have a symbol in every cycle in the graph, so that recursive traversal can +be done without mark bits.

    + +

      Back to top

    + + + +
    + +

    How are closures implemented ?

    + +
    + +

    A closure, the return value from a +lambda, is a regular +coded-in-lisp function. Physically, it is implemented like an eleven-slot +vector, with the node 'n_type' field hacked to contain CLOSURE instead of +VECTOR. The vector slots contain:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    name  - a symbol, the first argument of + defun. + nil for + lambda closures.
    type  - 's_lambda' or 's_macro'. Must be 's_lambda' to be + executable.
    args  - list of required formal arguments [as symbols].
    oargs  - list of + &optional arguments, + each like (name (default specified-p)).
    rest  - name of '&rest' formal arguments, else + nil.
    kargs  - &key-word + arguments, each like ((':foo 'bar default specified-p))
    aargs  - &aux + variables, each like (('arg default)).
    body  - actual code [as a Lisp list] for the function.
    env  - value of 'xlenv' when the closure was built.
    fenv  - value of 'xlfend' when the closure was built.
    lambda  - the original formal args list in the + defun or + lambda.

    + +

    The lambda field is for printout purposes. The remaining fields store a +predigested version of the formal arguments list. This is a limited form of +compilation. By processing the arguments list at closure-creation time, we +reduce the work needed during calls to the closure.

    + +

      Back to top

    + + + +
    + +

    How are objects implemented ?

    + +
    + +

    An object is implemented like a vector, with the size determined by the +number of instance variables. The first slot in the vector points to the +class of the object, the remaining slots hold the instance variables for the +object. An object needs enough slots to hold all the instance variables +defined by its class, *plus* all the instance variables defined by all of +its superclasses.

    + +

      Back to top

    + + + +
    + +

    How are classes implemented ?

    + +
    + +

    A class is a specific kind of object, hence has a class pointer plus +instance variables. All classes have the following instance variables:

    + +
    +  MESSAGES     a list of (interned-symbol method-closure) pairs.
    +  IVARS        instance variable names, a list of interned symbols.
    +  CVARS        class variable names, a list of interned symbols.
    +  CVALS        class variable values, a vector of values.
    +  SUPERCLASS   a pointer to the superclass.
    +  IVARCNT      the number of class instance variables, a fixnum.
    +  IVARTOTAL    the total number of instance variables, a fixnum.
    +
    + +

    IVARCNT is the count of the number of instance variables defined by our +class. IVARTOTAL is the total number of instance variables in an object of this +class -- IVARCNT for this class plus the IVARCNTs from all of our +superclasses.

    + +
      +  Back to Top +
    + +

    How is the class hierarchy laid out ?

    + +

    The fundamental objects are the OBJECT and CLASS class objects. (Both are +instances of class CLASS, and since CLASSes are a particular kind of OBJECT, +both are also objects, with n_type==OBJECT. Bear with me!)

    + +

    OBJECT is the root of the class hierarchy: everything you can send a message +to has OBJECT as its class or super*class. (Vectors, chars, integers and so +forth stand outside the object hierarchy -- you can't send messages to them. I'm +not sure why Dave did it this way.) OBJECT defines the messages:

    + +
    +  :isnew -- Does nothing but return the object.
    +  :class -- Returns contents of class-pointer slot.
    +  :show  -- Prints names of obj, obj->class and instance vars.
    +
    + +

    Since a CLASS is a specialized type of OBJECT (with instance variables like +MESSAGES which generic OBJECTs lack), class CLASS has class OBJECT as its +superclass. The CLASS object defines the messages:

    + +
    +  :new    -- Create new object with self.IVARTOTAL LVAR slots, plus
    +             one for the class pointer. Point class slot to self.
    +             Set new.n_type char to OBJECT.
    +  :isnew  -- Fill in IVARS, CVARS, CVALS, SUPERCLASS, IVARCNT and
    +             IVARTOTAL, using parameters from :new call.  (The
    +             :isnew msg inherits the :new msg parameters because
    +             the  :isnew msg is generated automatically after
    +             each :new   msg, courtesy of a special hack in
    +             xlobj.c:sendmsg().)
    +  :answer -- Add a (msg closure) pair to self.MESSAGES.
    +
    + +

    Here's a figure to summarize the above, with a generic object thrown in for +good measure. Note that all instances of CLASS will have a SUPERCLASS pointer, +but no normal object will. Note also that the messages known to an object are +those which can be reached by following exactly one Class Ptr and then zero or +more Superclass Ptrs. For example, the generic object can respond to :ISNEW, +:CLASS and :SHOW, but not to :NEW or :ANSWER. (The functions implementing the +given messages are shown in parentheses.)

    + +
    +                                     NIL
    +                                      ^
    +                                      |
    +                                      |Superclass Ptr
    +                                      |
    +                             Msg+--------+
    +  :isnew (xlobj.c:obisnew) <----|  class |Class Ptr
    +  :class (xlobj.c:obclass) <----| OBJECT |------------------------------>+
    +  :show  (xlobj.c:objshow) <----|        |                               |
    +                                +--------+                               |
    +                                  ^  ^  ^                                |
    +        +---------+               |  |  |                                |
    +        | generic |Class Ptr      |  |  +<---------------+               |
    +        | object  |-------------->+  |Superclass Ptr     ^Superclass Ptr |
    +        +---------+                  |                   |               |
    +                             Msg+--------+          +---------+          |
    +  :isnew (xlobj.c:clnew)   <----| class  |Class Ptr | generic |Class Ptr |
    +  :new   (xlobj.c:clisnew) <----| CLASS  |------->+ | CLASS   |------->+ |
    +  :answer(xlobj.c:clanswer)<----|        |        | |         |        | |
    +                                +--------+        | +---------+        | |
    +                                   ^  ^           |                    | |
    +                                   |  |           v                    v |
    +                                   |  +-----------+ <------------------+ v
    +                                   +<------------------------------------+
    +
    + +

    Thus, class CLASS inherits the :CLASS and :SHOW messages from class OBJECT, +overrides the default :ISNEW message, and provides new messages :NEW and +:ANSWER.

    + +

    New classes are created by (send CLASS :NEW ...) messages. Their Class Ptr +will point to CLASS. By default, they will have OBJECT as their superclass, but +this can be overridden by the second optional argument to :NEW.

    + +

    The above basic structure is set up by xlobj.c:xloinit().

    + +
      +  Back to Top +
    + +

    How do we look up the value of a variable ?

    + +

    When we're cruising along evaluating an expression and encounter a symbol, +the symbol might refer to a global variable, an instance variable, or a class +variable in any of our superclasses. Figuring out which means digging through +the environment. The canonical place this happens is in xleval.c:xleval(), which +simply passes the buck to xlsym.c:xlgetvalue(), which in turn passes the buck to +xlxsym.c:xlxgetvalue(), where the fun of scanning down xlenv begins. The xlenv +environment looks something like

    + +
    +           Backbone    Environment frame contents
    +           --------    --------------------------
    +  xlenv --> frame      ((sym val) (sym val) (sym val) ... )
    +            frame      ...
    +            object     (obj msg-class)
    +            frame      ...
    +            object     ...
    +            frame      ...
    +            ...
    +
    + +

    The "frame" lines are due to everyday nested constructs like LET expressions, +while the "object" lines represent an object environment entered via a message +send. xlxgetvalue scans the enviroment left to right, and then top to bottom. It +scans down the regular environment frames itself, and calls +xlobj.c:xlobjgetvalue() to search the object environment frames.

    + +

    xlobjgetvalue() first searches for the symbol in the msg-class, then in all +the successive superclasses of msg-class. In each class, it first checks the +list of instance-variable names in the IVARS slot, then the list of +class-variables name in the CVARS slot.

    + +
      +  Back to Top +
    + +

    How are function calls implemented ?

    + +

    xleval.c contains the central expression-evaluation code. xleval.c:xleval() +is the standard top-level entrypoint. The two central functions are +xleval.c:xlevform() and xleval.c:evfun(). xlevform() can evaluate four kinds of +expression nodes:

    + +

    SUBR: A normal primitive fn coded in C. We call evpushargs() to +evaluate and push the arguments, then call the primitive.

    + +

    FSUBR: A special primitive fn coded in C, which (like IF) wants its +arguments unevaluated. We call pushargs() (instead of evpushargs()) and then the +C fn.

    + +

    CLOSURE: A preprocessed written-in-lisp fn from a DEFUN or LAMBDA. We +call evpushargs() and then evfun().

    + +

    CONS: We issue an error if CONS.car isn't a LAMBDA, otherwise we call +xleval.c:xlclose() to build a CLOSURE from the LAMBDA, and fall into the CLOSURE +code.

    + +

    The common thread in all the above cases is that we call evpushargs() or +pushargs() to push all the arguments on the evaluation stack, leaving the number +and location of the arguments in the global variables xlargc and xlargv. The +primitive C functions consume their arguments directly from the argument +stack.

    + +

    xleval.c:evfun() evaluates a CLOSURE by:

    + +

    (1) Switching xlenv and xlfenv to the values they had when the CLOSURE was +built. (These values are recorded in the CLOSURE.)

    + +

    (2) Binding the arguments to the environment. This involves scanning through +the section of the argument stack indicated by xlargc/xlargv, using information +from the CLOSURE to resolve keyword arguments correctly and assign appropriate +default values to optional arguments, among other things.

    + +

    (3) Evaluating the body of the function via xleval.c:xleval().

    + +

    (4) Cleaning up and restoring the original environment.

    + +
      +  Back to Top +
    + +

    How are message-sends implemented ?

    + +

    We scan the MESSAGES list in the CLASS object of the recipient, looking for a +(message-symbol method) pair that matches our message symbol. If necessary, we +scan the MESSAGES lists of the recipient's superclasses too. +(xlobj.c:sendmsg().) Once we find it, we basically do a normal function +evaluation. (xlobjl.c:evmethod().)

    + +

    Two differences between message-send and normal function invocation:

    + +

    1) We need to replace the message-symbol by the recipient on the argument +stack to make "self" available in the method closure.

    + +

    2) We need to push an 'object' stack entry on the xlenv environment to record +which class is handling the message (so that, for example, SEND-SUPER can find +our superclass).

    + +
      +  Back to Top +
    + +

    How is garbage collection implemented ?

    + +

    The dynamic memory pool managed by xlisp consists of a chain of memory +segments (xldmem.h:struct segment) rooted at global C variable "segs". Each +segment contains an array of "struct node"s plus a pointer to the next segment. +Each node contains a n_type field and a MARK bit, which is zero except during +garbage collection.

    + +

    Xlisp uses a simple, classical mark-and-sweep garbage collector. When it runs +out of memory (fnodes==NIL), it does a recursive traversal setting the MARK flag +on all nodes reachable from the obarray, the three environments +xlenv/xlfenv/xldenv, and the evaluation and argument stacks. (A "switch" on the +n_type field tells us how to find all the LVAL slots in the node (plus +associated storage), and a pointer-reversal trick lets us avoid using too much +stack space during the traversal.) sweep() then adds all un-MARKed LVALs to +fnodes, and clears the MARK bit on the remaining nodes. If this fails to produce +enough free nodes, a new segment is malloc()ed.

    + +

    The code to do this stuff is mostly in xldmem.c.

    + +
      +  Back to Top +
    + +

    How are the source files laid out ?

    + +

    To really understand the source, of course, you simply have to sit down and +read it. There's no royal road to hacking! So this is a map of the source, not a +picture of it.

    + +

    The core portable xlisp files have the prefix 'xl' (for 'xlisp').

    + +

    The best place to start reading the code is in the two main header files, +xlisp.h and xldmem.h.

    + +

    The xldmem.h file ('dmem' for 'dynamic memory') defines the actual structure +in memory of all the primitive xlisp data types. This is the file you will most +likely refer to most often.

    + +

    The xlisp.h file defines essentially all global constants and macros which +don't need to know about the structures in xldmem.h, mainly manifest constants +sizing various arrays for different machines, and macros to test for the type of +a list object and to help parse xlisp argument lists.

    + +

    The central code files to understand are xlmain.c, xleval.c, xlbfun.c, and +xlsym.c.

    + +

    xlmain.c contains both main() and the central read-eval-print loop, so +it is the place from which to begin tracing flow of control.

    + +

    xleval.c (with some support from xlbfun.) contains the heart of xlisp, +the code to evaluate functions and macros.

    + +

    xlsym.c contains the code to find the value of a symbol.

    + +

    Once you understand the above three, you know where xlisp decides to evaluate +an s-expression, how it evaluates it, and how it finds the values needed by the +expression.

    + +

    A good file to tackle next is xlobj.c, which handles much of the +object-oriented support, and has much of the flavor of xleval.c.

    + +

    Most of the other files are just libraries of functions to handle particular +types of processing, and are easily understood once the central code is +grokked.

    + +

    One of the charms of xlisp *is* that it is small enough to easily read and +comprehend. I hope it stays that way!

    + +

    Here's a very brief file-by-file overview of the source. Your files will +probably be laid out just a little differently. In particular, if you're not +running on unix, instead of 'unixstuff.c' you'll have something like +'dosstuff.c'.

    + +
    +   Size Name        Contains
    +  ----- --------    --------
    +   2054 osdefs.h    System specific declarations.  Empty file in my case.
    +   2050 osptrs.h    System specific pointers.      Empty file in my case.
    +  14172 unixstuff.c Isolates I/O fns, which tend to be OS-specific. Unix version.
    +  19049 xlbfun.c    'Basic FUNctions': highlevel eval stuff + random support.
    +  30229 xlcont.c    'CONTrol': case, do, while, dotimes, other special forms.
    +   6380 xldbug.c    'DeBUG': break, abort, error, baktrace...
    +  18006 xldmem.c    'Dynamic MEMory': ram allocation, garbage collector.
    +   9431 xldmem.h    Declaration of LVAL, scads of useful macros.
    +  21220 xleval.c    'EVALuation': eval, apply, macroexpand and support for them.
    +  11935 xlfio.c     'File I/O': OPEN, READ-CHAR, WRITE-CHAR ...
    +  18481 xlftab.c    'Function TABle': Array of all xlisp primitives.
    +   4866 xlglob.c    'GLOBal variables':  Boring list of declarations.
    +  11048 xlimage.c   'memory IMAGE': Code to save/restore contents of xlisp.
    +  10579 xlinit.c    'INITialization': Start-of-the-world setup code.
    +   6016 xlio.c      'Input/Output': misc I/O stuff, some called by xlfio.c.
    +  12664 xlisp.h     consp() ..., xlgetarg() ..., misc types.
    +   5853 xljump.c    catch, throw, return ...
    +  20723 xllist.c    car, cdr, append, map ... basic list manipulation.
    +  11975 xlmath.c    Arithmetic functions -- addition, multiplication ...
    +  16425 xlobj.c     Object support -- create objects & classes, send msgs...
    +   4134 xlpp.c      A little prettyprinter.
    +   9487 xlprin.c    Print an arbitrary lisp value in ascii.
    +  19535 xlread.c    Read in an arbitrary ascii lisp expression.
    +  15062 xlstr.c     Manipulation of characters and strings.
    +  12889 xlstruct.c  Lisp structures -- defstruct and kin.
    +   5957 xlsubr.c    eq, equal, some internal utility fns.
    +   7019 xlsym.c     Symbols and obarrays ... maksym, getvalue, getprop...
    +   5566 xlsys.c     Misc stuff -- read file, print backtrace, peek/poke...
    +   3926 xmain.c     main(), with top read-eval-print loop.
    +
    + +
      +  Back to Top +
    + +

    How do I add a new primitive fn to xlisp ?

    + +

    A preliminary comment: You should have a copy of Guy L Steele's "Common Lisp: +The Language" (2nd Edition), and make your new primitives compatible with the +standard whenever practical.

    + +

    Add a line to the end of xlftab.c:funtab[]. This table contains a list of +triples:

    + +

    The first element of each triple is the function name as it will appear to +the programmer. Make it all upper case.

    + +

    The second element is S (for SUBR) if (like most fns) your function wants its +arguments pre-evaluated, else F (for FSUBR).

    + +

    The third element is the name of the C function to call.

    + +

    Remember that your arguments arrive on the xlisp argument stack rather than +via the usual C parameter mechanism.

    + +

    CAUTION: Try to keep your files separate from generic xlisp files, and to +minimize the number of changes you make in the generic xlisp files. This way, +you'll have an easier time re-installing your changes when new versions of xlisp +come out. For example, if you are going to add many primitive functions to your +xlisp, use an #include file rather than putting them all in xlftab.c. It's a +good idea to put a marker (like a comment with your initials) on each line you +change or insert in the generic xlisp fileset.

    + +

    CAUTION: Remember that you usually need to protect the LVAL variables in your +function from the garbage-collector. It never hurts to do this, and often +produces obscure bugs if you do not. You protect uninitialized local variables +with xlsave1() and initialized local variables with xlprot1().

    + +

    BE CAREFUL NOT TO PROTECT UNINITIALIZED LOCAL VARIABLES WITH XLPROT1() OR +XLPROTECT()! This will appear to work fine until garbage collection happens at +an inconvenient moment, at which point the garbage collector will wind up +following your uninitialized pointer off to never-never land.

    + +

    Note: If you have several pointers to protect, you can save a little runtime +and codespace by using xlstkcheck(number-of-variables-to-protect) followed by +xlsave()s and xlprotect()s instead of the more expensive xlsave1()s and +xlprot1()s.

    + +

    Generic code for a new primitive fn:

    + +
    +  /* xlsamplefun - do useless stuff.        */
    +  /* Called like (samplefun '(a c b) 1 2.0) */
    +  LVAL xlsamplefun()
    +  {
    +      /* Variables to hold the arguments: */
    +      LVAL    list_arg, integer_arg, float_arg;
    +  
    +      /* Get the arguments, with appropriate errors */
    +      /* if any are of the wrong type.  Look in     */
    +      /* xlisp.h for macros to read other types of  */
    +      /* arguments.  Look in xlmath.c for examples  */
    +      /* of functions which can handle an argument  */
    +      /* which may be either int or float:          */
    +      list_arg    = xlgalist()  ;  /* "XLisp Get A LIST"   */
    +      integer_arg = xlgafixnum();  /* "XLisp Get A FIXNUM" */
    +      float_arg   = xlgaflonum();  /* "XLisp Get A FLONUM" */
    +  
    +      /* Issue an error message if there are any extra arguments: */
    +      xllastarg();
    +  
    +      /* Call a separate C function to do the actual  */
    +      /* work.  This way, the main function can       */
    +      /* be called from both xlisp code and C code.   */
    +      /* By convention, the name of the xlisp wrapper */
    +      /* starts with "xl", and the native C function  */
    +      /* has the same name minus the "xl" prefix:     */
    +      return samplefun( list_arg, integer_arg, float_arg );
    +  }
    +  LVAL samplefun( list_arg, integer_arg, float_arg )
    +  LVAL            list_arg, integer_arg, float_arg;
    +  {
    +      FIXTYPE val_of_integer_arg;
    +      FLOTYPE val_of_float_arg;
    +  
    +      /* Variables which will point to LISP objects: */
    +      LVAL result;
    +      LVAL list_ptr;
    +      LVAL float_ptr;
    +      LVAL int_ptr;
    +  
    +      /* Protect our internal pointers by */
    +      /* pushing them on the evaluation   */
    +      /* stack so the garbage collector   */
    +      /* can't recycle them in the middle */
    +      /* of the routine:                  */
    +      xlstkcheck(4);    /* Make sure following xlsave */
    +                        /* calls won't overrun stack. */
    +      xlsave(list_ptr); /* Use xlsave1() if you don't */
    +      xlsave(float_ptr);/* do an xlstkcheck().        */
    +      xlsave(int_ptr);
    +      xlsave(result);
    +  
    +      /* Semantic check, illustrating use of xlfail(): */
    +      if (list_ptr == NIL) {
    +          xlfail("null list");
    +          /* Won't return. */
    +      }
    +  
    +      /* Create an internal list structure, protected */
    +      /* against garbage collection until we exit fn: */
    +      list_ptr = cons(list_arg,list_arg);
    +  
    +      /* Get the actual values of our fixnum and flonum: */
    +      val_of_integer_arg = getfixnum( integer_arg );
    +      val_of_float_arg   = getflonum( float_arg   );
    +  
    +      /* Semantic check, illustrating use of xlerror(): */
    +      if (val_of_integer_arg < -2) {
    +          xlerror("bad integer",cvfixnum(val_of_integer_arg));
    +          /* Won't return. */
    +      }
    +  
    +      /*******************************************/
    +      /* You can have any amount of intermediate */
    +      /* computations at this point in the fn... */
    +      /*******************************************/
    +  
    +      /* Make new numeric values to return: */
    +      integer_ptr = cvfixnum( val_of_integer_arg * 3   );
    +      float_ptr   = cvflonum( val_of_float_arg   * 3.0 );
    +  
    +      /* Cons it all together to produce a return value: */
    +      result = cons( float_ptr,   NIL    );
    +      result = cons( integer_ptr, result );
    +      result = cons( list_ptr,    result );
    +  
    +      /* Restore the stack, canceling the xlsave()s: */
    +      xlpopn(4); /* Use xlpop() for a single argument.*/
    +  
    +      return result;
    +  }
    +
    + +

    Example of what NOT to do:

    + +

    Here's a function I wrote which does *NOT* correctly prevent the garbage +collector from stealing its dynamically allocated cells:

    + +
    +  LVAL incorrect_Point_To_List( p )/*DON'T USE THIS CODE! */
    +  geo_point*                    p;
    +  /*-
    +      Convert point to (x y z) list.
    +  -*/
    +  {
    +      LVAL result;
    +      xlsave1(result);
    +      result = cons(              /* THIS CODE IS BROKEN! */
    +          cvflonum(        p->x), /* THIS CODE IS BROKEN! */
    +          cons(                   /* THIS CODE IS BROKEN! */
    +              cvflonum(    p->y), /* THIS CODE IS BROKEN! */
    +              cons(               /* THIS CODE IS BROKEN! */
    +                  cvflonum(p->z), /* THIS CODE IS BROKEN! */
    +                  NIL             /* THIS CODE IS BROKEN! */
    +              )                   /* THIS CODE IS BROKEN! */
    +          )                       /* THIS CODE IS BROKEN! */
    +      );                          /* THIS CODE IS BROKEN! */
    +      xlpop();
    +      return result;
    +  }
    +
    + +

    The problem with the above function is that the "z" cell will be allocated +first, and is not protected during the allocation of the "y" flonum (or vice +versa, depending on the order the compiler chooses to evaluate these arguments). +Similarly, the "y" cell is not protected during allocation of the "x" flonum. +Here is a correct version, in which "result" always protects the +list-to-date:

    + +
    +  LVAL correct_Point_To_List( p )
    +  geo_point*                  p;
    +  /*-
    +      Convert point to (x y z) list.
    +  -*/
    +  {
    +      LVAL result;
    +      xlsave1(result);
    +      result = cons( cvflonum(p->z), NIL          );
    +      result = cons( cvflonum(p->y), result       );
    +      result = cons( cvflonum(p->x), result       );
    +      xlpop();
    +      return result;
    +  }
    +
    + +
      +  Back to Top +
    + +

    Minor Observations:

    + +

    xlapply, xlevform and sendmsg will issue an error if they encounter a s_macro +CLOSURE. You are not allowed to use APPLY or FUNCALL with macros in Common Lisp. +There is no way provided to declare macro methods, nor do they make much +sense...

    + +

    Neither xlapply nor sendmsg will handle FSUBRs. Common Lisp does not allow +APPLYing a special form (FSUBR), and since SEND is a SUBR, all of its arguments +are already evaluated, so it is not possible to have FSUBR methods.

    + +

    Since xlisp tracks the three most recent input expressions (in variables +, +++ and +++) and three most recent results (in variables *, ** and ***), things +may occasionally not get garbage-collected as soon as you expect!

    + +

    Both xlobj.c:xloinit() and xlobj.c:obsymvols() initialize the "object" and +"class" variables. This is neither redundant nor a bug:

    + +

    xloinit creates the classes class and object, as well as the symbols, but +sets the C variables class and object to point to the class and object.

    + +

    obsymbols just sets the C variables by looking up the symbols. It is needed +because when you restore a workspace you don't create new objects but still need +to know where the existing objects are (they might be in a different location in +the saved workspace). Notice that obsymbols is called by xlsymbols which is +called both when initializing a new workspace and when restoring an old +workspace.

    + +
      +  Back to Top +
    + +

    Acknowledgements

    + +

    This document is considerably improved thanks to careful reading and +thoughtful suggestions from Ken Whedbee (kcw@beach.cis.ufl.edu) and (especially) +Tom Almy (toma@sail.labs.tek.com).

    + +
      +  Back to Top +
    + +

    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/manual/contents.htm b/docsrc/xlisp/xlisp-doc/manual/contents.htm new file mode 100644 index 0000000..d959433 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/contents.htm @@ -0,0 +1,858 @@ +Table of Contents + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Table of Contents

    + +
    + +
      +
    1. Manuals
    2. + +
    3. Reference
    4. + +
    + + + +
    + +

    XLISP 2.0 Manual

    + +
    + + + +

      Back to top

    + + + +
    + +

    XLISP Object System

    + +
    + + + +

      Back to top

    + + + +
    + +

    Symbols

    + +
    + + + +
      +
    •  +  - the most recent input expression
    • +
    •  ++  - the next to the last input expression
    • +
    •  +++  - the second to the last input expression
    • +
    •  *  - the result of the previously evaluated expression
    • +
    •  **  - the result of the next to the last evaluated expression
    • +
    •  ***  - the result of the second to the last evaluated expression
    • +
    •  -  - the expression currently being evaluated
    • +
    + +

      Back to top

    + + + +
    + +

    Evaluation Functions

    + +
    + + + +

      Back to top

    + + + +
    + +

    Symbol Functions

    + +
    + +
      +
    • Constructors
    • + +
    • Accessors
    • + +
    • Assignment
    • +
        +
      • set - set the value of a symbol
      • +
      • setq - set the [quoted] value of a symbol
      • +
      • psetq - parallel version of setq
      • +
      • setf - set the value of a field
      • +
      +
    • Utilities
    • +
        +
      • incf - increment a variable
      • +
      • decf - decrement a variable
      • +
      +
    + +

      Back to top

    + + + +
    + +

    Array Functions

    + +
    + +
      +
    • Constructors
    • + +
    • Acessors
    • +
        +
      • aref - get the nth element of an array
      • +
      +
    • Predicate
    • +
        +
      • arrayp - is this an array?
      • +
      +
    • Utilities
    • +
        +
      • length - find the length of a list, vector or string
      • +
      • hash - compute the hash index for a symbol
      • +
      +
    + +

      Back to top

    + + + +
    + +

    List Functions

    + +
    + +
      +
    • Constructors
    • +
        +
      • cons - construct a new list node
      • +
      • list - create a list of values
      • +
      +
    • Accessors
    • + +
    • Predicates
    • +
        +
      • consp - is this a non-empty list?
      • +
      • listp - is this an empty or non-empty list?
      • +
      • null - is this an empty list?
      • +
      +
    • List Functions
    • +
        +
      • append - append lists
      • +
      • reverse - reverse a list
      • +
      • member - find an expression in a list
      • +
      • length - find the length of a list, vector or string
      • +
      • subst - substitute expressions
      • +
      +
    • Association Lists
    • +
        +
      • assoc - find an expression in an a-list
      • +
      • sublis - substitute with an a-list
      • +
      +
    • Property Lists
    • +
        +
      • get - get the value of a property
      • +
      • putprop - put a property onto a property list
      • +
      • remprop - remove a property from a property list
      • +
      +
    • Mapping
    • +
        +
      • mapc - apply function to successive cars
      • +
      • mapcar - apply function to successive cars
      • +
      • mapl - apply function to successive cdrs
      • +
      • maplist - apply function to successive cdrs
      • +
      +
    • Lists as Stack
    • +
        +
      • push - push a value to the front of a list
      • +
      • pop - pop a value from the front of a list
      • +
      +
    • Lists as Sets
    • +
        +
      • union - compute the union of two lists
      • +
      • intersection - compute the intersection of two lists
      • +
      • set-difference - compute the set-difference of two lists
      • +
      • subsetp - test if a list is a subset of another list
      • +
      +
    • Non-destructive List Functions
    • + +
    • Destructive List Functions
    • +
        +
      • rplaca - replace the car of a list node
      • +
      • rplacd - replace the cdr of a list node
      • +
      • nconc - destructively concatenate lists
      • +
      • delete - delete elements from a list
      • +
      • delete-if - delete elements that pass test
      • +
      • delete-if-not - delete elements that fail test
      • +
      • sort - sort a list
      • +
      +
    + +

      Back to top

    + + + +
    + +

    Predicate Functions

    + +
    + +
      +
    • Predicates
    • +
        +
      • atom - is this an atom?
      • +
      • symbolp - is this a symbol?
      • +
          +
        • boundp - is a variable value bound to this symbol?
        • +
        • fboundp - is a function value bound to this symbol?
        • +
        +
      • keywordp - is this a keyword?
      • +
      • numberp - is this a number?
      • +
          +
        • plusp - is this number positive?
        • +
        • minusp - is this number negative?
        • +
        • zerop - is this number zero?
        • +
        • integerp - is this number an integer?
        • +
            +
          • evenp - is this integer even?
          • +
          • oddp - is this integer odd?
          • +
          +
        • floatp - is this number a float?
        • +
        +
      • null - is this an empty list?
      • +
      • consp - is this a non-empty list?
      • +
      • listp - is this a list?
      • +
          +
        • endp - is this the end of a list?
        • +
        +
      • stringp - is this a string?
      • +
      • characterp - is this a character?
      • + +
      • arrayp - is this an array?
      • +
      • streamp - is this a stream?
      • +
      • filep - is this a file?
      • +
      • objectp - is this an object?
      • +
      • soundp - is this a Nyquist sound?
      • +
      • bigendianp - is this a bigendian machine?
      • +
      +
    • Comparison
    • +
        +
      • eq - are the expressions identical?
      • +
      • eql - are the expressions identical?
      • +
      • equal - are the expressions equal?
      • +
      +
    • Boolean
    • +
        +
      • not - is this false?
      • +
      +
    + +

      Back to top

    + + + +
    + +

    Control Constructs

    + +
    + +
      +
    • Logical
    • +
        +
      • and - the logical AND of a list of expressions
      • +
      • or - the logical OR of a list of expressions
      • +
      +
    • Conditional
    • +
        +
      • if - evaluate expressions conditionally
      • +
      • when - evaluate only when a condition is true
      • +
      • unless - evaluate only when a condition is false
      • +
      • cond - evaluate conditionally
      • +
      • case - select by case
      • +
      +
    • Binding
    • +
        +
      • let - create local bindings
      • +
      • let* - let with sequential binding
      • +
      • flet - create local functions
      • +
      • labels - flet with recursive functions
      • +
      • macrolet - create local macros
      • +
      +
    • Non-local Exits
    • + +
    • Looping Constructs
    • +
        +
      • loop - basic looping form
      • +
      • do - loop while the termination test is NIL
      • +
      • do* - 'do' loop with sequential binding
      • +
      • dolist - loop through a list
      • +
      • dotimes - loop from zero to n-1
      • +
      • while - standard 'while' loop
      • +
      +
    • The Program Feature
    • +
        +
      • prog - the program feature
      • +
      • prog* - 'prog' with sequential binding
      • +
      • block - named block
      • +
      • return - cause a prog construct to return a value
      • +
      • return-from - return from a named block
      • +
      • tagbody - block with labels
      • +
      • go - go to a tag within a tagbody or prog
      • +
      • progv - dynamically bind symbols
      • +
      • prog1 - return the value of the first expression
      • +
      • prog2 - return the value of the second expression
      • +
      • progn - return the value of the last expression
      • +
      +
    + +

      Back to top

    + + + +
    + +

    Debugging and Error Handling

    + +
    + +
      +
    • trace - add a function to the trace list
    • +
    • untrace - remove a function from the trace list
    • +
    • error - signal a non-correctable error
    • +
    • cerror - signal a correctable error
    • +
    • break - enter a break loop
    • +
    • clean-up - clean-up after an error
    • +
    • top-level - clean-up after an error and return to the top level
    • +
    • continue - continue from a correctable error
    • +
    • errset - trap errors
    • +
    • baktrace - print n levels of trace back information
    • +
    • evalhook - evaluate with hooks
    • +
    • profile - turn profiling on or off
    • +
    + +

      Back to top

    + + + +
    + +

    Arithmetic Functions

    + +
    + +
      +
    • Integer and Floating Point - error if not a number
    • +
        +
      • truncate - truncates a floating point number to an integer
      • +
      • float - converts an integer to a floating point number
      • +
      •  +  - add one or several numbers
      • +
      •  −  - negate a single number or subtract one or several numbers
      • +
      •  *  - multiply one or several numbers
      • +
      •  /  - get the reciprocal of a single number or divide several numbers
      • +
      • 1+ - increment a number by one
      • +
      • 1− - decrement a number by one
      • +
      • min - the smallest of one or several numbers
      • +
      • max - the largest of one or several numbers
      • +
      • abs - the absolute value of a number
      • +
      • asin - compute the arcsine of a number
      • +
      • acos - compute the arccosine of a number
      • +
      • atan - compute the arctangent of a number
      • +
      • power - compute 'x' to the 'y' power
      • +
      • interpolate - compute the 'y' coordinate corresponding to 'x'
      • +
      +
    • Comparison - error if not a number
    • +
        +
      •  <  - test for less than
      • +
      •  <=  - test for less than or equal to
      • +
      •  =  - test for equal to
      • +
      •  /=  - test for not equal to
      • +
      •  >=  - test for greater than or equal to
      • +
      •  >  - test for greater than
      • +
      +
    • Floating Point - error if not a floating point number
    • +
        +
      • sin - compute the sine of a floating-point number
      • +
      • cos - compute the cosine of a floating-point number
      • +
      • tan - compute the tangent of a floating-point number
      • +
      • expt - compute x to the y power
      • +
      • exp - compute e to the x power
      • +
      • exp - compute the natural logarithm of a floating-point number
      • +
      • sqrt - compute the square root of a floating-point number
      • +
      +
    • Integer - error if not an integer number
    • +
        +
      • gcd - compute the greatest common divisor
      • +
      • logand - compute the bitwise 'and' of one or several numbers
      • +
      • logior - compute the bitwise 'inclusive or' of one or several numbers
      • +
      • logxor - compute the bitwise 'exclusive or' of one or several numbers
      • +
      • lognot - compute the bitwise 'not' of an number
      • +
      • rem - remainder of one or several integer numbers
      • +
      +
    • Random Numbers
    • +
        +
      • random - compute an integer random number between 0 and n-1 inclusive
      • +
      • rrandom - compute a floating point random number between 0 and 1 inclusive
      • +
      • real-random - compute a floating point random number in an arbitrary range
      • +
      +
    + +

      Back to top

    + + + +
    + +

    String Functions

    + +
    + +
      +
    • String Functions
    • +
        +
      • string - make a string from a character or an integer ASCII value
      • +
      • strcat - concatenate strings
      • +
      • subseq - extract a substring
      • +
      • length - find the length of a list, vector or string
      • +
      • string-search - search for a pattern in a string
      • +
      +
    • Trimming
    • + +
    • Case Conversion
    • + +
    • Case-sensitive Comparison
    • +
        +
      • string< - test for less than in ASCII ordering
      • +
      • string<= - test for less than or equal to in ASCII ordering
      • +
      • string= - test for equal to in ASCII ordering
      • +
      • string/= - test for not equal to in ASCII ordering
      • +
      • string>= - test for greater than or equal to in ASCII ordering
      • +
      • string> - test for greater than in ASCII ordering
      • +
      +
    • Case-insensitive Comparison
    • + +
    + +

      Back to top

    + + + +
    + +

    Character Functions

    + +
    + +
      +
    • Character Functions
    • +
        +
      • char - extract a character from a string
      • +
      • char-code - get the ASCII code of a character
      • +
      • code-char - get the character with a specified ASCII code
      • +
      • digit-char - convert a digit weight to a digit
      • +
      • char-int - convert a character to an integer
      • +
      • int-char - convert an integer to a character
      • +
      +
    • General Predicate - all data types
    • + +
    • Character Predicates - error if not a character
    • + +
    • Case Conversion
    • + +
    • Case-sensitive Comparison
    • +
        +
      • char< - test for less than in ASCII ordering
      • +
      • char<= - test for less than or equal to in ASCII ordering
      • +
      • char= - test for equal to in ASCII ordering
      • +
      • char/= - test for not equal to in ASCII ordering
      • +
      • char>= - test for greater than or equal to in ASCII ordering
      • +
      • char> - test for greater than in ASCII ordering
      • +
      +
    • Case-insensitive Comparison
    • + +
    + +

      Back to top

    + + + +
    + +

    Input/Output Functions

    + +
    + +
      +
    • get-key - get a single key stroke from the keyboard
    • +
    • read - read an expression
    • +
    • print - print an expression on a new line
    • +
    • prin1 - print an expression
    • +
    • princ - print an expression without quoting
    • +
    • pprint - pretty print an expression
    • +
    • terpri - terminate the current print line
    • +
    • flatsize - length of printed representation using prin1
    • +
    • flatc - length of printed representation using princ
    • +
    • format - do formated output
    • +
    + +

      Back to top

    + + + +
    + +

    File I/O Functions

    + +
    + +
      +
    • Character I/O
    • +
        +
      • open - open a character file stream
      • +
      • peek-char - peek at the next character
      • +
      • read-char - read a character from a stream
      • +
      • read-line - read a line from a stream
      • +
      • write-char - write a character to a stream
      • +
      +
    • Binary I/O
    • +
        +
      • bigendianp - is this a bigendian machine?
      • +
      • open-binary - open a binary file stream
      • +
      • Bytes
      • + +
      • Integer Numbers
      • +
          +
        • read-int - read a binary integer number from a stream
        • +
        • write-int - write a binary integer number to a stream
        • +
        +
      • Floating Point Numbers
      • +
          +
        • read-float - read a binary floating point number from a stream
        • +
        • write-float - write a binary floating point number to a stream
        • +
        +
      +
    • Character and Bibary I/O
    • +
        +
      • close - close a file stream
      • +
      +
    • Operating System
    • + +
    + +

      Back to top

    + + + +
    + +

    String Stream Functions

    + +
    + + + +

      Back to top

    + + + +
    + +

    System Functions

    + +
    + +
      +
    • load - load a source file
    • +
    • save - save workspace to a file
    • +
    • restore - restore workspace from a file
    • +
    • dribble - create a file with a transcript of a session
    • +
    • gc - force garbage collection
    • +
    • expand - expand memory by adding segments
    • +
    • alloc - change number of nodes to allocate in each segment
    • +
    • info - show information about memory usage
    • +
    • room - show memory allocation statistics
    • +
    • type-of - returns the type of the expression
    • +
    • peek - peek at a location in memory
    • +
    • poke - poke a value into memory
    • +
    • bigendianp - is this a big-endian machine?
    • +
    • address-of - get the address of an xlisp node
    • +
    • get-env - get the value of an environment variable
    • +
    • system - execute a command of the operating system
    • +
    • quit - exit XLISP
    • +
    • exit - exit XLISP
    • +
    • setup-console - set default console attributes
    • +
    • echoenabled - turn console input echo on or off
    • +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/manual/links.htm b/docsrc/xlisp/xlisp-doc/manual/links.htm new file mode 100644 index 0000000..eff06d6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/links.htm @@ -0,0 +1,3 @@ + + +object diff --git a/docsrc/xlisp/xlisp-doc/manual/manual.css b/docsrc/xlisp/xlisp-doc/manual/manual.css new file mode 100644 index 0000000..964dca2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/manual.css @@ -0,0 +1,34 @@ +.example { + color: #000000; + background-color: #F5F5F5; + padding: 8px; + border: #808080; + border-style: solid; + border-width: 1px; + width:auto; +} + +.button { + color: #000000; + background-color: #F5F5F5; + padding-top: 1px; + padding-bottom: 1px; + padding-left: 4px; + padding-right: 8px; + border: #808080; + border-style: solid; + border-width: 1px; + white-space: pre; +} + +.box { + color: #000000; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 16px; + padding-right: 16px; + border: #808080; + border-style: solid; + border-width: 1px; +} + diff --git a/docsrc/xlisp/xlisp-doc/manual/objects.htm b/docsrc/xlisp/xlisp-doc/manual/objects.htm new file mode 100644 index 0000000..31c4fea --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/objects.htm @@ -0,0 +1,358 @@ +XLISP: An Object-oriented Lisp + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    XLISP Object System

    + +
    + +
      +
    1. Definitions
    2. +
        +
      • selector - a symbol used to select an appropriate method
      • +
      • message - a selector and a list of actual arguments
      • +
      • method - the code that implements a message
      • +
      • object - the top of the class hierarchy
      • +
      • class - the class of all object classes
      • +
      +
    3. The 'send' Function
    4. +
    5. The 'self' Symbol
    6. +
    7. The 'send-super' Function
    8. +
    9. The 'object' Class
    10. +
        +
      • object - the top of the class hierarchy
      • +
          +
        • :show - show an object's instance variables
        • +
        • :class - return the class of an object
        • +
        • :isnew - the default object initialization routine
        • +
        • send-super - send superclass a message
        • +
        +
      +
    11. The 'class' Class
    12. +
        +
      • class - class of all object classes
      • +
          +
        • :new - create a new instance of a class
        • +
        • :isnew - initialize a new class
        • +
        • :answer - add a message to a class
        • +
        +
      +
    + + + + + + + + +
    + +

    1  Definitions

    + +
    + +

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    selector — a symbol used to select an appropriate method, usually a keyword
    message — a selector symbol and a list of actual arguments
    method — the Lisp code that implements a message
    object — the top of the class hierarchy
    class — the class of all object classes [including itself]

    + +

    + +

    Since XLISP was created to provide a simple basis for experimenting with +object-oriented programming, one of the primitive data types +included is object. In +XLISP, an object consists of a data structure containing a pointer to +the object's class as well as an array +containing the values of the object's instance variables.

    + +

    Officially, there is no way to see inside an object [look at the values +of its instance variables]. The only way to communicate with an object is by +sending it a message.

    + +

      Back to Top

    + + + +
    + +

    2  The 'send' Function

    + +
    + +

    You can send a message to an object using the +send function:

    + +

    + +
    +
    (send object selector [args])
    +
    object - an object
    +selector - message selector for object
    +arg - parameter sent to object method
    +returns - the object
    +
    + +

    + +

    The send function takes the object as +its first argument, the message selector as its second argument [which must +be a symbol] and the message arguments as its remaining arguments. It +determines the class of the receiving object and attempts to find a +method corresponding to the message selector in the set of messages defined +for that class. If the message is not found in the object's +class and the class has a super-class, the search continues by +looking at the messages defined for the super-class. This +process continues from one super-class to the next until a +method for the message is found. If no method is found, an +error occurs.

    + +

      Back to Top

    + + + +
    + +

    3  The 'self' Symbol

    + +
    + +

    When a method is found, the evaluator binds the receiving object to the +symbol self and evaluates the method +using the remaining elements of the original list as arguments to the +method. These arguments are always evaluated prior to being bound to their +corresponding formal arguments. The result of evaluating the method becomes +the result of the expression.

    + +

    Within the body of a method, a message can be sent to the current object +by calling:

    + +
    +(send self ... )
    +
    + +

    The method lookup starts with the object's class regardless of the class +containing the current method.

    + +

      Back to Top

    + + + +
    + +

    4  The 'send-super' Function

    + +
    + +

    Sometimes it is desirable to invoke a general method in a superclass even +when it is overridden by a more specific method in a subclass. This can be +accomplished by calling send-super, which begins the +method lookup in the superclass of the class defining the current method +rather than in the class of the current object:

    + +

    + +
    +
    (send-super selector [args])
    +
    selector - the message selector
    +args - the optional message arguments
    +returns - the result of sending the message
    +
    + +

    + +

    The send-super function +takes a selector as its first argument [which must be a symbol] and the +message arguments as its remaining arguments. Notice that send-super can only be sent from +within a method, and the target of the message is always the current object +self.

    + +
    +(send-super ... )
    +
    + +

    is similar to:

    + +
    +(send self ... )
    +
    + +

    except that method lookup begins in the superclass of the class +containing the current method rather than the class of the current +object.

    + +

      Back to Top

    + + + + + + + + +
    + +

    5  The 'object' Class

    + +
    + +

    + +

    object - the top of the class hierarchy.

    + +

    + +

    Messages:

    + +

    + +
    + +
    (send object :show) +- show an object's instance variables.
    +
    returns - the object
    + +
    + +
    (send object :class) +- return the class of an object
    +
    returns - the class of the object
    + +
    + +
    (send object :isnew args) +- run the default object initialization routine
    +
    returns - the object
    + +
    + +
    (send object :isa class) +- test if object inherits from class
    +
    returns -  T  if object +is an instance of class or a subclass of class, otherwise +NIL
    + +
    + +

    + +

      Back to Top

    + + + + + + + +
    + +

    6  The 'class' Class

    + +
    + +

    + +

    class + - class of all object classes (including itself)

    + +

    + +

    Messages:

    + +

    + +
    + +
    (send class :new ivars [cvars [super]]) + - create a new instance of a class
    +
    returns - the new class object
    + +
    + +
    (send class :isnew ivars [cvars [super]]) + - initialize a new class
    +
    ivars - list of instance variable symbols
    +cvars - list of class variable symbols
    +super - the superclass, default is object
    +returns - the new class object
    + +
    + +
    (send class :answer selector fargs body) + - add a message to a class
    +
    selector - a message selector symbol
    +fargs - the formal argument list, a lambda list
    +body - a list of executable expressions
    +returns - the object
    + +
    + +

    + +

    When a new instance of a +class is created by sending +the message :new +to an existing class, the +message :isnew followed by +whatever parameters were passed to the +:new message is sent to the +newly created object.

    + +

    When a new class is created +by sending the :new message to +the object class, an optional +parameter may be specified indicating the superclass of the new +class. If this parameter is +omitted, the new class will be +a subclass of object. A +class inherits all instance +variables, class variables, and methods from its superclass.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/manual/part15.html b/docsrc/xlisp/xlisp-doc/manual/part15.html new file mode 100755 index 0000000..23a808d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/part15.html @@ -0,0 +1,2131 @@ +Appendix 3: XLISP: An Object-oriented Lisp +

    Appendix 3: XLISP: An Object-oriented Lisp

    + +
    Version 2.0 +

    +February 6, 1988 +

    +by
    + +David Michael Betz
    + +127 Taylor Road
    + +Peterborough, NH 03458 +

    +(603) 924-6936 (home) +

    +Copyright (c) 1988, by David Michael Betz
    + +All Rights Reserved
    + +Permission is granted for unrestricted non-commercial use
    + +

    + + +

    Introduction

    +

    + XLISP is an experimental programming language combining some of + the features of Common Lisp with an object-oriented extension + capability. It was implemented to allow experimentation with + object-oriented programming on small computers. +

    + There are currently implementations of XLISP running on the IBM- + PC and clones under MS-DOS, on the Macintosh, the Atari-ST and + the Amiga. It is completely written in the programming language + C and is easily extended with user written built-in functions + and classes. It is available in source form to non-commercial + users. +

    + Many Common Lisp functions are built into XLISP. In addition, + XLISP defines the objects Object and Class as primitives. + Object is the only class that has no superclass and hence is + the root of the class hierarchy tree. Class is the class of + which all classes are instances (it is the only object that is + an instance of itself). +

    + This document is a brief description of XLISP. It assumes some + knowledge of LISP and some understanding of the concepts of + object-oriented programming. +

    + I recommend the book Lisp by Winston and Horn and published by + Addison Wesley for learning Lisp. The first edition of this + book is based on MacLisp and the second edition is based on + Common Lisp. XLISP will continue to migrate towards + compatibility with Common Lisp. +

    + You will probably also need a copy of Common Lisp: The + Language by Guy L. Steele, Jr., published by Digital Press to + use as a reference for some of the Common Lisp functions that + are described only briefly in this document. +

    +

    A Note From The Author

    If you have any problems with XLISP, feel free to contact me [me being David Betz - RBD] for + help or advice. Please remember that since XLISP is available + in source form in a high level language, many users [e.g. that Dannenberg fellow - RBD] have been + making versions available on a variety of machines. If you call + to report a problem with a specific version, I may not be able + to help you if that version runs on a machine to which I don't + have access. Please have the version number of the version that + you are running readily accessible before calling me. +

    + If you find a bug in XLISP, first try to fix the bug yourself + using the source code provided. If you are successful in fixing + the bug, send the bug report along with the fix to me. If you + don't have access to a C compiler or are unable to fix a bug, + please send the bug report to me and I'll try to fix it. +

    + Any suggestions for improvements will be welcomed. Feel free to + extend the language in whatever way suits your needs. However, + PLEASE DO NOT RELEASE ENHANCED VERSIONS WITHOUT CHECKING WITH ME + FIRST!! I would like to be the clearing house for new features + added to XLISP. If you want to add features for your own + personal use, go ahead. But, if you want to distribute your + enhanced version, contact me first. Please remember that the + goal of XLISP is to provide a language to learn and experiment + with LISP and object-oriented programming on small computers. I + don't want it to get so big that it requires megabytes of memory + to run. +

    +

    XLISP Command Loop

    When XLISP is started, it first tries to load the workspace + xlisp.wks from the current directory. If that file doesn't + exist, XLISP builds an initial workspace, empty except for the + built-in functions and symbols. +

    + Then XLISP attempts to load init.lsp from the current + directory. It then loads any files named as parameters on the + command line (after appending .lsp to their names). +

    + XLISP then issues the following prompt: +

    +        >
    +
    + + This indicates that XLISP is waiting for an expression to be + typed. +

    + When a complete expression has been entered, XLISP attempts to + evaluate that expression. If the expression evaluates + successfully, XLISP prints the result and then returns to the + initial prompt waiting for another expression to be typed. +

    +

    Break Command Loop

    When XLISP encounters an error while evaluating an expression, + it attempts to handle the error in the following way: +

    + If the symbol *breakenable* is true, the message corresponding + to the error is printed. If the error is correctable, the + correction message is printed. +

    + If the symbol *tracenable* is true, a trace back is printed. + The number of entries printed depends on the value of the symbol + *tracelimit*. If this symbol is set to something other than a + number, the entire trace back stack is printed. +

    + XLISP then enters a read/eval/print loop to allow the user to + examine the state of the interpreter in the context of the + error. This loop differs from the normal top-level + read/eval/print loop in that if the user invokes the function + continue, XLISP will continue from a correctable error. If + the user invokes the function clean-up, XLISP will abort the + break loop and return to the top level or the next lower + numbered break loop. When in a break loop, XLISP prefixes the + break level to the normal prompt. +

    + If the symbol *breakenable* is nil, XLISP looks for a + surrounding errset function. If one is found, XLISP examines + the value of the print flag. If this flag is true, the error + message is printed. In any case, XLISP causes the errset + function call to return nil. +

    + If there is no surrounding errset function, XLISP prints the + error message and returns to the top level. +

    +

    Data Types

    There are several different data types available to XLISP + programmers. +

    +

      +
    • +lists +
    • symbols +
    • strings +
    • integers +
    • characters +
    • floats +
    • objects +
    • arrays +
    • streams +
    • subrs (built-in functions) +
    • fsubrs (special forms) +
    • closures (user defined functions) +
    +

    +

    The Evaluator

    The process of evaluation in XLISP: +
      +
    • + Strings, integers, characters, floats, objects, arrays, streams, + subrs, fsubrs and closures evaluate to themselves. +
    • Symbols act as variables and are evaluated by retrieving the + value associated with their current binding. +
    • Lists are evaluated by examining the first element of the list + and then taking one of the following actions: +
        +
      • + If it is a symbol, the functional binding of the symbol is + retrieved. +
      • If it is a lambda expression, a closure is constructed for + the function described by the lambda expression. +
      • If it is a subr, fsubr or closure, it stands for itself. +
      • Any other value is an error. +
      + Then, the value produced by the previous step is examined: +
        +
      • + If it is a subr or closure, the remaining list elements are + evaluated and the subr or closure is called with these + evaluated expressions as arguments. +
      • If it is an fsubr, the fsubr is called using the remaining + list elements as arguments (unevaluated). +
      • If it is a macro, the macro is expanded using the remaining + list elements as arguments (unevaluated). The macro + expansion is then evaluated in place of the original macro + call. +
      +
    +

    +

    Lexical Conventions

    The following conventions must be followed when entering XLISP + programs: +

    + Comments in XLISP code begin with a semi-colon character and + continue to the end of the line. +

    + Symbol names in XLISP can consist of any sequence of non-blank + printable characters except the following: +

    +                ( ) ' ` , " ;
    +
    + + Uppercase and lowercase characters are not distinguished within + symbol names. All lowercase characters are mapped to uppercase + on input. +

    + Integer literals consist of a sequence of digits optionally + beginning with a + or -. The range of values an integer can + represent is limited by the size of a C long on the machine on + which XLISP is running. +

    + Floating point literals consist of a sequence of digits + optionally beginning with a + or - and including an embedded + decimal point. The range of values a floating point number can + represent is limited by the size of a C float (double on + machines with 32 bit addresses) on the machine on which XLISP is + running. +

    + Literal strings are sequences of characters surrounded by double + quotes. Within quoted strings the ``\'' character is used to + allow non-printable characters to be included. The codes + recognized are: +

      +
    • +\\ means the character ``\'' +
    • \n means newline +
    • \t means tab +
    • \r means return +
    • \f means form feed +
    • \nnn means the character whose octal code is nnn +
    +

    +

    Readtables

    The behavior of the reader is controlled by a data structure + called a readtable. The reader uses the symbol *readtable* to + locate the current readtable. This table controls the + interpretation of input characters. It is an array with 128 + entries, one for each of the ASCII character codes. Each entry + contains one of the following things: +
      +
    • + NIL - Indicating an invalid character +
    • :CONSTITUENT - Indicating a symbol constituent +
    • :WHITE-SPACE - Indicating a whitespace character +
    • (:TMACRO . fun) - Terminating readmacro +
    • (:NMACRO . fun) - Non-terminating readmacro +
    • :SESCAPE - Single escape character ('\') +
    • :MESCAPE - Multiple escape character ('|') +
    +

    + In the case of :TMACRO and :NMACRO, the fun component is a + function. This can either be a built-in readmacro function or a + lambda expression. The function should take two parameters. + The first is the input stream and the second is the character + that caused the invocation of the readmacro. The readmacro + function should return NIL to indicate that the character should + be treated as white space or a value consed with NIL to indicate + that the readmacro should be treated as an occurence of the + specified value. Of course, the readmacro code is free to read + additional characters from the input stream. +

    + XLISP defines several useful read macros: +

      +
    • + '<expr> == (quote <expr>) +
    • #'<expr> == (function <expr>) +
    • #(<expr>...) == an array of the specified expressions +
    • #x<hdigits> == a hexadecimal number (0-9,A-F) +
    • #o<odigits> == an octal number (0-7) +
    • #b<bdigits> == a binary number (0-1) +
    • #\<char> == the ASCII code of the character +
    • #| ... |# == a comment +
    • #:<symbol> == an uninterned symbol +
    • `<expr> == (backquote <expr>) +
    • ,<expr> == (comma <expr>) +
    • ,@<expr> == (comma-at <expr>) +
    +

    Lambda Lists

    There are several forms in XLISP that require that a ``lambda + list'' be specified. A lambda list is a definition of the + arguments accepted by a function. There are four different + types of arguments. +

    + The lambda list starts with required arguments. Required + arguments must be specified in every call to the function. +

    + The required arguments are followed by the &optional arguments. + Optional arguments may be provided or omitted in a call. An + initialization expression may be specified to provide a default + value for an &optional argument if it is omitted from a call. + If no initialization expression is specified, an omitted + argument is initialized to NIL. It is also possible to provide + the name of a supplied-p variable that can be used to + determine if a call provided a value for the argument or if the + initialization expression was used. If specified, the supplied- + p variable will be bound to T if a value was specified in the + call and NIL if the default value was used. +

    + The &optional arguments are followed by the &rest argument. The + &rest argument gets bound to the remainder of the argument list + after the required and &optional arguments have been removed. +

    + The &rest argument is followed by the &key arguments. When a + keyword argument is passed to a function, a pair of values + appears in the argument list. The first expression in the pair + should evaluate to a keyword symbol (a symbol that begins with a + ``:''). The value of the second expression is the value of the + keyword argument. Like &optional arguments, &key arguments can + have initialization expressions and supplied-p variables. In + addition, it is possible to specify the keyword to be used in a + function call. If no keyword is specified, the keyword obtained + by adding a ``:'' to the beginning of the keyword argument symbol + is used. In other words, if the keyword argument symbol is + foo, the keyword will be ':foo. +

    + The &key arguments are followed by the &aux variables. These + are local variables that are bound during the evaluation of the + function body. It is possible to have initialization + expressions for the &aux variables. +

    + Here is the complete syntax for lambda lists: +

    + (rarg...
    + + [&optional [oarg | (oarg [init [svar]])]...]
    + + [&rest rarg]
    + + [&key
    + + [karg | ([karg | (key karg)] [init [svar]])]...
    + + &allow-other-keys]
    + + [&aux
    + + [aux | (aux [init])]...]) +

    + where: +

    + rarg is a required argument symbol
    + + oarg is an &optional argument symbol
    + + rarg is the &rest argument symbol
    + + karg is a &key argument symbol
    + + key is a keyword symbol
    + + aux is an auxiliary variable symbol
    + + init is an initialization expression
    + + svar is a supplied-p variable symbol
    + +

    +

    +

    Objects

    Definitions: +
      +
    • +selector - a symbol used to select an appropriate method +
    • message - a selector and a list of actual arguments +
    • method - the code that implements a message +
    + Since XLISP was created to provide a simple basis for + experimenting with object-oriented programming, one of the + primitive data types included is object. In XLISP, an object + consists of a data structure containing a pointer to the + object's class as well as an array containing the values of the + object's instance variables. +

    + Officially, there is no way to see inside an object (look at the + values of its instance variables). The only way to communicate + with an object is by sending it a message. +

    + You can send a message to an object using the send function. + This function takes the object as its first argument, the + message selector as its second argument (which must be a symbol) + and the message arguments as its remaining arguments. +

    + The send function determines the class of the receiving object + and attempts to find a method corresponding to the message + selector in the set of messages defined for that class. If the + message is not found in the object's class and the class has a + super-class, the search continues by looking at the messages + defined for the super-class. This process continues from one + super-class to the next until a method for the message is found. + If no method is found, an error occurs. +

    + A message can also be sent from the body of a method by using + the current object, but the method lookup starts with the + object's superclass rather than its class. This allows a + subclass to invoke a standard method in its parent class even + though it overrides that method with its own specialized + version. +

    + When a method is found, the evaluator binds the receiving object + to the symbol self and evaluates the method using the + remaining elements of the original list as arguments to the + method. These arguments are always evaluated prior to being + bound to their corresponding formal arguments. The result of + evaluating the method becomes the result of the expression. +

    +

    The ``Object'' Class

    Object - the top of the class hierarchy. +

    +Messages: +

    +
    +:show - show an object's instance variables. +
    +returns - the object + +
    +
    :class - return the class of an object +
    +returns - the class of the object + +
    +
    :isnew - the default object initialization routine +
    +returns - the object +
    +:sendsuper sel args... - send superclass a message +
    +sel - the message selector
    +args - the message arguments
    +returns - the result of sending the message + +
    +
    +
    +

    +

    The ``Class'' Class

    Class - class of all object classes (including itself) +

    + Messages: +

    +

    +
    + :new - create a new instance of a class +
    + returns - the new class object + +
    +
    :isnew ivars [cvars [super]] - initialize a new class +
    + ivars - the list of instance variable symbols
    + cvars - the list of class variable symbols
    + super - the superclass (default is object)
    + returns - the new class object + +
    +
    :answer msg fargs code - add a message to a class +
    + msg - the message symbol
    + fargs - the formal argument list (lambda list)
    + code - a list of executable expressions
    + returns - the object + +
    +
    +
    +

    + When a new instance of a class is created by sending the message + :new to an existing class, the message :isnew followed by + whatever parameters were passed to the :new message is sent to + the newly created object. +

    + When a new class is created by sending the :new message to the + object Class, an optional parameter may be specified + indicating the superclass of the new class. If this parameter + is omitted, the new class will be a subclass of Object. A + class inherits all instance variables, class variables, and + methods from its super-class. +

    +

    Profiling

    +The Xlisp 2.0 release has been extended with a profiling facility, which counts how many times and where eval is executed. A separate count is maintained for each named function, closure, or macro, and a count indicates an eval in the immediately (lexically) enclosing named function, closure, or macro. Thus, the count gives an indication of the amount of time spent in a function, not counting nested function calls. The list of all functions executed is maintained on the global *profile* variable. These functions in turn have *profile* properties, which maintain the counts. The profile system merely increments counters and puts symbols on the *profile* list. It is up to the user to initialize data and gather results. Profiling is turned on or off with the profile function. Unfortunately, methods cannot be profiled with this facility. +

    +

    SYMBOLS

    + +

    + There are several symbols maintained by the read/eval/print + loop. The symbols +, ++, and +++ are bound to the most + recent three input expressions. The symbols *, ** and *** + are bound to the most recent three results. The symbol - is + bound to the expression currently being evaluated. It becomes + the value of + at the end of the evaluation. +

    Evaluation Functions

    +
    +
    + (eval expr) - evaluate an xlisp expression +
    + expr - the expression to be evaluated
    + returns - the result of evaluating the expression + +
    +
    (apply fun args) - apply a function to a list of arguments +
    + fun - the function to apply (or function symbol)
    + args - the argument list
    + returns - the result of applying the function to the arguments + +
    +
    (funcall fun arg...) - call a function with arguments +
    + fun - the function to call (or function symbol)
    + arg - arguments to pass to the function
    + returns - the result of calling the function with the arguments + +
    +
    (quote expr) - return an expression unevaluated +
    + expr - the expression to be quoted (quoted)
    + returns - expr unevaluated + +
    +
    (function expr) - get the functional interpretation
    + expr - the symbol or lambda expression (quoted)
    + returns - the functional interpretation
    + +
    (backquote expr) - fill in a template
    + expr - the template
    + returns - a copy of the template with comma and comma-at
    + expressions expanded + +
    +
    (lambda args expr...) - make a function closure
    + args - formal argument list (lambda list) (quoted)
    + expr - expressions of the function body
    + returns - the function closure
    + +
    (get-lambda-expression closure) - get the lambda expression
    + closure - the closure
    + returns - the original lambda expression
    + +
    (macroexpand form) - recursively expand macro calls
    + form - the form to expand
    + returns - the macro expansion
    + +
    (macroexpand-1 form) - expand a macro call
    + form - the macro call form
    + returns - the macro expansion
    + +
    +

    Symbol Functions

    +
    +
    + (set sym expr) - set the value of a symbol +
    + sym - the symbol being set
    + expr - the new value
    + returns - the new value
    + +
    (setq [sym expr]...) - set the value of a symbol +
    + sym - the symbol being set (quoted)
    + expr - the new value
    + returns - the new value
    + +
    (psetq [sym expr]...) - parallel version of setq +
    + sym - the symbol being set (quoted)
    + expr - the new value
    + returns - the new value
    + +
    (setf [place expr]...) - set the value of a field +
    + place - the field specifier (quoted):
    +
    + sym - set value of a symbol
    + (car expr) - set car of a cons node
    + (cdr expr) - set cdr of a cons node
    + (nth n expr) - set nth car of a list
    + (aref expr n) - set nth element of an array
    + (get sym prop) - set value of a property
    + (symbol-value sym) - set value of a symbol
    + (symbol-function sym) - set functional value of a symbol
    + (symbol-plist sym) - set property list of a symbol
    +
    + expr - the new value
    + returns - the new value
    + +
    + + (defun sym fargs expr...) - define a function
    + (defmacro
    sym fargs expr...) - define a macro + +
    + sym - symbol being defined (quoted)
    + fargs - formal argument list (lambda list) (quoted)
    + expr - expressions constituting the body of the
    + function (quoted) + returns - the function symbol
    + +
    (gensym [tag]) - generate a symbol +
    + tag - string or number
    + returns - the new symbol
    + +
    (intern pname) - make an interned symbol +
    + pname - the symbol's print name string
    + returns - the new symbol
    + +
    (make-symbol pname) - make an uninterned symbol +
    + pname - the symbol's print name string
    + returns - the new symbol
    + +
    (symbol-name sym) - get the print name of a symbol +
    + sym - the symbol
    + returns - the symbol's print name
    + +
    (symbol-value sym) - get the value of a symbol +
    + sym - the symbol
    + returns - the symbol's value
    + +
    (symbol-function sym) - get the functional value of a symbol +
    + sym - the symbol
    + returns - the symbol's functional value
    + +
    (symbol-plist sym) - get the property list of a symbol +
    + sym - the symbol
    + returns - the symbol's property list
    + +
    (hash sym n) - compute the hash index for a symbol +
    + sym - the symbol or string
    + n - the table size (integer)
    + returns - the hash index (integer)
    + +
    +

    Property List Functions

    +
    +
    + (get sym prop) - get the value of a property +
    + sym - the symbol
    + prop - the property symbol
    + returns - the property value or nil
    + +
    (putprop sym val prop) - put a property onto a property list +
    + sym - the symbol
    + val - the property value
    + prop - the property symbol
    + returns - the property value
    + +
    (remprop sym prop) - remove a property +
    + sym - the symbol
    + prop - the property symbol
    + returns - nil
    + +
    +

    Array Functions

    +
    +
    + (aref array n) - get the nth element of an array +
    + array - the array
    + n - the array index (integer)
    + returns - the value of the array element
    + +
    (make-array size) - make a new array +
    + size - the size of the new array (integer)
    + returns - the new array
    + +
    (vector expr...) - make an initialized vector +
    + expr - the vector elements
    + returns - the new vector
    + +
    +

    List Functions

    +
    +
    + (car expr) - return the car of a list node +
    + expr - the list node
    + returns - the car of the list node
    + +
    (cdr expr) - return the cdr of a list node +
    + expr - the list node
    + returns - the cdr of the list node
    + +
    (cxxr expr) - all cxxr combinations +
    + +
    +
    (cxxxr expr) - all cxxxr combinations +
    + +
    +
    (cxxxxr expr) - all cxxxxr combinations +
    + +
    +
    (first expr) - a synonym for car +
    + +
    +
    (second expr) - a synonym for cadr +
    + +
    +
    (third expr) - a synonym for caddr +
    + +
    +
    (fourth expr) - a synonym for cadddr +
    + +
    +
    (rest expr) - a synonym for cdr +
    + +
    +
    (cons expr1 expr2) - construct a new list node +
    + expr1 - the car of the new list node
    + expr2 - the cdr of the new list node
    + returns - the new list node
    + +
    (list expr...) - create a list of values +
    + expr - expressions to be combined into a list
    + returns - the new list
    + +
    (append expr...) - append lists +
    + expr - lists whose elements are to be appended
    + returns - the new list
    + +
    (reverse expr) - reverse a list +
    + expr - the list to reverse
    + returns - a new list in the reverse order
    + +
    (last list) - return the last list node of a list +
    + list - the list
    + returns - the last list node in the list
    + +
    (member expr list &key :test :test-not) - find an expression in a list +
    + expr - the expression to find
    + list - the list to search
    + :test - the test function (defaults to eql)
    + :test-not - the test function (sense inverted)
    + returns - the remainder of the list starting with the expression
    + +
    (assoc expr alist &key :test :test-not) - find an expression in an a-list +
    + expr - the expression to find
    + alist - the association list
    + :test - the test function (defaults to eql)
    + :test-not - the test function (sense inverted)
    + returns - the alist entry or nil
    + +
    (remove expr list &key :test :test-not) - remove elements from a list +
    + expr - the element to remove
    + list - the list
    + :test - the test function (defaults to eql)
    + :test-not - the test function (sense inverted)
    + returns - copy of list with matching expressions removed
    + +
    (remove-if test list) - remove elements that pass test +
    + test - the test predicate
    + list - the list
    + returns - copy of list with matching elements removed
    + +
    (remove-if-not test list) - remove elements that fail test +
    + test - the test predicate
    + list - the list
    + returns - copy of list with non-matching elements removed
    + +
    (length expr) - find the length of a list, vector or string +
    + expr - the list, vector or string
    + returns - the length of the list, vector or string
    + +
    (nth n list) - return the nth element of a list +
    + n - the number of the element to return (zero origin)
    + list - the list
    + returns - the nth element or nil if the list isn't that long
    + +
    (nthcdr n list) - return the nth cdr of a list +
    + n - the number of the element to return (zero origin)
    + list - the list
    + returns - the nth cdr or nil if the list isn't that long
    + +
    (mapc fcn list1 list...) - apply function to successive cars +
    + fcn - the function or function name
    + listn - a list for each argument of the function
    + returns - the first list of arguments
    + +
    (mapcar fcn list1 list...) - apply function to successive cars +
    + fcn - the function or function name
    + listn - a list for each argument of the function
    + returns - a list of the values returned
    + +
    (mapl fcn list1 list...) - apply function to successive cdrs +
    + fcn - the function or function name
    + listn - a list for each argument of the function
    + returns - the first list of arguments
    + +
    (maplist fcn list1 list...) - apply function to successive cdrs +
    + fcn - the function or function name
    + listn - a list for each argument of the function
    + returns - a list of the values returned
    + +
    (subst to from expr &key :test :test-not) - substitute expressions +
    + to - the new expression
    + from - the old expression
    + expr - the expression in which to do the substitutions
    + :test - the test function (defaults to eql)
    + :test-not - the test function (sense inverted)
    + returns - the expression with substitutions
    + +
    (sublis alist expr &key :test :test-not) - substitute with an a-list +
    + alist - the association list
    + expr - the expression in which to do the substitutions
    + :test - the test function (defaults to eql)
    + :test-not - the test function (sense inverted)
    + returns - the expression with substitutions
    + +
    +

    Destructive List Functions

    +
    +
    + (rplaca list expr) - replace the car of a list node +
    + list - the list node
    + expr - the new value for the car of the list node
    + returns - the list node after updating the car
    + +
    (rplacd list expr) - replace the cdr of a list node +
    + list - the list node
    + expr - the new value for the cdr of the list node
    + returns - the list node after updating the cdr
    + +
    (nconc list...) - destructively concatenate lists +
    + list - lists to concatenate
    + returns - the result of concatenating the lists
    + +
    (delete expr &key :test :test-not) - delete elements from a list +
    + expr - the element to delete
    + list - the list
    + :test - the test function (defaults to eql)
    + :test-not - the test function (sense inverted)
    + returns - the list with the matching expressions deleted
    + +
    (delete-if test list) - delete elements that pass test +
    + test - the test predicate
    + list - the list
    + returns - the list with matching elements deleted
    + +
    (delete-if-not test list) - delete elements that fail test +
    + test - the test predicate
    + list - the list
    + returns - the list with non-matching elements deleted
    + +
    (sort list test) - sort a list +
    + list - the list to sort
    + test - the comparison function
    + returns - the sorted list
    + +
    +

    Predicate Functions

    +
    +
    + (atom expr) - is this an atom? +
    + expr - the expression to check
    + returns - t if the value is an atom, nil otherwise
    + +
    (symbolp expr) - is this a symbol? +
    + expr - the expression to check
    + returns - t if the expression is a symbol, nil otherwise
    + +
    (numberp expr) - is this a number? +
    + expr - the expression to check
    + returns - t if the expression is a number, nil otherwise
    + +
    (null expr) - is this an empty list? +
    + expr - the list to check
    + returns - t if the list is empty, nil otherwise
    + +
    (not expr) - is this false? +
    + expr - the expression to check
    + return - t if the value is nil, nil otherwise
    + +
    (listp expr) - is this a list? +
    + expr - the expression to check
    + returns - t if the value is a cons or nil, nil otherwise
    + +
    (endp list) - is this the end of a list +
    + list - the list
    + returns - t if the value is nil, nil otherwise
    + +
    (consp expr) - is this a non-empty list? +
    + expr - the expression to check
    + returns - t if the value is a cons, nil otherwise
    + +
    (integerp expr) - is this an integer? +
    + expr - the expression to check
    + returns - t if the value is an integer, nil otherwise
    + +
    (floatp expr) - is this a float? +
    + expr - the expression to check
    + returns - t if the value is a float, nil otherwise
    + +
    (stringp expr) - is this a string? +
    + expr - the expression to check
    + returns - t if the value is a string, nil otherwise
    + +
    (characterp expr) - is this a character? +
    + expr - the expression to check
    + returns - t if the value is a character, nil otherwise
    + +
    (arrayp expr) - is this an array? +
    + expr - the expression to check
    + returns - t if the value is an array, nil otherwise
    + +
    (streamp expr) - is this a stream? +
    + expr - the expression to check
    + returns - t if the value is a stream, nil otherwise
    + +
    (objectp expr) - is this an object? +
    + expr - the expression to check
    + returns - t if the value is an object, nil otherwise
    + +
    (boundp sym) - is a value bound to this symbol? +
    + sym - the symbol
    + returns - t if a value is bound to the symbol, nil otherwise
    + +
    (fboundp sym) - is a functional value bound to this symbol? +
    + sym - the symbol
    + returns - t if a functional value is bound to the symbol,
    + nil otherwise + +
    +
    (minusp expr) - is this number negative? +
    + expr - the number to test
    + returns - t if the number is negative, nil otherwise
    + +
    (zerop expr) - is this number zero? +
    + expr - the number to test
    + returns - t if the number is zero, nil otherwise
    + +
    (plusp expr) - is this number positive? +
    + expr - the number to test
    + returns - t if the number is positive, nil otherwise
    + +
    (evenp expr) - is this integer even? +
    + expr - the integer to test
    + returns - t if the integer is even, nil otherwise
    + +
    (oddp expr) - is this integer odd? +
    + expr - the integer to test
    + returns - t if the integer is odd, nil otherwise
    + +
    (eq expr1 expr2) - are the expressions identical? +
    + expr1 - the first expression
    + expr2 - the second expression
    + returns - t if they are equal, nil otherwise
    + +
    (eql expr1 expr2) - are the expressions +identical? (works with all numbers) +
    + expr1 - the first expression
    + expr2 - the second expression
    + returns - t if they are equal, nil otherwise
    + +
    (equal expr1 expr2) - are the expressions equal? +
    + expr1 - the first expression
    + expr2 - the second expression
    + returns - t if they are equal, nil otherwise
    + +
    +

    Control Constructs

    +
    +
    + (cond pair...) - evaluate conditionally +
    + pair - pair consisting of:
    +
    + (pred expr...) +
    + where: +
    + pred - is a predicate expression
    + expr - evaluated if the predicate + is not nil +
    +returns - the value of the first expression whose predicate is not +nil + +
    +
    (and expr...) - the logical and of a list of expressions +
    + expr - the expressions to be anded
    + returns - nil if any expression evaluates to nil, + otherwise the value of the last expression + (evaluation of expressions stops after the first + expression that evaluates to nil) + +
    +
    (or expr...) - the logical or of a list of expressions +
    + expr - the expressions to be ored
    + returns - nil if all expressions evaluate to nil, + otherwise the value of the first non-nil expression + (evaluation of expressions stops after the first + expression that does not evaluate to nil) + +
    +
    (if texpr expr1 [expr2]) - evaluate expressions conditionally +
    + texpr - the test expression
    + expr1 - the expression to be evaluated if texpr is non-nil
    + expr2 - the expression to be evaluated if texpr is nil
    + returns - the value of the selected expression
    + +
    (when texpr expr...) - evaluate only when a condition is true +
    + texpr - the test expression
    + expr - the expression(s) to be evaluated if texpr is non-nil
    + returns - the value of the last expression or nil + +
    +
    (unless texpr expr...) - evaluate only when a condition is false +
    + texpr - the test expression
    + expr - the expression(s) to be evaluated if texpr is nil
    + returns - the value of the last expression or nil
    + +
    (case expr case...) - select by case +
    + expr - the selection expression
    + case - pair consisting of:
    +
    + (value expr...) +
    + where: +
    + value - is a single expression or a list of + expressions (unevaluated)
    + expr - are expressions to execute if the + case matches +
    + returns - the value of the last expression of the matching case
    + +
    + + (let (binding...) expr...) - create local bindings
    + (let*
    (binding...) expr...) - let with sequential binding + +
    + binding - the variable bindings each of which is either:
    +
    + 1) a symbol (which is initialized to nil)
    + 2) a list whose car is a symbol and whose cadr + is an initialization expression +
    + expr - the expressions to be evaluated
    + returns - the value of the last expression
    + +
    + + (flet (binding...) expr...) - create local functions
    + (labels
    (binding...) expr...) - flet with recursive functions
    + (macrolet
    (binding...) expr...) - create local macros + +
    + binding - the function bindings each of which is:
    +
    + (sym fargs expr...) +
    + where: +
    + sym - the function/macro name
    + fargs - formal argument list (lambda list)
    + expr - expressions constituting the body of + the function/macro +
    + expr - the expressions to be evaluated
    + returns - the value of the last expression + +
    +
    (catch sym expr...) - evaluate expressions and catch throws +
    + sym - the catch tag
    + expr - expressions to evaluate
    + returns - the value of the last expression the throw expression
    + +
    (throw sym [expr]) - throw to a catch +
    + sym - the catch tag
    + expr - the value for the catch to return (defaults to nil)
    + returns - never returns
    + +
    (unwind-protect expr cexpr...) - protect evaluation of an expression +
    + expr - the expression to protect
    + cexpr - the cleanup expressions
    + returns - the value of the expression
    + Note: unwind-protect guarantees to execute the cleanup expressions + even if a non-local exit terminates the evaluation of the + protected expression + +
    +
    +
    +

    +

    Looping Constructs

    +
    +
    + (loop expr...) - basic looping form +
    + expr - the body of the loop
    + returns - never returns (must use non-local exit)
    + +
    + + (do (binding...) (texpr rexpr...) expr...)
    + (do*
    (binding...) (texpr rexpr...) expr...) + +
    + binding - the variable bindings each of which is either:
    +
    + 1) a symbol (which is initialized to nil)
    + 2) a list of the form: (sym init [step]) + where: +
    + sym - is the symbol to bind
    + init - is the initial value of the symbol
    + step - is a step expression
    +
    +
    + texpr - the termination test expression
    + rexpr - result expressions (the default is nil)
    + expr - the body of the loop (treated like an implicit prog)
    + returns - the value of the last result expression
    + +
    (dolist (sym expr [rexpr]) expr...) - loop through a list +
    + sym - the symbol to bind to each list element
    + expr - the list expression
    + rexpr - the result expression (the default is nil)
    + expr - the body of the loop (treated like an implicit prog)
    + +
    (dotimes (sym expr [rexpr]) expr...) - loop from zero to n-1 +
    + sym - the symbol to bind to each value from 0 to n-1
    + expr - the number of times to loop
    + rexpr - the result expression (the default is nil)
    + expr - the body of the loop (treated like an implicit prog)
    + +
    +

    The Program Feature

    +
    +
    + +(prog (binding...) expr...) - the program feature
    +(prog*
    (binding...) expr...) - prog with sequential binding + +
    + binding - the variable bindings each of which is either:
    +
    + 1) a symbol (which is initialized to nil)
    + 2) a list whose car is a symbol and whose cadr + is an initialization expression +
    + expr - expressions to evaluate or tags (symbols)
    + returns - nil or the argument passed to the return function
    + +
    (block name expr...) - named block +
    + name - the block name (symbol)
    + expr - the block body
    + returns - the value of the last expression
    + +
    (return [expr]) - cause a prog construct to return a value +
    + expr - the value (defaults to nil)
    + returns - never returns
    + +
    (return-from name [value]) - return from a named block +
    + name - the block name (symbol)
    + value - the value to return (defaults to nil)
    + returns - never returns
    + +
    (tagbody expr...) - block with labels +
    + expr - expression(s) to evaluate or tags (symbols)
    + returns - nil
    + +
    (go sym) - go to a tag within a tagbody or prog +
    + sym - the tag (quoted)
    + returns - never returns
    + +
    (progv slist vlist expr...) - dynamically bind symbols +
    + slist - list of symbols
    + vlist - list of values to bind to the symbols
    + expr - expression(s) to evaluate
    + returns - the value of the last expression
    + +
    (prog1 expr1 expr...) - execute expressions sequentially +
    + expr1 - the first expression to evaluate
    + expr - the remaining expressions to evaluate
    + returns - the value of the first expression
    + +
    (prog2 expr1 expr2 expr...) - execute expressions sequentially +
    + expr1 - the first expression to evaluate
    + expr2 - the second expression to evaluate
    + expr - the remaining expressions to evaluate
    + returns - the value of the second expression
    + +
    (progn expr...) - execute expressions sequentially +
    + expr - the expressions to evaluate
    + returns - the value of the last expression (or nil)
    + +
    +

    Debugging and Error Handling

    +
    +
    + (trace sym) - add a function to the trace list +
    + sym - the function to add (quoted)
    + returns - the trace list
    + +
    (untrace sym) - remove a function from the trace list +
    + sym - the function to remove (quoted)
    + returns - the trace list
    + +
    (error emsg [arg]) - signal a non-correctable error +
    + emsg - the error message string
    + arg - the argument expression (printed after the message)
    + returns - never returns
    + +
    (cerror cmsg emsg [arg]) - signal a correctable error +
    + cmsg - the continue message string
    + emsg - the error message string
    + arg - the argument expression (printed after the message)
    + returns - nil when continued from the break loop
    + +
    (break [bmsg [arg]]) - enter a break loop +
    + bmsg - the break message string (defaults to **break**)
    + arg - the argument expression (printed after the message)
    + returns - nil when continued from the break loop
    + +
    (clean-up) - clean-up after an error +
    + returns - never returns
    + +
    (top-level) - clean-up after an error and return to the top level +
    + returns - never returns
    + +
    (continue) - continue from a correctable error +
    + returns - never returns
    + +
    (errset expr [pflag]) - trap errors +
    + expr - the expression to execute
    + pflag - flag to control printing of the error message
    + returns - the value of the last expression consed with nil
    + or nil on error + +
    +
    (baktrace [n]) - print n levels of trace back information +
    + n - the number of levels (defaults to all levels)
    + returns - nil
    + +
    (evalhook expr ehook ahook [env]) - evaluate with hooks +
    + expr - the expression to evaluate
    + ehook - the value for *evalhook*
    + ahook - the value for *applyhook*
    + env - the environment (default is nil)
    + returns - the result of evaluating the expression
    + +
    (profile flag) (Footnote 3) - turn profiling on or off. +
    + flag - nil turns profiling off, otherwise on
    + returns - the previous state of profiling.
    + +
    +

    Arithmetic Functions

    +
    +
    + (truncate expr) - truncates a floating point number to an integer +
    + expr - the number
    + returns - the result of truncating the number
    + +
    (float expr) - converts an integer to a floating point number +
    + expr - the number
    + returns - the result of floating the integer
    + +
    (+ expr...) - add a list of numbers +
    + expr - the numbers
    + returns - the result of the addition
    + +
    (- expr...) - subtract a list of numbers or negate a single number +
    + expr - the numbers
    + returns - the result of the subtraction
    + +
    (* expr...) - multiply a list of numbers +
    + expr - the numbers
    + returns - the result of the multiplication
    + +
    (/ expr...) - divide a list of numbers +
    + expr - the numbers
    + returns - the result of the division
    + +
    (1+ expr) - add one to a number +
    + expr - the number
    + returns - the number plus one
    + +
    (1- expr) - subtract one from a number +
    + expr - the number
    + returns - the number minus one
    + +
    (rem expr...) - remainder of a list of numbers +
    + expr - the numbers
    + returns - the result of the remainder operation
    + +
    (min expr...) - the smallest of a list of numbers +
    + expr - the expressions to be checked
    + returns - the smallest number in the list
    + +
    (max expr...) - the largest of a list of numbers +
    + expr - the expressions to be checked
    + returns - the largest number in the list
    + +
    (abs expr) - the absolute value of a number +
    + expr - the number
    + returns - the absolute value of the number
    + +
    (gcd n1 n2...) - compute the greatest common divisor +
    + n1 - the first number (integer)
    + n2 - the second number(s) (integer)
    + returns - the greatest common divisor
    + +
    (random n) - compute a random number between 1 and n-1 +
    + n - the upper bound (integer)
    + returns - a random number
    + +
    (sin expr) - compute the sine of a number +
    + expr - the floating point number
    + returns - the sine of the number
    + +
    (cos expr) - compute the cosine of a number +
    + expr - the floating point number
    + returns - the cosine of the number
    + +
    (tan expr) - compute the tangent of a number +
    + expr - the floating point number
    + returns - the tangent of the number
    + +
    (expt x-expr y-expr) - compute x to the y power +
    + x-expr - the floating point number
    + y-expr - the floating point exponent
    + returns - x to the y power
    + +
    (exp x-expr) - compute e to the x power +
    + x-expr - the floating point number
    + returns - e to the x power
    + +
    (sqrt expr) - compute the square root of a number +
    + expr - the floating point number
    + returns - the square root of the number
    + +
    + +(< n1 n2...) - test for less than
    +(<=
    n1 n2...) - test for less than or equal to
    +(=
    n1 n2...) - test for equal to
    +(/=
    n1 n2...) - test for not equal to
    +(>=
    n1 n2...) - test for greater than or equal to
    +(>
    n1 n2...) - test for greater than + +
    + n1 - the first number to compare
    + n2 - the second number to compare
    +returns - t if the results of comparing n1 with n2, +n2 with n3, etc., are all true.
    + +
    +

    Bitwise Logical Functions

    +
    +
    + (logand expr...) - the bitwise and of a list of numbers +
    + expr - the numbers
    + returns - the result of the and operation
    + +
    (logior expr...) - the bitwise inclusive or of a list of numbers +
    + expr - the numbers
    + returns - the result of the inclusive or operation
    + +
    (logxor expr...) - the bitwise exclusive or of a list of numbers +
    + expr - the numbers
    + returns - the result of the exclusive or operation
    + +
    (lognot expr) - the bitwise not of a number +
    + expr - the number
    + returns - the bitwise inversion of number
    + +
    +

    String Functions

    +
    +
    + (string expr) - make a string from an integer ascii value +
    + expr - the integer
    + returns - a one character string
    + +
    (string-search pat str &key :start :end) (Footnote 4) - search for pattern in string +
    + pat - a string to search for
    + str - the string to be searched
    + :start - the starting offset in str
    + :end - the ending offset + 1
    + returns - index of pat in str or NIL if not found
    + +
    (string-trim bag str) - trim both ends of a string +
    + bag - a string containing characters to trim
    + str - the string to trim
    + returns - a trimed copy of the string
    + +
    (string-left-trim bag str) - trim the left end of a string +
    + bag - a string containing characters to trim
    + str - the string to trim
    + returns - a trimed copy of the string
    + +
    (string-right-trim bag str) - trim the right end of a string +
    + bag - a string containing characters to trim
    + str - the string to trim
    + returns - a trimed copy of the string
    + +
    (string-upcase str &key :start :end) - convert to uppercase +
    + str - the string
    + :start - the starting offset
    + :end - the ending offset + 1
    + returns - a converted copy of the string
    + +
    (string-downcase str &key :start :end) - convert to lowercase +
    + str - the string
    + :start - the starting offset
    + :end - the ending offset + 1
    + returns - a converted copy of the string
    + +
    (nstring-upcase str &key :start :end) - convert to uppercase +
    + str - the string
    + :start - the starting offset
    + :end - the ending offset + 1
    + returns - the converted string (not a copy)
    + +
    (nstring-downcase str &key :start :end) - convert to lowercase +
    + str - the string
    + :start - the starting offset
    + :end - the ending offset + 1
    + returns - the converted string (not a copy)
    + +
    (strcat expr...) - concatenate strings +
    + expr - the strings to concatenate
    + returns - the result of concatenating the strings
    + +
    (subseq string start [end]) - extract a substring +
    + string - the string
    + start - the starting position (zero origin)
    + end - the ending position + 1 (defaults to end)
    + returns - substring between start and end
    + +
    + + (string< str1 str2 &key :start1 :end1 :start2 :end2)
    + (string<=
    str1 str2 &key :start1 :end1 :start2 :end2)
    + (string=
    str1 str2 &key :start1 :end1 :start2 :end2)
    + (string/=
    str1 str2 &key :start1 :end1 :start2 :end2)
    + (string>=
    str1 str2 &key :start1 :end1 :start2 :end2)
    + (string>
    str1 str2 &key :start1 :end1 :start2 :end2) + +
    + str1 - the first string to compare
    + str2 - the second string to compare
    + :start1 - first substring starting offset
    + :end1 - first substring ending offset + 1
    + :start2 - second substring starting offset
    + :end2 - second substring ending offset + 1
    + returns - t if predicate is true, nil otherwise
    + Note: case is significant with these comparison functions. + +
    +
    + +(string-lessp str1 str2 &key :start1 :end1 :start2 :end2)
    +(string-not-greaterp
    str1 str2 &key :start1 :end1 :start2 :end2)
    +(string-equalp
    str1 str2 &key :start1 :end1 :start2 :end2)
    +(string-not-equalp
    str1 str2 &key :start1 :end1 :start2 :end2)
    +(string-not-lessp
    str1 str2 &key :start1 :end1 :start2 :end2)
    +(string-greaterp str1 str2 &key :start1 :end1 :start2 :end2) + +
    + str1 - the first string to compare
    + str2 - the second string to compare
    + :start1 - first substring starting offset
    + :end1 - first substring ending offset + 1
    + :start2 - second substring starting offset
    + :end2 - second substring ending offset + 1
    + returns - t if predicate is true, nil otherwise
    + Note: case is not significant with these comparison functions. + +
    +
    +
    +

    +

    Character Functions

    +
    +
    + (char string index) - extract a character from a string +
    + string - the string
    + index - the string index (zero relative)
    + returns - the ascii code of the character
    + +
    (upper-case-p chr) - is this an upper case character? +
    + chr - the character
    + returns - t if the character is upper case, nil otherwise
    + +
    (lower-case-p chr) - is this a lower case character? +
    + chr - the character
    + returns - t if the character is lower case, nil otherwise
    + +
    (both-case-p chr) - is this an alphabetic (either case) character? +
    + chr - the character
    + returns - t if the character is alphabetic, nil otherwise
    + +
    (digit-char-p chr) - is this a digit character? +
    + chr - the character
    + returns - the digit weight if character is a digit, nil otherwise
    + +
    (char-code chr) - get the ascii code of a character +
    + chr - the character
    + returns - the ascii character code (integer)
    + +
    (code-char code) - get the character with a specified ascii code +
    + code - the ascii code (integer)
    + returns - the character with that code or nil
    + +
    (char-upcase chr) - convert a character to upper case +
    + chr - the character
    + returns - the upper case character
    + +
    (char-downcase chr) - convert a character to lower case +
    + chr - the character
    + returns - the lower case character
    + +
    (digit-char n) - convert a digit weight to a digit +
    + n - the digit weight (integer)
    + returns - the digit character or nil
    + +
    (char-int chr) - convert a character to an integer +
    + chr - the character
    + returns - the ascii character code
    + +
    (int-char int) - convert an integer to a character +
    + int - the ascii character code
    + returns - the character with that code
    + +
    + + (char< chr1 chr2...)
    + (char<=
    chr1 chr2...)
    + (char=
    chr1 chr2...)
    + (char/=
    chr1 chr2...)
    + (char>=
    chr1 chr2...)
    + (char>
    chr1 chr2...) + +
    + chr1 - the first character to compare
    + chr2 - the second character(s) to compare
    + returns - t if predicate is true, nil otherwise
    + Note: case is significant with these comparison functions. + +
    +
    + +(char-lessp chr1 chr2...)
    +(char-not-greaterp
    chr1 chr2...)
    +(char-equalp
    chr1 chr2...)
    +(char-not-equalp
    chr1 chr2...)
    +(char-not-lessp
    chr1 chr2...)
    +(char-greaterp
    chr1 chr2...) + +
    +chr1 - the first string to compare
    +chr2 - the second string(s) to compare
    +returns - t if predicate is true, nil otherwise
    + +
    + Note: case is not significant with these comparison functions. +
    +

    +

    Input/Output Functions

    +
    +
    + (read [stream [eof [rflag]]]) - read an expression +
    + stream - the input stream (default is standard input)
    + eof - the value to return on end of file (default is nil)
    + rflag - recursive read flag (default is nil)
    + returns - the expression read
    + +
    (print expr [stream]) - print an expression on a new line +
    + expr - the expression to be printed
    + stream - the output stream (default is standard output)
    + returns - the expression
    + +
    (prin1 expr [stream]) - print an expression +
    + expr - the expression to be printed
    + stream - the output stream (default is standard output)
    + returns - the expression
    + +
    (princ expr [stream]) - print an expression without quoting +
    + expr - the expressions to be printed
    + stream - the output stream (default is standard output)
    + returns - the expression
    + +
    (pprint expr [stream]) - pretty print an expression +
    + expr - the expressions to be printed
    + stream - the output stream (default is standard output)
    + returns - the expression
    + +
    (terpri [stream]) - terminate the current print line +
    + stream - the output stream (default is standard output)
    + returns - nil
    + +
    (flatsize expr) - length of printed representation using prin1 +
    + expr - the expression
    + returns - the length
    + +
    (flatc expr) - length of printed representation using princ +
    + expr - the expression
    + returns - the length
    + +
    +

    The Format Function

    +
    +
    +(format stream fmt arg...) - do formated +output +
    + stream - the output stream
    + fmt - the format string
    + arg - the format arguments
    + returns - output string if stream is nil, nil otherwise
    + +
    +
    + The format string can contain characters that should be copied + directly to the output and formatting directives. The + formatting directives are: +
    +~A - print next argument using princ
    + +~S - print next argument using prin1
    + +~% - start a new line
    + +~~ - print a tilde character
    + +
    +

    +

    File I/O Functions

    +Note that files are ordinarily opened as text. Binary files (such as standard midi files) must be opened with open-binary on non-unix systems. +
    +
    + (open fname &key :direction) - open a file stream +
    + fname - the file name string or symbol
    + :direction - :input or :output (default is :input)
    + returns - a stream
    + +
    + (open-binary fname &key :direction) - open a binary file stream +
    + fname - the file name string or symbol
    + :direction - :input or :output (default is :input)
    + returns - a stream
    + +
    (close stream) - close a file stream +
    + stream - the stream
    + returns - nil
    + +
    (read-char [stream]) - read a character from a stream +
    + stream - the input stream (default is standard input)
    + returns - the character
    + +
    (peek-char [flag [stream]]) - peek at the next character +
    + flag - flag for skipping white space (default is nil)
    + stream - the input stream (default is standard input)
    + returns - the character (integer)
    + +
    (write-char ch [stream]) - write a character to a stream +
    + ch - the character to write
    + stream - the output stream (default is standard output)
    + returns - the character
    + +
    (read-int [stream [length]]) - read a binary integer from a stream +
    + stream - the input stream (default is standard input)
    + length - the length of the integer in bytes (default is 4)
    + returns - the integer
    +Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
    + +
    (write-int ch [stream [length]]) - write a binary integer to a stream +
    + ch - the character to write
    + stream - the output stream (default is standard output)
    + length - the length of the integer in bytes (default is 4)
    + returns - the integer
    +Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
    + +
    (read-float [stream [length]]) - read a binary floating-point number from a stream +
    + stream - the input stream (default is standard input)
    + length - the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8)
    + returns - the integer
    +Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
    + +
    (write-float ch [stream [length]]) - write a binary floating-point number to a stream +
    + ch - the character to write
    + stream - the output stream (default is standard output)
    + length - the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8)
    + returns - the integer
    +Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode.
    + +
    (read-line [stream]) - read a line from a stream +
    + stream - the input stream (default is standard input)
    + returns - the string
    + +
    (read-byte [stream]) - read a byte from a stream +
    + stream - the input stream (default is standard input)
    + returns - the byte (integer)
    + +
    (write-byte byte [stream]) - write a byte to a stream +
    + byte - the byte to write (integer)
    + stream - the output stream (default is standard output)
    + returns - the byte (integer)
    + +
    +

    String Stream Functions

    + These functions operate on unnamed streams. An unnamed output + stream collects characters sent to it when it is used as the + destination of any output function. The functions +get-output-stream-string and string or a list of characters. +

    +An unnamed input stream is setup with the + make-string-input-stream function and returns each character of the string when + it is used as the source of any input function. +

    +

    +
    +
    + (make-string-input-stream str [start [end]]) +
    + str - the string
    + start - the starting offset
    + end - the ending offset + 1
    + returns - an unnamed stream that reads from the string
    + +
    (make-string-output-stream) +
    + returns - an unnamed output stream
    + +
    (get-output-stream-string stream) +
    + stream - the output stream
    + returns - the output so far as a string
    + + Note: the output stream is emptied by this function +
    +
    (get-output-stream-list stream) +
    + stream - the output stream
    + returns - the output so far as a list
    + + Note: the output stream is emptied by this function +
    +
    +
    +

    +

    System Functions

    +Note: the load function first tries to load a file from the current directory. A .lsp extension is added if there is not already an alphanumeric extension following a period. If that fails, XLisp searches the path, which is obtained from the XLISPPATH environment variable in Unix and HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under Win32. (The Macintosh version has no search path.) +

    +

    +
    + (load fname &key :verbose :print) - load a source file +
    + fname - the filename string or symbol
    + :verbose - the verbose flag (default is t)
    + :print - the print flag (default is nil)
    + returns - the filename
    + +
    (save fname) - save workspace to a file +
    + fname - the filename string or symbol
    + returns - t if workspace was written, nil otherwise
    + +
    (restore fname) - restore workspace from a file +
    + fname - the filename string or symbol
    + returns - nil on failure, otherwise never returns
    + +
    (dribble [fname]) - create a file with a transcript of a session +
    + fname - file name string or symbol + (if missing, close current transcript)
    + returns - t if the transcript is opened, nil if it is closed
    + +
    (gc) - force garbage collection +
    + returns - nil
    + +
    (expand num) - expand memory by adding segments +
    + num - the number of segments to add
    + returns - the number of segments added
    + +
    (alloc num) - change number of nodes to allocate in each segment +
    + num - the number of nodes to allocate
    + returns - the old number of nodes to allocate
    + +
    (room) - show memory allocation statistics +
    + returns - nil
    + +
    (type-of expr) - returns the type of the expression +
    + expr - the expression to return the type of
    + returns - nil if the value is nil otherwise one of the symbols:
    +
    + SYMBOL - for symbols
    + OBJECT - for objects
    + CONS - for conses
    + SUBR - for built-in functions
    + FSUBR - for special forms
    + CLOSURE - for defined functions
    + STRING - for strings
    + FIXNUM - for integers
    + FLONUM - for floating point numbers
    + CHARACTER - for characters
    + FILE-STREAM - for file pointers
    + UNNAMED-STREAM - for unnamed streams
    + ARRAY - for arrays
    +
    + +
    (peek addrs) - peek at a location in memory +
    + addrs - the address to peek at (integer)
    + returns - the value at the specified address (integer)
    + +
    (poke addrs value) - poke a value into memory +
    + addrs - the address to poke (integer)
    + value - the value to poke into the address (integer)
    + returns - the value
    + +
    (address-of expr) - get the address of an xlisp node +
    + expr - the node
    + returns - the address of the node (integer)
    + +
    (exit) - exit xlisp +
    + returns - never returns
    + +
    (setup-console) - set default console attributes +
    + returns - NIL
    +Note: Under Windows, Nyquist normally starts up in a medium-sized console window with black text and a white background, with a window title of ``Nyquist.'' This is normally accomplished by calling setup-console in system.lsp. In Nyquist, you can avoid this behavior by setting *setup-console* to NIL in your init.lsp file. If setup-console is not called, Nyquist uses standard input and output as is. This is what you want if you are running Nyquist inside of emacs, for example.

    + +

    File I/O Functions

    Input from a File

    To open a file for input, use the open function with the keyword +argument :direction set to :input. To open a file for output, +use the open function with the keyword argument :direction set +to :output. The open function takes a single required argument which +is the name of the file to be opened. This name can be in the form of a +string or a symbol. The open function returns an object of type +FILE-STREAM if it succeeds in opening the specified file. It returns the +value nil if it fails. In order to manipulate the file, it is +necessary to save the value returned by the open function. This is +usually done by assigning it to a variable with the setq special form or by +binding it using let or let*. Here is an example: +
    +(setq fp (open "init.lsp" :direction :input))
    +
    + + Evaluating this expression will result in the file init.lsp + being opened. The file object that will be returned by the open + function will be assigned to the variable fp. +

    + It is now possible to use the file for input. To read an + expression from the file, just supply the value of the fp + variable as the optional stream argument to read. +

    +(read fp)
    +
    + + Evaluating this expression will result in reading the first + expression from the file init.lsp. The expression will be + returned as the result of the read function. More expressions + can be read from the file using further calls to the read + function. When there are no more expressions to read, the read + function will return nil (or whatever value was supplied as the + second argument to read). +

    + Once you are done reading from the file, you should close it. + To close the file, use the following expression: +

    +(close fp)
    +
    + + Evaluating this expression will cause the file to be closed. +

    +

    Output to a File

    Writing to a file is pretty much the same as reading from one. + You need to open the file first. This time you should use the + open function to indicate that you will do output to the file. + For example: +
    +(setq fp (open "test.dat" :direction :output))
    +
    + + Evaluating this expression will open the file test.dat for + output. If the file already exists, its current contents will + be discarded. If it doesn't already exist, it will be created. + In any case, a FILE-STREAM object will be returned by the OPEN + function. This file object will be assigned to the fp + variable. +

    + It is now possible to write to this file by supplying the value + of the fp variable as the optional stream parameter in the print function. +

    +(print "Hello there" fp)
    +
    + + Evaluating this expression will result in the string ``Hello + there'' being written to the file test.dat. More data can be + written to the file using the same technique. +

    + Once you are done writing to the file, you should close it. + Closing an output file is just like closing an input file. +

    +(close fp)
    +
    + + Evaluating this expression will close the output file and make + it permanent. +

    +

    A Slightly More Complicated File Example

    This example shows how to open a file, read each Lisp expression + from the file and print it. It demonstrates the use of files + and the use of the optional stream argument to the read + function. +
    +(do* ((fp (open "test.dat" :direction :input))
    +      (ex (read fp) (read fp)))
    +     ((null ex) nil)
    +  (print ex))
    +
    + +

    + +


    +Previous Section | Next Section (Index) | Table of Contents | Title Page + diff --git a/docsrc/xlisp/xlisp-doc/manual/sal.htm b/docsrc/xlisp/xlisp-doc/manual/sal.htm new file mode 100644 index 0000000..c3eeb30 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/sal.htm @@ -0,0 +1,160 @@ + + +SAL + + + + + + + +XLISP + +
    + +

    SAL

    + +
    + +

    Data Types

    + +
    + +

    Data types used in SAL and XLISP:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      SALXLISP
      integer: 11
      float: 1.01.0
      string: "hello""hello"
      symbol: namename
      keyword: symbol::symbol
      list: {item-1 item-2 ...}(item-1 item-2 ...)
      array: array[index](aref array index)
      boolean: #t#f t nil

    + +

    Data types with different concepts:

    + +

    SAL:

    + +
      +
    • expressions - evaluated to produce a return value
    • +
    • statements - evaluated for side-effects
    • +
    + +

    XLISP:

    + +
      +
    • character - a single ASCII character
    • +
    • object - the XLISP object system
    • +
    • stream - data type of unknown length
    • +
    • subr - built-in function
    • +
    • fsubr - special form
    • +
    • closure - user defined function
    • +
    + +

    A function to print the Lisp code, produced by the SAL compiler, to the +screen:

    + +
    +(defun test (string)
    +  (if (not (stringp string))
    +      (error "not a string" string)
    +      (pprint (third (second (sal-compile string nil nil "<console>"))))))
    +
    + +

      Back to top

    + +
    + +
    + + diff --git a/docsrc/xlisp/xlisp-doc/manual/xlisp-man-033.htm b/docsrc/xlisp/xlisp-doc/manual/xlisp-man-033.htm new file mode 100644 index 0000000..223e3c6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/xlisp-man-033.htm @@ -0,0 +1,356 @@ +XLISP: An Object-oriented Lisp + + + + + +XLISP > +XLISP 2.0  -  +Contents  -  +Reference  -  +Previous | +Next + +
    + +

    33  Nyquist Functions

    + +
    + +
      +
    1. Predicate Functions
    2. +
        +
      • filep - is this a file ?
      • +
      +
    3. Arithmetic Functions
    4. +
        +
      • rrandom - compute a random real number between 0 and 1 inclusive
      • +
      +
    5. String Functions
    6. + +
    7. File I/O Functions
    8. +
        +
      • open-binary - open a binary file stream
      • +
      • setdir - set current directory
      • +
      • listdir - get a directory listing
      • +
      • get-temp-path - get a path where a temporary file can be created
      • +
      • read-int - read a binary integer from a stream
      • +
      • write-int - write a binary integer to a stream
      • +
      • read-float - read a binary floating-point number from a stream
      • +
      • write-float - write a binary floating-point number to a stream
      • +
      +
    9. System Functions
    10. +
        +
      • info - show information about memory usage
      • +
      • bigendiap - is this a big-endian machine ?
      • +
      • setup-console - set default console attributes
      • +
      • echoenabled - turn console input echoing on or off
      • +
      +
    11. Profiling
    12. +
        +
      • profile - turn profiling on or off
      • +
      +
    + +

    Note: if you're interested in *all* functions added by Nyquist to +the XLISP language, I suggest you download the Nyquist manual from:

    + + + +

    The following is a list of all Nyquist functions I have found in the +XLISP section of the Nyquist 2.36 manual but I cannot even +guarantee that the list is complete. I'm willing to add more functions here +if you find that some are missing but the best information source is the +Nyquist manual itself. Roger is always a step ahead and I do not want to +spread obsolete or wrong information.

    + + + +
    + +

    Predicate Functions

    + +
    + + + +
    + +
    (filep expr) - is this a file ?
    +
    expr - the expression to check
    +returns - T if the value is an object, NIL otherwise
    + +
    + +

      Back to Top

    + + + +
    + +

    Arithmetic Functions

    + +
    + + + +
    + +
    (rrandom) - compute a random real number between 0 and 1 inclusive
    +
    returns - a random floating point number
    + +
    + +

      Back to Top

    + + + +
    + +

    String Functions

    + +
    + + + +
    + +
    (string-search pat str &key :start :end) +- search for pattern in string
    +pat - a string to search for
    +str - the string to be searched
    +:start - the starting offset in str
    +:end - the ending offset + 1
    +returns - index of pat in str or NIL if not found
    + +
    + +

      Back to Top

    + + + +
    + +

    File I/O Functions

    + +
    + + + +

    Note: Files are ordinarily opened as text. Binary files [such +as standard MIDI files] must be opened with 'open-binary' on non-unix +systems.

    + +
    + +
    (open-binary fname &key :direction) - open a binary file stream
    +
    fname - the file name string or symbol
    +:direction - :input or :output [default is :input]
    +returns - a stream
    + +
    + +
    (setdir path) - set current directory
    +
    path - the path of the new directory
    +returns - the resulting full path, e.g. (setdir ".") gets the current +working directory, or NIL if an error occurs
    + +
    + +
    (listdir path) - get a directory listing
    +
    path - the path of the directory to be listed
    +returns - list of filenames in the directory
    + +
    + +
    (get-temp-path) - get a path where a temporary file can be created
    +
    returns - the resulting full path as a string
    + +
    + +

    Note: Under Windows, the 'get-temp-path' function is based on +environment variables. If XLISP is running as a sub-process to Java, the +environment may not exist, in which case the default result is the +unfortunate choice 'c:\windows\'.

    + +
    + + + +
    (read-int [stream [length]]) - read a binary integer from a stream
    +
    stream - the input stream [default is standard input]
    +length - the length of the integer in bytes [default is 4]
    +returns - the integer
    + +
    + +
    (write-int ch [stream [length]]) - write a binary integer to a stream
    +
    ch - the character to write
    +stream - the output stream [default is standard output]
    +length - the length of the integer in bytes [default is 4]
    +returns - the integer
    + +
    + +
    (read-float [stream [length]]) - read a binary +floating-point number from a stream
    +
    stream - the input stream (default is standard input)
    +length - the length of the float in bytes [default is 4, +legal values are -4, -8, 4, and 8]
    +returns - the float
    + +
    + +
    (write-float ch [stream [length]]) - write a binary floating-point number to a stream
    +
    ch - the character to write
    +stream - the output stream [default is standard output]
    +length - the length of the float in bytes [default is 4, +legal values are -4, -8, 4, and 8]
    +returns - the float
    + +
    + +

    Note: Integers and floats are assumed to be big-endian [high-order +byte first] and signed, regardless of the platform. To read little-endian +format, use a negative number for the length, e.g. '-4' indicates a 4-bytes, +low-order byte first. The file should be opened in binary mode.

    + +

      Back to Top

    + + + +
    + +

    System Functions

    + +
    + +

    Note: in Nyquist, the XLISP +load function first tries to +load a file from the current directory. A '.lsp' extension is added if there +is not already an alphanumeric extension following a period. If that fails, +XLISP searches the path, which is obtained from the XLISPPATH environment +variable in Unix and HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under +Win32. [The Macintosh version has no search path.]

    + + + +
    +
    (info) - show information about memory usage.
    +
    returns - NIL
    +
    + + + +
    +
    (bigendiap) - is this a big-endian machine ?
    +
    returns - T if this a big-endian architecture, storing the high-order +byte of an integer at the lowest byte address of the integer, otherwise +NIL.
    +
    + +

    Note: Under Windows, Nyquist normally starts up in a medium-sized +console window with black text and a white background, with a window title +of "Nyquist." This is normally accomplished by calling 'setup-console' in +'system.lsp'. In Nyquist, you can avoid this behavior by setting +*setup-console* to NIL in your 'init.lsp' file. If 'setup-console' is not +called, Nyquist uses standard input and output as is. This is what you want +if you are running Nyquist inside of emacs, for example.

    + + + +
    +
    (setup-console) - set default console attributes
    +
    returns - NIL
    +
    + +

    Note: The 'echoenabled' function is only implemented under Linux +and Mac OS X. If Nyquist I/O is redirected through pipes, the +Windows version does not echo the input, but the Linux and Mac versions do. +You can turn off echoing with this function. Under windows it is defined to +do nothing.

    + + + +
    +
    (echoenabled flag) - turn console input echoing on or off
    +
    flag - T to enable echo, NIL to disable
    +returns - NIL
    +
    + +

      Back to Top

    + + + +
    + +

    Profiling

    + +
    + +

    The Xlisp 2.0 release has been extended with a profiling facility, which +counts how many times and where +eval is executed. A separate +count is maintained for each named function, closure, or macro, and a count +indicates an eval in the +immediately [lexically] enclosing named function, closure, or macro. Thus, +the count gives an indication of the amount of time spent in a function, not +counting nested function calls.

    + +

    The list of all functions executed is maintained on the global *profile* +variable. These functions in turn have *profile* properties, which maintain +the counts. The profile system merely increments counters and puts symbols +on the *profile* list. It is up to the user to initialize data and gather +results. Profiling is turned on or off with the 'profile' function.

    + + + +
    +
    (profile flag) - turn profiling on or off
    +
    flag - NIL turns profiling off, otherwise on
    +returns - the previous state of profiling
    +
    + +

    Unfortunately, methods cannot be profiled with this facility.

    + +

    [Nyquist sources: xlsys.c, xleval.c]

    + +

      Back to Top

    + +
    + +XLISP > +XLISP 2.0  -  +Contents  -  +Reference  -  +Previous | +Next + + diff --git a/docsrc/xlisp/xlisp-doc/manual/xlisp.htm b/docsrc/xlisp/xlisp-doc/manual/xlisp.htm new file mode 100644 index 0000000..c32b7a0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/manual/xlisp.htm @@ -0,0 +1,1256 @@ + + +XLISP 2.0 + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    XLISP 2.0

    + +
    + +

    XLISP: An Object-oriented Lisp  Version +2.0, February 6, 1988, by David Michael +Betz, 127 Taylor Road, Peterborough, NH +03458

    + +

    Copyright (c) 1988, by David Michael Betz, +All Rights Reserved, Permission is granted for unrestricted +non-commercial use.

    + +
    + +
      +
    1. Introduction
    2. +
    3. A Note From The Author
    4. +
    5. Command Loop
    6. +
    7. Break Loop
    8. +
    9. Data Types
    10. +
    11. The Evaluator
    12. +
    13. Lexical Conventions
    14. +
    15. The Readtable
    16. +
    17. Lambda Lists
    18. + +
    + + + +
    + +

    1  Introduction

    + +
    + +

    XLISP is an experimental programming language combining some of the +features of Common Lisp with an object-oriented extension capability. It was +implemented to allow experimentation with object-oriented programming on +small computers. Implementations of XLISP run on virtually every operating +system. XLISP is completely written in the programming language C and is +easily extended with user written built-in functions and classes. It is +available in source form to non-commercial users. Many Common Lisp functions +are built into XLISP. In addition, XLISP defines the objects object and class as primitives. Object is the +only class that has no superclass and hence is the root of the class +hierarchy tree. Class is the class of which all classes are instances [it is +the only object that is an instance of itself].

    + +

    This document is a brief description of XLISP. It assumes some knowledge +of LISP and some understanding of the concepts of object-oriented +programming. I recommend the book 'Lisp' by Winston and Horn and published +by Addison Wesley for learning Lisp. The first edition of this book is based +on MacLisp and the second edition is based on Common Lisp. You will probably +also need a copy of 'Common Lisp, The Language' by Guy L. Steele, Jr., +published by Digital Press to use as a reference for some of the Common Lisp +functions that are described only briefly in this document.

    + +

    A list with Lisp books and documents available for free in the internet +can be found under Lisp Links.

    + +

      Back to Top

    + + + +
    + +

    2  A Note From The Author

    + +
    + +

    If you have any problems with XLISP, feel free to contact me [David Betz] +for help or advice. Please remember that since XLISP is available in source +form in a high level language, many users have been making versions +available on a variety of machines. If you call to report a problem with a +specific version, I may not be able to help you if that version runs on a +machine to which I don't have access. Please have the version number of the +version that you are running readily accessible before calling me.

    + +

    If you find a bug in XLISP, first try to fix the bug yourself using the +source code provided. If you are successful in fixing the bug, send the bug +report along with the fix to me. If you don't have access to a C compiler or +are unable to fix a bug, please send the bug report to me and I'll try to +fix it.

    + +

    Any suggestions for improvements will be welcomed. Feel free to extend +the language in whatever way suits your needs. However,

    + +

    + +

    PLEASE DO NOT RELEASE ENHANCED VERSIONS WITHOUT CHECKING WITH ME +FIRST!!

    + +

    + +

    I would like to be the clearing house for new features added to XLISP. If +you want to add features for your own personal use, go ahead. But, if you +want to distribute your enhanced version, contact me first. Please remember +that the goal of XLISP is to provide a language to learn and experiment with +LISP and object-oriented programming on small computers. I don't want it to +get so big that it requires megabytes of memory to run.

    + +

    The official XLISP homepage is:

    + + + +

      Back to top

    + + + +
    + +

    3  Command Loop

    + +
    + +

    When XLISP is started, it first tries to load the workspace 'xlisp.wks' +from the current directory. If that file doesn't exist, XLISP builds an +initial workspace, empty except for the built-in functions and symbols. Then +XLISP attempts to load 'init.lsp' from the current directory. It then loads +any files named as parameters on the command line [after appending '.lsp' to +their names].

    + +

    XLISP then issues the following prompt:

    + +
    +>
    +
    + +

    This indicates that XLISP is waiting for an expression to be typed. When +a complete expression has been entered, XLISP attempts to evaluate that +expression. If the expression evaluates successfully, XLISP prints the +result and then returns to the initial prompt waiting for another expression +to be typed.

    + + + +

    + +

    Interactive Programming

    + +

    There are several symbols maintained by the read-eval-print +loop:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      *  - the most recent result
      **  - the second recent result
      ***  - the third recent result
      +  - the most recent input expression
      ++  - the second recent input expression
      +++  - the third recent input expression
        - the expression currently being evaluated, becomes the + value of + at the end of the evaluation

    + +

    These symbols are for interactive programming. It is not +recommended to use them in program code.

    + +

    + + + +

    + +

    Special Characters

    + +

    When XLISP is running from a console [not in the Nyquist +Java IDE], some control characters invoke operations:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Control-c  - executes the top-level function
      Control-g  - executes the clean-up function
      Control-p  - executes the continue function
      Control-b  - stops execution and enters the break command loop, + execution can be continued by typing Control-p or + (continue)
      Control-e  - turns on character echoing [Linux and Mac OS X only]
      Control-f  - turns off character echoing [Linux and Mac OS X only]
      Control-t  - evaluates the info function
      Control-u  - erases the entire input line

    + +

    Backspace and Delete characters erase the previous character on the input +line [if any].

    + +

    + +

      Back to top

    + + + +
    + +

    4  Break Loop

    + +
    + +

    When XLISP encounters an error while evaluating an expression, it +attempts to handle the error in the following way:

    + +
    + +

    1. If the symbol +*breakenable* is true, the +message corresponding to the error is printed. If the error is +correctable, the correction message is printed.

    + +
    +
      + +
    • If the symbol +*tracenable* is true, a +trace back is printed. The number of entries printed depends on the value of +the symbol *tracelimit*. +If this symbol is set to something other than a number, the +entire trace back stack is printed.

    • + +
    + +

    XLISP then enters a 'read-eval-print' loop to allow the user +to examine the state of the interpreter in the context of the error. This +loop differs from the normal top-level +'read-eval-print' loop in that if the user invokes the +continue function:

    + +
    +1> (continue)
    +
    + +

    XLISP will continue from a correctable error. If the user +invokes the clean-up function:

    + +
    +1> (clean-up)
    +
    + +

    XLISP will abort the break loop and return to the top level or the next +lower numbered break loop. When in a break loop, XLISP prefixes the break +level to the normal prompt with a number.

    + +

    2. If the symbol +*breakenable* +is NIL, XLISP looks for a surrounding +errset function:

    + +
    + +
      + +
    • If an error happened within the scope of an +errset function, XLISP examines the +value of the errset print flag. +If this flag is true, the error message is printed. +In case of an error, the +errset function always returns +NIL.

    • + +
    • If there is no surrounding +errset function, XLISP prints the +error message and returns to the top level.

    • + +
    + +

      Back to top

    + + + +
    + +

    5  Data Types

    + +
    + +

    There are several different data types available to XLISP +programmers:

    + + + +

    See also the type-of +function.

    + +

      Back to top

    + + + +
    + +

    6  The Evaluator

    + +
    + +

    The process of evaluation in XLISP:

    + +
      + +
    • The following Lisp objects evaluate to themselves:

      + + +
    • + +
    • Symbols act as variables and are +evaluated by retrieving the value associated with their current +binding.

    • + +
    • Lists are evaluated by examining +the first element of the list and then taking one of the following +actions:

    • + +
        + +
      • If it is a symbol, the functional +binding of the symbol is retrieved.

      • + +
      • If it is a lambda expression, a +closure is constructed for the function described by the lambda +expression.

      • + +
      • If it is a subr [built-in +function], fsubr [special form] or closure [user defined function], it stands for +itself.

      • + +
      • Any other value is an error.

      • + +
      + +

      Then, the value produced by the previous step is examined:

      + +
        + +
      • If it is a subr +[built-in function] or closure [user defined function], the remaining +list elements are evaluated and the subr or closure is called with these +evaluated expressions as arguments.

      • + +
      • If it is an fsubr [special form], +the fsubr is called using the remaining list elements as arguments +[unevaluated].

      • + +
      • If it is a macro, the macro is +expanded using the remaining list elements as arguments [unevaluated]. The +macro expansion is then evaluated in place of the original macro +call.

      • + +
      + +
    + +

      Back to top

    + + + +
    + +

    7  Lexical Conventions

    + +
    + +

    The following conventions must be followed when entering XLISP +programs:

    + +
      + +
    • Comments in XLISP code begin with a semicolon character and continue +to the end of the line.

    • + +
    • Symbol names in XLISP can consist of any sequence of non-blank +printable characters except the following:

    • + +

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        (  - opening parenthesis
        )  - closing parenthesis
        '  - single-quote
        `  - backquote
        ,  - comma
        "  - double-quote
        ;  - semicolon

      + +
    • Uppercase and lowercase characters are not distinguished within +symbol names. All lowercase characters are mapped to uppercase on +input.

    • + +
    • Integer literals consist of a sequence of digits optionally beginning +with a '+' [plus] or '-' [minus]. The range of values an integer can +represent is limited by the size of a C 'long' value on the machine on which +XLISP is running. Also be aware that Nyquist doesn't check for +CPU register overflow with integer numbers, so for example if you add 1 to +the biggest Nyquist integer number, the result will be a negative +number.

    • + +
    • Floating point literals consist of a sequence of digits optionally +beginning with a '+' [plus] or '-' [minus] and including an embedded decimal +point. The range of values a floating point number can represent is limited +by the size of a C 'float' [or 'double' on machines with 32 bit addresses] +on the machine on which XLISP is running.

    • + +
    • Literal strings are sequences of characters surrounded by double +quotes. Within quoted strings the '\' [backslash] character is used to allow +non-printable characters to be included. The codes recognized are:

    • + +

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        \\  - the character '\' [backslash]
        \n  - newline
        \t  - tab
        \r  - return
        \f  - form feed
        \nnn  - the character whose octal code is 'nnn'

      + +

      An ASCII table +is provided with this version of the XLISP manual with all octal, decimal +and hexadecimal character values.

      + +
    + +

      Back to top

    + + + +
    + +

    8  The Readtable

    + +
    + + + + + +

    The behavior of the reader is controlled by a data structure called a +'readtable'. The reader uses the symbol +*readtable* to locate the +current readtable. This table controls the interpretation of input +characters. It is an array with 128 entries, one for each of the +ASCII character codes. Each +entry contains one of the following things:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       NIL  -  indicating an invalid character   [see + nil]
      :CONSTITUENT  -  indicating a symbol constituent   [see + :constituent]
      :WHITE-SPACE  -  indicating a whitespace character   [see + :white-space]
      (:TMACRO . function)  -  terminating readmacro   [see + :tmacro]
      (:NMACRO . function)  -  non-terminating readmacro   [see + :nmacro]
      :SESCAPE  -  single escape character '\'   [see + :sescape]
      :MESCAPE  -  multiple escape character '|'   [see + :mescape]

    + +

    In the case of :tmacro and +:nmacro, the 'fun' component +is a function. This can either be a built-in readmacro function or a +lambda expression. The +function should take two parameters. The first is the input stream and the +second is the character that caused the invocation of the readmacro. The +readmacro function should return +NIL to indicate that the +character should be treated as white space or a value +consed with +NIL to indicate that the +readmacro should be treated as an occurence of the specified value. Of +course, the readmacro code is free to +read additional characters +from the input stream.

    + + + + + + +

    XLISP defines several useful read macros:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      'expression  =  (quote + expr)
      #'expression  =  (function + expr)
      #(expression...)  =  an array of the specified expressions
      #xdigits  =  a hexadecimal number [0-9,A-F]
      #odigits  =  an octal number [0-7]
      #bdigits  =  a binary number [0-1]
      #\character  =  a single character
      #| ... |#  =  a comment
      #:symbol  =  an uninterned symbol
      `expression  =  (backquote + expr)
      ,expression  =  (comma + expr)
      ,@expression  =  (comma-at + expr)

    + + + +

    Characters names handled by the reader:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #\Tab  =  horiz. tab   [ASCII decimal value 9]
      #\Newline  =  newline   [ASCII decimal value 10]
      #\Space  =  space   [ASCII decimal value 32]

    + +

      Back to top

    + + + +
    + +

    9  Lambda Lists

    + + + +
    + +

    9.1  Arguments

    + +
    + +

    There are several forms in XLISP that require that a 'lambda +list' be specified. A lambda list is a definition of the arguments +accepted by a function.

    + +

      Back to top

    + + + +
    + +

    9.1.1  Required Arguments

    + +
    + +

    The lambda list starts with 'required' arguments. Required arguments must +be specified in every call to the function.

    + +

    The function 'print-x' has exactly one required +argument 'x':

    + +
    +(defun print-x (x)
    +  (print x))
    +
    +(print-x 1)    => 1
    +(print-x)      => error: too few arguments
    +(print-x 1 2)  => error: too many arguments
    +
    + +

      Back to top

    + + + +
    + +

    9.1.2  Optional Arguments

    + +
    + +

    The Required Arguments are followed by +the &optional +arguments. Optional arguments may be provided or omitted in a call. An +initialization expression may be specified to provide a default value for an +&optional +argument if it is omitted from a call. If no initialization expression is +specified, an omitted argument is initialized to +NIL.

    + +

    It is also possible to provide the name of a 'supplied-p' variable that +can be used to determine if a call provided a value for the argument or if +the initialization expression was used. If specified, the 'supplied-p' +variable will be bound to + T  if a value was +specified in the call and +NIL if the default value was +used.

    + +

      Back to top

    + + + +
    + +

    9.1.3  Rest Argument

    + +
    + +

    The Optional Arguments are followed by +the &rest argument. +The &rest +argument gets bound to the remainder of the argument list after the required +and &optional +arguments have been removed.

    + +

    + +

    Known Problems with the Rest Argument

    + +

    A subtle problem arises if +Optional Arguments are used together with +a &rest argument:

    + +
    +(defun test (&optional opt &rest rest)
    +  (format t "opt = ~a, rest = ~a~%" opt rest))
    +
    +(test 1)      => opt = 1, rest = NIL
    +(test 1 2)    => opt = 1, rest = (2)
    +(test 1 2 3)  => opt = 1, rest = (2 3)
    +
    + +

    Now the +&optional +argument is not optional anymore, there is no way to make the first argument +appear in the &rest +list and not in the +&optional +variable. This is not a XLISP bug, this is a general Lisp phenomenon. +In Lisp it's not a good idea to use +Optional Arguments together with a +&rest argument.

    + +

    If a &rest +argument is used togethter with +Keyword Arguments, then the keywords and +their arguments appear in the list bound to the +&rest +argument. This is not neccessarily a XLISP bug, this also happens with +other Lisps. In Lisp it's also not a good idea to use +Keyword Arguments together with a +&rest argument.

    + +

    XLISP Bug: If the number of elements in a +&rest list +is odd, then &key +variables have wrong values:

    + +
    +(defun test (&rest rest &key (key t))
    +  (format t "rest = ~a, key = ~a~%" rest key))
    +
    +(test 1     :key 'a)  => rest = (1 :KEY A),     key = T  ; wrong KEY value
    +(test 1 2   :key 'a)  => rest = (1 2 :KEY A),   key = A  ; quirk, but correct KEY value
    +(test 1 2 3 :key 'a)) => rest = (1 2 3 :KEY A), key = T  ; again wrong KEY value
    +
    + +

    + +

      Back to top

    + + + +
    + +

    9.1.4  Keyword Arguments

    + +
    + +

    The Rest Argument is +followed by the &key +arguments. When a keyword argument is passed to a function, a pair of values +appears in the argument list. The first expression in the pair should +evaluate to a keyword symbol [a symbol that begins with a colon +':']. The value of the second expression is the value of the keyword +argument.

    + +

    Like &optional +arguments, &key arguments can +have initialization expressions and 'supplied-p' variables. In addition, it +is possible to specify the keyword to be used in a function call. If no +keyword is specified, the keyword obtained by adding a colon ':' to the +beginning of the keyword argument symbol is used.

    + +

    In other words, if the keyword argument symbol is:

    + +
    +foo
    +
    + +

    the keyword will be:

    + +
    +:foo
    +
    + +

      Back to top

    + + + +
    + +

    9.1.5  Auxiliary Variables

    + +
    + +

    The Keyword Arguments are followed by +the &aux variables. +These are local variables that are bound during the evaluation of the +function body. It is possible to have initialization expressions for the +&aux variables.

    + +

      Back to Top

    + + + +
    + +

    9.2  Lambda List Syntax

    + +
    + +

    Here is the complete syntax for lambda lists:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
      (required-arg ...
        [&optional [optional-arg | (optional-arg [init-form [supplied-var]])] ... ]
        [&rest rest-arg]
        [&key [key-arg | ([key-arg | (keyword key-arg)] [init-form [supplied-var]]) ...] &allow-other-keys]
        [&aux [aux-var | (aux-var [init-form])] ... ])

    + +

    where:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      required-arg — is a required argument symbol
      optional-arg — is an &optional argument symbol
      rest-arg — is the &rest argument symbol
      key-arg — is a &key argument symbol
      keyword — is a keyword symbol
      aux-var — is an auxiliary variable symbol
      init-form — is an initialization expression
      supplied-var — is a supplied-p variable symbol

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/misc/ascii-table.htm b/docsrc/xlisp/xlisp-doc/misc/ascii-table.htm new file mode 100644 index 0000000..a313dd5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/misc/ascii-table.htm @@ -0,0 +1,1403 @@ +ASCII Character Set + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    The ASCII Character Set

    + +
    + +

    The standard ASCII character set uses only 7 bits of the 8 bit byte for +each character. There are several larger character sets that use all 8 bits +of the byte, which gives them an 128 additional characters in the set. The +extra characters are used to represent characters not used in the English +language, graphics characters or symbols, and mathematical representations +or symbols.

    + +

    ASCII Control Characters

    + +

    ASCII control characters are actually commands for the terminal, monitor, +computer, I/O devices, printer or other peripherals to do something. The +first 32 values are non-printing control characters, such as 'carriage +return' and 'line feed'. You generate these characters on the keyboard by +holding down the 'control' key while you strike another key. These +characters are also capable of being sent to the device by a software +sequence, most often by a program. They are usually sent as a string of +characters following an attention character, usually 'escape', but not +always.

    + +

    ASCII Control Characters

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CharOctDecHexCtrl-keyXLISP
    NUL000Ctrl+@  - null character
    SOH111Ctrl+a  - start of heading
    STX222Ctrl+b  - start of text
    ETX333Ctrl+c  - end of text
    EOT444Ctrl+d  - end of transmission
    ENQ555Ctrl+e  - enquiry
    ACK666Ctrl+f  - acknowledge
    BEL777Ctrl+g  - rings terminal bell
    CharOctDecHexCtrl-keyXLISP
    BS1088Ctrl+h  - backspace (non-destructive)
    HT1199Ctrl+i#\Tab  - horizontal tab
    LF1210ACtrl+j#\Newline  - line feed
    VT1311BCtrl+k  - vertical tab
    FF1412CCtrl+l  - form feed
    CR1513DCtrl+m  - carriage return
    SO1614ECtrl+n  - shift out
    SI1715FCtrl+o  - shift in
    CharOctDecHexCtrl-keyXLISP
    DLE201610Ctrl+p  - data link escape
    DC1211711Ctrl+q  - device control 1, normally 'xon'
    DC2221812Ctrl+r  - device control 2
    DC3231913Ctrl+s  - device control 3, normally 'xoff'
    DC4242014Ctrl+t  - device control 4
    NAK252115Ctrl+u  - negative acknowledge
    SYN262216Ctrl+v  - synchronous idle
    ETB272317Ctrl+w  - end transmission block
    CharOctDecHexCtrl-keyXLISP
    CAN302417Ctrl+x  - cancel line
    EM312519Ctrl+y  - end of medium
    SUB32261ACtrl+z  - substitute
    ESC33271BCtrl+[  - escape
    FS34281CCtrl+\  - file separator
    GS35291DCtrl+]  - group separator
    RS36301ECtrl+^  - record separator
    US37311FCtrl+_  - unit separator
    CharOctDecHexCtrl-keyXLISP

    + +

    ASCII Printing Characters

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CharOctDecHexXLISP
     403220#\Space  - space
    !413321#\!  - exclamation mark
    "423422#\"  - quotation mark
    #433523#\#  - cross hatch, number sign
    $443624#\$  - dollar sign
    %453725#\%  - percent sign
    &463826#\&  - ampersand
    `473927#\`  - backquote, apostrophe
    CharOctDecHexXLISP
    (504028#\(  - opening parentheses
    )514129#\)  - closing parentheses
    *52422A#\*  - asterisk, star, multiply
    +53432B#\+  - plus
    ,54442C#\,  - comma
    -55452D#\-  - hyphen, dash, minus
    .56462E#\.  - period
    /57472F#\/  - slash forward, divide
    CharOctDecHexXLISP
    0604830#\0  - zero
    1614931#\1  - one
    2625032#\2  - two
    3635133#\3  - three
    4645234#\4  - four
    5655335#\5  - five
    6665436#\6  - six
    7675537#\7  - seven
    CharOctDecHexXLISP
    8705638#\8  - eight
    9715739#\9  - nine
    :72583A#\:  - colon
    ;73593B#\;  - semicolon
    <74603C#\<  - less than sign
    =75613D#\=  - equals sign
    >76623E#\>  - greater than sign
    ?77633F#\?  - question mark
    CharOctDecHexXLISP
    @1006440#\@  - at-sign
    A1016541#\A  - upper case A
    B1026642#\B  - upper case B
    C1036743#\C  - upper case C
    D1046844#\D  - upper case D
    E1056945#\E  - upper case E
    F1067046#\F  - upper case F
    G1077147#\G  - upper case G
    CharOctDecHexXLISP
    H1107248#\H  - upper case H
    I1117349#\I  - upper case I
    J112744A#\J  - upper case J
    K113754B#\K  - upper case K
    L114764C#\L  - upper case L
    M115774D#\M  - upper case M
    N116784E#\N  - upper case N
    O117794F#\O  - upper case O
    CharOctDecHexXLISP
    P1208050#\P  - upper case P
    Q1218151#\Q  - upper case Q
    R1228252#\R  - upper case R
    S1238353#\S  - upper case S
    T1248454#\T  - upper case T
    U1258555#\U  - upper case U
    V1268656#\V  - upper case V
    W1278757#\W  - upper case W
    CharOctDecHexXLISP
    X1308858#\X  - upper case X
    Y1318959#\Y  - upper case Y
    Z132905A#\Z  - upper case Z
    [133915B#\[  - opening square bracket
    \134925C#\\  - backslash, reverse slant
    ]135935D#\]  - closing square bracket
    ^136945E#\^  - caret, circumflex
    _137955F#\_  - underscore
    CharOctDecHexXLISP
    `1409660#\`  - opening single quote
    a1419761#\a  - lower case a
    b1429862#\b  - lower case b
    c1439963#\c  - lower case c
    d14410064#\d  - lower case d
    e14510165#\e  - lower case e
    f14610266#\f  - lower case f
    g14710367#\g  - lower case g
    CharOctDecHexXLISP
    h15010468#\h  - lower case h
    i15110569#\i  - lower case i
    j1521066A#\j  - lower case j
    k1531076B#\k  - lower case k
    l1541086C#\l  - lower case l
    m1551096D#\m  - lower case m
    n1561106E#\n  - lower case n
    o1571116F#\o  - lower case o
    CharOctDecHexXLISP
    p16011270#\p  - lower case p
    q16111371#\q  - lower case q
    r16211472#\r  - lower case r
    s16311573#\s  - lower case s
    t16411674#\t  - lower case t
    u16511775#\u  - lower case u
    v16611876#\v  - lower case v
    w16711977#\w  - lower case w
    CharOctDecHexXLISP
    x17012078#\x  - lower case x
    y17112179#\y  - lower case y
    z1721227A#\z  - lower case z
    {1731237B#\{  - opening curly brace
    |1741247C#\|  - vertical line
    }1751257D#\}  - closing curly brace
    ~1761267E#\~  - tilde, approximate
    DEL1771277F  - delete, cross-hatch box
    CharOctDecHexXLISP

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/misc/c-printf.htm b/docsrc/xlisp/xlisp-doc/misc/c-printf.htm new file mode 100644 index 0000000..f87d62a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/misc/c-printf.htm @@ -0,0 +1,560 @@ + + +ANSI C 'printf' Format + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    ANSI C 'printf' Format

    + +
    + +

    Nyquist/XLISP: The +*float-format* and +*integer-format* +variables define format strings for the underlying 'sprintf' C +function. In C, the same format string specification is +used for 'fprint' [writes to a file], 'printf' [writes to +standard output] and 'sprintf' [writes to another string]. These three +functions are meant in the following text with 'the printf functions'.

    + +

    ANSI C: The printf functions write output under control of a +format string that specifies how subsequent arguments are converted for +output. If there are insufficient arguments for the format, the behavior is +undefined. If the format is exhausted while arguments remain, the excess +arguments are evaluated but are otherwise ignored. The printf functions +return when the end of the format string is encountered.

    + +

      Back to top

    + + + +
    + +

    Format String

    + +
    + +

    The format string is composed of zero or more directives, which are +ordinary characters [except "%"], which are copied +unchanged to the output stream, and conversion specifications, each of which +results in fetching zero or more subsequent arguments. Each conversion +specification is introduced by the character "%":

    + +
    +%[flags][field-with][precision][data-type]conversion-type
    +
    + +

    After the "%", the following appear in sequence:

    + +
      + +
    • Flags - Zero or more flags that modify +the meaning of the conversion specification.

    • + +
    • Field Width - An optional decimal integer +specifying a minimum field width. If the converted value has +fewer characters than the field width, it will be padded with spaces on the +left to the field width. The field is padded on the right if +the  −  flag has been +given, or padded with zeros if the + 0  flag had been +given. A negative integer, given as 'field width' +argument, is interpreted as a + −  flag followed by +a positive field width.

    • + +
    • Precision - An optional decimal integer that +gives the minimum number of digits to appear for +integer conversions, the number of digits to appear +after the +decimal-point character for floating-point + e  and + f  conversions, or the +maximum number of significant digits for the floating-point + g  conversion.

      + +

      The precision takes the form of a period character followed by an +optional decimal integer:

      + +
      +.[integer]
      +
      + +

      If the integer is omitted, it is treated as zero, a +negative precision argument is taken as if it were missing.

      + +

      Note: In C, the precision also specifies the +maximum number of characters to be written from a string in 's' +conversion, but "%s" should not be used in the XLISP +*float-format* or +*integer-format* +variables, otherwise XLISP will crash.

    • + + + +
    • Data Type - An optional character specifying a +data type to be used for the +conversion.

      + +

      XLISP: Nyquist/XLISP uses C 'long' signed integers +and C 'double' floats only, so with floating-point +numbers no special data type needs to +be given, while integer conversions should always be +prefixed by a 'l' [lowercase L], otherwise the printed +representation of integer numbers may be differently than the behaviour of +the Nyquist/XLISP functions.

    • + +
    • Conversion Type - A character that specifies the +conversion type to be +applied.

    • + +
    + +

    Not with Nyquist/XLISP: In C, a 'field +width' or 'precision', or both, may be indicated by an asterisk * +instead of a digit string. In this case, an int argument supplies the field +width or precision. The arguments specifying field width or precision, or +both, shall appear [in that order] before the argument [if any] to be +converted.

    + +

      Back to top

    + + + +
    + +

    Flags

    + +
    + +

    The flag characters and their meanings are:

    + +

    + +
    + + + +

    −  [minus sign character]

    + +

    The result of the conversion will be left-justified +within the field.

    + + + +

    +  [plus sign character]

    + +

    The result of a signed conversion will always begin with a plus or +minus sign.

    + + + +

    space  [space character]

    + +

    If the first character of a signed conversion is not a sign, or if a +signed conversion results in no characters, a space will be prepended to the +result. If the 'space' and + +  flags both appear, the +'space' flag will be ignored.

    + + + +

    #  [hash character]

    + +

    The result is to be converted to an 'alternate form':

    + +

    Octal Numbers - For o conversion, it increases the precision to force the +first digit of the result to be a zero.

    + +

    Hexadecimal Numbers - For x or X conversion, a nonzero result will have +0x or 0X prepended to it.

    + +

    Floating-point Numbers - For e, E, f, g, and G conversions, the result +will always contain a decimal-point character, even if no digits follow it +(normally, a decimal-point character appears in the result of these +conversions only if a digit follows it). For g and G conversions, trailing +zeros will not be removed from the result. For other conversions, the +behavior is undefined.

    + +
    + + + +

    0  [number zero character]

    + +

    For integer d, i, o, u, x, X, and floating-point e, E, f, g, G +conversions, leading zeros [following any indication of sign or base] are +used to pad to the field width. +No space padding is performed. +If the '0' and + −  flags both +appear, the '0' flag will be ignored. For integer d, i, o, u, +x, X conversions, if a precision is specified, +the '0' flag will be ignored. For other +conversions, the behavior is undefined.

    + +
    + +

    + +

      Back to top

    + + + +
    + +

    Data Type

    + +
    + +

    + +
    + +

    h  [lowercase H character]

    + +

    A following d, i, o, u, x, or X conversion specifier applies to a +short int or unsigned short int argument [the argument will have been +promoted according to the integral promotions, and its value shall be +converted to short int or unsigned short int before printing].

    + +

    A following n conversion specifier applies to a pointer to a short int +argument.

    + +

    l  [lowercase L character]

    + +

    A following d, i, o, u, x, or X conversion specifier applies to a +long int or unsigned long int argument.

    + +

    A following n conversion specifier applies to a pointer to a long int +argument.

    + +

    L  [uppercase L character]

    + +

    A following e, E, f, g, or G conversion specifier applies to a long +double argument.

    + +
    + +

    + +

    If an h, l, or L appears with any other conversion specifier, the +behavior is undefined.

    + +

      Back to top

    + + + +
    + +

    Conversion Type

    + +
    + +

    Integer conversion:

    + +

    + +
    + + + +

    d, i, o, u, x, +X

    + +

    The integer argument is converted to: + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      d → signed decimal
      i → signed decimal
      o → unsigned octal
      u → unsigned decimal
      x → unsigned hexadecimal, using 'abcdef'
      X → unsigned hexadecimal, using 'ABCDEF'

    + +

    The precision specifies the minimum number +of digits to appear. If the value being converted can be +represented in fewer digits, it will be expanded with leading zeros. The +default precision is 1. The result of converting a zero value +with an explicit precision of zero results in no characters.

    + +XLISP: Nyquist/XLISP uses C 'long' signed integers, so +the integer conversions should always be prefixed by a 'l' [lowercase +L] indicating a 'long int' C +data type, otherwise the printed +representation of integer numbers may be differently than the behaviour of +the Nyquist/XLISP functions.

    + +
    + +

    + +

    Floating-point conversion:

    + +

    + +
    + + + +

    f

    + +

    The floating-point argument of C data type +'double' is converted to decimal notation in the style:

    + +
    +[-]ddd.ddd
    +
    + +

    The number of digits after the decimal-point character +is equal to the precision specification. +If the precision is missing, it is +taken as 6. If the +precision is explicitly zero, no +decimal-point character appears. If a +decimal-point character appears, at least one digit appears +before it. The value is rounded to the appropriate +number of digits.

    + + + +

    e, E

    + +

    The floating-point argument of C data type +'double' is converted in the style:

    + +
    +[-]d.ddde+-dd
    +
    + +

    There is one digit before the decimal-point character +[which is nonzero if the argument is nonzero] and the number of digits after +it is equal to the precision. If +the precision is missing, it is taken +as 6. If the +precision is zero, no +decimal-point character appears. The value is +rounded to the appropriate number of digits. The exponent +always contains at least two digits. If the value is zero, the +exponent is zero. The "E" conversion specifier will +produce a number with 'E' instead of 'e' introducing the exponent.

    + + + +

    g, G

    + +

    The floating-point argument of C data type +'double' is converted in style  f  or + e , or in style + E  in the case of a "G" +conversion specifier, with the precision +specifying the number of significant digits. If an explicit +precision is zero, it is taken as +1. The style used depends on the value converted. +Style  e  will be used only if +the exponent resulting from such a conversion is less than -4 +or greater than or equal to the precision. +Trailing zeros are removed from the fractional portion of the result. +A decimal-point character appears only if it is followed by +a digit.

    + +
    + +

    + +

    If a conversion specification is invalid, the behavior is undefined. +In no case does a nonexistent or small +field width cause truncation of a +field. If the result of a conversion is wider than the +field width, the field is expanded +to contain the conversion result.

    + +

    The minimum value for the maximum number of characters produced by +any single conversion shall be 509.

    + +

      Back to top

    + + + +
    + +

    Other Conversion Types

    + +
    + +

    This section contains a list of all other conversion types defined +in ANSI C.

    + +

    Warning: Do not use thse conversions with the XLISP +*float-format* and +*integer-format* +variables, because XLISP will produce nonsense or just simply will crash. +The XLISP behaviour described below was tested with +Nyquist 3.03 in December 2010, compiled with +GCC 4.3.2 and glibc 2.7 on Debian 5 +[Lenny]. The behaviour may be different with different +Nyquist or XLISP versions, different C compilers and/or +libraries, or different operating systems.

    + +

    + +
    + +

    c

    + +

    ANSI C: The integer argument is converted to an +'unsigned char', and the resulting character is written.

    + +

    XLISP: If the +*float-format* or +*integer-format* +is set to "%c", then the lowest 8 bit +of the internal binary representation of the respective numbers will be +printed as an ASCII character.

    + +

    s

    + +

    ANSI C: The argument shall be a pointer to an array of +character type. Characters from the array are written up to [but not +including] a terminating null character. If the +precision is specified, no more than that many +characters are written. If the +precision is not specified or is greater than +the size of the array, the array shall contain a null character.

    + +XLISP: If the +*float-format* or +*integer-format* +is set to "%s" and XLISP tries to print a respective number, +XLISP crashes.
    + +

    p

    + +

    ANSI C: The argument shall be a pointer to 'void'. The value +of the pointer is converted to a sequence of printable characters, in an +implementation-defined manner.

    + +

    XLISP: If the +*float-format* +is set to "%p", then floating-point numbers are +printed as "(nil)". If the +*integer-format* +is set to "%p", the integer numbers are printed as +hexadecimal numbers, prefixed with "0x".

    + +

    n

    + +

    ANSI C: The argument shall be a pointer to an integer into +which is written the number of characters written to the output stream so +far by this call to the C 'fprintf' function. No +argument is converted.

    + +XLISP: If the +*float-format* or +*integer-format* +is set to "%n" and XLISP tries to print a respective number, +XLISP crashes.
    + +

    %

    + +

    ANSI C: A "%" is written. No +argument is converted. The complete conversion +specification shall be "%%".

    + +XLISP: If the +*float-format* +is set to "%g%%" or the +*integer-format* +is set to "%ld%%" then all respective numbers will be printed +with a trailing "%".
    + +
    + +

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/misc/links.htm b/docsrc/xlisp/xlisp-doc/misc/links.htm new file mode 100644 index 0000000..d0e47d7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/misc/links.htm @@ -0,0 +1,115 @@ + +Lisp Links + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Lisp Links

    + +
    + +

    The most helpful book to learn XLISP I found 'Common Lisp, A Gentle +Introduction to Symbolic Computation' by David Touretzky, mentioned in the +Nyquist manual by Roger Dannenberg. The book can be downloaded for free +from:

    + + + +

    It's a book about Lisp in general, not only about Common Lisp, explaining +and helping a lot to understand the the fundamental principles of Lisp +programming.

    + +

    Unfortunately there seems to be no specific information source about +XLISP programming in the internet [beside the David Betz manual and the Tim +I Mikkelsen documents], probably because most Lisp dialects have been merged +into the Common Lisp standard in the 1980s and 1990s.

    + +

    As a result of this I first had to learn Common Lisp to be able to +re-construct how the examples in all the books could work with XLISP. This +was a quite tedious way to learn and the main reason to start this document +collection.

    + +
    + +

    XLISP links

    + +
    + +

    The official XLISP homepage is:

    + + + +

    The official Nyquist homepage is:

    + + + +
    + +

    Common Lisp links

    + +
    + +

    Copies of 'Common Lisp, the Language, 2nd Edition' by Guy +Steele [known as 'CltL2'] can be downloaded in various formats for free +from the CMU archives:

    + + + +

    It is a quite huge book explaining all details and discussions about the +Common Lisp standard and is a real good Common Lisp information source. +Unfortunately it is not very useful for learning XLISP out of it.

    + +

    The most recent document about the Common Lisp standard is the 'Common +Lisp Hypespec' [re-worked in 2005]. It is available for online reading +under:

    + + + +

    or as a 'tar.gz' package for offline reading from:

    + + + +

    If you have no idea how to deal with 'tar.gz' packages on Windows +computers and the 'tar.gz' file doesn't open automatically by clicking on +it, the probably most easiest way is using the '7-zip' program available for +free from:

    + + + +
    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/misc/preface.htm b/docsrc/xlisp/xlisp-doc/misc/preface.htm new file mode 100644 index 0000000..eb3293f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/misc/preface.htm @@ -0,0 +1,116 @@ + +XLISP Preface + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Preface

    + +
    + + +

    This is a collection of documents about 'XLISP 2.0' as a +programming language in general. It is intended to be used together with +Nyquist, a language for composition and sound synthesis. It includes the +second re-work of the Tim I Mikkelsen 'XLISP Language Reference', linked +against the original 'XLISP 2.0 Manual' by David Betz.

    + +

    Both manuals are linked against each other and intended to be used as +'one' manual. You can jump back and forth from a function description in the +'XLISP Manual' to the description in the 'Language Reference' and vice versa +with ease.

    + +

    The navigation bar at the top and the bottom of each page need some +explanation. From the left to right you will find the following links:

    + +
      + +
    • XLISP - always returns to the main +page from everywhere, helping you to find your way back if you get lost in +the information jungle.

    • + +
    • XLISP 2.0 - opens the +front page of the 'XLISP 2.0 Manual' by David Betz with links +to all chapters so you can read it like a book.

    • + +
    • Contents - opens +the detailed contents page of the 'XLISP 2.0 Manual' with +links to all functions and symbols sorted by topic.

    • + +
    • Reference - opens the +index page of the 'XLISP Language Reference' with links to all XLISP +functions and symbols sorted in alphabetical order.

    • + +
    • The Previous and Next links are a bit tricky. As expected they +move to the previous and next pages, but in the 'XLISP 2.0 +Manual' they move through the manual while in the 'XLISP Language Reference' +they move through the reference. This needs some accustomisation but I have +worked like this during the last few month and found it the best possible +solution. You can always go back to the pages where you have been before by +using the 'back' button of your browser.

    • + +
    + +

    During the second re-work of the 'XLISP Language Reference' I have sorted +out all functions that were related to 'XLISP 2.1' and +'XLISP Plus'. They can now be found on their own page under +XLISP Plus Functions.

    + +

    I also have sorted out of the 'XLISP 2.0 Manual' all functions added by +Nyquist to the XLISP interpreter to an extra page, for just the simple +reason that unlike XLISP 2.0, Nyquist still evolves and it is +easier to maintain a single page with Nyquist Functions than +sixteen [or more] functions spread all over the manual.

    + +
    + +

    Things still to be done and how you can help:

    + +
    + +

    First of all, please note that this is a work in progress and not a final +version. There probably still are bugs and quirks that need to be resolved +and you can help by writing an e-mail to +edgar-rft@web.de if you find some and +I will try to fix it as soon as possible.

    + +

    This does not mean that these documents are 'overloaded with +bugs' but XLISP was [and is] an experimental language that +itself was re-worked several times and most of the time during the last +months I was busy with sorting out what really matters out of the manuals I +had collected over a period of two and a half years about several XLISP +versions and mutations.

    + +

    In case of doubt I will prefer the Nyquist version of XLISP +2.0 because this is the version I work with most often and the +original intention of this document collection was to support the Nyquist +manual with better XLISP information.

    + +

    Also please note that I do not want to change the David Betz manual more +than necessary, because I consider it as the most original information +source. Instead I whould like to improve the 'XLISP Language Reference' by better +explanations and source code examples. I also have not tested really *all* +examples with Nyquist yet. If you find bugs please write me an email.

    + +

    If you have any further ideas or suggestions how these documents can be +improved please write to +edgar-rft@web.de.

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/objects/advanced-objects.htm b/docsrc/xlisp/xlisp-doc/objects/advanced-objects.htm new file mode 100644 index 0000000..925d0a8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/objects/advanced-objects.htm @@ -0,0 +1,590 @@ + + +Advanced XLISP Objects + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Advanced XLISP Objects

    + +
    + +
      +
    1. Standard XLISP Objects
    2. +
    3. Initializing Class Variables
    4. +
    5. Accessing Class and Instance Variables
    6. +
    + + + +
    + +

    Standard XLISP Objects

    + +
    + +

    Define a class with an instance variable and a class variable:

    + +
    +(setq my-class (send class :new '(instance-var) '(class-var)))
    +
    + +

    Look at the layout of the new class:

    + +
    +> (send my-class :show)
    +Object is #<Object...>, Class is #<Object...>
    +  MESSAGES = NIL
    +  IVARS = (INSTANCE-VAR)
    +  CVARS = (CLASS-VAR)
    +  CVALS = #(NIL) ; default init-value of class variables
    +  SUPERCLASS = #<Object...>
    +  IVARCNT = 1
    +  IVARTOTAL = 1
    +#<Object...>
    +
    + +

    Make an instance of 'my-class':

    + +
    +(setq my-object (send my-class :new))
    +
    + +

    Look at the layout of the new object:

    + +
    +> (send my-object :show)
    +Object is #<Object...>, Class is #<Object...>
    +  INSTANCE-VAR = NIL ; default init-value of instance variables
    +#<Object...>
    +
    + +

      Back to top

    + + + +
    + +

    Initializing Class Variables

    + +
    + +

    1. Add an :isnew init-method to 'my-class':

    + +
    +(send my-class :answer :isnew nil '((setq class-var 1)))
    +
    + +

    Now reset the class:

    + +
    +(send my-class :isnew)  => error: too few arguments
    +
    + +

    It turns out that :isnew needs at least a list of instance variables plus +an optional list of class variables:

    + +
    +(send my-class :isnew '(ivar))           ; overwrites INSTANCE-VAR, deletes CLASS-VAR
    +(send my-class :isnew '(ivar) '(cvar)))  ; overwrites INSTANCE-VAR and CLASS-VAR
    +
    + +

    2. Add an :init method to 'my-class':

    + +
    +(send my-class :answer :init nil '((setq class-var 1)))
    +
    + +

    Now call the :init method:

    + +
    +(send my-class :init)  => error: no method for this message - :INIT
    +
    + +

    This is not true, there is an :init method:

    + +
    +> (send my-class :show)
    +Object is #<Object...>, Class is #<Object...>
    +  MESSAGES = ((:INIT . #<Closure-:INIT:...>))
    +  IVARS = (INSTANCE-VAR)
    +  CVARS = (CLASS-VAR)
    +  CVALS = #(NIL)
    +  SUPERCLASS = #<Object...>
    +  IVARCNT = 1
    +  IVARTOTAL = 1
    +#<Object...>
    +
    + +

    The problem here is that in XLISP, methods cannot be called from the +class they were defined in, methods only can be called from instances, and +exactly the same happens with manipulating class variables. There seems to +be no standard XLISP way to initialize class variables with values at the +time when the class is defined.

    + +

    3. The only way I know in XLISP to initialize a class variable is +to create an instance of the class and set the class variable e.g. from the +:isnew method of the instance:

    + +
    +(setq my-object (send my-class :new))
    +
    + +

    The :isnew method of 'my-object', inherited from +'my-class', has set the class variable in +'my-class' to a new value:

    + +
    +> (send my-class :show)
    +Object is #<Object...>, Class is #<Object...>
    +  MESSAGES = ((:ISNEW . #<Closure-:ISNEW:...>))
    +  IVARS = (INSTANCE-VAR)
    +  CVARS = (CLASS-VAR)
    +  CVALS = #(1) ; new value of CLASS-VAR
    +  SUPERCLASS = #<Object...>
    +  IVARCNT = 1
    +  IVARTOTAL = 1
    +#<Object...>
    +
    + +

    This works, but now I have two problems:

    + +
      + +
    1. If a class variable is set from an instance's :isnew method, +inherited from the superclass, then, whenever an instance is created, the +class variable will be reset to its initial value. Note that in +Lisp, instances can be created at arbitrary run-time, not only +at the beginning of a program. Setting class variables from an :isnew method +can produce unexpected side-effects if a class variable is used +for object inter-communication.

    2. + +
    3. Because instances can be created at arbitrary runtime, a framework +would need to be written when a class variable is allowed to be set or reset +and when not. Ok, if class variables are used for +object inter-communication, a framework needs to be witten +anyway, but I do not want to be forced to think about this only because I +want to initialize a single class variable.

    4. + +
    + +

    4. Here is a trick I use to initialize class variables.

    + +

    Create a class with class variables:

    + +
    +(setq my-class (send class :new nil '(cvar-1 cvar-2)))
    +
    + +

    Add an :isnew method to set the class variables:

    + +
    +(send my-class :answer :isnew nil '((setq cvar-1 "a" cvar-2 "b")))
    +
    + +

    Create a temporary dummy object to initialize the class variables:

    + +
    +(let ((x (send my-class :new))))
    +
    + +

    Replace the :isnew method with a dummy version [or a real +version, initializing the instance variables]:

    + +
    +(send my-class :answer :isnew nil nil)
    +
    + +

    Now I have a class with initialized class variables:

    + +
    +> (send my-class :show)
    +Object is #<Object...>, Class is #<Object...>
    +  MESSAGES = ((:ISNEW . #<Closure-:ISNEW...>))  ; dummy method
    +  IVARS = NIL
    +  CVARS = (CVAR-1 CVAR-2)  ; class variables
    +  CVALS = #("a" "b")       ; init values
    +  SUPERCLASS = #<Object...>
    +  IVARCNT = 0
    +  IVARTOTAL = 0
    +#<Object...>
    +
    + +

    See defclass below how to make this work automatically.

    + + + +

      Back to top

    + + + +
    + +

    Accessing Class and Instance Variables

    + +
    + +
    +(setq my-class (send class :new '(i-var) '(c-var)))
    +(setq my-object (send my-class :new))
    +
    + +

    A message to read internal class and instance variables:

    + +
    +(send my-class :answer :internal-slot-get '(slot-name)
    +  '((eval slot-name)))
    +
    + +

    A message to write internal class and instance variables:

    + +
    +(send my-class :answer :internal-slot-set '(slot-name value)
    +  '((eval (list 'setq slot-name value))))
    +
    + +

    + +

    Implementation Notes

    + +

    1. It's not really good Lisp style to explicitely call 'eval' in +Lisp code at run-time, because 'eval' produces a lot of +overhead, but here the only way to get access to the internal environment of +an object is passing the message arguments to 'eval' inside the object +itself.

    + +

    2. In the XLISP object system, an :answer message can only be +accessed in an instance of a class [a sub-class or on +object], but not in the class, where the :answer message has been defined, +so the :internal-slot accessor will only work in 'my-object' +but ont in 'my-class'.

    + +

    3. If a method had been changed in a superclass, the change will +automatically be inherited by all instances of the class +[sub-classes and objects], with no need to redefine them.

    + +

    Warning: If 'internal-slot-set' is given a +slot-name that doesn't exist inside the object, a global +variable will be created.

    + +

    + +

    Reading and writing an instance variable:

    + +
    +> (send my-object :internal-slot-get 'i-var)     ; read
    +NIL
    +
    +> (send my-object :internal-slot-set 'i-var 55)  ; write
    +55
    +
    +> (send my-object :internal-slot-get 'i-var)     ; read
    +55
    +
    +> (send my-object :show)
    +Object is #<Object: #9b95998>, Class is #<Object: #9b95c50>
    +  I-VAR = 55 ; new value
    +#<Object: #9b95998>
    +
    + +

    Reading and writing a class variable:

    + +
    +> (send my-object :internal-slot-get 'c-var)      ; read
    +NIL
    +
    +> (send my-object :internal-slot-set 'c-var 123)  ; write
    +123
    +
    +> (send my-object :internal-slot-get 'c-var)      ; read
    +123
    +
    +> (send my-class :show)
    +Object is #<Object: #9b95c50>, Class is #<Object: #9af7dd4>
    +  MESSAGES = ((:INTERNAL-SLOT-GET . #<Closure-:INTERNAL-SLOT-GET: #9b90080>)
    +              (:INTERNAL-SLOT-SET . #<Closure-:INTERNAL-SLOT-SET: #9b900d4>))
    +  IVARS = (I-VAR)
    +  CVARS = (C-VAR)
    +  CVALS = #(123) ; new value
    +  SUPERCLASS = #<Object: #9af7dc8>
    +  IVARCNT = 1
    +  IVARTOTAL = 1
    +#<Object: #9b95c50>
    +
    + +

    See the 'slot-get' and 'slot-set' functions +below how this can be generalized to access any class or instance variable +in any class or object via only two functions.

    + +

      Back to top

    + + + +
    + +

    defclass

    + +
    + +

    The original RBD 'defclass' macro:

    + +
    +(defmacro defclass (name super locals class-vars)
    +  (if (not (boundp name))
    +    (if super
    +        `(setq ,name (send class :new ',locals ',class-vars ,super))
    +        `(setq ,name (send class :new ',locals ',class-vars)))))
    +
    + +

    In order to read or write XLISP class or object variables two +slot-acessor messages need to be added to every new +top-level class:

    + +
    +(defmacro defclass (name super locals class-vars)
    +  (when (boundp name)
    +    (format t ";; WARNING: redefining ~a~%" name))
    +  (if super
    +      `(setq ,name (send class :new ',locals ',class-vars ,super))
    +      `(progn
    +         (setq ,name (send class :new ',locals ',class-vars))
    +         (send ,name :answer :internal-slot-set '(slot-name value)
    +           '((eval (list 'setq slot-name value))))
    +         (send ,name :answer :internal-slot-get '(slot-name)
    +           '((eval slot-name))))))
    +
    + +

    The third version provides 'let'-syntax with instance and +class variables. A list of symbols will create variables +initialized to NIL. This is the XLISP default behaviour. +If an element is a (symbol value) list, then the +variable will be initialized with 'value', as soon as an instance of the +class is created.

    + +

    + +

    + + + + + + + + + + + + + + + + + + + + + +
    (defclass class {superclass | NIL}
      ({ivar | (ivar init-form)} ... )  ; instance variables
      ({cvar | (cvar init-form)} ... ))  ; class variables

    + +

    + +
    +(defmacro expand-init-values (vars var-list init-list)
    +  (let ((var (gensym)))
    +    `(dolist (,var ,vars (setq ,var-list  (reverse ,var-list)
    +                               ,init-list (reverse ,init-list)))
    +       (cond ((symbolp ,var)
    +              ;; if the element is a single symbol,
    +              ;; then add it to the variable list
    +              (push ,var ,var-list))
    +             ((and (listp ,var) (symbolp (first ,var)))
    +              ;; if the element is a (symbol value) list, then add
    +              ;; an (setq symbol value) element to the init-list
    +              (push (list 'setq (first ,var) (second ,var)) ,init-list)
    +              ;; and add the symbol to the variable-list
    +              (push (first ,var) ,var-list))
    +             (t (error "bad argument type" ,var))))))
    +
    +(defmacro with-unique-names (symbols &rest body)
    +  `(let ,(mapcar #'(lambda (x) `(,x (gensym))) symbols) ,@body))
    +
    +(defmacro defclass (name super class-vars instance-vars)
    +  (with-unique-names (class-list class-init instance-list instance-init x)
    +    `(let (,instance-list ,instance-init ,class-list ,class-init)
    +       (expand-init-values ',class-vars ,class-list ,class-init)
    +       (expand-init-values ',instance-vars ,instance-list ,instance-init)
    +       (if (boundp ',name)
    +           (format t ";; Redefining ~a~%" ',name)
    +           (format t ";; CLASS ~a~%" ',name))
    +       (format t ";; CVARS ~a~%" ',class-vars)
    +       (format t ";; IVARS ~a~%" ',instance-vars)
    +       ,(if super
    +            `(setq ,name (send class :new ,instance-list ,class-list ,super))
    +            `(setq ,name (send class :new ,instance-list ,class-list)))
    +       ;; initialize class and instance variables
    +       (when ,class-list
    +         (send ,name :answer :isnew nil ,class-init)
    +         (let ((,x (send ,name :new)))))
    +       (when (or ,instance-list ,class-list)
    +         (send ,name :answer :isnew nil ,instance-init))
    +       ;; add slot-accessors to top-level classes
    +       ,(unless super
    +          `(progn
    +             (send ,name :answer :internal-slot-set '(slot-name value)
    +               '((eval (list 'setq slot-name value))))
    +             (send ,name :answer :internal-slot-get '(slot-name)
    +               '((eval slot-name))))))))
    +
    + +

    Sub-classes and objects inherit their acessors from the +super-class.

    + +

    Define a class with an instance-variable, a +class-variable and slot acessors:

    + +
    +> (defclass my-class nil 
    +    ((a 1) (b 2) (c 3))
    +    ((d 4) (e 5) (f 6)))
    +
    +> 
    +
    + +

      Back to top

    + + + +
    + +

    Generalized Slot Accessors

    + +
    + +

    Now the slot accessors for internal class and instance variables can be +defined as ordinary XLISP functions:

    + +
    +(defun slot-set (object slot-name value)
    +  (send object :internal-slot-set slot-name value))
    +
    +(defun slot-get (object slot-name)
    +  (send object :internal-slot-get slot-name))
    +
    + +

    Examples:

    + +
    +> (slot-set my-object 'i-var 333)
    +333
    +
    +> (slot-get my-object 'i-var)
    +333
    +
    + +

    Even typing the quote could be saved if 'slot-set' and 'slot-get' are +defined as macros:

    + +
    +(defmacro slot-set (object slot-name value)
    +  `(send ,object :internal-slot-set ',slot-name ,value))
    +
    +(defmacro slot-get (object slot-name)
    +  (send ,object :internal-slot-set ',slot-name ,value))
    +
    + +

    Examples:

    + +
    +> (slot-set my-object i-var 444)
    +444
    +
    +> (slot-get my-object i-var)
    +444
    +
    + +

      Back to top

    + + + +
    + +

    Removing a Method from a Class or Instance

    + +
    + +

    In Smalltalk, if a method's body is unbound and no other object refernces +the method, then the method is automatically garbage collected. +Unfortunately in XLISP this doesn't work because the instance variables, +including the list of methods, are not accessed by the garbage collector +at all. This means that even if the message body is set to NIL, +the message is not garbage collected, instead the 'no function' +message returns NIL and blocks the built-in search for +super-class messages.

    + +

    Because messages cannot be removed from XLISP objects, the only way to +make a message 'disappear' is to replage it's body by a call to the +super-class, passing the arguments of the original message:

    + +
    +(defun remove-method (object message-selector &rest args)
    +  (send object message-selector
    +  (send-super message-selector args))
    +
    + +

    Shit: this doesn't work if the metod is defined in a super-class.

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/objects/smalltalk.htm b/docsrc/xlisp/xlisp-doc/objects/smalltalk.htm new file mode 100644 index 0000000..48c4712 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/objects/smalltalk.htm @@ -0,0 +1,441 @@ + + +Smalltalk Object Model + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    The Smalltalk Object Model

    + +
    + +

    This page is based on a document written by Glenn Hollowell:

    + + + +

    The original document has been adapted for use with the XLISP +2.0 object system.

    + +
    + +

    1  Basic Concepts

    + +
    + +

    Within the context of Smalltalk, objects are implemented in code through +encapsulation and polymorphism.

    + +

    Encapsulation is the approach used in Smalltalk to bundle everything +needed into an object to preserve the integrity of the enclosed data. +The code within an object performs operations on the objects +internal data. Operations in Smalltalk are performed as the result of a +messages being sent to an object to execute a specific portion of its code, +usually called a 'method'.

    + +

    Polymorphism is the way that the Smalltalk language allows methods of the +same name to have predictable and meaningful results in related instances, +yet perform the operations differently to achieve the results.

    + +

    Polymorphism is typically implemented in Smalltalk through the +abstraction of the common properties of a group of objects into classes and +hierarchically subclassing shared properties using inheritance, along with +specialization of the subclass to define the differences.

    + +

    Classes serve as templates because they define the instance variables for +all the class instance variables and methods. The instance of a +class is created by sending a +:new message to the class which +uniquely identifies the object instance and allocates space for its +variables.

    + +

      Back to top

    + + + +
    + +

    2  Objects

    + +
    + +

    An object is an encapsulated software component made up of memory and +operations that creates a coherent programming entity. All objects are an +instance of a class. Objects have public and private properties. An object's +implementation details are private and are hidden from other objects. + +

      + +
    • An object's public properties are its messages that make up its +interface.

    • + +
    • The object's private properties are its variables.

    • + +
    + +

    Interaction with an object only occurs via these messages to its +interface. All object instances of a given class have a common +message interface.

    + +

      Back to top

    + + + +
    + +

    2.1  Operations

    + +
    + +

    An operation is the action taken by an object instance as result of a +message being received through the object's interface. Messages requesting +operations are addressed to specific recipient object instances, thus +Smalltalk uses the 'classical' object model and the method to execute in +response to a message is determined by searching the object's class +hierarchy.

    + +

      Back to top

    + + + +
    + +

    2.2  Requests

    + +
    + +

    A request is act of sending a message to an object's interface with the +expectation that the object will perform a known operation that is +associated with the message.

    + +

      Back to top

    + + + +
    + +

    2.3  Messages

    + +
    + +

    A message is a request to an object instance to perform an operation. A +message expression consists of a receiver, selector [message name], and +potentially some arguments. The selector must be mapped to a +method of the same name, encapsulated in the receiver object's class +hierarchy. The arguments, if any, are used by the method to +perform its operation.

    + +
    +(send receiver :selector [arguments])
    +
    + +

    In Smalltalk there exist several message types, like unary, binary, and +keyword messages. In XLISP there is only one message type, so +the description of the Smalltalk message types has been omitted from this +document.

    + +

      Back to top

    + + + +
    + +

    2.4  Specification of Behavioral Semantics

    + +
    + +

    Behavior is defined by methods specified in classes which are implemented +as class instances and execution is triggered in those instances by message +requests.

    + +

      Back to top

    + + + +
    + +

    2.5  Methods

    + +
    + +

    A method is the executable code rendered in the class and executed in the +context of an object instance. It defines how to perform an operation in the +object instance. It is made up of a message pattern that is used to match +against incoming messages, temporary variables, and a sequence of +instructions. A method execution is triggered when message is received that +matches the methods' message pattern.

    + +

      Back to top

    + + + +
    + +

    2.6  State

    + +
    + +

    The state of an instance is represented by the values of its instance +variables.

    + +

      Back to top

    + + + +
    + +

    2.7  Object Lifetime

    + +
    + +

    Object instances are created with the +:new method. Each object +instance is given a unique identifier called an object pointer or object +reference.

    + +

    + +

    New classes are created by using the "subclass" method. The "new" and +"subclass" methods are inheritedby almost all classes. Every instance object +pointer is also associated with an object pointer of a class. Unlike the +"new" and "subclass" methods, there are no specific methods that remove an +object that is no longer useful. Smalltalk objects are deleted when they are +no longer reachable (garbage collected).

    + +

    + +

      Back to top

    + + + +
    + +

    2.8  Behavior/State Grouping

    + +
    + +

    Smalltalk uses the 'classical' object model.

    + +

      Back to top

    + + + +
    + +

    2.9  Communication Model

    + +
    + +

    All communications within Smalltalk occur through messages between +objects and most Smalltalk implementations support a form of concurrency. +For example, Smalltalk-80 provides for multiple independent processes, and +semaphores provide the common mechanism for synchronizing the independent +processes.

    + +

      Back to top

    + + + +
    + +

    2.10  Events

    + +
    + +

    No specific mechanisms for handling events are built into the +Smalltalk language, but "event handling" logic is commonly implemented in +Smalltalk applications through its normal messaging techniques.

    + +

      Back to top

    + + + +
    + +

    4  Polymorphism

    + +
    + +

    Polymorphism is the way that the Smalltalk language allows methods of +same name to have predictable and meaningful results in related instances, +yet perform the operations differently to achieve similar results.

    + +

    Smalltalk supports polymorphism by allowing methods defined in classes to +be overridden with methods of the same name, but different logic, in a +subsequent subclass. In addition, methods of the same name can be defined in +a total different subclass hierarchy.

    + +

    In the class hierarchy below, all of the lowest level classes are defined +to accept the message 'moveForward' (mFabstract), but several +different versions are implemented as indicated by (MFn) in the diagram. +The message sent to the instances of 'Bus' or 'Auto' uses the +method defined in the 'Motorized' class. The same method is +inherited by 'Train' and 'Motorcycle', but both have overridden the +inherited method by defining a method with different logic using the same +message pattern. All the others instances in the diagram have +the 'moveForward' message pattern in their interface, but are not in the +'Motorized' inheritance chain. All of the 'moveForward' +(mFabstract) methods function as you intuitively expect.

    + +
    +                     Transport Mechanism  (mFabstract)
    +       /---------------       |        -------------------\
    +Animal Powered          Human Powered                  Motorized
    +  /  (mF1)  \         /               \               /  (mF5)  \
    +Buggy      Wagon  Land-based      Water-based    Public       Private
    +                   /     \         / (mF4) \     /    \        /   \
    +                 Bike  Skates  Row Boat  Canoe  Bus  Train  Auto  Motorcycle
    +                (mF2)   (mF3)                        (mF6)          (mF7)
    +
    + +

      Back to top

    + + + +
    + +

    5  Encapsulation

    + +
    + +

    The approach used in Smalltalk is to encapsulate all objects, whether a +complex as a sorted list or as simple as a string, into a single programming +entity that includes data and logic. Further, other objects can not invoke +the encapsulated data or logic. In order to interact, other objects must +send messages to an object's interface that will cause the object to perform +a function that will have a known effect. See also entry under +2.3 Messages.

    + +

      Back to top

    + + + +
    + +

    6  Identity, Equality, Copy

    + +
    + +

    + +

    Smalltalk provides unique identity for all objects. Objects can be tested +for equivalence (Are the objects being compared the same object?) and +equality (every object may implement its own definition of equality).

    + +

    Copying of objects can be performed as a deep copy (object's structure +and the objects pointed to by its variables are copied) or shallow copy +(objects pointed to by variables, their variables are not copied, but are +shared with the original object).

    + +

    + +

    XLISP does not provide build-in functions or methods to +compare or to copy objects.

    + +

      Back to top

    + + + +
    + +

    7  Types and Classes

    + +
    + +

    Smalltalk does not have a separate notion of 'type' [message protocol +shared by a group of objects] apart from 'class'.

    + +

    A class is a group of objects that represent the same type of entity and +share the same methods. A class describes the implementation of a set of +similar objects. Classes are themselves objects. All objects belong to some +class and an object is an instance of the class of which it belongs.

    + +

    XLISP: If an object is a member of a class can be tested by +sending an :isa message.

    + +

      Back to top

    + + + +
    + +

    8  Inheritance and Delegation

    + +
    + +

    Smalltalk class relationships are defined in terms of inheritance. The +properties of one class are be inherited from another class in a +hierarchical structure beginning with the upper-most +class object. In +inheritance, the inheriting class is called the 'subclass' and the +class being inherited from is call the 'superclass'. A subclass +inherits all of its superclass' variables and methods.

    + +

    Abstract classes are classes from which other classes are inherited +(subclassed) only. Instances can be implemented any non-abstract class.

    + +

    Subclasses are specialization of their superclasses. A subclass may add +variables, but it cannot delete those inherited from the superclass. A +subclass may accept an inherited method or it may override the method by +providing an new method with the same name (or message selector).

    + +

    Object instances are instances of a class. Smalltalk does not provide for +delegation (defined as object instances being created from other object +instances and not a class).

    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/reference/abs.htm b/docsrc/xlisp/xlisp-doc/reference/abs.htm new file mode 100644 index 0000000..3069cb2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/abs.htm @@ -0,0 +1,78 @@ +XLISP abs + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    abs

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlisp/xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (abs number)
    +
    number - an integer or floating point expression
    +returns - the absolute value of the number
    +
    + +

    + +

    Description

    + +

    The 'abs' function computes the absolute value of a number and returns +the result. A 'bad argument type' error is signalled if the +argument is not a numebr.

    + +

    Examples

    + +
    +(abs 1)       => 1
    +(abs -99)     => 99
    +(abs -99.9)   => 99.9
    +(abs -32768)  => 32768
    +(abs "123")   => error: bad argument type
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/acos.htm b/docsrc/xlisp/xlisp-doc/reference/acos.htm new file mode 100644 index 0000000..8351556 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/acos.htm @@ -0,0 +1,93 @@ +XLISP acos + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    acos

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  

    + +

    Syntax

    + +

    + +
    +
    (acos flonum)
    +
    flonum - an integer or floating point expression
    +returns - the arc-cosine of the number
    +
    + +

    + +

    Note: the 'acos' function is not implemented in Nyquist. Here +is a Lisp implementation of 'acos', using the atan +function:

    + +
    +(defun acos (x)
    +  (cond ((not (numberp x)) (error "bad argument type" x))
    +        ((= x 1) 0.0)
    +        ((= x -1) pi)
    +        ((< -1 x 1) (+ (atan (/ (- x) (sqrt (1+ (* x (- (float x))))))) (/ pi 2.0)))
    +        (t (error "argument out of range" x))))
    +
    + +

    Description

    + +

    The 'acos' function returns the arc-cosine of an integer or +floating point expression. The result is a floating point +number in radians. If the argument is less than -1 +or greater than +1, the arc-cosine is a complex +number. Complex numbers are not available in XLISP. In +this case the 'acos' function signals an 'argument out of range' +error.

    + +

    Examples

    + +
    +(acos 0.0)   => 1.5708
    +(acos 1.0)   => 0.0
    +(acos -1.0)  => 3.14159
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/addition.htm b/docsrc/xlisp/xlisp-doc/reference/addition.htm new file mode 100644 index 0000000..13e925d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/addition.htm @@ -0,0 +1,87 @@ +XLISP + + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    +

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (+ expr1 ...)
    +
    exprN - integer or floating point number/expression
    +returns - the result of adding the expressions
    +
    + +

    + +

    Description

    + +

    The '+' function adds a list of numbers together and returns the +result.

    + +

    Examples

    + +
    +(+ 1)         => 1
    +(+ 1 2)       => 3
    +(+ 1 2 3)     => 6
    +(+ 1 2 3 4)   => 10
    +
    + +
    +> (print (+ 1 2 (* 3.5 (/ 3.9 1.45))))
    +12.4138  ; screen output of PRINT
    +12.4138  ; return value
    +
    + +

    See  * , + / , print. +XLISP first prints the value on the screen, the second number is the +return value.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/address-of.htm b/docsrc/xlisp/xlisp-doc/reference/address-of.htm new file mode 100644 index 0000000..07190d2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/address-of.htm @@ -0,0 +1,99 @@ +XLISP address-of + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    address-of

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (address-of expr)
    +
    expr - an expression
    +returns - the memory address of the expression as an integer
    +
    + +

    + +

    Description

    + +

    The 'address-of' function returns the internal memory address of the +XLISP node that corresponds to 'expr'. The value returned is an integer.

    + +

    Examples

    + +
    +(setq var 0)                    => 0   ; set up VAR with 0
    +(address-of var)                => 123224
    +(address-of 'var)               => 182638
    +(peek (address-of var))         => 83951616
    +(peek (1+ (address-of var)))    => 16777216
    +(peek (+ 2 (address-of var)))   => 0   ; value of VAR
    +(setq var 14)                   => 14  ; change the value to 14
    +(peek (+ 2 (address-of var)))   => 14
    +(setq var 99)                   => 99  ; change the value to 99
    +(peek (+ 2 (address-of var)))   => 99
    +
    + +

    See  + , +1+, peek, +setq.

    + +

    + +

    Nyquist: The 'address-of' function is internally +disabled, but the code still exists. Look out for PEEK_AND_POKE in the +Nyquist source code.

    + +

    Caution: Be careful when modifying the internal state of XLISP. +If you have modified it, it would be a good idea to exit XLISP +and re-enter before doing any work you really want to +retain.

    + +

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/alloc.htm b/docsrc/xlisp/xlisp-doc/reference/alloc.htm new file mode 100644 index 0000000..22feb53 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/alloc.htm @@ -0,0 +1,98 @@ +XLISP alloc + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    alloc

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xldmem.c

    + +

    Syntax

    + +

    + +
    +
    (alloc size)
    +
    size - the number of nodes to allocate as an integer
    +returns - the old number of nodes to allocate
    +
    + +

    + +

    Description

    + +

    The 'alloc' function changes the number of memory nodes allocated per +segment whenever memory is expanded. The previous number of +nodes allocated per segment is the value returned as the result. The +power-up default is 1000 nodes per segment. Note that +'alloc' does not, itself, expand memory. You need to call the +expand function to do the expand operation.

    + +

    Examples

    + +
    +> (room)
    +Nodes:       4000
    +Free nodes:  1669
    +Segments:    4
    +Allocate:    1000    ; default ALLOC value
    +Total:       52570
    +Collections: 8
    +NIL
    +
    +> (alloc 2000)       ; new ALLOC value
    +1000                 ; old ALLOC value
    +
    +> (room)
    +Nodes:       4000
    +Free nodes:  1655
    +Segments:    4
    +Allocate:    2000    ; new ALLOC value
    +Total:       52570
    +Collections: 8
    +NIL
    +
    + +

    See room.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/alphanumericp.htm b/docsrc/xlisp/xlisp-doc/reference/alphanumericp.htm new file mode 100644 index 0000000..9067193 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/alphanumericp.htm @@ -0,0 +1,84 @@ +XLISP alphanumericp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    alphanumericp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (alphanumericp char)
    +
    char - a character expression
    +returns -  T  if the character +is alphabetic or a digit, NIL otherwise
    +
    + +

    + +

    Description

    + +

    The 'alphanumericp' function checks if the 'char' expression is an +alphabetic or a digit character. If 'char' is an alphabetic +[either an upper or lower case] or a digit character, + T  is returned, otherwise +NIL is returned. Note that XLISP is limited to +ASCII characters, so there is no way +to find out if an Unicode character with a +char-code greater than +ASCII 127 is alphanumeric or not.

    + +

    Examples

    + +
    +(alphanumericp #\A)  => T
    +(alphanumericp #\a)  => T
    +(alphanumericp #\1)  => T
    +(alphanumericp #\[)  => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/and.htm b/docsrc/xlisp/xlisp-doc/reference/and.htm new file mode 100644 index 0000000..1a2c3d9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/and.htm @@ -0,0 +1,118 @@ +XLISP and + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    and

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +

    + +
    +
    (and [expr1 ... ])
    +
    exprN - an expression
    +returns - NIL if any expression evaluates +to NIL , otherwise the value +of the last expression
    +Note: evaluation of expressions stops after the first +expression that evaluates to NIL
    +
    + +

    + +

    Description

    + +

    The 'and' special form evaluates a sequence of expressions and returns +the effect of a logical AND on the expressions. If, at any +point, an expression is NIL, then +NIL is returned as the result of the 'and' +function. If all of the expressions have a +non-NIL value, the value of the last +expression is returned as the result. Evaluation of the expressions will +stop when an expression evaluates to NIL, +none of the subsequent expressions will be evaluated. If there +are no expressions, then 'and' returns  T  +as its result.

    + +

    Examples

    + +
    +(and t t t)  => T
    +(and nil t)  => NIL
    +(and t nil)  => NIL
    +(and)        => T
    +
    + +

    Some more practical examples:

    + +
    +> (and T "boo" "hiss" T "rah")
    +"rah"    ; return value of AND
    +
    +> (and (princ "hi") NIL (princ "ho"))
    +hi       ; prints "hi"
    +NIL      ; return value of AND
    +
    + +See princ. + +
    +> (setq a 5 b 6)                 ; set up A and B
    +6                                ; return value of SETQ
    + 
    +> (if (and (numberp a)           ; if A is a number
    +           (numberp b)           ; and B is a number
    +           (< a b))              ; and A < B
    +    (print "A is less than B")   ; then do this
    +    (print "error"))             ; else do this
    +"A is less than B"               ; screen output of PRINT
    +"A is less than B"               ; return value of IF
    +
    + +

    See  < , + if , print, +setq.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +XLISP > +XLISP 2.0  -  +Contents  -  +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/append.htm b/docsrc/xlisp/xlisp-doc/reference/append.htm new file mode 100644 index 0000000..4d7b54a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/append.htm @@ -0,0 +1,90 @@ +XLISP append + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + + +

    append

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (append [expr ... ])
    +
    expr - a list or list expression
    +returns - the new list
    +
    + +

    + +

    Description

    + +

    The 'append' function takes an arbitrary number of lists and splices them +together into a single list. This single list is returned. If +an empty list NIL is appended, it has no +effect, it does not appear in the final list. Remember that '(nil) is not an +empty list. If a list is appended to an atom, it also has no +effect and the atom will not appear in the final list.

    + +

    Examples

    + +
    +(append)                            => NIL
    +(append 'a 'b)                      => B
    +(append '(a) '(b))                  => (A B)
    +(append 'a '(b))                    => (B)
    +(append '(a) 'b)                    => (A . B)
    +(append '(a) nil)                   => (A)
    +(append (list 'a 'b) (list 'c 'd))  => (A B C D)
    +(append '(a (b)) '(c (d)))          => (A (B) C (D))
    +(append '(a) nil nil nil '(b))      => (A B)
    +(append '(a) '(nil) '(b))           => (A NIL B)
    +
    + +

    Note: If a list is appended to an atom, XLISP signals no error, +the atom just disappears!

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/apply.htm b/docsrc/xlisp/xlisp-doc/reference/apply.htm new file mode 100644 index 0000000..acc5f05 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/apply.htm @@ -0,0 +1,89 @@ +XLISP apply + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    apply

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +

    + +
    +
    (apply function args)
    +
    function - the function or symbol to be applied to 'args'
    +args - a list that contains the arguments to be passed to 'function'
    +returns - the result of applying the function to the arguments
    +
    + +

    + +

    Description

    + +

    The 'apply' function causes 'function' to be evaluated with 'args' as the +parameters, returning the result of 'function'. The 'args' argument must be +a list.

    + +

    Examples

    + +
    +> (defun my-add (x y)        ; define MY-ADD function
    +    (+ x y))
    +MY-ADD
    +
    +> (my-add 1 2)               ; ordinary function call
    +3                            ; returns 3
    +
    +> (apply #'my-add '(2 4))    ; symbol-function applied to argument-list
    +6                            ; returns 6
    +
    + +

    Note: When using 'apply' to cause the evaluation of a function, +you can use the sharp-quoted name of the function like +#'my-add in the example, or (function my-add). In +XLISP also 'my-add and (quote my-add) work, +but this is no good Lisp style.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/aref.htm b/docsrc/xlisp/xlisp-doc/reference/aref.htm new file mode 100644 index 0000000..68ad742 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/aref.htm @@ -0,0 +1,105 @@ +XLISP aref + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    aref

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +

    + +
    +
    (aref array element)
    +
    array - an array expression
    +element - an integer expression
    +returns - the value of the array element
    +
    + +

    + +

    Description

    + +

    The 'aref' function returns the specified element out of a previously +created array. Array elements may be any valid lisp data type, including +lists or arrays. Arrays made by make-array and +accessed by 'aref' are base 0. This means the first element is +accessed by element number '0' and the last element is accessed +by element number 'n-1' [where 'n' is the array size]. Array +elements are initialized to NIL.

    + +

    Examples

    + +
    +(setq my-array '#(0 1 2 3 4))       => #(0 1 2 3 4)
    +(aref my-array 0)                   => 0
    +(aref my-array 4)                   => 4
    +(aref my-array 5)                   => error: array index out of bounds - 5
    +my-array                            => #(0 1 2 3 4)
    +                                    
    +(setq new (make-array 4))           => #(NIL NIL NIL NIL)
    +(setf (aref new 0) (make-array 4))  => #(NIL NIL NIL NIL)
    +new                                 => #(#(NIL NIL NIL NIL) NIL NIL NIL) 
    +(setf (aref (aref new 0) 1) 'a)     => A
    +new                                 => #(#(NIL A NIL NIL) NIL NIL NIL)
    +(setf (aref new 2) '(a b c))        => (A B C)
    +new                                 => #(#(NIL A NIL NIL) NIL (A B C) NIL)
    +
    + +

    Read macro: There is a built-in read-macro for arrays, +'#(...)' [the hash symbol with the array elements +in parentheses]. This allows you to create arbitrary arrays with initial +values without going through a make-array +function. See the Readtable +section in the XLISP 2.0 Manual.

    + +

    Note: This function returns the value of an array element. +However, there is no equivalent direct function to set the value of an array +element to some value. To set an element value, you must use +the setf function. +The setf function is a generalized +function that allows you to set the value of arbitrary lisp entities.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/arrayp.htm b/docsrc/xlisp/xlisp-doc/reference/arrayp.htm new file mode 100644 index 0000000..139fc4d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/arrayp.htm @@ -0,0 +1,84 @@ +XLISP arrayp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    arrayp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +

    + +
    +
    (arrayp expr)
    +
    expr - an arbitrary Lisp expression
    +returns -  T  if the value is an +array, NIL otherwise
    +
    + +

    + +

    Description

    + +

    The 'arrayp' function checks if 'expr' evaluates to an array. + T  is returned if 'expr' evaluates to an +array, NIL is returned otherwise.

    + +

    Examples

    + +
    +(arrayp #(0 1 2))  => T    ; array
    +(setq a #(a b c))  => #(A B C))
    +(arrayp a)         => T    ; evaluates to an array
    +(arrayp '(a b c))  => NIL  ; list
    +(arrayp 1)         => NIL  ; integer
    +(arrayp 1.2)       => NIL  ; float
    +(arrayp 'a)        => NIL  ; symbol
    +(arrayp #\a)       => NIL  ; character
    +(arrayp NIL)       => NIL  ; NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/asin.htm b/docsrc/xlisp/xlisp-doc/reference/asin.htm new file mode 100644 index 0000000..cd7d7fa --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/asin.htm @@ -0,0 +1,93 @@ +XLISP asin + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    asin

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  

    + +

    Syntax

    + +

    + +
    +
    (asin expr)
    +
    expr - floating point number/expression
    +returns - the arcsine of the number
    +
    + +

    + +

    Note: The 'asin' function is not imlemented in Nyquist. Here is a +Lisp implementation of 'asin', using the atan +function:

    + +
    +(defun asin (x)
    +  (cond ((not (numberp x)) (error "bad argument type" x))
    +        ((= x 1) (/ pi 2.0))
    +        ((= x -1) (/ pi -2.0))
    +        ((< -1 x 1) (atan (/ x (sqrt (1+ (* x (- x)))))))
    +        (t (error "argument out of range" x))))
    +
    + +

    Description

    + +

    The 'asin' function returns the arc sine of a floating point +expression. The result is a floating point number in radians. +If the argument is less than -1 or greater +than +1, the arc sine is a complex number. Complex +numbers are not available in XLISP. In this case +the 'asin' function signals an 'argument out of range' error.

    + +

    Examples

    + +
    +(asin 0.0)   => 0.0
    +(asin 1.0)   => 1.5708
    +(asin -1.0)  => -1.5708
    +(asin 0)     => error: bad integer operation
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/assoc.htm b/docsrc/xlisp/xlisp-doc/reference/assoc.htm new file mode 100644 index 0000000..ab1344a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/assoc.htm @@ -0,0 +1,121 @@ +XLISP assoc + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    assoc

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (assoc expr a-list [{:test | :test-not} test])
    +
    expr - the expression to find as an atom or list
    +a-list - the association list to search
    +test - optional test function (default is eql)
    +returns - the alist entry or NIL
    +
    + +

    + +

    Description

    + +

    An association list is a collection of list pairs of the form:

    + +
    +((key1 item1) (key2 item2) ... (keyN itemN))
    +
    + +

    The 'assoc' function searches through an association list +'a-list' looking for the key +[a car in an association pair] that +matches the search 'expr'. If a match is found, that +association pair is returned as the result. If no match is +found, NIL is returned. You +may specify your own test with the ':test' and +':test-not' keywords followed by the 'test' you wish to +perform.

    + +

    Examples

    + +
    +(setq mylist '((a . my-a)
    +               (b . his-b)
    +               (c . her-c)
    +               (d . end)))
    +
    +(assoc 'a mylist)  => (A . MY-A)
    +(assoc 'b mylist)  => (B . HIS-B)
    +(assoc  1 mylist)  => NIL
    +
    + +
    +(setq agelist '((1 (bill bob))
    +                (2 (jane jill))
    +                (3 (tim tom))
    +                (5 (larry daryl daryl))))
    +
    +(assoc 1 agelist)                 => (1 (BILL BOB))
    +(assoc 3 agelist :test #'>=)      => (1 (BILL BOB))
    +(assoc 3 agelist :test #'<)       => (5 (LARRY DARYL DARYL))
    +(assoc 3 agelist :test #'<=)      => (3 (TIM TOM))
    +(assoc 3 agelist :test-not #'>=)  => (5 (LARRY DARYL DARYL))
    +
    + +

    Using a list as key, tested with equal:

    + +
    +> (assoc '(a b) '(((c d) e) ((a b) x)) :test #'equal)
    +((A B) X)
    +
    + +

    Note: The 'assoc' function can work with a list or string as the +'expr'. However, the default eql test does +not work with lists or strings, only symbols and numbers. +To make this work, you need to use the ':test' keyword along +with equal for 'test'.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/atan.htm b/docsrc/xlisp/xlisp-doc/reference/atan.htm new file mode 100644 index 0000000..27d67b5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/atan.htm @@ -0,0 +1,77 @@ +XLISP atan + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    atan

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (atan expr [expr2])
    +
    expr - an integer or floating point expression
    +expr2 - an optional divisor [default value is 1.0]
    +returns - the arctangent of the division of expr and expr2
    +
    + +

    + +

    Description

    + +

    The 'atan' function returns the arc tangent of the division of 'expr' and +'expr2'. The result is in radians.

    + +

    Examples

    + +
    +(atan  0.0)  =>  0
    +(atan  1.0)  =>  0.785398
    +(atan -1.0)  => -0.785398
    +(atan    0)  =>  0
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/atom.htm b/docsrc/xlisp/xlisp-doc/reference/atom.htm new file mode 100644 index 0000000..fed7af5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/atom.htm @@ -0,0 +1,90 @@ +XLISP atom + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    atom

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +

    + +
    +
    (atom expr)
    +
    expr - an arbitrary Lisp expression
    +returns -  T  if the value is +an atom, NIL otherwise
    +
    + +

    + +

    Description

    + +

    The 'atom' predicate function tests if the 'expr' is an atom. + T  is returned if 'expr' is an +atom, NIL is returned otherwise.

    + +

    Examples

    + +
    +(atom 'a)                      => T   ; symbol
    +(atom #'atom)                  => T   ; subr - function
    +(atom "string")                => T   ; string
    +(atom 4)                       => T   ; integer
    +(atom 4.5)                     => T   ; float
    +(atom object)                  => T   ; object
    +(atom #(1 2 3))                => T   ; array
    +(atom #'quote)                 => T   ; fsubr
    +(atom *standard-output*)       => T   ; stream
    +(atom '())                     => T   ; NIL is an atom
    +(atom (lambda (x) (print x)))  => T   ; closure
    +(atom '(a b c))                => NIL ; list
    +(setq a '(a b))                => (A B)
    +(atom a)                       => NIL ; value of A is not an atom
    +
    + +

    Note: NIL or '() is used in many places as a +list or atom expression. Both 'atom' and listp, when +applied to NIL, return + T .

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +XLISP > +XLISP 2.0  -  +Contents  -  +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/backquote.htm b/docsrc/xlisp/xlisp-doc/reference/backquote.htm new file mode 100644 index 0000000..8cb8b59 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/backquote.htm @@ -0,0 +1,170 @@ +XLISP backquote + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    backquote

    + +
    + +

    backquote:

    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c, xlread.c

    + +

    comma, comma-at:

    + +

    + + + + + + + + + + +
    Type:  -  reader expansion
    Source:  -  xlcont.c, xlread.c

    + +

    Syntax

    + +

    + +
    +
    (backquote expr)
    +
    expr - an expression which is not evaluated except for 'comma' and 'comma-at' portions
    +returns - a copy of the template with 'comma' and 'comma-at' expressions expanded
    +
    + +
    +
    (comma expr)
    +
    expr - an expression which is evaluated within a backquoted expression
    +
    + +
    +
    (comma-at expr)
    +
    expr - an expression which is evaluated within a backquoted expression
    +
    + +

    + +

    Description

    + +

    The 'backquote' special form returns 'expr' unevaluated, like +quote. The difference is that portions of the +expression may be evaluated when they are preceeded by a 'comma' or +'comma-at'.

    + +
      + +
    • comma will evaluate the portion of the expression the comma +preceeds. If the portion is an atom or a list, it is placed as +is within the expression.

    • + +
    • comma-at will evaluate the portion of the +expression that the 'comma-at' preceeds. The +portion needs to be a list. The list is spliced into the +expression. If the portion is not a list, +'comma-at' will splice in nothing.

    • + +
    + +

    XLISP supports the following read macros:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
      `expression  →  (backquote expression)
      ,expression  →  (comma expression)
      ,@expression  →  (comma-at expression)

    + +

    Examples

    + +
    +(setq box 'stuff-inside)  => STUFF-INSIDE  ; BOX contains STUFF-INSIDE
    +(print box)               => STUFF-INSIDE
    +
    +'(i have the box)   ≡ (quote (i have the box))                 => (I HAVE THE BOX)
    +`(i have the box)   ≡ (backquote (i have the box))             => (I HAVE THE BOX)
    +`(i have the ,box)  ≡ (backquote (i have the (comma box)))     => (I HAVE THE STUFF-INSIDE)
    +`(i have the ,@box) ≡ (backquote (I have the (comma-at box)))  => (I HAVE THE)  ; STUFF-INSIDE is not a list
    +
    +(setq automobile '(a van))  => (A VAN)  ; AUTOMOBILE is a VAN
    +(print automobile)          => (A VAN)
    +
    +'(I have automobile)   ≡ (quote (I have automobile))                 => (I HAVE AUTOMOBILE)
    +`(I have automobile)   ≡ (backquote (I have automobile))             => (I HAVE AUTOMOBILE)
    +`(I have ,automobile)  ≡ (backquote (I have (comma automobile)))     => (I HAVE (A VAN))
    +`(I have ,@automobile) ≡ (backquote (I have (comma-at automobile)))  => (I HAVE A VAN)
    +
    + +

    Common errors:

    + +
    +`(,@(i am a list))   => error: bad function - I
    +`(,@'(i am a list))  => (I AM A LIST)
    +
    + +

    Note: 'backquote', 'comma', and 'comma-at' are very useful in +defining macros via defmacro.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/baktrace.htm b/docsrc/xlisp/xlisp-doc/reference/baktrace.htm new file mode 100644 index 0000000..1128206 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/baktrace.htm @@ -0,0 +1,117 @@ +XLISP baktrace + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    baktrace

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xldbug.c, xlsys.c

    + +

    Syntax

    + +

    + +
    +
    (baktrace [level])
    +
    level - an optional integer expression
    +returns - NIL
    +
    + +

    + +

    Description

    + +

    The 'baktrace' function is used to examine the system execution stack +from within the +Break Loop. It +shows the nested forms that got the system to the current state. The +Break Loop can be +entered by a system error, or by the Nyquist/XLISP +error, cerror, or +break functions. If the 'levels' +parameter is not specified, all the nested forms will be shown back to the +main loop form that started the execution. If 'level' is +specified the most recent 'level' nested forms will be shown.

    + +

    Examples

    + +
    +(defun out (x)
    +  (print x)
    +  (mid 99))
    +
    +(defun mid (x)
    +  (print x)
    +  (in 999))
    +
    +(defun in (x)
    +  (print x)
    +  (break "in" x))  ; break
    +
    +> (out 9)
    +9
    +99
    +999
    +break: in - 999
    +if continued: return from BREAK
    +
    +1> (baktrace)   ; the 1 before the > indicates a break loop
    +Function: #<Subr-BAKTRACE: #9af6688>
    +Function: #<Subr-BREAK: #9af6778>
    +Arguments:
    +  "in"
    +  999
    +Function: #<Closure-IN: #9b99574>
    +Arguments:
    +  999
    +Function: #<Closure-MID: #9b99670>
    +Arguments:
    +  99
    +Function: #<Closure-OUT: #9b99778>
    +Arguments:
    +  9
    +NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/bigendianp.htm b/docsrc/xlisp/xlisp-doc/reference/bigendianp.htm new file mode 100644 index 0000000..38037cb --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/bigendianp.htm @@ -0,0 +1,69 @@ +XLISP bigendianp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    bigendianp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +

    + +
    +
    (bigendiap)
    +
    returns -  T  with a big-endian +architecture, otherwise NIL.
    +
    + +

    + +

    Description

    + +

    The 'bigendianp' function tests if Nyquist/XLISP runs on a +bigendian machine, storing the high-order byte of an integer at +the lowest byte address of the integer.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/block.htm b/docsrc/xlisp/xlisp-doc/reference/block.htm new file mode 100644 index 0000000..7d3e21d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/block.htm @@ -0,0 +1,94 @@ +XLISP block + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    block

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +

    + +
    +
    (block name [body ... ])
    +
    name - an unevaluated symbol for the block name
    +body - an arbitrary number of Lisp expressions
    +returns - the value of the last expression
    +
    + +

    + +

    Description

    + +

    The 'block' special form specifies a 'named block' +construct. The last expression in 'body' will be returned by +the 'block' construct as its result unless a return +or return-from is executed within 'block'. +The return exit will exit the nearest +[inner-most] 'block'. +The return-from exit will exit +the specified 'block'.

    + +

    Examples

    + +
    +(defun test ()
    +  (block outer         ; outer BLOCK
    +    (print "outer")
    +    (block inner       ; inner BLOCK
    +      (print "inner")
    +      (return-from outer "all done")
    +      (print "won't get here"))))
    +
    +> (test)
    +"outer"     ; screen output of PRINT
    +"inner"     ; screen output of PRINT
    +"all done"  ; return value
    +
    + +

    See defun, print, +return-from.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/both-case-p.htm b/docsrc/xlisp/xlisp-doc/reference/both-case-p.htm new file mode 100644 index 0000000..7d3a691 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/both-case-p.htm @@ -0,0 +1,84 @@ +XLISP both-case-p + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    both-case-p

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (both-case-p char)
    +
    char - a character expression
    +returns -  T  if the character +is alphabetic, NIL otherwise
    +
    + +

    + +

    Description

    + +

    The 'both-case-p' predicate function checks if the 'char' +expression evaluates to an alphabetic character. If 'char' +evaluates to an alphabetic [either an upper or lower case] character + T  is returned, otherwise +NIL is returned. Note that XLISP is limited to ASCII characters, so there is no way to +find out if an Unicode character is 'both-case-p' if the +char-code is greater than +127.

    + +

    Examples

    + +
    +(both-case-p #\A)  => T
    +(both-case-p #\a)  => T
    +(both-case-p #\1)  => NIL
    +(both-case-p #\[)  => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/boundp.htm b/docsrc/xlisp/xlisp-doc/reference/boundp.htm new file mode 100644 index 0000000..22bad23 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/boundp.htm @@ -0,0 +1,104 @@ +XLISP boundp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    boundp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +

    + +
    +
    (boundp symbol)
    +
    symbol - a symbol expression
    +returns -  T  if a value is +bound to the symbol, NIL otherwise
    +
    + +

    + +

    Description

    + +

    The 'boundp' predicate function tests if 'symbol' evaluates to a symbol +in the *obarray* with a value +bound to it.  T  is returned if +'symbol' has a value, NIL is returned otherwise. Note +that 'boundp' does not test if local let variables, or +class or instance variables exist.

    + +

    Examples

    + +
    +(setq a 1)            => 1    ; create a variable A in the *OBARRAY*
    +(boundp 'a)           => T    ; variable A has a value 1
    +
    +(let ((b 'value))
    +  (boundp b))         => NIL  ; BOUNDP does NOT test LET bindings
    +
    +(defun foo (x)                ; create a function FOO in the *OBARRAY*
    +  (print x))          => FOO
    +
    +(boundp 'foo)         => NIL  ; FOO is not a variable
    +
    +(print myvar)         => error: unbound variable - MYVAR
    +(boundp 'myvar)       => NIL
    +
    +(setq myvar 'abc)             ; give MYVAR a value
    +(boundp 'myvar)       => T
    +
    + +

    Note that 'symbol' is a symbol expression. This means that 'symbol' is +evaluated and the return value is tested:

    + +
    +(setq myvar 'qq)              ; MYVAR evaluates to QQ
    +(boundp myvar)        => NIL  ; but QQ has no value yet
    +
    +(setq qq 'new-value)          ; give QQ a value
    +(boundp myvar)        => T
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/break.htm b/docsrc/xlisp/xlisp-doc/reference/break.htm new file mode 100644 index 0000000..a8a6c58 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/break.htm @@ -0,0 +1,107 @@ +XLISP break + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    break

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xldbug.c

    + +

    Syntax

    + +

    + +
    +
    (break [err-msg [arg]])
    +
    err-msg - a string expression for the error message
    +arg - an optional argument expression
    +returns - NIL when continued from the +break loop
    +
    + +

    + +

    Description

    + +

    The 'break' function allows the entry into the +Break Loop with a +continuable error. The continuable error generated by 'break' does not +require any corrective action. The form of the message generated is:

    + +
    +break: err-msg - arg
    +if continued: return from BREAK
    +
    + +

    The default for 'err-msg' is:

    + +
    +**BREAK**
    +
    + +

    From within the +Break Loop, if a +continue form is evaluated then +NIL is returned from 'break'. If desired, +the clean-up or +top-level functions may be evaluated to abort +the Break Loop.

    + +

    Examples

    + +
    +> (break)
    +break: **BREAK**
    +if continued: return from BREAK
    +
    +> (break "out")
    +break: out
    +if continued: return from BREAK
    +
    +> (break "it" "up")
    +break: it - "up"
    +if continued: return from BREAK
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/caaaar.htm b/docsrc/xlisp/xlisp-doc/reference/caaaar.htm new file mode 100644 index 0000000..69ccda4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/caaaar.htm @@ -0,0 +1,134 @@ +XLISP caaaar ... cadddr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    caaaar ... cadddr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (caaaar expr)
    +(caaadr expr)
    +(caadar expr)
    +(caaddr expr)
    +(cadaar expr)
    +(cadadr expr)
    +(caddar expr)
    +(cadddr expr)
    +
    expr - a list or list expression
    +returns - the result of the last car +function
    +
    + +

    + +

    Description

    + +

    The 'caaaar' ... 'cadddr' functions go through the list expression and +perform a sequence of car or cdr +operations. The sequence of operations is performed from right +to left. So 'caaddr' does a cdr on the +expression, followed by a cdr, followed by a +car, followed by +another car. If at any point +the list is NIL, then NIL is +returned. If at any point a car operation +is performed on an atom [as opposed to a list] an +error is signalled:

    + +
    +error: bad argument
    +
    + +

    The 'cadddr' function returns the same result as the +fourth function.

    + +

    Examples

    + +
    +(setq mylist '((((111A 111B) (112A 112B) (113A 113B))   ; 1st set
    +                ((121A 121B) (122A 122B) (123A 123B))
    +                ((131A 131B) (132A 132B) (133A 133B))
    +                ((141A 141B) (142A 142B) (143A 143B)))
    +               (((211A 211B) (212A 212B) (213A 213B))   ; 2nd set
    +                ((221A 221B) (222A 222B) (223A 223B))
    +                ((231A 231B) (232A 232B) (233A 233B))
    +                ((241A 241B) (242A 242B) (243A 243B)))
    +               (((311A 311B) (312A 312B) (313A 313B))   ; 3rd set
    +                ((321A 321B) (322A 322B) (323A 323B))
    +                ((331A 331B) (332A 332B) (333A 333B))
    +                ((341A 341B) (342A 342B) (343A 343B)))
    +               (((411A 411B) (412A 412B) (413A 413B))   ; 4th set
    +                ((421A 421B) (422A 422B) (423A 423B))
    +                ((431A 431B) (432A 432B) (433A 433B))
    +                ((441A 441B) (442A 442B) (443A 443B)))
    +               (((511A 511B) (512A 512B) (513A 513B))   ; 5th set
    +                ((521A 521B) (522A 522B) (523A 523B))
    +                ((531A 531B) (532A 532B) (533A 533B))
    +                ((541A 541B) (542A 542B) (543A 543B)))))
    +
    +(caaaar mylist)  => 111A
    +(caaadr mylist)  => (211A 211B)
    +(caadar mylist)  => (121A 121B)
    +(caaddr mylist)  => ((311A 311B) (312A 312B) (313A 313B))
    +(cadaar mylist)  => (112A 112B)
    +(cadadr mylist)  => ((221A 221B) (222A 222B) (223A 223B))
    +(caddar mylist)  => ((131A 131B) (132A 132B) (133A 133B))
    +(cadddr mylist)  => (((411A 411B) (412A 412B) (413A 413B))
    +                     ((421A 421B) (422A 422B) (423A 423B))
    +                     ((431A 431B) (432A 432B) (433A 433B))
    +                     ((441A 441B) (442A 442B) (443A 443B)))
    +
    + +

    Note: The 'c...r' functions are part of the +historical Lisp functions. You may find it easier to work with the modern +lisp functions like nth and +nthcdr.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/caaar.htm b/docsrc/xlisp/xlisp-doc/reference/caaar.htm new file mode 100644 index 0000000..a4b210e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/caaar.htm @@ -0,0 +1,106 @@ +XLISP caaar ... caddr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    caaar ... caddr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (caaar expr)
    +(caadr expr)
    +(cadar expr)
    +(caddr expr)
    +
    expr - a list expression
    +returns - the result of the last car function
    +
    + +

    + +

    Description

    + +

    The 'caaar', 'caadr', 'cadar' and 'caddr' functions go through the list +expression and perform a sequence of car or +cdr operations. The sequence of +operations is performed from right to left. So 'caddr' does a +cdr on the expression, followed by +a cdr, followed by +a car. If at any point the +list is NIL, then NIL is +returned. If at any point a car operation +is performed on an atom [as opposed to a list] an +error is signalled:

    + +
    +error: bad argument
    +
    + +

    The 'caddr' function returns the same result as the +third function.

    + +

    Examples

    + +
    +(setq mylist '(((11A 11B) (12A 12B) (13A 13B))
    +               ((21A 21B) (22A 22B) (23A 23B))
    +               ((31A 31B) (32A 32B) (33A 33B))
    +               ((41A 41B) (42A 42B) (43A 43B))))
    +
    +(caaar mylist)  => 11A
    +(caadr mylist)  => (21A 21B)
    +(cadar mylist)  => (12A 12B)
    +(caddr mylist)  => ((31A 31B) (32A 32B) (33A 33B))
    +
    + +

    Note: The 'c...r' functions are part of the +historical Lisp functions. You may find it easier to work with the modern +lisp functions like nth and +nthcdr.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/caar.htm b/docsrc/xlisp/xlisp-doc/reference/caar.htm new file mode 100644 index 0000000..03cee4a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/caar.htm @@ -0,0 +1,101 @@ +XLISP caar, cadr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    caar, cadr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (caar expr)
    +(cadr expr)
    +
    expr - a list expression
    +returns - the result of the last car function
    +
    + +

    + +

    Description

    + +

    The 'caar' and 'cadr' functions go through the list expression and +perform a sequence of car or +cdr operations. The sequence of operations is +performed from right to left. So 'cadr' does a +cdr on the expression, followed by a +car. If at any point the list is +NIL, then +NIL is returned. If at any point a +car operation is performed on an atom +[as opposed to a list] an error is signalled:

    + +
    +error: bad argument
    +
    + +

    The 'cadr' function returns the same result as the +second function.

    + +

    Examples

    + +
    +(setq mylist '((1A 1B) (2A 2B) (3A 3B)))
    +
    +(caar mylist)  => 1A
    +(cadr mylist)  => (2A 2B)
    +
    +(caar 'a)      => error: bad argument
    +(caar nil)     => NIL
    +
    + +

    Note: The 'c...r' functions are part of the +historical Lisp functions. You may find it easier to work with the modern +lisp functions like nth and +nthcdr.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/car.htm b/docsrc/xlisp/xlisp-doc/reference/car.htm new file mode 100644 index 0000000..035d240 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/car.htm @@ -0,0 +1,85 @@ +XLISP car + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    car

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (car expr)
    +
    expr - a list or list expression
    +returns - the first element of the list
    +
    + +

    + +

    Description

    + +

    The 'car' function returns the first element of +the expression. If the first expression +is itself a list, then the sublist is returned. If the list is +NIL , NIL is +returned.

    + +

    The 'car' function returns the same result as the +first function.

    + +

    Examples

    + +
    +(car '(a b c))       => A
    +(car '((a b) c d))   => (A B)
    +(car NIL)            => NIL
    +(car 'a)             => error: bad argument type
    +(setq bob '(1 2 3))  => (1 2 3)
    +(car bob)            => 1
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/case.htm b/docsrc/xlisp/xlisp-doc/reference/case.htm new file mode 100644 index 0000000..8cac054 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/case.htm @@ -0,0 +1,171 @@ +XLISP case + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    case

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +

    + +
    +
    (case expr [(value action) ... ])
    +
    expr - an expression that can be compared via eql
    +value - an unevaluated expression or list of unevaluated expressions
    +action - one or more expressions
    +returns - the value of the last expression of the matching case
    +
    + +

    + +

    Description

    + +

    The 'case' special form first evaluates 'expr', the return value of this +evaluation is then compared against all the 'value' entries:

    + +
    +(case expr
    +  (value-1 action-1)
    +  (value-2 action-2)
    +    ...
    +  (value-n action-n))
    +
    + +

    If 'value' is a single atom, the atom is compared against 'expr':

    + +
    +> (case 'a
    +    ('a "a")
    +    ('b "b"))
    +"a"
    +
    + +

    If 'value' is a list, each of the elements of the list are compared +against 'expr':

    + +
    +> (case 'a
    +    ((1 2 3 4) "number")
    +    ((a b c d) "alpha"))
    +"alpha"
    +
    + +

    The 'action' associated with the first 'value' that matches 'expr' is +evaluated and returned as the result of the 'case' special form.

    + +

    If no 'value' matches, NIL is returned:

    + +
    +> (case 'c
    +    ('a "a")
    +    ('b "b"))
    +NIL
    +
    + +

    If the last 'value' is the symbol  T  and +no other 'value' has matched 'expr', then 'case' will evaluate the 'action' +associated with  T :

    + +
    +> (case 3
    +    (1 "one")
    +    (2 "two")
    +    (t "no match"))
    +"no match"
    +
    + +

    If there are multiple  T  entries, the +first is considered to be the end of the 'case':

    + +
    +> (case 9
    +    (1 "one")
    +    (t "first t")
    +    (t "second t"))
    +"first t"
    +
    + +

    Note: The 'case' special form does not work with a list or string +as the 'expr' because 'case' uses eql which cannot +compare lists or strings:

    + +
    +> (case "a"   ; doesn't work!
    +    ("a" 'a)
    +    ("b" 'b))
    +NIL
    +
    + +

    The cond special form can be used to test Lisp +expressions that cannot be handled by 'case'.

    + +

    Examples

    + +
    +(case)     => NIL
    +(case 'a)  => NIL
    +
    +(defun c-type (expr)
    +  (case (type-of expr)
    +    (flonum  "float")
    +    (fixnum  "integer")
    +    (string  "string")
    +    (cons    "non-empty list")
    +    (nil     "empty list")
    +    (t       "other")))
    +
    +(c-type 1.2)     => "float"
    +(c-type 3)       => "integer"
    +(c-type "ab")    => "string"
    +(c-type '(a b))  => "non-empty list"
    +(c-type '())     => "empty list"
    +(c-type 'a)      => "other"
    +
    + +

    See defun, +type-of.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/catch.htm b/docsrc/xlisp/xlisp-doc/reference/catch.htm new file mode 100644 index 0000000..28b682a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/catch.htm @@ -0,0 +1,197 @@ +XLISP catch, throw + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    catch, throw

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c, xljump.c

    + +

    Syntax

    + +

    + +
    +
    (catch tag-symbol [expr ... ])
    +
    tag-symbol - an expression that evaluates to a symbol
    +expr - an optional series of expressions to be evaluated
    +returns - the value of the last expression the +throw expression
    +
    + +
    +
    (throw tag-symbol [expr])
    +
    tag-symbol - an expression that evaluates to a symbol
    +expr - an optional expression to be returned
    +returns - never returns
    +
    + +

    + +

    Description

    + +

    The 'catch' and 'throw' special forms allow for non-local exits and traps +without going through the intermediate evaluations and function returns:

    + +
    +(catch tag-symbol
    +  [expr ...]
    +  (throw tag-symbol [expr]))
    +
    + +

    If there is a 'catch' for a 'tag-symbol' that has no 'throw' +performed to it, 'catch' returns the value returned from 'expr':

    + +
    +> (catch 'mytag
    +    (+ 1 (+ 2 3)))
    +6
    +
    + +

    If there is no 'expr', NIL is +returned:

    + +
    +> (catch 'mytag)
    +NIL
    +
    + +

    The 'expr' in 'throw' specifies what value is to be returned by the +corresponding 'catch':

    + +
    +> (catch 'mytag
    +    (+ 1 (throw 'mytag 55)))
    +55
    +
    + +

    If there is no 'expr' in 'throw', NIL is returned +to the corresponding 'catch':

    + +
    +> (catch 'mytag
    +    (throw 'mytag))
    +NIL
    +
    + +

    If more than one 'catch' is set up for the same +'tag-symbol', the most recently evaluated +'tag-symbol' will be the one that does the actual catching:

    + +
    +> (catch 'mytag
    +    (catch 'mytag
    +      (throw 'mytag))
    +    (print 'hello))
    +HELLO
    +
    + +

    If a 'throw' is evaluated with no corresponding 'catch', an error is +signalled:

    + +
    +> (catch 'mytag
    +    (throw 'foo))
    +error: no target for THROW
    +
    + +

    + +

    Examples

    + +
    +(defun in (x)
    +  (if (numberp x)           ; if X is a number
    +      (+ x x)               ; then double X
    +      (throw 'math 42)))    ; else throw 42
    +
    +(defun out (x)
    +  (princ "<") 
    +  (princ  (* (in x) 2))     ; double via multiply
    +  (princ ">")
    +  "there")
    +
    +(defun main (x)
    +  (catch 'math (out x)))    ; catch the throw from IN
    +
    +> (in 5)
    +10       ; return value
    +
    +> (out 5)
    +<20>     ; screen output of PRINC
    +"there"  ; return value
    +
    +> (main 5)
    +<20>     ; screen output of PRINC
    +"there"  ; return value
    +
    +> (main 'a)
    +<        ; screen output of PRINC
    +42       ; return value
    +
    + +

    See  + , + * , +defun, + if , +numberp, +princ.

    + +

    + +

    Note: 'catch' and 'throw' accept not only symbols as +'tag-symbol', but if a 'tag-symbol' cannot be +compared via eql, an error is signalled:

    + +
    +> (catch "mytag"
    +    (throw "mytag"))
    +error: no target for THROW
    +
    + +

    This was reproduced with Nyquist 3.03 in December +2010.

    + +

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cddddr.htm b/docsrc/xlisp/xlisp-doc/reference/cddddr.htm new file mode 100644 index 0000000..68b688a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cddddr.htm @@ -0,0 +1,135 @@ +XLISP cdaaar ... cddddr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cdaaar ... cddddr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (cdaaar expr)
    +(cdaadr expr)
    +(cdadar expr)
    +(cdaddr expr)
    +(cddaar expr)
    +(cddadr expr)
    +(cdddar expr)
    +(cddddr expr)
    +
    expr - a list or list expression
    +returns - the result of the last cdr +function
    +
    + +

    + +

    Description

    + +

    The 'cdaaar' ... 'cddddr' functions go through the list expression and +perform a sequence of car or +cdr operations. The sequence of +operations is performed from right to left. So 'cddaar' does a +car on the expression, followed by +a car, followed by +a cdr, followed by another +cdr. If at any point the list +is NIL, then +NIL is returned. If at anypoint a +car operation is performed on an atom [as +opposed to a list] an error is signalled:

    + +
    +error: bad argument
    +
    + +

    Examples

    + +
    +(setq mylist '((((111A 111B) (112A 112B) (113A 113B))   ; 1st set
    +                ((121A 121B) (122A 122B) (123A 123B))
    +                ((131A 131B) (132A 132B) (133A 133B))
    +                ((141A 141B) (142A 142B) (143A 143B)))
    +               (((211A 211B) (212A 212B) (213A 213B))   ; 2nd set
    +                ((221A 221B) (222A 222B) (223A 223B))
    +                ((231A 231B) (232A 232B) (233A 233B))
    +                ((241A 241B) (242A 242B) (243A 243B)))
    +               (((311A 311B) (312A 312B) (313A 313B))   ; 3rd set
    +                ((321A 321B) (322A 322B) (323A 323B))
    +                ((331A 331B) (332A 332B) (333A 333B))
    +                ((341A 341B) (342A 342B) (343A 343B)))
    +               (((411A 411B) (412A 412B) (413A 413B))   ; 4th set
    +                ((421A 421B) (422A 422B) (423A 423B))
    +                ((431A 431B) (432A 432B) (433A 433B))
    +                ((441A 441B) (442A 442B) (443A 443B)))
    +               (((511A 511B) (512A 512B) (513A 513B))   ; 5th set
    +                ((521A 521B) (522A 522B) (523A 523B))
    +                ((531A 531B) (532A 532B) (533A 533B))
    +                ((541A 541B) (542A 542B) (543A 543B)))))
    +
    +(cdaaar mylist)  => (111B)
    +(cdaadr mylist)  => ((212A 212B) (213A 213B))
    +(cdadar mylist)  => ((122A 122B) (123A 123B))
    +(cdaddr mylist)  => (((321A 321B) (322A 322B) (323A 323B))
    +                     ((331A 331B) (332A 332B) (333A 333B))
    +                     ((341A 341B) (342A 342B) (343A 343B)))
    +(cddaar mylist)  => ((113A 113B))
    +(cddadr mylist)      (((231A 231B) (232A 232B) (233A 233B))
    +                     ((241A 241B) (242A 242B) (243A 243B)))
    +(cdddar mylist)  => (((141A 141B) (142A 142B) (143A 143B)))
    +(cddddr mylist)  => ((((511A 511B) (512A 512B) (513A 513B))
    +                     ((521A 521B) (522A 522B) (523A 523B))
    +                     ((531A 531B) (532A 532B) (533A 533B))
    +                     ((541A 541B) (542A 542B) (543A 543B))))
    +
    + +

    Note: The 'c...r' functions are part of the +historical Lisp functions. You may find it easier to work with the modern +lisp functions like nth and +nthcdr.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cdddr.htm b/docsrc/xlisp/xlisp-doc/reference/cdddr.htm new file mode 100644 index 0000000..ce35fa5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cdddr.htm @@ -0,0 +1,104 @@ +XLISP cdaar ... cdddr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cdaar ... cdddr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (cdaar expr)
    +(cdadr expr)
    +(cddar expr)
    +(cdddr expr)
    +
    expr - a list or list expression
    +returns - the result of the last cdr +function
    +
    + +

    + +

    Description

    + +

    The 'cdaar', 'cdadr', 'cddar' and 'cdddr' functions go through the list +expression and perform a sequence of car or +cdr operations. The sequence of +operations is performed from right to left. So 'cddar' does a +car on the expression, followed by a + acdr, followed by another +cdr. If at any point the list +is NIL, then +NIL is returned. If at any point a +car operation is performed on an atom [as +opposed to a list] an error is signalled:

    + +
    +error: bad argument
    +
    + +

    Examples

    + +
    +(setq mylist '(((11A 11B) (12A 12B) (13A 13B))
    +               ((21A 21B) (22A 22B) (23A 23B))
    +               ((31A 31B) (32A 32B) (33A 33B))
    +               ((41A 41B) (42A 42B) (43A 43B))))
    +
    +(cdaar mylist)  => (11B)
    +(cdadr mylist)  => ((22A 22B) (23A 23B))
    +(cddar mylist)  => ((13A 13B))
    +(cdddr mylist)  => (((41A 41B) (42A 42B) (43A 43B)))
    +
    + +

    Note: The 'c...r' functions are part of the +historical Lisp functions. You may find it easier to work with the modern +lisp functions like nth and +nthcdr.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cddr.htm b/docsrc/xlisp/xlisp-doc/reference/cddr.htm new file mode 100644 index 0000000..a69d2f3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cddr.htm @@ -0,0 +1,101 @@ +XLISP cdar, cddr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cdar, cddr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (cdar expr)
    +(cddr expr)
    +
    expr - a list or list expression
    +returns - the result of the last cdr +function
    +
    + +

    + +

    Description

    + +

    The 'cdar' and 'cddr' functions go through the list expression and perform a +sequence of car or +cdr operations. The sequence of +operations is performed from right to left. So 'cdar' does a +car on the expression, followed by a +cdr. If at any point the list is +NIL, then NIL is returned. +If at any point a car operation is +performed on an atom [as opposed to a list] an error is signalled:

    + +
    +error: bad argument
    +
    + +

    Examples

    + +
    +(setq mylist '((1A 1B) (2A 2B) (3A 3B))) 
    +
    +(caar mylist)  => 1A
    +(cadr mylist)  => (2A 2B)
    +
    +(cdar mylist)  => (1B)
    +(cddr mylist)  => ((3A 3B))
    +
    +(cdar 'a)      => error: bad argument
    +(cdar nil)     => NIL
    +
    + +

    Note: The 'c...r' functions are part of the +historical Lisp functions. You may find it easier to work with the modern +lisp functions like nth and +nthcdr.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cdr.htm b/docsrc/xlisp/xlisp-doc/reference/cdr.htm new file mode 100644 index 0000000..d9845f5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cdr.htm @@ -0,0 +1,85 @@ +XLISP cdr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cdr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +

    + +
    +
    (cdr expr)
    +
    expr - a list expression
    +returns - expr with the first element removed
    +
    + +

    + +

    Description

    + +

    The 'cdr' function returns the rest of a +list expression after the first element of the list is removed. If +the list is NIL, then +NIL is returned.

    + +

    The 'cdr' function returns the same result as the +rest function.

    + +

    Examples

    + +
    +(cdr '(a b c))       => (B C)
    +(cdr '((a b) c d))   => (C D)
    +(cdr nil)            => NIL
    +(cdr 'a)             => error: bad argument type
    +(cdr '(a))           => NIL
    +(setq ben '(a b c))  =>
    +(cdr ben)            => (B C)
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cerror.htm b/docsrc/xlisp/xlisp-doc/reference/cerror.htm new file mode 100644 index 0000000..116f9f3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cerror.htm @@ -0,0 +1,23 @@ +XLISP cerror + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cerror

    + +
    + +

    See error.

    + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-code.htm b/docsrc/xlisp/xlisp-doc/reference/char-code.htm new file mode 100644 index 0000000..eafd74b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-code.htm @@ -0,0 +1,86 @@ +XLISP char-code + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-code

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-code char)
    +
    char - a character expression
    +returns - the decimal ASCII +value as an integer
    +
    + +

    + +

    Description

    + +

    The 'char-code' function returns the decimal +ASCII value of the 'char' +expression.

    + +

    Examples

    + +
    +(char-code #\0)              => 48
    +(char-code #\A)              => 65
    +(char-code #\a)              => 97
    +(char-code #\[)              => 91
    +(char-code #\newline)        => 10
    +(char-code (code-char 127))  => 127
    +(char-code (int-char 255))   => 255
    +
    + +

    Note: In Nyquist/XLISP, 'char-code' and +char-int are two different functions, but behave +exactly the same [Nyquist 3.03, December +2010].

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-downcase.htm b/docsrc/xlisp/xlisp-doc/reference/char-downcase.htm new file mode 100644 index 0000000..bcf5829 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-downcase.htm @@ -0,0 +1,79 @@ +XLISP char-downcase + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-downcase

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-downcase char)
    +
    char - a character expression
    +returns - the lower case character
    +
    + +

    + +

    Description

    + +

    The 'char-downcase' function converts the 'char' expression +to lower case. The lower case equivalent of 'char' is returned. If +'char' is not alphabetic [a-z or A-Z], then the +character is returned unchanged.

    + +

    Examples

    + +
    +(char-downcase #\0)  => #\0
    +(char-downcase #\A)  => #\a
    +(char-downcase #\a)  => #\a
    +(char-downcase #\[)  => #\[
    +(char-downcase #\+)  => #\+
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-equal-i.htm b/docsrc/xlisp/xlisp-doc/reference/char-equal-i.htm new file mode 100644 index 0000000..a4a53b4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-equal-i.htm @@ -0,0 +1,89 @@ +XLISP char-equal + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-equal

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-equal char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  if all characters +are equal, NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char-equal' function tests if all the character arguments are +equivalent.  T  is returned if the arguments +are of the same ASCII value, +NIL otherwise. In the case of two +arguments, this has the effect of testing if 'char1' is equal to 'char2'. +This test is case insensitive, the character '#\a' is considered to be the +same ASCII value as the +character '#\A'.

    + +

    Examples

    + +
    +(char-equal #\a #\b)      => NIL
    +(char-equal #\b #\a)      => NIL
    +(char-equal #\a #\b #\c)  => NIL
    +(char-equal #\a #\a)      => T
    +(char-equal #\a #\a #\a)  => T
    +(char-equal #\a #\a #\b)  => NIL
    +(char-equal #\A #\a)      => T
    +(char-equal #\a #\A)      => T
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-equal-s.htm b/docsrc/xlisp/xlisp-doc/reference/char-equal-s.htm new file mode 100644 index 0000000..04e268f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-equal-s.htm @@ -0,0 +1,91 @@ +XLISP char= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char= char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of the same +ASCII value, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char=' function tests if all the character arguments are equivalent. + T  is returned if the arguments +are of the same ASCII value, +NIL otherwise. In the case of two +arguments, this has the effect of testing if 'char1' is equal to 'char2'. +This test is case sensitive, the character '#\a' is different and of greater +ASCII value than the character +'#\A'.

    + +

    Examples

    + +
    +(char= #\a #\b)      => NIL
    +(char= #\b #\a)      => NIL
    +(char= #\a #\b #\c)  => NIL
    +(char= #\a #\a)      => T
    +(char= #\a #\a #\a)  => T
    +(char= #\a #\a #\b)  => NIL
    +(char= #\A #\a)      => NIL
    +(char= #\a #\A)      => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-greaterp-i.htm b/docsrc/xlisp/xlisp-doc/reference/char-greaterp-i.htm new file mode 100644 index 0000000..7188588 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-greaterp-i.htm @@ -0,0 +1,91 @@ +XLISP char-greaterp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-greaterp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-greaterp char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression(s) to compare
    +returns -  T  +if the characters are of monotonically decreasing +ASCII value, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char-greaterp' function tests if all the character +arguments are monotonically decreasing. + T  is returned if the arguments +are of monotonically decreasing ASCII +value, NIL otherwise. In the case of two +arguments, this has the effect of testing if 'char1' is greater than +'char2'. This test is case insensitive, the character '#\a' is considered to +be the same ASCII value as the +character '#\A'.

    + +

    Examples

    + +
    +(char-greaterp #\a #\b)      => NIL
    +(char-greaterp #\b #\a)      => T
    +(char-greaterp #\c #\b #\a)  => T
    +(char-greaterp #\a #\a)      => NIL
    +(char-greaterp #\c #\a #\b)  => NIL
    +(char-greaterp #\A #\a)      => NIL
    +(char-greaterp #\a #\A)      => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-greaterp-s.htm b/docsrc/xlisp/xlisp-doc/reference/char-greaterp-s.htm new file mode 100644 index 0000000..95c3258 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-greaterp-s.htm @@ -0,0 +1,91 @@ +XLISP char> + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char>

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char> char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of monotonically decreasing +ASCII value, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char>' function tests if all the character arguments are +monotonically decreasing.  T  is +returned if the arguments are of monotonically decreasing +ASCII value, NIL +otherwise. In the case of two arguments, this has the effect of +testing if 'char1' is greater than 'char2'. This test is case sensitive, the +character '#\a' is different and of greater ASCII value than the +character '#\A'.

    + +

    Examples

    + +
    +(char> #\a #\b)      => NIL
    +(char> #\b #\a)      => T
    +(char> #\c #\b #\a)  => T
    +(char> #\a #\a)      => NIL
    +(char> #\c #\a #\b)  => NIL
    +(char> #\A #\a)      => NIL
    +(char> #\a #\A)      => T
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-int.htm b/docsrc/xlisp/xlisp-doc/reference/char-int.htm new file mode 100644 index 0000000..dbb279c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-int.htm @@ -0,0 +1,86 @@ +XLISP char-int + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-int

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-int char)
    +
    char - a character expression
    +returns - the decimal ASCII +value as an integer
    +
    + +

    + +

    Description

    + +

    The 'char-int' function returns the decimal +ASCII value of the 'char' +expression.

    + +

    Examples

    + +
    +(char-int #\0)              => 48
    +(char-int #\A)              => 65
    +(char-int #\a)              => 97
    +(char-int #\[)              => 91
    +(char-int #\newline)        => 10
    +(char-int (code-char 127))  => 127
    +(char-int (int-char 255))   => 255
    +
    + +

    Note: In Nyquist/XLISP, +char-code and 'char-int' are two +different functions, but behave exactly the same [Nyquist 3.03, +December 2010].

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-lessp-i.htm b/docsrc/xlisp/xlisp-doc/reference/char-lessp-i.htm new file mode 100644 index 0000000..6b662ab --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-lessp-i.htm @@ -0,0 +1,91 @@ +XLISP char-lessp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-lessp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-lessp char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of monotonically increasing +ASCII value, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char-lessp' function tests if all the character +arguments are monotonically increasing. + T  is returned if the arguments +are of increasing ASCII value, +NIL otherwise. In the case of two +arguments, this has the effect of testing if 'char1' is less than 'char2'. +This test is case insensitive, the character '#\a' is +considered to be the same ASCII value +as the character '#\A'.

    + +

    Examples

    + +
    +(char-lessp #\a #\b)      => T
    +(char-lessp #\b #\a)      => NIL
    +(char-lessp #\a #\b #\c)  => T
    +(char-lessp #\a #\a)      => NIL
    +(char-lessp #\a #\b #\b)  => NIL
    +(char-lessp #\A #\a)      => NIL
    +(char-lessp #\a #\A)      => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-lessp-s.htm b/docsrc/xlisp/xlisp-doc/reference/char-lessp-s.htm new file mode 100644 index 0000000..5bee3dd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-lessp-s.htm @@ -0,0 +1,92 @@ +XLISP char< + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + + +

    char<

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char< char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of monotonically increasing +ASCII value, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char<' function tests if all the character arguments are +monotonically increasing.  T  is returned if +the arguments are of monotonically increasing +ASCII value, NIL +otherwise. In the case of two arguments, this has the effect of +testing if 'char1' is less than 'char2'. This test is case sensitive, the +character '#\a' is different and of greater +ASCII value than the character +'#\A'.

    + +

    Examples

    + +
    +(char< #\a #\b)      => T
    +(char< #\b #\a)      => NIL
    +(char< #\a #\b #\c)  => T
    +(char< #\a #\a)      => NIL
    +(char< #\a #\b #\b)  => NIL
    +(char< #\A #\a)      => T
    +(char< #\a #\A)      => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-not-equal-i.htm b/docsrc/xlisp/xlisp-doc/reference/char-not-equal-i.htm new file mode 100644 index 0000000..5d649b5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-not-equal-i.htm @@ -0,0 +1,90 @@ +XLISP char-not-equal + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-not-equal

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-not-equal char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression(s) to compare
    +returns -  T  +if the characters are of different +ASCII value, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char-not-equal' function tests if all the character +arguments are different values.  T  +is returned if the arguments are of different +ASCII value, NIL +otherwise. In the case of two arguments, this has the effect of +testing if 'char1' is not equal to 'char2'. This test is case insensitive, +the character '#\a' is considered to be the same +ASCII value as the character +'#\A'.

    + +

    Examples

    + +
    +(char-not-equal #\a #\b)      => T
    +(char-not-equal #\a #\b #\c)  => T
    +(char-not-equal #\a #\a)      => NIL
    +(char-not-equal #\a #\b #\b)  => NIL
    +(char-not-equal #\A #\a)      => NIL
    +(char-not-equal #\a #\A)      => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-not-equal-s.htm b/docsrc/xlisp/xlisp-doc/reference/char-not-equal-s.htm new file mode 100644 index 0000000..d8876ff --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-not-equal-s.htm @@ -0,0 +1,98 @@ +XLISP char/= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char/=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char/= char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are not equal, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char/=' function tests if all character arguments are different +values.  T  is returned if the +arguments are of different ASCII +value, NIL otherwise. In the case of two +arguments, this has the effect of testing if 'char1' is not equal to +'char2'. This test is case sensitive, the character '#\a' is different and +of greater ASCII value than the +character '#\A'.

    + +

    Examples

    + +
    +(char/= #\a #\b)      => T
    +(char/= #\a #\b #\c)  => T
    +(char/= #\a #\a)      => NIL
    +(char/= #\a #\b #\b)  => NIL
    +(char/= #\A #\a)      => T
    +(char/= #\a #\A)      => T
    +
    + +

    + +

    Caution: If you type 'char\=' [with a backslash] instead of +'string/=' by mistake, no error will be signalled because backslash is the +single escape character and the XLISP reader will evaluate 'char\=' as +char=, but the meaning of the test is +exactly reversed.

    + +

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-i.htm b/docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-i.htm new file mode 100644 index 0000000..010bad1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-i.htm @@ -0,0 +1,92 @@ +XLISP char-not-greaterp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-not-greaterp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-not-greaterp char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of monotonically non-decreasing +ASCII value, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char-not-greaterp' function tests if all character +arguments are monotonically non-decreasing. + T  is returned if the arguments +are of monotonically non-decreasing +ASCII value, NIL +otherwise. In the case of two arguments, this has the effect of +testing if 'char1' is less than or equal to 'char2'. This test is case +insensitive, the character '#\a' is considered to be the same +ASCII value as the character +'#\A'.

    + +

    Examples

    + +
    +(char-not-greaterp #\a #\b)      => T
    +(char-not-greaterp #\b #\a)      => NIL
    +(char-not-greaterp #\a #\b #\c)  => T
    +(char-not-greaterp #\a #\a)      => T
    +(char-not-greaterp #\a #\b #\b)  => T
    +(char-not-greaterp #\A #\a)      => T
    +(char-not-greaterp #\a #\A)      => T
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-s.htm b/docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-s.htm new file mode 100644 index 0000000..ba1d599 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-not-greaterp-s.htm @@ -0,0 +1,92 @@ +XLISP char<= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char<=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char<= char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of monotonically non-decreasing +ASCII value, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char<=' function tests if all character arguments are +monotonically non-decreasing. + T  is returned if the arguments +are of monotonically non-decreasing +ASCII value, NIL +otherwise. In the case of two arguments, this has the effect of +testing if 'char1' is less than or equal to 'char2'. This test is case +sensitive, the character '#\a' is different and of greater +ASCII value than the character +'#\A'.

    + +

    Examples

    + +
    +(char<= #\a #\b)      => T
    +(char<= #\b #\a)      => NIL
    +(char<= #\a #\b #\c)  => T
    +(char<= #\a #\a)      => T
    +(char<= #\a #\b #\b)  => T
    +(char<= #\A #\a)      => T
    +(char<= #\a #\A)      => NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-not-lessp-i.htm b/docsrc/xlisp/xlisp-doc/reference/char-not-lessp-i.htm new file mode 100644 index 0000000..c991f04 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-not-lessp-i.htm @@ -0,0 +1,92 @@ +XLISP char-not-lessp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-not-lessp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-not-lessp char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of monotonically non-increasing +ASCII value, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char-not-lessp' function tests if all character +arguments are monotonically non-increasing. + T  is returned if the arguments +are of monotonically non-increasing +ASCII value, NIL +otherwise. In the case of two arguments, this has the effect of +testing if 'char1' is greater than or equal to 'char2'. This test is case +insensitive, the character '#\a' is considered to be the same +ASCII value as the character +'#\A'.

    + +

    Examples

    + +
    +(char-not-lessp #\a #\b)      => NIL
    +(char-not-lessp #\b #\a)      => T
    +(char-not-lessp #\c #\b #\a)  => T
    +(char-not-lessp #\a #\a)      => T
    +(char-not-lessp #\c #\a #\b)  => NIL
    +(char-not-lessp #\A #\a)      => T
    +(char-not-lessp #\a #\A)      => T
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-not-lessp-s.htm b/docsrc/xlisp/xlisp-doc/reference/char-not-lessp-s.htm new file mode 100644 index 0000000..3f85269 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-not-lessp-s.htm @@ -0,0 +1,92 @@ +XLISP char>= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char>=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char>= char1 charN ... )
    +
    char1 - a character expression
    +charN - character expression[s] to compare
    +returns -  T  +if the characters are of monotonically non-increasing +ASCII value, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    + +

    Description

    + +

    The 'char>=' function tests if all character arguments are +monotonically non-increasing. + T  is returned if the arguments +are of monotonically non-increasing +ASCII value, NIL +otherwise. In the case of two arguments, this has the effect of +testing if 'char1' is greater than or equal to 'char2'. This test is case +sensitive, the character '#\a' is different and of greater +ASCII value than the characrer +'#\A'.

    + +

    Examples

    + +
    +(char>= #\a #\b)      => NIL
    +(char>= #\b #\a)      => T
    +(char>= #\c #\b #\a)  => T
    +(char>= #\a #\a)      => T
    +(char>= #\c #\a #\b)  => NIL
    +(char>= #\A #\a)      => NIL
    +(char>= #\a #\A)      => T
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char-upcase.htm b/docsrc/xlisp/xlisp-doc/reference/char-upcase.htm new file mode 100644 index 0000000..6d13de0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char-upcase.htm @@ -0,0 +1,79 @@ +XLISP char-upcase + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char-upcase

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char-upcase char)
    +
    char - a character expression
    +returns - the upper case character
    +
    + +

    + +

    Description

    + +

    The 'char-upcase' function converts the 'char' expression to +upper case. The upper case equivalent of 'char' is returned. If +the 'char' is not alphabetic [a-z or A-Z], the +character is returned unchanged.

    + +

    Examples

    + +
    +(char-upcase #\0)  => #\0
    +(char-upcase #\A)  => #\A
    +(char-upcase #\a)  => #\A
    +(char-upcase #\[)  => #\[
    +(char-upcase #\+)  => #\+
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/char.htm b/docsrc/xlisp/xlisp-doc/reference/char.htm new file mode 100644 index 0000000..39d0a88 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/char.htm @@ -0,0 +1,80 @@ +XLISP char + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    char

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +

    + +
    +
    (char string position)
    +
    string - a string expression
    +position - an integer expression
    +returns - the ASCII code of +the character
    +
    + +

    + +

    Description

    + +

    The 'char' function returns the +ASCII numeric value of the character +at the specified 'position' in the 'string'. A position of '0' +is the first character in the string.

    + +

    Examples

    + +
    +(char "12345" 0)          => #\1
    +(char "12 45" 2)          => #\Space
    +(string (char "1234" 3))  => "4"
    +(char "1234" 9)           => error: index out of range
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/characterp.htm b/docsrc/xlisp/xlisp-doc/reference/characterp.htm new file mode 100644 index 0000000..d5f1d4d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/characterp.htm @@ -0,0 +1,86 @@ +XLISP characterp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    characterp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +

    + +
    +
    (characterp expr)
    +
    expr - the expression to check
    +returns -  T  if the value is a +character, NIL otherwise
    +
    + +

    + +

    Description

    + +

    The 'characterp' predicate function tests if 'expr' evaluates to a +character.  T  is returned if +'expr' evaluates to a character, NIL is returned +otherwise.

    + +

    Examples

    + +
    +(characterp #\a)       => T    ; character
    +(setq a #\b)           => #\b
    +(characterp a)         => T    ; evaluates to a character
    +(characterp "a")       => NIL  ; string
    +(characterp '(a b c))  => NIL  ; list
    +(characterp 1)         => NIL  ; integer
    +(characterp 1.2)       => NIL  ; float
    +(characterp 'a)        => NIL  ; symbol
    +(characterp #(0 1 2))  => NIL  ; array
    +(characterp nil)       => NIL  ; NIL
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/class.htm b/docsrc/xlisp/xlisp-doc/reference/class.htm new file mode 100644 index 0000000..af76573 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/class.htm @@ -0,0 +1,113 @@ +XLISP class + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    class

    + +
    + +

    + + + + + + + + + + +
    Type:  -  object
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
     class
    +
    + +

    Description

    + +

    'class' is the built-in object class that is used to build other classes. +Classes are, essentially, the template for defining +object instances.

    + +

    Examples

    + +
    +(setq myclass (send class :new '(var)))  ; create MYCLASS with VAR
    +
    +(send myclass :answer :isnew '()         ; set up initialization
    +  '((setq var nil) self))
    +
    +(send myclass :answer :set-it '(value)   ; create :SET-IT message
    +  '((setq var value)))    
    +
    +(setq my-obj (send myclass :new))        ; create MY-OBJ of MYCLASS
    +(send my-obj :set-it 5)                  ; VAR is set to 5
    +
    + +

    Class definition: The internal definition of the 'class' object +instance looks like:

    + +
    +Object is #<Object: #23fe2>, Class is #<Object: #23fe2>
    +  MESSAGES = ((:ANSWER . #<Subr-: #23e48>) 
    +              (:ISNEW . #<Subr-: #23e84>) 
    +              (:NEW . #<Subr-: #23ea2>))
    +  IVARS = (MESSAGES IVARS CVARS CVALS SUPERCLASS IVARCNT IVARTOTAL)
    +  CVARS = NIL
    +  CVALS = NIL
    +  SUPERCLASS = #<Object: #23fd8>
    +  IVARCNT = 7
    +  IVARTOTAL = 7
    +#<Object: #23fe2>
    +
    + +

    The class of 'class' is 'class', itself. The superclass of 'class' is +object. Remember that the location +information [like #23fe2] varies from system to system, yours will probably +look different.

    + +

    Built-in methods: The built in methods in XLISP include:

    + + + +

    Message Structure: The normal XLISP convention for a 'message' is +to have a valid symbol preceeded by a colon like +:isnew or ':my-message'. However, it +is possible to define a 'message' that is a symbol without a colon, but +this makes the code less readable.

    + +

    See the +class +object in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/clean-up.htm b/docsrc/xlisp/xlisp-doc/reference/clean-up.htm new file mode 100644 index 0000000..98faa09 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/clean-up.htm @@ -0,0 +1,90 @@ +XLISP clean-up + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    clean-up

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xldbug.c

    + +

    Syntax

    + +
    +
    (clean-up)
    +
    + +

    Description

    + +

    The 'clean-up' function aborts one level of the +break loop. This +is valid for breaks , +errors and +cerrors [continuable errors]. +If 'clean-up' is evaluated while not in a +break loop , +an error is generated: + +

    +error: not in a break loop
    +
    + +

    This error does not cause XLISP to go into a +break loop. +'clean-up' never actually returns a value.

    + +

    Examples

    + +
    +(clean-up)     ; [back to previous break level]
    +(break "out")  ; break: out
    +(clean-up)     ; to exit out of break loop
    +
    + +

    Note: With Nyquist, no error is generated if 'clean-up' is +invoked when not in a +break loop.

    + +

    Keystroke equivalent: In the IBM PC and MS-DOS versions of XLISP, +a 'Ctrl-g' key sequence has the same effect as doing a (clean-up). On a +Macintosh, this can be accomplished by a pull-down menu or a +'Command-g'. [I haven't tested this with Nyquist].

    + +

    See the +clean-up +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/close.htm b/docsrc/xlisp/xlisp-doc/reference/close.htm new file mode 100644 index 0000000..1efb3cd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/close.htm @@ -0,0 +1,85 @@ +XLISP close + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    close

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (close file-ptr)
    +
    file-ptr - a file pointer expression
    +returns - NIL
    +
    + +

    Description

    + +

    The 'close' function closes the file specified through 'file-ptr'. If +the file close was successful, then a +NIL is returned as the result. For the +file close to be successful, the 'file-ptr' has to point to a valid file. +If the file close was not successful, an error is generated:

    + +
    +error: file not open
    +
    + +

    Examples

    + +
    +(close (open 'f :direction :output))           ; returns NIL
    +(setq myfile (open 'mine :direction :output))  ; create MYFILE
    +(print "hi" myfile)                            ; returns "hi"
    +(close myfile)                                 ; returns NIL
    +                                               ; file contains <hi> <NEWLINE>
    +(setq myfile (open 'mine :direction :input))   ; open MYFILE for input
    +(read myfile)                                  ; returns "hi"
    +(close myfile)                                 ; returns NIL
    +
    + +

    Common Lisp: Common LISP has an XLISP compatible 'close' function. +Common LISP does support an ':abort' keyword, which is not supported in +XLISP.

    + +

    See the +close +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/code-char.htm b/docsrc/xlisp/xlisp-doc/reference/code-char.htm new file mode 100644 index 0000000..6497114 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/code-char.htm @@ -0,0 +1,92 @@ +XLISP code-char + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    code-char

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (code-char code)
    +
    code - a numeric expression representing the +ASCII code as an integer
    +returns - the character with that code or NIL
    +
    + +

    Description

    + +

    The 'code-char' function returns a character which is the result of +turning 'code' expression into a character. If a 'code' cannot be made into +a character, NIL is returned. The range +that 'code' produces a valid character is 0 through 127.

    + +

    Examples

    + +
    +(code-char 48)    ; returns #\0
    +(code-char 65)    ; returns #\A
    +(code-char 97)    ; returns #\a
    +(code-char 91)    ; returns #\[
    +(code-char 10)    ; returns #\Newline
    +(code-char 128)   ; returns NIL
    +(code-char 999)   ; returns NIL
    +
    + +

    Common Lisp: Common Lisp allows for some optional arguments in +'code-char' because it supports the concept of a complex character that +includes not only the ASCII code value, but also fonts and bits. The bits +allow for more than 8 bits per character [16 bits +is especially useful in oriental languages]. The fonts allow for up to 128 +different fonts. XLISP does not support fonts and bits or the optional +parameters associated with them.

    + +

    Note: Unlike the char-code and +char-int functions, 'code-char' and +int-char are not identical in use. +'code-char' accepts 0..127 for its range and then produces +NIL results. +int-char accepts 0..255 for its range and +then produces errors.

    + +

    See the +code-char +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cond.htm b/docsrc/xlisp/xlisp-doc/reference/cond.htm new file mode 100644 index 0000000..a86d487 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cond.htm @@ -0,0 +1,95 @@ +XLISP cond + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cond

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (cond [(pred1 expr1) [(pred2 expr2) ... ]])
    +
    predN - a predicate (NIL / +non-NIL) expression
    +exprN - an expression
    +returns - the value of the first expression whose predicate is +non-NIL
    +
    + +

    Description

    + +

    The 'cond' special form evaluates a series of predicate / +expression pairs. 'cond' will evaluate each predicate in sequential order +until it finds one that returns a non-NIL +value. The expression that is associated with the +non-NIL value is evaluated. The resulting +value of the evaluated expression is returned by 'cond'. If there are no +predicates that return a non-NIL value, +NIL is returned by 'cond'. Only one +expression is evaluated, the first one with a +non-NIL predicate. Note that the predicate +can be a symbol or expression.

    + +

    Examples

    + +
    +(cond                                       ; sample CONDitional
    +  ((not T) (print "this won't print"))
    +  ( NIL    (print "neither will this"))
    +  ( T      (print "this will print"))
    +  ( T      (print "won't get here")))       ; prints "this will print"
    +
    +(defun print-what (parm)
    +  (cond                                     ; start of COND
    +    ((numberp parm) (print "numeric"))      ; check for number
    +    ((consp parm)   (print "list"))         ; check for list
    +    ((null parm)    (print "nil"))          ; check for NIL
    +    (T              (print "something"))))  ; catch-all
    +
    +(print-what 'a)       ; prints "something"
    +(print-what 12)       ; prints "numeric"
    +(print-what NIL)      ; prints "nil"
    +(print-what '(a b))   ; prints "list"
    +
    + +

    See the +cond +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cons.htm b/docsrc/xlisp/xlisp-doc/reference/cons.htm new file mode 100644 index 0000000..08edf55 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cons.htm @@ -0,0 +1,74 @@ +XLISP cons + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cons

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (cons expr-car expr-cdr)
    +
    expr-car - an expression
    +expr-cdr - an expression
    +returns - the new list
    +
    + +

    Description

    + +

    The 'cons' function takes two expressions and constructs a new list from +them. If the 'expr-cdr' is not a list, then the result will be a +'dotted-pair'.

    + +

    Examples

    + +
    +(cons 'a 'b)           ; returns (A . B)
    +(cons 'a nil)          ; returns (A)
    +(cons 'a '(b))         ; returns (A B)
    +(cons '(a b) '(c d))   ; returns ((A B) C D)
    +(cons '(a b) 'c)       ; returns ((A B) . C)
    +(cons (- 4 3) '(2 3))  ; returns (1 2 3)
    +
    + +

    See the +cons +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/consp.htm b/docsrc/xlisp/xlisp-doc/reference/consp.htm new file mode 100644 index 0000000..9c2a8ef --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/consp.htm @@ -0,0 +1,95 @@ +XLISP consp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    consp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (consp expr)
    +
    expr - the expression to check
    +returns -  T  if the value is a +cons, NIL otherwise
    +
    + +

    Description

    + +

    The 'consp' predicate checks if the 'expr' is a non-empty list. + T  is returned if 'expr' is a +list, NIL is returned otherwise. Note that +if the 'expr' is NIL , +NIL is returned.

    + +

    Examples

    + +
    +(consp '(a b))                  ; returns T - list
    +(consp '(a . b))                ; returns T - dotted pair list
    +(consp #'defvar)                ; returns NIL - closure - macro
    +(consp (lambda (x) (print x)))  ; returns NIL - closure - lambda
    +(consp NIL)                     ; returns NIL - NIL
    +(consp #(1 2 3))                ; returns NIL - array
    +(consp *standard-output*)       ; returns NIL - stream
    +(consp 1.2)                     ; returns NIL - float
    +(consp #'quote)                 ; returns NIL - fsubr
    +(consp 1)                       ; returns NIL - integer
    +(consp object)                  ; returns NIL - object
    +(consp "str")                   ; returns NIL - string
    +(consp #'car)                   ; returns NIL - subr
    +(consp 'a)                      ; returns NIL - symbol
    +
    + +

    Note: When applied to 'consp', +NIL , the empty list, returns +a NIL. NIL +or '() is used in many places as a list-class or atom-class expression. Both +atom +and listp , when applied to +NIL , return + T . If you wish to check for a +list where an empty list is still considered a valid list, use the +listp predicate.

    + +

    See the +consp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/continue.htm b/docsrc/xlisp/xlisp-doc/reference/continue.htm new file mode 100644 index 0000000..44c620e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/continue.htm @@ -0,0 +1,90 @@ +XLISP continue + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    continue

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xldbug.c

    + +

    Syntax

    + +
    +
    (continue)
    +
    + +

    Description

    + +

    The 'continue' function attempts to continue from the +break loop. +This is valid only for cerrors [continuable +errors]. If 'continue' is evaluated while not in a +break loop , an +error is generated:

    + +
    +error: not in a break loop
    +
    + +

    In Nyquist, the error is:

    + +
    +error: this error can't be continued
    +
    + +

    This error does not cause XLISP to go into a break loop. 'continue' never +actually returns a value.

    + +

    Examples

    + +
    +(continue)     ; error: not in a break loop
    +(break "out")  ; break: out
    +(continue)     ; to continue from break loop
    +               ; BREAK returns NIL
    +
    + +

    Keystroke equivalent: In the IBM PC and MS-DOS versions of XLISP, +a 'Ctrl-p' key sequence has the same effect as doing a (continue). On a +Macintosh, this can be accomplished by a pull-down menu or a 'Command-p'. +[I haven't tested this with Nyquist.]

    + +

    See the +continue +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/cos.htm b/docsrc/xlisp/xlisp-doc/reference/cos.htm new file mode 100644 index 0000000..26bd1f3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/cos.htm @@ -0,0 +1,71 @@ +XLISP cos + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    cos

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (cos expr)
    +
    expr - floating point number/expression
    +returns - the cosine of the number
    +
    + +

    Description

    + +

    The 'cos' function returns the cosine of the 'expr'. The 'expr' is +in radians.

    + +

    Examples

    + +
    +(cos 0.0)            ; returns 1
    +(cos (/ 3.14159 2))  ; returns 1.32679e-06 (almost 0)
    +(cos .5)             ; returns 0.877583
    +(cos 0)              ; error: bad integer operation
    +(cos 1.)             ; error: bad integer operation
    +
    + +

    See the +cos +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/decf.htm b/docsrc/xlisp/xlisp-doc/reference/decf.htm new file mode 100644 index 0000000..1714e3f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/decf.htm @@ -0,0 +1,88 @@ +XLISP decf + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    decf

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp macro (closure)
    Source:  -  misc.lsp

    + +

    Syntax

    + +

    + +
    +
    (decf symbol)
    +
    symbol - a symbol with numerical value bound to it
    +returns - the new value of the symbol
    +
    + +

    + +

    In Nyquist, 'decf' is implemented as a Lisp macro:

    + +
    +(defmacro decf (symbol)
    +  `(setf ,symbol (1- ,symbol)))
    +
    + +

    Description

    + +

    The 'decf' macro is used for decrementing a numerical value of a variable. +1 is substracted to the number and the result is stored in the +variable. An error is signalled if the variable doesn't hold a +number.

    + +

    Examples

    + +
    +(setq n 3)    => 3
    +(decf n)      => 2
    +n             => 2
    +(decf n)      => 1
    +
    +(setq n 1.8)  => 1.8
    +(decf n)      => 0.8
    +(decf n)      => -0.2
    +(decf n)      => -1.2
    +n             => -1.2
    +
    +(setq n #\a)  => #\a
    +(decf a)      => error: bad argument type - #\a
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/decrement.htm b/docsrc/xlisp/xlisp-doc/reference/decrement.htm new file mode 100644 index 0000000..e41a3bd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/decrement.htm @@ -0,0 +1,75 @@ +XLISP 1- + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    1−

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (1- expr)
    +
    expr - integer or floating point number/expression
    +returns - the number minus one
    +
    + +

    + +

    Description

    + +

    The '1-' [decrement] function subtracts one from a number +and returns the result.

    + +

    Examples

    + +
    +(1- 1)     => 0
    +(1- 99.6)  => 98.6
    +(1- 1 2)   => error: too many arguments
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/defmacro.htm b/docsrc/xlisp/xlisp-doc/reference/defmacro.htm new file mode 100644 index 0000000..c1dc67d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/defmacro.htm @@ -0,0 +1,142 @@ +XLISP defmacro + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    defmacro

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (defmacro symbol arg-list body)
    +
    symbol - the name of the macro being defined
    +arg-list - a list of the formal arguments to the macro of the form:
    +
    +
    ([arg1 ... ]
    + [&optional oarg1 ... ]
    + [&rest rarg]
    + [&key ... ]
    + [&aux aux1 ... ])
    +
    +body - a series of LISP forms (expressions) that are executed in order.
    +returns - the macro symbol
    +
    + +

    Description

    + +

    'defmacro' defines a macro expansion. When the 'symbol' name of the macro +expansion is encountered [similar to a function invocation], the 'body' of +code that was defined in the 'defmacro' is expanded and replaces the macro +invocation.

    + +

    All of the 'argN' formal arguments that are defined are required to +appear in the invocation of the macro expansion.

    + +

    If there are any +&optional arguments defined, they will +be filled in order.

    + +

    If there is a &rest +argument defined, and all the required formal arguments and +&optional arguments are filled, any and +all further parameters will be passed into the function via the 'rarg' +argument. Note that there can be only one 'rarg' argument for +&rest.

    + +

    If there are insufficient parameters for any of the +&optional or +&rest arguments, they will contain +NIL.

    + +

    The &aux variables are a mechanism +for you to define variables local to the 'defmacro' execution. At the end of +the function execution, these local symbols and their values are are +removed.

    + +

    Examples

    + +
    +(defmacro plus (num1 num2)               ; define PLUS macro
    +  `(+ ,num1 ,num2))                      ;   which is a 2 number add
    +
    +(plus 1 2)                               ; returns 3
    +(setq x 10)                              ; set x to 10
    +(setq y 20)                              ; set y to 20
    +(plus x y)                               ; returns 30
    +
    +(defmacro betterplus (num &rest nlist)   ; define a BETTERPLUS macro
    +  `(+ ,num ,@nlist))                     ;   which can take many numbers
    +
    +(betterplus 1)                           ; returns 1
    +(betterplus 1 2 3)                       ; returns 6
    +(betterplus 1 2 3 4 5)                   ; returns 15
    +
    +(defmacro atest (x &optional y &rest z)  ; define ATEST macro
    +  (princ " x: ") (princ x)               ;    \
    +  (princ " y: ") (princ y)               ;     print out the parameters
    +  (princ " z: ") (princ z) (terpri)      ;    /      (un-evaluated)
    +  `(print (+ ,x ,y ,@z)))                ;   add them together (eval'ed)
    +
    +(atest 1)                                ; prints - x: 1 y: NIL z: NIL
    +                                         ;   error: bad argument type
    +                                         ;   because (+ 1 NIL) isn't valid
    +(atest 1 2)                              ; prints - x: 1 y: 2 z: NIL
    +                                         ;   returns 3
    +(atest 1 2 3)                            ; prints - x: 1 y: 2 z: (3)
    +                                         ;   returns 6
    +(atest 1 2 3 4 5)                        ; prints - x: 1 y: 2 z: (3 4 5)
    +                                         ;   returns 15
    +(setq a 99)                              ; set A to 99
    +(setq b 101)                             ; set B to 101
    +(atest a b)                              ; prints - x: A y: B z: NIL
    +                                         ;   returns 200
    +(atest a b 9 10 11)                      ; prints - x: A y: B z: (9 10 11)
    +                                         ;   returns 230
    +
    + +

    Common Lisp: Common Lisp supports an optional documentation +string as the first form in the 'body' of a 'defmacro' or +defun. XLISP will accept this string +as a valid form, but it will not do anything special with it.

    + +

    See the +defmacro +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/defun.htm b/docsrc/xlisp/xlisp-doc/reference/defun.htm new file mode 100644 index 0000000..aaa97c1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/defun.htm @@ -0,0 +1,134 @@ +XLISP defun + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    defun

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (defun symbol arg-list body)
    +
    symbol - the name of the function being defined
    +arg-list - a list of the formal arguments to the function of the form:
    +
    +
    ([arg1 ... ]
    + [&optional oarg1 ... ]
    + [&rest rarg]
    + [&key ... ]
    + [&aux aux1 ... ])
    +
    +body - a series of LISP forms (expressions) that are executed in order.
    +returns - the function symbol
    +
    + +

    Description

    + +

    The 'defun' special form defines a new function or re-defines an +exisiting function. The last form in 'body' that is evaluated is the value +that is returned when the function is executed.

    + +

    All of the 'argN' formal arguments that are defined are required to +appear in a call to the defined function.

    + +

    If there are any &optional +arguments defined, they will be filled in order.

    + +

    If there is a &rest argument +defined, and all the required formal arguments and +&optional arguments are filled, any +and all further parameters will be passed into the function via the 'rarg' +argument. Note that there can be only one 'rarg' argument for +&rest.

    + +

    If there are insufficient parameters for any of the +&optional or +&rest arguments, they will contain +NIL.

    + +

    The &aux variables are a mechanism +for you to define variables local to the function definition. At the end of +the function execution, these local symbols and their values are are +removed.

    + +

    Examples

    + +
    +(defun my-add                          ; define function MY-ADD
    +  (num1 num2)                          ;   with 2 formal parameters
    +  (+ num1 num2))                       ;   that adds the two paramters
    +
    +(my-add 1 2)                           ; returns 3
    +
    +(defun foo                             ; define function FOO
    +  (a b &optional c d &rest e)          ;   with some of each argument
    +  (print a) (print b)
    +  (print c) (print d)                  ;   print out each
    +  (print e))
    +
    +(foo)                                  ; error: too few arguments
    +(foo 1)                                ; error: too few arguments
    +(foo 1 2)                              ; prints 1 2 NIL NIL NIL
    +(foo 1 2 3)                            ; prints 1 2 3 NIL NIL
    +(foo 1 2 3 4)                          ; prints 1 2 3 4 NIL
    +(foo 1 2 3 4 5)                        ; prints 1 2 3 4 (5)
    +(foo 1 2 3 4 5 6 7 8 9)                ; prints 1 2 3 4 (5 6 7 8 9)
    +
    +(defun my-add                          ; define function MY-ADD
    +  (num1 &rest num-list &aux sum)       ;   with 1 arg, rest, 1 aux var
    +  (setq sum num1)                      ;   clear SUM
    +  (dotimes (i (length num-list) )      ;   loop through rest list
    +    (setq sum (+ sum (car num-list)))  ;      add the number to sum
    +    (setq num-list (cdr num-list)))    ;      and remove num from list
    +  sum)                                 ;   return sum when finished
    +
    +(my-add 1 2 3 4)                       ; returns 10
    +(my-add 5 5 5 5 5)                     ; returns 25
    +
    + +

    Common Lisp: Common Lisp supports an optional documentation +string as the first form in the 'body' of a +defmacro or 'defun'. XLISP will accept this +string as a valid form, but it will not do anything special with it.

    + +

    See the +defun +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/delete-if-not.htm b/docsrc/xlisp/xlisp-doc/reference/delete-if-not.htm new file mode 100644 index 0000000..7aed3a8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/delete-if-not.htm @@ -0,0 +1,107 @@ +XLISP delete-if-not + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    delete-if-not

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (delete-if-not test list)
    +
    test - the test function to be performed
    +list - the list to delete from
    +returns - the list with non-matching elements deleted
    +
    + +

    Description

    + +

    The 'delete-if-not' function destructively modifies the 'list' by +removing the elements of the list that fail the 'test'. The destructive +aspect of this operation means that the actual symbol value is used in the +list-modifying operations, not a copy.

    + +

    'list' must evaluate to a valid list. An atom for 'list' will result in +an error:

    + +
    +error: bad argument type
    +
    + +

    Having NIL for 'list' will return a +NIL as the result.

    + +

    Examples

    + +

    Caution: there's a bug:

    + +
    +(setq mylist '(1 2 3 4 5 6 7 8))             ; set up a list of numbers
    +(delete-if-not 'evenp mylist)                ; returns (2 4 6 8)
    +(print mylist)                               ; prints  (1 2 4 6 8) <-BUG!
    +
    +(setq mylist '(1 2 3 4 5 6 7 8))             ; set up the same list again
    +(setq mylist (delete-if-not 'evenp mylist))  ; returns (3 5 7)
    +(print mylist)                               ; prints  (3 5 7) <-OK
    +
    +(setq mylist '(1 2 3 4 5 6 7 8))             ; ... again ...
    +(delete-if-not 'oddp mylist)                 ; returns (1 3 5 7)
    +(print mylist)                               ; prints  (1 3 5 7) <-OK
    +
    +(setq mylist '(1 2 3 4 5 6 7 8))             ; ... and again ...
    +(setq mylist (delete-if-not 'oddp mylist))   ; returns (1 3 5 7)
    +(print mylist)                               ; prints  (1 3 5 7) <-OK
    +
    + +

    Bug: 'delete-if-not' will return the proper value, but it does not +always properly modify the symbol containing the value. This seems to be +true if the first element of the 'list' fails the test [and should be +deleted]. It's always better to use 'delete-if-not' together with +setq or +setf as shown in example 2 +and 4.

    + +

    Common Lisp: XLISP does not support the ':from-end', ':start', +':end', ':count' and ':key' keywords which Common Lisp does.

    + +

    See the +delete-if-not +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/delete-if.htm b/docsrc/xlisp/xlisp-doc/reference/delete-if.htm new file mode 100644 index 0000000..f0d0a1d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/delete-if.htm @@ -0,0 +1,110 @@ +XLISP delete-if + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    delete-if

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (delete-if test list)
    +
    test - the test function to be performed
    +list - the list to delete from
    +returns - the list with matching elements deleted
    +
    + +

    Description

    + +

    The 'delete-if' function destructively modifies the 'list' by removing +the elements of the list that pass the 'test'. The destructive aspect of +this operation means that the actual symbol value is used in the +list-modifying operations, not a copy.

    + +

    'list' must evaluate to a valid list. An atom for 'list' will result in +an error:

    + +
    +error: bad argument type
    +
    + +

    Having NIL for 'list' will return a +NIL as the result.

    + +

    Examples

    + +

    Caution: there's a bug:

    + +
    +(setq mylist '(1 2 3 4 5 6 7 8))         ; set up a list starting of numbers
    +(delete-if 'oddp mylist)                 ; returns (2 4 6)
    +(print mylist)                           ; prints  (1 2 4 6) <-BUG!
    +
    +(setq mylist '(1 2 3 4 5 6 7 8))         ; set up the same list again
    +(setq mylist (delete-if 'oddp mylist))   ; returns (2 4 6)
    +(print mylist)                           ; prints  (2 4 6) <-OK
    +
    +(setq mylist '(1 2 3 4 5 6 7 8))         ; ... again ...
    +(delete-if 'evenp mylist)                ; returns (1 3 5 7)
    +(print mylist)                           ; prints  (1 3 5 7) <-OK
    +
    +(setq mylist '(1 2 3 4 5 6 7 8))         ; ... and again ...
    +(setq mylist (delete-if 'evenp mylist))  ; returns (1 3 5 7)
    +(print mylist)                           ; prints  (1 3 5 7) <-OK
    +
    + +

    Bug: 'delete-if' will return the proper value, but it does not +always properly modify the symbol containing the value. This seems to be +true if the first element of the 'list' passes the test [and should be +deleted]. It's always better to use 'delete-if' together with +setq or +setf as shown in example 2 +and 4.

    + +

    Note: This bug can be reproduced with Nyquist 2.36 [in June 2007], +so please take care.

    + +

    Common Lisp: XLISP does not support the ':from-end', ':start', +':end', ':count' and ':key' keywords which Common LISP does.

    + +

    See the +delete-if +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/delete.htm b/docsrc/xlisp/xlisp-doc/reference/delete.htm new file mode 100644 index 0000000..71baf5d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/delete.htm @@ -0,0 +1,99 @@ +XLISP delete + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    delete

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (delete expr list [{:test | :test-not} test])
    +
    expr - the expression to delete from list
    +list - the list to destructively modify
    +test - optional test function (default is eql)
    +returns - the list with the matching expressions deleted
    +
    + +

    Description

    + +

    The 'delete' function destructively modifies the 'list' by removing the +'expr'. The destructive aspect of this operation means that the actual +symbol value is used in the list-modifying operations, not a copy. If 'expr' +appears multiple times in the 'list', all occurances will be removed.

    + +

    'list' must evaluate to a valid list. An atom for 'list' will result in +an error:

    + +
    +error: bad argument type
    +
    + +

    Having NIL for 'list' will return a +NIL as the result. You may specify your own +test with the ':test' and ':test-not' keywords.

    + +

    Examples

    + +
    +(delete 'b NIL)                          ; returns NIL
    +(delete 'b '(a b b c b))                 ; returns (A C)
    +(setq a '(1 2 3)) (setq b a)             ; set up A and B
    +(delete '2 a)                            ; returns (1 3)
    +(print a)                                ; prints (1 3)    A IS MODIFIED!
    +(print b)                                ; prints (1 3)    B IS MODIFIED!
    +(delete '(b) '((a)(b)(c)))               ; returns ((A) (B) (C))
    +                                         ;   EQL doesn't work on lists
    +(delete '(b) '((a)(b)(c)) :test 'equal)  ; returns ((A) (C))
    +
    + +

    Note: The 'delete' function can work with a list or string as the +'expr'. However, the default eql test does +not work with lists or strings, only symbols and numbers. To make this work, +you need to use the ':test' keyword along with +equal for 'test'.

    + +

    Common Lisp: XLISP does not support the ':from-end', ':start', +':end', ':count' and ':key' keywords which Common Lisp does.

    + +

    See the +delete +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/digit-char-p.htm b/docsrc/xlisp/xlisp-doc/reference/digit-char-p.htm new file mode 100644 index 0000000..99930d2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/digit-char-p.htm @@ -0,0 +1,87 @@ +XLISP digit-char-p + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    digit-char-p

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (digit-char-p char)
    +
    char - a character expression
    +returns - the digit weight if character is a digit, +NIL otherwise
    +
    + +

    Description

    + +

    The 'digit-char-p' predicate function checks if the 'char' expression is +a numeric digit. If 'char' is numeric digit, the equivalent integer value +is returned, otherwise a NIL is +returned. Decimal digits are '0' [ASCII decimal value 48] +through '9' [ASCII decimal value 57].

    + +

    Examples

    + +
    +(digit-char-p #\0)   ; returns 0
    +(digit-char-p #\9)   ; returns 9
    +(digit-char-p #\A)   ; returns NIL
    +(digit-char-p #\a)   ; returns NIL
    +(digit-char-p #\.)   ; returns NIL
    +(digit-char-p #\-)   ; returns NIL
    +(digit-char-p #\+)   ; returns NIL
    +
    + +

    Note: Other non-digit characters used in numbers are NOT included: +plus [+], minus [-], exponent [e or E] and decimal point +[.].

    + +

    Common Lisp: Common Lisp supports the use of an optional radix +parameter. This option specifies numeric base. This allows the +'digit-char-p' to function properly for hexadecimal digits [for example]. +Common LISP supports up to base 36 radix systems. XLISP does not support +this radix parameter.

    + +

    See the +digit-char-p +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/digit-char.htm b/docsrc/xlisp/xlisp-doc/reference/digit-char.htm new file mode 100644 index 0000000..5d40c74 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/digit-char.htm @@ -0,0 +1,79 @@ +XLISP digit-char + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    digit-char

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (digit-char int)
    +
    int - an integer expression
    +returns - the digit character or NIL
    +
    + +

    Description

    + +

    The 'digit-char' function takes an integer expression 'int' and converts +it into a decimal digit character. So, an integer value of '0' produces the +character '#\0'. An integer value of '1' produces the character '#\1' and so +on. If a valid character can be produce it is returned, otherwise a +NIL is returned.

    + +

    Examples

    + +
    +(digit-char 0)    ; returns #\0
    +(digit-char 9)    ; returns #\9
    +(digit-char 10)   ; returns NIL
    +
    + +

    Common Lisp: Common Lisp supports the use of an optional radix +parameter. This option specifies numeric base. This allows the 'digit-char' +to function properly for hexadecimal digits [for example]. Common Lisp +supports up to base 36 radix systems. XLISP does not support +this radix parameter. Common Lisp also supports a font parameter which XLISP +does not.

    + +

    See the +digit-char +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/division.htm b/docsrc/xlisp/xlisp-doc/reference/division.htm new file mode 100644 index 0000000..2fae40c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/division.htm @@ -0,0 +1,101 @@ +XLISP / + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    /

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (/ expr1 ...)
    +
    exprN - integer or floating point number/expression
    +returns - the result of the division
    +
    + +

    + +

    Description

    + +

    The '/' function divides the first number given by the rest of the +numbers and returns the result. If all the expressions are integers, the +division is integer division. If any expression is a floating point number, +then the division will be floating point division.

    + +

    Examples

    + +
    +(/ 1)               => 1
    +(/ 1 2)             => 0          ; integer division
    +(float (/ 1 2))     => 0          ; integer division
    +(/ (float 1) 2)     => 0.5        ; type contagion
    +(/ 1 1.0 2)         => 0.5        ; type contagion
    +(/ (float 1) 2 3)   => 0.166667   ; type contagion
    +(/ 1 1.0 2 3 4)     => 0.0416667  ; type contagion
    +
    + +
    +> (print (+ 1 2 (* 3.5 (/ 3.9 1.45))))
    +12.4138
    +12.4138
    +
    + +

    See  + , + * , +float, print. +XLISP first prints the value on the screen, the second number is the +return value.

    + +

    In XLISP, the type contagion depends on the order of +occurrence:

    + +
    +(/ 1 2 1.0)  => 0    ; because (/ 1 2)   => 0   and (/ 0 1.0) => 0.0
    +(/ 1.0 2 1)  => 0.5  ; because (/ 1.0 2) => 0.5 and (/ 0.5 1) => 0.5
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/do-star.htm b/docsrc/xlisp/xlisp-doc/reference/do-star.htm new file mode 100644 index 0000000..7ff4415 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/do-star.htm @@ -0,0 +1,144 @@ +XLISP do* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    do*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (do* ([binding ... ]) (test-expr [result]) [expr ... ])
    +
    binding - a variable binding which is can take one of the following forms:
    +
    symbol
    +(symbol init-expr [step-expr]) +
    symbol - a symbol
    +init-expr - an initialization expression for symbol
    +step-expr - an expression with that symbol is updated +at the end of each loop
    +test-expr - iteration ends when this expression returns a +non-NIL value
    +result - an optional expression for the returned result
    +expr - expressions comprising the body of the loop which may +contain returns, +gos or tags for +go
    +returns - the value of the last result expression
    +
    + +

    Description

    + +

    The 'do*' special form is basically a 'while' looping construct that +contains symbols [with optional initializations and updates], a loop test +[with an optional return value] and a block of code [expressions] to +evaluate. The 'do*' form evaluates its initializations and updates in +sequential order [as opposed to do which +doesn't]. The sequence of these events is:

    + +
    +  init-expr execution
    +  while test-expr do
    +    loop code execution
    +    step-expr execution
    +  end-while
    +  return result
    +
    + +

    The first form after the 'do*' is the 'binding' form. It contains a +series of 'symbols' or 'bindings'. The 'binding' is a 'symbol' followed by +an initialization expression 'init-expr' and an optional 'step-expr'. If +there is no 'init-expr', the 'symbol' will be initialized to +NIL. There is no specification as to the +order of execution of the bindings or the step expressions, except that they +happen all together.

    + +

    The 'do*' form will go through and create and initialize the symbols. +This is followed by evaluating the 'test-expr'. If 'test-expr' returns a +non-NIL value, the loop will terminate. If +'test-expr' returns a NIL value then the +'do*' will sequentially execute the 'exprs'. After execution of the loop +'exprs', the 'symbols' are set to the step-exprs' [if the 'step-exprs' +exist]. Then, the 'test-expr' is re-evaluated, and so on. The value of the +'result' expression is evaluated and returned. If no 'result' is specified, +NIL is returned. When the 'do*' is finished +execution, the 'symbols' that were defined will no longer exist or retain +their values.

    + +

    Examples

    + +
    +(do                                 ; DO example - won't work
    +  ((i 0)                            ;   var I=0
    +   (j i))                           ;   var J=I (won't work)
    +  ((eql i j) "done")                ;   test and result
    +  (print "looping"))                ; error: unbound variable - I
    +
    +(do*                                ; DO* example - will work
    +  ((i 0)                            ;   var I=0
    +   (j i))                           ;   var J=I (proper exec. order)
    +  ((eql i j) "done")                ;   test and result
    +  (print "looping"))                ;   returns "done"
    +
    +(do* (i)                            ; DO* loop with var I
    +  ((eql i 0) "done")                ;   test and result
    +  (print i) (setq i 0) (print i))   ;   prints NIL 0
    +                                    ;   returns "done"
    +
    +(do* (i)                            ; DO* loop with var I
    +  ((eql i 0))                       ;   test but no result
    +  (print i) (setq i 0) (print i))   ;   prints NIL 0
    +                                    ;   returns NIL
    +
    +(do*                                ; DO* loop
    +  ((i 0 (setq i (1+ i)))            ;   var I=0  increment by 1
    +   (j 10 (setq j (1- j))))          ;   var J=10 decrement by 1
    +  ((eql i j)  "met in the middle")  ;   test and result
    +  (princ i) (princ " ")             ;   prints  0 10
    +  (princ j) (terpri))               ;           1 9
    +                                    ;           2 8
    +                                    ;           3 7
    +                                    ;           4 6
    +                                    ;   returns "met in the middle"
    +
    + +

    See the +do* +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/do.htm b/docsrc/xlisp/xlisp-doc/reference/do.htm new file mode 100644 index 0000000..7b1258b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/do.htm @@ -0,0 +1,133 @@ +XLISP do + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    do

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (do ([binding ... ]) (test-expr [result]) [expr ... ])
    +
    binding - a variable binding which is can take one of the following forms:
    +
    symbol
    +(symbol init-expr [step-expr]) +
    symbol - a symbol
    +init-expr - an initialization expression for symbol
    +step-expr - an expression with that symbol is updated +at the end of each loop
    +test-expr - iteration ends when this expression returns a +non-NIL value
    +result - an optional expression for the returned result
    +expr - expressions comprising the body of the loop which may +contain returns, +gos or tags for +go
    +returns - the value of the last result expression
    +
    + +

    Description

    + +

    The 'do' special form is basically a 'while' looping construct that +contains symbols [with optional initializations and updates], a loop test +[with an optional return value] and a block of code [expressions] to +evaluate. The 'do' form evaluates its initializations and updates in no +specified order [as opposed to do* which +does it in sequential order]. The sequence of these events is:

    + +
    +  init-expr execution
    +  while not test-expr do
    +    loop code execution
    +    step-expr execution
    +  end-while
    +  return result
    +
    + + +

    The first form after the 'do' is the 'binding' form. It contains a +series of 'symbols' or 'bindings'. The 'binding' is a 'symbol' followed by +an initialization expression 'init-expr' and an optional 'step-expr'. If +there is no 'init-expr', the 'symbol' will be initialized to +NIL. There is no specification as to the +order of execution of the bindings or the step expressions, except that +they happen all together.

    + +

    The 'do' form will go through and create and initialize the symbols. +This is followed by evaluating the 'test-expr'. If 'test-expr' returns a +non-NIL value, the loop will terminate. +If 'test-expr' returns a NIL value then +the 'do' will sequentially execute the 'exprs'. After execution of the loop +'exprs', the 'symbols' are set to the 'step-exprs' [if the 'step-exprs' +exist]. Then, the 'test-expr' is re-evaluated, and so on. The value of the +'result' expression is evaluated and returned. If no 'result' is specified, +NIL is returned. When the 'do' is finished +execution, the 'symbol's that were defined will no longer exist or retain +their values.

    + +

    Examples

    + +
    +(do (i)                              ; DO loop with var I
    +  ((eql i 0) "done")                 ;   test and result
    +  (print i) (setq i 0) (print i))    ;   prints NIL 0
    +                                     ;   returns "done"
    +
    +(do (i)                              ; DO loop with var I
    +  ((eql i 0))                        ;   test but no result
    +  (print i) (setq i 0) (print i))    ;   prints NIL 0
    +                                     ;   returns NIL
    +
    +(do                                  ; DO loop
    +   ((i 0 (setq i (1+ i)))            ;   var I=0  increment by 1
    +    (j 10 (setq j (1- j))))          ;   var J=10 decrement by 1
    +   ((eql i j)  "met in the middle")  ;   test and result
    +   (princ i) (princ " ")             ;   prints  0 10
    +   (princ j) (terpri))               ;           1 9
    +                                     ;           2 8
    +                                     ;           3 7
    +                                     ;           4 6
    +                                     ;   returns "met in the middle"
    +
    + +

    See the +do +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/dolist.htm b/docsrc/xlisp/xlisp-doc/reference/dolist.htm new file mode 100644 index 0000000..ab6c637 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/dolist.htm @@ -0,0 +1,111 @@ +XLISP dolist + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    dolist

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (dolist (symbol list-expr [result]) [expr ... ])
    +
    symbol - a symbol
    +list-expr - a list expression
    +result - an optional expression for the returned result
    +expr - expressions comprising the body of the loop which may +contain returns, +gos or tags for +go
    +returns - the return value of the result expression or +NIL
    +
    + +

    Description

    + +

    The 'dolist' special form is basically a list-oriented 'for' looping +construct that contains a loop 'symbol', a 'list-expr' to draw values from, +an optional 'return' value and a block of code [expressions] to evaluate. +The sequence of execution is:

    + +
    +  symbol    := CAR of list-expr
    +  temp-list := CDR of list-expr
    +  while  temp-list is not empty
    +    loop code execution
    +    symbol    := CAR of temp-list
    +    temp-list := CDR of temp-list
    +  end-while
    +  return result
    +
    + +

    The main loop 'symbol' will take on successive values from 'list-expr'. +The 'dolist' form will go through and create and initialize the 'symbol'. +After execution of the loop 'exprs', the 'symbol' is set to the next value +in the 'list-expr'. This continues until the 'list-expr' has been exhausted. +The value of the 'result' expression is evaluated and returned. If no +'result' is specified, NIL is returned. +When the 'dolist' is finished execution, the 'symbol' that was defined will +no longer exist or retain its value. If the 'list-expr' is an empty list, +then no loop execution takes place and the 'result' is returned.

    + +

    Examples

    + +
    +  (dolist (i () "done")        ; DOLIST with I loop variable
    +          (print "here"))      ;   an empty list
    +                               ;   and a return value
    +                               ;   returns "done"
    +
    +  (dolist (x '(a b c) "fini")  ; DOLIST with X loop variable
    +          (princ x))           ;   a list with (A B C)
    +                               ;   and a return value
    +                               ;   prints  ABC   returns "fini"
    +
    +  (dolist (y '(1 2 3))         ; DOLIST with Y loop variable
    +          (princ (* y y)))     ;   a list with (1 2 3)
    +                               ;   and no return value
    +                               ;   prints  149   returns NIL
    +                               ;   returns "met in the middle"
    +
    + +

    See the +dolist +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/dotimes.htm b/docsrc/xlisp/xlisp-doc/reference/dotimes.htm new file mode 100644 index 0000000..bcbaf82 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/dotimes.htm @@ -0,0 +1,101 @@ +XLISP dotimes + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    dotimes

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (dotimes (symbol end-expr [result]) [expr ... ])
    +
    symbol - a symbol
    +end-expr - an integer expression
    +result - an optional expression for the returned result
    +expr - expressions comprising the body of the loop which may +contain returns, +gos or tags for +go
    +returns - the return value of the result expression or +NIL
    +
    + +

    Description

    + +

    The 'dotimes' special form is basically a 'for' looping construct that +contains a loop 'symbol', an 'end-expr' to specify the final value for +'symbol', an optional 'return' value and a block of code [expressions] to +evaluate. The sequence of execution is:

    + + +
    +  symbol := 0
    +  while  symbol value is not equal to end-expr value
    +    loop code execution
    +    symbol := symbol + 1
    +  end-while
    +  return result
    +
    + +

    The main loop 'symbol' will take on successive values from zero to +('end-expr' - 1). The 'dotimes' form will go through and create +and initialize the 'symbol' to zero. After execution of the loop 'exprs', +the 'symbol' value is incremented. This continues until the 'symbol' value +is equal to 'end-expr'. The value of the 'result' expression is evaluated +and returned. If no 'result' is specified, +NIL is returned. When the 'dotimes' is +finished execution, the 'symbol' that was defined will no longer exist or +retain its value. If the 'end-expr' is zero or less, then there will be no +execution of the loop body's code.

    + +

    Examples

    + +
    +(dotimes (i 4 "done") (princ i))  ; prints 0123 returns "done"
    +(dotimes (i 4) (princ i))         ; prints 0123 returns NIL
    +(dotimes (i 1) (princ i))         ; prints 0    returns NIL
    +(dotimes (i 0) (princ i))         ; returns NIL
    +(dotimes (i -9) (princ i))        ; returns NIL
    +
    + +

    See the +dotimes +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/dribble.htm b/docsrc/xlisp/xlisp-doc/reference/dribble.htm new file mode 100644 index 0000000..4fd0252 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/dribble.htm @@ -0,0 +1,82 @@ +XLISP dribble + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    dribble

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlisp.c, xlsys.c, msstuff.c

    + +

    Syntax

    + +
    +
    (dribble [file-str])
    +
    file-str - a string expression for a file name
    +returns -  T  if the transcript +is opened, NIL if it is closed
    +
    + +

    Description

    + +

    The 'dribble' function, when called with a 'file-str' argument, opens the +specified file and records a transcript of the XLISP session. When 'dribble' +is called with no 'file-str' argument, it closes the current transcript file +[if any]. 'dribble' will return + T  if the specified 'file-str' +was successfully opened. It will return a +NIL if the 'file-str' was not opened +successfully or if 'dribble' was evaluated to close a transcript.

    + +

    Examples

    + +
    +(dribble "my-trans-file")  ; open file "my-trans-file"
    +                           ;   for a session transcript
    +(+ 2 2)                                 
    +(dribble)                  ; close the transcript
    +
    + +

    Note: It is also possible to start a transcript when invoking +XLISP. To start XLISP with a transcript file of 'myfile' type in +'xlisp -tmyfile'. [I haven't tested this with +Nyquist.]

    + +

    See the +dribble +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/echoenabled.htm b/docsrc/xlisp/xlisp-doc/reference/echoenabled.htm new file mode 100644 index 0000000..08fa47e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/echoenabled.htm @@ -0,0 +1,68 @@ +XLISP echoenabled + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    echoenabled

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sys/unix/osstuff.c, sys/win/wingui/winguistuff.c, sys/win/msvc/winstuff.c

    + +

    Syntax

    + +
    +
    (echoenabled flag)
    +
    flag -  T  to enable echo, NIL to disable
    +returns - NIL
    +
    + +

    Description

    + +

    The 'echoenabled' function turns console input echoing on or off.

    + +

    Note: The 'echoenabled' function is only implemented under Linux +and Mac OS X. If Nyquist I/O is redirected through +pipes, the Windows version does not echo the input, but the Linux and Mac +versions do. You can turn off echoing with this +function. Under windows it is defined to do nothing.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/endp.htm b/docsrc/xlisp/xlisp-doc/reference/endp.htm new file mode 100644 index 0000000..dd7587f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/endp.htm @@ -0,0 +1,86 @@ +XLISP endp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    endp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (endp list)
    +
    list - the list to check
    +returns -  T  if the list is +empty, NIL otherwise
    +
    + +

    Description

    + +

    The 'endp' predicate function checks to see if 'list' is an empty list. + T  is returned if the list is +empty, NIL is returned if the list is +not empty. The 'list' has to be a valid list. An error is returned if it +is not a list:

    + +
    +error: bad argument type
    +
    + +

    Examples

    + +
    +(endp '())       ; returns T - empty list
    +(endp ())        ; returns T - still empty
    +(endp '(a b c))  ; returns NIL
    +(setq a NIL)     ; set up a variable
    +(endp a)         ; returns T - value = empty list
    +(endp "a")       ; error: bad argument type - "a"
    +(endp 'a)        ; error: bad argument type - A
    +
    + +

    Note: The 'endp' predicate is different from the +null and +not predicates in that it requires a +valid list.

    + +

    See the +endp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/eq.htm b/docsrc/xlisp/xlisp-doc/reference/eq.htm new file mode 100644 index 0000000..48253ea --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/eq.htm @@ -0,0 +1,93 @@ +XLISP eq + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    eq

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xllist.c, xlsubr.c

    + +

    Syntax

    + +

    + +
    +
    (eq expr1 expr2)
    +
    exprN - arbitrary Lisp expressions
    +returns -  T  if the expressions +eveluate to the same internal value, NIL +otherwise
    +
    + +

    + +

    Description

    + +

    Two expressions are 'eq' if the expressions are identical. The 'eq' +function tests if the results of the evaluated expressions point to +the same memory location.  T  is returned if +both expressions evaluate to exactly the same internal value, +NIL is returned otherwise.

    + +

    Integer numbers being  =  are +'eq' as long as not stored in a CPU register, so the +eql function is recommended for testing integers. Also +note that arrays, floating-point numbers, lists, and strings +are only 'eq' if they are bound as variable values to the same symbol.

    + +

    Examples

    + +
    +(eq 'a 'a)          => T
    +(eq 1 1)            => T or NIL
    +(eq 1 1.0)          => NIL
    +(eq 1.0 1.0)        => NIL
    +(eq "a" "a")        => NIL
    +(eq '(a b) '(a b))  => NIL
    +(eq 'a 34)          => NIL
    +
    +(setq a '(a b))     ; set value of A to (A B)
    +(setq b a)          ; set B to point to A's value
    +(setq c '(a b))     ; set value of C to different (A B)
    +(eq a b)            => T
    +(eq a c)            => NIL
    +
    + +

    See also eql, equal, +cl:equalp.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/eql.htm b/docsrc/xlisp/xlisp-doc/reference/eql.htm new file mode 100644 index 0000000..8be4067 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/eql.htm @@ -0,0 +1,99 @@ +XLISP eql + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    eql

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xllist.c, xlsubr.c

    + +

    Syntax

    + +

    + +
    +
    (eql expr1 expr2)
    +
    expr1 - the first expression to compare
    +expr2 - the second expression to compare
    +returns -  T  if the expressions have the +same symbolic or numerical value, NIL otherwise
    +
    + +

    + +

    Description

    + +

    Two expressions are 'eql':

    + +
      + +
    • If the expressions are eq.

    • + +
    • If two numbers of the same type +are  = .

    • + +
    • If two characters +are char=.

    • + +
    + +

    In all other cases 'eql' returns NIL. +Note that arrays, lists, and strings are only 'eql' if they +are eq.

    + +

    Examples

    + +
    +(eql 'a 'a)          => T
    +(eql 1 1)            => T
    +(eql 1 1.0)          => NIL
    +(eql 1.0 1.0)        => T
    +(eql "a" "a")        => NIL
    +(eql '(a b) '(a b))  => NIL
    +(eql 'a 34)          => NIL
    +
    +(setq a '(a b))      ; set value of A to (A B)
    +(setq b a)           ; set B to point to A's value
    +(setq c '(a b))      ; set value of C to different (A B)
    +(eql a b)            => T
    +(eql a c)            => NIL
    +
    + +

    See also eq, equal, +cl:equalp.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/equal.htm b/docsrc/xlisp/xlisp-doc/reference/equal.htm new file mode 100644 index 0000000..8eceaad --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/equal.htm @@ -0,0 +1,111 @@ +XLISP equal + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    equal

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xllist.c, xlsubr.c

    + +

    Syntax

    + +

    + +
    +
    (equal expr1 expr2)
    +
    exprN - arbitrary Lisp expressions
    +returns -  T  if the expressions +are structurally equivalent, NIL otherwise
    +
    + +

    + +

    Description

    + +

    Two expressions are 'equal':

    + +
      + +
    • If the expressions +are eql.

    • + +
    • If two strings +are string=.

    • + +
    • If the two cars in conses are +'equal' and the two cdrs in +conses are 'equal'.

    • + +
    + +

    In all other cases 'equal' +returns NIL. Note that arrays are only +'equal' if they are eq.

    + +

    A way to view 'equal' is that if 'expr1' and 'expr2' were printed +[via print or +princ] and they look the same, +then 'equal' will return  T .

    + +

    Examples

    + +
    +(equal 'a 'a)          => T
    +(equal 1 1)            => T
    +(equal 1 1.0)          => NIL  ; different number types
    +(equal 1.0 1.0)        => T
    +(equal "a" "a")        => T
    +(equal '(a b) '(a b))  => T
    +(equal 'a 34)          => NIL
    +
    +(setq a '(a b))        ; set value of A to (A B)
    +(setq b a)             ; set B to point to A's value
    +(setq c '(a b))        ; set value of C to different (A B)
    +(equal a b)            => T
    +(equal a c)            => T
    +
    +(equal '(a b) '(A B))  => T
    +(equal '(a b) '(c d))  => NIL
    +
    +(equal "a" "A")        => NIL
    +(equal "abc" "abcD")   => NIL
    +
    + +

    See also eq, eql, +cl:equalp.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/error.htm b/docsrc/xlisp/xlisp-doc/reference/error.htm new file mode 100644 index 0000000..c96b663 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/error.htm @@ -0,0 +1,161 @@ +XLISP error + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    error, cerror

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xldbug.c

    + +

    Syntax

    + +

    + +
    +
    (error err-msg [arg])
    +
    err-msg - a string expression for the error message
    +arg - an optional argument expression, printed after the error message
    +returns - never returns
    +
    + +
    +
    (cerror cont-msg err-msg [arg])
    +
    cont-msg - a string expression for the continue message
    +err-msg - a string expression for the error message
    +arg - an optional argument expression, printed after the error message
    +returns - NIL when continued from the +Break Loop
    +
    + +

    + +

    Description

    + +

    The 'error' function allows the generation of a +non-correctable error. A non-correctable error +requires evaluation of a clean-up or +top-level function from within the +XLISP Break Loop +to return to normal execution. The form of the message +generated is:

    + +
    +error: err-msg - arg
    +
    + +

    If a continue function is evaluated within the +Break Loop, then a +an error message is generated:

    + +
    +error: this error can't be continued
    +
    + +

    There is no return from the 'error' function.

    + +

    The 'cerror' function allows the generation of a correctable error. +A correctable error can be corrected by some action +within the XLISP Break +Loop. The form of the message generated is:

    + +
    +error: err-msg - arg
    +if continued: cont-msg
    +
    + +

    In the +Break Loop, +forms can be evaluated to correct the error. If a +continue function is evaluated within the +Break Loop, then +NIL is returned from 'cerror'. If desired, the +clean-up and +top-level forms may be evaluated +to abort out of the +Break Loop.

    + +

    + +

    Note: The *breakenable* +variable needs to be non-NIL for 'error', +'cerror' and system errors to be caught by the Nyquist/XLISP +Break Loop.

    + +

    + +

    Examples

    + +

    Example of a non-correctable error:

    + +
    +> (error "invalid argument" "arg")
    +error: invalid argument - "arg"
    +
    +1> (continue)   ; the 1 before the > indicates a break loop
    +error: this error can't be continued
    +
    +1> (clean-up)
    +[ back to previous break level ]
    +
    +>               ; no break loop any longer
    +
    + +

    Example of system generated correctable error:

    + +
    +> (symbol-value 'f)
    +error: unbound variable - F
    +if continued: try evaluating symbol again
    +
    +1> (setq f 123)   ; the 1 before the > indicates a break loop
    +123               ; return value of (setq f 123)
    +
    +1> (continue)
    +123               ; return value of (symbol-value 'f)
    +
    +>                 ; no break loop any longer
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/errset.htm b/docsrc/xlisp/xlisp-doc/reference/errset.htm new file mode 100644 index 0000000..b2094c8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/errset.htm @@ -0,0 +1,117 @@ +XLISP errset + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    errset

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (errset expr [print-flag])
    +
    expr - an expression to be evaluated
    +print-flag - an optional expression +[NIL or +non-NIL]
    +returns - the value of the last expression +consed with +NIL , or +NIL on error
    +
    + +

    Description

    + +

    The 'errset' special form is a mechanism that allows the trapping of +errors within the execution of 'expr'. +*breakenable* must be set to +NIL for the 'errset' form to function. If +*breakenable* is +non-NIL , the normal break +loop will handle the error. For 'errset', if no error occurs within 'expr', +the value of the last expression is consed +with NIL. If an error occurs within 'expr', +the error is caught by 'errset' and a NIL +is returned from 'errset'. If 'print-flag' is +NIL , the error message +normally generated by 'expr' will not be printed. If 'print-flag' is +non-NIL or not present in the 'errset' +form, the error message will be printed.

    + +

    Errors from error and +cerror and system errors +will be handled by 'errset'. Note that the +cerror message will only include +the error message portion, not the +continue message portion. +break is not intercepted by 'errset'.

    + +

    Examples

    + +
    +(setq *breakenable* nil)          ; do not enter the break-loop on errors
    +(errset (error "hi" "ho"))        ; prints  error: hi - "ho" returns NIL
    +(errset (cerror "hi" "ho" "he"))  ; prints  error: ho - "he" returns NIL
    +(errset (error "hey" "ho") NIL)   ; returns NIL
    +(errset (break "hey"))            ; break: hey - if continued: return from BREAK
    +(continue)                        ; [ continue from break loop ]
    +(errset (+ 1 5))                  ; returns (6)
    +(errset (+ 1 "a") NIL)            ; returns NIL
    +(setq *breakenable* t)            ; re-enable the break-loop on errors
    +
    + +

    How to keep XLISP from signalling an error:

    + +
    +(setq *breakenable* nil)
    +(errset expression-causing-an-error t)  ; print the error message
    +(errset expression-causing-an-error)    ; do NOT print the error message
    +
    + +

    Note: Be sure to set +*breakenable* to +NIL before using 'errset' and to +non-NIL after using 'errset'. If you don't +reset *breakenable* , no +errors will be reported.

    + +

    See the +errset +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/eval.htm b/docsrc/xlisp/xlisp-doc/reference/eval.htm new file mode 100644 index 0000000..9a5c69f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/eval.htm @@ -0,0 +1,79 @@ +XLISP eval + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    eval

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xleval.c

    + +

    Syntax

    + +
    +
    (eval expression)
    +
    expression - an arbitrary expression
    +returns - the result of evaluating the expression
    +
    + +

    Description

    + +

    The 'eval' function evaluates the 'expression' and returns the resulting +value.

    + +

    Examples

    + +
    +(eval '(+ 2 2))            ; returns 4
    +(eval (cons '+ '(2 2 2)))  ; returns 6
    +(eval (list '+ '2 '3 ))    ; returns 5
    +
    +(setq a 10)                ; set up A with value 10
    +(setq b 220)               ; set up B with value 220
    +
    +(eval (list '+ a b ))      ; returns 230 because
    +                           ;   (list '+ a b) => '(+ 10 220)
    +
    +(eval (list '+ 'a b))      ; returns 230 because
    +                           ;   (list '+ 'a b) => '(+ A 220)
    +                           ;   and A has the value 10
    +
    + +

    See the +eval +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/evalhook.htm b/docsrc/xlisp/xlisp-doc/reference/evalhook.htm new file mode 100644 index 0000000..86588d0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/evalhook.htm @@ -0,0 +1,142 @@ +XLISP evalhook + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    evalhook

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xleval.c

    + +

    Syntax

    + +
    +
    (evalhook expr eval-expr apply-expr [env])
    +
    expr - an expression to evaluate
    +eval-expr - an expression for the evaluation routine
    +apply-expr - an expression for +apply [not used]
    +env - an environment expression, default is +NIL
    +returns - the result of evaluating the expression
    +
    + +

    Description

    + +

    The 'evalhook' function is a function that performs evaluation. +The routine specified by 'eval-expr' is called with the 'expr' and 'env' +parameters. If 'eval-expr' is +NIL , then the normal system +evaluator is called. The 'apply-hook' is a dummy parameter that is not used +in the current XLISP system. The 'expr' contains the expression to be +evaluated. If the 'env' argument to 'evalhook' is not specified, +NIL is used, which specifies to use the +current global environment. The 'env', if specified, is a structure composed +of dotted pairs constructed of the symbol and its value which have the +form:

    + +
    +(((sym1 . val1) (sym2 . val2) ... )))
    +
    + +

    Examples

    + +
    +(setq a 100)                       ; set up global values
    +(setq b 200)
    +
    +(evalhook '(+ a b) NIL NIL)        ; returns 300 - no 'env' was given
    +
    +(evalhook '(+ a b) NIL NIL         ; eval with a=1 and b=2
    +          '((((a . 1)(b . 2)))))   ;   returns 3
    +
    +(defun myeval (exp env)            ; define MYEVAL routine
    +  (princ "exp: ") (print exp)
    +  (princ "env: ") (print env)
    +  (evalhook exp #'myeval NIL env))
    +
    +(defun foo (a) (+ a a))            ; create simple function
    +(setq *evalhook* #'myeval)         ; and install MYEVAL as hook
    +
    +(foo 1)                            ; prints exp: (FOO 1) env:NIL
    +                                   ;        exp: 1       env:NIL
    +                                   ;        exp: (+ A A) env:((((A . 1))))
    +                                   ;        exp: A       env:((((A . 1))))
    +                                   ;        exp: A       env:((((A . 1))))
    +                                   ; returns 2
    +
    +(top-level)                        ; to clean up *evalhook*
    +
    + +

    Note: The 'evalhook' function and +*evalhook* system variable are very useful +in the construction of debugging facilities within XLISP. The +trace and +untrace functions use 'evalhook' and +*evalhook* to implement their +functionality. The other useful aspect of 'evalhook' and +*evalhook* is to help in understanding +how XLISP works to see the expressions, their environment and how they +are evaluated.

    + +

    Caution: Be careful when using +*evalhook* and 'evalhook'. +If you put in a bad definition into +*evalhook* , you might not +be able to do anything and will need to exit XLISP.

    + +

    Unusual behaviour: The 'evalhook' function and +*evalhook* system variable, by their +nature, cause some unusual things to happen. After you have set +*evalhook* to some +non-NIL value, your function will be +called. However, when you are all done and set +*evalhook* to +NIL or some other new routine, it will +never be set. This is because the 'xevalhook' function [in the 'xlbfun.c' +source file] saves the old value of +*evalhook* before calling your routine, +and then restores it after the evaluation. The mechanism to reset +*evalhook* is to execute the +top-level function, which sets +*evalhook* to +NIL.

    + +

    See the +evalhook +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/evenp.htm b/docsrc/xlisp/xlisp-doc/reference/evenp.htm new file mode 100644 index 0000000..3f85fd7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/evenp.htm @@ -0,0 +1,92 @@ +XLISP evenp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    evenp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (evenp expr)
    +
    expr - the integer numeric expression to check
    +returns -  T  if the integer +is even, NIL otherwise
    +
    + +

    Description

    + +

    The 'evenp' predicate function checks to see if the number 'expr' is +even.  T  is returned if the +number is even, NIL is returned +otherwise.

    + +

    An error is generated if the 'expr' is not a numeric expression:

    + +
    +error: bad argument type
    +
    + +

    An error is generated if the 'expr' is a floating point number:

    + +
    +error: bad floating point operation
    +
    + +

    Zero is an even number.

    + +

    Examples

    + +
    +(evenp 0)     ; returns T
    +(evenp 1)     ; returns NIL
    +(evenp 2)     ; returns T
    +(evenp -1)    ; returns NIL
    +(evenp -2)    ; returns T
    +(evenp 14.0)  ; error: bad floating point operation
    +(evenp 'a)    ; error: bad argument type
    +(setq a 2)    ; set value of A to 2
    +(evenp a)     ; returns T
    +
    + +

    See the +evenp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/exit.htm b/docsrc/xlisp/xlisp-doc/reference/exit.htm new file mode 100644 index 0000000..a6a4124 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/exit.htm @@ -0,0 +1,69 @@ +XLISP exit + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    exit

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c

    + +

    Syntax

    + +
    +
    (exit)
    +
    returns - never returns
    +
    + +

    Description

    + +

    The 'exit' function causes the current XLISP session to be terminated. +It never returns.

    + +

    Examples

    + +
    +(exit)   ; never returns
    +
    + +

    Note: When XLISP is exited, any +dribble transcript file is automatically +closed. However, other open files are not closed, and so may lose some +information.

    + +

    See also quit.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/exp.htm b/docsrc/xlisp/xlisp-doc/reference/exp.htm new file mode 100644 index 0000000..8a56f40 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/exp.htm @@ -0,0 +1,76 @@ +XLISP exp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    exp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (exp power)
    +
    power - floating point number/expression
    +returns - e to the x power
    +
    + +

    Description

    + +

    The 'exp' function calculates e [2.7128] raised to the specified +'power' and returns the result.

    + +

    Examples

    + +
    +(exp 0.0)   ; returns 1
    +(exp 1.0)   ; returns 2.71828 - e
    +(exp 2.0)   ; returns 7.38906
    +(exp 10.0)  ; returns 22026.5
    +(exp 0)     ; error: bad integer operation
    +
    + +

    Note: 'exp' with a large 'power' like 1000.0 causes an incorrect +value to be generated, with no error. The returned value will be a very +large floating point number near the computer's limit [something like +1.79000e+308].

    + +

    See the +exp +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/expand.htm b/docsrc/xlisp/xlisp-doc/reference/expand.htm new file mode 100644 index 0000000..5ed5a28 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/expand.htm @@ -0,0 +1,91 @@ +XLISP expand + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    expand

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c, xldmem.c

    + +

    Syntax

    + +
    +
    (expand segments)
    +
    segments - the number of segments to add as an integer expression
    +returns - the number of segments added
    +
    + +

    Description

    + +

    The 'expand' function expands memory by the specified number of +'segments'. The number of 'segments' added is returned as the result. The +power up default is 1000 nodes per segment. Note that +alloc allows you to change the number of +nodes per segment.

    + +

    Examples

    + +
    +(room)      ; prints  Nodes:       8000
    +            ;         Free nodes:  5622
    +            ;         Segments:    6
    +            ;         Allocate:    1000
    +            ;         Total:       92586
    +            ;         Collections: 8
    +            ; returns NIL
    +
    +(expand 2)  ; add more nodes
    +
    +(room)      ; prints  Nodes:       10000
    +            ;         Free nodes:  7608
    +            ;         Segments:    8
    +            ;         Allocate:    1000
    +            ;         Total:       112602
    +            ;         Collections: 8
    +            ; returns NIL
    +
    + +

    Note: When gc is called or an +automatic garbage collection occurs, if the amount of free memory is still +low after the garbage collection, the system attempts to add more segments +[an automatic 'expand'].

    + +

    See the +expand +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/expt.htm b/docsrc/xlisp/xlisp-doc/reference/expt.htm new file mode 100644 index 0000000..7b9a4f6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/expt.htm @@ -0,0 +1,79 @@ +XLISP expt + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    expt

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (expt expr [power ... ])
    +
    expr - floating point number/expression
    +power - integer or floating point number/expression
    +returns - x to the y power
    +
    + +

    Description

    + +

    The 'expt' function raises the 'expr' to the specified 'power' and +returns the result. If there is no 'power' specified, the 'expr' is +returned. If there are multiple 'powers', they will be applied sequentially +to 'expr'.

    + +

    Examples

    + +
    +(expt 2.0 2)        ; returns 4
    +(expt 2.0 10)       ; returns 1024
    +(expt 2 2)          ; error: bad integer operation
    +(expt 99.9)         ; returns 99.9
    +(expt 2.0 2.0 2.0)  ; returns 16
    +
    + +

    Note: 'expt' with a large values like (expt 999.9 999.9) causes an +incorrect value to be generated, with no error. The returned value will be a +very large floating point number near the computer's limit [something like +1.79000e+308].

    + +

    See the +expt +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/fboundp.htm b/docsrc/xlisp/xlisp-doc/reference/fboundp.htm new file mode 100644 index 0000000..cc014f8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/fboundp.htm @@ -0,0 +1,84 @@ +XLISP fboundp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    fboundp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (fboundp symbol)
    +
    symbol - the symbol expression to check for a value
    +returns -  T  if a functional +value is bound to the symbol, NIL +otherwise
    +
    + +

    Description

    + +

    The 'fboundp' predicate function checks to see if 'symbol' is a symbol +with a function definition bound to it. + T  is returned if 'symbol' has a +function value, NIL is returned otherwise. +Note that 'symbol' is a symbol expression, it is evaluated and the resulting +expression is the one that is checked.

    + +

    Examples

    + +
    +(defun foo (x) (print x))       ; set up function FOO
    +(fboundp 'foo)                  ; returns T - FOO is closure
    +(fboundp 'car)                  ; returns T - CAR is subr
    +
    +(setq myvar 'goo)               ; set up MYVAR to have value GOO
    +(fboundp myvar)                 ; returns NIL - because GOO has no value yet
    +(defmacro goo () (print "hi"))  ; define GOO macro
    +(fboundp myvar)                 ; returns T
    +
    +(fboundp 'a)                    ; returns NIL
    +(fboundp '1)                    ; error: bad argument type - 1
    +(fboundp "hi")                  ; error: bad argument type - "hi"
    +
    + +

    See the +fboundp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/filep.htm b/docsrc/xlisp/xlisp-doc/reference/filep.htm new file mode 100644 index 0000000..6db78bf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/filep.htm @@ -0,0 +1,75 @@ +XLISP filep + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    filep

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  xlinit.lsp

    + +

    Syntax

    + +

    + +
    +
    (filep expr)
    +
    expr - an Lisp expression
    +returns -  T  if expr is of type FPTR, +NIL otherwise
    +
    + +

    + +

    In Nyquist, 'filep' is implemented as a Lisp function:

    + +
    +(defun filep (x)
    +  (eq (type-of x) 'FPTR))
    +
    + +

    Description

    + +

    The 'filep' function returns  T  if +'expr' is of type FPTR, NIL otherwise

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/find-in-xlisp-path.htm b/docsrc/xlisp/xlisp-doc/reference/find-in-xlisp-path.htm new file mode 100644 index 0000000..ee671d1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/find-in-xlisp-path.htm @@ -0,0 +1,66 @@ +XLISP find-in-xlisp-path + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    find-in-xlisp-path

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  path.c

    + +

    Syntax

    + +
    +
    (find-in-xlisp-path filename)
    +
    filename - the name of the file to search for as string
    +returns - a full path name to the first occurrence found
    +
    + +

    Description

    + +

    The 'find-in-xlisp-path' function searches the XLISP search +path [e.g. XLISPPATH from the environment] for 'filename'. +If 'filename' is not found as is, and there is no file +extension, '.lsp' is appended to filename and searched again. The +current directory is not searched.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/first.htm b/docsrc/xlisp/xlisp-doc/reference/first.htm new file mode 100644 index 0000000..054167a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/first.htm @@ -0,0 +1,74 @@ +XLISP first + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    first

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlinit.c

    + +

    Syntax

    + +
    +
    (first expr)
    +
    expr - a list or list expression
    +returns - the first element of the expression
    +
    + +

    Description

    + +

    The 'first' function returns the first element of the expression. +If the first expression is itself a list, then the sublist is returned. +If the list is NIL , +NIL is returned.

    + +

    Examples

    + +
    +(first '(a b c))               ; returns A
    +(first '((a b) c d))           ; returns (A B)
    +(first NIL)                    ; returns NIL
    +(first 'a)                     ; error: bad argument type
    +(setq children '(amanda ben))  ; set up variable CHILDREN
    +(first children)               ; returns AMANDA
    +
    + +

    See the +first +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/flatc.htm b/docsrc/xlisp/xlisp-doc/reference/flatc.htm new file mode 100644 index 0000000..0bf8f87 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/flatc.htm @@ -0,0 +1,74 @@ +XLISP flatc + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    flatc

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c, xlprin.c

    + +

    Syntax

    + +
    +
    (flatc expr)
    +
    expr - an expression
    +returns - the length
    +
    + +

    Description

    + +

    The 'flatc' function determines the character length that would be +printed if the 'expr' were printed using +princ. This means that the 'expr' would be +printed without a new-line. If 'expr' is a string, it would not be printed +with quotes around the string. The print character length is returned as the +result.

    + +

    Examples

    + +
    +(flatc 1234)          ; returns 4
    +(flatc '(a b c))      ; returns 7
    +(flatc "abcd")        ; returns 4
    +(flatc 'mybigsymbol)  ; returns 11
    +
    + +

    See the +flatc +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/flatsize.htm b/docsrc/xlisp/xlisp-doc/reference/flatsize.htm new file mode 100644 index 0000000..57da49c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/flatsize.htm @@ -0,0 +1,74 @@ +XLISP flatsize + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    flatsize

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c, xlprin.c

    + +

    Syntax

    + +
    +
    (flatsize expr)
    +
    expr - an expression
    +returns - the length
    +
    + +

    Description

    + +

    The 'flatsize' function determines the character length that would be +printed if the 'expr' were printed using prin1. This means that the 'expr' would be +printed without a new-line. If 'expr' is a string, it would be printed with +quotes around the string. The print character length is returned as the +result.

    + +

    Examples

    + +
    +(flatsize 1234)          ; returns 4
    +(flatsize '(a b c))      ; returns 7
    +(flatsize "abcd")        ; returns 6
    +(flatsize 'mybigsymbol)  ; returns 11
    +
    + +

    See the +flatsize +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/flet.htm b/docsrc/xlisp/xlisp-doc/reference/flet.htm new file mode 100644 index 0000000..aa5cc5d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/flet.htm @@ -0,0 +1,87 @@ +XLISP flet + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    flet

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (flet ([function ... ]) expr ... )
    +
    function - a function definition binding which is of the form: +
    (symbol arg-list body) +
    symbol - the symbol specifying the function name
    +arg-list - the argument list for the function
    +body - the body of the function
    +expr - an expression
    +returns - the value of the last expression
    +
    + +

    Description

    + +

    The 'flet' special form is basically a local block construct that allows +local 'function' definitions followed by a block of code to evaluate. The +first form after the 'flet' is the 'binding' form. It contains a series of +'functions'. The 'flet' form will go through and define the 'symbols' of the +'functions' and then sequentially execute the 'exprs'. The value of the last +'expr' evaluated is returned. When the 'flet' is finished execution, the +'symbols' that were defined will no longer exist.

    + +

    Examples

    + +
    +(flet ((fuzz (x) (+ x x)))  ; an FLET with FUZZ local function
    +  (fuzz 2))                 ; returns 4
    +                            ; FUZZ no longer exists
    +
    +(fuzz 2)                    ; error: unbound function - FUZZ
    +
    +                            ; an empty flet
    +(flet () (print 'a))        ; prints A
    +
    + +

    Note: 'flet' does not allow recursive definitions of functions. +The labels special form does allow this.

    + +

    See the +flet +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/float.htm b/docsrc/xlisp/xlisp-doc/reference/float.htm new file mode 100644 index 0000000..b20c35d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/float.htm @@ -0,0 +1,71 @@ +XLISP float + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    float

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (float expr)
    +
    expr - integer or floating point number/expression
    +returns - the result as a floating point number
    +
    + +

    Description

    + +

    The 'float' function takes a numeric expression and returns the result +as a floating point number.

    + +

    Examples

    + +
    +(/ 1 2)            ; returns 0 (integer division)
    +(/ (float 1) 2)    ; returns 0.5
    +(float (/ 1 2))    ; returns 0 (integer division)
    +(/ 1 2 3)          ; returns 0 (integer division)
    +(/ (float 1) 2 3)  ; returns 0.166667
    +
    + +

    See the +float +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/floatp.htm b/docsrc/xlisp/xlisp-doc/reference/floatp.htm new file mode 100644 index 0000000..ea4c1b8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/floatp.htm @@ -0,0 +1,81 @@ +XLISP floatp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    floatp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (floatp expr)
    +
    expr - the expression to check
    +returns -  T  if the value is a +floating point number, NIL otherwise
    +
    + +

    Description

    + +

    The 'floatp' predicate function checks if an 'expr' is a floating point +number.  T  is returned if 'expr' +is a floating point number, NIL is returned +otherwise.

    + +

    Examples

    + +
    +(floatp 1.2)       ; returns T - float
    +(floatp '1.2)      ; returns T - still a float
    +(setq a 1.234)
    +(floatp a)         ; returns T - evaluates to float
    +(floatp 0.0)       ; returns T - float zero
    +(floatp 0)         ; returns NIL - integer zero
    +(floatp 1)         ; returns NIL - integer
    +(floatp #x034)     ; returns NIL - integer readmacro
    +(floatp 'a)        ; returns NIL - symbol
    +(floatp #\a)       ; returns NIL - character
    +(floatp NIL)       ; returns NIL - NIL
    +(floatp #(0 1 2))  ; returns NIL - array
    +
    + +

    See the +floatp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/format.htm b/docsrc/xlisp/xlisp-doc/reference/format.htm new file mode 100644 index 0000000..8a8bdca --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/format.htm @@ -0,0 +1,161 @@ +XLISP format + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    format

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (format destination format [expr1 ... ])
    +
    destination - a required destination [see below]
    +format - a format string
    +exprN - an expression
    +returns - output string if stream is +NIL , +NIL otherwise
    +
    + +

    The 'destination' must be a file pointer, a stream, +NIL [to create a string] or + T  [to print to +*standard-output*].

    + +

    Description

    + +

    The 'format' function prints the specified expressions [if any] to the +specified 'destination' using the 'format' string to control the print +format. If the 'destination' is +NIL , a string is created and +returned with the contents of the 'format'. If the 'destination' is + T  , the printing +occurs to *standard-output*. The 'format' +function returns NIL , if +the 'destination' was non-NIL. The 'format' +string is a string [surrounded by double-quote characters]. This string +contains ASCII text to be printed along with formatting directives +[identified by a preceeding tilde '~' character]. The character following +the tilde character is not case sensitive ['~a' and '~A' will function +equivalently].

    + +

    Examples

    + +
    +(format T "Now is the time for")         ; prints  Now is the time for
    +(format T "all ~A ~S to" 'good 'men)     ; prints  all GOOD MEN to
    +(format T "come to the")                 ; prints  come to the
    +(format T "~A of their ~S"               ; prints  aid of their "party"
    +          "aid" "party")
    +(format *standard-ouput* "Hello there")  ; prints  Hello there
    +(format nil "ho ho ~S" 'ho)              ; returns "ho ho HO"
    +(format T "this is ~%a break")           ; prints  this is
    +                                         ;         a break
    +(format T "this is a long ~
    +           string")                      ; prints  this is a long string
    +
    + +

    Supported format directives: The 'format' string in XLISP supports +the following format directives:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ~A  -  ASCII, prints the 'expr'. If it is a string print it + without quotes. This is like the princ + function.
     
    ~S  -  s-expr, prints the 'expr'. If it is a string print it + with quotes. This is like the prin1 + function.
     
    ~%  -  prints a 'newline' control character.
     
    ~~  -  prints a single tilde '~' character.
     
    ~<newline>  -  continue the 'format' string on the next line. This + signals a line break in the format. The 'format' function will ignore + all white-space [blanks, tabs, newlines]. This is useful when the + 'format' string is longer than a program line. Note that the 'newline' + character must immediately follow the tilde character.

    + +

    Common Lisp: The 'format' function in Common Lisp is quite +impressive. It includes 26 different formatting directives. XLISP, as shown +above, does not include most of these. The more difficult ones that you +might encounter are the decimal, octal, hexidecimal, fixed-format +floating-point and exponential floating-point. It is possible to print in +octal and hexadecimal notation by setting +*integer-format*. It is possible to print +in fixed format and exponential by setting +*float-format*. However, neither of these +system variables are supported in Common Lisp and neither gives control over +field size.

    + +

    See the +format +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/fourth.htm b/docsrc/xlisp/xlisp-doc/reference/fourth.htm new file mode 100644 index 0000000..9cf0fbb --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/fourth.htm @@ -0,0 +1,79 @@ +XLISP fourth + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    fourth

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlinit.c

    + +

    Syntax

    + +
    +
    (fourth expr)
    +
    expr - a list or list expression
    +returns - the fourth element of the list
    +
    + +

    Description

    + +

    The 'fourth' function returns the fourth element of a list or list +expression. If the list is +NIL , +NIL is returned.

    + +

    Examples

    + +
    +(fourth '(1 2 3 4 5))                    ; returns 4
    +(fourth NIL)                             ; returns NIL
    +(setq kids '(junie vickie cindy chris))  ; set up variable KIDS
    +(first kids)                             ; returns JUNIE
    +(second kids)                            ; returns VICKIE
    +(third kids)                             ; returns CINDY
    +(fourth kids)                            ; returns CHRIS
    +(rest kids)                              ; returns (VICKIE CINDY CHRIS)
    +
    + +

    Note: This function is set to the same code as +cadddr.

    + +

    See the +fourth +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/funcall.htm b/docsrc/xlisp/xlisp-doc/reference/funcall.htm new file mode 100644 index 0000000..6deefa3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/funcall.htm @@ -0,0 +1,102 @@ +XLISP funcall + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    funcall

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (funcall function [arg1 ... ])
    +
    function - the function or symbol to be called
    +argN - an argument to be passed to function
    +returns - the result of calling the function with the arguments
    +
    + +

    Description

    + +

    The 'funcall' function calls a function with a series of arguments. +It returns the result from calling the function with the arguments.

    + +

    Examples

    + +
    +(funcall '+ 1 2 3 4)                 ; returns 10
    +(funcall #'+ 1 2 3 4)                ; returns 10
    +(funcall '+ '1 '2 '3)                ; returns 6
    +
    +(setq sys-add (function +))          ; returns #<Subr-+: #22c32>
    +(setq a 99)
    +(funcall sys-add 1 a)                ; 100
    +(funcall sys-add 1 'a)               ; error: bad argument type
    +                                     ;   you can't add a symbol, only it's value
    +
    +(setq a 2)                           ; set A
    +(setq b 3)                           ; and B values
    +(funcall (if (< a b) (function +)    ; 'function' can be computed
    +                     (function -))
    +         a b)                        ; returns 5
    +
    +(defun add-to-list (arg list)        ; add a list or an atom
    +   (funcall (if (atom arg) 'cons     ;   to the front of a list
    +                           'append)
    +            arg list))
    +(add-to-list 'a '(b c))              ; returns (A B C)
    +(add-to-list '(a b) '(b c))          ; returns (A B B C)
    +
    + +

    Notes

    + +

    In XLISP, a 'special form' of type FSUBR is not a function. +This means that 'funcall' only works with functions of type SUBR +[built-in function] or CLOSURE [function defined by +defun, flet, +labels, or lambda], but +with special forms of type FSUBR a 'bad function' error is +signalled. Here is an example how to work around this behaviour:

    + +
    +(defun funcall* (function &rest args)
    +  (if (eq (type-of function) 'fsubr)
    +      (eval (cons function args))
    +      (apply function args)))
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/function.htm b/docsrc/xlisp/xlisp-doc/reference/function.htm new file mode 100644 index 0000000..4e173fc --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/function.htm @@ -0,0 +1,87 @@ +XLISP function + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    function

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (function expr)
    +
    expr - an expression that evaluates to a function
    +returns - the functional interpretation
    +
    + +

    Description

    + +

    The 'function' special form returns the function definition of the +'expr'. Execution of the 'expr' form does not occur. 'function' will operate +on functions, special forms, lambda-expressions and macros.

    + +

    Examples

    + +
    +(function car)              ; returns #<Subr-CAR: #23ac4>
    +(function quote)            ; returns #<FSubr-QUOTE: #23d1c>
    +#'quote                     ; returns #<FSubr-QUOTE: #23d1c>
    +(function 'cdr)             ; error: not a function
    +
    +(defun foo (x) (+ x x))     ; define FOO function
    +(function foo)              ; returns #<Closure-FOO: #2cfb6>
    +
    +(defmacro bar (x) (+ x x))  ; define FOOMAC macro
    +(function bar)              ; returns #<Closure-BAR: #2ceee>
    +
    +(setq my 99)                ; define a variable MY
    +(function my)               ; error: unbound function
    +
    +(defun my (x) (print x))    ; define a function MY
    +(function my)               ; returns #<Closure-MY: #2cdd6>
    +
    + +

    Read macro: XLISP supports the normal Lisp read macro of a hash +and quote [#'] as a short-hand method of writing the 'function' special +form.

    + +

    See the +function +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/gc.htm b/docsrc/xlisp/xlisp-doc/reference/gc.htm new file mode 100644 index 0000000..1761b81 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/gc.htm @@ -0,0 +1,74 @@ +XLISP gc + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    gc

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xldmem.c

    + +

    Syntax

    + +
    +
    (gc)
    +
    returns - always returns NIL
    +
    + +

    Description

    + +

    The 'gc' function starts a garbage collection of the unused memory of +XLISP. NIL is always returned.

    + +

    Examples

    + +
    +(gc)  ; start a garbage collection right now
    +
    + +

    Note: The system will cause an automatic garbage collection if it +runs out of free memory.

    + +

    Note: When 'gc' is called or an automatic garbage collection +occurs, if the amount of free memory is still low after the garbage +collection, the system attempts to add more segments [an automatic +expand].

    + +

    See the +gc +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/gcd.htm b/docsrc/xlisp/xlisp-doc/reference/gcd.htm new file mode 100644 index 0000000..2dc7570 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/gcd.htm @@ -0,0 +1,75 @@ +XLISP gcd + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    gcd

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (gcd [int ... ])
    +
    int - an integer expression
    +returns - the greatest common divisor
    +
    + +

    Description

    + +

    The 'gcd' function returns the greatest common divisor of a series of +integers. If no arguments are given, a zero is returned. If only one +argument is given, the absolute value of the argument is returned. The +successful result is always a positive integer.

    + +

    Examples

    + +
    +(gcd 51 34)       ; returns 17
    +(gcd 99 66 22)    ; returns 11
    +(gcd -99 66 -33)  ; returns 33
    +(gcd -14)         ; returns 14
    +(gcd 0)           ; returns 0
    +(gcd)             ; returns 0
    +(gcd .2)          ; error: bad argument type - 0.2
    +
    + +

    See the +gcd +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/gensym.htm b/docsrc/xlisp/xlisp-doc/reference/gensym.htm new file mode 100644 index 0000000..93b05d2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/gensym.htm @@ -0,0 +1,89 @@ +XLISP gensym + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    gensym

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (gensym [tag])
    +
    tag - an optional integer or string
    +returns - the new symbol
    +
    + +

    Description

    + +

    The 'gensym' function generates and returns a symbol. The default symbol +form is as a character 'G' followed by a number, 'Gn'. The default numbering +starts at '1'. You can change what the generated symbol looks like. By +calling 'gensym' with a string 'tag', the default string is set to the +string parameter. If 'tag' is an integer number, the current number is +set to the integer parameter.

    + +

    Examples

    + +
    +(gensym)             ; first time => G1
    +(gensym 100)         ; returns G100
    +(gensym "MYGENSYM")  ; returns MYGENSYM101
    +(gensym 0)           ; returns MYGENSYM0
    +(gensym)             ; returns MYGENSYM1
    +(gensym "G")         ; \
    +(gensym 0)           ; /  put it back to 'normal'
    +(gensym)             ; just like first time => G1
    +
    + +

    Note: It takes 2 calls to 'gensym' to set both portions of the +'gensym' symbol.

    + +

    Note: Although it is possible to call 'gensym' with numbers in the string +like "AB1", this does generate an odd sequence. What will happen is you will +get a sequence of symbols like:

    + +
    +... AB18 AB19 AB110 AB111 ...
    +
    + +

    See the +gensym +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get-env.htm b/docsrc/xlisp/xlisp-doc/reference/get-env.htm new file mode 100644 index 0000000..4511afa --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get-env.htm @@ -0,0 +1,64 @@ +XLISP get-env + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get-env

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c

    + +

    Syntax

    + +
    +
    (get-env string)
    +
    string - environment variable name as string
    +returns - the value of the environment variable as string, +or NIL
    +
    + +

    Description

    + +

    The 'get-user' function returns the value of an environment +variable, or NIL if no variable had been found.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get-key.htm b/docsrc/xlisp/xlisp-doc/reference/get-key.htm new file mode 100644 index 0000000..b890899 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get-key.htm @@ -0,0 +1,66 @@ +XLISP get-key + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get-key

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sys/unix/osstuff.c, sys/mac/macfun.c, sys/win/msvc/winfun.c

    + +

    Syntax

    + +
    +
    (get-key)
    +
    returns - the decimal ASCII value of the key pressed
    +
    + +

    Description

    + +

    The 'get-key' function gets a single key stroke from the keyboard [as +opposed to an entire line, as read does].

    + +

    Note: In Nyquist, this function is only defined to work on Unix +systems [including Linux and Mac OS X]. On +Windows systems, NIL is returned.

    + +

    Examples

    + +
    +(setq mychar (get-key))   ; get a character
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get-lambda-expression.htm b/docsrc/xlisp/xlisp-doc/reference/get-lambda-expression.htm new file mode 100644 index 0000000..a3bc5bb --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get-lambda-expression.htm @@ -0,0 +1,78 @@ +XLISP get-lambda-expression + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get-lambda-expression

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (get-lambda-expression closure)
    +
    closure - a closure object from a previously defined +function or +macro
    +returns - the original lambda expression
    +
    + +

    Description

    + +

    The 'get-lambda-expression' function takes the 'closure' object and +returns a reconstruction of a +lambda or +macro expression that defines the +'closure'. The parameter must be a 'closure' expression.

    + +

    Examples

    + +
    +(defun mine (a b) (print (+ a b)))             ; define MINE defun
    +(get-lambda-expression (function mine))        ; returns (LAMBDA (A B) (PRINT (+ A B)))
    +
    +(get-lambda-expression (lambda (a) (print a))  ; returns (LAMBDA (A) (PRINT A))
    +
    +(defmacro plus (n1 n2) `(+ ,n1 ,n2))           ; define PLUS macro
    +(get-lambda-expression (function plus))        ; returns (MACRO (N1 N2) (BACKQUOTE (+ (COMMA N1) (COMMA N2))))
    +
    + +

    See the +get-lambda-expression +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get-output-stream-list.htm b/docsrc/xlisp/xlisp-doc/reference/get-output-stream-list.htm new file mode 100644 index 0000000..94c0c6d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get-output-stream-list.htm @@ -0,0 +1,75 @@ +XLISP get-output-stream-list + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get-output-stream-list

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (get-output-stream-list stream)
    +
    stream - an output stream expression
    +returns - the output so far as a list
    +
    + +

    Description

    + +

    The 'get-output-stream-list' function empties the specified 'stream' and +returns this data as a list. The output stream is emptied by this +operation.

    + +

    Examples

    + +
    +(setq out (make-string-output-stream))  ; returns #<Unnamed-Stream: #...>
    +
    +(format out "123")                      ; add some data to output stream
    +(get-output-stream-list out)            ; returns (#\1 #\2 #\3)
    +
    +(format out "123")                      ; add some data to output stream
    +(read out)                              ; returns 123
    +(get-output-stream-list out)            ; returns NIL, the string was emptied by 'read'
    +
    + +

    See the +get-output-stream-list +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get-output-stream-string.htm b/docsrc/xlisp/xlisp-doc/reference/get-output-stream-string.htm new file mode 100644 index 0000000..4dbc02a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get-output-stream-string.htm @@ -0,0 +1,80 @@ +XLISP get-output-stream-string + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get-output-stream-string

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (get-output-stream-string stream)
    +
    stream - an output stream expression
    +returns - the output so far as a string
    +
    + +

    Description

    + +

    The 'get-output-stream-string' function empties the specified 'stream' +and returns this data as a single string. The output stream is emptied by +this operation.

    + +

    Examples

    + +
    +(setq out (make-string-output-stream))  ; returns #<Unnamed-Stream: #...>
    +
    +(format out "fee fi fo fum ")           ; \
    +(format out "I smell the blood of ")    ;  fill up output stream
    +(format out "Elmer Fudd")               ; /
    +(get-output-stream-string out)          ; returns "fee fi fo fum I smell the blood of Elmer Fudd"
    +
    +(format out "~%now what")               ; add more to output stream
    +(get-output-stream-string out)          ; returns "\nnow what"
    +(get-output-stream-string out)          ; returns ""
    +
    +(format out "hello")                    ; add more to output stream
    +(read out)                              ; returns HELLO
    +
    + +

    See the +get-output-stream-string +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get-temp-path.htm b/docsrc/xlisp/xlisp-doc/reference/get-temp-path.htm new file mode 100644 index 0000000..eb015f9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get-temp-path.htm @@ -0,0 +1,68 @@ +XLISP get-temp-path + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get-temp-path

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sys/unix/osstuff.c, sys/win/msvc/winfun.c

    + +

    Syntax

    + +
    +
    (get-temp-path)
    +
    returns - the resulting full path as a string
    +
    + +

    Description

    + +

    The 'get-temp-path' function tries to get a path where a +temporary file can be created.

    + +

    Note: Under Windows, the 'get-temp-path' function is +based on environment variables. If XLISP is running as a +sub-process to Java, the environment may not exist, in which +case the default result is the unfortunate choice +'c:\windows\'.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get-user.htm b/docsrc/xlisp/xlisp-doc/reference/get-user.htm new file mode 100644 index 0000000..735a8e2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get-user.htm @@ -0,0 +1,67 @@ +XLISP get-user + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get-user

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sys/unix/osstuff.c, sys/win/msvc/winstuff.c

    + +

    Syntax

    + +
    +
    (get-user)
    +
    returns - a string naming the user, or "nyquist"
    +
    + +

    Description

    + +

    The 'get-user' function returns the current user name. +In Unix systems [including OS X and Linux], this +is the value of the USER environment variable. In Windows, this +is currently just "nyquist", which is also returned if the +environment variable cannot be accessed. This function is used to avoid the +case of two users creating files of the same name in the same temp +directory.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/get.htm b/docsrc/xlisp/xlisp-doc/reference/get.htm new file mode 100644 index 0000000..e8cc487 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/get.htm @@ -0,0 +1,97 @@ +XLISP get + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    get

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (get symbol property)
    +
    symbol - the symbol with a property list
    +property - he property name being retrieved
    +returns - the property value or NIL
    +
    + +

    Description

    + +

    The 'get' function returns the value of the'property' from the 'symbol'. +If the 'property' does not exist, a NIL is +returned. The 'symbol' must be an existing symbol. The returned value may be +a single value or a list.

    + +

    Property lists are lists attached to any user defined variables. The +lists are in the form of:

    + +
    +(name1 value1 name2 value2 ... )
    +
    + +

    Any number of properties may be attached to a single variable.

    + +

    Examples

    + +
    +(setq person 'bobby)                  ; create a variable with a value
    +(putprop person 'boogie 'last-name)   ; add a LAST-NAME property
    +(putprop person 'disc-jockey 'job)    ; add a JOB property
    +
    +(get person 'last-name)               ; retrieve LAST-NAME - boogie
    +(get person 'job)                     ; retrieve JOB - disc-jockey
    +(get person 'height)                  ; non-existant - returns NIL
    +
    +(putprop person '(10 20 30) 'stats)   ; add STATS - a list
    +(get person 'stats)                   ; retrieve STATS - (10 20 30)
    +
    + +

    Note: You can set a property to the value +NIL. However, this +NIL value is indistinguishable from the +NIL returned when a property does not +exist.

    + +

    Common Lisp: Common Lisp allows for an optional default value, +which XLISP does not support.

    + +

    See the +get +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-applyhook.htm b/docsrc/xlisp/xlisp-doc/reference/global-applyhook.htm new file mode 100644 index 0000000..4bc2bbd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-applyhook.htm @@ -0,0 +1,78 @@ +XLISP *applyhook* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *applyhook*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlglob.c (not implemented)

    + +

    Syntax

    + +

    + +
    +
     *applyhook*
    +
    + +

    + +

    Description

    + +

    *applyhook* is a system variable that exists and is initialized to +NIL. It is a hook that is intended to +contain a user function that is to be called whenever a function is applied +to a list of arguments. It is not, however, implemented in XLISP 2.0, it +only exists as a dummy hook.

    + +

    Examples

    + +
    +*applyhook*  => NIL
    +
    + +

    *applyhook* is often used to implement function stepping functionality in +a debugger.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-breakenable.htm b/docsrc/xlisp/xlisp-doc/reference/global-breakenable.htm new file mode 100644 index 0000000..9a22cf9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-breakenable.htm @@ -0,0 +1,106 @@ +XLISP *breakenable* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *breakenable*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xldbug.c

    + +

    Syntax

    + +

    + +
    +
    (setq *breakenable* boolean)
    +
    boolean - a generalized boolean value
    +returns - non-NIL if errors shall be handled by the +Break Loop, or NIL if not
    +
    + +

    + +

    Description

    + +

    The *breakenable* system variable controls entry to the +Break Loop and +the trapping of errors. If *breakenable* is set to +NIL , then no errors from the +system or from the error or +cerror functions will be trapped. +If *breakenable* is non-NIL, +the Break Loop +will handle these errors. The break +function is not affected by *breakenable* and will always force entry to the +Break Loop. +If the 'init.lsp' initialization file sets +*breakenable* to  T , +errors will be trapped by the +Break Loop.

    + +

    Examples

    + +
    +> (defun foo (x)            ; define function FOO
    +    (+ x x))
    +FOO
    +
    +> (setq *breakenable* NIL)  ; disable break loop
    +NIL
    +
    +> (foo "a")
    +error: bad argument type    ; does NOT enter a break loop
    +
    +> (setq *breakenable* T)    ; enable break loop
    +T
    +
    +> (foo "a")
    +error: bad argument type
    +
    +1>                          ; entered a break loop
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-debug-io.htm b/docsrc/xlisp/xlisp-doc/reference/global-debug-io.htm new file mode 100644 index 0000000..97edafd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-debug-io.htm @@ -0,0 +1,72 @@ +XLISP *debug-io* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *debug-io*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c, xlio.c, xldbug.c

    + +

    Syntax

    + +
    +
    *debug-io*
    + + +

    Description

    + +

    *debug-io* is a system variable that contains a file pointer pointing to +the stream where all debug input and output goes to and from. The default +file for *debug-io* is the system standard error device, normally the +keyboard and screen.

    + +

    Examples

    + +
    +*debug-io*   ; returns #<File-Stream...>
    +
    + +

    Note: +*trace-output* , +*debug-io* and *error-output* are normally +all set to the same file stream 'stderr'.

    + +

    See the +*debug-io* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-error-output.htm b/docsrc/xlisp/xlisp-doc/reference/global-error-output.htm new file mode 100644 index 0000000..604e60d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-error-output.htm @@ -0,0 +1,71 @@ +XLISP *error-output* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *error-output*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c, xlio.c

    + +

    Syntax

    + +
    +
     *error-output*
    +
    + +

    Description

    + +

    *error-output* is a system variable that contains a file pointer that +points to the file where all error output goes to. The default file for +*error-output* is the system standard error device, normally the screen.

    + +

    Examples

    + +
    +*error-output*   ; returns #<File-Stream...>
    +
    + +

    Note: +*trace-output* , +*debug-io* and *error-output* are normally +all set to the same file stream 'stderr'.

    + +

    See the +*error-output* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-evalhook.htm b/docsrc/xlisp/xlisp-doc/reference/global-evalhook.htm new file mode 100644 index 0000000..ad219d5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-evalhook.htm @@ -0,0 +1,123 @@ +XLISP *evalhook* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *evalhook*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xleval.c

    + +

    Syntax

    + +
    +
     *evalhook*
    +
    + +

    Description

    + +

    *evalhook* is a system variable whose value is user code that will +intercept evaluations either through normal system evaluation or through +calls to evalhook. The default value for +*evalhook* is NIL , which +specifies to use the built in system evaluator. If *evalhook* is +non-NIL , the routine is +called with expression and environment parameters. If the environment +argument is NIL , then the the +current global environment is used. The environment, if +non-NIL , is a structure +composed of dotted pairs constructed of the symbol and its value which have +the form:

    + +
    +(((sym1 . val1) (sym2 . val2) ... )))
    +
    + +

    Examples

    + +
    +(defun myeval (exp env)           ; define MYEVAL routine
    +  (princ "exp: ") (print exp)
    +  (princ "env: ") (print env)
    +  (evalhook exp #'myeval NIL env))
    +
    +(defun foo (a) (+ a a))           ; create simple function
    +(setq *evalhook* #'myeval)        ; and install MYEVAL as hook
    +
    +(foo 1)                           ; prints exp: (FOO 1) env:NIL
    +                                  ;        exp: 1       env:NIL
    +                                  ;        exp: (+ A A) env:((((A . 1))))
    +                                  ;        exp: A       env:((((A . 1))))
    +                                  ;        exp: A       env:((((A . 1))))
    +                                  ; returns 2
    +
    +(top-level)                       ; to clean up *evalhook*
    +
    + +

    Note: The evalhook function and +*evalhook* system variable are very useful in the construction of debugging +facilities within XLISP. The trace and +untrace functions use +evalhook and *evalhook* to implement +their functionality. The other useful aspect of +evalhook and *evalhook* is to help in +understanding how XLISP works to see the expressions, their environment +and how they are evaluated.

    + +

    Caution: Be careful when using *evalhook* and +evalhook. If you put in a bad definition +into *evalhook*, you might not be able to do anything and will need to +exit XLISP.

    + +

    Unusual behaviour: The evalhook +function and *evalhook* system variable, by their nature, cause some unusual +things to happen. After you have set *evalhook* to some +non-NIL value, your function will be +called. However, when you are all done and set *evalhook* to +NIL or some other new routine, it will +never be set. This is because the +evalhook function [in the 'xlbfun.c' +source file] saves the old value of *evalhook* before calling your routine, +and then restores it after the evaluation. The mechanism to reset +*evalhook* is to execute the +top-level function, which sets +*evalhook* to NIL.

    + +

    See the +*evalhook* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-file-separator.htm b/docsrc/xlisp/xlisp-doc/reference/global-file-separator.htm new file mode 100644 index 0000000..f30bb3b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-file-separator.htm @@ -0,0 +1,68 @@ +XLISP *file-separator* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *file-separator*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  system.lsp

    + +

    Syntax

    + +

    + +
    +
     *file-separator*
    +
    + +

    + +

    Description

    + +

    The Nyquist *file-separator* variable is initialized to the operation +system's file separator character. It has a value of #\\ on +Windows and a value of #\/ on Unix [including Linux and Mac OS +X].

    + +

    Examples

    + +
    +*file-separator*  => #\/  ; on Unix, Linux, and Mac OS X
    +*file-separator*  => #\\  ; on Windows
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-float-format.htm b/docsrc/xlisp/xlisp-doc/reference/global-float-format.htm new file mode 100644 index 0000000..3665b7b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-float-format.htm @@ -0,0 +1,179 @@ +XLISP *float-format* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *float-format*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlprin.c

    + +

    Syntax

    + +
    +
     *float-format*
    +
    returns - the print format for floating-point numbers
    +
    + +

    Description

    + +

    *float-format* is a system variable that allows a user to specify how +floating point numbers are to be printed by XLISP. The value of +*float-format* should be set to one of the string expressions +"%e", "%f" or "%g". These format strings are +similar to C-language floating point specifications:

    + +

    + + + + + + + + + + + + + + + + + + + + + +
      "%e"  - exponential. The number is converted to decimal notation + of the form: + +
    +[-]m.nnnnnnE[+-]xx
    +
    + + There is one leading digit. There are 6 digits after the decimal + point.
     
      "%f"  - decimal. The number is converted to decimal notation of + the form: + +
    +[-]mmmmmm.nnnnnn
    +
    + + There are as many digits before the decimal point as necessary. There + are 6 digits after the decimal point.
     
      "%g"  - shortest. The number is converted to either the form of + "%e" or "%f", whichever produces the shortest output + string. Non-significant zeroes are not printed.

    + +

    The default value for *float-format* is the string "%g".

    + +

    There are several additional flags and options available:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
        +  - always print the sign
      space  - print a space instead of a + sign
        #  - always print the dot, do not remove zeros after the dot
       .n  - number of digits after the dot

    + +

    The flags and options must be written between the "%" and the +formatting letter, as shown in the examples below.

    + +

    Examples

    + +
    +(setq *float-format* "%e")       ; exponential notation
    +(print 1.0)                      => 1.000000e+00
    +(print -9e99)                    => -9.000000e+99
    +
    +(setq *float-format* "%f")       ; decimal notation
    +(print 1.0)                      => 1.000000
    +(print 1.0e4)                    => 10000.000000
    +(print -999.99e-99)              => -0.000000
    +
    +(setq *float-format* "%g")       ; shortest notation
    +(print 1.0)                      => 1
    +(print 1.0e7)                    => 1e+07
    +(print -999.999e99)              => -9.99999e+101
    +
    +(setq *float-format* "%+g")      ; always print the sign
    +(print  1.1)                     => +1.1
    +(print -1.1)                     => -1.1
    +
    +(setq *float-format* "% g")      ; print a space instead of the + sign
    +(print  1.1)                     =>  1.1
    +(print -1.1)                     => -1.1
    +
    +(setq *float-format* "%#.10g")   ; ten digits after the dot
    +(print 1.0)                      => 1.000000000
    +(print 1.0e7)                    => 10000000.00
    +(print -999.9999999e99)          => -9.999999999e+101
    +
    +(setq *float-format* "%+#.10g")  ; ten digits after the dot plus sign
    +(print  1.2345)                  => +1.234500000
    +(print -1.2345)                  => -1.234500000
    +
    +(setq *float-format* "%%")       ; bad format
    +(print 1.0)                      => %%
    +
    +(setq *float-format* "%g")       ; reset to shortest notation
    +
    + +

    Note: The string in the *float-format* variable is +the format specifier for the the underlying 'sprintf' +C-function.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-gc-flag.htm b/docsrc/xlisp/xlisp-doc/reference/global-gc-flag.htm new file mode 100644 index 0000000..33e3834 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-gc-flag.htm @@ -0,0 +1,79 @@ +XLISP *gc-flag* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *gc-flag*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xldmem.c

    + +

    Syntax

    + +
    +
     *gc-flag*
    +
    + +

    Description

    + +

    *gc-flag* is a system variable that controls the printing of a garbage +collection message. If *gc-flag* is +NIL , +no garbage collection messages will be printed. If *gc-flag* is +non-NIL , a garbage collection +message will be printed whenever a gc takes +place. The default value for *gc-flag* is +NIL. The message will be of the form:

    + +
    +[ gc: total 4000, 2497 free ]
    +
    + + +

    Examples

    + +
    +*gc-flag*           ; returns NIL
    +(gc)                ; returns NIL
    +(setq *gc-flag* T)  ; set up for message
    +(gc)                ; prints a gc message
    +
    + +

    See the +*gc-flag* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-gc-hook.htm b/docsrc/xlisp/xlisp-doc/reference/global-gc-hook.htm new file mode 100644 index 0000000..df39b55 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-gc-hook.htm @@ -0,0 +1,125 @@ +XLISP *gc-hook* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *gc-hook*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xldmem.c

    + +

    Syntax

    + +
    +
     *gc-hook*
    +
    + +

    Description

    + +

    *gc-hook* is a system variable that allows a user function to be +performed everytime garbage is collected [either explicitly with +gc or automatically]. The default value for +*gc-hook* is NIL. When *gc-hook* is set to +a non-NIL symbol, it is enabled to execute +the specified user routine. The user routine can be a quoted symbol or a +closure. There are two parameters to the user routine, the total number of +nodes and current free nodes after the garbage collection.

    + +

    Examples

    + +
    +*gc-hook*                           ; returns NIL
    +(gc)                                ; returns NIL
    +
    +(defun mygchook (&rest stuff)       ; define the hook
    +  (print stuff)
    +  (print "my hook"))
    +
    +(setq *gc-hook* 'mygchook)          ; set up *GC-HOOK*
    +
    +(gc)                                ; prints (2640 232)
    +                                    ;        "my hook"
    +                                    ; returns NIL
    +
    +(setq *gc-flag* T)                  ; turn on the system GC message
    +
    +(gc)                                ; prints
    +                                    ;   [ gc: total 2640, (2640 241)
    +                                    ;   "my hook"
    +                                    ;   236 free ]
    +                                    ; returns NIL
    +
    +(setq *gc-flag* NIL)                ; turn off GC message
    +
    +(setq *gc-hook* (lambda (x y)       ; enable user routine
    +                  (princ "\007")))  ;   that beeps at every GC
    +
    +(gc)                                ; beeps
    +
    +(defun expand-on-gc (total free)    ; define EXPAND-ON-GC
    +  (if (< (/ free 1.0 total) .1)     ; IF free/total < .10
    +      (progn (expand 2)             ;    THEN expand memory
    +             (princ "\007"))))      ;         and beep
    +
    +                                    ; NOTE: XLISP already gets more nodes
    +                                    ; automatically, this is just an example.
    +
    +(setq *gc-hook* 'expand-on-gc)      ; enable EXPAND-ON-GC
    +(gc)                                ; beeps when low on nodes
    +
    + +

    Note: The *gc-hook* and *gc-flag* +facilities can interact. If you do printing in the *gc-hook* user form and +enable *gc-flag* , the +*gc-hook* printing will come out in the middle of the +*gc-flag* message.

    + +

    Note: The *gc-hook* user form is evaluated after the execution of +the actual garbage collection code. This means that if the user form causes +an error, it does not prevent a garbage collection.

    + +

    Note: Since *gc-hook* is set to a symbol, the user defined form +can be changed by doing another defun [or +whatever] to the symbol in *gc-hook*. Note also that you should define the +symbol first and then set *gc-hook* to the symbol. If you don't, an +automatic garbage collection might occur before you set *gc-hook*, +generating an error and stopping your program.

    + +

    See the +*gc-hook* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-integer-format.htm b/docsrc/xlisp/xlisp-doc/reference/global-integer-format.htm new file mode 100644 index 0000000..40cb06f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-integer-format.htm @@ -0,0 +1,129 @@ +XLISP *integer-format* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *integer-format*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlprin.c

    + +

    Syntax

    + +
    +
     *integer-format*
    +
    + +

    Description

    + +

    *integer-format* is a system variable that allows a user to specify how +integer numbers are to be printed by XLISP. The value of *integer-format* +should be set to one of the string expressions "%ld", +"%lo" or "%lx" [the character after the percent +character is the lower-case 'L' character]. These format strings are similar +to C-language floating point specifications:

    + + +

    + + + + + + + + + + + + + + + + + + + + +
    "%ld"  -  decimal
    "%lu"  -  unsigned decimal
    "%lo"  -  unsigned octal
    "%lx"  -  unsigned hexadecimal

    + +

    The default value for *integer-format* is the string "%ld".

    + +

    Examples

    + +
    +*integer-format*               ; returns "%ld"
    +
    +(setq *integer-format* "%ld")  ; signed decimal
    +(print 1)                      ; prints 1
    +(print 1234)                   ; prints 1234
    +(print -1)                     ; prints -1
    +(print -1234)                  ; prints -1234
    +
    +(setq *integer-format* "%lo")  ; octal notation
    +(print 1)                      ; prints 1
    +(print 1234)                   ; prints 2322
    +(print -1)                     ; prints 37777777777
    +(print -1234)                  ; prints 37777775456
    +
    +(setq *integer-format* "%lx")  ; hexadecimal notation
    +(print 1)                      ; prints 1
    +(print -1)                     ; prints ffffffff
    +(print 1234)                   ; prints 4d2
    +(print -1234)                  ; prints fffffb2e
    +
    +(setq *integer-format* "%u")   ; unsigned decimal
    +(print 1)                      ; prints 1
    +(print 1234)                   ; prints 1234
    +(print -1)                     ; prints 4294967295
    +(print -1234)                  ; prints 4294966062
    +
    +(setq *integer-format* "hi")   ; a bad notation
    +(print 1)                      ; prints hi
    +(print 9999)                   ; prints hi
    +
    +(setq *integer-format* "%ld")  ; reset to original "%ld"
    +
    + +

    Note: There can be other characters put in the string, but in +general, this will not produce particularly desirable behaviour. There is no +error checking performed on the format string.

    + +

    See the +*integer-format* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-obarray.htm b/docsrc/xlisp/xlisp-doc/reference/global-obarray.htm new file mode 100644 index 0000000..5014f40 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-obarray.htm @@ -0,0 +1,79 @@ +XLISP *obarray* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *obarray*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlsym.c

    + +

    Syntax

    + +
    +
     *obarray*
    +
    + +

    Description

    + +

    The *obarray* system variable contains the system symbol table. +This symbol table is an XLISP array that is constructed out of lists.

    + +

    Examples

    + +
    +(defun lookin (sym)                  ; create a function to
    +  (aref *obarray*                    ;   look inside *OBARRAY*
    +    (hash sym (length *obarray*))))  ;   and look for a specific
    +                                     ;   symbol - returns a list
    +
    +(lookin "CAR")                       ; returns (TEST PEEK CAR)
    +(lookin "car")                       ; returns NIL
    +
    + +

    Note: When looking into *obarray* or +interning symbols, remember that +"car" and "CAR" written as strings [with quotation marks +in front and behind] are two different symbols in *obarray*. Remember also +that normal symbols created by XLISP are upper case names. So, if you type +in 'car as a normal symbol [with a single quote in front of it], it will be +the symbol CAR after this normal upper-casing operation.

    + +

    See the +*obarray* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-print-case.htm b/docsrc/xlisp/xlisp-doc/reference/global-print-case.htm new file mode 100644 index 0000000..34b84a2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-print-case.htm @@ -0,0 +1,82 @@ +XLISP *print-case* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *print-case*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlprin.c

    + +

    Syntax

    + +
    +
     *print-case*
    +
    + +

    Description

    + +

    *print-case* is a system variable that allows a user to specify how +symbols are to be printed by XLISP. If *print-case* is set to ':downcase', +all symbols will be printed in lower case characters. If *print-case* is set +to ':upcase', all symbols will be printed in upper case characters. If +*print-case* is set to anything other than ':upcase' or ':downcase', all +symbols will be printed in upper case characters. The default value for +*print-case* is ':upcase'.

    + +

    Examples

    + +
    +(setq *print-case* :downcase)  ; returns :downcase
    +(setq a 'b)                    ; returns b
    +
    +(setq *print-case* 'foo)       ; returns FOO
    +(setq a 'b)                    ; returns B
    +
    +(setq *print-case* :upcase)    ; returns :UPCASE
    +(setq a 'b)                    ; returns B
    +
    + +

    Common Lisp: Common LISP supports a third keyword ':capitalize' to +print the first character of symbol names in upper-case. XLISP does not +support this. In XLISP, if *print-case* is set to ':capitalize', all +characters in symbols names will be printed in upper-case characters.

    + +

    See the +*print-case* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-readtable.htm b/docsrc/xlisp/xlisp-doc/reference/global-readtable.htm new file mode 100644 index 0000000..caa3d70 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-readtable.htm @@ -0,0 +1,166 @@ +XLISP *readtable* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *readtable*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlread.c

    + +

    Syntax

    + +
    +
     *readtable*
    +
    + +

    Description

    + +

    The *readtable* is a system variable that contains XLISP's data +structures relating to the processing of characters from the user (or files) +and read-macro expansions. The table is 128 entries [0..127] for each of the +7-bit ASCII characters that +XLISP can read. Each entry in the *readtable* array must be one of +NIL , +:constituent , +:white-space , +:sescape , +:mescape , a +:tmacro dotted pair or a +:nmacro dotted pair with the meaning +of:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     NIL  -  the character is invalid   [see + nil]
    :CONSTITUENT  -  the character is valid, as is   [see + :constituent]
    :WHITE-SPACE  -  the character may be skipped over   [see + :white-space]
    :SESCAPE  -  the single escape character '\'   [see + :sescape]
    :MESCAPE  -  the multiple escape character '|'   [see + :mescape]
    (:TMACRO . fun)  -  a terminating readmacro   [see + :tmacro]
    (:NMACRO . fun)  -  a non-terminating readmacro   [see + :nmacro]

    + + +

    In the case of :nmacro and +:tmacro , the form of the +*readtable* entry is a list like:

    + +
    +(:tmacro . function)
    +(:nmacro . function)
    +
    + +

    The 'function' can be a built-in read-macro function or a user defined +lambda expression. The 'function' takes two +parameters, an input stream specification, and an integer that is the +character value. The 'function' should return +NIL if the character is 'white-space' or a +value consed with +NIL to return the value.

    + +

    Examples

    + +
    +*readtable*             ; returns the current table
    +
    +;; define a function to look in a table and
    +;; print out any entries with a function
    +
    +(defun look-at (table)
    +  (dotimes (ch 127)
    +    (prog ((entry (aref table ch)))
    +      (case entry
    +        (nil          nil)
    +        (:constituent nil)
    +        (:white-space nil)
    +        (:sescape     nil)
    +        (:mescape     nil)
    +        (t (princ (int-char ch))))))
    +  (terpri))
    +
    +(look-at *readtable*)   ; prints "#'(),;`
    +
    + +

    Caution: If you experiment with *readtable*, it is useful to save +the old value in a variable, so that you can restore the system state.

    + +

    See the +*readtable* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-rslt.htm b/docsrc/xlisp/xlisp-doc/reference/global-rslt.htm new file mode 100644 index 0000000..84e2254 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-rslt.htm @@ -0,0 +1,83 @@ +XLISP *rslt* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *rslt*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  not explicitely defined

    + +

    Syntax

    + +

    + +
    +
    *rslt*
    +
    + +

    + +

    Description

    + +

    When a function returns more than one value, the global Nyquist *rslt* +variable is set to a list of the 'extra' values. This provides a +make-shift version of the 'multiple-value-return' +facility in Common Lisp.

    + +

    Examples

    + +
    +(defun cl:values (&rest args)
    +  (setq *rslt* args)
    +  (first args))
    +
    +(values 1 2 3)  => 1
    +*rslt*          => (1 2 3)
    +
    + +

    See defun, first, +rest, +&rest, +setq.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-standard-input.htm b/docsrc/xlisp/xlisp-doc/reference/global-standard-input.htm new file mode 100644 index 0000000..37cdcbc --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-standard-input.htm @@ -0,0 +1,73 @@ +XLISP *standard-input* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *standard-input*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c

    + +

    Syntax

    + +
    +
     *standard-input*
    +
    + +

    Description

    + +

    The *standard-input* system variable contains a file pointer that points +to the file where all normal input from the programmer or user comes from. +The default file for *standard-input* is the system standard input device, +normally the system keyboard.

    + +

    Examples

    + +
    +*standard-input*   ; returns #<File-Stream: #2442e>
    +
    + +

    Note: Be careful when modifying the *standard-input*. If you do +not save the old file pointer, you will not be able to return to normal +operation and will need to exit XLISP. If the file or source that you have +set *standard-input* to does not reset *standard-input* to its previous +value, you will never get control back to the keyboard.

    + +

    See the +*standard-input* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-standard-output.htm b/docsrc/xlisp/xlisp-doc/reference/global-standard-output.htm new file mode 100644 index 0000000..65c0d73 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-standard-output.htm @@ -0,0 +1,81 @@ +XLISP *standard-output* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *standard-output*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c

    + +

    Syntax

    + +
    +
     *standard-output*
    +
    + +

    Description

    + +

    The *standard-output* system variable contains a file pointer that points +to the file where all normal printing and messages from XLISP will go. The +default file for *standard-output* is the system standard output device, +normally the screen display.

    + +

    Examples

    + +
    +*standard-output*                        ; returns #<File-Stream: #24406>
    +(setq old-so *standard-output*)          ; save the file pointer
    +(setq fp (open "f" :direction :output))  ; open a new output file
    +(setq *standard-output* fp)              ; change where output goes
    +
    +(+ 2 2)                                  ; you won't see any messages
    +                                         ; just the echo of input line
    +
    +(setq *standard-output* old-so)          ; restore standard output
    +(close fp)                               ; close file
    +
    + +

    Note: Be careful when modifying the *standard-output*, you will +not be able to see what you are doing. If you do not save the old file +pointer, you will not be able to return to normal operation and will need to +exit XLISP.

    + +

    See the +*standard-output* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-trace-output.htm b/docsrc/xlisp/xlisp-doc/reference/global-trace-output.htm new file mode 100644 index 0000000..697a70f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-trace-output.htm @@ -0,0 +1,71 @@ +XLISP *trace-output* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *trace-output*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c, xlio.c

    + +

    Syntax

    + +
    +
     *trace-output*
    +
    + +

    Description

    + +

    The *trace-output* system variable contains a file pointer that points to +the file where all trace output goes to. The default file for *trace-output* +is the system standard error device, normally the screen.

    + +

    Examples

    + +
    +*trace-output*   ; returns #<File-Stream...>
    +
    + +

    Note: *trace-output*, +*debug-io* and +*error-output* are normally all set to +the same file stream 'stderr'.

    + +

    See the +*trace-output* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-tracelimit.htm b/docsrc/xlisp/xlisp-doc/reference/global-tracelimit.htm new file mode 100644 index 0000000..7af1f15 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-tracelimit.htm @@ -0,0 +1,103 @@ +XLISP *tracelimit* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *tracelimit*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c, xldbug.c

    + +

    Syntax

    + +
    +
     *tracelimit*
    +
    + +

    Description

    + +

    The *tracelimit* system variable controls the number of forms printed on +entry to the break +loop. If *tracelimit* is an integer, then the integer is the +maximum number of forms that will be printed. If *tracelimit* is NIL or a non-integer, then all of the forms +will be printed. Note that *tracenable* +needs to be set to a non-NIL value to +enable the printing of back-trace information on entry to the break loop.

    + +

    Examples

    + +
    +(defun foo (x) (fee x))   ; define FOO
    +(defun fee (y) (break))   ; define FEE
    +(setq *tracenable* T)     ; enable the back trace
    +(setq *tracelimit* NIL)   ; show all the entries
    +
    +(foo 5)                   ; break: **BREAK**
    +                          ; prints Function:#<Subr-BREAK...>
    +                          ;        Function:#<Closure-FEE...>
    +                          ;        Arguments:
    +                          ;          5
    +                          ;        Function:#<Closure-FOO...>
    +                          ;        Arguments:
    +                          ;          5
    +
    +(clean-up)                ; from break loop
    +(setq *tracelimit* 2)     ; show only 2 entries
    +
    +(foo 5)                   ; break: **BREAK**
    +                          ; prints Function:#<Subr-BREAK...>
    +                          ;        Function:#<Closure-FEE...>
    +                          ;        Arguments:
    +                          ;          5
    +
    +(clean-up)                ; from break loop
    +
    + +

    Note: *tracenable* and +*tracelimit* system variables have to do with back trace information at +entry to a +break loop +and are not related to the +trace and +untrace functions.

    + +

    See the +*tracelimit* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-tracelist.htm b/docsrc/xlisp/xlisp-doc/reference/global-tracelist.htm new file mode 100644 index 0000000..3c84faa --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-tracelist.htm @@ -0,0 +1,74 @@ +XLISP *tracelist* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *tracelist*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c, xleval.c

    + +

    Syntax

    + +
    +
     *tracelist*
    +
    + +

    Description

    + +

    The *tracelist* system variable contains a list of the current +functions being traced.

    + +

    Examples

    + +
    +(defun foo (x) (print (car x)))  ; define FOO
    +(trace foo)                      ; returns (FOO)
    +(trace car)                      ; returns (CAR FOO)
    +
    +(print *tracelist*)              ; prints (CAR FOO)
    +
    +(untrace foo)                    ; returns (CAR)
    +(untrace car)                    ; returns NIL
    +
    +(print *tracelist*)              ; prints NIL
    +
    + +

    See the +*tracelist* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-tracenable.htm b/docsrc/xlisp/xlisp-doc/reference/global-tracenable.htm new file mode 100644 index 0000000..8863e96 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-tracenable.htm @@ -0,0 +1,105 @@ +XLISP *tracenable* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *tracenable*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system variable
    Source:  -  xlinit.c, xldbug.c

    + +

    Syntax

    + +
    +
     *tracenable*
    +
    + +

    Description

    + +

    The *tracenable* system variable controls whether or not the +break loop +prints any back trace information on entry to the +break loop. If +*tracenable* is NIL , then +there will be no information printed on entry to the +break loop. +If *tracenable* is non-NIL , +then information will be printed. The 'init.lsp' initialization file sets +*tracenable* usually to NIL , +which suppresses the printing.

    + +

    Examples

    + +
    +(defun foo (x) (fee x))   ; define FOO
    +(defun fee (y) (break))   ; define FEE
    +(setq *tracenable* T)     ; enable the back trace
    +(setq *tracelimit* NIL)   ; show all the entries
    +
    +(foo 5)                   ; break: **BREAK**
    +                          ; prints  Function:#<Subr-BREAK...>
    +                          ;         Function:#<Closure-FEE...>
    +                          ;         Arguments:
    +                          ;           5
    +                          ;         Function:#<Closure-FOO...>
    +                          ;         Arguments:
    +                          ;           5
    +
    +(clean-up)                ; from break loop
    +(setq *tracelimit* 2)     ; show only 2 entries
    +
    +(foo 5)                   ; break: **BREAK**
    +                          ; prints  Function:#<Subr-BREAK...>
    +                          ;         Function:#<Closure-FEE...>
    +                          ;         Arguments:
    +                          ;           5
    +
    +(clean-up)                ; from break loop
    +
    + +

    Note: *tracenable* and +*tracelimit* system variables have to do +with back trace information at entry to a +break loop +and are not related to the +trace and +untrace functions.

    + +

    See the +*tracenable* +system variable in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/global-unbound.htm b/docsrc/xlisp/xlisp-doc/reference/global-unbound.htm new file mode 100644 index 0000000..424b603 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/global-unbound.htm @@ -0,0 +1,70 @@ +XLISP *unbound* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *unbound*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system constant
    Source:  -  xlinit.c, xlsym.c

    + +

    Syntax

    + +
    +
     *unbound*
    +
    + +

    Description

    + +

    The *unbound* system constant is used to indicate when a symbol has no +value. *unbound* is set to the value *unbound*. This means that the system +thinks the symbol *unbound* has no value.

    + +

    Examples

    + +
    +*unbound*            ; error: unbound variable
    +(setq a 5)           ; returns 5
    +a                    ; returns 5
    +(setq a '*unbound*)  ; returns *UNBOUND*
    +a                    ; error: unbound variable
    +
    + +

    See the +*unbound* +system constant in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/go.htm b/docsrc/xlisp/xlisp-doc/reference/go.htm new file mode 100644 index 0000000..3c3715f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/go.htm @@ -0,0 +1,106 @@ +XLISP go + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    go

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (go tag-symbol)
    +
    tag-symbol - a symbol
    +returns - never returns a value
    +
    + +

    Description

    + +

    The 'go' special form allows 'goto' style branching within 'block' constructs +[do , +do* , +dolist , +dotimes , +tagbody , +loop , +prog and +prog*]. The +'tag-symbol' is the 'label' and must exist somewhere within the 'block' +that the 'go' occurs within. Otherwise an error will be generated:

    + +
    +error: no target for GO
    +
    + +

    'go' never returns a value. If the 'tag-symbol' exists, then +the execution will continue immediately after the'tag-symbol'.

    + +

    Examples

    + +
    +(defun foo (i j)                   ; define FOO
    +  (prog ()                         ; with a PROG
    +         (print "begin")
    +   start (print j)                 ; tag - START
    +         (setq j (1- j))
    +         (if (eql i j) (GO start)  ; 2-way branch
    +                       (GO end))
    +         (print "hello")           ; won't ever be reached
    +   end   (print "done")            ; tag - END
    +         (return 42)))
    +
    +(foo 1 2)                          ; prints  "begin" 2 1 "done"
    +                                   ;   returns 42
    +
    +(foo 2 1)                          ; prints  "begin" 1 "done"
    +                                   ;   returns 42
    +
    + +

    Note: Although 'go' will accept a 'tag-symbol' that is not a +symbol, it will not find this improper 'tag-symbol'. An error will be +generated:

    + +
    +error: no target for GO
    +
    + +

    See the +go +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/hash.htm b/docsrc/xlisp/xlisp-doc/reference/hash.htm new file mode 100644 index 0000000..03abbe7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/hash.htm @@ -0,0 +1,90 @@ +XLISP hash + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    hash

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xlsym.c

    + +

    Syntax

    + +
    +
    (hash name table-size)
    +
    name - a symbol or string expression
    +table-size - an integer expression
    +returns - the hash index as an integer value
    +
    + +

    Description

    + +

    The 'hash' function computes and returns an integer index for a given +symbol 'name' and a given size of hash table 'table-size'. The intention is +for 'hash' to be used with tables made by +make-array and accessed by +aref.

    + +

    Examples

    + +
    +(hash "zzzz" 1000)        ; returns index 322
    +(hash "ZZZZ" 1000)        ; returns index 626
    +(hash 'ZZZZ  1000)        ; returns index 626
    +(hash "hiho" 1000)        ; returns index 519
    +(hash 'hiho  1000)        ; returns index 143
    +(hash "abcd" 1000)        ; returns index 72
    +
    +;; create a function to look inside *OBARRAY* and
    +;; look for a specific symbol - returns a list
    +
    +(defun lookin (sym)
    +  (aref *obarray*
    +        (hash sym (length *obarray*))))
    +
    +(lookin 'caar)       ; returns the hash table entry
    +                     ;   (ZEROP CDDDDR CAAR HASH)
    +
    + +

    Note: This is a useful function for creating and accessing tables. +It is also useful for looking inside of XLISP's own symbol table +*obarray*.

    + +

    See the +hash +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/if.htm b/docsrc/xlisp/xlisp-doc/reference/if.htm new file mode 100644 index 0000000..423e5bf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/if.htm @@ -0,0 +1,83 @@ +XLISP if + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    if

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (if test-expr then-expr [else-expr])
    +
    test-expr - an expression
    +then-expr - the THEN clause, an expression
    +else-expr - the ELSE clause, an optional expression
    +returns - the value of the selected expression
    +
    + +

    Description

    + +

    The 'if' special form evaluates the 'test-expr'. If 'test-expr' evaluates +to a non-NIL value, then 'then-expr' is +evaluated and returned as the result. If 'test-expr' evaluates to +NIL and there is an 'else-expr', then the +'else-expr' is evaluated and its result is returned. If there is no +'else-expr' and 'test-expr' evaluates to +NIL , then +NIL is returned as a result.

    + +

    Examples

    + +
    +(if T (print "will print")     ; prints  "will print"
    +      (print "won't print"))
    +
    +(if NIL (print "won't print")
    +        (print "will print"))  ; prints  "will print"
    +
    +(if 'a T NIL)                  ; returns T
    +
    +(if NIL 'nope 'yep)            ; returns YEP
    +
    + +

    See the + if  +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/incf.htm b/docsrc/xlisp/xlisp-doc/reference/incf.htm new file mode 100644 index 0000000..bcf70f2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/incf.htm @@ -0,0 +1,88 @@ +XLISP incf + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    incf

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp macro (closure)
    Source:  -  misc.lsp

    + +

    Syntax

    + +

    + +
    +
    (incf symbol)
    +
    symbol - a symbol with numerical value bound to it
    +returns - the new value of the symbol
    +
    + +

    + +

    In Nyquist, 'incf' is implemented as a Lisp macro:

    + +
    +(defmacro incf (symbol)
    +  `(setf ,symbol (1+ ,symbol)))
    +
    + +

    Description

    + +

    The 'incf' macro is used for incrementing a numerical value of a variable. +1 is added to the number and the result is stored in the +variable. An error is signalled if the variable doesn't hold a +number.

    + +

    Examples

    + +
    +(setq n 1)     => 1
    +(incf n)       => 2
    +n              => 2
    +(incf n)       => 3
    +
    +(setq n -1.8)  => -1.8
    +(incf n)       => -0.8
    +(incf n)       => 0.2
    +(incf n)       => 1.2
    +n              => 1.2
    +
    +(setq n #\a)  => #\a
    +(incf a)      => error: bad argument type - #\a
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/increment.htm b/docsrc/xlisp/xlisp-doc/reference/increment.htm new file mode 100644 index 0000000..06f3c57 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/increment.htm @@ -0,0 +1,75 @@ +XLISP 1+ + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    1+

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (1+ expr)
    +
    expr - integer or floating point number/expression
    +returns - the number plus one
    +
    + +

    + +

    Description

    + +

    The '1+' [increment] function adds one to a number and +returns the result.

    + +

    Examples

    + +
    +(1+ 1)     => 2
    +(1+ 99.1)  => 100.1
    +(1+ 1 2)   => error: too many arguments
    +
    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/info.htm b/docsrc/xlisp/xlisp-doc/reference/info.htm new file mode 100644 index 0000000..d76b33c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/info.htm @@ -0,0 +1,63 @@ +XLISP info + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    info

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xldmem.c

    + +

    Syntax

    + +
    +
    (info)
    +
    returns - NIL
    +
    + +

    Description

    + +

    The 'info' function shows information about memory usage.

    + +

    Examples

    + +
    +> (info)
    +[ Free: 5689, GC calls: 17, Total: 675111; samples 1KB, 0KB free]
    +NIL
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/int-char.htm b/docsrc/xlisp/xlisp-doc/reference/int-char.htm new file mode 100644 index 0000000..8bdd97e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/int-char.htm @@ -0,0 +1,92 @@ +XLISP int-char + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    int-char

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (int-char int)
    +
    int - an integer numeric expression
    +returns - the character with that code
    +
    + +

    Description

    + +

    The 'int-char' function returns a character which is the result of turning the +'int' expression into a character. If a 'int' cannot be made into a +character, an error is signalled:

    + +
    +error: character code out of range
    +
    + +

    The range that 'int' produces a valid character is 0 through 255.

    + +

    Examples

    + +
    +(int-char 48)    ; returns #\0
    +(int-char 65)    ; returns #\A
    +(int-char 97)    ; returns #\a
    +(int-char 91)    ; returns #\[
    +(int-char 10)    ; returns #\Newline
    +(int-char 999)   ; error - character code out of range
    +
    + +

    Common Lisp: Common Lisp specifies that 'int-char' should return a +NIL when there is no valid character for +the integer value being passed in while XLISP generates an error in these cases. +In some cases it is possible to substitue the +code-char function for 'int-char'.

    + +

    Note: Unlike the char-code and +char-int functions, +code-char and 'int-char' are not identical +in use. code-char accepts 0..127 for its +range and then produces NIL results while +'int-char' accepts 0..255 for its range and then produces errors.

    + +

    See the +int-char +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/integerp.htm b/docsrc/xlisp/xlisp-doc/reference/integerp.htm new file mode 100644 index 0000000..9bce615 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/integerp.htm @@ -0,0 +1,82 @@ +XLISP integerp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    integerp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (integerp expr)
    +
    expr - the expression to check
    +returns -  T  if the value is an +integer, NIL otherwise
    +
    + +

    Description

    + +

    The 'integerp' predicate function checks if an 'expr' is a integer +number.  T  is returned if +'expr' is a integer number, +NIL is returned otherwise.

    + +

    Examples

    + +
    +(integerp 1)         ; returns T - integer
    +(integerp #x034)     ; returns T - integer readmacro
    +(integerp '1)        ; returns T - still an integer
    +(setq a 14)
    +(integerp a)         ; returns T - evaluates to int.
    +(integerp 0)         ; returns T - integer zero
    +
    +(integerp 1.2)       ; returns NIL - float
    +(integerp 0.0)       ; returns NIL - float zero
    +(integerp 'a)        ; returns NIL - symbol
    +(integerp #\a)       ; returns NIL - character
    +(integerp NIL)       ; returns NIL - NIL
    +(integerp #(0 1 2))  ; returns NIL - array
    +
    + +

    See the +integerp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/intern.htm b/docsrc/xlisp/xlisp-doc/reference/intern.htm new file mode 100644 index 0000000..3b23ac5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/intern.htm @@ -0,0 +1,117 @@ +XLISP intern + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    intern

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (intern name-str)
    +
    name-str - a string expression
    +returns - the new symbol
    +
    + +

    Description

    + +

    The 'intern' function takes a string name 'name-str' and creates a new +interned symbol. What this means is that the symbol 'name-str' will be +placed into the symbol hash table +*obarray*. It's value will be unbound. It's +property list will be NIL [empty]. If the +symbol already exists, no error or action is taken and the old values and +property lists remain intact. The 'intern' function returns the symbol as +its result.

    + +

    Examples

    + +
    +(defun lookin (sym)                  ; create a function to
    +  (aref *obarray*                    ;   look inside *OBARRAY* and
    +    (hash sym (length *obarray*))))  ;   look for a specific symbol
    +                                     ;   returns a list
    +
    +(lookin "FINGERS")                   ; see if "FINGERS" is a symbol
    +                                     ;   returns (:START1) - it isn't
    +
    +(intern "FINGERS")                   ; intern "FINGERS" as a symbol
    +                                     ;   returns FINGERS
    +
    +(lookin "FINGERS")                   ; returns (FINGERS :START1)
    +
    +(print fingers)                      ; error: unbound variable
    +                                     ;   it exists, but has no value
    +
    +(lookin "TOES")                      ; returns NIL - doesn't exist
    +toes                                 ; error: unbound variable
    +
    +(lookin "TOES")                      ; returns (TOES)
    +                                     ;   the act of looking for a
    +                                     ;   value or using a symbol
    +                                     ;   causes it to be INTERNed
    +
    +(lookin "KNEECAPS")                  ; returns (MAX MAPLIST)
    +                                     ;   KNEECAPS doesn't exist
    +
    +(setq kneecaps 'a-bone)              ; create symbol with a value
    +(lookin "KNEECAPS")                  ; returns (KNEECAPS MAX MAPLIST)
    +
    + +

    Note: When you 'intern' a string symbol like "fingers" +in lower case letters, this gets placed in the +*obarray* symbol table as a lower case +symbol. Note that this is different from doing an 'intern' on a string +symbol "FINGERS" in upper case letters which will get placed in +the *obarray* as a upper case symbol. +"fingers" and "FINGERS" then are two different symbols +in *obarray*. Remember also that normal +symbols created by XLISP are automatically converted to upper case names. +So, an intern of the lower case symbol name 'fingers and the upper case +symbol name 'FINGERS will result in the effect that both symbol names get +interned as the same upper-case symbol FINGERS.

    + +

    Common Lisp: Common LISP allows an optional package +specification, which XLISP does not support.

    + +

    See the +intern +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/interpolate.htm b/docsrc/xlisp/xlisp-doc/reference/interpolate.htm new file mode 100644 index 0000000..72cee34 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/interpolate.htm @@ -0,0 +1,76 @@ +XLISP interpolate + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    interpolate

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  xm.lsp

    + +

    Syntax

    + +

    + +
    +
    (interpolate x x1 y1 x2 y2)
    +
    x, x1, y1, x2, y2 - integer or floating point numbers
    +returns - the 'y' value corresponding to 'x'
    +
    + +

    + +

    In Nyquist, 'interpolate' is implemented as a Lisp function:

    + +
    +(defun interpolate (x x1 y1 x2 y2)
    +  (cond ((= x1 x2) x1)
    +        (t (+ y1 (* (- x x1) (/ (- y2 y1) (- x2 (float x1))))))))
    +
    + +

    Description

    + +

    The 'interpolate' function linearly interpolates [or extrapolates] +between points (x1, y1) and (x2, y2) to compute +the 'y' value corresponding to 'x'.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/intersection.htm b/docsrc/xlisp/xlisp-doc/reference/intersection.htm new file mode 100644 index 0000000..80af5f7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/intersection.htm @@ -0,0 +1,76 @@ +XLISP intersection + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    intersection

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  xm.lsp

    + +

    Syntax

    + +

    + +
    +
    (intersection list1 list2)
    +
    listN - a list of symbols or numbers
    +returns - the intersection of list1 and list2
    +
    + +

    + +

    In Nyquist, 'intersection' is implemented as a Lisp function:

    + +
    +(defun intersection (a b)
    +  (let (result)
    +    (dolist (elem a)
    +      (if (member elem b) (push elem result)))
    +    result))
    +
    + +

    Description

    + +

    The 'intersection' function computes the intersection of two lists.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-answer.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-answer.htm new file mode 100644 index 0000000..d17b39b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-answer.htm @@ -0,0 +1,107 @@ +XLISP :answer + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :answer

    + +
    + +

    + + + + + + + + + + +
    Type:  -  message selector
    Source:  -  xlobj.c

    + +

    Syntax

    + +

    + +
    +
    (send class :answer selector fargs body)
    +
    class - an existing class
    +selector - the message selector symbol
    +fargs - formal argument list of the same form as a lambda argument list
    +body - a list containing the method code
    +returns - the class object
    +
    + +

    + +

    Description

    + +

    The ':answer' message selector adds or changes a method in the specified +class. This method consists of the +message selector symbol, the formal argument list and the executable code +associated with the message.

    + +

    Examples

    + +
    +(setq myclass (send class :new '(var)))  ; create MYCLASS with VAR
    +
    +(send myclass :answer :isnew '()         ; set up initialization
    +  '((setq var nil) self))
    +
    +(send myclass :answer :set-it '(value)   ; create :SET-IT message
    +  '((setq var value)))
    +
    +(send myclass :answer :mine '()          ; create :MINE message
    +  '((print "hi there")))
    +
    +(setq my-obj (send myclass :new))        ; create MY-OBJ of MYCLASS
    +(send my-obj :set-it 5)                  ; VAR is set to 5
    +(send my-obj :mine)                      ; prints  "hi there"
    +
    + +

    Note: When you define a message in a + +class, the message is only valid for +instances of the class or its +sub-classes. You will get an error if you try to +send the message to the class where it was first +defined. If you want to add a message to a +class, you need to define it in the +super-class of the class.

    + +

    Message structure: The normal XLISP convention for a message is to +have a valid symbol preceeded by a colon like +:isnew or ':my-message'. However, it is +possible to define a message that is a symbol without a colon, but this +pollutes the global namespace and also makes the code less readable.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-class.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-class.htm new file mode 100644 index 0000000..75b1ef5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-class.htm @@ -0,0 +1,83 @@ +XLISP :class + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :class

    + +
    + +

    + + + + + + + + + + +
    Type:  -  message selector
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
    (send object :class)
    +
    object - an existing object
    +returns the class object
    +
    + +

    Description

    + +

    The ':class' message selector will cause a method to run that will return the +object which is the class of the specified 'object'. Note that the +returned value is an object which will look like:

    + +
    +#<Object: #18d8c>
    +
    + +

    The 'object' must exist or an error will be generated:

    + +
    +error: bad argument type
    +
    + +

    Examples

    + +
    +(send object :class)                     ; returns the CLASS object
    +(send class :class)                      ; returns the CLASS object
    +(setq new-cls (send class :new '(var)))  ; create NEW-CLS
    +(setq new-obj (send new-cls :new))       ; create NEW-OBJ of NEW-CLS
    +(send new-obj :class)                    ; returns the NEW-CLS object
    +(send new-cls :class)                    ; returns the CLASS object
    +
    + +

    See the +:class +message selector in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-constituent.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-constituent.htm new file mode 100644 index 0000000..f9eca40 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-constituent.htm @@ -0,0 +1,95 @@ +XLISP :constituent + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :constituent

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xlread.c

    + +

    Syntax

    + +
    +
     :constituent
    +
    + +

    Description

    + +

    ':constituent' is an entry that is used in the +*readtable* system variable that +contains XLISP's data structures relating to the processing of characters +from the user [or files] and read-macro expansions. The existance of the +':constituent' keyword means that the specified character is to be used, as +is, with no further processing. The system defines that the following +characters are ':constituent' characters:

    + +
    +0123456789
    +!$%&*+-./:<=>?@[]^_{}~
    +ABCDEFGHIJKLMNOPQRSTUVWXYZ
    +abcdefghijklmnopqrstuvwxyz
    +
    + +

    Examples

    + +
    +(defun look-at (table)               ; define a function to
    +  (dotimes (ch 127)                  ;   look in a table
    +    (prog ((entry (aref table ch)))  ;   and print out any
    +      (case entry                    ;   entries with a function
    +        (:CONSTITUENT
    +          (princ (int-char ch)))
    +        (T NIL))))
    +  (terpri))
    +
    +(look-at *readtable*)                ; prints  !$%&*+-./0123456789
    +                                     ;         :<=>?@ABCDEFGHIJKLM
    +                                     ;         NOPQRSTUVWXYZ[]^_ab
    +                                     ;         cdefghijklmnopqrstu
    +                                     ;         vwxyz{}~
    +
    + +

    Caution: If you experiment with +*readtable* , it is useful to +save the old value in a variable, so that you can restore the system +state.

    + +

    See the +:constituent +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-isa.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-isa.htm new file mode 100644 index 0000000..e1b3e5c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-isa.htm @@ -0,0 +1,83 @@ +XLISP :isnew + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :isa

    + +
    + +

    + + + + + + + + + + +
    Type:  -  message selector
    Source:  -  xlobj.c

    + +

    Syntax

    + +

    + +
    +
    (send object :isa class) - test if object inherits from class
    +
    returns -  T  if object +is an instance of class or a subclass of class, otherwise +NIL

    +
    + +

    + +

    Description

    + +

    The ':isa' message selector tests if an object inherits from a class.

    + +

    Examples

    + +
    +(setq a-class (send class :new '(state)))   ; create a new class A-CLASS with STATE
    +
    +(send a-class :answer :isnew '()            ; set up initialization
    +                             '((setq state nil) self))
    +
    +(send a-class :answer :set-it '(value)      ; create :SET-IT message
    +                              '((setq state value)))
    +
    +(setq an-obj (send a-class :new))           ; create AN-OBJ out of A-CLASS
    +
    +(send an-obj :show)                         ; returns object - STATE = NIL
    +
    +(send an-obj :set-it 5)                     ; STATE is set to 5
    +(send an-obj :show)                         ; returns object - STATE = 5
    +
    +(SEND an-obj :ISNEW)                        ; re-initialize AN-OBJ
    +(send an-obj :show)                         ; returns object - STATE = NIL
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-isnew.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-isnew.htm new file mode 100644 index 0000000..eb595bc --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-isnew.htm @@ -0,0 +1,96 @@ +XLISP :isnew + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :isnew

    + +
    + +

    + + + + + + + + + + +
    Type:  -  message selector
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
    (send object :isnew args)
    +
    object - an existing object
    +args - the arguments to be passed to the init code
    +returns - the object
    +
    + +
    +
    (send class :isnew ivars [cvars [superclass]])
    +
    class - an existing XLISP class
    +ivars - list of instance variables for the new class
    +cvars - list of class variable symbols for the new class
    +superclass - superclass for the new object, default is +object
    +returns - the new class object
    +
    + +

    Description

    + +

    The ':isnew' message selector causes an instance to run its +initialization method. If an ':isnew' message is sent to a class, the class +definition and state will be reset as specified in the arguments of the +message.

    + +

    Examples

    + +
    +(setq a-class (send class :new '(state)))   ; create a new class A-CLASS with STATE
    +
    +(send a-class :answer :isnew '()            ; set up initialization
    +                             '((setq state nil) self))
    +
    +(send a-class :answer :set-it '(value)      ; create :SET-IT message
    +                              '((setq state value)))
    +
    +(setq an-obj (send a-class :new))           ; create AN-OBJ out of A-CLASS
    +
    +(send an-obj :show)                         ; returns object - STATE = NIL
    +
    +(send an-obj :set-it 5)                     ; STATE is set to 5
    +(send an-obj :show)                         ; returns object - STATE = 5
    +
    +(SEND an-obj :ISNEW)                        ; re-initialize AN-OBJ
    +(send an-obj :show)                         ; returns object - STATE = NIL
    +
    + +

    See the +:isnew +message selector in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-mescape.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-mescape.htm new file mode 100644 index 0000000..a0210f5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-mescape.htm @@ -0,0 +1,86 @@ +XLISP :mescape + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :mescape

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xlread.c

    + +

    Syntax

    + +
    +
     :mescape
    +
    + +

    Description

    + +

    The ':mescape' keyword is an entry used in the +*readtable* system variable that +contains XLISP's data structures relating to the processing of characters +from the user (or files) and read-macro expansions. The existance of the +':mescape' keyword means that the specified character is to be used as a +multiple escape character. The system defines that the the vertical bar +character '|' is the only ':mescape' character.

    + +

    Examples

    + +
    +;; define a function to look in a table
    +;; and print out any :mescape character
    +
    +(defun look-at (table)
    +  (dotimes (ch 127)
    +    (prog ((entry (aref table ch)))
    +      (case entry
    +        (:mescape (princ (int-char ch)))
    +        (t nil))))
    +  (terpri))
    +
    +(look-at *readtable*)     ; prints |
    +
    + +

    Caution: If you experiment with +*readtable* , it is useful +to save the old value in a variable, so that you can restore the system +state.

    + +

    See the +:mescape +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-new.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-new.htm new file mode 100644 index 0000000..deee953 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-new.htm @@ -0,0 +1,86 @@ +XLISP :new + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :new

    + +
    + +

    + + + + + + + + + + +
    Type:  -  message selector
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
    (send class :new args)
    +
    class - an existing XLISP class except for class
    +args - the initializing arguments for the new instance
    +returns - the new class object
    +
    + +
    +
    (send class :new ivars [cvars [superclass]])
    +
    ivars - list of instance variables for new class
    +cvars - list of class variable symbols for new class
    +superclass - superclass for new object, the default is object
    +returns - the new class object
    +
    + +

    Description

    + +

    The ':new' message selector exhibits two different behaviors. When you +are creating an instance of a class you +only need the ':new' message [consisting of the message selector and any +data]. When you are creating a new class +with ':new', you need to specify instance variables and optionally the +class variables and superclass.

    + +

    Examples

    + +
    +(setq new-class (send class :new '(state)))      ; create NEW-CLASS with STATE
    +(setq new-obj (send new-class :new))             ; create NEW-OBJ of NEW-CLASS
    +(send new-obj :show)                             ; shows the object
    +
    +(setq sub-class (send class :new '(sub-state)    ; create SUB-CLASS of NEW-CLASS
    +                                 '() new-class))
    +(send sub-class :show)                           ; show the SUB-CLASS
    +
    + +

    See the +:new +message selector in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-nmacro.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-nmacro.htm new file mode 100644 index 0000000..17732a2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-nmacro.htm @@ -0,0 +1,103 @@ +XLISP :nmacro + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :nmacro

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xlread.c

    + +

    Syntax

    + +
    +
    (:nmacro . function)
    +
    function - a function
    +
    + +

    Description

    + +

    ':nmacro' is an entry that is used in the +*readtable* system variable that contains +XLISP's data structures relating to the processing of characters from the +user [or files] and read-macro expansions. The existance of the ':nmacro' +keyword means that the specified character is the start of a non-terminal +read macro. For ':nmacro', the form of the +*readtable* entry is a dotted pair +like:

    + +
    +(:nmacro . function)
    +
    + +

    The 'function' can be a built-in read-macro function or a user defined +lambda expression. The 'function' takes two parameters, an input stream +specification, and an integer that is the character value. The 'function' +should return NIL if the character is +'white-space' or a value consed with +NIL to return the value. The 'function' +will probably read additional characters from the input stream.

    + +

    Examples

    + +
    +(defun look-at (table)                ; define a function to
    +  (dotimes (ch 127)                   ;   look in a table
    +    (prog ((entry (aref table ch)))   ;   and print out any
    +      (if (and (consp entry)          ;   :NMACRO entries
    +               (equal (car entry)
    +                      ':nmacro))
    +          (princ (int-char ch)))))
    +  (terpri))
    +(look-at *readtable*)                 ;  prints #
    +
    + +

    Note: The system defines that the hash [#] character is a +non-terminal. This is because the hash is used for a variety of 'read macro +expansions' including function, an +ASCII code, and hexadecimal +numbers.

    + +

    Caution: If you experiment with +*readtable* , it is useful +to save the old value in a variable, so that you can restore the system +state.

    + +

    See the +:nmacro +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-sescape.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-sescape.htm new file mode 100644 index 0000000..44d98f9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-sescape.htm @@ -0,0 +1,84 @@ +XLISP :sescape + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :sescape

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xlread.c

    + +

    Syntax

    + +
    +
     :sescape
    +
    + +

    Description

    + +

    The ':sescape' keyword is an entry used in the +*readtable* system variable that contains +XLISP's data structures relating to the processing of characters from the +user [or files] and read-macro expansions. The existance of the ':sescape' +keyword means that the specified character is to be used as a single escape +character. The system defines that the the backslash character '\' is the +only defined ':sescape' character.

    + +

    Examples

    + +
    +;; define a function to look in a table
    +;; and print out any :SESCAPE character
    +
    +(defun look-at (table)
    +  (dotimes (ch 127)
    +    (prog ((entry (aref table ch)))
    +      (case entry
    +        (:SESCAPE (princ (int-char ch)))
    +        (t nil))))
    +  (terpri))
    +
    +(look-at *readtable*)    ; prints  \
    +
    + +

    Caution: If you experiment with *readtable*, it is useful to save +the old value in a variable, so that you can restore the system state.

    + +

    See the +:sescape +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-show.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-show.htm new file mode 100644 index 0000000..0700e31 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-show.htm @@ -0,0 +1,82 @@ +XLISP :show + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :show

    + +
    + +

    + + + + + + + + + + +
    Type:  -  message selector
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
    (send object :show)
    +
    object - an existing object
    +returns - the object
    +
    + +

    Description

    + +

    The ':show' message selector attempts to find the 'show' method in the +specified objects class. Since the ':show' +message selector is built-in in the root +class, this is always a valid message +selector. The object must already +exist.

    + +

    Examples

    + +
    +(setq my-class (send class :new '(state)))              ; create MY-CLASS with STATE
    +
    +(send my-class :answer :isnew '()                       ; set up initialization
    +                              '((setq state nil) self))
    +
    +(send my-class :answer :set-it '(value)                 ; create :SET-IT message
    +                               '((setq state value)))  
    +
    +(setq my-obj (send my-class :new))         ; create MY-OBJ of MY-CLASS
    +(send my-obj :show)                        ; returns object state including STATE = NIL
    +(send my-obj :set-it 5)                    ; STATE is set to 5
    +(send new-obj :show)                       ; error: unbound variable
    +
    + +

    See the +:show +message selector in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-tmacro.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-tmacro.htm new file mode 100644 index 0000000..d290d9d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-tmacro.htm @@ -0,0 +1,107 @@ +XLISP :tmacro + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :tmacro

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xlread.c

    + +

    Syntax

    + +
    +
    (:tmacro . function)
    +
    function - a function
    +
    + +

    Description

    + +

    ':tmacro' is an entry that is used in the +*readtable* system variable that contains +XLISP's data structures relating to the processing of characters from the +user [or files] and read-macro expansions. The existance of the ':tmacro' +keyword means that the specified character is the start of a terminal read +macro. For ':tmacro', the form of the +*readtable* entry is a dotted pair +like:

    + +
    +(:tmacro . function)
    +
    + +

    The 'function' can be a built-in read-macro function or a user defined +lambda expression. The 'function' takes two parameters, an input stream +specification, and an integer that is the character value. The 'function' +should return NIL if the character is +'white-space' or a value consed with +NIL to return the value. The 'function' +will probably read additional characters from the input stream.

    + +

    Examples

    + +
    +(defun look-at (table)                ; define a function to look in a table
    +  (dotimes (ch 127)                   ; and print out any :TMACRO entries
    +    (prog ((entry (aref table ch)))
    +      (if (and (consp entry)
    +               (equal (car entry) ':TMACRO))
    +          (princ (int-char ch)))))
    +  (terpri))
    +
    +(look-at *readtable*)                 ;  prints "'(),;`
    +
    + +

    Note: The system defines that the following are ':tmacro' +characters:

    + +
    +   \  "  `  ,  ( )  ;
    +
    + +

    [backslash, double quote, backquote, comma, opening parenthesis, closing +parenthesis, semicolon.]

    + +

    Caution: If you experiment with +*readtable* , it is useful +to save the old value in a variable, so that you can restore the system +state.

    + +

    See the +:tmacro +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keyword-white-space.htm b/docsrc/xlisp/xlisp-doc/reference/keyword-white-space.htm new file mode 100644 index 0000000..be3fed0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keyword-white-space.htm @@ -0,0 +1,92 @@ +XLISP :white-space + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    :white-space

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xlread.c

    + +

    Syntax

    + +
    +
     :white-space
    +
    + +

    Description

    + +

    The ':white-space' keyword is an entry that is used in the *readtable* system variable that contains +XLISP's data structures relating to the processing of characters from the +user [or files] and read-macro expansions. The existance of the +':white-space' keyword means that the specified character may be skipped +over. The system defines that 'tab', 'space', 'return' and 'line-feed' are +':white-space' characters.

    + +

    Examples

    + +
    +;; define a function to look in a table
    +;; and print out any white-space characters
    +
    +(defun look-at (table)
    +  (dotimes (ch 127)
    +    (prog ((entry (aref table ch)))
    +      (case entry
    +        (nil          nil)
    +        (:constituent nil)
    +        (:white-space (print ch))
    +        (t            nil))))
    +  (terpri))
    +
    +(look-at *readtable*)  ; prints  9   - tab
    +                       ;         10  - newline
    +                       ;         12  - formfeed
    +                       ;         13  - return
    +                       ;         32  - space
    +
    + +

    Caution: If you experiment with +*readtable* , it is useful +to save the old value in a variable, so that you can restore the system +state.

    + +

    See the +:white-space +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/keywordp.htm b/docsrc/xlisp/xlisp-doc/reference/keywordp.htm new file mode 100644 index 0000000..dc49926 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/keywordp.htm @@ -0,0 +1,78 @@ +XLISP keywordp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    keywordp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  sal-parse.lsp

    + +

    Syntax

    + +

    + +
    +
    (keywordp expr)
    +
    expr - an arbitrary Lisp expression
    +returns -  T  if the expression is a keyword symbol, NIL otherwise
    +
    + +

    + +
    +(defun keywordp (s)
    +  (and (symbolp s)
    +       (eq (type-of (symbol-name s)) 'string)
    +       (equal (char (symbol-name s) 0) #\:)))
    +
    + +

    Description

    + +

    The 'keywordp' function tests if a lisp expression is a keyword symbol.

    + +

    Examples

    + +
    +(keywordp :a)   => T
    +(keywordp :B)   => T
    +(keywordp 'c)   => NIL
    +(keywordp "d")  => NIL
    +(keywordp #\e)  => NIL
    +(keywordp 123)  => NIL
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/labels.htm b/docsrc/xlisp/xlisp-doc/reference/labels.htm new file mode 100644 index 0000000..16fbc3c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/labels.htm @@ -0,0 +1,101 @@ +XLISP labels + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    labels

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (labels ([function ... ]) expr ... )
    +
    function - a function definition binding which is of the form:
    +
    (symbol arg-list body)
    +
    symbol - the symbol specifying the function name
    +arg-list - the argument list for the function
    +body - the body of the function
    +expr - an expression
    +returns - the value of the last expression
    +
    + +

    Description

    + +

    The 'labels' special form is basically a local block construct that +allows local 'function' definitions followed by a block of code to evaluate. +The first form after the labels is the 'binding' form. It contains a series +of 'functions'. 'labels' allows the'functions' to be defined in a mutually +recursive manner. [The similar flet form +does not allow this.] The 'labels' form will go through and define the +'symbols' of the 'functions' and then sequentially execute the 'exprs'. The +value of the last 'expr' evaluated is returned. When the 'labels' is +finished execution, the 'symbols' that were defined will no longer +exist.

    + +

    Examples

    + +
    +(labels ((fuzz (x) (+ x x)))      ; a LABELS with a local function FUZZ
    +  (fuzz 2))                       ; returns 4
    +
    +                                  ; FUZZ no longer exists
    +(fuzz 2)                          ; error: unbound function - FUZZ
    +
    +                                  ; an empty LABELS
    +(labels () (print 'a))            ; prints A
    +
    +                                  ; LABELS form including
    +(labels ((inc (arg) (est arg))    ;   INC definition using EST
    +         (est (var) (* .1 var)))  ;   EST definition
    +  (inc 99) )                      ;   returns 9.9
    +
    +                                  ; FLET form including
    +(flet ((inc (arg) (est arg))      ;   INC definition using EST
    +       (est (var) (* .1 var)))    ;   EST definition
    +  (inc 99)                        ; error: unbound function - EST
    +
    + +

    Note: flet does not allow +recursive definitions of functions. The 'label' special form does allow +this.

    + +

    See the +labels +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-aux.htm b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-aux.htm new file mode 100644 index 0000000..b3c5324 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-aux.htm @@ -0,0 +1,116 @@ +XLISP &aux + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    &aux

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xleval.c

    + +

    Syntax

    + +

    + +
    +
    &aux [aux-var | (aux-var aux-value)] ...
    +
    aux-var - auxiliary variable
    +aux-value - auxiliary variable initialization
    +
    + +

    + +

    Description

    + +

    In XLISP, there are several times that you define a formal argument list +for a body of code [like defun, +defmacro, +:answer and lambda]. The 'aux-var' variables are a +mechanism for you to define variables local to the function or operation +definition. If there is an optional 'aux-value', +they will be set to that value on entry to the body of code. Otherwise, they +are initialized to NIL. At +the end of the function or operation execution, these local symbols +and their values are removed.

    + +

    Examples

    + +

    A function 'my-add' with one required argument +'num1', one &rest +argument 'num-list', and one &aux +variable 'sum':

    + +
    +(defun my-add (num1 &rest num-list &aux sum)
    +  (setq sum num1)          ; initialize SUM
    +  (dolist (i num-list)     ; loop through the num-list
    +    (setq sum (+ sum i)))  ; add each number to SUM
    +  sum)                     ; return SUM when finished
    +
    +(my-add 1 2 3 4)    => 10
    +(my-add 5 5 5 5 5)  => 25
    +
    + +

    See  + , +defun, dolist, +&rest, +setq.

    + +

    A function 'more-keys' with one required +argument 'a' and three &aux variables 'b' +[initialized to NIL], 'c' +[initialized to 99], and 'd' [initialized +to  T ]:

    + +
    +(defun more-keys (a &aux b (c 99) (d t))
    +  (format t "a=~a b=~a c=~a d=~a~%" a b c d))
    +
    +> (more-keys "hi")
    +a=hi b=NIL c=99 d=T
    +NIL
    +
    + +

    See defun, format.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-key.htm b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-key.htm new file mode 100644 index 0000000..b9062d2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-key.htm @@ -0,0 +1,132 @@ +XLISP &key + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    &key

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xleval.c

    + +

    Syntax

    + +
    +
    &key key-arg ...
    +&key (key-arg [key-value [supplied-p-var]]) ...
    +&key ((key-symbol key-arg) [key-value [supplied-p-var]]) ...
    +
    key-arg - keyword argument
    +key-symbol - keyword argument symbol
    +key-value - keyword argument initialization
    +supplied-p-var - argument existence variable
    +
    + +

    Description

    + +

    In XLISP, there are several times that you define a formal argument list +for a body of code [like +defun , +defmacro , +:answer and +lambda]. +All of the formal arguments that are defined are required to appear in the +invocation of the defined function or operation. If there are any +&optional arguments defined, they will +be filled in order.

    + +

    There are other optional arguments called 'keyword' arguments. These +arguments are not position dependent but can be specified in any order by a +preceding keyword [a symbol with a leading colon ':']. If there is no +'key-symbol' specified in the argument list, the keyword will be constructed +from the 'key-arg' name by adding a leading colon ':'. For example a +'key-arg' of 'furter' will generate a keyword symbol of ':furter'.

    + +

    Like the &optional arguments, there +can be initialization values provided via the 'key-value' argument. If there +is no 'key-value' argument and no value is provided by the function call, +the 'key-arg' value will be NIL.

    + +

    The 'supplied-p-var', if it is specified, will contain a + T  if the 'key-arg' value was +supplied by the function call and a NIL if +it was not supplied by the function call. This 'supplied-p-var' allows the +programmer to test for an argument's existence. At the end of the function +or operation execution, these local symbols and their values are are +removed.

    + +

    Examples

    + +
    +(defun foo (a &key b c)
    +  (print a) (print b) (print c))
    +
    +(foo)                           ; error: too few arguments
    +(foo 1)                         ; prints 1 NIL NIL
    +(foo 1 2)                       ; prints 1 NIL NIL
    +(foo 1 :b 2 :c 3)               ; prints 1 2 3
    +(foo 1 :c 3 :b 2)               ; prints 1 2 3
    +(foo 1 :b 3 :b 2)               ; prints 1 3 NIL
    +
    +(defun fee (a &key (b 9 b-passed))
    +  (print a) (print b)
    +  (if b-passed (print "b was passed")
    +               (print "b not passed")))
    +
    +(fee)                           ; error: too few arguments
    +(fee 1)                         ; prints 1 9 "b not passed"
    +(fee 1 2)                       ; prints 1 9 "b not passed"
    +(fee 1 :b 2)                    ; prints 1 2 "b was passed"
    +
    +(defun fi (a &key ((:mykey b) 9 b-passed))
    +  (print a) (print b)
    +  (if b-passed (print "b was passed")
    +               (print "b not passed")))
    +
    +(fi)                            ; error: too few arguments
    +(fi 1)                          ; prints 1 9 "b not passed"
    +(fi 1 2)                        ; prints 1 9 "b not passed"
    +(fi 1 :b 2)                     ; prints 1 9 "b not passed"
    +(fi 1 :mykey 2)                 ; prints 1 2 "b was passed"
    +
    + +

    Note: There is a '&allow-other-keys' keyword in XLISP and +Common Lisp. In the case of XLISP, this keyword is extraneous since the +default for keyword arguments is to allow other keys (without errors).

    + +

    See the +&key +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-optional.htm b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-optional.htm new file mode 100644 index 0000000..1b746d0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-optional.htm @@ -0,0 +1,98 @@ +XLISP &optional + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    &optional

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xleval.c

    + +

    Syntax

    + +
    +
    &optional [opt-arg | (opt-arg [opt-value [supplied-p]])] ...
    +
    opt-arg - optional argument
    +opt-value - optional argument initialization value
    +supplied-p - optional argument existence variable
    +
    + +

    Description

    + +

    In XLISP, there are several times that you define a formal argument list +for a body of code like +defun , +defmacro , +:answer and +lambda. All of the formal arguments +that are defined are required to appear in the invocation of the defined +function or operation. If there are any '&optional' arguments defined, +they will be filled in order. If there are insufficient parameters for the +'&optional' arguments, they will contain +NIL , unless the arguments +have an 'opt-value' initial value specified. The 'supplied-p' variable, if +specified, will contain  T  if +the 'opt-arg' was supplied by the function call and +NIL if it was not supplied by the function +call. This 'supplied-p' variable allows the programmer to test for an +arguments existence. At the end of the function or operation execution, +these local symbols and their values are are removed.

    + +

    Examples

    + +
    +(defun foo                              ; define function FOO
    +  (a &optional b (c 1) )                ;   with some optional args
    +  (print a) (print b) (print c))
    +(foo)                                   ; error: too few arguments
    +(foo 1)                                 ; prints 1 NIL 1
    +(foo 1 2)                               ; prints 1 2 1
    +(foo 1 2 3)                             ; prints 1 2 3
    +
    +(defun fee                              ; define function FEE
    +  (a &optional (b 9 b-passed) )         ;   with some optional args
    +  (print a) (print b)
    +  (if b-passed (print "b was passed")
    +               (print "b not passed")))
    +(fee 1)                                 ; prints 1 9 "b not passed"
    +(fee 1 2)                               ; prints 1 2 "b was passed"
    +
    + +

    See the +&optional +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-rest.htm b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-rest.htm new file mode 100644 index 0000000..639465d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/lambda-keyword-rest.htm @@ -0,0 +1,104 @@ +XLISP &rest + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    &rest

    + +
    + +

    + + + + + + + + + + +
    Type:  -  keyword
    Source:  -  xleval.c

    + +

    Syntax

    + +
    +
    &rest [rest-arg]
    +
    rest-arg - rest argument symbol
    +
    + +

    Description

    + +

    In XLISP, there are several times that you define a formal argument list +for a body of code like +defun , +defmacro , +:answer and +lambda. All of the formal arguments that +are defined are required to appear in the invocation of the defined function +or operation. If there are any +&optional arguments defined, they will +be filled in order. If there is a '&rest' argument defined, and all +the required formal arguments and +&optional arguments are filled, any and +all further parameters will be passed into the function via the 'rarg' +argument. There can be only one 'rest-arg' argument for '&rest'. If +there are insufficient parameters for any of the +&optional or '&rest' arguments, +they will contain NIL. At the end of the +function or operation execution, these local symbols and their values are +removed.

    + +

    Examples

    + +
    +(defun foo                             ; define function FOO
    +  (a b &optional c d &rest e)          ;   with some of each argument
    +  (print a) (print b)
    +  (print c) (print d)                  ;   print out each
    +  (print e))
    +(foo)                                  ; error: too few arguments
    +(foo 1)                                ; error: too few arguments
    +(foo 1 2)                              ; prints 1 2 NIL NIL NIL
    +(foo 1 2 3)                            ; prints 1 2 3 NIL NIL
    +(foo 1 2 3 4)                          ; prints 1 2 3 4 NIL
    +(foo 1 2 3 4 5)                        ; prints 1 2 3 4 (5)
    +(foo 1 2 3 4 5 6 7 8 9)                ; prints 1 2 3 4 (5 6 7 8 9)
    +
    +(defun my-add                          ; define function MY-ADD
    +  (num1 &rest num-list &aux sum)       ;   with 1 arg, rest, 1 aux var
    +  (setq sum num1)                      ;   clear SUM
    +  (dotimes (i (length num-list) )      ;   loop through rest list
    +    (setq sum (+ sum (car num-list)))  ;      add the number to sum
    +    (setq num-list (cdr num-list)))    ;      and remove num from list
    +  sum)                                 ;   return sum when finished
    +(my-add 1 2 3 4)                       ; returns 10
    +(my-add 5 5 5 5 5)                     ; returns 25
    +
    + +

    See the +&rest +keyword in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/lambda.htm b/docsrc/xlisp/xlisp-doc/reference/lambda.htm new file mode 100644 index 0000000..6f656a2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/lambda.htm @@ -0,0 +1,109 @@ +XLISP lambda + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    lambda

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (lambda arg-list [body])
    +
    arg-list - a list of the formal arguments to the function of the form:
    +
    +
    ([arg1 ... ]
    + [&optional oarg1 ... ]
    + [&rest rarg]
    + [&key ... ]
    + [&aux aux1 ... ])
    +
    +body - a series of LISP forms (expressions) that are executed in order
    +returns - the function closure
    +
    + +

    Description

    + +

    The LAMBDA special form returns a function definition [an executable +function] that has no name. All of the 'argN' formal arguments that are +defined are required to appear in a call to the defined function. If there +are any &optional arguments defined, +they will be filled in order. If there is a +&rest argument defined, and all the +required formal arguments and &optional +arguments are filled, any and all further parameters will be passed into the +function via the 'rarg' argument. Note that there can be only one 'rarg' +argument for &rest. If there are +insufficient parameters for any of the +&optional or +&rest arguments, they will contain +NIL. The +&aux variables are a mechanism for you +to define variables local to the function definition. At the end of the +function execution, these local symbols and their values are are +removed.

    + +

    Read also the chapter about +lambda lists +in the XLISP 2.0 manual.

    + +

    Examples

    + +
    +(funcall (lambda (a b) (* a b)) 4 8 )  ; evaluate a lambda function
    +                                       ;   returns 32
    +
    +(funcall (lambda '(a b) (+ a b)) 1 2)  ; evaluate another function
    +                                       ;   returns 3
    +
    +(funcall (lambda (a b)                 ; evaluate a more complex function
    +            (print "a no-name fnc")    ;   prints "a no-name fnc"
    +            (* a b)) 3 8)              ;   and returns 24
    +
    + +

    Note: Using a setq on a 'lambda' +expression is not the same as a defun. A +setq on a 'lambda' will give the +variable the value of the 'lambda' closure. This does not mean that the +variable name can be used as a function.

    + +

    See the +lambda +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/last.htm b/docsrc/xlisp/xlisp-doc/reference/last.htm new file mode 100644 index 0000000..6abb312 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/last.htm @@ -0,0 +1,75 @@ +XLISP last + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    last

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (last list-expr)
    +
    list-expr - a list or list expression
    +returns - the last list node in the list
    +
    + +

    Description

    + +

    The 'last' function returns a list containing the last node or element of +a list. If the last node is a sub-list, this is returned unaffected.

    + +

    Examples

    + +
    +(last NIL)                     ; returns NIL
    +(last 'a)                      ; error: bad argument type
    +(last '(A))                    ; returns (A)
    +(last '(A B C D E))            ; returns (E)
    +(last '( A (B C) (D E (F))))   ; returns ((D E (F)))
    +
    +(setq children '(junie vicki cindy chris))
    +
    +(last children)                ; returns (CHRIS)
    +
    + +

    See the +last +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/length.htm b/docsrc/xlisp/xlisp-doc/reference/length.htm new file mode 100644 index 0000000..119d838 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/length.htm @@ -0,0 +1,74 @@ +XLISP length + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    length

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (length expr)
    +
    expr - a list expression or string expression
    +returns - the length of the list, array or string
    +
    + +

    Description

    + +

    The 'length' function returns the length of the 'expr'. If the 'expr' is +a string, the number of characters is returned. If the 'expr' is a list, the +number of top level elements [atoms or sublists] is returned. If the list is +NIL , a '0' is returned.

    + +

    Examples

    + +
    +(length NIL)                     ; returns 0
    +(length 'a)                      ; error: bad argument type
    +(length '(a))                    ; returns 1
    +(length '(1 2 3 4 5 6))          ; returns 6
    +(length '(a (b c) (d (e) f) g))  ; returns 4
    +(length "12345")                 ; returns 5
    +
    + +

    See the +length +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/let-star.htm b/docsrc/xlisp/xlisp-doc/reference/let-star.htm new file mode 100644 index 0000000..f6ac98a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/let-star.htm @@ -0,0 +1,106 @@ +XLISP let* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    let*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (let* ([binding ... ]) expr ... )
    +
    binding - a variable binding which is one of the forms: +
    +
    symbol
    +(symbol init-expr) +
    +
    symbol - a symbol
    +init-expr - an initialization expression for symbol
    +
    +expr - an expression
    +returns - the value of the last expression
    +
    + +

    Description

    + +

    The 'let*' special form is basically a local block construct that +contains symbols [with optional initializations] and a block of code +[expressions] to evaluate. The first form after the 'let*' is the 'binding' +form. It contains a series of 'symbols' or 'bindings'. The 'binding' is a +'symbol' followed by an initialization expression 'init-expr'. If there is +no 'init-expr', the 'symbol' will be initialized to +NIL. The execution of the bindings will +occur from the first to the last binding. The 'let*' form will go through +and create and initialize the symbols and then sequentially execute the +'exprs'. The value of the last 'expr' evaluated is returned. When the 'let*' +is finished execution, the 'symbols' that were defined will no longer exist +or retain their values.

    + +

    Examples

    + +
    +(let* (x y z)                     ; LET* with local vars
    +  (print x) (print y) (print z))  ;   prints   NIL NIL NIL
    +
    +(let* ((a 1) (b 2) (c 3))         ; LET* with local vars & init
    +  (print (+ a b c)))              ;   prints and returns 6
    +
    +(let* ((a 1) (b 2) (c (+ a b)))   ; LET* with local vars & init
    +  (print (+ a b c)))              ;   prints and returns 6
    +
    + +

    Note:

    + +
    +(let* (a b) ... )
    +
    + +

    can be understood as:

    + +
    +(let (a)
    +  (let (b)
    +    ... ))
    +
    + +

    See the +let* +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/let.htm b/docsrc/xlisp/xlisp-doc/reference/let.htm new file mode 100644 index 0000000..442fecf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/let.htm @@ -0,0 +1,94 @@ +XLISP let + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    let

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (let ([binding ... ]) expr ... )
    +
    binding - a variable binding which is one of the forms: +
    +
    symbol
    +(symbol init-expr) +
    +
    symbol - a symbol
    +init-expr - an initialization expression for symbol
    +
    +expr - an expression
    +returns - the value of the last expression
    +
    + +

    Description

    + +

    The 'let' special form is basically a local block construct that contains +symbols [with optional initializations] and a block of code [expressions] to +evaluate. The first form after the 'let' is the 'binding' form. It contains +a series of 'symbols' or 'bindings'. The 'binding' is a 'symbol' followed by +an initialization expression 'init-expr'. If there is no 'init-expr', the +'symbol' will be initialized to NIL. There +is no specification as to the order of execution of the bindings. The 'let' +form will go through and create and initialize the symbols and then +sequentially execute the 'exprs'. The value of the last 'expr' evaluated is +returned. When the 'let' is finished execution, the 'symbols' that were +defined will no longer exist or retain their values.

    + +

    Examples

    + +
    +(let (x y z)                      ; LET with local vars
    +  (print x) (print y) (print z))  ;   prints   NIL NIL NIL
    +
    +(let ((a 1) (b 2) (c 3))          ; LET with local vars & init
    +  (print (+ a b c)))              ;   prints and returns 6
    +
    +(let ((a 1) (b 2) (c (+ a b)))    ; LET with local vars & init
    +  (print (+ a b c)))              ;   error: unbound variable - A
    +
    + +

    Note: to make the last example work you need the +let* special form.

    + +

    See the +let +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/list.htm b/docsrc/xlisp/xlisp-doc/reference/list.htm new file mode 100644 index 0000000..c62588d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/list.htm @@ -0,0 +1,74 @@ +XLISP list + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    list

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (list [expr1 ... ])
    +
    exprN - an expression
    +returns - the new list
    +
    + +

    Description

    + +

    The 'list' function takes the expressions and constructs a list out of +them. This constructed list is returned.

    + +

    Examples

    + +
    +(list)                           ; returns NIL
    +(list nil)                       ; returns (NIL)
    +(list 'a)                        ; returns (A)
    +(list 'a 'b)                     ; returns (A B)
    +(list 'a 'b 'c)                  ; returns (A B C)
    +(list 'a 'b nil)                 ; returns (A B NIL)
    +(list '(a b) '(c d) '( (e f) ))  ; returns ((A B) (C D) ((E F)))
    +(list (+ 1 2) (+ 3 4))           ; returns (3 7)
    +
    + +

    See the +list +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/listdir.htm b/docsrc/xlisp/xlisp-doc/reference/listdir.htm new file mode 100644 index 0000000..c155abe --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/listdir.htm @@ -0,0 +1,67 @@ +XLISP listdir + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    listdir

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (listdir path)
    +
    path - the path of the directory to be listed
    +returns - list of filenames in the directory
    +
    + +

    Description

    + +

    The 'listdir' function returns a list with all filenames in the directory +or NIL if the directory could not be found.

    + +

    Examples

    + +
    +(let ((filenames (sort (listdir ".") #'string-lessp)))
    +  (dolist (filename filenames)
    +    (print filename)))
    +
    + +

    See also setdir.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/listp.htm b/docsrc/xlisp/xlisp-doc/reference/listp.htm new file mode 100644 index 0000000..21fd92c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/listp.htm @@ -0,0 +1,92 @@ +XLISP listp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    listp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (listp expr)
    +
    expr - the expression to check
    +returns -  T  if the value is a +list or NIL , +NIL otherwise
    +
    + +

    Description

    + +

    The 'listp' predicate function checks if the 'expr' is a list. + T  is returned if 'expr' is a +list or an empty list [the NIL value], +NIL is returned otherwise.

    + +

    Examples

    + +
    +(listp '(a b))                  ; returns T - list
    +(listp nil)                     ; returns T - NIL
    +(listp '(a . b))                ; returns T - dotted pair list
    +
    +(listp (lambda (x) (print x)))  ; returns NIL - closure - lambda
    +(listp #(1 2 3))                ; returns NIL - array
    +(listp *standard-output*)       ; returns NIL - stream
    +(listp 1.2)                     ; returns NIL - float
    +(listp #'quote)                 ; returns NIL - fsubr
    +(listp 1)                       ; returns NIL - integer
    +(listp object)                  ; returns NIL - object
    +(listp "str")                   ; returns NIL - string
    +(listp #'car)                   ; returns NIL - subr
    +(listp 'a)                      ; returns NIL - symbol
    +
    + +

    Note: NIL or '() is used in many +places as a list-class or atom-class expression. Both +atom and 'listp', when applied to +NIL , return + T . If you wish to check +for a non-empty list, use the consp +predicate function.

    + +

    See the +listp +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/load.htm b/docsrc/xlisp/xlisp-doc/reference/load.htm new file mode 100644 index 0000000..627dccd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/load.htm @@ -0,0 +1,162 @@ +XLISP load + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    load

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c, xlread.c

    + +

    Syntax

    + +
    +
    (load file [:verbose v-flag] [:print p-flag]))
    +
    file - a string expression or symbol
    +v-flag - an optional key-word expression, default is + T 
    +p-flag - an optional key-word expression, default is +NIL
    +returns - the filename
    +
    + +

    Description

    + +

    The 'load' function opens the 'file', reads and evaluates all the forms +within the 'file'. 'file' may be a string expression or a symbol. When +'file' is a string, you may specify a complete file location or extensions +like "/usr/local/bin/myfile.lsp" or "A:\LISP\TIM.LSP". +If 'file' is a string and includes a file type or an extension [like +".lsp"], then 'load' accesses the specified file. If there is no +extension on 'file', it will add ".lsp". If the ':verbose' keyword +is present and 'v-flag' is +non-NIL , a load message of +the form:

    + +
    +; loading "xxxx.lsp"
    +
    + +

    will be printed to *standard-output*. +If the ':print' keyword is present and 'p-flag' is +non-NIL , the resulting value +of each top-level form in 'file' will be printed to +*standard-output*. If the file load was +successful, then  T  is returned +as the result. If the file load was not successful, a +NIL is returned.

    + +

    Note: in Nyquist, the XLISP 'load' function first tries to load a +file from the current directory. A '.lsp' extension is added if +there is not already an alphanumeric extension following a period. If +that fails, XLISP searches the path, which is obtained from the +XLISPPATH environment variable in Unix and +HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under Win32.

    + +

    Examples

    + +
    +(load 'gloop)                     ; prints  ; loading "GLOOP.lsp"
    +                                  ; returns NIL   there is no file
    +
    +(defun foo (x) (print x))         ; create a function
    +(savefun foo)                     ; create a file FOO.lsp
    +
    +(load 'foo)                       ; prints  ; loading "FOO.lsp"
    +                                  ; returns T
    +
    +(load 'foo :verbose NIL)          ; no printing   returns T
    +
    +(load 'foo :print T)              ; prints  FOO   returns T
    +
    +(load 'save :verbose T :print T)  ; prints  ; loading "FOO.lsp"
    +                                  ; prints  FOO   returns T
    +
    +(load "foo")                      ; prints  ; loading "foo.lsp"
    +                                  ; returns NIL - didn't work
    +                                  ;   because the file is "FOO.lsp"
    +
    +(load "FOO")                      ; prints  ; loading "FOO.lsp"
    +                                  ; returns T - did work
    +
    +(load "FOO.lsp")                  ; prints  ; loading "FOO.lsp"
    +                                  ; returns T - did work
    +
    + +

    File names: In the PC and DOS world, all file names and extensions +["foo.bat"] are automatically made uppercase. In using XLISP, this +means you don't have to worry about whether the name is "foo.bat", +"FOO.BAT" or even "FoO.bAt", they will all work. +However, in other file systems [UNIX in particular], uppercase and lowercase +do make a difference:

    + +

    This will create a file named FOO-FILE in UNIX, because XLISP uppercases +its symbols:

    + +
    +(open 'foo-file :direction :output)
    +
    + +

    This will create a file named 'foo-file' because UNIX doesn't +uppercase its file names:

    + +
    +(open "foo-file" :direction :output)
    +
    + +

    So, if you are having trouble with opening and accessing files, check to +make sure the file name is in the proper case.

    + +

    Common Lisp: Common Lisp has a 'load' function that is similar +to XLISP's 'load'. The only difference is that Common Lisp uses an optional +keyword parameter ':if-does-not-exist' which XLISP does not support.

    + +

    Nyquist: in Nyquist, the XLISP 'load' function first tries to load +a file from the current directory. A '.lsp' extension is added if there is +not already an alphanumeric extension following a period. If that fails, +XLISP searches the path, which is obtained from the XLISPPATH environment +variable in Unix and HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under +Win32. [The Macintosh version has no search path.]

    + +

    Note: In XLISP, the keyword parameters are order sensitive. If +both ':verbose' and ':print' keywords are used, ':verbose' must come +first.

    + +

    See the +load +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/log.htm b/docsrc/xlisp/xlisp-doc/reference/log.htm new file mode 100644 index 0000000..98bfe25 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/log.htm @@ -0,0 +1,67 @@ +XLISP log + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    log

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sndfnint.c, sound.h

    + +

    Syntax

    + +

    + +
    +
    (log number)
    +
    number - a floating-point number
    +returns - the natural logarithm of number
    +
    + +

    + +

    Description

    + +

    The 'log' function computes the natural logarithm of a +floating-point number and returns the result.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/logand.htm b/docsrc/xlisp/xlisp-doc/reference/logand.htm new file mode 100644 index 0000000..959f918 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/logand.htm @@ -0,0 +1,81 @@ +XLISP logand + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    logand

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (logand expr1 ... )
    +
    expr - an integer expression
    +returns - the result of the AND operation
    +
    + +

    Description

    + +

    The 'logand' function returns the logical bitwise 'and' of the list of +expressions. If there is only one argument, it is returned unaltered. If +there are two or more arguments, the 'logand' function performs the logical +and operation successively applying the bitwise operation.

    + +

    Examples

    + +
    +(logand 0 0)         ; returns 0
    +(logand 0 1)         ; returns 0
    +(logand 1 0)         ; returns 0
    +(logand 1 1)         ; returns 1
    +(logand 55 #x0F)     ; returns 7
    +(logand 7 #b0011)    ; returns 3
    +(logand 1 2 4 8 16)  ; returns 0
    +(logand 15 7 3)      ; returns 3
    +
    + +

    Note: XLISP does not check when read-macro expansions like '#x0FF' +are out of bounds. It gives no error message and will just truncate the +number to the low-order bits that it can deal with [usually 32 bits or 8 hex +digits].

    + +

    See the +logand +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/logior.htm b/docsrc/xlisp/xlisp-doc/reference/logior.htm new file mode 100644 index 0000000..d0e004a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/logior.htm @@ -0,0 +1,82 @@ +XLISP logior + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    logior

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (logior expr1 ... )
    +
    exprN - an integer expression
    +returns - the result of the Inclusive OR operation
    +
    + +

    Description

    + +

    The 'logior' function returns the logical bitwise 'inclusive-or' of the +list of expressions. If there is only one argument, it is returned +unaltered. If there are two or more arguments, the 'logior' function +performs the 'inclusive-or' successively applying the bitwise operation.

    + +

    Examples

    + +
    +(logior 0 0)               ; returns 0
    +(logior 0 1)               ; returns 1
    +(logior 1 0)               ; returns 1
    +(logior 1 1)               ; returns 1
    +        
    +(logior 1 2 4 8 16 32 64)  ; returns 127
    +(logior 5 #b010)           ; returns 7
    +(logior 99 #x1FF)          ; returns 511
    +(logior 99 #x400)          ; returns 1123
    +
    + +

    Note: XLISP does not check when read-macro expansions like '#x0FF' +are out of bounds. It gives no error message and will just truncate the +number to the low-order bits that it can deal with [usually 32 bits or 8 hex +digits].

    + +

    See the +logior +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/lognot.htm b/docsrc/xlisp/xlisp-doc/reference/lognot.htm new file mode 100644 index 0000000..3ca21b4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/lognot.htm @@ -0,0 +1,79 @@ +XLISP lognot + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    lognot

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (lognot expr)
    +
    expr - an integer expression
    +returns - the bitwise inversion of number
    +
    + +

    Description

    + +

    The 'lognot' function returns the logical bitwise inversion of the +expression.

    + +

    Examples

    + +
    +(lognot 255)                 ; returns -256
    +(lognot #xffff0000)          ; returns 65535
    +(lognot #x00000000)          ; returns -1
    +(lognot 1)                   ; returns -2
    +
    +(logand (lognot 256) 65535)  ; returns 65279
    +(lognot #xFFFFFFFE)          ; returns 1
    +(lognot #xFFFFFFFC)          ; returns 3
    +
    + +

    Note: XLISP does not check when read-macro expansions like '#x0FF' +are out of bounds. It gives no error message and will just truncate the +number to the low-order bits that it can deal with [usually 32 bits or 8 hex +digits].

    + +

    See the +lognot +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/logxor.htm b/docsrc/xlisp/xlisp-doc/reference/logxor.htm new file mode 100644 index 0000000..2cf8b11 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/logxor.htm @@ -0,0 +1,82 @@ +XLISP logxor + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    logxor

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (logxor expr1 ... )
    +
    exprN - an integer expression
    +returns - the result of the eXclusive OR operation
    +
    + +

    Description

    + +

    The 'logxor' function returns the logical bitwise 'exclusive-or' of the +list of expressions. If there is only one argument, it is returned +unaltered. If there are two or more arguments, the 'logxor' function +performs the 'exclusive-or' successively applying the bitwise operation.

    + +

    Examples

    + +
    +(logxor 0 0)                  ; returns 0
    +(logxor 0 1)                  ; returns 1
    +(logxor 1 0)                  ; returns 1
    +(logxor 1 1)                  ; returns 0
    +
    +(logxor #b0011 #b0101)        ; returns 6
    +(logxor 255 #xF0)             ; returns 15
    +(logxor 255 #x0F)             ; returns 240
    +(logxor 255 (logxor 255 99))  ; returns 99
    +
    + +

    Note: XLISP does not check when read-macro expansions like '#x0FF' +are out of bounds. It gives no error message and will just truncate the +number to the low-order bits that it can deal with [usually 32 bits or 8 hex +digits].

    + +

    See the +logxor +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/loop.htm b/docsrc/xlisp/xlisp-doc/reference/loop.htm new file mode 100644 index 0000000..85c3170 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/loop.htm @@ -0,0 +1,84 @@ +XLISP loop + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    loop

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (loop body ... )
    +
    body - a series of expressions
    +returns - never returns [must use non-local exit]
    +
    + +

    Description

    + +

    The 'loop' special form specifies a 'repeat-forever' construct. The +expressions in'body' will be evaluated. When the last expression is +evaluated in 'body', 'loop' will then repeat the 'body'. When a +return is evaluated within a 'loop', the +specified value will be returned. 'loop' itself does not generate a return +value. Other exit mechanisms include +go , +throw , +return-from and errors.

    + +

    Examples

    + +
    +(setq i 65)                      ; initial value
    +
    +(loop                            ; LOOP
    +  (princ (int-char i))           ;   print the character
    +  (if (= i 90) (return "done"))  ;   test for limit
    +  (setq i (1+ i)))               ;   increment and repeat
    +                                 ; prints ABCDEFGHIJKLMNOPQRSTUVWXYZ
    +                                 ; returns "done"
    +
    + +

    Note: If you create a 'loop' with no exit mechanism, you will +probably have to abort your XLISP session.

    + +

    See the +loop +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/lower-case-p.htm b/docsrc/xlisp/xlisp-doc/reference/lower-case-p.htm new file mode 100644 index 0000000..e683614 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/lower-case-p.htm @@ -0,0 +1,79 @@ +XLISP lower-case-p + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    lower-case-p

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (lower-case-p char)
    +
    char - a character expression
    +returns -  T  +if the character is lower case, +NIL otherwise
    +
    + +

    Description

    + +

    The 'lower-case-p' predicate function checks if the 'char' expression +is a lower case character. If 'char' is lower case a + T  is returned, +otherwise a +NIL is returned. +Lower case characters are 'a' +[ASCII decimal value 97] +through 'z' +[ASCII decimal value 122].

    + +

    Examples

    + +
    +(lower-case-p #\a)   ; returns T
    +(lower-case-p #\A)   ; returns NIL
    +(lower-case-p #\1)   ; returns NIL
    +(lower-case-p #\[)   ; returns NIL
    +
    + +

    See the +lower-case-p +predicate function form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/macroexpand-1.htm b/docsrc/xlisp/xlisp-doc/reference/macroexpand-1.htm new file mode 100644 index 0000000..5c43a44 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/macroexpand-1.htm @@ -0,0 +1,85 @@ +XLISP macroexpand-1 + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    macroexpand-1

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (macroexpand-1 form)
    +
    form - a macro form
    +returns - the macro expansion
    +
    + +

    Description

    + +

    The 'macroexpand-1' function takes a 'form' and expands the first level +of the macro definition used in the 'form'. The function returns the +expansion. If the 'form' does not contain a macro, the form is returned +unaltered.

    + +

    Examples

    + +
    +(defmacro plus (n1 n2) `(+ ,n1 ,n2))   ; define PLUS macro
    +(plus 1 2)                             ; returns 3
    +(macroexpand '(plus 3 4))              ; returns (+ 3 4)
    +(macroexpand-1 '(plus 3 4))            ; returns (+ 3 4)
    +
    +(defmacro pl (p1 p2) `(plus ,p1 ,p2))  ; define PL macro using PLUS
    +(pl 3 4)                               ; returns 7
    +(macroexpand '(pl 3 4))                ; returns (+ 3 4)
    +(macroexpand-1 '(pl 3 4))              ; returns (PLUS 3 4)
    +
    + +

    Common Lisp: Common Lisp returns 2 values for its result of +'macroexpand-1', the expanded form and a + T  or +NIL value that indicates if the form was a +macro. XLISP returns only the expanded form. Common Lisp also supports an +optional argument in 'macroexpand-1' for the environment of the expansion. +XLISP does not support this optional argument.

    + +

    See the +macroexpand-1 +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/macroexpand.htm b/docsrc/xlisp/xlisp-doc/reference/macroexpand.htm new file mode 100644 index 0000000..771f752 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/macroexpand.htm @@ -0,0 +1,83 @@ +XLISP macroexpand + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    macroexpand

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (macroexpand form)
    +
    form - a macro form
    +returns - the macro expansion
    +
    + +

    Description

    + +

    The 'macroexpand' function takes a 'form' and recursively expands the +macro definitions used in the 'form'. The function returns the expansion. If +the 'form' does not contain a macro, the form is returned unaltered.

    + +

    Examples

    + +
    +(defmacro plus (n1 n2) `(+ ,n1 ,n2))   ; define PLUS macro
    +(plus 1 2)                             ; returns 3
    +(macroexpand '(plus 3 4))              ; returns (+ 3 4)
    +
    +(defmacro pl (p1 p2) `(plus ,p1 ,p2))  ; define PL macro using PLUS
    +(pl 3 4)                               ; returns 7
    +(macroexpand '(pl 3 4))                ; returns (+ 3 4)
    +(macroexpand-1 '(pl 3 4))              ; returns (PLUS 3 4)
    +
    + +

    Common Lisp: Common Lisp returns 2 values for its result of +'macroexpand', the expanded form and a + T  or +NIL value that indicates if the form was a +macro. XLISP returns only the expanded form. Common Lisp also supports an +optional argument in 'macroexpand' for the environment of the expansion. +XLISP does not support this optional argument.

    + +

    See the +macroexpand +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/macrolet.htm b/docsrc/xlisp/xlisp-doc/reference/macrolet.htm new file mode 100644 index 0000000..39de0f2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/macrolet.htm @@ -0,0 +1,146 @@ +XLISP macrolet + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    macrolet

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +

    + +
    +
    (macrolet ([macro ... ]) expr ... )
    +
    macro - a macro definition binding which is of the form:
    +
    (symbol arg-list body)
    +
    symbol - the symbol specifying the macro name
    +arg-list - the argument list for the macro
    +body - the body of the macro
    +expr - an expression
    +returns - the value of the last expression
    +
    + +

    + +

    Description

    + +

    The 'macrolet' special form is basically a local block construct that allows local 'macro' definitions +followed by a block of code to evaluate. The first form after +the macrolet is the 'binding' form. It contains a series of +'macros'. The 'macrolet' form will sequentially execute the +'exprs' after defining the 'macros'. The value of the last +'expr' evaluated is returned. When the 'macrolet' is finished execution, the +'symbols' that were defined will no longer exist.

    + +

    Examples

    + +
    +> (macrolet ((pls (n1 n2)     ; MACROLET defining a PLS macro
    +               `(+ ,n1 ,n2)))
    +    (pls 4 5))
    +9
    +
    +> (pls 4 5)                   ; the PLS macro no longer exists
    +error: unbound function - PLS
    +
    +> (macrolet ()                ; an empty MACROLET
    +    (print 'a))
    +A  ; screen output of PRINT
    +A  ; return value
    +
    + +

    Known Problems

    + +

    1. In XLISP, only macros defined by + +defmacro [interned in the +*obarray*] can be used with +setf:

    + +
    +(setq a #(1 2 3))
    +
    +(defmacro second-array-element (array)
    +  `(aref ,array 1))
    +
    +(second-array-element a)            => 2
    +(setf (second-array-element a) 'x)  => X
    +a                                   => #(1 X 3)
    +
    + +

    With macros defined by 'macrolet' [stored in the lexical environment], +setf signals a 'bad place form' error:

    + +
    +(macrolet ((second-element (array)
    +             `(aref ,array 1)))
    +  (second-element a))               => X
    +
    +(macrolet ((second-element (array)
    +             `(aref ,array 1)))
    +  (setf (second-element a) 'y))     => error: bad place form
    +
    + +

    2. In XLISP, the macroexpand and +macroexpand-1 functions can +only expand macros defined +by defmacro:

    + +
    +> (macroexpand-1 '(second-array-element a))
    +(AREF A 1)
    +
    + +

    With macros defined by 'macrolet', the macro form is returned +unexpanded:

    + +
    +> (macrolet ((second-element (array)
    +               `(aref ,array 1)))
    +    (macroexpand-1 '(second-element a)))
    +(SECOND-ELEMENT A)
    +
    + +

    In XLISP, the macroexpand and +macroexpand-1 functions only +search in the *obarray* for defined macros, +but not in the lexical environment.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/make-array.htm b/docsrc/xlisp/xlisp-doc/reference/make-array.htm new file mode 100644 index 0000000..47b576e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/make-array.htm @@ -0,0 +1,95 @@ +XLISP make-array + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    make-array

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (make-array size)
    +
    size - the size [integer] of the array to be created
    +returns - the new array
    +
    + +

    Description

    + +

    The 'make-array' function creates an array of the specified size and +returns the array. Array elements may be any valid lisp data type, including +lists or arrays. Arrays made by 'make-array' and accessed by +aref are base 0. This means +the first element is accessed by element number '0' and the last element is +accessed by element number 'n-1', where 'n' is the array size. Array +elements are initialized to NIL.

    + +

    Examples

    + +
    +(setq my-array (make-array 16))     ; make the array
    +(aref my-array 0)                   ; return 0th (first) element
    +(aref my-array 15)                  ; return 15th (last) element
    +(aref my-array 16)                  ; error: non existant element
    +
    +(dotimes (i 16)                     ; set each element to its index
    +  (setf (aref my-array i) i))       ;   by the setf function
    +
    +(setq new (make-array 4))           ; make another array
    +(setf (aref new 0) (make-array 4))  ; make new[0] an array of 4
    +(setf (aref (aref new 0) 1) 'a)     ; set new[0,1] = 'a
    +(setf (aref new 2) '(a b c))        ; set new[2] = '(a b c)
    +my-array                            ; look at array
    +
    + +

    Read macro: There is a built-in read-macro for arrays, '#(...)' +[the hash symbol with an opening and a closing parenthesis]. This allows you +to create arbitrary arrays with initial values without going through a +'make-array' function. There is also the XLISP vector function to create initialized arrays.

    + +

    Common Lisp: Common Lisp supports multi-dimensional arrays, XLISP +only supports one-dimensional arrays. In XLISP, multi-dimenstional arrays +can be created by using 'arrays within arrays'. Common Lisp supports various +keyword parameters that are not supported in XLISP.

    + +

    See the +make-array +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/make-string-input-stream.htm b/docsrc/xlisp/xlisp-doc/reference/make-string-input-stream.htm new file mode 100644 index 0000000..0dd3fe9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/make-string-input-stream.htm @@ -0,0 +1,84 @@ +XLISP make-string-input-stream + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    make-string-input-stream

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (make-string-input-stream string [start-pos [end-pos]])
    +
    string - a string expression
    +start-pos - an optional numeric expression, default value is '0' [the first character of the string]
    +end-pos - an optional numeric expression, default value is the length of the string
    +returns - an unnamed stream that reads from the string
    +
    + +

    Description

    + +

    The 'make-string-input-stream' function creates an unnamed stream from +the 'string' expression. The stream can then be used as any other stream +object. The optional 'start-pos' expression specifies the starting offset of +the 'string' expression. A 'start-pos' of '0' will start with the beginning +of the 'string'. The optional 'end-pos' expression specifies the ending +offset of the 'string' expression. A 'end-pos' of 4 will make the fourth +character the last in the stream. If the function is successful, it returns +the unnamed stream object. If the string is empty, an unnamed stream is +still returned. Error conditions include 'start-pos' and 'end-pos' being out +of bounds.

    + +

    Examples

    + +
    +(make-string-input-stream "abcdefgh")           ; returns #<Unnamed-Stream: #277e2>
    +(read (make-string-input-stream "123456"))      ; returns 123456
    +(read (make-string-input-stream "123456" 1))    ; returns 23456
    +(read (make-string-input-stream "123456" 1 3))  ; returns 23
    +(read (make-string-input-stream "123" 0))       ; returns 123
    +(read (make-string-input-stream "123" 0 3))     ; returns 123
    +(read (make-string-input-stream "123" 2 1))     ; returns NIL
    +(read (make-string-input-stream "123" 0 4))     ; error: string index out of bounds - 4
    +
    + +

    See the +make-string-input-stream +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/make-string-output-stream.htm b/docsrc/xlisp/xlisp-doc/reference/make-string-output-stream.htm new file mode 100644 index 0000000..ae2cfe2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/make-string-output-stream.htm @@ -0,0 +1,79 @@ +XLISP make-string-output-stream + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    make-string-output-stream

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (make-string-output-stream)
    +
    returns - an unnamed output stream
    +
    + +

    Description

    + +

    The 'make-string-output-stream' function creates and returns an unnamed +output stream. The stream can then be used as any other stream object.

    + +

    Examples

    + +
    +(make-string-output-stream)             ; returns #<Unnamed-Stream: #2d9c0>
    +
    +(setq out (make-string-output-stream))  ; returns #<Unnamed-Stream: #2d95c>
    +
    +(format out "fee fi fo fum ")           ; \
    +(format out "I smell the blood of ")    ;  fill up output stream
    +(format out "Elmer Fudd")               ; /
    +(get-output-stream-string out)          ; returns "fee fi fo fum I smell the blood of Elmer Fudd"
    +
    +(format out "~%now what")               ; add more to output stream
    +(get-output-stream-string out)          ; returns "\nnow what"
    +
    +(format out "hello")                    ; add more to output stream
    +(read out)                              ; returns HELLO
    +
    + +

    See the +make-string-output-stream +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/make-symbol.htm b/docsrc/xlisp/xlisp-doc/reference/make-symbol.htm new file mode 100644 index 0000000..f0d0a7b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/make-symbol.htm @@ -0,0 +1,93 @@ +XLISP make-symbol + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    make-symbol

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (make-symbol symbol-str)
    +
    symbol-str - a string expression
    +returns - the new symbol
    +
    + +

    Description

    + +

    The 'make-symbol' function takes a string name 'symbol-str' and creates a +new symbol. This symbol is temporary and is not +interned [placed] into the symbol hash +table *obarray*. If the symbol already +exists, no error or action is taken and the old values and property lists +remain intact. The 'make-symbol' function returns the symbol as its +result.

    + +

    Examples

    + +
    +(defun lookin (sym)                  ; create a function to
    +  (aref *obarray*                    ;   look inside *OBARRAY*
    +    (hash sym (length *obarray*))))  ;   and look for a specific
    +                                     ;   symbol - returns a list
    +
    +(lookin "FEE")                       ; returns (CHAR-INT NTH ++)
    +                                     ;   FEE symbol doesn't exist
    +
    +(make-symbol "FEE")                  ; returns FEE symbol
    +(lookin "FEE")                       ; returns (CHAR-INT NTH ++)
    +                                     ;   FEE still doesn't exist
    +
    +(intern "FEE")                       ; intern FEE symbol
    +(lookin "FEE")                       ; returns (FEE CHAR-INT NTH ++)
    +                                     ;   FEE does now exist
    +
    + +

    Note: When you 'make-symbol' a string type symbol like +"fingers", this is a lower case symbol. This is different from +doing a 'make-symbol' on a string type symbol "FINGERS", which is +an upper case symbol. With string type symbols, "fingers" and +"FINGERS" are two different symbols. Remember also that normal +symbols created by XLISP are automatically converted to upper case.

    + +

    See the +make-symbol +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/mapc.htm b/docsrc/xlisp/xlisp-doc/reference/mapc.htm new file mode 100644 index 0000000..83fe3fc --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/mapc.htm @@ -0,0 +1,87 @@ +XLISP mapc + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    mapc

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (mapc function list1 [list2 ... ])
    +
    function - a function definition like a +lambda form or a function name
    +listN - a list or list expression
    +returns - the first list of arguments
    +
    + +

    Description

    + +

    The 'mapc' function applies the 'function' to the succesive +cars of each of the lists 'listN'. Each of +the lists supplies one of the arguments to 'function'. The 'mapc' function +returns a list that is equivalent to the first list 'list1'. It's purpose is +to perform operations that have side-effects. If the lists are of different +lengths, the shortest list will determine the number of applications of +'function'.

    + +

    Examples

    + +
    +(mapc 'princ '(hi there bob))         ; prints HITHEREBOB
    +                                      ;   returns (HI THERE BOB)
    +
    +(mapc '+ '(1 2 3) '(1 2 3))           ; returns (1 2 3)
    +                                      ;   there were no side effects
    +
    +(mapc (lambda (x y) (print (+ x y)))  ; define a function with side effects
    +      '(1 2 3) '(1 2 3))              ;   prints 2 4 6 
    +                                      ;   returns (1 2 3)
    +
    + +

    Note: The use of the 'function' will work properly when it is a +quoted symbol [the name of the function], an unquoted symbol, whose value is +a function, or a closure object like a +lambda form.

    + +

    See the +mapc +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/mapcar.htm b/docsrc/xlisp/xlisp-doc/reference/mapcar.htm new file mode 100644 index 0000000..8112cba --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/mapcar.htm @@ -0,0 +1,151 @@ +XLISP mapcar + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    mapcar

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (mapcar function list1 [list2 ... ])
    +
    function - a function definition like a +lambda or a function name
    +listN - a list or list expression
    +returns - a list that is constructed from the results of the function applications
    +
    + +

    Description

    + +

    The mapcan function 'mapcar' applies the 'function' to the succesive +cars of each of the lists 'listN'. Each of +the lists supplies one of the arguments to 'function'. The 'mapcar' function +returns a list that is constructed from the results of the 'function' +applications. If the lists are of different lengths, the shortest list will +determine the number of applications of 'function'.

    + +

    Examples

    + +
    +> (mapcar #'+ '(1 2 3) '(1 2 3))
    +(2 4 6)
    +
    +> (mapcar #'princ '(1 2 3))       
    +123       ; screen output
    +(1 2 3)   ; return value
    +
    +> (mapcar #'+ '(1 2 3) '(1 2 3 4 5 6)  ; different length lists
    +(2 4 6)
    +
    + +

    Note: The use of the 'function' will work properly when it is a +sharp-quoted symbol, a quoted symbol [must be the +name of a function], an unquoted symbol whose value is a +function, or a closure object like a lambda +form.

    + +

    + +

    Bug: The proper syntax for 'function' when 'function' is a +lambda expression is, for example:

    + +
    +(mapcar #'(lambda (arg1 arg2) (+ arg1 arg2)) '(1 2))
    +
    + +

    and not:

    + +
    +(mapcar '(lambda (arg1 arg2) (+ arg1 arg2)) '(1 2))
    +
    + +

    That is, the #' [function] read macro must be +present. This error should be caught by the XLISP interpreter, but it is +not, with the result that very obscure garbage collection bugs occur. +[I still haven't tested Nyquist for possible garbage collection +bugs caused by this.]

    + +

    + +

    Notes

    + +

    In XLISP, a 'special form' of type FSUBR is not a function. +This means that 'mapcar' only works with functions of type SUBR +[built-in function] or CLOSURE [function defined by +defun, flet, +labels, or lambda], but +with special forms of type FSUBR a 'bad function' error is +signalled. Here is an example how to work around this behaviour:

    + +
    +(defmacro mapcar* (function &rest args)
    +  (if (eq (type-of (symbol-function (second function))) 'fsubr)
    +      (let ((rest (gensym)))
    +        `(mapcar #'(lambda (&rest ,rest) 
    +                     (eval (cons ,function ,rest)))
    +                 ,@args))
    +      `(mapcar ,function ,@args)))
    +
    + +

    Examples:

    + +
    +(type-of #'eql)  => SUBR   ; built-in function
    +(type-of #'and)  => FSUBR  ; built-in special form
    +
    +> (macroexpand-1 '(mapcar* #'eql '(1 2 3) '(t nil 3)))
    +(MAPCAR (FUNCTION EQL)
    +        (QUOTE (1 2 3))
    +        (QUOTE (T NIL 3)))
    +
    +> (macroexpand-1 '(mapcar* #'and '(1 2 3) '(t nil 3)))
    +(MAPCAR (FUNCTION (LAMBDA (&REST G7)
    +                    (EVAL (CONS (FUNCTION AND) G7))))
    +        (QUOTE (1 2 3))
    +        (QUOTE (T NIL 3)))
    +
    +(mapcar  #'eql '(1 2 3) '(t nil 3)))  => (NIL NIL T)
    +(mapcar* #'eql '(1 2 3) '(t nil 3)))  => (NIL NIL T)
    +
    +(mapcar  #'and '(1 2 3) '(t nil 3)))  => error: bad function
    +(mapcar* #'and '(1 2 3) '(t nil 3)))  => (T NIL 3)
    +
    + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/mapl.htm b/docsrc/xlisp/xlisp-doc/reference/mapl.htm new file mode 100644 index 0000000..fb65045 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/mapl.htm @@ -0,0 +1,89 @@ +XLISP mapl + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    mapl

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (mapl function list1 [list2 ... ])
    +
    function - a function definition like a +lambda form or a function name
    +listN - a list or list expression
    +returns - a list that is equivalent to list1
    +
    + +

    Description

    + +

    Tha 'mapl' function applies the 'function' to the successive +cdrs of each of the lists 'listN'. Each of +the lists supplies one of the arguments to 'function'. The 'mapl' function +returns a list that is equivalent to the first list 'list1'. It's purpose is +to perform operations that have side-effects. If the lists are of different +lengths, the shortest list will determine the number of applications of +'function'.

    + +

    Examples

    + +
    +(mapl 'print '(a b c))       ; prints (A B C)
    +                             ;        (B C)
    +                             ;        (C)
    +                             ; returns (A B C)
    +
    +;; apply a lambda function to a list
    +(mapl (lambda (x y) (princ x) (princ y) (terpri))
    +      '(a b c) '(1 2 3))     ; prints (A B C)(1 2 3)
    +                             ;        (B C)(2 3)
    +                             ;        (C)(3)
    +                             ; returns (A B C)
    +
    + +

    Note: The use of the 'function' will work properly when it is a +quoted symbol [the name of the function], an unquoted symbol whose value is +a function or a closure object like a +lambda form.

    + +

    See the +mapl +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/maplist.htm b/docsrc/xlisp/xlisp-doc/reference/maplist.htm new file mode 100644 index 0000000..a0abe69 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/maplist.htm @@ -0,0 +1,86 @@ +XLISP maplist + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    maplist

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (maplist function list1 [list2 ... ])
    +
    function - a function definition like a +lambda or a function name
    +listN - a list or list expression
    +returns - a list that is constructed from the results of the +function applications
    +
    + +

    Description

    + +

    The 'maplist' function applies the 'function' to the successive +cdrs of each of the lists 'listN'. Each of +the lists supplies one of the arguments to 'function'. The 'maplist' +function returns a list that is constructed from the results of the +'function' applications. If the lists are of different lengths, the shortest +list will determine the number of applications of 'function'.

    + +

    Examples

    + +
    +(maplist 'print '(a b c))      ; prints (A B C)
    +                               ;        (B C)
    +                               ;        (C)
    +                               ; returns ((A B C) (B C) (C))
    +
    +;; append the lists into one list and find it's length
    +(maplist (lambda (x y) (length (append x y)))
    +         '(a b c d) '(1 2 3 4))  ; returns (8 6 4 2)
    +
    + +

    Note: The use of the 'function' will work properly when it is a +quoted symbol [the name of the function], an unquoted symbol whose value is +a function or a closure object like a +lambda form.

    + +

    See the +maplist +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/max.htm b/docsrc/xlisp/xlisp-doc/reference/max.htm new file mode 100644 index 0000000..bdac974 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/max.htm @@ -0,0 +1,73 @@ +XLISP max + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    max

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (max expr1 ... )
    +
    exprN - integer or floating point number/expression
    +returns - the largest number in the list of numbers/expressions
    +
    + +

    Description

    + +

    The 'max' function returns the largest numeric expression from the list +of arguments.

    + +

    Examples

    + +
    +(max 1)               ; returns 1
    +(max 1 -5 9)          ; returns 9
    +
    +(setq a '( 9 3 5 2))  ; set up a list - (9 3 5 2)
    +(apply 'max a)        ; returns 9
    +(apply #'max a)       ; returns 9
    +(apply 'min a)        ; returns 2
    +
    + +

    See the +max +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/member.htm b/docsrc/xlisp/xlisp-doc/reference/member.htm new file mode 100644 index 0000000..3dfbebf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/member.htm @@ -0,0 +1,93 @@ +XLISP member + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    member

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (member expr list-expr [{:test | :test-not} test])
    +
    expr - the expression to find [an atom or a list]
    +list-expr - the list to search
    +test - optional test function, default is +eql
    +returns - the remainder of the list starting with expr
    +
    + +

    Description

    + +

    The 'member' function searches through 'list-expr' for 'expr'. If found, +'member' returns the remainder of the 'list-expr' starting with 'expr'. If +'expr' is not found, a NIL is returned. You +may specify your own test with the ':test' and ':test-not' keywords followed +by the test you which to perform.

    + +

    Examples

    + +
    +(member 'a '(1 2 3 4))                         ; returns NIL
    +(member '2 '(1 2 3 4))                         ; returns (2 3 4)
    +
    +(setq mylist '(2 4 8 16 32 64 128 256))        ; make a numeric list
    +(member 6 mylist :test '<)                     ; returns (8 16 32 64 128 256)
    +(member 6 (reverse mylist) :test-not '<)       ; returns (4 2)
    +(member '20 '(60 40 20 10) :test '> )          ; returns (10)
    +
    +(member '(a) '((see) (a) (cat)) :test 'equal)  ; returns ((A) (CAT)) with EQUAL as test
    +(member "hi" '("a" "hi" "c") :test 'string= )  ; returns ("hi" "c") with STRING= as test
    +
    +
    + +

    Note: The 'member' function can work with a list or string as the +'expr'. However, the default eql test does +not work with lists or strings, only symbols and numbers. To make this work, +you need to use the ':test' keyword along with +equal for 'test'.

    + +

    Common Lisp: Common Lisp supports the use of the ':key' keyword +which specifies a function that is applied to each element of 'list-expr' +before it is tested. XLISP does not support this.

    + +

    See the +member +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/min.htm b/docsrc/xlisp/xlisp-doc/reference/min.htm new file mode 100644 index 0000000..287c85a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/min.htm @@ -0,0 +1,73 @@ +XLISP min + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    min

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (min expr1 ... )
    +
    exprN - integer or floating point number/expression
    +returns - the smallest number in the list of numbers/expressions
    +
    + +

    Description

    + +

    The 'min' function returns the minimum [most negative or most nearly +negative] numeric expression from the list of arguments.

    + +

    Examples

    + +
    +(min 1)               ; returns 1
    +(min 8 7 4 2)         ; returns 2
    +(min 2 3 -1 -99)      ; returns -99
    +(setq a '( 9 3 5 2))  ; make a numeric list - (9 3 5 2)
    +(apply 'min a)        ; returns 2
    +(apply #'min a)       ; returns 2
    +(apply 'max a)        ; returns 9
    +
    + +

    See the +min +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/minusp.htm b/docsrc/xlisp/xlisp-doc/reference/minusp.htm new file mode 100644 index 0000000..e01376e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/minusp.htm @@ -0,0 +1,84 @@ +XLISP minusp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    minusp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +(minusp expr) +
    expr - the numeric expression to check
    +returns -  T  if the number is +negative, NIL otherwise
    +
    + +

    Description

    + +

    The 'minusp' predicate function checks to see if the number 'expr' is +negative.  T  is returned if the +number is negative [less than zero], NIL is +returned otherwise. An error is generated if the +'expr' is not a numeric expression:

    + +
    +error: bad argument type
    +
    + +

    Examples

    + +
    +(minusp 1)             ; returns NIL
    +(minusp 0)             ; returns NIL
    +(minusp -1)            ; returns T
    +(minusp -.000000005)   ; returns T
    +(minusp #xFFFFFFFF)    ; returns T
    +(minusp #x01)          ; returns NIL
    +
    +(minusp 'a)            ; error: bad argument type
    +(setq a -3.5)          ; set A to -3.5
    +(minusp a)             ; returns T
    +
    + +

    See the +minusp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/multiplication.htm b/docsrc/xlisp/xlisp-doc/reference/multiplication.htm new file mode 100644 index 0000000..07b6b6e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/multiplication.htm @@ -0,0 +1,87 @@ +XLISP * + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    *

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (* expr1 ...)
    +
    exprN - integer or floating point number/expression
    +returns - the result of the multiplication
    +
    + +

    + +

    Description

    + +

    The '*' function multiplies one or more numbers together and +returns the result.

    + +

    Examples

    + +
    +(* 1)         => 1
    +(* 1 2)       => 2
    +(* 1 2 3)     => 6
    +(* 1 2 3 4)   => 24
    +
    + +
    +> (print (+ 1 2 (* 3.5 (/ 3.9 1.45))))
    +12.4138
    +12.4138
    +
    + +

    See  + , + / , print. +XLISP first prints the value on the screen, the second number is the +return value.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/nconc.htm b/docsrc/xlisp/xlisp-doc/reference/nconc.htm new file mode 100644 index 0000000..20e3b91 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/nconc.htm @@ -0,0 +1,89 @@ +XLISP nconc + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    nconc

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (nconc [list1 ... ])
    +
    listN - a list to destructively concatenate
    +returns - the result of concatenating the lists
    +
    + +

    Description

    + +

    The 'nconc' function destructively concatenates a sequence of lists and +returns the result of this concatentation. The destructive aspect of this +operation means that the actual symbol values are used in the list-modifying +operations, not copies. This means, for 'nconc', that the lists are spliced +together. 'listN' must evaluate to a valid list. An atom for 'listN' will +result in an error. NIL is a valid +'listN'.

    + +

    Examples

    + +
    +(setq a '(1 2 3))      ; set up A with (1 2 3)
    +(setq b '(4 5 6))      ; set up B with (4 5 6)
    +(setq c '(7 8 9))      ; set up C with (7 8 9)
    +(NCONC a b c)          ; returns (1 2 3 4 5 6 7 8 9)
    +(setf (nth 8 a) 'end)  ; change last element of A
    +(print a)              ; prints (1 2 3 4 5 6 7 8 END)
    +(print b)              ; prints (4 5 6 7 8 END)
    +(print c)              ; prints (7 8 END)
    +
    + +

    Note: with Nyquist, no error is raised if 'listN' is an atom. +Instead, all atoms given to the 'nconc' function, if not given as the last +argument, just disappear:

    + +
    +(nconc 'a 'b 'c 'd)       ; returns D
    +(nconc 'a '(b) 'c '(d))   ; returns (B D)
    +(nconc '(a) 'b '(c) 'd)   ; returns (A C . D)
    +
    + +

    See the +nconc +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/nil.htm b/docsrc/xlisp/xlisp-doc/reference/nil.htm new file mode 100644 index 0000000..b8265e9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/nil.htm @@ -0,0 +1,70 @@ +XLISP nil + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    nil

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system constant
    Source:  -  xlsym.c

    + +

    Syntax

    + +
    +
     nil
    +
    + +

    Description

    + +

    The 'nil' constant represents the empty list or the false value, as +oppossed to the true value [the symbol + T ]. 'nil' can be written as +the three character symbol 'nil' or as the empty list ().

    + +

    Examples

    + +
    +(setq myvar nil)                     ; set MYVAR to False
    +(setq myvar 'nil)                    ; NIL and 'NIL evaluate to NIL
    +(setq myvar ())                      ; () is the empty list = NIL
    +(setq myvar '())                     ; () and '() evaluate to NIL
    +(if nil (print "this won't print")   ; if/then/else
    +        (print "this will print"))
    +
    + +

    Note: You can not change the value of NIL.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/not.htm b/docsrc/xlisp/xlisp-doc/reference/not.htm new file mode 100644 index 0000000..a6ba8d0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/not.htm @@ -0,0 +1,80 @@ +XLISP not + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    not

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (not expr)
    +
    expr - the expression to check
    +return -  T  if the value is +NIL , +NIL otherwise
    +
    + +

    Description

    + +

    The 'not' predicate function checks to see if the 'expr' is false. + T  is returned if the +expression is NIL , +NIL is returned otherwise.

    + +

    Examples

    + +
    +(not '())      ; returns T - empty list
    +(not ())       ; returns T - still empty
    +(setq a NIL)   ; set up a variable
    +(not a)        ; returns T - value = empty list
    +
    +(not "a")      ; returns NIL - not a list
    +(not 'a)       ; returns NIL - not a list
    +
    + +

    Note: The 'not' predicate is the same function as the +null predicate.

    + +

    See the +not +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/nstring-downcase.htm b/docsrc/xlisp/xlisp-doc/reference/nstring-downcase.htm new file mode 100644 index 0000000..4d30642 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/nstring-downcase.htm @@ -0,0 +1,82 @@ +XLISP nstring-downcase + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    nstring-downcase

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (nstring-downcase string [{:start | :end} offset] ... )
    +
    string - a string expression
    +offset - an optional integer expression for a keyword
    +returns - the converted string, not a copy
    +
    + +

    Description

    + +

    The 'nstring-downcase' function takes a string argument and makes it +lower case. This function modifies the string or string variable itself, it +does not just make a copy. The lower case string is returned.

    + +

    The keyword arguments allow for accessing substrings within 'string'. +The keyword arguments require a keyword [':start' or ':end'] first and a +single integer expression second. The ':start' keyword specifies the +starting offset for the 'nstring-downcase' operation on 'string'. A value of +0 starts the string at the beginning [no offset]. The ':end' keyword +specifies the end offset for the operation on 'string'.

    + +

    Examples

    + +
    +(nstring-downcase "ABcd+-12&[")                ; returns "abcd+-&["
    +(nstring-downcase "ABCDEFGH" :start 2 :end 4)  ; returns "ABcdEFGH"
    +
    +(setq mystr "ABcdEFgh")        ; set up variable
    +(nstring-downcase mystr)       ; returns "abcdefgh"
    +(print mystr)                  ; prints  "abcdefgh"
    +                               ; note that MYSTR is modified
    +
    + +

    See the +nstring-downcase +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/nstring-upcase.htm b/docsrc/xlisp/xlisp-doc/reference/nstring-upcase.htm new file mode 100644 index 0000000..98b2b33 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/nstring-upcase.htm @@ -0,0 +1,82 @@ +XLISP nstring-upcase + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    nstring-upcase

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (nstring-upcase string [{:start | :end} offset] ... )
    +
    string - a string expression
    +offset - an optional integer expression for a keyword
    +returns - the converted string, not a copy
    +
    + +

    Description

    + +

    The 'nstring-upcase' function takes a string argument and makes it upper +case. This function modifies the string or string variable itself, it does +not just make a copy. The upper case string is returned.

    + +

    The keyword arguments allow for accessing substrings within 'string'. The +keyword arguments require a keyword (':start' or ':end') first and a single +integer expression second. The ':start' keyword specifies the starting +offset for the 'nstring-upcase' operation on 'string'. A value of 0 starts +the string at the beginning [no offset]. The ':end' keyword specifies the +end offset for the operation on 'string'.

    + +

    Examples

    + +
    +(nstring-upcase "ABcd+-12&[")                ; returns "ABCD+-&["
    +(nstring-upcase "abcdefgh" :start 2 :end 4)  ; returns "abCDefgh"
    +
    +(setq mystr "ABcdEFgh")      ; set up variable
    +(nstring-upcase mystr)       ; returns "ABCDEFGH"
    +(print mystr)                ; prints  "ABCDEFGH"
    +                             ; note that MYSTR is modified
    +
    + +

    See the +nstring-upcase +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/nth.htm b/docsrc/xlisp/xlisp-doc/reference/nth.htm new file mode 100644 index 0000000..fee31f5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/nth.htm @@ -0,0 +1,74 @@ +XLISP nth + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    nth

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (nth expr list-expr)
    +
    expr - an integer expression
    +list-expr - a list or list expression
    +returns - the nth element or NIL if the +list isn't that long
    +
    + +

    Description

    + +

    'nth' returns the 'expr'-th element of 'list-expr'. If the 'list-expr' is +shorter than 'expr', a NIL is returned. The +counting sequence is base zero, the first element is the 0th element.

    + +

    Examples

    + +
    +(nth 4 '(0 1 2 3 4 5 6))  ; returns 4
    +(nth 3 '(a b))            ; returns NIL
    +
    +(nth 4 'a)                ; error: bad argument type
    +(nth 3 "abcdefg")         ; error: bad argument type
    +
    + +

    See the +nth +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/nthcdr.htm b/docsrc/xlisp/xlisp-doc/reference/nthcdr.htm new file mode 100644 index 0000000..fa41dac --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/nthcdr.htm @@ -0,0 +1,75 @@ +XLISP nthcdr + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    nthcdr

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (nthcdr expr list-expr)
    +
    expr - an integer expression
    +list-expr - a list or list expression
    +returns - the nth +cdr or +NIL if the list isn't that long
    +
    + +

    Description

    + +

    'nthcdr' returns the 'expr'-th cdr +of 'list-expr'. If the 'list-expr' is shorter than 'exp', +a NIL is returned. The counting sequence +is base zero, the first element is the 0th element.

    + +

    Examples

    + +
    +(nthcdr 4 '(0 1 2 3 4 5 6))  ; returns (4 5 6)
    +(nthcdr 3 '(a b))            ; returns NIL
    +
    +(nthcdr 4 'a)                ; error: bad argument type
    +
    + +

    See the +nthcdr +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/null.htm b/docsrc/xlisp/xlisp-doc/reference/null.htm new file mode 100644 index 0000000..e683053 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/null.htm @@ -0,0 +1,80 @@ +XLISP null + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    null

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (null expr)
    +
    expr - the expression to check
    +returns -  T  if the list is +empty, NIL otherwise
    +
    + +

    Description

    + +

    The 'null' predicate function checks 'expr' for an empty list. + T  is returned if the list is +empty, NIL is returned otherwise. The +'expr' does not have to be a valid list, but if it is not a list then +NIL is returned as the result.

    + +

    Examples

    + +
    +(null '())     ; returns T - empty list
    +(null ())      ; returns T - still empty
    +(setq a NIL)   ; set up a variable
    +(null a)       ; returns T - value = empty list
    +
    +(null "a")     ; returns NIL - not a list
    +(null 'a)      ; returns NIL - not a list
    +
    + +

    Note: The 'null' predicate function is the same function as the +not predicate function.

    + +

    See the +null +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/number-equal.htm b/docsrc/xlisp/xlisp-doc/reference/number-equal.htm new file mode 100644 index 0000000..7316d17 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/number-equal.htm @@ -0,0 +1,87 @@ +XLISP = + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    =

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (= expr1 expr2 ...)
    +
    exprN - a numeric expression
    +returns -  T  if the results of +comparing the expressions are all true, +NIL otherwise
    +
    + +

    + +

    Description

    + +

    The '=' [equality] function takes an arbitrary number of +numeric arguments. It checks to see if all the numbers are +equal.  T  is returned if all of the arguments +are numerically equal to each other, NIL is returned +otherwise.

    + +

    Examples

    + +
    +(= 1 1)              => T
    +(= 1 2)              => NIL
    +(= 1 1.0)            => T
    +(= 1 1.0 1 (+ 0 1))  => T
    +(= 1 1.0 1.00001)    => NIL
    +(= "a" "b")          => error: bad argument type
    +(setq a 1 b 1.0)     => 1.0  ; set up A and B with values
    +(= a b)              => T
    +
    + +

    See setq.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/number-greaterp.htm b/docsrc/xlisp/xlisp-doc/reference/number-greaterp.htm new file mode 100644 index 0000000..a4cfe28 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/number-greaterp.htm @@ -0,0 +1,90 @@ +XLISP > + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    >

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (> expr1 expr2 ...)
    +
    exprN - a numeric expression
    +returns -  T  if the results of +comparing the expressions are all true, +NIL otherwise
    +
    + +

    + +

    Description

    + +

    The '>' [greater-than] function takes an arbitrary number +of numeric arguments. It checks to see if all the numbers are +monotonically decreasing.  T  is returned if +the arguments are numerically, and monotonically decreasing, +NIL is returned otherwise. For two +arguments, this has the effect of testing if 'expr1' is greater than +'expr2'.

    + +

    Examples

    + +
    +(> 1 1)             => NIL
    +(> 1 2)             => NIL
    +(> 2.0 1.99)        => T
    +(> 3 2 1)           => T
    +(> 3 2 2)           => NIL
    +(> "aa" "aa")       => error: bad argument type
    +(setq a 12 b 99.9)  => 99.9  ; set up A and B with values
    +(> a b)             => NIL
    +(> b a)             => T
    +
    + +

    See setq.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/number-lessp.htm b/docsrc/xlisp/xlisp-doc/reference/number-lessp.htm new file mode 100644 index 0000000..d1ba84a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/number-lessp.htm @@ -0,0 +1,90 @@ +XLISP < + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    <

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (< expr1 expr2 ...)
    +
    exprN - a numeric expression
    +returns -  T  if the results of +comparing the expressions are all true, +NIL otherwise
    +
    + +

    + +

    Description

    + +

    The '<' [less-than] function takes an arbitrary number +of numeric arguments. It checks to see if all the numbers are monotonically +increasing.  T  is returned if +the arguments are numerically, and monotonically increasing, +NIL is returned otherwise. In the case of +two arguments, this has the effect of testing if 'expr1' is less than +'expr2'.

    + +

    Examples

    + +
    +(< 1 2)              => T
    +(< 1 1)              => NIL
    +(< -1.5 -1.4)        => T
    +(< 1 2 3 4)          => T
    +(< 1 2 3 2)          => NIL
    +(< "a" "b")          => error: bad argument type
    +(setq a 12 b 13.99)  => 13.99  ; set up A and B with values
    +(< a b)              => T
    +(< b a)              => NIL
    +
    + +

    See setq.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/number-not-equal.htm b/docsrc/xlisp/xlisp-doc/reference/number-not-equal.htm new file mode 100644 index 0000000..595836b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/number-not-equal.htm @@ -0,0 +1,101 @@ +XLISP /= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    /=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (/= expr1 expr2 ...)
    +
    exprN - a numeric expression
    +returns -  T  if the results of +comparing the expressions are all true, +NIL otherwise
    +
    + +

    + +

    Description

    + +

    The '/=' [not-equal] function takes an arbitrary number of +numeric arguments. It checks to see if all the numeric arguments are +different.  T  is returned if +the arguments are numerically not equivalent, +NIL is returned otherwise.

    + +

    Examples

    + +
    +(/= 1 1)            => NIL
    +(/= 1 2)            => T
    +(/= 1 1.0)          => NIL
    +(/= 1 2 3)          => T
    +(/= 1 2 2)          => NIL
    +(/= "a" "b")        => error: bad argument type
    +(setq a 1 b 12.4)   => 12.4  ; set up A and B with values
    +(/= a b)            => NIL
    +
    + +

    See setq.

    + +

    + +

    XLISP Bug

    + +
    +(/= 1 2 3)      => T  ; OK
    +(/= 1 2 3 2 1)  => T  ; wrong
    +
    + +

    This is only a problem for the '/=' function. The bug can be +reproduced with Nyquist 3.03 in November 2010.

    + +

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/number-not-greaterp.htm b/docsrc/xlisp/xlisp-doc/reference/number-not-greaterp.htm new file mode 100644 index 0000000..c9401a4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/number-not-greaterp.htm @@ -0,0 +1,91 @@ +XLISP <= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    <=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (<= expr1 expr2 ...)
    +
    exprN - a numeric expression
    +returns -  T  if the results of +comparing the expressions are all true, +NIL otherwise
    +
    + +

    + +

    Description

    + +

    The '<=' [less-than-or-equal] function takes an arbitrary +number of numeric arguments. It checks to see if all the +numbers are monotonically non-decreasing. + T  is returned if the arguments +are numerically, and monotonically non-decreasing, +NIL is returned otherwise. For two +arguments, this has the effect of testing if 'expr1' is less than or equal +to 'expr2'.

    + +

    Examples

    + +
    +(<= 1 1)            => T
    +(<= 1 2)            => T
    +(<= 2.0 1.99)       => NIL
    +(<= 1 2 3 3)        => T
    +(<= 1 2 3 3 2)      => NIL
    +(<= "aa" "aa")      => error: bad argument type
    +(setq a 12 b 99.9)  => 99.9  ; set up A and B with values
    +(<= a b)            => T
    +(<= b a)            => NIL
    +
    + +

    See setq.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/number-not-lessp.htm b/docsrc/xlisp/xlisp-doc/reference/number-not-lessp.htm new file mode 100644 index 0000000..c9626d8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/number-not-lessp.htm @@ -0,0 +1,92 @@ +XLISP >= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    >=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (>= expr1 expr2 ...)
    +
    exprN - a numeric expression
    +returns -  T  if the results of +comparing the expressions are all true, +NIL otherwise
    +
    + +

    + +

    Description

    + +

    The '>=' [greater-than-or-equal] function takes an +arbitrary number of numeric arguments. It checks to see if all +the numbers are monotonically non-increasing. + T  is returned if 'expr1' is the arguments +are numerically, and monotonically non-increasing, +NIL is returned otherwise. For two +arguments, this has the effect of testing if 'expr1' is greater than or +equal to 'expr2'.

    + +

    Examples

    + +
    +(>= 1 2)            => NIL
    +(>= 1 1)            => T
    +(>= -1.5 -1.4)      => NIL
    +(>= 3 2 1)          => T
    +(>= 3 2 2)          => T
    +(>= 3 2 3)          => NIL
    +(>= "aa" "abc")     => error: bad argument type
    +(setq a 12 b 13.9)  => 13.9  ; set up A and B with values
    +(>= a b)            => NIL
    +(>= b a)            => T
    +
    + +

    See setq.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/numberp.htm b/docsrc/xlisp/xlisp-doc/reference/numberp.htm new file mode 100644 index 0000000..37e994f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/numberp.htm @@ -0,0 +1,78 @@ +XLISP numberp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    numberp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (numberp expr)
    +
    expr - the expression to check
    +returns -  T  if the expression +is a number, NIL otherwise
    +
    + +

    Description

    + +

    The 'numberp' predicate function checks if an 'expr' is a number. + T  is returned if 'expr' is an +integer or floating point number, NIL is +returned otherwise.

    + +

    Examples

    + +
    +(numberp 1)         ; returns T - integer
    +(numberp 1.2)       ; returns T - float
    +(numberp '1)        ; returns T - still an integer
    +(numberp #x034)     ; returns T - the readmacro produces an integer
    +
    +(numberp 'a)        ; returns NIL - symbol
    +(numberp #\a)       ; returns NIL - character
    +(numberp NIL)       ; returns NIL - NIL
    +(numberp #(0 1 2))  ; returns NIL - array
    +
    + +

    See the +numberp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/object.htm b/docsrc/xlisp/xlisp-doc/reference/object.htm new file mode 100644 index 0000000..5c6ede3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/object.htm @@ -0,0 +1,120 @@ +XLISP object + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    object

    + +
    + +

    + + + + + + + + + + +
    Type:  -  object
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
     object
    +
    + +

    Description

    + +

    'object' is an object class. An object +is a composite structure that contains internal state information, methods +[which respond to messages], a pointer to the object's +class and a pointer to the object's +super-class. XLISP contains two built in objects: 'object' and +class. 'object' is the superclass for the +class object.

    + +

    Examples

    + +
    +(send object :show)                                     ; look at the object definition
    +
    +                                                        ; example use of objects
    +(setq my-class (send class :new '(state)))              ; new class MY-CLASS with STATE
    +       
    +(send my-class :answer :isnew '()                       ; set up initialization
    +                              '((setq state nil) self))
    +
    +(send my-class :answer :set-it '(value)                 ; create :SET-IT message
    +                               '((setq state value)))
    +
    +(setq my-obj (send my-class :new))                      ; create MY-OBJ out of MY-CLASS
    +(send my-obj :set-it 5)                                 ; STATE is set to 5
    +
    + +

    Object definition: The internal definition of the 'object' object +instance is:

    + +
    +Object is #<Object: #23fd8>, Class is #<Object: #23fe2>
    +  MESSAGES = ((:SHOW . #<Subr-: #23db2>) 
    +              (:CLASS . #<Subr-: #23dee>) 
    +              (:ISNEW . #<Subr-: #23e2a>))
    +  IVARS = NIL
    +  CVARS = NIL
    +  CVALS = NIL
    +  SUPERCLASS = NIL
    +  IVARCNT = 0
    +  IVARTOTAL = 0
    +#<Object: #23fd8>
    +
    + +

    The class of 'object' is +class. There is no superclass of 'object'. +Remember that the location information [like #23fd8] varies from system to +system, yours will probably look different.

    + +

    Built-in methods: The built in methods in XLISP include:

    + +
      +
    • :answer - add a method to an object
    • +
    • :class - return the object's class
    • +
    • :isnew - run initialization code on object
    • +
    • :new - create a new object [instance or class]
    • +
    • :show - show the internal state of the object
    • +
    + +

    Message structure: The normal XLISP convention for a 'message' is +to have a valid symbol preceeded by a colon like +:isnew or ':my-message'. However, it is +possible to define a 'message' that is a symbol without a colon, but this +makes the code less readable.

    + +

    See the +object +class in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/objectp.htm b/docsrc/xlisp/xlisp-doc/reference/objectp.htm new file mode 100644 index 0000000..22ea9b9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/objectp.htm @@ -0,0 +1,72 @@ +XLISP objectp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    objectp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (objectp expr)
    +
    expr - the expression to check
    +returns -  T  if the expression +is an object, NIL otherwise
    +
    + +

    Description

    + +

    The 'objectp' predicate function checks if the 'expr' is an object. + T  is returned if 'expr' is +an object, NIL is returned otherwise.

    + +

    Examples

    + +
    +(objectp object)   ; returns T
    +(objectp class)    ; returns T
    +(objectp NIL)      ; returns NIL
    +(objectp '(a b))   ; returns NIL
    +
    + +

    See the +objectp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/oddp.htm b/docsrc/xlisp/xlisp-doc/reference/oddp.htm new file mode 100644 index 0000000..fa71431 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/oddp.htm @@ -0,0 +1,92 @@ +XLISP oddp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    oddp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (oddp expr)
    +
    expr - the integer numeric expression to check
    +returns -  T  if the integer is +odd, NIL otherwise
    +
    + +

    Description

    + +

    The 'oddp' predicate function checks to see if the number 'expr' is odd. + T  is returned if the number is +odd, NIL is returned otherwise.

    + +

    An error is generated if the 'expr' is not a numeric expression:

    + +
    +error: bad argument type
    +
    + +

    An error is generated if the 'expr' is a floating point number:

    + +
    +error: bad floating point operation
    +
    + +

    Zero is an even number.

    + +

    Examples

    + +
    +(oddp 0)     ; returns NIL
    +(oddp 1)     ; returns T
    +(oddp 2)     ; returns NIL
    +(oddp -1)    ; returns T
    +(oddp -2)    ; returns NIL
    +
    +(oddp 13.0)  ; error: bad floating point operation
    +(oddp 'a)    ; error: bad argument type
    +(setq a 3)   ; set value of A to 3
    +(oddp a)     ; returns T
    +
    + +

    See the +oddp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/open-binary.htm b/docsrc/xlisp/xlisp-doc/reference/open-binary.htm new file mode 100644 index 0000000..1707407 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/open-binary.htm @@ -0,0 +1,103 @@ +XLISP open-binary + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    open-binary

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (open-binary file [:direction in-out])
    +
    file - a string expression or symbol
    +in-out - an optional keyword symbol that must be either ':input' or +':output'. The default is ':input'.
    +returns - a stream
    +
    + +

    Description

    + +

    The 'open-binary' function opens the 'file' for binary input +or output. The 'file' may be a string expression or a symbol. Following the +'file', there is an optional keyword, ':direction'. The argument following +this is either ':input' or ':output' which specifies the direction of the +file. If no ':direction' is specified, the default is ':input'. +When 'file' is a string, you may specify a complete file location or +extensions like "/usr/local/bin/myfile.lsp" or +"A:\LISP\TIM.BAT". If the file open was successful, +then a file pointer of the following form is returned as the result:

    + +
    +#<File: #99999>
    +
    + +

    If the file open was not successful, a NIL is +returned. For an input file, the file has to exist, or an error +will be signaled.

    + +

    Examples

    + +
    +
    +
    + +

    This will create a file named FOO-FILE, because XLISP uppercases its +symbols:

    + +
    +(open-binary 'foo-file :direction :output)
    +
    + +

    This will create a file named 'foo-file' because UNIX doesn't +uppercase its file names:

    + +
    +(open-binary "foo-file" :direction :output)
    +
    + +

    So, if you are having trouble with opening and accessing files, check to +make sure the file name is in the proper case.

    + +

    See also bigendianp, +read-int, +write-int, +read-float, +write-float.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/open.htm b/docsrc/xlisp/xlisp-doc/reference/open.htm new file mode 100644 index 0000000..fe2a925 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/open.htm @@ -0,0 +1,117 @@ +XLISP open + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    open

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (open file [:direction in-out])
    +
    file - a string expression or symbol
    +in-out - an optional keyword symbol that must be either ':input' or +':output'. The default is ':input'.
    +returns - a stream
    +
    + +

    Description

    + +

    The 'open' function opens the 'file' for input or output. The 'file' may +be a string expression or a symbol. Following the 'file', there is an +optional keyword, ':direction'. The argument following this is either +':input' or ':output' which specifies the direction of the file. If no +':direction' is specified, the default is ':input'. When 'file' is a string, +you may specify a complete file location or extensions like +"/usr/local/bin/myfile.lsp" or "A:\LISP\TIM.BAT". If +the file open was successful, then a file pointer of the following form is +returned as the result:

    + +
    +#<File: #99999>
    +
    + +

    If the file open was not successful, a +NIL is returned. For an input file, the +file has to exist, or an error will be signaled.

    + +

    Examples

    + +
    +(setq f (open 'mine :direction :output))  ; create file named MINE
    +(print "hi" f)                            ; returns "hi"
    +(close f)                                 ; file contains "hi" <newline>
    +(setq f (open 'mine :direction :input))   ; open MYFILE for input
    +(read f)                                  ; returns "hi"
    +(close f)                                 ; close it
    +
    + +

    File names: In the PC and DOS world, all file names and extensions +["foo.bat"] are automatically made uppercase. In using XLISP, this +means you don't have to worry about whether the name is "foo.bat", +"FOO.BAT" or even "FoO.bAt", they will all work. +However, in other file systems [UNIX in particular], uppercase and lowercase +do make a difference:

    + +

    This will create a file named FOO-FILE in UNIX, because XLISP uppercases +its symbols:

    + +
    +(open 'foo-file :direction :output)
    +
    + +

    This will create a file named 'foo-file' because UNIX doesn't +uppercase its file names:

    + +
    +(open "foo-file" :direction :output)
    +
    + +

    So, if you are having trouble with opening and accessing files, check to +make sure the file name is in the proper case.

    + +

    Common Lisp: Common Lisp supports bidirectional files. So, porting +Common Lisp code may be difficult to port if it uses these other file +types.

    + +

    See the +open +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/or.htm b/docsrc/xlisp/xlisp-doc/reference/or.htm new file mode 100644 index 0000000..9900bdd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/or.htm @@ -0,0 +1,87 @@ +XLISP or + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    or

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (or [expr1 ... ])
    +
    exprN - an expression
    +returns - NIL if all expressions evaluate +to NIL , otherwise the value +of the first non-NIL expression
    +Note: evaluation of expressions stops after the first expression +that does not evaluate to NIL
    +
    + +

    Description

    + +

    The 'or' special form evaluates a sequence of expressions and returns the +effect of a logical 'inclusive-or' operation on the expressions. If all of +the expressions are NIL , +NIL is returned as the result. Evaluation +of the expressions will stop when an expression evaluates to something other +than NIL , none of the +subsequent expressions will be evaluated. If there are no expressions, 'or' +returns NIL as its result.

    + +

    Examples

    + +
    +(or NIL NIL NIL)                    ; returns NIL
    +(or NIL T NIL)                      ; returns T
    +(or NIL (princ "hi") (princ "ho"))  ; prints  hi  and returns "hi"
    +(or T T T)                          ; returns T
    +(or)                                ; returns NIL
    +
    +(setq a 5)  (setq b 6)              ; set up A and B
    +(if (or (< a b) (< b a))            ; if
    +   (print "not equal")              ;   then
    +   (print "equal"))                 ;   else
    +                                    ; prints  "not equal"
    +
    + +

    See the +or +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/peek-char.htm b/docsrc/xlisp/xlisp-doc/reference/peek-char.htm new file mode 100644 index 0000000..8111cf4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/peek-char.htm @@ -0,0 +1,105 @@ +XLISP peek-char + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    peek-char

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (peek-char [skip-flag [source]])
    +
    skip-flag - an optional expression, default is +NIL
    +source - an optional source, must be a file pointer or stream, default +is *standard-input*
    +returns - the character
    +
    + +

    Description

    + +

    The 'peek-char' function looks at a single character from the specified +'source'. The character looked-at is returned as an integer value for the +result. If the 'skip-flag' expression is +NIL , then the next character +will be looked-at, without advancing the position within the file. If the +'skip-flag' expression is non-NIL +, then the next non-white-space character will be looked-at. This +skipping does advance the position within the file. White-space characters +include 'blank', 'tab' and 'new-line' characters. If 'skip-flag' is not +used, no skipping will occur. The 'source' may be a file pointer or a +stream. If there is no 'source', +*standard-input* is the default. If an +end-of-file is encountered in the 'source', then +NIL will be returned as the result.

    + +

    Examples

    + +
    +(setq fp (open "f" :direction :output))  ; create file "f"
    +(print 12 fp)
    +(princ "  34" fp)
    +(terpri fp)
    +(close fp)
    +
    +(setq fp (open "f" :direction :input))   ; open "f" for reading
    +(peek-char NIL fp)                       ; returns #\1
    +(peek-char NIL fp)                       ; returns #\1 - didn't advance
    +(read-char fp)                           ; returns #\1 - force advance
    +(peek-char NIL fp)                       ; returns #\2
    +(read-char fp)                           ; returns #\2 - force advance
    +(peek-char NIL fp)                       ; returns #\Newline
    +(peek-char T fp)                         ; returns #\3 - skipped blanks
    +(read-line fp)                           ; returns "34"
    +(close fp)
    +
    + +

    Common Lisp: The XLISP and Common Lisp 'peek-char' functions are +compatible for simple cases. They both allow for the optional 'skip-flag' +and 'source'. However, in Common Lisp, there are additional parameters which +occur right after 'source' that support various end-of-file operations and +recursive calls. So, when porting from Common Lisp to XLISP, remember there +are additional arguments in Common Lisp's 'peek-char' that are not supported +in XLISP.

    + +

    See the +peek-char +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/peek.htm b/docsrc/xlisp/xlisp-doc/reference/peek.htm new file mode 100644 index 0000000..58e2cec --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/peek.htm @@ -0,0 +1,86 @@ +XLISP peek + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    peek

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c

    + +

    Syntax

    + +
    +
    (peek address)
    +
    address - an integer expression
    +returns - the value at the specified address as an integer
    +
    + +

    Description

    + +

    The 'peek' function returns the internal memory value at the 'address'. +The returned value is an integer.

    + +

    Examples

    + +
    +(setq var 0)                    ; set up VAR with 0
    +(address-of var)                ; returns 123224
    +(address-of 'var)               ; returns 161922
    +(peek (address-of var))         ; returns 83951616
    +(peek (1+ (address-of var)))    ; returns 16777216
    +(peek (+ 2 (address-of var)))   ; returns 0  <-- value of VAR
    +(setq var 14)                   ; change the value to 14
    +(peek (+ 2 (address-of var)))   ; returns 14
    +(setq var 99)                   ; change the value to 99
    +(peek (+ 2 (address-of var)))   ; returns 99
    +
    + +

    Caution: Be careful when modifying the internal state of XLISP. If +you have modified it, it would be a good idea to exit XLISP and re-enter +before doing any work you really want to retain.

    + +

    Caution: It is possible to 'peek' and +poke not just XLISP's memory put other +parts of your computer's memory. Be very careful when doing this. Also, in +some computers, just looking at a memory location can cause things to +happen, I/O locations fall in this category.

    + +

    See the +peek +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/pi.htm b/docsrc/xlisp/xlisp-doc/reference/pi.htm new file mode 100644 index 0000000..9be3a2a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/pi.htm @@ -0,0 +1,66 @@ +XLISP rrandom + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    rrandom

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp variable
    Source:  -  dspprims.lsp

    + +

    Syntax

    + +

    + +
    +
    pi
    +
    returns - a floating point value of 3.14159265358979
    +
    + +

    + +

    Description

    + +

    The 'pi' variable returns a floating point approximation of the +number 'pi'.

    + +

    Examples

    + +
    +pi  => 3.14159265358979
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/plus.htm b/docsrc/xlisp/xlisp-doc/reference/plus.htm new file mode 100644 index 0000000..b5e3984 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/plus.htm @@ -0,0 +1,75 @@ +XLISP + (variable) + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    (variable)

    + +
    + +

    + + + + + + + + + + +
    Type:  -  variable
    Source:  -  xlinit.c, xlisp.c

    + +

    Syntax

    + +

    + +
    +
     +
    +
    returns - the most recent input expression
    +
    + +

    + +

    Description

    + +

    The '+' variable is set to the most recent input expression.

    + +

    Examples

    + +
    +(setq hi 'there)  => THERE
    ++                 => (SETQ HI (QUOTE THERE))
    ++                 => +
    +
    + +

    See setq.

    + +

    Note: The '+' variable is for interactive programming. It +is not recommended to use the '+' variable in program code.

    + +

    See also the +XLISP Command Loop.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/poke.htm b/docsrc/xlisp/xlisp-doc/reference/poke.htm new file mode 100644 index 0000000..336ca39 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/poke.htm @@ -0,0 +1,88 @@ +XLISP poke + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    poke

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c

    + +

    Syntax

    + +
    +
    (poke address expr)
    +
    address - an integer expression
    +expr - an integer expression
    +returns - the value
    +
    + +

    Description

    + +

    The 'poke' function writes the 'expr' at the internal memory value at the +specified 'address'. The returned value is 'expr'. Be very careful with this +function.

    + +

    Examples

    + +
    +(setq var 0)                        ; set up VAR with 0
    +(address-of var)                    ; returns 123224
    +(address-of 'var)                   ; returns 161922
    +(peek (address-of var))             ; returns 83951616
    +(peek (1+ (address-of var)))        ; returns 16777216
    +(peek (+ 2 (address-of var)))       ; returns 0  <-- value of VAR
    +(setq var 14)                       ; change the value to 14
    +(peek (+ 2 (address-of var)))       ; returns 14
    +(poke (+ 2 (address-of var)) 1023)  ; POKE the value to 1023
    +(print var)                         ; prints  1023
    +
    + +

    Caution: Be careful when modifying the internal state of XLISP. If +you have modified it, it would be a good idea to exit XLISP and re-enter +before doing any work you really want to retain.

    + +

    Caution: It is possible to peek +and 'poke' not just XLISP's memory put other parts of your computer's +memory. Be very careful when doing this. Also, in some computers, just +looking at a memory location can cause things to happen, I/O locations fall +in this category.

    + +

    See the +poke +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/pop.htm b/docsrc/xlisp/xlisp-doc/reference/pop.htm new file mode 100644 index 0000000..73165ca --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/pop.htm @@ -0,0 +1,85 @@ +XLISP pop + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    pop

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp macro
    Source:  -  misc.lsp

    + +

    Syntax

    + +

    + +
    +
    (pop list)
    +
    list - a list
    +returns - the first element from the list
    +
    + +

    + +

    'pop' is implemented as a Lisp macro:

    + +
    +(defmacro pop (lis)
    +  `(prog1 (car ,lis)
    +          (setf ,lis (cdr ,lis))))
    +
    + +

    Description

    + +

    The 'pop' macro reads, removes and returns the first element from the +list.

    + +

    Examples

    + +
    +(setq stack '(a b c))  => (A B C)
    +(pop stack)            => A  
    +stack                  => (B C)
    +(pop stack)            => B  
    +stack                  => (C)
    +(pop stack)            => C 
    +stack                  => NIL
    +(pop stack)            => NIL
    +stack                  => NIL
    +
    + +

    See setq. See also the push macro.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/power.htm b/docsrc/xlisp/xlisp-doc/reference/power.htm new file mode 100644 index 0000000..6df1216 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/power.htm @@ -0,0 +1,77 @@ +XLISP power + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    power

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  misc.lsp

    + +

    Syntax

    + +

    + +
    +
    (power x y)
    +
    x, y - two integer or floating point numbers
    +returns - x raised to the y power as a floating point number
    +
    + +

    + +

    In Nyquist, 'power' is implemented as a Lisp function:

    + +
    +(defun power (x y)
    +  (exp (* (log (float x)) y)))
    +
    + +

    Description

    + +

    The 'power' function returns 'x' raised to the 'y' power as a floating +point number. + +

    Examples

    + +
    +(power 2 8)   => 256
    +(power 4 .5)  => 2.0
    +
    + +

    See also expt.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/pprint.htm b/docsrc/xlisp/xlisp-doc/reference/pprint.htm new file mode 100644 index 0000000..7ab7021 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/pprint.htm @@ -0,0 +1,94 @@ +XLISP pprint + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    pprint

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlpp.c

    + +

    Syntax

    + +
    +
    (pprint expr [dest])
    +
    expr - an expression to be pretty printed
    +dest - an optional destination, must be a file pointer or +stream, default is *standard-output*
    +returns - always returns NIL
    +
    + +

    Description

    + +

    The 'pprint' function produces a pretty looking version of the 'expr' and +prints it to the specified 'destination'. If 'expr' is an atom like a +string, a symbol, a number, etc., 'pprint' will print it like +print. If 'expr' is a list, it will perform +indenting, as necessary. NIL is always +returned as the result of 'pprint'. The 'destination' may be a file pointer +or a stream. If there is no 'destination' or it is +NIL , +*standard-output* is the default.

    + +

    Examples

    + +
    +(pprint 'a)      ; prints  A       returns NIL
    +(pprint "abcd")  ; prints  "abcd"  returns NIL
    +
    +(pprint '(a-very-long-name (first list) (second list)))
    +
    +                 ; prints (A-VERY-LONG-NAME (FIRST LIST)
    +                 ;                          (SECOND LIST))
    +                 ; returns NIL
    +
    + +

    Common Lisp: Common Lisp specifies that 'pprint' with a +'destination' of NIL will go to +*standard-output*. XLISP does not send the +output to *standard-output* with a +'destination' of NIL. Common Lisp also +specifies that a 'destination' of + T  will be sent to +*terminal-io*, which is not defined in XLISP by default. XLISP does not +allow  T  as a valid argument +for 'destination'.

    + +

    See the +pprint +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/prin1.htm b/docsrc/xlisp/xlisp-doc/reference/prin1.htm new file mode 100644 index 0000000..c0b8a7c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/prin1.htm @@ -0,0 +1,94 @@ +XLISP prin1 + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    prin1

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c, xlprin.c

    + +

    Syntax

    + +
    +
    (prin1 expr [dest])
    +
    expr - an expression
    +dest - an optional destination, must be a file pointer or +stream, default is *standard-output*
    +returns - the expression
    +
    + +

    Description

    + +

    The 'prin1' function prints the 'expr' to the specified 'destination'. +The 'expr' is printed without a 'newline' character. If 'expr' is a string, +it will be printed with quotes around the string. The 'expr' is returned as +the result. The 'destination' may be a file pointer or a stream. If there is +no 'destination', *standard-output* is the +default. The terpri function is used to +terminate the print lines produced.

    + +

    Examples

    + +
    +(prin1 'a)                              ; prints A     without #\Newline
    +(prin1 '(a b))                          ; prints (A B) without #\Newline
    +(prin1 2.5)                             ; prints 2.5   without #\Newline
    +(prin1 "hi")                            ; prints "hi"  without #\Newline
    +
    +(setq f (open "f" :direction :output))  ; create file
    +(prin1 "hi" f)                          ; returns "hi"
    +(prin1 1234 f)                          ; returns 1234
    +(prin1 "he" f)                          ; returns "he"
    +(close f)                               ; file contains "hi"1234"he"
    +
    + +

    Common Lisp: Common Lisp specifies that 'pprint' with a +'destination' of NIL will go to +*standard-output*. XLISP does not send the +output to *standard-output* with a +'destination' of NIL. Common Lisp also +specifies that a 'destination' of + T  will be sent to +*terminal-io*, which is not defined in XLISP by default. XLISP does not +allow  T  as a valid argument +for 'destination'.

    + +

    See the +prin1 +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/princ.htm b/docsrc/xlisp/xlisp-doc/reference/princ.htm new file mode 100644 index 0000000..a3a095f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/princ.htm @@ -0,0 +1,94 @@ +XLISP princ + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    princ

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c, xlprin.c

    + +

    Syntax

    + +
    +
    (princ expr [dest])
    +
    expr - an expression
    +dest - an optional destination, must be a file pointer or +stream, default is *standard-output*
    +returns - the expression
    +
    + +

    Description

    + +

    The 'princ' function prints the 'expr' to the specified 'destination'. +The 'expr' is printed without a 'newline' character. If 'expr' is a string, +it will not be printed with quotes around the string. The 'expr' is returned +as the result. The 'destination' may be a file pointer or a stream. If there +is no 'destination', *standard-output* is +the default. The terpri function is used to +terminate the print lines produced.

    + +

    Examples

    + +
    +(princ 'a)                              ; prints A     without #\Newline
    +(princ '(a b))                          ; prints (A B) without #\Newline
    +(princ 99)                              ; prints 99    without #\Newline
    +(princ "hi")                            ; prints hi    without #\Newline
    +
    +(setq f (open "f" :direction :output))  ; create file
    +(princ "hi" f)                          ; returns "hi"
    +(princ 727 f)                           ; returns 727
    +(princ "ho" f)                          ; returns "ho"
    +(close f)                               ; file contains hi727ho
    +
    + +

    Common Lisp: Common Lisp specifies that 'pprint' with a +'destination' of NIL will go to +*standard-output*. XLISP does not send the +output to *standard-output* with a +'destination' of NIL. Common Lisp also +specifies that a 'destination' of + T  will be sent to +*terminal-io*, which is not defined in XLISP by default. XLISP does not +allow  T  as a valid argument +for 'destination'.

    + +

    See the +princ +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/print.htm b/docsrc/xlisp/xlisp-doc/reference/print.htm new file mode 100644 index 0000000..d714844 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/print.htm @@ -0,0 +1,95 @@ +XLISP print + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    print

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c, xlprin.c

    + +

    Syntax

    + +
    +
    (print expr [dest])
    +
    expr - an expression
    +dest - an optional destination, must be a file pointer or +stream, default is *standard-output*
    +returns - the expression
    +
    + +

    Description

    + +

    The 'print' function prints the 'expr' to the specified 'destination'. +The 'expr' is printed followed by a 'newline' character. If 'expr' is a +string, it will be printed with quotes around the string. The 'expr' is +returned as the result. The 'destination' may be a file pointer or a stream. +If there is no 'destination', +*standard-output* is the default.

    + +

    Examples

    + +
    +(print 'a)                              ; prints A     with #\Newline
    +(print '(a b))                          ; prints (A B) with #\Newline
    +(print 99)                              ; prints 99    with #\Newline
    +(print "hi")                            ; prints "hi"  with #\Newline
    +
    +(setq f (open "f" :direction :output))  ; create file
    +(print "hi" f)                          ; returns "hi"
    +(print 727 f)                           ; returns 727
    +(print "ho" f)                          ; returns "ho"
    +(close f)                               ; file contains "hi"#\Newline
    +                                        ;               727#\Newline
    +                                        ;               "ho"#\Newline
    +
    + +

    Common Lisp: Common Lisp specifies that 'pprint' with a +'destination' of NIL will go to +*standard-output*. XLISP does not send the +output to *standard-output* with a +'destination' of NIL. Common Lisp also +specifies that a 'destination' of + T  will be sent to +*terminal-io*, which is not defined in XLISP by default. XLISP does not +allow  T  as a valid argument +for 'destination'.

    + +

    See the +print +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/profile.htm b/docsrc/xlisp/xlisp-doc/reference/profile.htm new file mode 100644 index 0000000..0c3cf6a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/profile.htm @@ -0,0 +1,85 @@ + + +Profiling + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    profile

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c, xleval.c

    + +

    Syntax

    + + + +

    + +
    +
    (profile flag) - turn profiling on or off
    +
    flag - NIL turns profiling off, otherwise on
    +returns - the previous state of profiling
    +
    + +

    + +

    Description

    + +

    The Xlisp 2.0 release has been extended with a profiling +facility, which counts how many times and where eval +is executed. A separate count is maintained for each named +function, closure, or macro, and a count indicates an +eval in the immediately [lexically] enclosing named +function, closure, or macro. Thus, the count gives an indication of the +amount of time spent in a function, not counting nested function calls.

    + +

    The list of all functions executed is maintained on the global *profile* +variable. These functions in turn have *profile* properties, which maintain +the counts. The profile system merely increments counters and puts symbols +on the *profile* list. It is up to the user to initialize data +and gather results. Profiling is turned on or off with the 'profile' +function.

    + +

    Unfortunately, methods cannot be profiled with this facility.

    + +

    Examples

    + +
    +
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/reference/prog-star.htm b/docsrc/xlisp/xlisp-doc/reference/prog-star.htm new file mode 100644 index 0000000..98ba7b1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/prog-star.htm @@ -0,0 +1,101 @@ +XLISP prog* + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    prog*

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (prog* ([binding ... ]) [expr ... ])
    +
    binding - a variable binding which is can take one of +
    symbol
    +(symbol init-expr)
    +
    symbol - a symbol
    +init-expr - an initialization expression for symbol
    +expr - expressions comprising the body of the loop which may contain +returns, +gos or tags for +go
    +returns - NIL or the argument passed to +the return function
    +
    + +

    Description

    + +

    The 'prog*' special form is basically a 'block' construct that contains +symbols with optional initializations and a block of code [expressions] to +evaluate. The 'prog*' special form evaluates its initializations in +sequential order as opposed to prog which does it in no +specified order. The first form after the 'prog*' is the 'binding' form. It +contains a series of 'symbols' or 'bindings'. The 'binding' is a 'symbol' +followed by an initialization expression 'init-expr'. If there is no +'init-expr', the 'symbol' will be initialized to +NIL. The order of execution of the bindings +is sequential. If a return form is +evaluated, its value will be returned. Otherwise, +NIL is returned. When the 'prog*' is +finished execution, the 'symbols' that were defined will no longer exist or +retain their values.

    + +

    Examples

    + +
    +(prog* (i j)                 ; PROG* with vars I and J
    +       (print i) (print j))  ; prints  NIL NIL  returns NIL
    +
    +(prog* ((i 1) (j 2))         ; PROG* with vars I and J
    +       (print i) (print j)
    +       (return (+ i j)))     ; prints 1 2  returns 3
    +
    +(prog* () (print "hello"))   ; prints "hello"  returns NIL
    +
    +(prog ((i 1) (j (+ i 1)))    ; PROG won't work due to order
    +      (print (+ i j)) )      ; error: unbound variable - I
    +
    +(prog* ((i 1) (j (+ i 1)))   ; PROG* will work due to order
    +       (print (+ i j)) )     ; prints 3  returns NIL
    +
    + +

    See the +prog* +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/prog.htm b/docsrc/xlisp/xlisp-doc/reference/prog.htm new file mode 100644 index 0000000..ea1d29c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/prog.htm @@ -0,0 +1,96 @@ +XLISP prog + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    prog

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (prog ([binding ... ]) [expr ... ])
    +
    binding - a variable binding which is can take one of +
    symbol
    +(symbol init-expr)
    +
    symbol - a symbol
    +init-expr - an initialization expression for symbol
    +expr - expressions comprising the body of the loop which may contain +returns, +gos or tags for +go
    +returns - NIL or the argument passed to +the return function
    +
    + +

    Description

    + +

    The 'prog' special form is basically a 'block' construct that contains +symbols with optional initializations and a block of code [expressions] to +evaluate. The 'prog' special form evaluates its initializations in no +specified order, as opposed to prog* which +does it sequential order. The first form after the 'prog' is the 'binding' +form. It contains a series of 'symbols' or 'bindings'. The 'binding' is a +'symbol' followed by an initialization expression 'init-expr'. If there is +no 'init-expr', the 'symbol' will be initialized to +NIL. There is no specification as to the +order of execution of the bindings or the step expressions, except that they +happen all together. If a return form is +evaluated, its value will be returned. Otherwise, +NIL is returned. When 'prog' is finished +execution, the 'symbols' that were defined will no longer exist or retain +their values.

    + +

    Examples

    + +
    +(prog () (print "hello"))   ; prints "hello"  returns NIL
    +
    +(prog (i j)                 ; PROG with vars I and J
    +      (print i) (print j))  ; prints NIL NIL  returns NIL
    +
    +(prog ((i 1) (j 2))         ; PROG with vars I and J
    +      (print i) (print j)
    +      (return (+ i j)))     ; prints 1 2  returns 3
    +
    + +

    See the +prog +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/prog1.htm b/docsrc/xlisp/xlisp-doc/reference/prog1.htm new file mode 100644 index 0000000..d56a1f0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/prog1.htm @@ -0,0 +1,80 @@ +XLISP prog1 + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    prog1

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (prog1 [expr1 expr2 ... ])
    +
    exprN - expressions comprising the body of the loop
    +returns - the value of the first expression
    +
    + +

    Description

    + +

    The 'prog1' special form is basically a 'block' construct that contains a +block of code [expressions] to evaluate. The value of the first expression +'expr1' will be returned as the result of 'prog1'. If there is no 'expr1', +NIL is returned.

    + +

    Examples

    + +
    +(prog1 (print "hi") (print "ho"))  ; prints "hi" "ho"  returns "hi"
    +(prog1)                            ; returns NIL
    +(prog1 'a)                         ; returns A
    +(prog1 "hey" (print "ho"))         ; prints "ho"  returns "hey"
    +
    + +

    Note: 'prog1', +prog2 , +progn and +progv do not allow the use of +return or +go or tags for +go.

    + +

    See the +prog1 +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/prog2.htm b/docsrc/xlisp/xlisp-doc/reference/prog2.htm new file mode 100644 index 0000000..8ed5592 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/prog2.htm @@ -0,0 +1,82 @@ +XLISP prog2 + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    prog2

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (prog2 [expr1 expr2 ... ])
    +
    exprN - expressions comprising the body of the loop
    +returns - the value of the second expression
    +
    + +

    Description

    + +

    The 'prog2' special form is basically a 'block' construct that contains a +block of code [expressions] to evaluate. The value of the second expression +'expr2' will be returned as the result of 'prog2'. If there is no 'expr2', +'expr1' is returned. If there is no 'expr1', +NIL is returned.

    + +

    Examples

    + +
    +(prog2 (print "hi") (print "ho"))  ; prints "hi" "ho"  returns "ho"
    +(prog2)                            ; returns NIL
    +(prog2 (print "hi"))               ; prints "hi"  returns "hi"
    +(prog2 (print "ho") "hey")         ; prints "ho"  returns "hey"
    +(prog2 'a 'b 'c)                   ; returns B
    +
    + +

    Note: prog1 , +'prog2', +progn and +progv do not allow the use of +return or +go or tags for +go.

    + +

    See the +prog2 +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/progn.htm b/docsrc/xlisp/xlisp-doc/reference/progn.htm new file mode 100644 index 0000000..9cb28a3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/progn.htm @@ -0,0 +1,81 @@ +XLISP progn + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    progn

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c, xllist.c

    + +

    Syntax

    + +
    +
    (progn [expr1 expr2 ... ])
    +
    exprN - expressions comprising the body of the loop
    +returns - the value of the last expression
    +
    + +

    Description

    + +

    The 'progn' special form is basically a 'block' construct that contains a +block of code [expressions] to evaluate. The value of the last expression +'exprN' will be returned as the result of 'progn'. If there are no 'exprs', +NIL is returned.

    + +

    Examples

    + +
    +(progn (print "hi") (print "ho"))  ; prints "hi" "ho"  returns "ho"
    +(progn)                            ; returns NIL
    +(progn "hey" (print "ho"))         ; prints "ho"  returns "ho"
    +(progn 'a)                         ; returns A
    +(progn 'a 'b 'c)                   ; returns C
    +
    + +

    Note: prog1 , +prog2 , +'progn' and +progv do not allow the use of +return or +go or tags for +go.

    + +

    See the +progn +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/progv.htm b/docsrc/xlisp/xlisp-doc/reference/progv.htm new file mode 100644 index 0000000..47ccd84 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/progv.htm @@ -0,0 +1,133 @@ +XLISP progv + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    progv

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +

    + +
    +
    (progv symbols values [expr1 expr2 ... ])
    +
    symbols - a list of symbols to be bound
    +values - a list of values to be bound to symbols
    +exprN - expressions for the body of the loop
    +returns - the value of the last expression
    +
    + +

    + +

    Description

    + +

    The 'progv' special form is basically a 'block' construct that contains a +block of code [expressions] to evaluate. 'progv' is different from +prog1, prog2 +and progn in that it contains a pair of lists, +'symbols' and 'values'. Before evaluating the expressions, 'progv' +will dynamically bind the 'values' to the corresponding 'symbols'. +If there are too many 'symbols' for the 'values', the 'symbols' +with no corresponding 'values' will be bound to NIL. +The variables will be unbound after the execution of 'progv'. +The value of the last 'expr' will be returned as the result of +'progv'. If there are no 'exprs', +NIL is returned.

    + +

    Examples

    + +
    +> (progv '(var) '(2)
    +    (print var)
    +    (print "two"))
    +2      ; output of PRINT
    +"two"  ; output of PRINT
    +"two"  ; return value
    +
    +> (setq a "beginning")   ; initialize A
    +"beginning"
    +
    +> (progv '(a) '(during)  ; bind A to a new value
    +    (print a))
    +DURING  ; output of PRINT
    +DURING  ; return value     restore A the original value
    +
    +> (print a)
    +"beginning"              ; prints the original value
    +"beginning"
    +
    +> (progv '(no-way) '(no-how))
    +NIL
    +
    +> (progv)
    +error: too few arguments
    +
    + +

    Note: 'progv' is different from +prog, which allows symbols and +initialization forms, in that 'progv' allows its 'symbols' and 'values' to +be evaluated. This allows you to pass in forms that generate the 'symbols' +and their 'values'.

    + +

    Note: prog1, +prog2, progn +and 'progv' do not allow the use of return or +go or tags for go.

    + +

    Important: In contrast to all other binding constructs, 'progv' +binds global variables and not lexical variables, so 'progv' behaves +like:

    + +
    +(defun progv (symbols values &rest body)  ; this function does
    +  (push symbol-values *internal-stack*)   ; not really work,
    +  (setq symbols values)                   ; it only demonstates
    +  (prog1                                  ; the principle
    +    (eval body)
    +    (setq symbol-values (pop *internal-stack*))))
    +
    + +

    Variables bound by 'progv' can be manipulated by global functions +including symbol-value. +All changes to the 'progv' variables by other functions, called +in the 'progv' body, will be lost after 'progv' is finished, because the +original value from the beginning of 'progv' will be restored. This can be +good or bad, depending on the situation.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/psetq.htm b/docsrc/xlisp/xlisp-doc/reference/psetq.htm new file mode 100644 index 0000000..dea8f74 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/psetq.htm @@ -0,0 +1,78 @@ +XLISP psetq + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    psetq

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (psetq [symbol expr] ... )
    +
    symbol - un-evaluated symbol
    +expr - value for symbol
    +returns - the value from the last expr
    +
    + +

    Description

    + +

    'psetq' sets 'expr' as the value of 'symbol'. There can be several pairs +of assignment. 'psetq' performs these assignments in parallel, the 'symbols' +are not assigned new values until all the 'exprs' have been evaluated. +'psetq' returns the value from the last 'expr' as it's result.

    + +

    Examples

    + +
    +(psetq a 1)              ; symbol A gets value 1
    +(psetq b '(a b c))       ; symbol B gets value (A B C)
    +(psetq mynum (+ 3 4))    ; symbol MYNUM gets value 7
    +
    +(setq goo 'ber)          ; returns BER
    +(setq num 1)             ; returns 1
    +(psetq goo num num goo)  ; returns BER
    +(print goo)              ; returns 1
    +(print num)              ; returns BER
    +
    + +

    See the +psetq +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/push.htm b/docsrc/xlisp/xlisp-doc/reference/push.htm new file mode 100644 index 0000000..d649432 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/push.htm @@ -0,0 +1,83 @@ +XLISP push + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    push

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp macro
    Source:  -  misc.lsp

    + +

    Syntax

    + +

    + +
    +
    (push expr list)
    +
    expr - an expression
    +list - a list
    +returns - the new value of list
    +
    + +

    + +

    'push' is implemented as a Lisp macro:

    + +
    +(defmacro push (val lis)
    +  `(setf ,lis (cons ,val ,lis)))
    +
    + +

    Description

    + +

    The 'push' macro stores the value of the expression to the front of the +list and returns the list.

    + +

    Examples

    + +
    +(setq lst nil)  => NIL
    +(push 1 lst)    => (1)
    +lst             => (1)
    +(push 2 lst)    => (2 1)
    +lst             => (2 1)
    +(push 3 lst)    => (3 2 1)
    +lst             => (3 2 1)
    +
    + +

    See setq. See also the pop macro.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/putprop.htm b/docsrc/xlisp/xlisp-doc/reference/putprop.htm new file mode 100644 index 0000000..7711bf2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/putprop.htm @@ -0,0 +1,108 @@ +XLISP putprop + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    putprop

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (putprop symbol value property)
    +
    symbol - the symbol with a property list
    +value - the value to be assigned to the property
    +property - the property name being changed or added
    +returns - the property value
    +
    + +

    Description

    + +

    The 'putprop' function sets the value of the 'property' in the 'symbol'. +If the 'property' does not exist, the 'property' is added to the property +list. The 'symbol' must be an existing symbol. The 'value' may be a single +value or a list.

    + +

    Property lists are lists attached to any user defined variables. The +lists are in the form of:

    + +
    +(name1 val1 name2 val2 ... )
    +
    + +

    Any number of properties may be attached to a single variable.

    + +

    Examples

    + +
    +(setq person 'bobby)                  ; create a var with a value
    +(putprop person 'boogie 'last-name)   ; add a LAST-NAME property
    +(putprop person 'disc-jockey 'job)    ; add a JOB property
    +
    +(get person 'last-name)               ; retrieve LAST-NAME - boogie
    +(get person 'job)                     ; retrieve JOB - disc-jockey
    +(get person 'height)                  ; non-existant - returns NIL
    +
    +(putprop person '(10 20 30) 'stats)   ; add STATS - a list
    +(get person 'stats)                   ; retrieve STATS - (10 20 30)
    +
    + +

    Note: You can set a property to the value +NIL. However, this +NIL value is indistinguishable from the +NIL returned when a property does not +exist.

    + +

    Common Lisp: Common LISP does not have a 'putprop' function. It +uses setf to achieve this functionality. +Porting from Common Lisp to XLISP will work fine since XLISP supports the setf modifications of property lists as well +as the get function to retrieve property +values from symbol names. Porting from XLISP to Common Lisp will require +translating 'putprop' into setf forms.

    + +

    Caution: In XLISP, the order of 'putprop' arguments is 'symbol', +'value', 'property'. This is different from many other Lisps which normally +use 'symbol', 'property', 'value'. Be careful when porting existing Lisp +code.

    + +

    See the +putprop +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/quit.htm b/docsrc/xlisp/xlisp-doc/reference/quit.htm new file mode 100644 index 0000000..1710d92 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/quit.htm @@ -0,0 +1,69 @@ +XLISP quit + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    quit

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c

    + +

    Syntax

    + +
    +
    (quit)
    +
    returns - never returns
    +
    + +

    Description

    + +

    The 'quit' function causes the current XLISP session to be terminated. +It never returns.

    + +

    Examples

    + +
    +(quit)   ; never returns
    +
    + +

    Note: When XLISP is exited, any +dribble transcript file is automatically +closed. However, other open files are not closed, and so may lose some +information.

    + +

    See also exit.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/quote.htm b/docsrc/xlisp/xlisp-doc/reference/quote.htm new file mode 100644 index 0000000..8a84180 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/quote.htm @@ -0,0 +1,84 @@ +XLISP quote + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    quote

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (quote expr)
    +
    expr - an expression
    +returns - the unevaluated expression
    +
    + +

    Description

    + +

    The 'quote' function returns the 'expr' unevaluated.

    + +

    Examples

    + +
    +my-var                    ; error: unbound variable
    +(quote my-var)            ; returns MY-VAR
    +my-var                    ; still error: unbound variable
    +(set (quote my-var) 111)  ; give MY-VAR a value, make it exist
    +my-var                    ; returns 111
    +(quote my-var)            ; returns MY-VAR
    +
    +;; Same as above but using the ' read macro for quote
    +
    +new-var                   ; error: unbound variable
    +'new-var                  ; returns NEW-VAR
    +new-var                   ; still error: unbound variable
    +(setq new-var 222)        ; give NEW-VAR a value, make it exist
    +new-var                   ; returns 222
    +'new-var                  ; returns NEW-VAR
    +
    + +

    Read macro: XLISP supports the +read macro +of a single quote as a short-hand method of writing the 'quote' function.

    + +

    See the +quote +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/random.htm b/docsrc/xlisp/xlisp-doc/reference/random.htm new file mode 100644 index 0000000..d697135 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/random.htm @@ -0,0 +1,86 @@ +XLISP random + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    random

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (random expr)
    +
    expr - integer number or expression
    +returns - a random number between 0 and expr - 1.
    +
    + +

    Description

    + +

    The 'random' function generates and returns a random number between 0 and +'expr' - 1. If 'expr' is negative, the number range is forced +to be positive.

    + +

    Examples

    + +
    +(random 100)      ; returns 7
    +(random 100)      ; returns 49
    +(random 100)      ; returns 73
    +(random -100)     ; returns 58
    +(random 100.01)   ; error: bad floating point operation
    +
    + +

    Common Lisp: Common Lisp allows an optional 'state' parameter, +which is not supported in XLISP. Also, Common LISP allows floating point +numbers, which XLISP does not support.

    + +

    Note: This function is an extension of the XLISP system. It is +provided in the 'msstuff.c' source code file. If your XLISP system is built +for an IBM PC and compatibles, this function will work. If your system is +built on UNIX or some other operating system, it will need the code in the +corresponding 'stuff.c' file.

    + +

    Nyquist: As far as I know the Nyquist 'random' function works on +all systems. See also the Nyquist +rrandom function.

    + +

    See the +random +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/read-byte.htm b/docsrc/xlisp/xlisp-doc/reference/read-byte.htm new file mode 100644 index 0000000..4047ae6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/read-byte.htm @@ -0,0 +1,100 @@ +XLISP read-byte + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    read-byte

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (read-byte [source])
    +
    source - an optional source, must be a file pointer or stream, +default is *standard-input*
    +returns - the byte as an integer
    +
    + +

    Description

    + +

    The 'read-byte' function reads a single character from the specified +'source'. The character read is returned as an integer value for the result. +The 'source' may be a file pointer or a stream. If there is no 'source', +*standard-input* is the default. If an +end-of-file is encountered in the 'source', then +NIL will be returned as the result.

    + +

    Examples

    + +
    +(setq fp (open "f" :direction :output))  ; set up file
    +(print 12.34 fp)
    +(close fp)
    +
    +(setq fp (open "f" :direction :input))   ; now read the file
    +(read-byte fp)                           ; returns 49  - equals "1"
    +(read-byte fp)                           ; returns 50  - equals "2"
    +(read-byte fp)                           ; returns 46  - equals "."
    +(read-byte fp)                           ; returns 51  - equals "3"
    +(read-byte fp)                           ; returns 52  - equals "4"
    +(read-byte fp)                           ; returns 10  - equals "\n"
    +(read-byte fp)                           ; returns NIL - empty
    +(close fp)
    +
    + +

    Common Lisp: The XLISP and Common Lisp 'read-byte' functions are +compatible for simple cases. They both allow for the optional 'source'. +However, in Common Lisp, there are additional parameters which occur right +after 'source'. So, when porting from Common Lisp to XLISP, remember there +are additional arguments in Common Lisp's 'read-byte' function.

    + +

    Common Lisp: Common Lisp specifies that 'read' operations with a +'source' of NIL will come from +*standard-input*. XLISP does not read the +input from *standard-input* with a +'source' of NIL. Common Lisp also +specifies that a 'source' of  T  +will read from *terminal-io* which is not defined in XLISP by default. XLISP +does not allow  T  as a valid +argument for 'source'.

    + +

    See the +read-byte +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/read-char.htm b/docsrc/xlisp/xlisp-doc/reference/read-char.htm new file mode 100644 index 0000000..476763b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/read-char.htm @@ -0,0 +1,100 @@ +XLISP read-char + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    read-char

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (read-char [source])
    +
    source - an optional source, must be a file pointer or stream, +default is *standard-input*
    +returns - the character
    +
    + +

    Description

    + +

    The 'read-char' function reads a single character from the specified +'source'. The character read is returned as a single character value for +the result. The 'source' may be a file pointer or a stream. If there is no +'source', *standard-input* is the default. +If an end-of-file is encountered in the 'source', then +NIL will be returned as the result.

    + +

    Examples

    + +
    +(setq fp (open "f" :direction :output))  ; set up file
    +(print 12.34 fp)
    +(close fp)
    +
    +(setq fp (open "f" :direction :input))   ; now read the file
    +(read-char fp)                           ; returns #\1
    +(read-char fp)                           ; returns #\2
    +(read-char fp)                           ; returns #\.
    +(read-char fp)                           ; returns #\3
    +(read-char fp)                           ; returns #\4
    +(read-char fp)                           ; returns #\Newline
    +(read-char fp)                           ; returns NIL - empty
    +(close fp)
    +
    + +

    Common Lisp: The XLISP and Common Lisp 'read-char' functions are +compatible for simple cases. They both allow for the optional 'source'. +However, in Common Lisp, there are addition parameters which occur right +after 'source'. So, when porting from Common Lisp to XLISP, remember there +are additional arguments in Common Lisp's 'read-char' function.

    + +

    Common Lisp: Common Lisp specifies that 'read' operations with a +'source' of NIL will come from +*standard-input*. XLISP does not read the +input from *standard-input* with a +'source' of NIL. Common Lisp also +specifies that a 'source' of  T  +will read from *terminal-io* which is not defined in XLISP by default. XLISP +does not allow  T  as a valid +argument for 'source'.

    + +

    See the +read-char +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/read-float.htm b/docsrc/xlisp/xlisp-doc/reference/read-float.htm new file mode 100644 index 0000000..44b52e7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/read-float.htm @@ -0,0 +1,79 @@ +XLISP read-float + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    read-float

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (read-float [stream [length]])
    +
    stream - the input stream (default is standard input)
    +length - the length of the float in bytes [default is 4, +legal values are -4, -8, 4, and 8]
    +returns - the float
    +
    + +

    Description

    + +

    The 'read-float' function reads a binary floating point +number from an input stream, created by the +open-binary function.

    + +

    Note: Integers and floats are assumed to be +big-endian [high-order byte first] and signed, +regardless of the platform. To read little-endian +format, use a negative number for the length, e.g. '-4' indicates a +4-bytes, low-order byte first. The file should be +opened in binary mode.

    + +

    Examples

    + +
    +
    +
    + +

    See also read-int, +write-int, +write-float, +bigendianp, +open-binary.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/read-int.htm b/docsrc/xlisp/xlisp-doc/reference/read-int.htm new file mode 100644 index 0000000..15aa9d5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/read-int.htm @@ -0,0 +1,78 @@ +XLISP read-int + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    read-int

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (read-int [stream [length]])
    +
    stream - the input stream [default is standard input]
    +length - the length of the integer in bytes [default is 4]
    +returns - the integer
    +
    + +

    Description

    + +

    The 'read-int' function reads an integer from a binary input +stream, created by the +open-binary function.

    + +

    Note: Integers and floats are assumed to be +big-endian [high-order byte first] and signed, +regardless of the platform. To read little-endian +format, use a negative number for the length, e.g. '-4' indicates a +4-bytes, low-order byte first. The file should be +opened in binary mode.

    + +

    Examples

    + +
    +
    +
    + +

    See also write-int, +read-float, +write-float, +bigendianp, +open-binary.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/read-line.htm b/docsrc/xlisp/xlisp-doc/reference/read-line.htm new file mode 100644 index 0000000..e6860d4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/read-line.htm @@ -0,0 +1,97 @@ +XLISP read-line + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    read-line

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (read-line [source])
    +
    source - an optional source, must be a file pointer or stream, +default is *standard-input*
    +returns - the line as a string
    +
    + +

    Description

    + +

    The 'read-line' function reads a single line from the specified 'source'. +The line read is returned as a string value for the result. The 'source' may +be a file pointer or a stream. If there is no 'source', +*standard-input* is the default. If an +end-of-file is encountered in the 'source', then +NIL will be returned as the result.

    + +

    Examples

    + +
    +(setq fp (open "f" :direction :output))  ; set up file
    +(print "fe fi" fp)
    +(print 12.34 fp)
    +(close fp)
    +
    +(setq fp (open "f" :direction :input))   ; now read the file
    +(read-line fp)                           ; returns ""fe fi""    
    +(read-line fp)                           ; returns "12.34"
    +(read-line fp)                           ; returns NIL
    +(close fp)
    +
    + +

    Common Lisp: The XLISP and Common Lisp 'read-line' functions are +compatible for simple cases. They both allow for the optional 'source'. +However, in Common Lisp, there are additional parameters which occur right +after 'source'. So, when porting from Common Lisp to XLISP, remember there +are additional arguments in Common Lisp's 'read-line' function.

    + +

    Common Lisp: Common Lisp specifies that 'read' operations with a +'source' of NIL will come from +*standard-input*. XLISP does not read the +input from *standard-input* with a +'source' of NIL. Common Lisp also +specifies that a 'source' of  T  +will read from *terminal-io* which is not defined in XLISP by default. XLISP +does not allow  T  as a valid +argument for 'source'.

    + +

    See the +read-line +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/read.htm b/docsrc/xlisp/xlisp-doc/reference/read.htm new file mode 100644 index 0000000..7e7e339 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/read.htm @@ -0,0 +1,125 @@ +XLISP read + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    read

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c, xlread.c

    + +

    Syntax

    + +
    +
    (read [source [eof-result [recursive-flag]]])
    +
    source - an optional source, must be a file pointer or stream, the +default is *standard-input*
    +eof-result - an optional expression, default is +NIL
    +recursive-flag - an optional expression, +NIL or +non-NIL
    +returns - the expression read
    +
    + +

    Description

    + +

    The 'read' function reads an expression from the specified 'source'. The +expression read is a normal XLISP expression, not necessarily a line. This +means that white space is removed, where 'white space' is blanks, empty +lines and comment lines. Read-macro expansions will occur. The expression +needs to be an atom [numeric, string or symbol] or a valid list. It can span +several lines. The expression read is returned as the result. The 'source' +may be a file pointer or a stream. If there is no 'source', +*standard-input* is the default. If an +end-of-file is encountered in the 'source', then the 'eof-result' value will +be returned as the result.

    + +

    If you wish to read just lines or characters, refer to the +read-line or +read-char functions.

    + +

    The 'recursive-flag' is intended for use with embedded calls to 'read'. +This is useful in read-macro and read-table uses. If 'recursive-flag' is +non-NIL , 'read' does not +expect itself to be at a 'top-level', but recursively executing within +another 'read' that is in progress.

    + +

    Examples

    + +
    +(setq fp (open "f" :direction :output))  ; set up file
    +(print "hello" fp)                       ; and fill it with stuff
    +(print 12.34 fp)
    +(princ "'(a b" fp) (terpri fp)
    +(princ "; comment" fp) (terpri fp)
    +(princ " c d)" fp )
    +(close fp)
    +
    +(setq fp (open "f" :direction :input))   ; now read the file
    +(read fp "done")                         ; returns "hello"
    +(read fp "done")                         ; returns 12.34
    +(read fp "done")                         ; returns (QUOTE (A B C D))
    +                                         ;   note the macro expansion of QUOTE
    +                                         ;   note that "; comment" is gone
    +(read fp "done")                         ; returns "done"
    +(close fp)
    +
    + +

    Common Lisp: The XLISP and Common Lisp 'read' functions are +similar. They both allow for 'source', 'eof-result' and 'recursive-flag'. +However, in Common LISP, there is an additional end-of-file error parameter. +This parameter occurs right after 'source' and specifies whether or not to +flag an error on end-of-file. So, when porting, remember there is one +additional argument in Common Lisp's 'read' function. You need to be +concerned about this if you use more than just a 'source' argument, going +either from XLISP to Common LISP or vice versa.

    + +

    Common Lisp: Common Lisp specifies that 'read' operations with a +'source' of NIL will come from +*standard-input*. XLISP does not read the +input from *standard-input* with a +'source' of NIL. Common Lisp also +specifies that a 'source' of  T  +will read from *terminal-io* which is not defined in XLISP by default. XLISP +does not allow  T  as a valid +argument for 'source'.

    + +

    See the +read +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/real-random.htm b/docsrc/xlisp/xlisp-doc/reference/real-random.htm new file mode 100644 index 0000000..d3438a8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/real-random.htm @@ -0,0 +1,82 @@ +XLISP real-random + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    real-random

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  misc.lsp

    + +

    Syntax

    + +

    + +
    +
    (real-random from to)
    +
    from, to - the limits as integer or floating point numbers
    +returns - a random floating point number between from and to
    +
    + +

    + +

    In Nyquist, 'real-random' is implemented as a Lisp +function:

    + +
    +(defun real-random (from to)
    +  (+ (* (rrandom) (- to from)) from))
    +
    + +

    Description

    + +

    The 'real-random' function returns a random floating point +number between 'from' and 'to'. See also rrandom, which is equivalent to: + +

    +(real-random 0 1))
    +
    + +

    Examples

    + +
    +
    +
    + +

    See also rrandom.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/reference-copyright.htm b/docsrc/xlisp/xlisp-doc/reference/reference-copyright.htm new file mode 100644 index 0000000..854f384 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/reference-copyright.htm @@ -0,0 +1,50 @@ +Copyright + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Copyright

    + +
    + +

    This XLISP language reference is a re-work of a 'XLISPREF.DOC' document +with the following copyright:

    + +

    XLISP 2.0 Language Reference by Tim I Mikkelsen - December 11, 1989

    + +
    +

    Copyright (c) 1989 by Tim I. Mikkelsen. All Rights Reserved. No part of this +document may be copied, reproduced or translated for commercial use without +prior written consent of the author. Permission is granted for non-commercial +use as long as this notice is left intact.

    + +

    This document is intended to serve as a reference for the XLISP 2.0 dialect +of LISP. It includes a description of each symbol, function, special form and +keyword available in XLISP. This reference is not a complete and extensive +introduction to LISP programming.

    + +

    If you find problems with the reference or find that I have left something +out, drop me a line. If you find this useful, I would be interested in hearing +that as well. If you are into 'pretty' looking documents (as opposed to plain +ASCII text), I have a TeX version of the reference.

    +
    + +

    Tim Mikkelsen, 4316 Picadilly Drive, Fort Collins, Colorado 80526

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + + diff --git a/docsrc/xlisp/xlisp-doc/reference/reference-format.htm b/docsrc/xlisp/xlisp-doc/reference/reference-format.htm new file mode 100644 index 0000000..140d2c0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/reference-format.htm @@ -0,0 +1,83 @@ +Entry Format + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Entry Format

    + +
    + +

    Each entry is a symbol of some variety that the XLISP system will +recognize. The parts of each reference entry include:

    + +
      + +
    1. The Headline of the page gives the name or symbol of the +entry.

    2. + +
    3. The Reference section below the headline gives infomations in +the following order:

    4. + +
        + +
      • Type may be one of the following:

      • + +
          +
        • function (subr)
        • +
        • predicate function (subr)
        • +
        • special form (fsubr)
        • +
        • reader expansion
        • +
        • system variable
        • +
        • system constant
        • +
        • keyword
        • +
        • object
        • +
        • message selector
        • +
        + +
      • Source specifies the source file where the routine or code +associated with the entry resides. [Please not that I have copied the +source file locations out of the Tim I Mikkelsen manual without checking, +so some of them may be wrong.]

      • + +
      + +
    5. Syntax defines the syntax or usage of the entry. It is also +used to specify the arguments. Items written in italics are +arguments. Items enclosed between square brackets like '[' and ']' are +optional entries. Items that have '...' [ellipses] indicate that there can +be one or many of the item. Items enclosed between '{' and '}' which are +separated by '|' indicate that one of the items should be included.

    6. + +
    7. Description defines the entry, necessary conditions, results, +defaults, etc.

    8. + +
    9. Examples shows example uses of the entry.

    10. + +
    11. The Comments section after the examples includes additional +information such as compatibility notes, bugs, usage notes, potential +problems, keystroke equivalences, etc.

    12. + +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/reference-index.htm b/docsrc/xlisp/xlisp-doc/reference/reference-index.htm new file mode 100644 index 0000000..a50ea90 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/reference-index.htm @@ -0,0 +1,2468 @@ +Language Reference + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Nyquist / XLISP 2.0 Language Reference

    + +
    + +

      + #  | + a  | + b  | + c  | + d  | + e  | + f  | + g  | + h  | + i  | + k  | + l  | + m  | + n  | + o  | + p  | + q  | + r  | + s  | + t  | + u  | + v  | + w  | + z  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     *   - variable + - most recent result
     **   - variable + - second recent result
     ***   - variable + - third recent result
     +   - variable + - most recent input expression
     ++   - variable + - second recent input expression
     +++   - variable + - third recent input expression
     −   - variable + - the expression currently being evaluated
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     +   - function + - add one or several numbers
     −   - function + - negate one number or subtract several numbers
     *   - function + - multiply one or several numbers
     /   - function + - divide one or several numbers
     <   - function + - test if numbers are monotonically increasing
     <=   - function + - test if numbers are monotonically non-decreasing
     =   - function + - test numbers for equality
     /=   - function + - test numbers for non-equality
     >   - function + - test if numbers are monotonically decreasing
     >=   - function + - test if numbers are monotonically non-increasing
     1+   - function + - increment a number by one
     1−   - function + - decrement a number by one
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    abs  - function + - compute the absolute value of a number
    acos  - function + - compute the arccosine of a floating point number
    address-of  - function + - get the address of an xlisp node
    alloc  - function + - change the number of nodes to allocate in each segment
    alphanumericp  - function + - is this an alphabetic or a digit character?
    and  - special form + - the logical 'and' of an arbitrary number of expressions
    :answer  - message selector + - add a message to a class
    append  - function + - append lists
    apply  - function + - apply a function to a list of arguments
    *applyhook*  - system variable + - returns NIL [hook not implemented]
    aref  - function + - array accessor for the nth element of an array
    arrayp  - predicate function + - is this an array?
    asin  - function + - compute the arcsine of a floating point number
    assoc  - function + - find an expression in an association list
    atan  - function + - compute the arctangent of a floating point number
    atom  - predicate function + - is this an atom?
    &aux  - keyword + - define auxiliary variables
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    backquote  - special form + - fill in a template
    baktrace  - function + - print n levels of trace back information
    bigendianp  - function + - is this a bigendian machine?
    block  - special form + - define a named block
    both-case-p  - predicate function + - is this an uppercase or lowercase alphabetic character?
    boundp  - predicate function + - is a variable value bound to this symbol in the *obarray*?
    break  - function + - enter a Break Loop
    *breakenable*  - system variable + - define if the Break Loop shall be entered on errors
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    car  - function + - list accessor for the first element of a list
    caar cadr  - function + - list accessors for a sequence of car and + cdr operations
    caaar...caddr  - function + - list accessors for a sequence of car and + cdr operations
    caaaar...cadddr  - function + - list accessors for a sequence of car and + cdr operations
    case  - special form + - select by case
    catch  - special form + - evaluate expressions and catch throws
    cdr  - function + - list accessor for the tail of a list with the + first element removed
    cdar cddr  - function + - list accessors for a sequence of car and + cdr operations
    cdaar...cdddr  - function + - list accessors for a sequence of car and + cdr operations
    cdaaar...cddddr  - function + - list accessors for a sequence of car and + cdr operations
    cerror  - function + - signal a correctable error
    char  - function + - extract a character from a string
    char/=  - function + - test if characters are not equal, case is significant
    char<  - function + - test if characters are monotonically increasing, case is significant
    char<=  - function + - test if characters are monotonically non-decreasing, case is significant
    char=  - function + - test if characters are equivalent, case is significant
    char>  - function + - test if characters are monotonically decreasing, case is significant
    char>=  - function + - test if characters are monotonically non-increasing, case is significant
    characterp  - predicate function + - is this a character?
    char-code  - function + - get the ASCII code of a character
    char-downcase  - function + - convert a character to lower case
    char-equal  - function + - test if characters are equivalent, case is not significant
    char-greaterp  - predicate function + - test if characters are monotonically decreasing, case is not significant
    char-int  - function + - convert a character to an integer
    char-lessp  - predicate function + - test if characters are monotonically increasing, case is not significant
    char-not-equal  - function + - test if characters are different values, case is not significant
    char-not-greaterp  - predicate function + - test if characters are monotonically non-decreasing, case is not significant
    char-not-lessp  - predicate function + - test if characters are monotonically non-increasing, case is not significant
    char-upcase  - function + - convert a character to upper case
    class  - object + - the built-in object class
    :class  - message selector + - return the class of an object
    clean-up  - function + - clean-up after an error
    close  - function + - close a file stream
    code-char  - function + - get the character with a specified ASCII code
    comma  - reader expansion + - comma evaluates expressions in a backquote form
    comma-at  - reader expansion + - splices a list into a expression in a backquote form
    cond  - special form + - evaluate conditionally
    cons  - function + - construct a new list node
    consp  - predicate function + - is this a non-empty list?
    :constituent  - keyword + - readtable entry to specify a character to be used as is
    continue  - function + - continue from a correctable error
    cos  - function + - compute the cosine of a floating point number
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    *debug-io*  - system variable + - file pointer for debug input and output
    decf  - macro + - decrement a variable
    defmacro  - special form + - define a Lisp macro
    defun  - special form + - define a Lisp function
    delete  - function + - delete elements from a list
    delete-if  - function + - delete elements from a list that pass a test
    delete-if-not  - function + - delete elements from a list that fail a test
    digit-char  - function + - convert a decimal digit to a character
    digit-char-p  - predicate function + - convert a character to a decimal digit, if possible
    do  - special form + - loop with local 'let' bindings
    do*  - special form + - loop with local 'let*' bindings
    dolist  - special form + - loop through a list
    dotimes  - special form + - loop a given number of times
    dribble  - function + - create a file with a transcript of a Nyquist/ XLISP session
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    echoenabled  - function + - turn the console input echo on or off
    endp  - predicate function + - is this the end of a list?
    eq  - predicate function + - equality test comparing memory pointers, may fail on numbers
    eql  - predicate function + - same as 'eq', but works with all symbols and numbers
    equal  - predicate function + - equality test by comparing printed values
    error  - function + - signal a non-correctable error
    *error-output*  - system variable + - file pointer for error input and output
    errset  - special form + - trapping errors
    eval  - function + - evaluate a Lisp expression
    evalhook  - function + - evaluate with hooks
    *evalhook*  - system variable + - user substitute for the evaluator function
    evenp  - predicate function + - is this integer even?
    exit  - function + - exit XLISP
    exp  - function + - compute 'e' to the 'x' power
    expand  - function + - expand memory by adding segments
    expt  - function + - compute 'x' to the 'y' power
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    fboundp  - predicate function + - is a function value bound to this symbol in the *obarray*??
    filep  - function + - is this a file?
    find-in-xlisp-path  - function + - searches the XLISP path for a filename
    *file-separator*  - variable + - the operating system's file separator character
    first  - function + - list accessor for the first element of a list
    flatc  - function + - length of printed representation using princ
    flatsize  - function + - length of printed representation using prin1
    flet  - special form + - define local Lisp functions
    float  - function + - convert an integer to a floating point number
    *float-format*  - system variable + - format for printing floating point numbers
    floatp  - predicate function + - is this number a floating point number?
    format  - function + - do formatted output
    fourth  - function + - list accessor for the fourth element of a list
    funcall  - function + - call a function with arguments
    function  - special form + - get the functional value of a symbol or lambda expression
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    gc  - function + - call the garbage collector
    gcd  - function + - compute the greatest common divisor
    *gc-flag*  - system variable + - controls the printing of 'gc' messages
    *gc-hook*  - system variable + - function to call after garbage collection
    gensym  - function + - generate an unique Lisp symbol
    get  - function + - list accessor for property lists
    get-env  - function + - get the value of an environment variable
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    get-key  - function + - get a single key stroke from the keyboard
    get-lambda-expression  - function + - get the Lisp code of a lambda or macro expression as a list
    get-output-stream-list  - function + - empty a stream and return it's data as a list
    get-output-stream-string  - function + - empty a stream and return it's data as a single string
    get-temp-path  - function + - get a path where a temporary file can be created
    +
    get-user  - function + - get the current user name
    go  - special form + - go to a tag within a 'tagbody' or 'prog'
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + +
    hash  - function + - compute the hash index for a symbol
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     if   - special form + - evaluate expressions conditionally
    incf  - macro + - increment a variable
    info  - function + - show information about memory usage
    int-char  - function + - convert an integer to a character
    *integer-format*  - system variable + - format for printing integer numbers
    integerp  - predicate function + - is this number an integer?
    intern  - function + - create a new interned symbol
    interpolate  - function + - compute the 'y' coordinate value corresponding to 'x'
    intersection  - function + - compute the intersection of two lists
    :isa  - message selector + - test if object inherits from class
    :isnew  - message selector + - cause an instance to run its initialization method
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + +
    keywordp  - function + - is this a keyword?
    &key  - lambda list keyword + - define keyword arguments
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    labels  - special form + - define local Lisp functions in a mutually recursive manner
    lambda  - special form + - define a unnamed function
    last  - function + - list accessor for the last element of a list
    length  - function + - returns the length of a list, vector or string
    let  - special form + - define local bindings, evaluated in no specific order
    let*  - special form + - define local bindings, evaluated in sequencial order
    list  - function + - create a list of values
    listdir  - function + - get a list of all filenames in a directory
    listp  - predicate function + - is this a list?
    load  - function + - load a source file
    log  - function + - the natural logarithm of a floating-point number
    logand  - function + - the bitwise 'and' of one or several numbers
    logior  - function + - the bitwise 'inclusive or' of one or several numbers
    lognot  - function + - the bitwise 'exclusive or' of one or several numbers
    logxor  - function + - the bitwise 'not' of a number
    loop  - special form + - basic looping form
    lower-case-p  - predicate function + - is this a lowercase character?
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    macroexpand  - function + - expand macro definitions recursively
    macroexpand-1  - function + - expand the first level of a macro definition
    macrolet  - special form + - define a local macro
    + + + + + + + + + + + + + + + + + + + + + +
    make-array  - function + - create an array of specified size
    make-string-input-stream  - function + - create an unnamed stream from a string expression
    make-string-output-stream  - function + - create and return an unnamed output stream
    make-symbol  - function + - create a temporary, uninterned symbol
    +
    mapc  - function + - apply a function to successive 'car's, return the first list of arguments
    mapcar  - function + - apply a function to successive 'car's, return a list of the values
    mapl  - function + - apply a function to successive 'cdr's, return the first list of arguments
    maplist  - function + - apply a function to successive 'cdr's, return a list of the values
    max  - function + - return the largest of one or several numbers
    member  - function + - test if an expression is contained in a list
    :mescape  - keyword + - readtable entry specifying a character to be used as a multiple escape character
    min  - function + - return the smallest of one or several numbers
    minusp  - predicate function + - is this number negative?
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    nconc  - function + - destructively concatenate lists
    :new  - message selector + - create a new instance of a class
    nil  - system constant + - representing the empty list as well as the false value
    :nmacro  - keyword + - readtable entry to specify a character to be used as the start of a non-terminating read macro
    not  - predicate function + - is this expression false?
    nstring-downcase  - function + - destructively convert a string or a part of it to lower case
    nstring-upcase  - function + - destructively convert a string or a part of it to upper case
    nth  - function + - list accessor for the nth element of a list
    nthcdr  - function + - list accessor for the nth tail of a list
    null  - predicate function + - is this an empty list?
    numberp  - predicate function + - is this a number?
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    *obarray*  - system variable + - the system symbol table
    object  - object + - the build-in object class
    objectp  - predicate function + - is this an object?
    oddp  - predicate function + - is this integer number odd?
    open  - function + - open a file for character or byte i/o
    open-binary  - function + - open a file for multi-byte i/o
    &optional  - lambda list keyword + - define optional arguments
    or  - special form + - the logical 'or' of an arbitrary number of expressions
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    peek  - function + - accessor for an internal computer memory value
    peek-char  - function + - look at a single character from a specified source
    pi  - variable + - floating point approximation of the number 'pi'
    plusp  - predicate function + - is this number positive?
    poke  - function + - write a value to the internal computer memory
    pop  - macro + - pop a value from a list
    power  - function + - compute 'x' raised to the 'y' power
    pprint  - function + - print a pretty looking version of an expression
    prin1  - function + - print an expression without a newline
    princ  - function + - print an expression without quoting and without a newline
    print  - function + - print an expression on a new line
    *print-case*  - system variable + - specifies how symbols are printed
    profile  - function + - turn profiling on or off
    prog  - special form + - a 'block' with local 'let' bindings
    prog*  - special form + - a 'block' with local 'let*' bindings
    prog1  - special form + - a 'block' returning the value of the first expression
    prog2  - special form + - a 'block' returning the value of the second expression
    progn  - special form + - a 'block' returning the value of the last expression
    progv  - special form + - a 'block' with local bindings, created out of two lists
    psetq  - special form + - perform 'setq' assignments in parallel
    push  - macro + - push a value to the front of a list
    putprop  - function + - put a property onto a symbol's property list
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + +
    quit  - function + - quit XLISP
    quote  - special form + - return an expression unevaluated
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    random  - function + - compute an integer random number between 0 and n-1 inclusive
    read  - function + - read a Lisp expression
    read-byte  - function + - read a byte from a stream
    read-char  - function + - read a character from a stream
    read-float  - function + - read a binary floating point number from a stream
    read-int  - function + - read a binary integer number from a stream
    read-line  - function + - read a line from a stream, returned as a string
    *readtable*  - system variable + - contains data structures relating to the processing of characters
    real-random  - function + - compute a floating point random number in an arbitrary range
    rem  - function + - compute the remainder of one or several numbers
    remove  - function + - remove elements from a list
    remove-if  - function + - remove elements from a list that pass a test
    remove-if-not  - function + - remove elements from a list that fail a test
    remprop  - function + - remove a property from a symbol's property list
    rest  - function + - list accessor for the tail of a list, identical to 'cdr'
    &rest  - lambda list keyword + - define 'rest' arguments, to be collected in a list
    restore  - function + - restore a XLISP workspace from a file
    return  - special form + - return from a 'block' construct
    return-from  - special form + - return from a named block
    reverse  - function + - reverse a list
    room  - function + - show memory allocation statistics
    round  - function + - round a number to the next integer value
    rplaca  - function + - replace the first element of a list
    rplacd  - function + - replace the tail of a list
    rrandom  - function + - compute a random floating point number between 0 and 1 inclusive
    *rslt*  - system variable + - used to store multiple return values
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    save  - function + - save a XLISP workspace to a file
    second  - function + - list accessor for the second element of a list
    self  - symbol + - evaluates to the current object when used within a message context
    send  - function + - send a message to an object
    send-super  - function + - send a message to the superclass of an object
    :sescape  - keyword + - readtable entry specifying a character to be used as a single escape character
    set  - function + - set the value of a symbol
    set-difference  - function + - compute the set-difference of two lists
    setdir  - function + - set a new working directory
    setf  - special form + - set the value of a place
    setq  - special form + - set the value of a quoted symbol
    setup-console  - function + - set default console attributes
    :show  - message selector + - show an object's instance variables
    sin  - function + - compute the sine of a floating point number
    sort  - function + - destructively sort a list
    soundp  - function + - is this a sound?
    sqrt  - function + - compute the square root of a floating point number
    *standard-input*  - system variable + - file pointer for standard input
    *standard-output*  - system variable + - file pointer for standard output
    strcat  - function + - concatenate strings
    streamp  - predicate function + - is this a stream?
    string  - function + - make a string from a symbol, character or string
    string/=  - function + - test if string1 is not equal to string2, case is significant
    string<  - function + - test if string1 is less than string2, case is significant
    string<=  - function + - test if string1 is less than or equal to string2, case is significant
    string=  - function + - test if the string arguments have the same values, case is significant
    string>  - function + - test if string1 is greater than string2, case is significant
    string>=  - function + - test if string1 is greater than or equal to string2, case is significant
    stringp  - predicate function + - is this a string?
    string-downcase  - function + - convert a string to lower case
    string-equal  - function + - test if string1 equal to string2, case is not significant
    string-greaterp  - predicate function + - test if string1 is greater than string2, case is not significant
    string-left-trim  - function + - trim the left end of a string
    string-lessp  - predicate function + - test if string1 is less than string2, case is not significant
    string-not-equal  - function + - test if string1 is not equal to string2, case is not significant
    string-not-greaterp  - predicate function + - test if string1 is less than or equal to string2, case is not significant
    string-not-lessp  - predicate function + - test if string1 is greater than or equal to string2, case is not significant
    string-right-trim  - function + - trim the right end of a string
    string-search  - function + - search for a pattern in a string
    string-trim  - function + - trim both ends of a string
    string-upcase  - function + - convert a string to upper case
    sublis  - function + - substitute expressions by using an association list
    subseq  - function + - extract a substring
    subsetp  - function + - test if a list is a subset of another list
    subst  - function + - substitute expressions
    symbol-function  - function + - get the functional value of a symbol
    symbol-name  - function + - get the print name of a symbol
    symbol-plist  - function + - get the property list of a symbol
    symbol-value  - function + - get the value of a symbol
    symbolp  - predicate function + - is this a symbol?
    system  - function + - execute a command of the operating system
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     t   - system constant + - represents 'true'
    tagbody  - special form + - a 'block' form with labels
    tan  - function + - compute the tangent of a floating point number
    terpri  - function + - terminate printing, prints a newline character
    third  - function + - list accessor for the third element of a list
    throw  - special form + - throw to a 'catch', allows non-local exits and traps
    :tmacro  - keyword + - readtable entry to specify a character to be used as the start of a terminating read macro
    top-level  - function + - clean-up after an error and return to the top level
    trace  - function + - add a function to the trace list
    *tracelimit*  - system variable + - the number of forms printed on entry to the Break Loop
    *tracelist*  - system variable + - a list of the current functions being traced
    *tracenable*  - system variable + - controls whether or not the Break Loop prints any back trace information on entry
    *trace-output*  - system variable + - file pointer for trace output
    truncate  - function + - truncates a number to an integer
    type-of  - function + - compute the type of a Lisp expression
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    *unbound*  - system constant + - used to indicate when a symbol has no value
    union  - function + - compute the union of two lists
    unless  - special form + - evaluate only when a condition is false
    untrace  - function + - remove a function from the trace list
    unwind-protect  - special form + - allows the trapping of all forms of exit from a protected form
    upper-case-p  - predicate function + - is this an uppercase character?
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + +
    vector  - function + - create an initialized vector [one-dimensional array]
     [ + Back to Top ] +       
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    when  - special form + - evaluate only when a condition is true
    while  - macro + - loop while a condition is met
    :white-space  - keyword + - readtable entry to specifying a character that may be skipped over
    write-byte  - function + - write a byte to a stream
    write-char  - function + - write a character to a stream
    write-float  - function + - write a binary floating point number to a stream
    write-int  - function + - write a binary integer number to a stream
     [ + Back to Top ] +       
    zerop  - predicate function + - is this number zero?
    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/reference.css b/docsrc/xlisp/xlisp-doc/reference/reference.css new file mode 100644 index 0000000..964dca2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/reference.css @@ -0,0 +1,34 @@ +.example { + color: #000000; + background-color: #F5F5F5; + padding: 8px; + border: #808080; + border-style: solid; + border-width: 1px; + width:auto; +} + +.button { + color: #000000; + background-color: #F5F5F5; + padding-top: 1px; + padding-bottom: 1px; + padding-left: 4px; + padding-right: 8px; + border: #808080; + border-style: solid; + border-width: 1px; + white-space: pre; +} + +.box { + color: #000000; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 16px; + padding-right: 16px; + border: #808080; + border-style: solid; + border-width: 1px; +} + diff --git a/docsrc/xlisp/xlisp-doc/reference/rem.htm b/docsrc/xlisp/xlisp-doc/reference/rem.htm new file mode 100644 index 0000000..e17717c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/rem.htm @@ -0,0 +1,88 @@ +XLISP rem + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    rem

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (rem expr1 ... )
    +
    exprN - integer number or expression
    +returns - the result of the remainder operation
    +
    + +

    Description

    + +

    The 'rem' function takes the first pair of expressions and determines +what is the remainder from dividing the first by the second expression. If +there are no other arguments, this value is returned. If there are +additional arguments, the remainder of the first pair is applied to the next +and then the next and so on. In other words:

    + +
    +(REM A B C D)
    +
    + +

    is equivalent to:

    + +
    +(REM (REM (REM A B) C) D)
    +
    + +

    Examples

    + +
    +(rem 1)        ; returns 1
    +(rem 1 2)      ; returns 1
    +(rem 13 8)     ; returns 5
    +(rem 13 8 3)   ; returns 2
    +(rem 13.5 8)   ; error: bad floating point operation
    +
    + +

    Common Lisp: Common Lisp only allows two arguments. XLISP supports +an arbitrary number of arguments. Also, Common Lisp allows for floating +point expressions where XLISP does not support this.

    + +

    See the +rem +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/remove-if-not.htm b/docsrc/xlisp/xlisp-doc/reference/remove-if-not.htm new file mode 100644 index 0000000..cffc53e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/remove-if-not.htm @@ -0,0 +1,80 @@ +XLISP remove-if-not + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    remove-if-not

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (remove-if-not test list-expr)
    +
    test - the test function to be performed
    +list-expr - the list to remove from
    +returns - a copy of list-expr with non-matching elements removed
    +
    + +

    Description

    + +

    The 'remove-if-not' function searches through 'list-expr' and removes any +elements that fail the 'test'. Note that this operation is non-destructive, +it does not modify or affect 'list-expr' directly, it creates a modified +copy.

    + +

    Examples

    + +
    +(setq mylist '(1 2 3 4 5 6 7 8))   ; set up a list
    +(remove-if-not 'oddp mylist)       ; returns (1 3 5 7)
    +(remove-if-not 'evenp mylist)      ; returns (2 4 6 8)
    +(print mylist)                     ; prints (1 2 3 4 5 6 7 8)
    +                                   ;   note that MYLIST is not affected
    +
    +(setq mylist '(a nil b nil c))     ; set up a list
    +(remove-if-not 'null mylist)       ; returns (NIL NIL)
    +
    + +

    Common Lisp: XLISP does not support the ':from-end', ':start', +':end', ':count' and ':key' keywords which Common Lisp does.

    + +

    See the +remove-if-not +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/remove-if.htm b/docsrc/xlisp/xlisp-doc/reference/remove-if.htm new file mode 100644 index 0000000..0bcbfdb --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/remove-if.htm @@ -0,0 +1,80 @@ +XLISP remove-if + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    remove-if

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (remove-if test list-expr)
    +
    test - the test function to be performed
    +list-expr - the list to remove from
    +returns - copy of list with matching elements removed
    +
    + +

    Description

    + +

    The 'remove-if' function searches through 'list-expr' and removes any +elements that pass the 'test'. Note that this operation is non-destructive, +it does not modify or affect 'list-expr' directly, it creates a modified +copy.

    + +

    Examples

    + +
    +(setq mylist '(1 2 3 4 5 6 7 8))   ; set up a list
    +(remove-if 'oddp mylist)           ; returns (2 4 6 8)
    +(remove-if 'evenp mylist)          ; returns (1 3 5 7)
    +(print mylist)                     ; prints (1 2 3 4 5 6 7 8)
    +                                   ;   note that MYLIST is not affected
    +
    +(setq mylist '(a nil b nil c))     ; set up a list
    +(remove-if 'null mylist)           ; returns (A B C)
    +
    + +

    Common Lisp: XLISP does not support the ':from-end', ':start', +':end', ':count' and ':key' keywords which Common Lisp does.

    + +

    See the +remove-if +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/remove.htm b/docsrc/xlisp/xlisp-doc/reference/remove.htm new file mode 100644 index 0000000..e9108e5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/remove.htm @@ -0,0 +1,100 @@ +XLISP remove + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    remove

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (remove expr list-expr [{:test | :test-not} test])
    +
    expr - the expression to remove, an atom or list
    +list-expr - the list to remove from
    +test - optional test function, default is +eql
    +returns - a copy of list-expr with matching expressions removed
    +
    + +

    Description

    + +

    The 'remove' function searches through 'list-expr' for 'expr'. If 'expr' +is found, 'remove' returns the list with the 'expr' deleted. All occurances +of 'expr' are deleted. If 'expr' is not found, then the 'list-expr' is +returned unaltered. You may specify your own test with the ':test' and +':test-not' keywords followed by the test you which to perform. Note that +this operation is non-destructive, it does not modify or affect 'list-expr' +directly, it creates a modified copy.

    + +

    Examples

    + +
    +(setq mylist '(a b c d it e f))       ; set up a list
    +(remove 'it mylist)                   ; returns (A B C D E F)
    +(print mylist)                        ; prints (A B C D IT E F)
    +                                      ;   note that MYLIST is not affected
    +
    +(setq mylist '(a b c b d b))          ; change list to include duplicates
    +(remove 'b mylist)                    ; returns (A C D)
    +
    +(setq alist '( (a) (b) (it) (c)))     ; set up another list
    +(remove '(it) alist)                  ; returns ((A) (B) (IT) (C))
    +                                      ;   the EQ test doesn't work for lists
    +(remove '(it) alist :test 'equal)     ; returns ((A) (B) (C))
    +
    +(setq slist '( "a" "b" "it" "c"))     ; set up yet another list
    +(remove "it" slist)                   ; returns ("a" "b" "c")
    +(remove "it" slist :test-not 'equal)  ; returns ("it")
    +                                      ;   REMOVE takes away everything but IT
    +
    + +

    Note: The 'remove' function can work with a list or string as the +'expr'. However, the default eql test does +not work with lists or strings, only symbols and numbers. To make this work, +you need to use the ':test' keyword along with +equal for 'test'.

    + +

    Common Lisp: XLISP does not support the ':from-end', ':start', +':end', ':count' and ':key' keywords which Common Lisp does.

    + +

    See the +remove +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/remprop.htm b/docsrc/xlisp/xlisp-doc/reference/remprop.htm new file mode 100644 index 0000000..8b98b92 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/remprop.htm @@ -0,0 +1,94 @@ +XLISP remprop + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    remprop

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (remprop symbol property)
    +
    symbol - the symbol with a property list
    +property - the property name being removed
    +returns - the property value
    +
    + +

    Description

    + +

    The 'remprop' function removes the 'property' from the 'symbol'. The +function returns a NIL. If the 'property' +does not exist, there is no error generated. The 'symbol' must be an +existing symbol. Property lists are lists attached to any user defined +variables. The lists are in the form of:

    + +
    +(name1 val1 name2 val2 ... )
    +
    + +

    Any number of properties may be attached to a single variable.

    + +

    Examples

    + +
    +(setq person 'bobby)                 ; create a var with a value
    +(putprop person 'boogie 'last-name)  ; add a LAST-NAME property
    +(putprop person 'disc-jockey 'job)   ; add a JOB property
    +
    +(get person 'last-name)              ; retrieve LAST-NAME - boogie
    +(get person 'job)                    ; retrieve JOB - disc-jockey
    +(get person 'height)                 ; non-existant - returns NIL
    +
    +(remprop person 'job)                ; remove JOB
    +(remprop person 'height)             ; remove non-existant
    +
    + +

    Common Lisp: Common Lisp does not have a 'remprop' function. It +uses setf to achieve this functionality. +Porting from Common Lisp to XLISP will work fine since XLISP supports the +setf modifications of property lists and +the get function to retrieve property +values from symbol names. Porting from XLISP to Common LISP will require +translating 'remprop' into setf forms.

    + +

    See the +remprop +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/rest.htm b/docsrc/xlisp/xlisp-doc/reference/rest.htm new file mode 100644 index 0000000..1937471 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/rest.htm @@ -0,0 +1,80 @@ +XLISP rest + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    rest

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlinit.lsp

    + +

    Syntax

    + +
    +
    (rest expr)
    +
    expr - a list or list expression
    +returns - expr with the first element removed
    +
    + +

    Description

    + +

    The 'rest' function returns the remainder of a list or list expression +after first element of the list is removed. If the list is +NIL , +NIL is returned.

    + +

    Examples

    + +
    +(rest '(a b c))                         ; returns (B C)
    +(rest '((a b) c d))                     ; returns (C D)
    +(rest NIL)                              ; returns NIL
    +(rest 'a)                               ; error: bad argument type
    +(rest '(a))                             ; returns NIL
    +
    +(setq sisters '(virginia vicki cindy))  ; set up variable SISTERS
    +(first sisters)                         ; returns VIRGINIA
    +(rest sisters)                          ; returns (VICKI CINDY)
    +
    + +

    Note: The 'rest' function is set to the same code as the +cdr function.

    + +

    See the +rest +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/restore.htm b/docsrc/xlisp/xlisp-doc/reference/restore.htm new file mode 100644 index 0000000..577cfc1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/restore.htm @@ -0,0 +1,112 @@ +XLISP restore + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    restore

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xldmem.c, xlimage.c

    + +

    Syntax

    + +
    +
    (restore file)
    +
    file - a string or symbol for the name of the file
    +returns - NIL on failure, otherwise never +returns
    +
    + +

    Description

    + +

    The 'restore' function restores the previously +saved XLISP workspace [system state] from +the specified file. The 'file' may be a string or a symbol. If the 'file' +does not include a '.wks' suffix, it will be extended to be called +'file.wks'. If successful, 'restore' will print a message saying:

    + +
    +[ returning to the top level ]
    +
    + +

    and will not return any value. If 'restore' fails, it will return +NIL. There can be several saved workspaces. +These workspaces can be restored as often as desired.

    + +

    Examples

    + +
    +(setq myvar 5)       ; set MYVAR to value 5
    +myvar                ; returns 5
    +
    +(save 'farp)         ; save workspace in FARP.wks
    +
    +(setq myvar "garp")  ; change MYVAR to "garp"
    +myvar                ; returns "garp"
    +
    +(restore 'farp)      ; restore workspace
    +myvar                ; returns 5
    +
    + +

    File names: In the PC and DOS world, all file names and extensions +["foo.bat"] are automatically made uppercase. In using XLISP, this +means you don't have to worry about whether the name is "foo.bat", +"FOO.BAT" or even "FoO.bAt", they will all work. +However, in other file systems [UNIX in particular], uppercase and lowercase +do make a difference:

    + +

    This will create a file named FOO-FILE in UNIX, because XLISP uppercases +its symbols:

    + +
    +(open 'foo-file :direction :output)
    +
    + +

    This will create a file named 'foo-file' because UNIX doesn't +uppercase its file names:

    + +
    +(open "foo-file" :direction :output)
    +
    + +

    So, if you are having trouble with opening and accessing files, check to +make sure the file name is in the proper case.

    + +

    See the +restore +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/return-from.htm b/docsrc/xlisp/xlisp-doc/reference/return-from.htm new file mode 100644 index 0000000..ea00206 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/return-from.htm @@ -0,0 +1,89 @@ +XLISP return-from + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    return-from

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (return-from name [expr])
    +
    name - an unevaluated symbol for the block name
    +expr - an expression
    +returns - never returns
    +
    + +

    Description

    + +

    The 'return-from' special form allows the return of an arbitrary value at +arbitrary times within a 'named-block' +construct of the specified 'name'. The 'expr' will be returned by the +block construct. A +NIL will be returned by the block construct if there is no 'expr' +specified.

    + +

    If 'return-from' is used without being within a valid +block construct, an error is generated:

    + +
    +error: no target for RETURN
    +
    + +

    Examples

    + +
    +(block out                        ; outer BLOCK
    +  (print "outer")
    +  (block in                       ; inner BLOCK
    +    (print "inner")
    +    (return-from out "all done")
    +    (print "won't get here")))    ; prints "outer"
    +                                  ; prints "inner"
    +                                  ; returns "all done"
    +
    +(return-from nobody 9)            ; error: no target for RETURN
    +
    + +

    See the +return-from +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/return.htm b/docsrc/xlisp/xlisp-doc/reference/return.htm new file mode 100644 index 0000000..9e52426 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/return.htm @@ -0,0 +1,93 @@ +XLISP return + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    return

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (return [expr])
    +
    expr - an expression
    +returns - never returns
    +
    + +

    Description

    + +

    The 'return' special form allows the return of an arbitrary value at +arbitrary times within 'block' constructs like +do , +do* , +dolist , +dotimes , +loop , +prog and +prog*. The 'expr' will be returned by the +outer 'block' construct. A NIL will be +returned by the outer 'block' construct if there is no 'expr' specified.

    + +

    If 'return' is used without being within a valid 'block' construct, an +error is generated:

    + +
    +error: no target for RETURN
    +
    + +

    Examples

    + +
    +(prog (i)                              ; PROG form
    +  (print i) (RETURN "foo") (print j))  ; prints NIL  returns "foo"
    +
    +(dotimes (i 10)
    +  (if (eql i 5) (RETURN 20)
    +                (princ i)))            ; prints 01234  returns 20
    +
    +(prog1 (print "hi") (RETURN "foo"))    ; prints "hi"
    +                                       ; error: no target for RETURN
    +
    +(return 9)                             ; error: no target for RETURN
    +
    + +

    See the +return +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/reverse.htm b/docsrc/xlisp/xlisp-doc/reference/reverse.htm new file mode 100644 index 0000000..f7132cc --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/reverse.htm @@ -0,0 +1,73 @@ +XLISP reverse + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    reverse

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (reverse list-expr)
    +
    list-expr - a list or list expression
    +returns - a new list in the reverse order
    +
    + +

    Description

    + +

    The 'reverse' function reverses the 'list-expr'. The reversed list is the +returned value. The reversal process only occurs on the 'top-level' of the +'list-expr'. If there are nested sub-lists, these are left intact.

    + +

    Examples

    + +
    +(reverse NIL)                     ; returns NIL
    +(reverse 'a)                      ; error: bad argument type
    +(reverse '(a))                    ; returns (A)
    +(reverse '(a b c))                ; returns (C B A)
    +(reverse '((a b) (c d) (e f)))    ; returns ((E F) (C D) (A B))
    +(reverse (list (+ 1 2) (+ 3 4)))  ; returns (7 3)
    +
    + +

    See the +reverse +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/room.htm b/docsrc/xlisp/xlisp-doc/reference/room.htm new file mode 100644 index 0000000..79c5d78 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/room.htm @@ -0,0 +1,90 @@ +XLISP room + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    room

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xldmem.c

    + +

    Syntax

    + +
    +
    (room [info])
    +
    info - an optional, unused expression
    +returns - NIL
    +
    + +

    Description

    + +

    The 'room' function prints the current memory statistics to +*standard-output*. +NIL is always returned. The message shows +the statistics for:

    + +
      +
    • total nodes
    • +
    • current free nodes
    • +
    • current number of allocated memory segments
    • +
    • node size of the allocated memory segments
    • +
    • total memory in bytes
    • +
    • total number of garbage collections that have occured +since this session of XLISP started
    • +
    + +

    Examples

    + +
    +(room)    ; prints  Nodes:       4000
    +          ;         Free nodes:  1723
    +          ;         Segments:    4
    +          ;         Allocate:    1000
    +          ;         Total:       52566
    +          ;         Collections: 8
    +          ; returns NIL
    +
    + +

    Common Lisp: In Common LISP, the 'info' argument controls the +amount of information that is printed. In Common Lisp, the form of and +information provided by the 'room' output is implementation dependent. For +portability, you should not count on this information or form.

    + +

    See the +room +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/round.htm b/docsrc/xlisp/xlisp-doc/reference/round.htm new file mode 100644 index 0000000..11c84b1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/round.htm @@ -0,0 +1,81 @@ +XLISP round + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    round

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  fileio.lsp

    + +

    Syntax

    + +

    + +
    +
    (round number)
    +
    number - an integer or floating point numbers
    +returns - the number, rounded to the next integer value
    +
    + +

    + +

    In Nyquist, 'round' is implemented as a Lisp function:

    + +
    +(defun round (x) 
    +  (cond ((> x 0) (truncate (+ x 0.5)))
    +        ((= (- x 0.5) (truncate (- x 0.5))) (truncate x))
    +        (t (truncate (- x 0.5)))))
    +
    + +

    Description

    + +

    The 'round' function rounds a number to the next integer value. This is +tricky because truncate rounds toward zero as +does C in other words, rounding is down for positive numbers +and up for negative numbers. You can convert rounding up to +rounding down by subtracting one, but this fails on the integers, so we need +a special test if (- x 0.5) is an integer.

    + +

    Examples

    + +
    +(round .5)   => 1
    +(round -.5)  => 0
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/rplaca.htm b/docsrc/xlisp/xlisp-doc/reference/rplaca.htm new file mode 100644 index 0000000..3b6ca54 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/rplaca.htm @@ -0,0 +1,99 @@ +XLISP rplaca + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    rplaca

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (rplaca list expr)
    +
    list - the list to destructively modify
    +expr - the expression to replace car +of list
    +returns - the list node after updating the +car
    +
    + +

    Description

    + +

    The 'rplaca' function destructively modifies the +car of 'list' and replaces it with the +'expr'. The destructive aspect of this operation means that the actual +symbol value is used in the list-modifying operations, not a copy. 'list' +must evaluate to a valid list.

    + +

    An atom or NIL for 'list' will result in +an error:

    + +
    +error: bad argument type
    +
    + +

    Examples

    + +
    +(setq a '(1 2 3))           ; make A with value (1 2 3)
    +(setq b '(1 2 3))           ; make B with value (1 2 3)
    +(setq c a)                  ; make C point to A's value
    +(rplaca a 'new)             ; returns (NEW 2 3)
    +
    +(print a)                   ; prints (NEW 2 3)
    +                            ;   note that A is modified
    +
    +(print b)                   ; prints (1 2 3)
    +                            ;   note that B is not modified
    +
    +(print c)                   ; prints (NEW 2 3)
    +                            ;   note that C is modified too
    +
    +(setq a '(1 2 3))           ; reset A to value (1 2 3)
    +(rplaca a '(the sub list))  ; returns ((THE SUB LIST) 2 3)
    +(rplaca '(1 2 3) 'more)     ; returns (MORE 2 3)
    +
    +(rplaca 'a 'b)              ; error: bad argument type
    +(rplaca NIL 'b)             ; error: bad argument type
    +
    + +

    See the +rplaca +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/rplacd.htm b/docsrc/xlisp/xlisp-doc/reference/rplacd.htm new file mode 100644 index 0000000..11b80c5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/rplacd.htm @@ -0,0 +1,89 @@ +XLISP rplacd + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    rplacd

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (rplacd list expr)
    +
    list - the list to destructively modify
    +expr - the expression to replace the +cdr of list
    +returns - the list node after updating the +cdr
    +
    + +

    Description

    + +

    The 'rplacd' function destructively modifies the +cdr of 'list' and replaces it with the +'expr'. The destructive aspect of this operation means that the actual +symbol value is used in the list-modifying operations, not a copy. 'list' +must evaluate to a valid list.

    + +

    An atom or NIL for 'list' will result in +an error:

    + +
    +error: bad argument type
    +
    + +

    Examples

    + +
    +(setq a '(1 2 3))          ; set up A with (1 2 3)
    +(rplacd a 'new)            ; returns (1 . NEW)
    +
    +(print a)                  ; prints (1 . NEW)
    +                           ;   note that A is modified
    +
    +(rplacd a '(a new list))   ; returns (1 A NEW LIST)
    +(rplacd '(1 2 3) '(more))  ; returns (1 MORE)
    +
    +(rplacd 'a 'b)             ; error: bad argument type
    +(rplacd NIL 'b)            ; error: bad argument type
    +
    + +

    See the +rplacd +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +XLISP > +XLISP 2.0  -  +Contents  -  +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/rrandom.htm b/docsrc/xlisp/xlisp-doc/reference/rrandom.htm new file mode 100644 index 0000000..5735287 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/rrandom.htm @@ -0,0 +1,66 @@ +XLISP rrandom + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    rrandom

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c, xlisp.c

    + +

    Syntax

    + +

    + +
    +
    (rrandom)
    +
    returns - a random floating point number between 0 and 1 inclusive
    +
    + +

    + +

    Description

    + +

    The 'random' function returns a random floating point number between 0 +and 1 inclusive.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/save.htm b/docsrc/xlisp/xlisp-doc/reference/save.htm new file mode 100644 index 0000000..8b7aba3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/save.htm @@ -0,0 +1,124 @@ +XLISP save + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    save

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -   xldmem.c, xlimage.c

    + +

    Syntax

    + +
    +
    (save file)
    +
    file - a string or symbol for the name of the file
    +returns -  T  if workspace was +written, NIL otherwise
    +
    + +

    Description

    + +

    The 'save' function saves the current XLISP workspace [system state] to +the specified file. The 'file' may be a string or a symbol. If the 'file' +does not include a '.wks' suffix, it will be extended to be called +'file.wks'. The function returns + T  if the workspace was properly +created and saved, NIL is returned +otherwise. There can be several saved workspaces. These workspaces can be +restored as often as desired.

    + +

    Examples

    + +
    +(setq myvar 5)       ; set MYVAR to value 5
    +myvar                ; returns 5
    +
    +(save 'farp)         ; save workspace in FARP.wks
    +
    +(setq myvar "garp")  ; change MYVAR to "garp"
    +myvar                ; returns "garp"
    +
    +(restore 'farp)      ; restore workspace
    +myvar                ; returns 5
    +
    + +

    Bug: The 'save' function generates a system error if the 'file' +being created already exists. This 'file' will be modified and will not be +restorable after restarting XLISP. [I still haven't tested this with +Nyquist.]

    + +

    Note: The saved workspace size is implementation dependent, but +can be fairly large.

    + +

    File names: In the PC and DOS world, all file names and extensions +["foo.bat"] are automatically made uppercase. In using XLISP, this +means you don't have to worry about whether the name is "foo.bat", +"FOO.BAT" or even "FoO.bAt", they will all work. +However, in other file systems [UNIX in particular], uppercase and lowercase +do make a difference:

    + +

    This will create a file named FOO-FILE in UNIX, because XLISP uppercases +its symbols:

    + +
    +(open 'foo-file :direction :output)
    +
    + +

    This will create a file named 'foo-file' because UNIX doesn't +uppercase its file names:

    + +
    +(open "foo-file" :direction :output)
    +
    + +

    So, if you are having trouble with opening and accessing files, check to +make sure the file name is in the proper case.

    + +

    Common Lisp: The XLISP 'save' function is similar in use to the +'save-world' function in Common Lisp. The primarily difference is that +'save-world' allows you to restart everything since it creates an executable +file. The 'save' function requires you to start XLISP up first and then do a +restore. Depending on the operating system +that you are using, it is possible to write a 'save-world' equivalent using +'save', restore and system.htm +functions.

    + +

    See the +save +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/second.htm b/docsrc/xlisp/xlisp-doc/reference/second.htm new file mode 100644 index 0000000..1b1c3e0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/second.htm @@ -0,0 +1,81 @@ +XLISP second + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    second

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlinit.c

    + +

    Syntax

    + +
    +
    (second expr)
    +
    expr - a list or list expression
    +returns - the second element of expr
    +
    + +

    Description

    + +

    The 'second' function returns the second element of a list or list +expression. If the list is +NIL , +NIL is returned.

    + +

    Examples

    + +
    +(second '(1 2 3))              ; returns 2
    +(second NIL)                   ; returns NIL
    +
    +(setq carol '(a b c))          ; set up variable CAROL
    +(first carol)                  ; returns A
    +(second carol)                 ; returns B
    +(rest carol)                   ; returns (B C)
    +
    +(setq children '(amanda ben))  ; set up variable CHILDREN
    +(second children)              ; returns BEN
    +
    + +

    Note: This function is set to the same code as the +cadr function.

    + +

    See the +second +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/self.htm b/docsrc/xlisp/xlisp-doc/reference/self.htm new file mode 100644 index 0000000..83ca806 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/self.htm @@ -0,0 +1,81 @@ +XLISP self + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    self

    + +
    + +

    + + + + + + + + + + +
    Type:  -  symbol
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
     self
    +
    + +

    Description

    + +

    The 'self' symbol evaluates to the current object when used within a +message context.

    + +

    Examples

    + +
    +(setq my-class (send class :new '(state)))               ; create MY-CLASS with STATE
    +
    +(send my-class :answer :isnew '()                        ; set up initialization
    +                              '((setq state nil) SELF))  ;   returning SELF
    +
    +(send my-class :answer :set-it '(value)                  ; create :SET-IT message
    +                               '((setq state value)))
    +
    +(setq my-obj (send my-class :new))                       ; create MY-OBJ of MY-CLASS
    +(send my-obj :set-it 5)                                  ; STATE is set to 5
    +
    + +

    Context: 'self' does not exist except within the context of a +method and it's execution.

    + +

    Note: In the previous example, there is a 'self' in the line that +creates the ':set-it' message. What this does is to return the object as the +last operation when you do an :isnew.

    + +

    See the +self +symbol in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/send-super.htm b/docsrc/xlisp/xlisp-doc/reference/send-super.htm new file mode 100644 index 0000000..c29d01f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/send-super.htm @@ -0,0 +1,87 @@ +XLISP send-super + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    send-super

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
    (send-super message [args])
    +
    message - the message selector
    +args - the optional message arguments
    +returns - the result of sending the message
    +
    + +

    Description

    + +

    The 'send-super' function sends the specified arguments 'args' to the +'message' specified method of the superclass. It is necessary for +'send-super' to be executed from within a method being performed on an +object. It will return the result of +sending the message. If 'send-super' is performed outside of a method an +error will result.

    + +
    +error: not in a method
    +
    + +

    Examples

    + +
    +(setq a-class (send class :new '()))                       ; create A-CLASS
    +
    +(send a-class :answer :show '()                            ; set up special SHOW method
    +                            '((print "nobody here") self))
    +
    +(setq an-obj (send a-class :new))                          ; create AN-OBJ of A-CLASS
    +(send an-obj :show)                                        ; prints "nobody here"
    +
    +(send a-class :answer :myshow '()                          ; set up MYSHOW method which
    +                              '((send-super :show )))      ;   calls :SHOW in superclass
    +
    +(send an-obj :myshow)                                      ; prints Object is ...
    +
    + +

    See the +send-super +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/send.htm b/docsrc/xlisp/xlisp-doc/reference/send.htm new file mode 100644 index 0000000..8874399 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/send.htm @@ -0,0 +1,96 @@ +XLISP send + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    send

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlobj.c

    + +

    Syntax

    + +
    +
    (send object message [args])
    +
    object - an object
    +message - message selector for object
    +arg - parameter sent to object method
    +returns - the object
    +
    + +

    Description

    + +

    The 'send' function is the mechanism used to send a 'message' to an +object. The 'message' is the message +selector symbol that is used to select a particular action [method] from +the object.

    + +

    Examples

    + +
    +(setq myclass (send class :new '(var)))              ; create MYCLASS with VAR
    +
    +(send myclass :answer :isnew '()                     ; set up initialization
    +                             '((setq var nil) self))
    +
    +(send myclass :answer :set-it '(value)               ; create :SET-IT message
    +                              '((setq var value)))
    +  
    +(setq my-obj (send myclass :new))                    ; create MY-OBJ of MYCLASS
    +(send my-obj :set-it 5)                              ; VAR is set to 5
    +
    + +

    Built-in methods: The built in methods in XLISP include:

    + +
      +
    • :answer - add a method to an object
    • +
    • :class - return the object's class
    • +
    • :isnew - run initialization code on object
    • +
    • :new - create a new object [instance or class]
    • +
    • :show - show the internal state of the object
    • +
    + +

    Message structure: The normal XLISP convention for a 'message' is +to have a valid symbol preceeded by a colon like +:isnew or ':my-message'. However, it is +possible to define a 'message' that is a symbol without a colon, but this +makes the code less readable.

    + +

    See the +send +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/set-difference.htm b/docsrc/xlisp/xlisp-doc/reference/set-difference.htm new file mode 100644 index 0000000..731ecb7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/set-difference.htm @@ -0,0 +1,75 @@ +XLISP set-difference + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    set-difference

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  xm.lsp

    + +

    Syntax

    + +

    + +
    +
    (set-difference list1 list2)
    +
    listN - a list of symbols or numbers
    +returns - the set-difference of list1 and list2
    +
    + +

    + +

    In Nyquist, 'set-difference' is implemented as a Lisp function:

    + +
    +(defun set-difference (a b)
    +  (remove-if (lambda (elem) (member elem b)) a))
    +
    + +

    Description

    + +

    The 'set-difference' function computes the +set-difference of two lists. The result is a list +containing all elements that appear in only one of both lists.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/set.htm b/docsrc/xlisp/xlisp-doc/reference/set.htm new file mode 100644 index 0000000..e67abb0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/set.htm @@ -0,0 +1,83 @@ +XLISP set + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    set

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (set symbol expr)
    +
    symbol - expression that evaluates to a symbol name [if the +expression is quoted, no evaluation occurs]
    +expr - an expression, which will be the new value
    +returns - the new value
    +
    + +

    Description

    + +

    The 'set' function evaluates 'symbol' and sets 'expr' as it's value. If +the 'symbol' value is quoted via the quote +special form or read-macro expansion, the 'symbol' is not evaluated. 'set' +returns the value from 'expr' as it's result.

    + +

    Examples

    + +
    +(set 'a 2)            ; sets symbol A to value 2
    +(set 'value a)        ; sets symbol VALUE to value 2
    +(print value)         ; show the value - prints 2
    +
    +(set 'name 'myvar)    ; set symbol NAME to value MYVAR
    +(set name 12345)      ; set symbol which is the value
    +                      ;   of NAME (MYVAR) to 12345
    +
    +(print name)          ; prints MYVAR
    +(print myvar)         ; prints 12345
    +
    +(set notsymbol 1)     ; error: unbound variable
    +(set name notvalue)   ; error: unbound variable
    +
    + +

    See the +set +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/setdir.htm b/docsrc/xlisp/xlisp-doc/reference/setdir.htm new file mode 100644 index 0000000..8e820ec --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/setdir.htm @@ -0,0 +1,65 @@ +XLISP setdir + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    setdir

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sys/unix/osstuff.c, sys/win/msvc/winfun.c

    + +

    Syntax

    + +
    +
    (setdir path) - set current directory
    +
    path - the path of the new directory
    +returns - the resulting full path or NIL if an error occurs
    +
    + +

    Description

    + +

    The 'setdir' function sets current directory, e.g. (setdir +".") gets the current working directory.

    + +

    Examples

    + +
    +
    +
    + +

    See also listdir.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/setf.htm b/docsrc/xlisp/xlisp-doc/reference/setf.htm new file mode 100644 index 0000000..72845bf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/setf.htm @@ -0,0 +1,273 @@ +XLISP setf + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    setf

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (setf [place1 expr1 ... ])
    +
    placeN - a field specifier which may be one of:
    +
    symbol - set value of a symbol
    +(car expr) - set car of a cons node
    +(cdr expr) - set cdr of a cons node
    +(nth n expr) - set nth car of a list
    +(aref expr n) - set nth element of an array
    +(get symbol property) - set value of a property
    +(symbol-value symbol) - set value of a symbol
    +(symbol-function symbol) - set functional value of a symbol
    +(symbol-plist symbol) - set property list of a symbol
    +exprN - an expression, which will be the new value
    +returns - the new value
    +
    + +

    Description

    + +

    The 'setf' special form evaluates the field 'placeN' and sets 'exprN' as +it's value. This is a generalized tool that allows you to set the value of +the various data types of the system. 'setf' returns the value from 'exprN' +as it's result. The specific action of 'setf' depends on the 'placeN' field. +A more detailed explanation follows below the examples.

    + +

    Examples

    + + +
    +:; setf symbols
    +
    +(setf a 123)                          ; set a symbol A to value 123
    +
    + +
    +;; setf symbol-values
    +
    +(setq x 'y)                           ; make symbol X with value Y
    +(setf (symbol-value x) 'z)            ; set symbol that X contains (Y) to value Z
    +
    + +
    +;; setf list elements
    +
    +(setq mylist '(a b c d))              ; MYLIST with value (A B C D)
    +
    +(setf (car mylist) 'x)                ; change CAR of MYLIST to X
    +                                      ;   MYLIST now is (X B C D)
    +
    +(setf (cdr mylist) '(y z da-end))     ; change CDR of MYLIST to (Y Z DA-END)
    +                                      ;   MYLIST now is (X Y Z DA-END)
    +
    +(setf (nth 3 mylist) 'here-i-am)      ; change 3rd of MYLIST to HERE-I-AM
    +                                      ;   MYLIST now is (X Y Z HERE-I-AM)
    +
    + +
    +;; setf arrays
    +
    +(setq myarray (make-array 5))         ; make MYARRAY
    +(aref myarray 2)                      ; get value of element 2 = NIL
    +(setf (aref myarray 2) 'new-value)    ; set value of element 2 to value NEW-VALUE
    +(print myarray)                       ; prints #(NIL NIL NEW-VALUE NIL NIL)
    +
    + +
    +;; setf properties
    +
    +(setq person 'joe-bob)                ; make PERSON with value JOE-BOB
    +(putprop person 'critic 'profession)  ; set PROFESSION property to value CRITIC
    +(setf (get person 'profession)        ; change PROFESSION to value TEXAS-CRITIC
    +(setf (get person 'home) 'texas)      ; add property HOME with value TEXAS
    +                
    +(symbol-plist person)                 ; returns property list:
    +                                      ;   (HOME TEXAS
    +                                      ;    PROFESSION TEXAS-CRITIC)
    +
    +(setf (symbol-plist person)           ; change the property list
    +      '(home on-the-range
    +        profession movie-critic))
    +
    +(get person 'profession)              ; now returns MOVIE-CRITIC
    +(get person 'home)                    ; now returns ON-THE-RANGE
    +
    + +

    Operations

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    (setf sym exprN)
    +
      - Sets the value of 'symbol' to the value of 'exprN'. + This is equivalent to (setq + sym exprN)
    + + + + +
    (setf (car expr) exprN)
    +
      - Sets the first element of the 'expr' list to 'exprN'. + 'expr' must be a list. This is equivalent to + (rplaca expr exprN) + except that 'setf' will return 'exprN' as the value.
    + + + + +
    (setf (cdr expr) exprN)
    +
      - Sets the tail of the 'expr' list to 'exprN'. 'expr' must + be a list. This is equivalent to + (rplacd expr exprN) + except that 'setf' will return 'exprN' as the value.
    + + + + +
    (setf (nth n expr) exprN)
    +
      - Sets the nth element of + the 'expr' list to 'exprN'. 'expr' must be a list. This allows you to + set an arbitrary element of a list to an arbitrary value. Note that the + list is numbered from the 0th element (0, 1, 2, 3, + ...).
    + + + + +
    (setf (aref expr n) exprN)
    +
      - Sets the nth element of the 'expr' array to 'exprN'. + 'expr' must be an array. This allows you to set an arbitrary element of + an array to an arbitrary value. Note that the list is numbered from the + 0th element (0, 1, 2, 3, ...). Note also that this is the + intended way to set the value of an array element.
    + + + + +
    (setf (get sym prop) exprN)
    +
      - Sets the 'property' of 'symbol' to the value 'exprN'. + If 'symbol' does not have the 'property', one will be created. This is + equivalent to (putprop sym + exprN prop).
    + + + + +
    (setf (symbol-value sym) exprN)
    +
      - Sets the symbol's value to contain 'exprN'. 'symbol' is + an expression that must evaluate to a valid symbol, it doesn't have to + exist before the 'setf' function is applied, it just has to be a valid + symbol. This is equivalent to (set symbol exprN).
    + + + + +
    (setf (symbol-plist sym) exprN)
    +
      - Sets the property list of 'symbol' to 'exprN'. This + allows you to change or destroy the entire property list of a 'symbol' + at one time.

    + +

    See the +setf +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/setq.htm b/docsrc/xlisp/xlisp-doc/reference/setq.htm new file mode 100644 index 0000000..83fee7a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/setq.htm @@ -0,0 +1,70 @@ +XLISP setq + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    setq

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (setq [symbol1 expr1] ... )
    +
    symbolN - un-evaluated symbol
    +exprN - value for symbolN
    +returns - the new value
    +
    + +

    Description

    + +

    The 'setq' special form sets 'expr' as the value of 'symbol'. 'setq' +returns the value from 'expr' as it's result.

    + +

    Examples

    + +
    +(setq a 1)             ; symbol A gets value 1
    +(setq b '(a b c))      ; symbol B gets value (A B C)
    +(setq mynum (+ 3 4))   ; symbol MYNUM gets value 7
    +
    + +

    See the +setq +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/setup-console.htm b/docsrc/xlisp/xlisp-doc/reference/setup-console.htm new file mode 100644 index 0000000..ff21c53 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/setup-console.htm @@ -0,0 +1,72 @@ +XLISP setup-console + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    setup-console

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sys/unix/osstuff.c, sys/mac/macstuff.c, sys/win/msvc/winfun.c

    + +

    Syntax

    + +
    +
    (setup-console)
    +
    returns - NIL
    +
    + +

    Description

    + +

    The 'setup-console' function sets the default console +attributes.

    + +

    Note: Under Windows, Nyquist normally starts up in a +medium-sized console window with black text and a white +background, with a window title of 'Nyquist'. This is normally accomplished +by calling 'setup-console' in 'system.lsp'. +In Nyquist, you can avoid this behavior by setting +*setup-console* to NIL in your +'init.lsp' file. If 'setup-console' is not called, +Nyquist uses standard input and output as is. This is what you +want if you are running Nyquist inside of emacs, for example.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/sin.htm b/docsrc/xlisp/xlisp-doc/reference/sin.htm new file mode 100644 index 0000000..6ca07b6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/sin.htm @@ -0,0 +1,76 @@ +XLISP sin + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    sin

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (sin expr)
    +
    expr - floating point number or expression
    +returns - the sine of the number
    +
    + +

    Description

    + +

    The 'sin' function returns the sine of the 'expr'. The 'expr' is in +radians.

    + +

    Examples

    + +
    +(sin 0.0)             ; returns 0
    +(sin .5)              ; returns 0.479426
    +(sin 1.0)             ; returns 0.841471
    +(sin (/ 3.14159 2))   ; returns 1
    +(sin 3.14159)         ; returns 2.65359e-06
    +(sin 0)               ; error: bad integer operation
    +(sin 1.)              ; error: bad integer operation
    +
    + +

    Common Lisp: Common LISP allows for integer numbers, which +XLISP does not support for 'sin'.

    + +

    See the +sin +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/sort.htm b/docsrc/xlisp/xlisp-doc/reference/sort.htm new file mode 100644 index 0000000..ac874e1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/sort.htm @@ -0,0 +1,104 @@ +XLISP sort + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    sort

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (sort list test)
    +
    list - a list containing elements to be sorted
    +test - the test to use for the sort
    +returns - the sorted list
    +
    + +

    Description

    + +

    The 'sort' function sorts the 'list' using the 'test' to order the +list. The 'sort' function is destructive and modifies the 'list'.

    + +

    Examples

    + +
    +(setq a '(3 1 4 1 5 9 6 7))          ; returns (3 1 4 1 5 9 6 7)
    +
    +(sort a '<)                          ; returns (1 1 3 4 5 6 7 9)
    +
    +(print a)                            ; returns (1 1 3 4 5 6 7 9)
    +                                     ; notice that A is modified
    +
    +(sort a '>)                          ; returns (9 7 6 5 4 3 1 1)
    +
    +(sort '("a" "bar" "foo") 'string>)   ; returns ("foo" "bar" "a")
    +
    + +

    + +

    XLISP Bug

    + +

    Nyquist 'sort' returns the proper value, but improperly modifies the +symbol or the actual 'list', for example:

    + +
    +(setq a '(3 1 4 1 5 9 6 7))  => (3 1 4 1 5 9 6 7)
    +(sort a '<)                  => (1 1 3 4 5 6 7 9)  ; OK
    +a                            => (3 4 5 6 7 9)      ; BUG
    +
    + +

    But this way it works:

    + +
    +(setq a '(3 1 4 1 5 9 6 7))  => (3 1 4 1 5 9 6 7)
    +(setq a (sort a '<))         => (1 1 3 4 5 6 7 9)
    +a                            => (1 1 3 4 5 6 7 9)
    +
    + +

    + +

    Common Lisp: Common Lisp allows for a ':key' keyword, which +allows a specified function to be run before the ordering takes place, which +XLISP does not support.

    + +

    See the +sort +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/soundp.htm b/docsrc/xlisp/xlisp-doc/reference/soundp.htm new file mode 100644 index 0000000..3e72247 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/soundp.htm @@ -0,0 +1,70 @@ +XLISP soundp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    soundp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sndfnint.c, sound.c

    + +

    Syntax

    + +

    + +
    +
    (soundp expr)
    +
    expr - an arbitrary Lisp expression
    +returns -  T  if expr is a sound, +NIL otherwise
    +
    + +

    + +

    Description

    + +

    The 'soundp' function returns  T  if +'expr' is a Nyquist sound, NIL otherwise.

    + +

    Examples

    + +
    +
    +
    + +

    Please see the Nyquist manual for Nyquist/XLISP audio functions.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/sqrt.htm b/docsrc/xlisp/xlisp-doc/reference/sqrt.htm new file mode 100644 index 0000000..c563933 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/sqrt.htm @@ -0,0 +1,76 @@ +XLISP sqrt + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    sqrt

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (sqrt expr)
    +
    expr - floating point number or expression
    +returns - the square root of the number
    +
    + +

    Description

    + +

    The 'sqrt' function calculates the square root of 'expr' and returns +this result.

    + +

    Examples

    + +
    +(sqrt 1.0)    ; returns 1
    +(sqrt 2.0)    ; returns 1.41421
    +(sqrt 3.0)    ; returns 1.73205
    +(sqrt 4.0)    ; returns 2
    +(sqrt 5.0)    ; returns 2.23607
    +(sqrt -1.0)   ; error: square root of a negative number
    +(sqrt 2)      ; error: bad integer operation
    +
    + +

    Common Lisp: Common Lisp allows for integer numbers, which +XLISP does not support for 'sqrt'.

    + +

    See the +sqrt +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/strcat.htm b/docsrc/xlisp/xlisp-doc/reference/strcat.htm new file mode 100644 index 0000000..f0437b9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/strcat.htm @@ -0,0 +1,72 @@ +XLISP strcat + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    strcat

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (strcat [string1 ... ])
    +
    stringN - a string expression
    +returns - the result of concatenating the strings
    +
    + +

    Description

    + +

    The 'strcat' function returns the concatenation of a sequence of string +expressions. If there are no strings, an empty string is returned.

    + +

    Examples

    + +
    +(strcat)                     ; returns ""
    +(strcat "a")                 ; returns "a"
    +(strcat "a" "b")             ; returns "ab"
    +(strcat "ab" "cd" "ef")      ; returns "abcdef"
    +(strcat "f" "ire tr" "uck")  ; returns "fire truck"
    +(strcat 1 2)                 ; error: bad argument type
    +
    + +

    See the +strcat +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/streamp.htm b/docsrc/xlisp/xlisp-doc/reference/streamp.htm new file mode 100644 index 0000000..848998b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/streamp.htm @@ -0,0 +1,84 @@ +XLISP streamp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    streamp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (streamp expr)
    +
    expr - the expression to check
    +returns -  T  if the value is a +stream, NIL otherwise
    +
    + +

    Description

    + +

    The 'streamp' predicate function checks if an 'expr' is a stream. + T  is returned if 'expr' is a +stream, NIL is returned otherwise.

    + +

    EXAMPLES

    + +
    +(streamp *standard-input*)             ; returns T - stream
    +(streamp *debug-io*)                   ; returns T - stream
    +(streamp (make-string-output-stream))  ; returns T - stream
    +
    +(setq a *standard-output*)
    +(streamp a)                            ; returns T - evaluates to stream
    +
    +(streamp "a")                          ; returns NIL - string
    +(streamp #\a)                          ; returns NIL - character
    +(streamp '(a b c))                     ; returns NIL - list
    +(streamp 1)                            ; returns NIL - integer
    +(streamp 1.2)                          ; returns NIL - float
    +(streamp '*debug-io*)                  ; returns NIL - symbol
    +(streamp 'a)                           ; returns NIL - symbol
    +(streamp #(0 1 2))                     ; returns NIL - array
    +(streamp NIL)                          ; returns NIL - NIL
    +
    + +

    See the +streamp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-downcase.htm b/docsrc/xlisp/xlisp-doc/reference/string-downcase.htm new file mode 100644 index 0000000..f67c211 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-downcase.htm @@ -0,0 +1,80 @@ +XLISP string-downcase + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-downcase

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-downcase string [{:start | :end} offset] ... )
    +
    string - a string expression
    +offset - an optional integer expression for a keyword
    +returns - a converted copy of the string
    +
    + +

    Description

    + +

    The 'string-downcase' function takes a string argument and returns a new +string that has been made lower case.

    + +

    The keyword arguments allow for accessing substrings within 'string'. The +keyword arguments require a keyword ':start' or ':end' first and a single +integer expression second. The ':start' keyword specifies the starting +offset for the 'string-downcase' operation on 'string'. A value of 0 starts +the string at the beginning [no offset]. The ':end' keyword specifies the +end offset for the operation on 'string'.

    + +

    Examples

    + +
    +(string-downcase "ABcd+-12&[")                ; returns "abcd+-&["
    +(string-downcase "ABCDEFGH" :start 2 :end 4)  ; returns "ABcdEFGH"
    +
    +(setq mystr "ABcdEFgh")      ; set up variable
    +(string-downcase mystr)      ; returns "abcdefgh"
    +(print mystr)                ; prints  "ABcdEFgh"
    +
    + +

    See the +string-downcase +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-equal-i.htm b/docsrc/xlisp/xlisp-doc/reference/string-equal-i.htm new file mode 100644 index 0000000..f83b91c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-equal-i.htm @@ -0,0 +1,111 @@ +XLISP tring-equal + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-equal

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-equal string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns -  T  if string1 +equal to string2, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    Description

    + +

    The 'string-equal' function takes two string arguments. It checks to see +if the string arguments have the same values. + T  is returned if 'string1' is +equal to 'string2', NIL is returned +otherwise. This test is not case sensitive, the character '#\a' is +considered to be the same as '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string-equal "a" "b")            ; returns NIL
    +(string-equal "a" "a")            ; returns T
    +(string-equal "a" "A")            ; returns T
    +(string-equal "A" "a")            ; returns T
    +(string-equal "abc" "abc ")       ; returns NIL
    +
    +(string-equal "J Smith" "K Smith" :start1 1 :start2 1)  ; strip off the first chars
    +                                                        ; returns T
    +
    +(string-equal "abc" "123456789" :end2 3 :end1 3)        ; leave just the first 3 chars
    +                                                        ; returns NIL
    +
    + +

    Bug: The 'string-equal' function is listed in the original XLISP +documentation as 'string-equalp'. In the XLISP interpreter a call to +'string-equalp' causes an error:

    + +
    +error: unbound function - STRING-EQUALP
    +
    + +

    The 'string-equal' function works exactly as the 'string-equalp' function +described in the XLISP manual. This bug had obviously been corrected in +the manual only but never in the interpreter. As the bug still exists with +Nyquist 2.36 in July 2007 as well as all other +XLISP 2.x implementations I know, I have changed both manuals +to 'string-equal' even if I myself whould consider 'string-equalp' as the +better name.

    + +

    See the +string-equal +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-equal-s.htm b/docsrc/xlisp/xlisp-doc/reference/string-equal-s.htm new file mode 100644 index 0000000..a50ad74 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-equal-s.htm @@ -0,0 +1,96 @@ +XLISP string= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string= string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns -  T  if the string +arguments have the same values, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    Description

    + +

    The 'string=' [string-equal] function takes two string arguments. It +checks to see if the string arguments have the same values. + T  is returned if 'string1' is +equal to 'string2', NIL is returned +otherwise. This test is case sensitive, the character '#\a' is different and +of greater ASCII value than +'#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string= "a" "b")           ; returns NIL
    +(string= "a" "a")           ; returns T
    +(string= "a" "A")           ; returns NIL
    +(string= "A" "a")           ; returns NIL
    +(string= "abc" "abc ")      ; returns NIL
    +
    +(string= "J Smith" "K Smith" :start1 1 :start2 1)  ; strip off the first chars 
    +                                                   ; returns T
    +
    +(string= "abc" "123456789" :end2 3 :end1 3)        ; leave just the first 3 chars 
    +                                                   ; returns NIL
    +
    + +

    See the +string= +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-greaterp-i.htm b/docsrc/xlisp/xlisp-doc/reference/string-greaterp-i.htm new file mode 100644 index 0000000..71b18db --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-greaterp-i.htm @@ -0,0 +1,98 @@ +XLISP string-greaterp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-greaterp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-greaterp string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is greater than string2 in +ASCII ordering, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    Description

    + +

    The 'string-greaterp' [string-greater-than] predicate function takes two +string arguments. A non-NIL value is +returned if 'string1' is greater than 'string2' in +ASCII ordering, otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char-greaterp [char-greater-than] the +corresponding character of 'string2'. This test is not case sensitive, the +character '#\a' is considered to be the same as '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string-greaterp "a" "b")                   ; returns NIL
    +(string-greaterp "a" "a")                   ; returns NIL
    +(string-greaterp "a" "A")                   ; returns NIL
    +(string-greaterp "A" "a")                   ; returns NIL
    +(string-greaterp "abc" "abc ")              ; returns NIL
    +(string-greaterp "1234qrst" "12345678")     ; returns 4
    +
    +(string-greaterp "J Smith" "K Jones" :start1 1 :start2 1)  ; strip off the first chars 
    +                                                           ; returns 2
    +
    + +

    See the +string-greaterp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-greaterp-s.htm b/docsrc/xlisp/xlisp-doc/reference/string-greaterp-s.htm new file mode 100644 index 0000000..c5f5fa4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-greaterp-s.htm @@ -0,0 +1,99 @@ +XLISP string> + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string>

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string> string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is greater than string2 in +ASCII ordering, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    Description

    + +

    The 'string>' [string-greater-than] function takes two string +arguments. A non-NIL value is returned if +'string1' is greater than 'string2' in +ASCII ordering, otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char> [char-greater-than] the +corresponding character of 'string2'. This test is case sensitive, the +character '#\a' is different and of greater +ASCII value than '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string> "a" "b")                   ; returns NIL
    +(string> "a" "a")                   ; returns NIL
    +(string> "a" "A")                   ; returns 0
    +(string> "A" "a")                   ; returns NIL
    +(string> "abc" "abc ")              ; returns NIL
    +(string> "1234qrst" "12345678")     ; returns 4
    +
    +(string> "J Smith" "K Jones" :start1 1 :start2 1)  ; strip off the first chars
    +                                                   ; returns 2
    +
    + +

    See the +string> +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-left-trim.htm b/docsrc/xlisp/xlisp-doc/reference/string-left-trim.htm new file mode 100644 index 0000000..bf88c2c --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-left-trim.htm @@ -0,0 +1,84 @@ +XLISP string-left-trim + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-left-trim

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-left-trim trim-stuff string)
    +
    trim-stuff - a string expression
    +string - a string expression
    +returns - a trimed copy of the string
    +
    + +

    Description

    + +

    The 'string-left-trim' function takes the 'trim-stuff' characters and +removes them from the left end of the 'string'. The 'trim-stuff' characters +are an un-ordered set of characters to be removed, so any character that +occurs in 'trim-stuff' is removed if it appears in left portion of 'string'. +A new string is created and returned as the result of this function.

    + +

    Examples

    + +
    +(string-left-trim "." "....foo....")     ; returns "foo...."
    +(string-left-trim "<>" "<<<<bar>>>>")    ; returns "bar>>>>"
    +(string-left-trim "(.)" "..(12.34)..")   ; returns "12.34).."
    +
    + +

    Common Lisp: Common Lisp also supports a list of characters as +a valid 'trim-stuff' argument. An example:

    + +
    +(string-trim '(#\Tab #\Newline) mystring)
    +
    + +

    XLISP does not support non-string parameters. Porting from XLISP will +be no problem, but modifications will be necessary if porting from Common +Lisp code which uses a list of characters.

    + +

    See the +string-left-trim +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-lessp-i.htm b/docsrc/xlisp/xlisp-doc/reference/string-lessp-i.htm new file mode 100644 index 0000000..14d40f7 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-lessp-i.htm @@ -0,0 +1,98 @@ +XLISP string-lessp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-lessp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-lessp string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is less than string2 in +ASCII ordering, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    Description

    + +

    The 'string-lessp' [string-less-than] predicate function takes two string +arguments. A non-NIL value is returned if +'string1' is less than 'string2' in +ASCII ordering, otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char-lessp [char-less-than] the +corresponding character of 'string2'. This test is not case sensitive, the +character '#\a' is considered to be the same as '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string-lessp "a" "b")                  ; returns 0
    +(string-lessp "a" "a")                  ; returns NIL
    +(string-lessp "a" "A")                  ; returns NIL
    +(string-lessp "A" "a")                  ; returns NIL
    +(string-lessp "abc" "abc ")             ; returns 3
    +(string-lessp "1234567" "1234qrst")     ; returns 4
    +
    +(string-lessp "J Smith" "K Smith" :start1 1 :start2 1)  ; strip off the first chars
    +                                                        ; returns NIL
    +
    + +

    See the +string-lessp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-lessp-s.htm b/docsrc/xlisp/xlisp-doc/reference/string-lessp-s.htm new file mode 100644 index 0000000..393ef49 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-lessp-s.htm @@ -0,0 +1,98 @@ +XLISP string< + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string<

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string< string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is less than string2 in +ASCII ordering, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    Description

    + +

    The 'string<' [string-less-than] function takes two string arguments. +A non-NIL value is returned if 'string1' +is less than 'string2' in ASCII +ordering, otherwise NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char< [char-less-than] the corresponding +character of 'string2'. This test is case sensitive, the character '#\a' is +different and of greater ASCII +value than '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string< "a" "b")                ; returns 0
    +(string< "a" "a")                ; returns NIL
    +(string< "a" "A")                ; returns NIL
    +(string< "A" "a")                ; returns 0
    +(string< "abc" "abc ")           ; returns 3
    +(string< "1234567" "1234qrst")   ; returns 4
    +
    +(string< "J Smith" "K Smith" :start1 1 :start2 1)  ; strip off the first chars
    +                                                   ; returns NIL
    +
    + +

    See the +string< +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-not-equal-i.htm b/docsrc/xlisp/xlisp-doc/reference/string-not-equal-i.htm new file mode 100644 index 0000000..4360306 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-not-equal-i.htm @@ -0,0 +1,112 @@ +XLISP string-not-equal + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-not-equal

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-not-equal string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is not equal to string2, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    Description

    + +

    The 'string-not-equal' function takes two string arguments. A +non-NIL value is returned if 'string1' is +not equal to 'string2', otherwise NIL is +returned. The non-NIL value returned is the +integer index of the first character of 'string1' which is +char-not-equal to the corresponding +character of 'string2'. This test is not case sensitive, the character +'#\a' is considered to be the same as '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string-not-equal "a" "b")               ; returns 0
    +(string-not-equal "a" "a")               ; returns NIL
    +(string-not-equal "a" "A")               ; returns NIL
    +(string-not-equal "A" "a")               ; returns NIL
    +(string-not-equal "abc" "abc ")          ; returns 3
    +
    +(string-not-equal "J Smith" "K Smith" :start1 1 :start2 1)  ; strip off the first chars
    +                                                            ; returns NIL
    +(string-not-equal "abc" "123456789" :end2 3 :end1 3)        ; leave just the first 3 chars
    +                                                            ; returns 0
    +
    + +

    Bug: The 'string-not-equal' function is listed in the original +XLISP documentation as 'string-not-equalp'. In the XLISP interpreter a call +to 'string-not-equalp' causes an error:

    + +
    +error: unbound function - STRING-NOT-EQUALP
    +
    + +

    The 'string-not-equal' function works exactly as the 'string-not-equalp' +function described in the XLISP manual. This bug had obviously been +corrected in the manual only but never in the interpreter. As the bug still +exists with Nyquist 2.36 in July 2007 as well as +all other XLISP 2.x implementations I know, I have changed both +manuals to 'string-not-equal' even if I myself whould consider +'string-not-equalp' as the better name.

    + +

    See the +string-not-equal +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-not-equal-s.htm b/docsrc/xlisp/xlisp-doc/reference/string-not-equal-s.htm new file mode 100644 index 0000000..ef515c6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-not-equal-s.htm @@ -0,0 +1,104 @@ +XLISP string/= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string/=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string/= string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is not equal to string2, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    Description

    + +

    The 'string/=' [string-not-equal] function takes two string arguments. A +non-NIL value is returned if 'string1' is +not equal to 'string2', otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char/= [char-not-equal] to the +corresponding character of 'string2'. +This test is case sensitive, the character '#\a' is different and of greater +ASCII value than '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string/= "a" "b")           ; returns 0
    +(string/= "a" "a")           ; returns NIL
    +(string/= "a" "A")           ; returns 0
    +(string/= "A" "a")           ; returns 0
    +(string/= "abc" "abc ")      ; returns 3
    +
    +(string/= "J Smith" "K Smith" :start1 1 :start2 1)  ; returns NIL
    +(string/= "abc" "123456789" :end2 3 :end1 3)        ; returns 0
    +
    + +

    Note: Be sure that the 'string/=' function is properly typed in. +The '/' is a forward slash. It is possible to mistakenly type a '\' +backslash. This is especially easy because the character mechanism is '#\a'. +If you do use the backslash, no error will be reported because backslash is +the single escape character and the XLISP reader will evaluate 'string\=' as +'string='. No error will be reported, but the sense of the test is +reversed.

    + +

    See the +string/= +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-i.htm b/docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-i.htm new file mode 100644 index 0000000..a5cafa8 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-i.htm @@ -0,0 +1,99 @@ +XLISP string-not-greaterp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-not-greaterp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-not-greaterp string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is less than or equal to string2 in +ASCII ordering, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    Description

    + +

    The 'string-not-greaterp' [string-not-greater-than] predicate function +takes two string arguments. A non-NIL value +is returned if 'string1' is less than or equal to 'string2' in +ASCII ordering, otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char-not-greaterp [char-not-greater-than] the corresponding +character of 'string2'. This test is not case sensitive, the character +'#\a' is considered to be the same as '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string-not-greaterp "a" "b")                ; returns 0
    +(string-not-greaterp "b" "a")                ; returns NIL
    +(string-not-greaterp "a" "a")                ; returns 1
    +(string-not-greaterp "a" "A")                ; returns 1
    +(string-not-greaterp "A" "a")                ; returns 1
    +(string-not-greaterp "abc" "abc ")           ; returns 3
    +(string-not-greaterp "12345" "1234qr")       ; returns 4
    +
    +(string-not-greaterp "J Smith" "K Smith" :start1 1 :start2 1)  ; strip off the first chars
    +                                                               ; returns 7
    +
    + +

    See the +string-not-greaterp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-s.htm b/docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-s.htm new file mode 100644 index 0000000..8710fdf --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-not-greaterp-s.htm @@ -0,0 +1,99 @@ +XLISP string<= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string<=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string<= string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is less than or equal to string2 in +ASCII ordering, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    Description

    + +

    The 'string<=' [string-less-than-or-equal] function takes two string +arguments. A non-NIL value is returned if +'string1' is less than or equal to 'string2' in +ASCII ordering, otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char<= [char-less-than-or-equal] to the +corresponding character of 'string2'. This test is case sensitive, the +character '#\a' is different and of greater +ASCII value than '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string<= "a" "b")                ; returns 0
    +(string<= "a" "a")                ; returns 1
    +(string<= "a" "A")                ; returns NIL
    +(string<= "A" "a")                ; returns 0
    +(string<= "abc" "abc ")           ; returns 3
    +(string<= "1234567" "1234qrst")   ; returns 4
    +
    +(string<= "J Smith" "K Smith" :start1 1 :start2 1)  ; strip off the first chars
    +                                                    ; returns 7
    +
    + +

    See the +string<= +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-not-lessp-i.htm b/docsrc/xlisp/xlisp-doc/reference/string-not-lessp-i.htm new file mode 100644 index 0000000..e70c391 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-not-lessp-i.htm @@ -0,0 +1,98 @@ +XLISP string-not-lessp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-not-lessp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-not-lessp string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is greater than or equal to string2 in +ASCII ordering, +NIL otherwise
    +Note: case is not significant with this function
    +
    + +

    Description

    + +

    The 'string-not-lessp' [string-not-less-than] predicate function +takes two string arguments. A non-NIL value +is returned if 'string1' is greater than or equal to 'string2' in +ASCII ordering, otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char-not-lessp [char-not-less-than] the +corresponding character of 'string2'. This test is not case sensitive, the +character '#\a' is considered to be the same as '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string-not-lessp "a" "b")                ; returns NIL
    +(string-not-lessp "a" "a")                ; returns 1
    +(string-not-lessp "a" "A")                ; returns 1
    +(string-not-lessp "A" "a")                ; returns 1
    +(string-not-lessp "abc" "abc ")           ; returns NIL
    +(string-not-lessp "1234qr" "123456")      ; returns 4
    +
    +(string-not-lessp "J Smith" "K Jones" :start1 1 :start2 1)  ; strip off the first chars 
    +                                                            ; returns 2
    +
    + +

    See the +string-not-lessp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-not-lessp-s.htm b/docsrc/xlisp/xlisp-doc/reference/string-not-lessp-s.htm new file mode 100644 index 0000000..527c116 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-not-lessp-s.htm @@ -0,0 +1,99 @@ +XLISP string>= + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string>=

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string>= string1 string2 [key offset] ... )
    +
    stringN - a string expression
    +key - a keyword [one of :start1 :start2 :end1 :end2]
    +offset - an optional integer expression for a keyword
    +returns - a non-NIL value if string1 +is greater than or equal to string2 in +ASCII ordering, +NIL otherwise
    +Note: case is significant with this function
    +
    + +

    Description

    + +

    The 'string>=' [string-greater-than-or-equal] function takes two +string arguments. A non-NIL value is +returned if 'string1' is greater than or equal to 'string2' in an +ASCII ordering, otherwise +NIL is returned. The +non-NIL value returned is the integer index +of the first character of 'string1' which is +char>= [char-greater-than-or-equal] to +the corresponding character of 'string2'. This test is case sensitive, the +character '#\a' is different and of greater +ASCII value than '#\A'.

    + +

    The keyword arguments allow for accessing substrings within 'string1' and +'string2'. The keyword arguments each require a keyword ':start1', ':end1', +':start2' or ':end2' and a single integer expression as a pair with the +keyword first and the integer second. The pairs may be in any order. The +':startN' keywords specify the starting offset of the substring. A value of +0 starts the string at the beginning [no offset]. The ':endN' keywords +specify the ending offset of the substring. A value of 3 ends the string +after the 3rd character [an offset of 3 characters].

    + +

    Examples

    + +
    +(string>= "a" "b")                   ; returns NIL
    +(string>= "a" "a")                   ; returns 1
    +(string>= "a" "A")                   ; returns 0
    +(string>= "A" "a")                   ; returns NIL
    +(string>= "abc" "abc ")              ; returns NIL
    +(string>= "1234qrst" "12345678")     ; returns 4
    +
    +(string>= "J Smith" "K Jones" :start1 1 :start2 1)  ; strip off the first chars
    +                                                    ; returns 2
    +
    + +

    See the +string>= +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-right-trim.htm b/docsrc/xlisp/xlisp-doc/reference/string-right-trim.htm new file mode 100644 index 0000000..56cb58d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-right-trim.htm @@ -0,0 +1,85 @@ +XLISP string-right-trim + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-right-trim

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-right-trim trim-stuff string)
    +
    trim-stuff - a string expression
    +string - a string expression
    +returns - a trimed copy of the string
    +
    + +

    Description

    + +

    The 'string-right-trim' function takes the 'trim-stuff' characters and +removes them from the right end of the 'string'. The 'trim-stuff' characters +are an un-ordered set of characters to be removed, so any character that +occurs in 'trim-stuff' is removed if it appears in right portion of +'string'. A new string is created and returned as the result of this +function.

    + +

    Examples

    + +
    +(string-right-trim "." "....foo....")     ; returns "....foo"
    +(string-right-trim "<>" "<<<<bar>>>>")    ; returns "<<<<bar"
    +(string-right-trim "(.)" "..(12.34)..")   ; returns "..(12.34"
    +
    + +

    Common Lisp: Common LISP also supports a list of characters as +a valid 'trim-stuff' argument. An example: + +

    +(string-trim '(#\Tab #\Newline) mystring)
    +
    + +

    XLISP does not support non-string parameters. Porting from XLISP will be +no problem, but modifications will be necessary if porting from Common LISP +code which uses a list of characters.

    + +

    See the +string-right-trim +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-search.htm b/docsrc/xlisp/xlisp-doc/reference/string-search.htm new file mode 100644 index 0000000..ebf5e8a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-search.htm @@ -0,0 +1,68 @@ +XLISP string-search + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-search

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-search pattern string &key :start :end)
    +pattern - a string to search for
    +string - the string to be searched
    +:start integer - the starting offset in string
    +:end integer - the ending offset + 1
    +returns - index of pattern in string or NIL if not found
    +
    + + +

    Description

    + +

    The 'string-search' function searches for 'pattern' in +'string' and returns the index of the first 'pattern' found in 'string' or +NIL if no pattern was found.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-trim.htm b/docsrc/xlisp/xlisp-doc/reference/string-trim.htm new file mode 100644 index 0000000..7e26375 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-trim.htm @@ -0,0 +1,84 @@ +XLISP string-trim + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-trim

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-trim trim-stuff string)
    +
    trim-stuff - a string expression
    +string - a string expression
    +returns - a trimed copy of the string
    +
    + +

    Description

    + +

    The 'string-trim' function takes the 'trim-stuff' characters and removes +them from both ends of the 'string'. The 'trim-stuff' characters are an +un-ordered set of characters to be removed, so any character that occurs in +'trim-stuff' is removed if it appears in 'string'. A new string is created +and returned as the result of this function.

    + +

    Examples

    + +
    +(string-trim "." "....foo....")     ; returns "foo"
    +(string-trim "<>" "<<<<bar>>>>")    ; returns "bar"
    +(string-trim "(.)" "..(12.34)..")   ; returns "12.34"
    +
    + +

    Common Lisp: Common LISP also supports a list of characters as +a valid 'trim-stuff' argument. An example: + +

    +(string-trim '(#\Tab #\Newline) mystring)
    +
    + +

    XLISP does not support non-string parameters. Porting from XLISP will be +no problem, but modifications will be necessary if porting from Common LISP +code which uses a list of characters.

    + +

    See the +string-trim +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string-upcase.htm b/docsrc/xlisp/xlisp-doc/reference/string-upcase.htm new file mode 100644 index 0000000..cd2e54f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string-upcase.htm @@ -0,0 +1,80 @@ +XLISP string-upcase + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string-upcase

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string-upcase string [{:start | :end} offset] ... )
    +
    string - a string expression
    +offset - an optional integer expression for a keyword
    +returns - a converted copy of the string
    +
    + +

    Description

    + +

    The 'string-upcase' function takes a string argument and returns a new +string that has been made upper case.

    + +

    The keyword arguments allow for accessing substrings within 'string'. The +keyword arguments require a keyword ':start' or ':end' first and a single +integer expression second. The ':start' keyword specifies the starting +offset for the 'string-upcase' operation on 'string'. A value of 0 starts +the string at the beginning [no offset]. The ':end' keyword specifies the +end offset for the operation on 'string'.

    + +

    Examples

    + +
    +(string-upcase "ABcd+-12&[")                ; returns "ABCD+-&["
    +(string-upcase "abcdefgh" :start 2 :end 4)  ; returns "abCDefgh"
    +
    +(setq mystr "ABcdEFgh")       ; set up variable
    +(string-upcase mystr)         ; returns "ABCDEFGH"
    +(print mystr)                 ; prints  "ABcdEFgh"
    +
    + +

    See the +string-upcase +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/string.htm b/docsrc/xlisp/xlisp-doc/reference/string.htm new file mode 100644 index 0000000..90224fa --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/string.htm @@ -0,0 +1,88 @@ +XLISP string + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    string

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (string expr)
    +
    expr - a symbol, character, integer or string expression
    +returns - a string
    +
    + +

    Description

    + +

    The 'string' function makes the 'expr' to be a string. If +the 'expr' is a string, it is returned, as is. If the +'expr' is a character, a one-character string is returned. +If the 'expr' is a symbol, the symbol is turned into a string. +If the 'expr' is an integer, a string representing the +character with an ASCII code of the lowest 8-bit of the intger will be +returned:

    + +

    + + + + + + + + +
      (string integer)  →  (code-char (rem integer 256))  →  string

    + +

    Examples

    + +
    +(string 'foo)        ; returns "FOO"
    +(string 'x)          ; returns "X"
    +(string "abcdef")    ; returns "abcdef"
    +(string #\a)         ; returns "a"
    +(string #\A)         ; returns "A"
    +(string #\Newline)   ; returns "\n"
    +
    + +

    See the +string +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/stringp.htm b/docsrc/xlisp/xlisp-doc/reference/stringp.htm new file mode 100644 index 0000000..a9fa3da --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/stringp.htm @@ -0,0 +1,80 @@ +XLISP tringp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    stringp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (stringp expr)
    +
    expr - the expression to check
    +returns -  T  if the value is a +string, NIL otherwise
    +
    + +

    Description

    + +

    The 'stringp' predicate function checks if 'expr' is a string. + T  is returned if 'expr' is a +string, NIL is returned otherwise.

    + +

    Examples

    + +
    +(stringp "a")        ; returns T - string
    +
    +(setq a "hi there"
    +(stringp a)          ; returns T - evaluates to string
    +
    +(stringp #\a)        ; returns NIL - character
    +(stringp '(a b c))   ; returns NIL - list
    +(stringp 1)          ; returns NIL - integer
    +(stringp 1.2)        ; returns NIL - float
    +(stringp 'a)         ; returns NIL - symbol
    +(stringp #(0 1 2))   ; returns NIL - array
    +(stringp nil)        ; returns NIL - nil
    +
    + +

    See the +stringp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/sublis.htm b/docsrc/xlisp/xlisp-doc/reference/sublis.htm new file mode 100644 index 0000000..2724892 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/sublis.htm @@ -0,0 +1,129 @@ +XLISP sublis + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    sublis

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (sublis a-list expr [{:test | :test-not} test])
    +
    expr - the expression to substitute within, an atom
    +a-list - the association list to search
    +test - optional test function, default is eql
    +returns - the expression with substitutions
    +
    + +

    Description

    + +

    The 'sublis' function searches through an 'expr' and replaces each of the +elements in the 'expr' that match the car +of the elements of the association list 'a-list' with the + +cdr of elements of the 'a-list'. The 'expr' +with the substitutions, if any, is returned. You may specify your own test +with the ':test' and ':test-not' keywords followed by the 'test' you wish to +perform. The 'sublis' function is normally used with a dotted pair (A +. B) association list. It is possible to use a normal list pair +(A B) or a list of the form (A (B C)).

    + +

    Examples

    + +
    +(sublis '((a . b))   '(a a))            ; returns (B B)
    +(sublis '((a b))     '(a a))            ; returns ((B) (B))
    +(sublis '((a (b c))) '(a a))            ; returns (((B C)) ((B C)))
    +
    +(setq newlist '((a . 1)                 ; set up an association list
    +                (b . 2)
    +                (c . 3)))
    +
    +(sublis newlist '(a b c d e f b a c))   ; returns (1 2 3 D E F 2 1 3)
    +
    +(sublis newlist 'a)                     ; returns 1
    +
    +(setq mylist '((a my-a) (b his-b)       ; set up a non-dotted pair assoc list
    +               (c her-c) (d end)))
    +
    +(sublis mylist '(a b c d e f g))        ; returns ((MY-A) (HIS-B)
    +                                        ;          (HER-C) (END) E F G)
    +
    +(sublis mylist 'a)                      ; returns (MY-A)
    +
    +(setq numlist '((1 . a) (2 . b)) )      ; set up a new assoc list
    +
    +(defun mytest (x y) (princ ": ")        ; set up my own test function with 2 parameters
    +                    (princ x)           ; to see what SUBLIS does
    +                    (princ " ")
    +                    (princ y) (terpri)
    +                    t)                  ; always return T
    +
    +(sublis numlist '(3 1) :test mytest)    ; prints : (3 1) 1
    +                                        ; returns A - because the entire list succeeds
    +                                        ; with the test and so (1 . A) produces the
    +                                        ; returned value
    +
    +(sublis numlist '(1) :test-not mytest)  ; prints : (1) 1
    +                                        ;        : (1) 2
    +                                        ;        : 1 1
    +                                        ;        : 1 2
    +                                        ;        : NIL 1
    +                                        ;        : NIL 2
    +                                        ; returns (1) - because SUBLIS tried to match
    +                                        ; every list/sublist against each entry in the
    +                                        ; assoc list and failed because of the :TEST-NOT
    +                                        ; and so returned the original list unaltered
    +
    + +

    Note: The SUBLIS function can work with a list or string as the +'expr'. However, the default eql test does +not work with lists or strings, only symbols and numbers. To make this work, +you need to use the ':test' keyword along with +equal for 'test'.

    + +

    Common Lisp: Common LISP supports the use of the ':key' keyword +which specifies a function that is applied to each element of 'a-list' +before it is tested. XLISP does not support this.

    + +

    See the +sublis +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/subseq.htm b/docsrc/xlisp/xlisp-doc/reference/subseq.htm new file mode 100644 index 0000000..ebc0fb4 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/subseq.htm @@ -0,0 +1,83 @@ +XLISP subseq + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    subseq

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (subseq string start [end])
    +
    string - a string expression
    +start - an integer expression
    +end - an integer expression
    +returns - the substring between start and end
    +
    + +

    Description

    + +

    The 'subseq' function extracts a substring from 'string' starting with +the 'start' offset and ending with the 'end' offset. The 'start' offset has +a origin or 0. The substring is returned.

    + +

    Examples

    + +
    +(subseq "12345678" 0)     ; returns "12345678"
    +(subseq "12345678" 2)     ; returns "345678"
    +(subseq "12345678" 2 4)   ; returns "34"
    +(subseq "1234" 3)         ; returns "4"
    +
    +(subseq "1234" 4)         ; returns ""
    +(subseq "1234" 4 2)       ; returns ""
    +(subseq "1234" 5)         ; error: string index out of bounds - 5
    +
    + +

    Common Lisp: The 'subseq' function in Common Lisp is intended to +return a portion of a sequence, a sub-sequence. This function operates on +lists and vectors [one-dimensional arrays of data], basically ordered data. +Strings are just one of the valid types operated on by 'subseq' in Common +Lisp. The XLISP 'subseq' function only operates on strings.

    + +

    See the +subseq +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/subsetp.htm b/docsrc/xlisp/xlisp-doc/reference/subsetp.htm new file mode 100644 index 0000000..dff9b98 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/subsetp.htm @@ -0,0 +1,79 @@ +XLISP subsetp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    subsetp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  xm.lsp

    + +

    Syntax

    + +

    + +
    +
    (subsetp list1 list2)
    +
    listN - a list of symbols or numbers
    +returns -  T  if list1 is a subset of list2, NIL otherwise
    +
    + +

    + +

    In Nyquist, 'subsetp' is implemented as a Lisp function:

    + +
    +(defun subsetp (a b)
    +  (let ((result t))
    +    (dolist (elem a)
    +      (cond ((not (member elem b))
    +             (setf result nil)
    +             (return nil))))
    +    result))
    +
    + +

    Description

    + +

    The 'subsetp' function tests if all elements of 'list1' are +contained in 'list2'.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/subst.htm b/docsrc/xlisp/xlisp-doc/reference/subst.htm new file mode 100644 index 0000000..9fc00f0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/subst.htm @@ -0,0 +1,96 @@ +XLISP subst + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    subst

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (subst new-expr old-expr expr [{:test | :test-not} test])
    +
    old-expr - the expression to search for
    +new-expr - the expression to replace old-expr with
    +expr - the expression to substitute within, an atom or list
    +test - optional test function, default is eql
    +returns - the expression with substitutions
    +
    + +

    Description

    + +

    The 'subst' function searches through an 'expr' and replaces each of the +'old-expr' elements with the 'new-expr'. The 'expr' with the substitutions, +if any, is returned. You may specify your own test with the ':test' and +':test-not' keywords followed by the 'test' you wish to perform.

    + +

    Examples

    + +
    +(subst 'new 'old '(old mid dif))           ; returns (NEW MID DIF)
    +(subst '(a) 'old '(old mid dif))           ; returns ((A) MID DIF)
    +(subst "a" 'old '(old mid dif))            ; returns ("a" MID DIF)
    +
    +(defun mytest (x y) (princ x) (princ " ")  ; define a test function
    +                    (princ y) (terpri)     ; that prints the arguments
    +                    T )                    ; and always returns T
    +
    +(subst 'a 'b '(a b c d) :test 'mytest)     ; prints (A B C D) B   returns A
    +
    +(subst 'a 'b '(a b) :test-not 'mytest)     ; prints (A B) B
    +                                           ;        A B
    +                                           ;        (B) B
    +                                           ;        B B
    +                                           ;        NIL B    returns (A B)
    +
    + +

    Note: The 'subst' function can work with a list or string as the +'expr' However, the default eql test does +not work with lists or strings, only symbols and numbers. To make this work, +you need to use the ':test' keyword along with +equal for 'test'.

    + +

    Common Lisp: Common Lisp supports the use of the ':key' keyword +which specifies a function that is applied to each element of 'expr' before +it is tested. XLISP does not support this.

    + +

    See the +subst +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/subtraction.htm b/docsrc/xlisp/xlisp-doc/reference/subtraction.htm new file mode 100644 index 0000000..96ca6a9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/subtraction.htm @@ -0,0 +1,88 @@ +XLISP − + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +

    + +
    +
    (- expr1 ...)
    +
    exprN - integer or floating point number/expression
    +returns - the result of the subtraction
    +
    + +

    + +

    Description

    + +

    The '-' function subtracts one or more numbers from the first number +given and returns the result. If there is only one number as an argument, it +is negated.

    + +

    Examples

    + +
    +(- 1)         => -1
    +(- 1 2)       => -1
    +(- 1 2 3)     => -4
    +(- 1 2 3 4)   => -8
    +
    + +
    +> (print (- 1 2 (* 3.5 (/ 3.9 1.45))))
    +-10.4138
    +-10.4138
    +
    + +

    See  * , + / , print. +XLISP first prints the value on the screen, the second number is the +return value.

    + +

    See also:

    + + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/symbol-function.htm b/docsrc/xlisp/xlisp-doc/reference/symbol-function.htm new file mode 100644 index 0000000..e63dc8a --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/symbol-function.htm @@ -0,0 +1,67 @@ +XLISP symbol-name + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    symbol-function

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (symbol-function symbol)
    +
    symbol - an expression that evaluates to a symbol name
    +returns - the symbol's functional value
    +
    + +

    Description

    + +

    The 'symbol-function' function ... [this page was missing in the +original reference and still needs to be written].

    + +

    Examples

    + +
    +
    +
    + +

    See the +symbol-function +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/symbol-name.htm b/docsrc/xlisp/xlisp-doc/reference/symbol-name.htm new file mode 100644 index 0000000..8ab1ac2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/symbol-name.htm @@ -0,0 +1,80 @@ +XLISP symbol-name + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    symbol-name

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +

    + +
    +
    (symbol-name symbol)
    +
    symbol - an expression that evaluates to a symbol name
    +returns - the symbol's print name
    +
    + +

    + +

    Description

    + +

    The 'symbol-name' function takes the 'symbol' expression and returns the +printable string of the 'symbol'. If the 'symbol' had not existed, then it +will be created and interned into the +system symbol table +*obarray* , but with it's +value unbound and an empty property list.

    + +

    Examples

    + +
    +(symbol-name 'foo)        ; returns "FOO"
    +(symbol-name 'gleep)      ; returns "GLEEP"
    +
    +(setq my-symbol 'flop)    ; define MY-SYMBOL
    +(symbol-name my-symbol)   ; returns "FLOP"
    +
    + +

    XLISP Bug: The 'symbol-name' function signals a 'bad +argument type' error with the symbol +NIL [Nyquist 3.03 in +December 2010].

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/symbol-plist.htm b/docsrc/xlisp/xlisp-doc/reference/symbol-plist.htm new file mode 100644 index 0000000..3260cd1 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/symbol-plist.htm @@ -0,0 +1,85 @@ +XLISP symbol-plist + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    symbol-plist

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -   xlbfun.c

    + +

    Syntax

    + +
    +
    (symbol-plist symbol)
    +
    symbol - the symbol name with a property list
    +returns - the symbol's property list
    +
    + +

    Description

    + +

    The 'symbol-plist' function returns the actual property list from the +'symbol'. The 'symbol' must be an existing, bound variable, but it does not +need to have anything in it's property list.

    + +

    Property lists are lists attached to any user defined variables. The lists +are in the form of:

    + +
    +(name1 val1 name2 val2 ....)
    +
    + +

    Any number of properties may be attached to a single variable.

    + +

    Examples

    + +
    +(setq person 'bobby)                  ; create a var with a value
    +(putprop person 'boogie 'last-name)   ; add a LAST-NAME property
    +(putprop person 'disc-jockey 'job)    ; add a JOB property
    +(putprop person '(10 20 30) 'stats)   ; add a STATS list
    +
    +(symbol-plist person)                 ; returns the property list:
    +                                      ;   (STATS (10 20 30)
    +                                      ;    JOB DISC-JOCKEY
    +                                      ;    LAST-NAME BOOGIE)
    +
    + +

    See the +symbol-plist +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/symbol-value.htm b/docsrc/xlisp/xlisp-doc/reference/symbol-value.htm new file mode 100644 index 0000000..7097d22 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/symbol-value.htm @@ -0,0 +1,82 @@ +XLISP symbol-value + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    symbol-value

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (symbol-value symbol)
    +
    symbol - an expression that evaluates to a symbol name
    +returns - the symbol's value
    +
    + +

    Description

    + +

    The 'symbol-value' function takes the 'symbol' expression and returns +the current value of the 'symbol'.

    + +

    If the 'symbol' had not existed, then it will be created and +interned into the system symbol table +*obarray* , but with it's +value unbound and an empty property list. In this case of a previously +non-existant 'symbol', since it has no bound value, the 'symbol-value' +function will still report an error due to an unbound variable.

    + +

    Examples

    + +
    +(setq myvar 55)                   ; set MYVAR to value 55
    +(symbol-value 'myvar)             ; returns 55
    +(symbol-value 'floop)             ; error: unbound variable
    +
    +(setq my-symbol 'a)               ; set MY-SYMBOL to A
    +
    +(setq a '(contents of symbol a))  ; set A to value (CONTENTS OF SYMBOL A)
    +
    +(symbol-value my-symbol)          ; returns (CONTENTS OF SYMBOL A)
    +
    + +

    See the +symbol-value +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/symbolp.htm b/docsrc/xlisp/xlisp-doc/reference/symbolp.htm new file mode 100644 index 0000000..c27fd71 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/symbolp.htm @@ -0,0 +1,85 @@ +XLISP symbolp + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    symbolp

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xllist.c

    + +

    Syntax

    + +
    +
    (symbolp expr)
    +
    expr - the expression to check
    +returns -  T  if the expression +is a symbol, NIL otherwise
    +
    + +

    Description

    + +

    The 'symbolp' predicate function checks if an 'expr' is a valid symbol. + T  is returned if 'expr' is a +symbol, NIL is returned otherwise. An +'expr' that evaluates to an integer, function [subr or otherwise], and so +on is not a symbol. However, the quoted [un-evaluated] name of these +objects [like 'myarray] is a valid symbol.

    + +

    Examples

    + +
    +(symbolp (make-symbol "a"))       ; returns T - symbol
    +(symbolp 'a)                      ; returns T - symbol
    +
    +(symbolp #(1 2 3))                ; returns NIL - array
    +(symbolp (lambda (x) (print x)))  ; returns NIL - closure
    +(symbolp *standard-output*)       ; returns NIL - stream
    +(symbolp 1.2)                     ; returns NIL - float
    +(symbolp 2)                       ; returns NIL - integer
    +(symbolp object)                  ; returns NIL - object
    +(symbolp "hi")                    ; returns NIL - string
    +
    +(symbolp #'car)                   ; returns NIL - subr
    +(symbolp 'car)                    ; returns T - it is a symbol now
    +(symbolp '2)                      ; returns NIL - not a symbol
    +
    + +

    See the +symbolp +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/system.htm b/docsrc/xlisp/xlisp-doc/reference/system.htm new file mode 100644 index 0000000..e2f5888 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/system.htm @@ -0,0 +1,73 @@ +XLISP system + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    system

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  sys/unix/osstuff.c, sys/mac/macfun.c, sys/win/msvc/winfun.c

    + +

    Syntax

    + +
    +
    (system command)
    +
    command - the OS command string to be executed
    +returns -  T  if the command +was successful, the error code otherwise
    +
    + +

    Description

    + +

    The 'system' function will send the 'command' string to the underlying +operating system for execution. After execution of the 'command', the +'system' function will return a + T  result if the 'command' was +successful. If the 'command' was not successful, the numeric error code will +be returned. Any output from the 'command' execution will not be put in the +transcript file.

    + +

    Note: In Nyquist, this function is only defined to work on Unix +systems [including Linux and Mac OS X]. On +Windows systems, NIL is returned.

    + +

    Examples

    + +
    +(system "ls")     ; do a directory listing
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/t.htm b/docsrc/xlisp/xlisp-doc/reference/t.htm new file mode 100644 index 0000000..99e3e63 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/t.htm @@ -0,0 +1,71 @@ +XLISP t + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    t

    + +
    + +

    + + + + + + + + + + +
    Type:  -  system constant
    Source:  -  xlinit.c

    + +

    Syntax

    + +
    +
     t
    +
    + +

    Description

    + +

    The T system constant is built into XLISP. T represents 'true', +as oppossed to NIL , +representing 'false'.

    + +

    Examples

    + +
    +(setq myvar T)                     ; set MYVAR to True
    +(setq myvar 'T)                    ; T and 'T both evaluate to T
    +(if t (print "this will print")    ; if, then, else
    +      (print "this won't print"))
    +
    + +

    Note: Be careful with the T value. It is possible to do a +setq on T and set it to other values like +NIL. Some operations will still return +proper T or NIL values, but the system +will be in a bad state.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/tagbody.htm b/docsrc/xlisp/xlisp-doc/reference/tagbody.htm new file mode 100644 index 0000000..123167d --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/tagbody.htm @@ -0,0 +1,81 @@ +XLISP tagbody + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    tagbody

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (tagbody [expr ... ])
    +
    expr - expressions comprising the body of the block which may +contain gos or tags for +go
    +returns - NIL
    +
    + +

    Description

    + +

    The 'tagbody' special form is basically a 'block' construct that contains +a block of code [expressions] to evaluate. After the execution of the +'tagbody' 'exprs', NIL is returned. The +'tagbody' special form allows 'go-to' style branching within the 'block' +construct via the go special form. To allow +this, each 'expr' may be a tag or a form. The tag-symbol is the 'label' and +must exist somewhere within the 'block' that the go occurs within.

    + +

    Examples

    + +
    +(tagbody                   ; build the 'block'
    +   start (print "begin")   ; tag - start
    +         (GO end)
    +         (print "hello")   ; won't ever be reached
    +   end   (print "done"))   ; tag - END
    +                           ; prints  "begin" "done"
    +                           ; returns NIL
    +
    + +

    See the +tagbody +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/tan.htm b/docsrc/xlisp/xlisp-doc/reference/tan.htm new file mode 100644 index 0000000..81fd0de --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/tan.htm @@ -0,0 +1,76 @@ +XLISP tan + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    tan

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (tan expr)
    +
    expr - floating point number or expression
    +returns - the tangent of the number
    +
    + +

    Description

    + +

    The 'tan' function calculates the tangent of the 'expr' and returns the +result. The 'expr' is in radians.

    + +

    Examples

    + +
    +(tan 0.0)             ; returns 0
    +(tan 1.0)             ; returns 1.55741
    +(tan (/ 3.14159 2))   ; returns 753696
    +(tan 2.0)             ; returns -2.18504
    +(tan 3.0)             ; returns -0.142547
    +(tan 3.14159)         ; returns -2.65359e-06
    +(tan 4.5)             ; returns 4.63733
    +
    + +

    Common Lisp: Common Lisp allows for integer numbers, which +XLISP does not support for 'tan'.

    + +

    See the +tan +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/terpri.htm b/docsrc/xlisp/xlisp-doc/reference/terpri.htm new file mode 100644 index 0000000..2b5cdf2 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/terpri.htm @@ -0,0 +1,90 @@ +XLISP terpri + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    terpri

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c, xlprin.c

    + +

    Syntax

    + +
    +
    (terpri [dest])
    +
    dest - an optional destination, must be a file pointer or +stream, default is *standard-output*
    +returns - NIL
    +
    + +

    Description

    + +

    The 'terpri' function prints a new-line to the specified 'destination' +This will terminate the current print line for 'destination'. +NIL is always returned as the result. The +'destination' may be a file pointer or a stream. If there is no +'destination', *standard-output* is the +default.

    + +

    Examples

    + +
    +(terpri)                                 ; prints  #\Newline
    +
    +(setq f (open "pr" :direction :output))  ; create a file
    +(princ "hi" f)                           ; returns "hi"
    +(princ 727 f)                            ; returns 727
    +(princ "ho" f)                           ; returns "ho"
    +(terpri f)                               ; returns NIL
    +(close f)                                ; file contains hi727ho#\Newline
    +
    + +

    Common Lisp: Common Lisp specifies that print operations with a +'destination' of NIL will go to +*standard-output*. XLISP does not send the +output to *standard-output* with a +'destination' of NIL. Common Lisp also +specifies that a 'destination' of + T  will be sent to +*terminal-io*, which is not defined in XLISP by default. XLISP does not +allow  T  as a valid argument +for 'destination'.

    + +

    See the +terpri +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/third.htm b/docsrc/xlisp/xlisp-doc/reference/third.htm new file mode 100644 index 0000000..78fab50 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/third.htm @@ -0,0 +1,81 @@ +XLISP third + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    third

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlinit.c

    + +

    Syntax

    + +
    +
    (third expr)
    +
    expr - a list or list expression
    +returns - the third element of expr or +NIL
    +
    + +

    Description

    + +

    The 'third' function returns the third element of a list or list +expression. If the list is +NIL , +NIL is returned.

    + +

    Examples

    + +
    +(third '(1 2 3 4))                       ; returns 3
    +(third NIL)                              ; returns NIL
    +
    +(setq kids '(junie vickie cindy chris))  ; set up variable KIDS
    +(first kids)                             ; returns JUNIE
    +(second kids)                            ; returns VICKIE
    +(third kids)                             ; returns CINDY
    +(fourth kids)                            ; returns CHRIS
    +(rest kids)                              ; returns (VICKIE CINDY CHRIS)
    +
    + +

    Note: This function is set to the same code as +caddr.

    + +

    See the +third +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/throw.htm b/docsrc/xlisp/xlisp-doc/reference/throw.htm new file mode 100644 index 0000000..4b12de6 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/throw.htm @@ -0,0 +1,23 @@ +XLISP throw + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    throw

    + +
    + +

    See catch.

    + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/top-level.htm b/docsrc/xlisp/xlisp-doc/reference/top-level.htm new file mode 100644 index 0000000..6a0a8e3 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/top-level.htm @@ -0,0 +1,91 @@ +XLISP top-level + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    top-level

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c, xldbug.c

    + +

    Syntax

    + +
    +
    (top-level)
    +
    returns - never returns
    +
    + +

    Description

    + +

    The 'top-level' function aborts to the top level of XLISP. This may be +from within several levels of the +break loop. +This is valid for +breaks, +errors and +cerrors [continuable errors]. If 'top-level' +is evaluated while not in a +break loop , +a message is printed: + +

    +[ back to top level ]
    +
    + +

    This message does not cause XLISP to go into a +break loop. +The 'top-level' function never actually returns a value.

    + +

    Examples

    + +
    +(top-level)      ; [ back to top level ]
    +
    +(break "out")    ; break: out    (1st)
    +(break "twice")  ; break: twice  (2nd)
    +(top-level)      ; to exit out of the break loop
    +
    + +

    Keyboard: In the IBM PC and MS-DOS versions of XLISP, a 'Ctrl+c' +key sequence has the same effect as doing a (top-level). On a Macintosh, +this can be accomplished by a pull-down menu or a 'Command+t'. [I haven't +tested this with Nyquist.]

    + +

    See the +top-level +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/trace.htm b/docsrc/xlisp/xlisp-doc/reference/trace.htm new file mode 100644 index 0000000..f81f621 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/trace.htm @@ -0,0 +1,93 @@ +XLISP trace + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    trace

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (trace function ... )
    +
    function - an unquoted function
    +returns - the trace list
    +
    + +

    Description

    + +

    The 'trace' special form allows the tracing of user or system functions. +'trace' returns a list containing the current set of functions that are +being traced. The 'function' does not have to be currently defined, it can +be created as part of the execution. The trace output consists of entry and +exit information.

    + +

    At entry and exit of a traced 'function', lines will be printed of the +form:

    + +
    +Entering: function, Argument list: arg-list
    +Exiting: function, Value: return-value
    +
    + +

    A list of all currently traced functions can be found in the +*tracelist* system variable.

    + +

    Examples

    + +
    +(defun foo (x) (print (car x)))  ; define FOO
    +(trace 'foo)                     ; returns (FOO)
    +(trace 'car)                     ; returns (CAR FOO)
    +
    +(foo '(a))                       ; Entering: FOO, Argument list: ((A))
    +                                 ;  Entering: CAR, Argument list: ((A))
    +                                 ;  Exiting: CAR, Value: A
    +                                 ; A
    +                                 ; Exiting: FOO, Value: A
    +                                 ; returns A
    +
    + +

    Common Lisp: The XLISP 'trace' function does not support any +keyword options, which Common Lisp allows.

    + +

    See the +trace +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/truncate.htm b/docsrc/xlisp/xlisp-doc/reference/truncate.htm new file mode 100644 index 0000000..421ca7f --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/truncate.htm @@ -0,0 +1,74 @@ +XLISP truncate + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    truncate

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (truncate expr)
    +
    expr - integer or floating point number or expression
    +returns - the result of truncating expr
    +
    + +

    Description

    + +

    The 'truncate' function takes the 'expr' and truncates it to an integer +value and returns this result.

    + +

    Examples

    + +
    +(truncate 123.456)   ; returns 123
    +(truncate -1.49)     ; returns -1
    +(truncate -1.59)     ; returns -1
    +(truncate 123)       ; returns 123
    +(truncate 123.999)   ; returns 123
    +
    + +

    Common Lisp: Common LISP allows an optional division parameter, +which XLISP does not support.

    + +

    See the +truncate +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/type-of.htm b/docsrc/xlisp/xlisp-doc/reference/type-of.htm new file mode 100644 index 0000000..1e01c24 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/type-of.htm @@ -0,0 +1,103 @@ +XLISP type-of + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    type-of

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlsys.c

    + +

    Syntax

    + +
    +
    (type-of expr)
    +
    expr - an expression to check
    +returns - the type of the expression
    +
    + +

    Description

    + +

    The 'type-of' function returns the type of the expression.

    + +
      +
    • SYMBOL - for symbols
    • +
    • OBJECT - for objects
    • +
    • CONS - for conses
    • +
    • SUBR - for built-in functions
    • +
    • FSUBR - for special forms
    • +
    • CLOSURE - for defined functions
    • +
    • STRING - for strings
    • +
    • FIXNUM - for integers
    • +
    • FLONUM - for floating point numbers
    • +
    • CHARACTER - for characters
    • +
    • FILE-STREAM - for file pointers
    • +
    • UNNAMED-STREAM - for unnamed streams
    • +
    • ARRAY - for arrays
    • +
    + +

    Examples

    + +
    +(type-of NIL)                             ; returns NIL
    +(type-of '#(1 2 3))                       ; returns ARRAY
    +(type-of (lambda (x) (print x)))          ; returns CLOSURE
    +(type-of '(a b))                          ; returns CONS
    +(type-of #'savefun)                       ; returns CLOSURE
    +(type-of '(a . b))                        ; returns CONS
    +(type-of *standard-output*)               ; returns FILE-STREAM
    +(type-of 1.2)                             ; returns FLONUM
    +(type-of #'do)                            ; returns FSUBR
    +(type-of 1)                               ; returns FIXNUM
    +(type-of object)                          ; returns OBJECT
    +(type-of "str")                           ; returns STRING
    +(type-of #'car)                           ; returns SUBR
    +(type-of 'a)                              ; returns SYMBOL
    +(type-of #\a)                             ; returns CHARACTER
    +(type-of (make-string-input-stream "a"))  ; returns UNNAMED-STREAM
    +
    + +

    Common Lisp: The XLISP and Common Lisp 'type-of' functions are +basically the same. Differences between the two can occur in what the types +are called [like CHARACTER in XLISP and STANDARD-CHAR in Common Lisp]. Also, +Common Lisp can give additional information. For strings, it returns a list +of the form (SIMPLE-STRING 32) where the number 32 is the string size.

    + +

    See the +type-of +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/union.htm b/docsrc/xlisp/xlisp-doc/reference/union.htm new file mode 100644 index 0000000..d728399 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/union.htm @@ -0,0 +1,80 @@ +XLISP union + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    union

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp function (closure)
    Source:  -  xm.lsp

    + +

    Syntax

    + +

    + +
    +
    (union list1 list2)
    +
    listN - a list of symbols or numbers
    +returns - the union of list1 and list2
    +
    + +

    + +

    In Nyquist, 'union' is implemented as a Lisp function:

    + +
    +(defun union (a b)
    +  (let (result)
    +    (dolist (elem a)
    +      (if (not (member elem result)) (push elem result)))
    +    (dolist (elem b)
    +      (if (not (member elem result)) (push elem result)))
    +    result))
    +
    + +

    Description

    + +

    The 'union' function computes the union of two lists. The +result is a list containing all elements of both lists, where every +element appears exactly once.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/unless.htm b/docsrc/xlisp/xlisp-doc/reference/unless.htm new file mode 100644 index 0000000..d54cbd0 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/unless.htm @@ -0,0 +1,82 @@ +XLISP unless + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    unless

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (unless test [expr ... ])
    +
    test - an expression, NIL or +non-NIL
    +expr - expressions comprising a body of code
    +returns - the value of the last expression or +NIL
    +
    + +

    Description

    + +

    The 'unless' special form executes the 'expr' forms if 'test' evaluates +to a NIL value. If 'test' is +NIL , the value of the last +'expr' is returned as the result. If 'test' is +non-NIL , +NIL is returned with none of 'expr' +evaluated.

    + +

    Examples

    + +
    +(unless NIL)                    ; returns NIL
    +(unless T)                      ; returns NIL
    +
    +(unless NIL (print "hi") 'foo)  ; prints "hi"  returns FOO
    +
    +(unless (listp "a")
    +        (print "not a list"))   ; prints  "not a list"
    +                                ; returns "not a list"
    +
    + +

    See the +unless +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/untrace.htm b/docsrc/xlisp/xlisp-doc/reference/untrace.htm new file mode 100644 index 0000000..5576b8e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/untrace.htm @@ -0,0 +1,86 @@ +XLISP untrace + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    untrace

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (untrace function ... )
    +
    function - a function name
    +returns - the trace list
    +
    + +

    Description

    + +

    The 'untrace' function removes 'function' from the current list of traced +functions. 'untrace' returns a list containing the current set of functions +that are being traced. If the 'function' does currently exist or is +currently be traced, there will be no error reported. If there are no +functions being traced, a NIL is +returned. A list of all currently traced functions can be found in the +*tracelist* system variable.

    + +

    Examples

    + +
    +(defun foo (x) (print (car x)))  ; define FOO
    +(trace 'foo)                     ; returns (FOO)
    +
    +(foo '(a))                       ; Entering: FOO, Argument list: ((A))
    +                                 ; A
    +                                 ; Exiting: FOO, Value: A
    +                                 ; returns A
    +
    +(untrace 'foo)                   ; returns NIL
    +(untrace 'glip)                  ; returns NIL
    +
    +(foo '(a))                       ; prints A  returns A
    +
    + +

    Common Lisp: The XLISP 'untrace' function does not support any +options, which Common Lisp allows.

    + +

    See the +untrace +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/unwind-protect.htm b/docsrc/xlisp/xlisp-doc/reference/unwind-protect.htm new file mode 100644 index 0000000..1f40d74 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/unwind-protect.htm @@ -0,0 +1,137 @@ +XLISP unwind-protect + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    unwind-protect

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (unwind-protect protect-form clean-up-form ... )
    +
    protect-form - a form that is to be protected
    +clean-up-form - a sequence forms to execute after protect-form
    +returns - the value of protect-form
    +
    + +

    Description

    + +

    The 'unwind-protect' special form allows the protecting [trapping] of +all forms of exit from the 'protect-form'. The exits that are trapped +include errors, throw , return and go. The 'clean-up-form' will be executed in +all cases, when there is an exit from 'protect-form' and when the form does +not have exit. 'unwind-protect' will return the result from the +'protect-form', not from the 'clean-up-forms'. Errors or exits that occur in +the 'clean-up-form' are not protected. It is possible to trap these with +another 'unwind-protect'.

    + +

    + +

    Note: 'unwind-protext' will not protect against errors signalled +by built-in functions if +*breakenable* is not +NIL.

    + +

    + +

    Examples

    + +
    +(unwind-protect
    +  (+ 2 2)                           ; protected form
    +  (print "an exit"))                ; clean up form
    +                                    ; prints "an exit"
    +                                    ; returns 4
    +
    + +
    +(setq *breakenable* nil)            ; to turn off break loop traps
    +
    +(unwind-protect
    +  (+ 1 "2")                         ; protected form
    +  (print "something happened"))     ; clean up form
    +                                    ; error: bad argument type - "2"
    +                                    ; prints "something happened"
    +
    + +
    +(catch 'mytag
    +  (unwind-protect
    +    (throw 'mytag)                  ; protected form
    +    (print "an exit")))             ; clean up form
    +                                    ; prints "an exit"
    +
    + +
    +(setq *breakenable* nil)            ; to turn off break loop traps
    +
    +(unwind-protect
    +  (throw 'notag)                    ; protected form
    +  (print "an exit"))                ; clean up form
    +                                    ; error: no target for THROW
    +                                    ; prints "an exit"
    +
    + +
    +(prog () (print "start")
    +         (unwind-protect
    +           (go end)                 ; protected form
    +           (print "an exit"))       ; clean-up form
    +    end  (print "end"))             ; prints "start"
    +                                    ; prints "an exit"
    +                                    ; prints "end"
    +
    + +
    +(prog () (print "start")
    +         (unwind-protect
    +           (return "I'm done")      ; protected form
    +           (print "but first"))     ; clean-up form
    +         (print "won't get here"))  ; prints "start"
    +                                    ; prints "but first"
    +                                    ; returns "I'm done"
    +
    + +

    See the +unwind-protect +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/upper-case-p.htm b/docsrc/xlisp/xlisp-doc/reference/upper-case-p.htm new file mode 100644 index 0000000..406f546 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/upper-case-p.htm @@ -0,0 +1,76 @@ +XLISP upper-case-p + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    upper-case-p

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlstr.c

    + +

    Syntax

    + +
    +
    (upper-case-p char)
    +
    char - a character expression
    +returns -  T  if the character +is upper case, NIL otherwise
    +
    + +

    Description

    + +

    The 'upper-case-p' predicate function checks if the 'char' expression is +an upper case character. If 'char' is upper case a + T  is returned, otherwise a +NIL is returned. Upper case characters are +'A' [ASCII decimal value +65] through 'Z' [ASCII +decimal value 90].

    + +

    Examples

    + +
    +(upper-case-p #\A)   ; returns T
    +(upper-case-p #\a)   ; returns NIL
    +(upper-case-p #\1)   ; returns NIL
    +(upper-case-p #\[)   ; returns NIL
    +
    + +

    See the +upper-case-p +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/vector.htm b/docsrc/xlisp/xlisp-doc/reference/vector.htm new file mode 100644 index 0000000..4ef325e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/vector.htm @@ -0,0 +1,73 @@ +XLISP vector + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    vector

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlbfun.c

    + +

    Syntax

    + +
    +
    (vector [expr ... ])
    +
    expr - an expression
    +returns - the new vector
    +
    + +

    Description

    + +

    The 'vector' function creates an initialized vector and returns it as the +result. 'vector' is essentially a fast method to do a one-dimensional make-array with initial data in the +vector.

    + +

    Examples

    + +
    +(vector 'a 'b 'c)        ; returns #(A B C)
    +(vector '(a b) '(c d))   ; returns #((A B) (C D))
    +(vector)                 ; returns #()
    +(vector NIL)             ; returns #(NIL)
    +(vector 'a () 4 "s")     ; returns #(A NIL 4 "s")
    +
    + +

    See the +vector +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/when.htm b/docsrc/xlisp/xlisp-doc/reference/when.htm new file mode 100644 index 0000000..5129f6e --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/when.htm @@ -0,0 +1,82 @@ +XLISP when + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    when

    + +
    + +

    + + + + + + + + + + +
    Type:  -  special form (fsubr)
    Source:  -  xlcont.c

    + +

    Syntax

    + +
    +
    (when test [expr ... ])
    +
    test - an expression, NIL +or non-NIL
    +expr - expressions comprising a body of code
    +returns - the value of the last expression or +NIL
    +
    + +

    Description

    + +

    The 'when' macro executes the 'expr' forms if 'test' evaluates to a +non-NIL value. If 'test' is +non-NIL , the value of the +last 'expr' is returned as the result. If 'test' is +NIL , +NIL is returned with none of 'expr' +evaluated.

    + +

    Examples

    + +
    +(when NIL)                  ; returns NIL
    +(when T)                    ; returns T
    +
    +(when T (print "hi") 'foo)  ; prints "hi"  returns FOO
    +
    +(when (listp '(a))
    +      (print "a list"))     ; prints  "a list"
    +                            ; returns "a list"
    +
    + +

    See the +when +special form in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/while.htm b/docsrc/xlisp/xlisp-doc/reference/while.htm new file mode 100644 index 0000000..2a2f8da --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/while.htm @@ -0,0 +1,81 @@ +XLISP while + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    while

    + +
    + +

    + + + + + + + + + + +
    Type:  -  Lisp macro (closure)
    Source:  -  misc.lsp

    + +

    Syntax

    + +

    + +
    +
    (while condition body)
    +
    condition - test expression for terminating the 'while' loop
    +
    body - Lisp expressions to be executed inside the loop
    +returns - returns NIL or a value defined by +(return expr) inside body
    +
    + +

    + +

    In Nyquist, 'while' is implemented as a Lisp macro:

    + +
    +(defmacro while (condition &rest body)
    +  `(prog () loop (if ,condition () (return)) ,@body (go loop)))
    +
    + +

    Description

    + +

    The 'while' macro implements a conventional 'while' loop. If +the 'condition' evaluates to true, the expressions in the in the +'body' are evaluated, then the 'condition' is tested again. If +the 'condition' evaluates to false, the 'while' loop terminates. The +'while' macro returns NIL unless a (return expr) is evaluated in the 'body', +in which case the value of 'expr' is returned.

    + +

    Examples

    + +
    +
    +
    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/write-byte.htm b/docsrc/xlisp/xlisp-doc/reference/write-byte.htm new file mode 100644 index 0000000..6ceab26 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/write-byte.htm @@ -0,0 +1,92 @@ +XLISP write-byte + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    write-byte

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (write-byte expr [dest])
    +
    expr - an integer expression
    +dest - an optional destination, must be a file pointer or stream, +default is *standard-output*
    +returns - the byte as an integer
    +
    + +

    Description

    + +

    The 'write-byte' function writes the 'expr' as a single byte to the +specified 'destination'. Only the 'expr' byte is written. The 'expr' must be +an integer expression. The 'expr' is returned as the result. The +'destination' may be a file pointer or a stream. If there is no +'destination', *standard-output* is the +default.

    + +

    Examples

    + +
    +(write-byte 67)                          ; prints C  returns 67
    +
    +(setq fp (open "t" :direction :output))  ; create file
    +(write-byte 65 fp)                       ; returns 65
    +(write-byte 66 fp)                       ; returns 66
    +(write-byte 10 fp)                       ; returns 10
    +(close fp)                               ; returns NIL
    +
    +(read (open "t" :direction :input))      ; returns AB
    +
    + +

    Common Lisp: Common Lisp specifies that print operations with a +'destination' of NIL will go to +*standard-output*. XLISP does not send the +output to *standard-output* with a +'destination' of NIL. Common Lisp also +specifies that a 'destination' of + T  will be sent to +*terminal-io*, which is not defined in XLISP by default. XLISP does not +allow  T  as a valid argument +for 'destination'.

    + +

    See the +write-byte +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/write-char.htm b/docsrc/xlisp/xlisp-doc/reference/write-char.htm new file mode 100644 index 0000000..d4075cd --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/write-char.htm @@ -0,0 +1,92 @@ +XLISP write-char + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    write-char

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (write-char char-expr [dest])
    +
    char-expr - a character expression
    +dest - an optional destination, must be a file pointer or stream, +default is *standard-output*
    +returns - the character
    +
    + +

    Description

    + +

    The 'write-char' function writes the 'char-expr' to the specified +'destination'. Only the 'char-expr' is written. The 'char-expr' must be a +character expression. The 'char-expr' is returned as the result. The +'destination' may be a file pointer or a stream. If there is no +'destination', *standard-output* is the +default.

    + +

    Examples

    + +
    +(write-char #\C)                         ; prints  C
    +
    +(setq fp (open "t" :direction :output))  ; create file
    +(write-char #\A fp)                      ; returns #\A
    +(write-char #\B fp)                      ; returns #\B
    +(write-char #\Newline fp)                ; returns #\Newline
    +(close fp)                               ; returns NIL
    +
    +(read (open "t" :direction :input))      ; returns AB
    +
    + +

    Common Lisp: Common Lisp specifies that print operations with a +'destination' of NIL will go to +*standard-output*. XLISP does not send the +output to *standard-output* with a +'destination' of NIL. Common Lisp also +specifies that a 'destination' of + T  will be sent to +*terminal-io*, which is not defined in XLISP by default. XLISP does not +allow  T  as a valid argument +for 'destination'.

    + +

    See the +write-char +function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/write-float.htm b/docsrc/xlisp/xlisp-doc/reference/write-float.htm new file mode 100644 index 0000000..f5bce92 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/write-float.htm @@ -0,0 +1,80 @@ +XLISP write-float + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    write-float

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (write-float float [stream [length]])
    +
    float - the floating point number to write
    +stream - the output stream [default is standard output]
    +length - the length of the float in bytes [default is 4, +legal values are -4, -8, 4, and 8]
    +returns - the float
    +
    + +

    Description

    + +

    The 'write-float' function writes a binary floating point +number to an output stream, created by the +open-binary function.

    + +

    Note: Integers and floats are assumed to be +big-endian [high-order byte first] and signed, +regardless of the platform. To read little-endian +format, use a negative number for the length, e.g. '-4' indicates a +4-bytes, low-order byte first. The file should be +opened in binary mode.

    + +

    Examples

    + +
    +
    +
    + +

    See also read-int, +write-int, +read-float, +bigendianp, +open-binary.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/write-int.htm b/docsrc/xlisp/xlisp-doc/reference/write-int.htm new file mode 100644 index 0000000..131f9ae --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/write-int.htm @@ -0,0 +1,79 @@ +XLISP write-int + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    write-int

    + +
    + +

    + + + + + + + + + + +
    Type:  -  function (subr)
    Source:  -  xlfio.c

    + +

    Syntax

    + +
    +
    (write-int integer [stream [length]])
    +
    integer - the integer to write
    +stream - the output stream [default is standard output]
    +length - the length of the integer in bytes [default is 4]
    +returns - the integer
    +
    + +

    Description

    + +

    The 'write-int' function writes an integer to a binary output +stream, created by the +open-binary function.

    + +

    Note: Integers and floats are assumed to be +big-endian [high-order byte first] and signed, +regardless of the platform. To read little-endian +format, use a negative number for the length, e.g. '-4' indicates a +4-bytes, low-order byte first. The file should be +opened in binary mode.

    + +

    Examples

    + +
    +
    +
    + +

    See also read-int, +read-float, +write-float, +bigendianp, +open-binary.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/reference/zerop.htm b/docsrc/xlisp/xlisp-doc/reference/zerop.htm new file mode 100644 index 0000000..014101b --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/reference/zerop.htm @@ -0,0 +1,81 @@ +XLISP zerop + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    zerop

    + +
    + +

    + + + + + + + + + + +
    Type:  -  predicate function (subr)
    Source:  -  xlmath.c

    + +

    Syntax

    + +
    +
    (zerop expr)
    +
    expr - the numeric expression to check
    +returns -  T  if the number is +zero, NIL otherwise
    +
    + +

    Description

    + +

    The 'zerop' predicate function checks to see if the number 'expr' is +zero.  T  is returned if the +number is zero, NIL is returned otherwise. +An error is generated if the 'expr' is not a numeric expression:

    + +
    +error: bad argument type
    +
    + +

    Examples

    + +
    +(zerop 0)                ; returns T
    +(zerop 0.0)              ; returns T
    +(zerop 99999.9)          ; returns NIL
    +(zerop -0.000000000002)  ; returns NIL
    +
    +(zerop 'a)               ; error: bad argument type
    +(setq a 0)               ; set value of A to 0
    +(zerop a)                ; returns T
    +
    + +

    See the +zerop +predicate function in the XLISP 2.0 manual.

    + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/start.htm b/docsrc/xlisp/xlisp-doc/start.htm new file mode 100644 index 0000000..c8154c9 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/start.htm @@ -0,0 +1,86 @@ + + +XLisp + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Nyquist / XLISP 2.0

    + +
    + +
      +
    • Preface - what's this all about
    • +
    + + + + + + + + + + + +
    + +

    If you find bugs in these documents please write to:

    + + + +

    If you send me email please write the words XLISP or NYQUIST as big as +possible into the subject line in case you get catched by the spam filter. +I usually sort out my emails by hand but often do not have the time to +open them all during sorting.

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/binary-io.htm b/docsrc/xlisp/xlisp-doc/tutorials/binary-io.htm new file mode 100644 index 0000000..73fce58 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/binary-io.htm @@ -0,0 +1,79 @@ + + +Binary File I/O + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Binary File I/O

    + +
    + + + +
    +(defun hexdump (filename &key (start 0) end)
    +  (if (and (integerp start) (not (minusp start)))
    +      (error "not a non-negative integer" start))
    +  (or (null end)
    +      (and (integerp end) (not (minusp end)))
    +      (error "not a non-negative integer" end))
    +  (let ((file (open-binary filename)))
    +
    + + + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/environment.htm b/docsrc/xlisp/xlisp-doc/tutorials/environment.htm new file mode 100644 index 0000000..2ce9a99 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/environment.htm @@ -0,0 +1,530 @@ + + +Environment + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Environment

    + +
    + + + +
    + +

    Global and Lexical Binding

    + +
    + +

    From the XLISP perspective, there are two kinds of bindings:

    + +
      + +
    1. Global bindings are bindings to symbols in the *obarray*.

    2. + +
    3. Lexical bindings are bindings in a local association list

    4. + +
    + +

    There is a third kind of binding, 'dynamical binding', used by progv.

    + +

      Back to top

    + + + +
    + +

    Lexical Scope

    + +
    + +

    Have you ever wondered why this doesn't work:

    + +
    +(defun print-x ()
    +  (print x))  ; unbound variable X
    +
    +(let ((x 'hello))
    +  (print-x))
    +error: unbound variable - X
    +
    + +

    The answer is twofold:

    + +
      + +
    1. The 'print-x' function is defined at the global +top-level, where no lexical environment exists.

    2. + +
    3. The 'print-x' function is called inside a +let form, where a lexical variable +binding for 'x' exists, but 'print-x' is evaluated at the +global top-level, where it was defined, so +'print-x' cannot see the lexical +let binding of 'x' and +signals an 'unbound variable' error.

    4. + +
    + +

    Here is a version that seems to work:

    + +
    +(let ((x 'hello))
    +
    +  (defun print-x ()
    +    (print x))
    +
    +  (print-x))
    +HELLO
    +
    + +
      + +
    1. The 'print-x' function is defined inside a +let form.

    2. + +
    3. The 'print-x' function is called inside the same +let form as where it was defined, so +'print-x' prints the lexical +let binding +of 'x'.

    4. + +
    + +

    But here again a version that does not behave as wanted:

    + +
    +(let ((x 'lexical))
    +  (defun print-x ()
    +    (print x)))
    +
    +(let ((x 'hello))
    +  (print-x))
    +LEXICAL
    +
    + +
      + +
    1. The 'print-x' function is defined inside a +let form.

    2. + +
    3. The 'print-x' function is called inside a different +let form as where it was defined, so +'print-x' prints the lexical +let binding of 'x' from +the place where it was defined.

    4. + +
    + +

    Somehow it seems to be important where a function was defined.

    + + + +
    + +

    Closures

    + +
    + +

    Here a Lisp function, defined inside a +let form:

    + +
    +(let ((a 'A) (b 'B) (c 'C))
    +
    +  (defun print-abc ()
    +    (format t ";; a = ~s, b = ~s, c = ~s~%" a b c))
    +
    +  )  ; end of LET
    +
    + +

    Now 'print-abc' is called outside the +let form:

    + +
    +> (print-abc)
    +;; a = A, b = B, c = C
    +NIL
    +
    + +

    The lexical let variables 'a', 'b', +and 'c' have become a permanent part of the 'print-abc' +function.

    + +

      Back to top

    + + + +
    + +

    Lisp Objects

    + +
    + +

    The following examples are based on Chapter 13 of 'Paradigms +of Artificial Intelligence Programming' by Peter Norvig. The +code has been ported from Common Lisp to XLISP, all +examples have been tested with Nyquist 3.03 in December +2010.

    + +

    The function 'new-account' creates account objects, which +are implemented as closures encapsulating three variables 'name', 'balance', +and 'interest-rate'. An account object also +encapsulates functions to handle five messages ':withdraw', ':deposit', +':balance', ':name', and ':interest', to which the object can respond:

    + +
    +(defun new-account (name &optional (balance 0.0) (interest-rate 0.06))
    +  #'(lambda (message)
    +      (case message
    +        (:withdraw #'(lambda (amount)
    +                       (if (<= amount balance)
    +                           (setq balance (- balance amount))
    +                           'insufficient-funds)))
    +        (:deposit  #'(lambda (amount)
    +                       (setq balance (+ balance amount))))
    +        (:balance  #'(lambda () balance))
    +        (:name     #'(lambda () name))
    +        (:interest #'(lambda ()
    +                       (setq balance (+ balance (* interest-rate balance))))))))
    +
    + +

    An account object can only do one thing, receive a message and return the +appropriate function to execute that message. This function is called the +'method' that implements the message.

    + +

    The function 'get-method' finds the method that implements a +message for a given object:

    + +
    +(defun get-method (object message)
    +  (funcall object message))
    +
    + +

    The function 'send-message' gets the method and applies it +to a list of arguments:

    + +
    +(defun send-message (object message &rest args)
    +  (apply (get-method object message) args))
    +
    + +

    Here are some examples how it works:

    + +
    +> (setq a1 (new-account "My Name" 1000.0))
    +#<Closure...>
    +
    +> (send-message a1 :name)
    +"My Name"
    +
    +> (send-message a1 :balance)
    +1000.0
    +
    +> (send-message a1 :withdraw 500.0)
    +500
    +
    +> (send-message a1 :deposit 123.45)
    +623.45
    +
    +> (send-message a1 :balance)
    +623.45
    +
    + +

      Back to top

    + + + +
    + +

    Generic Functions

    + +
    + +

    The 'send-message' syntax is awkward, as it is different +from normal Lisp function calling syntax, and it doesn't fit in with the +other Lisp tools.

    + +

    For example if we want to say:

    + +
    +(mapcar :balance accounts)
    +
    + +

    with 'send-message' we would have to write:

    + +
    +(mapcar #'(lambda (acc)
    +            (send-message acc :balance))
    +        accounts)
    +
    + +

    We could fix this problem by defining a generic function 'withdraw' like +this:

    + +
    +(defun withdraw (object &rest args)
    +  (apply (get-method object :withdraw) args))
    +
    + +

    Now we can write:

    + +
    +(withdraw account x)
    +
    + +

    instead of:

    + +
    +(send-message account :withdraw x)
    +
    + +

      Back to top

    + + + +
    + +

    Classes

    + +
    + +

    The macro 'define-class' defines a class with its associated +message handling methods. It also defines a generic function +for each message. Finally, it allows the programmer to make a distinction +between instance variables, associated with each object, and class +variables, associated with a class and shared by all members of the +class.

    + +
    +(defmacro define-class (class ivars cvars &rest methods)
    +  `(let ,cvars
    +     (mapcar #'ensure-generic-function ',(mapcar #'first methods))
    +     (defun ,class ,ivars
    +       #'(lambda (message)
    +           (case message
    +             ,@(mapcar #'make-clause methods))))))
    +
    + +

    The 'make-clause' function translates a message from +'define-class' into a +case clause.

    + +
    +(defun make-clause (clause)
    +  `(,(car clause) #'(lambda ,(cadr clause) ,@(cddr clause))))
    +
    + +

    The 'ensure-generic-function' function defines a dispatch +function for a message, unless it already has been defined as +one:

    + +
    +(defun ensure-generic-function (message)
    +  (unless (generic-function-p message)
    +    (let ((fn #'(lambda (object &rest args)
    +                  (apply (get-method object message) args))))
    +      (setf (symbol-function message) fn)
    +      (putprop message fn 'generic-function))))
    +
    + +

    The 'generic-function-p' function tests if a function has +been defined as a generic function:

    + +
    +(defun generic-function-p (name)
    +  (and (fboundp name)
    +       (eq (get name 'generic-function) (symbol-function name))))
    +
    + +

    Now we can define the 'account' class with 'define-class'. +We make 'interest-rate' a class variable, shared by all +accounts:

    + +
    +(define-class account (name &optional (balance 0.0)) ((interest-rate 0.06))
    +  (withdraw (amount)
    +    (if (<= amount balance)
    +        (setq balance (- balance amount))
    +        'insufficient-funds))
    +  (deposit (amount)
    +    (setq balance (+ balance amount)))
    +  (balance ()
    +    balance)
    +  (name ()
    +    name)
    +  (interest ()
    +    (setq balance (+ balance (* interest-rate balance)))))
    +
    + +

    Macroexpansion:

    + +
    +(let ((interest-rate 0.06))
    +  (mapcar (function ensure-generic-function)
    +          (quote (withdraw deposit balance name interest)))
    +  (defun account (name &optional (balance 0))
    +    (function (lambda (message)
    +      (case message
    +        (withdraw (function (lambda (amount)
    +                              (if (<= amount balance)
    +                                  (setq balance (- balance amount))
    +                                  (quote insufficient-funds)))))
    +        (deposit  (function (lambda (amount)
    +                              (setq balance (+ balance amount)))))
    +        (balance  (function (lambda nil balance)))
    +        (name     (function (lambda nil name)))
    +        (interest (function (lambda nil
    +                              (setq balance (+ balance (* interest-rate balance)))))))))))
    +
    + +

    Here is how it works:

    + +
    +> (setq a2 (account "my-name" 2000.0)
    +#<Closure...>
    +
    +> (balance a2)
    +2000
    +
    +> (deposit a2 42.0)
    +2042
    +
    +> (interest a2)
    +2164.52
    +
    + +

      Back to top

    + + + +
    + +

    Delegation

    + +
    + +

    Here is a 'password-account' class with two +message clauses:

    + +
    +(define-class password-account (password acc) ()
    +  (change-password (pass new-pass)
    +    (if (equal pass password)
    +        (setq password new-pass)
    +        'wrong-password))
    +  (t (pass &rest args)
    +    (if (equal pass password)
    +        (if args
    +            (apply message (cons acc args))
    +            (funcall message acc))
    +        'wrong-password)))
    +
    + +

    The definition of 'password-account' depends on some +internal details of 'define-class'. It uses 't' as +a catch-all clause to case +and uses the dispatch variable 'message'. Usually it is not a good idea to +rely on details of other code, so this will be changed below.

    + +

    Here is how 'password-account' works:

    + +
    +> (setq a3 (password-account "secret" a2))
    +#<Closure...>
    +
    +> (balance a3 "secret")
    +2164.52
    +
    +> (withdraw a3 "guess" 2000.0)
    +WRONG-PASSWORD
    +
    +> (withdraw a3 "secret" 2000.0)
    +164.52
    +
    + +

    Here is a 'limited-account' class, where only a limited +amount of money can be withdrawn at any time:

    + +
    +(define-class limited-account (limit acc) ()
    +  (withdraw (amount)
    +    (if (<= amount limit)
    +        (withdraw acc amount)
    +        'over-limit))
    +  (t (&rest args)
    +    (if args
    +        (apply message (cons acc args))
    +        (funcall message acc))))
    +
    + +

    The 'withdraw' message is redefined to check if the account limit is +exceeded, while the 't' clause passes all other messages unchanged:

    + +
    +> (setq a4 (password-account "pass"
    +             (limited-account 100.0
    +               (account "limited" 500.0)))
    +#<Closure...>
    +
    +
    +
    +
    +
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/file-io.htm b/docsrc/xlisp/xlisp-doc/tutorials/file-io.htm new file mode 100644 index 0000000..19f6862 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/file-io.htm @@ -0,0 +1,349 @@ +XLISP: An Object-oriented Lisp + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    File I/O

    + +
    + +
      +
    1. File I/O Examples - from the XLISP 2.0 manual, by David Betz
    2. + +
    3. Files and Directories
    4. + +
    5. Testing Existence
    6. + +
    7. Text File I/O
    8. + +
    9. Binary File I/O
    10. +
    + + + +
    + +

    1  File I/O Examples

    + + + +
    + +

    1.1  Input from a File

    + +
    + +

    The basics of file i/o with XLISP:

    + +
      + +
    • To open a file for input, use the +open function with the keyword argument +:direction set to :input.

    • + +
    • To open a file for +output, use the open function with the +keyword argument :direction set to :output.

    • + +
    • To close a file, use the close +function.

    • + +
    + +

    The open function takes a single +required argument which is the name of the file to be opened. This name can +be in the form of a string or a symbol. The +open function returns an object +of type 'file-stream' if it succeeds in opening the specified +file. It returns the value +NIL if it fails.

    + +

    In order to manipulate the file, it is necessary to save the value +returned by the open function. +This is usually done by assigning it to a variable with the +setq special form or by binding it using +let or +let*. Here is an example: + +

    +(setq file-stream (open "init.lsp" :direction :input))
    +
    + +

    Evaluating this expression will result in the file 'init.lsp' being +opened. The file object that will be returned by the +open function will be +assigned to the variable 'file-stream'.

    + +

    It is now possible to use the file for input. To read an +expression from the file, just supply the value of the +'file-stream' variable as the optional 'stream' argument to the +read function:

    + +
    +(read file-stream)
    +
    + +

    Evaluating this expression will result in reading the first expression +from the file 'init.lsp'. The expression will be returned as the +result of the read function. +More expressions can be read from the file using further calls to the +read function. When there +are no more expressions to read, the +read function will return +NIL [or whatever value was +supplied as the second argument to +read].

    + +

    Once you are done reading from the file, you should close it. To close +the file, use the close +function:

    + +
    +(close file-stream)
    +
    + +

    Evaluating this expression will cause the file to be closed.

    + +

      Back to Top

    + + + +
    + +

    1.2  Output to a File

    + +
    + +

    Writing to a file is pretty much the same as reading from one. You need +to open the file first. This time you should use the +open function to indicate +that you will do output to the file:

    + +
    +(setq file-stream (open "test.dat" :direction :output))
    +
    + +

    Evaluating this expression will open the file 'test.dat' for output. +If the file already exists, its current contents will be +discarded. If it doesn't already exist, it will be created. +In any case, a 'file-stream' object will be +returned by the open function. This file +object will be assigned to the 'file-stream' variable.

    + +

    It is now possible to write to this file by supplying the value of the +'file-stream' variable as the optional 'stream' parameter in +the print function.

    + +
    +(print "Hello there" file-stream)
    +
    + +

    Evaluating this expression will result in the string "Hello +there" being written to the file +"test.dat". More data can be written to the file using the +same technique.

    + +

    Once you are done writing to the file, you should +close it. Closing an +output file is just like closing an input file:

    + +
    +(close file-stream)
    +
    + +

    Evaluating this expression will +close the output file and +make it permanent.

    + +

      Back to Top

    + + + +
    + +

    1.3  A Slightly More Complicated File Example

    + +
    + +

    This example shows how to +open a file, +read each Lisp expression +from the file and print it. +It demonstrates the use of files and the use of the optional 'stream' +argument to the read +function.

    + +
    +(do* ((file-stream (open "test.dat" :direction :input))
    +      (expression (read file-stream) (read file-stream)))
    +     ((null expression) nil)
    +  (print expression))
    +
    + +

      Back to top

    + + + +
    + +

    1.4  Closing Files via 'unwind-protect'

    + +
    + +

    To make sure that the file gets closed in the end, the +file i/o functions can be wrapped by an unwind-protect form:

    + +
    +(let ((file-stream (open "test.dat" :direction :input)))
    +  (unwind-protect
    +    ;; protect-form
    +    (do ((expression (read file-stream) (read file-stream)))
    +        ((null expression) nil)
    +      (print expression))
    +    ;; clean-up form
    +    (when file-stream (close file-stream))))
    +
    + +

    This pattern can be found in many file i/o functions:

    + +
    +(let ((file-stream (open filename :direction direction)))
    +  (unwind-protect
    +    (progn
    +      ;; do something with the file-stream
    +      )
    +    (when file-stream (close file-stream))))
    +
    + +

      Back to top

    + + + +
    + +

    3  Testing Existence

    + +
    + +

    + +

    Note that these function are meant to prevent accidents during basic +file i/o, they may not be able to test if a file or directory +physically exists or is a link to a different place.

    + +

    + + + +

    The Nyquist listdir function can +be used to test if a directory exists:

    + +
    +(defun directory-exists-p (string)
    +  (and (listdir string) t))
    +
    + + + +

    Testing if a file exists is a bit more tricky because on Unix [including +Linux and Mac OS X] a directory is a special kind of file, so +the XLISP open function also can open +directories. That's why we first must make sure that the filename string is +not the name of an existing directory:

    + +
    +(defun file-exists-p (string)
    +  (or (stringp string) (error "not a string" string))
    +  (unless (listdir string)
    +    (let ((file-stream (open string)))
    +      (when file-stream
    +        (close file-stream)
    +        string))))
    +
    + + + +

    Before creating a new file it's always a good idea to check +if a file or directory with the same name already exists:

    + +
    +(defun file-or-directory-exists-p (string)
    +  (or (stringp string) (error "not a string" string))
    +  (when (or (listdir string)
    +            (let ((file-stream (open string)))
    +              (when file-stream
    +                (close file-stream)
    +                t)))
    +    string))
    +
    + + +

      Back to Top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/tutorials/lisp-faq.htm b/docsrc/xlisp/xlisp-doc/tutorials/lisp-faq.htm new file mode 100644 index 0000000..a00e621 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/lisp-faq.htm @@ -0,0 +1,199 @@ + + +Lisp FAQ + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Lisp FAQ

    + +
    + +
      +
    1. Why do #'and and #'or not work with apply and funcall?
    2. +
    3. Where can I find more Lisp FAQs in the Internet?
    4. +
    + + + +
    + +

    Why do #'and and #'or not work with apply and funcall?

    + +
    + +

    From +http://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part3/faq-doc-3.html

    + +

    The short answer is that and and +or are special operators, not functions, +while apply and +funcall can only be used to invoke +functions, not macros and special operators.

    + +

    The reason why and and or are special operators is because they +implement control structure in addition to computing a boolean value. They +evaluate their subforms sequentially from left to right, and stop evaluating +subforms as soon as the result can be determined. This is referred to as +'short circuiting'. apply +and funcall, however, are ordinary +functions. Therefore, their arguments are evaluated before they are called. +Thus, were apply able to be used with +#'and and +or, the short-circuiting +would be defeated.

    + +

    Perhaps you don't really care about the short-circuiting, +and simply want the functional, boolean interpretation. While this may be a +reasonable interpretation of trying to +apply +and +or or, it doesn't generalize +to other macros well, so there's no obvious way to have the Lisp system 'do +the right thing' when trying to apply macros. The only function +associated with a macro is its expander function. This function accepts and +returns and form, so it cannot be used to compute the value.

    + +

    The Common Lisp functions EVERY, SOME and IDENTITY can be +used to get the functionality you intend when trying to +apply +#'and +and #'or:

    + +

    + + + + + + + + + + + + + + + +
      (apply #'and list) → (every #'identity list)
      (apply #'or  list) → (some  #'identity list)

    + +

    Defining and and +or as functions using +cons and +eval:

    + +
    +(defun and-fn (&rest args)
    +  (eval (cons 'and args)))
    +
    +(defun or-fn (&rest args)
    +  (eval (cons 'or args)))
    +
    + +

    Defining and and +or as functions using +dolist:

    + +
    +(defun and-fn (&rest args)
    +  (dolist (x args t)
    +    (and (not x) (return nil))))
    +
    +(defun or-fn (&rest args)
    +  (dolist (x args nil)
    +    (and x (return t))))
    +
    + + +
    +(defun apply* (function args)
    +  (if (eq (type-of function) 'fsubr)
    +      (eval (cons function args))
    +      (apply function args)))
    +
    +
    +
    + + +

      Back to top

    + + + +
    + +

    Where can I find more Lisp FAQs in the Internet?

    + +
    + + + + + + + + + + + + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/lisp-hints.htm b/docsrc/xlisp/xlisp-doc/tutorials/lisp-hints.htm new file mode 100644 index 0000000..13e0e84 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/lisp-hints.htm @@ -0,0 +1,2055 @@ + + +Lisp Hints + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Lisp Hints

    + +
    + +

    The original document was written by Geoffrey J. Gordon +[ggordon@cs.cmu.edu], Friday, February 5, 1993, +for CMUCL.

    + +

    Modified by:

    + +
      + +
    • Bruno Haible for CLISP.
    • + +
    • Tom Almy in 1995 for XLISP Plus.
    • + +
    • Edgar M. Franke [edgar-rft@web.de] in 2010 for +Nyquist.
    • + +
    + +

    All examples tested with Nyquist 3.03 in November +2010.

    + +
    + +

    Table of Contents

    + +
    + +
      +
    1. Symbols
    2. +
    3. Numbers
    4. +
    5. Conses
    6. +
    7. Lists
    8. +
    9. Functions
    10. +
    11. Printing
    12. +
    13. Forms and the Top-Level Loop
    14. +
    15. Special Forms
    16. +
    17. Binding
    18. +
    19. Dynamic Scoping
    20. +
    21. Arrays
    22. +
    23. Strings
    24. +
    25. Setf
    26. +
    27. Booleans and Conditionals
    28. +
    29. Iteration
    30. +
    31. Non-local Exits
    32. +
    33. Funcall, Apply, and Mapcar
    34. +
    35. Lambda
    36. +
    37. Sorting
    38. +
    39. Equality
    40. +
    41. Some Useful List Functions
    42. +
    + + + +
    + +

    1  Symbols

    + +
    + +

    A symbol is just a sequence of characters. There are restrictions on what +you can include in a symbol and what the first character can be, but as long +as you stick to letters, digits, and hyphens, you'll be safe. [Except that +if you use only digits and possibly an initial hyphen, Lisp will think you +typed an integer rather than a symbol.] Some examples of symbols:

    + +
    +a
    +b
    +c1
    +foo
    +bar
    +baaz-quux-garply
    +
    + +

    Some things you can do with symbols follow. Things after a '>' +prompt are what you type to the Lisp interpreter, while other things +are what the Lisp interpreter prints back to you. The semicolon +';' is Lisp's comment character. Everything from a ';' to the end of +line is ignored.

    + +
    +> (setq a 5)        ; store a number as the value of a symbol
    +5
    +
    +> a                 ; take the value of a symbol
    +5
    +
    +> (let ((a 6))      ; bind the value of a symbol temporarily to 6
    +    a)
    +6
    +
    +> a                 ; the value returns to 5 once the let is finished
    +5
    +
    +> (+ a 6)           ; use the value of a symbol as an argument to a function
    +11
    +
    +> b                 ; try to take the value of a symbol which has no value
    +error: unbound variable - b
    +
    + +

    There are two special symbols, + T  +and NIL. The +value of  T  is defined +always to be  T , +and the value of NIL is defined +always to be NIL. +Lisp uses  T  and +NIL to represent true and false. +An example of this use is in the if statement, described more +fully later:

    + +
    +> (if t 5 6)
    +5
    +
    +> (if nil 5 6)
    +6
    +
    +> (if 4 5 6)
    +5
    +
    + +

    The last example is odd but correct. +NIL means false, and +anything else means true. Unless we have a reason to do otherwise, we use + T  to mean true, just for the +sake of clarity.

    + +

    Symbols like  T  and +NIL are called +'self-evaluating' symbols, because they evaluate to themselves. +There is a whole class of self-evaluating symbols called +'keywords'. Any symbol whose name starts with a colon is a keyword. [See +below for some uses for keywords.] Some examples:

    + +
    +> :this-is-a-keyword
    +:THIS-IS-A-KEYWORD
    +
    +> :so-is-this
    +:SO-IS-THIS
    +
    +> :me-too
    +:ME-TOO
    +
    + +

      Back to top

    + + + +
    + +

    2  Numbers

    + +
    + +

    An integer number [FIXNUM] is a sequence of digits optionally preceded by +a plus sign '+' or a minus sign '-'. A +floating point number [FLONUM] looks like an integer, except that it +has a decimal point and optionally can be written in scientific notation. +Here are some numbers:

    + +
    +5
    +17
    +-34
    ++6
    +3.1415
    +1.722e-15
    +
    + +

    The standard arithmetic functions are all available:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +  - addition
      -  - subtraction
      *  - multiplication
      /  - division
      truncate  - truncate a float to an integer
      rem  - remainder of a division
      sin  - sine
      cos  - cosine
      tan  - tangent
      sqrt  - square root
      exp  - natural exponent
      expt  - math exponent

    + + +

     +  [addition], + -  [subtraction], + *  [multiplication], +and  /  [division] +accept any number of arguments and return a number according to type +contagion. This means that as long as only integer numbers are given as +arguments the result will always be an integer number, but as soon as at +least one of the arguments is a floating number then the result will be a +floating point number. Here are some examples:

    + +
    +> (/ 3 2)               ; integer division causes rounding error
    +1
    +
    +> (/ 3 2.0)             ; the 2.0 forces floating point computation
    +1.5
    +
    +> (exp 1)               ; e
    +2.71828
    +
    +> (exp 3)               ; e * e * e
    +20.0855
    +
    +> (expt 3 4.2)          ; exponent with a base other than e
    +100.904
    +
    +> (+ 5 6 7 (* 8 9 10))  ; the functions + - * / accept multiple arguments
    +738
    +
    + +

    In Nyquist the valid range of integer numbers is limited by the size of a +C 'long' value on the machine on which Nyquist is running.

    + +

      Back to top

    + + + +
    + +

    3  Conses

    + +
    + +

    A cons is just a +two-field record. The fields are called +car and +cdr, for historical reasons. +On the first machine where Lisp was implemented, there +were two assembly language instructions CAR and CDR which stood for +'contents of address register' and 'contents of decrement register'. +Conses were implemented using these two registers.

    + +

    Conses are created by the cons +function:

    + +
    +> (cons 4 5)            ; Allocate a cons. Set the car to 4 and the cdr to 5
    +(4 . 5)
    +
    +> (cons (cons 4 5) 6)
    +((4 . 5) . 6)
    +
    +> (car (cons 4 5))
    +4
    +
    +> (cdr (cons 4 5))
    +5
    +
    + +

      Back to top

    + + + +
    + +

    4  Lists

    + +
    + +

    You can build many structures out of conses. Perhaps the simplest is a +linked list. The car +[the first element] of +each cons points to one of the elements of the list, and the +cdr [the +rest of the elements] points +either to another cons or to NIL. +You can create such a linked list with the +list function:

    + +
    +> (list 4 5 6)
    +(4 5 6)
    +
    + +

    Notice that Lisp prints linked lists a special way. It omits +some of the periods and parentheses. The rule is that if the +cdr of a +cons is +NIL, Lisp doesn't bother to print the +period or the NIL, and if the +cdr of +cons A is +cons B, then Lisp doesn't +bother to print the period for +cons A or the parentheses +for cons B. So:

    + +
    +> (cons 4 nil)
    +(4)             ; (4 . nil)
    +
    +> (cons 4 (cons 5 6))
    +(4 5 . 6)       ; (4 . (5 . 6))
    +
    +> (cons 4 (cons 5 (cons 6 nil)))
    +(4 5 6)         ; (4 . (5 . (6 . nil)))
    +
    + +

    The last example is exactly equivalent to the call:

    + +
    +(list 4 5 6)
    +
    + +

    Note that NIL now means the list with +no elements. The cdr of +(a b), a list with 2 elements, is +(b), a list with 1 element, and the +cdr of (b), a list with 1 +element, is NIL, +which therefore must be a list with no elements.

    + +

    + +

    The car and +cdr of +NIL are defined to +be NIL.

    + +

    + +

    If you store your list in a variable, you can make it act like a +stack:

    + +
    +> (setq a nil)
    +NIL             ; A = ()
    +
    +> (push 4 a)
    +(4)             ; A = (4)
    +
    +> (push 5 a)
    +(5 4)           ; A = (5 4)
    +
    +> (pop a)
    +5               ; A = (4)
    +
    +> (pop a)
    +4               ; A = ()
    +
    +> (pop a)
    +NIL             ; A = ()
    +
    + +

    See pop, +push, +setq.

    + + + +

    List Accessors

    + +

    There are several different approaches to name the accessor +functions for elements of conses and lists. The 'traditional' +Lisp still uses function names like +car and +cdr while the 'modern' Lisp uses more +descriptive names like first and rest. This leads to the situation that in +most Lisps today the list accessor functions are available under different +names for the same functions:

    + +

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    modern — traditionalequivalent to  (1 2 3 4 5 6 7 8)
    first — car  (nth 0 ... )  →  1
    second — cadr  (nth 1 ... )  →  2
    third — caddr  (nth 2 ... )  →  3
    fourth — cadddr  (nth 3 ... )  →  4
      (nth 4 ... )  →  5
        ...
    (nthcdr 0 ... )  →  (1 2 3 4 5 6 7 8)
    rest — cdr  (nthcdr 1 ... )  →  (2 3 4 5 6 7 8)
    cddr  (nthcdr 2 ... )  →  (3 4 5 6 7 8)
    cdddr  (nthcdr 3 ... )  →  (4 5 6 7 8)
    cddddr  (nthcdr 4 ... )  →  (5 6 7 8)
    (nthcdr 5 ... )  →  (6 7 8)
        ...
    last  →  (8)

    + +

    + +

    The traditional c..r-functions are available in even more +variations, see car, +cdr, +cadr, cddr, +caaar...caddr, +cdaar...cdddr, +caaaar...cadddr, +and cdaaar...cddddr.

    + +

      Back to top

    + + + +
    + +

    5  Functions

    + +
    + +

    You saw one example of a function above. Here are some more:

    + +
    +> (+ 3 4 5 6)                 ; this function takes any number of arguments
    +18
    +
    +> (+ (+ 3 4) (+ (+ 4 5) 6))   ; isn't prefix notation fun?
    +22
    +
    +> (defun foo (x y)            ; defining a function
    +    (+ x y 5))
    +FOO
    +
    +> (foo 5 0)                   ; calling a function
    +10
    +
    +> (defun fact (x)             ; a recursive function
    +    (if (> x 0)
    +        (* x (fact (- x 1)))
    +        1))
    +FACT
    +
    +> (fact 5)
    +120
    +
    +> (defun a (x)
    +    (if (= x 0)
    +        t
    +        (b (- x))))           ; mutually recursive functions
    +A
    +
    +> (defun b (x)
    +    (if (> x 0)
    +        (a (- x 1))
    +        (a (+ x 1))))
    +B
    +
    +> (a 5)
    +T
    +
    +> (defun bar (x)              ; A function with multiple statements
    +    (setq x (* x 3))          ; in its body. It will return the value
    +    (setq x (/ x 2))          ; returned by its final statement
    +    (+ x 4))
    +BAR
    +
    +> (bar 6)
    +13
    +
    + +

    See  + , + − , + * , + / , + = , + > , +defun, + if , +setq. When we defined 'foo', we +gave it two arguments, 'x' and 'y'. Now when we call 'foo', we +are required to provide exactly two arguments. The first will become the +value of 'x' for the duration of the call to 'foo', and the second will +become the value of 'y' for the duration of the call. In Lisp, +most variables are lexically scoped. That is, if 'foo' calls +'bar' and 'bar' tries to reference 'x', then 'bar' will not get 'foo's value +for x.

    + +

    + +

    The process of assigning a symbol a value for the duration of some +lexical scope is called 'binding'.

    + +

    + +

    You can specify optional arguments for your functions. Any argument +after the symbol +&optional is +optional:

    + +
    +> (defun bar (x &optional y)
    +    (if y
    +        x
    +        0))
    +BAR
    +
    +> (defun baaz (&optional (x 3) (z 10))
    +    (+ x z))
    +BAAZ
    +
    +> (bar 5)
    +0
    +
    +> (bar 5 t)
    +5
    +
    +> (baaz 5)
    +15
    +
    +> (baaz 5 6)
    +11
    +
    +> (baaz)
    +13
    +
    + +

    See  + , +defun, + if . +It is legal to call the function 'bar' with either one or two +arguments. If it is called with one argument, 'x' will be bound +to the value of that argument and 'y' will be bound to +NIL. If it is called +with two arguments, 'x' and 'y' will be bound to the values of the first and +second argument, respectively.

    + +

    The function 'baaz' has two optional arguments. It specifies a +default value for each of them. If the caller specifies only +one argument, 'z' will be bound to 10 instead of to +NIL, and if the caller +specifies no arguments, 'x' will be bound to 3 and 'z' to +10.

    + +

    You can make your function accept any number of arguments by ending its +argument list with an +&rest parameter. +Lisp will collect all arguments not otherwise accounted for into a list and +bind the &rest +parameter to that list. So:

    + +
    +> (defun foo (x &rest y)
    +    y)
    +FOO
    +
    +> (foo 3)
    +NIL
    +
    +> (foo 4 5 6)
    +(5 6)
    +
    + +

    See defun. Finally, you can give +your function another kind of optional argument called a +&key 'keyword' +argument. The caller can give these arguments in any order, +because they're labelled with keywords:

    + +
    +> (defun foo (&key x y)
    +    (cons x y))
    +FOO
    +
    +> (foo :x 5 :y 3)
    +(5 . 3)
    +
    +> (foo :y 3 :x 5)
    +(5 . 3)
    +
    +> (foo :y 3)
    +(NIL . 3)
    +
    +> (foo)
    +(NIL)
    +
    + +

    See defun. +An &key +parameter can have a default value too:

    + +
    +> (defun foo (&key (x 5))
    +    x)
    +FOO
    +
    +> (foo :x 7)
    +7
    +
    +> (foo)
    +5
    +
    + +

      Back to top

    + + + +
    + +

    6  Printing

    + +
    + +

    Some functions can cause output. The simplest one is +print, which +prints its argument and then returns it:

    + +
    +> (print 3)
    +3            ; screen output
    +3            ; return value
    +
    + +

    The first 3 above was printed, the +second was returned.

    + +

    If you want more complicated output, you will need to use +format. +Here's an example:

    + +
    +> (format t "An atom: ~S~%and a list: ~S~%and an integer: ~A~%"
    +          nil (list 5) 6)
    +An atom: NIL          ; screen output
    +and a list: (5)       ; screen output
    +and an integer: 6     ; screen output
    +NIL                   ; return value
    +
    + +

    See list. The first +argument to format is either + T , +NIL, or a stream. + T  specifies output +to the terminal. NIL means +not to print anything but to return a string containing the output instead. +Streams are general places for output to go. They can specify a +file, or the terminal, or a printer device. This tutorial will not describe +streams in any further detail.

    + +

    The second argument is a formatting template, which is a string +optionally containing formatting directives. All remaining +arguments may be referred to by the formatting directives. Lisp will replace +the directives with some appropriate characters based on the arguments to +which they refer and then print the resulting string.

    + +

    The format function always returns NIL +unless its first argument is NIL, in +which case it prints nothing and returns a string.

    + +

    There are several different directives available:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       + + + + +
    ~S
    +
      - [standard] - accepts any Lisp object and replaces it by + the same printed representation which is produced by the + print function.
     
       + + + + +
    ~A
    +
      - [aestethic] - tries to 'pretty-print' + its argument.
     
       + + + + +
    ~%
    +
      - [linebreak] - is always replaced by a linebreak character + or character sequence of the underlying operation system.
     
       + + + + +
    ~~
    +
      - [tilde] - is replaced by a single '~' character.

    + +

    If the last character in a line in a +format template is a tilde, then +the linebreak is ignored and the template continues with the next +non-whitespace character in the next line.

    + +

      Back to top

    + + + +
    + +

    7  Forms and the Top-Level Loop

    + +
    + +

    The things which you type to the Lisp interpreter are called 'forms'. +The Lisp interpreter repeatedly +reads a form, +evaluates it, and +prints the result. This procedure +is therefore called the 'read-eval-print' loop, or REPL for +short.

    + +

    Some forms will cause errors. After an error, Lisp will put you into the +debugger so you can try to figure out what caused the error.

    + +

    In general, a form is either an atom, +[for example a symbol, an integer, or a string] or a +list. If the form is +an atom, Lisp evaluates it immediately. +Symbols evaluate to their value, integers and strings evaluate to +themselves. If the form is a +list, Lisp treats its first +element as the name of a function. It evaluates the remaining +elements recursively, and then calls the function with the values of the +remaining elements as arguments.

    + +

    For example, if Lisp sees the form:

    + +
    +(+ 3 4)
    +
    + +

    then it treats  +  as +the name of a function. It then evaluates 3 to get +3 and 4 to get 4, finally it calls  +  with 3 and 4 as the +arguments. The  +  +function returns 7, which Lisp prints.

    + +

    + +

    Nyquist: A description of the debugger can be found +in the Break Command Loop +section and a detailed description of the evaluation process can be found in +the Evaluator section of the XLISP +manual.

    + +

    + +

    The top-level loop provides some other conveniences. +One particularly convenient convenience is the ability to talk +about the results of previously typed forms. Lisp always saves its most +recent three results, it stores them as the values of the symbols + * , + ** , +and  *** . +For example:

    + +
    +> 3
    +3
    +
    +> 4
    +4
    +
    +> 5
    +5
    +
    +> ***
    +3
    +
    +> ***
    +4
    +
    +> ***
    +5
    +
    +> **
    +4
    +
    +> *
    +4
    +
    + +

    See  * , + ** , + *** , + + , + ++ , + +++ , + − .

    + +

      Back to top

    + + + +
    + +

    8  Special Forms

    + +
    + +

    There are a number of special forms which look like function calls but +aren't. These include control constructs such as + if  statements and +do loops, assignments like +setq, +setf, +push, and +pop, definitions such as +defun, and binding constructs such +as let. Not all +of these special forms have been mentioned yet, see below for examples.

    + +

    One useful special form is the quote +form. The quote function +prevents its argument from being evaluated. For example:

    + +
    +> (setq a 3)
    +3
    +
    +> a
    +3
    +
    +> (quote a)
    +A
    +
    +> 'a            ; 'a is an abbreviation for (quote a)
    +A
    +
    + +

    Another similar special form is the +function form, it causes its +argument to be interpreted as a function rather than being evaluated. +For example:

    + +
    +> (setq + 3)
    +3
    +
    +> +
    +3
    +
    +> '+
    ++
    +
    +> (function +)
    +#<Subr-+: #88b44d5e>
    +
    +> #'+                   ; #'+ is an abbreviation for (function +)
    +#<Subr-+: #88b44d5e>
    +
    + +

    The function special form is +useful when you want to pass a function as an argument to another function. +See below for some examples of functions which take functions +as arguments.

    + +

      Back to top

    + + + +
    + +

    9  Binding

    + +
    + +

    Binding is lexically scoped assignment. It happens to the +variables in a function's parameter list whenever the function is called. +The formal parameters are bound to the actual parameters for +the duration of the function call. You can bind variables +anywhere in a program with the let +special form, which looks like this:

    + +
    +(let ((variable-1 value-1)
    +      (variable-2 value-2)
    +       ... )
    +  body)
    +
    + +

    The let function binds +'variable-1' to 'value-1', +'variable-2' to 'value-2', and so forth. +Then it executes the statements in its body. The body of a +let follows exactly the same rules that +a function body does. Some examples:

    + +
    +> (let ((a 3)) (+ a 1))
    +4
    +
    +> (let ((a 2)
    +        (b 3)
    +        (c 0))
    +    (setq c (+ a b))
    +    c)
    +5
    +
    +> (setq c 4)
    +4
    +
    +> (let ((c 5))
    +    c)
    +5
    +
    +> c
    +4
    +
    + +

    See  + , +let, +setq. Instead of:

    + +
    +(let ((a nil)
    +      (b nil))
    +  ... )
    +
    + +

    you can write:

    + +
    +(let (a b)
    +  ... )
    +
    + +

    The 'value-1', 'value-2', etc. inside a +let form cannot reference the variables +'variable-1', 'variable-2', etc. that the +let form is binding. For +example:

    + +
    +> (let ((x 1)
    +        (y (+ x 1)))  ; x is still unbound here
    +    y)
    +error: unbound variable - x
    +
    + +

    If the symbol 'x' already has a global value, stranger happenings will +result:

    + +
    +> (setq x 7)
    +7
    +
    +> (let ((x 1)
    +        (y (+ x 1)))  ; references to the global x
    +    y)
    +8
    +
    + +

    The let* special form is just +like let except that it allows values to +reference variables defined earlier in the +let* form. +For example:

    + +
    +> (setq x 7)
    +7
    +
    +> (let* ((x 1)
    +         (y (+ x 1)))  ; references to x in the line before
    +    y)
    +2
    +
    + +

    The let* form:

    + +
    +(let* ((x a)
    +       (y b))
    +  ... )
    +
    + +

    is equivalent to the following let +construct:

    + +
    +(let ((x a))
    +  (let ((y b))
    +    ... ))
    +
    + +

      Back to top

    + + + +
    + +

    10  Dynamic Scoping

    + +
    + +

    The let and +let* forms provide lexical scoping, +which is what you expect if you're used to programming in C or Pascal. +Dynamic scoping is what you get in BASIC. If you assign a value +to a dynamically scoped variable, every mention of that variable returns +that value until you assign another value to the same variable.

    + +

    In Lisp, dynamically scoped variables are called 'special' variables. +In Common Lisp special variables are declared with the 'defvar' +special form. In Nyquist there is no 'defvar' form.

    + +

    + +

    Nyquist has no 'dynamic' scoping in the Common Lisp sense.

    + +

    + +

    In Nyquist every variable assigned with +setq or +setf at the top-level, +outside of a function or a let +binding, is a lexical scoped variable. Here is an example what this means:

    + +
    +> (setq *variable* 5)         ; define a global variable
    +5
    +
    +> (defun check-variable ()    ; define a function in global scope,
    +    *variable*)               ; returning the value of the variable
    +CHECK-VARIABLE
    +
    +> (check-variable)            ; the CHECK-VARIABLE function returns
    +5                             ; the global value of the variable
    +
    +> (let ((*variable* 10))      ; create a local binding for the variable
    +    (print (check-variable))  ; call CHECK-VARIABLE and print the return value
    +    (print *variable*))       ; print the local value of the variable
    +5   ; return value of CHECK-VARIABLE
    +10  ; variable value inside of LET
    +10
    +
    + +

    See defun, +let, +print, +setq. Because the +'check-variable' function was defined in global +scope and therefore is lexically outside of the +let form, the +'check-variable' function returns the variable's global value +of 5, even if called from inside the +let form, where the variable has a +value of 10.

    + +

    + +

    Important: In Nyquist there is no way to change the scoping +behaviour of variables, so you must be careful where you define your +variables. With Nyquist it's generally a good idea to prefer local +let bindings over global variables.

    + +

    + +

    By convention, the name of a global Nyquist variable begins and ends with +a star * to signal that the variable might behave differently +than the programmer expects.

    + +

      Back to top

    + + + +
    + +

    11  Arrays

    + +
    + +

    The function +make-array makes a +1-dimensional array. +The aref function accesses +its elements. All elements of an array are initially set +to NIL. +For example:

    + +
    +> (make-array 4)        ; 1-D array with 4 elements
    +#(NIL NIL NIL NIL)
    +
    + +

    Array indices always start at 0. See +below for how to set the elements of an array.

    + +

      Back to top

    + + + +
    + +

    12  Strings

    + +
    + +

    A string is a sequence of characters between double quotes. Nyquist +represents a string internally as a variable-length array of +characters. You can write a string containing a double quote by +preceding the quote with a backslash. A double backslash stands +for a single backslash. For example:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
      "abcd"  - has 4 characters
      "\""  - has 1 character, a quote
      "\\"  - has 1 character, a backslash

    + +

    Here are some functions for dealing with strings:

    + +
    +> (strcat "abcd" "efg")
    +"abcdefg"                ; STRCAT concatenates strings
    +
    +> (char "abc" 1)
    +#\b                      ; Lisp writes characters preceded by #\
    +
    +> (subseq "abc" 0 2)
    +"ab"                     ; SUBSEQ extracts substrings
    +
    + +

    See char, +strcat, +subseq.

    + +

      Back to top

    + + + +
    + +

    13  Setf

    + +
    + +

    Certain forms in Lisp naturally define a memory location. For example, if +the value of 'x' is a list, then +(nth 4 x) defines the fifth +element of the list. Or, if +the value of 'y' is a one-dimensional +array, +(aref y 2) defines the +third element of the array.

    + +

    The setf special form uses its first +argument to define a place in memory, evaluates its second argument, and +stores the resulting value in the resulting memory location. For +example:

    + +
    +> (setq a (make-array 3))
    +#(NIL NIL NIL)
    +
    +> (aref a 1)
    +NIL
    +
    +> (setf (aref a 1) 3)         ; store 3 in the second element of a
    +3
    +
    +> a
    +#(NIL 3 NIL)
    +
    +> (aref a 1)                  ; read the second element of a
    +3
    +
    +> (setq b (list 1 2 3 4 5))
    +(1 2 3 4 5)
    +
    +> (nth 4 b)
    +5
    +
    +> (setf (nth 4 b) "five")     ; store "five" in the fifth element of b
    +"five"
    +
    +> b
    +(1 2 3 4 "five")
    +
    +> (nth 4 b)
    +"five"
    +
    + +

    The setf function is the only way to +set the elements of a list or an array.

    + +

      Back to top

    + + + +
    + +

    14  Booleans and Conditionals

    + +
    + +

    Lisp uses the self-evaluating symbol +NIL to mean false. Anything other than +self-evaluating means true. Unless we have a reason not to, +we usually use the self-evaluating symbol + T  to stand +for true.

    + +

    Lisp provides a standard set of logical functions, for example +and, +or, and +not. +The and and +or connectives are +short-circuiting, and +will not evaluate any arguments to the right of the first one which +evaluates to NIL, while +or will not evaluate any arguments to the +right of the first one which evaluates +to  T .

    + +

    Lisp also provides several special forms for conditional execution. The +simplest of these is + if . The first argument +of  if  determines whether the +second or third argument will be executed:

    + +
    +> (if t 5 6)
    +5
    +
    +> (if nil 5 6)
    +6
    +
    +> (if 4 5 6)
    +5
    +
    + +

    If you need to put more than one statement in the 'then' or 'else' clause +of an  if  statement, +you can use the progn special form. +progn executes each statement in its +body, then returns the value of the final one:

    + +
    +> (setq a 7)
    +7
    +
    +> (setq b 0)
    +0
    +
    +> (setq c 5)
    +5
    +
    +> (if (> a 5)
    +    (progn
    +      (setq a (+ b 7))
    +      (setq b (+ c 8)))
    +    (setq b 4))
    +13
    +
    + +

    An  if  statement which lacks +either a 'then' or an 'else' clause can be written using the +when or +unless special form:

    + +
    +> (when t 3)
    +3
    +
    +> (when nil 3)
    +NIL
    +
    +> (unless t 3)
    +NIL
    +
    +> (unless nil 3)
    +3
    +
    + +

    when and +unless, unlike + if , allow any number of +statements in their bodies:

    + +
    +(when x
    +  a
    +  b
    +  c)
    +
    + +

    is equivalent to:

    + +
    +(if x
    +    (progn
    +      a
    +      b
    +      c))
    +
    + +

    For example:

    + +
    +> (when t
    +    (setq a 5)
    +    (+ a 6))
    +11
    +
    + +

    More complicated conditionals can be defined using the +cond special form. +A cond form consists of +the symbol cond followed by a number of +cond clauses, each of which is a list. +The first element of a cond +clause is the condition, the remaining elements [if any] are +the actions:

    + +
    +(cond (condition-1 action-1)
    +      (condition-2 action-2)
    +        ...
    +      (t default-action))
    +
    + +

    The cond form finds the first clause +whose condition evaluates to true [does not evaluate to +NIL]. It then +executes the corresponding action and returns the resulting value. None of +the remaining conditions are evaluated, nor are any actions except the one +corresponding to the selected condition. For example:

    + +
    +> (setq a 3)
    +3
    +
    +> (cond
    +    ((evenp a) a)        ; if a is even return a
    +    ((> a 7) (/ a 2))    ; else if a is bigger than 7 return a/2
    +    ((< a 5) (- a 1))    ; else if a is smaller than 5 return a-1
    +    (t 17))              ; else return 17
    +2
    +
    + +

    If the action in the selected cond +clause is missing, then cond returns +what the condition evaluated to:

    + +
    +> (cond ((+ 3 4)))
    +7
    +
    + +

    The Lisp case form is like a C +'switch' statement:

    + +
    +> (setq x 'b)
    +B
    +
    +> (case x
    +    (a 5)
    +    ((d e) 7)
    +    ((b f) 3)
    +    (t 9))
    +3
    +
    + +

    The  T  clause at the end +means that if 'x' is not 'a', 'd or e', or +'b or f', then the case +form will return 9.

    + +

      Back to top

    + + + +
    + +

    15  Iteration

    + +
    + +

    The simplest iteration construct in Lisp is +loop. +A loop construct repeatedly +executes its body until it hits a +return special form. +For example:

    + +
    +> (setq a 4)
    +4
    +
    +> (loop
    +    (setq a (+ a 1))
    +    (when (> a 7) (return a)))
    +8
    +
    +> (loop
    +    (setq a (- a 1))
    +    (when (< a 3) (return)))
    +NIL
    +
    + +

    The next simplest is dolist. +It binds a variable to the elements of a list in order and +stops when it hits the end of the list:

    + +
    +> (dolist (x '(a b c))
    +    (print x))
    +A
    +B
    +C
    +NIL
    +
    + +

    dolist always +returns NIL. Note that the +value of 'x' in the above example was +never NIL. +The NIL below the C was the +value that dolist returned, printed +by the read-eval-print loop.

    + +

    The most flexible, but also most complicated iteration form is +called do. +A do form looks +like this:

    + +
    +> (do ((x 1 (+ x 1))    ; variable x, initial value 1, update with (+ x 1)
    +       (y 1 (* y 2)))   ; variable y, initial value 1, update with (* y 2)
    +      ((> x 5) y)       ; terminate if (> x 5), return the value of y
    +    (print y)
    +    (print 'working))
    +1
    +WORKING
    +2
    +WORKING
    +4
    +WORKING
    +8
    +WORKING
    +16
    +WORKING
    +32
    +
    + +

    The first part of a do form specifies +what variables to bind, what their initial values are, and how to update +them. The second part specifies a termination condition and a +return value. The last part is the body. A +do form binds its variables to +their initial values like +a let, then checks the +termination condition. As long as the condition is false, it +executes the body repeatedly. When the condition becomes true, it +returns the value of the return-value form.

    + +

    The do* form is to +do as +let* is +to let.

    + +

      Back to top

    + + + +
    + +

    16  Non-local Exits

    + +
    + +

    The return special form is an +example of a nonlocal return. Another example is +return-from, which +returns a value from the surrounding function:

    + +
    +> (defun foo (x)
    +    (return-from foo 3)
    +    x)
    +FOO
    +
    +> (foo 17)
    +3
    +
    + +

    Actually, the return-from form can return +from any named block, it's just that functions are the only blocks which are +named by default. You can create a named block with the +block special form:

    + +
    +> (block foo
    +    (return-from foo 7)
    +    3)
    +7
    +
    + +

    The return special form can return +from any block named NIL. +Loops are by default +named NIL, but you can +make your own +NIL-named blocks:

    + +
    +> (block nil
    +    (return 7)
    +    3)
    +7
    +
    + +

    Another form which causes a nonlocal exit is the +error form:

    + +
    +> (error "This is an error")
    +error: This is an error
    +
    + +

    The error form applies format to its +arguments, then places you in the debugger.

    + +

      Back to top

    + + + +
    + +

    17  Funcall, Apply, and Mapcar

    + +
    + +

    Earlier I promised to give some functions which take functions as +arguments. Here they are:

    + +
    +> (funcall #'+ 3 4)
    +7
    +
    +> (apply #'+ 3 4 '(3 4))
    +14
    +
    +> (mapcar #'not '(t nil t nil t nil))
    +(NIL T NIL T NIL T)
    +
    + +

    funcall calls its first argument +on its remaining arguments.

    + +

    apply is just like +funcall, except that its final +argument should be a list. The elements of that list are +treated as if they were additional arguments to +a funcall.

    + +

    The first argument to mapcar must +be a function of one argument, mapcar +applies this function to each element of a list and collects the results in +another list.

    + +

    funcall and +apply are chiefly useful when their +first argument is a variable. For instance, a search engine +could take a heuristic function as a parameter and use +funcall or +apply to call that function on a +state description. The sorting functions described later use +funcall to call their comparison +functions.

    + +

    mapcar, along with nameless +lambda functions, can replace many loops.

    + +

    + +

    Nyquist/XLISP: In XLISP, a 'special +form' of type FSUBR is not a function. This means that +apply, +funcall and +mapcar only work with functions +of type SUBR [built-in function] or CLOSURE [function defined by +defun, +flet, +labels, or +lambda], but with special forms +of type FSUBR a 'bad argument type' error is signalled.

    + +

    + +

      Back to top

    + + + +
    + +

    18  Lambda

    + +
    + +

    If you just want to create a temporary function and don't want to +bother giving it a name, lambda is +what you need.

    + +
    +> #'(lambda (x)
    +      (+ x 3))
    +#<Closure: #88b71ece>
    +
    +> (funcall * 5)
    +8
    +
    + +

    The combination of lambda and +mapcar can replace many loops. +For example, the following two forms are equivalent:

    + +
    +> (do ((x '(1 2 3 4 5) (cdr x))
    +       (y nil))
    +      ((null x) (reverse y))
    +    (push (+ (car x) 2) y))
    +(3 4 5 6 7)
    +
    +> (mapcar #'(lambda (x) (+ x 2)) '(1 2 3 4 5))
    +(3 4 5 6 7)
    +
    + +

      Back to top

    + + + +
    + +

    19  Sorting

    + +
    + +

    Lisp provides a primitive for +sorting, sort:

    + +
    +> (sort '(2 1 5 4 6) #'<)
    +(1 2 4 5 6)
    +
    +> (sort '(2 1 5 4 6) #'>)
    +(6 5 4 2 1)
    +
    + +

    The first argument to sort is a list, +the second is a comparison function. Be careful, because +sort is allowed to destroy its argument, +so if the original sequence is important to you, make a copy before sorting +the list.

    + +

    + +

    Bug: In Nyquist 3.03 [November 2010] the XLISP +sort function has a bug, so it's better +to store the return value of sort in the original variable like +this:

    + +
    +(setq a '(3 1 4 1 5 9 6 7))  => (3 1 4 1 5 9 6 7)
    +(setq a (sort a '<))         => (1 1 3 4 5 6 7 9)
    +a                            => (1 1 3 4 5 6 7 9)
    +
    + +

    + +

      Back to top

    + + + +
    + +

    20  Equality

    + +
    + +

    Lisp has many different ideas of equality. Numerical equality is +denoted by =. Two symbols are eq if and only if they are identical. Two +copies of the same list are not eq, but they are equal.

    + +
    +> (eq 'a 'a)
    +T
    +
    +> (eq 'a 'b)
    +NIL
    +
    +> (= 3 4)
    +T
    +
    +> (eq '(a b c) '(a b c))
    +NIL
    +
    +> (equal '(a b c) '(a b c))
    +T
    +
    +> (eql 'a 'a)
    +T
    +
    +> (eql 3 3)
    +T
    +
    + +

    The eql predicate is equivalent to eq for symbols and to = for numbers.

    + +

    The equal predicate is equivalent to eql for symbols and numbers. It is +true for two conses if and only if their cars are equal and their cdrs are +equal.

    + +

      Back to top

    + + + +
    + +

    21  Some Useful List Functions

    + +
    + +

    These functions all manipulate lists:

    + +
    +> (append '(1 2 3) '(4 5 6))    ;concatenate lists
    +(1 2 3 4 5 6)
    +
    +> (reverse '(1 2 3))            ;reverse the elements of a list
    +(3 2 1)
    +
    +> (member 'a '(b d a c))        ;set membership -- returns the first tail
    +(A C)                           ;whose car is the desired element
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/nyquist.htm b/docsrc/xlisp/xlisp-doc/tutorials/nyquist.htm new file mode 100644 index 0000000..19364ea --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/nyquist.htm @@ -0,0 +1,383 @@ + + +Nyquist + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Nyquist

    + +
    + +
      +
    • Debugger Shortcuts
    • +
    • grindef - print the function definition of a closure
    • +
    • args - print the argument list of a closure
    • +
    • setfn - define 'alias' names for functions
    • +
    • display - framework for debug messages
    • +
    + +

    This page will not save you from reading the Nyquist manual, it's a list +of things I find useful but frequently have to look them up in the manuals +when I haven't worked with Nyquist for a while. Many more useful tricks can +be found in the 'Developing and Debugging in Nyquist' chapter in the Nyquist +manual.

    + + + +
    + +

    Debugger Shortcuts

    + +
    + +

    Some Nyquist/XLISP debugger shortcuts, defined in 'xlinit.lsp' and +'misc.lsp':

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       + + + + +
    (bt)
    +
      → baktrace
       + + + + +
    (co)
    +
      → continue
       + + + + +
    (top)
    +
      → top-level
     
       + + + + +
    (res)
    +
      → clean-up
       + + + + +
    (up)
    +
      → clean-up

    + +

    The debugger commands only work if +*breakenable* +is non-NIL:

    + +

    + + + + + + + + + + + + + + + +
       + + + + +
    (bkon)
    +
      → (setq + *breakenable* + t)
       + + + + +
    (bkoff)
    +
      → (setq + *breakenable* + nil)

    + +

    You can make your own +*tracenable* +shortcuts like shown here:

    + +
    +(defun tron ()
    +  (setq *tracenable* t))
    +
    +(defun troff ()
    +  (setq *tracenable* nil))
    +
    + +

    See also:

    + + + +

      Back to top

    + + + +
    + +

    grindef

    + +
    + +

    The 'grindef' function prints the Lisp code of a +closure [user-defined +function or macro]:

    + +
    +(defun grindef (e)
    +  (pprint (get-lambda-expression (symbol-function e))))
    +
    + +

    Example:

    + +
    +> (grindef 'grindef)
    +(LAMBDA (E)
    +        (PPRINT (GET-LAMBDA-EXPRESSION (SYMBOL-FUNCTION E))))
    +NIL
    +
    + +

      Back to top

    + + + +
    + +

    args

    + +
    + +

    The 'args' function prints the name and the argument variables of a +closure [user-defined +function or macro]:

    + +
    +(defun args (e) 
    +  (pprint (cons e (second (get-lambda-expression (symbol-function e))))))
    +
    + +

    Example:

    + +
    +> (args 'args)
    +(ARGS E)
    +NIL
    +
    + +

      Back to top

    + + + +
    + +

    setfn

    + +
    + +

    The 'setfn' macro defines 'alias' names for functions:

    + +
    +(defmacro setfn (a b) 
    +  `(setf (symbol-function ',a) (symbol-function ',b)))
    +
    + +

    Examples from 'xlinit.lsp':

    + +
    +(setfn co  continue)
    +(setfn top top-level)
    +(setfn res clean-up)
    +(setfn up  clean-up)
    +
    + +

      Back to top

    + + + +
    + +

    display

    + +
    + +

    'display' is a debugging macro, defined in 'xlinit.lsp'.

    + +
    +(defmacro display-macro (label &rest items)
    +  (let ($res$)
    +    (dolist ($item$ items)
    +            (setq $res$ (cons
    +                         `(format t "~A = ~A  " ',$item$ ,$item$)
    +                         $res$)))
    +    (append (list 'let nil `(format t "~A : " ,label))
    +            (reverse $res$)
    +            '((terpri)))))
    +
    +(defun display-on ()
    +  (setfn display display-macro) t)
    +
    +(defun display-off ()
    +  (setfn display or) nil)
    +
    + +

    Usage:

    + +
    +(display "heading" var1 var2 ...)
    +
    + +

    expands into:

    + +
    +(let ()
    +  (format t "~A: " "heading")
    +  (format t "~A = ~A  " ',var1 ,var1)
    +  (format t "~A = ~A  " ',var2 ,var2)
    +   ... )
    +
    + +

    and then prints:

    + +
    +heading : VAR1 = value1 VAR2 = value2 ...
    +
    + +

    Using the 'display' macro in a function like shown here:

    + +
    +(defun hello ()
    +  (let ((local-var 'hello))
    +    (display "debug message" local-var)
    +    local-var)) ; return value
    +
    + +

    Now the 'debug message' can be switched on and off without +changing the code:

    + +
    +> (display-on)
    +T
    +
    +> (hello)
    +debug message : LOCAL-VAR = HELLO  
    +HELLO
    +
    +> (display-off)
    +NIL
    +
    +> (hello)
    +HELLO
    +
    + + + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/shell-utilities.htm b/docsrc/xlisp/xlisp-doc/tutorials/shell-utilities.htm new file mode 100644 index 0000000..4c0a075 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/shell-utilities.htm @@ -0,0 +1,539 @@ + + +Shell Utilities + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Shell Utilities

    + +
    + +
      +
    • cd - display and change directories
    • +
    • ls - display files and sub-directories
    • +
    • hd - hexdump a file
    • +
    + +

    Nyquist is not a system programming language, so Nyquist/XLISP cannot +create or remove files and directories, and the system function does not work on Windows. +But sometimes it helps to know the name of the current working +directory, the name of the directory where the soundfiles are stored, or the +names of files and sub-directories.

    + + + +
    + +

    cd

    + +
    + +

    The 'cd' function displays or changes the current working directory, it +also displays the name of the *default-sf-dir* directory, where +Nyquist stores its sound files:

    + +
    +> (cd)
    +;; *default-sf-dir*  = /tmp/
    +;; working directory = /home/edgar
    +NIL
    +
    +> (cd "test")
    +;; directory changed to "test"
    +;; *default-sf-dir*  = /tmp/
    +;; working directory = /home/edgar/test
    +T
    +
    +> (cd "..")
    +;; directory changed to "edgar"
    +;; *default-sf-dir*  = /tmp/
    +;; working directory = /home/edgar
    +T
    +
    +> (cd "foo")
    +;; directory not changed, "foo" not found
    +;; *default-sf-dir*  = /tmp/
    +;; working directory = /home/edgar
    +NIL
    +
    +> (cd 123)
    +;; directory not changed, 123 is not a string
    +;; *default-sf-dir*  = /tmp/
    +;; working directory = /home/edgar
    +NIL
    +
    + +

    The 'cd' function is intended for interactive use, in program code it's +better to use the Nyquist setdir +function.

    + +
    +(defun cd (&optional dirname)
    +  (let ((old-dir (setdir "."))
    +        (new-dir (when (stringp dirname) (setdir dirname))))
    +    (when dirname
    +      (if new-dir
    +          (when (string/= old-dir new-dir)
    +            (let ((string-end (length new-dir))
    +                  (subseq-start 0))
    +              (dotimes (index string-end)
    +                (when (char= (char new-dir index) *file-separator*)
    +                  (setq subseq-start index)))
    +              (incf subseq-start)
    +              (format t ";; directory changed to ~s~%"
    +                        (if (< subseq-start string-end)
    +                            (subseq new-dir subseq-start)
    +                            (string *file-separator*)))))
    +          (format t ";; directory not changed, ~s ~a~%" dirname
    +            (if (stringp dirname) "not found" "is not a string"))))
    +    (format t ";; *default-sf-dir*  = ~a~%" *default-sf-dir*)
    +    (format t ";; working directory = ~a~%" (setdir "."))
    +    (when new-dir t)))
    +
    + +

      Back to top

    + + + +
    + +

    ls

    + +
    + +

    The 'ls' function lists files and directories:

    + +
    +> (ls)
    +;;; /home/edgar/Downloads/nyquist/svn/nyquist
    +;;  advantages.txt  cmt/               comp-ide.bat       convert.dsp
    +;;  convert.dsw     demos/             doc/               docsrc/
    +;;  fft/            ffts/              files.txt          howtorelease.txt
    +;;  jny             jnyqide.bat        jnyqide/           lib/
    +;;  liblo/          license.txt        lpc/               macosxproject/
    +;;  macproject/     Makefile           misc/              nylsf/
    +;;  nyqide/         nyqsrc/            nyqstk/            nyquist.dsp
    +;;  nyquist.dsw     nyquist.sln        nyquist.vcproj     nyqwin.dsp
    +;;  nyqwin.vcproj   portaudio-oldv19/  portaudio/         portaudio_test/
    +;;  Readme.txt      release.bat        releasenyqide.bat  releasenyqwin.bat
    +;;  runtime/        snd/               sys/               test/
    +;;  todo.txt        tran/              xlisp/             
    +47
    +
    + +

    The algorithm to find the number of colums is +trial-and-error, for example it starts with one column:

    + +
    +<- maximum-width ->|
    +item-1 
    +item-2
    +item-3
    +item-4
    +item-5
    +
    + +

    When no line was longer than the maximum-width the +layout is saved and a new test is started with two columns:

    + +
    +<- maximum-width ->|
    +item-1  item-2
    +item-3  item-4
    +item-5
    +
    + +

    When no line was longer than the maximum-width the +layout is saved and a new test is started with three columns:

    + +
    +<- maximum-width ->|
    +item-1  item-2  item-3
    +
    + +

    As soon as a line becomes longer than the maximum-width, the +test is aborted and the saved layout from the previous run is used.

    + +

    The main reason why arrays are used instead of lists is that we need +access to predefined numbers. With lists we always first need to test if an +element exists because non-existent list elements are NIL and +not numbers:

    + +
    +(< (nth 3 '(1 2)) 0)  => error: bad argument type - NIL
    +
    + +

    It's also no good idea to use setf +with non-existent list elements:

    + +
    +(setf (nth 2 nil) 'value)  => VALUE
    +(nth 2 nil)                => error: bad argument type - NIL
    +
    + +

    Caution: The XLISP setf +special form does not signal an error if values are assigned to +non-existent places.

    + +

    We use the Common Lisp 'incf' macro because the Nyquist +incf macro has no 'increment' +argument:

    + +
    +(defmacro cl:incf (place &optional (increment 1))
    +  `(setf ,place (+ ,place ,increment)))
    +
    + +
    +(defun ls (&rest args)
    +  (let* ((dirname   (if (stringp (car args))
    +                        (prog1 (car args) (setq args (cdr args)))
    +                        (setdir ".")))
    +         (show-all (car args))
    +         (raw-list (listdir dirname)))
    +    (cond ((null raw-list)
    +           (format t ";; directory ~s not found~%" dirname))
    +          ((<= (length raw-list) 2)
    +           (format t ";;; ~a~%" dirname)
    +           (format t ";; [directory is empty]~%") 0)
    +          (t
    +           (format t ";;; ~a~%" dirname)
    +           (let ((file-separator (string *file-separator*))
    +                 (dir-list nil))
    +             (dolist (item raw-list)
    +               (when (or show-all (not (ls:hidden-p item)))
    +                 (if (listdir (strcat dirname file-separator item))
    +                     (push (strcat item "/") dir-list)
    +                     (push item dir-list))))
    +             (ls:list-items (sort dir-list #'string-lessp)))))))
    +
    +(setq *ls-hidden-start* (list "." "#"))
    +(setq *ls-hidden-end* (list "~" "#"))
    +
    +(defun ls:hidden-p (string)
    +  (let ((string-length (length string)))
    +    (or (dolist (item *ls-hidden-start* nil)
    +          (let ((subseq-end (length item)))
    +            (when (and (>= string-length subseq-end)
    +                       (string= item (subseq string 0 subseq-end)))
    +              (return t))))
    +        (dolist (item *ls-hidden-end* nil)
    +          (let ((subseq-start (- string-length (length item))))
    +            (when (and (<= 0 subseq-start)
    +                       (string= item (subseq string subseq-start)))
    +              (return t)))))))
    +
    +(defmacro ls:reset-array (array)
    +  (let ((index (gensym)))
    +    `(dotimes (,index (length ,array))
    +       (setf (aref ,array ,index) 0))))
    +
    +(defmacro ls:copy-array (from-array to-array end)
    +  (let ((index (gensym)))
    +    `(dotimes (,index ,end)
    +       (setf (aref ,to-array ,index)
    +             (aref ,from-array ,index)))))
    +
    +(defun ls:fill-string (length)
    +  (let ((string ""))
    +    (dotimes (i length)
    +      (setq string (strcat string " ")))
    +    string))
    +
    +(defun ls:list-items (item-list &optional (terminal-width 80))
    +  (let* ((separator 2)
    +         (width (- terminal-width 4))
    +         (width-max (+ width separator))
    +         (num-items (length item-list))
    +         (num-columns 1)     ; number of columns
    +         (item-array   (make-array num-items))
    +         (length-array (make-array num-items))
    +         (length-min width)  ; shortest item
    +         (length-max 0)      ; longest item
    +         (length-all 0)      ; all items + separators
    +         ;; the maximum possible number of columns is
    +         ;; width-max / (1 char + separator)
    +         (max-columns (/ width-max (1+ separator)))
    +         (column-array (make-array max-columns)))
    +
    +    ;; initialize the column-array
    +    (ls:reset-array column-array)
    +
    +    ;; copy the items from the list into the item-array
    +    (let ((item-index 0))
    +      (dolist (item item-list)
    +        (setf (aref item-array item-index) item)
    +        (incf item-index)))
    +
    +    ;; find the length of all items and store them in the length-array
    +    (dotimes (item-index num-items)
    +      (let ((length-item (length (aref item-array item-index))))
    +        (setf (aref length-array item-index) length-item
    +              length-all (+ length-all length-item separator)
    +              length-min (min length-min length-item)
    +              length-max (max length-max length-item))))
    +
    +    ;; find the number and widths of the columns
    +    (cond ((<= length-all width-max)
    +           ;; if all items together fit into a single line
    +           (setq num-columns num-items)
    +           (ls:copy-array length-array column-array num-items))
    +          ((and (> num-items 1)
    +                (<= (+ length-min length-max separator) width))
    +           ;; if there is more than one item and the
    +           ;; longest + shortest item + separator fit into one line
    +           ;; we start with two columns, one column is the fallback
    +           (incf num-columns)
    +           ;; the test-array must be 1+ because we need 1 failure-run
    +           (do ((test-array (make-array (1+ max-columns)))
    +                (item-index 0 0))
    +               ((progn
    +                  (ls:reset-array test-array)
    +                  ;; loop until there are no more items in the list
    +                  (do ((line-length 0 0))
    +                      ((>= item-index num-items))
    +                    ;; compute a complete line
    +                    (dotimes (column-index num-columns)
    +                      ;; loop through all columns in the test-array
    +                      (when (and (< item-index num-items)
    +                                 (< (aref test-array column-index)
    +                                    (aref length-array item-index)))  
    +                        ;; if there are still items in the list and the
    +                        ;; item is wider than the column, update the array
    +                        (setf (aref test-array column-index)
    +                              (aref length-array item-index)))
    +                      ;; compute the line-length from the value in the array
    +                      (cl:incf line-length
    +                               (+ (aref test-array column-index) separator))
    +                      (incf item-index))
    +                    ;; analyze the result from computing the line
    +                    (cond ((> line-length width-max)
    +                           ;; if the line is too long, abort completely, use
    +                           ;; the column-array values from the previous run
    +                           (decf num-columns)
    +                           (return t))  ; abort both 'do' loops
    +                          ((>= item-index num-items)
    +                           ;; if no items is left and no line was too long
    +                           ;; first save the test-array in the column-array
    +                           (ls:copy-array test-array column-array num-columns)
    +                           ;; then try again with one more column
    +                           (incf num-columns)))))))))
    +
    +    ;; print the items on the screen
    +    (do ((item-index 0)
    +         (last-item (1- num-items))
    +         (last-column (1- num-columns))
    +         (line ";;  " ";;  "))
    +        ((>= item-index num-items))
    +      (dotimes (column-index num-columns)
    +        ;; loop through all columns
    +        (when (< item-index num-items)
    +          ;; if there are still items in the list
    +          (setq line
    +                (if (and (< column-index last-column)
    +                         (< item-index last-item))
    +                    ;; if not the last column and not the last item
    +                    (strcat line (aref item-array item-index)
    +                      ;; add a fill-string
    +                      (let ((column (aref column-array column-index))
    +                            (item   (aref length-array item-index)))
    +                        (ls:fill-string (+ (- column item) separator))))
    +                    ;; if the last column or the last item
    +                    (strcat line (aref item-array item-index))))
    +          (incf item-index)))
    +      ;; display the line on the screen
    +      (format t "~a~%" line))
    +
    +    ;; return the number of items listed on the screen
    +    num-items))
    +
    + +

    Note: The code works, but this section is still too much mess.

    + +

      Back to top

    + + + +
    + +

    hd

    + +
    + +

    The 'hd' function prints the hexdump of a file on the screen:

    + +
    +> (hd "/tmp/edgar-temp.wav")
    +0000000000  52 49 46 46 ac 58 01 00  57 41 56 45 66 6d 74 20  RIFF.X..WAVEfmt 
    +0000000016  10 00 00 00 01 00 01 00  44 ac 00 00 88 58 01 00  ........D....X..
    +0000000032  02 00 10 00 64 61 74 61  88 58 01 00 00 00 4a 04  ....data.X....J.
    +0000000048  93 08 da 0c 1b 11 57 15  8b 19 b7 1d d7 21 ec 25  ......W......!.%
    +0000000064  f3 29 eb 2d d3 31 a9 35  6c 39 1a 3d b3 40 35 44  .).-.1.5l9.=.@5D
    +0000000080  9e 47 ee 4a 24 4e 3d 51  3a 54 19 57 d9 59 78 5c  .G.J$N=Q:T.W.Yx\
    +0000000096  f7 5e 54 61 8f 63 a6 65  99 67 67 69 10 6b 92 6c  .^Ta.c.e.ggi.k.l
    +0000000112  ee 6d 23 6f 31 70 16 71  d3 71 68 72 d4 72 17 73  .m#o1p.q.qhr.r.s
    +0000000128  31 73 23 73 eb 72 8a 72  01 72 4f 71 75 70 73 6f  1s#s.r.r.rOqupso
    +0000000144  49 6e f8 6c 80 6b e2 69  1f 68 36 66 29 64 f8 61  In.l.k.i.h6f)d.a
    +0000000160  a5 5f 2f 5d 98 5a e2 57  0b 55 17 52 05 4f d8 4b  ._/].Z.W.U.R.O.K
    +0000000176  8f 48 2c 45 b1 41 1f 3e  76 3a b9 36 e8 32 05 2f  .H,E.A.>v:.6.2./
    +0000000192  11 2b 0e 27 fe 22 e0 1e  b8 1a 86 16 4c 12 0c 0e  .+.'."......L...
    +0000000208  c7 09 7e 05 33 01 e9 fc  9f f8 57 f4 14 f0 d6 eb  ..~.3.....W.....
    +0000000224  a0 e7 72 e3 4e df 36 db  2b d7 2f d3 42 cf 67 cb  ..r.N.6.+./.B.g.
    +0000000240  9f c7 ea c3 4b c0 c3 bc  53 b9 fb b5 be b2 9d af  ....K...S.......
    +;; type "q" to quit or press Return to continue... 
    +
    + +
    +(defun hd (filename &key (start 0) end)
    +  (cond
    +    ((not (stringp filename))
    +     (format t ";; not a string ~s~%" filename))
    +    ((listdir filename)
    +     (format t ";; not a file ~s~%" string))
    +    ((or (not (integerp start)) (minusp start))
    +     (format t ";; not a non-negative integer ~s~%" start))
    +    ((and end (or (not (integerp end)) (minusp end)))
    +     (format t ";; not a non-negative integer ~s~%" end))
    +    ((and end (>= start end))
    +     (format t ";; :start ~s is greater then :end ~s~%" start end))
    +    (t (let ((file-stream (open-binary filename)))
    +         (if (null file-stream)
    +             (format t ";; file not found ~s~%" filename)
    +             (unwind-protect
    +               (hd:dump file-stream start end)
    +               (when file-stream (close file-stream))))))))
    +
    +(defun hd:dump (file-stream start end)
    +  (let ((file-position (hd:skip file-stream start))
    +        (break (+ start 255))
    +        (end-of-file nil)
    +        (end-of-dump nil))
    +    (if (< file-position start)
    +        (setq end-of-file t)
    +        (flet ((read-eight-bytes (start-position)
    +                 (let (byte-list)
    +                   (dotimes (offset 8)
    +                     (let* ((position (+ start-position offset))
    +                            (read-p (and (<= start position)
    +                                         (or (null end)
    +                                             (>= end position))))
    +                            (byte (when read-p
    +                                    (read-byte file-stream))))
    +                       (push byte byte-list)
    +                       (when byte (incf file-position))
    +                       (when (and read-p (null byte))
    +                         (setq end-of-file t))))
    +                   (reverse byte-list))))
    +          (read-line)
    +          (do ((line-start (* (/ start 16) 16) (+ line-start 16)))
    +              ((or end-of-file end-of-dump))
    +            (let* ((number  (hd:line-number line-start))
    +                   (list-1  (read-eight-bytes line-start))
    +                   (list-2  (read-eight-bytes (+ line-start 8)))
    +                   (bytes-1 (hd:byte-string list-1))
    +                   (bytes-2 (hd:byte-string list-2))
    +                   (chars   (hd:char-string (append list-1 list-2))))
    +              (format t "~a  ~a  ~a  ~a~%" number bytes-1 bytes-2 chars)
    +              (when (and end (> file-position end))
    +                (setq end-of-dump t))
    +              (when (> file-position break)
    +                (format t ";; type \"q\" to quit or press Return to continue... ")
    +                (if (string-equal "q" (read-line))
    +                    (setq end-of-dump t)
    +                    (setq break (+ break 256))))))))
    +    (when (and end (>= file-position end))
    +      (format t ";; reached specified :end at byte number ~a~%" end))
    +    (when end-of-file
    +      (format t ";; end of file at byte number ~a~%" file-position))))
    +
    +(defun hd:line-number (integer)
    +  (progv '(*integer-format*) '("%.10d")
    +    (format nil "~s" integer)))
    +
    +(defun hd:byte-string (byte-list)
    +  (let ((string ""))
    +    (dolist (byte byte-list)
    +      (setq string (strcat string (if byte
    +                                      (progv '(*integer-format*) '("%.2x")
    +                                        (format nil "~s " byte))
    +                                      "   "))))
    +    (subseq string 0 (1- (length string)))))
    +
    +(defun hd:char-string (byte-list)
    +  (let ((string ""))
    +    (dolist (byte byte-list)
    +      (setq string (strcat string (if byte
    +                                      (if (<= 32 byte 126)
    +                                          (string byte)
    +                                          ".")
    +                                      " "))))
    +    string))
    +
    +(defun hd:skip (file-stream offset)
    +  (if (= offset 0)
    +      offset
    +      (let ((count 0))
    +          (format t ";; skipping ~a bytes...~%" offset)
    +          (dotimes (ignore offset)
    +            (if (read-byte file-stream)
    +                (incf count)
    +                (return)))
    +        count)))
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/tutorials.htm b/docsrc/xlisp/xlisp-doc/tutorials/tutorials.htm new file mode 100644 index 0000000..0e7ecf5 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/tutorials.htm @@ -0,0 +1,28 @@ +Tutorials + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    Tutorials

    + +
    + + + + diff --git a/docsrc/xlisp/xlisp-doc/tutorials/xlisp-objects.htm b/docsrc/xlisp/xlisp-doc/tutorials/xlisp-objects.htm new file mode 100644 index 0000000..1b02a86 --- /dev/null +++ b/docsrc/xlisp/xlisp-doc/tutorials/xlisp-objects.htm @@ -0,0 +1,839 @@ +XLISP Objects Primer + + + + + + + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + +
    + +

    XLISP Objects Primer

    + +
    + +
      +
    1. Programming Styles
    2. +
    3. Object Oriented Programming
    4. +
    5. Xlisp Object Terminology
    6. +
    7. Sending Messages
    8. +
    9. Classes
    10. +
    11. A Better Class Example
    12. +
    13. Instances
    14. +
    15. Methods
    16. +
    17. Sending Messages To A Superclass
    18. +
    19. Object And Class
    20. +
    21. Objects Example
    22. +
    + +

    This tutorial is adapted from a 'XLISPOOP.DOC' document with +the following copyright:

    + +

    + +

    XLisp 2.0 Objects Primer by Tim I Mikkelsen - February 3, 1990

    + +
    + +

    Copyright (c) 1990 by Tim I. Mikkelsen. All Rights Reserved. No part of this +document may be copied, reproduced or translated for commercial use without +prior written consent of the author. Permission is granted for non-commercial +use as long as this notice is left intact. + +

    One of the features in the design of XLISP is object-oriented programming. +This primer is intended to serve as a very brief introduction to the object +facilities of the XLISP 2.0 dialect of LISP. Note that the object features of +XLISP are not based on other existing object definitions in other LISP dialects. +If you find problems in the primer, I'd appreciate hearing.

    + +
    + +

    Tim Mikkelsen, (tim@hpfcbig.SDE.HP.COM), 4316 Picadilly Drive, Fort Collins, +Colorado 80526

    + +

    + + + +
    + +

    1  Programming Styles

    + +
    + +

    There are many programming models, some of them are:

    + +
      +
    • procedural
    • +
    • functional
    • +
    • rule-based
    • +
    • declarative
    • +
    • object-oriented
    • +
    + +

    A language can have aspects of one or many of these programming +models.

    + +

    + +
    + +

    Procedure-Oriented

    + +

    The programming paradigm most people are familiar with is the +procedural style. The primitives in procedural programming are subroutines +and data structures. Through these primitives, programmers have some limited +abilities to share programs and program fragments. C and Pascal +are examples of procedural languages. Some procedural languages [such +as Modula and ADA] have extensions that provide for +better sharing of code.

    + +

    Object-Oriented

    + +

    Object-oriented programming is based on the primitives +of objects, classes and messages. Objects are defined in terms of classes. +Actions occur by sending a message to an object. An object's +definition can be inherited from more general classes. +Objective-C and C++ both are object-oriented +dialects of the C language. Many dialects of Lisp +have some object-oriented extension [Flavors, Common +LOOPS, CLOS and others]. There currently is standards work proceeding +to add object-oriented programming to Common +Lisp.

    + +
    + +

    + +

      Back to top

    + + + +
    + +

    2  Object Oriented Programming

    + +
    + +

    The object-oriented programming model is based around the +concepts of objects, classes and messages. An object is +essentially a black box that contains internal state information. You +send an object a message which causes the object to perform some +operation. Objects are defined and described through classes.

    + +

    One aspect of an object is that you do not have to know what is inside or +how it works to be able to use it. From a programming point of +view, this is very handy. You can develop a series of objects +for someone to use. If you need to change what goes on inside, +the users of the objects should be unaware.

    + +

    Another aspect of objects is that of inheritance. You can +build up new classes from existing classes by inheriting the existing +class's functionality and then extending the new definition. For example, +you can define a 'tool' class with various attributes and then go about +creating object instances like 'tool-1', 'tool-2', +and so on. You can also create new +sub-classes of the 'tool' class like 'power-tool'. +This is also very handy because you don't have to +re-implement something if you can build it up from +existing code.

    + +

      Back to top

    + + + +
    + +

    3  Xlisp Object Terminology

    + +
    + +

    There are many different languages with object-oriented +extensions and facilities. The terminology, operations and +styles of these are very different. Some of the main definitions for XLISP's +object-oriented extensions are:

    + +

    + +
    + +

    object data type

    + +

    The object data type is a +built-in data type of XLISP. Members of the object data type +are object instances and classes.

    + +

    object instances

    + +

    An 'object instance' is a composite structure that contains internal +state information, methods [the code which respond to messages], a +pointer to the object instance's defining class and a pointer to the +object's super-class. XLISP contains no built-in +object instances.

    + +

    class objects

    + +

    A class object is, essentially, +the template for defining the derived object instances. A class +object, although used differently from a simple object instance, is +structurally a member of the object data type. It also contains +the linking mechanism that allows you to build class hierarchies +[sub-classes and super-classes]. XLISP contains +two built-in class objects, 'object' and 'class'.

    + +

    message selector

    + +

    The 'message selector' is the symbol that is used to select a +particular action [method] from the object.

    + +

    message

    + +

    The 'message' is the combination of the message selector and the data +[if any] to be sent to the object.

    + +

    method

    + +

    The 'method' is the actual code that gets executed when the object +receives the message.

    + +
    + +

    + +

      Back to top

    + + + +
    + +

    4  Sending Messages

    + +
    + +

    The mechanism for sending messages to XLISP objects is via the +send function. It takes +an object, a message selector and various optional arguments [depending on +the message selector].

    + +

    The way that a user creates a new object is to +send a +:new message to a previously +defined class. The result of this +send will return an object, so this is +normally preceded by a +setq.

    + +
    +> (setq my-object (send object :new))
    +#<Object: #2e100>
    +
    + +

    + +

    The examples are similar to what you should see on your +computer screen. The '>' is the normal XLISP prompt, the +characters that follow the prompt is what you type in to try the examples. +Note that XLISP prints objects together with their internal pointer, like +#2e100 in the example above. These #ID numbers may not match +with the numbers you see on the screen if you try the examples, but this is +not an error.

    + +

    + +

    The object created above is of limited value. Most often, you create a +'class' object and then you create instances of that class. So +in the following example, a class called 'my-class' is +created that inherits its definition from the a built-in class definition. Then two instances are +created of the new class:

    + +
    +> (setq my-class (send class :new '()))
    +#<Object: #27756>
    +
    +> (setq my-instance (send my-class :new))
    +#<Object: #27652>
    +
    +> (setq another-instance (send my-class :new))
    +#<Object: #275da>
    +
    + +

      Back to top

    + + + +
    + +

    5  Classes

    + +
    + +

    In the examples above, a :new +message was used to create an object. The message used to see +what is in an object is the +:show message:

    + +
    +> (send my-class :show)
    +Object is #<Object: #27756>, Class is #<Object: #23fe2>
    +  MESSAGES = NIL
    +  IVARS = NIL
    +  CVARS = NIL
    +  CVALS = NIL
    +  SUPERCLASS = #<Object: #23fd8>
    +  IVARCNT = 0
    +  IVARTOTAL = 0
    +#<Object: #27756>
    +
    + +

    From the display of the 'my-class' object you can see there are a +variety of components. The components of a class are:

    + +

    + +
    + +

    class pointer

    + +

    This pointer shows to what class the object [instance or class] +belongs. For a class, this always points to the built-in object +class. This is also true of the +class object, its class pointer points +to itself.

    + +

    superclass pointer

    + +

    This pointer shows what the next class up the class hierarchy +is. If the user does not specify what class is the +superclass, it will point to the built-in class +object.

    + +

    messages

    + +

    This component shows what messages are allowed for the class, and the +description of the method that will be used. If the method is +system-defined, it will show up in the form +of:

    + +
    +#<Subr-: #18b98>
    +
    + +

    Remember that the class hierarchy [through the superclass pointer] is +searched if the requested message is not found in the class.

    + +

    instance variables

    + +

    The IVARS component lists what instance variables will be created +when an object instance is created. If no instances of the +class exist, there are no instance variables. If there are +5 instances of a class, there are 5 complete and +different groups of the instance variables.

    + +

    class variables and values

    + +

    The CVARS component lists what class variables exist within the +class. The CVALS component shows what the current values of the variables +are. Class variables are used to hold state information about a class. There +will be one of each of the class variables, independent of the number of +instances of the class created.

    + +
    + +

    + +

      Back to top

    + + + +
    + +

    6  A Better Class Example

    + +
    + +

    The example shown in the previous section does work, but the class and +instances created don't really do anything of interest. The following +example sets up a tool class and creates some tool instances:

    + +
    +> (setq my-tools (send class :new '(power moveable operation)))
    +#<Object: #277a6>
    +
    +> (send my-tools :answer :isnew '(pow mov op) 
    +    '((setq power pow moveable mov operation op))
    +#<Object: #277a6>
    +
    +> (setq drill (send my-tools :new 'AC t 'holes))
    +#<Object: #2ddbc>
    +
    +> (setq hand-saw (send my-tools :new 'none t 'cuts))
    +#<Object: #2dc40>
    +
    +> (setq table-saw (send my-tools :new 'AC nil 'cuts))
    +#<Object: #2db00>
    +
    + +

    A class of objects called 'my-tools' and three instances +were created:

    + +

      [Figure 1]

    + +

    First the class 'my-tools' was created by sending the +:new message to the +built-in class object. +Then, within the 'my-tool' class, three instances called +'drill', 'hand-saw' and 'table-saw' were +created by sending the :new +message to the 'my-tools' class. Notice the three parameters +following the message selector. The instance variables are initialized +from these parameters by the :isnew method, inherited from the +'my-tools' class at the time when the instances were created.

    + +

      Back to top

    + + + +
    + +

    7  Instances

    + +
    + +

    The following is a display of the contents of some of the instances +created above, where the XLISP object #ID numbers had been replaced by the +respective class and instance names:

    + +
    +> (send drill :show)
    +Object is #<Object: #[drill]>, Class is #<Object: #[my-tools]>
    +  POWER = AC
    +  MOVEABLE = T
    +  OPERATION = HOLES
    +#<Object: #[drill]>
    +
    +> (send hand-saw :show)
    +Object is #<Object: #[hand-saw]>, Class is #<Object: #[my-tools]>
    +  POWER = NONE
    +  MOVEABLE = T
    +  OPERATION = CUTS
    +#<Object: #[hand-saw]>
    +
    + +

    From the display of these instances you can see there are some +components and values. The components of an instance are:

    + +

    + +
    + +

    class pointer

    + +

    This pointer shows to which class the current object instance +belongs. It is through this link that the system finds the methods to +execute for the received messages.

    + +

    instance variables and values

    + +

    The variables existing within the instance are shown together with +their values. Instance Variables are used to hold state information for each +instance. There will be a group of instance variables for each +instance.

    + +
    + +

    + +

      Back to top

    + + + +
    + +

    8  Methods

    + +
    + +

    There have been a few of the messages and methods in XLISP shown to this +point like :new and +:show. The following are the +methods built into XLISP:

    + +

    + +
    + +

    :answer

    + +

    The :answer method +allows you to define or change methods within a class.

    + +

    :class

    + +

    The :class method +returns the class of an object.

    + +

    :isnew

    + +

    The :isnew method causes an +instance to run its initialization code. When the +:isnew method is run on a class, it +resets the class state. This allows you to re-define instance +variables, class variables, etc.

    + +

    :new

    + +

    The :new method allows you +to create an instance when the +:new message is sent to a +user-defined class. The +:new method allows you to create +a new class when the :new message +is sent to the +built-in class.

    + +

    :show

    + +

    The :show method displays the instance or class.

    + +

    :isa

    + +

    The :isa method tests if +an object inherits from a class.

    + +
    + +

    + +

      Back to top

    + + + +
    + +

    9  Sending Messages To A Superclass

    + +
    + +

    In addition to the send function, +there is another function called +send-super. The +send-super +function causes the specified message to be performed by the superclass +method. This is a mechanism to allow chaining of methods in a class +hierarchy. This chaining behavior can be achieved by creating a method for a +class with the :answer +message. Within the body of the method, you include a +send-super form. This +function is allowed only inside the execution of a method of an object.

    + +

      Back to top

    + + + +
    + +

    10  Object And Class

    + +
    + +

    The definition of the built-in class 'object' is:

    + +
    +> (send object :show)
    +Object is #<Object: #[built-in-object]>, Class is #<Object: #[built-in-class]>
    +  MESSAGES = ((:ISA   . #<Subr-: #[built-in-isa-method]>)
    +              (:SHOW  . #<Subr-: #[built-in-show-method]>)
    +              (:CLASS . #<Subr-: #[built-in-class-method]>)
    +              (:ISNEW . #<Subr-: #[built-in-isnew-method]>))
    +  IVARS = NIL
    +  CVARS = NIL
    +  CVALS = NIL
    +  SUPERCLASS = NIL  ; no superclass
    +  IVARCNT = 0
    +  IVARTOTAL = 0
    +#<Object: #[built-in-object]>
    +
    + +

    Note that 'object' is a class, as opposed to an 'instance-style' object. +'object' has no superclass, it is the top or root of the class hierarchy. +'object's class is 'class'.

    + +
    +> (send class :show)
    +Object is #<Object: #[built-in-class]>, Class is #<Object: #[built-in-class]>
    +  MESSAGES = ((:ANSWER . #<Subr-: #[built-in-answer-method]>) 
    +              (:ISNEW  . #<Subr-: #[built-in-isnew-method]>) 
    +              (:NEW    . #<Subr-: #[built-in-new-method]>))
    +  IVARS = (MESSAGES IVARS CVARS CVALS SUPERCLASS IVARCNT IVARTOTAL)
    +  CVARS = NIL
    +  CVALS = NIL
    +  SUPERCLASS = #<Object: #[built-in-object]>
    +  IVARCNT = 7
    +  IVARTOTAL = 7
    +#<Object: #[built-in-class]>
    +
    + +

    'class' has a superclass of 'object'. It's class is itself, 'class'.

    + +

      Back to top

    + + + +
    + +

    11  Objects Example

    + +
    + +

    The following is an example, using the idea of tools again. It +contains a hierarchy of tool classes. The top of the +class hierarchy is 'tools'. 'hand-tools' and +'shop-tools' are sub-classes of 'tools'. The +example creates instances of these sub-classes. It +is possible to extend this example in various ways. One obvious +extension would be to create a third tier of classes under +'hand-tools' that could contain classes like drills, +screwdrivers, pliers and so on.

    + +
    +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    +;;
    +;;       Define the superclasses and classes
    +;;
    +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    +;;
    +;; make TOOLS superclass
    +;;
    +;;   with a different :ISNEW method
    +;;   added methods are :BORROW and :RETURN
    +;;
    +;;   class variables      NUMBER        contains # of tool instances
    +;;                        ACTIVE-LIST   contains list of current objects
    +;;
    +;;   instance variables   POWER         list - (AC BATTERY HAND)
    +;;                        MOVEABLE      CAN-CARRY or CAN-ROLL or FIXED
    +;;                        OPERATIONS    list
    +;;                        MATERIAL      list - (WOOD METAL PLASTIC ...)
    +;;                        PIECES        list
    +;;                        LOCATION      HOME or person's name
    +;;
    +
    +(setq tools (send class :new '(power moveable operations
    +                               material pieces location) 
    +                             '(number active-list)))
    +
    +(send tools :answer :isnew '() 
    +  '((setq number      (if (null number) 1 (1+ number))
    +          active-list (cons self active-list)
    +          location    'home)))
    +
    +(send tools :answer :borrow '(by-who)
    +  '((if (eq location 'home)
    +        (setq location by-who)
    +        (print "you can't"))))
    +
    +(send tools :answer :return '()
    +  '((if (eq location 'home)
    +        (print "got it already")
    +        (setq location 'home))))
    +
    +;; make HAND-TOOLS class
    +;; - with a different :ISNEW method
    +;; - new instance variable WEIGHT = <number> of pounds
    +;; - the rest is inherited from TOOLS
    + 
    +(setq hand-tools (send class :new '(weight) '() tools))
    +
    +(send hand-tools :answer :isnew '(pow op mat parts w-in)
    +  '((setq power       pow
    +          moveable    'can-carry
    +          operations  op
    +          material    mat
    +          pieces      parts
    +          weight      w-in)
    +    (send-super :isnew)))
    +
    +;; make SHOP-TOOLS class
    +;; - with a different :ISNEW method
    +;; - no new instance variables
    +;; - the rest is inherited from TOOLS
    +
    +(setq shop-tools (send class :new '() '() tools))
    +
    +(send shop-tools :answer :isnew '(pow mov op mat parts)
    +  '((setq power       pow
    +          moveable    mov
    +          operations  op
    +          material    mat
    +          pieces      parts)
    +    (send-super :isnew)))
    +
    +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    +;;
    +;;       Create instances of various tool classes
    +;;
    +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    +
    +(setq hand-drill (send hand-tools :new       ; make an instance - HAND-DRILL
    +                                  '(ac) 
    +                                  '(drill polish grind screw)
    +                                  '(wood metal plastic)
    +                                  '(drill drill-bits screw-bits buffer)
    +                                  '2.5))
    +
    +(setq table-saw  (send shop-tools :new       ; make an instance - TABLE-SAW
    +                                  '(ac)
    +                                  'fixed
    +                                  '(rip cross-cut)
    +                                  '(wood plastic)
    +                                  '(saw blades fence)))
    +
    +(setq radial-arm (send shop-tools :new       ; make an instance = RADIAL-ARM
    +                                  '(ac)
    +                                  'can-roll
    +                                  '(rip cross-cut)
    +                                  '(wood plastic)
    +                                  '(saw blades dust-bag)))
    +
    + +

    The following session shows how to use the tool definitions from the +code above:

    + +
    +> (send hand-drill :borrow 'fred)
    +FRED
    +
    +> (send table-saw :return)
    +"got it already"
    +"got it already"
    +
    +> (send hand-drill :borrow 'joe)
    +"you can't"
    +"you can't"
    +
    +> (send hand-drill :return)
    +HOME
    +
    + +

    Fred was able to borrow the 'hand-drill'. When an attempt +was made to return the 'table-saw', it was already at home. +A second attempt to borrow the 'hand-drill' +indicated that "you can't" because it was already +lent out. Lastly, the 'hand-drill' was returned +successfully. [Note that the "got it +already" and "you can't" strings show up +twice in the display because the methods both print and return the +string.)

    + +

    The following example shows the structure of the 'tools' object with the +XLISP #ID numbers replaced by the related class and method names:

    + +
    +> (send tools :show)
    +Object is #<Object: #[tools]>, Class is #<Object: #[class]>
    +  MESSAGES = ((:RETURN . #<Closure-:RETURN: #[tools-return-method]>) 
    +              (:BORROW . #<Closure-:BORROW: #[tools-borrow-method]>) 
    +              (:ISNEW  . #<Closure-:ISNEW:  #[tools-isnew-method]>))
    +  IVARS = (POWER MOVEABLE OPERATIONS MATERIAL PIECES LOCATION)
    +  CVARS = (NUMBER ACTIVE-LIST)
    +  CVALS = #(3 (#<Object: #[radial-arm]> 
    +               #<Object: #[table-saw]> 
    +               #<Object: #[hand-drill]>))
    +  SUPERCLASS = #<Object: #[object]>
    +  IVARCNT = 6
    +  IVARTOTAL = 6
    +#<Object: #[tools]>
    +
    + +

    The two 'tools' sub-classes 'hand-tools' and 'shop-tools' structure looks +like:

    + +
    +> (send hand-tools :show)
    +Object is #<Object: #[hand-tools]>, Class is #<Object: #[class]>
    +  MESSAGES = ((:ISNEW . #<Closure-:ISNEW: #[hand-tools-isnew-method]>))
    +  IVARS = (WEIGHT)
    +  CVARS = NIL
    +  CVALS = NIL
    +  SUPERCLASS = #<Object: #[tools]>
    +  IVARCNT = 1
    +  IVARTOTAL = 7
    +#<Object: #[hand-tools]>
    +
    +> (send shop-tools :show)
    +Object is #<Object: #[shop-tools]>, Class is #<Object: #[class]>
    +  MESSAGES = ((:ISNEW . #<Closure-:ISNEW: #[shop-tools-isnew-method]>))
    +  IVARS = NIL
    +  CVARS = NIL
    +  CVALS = NIL
    +  SUPERCLASS = #<Object: #[tools]>
    +  IVARCNT = 0
    +  IVARTOTAL = 6
    +#<Object: #[shop-tools]>
    +
    + +

    The class 'hand-tools' has an instance 'hand-drill' which looks like:

    + +
    +> (send hand-drill :show)
    +Object is #<Object: #[hand-drill]>, Class is #<Object: #[hand-tools]>
    +  WEIGHT = 2.5
    +  POWER = (AC)
    +  MOVEABLE = CAN-CARRY
    +  OPERATIONS = (DRILL POLISH GRIND SCREW)
    +  MATERIAL = (WOOD METAL PLASTIC)
    +  PIECES = (DRILL DRILL-BITS SCREW-BITS BUFFER)
    +  LOCATION = HOME
    +#<Object: #[hand-drill]>
    +
    + +

      Back to top

    + +
    + +Nyquist / XLISP 2.0  -  +Contents | +Tutorials | +Examples | +Reference + + \ No newline at end of file diff --git a/docsrc/xlisp/xlisp-doc/tutorials/xobj-1.png b/docsrc/xlisp/xlisp-doc/tutorials/xobj-1.png new file mode 100644 index 0000000..b22d557 Binary files /dev/null and b/docsrc/xlisp/xlisp-doc/tutorials/xobj-1.png differ diff --git a/docsrc/xlisp/xlisp-no-sal.mss b/docsrc/xlisp/xlisp-no-sal.mss new file mode 100644 index 0000000..ee48721 --- /dev/null +++ b/docsrc/xlisp/xlisp-no-sal.mss @@ -0,0 +1,3339 @@ +@define(codef, FaceCode T, size 11) +@comment{In my original scribe conversion of the ascii xlisp documentation, I used + times roman fonts for xlisp function names and code text in general. To be + consistent with Nyquist documentation, I have changed the code font to xlcode + which is defined here. If this turns out to be a problem, redefine xlcode to + use the regular FaceCode. -RBD} +@define(xlcode, FaceCode T, size 11) +@textform(pragma=[]) +@section(Introduction) + XLISP is an experimental programming language combining some of + the features of Common Lisp with an object-oriented extension + capability. It was implemented to allow experimentation with + object-oriented programming on small computers. + + Implementations of XLISP run on virtually every operating system. + XLISP is completely written in the programming language + C and is easily extended with user written built-in functions + and classes. It is available in source form to non-commercial + users. + + Many Common Lisp functions are built into XLISP. In addition, + XLISP defines the objects Object and Class as primitives. + Object is the only class that has no superclass and hence is + the root of the class hierarchy tree. Class is the class of + which all classes are instances (it is the only object that is + an instance of itself). + + This document is a brief description of XLISP. It assumes some + knowledge of LISP and some understanding of the concepts of + object-oriented programming. + + I recommend the book @i(Lisp) by Winston and Horn and published by + Addison Wesley for learning Lisp. The first edition of this + book is based on MacLisp and the second edition is based on + Common Lisp. + + You will probably also need a copy of @i(Common Lisp: The + Language) by Guy L. Steele, Jr., published by Digital Press to + use as a reference for some of the Common Lisp functions that + are described only briefly in this document. + + @section(A Note From The Author) + + If you have any problems with XLISP, feel free to contact me [me being David Betz - RBD] for + help or advice. Please remember that since XLISP is available + in source form in a high level language, many users [e.g. that Dannenberg fellow - RBD] have been + making versions available on a variety of machines. If you call + to report a problem with a specific version, I may not be able + to help you if that version runs on a machine to which I don't + have access. Please have the version number of the version that + you are running readily accessible before calling me. + + If you find a bug in XLISP, first try to fix the bug yourself + using the source code provided. If you are successful in fixing + the bug, send the bug report along with the fix to me. If you + don't have access to a C compiler or are unable to fix a bug, + please send the bug report to me and I'll try to fix it. + + Any suggestions for improvements will be welcomed. Feel free to + extend the language in whatever way suits your needs. However, + PLEASE DO NOT RELEASE ENHANCED VERSIONS WITHOUT CHECKING WITH ME + FIRST!! I would like to be the clearing house for new features + added to XLISP. If you want to add features for your own + personal use, go ahead. But, if you want to distribute your + enhanced version, contact me first. Please remember that the + goal of XLISP is to provide a language to learn and experiment + with LISP and object-oriented programming on small computers. I + don't want it to get so big that it requires megabytes of memory + to run. + + + @section(XLISP Command Loop)@index(XLISP Command Loop)@index(Command Loop) + + When XLISP is started, it first tries to load the workspace + @code(xlisp.wks) from the current directory. If that file doesn't + exist, XLISP builds an initial workspace, empty except for the + built-in functions and symbols. + + Then XLISP attempts to load @code(init.lsp) from the current + directory. It then loads any files named as parameters on the + command line (after appending @code(.lsp) to their names). + + XLISP then issues the following prompt: +@begin(example) + > +@end(example) + This indicates that XLISP is waiting for an expression to be + typed. + + When a complete expression has been entered, XLISP attempts to + evaluate that expression. If the expression evaluates + successfully, XLISP prints the result and then returns to the + initial prompt waiting for another expression to be typed. + + @section(Special Characters)@index(control characters, XLISP) + + When XLISP is running from a console, some control characters invoke operations: +@begin(itemize) +Backspace and Delete characters erase the previous character on the input line (if any). + +Control-U erases the entire input line. + +Control-C executes the TOP-LEVEL function. + +Control-G executes the CLEAN-UP function. + +Control-P executes the CONTINUE function. + +Control-B stops execution and enters the break command loop. Execution can be continued by typing Control-P or (CONTINUE). + +Control-E turns on character echoing (Linux and Mac OS X only). + +Control-F turns off character echoing (Linux and Mac OS X only). + +Control-T evaluates the INFO function. +@end(itemize) + + @section(Break Command Loop)@index(break) + + When XLISP encounters an error while evaluating an expression, + it attempts to handle the error in the following way: + + If the symbol @xlcode(*breakenable*@index(*breakenable*)) is + true, the message corresponding to the error is printed. If + the error is correctable, the correction message is printed. + + If the symbol @xlcode(*tracenable*@index(*tracenable*)) is true, a trace back is printed. + The number of entries printed depends on the value of the symbol + @xlcode(*tracelimit*@index(*tracelimit*)). If this symbol is set to something other than a + number, the entire trace back stack is printed. + + XLISP then enters a read/eval/print loop to allow the user to + examine the state of the interpreter in the context of the + error. This loop differs from the normal top-level + read/eval/print loop in that if the user invokes the function + @xlcode(continue), XLISP will continue from a correctable error. If + the user invokes the function @xlcode(clean-up), XLISP will abort the + break loop and return to the top level or the next lower + numbered break loop. When in a break loop, XLISP prefixes the + break level to the normal prompt. + + If the symbol @xlcode(*breakenable*@index(*breakenable*)) is @xlcode(nil), XLISP looks for a + surrounding errset function. If one is found, XLISP examines + the value of the print flag. If this flag is true, the error + message is printed. In any case, XLISP causes the errset + function call to return @xlcode(nil). + + If there is no surrounding errset function, XLISP prints the + error message and returns to the top level. + + @section(Data Types)@index(XLISP Data Types)@index(Data Types) + + There are several different data types available to XLISP + programmers. + +@begin(itemize) +lists + +symbols + +strings + +integers + +characters + +floats + +objects + +arrays + +streams + +subrs (built-in functions) + +fsubrs (special forms) + +closures (user defined functions) +@end(itemize) + + + + +@section(The Evaluator)@index(evaluator)@index(XLISP evaluator) + + The process of evaluation in XLISP: +@begin(itemize) + Strings, integers, characters, floats, objects, arrays, streams, + subrs, fsubrs and closures evaluate to themselves. + + Symbols act as variables and are evaluated by retrieving the + value associated with their current binding. + + Lists are evaluated by examining the first element of the list + and then taking one of the following actions: +@begin(itemize) + If it is a symbol, the functional binding of the symbol is + retrieved. + + If it is a lambda expression, a closure is constructed for + the function described by the lambda expression. + + If it is a subr, fsubr or closure, it stands for itself. + + Any other value is an error. +@end(itemize) + Then, the value produced by the previous step is examined: +@begin(itemize) + If it is a subr or closure, the remaining list elements are + evaluated and the subr or closure is called with these + evaluated expressions as arguments. + + If it is an fsubr, the fsubr is called using the remaining + list elements as arguments (unevaluated). + + If it is a macro, the macro is expanded using the remaining + list elements as arguments (unevaluated). The macro + expansion is then evaluated in place of the original macro + call. +@end(itemize) +@end(itemize) + +@section(Lexical Conventions)@index(Lexical conventions)@index(XLISP Lexical Conventions) + + The following conventions must be followed when entering XLISP + programs: + + Comments in XLISP code begin with a semi-colon character and + continue to the end of the line. + + Symbol names in XLISP can consist of any sequence of non-blank + printable characters except the following: +@begin(example) + ( ) ' ` , " ; +@end(example) + Uppercase and lowercase characters are not distinguished within + symbol names. All lowercase characters are mapped to uppercase + on input. + + Integer literals consist of a sequence of digits optionally + beginning with a @code(+) or @code(-). The range of values an integer can + represent is limited by the size of a C @code(long) on the machine on + which XLISP is running. + + Floating point literals consist of a sequence of digits + optionally beginning with a @code(+) or @code(-) and including an embedded + decimal point. The range of values a floating point number can + represent is limited by the size of a C @code(float) (@code(double) on + machines with 32 bit addresses) on the machine on which XLISP is + running. + + Literal strings are sequences of characters surrounded by double + quotes. Within quoted strings the ``@code(\)'' character is used to + allow non-printable characters to be included. The codes + recognized are: +@begin(itemize) +@code(\\) means the character ``@code(\)'' + +@code(\n) means newline + +@code(\t) means tab + +@code(\r) means return + +@code(\f) means form feed + +@code(\nnn) means the character whose octal code is nnn +@end(itemize) + +@section(Readtables)@index(Readtables) + + The behavior of the reader is controlled by a data structure + called a @i(readtable). The reader uses the symbol @xlcode(*readtable*@index(*readtable*)) to + locate the current readtable. This table controls the + interpretation of input characters. It is an array with 128 + entries, one for each of the ASCII character codes. Each entry + contains one of the following things: +@begin(itemize) + @xlcode(NIL) @itemsep Indicating an invalid character + + @xlcode(:CONSTITUENT) @itemsep Indicating a symbol constituent + + @xlcode(:WHITE-SPACE) @itemsep Indicating a whitespace character + + @xlcode[(:TMACRO . @i(fun))] @itemsep Terminating readmacro + + @xlcode[(:NMACRO . @i(fun))] @itemsep Non-terminating readmacro + + @xlcode(:SESCAPE) @itemsep Single escape character ('\') + + @xlcode(:MESCAPE) @itemsep Multiple escape character ('|') +@end(itemize) + + In the case of @xlcode(:TMACRO) and @xlcode(:NMACRO), the @i(fun) component is a + function. This can either be a built-in readmacro function or a + lambda expression. The function should take two parameters. + The first is the input stream and the second is the character + that caused the invocation of the readmacro. The readmacro + function should return @xlcode(NIL) to indicate that the character should + be treated as white space or a value consed with @xlcode(NIL) to indicate + that the readmacro should be treated as an occurence of the + specified value. Of course, the readmacro code is free to read + additional characters from the input stream. + + XLISP defines several useful read macros@index(read macros): +@begin(itemize) + @xlcode(')@i[] == @xlcode{(quote} @i[]@xlcode{)} + + @xlcode(#')@i[] == @xlcode{(function} @i[]@xlcode{)} + + @xlcode{#(}@i[]...@xlcode{)} == an array of the specified expressions + + @xlcode(#x)@i[] == a hexadecimal number (0-9,A-F) + + @xlcode(#o)@i[] == an octal number (0-7) + + @xlcode(#b)@i[] == a binary number (0-1) + + @xlcode(#\)@i[] == the ASCII code of the character + + @xlcode(#|) ... @xlcode(|#) == a comment + + @xlcode(#:)@i[] == an uninterned symbol + + @xlcode(`)@i[] == @xlcode{(backquote} @i[]@xlcode{)} + + @xlcode(,)@i[] == @xlcode{(comma} @i[]@xlcode{)} + + @xlcode(,@@)@i[] == @xlcode{(comma-at} @i[]@xlcode{)} + +@end(itemize) +@section(Lambda Lists)@index(Lambda Lists) + + There are several forms in XLISP that require that a ``lambda + list'' be specified. A lambda list is a definition of the + arguments accepted by a function. There are four different + types of arguments. + + The lambda list starts with required arguments. Required + arguments must be specified in every call to the function. + + The required arguments are followed by the @xlcode(&optional) arguments. + Optional arguments may be provided or omitted in a call. An + initialization expression may be specified to provide a default + value for an @xlcode(&optional) argument if it is omitted from a call. + If no initialization expression is specified, an omitted + argument is initialized to @xlcode(NIL). It is also possible to provide + the name of a @xlcode(supplied-p) variable that can be used to + determine if a call provided a value for the argument or if the + initialization expression was used. If specified, the supplied- + p variable will be bound to T if a value was specified in the + call and @xlcode(NIL) if the default value was used. + + The @xlcode(&optional) arguments are followed by the @xlcode(&rest) argument. The + @xlcode(&rest) argument gets bound to the remainder of the argument list + after the required and @xlcode(&optional) arguments have been removed. + + The @xlcode(&rest) argument is followed by the @xlcode(&key) arguments. When a + keyword argument is passed to a function, a pair of values + appears in the argument list. The first expression in the pair + should evaluate to a keyword symbol (a symbol that begins with a + ``@code(:)''). The value of the second expression is the value of the + keyword argument. Like @xlcode(&optional) arguments, @xlcode(&key) arguments can + have initialization expressions and supplied-p variables. In + addition, it is possible to specify the keyword to be used in a + function call. If no keyword is specified, the keyword obtained + by adding a ``@code(:)'' to the beginning of the keyword argument symbol + is used. In other words, if the keyword argument symbol is + @xlcode(foo), the keyword will be @xlcode(:foo). + + The @xlcode(&key) arguments are followed by the @xlcode(&aux) variables. These + are local variables that are bound during the evaluation of the + function body. It is possible to have initialization + expressions for the @xlcode(&aux) variables. + + Here is the complete syntax for lambda lists: +@begin(display) + (@i... + [@xlcode(&optional) [@i | (@i [@i [@i]])]...] + [@xlcode(&rest) @i] + [@xlcode(&key) + [@i | ([@i | (@i @i)] [@i [@i]])]... + @xlcode(&allow)-other-keys] + [@xlcode(&aux) + [@i | (@i [@i])]...]) + + where: + + @i is a required argument symbol + @i is an @xlcode(&optional) argument symbol + @i is the @xlcode(&rest) argument symbol + @i is a @xlcode(&key) argument symbol + @i is a keyword symbol + @i is an auxiliary variable symbol + @i is an initialization expression + @i is a supplied-p variable symbol +@end(display) + + +@section(Objects)@index(Objects)@label(objects-sec) + + Definitions: +@begin(itemize) +selector @itemsep a symbol used to select an appropriate method + +message @itemsep a selector and a list of actual arguments + +method @itemsep the code that implements a message +@end(itemize) + Since XLISP was created to provide a simple basis for + experimenting with object-oriented programming, one of the + primitive data types included is @i(object). In XLISP, an object + consists of a data structure containing a pointer to the + object's class as well as an array containing the values of the + object's instance variables. + + Officially, there is no way to see inside an object (look at the + values of its instance variables). The only way to communicate + with an object is by sending it a message. + + You can send a message to an object using the @xlcode(send) function. + This function takes the object as its first argument, the + message selector as its second argument (which must be a symbol) + and the message arguments as its remaining arguments. + + The @xlcode(send) function determines the class of the receiving object + and attempts to find a method corresponding to the message + selector in the set of messages defined for that class. If the + message is not found in the object's class and the class has a + super-class, the search continues by looking at the messages + defined for the super-class. This process continues from one + super-class to the next until a method for the message is found. + If no method is found, an error occurs. + +@begin(comment) +THIS IS WRONG -- I DON'T KNOW IF IT WAS CORRECT IN THE ORIGINAL XLISP. -RBD + A message can also be sent from the body of a method by using + the current object, but the method lookup starts with the + object's superclass rather than its class. This allows a + subclass to invoke a standard method in its parent class even + though it overrides that method with its own specialized + version. +@end(comment) + + When a method is found, the evaluator binds the receiving object + to the symbol @xlcode(self) and evaluates the method using the + remaining elements of the original list as arguments to the + method. These arguments are always evaluated prior to being + bound to their corresponding formal arguments. The result of + evaluating the method becomes the result of the expression. + + Within the body of a method, a message can be sent to the current + object by calling the @xlcode[(send self ...)]. The method lookup + starts with the object's class regardless of the class containing + the current method. + + Sometimes it is desirable to invoke a general method in a superclass + even when it is overridden by a more specific method in a subclass. + This can be accomplished by calling @xlcode(send-super), which begins + the method lookup in the superclass of the class defining the current + method rather than in the class of the current object. + + The @xlcode(send-super) function takes a selector as its first argument + (which must be a symbol) and the message arguments as its remaining + arguments. Notice that @xlcode(send-super) can only be sent from within + a method, and the target of the message is always the current object + (@xlcode(self)). @xlcode[(send-super ...)] is similar to + @xlcode[(send self ...)] except that method lookup begins in the + superclass of the class containing the current method + rather than the class of the current object. + +@section(The ``Object'' Class)@index(Object Class) + +@xlcode(Object)@index(Object) @itemsep the top of the class hierarchy. + +Messages: +@begin(fdescription) +@xlcode(:show@index(:show)) @itemsep show an object's instance variables. +@begin(pdescription) +returns @itemsep the object +@end(pdescription) +@blankspace(1) + +@xlcode{:class@index(:class)} @itemsep return the class of an object +@begin(pdescription) +returns @itemsep the class of the object +@end(pdescription) +@blankspace(1) + +@xlcode{:isa@index(:isa)} @i(class) @itemsep test if object inherits from class +@begin(pdescription) +returns @itemsep @xlcode(t) if object is an instance of @i(class) or a subclass of @i(class), otherwise @xlcode(nil) +@end(pdescription) +@blankspace(1) + +@xlcode(:isnew@index(:isnew)) @itemsep the default object initialization routine +@begin(pdescription) +returns @itemsep the object +@end(pdescription) +@end(fdescription) + +@section(The ``Class'' Class)@index(Class class) + +@xlcode(Class@index(Class)) @itemsep class of all object classes (including itself) + + Messages: + +@begin(fdescription) + @xlcode(:new@index(:new)) @itemsep create a new instance of a class +@begin(pdescription) + returns @itemsep the new class object +@end(pdescription) +@blankspace(1) + + @xlcode(:isnew@index(:isnew)) @i [@i [@i]] @itemsep initialize a new class +@begin(pdescription) + @i @itemsep the list of instance variable symbols + + @i @itemsep the list of class variable symbols + + @i @itemsep the superclass (default is object) + + returns @itemsep the new class object +@end(pdescription) +@blankspace(1) + + @xlcode(:answer@index(:answer)) @i @i @i @itemsep add a message to a class +@begin(pdescription) + @i @itemsep the message symbol + + @i @itemsep the formal argument list (lambda list) + + @i @itemsep a list of executable expressions + + returns @itemsep the object +@end(pdescription) +@blankspace(1) +@end(fdescription) + + When a new instance of a class is created by sending the message + @xlcode(:new) to an existing class, the message @xlcode(:isnew) followed by + whatever parameters were passed to the @xlcode(:new) message is sent to + the newly created object. + + When a new class is created by sending the @xlcode(:new) message to the + object @xlcode(Class), an optional parameter may be specified + indicating the superclass of the new class. If this parameter + is omitted, the new class will be a subclass of @xlcode(Object). A + class inherits all instance variables, class variables, and + methods from its super-class. + +@section(Profiling)@index(profiling) +The Xlisp 2.0 release has been extended with a profiling facility, which counts how many times and where @xlcode(eval) is executed. A separate count is maintained for each named function, closure, or macro, and a count indicates an @xlcode(eval) in the immediately (lexically) enclosing named function, closure, or macro. Thus, the count gives an indication of the amount of time spent in a function, not counting nested function calls. The list of all functions executed is maintained on the global @xlcode(*profile*) variable. These functions in turn have @xlcode(*profile*) properties, which maintain the counts. The profile system merely increments counters and puts symbols on the @xlcode(*profile*) list. It is up to the user to initialize data and gather results. Profiling is turned on or off with the @xlcode(profile) function. Unfortunately, methods cannot be profiled with this facility. + +@label(symbols-sec) +@section(Symbols)@index(symbols) +@begin(itemize) +@codef(self)@pragma(defn)@index(self) @dash the current object (within a method context) + +@codef(*obarray*@pragma(defn)@index(*obarray*)) @dash the object hash table + +@codef(*standard-input*@pragma(defn)@index(*standard-input*)) @dash the standard input stream + +@codef(*standard-output*@pragma(defn)@index(*standard-output*)) @dash the standard output stream + +@codef(*error-output*@pragma(defn)@index(*error-output*)) @dash the error output stream + +@codef(*trace-output*@pragma(defn)@index(*trace-output*)) @dash the trace output stream + +@codef(*debug-io*@pragma(defn)@index(*debug-io*)) @dash the debug i/o stream + +@codef(*breakenable*@pragma(defn)@index(*breakenable*)) @dash flag controlling entering break loop on errors + +@codef(*tracelist*@pragma(defn)@index(*tracelist*)) @dash list of names of functions to trace + +@codef(*tracenable*@pragma(defn)@index(*tracenable*)) @dash enable trace back printout on errors + +@codef(*tracelimit*@pragma(defn)@index(*tracelimit*)) @dash number of levels of trace back information + +@codef(*evalhook*@pragma(defn)@index(*evalhook*)) @dash user substitute for the evaluator function + +@codef(*applyhook*@pragma(defn)@index(*applyhook*)) @dash (not yet implemented) + +@codef(*readtable*@pragma(defn)@index(*readtable*)) @dash the current readtable + +@codef(*unbound*@pragma(defn)@index(*unbound*)) @dash indicator for unbound symbols + +@codef(*gc-flag*@pragma(defn)@index(*gc-flag*)) @dash controls the printing of gc messages + +@codef(*gc-hook*@pragma(defn)@index(*gc-hook*)) @dash function to call after garbage collection + +@codef(*integer-format*@pragma(defn)@index(*integer-format*)) @dash format for printing integers (``%d'' or ``%ld'') + +@codef(*float-format*@pragma(defn)@index(*float-format*)) @dash format for printing floats (``%g'') + +@codef(*print-case*@pragma(defn)@index(*print-case*)) @dash symbol output case (:upcase or :downcase) +@end(itemize) + + There are several symbols maintained by the read/eval/print + loop. The symbols @code(+), @code(++), and @code(+++) are bound to the most + recent three input expressions. The symbols @code(*), @code(**) and @code(***) + are bound to the most recent three results. The symbol @code(-) is + bound to the expression currently being evaluated. It becomes + the value of @code(+) at the end of the evaluation. +@section(Evaluation Functions)@index(evaluation functions) +@begin(fdescription) + (eval@pragma(defn)@index(eval) @i) @itemsep evaluate an xlisp expression +@begin(pdescription) + @i @itemsep the expression to be evaluated + + returns @itemsep the result of evaluating the expression +@end(pdescription) +@blankspace(1) + + (apply@pragma(defn)@index(apply) @i @i) @itemsep apply a function to a list of arguments +@begin(pdescription) + @i @itemsep the function to apply (or function symbol) + + @i @itemsep the argument list + + returns @itemsep the result of applying the function to the arguments +@end(pdescription) +@blankspace(1) + + (funcall@pragma(defn)@index(funcall) @i @i...) @itemsep call a function with arguments +@begin(pdescription) + @i @itemsep the function to call (or function symbol) + + @i @itemsep arguments to pass to the function + + returns @itemsep the result of calling the function with the arguments +@end(pdescription) +@blankspace(1) + + (quote@pragma(defn)@index(quote) @i) @itemsep return an expression unevaluated +@begin(pdescription) + @i @itemsep the expression to be quoted (quoted) + + returns @itemsep @i unevaluated +@end(pdescription) +@blankspace(1) + + (function@pragma(defn)@index(function) @i) @itemsep get the functional interpretation + +@begin(pdescription) + @i @itemsep the symbol or lambda expression (quoted) + + returns @itemsep the functional interpretation + +@end(pdescription) +@blankspace(1) + + (backquote@pragma(defn)@index(backquote) @i) @itemsep fill in a template + +@begin(pdescription) + @i @itemsep the template + + returns @itemsep a copy of the template with comma and comma-at + + expressions expanded +@end(pdescription) +@blankspace(1) + + (lambda@pragma(defn)@index(lambda) @i @i...) @itemsep make a function closure + +@begin(pdescription) + @i @itemsep formal argument list (lambda list) (quoted) + + @i @itemsep expressions of the function body + + returns @itemsep the function closure + +@end(pdescription) +@blankspace(1) + + (get-lambda-expression@pragma(defn)@index(get-lambda-expression) @i) @itemsep get the lambda expression + +@begin(pdescription) + @i @itemsep the closure + + returns @itemsep the original lambda expression + +@end(pdescription) +@blankspace(1) + + (macroexpand@pragma(defn)@index(macroexpand) @i
    ) @itemsep recursively expand macro calls + +@begin(pdescription) + @i @itemsep the form to expand + + returns @itemsep the macro expansion + +@end(pdescription) +@blankspace(1) + + (macroexpand-1@pragma(defn)@index(macroexpand-1) @i) @itemsep expand a macro call + +@begin(pdescription) + @i @itemsep the macro call form + + returns @itemsep the macro expansion + +@end(pdescription) +@blankspace(1) +@end(fdescription) + + +@section(Symbol Functions)@index(Symbol Functions) +@begin(fdescription) + (set@pragma(defn)@index(set) @i @i) @itemsep set the value of a symbol +@begin(pdescription) + @i @itemsep the symbol being set + + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) + + (setq@pragma(defn)@index(setq) [@i @i]...) @itemsep set the value of a symbol +@begin(pdescription) + @i @itemsep the symbol being set (quoted) + + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) + + (psetq@pragma(defn)@index(psetq) [@i @i]...) @itemsep parallel version of setq +@begin(pdescription) + @i @itemsep the symbol being set (quoted) + + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) + + (setf@pragma(defn)@index(setf) [@i @i]...) @itemsep set the value of a field +@begin(pdescription) + @i @itemsep the field specifier (quoted): + +@begin(pdescription) + @i @itemsep set value of a symbol + + (car @i) @itemsep set car of a cons node + + (cdr @i) @itemsep set cdr of a cons node + + (nth @i @i) @itemsep set nth car of a list + + (aref @i @i) @itemsep set nth element of an array + + (get @i @i) @itemsep set value of a property + + (symbol-value @i) @itemsep set value of a symbol + + (symbol-function @i) @itemsep set functional value of a symbol + + (symbol-plist @i) @itemsep set property list of a symbol + +@end(pdescription)@pragma(stopcodef) + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + (defun@pragma(defn)@index(defun) @i @i @i...) @itemsep define a function + +@pragma(startcodef) + (defmacro@pragma(defn)@index(defmacro) @i @i @i...) @itemsep define a macro +@end(fgroup) +@begin(pdescription) + @i @itemsep symbol being defined (quoted) + + @i @itemsep formal argument list (lambda list) (quoted) + + @i @itemsep expressions constituting the body of the + + function (quoted) + returns @itemsep the function symbol + +@end(pdescription) +@blankspace(1) + + (gensym@pragma(defn)@index(gensym) [@i]) @itemsep generate a symbol +@begin(pdescription) + @i @itemsep string or number + + returns @itemsep the new symbol + +@end(pdescription) +@blankspace(1) + +(intern@pragma(defn)@index(intern) @i) @itemsep make an interned symbol +@begin(pdescription) + @i @itemsep the symbol's print name string + + returns @itemsep the new symbol + +@end(pdescription) +@blankspace(1) + + (make-symbol@pragma(defn)@index(make-symbol) @i) @itemsep make an uninterned symbol +@begin(pdescription) + @i @itemsep the symbol's print name string + + returns @itemsep the new symbol + +@end(pdescription) +@blankspace(1) + + (symbol-name@pragma(defn)@index(symbol-name) @i) @itemsep get the print name of a symbol +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's print name + +@end(pdescription) +@blankspace(1) + + (symbol-value@pragma(defn)@index(symbol-value) @i) @itemsep get the value of a symbol +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's value + +@end(pdescription) +@blankspace(1) + + (symbol-function@pragma(defn)@index(symbol-function) @i) @itemsep get the functional value of a symbol +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's functional value + +@end(pdescription) +@blankspace(1) + + (symbol-plist@pragma(defn)@index(symbol-plist) @i) @itemsep get the property list of a symbol +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's property list + +@end(pdescription) +@blankspace(1) + + (hash@pragma(defn)@index(hash) @i @i) @itemsep compute the hash index for a symbol +@begin(pdescription) + @i @itemsep the symbol or string + + @i @itemsep the table size (integer) + + returns @itemsep the hash index (integer) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Property List Functions)@index(Property List Functions) +@begin(fdescription) + (get@pragma(defn)@index(get) @i @i) @itemsep get the value of a property +@begin(pdescription) + @i @itemsep the symbol + + @i @itemsep the property symbol + + returns @itemsep the property value or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (putprop@pragma(defn)@index(putprop) @i @i @i) @itemsep put a property onto a property list +@begin(pdescription) + @i @itemsep the symbol + + @i @itemsep the property value + + @i @itemsep the property symbol + + returns @itemsep the property value + +@end(pdescription) +@blankspace(1) + + (remprop@pragma(defn)@index(remprop) @i @i) @itemsep remove a property +@begin(pdescription) + @i @itemsep the symbol + + @i @itemsep the property symbol + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Array Functions)@index(Array Functions) +@begin(fdescription) + (aref@pragma(defn)@index(aref) @i @i) @itemsep get the nth element of an array +@begin(pdescription) + @i @itemsep the array + + @i @itemsep the array index (integer) + + returns @itemsep the value of the array element + +@end(pdescription) +@blankspace(1) + + (make-array@pragma(defn)@index(make-array) @i) @itemsep make a new array +@begin(pdescription) + @i @itemsep the size of the new array (integer) + + returns @itemsep the new array + +@end(pdescription) +@blankspace(1) + + (vector@pragma(defn)@index(vector) @i...) @itemsep make an initialized vector +@begin(pdescription) + @i @itemsep the vector elements + + returns @itemsep the new vector + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(List Functions)@index(List Functions) +@begin(fdescription) + (car@pragma(defn)@index(car) @i) @itemsep return the car of a list node +@begin(pdescription) + @i @itemsep the list node + + returns @itemsep the car of the list node + +@end(pdescription) +@blankspace(1) + + (cdr@pragma(defn)@index(cdr) @i) @itemsep return the cdr of a list node +@begin(pdescription) + @i @itemsep the list node + + returns @itemsep the cdr of the list node + +@end(pdescription) +@blankspace(1) + + (c@i(xx)r@index(cxxr) @i) @itemsep all c@i(xx)r combinations +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (c@i(xxx)r@index(cxxxr) @i) @itemsep all c@i(xxx)r combinations +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (c@i(xxxx)r@index(cxxxxr) @i) @itemsep all c@i(xxxx)r combinations +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (first@pragma(defn)@index(first) @i) @itemsep a synonym for car +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (second@pragma(defn)@index(second) @i) @itemsep a synonym for cadr +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (third@pragma(defn)@index(third) @i) @itemsep a synonym for caddr +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (fourth@pragma(defn)@index(fourth) @i) @itemsep a synonym for cadddr +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (rest@pragma(defn)@index(rest) @i) @itemsep a synonym for cdr +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + (cons@pragma(defn)@index(cons) @i @i) @itemsep construct a new list node +@begin(pdescription) + @i @itemsep the car of the new list node + + @i @itemsep the cdr of the new list node + + returns @itemsep the new list node + +@end(pdescription) +@blankspace(1) + + (list@pragma(defn)@index(list) @i...) @itemsep create a list of values +@begin(pdescription) + @i @itemsep expressions to be combined into a list + + returns @itemsep the new list + +@end(pdescription) +@blankspace(1) + + (append@pragma(defn)@index(append) @i...) @itemsep append lists +@begin(pdescription) + @i @itemsep lists whose elements are to be appended + + returns @itemsep the new list + +@end(pdescription) +@blankspace(1) + + (reverse@pragma(defn)@index(reverse) @i) @itemsep reverse a list +@begin(pdescription) + @i @itemsep the list to reverse + + returns @itemsep a new list in the reverse order + +@end(pdescription) +@blankspace(1) + + (last@pragma(defn)@index(last) @i) @itemsep return the last list node of a list +@begin(pdescription) + @i @itemsep the list + + returns @itemsep the last list node in the list + +@end(pdescription) +@blankspace(1) + + (member@pragma(defn)@index(member) @i @i &key :test :test-not) @itemsep find an expression in a list +@begin(pdescription) + @i @itemsep the expression to find + + @i @itemsep the list to search + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the remainder of the list starting with the expression + +@end(pdescription) +@blankspace(1) + + (assoc@pragma(defn)@index(assoc) @i @i &key :test :test-not) @itemsep find an expression in an a-list +@begin(pdescription) + @i @itemsep the expression to find + + @i @itemsep the association list + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the alist entry or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (remove@pragma(defn)@index(remove) @i @i &key :test :test-not) @itemsep remove elements from a list +@begin(pdescription) + @i @itemsep the element to remove + + @i @itemsep the list + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep copy of list with matching expressions removed + +@end(pdescription) +@blankspace(1) + + (remove-if@pragma(defn)@index(remove-if) @i @i) @itemsep remove elements that pass test +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep copy of list with matching elements removed + +@end(pdescription) +@blankspace(1) + + (remove-if-not@pragma(defn)@index(remove-if-not) @i @i) @itemsep remove elements that fail test +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep copy of list with non-matching elements removed + +@end(pdescription) +@blankspace(1) + + (length@pragma(defn)@index(length) @i) @itemsep find the length of a list, vector or string +@begin(pdescription) + @i @itemsep the list, vector or string + + returns @itemsep the length of the list, vector or string + +@end(pdescription) +@blankspace(1) + + (nth@pragma(defn)@index(nth) @i @i) @itemsep return the nth element of a list +@begin(pdescription) + @i @itemsep the number of the element to return (zero origin) + + @i @itemsep the list + + returns @itemsep the nth element or @xlcode(nil) if the list isn't that long + +@end(pdescription) +@blankspace(1) + + (nthcdr@pragma(defn)@index(nthcdr) @i @i) @itemsep return the nth cdr of a list +@begin(pdescription) + @i @itemsep the number of the element to return (zero origin) + + @i @itemsep the list + + returns @itemsep the nth cdr or @xlcode(nil) if the list isn't that long + +@end(pdescription) +@blankspace(1) + + (mapc@pragma(defn)@index(mapc) @i @i @i...) @itemsep apply function to successive cars +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep the first list of arguments + +@end(pdescription) +@blankspace(1) + + (mapcar@pragma(defn)@index(mapcar) @i @i @i...) @itemsep apply function to successive cars +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep a list of the values returned + +@end(pdescription) +@blankspace(1) + + (mapl@pragma(defn)@index(mapl) @i @i @i...) @itemsep apply function to successive cdrs +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep the first list of arguments + +@end(pdescription) +@blankspace(1) + + (maplist@pragma(defn)@index(maplist) @i @i @i...) @itemsep apply function to successive cdrs +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep a list of the values returned + +@end(pdescription) +@blankspace(1) + + (subst@pragma(defn)@index(subst) @i @i @i &key :test :test-not) @itemsep substitute expressions +@begin(pdescription) + @i @itemsep the new expression + + @i @itemsep the old expression + + @i @itemsep the expression in which to do the substitutions + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the expression with substitutions + +@end(pdescription) +@blankspace(1) + + (sublis@pragma(defn)@index(sublis) @i @i &key :test :test-not) @itemsep substitute with an a-list +@begin(pdescription) + @i @itemsep the association list + + @i @itemsep the expression in which to do the substitutions + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the expression with substitutions + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Destructive List Functions)@index(Destructive List Functions) +@begin(fdescription) + (rplaca@pragma(defn)@index(rplaca) @i @i) @itemsep replace the car of a list node +@begin(pdescription) + @i @itemsep the list node + + @i @itemsep the new value for the car of the list node + + returns @itemsep the list node after updating the car + +@end(pdescription) +@blankspace(1) + + (rplacd@pragma(defn)@index(rplacd) @i @i) @itemsep replace the cdr of a list node +@begin(pdescription) + @i @itemsep the list node + + @i @itemsep the new value for the cdr of the list node + + returns @itemsep the list node after updating the cdr + +@end(pdescription) +@blankspace(1) + + (nconc@pragma(defn)@index(nconc) @i...) @itemsep destructively concatenate lists +@begin(pdescription) + @i @itemsep lists to concatenate + + returns @itemsep the result of concatenating the lists + +@end(pdescription) +@blankspace(1) + + (delete@pragma(defn)@index(delete) @i &key :test :test-not) @itemsep delete elements from a list +@begin(pdescription) + @i @itemsep the element to delete + + @i @itemsep the list + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the list with the matching expressions deleted + +@end(pdescription) +@blankspace(1) + + (delete-if@pragma(defn)@index(delete-if) @i @i) @itemsep delete elements that pass test +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep the list with matching elements deleted + +@end(pdescription) +@blankspace(1) + + (delete-if-not@pragma(defn)@index(delete-if-not) @i @i) @itemsep delete elements that fail test +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep the list with non-matching elements deleted + +@end(pdescription) +@blankspace(1) + + (sort@pragma(defn)@index(sort) @i @i) @itemsep sort a list +@begin(pdescription) + @i @itemsep the list to sort + + @i @itemsep the comparison function + + returns @itemsep the sorted list + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Predicate Functions)@index(Predicate Functions) +@begin(fdescription) + (atom@pragma(defn)@index(atom) @i) @itemsep is this an atom? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an atom, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (symbolp@pragma(defn)@index(symbolp) @i) @itemsep is this a symbol? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the expression is a symbol, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (numberp@pragma(defn)@index(numberp) @i) @itemsep is this a number? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the expression is a number, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (null@pragma(defn)@index(null) @i) @itemsep is this an empty list? +@begin(pdescription) + @i @itemsep the list to check + + returns @itemsep @xlcode(t) if the list is empty, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (not@pragma(defn)@index(not) @i) @itemsep is this false? +@begin(pdescription) + @i @itemsep the expression to check + + return @itemsep @xlcode(t) if the value is @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (listp@pragma(defn)@index(listp) @i) @itemsep is this a list? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a cons or @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (endp@pragma(defn)@index(endp) @i) @itemsep is this the end of a list +@begin(pdescription) + @i @itemsep the list + + returns @itemsep @xlcode(t) if the value is @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (consp@pragma(defn)@index(consp) @i) @itemsep is this a non-empty list? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a cons, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (integerp@pragma(defn)@index(integerp) @i) @itemsep is this an integer? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an integer, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (floatp@pragma(defn)@index(floatp) @i) @itemsep is this a float? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a float, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (stringp@pragma(defn)@index(stringp) @i) @itemsep is this a string? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a string, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (characterp@pragma(defn)@index(characterp) @i) @itemsep is this a character? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a character, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (arrayp@pragma(defn)@index(arrayp) @i) @itemsep is this an array? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an array, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (streamp@pragma(defn)@index(streamp) @i) @itemsep is this a stream? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a stream, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (objectp@pragma(defn)@index(objectp) @i) @itemsep is this an object? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an object, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (filep@pragma(defn)@index(filep) @i)@foot(This is not part of standard XLISP nor is it built-in. Nyquist defines it though.) @itemsep is this a file? +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an object, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (boundp@pragma(defn)@index(boundp) @i) @itemsep is a value bound to this symbol? +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep @xlcode(t) if a value is bound to the symbol, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (fboundp@pragma(defn)@index(fboundp) @i) @itemsep is a functional value bound to this symbol? +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep @xlcode(t) if a functional value is bound to the symbol, + + @xlcode(nil) otherwise +@end(pdescription) +@blankspace(1) + + (minusp@pragma(defn)@index(minusp) @i) @itemsep is this number negative? +@begin(pdescription) + @i @itemsep the number to test + + returns @itemsep @xlcode(t) if the number is negative, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (zerop@pragma(defn)@index(zerop) @i) @itemsep is this number zero? +@begin(pdescription) + @i @itemsep the number to test + + returns @itemsep @xlcode(t) if the number is zero, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (plusp@pragma(defn)@index(plusp) @i) @itemsep is this number positive? +@begin(pdescription) + @i @itemsep the number to test + + returns @itemsep @xlcode(t) if the number is positive, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (evenp@pragma(defn)@index(evenp) @i) @itemsep is this integer even? +@begin(pdescription) + @i @itemsep the integer to test + + returns @itemsep @xlcode(t) if the integer is even, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (oddp@pragma(defn)@index(oddp) @i) @itemsep is this integer odd? +@begin(pdescription) + @i @itemsep the integer to test + + returns @itemsep @xlcode(t) if the integer is odd, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (eq@pragma(defn)@index(eq) @i @i) @itemsep are the expressions identical? +@begin(pdescription) + @i @itemsep the first expression + + @i @itemsep the second expression + + returns @itemsep @xlcode(t) if they are equal, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + +(eql@pragma(defn)@index(eql) @i @i) @itemsep are the expressions identical? (works with all numbers) +@begin(pdescription) + @i @itemsep the first expression + + @i @itemsep the second expression + + returns @itemsep @xlcode(t) if they are equal, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (equal@pragma(defn)@index(equal) @i @i) @itemsep are the expressions equal? +@begin(pdescription) + @i @itemsep the first expression + + @i @itemsep the second expression + + returns @itemsep @xlcode(t) if they are equal, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Control Constructs)@index(Control Constructs) +@begin(fdescription) + (cond@pragma(defn)@index(cond) @i...) @itemsep evaluate conditionally +@begin(pdescription) + @i @itemsep pair consisting of: + +@begin(pdescription) + (@i @i...) +@end(pdescription)@pragma(stopcodef) + where: +@begin(pdescription) + @i @itemsep is a predicate expression + + @i @itemsep evaluated if the predicate + is not @xlcode(nil) +@end(pdescription)@pragma(stopcodef) +returns @itemsep the value of the first expression whose predicate is not +@xlcode(nil) +@end(pdescription) +@blankspace(1) + + (and@pragma(defn)@index(and) @i...) @itemsep the logical and of a list of expressions +@begin(pdescription) + @i @itemsep the expressions to be anded + + returns @itemsep @xlcode(nil) if any expression evaluates to @xlcode(nil), + otherwise the value of the last expression + (evaluation of expressions stops after the first + expression that evaluates to @xlcode(nil)) +@end(pdescription) +@blankspace(1) + + (or@pragma(defn)@index(or) @i...) @itemsep the logical or of a list of expressions +@begin(pdescription) + @i @itemsep the expressions to be ored + + returns @itemsep @xlcode(nil) if all expressions evaluate to @xlcode(nil), + otherwise the value of the first non-@xlcode(nil) expression + (evaluation of expressions stops after the first + expression that does not evaluate to @xlcode(nil)) +@end(pdescription) +@blankspace(1) + + (if@pragma(defn)@index(if) @i @i [@i]) @itemsep evaluate expressions conditionally +@begin(pdescription) + @i @itemsep the test expression + + @i @itemsep the expression to be evaluated if texpr is non-@xlcode(nil) + + @i @itemsep the expression to be evaluated if texpr is @xlcode(nil) + + returns @itemsep the value of the selected expression + +@end(pdescription) +@blankspace(1) + + (when@pragma(defn)@index(when) @i @i...) @itemsep evaluate only when a condition is true +@begin(pdescription) + @i @itemsep the test expression + + @i @itemsep the expression(s) to be evaluated if texpr is non-@xlcode(nil) + + returns @itemsep the value of the last expression or @xlcode(nil) +@end(pdescription) +@blankspace(1) + + (unless@pragma(defn)@index(unless) @i @i...) @itemsep evaluate only when a condition is false +@begin(pdescription) + @i @itemsep the test expression + + @i @itemsep the expression(s) to be evaluated if texpr is @xlcode(nil) + + returns @itemsep the value of the last expression or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (case@pragma(defn)@index(case) @i @i...) @itemsep select by case +@begin(pdescription) + @i @itemsep the selection expression + + @i @itemsep pair consisting of: + +@begin(pdescription) + (@i @i...) +@end(pdescription)@pragma(stopcodef) + where: +@begin(pdescription) + @i @itemsep is a single expression or a list of + expressions (unevaluated) + + @i @itemsep are expressions to execute if the + case matches +@end(pdescription)@pragma(stopcodef) + returns @itemsep the value of the last expression of the matching case + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + (let@pragma(defn)@index(let) (@i...) @i...) @itemsep create local bindings + +@pragma(startcodef) + (let*@pragma(defn)@index(let*) (@i...) @i...) @itemsep let with sequential binding +@end(fgroup) +@begin(pdescription) + @i @itemsep the variable bindings each of which is either: + +@begin(pdescription) + 1) a symbol (which is initialized to @xlcode(nil)) + + 2) a list whose car is a symbol and whose cadr + is an initialization expression +@end(pdescription)@pragma(stopcodef) + @i @itemsep the expressions to be evaluated + + returns @itemsep the value of the last expression + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + (flet@pragma(defn)@index(flet) (@i...) @i...) @itemsep create local functions + +@pragma(startcodef) + (labels@pragma(defn)@index(labels) (@i...) @i...) @itemsep flet with recursive functions + +@pragma(startcodef) + (macrolet@pragma(defn)@index(macrolet) (@i...) @i...) @itemsep create local macros +@end(fgroup) +@begin(pdescription) + @i @itemsep the function bindings each of which is: + +@begin(pdescription) + (@i @i @i...) +@end(pdescription)@pragma(stopcodef) + where: +@begin(pdescription) + @i @itemsep the function/macro name + + @i @itemsep formal argument list (lambda list) + + @i @itemsep expressions constituting the body of + the function/macro +@end(pdescription)@pragma(stopcodef) + @i @itemsep the expressions to be evaluated + + returns @itemsep the value of the last expression +@end(pdescription) +@blankspace(1) + + (catch@pragma(defn)@index(catch) @i @i...) @itemsep evaluate expressions and catch throws +@begin(pdescription) + @i @itemsep the catch tag + + @i @itemsep expressions to evaluate + + returns @itemsep the value of the last expression the throw expression + +@end(pdescription) +@blankspace(1) + + (throw@pragma(defn)@index(throw) @i [@i]) @itemsep throw to a catch +@begin(pdescription) + @i @itemsep the catch tag + + @i @itemsep the value for the catch to return (defaults to @xlcode(nil)) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (unwind-protect@pragma(defn)@index(unwind-protect) @i @i...) @itemsep protect evaluation of an expression +@begin(pdescription) + @i @itemsep the expression to protect + + @i @itemsep the cleanup expressions + + returns @itemsep the value of the expression@* + + Note: unwind-protect guarantees to execute the cleanup expressions + even if a non-local exit terminates the evaluation of the + protected expression +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Looping Constructs)@index(Looping Constructs) +@begin(fdescription) + (loop@pragma(defn)@index(loop) @i...) @itemsep basic looping form +@begin(pdescription) + @i @itemsep the body of the loop + + returns @itemsep never returns (must use non-local exit) + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + (do@pragma(defn)@index(do) (@i...) (@i @i...) @i...) +@pragma(endcodef) + (do*@pragma(defn)@index(do*) (@i...) (@i @i...) @i...) +@end(fgroup) +@begin(pdescription) + @i @itemsep the variable bindings each of which is either: + +@begin(pdescription) + 1) a symbol (which is initialized to @xlcode(nil)) + + 2) a list of the form: (@i @i [@i]) + where: +@begin(pdescription) + @i @itemsep is the symbol to bind + + @i @itemsep is the initial value of the symbol + + @i @itemsep is a step expression + +@end(pdescription) +@end(pdescription)@pragma(stopcodef) + @i @itemsep the termination test expression + + @i @itemsep result expressions (the default is @xlcode(nil)) + + @i @itemsep the body of the loop (treated like an implicit prog) + + returns @itemsep the value of the last result expression + +@end(pdescription) +@blankspace(1) + + (dolist@pragma(defn)@index(dolist) (@i @i [@i]) @i...) @itemsep loop through a list +@begin(pdescription) + @i @itemsep the symbol to bind to each list element + + @i @itemsep the list expression + + @i @itemsep the result expression (the default is @xlcode(nil)) + + @i @itemsep the body of the loop (treated like an implicit prog) + +@end(pdescription) +@blankspace(1) + + (dotimes@pragma(defn)@index(dotimes) (@i @i [@i]) @i...) @itemsep loop from zero to n-1 +@begin(pdescription) + @i @itemsep the symbol to bind to each value from 0 to n-1 + + @i @itemsep the number of times to loop + + @i @itemsep the result expression (the default is @xlcode(nil)) + + @i @itemsep the body of the loop (treated like an implicit prog) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(The Program Feature)@index(The Program Feature) +@begin(fdescription) +@begin(fgroup) +(prog@pragma(defn)@index(prog) (@i...) @i...) @itemsep the program feature + +@pragma(startcodef) +(prog*@pragma(defn)@index(prog*) (@i...) @i...) @itemsep prog with sequential binding +@end(fgroup) +@begin(pdescription) + @i @itemsep the variable bindings each of which is either: + +@begin(pdescription) + 1) a symbol (which is initialized to @xlcode(nil)) + + 2) a list whose car is a symbol and whose cadr + is an initialization expression +@end(pdescription)@pragma(stopcodef) + @i @itemsep expressions to evaluate or tags (symbols) + + returns @itemsep @xlcode(nil) or the argument passed to the return function + +@end(pdescription) +@blankspace(1) + + (block@pragma(defn)@index(block) @i @i...) @itemsep named block +@begin(pdescription) + @i @itemsep the block name (symbol) + + @i @itemsep the block body + + returns @itemsep the value of the last expression + +@end(pdescription) +@blankspace(1) + + (return@pragma(defn)@index(return) [@i]) @itemsep cause a prog construct to return a value +@begin(pdescription) + @i @itemsep the value (defaults to @xlcode(nil)) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (return-from@pragma(defn)@index(return-from) @i [@i]) @itemsep return from a named block +@begin(pdescription) + @i @itemsep the block name (symbol) + + @i @itemsep the value to return (defaults to @xlcode(nil)) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (tagbody@pragma(defn)@index(tagbody) @i...) @itemsep block with labels +@begin(pdescription) + @i @itemsep expression(s) to evaluate or tags (symbols) + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (go@pragma(defn)@index(go) @i) @itemsep go to a tag within a tagbody or prog +@begin(pdescription) + @i @itemsep the tag (quoted) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (progv@pragma(defn)@index(progv) @i @i @i...) @itemsep dynamically bind symbols +@begin(pdescription) + @i @itemsep list of symbols + + @i @itemsep list of values to bind to the symbols + + @i @itemsep expression(s) to evaluate + + returns @itemsep the value of the last expression + +@end(pdescription) +@blankspace(1) + + (prog1@pragma(defn)@index(prog1) @i @i...) @itemsep execute expressions sequentially +@begin(pdescription) + @i @itemsep the first expression to evaluate + + @i @itemsep the remaining expressions to evaluate + + returns @itemsep the value of the first expression + +@end(pdescription) +@blankspace(1) + + (prog2@pragma(defn)@index(prog2) @i @i @i...) @itemsep execute expressions sequentially +@begin(pdescription) + @i @itemsep the first expression to evaluate + + @i @itemsep the second expression to evaluate + + @i @itemsep the remaining expressions to evaluate + + returns @itemsep the value of the second expression + +@end(pdescription) +@blankspace(1) + + (progn@pragma(defn)@index(progn) @i...) @itemsep execute expressions sequentially +@begin(pdescription) + @i @itemsep the expressions to evaluate + + returns @itemsep the value of the last expression (or @xlcode(nil)) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Debugging and Error Handling)@index(Debugging)@index(Error Handling) +@begin(fdescription) + (trace@pragma(defn)@index(trace) @i) @itemsep add a function to the trace list +@begin(pdescription) + @i @itemsep the function to add (quoted) + + returns @itemsep the trace list + +@end(pdescription) +@blankspace(1) + + (untrace@pragma(defn)@index(untrace) @i) @itemsep remove a function from the trace list +@begin(pdescription) + @i @itemsep the function to remove (quoted) + + returns @itemsep the trace list + +@end(pdescription) +@blankspace(1) + + (error@pragma(defn)@index(error) @i [@i]) @itemsep signal a non-correctable error +@begin(pdescription) + @i @itemsep the error message string + + @i @itemsep the argument expression (printed after the message) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (cerror@pragma(defn)@index(cerror) @i @i [@i]) @itemsep signal a correctable error +@begin(pdescription) + @i @itemsep the continue message string + + @i @itemsep the error message string + + @i @itemsep the argument expression (printed after the message) + + returns @itemsep @xlcode(nil) when continued from the break loop + +@end(pdescription) +@blankspace(1) + + (break@pragma(defn)@index(break) [@i [@i]]) @itemsep enter a break loop +@begin(pdescription) + @i @itemsep the break message string (defaults to @xlcode(**break**)) + + @i @itemsep the argument expression (printed after the message) + + returns @itemsep @xlcode(nil) when continued from the break loop + +@end(pdescription) +@blankspace(1) + + (clean-up@pragma(defn)@index(clean-up)) @itemsep clean-up after an error +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (top-level@pragma(defn)@index(top-level)) @itemsep clean-up after an error and return to the top level +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (continue@pragma(defn)@index(continue)) @itemsep continue from a correctable error +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (errset@pragma(defn)@index(errset) @i [@i]) @itemsep trap errors +@begin(pdescription) + @i @itemsep the expression to execute + + @i @itemsep flag to control printing of the error message + + returns @itemsep the value of the last expression consed with @xlcode(nil) + + or @xlcode(nil) on error +@end(pdescription) +@blankspace(1) + + (baktrace@pragma(defn)@index(baktrace)@index(debugging)@index(stack trace) [@i]) @itemsep print n levels of trace back information +@begin(pdescription) + @i @itemsep the number of levels (defaults to all levels) + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (evalhook@pragma(defn)@index(evalhook) @i @i @i [@i]) @itemsep evaluate with hooks +@begin(pdescription) + @i @itemsep the expression to evaluate + + @i @itemsep the value for @xlcode(*evalhook*) + + @i @itemsep the value for @xlcode(*applyhook*) + + @i @itemsep the environment (default is @xlcode(nil)) + + returns @itemsep the result of evaluating the expression + +@end(pdescription) +@blankspace(1) + + (profile@pragma(defn)@index(profile) @i(flag))@foot(This is not a standard XLISP 2.0 function.) @itemsep turn profiling on or off. +@begin(pdescription) + @i @itemsep @xlcode(nil) turns profiling off, otherwise on + + returns @itemsep the previous state of profiling. + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Arithmetic Functions)@index(Arithmetic Functions) +@begin(fdescription) + (truncate@pragma(defn)@index(truncate) @i) @itemsep truncates a floating point number to an integer +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the result of truncating the number + +@end(pdescription) +@blankspace(1) + + (float@pragma(defn)@index(float) @i) @itemsep converts an integer to a floating point number +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the result of floating the integer + +@end(pdescription) +@blankspace(1) + + (+@pragma(defn)@index(+) @i...) @itemsep add a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the addition + +@end(pdescription) +@blankspace(1) + + (-@pragma(defn)@index(-) @i...) @itemsep subtract a list of numbers or negate a single number +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the subtraction + +@end(pdescription) +@blankspace(1) + + (*@pragma(defn)@index(*) @i...) @itemsep multiply a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the multiplication + +@end(pdescription) +@blankspace(1) + + (/@pragma(defn)@index(/) @i...) @itemsep divide a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the division + +@end(pdescription) +@blankspace(1) + + (1+@pragma(defn)@index(1+) @i) @itemsep add one to a number +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the number plus one + +@end(pdescription) +@blankspace(1) + + (1-@pragma(defn)@index(1-) @i) @itemsep subtract one from a number +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the number minus one + +@end(pdescription) +@blankspace(1) + + (rem@pragma(defn)@index(rem)@index(remainder)@index(modulo (rem) function) @i...) @itemsep remainder of a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the remainder operation + +@end(pdescription) +@blankspace(1) + + (min@pragma(defn)@index(min)@index(minimum) @i...) @itemsep the smallest of a list of numbers +@begin(pdescription) + @i @itemsep the expressions to be checked + + returns @itemsep the smallest number in the list + +@end(pdescription) +@blankspace(1) + + (max@pragma(defn)@index(max)@index(maximum) @i...) @itemsep the largest of a list of numbers +@begin(pdescription) + @i @itemsep the expressions to be checked + + returns @itemsep the largest number in the list + +@end(pdescription) +@blankspace(1) + + (abs@pragma(defn)@index(abs) @i) @itemsep the absolute value of a number +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the absolute value of the number + +@end(pdescription) +@blankspace(1) + + (gcd@pragma(defn)@index(gcd) @i @i...) @itemsep compute the greatest common divisor +@begin(pdescription) + @i @itemsep the first number (integer) + + @i @itemsep the second number(s) (integer) + + returns @itemsep the greatest common divisor + +@end(pdescription) +@blankspace(1) + + (random@pragma(defn)@index(random) @i) @itemsep compute a random number between 0 and n-1 inclusive +@begin(pdescription) + @i @itemsep the upper bound (integer) + + returns @itemsep a random number + +@end(pdescription) +@blankspace(1) + + (rrandom@pragma(defn)@index(rrandom)@index(uniform random)) @itemsep compute a random real number between 0 and 1 inclusive +@begin(pdescription) + returns @itemsep a random floating point number + +@end(pdescription) +@blankspace(1) + + (sin@pragma(defn)@index(sin) @i) @itemsep compute the sine of a number +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the sine of the number + +@end(pdescription) +@blankspace(1) + + (cos@pragma(defn)@index(cos) @i) @itemsep compute the cosine of a number +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the cosine of the number + +@end(pdescription) +@blankspace(1) + + (tan@pragma(defn)@index(tan) @i) @itemsep compute the tangent of a number +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the tangent of the number + +@end(pdescription) +@blankspace(1) + + (atan@pragma(defn)@index(atan) @i [@i])@foot(This is not a standard XLISP 2.0 function.) @itemsep compute the arctangent +@begin(pdescription) + @i @itemsep the value of @i(x) + + @i @itemsep the value of @i(y) (default value is 1.0) + + returns @itemsep the arctangent of @i(x)/@i(y) + +@end(pdescription) +@blankspace(1) + + (expt@pragma(defn)@index(expt) @i @i) @itemsep compute x to the y power +@begin(pdescription) + @i @itemsep the floating point number + + @i @itemsep the floating point exponent + + returns @itemsep x to the y power + +@end(pdescription) +@blankspace(1) + + (exp@pragma(defn)@index(exp) @i) @itemsep compute e to the x power +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep e to the x power + +@end(pdescription) +@blankspace(1) + + (sqrt@pragma(defn)@index(sqrt) @i) @itemsep compute the square root of a number +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the square root of the number + +@end(pdescription) +@blankspace(1) +@begin(fgroup) +(<@pragma(defn)@index(<) @i @i...) @itemsep test for less than + +(<=@pragma(defn)@index(<=) @i @i...) @itemsep test for less than or equal to + +(=@pragma(defn)@index(=) @i @i...) @itemsep test for equal to + +(/=@pragma(defn)@index(/=) @i @i...) @itemsep test for not equal to + +(>=@pragma(defn)@index(>=) @i @i...) @itemsep test for greater than or equal to + +(>@pragma(defn)@index(>) @i @i...) @itemsep test for greater than +@end(fgroup) +@begin(pdescription) + @i @itemsep the first number to compare + + @i @itemsep the second number to compare + +returns @itemsep @xlcode(t) if the results of comparing @i with @i, +@i with @i, etc., are all true. + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Bitwise Logical Functions)@index(Bitwise Logical Functions) +@begin(fdescription) + (logand@pragma(defn)@index(logand) @i...) @itemsep the bitwise and of a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the and operation + +@end(pdescription) +@blankspace(1) + + (logior@pragma(defn)@index(logior) @i...) @itemsep the bitwise inclusive or of a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the inclusive or operation + +@end(pdescription) +@blankspace(1) + + (logxor@pragma(defn)@index(logxor) @i...) @itemsep the bitwise exclusive or of a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the exclusive or operation + +@end(pdescription) +@blankspace(1) + + (lognot@pragma(defn)@index(lognot) @i) @itemsep the bitwise not of a number +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the bitwise inversion of number + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(String Functions)@index(String Functions) +@begin(fdescription) + (string@pragma(defn)@index(string) @i) @itemsep make a string from a value +@begin(pdescription) + @i @itemsep an integer (which is first converted into its ASCII character value), string, character, or symbol + + returns @itemsep the string representation of the argument + +@end(pdescription) +@blankspace(1) + + (string-search@pragma(defn)@index(string-search)@index(find string) @i @i &key :start :end)@foot(This is not a standard XLISP 2.0 function.) @itemsep search for pattern in string +@begin(pdescription) + @i @itemsep a string to search for + + @i @itemsep the string to be searched + + :start @itemsep the starting offset in str + + :end @itemsep the ending offset + 1 + + returns @itemsep index of pat in str or NIL if not found + +@end(pdescription) +@blankspace(1) + + (string-trim@pragma(defn)@index(string-trim) @i @i) @itemsep trim both ends of a string +@begin(pdescription) + @i @itemsep a string containing characters to trim + + @i @itemsep the string to trim + + returns @itemsep a trimed copy of the string + +@end(pdescription) +@blankspace(1) + + (string-left-trim@pragma(defn)@index(string-left-trim) @i @i) @itemsep trim the left end of a string +@begin(pdescription) + @i @itemsep a string containing characters to trim + + @i @itemsep the string to trim + + returns @itemsep a trimed copy of the string + +@end(pdescription) +@blankspace(1) + + (string-right-trim@pragma(defn)@index(string-right-trim) @i @i) @itemsep trim the right end of a string +@begin(pdescription) + @i @itemsep a string containing characters to trim + + @i @itemsep the string to trim + + returns @itemsep a trimed copy of the string + +@end(pdescription) +@blankspace(1) + + (string-upcase@pragma(defn)@index(string-upcase) @i &key :start :end) @itemsep convert to uppercase +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep a converted copy of the string + +@end(pdescription) +@blankspace(1) + + (string-downcase@pragma(defn)@index(string-downcase) @i &key :start :end) @itemsep convert to lowercase +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep a converted copy of the string + +@end(pdescription) +@blankspace(1) + + (nstring-upcase@pragma(defn)@index(nstring-upcase) @i &key :start :end) @itemsep convert to uppercase +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep the converted string (not a copy) + +@end(pdescription) +@blankspace(1) + + (nstring-downcase@pragma(defn)@index(nstring-downcase) @i &key :start :end) @itemsep convert to lowercase +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep the converted string (not a copy) + +@end(pdescription) +@blankspace(1) + + (strcat@pragma(defn)@index(strcat)@index(concatenate strings) @i...) @itemsep concatenate strings +@begin(pdescription) + @i @itemsep the strings to concatenate + + returns @itemsep the result of concatenating the strings + +@end(pdescription) +@blankspace(1) + + (subseq@pragma(defn)@index(subseq) @i @i [@i]) @itemsep extract a substring +@begin(pdescription) + @i @itemsep the string + + @i @itemsep the starting position (zero origin) + + @i @itemsep the ending position + 1 (defaults to end) + + returns @itemsep substring between @i and @i + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + (string<@pragma(defn)@index(string<) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + (string<=@pragma(defn)@index(string<=) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + + (string=@pragma(defn)@index(string=) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + + (string/=@pragma(defn)@index(string/=) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + + (string>=@pragma(defn)@index(string>=) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + + (string>@pragma(defn)@index(string>) @i @i &key :start1 :end1 :start2 :end2) +@end(fgroup) +@begin(pdescription) + @i @itemsep the first string to compare + + @i @itemsep the second string to compare + + :start1 @itemsep first substring starting offset + + :end1 @itemsep first substring ending offset + 1 + + :start2 @itemsep second substring starting offset + + :end2 @itemsep second substring ending offset + 1 + + returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@begin(fgroup) +(string-lessp@pragma(defn)@index(string-lessp) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + +(string-not-greaterp@pragma(defn)@index(string-not-greaterp) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + +(string-equalp@pragma(defn)@index(string-equalp) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + +(string-not-equalp@pragma(defn)@index(string-not-equalp) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + +(string-not-lessp@pragma(defn)@index(string-not-lessp) @i @i &key :start1 :end1 :start2 :end2) +@pragma(endcodef) + +(string-greaterp@pragma(defn)@index(string-greaterp) @i @i &key :start1 :end1 :start2 :end2) +@end(fgroup) +@begin(pdescription) + @i @itemsep the first string to compare + + @i @itemsep the second string to compare + + :start1 @itemsep first substring starting offset + + :end1 @itemsep first substring ending offset + 1 + + :start2 @itemsep second substring starting offset + + :end2 @itemsep second substring ending offset + 1 + + returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is not significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Character Functions)@index(Character Functions) +@begin(fdescription) + (char@pragma(defn)@index(char) @i @i) @itemsep extract a character from a string +@begin(pdescription) + @i @itemsep the string + + @i @itemsep the string index (zero relative) + + returns @itemsep the ascii code of the character + +@end(pdescription) +@blankspace(1) + + (upper-case-p@pragma(defn)@index(upper-case-p) @i) @itemsep is this an upper case character? +@begin(pdescription) + @i @itemsep the character + + returns @itemsep @xlcode(t) if the character is upper case, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (lower-case-p@pragma(defn)@index(lower-case-p) @i) @itemsep is this a lower case character? +@begin(pdescription) + @i @itemsep the character + + returns @itemsep @xlcode(t) if the character is lower case, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (both-case-p@pragma(defn)@index(both-case-p) @i) @itemsep is this an alphabetic (either case) character? +@begin(pdescription) + @i @itemsep the character + + returns @itemsep @xlcode(t) if the character is alphabetic, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (digit-char-p@pragma(defn)@index(digit-char-p) @i) @itemsep is this a digit character? +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the digit weight if character is a digit, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (char-code@pragma(defn)@index(char-code) @i) @itemsep get the ascii code of a character +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the ascii character code (integer) + +@end(pdescription) +@blankspace(1) + + (code-char@pragma(defn)@index(code-char) @i) @itemsep get the character with a specified ascii code +@begin(pdescription) + @i @itemsep the ascii code (integer) + + returns @itemsep the character with that code or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (char-upcase@pragma(defn)@index(char-upcase) @i) @itemsep convert a character to upper case +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the upper case character + +@end(pdescription) +@blankspace(1) + + (char-downcase@pragma(defn)@index(char-downcase) @i) @itemsep convert a character to lower case +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the lower case character + +@end(pdescription) +@blankspace(1) + + (digit-char@pragma(defn)@index(digit-char) @i) @itemsep convert a digit weight to a digit +@begin(pdescription) + @i @itemsep the digit weight (integer) + + returns @itemsep the digit character or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (char-int@pragma(defn)@index(char-int) @i) @itemsep convert a character to an integer +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the ascii character code + +@end(pdescription) +@blankspace(1) + + (int-char@pragma(defn)@index(int-char) @i) @itemsep convert an integer to a character +@begin(pdescription) + @i @itemsep the ascii character code + + returns @itemsep the character with that code + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + (char<@pragma(defn)@index(char<) @i @i...) +@pragma(endcodef) + + (char<=@pragma(defn)@index(char<=) @i @i...) +@pragma(endcodef) + + (char=@pragma(defn)@index(char=) @i @i...) +@pragma(endcodef) + + (char/=@pragma(defn)@index(char/=) @i @i...) +@pragma(endcodef) + + (char>=@pragma(defn)@index(char>=) @i @i...) +@pragma(endcodef) + + (char>@pragma(defn)@index(char>) @i @i...) +@end(fgroup) +@begin(pdescription) + @i @itemsep the first character to compare + + @i @itemsep the second character(s) to compare + + returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@begin(fgroup) +(char-lessp@pragma(defn)@index(char-lessp) @i @i...) +@pragma(endcodef) + +(char-not-greaterp@pragma(defn)@index(char-not-greaterp) @i @i...) +@pragma(endcodef) + +(char-equalp@pragma(defn)@index(char-equalp) @i @i...) +@pragma(endcodef) + +(char-not-equalp@pragma(defn)@index(char-not-equalp) @i @i...) +@pragma(endcodef) + +(char-not-lessp@pragma(defn)@index(char-not-lessp) @i @i...) +@pragma(endcodef) + +(char-greaterp@pragma(defn)@index(char-greaterp) @i @i...) +@end(fgroup) +@begin(pdescription) +@i @itemsep the first string to compare + +@i @itemsep the second string(s) to compare + +returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is not significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Input/Output Functions)@index(Input/Output Functions) +@begin(fdescription) + (read@pragma(defn)@index(read) [@i [@i [@i]]]) @itemsep read an expression +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + @i @itemsep the value to return on end of file (default is @xlcode(nil)) + + @i @itemsep recursive read flag (default is @xlcode(nil)) + + returns @itemsep the expression read + +@end(pdescription) +@blankspace(1) + + (print@pragma(defn)@index(print) @i [@i]) @itemsep print an expression on a new line +@begin(pdescription) + @i @itemsep the expression to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + (prin1@pragma(defn)@index(prin1) @i [@i]) @itemsep print an expression +@begin(pdescription) + @i @itemsep the expression to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + (princ@pragma(defn)@index(princ) @i [@i]) @itemsep print an expression without quoting +@begin(pdescription) + @i @itemsep the expressions to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + (pprint@pragma(defn)@index(pprint) @i [@i]) @itemsep pretty print an expression +@begin(pdescription) + @i @itemsep the expressions to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + (terpri@pragma(defn)@index(terpri) [@i]) @itemsep terminate the current print line +@begin(pdescription) + @i @itemsep the output stream (default is standard output) + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (flatsize@pragma(defn)@index(flatsize) @i) @itemsep length of printed representation using prin1 +@begin(pdescription) + @i @itemsep the expression + + returns @itemsep the length + +@end(pdescription) +@blankspace(1) + + (flatc@pragma(defn)@index(flatc) @i) @itemsep length of printed representation using princ +@begin(pdescription) + @i @itemsep the expression + + returns @itemsep the length +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(The Format Function)@index(The Format Function) +@begin(fdescription) +(format@pragma(defn)@index(format) @i @i @i...) @itemsep do formated +output +@begin(pdescription) + @i @itemsep the output stream + + @i @itemsep the format string + + @i @itemsep the format arguments + + returns @itemsep output string if @i is @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) +@end(fdescription) + The format string can contain characters that should be copied + directly to the output and formatting directives. The + formatting directives are: +@begin(display) +@xlcode(~A) @itemsep print next argument using princ +@xlcode(~S) @itemsep print next argument using prin1 +@xlcode(~%) @itemsep start a new line +@xlcode(~~) @itemsep print a tilde character +@xlcode(~) @itemsep ignore this one newline and white space on the +next line up to the first non-white-space character or newline. This +allows strings to continue across multiple lines +@end(display) + +@section(File I/O Functions)@index(File I/O Functions) +Note that files are ordinarily opened as text. Binary files (such as standard midi files) must be opened with @xlcode(open-binary) on non-unix systems. +@begin(fdescription) + (open@pragma(defn)@index(open) @i &key :direction) @itemsep open a file stream +@begin(pdescription) + @i @itemsep the file name string or symbol + + :direction @itemsep :input or :output (default is :input) + + returns @itemsep a stream + +@end(pdescription) +@blankspace(1) + (open-binary@pragma(defn)@index(open-binary)@index(open)@index(binary files) @i &key :direction) @itemsep open a binary file stream +@begin(pdescription) + @i @itemsep the file name string or symbol + + :direction @itemsep :input or :output (default is :input) + + returns @itemsep a stream + +@end(pdescription) +@blankspace(1) + + (close@pragma(defn)@index(close) @i) @itemsep close a file stream +@begin(pdescription) + @i @itemsep the stream + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (setdir@pragma(defn)@index(setdir)@index(change directory) @i)@foot(This is not a standard XLISP 2.0 function.) @itemsep set current directory +@begin(pdescription) + @i @itemsep the path of the new directory + + returns @itemsep the resulting full path, e.g. (setdir ".") gets the current working directory, or @xlcode(nil) if an error occurs + +@end(pdescription) +@blankspace(1) + + (listdir@pragma(defn)@index(listdir)@index(directory listing)@index(scan directory)@index(read directory)@index(list directory) @i)@foot(This is not a standard XLISP 2.0 function.) @itemsep get a directory listing +@begin(pdescription) + @i @itemsep the path of the directory to be listed + + returns @itemsep list of filenames in the directory + +@end(pdescription) +@blankspace(1) + + (get-temp-path@pragma(defn)@index(get-temp-path)@index(temporary files)@index(temp file))@foot(This is not a standard XLISP 2.0 function.) @itemsep get a path where a temporary file can be created. Under Windows, this is based on environment variables. If XLISP is running as a sub-process to Java, the environment may not exist, in which case the default result is the unfortunate choice @xlcode(c:\windows\). +@begin(pdescription) + returns @itemsep the resulting full path as a string + +@end(pdescription) +@blankspace(1) + + (get-user@pragma(defn)@index(get-user)@index(user name)@index(temp file))@foot(This is not a standard XLISP 2.0 function.) @itemsep get the user ID. In Unix systems (including OS X and Linux), this is the value of the USER environment variable. In Windows, this is currently just ``nyquist'', which is also returned if the environment variable cannot be accessed. This function is used to avoid the case of two users creating files of the same name in the same temp directory. +@begin(pdescription) + returns @itemsep the string naming the user + +@end(pdescription) +@blankspace(1) + (find-in-xlisp-path@pragma(defn)@index(find-in-xlisp-path) @i)@foot(This is not a standard XLISP 2.0 function.) @itemsep search the XLISP search path (e.g. @xlcode(XLISPPATH) from the environment) for @i(filename). If @i(filename) is not found as is, and there is no file extension, append "@code(.lsp)" to @i(filename) and search again. The current directory is not searched. +@begin(pdescription) + @i @itemsep the name of the file to search for + + returns @itemsep a full path name to the first occurrence found + +@end(pdescription) +@blankspace(1) + + (read-char@pragma(defn)@index(read-char)@index(get char) [@i]) @itemsep read a character from a stream +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + returns @itemsep the character + +@end(pdescription) +@blankspace(1) + + (peek-char@pragma(defn)@index(peek-char) [@i [@i]]) @itemsep peek at the next character +@begin(pdescription) + @i @itemsep flag for skipping white space (default is @xlcode(nil)) + + @i @itemsep the input stream (default is standard input) + + returns @itemsep the character (integer) + +@end(pdescription) +@blankspace(1) + + (write-char@pragma(defn)@index(write-char) @i [@i]) @itemsep write a character to a stream +@begin(pdescription) + @i @itemsep the character to write + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the character + +@end(pdescription) +@blankspace(1) + + (read-int@pragma(defn)@index(read-int) [@i [@i]]) @itemsep read a binary integer from a stream +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + @i @itemsep the length of the integer in bytes (default is 4) + + returns @itemsep the integer + +Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + (write-int@pragma(defn)@index(write-int) @i [@i [@i]]) @itemsep write a binary integer to a stream +@begin(pdescription) + @i @itemsep the character to write + + @i @itemsep the output stream (default is standard output) + + @i @itemsep the length of the integer in bytes (default is 4) + + returns @itemsep the integer + +Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + (read-float@pragma(defn)@index(read-float) [@i [@i]]) @itemsep read a binary floating-point number from a stream +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + @i @itemsep the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8) + + returns @itemsep the integer + +Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + (write-float@pragma(defn)@index(write-float) @i [@i [@i]]) @itemsep write a binary floating-point number to a stream +@begin(pdescription) + @i @itemsep the character to write + + @i @itemsep the output stream (default is standard output) + + @i @itemsep the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8) + + returns @itemsep the integer + +Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + (read-line@pragma(defn)@index(read-line) [@i]) @itemsep read a line from a stream +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + returns @itemsep the string + +@end(pdescription) +@blankspace(1) + + (read-byte@pragma(defn)@index(read-byte) [@i]) @itemsep read a byte from a stream +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + returns @itemsep the byte (integer) + +@end(pdescription) +@blankspace(1) + + (write-byte@pragma(defn)@index(write-byte) @i [@i]) @itemsep write a byte to a stream +@begin(pdescription) + @i @itemsep the byte to write (integer) + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the byte (integer) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(String Stream Functions)@index(String Stream Functions) + These functions operate on unnamed streams. An unnamed output + stream collects characters sent to it when it is used as the + destination of any output function. The functions +@xlcode(get-output-stream-string) and @xlcode(get-output-stream-list) return a string or a list of characters. + +An unnamed input stream is setup with the + @xlcode(make-string-input-stream) function and returns each character of the string when + it is used as the source of any input function. + +@begin(fdescription) +@blankspace(1) + (make-string-input-stream@pragma(defn)@index(make-string-input-stream) @i [@i [@i]]) +@begin(pdescription) + @i @itemsep the string + + @i @itemsep the starting offset + + @i @itemsep the ending offset + 1 + + returns @itemsep an unnamed stream that reads from the string + +@end(pdescription) +@blankspace(1) + + (make-string-output-stream)@pragma(defn)@index(make-string-output-stream) +@begin(pdescription) + returns @itemsep an unnamed output stream + +@end(pdescription) +@blankspace(1) + + (get-output-stream-string@pragma(defn)@index(get-output-stream-string) @i) +@begin(pdescription) + @i @itemsep the output stream + + returns @itemsep the output so far as a string + + Note: the output stream is emptied by this function +@end(pdescription) +@blankspace(1) + + (get-output-stream-list@pragma(defn)@index(get-output-stream-list) @i) +@begin(pdescription) + @i @itemsep the output stream + + returns @itemsep the output so far as a list + + Note: the output stream is emptied by this function +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(System Functions)@index(System Functions) +Note: the @xlcode(load) function first tries to load a file from the current directory. A @code(.lsp) extension is added if there is not already an alphanumeric extension following a period. If that fails, XLISP searches the path, which is obtained from the XLISPPATH environment variable in Unix and HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under Win32. (The Macintosh version has no search path.) + +@begin(fdescription) + (get-env@pragma(defn)@index(get-env)@index(getenv)@index(environment variables) @i) @itemsep get from an environment variable +@begin(pdescription) + @i @itemsep the name of the environment variable + + returns @itemsep string value of the environment variable, @xlcode(nil) if variable does not exist + +@end(pdescription) +@blankspace(1) + + (load@pragma(defn)@index(load) @i &key :verbose :print) @itemsep load a source file +@begin(pdescription) + @i @itemsep the filename string or symbol + + :verbose @itemsep the verbose flag (default is t) + + :print @itemsep the print flag (default is @xlcode(nil)) + + returns @itemsep the filename + +@end(pdescription) +@blankspace(1) + + (save@pragma(defn)@index(save) @i) @itemsep save workspace to a file +@begin(pdescription) + @i @itemsep the filename string or symbol + + returns @itemsep @xlcode(t) if workspace was written, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + (restore@pragma(defn)@index(restore) @i) @itemsep restore workspace from a file +@begin(pdescription) + @i @itemsep the filename string or symbol + + returns @itemsep @xlcode(nil) on failure, otherwise never returns + +@end(pdescription) +@blankspace(1) + + (dribble@pragma(defn)@index(dribble) [@i]) @itemsep create a file with a transcript of a session +@begin(pdescription) + @i @itemsep file name string or symbol + (if missing, close current transcript) + + returns @itemsep @xlcode(t) if the transcript is opened, @xlcode(nil) if it is closed + +@end(pdescription) +@blankspace(1) + + (gc@pragma(defn)@index(gc)) @itemsep force garbage collection +@begin(pdescription) + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (expand@pragma(defn)@index(expand) @i) @itemsep expand memory by adding segments +@begin(pdescription) + @i @itemsep the number of segments to add + + returns @itemsep the number of segments added + +@end(pdescription) +@blankspace(1) + + (alloc@pragma(defn)@index(alloc) @i) @itemsep change number of nodes to allocate in each segment +@begin(pdescription) + @i @itemsep the number of nodes to allocate + + returns @itemsep the old number of nodes to allocate + +@end(pdescription) +@blankspace(1) + + (info@pragma(defn)@index(info)) @itemsep show information about memory usage. +@begin(pdescription) + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (room@pragma(defn)@index(room)) @itemsep show memory allocation statistics +@begin(pdescription) + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + (type-of@pragma(defn)@index(type-of) @i) @itemsep returns the type of the expression +@begin(pdescription) + @i @itemsep the expression to return the type of + + returns @itemsep @xlcode(nil) if the value is @xlcode(nil) otherwise one of the symbols: + +@begin(pdescription) + SYMBOL @itemsep for symbols + + OBJECT @itemsep for objects + + CONS @itemsep for conses + + SUBR @itemsep for built-in functions + + FSUBR @itemsep for special forms + + CLOSURE @itemsep for defined functions + + STRING @itemsep for strings + + FIXNUM @itemsep for integers + + FLONUM @itemsep for floating point numbers + + CHARACTER @itemsep for characters + + FILE-STREAM @itemsep for file pointers + + UNNAMED-STREAM @itemsep for unnamed streams + + ARRAY @itemsep for arrays + +@end(pdescription) +@end(pdescription) +@blankspace(1) + + (peek@pragma(defn)@index(peek) @i) @itemsep peek at a location in memory +@begin(pdescription) + @i @itemsep the address to peek at (integer) + + returns @itemsep the value at the specified address (integer) + +@end(pdescription) +@blankspace(1) + + (poke@pragma(defn)@index(poke) @i @i) @itemsep poke a value into memory +@begin(pdescription) + @i @itemsep the address to poke (integer) + + @i @itemsep the value to poke into the address (integer) + + returns @itemsep the value + +@end(pdescription) +@blankspace(1) + + (bigendianp@pragma(defn)@index(bigendianp)@index(endian)@index(big endian)@index(little endian)) @itemsep is this a big-endian machine? +@begin(pdescription) + returns @itemsep T if this a big-endian architecture, storing the high-order byte of an integer at the lowest byte address of the integer; otherwise, NIL. +@foot(This is not a standard XLISP 2.0 function.) + +@end(pdescription) +@blankspace(1) + + (address-of@pragma(defn)@index(address-of) @i) @itemsep get the address of an xlisp node +@begin(pdescription) + @i @itemsep the node + + returns @itemsep the address of the node (integer) + +@end(pdescription) +@blankspace(1) + + (exit@pragma(defn)@index(exit)) @itemsep exit xlisp +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + (setup-console@pragma(defn)@index(setup-console)@index(window initialization)) @itemsep set default console attributes +@begin(pdescription) + returns @itemsep NIL + +Note: Under Windows, Nyquist normally starts up in a medium-sized console window with black text and a white background, with a window title of ``Nyquist.'' This is normally accomplished by calling @xlcode(setup-console) in @code(system.lsp). In Nyquist, you can avoid this behavior by setting @xlcode(*setup-console*) to NIL in your @code(init.lsp) file. If @xlcode(setup-console) is not called, Nyquist uses standard input and output as is. This is what you want if you are running Nyquist inside of emacs, for example.@index(emacs, using Nyquist with) + +@end(pdescription) +@blankspace(1) + + (echoenabled@pragma(defn)@index(echoenabled)@index(console, XLISP) @i) @itemsep turn console input echoing on or off +@begin(pdescription) + @i @itemsep T to enable echo, NIL to disable + + returns @itemsep NIL + +Note: This function is only implemented under Linux and Mac OS X. If Nyquist I/O is redirected through pipes, +the Windows version does not echo the input, but the Linux and Mac versions do. You can turn off echoing with +this function. Under windows it is defined to do nothing. + +@end(pdescription) +@end(fdescription) + +@section(File I/O Functions)@index(File I/O Functions) + +@subsection(Input from a File)@index(Input from a File) + +To open a file for input, use the @xlcode(open) function with the keyword +argument @xlcode(:direction) set to @xlcode(:input). To open a file for output, +use the @xlcode(open) function with the keyword argument @xlcode(:direction) set +to @xlcode(:output). The @xlcode(open) function takes a single required argument which +is the name of the file to be opened. This name can be in the form of a +string or a symbol. The @xlcode(open) function returns an object of type +@xlcode(FILE-STREAM) if it succeeds in opening the specified file. It returns the +value @xlcode(nil) if it fails. In order to manipulate the file, it is +necessary to save the value returned by the @xlcode(open) function. This is +usually done by assigning it to a variable with the @xlcode(setq) special form or by +binding it using @xlcode(let) or @xlcode(let*). Here is an example: +@begin(example) +(setq fp (open "init.lsp" :direction :input)) +@end(example) + Evaluating this expression will result in the file @code(init.lsp) + being opened. The file object that will be returned by the @xlcode(open) + function will be assigned to the variable @xlcode(fp). + + It is now possible to use the file for input. To read an + expression from the file, just supply the value of the @xlcode(fp) + variable as the optional @i(stream) argument to @xlcode(read). +@begin(example) +(read fp) +@end(example) + Evaluating this expression will result in reading the first + expression from the file @code(init.lsp). The expression will be + returned as the result of the @xlcode(read) function. More expressions + can be read from the file using further calls to the @xlcode(read) + function. When there are no more expressions to read, the @xlcode(read) + function will return @xlcode(nil) (or whatever value was supplied as the + second argument to @xlcode(read)). + + Once you are done reading from the file, you should close it. + To close the file, use the following expression: +@begin(example) +(close fp) +@end(example) + Evaluating this expression will cause the file to be closed. + +@subsection(Output to a File)@index(Output to a File) + + Writing to a file is pretty much the same as reading from one. + You need to open the file first. This time you should use the + @xlcode(open) function to indicate that you will do output to the file. + For example: +@begin(example) +(setq fp (open "test.dat" :direction :output)) +@end(example) + Evaluating this expression will open the file @code(test.dat) for + output. If the file already exists, its current contents will + be discarded. If it doesn't already exist, it will be created. + In any case, a @xlcode(FILE-STREAM) object will be returned by the @xlcode(OPEN) + function. This file object will be assigned to the @xlcode(fp) + variable. + + It is now possible to write to this file by supplying the value + of the @xlcode(fp) variable as the optional @i(stream) parameter in the @xlcode(print) function. +@begin(example) +(print "Hello there" fp) +@end(example) + Evaluating this expression will result in the string ``Hello + there'' being written to the file @code(test.dat). More data can be + written to the file using the same technique. + + Once you are done writing to the file, you should close it. + Closing an output file is just like closing an input file. +@begin(example) +(close fp) +@end(example) + Evaluating this expression will close the output file and make + it permanent. + +@subsection(A Slightly More Complicated File Example) + + This example shows how to open a file, read each Lisp expression + from the file and print it. It demonstrates the use of files + and the use of the optional @i(stream) argument to the @xlcode(read) + function. +@begin(programexample) +(do* ((fp (open "test.dat" :direction :input)) + (ex (read fp) (read fp))) + ((null ex) nil) + (print ex)) +@end(programexample) + diff --git a/docsrc/xlisp/xlisp.mss b/docsrc/xlisp/xlisp.mss new file mode 100644 index 0000000..cc00251 --- /dev/null +++ b/docsrc/xlisp/xlisp.mss @@ -0,0 +1,4016 @@ +@define(codef, FaceCode T, size 11) +@comment{In my original scribe conversion of the ascii xlisp documentation, I used + times roman fonts for xlisp function names and code text in general. To be + consistent with Nyquist documentation, I have changed the code font to xlcode + which is defined here. If this turns out to be a problem, redefine xlcode to + use the regular FaceCode. -RBD} +@define(xlcode, FaceCode T, size 11) +@textform(pragma=[]) +@section(Introduction) + XLISP is an experimental programming language combining some of + the features of Common Lisp with an object-oriented extension + capability. It was implemented to allow experimentation with + object-oriented programming on small computers. + + Implementations of XLISP run on virtually every operating system. + XLISP is completely written in the programming language + C and is easily extended with user written built-in functions + and classes. It is available in source form to non-commercial + users. + + Many Common Lisp functions are built into XLISP. In addition, + XLISP defines the objects Object and Class as primitives. + Object is the only class that has no superclass and hence is + the root of the class hierarchy tree. Class is the class of + which all classes are instances (it is the only object that is + an instance of itself). + + This document is a brief description of XLISP. It assumes some + knowledge of LISP and some understanding of the concepts of + object-oriented programming. + + I recommend the book @i(Lisp) by Winston and Horn and published by + Addison Wesley for learning Lisp. The first edition of this + book is based on MacLisp and the second edition is based on + Common Lisp. + + You will probably also need a copy of @i(Common Lisp: The + Language) by Guy L. Steele, Jr., published by Digital Press to + use as a reference for some of the Common Lisp functions that + are described only briefly in this document. + + @section(A Note From The Author) + + If you have any problems with XLISP, feel free to contact me [me being David Betz - RBD] for + help or advice. Please remember that since XLISP is available + in source form in a high level language, many users [e.g. that Dannenberg fellow - RBD] have been + making versions available on a variety of machines. If you call + to report a problem with a specific version, I may not be able + to help you if that version runs on a machine to which I don't + have access. Please have the version number of the version that + you are running readily accessible before calling me. + + If you find a bug in XLISP, first try to fix the bug yourself + using the source code provided. If you are successful in fixing + the bug, send the bug report along with the fix to me. If you + don't have access to a C compiler or are unable to fix a bug, + please send the bug report to me and I'll try to fix it. + + Any suggestions for improvements will be welcomed. Feel free to + extend the language in whatever way suits your needs. However, + PLEASE DO NOT RELEASE ENHANCED VERSIONS WITHOUT CHECKING WITH ME + FIRST!! I would like to be the clearing house for new features + added to XLISP. If you want to add features for your own + personal use, go ahead. But, if you want to distribute your + enhanced version, contact me first. Please remember that the + goal of XLISP is to provide a language to learn and experiment + with LISP and object-oriented programming on small computers. I + don't want it to get so big that it requires megabytes of memory + to run. + + + @section(XLISP Command Loop)@index(XLISP Command Loop)@index(Command Loop) + + When XLISP is started, it first tries to load the workspace + @code(xlisp.wks) from the current directory. If that file doesn't + exist, XLISP builds an initial workspace, empty except for the + built-in functions and symbols. + + Then XLISP attempts to load @code(init.lsp) from the current + directory. It then loads any files named as parameters on the + command line (after appending @code(.lsp) to their names). + + XLISP then issues the following prompt: +@begin(example) + > +@end(example) + This indicates that XLISP is waiting for an expression to be + typed. + + When a complete expression has been entered, XLISP attempts to + evaluate that expression. If the expression evaluates + successfully, XLISP prints the result and then returns to the + initial prompt waiting for another expression to be typed. + + @section(Special Characters)@index(control characters, XLISP) + + When XLISP is running from a console, some control characters invoke operations: +@begin(itemize) +Backspace and Delete characters erase the previous character on the input line (if any). + +Control-U erases the entire input line. + +Control-C executes the TOP-LEVEL function. + +Control-G executes the CLEAN-UP function. + +Control-P executes the CONTINUE function. + +Control-B stops execution and enters the break command loop. Execution can be continued by typing Control-P or (CONTINUE). + +Control-E turns on character echoing (Linux and Mac OS X only). + +Control-F turns off character echoing (Linux and Mac OS X only). + +Control-T evaluates the INFO function. +@end(itemize) + + @section(Break Command Loop)@index(break) + + When XLISP encounters an error while evaluating an expression, + it attempts to handle the error in the following way: + + If the symbol @xlcode(*breakenable*@index(*breakenable*)) is + true, the message corresponding to the error is printed. If + the error is correctable, the correction message is printed. + + If the symbol @xlcode(*tracenable*@index(*tracenable*)) is true, a trace back is printed. + The number of entries printed depends on the value of the symbol + @xlcode(*tracelimit*@index(*tracelimit*)). If this symbol is set to something other than a + number, the entire trace back stack is printed. + + XLISP then enters a read/eval/print loop to allow the user to + examine the state of the interpreter in the context of the + error. This loop differs from the normal top-level + read/eval/print loop in that if the user invokes the function + @xlcode(continue), XLISP will continue from a correctable error. If + the user invokes the function @xlcode(clean-up), XLISP will abort the + break loop and return to the top level or the next lower + numbered break loop. When in a break loop, XLISP prefixes the + break level to the normal prompt. + + If the symbol @xlcode(*breakenable*@index(*breakenable*)) is @xlcode(nil), XLISP looks for a + surrounding errset function. If one is found, XLISP examines + the value of the print flag. If this flag is true, the error + message is printed. In any case, XLISP causes the errset + function call to return @xlcode(nil). + + If there is no surrounding errset function, XLISP prints the + error message and returns to the top level. + + @section(Data Types)@index(XLISP Data Types)@index(Data Types) + + There are several different data types available to XLISP + programmers. + +@begin(itemize) +lists + +symbols + +strings + +integers + +characters + +floats + +objects + +arrays + +streams + +subrs (built-in functions) + +fsubrs (special forms) + +closures (user defined functions) +@end(itemize) + + + + +@section(The Evaluator)@index(evaluator)@index(XLISP evaluator) + + The process of evaluation in XLISP: +@begin(itemize) + Strings, integers, characters, floats, objects, arrays, streams, + subrs, fsubrs and closures evaluate to themselves. + + Symbols act as variables and are evaluated by retrieving the + value associated with their current binding. + + Lists are evaluated by examining the first element of the list + and then taking one of the following actions: +@begin(itemize) + If it is a symbol, the functional binding of the symbol is + retrieved. + + If it is a lambda expression, a closure is constructed for + the function described by the lambda expression. + + If it is a subr, fsubr or closure, it stands for itself. + + Any other value is an error. +@end(itemize) + Then, the value produced by the previous step is examined: +@begin(itemize) + If it is a subr or closure, the remaining list elements are + evaluated and the subr or closure is called with these + evaluated expressions as arguments. + + If it is an fsubr, the fsubr is called using the remaining + list elements as arguments (unevaluated). + + If it is a macro, the macro is expanded using the remaining + list elements as arguments (unevaluated). The macro + expansion is then evaluated in place of the original macro + call. +@end(itemize) +@end(itemize) + +@section(Lexical Conventions)@index(Lexical conventions)@index(XLISP Lexical Conventions) + + The following conventions must be followed when entering XLISP + programs: + + Comments in XLISP code begin with a semi-colon character and + continue to the end of the line. + + Symbol names in XLISP can consist of any sequence of non-blank + printable characters except the following: +@begin(example) + ( ) ' ` , " ; +@end(example) + Uppercase and lowercase characters are not distinguished within + symbol names. All lowercase characters are mapped to uppercase + on input. + + Integer literals consist of a sequence of digits optionally + beginning with a @code(+) or @code(-). The range of values an integer can + represent is limited by the size of a C @code(long) on the machine on + which XLISP is running. + + Floating point literals consist of a sequence of digits + optionally beginning with a @code(+) or @code(-) and including an embedded + decimal point. The range of values a floating point number can + represent is limited by the size of a C @code(float) (@code(double) on + machines with 32 bit addresses) on the machine on which XLISP is + running. + + Literal strings are sequences of characters surrounded by double + quotes. Within quoted strings the ``@code(\)'' character is used to + allow non-printable characters to be included. The codes + recognized are: +@begin(itemize) +@code(\\) means the character ``@code(\)'' + +@code(\n) means newline + +@code(\t) means tab + +@code(\r) means return + +@code(\f) means form feed + +@code(\nnn) means the character whose octal code is nnn +@end(itemize) + +@section(Readtables)@index(Readtables) + + The behavior of the reader is controlled by a data structure + called a @i(readtable). The reader uses the symbol @xlcode(*readtable*@index(*readtable*)) to + locate the current readtable. This table controls the + interpretation of input characters. It is an array with 128 + entries, one for each of the ASCII character codes. Each entry + contains one of the following things: +@begin(itemize) + @xlcode(NIL) @itemsep Indicating an invalid character + + @xlcode(:CONSTITUENT) @itemsep Indicating a symbol constituent + + @xlcode(:WHITE-SPACE) @itemsep Indicating a whitespace character + + @xlcode[(:TMACRO . @i(fun))] @itemsep Terminating readmacro + + @xlcode[(:NMACRO . @i(fun))] @itemsep Non-terminating readmacro + + @xlcode(:SESCAPE) @itemsep Single escape character ('\') + + @xlcode(:MESCAPE) @itemsep Multiple escape character ('|') +@end(itemize) + + In the case of @xlcode(:TMACRO) and @xlcode(:NMACRO), the @i(fun) component is a + function. This can either be a built-in readmacro function or a + lambda expression. The function should take two parameters. + The first is the input stream and the second is the character + that caused the invocation of the readmacro. The readmacro + function should return @xlcode(NIL) to indicate that the character should + be treated as white space or a value consed with @xlcode(NIL) to indicate + that the readmacro should be treated as an occurence of the + specified value. Of course, the readmacro code is free to read + additional characters from the input stream. + + XLISP defines several useful read macros@index(read macros): +@begin(itemize) + @xlcode(')@i[] == @xlcode{(quote} @i[]@xlcode{)} + + @xlcode(#')@i[] == @xlcode{(function} @i[]@xlcode{)} + + @xlcode{#(}@i[]...@xlcode{)} == an array of the specified expressions + + @xlcode(#x)@i[] == a hexadecimal number (0-9,A-F) + + @xlcode(#o)@i[] == an octal number (0-7) + + @xlcode(#b)@i[] == a binary number (0-1) + + @xlcode(#\)@i[] == the ASCII code of the character + + @xlcode(#|) ... @xlcode(|#) == a comment + + @xlcode(#:)@i[] == an uninterned symbol + + @xlcode(`)@i[] == @xlcode{(backquote} @i[]@xlcode{)} + + @xlcode(,)@i[] == @xlcode{(comma} @i[]@xlcode{)} + + @xlcode(,@@)@i[] == @xlcode{(comma-at} @i[]@xlcode{)} + +@end(itemize) +@section(Lambda Lists)@index(Lambda Lists) + + There are several forms in XLISP that require that a ``lambda + list'' be specified. A lambda list is a definition of the + arguments accepted by a function. There are four different + types of arguments. + + The lambda list starts with required arguments. Required + arguments must be specified in every call to the function. + + The required arguments are followed by the @xlcode(&optional) arguments. + Optional arguments may be provided or omitted in a call. An + initialization expression may be specified to provide a default + value for an @xlcode(&optional) argument if it is omitted from a call. + If no initialization expression is specified, an omitted + argument is initialized to @xlcode(NIL). It is also possible to provide + the name of a @xlcode(supplied-p) variable that can be used to + determine if a call provided a value for the argument or if the + initialization expression was used. If specified, the supplied- + p variable will be bound to T if a value was specified in the + call and @xlcode(NIL) if the default value was used. + + The @xlcode(&optional) arguments are followed by the @xlcode(&rest) argument. The + @xlcode(&rest) argument gets bound to the remainder of the argument list + after the required and @xlcode(&optional) arguments have been removed. + + The @xlcode(&rest) argument is followed by the @xlcode(&key) arguments. When a + keyword argument is passed to a function, a pair of values + appears in the argument list. The first expression in the pair + should evaluate to a keyword symbol (a symbol that begins with a + ``@code(:)''). The value of the second expression is the value of the + keyword argument. Like @xlcode(&optional) arguments, @xlcode(&key) arguments can + have initialization expressions and supplied-p variables. In + addition, it is possible to specify the keyword to be used in a + function call. If no keyword is specified, the keyword obtained + by adding a ``@code(:)'' to the beginning of the keyword argument symbol + is used. In other words, if the keyword argument symbol is + @xlcode(foo), the keyword will be @xlcode(:foo). + + The @xlcode(&key) arguments are followed by the @xlcode(&aux) variables. These + are local variables that are bound during the evaluation of the + function body. It is possible to have initialization + expressions for the @xlcode(&aux) variables. + + Here is the complete syntax for lambda lists: +@begin(display) + (@i... + [@xlcode(&optional) [@i | (@i [@i [@i]])]...] + [@xlcode(&rest) @i] + [@xlcode(&key) + [@i | ([@i | (@i @i)] [@i [@i]])]... + @xlcode(&allow)-other-keys] + [@xlcode(&aux) + [@i | (@i [@i])]...]) + + where: + + @i is a required argument symbol + @i is an @xlcode(&optional) argument symbol + @i is the @xlcode(&rest) argument symbol + @i is a @xlcode(&key) argument symbol + @i is a keyword symbol + @i is an auxiliary variable symbol + @i is an initialization expression + @i is a supplied-p variable symbol +@end(display) + + +@section(Objects)@index(Objects)@label(objects-sec) + + Definitions: +@begin(itemize) +selector @itemsep a symbol used to select an appropriate method + +message @itemsep a selector and a list of actual arguments + +method @itemsep the code that implements a message +@end(itemize) + Since XLISP was created to provide a simple basis for + experimenting with object-oriented programming, one of the + primitive data types included is @i(object). In XLISP, an object + consists of a data structure containing a pointer to the + object's class as well as an array containing the values of the + object's instance variables. + + Officially, there is no way to see inside an object (look at the + values of its instance variables). The only way to communicate + with an object is by sending it a message. + + You can send a message to an object using the @xlcode(send) function. + This function takes the object as its first argument, the + message selector as its second argument (which must be a symbol) + and the message arguments as its remaining arguments. + + The @xlcode(send) function determines the class of the receiving object + and attempts to find a method corresponding to the message + selector in the set of messages defined for that class. If the + message is not found in the object's class and the class has a + super-class, the search continues by looking at the messages + defined for the super-class. This process continues from one + super-class to the next until a method for the message is found. + If no method is found, an error occurs. + +@begin(comment) +THIS IS WRONG -- I DON'T KNOW IF IT WAS CORRECT IN THE ORIGINAL XLISP. -RBD + A message can also be sent from the body of a method by using + the current object, but the method lookup starts with the + object's superclass rather than its class. This allows a + subclass to invoke a standard method in its parent class even + though it overrides that method with its own specialized + version. +@end(comment) + + When a method is found, the evaluator binds the receiving object + to the symbol @xlcode(self) and evaluates the method using the + remaining elements of the original list as arguments to the + method. These arguments are always evaluated prior to being + bound to their corresponding formal arguments. The result of + evaluating the method becomes the result of the expression. + + Within the body of a method, a message can be sent to the current + object by calling the @xlcode[(send self ...)]. The method lookup + starts with the object's class regardless of the class containing + the current method. + + Sometimes it is desirable to invoke a general method in a superclass + even when it is overridden by a more specific method in a subclass. + This can be accomplished by calling @xlcode(send-super), which begins + the method lookup in the superclass of the class defining the current + method rather than in the class of the current object. + + The @xlcode(send-super) function takes a selector as its first argument + (which must be a symbol) and the message arguments as its remaining + arguments. Notice that @xlcode(send-super) can only be sent from within + a method, and the target of the message is always the current object + (@xlcode(self)). @xlcode[(send-super ...)] is similar to + @xlcode[(send self ...)] except that method lookup begins in the + superclass of the class containing the current method + rather than the class of the current object. + +@section(The ``Object'' Class)@index(Object Class) + +@xlcode(Object)@index(Object) @itemsep the top of the class hierarchy. + +Messages: +@begin(fdescription) +@xlcode(:show@index(:show)) @itemsep show an object's instance variables. +@begin(pdescription) +returns @itemsep the object +@end(pdescription) +@blankspace(1) + +@xlcode{:class@index(:class)} @itemsep return the class of an object +@begin(pdescription) +returns @itemsep the class of the object +@end(pdescription) +@blankspace(1) + +@xlcode{:isa@index(:isa)} @i(class) @itemsep test if object inherits from class +@begin(pdescription) +returns @itemsep @xlcode(t) if object is an instance of @i(class) or a subclass of @i(class), otherwise @xlcode(nil) +@end(pdescription) +@blankspace(1) + +@xlcode(:isnew@index(:isnew)) @itemsep the default object initialization routine +@begin(pdescription) +returns @itemsep the object +@end(pdescription) +@end(fdescription) + +@section(The ``Class'' Class)@index(Class class) + +@xlcode(Class@index(Class)) @itemsep class of all object classes (including itself) + + Messages: + +@begin(fdescription) + @xlcode(:new@index(:new)) @itemsep create a new instance of a class +@begin(pdescription) + returns @itemsep the new class object +@end(pdescription) +@blankspace(1) + + @xlcode(:isnew@index(:isnew)) @i [@i [@i]] @itemsep initialize a new class +@begin(pdescription) + @i @itemsep the list of instance variable symbols + + @i @itemsep the list of class variable symbols + + @i @itemsep the superclass (default is object) + + returns @itemsep the new class object +@end(pdescription) +@blankspace(1) + + @xlcode(:answer@index(:answer)) @i @i @i @itemsep add a message to a class +@begin(pdescription) + @i @itemsep the message symbol + + @i @itemsep the formal argument list (lambda list) + + @i @itemsep a list of executable expressions + + returns @itemsep the object +@end(pdescription) +@blankspace(1) +@end(fdescription) + + When a new instance of a class is created by sending the message + @xlcode(:new) to an existing class, the message @xlcode(:isnew) followed by + whatever parameters were passed to the @xlcode(:new) message is sent to + the newly created object. + + When a new class is created by sending the @xlcode(:new) message to the + object @xlcode(Class), an optional parameter may be specified + indicating the superclass of the new class. If this parameter + is omitted, the new class will be a subclass of @xlcode(Object). A + class inherits all instance variables, class variables, and + methods from its super-class. + +@section(Profiling)@index(profiling) +The Xlisp 2.0 release has been extended with a profiling facility, which counts how many times and where @xlcode(eval) is executed. A separate count is maintained for each named function, closure, or macro, and a count indicates an @xlcode(eval) in the immediately (lexically) enclosing named function, closure, or macro. Thus, the count gives an indication of the amount of time spent in a function, not counting nested function calls. The list of all functions executed is maintained on the global @xlcode(*profile*) variable. These functions in turn have @xlcode(*profile*) properties, which maintain the counts. The profile system merely increments counters and puts symbols on the @xlcode(*profile*) list. It is up to the user to initialize data and gather results. Profiling is turned on or off with the @xlcode(profile) function. Unfortunately, methods cannot be profiled with this facility. + +@label(symbols-sec) +@section(Symbols)@index(symbols) +@begin(itemize) +@codef(self)@pragma(defn)@index(self) @dash the current object (within a method context) + +@codef(*obarray*@pragma(defn)@index(*obarray*)) @dash the object hash table + +@codef(*standard-input*@pragma(defn)@index(*standard-input*)) @dash the standard input stream + +@codef(*standard-output*@pragma(defn)@index(*standard-output*)) @dash the standard output stream + +@codef(*error-output*@pragma(defn)@index(*error-output*)) @dash the error output stream + +@codef(*trace-output*@pragma(defn)@index(*trace-output*)) @dash the trace output stream + +@codef(*debug-io*@pragma(defn)@index(*debug-io*)) @dash the debug i/o stream + +@codef(*breakenable*@pragma(defn)@index(*breakenable*)) @dash flag controlling entering break loop on errors + +@codef(*tracelist*@pragma(defn)@index(*tracelist*)) @dash list of names of functions to trace + +@codef(*tracenable*@pragma(defn)@index(*tracenable*)) @dash enable trace back printout on errors + +@codef(*tracelimit*@pragma(defn)@index(*tracelimit*)) @dash number of levels of trace back information + +@codef(*evalhook*@pragma(defn)@index(*evalhook*)) @dash user substitute for the evaluator function + +@codef(*applyhook*@pragma(defn)@index(*applyhook*)) @dash (not yet implemented) + +@codef(*readtable*@pragma(defn)@index(*readtable*)) @dash the current readtable + +@codef(*unbound*@pragma(defn)@index(*unbound*)) @dash indicator for unbound symbols + +@codef(*gc-flag*@pragma(defn)@index(*gc-flag*)) @dash controls the printing of gc messages + +@codef(*gc-hook*@pragma(defn)@index(*gc-hook*)) @dash function to call after garbage collection + +@codef(*integer-format*@pragma(defn)@index(*integer-format*)) @dash format for printing integers (``%d'' or ``%ld'') + +@codef(*float-format*@pragma(defn)@index(*float-format*)) @dash format for printing floats (``%g'') + +@codef(*print-case*@pragma(defn)@index(*print-case*)) @dash symbol output case (:upcase or :downcase) +@end(itemize) + + There are several symbols maintained by the read/eval/print + loop. The symbols @code(+), @code(++), and @code(+++) are bound to the most + recent three input expressions. The symbols @code(*), @code(**) and @code(***) + are bound to the most recent three results. The symbol @code(-) is + bound to the expression currently being evaluated. It becomes + the value of @code(+) at the end of the evaluation. +@section(Evaluation Functions)@index(evaluation functions) +@begin(fdescription) + @begin(fgroup)@xlcode{eval(@i(expr))} @c{[sal]} + + @xlcode{(eval@pragma(defn)@index(eval) @t(@i(expr)))} @c{[lisp]} @itemsep evaluate an xlisp expression +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to be evaluated + + returns @itemsep the result of evaluating the expression +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{apply(@i(fun), @i(args))} @c{[sal]} + + @xlcode{(apply@pragma(defn)@index(apply) @t(@i(fun)) @t(@i(args)))} @c{[lisp]} @itemsep apply a function to a list of arguments +@end(fgroup) +@begin(pdescription) + @i @itemsep the function to apply (or function symbol) + + @i @itemsep the argument list + + returns @itemsep the result of applying the function to the arguments +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{funcall(@i(fun), @i(arg)@r(...))} @c{[sal]} + + @xlcode{(funcall@pragma(defn)@index(funcall) @t(@i(fun)) @t(@i(arg))@r(...))} @c{[lisp]} @itemsep call a function with arguments +@end(fgroup) +@begin(pdescription) + @i @itemsep the function to call (or function symbol) + + @i @itemsep arguments to pass to the function + + returns @itemsep the result of calling the function with the arguments +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{quote(@i(expr))} @c{[sal]} + + @xlcode{(quote@pragma(defn)@index(quote) @t(@i(expr)))} @c{[lisp]} @itemsep return an expression unevaluated +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to be quoted (quoted) + + returns @itemsep @i unevaluated +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{function(@i(expr))} @c{[sal]} + + @xlcode{(function@pragma(defn)@index(function) @t(@i(expr)))} @c{[lisp]} @itemsep get the functional interpretation +@end(fgroup) + +@begin(pdescription) + @i @itemsep the symbol or lambda expression (quoted) + + returns @itemsep the functional interpretation + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{backquote(@i(expr))} @c{[sal]} + + @xlcode{(backquote@pragma(defn)@index(backquote) @t(@i(expr)))} @c{[lisp]} @itemsep fill in a template +@end(fgroup) + +@begin(pdescription) + @i @itemsep the template + + returns @itemsep a copy of the template with comma and comma-at + + expressions expanded +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{lambda(@i(args), @i(expr)@r(...))} @c{[sal]} + + @xlcode{(lambda@pragma(defn)@index(lambda) @t(@i(args)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep make a function closure +@end(fgroup) + +@begin(pdescription) + @i @itemsep formal argument list (lambda list) (quoted) + + @i @itemsep expressions of the function body + + returns @itemsep the function closure + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{get-lambda-expression(@i(closure))} @c{[sal]} + + @xlcode{(get-lambda-expression@pragma(defn)@index(get-lambda-expression) @t(@i(closure)))} @c{[lisp]} @itemsep get the lambda expression +@end(fgroup) + +@begin(pdescription) + @i @itemsep the closure + + returns @itemsep the original lambda expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{macroexpand(@i(form))} @c{[sal]} + + @xlcode{(macroexpand@pragma(defn)@index(macroexpand) @t(@i(form)))} @c{[lisp]} @itemsep recursively expand macro calls +@end(fgroup) + +@begin(pdescription) + @i @itemsep the form to expand + + returns @itemsep the macro expansion + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{macroexpand-1(@i(form))} @c{[sal]} + + @xlcode{(macroexpand-1@pragma(defn)@index(macroexpand-1) @t(@i(form)))} @c{[lisp]} @itemsep expand a macro call +@end(fgroup) + +@begin(pdescription) + @i @itemsep the macro call form + + returns @itemsep the macro expansion + +@end(pdescription) +@blankspace(1) +@end(fdescription) + + +@section(Symbol Functions)@index(Symbol Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{set(@i(sym), @i(expr))} @c{[sal]} + + @xlcode{(set@pragma(defn)@index(set) @t(@i(sym)) @t(@i(expr)))} @c{[lisp]} @itemsep set the value of a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol being set + + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{setq([@i(sym), @i(expr)]@r(...))} @c{[sal]} + + @xlcode{(setq@pragma(defn)@index(setq) [@t(@i(sym)) @t(@i(expr))]@r(...))} @c{[lisp]} @itemsep set the value of a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol being set (quoted) + + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{psetq([@i(sym), @i(expr)]@r(...))} @c{[sal]} + + @xlcode{(psetq@pragma(defn)@index(psetq) [@t(@i(sym)) @t(@i(expr))]@r(...))} @c{[lisp]} @itemsep parallel version of setq +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol being set (quoted) + + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{setf([@i(place), @i(expr)]@r(...))} @c{[sal]} + + @xlcode{(setf@pragma(defn)@index(setf) [@t(@i(place)) @t(@i(expr))]@r(...))} @c{[lisp]} @itemsep set the value of a field +@end(fgroup) +@begin(pdescription) + @i @itemsep the field specifier (quoted): + +@begin(pdescription) + @i @itemsep set value of a symbol + + (car @i) @itemsep set car of a cons node + + (cdr @i) @itemsep set cdr of a cons node + + (nth @i @i) @itemsep set nth car of a list + + (aref @i @i) @itemsep set nth element of an array + + (get @i @i) @itemsep set value of a property + + (symbol-value @i) @itemsep set value of a symbol + + (symbol-function @i) @itemsep set functional value of a symbol + + (symbol-plist @i) @itemsep set property list of a symbol + +@end(pdescription)@pragma(stopcodef) + @i @itemsep the new value + + returns @itemsep the new value + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + @xlcode{(defun@pragma(defn)@index(defun) @t(@i(sym)) @t(@i(fargs)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep define a function + +@pragma(startcodef) + @xlcode{(defmacro@pragma(defn)@index(defmacro) @t(@i(sym)) @t(@i(fargs)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep define a macro +@end(fgroup) +@begin(pdescription) + @i @itemsep symbol being defined (quoted) + + @i @itemsep formal argument list (lambda list) (quoted) + + @i @itemsep expressions constituting the body of the + + function (quoted) + returns @itemsep the function symbol + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{gensym([@i(tag)])} @c{[sal]} + + @xlcode{(gensym@pragma(defn)@index(gensym) [@t(@i(tag))])} @c{[lisp]} @itemsep generate a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep string or number + + returns @itemsep the new symbol + +@end(pdescription) +@blankspace(1) + +@begin(fgroup)@xlcode{intern(@i(pname))} @c{[sal]} + + @xlcode{(intern@pragma(defn)@index(intern) @t(@i(pname)))} @c{[lisp]} @itemsep make an interned symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol's print name string + + returns @itemsep the new symbol + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{make-symbol(@i(pname))} @c{[sal]} + + @xlcode{(make-symbol@pragma(defn)@index(make-symbol) @t(@i(pname)))} @c{[lisp]} @itemsep make an uninterned symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol's print name string + + returns @itemsep the new symbol + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{symbol-name(@i(sym))} @c{[sal]} + + @xlcode{(symbol-name@pragma(defn)@index(symbol-name) @t(@i(sym)))} @c{[lisp]} @itemsep get the print name of a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's print name + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{symbol-value(@i(sym))} @c{[sal]} + + @xlcode{(symbol-value@pragma(defn)@index(symbol-value) @t(@i(sym)))} @c{[lisp]} @itemsep get the value of a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's value + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{symbol-function(@i(sym))} @c{[sal]} + + @xlcode{(symbol-function@pragma(defn)@index(symbol-function) @t(@i(sym)))} @c{[lisp]} @itemsep get the functional value of a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's functional value + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{symbol-plist(@i(sym))} @c{[sal]} + + @xlcode{(symbol-plist@pragma(defn)@index(symbol-plist) @t(@i(sym)))} @c{[lisp]} @itemsep get the property list of a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep the symbol's property list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{hash(@i(sym), @i(n))} @c{[sal]} + + @xlcode{(hash@pragma(defn)@index(hash) @t(@i(sym)) @t(@i(n)))} @c{[lisp]} @itemsep compute the hash index for a symbol +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol or string + + @i @itemsep the table size (integer) + + returns @itemsep the hash index (integer) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Property List Functions)@index(Property List Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{get(@i(sym), @i(prop))} @c{[sal]} + + @xlcode{(get@pragma(defn)@index(get) @t(@i(sym)) @t(@i(prop)))} @c{[lisp]} @itemsep get the value of a property +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + @i @itemsep the property symbol + + returns @itemsep the property value or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{putprop(@i(sym), @i(val), @i(prop))} @c{[sal]} + + @xlcode{(putprop@pragma(defn)@index(putprop) @t(@i(sym)) @t(@i(val)) @t(@i(prop)))} @c{[lisp]} @itemsep put a property onto a property list +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + @i @itemsep the property value + + @i @itemsep the property symbol + + returns @itemsep the property value + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{remprop(@i(sym), @i(prop))} @c{[sal]} + + @xlcode{(remprop@pragma(defn)@index(remprop) @t(@i(sym)) @t(@i(prop)))} @c{[lisp]} @itemsep remove a property +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + @i @itemsep the property symbol + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Array Functions)@index(Array Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{aref(@i(array), @i(n))} @c{[sal]} + + @xlcode{(aref@pragma(defn)@index(aref) @t(@i(array)) @t(@i(n)))} @c{[lisp]} @itemsep get the nth element of an array +@end(fgroup) +@begin(pdescription) + @i @itemsep the array + + @i @itemsep the array index (integer) + + returns @itemsep the value of the array element + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{make-array(@i(size))} @c{[sal]} + + @xlcode{(make-array@pragma(defn)@index(make-array) @t(@i(size)))} @c{[lisp]} @itemsep make a new array +@end(fgroup) +@begin(pdescription) + @i @itemsep the size of the new array (integer) + + returns @itemsep the new array + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{vector(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(vector@pragma(defn)@index(vector) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep make an initialized vector +@end(fgroup) +@begin(pdescription) + @i @itemsep the vector elements + + returns @itemsep the new vector + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(List Functions)@index(List Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{car(@i(expr))} @c{[sal]} + + @xlcode{(car@pragma(defn)@index(car) @t(@i(expr)))} @c{[lisp]} @itemsep return the car of a list node +@end(fgroup) +@begin(pdescription) + @i @itemsep the list node + + returns @itemsep the car of the list node + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{cdr(@i(expr))} @c{[sal]} + + @xlcode{(cdr@pragma(defn)@index(cdr) @t(@i(expr)))} @c{[lisp]} @itemsep return the cdr of a list node +@end(fgroup) +@begin(pdescription) + @i @itemsep the list node + + returns @itemsep the cdr of the list node + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{c@i(xx)r(@i(expr))} @c{[sal]} + + @xlcode{(c@i(xx)r@index(cxxr) @t(@i(expr)))} @c{[lisp]} @itemsep all c@i(xx)r combinations +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{c@i(xxx)r(@i(expr))} @c{[sal]} + + @xlcode{(c@i(xxx)r@index(cxxxr) @t(@i(expr)))} @c{[lisp]} @itemsep all c@i(xxx)r combinations +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{c@i(xxxx)r(@i(expr))} @c{[sal]} + + @xlcode{(c@i(xxxx)r@index(cxxxxr) @t(@i(expr)))} @c{[lisp]} @itemsep all c@i(xxxx)r combinations +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{first(@i(expr))} @c{[sal]} + + @xlcode{(first@pragma(defn)@index(first) @t(@i(expr)))} @c{[lisp]} @itemsep a synonym for car +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{second(@i(expr))} @c{[sal]} + + @xlcode{(second@pragma(defn)@index(second) @t(@i(expr)))} @c{[lisp]} @itemsep a synonym for cadr +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{third(@i(expr))} @c{[sal]} + + @xlcode{(third@pragma(defn)@index(third) @t(@i(expr)))} @c{[lisp]} @itemsep a synonym for caddr +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{fourth(@i(expr))} @c{[sal]} + + @xlcode{(fourth@pragma(defn)@index(fourth) @t(@i(expr)))} @c{[lisp]} @itemsep a synonym for cadddr +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{rest(@i(expr))} @c{[sal]} + + @xlcode{(rest@pragma(defn)@index(rest) @t(@i(expr)))} @c{[lisp]} @itemsep a synonym for cdr +@end(fgroup) +@begin(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{cons(@i(expr1), @i(expr2))} @c{[sal]} + + @xlcode{(cons@pragma(defn)@index(cons) @t(@i(expr1)) @t(@i(expr2)))} @c{[lisp]} @itemsep construct a new list node +@end(fgroup) +@begin(pdescription) + @i @itemsep the car of the new list node + + @i @itemsep the cdr of the new list node + + returns @itemsep the new list node + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{list(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(list@pragma(defn)@index(list) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep create a list of values +@end(fgroup) +@begin(pdescription) + @i @itemsep expressions to be combined into a list + + returns @itemsep the new list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{append(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(append@pragma(defn)@index(append) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep append lists +@end(fgroup) +@begin(pdescription) + @i @itemsep lists whose elements are to be appended + + returns @itemsep the new list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{reverse(@i(expr))} @c{[sal]} + + @xlcode{(reverse@pragma(defn)@index(reverse) @t(@i(expr)))} @c{[lisp]} @itemsep reverse a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the list to reverse + + returns @itemsep a new list in the reverse order + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{last(@i(list))} @c{[sal]} + + @xlcode{(last@pragma(defn)@index(last) @t(@i(list)))} @c{[lisp]} @itemsep return the last list node of a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the list + + returns @itemsep the last list node in the list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{member(@i(expr), @i(list), test: @i(test), test-not: @i(test-not))} @c{[sal]} + + @xlcode{(member@pragma(defn)@index(member) @t(@i(expr)) @t(@i(list)) @t(&key )@t(:test) @t(:test-not))} @c{[lisp]} @itemsep find an expression in a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to find + + @i @itemsep the list to search + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the remainder of the list starting with the expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{assoc(@i(expr), @i(alist), test: @i(test), test-not: @i(test-not))} @c{[sal]} + + @xlcode{(assoc@pragma(defn)@index(assoc) @t(@i(expr)) @t(@i(alist)) @t(&key )@t(:test) @t(:test-not))} @c{[lisp]} @itemsep find an expression in an a-list +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to find + + @i @itemsep the association list + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the alist entry or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{remove(@i(expr), @i(list), test: @i(test), test-not: @i(test-not))} @c{[sal]} + + @xlcode{(remove@pragma(defn)@index(remove) @t(@i(expr)) @t(@i(list)) @t(&key )@t(:test) @t(:test-not))} @c{[lisp]} @itemsep remove elements from a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the element to remove + + @i @itemsep the list + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep copy of list with matching expressions removed + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{remove-if(@i(test), @i(list))} @c{[sal]} + + @xlcode{(remove-if@pragma(defn)@index(remove-if) @t(@i(test)) @t(@i(list)))} @c{[lisp]} @itemsep remove elements that pass test +@end(fgroup) +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep copy of list with matching elements removed + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{remove-if-not(@i(test), @i(list))} @c{[sal]} + + @xlcode{(remove-if-not@pragma(defn)@index(remove-if-not) @t(@i(test)) @t(@i(list)))} @c{[lisp]} @itemsep remove elements that fail test +@end(fgroup) +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep copy of list with non-matching elements removed + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{length(@i(expr))} @c{[sal]} + + @xlcode{(length@pragma(defn)@index(length) @t(@i(expr)))} @c{[lisp]} @itemsep find the length of a list, vector or string +@end(fgroup) +@begin(pdescription) + @i @itemsep the list, vector or string + + returns @itemsep the length of the list, vector or string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{nth(@i(n), @i(list))} @c{[sal]} + + @xlcode{(nth@pragma(defn)@index(nth) @t(@i(n)) @t(@i(list)))} @c{[lisp]} @itemsep return the nth element of a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the number of the element to return (zero origin) + + @i @itemsep the list + + returns @itemsep the nth element or @xlcode(nil) if the list isn't that long + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{nthcdr(@i(n), @i(list))} @c{[sal]} + + @xlcode{(nthcdr@pragma(defn)@index(nthcdr) @t(@i(n)) @t(@i(list)))} @c{[lisp]} @itemsep return the nth cdr of a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the number of the element to return (zero origin) + + @i @itemsep the list + + returns @itemsep the nth cdr or @xlcode(nil) if the list isn't that long + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{mapc(@i(fcn), @i(list1), @i(list)@r(...))} @c{[sal]} + + @xlcode{(mapc@pragma(defn)@index(mapc) @t(@i(fcn)) @t(@i(list1)) @t(@i(list))@r(...))} @c{[lisp]} @itemsep apply function to successive cars +@end(fgroup) +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep the first list of arguments + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{mapcar(@i(fcn), @i(list1), @i(list)@r(...))} @c{[sal]} + + @xlcode{(mapcar@pragma(defn)@index(mapcar) @t(@i(fcn)) @t(@i(list1)) @t(@i(list))@r(...))} @c{[lisp]} @itemsep apply function to successive cars +@end(fgroup) +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep a list of the values returned + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{mapl(@i(fcn), @i(list1), @i(list)@r(...))} @c{[sal]} + + @xlcode{(mapl@pragma(defn)@index(mapl) @t(@i(fcn)) @t(@i(list1)) @t(@i(list))@r(...))} @c{[lisp]} @itemsep apply function to successive cdrs +@end(fgroup) +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep the first list of arguments + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{maplist(@i(fcn), @i(list1), @i(list)@r(...))} @c{[sal]} + + @xlcode{(maplist@pragma(defn)@index(maplist) @t(@i(fcn)) @t(@i(list1)) @t(@i(list))@r(...))} @c{[lisp]} @itemsep apply function to successive cdrs +@end(fgroup) +@begin(pdescription) + @i @itemsep the function or function name + + @i @itemsep a list for each argument of the function + + returns @itemsep a list of the values returned + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{subst(@i(to), @i(from), @i(expr), test: @i(test), test-not: @i(test-not))} @c{[sal]} + + @xlcode{(subst@pragma(defn)@index(subst) @t(@i(to)) @t(@i(from)) @t(@i(expr)) @t(&key )@t(:test) @t(:test-not))} @c{[lisp]} @itemsep substitute expressions +@end(fgroup) +@begin(pdescription) + @i @itemsep the new expression + + @i @itemsep the old expression + + @i @itemsep the expression in which to do the substitutions + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the expression with substitutions + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{sublis(@i(alist), @i(expr), test: @i(test), test-not: @i(test-not))} @c{[sal]} + + @xlcode{(sublis@pragma(defn)@index(sublis) @t(@i(alist)) @t(@i(expr)) @t(&key )@t(:test) @t(:test-not))} @c{[lisp]} @itemsep substitute with an a-list +@end(fgroup) +@begin(pdescription) + @i @itemsep the association list + + @i @itemsep the expression in which to do the substitutions + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the expression with substitutions + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Destructive List Functions)@index(Destructive List Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{rplaca(@i(list), @i(expr))} @c{[sal]} + + @xlcode{(rplaca@pragma(defn)@index(rplaca) @t(@i(list)) @t(@i(expr)))} @c{[lisp]} @itemsep replace the car of a list node +@end(fgroup) +@begin(pdescription) + @i @itemsep the list node + + @i @itemsep the new value for the car of the list node + + returns @itemsep the list node after updating the car + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{rplacd(@i(list), @i(expr))} @c{[sal]} + + @xlcode{(rplacd@pragma(defn)@index(rplacd) @t(@i(list)) @t(@i(expr)))} @c{[lisp]} @itemsep replace the cdr of a list node +@end(fgroup) +@begin(pdescription) + @i @itemsep the list node + + @i @itemsep the new value for the cdr of the list node + + returns @itemsep the list node after updating the cdr + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{nconc(@i(list)@r(...))} @c{[sal]} + + @xlcode{(nconc@pragma(defn)@index(nconc) @t(@i(list))@r(...))} @c{[lisp]} @itemsep destructively concatenate lists +@end(fgroup) +@begin(pdescription) + @i @itemsep lists to concatenate + + returns @itemsep the result of concatenating the lists + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{delete(@i(expr), test: @i(test), test-not: @i(test-not))} @c{[sal]} + + @xlcode{(delete@pragma(defn)@index(delete) @t(@i(expr)) @t(&key )@t(:test) @t(:test-not))} @c{[lisp]} @itemsep delete elements from a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the element to delete + + @i @itemsep the list + + :test @itemsep the test function (defaults to eql) + + :test-not @itemsep the test function (sense inverted) + + returns @itemsep the list with the matching expressions deleted + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{delete-if(@i(test), @i(list))} @c{[sal]} + + @xlcode{(delete-if@pragma(defn)@index(delete-if) @t(@i(test)) @t(@i(list)))} @c{[lisp]} @itemsep delete elements that pass test +@end(fgroup) +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep the list with matching elements deleted + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{delete-if-not(@i(test), @i(list))} @c{[sal]} + + @xlcode{(delete-if-not@pragma(defn)@index(delete-if-not) @t(@i(test)) @t(@i(list)))} @c{[lisp]} @itemsep delete elements that fail test +@end(fgroup) +@begin(pdescription) + @i @itemsep the test predicate + + @i @itemsep the list + + returns @itemsep the list with non-matching elements deleted + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{sort(@i(list), @i(test))} @c{[sal]} + + @xlcode{(sort@pragma(defn)@index(sort) @t(@i(list)) @t(@i(test)))} @c{[lisp]} @itemsep sort a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the list to sort + + @i @itemsep the comparison function + + returns @itemsep the sorted list + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Predicate Functions)@index(Predicate Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{atom(@i(expr))} @c{[sal]} + + @xlcode{(atom@pragma(defn)@index(atom) @t(@i(expr)))} @c{[lisp]} @itemsep is this an atom? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an atom, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{symbolp(@i(expr))} @c{[sal]} + + @xlcode{(symbolp@pragma(defn)@index(symbolp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a symbol? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the expression is a symbol, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{numberp(@i(expr))} @c{[sal]} + + @xlcode{(numberp@pragma(defn)@index(numberp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a number? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the expression is a number, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{null(@i(expr))} @c{[sal]} + + @xlcode{(null@pragma(defn)@index(null) @t(@i(expr)))} @c{[lisp]} @itemsep is this an empty list? +@end(fgroup) +@begin(pdescription) + @i @itemsep the list to check + + returns @itemsep @xlcode(t) if the list is empty, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{not(@i(expr))} @c{[sal]} + + @xlcode{(not@pragma(defn)@index(not) @t(@i(expr)))} @c{[lisp]} @itemsep is this false? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + return @itemsep @xlcode(t) if the value is @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{listp(@i(expr))} @c{[sal]} + + @xlcode{(listp@pragma(defn)@index(listp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a list? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a cons or @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{endp(@i(list))} @c{[sal]} + + @xlcode{(endp@pragma(defn)@index(endp) @t(@i(list)))} @c{[lisp]} @itemsep is this the end of a list +@end(fgroup) +@begin(pdescription) + @i @itemsep the list + + returns @itemsep @xlcode(t) if the value is @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{consp(@i(expr))} @c{[sal]} + + @xlcode{(consp@pragma(defn)@index(consp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a non-empty list? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a cons, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{integerp(@i(expr))} @c{[sal]} + + @xlcode{(integerp@pragma(defn)@index(integerp) @t(@i(expr)))} @c{[lisp]} @itemsep is this an integer? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an integer, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{floatp(@i(expr))} @c{[sal]} + + @xlcode{(floatp@pragma(defn)@index(floatp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a float? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a float, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{stringp(@i(expr))} @c{[sal]} + + @xlcode{(stringp@pragma(defn)@index(stringp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a string? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a string, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{characterp(@i(expr))} @c{[sal]} + + @xlcode{(characterp@pragma(defn)@index(characterp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a character? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a character, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{arrayp(@i(expr))} @c{[sal]} + + @xlcode{(arrayp@pragma(defn)@index(arrayp) @t(@i(expr)))} @c{[lisp]} @itemsep is this an array? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an array, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{streamp(@i(expr))} @c{[sal]} + + @xlcode{(streamp@pragma(defn)@index(streamp) @t(@i(expr)))} @c{[lisp]} @itemsep is this a stream? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is a stream, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{objectp(@i(expr))} @c{[sal]} + + @xlcode{(objectp@pragma(defn)@index(objectp) @t(@i(expr)))} @c{[lisp]} @itemsep is this an object? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an object, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{filep(@i(expr))} @c{[sal]} + + @xlcode{(filep@pragma(defn)@index(filep) @t(@i(expr)))} @c{[lisp]}@foot(This is not part of standard XLISP nor is it built-in. Nyquist defines it though.) @itemsep is this a file? +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to check + + returns @itemsep @xlcode(t) if the value is an object, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{boundp(@i(sym))} @c{[sal]} + + @xlcode{(boundp@pragma(defn)@index(boundp) @t(@i(sym)))} @c{[lisp]} @itemsep is a value bound to this symbol? +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep @xlcode(t) if a value is bound to the symbol, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{fboundp(@i(sym))} @c{[sal]} + + @xlcode{(fboundp@pragma(defn)@index(fboundp) @t(@i(sym)))} @c{[lisp]} @itemsep is a functional value bound to this symbol? +@end(fgroup) +@begin(pdescription) + @i @itemsep the symbol + + returns @itemsep @xlcode(t) if a functional value is bound to the symbol, + + @xlcode(nil) otherwise +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{minusp(@i(expr))} @c{[sal]} + + @xlcode{(minusp@pragma(defn)@index(minusp) @t(@i(expr)))} @c{[lisp]} @itemsep is this number negative? +@end(fgroup) +@begin(pdescription) + @i @itemsep the number to test + + returns @itemsep @xlcode(t) if the number is negative, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{zerop(@i(expr))} @c{[sal]} + + @xlcode{(zerop@pragma(defn)@index(zerop) @t(@i(expr)))} @c{[lisp]} @itemsep is this number zero? +@end(fgroup) +@begin(pdescription) + @i @itemsep the number to test + + returns @itemsep @xlcode(t) if the number is zero, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{plusp(@i(expr))} @c{[sal]} + + @xlcode{(plusp@pragma(defn)@index(plusp) @t(@i(expr)))} @c{[lisp]} @itemsep is this number positive? +@end(fgroup) +@begin(pdescription) + @i @itemsep the number to test + + returns @itemsep @xlcode(t) if the number is positive, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{evenp(@i(expr))} @c{[sal]} + + @xlcode{(evenp@pragma(defn)@index(evenp) @t(@i(expr)))} @c{[lisp]} @itemsep is this integer even? +@end(fgroup) +@begin(pdescription) + @i @itemsep the integer to test + + returns @itemsep @xlcode(t) if the integer is even, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{oddp(@i(expr))} @c{[sal]} + + @xlcode{(oddp@pragma(defn)@index(oddp) @t(@i(expr)))} @c{[lisp]} @itemsep is this integer odd? +@end(fgroup) +@begin(pdescription) + @i @itemsep the integer to test + + returns @itemsep @xlcode(t) if the integer is odd, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{eq(@i(expr1), @i(expr2))} @c{[sal]} + + @xlcode{(eq@pragma(defn)@index(eq) @t(@i(expr1)) @t(@i(expr2)))} @c{[lisp]} @itemsep are the expressions identical? +@end(fgroup) +@begin(pdescription) + @i @itemsep the first expression + + @i @itemsep the second expression + + returns @itemsep @xlcode(t) if they are equal, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + +@begin(fgroup)@xlcode{eql(@i(expr1), @i(expr2))} @c{[sal]} + + @xlcode{(eql@pragma(defn)@index(eql) @t(@i(expr1)) @t(@i(expr2)))} @c{[lisp]} @itemsep are the expressions identical? (works with all numbers) +@end(fgroup) +@begin(pdescription) + @i @itemsep the first expression + + @i @itemsep the second expression + + returns @itemsep @xlcode(t) if they are equal, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{equal(@i(expr1), @i(expr2))} @c{[sal]} + + @xlcode{(equal@pragma(defn)@index(equal) @t(@i(expr1)) @t(@i(expr2)))} @c{[lisp]} @itemsep are the expressions equal? +@end(fgroup) +@begin(pdescription) + @i @itemsep the first expression + + @i @itemsep the second expression + + returns @itemsep @xlcode(t) if they are equal, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Control Constructs)@index(Control Constructs) +@begin(fdescription) + @xlcode{(cond@pragma(defn)@index(cond) @t(@i(pair))@r(...))} @c{[lisp]} @itemsep evaluate conditionally +@begin(pdescription) + @i @itemsep pair consisting of: + +@begin(pdescription) + (@i @i...) +@end(pdescription)@pragma(stopcodef) + where: +@begin(pdescription) + @i @itemsep is a predicate expression + + @i @itemsep evaluated if the predicate + is not @xlcode(nil) +@end(pdescription)@pragma(stopcodef) +returns @itemsep the value of the first expression whose predicate is not +@xlcode(nil) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{and(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(and@pragma(defn)@index(and) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the logical and of a list of expressions +@end(fgroup) +@begin(pdescription) + @i @itemsep the expressions to be anded + + returns @itemsep @xlcode(nil) if any expression evaluates to @xlcode(nil), + otherwise the value of the last expression + (evaluation of expressions stops after the first + expression that evaluates to @xlcode(nil)) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{or(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(or@pragma(defn)@index(or) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the logical or of a list of expressions +@end(fgroup) +@begin(pdescription) + @i @itemsep the expressions to be ored + + returns @itemsep @xlcode(nil) if all expressions evaluate to @xlcode(nil), + otherwise the value of the first non-@xlcode(nil) expression + (evaluation of expressions stops after the first + expression that does not evaluate to @xlcode(nil)) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{if(@i(texpr), @i(expr1)[, @i(expr2)])} @c{[sal]} + + @xlcode{(if@pragma(defn)@index(if) @t(@i(texpr)) @t(@i(expr1)) [@t(@i(expr2))])} @c{[lisp]} @itemsep evaluate expressions conditionally +@end(fgroup) +@begin(pdescription) + @i @itemsep the test expression + + @i @itemsep the expression to be evaluated if texpr is non-@xlcode(nil) + + @i @itemsep the expression to be evaluated if texpr is @xlcode(nil) + + returns @itemsep the value of the selected expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{when(@i(texpr), @i(expr)@r(...))} @c{[sal]} + + @xlcode{(when@pragma(defn)@index(when) @t(@i(texpr)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep evaluate only when a condition is true +@end(fgroup) +@begin(pdescription) + @i @itemsep the test expression + + @i @itemsep the expression(s) to be evaluated if texpr is non-@xlcode(nil) + + returns @itemsep the value of the last expression or @xlcode(nil) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{unless(@i(texpr), @i(expr)@r(...))} @c{[sal]} + + @xlcode{(unless@pragma(defn)@index(unless) @t(@i(texpr)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep evaluate only when a condition is false +@end(fgroup) +@begin(pdescription) + @i @itemsep the test expression + + @i @itemsep the expression(s) to be evaluated if texpr is @xlcode(nil) + + returns @itemsep the value of the last expression or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @xlcode{(case@pragma(defn)@index(case) @t(@i(expr)) @t(@i(case))@r(...))} @c{[lisp]} @itemsep select by case +@begin(pdescription) + @i @itemsep the selection expression + + @i @itemsep pair consisting of: + +@begin(pdescription) + (@i @i...) +@end(pdescription)@pragma(stopcodef) + where: +@begin(pdescription) + @i @itemsep is a single expression or a list of + expressions (unevaluated) + + @i @itemsep are expressions to execute if the + case matches +@end(pdescription)@pragma(stopcodef) + returns @itemsep the value of the last expression of the matching case + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + @xlcode{(let@pragma(defn)@index(let) (@t(@i(binding))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep create local bindings + +@pragma(startcodef) + @xlcode{(let*@pragma(defn)@index(let*) (@t(@i(binding))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep let with sequential binding +@end(fgroup) +@begin(pdescription) + @i @itemsep the variable bindings each of which is either: + +@begin(pdescription) + 1) a symbol (which is initialized to @xlcode(nil)) + + 2) a list whose car is a symbol and whose cadr + is an initialization expression +@end(pdescription)@pragma(stopcodef) + @i @itemsep the expressions to be evaluated + + returns @itemsep the value of the last expression + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + @xlcode{(flet@pragma(defn)@index(flet) (@t(@i(binding))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep create local functions + +@pragma(startcodef) + @xlcode{(labels@pragma(defn)@index(labels) (@t(@i(binding))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep flet with recursive functions + +@pragma(startcodef) + @xlcode{(macrolet@pragma(defn)@index(macrolet) (@t(@i(binding))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep create local macros +@end(fgroup) +@begin(pdescription) + @i @itemsep the function bindings each of which is: + +@begin(pdescription) + (@i @i @i...) +@end(pdescription)@pragma(stopcodef) + where: +@begin(pdescription) + @i @itemsep the function/macro name + + @i @itemsep formal argument list (lambda list) + + @i @itemsep expressions constituting the body of + the function/macro +@end(pdescription)@pragma(stopcodef) + @i @itemsep the expressions to be evaluated + + returns @itemsep the value of the last expression +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{catch(@i(sym), @i(expr)@r(...))} @c{[sal]} + + @xlcode{(catch@pragma(defn)@index(catch) @t(@i(sym)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep evaluate expressions and catch throws +@end(fgroup) +@begin(pdescription) + @i @itemsep the catch tag + + @i @itemsep expressions to evaluate + + returns @itemsep the value of the last expression the throw expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{throw(@i(sym)[, @i(expr)])} @c{[sal]} + + @xlcode{(throw@pragma(defn)@index(throw) @t(@i(sym)) [@t(@i(expr))])} @c{[lisp]} @itemsep throw to a catch +@end(fgroup) +@begin(pdescription) + @i @itemsep the catch tag + + @i @itemsep the value for the catch to return (defaults to @xlcode(nil)) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{unwind-protect(@i(expr), @i(cexpr)@r(...))} @c{[sal]} + + @xlcode{(unwind-protect@pragma(defn)@index(unwind-protect) @t(@i(expr)) @t(@i(cexpr))@r(...))} @c{[lisp]} @itemsep protect evaluation of an expression +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to protect + + @i @itemsep the cleanup expressions + + returns @itemsep the value of the expression@* + + Note: unwind-protect guarantees to execute the cleanup expressions + even if a non-local exit terminates the evaluation of the + protected expression +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Looping Constructs)@index(Looping Constructs) +@begin(fdescription) + @xlcode{(loop@pragma(defn)@index(loop) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep basic looping form +@begin(pdescription) + @i @itemsep the body of the loop + + returns @itemsep never returns (must use non-local exit) + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + @xlcode{(do@pragma(defn)@index(do) (@t(@i(binding))@r(...)) (@t(@i(texpr)) @t(@i(rexpr))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} +@pragma(endcodef) + @xlcode{(do*@pragma(defn)@index(do*) (@t(@i(binding))@r(...)) (@t(@i(texpr)) @t(@i(rexpr))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} +@end(fgroup) +@begin(pdescription) + @i @itemsep the variable bindings each of which is either: + +@begin(pdescription) + 1) a symbol (which is initialized to @xlcode(nil)) + + 2) a list of the form: (@i @i [@i]) + where: +@begin(pdescription) + @i @itemsep is the symbol to bind + + @i @itemsep is the initial value of the symbol + + @i @itemsep is a step expression + +@end(pdescription) +@end(pdescription)@pragma(stopcodef) + @i @itemsep the termination test expression + + @i @itemsep result expressions (the default is @xlcode(nil)) + + @i @itemsep the body of the loop (treated like an implicit prog) + + returns @itemsep the value of the last result expression + +@end(pdescription) +@blankspace(1) + + @xlcode{(dolist@pragma(defn)@index(dolist) (@t(@i(sym)) @t(@i(expr)) [@t(@i(rexpr))]) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep loop through a list +@begin(pdescription) + @i @itemsep the symbol to bind to each list element + + @i @itemsep the list expression + + @i @itemsep the result expression (the default is @xlcode(nil)) + + @i @itemsep the body of the loop (treated like an implicit prog) + +@end(pdescription) +@blankspace(1) + + @xlcode{(dotimes@pragma(defn)@index(dotimes) (@t(@i(sym)) @t(@i(expr)) [@t(@i(rexpr))]) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep loop from zero to n-1 +@begin(pdescription) + @i @itemsep the symbol to bind to each value from 0 to n-1 + + @i @itemsep the number of times to loop + + @i @itemsep the result expression (the default is @xlcode(nil)) + + @i @itemsep the body of the loop (treated like an implicit prog) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(The Program Feature)@index(The Program Feature) +@begin(fdescription) +@begin(fgroup) +@xlcode{(prog@pragma(defn)@index(prog) (@t(@i(binding))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the program feature + +@pragma(startcodef) +@xlcode{(prog*@pragma(defn)@index(prog*) (@t(@i(binding))@r(...)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep prog with sequential binding +@end(fgroup) +@begin(pdescription) + @i @itemsep the variable bindings each of which is either: + +@begin(pdescription) + 1) a symbol (which is initialized to @xlcode(nil)) + + 2) a list whose car is a symbol and whose cadr + is an initialization expression +@end(pdescription)@pragma(stopcodef) + @i @itemsep expressions to evaluate or tags (symbols) + + returns @itemsep @xlcode(nil) or the argument passed to the return function + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{block(@i(name), @i(expr)@r(...))} @c{[sal]} + + @xlcode{(block@pragma(defn)@index(block) @t(@i(name)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep named block +@end(fgroup) +@begin(pdescription) + @i @itemsep the block name (symbol) + + @i @itemsep the block body + + returns @itemsep the value of the last expression + +@end(pdescription) +@blankspace(1) + + @xlcode{(return@pragma(defn)@index(return) [@t(@i(expr))])} @c{[lisp]} @itemsep cause a prog construct to return a value +@begin(pdescription) + @i @itemsep the value (defaults to @xlcode(nil)) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{return-from(@i(name)[, @i(value)])} @c{[sal]} + + @xlcode{(return-from@pragma(defn)@index(return-from) @t(@i(name)) [@t(@i(value))])} @c{[lisp]} @itemsep return from a named block +@end(fgroup) +@begin(pdescription) + @i @itemsep the block name (symbol) + + @i @itemsep the value to return (defaults to @xlcode(nil)) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{tagbody(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(tagbody@pragma(defn)@index(tagbody) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep block with labels +@end(fgroup) +@begin(pdescription) + @i @itemsep expression(s) to evaluate or tags (symbols) + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{go(@i(sym))} @c{[sal]} + + @xlcode{(go@pragma(defn)@index(go) @t(@i(sym)))} @c{[lisp]} @itemsep go to a tag within a tagbody or prog +@end(fgroup) +@begin(pdescription) + @i @itemsep the tag (quoted) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @xlcode{(progv@pragma(defn)@index(progv) @t(@i(slist)) @t(@i(vlist)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep dynamically bind symbols +@begin(pdescription) + @i @itemsep list of symbols + + @i @itemsep list of values to bind to the symbols + + @i @itemsep expression(s) to evaluate + + returns @itemsep the value of the last expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{prog1(@i(expr1), @i(expr)@r(...))} @c{[sal]} + + @xlcode{(prog1@pragma(defn)@index(prog1) @t(@i(expr1)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep execute expressions sequentially +@end(fgroup) +@begin(pdescription) + @i @itemsep the first expression to evaluate + + @i @itemsep the remaining expressions to evaluate + + returns @itemsep the value of the first expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{prog2(@i(expr1), @i(expr2), @i(expr)@r(...))} @c{[sal]} + + @xlcode{(prog2@pragma(defn)@index(prog2) @t(@i(expr1)) @t(@i(expr2)) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep execute expressions sequentially +@end(fgroup) +@begin(pdescription) + @i @itemsep the first expression to evaluate + + @i @itemsep the second expression to evaluate + + @i @itemsep the remaining expressions to evaluate + + returns @itemsep the value of the second expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{progn(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(progn@pragma(defn)@index(progn) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep execute expressions sequentially +@end(fgroup) +@begin(pdescription) + @i @itemsep the expressions to evaluate + + returns @itemsep the value of the last expression (or @xlcode(nil)) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Debugging and Error Handling)@index(Debugging)@index(Error Handling) +@begin(fdescription) + @begin(fgroup)@xlcode{trace(@i(sym))} @c{[sal]} + + @xlcode{(trace@pragma(defn)@index(trace) @t(@i(sym)))} @c{[lisp]} @itemsep add a function to the trace list +@end(fgroup) +@begin(pdescription) + @i @itemsep the function to add (quoted) + + returns @itemsep the trace list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{untrace(@i(sym))} @c{[sal]} + + @xlcode{(untrace@pragma(defn)@index(untrace) @t(@i(sym)))} @c{[lisp]} @itemsep remove a function from the trace list +@end(fgroup) +@begin(pdescription) + @i @itemsep the function to remove (quoted) + + returns @itemsep the trace list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{error(@i(emsg)[, @i(arg)])} @c{[sal]} + + @xlcode{(error@pragma(defn)@index(error) @t(@i(emsg)) [@t(@i(arg))])} @c{[lisp]} @itemsep signal a non-correctable error +@end(fgroup) +@begin(pdescription) + @i @itemsep the error message string + + @i @itemsep the argument expression (printed after the message) + + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{cerror(@i(cmsg), @i(emsg)[, @i(arg)])} @c{[sal]} + + @xlcode{(cerror@pragma(defn)@index(cerror) @t(@i(cmsg)) @t(@i(emsg)) [@t(@i(arg))])} @c{[lisp]} @itemsep signal a correctable error +@end(fgroup) +@begin(pdescription) + @i @itemsep the continue message string + + @i @itemsep the error message string + + @i @itemsep the argument expression (printed after the message) + + returns @itemsep @xlcode(nil) when continued from the break loop + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{break([@i(bmsg)[, @i(arg)]])} @c{[sal]} + + @xlcode{(break@pragma(defn)@index(break) [@t(@i(bmsg)) [@t(@i(arg))]])} @c{[lisp]} @itemsep enter a break loop +@end(fgroup) +@begin(pdescription) + @i @itemsep the break message string (defaults to @xlcode(**break**)) + + @i @itemsep the argument expression (printed after the message) + + returns @itemsep @xlcode(nil) when continued from the break loop + +@end(pdescription) +@blankspace(1) + + @xlcode{(clean-up@pragma(defn)@index(clean-up))} @c{[lisp]} @itemsep clean-up after an error +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @xlcode{(top-level@pragma(defn)@index(top-level))} @c{[lisp]} @itemsep clean-up after an error and return to the top level +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @xlcode{(continue@pragma(defn)@index(continue))} @c{[lisp]} @itemsep continue from a correctable error +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @xlcode{(errset@pragma(defn)@index(errset) @t(@i(expr)) [@t(@i(pflag))])} @c{[lisp]} @itemsep trap errors +@begin(pdescription) + @i @itemsep the expression to execute + + @i @itemsep flag to control printing of the error message + + returns @itemsep the value of the last expression consed with @xlcode(nil) + + or @xlcode(nil) on error +@end(pdescription) +@blankspace(1) + + @xlcode{(baktrace@pragma(defn)@index(baktrace)@index(debugging)@index(stack trace) [@t(@i(n))])} @c{[lisp]} @itemsep print n levels of trace back information +@begin(pdescription) + @i @itemsep the number of levels (defaults to all levels) + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @xlcode{(evalhook@pragma(defn)@index(evalhook) @t(@i(expr)) @t(@i(ehook)) @t(@i(ahook)) [@t(@i(env))])} @c{[lisp]} @itemsep evaluate with hooks +@begin(pdescription) + @i @itemsep the expression to evaluate + + @i @itemsep the value for @xlcode(*evalhook*) + + @i @itemsep the value for @xlcode(*applyhook*) + + @i @itemsep the environment (default is @xlcode(nil)) + + returns @itemsep the result of evaluating the expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{profile(@i(flag))} @c{[sal]} + + @xlcode{(profile@pragma(defn)@index(profile) @t(@i(flag)))} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep turn profiling on or off. +@end(fgroup) +@begin(pdescription) + @i @itemsep @xlcode(nil) turns profiling off, otherwise on + + returns @itemsep the previous state of profiling. + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Arithmetic Functions)@index(Arithmetic Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{truncate(@i(expr))} @c{[sal]} + + @xlcode{(truncate@pragma(defn)@index(truncate) @t(@i(expr)))} @c{[lisp]} @itemsep truncates a floating point number to an integer +@end(fgroup) +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the result of truncating the number + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{float(@i(expr))} @c{[sal]} + + @xlcode{(float@pragma(defn)@index(float) @t(@i(expr)))} @c{[lisp]} @itemsep converts an integer to a floating point number +@end(fgroup) +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the result of floating the integer + +@end(pdescription) +@blankspace(1) + + @xlcode{(+@pragma(defn)@index(+) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep add a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the addition + +@end(pdescription) +@blankspace(1) + + @xlcode{(-@pragma(defn)@index(-) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep subtract a list of numbers or negate a single number +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the subtraction + +@end(pdescription) +@blankspace(1) + + @xlcode{(*@pragma(defn)@index(*) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep multiply a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the multiplication + +@end(pdescription) +@blankspace(1) + + @xlcode{(/@pragma(defn)@index(/) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep divide a list of numbers +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the division + +@end(pdescription) +@blankspace(1) + + @xlcode{(1+@pragma(defn)@index(1+) @t(@i(expr)))} @c{[lisp]} @itemsep add one to a number +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the number plus one + +@end(pdescription) +@blankspace(1) + + @xlcode{(1-@pragma(defn)@index(1-) @t(@i(expr)))} @c{[lisp]} @itemsep subtract one from a number +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the number minus one + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{rem(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(rem@pragma(defn)@index(rem)@index(remainder)@index(modulo (rem) function) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep remainder of a list of numbers +@end(fgroup) +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the remainder operation + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{min(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(min@pragma(defn)@index(min)@index(minimum) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the smallest of a list of numbers +@end(fgroup) +@begin(pdescription) + @i @itemsep the expressions to be checked + + returns @itemsep the smallest number in the list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{max(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(max@pragma(defn)@index(max)@index(maximum) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the largest of a list of numbers +@end(fgroup) +@begin(pdescription) + @i @itemsep the expressions to be checked + + returns @itemsep the largest number in the list + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{abs(@i(expr))} @c{[sal]} + + @xlcode{(abs@pragma(defn)@index(abs) @t(@i(expr)))} @c{[lisp]} @itemsep the absolute value of a number +@end(fgroup) +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the absolute value of the number + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{gcd(@i(n1), @i(n2)@r(...))} @c{[sal]} + + @xlcode{(gcd@pragma(defn)@index(gcd) @t(@i(n1)) @t(@i(n2))@r(...))} @c{[lisp]} @itemsep compute the greatest common divisor +@end(fgroup) +@begin(pdescription) + @i @itemsep the first number (integer) + + @i @itemsep the second number(s) (integer) + + returns @itemsep the greatest common divisor + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{random(@i(n))} @c{[sal]} + + @xlcode{(random@pragma(defn)@index(random) @t(@i(n)))} @c{[lisp]} @itemsep compute a random number between 0 and n-1 inclusive +@end(fgroup) +@begin(pdescription) + @i @itemsep the upper bound (integer) + + returns @itemsep a random number + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{rrandom()} @c{[sal]} + + @xlcode{(rrandom@pragma(defn)@index(rrandom)@index(uniform random))} @c{[lisp]} @itemsep compute a random real number between 0 and 1 inclusive +@end(fgroup) +@begin(pdescription) + returns @itemsep a random floating point number + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{sin(@i(expr))} @c{[sal]} + + @xlcode{(sin@pragma(defn)@index(sin) @t(@i(expr)))} @c{[lisp]} @itemsep compute the sine of a number +@end(fgroup) +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the sine of the number + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{cos(@i(expr))} @c{[sal]} + + @xlcode{(cos@pragma(defn)@index(cos) @t(@i(expr)))} @c{[lisp]} @itemsep compute the cosine of a number +@end(fgroup) +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the cosine of the number + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{tan(@i(expr))} @c{[sal]} + + @xlcode{(tan@pragma(defn)@index(tan) @t(@i(expr)))} @c{[lisp]} @itemsep compute the tangent of a number +@end(fgroup) +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the tangent of the number + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{atan(@i(expr)[, @i(expr2)])} @c{[sal]} + + @xlcode{(atan@pragma(defn)@index(atan) @t(@i(expr)) [@t(@i(expr2))])} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep compute the arctangent +@end(fgroup) +@begin(pdescription) + @i @itemsep the value of @i(x) + + @i @itemsep the value of @i(y) (default value is 1.0) + + returns @itemsep the arctangent of @i(x)/@i(y) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{expt(@i(x-expr), @i(y-expr))} @c{[sal]} + + @xlcode{(expt@pragma(defn)@index(expt) @t(@i(x-expr)) @t(@i(y-expr)))} @c{[lisp]} @itemsep compute x to the y power +@end(fgroup) +@begin(pdescription) + @i @itemsep the floating point number + + @i @itemsep the floating point exponent + + returns @itemsep x to the y power + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{exp(@i(x-expr))} @c{[sal]} + + @xlcode{(exp@pragma(defn)@index(exp) @t(@i(x-expr)))} @c{[lisp]} @itemsep compute e to the x power +@end(fgroup) +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep e to the x power + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{sqrt(@i(expr))} @c{[sal]} + + @xlcode{(sqrt@pragma(defn)@index(sqrt) @t(@i(expr)))} @c{[lisp]} @itemsep compute the square root of a number +@end(fgroup) +@begin(pdescription) + @i @itemsep the floating point number + + returns @itemsep the square root of the number + +@end(pdescription) +@blankspace(1) +@begin(fgroup) +@xlcode{(<@pragma(defn)@index(<) @t(@i(n1)) @t(@i(n2))@r(...))} @c{[lisp]} @itemsep test for less than + +@xlcode{(<=@pragma(defn)@index(<=) @t(@i(n1)) @t(@i(n2))@r(...))} @c{[lisp]} @itemsep test for less than or equal to + +@xlcode{(=@pragma(defn)@index(=) @t(@i(n1)) @t(@i(n2))@r(...))} @c{[lisp]} @itemsep test for equal to + +@xlcode{(/=@pragma(defn)@index(/=) @t(@i(n1)) @t(@i(n2))@r(...))} @c{[lisp]} @itemsep test for not equal to + +@xlcode{(>=@pragma(defn)@index(>=) @t(@i(n1)) @t(@i(n2))@r(...))} @c{[lisp]} @itemsep test for greater than or equal to + +@xlcode{(>@pragma(defn)@index(>) @t(@i(n1)) @t(@i(n2))@r(...))} @c{[lisp]} @itemsep test for greater than +@end(fgroup) +@begin(pdescription) + @i @itemsep the first number to compare + + @i @itemsep the second number to compare + +returns @itemsep @xlcode(t) if the results of comparing @i with @i, +@i with @i, etc., are all true. + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Bitwise Logical Functions)@index(Bitwise Logical Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{logand(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(logand@pragma(defn)@index(logand) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the bitwise and of a list of numbers +@end(fgroup) +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the and operation + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{logior(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(logior@pragma(defn)@index(logior) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the bitwise inclusive or of a list of numbers +@end(fgroup) +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the inclusive or operation + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{logxor(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(logxor@pragma(defn)@index(logxor) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep the bitwise exclusive or of a list of numbers +@end(fgroup) +@begin(pdescription) + @i @itemsep the numbers + + returns @itemsep the result of the exclusive or operation + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{lognot(@i(expr))} @c{[sal]} + + @xlcode{(lognot@pragma(defn)@index(lognot) @t(@i(expr)))} @c{[lisp]} @itemsep the bitwise not of a number +@end(fgroup) +@begin(pdescription) + @i @itemsep the number + + returns @itemsep the bitwise inversion of number + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(String Functions)@index(String Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{string(@i(expr))} @c{[sal]} + + @xlcode{(string@pragma(defn)@index(string) @t(@i(expr)))} @c{[lisp]} @itemsep make a string from a value +@end(fgroup) +@begin(pdescription) + @i @itemsep an integer (which is first converted into its ASCII character value), string, character, or symbol + + returns @itemsep the string representation of the argument + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{string-search(@i(pat), @i(str), start: @i(start), end: @i(end))} @c{[sal]} + + @xlcode{(string-search@pragma(defn)@index(string-search)@index(find string) @t(@i(pat)) @t(@i(str)) @t(&key )@t(:start) @t(:end))} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep search for pattern in string +@end(fgroup) +@begin(pdescription) + @i @itemsep a string to search for + + @i @itemsep the string to be searched + + :start @itemsep the starting offset in str + + :end @itemsep the ending offset + 1 + + returns @itemsep index of pat in str or NIL if not found + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{string-trim(@i(bag), @i(str))} @c{[sal]} + + @xlcode{(string-trim@pragma(defn)@index(string-trim) @t(@i(bag)) @t(@i(str)))} @c{[lisp]} @itemsep trim both ends of a string +@end(fgroup) +@begin(pdescription) + @i @itemsep a string containing characters to trim + + @i @itemsep the string to trim + + returns @itemsep a trimed copy of the string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{string-left-trim(@i(bag), @i(str))} @c{[sal]} + + @xlcode{(string-left-trim@pragma(defn)@index(string-left-trim) @t(@i(bag)) @t(@i(str)))} @c{[lisp]} @itemsep trim the left end of a string +@end(fgroup) +@begin(pdescription) + @i @itemsep a string containing characters to trim + + @i @itemsep the string to trim + + returns @itemsep a trimed copy of the string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{string-right-trim(@i(bag), @i(str))} @c{[sal]} + + @xlcode{(string-right-trim@pragma(defn)@index(string-right-trim) @t(@i(bag)) @t(@i(str)))} @c{[lisp]} @itemsep trim the right end of a string +@end(fgroup) +@begin(pdescription) + @i @itemsep a string containing characters to trim + + @i @itemsep the string to trim + + returns @itemsep a trimed copy of the string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{string-upcase(@i(str), start: @i(start), end: @i(end))} @c{[sal]} + + @xlcode{(string-upcase@pragma(defn)@index(string-upcase) @t(@i(str)) @t(&key )@t(:start) @t(:end))} @c{[lisp]} @itemsep convert to uppercase +@end(fgroup) +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep a converted copy of the string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{string-downcase(@i(str), start: @i(start), end: @i(end))} @c{[sal]} + + @xlcode{(string-downcase@pragma(defn)@index(string-downcase) @t(@i(str)) @t(&key )@t(:start) @t(:end))} @c{[lisp]} @itemsep convert to lowercase +@end(fgroup) +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep a converted copy of the string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{nstring-upcase(@i(str), start: @i(start), end: @i(end))} @c{[sal]} + + @xlcode{(nstring-upcase@pragma(defn)@index(nstring-upcase) @t(@i(str)) @t(&key )@t(:start) @t(:end))} @c{[lisp]} @itemsep convert to uppercase +@end(fgroup) +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep the converted string (not a copy) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{nstring-downcase(@i(str), start: @i(start), end: @i(end))} @c{[sal]} + + @xlcode{(nstring-downcase@pragma(defn)@index(nstring-downcase) @t(@i(str)) @t(&key )@t(:start) @t(:end))} @c{[lisp]} @itemsep convert to lowercase +@end(fgroup) +@begin(pdescription) + @i @itemsep the string + + :start @itemsep the starting offset + + :end @itemsep the ending offset + 1 + + returns @itemsep the converted string (not a copy) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{strcat(@i(expr)@r(...))} @c{[sal]} + + @xlcode{(strcat@pragma(defn)@index(strcat)@index(concatenate strings) @t(@i(expr))@r(...))} @c{[lisp]} @itemsep concatenate strings +@end(fgroup) +@begin(pdescription) + @i @itemsep the strings to concatenate + + returns @itemsep the result of concatenating the strings + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{subseq(@i(string), @i(start)[, @i(end)])} @c{[sal]} + + @xlcode{(subseq@pragma(defn)@index(subseq) @t(@i(string)) @t(@i(start)) [@t(@i(end))])} @c{[lisp]} @itemsep extract a substring +@end(fgroup) +@begin(pdescription) + @i @itemsep the string + + @i @itemsep the starting position (zero origin) + + @i @itemsep the ending position + 1 (defaults to end) + + returns @itemsep substring between @i and @i + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + @begin(fgroup)@xlcode{string<(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string<@pragma(defn)@index(string<) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + @begin(fgroup)@xlcode{string<=(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string<=@pragma(defn)@index(string<=) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{string=(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string=@pragma(defn)@index(string=) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{string/=(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string/=@pragma(defn)@index(string/=) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{string>=(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string>=@pragma(defn)@index(string>=) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{string>(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string>@pragma(defn)@index(string>) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@end(fgroup) +@begin(pdescription) + @i @itemsep the first string to compare + + @i @itemsep the second string to compare + + :start1 @itemsep first substring starting offset + + :end1 @itemsep first substring ending offset + 1 + + :start2 @itemsep second substring starting offset + + :end2 @itemsep second substring ending offset + 1 + + returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@begin(fgroup) +@begin(fgroup)@xlcode{string-lessp(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string-lessp@pragma(defn)@index(string-lessp) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{string-not-greaterp(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string-not-greaterp@pragma(defn)@index(string-not-greaterp) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{string-equalp(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string-equalp@pragma(defn)@index(string-equalp) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{string-not-equalp(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string-not-equalp@pragma(defn)@index(string-not-equalp) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{string-not-lessp(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string-not-lessp@pragma(defn)@index(string-not-lessp) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{string-greaterp(@i(str1), @i(str2), start1: @i(start1), end1: @i(end1), start2: @i(start2), end2: @i(end2))} @c{[sal]} + + @xlcode{(string-greaterp@pragma(defn)@index(string-greaterp) @t(@i(str1)) @t(@i(str2)) @t(&key )@t(:start1) @t(:end1) @t(:start2) @t(:end2))} @c{[lisp]} +@end(fgroup) +@end(fgroup) +@begin(pdescription) + @i @itemsep the first string to compare + + @i @itemsep the second string to compare + + :start1 @itemsep first substring starting offset + + :end1 @itemsep first substring ending offset + 1 + + :start2 @itemsep second substring starting offset + + :end2 @itemsep second substring ending offset + 1 + + returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is not significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Character Functions)@index(Character Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{char(@i(string), @i(index))} @c{[sal]} + + @xlcode{(char@pragma(defn)@index(char) @t(@i(string)) @t(@i(index)))} @c{[lisp]} @itemsep extract a character from a string +@end(fgroup) +@begin(pdescription) + @i @itemsep the string + + @i @itemsep the string index (zero relative) + + returns @itemsep the ascii code of the character + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{upper-case-p(@i(chr))} @c{[sal]} + + @xlcode{(upper-case-p@pragma(defn)@index(upper-case-p) @t(@i(chr)))} @c{[lisp]} @itemsep is this an upper case character? +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep @xlcode(t) if the character is upper case, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{lower-case-p(@i(chr))} @c{[sal]} + + @xlcode{(lower-case-p@pragma(defn)@index(lower-case-p) @t(@i(chr)))} @c{[lisp]} @itemsep is this a lower case character? +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep @xlcode(t) if the character is lower case, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{both-case-p(@i(chr))} @c{[sal]} + + @xlcode{(both-case-p@pragma(defn)@index(both-case-p) @t(@i(chr)))} @c{[lisp]} @itemsep is this an alphabetic (either case) character? +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep @xlcode(t) if the character is alphabetic, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{digit-char-p(@i(chr))} @c{[sal]} + + @xlcode{(digit-char-p@pragma(defn)@index(digit-char-p) @t(@i(chr)))} @c{[lisp]} @itemsep is this a digit character? +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the digit weight if character is a digit, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{char-code(@i(chr))} @c{[sal]} + + @xlcode{(char-code@pragma(defn)@index(char-code) @t(@i(chr)))} @c{[lisp]} @itemsep get the ascii code of a character +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the ascii character code (integer) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{code-char(@i(code))} @c{[sal]} + + @xlcode{(code-char@pragma(defn)@index(code-char) @t(@i(code)))} @c{[lisp]} @itemsep get the character with a specified ascii code +@end(fgroup) +@begin(pdescription) + @i @itemsep the ascii code (integer) + + returns @itemsep the character with that code or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{char-upcase(@i(chr))} @c{[sal]} + + @xlcode{(char-upcase@pragma(defn)@index(char-upcase) @t(@i(chr)))} @c{[lisp]} @itemsep convert a character to upper case +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the upper case character + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{char-downcase(@i(chr))} @c{[sal]} + + @xlcode{(char-downcase@pragma(defn)@index(char-downcase) @t(@i(chr)))} @c{[lisp]} @itemsep convert a character to lower case +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the lower case character + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{digit-char(@i(n))} @c{[sal]} + + @xlcode{(digit-char@pragma(defn)@index(digit-char) @t(@i(n)))} @c{[lisp]} @itemsep convert a digit weight to a digit +@end(fgroup) +@begin(pdescription) + @i @itemsep the digit weight (integer) + + returns @itemsep the digit character or @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{char-int(@i(chr))} @c{[sal]} + + @xlcode{(char-int@pragma(defn)@index(char-int) @t(@i(chr)))} @c{[lisp]} @itemsep convert a character to an integer +@end(fgroup) +@begin(pdescription) + @i @itemsep the character + + returns @itemsep the ascii character code + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{int-char(@i(int))} @c{[sal]} + + @xlcode{(int-char@pragma(defn)@index(int-char) @t(@i(int)))} @c{[lisp]} @itemsep convert an integer to a character +@end(fgroup) +@begin(pdescription) + @i @itemsep the ascii character code + + returns @itemsep the character with that code + +@end(pdescription) +@blankspace(1) +@begin(fgroup) + @begin(fgroup)@xlcode{char<(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char<@pragma(defn)@index(char<) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{char<=(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char<=@pragma(defn)@index(char<=) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{char=(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char=@pragma(defn)@index(char=) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{char/=(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char/=@pragma(defn)@index(char/=) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{char>=(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char>=@pragma(defn)@index(char>=) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + + @begin(fgroup)@xlcode{char>(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char>@pragma(defn)@index(char>) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@end(fgroup) +@begin(pdescription) + @i @itemsep the first character to compare + + @i @itemsep the second character(s) to compare + + returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@begin(fgroup) +@begin(fgroup)@xlcode{char-lessp(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char-lessp@pragma(defn)@index(char-lessp) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{char-not-greaterp(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char-not-greaterp@pragma(defn)@index(char-not-greaterp) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{char-equalp(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char-equalp@pragma(defn)@index(char-equalp) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{char-not-equalp(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char-not-equalp@pragma(defn)@index(char-not-equalp) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{char-not-lessp(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char-not-lessp@pragma(defn)@index(char-not-lessp) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@pragma(endcodef) + +@begin(fgroup)@xlcode{char-greaterp(@i(chr1), @i(chr2)@r(...))} @c{[sal]} + + @xlcode{(char-greaterp@pragma(defn)@index(char-greaterp) @t(@i(chr1)) @t(@i(chr2))@r(...))} @c{[lisp]} +@end(fgroup) +@end(fgroup) +@begin(pdescription) +@i @itemsep the first string to compare + +@i @itemsep the second string(s) to compare + +returns @itemsep @xlcode(t) if predicate is true, @xlcode(nil) otherwise + + Note: case is not significant with these comparison functions. +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(Input/Output Functions)@index(Input/Output Functions) +@begin(fdescription) + @begin(fgroup)@xlcode{read([@i(stream)[, @i(eof)[, @i(rflag)]]])} @c{[sal]} + + @xlcode{(read@pragma(defn)@index(read) [@t(@i(stream)) [@t(@i(eof)) [@t(@i(rflag))]]])} @c{[lisp]} @itemsep read an expression +@end(fgroup) +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + @i @itemsep the value to return on end of file (default is @xlcode(nil)) + + @i @itemsep recursive read flag (default is @xlcode(nil)) + + returns @itemsep the expression read + +@end(pdescription) +@blankspace(1) + + @xlcode{(print@pragma(defn)@index(print) @t(@i(expr)) [@t(@i(stream))])} @c{[lisp]} @itemsep print an expression on a new line +@begin(pdescription) + @i @itemsep the expression to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{prin1(@i(expr)[, @i(stream)])} @c{[sal]} + + @xlcode{(prin1@pragma(defn)@index(prin1) @t(@i(expr)) [@t(@i(stream))])} @c{[lisp]} @itemsep print an expression +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{princ(@i(expr)[, @i(stream)])} @c{[sal]} + + @xlcode{(princ@pragma(defn)@index(princ) @t(@i(expr)) [@t(@i(stream))])} @c{[lisp]} @itemsep print an expression without quoting +@end(fgroup) +@begin(pdescription) + @i @itemsep the expressions to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{pprint(@i(expr)[, @i(stream)])} @c{[sal]} + + @xlcode{(pprint@pragma(defn)@index(pprint) @t(@i(expr)) [@t(@i(stream))])} @c{[lisp]} @itemsep pretty print an expression +@end(fgroup) +@begin(pdescription) + @i @itemsep the expressions to be printed + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the expression + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{terpri([@i(stream)])} @c{[sal]} + + @xlcode{(terpri@pragma(defn)@index(terpri) [@t(@i(stream))])} @c{[lisp]} @itemsep terminate the current print line +@end(fgroup) +@begin(pdescription) + @i @itemsep the output stream (default is standard output) + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{flatsize(@i(expr))} @c{[sal]} + + @xlcode{(flatsize@pragma(defn)@index(flatsize) @t(@i(expr)))} @c{[lisp]} @itemsep length of printed representation using prin1 +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression + + returns @itemsep the length + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{flatc(@i(expr))} @c{[sal]} + + @xlcode{(flatc@pragma(defn)@index(flatc) @t(@i(expr)))} @c{[lisp]} @itemsep length of printed representation using princ +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression + + returns @itemsep the length +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(The Format Function)@index(The Format Function) +@begin(fdescription) +@begin(fgroup)@xlcode{format(@i(stream), @i(fmt), @i(arg)@r(...))} @c{[sal]} + + @xlcode{(format@pragma(defn)@index(format) @t(@i(stream)) @t(@i(fmt)) @t(@i(arg))@r(...))} @c{[lisp]} @itemsep do formated +@end(fgroup) +output +@begin(pdescription) + @i @itemsep the output stream + + @i @itemsep the format string + + @i @itemsep the format arguments + + returns @itemsep output string if @i is @xlcode(nil), @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) +@end(fdescription) + The format string can contain characters that should be copied + directly to the output and formatting directives. The + formatting directives are: +@begin(display) +@xlcode(~A) @itemsep print next argument using princ +@xlcode(~S) @itemsep print next argument using prin1 +@xlcode(~%) @itemsep start a new line +@xlcode(~~) @itemsep print a tilde character +@xlcode(~) @itemsep ignore this one newline and white space on the +next line up to the first non-white-space character or newline. This +allows strings to continue across multiple lines +@end(display) + +@section(File I/O Functions)@index(File I/O Functions) +Note that files are ordinarily opened as text. Binary files (such as standard midi files) must be opened with @xlcode(open-binary) on non-unix systems. +@begin(fdescription) + @begin(fgroup)@xlcode{open(@i(fname), direction: @i(direction))} @c{[sal]} + + @xlcode{(open@pragma(defn)@index(open) @t(@i(fname)) @t(&key )@t(:direction))} @c{[lisp]} @itemsep open a file stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the file name string or symbol + + :direction @itemsep :input or :output (default is :input) + + returns @itemsep a stream + +@end(pdescription) +@blankspace(1) + @begin(fgroup)@xlcode{open-binary(@i(fname), direction: @i(direction))} @c{[sal]} + + @xlcode{(open-binary@pragma(defn)@index(open-binary)@index(open)@index(binary files) @t(@i(fname)) @t(&key )@t(:direction))} @c{[lisp]} @itemsep open a binary file stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the file name string or symbol + + :direction @itemsep :input or :output (default is :input) + + returns @itemsep a stream + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{close(@i(stream))} @c{[sal]} + + @xlcode{(close@pragma(defn)@index(close) @t(@i(stream)))} @c{[lisp]} @itemsep close a file stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the stream + + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{setdir(@i(path)[, @i(verbose)])} @c{[sal]} + + @xlcode{(setdir@pragma(defn)@index(setdir)@index(change directory) @t(@i(path)) [@t(@i(verbose))])} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep set current directory +@end(fgroup) +@begin(pdescription) + @i @itemsep the path of the new directory + + @i @itemsep print error message if current directory cannot be changed to @i(path) + + returns @itemsep the resulting full path, e.g. (setdir ".") gets the current working directory, or @xlcode(nil) if an error occurs + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{listdir(@i(path))} @c{[sal]} + + @xlcode{(listdir@pragma(defn)@index(listdir)@index(directory listing)@index(scan directory)@index(read directory)@index(list directory) @t(@i(path)))} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep get a directory listing +@end(fgroup) +@begin(pdescription) + @i @itemsep the path of the directory to be listed + + returns @itemsep list of filenames in the directory + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{get-temp-path()} @c{[sal]} + + @xlcode{(get-temp-path@pragma(defn)@index(get-temp-path)@index(temporary files)@index(temp file))} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep get a path where a temporary file can be created. Under Windows, this is based on environment variables. If XLISP is running as a sub-process to Java, the environment may not exist, in which case the default result is the unfortunate choice @xlcode(c:\windows\). +@end(fgroup) +@begin(pdescription) + returns @itemsep the resulting full path as a string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{get-user()} @c{[sal]} + + @xlcode{(get-user@pragma(defn)@index(get-user)@index(user name)@index(temp file))} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep get the user ID. In Unix systems (including OS X and Linux), this is the value of the USER environment variable. In Windows, this is currently just ``nyquist'', which is also returned if the environment variable cannot be accessed. This function is used to avoid the case of two users creating files of the same name in the same temp directory. +@end(fgroup) +@begin(pdescription) + returns @itemsep the string naming the user + +@end(pdescription) +@blankspace(1) + @begin(fgroup)@xlcode{find-in-xlisp-path(@i(filename))} @c{[sal]} + + @xlcode{(find-in-xlisp-path@pragma(defn)@index(find-in-xlisp-path) @t(@i(filename)))} @c{[lisp]}@foot(This is not a standard XLISP 2.0 function.) @itemsep search the XLISP search path (e.g. @xlcode(XLISPPATH) from the environment) for @i(filename). If @i(filename) is not found as is, and there is no file extension, append "@code(.lsp)" to @i(filename) and search again. The current directory is not searched. +@end(fgroup) +@begin(pdescription) + @i @itemsep the name of the file to search for + + returns @itemsep a full path name to the first occurrence found + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{read-char([@i(stream)])} @c{[sal]} + + @xlcode{(read-char@pragma(defn)@index(read-char)@index(get char) [@t(@i(stream))])} @c{[lisp]} @itemsep read a character from a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + returns @itemsep the character + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{peek-char([@i(flag)[, @i(stream)]])} @c{[sal]} + + @xlcode{(peek-char@pragma(defn)@index(peek-char) [@t(@i(flag)) [@t(@i(stream))]])} @c{[lisp]} @itemsep peek at the next character +@end(fgroup) +@begin(pdescription) + @i @itemsep flag for skipping white space (default is @xlcode(nil)) + + @i @itemsep the input stream (default is standard input) + + returns @itemsep the character (integer) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{write-char(@i(ch)[, @i(stream)])} @c{[sal]} + + @xlcode{(write-char@pragma(defn)@index(write-char) @t(@i(ch)) [@t(@i(stream))])} @c{[lisp]} @itemsep write a character to a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the character to write + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the character + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{read-int([@i(stream)[, @i(length)]])} @c{[sal]} + + @xlcode{(read-int@pragma(defn)@index(read-int) [@t(@i(stream)) [@t(@i(length))]])} @c{[lisp]} @itemsep read a binary integer from a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + @i @itemsep the length of the integer in bytes (default is 4) + + returns @itemsep the integer + +Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{write-int(@i(ch)[, @i(stream)[, @i(length)]])} @c{[sal]} + + @xlcode{(write-int@pragma(defn)@index(write-int) @t(@i(ch)) [@t(@i(stream)) [@t(@i(length))]])} @c{[lisp]} @itemsep write a binary integer to a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the character to write + + @i @itemsep the output stream (default is standard output) + + @i @itemsep the length of the integer in bytes (default is 4) + + returns @itemsep the integer + +Note: Integers are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{read-float([@i(stream)[, @i(length)]])} @c{[sal]} + + @xlcode{(read-float@pragma(defn)@index(read-float) [@t(@i(stream)) [@t(@i(length))]])} @c{[lisp]} @itemsep read a binary floating-point number from a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + @i @itemsep the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8) + + returns @itemsep the integer + +Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To read little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{write-float(@i(ch)[, @i(stream)[, @i(length)]])} @c{[sal]} + + @xlcode{(write-float@pragma(defn)@index(write-float) @t(@i(ch)) [@t(@i(stream)) [@t(@i(length))]])} @c{[lisp]} @itemsep write a binary floating-point number to a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the character to write + + @i @itemsep the output stream (default is standard output) + + @i @itemsep the length of the float in bytes (default is 4, legal values are -4, -8, 4, and 8) + + returns @itemsep the integer + +Note: Floats are assumed to be big-endian (high-order byte first) and +signed, regardless of the platform. To write in little-endian format, use a +negative number for the length, e.g. -4 indicates a 4-bytes, low-order +byte first. The file should be opened in binary mode. + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{read-line([@i(stream)])} @c{[sal]} + + @xlcode{(read-line@pragma(defn)@index(read-line) [@t(@i(stream))])} @c{[lisp]} @itemsep read a line from a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + returns @itemsep the string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{read-byte([@i(stream)])} @c{[sal]} + + @xlcode{(read-byte@pragma(defn)@index(read-byte) [@t(@i(stream))])} @c{[lisp]} @itemsep read a byte from a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the input stream (default is standard input) + + returns @itemsep the byte (integer) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{write-byte(@i(byte)[, @i(stream)])} @c{[sal]} + + @xlcode{(write-byte@pragma(defn)@index(write-byte) @t(@i(byte)) [@t(@i(stream))])} @c{[lisp]} @itemsep write a byte to a stream +@end(fgroup) +@begin(pdescription) + @i @itemsep the byte to write (integer) + + @i @itemsep the output stream (default is standard output) + + returns @itemsep the byte (integer) + +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(String Stream Functions)@index(String Stream Functions) + These functions operate on unnamed streams. An unnamed output + stream collects characters sent to it when it is used as the + destination of any output function. The functions +@xlcode(get-output-stream-string) and @xlcode(get-output-stream-list) return a string or a list of characters. + +An unnamed input stream is setup with the + @xlcode(make-string-input-stream) function and returns each character of the string when + it is used as the source of any input function. + +@begin(fdescription) +@blankspace(1) + @begin(fgroup)@xlcode{make-string-input-stream(@i(str)[, @i(start)[, @i(end)]])} @c{[sal]} + + @xlcode{(make-string-input-stream@pragma(defn)@index(make-string-input-stream) @t(@i(str)) [@t(@i(start)) [@t(@i(end))]])} @c{[lisp]} +@end(fgroup) +@begin(pdescription) + @i @itemsep the string + + @i @itemsep the starting offset + + @i @itemsep the ending offset + 1 + + returns @itemsep an unnamed stream that reads from the string + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{make-string-output-stream)()} @c{[sal]} + + @xlcode{(make-string-output-stream)} @c{[lisp]}@pragma(defn)@index(make-string-output-stream) +@end(fgroup) +@begin(pdescription) + returns @itemsep an unnamed output stream + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{get-output-stream-string(@i(stream))} @c{[sal]} + + @xlcode{(get-output-stream-string@pragma(defn)@index(get-output-stream-string) @t(@i(stream)))} @c{[lisp]} +@end(fgroup) +@begin(pdescription) + @i @itemsep the output stream + + returns @itemsep the output so far as a string + + Note: the output stream is emptied by this function +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{get-output-stream-list(@i(stream))} @c{[sal]} + + @xlcode{(get-output-stream-list@pragma(defn)@index(get-output-stream-list) @t(@i(stream)))} @c{[lisp]} +@end(fgroup) +@begin(pdescription) + @i @itemsep the output stream + + returns @itemsep the output so far as a list + + Note: the output stream is emptied by this function +@end(pdescription) +@blankspace(1) +@end(fdescription) + +@section(System Functions)@index(System Functions) +Note: the @xlcode(load) function first tries to load a file from the current directory. A @code(.lsp) extension is added if there is not already an alphanumeric extension following a period. If that fails, XLISP searches the path, which is obtained from the XLISPPATH environment variable in Unix and HKEY_LOCAL_MACHINE\SOFTWARE\CMU\Nyquist\XLISPPATH under Win32. (The Macintosh version has no search path.) + +@begin(fdescription) + @begin(fgroup)@xlcode{get-env(@i(name))} @c{[sal]} + + @xlcode{(get-env@pragma(defn)@index(get-env)@index(getenv)@index(environment variables) @t(@i(name)))} @c{[lisp]} @itemsep get from an environment variable +@end(fgroup) +@begin(pdescription) + @i @itemsep the name of the environment variable + + returns @itemsep string value of the environment variable, @xlcode(nil) if variable does not exist + +@end(pdescription) +@blankspace(1) + + @xlcode{(load@pragma(defn)@index(load) @t(@i(fname)) @t(&key )@t(:verbose) @t(:print))} @c{[lisp]} @itemsep load a source file +@begin(pdescription) + @i @itemsep the filename string or symbol + + :verbose @itemsep the verbose flag (default is t) + + :print @itemsep the print flag (default is @xlcode(nil)) + + returns @itemsep the filename + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{save(@i(fname))} @c{[sal]} + + @xlcode{(save@pragma(defn)@index(save) @t(@i(fname)))} @c{[lisp]} @itemsep save workspace to a file +@end(fgroup) +@begin(pdescription) + @i @itemsep the filename string or symbol + + returns @itemsep @xlcode(t) if workspace was written, @xlcode(nil) otherwise + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{restore(@i(fname))} @c{[sal]} + + @xlcode{(restore@pragma(defn)@index(restore) @t(@i(fname)))} @c{[lisp]} @itemsep restore workspace from a file +@end(fgroup) +@begin(pdescription) + @i @itemsep the filename string or symbol + + returns @itemsep @xlcode(nil) on failure, otherwise never returns + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{dribble([@i(fname)])} @c{[sal]} + + @xlcode{(dribble@pragma(defn)@index(dribble) [@t(@i(fname))])} @c{[lisp]} @itemsep create a file with a transcript of a session +@end(fgroup) +@begin(pdescription) + @i @itemsep file name string or symbol + (if missing, close current transcript) + + returns @itemsep @xlcode(t) if the transcript is opened, @xlcode(nil) if it is closed + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{gc()} @c{[sal]} + + @xlcode{(gc@pragma(defn)@index(gc))} @c{[lisp]} @itemsep force garbage collection +@end(fgroup) +@begin(pdescription) + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{expand(@i(num))} @c{[sal]} + + @xlcode{(expand@pragma(defn)@index(expand) @t(@i(num)))} @c{[lisp]} @itemsep expand memory by adding segments +@end(fgroup) +@begin(pdescription) + @i @itemsep the number of segments to add + + returns @itemsep the number of segments added + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{alloc(@i(num))} @c{[sal]} + + @xlcode{(alloc@pragma(defn)@index(alloc) @t(@i(num)))} @c{[lisp]} @itemsep change number of nodes to allocate in each segment +@end(fgroup) +@begin(pdescription) + @i @itemsep the number of nodes to allocate + + returns @itemsep the old number of nodes to allocate + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{info()} @c{[sal]} + + @xlcode{(info@pragma(defn)@index(info))} @c{[lisp]} @itemsep show information about memory usage. +@end(fgroup) +@begin(pdescription) + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{room()} @c{[sal]} + + @xlcode{(room@pragma(defn)@index(room))} @c{[lisp]} @itemsep show memory allocation statistics +@end(fgroup) +@begin(pdescription) + returns @itemsep @xlcode(nil) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{type-of(@i(expr))} @c{[sal]} + + @xlcode{(type-of@pragma(defn)@index(type-of) @t(@i(expr)))} @c{[lisp]} @itemsep returns the type of the expression +@end(fgroup) +@begin(pdescription) + @i @itemsep the expression to return the type of + + returns @itemsep @xlcode(nil) if the value is @xlcode(nil) otherwise one of the symbols: + +@begin(pdescription) + SYMBOL @itemsep for symbols + + OBJECT @itemsep for objects + + CONS @itemsep for conses + + SUBR @itemsep for built-in functions + + FSUBR @itemsep for special forms + + CLOSURE @itemsep for defined functions + + STRING @itemsep for strings + + FIXNUM @itemsep for integers + + FLONUM @itemsep for floating point numbers + + CHARACTER @itemsep for characters + + FILE-STREAM @itemsep for file pointers + + UNNAMED-STREAM @itemsep for unnamed streams + + ARRAY @itemsep for arrays + +@end(pdescription) +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{peek(@i(addrs))} @c{[sal]} + + @xlcode{(peek@pragma(defn)@index(peek) @t(@i(addrs)))} @c{[lisp]} @itemsep peek at a location in memory +@end(fgroup) +@begin(pdescription) + @i @itemsep the address to peek at (integer) + + returns @itemsep the value at the specified address (integer) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{poke(@i(addrs), @i(value))} @c{[sal]} + + @xlcode{(poke@pragma(defn)@index(poke) @t(@i(addrs)) @t(@i(value)))} @c{[lisp]} @itemsep poke a value into memory +@end(fgroup) +@begin(pdescription) + @i @itemsep the address to poke (integer) + + @i @itemsep the value to poke into the address (integer) + + returns @itemsep the value + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{bigendianp()} @c{[sal]} + + @xlcode{(bigendianp@pragma(defn)@index(bigendianp)@index(endian)@index(big endian)@index(little endian))} @c{[lisp]} @itemsep is this a big-endian machine? +@end(fgroup) +@begin(pdescription) + returns @itemsep T if this a big-endian architecture, storing the high-order byte of an integer at the lowest byte address of the integer; otherwise, NIL. +@foot(This is not a standard XLISP 2.0 function.) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{address-of(@i(expr))} @c{[sal]} + + @xlcode{(address-of@pragma(defn)@index(address-of) @t(@i(expr)))} @c{[lisp]} @itemsep get the address of an xlisp node +@end(fgroup) +@begin(pdescription) + @i @itemsep the node + + returns @itemsep the address of the node (integer) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{exit()} @c{[sal]} + + @xlcode{(exit@pragma(defn)@index(exit))} @c{[lisp]} @itemsep exit xlisp +@end(fgroup) +@begin(pdescription) + returns @itemsep never returns + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{setup-console()} @c{[sal]} + + @xlcode{(setup-console@pragma(defn)@index(setup-console)@index(window initialization))} @c{[lisp]} @itemsep set default console attributes +@end(fgroup) +@begin(pdescription) + returns @itemsep NIL + +Note: Under Windows, Nyquist normally starts up in a medium-sized console window with black text and a white background, with a window title of ``Nyquist.'' This is normally accomplished by calling @xlcode(setup-console) in @code(system.lsp). In Nyquist, you can avoid this behavior by setting @xlcode(*setup-console*) to NIL in your @code(init.lsp) file. If @xlcode(setup-console) is not called, Nyquist uses standard input and output as is. This is what you want if you are running Nyquist inside of emacs, for example.@index(emacs, using Nyquist with) + +@end(pdescription) +@blankspace(1) + + @begin(fgroup)@xlcode{echoenabled(@i(flag))} @c{[sal]} + + @xlcode{(echoenabled@pragma(defn)@index(echoenabled)@index(console, XLISP) @t(@i(flag)))} @c{[lisp]} @itemsep turn console input echoing on or off +@end(fgroup) +@begin(pdescription) + @i @itemsep T to enable echo, NIL to disable + + returns @itemsep NIL + +Note: This function is only implemented under Linux and Mac OS X. If Nyquist I/O is redirected through pipes, +the Windows version does not echo the input, but the Linux and Mac versions do. You can turn off echoing with +this function. Under windows it is defined to do nothing. + +@end(pdescription) +@end(fdescription) + +@section(File I/O Functions)@index(File I/O Functions) + +@subsection(Input from a File)@index(Input from a File) + +To open a file for input, use the @xlcode(open) function with the keyword +argument @xlcode(:direction) set to @xlcode(:input). To open a file for output, +use the @xlcode(open) function with the keyword argument @xlcode(:direction) set +to @xlcode(:output). The @xlcode(open) function takes a single required argument which +is the name of the file to be opened. This name can be in the form of a +string or a symbol. The @xlcode(open) function returns an object of type +@xlcode(FILE-STREAM) if it succeeds in opening the specified file. It returns the +value @xlcode(nil) if it fails. In order to manipulate the file, it is +necessary to save the value returned by the @xlcode(open) function. This is +usually done by assigning it to a variable with the @xlcode(setq) special form or by +binding it using @xlcode(let) or @xlcode(let*). Here is an example: +@begin(example) +(setq fp (open "init.lsp" :direction :input)) +@end(example) + Evaluating this expression will result in the file @code(init.lsp) + being opened. The file object that will be returned by the @xlcode(open) + function will be assigned to the variable @xlcode(fp). + + It is now possible to use the file for input. To read an + expression from the file, just supply the value of the @xlcode(fp) + variable as the optional @i(stream) argument to @xlcode(read). +@begin(example) +(read fp) +@end(example) + Evaluating this expression will result in reading the first + expression from the file @code(init.lsp). The expression will be + returned as the result of the @xlcode(read) function. More expressions + can be read from the file using further calls to the @xlcode(read) + function. When there are no more expressions to read, the @xlcode(read) + function will return @xlcode(nil) (or whatever value was supplied as the + second argument to @xlcode(read)). + + Once you are done reading from the file, you should close it. + To close the file, use the following expression: +@begin(example) +(close fp) +@end(example) + Evaluating this expression will cause the file to be closed. + +@subsection(Output to a File)@index(Output to a File) + + Writing to a file is pretty much the same as reading from one. + You need to open the file first. This time you should use the + @xlcode(open) function to indicate that you will do output to the file. + For example: +@begin(example) +(setq fp (open "test.dat" :direction :output)) +@end(example) + Evaluating this expression will open the file @code(test.dat) for + output. If the file already exists, its current contents will + be discarded. If it doesn't already exist, it will be created. + In any case, a @xlcode(FILE-STREAM) object will be returned by the @xlcode(OPEN) + function. This file object will be assigned to the @xlcode(fp) + variable. + + It is now possible to write to this file by supplying the value + of the @xlcode(fp) variable as the optional @i(stream) parameter in the @xlcode(print) function. +@begin(example) +(print "Hello there" fp) +@end(example) + Evaluating this expression will result in the string ``Hello + there'' being written to the file @code(test.dat). More data can be + written to the file using the same technique. + + Once you are done writing to the file, you should close it. + Closing an output file is just like closing an input file. +@begin(example) +(close fp) +@end(example) + Evaluating this expression will close the output file and make + it permanent. + +@subsection(A Slightly More Complicated File Example) + + This example shows how to open a file, read each Lisp expression + from the file and print it. It demonstrates the use of files + and the use of the optional @i(stream) argument to the @xlcode(read) + function. +@begin(programexample) +(do* ((fp (open "test.dat" :direction :input)) + (ex (read fp) (read fp))) + ((null ex) nil) + (print ex)) +@end(programexample) + diff --git a/fft/fftn.c b/fft/fftn.c new file mode 100644 index 0000000..6ee7c5a --- /dev/null +++ b/fft/fftn.c @@ -0,0 +1,1046 @@ +/*--------------------------------*-C-*---------------------------------* + * File: + * fftn.c + * + * Public: + * fft_free (); + * fftn / fftnf (); + * + * Private: + * fftradix / fftradixf (); + * + * Descript: + * multivariate complex Fourier transform, computed in place + * using mixed-radix Fast Fourier Transform algorithm. + * + * Fortran code by: + * RC Singleton, Stanford Research Institute, Sept. 1968 + * + * translated by f2c (version 19950721). + * + * Revisions: + * 26 July 95 John Beale + * - added maxf and maxp as parameters to fftradix() + * + * 28 July 95 Mark Olesen + * - cleaned-up the Fortran 66 goto spaghetti, only 3 labels remain. + * + * - added fft_free() to provide some measure of control over + * allocation/deallocation. + * + * - added fftn() wrapper for multidimensional FFTs + * + * - use -DFFT_NOFLOAT or -DFFT_NODOUBLE to avoid compiling that + * precision. Note suffix `f' on the function names indicates + * float precision. + * + * - revised documentation + * + * 31 July 95 Mark Olesen + * - added GNU Public License + * - more cleanup + * - define SUN_BROKEN_REALLOC to use malloc() instead of realloc() + * on the first pass through, apparently needed for old libc + * - removed #error directive in favour of some code that simply + * won't compile (generate an error that way) + * + * 1 Aug 95 Mark Olesen + * - define FFT_RADIX4 to only have radix 2, radix 4 transforms + * - made fftradix /fftradixf () static scope, just use fftn() + * instead. If you have good ideas about fixing the factors + * in fftn() please do so. + * + * ======================================================================* + * NIST Guide to Available Math Software. + * Source for module FFT from package GO. + * Retrieved from NETLIB on Wed Jul 5 11:50:07 1995. + * ======================================================================* + * + *-----------------------------------------------------------------------* + * + * int fftn (int ndim, const int dims[], REAL Re[], REAL Im[], + * int iSign, double scaling); + * + * NDIM = the total number dimensions + * DIMS = a vector of array sizes + * if NDIM is zero then DIMS must be zero-terminated + * + * RE and IM hold the real and imaginary components of the data, and return + * the resulting real and imaginary Fourier coefficients. Multidimensional + * data *must* be allocated contiguously. There is no limit on the number + * of dimensions. + * + * ISIGN = the sign of the complex exponential (ie, forward or inverse FFT) + * the magnitude of ISIGN (normally 1) is used to determine the + * correct indexing increment (see below). + * + * SCALING = normalizing constant by which the final result is *divided* + * if SCALING == -1, normalize by total dimension of the transform + * if SCALING < -1, normalize by the square-root of the total dimension + * + * example: + * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3] + * + * int dims[3] = {n1,n2,n3} + * fftn (3, dims, Re, Im, 1, scaling); + * + *-----------------------------------------------------------------------* + * int fftradix (REAL Re[], REAL Im[], size_t nTotal, size_t nPass, + * size_t nSpan, int iSign, size_t max_factors, + * size_t max_perm); + * + * RE, IM - see above documentation + * + * Although there is no limit on the number of dimensions, fftradix() must + * be called once for each dimension, but the calls may be in any order. + * + * NTOTAL = the total number of complex data values + * NPASS = the dimension of the current variable + * NSPAN/NPASS = the spacing of consecutive data values while indexing the + * current variable + * ISIGN - see above documentation + * + * example: + * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3] + * + * fftradix (Re, Im, n1*n2*n3, n1, n1, 1, maxf, maxp); + * fftradix (Re, Im, n1*n2*n3, n2, n1*n2, 1, maxf, maxp); + * fftradix (Re, Im, n1*n2*n3, n3, n1*n2*n3, 1, maxf, maxp); + * + * single-variate transform, + * NTOTAL = N = NSPAN = (number of complex data values), + * + * fftradix (Re, Im, n, n, n, 1, maxf, maxp); + * + * The data can also be stored in a single array with alternating real and + * imaginary parts, the magnitude of ISIGN is changed to 2 to give correct + * indexing increment, and data [0] and data [1] used to pass the initial + * addresses for the sequences of real and imaginary values, + * + * example: + * REAL data [2*NTOTAL]; + * fftradix ( &data[0], &data[1], NTOTAL, nPass, nSpan, 2, maxf, maxp); + * + * for temporary allocation: + * + * MAX_FACTORS >= the maximum prime factor of NPASS + * MAX_PERM >= the number of prime factors of NPASS. In addition, + * if the square-free portion K of NPASS has two or more prime + * factors, then MAX_PERM >= (K-1) + * + * storage in FACTOR for a maximum of 15 prime factors of NPASS. if NPASS + * has more than one square-free factor, the product of the square-free + * factors must be <= 210 array storage for maximum prime factor of 23 the + * following two constants should agree with the array dimensions. + * + *-----------------------------------------------------------------------* + * + * void fft_free (void); + * + * free-up allocated temporary storage after finished all the Fourier + * transforms. + * + *----------------------------------------------------------------------*/ +#ifndef _FFTN_C +#define _FFTN_C +#include +#include +#include +#include "fftn.h" + +/* double precision routine */ +static int +fftradix (double Re[], double Im[], + size_t nTotal, size_t nPass, size_t nSpan, int isign, + int max_factors, int max_perm); + +/* float precision routine */ +static int +fftradixf (float Re[], float Im[], + size_t nTotal, size_t nPass, size_t nSpan, int isign, + int max_factors, int max_perm); + +/* parameters for memory management */ + +static size_t SpaceAlloced = 0; +static size_t MaxPermAlloced = 0; + +/* temp space, (void *) since both float and double routines use it */ +static void *Tmp0 = NULL; /* temp space for real part */ +static void *Tmp1 = NULL; /* temp space for imaginary part */ +static void *Tmp2 = NULL; /* temp space for Cosine values */ +static void *Tmp3 = NULL; /* temp space for Sine values */ +static int *Perm = NULL; /* Permutation vector */ + +#define NFACTOR 11 +static int factor [NFACTOR]; + +void +fft_free (void) +{ + SpaceAlloced = MaxPermAlloced = 0; + if (Tmp0 != NULL) { free (Tmp0); Tmp0 = NULL; } + if (Tmp1 != NULL) { free (Tmp1); Tmp1 = NULL; } + if (Tmp2 != NULL) { free (Tmp2); Tmp2 = NULL; } + if (Tmp3 != NULL) { free (Tmp3); Tmp3 = NULL; } + if (Perm != NULL) { free (Perm); Perm = NULL; } +} + +#ifndef M_PI +# define M_PI 3.14159265358979323846264338327950288 +#endif + +#ifndef SIN60 +# define SIN60 0.86602540378443865 /* sin(60 deg) */ +# define COS72 0.30901699437494742 /* cos(72 deg) */ +# define SIN72 0.95105651629515357 /* sin(72 deg) */ +#endif + +/* re-include this source file on the second pass through */ +#undef REAL +#undef FFTN +#undef FFTNS +#undef FFTRADIX +#undef FFTRADIXS + +#ifndef FFT_NOFLOAT +# define REAL float +# define FFTN fftnf /* trailing 'f' for float */ +# define FFTNS "fftnf" /* name for error message */ +# define FFTRADIX fftradixf /* trailing 'f' for float */ +# define FFTRADIXS "fftradixf" /* name for error message */ +# include "fftn.c" /* include this file again */ +#endif + +#undef REAL +#undef FFTN +#undef FFTNS +#undef FFTRADIX +#undef FFTRADIXS + +#ifndef FFT_NODOUBLE +# define REAL double +# define FFTN fftn +# define FFTNS "fftn" +# define FFTRADIX fftradix +# define FFTRADIXS "fftradix" +# include "fftn.c" /* include this file again */ +#endif + +#if defined (FFT_NOFLOAT) && defined (FFT_NODOUBLE) && !defined (lint) +Error: cannot have both -DFFT_NOFLOAT and -DFFT_NODOUBLE +#endif +#else /* _FFTN_C */ + +/* + * + */ +int +FFTN (int ndim, const int dims[], + REAL Re [], + REAL Im [], + int iSign, + double scaling) +{ + size_t nSpan, nPass, nTotal; + int ret, i, max_factors, max_perm; + + /* + * tally the number of elements in the data array + * and determine the number of dimensions + */ + nTotal = 1; + if (ndim && dims [0]) + { + for (i = 0; i < ndim; i++) + { + if (dims [i] <= 0) + { + fputs ("Error: " FFTNS "() - dimension error\n", stderr); + fft_free (); /* free-up memory */ + return -1; + } + nTotal *= dims [i]; + } + } + else + { + ndim = 0; + for (i = 0; dims [i]; i++) + { + if (dims [i] <= 0) + { + fputs ("Error: " FFTNS "() - dimension error\n", stderr); + fft_free (); /* free-up memory */ + return -1; + } + nTotal *= dims [i]; + ndim++; + } + } + + /* determine maximum number of factors and permuations */ +#if 1 + /* + * follow John Beale's example, just use the largest dimension and don't + * worry about excess allocation. May be someone else will do it? + */ + max_factors = max_perm = 1; + for (i = 0; i < ndim; i++) + { + nSpan = dims [i]; + if (nSpan > max_factors) max_factors = nSpan; + if (nSpan > max_perm) max_perm = nSpan; + } +#else + /* use the constants used in the original Fortran code */ + max_factors = 23; + max_perm = 209; +#endif + /* loop over the dimensions: */ + nPass = 1; + for (i = 0; i < ndim; i++) + { + nSpan = dims [i]; + nPass *= nSpan; + ret = FFTRADIX (Re, Im, nTotal, nSpan, nPass, iSign, + max_factors, max_perm); + /* exit, clean-up already done */ + if (ret) + return ret; + } + + /* Divide through by the normalizing constant: */ + if (scaling && scaling != 1.0) + { + if (iSign < 0) iSign = -iSign; + if (scaling < 0.0) + { + scaling = nTotal; + if (scaling < -1.0) + scaling = sqrt (scaling); + } + scaling = 1.0 / scaling; /* multiply is often faster */ + for (i = 0; i < nTotal; i += iSign) + { + Re [i] *= scaling; + Im [i] *= scaling; + } + } + return 0; +} + +/* + * singleton's mixed radix routine + * + * could move allocation out to fftn(), but leave it here so that it's + * possible to make this a standalone function + */ +static int +FFTRADIX (REAL Re[], + REAL Im[], + size_t nTotal, + size_t nPass, + size_t nSpan, + int iSign, + int max_factors, + int max_perm) +{ + int ii, mfactor, kspan, ispan, inc; + int j, jc, jf, jj, k, k1, k2, k3, k4, kk, kt, nn, ns, nt; + + REAL radf; + REAL c1, c2, c3, cd, aa, aj, ak, ajm, ajp, akm, akp; + REAL s1, s2, s3, sd, bb, bj, bk, bjm, bjp, bkm, bkp; + + REAL *Rtmp = NULL; /* temp space for real part*/ + REAL *Itmp = NULL; /* temp space for imaginary part */ + REAL *Cos = NULL; /* Cosine values */ + REAL *Sin = NULL; /* Sine values */ + + REAL s60 = SIN60; /* sin(60 deg) */ + REAL c72 = COS72; /* cos(72 deg) */ + REAL s72 = SIN72; /* sin(72 deg) */ + REAL pi2 = M_PI; /* use PI first, 2 PI later */ + + /* gcc complains about k3 being uninitialized, but I can't find out where + * or why ... it looks okay to me. + * + * initialize to make gcc happy + */ + k3 = 0; + + /* gcc complains about c2, c3, s2,s3 being uninitialized, but they're + * only used for the radix 4 case and only AFTER the (s1 == 0.0) pass + * through the loop at which point they will have been calculated. + * + * initialize to make gcc happy + */ + c2 = c3 = s2 = s3 = 0.0; + + /* Parameter adjustments, was fortran so fix zero-offset */ + Re--; + Im--; + + if (nPass < 2) + return 0; + + /* allocate storage */ + if (SpaceAlloced < max_factors * sizeof (REAL)) + { +#ifdef SUN_BROKEN_REALLOC + if (!SpaceAlloced) /* first time */ + { + SpaceAlloced = max_factors * sizeof (REAL); + Tmp0 = (void *) malloc (SpaceAlloced); + Tmp1 = (void *) malloc (SpaceAlloced); + Tmp2 = (void *) malloc (SpaceAlloced); + Tmp3 = (void *) malloc (SpaceAlloced); + } + else + { +#endif + SpaceAlloced = max_factors * sizeof (REAL); + Tmp0 = (void *) realloc (Tmp0, SpaceAlloced); + Tmp1 = (void *) realloc (Tmp1, SpaceAlloced); + Tmp2 = (void *) realloc (Tmp2, SpaceAlloced); + Tmp3 = (void *) realloc (Tmp3, SpaceAlloced); +#ifdef SUN_BROKEN_REALLOC + } +#endif + } + else + { + /* allow full use of alloc'd space */ + max_factors = SpaceAlloced / sizeof (REAL); + } + if (MaxPermAlloced < max_perm) + { +#ifdef SUN_BROKEN_REALLOC + if (!MaxPermAlloced) /* first time */ + Perm = (int *) malloc (max_perm * sizeof(int)); + else +#endif + Perm = (int *) realloc (Perm, max_perm * sizeof(int)); + MaxPermAlloced = max_perm; + } + else + { + /* allow full use of alloc'd space */ + max_perm = MaxPermAlloced; + } + if (Tmp0 == NULL || Tmp1 == NULL || Tmp2 == NULL || Tmp3 == NULL + || Perm == NULL) + goto Memory_Error_Label; + + /* assign pointers */ + Rtmp = (REAL *) Tmp0; + Itmp = (REAL *) Tmp1; + Cos = (REAL *) Tmp2; + Sin = (REAL *) Tmp3; + + /* + * Function Body + */ + inc = iSign; + if (iSign < 0) { + s72 = -s72; + s60 = -s60; + pi2 = -pi2; + inc = -inc; /* absolute value */ + } + + /* adjust for strange increments */ + nt = inc * nTotal; + ns = inc * nSpan; + kspan = ns; + + nn = nt - inc; + jc = ns / nPass; + radf = pi2 * (double) jc; + pi2 *= 2.0; /* use 2 PI from here on */ + + ii = 0; + jf = 0; + /* determine the factors of n */ + mfactor = 0; + k = nPass; + while (k % 16 == 0) { + mfactor++; + factor [mfactor - 1] = 4; + k /= 16; + } + j = 3; + jj = 9; + do { + while (k % jj == 0) { + mfactor++; + factor [mfactor - 1] = j; + k /= jj; + } + j += 2; + jj = j * j; + } while (jj <= k); + if (k <= 4) { + kt = mfactor; + factor [mfactor] = k; + if (k != 1) + mfactor++; + } else { + if (k - (k / 4 << 2) == 0) { + mfactor++; + factor [mfactor - 1] = 2; + k /= 4; + } + kt = mfactor; + j = 2; + do { + if (k % j == 0) { + mfactor++; + factor [mfactor - 1] = j; + k /= j; + } + j = ((j + 1) / 2 << 1) + 1; + } while (j <= k); + } + if (kt) { + j = kt; + do { + mfactor++; + factor [mfactor - 1] = factor [j - 1]; + j--; + } while (j); + } + + /* test that mfactors is in range */ + if (mfactor > NFACTOR) + { + fputs ("Error: " FFTRADIXS "() - exceeded number of factors\n", stderr); + goto Memory_Error_Label; + } + + /* compute fourier transform */ + for (;;) { + sd = radf / (double) kspan; + cd = sin(sd); + cd = 2.0 * cd * cd; + sd = sin(sd + sd); + kk = 1; + ii++; + + switch (factor [ii - 1]) { + case 2: + /* transform for factor of 2 (including rotation factor) */ + kspan /= 2; + k1 = kspan + 2; + do { + do { + k2 = kk + kspan; + ak = Re [k2]; + bk = Im [k2]; + Re [k2] = Re [kk] - ak; + Im [k2] = Im [kk] - bk; + Re [kk] += ak; + Im [kk] += bk; + kk = k2 + kspan; + } while (kk <= nn); + kk -= nn; + } while (kk <= jc); + if (kk > kspan) + goto Permute_Results_Label; /* exit infinite loop */ + do { + c1 = 1.0 - cd; + s1 = sd; + do { + do { + do { + k2 = kk + kspan; + ak = Re [kk] - Re [k2]; + bk = Im [kk] - Im [k2]; + Re [kk] += Re [k2]; + Im [kk] += Im [k2]; + Re [k2] = c1 * ak - s1 * bk; + Im [k2] = s1 * ak + c1 * bk; + kk = k2 + kspan; + } while (kk < nt); + k2 = kk - nt; + c1 = -c1; + kk = k1 - k2; + } while (kk > k2); + ak = c1 - (cd * c1 + sd * s1); + s1 = sd * c1 - cd * s1 + s1; + c1 = 2.0 - (ak * ak + s1 * s1); + s1 *= c1; + c1 *= ak; + kk += jc; + } while (kk < k2); + k1 += inc + inc; + kk = (k1 - kspan) / 2 + jc; + } while (kk <= jc + jc); + break; + + case 4: /* transform for factor of 4 */ + ispan = kspan; + kspan /= 4; + + do { + c1 = 1.0; + s1 = 0.0; + do { + do { + k1 = kk + kspan; + k2 = k1 + kspan; + k3 = k2 + kspan; + akp = Re [kk] + Re [k2]; + akm = Re [kk] - Re [k2]; + ajp = Re [k1] + Re [k3]; + ajm = Re [k1] - Re [k3]; + bkp = Im [kk] + Im [k2]; + bkm = Im [kk] - Im [k2]; + bjp = Im [k1] + Im [k3]; + bjm = Im [k1] - Im [k3]; + Re [kk] = akp + ajp; + Im [kk] = bkp + bjp; + ajp = akp - ajp; + bjp = bkp - bjp; + if (iSign < 0) { + akp = akm + bjm; + bkp = bkm - ajm; + akm -= bjm; + bkm += ajm; + } else { + akp = akm - bjm; + bkp = bkm + ajm; + akm += bjm; + bkm -= ajm; + } + /* avoid useless multiplies */ + if (s1 == 0.0) { + Re [k1] = akp; + Re [k2] = ajp; + Re [k3] = akm; + Im [k1] = bkp; + Im [k2] = bjp; + Im [k3] = bkm; + } else { + Re [k1] = akp * c1 - bkp * s1; + Re [k2] = ajp * c2 - bjp * s2; + Re [k3] = akm * c3 - bkm * s3; + Im [k1] = akp * s1 + bkp * c1; + Im [k2] = ajp * s2 + bjp * c2; + Im [k3] = akm * s3 + bkm * c3; + } + kk = k3 + kspan; + } while (kk <= nt); + + c2 = c1 - (cd * c1 + sd * s1); + s1 = sd * c1 - cd * s1 + s1; + c1 = 2.0 - (c2 * c2 + s1 * s1); + s1 *= c1; + c1 *= c2; + /* values of c2, c3, s2, s3 that will get used next time */ + c2 = c1 * c1 - s1 * s1; + s2 = 2.0 * c1 * s1; + c3 = c2 * c1 - s2 * s1; + s3 = c2 * s1 + s2 * c1; + kk = kk - nt + jc; + } while (kk <= kspan); + kk = kk - kspan + inc; + } while (kk <= jc); + if (kspan == jc) + goto Permute_Results_Label; /* exit infinite loop */ + break; + + default: + /* transform for odd factors */ +#ifdef FFT_RADIX4 + fputs ("Error: " FFTRADIXS "(): compiled for radix 2/4 only\n", stderr); + fft_free (); /* free-up memory */ + return -1; + break; +#else /* FFT_RADIX4 */ + k = factor [ii - 1]; + ispan = kspan; + kspan /= k; + + switch (k) { + case 3: /* transform for factor of 3 (optional code) */ + do { + do { + k1 = kk + kspan; + k2 = k1 + kspan; + ak = Re [kk]; + bk = Im [kk]; + aj = Re [k1] + Re [k2]; + bj = Im [k1] + Im [k2]; + Re [kk] = ak + aj; + Im [kk] = bk + bj; + ak -= 0.5 * aj; + bk -= 0.5 * bj; + aj = (Re [k1] - Re [k2]) * s60; + bj = (Im [k1] - Im [k2]) * s60; + Re [k1] = ak - bj; + Re [k2] = ak + bj; + Im [k1] = bk + aj; + Im [k2] = bk - aj; + kk = k2 + kspan; + } while (kk < nn); + kk -= nn; + } while (kk <= kspan); + break; + + case 5: /* transform for factor of 5 (optional code) */ + c2 = c72 * c72 - s72 * s72; + s2 = 2.0 * c72 * s72; + do { + do { + k1 = kk + kspan; + k2 = k1 + kspan; + k3 = k2 + kspan; + k4 = k3 + kspan; + akp = Re [k1] + Re [k4]; + akm = Re [k1] - Re [k4]; + bkp = Im [k1] + Im [k4]; + bkm = Im [k1] - Im [k4]; + ajp = Re [k2] + Re [k3]; + ajm = Re [k2] - Re [k3]; + bjp = Im [k2] + Im [k3]; + bjm = Im [k2] - Im [k3]; + aa = Re [kk]; + bb = Im [kk]; + Re [kk] = aa + akp + ajp; + Im [kk] = bb + bkp + bjp; + ak = akp * c72 + ajp * c2 + aa; + bk = bkp * c72 + bjp * c2 + bb; + aj = akm * s72 + ajm * s2; + bj = bkm * s72 + bjm * s2; + Re [k1] = ak - bj; + Re [k4] = ak + bj; + Im [k1] = bk + aj; + Im [k4] = bk - aj; + ak = akp * c2 + ajp * c72 + aa; + bk = bkp * c2 + bjp * c72 + bb; + aj = akm * s2 - ajm * s72; + bj = bkm * s2 - bjm * s72; + Re [k2] = ak - bj; + Re [k3] = ak + bj; + Im [k2] = bk + aj; + Im [k3] = bk - aj; + kk = k4 + kspan; + } while (kk < nn); + kk -= nn; + } while (kk <= kspan); + break; + + default: + if (k != jf) { + jf = k; + s1 = pi2 / (double) k; + c1 = cos(s1); + s1 = sin(s1); + if (jf > max_factors) + goto Memory_Error_Label; + Cos [jf - 1] = 1.0; + Sin [jf - 1] = 0.0; + j = 1; + do { + Cos [j - 1] = Cos [k - 1] * c1 + Sin [k - 1] * s1; + Sin [j - 1] = Cos [k - 1] * s1 - Sin [k - 1] * c1; + k--; + Cos [k - 1] = Cos [j - 1]; + Sin [k - 1] = -Sin [j - 1]; + j++; + } while (j < k); + } + do { + do { + k1 = kk; + k2 = kk + ispan; + ak = aa = Re [kk]; + bk = bb = Im [kk]; + j = 1; + k1 += kspan; + do { + k2 -= kspan; + j++; + Rtmp [j - 1] = Re [k1] + Re [k2]; + ak += Rtmp [j - 1]; + Itmp [j - 1] = Im [k1] + Im [k2]; + bk += Itmp [j - 1]; + j++; + Rtmp [j - 1] = Re [k1] - Re [k2]; + Itmp [j - 1] = Im [k1] - Im [k2]; + k1 += kspan; + } while (k1 < k2); + Re [kk] = ak; + Im [kk] = bk; + k1 = kk; + k2 = kk + ispan; + j = 1; + do { + k1 += kspan; + k2 -= kspan; + jj = j; + ak = aa; + bk = bb; + aj = 0.0; + bj = 0.0; + k = 1; + do { + k++; + ak += Rtmp [k - 1] * Cos [jj - 1]; + bk += Itmp [k - 1] * Cos [jj - 1]; + k++; + aj += Rtmp [k - 1] * Sin [jj - 1]; + bj += Itmp [k - 1] * Sin [jj - 1]; + jj += j; + if (jj > jf) { + jj -= jf; + } + } while (k < jf); + k = jf - j; + Re [k1] = ak - bj; + Im [k1] = bk + aj; + Re [k2] = ak + bj; + Im [k2] = bk - aj; + j++; + } while (j < k); + kk += ispan; + } while (kk <= nn); + kk -= nn; + } while (kk <= kspan); + break; + } + /* multiply by rotation factor (except for factors of 2 and 4) */ + if (ii == mfactor) + goto Permute_Results_Label; /* exit infinite loop */ + kk = jc + 1; + do { + c2 = 1.0 - cd; + s1 = sd; + do { + c1 = c2; + s2 = s1; + kk += kspan; + do { + do { + ak = Re [kk]; + Re [kk] = c2 * ak - s2 * Im [kk]; + Im [kk] = s2 * ak + c2 * Im [kk]; + kk += ispan; + } while (kk <= nt); + ak = s1 * s2; + s2 = s1 * c2 + c1 * s2; + c2 = c1 * c2 - ak; + kk = kk - nt + kspan; + } while (kk <= ispan); + c2 = c1 - (cd * c1 + sd * s1); + s1 += sd * c1 - cd * s1; + c1 = 2.0 - (c2 * c2 + s1 * s1); + s1 *= c1; + c2 *= c1; + kk = kk - ispan + jc; + } while (kk <= kspan); + kk = kk - kspan + jc + inc; + } while (kk <= jc + jc); + break; +#endif /* FFT_RADIX4 */ + } + } + +/* permute the results to normal order---done in two stages */ +/* permutation for square factors of n */ +Permute_Results_Label: + Perm [0] = ns; + if (kt) { + k = kt + kt + 1; + if (mfactor < k) + k--; + j = 1; + Perm [k] = jc; + do { + Perm [j] = Perm [j - 1] / factor [j - 1]; + Perm [k - 1] = Perm [k] * factor [j - 1]; + j++; + k--; + } while (j < k); + k3 = Perm [k]; + kspan = Perm [1]; + kk = jc + 1; + k2 = kspan + 1; + j = 1; + if (nPass != nTotal) { +/* permutation for multivariate transform */ +Permute_Multi_Label: + do { + do { + k = kk + jc; + do { + /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */ + ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak; + bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk; + kk += inc; + k2 += inc; + } while (kk < k); + kk += ns - jc; + k2 += ns - jc; + } while (kk < nt); + k2 = k2 - nt + kspan; + kk = kk - nt + jc; + } while (k2 < ns); + do { + do { + k2 -= Perm [j - 1]; + j++; + k2 = Perm [j] + k2; + } while (k2 > Perm [j - 1]); + j = 1; + do { + if (kk < k2) + goto Permute_Multi_Label; + kk += jc; + k2 += kspan; + } while (k2 < ns); + } while (kk < ns); + } else { +/* permutation for single-variate transform (optional code) */ +Permute_Single_Label: + do { + /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */ + ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak; + bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk; + kk += inc; + k2 += kspan; + } while (k2 < ns); + do { + do { + k2 -= Perm [j - 1]; + j++; + k2 = Perm [j] + k2; + } while (k2 > Perm [j - 1]); + j = 1; + do { + if (kk < k2) + goto Permute_Single_Label; + kk += inc; + k2 += kspan; + } while (k2 < ns); + } while (kk < ns); + } + jc = k3; + } + + if ((kt << 1) + 1 >= mfactor) + return 0; + ispan = Perm [kt]; + /* permutation for square-free factors of n */ + j = mfactor - kt; + factor [j] = 1; + do { + factor [j - 1] *= factor [j]; + j--; + } while (j != kt); + kt++; + nn = factor [kt - 1] - 1; + if (nn > max_perm) + goto Memory_Error_Label; + j = jj = 0; + for (;;) { + k = kt + 1; + k2 = factor [kt - 1]; + kk = factor [k - 1]; + j++; + if (j > nn) + break; /* exit infinite loop */ + jj += kk; + while (jj >= k2) { + jj -= k2; + k2 = kk; + k++; + kk = factor [k - 1]; + jj += kk; + } + Perm [j - 1] = jj; + } + /* determine the permutation cycles of length greater than 1 */ + j = 0; + for (;;) { + do { + j++; + kk = Perm [j - 1]; + } while (kk < 0); + if (kk != j) { + do { + k = kk; + kk = Perm [k - 1]; + Perm [k - 1] = -kk; + } while (kk != j); + k3 = kk; + } else { + Perm [j - 1] = -j; + if (j == nn) + break; /* exit infinite loop */ + } + } + max_factors *= inc; + /* reorder a and b, following the permutation cycles */ + for (;;) { + j = k3 + 1; + nt -= ispan; + ii = nt - inc + 1; + if (nt < 0) + break; /* exit infinite loop */ + do { + do { + j--; + } while (Perm [j - 1] < 0); + jj = jc; + do { + kspan = jj; + if (jj > max_factors) { + kspan = max_factors; + } + jj -= kspan; + k = Perm [j - 1]; + kk = jc * k + ii + jj; + k1 = kk + kspan; + k2 = 0; + do { + k2++; + Rtmp [k2 - 1] = Re [k1]; + Itmp [k2 - 1] = Im [k1]; + k1 -= inc; + } while (k1 != kk); + do { + k1 = kk + kspan; + k2 = k1 - jc * (k + Perm [k - 1]); + k = -Perm [k - 1]; + do { + Re [k1] = Re [k2]; + Im [k1] = Im [k2]; + k1 -= inc; + k2 -= inc; + } while (k1 != kk); + kk = k2; + } while (k != j); + k1 = kk + kspan; + k2 = 0; + do { + k2++; + Re [k1] = Rtmp [k2 - 1]; + Im [k1] = Itmp [k2 - 1]; + k1 -= inc; + } while (k1 != kk); + } while (jj); + } while (j != 1); + } + return 0; /* exit point here */ + + /* alloc or other problem, do some clean-up */ +Memory_Error_Label: + fputs ("Error: " FFTRADIXS "() - insufficient memory.\n", stderr); + fft_free (); /* free-up memory */ + return -1; +} +#endif /* _FFTN_C */ +/* ---------------------- end-of-file (c source) ---------------------- */ diff --git a/fft/fftn.h b/fft/fftn.h new file mode 100644 index 0000000..c760f80 --- /dev/null +++ b/fft/fftn.h @@ -0,0 +1,32 @@ +/*--------------------------------*-C-*---------------------------------* + * File: + * fftn.h + * ---------------------------------------------------------------------* + * Re[]: real value array + * Im[]: imaginary value array + * nTotal: total number of complex values + * nPass: number of elements involved in this pass of transform + * nSpan: nspan/nPass = number of bytes to increment pointer + * in Re[] and Im[] + * isign: exponent: +1 = forward -1 = reverse + * scaling: normalizing constant by which the final result is *divided* + * scaling == -1, normalize by total dimension of the transform + * scaling < -1, normalize by the square-root of the total dimension + * + * ---------------------------------------------------------------------- + * See the comments in the code for correct usage! + */ + +#ifndef _FFTN_H +#define _FFTN_H + +extern void fft_free (void); + +/* double precision routine */ +extern int fftn (int ndim, const int dims[], double Re[], double Im[], + int isign, double scaling); + +/* float precision routine */ +extern int fftnf (int ndim, const int dims[], float Re[], float Im[], + int isign, double scaling); +#endif /* _FFTN_H */ diff --git a/ffts/Matlab-testing/conv2dTest.c b/ffts/Matlab-testing/conv2dTest.c new file mode 100644 index 0000000..37213e6 --- /dev/null +++ b/ffts/Matlab-testing/conv2dTest.c @@ -0,0 +1,116 @@ +/* A program to test fast 2d real convolution */ + +#include +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" +#include "fft2d.h" + +#if macintosh +#include +#endif + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) +//#define BIPRAND(a) round(100*(2.0/(RAND_MAX+1.0)*a-1.0)) + +void main(){ +long N = 256; /* the number of cols in 2d ffts, must be power of 2 */ +long N2 = 64; /* the number of rows in 2d ffts, must be power of 2 */ +long kernSize = 53; /* kernal cols must be less than N */ +long kernSize2 = 29; /* kernal rows must be less than N2*/ +long dataSize = N-kernSize+1; /* data cols */ +long dataSize2 = N2-kernSize2+1; /* data rows */ +float *a; +float *b; +long i1; +long i2; +long TheErr; +long M; +long M2; + +FILE *fdataout; /* output file */ + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a[0])); +printf(" randseed = %10u\n", randseed); + +srand(randseed); +M = roundtol(LOG2(N)); +N = POW2(M); +M2 = roundtol(LOG2(N2)); +N2 = POW2(M2); + +printf("fft size = %6d X%6d, ", N2, N); + +if ((dataSize <= 0)||(dataSize2 <= 0)) TheErr = 22; +else TheErr = 0; + +if(!TheErr){ + TheErr = fft2dInit(M2, M); +} + +a = (float *) calloc(N2*N,sizeof(float) ); // calloc to zero pad data to fill N to N2 +if (a == 0) TheErr = 2; +if(!TheErr){ + b = (float *) calloc(N2*N,sizeof(float) ); // calloc to zero pad data to fill N to N2 + if (b == 0) TheErr = 2; +} +if(!TheErr){ + fdataout = fopen("conv2ddat.c2d", "wb"); + if (fdataout == NULL) TheErr = -50; +} +if(!TheErr){ + + /* write sizes to fdataout */ + fwrite(&dataSize, sizeof(dataSize), 1, fdataout); + fwrite(&dataSize2, sizeof(dataSize2), 1, fdataout); + fwrite(&kernSize, sizeof(kernSize), 1, fdataout); + fwrite(&kernSize2, sizeof(kernSize2), 1, fdataout); + /* set up a simple test case and write to fdataout */ + for (i2=0; i2 +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" + +#if macintosh +#include +#endif + + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) +//#define BIPRAND(a) round(100*(2.0/(RAND_MAX+1.0)*a-1.0)) + +void main(){ +const long N2 = 2; /* the number ffts to test */ +long N = 2048; /* size of FFTs, must be power of 2 */ +long kernSize = 1003; /* kernal size must be less than N */ +long dataSize = N-kernSize+1; /* data size */ +float *a; +float *b; +long i1; +long i2; +long TheErr; +long M; + +FILE *fdataout; /* output file */ + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a[0])); +printf(" randseed = %10u\n", randseed); + +srand(randseed); +M = roundtol(LOG2(N)); +N = POW2(M); + +printf("fft size = %6d, ", N); + +if (dataSize <= 0) TheErr = 22; +else TheErr = 0; + +if(!TheErr){ + TheErr = fftInit(M); +} + +a = (float *) calloc(N2*N,sizeof(float) ); // calloc to zero pad data to fill N +if (a == 0) TheErr = 2; +if(!TheErr){ + b = (float *) calloc(N2*N,sizeof(float) ); // calloc to zero pad data to fill N + if (b == 0) TheErr = 2; +} +if(!TheErr){ + fdataout = fopen("convdat.cnv", "wb"); + if (fdataout == NULL) TheErr = -50; +} +if(!TheErr){ + + /* write sizes to fdataout */ + fwrite(&dataSize, sizeof(dataSize), 1, fdataout); + fwrite(&kernSize, sizeof(kernSize), 1, fdataout); + fwrite(&N2, sizeof(N2), 1, fdataout); + /* set up a simple test case and write to fdataout */ + for (i2=0; i2 +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" +#include "fft2d.h" + +#if macintosh +#include +#endif + + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) + +void main(){ +long N2 = 64; /* the number of rows in 2d ffts, must be power of 2 */ +long N = 256; /* the number of cols in 2d ffts, must be power of 2 */ +float *a; +float maxerrfft; +long i1; +long TheErr; +long M; +long M2; + +FILE *fdataout; /* output file */ + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a[0])); +printf(" randseed = %10u\n", randseed); + +srand(randseed); +M = roundtol(LOG2(N)); +N = POW2(M); +M2 = roundtol(LOG2(N2)); +N2 = POW2(M2); + +printf("fft size = %6d X%6d, ", N2, N); + +TheErr = 0; + +if(!TheErr){ + TheErr = fft2dInit(M2, M); +} + +a = (float *) malloc(N2*N*sizeof(float) ); +if (a == 0) TheErr = 2; +if(!TheErr){ + fdataout = fopen("fftdat.dr2", "wb"); + if (fdataout == NULL) TheErr = -50; +} +if(!TheErr){ + + /* write sizes to fdataout */ + fwrite(&N, sizeof(N), 1, fdataout); + fwrite(&N2, sizeof(N2), 1, fdataout); + /* set up a simple test case and write to fdataout */ + for (i1=0; i1 /* uses four1 from numerical recipes in C to verify iffts */ + /*change fmin in numerical recipes to fminnr to avoid conflict with fp.h */ +#include +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" + + +#if macintosh +#include +#endif + +#define NSIZES 24 /* the number of different fft sizes to test */ + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) + +typedef struct{ + float Re; + float Im; + } Complex; + +void main(){ +long fftSize[NSIZES] = /* size of FFTs, must be powers of 2 */ + {2, 4, 8, 16, 32, 64, 128, 256, + 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, + 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216}; +Complex *a1; +const long N2 = 2; /* the number ffts to test at each size */ +long isize; +long i1; +long TheErr; +long N; +long M; +float maxerrifft; +float maxerrfft; + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a1[0].Re)); +printf(" randseed = %10u\n", randseed); +for (isize = 0; isize < NSIZES; isize++){ + + srand(randseed); + N = fftSize[isize]; + printf("ffts size = %8d, ", N); + M = roundtol(LOG2(N)); + + TheErr = fftInit(M); + + if(!TheErr){ + a1 = (Complex *) malloc( N2*N*sizeof(Complex) ); + if (a1 == 0) TheErr = 2; + } + + if(!TheErr){ + + /* set up a1 simple test case */ + for (i1=0; i1 /* uses fourn from numerical recipes in C to verify ifft2d */ + /*change fmin in numerical recipes to fminnr to avoid conflict with fp.h */ + +#include +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" +#include "fft2d.h" + +#if macintosh +#include +#endif + +#define NSIZES 24 /* the number of different ffts col sizes to test */ + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) +//#define BIPRAND(a) round(100*(2.0/(RAND_MAX+1.0)*a-1.0)) +typedef struct{ + float Re; + float Im; + } Complex; + +void main(){ +long fftSize[NSIZES] = /* size of FFTs cols, must be powers of 2 */ + {2, 4, 8, 16, 32, 64, 128, 256, + 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, + 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216}; +Complex *a1; +long N2 = 64; /* the number of rows in the 2d fft */ +long isize; +long i1; +long TheErr; +long N; +long M; +long M2; +float maxerrifft; +float maxerrfft; +unsigned long nn[2]; + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a1[0].Re)); +printf(" randseed = %10u\n", randseed); +for (isize = 0; isize < NSIZES; isize++){ + + srand(randseed); + N = fftSize[isize]; + M = roundtol(LOG2(N)); + N = POW2(M); + M2 = roundtol(LOG2(N2)); + N2 = POW2(M2); + + printf("ffts size = %6d X%6d, ", N2, N); + + nn[0] = N2; + nn[1] = N; + + TheErr = fft2dInit(M2, M); + + if(!TheErr){ + a1 = (Complex *) malloc(N2*N*sizeof(Complex) ); + if (a1 == 0) TheErr = 2; + } + + if(!TheErr){ + + /* set up a simple test case */ + for (i1=0; i1 /* uses fourn from numerical recipes in C to verify ifft3d */ + /*change fmin in numerical recipes to fminnr to avoid conflict with fp.h */ + +#include +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" +#include "fft2d.h" + +#if macintosh +#include +#endif + +#define NSIZES 24 /* the number of different ffts col sizes to test */ + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) + +typedef struct{ + float Re; + float Im; + } Complex; + +void main(){ +long fftSize[NSIZES] = /* size of FFTs cols, must be powers of 2 */ + {2, 4, 8, 16, 32, 64, 128, 256, + 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, + 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216}; +Complex *a1; +long isize; +long i1; +long TheErr; +long N; +long M; +long N2 = 16; /* the number of rows in the 3d fft */ +long M2; +long N3 = 32; /* the number of pages in the 3d fft */ +long M3; +float maxerrifft; +float maxerrfft; +unsigned long nn[3]; + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a1[0].Re)); +printf(" randseed = %10u\n", randseed); +for (isize = 0; isize < NSIZES; isize++){ + + srand(randseed); + N = fftSize[isize]; + M = roundtol(LOG2(N)); + N = POW2(M); + M2 = roundtol(LOG2(N2)); + N2 = POW2(M2); + M3 = roundtol(LOG2(N3)); + N3 = POW2(M3); + + printf("ffts size = %5d X%5d X%6d, ", N3, N2, N); + + nn[0] = N3; + nn[1] = N2; + nn[2] = N; + + TheErr = fft3dInit(M3, M2, M); + + if(!TheErr){ + a1 = (Complex *) malloc(N3*N2*N*sizeof(Complex) ); + if (a1 == 0) TheErr = 2; + } + + if(!TheErr){ + + /* set up a simple test case */ + for (i1=0; i1 /* uses realft from numerical recipes in C to verify riffts */ + /*change fmin in numerical recipes to fminnr to avoid conflict with fp.h */ + +#include +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" + +#if macintosh +#include +#endif + +#define NSIZES 24 /* the number of different fft sizes to test */ + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) + +void main(){ +long fftSize[NSIZES] = /* size of FFTs, must be powers of 2 */ + {2, 4, 8, 16, 32, 64, 128, 256, + 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, + 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216}; +float *a; +const long N2 = 2; /* the number ffts to test at each size */ +long isize; +long i1; +long i2; +long TheErr; +long N; +long M; +float maxerrifft; +float maxerrfft; + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a[0])); +printf(" randseed = %10u\n", randseed); +for (isize = 0; isize < NSIZES; isize++){ + + srand(randseed); + N = fftSize[isize]; + printf("rffts size = %8d, ", N); + M = roundtol(LOG2(N)); + + TheErr = 0; + TheErr = fftInit(M); + + if(!TheErr){ + a = (float *) malloc(N2*N*sizeof(float) ); + if (a == 0) TheErr = 2; + } + + if(!TheErr){ + + /* set up a simple test case */ + for (i1=0; i1 /* uses rlft3 from numerical recipes in C to verify rifft2d */ + /*change fmin in numerical recipes to fminnr to avoid conflict with fp.h */ + +#include +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" +#include "fft2d.h" +#include // uses ugly tensors from numerical recipes; so can call rlft3 + +#if macintosh +#include +#endif + +#define NSIZES 24 /* the number of different ffts sizes to test */ + +#define BIPRAND(a) (2.0/(RAND_MAX+1.0)*a-1.0) + +void main(){ +long fftSize[NSIZES] = /* size of FFTs, must be powers of 2 */ + {2, 4, 8, 16, 32, 64, 128, 256, + 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, + 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216}; +float *a; +long N2 = 64; /* the number of rows in 2d ffts, must be power of 2 */ +long isize; +long i1; +long i2; +long TheErr; +long N; +long M; +long M2; +float maxerrifft; +float maxerrfft; + +float ***NRtensdata; /* needed for rlft3 */ +float **NRmatdata; /* needed for rlft3 */ +float *specdata; /* needed for rlft3 */ +float t1,t2; + +unsigned int randseed = 777; +int rannum; +#if macintosh + UnsignedWide TheTime1; + Microseconds(&TheTime1); + randseed = TheTime1.lo; +#endif + +printf(" %6d Byte Floats \n", sizeof(a[0])); +printf(" randseed = %10u\n", randseed); +for (isize = 0; isize < NSIZES; isize++){ + + srand(randseed); + N = fftSize[isize]; + M = roundtol(LOG2(N)); + N = POW2(M); + M2 = roundtol(LOG2(N2)); + N2 = POW2(M2); + + printf("rffts size = %6d X%6d, ", N2, N); + + TheErr = 0; + TheErr = fft2dInit(M2, M); + + if(!TheErr){ + NRmatdata=matrix(1,1,1,2*N2); + specdata = &NRmatdata[1][1]; + NRtensdata=f3tensor(1,1,1,N2,1,N); // uses ugly tensors from NRUTIL; so can call rlft3 + a = &NRtensdata[1][1][1]; + if ((a == 0)||(specdata == 0)) TheErr = 2; + } + + if(!TheErr){ + + /* set up a simple test case */ + for (i1=0; i1 +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" + +#if macintosh +#include +#endif + +#define NSIZES 3 /* the number of different ffts sizes to time */ + +typedef struct{ + float Re; + float Im; + } Complex; + +void main(){ +long fftSize[NSIZES] = {1024, 16384, 262144}; /* size of FFTs, must be powers of 2 */ +long fftRepeats[NSIZES] = {2000, 50, 1}; /* number of timing loops */ +Complex *a; +long isize; +long i1; +long TheErr; +long N; +long M; + +#if macintosh +UnsignedWide TheTime1; +UnsignedWide TheTime2; +double TheTime; +#endif + +printf(" %6d Byte Floats \n", sizeof(a[0].Re)); +for (isize = 0; isize < NSIZES; isize++){ + + N = fftSize[isize]; + printf("ffts size = %7d, ", N); + M = roundtol(LOG2(N)); + + TheErr = fftInit(M); + + if(!TheErr){ + a = (Complex *) malloc(N*sizeof(Complex) ); + if (a == 0) TheErr = 2; + } + + if(!TheErr){ + + /* set up a simple test case */ + for (i1=0; i1 +#include +#include +#include +#include "fftlib.h" +#include "fftext.h" + +#if macintosh +#include +#endif + +#define NSIZES 3 /* the number of different fft sizes to time */ + +void main(){ +float *a; +long fftSize[NSIZES] = {2048, 32768, 524288}; /* size of FFTs, must be powers of 2 */ +long fftRepeats[NSIZES] = {2000, 50, 1}; /* number of timing loops */ +long isize; +long i1; +long TheErr; +long N; +long M; + +#if macintosh +UnsignedWide TheTime1; +UnsignedWide TheTime2; +double TheTime; +#endif + +printf(" %6d Byte Floats \n", sizeof(a[0])); +for (isize = 0; isize < NSIZES; isize++){ + + N = fftSize[isize]; + printf("rffts size = %9d ", N); + M = roundtol(LOG2(N)); + TheErr = fftInit(M); + + if(!TheErr){ + a = (float *) malloc(N*sizeof(float)); + if (a == 0) TheErr = 2; + } + + if(!TheErr){ + /* set up a simple test case */ + for (i1=0; i10; RowCnt--){ + idata = irow; + odata = ocol; + for (ColCnt=Ncols; ColCnt>0; ColCnt--){ + T0 = *idata; + T1 = *(idata+inRsizd1); + T2 = *(idata+inRsizd2); + T3 = *(idata+inRsizd3); + T4 = *(idata+inRsizd4); + T5 = *(idata+inRsizd5); + T6 = *(idata+inRsizd6); + T7 = *(idata+inRsizd7); + *odata = T0; + *(odata+1) = T1; + *(odata+2) = T2; + *(odata+3) = T3; + *(odata+4) = T4; + *(odata+5) = T5; + *(odata+6) = T6; + *(odata+7) = T7; + idata++; + odata += oRsiz; + } + irow += inRsizd8; + ocol += 8; +} +if (Nrows%8 != 0){ + for (ColCnt=Ncols; ColCnt>0; ColCnt--){ + idata = irow++; + odata = ocol; + ocol += oRsiz; + for (RowCnt=Nrows%8; RowCnt>0; RowCnt--){ + T0 = *idata; + *odata++ = T0; + idata += iRsiz; + } + } +} +} diff --git a/ffts/src/dxpose.h b/ffts/src/dxpose.h new file mode 100644 index 0000000..730f81f --- /dev/null +++ b/ffts/src/dxpose.h @@ -0,0 +1,16 @@ +/********************* +This matrix transpose is in a seperate file because it should always be double precision. +*********************/ +typedef double_t xdouble; // I use double_t so that global search and replace on double won't + // change this to float accidentally. + +void dxpose(xdouble *indata, long iRsiz, xdouble *outdata, long oRsiz, long Nrows, long Ncols); +/* not in-place double precision matrix transpose */ +/* INPUTS */ +/* *indata = input data array */ +/* iRsiz = offset to between rows of input data array */ +/* oRsiz = offset to between rows of output data array */ +/* Nrows = number of rows in input data array */ +/* Ncols = number of columns in input data array */ +/* OUTPUTS */ +/* *outdata = output data array */ diff --git a/ffts/src/fft2d.c b/ffts/src/fft2d.c new file mode 100644 index 0000000..0d8c3d8 --- /dev/null +++ b/ffts/src/fft2d.c @@ -0,0 +1,402 @@ +/******************************************************************* + This file extends the fftlib with 2d and 3d complex fft's and + 2d real fft's. All fft's return results in-place. Temporary buffers + for transposing columns are maintained privately via calls to + fft2dInit, fft2dFree, fft3dInit, and fft3dFree. + Note that you can call fft2dInit and fft3dInit repeatedly + with the same sizes, the extra calls will be ignored. + So, you could make a macro to call fft2dInit every time you call fft2d. + *** Warning *** fft2dFree and fft3dFree also call fftFree + so you must re-init all 1d fft sizes you are going to continue using +*******************************************************************/ +#include +#include +#include "fftlib.h" +#include "fftext.h" +#include "matlib.h" +#include "dxpose.h" +#include "fft2d.h" + // use trick of using a real double transpose in place of a complex transpose if it fits +#define cxpose(a,b,c,d,e,f) (2*sizeof(float)==sizeof(xdouble)) ? dxpose((xdouble *)(a), b, (xdouble *)(c), d, e, f) : cxpose(a,b,c,d,e,f); + // for this trick to work you must NOT replace the xdouble declarations in + // dxpose with float declarations. + + + // pointers for temporary storage for four columns +static float *Array2d[8*sizeof(long)] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; +int fft2dInit(long M2, long M){ + // init for fft2d, ifft2d, rfft2d, and rifft2d + // malloc storage for 4 columns of 2d ffts then call fftinit for both row and column ffts sizes +/* INPUTS */ +/* M = log2 of number of columns */ +/* M2 = log2 of number of rows */ +/* of 2d matrix to be fourier transformed */ +/* OUTPUTS */ +/* private storage for columns of 2d ffts */ +/* calls fftInit for cosine and bit reversed tables */ +int theError = 1; +if ((M2 >= 0) && (M2 < 8*sizeof(long))){ + theError = 0; + if (Array2d[M2] == 0){ + Array2d[M2] = (float *) malloc( 4*2*POW2(M2)*sizeof(float) ); + if (Array2d[M2] == 0) + theError = 2; + else{ + theError = fftInit(M2); + } + } + if (theError == 0) + theError = fftInit(M); +} +return theError; +} + +void fft2dFree(){ +// free storage for columns of 2d ffts and call fftFree to free all BRLow and Utbl storage +long i1; +for (i1=8*sizeof(long)-1; i1>=0; i1--){ + if (Array2d[i1] != 0){ + free(Array2d[i1]); + Array2d[i1] = 0; + }; +}; +fftFree(); +} + +void fft2d(float *data, long M2, long M){ +/* Compute 2D complex fft and return results in-place */ +/* INPUTS */ +/* *data = input data array */ +/* M2 = log2 of fft size number of rows */ +/* M = log2 of fft size number of columns */ +/* OUTPUTS */ +/* *data = output data array */ +long i1; +if((M2>0)&&(M>0)){ + ffts(data, M, POW2(M2)); + if (M>2) + for (i1=0; i10)&&(M>0)){ + iffts(data, M, POW2(M2)); + if (M>2) + for (i1=0; i1= 0) && (L < 8*sizeof(long))){ + theError = 0; + if (Array2d[L] == 0){ + Array2d[L] = (float *) malloc( 4*2*POW2(L)*sizeof(float) ); + if (Array2d[L] == 0) + theError = 2; + else{ + theError = fftInit(L); + } + } + if (theError == 0){ + if (Array2d[M2] == 0){ + Array2d[M2] = (float *) malloc( 4*2*POW2(M2)*sizeof(float) ); + if (Array2d[M2] == 0) + theError = 2; + else{ + theError = fftInit(M2); + } + } + } + if (theError == 0) + theError = fftInit(M); +} +return theError; +} + +void fft3dFree(){ +// free storage for columns of all 2d&3d ffts and call fftFree to free all BRLow and Utbl storage +fft2dFree(); +} + +void fft3d(float *data, long M3, long M2, long M){ +/* Compute 2D complex fft and return results in-place */ +/* INPUTS */ +/* *data = input data array */ +/* M3 = log2 of fft size number of pages */ +/* M2 = log2 of fft size number of rows */ +/* M = log2 of fft size number of columns */ +/* OUTPUTS */ +/* *data = output data array */ +long i1; +long i2; +const long N = POW2(M); +const long N2 = POW2(M2); +const long N3 = POW2(M3); +if((M3>0)&&(M2>0)&&(M>0)){ + ffts(data, M, N3*N2); + if (M>2) + for (i2=0; i22) + for (i1=0; i10)&&(M2>0)&&(M>0)){ + iffts(data, M, N3*N2); + if (M>2) + for (i2=0; i22) + for (i1=0; i10)&&(M>0)){ + rffts(data, M, POW2(M2)); + if (M==1){ + cxpose(data, POW2(M)/2, Array2d[M2]+POW2(M2)*2, POW2(M2), POW2(M2), 1); + xpose(Array2d[M2]+POW2(M2)*2, 2, Array2d[M2], POW2(M2), POW2(M2), 2); + rffts(Array2d[M2], M2, 2); + cxpose(Array2d[M2], POW2(M2), data, POW2(M)/2, 1, POW2(M2)); + } + else if (M==2){ + cxpose(data, POW2(M)/2, Array2d[M2]+POW2(M2)*2, POW2(M2), POW2(M2), 1); + xpose(Array2d[M2]+POW2(M2)*2, 2, Array2d[M2], POW2(M2), POW2(M2), 2); + rffts(Array2d[M2], M2, 2); + cxpose(Array2d[M2], POW2(M2), data, POW2(M)/2, 1, POW2(M2)); + + cxpose(data + 2, POW2(M)/2, Array2d[M2], POW2(M2), POW2(M2), 1); + ffts(Array2d[M2], M2, 1); + cxpose(Array2d[M2], POW2(M2), data + 2, POW2(M)/2, 1, POW2(M2)); + } + else{ + cxpose(data, POW2(M)/2, Array2d[M2]+POW2(M2)*2, POW2(M2), POW2(M2), 1); + xpose(Array2d[M2]+POW2(M2)*2, 2, Array2d[M2], POW2(M2), POW2(M2), 2); + rffts(Array2d[M2], M2, 2); + cxpose(Array2d[M2], POW2(M2), data, POW2(M)/2, 1, POW2(M2)); + + cxpose(data + 2, POW2(M)/2, Array2d[M2], POW2(M2), POW2(M2), 3); + ffts(Array2d[M2], M2, 3); + cxpose(Array2d[M2], POW2(M2), data + 2, POW2(M)/2, 3, POW2(M2)); + for (i1=4; i10)&&(M>0)){ + if (M==1){ + cxpose(data, POW2(M)/2, Array2d[M2], POW2(M2), POW2(M2), 1); + riffts(Array2d[M2], M2, 2); + xpose(Array2d[M2], POW2(M2), Array2d[M2]+POW2(M2)*2, 2, 2, POW2(M2)); + cxpose(Array2d[M2]+POW2(M2)*2, POW2(M2), data, POW2(M)/2, 1, POW2(M2)); + } + else if (M==2){ + cxpose(data, POW2(M)/2, Array2d[M2], POW2(M2), POW2(M2), 1); + riffts(Array2d[M2], M2, 2); + xpose(Array2d[M2], POW2(M2), Array2d[M2]+POW2(M2)*2, 2, 2, POW2(M2)); + cxpose(Array2d[M2]+POW2(M2)*2, POW2(M2), data, POW2(M)/2, 1, POW2(M2)); + + cxpose(data + 2, POW2(M)/2, Array2d[M2], POW2(M2), POW2(M2), 1); + iffts(Array2d[M2], M2, 1); + cxpose(Array2d[M2], POW2(M2), data + 2, POW2(M)/2, 1, POW2(M2)); + } + else{ + cxpose(data, POW2(M)/2, Array2d[M2], POW2(M2), POW2(M2), 1); + riffts(Array2d[M2], M2, 2); + xpose(Array2d[M2], POW2(M2), Array2d[M2]+POW2(M2)*2, 2, 2, POW2(M2)); + cxpose(Array2d[M2]+POW2(M2)*2, POW2(M2), data, POW2(M)/2, 1, POW2(M2)); + + cxpose(data + 2, POW2(M)/2, Array2d[M2], POW2(M2), POW2(M2), 3); + iffts(Array2d[M2], M2, 3); + cxpose(Array2d[M2], POW2(M2), data + 2, POW2(M)/2, 3, POW2(M2)); + for (i1=4; i1 1) && (N1>1)){ + outdata[0] = data1[0] * data2[0]; // multiply the zero freq, zero wavenumber values + outdata[1] = data1[1] * data2[1]; // multiply the zero freq, nyquest wavenumber values + + cvprod(data1 + 2, data2 + 2, outdata + 2, N/2-1); + + outdata[N] = data1[N] * data2[N]; // multiply the nyquest freq, zero wavenumber values + outdata[N+1] = data1[N+1] * data2[N+1]; // multiply the nyquest freq, nyquest wavenumber values + + cvprod(data1 + N+2, data2 + N+2, outdata + N+2, N/2-1); +} +else{ // really 1D rfft spectra + N = N2 * N1; // one of these is a 1 + if(N>1){ + outdata[0] = data1[0] * data2[0]; // multiply the zero freq values + outdata[1] = data1[1] * data2[1]; // multiply the nyquest freq values + cvprod(data1 + 2, data2 + 2, outdata + 2, N/2-1); // multiply the other positive freq values + } + else{ + outdata[0] = data1[0] * data2[0]; + } +} +} \ No newline at end of file diff --git a/ffts/src/fft2d.h b/ffts/src/fft2d.h new file mode 100644 index 0000000..fd074ff --- /dev/null +++ b/ffts/src/fft2d.h @@ -0,0 +1,114 @@ +/******************************************************************* + This file extends the fftlib with 2d and 3d complex fft's and + 2d real fft's. All fft's return results in-place. Temporary buffers + for transposing columns are maintained privately via calls to + fft2dInit, fft2dFree, fft3dInit, and fft3dFree. + Note that you can call fft2dInit and fft3dInit repeatedly + with the same sizes, the extra calls will be ignored. + So, you could make a macro to call fft2dInit every time you call fft2d. + *** Warning *** fft2dFree and fft3dFree also call fftFree + so you must re-init all 1d fft sizes you are going to continue using +*******************************************************************/ +int fft2dInit(long M2, long M); + // init for fft2d, ifft2d, rfft2d, and rifft2d + // malloc storage for columns of 2d ffts then call fftinit for both row and column ffts sizes +/* INPUTS */ +/* M = log2 of number of columns */ +/* M2 = log2 of number of rows */ +/* of 2d matrix to be fourier transformed */ +/* OUTPUTS */ +/* private storage for columns of 2d ffts */ +/* calls fftInit for cosine and bit reversed tables */ + +void fft2dFree(); +// free storage for columns of all 2d&3d ffts and call fftFree to free all BRLow and Utbl storage + +void fft2d(float *data, long M2, long M); +/* Compute 2D complex fft and return results in-place */ +/* INPUTS */ +/* *data = input data array */ +/* M2 = log2 of fft size number of rows */ +/* M = log2 of fft size number of columns */ +/* OUTPUTS */ +/* *data = output data array */ + +void ifft2d(float *data, long M2, long M); +/* Compute 2D complex ifft and return results in-place */ +/* INPUTS */ +/* *data = input data array */ +/* M2 = log2 of fft size number of rows */ +/* M = log2 of fft size number of columns */ +/* OUTPUTS */ +/* *data = output data array */ + +int fft3dInit(long L, long M2, long M); + // init for fft3d, ifft3d + // malloc storage for 4 columns and 4 pages of 3d ffts + // then call fftinit for page, row and column ffts sizes +/* M = log2 of number of columns */ +/* M2 = log2 of number of rows */ +/* L = log2 of number of pages */ +/* of 3d matrix to be fourier transformed */ +/* OUTPUTS */ +/* private storage for columns and pages of 3d ffts */ +/* calls fftInit for cosine and bit reversed tables */ + +void fft3dFree(); +// free storage for columns of all 2d&3d ffts and call fftFree to free all BRLow and Utbl storage + +void fft3d(float *data, long M3, long M2, long M); +/* Compute 2D complex fft and return results in-place */ +/* INPUTS */ +/* *data = input data array */ +/* M3 = log2 of fft size number of pages */ +/* M2 = log2 of fft size number of rows */ +/* M = log2 of fft size number of columns */ +/* OUTPUTS */ +/* *data = output data array */ + +void ifft3d(float *data, long M3, long M2, long M); +/* Compute 2D complex ifft and return results in-place */ +/* INPUTS */ +/* *data = input data array */ +/* M3 = log2 of fft size number of pages */ +/* M2 = log2 of fft size number of rows */ +/* M = log2 of fft size number of columns */ +/* OUTPUTS */ +/* *data = output data array */ + +void rfft2d(float *data, long M2, long M); +/* Compute 2D real fft and return results in-place */ +/* First performs real fft on rows using size from M to compute positive frequencies */ +/* then performs transform on columns using size from M2 to compute wavenumbers */ +/* If you think of the result as a complex pow(2,M2) by pow(2,M-1) matrix */ +/* then the first column contains the positive wavenumber spectra of DC frequency */ +/* followed by the positive wavenumber spectra of the nyquest frequency */ +/* since these are two positive wavenumber spectra the first complex value */ +/* of each is really the real values for the zero and nyquest wavenumber packed together */ +/* All other columns contain the positive and negative wavenumber spectra of a positive frequency */ +/* See rspect2dprod for multiplying two of these spectra together- ex. for fast convolution */ +/* INPUTS */ +/* *data = input data array */ +/* M2 = log2 of fft size number of rows in */ +/* M = log2 of fft size number of columns in */ +/* OUTPUTS */ +/* *data = output data array */ + +void rifft2d(float *data, long M2, long M); +/* Compute 2D real ifft and return results in-place */ +/* The input must be in the order as outout from rfft2d */ +/* INPUTS */ +/* *data = input data array */ +/* M2 = log2 of fft size number of rows out */ +/* M = log2 of fft size number of columns out */ +/* OUTPUTS */ +/* *data = output data array */ + +void rspect2dprod(float *data1, float *data2, float *outdata, long N2, long N1); +// When multiplying a pair of 2d spectra from rfft2d care must be taken to multiply the +// four real values seperately from the complex ones. This routine does it correctly. +// the result can be stored in-place over one of the inputs +/* *data1 = input data array first spectra */ +/* *data2 = input data array second spectra */ +/* N2 = fft size number of rows into rfft2d for both data1 and data2 */ +/* N1 = fft size number of columns into rfft2d for both data1 and data2 */ diff --git a/ffts/src/fftext.c b/ffts/src/fftext.c new file mode 100644 index 0000000..a39911c --- /dev/null +++ b/ffts/src/fftext.c @@ -0,0 +1,156 @@ +/******************************************************************* + This file extends the fftlib with calls to maintain the cosine and bit reversed tables + for you (including mallocs and free's). Call the init routine for each fft size you will + be using. Then you can call the fft routines below which will make the fftlib library + call with the appropriate tables passed. When you are done with all fft's you can call + fftfree to release the storage for the tables. Note that you can call fftinit repeatedly + with the same size, the extra calls will be ignored. So, you could make a macro to call + fftInit every time you call ffts. For example you could have someting like: + #define FFT(a,n) if(!fftInit(roundtol(LOG2(n)))) ffts(a,roundtol(LOG2(n)),1);else printf("fft error\n"); +*******************************************************************/ +#include +#include "fftlib.h" +#include "matlib.h" +#include "fftext.h" + +// pointers to storage of Utbl's and BRLow's +static float *UtblArray[8*sizeof(long)] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; +static short *BRLowArray[8*sizeof(long)/2] = {0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; + +int fftInit(long M){ +// malloc and init cosine and bit reversed tables for a given size fft, ifft, rfft, rifft +/* INPUTS */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* OUTPUTS */ +/* private cosine and bit reversed tables */ + +int theError = 1; +/*** I did NOT test cases with M>27 ***/ +if ((M >= 0) && (M < 8*sizeof(long))){ + theError = 0; + if (UtblArray[M] == 0){ // have we not inited this size fft yet? + // init cos table + UtblArray[M] = (float *) malloc( (POW2(M)/4+1)*sizeof(float) ); + if (UtblArray[M] == 0) + theError = 2; + else{ + fftCosInit(M, UtblArray[M]); + } + if (M > 1){ + if (BRLowArray[M/2] == 0){ // init bit reversed table for cmplx fft + BRLowArray[M/2] = (short *) malloc( POW2(M/2-1)*sizeof(short) ); + if (BRLowArray[M/2] == 0) + theError = 2; + else{ + fftBRInit(M, BRLowArray[M/2]); + } + } + } + if (M > 2){ + if (BRLowArray[(M-1)/2] == 0){ // init bit reversed table for real fft + BRLowArray[(M-1)/2] = (short *) malloc( POW2((M-1)/2-1)*sizeof(short) ); + if (BRLowArray[(M-1)/2] == 0) + theError = 2; + else{ + fftBRInit(M-1, BRLowArray[(M-1)/2]); + } + } + } + } +}; +return theError; +} + +void fftFree(){ +// release storage for all private cosine and bit reversed tables +long i1; +for (i1=8*sizeof(long)/2-1; i1>=0; i1--){ + if (BRLowArray[i1] != 0){ + free(BRLowArray[i1]); + BRLowArray[i1] = 0; + }; +}; +for (i1=8*sizeof(long)-1; i1>=0; i1--){ + if (UtblArray[i1] != 0){ + free(UtblArray[i1]); + UtblArray[i1] = 0; + }; +}; +} + +/************************************************* + The following calls are easier than calling to fftlib directly. + Just make sure fftlib has been called for each M first. +**************************************************/ + +void ffts(float *data, long M, long Rows){ +/* Compute in-place complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = output data array */ + ffts1(data, M, Rows, UtblArray[M], BRLowArray[M/2]); +} + +void iffts(float *data, long M, long Rows){ +/* Compute in-place inverse complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = output data array */ + iffts1(data, M, Rows, UtblArray[M], BRLowArray[M/2]); +} + +void rffts(float *data, long M, long Rows){ +/* Compute in-place real fft on the rows of the input array */ +/* The result is the complex spectra of the positive frequencies */ +/* except the location for the first complex number contains the real */ +/* values for DC and Nyquest */ +/* See rspectprod for multiplying two of these spectra together- ex. for fast convolution */ +/* INPUTS */ +/* *ioptr = real input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = output data array in the following order */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ + rffts1(data, M, Rows, UtblArray[M], BRLowArray[(M-1)/2]); +} + +void riffts(float *data, long M, long Rows){ +/* Compute in-place real ifft on the rows of the input array */ +/* data order as from rffts */ +/* INPUTS */ +/* *ioptr = input data array in the following order */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = real output data array */ + riffts1(data, M, Rows, UtblArray[M], BRLowArray[(M-1)/2]); +} + +void rspectprod(float *data1, float *data2, float *outdata, long N){ +// When multiplying a pair of spectra from rfft care must be taken to multiply the +// two real values seperately from the complex ones. This routine does it correctly. +// the result can be stored in-place over one of the inputs +/* INPUTS */ +/* *data1 = input data array first spectra */ +/* *data2 = input data array second spectra */ +/* N = fft input size for both data1 and data2 */ +/* OUTPUTS */ +/* *outdata = output data array spectra */ +if(N>1){ + outdata[0] = data1[0] * data2[0]; // multiply the zero freq values + outdata[1] = data1[1] * data2[1]; // multiply the nyquest freq values + cvprod(data1 + 2, data2 + 2, outdata + 2, N/2-1); // multiply the other positive freq values +} +else{ + outdata[0] = data1[0] * data2[0]; +} +} diff --git a/ffts/src/fftext.h b/ffts/src/fftext.h new file mode 100644 index 0000000..15d8a6b --- /dev/null +++ b/ffts/src/fftext.h @@ -0,0 +1,106 @@ +/******************************************************************* + This file extends the fftlib with calls to maintain the cosine and bit reversed tables + for you (including mallocs and free's). Call the init routine for each fft size you will + be using. Then you can call the fft routines below which will make the fftlib library + call with the appropriate tables passed. When you are done with all fft's you can call + fftfree to release the storage for the tables. Note that you can call fftinit repeatedly + with the same size, the extra calls will be ignored. So, you could make a macro to call + fftInit every time you call ffts. For example you could have someting like: + #define FFT(a,n) if(!fftInit(roundtol(LOG2(n)))) ffts(a,roundtol(LOG2(n)),1);else printf("fft error\n"); +*******************************************************************/ + +int fftInit(long M); +// malloc and init cosine and bit reversed tables for a given size fft, ifft, rfft, rifft +/* INPUTS */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* OUTPUTS */ +/* private cosine and bit reversed tables */ + +void fftFree(); +// release storage for all private cosine and bit reversed tables + +void ffts(float *data, long M, long Rows); +/* Compute in-place complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = output data array */ + +void iffts(float *data, long M, long Rows); +/* Compute in-place inverse complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = output data array */ + +void rffts(float *data, long M, long Rows); +/* Compute in-place real fft on the rows of the input array */ +/* The result is the complex spectra of the positive frequencies */ +/* except the location for the first complex number contains the real */ +/* values for DC and Nyquest */ +/* See rspectprod for multiplying two of these spectra together- ex. for fast convolution */ +/* INPUTS */ +/* *ioptr = real input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = output data array in the following order */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ + +void riffts(float *data, long M, long Rows); +/* Compute in-place real ifft on the rows of the input array */ +/* data order as from rffts */ +/* INPUTS */ +/* *ioptr = input data array in the following order */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ +/* Rows = number of rows in ioptr array (use 1 for Rows for a single fft) */ +/* OUTPUTS */ +/* *ioptr = real output data array */ + +void rspectprod(float *data1, float *data2, float *outdata, long N); +// When multiplying a pair of spectra from rfft care must be taken to multiply the +// two real values seperately from the complex ones. This routine does it correctly. +// the result can be stored in-place over one of the inputs +/* INPUTS */ +/* *data1 = input data array first spectra */ +/* *data2 = input data array second spectra */ +/* N = fft input size for both data1 and data2 */ +/* OUTPUTS */ +/* *outdata = output data array spectra */ + + +// The following is FYI + + +//Note that most of the fft routines require full matrices, ie Rsiz==Ncols +//This is how I like to define a real matrix: +//struct matrix { // real matrix +// float *d; // pointer to data +// long Nrows; // number of rows in the matrix +// long Ncols; // number of columns in the matrix (can be less than Rsiz) +// long Rsiz; // number of floats from one row to the next +//}; +//typedef struct matrix matrix; + + + +// CACHEFILLMALLOC and CEILCACHELINE can be used instead of malloc to make +// arrays that start exactly on a cache line start. +// First we CACHEFILLMALLOC a void * (use this void * when free'ing), +// then we set our array pointer equal to the properly cast CEILCACHELINE of this void * +// example: +// aInit = CACHEFILLMALLOC( NUMFLOATS*sizeof(float) ); +// a = (float *) CEILCACHELINE(ainit); +// ... main body of code ... +// free(aInit); +// +// To disable this alignment, set CACHELINESIZE to 1 +//#define CACHELINESIZE 32 // Bytes per cache line +//#define CACHELINEFILL (CACHELINESIZE-1) +//#define CEILCACHELINE(p) ((((unsigned long)p+CACHELINEFILL)/CACHELINESIZE)*CACHELINESIZE) +//#define CACHEFILLMALLOC(n) malloc((n)+CACHELINEFILL) diff --git a/ffts/src/fftlib.c b/ffts/src/fftlib.c new file mode 100644 index 0000000..d832f89 --- /dev/null +++ b/ffts/src/fftlib.c @@ -0,0 +1,3174 @@ +/******************************************************************* +lower level fft stuff including routines called in fftext.c and fft2d.c +*******************************************************************/ +#include "fftlib.h" +#include +#define MCACHE (11-(sizeof(float)/8)) // fft's with M bigger than this bust primary cache +#ifdef WIN32 +#define inline __inline +#endif + +// some math constants to 40 decimal places +#define MYPI 3.141592653589793238462643383279502884197 // pi +#define MYROOT2 1.414213562373095048801688724209698078569 // sqrt(2) +#define MYCOSPID8 0.9238795325112867561281831893967882868224 // cos(pi/8) +#define MYSINPID8 0.3826834323650897717284599840303988667613 // sin(pi/8) + + +/************************************************* +routines to initialize tables used by fft routines +**************************************************/ + +void fftCosInit(long M, float *Utbl){ +/* Compute Utbl, the cosine table for ffts */ +/* of size (pow(2,M)/4 +1) */ +/* INPUTS */ +/* M = log2 of fft size */ +/* OUTPUTS */ +/* *Utbl = cosine table */ +unsigned long fftN = POW2(M); +unsigned long i1; + Utbl[0] = 1.0; + for (i1 = 1; i1 < fftN/4; i1++) + Utbl[i1] = cos( (2.0 * MYPI * i1) / fftN ); + Utbl[fftN/4] = 0.0; +} + +void fftBRInit(long M, short *BRLow){ +/* Compute BRLow, the bit reversed table for ffts */ +/* of size pow(2,M/2 -1) */ +/* INPUTS */ +/* M = log2 of fft size */ +/* OUTPUTS */ +/* *BRLow = bit reversed counter table */ +long Mroot_1 = M / 2 - 1; +long Nroot_1 = POW2(Mroot_1); +long i1; +long bitsum; +long bitmask; +long bit; +for (i1 = 0; i1 < Nroot_1; i1++){ + bitsum = 0; + bitmask = 1; + for (bit=1; bit <= Mroot_1; bitmask<<=1, bit++) + if (i1 & bitmask) + bitsum = bitsum + (Nroot_1 >> bit); + BRLow[i1] = bitsum; +}; +} + +/************************************************ +parts of ffts1 +*************************************************/ + +inline void bitrevR2(float *ioptr, long M, short *BRLow); +inline void bitrevR2(float *ioptr, long M, short *BRLow){ +/*** bit reverse and first radix 2 stage of forward or inverse fft ***/ +float f0r; +float f0i; +float f1r; +float f1i; +float f2r; +float f2i; +float f3r; +float f3i; +float f4r; +float f4i; +float f5r; +float f5i; +float f6r; +float f6i; +float f7r; +float f7i; +float t0r; +float t0i; +float t1r; +float t1i; +float *p0r; +float *p1r; +float *IOP; +float *iolimit; +long Colstart; +long iCol; +unsigned long posA; +unsigned long posAi; +unsigned long posB; +unsigned long posBi; + +const unsigned long Nrems2 = POW2((M+3)/2); +const unsigned long Nroot_1_ColInc = POW2(M)-Nrems2; +const unsigned long Nroot_1 = POW2(M/2-1)-1; +const unsigned long ColstartShift = (M+1)/2 +1; +posA = POW2(M); // 1/2 of POW2(M) complexes +posAi = posA + 1; +posB = posA + 2; +posBi = posB + 1; + +iolimit = ioptr + Nrems2; +for (; ioptr < iolimit; ioptr += POW2(M/2+1)){ + for (Colstart = Nroot_1; Colstart >= 0; Colstart--){ + iCol = Nroot_1; + p0r = ioptr+ Nroot_1_ColInc + BRLow[Colstart]*4; + IOP = ioptr + (Colstart << ColstartShift); + p1r = IOP + BRLow[iCol]*4; + f0r = *(p0r); + f0i = *(p0r+1); + f1r = *(p0r+posA); + f1i = *(p0r+posAi); + for (; iCol > Colstart;){ + f2r = *(p0r+2); + f2i = *(p0r+(2+1)); + f3r = *(p0r+posB); + f3i = *(p0r+posBi); + f4r = *(p1r); + f4i = *(p1r+1); + f5r = *(p1r+posA); + f5i = *(p1r+posAi); + f6r = *(p1r+2); + f6i = *(p1r+(2+1)); + f7r = *(p1r+posB); + f7i = *(p1r+posBi); + + t0r = f0r + f1r; + t0i = f0i + f1i; + f1r = f0r - f1r; + f1i = f0i - f1i; + t1r = f2r + f3r; + t1i = f2i + f3i; + f3r = f2r - f3r; + f3i = f2i - f3i; + f0r = f4r + f5r; + f0i = f4i + f5i; + f5r = f4r - f5r; + f5i = f4i - f5i; + f2r = f6r + f7r; + f2i = f6i + f7i; + f7r = f6r - f7r; + f7i = f6i - f7i; + + *(p1r) = t0r; + *(p1r+1) = t0i; + *(p1r+2) = f1r; + *(p1r+(2+1)) = f1i; + *(p1r+posA) = t1r; + *(p1r+posAi) = t1i; + *(p1r+posB) = f3r; + *(p1r+posBi) = f3i; + *(p0r) = f0r; + *(p0r+1) = f0i; + *(p0r+2) = f5r; + *(p0r+(2+1)) = f5i; + *(p0r+posA) = f2r; + *(p0r+posAi) = f2i; + *(p0r+posB) = f7r; + *(p0r+posBi) = f7i; + + p0r -= Nrems2; + f0r = *(p0r); + f0i = *(p0r+1); + f1r = *(p0r+posA); + f1i = *(p0r+posAi); + iCol -= 1; + p1r = IOP + BRLow[iCol]*4; + }; + f2r = *(p0r+2); + f2i = *(p0r+(2+1)); + f3r = *(p0r+posB); + f3i = *(p0r+posBi); + + t0r = f0r + f1r; + t0i = f0i + f1i; + f1r = f0r - f1r; + f1i = f0i - f1i; + t1r = f2r + f3r; + t1i = f2i + f3i; + f3r = f2r - f3r; + f3i = f2i - f3i; + + *(p0r) = t0r; + *(p0r+1) = t0i; + *(p0r+2) = f1r; + *(p0r+(2+1)) = f1i; + *(p0r+posA) = t1r; + *(p0r+posAi) = t1i; + *(p0r+posB) = f3r; + *(p0r+posBi) = f3i; + + }; +}; +} + +inline void fft2pt(float *ioptr); +inline void fft2pt(float *ioptr){ +/*** RADIX 2 fft ***/ +float f0r, f0i, f1r, f1i; +float t0r, t0i; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[2]; +f1i = ioptr[3]; + + /* Butterflys */ + /* + f0 - - t0 + f1 - 1 - f1 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + + /* store result */ +ioptr[0] = t0r; +ioptr[1] = t0i; +ioptr[2] = f1r; +ioptr[3] = f1i; +} + + +inline void fft4pt(float *ioptr); +inline void fft4pt(float *ioptr){ +/*** RADIX 4 fft ***/ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float t0r, t0i, t1r, t1i; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[4]; +f1i = ioptr[5]; +f2r = ioptr[2]; +f2i = ioptr[3]; +f3r = ioptr[6]; +f3i = ioptr[7]; + + /* Butterflys */ + /* + f0 - - t0 - - f0 + f1 - 1 - f1 - - f1 + f2 - - f2 - 1 - f2 + f3 - 1 - t1 - -i - f3 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = t0i - f2i; + +f3r = f1r - t1i; +f3i = f1i + t1r; +f1r = f1r + t1i; +f1i = f1i - t1r; + + /* store result */ +ioptr[0] = f0r; +ioptr[1] = f0i; +ioptr[2] = f1r; +ioptr[3] = f1i; +ioptr[4] = f2r; +ioptr[5] = f2i; +ioptr[6] = f3r; +ioptr[7] = f3i; +} + +inline void fft8pt(float *ioptr); +inline void fft8pt(float *ioptr){ +/*** RADIX 8 fft ***/ +float w0r = 1.0/MYROOT2; /* cos(pi/4) */ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[8]; +f1i = ioptr[9]; +f2r = ioptr[4]; +f2i = ioptr[5]; +f3r = ioptr[12]; +f3i = ioptr[13]; +f4r = ioptr[2]; +f4i = ioptr[3]; +f5r = ioptr[10]; +f5i = ioptr[11]; +f6r = ioptr[6]; +f6i = ioptr[7]; +f7r = ioptr[14]; +f7i = ioptr[15]; + /* Butterflys */ + /* + f0 - - t0 - - f0 - - f0 + f1 - 1 - f1 - - f1 - - f1 + f2 - - f2 - 1 - f2 - - f2 + f3 - 1 - t1 - -i - f3 - - f3 + f4 - - t0 - - f4 - 1 - t0 + f5 - 1 - f5 - - f5 - w3 - f4 + f6 - - f6 - 1 - f6 - -i - t1 + f7 - 1 - t1 - -i - f7 - iw3- f6 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = t0i - f2i; + +f3r = f1r - t1i; +f3i = f1i + t1r; +f1r = f1r + t1i; +f1i = f1i - t1r; + + +t0r = f4r + f5r; +t0i = f4i + f5i; +f5r = f4r - f5r; +f5i = f4i - f5i; + +t1r = f6r - f7r; +t1i = f6i - f7i; +f6r = f6r + f7r; +f6i = f6i + f7i; + +f4r = t0r + f6r; +f4i = t0i + f6i; +f6r = t0r - f6r; +f6i = t0i - f6i; + +f7r = f5r - t1i; +f7i = f5i + t1r; +f5r = f5r + t1i; +f5i = f5i - t1r; + + +t0r = f0r - f4r; +t0i = f0i - f4i; +f0r = f0r + f4r; +f0i = f0i + f4i; + +t1r = f2r - f6i; +t1i = f2i + f6r; +f2r = f2r + f6i; +f2i = f2i - f6r; + +f4r = f1r - f5r * w0r - f5i * w0r; +f4i = f1i + f5r * w0r - f5i * w0r; +f1r = f1r * Two - f4r; +f1i = f1i * Two - f4i; + +f6r = f3r + f7r * w0r - f7i * w0r; +f6i = f3i + f7r * w0r + f7i * w0r; +f3r = f3r * Two - f6r; +f3i = f3i * Two - f6i; + + /* store result */ +ioptr[0] = f0r; +ioptr[1] = f0i; +ioptr[2] = f1r; +ioptr[3] = f1i; +ioptr[4] = f2r; +ioptr[5] = f2i; +ioptr[6] = f3r; +ioptr[7] = f3i; +ioptr[8] = t0r; +ioptr[9] = t0i; +ioptr[10] = f4r; +ioptr[11] = f4i; +ioptr[12] = t1r; +ioptr[13] = t1i; +ioptr[14] = f6r; +ioptr[15] = f6i; +} + +inline void bfR2(float *ioptr, long M, long NDiffU); +inline void bfR2(float *ioptr, long M, long NDiffU){ +/*** 2nd radix 2 stage ***/ +unsigned long pos; +unsigned long posi; +unsigned long pinc; +unsigned long pnext; +unsigned long NSameU; +unsigned long SameUCnt; + +float *pstrt; +float *p0r, *p1r, *p2r, *p3r; + +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +const float Two = 2.0; + +pinc = NDiffU * 2; // 2 floats per complex +pnext = pinc * 4; +pos = 2; +posi = pos+1; +NSameU = POW2(M) / 4 /NDiffU; // 4 Us at a time +pstrt = ioptr; +p0r = pstrt; +p1r = pstrt+pinc; +p2r = p1r+pinc; +p3r = p2r+pinc; + + /* Butterflys */ + /* + f0 - - f4 + f1 - 1 - f5 + f2 - - f6 + f3 - 1 - f7 + */ + /* Butterflys */ + /* + f0 - - f4 + f1 - 1 - f5 + f2 - - f6 + f3 - 1 - f7 + */ + +for (SameUCnt = NSameU; SameUCnt > 0 ; SameUCnt--){ + + f0r = *p0r; + f1r = *p1r; + f0i = *(p0r + 1); + f1i = *(p1r + 1); + f2r = *p2r; + f3r = *p3r; + f2i = *(p2r + 1); + f3i = *(p3r + 1); + + f4r = f0r + f1r; + f4i = f0i + f1i; + f5r = f0r - f1r; + f5i = f0i - f1i; + + f6r = f2r + f3r; + f6i = f2i + f3i; + f7r = f2r - f3r; + f7i = f2i - f3i; + + *p0r = f4r; + *(p0r + 1) = f4i; + *p1r = f5r; + *(p1r + 1) = f5i; + *p2r = f6r; + *(p2r + 1) = f6i; + *p3r = f7r; + *(p3r + 1) = f7i; + + f0r = *(p0r + pos); + f1i = *(p1r + posi); + f0i = *(p0r + posi); + f1r = *(p1r + pos); + f2r = *(p2r + pos); + f3i = *(p3r + posi); + f2i = *(p2r + posi); + f3r = *(p3r + pos); + + f4r = f0r + f1i; + f4i = f0i - f1r; + f5r = f0r - f1i; + f5i = f0i + f1r; + + f6r = f2r + f3i; + f6i = f2i - f3r; + f7r = f2r - f3i; + f7i = f2i + f3r; + + *(p0r + pos) = f4r; + *(p0r + posi) = f4i; + *(p1r + pos) = f5r; + *(p1r + posi) = f5i; + *(p2r + pos) = f6r; + *(p2r + posi) = f6i; + *(p3r + pos) = f7r; + *(p3r + posi) = f7i; + + p0r += pnext; + p1r += pnext; + p2r += pnext; + p3r += pnext; + +} +} + +inline void bfR4(float *ioptr, long M, long NDiffU); +inline void bfR4(float *ioptr, long M, long NDiffU){ +/*** 1 radix 4 stage ***/ +unsigned long pos; +unsigned long posi; +unsigned long pinc; +unsigned long pnext; +unsigned long pnexti; +unsigned long NSameU; +unsigned long SameUCnt; + +float *pstrt; +float *p0r, *p1r, *p2r, *p3r; + +float w1r = 1.0/MYROOT2; /* cos(pi/4) */ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t1r, t1i; +const float Two = 2.0; + +pinc = NDiffU * 2; // 2 floats per complex +pnext = pinc * 4; +pnexti = pnext + 1; +pos = 2; +posi = pos+1; +NSameU = POW2(M) / 4 /NDiffU; // 4 pts per butterfly +pstrt = ioptr; +p0r = pstrt; +p1r = pstrt+pinc; +p2r = p1r+pinc; +p3r = p2r+pinc; + + /* Butterflys */ + /* + f0 - - f0 - - f4 + f1 - 1 - f5 - - f5 + f2 - - f6 - 1 - f6 + f3 - 1 - f3 - -i - f7 + */ + /* Butterflys */ + /* + f0 - - f4 - - f4 + f1 - -i - t1 - - f5 + f2 - - f2 - w1 - f6 + f3 - -i - f7 - iw1- f7 + */ + +f0r = *p0r; +f1r = *p1r; +f2r = *p2r; +f3r = *p3r; +f0i = *(p0r + 1); +f1i = *(p1r + 1); +f2i = *(p2r + 1); +f3i = *(p3r + 1); + +f5r = f0r - f1r; +f5i = f0i - f1i; +f0r = f0r + f1r; +f0i = f0i + f1i; + +f6r = f2r + f3r; +f6i = f2i + f3i; +f3r = f2r - f3r; +f3i = f2i - f3i; + +for (SameUCnt = NSameU-1; SameUCnt > 0 ; SameUCnt--){ + + f7r = f5r - f3i; + f7i = f5i + f3r; + f5r = f5r + f3i; + f5i = f5i - f3r; + + f4r = f0r + f6r; + f4i = f0i + f6i; + f6r = f0r - f6r; + f6i = f0i - f6i; + + f2r = *(p2r + pos); + f2i = *(p2r + posi); + f1r = *(p1r + pos); + f1i = *(p1r + posi); + f3i = *(p3r + posi); + f0r = *(p0r + pos); + f3r = *(p3r + pos); + f0i = *(p0r + posi); + + *p3r = f7r; + *p0r = f4r; + *(p3r + 1) = f7i; + *(p0r + 1) = f4i; + *p1r = f5r; + *p2r = f6r; + *(p1r + 1) = f5i; + *(p2r + 1) = f6i; + + f7r = f2r - f3i; + f7i = f2i + f3r; + f2r = f2r + f3i; + f2i = f2i - f3r; + + f4r = f0r + f1i; + f4i = f0i - f1r; + t1r = f0r - f1i; + t1i = f0i + f1r; + + f5r = t1r - f7r * w1r + f7i * w1r; + f5i = t1i - f7r * w1r - f7i * w1r; + f7r = t1r * Two - f5r; + f7i = t1i * Two - f5i; + + f6r = f4r - f2r * w1r - f2i * w1r; + f6i = f4i + f2r * w1r - f2i * w1r; + f4r = f4r * Two - f6r; + f4i = f4i * Two - f6i; + + f3r = *(p3r + pnext); + f0r = *(p0r + pnext); + f3i = *(p3r + pnexti); + f0i = *(p0r + pnexti); + f2r = *(p2r + pnext); + f2i = *(p2r + pnexti); + f1r = *(p1r + pnext); + f1i = *(p1r + pnexti); + + *(p2r + pos) = f6r; + *(p1r + pos) = f5r; + *(p2r + posi) = f6i; + *(p1r + posi) = f5i; + *(p3r + pos) = f7r; + *(p0r + pos) = f4r; + *(p3r + posi) = f7i; + *(p0r + posi) = f4i; + + f6r = f2r + f3r; + f6i = f2i + f3i; + f3r = f2r - f3r; + f3i = f2i - f3i; + + f5r = f0r - f1r; + f5i = f0i - f1i; + f0r = f0r + f1r; + f0i = f0i + f1i; + + p3r += pnext; + p0r += pnext; + p1r += pnext; + p2r += pnext; + +} +f7r = f5r - f3i; +f7i = f5i + f3r; +f5r = f5r + f3i; +f5i = f5i - f3r; + +f4r = f0r + f6r; +f4i = f0i + f6i; +f6r = f0r - f6r; +f6i = f0i - f6i; + +f2r = *(p2r + pos); +f2i = *(p2r + posi); +f1r = *(p1r + pos); +f1i = *(p1r + posi); +f3i = *(p3r + posi); +f0r = *(p0r + pos); +f3r = *(p3r + pos); +f0i = *(p0r + posi); + +*p3r = f7r; +*p0r = f4r; +*(p3r + 1) = f7i; +*(p0r + 1) = f4i; +*p1r = f5r; +*p2r = f6r; +*(p1r + 1) = f5i; +*(p2r + 1) = f6i; + +f7r = f2r - f3i; +f7i = f2i + f3r; +f2r = f2r + f3i; +f2i = f2i - f3r; + +f4r = f0r + f1i; +f4i = f0i - f1r; +t1r = f0r - f1i; +t1i = f0i + f1r; + +f5r = t1r - f7r * w1r + f7i * w1r; +f5i = t1i - f7r * w1r - f7i * w1r; +f7r = t1r * Two - f5r; +f7i = t1i * Two - f5i; + +f6r = f4r - f2r * w1r - f2i * w1r; +f6i = f4i + f2r * w1r - f2i * w1r; +f4r = f4r * Two - f6r; +f4i = f4i * Two - f6i; + +*(p2r + pos) = f6r; +*(p1r + pos) = f5r; +*(p2r + posi) = f6i; +*(p1r + posi) = f5i; +*(p3r + pos) = f7r; +*(p0r + pos) = f4r; +*(p3r + posi) = f7i; +*(p0r + posi) = f4i; + +} + +inline void bfstages(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt); +inline void bfstages(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt){ +/*** RADIX 8 Stages ***/ +unsigned long pos; +unsigned long posi; +unsigned long pinc; +unsigned long pnext; +unsigned long NSameU; +unsigned long Uinc; +unsigned long Uinc2; +unsigned long Uinc4; +unsigned long DiffUCnt; +unsigned long SameUCnt; +unsigned long U2toU3; + +float *pstrt; +float *p0r, *p1r, *p2r, *p3r; +float *u0r, *u0i, *u1r, *u1i, *u2r, *u2i; + +float w0r, w0i, w1r, w1i, w2r, w2i, w3r, w3i; +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; + +pinc = NDiffU * 2; // 2 floats per complex +pnext = pinc * 8; +pos = pinc * 4; +posi = pos + 1; +NSameU = POW2(M) / 8 /NDiffU; // 8 pts per butterfly +Uinc = NSameU * Ustride; +Uinc2 = Uinc * 2; +Uinc4 = Uinc * 4; +U2toU3 = (POW2(M) / 8)*Ustride; +for (; StageCnt > 0 ; StageCnt--){ + + u0r = &Utbl[0]; + u0i = &Utbl[POW2(M-2)*Ustride]; + u1r = u0r; + u1i = u0i; + u2r = u0r; + u2i = u0i; + + w0r = *u0r; + w0i = *u0i; + w1r = *u1r; + w1i = *u1i; + w2r = *u2r; + w2i = *u2i; + w3r = *(u2r+U2toU3); + w3i = *(u2i-U2toU3); + + pstrt = ioptr; + + p0r = pstrt; + p1r = pstrt+pinc; + p2r = p1r+pinc; + p3r = p2r+pinc; + + /* Butterflys */ + /* + f0 - - t0 - - f0 - - f0 + f1 - w0- f1 - - f1 - - f1 + f2 - - f2 - w1- f2 - - f4 + f3 - w0- t1 - iw1- f3 - - f5 + + f4 - - t0 - - f4 - w2- t0 + f5 - w0- f5 - - f5 - w3- t1 + f6 - - f6 - w1- f6 - iw2- f6 + f7 - w0- t1 - iw1- f7 - iw3- f7 + */ + + for (DiffUCnt = NDiffU; DiffUCnt > 0 ; DiffUCnt--){ + f0r = *p0r; + f0i = *(p0r + 1); + f1r = *p1r; + f1i = *(p1r + 1); + for (SameUCnt = NSameU-1; SameUCnt > 0 ; SameUCnt--){ + f2r = *p2r; + f2i = *(p2r + 1); + f3r = *p3r; + f3i = *(p3r + 1); + + t0r = f0r + f1r * w0r + f1i * w0i; + t0i = f0i - f1r * w0i + f1i * w0r; + f1r = f0r * Two - t0r; + f1i = f0i * Two - t0i; + + f4r = *(p0r + pos); + f4i = *(p0r + posi); + f5r = *(p1r + pos); + f5i = *(p1r + posi); + + f6r = *(p2r + pos); + f6i = *(p2r + posi); + f7r = *(p3r + pos); + f7i = *(p3r + posi); + + t1r = f2r - f3r * w0r - f3i * w0i; + t1i = f2i + f3r * w0i - f3i * w0r; + f2r = f2r * Two - t1r; + f2i = f2i * Two - t1i; + + f0r = t0r + f2r * w1r + f2i * w1i; + f0i = t0i - f2r * w1i + f2i * w1r; + f2r = t0r * Two - f0r; + f2i = t0i * Two - f0i; + + f3r = f1r + t1r * w1i - t1i * w1r; + f3i = f1i + t1r * w1r + t1i * w1i; + f1r = f1r * Two - f3r; + f1i = f1i * Two - f3i; + + + t0r = f4r + f5r * w0r + f5i * w0i; + t0i = f4i - f5r * w0i + f5i * w0r; + f5r = f4r * Two - t0r; + f5i = f4i * Two - t0i; + + t1r = f6r - f7r * w0r - f7i * w0i; + t1i = f6i + f7r * w0i - f7i * w0r; + f6r = f6r * Two - t1r; + f6i = f6i * Two - t1i; + + f4r = t0r + f6r * w1r + f6i * w1i; + f4i = t0i - f6r * w1i + f6i * w1r; + f6r = t0r * Two - f4r; + f6i = t0i * Two - f4i; + + f7r = f5r + t1r * w1i - t1i * w1r; + f7i = f5i + t1r * w1r + t1i * w1i; + f5r = f5r * Two - f7r; + f5i = f5i * Two - f7i; + + t0r = f0r - f4r * w2r - f4i * w2i; + t0i = f0i + f4r * w2i - f4i * w2r; + f0r = f0r * Two - t0r; + f0i = f0i * Two - t0i; + + t1r = f1r - f5r * w3r - f5i * w3i; + t1i = f1i + f5r * w3i - f5i * w3r; + f1r = f1r * Two - t1r; + f1i = f1i * Two - t1i; + + *(p0r + pos) = t0r; + *(p1r + pos) = t1r; + *(p0r + posi) = t0i; + *(p1r + posi) = t1i; + *p0r = f0r; + *p1r = f1r; + *(p0r + 1) = f0i; + *(p1r + 1) = f1i; + + p0r += pnext; + f0r = *p0r; + f0i = *(p0r + 1); + + p1r += pnext; + + f1r = *p1r; + f1i = *(p1r + 1); + + f4r = f2r - f6r * w2i + f6i * w2r; + f4i = f2i - f6r * w2r - f6i * w2i; + f6r = f2r * Two - f4r; + f6i = f2i * Two - f4i; + + f5r = f3r - f7r * w3i + f7i * w3r; + f5i = f3i - f7r * w3r - f7i * w3i; + f7r = f3r * Two - f5r; + f7i = f3i * Two - f5i; + + *p2r = f4r; + *p3r = f5r; + *(p2r + 1) = f4i; + *(p3r + 1) = f5i; + *(p2r + pos) = f6r; + *(p3r + pos) = f7r; + *(p2r + posi) = f6i; + *(p3r + posi) = f7i; + + p2r += pnext; + p3r += pnext; + + } + + f2r = *p2r; + f2i = *(p2r + 1); + f3r = *p3r; + f3i = *(p3r + 1); + + t0r = f0r + f1r * w0r + f1i * w0i; + t0i = f0i - f1r * w0i + f1i * w0r; + f1r = f0r * Two - t0r; + f1i = f0i * Two - t0i; + + f4r = *(p0r + pos); + f4i = *(p0r + posi); + f5r = *(p1r + pos); + f5i = *(p1r + posi); + + f6r = *(p2r + pos); + f6i = *(p2r + posi); + f7r = *(p3r + pos); + f7i = *(p3r + posi); + + t1r = f2r - f3r * w0r - f3i * w0i; + t1i = f2i + f3r * w0i - f3i * w0r; + f2r = f2r * Two - t1r; + f2i = f2i * Two - t1i; + + f0r = t0r + f2r * w1r + f2i * w1i; + f0i = t0i - f2r * w1i + f2i * w1r; + f2r = t0r * Two - f0r; + f2i = t0i * Two - f0i; + + f3r = f1r + t1r * w1i - t1i * w1r; + f3i = f1i + t1r * w1r + t1i * w1i; + f1r = f1r * Two - f3r; + f1i = f1i * Two - f3i; + + if (DiffUCnt == NDiffU/2) + Uinc4 = -Uinc4; + + u0r += Uinc4; + u0i -= Uinc4; + u1r += Uinc2; + u1i -= Uinc2; + u2r += Uinc; + u2i -= Uinc; + + pstrt += 2; + + t0r = f4r + f5r * w0r + f5i * w0i; + t0i = f4i - f5r * w0i + f5i * w0r; + f5r = f4r * Two - t0r; + f5i = f4i * Two - t0i; + + t1r = f6r - f7r * w0r - f7i * w0i; + t1i = f6i + f7r * w0i - f7i * w0r; + f6r = f6r * Two - t1r; + f6i = f6i * Two - t1i; + + f4r = t0r + f6r * w1r + f6i * w1i; + f4i = t0i - f6r * w1i + f6i * w1r; + f6r = t0r * Two - f4r; + f6i = t0i * Two - f4i; + + f7r = f5r + t1r * w1i - t1i * w1r; + f7i = f5i + t1r * w1r + t1i * w1i; + f5r = f5r * Two - f7r; + f5i = f5i * Two - f7i; + + w0r = *u0r; + w0i = *u0i; + w1r = *u1r; + w1i = *u1i; + + if (DiffUCnt <= NDiffU/2) + w0r = -w0r; + + t0r = f0r - f4r * w2r - f4i * w2i; + t0i = f0i + f4r * w2i - f4i * w2r; + f0r = f0r * Two - t0r; + f0i = f0i * Two - t0i; + + f4r = f2r - f6r * w2i + f6i * w2r; + f4i = f2i - f6r * w2r - f6i * w2i; + f6r = f2r * Two - f4r; + f6i = f2i * Two - f4i; + + *(p0r + pos) = t0r; + *p2r = f4r; + *(p0r + posi) = t0i; + *(p2r + 1) = f4i; + w2r = *u2r; + w2i = *u2i; + *p0r = f0r; + *(p2r + pos) = f6r; + *(p0r + 1) = f0i; + *(p2r + posi) = f6i; + + p0r = pstrt; + p2r = pstrt + pinc + pinc; + + t1r = f1r - f5r * w3r - f5i * w3i; + t1i = f1i + f5r * w3i - f5i * w3r; + f1r = f1r * Two - t1r; + f1i = f1i * Two - t1i; + + f5r = f3r - f7r * w3i + f7i * w3r; + f5i = f3i - f7r * w3r - f7i * w3i; + f7r = f3r * Two - f5r; + f7i = f3i * Two - f5i; + + *(p1r + pos) = t1r; + *p3r = f5r; + *(p1r + posi) = t1i; + *(p3r + 1) = f5i; + w3r = *(u2r+U2toU3); + w3i = *(u2i-U2toU3); + *p1r = f1r; + *(p3r + pos) = f7r; + *(p1r + 1) = f1i; + *(p3r + posi) = f7i; + + p1r = pstrt + pinc; + p3r = p2r + pinc; + } + NSameU /= 8; + Uinc /= 8; + Uinc2 /= 8; + Uinc4 = Uinc * 4; + NDiffU *= 8; + pinc *= 8; + pnext *= 8; + pos *= 8; + posi = pos + 1; +} +} + +void fftrecurs(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt); +void fftrecurs(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt){ +/* recursive bfstages calls to maximize on chip cache efficiency */ +long i1; +if (M <= MCACHE) // fits on chip ? + bfstages(ioptr, M, Utbl, Ustride, NDiffU, StageCnt); /* RADIX 8 Stages */ +else{ + for (i1=0; i1<8; i1++){ + fftrecurs(&ioptr[i1*POW2(M-3)*2], M-3, Utbl, 8*Ustride, NDiffU, StageCnt-1); /* RADIX 8 Stages */ + } + bfstages(ioptr, M, Utbl, Ustride, POW2(M-3), 1); /* RADIX 8 Stage */ +} +} + +void ffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow){ +/* Compute in-place complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = output data array */ + +long StageCnt; +long NDiffU; + +switch (M){ +case 0: + break; +case 1: + for (;Rows>0;Rows--){ + fft2pt(ioptr); /* a 2 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 2: + for (;Rows>0;Rows--){ + fft4pt(ioptr); /* a 4 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 3: + for (;Rows>0;Rows--){ + fft8pt(ioptr); /* an 8 pt fft */ + ioptr += 2*POW2(M); + } + break; +default: + for (;Rows>0;Rows--){ + + bitrevR2(ioptr, M, BRLow); /* bit reverse and first radix 2 stage */ + + StageCnt = (M-1) / 3; // number of radix 8 stages + NDiffU = 2; // one radix 2 stage already complete + + if ( (M-1-(StageCnt * 3)) == 1 ){ + bfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ + NDiffU *= 2; + } + + if ( (M-1-(StageCnt * 3)) == 2 ){ + bfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ + NDiffU *= 4; + } + + if (M <= MCACHE) + bfstages(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ + + else{ + fftrecurs(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ + } + + ioptr += 2*POW2(M); + } +} +} + +/************************************************ +parts of iffts1 +*************************************************/ + +inline void scbitrevR2(float *ioptr, long M, short *BRLow, float scale); +inline void scbitrevR2(float *ioptr, long M, short *BRLow, float scale){ +/*** scaled bit reverse and first radix 2 stage forward or inverse fft ***/ +float f0r; +float f0i; +float f1r; +float f1i; +float f2r; +float f2i; +float f3r; +float f3i; +float f4r; +float f4i; +float f5r; +float f5i; +float f6r; +float f6i; +float f7r; +float f7i; +float t0r; +float t0i; +float t1r; +float t1i; +float *p0r; +float *p1r; +float *IOP; +float *iolimit; +long Colstart; +long iCol; +unsigned long posA; +unsigned long posAi; +unsigned long posB; +unsigned long posBi; + +const unsigned long Nrems2 = POW2((M+3)/2); +const unsigned long Nroot_1_ColInc = POW2(M)-Nrems2; +const unsigned long Nroot_1 = POW2(M/2-1)-1; +const unsigned long ColstartShift = (M+1)/2 +1; +posA = POW2(M); // 1/2 of POW2(M) complexes +posAi = posA + 1; +posB = posA + 2; +posBi = posB + 1; + +iolimit = ioptr + Nrems2; +for (; ioptr < iolimit; ioptr += POW2(M/2+1)){ + for (Colstart = Nroot_1; Colstart >= 0; Colstart--){ + iCol = Nroot_1; + p0r = ioptr+ Nroot_1_ColInc + BRLow[Colstart]*4; + IOP = ioptr + (Colstart << ColstartShift); + p1r = IOP + BRLow[iCol]*4; + f0r = *(p0r); + f0i = *(p0r+1); + f1r = *(p0r+posA); + f1i = *(p0r+posAi); + for (; iCol > Colstart;){ + f2r = *(p0r+2); + f2i = *(p0r+(2+1)); + f3r = *(p0r+posB); + f3i = *(p0r+posBi); + f4r = *(p1r); + f4i = *(p1r+1); + f5r = *(p1r+posA); + f5i = *(p1r+posAi); + f6r = *(p1r+2); + f6i = *(p1r+(2+1)); + f7r = *(p1r+posB); + f7i = *(p1r+posBi); + + t0r = f0r + f1r; + t0i = f0i + f1i; + f1r = f0r - f1r; + f1i = f0i - f1i; + t1r = f2r + f3r; + t1i = f2i + f3i; + f3r = f2r - f3r; + f3i = f2i - f3i; + f0r = f4r + f5r; + f0i = f4i + f5i; + f5r = f4r - f5r; + f5i = f4i - f5i; + f2r = f6r + f7r; + f2i = f6i + f7i; + f7r = f6r - f7r; + f7i = f6i - f7i; + + *(p1r) = scale*t0r; + *(p1r+1) = scale*t0i; + *(p1r+2) = scale*f1r; + *(p1r+(2+1)) = scale*f1i; + *(p1r+posA) = scale*t1r; + *(p1r+posAi) = scale*t1i; + *(p1r+posB) = scale*f3r; + *(p1r+posBi) = scale*f3i; + *(p0r) = scale*f0r; + *(p0r+1) = scale*f0i; + *(p0r+2) = scale*f5r; + *(p0r+(2+1)) = scale*f5i; + *(p0r+posA) = scale*f2r; + *(p0r+posAi) = scale*f2i; + *(p0r+posB) = scale*f7r; + *(p0r+posBi) = scale*f7i; + + p0r -= Nrems2; + f0r = *(p0r); + f0i = *(p0r+1); + f1r = *(p0r+posA); + f1i = *(p0r+posAi); + iCol -= 1; + p1r = IOP + BRLow[iCol]*4; + }; + f2r = *(p0r+2); + f2i = *(p0r+(2+1)); + f3r = *(p0r+posB); + f3i = *(p0r+posBi); + + t0r = f0r + f1r; + t0i = f0i + f1i; + f1r = f0r - f1r; + f1i = f0i - f1i; + t1r = f2r + f3r; + t1i = f2i + f3i; + f3r = f2r - f3r; + f3i = f2i - f3i; + + *(p0r) = scale*t0r; + *(p0r+1) = scale*t0i; + *(p0r+2) = scale*f1r; + *(p0r+(2+1)) = scale*f1i; + *(p0r+posA) = scale*t1r; + *(p0r+posAi) = scale*t1i; + *(p0r+posB) = scale*f3r; + *(p0r+posBi) = scale*f3i; + + }; +}; +} + +inline void ifft2pt(float *ioptr, float scale); +inline void ifft2pt(float *ioptr, float scale){ +/*** RADIX 2 ifft ***/ +float f0r, f0i, f1r, f1i; +float t0r, t0i; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[2]; +f1i = ioptr[3]; + + /* Butterflys */ + /* + f0 - - t0 + f1 - 1 - f1 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + + /* store result */ +ioptr[0] = scale*t0r; +ioptr[1] = scale*t0i; +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +} + +inline void ifft4pt(float *ioptr, float scale); +inline void ifft4pt(float *ioptr, float scale){ +/*** RADIX 4 ifft ***/ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float t0r, t0i, t1r, t1i; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[4]; +f1i = ioptr[5]; +f2r = ioptr[2]; +f2i = ioptr[3]; +f3r = ioptr[6]; +f3i = ioptr[7]; + + /* Butterflys */ + /* + f0 - - t0 - - f0 + f1 - 1 - f1 - - f1 + f2 - - f2 - 1 - f2 + f3 - 1 - t1 - i - f3 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = t0i - f2i; + +f3r = f1r + t1i; +f3i = f1i - t1r; +f1r = f1r - t1i; +f1i = f1i + t1r; + + /* store result */ +ioptr[0] = scale*f0r; +ioptr[1] = scale*f0i; +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +ioptr[4] = scale*f2r; +ioptr[5] = scale*f2i; +ioptr[6] = scale*f3r; +ioptr[7] = scale*f3i; +} + +inline void ifft8pt(float *ioptr, float scale); +inline void ifft8pt(float *ioptr, float scale){ +/*** RADIX 8 ifft ***/ +float w0r = 1.0/MYROOT2; /* cos(pi/4) */ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[8]; +f1i = ioptr[9]; +f2r = ioptr[4]; +f2i = ioptr[5]; +f3r = ioptr[12]; +f3i = ioptr[13]; +f4r = ioptr[2]; +f4i = ioptr[3]; +f5r = ioptr[10]; +f5i = ioptr[11]; +f6r = ioptr[6]; +f6i = ioptr[7]; +f7r = ioptr[14]; +f7i = ioptr[15]; + + /* Butterflys */ + /* + f0 - - t0 - - f0 - - f0 + f1 - 1 - f1 - - f1 - - f1 + f2 - - f2 - 1 - f2 - - f2 + f3 - 1 - t1 - i - f3 - - f3 + f4 - - t0 - - f4 - 1 - t0 + f5 - 1 - f5 - - f5 - w3 - f4 + f6 - - f6 - 1 - f6 - i - t1 + f7 - 1 - t1 - i - f7 - iw3- f6 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = t0i - f2i; + +f3r = f1r + t1i; +f3i = f1i - t1r; +f1r = f1r - t1i; +f1i = f1i + t1r; + + +t0r = f4r + f5r; +t0i = f4i + f5i; +f5r = f4r - f5r; +f5i = f4i - f5i; + +t1r = f6r - f7r; +t1i = f6i - f7i; +f6r = f6r + f7r; +f6i = f6i + f7i; + +f4r = t0r + f6r; +f4i = t0i + f6i; +f6r = t0r - f6r; +f6i = t0i - f6i; + +f7r = f5r + t1i; +f7i = f5i - t1r; +f5r = f5r - t1i; +f5i = f5i + t1r; + + +t0r = f0r - f4r; +t0i = f0i - f4i; +f0r = f0r + f4r; +f0i = f0i + f4i; + +t1r = f2r + f6i; +t1i = f2i - f6r; +f2r = f2r - f6i; +f2i = f2i + f6r; + +f4r = f1r - f5r * w0r + f5i * w0r; +f4i = f1i - f5r * w0r - f5i * w0r; +f1r = f1r * Two - f4r; +f1i = f1i * Two - f4i; + +f6r = f3r + f7r * w0r + f7i * w0r; +f6i = f3i - f7r * w0r + f7i * w0r; +f3r = f3r * Two - f6r; +f3i = f3i * Two - f6i; + + /* store result */ +ioptr[0] = scale*f0r; +ioptr[1] = scale*f0i; +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +ioptr[4] = scale*f2r; +ioptr[5] = scale*f2i; +ioptr[6] = scale*f3r; +ioptr[7] = scale*f3i; +ioptr[8] = scale*t0r; +ioptr[9] = scale*t0i; +ioptr[10] = scale*f4r; +ioptr[11] = scale*f4i; +ioptr[12] = scale*t1r; +ioptr[13] = scale*t1i; +ioptr[14] = scale*f6r; +ioptr[15] = scale*f6i; +} + +inline void ibfR2(float *ioptr, long M, long NDiffU); +inline void ibfR2(float *ioptr, long M, long NDiffU){ +/*** 2nd radix 2 stage ***/ +unsigned long pos; +unsigned long posi; +unsigned long pinc; +unsigned long pnext; +unsigned long NSameU; +unsigned long SameUCnt; + +float *pstrt; +float *p0r, *p1r, *p2r, *p3r; + +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +const float Two = 2.0; + +pinc = NDiffU * 2; // 2 floats per complex +pnext = pinc * 4; +pos = 2; +posi = pos+1; +NSameU = POW2(M) / 4 /NDiffU; // 4 Us at a time +pstrt = ioptr; +p0r = pstrt; +p1r = pstrt+pinc; +p2r = p1r+pinc; +p3r = p2r+pinc; + + /* Butterflys */ + /* + f0 - - f4 + f1 - 1 - f5 + f2 - - f6 + f3 - 1 - f7 + */ + /* Butterflys */ + /* + f0 - - f4 + f1 - 1 - f5 + f2 - - f6 + f3 - 1 - f7 + */ + +for (SameUCnt = NSameU; SameUCnt > 0 ; SameUCnt--){ + + f0r = *p0r; + f1r = *p1r; + f0i = *(p0r + 1); + f1i = *(p1r + 1); + f2r = *p2r; + f3r = *p3r; + f2i = *(p2r + 1); + f3i = *(p3r + 1); + + f4r = f0r + f1r; + f4i = f0i + f1i; + f5r = f0r - f1r; + f5i = f0i - f1i; + + f6r = f2r + f3r; + f6i = f2i + f3i; + f7r = f2r - f3r; + f7i = f2i - f3i; + + *p0r = f4r; + *(p0r + 1) = f4i; + *p1r = f5r; + *(p1r + 1) = f5i; + *p2r = f6r; + *(p2r + 1) = f6i; + *p3r = f7r; + *(p3r + 1) = f7i; + + f0r = *(p0r + pos); + f1i = *(p1r + posi); + f0i = *(p0r + posi); + f1r = *(p1r + pos); + f2r = *(p2r + pos); + f3i = *(p3r + posi); + f2i = *(p2r + posi); + f3r = *(p3r + pos); + + f4r = f0r - f1i; + f4i = f0i + f1r; + f5r = f0r + f1i; + f5i = f0i - f1r; + + f6r = f2r - f3i; + f6i = f2i + f3r; + f7r = f2r + f3i; + f7i = f2i - f3r; + + *(p0r + pos) = f4r; + *(p0r + posi) = f4i; + *(p1r + pos) = f5r; + *(p1r + posi) = f5i; + *(p2r + pos) = f6r; + *(p2r + posi) = f6i; + *(p3r + pos) = f7r; + *(p3r + posi) = f7i; + + p0r += pnext; + p1r += pnext; + p2r += pnext; + p3r += pnext; + +} +} + +inline void ibfR4(float *ioptr, long M, long NDiffU); +inline void ibfR4(float *ioptr, long M, long NDiffU){ +/*** 1 radix 4 stage ***/ +unsigned long pos; +unsigned long posi; +unsigned long pinc; +unsigned long pnext; +unsigned long pnexti; +unsigned long NSameU; +unsigned long SameUCnt; + +float *pstrt; +float *p0r, *p1r, *p2r, *p3r; + +float w1r = 1.0/MYROOT2; /* cos(pi/4) */ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t1r, t1i; +const float Two = 2.0; + +pinc = NDiffU * 2; // 2 floats per complex +pnext = pinc * 4; +pnexti = pnext + 1; +pos = 2; +posi = pos+1; +NSameU = POW2(M) / 4 /NDiffU; // 4 pts per butterfly +pstrt = ioptr; +p0r = pstrt; +p1r = pstrt+pinc; +p2r = p1r+pinc; +p3r = p2r+pinc; + + /* Butterflys */ + /* + f0 - - f0 - - f4 + f1 - 1 - f5 - - f5 + f2 - - f6 - 1 - f6 + f3 - 1 - f3 - -i - f7 + */ + /* Butterflys */ + /* + f0 - - f4 - - f4 + f1 - -i - t1 - - f5 + f2 - - f2 - w1 - f6 + f3 - -i - f7 - iw1- f7 + */ + +f0r = *p0r; +f1r = *p1r; +f2r = *p2r; +f3r = *p3r; +f0i = *(p0r + 1); +f1i = *(p1r + 1); +f2i = *(p2r + 1); +f3i = *(p3r + 1); + +f5r = f0r - f1r; +f5i = f0i - f1i; +f0r = f0r + f1r; +f0i = f0i + f1i; + +f6r = f2r + f3r; +f6i = f2i + f3i; +f3r = f2r - f3r; +f3i = f2i - f3i; + +for (SameUCnt = NSameU-1; SameUCnt > 0 ; SameUCnt--){ + + f7r = f5r + f3i; + f7i = f5i - f3r; + f5r = f5r - f3i; + f5i = f5i + f3r; + + f4r = f0r + f6r; + f4i = f0i + f6i; + f6r = f0r - f6r; + f6i = f0i - f6i; + + f2r = *(p2r + pos); + f2i = *(p2r + posi); + f1r = *(p1r + pos); + f1i = *(p1r + posi); + f3i = *(p3r + posi); + f0r = *(p0r + pos); + f3r = *(p3r + pos); + f0i = *(p0r + posi); + + *p3r = f7r; + *p0r = f4r; + *(p3r + 1) = f7i; + *(p0r + 1) = f4i; + *p1r = f5r; + *p2r = f6r; + *(p1r + 1) = f5i; + *(p2r + 1) = f6i; + + f7r = f2r + f3i; + f7i = f2i - f3r; + f2r = f2r - f3i; + f2i = f2i + f3r; + + f4r = f0r - f1i; + f4i = f0i + f1r; + t1r = f0r + f1i; + t1i = f0i - f1r; + + f5r = t1r - f7r * w1r - f7i * w1r; + f5i = t1i + f7r * w1r - f7i * w1r; + f7r = t1r * Two - f5r; + f7i = t1i * Two - f5i; + + f6r = f4r - f2r * w1r + f2i * w1r; + f6i = f4i - f2r * w1r - f2i * w1r; + f4r = f4r * Two - f6r; + f4i = f4i * Two - f6i; + + f3r = *(p3r + pnext); + f0r = *(p0r + pnext); + f3i = *(p3r + pnexti); + f0i = *(p0r + pnexti); + f2r = *(p2r + pnext); + f2i = *(p2r + pnexti); + f1r = *(p1r + pnext); + f1i = *(p1r + pnexti); + + *(p2r + pos) = f6r; + *(p1r + pos) = f5r; + *(p2r + posi) = f6i; + *(p1r + posi) = f5i; + *(p3r + pos) = f7r; + *(p0r + pos) = f4r; + *(p3r + posi) = f7i; + *(p0r + posi) = f4i; + + f6r = f2r + f3r; + f6i = f2i + f3i; + f3r = f2r - f3r; + f3i = f2i - f3i; + + f5r = f0r - f1r; + f5i = f0i - f1i; + f0r = f0r + f1r; + f0i = f0i + f1i; + + p3r += pnext; + p0r += pnext; + p1r += pnext; + p2r += pnext; + +} +f7r = f5r + f3i; +f7i = f5i - f3r; +f5r = f5r - f3i; +f5i = f5i + f3r; + +f4r = f0r + f6r; +f4i = f0i + f6i; +f6r = f0r - f6r; +f6i = f0i - f6i; + +f2r = *(p2r + pos); +f2i = *(p2r + posi); +f1r = *(p1r + pos); +f1i = *(p1r + posi); +f3i = *(p3r + posi); +f0r = *(p0r + pos); +f3r = *(p3r + pos); +f0i = *(p0r + posi); + +*p3r = f7r; +*p0r = f4r; +*(p3r + 1) = f7i; +*(p0r + 1) = f4i; +*p1r = f5r; +*p2r = f6r; +*(p1r + 1) = f5i; +*(p2r + 1) = f6i; + +f7r = f2r + f3i; +f7i = f2i - f3r; +f2r = f2r - f3i; +f2i = f2i + f3r; + +f4r = f0r - f1i; +f4i = f0i + f1r; +t1r = f0r + f1i; +t1i = f0i - f1r; + +f5r = t1r - f7r * w1r - f7i * w1r; +f5i = t1i + f7r * w1r - f7i * w1r; +f7r = t1r * Two - f5r; +f7i = t1i * Two - f5i; + +f6r = f4r - f2r * w1r + f2i * w1r; +f6i = f4i - f2r * w1r - f2i * w1r; +f4r = f4r * Two - f6r; +f4i = f4i * Two - f6i; + +*(p2r + pos) = f6r; +*(p1r + pos) = f5r; +*(p2r + posi) = f6i; +*(p1r + posi) = f5i; +*(p3r + pos) = f7r; +*(p0r + pos) = f4r; +*(p3r + posi) = f7i; +*(p0r + posi) = f4i; + +} + +inline void ibfstages(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt); +inline void ibfstages(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt){ +/*** RADIX 8 Stages ***/ +unsigned long pos; +unsigned long posi; +unsigned long pinc; +unsigned long pnext; +unsigned long NSameU; +unsigned long Uinc; +unsigned long Uinc2; +unsigned long Uinc4; +unsigned long DiffUCnt; +unsigned long SameUCnt; +unsigned long U2toU3; + +float *pstrt; +float *p0r, *p1r, *p2r, *p3r; +float *u0r, *u0i, *u1r, *u1i, *u2r, *u2i; + +float w0r, w0i, w1r, w1i, w2r, w2i, w3r, w3i; +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; + +pinc = NDiffU * 2; // 2 floats per complex +pnext = pinc * 8; +pos = pinc * 4; +posi = pos + 1; +NSameU = POW2(M) / 8 /NDiffU; // 8 pts per butterfly +Uinc = NSameU * Ustride; +Uinc2 = Uinc * 2; +Uinc4 = Uinc * 4; +U2toU3 = (POW2(M) / 8)*Ustride; +for (; StageCnt > 0 ; StageCnt--){ + + u0r = &Utbl[0]; + u0i = &Utbl[POW2(M-2)*Ustride]; + u1r = u0r; + u1i = u0i; + u2r = u0r; + u2i = u0i; + + w0r = *u0r; + w0i = *u0i; + w1r = *u1r; + w1i = *u1i; + w2r = *u2r; + w2i = *u2i; + w3r = *(u2r+U2toU3); + w3i = *(u2i-U2toU3); + + pstrt = ioptr; + + p0r = pstrt; + p1r = pstrt+pinc; + p2r = p1r+pinc; + p3r = p2r+pinc; + + /* Butterflys */ + /* + f0 - - t0 - - f0 - - f0 + f1 - w0- f1 - - f1 - - f1 + f2 - - f2 - w1- f2 - - f4 + f3 - w0- t1 - iw1- f3 - - f5 + + f4 - - t0 - - f4 - w2- t0 + f5 - w0- f5 - - f5 - w3- t1 + f6 - - f6 - w1- f6 - iw2- f6 + f7 - w0- t1 - iw1- f7 - iw3- f7 + */ + + for (DiffUCnt = NDiffU; DiffUCnt > 0 ; DiffUCnt--){ + f0r = *p0r; + f0i = *(p0r + 1); + f1r = *p1r; + f1i = *(p1r + 1); + for (SameUCnt = NSameU-1; SameUCnt > 0 ; SameUCnt--){ + f2r = *p2r; + f2i = *(p2r + 1); + f3r = *p3r; + f3i = *(p3r + 1); + + t0r = f0r + f1r * w0r - f1i * w0i; + t0i = f0i + f1r * w0i + f1i * w0r; + f1r = f0r * Two - t0r; + f1i = f0i * Two - t0i; + + f4r = *(p0r + pos); + f4i = *(p0r + posi); + f5r = *(p1r + pos); + f5i = *(p1r + posi); + + f6r = *(p2r + pos); + f6i = *(p2r + posi); + f7r = *(p3r + pos); + f7i = *(p3r + posi); + + t1r = f2r - f3r * w0r + f3i * w0i; + t1i = f2i - f3r * w0i - f3i * w0r; + f2r = f2r * Two - t1r; + f2i = f2i * Two - t1i; + + f0r = t0r + f2r * w1r - f2i * w1i; + f0i = t0i + f2r * w1i + f2i * w1r; + f2r = t0r * Two - f0r; + f2i = t0i * Two - f0i; + + f3r = f1r + t1r * w1i + t1i * w1r; + f3i = f1i - t1r * w1r + t1i * w1i; + f1r = f1r * Two - f3r; + f1i = f1i * Two - f3i; + + + t0r = f4r + f5r * w0r - f5i * w0i; + t0i = f4i + f5r * w0i + f5i * w0r; + f5r = f4r * Two - t0r; + f5i = f4i * Two - t0i; + + t1r = f6r - f7r * w0r + f7i * w0i; + t1i = f6i - f7r * w0i - f7i * w0r; + f6r = f6r * Two - t1r; + f6i = f6i * Two - t1i; + + f4r = t0r + f6r * w1r - f6i * w1i; + f4i = t0i + f6r * w1i + f6i * w1r; + f6r = t0r * Two - f4r; + f6i = t0i * Two - f4i; + + f7r = f5r + t1r * w1i + t1i * w1r; + f7i = f5i - t1r * w1r + t1i * w1i; + f5r = f5r * Two - f7r; + f5i = f5i * Two - f7i; + + t0r = f0r - f4r * w2r + f4i * w2i; + t0i = f0i - f4r * w2i - f4i * w2r; + f0r = f0r * Two - t0r; + f0i = f0i * Two - t0i; + + t1r = f1r - f5r * w3r + f5i * w3i; + t1i = f1i - f5r * w3i - f5i * w3r; + f1r = f1r * Two - t1r; + f1i = f1i * Two - t1i; + + *(p0r + pos) = t0r; + *(p0r + posi) = t0i; + *p0r = f0r; + *(p0r + 1) = f0i; + + p0r += pnext; + f0r = *p0r; + f0i = *(p0r + 1); + + *(p1r + pos) = t1r; + *(p1r + posi) = t1i; + *p1r = f1r; + *(p1r + 1) = f1i; + + p1r += pnext; + + f1r = *p1r; + f1i = *(p1r + 1); + + f4r = f2r - f6r * w2i - f6i * w2r; + f4i = f2i + f6r * w2r - f6i * w2i; + f6r = f2r * Two - f4r; + f6i = f2i * Two - f4i; + + f5r = f3r - f7r * w3i - f7i * w3r; + f5i = f3i + f7r * w3r - f7i * w3i; + f7r = f3r * Two - f5r; + f7i = f3i * Two - f5i; + + *p2r = f4r; + *(p2r + 1) = f4i; + *(p2r + pos) = f6r; + *(p2r + posi) = f6i; + + p2r += pnext; + + *p3r = f5r; + *(p3r + 1) = f5i; + *(p3r + pos) = f7r; + *(p3r + posi) = f7i; + + p3r += pnext; + + } + + f2r = *p2r; + f2i = *(p2r + 1); + f3r = *p3r; + f3i = *(p3r + 1); + + t0r = f0r + f1r * w0r - f1i * w0i; + t0i = f0i + f1r * w0i + f1i * w0r; + f1r = f0r * Two - t0r; + f1i = f0i * Two - t0i; + + f4r = *(p0r + pos); + f4i = *(p0r + posi); + f5r = *(p1r + pos); + f5i = *(p1r + posi); + + f6r = *(p2r + pos); + f6i = *(p2r + posi); + f7r = *(p3r + pos); + f7i = *(p3r + posi); + + t1r = f2r - f3r * w0r + f3i * w0i; + t1i = f2i - f3r * w0i - f3i * w0r; + f2r = f2r * Two - t1r; + f2i = f2i * Two - t1i; + + f0r = t0r + f2r * w1r - f2i * w1i; + f0i = t0i + f2r * w1i + f2i * w1r; + f2r = t0r * Two - f0r; + f2i = t0i * Two - f0i; + + f3r = f1r + t1r * w1i + t1i * w1r; + f3i = f1i - t1r * w1r + t1i * w1i; + f1r = f1r * Two - f3r; + f1i = f1i * Two - f3i; + + if (DiffUCnt == NDiffU/2) + Uinc4 = -Uinc4; + + u0r += Uinc4; + u0i -= Uinc4; + u1r += Uinc2; + u1i -= Uinc2; + u2r += Uinc; + u2i -= Uinc; + + pstrt += 2; + + t0r = f4r + f5r * w0r - f5i * w0i; + t0i = f4i + f5r * w0i + f5i * w0r; + f5r = f4r * Two - t0r; + f5i = f4i * Two - t0i; + + t1r = f6r - f7r * w0r + f7i * w0i; + t1i = f6i - f7r * w0i - f7i * w0r; + f6r = f6r * Two - t1r; + f6i = f6i * Two - t1i; + + f4r = t0r + f6r * w1r - f6i * w1i; + f4i = t0i + f6r * w1i + f6i * w1r; + f6r = t0r * Two - f4r; + f6i = t0i * Two - f4i; + + f7r = f5r + t1r * w1i + t1i * w1r; + f7i = f5i - t1r * w1r + t1i * w1i; + f5r = f5r * Two - f7r; + f5i = f5i * Two - f7i; + + w0r = *u0r; + w0i = *u0i; + w1r = *u1r; + w1i = *u1i; + + if (DiffUCnt <= NDiffU/2) + w0r = -w0r; + + t0r = f0r - f4r * w2r + f4i * w2i; + t0i = f0i - f4r * w2i - f4i * w2r; + f0r = f0r * Two - t0r; + f0i = f0i * Two - t0i; + + f4r = f2r - f6r * w2i - f6i * w2r; + f4i = f2i + f6r * w2r - f6i * w2i; + f6r = f2r * Two - f4r; + f6i = f2i * Two - f4i; + + *(p0r + pos) = t0r; + *p2r = f4r; + *(p0r + posi) = t0i; + *(p2r + 1) = f4i; + w2r = *u2r; + w2i = *u2i; + *p0r = f0r; + *(p2r + pos) = f6r; + *(p0r + 1) = f0i; + *(p2r + posi) = f6i; + + p0r = pstrt; + p2r = pstrt + pinc + pinc; + + t1r = f1r - f5r * w3r + f5i * w3i; + t1i = f1i - f5r * w3i - f5i * w3r; + f1r = f1r * Two - t1r; + f1i = f1i * Two - t1i; + + f5r = f3r - f7r * w3i - f7i * w3r; + f5i = f3i + f7r * w3r - f7i * w3i; + f7r = f3r * Two - f5r; + f7i = f3i * Two - f5i; + + *(p1r + pos) = t1r; + *p3r = f5r; + *(p1r + posi) = t1i; + *(p3r + 1) = f5i; + w3r = *(u2r+U2toU3); + w3i = *(u2i-U2toU3); + *p1r = f1r; + *(p3r + pos) = f7r; + *(p1r + 1) = f1i; + *(p3r + posi) = f7i; + + p1r = pstrt + pinc; + p3r = p2r + pinc; + } + NSameU /= 8; + Uinc /= 8; + Uinc2 /= 8; + Uinc4 = Uinc * 4; + NDiffU *= 8; + pinc *= 8; + pnext *= 8; + pos *= 8; + posi = pos + 1; +} +} + +void ifftrecurs(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt); +void ifftrecurs(float *ioptr, long M, float *Utbl, long Ustride, long NDiffU, long StageCnt){ +/* recursive bfstages calls to maximize on chip cache efficiency */ +long i1; +if (M <= MCACHE) + ibfstages(ioptr, M, Utbl, Ustride, NDiffU, StageCnt); /* RADIX 8 Stages */ +else{ + for (i1=0; i1<8; i1++){ + ifftrecurs(&ioptr[i1*POW2(M-3)*2], M-3, Utbl, 8*Ustride, NDiffU, StageCnt-1); /* RADIX 8 Stages */ + } + ibfstages(ioptr, M, Utbl, Ustride, POW2(M-3), 1); /* RADIX 8 Stage */ +} +} + +void iffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow){ +/* Compute in-place inverse complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = output data array */ + +long StageCnt; +long NDiffU; +const float scale = 1.0/POW2(M); + +switch (M){ +case 0: + break; +case 1: + for (;Rows>0;Rows--){ + ifft2pt(ioptr, scale); /* a 2 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 2: + for (;Rows>0;Rows--){ + ifft4pt(ioptr, scale); /* a 4 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 3: + for (;Rows>0;Rows--){ + ifft8pt(ioptr, scale); /* an 8 pt fft */ + ioptr += 2*POW2(M); + } + break; +default: + for (;Rows>0;Rows--){ + + scbitrevR2(ioptr, M, BRLow, scale); /* bit reverse and first radix 2 stage */ + + StageCnt = (M-1) / 3; // number of radix 8 stages + NDiffU = 2; // one radix 2 stage already complete + + if ( (M-1-(StageCnt * 3)) == 1 ){ + ibfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ + NDiffU *= 2; + } + + if ( (M-1-(StageCnt * 3)) == 2 ){ + ibfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ + NDiffU *= 4; + } + + if (M <= MCACHE) + ibfstages(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ + + else{ + ifftrecurs(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ + } + + ioptr += 2*POW2(M); + } +} +} + +/************************************************ +parts of rffts1 +*************************************************/ + +inline void rfft1pt(float *ioptr); +inline void rfft1pt(float *ioptr){ +/*** RADIX 2 rfft ***/ +float f0r, f0i; +float t0r, t0i; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; + + /* finish rfft */ +t0r = f0r + f0i; +t0i = f0r - f0i; + + /* store result */ +ioptr[0] = t0r; +ioptr[1] = t0i; +} + +inline void rfft2pt(float *ioptr); +inline void rfft2pt(float *ioptr){ +/*** RADIX 4 rfft ***/ +float f0r, f0i, f1r, f1i; +float t0r, t0i; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[2]; +f1i = ioptr[3]; + + /* Butterflys */ + /* + f0 - - t0 + f1 - 1 - f1 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f1i - f0i; + /* finish rfft */ +f0r = t0r + t0i; +f0i = t0r - t0i; + + /* store result */ +ioptr[0] = f0r; +ioptr[1] = f0i; +ioptr[2] = f1r; +ioptr[3] = f1i; +} + +inline void rfft4pt(float *ioptr); +inline void rfft4pt(float *ioptr){ +/*** RADIX 8 rfft ***/ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float t0r, t0i, t1r, t1i; +float w0r = 1.0/MYROOT2; /* cos(pi/4) */ +const float Two = 2.0; +const float scale = 0.5; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[4]; +f1i = ioptr[5]; +f2r = ioptr[2]; +f2i = ioptr[3]; +f3r = ioptr[6]; +f3i = ioptr[7]; + + /* Butterflys */ + /* + f0 - - t0 - - f0 + f1 - 1 - f1 - - f1 + f2 - - f2 - 1 - f2 + f3 - 1 - t1 - -i - f3 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = f2i - t0i; // neg for rfft + +f3r = f1r - t1i; +f3i = f1i + t1r; +f1r = f1r + t1i; +f1i = f1i - t1r; + + /* finish rfft */ +t0r = f0r + f0i; /* compute Re(x[0]) */ +t0i = f0r - f0i; /* compute Re(x[N/2]) */ + +t1r = f1r + f3r; +t1i = f1i - f3i; +f0r = f1i + f3i; +f0i = f3r - f1r; + +f1r = t1r + w0r * f0r + w0r * f0i; +f1i = t1i - w0r * f0r + w0r * f0i; +f3r = Two * t1r - f1r; +f3i = f1i - Two * t1i; + + /* store result */ +ioptr[4] = f2r; +ioptr[5] = f2i; +ioptr[0] = t0r; +ioptr[1] = t0i; + +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +ioptr[6] = scale*f3r; +ioptr[7] = scale*f3i; +} + +inline void rfft8pt(float *ioptr); +inline void rfft8pt(float *ioptr){ +/*** RADIX 16 rfft ***/ +float w0r = 1.0/MYROOT2; /* cos(pi/4) */ +float w1r = MYCOSPID8; /* cos(pi/8) */ +float w1i = MYSINPID8; /* sin(pi/8) */ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; +const float scale = 0.5; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; +f1r = ioptr[8]; +f1i = ioptr[9]; +f2r = ioptr[4]; +f2i = ioptr[5]; +f3r = ioptr[12]; +f3i = ioptr[13]; +f4r = ioptr[2]; +f4i = ioptr[3]; +f5r = ioptr[10]; +f5i = ioptr[11]; +f6r = ioptr[6]; +f6i = ioptr[7]; +f7r = ioptr[14]; +f7i = ioptr[15]; + /* Butterflys */ + /* + f0 - - t0 - - f0 - - f0 + f1 - 1 - f1 - - f1 - - f1 + f2 - - f2 - 1 - f2 - - f2 + f3 - 1 - t1 - -i - f3 - - f3 + f4 - - t0 - - f4 - 1 - t0 + f5 - 1 - f5 - - f5 - w3 - f4 + f6 - - f6 - 1 - f6 - -i - t1 + f7 - 1 - t1 - -i - f7 - iw3- f6 + */ + +t0r = f0r + f1r; +t0i = f0i + f1i; +f1r = f0r - f1r; +f1i = f0i - f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = t0i - f2i; + +f3r = f1r - t1i; +f3i = f1i + t1r; +f1r = f1r + t1i; +f1i = f1i - t1r; + + +t0r = f4r + f5r; +t0i = f4i + f5i; +f5r = f4r - f5r; +f5i = f4i - f5i; + +t1r = f6r - f7r; +t1i = f6i - f7i; +f6r = f6r + f7r; +f6i = f6i + f7i; + +f4r = t0r + f6r; +f4i = t0i + f6i; +f6r = t0r - f6r; +f6i = t0i - f6i; + +f7r = f5r - t1i; +f7i = f5i + t1r; +f5r = f5r + t1i; +f5i = f5i - t1r; + + +t0r = f0r - f4r; +t0i = f4i - f0i; // neg for rfft +f0r = f0r + f4r; +f0i = f0i + f4i; + +t1r = f2r - f6i; +t1i = f2i + f6r; +f2r = f2r + f6i; +f2i = f2i - f6r; + +f4r = f1r - f5r * w0r - f5i * w0r; +f4i = f1i + f5r * w0r - f5i * w0r; +f1r = f1r * Two - f4r; +f1i = f1i * Two - f4i; + +f6r = f3r + f7r * w0r - f7i * w0r; +f6i = f3i + f7r * w0r + f7i * w0r; +f3r = f3r * Two - f6r; +f3i = f3i * Two - f6i; + + /* finish rfft */ +f5r = f0r + f0i; /* compute Re(x[0]) */ +f5i = f0r - f0i; /* compute Re(x[N/2]) */ + +f0r = f2r + t1r; +f0i = f2i - t1i; +f7r = f2i + t1i; +f7i = t1r - f2r; + +f2r = f0r + w0r * f7r + w0r * f7i; +f2i = f0i - w0r * f7r + w0r * f7i; +t1r = Two * f0r - f2r; +t1i = f2i - Two * f0i; + + +f0r = f1r + f6r; +f0i = f1i - f6i; +f7r = f1i + f6i; +f7i = f6r - f1r; + +f1r = f0r + w1r * f7r + w1i * f7i; +f1i = f0i - w1i * f7r + w1r * f7i; +f6r = Two * f0r - f1r; +f6i = f1i - Two * f0i; + +f0r = f3r + f4r; +f0i = f3i - f4i; +f7r = f3i + f4i; +f7i = f4r - f3r; + +f3r = f0r + w1i * f7r + w1r * f7i; +f3i = f0i - w1r * f7r + w1i * f7i; +f4r = Two * f0r - f3r; +f4i = f3i - Two * f0i; + + /* store result */ +ioptr[8] = t0r; +ioptr[9] = t0i; +ioptr[0] = f5r; +ioptr[1] = f5i; + +ioptr[4] = scale*f2r; +ioptr[5] = scale*f2i; +ioptr[12] = scale*t1r; +ioptr[13] = scale*t1i; + +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +ioptr[6] = scale*f3r; +ioptr[7] = scale*f3i; +ioptr[10] = scale*f4r; +ioptr[11] = scale*f4i; +ioptr[14] = scale*f6r; +ioptr[15] = scale*f6i; +} + +inline void frstage(float *ioptr, long M, float *Utbl); +inline void frstage(float *ioptr, long M, float *Utbl){ +/* Finish RFFT */ + +unsigned long pos; +unsigned long posi; +unsigned long diffUcnt; + +float *p0r, *p1r; +float *u0r, *u0i; + +float w0r, w0i; +float f0r, f0i, f1r, f1i, f4r, f4i, f5r, f5i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; + +pos = POW2(M-1); +posi = pos + 1; + +p0r = ioptr; +p1r = ioptr + pos/2; + +u0r = Utbl + POW2(M-3); + +w0r = *u0r, + +f0r = *(p0r); +f0i = *(p0r + 1); +f4r = *(p0r + pos); +f4i = *(p0r + posi); +f1r = *(p1r); +f1i = *(p1r + 1); +f5r = *(p1r + pos); +f5i = *(p1r + posi); + + t0r = Two * f0r + Two * f0i; /* compute Re(x[0]) */ + t0i = Two * f0r - Two * f0i; /* compute Re(x[N/2]) */ + t1r = f4r + f4r; + t1i = -f4i - f4i; + + f0r = f1r + f5r; + f0i = f1i - f5i; + f4r = f1i + f5i; + f4i = f5r - f1r; + + f1r = f0r + w0r * f4r + w0r * f4i; + f1i = f0i - w0r * f4r + w0r * f4i; + f5r = Two * f0r - f1r; + f5i = f1i - Two * f0i; + +*(p0r) = t0r; +*(p0r + 1) = t0i; +*(p0r + pos) = t1r; +*(p0r + posi) = t1i; +*(p1r) = f1r; +*(p1r + 1) = f1i; +*(p1r + pos) = f5r; +*(p1r + posi) = f5i; + +u0r = Utbl + 1; +u0i = Utbl + (POW2(M-2)-1); + +w0r = *u0r, +w0i = *u0i; + +p0r = (ioptr + 2); +p1r = (ioptr + (POW2(M-2)-1)*2); + + /* Butterflys */ + /* + f0 - t0 - - f0 + f5 - t1 - w0 - f5 + + f1 - t0 - - f1 + f4 - t1 -iw0 - f4 + */ + +for (diffUcnt = POW2(M-3)-1; diffUcnt > 0 ; diffUcnt--){ + + f0r = *(p0r); + f0i = *(p0r + 1); + f5r = *(p1r + pos); + f5i = *(p1r + posi); + f1r = *(p1r); + f1i = *(p1r + 1); + f4r = *(p0r + pos); + f4i = *(p0r + posi); + + t0r = f0r + f5r; + t0i = f0i - f5i; + t1r = f0i + f5i; + t1i = f5r - f0r; + + f0r = t0r + w0r * t1r + w0i * t1i; + f0i = t0i - w0i * t1r + w0r * t1i; + f5r = Two * t0r - f0r; + f5i = f0i - Two * t0i; + + t0r = f1r + f4r; + t0i = f1i - f4i; + t1r = f1i + f4i; + t1i = f4r - f1r; + + f1r = t0r + w0i * t1r + w0r * t1i; + f1i = t0i - w0r * t1r + w0i * t1i; + f4r = Two * t0r - f1r; + f4i = f1i - Two * t0i; + + *(p0r) = f0r; + *(p0r + 1) = f0i; + *(p1r + pos) = f5r; + *(p1r + posi) = f5i; + + w0r = *++u0r; + w0i = *--u0i; + + *(p1r) = f1r; + *(p1r + 1) = f1i; + *(p0r + pos) = f4r; + *(p0r + posi) = f4i; + + p0r += 2; + p1r -= 2; +}; +} + +void rffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow){ +/* Compute in-place real fft on the rows of the input array */ +/* The result is the complex spectra of the positive frequencies */ +/* except the location for the first complex number contains the real */ +/* values for DC and Nyquest */ +/* INPUTS */ +/* *ioptr = real input data array */ +/* M = log2 of fft size */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = output data array in the following order */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ + +float scale; +long StageCnt; +long NDiffU; + +M=M-1; +switch (M){ +case -1: + break; +case 0: + for (;Rows>0;Rows--){ + rfft1pt(ioptr); /* a 2 pt fft */ + ioptr += 2*POW2(M); + } +case 1: + for (;Rows>0;Rows--){ + rfft2pt(ioptr); /* a 4 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 2: + for (;Rows>0;Rows--){ + rfft4pt(ioptr); /* an 8 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 3: + for (;Rows>0;Rows--){ + rfft8pt(ioptr); /* a 16 pt fft */ + ioptr += 2*POW2(M); + } + break; +default: + scale = 0.5; + for (;Rows>0;Rows--){ + + scbitrevR2(ioptr, M, BRLow, scale); /* bit reverse and first radix 2 stage */ + + StageCnt = (M-1) / 3; // number of radix 8 stages + NDiffU = 2; // one radix 2 stage already complete + + if ( (M-1-(StageCnt * 3)) == 1 ){ + bfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ + NDiffU *= 2; + } + + if ( (M-1-(StageCnt * 3)) == 2 ){ + bfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ + NDiffU *= 4; + } + + if (M <= MCACHE){ + bfstages(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ + frstage(ioptr, M+1, Utbl); + } + + else{ + fftrecurs(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ + frstage(ioptr, M+1, Utbl); + } + + ioptr += 2*POW2(M); + } +} +} + +/************************************************ +parts of riffts1 +*************************************************/ + +inline void rifft1pt(float *ioptr, float scale); +inline void rifft1pt(float *ioptr, float scale){ +/*** RADIX 2 rifft ***/ +float f0r, f0i; +float t0r, t0i; + + /* bit reversed load */ +f0r = ioptr[0]; +f0i = ioptr[1]; + + /* finish rfft */ +t0r = f0r + f0i; +t0i = f0r - f0i; + + /* store result */ +ioptr[0] = scale*t0r; +ioptr[1] = scale*t0i; +} + +inline void rifft2pt(float *ioptr, float scale); +inline void rifft2pt(float *ioptr, float scale){ +/*** RADIX 4 rifft ***/ +float f0r, f0i, f1r, f1i; +float t0r, t0i; +const float Two = 2.0; + + /* bit reversed load */ +t0r = ioptr[0]; +t0i = ioptr[1]; +f1r = Two * ioptr[2]; +f1i = Two * ioptr[3]; + + /* start rifft */ +f0r = t0r + t0i; +f0i = t0r - t0i; + /* Butterflys */ + /* + f0 - - t0 + f1 - 1 - f1 + */ + +t0r = f0r + f1r; +t0i = f0i - f1i; +f1r = f0r - f1r; +f1i = f0i + f1i; + + /* store result */ +ioptr[0] = scale*t0r; +ioptr[1] = scale*t0i; +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +} + +inline void rifft4pt(float *ioptr, float scale); +inline void rifft4pt(float *ioptr, float scale){ +/*** RADIX 8 rifft ***/ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float t0r, t0i, t1r, t1i; +float w0r = 1.0/MYROOT2; /* cos(pi/4) */ +const float Two = 2.0; + + /* bit reversed load */ +t0r = ioptr[0]; +t0i = ioptr[1]; +f2r = ioptr[2]; +f2i = ioptr[3]; +f1r = Two * ioptr[4]; +f1i = Two * ioptr[5]; +f3r = ioptr[6]; +f3i = ioptr[7]; + + /* start rfft */ +f0r = t0r + t0i; /* compute Re(x[0]) */ +f0i = t0r - t0i; /* compute Re(x[N/2]) */ + +t1r = f2r + f3r; +t1i = f2i - f3i; +t0r = f2r - f3r; +t0i = f2i + f3i; + +f2r = t1r - w0r * t0r - w0r * t0i; +f2i = t1i + w0r * t0r - w0r * t0i; +f3r = Two * t1r - f2r; +f3i = f2i - Two * t1i; + + /* Butterflys */ + /* + f0 - - t0 - - f0 + f1 - 1 - f1 - - f1 + f2 - - f2 - 1 - f2 + f3 - 1 - t1 - i - f3 + */ + +t0r = f0r + f1r; +t0i = f0i - f1i; +f1r = f0r - f1r; +f1i = f0i + f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = t0i - f2i; + +f3r = f1r + t1i; +f3i = f1i - t1r; +f1r = f1r - t1i; +f1i = f1i + t1r; + + /* store result */ +ioptr[0] = scale*f0r; +ioptr[1] = scale*f0i; +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +ioptr[4] = scale*f2r; +ioptr[5] = scale*f2i; +ioptr[6] = scale*f3r; +ioptr[7] = scale*f3i; +} + +inline void rifft8pt(float *ioptr, float scale); +inline void rifft8pt(float *ioptr, float scale){ +/*** RADIX 16 rifft ***/ +float w0r = 1.0/MYROOT2; /* cos(pi/4) */ +float w1r = MYCOSPID8; /* cos(pi/8) */ +float w1i = MYSINPID8; /* sin(pi/8) */ +float f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; +float f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; + + /* bit reversed load */ +t0r = ioptr[0]; +t0i = ioptr[1]; +f4r = ioptr[2]; +f4i = ioptr[3]; +f2r = ioptr[4]; +f2i = ioptr[5]; +f6r = ioptr[6]; +f6i = ioptr[7]; +f1r = Two * ioptr[8]; +f1i = Two * ioptr[9]; +f5r = ioptr[10]; +f5i = ioptr[11]; +f3r = ioptr[12]; +f3i = ioptr[13]; +f7r = ioptr[14]; +f7i = ioptr[15]; + + + /* start rfft */ +f0r = t0r + t0i; /* compute Re(x[0]) */ +f0i = t0r - t0i; /* compute Re(x[N/2]) */ + +t0r = f2r + f3r; +t0i = f2i - f3i; +t1r = f2r - f3r; +t1i = f2i + f3i; + +f2r = t0r - w0r * t1r - w0r * t1i; +f2i = t0i + w0r * t1r - w0r * t1i; +f3r = Two * t0r - f2r; +f3i = f2i - Two * t0i; + +t0r = f4r + f7r; +t0i = f4i - f7i; +t1r = f4r - f7r; +t1i = f4i + f7i; + +f4r = t0r - w1i * t1r - w1r * t1i; +f4i = t0i + w1r * t1r - w1i * t1i; +f7r = Two * t0r - f4r; +f7i = f4i - Two * t0i; + +t0r = f6r + f5r; +t0i = f6i - f5i; +t1r = f6r - f5r; +t1i = f6i + f5i; + +f6r = t0r - w1r * t1r - w1i * t1i; +f6i = t0i + w1i * t1r - w1r * t1i; +f5r = Two * t0r - f6r; +f5i = f6i - Two * t0i; + + /* Butterflys */ + /* + f0 - - t0 - - f0 - - f0 + f1* - 1 - f1 - - f1 - - f1 + f2 - - f2 - 1 - f2 - - f2 + f3 - 1 - t1 - i - f3 - - f3 + f4 - - t0 - - f4 - 1 - t0 + f5 - 1 - f5 - - f5 - w3 - f4 + f6 - - f6 - 1 - f6 - i - t1 + f7 - 1 - t1 - i - f7 - iw3- f6 + */ + +t0r = f0r + f1r; +t0i = f0i - f1i; +f1r = f0r - f1r; +f1i = f0i + f1i; + +t1r = f2r - f3r; +t1i = f2i - f3i; +f2r = f2r + f3r; +f2i = f2i + f3i; + +f0r = t0r + f2r; +f0i = t0i + f2i; +f2r = t0r - f2r; +f2i = t0i - f2i; + +f3r = f1r + t1i; +f3i = f1i - t1r; +f1r = f1r - t1i; +f1i = f1i + t1r; + + +t0r = f4r + f5r; +t0i = f4i + f5i; +f5r = f4r - f5r; +f5i = f4i - f5i; + +t1r = f6r - f7r; +t1i = f6i - f7i; +f6r = f6r + f7r; +f6i = f6i + f7i; + +f4r = t0r + f6r; +f4i = t0i + f6i; +f6r = t0r - f6r; +f6i = t0i - f6i; + +f7r = f5r + t1i; +f7i = f5i - t1r; +f5r = f5r - t1i; +f5i = f5i + t1r; + + +t0r = f0r - f4r; +t0i = f0i - f4i; +f0r = f0r + f4r; +f0i = f0i + f4i; + +t1r = f2r + f6i; +t1i = f2i - f6r; +f2r = f2r - f6i; +f2i = f2i + f6r; + +f4r = f1r - f5r * w0r + f5i * w0r; +f4i = f1i - f5r * w0r - f5i * w0r; +f1r = f1r * Two - f4r; +f1i = f1i * Two - f4i; + +f6r = f3r + f7r * w0r + f7i * w0r; +f6i = f3i - f7r * w0r + f7i * w0r; +f3r = f3r * Two - f6r; +f3i = f3i * Two - f6i; + + /* store result */ +ioptr[0] = scale*f0r; +ioptr[1] = scale*f0i; +ioptr[2] = scale*f1r; +ioptr[3] = scale*f1i; +ioptr[4] = scale*f2r; +ioptr[5] = scale*f2i; +ioptr[6] = scale*f3r; +ioptr[7] = scale*f3i; +ioptr[8] = scale*t0r; +ioptr[9] = scale*t0i; +ioptr[10] = scale*f4r; +ioptr[11] = scale*f4i; +ioptr[12] = scale*t1r; +ioptr[13] = scale*t1i; +ioptr[14] = scale*f6r; +ioptr[15] = scale*f6i; +} + +inline void ifrstage(float *ioptr, long M, float *Utbl); +inline void ifrstage(float *ioptr, long M, float *Utbl){ +/* Start RIFFT */ + +unsigned long pos; +unsigned long posi; +unsigned long diffUcnt; + +float *p0r, *p1r; +float *u0r, *u0i; + +float w0r, w0i; +float f0r, f0i, f1r, f1i, f4r, f4i, f5r, f5i; +float t0r, t0i, t1r, t1i; +const float Two = 2.0; + +pos = POW2(M-1); +posi = pos + 1; + +p0r = ioptr; +p1r = ioptr + pos/2; + +u0r = Utbl + POW2(M-3); + +w0r = *u0r, + +f0r = *(p0r); +f0i = *(p0r + 1); +f4r = *(p0r + pos); +f4i = *(p0r + posi); +f1r = *(p1r); +f1i = *(p1r + 1); +f5r = *(p1r + pos); +f5i = *(p1r + posi); + + t0r = f0r + f0i; + t0i = f0r - f0i; + t1r = f4r + f4r; + t1i = -f4i - f4i; + + f0r = f1r + f5r; + f0i = f1i - f5i; + f4r = f1r - f5r; + f4i = f1i + f5i; + + f1r = f0r - w0r * f4r - w0r * f4i; + f1i = f0i + w0r * f4r - w0r * f4i; + f5r = Two * f0r - f1r; + f5i = f1i - Two * f0i; + +*(p0r) = t0r; +*(p0r + 1) = t0i; +*(p0r + pos) = t1r; +*(p0r + posi) = t1i; +*(p1r) = f1r; +*(p1r + 1) = f1i; +*(p1r + pos) = f5r; +*(p1r + posi) = f5i; + +u0r = Utbl + 1; +u0i = Utbl + (POW2(M-2)-1); + +w0r = *u0r, +w0i = *u0i; + +p0r = (ioptr + 2); +p1r = (ioptr + (POW2(M-2)-1)*2); + + /* Butterflys */ + /* + f0 - t0 - f0 + f1 - t1 -w0- f1 + + f2 - t0 - f2 + f3 - t1 -iw0- f3 + */ + +for (diffUcnt = POW2(M-3)-1; diffUcnt > 0 ; diffUcnt--){ + + f0r = *(p0r); + f0i = *(p0r + 1); + f5r = *(p1r + pos); + f5i = *(p1r + posi); + f1r = *(p1r); + f1i = *(p1r + 1); + f4r = *(p0r + pos); + f4i = *(p0r + posi); + + t0r = f0r + f5r; + t0i = f0i - f5i; + t1r = f0r - f5r; + t1i = f0i + f5i; + + f0r = t0r - w0i * t1r - w0r * t1i; + f0i = t0i + w0r * t1r - w0i * t1i; + f5r = Two * t0r - f0r; + f5i = f0i - Two * t0i; + + t0r = f1r + f4r; + t0i = f1i - f4i; + t1r = f1r - f4r; + t1i = f1i + f4i; + + f1r = t0r - w0r * t1r - w0i * t1i; + f1i = t0i + w0i * t1r - w0r * t1i; + f4r = Two * t0r - f1r; + f4i = f1i - Two * t0i; + + *(p0r) = f0r; + *(p0r + 1) = f0i; + *(p1r + pos) = f5r; + *(p1r + posi) = f5i; + + w0r = *++u0r; + w0i = *--u0i; + + *(p1r) = f1r; + *(p1r + 1) = f1i; + *(p0r + pos) = f4r; + *(p0r + posi) = f4i; + + p0r += 2; + p1r -= 2; +}; +} + +void riffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow){ +/* Compute in-place real ifft on the rows of the input array */ +/* data order as from rffts1 */ +/* INPUTS */ +/* *ioptr = input data array in the following order */ +/* M = log2 of fft size */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = real output data array */ + +float scale; +long StageCnt; +long NDiffU; + +scale = 1.0/POW2(M); +M=M-1; +switch (M){ +case -1: + break; +case 0: + for (;Rows>0;Rows--){ + rifft1pt(ioptr, scale); /* a 2 pt fft */ + ioptr += 2*POW2(M); + } +case 1: + for (;Rows>0;Rows--){ + rifft2pt(ioptr, scale); /* a 4 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 2: + for (;Rows>0;Rows--){ + rifft4pt(ioptr, scale); /* an 8 pt fft */ + ioptr += 2*POW2(M); + } + break; +case 3: + for (;Rows>0;Rows--){ + rifft8pt(ioptr, scale); /* a 16 pt fft */ + ioptr += 2*POW2(M); + } + break; +default: + for (;Rows>0;Rows--){ + + ifrstage(ioptr, M+1, Utbl); + + scbitrevR2(ioptr, M, BRLow, scale); /* bit reverse and first radix 2 stage */ + + StageCnt = (M-1) / 3; // number of radix 8 stages + NDiffU = 2; // one radix 2 stage already complete + + if ( (M-1-(StageCnt * 3)) == 1 ){ + ibfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ + NDiffU *= 2; + } + + if ( (M-1-(StageCnt * 3)) == 2 ){ + ibfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ + NDiffU *= 4; + } + + if (M <= MCACHE){ + ibfstages(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ + } + + else{ + ifftrecurs(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ + } + + ioptr += 2*POW2(M); + } +} +} + diff --git a/ffts/src/fftlib.h b/ffts/src/fftlib.h new file mode 100644 index 0000000..86de4ac --- /dev/null +++ b/ffts/src/fftlib.h @@ -0,0 +1,76 @@ +#define MYRECIPLN2 1.442695040888963407359924681001892137426 // 1.0/log(2) + +/* some useful conversions between a number and its power of 2 */ +#define LOG2(a) (MYRECIPLN2*log(a)) // floating point logarithm base 2 +#define POW2(m) ((unsigned long) 1 << (m)) // integer power of 2 for m<32 + +/******************************************************************* +lower level fft stuff called by routines in fftext.c and fft2d.c +*******************************************************************/ + +void fftCosInit(long M, float *Utbl); +/* Compute Utbl, the cosine table for ffts */ +/* of size (pow(2,M)/4 +1) */ +/* INPUTS */ +/* M = log2 of fft size */ +/* OUTPUTS */ +/* *Utbl = cosine table */ + +void fftBRInit(long M, short *BRLow); +/* Compute BRLow, the bit reversed table for ffts */ +/* of size pow(2,M/2 -1) */ +/* INPUTS */ +/* M = log2 of fft size */ +/* OUTPUTS */ +/* *BRLow = bit reversed counter table */ + +void ffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow); +/* Compute in-place complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size (ex M=10 for 1024 point fft) */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = output data array */ + +void iffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow); +/* Compute in-place inverse complex fft on the rows of the input array */ +/* INPUTS */ +/* *ioptr = input data array */ +/* M = log2 of fft size */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = output data array */ + +void rffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow); +/* Compute in-place real fft on the rows of the input array */ +/* The result is the complex spectra of the positive frequencies */ +/* except the location for the first complex number contains the real */ +/* values for DC and Nyquest */ +/* INPUTS */ +/* *ioptr = real input data array */ +/* M = log2 of fft size */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = output data array in the following order */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ + + +void riffts1(float *ioptr, long M, long Rows, float *Utbl, short *BRLow); +/* Compute in-place real ifft on the rows of the input array */ +/* data order as from rffts1 */ +/* INPUTS */ +/* *ioptr = input data array in the following order */ +/* M = log2 of fft size */ +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ +/* Rows = number of rows in ioptr array (use Rows of 1 if ioptr is a 1 dimensional array) */ +/* *Utbl = cosine table */ +/* *BRLow = bit reversed counter table */ +/* OUTPUTS */ +/* *ioptr = real output data array */ diff --git a/ffts/src/files b/ffts/src/files new file mode 100644 index 0000000..2833fee --- /dev/null +++ b/ffts/src/files @@ -0,0 +1,22 @@ +tr "\r" "\n" < dxpose.c > tmp.c +mv tmp.c dxpose.c +tr "\r" "\n" < dxpose.h > tmp.c +mv tmp.c dxpose.h +tr "\r" "\n" < fft2d.c > tmp.c +mv tmp.c fft2d.c +tr "\r" "\n" < fft2d.h > tmp.c +mv tmp.c fft2d.h +tr "\r" "\n" < fftext.c > tmp.c +mv tmp.c fftext.c +tr "\r" "\n" < fftext.h > tmp.c +mv tmp.c fftext.h +tr "\r" "\n" < fftlib.c > tmp.c +mv tmp.c fftlib.c +tr "\r" "\n" < fftlib.h > tmp.c +mv tmp.c fftlib.h +tr "\r" "\n" < files > tmp.c +mv tmp.c n" < files +tr "\r" "\n" < matlib.c > tmp.c +mv tmp.c matlib.c +tr "\r" "\n" < matlib.h > tmp.c +mv tmp.c matlib.h diff --git a/ffts/src/matlib.c b/ffts/src/matlib.c new file mode 100644 index 0000000..4e8b682 --- /dev/null +++ b/ffts/src/matlib.c @@ -0,0 +1,297 @@ +/* a few routines from a vector/matrix library */ +#include "matlib.h" + +void xpose(float *indata, long iRsiz, float *outdata, long oRsiz, long Nrows, long Ncols){ +/* not in-place matrix transpose */ +/* INPUTS */ +/* *indata = input data array */ +/* iRsiz = offset to between rows of input data array */ +/* oRsiz = offset to between rows of output data array */ +/* Nrows = number of rows in input data array */ +/* Ncols = number of columns in input data array */ +/* OUTPUTS */ +/* *outdata = output data array */ + +float *irow; /* pointer to input row start */ +float *ocol; /* pointer to output col start */ +float *idata; /* pointer to input data */ +float *odata; /* pointer to output data */ +long RowCnt; /* row counter */ +long ColCnt; /* col counter */ +float T0; /* data storage */ +float T1; /* data storage */ +float T2; /* data storage */ +float T3; /* data storage */ +float T4; /* data storage */ +float T5; /* data storage */ +float T6; /* data storage */ +float T7; /* data storage */ +const long inRsizd1 = iRsiz; +const long inRsizd2 = 2*iRsiz; +const long inRsizd3 = inRsizd2+iRsiz; +const long inRsizd4 = 4*iRsiz; +const long inRsizd5 = inRsizd3+inRsizd2; +const long inRsizd6 = inRsizd4+inRsizd2; +const long inRsizd7 = inRsizd4+inRsizd3; +const long inRsizd8 = 8*iRsiz; + +ocol = outdata; +irow = indata; +for (RowCnt=Nrows/8; RowCnt>0; RowCnt--){ + idata = irow; + odata = ocol; + for (ColCnt=Ncols; ColCnt>0; ColCnt--){ + T0 = *idata; + T1 = *(idata+inRsizd1); + T2 = *(idata+inRsizd2); + T3 = *(idata+inRsizd3); + T4 = *(idata+inRsizd4); + T5 = *(idata+inRsizd5); + T6 = *(idata+inRsizd6); + T7 = *(idata+inRsizd7); + *odata = T0; + *(odata+1) = T1; + *(odata+2) = T2; + *(odata+3) = T3; + *(odata+4) = T4; + *(odata+5) = T5; + *(odata+6) = T6; + *(odata+7) = T7; + idata++; + odata += oRsiz; + } + irow += inRsizd8; + ocol += 8; +} +if (Nrows%8 != 0){ + for (ColCnt=Ncols; ColCnt>0; ColCnt--){ + idata = irow++; + odata = ocol; + ocol += oRsiz; + for (RowCnt=Nrows%8; RowCnt>0; RowCnt--){ + T0 = *idata; + *odata++ = T0; + idata += iRsiz; + } + } +} +} + +void cxpose(float *indata, long iRsiz, float *outdata, long oRsiz, long Nrows, long Ncols){ +/* not in-place complex float matrix transpose */ +/* INPUTS */ +/* *indata = input data array */ +/* iRsiz = offset to between rows of input data array */ +/* oRsiz = offset to between rows of output data array */ +/* Nrows = number of rows in input data array */ +/* Ncols = number of columns in input data array */ +/* OUTPUTS */ +/* *outdata = output data array */ + +float *irow; /* pointer to input row start */ +float *ocol; /* pointer to output col start */ +float *idata; /* pointer to input data */ +float *odata; /* pointer to output data */ +long RowCnt; /* row counter */ +long ColCnt; /* col counter */ +float T0r; /* data storage */ +float T0i; /* data storage */ +float T1r; /* data storage */ +float T1i; /* data storage */ +float T2r; /* data storage */ +float T2i; /* data storage */ +float T3r; /* data storage */ +float T3i; /* data storage */ +const long inRsizd1 = 2*iRsiz; +const long inRsizd1i = 2*iRsiz + 1; +const long inRsizd2 = 4*iRsiz; +const long inRsizd2i = 4*iRsiz + 1; +const long inRsizd3 = inRsizd2+inRsizd1; +const long inRsizd3i = inRsizd2+inRsizd1 + 1; +const long inRsizd4 = 8*iRsiz; + +ocol = outdata; +irow = indata; +for (RowCnt=Nrows/4; RowCnt>0; RowCnt--){ + idata = irow; + odata = ocol; + for (ColCnt=Ncols; ColCnt>0; ColCnt--){ + T0r = *idata; + T0i = *(idata +1); + T1r = *(idata+inRsizd1); + T1i = *(idata+inRsizd1i); + T2r = *(idata+inRsizd2); + T2i = *(idata+inRsizd2i); + T3r = *(idata+inRsizd3); + T3i = *(idata+inRsizd3i); + *odata = T0r; + *(odata+1) = T0i; + *(odata+2) = T1r; + *(odata+3) = T1i; + *(odata+4) = T2r; + *(odata+5) = T2i; + *(odata+6) = T3r; + *(odata+7) = T3i; + idata+=2; + odata += 2*oRsiz; + } + irow += inRsizd4; + ocol += 8; +} +if (Nrows%4 != 0){ + for (ColCnt=Ncols; ColCnt>0; ColCnt--){ + idata = irow; + odata = ocol; + for (RowCnt=Nrows%4; RowCnt>0; RowCnt--){ + T0r = *idata; + T0i = *(idata+1); + *odata = T0r; + *(odata+1) = T0i; + odata+=2; + idata += 2*iRsiz; + } + irow+=2; + ocol += 2*oRsiz; + } +} +} + +void cvprod(float *a, float *b, float *out, long N){ +/* complex vector product, can be in-place */ +/* product of complex vector *a times complex vector *b */ +/* INPUTS */ +/* N vector length */ +/* *a complex vector length N complex numbers */ +/* *b complex vector length N complex numbers */ +/* OUTPUTS */ +/* *out complex vector length N */ + +long OutCnt; /* output counter */ +float A0R; /* A storage */ +float A0I; /* A storage */ +float A1R; /* A storage */ +float A1I; /* A storage */ +float A2R; /* A storage */ +float A2I; /* A storage */ +float A3R; /* A storage */ +float A3I; /* A storage */ +float B0R; /* B storage */ +float B0I; /* B storage */ +float B1R; /* B storage */ +float B1I; /* B storage */ +float B2R; /* B storage */ +float B2I; /* B storage */ +float B3R; /* B storage */ +float B3I; /* B storage */ +float T0R; /* TMP storage */ +float T0I; /* TMP storage */ +float T1R; /* TMP storage */ +float T1I; /* TMP storage */ +float T2R; /* TMP storage */ +float T2I; /* TMP storage */ +float T3R; /* TMP storage */ +float T3I; /* TMP storage */ + +if (N>=4){ + A0R = *a; + B0R = *b; + A0I = *(a +1); + B0I = *(b +1); + A1R = *(a +2); + B1R = *(b +2); + A1I = *(a +3); + B1I = *(b +3); + A2R = *(a +4); + B2R = *(b +4); + A2I = *(a +5); + B2I = *(b +5); + A3R = *(a +6); + B3R = *(b +6); + A3I = *(a +7); + B3I = *(b +7); + T0R = A0R * B0R; + T0I = (A0R * B0I); + T1R = A1R * B1R; + T1I = (A1R * B1I); + T2R = A2R * B2R; + T2I = (A2R * B2I); + T3R = A3R * B3R; + T3I = (A3R * B3I); + T0R -= (A0I * B0I); + T0I = A0I * B0R + T0I; + T1R -= (A1I * B1I); + T1I = A1I * B1R + T1I; + T2R -= (A2I * B2I); + T2I = A2I * B2R + T2I; + T3R -= (A3I * B3I); + T3I = A3I * B3R + T3I; + for (OutCnt=N/4-1; OutCnt > 0; OutCnt--){ + a += 8; + b += 8; + A0R = *a; + B0R = *b; + A0I = *(a +1); + B0I = *(b +1); + A1R = *(a +2); + B1R = *(b +2); + A1I = *(a +3); + B1I = *(b +3); + A2R = *(a +4); + B2R = *(b +4); + A2I = *(a +5); + B2I = *(b +5); + A3R = *(a +6); + B3R = *(b +6); + A3I = *(a +7); + B3I = *(b +7); + *out = T0R; + *(out +1) = T0I; + *(out +2) = T1R; + *(out +3) = T1I; + *(out +4) = T2R; + *(out +5) = T2I; + *(out +6) = T3R; + *(out +7) = T3I; + T0R = A0R * B0R; + T0I = (A0R * B0I); + T1R = A1R * B1R; + T1I = (A1R * B1I); + T2R = A2R * B2R; + T2I = (A2R * B2I); + T3R = A3R * B3R; + T3I = (A3R * B3I); + T0R -= (A0I * B0I); + T0I = A0I * B0R + T0I; + T1R -= (A1I * B1I); + T1I = A1I * B1R + T1I; + T2R -= (A2I * B2I); + T2I = A2I * B2R + T2I; + T3R -= (A3I * B3I); + T3I = A3I * B3R + T3I; + out += 8; + } + a += 8; + b += 8; + *out = T0R; + *(out +1) = T0I; + *(out +2) = T1R; + *(out +3) = T1I; + *(out +4) = T2R; + *(out +5) = T2I; + *(out +6) = T3R; + *(out +7) = T3I; + out += 8; +} +for (OutCnt=N%4; OutCnt > 0; OutCnt--){ + A0R = *a++; + B0R = *b++; + A0I = *a++; + B0I = *b++; + T0R = A0R * B0R; + T0I = (A0R * B0I); + T0R -= (A0I * B0I); + T0I = A0I * B0R + T0I; + *out++ = T0R; + *out++ = T0I; +} +} diff --git a/ffts/src/matlib.h b/ffts/src/matlib.h new file mode 100644 index 0000000..baf9e6e --- /dev/null +++ b/ffts/src/matlib.h @@ -0,0 +1,33 @@ +/* a few routines from a vector/matrix library */ + +void xpose(float *indata, long iRsiz, float *outdata, long oRsiz, long Nrows, long Ncols); +/* not in-place matrix transpose */ +/* INPUTS */ +/* *indata = input data array */ +/* iRsiz = offset to between rows of input data array */ +/* oRsiz = offset to between rows of output data array */ +/* Nrows = number of rows in input data array */ +/* Ncols = number of columns in input data array */ +/* OUTPUTS */ +/* *outdata = output data array */ + +void cxpose(float *indata, long iRsiz, float *outdata, long oRsiz, long Nrows, long Ncols); +/* not in-place complex matrix transpose */ +/* INPUTS */ +/* *indata = input data array */ +/* iRsiz = offset to between rows of input data array */ +/* oRsiz = offset to between rows of output data array */ +/* Nrows = number of rows in input data array */ +/* Ncols = number of columns in input data array */ +/* OUTPUTS */ +/* *outdata = output data array */ + +void cvprod(float *a, float *b, float *out, long N); +/* complex vector product, can be in-place */ +/* product of complex vector *a times complex vector *b */ +/* INPUTS */ +/* N vector length */ +/* *a complex vector length N complex numbers */ +/* *b complex vector length N complex numbers */ +/* OUTPUTS */ +/* *out complex vector length N */ diff --git a/files.txt b/files.txt new file mode 100644 index 0000000..6e1bb4f --- /dev/null +++ b/files.txt @@ -0,0 +1,997 @@ +b .DS_Store +a nyquist.dsp +a nyquist.dsw +a todo.txt +a nyqwin.dsp +a convert.dsp +a advantages.txt +a convert.dsw +a jnyqide.bat +a Readme.txt +a files.txt +a releasenyqide.bat +a release.bat +a releasenyqwin.bat +a license.txt +a howtorelease.txt +a cmt/seqmwrite.h +a cmt/cext.c +a cmt/seqread.c +a cmt/seqread.h +a cmt/cext.h +a cmt/userio.c +a cmt/userio.h +a cmt/cleanup.c +a cmt/seqwrite.c +a cmt/seqwrite.h +a cmt/swlogic.h +a cmt/cleanup.h +a cmt/tempomap.c +a cmt/tempomap.h +a cmt/timebase.c +a cmt/cmdline.c +a cmt/timebase.h +a cmt/cmdline.h +a cmt/cmtcmd.c +a cmt/cmtcmd.h +a cmt/cmtio.c +a cmt/cmtio.h +a cmt/hash.h +a cmt/hashrout.h +a cmt/mem.c +a cmt/mem.h +a cmt/mfmidi.h +a cmt/midibuff.h +a cmt/midicode.h +a cmt/midierr.h +a cmt/midifile.c +a cmt/midifile.h +a cmt/midifns.c +a cmt/midifns.h +a cmt/midimgr.c +a cmt/midimgr.h +a cmt/moxc.c +a cmt/moxc.h +a cmt/musiprog.h +a cmt/pitch.h +a cmt/record.c +a cmt/record.h +a cmt/seq.c +a cmt/seq.h +a cmt/seqdecls.h +a cmt/seqmread.c +a cmt/seqmread.h +a cmt/seqmwrite.c +b demos/a-snd-file.snd +a demos/allewis/cell_aut.lsp +a demos/allewis/cellularautomata.htm +b demos/allewis/cmusic_pres.ppt +b demos/allewis/rule30.jpg +a demos/bandfx.htm +b demos/beginclip.jpg +b demos/demo-snd.aiff +b demos/demo.mid +a demos/distortion.htm +a demos/examples.lsp +a demos/fft_tutorial.htm +b demos/largeclip.jpg +a demos/lpc-exmpl.dat +a demos/lpc_tutorial.htm +a demos/lpcdemo.lsp +a demos/midi_tutorial.htm +a demos/pitch_change.htm +a demos/rhythm_tutorial.htm +a demos/scratch_tutorial.htm +a demos/sequence_example.htm +a demos/shepard.lsp +a demos/shepard.ny +b demos/softclip.gif +b demos/softclip.jpg +a demos/stktest.lsp +a demos/warble_tutorial.htm +a demos/wind_tutorial.htm +a demos/piano.htm +a demos/fft_demo.lsp +a demos/examples_home.htm +a demos/voice_synthesis.htm +a demos/pmorales/pjmg.lsp +a demos/pmorales/readme.txt +a demos/pmorales/a4.lsp +a demos/pmorales/a5.lsp +a demos/pmorales/a6.lsp +a demos/pmorales/b1.lsp +a demos/pmorales/b10.lsp +a demos/pmorales/b2.lsp +a demos/pmorales/b3.lsp +a demos/pmorales/b5.lsp +a demos/pmorales/b7.lsp +a demos/pmorales/b8.lsp +a demos/pmorales/b9.lsp +a demos/pmorales/c1.lsp +a demos/pmorales/d1.lsp +a demos/pmorales/e2.lsp +a demos/pmorales/ks.lsp +a demos/pmorales/partial.lsp +a demos/pmorales/phm.lsp +a demos/pmorales/buzz.lsp +b doc/fig1.gif +b doc/fig2.gif +b doc/fig3.gif +b doc/fig4.gif +b doc/fig5.gif +b doc/fig6.gif +a doc/foot.html +a doc/home.html +a doc/part1.html +a doc/part2.html +a doc/part3.html +a doc/part4.html +a doc/part5.html +a doc/part6.html +a doc/part7.html +a doc/part8.html +a doc/part9.html +a doc/part10.html +a doc/part11.html +a doc/part12.html +a doc/indx.html +a fft/fftn.c +a fft/fftn.h +a jnyqide/README.txt +b jnyqide/closefile.gif +a jnyqide/finddialog.java +b jnyqide/help.gif +a jnyqide/keywords.txt +a jnyqide/lispfilefilter.java +a jnyqide/main.java +a jnyqide/mainframe.java +a jnyqide/mainframe_aboutbox.java +a jnyqide/notfounddialog.java +a jnyqide/nyqplot.java +a jnyqide/nyquistfile.java +a jnyqide/nyquistthread.java +b jnyqide/openfile.gif +a jnyqide/pair.java +a jnyqide/plotframe.java +a jnyqide/plotmouseadapter.java +a jnyqide/replacedialog.java +a jnyqide/syntaxthread.java +a jnyqide/textcolor.java +a lib/bandfx.lsp +a lib/compress.lsp +a lib/dtmf.lsp +a lib/gran.lsp +a lib/grapheq.lsp +a lib/lpc.lsp +a lib/midishow.lsp +a lib/pianosyn.lsp +a lib/reverb.lsp +a lib/soften.lsp +a lib/time-delay-fns.lsp +b lib/piano/rls44100.pcm +b lib/piano/dur.tab +b lib/piano/gmax.tab +b lib/piano/demo.mid +b lib/piano/rls48000.pcm +b lib/piano/pn00.cod +b lib/piano/pn01.cod +b lib/piano/pn02.cod +b lib/piano/pn03.cod +b lib/piano/pn04.cod +b lib/piano/pn05.cod +b lib/piano/pn06.cod +b lib/piano/pn07.cod +b lib/piano/pn08.cod +b lib/piano/pn09.cod +b lib/piano/pn10.cod +b lib/piano/pn11.cod +b lib/piano/pn12.cod +b lib/piano/pn13.cod +b lib/piano/pn14.cod +b lib/piano/pn15.cod +b lib/piano/pn16.cod +b lib/piano/pn17.cod +b lib/piano/pn18.cod +b lib/piano/pn19.cod +b lib/piano/pn20.cod +b lib/piano/pn21.cod +b lib/piano/pn22.cod +b lib/piano/rlsrate.tab +b lib/piano/rls8000.pcm +b lib/piano/demo.mp3 +b lib/piano/att11025.pcm +b lib/piano/att16000.pcm +b lib/piano/att22050.pcm +b lib/piano/att32000.pcm +b lib/piano/att44100.pcm +b lib/piano/att48000.pcm +b lib/piano/att8000.pcm +b lib/piano/rls11025.pcm +b lib/piano/rls16000.pcm +b lib/piano/rls22050.pcm +b lib/piano/rls32000.pcm +a lpc/compile.txt +a lpc/lpc-example.dat +a lpc/lpc-exmpl.dat +a lpc/lpc-orig.lsp +a lpc/lpc.lsp +a lpc/lpcdemo-orig.lsp +a lpc/lpcdemo.lsp +a lpc/prims-ref.txt +a lpc/readme.txt +a lpc/src/allpoles.alg +a lpc/src/lpreson.alg +a lpc/src/lpanal.c +a lpc/src/lpanal.h +b macosxproject/build/.DS_store +b macosxproject/build/nyquist.build/.DS_store +b macosxproject/build/nyquist.build/Interface Generator.build/Interface Generator.hmap +b macosxproject/build/nyquist.build/nyquist.pbxindex/strings.pbxstrings/control +b macosxproject/build/nyquist.build/nyquist.pbxindex/strings.pbxstrings/strings +b macosxproject/build/nyquist.build/nyquist.pbxindex/categories.pbxbtree +b macosxproject/build/nyquist.build/nyquist.pbxindex/decls.pbxbtree +b macosxproject/build/nyquist.build/nyquist.pbxindex/files.pbxbtree +b macosxproject/build/nyquist.build/nyquist.pbxindex/imports.pbxbtree +b macosxproject/build/nyquist.build/nyquist.pbxindex/nyquist.indexed-headers +b macosxproject/build/nyquist.build/nyquist.pbxindex/nyquist.indexed-precomps +b macosxproject/build/nyquist.build/nyquist.pbxindex/pbxindex.header +b macosxproject/build/nyquist.build/nyquist.pbxindex/protocols.pbxbtree +b macosxproject/build/nyquist.build/nyquist.pbxindex/refs.pbxbtree +b macosxproject/build/nyquist.build/nyquist.pbxindex/subclasses.pbxbtree +b macosxproject/build/nyquist.build/nyquist.pbxindex/symbols0.pbxsymbols +b macosxproject/nyquistproject.pbproj/project.pbxproj +b macosxproject/.DS_Store +b macosxproject/Nyquist.icns +b macosxproject/README +b macproject/nyquistdata/CWSettingsMacOS.stg +b macproject/packer/packerdata/.DS_Store +b macproject/packer/packerdata/.CWSettingsMacOS.stg +b macproject/packer/packer.mcp +b macproject/unpacker/unpackerdata/.DS_Store +b macproject/unpacker/unpackerdata/CWSettingsMacOS.stg +b macproject/unpacker/unpackerdata/unpacker/TargetDataMacOS.tdt +b macproject/unpacker/unpacker.mcp +a macproject/mac_port_changes.txt +b macproject/nyquist.mcp +b macproject/nyquist.rsrc +b macproject/NyquistIcon +b macproject/NyquistIcon.sit +a misc/Makefile +a misc/args.h +a misc/cext.h +a misc/cmdline.c +a misc/cmdline.h +a misc/convert.c +a misc/convert.h +a misc/mac-to-win.lsp +a misc/filelist.c +a misc/filelist.dsp +a misc/intgen.c +a misc/packer.c +a misc/packer.dsp +a misc/play.c +a misc/plot.c +a misc/sampleprint.c +a misc/sine.c +a misc/stdefs2.h +a misc/unpacker.c +a misc/unpacker.dsp +a misc/makefile.lsp +a misc/transfiles.lsp +a misc/intgen2.c +a misc/intgen_win32/intgen.dsp +a misc/cmu/cmuinstall.bat +a misc/cmu/cmuinstall2.bat +a misc/cmu/cmu-linux-install.lsp +a misc/cmu/init.lsp +a misc/cmu/cleanup.bat +a misc/cmu/music.software.html +a misc/cmu/new.html +a misc/cmu/restore.bat +b nyqide/doc/nyqide_plot.gif +b nyqide/doc/nyquistide.gif +a nyqide/doc/tips.htm +b nyqide/nyqide.exe +b nyqide/nyqide_src.zip +a nyqide/readme-vcl.txt +a nyqsrc/nfilterkit.c +a nyqsrc/add.c +a nyqsrc/nfilterkit.h +a nyqsrc/add.h +a nyqsrc/resampv.c +a nyqsrc/resampv.h +a nyqsrc/avg.c +a nyqsrc/resamp.c +a nyqsrc/avg.h +a nyqsrc/resamp.h +a nyqsrc/samples.c +a nyqsrc/samples.h +a nyqsrc/compose.c +a nyqsrc/rfftw.h +a nyqsrc/seqfn.wcl +a nyqsrc/seqfnint.c +a nyqsrc/compose.h +a nyqsrc/convolve.c +a nyqsrc/convolve.h +a nyqsrc/seqext.c +a nyqsrc/seqext.h +a nyqsrc/cque.h +a nyqsrc/seqfn.cl +a nyqsrc/seqfnint.lsp +a nyqsrc/debug.c +a nyqsrc/seqinterf.c +a nyqsrc/debug.h +a nyqsrc/seqfnintdefs.h +a nyqsrc/downsample.c +a nyqsrc/seqfnintptrs.h +a nyqsrc/downsample.h +a nyqsrc/seqinterf.h +a nyqsrc/falloc.c +a nyqsrc/sndfn.wcl +a nyqsrc/sndfnint.c +a nyqsrc/sndfnintptrs.h +a nyqsrc/ffilterkit.c +a nyqsrc/sndfn.cl +a nyqsrc/sndfnint.lsp +a nyqsrc/f0.cpp +a nyqsrc/f0.h +a nyqsrc/fftw.h +a nyqsrc/ffilterkit.h +a nyqsrc/sndseq.c +a nyqsrc/sndwrite.c +a nyqsrc/sndwritepa.c +a nyqsrc/fft.c +a nyqsrc/fft-rbd.c +a nyqsrc/sndread.c +a nyqsrc/sndread.h +a nyqsrc/falloc.h +a nyqsrc/sndmax.c +a nyqsrc/sndmax.h +a nyqsrc/fft.h +a nyqsrc/sndwrite.h +a nyqsrc/sound.c +a nyqsrc/fftr4.c +a nyqsrc/sndseq.h +a nyqsrc/stats.c +a nyqsrc/sndfail.c +a nyqsrc/exitpa.h +a nyqsrc/fresample.h +a nyqsrc/fsmallfilter.h +a nyqsrc/sound.h +a nyqsrc/stdefs.h +a nyqsrc/handlers.c +a nyqsrc/inverse.c +a nyqsrc/inverse.h +a nyqsrc/local.c +a nyqsrc/sndfnintdefs.h +a nyqsrc/localdefs.h +a nyqsrc/localptrs.h +a nyqsrc/lpanal.c +a nyqsrc/lpanal.h +a nyqsrc/multiread.c +a nyqsrc/multiread.h +a nyqsrc/multiseq.c +a nyqsrc/multiseq.h +a nyqsrc/nyx.c +a nyqsrc/nyx.h +a nyqsrc/oldyin.c +a nyqsrc/oldyin.h +a nyqsrc/probe.c +a nyqsrc/probe.h +a nyqsrc/yin.c +a nyqsrc/yin.h +a nyqstk/globals.h +a nyqstk/instr.cpp +a nyqstk/instr.h +a nyqstk/stkinit.cpp +a nyqstk/stkinit.h +a nyqstk/include/Clarinet.h +a nyqstk/include/Delay.h +a nyqstk/include/DelayL.h +a nyqstk/include/Envelope.h +a nyqstk/include/Filter.h +a nyqstk/include/Instrmnt.h +a nyqstk/include/Noise.h +a nyqstk/include/OneZero.h +a nyqstk/include/ReedTabl.h +a nyqstk/include/Saxofony.h +a nyqstk/include/SKINI.msg +a nyqstk/include/Stk.h +a nyqstk/include/WaveLoop.h +a nyqstk/include/WvIn.h +a nyqstk/src/Clarinet.cpp +a nyqstk/src/Delay.cpp +a nyqstk/src/DelayL.cpp +a nyqstk/src/Envelope.cpp +a nyqstk/src/Filter.cpp +a nyqstk/src/Instrmnt.cpp +a nyqstk/src/Noise.cpp +a nyqstk/src/OneZero.cpp +a nyqstk/src/ReedTabl.cpp +a nyqstk/src/Saxofony.cpp +a nyqstk/src/Stk.cpp +a nyqstk/src/WaveLoop.cpp +a nyqstk/src/WvIn.cpp +a portaudio/aclocal.m4 +a portaudio/config.doxy +a portaudio/config.guess +a portaudio/config.sub +a portaudio/configure +a portaudio/configure.in +a portaudio/fixdir.bat +a portaudio/fixfile.bat +a portaudio/index.html +a portaudio/install-sh +a portaudio/LICENSE.txt +a portaudio/Makefile.in +a portaudio/rbdnotes.txt +a portaudio/README.txt +a portaudio/V19-devel-readme.txt +a portaudio/docs/index.html +a portaudio/docs/latency.html +a portaudio/docs/pa_impl_guide.html +a portaudio/docs/pa_impl_startstop.html +a portaudio/docs/pa_tutorial.html +a portaudio/docs/pa_tut_asio.html +a portaudio/docs/pa_tut_callback.html +a portaudio/docs/pa_tut_devs.html +a portaudio/docs/pa_tut_explore.html +a portaudio/docs/pa_tut_init.html +a portaudio/docs/pa_tut_mac.html +a portaudio/docs/pa_tut_mac_osx.html +a portaudio/docs/pa_tut_open.html +a portaudio/docs/pa_tut_oss.html +a portaudio/docs/pa_tut_over.html +a portaudio/docs/pa_tut_pc.html +a portaudio/docs/pa_tut_run.html +a portaudio/docs/pa_tut_rw.html +a portaudio/docs/pa_tut_term.html +a portaudio/docs/pa_tut_util.html +a portaudio/docs/portaudio_h.txt +b portaudio/docs/portaudio_icmc2001.pdf +a portaudio/docs/proposals.html +a portaudio/docs/releases.html +a portaudio/pablio/pablio.c +a portaudio/pablio/pablio.def +a portaudio/pablio/pablio.h +a portaudio/pablio/README.txt +a portaudio/pablio/ringbuffer.c +a portaudio/pablio/ringbuffer.h +a portaudio/pablio/test_rw.c +a portaudio/pablio/test_rw_echo.c +a portaudio/pablio/test_w_saw.c +a portaudio/pablio/test_w_saw8.c +a portaudio/pa_asio/ASIO-README.txt +b portaudio/pa_asio/Callback_adaptation_.pdf +a portaudio/pa_asio/iasiothiscallresolver.cpp +a portaudio/pa_asio/iasiothiscallresolver.h +a portaudio/pa_asio/pa_asio.cpp +a portaudio/pa_asio/pa_asio.h +b portaudio/pa_asio/Pa_ASIO.pdf +a portaudio/pa_beos/pa_beos_mk.cc +a portaudio/pa_beos/PlaybackNode.cc +a portaudio/pa_beos/PlaybackNode.h +a portaudio/pa_common/pa_allocation.c +a portaudio/pa_common/pa_allocation.h +a portaudio/pa_common/pa_converters.c +a portaudio/pa_common/pa_converters.h +a portaudio/pa_common/pa_cpuload.c +a portaudio/pa_common/pa_cpuload.h +a portaudio/pa_common/pa_dither.c +a portaudio/pa_common/pa_dither.h +a portaudio/pa_common/pa_endianness.h +a portaudio/pa_common/pa_front.c +a portaudio/pa_common/pa_hostapi.h +a portaudio/pa_common/pa_process.c +a portaudio/pa_common/pa_process.h +a portaudio/pa_common/pa_skeleton.c +a portaudio/pa_common/pa_stream.c +a portaudio/pa_common/pa_stream.h +a portaudio/pa_common/pa_trace.c +a portaudio/pa_common/pa_trace.h +a portaudio/pa_common/pa_util.h +a portaudio/pa_common/portaudio.h +a portaudio/pa_dll_switch/letter_from_tim_010817.txt +a portaudio/pa_dll_switch/loadPA_DLL.cpp +a portaudio/pa_dll_switch/PaDllEntry.h +a portaudio/pa_dll_switch/pa_lib.c +a portaudio/pa_dll_switch/portaudio.h +a portaudio/pa_jack/pa_jack.c +a portaudio/pa_linux_alsa/pa_linux_alsa.c +a portaudio/pa_linux_alsa/pa_linux_alsa.h +a portaudio/pa_mac_core/notes.txt +a portaudio/pa_mac_core/pa_mac_core.c +a portaudio/pa_mac_sm/pa_mac_sm.c +a portaudio/pa_sgi/pa_sgi.c +a portaudio/pa_tests/debug_convert.c +a portaudio/pa_tests/debug_dither_calc.c +a portaudio/pa_tests/debug_dual.c +a portaudio/pa_tests/debug_multi_in.c +a portaudio/pa_tests/debug_multi_out.c +a portaudio/pa_tests/debug_record.c +a portaudio/pa_tests/debug_record_reuse.c +a portaudio/pa_tests/debug_sine.c +a portaudio/pa_tests/debug_sine_amp.c +a portaudio/pa_tests/debug_sine_formats.c +a portaudio/pa_tests/debug_srate.c +a portaudio/pa_tests/debug_test1.c +a portaudio/pa_tests/paqa_devs.c +a portaudio/pa_tests/paqa_errs.c +a portaudio/pa_tests/patest1.c +a portaudio/pa_tests/patest_buffer.c +a portaudio/pa_tests/patest_callbackstop.c +a portaudio/pa_tests/patest_clip.c +a portaudio/pa_tests/patest_dither.c +a portaudio/pa_tests/patest_hang.c +a portaudio/pa_tests/patest_in_overflow.c +a portaudio/pa_tests/patest_latency.c +a portaudio/pa_tests/patest_leftright.c +a portaudio/pa_tests/patest_longsine.c +a portaudio/pa_tests/patest_many.c +a portaudio/pa_tests/patest_maxsines.c +a portaudio/pa_tests/patest_multi_sine.c +a portaudio/pa_tests/patest_out_underflow.c +a portaudio/pa_tests/patest_pink.c +a portaudio/pa_tests/patest_prime.c +a portaudio/pa_tests/patest_read_record.c +a portaudio/pa_tests/patest_record.c +a portaudio/pa_tests/patest_ringmix.c +a portaudio/pa_tests/patest_saw.c +a portaudio/pa_tests/patest_sine.c +a portaudio/pa_tests/patest_sine8.c +a portaudio/pa_tests/patest_sine_formats.c +a portaudio/pa_tests/patest_sine_time.c +a portaudio/pa_tests/patest_start_stop.c +a portaudio/pa_tests/patest_stop.c +a portaudio/pa_tests/patest_sync.c +a portaudio/pa_tests/patest_toomanysines.c +a portaudio/pa_tests/patest_underflow.c +a portaudio/pa_tests/patest_wire.c +a portaudio/pa_tests/patest_write_sine.c +a portaudio/pa_tests/pa_devs.c +a portaudio/pa_tests/pa_fuzz.c +a portaudio/pa_tests/pa_minlat.c +a portaudio/pa_tests/README.txt +a portaudio/pa_unix/pa_unix_hostapis.c +a portaudio/pa_unix/pa_unix_util.c +b portaudio/pa_unix_oss/low_latency_tip.txt +a portaudio/pa_unix_oss/pa_unix_oss.c +a portaudio/pa_unix_oss/recplay.c +a portaudio/pa_win/pa_win_hostapis.c +a portaudio/pa_win/pa_win_util.c +a portaudio/pa_win/pa_x86_plain_converters.c +a portaudio/pa_win/pa_x86_plain_converters.h +a portaudio/pa_win/dev-cpp/Makefile-dll +a portaudio/pa_win/dev-cpp/Makefile-static +a portaudio/pa_win/dev-cpp/portaudio-dll.dev +a portaudio/pa_win/dev-cpp/portaudio-static.dev +a portaudio/pa_win/dev-cpp/readme.txt +a portaudio/pa_win/msvc/clean.bat +a portaudio/pa_win/msvc/make.bat +a portaudio/pa_win/msvc/Makefile.msvc +a portaudio/pa_win/msvc/portaudio.def +a portaudio/pa_win/msvc/readme.txt +a portaudio/pa_win/msvc/setenv.bat +a portaudio/pa_win_ds/dsound_wrapper.c +a portaudio/pa_win_ds/dsound_wrapper.h +a portaudio/pa_win_ds/pa_win_ds.c +a portaudio/pa_win_wmme/pa_win_wmme.c +a portaudio/pa_win_wmme/pa_win_wmme.h +a portaudio/testcvs/changeme.txt +b portaudio_test/portaudio_test.dsp +a runtime/bug.lsp +a runtime/evalenv.lsp +a runtime/follow.lsp +a runtime/init.lsp +a runtime/nyqmisc.lsp +a runtime/printrec.lsp +a runtime/profile.lsp +a runtime/seq.lsp +a runtime/seqfnint.lsp +a runtime/sndfnint.lsp +a runtime/stk.lsp +a runtime/test.lsp +a runtime/xlinit.lsp +a runtime/fileio.lsp +a runtime/nyinit.lsp +a runtime/nyquist.lsp +a runtime/dspprims.lsp +a runtime/misc.lsp +a runtime/seqmidi.lsp +a runtime/nyquist-plot.txt +b runtime/rawwaves/sinewave.raw +a snd/sndnt.h +a snd/sndrs6k.h +a snd/audio.c +a snd/sndsystemmac.h +a snd/audiolinux.c +a snd/sndsystem.c +a snd/sndwin32.c +a snd/audiomac.c +a snd/sndsystem.h +a snd/sndwin32.h +a snd/audiomac.h +a snd/audiopa.c +a snd/sndlinux.c +a snd/sndcvt.c +a snd/wxsnd.h +a snd/audionone.c +a snd/sndwrite.h +a snd/wxsnd.cpp +a snd/audiooss.c +a snd/sndfaillinux.c +a snd/audiors6k.c +a snd/audiosgi.c +a snd/audiowin32.c +a snd/audiowin32.h +a snd/ieeecvt.c +a snd/ieeecvt.h +a snd/rs6kplaydemo.c +a snd/snd.c +a snd/snd.txt +a snd/sndconfig.h +a snd/sndfileio.h +a snd/sndfreebsd.h +a snd/sndhead.h +a snd/sndheader.h +a snd/sndio.c +a snd/sndlinux.h +a snd/sndmac.c +a snd/sndmac.h +a snd/sndfailwin32.c +a snd/convert.c +a snd/sndheader.c +a snd/snd.h +a snd/snd.htm +a sys/switches.h.template +a sys/unix/io.c +a sys/unix/io.h +a sys/unix/pl +a sys/unix/setup +a sys/unix/sndsystem.h +a sys/unix/switches.h +a sys/unix/term.c +a sys/unix/term.h +a sys/unix/termtest.c +a sys/unix/osstuff.c +a sys/unix/cmu/backup.script +a sys/unix/cmu/tar.script +a sys/unix/cmu/update.lsp +a sys/unix/linux/system.lsp +a sys/unix/linux/Makefile +a sys/unix/next/Makefile +a sys/unix/next/system.lsp +a sys/unix/pmax/Makefile +a sys/unix/pmax/system.lsp +a sys/unix/rs6k/Makefile +a sys/unix/rs6k/plotscript +a sys/unix/rs6k/system.lsp +a sys/unix/sgi/Makefile +a sys/unix/sgi/system.lsp +a sys/unix/sparc/Makefile +a sys/unix/sparc/system.lsp +a sys/win/msvc/sndsystem.h +a sys/win/msvc/switches.h +a sys/win/msvc/system.lsp +a sys/win/msvc/winfun.c +a sys/win/msvc/winfun.h +a sys/win/msvc/winstuff.c +a sys/win/wingui/winmain.h +a sys/win/wingui/textio.h +a sys/win/wingui/button.h +a sys/win/wingui/winmain.cpp +a sys/win/wingui/winmain.rc +a sys/win/wingui/cppext.h +a sys/win/wingui/textio.cpp +a sys/win/wingui/longque.cpp +a sys/win/wingui/longque.h +a sys/win/wingui/winguistuff.c +b sys/win/wingui/nycon.ico +a sys/win/wingui/resource.h +a sys/win/wingui/slider.h +b sys/win/wingui/winmain.aps +a sys/win/wingui/winmain2.h +a sys/win/wingui/xlextstart.c +a sys/win/wingui/xlispfns.c +a sys/win/wingui/xlispfns.h +a sys/win/wingui/typein.h +a sys/mac/xlextstart.c +a sys/mac/system.lsp +a sys/mac/switches.h +a sys/mac/sndsystem.h +a sys/mac/macdrag.c +a sys/mac/macstuff.h +a sys/mac/macstuff.c +a sys/mac/macptrs.h +a sys/mac/macint.h +a sys/mac/macint.c +a sys/mac/MacHandleEv.h +a sys/mac/MacHandleEv.c +a sys/mac/MacGlobals.h +a sys/mac/macfun.c +a sys/mac/MacFileUtils.h +a sys/mac/MacFileUtils.c +a sys/mac/MacDrag.h +a sys/mac/MacCommandWin.h +a sys/mac/MacCommandWin.c +a sys/mac/MacAE.c +a sys/mac/macaboutbox.h +a sys/mac/macaboutbox.c +a test/alex.lsp +a test/alpass.lsp +a test/arraystream.lsp +a test/articulator1.txt +a test/audio.lsp +a test/cnvl.lsp +a test/comb.lsp +a test/convolve.lsp +a test/delaytest.lsp +a test/eq.lsp +a test/fft.lsp +a test/gab.lsp +a test/gatetest.lsp +a test/gr.lsp +a test/ifft.lsp +a test/ifftnt.lsp +a test/init.lsp +a test/linux-segfault.lsp +a test/midi2.lsp +a test/ms2.lsp +a test/multiseq.lsp +a test/natbug.lsp +a test/nonewline.lsp +a test/overwrite.lsp +a test/product.lsp +a test/rbd.lsp +a test/readme +a test/seqmiditest.lsp +a test/shape.lsp +a test/sr.lsp +a test/stktest.lsp +a test/str.lsp +a test/temp.gio +a test/temp2.gio +a test/temp3.gio +a test/test.gio +a test/tp.lsp +a test/variable-resample.lsp +a test/warp.lsp +a tran/abs.alg +a tran/abs.c +a tran/abs.h +a tran/allpoles.alg +a tran/allpoles.c +a tran/allpoles.h +a tran/buzz.alg +a tran/buzz.c +a tran/buzz.h +a tran/pluck.alg +a tran/pluck.c +a tran/pluck.h +a tran/alpass.alg +a tran/alpass.c +a tran/alpass.h +a tran/alpasscv.alg +a tran/alpasscv.c +a tran/alpasscv.h +a tran/alpassvc.alg +a tran/alpassvc.c +a tran/alpassvc.h +a tran/alpassvv.alg +a tran/alpassvv.c +a tran/alpassvv.h +a tran/amosc.alg +a tran/amosc.c +a tran/amosc.h +a tran/areson.alg +a tran/areson.c +a tran/areson.h +a tran/aresoncv.alg +a tran/aresoncv.c +a tran/aresoncv.h +a tran/aresonvc.alg +a tran/aresonvc.c +a tran/aresonvc.h +a tran/aresonvv.alg +a tran/aresonvv.c +a tran/aresonvv.h +a tran/atone.alg +a tran/atone.c +a tran/atone.h +a tran/atonev.alg +a tran/atonev.c +a tran/atonev.h +a tran/biquad.alg +a tran/biquad.c +a tran/biquad.h +a tran/convolve.alg +a tran/coterm.alg +a tran/coterm.c +a tran/coterm.h +a tran/delay.alg +a tran/delaycc.c +a tran/delaycc.h +a tran/delaycv.alg +a tran/delaycv.c +a tran/delaycv.h +a tran/downproto.alg +a tran/eqbandv.alg +a tran/eqbandvvv.alg +a tran/eqbandvvv.c +a tran/eqbandvvv.h +a tran/exprel.alg +a tran/exp.alg +a tran/exp.c +a tran/exp.h +a tran/follow.alg +a tran/follow.c +a tran/fmosc.c +a tran/fmosc.h +a tran/follow.h +a tran/fromarraystream.alg +a tran/fromarraystream.c +a tran/fromarraystream.h +a tran/fromobject.alg +a tran/ifft-old.alg +a tran/ifft.alg +a tran/gate.alg +a tran/fromobject.c +a tran/gate.c +a tran/fromobject.h +a tran/gate.h +a tran/innerloop.lsp +a tran/ifft.c +a tran/ifft.h +a tran/init.lsp +a tran/instrclar.alg +a tran/instrclar.c +a tran/instrclar.h +a tran/instrclarall.alg +a tran/instrclarall.c +a tran/instrclarall.h +a tran/instrclarfreq.alg +a tran/instrclarfreq.c +a tran/instrclarfreq.h +a tran/instrsax.alg +a tran/instrsax.c +a tran/instrsax.h +a tran/instrsaxall.alg +a tran/instrsaxall.c +a tran/instrsaxall.h +a tran/instrsaxfreq.alg +a tran/instrsaxfreq.c +a tran/instrsaxfreq.h +a tran/integrate.alg +a tran/integrate.c +a tran/log.alg +a tran/log.c +a tran/log.h +a tran/lpreson.alg +a tran/lpreson.c +a tran/lpreson.h +a tran/offset.alg +a tran/integrate.h +a tran/maxv.alg +a tran/maxv.c +a tran/maxv.h +a tran/offset.c +a tran/chase.alg +a tran/oneshot.alg +a tran/oneshot.c +a tran/chase.c +a tran/offset.h +a tran/oneshot.h +a tran/chase.h +a tran/partial.alg +a tran/partial.c +a tran/clip.alg +a tran/osc.alg +a tran/osc.c +a tran/clip.c +a tran/osc.h +a tran/partial.h +a tran/clip.h +a tran/siosc.h +a tran/slope.alg +a tran/prod.alg +a tran/congen.alg +a tran/prod.c +a tran/prod.h +a tran/congen.c +a tran/pwl.alg +a tran/pwl.c +a tran/congen.h +a tran/pwl.h +a tran/tonev.alg +a tran/tonev.c +a tran/const.alg +a tran/slope.c +a tran/slope.h +a tran/sqrt.alg +a tran/sqrt.c +a tran/sqrt.h +a tran/tapf.alg +a tran/tapf.c +a tran/tapf.h +a tran/const.c +a tran/tapv.alg +a tran/tapv.c +a tran/const.h +a tran/tapv.h +a tran/tone.alg +a tran/tone.c +a tran/tone.h +a tran/tonev.h +a tran/upsample.alg +a tran/upsample.c +a tran/quantize.alg +a tran/writemake.lsp +a tran/white.c +a tran/quantize.c +a tran/upsample.h +a tran/white.alg +a tran/white.h +a tran/quantize.h +a tran/fmosc.alg +a tran/recip.alg +a tran/writesusp.lsp +a tran/recip.c +a tran/writetoss.lsp +a tran/recip.h +a tran/translate.lsp +a tran/shape.alg +a tran/reson.alg +a tran/reson.c +a tran/reson.h +a tran/resoncv.alg +a tran/resoncv.c +a tran/resoncv.h +a tran/resonvc.alg +a tran/resonvc.c +a tran/resonvc.h +a tran/resonvv.alg +a tran/resonvv.c +a tran/resonvv.h +a tran/sampler.alg +a tran/sampler.c +a tran/sampler.h +a tran/scale.alg +a tran/scale.c +a tran/scale.h +a tran/shape.c +a tran/shape.h +a tran/sine.alg +a tran/sine.c +a tran/sine.h +a tran/siosc.alg +a tran/siosc.c +a xlisp/extern.c +a xlisp/extern.h +a xlisp/osdefs.h +a xlisp/osptrs.h +a xlisp/path.c +a xlisp/xlbfun.c +a xlisp/xlcont.c +a xlisp/xldmem.h +a xlisp/xlfio.c +a xlisp/xlglob.c +a xlisp/xlimage.c +a xlisp/xlinit.c +a xlisp/xlio.c +a xlisp/xlisp.c +a xlisp/xljump.c +a xlisp/xllist.c +a xlisp/xlmath.c +a xlisp/xlpp.c +a xlisp/xlprin.c +a xlisp/xlstr.c +a xlisp/xlsubr.c +a xlisp/xlsym.c +a xlisp/xlsys.c +a xlisp/xlobj.c +a xlisp/xlread.c +a xlisp/xldbug.c +a xlisp/xleval.c +a xlisp/xldmem.c +a xlisp/xlisp.h +a xlisp/xlftab.c diff --git a/howtorelease.txt b/howtorelease.txt new file mode 100644 index 0000000..9d1791b --- /dev/null +++ b/howtorelease.txt @@ -0,0 +1,118 @@ +How to release Nyquist (notes from RBD to RBD): + +Note: releases are now on sourceforge. The file names are + nyqosx30n.tgz + nyqsrc30n.zip + setupnyqiderun30n.exe + +New primitives should be entered into misc\transfiles.lsp +and then makefile.lsp should be used to generate a new +Makefile as well as sndfn.cl and sndfn.wcl. Run intgen +under Windows (or Mac) using intgen @sndfn.wcl + +ON EITHER WINDOWS OR MAC + +Edit Readme.txt to contain correct version number at top. + +Add changes to Readme.txt changelog. + +Edit runtime/nyinit.lsp to contain correct version number. + +Edit documentation to contain correct version number. + +Is documentation current and installed? +[Update and Commit via SVN] + +To rebuild documentation: + cd docsrc + toafs.bat (or toafs.sh) -- copies source to afs + on afs, scribe nyquistman + ps2pdf nyquistman.ps + on afs, scribe nyquistman to text: + scribe nyquistman.mss -file + copy nyquistman.doc to nyqman.txt + copy nyquistman.pdf to doc + copy nyqman.txt to doc + cd docsrc/s2h + ny + (load "$system-dir$/system.lsp") -- use the appropriate one + (load "s2h") -- will load citations.lsp + (load "do-nyquist-manual") -- runs s2h 2x to get cross-references + (exit) + mv doc/NyquistWords.txt to jnyqide/NyquistWords.txt + +SVN commit -- documentation? + +ON WINDOWS AND MAC + +Search for temp.wav in c:\rbd\nyquist, and delete them all. +Search for points.dat in c:\rbd\nyquist, and delete them all. + +Check for and delete editor backup files in: + jnyqide + runtime + lib + +ON WINDOWS + +Run releasenyqide.bat to create release directory. +Run Inno Setup 5/Inno Setup Compiler +Select C:\Users\rbd\nyquist\sys\win\nyqrelide.iss +Select Build:Compile + +move sys\win\setup\setupnyqiderun.exe setupnyqiderunNNN.exe + , using the version number for NNN + +Visit https://frs.sourceforge.net/webupload and upload setupnyqiderun.exe + +copy the documentation from d:/rbd/nyquist to AFS, or + scp /Volumes/rbd/nyquist/doc/* rbd@linux.gp.cs.cmu.edu:www/doc/nyquist/ + +FOR THE MAC + +build jNyqIDE project with xcode. +source misc/cmu/cmuinstallmac.sh + +FOR PLIGHT DRUM MACHINE -- SHOULD NOT BE NECESSARY + +(this is a separate download because it is large) +source install-plight.sh + +FOR THE MAC TO BUILD RELEASE FOR UNIX + +source release is build along with Mac release by cmuinstallmac.sh + +****************************************************** +* OLD INSTRUCTIONS FOR AUTOMATIC RELEASE TO CMU WEB: * +****************************************************** + +ON WINDOWS + +Run release.bat to create release directory for nyquist_setup +Run Setup Generator and select nyquist_setup +Make sure Files:Source Directory is set to proper nyqrel just created by release.bat +Click Make + +Run releasenyqwin.bat to create release directory for nyqwin_setup +Run Setup Generator and select nyqwin_setup +Make sure Files:Source Directory is set to proper nyqrelwin just created by releasenyqwin.bat +Click Make + +... releasenyqide.bat ... + +from the nyquist directory: +make sure nyquist/ny exists for execution by misc/cmu/cmuinstall.sh + (copy it to nyquist/ny if not) +cd misc/cmu +run cmuinstall.bat or source cmuinstall.sh + +IGNORE THIS -- DELETE AFTER VERSION 3.02 +same thing on PPC, but use +cd ~/nyquist/misc/cmu +bash cmuinstallmac.sh +--- and use something like 232ppc for the version number + +FOR THE MAC TO BUILD RELEASE FOR UNIX + +the cmuinstall.sh file builds a source zip file and installs it + diff --git a/init.lsp~ b/init.lsp~ new file mode 100644 index 0000000..9e58a2e --- /dev/null +++ b/init.lsp~ @@ -0,0 +1,4 @@ +(load "misc/makefile.lsp") +(setf sys-type 'linux) +(makefile) +(exit) diff --git a/jny b/jny new file mode 100755 index 0000000..b94e217 --- /dev/null +++ b/jny @@ -0,0 +1,3 @@ +#!/bin/sh +java -jar jnyqide/jNyqIDE.jar + diff --git a/jnyqide.bat b/jnyqide.bat new file mode 100644 index 0000000..aae1358 --- /dev/null +++ b/jnyqide.bat @@ -0,0 +1,2 @@ +java -jar jnyqide/jNyqIDE.jar + diff --git a/jnyqide/BareBonesBrowserLaunch.java b/jnyqide/BareBonesBrowserLaunch.java new file mode 100644 index 0000000..b8e9a2e --- /dev/null +++ b/jnyqide/BareBonesBrowserLaunch.java @@ -0,0 +1,66 @@ +///////////////////////////////////////////////////////// +// Bare Bones Browser Launch // +// Version 1.5 // +// December 10, 2005 // +// Modified by RBD, 2008 to test for htmlview in linux// +// Supports: Mac OS X, GNU/Linux, Unix, Windows XP // +// Example Usage: // +// String url = "http://www.centerkey.com/"; // +// BareBonesBrowserLaunch.openURL(url); // +// Public Domain Software -- Free to Use as You Like // +///////////////////////////////////////////////////////// + +package jnyqide; // this line was added by RBD + +import java.lang.reflect.Method; +import javax.swing.JOptionPane; + +public class BareBonesBrowserLaunch { + + private static final String errMsg = + "Error attempting to launch web browser"; + + public static void openURL(String url) { + String osName = System.getProperty("os.name"); + System.out.println("BareBonesBrowserLaunch: url=" + url + + " osName:" + osName); + try { + if (osName.startsWith("Mac OS")) { + System.out.println("BareBonesBrowserLaunch: Mac OS detected"); + // try a new way + Runtime.getRuntime().exec(new String[] {"/usr/bin/open", url}); + // here's the old way that does not handle #name suffix on url +// Class fileMgr = Class.forName("com.apple.eio.FileManager"); +// System.out.println("fileMgr=" + fileMgr); +// Method openURL = fileMgr.getDeclaredMethod("openURL", +// new Class[] {String.class}); +// openURL.invoke(null, new Object[] {url}); + System.out.println("openURL invoked with " + url); + } else if (osName.startsWith("Windows")) { + Runtime.getRuntime().exec( + "rundll32 url.dll, FileProtocolHandler " + + "\"" + url + "\""); // quote url or lose "#" suffixes + } else { //assume Unix or Linux + String[] browsers = { + "htmlview", "firefox", "opera", "konqueror", + "epiphany", "mozilla", "netscape" }; + int count; + for (count = 0; count < browsers.length; count++) { + if (Runtime.getRuntime().exec( + new String[] {"which", + browsers[count]}).waitFor() == 0) { + break; + } + } + if (count >= browsers.length) + throw new Exception("Could not find web browser"); + System.out.println("Found browser: " + browsers[count]); + System.out.println("sending url: " + url); + Runtime.getRuntime().exec(new String[] {browsers[count], url}); + } + } catch (Exception e) { + JOptionPane.showMessageDialog(null, errMsg + ":\n" + + e.getLocalizedMessage()); + } + } +} diff --git a/jnyqide/CodePane.java b/jnyqide/CodePane.java new file mode 100644 index 0000000..e566226 --- /dev/null +++ b/jnyqide/CodePane.java @@ -0,0 +1,671 @@ +// +// CodePane.java +// nyquist +// +// Created by Roger Dannenberg on 12/15/07. +// Copyright 2007 Roger B. Dannenberg. All rights reserved. +// + +package jnyqide; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; +import javax.swing.undo.*; + +// CodePane subclasses a JScrollPane and initializes it to contain +// a JTextPane which holds a DefaultStyleDocument. Syntax coloring +// and paren balancing is performed. +// +// a CodePane also has a Timer -- it is used to blink a character somewhere. +// +public class CodePane extends JScrollPane + implements DocumentListener, CaretListener, + AdjustmentListener, KeyListener { + public JTextPane pane; + public DefaultStyledDocument doc; + public Timer timer; + public boolean evenParens; // used by MainFrame for command input + // (when user types return, if parens are balanced, that is, evenParens + // is true, then the command is sent to Nyquist) + // when user types a close paren, the matching one is blinked, and + // when user moves cursor, the matching paren is highlighted in bold + public int blinkLoc; // where to blink a matching paren + public int highlightLoc; // where to highlight a matching paren + public boolean blinkOn; + // mainFrame is a handle to access some methods, but it is also a + // flag to tell us if this is a command entry window: + public MainFrame mainFrame; + public boolean isSal; + int caretLine; // holds current line number + int caretColumn; // holds current column + int fontSize; // the font size + JLabel statusBar; + + final int TIMER_DELAY = 1000; // ms + + public CodePane(Dimension preferredSize, MainFrame mf, JLabel sb, + int fontSz) { + super(); + blinkLoc = 0; + blinkOn = false; // initialize + fontSize = fontSz; + mainFrame = mf; + statusBar = sb; + isSal = false; + doc = new DefaultStyledDocument(); + pane = new JTextPane(doc); + getViewport().add(pane); + setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + + // create timer for blinking + ActionListener blinkOffTask = new ActionListener() { + public void actionPerformed(ActionEvent evt) { + timer.stop(); // timer is just a one-shot, not periodic + blinkOn = false; + synchronousUpdate(); + } + }; + timer = new Timer(TIMER_DELAY, blinkOffTask); + + doc.addDocumentListener(this); + pane.addCaretListener(this); + this.getHorizontalScrollBar().addAdjustmentListener(this); + this.getVerticalScrollBar().addAdjustmentListener(this); + + final UndoManager undo = new UndoManager(); + doc.addUndoableEditListener( + new UndoableEditListener() { + public void undoableEditHappened(UndoableEditEvent evt) { + // do not make style changes undoable -- these + // are fixed automatically + if (!evt.getEdit().getPresentationName().equals( + "style change")) { + undo.addEdit(evt.getEdit()); + } + } + }); + + // Create an undo action and add it to the text component + pane.getActionMap().put("Undo", + new AbstractAction("Undo") { + public void actionPerformed(ActionEvent evt) { + try { + if (undo.canUndo()) { + undo.undo(); + } + } catch (CannotUndoException e) { + } + } + }); + + // Bind the undo action to ctl-Z + pane.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); + + // Create a redo action and add it to the text component + pane.getActionMap().put("Redo", + new AbstractAction("Redo") { + public void actionPerformed(ActionEvent evt) { + try { + if (undo.canRedo()) { + undo.redo(); + } + } catch (CannotRedoException e) { + } + } + }); + + // Bind the redo action to ctl-Y + pane.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo"); + + // add self as a key listener + pane.addKeyListener(this); + + + if (preferredSize != null) setPreferredSize(preferredSize); + + } + + + public void updateCaretLoc() { + String text; + try { + text = pane.getText(); + } catch(Exception ex) { + System.out.println("exception in keyTyped"); + return; + } + int pos = pane.getCaretPosition(); + caretColumn = 0; + caretLine = 0; + int i = 0; + while (i++ < pos) { + if (text.charAt(i - 1) == '\n') { + caretColumn = 0; + caretLine++; + } else { + caretColumn++; + } + } + // the first line is 1, not 0 + statusBar.setText(Integer.toString(caretLine + 1) + ":" + + Integer.toString(caretColumn)); + } + + + public void changedUpdate(DocumentEvent e) { + //System.out.println("changedUpdate " + e); + } + + + public void removeUpdate(DocumentEvent e) { + synchronousUpdate(); + } + + + public void insertUpdate(DocumentEvent e) { + // System.out.println("insertUpdate calls thread.update"); + synchronousUpdate(); + } + + + public void caretUpdate(CaretEvent e) { + // System.out.println("caretUpdate " + e.getDot() + " mark " + + // e.getMark()); + if (e.getDot() == e.getMark()) { + highlightMatchingParen(e.getDot() - 1); + updateCaretLoc(); + //System.out.println("caretUpdate: " + e.getDot() + " is line " + + // caretLine + " col " + caretColumn); + } else { + highlightMatchingParen(-1); + } + } + + public void adjustmentValueChanged(AdjustmentEvent evt) { + // System.out.println("adjustmentValueChanged"); + synchronousUpdate(); + } + + + //This method can be invoked from any thread. It + //invokes the setText and modelToView methods, which + //must run in the event dispatching thread. We use + //invokeLater to schedule the code for execution + //in the event dispatching thread. + protected void highlightMatchingParen(final int pos) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (pos == -1) { + highlightLoc = pos; + } else if (charAtPos(pos) == ')') { + try { + highlightLoc = findOpenParen( + pane.getText(0, pos), pos); + } catch(BadLocationException e) { + System.out.println(e); + return; + } + if (highlightLoc == pos) highlightLoc = -1; + } else { // not at close paren, so turn off highlight + highlightLoc = -1; + } + synchronousUpdate(); + } + } + ); + } + + char charAtPos(int pos) { + String text; + try { + text = doc.getText(pos, 1); + } catch(BadLocationException e) { + return 0; + } + return text.charAt(0); + } + + // complete the KeyListener interface: + public void keyReleased(KeyEvent ke) { return; } + public void keyPressed(KeyEvent ke) { return; } + + public void keyTyped(KeyEvent ke) { + // System.out.println("CodePane keyTyped |" + + // ke.getKeyChar() + "|"); + // cases: + // newline + // mainFrame + // evenParens: sendCommandToNyquist + // !evenParens: + // LISP: print "paren mismatch" + // indent handling + // else + // indent handling + // otherwise + // process key + // + // this is where we put auto parentheses: + char ch = ke.getKeyChar(); + int pos = pane.getCaretPosition(); + if (ch == '\n') { + //insertIndentation(p); + if (mainFrame != null) { + if (evenParens) { + if (doc.getLength() == pos) { + // only do indentation if newline is at end of text + insertIndentation(pos); + // remove newline + pos = doc.getLength(); // take out newline at end + int newlinePos = pos - 1; + try { + while (!doc.getText(newlinePos, 1).equals("\n")) { + newlinePos--; + } + } catch(BadLocationException e) { + System.out.println(e); + return; + } + System.out.println("cut newline: newlinePos " + newlinePos + + " pos " + pos); + pane.setSelectionStart(newlinePos); + } else { // no indentation, just remove newline + pane.setSelectionStart(pos - 1); + } + pane.setSelectionEnd(pos); + pane.replaceSelection(""); + mainFrame.sendCommandToNyquist(); + } else { + if (!isSal) { + mainFrame.jOutputArea.append( + "Invalid command - paren mismatch\n"); + } + insertIndentation(pos); + } + } else { + insertIndentation(pos); + } + } else if (ch == '\t') { + int spaces = TextColor.INDENT - + (caretColumn - 1) % TextColor.INDENT; + // remove tab and replace with spaces + pane.setSelectionStart(pos - 1); + pane.setSelectionEnd(pos); + pane.replaceSelection(" ".substring(0, spaces)); + System.out.println("Replaced TAB by " + spaces + " spaces"); + } else { // ordinary key handling + if (ke.getKeyChar() == ')') { + // get caret location + blinkParen(pos); + } else if (ch == '(') { + if (MainFrame.prefParenAutoInsert) { + pane.replaceSelection(")"); + pane.setCaretPosition(pos); + } + } + String text; + int start = Math.max(pos - 100, 0); + try { + text = pane.getText(start, pos - start); + } catch (Exception ex) { + System.out.println("exception in keyTyped: start " + start + + " pos " + pos + " pane " + pane); + return; + } + // simulate typing the character unless it's a backspace + if (ch != '\b') text += ch; + else pos--; + + String identifier; + int identLoc; + boolean forceExact = false; // force an exact match to complete word + if (isSal) { // generate completion list for SAL + // delimiters are "{}(),[]\n #\"" + // look back for identifier immediately before pos + // if none found, look back for unbalanced paren, then search + // back from there + identifier = getSalIdentifier(text, pos - start); + int len = identifier.length(); + identLoc = pos - len; + forceExact = (len > 0 && identifier.charAt(len - 1) == ' '); + if (len == 0) { // not found + int openParenLoc = findOpenParen(text, pos - start); + identifier = getSalIdentifier(text, openParenLoc); + identLoc = start + openParenLoc - identifier.length(); + forceExact = true; + } + } else { // generate completion list for Lisp + // look back for unmatched open paren, then forward for identifier + // look back a maximum of 100 characters + int openParenLoc = findOpenParen(text, pos - start); + openParenLoc++; + identifier = getIdentifier(text, openParenLoc); + identLoc = start + openParenLoc; + int len = identifier.length(); + forceExact = (len > 0 && identifier.charAt(len - 1) == ' '); + } + //System.out.println("keyTyped identifier is: |" + identifier + "|"); + // put up words list + WordList.printList(identifier, pane, identLoc, pos + 1, + forceExact, isSal); + } + } + + + // get an identifier starting at pos -- if a complete identifier (terminated by something) + // is found, the identifier is terminated by a space character + static String getIdentifier(String text, int pos) { + int idEnd = pos; // search forward to find identifier + String lispIdChars = "~!@$%^&*-_+={}|:<>?/"; + if (text.length() == 0 || pos < 0) return text; // special cases + while (true) { + if (idEnd == text.length()) { + text = text.substring(pos); // still typing + break; + } + char idChar = text.charAt(idEnd); + if (!Character.isLetterOrDigit(idChar) && + lispIdChars.indexOf(idChar) == -1) { + text = text.substring(pos, idEnd) + " "; // complete + break; // idEnd is one past last character + } + idEnd++; + } + return text; + } + + + static int findColumnOf(String text, int pos) { + int col = 0; + pos--; + while (pos >= 0 && text.charAt(pos) != '\n') { + col++; + pos--; + } + return col; + } + + + private void insertIndentation(int p) + { + String text; + int desired = 0; // desired indentation of the previous line + // initialized because compiler can't figure out that it's + // initialized below before it is used + try { + text = pane.getText(0, p); + } catch (Exception e) { + System.out.println("exception in insertIndentation"); + return; + } + int indent; + if (isSal) { + indent = salIndentAmount(p); + desired = TextColor.indentBefore; + } else { + indent = autoIndentAmount(text, p); + } + String indentation = ""; + while (indent > 0) { + indentation += " "; + indent--; + } + // System.out.println("before replaceSelection(indentation)"); + pane.replaceSelection(indentation); + // System.out.println("after replaceSelection(indentation)"); + if (isSal) { // indent the previous line as well + // first find the beginning of the previous line + int prevStart = p - 1; // index of newline + // System.out.println("prevStart " + prevStart + " char |" + + // text.charAt(prevStart) + "|"); + assert(text.charAt(prevStart) == '\n'); + while (prevStart - 1 >= 0 && + text.charAt(prevStart - 1) != '\n') prevStart--; + // System.out.println("PREV LINE BEGIN " + prevStart + " in |" + + // text + "|"); + // find the actual indentation of the previous line + int prevIndent = 0; // search forward from prevStart for nonspace + while (text.charAt(prevStart + prevIndent) == ' ' || + text.charAt(prevStart + prevIndent) == '\t') + prevIndent++; + // System.out.println("PREV INDENT " + prevIndent + + // " DESIRED " + desired); + // adjust the indentation + int delta = desired - prevIndent; + p = pane.getSelectionStart() + delta; + if (delta > 0) { + indentation = ""; + while (delta > 0) { + indentation += " "; + delta--; + } + // System.out.println("INSERT " + delta + + // " SPACES AT " + prevStart); + pane.setSelectionStart(prevStart); + pane.setSelectionEnd(prevStart); + pane.replaceSelection(indentation); + } else if (delta < 0) { + // System.out.println("BACKSPACE " + -delta + + // " AT " + prevStart); + pane.setSelectionStart(prevStart); + pane.setSelectionEnd(prevStart - delta); + pane.replaceSelection(""); + } + // System.out.println("MOVE CARET TO " + p); + pane.setSelectionStart(p); + pane.setSelectionEnd(p); + } + } + + private int salIndentAmount(int p) { + // how much is the default indentation? + // p is position AFTER a newline, so back up one to get + // the index of the newline character + // System.out.println("salIndentAmount " + p); + TextColor.format(this, p - 1); + // System.out.println("salIndent return " + TextColor.indentAfter); + return TextColor.indentAfter; + } + + + // find auto-indent position: + // first, go back and find open paren that would match a close paren + // second search forward to find identifier + // if identifier is defun, defmacro, let, let*, or prog, etc. + // indent to paren posn + 2 + // else indent to the first thing after the identifier + int autoIndentAmount(String text, int pos) { + int openParenLoc = findOpenParen(text, pos); + // System.out.println("autoIndent: openParenLoc = " + openParenLoc); + if (openParenLoc == -1) return 0; + String ident = getIdentifier(text, openParenLoc + 1); + if (ident.equals("defun ") || ident.equals("defmacro ") || + ident.equals("let ") || ident.equals("let* ") || + ident.equals("dotimes ") || ident.equals("dolist ") || + ident.equals("simrep ") || ident.equals("seqrep ") || + ident.equals("prog ") || ident.equals("prog* ") || + ident.equals("progv ")) { + pos = openParenLoc + 2; + } else { + pos = openParenLoc + ident.length(); + System.out.println("auto-indent, pos " + pos + ", ident " + ident + + ", length " + ident.length()); + while (pos < text.length() && Character.isWhitespace(text.charAt(pos))) { + if (text.charAt(pos) == '\n') { + // if the end of the line looks like "(foo \n" then the tab position + // will be indented two from the open paren (ignore the identifier): + pos = openParenLoc + 2; + break; + } + pos++; + } + // System.out.println("pos " + pos); + } + return findColumnOf(text, pos); + } + + + public static boolean inComment(String text, int pos) + // search back to newline for ";" indicating comment + // assumes text[pos] is not escaped or in string + { + boolean inString = false; + while (pos > 0) { + char c = text.charAt(pos); + if (c == ';') return true; + if (c == '\n') return false; + pos = backup(text, pos, false); + } + return false; + } + + static String SalIdChars = "{}(),[]\n #\""; + + public static String getSalIdentifier(String docText, int pos) { + // System.out.println("|" + docText + "| " + pos); + int start = pos; + if (pos < 0) return ""; // special case: no place to search from + // allow back up over single open paren + if (docText.charAt(pos) == '(') start = start - 1; + while (start >= 0 && + SalIdChars.indexOf(docText.charAt(start)) == -1) { + start--; + } + // protect from bogus arguments + if (start < -1 || pos >= docText.length()) return ""; + // if id is terminated by open paren, substitute blank so that + // when we search lisp-syntax wordlist we get a more precise match. + // E.g. "osc(" becomes "osc " which will not match "osc-enable ..." + if (docText.charAt(pos) == '(') + return docText.substring(start + 1, pos) + " "; + else + return docText.substring(start + 1, pos + 1); + + + } + + + public static int findOpenParen(String docText, int pos) { + int findx = -1; + try { + boolean inString = false; // need to get it from text color + findx = backup(docText, pos, inString); + if (findx == pos - 1 && findx > 0 && docText.charAt(findx) == '\\') { + // escaped paren + return pos; + } else if (inComment(docText, findx)) { // in comment + return pos; + } + // at this point we know there is a closed paren. + // go back until you find the matching open paren. + int closed = 1; + while (findx >= 0 && closed > 0) { + char c = docText.charAt(findx); + if (c == '(' || c == ')') { + if (!inComment(docText, findx)) { + if (c == '(') closed--; + else if (c == ')') closed++; + } + } + if (closed > 0) // not done, back up + findx = backup(docText, findx, false); + } + } catch( Exception e ) { + // System.out.println("findOpenParen " + e); + } + // System.out.println("findOpenParen returns " + findx); + return findx; + } + + + private static int backup(String text, int pos, boolean inString) + // find an index in text before pos by skipping over strings + // and escaped characters of the form #\A, but do not consider + // comment lines. If findx is zero, return result is -1. + { + int findx = pos - 1; + while (true) { + if (findx < 0) { + return findx; + } + char c = text.charAt(findx); + if (inString) { + if (c == '"') { + // could it be escaped? + if (findx > 0) { + char pre = text.charAt(findx - 1); + if (pre == '"') findx--; // escaped as "" + else if (pre == '\\') findx--; // escaped as \" + else inString = false; + } else inString = false; + } // else keep searching for string closing + } else { // not inString + // test for escaped character + if (findx > 0) { + char pre = text.charAt(findx - 1); + if (pre == '\\') findx--; // escaped + else inString = (c == '"'); + } // else if c == '"' then ... + // internal error: text begins with quote, but + // inString is false. Just ignore it because it + // may be that the coloring hasn't run yet + // and all will become well. + } + if (!inString || findx <= 0) { + return findx; + } + findx--; + } + } + + + void synchronousUpdate() { + // System.out.println("synchronousUpdate called"); + final CodePane codePane = this; + final JViewport v = getViewport(); + final Point pt = v.getViewPosition(); + final Dimension e = v.getExtentSize(); + EventQueue.invokeLater( + new Runnable() { + public void run() { + // System.out.println("calling TextColor"); + codePane.evenParens = TextColor.format(codePane, 0); + // System.out.println("returned from TextColor"); + codePane.updateFontSize(fontSize); + } + }); + } + + void blinkParen(int pos) { + try { + String docText = doc.getText(0, pos); + int openParenLoc = findOpenParen(docText, pos); + if (openParenLoc >= 0 && openParenLoc < pos) { + blink(openParenLoc); + } + } catch (Exception e) { System.out.println(e); } + } + + + // the blink interface: call blink(loc) to make a character blink + void blink(int loc) { + timer.start(); + blinkOn = true; + blinkLoc = loc; + } + + public void updateFontSize(int size) { + final MutableAttributeSet attributeSet = new SimpleAttributeSet(); + StyleConstants.setFontSize(attributeSet, size); + doc.setCharacterAttributes(0, 1000000, attributeSet, false); + } + + public void setFontSize(int size) { + fontSize = size; + updateFontSize(size); + } + +} diff --git a/jnyqide/EnvelopeFrame.java b/jnyqide/EnvelopeFrame.java new file mode 100644 index 0000000..9038ebb --- /dev/null +++ b/jnyqide/EnvelopeFrame.java @@ -0,0 +1,1317 @@ +// Code: Chris Yealy, 5/2/06 +// Edited: Derek D'Souza 5/3/07 +// Edited: Roger Dannenberg 23Jul07 + +// eq editor needs to do same with workspace + +/* Saving and Restoring: + * the Save button saves one envelope locally, to Nyquist, and saves the + * updated workspace + * the Load button loads all envelopes from Nyquist for editing. If no + * envelopes are loaded, suggests (load "workspace") + * selecting an envelope from the list saves the current envelope + * (locally, to Nyquist, and to the workspace) and switches the editor + * to the selected envelope + * delete button removes the envelope from the workspace after a confirm + */ + +/* + Graphics organization: + + myParent -- the MainFrame + EnvelopeFrame -- this editor, a JInternalFrame + mainPanel -- a JPanel + topPanel -- a JPanel + envNamePanel -- a JPanel, border "Current Envelope" + currEnvNameLabel -- a JLabel("Name:") + currEnvName -- a JTextField("ENVELOPE", 20) + saveEnv -- a JButtton("Save") + envTypeLabel - a JTextField("Type", ...) + envTypes - a JComboBox + envListPanel -- a JPanel, border "Saved Envelopes List" + envName -- a JComboBox + loadEnv -- a JButton("load") + deleteEnv -- a JButton("delete") + envPointsPanel - a JPanel, border Envelope Points + envTimesLabel - a JLabel("Time:") + envTimes - JComboBox + envAmplitudesLabel - a JLabel("Amplitudes:") + envAmplitudes - JTextField + addPoint - a JButton("Add Point") + deletePoint - a JButton("Delete Point") + updatePoint - a JButton("Update Point") + paramPanel -- a JPanel + rangePanel - a JPanel, border "Range Parameters" + maxTL - a JLabel("Stop Time") + maxT - a JTextField + minAL - a JLabel("Min. Amplitude") + maxAL - a JLabel("Max. Amplitude") + minA - a JTextField + maxA - a JTextField + update - JButton("Update Range" + envEditPanel -- a JPanel, border "Graphic Envelope Editor" + envEditButtonPanel - a JPanel + undo - a JButton("Undo") + redo - a JButton("Redo") + clear - a JButton("Clear") + dispCoord - a JButton("Coordinates") + output - a JButton("Output Envelope") + canvas - a PiecewiseCanvas (a JPanel) + + to drag point: + on mouse pressed, set selection to index of point + on mouse drag, delete selection and insert new point + +if endpoints are specified, e.g. if times[0] is 0 or last value in times + matches the ending time, then use PWLV or PWEV version + Be careful not to drop first/last point unless the time matches the + begin/end time. + + + */ + +package jnyqide; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import java.awt.image.BufferedImage; +import java.util.Vector; +import java.util.Hashtable; +import java.util.StringTokenizer; +import java.util.Enumeration; +import java.io.File; +import java.lang.Math.*; +import java.text.DecimalFormat; +import jnyqide.*; + + +public class EnvelopeFrame extends JInternalFrame implements ActionListener { + + double EPSILON = 0.00000001; // small number -- allow for rounding error + int LEFT_BORDER = 3; // inset everything by 3 pixels + int TOP_BORDER = 3; + int BOTTOM_BORDER = 5; + int RIGHT_BORDER = 5; + MainFrame myParent; + + //JComponents for envelope window + private JComboBox envTypes; + + private JPanel mainPanel; + + private JTextPane jInputArea; + //private JPanel canvasPanel; + private PiecewiseCanvas canvas; + + private JTextField envAmplitudes; + // private JTextField minT; + private JTextField maxT; + private JTextField minA; + private JTextField maxA; + private JTextField currEnvName; + private JComboBox envName; + private JComboBox envTimes; + private JButton dispCoord; + private String currentEnvName; + public String[] types = {"Piecewise Linear", "Piecewise Exponential"}; + public int PWL_TYPE = 0; + public int PWE_TYPE = 1; + // when saving envelopes, we copy current envelope to the collection, + // but this makes the combobox think that an envelope was selected, + // and we get a request to save the same envelope were saving. To + // avoid this, the "saving" flag is used to disable the check. + private boolean saving = false; + + //hashtable for storing envelopes + private Hashtable envColl; + + static double initTime=0.0; + static double finalTime=1.0; + static boolean displayCoord = false; + static boolean valueType=false; + static DecimalFormat form = new DecimalFormat("#.###"); + private boolean modified; // tells when any aspect of envelope + // has changed + // envelope is modified by: entering a point, deleting a point, changing + // the end-time (update), or clearing + // modified is reset when envelope is loaded or saved + + // Constructor + public EnvelopeFrame(final MainFrame parent, JTextPane inputArea) { + super(); + setTitle("Untitled"); + myParent = parent; + jInputArea = inputArea; + //canvasPanel = new JPanel(); + //canvasPanel.setPreferredSize(new Dimension(575, 256)); + mainPanel = (JPanel) getContentPane(); + + envColl = new Hashtable(); + setTitle("Piecewise Envelope Generator"); + setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); + final EnvelopeFrame envelopeFrame = this; + modified = false; + addInternalFrameListener( + new InternalFrameListener() { + public void internalFrameClosing(InternalFrameEvent e) { + //System.out.println("FrameClosing"); + int r = JOptionPane.OK_OPTION; + if (envelopeFrame.modified) { + r = JOptionPane.showConfirmDialog(envelopeFrame, + "Really close without saving?", + "Alert", JOptionPane.OK_CANCEL_OPTION); + } + if (r == JOptionPane.OK_OPTION) { + envelopeFrame.dispose(); + } + } + public void internalFrameOpened(InternalFrameEvent e) { + } + public void internalFrameClosed(InternalFrameEvent e) { + parent.disconnectEnv(); + //System.out.println("FrameClosed"); + } + public void internalFrameIconified(InternalFrameEvent e) { + } + public void internalFrameDeiconified(InternalFrameEvent e) { + } + public void internalFrameActivated(InternalFrameEvent e) { + } + public void internalFrameDeactivated(InternalFrameEvent e) { + } + } + ); + + System.out.println("EnvelopeFrame constructor 1"); + + JLabel currEnvNameLabel = new JLabel("Name: "); + currEnvName = new JTextField("envelope", 10); + currentEnvName = "envelope"; + + JButton saveEnv = new JButton("Save"); + saveEnv.addActionListener(this); + saveEnv.setActionCommand("saveEnvelopes"); + + JLabel currEnvTypeLabel = new JLabel("Type: "); + envTypes = new JComboBox(types); + envTypes.addActionListener(this); + envTypes.setActionCommand("envTypeChanged"); + + // components for envelope list panel + envName = new JComboBox(); + envName.setEditable(false); + envName.addActionListener(this); + envName.setActionCommand("envNameSelected"); + + JButton loadEnv = new JButton("Load"); + loadEnv.addActionListener(this); + loadEnv.setActionCommand("loadEnvelope"); + + JButton deleteEnv = new JButton("Delete"); + deleteEnv.addActionListener(this); + deleteEnv.setActionCommand("deleteEnvelope"); + + JPanel envNamePanel = new JPanel(); + envNamePanel.setBorder(BorderFactory.createTitledBorder("Current Envelope")); + GridBagLayout layout0 = new GridBagLayout(); + envNamePanel.setLayout(layout0); + + GridBagConstraints cons0 = new GridBagConstraints(); + + cons0.fill = GridBagConstraints.NONE; + cons0.anchor = GridBagConstraints.EAST; + cons0.weightx = 0; + cons0.weighty = 0; + cons0.gridx = 0; + cons0.gridy = 0; + cons0.gridheight = 1; + cons0.gridwidth = 1; + envNamePanel.add(currEnvNameLabel, cons0); + cons0.anchor = GridBagConstraints.WEST; + cons0.gridx = 1; + envNamePanel.add(currEnvName, cons0); + cons0.anchor = GridBagConstraints.CENTER; + cons0.gridx = 2; + envNamePanel.add(saveEnv, cons0); + cons0.anchor = GridBagConstraints.EAST; + cons0.gridx = 0; + cons0.gridy = 1; + envNamePanel.add(currEnvTypeLabel, cons0); + cons0.anchor = GridBagConstraints.WEST; + cons0.gridx = 1; + cons0.gridwidth = 2; + envNamePanel.add(envTypes, cons0); + + JPanel envListPanel = new JPanel(); + envListPanel.setBorder(BorderFactory.createTitledBorder("Saved Envelopes List")); + envListPanel.add(envName); + envListPanel.add(loadEnv); + envListPanel.add(deleteEnv); + + envTimes = new JComboBox(); + envTimes.setEditable(true); + envTimes.addActionListener(this); + envTimes.setActionCommand("envTimeChange"); + envTimes.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + System.out.println("itemStateChanged " + e); + } + }); + JLabel envTimesLabel = new JLabel("Time: "); + + envAmplitudes = new JTextField(6); + JLabel envAmplitudesLabel = new JLabel("Ampl: "); + envTimes.setPreferredSize(envAmplitudes.getPreferredSize()); + + JButton addPoint = new JButton("Add Point"); + addPoint.addActionListener(this); + addPoint.setActionCommand("addPoint"); + + JButton deletePoint = new JButton("Delete Point"); + deletePoint.addActionListener(this); + deletePoint.setActionCommand("deletePoint"); + + JButton updatePoint = new JButton("Update Point"); + updatePoint.addActionListener(this); + updatePoint.setActionCommand("updatePoint"); + + GridBagLayout layout1 = new GridBagLayout(); + JPanel envPointsPanel = new JPanel(); + envPointsPanel.setBorder(BorderFactory.createTitledBorder("Envelope Points")); + envPointsPanel.setLayout(layout1); + + GridBagConstraints cons = new GridBagConstraints(); + + cons.fill = GridBagConstraints.NONE; + cons.anchor = GridBagConstraints.EAST; + cons.weightx = 0; + cons.weighty = 0; + cons.gridx = 0; + cons.gridy = 0; + cons.gridheight = 1; + cons.gridwidth = 1; + envPointsPanel.add(envTimesLabel, cons); + cons.anchor = GridBagConstraints.WEST; + cons.gridx = 1; + envPointsPanel.add(envTimes, cons); + cons.anchor = GridBagConstraints.EAST; + cons.gridx = 0; + cons.gridy = 1; + envPointsPanel.add(envAmplitudesLabel, cons); + cons.anchor = GridBagConstraints.WEST; + cons.gridx = 1; + envPointsPanel.add(envAmplitudes, cons); + cons.anchor = GridBagConstraints.CENTER; + cons.gridx = 2; + cons.gridy = 0; + envPointsPanel.add(addPoint, cons); + cons.gridy = 1; + envPointsPanel.add(deletePoint, cons); + cons.gridy = 2; + envPointsPanel.add(updatePoint, cons); + + // panel to contain time and amplitude parameters + JPanel rangePanel = new JPanel(); + JPanel paramPanel = new JPanel(); + paramPanel.setBorder(BorderFactory.createTitledBorder("Range")); + rangePanel.setLayout(new GridBagLayout()); + paramPanel.setLayout(layout1); + + // components for parameter panel + ActionListener stateChange = new ActionListener() { + public void actionPerformed(ActionEvent e) { + canvas.history.save(canvas); + } + }; + maxT = new JTextField("1.0", 5); + minA = new JTextField("0.0", 5); + maxA = new JTextField("1.0", 5); + + JLabel maxTL = new JLabel("Stop: "); + JLabel minAL = new JLabel("Min: "); + JLabel maxAL = new JLabel("Max: "); + + cons.gridx = 2; + cons.gridy = 0; + rangePanel.add(maxTL, cons); + cons.gridx = 3; + cons.gridy = 0; + rangePanel.add(maxT, cons); + cons.gridx = 0; + cons.gridy = 1; + rangePanel.add(minAL, cons); + cons.gridx = 2; + rangePanel.add(maxAL, cons); + cons.gridx = 1; + rangePanel.add(minA, cons); + cons.gridx = 3; + rangePanel.add(maxA, cons); + JButton update = new JButton("Update Range"); + + update.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (getMaxT() <= 0) { + JOptionPane.showMessageDialog(mainPanel, + "Stop Time cannot be negative or zero"); + } else if (getMinA() > getMaxA()) { + JOptionPane.showMessageDialog(mainPanel, + "Minimum Amplitude cannot be greater than Maximum Amplitude"); + } else if ((canvas.times.size() > 0) && + (getMaxT() < canvas.times.lastElement())) { + JOptionPane.showMessageDialog(mainPanel, + "Stop Time is less than the time of an existing envelope point"); + } else { + modified = true; + canvas.history.save(canvas); + canvas.repaint(); + return; + } + // an error occurred, reset the Range (using complete restore) + canvas.restore(); + } + }); + + //insert components into the larger panels + cons.fill = GridBagConstraints.NONE; + cons.anchor = GridBagConstraints.WEST; + cons.weightx = 0; + cons.weighty = 0; + cons.gridx = 0; + cons.gridy = 0; + cons.gridheight = 1; + cons.gridwidth = 1; + //cons.insets = new Insets(5,0,0,5); + paramPanel.add(rangePanel, cons); + cons.fill = GridBagConstraints.NONE; + cons.anchor = GridBagConstraints.CENTER; + cons.weightx = 0; + cons.weighty = 0; + cons.gridx = 0; + cons.gridy = 1; + cons.gridheight = 1; + cons.gridwidth = 1; + //cons.insets = new Insets(0,0,0,5); + paramPanel.add(update, cons); + + // components for envelope edit panel + JButton undo = new JButton("Undo"); + undo.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + canvas.history.undo(); + canvas.restore(); + } + }); + JButton redo = new JButton("Redo"); + redo.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + canvas.history.redo(); + canvas.restore(); + } + }); + JButton clear = new JButton("Clear"); + clear.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.out.println("calling canvas.clear\n"); + canvas.clear(); + } + }); + dispCoord = new JButton("Coordinates"); + dispCoord.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + displayCoord = !displayCoord; + canvas.repaint(); + } + }); + JButton output = new JButton("Output Envelope"); + output.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String outputStr = canvas.getExpression(); + jInputArea.setText(jInputArea.getText().concat(outputStr)); + } + }); + + JPanel envEditButtonPanel = new JPanel(); + envEditButtonPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 0)); + envEditButtonPanel.add(undo); + envEditButtonPanel.add(redo); + envEditButtonPanel.add(clear); + envEditButtonPanel.add(dispCoord); + envEditButtonPanel.add(output); + JPanel topPanel = new JPanel(); + //topPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 30, 0)); + topPanel.setLayout(new GridBagLayout()); + cons.anchor = GridBagConstraints.NORTHWEST; + cons.gridx = 0; + cons.gridy = 0; + topPanel.add(envNamePanel, cons); + cons.gridx = 1; + topPanel.add(envListPanel, cons); + cons.gridx = 0; + cons.gridy = 1; + topPanel.add(envPointsPanel, cons); + cons.gridx = 1; + topPanel.add(paramPanel, cons); + + JPanel envEditPanel = new JPanel(); + envEditPanel.setBorder(BorderFactory.createTitledBorder( + "Graphical Envelope Editor")); + //envEditPanel.setLayout(new BoxLayout(envEditPanel, BoxLayout.Y_AXIS)); + envEditPanel.setLayout(new BorderLayout()); + envEditPanel.add(BorderLayout.NORTH, envEditButtonPanel); + canvas = new PiecewiseCanvas(); + //canvasPanel.add(canvas); + //canvasPanel.setBorder(BorderFactory.createEtchedBorder()); + envEditPanel.add(BorderLayout.CENTER, canvas); + + //insert panels into main frame and display + //mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + //mainPanel.setBorder(BorderFactory.createEmptyBorder()); + //canvasPanel.add(canvas); + mainPanel.add(BorderLayout.NORTH, topPanel); + mainPanel.add(BorderLayout.CENTER, envEditPanel); + + pack(); + + //resize and center the window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + setLocation(100, 100); + setSize(650, 580); + // setBackground(Color.white); + setResizable(true); + setVisible(true); + setClosable(true); + setMaximizable(true); + setIconifiable(true); + System.out.println("EnvelopeFrame constructor 2 after setIcnifiable"); + // synchronize env data by loading data from Nyquist process + loadEnvelopes(); + repaint(); + // canvas.repaint(); + } + + public void envNameSelected() { + if (saving) return; // ignore selection generated by "save" button + // If the name is different from the current envelope name, do + // a "save". Then switch to editing the newly selected envelope. + String name = (String) envName.getSelectedItem(); + // when we load the JComboBox with new names, the contentsChanged + // method of JComboBox invokes a selection action, even if nothing + // is selected. I don't know why, but we have to handle the null + // selection case. + if (name == null) return; + + String originalName = currentEnvName; + currentEnvName = currEnvName.getText().trim(); + if (!originalName.equals(currentEnvName)) { + modified = true; + } + if (modified) { + Object[] options = { "OK", "CANCEL" }; + int i = JOptionPane.showOptionDialog(mainPanel, + currentEnvName + " is being edited. Save it?", + "Warning", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, + null, options, options[0]); + if (i == JOptionPane.OK_OPTION) { + saveEnvelopes(); + } + } + + // store envelope under old name + String edited = canvas.getExpression(); + System.out.println("expression existed, putting " + currentEnvName + + " " + edited + ", changing currentEnvName to " + name); + if (currentEnvName.length() > 0) envColl.put(currentEnvName, edited); + // install name as new envelope to edit + String expression = envColl.get(name); + canvas.setEnv(expression); + currEnvName.setText(name); + // make name be the selected name + envName.setSelectedItem(name); + // } + currentEnvName = name; + } + + + //public double getMinT() { return Double.parseDouble(minT.getText().trim()); } + public double getMaxT() { return Double.parseDouble(maxT.getText().trim()); } + public double getMinA() { return Double.parseDouble(minA.getText().trim()); } + public double getMaxA() { return Double.parseDouble(maxA.getText().trim()); } + public int getEnvType() { + if (envTypes != null) { + String env = (String) envTypes.getSelectedItem(); + if (env.matches(types[PWL_TYPE])) return PWL_TYPE; + return PWE_TYPE; + } else /* initializing */ return PWL_TYPE; + } + + public boolean within(double x, double y, double eps) { + return Math.abs(x - y) < eps; + } + + // write current envelope definition to Nyquist + public void saveEnvelopes() { + // make sure current envelope has been stored in collection + if (currEnvName.getText().length() == 0) { + JOptionPane.showMessageDialog(mainPanel, "Please Enter an Envelope Name"); + return; + } + currentEnvName = currEnvName.getText().trim(); + + // now write all to Nyquist + saving = true; + boolean foundIt = false; + for (Enumeration keys = envColl.keys(); keys.hasMoreElements(); ) { + String name = (String) keys.nextElement(); + // update envelope collection with current envelope + if (name.equals(currentEnvName)) { + envColl.remove(name); + //envName.removeItem(name); + envColl.put(currentEnvName, canvas.getExpression()); + //envName.addItem(currentEnvName); + foundIt = true; + } + String expression = envColl.get(name); + String defn = "(define-env '" + name + " '" + expression + ")"; + System.out.print("in saveEnvelopes: " + defn); + myParent.sendInputLn(defn); // send to Nyquist for evaluation + } + // if the current envelope was not in the list, add it and save it + if (!foundIt) { + String expr = canvas.getExpression(); + envColl.put(currentEnvName, expr); + envName.addItem(currentEnvName); + String defn = "(define-env '" + currentEnvName + " '" + expr + ")"; + System.out.print("in saveEnvelopes: " + defn); + myParent.sendInputLn(defn); // send to Nyquist for evaluation + } + envName.setSelectedItem(currentEnvName); + modified = false; + saving = false; + System.out.println("modified false in saveEnvelopes\n"); + } + + + public void loadEnvelopes() { + myParent.callFunction("get-env-data", ""); + } + + public void deleteEnvelope() { + Object[] options = { "OK", "CANCEL" }; + int i = JOptionPane.showOptionDialog(mainPanel, + "Deletion cannot be undone, click OK to continue", + "Warning", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, + null, options, options[0]); + if (i != JOptionPane.OK_OPTION) return; + // it appears as though currentEnvName gets changed when you remove + // it from the envName comboBox, so make a local copy. Previously, + // we were calling DELETE-ENV after the name changed! + String name = currentEnvName; + // delete the envelope from hashtable + envColl.remove(name); + // delete the envelope from the combobox + envName.removeItem(name); + // delete the envelope from the workspace + myParent.sendInputLn( + "(delete-env '" + name + ")"); + } + + + public void actionPerformed(ActionEvent e) + { + //System.out.println(e.getActionCommand()); + String actionCommand = e.getActionCommand(); + + // File Menu options + if (actionCommand.equals("saveEnvelopes")) { + saveEnvelopes(); + } else if (actionCommand.equals("loadEnvelope")) { + loadEnvelopes(); + } else if (actionCommand.equals("deleteEnvelope")) { + deleteEnvelope(); + } else if (actionCommand.equals("envNameSelected")) { + envNameSelected(); + } else if (actionCommand.equals("envTypeChanged")) { + int type = getEnvType(); + if (type != canvas.type) { + canvas.type = type; + canvas.history.save(canvas); + canvas.repaint(); + } + + //set initial amplitude and time parameters + if (canvas.times.size() < 1) { + if (type == PWE_TYPE) { + minA.setText("1.0"); + maxA.setText("2.0"); + } else { + minA.setText("0.0"); + maxA.setText("1.0"); + } + } + canvas.repaint(); + validate(); + setVisible(true); + } else if (actionCommand.equals("deletePoint")) { + int index = envTimes.getSelectedIndex(); + System.out.println("at deletePoint, index " + index); + if (index >= 0) { + canvas.selection = index; + System.out.println("at deletePoint before deleteSelection"); + canvas.deleteSelection(); + index = envTimes.getSelectedIndex(); + System.out.println("deletePoint new index " + index); + if (index >= 0) { + canvas.selection = index; + envAmplitudes.setText(form.format(canvas.amps.get(index))); + } + canvas.repaint(); + } + } else if (actionCommand.equals("addPoint")) { + String text = (String) envTimes.getSelectedItem(); + if (text.equals("")) return; + double time = Double.parseDouble(text.trim()); + text = envAmplitudes.getText(); + double amp = Double.parseDouble(text.trim()); + canvas.insertInOrder(time, amp); + canvas.repaint(); + } else if (actionCommand.equals("updatePoint")) { + String text = (String) envTimes.getSelectedItem(); + if (text.equals("")) return; + double time = Double.parseDouble(text.trim()); + text = envAmplitudes.getText(); + double amp = Double.parseDouble(text.trim()); + System.out.println("updatePoint selection " + canvas.selection); + canvas.deleteSelection(); + canvas.insertInOrder(time, amp); + canvas.repaint(); + } else if (actionCommand.equals("envTimeChange")) { + // sometimes this action gets called in the middle of + // doing an update and in an inconsistent state. If this + // happens, don't try to set amplitude text. + if (canvas.amps.size() != envTimes.getItemCount()) return; + int index = envTimes.getSelectedIndex(); + System.out.println("envTimeChange " + index); + if (index >= 0) { + canvas.selection = index; + envAmplitudes.setText(form.format(canvas.amps.get(index))); + canvas.repaint(); // update selection marker + } + } else { + System.out.println("ACTION NOT HANDLED: " + actionCommand); + } + } + + public void loadEnvData(String data) { + data = data.toLowerCase(); + System.out.println("loadEnvData: data |" + data + "| len " + data.length()); + envName.removeAllItems(); // clear and reload combo box + envTimes.removeAllItems(); // clear times + envAmplitudes.setText(""); // clear amplitude box + while (data.length() > 0) { + int eolx = data.indexOf("\n"); + if (eolx < 0) return; // shouldn't happen, but bail if it does + String line = data.substring(0, eolx); + System.out.println("loadEnvData: line " + line); + data = data.substring(eolx + 1); + String name = line.substring(0, line.indexOf(' ')); + System.out.println("loadEnvData: name " + name); + String env = line.substring(name.length() + 1); + System.out.println("loadEnvData: env " + env); + if (name.length() > 0) envColl.put(name, env); + envName.addItem(name); + } + } + + private class State { + public int type; + public double maxT; + public double minA; + public double maxA; + + public State(int t, double stop, double low, double hi) { + type = t; maxT = stop; minA = low; maxA = hi; + } + } + + private class History { + /* consider a sequence of undo/redo to be a single edit operation -- thus + * the end of the versions list is set to the latest undo/redo selection + */ + private boolean undoRedo = false; + private Vector> t_history = new Vector>(); + private Vector> a_history = new Vector>(); + private Vector state_history = new Vector(); + private int version = -1; + + public void save(PiecewiseCanvas canvas) { + t_history.add((Vector) (canvas.times.clone())); + a_history.add((Vector) (canvas.amps.clone())); + state_history.add(new State(canvas.type, getMaxT(), + getMinA(), getMaxA())); + version = t_history.size() - 1; + System.out.println("Saved version " + version); + undoRedo = false; /* clear flag for next undoRedo sequence */ + } + + public boolean canGet() { + boolean result = version >= 0 && version < t_history.size(); + System.out.println("canGet returns " + result + " version " + + version); + return result; + } + + public Vector getTimes() { return t_history.get(version); } + public Vector getAmps() { return a_history.get(version); } + public State getState() { return state_history.get(version); } + + private void processUndoRedo() { + if (!undoRedo) { /* extend with copy of the version */ + t_history.add((Vector) (t_history.get(version).clone())); + a_history.add((Vector) (a_history.get(version).clone())); + state_history.add(state_history.get(version)); + } else { /* replace with different version */ + t_history.set(t_history.size() - 1, + (Vector) (t_history.get(version).clone())); + a_history.set(t_history.size() - 1, + (Vector) (a_history.get(version).clone())); + state_history.set(state_history.size() - 1, + state_history.get(version)); + } + undoRedo = true; + } + + public void undo() { + if (version > 0) { + version--; + processUndoRedo(); + } + } + public void redo() { + if (version < t_history.size() - 1) { + version++; + processUndoRedo(); + } + } + } + + + // Class for the drawing area + //private class PiecewiseCanvas extends Canvas implements MouseListener, + private class PiecewiseCanvas extends JPanel implements MouseListener, + MouseMotionListener, KeyListener { + private int currentAmp; + private int currentTime; + public BufferedImage image = null; + public boolean selectCheck = false; + public int selection; + public History history; + + private boolean mouseDown = false; // used to detect version for undo + private boolean changed = false; // used to detect version for undo + + // Vectors to store the absolute parameters of the points in the + // envelope. + public Vector times = new Vector(); + public Vector amps = new Vector(); + public int type = PWL_TYPE; /* PWL_TYPE or PWE_TYPE */ + + // Constructor + public PiecewiseCanvas() { + setBackground(Color.white); + addMouseListener(this); + addMouseMotionListener(this); + addKeyListener(this); + selection = -1; + history = new History(); + history.save(this); + } + + public boolean isValueType() { + if (times.size() == 0) return false; + return (times.get(0) == 0 || + within(times.lastElement(), getMaxT(), EPSILON)); + } + + public boolean isImpliedFirstPoint() { + return (times.size() == 0) || + !within(times.get(0), 0, EPSILON); + } + + public boolean isImpliedLastPoint() { + return (times.size() == 0) || + !within(times.lastElement(), getMaxT(), EPSILON); + } + + // Allow JPanel to accept keyboard events + public boolean isFocusable() { + return true; + } + + //try to make the canvas the correct size + public Dimension getMinimumSize() { + return new Dimension(0, 0); + } + + public Dimension getPreferredSize() { + return new Dimension(575, 256); + } + + public double impliedAmp() { + return (type == PWL_TYPE ? 0.0 : 1.0); + } + + + /* + public Dimension getMaximumSize() { + return getPreferredSize(); + }*/ + + // draw the graphics inside the full canvas, so use these + // functions to get the size and coordinates of the drawing + // area that is usable + private int graphLeft() { return LEFT_BORDER; } + private int graphRight() { return getWidth() - RIGHT_BORDER; } + private int graphWidth() { return getWidth() - + (LEFT_BORDER + RIGHT_BORDER); } + private int graphTop() { return TOP_BORDER; } + private int graphBottom() { return getHeight() - BOTTOM_BORDER; } + private int graphHeight() { return getHeight() - + (TOP_BORDER + BOTTOM_BORDER); } + private int clipX(int x) { + return Math.max(LEFT_BORDER, Math.min(graphRight(), x)); } + private int clipY(int y) { + return Math.max(BOTTOM_BORDER, Math.min(graphBottom(), y)); } + + public String getExpression() { + boolean valueType = isValueType(); + String env; + + if (type == PWL_TYPE) env = (valueType ? "pwlv" : "pwl"); + else env = (valueType ? "pwev" : "pwe"); + + return outputEnv(env, valueType, 0.0, // getMinT(), + getMaxT(), getMinA(), getMaxA()); + } + + + //draw the canvas image + public void paint(Graphics g) { + super.paint(g); + // test: g.drawLine(0, 0, 100, 100); + + Graphics2D drawArea = (Graphics2D) g; + canvas.drawCircles(drawArea); + canvas.drawSelectionCircle(drawArea); + canvas.connectTheDots(drawArea); + drawArea.dispose(); + } + + //erase the canvas, then draw all of the points in the envelope + private void drawCircles(Graphics2D g) { + //erase the previous image + //clearCanvas(g); + double maxTime = getMaxT(); + + // is the initial point implicit? + if (isImpliedFirstPoint()) { // implied + double amp = impliedAmp(); + int y = amp2y(amp); + // System.out.println("implied: amp " + amp + " y " + y); + drawDot(g, graphLeft(), y); + if (displayCoord) { + g.drawString("(0," + form.format(amp) + ")", + graphLeft(), y - 3); + } + } + + // is the final point implicit? + if (isImpliedLastPoint()) { + double amp = impliedAmp(); + int y = amp2y(amp); + drawDot(g, graphRight(), y); + if (displayCoord) { + g.drawString("(" + form.format(getMaxT()) + "," + + form.format(amp) + ")", graphWidth() - 36, + y - 9); + } + } + + //draw points for each point in the envelope + for (int i = 0; i < times.size(); i++) { + int t = time2x(times.get(i)); + int a = amp2y(amps.get(i)); + if (displayCoord) + g.drawString("(" + form.format(times.get(i)) + "," + + form.format(amps.get(i)) + ")", t, a); + drawDot(g, t, a); + //System.out.println("drawDot t " + t + " a " + a + " width " + + // getWidth()); + } + } + + //given coordinates, draw a circle on the canvas + private void drawDot(Graphics2D g, int t, int a) { + //draw a black circle at the specified point + g.setColor(Color.black); + //System.out.println("drawDot: " + t + "," + a); + g.fillOval(t - 2, a - 2, 5, 5); + } + + // given coordinates, draw a circle around selected envelope point + private void drawSelectionCircle(Graphics2D g) { + if (selection >= 0 && selection < times.size()) { + int t = time2x(times.get(selection)); + int a = amp2y(amps.get(selection)); + //draw a red circle around the specified point + g.setColor(Color.red); + g.drawOval(t - 4, a - 4, 9, 9); + } + } + + private void draw_connect(Graphics2D g, double t1, double a1, + double t2, double a2) { + int x1 = time2x(t1); + int x2 = time2x(t2); + int y1 = amp2y(a1); + int y2 = amp2y(a2); + if (type == PWL_TYPE) { + g.drawLine(x1, y1, x2, y2); + } else { + // pwe type, graph is linear along a log scale + if (a1 <= EPSILON || a2 <= EPSILON) { + g.drawLine(x1, y1, x1, graphBottom()); + g.drawLine(x1, graphBottom(), x2, graphBottom()); + g.drawLine(x2, graphBottom(), x2, y2); + } else { + double log1 = Math.log(a1); + double log2 = Math.log(a2); + int startline = y1; + double logIncr = (log2 - log1) / (x2 - x1); + for (int j = x1 + 1; j <= x2; j++) { + double loga = log1 + logIncr * (j - x1); + int a = amp2y(Math.exp(loga)); + g.drawLine(j - 1, startline, j, a); + startline = a; + } + } + } + } + + //connect adjacent points in the envelope by lines (pwl, pwlv) or by an + // exponential curve (pwe, pwev) + private void connectTheDots(Graphics2D g) { + g.setColor(Color.blue); + // System.out.println("connectTheDots\n"); + if (times.size() > 0) { + if (isImpliedFirstPoint()) { + draw_connect(g, 0, impliedAmp(), + times.get(0), amps.get(0)); + } + if (isImpliedLastPoint()) { + draw_connect(g, times.lastElement(), + amps.lastElement(), + getMaxT(), impliedAmp()); + } + //connect the non-endpoints in the envelope + double t1 = times.get(0); + double a1 = amps.get(0); + for (int i = 0; i < times.size() - 1; i++) { + double t2 = times.get(i + 1); + double a2 = amps.get(i + 1); + draw_connect(g, t1, a1, t2, a2); + t1 = t2; + a1 = a2; + } + } else { // size == 0, so both points are implied + draw_connect(g, 0, impliedAmp(), getMaxT(), impliedAmp()); + } + + } + + // erase the canvas and clear the parameter vectors - + // completely reset the envelope + public void clear() { + if (times != null) + times.removeAllElements(); + if (amps != null) + amps.removeAllElements(); + envTimes.removeAllItems(); + modified = true; + repaint(); + history.save(this); + } + + public void restore() { + if (history.canGet()) { + times = (Vector) (history.getTimes().clone()); + amps = (Vector) (history.getAmps().clone()); + State state = history.getState(); + type = state.type; + maxT.setText(String.valueOf(state.maxT)); + minA.setText(String.valueOf(state.minA)); + maxA.setText(String.valueOf(state.maxA)); + envTypes.setSelectedItem(types[type]); + selection = -1; + // put times in combo box + envTimes.removeAllItems(); + for (int i = 0; i < times.size(); i++) { + envTimes.insertItemAt(form.format(times.get(i)), i); + } + envAmplitudes.setText(""); + repaint(); + } + } + + //set time and amplitude on click by inserting the point into the vectors. + // if delete is checked, try to delete a point from the envelope + public void mousePressed(MouseEvent e) { + mouseDown = true; + System.out.println("mouseDown true\n"); + this.requestFocus(); + currentTime = e.getX(); + currentAmp = e.getY(); + selectCheck = checkSelection(currentTime, currentAmp); + if (selectCheck) { + return; + } + insertInOrder(x2time(currentTime), y2amp(currentAmp)); + repaint(); + } + + public void mouseDragged(MouseEvent e) { + currentTime = clipX(e.getX()); + currentAmp = clipY(e.getY()); + if (currentTime <= graphRight() && currentTime >= graphLeft() && + currentAmp >= graphTop() && currentAmp <= graphBottom()) { + deleteSelection(); + insertInOrder(x2time(currentTime), y2amp(currentAmp)); + repaint(); + } + } + + public void mouseReleased(MouseEvent e) { + System.out.println("mouseReleased\n"); + if (changed) { + history.save(this); + changed = false; + } + mouseDown = false; + System.out.println("mouseDown false\n"); + } + + // convert time coordinate to time in seconds + private double x2time(int x) { + return (x - graphLeft()) * getMaxT() / graphWidth(); + } + + private int time2x(double time) { + int x = (int) Math.round(time * graphWidth() / getMaxT()) + + graphLeft(); + return x; + } + + // convert amp coordinate to real amplitude + private double y2amp(int y) { + double maxAmp = getMaxA(); + double aRange = maxAmp - getMinA(); + double amp = maxAmp - ((y - graphTop()) * aRange / graphHeight()); + return amp; + } + + private int amp2y(double amp) { + double maxAmp = getMaxA(); + double aRange = maxAmp - getMinA(); + int y = (int) Math.round((maxAmp - amp) * graphHeight() / aRange) + + graphTop(); + // System.out.println("amp2y: amp " + amp + " y " + y); + return y; + } + + private void deleteSelection() { + if (selection < 0 || selection >= times.size()) return; + times.remove(selection); + amps.remove(selection); + modified = true; + System.out.println("deleteSelection at " + selection); + envTimes.removeItemAt(selection); + // make the Amp: box correspond to the new selection: + String amp = ""; + if (times.size() > 0) { + int index = envTimes.getSelectedIndex(); + if (index >= 0) amp = form.format(amps.get(index)); + } + envAmplitudes.setText(amp); + selection = -1; + if (!mouseDown) history.save(this); + } + + private void addPoint(int i, double absT, double absA) { + System.out.println("addPoint: " + i + " " + absT + " " + absA); + times.add(i, absT); + amps.add(i, absA); + envTimes.insertItemAt(form.format(absT), i); + System.out.println("addPoint time: " + absT + ", text " + form.format(absT)); + envTimes.setSelectedIndex(i); + envAmplitudes.setText(form.format(amps.get(i))); + selection = i; + changed = true; + if (!mouseDown) history.save(this); + } + + //insert the time and amplitude in the vectors in time sorted order + private void insertInOrder(double time, double amp) { + int i = 0; + modified = true; + if (times != null) { + while (i < times.size() && time > times.get(i)) i++; + } + addPoint(i, time, amp); + // System.out.println("absT: " + absT + " absA: " + absA + " i: " + i); + return; + } + + // Check if mouse click corresponds to existing envelope point + // return index of point or -1 if no point is close + private int getSelection(int x, int y) { + int cutoff = 7; + int bestDist = cutoff * 2; + int bestIndex = -1; + if (times == null) return bestIndex; + for (int i = 0; i < times.size(); i++) { + int xi = time2x(times.get(i)); + int yi = amp2y(amps.get(i)); + int dx = Math.abs(x - xi); + int dy = Math.abs(y - yi); + if (dx < cutoff && dy < cutoff && dx + dy < bestDist) { + bestDist = dx + dy; + bestIndex = i; + } + } + selection = bestIndex; + return bestIndex; + } + + //Check if mouse click corresponds with existing envelope point (to select point) + private boolean checkSelection(int time, int amp) { + int i = getSelection(time, amp); + if (i < 0) return false; + envTimes.setSelectedIndex(i); + envAmplitudes.setText(form.format(amps.get(i))); + repaint(); + return true; + } + + //output the envelope as a string + public String outputEnv(String envType, boolean valueType, + double minTime, double maxTime, double minAmp, + double maxAmp) { + String outputStr = new String(); + int start = 0; + + outputStr += ("(" + envType + " "); + + if (valueType) { // insert initial value + if (within(times.get(0), 0.0, EPSILON)) { + outputStr += (form.format(amps.get(0)) + " "); + start = 1; + } else outputStr += form.format(impliedAmp()) + " "; + } + + for (int i = start; i < amps.size(); i++) { + double time = times.get(i); + double amp = amps.get(i); + outputStr += form.format(time) + " " + form.format(amp) + " "; + } + + if (valueType) { // we're already ending with a value + if (within(times.lastElement(), maxTime, EPSILON)) { + // we're done because we output at maxTime + } else { + outputStr += form.format(maxTime) + " " + + form.format(impliedAmp()); + } + } else { + outputStr += form.format(maxTime); + } + outputStr += ")"; + + return outputStr; + } + + // parse envelope from string and prepare to edit + public void setEnv(String envData) { + + System.out.println("setEnv: envData " + envData); + if (envData == null) return; // just in case + //check if envelope exists in collection + boolean nameIsEnv = false; + + // trim the open and close parens from envData + int startx = envData.indexOf("(") + 1; + // if no open paren, startx will be 0 + int endx = envData.indexOf(")"); + if (endx < 0) endx = envData.length(); + envData = envData.substring(startx, endx); + + System.out.println("setEnv: envData(2) " + envData); + StringTokenizer st = new StringTokenizer(envData); + String type = st.nextToken(); + System.out.println("setEnv: type " + type); + envTypes.setSelectedItem(type); + //clear(); + + valueType = type.endsWith("v"); + int limit = (valueType ? 2 : 1); + times.removeAllElements(); + amps.removeAllElements(); + int i = 0; + // pretend mouse is down to avoid making each point undo-able + boolean save = mouseDown; + mouseDown = false; + double time, amp; + if (valueType) { // first element is value + amp = new Double(st.nextToken().trim()); + addPoint(i++, 0.0, amp); + } + while (st.countTokens() >= 2) { + String token1 = st.nextToken().trim(); + time = new Double(token1); + String token2 = st.nextToken().trim(); + amp = new Double(token2); + addPoint(i++, time, amp); + System.out.println("time " + token1 + " amp " + token2 + + " size " + times.size()); + } + mouseDown = save; // restore the mouseDown state + if (!valueType) { // last element is time + maxT.setText(st.nextToken()); + } + System.out.println("times " + times + " amps " + amps); + //calculateDraws(true); + modified = false; + repaint(); + } + + public void keyPressed(KeyEvent event) { + //Graphics2D drawArea = image.createGraphics(); + + if (event.getKeyCode() == KeyEvent.VK_DELETE) { + deleteSelection(); + repaint(); + } + } + + //fill rest of mouse functions + public void mouseEntered(MouseEvent e) {} + public void mouseExited(MouseEvent e) {} + public void mouseClicked(MouseEvent e) {} + public void mouseMoved(MouseEvent e) {} + public void keyReleased(KeyEvent event) {} + public void keyTyped(KeyEvent event) {} + } +} diff --git a/jnyqide/FindDialog.java b/jnyqide/FindDialog.java new file mode 100644 index 0000000..d67ec6c --- /dev/null +++ b/jnyqide/FindDialog.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1997 John Jensen. All rights reserved. + * + * This software is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE, + * provided the following condition is met. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that any copy or derivative of this software or documentation + * retaining the name "John Jensen" also retains this condition and the + * following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * CopyrightVersion 1.0 + */ + +package jnyqide; + +import java.util.*; +import java.awt.*; +import java.awt.event.*; +import jnyqide.*; + +class FindDialog extends Dialog implements WindowListener, ActionListener +{ + private Button fbutton,cbutton; + private MainFrame mainFrame; + private NyquistFile nyquistFile; + private TextField pattern; + private Properties strings; + + public FindDialog(NyquistFile tf, MainFrame mainFrame_) + { + super(mainFrame_, "Find", true); + + setBackground(Color.lightGray); + + nyquistFile = tf; + mainFrame = mainFrame_; + + Panel p1 = new Panel(); + p1.setLayout(new FlowLayout()); + p1.add(new Label("Find:")); + + + pattern = new TextField(); + pattern.setColumns(35); + + if (tf.pane.getSelectedText() == null) // BWP + pattern.setText(mainFrame.findPattern); + else // BWP + pattern.setText(tf.pane.getSelectedText()); // BWP + + p1.add(pattern); + p1.doLayout(); + add("North", p1); + + Panel p2 = new Panel(); + fbutton = new Button("Find Next"); + fbutton.addActionListener(this); + p2.add(fbutton); + cbutton = new Button("Close"); + cbutton.addActionListener(this); + p2.add(cbutton); + add("South",p2); + + Dimension size = new Dimension(400, 110); + setSize(size); + Point tfloc = tf.getLocation(); + Point mfloc = mainFrame.getLocation(); + setLocation(mfloc.x + tfloc.x, + mfloc.y + tfloc.y + 85); + + addWindowListener(this); + setVisible(true); + } + + public void windowDeiconified(WindowEvent event) {} + public void windowIconified(WindowEvent event) {} + public void windowActivated(WindowEvent event) {} + public void windowDeactivated(WindowEvent event) {} + public void windowOpened(WindowEvent event) {} + public void windowClosed(WindowEvent event) {} + public void windowClosing(WindowEvent event) { + mainFrame.findPattern = pattern.getText(); + nyquistFile.lastFound = pattern.getText(); // BWP + dispose(); + } + + public void actionPerformed(ActionEvent evt) + { + if (evt.getSource() == cbutton) { + mainFrame.findPattern = pattern.getText(); + nyquistFile.lastFound = pattern.getText(); + dispose(); + return; + } + + if (evt.getSource() == fbutton) + if (!nyquistFile.find(pattern.getText())) { + NotFoundDialog nf = new NotFoundDialog(mainFrame, strings, + getLocation()); + nf.setVisible(true); + } + } + +} diff --git a/jnyqide/InstrumentCharacteristics.java b/jnyqide/InstrumentCharacteristics.java new file mode 100644 index 0000000..91fac84 --- /dev/null +++ b/jnyqide/InstrumentCharacteristics.java @@ -0,0 +1,364 @@ +package jnyqide; + +import java.util.ArrayList; +import java.io.BufferedReader; + +/*** +** Class: InstrumentCharacteristics +** Author: Priyanka Raghavan and Roger B. Dannenberg +** Description: The instrument characteristics class reads from +** the instruments.txt file and stores the +** instrument characteristics such as the subcategory,name,library. +** The characteristics include the implementation and parameter +** description. The different parameters are added as an arraylist. +* +* Syntax for the instruments.txt file: +* (see instruments.txt for examples, it should be clear) +* Each sound is described by a function declaration preceded by +* a category like this: +* category:subcategory[function](parameters) +* where category and subcategory determine what appears in the +* pull-down lists in the browser, and function is the lisp +* function to call (if omitted, then subcategory is also the +* function name). parameters is a comma-separated list of +* parameter declarations. Each parameter is of the form +* type name = default (low:high) +* where type is "int" or "float", name is the parameter name +* (if the parameter is a keyword parameter, it is prefixed with +* a colon), and low:high gives the range for a slider. +* After the function declaration, there can be specifications for +* the implementation of the function. There should be either +* a pair of implementations for LISP and SAL, or a single +* REQUIRE. The LISP and SAL implementation is specified as follows: +* LISP-SOURCE +* +* SAL-SOURCE +* +* and the REQUIRE is specified as follows: +* REQUIRE "path to implementation file to be loaded" +* After the implementation specifications (if any), the +* sound description is terminated by the following line: +* END-SOUND +* There may be any number of these sound specifications (instruments) +* in the file. +* When a user selects an instrument in the browser, the appropriate +* implementation is constructed (using SAL-SOURCE or LISP-SOURCE if +* present, otherwise using REQUIRE to load a file) and the function +* is called with parameters chosen by sliders. +* +**/ + +public class InstrumentCharacteristics { + + private String categoryName; + private String subcategoryName; + private String functionName; + private ArrayList parameterList; + private String lispImplementation; + private String salImplementation; + private String require; + + private static char buffer; + private static boolean bufferp; + private static String line; + + InstrumentCharacteristics() { + bufferp = false; + parameterList = new ArrayList(); + } + + public String getCategoryName() { return categoryName; } + + public void setCategoryName(String name) { categoryName = name; } + + public void setSubcategoryName(String subname) { + subcategoryName = subname; + } + + public String getSubcategoryName() { return subcategoryName; } + + public String getFunctionName() { return functionName; } + + + public void addParameter(String name, String minValue, String maxValue, + String defaultValue, String type) { + Parameter parameter = new Parameter(name, minValue, maxValue, + defaultValue, type); + parameterList.add(parameter); + } + + public ArrayList getParameters(){ return parameterList; } + + public String getLispImplementation() { return lispImplementation; } + + public String getSalImplementation() { return salImplementation; } + + public String getRequire() { return require; } + + public String readImplementation(BufferedReader br) throws Exception { + String implementation = ""; + while ((line = br.readLine()) != null && + line.indexOf("REQUIRE") != 0 && + line.indexOf("LISP-SOURCE") != 0 && + line.indexOf("SAL-SOURCE") != 0 && + line.indexOf("END-SOUND") != 0) { + implementation = implementation + line + "\n"; + } + return implementation; + } + + public boolean readData(BufferedReader br) { + categoryName = getToken(br); // category + if (categoryName == null) return false; + if (getNonSpace(br) != ':') { + System.out.println("expected : after " + categoryName); + return false; + } + subcategoryName = getToken(br); + int c = getNonSpace(br); + functionName = subcategoryName; + if (c == '[') { + functionName = getToken(br); + if (getNonSpace(br) != ']') { + System.out.println("expected ] after " + functionName); + return false; + } + } else ungetChar(c); + if (getNonSpace(br) != '(') { + System.out.println("no ( after " + functionName); + return false; + } + while ((c = getNonSpace(br)) != ')') { + ungetChar(c); + Parameter p = readParameter(br); + if (p == null) { + System.out.println("syntax error for parameter in " + + subcategoryName); + return false; + } + parameterList.add(p); + } + // get a file to load or an implementation to execute + require = null; + lispImplementation = null; + salImplementation = null; + try { + // read eol after function spec + line = br.readLine(); + line = ""; // force a readline on first entry to loop + while (true) { + while (line != null && line.length() < 3) { + // skip blank lines -- we're not checking too carefully + // but a char count of 3 allows only CRLF and maybe a + // space or tab + line = br.readLine(); + } + if (line == null) { + System.out.println( + "expected LISP-SOURCE or SAL-SOURCE, REQUIRE or " + + "END-SOUND, not " + line); + return false; + } + + int reqPos = line.indexOf("REQUIRE"); + if (reqPos >= 0) { + reqPos += 8; // length of "REQUIRE " + require = line.substring(reqPos, line.length()); + line = br.readLine(); + } else if (line.indexOf("LISP-SOURCE") == 0) { + // read until LISP-END + lispImplementation = readImplementation(br); + } else if (line.indexOf("SAL-SOURCE") == 0) { + // read until SAL-END + salImplementation = readImplementation(br); + } else if (line.indexOf("END-SOUND") == 0) { + return true; + } else { + System.out.println( + "expected REQUIRE, LISP-SOURCE, SAL-SOURCE, or " + + "END-SOUND, not " + line); + return false; + } + } + } catch (Exception e) { + return false; + } + } + + private Parameter readParameter(BufferedReader br) { + Parameter p = new Parameter(); + String tok = getToken(br); + if (tok == null) { + System.out.println("expected parameter type: " + tok); + return null; + } + p.setType(tok); + int param1 = getNonSpace(br); + if (param1 != ':') { + ungetChar(param1); + } + tok = getToken(br); + if (tok == null) { + System.out.println("expected parameter name: " + tok); + return null; + } + if (param1 == ':') tok = ":" + tok; + p.setName(tok); + + if (getNonSpace(br) != '=') { + System.out.println("expected = after parameter: " + tok); + return null; + } + + tok = getToken(br); + if (tok == null) { + System.out.println("expected default value: " + tok); + return null; + } + p.setDefaultValue(tok); + + if (getNonSpace(br) != '(') { + System.out.println("expected ( after default value: " + tok); + return null; + } + + tok = getToken(br); + if (tok == null) { + System.out.println("expected min value: " + tok); + return null; + } + p.setMinValue(tok); + + if (getNonSpace(br) != ':') { + System.out.println("expected : after min value: " + tok); + return null; + } + + tok = getToken(br); + if (tok == null) { + System.out.println("expected max value: " + tok); + return null; + } + p.setMaxValue(tok); + + if (getNonSpace(br) != ')') { + System.out.println("expected ) after max value: " + tok); + return null; + } + + int c = getNonSpace(br); + if (c != ',') ungetChar(c); + + return p; + } + + private int getNonSpace(BufferedReader br) { + int c; + while ((c = getChar(br)) != -1 && Character.isWhitespace(c)); + return c; + } + + private int getChar(BufferedReader br) { + if (bufferp) { + bufferp = false; + return buffer; + } + try { + return br.read(); + } catch (Exception e) { + return -1; + } + } + + private void ungetChar(int c) { + if (c == -1) return; // ignore EOF + buffer = (char) c; + bufferp = true; + } + + private String getToken(BufferedReader br) { + int c = getNonSpace(br); + StringBuffer token = new StringBuffer(); + while (c != -1 && (Character.isLetterOrDigit(c) || + c == '-' || c == '.')) { + token.append((char) c); + c = getChar(br); + } + ungetChar(c); + String s = new String(token); + if (s.length() == 0) return null; + // System.out.println("gettoken: " + token); + return s; + } +} + + +/** + ** Class: Parameter + ** Author: Priyanka Raghavan + ** Description: This class is used to store parameter values like + ** name, minvalue, maxvalue, default value, and type (integer,string, etc.) + ** + **/ + +class Parameter{ + String name; + String minValue; + String maxValue; + String defaultValue; + String type; + float value; + + Parameter() { } + + Parameter(String name, String minValue, String maxValue, + String defaultValue, String type) { + this.name = name; + this.minValue = minValue; + this.maxValue = maxValue; + this.defaultValue = defaultValue; + this.type=type; + value = 0.0f; + } + + public void setName(String name) { + this.name=name; + } + + public void setMinValue(String value) { + minValue = value; + } + + public void setMaxValue(String value) { + maxValue = value; + } + + public void setDefaultValue(String defaultvalue) { + defaultValue = defaultvalue; + } + + public String getName() { + return name; + } + + public String getMinValue() { + return minValue; + } + + public String getMaxValue() { + return maxValue; + } + + public String getType() { return type; } + + public void setType(String type) { this.type = type; } + + public String getDefaultValue() { return defaultValue; } + + public float getValue() { return value; } + + public void setValue(float f) { value = f; } + +} + + diff --git a/jnyqide/Jslide.java b/jnyqide/Jslide.java new file mode 100755 index 0000000..fb68b12 --- /dev/null +++ b/jnyqide/Jslide.java @@ -0,0 +1,201 @@ +package jnyqide; +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +import javax.swing.event.*; +import java.util.*; + +public class Jslide extends JFrame implements ActionListener { + MainFrame myParent; + static final int numSliders = 8; + static final int numEqualizers = 10; + /* Sliders and labels that will be used on the gui*/ + JSlider[] js; + float[][] eqState; + + /* Buttons that will appear on the Equalizer*/ + JButton setEqValue = new JButton("Set"); + JButton loadEqValue = new JButton("Load"); + JButton restore = new JButton("Reset"); + JComboBox eqList = new JComboBox(); + JPanel p1 = new JPanel(); + JPanel GraphEqPanel; + String extension = ""; + // Create text fields to display slider position + String[] labels = {"84", "167", "330", "652", "1.3k", "2.5k", "5k", "10k"}; + JLabel[] jlabels; + boolean modified = false; + + public Jslide(MainFrame parent) + { + myParent = parent; + /*Open the file and set sliders to the default*/ + //fileName = "eq" + extension + ".dat"; + //setAllSliders(fileName); + + /* Action listener for the restore button. This + * restores all slider values to zero. Right now + * this has no effect on the file itself. + */ + js = new JSlider[numSliders]; + eqState = new float[numEqualizers][numSliders]; + for (int i = 0; i < numSliders; i++) { + js[i] = initializeSlider(); + for (int j = 0; j < numEqualizers; j++) eqState[j][i] = 0; + } + + setEqValue.addActionListener(this); + setEqValue.setActionCommand("set-eq-value"); + loadEqValue.addActionListener(this); + loadEqValue.setActionCommand("load-eq-value"); + + restore.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.out.println("reset listener"); + for (int i = 0; i < numSliders; i++) { + js[i].setValue(0); + } + } + } + ); + + /*Create individual Panels to be added to the Pane*/ + + /* Slider panel*/ + p1.setBackground(Color.WHITE); + p1.setSize(500,300); + p1.setLayout(new GridLayout(1, 8)); + /* Panel with all the labels*/ + JPanel p2 = new JPanel(); + p2.setBackground(Color.WHITE); + p2.setLayout(new GridLayout(1, 8)); + /* add the sliders and labels */ + jlabels = new JLabel[numSliders]; + for (int i = 0; i < numSliders; i++) { + p1.add(js[i]); + jlabels[i] = new JLabel(labels[i]); + p2.add(jlabels[i]); + } + /* Combo box with a liste of numbers of equalizer values*/ + String[] eqNums = {"0","1", "2", "3", "4","5","6","7","8","9"}; + eqList = new JComboBox(eqNums); + eqList.addActionListener(this); + eqList.setActionCommand("eq-selection"); + + /*Panel the buttons, and the combo box on it*/ + JPanel pA = new JPanel(); + pA.setLayout(new GridLayout(1,4)); + pA.setBackground(Color.WHITE); + pA.add(setEqValue); + pA.add(loadEqValue); + pA.add(restore); + pA.add(eqList); + + pA.setSize(50,50); + + GraphEqPanel = new JPanel(); + GraphEqPanel.setLayout(new BorderLayout()); + GraphEqPanel.setBackground(Color.WHITE); + GraphEqPanel.setSize(300,300); + GraphEqPanel.add(p1, BorderLayout.NORTH); + GraphEqPanel.add(p2, BorderLayout.CENTER); + GraphEqPanel.add(pA, BorderLayout.SOUTH); + + loadEqValue(); + } //Close constructor + + public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); + if (command.equals("eq-selection")) { + equalizerSelected(); + } else if (command.equals("set-eq-value")) { + setEqValue(); + } else if (command.equals("load-eq-value")) { + loadEqValue(); + } + } + + public void equalizerSelected() { + String name = (String) eqList.getSelectedItem(); + int index = new Integer(name); + // load values from state + for (int i = 0; i < numSliders; i++) { + js[i].setValue((int) eqState[index][i]); + } + } + + public void setEqValue() { + // store slider values into state + String name = (String) eqList.getSelectedItem(); + int index = new Integer(name); + // store value into state + String definition = "(define-eq " + name + " #("; + for (int i = 0; i < numSliders; i++) { + eqState[index][i] = js[i].getValue(); + definition += (" " + eqState[index][i]); + } + definition += "))\n\n"; + myParent.sendInput(definition); + } + + public void loadEqValue() { + myParent.callFunction("get-eq-data", ""); + } + + /** + * Public function that returns the graphic equalizer panel + * @return + */ + public JPanel getGraphEq() { + return GraphEqPanel; + } + + /**The getter for the GUI sliders + * @return db value as an int + */ + private int get_db_val(JSlider j){ + return j.getValue(); + } + + /** + * A Private method that will initialize the sliders. This is + * to clean up the code and make it shorter. + * @param j + */ + private JSlider initializeSlider() { + JSlider j = new JSlider(JSlider.VERTICAL, -15,15,0); + j.setMajorTickSpacing(10); + j.setMinorTickSpacing(2); + j.setPaintTicks(true); + j.setPaintLabels(true); + j.setForeground(Color.BLACK); + j.setBorder(BorderFactory.createEtchedBorder()); + return j; + } + + public void loadEqData(String data) { + System.out.println("loadEqData " + data); + while (true) { + int i = data.indexOf("\n"); + if (i < 0) { + equalizerSelected(); // load sliders from eqState + return; + } + String line = data.substring(0, i); + System.out.println("loadEqData line " + line); + data = data.substring(i + 1); + // string has 9 numbers + StringTokenizer st = new StringTokenizer(line); + String name = st.nextToken(); + int index = new Integer(name); + for (i = 0; i < numSliders; i++) { + eqState[index][i] = new Float(st.nextToken()); + } + } + } +} + + + diff --git a/jnyqide/LispFileFilter.java b/jnyqide/LispFileFilter.java new file mode 100644 index 0000000..219c7af --- /dev/null +++ b/jnyqide/LispFileFilter.java @@ -0,0 +1,33 @@ +package jnyqide; + +import javax.swing.filechooser.*; +import java.io.File; + + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +public class LispFileFilter extends FileFilter { + + public LispFileFilter() { + } + + public boolean accept(File f) { + if (f.getName().endsWith(".lsp")) return true; + for (int x = 0; x < f.getName().length(); x++) { + if ((f.getName().charAt(x) == '.')) + return false; + } + return true; + } + + public String getDescription() { + return "Lisp files."; + } +} diff --git a/jnyqide/Main.java b/jnyqide/Main.java new file mode 100644 index 0000000..6ff6fe9 --- /dev/null +++ b/jnyqide/Main.java @@ -0,0 +1,75 @@ +package jnyqide; + +import javax.swing.UIManager; +import java.awt.*; + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +public class Main { + boolean packFrame = false; + + //Construct the application + public Main() { + String osName = System.getProperty("os.name"); + System.out.println(osName); + if (osName.startsWith("Linux")) { + // motif style has some extra buttons to iconify internal frames + // but this obscures windows, and metal looks better anyway + try { + UIManager.setLookAndFeel( + "javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + System.out.println(e); + } + } + MainFrame frame = new MainFrame(); + //Validate frames that have preset sizes + //Pack frames that have useful preferred size info, e.g. from their layout + if (packFrame) { + frame.pack(); + } else { + frame.validate(); + } + //Center the window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = frame.getSize(); + // subtract 20 here because otherwise Mac OS X frames will be too tall + // to access resize nbutton + System.out.print("initial frame height "); + System.out.println(frameSize.height); + System.out.print("screen height "); + System.out.println(screenSize.height); + if (frameSize.height > screenSize.height) { + frameSize.height = screenSize.height - 40; + } + if (frameSize.width > screenSize.width) { + frameSize.width = screenSize.width; + } + System.out.print("finall frame height "); + System.out.println(frameSize.height); + frame.setSize(frameSize); + frame.setLocation((screenSize.width - frameSize.width) / 2, + (screenSize.height - frameSize.height) / 2); + frame.setVisible(true); + frame.tileCompletion(); + } + + + //Main method + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch(Exception e) { + e.printStackTrace(); + } + new Main(); + } +} diff --git a/jnyqide/MainFrame.java b/jnyqide/MainFrame.java new file mode 100644 index 0000000..04f924d --- /dev/null +++ b/jnyqide/MainFrame.java @@ -0,0 +1,1539 @@ +package jnyqide; + +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.event.*; +import java.beans.*; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.event.*; +import javax.swing.undo.*; +import javax.swing.text.html.*; +// import javax.swing.JOptionPane.*; +import javax.swing.filechooser.FileFilter; +import java.io.*; +import jnyqide.*; +// this won't work on non-Mac, so use reflection tricks below +// import com.apple.mrj.*; // import Mac menu support +import java.lang.reflect.*; // import Constructor class +import java.util.prefs.*; +import java.util.Collection; +import java.net.URL; + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +class ScrollUpdate implements Runnable { + MainFrame frame; + + ScrollUpdate(MainFrame mainframe) { + frame = mainframe; + } + + public void run() { + frame.ScrollToEnd(); + } +} + + +public class MainFrame extends JFrame { + JPanel contentPane; + JMenuBar jMenuBar1 = new JMenuBar(); + + JMenu jMenuFile = new JMenu(); + JMenu jMenuEdit = new JMenu(); + JMenu jMenuProcess = new JMenu(); + JMenu jMenuWindow = new JMenu(); + JMenu jMenuHelp = new JMenu(); + + JToolBar jToolBar = new JToolBar(); + float test_value = 0.0F; + ImageIcon image1; + ImageIcon image2; + ImageIcon image3; + public JLabel statusBar = new JLabel(); + JButton salLispButton; + BorderLayout borderLayout1 = new BorderLayout(); + JDesktopPane jDesktop; + public CodePane jScrollPane; + // accessed by CodePane sometimes: + public JTextArea jOutputArea; + JTextArea jListOutputArea; + JScrollPane jOutputPane; + JScrollPane jListOutputPane; + JInternalFrame jOutputFrame; + JInternalFrame jListOutputFrame; + MiniBrowser miniBrowser; + + NyquistThread nyquistThread; + JInternalFrame jFrame; + // used by TextColor to communicate result back to MainFrame + // public static boolean evenParens; + String currentDir = ""; + Runnable update = new ScrollUpdate(this); + PlotFrame plotFrame; + File homeDir = new File("."); + public String findPattern = ""; + public String replacePattern = ""; + boolean packFrame = false; + EnvelopeFrame envelopeEditor; + /* BEGIN UPIC */ + UPICFrame upicEditor; + /* END UPIC */ + Jslide eqEditor; + public Preferences prefs; + public static final boolean prefStartInSalModeDefault = true; + public static final boolean prefSalShowLispDefault = false; + public static final boolean prefParenAutoInsertDefault = false; + public static final boolean prefEnableSoundDefault = true; + public static final boolean prefAutoNormDefault = true; + + public static final boolean prefSalTraceBackDefault = true; + public static final boolean prefSalBreakDefault = false; + public static final boolean prefXlispBreakDefault = true; + public static final boolean prefXlispTraceBackDefault = false; + + public static final boolean prefPrintGCDefault = false; + public static final boolean prefFullSearchDefault = true; + public static final boolean prefInternalBrowserDefault = false; + public static final boolean prefOnlineManualDefault = false; + public static final double prefCompletionListPercentDefault = 60.0; + public static final String prefAudioRateDefault = "44100"; + public static final String prefControlRateDefault = "2205"; + public static final String prefFontSizeDefault = "12"; + + public static boolean prefStartInSalMode = prefStartInSalModeDefault; + public static boolean prefSalShowLisp = prefSalShowLispDefault; + public static boolean prefParenAutoInsert = prefParenAutoInsertDefault; + public static boolean prefEnableSound = prefEnableSoundDefault; + public static boolean prefAutoNorm = prefAutoNormDefault; + public static boolean prefSalTraceBack = prefSalTraceBackDefault; + public static boolean prefSalBreak = prefSalBreakDefault; + public static boolean prefXlispBreak = prefXlispBreakDefault; + public static boolean prefXlispTraceBack = prefXlispTraceBackDefault; + public static boolean prefPrintGC = prefPrintGCDefault; + public static boolean prefFullSearch = prefFullSearchDefault; + public static boolean prefInternalBrowser = prefInternalBrowserDefault; + public static boolean prefOnlineManual = prefOnlineManualDefault; + public static double prefCompletionListPercent = + prefCompletionListPercentDefault; + public static String prefAudioRate = prefAudioRateDefault; + public static String prefControlRate = prefControlRateDefault; + public static String prefFontSize = prefFontSizeDefault; + public static String prefDirectory = ""; + public static String prefSFDirectory = ""; + + public static boolean prefsHaveBeenSet = false; + + public boolean workspaceLoaded = false; + public boolean workspaceSaved = false; + + public static final String onlineManualURL = + "http://www.cs.cmu.edu/~rbd/doc/nyquist/"; + + + // inputStrings allows user to type ^P to get previous entry, + // or ^D for next entry. This is tricky. The desired behavior is: + // There is a history list of everything executed in order. + // Typing ^P moves a cursor back in history, ^D forward. When you type + // Enter, a new string is placed at the front of history, and the + // cursor is set to the front of history as well. + // To implement this behavior, inputStringsX is the front of history. + // It wraps around when it reaches inputStringsLen. To be precise, + // inputStringsX is the indeX of the location where the next input + // string will go. inputStringsCursor is the position controlled + // by ^P and ^D. inputSringsCursor is set + // to inputStringsX when the user types Enter. + + // Sending input is tricky because you could be in Lisp or SAL mode. + // Either way, you want to indent multi-line input by the prompt size + // (2 for lisp, 4 for Sal) and you want an extra return after Sal + // commands. You DO NOT want the last 2 returns to be followed by + // spaces since SAL looks at the end of input to determine when a + // command is complete. + // + // Use cases: + // calling a function like replay (R): + // use callFunction() + // user types return after code in input box: + // use SendInputLn + // + // Support functions: + // callFunction -- build expression and call SendInputLn + // setVariable -- build expression and call SendInputLn + // SendInputLn -- fix up indentation, append newline or 2, SendInput + // SendInput -- just send text to Nyquist + + int inputStringsX = 0; + int inputStringsCursor = 0; + int inputStringsLen = 20; + String inputStrings[] = new String[inputStringsLen]; + + // some "features" for system dependent code + public boolean hasRightMouseButton = true; + + //Construct the frame + public MainFrame() { + enableEvents(AWTEvent.WINDOW_EVENT_MASK); + try { + mainFrameInit(); + } + catch(Exception e) { + e.printStackTrace(); + } + } + + + public boolean isMac() { + // System.out.println("mrj.version" + System.getProperty("mrj.version")); + // return System.getProperty("mrj.version") != null; + + // The code above seems not to work on Leopard; the following + // suggested by Raymond Martin: + + final String strOS; + + try { strOS = System.getProperty("os.name"); } + catch(final SecurityException e) { + System.out.println("In isMac: error " + e); + return(false); + } + System.out.println("strOS " + strOS); + return(strOS.indexOf("Mac OS") >= 0); + } + + PreferencesDialog preferencesDialog; + + public void disconnectPreferences() { + preferencesDialog = null; + } + + + protected void setVariable(String var, String val) { + String input; + if (jScrollPane.isSal) { + input = "set " + var + " = " + val; + } else { + input = "(setf " + var + " " + val + ")"; + } + sendInputLn(input); + } + + + String tOrNil(boolean val) { + return (val ? "t" : "nil"); + } + + + protected void setBoolean(String var, boolean val) { + setVariable(var, tOrNil(val)); + } + + + // invoke a function call in Nyquist with 0 or 1 parameters + // (pass "" for 0 parameters) + protected void callFunction(String fn, String parameter) { + String input; + if (jScrollPane.isSal) { + input = "exec " + fn + "(" + parameter + ")"; + } else { + input = "(" + fn + (parameter.length() > 0 ? " " : "") + + parameter + ")"; + } + sendInputLn(input); + } + + + public void Prefs() { + // ignore if preferences is already open + if (preferencesDialog != null) return; + preferencesDialog = new PreferencesDialog(this); + jDesktop.add(preferencesDialog); + jDesktop.getDesktopManager().activateFrame(preferencesDialog); + } + + // create a button + private JButton buttonInit(String name, + String tip, ActionListener listener) { + JButton button = new JButton(); + button.setText(name); + button.setActionCommand(name); + button.setToolTipText(tip); + button.addActionListener(listener); + jToolBar.add(button); + return button; + } + + private void menuAddItem(JMenu menu, String name, char mnemonic, + KeyStroke accelerator, ActionListener listener) { + JMenuItem item = new JMenuItem(); + item.setText(name); + item.setActionCommand(name); + if (mnemonic != '\000') item.setMnemonic(mnemonic); + if (accelerator != null) item.setAccelerator(accelerator); + item.addActionListener(listener); + menu.add(item); + } + + public void handlePrefs() { + System.out.println("handlePrefs called"); + } + + //Component initialization + private void mainFrameInit() throws Exception { + // if this is a Mac, we want some menu items on the application menu, + // which is accessed via some special apple code, but the apple code + // is not going to be installed if you are running windows or linux, + // so we use java reflection here to load the special code ONLY if + // we're on a Mac + // + // The special code ultimately calls back to the methods About(), + // Prefs(), and Quit() in this class. The "normal" Windows/Linux + // code should do the same. + if (isMac()) { + hasRightMouseButton = false; + try { + Object[] args = { this }; + Class[] arglist = { MainFrame.class }; + + Class mac_class = Class.forName("jnyqide.SpecialMacHandler"); + + /* + Thread t = Thread.currentThread(); + ClassLoader cl = t.getContextClassLoader(); + Class mac_class = cl.loadClass("SpecialMacHandler"); + */ + + System.out.println("got the class\n"); + Constructor new_one = mac_class.getConstructor(arglist); + System.out.println("got the constructor\n"); + new_one.newInstance(args); + + System.out.println("isMac, so created instance of SpecialMacHandler"); + } catch(Exception e) { + System.out.println(e); + } + } + + prefs = Preferences.userNodeForPackage(Main.class); + prefStartInSalMode = prefs.getBoolean("start-with-sal", + prefStartInSalMode); + prefSalShowLisp = prefs.getBoolean("sal-show-lisp", prefSalShowLisp); + prefParenAutoInsert = prefs.getBoolean("paren-auto-insert", + prefParenAutoInsert); + prefEnableSound = prefs.getBoolean("sound-enable", prefEnableSound); + prefAutoNorm = prefs.getBoolean("auto-norm", prefAutoNorm); + prefSalTraceBack = prefs.getBoolean("sal-traceback", prefSalTraceBack); + prefSalBreak = prefs.getBoolean("sal-break", prefSalBreak); + prefXlispBreak = prefs.getBoolean("xlisp-break", prefXlispBreak); + prefXlispTraceBack = prefs.getBoolean("xlisp-traceback", + prefXlispTraceBack); + // if XlispTracBack, then we need to set XlispBreak: + prefXlispBreak = prefXlispBreak || prefXlispTraceBack; + prefPrintGC = prefs.getBoolean("print-gc", prefPrintGC); + prefFullSearch = prefs.getBoolean("completion-list-full-search", + prefFullSearch); + prefInternalBrowser = prefs.getBoolean("internal-browser", + prefInternalBrowser); + prefOnlineManual = prefs.getBoolean("online-manual", prefOnlineManual); + prefCompletionListPercent = prefs.getDouble("completion-list-percent", + prefCompletionListPercent); + prefAudioRate = prefs.get("audio-rate", prefAudioRate); + prefControlRate = prefs.get("control-rate", prefControlRate); + prefFontSize = prefs.get("font-size", prefFontSize); + prefDirectory = prefs.get("initial-directory", prefDirectory); + prefSFDirectory = prefs.get("default-sf-directory", prefSFDirectory); + prefsHaveBeenSet = false; + + image1 = new ImageIcon("openFile.gif"); + image2 = new ImageIcon("closeFile.gif"); + image3 = new ImageIcon("help.gif"); + //setIconImage(Toolkit.getDefaultToolkit().createImage(MainFrame.class.getResource("[Your Icon]"))); + contentPane = (JPanel) this.getContentPane(); + contentPane.setLayout(borderLayout1); + this.setSize(new Dimension(400, 300)); + this.setTitle("Nyquist IDE"); + statusBar.setText(" "); + + ActionListener menuButtonListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + menuButtonHandler(e); + } + }; + + // Menu Bar + jMenuFile.setText("File"); + menuAddItem(jMenuFile, "New", 'n', + KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + menuButtonListener); + menuAddItem(jMenuFile, "Open", 'o', + KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + menuButtonListener); + + if (!isMac()) { // if isMac(), Quit (not Exit) and Prefs are on the + // application menu + menuAddItem(jMenuFile, "Preferences...", '\000', null, + menuButtonListener); + menuAddItem(jMenuFile, "Exit", '\000', null, menuButtonListener); + } + + jMenuEdit.setText("Edit"); + + menuAddItem(jMenuEdit, "Previous", 'p', + KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + menuButtonListener); + + menuAddItem(jMenuEdit, "Next", 'n', + KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_D, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + menuButtonListener); + + menuAddItem(jMenuEdit, "Select Expression", 'e', + KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + menuButtonListener); + + jMenuHelp.setText("Help"); + if (!isMac()) { // if isMac(), About is on the application menu + menuAddItem(jMenuHelp, "About", 'h', null, menuButtonListener); + } + menuAddItem(jMenuHelp, "Manual", 'm', null, menuButtonListener); + + jMenuProcess.setText("Process"); + menuAddItem(jMenuProcess, "Replay", 'r', null, menuButtonListener); + menuAddItem(jMenuProcess, "Plot", 'p', null, menuButtonListener); + menuAddItem(jMenuProcess, "Copy to Lisp", 'u', + KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_U, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + menuButtonListener); + menuAddItem(jMenuProcess, "Mark", 'a', null, menuButtonListener); + + jMenuWindow.setText("Window"); + menuAddItem(jMenuWindow, "Tile", 't', null, menuButtonListener); + menuAddItem(jMenuWindow, "Browse", 'b', null, menuButtonListener); + menuAddItem(jMenuWindow, "EQ", 'q', null, menuButtonListener); + menuAddItem(jMenuWindow, "Envelope Edit", 'e', null, menuButtonListener); + /* BEGIN UPIC */ + menuAddItem(jMenuWindow, "UPIC Edit", 'u', null, menuButtonListener); + /* END UPIC */ + buttonInit("Info", "Print Lisp memory status", menuButtonListener); + buttonInit("Break", "Break/interrupt Lisp interpreter", + menuButtonListener); + // removed "Up" and "Cont" just to make some real-estate + // buttonInit("Up", "Return from this break level", menuButtonListener); + // buttonInit("Cont", "Continue Lisp execution", menuButtonListener); + salLispButton = buttonInit("Sal", "Change Mode", menuButtonListener); + buttonInit("Top", "Exit to Lisp top-level", menuButtonListener); + buttonInit("Replay", "Replay the last sound", menuButtonListener); + int i; + for (i = 0; i < 11; i++) { + String name = "F" + (i + 2); + String tip = "Evaluate (" + name + ")"; + buttonInit(name, tip, menuButtonListener); + } + + buttonInit("Browse", "Browse Sound/Instrument/Effect Library", + menuButtonListener); + buttonInit("EQ", "Equalizer Control Panel", menuButtonListener); + buttonInit("EnvEdit", "Open Graphical Envelope Editor", + menuButtonListener); + // buttonNew.setIcon(image1); + buttonInit("New File", "New File", menuButtonListener); + // buttonOpen.setIcon(image1); + buttonInit("Open File", "Open File", menuButtonListener); + // buttonSave.setIcon(image3); + buttonInit("Save File", "Save File", menuButtonListener); + buttonInit("Load", "Load File into Nyquist", menuButtonListener); + buttonInit("Mark", "Get elapsed audio play time", menuButtonListener); + + jMenuBar1.add(jMenuFile); + jMenuBar1.add(jMenuEdit); + jMenuBar1.add(jMenuProcess); + jMenuBar1.add(jMenuWindow); + jMenuBar1.add(jMenuHelp); + this.setJMenuBar(jMenuBar1); + + //MRJApplicationUtils.registerPrefsHandler(this); + + jOutputArea = new JTextArea(); + jOutputArea.setFont(new Font("Courier", Font.PLAIN, 12)); + jOutputArea.setLineWrap(true); + jOutputArea.setEditable(false); + jOutputPane = new JScrollPane( jOutputArea ); + jOutputPane.setHorizontalScrollBarPolicy( + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + jOutputPane.setVerticalScrollBarPolicy( + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + + jListOutputArea = new JTextArea(); + jListOutputArea.setLineWrap(true); + jListOutputArea.setEditable(false); + // add mouse listener + jListOutputArea.addMouseListener(new MouseListener () { + public void mouseExited(MouseEvent e) { }; + public void mouseEntered(MouseEvent e) { }; + public void mousePressed(MouseEvent e) { }; + public void mouseReleased(MouseEvent e) { }; + + public void mouseClicked(MouseEvent e) { + // System.out.println(e.paramString()); + int pos = jListOutputArea.viewToModel(e.getPoint()); + int start = 0, end = 0; + String line = ""; + // System.out.println("text posn = " + pos); + try { + int lineno = jListOutputArea.getLineOfOffset(pos); + // System.out.println("line no = " + lineno); + start = jListOutputArea.getLineStartOffset(lineno); + end = jListOutputArea.getLineEndOffset(lineno); + // System.out.println("start = " + start + " end = " + end); + // skip newline by subtracting one from length + if (end > start + 1) { + line = jListOutputArea.getText(start, end - start - 1); + // WordList.replaceWithTemplate(line); + } // otherwise nothing selected + } catch (Exception ex) { + ex.printStackTrace(System.err); + } + + // System.out.println("event: " + e); + if (SwingUtilities.isRightMouseButton(e) || + // for Mac, allow option click (which java sees as alt key) + (e.getModifiers() & InputEvent.ALT_MASK) != 0) { + String ext = WordList.getlink(line); + System.out.println(line + " : " + ext); + String url, urlbase; + + if (prefOnlineManual) urlbase = onlineManualURL; + else urlbase = findManualURL(""); + url = urlbase + ext; + + if (prefInternalBrowser) { + miniBrowser.setVisible(true); + System.out.println("URL is: " + url); + miniBrowser.setPage(url); + } else BareBonesBrowserLaunch.openURL(url); + } else { + // System.out.println(e.paramString()); + WordList.replaceWithTemplate(line); + } + } + }); + jListOutputPane = new JScrollPane( jListOutputArea ); + jListOutputPane.setHorizontalScrollBarPolicy( + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + jListOutputPane.setVerticalScrollBarPolicy( + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + + jScrollPane = new CodePane(new Dimension(400, 200), this, statusBar, + Integer.parseInt(prefFontSize)); + + // Top panel for command entry, plot, and toolbar + JPanel jCommands = new JPanel( new BorderLayout() ); + JPanel jInputAndPlot = new JPanel(new BorderLayout(3, 0)); + jInputAndPlot.add(jScrollPane, BorderLayout.WEST); + System.out.println("\n\n\n\n\n\n\nadded jScrollPane " + jScrollPane + " to panel\n\n\n\n\n\n"); + jCommands.add(jToolBar, BorderLayout.SOUTH); + jCommands.add(jInputAndPlot, BorderLayout.CENTER); + jCommands.setPreferredSize(new Dimension(300, 150)); + + // Main desktop + jDesktop = new JDesktopPane(); + jDesktop.setPreferredSize( new Dimension(300, 300) ); + + jOutputFrame = new JInternalFrame("Output"); + // make this wide enough so XLISP GC messages do not wrap + // (it's annoying) + //jOutputFrame.setSize(new Dimension(500, 530 / 3)); + jOutputFrame.setVisible(true); + jOutputFrame.getContentPane().add(jOutputPane); + jOutputFrame.setResizable( true ); + //jOutputFrame.setLocation(0, (530 * 2) / 3); + jDesktop.add( jOutputFrame ); + + + String clTitle = "Completion List" + (hasRightMouseButton ? + " - Right Click for Help" : + " - Option Click for Help"); + jListOutputFrame = new JInternalFrame(clTitle); + //jListOutputFrame.setSize( new Dimension (500, (530 * 2) / 3)); + jListOutputFrame.setVisible(true); + jListOutputFrame.getContentPane().add(jListOutputPane); + jListOutputFrame.setResizable(true); + //jListOutputFrame.setLocation(0,0); + jDesktop.add(jListOutputFrame); + + contentPane.add( jCommands, BorderLayout.NORTH); + contentPane.add( jDesktop, BorderLayout.CENTER ); + contentPane.add(statusBar, BorderLayout.SOUTH); + setSize( new Dimension(800, 800) ); + + miniBrowser = new MiniBrowser("Nyquist Manual"); + jDesktop.add(miniBrowser); + + TextColor.init(); + WordList.init(jListOutputArea); + SalWordList.init(); + + plotFrame = new PlotFrame(jInputAndPlot); + + nyquistThread = new NyquistThread(); + nyquistThread.start(jOutputArea, update, plotFrame, this); + + System.out.print("jDesktop size: "); + System.out.println(jDesktop.getSize().toString()); + + contentPane.setTransferHandler(new TransferHandler() { + public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { + for (DataFlavor transferFlavor : transferFlavors) { + if (transferFlavor.isFlavorJavaFileListType()) + return true; + } + return false; + } + + public boolean importData(JComponent comp, Transferable t) { + try { + Collection files = (Collection) + t.getTransferData(DataFlavor.javaFileListFlavor); + for (File file : files) { + openFile(file); + } + return true; + } catch (Exception e) { + System.out.println("Drop failed: "+e.getMessage()); + } + return false; + } + }); + // set size and location for jOutputFrame and jListOutputFrame + // now this is done in Main after making desktop visible (otherwise + // you can't get dimensions of the desktop and layout is faulty) + // tileCompletion(); + } + + + public void sendPreferenceData() { + // send Nyquist the preference values (assumes in Lisp mode) + sendInputLn(";; transferring preference data from jNyqIDE to Nyquist"); + sendInputLn("(progn"); + setBoolean("*sal-compiler-debug*", prefSalShowLisp); + callFunction(prefEnableSound ? "sound-on" : "sound-off", ""); + callFunction(prefAutoNorm ? "autonorm-on" : "autonorm-off", ""); + callFunction("sal-tracenable", tOrNil(prefSalTraceBack)); + callFunction("sal-breakenable", tOrNil(prefSalBreak)); + callFunction("xlisp-breakenable", tOrNil(prefXlispBreak)); + callFunction("xlisp-tracenable", tOrNil(prefXlispTraceBack)); + setBoolean("*gc-flag*", prefPrintGC); + callFunction("set-sound-srate", prefAudioRate); + callFunction("set-control-srate", prefControlRate); + setFontSize(Integer.parseInt(prefFontSize)); + if (prefDirectory != null && prefDirectory.length() > 0) { + changeDirectory(prefDirectory); + } + if (prefSFDirectory != null && prefSFDirectory.length() > 0) { + String dirString = escape_backslashes(prefSFDirectory); + setVariable("*default-sf-dir*", "\"" + dirString + "\""); + } else { // no preference, suggest Java temp dir. The Java temp dir + // will be used as *default-sf-dir* only if *default-sf-dir* + // was set to "", meaning previous methods to identify a temp + // directory failed to produce anything. + String tempdir = System.getProperty("java.io.tmpdir"); + if (!(tempdir.endsWith("/") || tempdir.endsWith("\\"))) + tempdir = tempdir + "/"; + // flip backslash to slash to avoid quote problems + tempdir = "\"" + tempdir.replaceAll("\\\\", "/") + "\""; + callFunction("suggest-default-sf-dir", tempdir); + } + setBoolean("*sal-secondary-prompt*", false); + sendInputLn(";; end preference data transfer"); + sendInputLn(")"); + + if (prefStartInSalMode) { + callFunction("sal", ""); + } + } + + //File | Exit action performed + public void menuButtonHandler(ActionEvent e) { + String cmd = e.getActionCommand(); + if (cmd == "New" || cmd == "New File") doFileNew(e); + else if (cmd == "Open" || cmd == "Open File") doFileOpen(e); + else if (cmd == "Save" || cmd == "Save File") doFileSave(e); + else if (cmd == "Save As...") doFileSaveAs(e); + else if (cmd == "Load" || cmd == "Load...") doFileLoad(e); + else if (cmd == "Mark") doProcessMark(e); + else if (cmd == "Preferences...") Prefs(); + else if (cmd == "Exit") { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + Quit(); + } + }); + // throw new IllegalStateException("Let the quit handler do it"); + } else if (cmd == "Find...") doEditFind(e); + else if (cmd == "Replace...") doEditReplace(e); + else if (cmd == "Previous") doEditPrevious(e); + else if (cmd == "Next") doEditNext(e); + else if (cmd == "Select Expression") doEditSelectExpression(e); + else if (cmd == "About") About(); + else if (cmd == "Manual") doHelpManual(e); + else if (cmd == "Replay") doProcessReplay(e); + else if (cmd == "Plot") doProcessPlot(e); + else if (cmd == "Tile") doWindowTile(e); + else if (cmd == "Browse") doWindowBrowse(e); + else if (cmd == "EQ") doWindowEQ(e); + else if (cmd == "EnvEdit" || cmd == "Envelope Edit") doWindowEnvelope(e); + /* BEGIN UPIC */ + else if (cmd == "UPIC Edit") doWindowUPIC(e); + /* END UPIC */ + else if (cmd == "Info") doProcessInfo(e); + else if (cmd == "Break") doProcessBreak(e); + else if (cmd == "Up") doProcessUp(e); + else if (cmd == "Cont") doProcessCont(e); + else if (cmd == "Top") doProcessTop(e); + else if (cmd == "Lisp") doProcessLisp(e); + else if (cmd == "Sal") doProcessSal(e); + else if (cmd == "Copy to Lisp") doProcessCopyToLisp(e); + // do this last so other commands starting with "F" get handled + else if (cmd.charAt(0) == 'F') doProcessFn(e); + else System.out.println("menu or button command not expected: " + cmd); + } + + public void Quit() { + System.out.println("Quit() called in MainFrame.java"); + // close prefs? + int r = JOptionPane.OK_OPTION; + if (preferencesDialog != null) { + r = JOptionPane.showConfirmDialog(this, + "Really close without closing (saving) preferences?", + "alert", JOptionPane.OK_CANCEL_OPTION); + } + if (r != JOptionPane.OK_OPTION) return; // do not quit + if (prefsHaveBeenSet) { + prefs.putBoolean("start-with-sal", prefStartInSalMode); + prefs.putBoolean("sal-show-lisp", prefSalShowLisp); + prefs.putBoolean("paren-auto-insert", prefParenAutoInsert); + prefs.putBoolean("sound-enable", prefEnableSound); + prefs.putBoolean("auto-norm", prefAutoNorm); + prefs.putBoolean("sal-traceback", prefSalTraceBack); + prefs.putBoolean("sal-break", prefSalBreak); + prefs.putBoolean("xlisp-break", prefXlispBreak); + prefs.putBoolean("xlisp-traceback", prefXlispTraceBack); + prefs.putBoolean("print-gc", prefPrintGC); + prefs.putBoolean("completion-list-full-search", prefFullSearch); + prefs.putBoolean("internal-browser", prefInternalBrowser); + prefs.putBoolean("online-manual", prefOnlineManual); + prefs.putDouble("completion-list-percent", + prefCompletionListPercent); + prefs.put("audio-rate", prefAudioRate); + prefs.put("control-rate", prefControlRate); + prefs.put("font-size", prefFontSize); + prefs.put("initial-directory", prefDirectory); + prefs.put("default-sf-directory", prefSFDirectory); + prefsHaveBeenSet = false; + } + JInternalFrame[] frames = jDesktop.getAllFrames(); + boolean flag = false; + int i; + for (i = 0; i < frames.length; i++) { + if (frames[i] instanceof NyquistFile) { + NyquistFile nyquistFile = (NyquistFile) frames[i]; + if (nyquistFile.modified) flag = true; + } + } + r = JOptionPane.OK_OPTION; + if (flag) { + r = JOptionPane.showConfirmDialog(this, + "Really close without saving?", + "alert", JOptionPane.OK_CANCEL_OPTION); + } + if (r != JOptionPane.OK_OPTION) return; // do not quit + if (workspaceLoaded) { + r = JOptionPane.showConfirmDialog(this, + "Save workspace to current directory before exiting?", + "alert", JOptionPane.YES_NO_CANCEL_OPTION); + if (r == JOptionPane.YES_OPTION) { + workspaceSaved = false; // interface with NyquistThread + callFunction("save-workspace", ""); + i = 0; + while (!workspaceSaved && i < 10000) { // allow 10s + try { Thread.sleep(200); } + catch (InterruptedException ie) { } + i += 200; + } + if (!workspaceSaved) { + r = JOptionPane.showConfirmDialog(this, + "Timed out waiting for workspace save.\n" + + "Your workspace data may not be saved.\n" + + "Exit anyway?", + "alert", JOptionPane.OK_CANCEL_OPTION); + } + } + if (r == JOptionPane.CANCEL_OPTION) return; // do not quit + } + System.out.println("Sending (exit) to Nyquist..."); + // try to shut down Nyquist before it is orphaned + // Sal need special syntax to exit the Nyquist process: + if (jScrollPane.isSal) sendInputLn("exit nyquist"); + else callFunction("exit", ""); + try { + Thread.sleep(200); // does it help Nyquist's exit to stall? + } catch (InterruptedException ie) { + } + System.out.println("Exiting from NyquistIDE"); + System.exit(0); + } + + + public void prepareNewNyquistFile(final NyquistFile file) { + jDesktop.add(file); + jDesktop.getDesktopManager().activateFrame(file); + jDesktop.setSelectedFrame(file); + file.addInternalFrameListener( + new InternalFrameListener() { + public void internalFrameClosing(InternalFrameEvent e) { + //System.out.println("FrameClosing"); + int r = JOptionPane.OK_OPTION; + if (file.modified) { + r = JOptionPane.showConfirmDialog(file, + "Really close without saving?", + "alert", JOptionPane.OK_CANCEL_OPTION); + } + if (r == JOptionPane.OK_OPTION) { + file.dispose(); + } + } + public void internalFrameOpened(InternalFrameEvent e) { + } + public void internalFrameClosed(InternalFrameEvent e) { + //System.out.println("FrameClosed"); + } + public void internalFrameIconified(InternalFrameEvent e) { + } + public void internalFrameDeiconified(InternalFrameEvent e) { + } + public void internalFrameActivated(InternalFrameEvent e) { + } + public void internalFrameDeactivated(InternalFrameEvent e) { + } + } + ); + } + + + public void doFileNew(ActionEvent e) { + + final NyquistFile file = + new NyquistFile(this, Integer.parseInt(prefFontSize)); + prepareNewNyquistFile(file); + } + + public String fileDirectory(File file) { + String path = file.getAbsolutePath(); + String name = file.getName(); + return path.substring(0, path.length() - name.length()); + } + + + //File | Exit action performed + public void doFileOpen(ActionEvent e) { + JFileChooser chooser = new JFileChooser(); + LispFileFilter lispFilter = new LispFileFilter(); + SalFileFilter salFilter = new SalFileFilter(); + // last one seems to be the default setting for user, so set according + // to current mode + if (jScrollPane.isSal) { + chooser.setFileFilter(lispFilter); + chooser.addChoosableFileFilter(salFilter); + } else { + chooser.setFileFilter(salFilter); + chooser.addChoosableFileFilter(lispFilter); + } + // note if current directory setting fails on some platform, + // consider this code using getCanonicalPath(): + // File f = new File(new File(".").getCanonicalPath()); + File curdir = new File(currentDir); + chooser.setCurrentDirectory(curdir); + int returnVal = chooser.showOpenDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + System.out.println("You chose to open this file: " + + chooser.getSelectedFile().getAbsoluteFile()); + openFile(chooser.getSelectedFile()); + } + } + + private void openFile(File fileToOpen) { + // see if file is already open + JInternalFrame[] frames = jDesktop.getAllFrames(); + int i; + for (i = 0; i < frames.length; i++) { + if (frames[i] instanceof NyquistFile) { + NyquistFile file = (NyquistFile) frames[i]; + + if (file.getFile() != null && + file.getFile().getAbsolutePath().equals( + fileToOpen.getAbsolutePath())) { + jDesktop.setSelectedFrame(file); + try { + file.setSelected(true); + } + catch(PropertyVetoException ve) { + //System.out.println("setSelected was vetoed"); + } + + JInternalFrame jInternalFrame = + jDesktop.getSelectedFrame(); + if (jInternalFrame instanceof NyquistFile) { + NyquistFile nf = (NyquistFile) jInternalFrame; + //System.out.println("selected is " + + // nf.getAbsolutePath()); + } else { + //System.out.println("selected not a NyquistFile"); + } + return; + } + } + } + // Didn't find it. Open it in a new frame. + final NyquistFile file = + new NyquistFile(fileToOpen, this, Integer.parseInt(prefFontSize)); + changeDirectory(fileDirectory(fileToOpen)); + prepareNewNyquistFile(file); + } + + public void doFileSave(ActionEvent e) { + if (jDesktop.getSelectedFrame() instanceof NyquistFile) { + NyquistFile file = (NyquistFile)jDesktop.getSelectedFrame(); + if (file.save(currentDir)) { + changeDirectory(fileDirectory(file.getFile())); + } + } + } + + public void doFileSaveAs(ActionEvent e) { + if (jDesktop.getSelectedFrame() instanceof NyquistFile) { + NyquistFile file = (NyquistFile)jDesktop.getSelectedFrame(); + if (file.saveAs(currentDir)) { + changeDirectory(fileDirectory(file.getFile())); + } + } + } + + public void doFileLoad(ActionEvent e) { + JInternalFrame frame = jDesktop.getSelectedFrame(); + if (frame instanceof NyquistFile) { + NyquistFile file = (NyquistFile) frame; + if (file.save(currentDir)) { + loadFile(file.getFile()); + } + } + } + + //Edit | Find action performed + public void doEditFind(ActionEvent e) { + JInternalFrame frame = jDesktop.getSelectedFrame(); + if (frame instanceof NyquistFile) { + NyquistFile file = (NyquistFile) frame; + FindDialog findDialog = new FindDialog(file, this); + } + } + + //Edit | Replace action performed + public void doEditReplace(ActionEvent e) { + JInternalFrame frame = jDesktop.getSelectedFrame(); + if (frame instanceof NyquistFile) { + NyquistFile file = (NyquistFile) frame; + ReplaceDialog replaceDialog = new ReplaceDialog(file, this); + } + } + + public void filterCRLF(StringBuffer buf) + { + //int i = buf.toString().indexOf("\r\n"); // note: buf.indexOf() doesn't work on Mac + //while (i >= 0) { + // buf.replace(i, i + 2, "\n"); + // i = buf.toString().indexOf("\r\n", i); + //} + buf.replace(0, buf.length(), buf.toString().replaceAll("\r\n", "\n")); + } + + public String trimNewline(String s) { + int len = s.length(); + while (len > 0 && + (s.charAt(len - 1) == '\n' || s.charAt(len - 1) == '\r')) { + len = len - 1; + } + return s.substring(0, len); + } + + //Edit | Previous action performed + public void doEditPrevious(ActionEvent e) { + inputStringsCursor = inputStringsCursor - 1; + if (inputStringsCursor < 0) inputStringsCursor = inputStringsLen - 1; + String text = inputStrings[inputStringsCursor]; + if (text != null) { + // remove the newline at the end + jScrollPane.pane.setText(trimNewline(text)); + } + } + + //Edit | Next action performed + public void doEditNext(ActionEvent e) { + inputStringsCursor = inputStringsCursor + 1; + if (inputStringsCursor >= inputStringsLen) inputStringsCursor = 0; + String text = inputStrings[inputStringsCursor]; + if (text != null) { + jScrollPane.pane.setText(trimNewline(text)); + } + } + + //Edit | Select Expression + public void doEditSelectExpression(ActionEvent e) { + JInternalFrame frame = jDesktop.getSelectedFrame(); + if (frame instanceof NyquistFile) { + NyquistFile file = (NyquistFile) frame; + file.selectExpression(); + } + } + + //Help | About action performed + public void About() { + MainFrame_AboutBox dlg = new MainFrame_AboutBox(this); + Dimension dlgSize = dlg.getPreferredSize(); + Dimension frmSize = getSize(); + Point loc = getLocation(); + dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y); + dlg.setModal(true); + dlg.setVisible(true); + + Graphics g = jFrame.getContentPane().getGraphics(); + g.setColor(Color.cyan); + g.fillRect(50, 50, 100, 100); + + } + + public String findManualURL(String ext) { + String url = ""; + try { + url = homeDir.getCanonicalPath(); + } catch (Exception e) { + System.out.println("findManualURL exception: " + e); + } + String osName = System.getProperty("os.name"); + if (osName.startsWith("Mac OS")) { + // from ./NyquistIDE.app/Contents/Resources/Java to . + // note: I tried this using homeDir.getParentFile(), but + // it always returns null, so I'm string parsing instead + int i; + for (i = 0; i < 4; i++) { + int pos = url.lastIndexOf('/'); + if (pos >= 0) { + url = url.substring(0, pos); + } + System.out.println(url); + } + url += "/nyquist"; + } else if (osName.startsWith("Windows")) { + // file://C:/ does not work, file:///C:/ does work + url = "/" + url; + } + url = "file://" + url + "/doc/" + ext; + return url; + } + + public void doHelpManual(ActionEvent e) { + if (prefInternalBrowser) { + miniBrowser.setVisible(true); + miniBrowser.setPage(findManualURL("title.html")); + } else { + // separate browser gets to use frames (with index) by + // opening home.html + String url = findManualURL("home.html"); + System.out.println("Try to open: " + url); + BareBonesBrowserLaunch.openURL(url); + } + } + + public void doProcessReplay(ActionEvent e) + { + callFunction("r", ""); + } + + public void disconnectEnv() { // no more envelopeFrame, so kill pointer + envelopeEditor = null; + } + + public void disconnectEq() { // no more equalizer panel, so kill pointer + eqEditor = null; + } + + /* BEGIN UPIC */ + public void disconnectUPIC() { // no more upicFrame, so kill pointer + upicEditor = null; + } + /* END UPIC */ + + public boolean workspaceWarning(String description) { // return true if OK to proceed + if (workspaceLoaded) return true; + Object[] options = { "CANCEL", "LOAD", "SKIP" }; + int i = JOptionPane.showOptionDialog(this, + "No workspace has been loaded. If you save " + description + + ",\nany existing workspace will be overwritten without\n" + + "further notice. You should probably click CANCEL,\n" + + "open workspace.lsp, load it into Nyquist, and then\n" + + "revisit this editor.\n\n" + + "Click SKIP to proceed at your own risk.\n" + + "Click LOAD to load workspace.lsp from the current directory.\n" + + "Click CANCEL to resume without opening a new editor window.\n\n" + + "(If you have no workspace to load, select SKIP.)\n", + "Warning", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, + null, options, options[0]); + System.out.println("dialog returns " + i); + if (i == 2) { // skip (proceed) option + workspaceLoaded = true; + } else if (i == 1) { // load workspace + callFunction("load", "\"workspace\""); + i = 0; + while (!workspaceLoaded && i < 10000) { // alow 10s + try { Thread.sleep(200); } + catch (InterruptedException ie) { } + i += 200; + } + if (!workspaceLoaded) { + JOptionPane.showMessageDialog(this, + "Timed out waiting for workspace load.\n" + + "Maybe it does not exist in this directory?", + "alert", JOptionPane.INFORMATION_MESSAGE); + } + } + // otherwise OK_OPTION selected, return false meaning do not proceed + return workspaceLoaded; + } + + public void doWindowEnvelope(ActionEvent e) + { + // only one editor instance allowed + if (envelopeEditor != null) { + JOptionPane.showMessageDialog(this, + "Envelope editor is already open.", + "alert", JOptionPane.INFORMATION_MESSAGE); + return; + } + // open an envelope window + if (!workspaceWarning("envelopes")) return; + final EnvelopeFrame envelopeFrame = + new EnvelopeFrame(this, jScrollPane.pane); + final MainFrame mainFrame = this; + envelopeEditor = envelopeFrame; + envelopeFrame.validate(); + jDesktop.add(envelopeFrame); + jDesktop.getDesktopManager().activateFrame(envelopeFrame); + jDesktop.setSelectedFrame(envelopeFrame); + } + + /* BEGIN UPIC */ + public void doWindowUPIC(ActionEvent e) + { + // only one editor instance allowed + if (upicEditor != null) { + JOptionPane.showMessageDialog(this, + "UPIC editor is already open.", + "alert", JOptionPane.INFORMATION_MESSAGE); + return; + } + // open a UPIC window + final UPICFrame upicFrame = + new UPICFrame(this, jScrollPane.pane); + upicEditor = upicFrame; + upicFrame.validate(); + jDesktop.add(upicFrame); + jDesktop.getDesktopManager().activateFrame(upicFrame); + jDesktop.setSelectedFrame(upicFrame); + } + /* END UPIC */ + + public void doWindowEQ(ActionEvent e) { + /* Code added by Rivera Create a slider object that is the graphic equalizer + * Then add that slider object to the desktop, It will display + * directly to the right of the output, given the outputs frame + * width of 500 + */ + if (eqEditor != null) { + JOptionPane.showMessageDialog(this, + "Equalizer editor is already open.", + "alert", JOptionPane.INFORMATION_MESSAGE); + return; + } + if (!workspaceWarning("equalizers")) return; + final Jslide jslide = new Jslide(this); + eqEditor = jslide; + final MainFrame mainFrame = this; + final JInternalFrame jEq = new JInternalFrame("Equalizer", true, true); + jEq.setSize(new Dimension(350, 300)); + jEq.setLocation(500, 0); + jEq.setVisible(true); + + jEq.getContentPane().add(jslide.getGraphEq()); + jDesktop.add(jEq); + + jEq.addInternalFrameListener( + new InternalFrameListener() { + public void internalFrameClosing(InternalFrameEvent e) { + //System.out.println("FrameClosing"); + int r = JOptionPane.OK_OPTION; + if (jslide.modified) { + r = JOptionPane.showConfirmDialog(jEq, + "Really close without saving?", + "alert", JOptionPane.OK_CANCEL_OPTION); + } + if (r == JOptionPane.OK_OPTION) { + jEq.dispose(); + } + } + public void internalFrameOpened(InternalFrameEvent e) { + } + public void internalFrameClosed(InternalFrameEvent e) { + mainFrame.disconnectEq(); + //System.out.println("FrameClosed"); + } + public void internalFrameIconified(InternalFrameEvent e) { + } + public void internalFrameDeiconified(InternalFrameEvent e) { + } + public void internalFrameActivated(InternalFrameEvent e) { + } + public void internalFrameDeactivated(InternalFrameEvent e) { + } + } + ); + + System.out.print("jOutputFrame size: "); + System.out.println(jOutputFrame.getSize().toString()); + System.out.print("Available space in jDesktop: "); + System.out.println(jDesktop.getInsets().toString()); + System.out.print("jDesktop size: "); + System.out.println(jDesktop.getSize().toString()); + } + + public void doProcessInfo(ActionEvent e) + { + callFunction("info", ""); + } + + public void doProcessBreak(ActionEvent e) + { + sendInput("\02\n"); + } + + public void doProcessCont(ActionEvent e) + { + callFunction("continue", ""); + } + + public void doProcessTop(ActionEvent e) + { + // don't use callFunction because isSal might be wrong + // using (top) will work in both Lisp and Sal modes + sendInputLn("(top)"); + } + + public void doProcessSal(ActionEvent e) { + callFunction("sal", ""); + } + + public void doProcessLisp(ActionEvent e) { + sendInputLn("exit"); + } + + public void doProcessUp(ActionEvent e) + { + callFunction("up", ""); + } + + public void doProcessMark(ActionEvent e) + { + sendInput(Character.toString('\001'), true); + } + + /* this is an old test function to simulate a slider change... + public void doProcessTest(ActionEvent e) + { + sendInput(Character.toString('\016'), true); // begin message + sendInput("S", true); // command is "slider change" + test_value += 1.0; + sendInput("5 ", true); // which slider + sendInput(Float.toString(test_value), true); // new value + sendInput(Character.toString('\021'), true); // end message + } + */ + + public void doProcessFn(ActionEvent e) + { + callFunction(e.getActionCommand(), ""); + } + + // Plot command + public void doProcessPlot(ActionEvent e) { + NyqPlot.plot("points.dat", plotFrame); + } + + + // Process | Copy to Lisp Command + public void doProcessCopyToLisp(ActionEvent e) { + JInternalFrame frame = jDesktop.getSelectedFrame(); + if (frame instanceof NyquistFile) { + NyquistFile file = (NyquistFile) frame; + String selection = file.currentSelection(); + jScrollPane.pane.setText(selection); + sendCommandToNyquist(); + } + } + + // adjust completion window and output windows only + public void tileCompletion() { + // place output frame at left, full height + Dimension dim = jDesktop.getSize(); + // something goes wrong at initialization, so hack in a reasonable value + if (dim.width == 0 || dim.height == 0) { + System.out.println("desktop size is zero, guessing 800 by 612"); + dim = new Dimension(800, 612); + } else { + System.out.println("desktop size is actually " + dim); + } + //System.out.print("jDesktop size: "); + //System.out.println(dim.toString()); + int loc = (int) (dim.height * prefCompletionListPercent * 0.01); + jOutputFrame.setLocation(0, loc); + jListOutputFrame.setLocation(0, 0); + // make output_width based on width of "desktop", which is the + // area that contains the output frame and all the file (editor) + // frames. + int output_width = 530; + if (dim.width < 600) output_width = dim.width - 100; + if (output_width < 100) output_width = dim.width / 2; + jOutputFrame.setSize(output_width, dim.height - loc); + jListOutputFrame.setSize(output_width, loc); + System.out.println("jListOutputFrame.setSize " + output_width + " " + loc + " " + dim); + } + + // Window Tile command -- organize window placement + public void doWindowTile(ActionEvent e) { + tileCompletion(); + // place output frame at left, full height + Dimension dim = jDesktop.getSize(); + System.out.println("jDesktop.getSize(): " + dim); + int output_width = 530; // for now this is constant, see tileCompletion + + // organize windows + // if there are 3 or less or width is less than 1200, + // use one column + int cols = 1; + JInternalFrame[] frames = jDesktop.getAllFrames(); + int num_frames = frames.length - 2; // don't count jOutput Frame or + // completion frame + if (!miniBrowser.isVisible()) num_frames--; // don't count browser frame + if (num_frames <= 0) return; // nothing to tile + if (num_frames > 3 && dim.width >= 1200) { + cols = 2; + } + int frames_per_col = (num_frames + cols - 1) / cols; + int frame_spacing = dim.height / frames_per_col; + // allow overlap if necessary + int frame_height = Math.max(frame_spacing, 100); + int frame_width = (dim.width - output_width) / cols; + int i; + int col = 0; + int row = 0; + for (i = 0; i < frames.length; i++) { + if (frames[i] != jOutputFrame && frames[i] != jListOutputFrame && + frames[i].isVisible()) { + //NyquistFile nyquistFile = (NyquistFile) frames[i]; + JInternalFrame nyquistFile = (JInternalFrame) frames[i]; + nyquistFile.setLocation(output_width + col * frame_width, + row * frame_spacing); + nyquistFile.setSize(frame_width, frame_height); + row = row + 1; + if (row >= frames_per_col) { + row = 0; + col = col + 1; + } + } + } + } + + // Window Browse command -- create a browse/demo window + public void doWindowBrowse(ActionEvent e) { + // place output frame at left, full height + loadBrowserFrame(); + } + + //Overridden so we can exit (if confirmed) when window is closed + protected void processWindowEvent(WindowEvent e) { + // super.processWindowEvent(e); + if (e.getID() == WindowEvent.WINDOW_CLOSING) { + Quit(); + } + } + + // convert backslash to escaped backslash in path for nyquist + public String escape_backslashes(String path) { + String escaped = ""; + int i = 0; + while (i < path.length()) { + char c = path.charAt(i); + escaped = escaped + c; + if (c == '\\') escaped = escaped + c; + i++; + } + return escaped; + } + + // set current directory + public void changeDirectory(String dir) { + System.out.println("changeDirectory: currentDir " + currentDir + + " to " + dir); + if (!currentDir.equals(dir)) { + currentDir = dir; + String escapedDir = escape_backslashes(dir); + callFunction("setdir", "\"" + escapedDir + "\""); + } + } + + // tell nyquist to load a file + public void loadFile(File file) { + changeDirectory(fileDirectory(file)); + String path = escape_backslashes(file.getAbsolutePath()); + // if we're in lisp, pop out of any debug/break prompts before loading + // don't do this is we're in sal because it will exit Sal - not good + if (jScrollPane.isSal) { + // callFunction would also work, but I prefer to use the "native" + // Sal load command + sendInputLn("load \"" + path + "\""); + } else { + callFunction("top", ""); + callFunction("sal-load", "\"" + path + "\""); + } + } + + + // send data to Nyquist process after fixing indentation and appending + // a newline + public void sendInputLn(String text) { + // fix text with indentation if there are multiple lines + String newlines = (jScrollPane.isSal ? "\n\n" : "\n"); + sendInput( + text.replaceAll("\n", (jScrollPane.isSal ? "\n " : "\n ")) + + newlines, false); + } + + public void setSalMode(final boolean sal) { + jScrollPane.isSal = sal; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + String name = (sal ? "Lisp" : "Sal"); + salLispButton.setText(name); + salLispButton.setActionCommand(name); + salLispButton.setToolTipText(sal ? "Switch to Lisp Mode" : + "Switch to SAL Mode"); + } + }); + } + + + // send data to Nyquist process + public void sendInput(String text) { + sendInput(text, false); + } + + public void sendInput(String text, boolean hide) { + SwingUtilities.invokeLater(update); + System.out.println("sendInput: " + text + "(" + hide + ")"); + nyquistThread.sendInput(text, hide); + } + + public void sendCommandToNyquist() { + StringBuffer text = new StringBuffer(jScrollPane.pane.getText()); + inputStrings[inputStringsX] = new String(text); + // for some reason, text sometimes ends up + // with a CR LF at end. Make sure it's gone + // before we output to Nyquist + filterCRLF(text); + // System.out.println("text |" + text + "| pos " + pos); + // SAL wants newline before multiline input to make input prettier + //if (jScrollPane.isSal && + // inputStrings[inputStringsX].indexOf("\n") >= 0) + // sendInput("\n"); + + sendInputLn(inputStrings[inputStringsX]); + // System.out.println("text sent to Nyquist"); + inputStringsX++; + if (inputStringsX >= inputStringsLen) { + inputStringsX = 0; + } + inputStringsCursor = inputStringsX; + jScrollPane.pane.setText(""); + } + + public void ScrollToEnd() { + JScrollBar scroll = jOutputPane.getVerticalScrollBar(); + scroll.setValue(scroll.getMaximum() - scroll.getVisibleAmount()); + } + + public void loadBrowserFrame() { + Browser frame = new Browser(this, nyquistThread); + + // Validate frames that have preset sizes + // Pack frames that have useful preferred size info, e.g. from their layout + if (packFrame) { + frame.pack(); + } else { + frame.validate(); + } + jDesktop.add(frame); + } + + public void loadEnvData(String data) { + if (envelopeEditor != null) { + envelopeEditor.loadEnvData(data); + } + /* BEGIN UPIC */ + /* if (upicEditor != null) { + upicEditor.loadEnvData(data); + } */ + /* END UPIC */ + } + + public void loadEqData(String data) { + if (eqEditor != null) { + eqEditor.loadEqData(data); + } + } + + public void setFontSize(int s) { + JInternalFrame[] frames = jDesktop.getAllFrames(); + int i; + for (i = 0; i < frames.length; i++) { + if (frames[i] instanceof NyquistFile) { + NyquistFile nyquistFile = (NyquistFile) frames[i]; + CodePane pane = nyquistFile.filePane; + pane.setFontSize(s); + } + } + jScrollPane.setFontSize(s); + jOutputArea.setFont(new Font("Courier", Font.PLAIN, s)); + } + +} + diff --git a/jnyqide/MainFrame_AboutBox.java b/jnyqide/MainFrame_AboutBox.java new file mode 100644 index 0000000..6f8d89a --- /dev/null +++ b/jnyqide/MainFrame_AboutBox.java @@ -0,0 +1,98 @@ +package jnyqide; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.border.*; + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +public class MainFrame_AboutBox extends JDialog implements ActionListener { + + JPanel panel1 = new JPanel(); + JPanel panel2 = new JPanel(); + JPanel insetsPanel1 = new JPanel(); + JPanel insetsPanel2 = new JPanel(); + JPanel insetsPanel3 = new JPanel(); + JButton button1 = new JButton(); + JLabel imageLabel = new JLabel(); + JLabel label1 = new JLabel(); + JLabel label2 = new JLabel(); + JLabel label3 = new JLabel(); + JLabel label4 = new JLabel(); + BorderLayout borderLayout1 = new BorderLayout(); + BorderLayout borderLayout2 = new BorderLayout(); + FlowLayout flowLayout1 = new FlowLayout(); + GridLayout gridLayout1 = new GridLayout(); + String product = "jNyqIDE - Nyquist Integrated Development Environment"; + String version = "Version 2.0"; + String copyright = "Copyright (c) 2002-2006"; + String comments = "Jesse Clark, David Howard, David Mowatt, David Deangelis, and Roger B. Dannenberg"; + public MainFrame_AboutBox(Frame parent) { + super(parent); + enableEvents(AWTEvent.WINDOW_EVENT_MASK); + try { + jbInit(); + } + catch(Exception e) { + e.printStackTrace(); + } + pack(); + } + //Component initialization + private void jbInit() throws Exception { + //imageLabel.setIcon(new ImageIcon(MainFrame_AboutBox.class.getResource("[Your Image]"))); + this.setTitle("About"); + setResizable(false); + panel1.setLayout(borderLayout1); + panel2.setLayout(borderLayout2); + insetsPanel1.setLayout(flowLayout1); + insetsPanel2.setLayout(flowLayout1); + insetsPanel2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + gridLayout1.setRows(4); + gridLayout1.setColumns(1); + label1.setText(product); + label2.setText(version); + label3.setText(copyright); + label4.setText(comments); + insetsPanel3.setLayout(gridLayout1); + insetsPanel3.setBorder(BorderFactory.createEmptyBorder(10, 60, 10, 10)); + button1.setText("Ok"); + button1.addActionListener(this); + insetsPanel2.add(imageLabel, null); + panel2.add(insetsPanel2, BorderLayout.WEST); + this.getContentPane().add(panel1, null); + insetsPanel3.add(label1, null); + insetsPanel3.add(label2, null); + insetsPanel3.add(label3, null); + insetsPanel3.add(label4, null); + panel2.add(insetsPanel3, BorderLayout.CENTER); + insetsPanel1.add(button1, null); + panel1.add(insetsPanel1, BorderLayout.SOUTH); + panel1.add(panel2, BorderLayout.NORTH); + } + //Overridden so we can exit when window is closed + protected void processWindowEvent(WindowEvent e) { + if (e.getID() == WindowEvent.WINDOW_CLOSING) { + cancel(); + } + super.processWindowEvent(e); + } + //Close the dialog + void cancel() { + dispose(); + } + //Close the dialog on a button event + public void actionPerformed(ActionEvent e) { + if (e.getSource() == button1) { + cancel(); + } + } +} diff --git a/jnyqide/MiniBrowser.java b/jnyqide/MiniBrowser.java new file mode 100644 index 0000000..69e7d9f --- /dev/null +++ b/jnyqide/MiniBrowser.java @@ -0,0 +1,66 @@ +package jnyqide; + +import java.awt.*; +import javax.swing.*; +import javax.swing.text.html.*; +import javax.swing.event.*; +import java.net.URL; + +public class MiniBrowser extends JInternalFrame { + JEditorPane urlPane; + + class Hyperactive implements HyperlinkListener { + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + JEditorPane pane = (JEditorPane) e.getSource(); + if (e instanceof HTMLFrameHyperlinkEvent) { + HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e; + //System.out.println("Target = " + evt.getTarget()); + HTMLDocument doc = (HTMLDocument) pane.getDocument(); + doc.processHTMLFrameHyperlinkEvent(evt); + } else { + try { + urlPane.setPage(e.getURL()); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + } + } + + + public MiniBrowser(String title) { + super(title); + urlPane = new JEditorPane(); + urlPane.setEditable(false); + urlPane.addHyperlinkListener(new Hyperactive()); + JScrollPane sp = new JScrollPane(urlPane); + sp.setHorizontalScrollBarPolicy( + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + sp.setVerticalScrollBarPolicy( + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + setVisible(false); + setClosable(true); + getContentPane().add(sp); + setResizable(true); + setPreferredSize(new Dimension(400, 400)); + setLocation(50, 100); + setSize(700, 400); + setDefaultCloseOperation(HIDE_ON_CLOSE); + } + + public void setPage(String url) { + try { + // hard-wired URL for testing only!: + // System.out.println("setPage actual input: " + url); + // url = "file://doc/nyquist/doc/part8.html"; + URL u = new URL(url); + System.out.println("MiniBrowser.setPage: " + u); + urlPane.setPage(u); + } catch (Exception ex) { + System.out.println( + "Exception from urlPane.setPage: " + ex); + } + } +} diff --git a/jnyqide/NotFoundDialog.java b/jnyqide/NotFoundDialog.java new file mode 100644 index 0000000..12a61e0 --- /dev/null +++ b/jnyqide/NotFoundDialog.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1997 John Jensen. All rights reserved. + * + * This software is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE, + * provided the following condition is met. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that any copy or derivative of this software or documentation + * retaining the name "John Jensen" also retains this condition and the + * following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * CopyrightVersion 1.0 + */ + +package jnyqide; + +import java.util.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +class NotFoundDialog extends Dialog implements WindowListener, ActionListener +{ + private Button okButton; + + public NotFoundDialog(MainFrame mainFrame, Properties strings, + Point loc) + { + super(mainFrame, "", true); + + Panel north = new Panel(); + north.add(new Label("Not Found")); + add("North", north); + + okButton = new Button("Ok"); + okButton.addActionListener(this); + Panel south = new Panel(); + south.add(okButton); + add("South", south); + + Dimension size = new Dimension(200,110); + setSize(size); + setLocation(loc); + // setLocation(textFrame.getPlace(size)); + + addWindowListener(this); + } + + public void windowDeiconified(WindowEvent event) {} + public void windowIconified(WindowEvent event) {} + public void windowActivated(WindowEvent event) {} + public void windowDeactivated(WindowEvent event) {} + public void windowOpened(WindowEvent event) {} + public void windowClosed(WindowEvent event) {} + public void windowClosing(WindowEvent event) + { + dispose(); + } + + public void actionPerformed(ActionEvent evt) + { + if (evt.getSource() == okButton) + dispose(); + } + +} diff --git a/jnyqide/NyqPlot.java b/jnyqide/NyqPlot.java new file mode 100644 index 0000000..4d010c7 --- /dev/null +++ b/jnyqide/NyqPlot.java @@ -0,0 +1,131 @@ +package jnyqide; + +import java.io.*; +import java.util.*; +import java.awt.*; +import javax.swing.*; + +// Note: Modifications to move plots from a JInternalFrame to a fixed JPanel +// are marked with //JPANEL: + +public class NyqPlot +{ + /** + * main method takes 1 parameter from command line + * @param args name of input file + */ + public static void plot(String plotFilename, PlotFrame plotFrame) { + if (plotFrame == null) { + System.out.println("null plotFrame in plot"); + return; + } + BufferedReader input = null; + + try { + input = new BufferedReader(new FileReader(plotFilename)); + } catch( FileNotFoundException fnfx ) { + System.out.println("File not found: " + plotFilename); + return; + } // End try/catch block + + + ///////////////////////////////////////////////// + // Read File + ///////////////////////////////////////////////// + + Vector dataPoints = new Vector(); + String line; + StringTokenizer st; + boolean firsttime = true; + + Double num1 = new Double(0); + + double innum1 = 0; + double innum2 = 0; + + double minx = 0; + double miny = 0; + double maxx = 0; + double maxy = 0; + + System.out.println("plot reading file"); + try { + while ((line = input.readLine()) != null) { + //Read another line from the file + st = new StringTokenizer(line); + if (st.countTokens() != 2) { + System.out.println("input must have two numbers per line"); + return; + } + + String word1 = st.nextToken(); + String word2 = st.nextToken(); + + innum1 = num1.valueOf(word1).doubleValue(); + innum2 = num1.valueOf(word2).doubleValue(); + + if (firsttime == true) { + // initializes mins and maxes to real values + minx = innum1; + maxx = innum1; + miny = innum2; + maxy = innum2; + firsttime = false; + } + + if (innum1 < minx){minx = innum1;} + if (innum1 > maxx){maxx = innum1;} + if (innum2 < miny){miny = innum2;} + if (innum2 > maxy){maxy = innum2;} + + Pair currentPair = new Pair(innum1, innum2); + dataPoints.add(currentPair); + } //while ((line = input.readLine()) != null) + + input.close(); //Close the file + + } catch( IOException iox ) { + System.out.println(iox ); + } // End try/catch block + + // printData(dataPoints); + + //System.out.println("Min X = " + minx + " Max X = " + maxx); + //System.out.println("Min Y = " + miny + " Max Y = " + maxy); + + // Plotting stuff +/* + Color [] colors = new Color [4]; + + colors[0] = Color.red; + colors[1] = Color.yellow; + colors[2] = Color.green; + colors[3] = Color.blue; + + + double [][][] graphstuff = new double [1][2][dataPoints.size()]; + + for(int i = 0; i < dataPoints.size(); i++){ + graphstuff[0][0][i] = ((Pair) dataPoints.get(i)).getNum1(); + graphstuff[0][1][i] = ((Pair) dataPoints.get(i)).getNum2(); + } + + + GRAph myGraph = new GRAph(colors); + myGraph.graphit(minx,maxx,miny,maxy,graphstuff); +*/ + + plotFrame.PlotData(dataPoints, minx, miny, maxx, maxy); + //JPANEL: JInternalFrame plotFrame = new PlotFrame(jDesktop, dataPoints, minx, miny, maxx, maxy); + //JPANEL: JPanel plotFrame = new PlotFrame(jDesktop, dataPoints, minx, miny, maxx, maxy); + //JPANEL: plotFrame.setVisible(true); + } + + public static void printData(Vector input){ + + for(int i = 0; i < input.size(); i++){ + System.out.println( ((Pair) input.get(i)).getTime() + " " + + ((Pair) input.get(i)).getValue()); + } + } +} diff --git a/jnyqide/NyquistFile.java b/jnyqide/NyquistFile.java new file mode 100644 index 0000000..a7c1ec6 --- /dev/null +++ b/jnyqide/NyquistFile.java @@ -0,0 +1,590 @@ +package jnyqide; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import javax.swing.event.*; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.undo.*; +import jnyqide.*; + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + + +// BWP -- added "implements ActionListener" +public class NyquistFile extends JInternalFrame + implements ActionListener, ComponentListener { + DefaultStyledDocument doc; + JTextPane pane; + public final CodePane filePane; + JLabel statusBar = new JLabel(); + UndoManager undo; + File file; + public boolean modified = false; + NyquistFile thisFile; + MainFrame myParent; //BWP + + String lastFound = ""; //BWP -- BUG, shouldn't these be global? + //String revertTo = ""; //BWP + + public File getFile() { + return file; + } + + + // BWP: Constructors now take a MainFrame object to associate + // the document window with the parent window for Find + // and Find/Replace operations + public NyquistFile(MainFrame parent, int fontSize) { // BWP + this(null, parent, fontSize); // BWP + modified = true; + setTitle(getTitle()+"*"); + } + + + public void readFile(File file) { + if (file != null) { + try { + FileInputStream openFileStream = new FileInputStream(file); + + byte b[] = new byte[1000]; // read 1K at a time + int pos = 0; + //System.out.println("starting to read file"); + doc.remove(0, doc.getLength()); // clear the current content + while (openFileStream.available() > 0) { + int count = openFileStream.read(b); + doc.insertString(pos, new String(b, 0, count), + TextColor.attrNormal); + pos += count; + } + } + catch (Exception e2) { System.out.println(e2); } + } + } + + + public void determineType() { + String name = file.getName(); + filePane.isSal = name.toLowerCase().endsWith(".sal"); + } + + + public NyquistFile(File f, MainFrame parent, int fontSize) { + super(); + + setTitle(f != null ? f.getName() : "Untitled"); + file = f; + thisFile = this; + + myParent = parent; + + int keyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + // Menu Bar for top of Document Windows + JMenuBar myMenuBar = new JMenuBar(); + + // File Menu + JMenu myFileMenu = new JMenu("File"); + + JMenuItem myLoad = new JMenuItem("Load"); + myLoad.setActionCommand("load"); + myLoad.addActionListener(this); + myLoad.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_K, keyMask)); + + JMenuItem mySave = new JMenuItem("Save"); + mySave.setActionCommand("save"); + mySave.addActionListener(this); + mySave.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, keyMask)); + + JMenuItem mySaveAs = new JMenuItem("Save As..."); + mySaveAs.setActionCommand("save as"); + mySaveAs.addActionListener(this); + mySaveAs.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, + keyMask | java.awt.event.InputEvent.SHIFT_MASK)); + + JMenuItem myRevert = new JMenuItem("Revert"); + myRevert.setActionCommand("revert"); + myRevert.addActionListener(this); + + JMenuItem myClose = new JMenuItem("Close"); + myClose.setActionCommand("close"); + myClose.addActionListener(this); + myClose.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, keyMask)); + + myFileMenu.add(myLoad); + myFileMenu.add(mySave); + myFileMenu.add(mySaveAs); + myFileMenu.add(myRevert); + myFileMenu.add(myClose); + + // Edit Menu + JMenu myEditMenu = new JMenu("Edit"); + + JMenuItem myCut = new JMenuItem("Cut"); + myCut.setActionCommand("cut"); + myCut.addActionListener(this); + myCut.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, keyMask)); + + JMenuItem myCopy = new JMenuItem("Copy"); + myCopy.setActionCommand("copy"); + myCopy.addActionListener(this); + myCopy.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, keyMask)); + + JMenuItem myPaste = new JMenuItem("Paste"); + myPaste.setActionCommand("paste"); + myPaste.addActionListener(this); + myPaste.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_V, keyMask)); + + JMenuItem myFind = new JMenuItem("Find..."); + myFind.setActionCommand("find"); + myFind.addActionListener(this); + myFind.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, keyMask)); + + JMenuItem myNext = new JMenuItem("Find Next"); + myNext.setActionCommand("next"); + myNext.addActionListener(this); + myNext.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, keyMask)); + + JMenuItem myReplace = new JMenuItem("Replace"); + myReplace.setActionCommand("replace"); + myReplace.addActionListener(this); + myReplace.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, keyMask)); + + JMenuItem mySelect = new JMenuItem("Select Expression"); + mySelect.setActionCommand("select expression"); + mySelect.addActionListener(this); + mySelect.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E, keyMask)); + + myEditMenu.add(myCut); + myEditMenu.add(myCopy); + myEditMenu.add(myPaste); + myEditMenu.addSeparator(); + myEditMenu.add(myFind); + myEditMenu.add(myNext); + myEditMenu.add(myReplace); + myEditMenu.add(mySelect); + + // Set up Menu Bar + myMenuBar.add(myFileMenu); + myMenuBar.add(myEditMenu); + thisFile.setJMenuBar(myMenuBar); + /* BWP END */ // end menu stuff + + filePane = new CodePane(null, null, statusBar, fontSize); + pane = filePane.pane; + System.out.println("NyquistFile creation, this " + this + " pane = " + pane); + doc = filePane.doc; + + getContentPane().add(filePane); + statusBar.setPreferredSize(new Dimension(200, 8)); + getContentPane().add(statusBar, java.awt.BorderLayout.SOUTH); + statusBar.setText(""); + + if (file != null) { + readFile(file); + determineType(); + } + + /////////////// BWP BEGIN + // Right-Click Menu for the Document Window + JPopupMenu myContext = new JPopupMenu(); + + JMenuItem contextCut = new JMenuItem("Cut"); + contextCut.setActionCommand("context cut"); + contextCut.setName("context cut"); + contextCut.addActionListener(this); + + JMenuItem contextCopy = new JMenuItem("Copy"); + contextCopy.setActionCommand("context copy"); + contextCopy.setName("context copy"); + contextCopy.addActionListener(this); + + JMenuItem contextPaste = new JMenuItem("Paste"); + contextPaste.setActionCommand("context paste"); + contextPaste.setName("context paste"); + contextPaste.addActionListener(this); + + JMenuItem contextFind = new JMenuItem("Find"); + contextFind.setActionCommand("context find"); + contextFind.setName("context find"); + contextFind.addActionListener(this); + + JMenuItem contextReplace = new JMenuItem("Replace"); + contextReplace.setActionCommand("context replace"); + contextReplace.setName("context replace"); + contextReplace.addActionListener(this); + + JMenuItem contextSelect = new JMenuItem("Select Expression"); + contextSelect.setActionCommand("context select"); + contextSelect.setName("context select"); + contextSelect.addActionListener(this); + + myContext.add(contextCut); + myContext.add(contextCopy); + myContext.add(contextPaste); + myContext.addSeparator(); + myContext.add(contextFind); + myContext.add(contextReplace); + myContext.add(contextSelect); + + MouseListener popupListener = new PopupListener(myContext, pane); + pane.addMouseListener(popupListener); + + //////////////// BWP END + + setLocation(50+10, 50+10); + setSize(600, 500); + setBackground(Color.white); + setResizable(true); + setVisible(true); + this.setClosable(true); + this.setMaximizable(true); + this.setIconifiable(true); + setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); + + System.out.println("Adding component listener"); + filePane.addComponentListener(this); + + doc.addDocumentListener( + new DocumentListener() { + public void changedUpdate(DocumentEvent e) { + } + public void removeUpdate(DocumentEvent e) { + //filePane.synchronousUpdate(null); + if (!modified) { + modified = true; + thisFile.setTitle(thisFile.getTitle() + "*"); + } + } + public void insertUpdate(DocumentEvent e) { + // System.out.println("insertUpdate calls thread.update"); + //filePane.synchronousUpdate(null); + if (!modified) { + modified = true; + thisFile.setTitle(thisFile.getTitle() + "*"); + } + } + }); + //revertTo = pane.getText(); // BWP + } + + public void doFileSave() { + if (file != null) save(file.getParent()); + else saveAs(""); + } + + //// BWP BEGIN + public void actionPerformed(ActionEvent e) + { + //System.out.println(e.getActionCommand()); + + // File Menu options + if (e.getActionCommand().equals("load")) { + doFileSave(); + myParent.loadFile(file); + } else if (e.getActionCommand().equals("save")) { + doFileSave(); + } else if (e.getActionCommand().equals("save as")) { + if (file != null) saveAs(file.getParent()); + else saveAs(""); + } else if (e.getActionCommand().equals("revert")) { + if (modified && file != null) { + readFile(file); + myParent.loadFile(file); + //pane.setText(revertTo); + modified = false; + thisFile.setTitle(thisFile.getTitle().substring(0, + thisFile.getTitle().length() - 1)); + } + } else if (e.getActionCommand().equals("close")) { + int input = 1; + + if (modified) + input = JOptionPane.showConfirmDialog(null, + "Close without saving?", "Closing...", + JOptionPane.YES_NO_OPTION); + else this.dispose(); + + if (input == 0) this.dispose(); + // Edit Menu options + } else if (e.getActionCommand().equals("cut")) { + pane.cut(); + } else if (e.getActionCommand().equals("copy")) { + pane.copy(); + } else if (e.getActionCommand().equals("paste")) { + pane.paste(); + } else if (e.getActionCommand().equals("find")) { + FindDialog findDialog = new FindDialog(thisFile, myParent); + } else if (e.getActionCommand().equals("next")) { + if (!lastFound.equals("")) find(lastFound); + } else if (e.getActionCommand().equals("replace")) { + ReplaceDialog replaceDialog = new ReplaceDialog(thisFile, myParent); + } else if (e.getActionCommand().equals("select expression")) { + myParent.doEditSelectExpression(e); + // Context Menu Options + } else if (e.getActionCommand().equals("context cut")) { + pane.cut(); + } else if (e.getActionCommand().equals("context copy")) { + pane.copy(); + } else if (e.getActionCommand().equals("context paste")) { + pane.paste(); + } else if (e.getActionCommand().equals("context find")) { + FindDialog findDialog = new FindDialog(thisFile, myParent); + } else if (e.getActionCommand().equals("context replace")) { + ReplaceDialog replaceDialog = new ReplaceDialog(thisFile, myParent); + } else if (e.getActionCommand().equals("context select")) { + myParent.doEditSelectExpression(e); + } + //// BWP END + } + + public void componentResized(ComponentEvent e) { + System.out.println(e.getComponent().getClass().getName() + + " --- Resized "); + filePane.synchronousUpdate(); + } + + public void componentHidden(ComponentEvent e) { + System.out.println(e.getComponent().getClass().getName() + + " --- Hidden "); + } + + public void componentMoved(ComponentEvent e) { + System.out.println(e.getComponent().getClass().getName() + + " --- Moved "); + } + + + public void componentShown(ComponentEvent e) { + System.out.println(e.getComponent().getClass().getName() + + " --- Shown "); + } + + + String currentSelection() { + System.out.println("currentSelection: this " + this + " pane " + pane); + int p = pane.getSelectionStart(); + int q = pane.getSelectionEnd(); + try { + return doc.getText(p, q - p); + } catch(Exception e) { + System.out.println(e); + return ""; + } + } + + public void setCursor(int line, int col) { + try { // because getText raises an exception BadLocationException + String text = doc.getText(0, doc.getLength()); + int i = 0; + int j = 0; + while (j < line - 1) + if (text.charAt(i++) == '\n') j++; + final int pos = i + col - 1; + EventQueue.invokeLater( + new Runnable() { + public void run() { + System.out.println("Automatically move caret to " + pos); + pane.select(pos, pos); + } + }); + } catch(Exception e) { + System.out.println(e); + } + } + + + public void selectExpression() { + int docLength; + String text; + try { + docLength = doc.getLength(); + text = doc.getText(0, docLength); + } catch (Exception e) { + System.out.println(e); return; + } + int p = pane.getSelectionStart(); + int openParenLoc = CodePane.findOpenParen(text, p); + if (openParenLoc == p) return; + if (openParenLoc < 0) return; // no open paren enclosing start of selection + // now findx is the beginning of the expression and closed == 0 + // go forward from p to find close paren + + int closed = 0; + while (p < text.length() && closed < 1) { + char c = text.charAt(p); + if (c == '(' || c == ')') { + if (!CodePane.inComment(text, p)) { + if (c == '(') closed--; + else if (c == ')') closed++; + } + } + if (closed < 1) // not done, keep going + p = forward(text, p, false); + } + + pane.select(openParenLoc, p + 1); // add one to include close paren + } + + + private static int forward(String text, int pos, boolean inString) + // find an index in text after pos by skipping over strings and + // escaped characters of the form #\A, also skip comment + // lines. If pos is text.length() - 1, return text.length() + { + boolean comment = false; + boolean string = false; + while (pos < text.length()) { + char c = text.charAt(pos); + if (comment) { + if (c == '\n') { + comment = false; + } + } else if (string) { + if (c == '"') { // skip string + string = false; + } + } else if (c == '\\') { // skip quoted char + pos++; + } else if (c == '"') { + string = true; + } else if (c == ';') { + comment = true; + } + pos++; + if (!comment && !string) return pos; + } + return pos; + } + + + public boolean find(String pat) { + String docText = ""; + int start = pane.getSelectionEnd(); + //System.out.print("location "); + //System.out.println(start); + try { + docText = doc.getText(0, doc.getLength()); + } catch(Exception e) {System.out.println(e);} + + //System.out.print(docText); + int found = docText.indexOf(pat, start); + if (found == -1) { + found = docText.indexOf(pat, 0); + } + if (found == -1) return false; + pane.select(found, found + pat.length()); + return true; + } + + public String copy(boolean a, boolean b) + { + String selectedText = pane.getSelectedText(); + pane.copy(); + return selectedText; + } + + public boolean paste(String text) + { + pane.replaceSelection(text); + return true; + } + + public String getAbsolutePath() + { + return file.getAbsolutePath(); + } + + public boolean save(String currentDir) + // saves the file if there is a file name, otherwise calls saveAs. + // returns false if the operation fails or is cancelled. + // returns true if save succeeds or if file is unmodified. + { + if (modified) { + if (file == null) + return saveAs(currentDir); + else { + try { + long length = file.length(); + long newLength = doc.getLength(); + System.out.println("existing " + length + " new " + newLength); + String msg = null; + if (length > 0 && newLength == 0) { + msg = "Replace existing file with an empty document?"; + } else if (length > newLength * 2) { + msg = "Replace file with new document that is less than 1/2 the existing size?"; + } + if (msg != null) { + int n = JOptionPane.showConfirmDialog(this, msg, "WARNING", + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (n == JOptionPane.NO_OPTION) return false; + } + + FileOutputStream saveFileStream = + new FileOutputStream(file); + + String fileStr = doc.getText(0, doc.getLength()); + saveFileStream.write(fileStr.getBytes()); + saveFileStream.flush(); + } + catch(Exception e) { + System.out.println(e); + return false; // did not save file + } + + modified = false; + thisFile.setTitle(thisFile.getTitle().substring( + 0, thisFile.getTitle().length() - 1)); + } + } + //revertTo = pane.getText(); + return true; + } + + public boolean saveAs(String currentDir) { + // select a file and write to it. Return true if success. + JFileChooser chooser = new JFileChooser(); + LispFileFilter filter = new LispFileFilter(); + SalFileFilter salFilter = new SalFileFilter(); + String name; // new file name + chooser.setFileFilter(filter); + chooser.setFileFilter(salFilter); + + File curdir = new File(currentDir); + chooser.setCurrentDirectory(curdir); + + while (true) { // loop until file is chosen + int returnVal = chooser.showSaveDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + name = file.getName(); + System.out.println("You chose to save this file: " + name); + String lower = name.toLowerCase(); + if (lower.endsWith(".sal") || + lower.endsWith(".lsp")) break; + JOptionPane dialog = new JOptionPane(); + System.out.println("creating dialog"); + int result = dialog.showConfirmDialog(this, + "Do you really want to save a file without a " + + ".lsp or .sal extension?", "Warning", + JOptionPane.YES_NO_OPTION); + System.out.println("return from dialog " + result); + if (result == JOptionPane.YES_OPTION) break; + } else { // file chooser cancel, early return + return false; + } + } + setTitle(name + "*"); + determineType(); + modified = true; + return save(currentDir); + } + +} diff --git a/jnyqide/NyquistThread.java b/jnyqide/NyquistThread.java new file mode 100644 index 0000000..e579558 --- /dev/null +++ b/jnyqide/NyquistThread.java @@ -0,0 +1,424 @@ +package jnyqide; + +import java.io.*; +import javax.swing.*; + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +public class NyquistThread extends Thread { + + Process myProcess; + InputStream stdout; + InputStreamReader isrStdout; + BufferedReader brStdout; + OutputStream stdin; + byte b[]; +// JTextPane textIn; + JTextArea textOut; + Runnable update; + String plotFilename; + boolean plotNow = false; + boolean envelopeNow = false; + boolean editNow = false; + boolean eqNow = false; + boolean preferenceDataSent = false; + boolean initialLoad = false; + String envData; + String eqData; + PlotFrame plotFrame; + MainFrame mainFrame; // used to find current directory + String soundBrowser; // path for sound browser + String scoreEditFileName; + public NyquistThread() { + } + +/* public void setInputArea( JTextPane in ) + { + textIn = in; + }*/ + + public String StringFromFile(String filename, String default_string) { + try { + BufferedReader br = new BufferedReader(new FileReader(filename)); + default_string = br.readLine(); + br.close(); + } catch (Exception e) { + // do nothing + } + return default_string; + } + + public void start(JTextArea out, Runnable u, + PlotFrame plot, MainFrame main) { + textOut = out; + update = u; + plotFrame = plot; + mainFrame = main; + + try { + // Get the current working directory where we can find lib and runtime + // get the "." file present in all directories + //java.io.File f = new java.io.File("."); + // get the absolute path to the "." file + //String cwd2 = f.getAbsolutePath(); + // return the absolute path minus the "." + //cwd2 = cwd2.substring(0, cwd2.length() - 2); + // the code above works, but the following is simpler: + + // find full path to instruments.txt + String cwd = System.getProperty("user.dir"); + soundBrowser = cwd.concat("/lib/instruments.txt"); + System.out.println("soundBrowser file is " + soundBrowser); + + // build XLISPPATH environment specification + String path = System.getenv("XLISPPATH"); // use getenv + if (path == null) { // getenv failed, use a default setting + path = cwd + "/lib/;" + cwd + "/runtime/;"; + } + // if xlisppath file exists, use it instead + path = "XLISPPATH=" + StringFromFile("xlisppath", path); + + // construct SystemRoot for environment from file + String systemroot = StringFromFile("systemroot", "SystemRoot=C:/windows"); + + // See if we can get the USER + String user = System.getenv("USER"); + if (user == null) user = ""; + user = StringFromFile("user", user); // file value overrides all + if (user == "") user = "IGNORE="; // default value + else user = "USER=" + user; + + // Construct the environment for nyquist subprocess + System.out.println(path); + System.out.println(user); + + // make environment from 3 strings + String[] envp = {path, user, systemroot}; + System.out.println("envp has " + systemroot); + + try { + myProcess = Runtime.getRuntime().exec( "./ny", envp ); + } catch (Exception e3) { + System.out.println("no ./ny found, trying ./nyquist"); + try { + myProcess = Runtime.getRuntime().exec("./nyquist", envp); + } catch (Exception e4) { + System.out.println("no ./nyquist found, trying ny"); + // try using PATH to find ny (for linux systems where + // ny is installed) + myProcess = Runtime.getRuntime().exec("ny", envp); + // if this one fails, we'll take the exception below + } + } + System.out.print("myProcess: " + myProcess); + + stdout = myProcess.getInputStream(); + isrStdout = new InputStreamReader(stdout); + brStdout = new BufferedReader(isrStdout); + stdin = myProcess.getOutputStream(); + stdin.write(6); // control-f turns off console echo for Mac and Linux + stdin.flush(); + } + catch( Exception e2 ) { System.out.println(e2); } + + b = new byte[1000]; + if (brStdout != null) { + super.start(); + } else { + textOut.append("Nyquist (ny or nyquist) not found or could not be started."); + } + } + + public void run() { + final int max_buf_len = 256; + StringBuffer buffer = new StringBuffer(max_buf_len); + int buffer_index = 0; + boolean nyquist_is_running = true; + // this is tricky -- we want to accumulate lines to test + // for plot commands, but we want to append chars to + // textOut even if there is no end-of-line. + // + // We're going to flush the buffer after every line. + // That will be expensive if lines are very short, but + // that's pretty rare. So we'll loop until we either + // accumulate a line or there are no characters ready. + // To avoid re-appending characters to textOut, use + // buffer_index to remember how many characters were + // output from the current line. + // + // Algorithm: + // accumulate chars while input is ready and newline not found + // if we have a newline, test for plot command + // append characters to text box + // if we have a newline, reset the buffer + + String line = null; + //String debug_strings[] = new String[100]; + //int debug_strings_x = 0; + while (nyquist_is_running) { + try { + // initialLoad is true when we see text that indicates + // Nyquist has just started. But we want to wait for the + // first prompt. We do this by delaying this process a bit + // hoping that Nyquist will finish output and issue the + // prompt. Then we process the input until we are about to + // block, meaning that (maybe) Nyquist has finished output + // and is waiting at the prompt. + if (initialLoad && !brStdout.ready()) { + mainFrame.sendPreferenceData(); + initialLoad = false; + } + // block until you read at least one character + int ic = brStdout.read(); + //System.out.println("got char"); + if (ic != -1) buffer.append((char) ic); + // read many characters to avoid the overhead of single + // character output. On the other hand, it's expensive + // to build huge buffers if Nyquist outputs a giant + // list, so limit the buffer length to max_buf_len. + while (brStdout.ready() && ic != '\n' && ic != -1 && + buffer.length() < max_buf_len) { + //System.out.println("block on char in while"); + ic = brStdout.read(); + //System.out.println("got it"); + if (ic != -1) buffer.append((char) ic); + } + if ((char) ic == '\n') { + line = new String(buffer); + testForPlot(line); + } else if (buffer.length() >= max_buf_len) { + // pretend we found a line in order to flush + // characters building up in buffer + line = " "; + } else if (ic == -1) { + buffer.append("The Nyquist process has terminated. Please save your files and exit.\n"); + nyquist_is_running = false; + } + textOut.append(buffer.substring(buffer_index)); + buffer_index = buffer.length(); + if (line != null) { // end of line, reset the buffer + line = null; + buffer.setLength(0); + buffer_index = 0; + // limit number of lines and characters in the textOut box + int lines = textOut.getLineCount(); + if (lines > 5000 || + textOut.getLineEndOffset(lines - 1) > 50000) { + // take out about 100 lines at a time: + textOut.replaceRange("", 0, + textOut.getLineStartOffset( + Math.max(1, lines - 4900))); + } + } + // cause the scroll to go to the end of the new text + SwingUtilities.invokeLater(update); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + + private NyquistFile findFile(String filename) { + JInternalFrame[] frames = mainFrame.jDesktop.getAllFrames(); + int i; + for (i = 0; i < frames.length; i++) { + if (frames[i] instanceof NyquistFile) { + NyquistFile nyquistFile = (NyquistFile) frames[i]; + System.out.println("findFile search: " + + nyquistFile.file.getName() + + " file " + nyquistFile.file + " getAbsolutePath " + + nyquistFile.file.getAbsolutePath()); + if (nyquistFile.file.getAbsolutePath().equals(filename)) + return nyquistFile; + } + } + return null; + } + + + // testForPlot looks for Nyquist output that the jNyqIDE wants to know + // about -- originally just plot command output, but now there are many + // Lisp functions that communicate and synchronize with the jNyqIDE + public void testForPlot(String output) { + int iNameStart; + int iNameStop; + //System.out.print("plot's text output:"); + //System.out.println(output); + if (!plotNow) { + iNameStart = output.indexOf("s-plot: writing "); + if (iNameStart >= 0) { + iNameStop = output.indexOf(" ..."); + plotFilename = output.substring(iNameStart + 16, iNameStop); + // Nyquist file should be absolute or current directories + // should be synchronized. Appending the current directory + // causes problems when Nyquist already prints a full path + //if (!mainFrame.currentDir.equals("")) { + // plotFilename = mainFrame.currentDir + plotFilename; + //} + System.out.println("file:" + plotFilename + ":"); + plotNow = true; + } + } + // this is not ...else if... because output can have many lines + if (plotNow) { + iNameStart = output.indexOf(" points from"); + // now, the file is written and closed so we can open it + if (iNameStart >= 0) { + System.out.println("Calling NyqPlot.plot"); + NyqPlot.plot(plotFilename, plotFrame); + plotNow = false; + } + } + // test for loading workspace and saving workspace + if (output.indexOf("workspace loaded") >= 0) { + mainFrame.workspaceLoaded = true; + } else if (output.indexOf("workspace saved") >= 0) { + mainFrame.workspaceSaved = true; + } else if (!envelopeNow) { // test for envelope data + int index = output.indexOf("get-env-data: begin"); + if (index >= 0) { + output = output.substring(index); + envData = ""; + envelopeNow = true; + } + } + if (envelopeNow) { + envData += output; + int index = envData.indexOf("get-env-data: end"); + // remove first line + if (index >= 0) { + int begin = envData.indexOf("\n"); + envData = envData.substring(begin + 1, index); + mainFrame.loadEnvData(envData); + envelopeNow = false; + } + } + if (!eqNow) { + int index = output.indexOf("get-eq-data: begin"); + if (index >= 0) { + output = output.substring(index); + eqData = ""; + eqNow = true; + } + } + if (eqNow) { + eqData += output; + int index = eqData.indexOf("get-eq-data: end"); + // remove first line + if (index >= 0) { + int begin = eqData.indexOf("\n"); + eqData = eqData.substring(begin + 1, index); + mainFrame.loadEqData(eqData); + eqNow = false; + } + } + if (!editNow) { + iNameStart = output.indexOf("score-edit: writing "); + if (iNameStart >= 0) { + iNameStop = output.indexOf(" ..."); + scoreEditFileName = output.substring(iNameStart + 20, iNameStop); + if (!mainFrame.currentDir.equals("")) { + scoreEditFileName = mainFrame.currentDir + scoreEditFileName; + } + System.out.println("file:" + scoreEditFileName + ":"); + editNow = true; + } + } + if (editNow) { + iNameStart = output.indexOf("score-edit: wrote "); + if (iNameStart >= 0) { + Piano_Roll.scoreEdit(scoreEditFileName); + editNow = false; + } + } + if (!preferenceDataSent) { + iNameStart = output.indexOf("by Roger B. Dannenberg"); + if (iNameStart >= 0) { + try { Thread.sleep(200); } + catch (InterruptedException ie) { } + initialLoad = true; + preferenceDataSent = true; + } + } + // System.out.println("OUTPUT FOR PROMPT SEARCH: " + output); + // determine command input mode from prompt by Nyquist: + int promptLoc = output.indexOf("> "); + if (output.indexOf("Entering SAL mode ...") >= 0) { + mainFrame.setSalMode(true); + } else if (output.indexOf("Returning to Lisp ...") >= 0) { + mainFrame.setSalMode(false); + } else if (output.indexOf("[ back to top level ]") >= 0) { + mainFrame.setSalMode(false); + } else if (output.indexOf("if continued: return from BREAK") >= 0) { + mainFrame.setSalMode(false); + } else if (promptLoc == 2 && output.indexOf(">>> in ") == 0) { + System.out.println("... detected >>> in (error line location) "); + int lineLoc = output.indexOf(", line "); + int colLoc = output.indexOf(", col "); + if (lineLoc > 0 && colLoc > 0) { + String filename = output.substring(7, lineLoc); + String lineString = output.substring(lineLoc + 7, colLoc); + String colString = output.substring(colLoc + 6, + output.length() - 2); + NyquistFile nf = findFile(filename); + System.out.println("nf.setCursor line " + lineString + + " col " + colString + " file " + filename + " nf " + nf); + if (isDigits(lineString) && isDigits(colString) && nf != null) { + nf.setCursor(Integer.parseInt(lineString), + Integer.parseInt(colString)); + } + } + } else if (promptLoc >= 0) { + if (output.indexOf("SAL> ") == 0) { + mainFrame.setSalMode(true); + // System.out.println("in SAL mode"); + } else if (isDigits(output.substring(0, promptLoc))) { + mainFrame.setSalMode(false); + // System.out.println("in LISP mode"); + } + } + } + + private boolean isDigits(String s) { + // returns true if all chars in s are digits + for (int i = 0; i < s.length(); i++) + if (!Character.isDigit(s.charAt(i))) return false; + return true; + } + + + public OutputStream getStdin() { + return stdin; + } + + public void sendInput(String s) { + sendInput(s, false); + } + + public void sendInput(String s, boolean hide) { + try { + //System.out.println("Sending:" + hide + ": " + s); + if (!hide) textOut.append(s); + stdin.write( s.getBytes() ); + stdin.flush(); + } catch (Exception e) { + System.out.println(e); + } + } +} + + + + + + + + + diff --git a/jnyqide/NyquistWords.txt b/jnyqide/NyquistWords.txt new file mode 100644 index 0000000..a5c5798 --- /dev/null +++ b/jnyqide/NyquistWords.txt @@ -0,0 +1,1520 @@ +* expr ...) +part19.html#index1460 +*a4-hertz* +part9.html#index789 +*applyhook* +part19.html#index1298 +*autonorm* +part9.html#index790 +*autonorm-max-samples* +part9.html#index792 +*autonorm-previous-peak* +part9.html#index793 +*autonorm-target* +part9.html#index794 +*autonorm-type* +part9.html#index795 +*autonormflag* +part9.html#index791 +*breakenable* +part19.html#index1293 +*breakenable* +part19.html#index1293 +*control-srate* +part9.html#index797 +*control-srate* +part9.html#index797 +*debug-io* +part19.html#index1292 +*default-control-srate* +part9.html#index802 +*default-plot-file* +part8.html#index629 +*default-sf-bits* +part9.html#index798 +*default-sf-dir* +part9.html#index799 +*default-sf-format* +part9.html#index800 +*default-sf-srate* +part9.html#index801 +*default-sound-srate* +part9.html#index803 +*error-output* +part19.html#index1290 +*evalhook* +part19.html#index1297 +*file-separator* +part9.html#index804 +*float-format* +part19.html#index1304 +*gc-flag* +part19.html#index1301 +*gc-hook* +part19.html#index1302 +*integer-format* +part19.html#index1303 +*loud* +part4.html#index130 +*obarray* +part19.html#index1287 +*print-case* +part19.html#index1305 +*readtable* +part19.html#index1299 +*rslt* +part9.html#index805 +*sound-srate* +part9.html#index806 +*sound-srate* +part9.html#index806 +*soundenable* +part9.html#index807 +*standard-input* +part19.html#index1288 +*standard-output* +part19.html#index1289 +*start* +part4.html#index133 +*stop* +part4.html#index134 +*sustain* +part4.html#index132 +*table* +part9.html#index788 +*trace-output* +part19.html#index1291 +*tracelimit* +part19.html#index1296 +*tracelist* +part19.html#index1294 +*tracenable* +part19.html#index1295 +*tracenable* +part19.html#index1295 +*transpose* +part4.html#index131 +*unbound* +part19.html#index1300 +*warp* +part4.html#index129 ++ expr ...) +part19.html#index1458 +- expr ...) +part19.html#index1459 +/ expr ...) +part19.html#index1461 +1+ expr) +part19.html#index1462 +1- expr) +part19.html#index1463 +< n1 n2 ...) +part19.html#index1483 +abs expr) +part19.html#index1471 +abs-env beh) +part8.html#index546 +add-action-to-workspace symbol) +part14.html#index1144 +add-to-workspace symbol) +part14.html#index1141 +address-of expr) +part19.html#index1612 +agc input range rise-time fall-time [lookahead]) +part15.html#index1170 +alloc num) +part19.html#index1602 +allpass2 signal hz [q]) +part8.html#index438 +allpoles-from-lpc snd lpc-frame) +part12.html#index970 +alpass sound decay hz [minhz]) +part8.html#index401 +amosc pitch modulation [table phase]) +part8.html#index367 +and expr ...) +part19.html#index1407 +append expr ...) +part19.html#index1353 +apply fun args) +part19.html#index1308 +apply-banded-bass-boost s lowp highp num-bands num-boost gain) +part15.html#index1198 +apply-banded-delay s lowp highp num-bands lowd highd fb wet) +part15.html#index1196 +apply-banded-treble-boost s lowp highp num-bands num-boost gain) +part15.html#index1200 +arc-sine-dist ) +part14.html#index1069 +aref array n) +part19.html#index1337 +areson sound center bandwidth n) +part8.html#index423 +args name) +part13.html#index983 +arrayp expr) +part19.html#index1391 +assoc expr alist :test test :test-not test-not) +part19.html#index1357 +at time beh) +part8.html#index547 +at-abs time beh) +part8.html#index549 +atan expr[expr2]) +part19.html#index1479 +atom expr) +part19.html#index1379 +atone sound cutoff) +part8.html#index418 +autonorm-off ) +part8.html#index608 +autonorm-on ) +part8.html#index607 +backquote expr) +part19.html#index1312 +baktrace [n]) +part19.html#index1450 +bandpass2 signal hz [q]) +part8.html#index436 +bernoulli-dist px1 [x1 x2]) +part14.html#index1076 +beta-dist a b) +part14.html#index1074 +bigendianp ) +part19.html#index1608 +bilateral-exponential-dist xmu tau [low high]) +part14.html#index1062 +binomial-dist n p) +part14.html#index1078 +biquad signal b0 b1 b2 a0 a1 a2) +part8.html#index432 +biquad-m signal b0 b1 b2 a0 a1 a2) +part8.html#index433 +block name expr ...) +part19.html#index1430 +both-case-p chr) +part19.html#index1524 +boundp sym) +part19.html#index1395 +bowed step bowpress-env) +part8.html#index496 +bowed-freq step bowpress-env freq-env) +part8.html#index498 +break [bmsg[arg]]) +part19.html#index1445 +build-harmonic n table-size) +part8.html#index334 +buzz n pitch modulation) +part8.html#index371 +car expr) +part19.html#index1341 +case expr case ...) +part19.html#index1412 +catch sym expr ...) +part19.html#index1418 +cauchy-dist tau [low high]) +part14.html#index1064 +cdr expr) +part19.html#index1342 +cerror cmsg emsg[arg]) +part19.html#index1444 +char string index) +part19.html#index1521 +char-code chr) +part19.html#index1526 +char-downcase chr) +part19.html#index1529 +char-equalp chr1 chr2 ...) +part19.html#index1541 +char-greaterp chr1 chr2 ...) +part19.html#index1544 +char-int chr) +part19.html#index1531 +char-lessp chr1 chr2 ...) +part19.html#index1539 +char-not-equalp chr1 chr2 ...) +part19.html#index1542 +char-not-greaterp chr1 chr2 ...) +part19.html#index1540 +char-not-lessp chr1 chr2 ...) +part19.html#index1543 +char-upcase chr) +part19.html#index1528 +char/= chr1 chr2 ...) +part19.html#index1536 +char< chr1 chr2 ...) +part19.html#index1533 +char<= chr1 chr2 ...) +part19.html#index1534 +char= chr1 chr2 ...) +part19.html#index1535 +char> chr1 chr2 ...) +part19.html#index1538 +char>= chr1 chr2 ...) +part19.html#index1537 +characterp expr) +part19.html#index1390 +chorus snd maxdepth depth rate saturation) +part15.html#index1191 +clarinet step breath-env) +part8.html#index474 +clarinet-all step breath-env freq-env vibrato-freq vibrato-gain reed-stiffness noise) +part8.html#index480 +clarinet-freq step breath-env freq-env) +part8.html#index477 +clean-up) +part19.html#index1446 +clip sound peak) +part8.html#index514 +close stream) +part19.html#index1561 +code-char code) +part19.html#index1527 +comb sound decay hz) +part8.html#index402 +compress input map rise-time fall-time [lookahead]) +part15.html#index1168 +compress-map compress-ratio compress-threshold expand-ratio expand-ratio :limit limit :transition transition) +part15.html#index1166 +cond pair ...) +part19.html#index1406 +congen gate risetime falltime) +part8.html#index404 +cons expr1 expr2) +part19.html#index1351 +consp expr) +part19.html#index1386 +const value [duration]) +part8.html#index322 +continue) +part19.html#index1448 +continuous-control-warp beh) +part8.html#index551 +continuous-sound-warp beh) +part8.html#index552 +control sound) +part8.html#index321 +control-srate-abs srate beh) +part8.html#index553 +control-warp warp-fn signal [wrate]) +part8.html#index338 +convolve sound response) +part8.html#index407 +cos expr) +part19.html#index1477 +cue sound) +part8.html#index318 +cue-file filename) +part8.html#index319 +current-path ) +part13.html#index995 +cxxr expr) +part19.html#index1343 +cxxxr expr) +part19.html#index1344 +cxxxxr expr) +part19.html#index1345 +db-average input) +part15.html#index1167 +db-to-linear x) +part8.html#index283 +decf symbol) +part13.html#index987 +defmacro sym fargs expr ...) +part19.html#index1323 +defun sym fargs expr ...) +part19.html#index1322 +delete expr :test test :test-not test-not) +part19.html#index1374 +delete-if test list) +part19.html#index1375 +delete-if-not test list) +part19.html#index1376 +describe symbol [description]) +part14.html#index1143 +diff a b) +part8.html#index585 +digit-char n) +part19.html#index1530 +digit-char-p chr) +part19.html#index1525 +do (binding ...) (texpr rexpr ...) expr ...) +part19.html#index1423 +do* (binding ...) (texpr rexpr ...) expr ...) +part19.html#index1424 +dolist (sym expr [rexpr]) expr ...) +part19.html#index1425 +dotimes (sym expr [rexpr]) expr ...) +part19.html#index1426 +dribble [fname]) +part19.html#index1599 +drum tracknum patternnum bpm) +part15.html#index1241 +drum-loop snd duration numtimes) +part15.html#index1242 +dtmf-tone key len space) +part15.html#index1211 +echoenabled flag) +part19.html#index1617 +endp list) +part19.html#index1385 +env t1 t2 t4 l1 l2 l3 [dur]) +part8.html#index324 +eq expr1 expr2) +part19.html#index1402 +eq-band signal hz gain width) +part8.html#index443 +eq-highshelf signal hz gain [slope]) +part8.html#index441 +eq-lowshelf signal hz gain [slope]) +part8.html#index439 +eql expr1 expr2) +part19.html#index1403 +equal expr1 expr2) +part19.html#index1404 +error emsg[arg]) +part19.html#index1443 +errset expr [pflag]) +part19.html#index1449 +eval expr) +part19.html#index1307 +evalhook expr ehook ahook [env]) +part19.html#index1453 +evenp expr) +part19.html#index1400 +event-dur event) +part14.html#index1092 +event-end event) +part14.html#index1096 +event-expression event) +part14.html#index1094 +event-get-attr event attribute [default]) +part14.html#index1101 +event-has-attr event attribute) +part14.html#index1100 +event-set-attr event attribute value) +part14.html#index1102 +event-set-dur event dur) +part14.html#index1093 +event-set-expression event dur) +part14.html#index1095 +event-set-time event time) +part14.html#index1091 +event-time event) +part14.html#index1090 +exit ) +part19.html#index1613 +exp x-expr) +part19.html#index1481 +exp-dec hold halfdec length) +part8.html#index325 +expand num) +part19.html#index1601 +exponential-dist delta [high]) +part14.html#index1059 +expr-get-attr expression attribute [default]) +part14.html#index1098 +expr-has-attr expression attribute) +part14.html#index1097 +expr-set-attr expr attribute value) +part14.html#index1099 +expt x-expr y-expr) +part19.html#index1480 +extract start stop beh) +part8.html#index555 +extract-abs start stop beh) +part8.html#index556 +fboundp sym) +part19.html#index1396 +feedback-delay sound delay feedback) +part8.html#index410 +filep expr) +part19.html#index1394 +find-in-xlisp-path filename) +part19.html#index1575 +first expr) +part19.html#index1346 +flange snd) +part15.html#index1186 +flatc expr) +part19.html#index1553 +flatsize expr) +part19.html#index1552 +flet (binding ...) expr ...) +part19.html#index1415 +float expr) +part19.html#index1457 +floatp expr) +part19.html#index1388 +flute step breath-env) +part8.html#index490 +flute-all step breath-env freq-env vibrato-freq vibrato-gain jet-delay noise) +part8.html#index494 +flute-freq step breath-env freq-env) +part8.html#index492 +fmfb pitch index [dur]) +part8.html#index369 +fmlfo freq [table phase]) +part8.html#index332 +fmosc pitch modulation [table phase]) +part8.html#index368 +follow sound floor risetime falltime lookahead) +part8.html#index284 +force-srate srate sound) +part8.html#index327 +format stream fmt arg ...) +part19.html#index1555 +fourth expr) +part19.html#index1349 +funcall fun arg ...) +part19.html#index1309 +function expr) +part19.html#index1311 +gamma-dist nu [high]) +part14.html#index1061 +gate sound lookahead risetime falltime floor threshold) +part8.html#index288 +gaussian-dist xmu sigma [low high]) +part14.html#index1072 +gc ) +part19.html#index1600 +gcd n1 n2 ...) +part19.html#index1472 +gensym [tag]) +part19.html#index1324 +geometric-dist p) +part14.html#index1080 +get sym prop) +part19.html#index1333 +get-duration dur) +part8.html#index303 +get-env name) +part19.html#index1593 +get-lambda-expression closure) +part19.html#index1314 +get-loud ) +part8.html#index304 +get-output-stream-list stream) +part19.html#index1591 +get-output-stream-string stream) +part19.html#index1590 +get-slider-value index) +part8.html#index642 +get-sustain ) +part8.html#index305 +get-temp-path ) +part19.html#index1569 +get-transpose ) +part8.html#index306 +get-user ) +part19.html#index1572 +get-warp ) +part8.html#index307 +go sym) +part19.html#index1434 +grindef name) +part13.html#index981 +hash sym n) +part19.html#index1331 +highpass2 signal hz [q]) +part8.html#index435 +highpass4 signal hz) +part8.html#index448 +highpass6 signal hz) +part8.html#index449 +highpass8 signal hz) +part8.html#index450 +hp sound cutoff) +part8.html#index416 +hyperbolic-cosine-dist [low high]) +part14.html#index1066 +hz-to-step freq) +part8.html#index290 +hzosc hz [table phase]) +part8.html#index358 +if texpr expr1[expr2]) +part19.html#index1409 +incf symbol) +part13.html#index985 +info ) +part19.html#index1603 +int-char int) +part19.html#index1532 +integerp expr) +part19.html#index1387 +integrate signal) +part8.html#index350 +intern pname) +part19.html#index1325 +interpolate x x1 y1 x2 y2) +part14.html#index1148 +intersection a b) +part14.html#index1150 +jcrev sound decay mix) +part8.html#index458 +labels (binding ...) expr ...) +part19.html#index1416 +lambda args expr ...) +part19.html#index1313 +last list) +part19.html#index1355 +length expr) +part19.html#index1361 +length-of-beat bpm) +part15.html#index1243 +let (binding ...) expr ...) +part19.html#index1413 +let* (binding ...) expr ...) +part19.html#index1414 +lfo freq [duration table phase]) +part8.html#index330 +linear-dist g) +part14.html#index1057 +linear-to-db x) +part8.html#index291 +list expr ...) +part19.html#index1352 +listdir path) +part19.html#index1564 +listp expr) +part19.html#index1384 +load fname [:verbose verbose] [:print print]) +part19.html#index1596 +local-to-global local-time) +part8.html#index308 +log x) +part8.html#index293 +logand expr ...) +part19.html#index1490 +logior expr ...) +part19.html#index1491 +logistic-dist alpha beta [low high]) +part14.html#index1067 +lognot expr) +part19.html#index1493 +logxor expr ...) +part19.html#index1492 +loop expr ...) +part19.html#index1422 +loud volume beh) +part8.html#index557 +loud-abs volume beh) +part8.html#index558 +lower-case-p chr) +part19.html#index1523 +lowpass2 signal hz [q]) +part8.html#index434 +lowpass4 signal hz) +part8.html#index445 +lowpass6 signal hz) +part8.html#index446 +lowpass8 signal hz) +part8.html#index447 +lp sound cutoff) +part8.html#index413 +lpc-frame-err frame) +part12.html#index974 +lpc-frame-filter-coefs frame) +part12.html#index975 +lpc-frame-rms1 frame) +part12.html#index972 +lpc-frame-rms2 frame) +part12.html#index973 +lpreson snd lpc-iterator skiptime) +part12.html#index971 +macroexpand form) +part19.html#index1315 +macroexpand-1 form) +part19.html#index1316 +macrolet (binding ...) expr ...) +part19.html#index1417 +make-accumulate sub-pattern :for for :max maximum :min minimum :name name :trace trace) +part14.html#index1028 +make-accumulation items :name name :trace trace) +part14.html#index1022 +make-array size) +part19.html#index1338 +make-copier sub-pattern :repeat repeat :merge merge :for for :name name :trace trace) +part14.html#index1025 +make-cycle items :for for :name name :trace trace) +part14.html#index1007 +make-eval expr :for for :name name :trace trace) +part14.html#index1037 +make-heap items :for for :max max :name name :trace trace) +part14.html#index1019 +make-length pattern length-pattern :name name :trace trace) +part14.html#index1044 +make-line items :for for :name name :trace trace) +part14.html#index1010 +make-lpanal-iterator sound framedur skiptime npoles) +part12.html#index966 +make-lpc-file-iterator filename) +part12.html#index967 +make-markov rules :past past :produces produces :for for :name name :trace trace) +part14.html#index1048 +make-palindrome items :elide elide :for for :name name :trace trace) +part14.html#index1016 +make-product x y :for for :name name :trace trace) +part14.html#index1034 +make-random items :for for :name name :trace trace) +part14.html#index1013 +make-string-input-stream str[start[end]]) +part19.html#index1588 +make-string-output-stream) ) +part19.html#index1589 +make-sum x y :for for :name name :trace trace) +part14.html#index1031 +make-symbol pname) +part19.html#index1326 +make-window pattern length-pattern skip-pattern :name name :trace trace) +part14.html#index1047 +maketable sound) +part8.html#index333 +mandolin step dur [detune]) +part8.html#index500 +mapc fcn list1 list ...) +part19.html#index1364 +mapcar fcn list1 list ...) +part19.html#index1365 +mapl fcn list1 list ...) +part19.html#index1366 +maplist fcn list1 list ...) +part19.html#index1367 +markov-create-rules sequence order [generalize]) +part14.html#index1051 +max expr ...) +part19.html#index1469 +member expr list :test test :test-not test-not) +part19.html#index1356 +midi-show the-seq [out-file]) +part15.html#index1206 +midi-show-file file-name) +part15.html#index1203 +min expr ...) +part19.html#index1467 +minusp expr) +part19.html#index1397 +modalbar preset step dur) +part8.html#index510 +mult a [b ...]) +part8.html#index582 +mult beh1 beh2 ...) +part8.html#index582 +nband input gains) +part15.html#index1177 +nband-range input gains lowf highf) +part15.html#index1174 +nconc list ...) +part19.html#index1373 +noise [duration]) +part8.html#index538 +not expr) +part19.html#index1383 +notch2 signal hz [q]) +part8.html#index437 +nrev sound decay mix) +part8.html#index454 +nstring-downcase str :start start :end end) +part19.html#index1504 +nstring-upcase str :start start :end end) +part19.html#index1503 +nth n list) +part19.html#index1362 +nthcdr n list) +part19.html#index1363 +null expr) +part19.html#index1382 +numberp expr) +part19.html#index1381 +Ny:all +part2.html#index67 +objectp expr) +part19.html#index1393 +oddp expr) +part19.html#index1401 +open fname :direction direction) +part19.html#index1557 +open-binary fname :direction direction) +part19.html#index1558 +or expr ...) +part19.html#index1408 +osc pitch [duration table phase]) +part8.html#index355 +osc-enable flag) +part8.html#index309 +osc-note pitch [duration env loud table]) +part8.html#index529 +osc-pulse hz bias [compare-shape]) +part8.html#index363 +osc-saw hz) +part8.html#index359 +osc-tri hz) +part8.html#index361 +pan sound where) +part8.html#index341 +params-scale params keyword amount) +part14.html#index1147 +params-transpose params keyword amount) +part14.html#index1146 +partial pitch env) +part8.html#index356 +patternp expression) +part14.html#index1145 +peak expression maxlen) +part8.html#index687 +peek addrs) +part19.html#index1606 +peek-char [flag[stream]]) +part19.html#index1578 +phaser snd) +part15.html#index1184 +piano-midi midi-file-name) +part15.html#index1164 +piano-midi2file midi-file-name sound-file-name) +part15.html#index1165 +piano-note duration step dynamic) +part15.html#index1161 +piano-note-2 step dynamic) +part15.html#index1163 +pitshift sound shift mix) +part8.html#index470 +pl-center snd) +part15.html#index1233 +pl-doppler snd r) +part15.html#index1238 +pl-left snd) +part15.html#index1232 +pl-pan2d snd x y) +part15.html#index1236 +pl-position snd x y config) +part15.html#index1237 +pl-rear snd) +part15.html#index1235 +pl-right snd) +part15.html#index1234 +play sound +part8.html#index591 +play-file filename) +part8.html#index606 +pluck pitch [duration final-amplitude]) +part8.html#index372 +plusp expr) +part19.html#index1399 +poisson-dist delta) +part14.html#index1082 +poke addrs value) +part19.html#index1607 +pop lis) +part13.html#index990 +power x y) +part13.html#index1001 +pprint expr[stream]) +part19.html#index1550 +prcrev sound decay mix) +part8.html#index462 +prin1 expr[stream]) +part19.html#index1548 +princ expr[stream]) +part19.html#index1549 +print expr [stream]) +part19.html#index1547 +prod beh1 beh2 ...) +part8.html#index343 +prod beh1 beh2 ...) +part8.html#index343 +profile flag) +part19.html#index1454 +prog (binding ...) expr ...) +part19.html#index1428 +prog* (binding ...) expr ...) +part19.html#index1429 +prog1 expr1 expr ...) +part19.html#index1436 +prog2 expr1 expr2 expr ...) +part19.html#index1437 +progn expr ...) +part19.html#index1438 +progv slist vlist expr ...) +part19.html#index1435 +prologic l c r s) +part15.html#index1229 +psetq [sym expr] ...) +part19.html#index1320 +push val lis) +part13.html#index989 +putprop sym val prop) +part19.html#index1334 +pwe t1 l1 t2 l2 ... tn) +part8.html#index390 +pwe-list breakpoints) +part8.html#index391 +pwer i1 l1 i2 l2 ... in) +part8.html#index394 +pwer-list breakpoints) +part8.html#index395 +pwev l1 t2 l2 t3 t3 ... tn ln) +part8.html#index392 +pwev-list breakpoints) +part8.html#index393 +pwevr l1 i2 l2 i3 i3 ... in ln) +part8.html#index397 +pwevr-list breakpoints) +part8.html#index398 +pwl t1 l1 t2 l2 ... tn) +part8.html#index382 +pwl-list breakpoints) +part8.html#index383 +pwlr i1 l1 i2 l2 ... in) +part8.html#index386 +pwlr-list breakpoints) +part8.html#index387 +pwlv l1 t2 l2 t3 t3 ... tn ln) +part8.html#index384 +pwlv-list breakpoints) +part8.html#index385 +pwlvr l1 i2 l2 i3 i3 ... in ln) +part8.html#index388 +pwlvr-list breakpoints) +part8.html#index389 +quantize sound steps) +part8.html#index530 +quote expr) +part19.html#index1310 +ramp [duration]) +part11.html#index947 +random n) +part19.html#index1473 +read [stream[eof[rflag]]]) +part19.html#index1546 +read-byte [stream]) +part19.html#index1585 +read-char [stream]) +part19.html#index1576 +read-float [stream[length]]) +part19.html#index1582 +read-int [stream[length]]) +part19.html#index1580 +read-line [stream]) +part19.html#index1584 +real-random from to) +part13.html#index1000 +recip sound) +part8.html#index533 +rem expr ...) +part19.html#index1464 +remove expr list :test test :test-not test-not) +part19.html#index1358 +remove-if test list) +part19.html#index1359 +remove-if-not test list) +part19.html#index1360 +remprop sym prop) +part19.html#index1335 +require-from fnsymbol filename [path]) +part13.html#index993 +resample sound srate) +part8.html#index344 +reson sound center bandwidth n) +part8.html#index419 +rest expr) +part19.html#index1350 +restore fname) +part19.html#index1598 +return [expr]) +part19.html#index1431 +return-from name[value]) +part19.html#index1432 +reverb snd time) +part15.html#index1207 +reverse expr) +part19.html#index1354 +rms sound [rate window-size]) +part8.html#index532 +room ) +part19.html#index1604 +rplaca list expr) +part19.html#index1371 +rplacd list expr) +part19.html#index1372 +rrandom ) +part19.html#index1474 +s-abs sound) +part8.html#index516 +s-add-to expression maxlen filename [offset]) +part8.html#index618 +s-exp sound) +part8.html#index520 +s-log sound) +part8.html#index522 +s-max sound1 sound2) +part8.html#index525 +s-min sound1 sound2) +part8.html#index527 +s-overwrite expression maxlen filename [offset]) +part8.html#index621 +s-plot sound [dur n]) +part8.html#index627 +s-print-tree sound) +part8.html#index630 +s-read filename :time-offset offset :srate sr :dur dur :nchans chans :format format :mode mode :bits n :swap flag) +part8.html#index615 +s-read-reverse filename :time-offset offset :srate sr :dur dur :nchans chans :format format :mode mode :bits n :swap flag) +part15.html#index1183 +s-rest [duration]) +part8.html#index537 +s-reverse snd) +part15.html#index1179 +s-save expression maxlen filename :format format :mode mode :bits bits :swap flag :play play) +part8.html#index611 +s-sqrt sound) +part8.html#index518 +sampler pitch modulation [sample npoints]) +part8.html#index378 +save fname) +part19.html#index1597 +save-lpc-file lpc-iterator filename) +part12.html#index968 +save-workspace ) +part14.html#index1142 +sax step breath-env) +part8.html#index487 +sax-all step breath-env freq-env vibrato-freq vibrato-gain reed-stiffness noise blow-pos reed-table-offset) +part8.html#index488 +sax-freq step breath-env freq-env) +part8.html#index485 +scale scale sound) +part8.html#index345 +scale-db db sound) +part8.html#index346 +scale-srate sound scale) +part8.html#index347 +score-adjacent-events score function :from-index i :to-index j :from-time x :to-time y) +part14.html#index1126 +score-append score1 score2 ...) +part14.html#index1112 +score-apply score function :from-index i :to-index j :from-time x :to-time y) +part14.html#index1127 +score-filter-length score cutoff) +part14.html#index1120 +score-filter-overlap score) +part14.html#index1123 +score-gen :k1 e1 :k2 e2 ...) +part14.html#index1087 +score-get-begin score) +part14.html#index1116 +score-get-end score) +part14.html#index1118 +score-indexof score function :from-index i :to-index j :from-time x :to-time y) +part14.html#index1128 +score-last-indexof score function :from-index i :to-index j :from-time x :to-time y) +part14.html#index1129 +score-merge score1 score2 ...) +part14.html#index1111 +score-must-have-begin-end score) +part14.html#index1119 +score-play score) +part14.html#index1125 +score-print score) +part14.html#index1124 +score-randomize-start score amt :from-index i :to-index j :from-time x :to-time y) +part14.html#index1130 +score-read-smf filename) +part14.html#index1136 +score-repeat score n) +part14.html#index1121 +score-scale score keyword amount :from-index i :to-index j :from-time x :to-time y) +part14.html#index1108 +score-select score predicate :from-index i :to-index j :from-time x :to-time y :reject flag) +part14.html#index1113 +score-set-begin score time) +part14.html#index1115 +score-set-end score time) +part14.html#index1117 +score-shift score offset :from-index i :to-index j :from-time x :to-time y) +part14.html#index1105 +score-sort score [copy-flag]) +part14.html#index1104 +score-sorted score) +part14.html#index1103 +score-stretch score factor :dur dur-flag :time time-flag :from-index i :to-index j :from-time x :to-time y) +part14.html#index1106 +score-stretch-to-length score length) +part14.html#index1122 +score-sustain score factor :from-index i :to-index j :from-time x :to-time y) +part14.html#index1109 +score-transpose score keyword amount :from-index i :to-index j :from-time x :to-time y) +part14.html#index1107 +score-voice score replacement-list :from-index i :to-index j :from-time x :to-time y) +part14.html#index1110 +score-write-smf score filename [programs]) +part14.html#index1138 +second expr) +part19.html#index1347 +Self +part19.html#index1286 +seq beh1 [beh2 ...]) +part8.html#index574 +seqrep var limit beh) +part8.html#index575 +set sym expr) +part19.html#index1318 +set-control-srate rate) +part8.html#index294 +set-difference a b) +part14.html#index1155 +set-logical-stop beh time) +part8.html#index579 +set-pitch-names ) +part8.html#index298 +set-sound-srate rate) +part8.html#index296 +setdir path[verbose]) +part19.html#index1562 +setf [place expr] ...) +part19.html#index1321 +setq [sym expr] ...) +part19.html#index1319 +setup-console ) +part19.html#index1614 +sf-granulate filename grain-dur grain-dev ioi ioi-dev pitch-dev [file-start file-end]) +part15.html#index1202 +sf-info filename) +part8.html#index624 +shape signal table origin) +part8.html#index425 +shift-time sound shift) +part8.html#index348 +show-lpc-data lpc-iterator iniframe endframe [poles?]) +part12.html#index969 +sim [beh1 beh2 ...]) +part8.html#index576 +simrep var limit beh) +part8.html#index577 +sin expr) +part19.html#index1476 +sine pitch [duration]) +part8.html#index357 +siosc pitch modulation tables) +part8.html#index376 +sitar step dur) +part8.html#index512 +slope signal) +part8.html#index352 +snd-abs sound) +part8.html#index644 +snd-add sound1 sound) +part8.html#index648 +snd-allpoles snd lpc-coefs gain) +part12.html#index977 +snd-alpass sound delay feedback) +part8.html#index713 +snd-alpasscv sound delay feedback) +part8.html#index714 +snd-alpassvv sound delay feedback maxdelay) +part8.html#index715 +snd-amosc sound step sr hz t0 am phase) +part8.html#index747 +snd-areson sound hz bw normalization) +part8.html#index716 +snd-aresoncv sound hz bw normalization) +part8.html#index717 +snd-aresonvc sound hz bw normalization) +part8.html#index718 +snd-aresonvv sound hz bw normalization) +part8.html#index719 +snd-atone sound hz) +part8.html#index720 +snd-atonev sound hz) +part8.html#index721 +snd-avg sound blocksize stepsize operation) +part8.html#index652 +snd-bandedwg freq bowpress-env preset sr) +part8.html#index757 +snd-biquad sound b0 b1 b2 a1 a2 z1init z2init) +part8.html#index722 +snd-bowed freq bowpress-env sr) +part8.html#index759 +snd-bowed-freq freq bowpress-env freq-env sr) +part8.html#index761 +snd-buzz n sr hz t0 fm) +part8.html#index751 +snd-chase sound risetime falltime) +part8.html#index723 +snd-clarinet freq breath-env sr) +part8.html#index763 +snd-clarinet-all freq vibrato-freq vibrato-gain freq-env breath-env reed-stiffness noise sr) +part8.html#index767 +snd-clarinet-freq freq breath-env freq-env sr) +part8.html#index765 +snd-clip sound peak) +part8.html#index657 +snd-compose f g) +part8.html#index660 +snd-congen gate risetime falltime) +part8.html#index724 +snd-const value t0 srate duration) +part8.html#index633 +snd-convolve sound response) +part8.html#index725 +snd-copy sound) +part8.html#index673 +snd-coterm s1 s2) +part8.html#index637 +snd-delay sound delay feedback) +part8.html#index726 +snd-delaycv sound delay feedback) +part8.html#index727 +snd-down srate sound) +part8.html#index675 +snd-exp sound) +part8.html#index676 +snd-extent sound maxsamples) +part8.html#index256 +snd-fetch sound) +part8.html#index259 +snd-fetch-array sound len step) +part8.html#index261 +snd-fft sound length skip window) +part10.html#index812 +snd-flatten sound maxlen) +part8.html#index262 +snd-flute freq breath-env sr) +part8.html#index768 +snd-flute-all freq vibrato-freq vibrato-gain freq-env breath-env jet-delay noise sr) +part8.html#index772 +snd-flute-freq freq breath-env freq-env sr) +part8.html#index770 +snd-fmfb t0 hz sr index dur) +part8.html#index749 +snd-fmfbv t0 hz sr index) +part8.html#index750 +snd-fmosc s step sr hz t0 fm phase) +part8.html#index748 +snd-follow sound floor risetime falltime lookahead) +part8.html#index677 +snd-from-array t0 sr array) +part8.html#index252 +snd-fromarraystream t0 sr object) +part8.html#index253 +snd-fromobject t0 sr object) +part8.html#index254 +snd-gate sound lookahead risetime falltime floor threshold) +part8.html#index680 +snd-ifft time srate iterator skip window) +part10.html#index814 +snd-inverse signal start srate) +part8.html#index684 +snd-length sound maxlen) +part8.html#index263 +snd-log sound) +part8.html#index685 +snd-lpanal samps npoles) +part12.html#index976 +snd-lpreson snd lpc-iterator skiptime) +part12.html#index978 +snd-mandolin t0 freq dur body-size detune sr) +part8.html#index774 +snd-max expression maxlen) +part8.html#index688 +snd-maxsamp sound) +part8.html#index264 +snd-maxv sound1 sound2) +part8.html#index690 +snd-modalbar t0 freq preset dur sr) +part8.html#index776 +snd-multiseq array closure) +part8.html#index785 +snd-normalize sound) +part8.html#index692 +snd-offset sound offset) +part8.html#index649 +snd-oneshot sound threshold ontime) +part8.html#index693 +snd-osc s step sr hz t0 d phase) +part8.html#index753 +snd-overwrite expression maxlen filename offset format mode bits swap) +part8.html#index636 +snd-partial sr hz t0 env) +part8.html#index754 +snd-play expression) +part8.html#index265 +snd-pluck sr hz t0 d final-amp) +part8.html#index752 +snd-print expression maxlen) +part8.html#index274 +snd-print-tree sound) +part8.html#index266 +snd-prod sound1 sound2) +part8.html#index696 +snd-pwl t0 sr lis) +part8.html#index699 +snd-quantize sound steps) +part8.html#index701 +snd-read filename offset t0 format channels mode bits swap sr dur) +part8.html#index634 +snd-recip sound) +part8.html#index702 +snd-resample f rate) +part8.html#index703 +snd-resamplev f rate g) +part8.html#index705 +snd-reson sound hz bw normalization) +part8.html#index728 +snd-resoncv sound hz bw normalization) +part8.html#index729 +snd-resonvc sound hz bw normalization) +part8.html#index730 +snd-resonvv sound hz bw normalization) +part8.html#index731 +snd-samples sound limit) +part8.html#index268 +snd-save expression maxlen filename format mode bits swap play) +part8.html#index635 +snd-sax freq breath-env sr) +part8.html#index778 +snd-sax-all freq vibrato-freq vibrato-gain freq-env breath-env reed-stiffness noise blow-pos reed-table-offset sr) +part8.html#index781 +snd-sax-freq freq freq-env breath-env sr) +part8.html#index780 +snd-scale scale sound) +part8.html#index708 +snd-seq sound closure) +part8.html#index784 +snd-set-latency latency) +part8.html#index316 +snd-set-logical-stop sound time) +part8.html#index276 +snd-shape signal table origin) +part8.html#index709 +snd-sine t0 hz sr d) +part8.html#index755 +snd-siosc tables sr hz t0 fm) +part8.html#index756 +snd-sitar t0 freq dur sr) +part8.html#index782 +snd-slider index t0 srate duration) +part8.html#index643 +snd-sqrt sound) +part8.html#index646 +snd-srate sound) +part8.html#index271 +snd-sref sound time) +part8.html#index277 +snd-stkchorus sound delay depth freq mix sr) +part8.html#index732 +snd-stkpitshift sound shift mix sr) +part8.html#index736 +snd-stkrev rev-type sound decay mix sr) +part8.html#index740 +snd-stop-time sound) +part8.html#index278 +snd-t0 sound) +part8.html#index273 +snd-tapf sound offset vardelay maxdelay) +part8.html#index670 +snd-tapv sound offset vardelay maxdelay) +part8.html#index665 +snd-time sound) +part8.html#index272 +snd-tone sound hz) +part8.html#index744 +snd-tonev sound hz) +part8.html#index746 +snd-trigger s closure) +part8.html#index786 +snd-up srate sound) +part8.html#index710 +snd-white t0 sr d) +part8.html#index640 +snd-xform sound sr time start stop scale) +part8.html#index711 +snd-yin sound minstep maxstep rate) +part8.html#index712 +snd-zero t0 srate) +part8.html#index641 +soften-clipping snd cutoff) +part15.html#index1172 +sort list test) +part19.html#index1377 +sound sound) +part8.html#index320 +sound-off ) +part8.html#index610 +sound-on ) +part8.html#index609 +sound-srate-abs srate beh) +part8.html#index559 +sound-warp warp-fn signal [wrate]) +part8.html#index349 +soundfilename name) +part8.html#index626 +soundp sound) +part8.html#index279 +span snd amt) +part15.html#index1225 +speed-dial thelist) +part15.html#index1212 +sqrt expr) +part19.html#index1482 +sref sound time) +part8.html#index248 +sref-inverse sound value) +part8.html#index250 +stats ) +part8.html#index280 +step-to-hz pitch) +part8.html#index302 +stereo-chorus snd) +part15.html#index1190 +stereoize snd) +part15.html#index1217 +stkchorus sound depth freq mix [delay]) +part8.html#index466 +strcat expr ...) +part19.html#index1505 +streamp expr) +part19.html#index1392 +stretch factor beh) +part8.html#index561 +stretch-abs factor beh) +part8.html#index562 +string expr) +part19.html#index1495 +string-downcase str :start start :end end) +part19.html#index1502 +string-equalp str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1516 +string-greaterp str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1519 +string-left-trim bag str) +part19.html#index1499 +string-lessp str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1514 +string-not-equalp str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1517 +string-not-greaterp str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1515 +string-not-lessp str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1518 +string-right-trim bag str) +part19.html#index1500 +string-search pat str :start start :end end) +part19.html#index1496 +string-trim bag str) +part19.html#index1498 +string-upcase str :start start :end end) +part19.html#index1501 +string/= str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1511 +string< str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1508 +string<= str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1509 +string= str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1510 +string> str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1513 +string>= str1 str2 :start1 start1 :end1 end1 :start2 start2 :end2 end2) +part19.html#index1512 +stringp expr) +part19.html#index1389 +sublis alist expr :test test :test-not test-not) +part19.html#index1369 +subseq string start[end]) +part19.html#index1507 +subsetp a b) +part14.html#index1156 +subst to from expr :test test :test-not test-not) +part19.html#index1368 +sum a [b ...]) +part8.html#index580 +sustain factor beh) +part8.html#index563 +sustain-abs factor beh) +part8.html#index567 +swapchannels snd) +part15.html#index1226 +symbol-function sym) +part19.html#index1329 +symbol-name sym) +part19.html#index1327 +symbol-plist sym) +part19.html#index1330 +symbol-value sym) +part19.html#index1328 +symbolp expr) +part19.html#index1380 +tagbody expr ...) +part19.html#index1433 +tan expr) +part19.html#index1478 +tapv sound offset vardelay maxdelay) +part8.html#index451 +terpri [stream]) +part19.html#index1551 +third expr) +part19.html#index1348 +throw sym[expr]) +part19.html#index1419 +timed-seq score) +part8.html#index587 +tone sound cutoff) +part8.html#index415 +top-level) +part19.html#index1447 +trace sym) +part19.html#index1441 +transpose amount beh) +part8.html#index568 +transpose-abs amount beh) +part8.html#index569 +trigger s beh) +part8.html#index578 +truncate expr) +part19.html#index1456 +type-of expr) +part19.html#index1605 +union a b) +part14.html#index1152 +unless texpr expr ...) +part19.html#index1411 +untrace sym) +part19.html#index1442 +unwind-protect expr cexpr ...) +part19.html#index1420 +upper-case-p chr) +part19.html#index1522 +vector expr ...) +part19.html#index1339 +warp fn beh) +part8.html#index570 +warp-abs fn beh) +part8.html#index571 +wg-glass-harm step bowpress-env) +part8.html#index506 +wg-tibetan-bowl step bowpress-env) +part8.html#index508 +wg-tuned-bar step bowpress-env) +part8.html#index504 +wg-uniform-bar step bowpress-env) +part8.html#index502 +when test action) +part19.html#index1410 +when texpr expr ...) +part19.html#index1410 +while test expr1 expr2 ...) +part13.html#index991 +widen snd amt) +part15.html#index1220 +write-byte byte[stream]) +part19.html#index1586 +write-char ch[stream]) +part19.html#index1579 +write-float ch[stream[length]]) +part19.html#index1583 +write-int ch[stream[length]]) +part19.html#index1581 +yin sound minstep maxstep stepsize) +part8.html#index539 +zerop expr) +part19.html#index1398 diff --git a/jnyqide/Pair.java b/jnyqide/Pair.java new file mode 100644 index 0000000..ca1caa9 --- /dev/null +++ b/jnyqide/Pair.java @@ -0,0 +1,38 @@ +package jnyqide; + +import java.io.*; +import java.util.*; + +public class Pair +{ + private double time, value; + + public Pair(){ + time = 0; + value = 0; + } + + public Pair(double t, double v){ + + if (t < 0) { + System.out.println("Warning: negative time scale input."); + } + + // plotted functions are not signals, so you shouldn't expect them to stay within [-1, 1] + //if (v < -1 || v > 1){ + // System.out.println("Warning: Value is out of bounds."); + //} + + time = t; + value = v; + } + + public double getTime(){ + return time; + } + + public double getValue(){ + return value; + } + +} \ No newline at end of file diff --git a/jnyqide/Piano_Roll.java b/jnyqide/Piano_Roll.java new file mode 100755 index 0000000..b2844ac --- /dev/null +++ b/jnyqide/Piano_Roll.java @@ -0,0 +1,1104 @@ +/* + * Ming Yang Koh (mykoh@andrew.cmu.edu) + * Eugene Ang (ewee@andrew.cmu.edu) + * Priscilla (cyp@andrew.cmu.edu) + * + * PianoRoll application which takes in an array of strings + * and creates a graphical representation of a piano roll + * + */ + + /* SOME NOTES BY ROGER B. DANNENBERG: + + This software is not ready for real use. + Some problems include: + 1) there's no way to zoom in on scores or scroll the score view + 2) there's no display of pitch information + 3) there's no way to edit anything but pitch and time + 4) there's no way to copy a note and its attributes, so any new note + will lack attributes that might be necessary + 5) there's no color coding of note types, e.g. instrumentation + 6) everytime you modify the score, the score is written to a file; + instead the file should be written explicitly + 7) when the file is written, you should tell Nyquist to evaluate + (score-restore) to read in the score and assign it to the global + variable it came from + 8) the score write command probably does not put the score name + (a lisp variable name) as the first line + 9) it looks like there's one representation for the score data + as read from the file and another for a display list -- this + should be simplified to one structure with accessor methods + if necessary to translate into different representation for display + 10) the score window should be resizable + 11) should the score window be a subwindow to the jNyqIDE main window? + + How does it work? See xm.lsp for SCORE-EDIT, the function that you + call to open a score editor, and SCORE-RESTORE, the function this + editor should call to return score data to Nyquist. Also see + NyquistThread.java for code that opens the score editor. Look for + "score-edit: writing " around line 230. + */ + +package jnyqide; +import java.io.*; +import java.awt.event.MouseListener; +import java.awt.event.MouseEvent; +import java.awt.event.WindowListener; +import java.awt.event.WindowEvent; +import java.awt.*; +import javax.swing.*; +import java.util.StringTokenizer; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + +public class Piano_Roll { + + // global variable to store the String + // for the time being, the Invariant will be, each String will + // contain 3 ints: x, y, and duration. + + // let user click and select centre left or right. center is to move to new location + // left and right is for user to drag along the axis + // start of global variables in Piano_Roll class + static ScoreManipulator sm = new ScoreManipulator(); + static Piano_Roll.ScoreManipulator.Event[] inputArray = new Piano_Roll.ScoreManipulator.Event[0]; + static int currentOption = 2; // 0 = add, 1 = delete, 2 = arrange + + //static Piano_Roll.ScoreManipulator.Event[] inputArray = new Piano_Roll.ScoreManipulator.Event[0]; + static String filename; + static String scoreName; + + // START OF BAOPANEL CLASS + static class BaoPanel extends JPanel implements MouseListener + { + private static final long serialVersionUID = 1L; + // for dragNotStretch : 0 = drag, 1 = stretch from + // left(change start time), 2 = stretch from right(change dur) + private int dragNotStretch; + private int pitchStartCoord = 500, + pitchHeight = 10, + WINDOWWIDTH = 1024, + maxClickableWidth = 946, + lengthUnit = 3; + /* + * each box shown on screen is 3 pixels wide + * each box represents 0.1 seconds + * the screen will hold approximately 90 seconds of music + */ + private int selectedIndex = -1, lastClickedX; + + /*drawing horizontal lines of grid + * if pitchHeight is 10, then there will be... + * 49 segments. 49 pitches + 1 pitchless + * A1 to G7 + */ + + + // START OF PAINTCOMPONENT FUNCTION TO DRAW OUT THE SCREEN + protected void paintComponent (Graphics g) { + int inputArrayLength = inputArray.length; + int tempX, tempY, tempDur; + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + Color oldColor = g2.getColor(); + g2.setColor(Color.BLACK); + + // drawing horizontal lines of grid + for(int i=20; i <= pitchStartCoord; i+= pitchHeight){ + g2.draw3DRect(0, i-10, WINDOWWIDTH, pitchHeight, false); + } + + /* drawing vertical lines of grid, + * as well as the blue vertical markers + * to mark out every second + */ + for(int i=0, j=0; i <= WINDOWWIDTH; i += lengthUnit, j++){ + if(j == 15){ + g2.setColor(Color.BLUE); + g2.draw3DRect(i, 10, 1, pitchStartCoord, false); + j = 0; + g2.setColor(Color.BLACK); + } + g2.draw3DRect(i, 10, lengthUnit, pitchStartCoord, false); + } + + + g2.setColor(Color.BLUE); + + //drawing the notes onto the grid + for(int i = 0; i < inputArrayLength; i++){ + tempX = inputArray[i].getTime(); + tempY = pitchHeight * (inputArray[i].getPitch()); + tempDur = inputArray[i].getDur(); + + /* the lowest pitch starts from bottom + * need to check if its zero, if so, then plot it in special area. + * this for loop is also responsible to draw the yellow sides + * for user to recognise that its the area for stretching notes + */ + if(tempY != 0) { + g2.fill3DRect(tempX+lengthUnit, (tempY+10), + (tempDur-(2*lengthUnit)), 10, false); + g2.setColor(Color.YELLOW); + g2.fill3DRect(tempX, (tempY+10), lengthUnit, 10, false); + g2.fill3DRect((tempX+tempDur-lengthUnit), + (tempY+10), lengthUnit, 10, false); + g2.setColor(Color.BLUE); + } + else{ + g2.setColor(Color.BLACK); + g2.fill3DRect(tempX, (tempY+10), tempDur, 10, false); + g2.setColor(Color.BLUE); + } + } + + + // setting back colour to prevent future + // screw-ups, eg, the border colours etc.. + g2.setColor(oldColor); + addMouseListener(this); + } + + // START OF DETERMINEACTION FUNCTION FOR DIFFERENTIATING + // DRAG AND STRETCH.. + private void determineAction(MouseEvent e){ + int arraySize = inputArray.length; + for(int i = 0; i < arraySize; i++){ + if(inputArray[i].checkWithinDuration(e.getX(), e.getY())){ + selectedIndex = i; + dragNotStretch = inputArray[i].checkDragNotStretch(e.getX(), e.getY()); + + return; + } + } + } + + /* whenever theres a change in the array, + * 1) change the array, + * 2) as well as call the function to notify's eugene's part + */ + + + /* + * START OF MOUSELISTENERS + * RESPONSIBLE FOR ALL THE USER INPUTS/CHANGES + * TO THE SCORE + */ + + /* + * mouseReleased basically first differentiates + * different actions before doing anthing, that + * refers to: add, delete or drag/stretch + * + * then, it will proceed to do the specifed action + * within the case of drag/stretch, then the code + * will differentiate drag or stretch and proceed + * on respectively + * + * the check of selectedIndex != -1 ensures the user + * is operating on a certain notes. + * + */ + public void mouseReleased(MouseEvent e) { + + // *** IF DRAG/STRETCH + if(currentOption == 2){ + /* + * the following are done in drag/stretch action: + * a)ensure that bounds are kept, ie no + * notes are dragged out of the screen, or + * 'dragged into itself..' + * b)changing the Event in the array and subsequently + * send it to the score through the changeScore, + * add_Event or delete_Event functions + * + */ + + if(selectedIndex != -1){ + int originalTime = inputArray[selectedIndex].getTime(), + originalDur = inputArray[selectedIndex].getDur(), + newX = e.getX(), + newY = e.getY(); + + + if(newX >= maxClickableWidth){ + selectedIndex = -1; + return; + } + // *** DRAG action + if(dragNotStretch == 0){ + int originalPitch = inputArray[selectedIndex].getPitch(); + int newStartTime = newX - lastClickedX + originalTime; + int newPitch = ((newY-10)/10); + + if(newStartTime + inputArray[selectedIndex].getDur() + >= maxClickableWidth){ + selectedIndex = -1; + return; + } + + if((originalPitch == 0) && (((newY - 10)/10) != 0)){ + selectedIndex = -1; + return; + } + + + // the following ensures the notes stay within bounds + if(newStartTime < 0) + newStartTime = 0; + if(newPitch > 49) + newPitch = 49; + else if(newPitch < 0) + newPitch = 1; + + inputArray[selectedIndex].setStartTime(newStartTime); + inputArray[selectedIndex].setPitch(newPitch); + + } + else if(dragNotStretch == 1){ // stretch from left + if(newX > originalTime + originalDur - 12) + newX = originalTime + originalDur - 12; + inputArray[selectedIndex].setDur( + originalDur + originalTime - newX); + inputArray[selectedIndex].setStartTime(newX); + + } + else { // stretch from right + if(newX < originalTime + 12) + newX = originalTime + 12; + inputArray[selectedIndex].setDur(newX - originalTime); + + } + //sends the data back to The middleman to send it back to nyquist + + inputArray = sm.my_score.changeScore( + inputArray[selectedIndex].getIndex(), + inputArray[selectedIndex].getTime(), + inputArray[selectedIndex].getDur(), + inputArray[selectedIndex].getPitch()); + repaint(); + revalidate(); + selectedIndex = -1; //end of drag or stretch. selectedIndex back to -1.. + + sm.writeFile(); + } + } + // *** IF DELETE + else if(currentOption == 1){ + if(selectedIndex != -1){ + + inputArray = sm.my_score.del_Event(inputArray[selectedIndex]); + repaint(); + revalidate(); + //at end. selectedIndex back to -1 + selectedIndex = -1; + sm.writeFile(); + return; + } + } + // *** IF ADD + else if(currentOption == 0){ + int tempY = (e.getY()-10)/10; + if((e.getX() + 20) > maxClickableWidth){ + return; + } + if( !(tempY <= 49 && tempY >=0)){ + return; + } + + inputArray = sm.my_score.add_Event(new + Piano_Roll.ScoreManipulator.Event(e.getX(), tempY, 20 , -1)); + repaint(); + revalidate(); + //at end. selectedIndex back to -1 + selectedIndex = -1; + sm.writeFile(); + return; + } + + } + /* + * mousePressed just does 2 things + * a) determine if its a drag or stretch action, + * as well as determining the Event manipulated + * b) logging down te x-coordinate of the click, + * for use of dragging nicely later + */ + public void mousePressed(MouseEvent e) { + determineAction(e); + lastClickedX = e.getX(); + } + + public void mouseEntered(MouseEvent e) {/* do nothing*/} + public void mouseExited(MouseEvent e) { /* do nothing*/} + public void mouseClicked(MouseEvent e) { /* do nothing*/} + + } + /* + * addComponentsToPane function deals with the layout + * and components outside the grid, such as text, buttons + * and xaxis and yaxis scales.. + * + */ + public static void addComponentsToPane (Container pane) { + // zero is center alignment.... + // can use HTML ways to edit the font/type + JLabel topLabel = new JLabel("" + + "Piano roll display:", 0); + JLabel bottomLabel = new JLabel( + "
    • To stretch, " + + "click on the yellow sections of notes
    • To transpose," + + " click on blue section of notes
    ", 0); + + topLabel.setPreferredSize(new Dimension(1024, 50)); + + JLabel leftPanel = new JLabel(); + JLabel bottomCenterLabel = new JLabel(); + + ImageIcon xAxis = new ImageIcon("xAxis.jpg"); + ImageIcon yAxis = new ImageIcon("xxx.jpg"); + bottomCenterLabel.setIcon(xAxis); + + + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + + // for center panel + JPanel subCenterPanel = new BaoPanel(); + mainPanel.add(bottomCenterLabel, BorderLayout.SOUTH); + mainPanel.add(subCenterPanel, BorderLayout.CENTER); + + + // for left panel + leftPanel.setIcon(yAxis); + leftPanel.setPreferredSize(new Dimension(30, 800)); + + //for bottom panel + JPanel bottomPanel = new JPanel(); + JPanel subBottomPanel = new JPanel(); + bottomPanel.setLayout(new BorderLayout()); + + // setting up the buttons, and adding listeners + JButton okButton = new JButton("Add"); + JButton deleteButton = new JButton("Delete"); + JButton arrangeButton = new JButton("Drag/Stretch"); + + okButton.addActionListener(new okButtonListener( + okButton, deleteButton, arrangeButton)); + deleteButton.addActionListener(new deleteButtonListener( + okButton, deleteButton, arrangeButton)); + arrangeButton.addActionListener(new arrangeButtonListener( + okButton, deleteButton, arrangeButton)); + arrangeButton.setEnabled(false); + subBottomPanel.setLayout(new FlowLayout()); + subBottomPanel.add(okButton); + subBottomPanel.add(deleteButton); + subBottomPanel.add(arrangeButton); + + + // combining the 2 sub panels together to form the bottomPanel + bottomPanel.add(bottomLabel, BorderLayout.CENTER); + bottomPanel.add(subBottomPanel, BorderLayout.EAST); + + JLabel fillerLabel2 = new JLabel(""); + + fillerLabel2.setSize(10, 600); + fillerLabel2.setVisible(true); + + // combining all the panels together to + // form the bulk of the screen + pane.add(topLabel, BorderLayout.NORTH); + pane.add(mainPanel, BorderLayout.CENTER); + pane.add(bottomPanel, BorderLayout.SOUTH); + pane.add(leftPanel, BorderLayout.WEST); + pane.add(fillerLabel2, BorderLayout.EAST); + } + + /* + * below are the 3 listener classes that deal with the 3 main + * operations: add, delete, drag/drop. + * + * what they do is to initialise the buttons and to set + * the respective buttons to become enabled/disabled + * when clicked. + * + * the MouseReleased function will deal with user inputs + * eg, drags or deletes instead of the listeners below + * + */ + private static class okButtonListener implements ActionListener { + private JButton ok, delete, arrange; + + public okButtonListener(JButton ok, JButton delete, JButton arrange){ + this.ok = ok; + this.delete = delete; + this.arrange = arrange; + } + + public void actionPerformed(ActionEvent e){ + currentOption = 0; + ok.setEnabled(false); + delete.setEnabled(true); + arrange.setEnabled(true); + } + } + + private static class deleteButtonListener implements ActionListener { + private JButton ok, delete, arrange; + public deleteButtonListener(JButton ok, JButton delete, JButton arrange){ + this.ok = ok; + this.delete = delete; + this.arrange = arrange; + } + public void actionPerformed(ActionEvent e){ + currentOption = 1; + ok.setEnabled(true); + delete.setEnabled(false); + arrange.setEnabled(true); + } + } + + private static class arrangeButtonListener implements ActionListener { + private JButton ok, delete, arrange; + public arrangeButtonListener(JButton ok, JButton delete, JButton arrange){ + this.ok = ok; + this.delete = delete; + this.arrange = arrange; + } + public void actionPerformed(ActionEvent e){ + currentOption = 2; + ok.setEnabled(true); + delete.setEnabled(true); + arrange.setEnabled(false); + } + } + + + /** + * Create the GUI and show it. For thread safety, + * this method should be invoked from the + * event-dispatching thread. + */ + private static void createAndShowGUI() { + //Create and set up the window. + JFrame.setDefaultLookAndFeelDecorated(true); + JFrame frame = new JFrame("Piano Bao : by Priscilla, Eugene and Damon. "); + frame.setResizable(false); + + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.addWindowListener(new prepareToComeBackListener()); + //Set up the content pane. + //frame is the most most outermost enclosure + frame.getContentPane().setLayout(new BorderLayout()); + addComponentsToPane(frame.getContentPane()); + + //Display the window, crops off exactly where the grid stops printing + frame.setSize(984, 672); + frame.setVisible(true); + } + + + public static void scoreEdit(String scoresaveFilename) { + + //Schedule a job for the event-dispatching thread: + //creating and showing this application's GUI. + + if (scoresaveFilename == null) + { + System.out.println("Error. No file argument."); + return; + } + + filename = scoresaveFilename; + + try + { + BufferedReader in = new BufferedReader(new FileReader(filename)); + scoreName = in.readLine(); + String str; + //make score object + while ((str = in.readLine()) != null) + { + sm.my_score.addNote(sm.makeNote(str)); + } + + in.close(); + + //parse it to Event list, for GUI functions + inputArray = sm.my_score.toEventList(); + + } + catch (IOException e) + { + System.out.println("IOException caught: " + e.getMessage()); + } + + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + createAndShowGUI(); + } + + }); + +} + private static class prepareToComeBackListener implements WindowListener{ + public void windowActivated(WindowEvent e){} + public void windowClosed(WindowEvent e){ + currentOption = 2; + + + } + public void windowClosing(WindowEvent e){/*do nothing*/} + public void windowDeactivated(WindowEvent e){/*do nothing*/} + public void windowDeiconified(WindowEvent e){/*do nothing*/} + public void windowIconified(WindowEvent e){/*do nothing*/} + public void windowOpened(WindowEvent e){/*do nothing*/} + } + +// This is a data structure that stores and +// changes notes from a Nyquist score. It +// nests another data structure, ScoreNote. +public static class ScoreManipulator +{ + + public ScoreNote my_score; // a collection of notes, with functions to + // add, delete and change the collection. + + public ScoreManipulator() + { + my_score = new ScoreNote(); + } + + // takes in a String of the following format: + // start_time duration pitch option_str1 ... option_strn + // and parses it into a Note object. + public Note makeNote(String str) + { + int numTokens; + StringTokenizer st = new StringTokenizer(str); + if ( (numTokens = st.countTokens()) < 3) + { + System.out.println("ERROR in makeNote: some string too short: " + + str); + return null; + } + + String st_time, dur, pitch; + + // the remainder of the string must be the options + String []opts = new String[numTokens - 3]; + + int numOpts = 0; + + st_time = st.nextToken(); + dur = st.nextToken(); + pitch = st.nextToken(); + + while (st.hasMoreTokens()) { + opts[numOpts] = st.nextToken(); + numOpts++; + } + + //System.out.println("st_time " + st_time + " dur " + dur + + // " pitch " + pitch + " opts " + opts); + + double stime = Double.parseDouble(st_time); + double duration = Double.parseDouble(dur); + int ptch = -9999; + if (!pitch.equals("NIL")) ptch = Integer.parseInt(pitch); + + return new Note(stime,duration,ptch,opts,numOpts); + } + + public void writeFile() + { + try { + FileWriter fwr = new FileWriter(filename); + fwr.write(my_score.writeScore()); + fwr.close(); + } + catch (IOException e) { + System.out.println("writeFile: IOException."); + } + + } + + + // The Note class stores information about a Nyquist + // score note such that it is easy to access the fields + // that we need in this piano roll application. + // Notice that the field pitch can be zero (0). + public class Note + { + + // fields + private double start_time; // Note's starting time + private double duration; + private int pitch, numopts; + private String []options; // all other information that the piano roll will + // not use, but that we must preserve + + public Note(double st_time, double dur, int pitch, String []opts, int numopts) + { + start_time = st_time; + duration = dur; + this.pitch = pitch; + this.numopts = numopts; + options = opts; + } + + //accessors + public double get_start() + { + return start_time; + } + + public double get_dur() + { + return duration; + } + + public int get_pitch() + { + return pitch; + } + + public int get_numopts() + { + return numopts; + } + + public String [] get_opts() + { + return options; + } + + // for debugging + public void PrintNote() + { + System.out.print("Start: " + start_time + " Duration: " + duration + + " Pitch: " + pitch); + for (int i = 0; i < numopts; i++) + { + System.out.print(" Opt string " + i + ": " + options[i]); + } + System.out.println(); + } + + } + + + // ScoreNote is a collection of notes. + // It also has a collection of functions + // such as add, delete and change that + // is used by the GUI functions to change + // the score when the user drags/shifts/adds/ + // deletes notes. + public class ScoreNote + { + private Note[] score; // the collection of notes + private int num_notes; // capacity of the score + private int notes_used; // number of notes in the + // collection that are + // presently non-empty. + + public ScoreNote() + { + num_notes = 0; + notes_used = 0; + score = new Note[0]; + } + + //adds a Note to the data structure sorted + //in order of start time. + //Invariant: score starts out sorted. This is + //true at the start => invariant is preserved + //each time we call this + public void addNote(Note newnote) + { + // If there exists a note in the score of the exact + // pitch duration and start time, then don't add it + // in. + for(int j = 0; j < notes_used; j++) { + if(score[j].get_start() == newnote.get_start() + && score[j].get_pitch() == newnote.get_pitch() + && score[j].get_dur() == newnote.get_dur()){ + return; + + } + } + + if (notes_used >= num_notes) + { + if (notes_used == 0) + { + score = new Note[10]; + num_notes = 10; + } + else + { + Note [] tempscore = new Note[num_notes * 2]; + for (int i = 0; i < notes_used; i++) + { + tempscore[i] = score[i]; + } + score = tempscore; + num_notes *= 2; + } + } + + for (int i = 0; i < notes_used; i++) + { + // when we find the index that newnote should be in, + // place it there and return + if (score[i].get_start() >= newnote.get_start()) + { + shift_right(i); + score[i] = newnote; + notes_used++; + return; + } + } + + // otherwise, newnote's start time is + // the largest in the score, and we + // put it at the back of the array. + score[notes_used] = newnote; + notes_used++; + } + + // shifts all notes in the array after and including + // index by one to the right. + public void shift_right(int index) + { + for (int i = notes_used - 1; i >= index; i--) + { + score[i+1] = score[i]; + } + + } + + // deletes the note specified by index from the score + // while maintaining the invariant that notes in score + // are sorted by start time. + public void delNote(int index) + { + if (index < 0 || index >= notes_used) + { + System.out.println("del_note: Error! index out of bounds!"); + return; + } + + shift_left(index); + notes_used--; + } + + // shifts all notes in score after + // index by one to the left. + public void shift_left(int index) + { + for (int i = index; i < notes_used; i++) + { + score[i] = score[i+1]; + } + + } + + // accessor for number of used notes in the score + public int getLength() + { + return notes_used; + } + + // accessor for a note at the particular index + public Note getNote(int index) + { + if (index < 0 || index >= notes_used) + { + System.out.println("getNote: trying to index note out of bounds!"); + return null; + } + + return score[index]; + } + + // makes an incremental change to the score, but makes sure to + // preserve the invariant that score remains sorted by start time. + public Event[] changeScore(int index, int new_start, int new_dur, int new_pitch) + { + if (index < 0 || index >= notes_used) + { + System.out.println("changeScore: index out of bounds!"); + return null; + } + + // make the new note + Note note = new Note( (double)(new_start / 10), (double)(new_dur / 10), + convertPitch(new_pitch), score[index].get_opts(), + score[index].get_numopts() ); + + // delNote and addNote both preserve the invariant that + // the notes in score are sorted in order of start time. + delNote(index); + addNote(note); + + // add one more layer of abstraction for the convenience of + // the GUI functions, by using Event objects rather than + // Note objects. The difference is basically in the standards + // of time and note values, documented below. + return toEventList(); + } + + // converts from a MIDI note to a note in + // our representation and vice versa. + public int convertPitch(int pitch) + { + if (pitch == 0) + return pitch; + + return 84 - (pitch - 1); + } + + // Gets the list for the GUI functions to manipulate. + // Invariant: the size of the event list returned is + // exactly the number of notes in our score. + public Event [] toEventList() + { + Event [] result = new Event[notes_used]; + int num_events = 0; + + for (int i = 0; i < notes_used; i++) + { + Note temp = score[i]; + + // Note: we multiply by 10 for convenience of computation, + // as Event stores time and duration as integers, not doubles. + int start = (int)(temp.get_start() * 10); + int dur = (int)(temp.get_dur() * 10); + Event new_event = new Event(start,convertPitch(temp.get_pitch()),dur,i); + result[i] = new_event; + num_events++; + + } + + // size the array + return shape_Event_List(result,num_events); + } + + // The original event list may have some redundant + // blank entries at the end. We use this shape_Event_List + // to size it nicely to the number of events that are actually + // needed. + public Event [] shape_Event_List(Event [] original, int num_events) + { + if (original == null) + { + System.out.println("shape_Event_List: null array given."); + return null; + } + + Event [] result = new Event [num_events]; + + for (int i = 0; i < num_events; i++) + { + result[i] = original[i]; + } + return result; + } + + // When the user clicks to add a new note, + // this function is called to add an event into the + // existing Event array. + public Event [] add_Event(Event e) + { + + // create new note + String [] def_string = new String[1]; + def_string[0] = "(NOTE)"; + Note newnote = new Note(e.getTime()/10, + e.getDur()/10, + convertPitch(e.getPitch()), + def_string, + 1); + + // add it to score + addNote(newnote); + + // return new list of events + return toEventList(); + } + + // When user clicks to delete a note from + // the piano roll, this function is called + // to cleanly remove the event, maintaining + // the invariant that the notes in score are + // sorted in order of start time. + public Event [] del_Event(Event e) + { + delNote(e.getIndex()); + return toEventList(); + } + + // This function outputs a string + // that represents the score + // in the format of the default file + // from which we parsed the original score + public String writeScore() + { + String result = scoreName + "\n"; + for (int i = 0; i < notes_used; i++) + { + result += Double.toString(score[i].get_start()); + result += " "; + result += Double.toString(score[i].get_dur()); + result += " "; + if (score[i].get_pitch() == -9999) result += "NIL"; + else result += Integer.toString(score[i].get_pitch()); + for (int j = 0; j < score[i].get_numopts(); j++) + { + result += " "; + result += (score[i].get_opts())[j]; + } + result += "\n"; + } + return result; + } + + // debugging function + public void PrintScore() + { + System.out.println("Printing Score.."); + System.out.println("Variables: notes_used = " + notes_used + + " num_notes = " + num_notes); + for (int i = 0; i < notes_used; i++) + { + Note temp = getNote(i); + temp.PrintNote(); + } + System.out.println("Done Printing Score!"); + } + + } + + + /* + the Event class, which defines a stretch of note on the piano roll + 15-392 - Pianobao project + + Most of the fields in the Event object are derived from + those in the Note class. The GUI functions use Events as + the representation of the actual Note, for simplicity. + For example, start time and duration are ints in Event + but are doubles in Note. Also, the values of start time and + duration are 10 times larger than its counterparts in Note + because the scaling prevents the notes from being too small + in the piano roll picture. + + Another point to note is that the pitch in Event is not + in standard MIDI format, while that in Note is. This is + because it was easier to use a range of 0-49 (these are + graphical coordinates) when plotting the pitch-axis in + a GUI, and this range corresponds to the MIDI pitches + 36-84 (C2 -> C4). + + The index field the index of the array in which this Event + resides. This is for book-keeping purposes. + the values stored in this Event object is a graphical location + on the interface. A set of value converters will parse these + coordinates into actual musical values when we need to update + the score in Nyquist. + + */ + + + public static class Event { + private int time, pitch, dur, index; + + + public Event(int startTime, int givenPitch, int duration, int index) { + time = startTime; + pitch = givenPitch; + dur = duration; + this.index = index; + } + + public Event(int startTime, int givenPitch) { + time = startTime; + pitch = givenPitch; + dur = 1; + } + + /* + checks whether the given x and y coordiante is within this particular event + 20 is the pitchHeight. Basically works by checking whether the coordinates + clicked is within the rectangle of the Event on screen + + */ + public boolean checkWithinDuration(int timeX, int pitchY) { + + return (((pitchY) <= ((pitch*10) + 20 )) && + (pitchY >= ((10*pitch) + 10)) && + (timeX >= time) && + (timeX <= (time + dur)) + ); + } + + // uses coordinates of user's click to determine whether + // user intends to drag the note or stretch its duration. + // returns : 0 if drag, + // 1 if stretch from left, + // 2 if stretch from right (change dur) + public int checkDragNotStretch(int timeX, int pitchY) { + if ((timeX <= (time+3)) && (timeX >= time)) { + return 1; + } + if ((timeX <= (time + dur)) && (timeX >= dur + time - 3)){ + return 2; + } + return 0; + } + + //accessors + public int getTime() { + return time; + } + + public int getPitch() { + return pitch; + } + + public int getDur() { + return dur; + } + + public int getIndex() { + return index; + } + + //mutators + public void editEvent(int startTime, int givenPitch, int duration) { + time = startTime; + pitch = givenPitch; + dur = duration; + return; + } + + public void setDur(int duration) {dur = duration;} + public void setStartTime(int startTime) {time = startTime;} + public void setPitch(int newPitch) {pitch = newPitch;} + public void setIndex(int newIndex) {index = newIndex;} + + public String toString(){ + return "Event of Pitch: " + pitch + " , start time = " + time + " , duration = " + + dur + ", index = " + index + "\n"; + } + + } + // end of Event class + + + } + + +} + diff --git a/jnyqide/PlotFrame.java b/jnyqide/PlotFrame.java new file mode 100644 index 0000000..866cebd --- /dev/null +++ b/jnyqide/PlotFrame.java @@ -0,0 +1,333 @@ +package jnyqide; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +// Note: originally this code put plots in JInternalFrames. The code to +// support this is commented out and marked with "JPANEL:" + +public class PlotFrame extends JPanel { //JPANEL: JInternalFrame { + + double minX, minY, height, width; // range of data values to be plotted + double minXlabel, minYlabel, xSpacing, ySpacing; + int numXlines, numYlines; // number of lines to be plotted + double minLabel, spacing; // computed by AxisLayout + int numLines; // computed by AxisLayout + double xExtent, yExtent; // value range of plot area + Vector data; + PlotMouseAdapter mouse; + Graphics g; // the whole thing, including labels + Graphics gGraph; // the graph image without labels + Image buffer; + Image graphBuffer; + int bufferHeight; // size of plot with labels + int bufferWidth; // size of plot with labels + //JPANEL: int offsetWindowSide = 3; // To clear the side bar + //JPANEL: int offsetWindowTop = 21; // To clear the title bar + int offsetX = 40; // how wide is label space to left of gGraph + int offsetRight = 10; // how wide is space to right of gGraph + int offsetY = 5; // how high is space above of gGraph + int dotSize = 3; // diameter of data points on the plot image + int textHeight = 20; + // width of plot area (without labels) + int graphBufferWidth; + // height of plot area (without labels) + int graphBufferHeight; + int axisMinSpacing = 30; + //JPANEL: int gadgetHeight = 10; + + public void CalcBufferSize() + { + graphBufferWidth = bufferWidth - offsetX - offsetRight; + graphBufferWidth = Math.max(10, graphBufferWidth); + graphBufferHeight = bufferHeight - textHeight; //JPANEL: - gadgetHeight; + graphBufferHeight = Math.max(10, graphBufferHeight); + } + + + public PlotFrame(JPanel jPanel) { + minX = 0; + minY = -1; + width = 1; + height = 2; + xExtent = 1; + yExtent = 2; + data = new Vector(); + data.add(new Pair(0.0, 0.0)); + data.add(new Pair(1.0, 0.0)); + mouse = new PlotMouseAdapter(this); + setPreferredSize(new Dimension(400, 100)); + // setResizable(true); + addMouseMotionListener(mouse); + addMouseListener(mouse); + setVisible(true); + jPanel.add(this, BorderLayout.CENTER); + CalcBufferSize(); + + renderGraph(); + } + + public void PlotData(Vector d, double minx, double miny, + double maxx, double maxy) { + //System.out.println("PlotData called."); + minX = minx; + minY = miny; + height = maxy - miny; + width = maxx - minx; + data = d; + //System.out.println("PlotData calling repaint"); + renderGraph(); + repaint(); + } + + + + //JPANEL: This is old code to put a plot in a JInternalFrame + // public PlotFrame(JDesktopPane jDesktop, Vector d, double minx, double miny, + // double maxx, double maxy) { + // minX = minx; + // minY = miny; + // height = maxy - miny; + // width = maxx - minx; + // data = d; + // mouse = new PlotMouseAdapter(this); + // + // setSize(new Dimension(720, 520)); + // //JPANEL: setResizable(true); + // //JPANEL: this.setClosable(true); + // //JPANEL: this.setIconifiable(true); + // + // addMouseMotionListener(mouse); + // addMouseListener(mouse); + // + // //JPANEL: setTitle("Plot"); + // setVisible(true); + // jDesktop.add(this); + // CalcBufferSize(); + // + // renderGraph(); + // } + // + // private int degree(double n) + // { + // int deg = 0; + // while (n < 10) { + // n *= 10.0; + // deg++; + // } + // return deg; + // } + // (END JPANEL:) + + // do label layouts for x and y axes. Returns values by setting + // spacing, minLabel, and numLines + // + public void AxisLayout(int buffersize, int axisMinSpacing, + double minval, double range) + { + if (range < 0.000001) range = 1.0; // convert range of zero + // compute axis layout + // first, figure out about how many label divisions there can be + int nlabels = buffersize / axisMinSpacing; + if (nlabels <= 0) nlabels = 1; // avoid divide by zero + // now figure out what that is in terms of the data + // spacing is a proposed spacing for labels in terms of actual data + spacing = range / nlabels; + // now increase spacing to nearest multiple of 0.1, 0.2, 0.5, ... + // first, get spacing between 0.1 and 1.0 + double tens = 1.0; + //System.out.print("spacing "); System.out.println(spacing); + while (spacing < 0.1) { + spacing = spacing * 10.0; + tens = tens * 0.1; + } + while (spacing > 1.0) { + spacing = spacing * 0.1; + tens = tens * 10.0; + } + // now 0.1 <= spacing <= 1.0, and spacing * tens is original value + // adjust spacing up to 0.2, 0.5, or 1.0 + // this will result in greater than minimum spacing + if (spacing < 0.2) spacing = 0.2; + else if (spacing < 0.5) spacing = 0.5; + else spacing = 1.0; + // now translate back to original power of ten + spacing = spacing * tens; + // figure out minLabel, the first multiple of spacing less or equal to minval + // the extra 0.1% added by multiplying by 1.001 is there so that if + // minval is already very close to a multiple of spacing, it is used + // Sometimes this happens due to floating point rounding even when + // minval is an exact multiple of spacing. + minLabel = ((int) ((minval / spacing) * 1.001)) * spacing; + // (int) rounds toward zero, so if minval is negative, subtract one + if (minLabel > minval + spacing * 0.0001) minLabel -= spacing; + // since spacing may have increased, we may not need so many divisions to + // span the range of the data + numLines = (int) ((minval + range - minLabel) / spacing); + // increase by one in case we rounded down + if (numLines < (minval + range - minLabel) / spacing) numLines += 1; + // increase by one again. E.g. if the graph is divided in two, there are + // three lines. (Always one more line than division.) + numLines += 1; + System.out.print("minLabel "); System.out.print(minLabel); + System.out.print(" spacing "); System.out.println(spacing); + System.out.print(" numLines " + numLines); + } + + public void renderGraph() + { + System.out.println("renderGraph"); + if (gGraph == null) { + System.out.print("creating graphbuffer"); + System.out.print(graphBufferWidth); System.out.print(", "); + System.out.println(graphBufferHeight); + graphBuffer = createImage(graphBufferWidth, graphBufferHeight); + //System.out.println(graphBuffer); + if (graphBuffer == null) return; // Why does this fail? + gGraph = graphBuffer.getGraphics(); + } + + gGraph.setColor(new Color(220, 220, 220)); + gGraph.fillRect(0, 0, graphBufferWidth, graphBufferHeight); + + System.out.println("calling AxisLayout"); + AxisLayout(graphBufferWidth, axisMinSpacing, minX, width); + //System.out.print("return from AxisLayout"); + xExtent = spacing * (numLines - 1); + minXlabel = minLabel; + xSpacing = spacing; + numXlines = numLines; + + AxisLayout(graphBufferHeight, axisMinSpacing, minY, height); + yExtent = spacing * (numLines - 1); + minYlabel = minLabel; + ySpacing = spacing; + numYlines = numLines; + + // draw graph as lines first, then overlay circles + ListIterator iter = data.listIterator(); + Pair prev = (Pair) iter.next(); + int x1 = (int) ((prev.getTime() - minXlabel) / xExtent * graphBufferWidth); + int y1 = (int) ((1.0 - ((prev.getValue() - minYlabel) / yExtent)) * + graphBufferHeight); + Color pointColor = new Color(220, 220, 0); + while (iter.hasNext()) { + Pair p = (Pair) iter.next(); + gGraph.setColor(Color.black); + int x2 = (int) ((p.getTime() - minXlabel) / xExtent * graphBufferWidth); + int y2 = (int) ((1.0 - ((p.getValue() - minYlabel) / yExtent)) * + graphBufferHeight); + gGraph.drawLine(x1, y1, x2, y2); + gGraph.setColor(pointColor); + x1 = x1 - dotSize / 2; + y1 = y1 - dotSize / 2; + gGraph.fillOval(x1, y1, dotSize, dotSize); + gGraph.setColor(Color.black); + gGraph.drawOval(x1, y1, dotSize, dotSize); + x1 = x2; + y1 = y2; + } + // draw the last point + gGraph.setColor(pointColor); + x1 = x1 - dotSize / 2; + y1 = y1 - dotSize / 2; + gGraph.fillOval(x1, y1, dotSize, dotSize); + gGraph.setColor(Color.black); + gGraph.drawOval(x1, y1, dotSize, dotSize); + + double x = minXlabel; + for (int i = 0; i < numXlines; i++) { + //System.out.println(x); + int axisX = (int) (((x - minXlabel) / ((numXlines - 1) * xSpacing)) * + graphBufferWidth + 0.5); + gGraph.setColor(new Color(170, 170, 170)); + gGraph.drawLine(axisX, 0, axisX, graphBufferHeight ); + x += xSpacing; + } + + double y = minYlabel; + for (int i = 0; i < numYlines; i++) { + //double y = minYlabel; y < minYlabel + height; y += ySpacing) { + int axisY = (int) ((1.0 - ((y - minYlabel) / ((numYlines - 1) * ySpacing))) * + graphBufferHeight + 0.5); + gGraph.setColor(new Color(170, 170, 170)); + gGraph.drawLine(0, axisY, graphBufferWidth, axisY ); + y += ySpacing; + } + } + + public void paint(Graphics g2) { + // Graphics g = getContentPane().getGraphics(); + System.out.println("Painting..."); + // because the window can be resized, check if we have the right width and height + //System.out.print("graph dim "); System.out.print(getWidth()); + //System.out.print(", "); System.out.println(getHeight()); + + if ((getHeight() != bufferHeight) || + (getWidth() != bufferWidth)) { + g = null; // delete any existing double buffer to force an update + gGraph = null; // the plot image is here, update this too + //System.out.println("recalculate width and height"); + } + + if (g == null) { // create matching image buffer for double buffer update + bufferHeight = getHeight(); + bufferWidth = getWidth(); + buffer = createImage(bufferWidth, bufferHeight); + g = buffer.getGraphics(); + CalcBufferSize(); + } + + if (gGraph == null) { + renderGraph(); + } + + if (g2 != null) { + g.setColor(new Color(150, 150, 150)); + g.fillRect(0, 0, bufferWidth, bufferHeight); //JPANEL: - gadgetHeight); + + if (gGraph != null) { + g.drawImage(graphBuffer, offsetX, offsetY, offsetX + graphBufferWidth, + offsetY + graphBufferHeight, 0, 0, + graphBufferWidth, graphBufferHeight, this); + } + + double x = minXlabel; + for (int i = 0; i < numXlines; i++) { + int axisX = (int) (((x - minXlabel) / (xSpacing * (numXlines - 1))) * + graphBufferWidth + 0.5); + g.setColor(Color.black); + String s = Double.toString(Math.round(x * 1000) / 1000.0); + g.drawString(s, offsetX + axisX - s.length() * 2 - + (i == numXlines - 1 ? s.length() * 2 : 0), + offsetY + graphBufferHeight + textHeight - 8); + x += xSpacing; + } + + double y = minYlabel; + for (int i = 0; i < numYlines; i++) { + int axisY = (int) (((y - minYlabel) / (ySpacing * (numYlines - 1))) * + graphBufferHeight + 0.5); + g.setColor(Color.black); + String s = Double.toString(Math.round(y * 1000) / 1000.0); + // note: offset top string to fit within graphics area + g.drawString(s, offsetX - s.length() * 5 - 5, + offsetY + graphBufferHeight - axisY + + (i == numYlines - 1 ? textHeight - 8 : 0)); + y += ySpacing; + } + } + super.paint(g2); + //JPANEL: g2.drawImage(buffer, offsetWindowSide, offsetWindowTop, this ); + g2.drawImage(buffer, 0, 0, this ); + } +} diff --git a/jnyqide/PlotMouseAdapter.java b/jnyqide/PlotMouseAdapter.java new file mode 100644 index 0000000..571660a --- /dev/null +++ b/jnyqide/PlotMouseAdapter.java @@ -0,0 +1,67 @@ +package jnyqide; + +import javax.swing.event.MouseInputAdapter; +import java.awt.event.MouseEvent; +import javax.swing.*; + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +public class PlotMouseAdapter extends MouseInputAdapter { + + int dx, dy; + int startx, starty; + int shiftx, shifty; + boolean shifting; + PlotFrame frame; + + public PlotMouseAdapter(PlotFrame f) + { + dx = 0; + dy = 0; + shiftx = 0; + shifty = 0; + shifting = false; + frame = f; + } + + public void mouseDragged(MouseEvent e) + { + System.out.println("mouseDragged"); + if (!shifting) { + shifting = true; + startx = e.getX(); + starty = e.getY(); + } + dx = e.getX() - startx; + dy = e.getY() - starty; + frame.repaint(); + } + + public void mouseClicked( MouseEvent e ) + { + } + + public void mouseReleased( MouseEvent e ) + { + shiftx += dx; + shifty += dy; + shifting = false; + } + + public int getShiftX() + { + return shiftx+dx; + } + + public int getShiftY() + { + return shifty+dy; + } +} \ No newline at end of file diff --git a/jnyqide/PopupListener.java b/jnyqide/PopupListener.java new file mode 100644 index 0000000..7b07792 --- /dev/null +++ b/jnyqide/PopupListener.java @@ -0,0 +1,46 @@ +package jnyqide; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import javax.swing.event.*; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.undo.*; +import jnyqide.*; + +class PopupListener extends MouseAdapter { + JPopupMenu popup; + JTextPane pane; + + PopupListener(JPopupMenu popupMenu, JTextPane textPane) + { + popup = popupMenu; + pane = textPane; + } + + public void mousePressed(MouseEvent e) + { + maybeShowPopup(e); + } + + public void mouseReleased(MouseEvent e) + { + maybeShowPopup(e); + } + + private void maybeShowPopup(MouseEvent e) + { + if (e.isPopupTrigger()) { + MenuElement[] items = popup.getSubElements(); + for (int i = 0; i < items.length; i++) { + String name = items[i].getComponent().getName(); + if (name.equals("context copy") || name.equals("context cut")) { + ((JMenuItem) items[i]).setEnabled(pane.getSelectedText() != + null); + } + } + popup.show(e.getComponent(), e.getX(), e.getY()); + } + } +} \ No newline at end of file diff --git a/jnyqide/PreferencesDialog.java b/jnyqide/PreferencesDialog.java new file mode 100644 index 0000000..fb6b04b --- /dev/null +++ b/jnyqide/PreferencesDialog.java @@ -0,0 +1,426 @@ +/* + * Preferences dialog based on ReplaceDialog.java + */ + +// Current elements are: +// +// Restore Defaults +// [] Automatically insert close-parentheses +// <-|--> Relative height of completion box +// +package jnyqide; + +import java.util.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import java.io.File; + +import com.sun.corba.se.spi.servicecontext.SendingContextServiceContext; + +import jnyqide.*; + +class PreferencesDialog extends JInternalFrame implements ActionListener { + private MainFrame mainFrame; + private JScrollPane scrollPane; + private JPanel panel; + private JButton defaultPrefs; // "Restore Defaults" + private JCheckBox startInSalMode; // "Start in SAL mode (not Lisp)" + private JCheckBox salShowLisp; // "Show translation of SAL to Lisp" + private JCheckBox parenAutoInsert; + // "Automatically insert close-parentheses" + private JCheckBox enableSound; // "Enable sound output in PLAY command" + private JCheckBox autoNorm; // "AutoNorm" + private JCheckBox salTraceBack; // "Print SAL traceback on SAL error" + private JCheckBox salBreak; // "Enable XLISP break on SAL error" + private JCheckBox xlispBreak; // "Enable XLISP break on XLISP error" + private JCheckBox xlispTraceBack; // "Print XLISP traceback on XLISP error" + private JCheckBox printGC; // "Print info about garbage collection" + private JCheckBox fullSearch; + // "Use full search for code completion" + private JCheckBox internalBrowser; + // "Use window in jNyqIDE for help browser" + private JCheckBox onlineManual; + // "Use online manual instead of local copy" + private JScrollBar completionListPercent; + // "Relative height of completion box" + private JComboBox audioRate; // "Audio Sample Rate" + private JTextField controlRate; // "Control Sample Rate" + private JComboBox fontSize; // "Font Size" + private JButton sfDirectory; // "Set Default Sound File Directory" + private JButton initialDirectory; // "Set Initial Directory" + private JFileChooser startfd; + private JFileChooser fd; + private String[] audioRates = { "96000", "48000", "44100", "22050", "16000", + "11025", "8000" }; + private String currentFontSize; + private String[] fontSizes = { "6", "7", "8", "9", "10", "11", "12", "14", + "16", "18", "20", "24", "28", "32", "36" }; + protected JCheckBox makeCheckBox(String doc, boolean val) { + //JPanel contentPane = (JPanel) getContentPane(); + JCheckBox cb = new JCheckBox(doc, val); + cb.setAlignmentX(Component.LEFT_ALIGNMENT); + //contentPane.add(cb); + panel.add(cb); + return cb; + } + + public PreferencesDialog(MainFrame mainFrame_) { + super(); + final PreferencesDialog preferencesDialog = this; + //super(mainFrame_, "Preferences", true); // initialize Dialog + setTitle("Preferences"); + + mainFrame = mainFrame_; + + addInternalFrameListener(new InternalFrameListener() { + public void internalFrameClosing(InternalFrameEvent e) { + mainFrame.prefStartInSalMode = startInSalMode.isSelected(); + + boolean enable = salShowLisp.isSelected(); + mainFrame.setBoolean("*sal-compiler-debug*", enable); + mainFrame.prefSalShowLisp = enable; + + mainFrame.prefParenAutoInsert = parenAutoInsert.isSelected(); + + enable = enableSound.isSelected(); + mainFrame.callFunction( + enable ? "sound-on" : "sound-off", ""); + mainFrame.prefEnableSound = enable; + + enable = autoNorm.isSelected(); + mainFrame.callFunction( + enable ? "autonorm-on" : "autonorm-off", ""); + mainFrame.prefAutoNorm = enable; + + enable = salTraceBack.isSelected(); + mainFrame.callFunction("sal-tracenable", + mainFrame.tOrNil(enable)); + mainFrame.prefSalTraceBack = enable; + + enable = salBreak.isSelected(); + mainFrame.callFunction("sal-breakenable", + mainFrame.tOrNil(enable)); + mainFrame.prefSalBreak = enable; + + enable = (xlispBreak.isSelected() || xlispTraceBack.isSelected()); + mainFrame.callFunction("xlisp-breakenable", + mainFrame.tOrNil(enable)); + mainFrame.prefXlispBreak = enable; + + enable = xlispTraceBack.isSelected(); + mainFrame.callFunction("xlisp-tracenable", + mainFrame.tOrNil(enable)); + mainFrame.prefXlispTraceBack = enable; + + enable = printGC.isSelected(); + if (enable != mainFrame.prefPrintGC) { + mainFrame.setBoolean("*gc-flag*", enable); + mainFrame.prefPrintGC = enable; + } + + mainFrame.prefFullSearch = fullSearch.isSelected(); + + mainFrame.prefInternalBrowser = internalBrowser.isSelected(); + + mainFrame.prefOnlineManual = onlineManual.isSelected(); + + if ((int) mainFrame.prefCompletionListPercent != + (int) (completionListPercent.getValue())) { + mainFrame.prefCompletionListPercent = + completionListPercent.getValue(); + mainFrame.tileCompletion(); + } + + String rateString = (String) audioRate.getSelectedItem(); + //audioRate.setSize(50, 20); + int rate = validate(rateString); + if (rate > 0 && !rateString.equals(mainFrame.prefAudioRate)) { + mainFrame.callFunction("set-sound-srate", rateString); + mainFrame.prefAudioRate = rateString; + } + + rateString = controlRate.getText(); + rate = validate(rateString); + if (rate > 0 && !rateString.equals(mainFrame.prefControlRate)) { + mainFrame.callFunction("set-control-srate ", rateString); + mainFrame.prefControlRate = rateString; + } + + String fontString = (String) fontSize.getSelectedItem(); + int size = validate(fontString); + if (size > 0 && !fontString.equals(mainFrame.prefFontSize)) { + mainFrame.prefFontSize = fontString; + mainFrame.setFontSize(size); + } + + File file = startfd.getSelectedFile(); + + System.out.println("startfd.getSelectedFile() -> " + file); + + if (file != null) { + String dir = file.toString().replaceAll("\\\\", "/"); + System.out.println("startfd.getSelectedFile: " + dir); + if (dir != null && dir.length() > 0) { + mainFrame.prefDirectory = dir; + mainFrame.changeDirectory(dir); + } + } else { + mainFrame.prefDirectory = ""; + } + + file = fd.getSelectedFile(); + if (file != null) { + String dir = file.toString().replaceAll("\\\\", "/"); + System.out.println("fd.getSelectedFile: " + dir); + if (dir != null && dir.length() > 0) { + mainFrame.prefSFDirectory = dir; + mainFrame.setVariable("*default-sf-dir*", + "\"" + dir + "\""); + } + } else { + mainFrame.prefSFDirectory = ""; + } + + mainFrame.prefsHaveBeenSet = true; + dispose(); + } + + public void internalFrameOpened(InternalFrameEvent e) { + } + public void internalFrameClosed(InternalFrameEvent e) { + mainFrame.disconnectPreferences(); + //System.out.println("FrameClosed"); + } + public void internalFrameIconified(InternalFrameEvent e) { + } + public void internalFrameDeiconified(InternalFrameEvent e) { + } + public void internalFrameActivated(InternalFrameEvent e) { + } + public void internalFrameDeactivated(InternalFrameEvent e) { + } + }); + + panel = new JPanel(); + scrollPane = new JScrollPane(panel); + JPanel contentPane = (JPanel) getContentPane(); + contentPane.add(scrollPane, BorderLayout.CENTER); + //contentPane + panel.setLayout( + new BoxLayout(panel, BoxLayout.Y_AXIS)); + + panel.add(new JLabel("Preferences are updated when you close this Preferences Window")); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + + // button to restore default preferences + defaultPrefs = new JButton("Restore Defaults"); + defaultPrefs.addActionListener(this); + defaultPrefs.setAlignmentX(Component.LEFT_ALIGNMENT); + panel.add(defaultPrefs); + + panel.add(Box.createRigidArea(new Dimension(0, 10))); + + // Start in Sal mode (not Lisp)" + startInSalMode = makeCheckBox("Start in SAL mode (not Lisp)", + mainFrame.prefStartInSalMode); + // Show translation of SAL to Lisp + salShowLisp = makeCheckBox("Show translation of SAL to Lisp", + mainFrame.prefSalShowLisp); + // Automatically insert close-parenthesis (checkbox) + parenAutoInsert = makeCheckBox( + "Automatically insert close-parentheses", + mainFrame.prefParenAutoInsert); + // Enable sound output (checkbox) + enableSound = makeCheckBox("Enable sound output in PLAY command", + mainFrame.prefEnableSound); + // AutoNorm (checkbox) + autoNorm = makeCheckBox("AutoNorm", mainFrame.prefAutoNorm); + + // Enable SAL Stack Traceback on Error + salTraceBack = makeCheckBox("Print SAL traceback on SAL error", + mainFrame.prefSalTraceBack); + // break into XLISP debugger on SAL error + salBreak = makeCheckBox("Enable XLISP break on SAL error", + mainFrame.prefSalBreak); + // Enable XLISP Break when XLISP encounters error + xlispBreak = makeCheckBox("Enable XLISP break on XLISP error", + mainFrame.prefXlispBreak); + // print XLISP TraceBack on XLISP error + xlispTraceBack = makeCheckBox("Print XLISP traceback on XLISP error", + mainFrame.prefXlispTraceBack); + // printGC + printGC = makeCheckBox("Print info about garbage collection", + mainFrame.prefPrintGC); + + // Use full search for code completion (checkbox) + fullSearch = makeCheckBox("Use full search for code completion", + mainFrame.prefFullSearch); + // Use internal window for manual (checkbox) + internalBrowser = makeCheckBox("Use window in jNyqIDE for help browser", + mainFrame.prefInternalBrowser); + // Use online manual (checkbox) + onlineManual = makeCheckBox("Use online manual instead of local copy", + mainFrame.prefOnlineManual); + + panel.add(Box.createRigidArea(new Dimension(0, 10))); + + // Relative height of completion box (slider) + panel.add(new JLabel("Relative height of completion box", + JLabel.CENTER)); + completionListPercent = new JScrollBar(JScrollBar.HORIZONTAL, + (int) mainFrame.prefCompletionListPercent, 1, 0, 100); + panel.add(completionListPercent); + + panel.add(Box.createRigidArea(new Dimension(0, 10))); + + // Audio Sample Rate (editable combobox) + panel.add(new JLabel("Audio Sample Rate")); + audioRate = new JComboBox(audioRates); + // Set correct selection + for (int i = 0; i < audioRates.length; i++) { + if (mainFrame.prefAudioRate.equals(audioRates[i])) { + audioRate.setSelectedIndex(i); + break; + } + } + audioRate.setEditable(true); + audioRate.setAlignmentX(Component.LEFT_ALIGNMENT); + audioRate.setMaximumSize( + new Dimension(100, audioRate.getPreferredSize().height)); + panel.add(audioRate); + + panel.add(Box.createRigidArea(new Dimension(0, 10))); + + // Control Rate (text field) + panel.add(new JLabel("Control Sample Rate")); + controlRate = new JTextField(mainFrame.prefControlRate); + controlRate.setAlignmentX(Component.LEFT_ALIGNMENT); + controlRate.setMaximumSize( + new Dimension(100, controlRate.getPreferredSize().height)); + panel.add(controlRate); + + panel.add(Box.createRigidArea(new Dimension(0, 10))); + + // Font Size (editable combobox) + panel.add(new JLabel("Font Size")); + fontSize = new JComboBox(fontSizes); + // Set correct selection + for (int i = 0; i < fontSizes.length; i++) { + if (mainFrame.prefFontSize.equals(fontSizes[i])) { + fontSize.setSelectedIndex(i); + break; + } + } + fontSize.setEditable(true); + fontSize.setAlignmentX(Component.LEFT_ALIGNMENT); + fontSize.setMaximumSize( + new Dimension(100, fontSize.getPreferredSize().height)); + panel.add(fontSize); + + panel.add(Box.createRigidArea(new Dimension(0, 10))); + + // Select Startup Directory (button) + startfd = new JFileChooser("Select Initial Directory"); + startfd.setCurrentDirectory(new File(mainFrame.prefDirectory)); + startfd.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + initialDirectory = new JButton("Set Initial Directory"); + initialDirectory.addActionListener(this); + initialDirectory.setAlignmentX(Component.LEFT_ALIGNMENT); + panel.add(initialDirectory); + + // Select Sound File Output Directory (button) + fd = new JFileChooser("Select Default Soundfile Directory"); + fd.setCurrentDirectory(new File(mainFrame.prefSFDirectory)); + fd.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + sfDirectory = new JButton("Set Default Soundfile Directory"); + sfDirectory.addActionListener(this); + sfDirectory.setAlignmentX(Component.LEFT_ALIGNMENT); + panel.add(sfDirectory); + + panel.add(Box.createVerticalGlue()); + + /* + * The Nyquist IDE has a preferences dialog with a couple of things you + * can change. It would be great to have a graphical way to set things + * like the normalization style, default audio and control sample rates, + * whether to play sounds or save audio to disk or both when calling the + * play function, whether to apply reverb and/or EQ to the output signal + * when using PLAY, a default sound file directory, whether to print a + * stack trace when an error is encountered, etc. (All of these things + * can be set in Nyquist, but most users do not know how.) + */ + + pack(); + Dimension size = new Dimension(400, 400); + setSize(size); + Point mfloc = mainFrame.getLocation(); + setLocation(mfloc.x + 25, mfloc.y + 25); + setResizable(true); + setVisible(true); + setClosable(true); + setMaximizable(true); + setIconifiable(true); + repaint(); + } + + private int validate(String s) { + try { + int temp = Integer.parseInt(s); + if (temp > 0) return temp; + } catch (Exception e) { + } + return -1; + } + + + /* + // On Mac OS X, we can select directories using the native file open dialog + void getDirectoryUsingFileDialog(String title) { + boolean saveUseJFC = Prefs.useJFileChooser; + Prefs.useJFileChooser = false; + System.setProperty("apple.awt.fileDialogForDirectories", "true"); + OpenDialog od = new OpenDialog(title, defaultDir, null); + if (od.getDirectory()==null) + directory = null; + else + directory = od.getDirectory() + od.getFileName() + "/"; + defaultDir = directory; + System.setProperty("apple.awt.fileDialogForDirectories", "false"); + Prefs.useJFileChooser = saveUseJFC; + } + */ + + public void actionPerformed(ActionEvent evt) { + if (evt.getSource() == sfDirectory) { + fd.showOpenDialog(this); + } else if (evt.getSource() == initialDirectory) { + startfd.showOpenDialog(this); + } else if (evt.getSource() == defaultPrefs) { + startInSalMode.setSelected(mainFrame.prefStartInSalModeDefault); + salShowLisp.setSelected(mainFrame.prefSalShowLispDefault); + parenAutoInsert.setSelected( + mainFrame.prefParenAutoInsertDefault); + enableSound.setSelected(mainFrame.prefEnableSoundDefault); + autoNorm.setSelected(mainFrame.prefAutoNormDefault); + salTraceBack.setSelected(mainFrame.prefSalTraceBackDefault); + salBreak.setSelected(mainFrame.prefSalBreakDefault); + xlispBreak.setSelected(mainFrame.prefXlispBreakDefault); + xlispTraceBack.setSelected(mainFrame.prefXlispTraceBackDefault); + printGC.setSelected(mainFrame.prefPrintGCDefault); + fullSearch.setSelected(mainFrame.prefFullSearchDefault); + internalBrowser.setSelected(mainFrame.prefInternalBrowserDefault); + onlineManual.setSelected(mainFrame.prefOnlineManualDefault); + completionListPercent.setValue( + (int) (mainFrame.prefCompletionListPercentDefault + 0.5)); + audioRate.setSelectedItem(mainFrame.prefAudioRateDefault); + controlRate.setText(mainFrame.prefControlRateDefault); + fontSize.setSelectedItem(mainFrame.prefFontSizeDefault); + startfd.setSelectedFile(null); + fd.setSelectedFile(null); + } + } +} diff --git a/jnyqide/README.txt b/jnyqide/README.txt new file mode 100644 index 0000000..3bbe5d3 --- /dev/null +++ b/jnyqide/README.txt @@ -0,0 +1,152 @@ +15-392 Final Project Description + +Dave Mowatt dmowatt@andrew.cmu.edu + +Source Code: + + Main.java - main executable + Creates a MainFrame swing window + + nyquist/ - All the ide files for text editing + nyquist/MainFrame.java - root frame for the IDE + This uses a basic swing interface, with a menu bar, + quick-action buttons, and the basic components of the + nyquist IDE: the input window (upper left), the output + window (left side), and a desktop for all the opened files. + + nyquist/NyquistThread.java - i/o to nyquist executable + Executes nyquist and maintains the input/output streams + for communication to and from the input and output windows + inside of MainFrame. The executable path (currently + "nyquist.exe" or "ny" should be set to reflect whatever + location the nyquist executable is on that particular machine. + + nyquist/NyquistFile.java - data for one open file in nyquist + On a new instance, creates an empty file. Save will write + to the current file unless it is a new file - where SaveAs + will automatically be called. (If the file is new then the + java File file variable will be null) Whenever a file is + modified, a * will be placed next to the file's name in the + title bar. + + nyquist/LispFileFilter.java* - filters out .lsp files. + + colortext/ - All the files relating to text coloring and + paren checking + colortext/SyntaxThread.java - maintains syntax highlighting for + one document + This is also used on the input window, where the paren + balencing is used to prevent invalid input to nyquist. + + colortext/ColorText.java - text highlighting functions + formatAll will go through the entire file to find the balanced + parens, strings, comments, and the keywords. The keywords are + currently in a list at the bottom, just append any missing ones + or read them in from a file. The format() functions take + in the syntax thread that is calling them. This is so they + will automatically exit as soon as the thread's document is + changed. That way if the user types another letter while the + current check is running, it will stop the current one and + start a new check from the beginning. + + + nyquistplot/ - All the files for plotting + nyquistplot/Pair.java - Stores the x, y coordinates of one data point + time is along the x axis, v is along the y axis + + nyquistplot/NyqPlot.java - Handles reading in the data, finding + mins/maxes + Pretty straightforward, reads in the data storing the sonud + data, then creates a graph based on that. + + nyquistplot/PlotFrame.java - Plots a graph of the file + Upon creation, draws the full graph to an image. From then on, + parts of that image are drawn to the double buffered window. + This is so scrolling can be done easily without re-drawing + the image again. The full graph image should be re-drawn + on scaling. + + nyquistplot/PlotMouseAdapter.java* - Handles data for mouse + scrolling/zooming + Counts how far the mouse has been dragged to just store the + change on how far to scroll. + +* not currently used, but the framework is there + +----- design notes for SAL ----- + +to move to SAL, we must support two languages: XLISP and SAL + +when you open an edit window, the type, XLISP or SAL, should become +a property of the window. I think we can just assume XLISP unless +the file extension is SAL. Another option would be to try to detect +the file type if the extension is not .lsp, .sal, or .ny. Maybe we could +compute the ratio of parens to non-parens, but this might fail for +data files (lists of numbers, in XLISP syntax), so we could add other +features like counts of SAL keywords, etc. Let's try the simple +file extension test first. + +When you open a new file, the editor should know whether it's a +new lisp window or a new sal window. We won't support a new +text window, but users can edit text and ignore syntax coloring +if they want to. + +Syntax editor is needed for SAL. Coloring should match SAL examples +on the CLM/SAL web pages, which look very good. + +Indentation should be suggested by the editor when you type newline. +It would be great if TAB would indent the line instead of inserting a TAB. + +The IDE needs know when the user is in SAL mode or LISP mode. SAL +prompts with "SAL>", so the sequence "\nSAL> " should put the IDE +into SAL mode. In SAL mode, the IDE should expect SAL to be +entered into the input window. Input should only be parsed when +the user types two newlines in a row -- that allows multiple line +input. + +Also, in SAL mode, errors need to be detected, parsed, and used +to position the cursor at the error location in an edit window. + +----- notes on Java ----- + +DETECTING A MAC + + if (System.getProperty("mrj.version") == null) { + mb.add(createJUnitMenu()); + } else { + // the Mac specific code will go here + } + +from http://java.sun.com/developer/technicalArticles/JavaLP/JavaToMac2/ + + public boolean isMac() { + return System.getProperty("mrj.version") != null; + } + +from http://www.kfu.com/~nsayer/Java/reflection.html + +LOADING CLASSES ONLY ON MAC + +That is, we really want to do this: + + if (isMac()) { + new SpecialMacHandler(this); + } +but we will land in hot water because the class loader doesn't know what isMac() will return. It will only see that SpecialMacHandler wants com.apple.mrj.MRJApplicationUtils and fail to start the program on non-Macs. We must achieve the same end without referencing the class directly in the code. Reflection offers us the way. The reflected version of the same code looks like this: + + if (isMac()) { + try { + Object[] args = { this }; + Class[] arglist = { Program.class }; + Class mac_class = class.forName("SpecialMacHandler"); + Constructor new_one = mac_class.getConstructor(arglist); + new_one.newInstance(args); + } + catch(Exception e) { + System.out.println(e); + } + } + +from http://www.kfu.com/~nsayer/Java/reflection.html + + diff --git a/jnyqide/ReplaceDialog.java b/jnyqide/ReplaceDialog.java new file mode 100644 index 0000000..0578d07 --- /dev/null +++ b/jnyqide/ReplaceDialog.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1997 John Jensen. All rights reserved. + * + * This software is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE, + * provided the following condition is met. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that any copy or derivative of this software or documentation + * retaining the name "John Jensen" also retains this condition and the + * following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * CopyrightVersion 1.0 + */ +package jnyqide; + +import java.util.*; +import java.awt.*; +import java.awt.event.*; +import jnyqide.*; + +class ReplaceDialog extends Dialog implements WindowListener, ActionListener +{ + private Button fbutton,rbutton,cbutton; + private TextField pattern; + private TextField replace; + private MainFrame mainFrame; + private NyquistFile nyquistFile; + private Properties strings; + + private boolean foundOnce = false; + + public ReplaceDialog(NyquistFile tf, MainFrame mainFrame_) + { + super(mainFrame_, "Replace", true); + + mainFrame = mainFrame_; + + setBackground(Color.lightGray); + + nyquistFile = tf; + + Panel p1 = new Panel(); + + GridBagLayout gridbag = new GridBagLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + p1.setLayout(gridbag); + + Label flabel = new Label("Find"); + constraints.anchor = GridBagConstraints.NORTHWEST; + gridbag.setConstraints(flabel, constraints); + + pattern = new TextField(); + pattern.setColumns(35); + + if(tf.pane.getSelectedText() == null) // BWP + pattern.setText(mainFrame.findPattern); + else // BWP + pattern.setText(tf.pane.getSelectedText()); // BWP + + constraints.gridwidth = GridBagConstraints.REMAINDER; + gridbag.setConstraints(pattern, constraints); + + p1.add(flabel); + p1.add(pattern); + + Label rlabel = new Label("Replace"); + constraints.anchor = GridBagConstraints.WEST; + constraints.gridwidth = 1; + gridbag.setConstraints(rlabel, constraints); + + replace = new TextField(); + replace.setColumns(35); + + replace.setText(mainFrame.replacePattern); + + constraints.gridwidth = GridBagConstraints.REMAINDER; + gridbag.setConstraints(replace, constraints); + + p1.add(rlabel); + p1.add(replace); + + add("Center", p1); + + Panel p3 = new Panel(); + fbutton = new Button("Find Next"); + fbutton.addActionListener(this); + p3.add(fbutton); + rbutton = new Button("Replace"); + rbutton.addActionListener(this); + p3.add(rbutton); + cbutton = new Button("Close"); + cbutton.addActionListener(this); + p3.add(cbutton); + add("South",p3); + + Dimension size = new Dimension(400,120); + setSize(size); + Point tfloc = tf.getLocation(); + Point mfloc = mainFrame.getLocation(); + setLocation(mfloc.x + tfloc.x, + mfloc.y + tfloc.y + 75); + + addWindowListener(this); + setVisible(true); + } + + public void windowDeiconified(WindowEvent event) {} + public void windowIconified(WindowEvent event) {} + public void windowActivated(WindowEvent event) {} + public void windowDeactivated(WindowEvent event) {} + public void windowOpened(WindowEvent event) {} + public void windowClosed(WindowEvent event) {} + public void windowClosing(WindowEvent event) + { + mainFrame.findPattern = pattern.getText(); + mainFrame.replacePattern = replace.getText(); + dispose(); + } + + public void actionPerformed(ActionEvent evt) + { + if (evt.getSource() == cbutton) + { + mainFrame.findPattern = pattern.getText(); + mainFrame.replacePattern = replace.getText(); + dispose(); + return; + } + + if (evt.getSource() == fbutton) + foundOnce = nyquistFile.find(pattern.getText()); + else if (evt.getSource() == rbutton) + { + if (!foundOnce) + { + String selection= nyquistFile.copy(false,false); + if (selection != null) + foundOnce = selection.equals(pattern.getText()); + } + + if (foundOnce) + nyquistFile.paste(replace.getText()); + + foundOnce = nyquistFile.find(pattern.getText()); + } + + if (!foundOnce) + { + NotFoundDialog nf = new NotFoundDialog(mainFrame, strings, + getLocation()); + nf.setVisible(true); + } + } +} diff --git a/jnyqide/SalFileFilter.java b/jnyqide/SalFileFilter.java new file mode 100644 index 0000000..641ff37 --- /dev/null +++ b/jnyqide/SalFileFilter.java @@ -0,0 +1,41 @@ +// +// SalFileFilter.java +// nyquist +// +// Created by Roger Dannenberg on 12/23/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +package jnyqide; + +import javax.swing.filechooser.*; +import java.io.File; + + +/** + *

    Title:

    + *

    Description:

    + *

    Copyright: Copyright (c) 2002

    + *

    Company:

    + * @author unascribed + * @version 1.0 + */ + +public class SalFileFilter extends FileFilter { + + public SalFileFilter() { + } + + public boolean accept(File f) { + if (f.getName().endsWith(".sal")) return true; + for (int x = 0; x < f.getName().length(); x++) { + if ((f.getName().charAt(x) == '.')) + return false; + } + return true; + } + + public String getDescription() { + return "Sal files."; + } +} diff --git a/jnyqide/SalWordList.java b/jnyqide/SalWordList.java new file mode 100644 index 0000000..5874be8 --- /dev/null +++ b/jnyqide/SalWordList.java @@ -0,0 +1,57 @@ +// +// SalWordList.java +// nyquist +// +// Created by Roger Dannenberg on 12/18/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +package jnyqide; + +import java.util.HashMap; +import java.util.Map; + + +public class SalWordList { + public static String[] reservedWords = { + "below", "by", "else", "finally", "for", "function", "in", "over", + "repeat", "then", "from", "to", "unless", "until", "variable", + "when", "while", "with" }; + + public static String[] commandWords = { + "begin", "end", "chdir", "define", "open", "exec", "exit", "display", + "load", "loop", "open", "print", "if", "return", "set", // "system", + "play" }; + + public static Map reservedWordsTable; + + public static Map commandWordsTable; + + + static public void init() { + int i; + reservedWordsTable = new HashMap(); + for (i = 0; i < reservedWords.length; i++) { + reservedWordsTable.put(reservedWords[i], null); + } + commandWordsTable = new HashMap(); + for (i = 0; i < commandWords.length; i++) { + commandWordsTable.put(commandWords[i], null); + } + } + + + static public boolean isReservedWord(String word) { + boolean rslt = reservedWordsTable.containsKey(word); + // System.out.println("Sal:isReservedWord " + word + " -> " + rslt); + return rslt; + } + + + static public boolean isCommandWord(String word) { + boolean rslt = commandWordsTable.containsKey(word); + // System.out.println("Sal:isCommandWord " + word + " -> " + rslt); + return rslt; + } + +} diff --git a/jnyqide/SpecialMacHandler.java b/jnyqide/SpecialMacHandler.java new file mode 100644 index 0000000..f48024a --- /dev/null +++ b/jnyqide/SpecialMacHandler.java @@ -0,0 +1,70 @@ +package jnyqide; + +import jnyqide.*; +import com.apple.eawt.ApplicationAdapter; +import com.apple.eawt.ApplicationEvent; +import com.apple.eawt.Application; +/* import com.apple.mrj.*; */ +import javax.swing.SwingUtilities; + +/* OLD CODE -- the MRJ classes are deprecated. +public class SpecialMacHandler + implements MRJQuitHandler, MRJPrefsHandler, MRJAboutHandler { + MainFrame us; + public SpecialMacHandler(jnyqide.MainFrame theProgram) { + us = theProgram; + System.setProperty("com.apple.macos.useScreenMenubar", "true"); + System.setProperty("com.apple.mrj.application.apple.menu.about.name", "jNyqIDE"); + MRJApplicationUtils.registerAboutHandler(this); + MRJApplicationUtils.registerPrefsHandler(this); + MRJApplicationUtils.registerQuitHandler(this); + System.out.println("\n\n\nRegistered handlers for Mac Application Menu\n\n\n"); + } + public void handleAbout() { + us.About(); + } + public void handlePrefs() { + us.Prefs(); + } + public void handleQuit() { + System.out.println("handleQuit in SpecialMacHandler.java called"); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + us.Quit(); + } + }); + throw new IllegalStateException("Let the quit handler do it"); + } +} +*/ + +public class SpecialMacHandler extends ApplicationAdapter { + + MainFrame us; + + public SpecialMacHandler(jnyqide.MainFrame theProgram) { + System.out.println("SpecialMacHandler created"); + us = theProgram; + Application app = Application.getApplication(); + app.addApplicationListener(this); + app.setEnabledPreferencesMenu(true); + } + + public void handleAbout(ApplicationEvent e) { + e.setHandled(true); + us.About(); + } + + public void handlePreferences(ApplicationEvent e) { + us.Prefs(); + } + + public void handleQuit(ApplicationEvent e) { + System.out.println("handleQuit in SpecialMacHandler called"); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + us.Quit(); + } + }); + } +} diff --git a/jnyqide/SpringUtilities.java b/jnyqide/SpringUtilities.java new file mode 100644 index 0000000..fff3af6 --- /dev/null +++ b/jnyqide/SpringUtilities.java @@ -0,0 +1,194 @@ +package jnyqide; + +import javax.swing.*; +import javax.swing.SpringLayout; +import java.awt.*; + +/** + * A 1.4 file that provides utility methods for + * creating form- or grid-style layouts with SpringLayout. + * These utilities are used by several programs, such as + * SpringBox and SpringCompactGrid. + */ +public class SpringUtilities { + /** + * A debugging utility that prints to stdout the component's + * minimum, preferred, and maximum sizes. + */ + public static void printSizes(Component c) { + System.out.println("minimumSize = " + c.getMinimumSize()); + System.out.println("preferredSize = " + c.getPreferredSize()); + System.out.println("maximumSize = " + c.getMaximumSize()); + } + + /** + * Aligns the first rows * cols + * components of parent in + * a grid. Each component is as big as the maximum + * preferred width and height of the components. + * The parent is made just big enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeGrid(Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout)parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeGrid must use SpringLayout."); + return; + } + + Spring xPadSpring = Spring.constant(xPad); + Spring yPadSpring = Spring.constant(yPad); + Spring initialXSpring = Spring.constant(initialX); + Spring initialYSpring = Spring.constant(initialY); + int max = rows * cols; + + //Calculate Springs that are the max of the width/height so that all + //cells have the same size. + Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)). + getWidth(); + Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)). + getWidth(); + for (int i = 1; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent(i)); + + maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); + maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); + } + + //Apply the new width/height Spring. This forces all the + //components to have the same size. + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent(i)); + + cons.setWidth(maxWidthSpring); + cons.setHeight(maxHeightSpring); + } + + //Then adjust the x/y constraints of all the cells so that they + //are aligned in a grid. + SpringLayout.Constraints lastCons = null; + SpringLayout.Constraints lastRowCons = null; + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent(i)); + if (i % cols == 0) { //start of new row + lastRowCons = lastCons; + cons.setX(initialXSpring); + } else { //x position depends on previous component + cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), + xPadSpring)); + } + + if (i / cols == 0) { //first row + cons.setY(initialYSpring); + } else { //y position depends on previous row + cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), + yPadSpring)); + } + lastCons = cons; + } + + //Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, + Spring.sum( + Spring.constant(yPad), + lastCons.getConstraint(SpringLayout.SOUTH))); + pCons.setConstraint(SpringLayout.EAST, + Spring.sum( + Spring.constant(xPad), + lastCons.getConstraint(SpringLayout.EAST))); + } + + /* Used by makeCompactGrid. */ + private static SpringLayout.Constraints getConstraintsForCell( + int row, int col, + Container parent, + int cols) { + SpringLayout layout = (SpringLayout) parent.getLayout(); + Component c = parent.getComponent(row * cols + col); + return layout.getConstraints(c); + } + + /** + * Aligns the first rows * cols + * components of parent in + * a grid. Each component in a column is as wide as the maximum + * preferred width of the components in that column; + * height is similarly determined for each row. + * The parent is made just big enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeCompactGrid(Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout)parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeCompactGrid must use SpringLayout."); + return; + } + + //Align all cells in each column and make them the same width. + Spring x = Spring.constant(initialX); + for (int c = 0; c < cols; c++) { + Spring width = Spring.constant(0); + for (int r = 0; r < rows; r++) { + width = Spring.max(width, + getConstraintsForCell(r, c, parent, cols). + getWidth()); + } + for (int r = 0; r < rows; r++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, parent, cols); + constraints.setX(x); + constraints.setWidth(width); + } + x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); + } + + //Align all cells in each row and make them the same height. + Spring y = Spring.constant(initialY); + for (int r = 0; r < rows; r++) { + Spring height = Spring.constant(0); + for (int c = 0; c < cols; c++) { + height = Spring.max(height, + getConstraintsForCell(r, c, parent, cols). + getHeight()); + } + for (int c = 0; c < cols; c++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, parent, cols); + constraints.setY(y); + constraints.setHeight(height); + } + y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); + } + + //Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, y); + pCons.setConstraint(SpringLayout.EAST, x); + } +} diff --git a/jnyqide/TextColor.java b/jnyqide/TextColor.java new file mode 100644 index 0000000..55b501c --- /dev/null +++ b/jnyqide/TextColor.java @@ -0,0 +1,984 @@ +package jnyqide; + +import javax.swing.*; +// import java.awt.*; -- includes List, which conflicts +import java.awt.Color; +import java.awt.event.*; +import java.awt.Point; +import java.awt.Dimension; +import javax.swing.text.*; +import javax.swing.border.*; +import javax.swing.event.*; +import java.util.*; +/* +import java.util.Iterator; +import java.util.List; +import java.util.HashSet; +import java.util.Set; +import java.util.Point; +*/ +import java.io.*; + +public class TextColor { + static final boolean TCDEBUG = false; + static final String TEXT_FONT = "Courier"; + static final int TEXT_SIZE = 12; + static final Color COLOR_NORMAL = Color.black; + static final Color COLOR_COMMENT = new Color(0, 100, 0); // darkish green + static final Color COLOR_BUILTIN = Color.blue; + static final Color COLOR_STRING = new Color(130, 140, 0); // brown + static final Color COLOR_ERROR = new Color(250, 0, 0); + static final Color COLOR_COMMAND = new Color(0, 0, 196); // darkBlue; + static final Color COLOR_RESERVED = new Color(96, 0, 196); // purple + static final Color COLOR_KEYWORD = new Color(255, 128, 128); // pink + static final Color COLOR_HIGHLIGHT_FG = Color.black; + static final Color COLOR_HIGHLIGHT_BG = Color.lightGray; + static final Color COLOR_BLINK_FG = Color.white; + static final Color COLOR_BLINK_BG = Color.black; + + // TextColor is set up to be non-reentrant, with some state saved + // as static variables that can be referenced by helper functions + // like setColor. For example, you call format to colorize the + // visible portions of a window. It saves some state that setColor + // (called from many places) can use to find the document, the + // visible region, etc. When format returns, TextColor is ready + // for another call to fix another window. + + static DefaultStyledDocument doc; // the document being colorized + static int start; // the start of the visible region + static int end; // the end of the visible region + static int indentPos; // where we want indent information + static int indentBefore; // special return values for editing + static int indentAfter; + + public static SimpleAttributeSet attrNormal, attrComment, attrBuiltin, + attrString, attrError, attrCommand, attrKeyword, attrReserved, + attrHighlight, attrBlink; + + private static SimpleAttributeSet newTextAttr(Color color) { + SimpleAttributeSet attr = new SimpleAttributeSet(); + attr.addAttribute(StyleConstants.ColorConstants.Foreground, color); + StyleConstants.setFontFamily(attr, TEXT_FONT); + StyleConstants.setFontSize(attr, TEXT_SIZE); + return attr; + } + + private static SimpleAttributeSet newTextHighlight(Color fg, Color bg) { + SimpleAttributeSet attr = new SimpleAttributeSet(); + attr.addAttribute(StyleConstants.ColorConstants.Foreground, fg); + attr.addAttribute(StyleConstants.ColorConstants.Background, bg); + return attr; + } + + // public static Set keywords = new HashSet(); + + public static void init() { + // System.out.println("initializing TextColor.java"); + attrNormal = newTextAttr(COLOR_NORMAL); + attrComment = newTextAttr(COLOR_COMMENT); + attrBuiltin = newTextAttr(COLOR_BUILTIN); + attrCommand = newTextAttr(COLOR_COMMAND); + attrKeyword = newTextAttr(COLOR_KEYWORD); + attrReserved = newTextAttr(COLOR_RESERVED); + attrError = newTextAttr(COLOR_ERROR); + attrString = newTextAttr(COLOR_STRING); + attrHighlight = newTextHighlight(COLOR_HIGHLIGHT_FG, COLOR_HIGHLIGHT_BG); + attrBlink = newTextHighlight(COLOR_BLINK_FG, COLOR_BLINK_BG); + } + + + public static boolean format(CodePane codePane, int nlLoc) + { + JTextPane pane = codePane.pane; + doc = codePane.doc; + JViewport v = codePane.getViewport(); + indentBefore = 0; + indentAfter = 0; + indentPos = nlLoc; // position of interest for indentation info + //System.out.println("format begin"); + Point point = v.getViewPosition(); + start = pane.viewToModel(point); + //System.out.print("text loc for origin: "); + //System.out.println(start); + Dimension extent = v.getExtentSize(); + point.translate(extent.width, extent.height); + end = pane.viewToModel(point); + //System.out.print("text loc for bottom right: "); + //System.out.println(end); + boolean b; + int docLength = doc.getLength(); + String docText; + try { + docText = doc.getText(0, docLength); + } catch(Exception e ) { System.out.println(e); + return false; } + if (codePane.isSal && (docLength == 0 || docText.charAt(0) != '(')) { + b = formatVisibleSal(codePane, docText, docLength); + } else { + b = formatVisible(codePane, docText, docLength); + } + // System.out.println("format end: isSal " + codePane.isSal + + // " indentBefore " + indentBefore + + // " After " + indentAfter); + return b; + } + + + public static void setColor(int pos, int len, + SimpleAttributeSet color) + { + // if color region overlaps visible region, update doc with color + if (!(end < pos || pos + len < start)) { + doc.setCharacterAttributes(pos, len, color, true); + } + } + + static final int INDENT = 2; // how much to indent + // these are codes for different bracket types: + static final int ONESHOT = 0; + static final int IF_THEN = 1; + static final int COMMAND = 2; + static final int BRACE = 3; + static final int BRACKET = 4; + static final int PAREN = 5; + static final int IF = 6; + static final int BEGIN = 7; + static final int TOP = 8; // imaginary initial/final brackets used + // to detect and mark any unclosed real brackets like begin, (, etc. + // debugging support (I guess I should have used enumerated type): + static String[] stateName = { "ONESHOT", "IF_THEN", "COMMAND", + "BRACE", "BRACKET", "PAREN", "IF", "BEGIN", "TOP" }; + + + // find the column of pos in text by searching back to newline + public static int columnFor(String text, int pos) { + int col = 0; + while (pos > 0 && text.charAt(pos - 1) != '\n') { + col++; + pos--; + } + return col; + } + + // placed here so it is accessible by inner classes -- not ideal + static int lineIndent; + + public static boolean formatVisibleSal(CodePane pane, + final String docText, int docLength) { + // start and end give the visible range over which we actually + // change the document. + // + // Parse the whole file (well, almost): + // Use a stack for matching tokens and to compute indent: + // The stack contains the indentation to restore to when + // the matching close token is found. Also, if the close + // token does not match the top of the stack, there is some + // balance problem -- use precedence to decide what to match to, e.g. + // and END will skip an unclosed open-paren to match a BEGIN because + // BEGIN/END has higher precedence. + // + // This idea breaks down when there are local syntax errors, e.g. + // if you type a "todo" list at the top of a file, and the text + // is (intentionally) full of SAL syntax errors (because it's not + // supposed to be SAL), then far down in the file, you may find + // indentation breaks down completely. To work around this problem + // the syntax coloring is RESET whenever "define" appears + // + // In SAL, IF-THEN-ELSE does not have close tokens, so indentation + // is very tricky. IF is actually closed by THEN, but THEN must + // be followed by a statement. We record this by pushing IF_THEN, + // meaning that there's an IF-THEN construct holding a place for + // a possible ELSE. Then we push a COMMAND, + // a placeholder for the next statement. After any statement word, + // we pop COMMAND. If we find an ELSE, we pop the matching IF-THEN. + // If we get a statement when we're not expecting COMMAND, we pop + // all the IF-THEN's because the statement is going to stop any + // ELSE from matching and therefore we have to pop the indentation + // level back before any pending IF-THENs. + // + // Note that indentBefore and indentAfter and indentPos are used + // so that indentation can be computed and inserted from external + // editing functions. These basically serve as probes into the + // parsing algorithm. + // + // Coloring: + // as for LISP: + // known functions are in blue + // strings are in brown + // comments are in green + // as in Common Music SAL: + // reserved words are in purple + // keyword parameters are in pink + // commands are in dark blue + // + boolean allMatched = true; + boolean afterNewline = true; // set to true after each newline, and + // false after first token after each newline; used for indentation + lineIndent = 0; // will hold the correct indentation for the + // current line when a newline is reached. + // This is in contrast to the ParseStack.indent number, which is + // the "nominal" indentation that will be adjusted if the first + // token on the line closes an open bracket (e.g. begin or "(") + // or if the first token is not an expected command word + class ParseState { + public int indent; // the indentation level + public int indent2; // indent level if not a command + public int elseIndent; // used only for IF and IF_THEN to + // remember indentation for a possible ELSE clause + public int pos; // location of the token + public int len; // length of the token + public int state; // the saved state + public ParseState(int i, int i2, int p, int l, int s) { + indent = i; indent2 = i2; pos = p; len = l; state = s; + elseIndent = 0; + } + }; + + class ParseStack { + public Stack stack; + public int indent; + public int indent2; // the indentation if a command is continued + public ParseStack() { + stack = new Stack(); + stack.push(new ParseState(0, 0, 0, 0, TOP)); + indent = 0; + indent2 = 0; + } + + // push an indentation level on the stack, the keyword responsible + // starts at pos and had length len. The new indentation level will + // be at the column of pos + offset + public void push(int offset, int offset2, int pos, int len, int state) { + offset += columnFor(docText, pos) - indent; + pushOffset(offset, offset2, pos, len, state); + } + + // pushOffset is like push except the offset is relative to the + // current indentation, not the position of the keyword (useful + // for "define function foo()" where function causes the indent + // (because you can have "define var" that does not indent), but + // you want to indent relative to define rather than function. + public void pushOffset(int offset, int offset2, int pos, int len, + int state) { + stack.push(new ParseState(indent, indent2, pos, len, state)); + indent += offset; + indent2 = indent + offset2; + if (TCDEBUG) { System.out.println("pushOffset " + offset + + " indent " + indent); } + } + + // pop stack back to a matching token: bracket tokens have + // priorities, e.g. begin is higher priority than "(", so + // and "end" will jump over an unmatched "(" to find a "begin" + // This is done to obtain more reasonable warnings to user, + // otherwise, for example, "begin ( end" would all be red + // instead of just showing the "(" in red. If anything is + // unmatched, return false so caller knows there is an error + // somewhere. + boolean pop(int state) { + boolean matched = true; + // System.out.println("pop " + stack); + while (!stack.empty() && stack.peek().state <= state) { + ParseState ps = stack.pop(); + indent = ps.indent; + indent2 = ps.indent2; + // System.out.println("pop indent " + indent + " indent2 " + indent2); + if (ps.state == state) return matched; + if (ps.state != IF_THEN) { // ignore these ; + matched = false; + setColor(ps.pos, ps.len, attrError); + } + } + if (TCDEBUG) System.out.println("pop return false at end"); + return false; + } + + // after a command like define, the indentation level + // is incremented, but the level should be returned as soon as + // a command word is encountered + public void popCommandAndIfThen() { + // System.out.println("popCommand"); + if (stack.peek().state == COMMAND) { + pop(COMMAND); + if (TCDEBUG) { + System.out.println(" --> poppedCommand"); print(); } + } else while (stack.peek().state == IF_THEN) { + pop(IF_THEN); + lineIndent = indent2 = indent; + if (TCDEBUG) { + System.out.println(" --> popped IF_THEN"); print(); } + } + } + + // add COMMAND to stack after an IF_THEN in response to "else" + // this is tricky because the column inherits from the IF_THEN, + // not the current indent value, and indent gets elseIndent + public int ifElseCommand(int pos, int len) { + ParseState ps = stack.peek(); + if (ps.state == IF_THEN) { // good, "else" follows if...then + // rather than popping IF_THEN and pushing COMMAND, just + // change ps: + indent = indent2 = ps.elseIndent + INDENT; + ps.pos = pos; + ps.len = len; + ps.state = COMMAND; + return ps.elseIndent; + } + return 0; + } + + + public void startCommand() { + // remove COMMAND if present and retain indentation + // otherwise pop out of IF_THEN's + if (stack.peek().state == COMMAND) { + ParseState ps = stack.pop(); + indent2 = indent = ps.indent; + // back up indentation to prepare for an ELSE: + ps = stack.peek(); + if (ps.state == IF_THEN) { + indent2 = indent = ps.elseIndent; + } + //lineIndent = indent; + //indent = indent2 = ps.indent; + } else { + popCommandAndIfThen(); + } + } + + public void convertCommand(int pos, int len, int state) { + // remove COMMAND if present and replace with state + if (stack.peek().state == COMMAND) { + ParseState ps = stack.peek(); + ps.pos = pos; + ps.len = len; + ps.state = state; + } else { + popCommandAndIfThen(); + pushOffset(0, len + 1, pos, len, state); + } + } + + public void finishCommand() { + // remove COMMAND if present + if (stack.peek().state == COMMAND) { + pop(COMMAND); + } else { + popCommandAndIfThen(); + } + } + + public boolean convertIf() { + if (stack.peek().state == IF) { + ParseState ps = stack.peek(); + ps.state = IF_THEN; + return true; + } else { + return false; + } + } + + public void print() { + ParseState state = stack.peek(); + System.out.println("State: indent " + state.indent + + " indent2 " + state.indent2 + + " pos " + state.pos + + " len " + state.len + + " state " + stateName[state.state] + + " (cur) indent " + indent + + " (cur) indent2 " + indent + + " (cur) lineIndent " + lineIndent); + for (int i = 0; i < stack.size(); i++) { + System.out.print(stateName[stack.get(i).state] + " " + + stack.get(i).indent + " "); + } + System.out.println(); + } + + //public boolean expectingStmt() { + // int s = stack.peek().state; + // return (s == BEGIN || s == TOP); + // } + }; + + //System.out.println("formatVisibleSal"); + try { + // To parse the file, we use a state machine with these states: + // comment -- in a comment started by ";" + // word -- in normal text, possibly a keyword + // hash -- we detected a hash mark (this state is implied) + // escape -- we detected a backslash (this state is implied) + // hashComment -- we're in a comment #| ... |# + // string -- in a string + // barSymbol -- in a symbol like |...| + // space -- in space between other tokens + // normal -- this state is orthogonal to the others. + // it records when we are accumulating a run of normal + // (black) characters. To make things run a little faster + // we don't color each black character individually but + // group them together into a run. It also helps at the end + // of the string to be able to color what's left. + boolean normal = false; + int normalStart = 0; // start of normal black characters + boolean comment = false; + int commentStart = 0; + boolean word = false; + int wordStart = 0; + boolean string = false; + int stringStart = 0; + boolean barSymbol = false; + int barSymbolStart = 0; + boolean space = false; + int spaceStart = 0; + int pos; + ParseStack stack = new ParseStack(); + + // originally, this code accumulated words in buf, but this + // caused many string allocations and ran very slowly, so now + // we just mark where the word begins and when the word ends + // we extract a string from docText + + + // process document text while you have not reached the end + // of the visible area and while there are unmatched parens + // (i.e. the parenStack isn't empty, but stop if you reach + // the end of the whole file. + // + // System.out.println("begin parse loop, docLength " + docLength); + for (pos = 0; + pos < docLength && (pos < end || !stack.stack.empty()); + pos++) { + char c = docText.charAt(pos); + // System.out.print("CHAR |" + c + "| "); + if (comment) { + if (c == '\n') { + if (pos >= start) { + setColor(commentStart, pos - commentStart, + attrComment); + } + comment = false; + } // note that escape chars are ignored in comments + } else if (string) { + if (c == '"') { + if (pos >= start) + setColor(stringStart, pos - stringStart + 1, + attrString); + string = false; + } else if (c == '\\') { // skip the quoted char + pos++; + } + } else if (word) { + // see if the word ends because of a character or end of text + boolean terminated = (c == ' ' || c == '(' || c == ')' || + c == '\n' || c == '"' || c == '{' || + c == '}' || c == '[' || c == ']'); + if (terminated || pos >= docLength - 1) { + word = false; + int stop = pos; + if (!terminated) stop++; + String buf = docText.substring(wordStart, stop); + if (TCDEBUG) + System.out.println("formatVisibleSal: " + buf); + buf = buf.toLowerCase(); // for simplified lookup + SimpleAttributeSet color; + // WordList.printList(buf); // to get words list. + if (SalWordList.isReservedWord(buf)) { + color = attrReserved; + // note that "then" is not included here because + // "then" in a "for" clause does not need to be + // followed by a COMMAND + if (buf.equals("function") || buf.equals("finally")) { + if (afterNewline) { + lineIndent = stack.indent; + } + stack.startCommand(); + stack.pushOffset(INDENT, 0, wordStart, + buf.length(), COMMAND); + } else if (buf.equals("else")) { + int i = stack.ifElseCommand(wordStart, 4); + if (afterNewline) { + lineIndent = i; + } + if (TCDEBUG) { + System.out.println("ifElseCommand"); + stack.print(); } + } else if (buf.equals("when") || + buf.equals("unless")) { + stack.push(INDENT, buf.length() + 1 - INDENT, + wordStart, buf.length(), COMMAND); + } else if (buf.equals("variable")) { + stack.startCommand(); + stack.indent2 = columnFor(docText, wordStart) + + buf.length() + 1; + } else if (buf.equals("with") || + buf.equals("while") || + buf.equals("until")) { + stack.startCommand(); + stack.push(0, buf.length() + 1, + wordStart, buf.length(), COMMAND); +// stack.indent2 = columnFor(docText, wordStart) + +// buf.length() + 1; + } else if (buf.equals("then")) { + if (TCDEBUG) { + System.out.println("at then"); + stack.print(); } + // if there's an if on the stack, pop it + if (stack.convertIf()) { + if (afterNewline) { + lineIndent = stack.indent; + } + stack.pushOffset(INDENT, INDENT, wordStart, + 4, COMMAND); + } else { + stack.indent2 = + columnFor(docText, wordStart) + + buf.length() + 1; + } + if (TCDEBUG) { + System.out.println("after then"); + stack.print(); } + } else if (buf.equals("for")) { + stack.popCommandAndIfThen(); + stack.indent2 = stack.indent + INDENT; + } + afterNewline = false; + } else if (SalWordList.isCommandWord(buf)) { + stack.indent2 = stack.indent; + color = attrCommand; + if (afterNewline) { + lineIndent = stack.indent; + } + if (buf.equals("define")) { + // reset syntax coloring + stack.pop(TOP); // color unmatched stuff + stack = new ParseStack(); // reset stack + } else if (buf.equals("begin") || buf.equals("loop")) { + stack.push(INDENT, INDENT, wordStart, 5, BEGIN); + } else if (buf.equals("end")) { + if (!stack.pop(BEGIN)) { + allMatched = false; + setColor(wordStart, 3, attrError); + } + if (TCDEBUG) { + System.out.println("end token after stack.pop"); + stack.print(); } + // if this is the first word on the line, then + // match indentation to the matching BEGIN + if (afterNewline) { + lineIndent = stack.indent; + } + stack.finishCommand(); + if (TCDEBUG) { + System.out.println("end end"); + stack.print(); } + } else if (buf.equals("if")) { + if (TCDEBUG) { + System.out.println("at if"); + stack.print(); } + // int i = stack.indent; + stack.convertCommand(wordStart, 2, IF); + stack.stack.peek().elseIndent = stack.indent; + // stack.indent = stack.indent2 = i; + // stack.push(0, 0, wordStart, 2, IF); + if (TCDEBUG) { + System.out.println("after if"); + stack.print(); } + } else if (buf.equals("print")) { + stack.startCommand(); + stack.indent2 = columnFor(docText, wordStart) + + buf.length() + 1; + } else { + stack.startCommand(); + stack.indent2 = stack.indent + INDENT + INDENT; + } + afterNewline = false; + } else if (WordList.isKeyword(buf)) { + if (afterNewline) { + lineIndent = stack.indent2; + afterNewline = false; + } + color = attrBuiltin; + } else if (buf.charAt(buf.length() - 1) == ':') { + if (afterNewline) { + lineIndent = stack.indent2; + afterNewline = false; + } + color = attrKeyword; + } else { + if (afterNewline) {// && stack.expectingStmt()) { + lineIndent = stack.indent2; + if (TCDEBUG) { + System.out.println("buf " + buf + + " afterNewline " + afterNewline + + " lineIndent becomes " + lineIndent); } + afterNewline = false; + } + color = attrNormal; + } + // System.out.println(color); + if (color != attrNormal) { + setColor(normalStart, + wordStart - normalStart, attrNormal); + setColor(wordStart, pos - wordStart + 1, + color); + normal = true; + normalStart = pos + 1; + } else { + // continue normal (black) color + } + } else if (c == '\\') { + pos++; // skip the quoted char + } + if (terminated) { + pos = pos - 1; // reexamine character at pos + continue; // back to for loop, skip indentation tests + } + // Starts + } else if (c == ' ' || c == '\t' || c == '\n') { + space = true; + spaceStart = pos; + if (!normal) normalStart = pos; + normal = true; + } else if (c == ';') { // Comment Start + comment = true; + commentStart = pos; + space = false; + if (pos >= start && normal) { + setColor(normalStart, pos - normalStart, attrNormal); + } + normal = false; + } else if (c == '"') { // String start + if (afterNewline) { + lineIndent = stack.indent2; + afterNewline = false; + } + string = true; + stringStart = pos; + space = false; + if (pos >= start && normal) { + setColor(normalStart, pos - normalStart, attrNormal); + } + normal = false; + } else if (c == '(' || c == ')' || c == '{' || c == '}' || + c == '[' || c == ']') { + // Paren/Brace start and end + if ((c == '(' || c == '{' || c == '[') && afterNewline) { + lineIndent = stack.indent2; + afterNewline = false; + } + space = false; + if (pos >= start && normal) { + setColor(normalStart, pos - normalStart, attrNormal); + } + normal = false; + if (pos >= start) + setColor(pos, 1, attrNormal); + if (c == '(' ) stack.push(1, 0, pos, 1, PAREN); + else if (c == '{') stack.push(1, 0, pos, 1, BRACE); + else if (c == '[') stack.push(1, 0, pos, 1, BRACKET); + else { // must be ')' or '}' or ']' + if (afterNewline) { + lineIndent = stack.indent - 1; + } + if (stack.pop(c == ')' ? PAREN : + (c == ']' ? BRACKET : BRACE))) { + // System.out.println("after ), ], or }: indent " + stack.indent); + } else { + allMatched = false; + setColor(pos, 1, attrError); + } + } + //System.out.println("highlight/blink " + c + " pos " + pos + + // " highlightLoc " + pane.highlightLoc + + // " blinkLoc " + pane.blinkLoc); + // there could be a race condition here, but failure + // is not critical -- this just blinks the closing paren + if (pane != null && pane.blinkLoc == pos && pane.blinkOn) { + setColor(pos, 1, attrBlink); + } else if (pane != null && pane.highlightLoc == pos) { + setColor(pos, 1, attrHighlight); + } + } else { // Word start + word = true; + wordStart = pos; + if (!normal) normalStart = pos; + normal = true; + if (c == '\\' && pos + 1 < docLength) { + pos++; // parse the quoted char + } + } + if (c == '\n') { // possibly store indentation info + //System.out.println(pos + " indentPos " + indentPos + + // " indent " + stack.indent); + if (pos == indentPos) { + indentBefore = lineIndent; + indentAfter = stack.indent; + } + lineIndent = stack.indent; + + afterNewline = true; + if (TCDEBUG) { + System.out.println("at newline"); stack.print(); } + } + /* + System.out.print("At end of loop, pos "); + System.out.println(pos); + */ + } // END FOR LOOP + //System.out.println("end parse loop"); + if (normal) { + setColor(normalStart, pos - normalStart + 1, attrNormal); + } else if (comment) { + setColor(commentStart, pos - commentStart + 1, attrComment); + } else if (string) { + setColor(stringStart, pos - stringStart + 1, attrString); + } + // set error color to any unmatched tokens on stack: + if (!stack.pop(TOP)) allMatched = false; + } catch(Exception e ) { + System.out.println(e); + e.printStackTrace(); + } + //System.out.println("salFormatVisible returns " + allMatched); + return allMatched; + } + + + public static boolean formatVisible(CodePane pane, + String docText, int docLength) + // start and end give the visible range over which we actually + // change the document. + { + boolean evenParens = false; + + try { + //System.out.println(docText); + + // To parse the file, we use a state machine with these states: + // comment -- in a comment started by ";" + // word -- in normal text, possibly a keyword + // hash -- we detected a hash mark (this state is implied) + // escape -- we detected a backslash (this state is implied) + // hashComment -- we're in a comment #| ... |# + // string -- in a string + // barSymbol -- in a symbol like |...| + // space -- in space between other tokens + // normal -- this state is orthogonal to the others. + // it records when we are accumulating a run of normal + // (black) characters. To make things run a little faster + // we don't color each black character individually but + // group them together into a run. It also helps at the end + // of the string to be able to color what's left. + boolean normal = false; + int normalStart = 0; // start of normal black characters + boolean comment = false; + int commentStart = 0; + boolean word = false; + int wordStart = 0; + boolean string = false; + int stringStart = 0; + boolean hashComment = false; + int hashCommentStart = 0; + boolean barSymbol = false; + int barSymbolStart = 0; + boolean space = false; + int spaceStart = 0; + int pos; + Stack parenStack = new Stack(); + // originally, this code accumulated words in buf, but this + // caused many string allocations and ran very slowly, so now + // we just mark where the word begins and when the word ends + // we extract a string from docText + + + // process document text while you have not reached the end + // of the visible area and while there are unmatched parens + // (i.e. the parenStack isn't empty, but stop if you reach + // the end of the whole file. + // + //System.out.println("begin parse loop"); + for (pos = 0; pos < docLength && (pos < end || !parenStack.empty()); + pos++) { + char c = docText.charAt(pos); + if (comment) { + if (c == '\n') { + if (pos >= start) { + setColor(commentStart, pos - commentStart, + attrComment); + } + comment = false; + } // note that escape chars are ignored in comments + } else if (string) { + if (c == '"') { + if (pos >= start) + setColor(stringStart, pos - stringStart + 1, + attrString); + string = false; + } else if (c == '\\') { // skip the quoted char + pos++; + } + } else if (word) { + // see if the word ends because of a character or end of text + boolean terminated = (c == ' ' || c == '(' || c == ')' || + c == '\n' || c == '"'); + if (terminated || pos >= docLength - 1) { + word = false; + int stop = pos; + if (!terminated) stop++; + String buf = docText.substring(wordStart, stop); + // WordList.printList(buf); // to get words list. + if (WordList.isKeyword(buf)) { + setColor(normalStart, wordStart - normalStart, + attrNormal); + setColor(wordStart, pos - wordStart + 1, + attrBuiltin); + normal = true; + normalStart = pos + 1; + } else { + // continue normal (black) color + } + } else if (c == '\\') { + pos++; // skip the quoted char + } + if (terminated) pos = pos - 1; // reexamine character at pos + } else if (hashComment) { + if (c == '|' && pos + 1 < docLength && + docText.charAt(pos + 1) == '#') { + pos++; + if (pos >= start) { + if (normal) { + setColor(normalStart, + hashCommentStart - normalStart, + attrNormal); + } + setColor(hashCommentStart, + pos - hashCommentStart + 1, attrComment); + } + normal = false; + hashComment = false; + } else if (c == '\\') pos++; // skip the quoted char + } else if (barSymbol) { + if (c == '|') { + if (pos >= start) { + if (normal) { + setColor(normalStart, wordStart - normalStart, + attrNormal); + } + normal = false; + setColor(wordStart, pos - wordStart, attrNormal); + } + } else if (c == '\\') pos++; // skip the quoted char + // Starts + } else if (c == ' ' || c == '\t' || c == '\n') { + space = true; + spaceStart = pos; + if (!normal) normalStart = pos; + normal = true; + } else if (c == ';') { // Comment Start + comment = true; + commentStart = pos; + space = false; + if (pos >= start && normal) { + setColor(normalStart, pos - normalStart, attrNormal); + } + normal = false; + } else if (c == '"') { // String start + string = true; + stringStart = pos; + space = false; + if (pos >= start && normal) { + setColor(normalStart, pos - normalStart, attrNormal); + } + normal = false; + } else if (c == '(' || c == ')') { // Paren start and end + space = false; + if (pos >= start && normal) { + setColor(normalStart, pos - normalStart, attrNormal); + } + normal = false; + if (pos >= start) + setColor(pos, 1, attrNormal); + if (c == '(' ) { + parenStack.push(new Integer(pos)); + } else { + if (parenStack.empty()) { + if (pos >= start) + setColor(pos, 1, attrError); + } else { + // System.out.println("pop stack"); + parenStack.pop(); + } + } + //System.out.println("highlight/blink " + c + " pos " + pos + + // " highlightLoc " + pane.highlightLoc + + // " blinkLoc " + pane.blinkLoc); + // there could be a race condition here, but failure + // is not critical -- this just blinks the closing paren + if (pane != null && pane.blinkLoc == pos && pane.blinkOn) { + setColor(pos, 1, attrBlink); + } else if (pane != null && pane.highlightLoc == pos) { + setColor(pos, 1, attrHighlight); + } + } else if (c == '#') { + space = false; + if (pos >= start && normal) { + setColor(normalStart, pos - normalStart, attrNormal); + } + normal = true; + normalStart = pos; + if (pos + 1 < docLength) { + char c2 = docText.charAt(pos + 1); + if (c2 == '\'' || c2 == 'x' || c2 == 'o' || c2 == 'b' || + c2 == ':') { + // ignore all these: #' #x #o #b #: + word = true; + wordStart = pos; + pos++; + } else if (c2 == '|') { + hashComment = true; + hashCommentStart = pos; + pos++; + normal = false; + } else { + word = true; + wordStart = pos; + } + } + } else { // Word start + word = true; + wordStart = pos; + if (!normal) normalStart = pos; + normal = true; + if (c == '\\' && pos + 1 < docLength) { + pos++; // parse the quoted char + } + } + /* + System.out.print("At end of loop, pos "); + System.out.println(pos); + */ + } // END FOR LOOP + //System.out.println("end parse loop"); + if (normal) { + setColor(normalStart, pos - normalStart + 1, attrNormal); + } else if (comment) { + setColor(commentStart, pos - commentStart + 1, attrComment); + } else if (hashComment) { + setColor(hashCommentStart, pos - hashCommentStart + 1, + attrComment); + } else if (string) { + setColor(stringStart, pos - stringStart + 1, attrString); + } + + evenParens = parenStack.empty(); + while( !parenStack.empty()) { + int parenPos = ((Integer)parenStack.pop()).intValue(); + if (pos >= start) + setColor(parenPos, 1, attrError); + } + } + catch(Exception e ) { System.out.println(e); } + + return evenParens; + } +} diff --git a/jnyqide/Trie.java b/jnyqide/Trie.java new file mode 100644 index 0000000..7c76727 --- /dev/null +++ b/jnyqide/Trie.java @@ -0,0 +1,129 @@ +/* +package jnyqide; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +public class Trie { + Node root; + + /** + * Creates an WordMode object with the given dictionary. + * + * @param strs + * A list of strings containing the words in dictionary file which + * contains the list of valid words sorted by frequency + */ +/* public Trie() + { + root = new Node(); + } + + public void addWord(String word) + { + char[] letters = word.toCharArray(); + Node n = root; + for(int i = 0; i < letters.length; i++) + { + if(n.get((int)letters[i]) == null) + { + Node x = n.addNode((int)letters[i]); + x.parent = n; + n = x; + } + else + n = n.get((int)letters[i]); + } + if(letters[letters.length-1] == ')') + word = "(" + word; + n.addWord(word); + while(n.parent != null) + { + n = n.parent; + n.addWord(word); + } + } + + /* Since you are not allowed to use anything from java.util (except for the + * Iterator interface and AbstractList), you must create your own implementation + * of a list. (You may choose to extend AbstractList if you would like) + * + * If you would like to return an AbstractList, + * **Hint: What are the methods you need to implement in order to extend + * AbstractList? Also, in order for the AbstractList to function, + * what other methods must you override? + */ + // if full, must match all letters +/* public List getWordsFor(String s, Boolean full) { + char[] letters = s.toCharArray(); + Node n = root; + for(int i = 0; i < letters.length; i++) + { + if(n.get((int)letters[i]) == null) + return (full ? null : n.unmodifiableList); + else + n = n.get((int)letters[i]); + } + return n.unmodifiableList; + } + + + public List getAllWordsFor(String s) + { + List r = new ArrayList(); + List l = getWordsFor("", false); + int i = 0; + while (i < l.size()) + { + if (l.get(i).toString().contains(s)) { + r.add(l.get(i).toString()); + } + i++; + } + return r; + } + + + private class Node { + Node parent; + Node nodes [] = new Node [128]; + ArrayList words = new ArrayList (); + List unmodifiableList; + + public Node() + { + parent = null; + unmodifiableList = Collections.unmodifiableList(new AbstractList() { + public int size() { + return words.size(); + } + + public String get(int i) { + return (String) words.get(i); + } + }); + } + + public Node get(int index) + { + return nodes[index]; + } + + public Node addNode(int i) + { + if(nodes[i] == null) + nodes[i] = new Node(); + return nodes[i]; + } + + public void addWord(String str) + { + words.add(str); +// System.out.println("( " + str + " ) is added to Trie"); + } + } +} +*/ \ No newline at end of file diff --git a/jnyqide/UPICFrame.java b/jnyqide/UPICFrame.java new file mode 100644 index 0000000..5c93c67 --- /dev/null +++ b/jnyqide/UPICFrame.java @@ -0,0 +1,1425 @@ +// Code: Dmitry Portnoy, 5/1/09 +// Revised 2011 by Roger B. Dannenberg +/* + Graphics organization: + + mainframe -- the MainFrame + UPICFrame -- this editor, a JInternalFrame + mainPanel -- a JPanel + topPanel -- a JPanel + dataPanel -- a JPanel, border "Current Envelope" + varNameLabel -- a JLabel ("Name:") + varName -- a JTextField + waveformNameLabel -- a JLabel ("Waveform:") + waveformName -- a JComboBox + envNameLabel -- a JLabel("Envelope:") + envName -- a JComboBox + rangePanel - a JPanel, border "Range" + update - JButton("Update Range") + jMaxTL - a JLabel("Stop Time") + jMaxT - a JTextField + jMinAL - a JLabel("Min Freq") + jMinA - a JTextField + jMaxAL - a JLabel("Max Freq") + jMaxA - a JTextField + undoPanel - a JPanel, border "Undo/Redo" + undo - a JButton("Undo") + redo - a JButton("Redo") + canvas - a PiecewiseCanvas (a JPanel) + +if endpoints are specified, e.g. if times[0] is 0 or last value in times + matches the ending time, then use PWLV or PWEV version + Be careful not to drop first/last point unless the time matches the + begin/end time. + + + */ + +/* Design notes by Dannenberg: + +Too much data to treat this like envelopes. Instead, load/save data a a file. +Menu items: save, save as, revert, clear +Use variable name box to give a variable name for the data. +Use waveform name drop-down box to name waveforms. +Use envelope name drop-down box to name envelopes. +File format will be a waveform name, envelope name, and +list of lists of alternating time value coordinates. +File will have the format: +------------ +;; data saved from NyquistIDE UPIC editor +set data-name = { +{ waveform envelope first list } +{ waveform envelope second list } +... +} +------------ +It's up to the user to interpret this data, but we'll add some +functions to do this. + +*/ + +package jnyqide; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import java.awt.image.*; +import java.util.*; +import java.text.*; +import java.io.*; +import javax.imageio.ImageIO; + +@SuppressWarnings("serial") +public class UPICFrame extends JInternalFrame implements ActionListener { + + double EPSILON = 0.00000001; // small number -- allow for rounding error + int LEFT_BORDER = 3; // inset everything by 3 pixels + int TOP_BORDER = 3; + int BOTTOM_BORDER = 5; + int RIGHT_BORDER = 5; + MainFrame mainframe; + + private JPanel mainPanel; + + private JTextPane jInputArea; + private PiecewiseCanvas canvas; + + private JTextField jMaxT; + private double maxT; + private JTextField jMinHz; + private double minHz; + private JTextField jMaxHz; + private double maxHz; + private JCheckBox jLinear; + private boolean isLinear = true; + private JTextField varName; + private String currentVarName; + private JComboBox envName; + private String currentEnvName = "upic-env"; + private JComboBox waveformName; + private String currentWaveformName = "*sine-table*"; + private boolean showCs; + private boolean showGrandStaff; + private boolean showPicture; + // when saving envelopes, we copy current envelope to the collection, + // but this makes the combobox think that an envelope was selected, + // and we get a request to save the same envelope were saving. To + // avoid this, the "saving" flag is used to disable the check. + private boolean saving = false; + private File file; // the file backing the current data + private String name; // name of file + + //hashtable for storing envelopes + private Hashtable envColl; + + static double initTime=0.0; + static double finalTime=1.0; + static boolean displayCoord = false; + static boolean valueType=false; + static DecimalFormat form = new DecimalFormat("#.###"); + private boolean modified; // tells when any aspect of envelope + // has changed + // envelope is modified by: entering a point, deleting a point, changing + // the end-time (update), or clearing + // modified is reset when envelope is loaded or saved + + private JButton MakeButton(String name, String cmd) { + JButton b = new JButton(name); + b.addActionListener(this); + b.setActionCommand(cmd); + return b; + } + + private void AddMenuItem(JMenu menu, String name, String cmd, int code) { + AddMenuItem(menu, name, cmd, code, false, false); + } + + private void AddMenuItem(JMenu menu, String name, String cmd, int code, + boolean shift) { + AddMenuItem(menu, name, cmd, code, shift, false); + } + + private void AddMenuItem(JMenu menu, String name, String cmd, + int code, boolean shift, boolean check) { + int keyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + JMenuItem item; + if (check) { + item = new JCheckBoxMenuItem(name); + } else { + item = new JMenuItem(name); + } + item.setActionCommand(cmd); + item.addActionListener(this); + if (code != -1) { + item.setAccelerator(KeyStroke.getKeyStroke(code, keyMask | + (shift ? java.awt.event.InputEvent.SHIFT_MASK : 0))); + } + menu.add(item); + } + + private JComboBox MakeCombo(String cmd) { + JComboBox b = new JComboBox(); + b.setPreferredSize(new Dimension(150, 20)); + b.setEditable(true); + b.addActionListener(this); + b.setActionCommand(cmd); + return b; + } + + // Constructor + public UPICFrame(final MainFrame parent, JTextPane inputArea) { + super(); + mainframe = parent; + jInputArea = inputArea; + mainPanel = (JPanel) getContentPane(); + + envColl = new Hashtable(); + name = "UPIC Editor"; + setTitle(name); + setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); + final UPICFrame upicFrame = this; + modified = false; + addInternalFrameListener( + new InternalFrameListener() { + public void internalFrameClosing(InternalFrameEvent e) { + //System.out.println("FrameClosing"); + int r = JOptionPane.OK_OPTION; + if (upicFrame.modified) { + r = JOptionPane.showConfirmDialog(upicFrame, + "Really close without saving?", + "Alert", JOptionPane.OK_CANCEL_OPTION); + } + if (r == JOptionPane.OK_OPTION) { + upicFrame.dispose(); + } + } + public void internalFrameOpened(InternalFrameEvent e) { + } + public void internalFrameClosed(InternalFrameEvent e) { + parent.disconnectUPIC(); + //System.out.println("FrameClosed"); + } + public void internalFrameIconified(InternalFrameEvent e) { + } + public void internalFrameDeiconified(InternalFrameEvent e) { + } + public void internalFrameActivated(InternalFrameEvent e) { + } + public void internalFrameDeactivated(InternalFrameEvent e) { + } + } + ); + + System.out.println("EnvelopeFrame constructor 1"); + + JMenuBar menuBar = new JMenuBar(); + // File Menu + JMenu fileMenu = new JMenu("File"); + AddMenuItem(fileMenu, "Load", "loadUpicData", + java.awt.event.KeyEvent.VK_K); + AddMenuItem(fileMenu, "Open", "openUpicData", + java.awt.event.KeyEvent.VK_O); + AddMenuItem(fileMenu, "Save", "saveUpicData", + java.awt.event.KeyEvent.VK_S); + AddMenuItem(fileMenu, "Save As...", "saveUpicDataAs", + java.awt.event.KeyEvent.VK_S, true); + AddMenuItem(fileMenu, "Revert", "revertUpicData", -1); + AddMenuItem(fileMenu, "Clear", "clearUpicData", -1); + + JMenu backgroundMenu = new JMenu("Background"); + AddMenuItem(backgroundMenu, "C's", "showCs", + java.awt.event.KeyEvent.VK_C, false, true); + AddMenuItem(backgroundMenu, "Grand Staff", "showGrandStaff", + java.awt.event.KeyEvent.VK_G, false, true); + AddMenuItem(backgroundMenu, "Show Picture", "showPicture", + java.awt.event.KeyEvent.VK_V, false, true); + AddMenuItem(backgroundMenu, "Load Picture...", "loadPicture", -1); + + menuBar.add(fileMenu); + menuBar.add(backgroundMenu); + setJMenuBar(menuBar); + + JLabel varNameLabel = new JLabel("Name: "); + varName = new JTextField("upicdata", 10); + currentVarName = "upicdata"; + + JLabel waveformNameLabel = new JLabel("Waveform:"); + waveformName = MakeCombo("waveformNameSelected"); + + JLabel envNameLabel = new JLabel("Envelope:"); + envName = MakeCombo("envNameSelected"); + + JPanel dataPanel = new JPanel(); + GridBagLayout layout0 = new GridBagLayout(); + dataPanel.setLayout(layout0); + GridBagConstraints cons0 = new GridBagConstraints(); + + cons0.fill = GridBagConstraints.NONE; + cons0.anchor = GridBagConstraints.EAST; + cons0.insets = new Insets(2, 2, 2, 2); // TEST + cons0.weightx = 0; + cons0.weighty = 0; + cons0.gridy = 0; + cons0.gridx = 0; + cons0.gridheight = 1; + cons0.gridwidth = 1; + dataPanel.add(varNameLabel, cons0); + cons0.anchor = GridBagConstraints.WEST; + cons0.gridx = 1; + cons0.fill = GridBagConstraints.HORIZONTAL; //TEST + dataPanel.add(varName, cons0); + cons0.anchor = GridBagConstraints.EAST; + cons0.fill = GridBagConstraints.NONE; + cons0.gridy = 1; + cons0.gridx = 0; + dataPanel.add(waveformNameLabel, cons0); + cons0.anchor = GridBagConstraints.WEST; + cons0.gridx = 1; + dataPanel.add(waveformName, cons0); + cons0.gridy = 2; + cons0.gridx = 0; + dataPanel.add(envNameLabel, cons0); + cons0.anchor = GridBagConstraints.WEST; + cons0.gridx = 1; + dataPanel.add(envName, cons0); + + // panel to contain time and amplitude parameters + JPanel rangePanel = new JPanel(); + //JPanel paramPanel = new JPanel(); + //paramPanel.setBorder(BorderFactory.createTitledBorder("Range")); + rangePanel.setLayout(new GridBagLayout()); + rangePanel.setBorder(BorderFactory.createTitledBorder("Range")); //TEST + //paramPanel.setLayout(new GridBagLayout()); + + jMaxT = new JTextField("20.0", 5); + maxT = 20.0; + jMinHz = new JTextField("20.0", 5); + minHz = 20.0; + jMaxHz = new JTextField("2000.0", 5); + maxHz = 2000; + jLinear = new JCheckBox("linear", true); + showCs = false; + showGrandStaff = false; + showPicture = false; + + JLabel jMaxTL = new JLabel("Stop Time: "); + JLabel jMinHzL = new JLabel("Min Freq: "); + JLabel jMaxHzL = new JLabel("Max Freq: "); + + JButton update = new JButton("Update Range"); + cons0.gridx = 0; + cons0.gridy = 0; + cons0.gridwidth = 2; + rangePanel.add(update, cons0); + cons0.gridwidth = 1; + cons0.gridx = 2; + cons0.gridy = 0; + rangePanel.add(jMaxTL, cons0); + cons0.gridx = 3; + cons0.gridy = 0; + rangePanel.add(jMaxT, cons0); + cons0.gridx = 0; + cons0.gridy = 1; + rangePanel.add(jMinHzL, cons0); + cons0.gridx = 2; + rangePanel.add(jMaxHzL, cons0); + cons0.gridx = 1; + rangePanel.add(jMinHz, cons0); + cons0.gridx = 3; + rangePanel.add(jMaxHz, cons0); + cons0.gridx = 4; + rangePanel.add(jLinear, cons0); + + update.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (getMaxT() <= 0) { + JOptionPane.showMessageDialog(mainPanel, + "Stop Time cannot be negative or zero"); + } else if (getMinHz() > getMaxHz()) { + JOptionPane.showMessageDialog(mainPanel, + "Minimum frequency cannot be greater than maximum frequency"); + } else if ((canvas.endTime() > getMaxT())) { + JOptionPane.showMessageDialog(mainPanel, + "Stop Time is less than the time of an existing envelope point"); + } else if (getMinHz() < 20.0) { + JOptionPane.showMessageDialog(mainPanel, + "Minimum frequency cannot be less than 20 Hz"); + } else { + setModified(); + maxT = getMaxT(); + minHz = getMinHz(); + maxHz = getMaxHz(); + isLinear = getLinear(); + canvas.history.save(canvas); + canvas.repaint(); + return; + } + // an error occurred, reset the Range (using complete restore) + canvas.restore(); + } + }); + + JPanel undoPanel = new JPanel(); + undoPanel.setLayout(new GridBagLayout()); + undoPanel.setBorder(BorderFactory.createTitledBorder("Undo/Redo")); + JButton undo = new JButton("Undo"); + undo.setActionCommand("undo"); + undo.addActionListener(this); + JButton redo = new JButton("Redo"); + redo.setActionCommand("redo"); + redo.addActionListener(this); + cons0.gridx = 0; + cons0.gridy = 0; + undoPanel.add(undo, cons0); + cons0.gridy = 1; + undoPanel.add(redo, cons0); + + //insert components into the larger panels + cons0.fill = GridBagConstraints.NONE; + cons0.anchor = GridBagConstraints.WEST; + cons0.weightx = 0; + cons0.weighty = 0; + cons0.gridx = 0; + cons0.gridy = 0; + cons0.gridheight = 1; + cons0.gridwidth = 1; + //cons0.insets = new Insets(5,0,0,5); + //paramPanel.add(rangePanel, cons0); + // cons0.fill = GridBagConstraints.NONE; + // cons0.anchor = GridBagConstraints.CENTER; + // cons0.weightx = 0; + // cons0.weighty = 0; + // cons0.gridx = 0; + // cons0.gridy = 1; + // cons0.gridheight = 1; + // cons0.gridwidth = 1; + // //cons0.insets = new Insets(0,0,0,5); + // paramPanel.add(update, cons0); + + JPanel topPanel = new JPanel(); + //topPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 30, 0)); + topPanel.setLayout(new GridBagLayout()); + cons0.anchor = GridBagConstraints.NORTHWEST; + cons0.gridx = 0; + cons0.gridy = 0; + topPanel.add(dataPanel, cons0); + cons0.gridx = 1; + topPanel.add(rangePanel, cons0); //TEST + cons0.gridx = 2; + topPanel.add(undoPanel, cons0); + + canvas = new PiecewiseCanvas(); + //insert panels into main frame and display + mainPanel.add(BorderLayout.NORTH, topPanel); + mainPanel.add(BorderLayout.CENTER, canvas); + pack(); + + //resize and center the window + //Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + setLocation(100, 100); + setSize(650, 580); + // setBackground(Color.white); + setResizable(true); + setVisible(true); + setClosable(true); + setMaximizable(true); + setIconifiable(true); + clearUpicData(true); + System.out.println("UPICFrame constructor 2 after setIconifiable"); + repaint(); + } + + public boolean waveformNameSelected() { + String name = (String) waveformName.getSelectedItem(); + if (name == null || name.equals("")) return false; + currentWaveformName = name; + return true; + } + + public void waveformNewName() { + if (waveformNameSelected()) { + waveformName.addItem(currentWaveformName); + } + } + + public boolean envNameSelected() { + String name = (String) envName.getSelectedItem(); + if (name == null) return false; + + String originalName = currentEnvName; + currentEnvName = name.trim(); + if (!originalName.equals(currentEnvName)) { + modified = true; + } + + // make name be the selected name + envName.setSelectedItem(name); + currentEnvName = name; + return true; + } + + + public void envNewName() { + if (envNameSelected()) { + envName.addItem(currentEnvName); + } + } + + + public void varNameSelected() { + if (saving) return; // ignore selection generated by "save" button + // If the name is different from the current envelope name, do + // a "save". Then switch to editing the newly selected envelope. + String name = (String) varName.getText(); + // when we load the JComboBox with new names, the contentsChanged + // method of JComboBox invokes a selection action, even if nothing + // is selected. I don't know why, but we have to handle the null + // selection case. + if (name == null) return; + + String originalName = currentVarName; + currentVarName = varName.getText().trim(); + if (!originalName.equals(currentVarName)) { + modified = true; + } + varName.setText(name); + currentVarName = name; + } + + + //public double getMinT() { return Double.parseDouble(minT.getText().trim()); } + public double getMaxT() { return Double.parseDouble(jMaxT.getText().trim()); } + public double getMinHz() { return Double.parseDouble(jMinHz.getText().trim()); } + public double getMaxHz() { return Double.parseDouble(jMaxHz.getText().trim()); } + public boolean getLinear() { return jLinear.isSelected(); } + + public boolean within(double x, double y, double eps) { + return Math.abs(x - y) < eps; + } + + + // prompt for a file name and write the data + public boolean saveUpicDataAs() { + // select a file and write to it. Return true if success. + JFileChooser chooser = new JFileChooser(); + SalFileFilter salFilter = new SalFileFilter(); + chooser.setFileFilter(salFilter); + File tmpfile; + String tmp; + + File curdir = new File(mainframe.currentDir); + chooser.setCurrentDirectory(curdir); + + while (true) { // loop until file is chosen + int returnVal = chooser.showSaveDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + tmpfile = chooser.getSelectedFile(); + tmp = tmpfile.getName(); + System.out.println("You chose to save this file: " + tmp); + tmp = tmp.toLowerCase(); + if (tmp.endsWith(".sal")) break; + JOptionPane dialog = new JOptionPane(); + System.out.println("creating dialog"); + int result = dialog.showConfirmDialog(this, + "Do you really want to save a file without a " + + ".lsp or .sal extension?", "Warning", + JOptionPane.YES_NO_OPTION); + System.out.println("return from dialog " + result); + if (result == JOptionPane.YES_OPTION) break; + } else { // file chooser cancel, early return + return false; + } + } + name = tmp; + file = tmpfile; + mainframe.changeDirectory(mainframe.fileDirectory(file)); + modified = true; // for saveUpicData, do not need to add "*" + return saveUpicData(); + } + + + private void setModified() { + if (modified) return; + setTitle(name + "*"); + modified = true; + } + + public boolean saveUpicData() + // saves the file if there is a file name, otherwise calls saveAs. + // returns false if the operation fails or is cancelled. + // returns true if save succeeds or if file is unmodified. + { + if (modified) { + if (file == null) + return saveUpicDataAs(); + else { + try { + FileWriter saveFileStream = new FileWriter(file); + BufferedWriter out = new BufferedWriter(saveFileStream); + String s = ";; data saved from NyquistIDE UPIC editor\n"; + s += String.format( + ";!; maxT %g minHz %g maxHz %g linear %s\n", + maxT, minHz, maxHz, (isLinear ? "t" : "nil")); + s += String.format("set %s = {\n", + varName.getText().trim()); + out.write(s); + for (Curve c : canvas.curves) { + if (c.times.size() > 0) { + out.write(String.format("{ %s %s\n", + c.waveform, c.envelope)); + for (int i = 0; i < c.times.size(); i++) { + out.write(String.format(" %.4f %.1f", + c.times.get(i), c.freqs.get(i))); + } + out.write(" }\n\n"); + } + } + out.write("}\n"); + out.close(); + } + catch(Exception e) { + System.out.println("exception in saveUpicData" + e); + return false; // did not save file + } + + modified = false; + setTitle(name); + } + } + return true; + } + + + public void actionPerformed(ActionEvent e) + { + String cmd = e.getActionCommand(); + + // File Menu options + if (cmd.equals("saveUpicData")) saveUpicData(); + else if (cmd.equals("loadUpicData")) { + saveUpicData(); + mainframe.loadFile(file); + } else if (cmd.equals("saveUpicDataAs")) saveUpicDataAs(); + else if (cmd.equals("openUpicData")) openUpicData(); + else if (cmd.equals("clearUpicData")) clearUpicData(false); + else if (cmd.equals("envNameSelected")) envNameSelected(); + else if (cmd.equals("waveformNameSelected")) waveformNameSelected(); + else if (cmd.equals("showCs")) { + showCs = ((JCheckBoxMenuItem) e.getSource()).getState(); + canvas.history.save(canvas); + canvas.repaint(); + } else if (cmd.equals("showGrandStaff")) { + showGrandStaff = ((JCheckBoxMenuItem) e.getSource()).getState(); + canvas.history.save(canvas); + canvas.repaint(); + } else if (cmd.equals("showPicture")) { + showPicture = ((JCheckBoxMenuItem) e.getSource()).getState(); + canvas.history.save(canvas); + canvas.repaint(); + } else if (cmd.equals("loadPicture")) { + canvas.loadPicture(); + canvas.repaint(); + } else if (cmd.equals("undo")) { + canvas.history.undo(); + canvas.restore(); + } else if (cmd.equals("redo")) { + canvas.history.redo(); + canvas.restore(); + } else if (cmd.equals("comboBoxEdited")) { + if (e.getSource() == envName) envNewName(); + else if (e.getSource() == waveformName) waveformNewName(); + else System.out.println("COMBOBOXEDITED not handled\n"); + } else System.out.println("ACTION NOT HANDLED: " + cmd); + } + + + public void clearUpicData(boolean init) { + canvas.clearUpicData(init); + waveformName.removeAllItems(); + waveformName.addItem("*sine-table*"); + waveformName.addItem("*tri-table*"); + waveformName.addItem("*saw-table*"); + waveformName.setSelectedItem("*sine-table*"); + + envName.removeAllItems(); + envName.addItem("upic-env"); + envName.setSelectedItem("upic-env"); + } + + + public void addToComboBox(JComboBox cb, String s) { + int n = cb.getItemCount(); + for (int i = 0; i < n; i++) { + if (s.equals(cb.getItemAt(i))) return; + } + cb.addItem(s); + } + + + public void readUpicData(File fileToOpen) { + clearUpicData(false); + name = fileToOpen.getName(); + setTitle(name); + double maxt = 20, minhz = 0, maxhz = 2000; + boolean islinear = true; + // this disabled saving state for undo: + canvas.mouseDown = true; + try { + Scanner sc = new Scanner(fileToOpen); + String next = sc.next(); + while (next.charAt(0) == ';') { + if (next.equals(";!;")) { // parse parameters + if (!sc.next().equals("maxT") ) + throw new Exception("syntax - maxT"); + maxt = Double.parseDouble(sc.next()); + if (!sc.next().equals("minHz") ) + throw new Exception("syntax - minHz"); + minhz = Double.parseDouble(sc.next()); + if (!sc.next().equals("maxHz") ) + throw new Exception("syntax - maxHz"); + maxhz = Double.parseDouble(sc.next()); + if (!sc.next().equals("linear") ) + throw new Exception("syntax - linear"); + islinear = !sc.next().equals("nil"); + if (maxt < 0 || minhz < 20.0 || maxhz < minhz) { + throw new Exception("bad maxt, minhz, maxhz"); + } + } + sc.nextLine(); + next = sc.next(); + } + // next tokens are (s)et variable = + if (!next.equals("set")) throw new Exception("syntax - set"); + currentVarName = sc.next(); + varName.setText(currentVarName); + if (!sc.next().equals("=")) throw new Exception("syntax - ="); + // now read the first { + if (!sc.next().equals("{")) throw new Exception("syntax - {"); + // read lists + next = sc.next(); + while (next.equals("{")) { + String waveform = sc.next(); + addToComboBox(waveformName, waveform); + String envelope = sc.next(); + addToComboBox(envName, envelope); + System.out.println("waveform " + waveform + " env " + envelope); + canvas.startNewCurve(); + next = sc.next(); + while (!next.equals("}")) { + // System.out.println("time " + next); + double time = Double.parseDouble(next); + double freq = Double.parseDouble(sc.next()); + if (time < 0) time = 0; + canvas.insertInOrder(time, freq); + next = sc.next(); + } + next = sc.next(); + } + if (!next.equals("}")) { + throw new Exception("syntax"); + } + // make sure whole thing fits on canvas + maxT = Math.max(canvas.endTime(), maxt); + minHz = Math.min(canvas.lowHz(), minhz); + maxHz = Math.max(canvas.highHz(), maxhz); + isLinear = islinear; + + jMaxT.setText(String.valueOf(maxT)); + jMinHz.setText(String.valueOf(minHz)); + jMaxHz.setText(String.valueOf(maxHz)); + jLinear.setSelected(isLinear); + } catch (Exception e) { + System.out.println("readUpicData " + e); + JOptionPane.showMessageDialog(this, +"A problem was encountered reading a upic data file, data may have been lost"); + } + canvas.mouseDown = false; + } + + + public void openUpicData() { + JFileChooser chooser = new JFileChooser(); + SalFileFilter salFilter = new SalFileFilter(); + chooser.addChoosableFileFilter(salFilter); + File curdir = new File(mainframe.currentDir); + chooser.setCurrentDirectory(curdir); + int returnVal = chooser.showOpenDialog(this); + System.out.println("openUpicData chooser returns " + returnVal); + file = null; // in case open fails + if (returnVal == JFileChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + mainframe.changeDirectory(mainframe.fileDirectory(file)); + System.out.println("reading from " + file); + readUpicData(file); + modified = false; + } + } + + /* data = data.toLowerCase(); + //System.out.println("openUpicData: data |" + data + "| len " + data.length()); + envName.removeAllItems(); // clear and reload combo box + while (data.length() > 0) { + int eolx = data.indexOf("\n"); + if (eolx < 0) return; // shouldn't happen, but bail if it does + String line = data.substring(0, eolx); + //System.out.println("openUpicData: line " + line); + data = data.substring(eolx + 1); + String name = line.substring(0, line.indexOf(' ')); + System.out.println("openUpicData: name " + name); + String env = line.substring(name.length() + 1); + System.out.println("openUpicData: env " + env); + if (name.length() > 0) envColl.put(name, env); + envName.addItem(name); + } */ + + private class State { + public double maxT; + public double minHz; + public double maxHz; + public boolean linear; + public boolean cs; + public boolean gs; + public boolean picture; + + public State(double stop, double low, double hi, boolean lin, + boolean showcs, boolean showgs, boolean showpic) { + maxT = stop; minHz = low; maxHz = hi; linear = lin; + cs = showcs; gs = showgs; picture = showpic; + } + } + + private class History { + /* consider a sequence of undo/redo to be a single edit operation -- thus + * the end of the versions list is set to the latest undo/redo selection + */ + private boolean undoRedo = false; + private ArrayList> history = + new ArrayList>(); + private ArrayList state_history = new ArrayList(); + private int version = -1; + + @SuppressWarnings("unchecked") + public void save(PiecewiseCanvas canvas) { + history.add((ArrayList) canvas.curves.clone()); + state_history.add(new State(maxT, minHz, maxHz, isLinear, + showCs, showGrandStaff, showPicture)); + version = history.size() - 1; + System.out.println("Saved version " + version); + undoRedo = false; /* clear flag for next undoRedo sequence */ + } + + public boolean canGet() { + boolean result = version >= 0 && version < history.size(); + System.out.println("canGet returns " + result + " version " + + version); + return result; + } + + public ArrayList getCurves() { return history.get(version); } + + public State getState() { return state_history.get(version); } + + @SuppressWarnings("unchecked") + private void processUndoRedo() { + if (!undoRedo) { /* extend with copy of the version */ + history.add((ArrayList) (history.get(version).clone())); + state_history.add(state_history.get(version)); + } else { /* replace with different version */ + history.set(history.size() - 1, + (ArrayList) (history.get(version).clone())); + state_history.set(state_history.size() - 1, + state_history.get(version)); + } + undoRedo = true; + } + + public void undo() { + if (version > 0) { + version--; + processUndoRedo(); + } + } + public void redo() { + if (version < history.size() - 1) { + version++; + processUndoRedo(); + } + } + } + + private class Curve { + public String waveform; + public String envelope; + public ArrayList times; + public ArrayList freqs; + + public Curve(String wave, String env) { + waveform = wave; + envelope = env; + times = new ArrayList(); + freqs = new ArrayList(); + } + } + + // Class for the drawing area + //private class PiecewiseCanvas extends Canvas implements MouseListener, + private class PiecewiseCanvas extends JPanel implements MouseListener, + MouseMotionListener, KeyListener { + private int currentHz; + private int currentTime; + public BufferedImage image = null; + public boolean selectCheck = false; + public int selection; + public History history; + + public boolean mouseDown = false; // used to detect version for undo + private boolean changed = false; // used to detect version for undo + + // Vectors to store the absolute parameters of the points in the + // envelope. + public ArrayList curves = new ArrayList(); + public int selectedCurve; + private int left, top, width, height; + + private BufferedImage background; + + // Constructor + public PiecewiseCanvas() { + setBackground(Color.white); + addMouseListener(this); + addMouseMotionListener(this); + addKeyListener(this); + selection = -1; + history = new History(); + history.save(this); + selectedCurve = -1; + background = null; + } + + + public void loadPicture() { + JFileChooser chooser = new JFileChooser(); + File curdir = new File(mainframe.currentDir); + chooser.setCurrentDirectory(curdir); + int returnVal = chooser.showOpenDialog(this); + File file = null; // in case open fails + if (returnVal == JFileChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + mainframe.changeDirectory(mainframe.fileDirectory(file)); + System.out.println("reading image from " + file); + try { + background = ImageIO.read(file); + } catch (Exception e) { + System.out.println("Image read failed " + e); + JOptionPane.showMessageDialog(this, + "Could not open image file"); + background = null; + } + } + } + + + public double endTime() { + double m = 0; + for (Curve c : curves) { + for (double time : c.times) { + m = Math.max(m, time); + } + } + return m; + } + + public double lowHz() { + double low = 20000; + for (Curve c : curves) { + for (double hz : c.freqs) { + low = Math.min(low, hz); + } + } + return low; + } + + public double highHz() { + double high = 0; + for (Curve c : curves) { + for (double hz : c.freqs) { + high = Math.max(high, hz); + } + } + return high; + } + + + // erase the canvas and clear the parameter vectors - + // completely reset the envelope + public void clearUpicData(boolean init) { + curves.clear(); + if (!init) setModified(); + repaint(); + history.save(this); + } + + + // Allow JPanel to accept keyboard events + public boolean isFocusable() { + return true; + } + + //try to make the canvas the correct size + public Dimension getMinimumSize() { + return new Dimension(0, 0); + } + + public Dimension getPreferredSize() { + return new Dimension(575, 256); + } + + public double impliedAmp() { + return 0.0; + } + + + /* + public Dimension getMaximumSize() { + return getPreferredSize(); + }*/ + + // draw the graphics inside the full canvas, so use these + // functions to get the size and coordinates of the drawing + // area that is usable + private int graphLeft() { return LEFT_BORDER; } + private int graphWidth() { + return getWidth() - (LEFT_BORDER + RIGHT_BORDER); + } + private int graphTop() { return TOP_BORDER; } + private int graphHeight() { + return getHeight() - (TOP_BORDER + BOTTOM_BORDER); + } + private int clipX(int x) { + return Math.max(LEFT_BORDER, Math.min(left + width, x)); } + private int clipY(int y) { + return Math.max(BOTTOM_BORDER, Math.min(top + height, y)); } + + // public String getExpression() { + // String env; + // + // /*if (type == PWL_TYPE) env = (valueType ? "pwlv" : "pwl"); + // else env = (valueType ? "pwev" : "pwe");*/ + // + // env = "pwlv"; + // + // return outputEnv(env, true, 0.0, // getMinT(), + // getMaxT(), getMinHz(), getMaxHz()); + // } + + //draw the canvas image + public void paint(Graphics g) { + super.paint(g); + + Graphics2D drawArea = (Graphics2D) g; + if (showCs) { // draw line for C in all octaves + double hz = 16.3516; + while (hz < maxHz) { + drawPitch(drawArea, hz); + hz *= 2; + } + } + + if (showPicture && (background != null)) { + drawArea.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + int x = time2x(0); + int y = hz2y(maxHz); + int w = time2x(maxT) - x; + int h = hz2y(minHz) - y; + drawArea.drawImage(background, x, y, w, h, null); + } + + if (showGrandStaff) { // draw GrandStaff lines + drawPitch(drawArea, 698.456); // top line F + drawPitch(drawArea, 587.330); // D + drawPitch(drawArea, 493.883); // B + drawPitch(drawArea, 391.995); // G + drawPitch(drawArea, 329.628); // E + + drawPitch(drawArea, 220.000); // A + drawPitch(drawArea, 174.614); // F + drawPitch(drawArea, 146.832); // D + drawPitch(drawArea, 123.471); // B + drawPitch(drawArea, 97.9989); // G + } + + connectTheDots(drawArea); + drawArea.dispose(); + } + + private void drawPitch(Graphics2D g, double hz) { + g.setColor(Color.lightGray); + int y = hz2y(hz); + g.drawLine(time2x(0), y, time2x(maxT), y); + } + + private void draw_connect(Graphics2D g, double t1, double a1, + double t2, double a2) { + int x1 = time2x(t1); + int x2 = time2x(t2); + int y1 = hz2y(a1); + int y2 = hz2y(a2); + + g.drawLine(x1, y1, x2, y2); + } + + private void cacheSize() { + left = graphLeft(); + top = graphTop(); + width = graphWidth() - 1; + height = graphHeight() - 1; + } + + //connect adjacent points in the envelope by lines + private void connectTheDots(Graphics2D g) { + cacheSize(); + for (int j = 0; j < curves.size(); j++) { + g.setColor(selectedCurve == j ? Color.red : Color.blue); + Curve c = curves.get(j); + if (c.times.size() > 0) { + //connect the points in the envelope + double t1 = c.times.get(0); + double a1 = c.freqs.get(0); + + for (int i = 1; i < c.times.size(); i++) { + double t2 = c.times.get(i); + double a2 = c.freqs.get(i); + draw_connect(g, t1, a1, t2, a2); + t1 = t2; + a1 = a2; + } + } + } + } + + + @SuppressWarnings("unchecked") + public void restore() { + if (history.canGet()) { + curves = (ArrayList) (history.getCurves().clone()); + State state = history.getState(); + maxT = state.maxT; + jMaxT.setText(String.valueOf(state.maxT)); + minHz = state.minHz; + jMinHz.setText(String.valueOf(state.minHz)); + maxHz = state.maxHz; + jMaxHz.setText(String.valueOf(state.maxHz)); + isLinear = state.linear; + jLinear.setSelected(state.linear); + showCs = state.cs; + showGrandStaff = state.gs; + showPicture = state.picture; + selection = -1; + repaint(); + } + } + + //set time and amplitude on click by inserting the point into the vectors. + public void mousePressed(MouseEvent e) { + requestFocus(); + cacheSize(); + // check for curve selection + if (e.getButton() == MouseEvent.BUTTON3) { + for (int x = 0; x < curves.size(); x++) { + Curve c = curves.get(x); + for (int y = 0; y < c.times.size(); y++) { + if (Math.abs(time2x(c.times.get(y)) - e.getX()) <= 8 && + Math.abs(hz2y(c.freqs.get(y)) - e.getY()) <= 8) { + selectedCurve = x; + repaint(); + System.out.println("Selected curve " + x); + System.out.println("e.getX(): " + e.getX()+ + ", e.getY: " + e.getY()); + System.out.println("c.times.get(y): " + + c.times.get(y) + + ", c.freqs.get(y): " + + c.freqs.get(y)); + return; + } + } + } + + selectedCurve = -1; + repaint(); + System.out.println("No curve selected"); + return; + } + + // not button3, so start a new curve + startNewCurve(); + mouseDown = true; + System.out.println("mouseDown true\n"); + this.requestFocus(); + currentTime = e.getX(); + currentHz = e.getY(); + insertInOrder(x2time(currentTime), y2hz(currentHz)); + repaint(); + } + + + public void mouseDragged(MouseEvent e) { + // if this is not the left button drawing event, return + if (!mouseDown) return; + currentTime = clipX(e.getX()); + currentHz = clipY(e.getY()); + + if (currentTime <= left + width && currentTime >= left && + currentHz >= top && currentHz <= top + height) { + + insertInOrder(x2time(currentTime), y2hz(currentHz)); + repaint(); + } + } + + + public void startNewCurve() { + curves.add(new Curve((String) waveformName.getSelectedItem(), + (String) envName.getSelectedItem())); + } + + public void mouseReleased(MouseEvent e) { + requestFocus(); // otherwise, delete key may not work + if (e.getButton() != MouseEvent.BUTTON1) + return; + if (changed) { + history.save(this); + changed = false; + } + mouseDown = false; + } + + + // convert time coordinate to time in seconds + private double x2time(int x) { + return (x - left) * maxT / width; + } + + private int time2x(double time) { + return (int) Math.round(time * width / maxT) + left; + } + + // convert amp coordinate to real amplitude + private double y2hz(int y) { + double mx, mn, r; + if (isLinear) { + mx = maxHz; + mn = minHz; + r = mx - mn; + return mx - ((y - top) * r / height); + } + mx = Math.log(maxHz); + mn = Math.log(minHz); + r = mx - mn; + return Math.exp(mx - ((y - top) * r / height)); + } + + private int hz2y(double hz) { + double mx, mn; + if (isLinear) { + mx = maxHz; + mn = minHz; + } else { + mx = Math.log(maxHz); + mn = Math.log(minHz); + hz = Math.log(hz); + } + double r = mx - mn; + return (int) Math.round((mx - hz) * height / r) + top; + } + + private void addPoint(int i, double absT, double absA) { + addPoint(curves.size() - 1, i, absT, absA); + } + + private void addPoint(int curve, int i, double absT, double absA) { + //System.out.println("addPoint: " + i + " " + absT + " " + absA); + Curve c = curves.get(curve); + c.times.add(i, absT); + c.freqs.add(i, Math.max(absA, 0.0)); + //System.out.println("addPoint time: " + absT + ", text " + form.format(absT)); + selection = i; + changed = true; + setModified(); + } + + + //insert the time and amplitude in the vectors in time sorted order + private void insertInOrder(double time, double amp) { + Curve c = curves.get(curves.size() - 1); + int i = c.times.size(); + while (i > 0 && time < c.times.get(i - 1)) { + i--; + } + addPoint(i, time, amp); + } + + + // Check if mouse click corresponds to existing envelope point + // return index of point or -1 if no point is close + // private int getSelection(int x, int y) { + // int cutoff = 7; + // int bestDist = cutoff * 2; + // int bestIndex = -1; + // if (times == null) return bestIndex; + // for (int i = 0; i < times.get(curCurve).size(); i++) { + // int xi = time2x(times.get(curCurve).get(i)); + // int yi = hz2y(freqs.get(curCurve).get(i)); + // int dx = Math.abs(x - xi); + // int dy = Math.abs(y - yi); + // if (dx < cutoff && dy < cutoff && dx + dy < bestDist) { + // bestDist = dx + dy; + // bestIndex = i; + // } + // } + // selection = bestIndex; + // return bestIndex; + // } + + //Check if mouse click corresponds with existing envelope point (to select point) + // private boolean checkSelection(int time, int amp) { + // int i = getSelection(time, amp); + // if (i < 0) return false; + // repaint(); + // return true; + // } + + //output the envelope as a string + // public String outputEnv(String envType, boolean valueType, double minTime, double maxTime, double minHertz, double maxHertz) { + // String outputStr = "(sim"; + // + // for (int j = 0; j < times.size() - 1; j++) { + // int start = 0; + // outputStr += " (osc-tri (" + envType; + // + // if (valueType) { // insert initial value + // if (within(times.get(j).get(0), 0.0, EPSILON)) { + // outputStr += " " + form.format(freqs.get(j).get(0)); + // start = 1; + // } else + // outputStr += " " + form.format(impliedAmp()); + // } + // + // for (int i = start; i < freqs.get(j).size(); i++) { + // double time = times.get(j).get(i); + // double amp = freqs.get(j).get(i); + // + // if (time == 1) + // break; + // + // outputStr += " " + form.format(time) + " " + form.format(amp); + // } + // + // if (valueType) { // we're already ending with a value + // if (within(times.get(j).lastElement(), maxTime, EPSILON)) { + // // we're done because we output at maxTime + // } else + // outputStr += " " + form.format(maxTime) + " " + form.format(impliedAmp()); + // } else + // outputStr += " " + form.format(maxTime); + // + // outputStr += "))"; + // } + // outputStr += ")"; + // return outputStr; + // } + + // parse envelope from string and prepare to edit + // public void setEnv(String envData) { + // + // System.out.println("\nCALLED setEnv\n"); + // + // // System.out.println("setEnv: envData " + envData.substring(0, 100) + " ... " + envData.substring(envData.length()-5)); + // if (envData == null) return; // just in case + // //check if envelope exists in collection + // //boolean nameIsEnv = false; + // + // // trim the open and close parens from envData + // int startx = envData.indexOf("(") + 5; + // // if no open paren, startx will be 0 + // int endx = envData.lastIndexOf(")"); + // if (endx < 0) endx = envData.length(); + // envData = envData.substring(startx, endx); + // + // int x = 0; + // while (envData.indexOf("(") > -1) { + // String strCurve = envData.substring(envData.indexOf("(")+10, envData.indexOf(")")); + // envData = envData.substring(envData.indexOf(")")+2); + // + // StringTokenizer st = new StringTokenizer(strCurve); + // String type = st.nextToken(); + // System.out.println("setEnv: type " + type); + // + // valueType = type.endsWith("v"); + // + // if (times.size() <= x) { + // times.add(new Vector()); + // freqs.add(new Vector()); + // } + // + // times.get(x).removeAllElements(); + // freqs.get(x).removeAllElements(); + // int i = 0; + // // pretend mouse is down to avoid making each point undo-able + // boolean save = mouseDown; + // mouseDown = false; + // double time, amp; + // if (valueType) { // first element is value + // amp = new Double(st.nextToken().trim()); + // addPoint(x, i++, 0.0, amp); + // } + // while (st.countTokens() >= 2) { + // String token1 = st.nextToken().trim(); + // time = new Double(token1); + // String token2 = st.nextToken().trim(); + // amp = new Double(token2); + // addPoint(x, i++, time, amp); + // /*System.out.println("time " + token1 + " amp " + token2 + + // " size " + times.get(x).size());*/ + // } + // + // mouseDown = save; // restore the mouseDown state + // if (!valueType) { // last element is time + // maxT.setText(st.nextToken()); + // } + // + // x++; + // } + // + // times.add(new Vector()); + // freqs.add(new Vector()); + // curCurve = x; + // System.out.println("curCurve: " + curCurve); + // + // modified = false; + // repaint(); + // } + + + public void keyPressed(KeyEvent event) { + System.out.println("key event detected"); + if (event.getKeyCode() == KeyEvent.VK_DELETE) { + curves.remove(selectedCurve); + selectedCurve = -1; + canvas.history.save(canvas); + System.out.println("curve should be deleted"); + repaint(); + } + } + + //fill rest of mouse functions + public void mouseEntered(MouseEvent e) {} + public void mouseExited(MouseEvent e) {} + public void mouseClicked(MouseEvent e) {} + public void mouseMoved(MouseEvent e) {} + public void keyReleased(KeyEvent event) {} + public void keyTyped(KeyEvent event) {} + } +} diff --git a/jnyqide/WordList.java b/jnyqide/WordList.java new file mode 100644 index 0000000..758476f --- /dev/null +++ b/jnyqide/WordList.java @@ -0,0 +1,247 @@ +package jnyqide; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; + + +import javax.swing.JTextArea; +import javax.swing.JTextPane; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultStyledDocument; + +public class WordList { + //public static Trie wordsTrie = new Trie(); + public static JTextArea textArea; + public static JTextPane pane; + public static int startPos; + public static int endPos; + public static Map URLLinks = new HashMap(); + public static ArrayList words = new ArrayList (); + + public static String getlink(String word) { + // strip off syntax help from word, e.g. (osc-tri hz) -> osc + System.out.println("getlink " + word); + if (word.charAt(0) == '(') { + int i = word.indexOf(" "); + if (i <= 0) i = word.length() - 1; // remove ")" + word = word.substring(1, i); + } else /* maybe SAL mode */ { + int i = word.indexOf("("); + if (i > 0) word = word.substring(0, i); + } + String s = URLLinks.get(word); + System.out.println("getlink(" + word + ")->" + s); + if (s == null) return "home.html"; + return s; + } + + public static void init(JTextArea a) + { + textArea = a; + //System.out.println("initializing WordList.java"); + try { + BufferedReader inf; + try { + inf = new BufferedReader(new FileReader("NyquistWords.txt")); + System.out.println("\n\n***********************Opened NyquistWords.txt*********\n\n"); + } catch (IOException e) { + System.out.println("could not find NyquistWords.txt, trying jnyqide/NyquistWords.txt"); + inf = new BufferedReader(new FileReader("jnyqide/NyquistWords.txt")); + } + String word, link; + while ((word = inf.readLine()) != null) { + //wordsTrie.addWord(word); + words.add(word); + link = inf.readLine(); + if ((link == null) || (link.equals(""))) link = "home.html"; + //char[] letters = word.toCharArray(); + //if (letters[letters.length-1] == ')') word = "(" + word; + //URLLinks.put(word, link); + // word is usually an expression, e.g. + // "transpose-abs amount beh)", so parse out the first word + int i = word.indexOf(" "); + if (i >= 0) word = word.substring(0, i); + i = word.indexOf(")"); + if (i >= 0) word = word.substring(0, i); + URLLinks.put(word, link); + } + inf.close(); + } catch (IOException e) { + System.out.println("Error: could not open NyquistWords.txt"); + } + } + + public static String removeChar(String word, char c) { + int loc = word.indexOf(c); + while (loc >= 0) { + word = word.substring(0, loc) + word.substring(loc + 1); + loc = word.indexOf(c); + } + return word; + } + + public static void appendSyntaxTip(StringBuffer s, String word, boolean sal) { + // let's keep the brackets until we copy the hint string into an editor + // first, remove brackets + // word = removeChar(removeChar(word, '['), ']'); + // if this is a lisp expression, append close paren + if (word.charAt(word.length() - 1) == ')') { + if (sal) { + // make it prefix with commas + int loc = word.indexOf(' '); // end of function name + int loc2 = loc + 1; // trim the space + if (loc < 0) { + loc = word.indexOf(')'); + loc2 = loc; // don't trim the ')' + } + if (loc < 0) { + System.out.println("appendSyntaxTip internal error: |" + + word + "|"); + return; + } + // now loc is the character after the function name and + // loc2 is the character to place after the open paren + word = word.substring(0, loc) + "(" + word.substring(loc2); + // insert commas after tokens starting after open paren + loc = loc + 1; + while (loc < word.length()) { + // advance to token + while (loc < word.length() && + (word.charAt(loc) == ' ' || + word.charAt(loc) == '[' || + word.charAt(loc) == ']')) loc++; + // retain starting location for keyword processing + loc2 = loc; + // advance to end of word + while (loc < word.length() && + word.charAt(loc) != ' ' && + word.charAt(loc) != '[' && + word.charAt(loc) != ']') loc++; + // convert to keyword or maybe add comma + if (loc < word.length()) { + if (word.charAt(loc2) == ':') { + word = word.substring(0, loc2) + // before keyword + word.substring(loc2 + 1, loc) + // after ':' + ":" + word.substring(loc); + // insert comma if this is not the last parameter, + // determined by looking ahead for a space + } else if (word.indexOf(' ', loc) > 0) { + word = word.substring(0, loc) + "," + + word.substring(loc); + loc = loc + 1; // skip the comma + } + } + // System.out.println("word |" + word + "| loc " + loc); + } + } else { + s.append("("); + } + } + s.append(word); + s.append("\n"); + } + + + public static void getAllWordsFor(String str, StringBuffer s, boolean sal) { + for (int i = 0; i < words.size(); i++) { + String word = (String) words.get(i); + int pos = word.indexOf(str); + if (pos >= 0) { + int sp = word.indexOf(" "); + if (sp < 0 || sp > pos) { + appendSyntaxTip(s, word, sal); + } + } + } + } + + + public static boolean isKeyword(String str) { + String s = URLLinks.get(str); + return s != null; + /* + str = str.toLowerCase(); + for (int i = 0; i < words.size(); i++) { + String word = (String) words.get(i); + int pos = word.indexOf(str); + if (pos == 0 && + (word.length() == str.length() || + (word.charAt(str.length() - 1) == ' ' || + word.charAt(str.length() - 1) == ')'))) { + return true; + } + } + return false; + */ + } + + + public static void getWordsFor(String str, StringBuffer s, boolean sal) { + for (int i = 0; i < words.size(); i++) { + String word = (String) words.get(i); + int pos = word.indexOf(str); + if (pos == 0) { + appendSyntaxTip(s, word, sal); + } + } + } + + + public static void printList(String str, JTextPane jTextPane, + int start, int end, boolean forceExact, boolean sal) { + + //List l; + //System.out.println("printList: prefFullSearch = " + MainFrame.prefFullSearch); + //if (MainFrame.prefFullSearch) l = wordsTrie.getAllWordsFor(str.toLowerCase()); + //else l = wordsTrie.getWordsFor(str.toLowerCase(), false); + //System.out.println(l); + //StringBuffer s = new StringBuffer(); + //if (l != null) { + // Iterator iter = l.iterator(); + // while (iter.hasNext()) { + // s.append(iter.next()).append("\n"); + // } + //} + StringBuffer s = new StringBuffer(); + str = str.toLowerCase(); + if (MainFrame.prefFullSearch && !forceExact) getAllWordsFor(str, s, sal); + else getWordsFor(str, s, sal); + textArea.setText(s.toString()); + pane = jTextPane; + startPos = start; + endPos = end; // haven't inserted character yet + } + + + public static void replaceWithTemplate(String template) { + // templates were displayed in textArea based on what the user + // typed. Now, the user has clicked on a template. Replace what + // the user typed (and parens) with the template string. + String before; + try { + before = pane.getText(startPos - 1, 1); + if (before.equals("(")) startPos--; + } catch (Exception ex) { + } + String after; + try { + after = pane.getText(endPos, 1); + while (Character.isWhitespace(after.charAt(0))) { + endPos++; + after = pane.getText(endPos, 1); + } + if (after.equals(")")) endPos++; + } catch (Exception ex) { + } + pane.select(startPos, endPos); + // remove those pesky brackets (denoting "optional") + template = removeChar(removeChar(template, '['), ']'); + pane.replaceSelection(template); + } +} diff --git a/jnyqide/browser.java b/jnyqide/browser.java new file mode 100644 index 0000000..2db6cb0 --- /dev/null +++ b/jnyqide/browser.java @@ -0,0 +1,439 @@ +package jnyqide; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.ArrayList; + +import javax.swing.BorderFactory; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSlider; +import javax.swing.JTextArea; +import javax.swing.ListModel; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.SpringLayout; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeListener; +import javax.swing.event.ChangeEvent; + + +/*** +** Class: Browser +** Author: Priyanka Raghavan and Roger B. Dannenberg +** Description: This is the frame class that implements the sound browser. +**/ + +class Browser extends JInternalFrame { + + NyquistThread nyquistThread; + MainFrame mainFrame; + ArrayList instruments; + InstrumentCharacteristics currentInstr; + + /** + * @ desc Default constructor, takes the nyquist thread from main frame + * @author prirags - removed all references to the log factory + */ + + public Browser(MainFrame mainFrame, NyquistThread nyquistThread) { + this.mainFrame = mainFrame; + this.nyquistThread=nyquistThread; + instruments = new ArrayList(); + currentInstr = null; + try { + System.out.println("in Browser()"); + initGUI(); + setLocation(50+10, 50+10); + setSize(600, 500); + setResizable(true); + setVisible(true); + setClosable(true); + setMaximizable(true); + setIconifiable(true); + // setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); + System.out.println("at end of Browser()"); + } + catch (Exception exception) { + exception.printStackTrace(); + } + } + + /** + * @ desc intializes gui elements + * @author prirags - removed all references to the log factory + */ + + private void initGUI() { + setTitle("Sound Browser"); + this.setSize(800, 513); + jPanel1 = new JPanel(new SpringLayout()); + Border etchedLine; + etchedLine = BorderFactory.createEtchedBorder(EtchedBorder.RAISED); + this.getContentPane().add(jPanel1, BorderLayout.NORTH); + jPanel1.setBorder(etchedLine); + // jPanel1.setPreferredSize(new java.awt.Dimension(638, 101)); + categoryLabel = new JLabel(); + jPanel1.add(categoryLabel); + categoryLabel.setText("Sound Category:"); + ComboBoxModel categoryComboModel = new DefaultComboBoxModel(); + categoryCombo = new JComboBox(); + categoryCombo.addItemListener( + new ItemListener() { + public void itemStateChanged(ItemEvent evt) { + if (evt.getStateChange() != evt.SELECTED) return; + if (subcategoryCombo == null) return; // just in case + // set up subcategory + subcategoryCombo.removeAllItems(); + subcategoryCombo.addItem("Select One"); + String category = (String) evt.getItem(); + System.out.println("category is " + category); + for (int i = 0; i < instruments.size(); i++) { + if (((InstrumentCharacteristics) instruments.get(i)). + getCategoryName().equalsIgnoreCase(category)) { + subcategoryCombo.addItem( + ((InstrumentCharacteristics) instruments. + get(i)).getSubcategoryName()); + } + } + } + }); + jPanel1.add(categoryCombo); + categoryCombo.setModel(categoryComboModel); + // categoryCombo.setPreferredSize(new java.awt.Dimension(306, 25)); + subcategoryLabel = new JLabel(); + jPanel1.add(subcategoryLabel); + subcategoryLabel.setText("Sound Name:"); + ComboBoxModel subcategoryComboModel = new DefaultComboBoxModel(); + subcategoryCombo = new JComboBox(); + subcategoryCombo.addItemListener( + new ItemListener() { + public void itemStateChanged(ItemEvent evt) { + for (int i = 0; i < instruments.size(); i++) { + InstrumentCharacteristics ic = + (InstrumentCharacteristics) instruments.get(i); + String name = (String) evt.getItem(); + if (ic.getSubcategoryName().equalsIgnoreCase(name)) { + currentInstr = ic; + visitSound(); + } + } + } + }); + jPanel1.add(subcategoryCombo); + subcategoryCombo.setModel(subcategoryComboModel); + // subcategoryCombo.setPreferredSize(new java.awt.Dimension(304, 28)); + SpringUtilities.makeCompactGrid(jPanel1, 2, 2, 6, 6, 6, 6); + + + jPanel3 = new JPanel(new SpringLayout()); + this.getContentPane().add(jPanel3, BorderLayout.CENTER); + etchedLine = BorderFactory.createEtchedBorder(EtchedBorder.RAISED); + jPanel3.setBorder(etchedLine); + // jPanel3.setPreferredSize(new java.awt.Dimension(638, 148)); + + BorderLayout bl = new BorderLayout(); + bl.setHgap(6); + bl.setVgap(6); + jPanel2 = new JPanel(bl); + this.getContentPane().add(jPanel2, BorderLayout.SOUTH); + etchedLine = BorderFactory.createEtchedBorder(EtchedBorder.RAISED); + jPanel2.setBorder(etchedLine); + // jPanel2.setPreferredSize(new java.awt.Dimension(791, 159)); + + playButton = new JButton(); + playButton.setText("PLAY"); + // playButton.setPreferredSize(new java.awt.Dimension(100, 36)); + // playButton.setBounds(4, -5, 100, 36); + playButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + playSound(); + } + + }); + + // try this: + // (west: (north: play button)) + // center: (north: + // (center: "Lisp Expression that produced the sound") + // center: scrolling text)) + bl = new BorderLayout(); + bl.setHgap(6); + bl.setVgap(6); + JPanel jPanel2a = new JPanel(bl); + jPanel2.add(jPanel2a, BorderLayout.WEST); + jPanel2a.add(playButton, BorderLayout.NORTH); + bl = new BorderLayout(); + bl.setHgap(6); + bl.setVgap(6); + JPanel jPanel2b = new JPanel(bl); + jPanel2.add(jPanel2b, BorderLayout.CENTER); + bl = new BorderLayout(); + bl.setHgap(6); + bl.setVgap(6); + JPanel jPanel2b1 = new JPanel(bl); + jPanel2b.add(jPanel2b1, BorderLayout.NORTH); + JLabel label = new JLabel("Lisp Expression that produced the sound:"); + label.setHorizontalAlignment(label.CENTER); + jPanel2b1.add(label, BorderLayout.CENTER); + jScrollPane1 = new JScrollPane(); + expArea = new JTextArea(); + jScrollPane1.setViewportView(expArea); + + // expArea.setPreferredSize(new java.awt.Dimension(650, 60)); + + jPanel2b.add(jScrollPane1, BorderLayout.CENTER); + jScrollPane1.setPreferredSize(new java.awt.Dimension(700, 62)); + // SpringUtilities.makeCompactGrid(jPanel2, 2, 2, 6, 6, 6, 6); + + categoryCombo.addItem("Select One"); + + // read the instrument.txt text file from lib + // and create the InstrumentCharacteristic objects. + // + BufferedReader br; + try { + br = new BufferedReader( + new FileReader(nyquistThread.soundBrowser)); + } catch (Exception e) { + System.out.println("ERROR -- could not open " + + nyquistThread.soundBrowser); + return; + } + while (true) { + InstrumentCharacteristics ic = + new InstrumentCharacteristics(); + if (!ic.readData(br)) break; + System.out.println("new IC: " + ic.getCategoryName() + ":" + + ic.getSubcategoryName()); + instruments.add(ic); + boolean foundIt = false; + for (int k = 0; k < categoryCombo.getItemCount(); k++) { + if (categoryCombo.getItemAt(k).toString(). + equalsIgnoreCase(ic.getCategoryName())) { + foundIt = true; + break; + } + } //end of for + if (!foundIt) { + System.out.println("Added " + ic.getCategoryName()); + categoryCombo.addItem(ic.getCategoryName()); + } + } + } + + private JPanel jPanel1; + private JComboBox subcategoryCombo; + private JLabel subcategoryLabel; + private JLabel categoryLabel; + private JComboBox categoryCombo; + + private JScrollPane jScrollPane1; + + private JPanel jPanel3; + private JTextArea expArea; + private JButton playButton; + + private JPanel jPanel2; + private JLabel[] paramLabels = null; + private JSlider[] paramSliders = null; + + public void newParameterCount(int n) { + // make array for new labels and sliders + JLabel[] newParamLabels = paramLabels; + JSlider[] newParamSliders = paramSliders; + int oldN = 0; + if (paramLabels != null) { + oldN = paramLabels.length; + } + if (n > oldN) { + newParamLabels = new JLabel[n]; + newParamSliders = new JSlider[n]; + } + // make old labels and sliders invisible before reuse + if (paramLabels != null) { + // paramLabel0.setVisible(false); + for (int i = 0; i < oldN; i++) { + paramLabels[i].setVisible(false); + newParamLabels[i] = paramLabels[i]; + + paramSliders[i].setVisible(false); + newParamSliders[i] = paramSliders[i]; + } + } else { + // paramLabel0 = new JLabel(); + // paramLabel0.setText("SLIDERS"); + // jPanel3.add(paramLabel0); + } + // if we don't have enough, make more + if (n > oldN) { + for (int i = oldN; i < n; i++) { + newParamLabels[i] = new JLabel(); + jPanel3.add(newParamLabels[i]); + newParamSliders[i] = new JSlider(); + jPanel3.add(newParamSliders[i]); + } + paramLabels = newParamLabels; + paramSliders = newParamSliders; + } + SpringUtilities.makeCompactGrid(jPanel3, n, 2, 6, 6, 6, 6); + + // now we have n labels and sliders in arrays + // we also have paramLabel0 + } + + + public void visitSound() { + System.out.println("visitSound called: " + + currentInstr.getSubcategoryName()); + /* + * This hides the labels and the sliders that could have + * been created in previous runs + */ + int numParams = currentInstr.getParameters().size(); + newParameterCount(numParams); + System.out.println("visitSound: numParams " + numParams); + + for(int i = 0; i < numParams; i++) { + Parameter p = (Parameter) (currentInstr.getParameters().get(i)); + paramLabels[i].setText(p.getName().toUpperCase()); + System.out.println("Parameter" + p.getName()); + paramLabels[i].setVisible(true); + if (p.getType().equals("int")) { + final JSlider s = paramSliders[i]; + int max = Integer.parseInt(p.getMaxValue()); + s.setMaximum(max); + int min = Integer.parseInt(p.getMinValue()); + s.setMinimum(min); + int range = max - min; + int major = 1; + while (major < range) major *= 10; + s.setMajorTickSpacing(major / 10); + s.setMinorTickSpacing(major / 100); + System.out.println("major " + major); + s.setPaintTicks(true); + s.setPaintLabels(true); + s.setValue(Integer.parseInt(p.getDefaultValue())); + } else if (p.getType().equals("float")) { + final float min = Float.valueOf(p.getMinValue()).floatValue(); + final float max = Float.valueOf(p.getMaxValue()).floatValue(); + final float width = max - min; + final Parameter param = p; + final JSlider s = paramSliders[i]; + float fval = Float.valueOf(p.getDefaultValue()).floatValue(); + param.setValue(fval); + s.setMinimum(0); + s.setMaximum(1000); + s.setValue((int) ((fval - min) / width * 1000)); + java.util.Hashtable labels = new java.util.Hashtable(3); + labels.put(new Integer(0), new JLabel(p.getMinValue())); + labels.put(new Integer(500), + new JLabel(new Float((max + min) / 2.0f). + toString())); + labels.put(new Integer(1000), new JLabel(p.getMaxValue())); + s.setLabelTable(labels); + s.setPaintTicks(false); + s.setPaintLabels(true); + // s.setBorder(new TitledBorder("border text")); + s.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + int j = s.getValue(); + float f = min + (j * width / 1000.0f); + param.setValue(f); + } + }); + } else { + System.out.println("Expected int or float in " + + i + " |" + p.getType() + "|"); + } + + if (numParams > 1) { + paramSliders[i].setOrientation(JSlider.HORIZONTAL); + } else { + paramSliders[i].setOrientation(JSlider.HORIZONTAL); + } + paramSliders[i].setVisible(true); + } + } + + + public void playSound() { + boolean isSal = mainFrame.jScrollPane.isSal; + /* debugging + System.out.println("isSal: " + isSal + "\n" + + currentInstr.getFunctionName() + "\nSal: " + + currentInstr.getSalImplementation() + "\nLisp: " + + currentInstr.getLispImplementation() + "\nReq: " + + currentInstr.getRequire()); + end debugging */ + String cmd = (isSal ? "play " : "(play (") + + currentInstr.getFunctionName(); + String sep = (isSal ? ", " : " "); + if (isSal) cmd = cmd + "("; + boolean first = isSal; + for (int i = 0; i < currentInstr.getParameters().size(); i++) { + Parameter p = (Parameter) currentInstr.getParameters().get(i); + // is this a keyword parameter? If so, put it in + if (p.getName().charAt(0) == ':') { + if (!first) cmd = cmd + sep; + cmd = cmd + p.getName(); + first = false; + } + String actual; + if (p.getType().equals("int")) { + actual = new Integer(paramSliders[i].getValue()).toString(); + } else if (p.getType().equals("float")) { + actual = new Float(p.getValue()).toString(); + } else { + actual = ""; + System.out.println("bad parameter type"); + } + if (!first) cmd = cmd + sep; + first = false; + cmd = cmd + actual; + } + if (!isSal) cmd = cmd + ")"; // to match (play + cmd = cmd + ")\n"; + String impl = (isSal ? currentInstr.getSalImplementation() : + currentInstr.getLispImplementation()); + if (impl == null && currentInstr.getRequire() != null) { + impl = currentInstr.getRequire(); + if (isSal) { + impl = "if ! fboundp(quote(" + currentInstr.getFunctionName() + + ")) then load " + impl + "\n"; + } else { + impl = "(if (not (fboundp '" + currentInstr.getFunctionName() + + ")) (load " + impl + "))\n"; + } + } + if (impl != null) { + if (isSal) { // for SAL, need one command + cmd = "begin\n " + impl + " " + cmd + "end\n"; + } else { + cmd = impl + cmd; // lisp can take sequence of commands + } + } + cmd = cmd + "\n"; // need extra newline to cause parser to run + expArea.setText(cmd); + mainFrame.sendInput(cmd); + } +} + diff --git a/jnyqide/closeFile.gif b/jnyqide/closeFile.gif new file mode 100644 index 0000000..29f5fee Binary files /dev/null and b/jnyqide/closeFile.gif differ diff --git a/jnyqide/help.gif b/jnyqide/help.gif new file mode 100644 index 0000000..7311814 Binary files /dev/null and b/jnyqide/help.gif differ diff --git a/jnyqide/keywords.txt b/jnyqide/keywords.txt new file mode 100644 index 0000000..2f36731 --- /dev/null +++ b/jnyqide/keywords.txt @@ -0,0 +1,512 @@ +abs +abs-env +address-of +and +alloc +alpass +allpass2 +amosc +append +apply +aref +areson +arrayp +assoc +at +atom +at-abs +atone +autonorm-off +autonorm-on +backquote +baktrace +bandpass2 +biquad +biquad-m +block +both-case-p +boundp +break +build-harmonic +buzz +car +catch +cdr +caar +cadr +cdar +cddr +caaar +caadr +cadar +caddr +cdaar +cdadr +cddar +cdddr +case +cerror +char +code-char +char-code +char-upcase +char-downcase +char-int +char< +char<= +char= +char/= +char> +char-lessp +char-not-greaterp +char-equalp +char-not-equalp +char-not-lessp +char-greaterp +characterp +clean-up +clip +close +comb +cond +const +cons +consp +congen +const +continue +continuous-control-warp +continuous-sound-warp +control +control-srate-abs +control-warp +convolve +cos +cue +cue-file +db-to-linear +defmacro +defun +delete +delete-if +delete-if-not +diff +digit-char +digit-char-p +display +do +do* +dolist +dotimes +do +dribble +endp +env +errset +eq +eq-band +eq-highshelf +eq-lowshelf +eql +equal +error +eval +evalhook +evenp +exit +exp +expand +expt +exp-dec +extract +extract-abs +fboundp +feedback-delay +first +flatc +flatsize +flet +float +floatp +fmosc +fmlfo +force-srate +format +fourth +funcall +function +gc +gcd +gensym +get +get-duration +get-lambda-expression +get-loud +get-output-stream-list +get-sustain +get-transpose +get-warp +go +hash +highpass2 +highpass4 +highpass6 +highpass8 +hp +hz-to-step +hzosc +if +int-char +integerp +integrate +intern +labels +lambda +last +length +let +let* +lfo +linear-to-db +list +listp +load +local-to-global +log +logand +logior +lognot +logxor +loop +loud +loud-abs +lower-case-p +lowpass2 +lowpass4 +lowpass6 +lowpass8 +lp +macroexpand +macroexpand-1 +macrolet +maketable +make-array +make-string-input-stream +make-string-output-stream +make-symbol +mapc +mapcar +mapl +maplist +max +member +min +minusp +mult +nconc +noise +not +notch2 +nstring-upcase +nstring-downcase +nth +nthcdr +null +numberp +objectp +oddp +open +open-binary +or +osc +osc-note +osc-pulse +osc-saw +osc-tri +pan +partial +peak +peek +peek-char +play +play-file +pluck +plusp +poke +print +prin1 +princ +pprint +prod +profile +prog +prog* +progv +progl +prog2 +progn +psetq +push +putprop +pwe +pwe-list +pwer +pwer-list +pwev +pwev-list +pwevr +pwevr-list +pwl +pwl-list +pwlr +pwlr-list +pwlv +pwlv-list +pwlvr +pwlvr-list +quantize +quote +ramp +random +read +read-byte +read-char +read-int +read-float +read-line +recip +return +return-from +rplaca +rplacd +ref +resample +reson +rest +rem +remove +remove-if +remove-if-not +remprop +restore +reverse +rms +room +s-abs +s-add-to +s-exp +s-log +s-max +s-min +s-overwrite +s-plot +s-print-tree +s-read +s-rest +s-save +s-sqrt +sampler +save +scale +scale-db +scale-srate +second +send +seq +seq-create +seq-get +seq-next +seq-reset +seqrep +set +set-control-srate +set-logical-stop +set-pitch-names +set-sound-srate +setdir +setf +setq +setup-console +sf-info +shape +shift-time +sim +simrep +sin +sine +siosc +slope +snd-abs +snd-add +snd-alpass +snd-alpasscv +snd-alpassvv +snd-amosc +snd-areson +snd-aresoncv +snd-aresonvc +snd-aresonvv +snd-atone +snd-atonev +snd-avg +snd-biquad +snd-buzz +snd-chase +snd-clip +snd-compose +snd-congen +snd-const +snd-convolve +snd-copy +snd-coterm +snd-delay +snd-delaycv +snd-down +snd-exp +snd-extent +snd-fetch +snd-fetch-array +snd-fft +snd-flatten +snd-fmosc +snd-follow +snd-from-array +snd-fromarraystream +snd-fromobject +snd-gate +snd-ifft +snd-inverse +snd-length +snd-log +snd-max +snd-maxv +snd-maxsamp +snd-multiseq +snd-normalize +snd-osc +snd-overwrite +snd-partial +snd-play +snd-pluck +snd-print +snd-print-tree +snd-prod +snd-pwl +snd-quantize +snd-read +snd-recip +snd-resample +snd-resamplev +snd-reson +snd-resoncv +snd-resonvc +snd-resonvv +snd-samples +snd-save +snd-scale +snd-seq +snd-set-logical-stop +snd-shape +snd-sine +snd-siosc +snd-sqrt +snd-srate +snd-sref +snd-stop-time +snd-tapv +snd-time +snd-tone +snd-tonev +snd-t0 +snd-up +snd-white +snd-xform +snd-zero +sort +sound +sound-off +sound-on +sound-srate-abs +sound-warp +sound-srate-abs +soundfilename +soundp +sublis +subst +sum +sqrt +sref +sref-inverse +stats +step-to-hz +streamp +strcat +stretch +stretch-abs +string +string-search +string-trim +string-left-trim +string-lessp +string-not-greaterp +string-equalp +string-not-equalp +string-not-lessp +string-greaterp +string-right-trim +string-upcase +string-downcase +stringp +string< +string<= +string/= +string>= +string> +subseq +sustain +sustain-abs +synbol-function +symbol-name +symbol-plist +symbol-value +symbolp +system +tagbody +tan +terpri +third +throw +timed-seq +type-of +tone +top-level +trace +transpose +transpose-abs +truncate +unless +untrace +unwind-protect +upper-case-p +vector +warp +warp-abs +when +while +write-byte +write-char +write-int +write-float +zerop +1+ +1- +/ ++ +- +* += +< +> +<= +>= +/= diff --git a/jnyqide/manifest.txt b/jnyqide/manifest.txt new file mode 100644 index 0000000..5f6b076 --- /dev/null +++ b/jnyqide/manifest.txt @@ -0,0 +1 @@ +Main-Class: jnyqide/Main diff --git a/jnyqide/openFile.gif b/jnyqide/openFile.gif new file mode 100644 index 0000000..4a7553f Binary files /dev/null and b/jnyqide/openFile.gif differ diff --git a/lib/bandfx.lsp b/lib/bandfx.lsp new file mode 100644 index 0000000..a5b724c --- /dev/null +++ b/lib/bandfx.lsp @@ -0,0 +1,153 @@ +;; bandfx -- audio effects based on separate frequency bands +;; +;; by Michael Mishkin and Roger B. Dannenberg + +;; SEPARATE-INTO-BANDS -- separate sound s into frequency bands with +;; exponential spacing from p to p + inc * n. Filteres have a bandwidth +;; of inc and there are n bands. +;; The last band is not filtered. +;; +(defun separate-into-bands (s p inc n) + (let (bands width low-freq high-freq) + (setf bands (make-array n)) + (setf high-freq (step-to-hz p)) + (dotimes (i (1- n)) + (setf low-freq high-freq) + (setf p (+ p inc)) + (setf high-freq (step-to-hz p)) + (setf width (- high-freq low-freq)) + (setf (aref bands i) (reson s (+ low-freq (* 0.5 width)) width 1)) + (setf s (areson s (+ low-freq (* 0.5 width)) width 1))) + (setf (aref bands (1- n)) s) + bands)) + + +;; SEPARATE-INTO-BANDS-RANGE -- separate signal s into num-bands bands +;; from the low to high step +;; +(defun separate-into-bands-range (s low high num-bands) + (let ((inc (/ (- high low) num-bands))) + (separate-into-bands s low inc num-bands))) + + +;; RECONSTRUCT-FROM-BANDS -- reconstruct a signal from bands +;; +(defun reconstruct-from-bands (bands) + (let ((result (aref bands 0))) + (dotimes (i (1- (length bands))) + (setf result (sum result (aref bands (1+ i))))) + result)) + +;; BANDED-DELAY -- apply different delay to each band (channel) of bands. +;; del is the delay for the first band, and inc is the difference in +;; delay for each successive band. fb is the feedback for all delays. +;; +(defun banded-delay (bands del inc fb wet) + (let ((result (make-array (length bands)))) + (dotimes (i (length bands)) + (setf (aref result i) + (sum (mult (- 1 wet) (aref bands i)) + (mult wet (feedback-delay (aref bands i) del fb)))) + (setf del (+ del inc))) + result)) + +;; APPLY-BANDED-DELAY -- apply banded delay effect to a sound +;; s is the sound to be processed +;; lowp, highp is the pitch range for the bands +;; num-bands is the number of bands +;; lowd, highd is the range of delays +;; fb is the feedback (same for all bands) +;; (note that if lowd > highd, delay decreases with increasing frequency) +;; +(defun apply-banded-delay (s lowp highp num-bands lowd highd fb wet) + (let (bands inc) + (reconstruct-from-bands + (banded-delay (separate-into-bands-range s lowp highp num-bands) + lowd (/ (- highd lowd) num-bands) fb wet)))) + +(defun banded-bass-boost (bands num-boost gain) + (let ((result (make-array (length bands)))) + (dotimes (i (length bands)) + (setf (aref result i) + (scale (if (< i num-boost) gain 1.0) + (aref bands i)))) + result)) + + +(defun apply-banded-bass-boost (s lowp highp num-bands num-boost gain) + (reconstruct-from-bands + (banded-bass-boost + (separate-into-bands-range s lowp highp num-bands) + num-boost gain))) + +(defun banded-treble-boost (bands num-boost gain) + (let ((result (make-array (length bands))) + (num-unity (- (length bands) num-boost))) + (dotimes (i (length bands)) + (setf (aref result i) + (scale (if (< i num-unity) 1.0 gain) + (aref bands i)))) + result)) + + +(defun apply-banded-treble-boost (s lowp highp num-bands num-boost gain) + (reconstruct-from-bands + (banded-treble-boost + (separate-into-bands-range s lowp highp num-bands) + num-boost gain))) + + +;; EXAMPLES + +;; First, a few helper functions + +;; CHECK-PIANO -- make sure pianosyn.lsp is loaded +;; +(defun check-piano () + (cond ((not (boundp '*pianosyn-path*)) + (load "pianosyn")))) + +;; PN-RIFF -- make a sound to which we can add effects +;; +(defun pn-riff () + (seq + (seqrep (i 20) + (set-logical-stop + (piano-note 0.1 (+ (rem (* i 5) 48) c2) 100) + 0.2)) + (s-rest))) + +;; Examples start with band-2. You can run examples in the IDE after +;; loading this file using the F2, F3, ... buttons in the IDE. + +(defun band-2 () + (check-piano) + (play (apply-banded-delay (pn-riff) c2 120 28 1.0 0.0 0.0 0.2))) + +(setfn f2 band-2) + +(defun band-3 () + (check-piano) + (play (apply-banded-delay (pn-riff) c2 120 28 0.0 1.0 0.0 0.2))) + +(setfn f3 band-3) + +(defun band-4 () + (check-piano) + (play (scale 0.4 (apply-banded-bass-boost (pn-riff) c2 120 28 5 10)))) + +(setfn f4 band-4) + +(defun band-5 () + (check-piano) + (play (scale 0.4 (apply-banded-treble-boost (pn-riff) c2 120 28 5 10)))) + +(setfn f5 band-5) + +(print "bandfx.lsp has been loaded. Try (f2) through (f5) for examples.") + + + + + + diff --git a/lib/compress.lsp b/lib/compress.lsp new file mode 100644 index 0000000..e1f0c49 --- /dev/null +++ b/lib/compress.lsp @@ -0,0 +1,310 @@ +; This code implements a compressor for noisy speech audio. +; There are actually two compressors that can be used in +; series. The first is +; a fairly standard one: it detects signal level with an RMS +; detector and used table-lookup to determine how much gain +; to place on the original signal at that point. One bit of +; cleverness here is that the RMS envelope is "followed" or +; enveloped using SND-FOLLOW, which does look-ahead to anticipate +; peaks before they happen. +; +; The other piece of high-tech is COMPRESS-MAP, which builds +; a map in terms of compression and expansion. What I recommend +; is figure out the noise floor on the signal you are compressing. +; Use a compression map that leaves the noise alone and boosts +; signals that are well above the noise floor. Alas, the COMPRESS-MAP +; function is not written in these terms, so some head-scratching is +; involved. Maybe I'll write another map generator if someone has a +; good application to test with. + +; COMPRESS-MAP -- constructs a map for the compress function +; +; The map consists of two parts: a compression part and an expansion part. +; The intended use is to compress everything above compress-threshold by +; compress-ratio, and to downward expand everything below expand-ratio +; by expand-ratio. Thresholds are in dB and ratios are dB-per-dB. +; 0dB corresponds to a peak amplitude of 1.0 or rms amplitude of 0.7 +; If the input goes above 0dB, the output can optionally be limited +; by setting :limit (a keyword parameter) to T. This effectively changes +; the compression ratio to infinity at 0dB. If :limit is NIL +; (the default), then the compression-ratio continues to apply above 0dB. +; +; Another keyword parameter, :transition, sets the amount below the +; thresholds (in dB) that a smooth transition starts. The default is 0, +; meaning that there is no smooth transition. +; +; It is assumed that expand-threshold <= compress-threshold <= 0 +; The gain is unity at 0dB so if compression-ratio > 1, then gain +; will be greater than unity below 0dB + +; RETURNS: a sound for use in the SHAPE function. The sound maps input +; dB to gain. Time 1.0 corresponds to 0dB, and Time 0.0 corresponds to +; -100 dB, and Time 2.0 corresponds to +100dB, so this is a +; 100hz "sample rate" sound. The sound gives gain in dB. + +; Smooth transition equations: this is a parabola that makes a +; transition between two intersecting straight lines. The parabola +; matches the slope of the lines where it intersects them, and +; it intersects the first (left) line at location (u, v). The equation +; is: +; y = v + m(x-u) + d(s-m)((x-u)/d - (x-u)^2/(2d^2)) +; = v + m(x-u) + (s-m)((x-u) - (x-u)^2/(2d)) +; = v + m(x-u) + (s-m)((x-u) - (x-u)^2(s-m)/(4(b-v))) +; +; where s is the slope of the left line, the right line is expressed by +; y = mx+b, and +; d is the duration of the transition = 2(b-v)/(s-m) +; +; To show this is correct, show that (1) at the left intersection, the left +; line and the transition both pass through u,v and (2) have the same slope s, +; and show that (3) at the right intersection, the right line and the +; transition both meet at u+d and (4) have the same slope m. +; +; transition runs from u,v on left line to u+d on right line +; d = 2(v - mu - f)/(m - s), +; where right line is described by y = mx + f and left line slope = s +; c = (m - s)/2d +; b = s - 2cu +; a = v - bu - cu^2 +; +; transition is y = a + bx + cx^2 +; +; Now, show that curve meets left line at x = u +; (1) a + bx + cx^2 = v at x = u +; a + bu + cuu = v - bu - cuu + bu + cuu = v +; +; (2) slope at x = u is s: +; b + 2cu = s - 2cu + 2cu = s +; +; (3) curve meets right line at x = u + d +; a + b(u + d) + c(uu + 2ud + dd) = +; v - bu - cuu + bu + bd + cuu + 2cud + cdd = +; v + bd +2cud + cdd = +; v + (s - 2cu)d + 2cud + cdd = +; v + sd + cdd = +; v + sd + dd(m-s)/2d = +; v + sd + d(m-s)/2 = + +; v + s(2(v - mu - f)/(m - s)) + (2(v - mu - f)/(m - s))(m-s)/2 = +; v + 2sv/(m-s) -2smu/(m-s) -2sf/(m-s) + v - mu - f = +; 2v + (2sv - 2smu - 2sf)/(m-s) - mu - f = +; 2v + 2s(v - mu - f)/(m-s) - mu - f = +; 2v + sd - mu - f +; try subtracting mx + b': +; 2v + sd - mu - f - m(u + d) - f = +; 2v + sd - 2mu - 2f - md = +; 2v + (s - m)d - 2mu - 2f = +; 2v + (s - m)2(v - mu - f) / (m - s) - 2mu - 2f = +; 0 +; +(defun compress-map (compress-ratio compress-threshold expand-ratio + expand-threshold &key (limit nil) (transition 0.0)) + (display "compress-map" compress-ratio compress-threshold expand-ratio + expand-threshold limit transition) + (let (m s ; see equations above + eupd ; eu + d + cupd ; ct1 + d + lim ; 0dB or infinity, depends on limit + b2 ; y-intercept of the 1:1 part + ea eb ec ca cb cc ; polynomial coefficients + eu ev cu cv ; intersection points (u,v) + ed cd ; d values + lower-db upper-db ; function to compute + map ; samples for map + x ; loop value + den ; denominator + ) + ; check input for good values: + (cond ((> expand-threshold compress-threshold) + (error "expand-threshold must be lower than compress threshold")) + ((> compress-threshold 0) + (error "compress-threshold must be at or below 0dB")) + ((<= compress-ratio 0.0) + (error "negative compress-ratio")) + ((< expand-ratio 0.0) + (error "negative expand-ratio")) + ) + ; set some constants + (setf eu (- expand-threshold transition)) + (setf cu (- compress-threshold transition)) + (setf m (/ 1.0 compress-ratio)) + (setf s expand-ratio) ; rename to match equations + ; point where compression line intersects non-compression + ; line is (* m compress-threshold), and cv is this point + ; minus transition (since slope is one) + (setf cv (- (* m compress-threshold) transition)) + ; slope is 1 from compress-threshold to expand-threshold + (setf ev (+ (* m compress-threshold) + (- expand-threshold compress-threshold) + (* s (- transition)))) + ; the 1:1 part passes through cu,cv with slope of 1, so the y-intercept + ; is cv-cu + (setf b2 (- cv cu)) + ; d = 2(v - mu - f)/(m - s) --note m = s, s = 1, f = 0 + (setf den (- m 1.0)) + (cond ((< (abs den) .001) + (setf cd 0.0)) + (t + (setf cd (* 2 (- cv (* cu m)) (/ den))))) + (setf cupd (+ cu cd)) + + (setf den (- 1.0 s)) + (cond ((< (abs den) .001) + (setf ed 0.0)) + (t + (setf ed (* 2 (- ev eu b2) (/ den))))) + (setf eupd (+ eu ed)) + + ; ec = (1.0 - s)/(2*ed) + (cond ((< (abs ed) 0.001) + (setf ec 0.0)) + (t + (setf ec (/ (- 1.0 s) (* 2.0 ed))))) + ; eb = s - 2*ec*eu + (setf eb (- s (* 2.0 ec eu))) + ; ea = ev - eb*eu - ec*eu*eu + (setf ea (- ev (* eb eu) (* ec eu eu))) + + ; cc = (m - 1.0)/(2*cd) + (cond ((< (abs cd) 0.001) + (setf cc 0.0)) + (t + (setf cc (/ (- m 1.0) (* 2.0 cd))))) + ; cb = s - 2*cc*cu + (setf cb (- 1.0 (* 2.0 cc cu))) + ; ca = cv - cb*cu - cc*cu*cu + (setf ca (- cv (* cb cu) (* cc cu cu))) + + + (cond (limit ; hard limit to 0dB + (setf lim 0.0)) + (t ; no hard limit, set limit to effectively infinity + (setf lim 10000.0))) + + (display "compress-map" + m s ; see equations above + eupd ; et1 + d + cupd ; ct1 + d + lim ; 0dB or infinity, depends on limit + b2 ; y-intercept of the 1:1 part + ea eb ec ca cb cc ; polynomial coefficients + eu ev cu cv ; intersection points (u,v) + ed cd) ; d values + + ; now create function that goes 100dB below expansion threshold + ; and up to 100dB + (setf lower-db -100.0) + (setf upper-db 100.0) + (setf map (make-array 201)) + (setf x lower-db) ; this should be an even integer + (dotimes (i (length map)) + (setf (aref map i) + (cond ((< x eu) (+ ev (* s (- x eu)))) + ((< x eupd) (+ ea (* eb x) (* ec x x))) + ((< x cu) (+ cv (- x cu))) + ((< x cupd) (+ ca (* cb x) (* cc x x))) + ((< x lim) (* m x)) + (t 0))) + ; map[i] has the desired output dB, so subtract input dB to + ; get gain: + (setf (aref map i) (- (aref map i) x)) + (cond ((and (> x (- eu 3)) (< x 0)) + (format t "~A -> ~A~%" x (aref map i)))) + (setf x (+ x 1))) + ; return a sound + (snd-from-array 0.0 100.0 map))) + + +(defun db-average (input) + (let (y) + (setf y (mult input input)) ; first square input + (setf y (snd-avg y 1000 500 op-average)) ; then time average + (setf y (snd-log (scale 2.0 y))) ; peak normalization, then take log + (setf y (scale (/ 10.0 (log 10.0)) y)) ; see below for scaling explanation + y)) + + +(defun compress (input map rise-time fall-time &optional (lookahead 0.0)) + ; take the square of the input to get power + (let ((in-squared (mult input input)) + window avg env gain) + (cond ((zerop lookahead) (setf lookahead rise-time))) + ; compute the time-average (sort of a low-pass) of the square + ; parameters give 50ms window and a 25ms step + (setf window (round (* (snd-srate input) 0.05))) + (setf avg (snd-avg in-squared window (/ window 2) op-average)) + ; use follower to anticipate rise and trail off smoothly + ; N.B.: the floor (2nd argument to snd-follow) should be the + ; square of the noise floor, e.g. for a noise floor of 1/2^16, + ; use 1/2^32 = about 4E-9. If the number is too small, you will + ; not get expansion below the square root of the floor parameter. + ; set lookahead to be number of samples in rise time: + (setf lookahead (round (* lookahead (snd-srate avg)))) + (setf env (snd-follow avg 0.000001 rise-time fall-time lookahead)) + ; take logarithm to get dB instead of linear, also adjust for + ; peak vs. average as follows: a sinusoid with peak of 1.0 has + ; an average amplitude of 1/sqrt(2), we squared the signal, so + ; the average amplitude should be 1/2, so multiply by 2 so + ; that a sine with peak amplitude of 1 will get an average of 1 + ; which will convert to 0dB + (setf logenv (snd-log (scale 2.0 env))) + ; tricky part: map converts dB of input to desired gain in dB + ; this defines the character of the compressor + ; map is scaled so that (0,2) corresponds to (-100dB, 100dB) + ; so you need to scale input by .01. But first, we need to get dB: + ; we have log(avg(x^2)), and we want dB = 20log10(sqrt(avg(x^2))) + ; simplify dB to 10log10(avg(x^2)) = 10log(avg(x^2))/log(10), + ; so scale by 10/log(10) * 0.01 = 0.1/log(10) + (setf shaped-env (shape (setf gle (scale (/ 0.1 (log 10.0)) logenv)) map 1.0)) + ; Go back to linear. To get from dB to linear, use: + ; 20log(linear) = dB + ; linear = exp(dB/20), + ; so scale the result by 1/20 = 0.05 + (setf gain (snd-exp (scale 0.05 shaped-env))) + ; return the scaled input sound, + ; another trick: avg signal will be delayed. Also, snd-follow + ; has a delayed response because it's looking ahead in sound + ; 20 = the number of samples of lookahead from snd-follow + ; 88.2 = 44,100 (sample rate) / 500 (the step-size in avg) + ; in other words, 44100/500 is the sample rate of the control + ; signal looked at by follow + ; "44100" should be replaced by the signal's sample rate + ; = (snd-srate input) + ; (setf gg gain) + (sound-srate-abs (snd-srate input) ; set default sample rate for s-rest + (mult (seq (s-rest (/ 20.0 (/ (snd-srate input) 500.0))) (cue input)) gain)))) + + + ; this is an automatic gain control using peak detection for + ; gain control -- the range parameter gives the maximum gain in dB + ; the agc will attenuate peaks to 1.0. + ; + (defun agc (input range rise-time fall-time &optional (lookahead 0.0)) + ; take the square of the input to get power + (let (window avg env gain lookahead-samples) + (cond ((zerop lookahead) (setf lookahead rise-time))) + ; compute the time-average (sort of a low-pass) of the square + ; parameters give 50ms window and a 25ms step + (setf window (round (* (snd-srate input) 0.05))) + (setf avg (snd-avg input window (/ window 2) op-peak)) + ; use follower to anticipate rise and trail off smoothly + ; set lookahead to be number of samples in rise time: + (setf lookahead-samples (round (* lookahead (snd-srate avg)))) + (setf env (snd-follow avg (db-to-linear (- range)) + rise-time fall-time lookahead-samples)) + (setf gain (snd-recip env)) + ; return the scaled input sound, + ; another trick: avg signal will be delayed. Also, snd-follow + ; has a delayed response because it's looking ahead in sound + ; 20 = the number of samples of lookahead from snd-follow + ; 88.2 = 44,100 (sample rate) / 500 (the step-size in avg) + ; in other words, 44100/500 is the sample rate of the control + ; signal looked at by follow + (sound-srate-abs (snd-srate input) ; set default sample rate for s-rest + (mult (seq (s-rest lookahead) (cue input)) gain)) + ;(vector ; (seq (s-rest lookahead) (cue input)) + ; (mult (seq (s-rest lookahead) (cue input)) gain) + ; (force-srate (snd-srate input) (scale 0.3 gain)))) + )) + + diff --git a/lib/dist-test.lsp b/lib/dist-test.lsp new file mode 100644 index 0000000..a8a0c1e --- /dev/null +++ b/lib/dist-test.lsp @@ -0,0 +1,193 @@ +;; Examples of how to use distributions.lsp + +;;1. Altered granulate methods based on distribution + +(load "gran") + +;;The deviatons in pitch and grainlength of the standard granular synthesis +;;functions in are based on the uniform random distribution. With simple +;;modifications, these can be made to take in a distribution generator +;;function as a variable. + +;; filename -- name of the file +;; grain-dur -- the duration of a grain +;; grain-dev -- grain dur is actually grain-dur + random(0, grain-dev) +;; ioi -- the basic inter-onset-interval for grains +;; ioi-dev -- ioi is actually: ioi + random(0, ioi-dev) +;; pitch-dist -- the distribution of the alteration in pitch to the grains +;; the distribution values should be > 1. +;; file-start -- when to start reading the file (an offset from start) +;; file-end -- when to stop reading the file (an offset from end) + +(defun pitch-dist-granulate (filename grain-dur grain-dev ioi ioi-dev + pitch-dist &optional (file-start 0) (file-end 0)) +(let (orig n env actual-grain-dur step-size + (avg-ioi (+ ioi (/ ioi-dev 2.0))) + (file-dur (sf-dur filename)) + (dur (get-duration 1))) + (setf n (truncate (/ dur avg-ioi))) + (cond ((< file-dur file-start) + (error "sf-granulate: file-start is after end of file!")) + ((< file-dur file-end) + (error "sf-granulate: file-end (offset) exceeds file duration!")) + ((< file-dur (+ file-start file-end)) + (error "sf-granulate: file-start + file-end > file duration!"))) + (setf file-dur (- file-dur file-start file-end)) + (setf step-size (/ file-dur n)) + (stretch-abs 1.0 (let () + (seqrep (i n) (let () + (setf actual-grain-dur (real-random grain-dur (+ grain-dur grain-dev))) + (setf env (stretch actual-grain-dur (one-minus-cosine))) + (force-srate *sound-srate* + (stretch (funcall pitch-dist) + (sound2 + (set-logical-stop + (mult (cue env) + (s-read filename + :time-offset (+ file-start (* step-size i)) + :dur actual-grain-dur)) + (real-random ioi (+ ioi ioi-dev)))))))))))) + + +;; filename -- name of the file +;; dist -- the distribution function that the grain sizes should follow +;; ioi -- the basic inter-onset-interval for grains +;; ioi-dev -- ioi is actually: ioi + random(0, ioi-dev) +;; pitch-dev -- grains are resampled at rate between 1 and pitch-dev +;; file-start -- when to start reading the file (an offset from start) +;; file-end -- when to stop reading the file (an offset from end) + +(defun len-dist-granulate (filename dist ioi ioi-dev pitch-dev + &optional (file-start 0) (file-end 0)) + (let (orig n env actual-grain-dur step-size + (avg-ioi (+ ioi (/ ioi-dev 2.0))) + (file-dur (sf-dur filename)) + (dur (get-duration 1))) + (setf n (truncate (/ dur avg-ioi))) + (cond ((< file-dur file-start) + (error "sf-granulate: file-start is after end of file!")) + ((< file-dur file-end) + (error "sf-granulate: file-end (offset) exceeds file duration!")) + ((< file-dur (+ file-start file-end)) + (error "sf-granulate: file-start + file-end > file duration!"))) + (setf file-dur (- file-dur file-start file-end)) + (setf step-size (/ file-dur n)) + (stretch-abs 1.0 (let () + (seqrep (i n) (let () + (setf actual-grain-dur (funcall dist)) + (setf env (stretch actual-grain-dur (one-minus-cosine))) + (force-srate *sound-srate* + (stretch (real-random 1.0 pitch-dev) + (sound2 + (set-logical-stop + (mult (cue env) + (s-read filename + :time-offset (+ file-start (* step-size i)) + :dur actual-grain-dur)) + (real-random ioi (+ ioi ioi-dev)))))))))))) + +;; How to use these granular-synthesis functions + +;; First, make a continuation out of the distribution functions +(defun make-gauss (xmu sigma low high) + (lambda () (gauss-dist xmu sigma low high))) + +;; Second, Plug in that continuation as a variable to the granular-synthesis function +(defun try-len-dist () + (play (stretch 4 + (simrep (i 2) + (len-dist-granulate "samples.wav" + (make-gauss 0.0 1.0 0.1 .5) 0.02 0.001 2.0 0 0))))) + +;; Here's an example of changing the pitch distribution +(defun make-gamma (nu high) + (lambda () (gamma-dist nu high))) + +(defun try-pitch-dist () + (play (stretch 4 + (simrep (i 4) + (pitch-dist-granulate "samples.wav" 0.04 0.0 0.02 0.001 + (make-gamma 2.0 5.0) 0 0))))) + + +;; 2. Simple methods of usuing probability distribution generators +;; In general, a probability distribution generator can substitue for a +;; uniform ranom generator which is (real-random min max) + +;; Use a continuous distribution generator to alter the time between sounds +(defun try-exponential () + (play (seqrep (i 20) + (pluck c4 (* 0.5 (exponential-dist .25 2.0)))))) + +;; Use a discrete generator to alter the pitch by a whole number. +(defun try-binomial () + (play (seqrep (i 20) + (pluck (+ (binomial-dist 6 .5) c4) 0.1)))) + + +(defun dist-hist (fn n nbins low high &rest params) + (let ((bins (make-array nbins)) + (step (/ (- high low) (float (- nbins 2))))) + (dotimes (i nbins) + (setf (aref bins i) 0.0)) + (dotimes (i n) + (let ((x (apply fn params)) i) + (cond ((< x low) (incf (aref bins 0))) + ((>= x high) (incf (aref bins (1- nbins)))) + (t + (setf i (truncate (1+ (/ (- x low) step)))) + (if (or (< i 1) (>= i (1- nbins))) + (error "unexpected bin number")) + (incf (aref bins i)))))) + bins)) + + +; test LINEAR-DIST +;(setf hist (dist-hist #'linear-dist 10000 100 0 4 4)) +;(s-plot (scale 0.001 (snd-from-array 0.0 100 hist))) + +; test EXPONENTIAL-DIST +; (setf hist (dist-hist #'exponential-dist 10000 100 0 3 1 3)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test GAMMA-DIST +;(setf hist (dist-hist #'gamma-dist 10000 100 0 10 3 4)) +;(s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test BILATERAL-EXPONENTIAL-DIST +; (setf hist (dist-hist #'bilateral-exponential-dist 10000 100 0 10 4.0 1.1 0 10)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test CAUCHY-DIST +; (setf hist (dist-hist #'cauchy-dist 100000 100 -10 10 1.0 -9 6)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test HYPERBOLIC-COSINE-DIST +; (setf hist (dist-hist #'hyperbolic-cosine-dist 1000000 500 -10 10)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test LOGISTIC-DIST +; (setf hist (dist-hist #'logistic-dist 10000 100 -10 10 0.5 2 -5 1)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test GAUSSIAN-DIST +; (setf hist (dist-hist #'gaussian-dist 100000 100 0 10 5 1 2 8)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test BETA-DIST +; (setf hist (dist-hist #'beta-dist 100000 100 -0.1 1.1 0.5 0.25)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test BERNOULLI-DIST +; (setf hist (dist-hist #'bernoulli-dist 10000 100 -0.1 1.1 0.75 0.1 0.9)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test GEOMETRIC-DIST +; (setf hist (dist-hist #'geometric-dist 100000 100 0 10 0.7)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + +; test POISSON-DIST +; (setf hist (dist-hist #'poisson-dist 10000 100 0 20 4)) +; (s-plot (scale 1.0 (snd-from-array 0.0 100 hist))) + + diff --git a/lib/distributions.lsp b/lib/distributions.lsp new file mode 100644 index 0000000..2821c31 --- /dev/null +++ b/lib/distributions.lsp @@ -0,0 +1,155 @@ +;; Andreas Pfenning, 26 Apr 05 +;; modified by Roger B. Dannenberg, 25 Jun 05 + +;; Probability distribution functions and demo + +#| +This is a library of various probability distribution generators. +The functions output values based on the probability distributions +and the input parameters that scale the distributions. Plots +of the various distributions are shown in the documentation. +The user has option of adding bounds to the output values, +especially in the cases where high or low outliers are expected. +When a distribution returns a value outside of the given bounds, +the value is rejected and another value is generated. Both +discrete (whole number) and continuous distributions are +available. For continous distributions, the probability of +outputing a value between any two points on the x axis is equal +to the area under the curve between those two points. Essentially, +the higher the curve is for a an area of the x axis, the more +likely it is that the generator will output a value in that area. +Discrete generators output values based on how high the "bar" is +at that location. The documentation shows the behavior generated +by 100 trials of discrete probability distributioin generators. +|# + +;;Library of Continuous Probability Distribution Generators + +(defun linear-dist (g) + (* g (- 1.0 (sqrt (rrandom))))) + +(defun exponential-dist (delta &optional high) + (cond ((and high (<= high 0)) + (error "exponential-dist: high value must be positive"))) + (loop + (let ((expv (* (/ -1.0 delta) (log (rrandom))))) + (cond ((or (null high) + (<= expv high)) + (return expv)))))) + +(defun gamma-dist (nu &optional high) + (cond ((and high (<= high 0) + (error "gamma-dist: high value must be positive")))) + (loop + (let* ((summ 1) + (summ2 (dotimes (count nu summ) + (setf summ (* summ (rrandom))))) + (gamv (* -1.0 (log summ2)))) + (cond ((or (null high) + (<= gamv high)) + (return gamv)))))) + + +(defun bilateral-exponential-dist (xmu tau &optional low high) + (cond ((and high low (<= high low)) + (error "bilateral-exponential-dist: high must be greater than low"))) + (loop + (let* ((u (* (rrandom) 2.0)) + (bev (if (> u 1.0) + (+ (* -1.0 tau (log (- u 1.0))) xmu) + (+ (* tau (log u)) xmu)))) + (cond ((and (or (null high) (< bev high)) + (or (null low) (> bev low))) + (return bev)))))) + + +(defun cauchy-dist (tau &optional low high) + (cond ((and high low (<= high low)) + (error "cauchy-dist: high must be greater than low"))) + (loop + (let* ((u (* PI (rrandom))) + (cauv (* tau (/ (sin u) (cos u))))) + (cond ((and (or (null high) (< cauv high)) + (or (null low) (> cauv low))) + (return cauv)))))) + + +(defun hyperbolic-cosine-dist (&optional low high) + (cond ((and high low (<= high low)) + (error "hyperbolic-cosine-dist: high must be greater than low"))) + (loop + (let* ((hcv (log (tan (/ (* PI (rrandom)) 2.0))))) + (cond ((and (or (null high) (< hcv high)) + (or (null low) (> hcv low))) + (return hcv)))))) + + +(defun logistic-dist (alpha beta &optional low high) + (cond ((and high low (<= high low)) + (error "logistic-dist: high must be greater than low"))) + (loop + (let (rand lgv) + (setf rand (rrandom)) + (cond ((zerop rand)) ; try again -- do not use zero + (t + (setf rand (- (/ rand) 1.0)) + (cond ((zerop rand)) ; try again -- do not use zero + (t + (setf lgv (/ (- (+ beta (log rand))) + alpha)) + (cond ((and (or (null high) (< lgv high)) + (or (null low) (> lgv low))) + (return lgv)))))))))) + + +(defun gaussian-dist (xmu sigma &optional low high) + (cond ((and high low (<= high low)) + (error "gauss-dist: high must be greater than low"))) + (loop + (let* ((s 0.0) + (s2 (dotimes (i 12 s) + (setq s (+ s (rrandom))))) + (gsv (+ (* sigma (- s2 6.0)) xmu))) + (cond ((and (or (null high) (< gsv high)) + (or (null low) (> gsv low))) + (return gsv)))))) + + +(defun beta-help (ea eb) + (loop + (let ((y1 (power (rrandom) ea)) + (y2 (power (rrandom) eb))) + (if (<= (+ y1 y2) 1.0) + (return (/ y1 (+ y1 y2))))))) + + +(defun beta-dist (a b) + (let ((ea (/ 1.0 a)) (eb (/ 1.0 b))) + (beta-help ea eb))) + + +;;Library of Discrete Probability Distribution Generators + +(defun bernoulli-dist (px1 &optional (x1 1) (x2 0)) + (let ((u (rrandom))) + (if (< u px1) x1 x2))) + +(defun binomial-dist (n p) + (let ((suc 0)) + (dotimes (count n suc) + (setf suc (+ suc (bernoulli-dist p)))))) + +(defun geometric-dist (p &optional (count 0)) + (loop + (cond ((= (bernoulli-dist p) 1) + (return count))) + (setf count (1+ count)))) + +(defun poisson-dist (delta) + (let ((x 0) (t 0.0)) + (loop + (setf t (- t (/ (log (rrandom)) delta))) + (cond ((> t 1) (return x))) + (setf x (1+ x))))) + + diff --git a/lib/dtmf.lsp b/lib/dtmf.lsp new file mode 100644 index 0000000..4e9615d --- /dev/null +++ b/lib/dtmf.lsp @@ -0,0 +1,46 @@ +;; dtmf.lsp -- DTMF encoding functions +;; Rob Rost and Roger B. Dannenberg + +;; This library takes a list of DTMF (touch-tone) digits and +;; synthesizes the correct audio. Example: +;; (speed-dial '(1 2 3 pound 5 6 star 7)) +;; Note how pound and star keys are entered. + + +(setf dtmf-freqs + '((star 941 1209) (0 941 1336) (pound 941 1477) + (1 697 1209) (2 697 1336) (3 697 1477) + (4 770 1209) (5 770 1336) (6 770 1477) + (7 852 1209) (8 852 1336) (9 852 1477))) + +(defun dtmf-freq1 (key) + (cadr (assoc key dtmf-freqs))) + +(defun dtmf-freq2 (key) + (caddr (assoc key dtmf-freqs))) + +(defun dtmf-tone (key len space) + (scale 0.5 + (seq + (stretch len + (sim (hzosc (dtmf-freq1 key)) + (hzosc (dtmf-freq2 key)))) + (s-rest space)))) + + +; send it a list of digits and it returns the +; Sound object to dial that number +(defun speed-dial (thelist) + (cond ((null thelist) (s-rest 0)) + (t + (seq (dtmf-tone (car thelist) 0.2 0.1) + (speed-dial (cdr thelist)))))) + + +(defun dtmf-example () + (play (speed-dial (list 4 1 2 5 5 5 1 2 1 2)))) + +(print "DTMF library loaded. Run (dtmf-example) for a sample output.") + + + diff --git a/lib/gran.lsp b/lib/gran.lsp new file mode 100644 index 0000000..7e41d6f --- /dev/null +++ b/lib/gran.lsp @@ -0,0 +1,149 @@ +;; GRAN.LSP -- granular synthesis example by Roger B. Dannenberg +;; +;; This is not the ultimate granular synthesis package, so do not +;; consider this to be a stable, permanent addition to the Nyquist +;; library. You can use it as is, or use it as the basis for your +;; own custom variations. + +;; ================================================================== +;; Grains are windowed with "raised cosine pulse functions." These +;; are smooth envelopes based on the function (1-cos(2*pi*t))/2. +;; To speed up computation, I save three functions with 20, 200, and +;; 2205 samples. The function one-minus-cosine selects an appropriate +;; envelope based on the duration (stretch) currently in effect. + +(defun cos-pulse () (scale 0.5 (sum 1 (lfo 1 1 *sine-table* 270.0)))) + +;; this will be a 2205 point smooth 1-cos(x) curve: +;; +(setf *cos-pulse-2205* (cos-pulse)) + +;; this will be a 200 point smooth 1-cos(x) curve: +;; +(setf *cos-pulse-200* (control-srate-abs 200 (cos-pulse))) +(setf *cos-pulse-20* (control-srate-abs 20 (cos-pulse))) + + +;; one-minus-cosine -- an envelope based on (1-cos(2pi*t))/2 +;; +(defun one-minus-cosine () + (let ((max-samps (* *sound-srate* (get-duration 1)))) + (cond ((> max-samps 2205) (sound *cos-pulse-2205*)) + ((> max-samps 200) (sound *cos-pulse-200*)) + (t (sound *cos-pulse-20*))))) + +' (let ((duration (get-duration 1))) + (scale 0.5 (sum 1 (lfo (/ duration) 1 *sine-table* 270.0)))) + +;; ================================================================== +;; The granulation is applied to a sound file rather than a sound. +;; This gives us the ability to access the sound file at any point +;; in time, although is is a bit less efficient because we have to +;; reopen the file hundreds or thousands of times. (On the other hand +;; the file data is likely to be cached by the OS, so it goes pretty +;; fast.) +;; Here, we define some functions for getting file information. + +(defun sf-srate (filename) + (s-read filename) ; s-read returns list of info in *rslt* + (s-read-srate *rslt*)) + + +(defun sf-dur (filename) + (s-read filename) + (s-read-dur *rslt*)) + +;; ============================================================ +;; Define some other handy support functions + +;; real-random -- pick a random real from a range +;; +(defun real-random (from to) + (cond ((= from to) from) + (t + (+ from + (* (random 10000) + 0.0001 + (- to from)))))) + + +;; sound2 -- like SOUND but operates on stereo signal +;; +(defun sound2 (a) + (cond ((eq (type-of a) 'array) + (vector (sound (aref a 0)) (sound (aref a 1)))) + (t + (sound a)))) + + +(defun monoize (v) + (cond ((eq (type-of v) 'array) (aref v 0)) + (t v))) + +;; ================================================================== +;; sf-granulate -- granular synthesis applied to file +;; +;; filename -- name of the file +;; grain-dur -- the duration of a grain +;; grain-dev -- grain dur is actually grain-dur + random(0, grain-dev) +;; ioi -- the basic inter-onset-interval for grains +;; ioi-dev -- ioi is actually: ioi + random(0, ioi-dev) +;; pitch-dev -- grains are resampled at rate between 1 and pitch-dev +;; file-start -- when to start reading the file (an offset from start) +;; file-end -- when to stop reading the file (an offset from end) +;; +;; NOTES: the number of grains is based on an average grain spacing +;; of (ioi + ioi-dev/2). The step through the file is computed +;; by dividing the duration (file-start - file-end) by number of +;; grains. +;; +(defun sf-granulate (filename grain-dur grain-dev ioi ioi-dev pitch-dev + &optional (file-start 0) (file-end 0)) + (let (orig n step-size + (avg-ioi (+ ioi (/ ioi-dev 2.0))) + (file-dur (sf-dur filename)) + (dur (get-duration 1))) + (setf n (truncate (/ dur avg-ioi))) + (cond ((< file-dur file-start) + (error "sf-granulate: file-start is after end of file!")) + ((< file-dur file-end) + (error "sf-granulate: file-end (offset) exceeds file duration!")) + ((< file-dur (+ file-start file-end)) + (error "sf-granulate: file-start + file-end > file duration!"))) + (setf file-dur (- file-dur file-start file-end)) + (setf step-size (/ file-dur n)) + ;(display "sf-granulate" step-size file-dur n) + (stretch-abs 1.0 + (set-logical-stop + (seqrep (i n) + (let* ((actual-grain-dur + (real-random grain-dur (+ grain-dur grain-dev))) + (env (stretch actual-grain-dur (one-minus-cosine))) + (pitch-ratio (real-random 1.0 pitch-dev))) + ;(display "gran" (local-to-global 0) i pitch-ratio) + (set-logical-stop + (force-srate *sound-srate* + (stretch pitch-ratio + (sound2 + (mult (cue env) + (s-read filename + :time-offset (+ file-start (* step-size i)) + :dur actual-grain-dur))))) + (real-random ioi (+ ioi ioi-dev))))) + dur)))) + +;;============================================================================ +;; Here is a sample application of sf-granulate. +;; Notice that I am using simrep to mix four copies of sf-granulate output. +;; Since there are random timings involved, the layers are not identical. +;; +(setf *granfile* "../demos/demo-snd.aiff") + +(defun gran-test () + (play (stretch 4 + (simrep (i 4) + (sf-granulate *granfile* 0.04 0.0 0.02 0.001 2.0 0 0))))) + + +(print "Set *granfile* and then call gran-test for an example") + diff --git a/lib/grapheq.lsp b/lib/grapheq.lsp new file mode 100644 index 0000000..413056b --- /dev/null +++ b/lib/grapheq.lsp @@ -0,0 +1,74 @@ +; basic 4 band equalizer with cuts at 4k, 2k, 1k, and 630 hertz. +; designed as a test +;(defun 4band (s f630 f1k f2k f4k) +; (eq-band +; (eq-band +; (eq-band +; (eq-band s +; 630 f630 0.33) +; 1000 f1k 0.33) +; 2000 f2k 0.33) +; 4000 f4k 0.33)) + +(setf *grapheq-loaded* t) + +;; inf-const -- stretch a number into an "infinite" signal +;; Nyquist does not have infinite signals, so just make it very long +;; ny:all is a large number of samples, so use it as the length in samples +;; +(defun inf-const (x) + (stretch-abs (/ ny:all *default-sound-srate*) + (const x))) + +; n-band graphic eq with variable range. +; sig - input signal +; gains - vector of gain changes in dB +; lowf - lower eq band limit +; highf - upper eq band limit +(defun nband-range (sig gains lowf highf) + (let ((bandsep ;; bandwidth of each channel in steps + (/ (- (hz-to-step highf) (hz-to-step lowf)) (length gains))) + lowstep ;; low frequency in steps + (newsnd sig) + (chans (length gains))) + (setf lowstep (+ (hz-to-step lowf) (* 0.5 bandsep))) + (cond ((< bandsep 0) + (error "band width must be greater than 0")) + (t + (dotimes (i chans newsnd) + ;; gains[i] can be either a number or a signal + (cond ((numberp (aref gains i)) + (cond ((not (zerop (aref gains i))) + (setf newsnd + ;; note: gain in dB + (eq-band newsnd + (step-to-hz (+ + (* i bandsep) + lowstep)) + (aref gains i) + (/ bandsep 12)))))) + (t + (setf newsnd + (eq-band newsnd + (inf-const (step-to-hz (+ + (* i bandsep) + lowstep))) + (aref gains i) + (inf-const (/ bandsep 12))))))))))) + + +; nband eq without variable range +; wraps around nband-vl with standard limits +(defun nband (sig gains) + (nband-range sig gains 20 20000) +) + + +; simple test demo +;(play (nband-vl (noise 1) '(-6 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0) 20 20000)) + +; variable gain demo +;(play (nband-vl (noise 1) '(0 0 0 0 0 0 (pwl 0 0 .9 10 1) 0 0 0 0 0 0 0 0 0 0 (pwl 0 -10 .9 10 1) (pwl 0 -10 .9 10 1) (pwl 0 -10 .9 10 1) (pwl 0 -10 .9 10 1) 0 0 0 0) 20 20000)) + +; test of adjacent band cuts +;(play (nband-vl (noise 1) '(0 0 0 0 0 0 0 0 0 0 6 6 6 0 0 0 -6 -6 0 0 0 0) 20 20000)) diff --git a/lib/instruments.txt b/lib/instruments.txt new file mode 100644 index 0000000..f0f5d09 --- /dev/null +++ b/lib/instruments.txt @@ -0,0 +1,249 @@ +Tones:shiver(float dur = 1.0 (0.1:9.9), + int pitch = 72 (48:96), + int noise-percent = 50 (0:100), + float noise-freq = 100 (20:480)) +REQUIRE "../demos/pmorales/a4.lsp" +END-SOUND + +Tones:cheap(float frq-randi = 100 (0.0:1000.0), + int pitch = 69 (48:96), + float dur = 2.0 (0.1:9.9), + float rate = 3.0 (0.1:9.9), + float amount = 1000.0 (100.0:9900.0)) +REQUIRE "../demos/pmorales/a6.lsp" +END-SOUND + +Percussion:gong-1() +REQUIRE "../demos/pmorales/b1.lsp" +END-SOUND + + +Percussion:gong-2() +REQUIRE "../demos/pmorales/b1.lsp" +END-SOUND + + +Percussion:gong-3(int freq = 440 (200:800), + float dur = 5.0 (2.0:10.0)) +REQUIRE "../demos/pmorales/b1.lsp" +END-SOUND + + +Percussion:gong-3-melody() +REQUIRE "../demos/pmorales/b1.lsp" +END-SOUND + +Percussion:plight-drum-example() +LISP-SOURCE +(if (not (boundp ' *plight-drum-path*)) + (cond ((not (load "../demos/plight/drum.lsp")) + (princ "COULD NOT FIND DRUM.LSP -- THE PLIGHT-DRUM PACKAGE IS +NOT PART OF THE BASIC NYQUIST DISTRIBUTION, BUT +YOU CAN DOWNLOAD IT") + nil))) +SAL-SOURCE +if ! boundp(quote(*plight-drum-path*)) then + if ! #load("../demos/plight/drum.lsp") then + exec princ("COULD NOT FIND DRUM.LSP -- THE PLIGHT-DRUM PACKAGE IS +NOT PART OF THE BASIC NYQUIST DISTRIBUTION, BUT +YOU CAN DOWNLOAD IT") +END-SOUND + +Tones:st-sac(int pitch = 67 (48:96), + float dur = 4.0 (0.1:9.9), + float offset-entry = 1.25 (0.1:3.9), + int num-harmonics = 8 (1:16)) +REQUIRE "../demos/pmorales/b2.lsp" +END-SOUND + + +Tones:st-sac-sequence() +REQUIRE "../demos/pmorales/b2.lsp" +END-SOUND + + +Percussion:risset-bell(float amp = 1.0 (0.0:1.0), + float dur = 4.0 (0.1:9.9), + float frq = 440.0 (50.0:1950.0)) +REQUIRE "../demos/pmorales/b3.lsp" +END-SOUND + + +Percussion:risset-bell-sequence() +REQUIRE "../demos/pmorales/b3.lsp" +END-SOUND + + +Tones:starship(float freq = 200.0 (100.0:900.0), + float scale = 1000.0 (0.0:4000.0)) +REQUIRE "../demos/pmorales/b5.lsp" +END-SOUND + + +Tones:tibetan(float freq = 110 (25.0:575.0), + float offset = 0.03 (0.0:0.1), + float dur = 10.0 (1.0:29.0), + float rise = 1.0 (0.02:4.98), + float dec = 4.0 (0.01:19.99)) +REQUIRE "../demos/pmorales/b7.lsp" +END-SOUND + + +Tones:tibetan-sequence() +REQUIRE "../demos/pmorales/b7.lsp" +END-SOUND + + +Percussion:risset-drum(float amp = 1.0 (0.0:1.0), + float dur = 1.0 (0.1:9.9), + float freq = 100 (25.0:775.0)) +REQUIRE "../demos/pmorales/b8.lsp" +END-SOUND + + +Percussion:risset-drum-sequence() +REQUIRE "../demos/pmorales/b8.lsp" +END-SOUND + + +Tones:risset-endless() +REQUIRE "../demos/pmorales/b9.lsp" +END-SOUND + + +Vocal:buzz-ah[ah](int pitch = 36 (24:72), + float dur = 1 (0.1:9.9)) +REQUIRE "../demos/pmorales/buzz.lsp" +END-SOUND + + +Vocal:buzz-ah[ah](int pitch = 36 (24:72), + float dur = 1 (0.1:9.9)) +REQUIRE "../demos/pmorales/buzz.lsp" +END-SOUND + + +Vocal:buzz-eh[eh](int pitch = 36 (24:72), + float dur = 1 (0.1:9.9)) +REQUIRE "../demos/pmorales/buzz.lsp" +END-SOUND + + +Vocal:buzz-eeh[eeh](int pitch = 36 (24:72), + float dur = 1 (0.1:9.9)) +REQUIRE "../demos/pmorales/buzz.lsp" +END-SOUND + + +Vocal:buzz-ooh[ooh](int pitch = 36 (24:72), + float dur = 1 (0.1:9.9)) +REQUIRE "../demos/pmorales/buzz.lsp" +END-SOUND + + +Vocal:buzz-demo[buzz-demo]() +REQUIRE "../demos/pmorales/buzz.lsp" +END-SOUND + + +Tones:tenney(float frandi = 400 (100.0:1900.0), + float freq = 440 (100.0:1900.0), + float dur = 1 (0.1:9.9)) +REQUIRE "../demos/pmorales/c1.lsp" +END-SOUND + + +Tones:tenney-demo() +REQUIRE "../demos/pmorales/c1.lsp" +END-SOUND + + +Tones:pluck(int pitch = 36 (24:72), + float dur = 1 (0.1:9.9)) +END-SOUND + + +FM:fm-bell(float freq = 150.0 (50.0:350.0), + float cm-ratio = 0.714286 (0.1:1.9), + float imax = 10.0 (3.0:37.0), + float dur = 5.0 (0.1:9.9), + float amp = 1.0 (0.0:1.0)) +REQUIRE "../demos/pmorales/e2.lsp" +END-SOUND + + +FM:fm-wood-drum[fm-w-d](int pitch = 62 (48:72)) +REQUIRE "../demos/pmorales/e2.lsp" +END-SOUND + + +FM:fm-brass[fm-br](int pitch = 62 (48:84)) +REQUIRE "../demos/pmorales/e2.lsp" +END-SOUND + + +FM:fm-clarinet[fm-c](int pitch = 67 (48:84)) +REQUIRE "../demos/pmorales/e2.lsp" +END-SOUND + + +FM:double-carrier(float dur = 1.0 (0.1:9.9), + float freq = 440.0 (60.0:1940.0), + float cm-ratio = 1.0 (0.1:3.9), + float amp = 1.0 (0.0:10.0), + float amp-ratio = 0.5 (0.0:10.0), + float imax = 3.0 (0.1:3.9), + float imin = 1.0 (0.1:3.9), + float modulator = 2.0 (0.0:10.0)) +REQUIRE "../demos/pmorales/e2.lsp" +END-SOUND + + +FM:v-fm(int pitch = 67 (48:84), + float break = 0.3 (0.0:1.0), + float dur = 3.0 (1.0:10.0), + float rev = 0.5 (0.0:1.0)) +REQUIRE "../demos/pmorales/e2.lsp" +END-SOUND + + +Tones:bell-sequence() +REQUIRE "../demos/pmorales/partial.lsp" +END-SOUND + + +Keyboard:dmhm-organ(int pitch = 70 (48:96)) +REQUIRE "../demos/mateos/organ.lsp" +END-SOUND + + +Keyboard:dmhm-organ-test() +REQUIRE "../demos/mateos/organ.lsp" +END-SOUND + + +Percussion:dmhm-gong[dmhm-gong](int pitch = 57 (40:80)) +REQUIRE "../demos/mateos/gong.lsp" +END-SOUND + + +Brass:dmhm-tuba(float freq = 70 (30:170)) +REQUIRE "../demos/mateos/tuba.lsp" +END-SOUND + + +Percussion:dmhm-bell(int bell = 31 (24:60)) +REQUIRE "../demos/mateos/bell.lsp" +END-SOUND + + +Keyboard:piano[piano-note](float duration = 2 (0.1:9.9), + int pitch = 70 (60:100), + int dynamic = 50 (0:100)) +REQUIRE "pianosyn.lsp" +END-SOUND + + +Music:cellular-automation-demo[cell-aut-demo]() +REQUIRE "../demos/allewis/cell_aut.lsp" +END-SOUND diff --git a/lib/lpc.lsp b/lib/lpc.lsp new file mode 100644 index 0000000..5edecf7 --- /dev/null +++ b/lib/lpc.lsp @@ -0,0 +1,178 @@ +;--------------------------------------------------------------------- +; LPANAL. Performs LPC analysis +; +; snd sound for analysis +; an-dur duration of analysis (= duration of sound) +; skiptime step frame to frame +; npoles number of poles +; +; RESULT: analysis data in list format. +; Every element of the list is a list of the form +; +; (RMS1 RMS2 ERR FILTER-COEFS) +; +; RMS1 Energy (not rms value) of input signal +; RMS2 Energy (not rms value) of residual signal +; ERR = sqrt(RMS2/RMS1) If it is small then VOICED sound, +; else UNVOICED +; FILTER-COEFS Array of filter coefs. +; +; +; The z transform of filter is H(z) = 1/A(z) +; +; where A(z) is a polynome of the form: +; +; +; A(z) = 1 + a1 z + a2 z^2 + a3 z^3 + ... + aP z^P +; +; FILTER-COEFS is the array +; +; #(-aP -aP-1 -aP-2 ... a3 a2 a1) +; +; (this format is suited for the filter ALLPOLES) +; + +(setfn lpc-frame-rms1 car) +(setfn lpc-frame-rms2 cadr) +(setfn lpc-frame-err caddr) +(setfn lpc-frame-filter-coefs cadddr) + +;; LPANAL-CLASS -- does lpc analysis. Frames are returned +;; from an iterator object + +(setf lpanal-class (send class :new '(sound framesize skipsize npoles))) + +(send lpanal-class :answer :isnew '(snd framedur skiptime np) '( + (let ((sr (snd-srate snd))) + (setf sound snd) + (setf framesize (round (* sr framedur))) + (setf skipsize (round (* sr skiptime))) + (setf npoles np)))) + +(send lpanal-class :answer :next '() '( + (let ((samps (snd-fetch-array sound framesize skipsize))) + (cond ((null samps) nil) + (t + (snd-lpanal samps npoles)))))) + +(defun make-lpanal-iterator (sound framedur skiptime npoles) + (send lpanal-class :new (snd-copy sound) framedur skiptime npoles)) + +;; LPC-FILE-CLASS -- iterator returns frames from file +;; +(setf lpc-file-class (send class :new '(file))) + +(send lpc-file-class :answer :isnew '(filename) '( + (setf file (open filename)))) + +(send lpc-file-class :answer :next '() '( + (read file))) + +(defun make-lpc-file-iterator (filename) + (send lpc-file-class :new filename)) + + +;; SAVE-LPC-FILE -- create a file from an iterator. This file can +;; be turned back into an iterator using make-lpc-file-iterator. +;; +(defun save-lpc-file (lpc-iterator filename) + (let ((fp (open filename :direction :output)) + (frame t)) + (while frame + (setf frame (send lpc-iterator :next)) + (if frame (format fp "~A~%" frame))) + (close fp))) + + + +;; SHOW-LPC-DATA. Show values of LPC analysis frames from interator. +;; +(defun show-lpc-data (lpc-iterator iniframe endframe &optional (poles? NIL)) + (dotimes (i iniframe) (send lpc-iterator :next)) + (dotimes (i (- endframe iniframe)) + (let ((frame (send lpc-iterator :next))) + (cond ((null frame) (return)) + (poles? + (format t "FRM ~A : ~A\n" (+ i iniframe) frame)) + (t + (format t "FRM ~A : ~A\n" (+ i iniframe) + (reverse (cdr (reverse frame))))))))) + + +;---------------------------------------------------------------------- +; LPC-FREQ. Show frequency response of ALLPOLES filter. +; NEEDS MATLAB or OCTAVE +; +; +; HELPER FUNS : GET-FILTER-COEFS from a LPC analysis data +; lpc-data: data generated by LPCANAL +; numframe: index of frame data +; +; LPC-COEFS-TO-MATLAB : transforms LPC coefs format to Matlab format +; +; LPC-FREQ. +; +; varname : the name of variable that holds coef array in MATLAB +; lpc-data : as above +; numframe : as above +; + + +; THIS CODE TO GET FREQUENCY ASSUMES AN ARRAY OF LPC FRAMES AND REQUIRES +; MATLAB OR OCTAVE. I HAVE NOT ADAPTED THIS TO USE THE STREAM OF FRAMES +; APPROACH. -RBD +; +;(defun get-filter-coefs (lpc-data numframe) +; (nth 3 (aref lpc-data numframe))) +; +; +;(defun lpc-coefs-to-matlab (lpc-data numframe) +; (let* ((lpc-coefs (get-filter-coefs lpc-data numframe)) +; (lencoefs (length lpc-coefs)) +; (result (make-array (1+ lencoefs)))) +; (setf (aref result 0) 1.0) +; (dotimes (i lencoefs) +; (setf (aref result (1+ i)) +; (- (aref lpc-coefs (- lencoefs i 1))))) +; result)) +; +; +;(defun lpc-freq (varname lpc-data numframe) +; (octave (list (list (lpc-coefs-to-matlab lpc-data numframe) varname 'ARR)))) + + +;---------------------------------------------------------------------------- +; ALLPOLES +; +; THIS VERSION IS FOR ARRAY OF FRAMES +; +;(defun get-allpoles-gain (lpc-data numframe) +; (nth 2 (aref lpc-data numframe))) ; se toma ERR para que la amplitud de +; ; la salida se aproxime a 1 +; +;(defun allpoles-from-lpc (snd lpc-data numframe) +; (snd-allpoles snd (get-filter-coefs lpc-data numframe) (get-allpoles-gain lpc-data numframe))) + +; ALLPOLES USES A SINGLE FRAME TO CREATE A FILTER +; +; We introduce two functions: +; NTH-FRAME runs the interator to get the nth frame; +; ALLPOLES-FROM-LPC filters a sound given a frame from an iterator + +;; NTH-FRAME - get the nth frame from lpc iterator, +;; first frame is numbered zero +(defun nth-frame (lpc-iterator numframe) + (dotimes (i numframe) (send lpc-iterator :next)) + (send lpc-iterator :next)) + + +;; ALLPOLES-FROM-LPC -- filter a sound using an LPC frame +;; +(defun allpoles-from-lpc (snd lpc-frame) + (snd-allpoles snd (lpc-frame-filter-coefs lpc-frame) + (lpc-frame-err lpc-frame))) ;; use ERR for gain + +;------------------------------------------------------------------------------- +; LPRESON + +(setfn lpreson snd-lpreson) diff --git a/lib/midishow.lsp b/lib/midishow.lsp new file mode 100644 index 0000000..d33d004 --- /dev/null +++ b/lib/midishow.lsp @@ -0,0 +1,48 @@ +(defun midi-show-file (score-name &optional (out-file t)) + (let ((infile (open-binary score-name :direction :input))) + (setf my-seq (seq-create)) + (seq-read-smf my-seq infile) + (close infile) + (midi-show my-seq out-file))) + + +;iterate over midi sequence and prints events +; +(defun midi-show (the-seq &optional (out-file t)) + (prog (event) + (seq-reset the-seq) +loop + (setf event (seq-get the-seq)) + (if (eq (car event) seq-done-tag) + (go exit)) + (midi-show-event event out-file) + (seq-next the-seq) + (go loop) +exit + )) + +; midi-show-event -- ascii format an event +; +(defun midi-show-event (ev file) + (let ((tag (seq-tag ev))) + (cond ((= tag seq-note-tag) + (format file "Note@~A ch:~A pitch:~A vel:~A line:~A dur:~A~%" + (seq-time ev) (seq-channel ev) (seq-pitch ev) (seq-velocity ev) + (seq-line ev) (seq-duration ev))) + ((= tag seq-ctrl-tag) + (format file "Ctrl@~A ch:~A num:~A val:~A line:~A~%" + (seq-time ev) (seq-channel ev) (seq-control ev) + (seq-value ev) (seq-line ev))) + ((= tag seq-touch-tag) + (format file "Aftr@~A ch:~A val:~A line:~A~%" + (seq-time ev) (seq-channel ev) (seq-touch ev) (seq-line ev))) + ((= tag seq-bend-tag) + (format file "Bend@~A ch:~A val:~A line:~A~%" + (seq-time ev) (seq-channel ev) (seq-bend ev) (seq-line ev))) + ((= tag seq-prgm-tag) + (format file "Prgm@~A ch:~A num:~A line:~A~%" + (seq-time ev) (seq-channel ev) (seq-program ev) (seq-line ev))) + ((= tag seq-other-tag) + (format file "Othr~%")) + (t + (format file "????: ~A~%" ev))))) diff --git a/lib/moog.lsp b/lib/moog.lsp new file mode 100644 index 0000000..25d4f71 --- /dev/null +++ b/lib/moog.lsp @@ -0,0 +1,146 @@ +;Stephen Mangiat +;15-392 Final Project +;Moog Instrument + + +;Moog Instrument: Main Function +(defun moog (s &key + (range-osc1 2) + (range-osc2 1) + (range-osc3 3) + (detun2 -.035861) + (detun3 .0768) + (noiselevel .05) + (filter-cutoff 768) + (Q 2) + (contour .65) + (filter-attack .0001) + (filter-decay .5) + (filter-sustain .8) + (shape-osc1 *saw-table*) + (shape-osc2 *saw-table*) + (shape-osc3 *saw-table*) + (volume-osc1 1) + (volume-osc2 1) + (volume-osc3 1) + (amp-attack .01) + (amp-decay 1) + (amp-sustain 1) + (amp-release 0) + (glide 0)) + + (cond ((eq glide 0) (setf cv (score-to-cv s))) + (t (setf cv (lp (score-to-cv s) (+ .1 (recip glide)))))) + + (cond ((< range-osc1 2) (setf freq1 cv)) + (t (setf freq1 (mult cv (mult (- range-osc1 1) 2))))) + + (cond ((< range-osc2 2) (setf freq2temp cv)) + (t (setf freq2temp (mult cv (mult (- range-osc2 1) 2))))) + + (cond ((< range-osc3 2) (setf freq3temp cv)) + (t (setf freq3temp (mult cv (mult (- range-osc3 1) 2))))) + + (setf freq2 (mult freq2temp (1+ (mult detun2 .0596)))) + (setf freq3 (mult freq3temp (1+ (mult detun3 .0596)))) + + (setf osc1 (hzosc freq1 shape-osc1)) + (setf osc2 (hzosc freq2 shape-osc2)) + (setf osc3 (hzosc freq3 shape-osc3)) + + (setf mix1 (sum (scale volume-osc1 osc1) + (scale volume-osc2 osc2) (scale volume-osc3 osc3))) + + (setf ampenv (score-to-env-trig s 0 0 0 amp-attack amp-decay amp-sustain amp-release)) + ; noise should be infinite. I hope 10000s is close enough. + (setf mix2 (sum mix1 (scale noiselevel (noise 10000)))) + + (setf durSum 0) + (setf cutoffenv (score-to-filter-trig s 0 0 0 + filter-cutoff Q contour filter-attack filter-decay filter-sustain)) + (setf bandwidth (mult (recip Q) cutoffenv)) + + (setf mix3 (reson mix2 cutoffenv bandwidth 2)) + (setf mix4 (mult mix3 ampenv)) +) + +; Convert input list into Control Voltages +(defun score-to-cv (s) + (cond ((cdr s) + (seq (const (step-to-hz (caar s)) (cadar s)) (score-to-cv (cdr s)))) + (t (const (step-to-hz (caar s)) (cadar s)))) +) + +; Helper functions used to maintain continuity in envelopes +(defun last-value (env1 info) + (sref env1 (- (cadr info) (recip 2205)))) +(defun last-value-2 (env1 info) + (sref env1 (- info (recip 2205)))) + + +; Create filter cutoff frequencies for Control Voltages +(defun score-to-filter-trig (s start dur-prev art-prev filter-cutoff Q contour attack decay sust) + (let (env1 finish) + (cond ((cdr s) (setf env1 + (make-filter start (car s) dur-prev art-prev filter-cutoff Q contour attack decay sust)) + (setf finish (last-value env1 (car s))) + (seq (mult env1 (const 1 (cadar s))) + (score-to-filter-trig (cdr s) finish (cadar s) (caddr (car s)) filter-cutoff Q contour attack decay sust))) + (t (make-filter start (car s) dur-prev art-prev filter-cutoff Q contour attack decay sust))))) + +(defun make-filter (start info dur-prev art-prev filter-cutoff Q contour attack decay sust) + (let ((dur (cadr info)) (art (caddr info))) + (setf highF (sum (mult 10000 contour) filter-cutoff)) + (setf sust1 (mult sust filter-cutoff)) + (cond ((eq art-prev 1) + (setf durSum (+ durSum dur-prev)) + (cond ((> attack durSum) + (mult (const 1 dur) (pwl 0 start (- attack durSum) highF (+ (- attack dur-prev) decay) sust1 dur sust1))) + + ((> (+ attack decay) durSum) + (mult (const 1 dur) (pwl 0 start (- (+ attack decay) durSum) sust1 dur sust1))) + + (t (const sust1 dur)))) + (t (setf durSum 0) (mult (const 1 dur) (pwl 0 0 attack highF (+ decay attack) sust1 dur sust1)))))) + +; Create amplitude envelope for Control Voltages +(defun score-to-env-trig (s start dur-prev art-prev attack decay sust release) + (let (env1 finish) + (cond ((cdr s) (setf env1 + (make-env-trig start (car s) dur-prev art-prev attack decay sust release)) + (setf finish (last-value env1 (car s))) + (seq (mult env1 (const 1 (cadar s))) + (score-to-env-trig (cdr s) finish (cadar s) (caddr (car s)) attack decay sust release))) + (t (make-env-trig start (car s) dur-prev art-prev attack decay sust release))))) + +; Make individual amplitude envelopes. Case checking needed if attack/decay are longer than notes. +(defun make-env-trig (start info dur-prev art-prev attack decay sust release) + (let ((dur (cadr info)) (art (caddr info))) + + (cond ((eq art-prev 1) + (cond ((> (+ attack decay) dur-prev) + (cond ((> (- (+ attack decay) dur-prev) (* dur art)) + (setf art-cutoff (seq (const 1 (* dur art)) (const 0 (- dur (* dur art))))) + (setf env1 (mult (const 1 dur) (pwl 0 start (- (+ attack decay) + dur-prev) sust (* dur art) sust (+ (* dur art) release) 0 dur 0))) + (setf env2 (mult art-cutoff env1)) + (mult (const 1 dur) + (sum env2 (pwl 0 0 (* dur art) 0 (+ (* dur art) .00001) + (last-value-2 env2 (* dur art)) (+ (* dur art) release) 0 dur 0)))) + + (t (mult (const 1 dur) + (pwl 0 start (- (+ attack decay) dur-prev) + sust (* dur art) sust (+ (* dur art) release) 0 dur 0))))) + (t (mult (const 1 dur) (pwl 0 start (* dur art) sust (+(* dur art) release) 0 dur 0))))) + + (t (cond ((> (+ attack decay) (* dur art)) + (setf art-cutoff (seq (const 1 (* dur art)) (const 0 (- dur (* dur art))))) + (setf env1 (pwl 0 start attack 1 (+ attack decay) sust (* dur art) sust + (+(* dur art) release) 0 dur 0)) + (setf env2 (mult art-cutoff env1)) + (mult (const 1 dur) + (sum env2 (pwl 0 0 (* dur art) 0 (+ (* dur art) .00001) + (last-value-2 env2 (* dur art)) (+ (* dur art) release) 0 dur 0)))) + (t (mult (const 1 dur) + (pwl 0 start attack 1 (+ attack decay) sust (* dur art) + sust (+(* dur art) release) 0 dur 0)))))))) \ No newline at end of file diff --git a/lib/piano/att11025.pcm b/lib/piano/att11025.pcm new file mode 100644 index 0000000..683834f Binary files /dev/null and b/lib/piano/att11025.pcm differ diff --git a/lib/piano/att16000.pcm b/lib/piano/att16000.pcm new file mode 100644 index 0000000..60d8e68 Binary files /dev/null and b/lib/piano/att16000.pcm differ diff --git a/lib/piano/att22050.pcm b/lib/piano/att22050.pcm new file mode 100644 index 0000000..9e0e037 Binary files /dev/null and b/lib/piano/att22050.pcm differ diff --git a/lib/piano/att32000.pcm b/lib/piano/att32000.pcm new file mode 100644 index 0000000..06f9818 Binary files /dev/null and b/lib/piano/att32000.pcm differ diff --git a/lib/piano/att44100.pcm b/lib/piano/att44100.pcm new file mode 100644 index 0000000..17030ea Binary files /dev/null and b/lib/piano/att44100.pcm differ diff --git a/lib/piano/att48000.pcm b/lib/piano/att48000.pcm new file mode 100644 index 0000000..3482270 Binary files /dev/null and b/lib/piano/att48000.pcm differ diff --git a/lib/piano/att8000.pcm b/lib/piano/att8000.pcm new file mode 100644 index 0000000..4956f72 Binary files /dev/null and b/lib/piano/att8000.pcm differ diff --git a/lib/piano/demo.mid b/lib/piano/demo.mid new file mode 100644 index 0000000..472dc6b Binary files /dev/null and b/lib/piano/demo.mid differ diff --git a/lib/piano/demo.mp3 b/lib/piano/demo.mp3 new file mode 100644 index 0000000..b4a84d9 Binary files /dev/null and b/lib/piano/demo.mp3 differ diff --git a/lib/piano/dur.tab b/lib/piano/dur.tab new file mode 100644 index 0000000..fff61a9 Binary files /dev/null and b/lib/piano/dur.tab differ diff --git a/lib/piano/gmax.tab b/lib/piano/gmax.tab new file mode 100644 index 0000000..8c586ac Binary files /dev/null and b/lib/piano/gmax.tab differ diff --git a/lib/piano/pn00.cod b/lib/piano/pn00.cod new file mode 100644 index 0000000..0f3d840 Binary files /dev/null and b/lib/piano/pn00.cod differ diff --git a/lib/piano/pn01.cod b/lib/piano/pn01.cod new file mode 100644 index 0000000..f099282 Binary files /dev/null and b/lib/piano/pn01.cod differ diff --git a/lib/piano/pn02.cod b/lib/piano/pn02.cod new file mode 100644 index 0000000..139c77d Binary files /dev/null and b/lib/piano/pn02.cod differ diff --git a/lib/piano/pn03.cod b/lib/piano/pn03.cod new file mode 100644 index 0000000..5ed165d Binary files /dev/null and b/lib/piano/pn03.cod differ diff --git a/lib/piano/pn04.cod b/lib/piano/pn04.cod new file mode 100644 index 0000000..0cb4665 Binary files /dev/null and b/lib/piano/pn04.cod differ diff --git a/lib/piano/pn05.cod b/lib/piano/pn05.cod new file mode 100644 index 0000000..36087cc Binary files /dev/null and b/lib/piano/pn05.cod differ diff --git a/lib/piano/pn06.cod b/lib/piano/pn06.cod new file mode 100644 index 0000000..5ed27a4 Binary files /dev/null and b/lib/piano/pn06.cod differ diff --git a/lib/piano/pn07.cod b/lib/piano/pn07.cod new file mode 100644 index 0000000..11933b8 Binary files /dev/null and b/lib/piano/pn07.cod differ diff --git a/lib/piano/pn08.cod b/lib/piano/pn08.cod new file mode 100644 index 0000000..37c13f3 Binary files /dev/null and b/lib/piano/pn08.cod differ diff --git a/lib/piano/pn09.cod b/lib/piano/pn09.cod new file mode 100644 index 0000000..60c000d Binary files /dev/null and b/lib/piano/pn09.cod differ diff --git a/lib/piano/pn10.cod b/lib/piano/pn10.cod new file mode 100644 index 0000000..03dcad3 Binary files /dev/null and b/lib/piano/pn10.cod differ diff --git a/lib/piano/pn11.cod b/lib/piano/pn11.cod new file mode 100644 index 0000000..4e77387 Binary files /dev/null and b/lib/piano/pn11.cod differ diff --git a/lib/piano/pn12.cod b/lib/piano/pn12.cod new file mode 100644 index 0000000..c345aac Binary files /dev/null and b/lib/piano/pn12.cod differ diff --git a/lib/piano/pn13.cod b/lib/piano/pn13.cod new file mode 100644 index 0000000..473d1e4 Binary files /dev/null and b/lib/piano/pn13.cod differ diff --git a/lib/piano/pn14.cod b/lib/piano/pn14.cod new file mode 100644 index 0000000..64cce3b Binary files /dev/null and b/lib/piano/pn14.cod differ diff --git a/lib/piano/pn15.cod b/lib/piano/pn15.cod new file mode 100644 index 0000000..732cc99 Binary files /dev/null and b/lib/piano/pn15.cod differ diff --git a/lib/piano/pn16.cod b/lib/piano/pn16.cod new file mode 100644 index 0000000..54c0cdb Binary files /dev/null and b/lib/piano/pn16.cod differ diff --git a/lib/piano/pn17.cod b/lib/piano/pn17.cod new file mode 100644 index 0000000..6e2c4b6 Binary files /dev/null and b/lib/piano/pn17.cod differ diff --git a/lib/piano/pn18.cod b/lib/piano/pn18.cod new file mode 100644 index 0000000..a1120a7 Binary files /dev/null and b/lib/piano/pn18.cod differ diff --git a/lib/piano/pn19.cod b/lib/piano/pn19.cod new file mode 100644 index 0000000..45a08d8 Binary files /dev/null and b/lib/piano/pn19.cod differ diff --git a/lib/piano/pn20.cod b/lib/piano/pn20.cod new file mode 100644 index 0000000..dbef4ac Binary files /dev/null and b/lib/piano/pn20.cod differ diff --git a/lib/piano/pn21.cod b/lib/piano/pn21.cod new file mode 100644 index 0000000..e6a4cb2 Binary files /dev/null and b/lib/piano/pn21.cod differ diff --git a/lib/piano/pn22.cod b/lib/piano/pn22.cod new file mode 100644 index 0000000..b485ba0 Binary files /dev/null and b/lib/piano/pn22.cod differ diff --git a/lib/piano/rls11025.pcm b/lib/piano/rls11025.pcm new file mode 100644 index 0000000..a1ff3b2 Binary files /dev/null and b/lib/piano/rls11025.pcm differ diff --git a/lib/piano/rls16000.pcm b/lib/piano/rls16000.pcm new file mode 100644 index 0000000..cef5c5a Binary files /dev/null and b/lib/piano/rls16000.pcm differ diff --git a/lib/piano/rls22050.pcm b/lib/piano/rls22050.pcm new file mode 100644 index 0000000..28f94c6 Binary files /dev/null and b/lib/piano/rls22050.pcm differ diff --git a/lib/piano/rls32000.pcm b/lib/piano/rls32000.pcm new file mode 100644 index 0000000..83f313d Binary files /dev/null and b/lib/piano/rls32000.pcm differ diff --git a/lib/piano/rls44100.pcm b/lib/piano/rls44100.pcm new file mode 100644 index 0000000..7529631 Binary files /dev/null and b/lib/piano/rls44100.pcm differ diff --git a/lib/piano/rls48000.pcm b/lib/piano/rls48000.pcm new file mode 100644 index 0000000..a92c93d Binary files /dev/null and b/lib/piano/rls48000.pcm differ diff --git a/lib/piano/rls8000.pcm b/lib/piano/rls8000.pcm new file mode 100644 index 0000000..3fd2591 Binary files /dev/null and b/lib/piano/rls8000.pcm differ diff --git a/lib/piano/rlsrate.tab b/lib/piano/rlsrate.tab new file mode 100644 index 0000000..2497478 Binary files /dev/null and b/lib/piano/rlsrate.tab differ diff --git a/lib/pianosyn.lsp b/lib/pianosyn.lsp new file mode 100644 index 0000000..9bcdfa6 --- /dev/null +++ b/lib/pianosyn.lsp @@ -0,0 +1,579 @@ +;; ================================================ +;; Show Program Information +;; ================================================ +(princ "\n\nPiano Synthesizer V1.2 (Feb 2004)\n") +(princ " Original algorithm and program by Zheng (Geoffrey) Hua\n") +(princ " and Jim Beauchamp, University of Illinois. Any publication\n") +(princ " or notes on any composition that utilizes this software\n") +(princ " should credit the original creators. Any software based on\n") +(princ " this algorithm should carry a similar notice and restriction.\n") +(princ " Ported to Nyquist from source code in M4C program by\n") +(princ " Ning Hu and Roger Dannenberg, Carnegie Mellon University\n") +(princ " School of Computer Science\n\n") +(princ " Program Initializing...\n") + +(setf *pianosyn-path* (current-path)) + +;; ================================================ +;; Function definition +;; ================================================ +(defun readdat (filename dim data) + (setf filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) + (setq fp (open-binary filename :direction :input)) + (dotimes (count 4) + (setf (aref dim count) (read-int fp))) + (dotimes (count (aref dim 3)) + (setf (aref data count) (read-float fp))) + (close fp)) + +(defun build-harmonic-phase (n phase size) + (sound-srate-abs size (osc (hz-to-step n) 1 *sine-table* phase))) + + +;; ****************************************** +;; * Build envelope * +;; ****************************************** + +; after the initial envelope, which is stored in a table, +; envelopes are extended by splicing together final segments +; of the real envelope. The final segment is approximately +; exponential, and so each copy of the segments that is +; spliced is scaled by the amount of decay during the segment. +; The long term shape will therefore be exactly exponential, but +; we thought that a bit of variation rather than a perfectly +; smooth exponential decay might be better. +; +; This function takes a segment, the amount of decay in the +; segment (the scale factor for the next segment) and a count +; and builds an envelope +; +(defun decay-env (segment decay count) + (cond ((<= count 1) (cue segment)) + (t (seq (cue segment) + (scale decay (decay-env segment decay (1- count))))))) + +; PIANO-ENVELOPE builds the amplitude envelope for a group of partials. +; igroup is the index of the group +; sc-duration is the score duration +; attack is the sampled portion of the envelope with a duration of +; gmagendtime +; seg-array is the repeating portion of the envelope tacked onto +; attack to make the envelope longer. The duration of a segment +; in seg-array is gmagendtimemini +; the amount by which seg-array[igroup] decays is scalemag1[igroup] +; +; Algorithm: +; figure out how many repetitions of the seq-array[igroup] to +; add onto the attack to make the envelope long enough. Multiply +; by an exponential decay starting at the duration -- effectively +; the damper hits the string at sc-duration. +; +(defun piano-envelope (igroup sc-duration gmagendtime gmagendtimemini + attack seg-array scalegmag1) + (let ((decaycount (1+ (truncate (/ (- (+ sc-duration endingtime) gmagendtime) + gmagendtimemini)))) + pianoenv ) + + (setf pianoenv + (sim (at 0 (cue attack)) + (at gmagendtime (decay-env (aref seg-array igroup) + (aref scalegmag1 igroup) + decaycount)))) + ;; For ending time + (mult (scale (aref scale1 igroup) pianoenv) + (pwlv 1 sc-duration + ; decay to 1/1000: about 60dB + 1 (+ sc-duration endingtime) 0.001)))) + + +;; ****************************************** +;; * Build wavetable * +;; ****************************************** +(defun piano-group (jgroup sc-duration freq table) + (sound-srate-abs *piano-srate* + (osc (hz-to-step freq) sc-duration + (aref table jgroup)))) + +;; ****************************************** +;; * Produce single piano note * +;; ****************************************** +(defun piano-note (duration pitch dynamic) + (let ((ioi (get-duration duration)) + (full-pitch (+ (get-transpose) pitch)) + (full-dynamic (+ (get-loud) dynamic)) + ;; note: the "loud" is nominally in dB, but + ;; piano-note-abs uses something akin to midi velocity + ;; we should probably work out a better conversion + (start-time (local-to-global 0)) + on-dur) + (setf on-dur (* ioi (get-sustain))) + (set-logical-stop + (abs-env (at start-time + (piano-note-abs on-dur full-pitch full-dynamic))) + ioi))) + + +;; PIANO-NOTE-ABS -- private function to do the work; assumes +;; stretch factor of 1, etc. +(defun piano-note-abs (sc-duration sc-pitch sc-dynamic) + (let (attnamp freq key whichone whichone1 ngroup1 ngroup2 dyna smax + dur gmagendtime gmagendtimemini k j envpoint) + ;; ****************************************** + ;; * Initilization for each note * + ;; ****************************************** + (setq attnamp 0.03) + + ; key is midi pitch number + (setq key (truncate (+ sc-pitch 0.000001))) + (cond ((< key 21) ;; 21 is A0, lowest pitch on this piano + (break "piano-note-abs pitch is too low" sc-pitch) + ;; continued -- transpose up to lowest octave + (while (< key 21) + (setf sc-pitch (+ sc-pitch 12)) + (setf key (truncate (+ sc-pitch 0.000001))))) + ((> key 108) ;; 108 is c9, highest pitch on this piano + (break "piano-note-abs pitch is too high" sc-pitch) + ;; continued -- transpose down to highest octave + (while (> key 108) + (setf sc-pitch (- sc-pitch 12)) + (setf key (truncate (+ sc-pitch 0.000001)))))) + (setq freq (step-to-hz sc-pitch)) + + (setq whichone -2) + (dotimes (i GROUPCON) + (if (and (= whichone -2) + (< freq (- (aref fa i) 0.001))) + (setq whichone (- i 1)))) + ;; Have to use (- (aref fa i) 0.001) because of the calculation precision of Nyquist + + (setq whichone1 (1+ whichone)) + (setq ngroup2 (aref ngroup whichone1)) + + (setq dyna (truncate sc-dynamic)) + (setq smax 0.25) + + ; (setq attnpretime (/ (+ (* 0.018 dyna dyna) (* -3.9588 dyna) 244.8139) 1000.0)) + (setq dur (aref durtab (+ (* key 128) dyna))) + (setq ngroup1 (aref ngroup whichone)) + (setq gmagendtime (* (nth whichone hkframe) (aref dt whichone))) + (setq gmagendtimemini (* (aref nptsmini whichone) (aref dtmini whichone))) + + (setq k (* (aref gmaxtabdim 1) (aref gmaxtabdim 2))) + (setq j (+ (* whichone k) (* dyna (aref gmaxtabdim 2)))) + (dotimes (i (aref gmaxtabdim 2)) + (setf (aref gmax1 i) (aref gmaxtab j)) + (incf j)) + + (dotimes (i ngroup1) + (setq envpoint (sref (aref (aref gmagmini whichone) i) 0)) + (if (/= envpoint 0) + (setf (aref scalegmag1 i) + (/ (sref (aref (aref gmagmini whichone) i) + (- gmagendtimemini (aref dtmini whichone))) + envpoint)) + (setf (aref scalegmag1 i) 0.0)) + (setf (aref scale1 i) (* smax (aref gmax1 i)))) + (if (> ngroup2 ngroup1) (setf ngroup2 ngroup1)) + + (if (< dur sc-duration) (setq sc-duration dur)) + ;; ********************** + ;; * now sum the groups * + ;; ********************** + (scale 0.5 + (sim (at 0 (set-logical-stop (cue (scale attnamp attsound)) sc-duration)) + (at 0 (cue (simrep (i ngroup2) + (mult (piano-envelope i sc-duration gmagendtime + gmagendtimemini (aref (aref gmag whichone) i) + (aref gmagmini whichone) scalegmag1) + (piano-group i (+ sc-duration endingtime) freq + (aref wavetab whichone1)))))))) )) +;;;;; This is for debugging -- replace synthesis with a sine tone to study envelope +; (at 0 (cue (mult (piano-envelope 0 sc-duration gmagendtime +; gmagendtimemini (aref (aref gmag whichone) 0) +; (aref gmagmini whichone) scalegmag1) +; (osc c4 2.0)))))))) + + +(defun piano-note-2 (sc-pitch sc-dynamic) + (let ((dur (get-duration 1))) + (stretch-abs 1 (piano-note dur sc-pitch sc-dynamic)))) + + +(defun piano-midi (midiin) + (let (midi-seq midifile) + (setf midi-seq (seq-create)) + (setf midifile (open-binary midiin)) + (seq-read-smf midi-seq midifile) + (close midifile) + (seq-midi midi-seq + (note (channel pitch velocity) + (piano-note-2 pitch velocity))))) + + +;; ****************************************** +;; *Produce wave file according to MIDI file* +;; ****************************************** +(defun piano-midi2file (midiin out-name) + (princ "\nBegin sound production\n") + (princ "=============================================\n") + (s-save (piano-midi midiin) + ny:all (string out-name) :play T) + (princ "=============================================\n") + (princ "End sound production\n")) + + +;; ==================================== +;; Main Program +;; ==================================== +(if (not (boundp '*piano-srate*)) ;; if pianosyn.lsp wasn't loaded already + (expand 70)) ;; we'll allocate a lot of nodes for data, so expand now +(setf *pianosyn-save-gc-flag* *gc-flag*) +(setf *gc-flag* nil) ;; we'll do a lot of gc, so turn off messages +;; Definite some constant +(setq NPITCH 22 GROUPCON 23) +(setq MAXAMP 32767.0) +(setq TWOPI (+ pi pi)) +(setq *piano-srate* *default-sound-srate*) +(setq bits 32) +;; 512 gives pretty good SNR for interpolated sines +;; some tables will be larger: 512 is just the minimum +(setq tabsize 512) + +;; For ending time, use 30 msec. (This was originally 0.1 msec, +;; about 4 samples, but that's too short to avoid clicks.) +;; This not only must avoid clicks but it simulates the damper. +;; This is the time to decay to 0.001 of the original, so it's +;; actually quite a rapid decay. +(setq endingtime 0.03) + +(setf hkframe (list 66 73 82 90 99 108 116 123 130 135 138 140 138 + 133 126 117 107 102 105 127 153 187 200)) +(setf attsratelist (list 8000 11025 16000 22050 32000 44100 48000)) +(setf gmax1 (make-array GROUPCON)) +(setf scalegmag1 (make-array GROUPCON)) +(setf scale1 (make-array GROUPCON)) +(setf wavetab (make-array GROUPCON)) +(setf ti (make-array GROUPCON)) +(setf tstep (make-array GROUPCON)) +(setf gmaxtabdim (make-array 4)) +(setf gmaxtab (make-array 64768)) +(setf durtabdim (make-array 4)) +(setf durtab (make-array 16384)) +(setf rlsratetabdim (make-array 4)) +(setf rlsratetab (make-array 11392)) +(setf fa (make-array GROUPCON)) +(setf dt (make-array GROUPCON)) +(setf ngroup (make-array GROUPCON)) +(setf npts (make-array GROUPCON)) +(setf gmag (make-array GROUPCON)) +(setf nhar (make-array GROUPCON)) + +(setf gmagmini (make-array GROUPCON)) +(setf dtmini (make-array GROUPCON)) +(setf nptsmini (make-array GROUPCON)) + +(setf cw (make-array GROUPCON)) +(setf phase (make-array GROUPCON)) +(setf hfrom (make-array GROUPCON)) +(setf hto (make-array GROUPCON)) + +(setf *zero-table* (scale 0 (build-harmonic 1 tabsize))) + +;; ================================================= +;; run-once initilization: pianoActor construction +;; ================================================= +(princ "\nBegin Instrument-wise initialization...\n") +(princ "=======================================\n") +(princ "Reading source files:\n") + + +;; Read gmax.tab +(readdat "gmax.tab" gmaxtabdim gmaxtab) + +;; Read dur.tab +(readdat "dur.tab" durtabdim durtab) + +;; Read rlsrate.tab +(readdat "rlsrate.tab" rlsratetabdim rlsratetab) + +;; Read cwxx.cwd +(dotimes (pncount GROUPCON) + (format t "~A " pncount) + (setq filename (strcat "pn" + (string (int-char (+ (truncate (/ pncount 10)) 48))) + (string (int-char (+ (rem pncount 10) 48))) + ".cod")) + (setq filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) + (setq fp (open-binary filename)) + + ;; Read cwdHdr in cwxx.cwd + (setq cwdHdr-ckID (read-int fp) cwdHdr-type (read-int fp)) + ;; "CNDN" == 1129202766 + + ;; That is for "FORM"==cwdHdr-ckID + ;;(if (and (= cwdHdr-ckID 1179603533) (= cwdHdr-type 1129202766)) + ;; () + ;; (error "Error in reading chunk header.")) + + ;;That is for "SYNC"==cwdHdr-ckID + (if (and (= cwdHdr-ckID 1398361667) (= cwdHdr-type 1129202766)) + () + (error "Error in reading chunk header.")) + + ;; Read COMMCK in cwxx.cwd + (setq COMMCK-ckID (read-int fp)) + (if (= COMMCK-ckID 1129270605) () (error "COMMCK chunk not found.")) + (setq COMMCK-fa (read-float fp) COMMCK-dt (read-float fp)) + (setf (aref fa pncount) COMMCK-fa) + (setf (aref dt pncount) COMMCK-dt) + (setf (aref dtmini pncount) (* 10 COMMCK-dt)) + (setq COMMCK-npts (read-int fp) COMMCK-ngroup (read-int fp)) + (setf (aref npts pncount) COMMCK-npts) + (setf (aref nptsmini pncount) + (truncate (/ (+ 9 (- COMMCK-npts (nth pncount hkframe))) 10))) + (setf (aref ngroup pncount) COMMCK-ngroup) + + ;; Read DATACK in cwxx.cwd + (setq DATACK-ckID (read-int fp)) + (if (= DATACK-ckID 1346458196) () (error "DATACK chunk not found.")) + (setf (aref nhar pncount) (read-int fp)) + (setf (aref cw pncount) (make-array (aref nhar pncount))) + (setf (aref phase pncount) (make-array (aref nhar pncount))) + (dotimes (count (aref nhar pncount)) + (setf (aref (aref cw pncount) count) (read-float fp))) + (dotimes (count (aref nhar pncount)) + (setf (aref (aref phase pncount) count) (read-float fp))) + + ;; Read GRUPCK in cwxx.cwd + (setq GRUPCK-ckID (read-int fp)) + (if (= GRUPCK-ckID 1196578128) () (error "GRUPCK chunk not found.")) + (setf (aref hfrom pncount) (make-array (aref ngroup pncount))) + (setf (aref hto pncount) (make-array (aref ngroup pncount))) + ;(display "reading grupck" (aref ngroup pncount) (aref nhar pncount) pncount) + (dotimes (count (aref ngroup pncount)) + (setf (aref (aref hfrom pncount) count) + (read-float fp))) + (dotimes (count (aref ngroup pncount)) + (setf (aref (aref hto pncount) count) (read-float fp))) + + ;; Read GMAGCK in cwxx.cwd + (setq GMAGCK-ckID (read-int fp)) + (if (= GMAGCK-ckID 1196245319) + () + (error "GMAGCK chunk not found.")) + (setq gmaghead (read-int fp)) + (close fp) + (setf (aref gmag pncount) (make-array (aref ngroup pncount))) + (setq gmagrate (/ 1 (aref dt pncount))) + (setq gmagdur (/ (nth pncount hkframe) gmagrate)) + + ; (display "gmagmini" pncount (aref ngroup pncount)) + (setf (aref gmagmini pncount) (make-array (aref ngroup pncount))) + (setq gmagratemini (/ 1 (aref dtmini pncount))) + (setq gmagdurmini (/ (aref nptsmini pncount) gmagratemini)) + + (dotimes (i (aref ngroup pncount)) + (let (gmaghead1 samps gmaghead1mini) + (setf gmaghead1 (/ (float gmaghead) (* gmagrate (/ bits 8)))) + ;(display "gmag read" i gmaghead1 gmagrate filename) + (setf samps (s-read filename :time-offset gmaghead1 :srate gmagrate + :dur gmagdur :mode snd-mode-float + :format snd-head-raw :bits bits :endian :big)) + (if samps (snd-length samps ny:all)) ; force read into memory + (setf (aref (aref gmag pncount) i) samps) + (setq gmaghead (+ gmaghead (* 4 (nth pncount hkframe)))) + (setq gmaghead1mini (/ (float gmaghead) (* gmagratemini (/ bits 8)))) + ;(display "gmag read mini" i gmaghead1mini gmagratemini filename) + (setf samps (s-read filename :time-offset gmaghead1mini :srate gmagratemini + :dur gmagdurmini :mode snd-mode-float :format snd-head-raw + :bits bits :endian :big)) + (if samps (snd-length samps ny:all)) ; force read into memory + ;(display "read gmagmini" filename pncount i + ; (if samps (snd-length samps ny:all))) + (setf (aref (aref gmagmini pncount) i) samps) + (setq gmaghead (+ gmaghead (* 4 (aref nptsmini pncount)))) + )) +) + +(setq maxfreq (aref fa (1- GROUPCON))) +(dotimes (i GROUPCON) + (setq ngrouptemp -1) + (dotimes (j (aref ngroup i)) + (if (and (= ngrouptemp -1) + (>= (* (aref (aref hto i) j) (aref fa i)) + (/ *piano-srate* 2))) + (setq ngrouptemp j))) + (if (>= ngrouptemp 0) (setf (aref ngroup i) ngrouptemp))) + +(princ "\nGenerating wavetables...\n") +(setq tempi (/ (* 360 tabsize) (* TWOPI TWOPI))) +(dotimes (h GROUPCON) + (setf (aref wavetab h) (make-array (aref ngroup h))) + (dotimes (i (aref ngroup h)) + ;(FORMAT T "WAVE ~A OF GROUP ~A~%" i h) + (let ((low (aref (aref hfrom h) i)) + (high (aref (aref hto h) i)) + tempphase tempcw + (len tabsize)) + ; table size must be more than twice greatest harmonic number + ; use a factor of three so we have a wider margin of oversampling + (setf len (max len (* 3 high))) + (setf sumwave *zero-table*) + (do ((k (truncate low) (incf k))) + ((> k high)) + (cond ((< k (aref nhar h)) + (setq tempphase (aref (aref phase h) k)) + (setq tempcw (aref (aref cw h) k))) + (t + (setq tempphase 0) + (setq tempcw 0))) + (setf sumwave (sum sumwave (scale tempcw (build-harmonic-phase k + (+ (* tempphase tempi) 90.0) + len)))))) + ;(PRINT "FORCE SUMMATION OF WAVE") + (snd-length sumwave ny:all) ; force summation + ;( "END SUMMATION OF WAVE") + (setf (aref (aref wavetab h) i) (list sumwave (hz-to-step 1) T)))) + +;; Read in attack sound +(princ "\nRead in attack sound...\n") +(setq attndur 0.5) +(setq attnth -1) +(dotimes (count (length attsratelist)) + (if (and (= attnth -1) (<= *piano-srate* (nth count attsratelist))) (setq attnth count))) +(if (or (= attnth -1) (/= (nth attnth attsratelist) *piano-srate*)) + (princ "No attack sound rate corresponds to current sound rate, use the nearest one\n")) +(if (> attnth 0) + (if (<= (- (nth attnth attsratelist) *piano-srate*) (- *piano-srate* (nth (1- attnth) attsratelist))) + (setq attsrate (nth attnth attsratelist)) (setq attsrate (nth (1- attnth) attsratelist))) + (case attnth + (-1 (setq attsrate (last attsratelist))) + (0 (setq attsrate (nth 0 attsratelist))))) +(setq filename (format nil "att~A.pcm" (truncate attsrate))) +(setf filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) +(setf attsound + (s-read filename :srate attsrate :dur attndur :format snd-head-raw + :mode snd-mode-pcm :bits 16 :endian :big)) + +(princ "=============================================\n") +(princ "End instrument-wise initialization\n") +(princ "\n\n=============================================\n") +(princ "Piano Synthesizer function definition:\n") +(princ "(piano-note-2 step dynamic)\n") +(princ "(piano-note duration step dynamic)\n") +(princ "(piano-midi midi-file-name)\n") +(princ "(piano-midi2file midi-file-name sound-file-name)\n\n") +(princ "=============================================\n") +(setf *gc-flag* *pianosyn-save-gc-flag*) ;; restore original value + + +#| + +;;================= DEBUGGING CODE ========================= +;; +;; run (show-cn-file n) to dump some data from pn??.cod +;; +;;========================================================== + + +;; INT-HEX -- convert integer to hex string +;; +(defun int-hex (int) + (let ((result "") ch) + (while (/= int 0) + (setf ch (char "0123456789ABCDEF" (logand int 15))) + (setf result (strcat (string ch) result)) + (setf int (/ int 16))) + (if (equal result "") "0" result))) + +(defun int-4char (int) + (strcat (string (int-char (logand 255 (/ int (* 256 256 256))))) + (string (int-char (logand 255 (/ int (* 256 256))))) + (string (int-char (logand 255 (/ int 256)))) + (string (int-char (logand 255 int))))) + +(defun show-cn-file (pncount) + (let (filename fp cwdhdr-ckid cwdhdr-type) + (setq filename (strcat "pn" + (string (int-char (+ (truncate (/ pncount 10)) 48))) + (string (int-char (+ (rem pncount 10) 48))) + ".cod")) + (setf filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) + (format t "SHOW-CN-FILE ~A (~A)~%" pncount filename) + (setf fp (open-binary filename)) + ;; Read cwdHdr in cwxx.cwd + (setq cwdHdr-ckID (read-int fp) cwdHdr-type (read-int fp)) + (format t "header ckID: ~A (~A)~%" (int-hex cwdhdr-ckid) + (int-4char cwdhdr-ckid)) + (format t "header type: ~A (~A)~%" (int-hex cwdhdr-type) + (int-4char cwdhdr-type)) + (setq COMMCK-ckID (read-int fp)) + (format t "header ckID: ~A (~A)~%" (int-hex commck-ckid) + (int-4char commck-ckid)) + (setq COMMCK-fa (read-float fp) COMMCK-dt (read-float fp)) + (format t "commck-fa ~A commck-dt ~A~%" commck-fa commck-dt) + (setq COMMCK-npts (read-int fp) COMMCK-ngroup (read-int fp)) + (format t "commck-npts ~A commck-ngroup ~A~%" commck-npts commck-ngroup) + (setq DATACK-ckID (read-int fp)) + (format t "header ckID: ~A (~A)~%" (int-hex datack-ckid) + (int-4char datack-ckid)) + (setf datack-nhar (read-int fp)) + (format t "datack-nhar ~A~%cw data:" datack-nhar) + (dotimes (i datack-nhar) + (if (and (zerop (rem i 10)) (or (< i 10) (> i (- datack-nhar 10)))) + (format t "~% ~A:" i)) + (setf data-cw (read-float fp)) + (if (or (< i 10) (>= i (* (/ datack-nhar 10) 10))) + (format t " ~A" data-cw))) + (format t "~%phase data:") + (dotimes (i datack-nhar) + (if (and (zerop (rem i 10)) (or (< i 10) (> i (- datack-nhar 10)))) + (format t "~% ~A:" i)) + (setf data-phase (read-float fp)) + (if (or (< i 10) (> i (- datack-nhar 10))) (format t " ~A" data-cw))) + (format t "~%") + (setf grupck-ckid (read-int fp)) + (format t "header ckID: ~A (~A)~%hfrom data:" + (int-hex grupck-ckid) (int-4char grupck-ckid)) + (dotimes (count commck-ngroup) + (setf data-hfrom (read-float fp)) + (if (zerop (rem count 10)) + (format t "~% ~A:" count)) + (format t " ~A" data-hfrom)) + (format t "~%hto data:") + (dotimes (count commck-ngroup) + (setf data-hto (read-float fp)) + (if (zerop (rem count 10)) + (format t "~% ~A:" count)) + (format t " ~A" data-hto)) + (setf gmagck-ckid (read-int fp)) + (format t "~%header ckID: ~A (~A)~%" + (int-hex gmagck-ckid) (int-4char gmagck-ckid)) + (setf gmaghead (read-int fp)) + (format t "gmaghead ~A" gmaghead) + (format t "~%") + ;; compute range of data to be read + (setf offset gmaghead) + (dotimes (i commck-ngroup) + (format t "gmag: group ~A offset ~A length ~A end ~A~%" + i offset (* 4 (nth pncount hkframe)) + (+ offset (* 4 (nth pncount hkframe)))) + (setf offset (+ offset (* 4 (nth pncount hkframe)))) + (format t "gmagmini: group ~A offset ~A length ~A end ~A~%" + i offset (* 4 (aref nptsmini pncount)) + (+ offset (* 4 (aref nptsmini pncount)))) + (setf offset (+ offset (* 4 (aref nptsmini pncount))))) + + (close fp) + + (setf gmag-and-gmagmini + (s-read filename + :time-offset (* (float gmaghead) 0.25 commck-dt) + :srate (/ 1.0 commck-dt) + :mode snd-mode-float :format snd-head-raw + :bits 32 :endian :big)))) +|# diff --git a/lib/plugin-test.lsp b/lib/plugin-test.lsp new file mode 100644 index 0000000..5e78342 --- /dev/null +++ b/lib/plugin-test.lsp @@ -0,0 +1,184 @@ +;; plugin-test -- simulate Audacity interface to Nyquist plugins +;; +;; Roger B. Dannenberg, Dec 2005 +;; +;; This program runs an Audacity plugin from within Nyquist, where +;; more debugging tools are available. +;; There are two functions: +;; +;; (PLUGIN-TEST "plugin-file-name") -- full emulation of Audacity, +;; prompts for parameters and audio file. The ".ny" extension +;; is optional. +;; +;; (PLUGIN-AUTO-TEST "plugin-file-name" bindings ["audio-file-name"]) -- load +;; and run the plugin. Bindings is a list of bindings, e.g. +;; ((amp 1.0) (n 3)), setting the controls of the plugin. +;; This version does not prompt for values. +;; + + +;; ADD-EXTENSION -- if filename does not end in ext, append ext to +;; filename ext should include the ".", e.g. ".ny" +;; +(defun add-extension (filename ext) + (cond ((equal (subseq filename (- (length filename) (length ext))) + ext) + filename) + (t + (strcat filename ext)))) + +(defun string-to-number (str) + (read (make-string-input-stream str))) + + +(defun parse-control-spec (line) + (let ((stream (make-string-input-stream (subseq line 8)))) + (list (read stream) + (read stream) + (read stream) + (read stream) + (read stream) + (read stream) + (read stream)))) + + +(defun describe-sound (snd) + (let ((typ (type-of snd)) sr) + (cond ((eq typ 'sound) + (setf typ "single-channel sound") + (setf sr (snd-srate snd))) + ((and (eq typ 'VECTOR) (eq (type-of (aref snd 0)) 'SOUND)) + (setf typ "multi-channel sound") + (setf sr (snd-srate (aref snd 0))))) + (cond ((stringp typ) + (format t "=== Plugin result is a ~A at sample rate ~A ===~%" + typ sr) + snd) + (t + (format t "=== Plugin result is of type ~A ===~%" typ) + (pprint snd) ;; print result of plugin if it's not a sound + (s-rest 0.1))))) ;; return silence to make play happy + + +(defun read-file-expressions (filename) + (let (file expr exprs) + (setf file (open filename)) + (while (setf expr (read file)) + (push expr exprs)) + (reverse exprs))) + + +;; AUDIO-FILE-TO-BINDINGS -- convert audio filename to pair of bindings: +;; ((s (s-read )) (len )) +;; return nil if filename is invalid +;; +(defun audio-file-to-bindings (audio-file) + (let (source) + (if (> (length audio-file) 0) + (setf source (s-read audio-file))) + (cond (source + (setf len (* (nth 5 *rslt*) (nth 6 *rslt*))) + (list `(len ,len) + `(s (s-read ,audio-file)))) + (t nil)))) + + +(defun plugin-test (filename) + (let (file controls bindings description plug-type + value audio-file source exprs len) + ;; first, check for filename extension + (setf filename (add-extension filename ".ny")) + ;; see if we can open the file + (setf file (open filename)) + (if (null file) + (error (strcat "Could not open " filename))) + ;; parse the file + ;sym init step + (do ((line (read-line file) (read-line file))) + ((null line)) + ;(display "pass 1" line) + (cond ((eql 0 (string-search ";control" line)) + (push (parse-control-spec line) controls)) + ((or (eql 0 (string-search ";nyquist" line)) + (eql 0 (string-search ";version" line)) + (eql 0 (string-search ";name" line)) + (eql 0 (string-search ";action" line)) + (eql 0 (string-search ";info" line))) + (push line description)) + ((eql 0 (string-search ";type" line)) + (cond ((string-search "process" line) + (setf plug-type 'process)) + ((string-search "generate") + (setf plug-type 'generate)) + ((string-search "analyze") + (setf plug-type 'analyze)) + (t + (error (strcat "unexpected specification: " line))))))) + (close file) + ;; print description + (dolist (line description) + (format t "~A~%" line)) + ;; get control values and set them as global variables + (setf controls (reverse controls)) + (read-line) ;; read the newline after the expression that called this fn + ;; (otherwise, we'll read in unintended new-line for first control) + (dolist (control controls) + ;; control is (symbol description type units default minimum maximum) + (let ((sym (car control)) + (desc (cadr control)) + (ctrl-type (caddr control)) + (units (cadddr control)) + (default (nth 4 control)) + (minimum (nth 5 control)) + (maximum (nth 6 control))) + (loop + (format t "~A (~A) [~A]: " desc units default) + (setf value (read-line)) + (if (equal value "") + (setf value default) + (setf value (string-to-number value))) + (if (equal ctrl-type 'int) + (setf value (round value)) + (setf value (float value))) + (if (and (<= minimum value) (<= value maximum)) + (return)) ; break from loop + (format t "Try again, value must be between ~A and ~A.~%" + minimum maximum)) + (push (list sym value) bindings))) + (setf bindings (reverse bindings)) + ;; determine the sound file name to process, if any, and open it + (cond ((member plug-type '(process analyze)) + (loop + (format t "Audio input file: ") + (setf audio-file (read-line)) + (setf source (audio-file-to-bindings audio-file)) + (if source (return)) + (format t "Could not open ~A. Try again.~%" audio-file)) + (setf bindings (append source bindings)))) + ;; now we're ready to read the plug-in as expressions + (setf exprs (read-file-expressions filename)) + ;; turn expression list into a let and evaluate + (run-plugin exprs bindings))) + + +(defun plugin-auto-test (filename bindings &optional audio-file) + (setf filename (add-extension filename ".ny")) + (let ((exprs (read-file-expressions filename)) + source) + (cond (audio-file + (setf source (audio-file-to-bindings audio-file)))) + (cond (source + (setf bindings (append source bindings))) + (t + (error (strcat "audio file not valid: " audio-file)))) + (run-plugin exprs bindings))) + +(defun run-plugin (exprs bindings) + (setf exprs `(let (,@bindings) ,@exprs)) + (pprint exprs) + (play (describe-sound (eval exprs)))) + + + + + diff --git a/lib/reverb.lsp b/lib/reverb.lsp new file mode 100644 index 0000000..32da1ad --- /dev/null +++ b/lib/reverb.lsp @@ -0,0 +1,45 @@ +(defun reverb (x time) + (multichan-expand #'reverb-mono x time)) + +(defun reverb-mono (ga irevfactor) + (let (sr ilowpass idel ihz icsc acomball allp1 allp2 allp3 alow allp4 allp5 + arevout) + (setf sr (snd-srate ga)) + + (setf ilowpass 9000.000) ; frequency of lowpass filter + + (setf idel (list ; list of frequency/delay values + (/ 1237.000 sr) (/ 1381.000 sr) (/ 1607.000 sr) + (/ 1777.000 sr) (/ 1949.000 sr) (/ 2063.000 sr) + (/ 307.000 sr) (/ 97.000 sr) (/ 71.000 sr) + (/ 53.000 sr) (/ 47.000 sr) (/ 37.000 sr) + (/ 31.000 sr))) + ; Nyquist's comb filter uses Hz rather than delay as parameter, + ; so take reciprocals to get Hz: + (setf ihz (mapcar #'/ idel)) + + (setf icsc (list ; list of delay times + (* irevfactor 0.822) (* irevfactor 0.802) + (* irevfactor 0.773) (* irevfactor 0.753) + (* irevfactor 0.753) (* irevfactor 0.753) + (* irevfactor 0.7))) + + (setf acomball (sum + (comb ga (nth 0 icsc) (nth 0 ihz)) + (comb ga (nth 1 icsc) (nth 1 ihz)) + (comb ga (nth 2 icsc) (nth 2 ihz)) + (comb ga (nth 3 icsc) (nth 3 ihz)) + (comb ga (nth 4 icsc) (nth 4 ihz)) + (comb ga (nth 5 icsc) (nth 5 ihz)))) + + (setf allp1 (alpass acomball (nth 6 icsc) (nth 6 ihz))) + (setf allp2 (alpass allp1 (nth 6 icsc) (nth 7 ihz))) + (setf allp3 (alpass allp2 (nth 6 icsc) (nth 8 ihz))) + (setf alow (lp allp3 ilowpass)) + (setf allp4 (alpass alow (nth 6 icsc) (nth 9 ihz))) + (setf allp5 (alpass allp4 (nth 6 icsc) (nth 11 ihz))) + + allp5 + ; acomball + )) + diff --git a/lib/reverse.lsp b/lib/reverse.lsp new file mode 100644 index 0000000..f2f8e3a --- /dev/null +++ b/lib/reverse.lsp @@ -0,0 +1,117 @@ +;; reverse.lsp -- reverse sounds and files +;; + +(setf *max-reverse-samples* 25000000) ;; about 100MB of memory +(setf *reverse-blocksize* 10000) ;; how many to reverse at a time + +(defun s-reverse (snd) (multichan-expand #'nyq:s-reverse snd)) + +(defun nyq:s-reverse (snd) + (let ((now (local-to-global 0))) + (setf len (snd-length snd *max-reverse-samples*)) + (cond ((= len *max-reverse-samples*) + (error + "s-reverse cannot reverse a sound longer than *max-reverse-samples*"))) + (abs-env (at-abs now (nyq:s-reverse-from snd len))))) + +(defun nyq:s-reverse-from (snd len) + (cond ((> len *reverse-blocksize*) + (seq (nyq:reverse-some-samples snd (- len *reverse-blocksize*) + *reverse-blocksize*) + (nyq:s-reverse-from snd (- len *reverse-blocksize*)))) + (t + (nyq:reverse-some-samples snd 0 len)))) + +(defun nyq:reverse-some-samples (snd offset len) + (display "reverse-some-samples" (snd-length snd 20000) offset len) + (let ((samps (snd-samples (nyq:extract-samples snd offset len) len)) + (i2 (1- len))) + (display "reverse-some-samples" (length samps)) + (dotimes (i1 (/ len 2)) + (let ((s1 (aref samps i1)) + (s2 (aref samps i2))) + (setf (aref samps i1) s2) + (setf (aref samps i2) s1) + (setf i2 (1- i2)))) + (snd-from-array (local-to-global 0) (snd-srate snd) samps))) + +(defun nyq:extract-samples (snd offset len) + (let (start stop) + (setf start (/ offset (snd-srate snd))) + (setf stop (+ start (/ len (snd-srate snd)))) + (display "nyq:extract-samples" start stop (snd-t0 snd)) + (extract-abs start stop snd))) + +;(play (s-reverse (s-read "sample.wav"))) + +(defun s-read-reverse (filename &key (time-offset 0) (srate *sound-srate*) + (dur 10000) (nchans 1) (format *default-sf-format*) + (mode *default-sf-mode*) (bits *default-sf-bits*) + (endian nil)) + (let (fsrate fdur channels rslt) + ;; first, read the sound just to get the duration and rate of the file + (setf rslt (s-read filename :time-offset time-offset :srate srate :dur dur + :nchans nchans :format format :mode mode + :bits bits :endian endian)) + (if (null rslt) (error "s-read-reverse could not open file" filename)) + (setf channels (cadr *rslt*)) + (setf *rslt* (cddddr *rslt*)) + (setf fsrate (cadr *rslt*)) + (display "s-read-reverse" filename srate channels) + (setf fdur (caddr *rslt*)) + (setf time-offset (max 0 (min fdur time-offset))) + (setf dur (max 0 (min (- fdur time-offset) dur))) + (cond ((> channels 1) + (setf rslt (make-array channels)) + (dotimes (i channels) + (setf (aref rslt i) + (nyq:s-reverse-file filename time-offset fsrate dur + channels format mode bits endian i))) + rslt) + (t (nyq:s-reverse-file filename time-offset fsrate dur + channels format mode bits endian nil))))) + + +;; nyq:s-reverse-file -- do the work of reversing one channel of a file +;; +;; if nchans > 1, chan is the channel number to read +;; +(defun nyq:s-reverse-file (filename time-offset srate dur nchans + format mode bits endian chan) + (let ((blockdur (/ *reverse-blocksize* srate))) + (if (> dur blockdur) + (seq (nyq:reverse-some-samples + (nyq:s-read-chan filename + (+ time-offset dur (- blockdur)) + srate (/ *reverse-blocksize* srate) + nchans format mode bits endian chan) + 0 *reverse-blocksize*) + (nyq:s-reverse-file filename time-offset srate (- dur blockdur) + nchans format mode bits endian chan)) + (nyq:s-read-chan filename time-offset srate dur nchans format + mode bits endian chan)))) + + +;; nyq:s-read-chan -- grab some samples from one channel of a file +;; +(defun nyq:s-read-chan (filename time-offset srate dur nchans format + mode bits endian chan) + (let (rslt) + (setf rslt + (if (= nchans 1) + (s-read filename :time-offset time-offset :srate srate + :dur dur :nchans nchans :format format :mode mode + :bits bits :endian endian) + (aref (s-read filename :time-offset time-offset :srate srate + :dur dur :nchans nchans :format format :mode mode + :bits bits :endian endian) + chan))) + (if (not rslt) (error "nyq:s-read-chan could not read part of file" filename)) + rslt)) + + +;(play (s-read-reverse "sample.wav")) +;(play (s-read-reverse "test.wav")) + + + \ No newline at end of file diff --git a/lib/sdl.lsp b/lib/sdl.lsp new file mode 100755 index 0000000..ea22071 --- /dev/null +++ b/lib/sdl.lsp @@ -0,0 +1,402 @@ +;;; Score Description Library. v 1.0 +;;; pmorales. Junio, 2007 + + +; NOTAS: +; - es obligatorio definir un instrumento al menos y asignarlo desde el principio +; - en su lugar hay que utilizar TF (time factor) que tiene un efecto similar al de Cakewalk +; - los atributos ATTR solo tienen efecto sobre el instrumento que estan definidos. +; los atributos estan asociados a un instrumento en particular + +; a helper function ------------------------------------------ + +(defun floor (x) + (round (- x 0.5))) + + +; this code is imported from pmorales lambda music + +(defun sdl:pitch-lex (pitch) + "ARGS: pitch +DEVUELVE: Cadena con el valor del argumento convertido a pitch-midi" + (case (type-of pitch) + (fixnum pitch) + (flonum pitch (round pitch)) + (symbol (sdl:pitch-name->step (let ((str (symbol-name pitch))) (if (equal (char str 0) #\:) (subseq str 1) str)))) + (string (sdl:pitch-name->step pitch)) + (t (error "PITCH-LEX: Error lexico en especificacion de pitch")))) + + +(defun sdl:digit-char-p (chr) + (char>= #\9 chr #\0)) + +(defun sdl:code-pitch-p-1 (chr) + (or (char>= #\g chr #\a) (char>= #\G chr #\A))) + +(defun sdl:code-pitch-p-2 (chr) + (or (eq chr #\#) (eq chr #\b)(eq chr #\B)(eq chr #\s)(eq chr #\f) (sdl:digit-char-p chr))) + +(defun sdl:pitch-p (str) + "Detecta si el argumento es un simbolo que representa un pitch" + (case (length str) + (1 (sdl:code-pitch-p-1 (aref str 0))) + (2 (and (sdl:code-pitch-p-1 (char str 0)) (sdl:code-pitch-p-2 (char str 1)))) + (3 (and (sdl:code-pitch-p-1 (char str 0)) (sdl:code-pitch-p-2 (char str 1)) + (sdl:digit-char-p (char str 2)))) + (4 (and (sdl:code-pitch-p-1 (char str 0)) (sdl:code-pitch-p-2 (char str 1)) + (sdl:digit-char-p (char str 2)) (sdl:digit-char-p (char str 3)))))) + + +(defun sdl:b-or-# (pname) + (let ((chrom (char pname 1))) + (case chrom + ((#\b #\B #\f) -1) + ((#\# #\s) 1) + (t 0)))) + +(defun sdl:pitch-name-category (pname) + (let ((first-char (char pname 0))) + (case first-char + ((#\C #\c) 0) + ((#\D #\d) 2) + ((#\E #\e) 4) + ((#\F #\f) 5) + ((#\G #\g) 7) + ((#\A #\a) 9) + ((#\B #\b) 11) + (t (error (strcat "Improper pitch name " pname)))))) + +(defun sdl:char-to-val (char) + (- (char-code char) 48)) + +(defun sdl:string-to-val (string) + (let ((len (1- (length string)))) + (do* ((i -1 (1+ i)) + (suma 0 (+ suma (* (sdl:char-to-val (char string i)) (expt 10 (float (- len i))))))) + ((= i len) suma)))) + +(defun sdl:pitch-name->step (pname) + (when (symbolp pname) (setf pname (string-trim ":" (symbol-name pname)))) + (let ((chrom (sdl:b-or-# pname)) + (category (sdl:pitch-name-category pname)) + (octave (sdl:string-to-val (string-left-trim "AaBbCcDdEeFfGg#s" pname)))) + (+ chrom category (* 12 (- octave 4)) 60))) + + +(defun sdl:one-of-twelve-to-string (number) + (case number + (0 "C") + (1 "C#") + (2 "D") + (3 "D#") + (4 "E") + (5 "F") + (6 "F#") + (7 "G") + (8 "G#") + (9 "A") + (10 "A#") + (11 "B"))) + +(defun step->pitch-name (midi-number) + (let ((one-of-twelve (rem midi-number 12)) + (octave (1- (floor (/ midi-number 12))))) + (format nil "~A~A" (sdl:one-of-twelve-to-string one-of-twelve) octave))) + +(defun step->hz (midi) + (* 440.0 (expt 2.0 (/ (- midi 69.0) 12.0)))) + +(defun pitch-name->hz (name) + (step->hz (pitch-name->step name))) + +(defun pitch-name->step (pn) + (if (numberp pn) + pn + (sdl:pitch-name->step pn))) + + + + + +;;; functions for SYMBOL PROPERTY LIST processing + + +(defun sdl:iterate-on-symbol-plist (fun plist &optional result) + (if plist + (sdl:iterate-on-symbol-plist fun (cddr plist) (cons (funcall fun (car plist) (second plist)) result)) + result)) + + +(defun sdl:sort-pwl (plist) + (sdl:iterate-on-symbol-plist + #'(lambda (sym pwl-list) + (list sym (sort pwl-list #'(lambda (x y) (< (car x)(car y)))))) + plist)) + + + +; ATENCION: los calculos se hacen sobre pulsos, no sobre segundos +(defun sdl:calcule-pwl-val (tm plist) + (apply #'append + (sdl:iterate-on-symbol-plist + #'(lambda (prop-sym prop-val) + (list prop-sym (sdl:pwl-val tm prop-val))) + plist))) + + + +; this function compute variable attributes + +(defun sdl:pwl-val (x points) + (labels + ((pwl-interpolate (x x1 y1 x2 y2) + (let* ((a (/ (- y1 y2) (- x1 (float x2)))) + (b (- y1 (* a x1)))) + (+ b (* a x)))) + (search-points (x points &optional (result 0)) + (if (or (null points) (< x (caar points))) + result + (search-points x (cdr points) (+ 1 result)))) + (points-xval (n points) (car (nth n points))) + (points-yval (n points) (cadr (nth n points)))) + (let ((len (length points)) + (index (search-points x points))) + (cond + ((= 0 index) (points-yval 0 points)) + ((= len index) (points-yval (- len 1) points)) + (t (pwl-interpolate x (points-xval (- index 1) points) (points-yval (- index 1) points) + (points-xval index points) (points-yval index points))))))) + + +; macros in SDL-------------------------------------------------------------- + +(defun sdl:is-event-macro? (ev) + (and (listp ev) (equal (car ev) 'MAC))) + +(defun sdl:score-has-macros? (sdl-sco) + (do ((i 0 (+ 1 i)) + result) + ((cond + ((sdl:is-event-macro? (nth i sdl-sco)) (setf result T) T) + ((= i (length sdl-sco)) T)) + result))) + +(defun sdl:expand-macros (sdl-sco) + (apply #'append + (mapcar #'(lambda (ev) + (cond + ((not (listp ev)) (list ev)) + ((and (listp ev) (not (equal (car ev) 'MAC))) (list ev)) + (t (apply (second ev) (cddr ev))))) + sdl-sco))) + + +; main functions for SDL ------------------------------------------------------- + +; this is a BIG function + +(defun sdl:sdl->score-aux (score-data &optional time-marks) + (let ((tf 1.0) ; global time factor + sc-instr + chords + (sc-time 0) + (sc-dur 1)) + (unless time-marks (setf time-marks (gensym))) + (labels ((filter-name (ky l &optional xresult) + (if l + (if (not (member (car l) ky :test #'equal)) + (let () (push (car l) xresult) + (push (cadr l) xresult) + (filter-name ky (cddr l) xresult)) + (filter-name ky (cddr l) xresult)) + (reverse xresult))) + (attrs-vals () (symbol-plist sc-instr)) + (scale-score-time (event scale) + (list (* scale (car event)) (* scale (cadr event)) (caddr event))) + (make-sc-note (p) (list sc-time sc-dur + (append (list (get sc-instr :name) :pitch (sdl:pitch-lex p)) + (sdl:calcule-pwl-val sc-time (get sc-instr :pwl)) + (filter-name (list :name :pwl) (attrs-vals))))) + (calcula-dur (datum) (if (listp datum) (eval datum) datum)) + (setdur (dur) (setf sc-dur (calcula-dur (car dur)))) + (setinstr (instr) (setf sc-instr (intern (car instr)))) + (init-instr (instr instr-name) + (setf sc-instr (intern instr)) + (setf (symbol-plist sc-instr) NIL) + (putprop sc-instr (gensym) :pwl) + (putprop sc-instr instr-name :name)) + (set-attr (prop val) (putprop sc-instr val prop)) + (set-pwl-point (prop val) + (push (list sc-time val) (get (get sc-instr :pwl) prop))) + (set-mrk (mrk-symbol) (if (get time-marks mrk-symbol) + (error "sdl->score: time mark ~A already set" mrk-symbol) + (putprop time-marks sc-time mrk-symbol))) + (set-time-mrk (mrk-symbol) + (let ((mrk-time (get time-marks mrk-symbol))) + (if mrk-time (setf sc-time mrk-time) + (error (format nil "sdl->score: time mark ~A does not exists" mrk-symbol))))) + + + (proc-elt-for-pwl (elt) + (if (not (listp elt)) + (cond ((numberp elt) (setf sc-time (+ sc-time elt)) NIL) + (t (setf sc-time (+ sc-time sc-dur)) NIL)) + (case (car elt) + ((KEY TS CHN PATCH LM TN MRK NTR) NIL) ; filter out all these + ; for compatibility with lambda music + ((TF) (setf tf (calcula-dur (cadr elt))) NIL) + ((LABEL SET-MRK) NIL) + ((AT-LABEL AT-MRK) NIL) + ((TIME-IN-SECONDS) (setf tf 0.25) NIL) ; with mm = 60 + ((DUR) (setdur (cdr elt)) NIL) + ((INSTRUMENT) (setinstr (cdr elt)) NIL) + ((INIT-INSTR) (init-instr (second elt)(third elt)) NIL) + ((ATTR) NIL) + ((PWL-POINT) (set-pwl-point (second elt) (calcula-dur (third elt))) NIL) + ((FUN) (apply (eval (cadr elt)) (cddr elt))) + ((DELTA PAU) (setf sc-time (+ sc-time (calcula-dur (second elt)))) NIL) ; pause positive or negative + ((CH) (setf sc-time (+ sc-time sc-dur)) NIL) + ((CH1) (setf sc-dur (calcula-dur (third elt))) ; pitch dur + (setf sc-time (+ sc-time sc-dur)) NIL) + (t (setf sc-dur (calcula-dur (cadr elt))) + (setf sc-time (+ sc-time sc-dur)) + NIL)))) + + + + + (proc-elt (elt) + (if (not (listp elt)) + (cond ((numberp elt) (setf sc-time (+ sc-time elt)) NIL) + (t (let ((ret-note (make-sc-note elt))) + (setf sc-time (+ sc-time sc-dur)) + ret-note))) + (case (car elt) + ((KEY TS CHN PATCH LM TN MRK NTR) NIL) ; filter out all these + ; for compatibility with lambda music + ((TF) (setf tf (calcula-dur (cadr elt))) NIL) + ((LABEL SET-MRK) (set-mrk (second elt)) NIL) + ((AT-LABEL AT-MRK) (set-time-mrk (second elt)) NIL) + ((TIME-IN-SECONDS) (setf tf 0.25) NIL) + ((DUR) (setdur (cdr elt)) NIL) + ((INSTRUMENT) (setinstr (cdr elt)) NIL) + ((INIT-INSTR) NIL) ;(init-instr (second elt)(third elt)) NIL) + ((ATTR) (set-attr (second elt) (calcula-dur (third elt))) NIL) + ((PWL-POINT) NIL) + ((FUN) (apply (eval (cadr elt)) (cddr elt))) + ((DELTA PAU) (setf sc-time (+ sc-time (calcula-dur (second elt)))) NIL) ; pause positive or negative + ((CH) (dolist (n (cdr elt)) (push (make-sc-note n) chords)) NIL) + ((CH1) (setf sc-dur (calcula-dur (third elt))) ; pitch dur + (make-sc-note (second elt))) + (t (setf sc-dur (calcula-dur (cadr elt))) + (let ((ret-note (make-sc-note (car elt)))) + (setf sc-time (+ sc-time sc-dur)) + ret-note)))))) + + ; first sets pwl data + (dolist (ev score-data NIL) + (proc-elt-for-pwl ev)) + + ; sort pwl data + (dolist (elt score-data NIL) + (when + (and (listp elt) (equal (car elt) 'INIT-INSTR)) + + (putprop (intern (second elt)) + (apply #'append (sdl:sort-pwl (symbol-plist (get (intern (second elt)) :pwl)))) + :pwl))) + + + ; then process score + + (setf sc-time 0.0) + + (do ((data score-data (cdr data)) + (result '())) + ((null data) (list (sort (mapcar #'(lambda (ev) (scale-score-time ev tf)) result) + #'(lambda (x y) (< (car x) (car y)))) time-marks)) + (let ((proced-elt (proc-elt (car data)))) + (when proced-elt (push proced-elt result))) + (setf result (append result chords)))))) + + +(defun sdl:get-key (l k) + (when l + (if (equal (car l) k) + (second l) + (sdl:get-key (cdr l) k)))) + + +(defun sdl:apply-mm-to-score (sco) + (let (current-time current-dur end-last-note gap current-mm result) + (setf current-mm (sdl:get-key (caddar sco) :mm)) + (setf current-time (* (/ 15.0 current-mm) (caar sco))) + (setf end-last-note (caar sco)) + (dolist (ev sco) + (setf gap (- (car ev) end-last-note)) + (setf end-last-note (+ (car ev) (second ev))) + (setf current-mm (sdl:get-key (caddr ev) :mm)) + (setf current-dur (* (/ 15.0 current-mm) (cadr ev))) + (push (list (+ current-time (* (/ 15.0 current-mm) gap)) current-dur (caddr ev)) result) + (setf current-time (+ current-time (* (/ 15.0 current-mm) gap) current-dur))) + (reverse result))) + + +(defun sdl:normalize-score-duration (sco) + (mapcar #'(lambda (ev) (list (car ev) 1 (third ev))) sco)) + + +; main functions interface ------- + +;(defun sdl->score (score-data &optional time-marks) +; (when (sdl:score-has-macros? score-data) +; (setf score-data (sdl:expand-macros score-data))) +; (car (sdl:sdl->score-aux score-data time-marks))) + +(defun sdl->score (score-data &optional time-marks) + (when (sdl:score-has-macros? score-data) + (setf score-data (sdl:expand-macros score-data))) + (sdl:apply-mm-to-score + (car (sdl:sdl->score-aux score-data time-marks)))) + +(defun sdl->timelabels (score-data &optional time-marks) + (when (sdl:score-has-macros? score-data) + (setf score-data (sdl:expand-macros score-data))) + (second (sdl:sdl->score-aux score-data time-marks))) + + +#| + +; PRUEBAS + + +(defun sdl-repeat (n quoted-event) + (let (result) + (dotimes (i n (apply #'append result)) + (push quoted-event result)))) + + +(setf *score* '((TF 1.0) + (INIT-INSTR "i1" xx)(INIT-INSTR "i2" yy) + (INSTRUMENT "i1")(ATTR :at1 2)(ATTR :mm 60) 4 (:e4 2) 2 (:d4 4) 10 (LABEL :t1) + (INSTRUMENT "i2") (ATTR :mm 60)(:f4 8) + (LABEL :vuelta) (AT-LABEL :t1) (:f5 4) + (AT-LABEL :vuelta) (:f6 8) +)) + + +(setf *score2* '((TF 1.0) + (INIT-INSTR "i1" xx2)(INSTRUMENT "i1")(ATTR :mm 60) + (AT-LABEL :t1) (:e4 4) (MAC sdl-repeat 4 (:f4 :g4)) )) + +;(print (sdl:apply-mm-to-score (car (sdl:sdl->score-aux *score*)))) +;(print (car (sdl:sdl->score-aux *score*))) + +(setf *tlabels* (sdl->timelabels *score*)) + +(print (sdl->score *score*)) +(print (sdl->score *score2* *tlabels*)) + +|# + + diff --git a/lib/soften.lsp b/lib/soften.lsp new file mode 100644 index 0000000..ad5c2ab --- /dev/null +++ b/lib/soften.lsp @@ -0,0 +1,45 @@ +;; soften.lsp -- this is code to "soften" harsh clipping +; +; it works by detecting peaks that exceed an absolute amplitude of 126/127 +; using SND-ONESHOT. Then the envelope is smoothed using SND-CHASE +; to produce a smooth cross-fade envelope. The envelope picks out the loud +; stuff to be filtered (try 4K) and an inverted envelope grabs the soft +; stuff which is unmodified except where the loud regions are clipped out. +; The sum of soft and filtered loud components is returned. +; +; Since clipping tends to generate harsh aliasing, the low-pass filter +; eliminates a lot of the problem, and the filter is usually on so +; briefly that you don't notice it. + +(defun square (x) (* x x)) + +;; region for low-pass will be *soften-width* wide, with +;; *soften-crossfade* seconds of cross-fade +(setf *soften-width* 0.02) +(setf *soften-crossfade* 0.002) + +(defun soften-clipping (snd cutoff) + (let (clip-region snd2 loud-stuff soft-stuff filtered-stuff) + (setf clip-region (snd-oneshot (prod snd snd) + (square (/ 126.0 127.0)) *soften-width*)) + (setf clip-region (snd-chase clip-region + *soften-crossfade* *soften-crossfade*)) + ; s-rest needs a sample rate: + (sound-srate-abs (snd-srate snd) + (setf snd2 (seq (s-rest (/ *soften-width* 2)) + (cue (scale 0.99 snd))) )) + (setf loud-stuff (prod snd2 clip-region)) + (setf soft-stuff (prod snd2 (sum 1 (scale -1 clip-region)))) + (setf filtered-stuff (lp loud-stuff cutoff)) + ; (vector filtered-stuff loud-stuff) + (sum filtered-stuff soft-stuff) + )) + + +;(defun tes () +; (sound-off) +; (let (snd) +; (setf snd (s-read "..\\..\\intro.aif")) +; (s-save (soften-clipping snd 4000) ny:all "temp.wav" :bits 16))) + +; (tes) diff --git a/lib/spatial.lsp b/lib/spatial.lsp new file mode 100644 index 0000000..bef95da --- /dev/null +++ b/lib/spatial.lsp @@ -0,0 +1,506 @@ +; SPATIAL.LSP +; created by Adam Hartman and Roger B. Dannenberg +; 2005 +; stereo manipulation and spatialization functions + +; EMPHIGH -- use four equalizer bands to emphasize +; the higher frequencies in an input sound +; +(defun emphigh (base) + (eq-band + (eq-band + (eq-band + (eq-band base 31 -3 1) + 62 -3 1) + 8000 3 1) + 16000 3 1)) + +; EMPLOW -- use four equalizer bands to emphasize +; the lower frequencies in an input sound +; +(defun emplow (base) + (eq-band + (eq-band + (eq-band + (eq-band base 31 3 1) + 62 3 1) + 8000 -3 1) + 16000 -3 1)) + +; LEFTIN -- apply low frequency emphasis to a sound +(defun leftin (inl) (emplow inl)) + +; RIGHTIN - apply high frequency emphasis and +; a very slight delay to a sound +; +(defun rightin (inr) (seq (s-rest 0.02) (emphigh inr))) + +; STEREOIZE -- create a stereo sound from a monaural source +; +(defun stereoize (monoin) + (vector (leftin monoin) (rightin monoin))) + +; EXTRACTLEFT -- extract the left channel of a stereo sound +(defun extractleft (inl) (aref inl 0)) + +; EXTRACTRIGHT -- extract the right channel of a stereo sound +(defun extractright (inr) (aref inr 1)) + + +; WSUM -- weighted sum of two monaural sounds +; +; inl: first monaural sound +; inr: second monaural sound +; amtl: multiplier for the first monaural sound +; amtr: multiplier for the second monaural sound +; +(defun wsum (inl inr amtl amtr) + (sum (mult inl amtl) (mult inr amtr))) + + +; SMIXER -- remix a stereo signal +; +; in: original stereo sound +; lamtl: amount in new left channel from the original left channel +; lamtr: amount in new left channel from the original right channel +; ramtl: amount in new right channel from the original left channel +; ramtr: amount in new right channel from the original right channel +; Note: lamtl, lamtr, ramtl, ramtr should have values in the +; range of -1 to 1 and may be static numbers or sounds +; +(defun smixer (in lamtl lamtr ramtl ramtr) + (let ((eleft (extractleft in)) (eright (extractright in))) + (vector (wsum eleft eright lamtl lamtr) + (wsum eleft eright ramtl ramtr)))) + + +; WIDEN -- widen the field of a stereo sound +; +; in: original stereo sound +; amt: a value between 0 and 1 which represents a widening factor +; 0 will leave the sound unchanged while 1 indicates the widest +; possible stereo field +; Note: amt may be a static number or a sound +; +(defun widen (in amt) + (let ((widenamt (mult -1 amt))) + (smixer in 1 widenamt widenamt 1))) + +; SPAN -- pan the virtual center channel of a stereo sound +; +; in: original stereo sound +; amt: a value between 0 and 1 which represents the panning location +; 0 pans the center channel all the way to the left while 1 pans +; it all the way to the right +; Note: amt may be a static number or a sound +; +(defun span (in amt) + (let ((leftc (sum 0.5 (mult -1 amt))) (rightc (sum -0.5 amt))) + (smixer in 0.5 leftc rightc 0.5))) + +; SWAPCHANNELS -- swap the two channels in a stereo sound +(defun swapchannels (in) (vector (aref in 1) (aref in 0))) + +#| NOTE: there's nothing wrong with the code that is commented out here. +These functions were in the original library, but I have commented them +out because they are very simple and not very general. Perhaps they +can be incorporated in an expanded form in a future version of Nyquist. +For example, some general 3-D positioning with Doppler effects, etc., +and some more elaborate HRTF code would be very interesting. Feel free +to give these a try. -RBD + +; IID -- position a monaural sound source by attenuating the volume +; of the sound at each ear point based on the distance between the +; two ear points and the distance of the sound source from the listener +; +; in: monaural source sound +; dist: lateral distance of the sound source from the listener in meters +; headwidth: width of the listener's head (i.e. the distance between +; the two ears) in meters +; rorl: a value of either 0 or 1 which represents whether the sound +; source is to the left or to the right of the listener +; +(defun iid (in dist headWidth RorL) + (let ((nearmult (/ 1.0 (mult dist dist))) + (farmult (/ 1.0 (mult (sum dist headWidth) + (sum dist headWidth))))) + (if (eq rorl 0) + ; sound source is to the left of listener + (vector (mult in nearmult) (mult in farmult)) + ; sound source is to the right of listener + (vector (mult in farmult) (mult in nearmult))))) + +; ITD -- position a monaural sound source by delaying the arrival +; of the sound at each ear point based on the distance +; between the two ear points and the distance of the sound +; source from the listener +; in: monaural source sound +; dist: lateral distance of the sound source from the listener in meters +; headwidth: width of the listener's head (i.e. the distance +; between the two ears) in meters +; rorl: a value of either 0 or 1 which represents whether the sound +; source is to the left or to the right of the listener +; +(defun itd (in dist headWidth RorL) + (let ((neardel (mult 0.0029387 dist)) + (fardel (mult 0.0029387 (sum dist headWidth)))) + (if (eq rorl 0) + ; sound source is to the left of listener + (vector (seq (s-rest neardel) in ) (seq (s-rest fardel) in)) + ; sound source is to the right of listener + (vector (seq (s-rest fardel) in) (seq (s-rest neardel) in))))) + + +; CFSPATIALIZATION -- a spatialization effect based on a cross-feed network +; +(defun cfspatialization (in) + (let ((shadowLeft (lp (seq (s-rest 0.0004) (aref in 0)) 265)) + (shadowRight (lp (seq (s-rest 0.0004) (aref in 1)) 265))) + (vector (sum (aref in 0) shadowRight) (sum (aref in 1) shadowLeft)))) + +; CUSTBP -- a helper function that creates a custom bandpass filter +; for use in the hrtfapprox function +(defun custbp (in) (lp (sum (hp in 4980) (mult in 0.75)) 7900)) + +; HRTFAPPROX -- a spatialization effect based on an approximated HRTF +; +(defun hrtfapprox (in) + (let ((filteredLeft (seq (s-rest 0.00025) (custbp (aref in 0)))) + (filteredRight (seq (s-rest 0.00025) (custbp (aref in 1))))) + (vector (sum (aref in 0) (lp filteredRight 10200)) + (sum (aref in 0) (lp filteredLeft 1020))))) +|# + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Dolby Pro-Logic encoding and a +;; 2D Sound Positioning Scheme +;; +;; Dave Borel (dborel) with minor changes by +;; Roger B. Dannenberg +;; +;; Features: +;; -Dolby Pro-Logic panning +;; -Doppler for moving sounds +;; -Distance attenuation +;; -Atmospheric damping of high frequencies +;; -Progagation delay +;; -Test programs + +(setf config 1) ;Distance between listener and speakers + +;--------------------------------------------------- +; Math Helpers +;--------------------------------------------------- + +; +; Distance between two points +; +(defun dist (x0 y0 x1 y1) + (let* ( (rx (sum x1 (mult -1.0 x0))) + (ry (sum y1 (mult -1.0 y0))) ) + (s-sqrt (sum (mult rx rx) (mult ry ry))))) + +; +; Raise x to each sample of snd +; +(defun s-expt (x snd) + (s-exp (mult (s-log x) snd))) + + +;; +;; SPATIALIZATION HELPERS: +;; + +; +; Doppler effect +; +(defun pl-doppler (snd r) + (let* ( (v (mult -1 (slope r))) + (ratio (recip (sum 1 (mult v (recip 344.31))))) + (map (integrate ratio)) ) + + (sound-warp map snd) )) + + +; +; Distance-based low-pass filter +; (see report) +; +(defun absorb (snd r-m) + (lp snd (mult 14763.67 (s-expt 0.97895 r-m)))) + + +; +; Distance-based attenuation +; (see report) +; +(defun atten (snd r) + +; (let* ( (log2-r (mult (s-log r) (recip (log 10.0)))) +; (db-ratio (mult 20 log2-r)) +; (ratio (db-to-linear db-ratio)) ) +; +; (mult (clip ratio 1.0) snd))) + (mult snd (clip (recip (mult r r)) 1))) + +; +; Top-level spatializer +; sound source at (x,y) +; speaker at (xs, ys) +; assumes listener at (0,0) +; +; You could use this with +; configurations other than +; pro-logic (e.g. 6.1, 7.1, etc) +; +(defun stage (snd x y xs ys) + (let* ( (r (dist x y 0 0)) + (rs (dist xs ys 0 0)) + (x-hat (mult x (recip r))) + (y-hat (mult y (recip r))) + (xs-hat (mult xs (recip rs))) + (ys-hat (mult ys (recip rs))) + + (dot (sum (mult x-hat xs-hat) (mult y-hat ys-hat))) + (overlap (mult 0.5 (sum dot (s-abs dot)))) ) + (mult overlap snd))) + + +;--------------------------------------------------- +; Speaker Mixing +;--------------------------------------------------- +; +; Dolby Pro-Logic Encoder +; +(defun prologic (left center right surround) + (let* ( (c (scale 0.5 center)) + (s (highpass2 (lowpass2 (scale 0.5 surround) 7000) 100) ) + (slfe (scale 0.25 (lp surround 100))) + (l (sim left center (mult -1.0 s) slfe)) + (r (sim right center s slfe)) ) + (vector l r))) + + +; +; Direct-to-speaker playback +; +(defun pl-left (snd) (let ((s (mult 0 snd))) (prologic snd s s s))) +(defun pl-center (snd) (let ((s (mult 0 snd))) (prologic s snd s s))) +(defun pl-right (snd) (let ((s (mult 0 snd))) (prologic s s snd s))) +(defun pl-rear (snd) (let ((s (mult 0 snd))) (prologic s s s snd))) + +; +; Pans a sound across the surround speakers +; (no realistic imaging or attenuation) +; Works like pan but y specifies depth +(defun pl-pan2d (s-in x y) + (let ((snd (scale 0.5 s-in))) + (prologic (mult snd (sum 1.0 (mult -1.0 x) + (sum 1 (mult -1.0 y))) );left + (mult snd 0.0) ;center(null) + (mult snd x (sum 1.0 (mult -1.0 y) )) ;right + (mult snd y 0.5)))) ;rear + +; +; Position a sound in the 2D soundstage +; Includes spatialization effects +; +; (x,y) may be (flonum, flonum) or (behavior, behavior) +; +(defun pl-position (s-in x y config) + (let* ( (r-m (dist x y 0 0)) + (r (mult r-m (recip config))) + (spd-snd (/ 344.31 config)) + (offset (if (soundp r-m) + (/ (aref (snd-samples r 1) 0) spd-snd) + (/ r spd-snd))) + (snd (seq (s-rest offset) + (if (soundp r-m) + (atten (absorb (pl-doppler s-in r-m) r-m) r) + (atten (absorb s-in r-m) r)))) ) + + ; Two Notes: + ; 1.) The center channel is automatically imaged correctly + ; because sounds placed between the left-and-right channels + ; distribute linearly between the two channels. + ; + ; 2.) Although the below settings assume that all speakers are + ; equidistant from the listener, you can easily assume a + ; different layout by modifying the xs and ys values in + ; each channel's call to the stage function. + ; + (prologic (stage snd x y -.1913 -.4619) ;left + (scale 0.0 snd) ;center (null) + (stage snd x y .1913 -.4619) ;right + (stage snd x y 0.0 .5 )))) ;rear + + +;--------------------------------------------------- +; Diagnostics +;--------------------------------------------------- + +; +; Pro-Logic Channel Test Tones +; +(defun pl-test () + (play (prologic + ( osc-note a3 ) + (seq (s-rest 1.25) (osc-note b3)) + (seq (s-rest 2.5 ) (osc-note c4)) + (seq (s-rest 3.75) (osc-note d4)) ))) + + +; +; Pan Test +; +(defun pan-test () + (play (pl-pan2d + (seq + (s-rest .25) (osc a3 .75) + (s-rest .25) (osc b3 .75) + (s-rest .25) (osc c4 .75) + (s-rest .25) (osc d4 .75)) + + (pwl + 0 0 + 0.99 0 + + 1 1 + 2.99 1 + + 3 0 + 4 0 + 4 ) + + (pwl + 0 0 + 1.99 0 + + 2 1 + 4 1 + 4 )))) + + +; +; Doppler test +; +(defun dop () + (play (pl-doppler (osc c4 10) (pwl .25 0 .5 100 .75 100 1.0)))) + +; +; Attenuation test +; +(defun att () + (play (atten (osc-note c4 4) + (pwl 0 2 + 1 2 + 2 100 + 3 100 + 4 2 + 4 )))) + + +; +; Doppler positioning test (ambulance) +; +(defun ambulance () + (play (scale 0.2 + (pl-position + + (stretch 16 (fmosc c4 (mult 1000 (lfo 2)))) + + (pwl + 0 -20 + 8 20 + 8 ) + + (pwl + 0 0 + 8 ) + + config)))) + + +; +; Position test +; + +; Make a sound orbit the listener +(defun orbit-x (r t times) + (let (k) + (seqrep (k times) + (pwl + 0.0 0.0 + (/ t 4) r + (/ t 2) 0.0 + (/ (* t 3) 4) (* -1 r) + t 0.0 + t ) ))) +(defun orbit-y (r t times) + (let (k) + (seqrep (k times) + (pwl + 0.0 (* -1 r) + (/ t 4.0) 0.0 + (/ t 2.0) r + (/ (* t 3.0)4.0) 0.0 + t (* -1 r) + t ) ))) +(defun orbit (snd r t times) + (pl-position snd + (orbit-x r t times) + (orbit-y r t times) + config)) + + +; Play some tones +(defun pos-1 () + (play (pl-position + (seq + (s-rest .125) (osc a3 1.75) + (s-rest .25) (osc b3 1.75) + (s-rest .25) (osc c4 1.75) + (s-rest .25) (osc d4 1.75) (s-rest .125)) + + (pwl + 0 -5 + 1 5 + 2 5 + 3 -5 + 4 -5 + 5 5 + 6 5 + 7 -5 + 8 -5 + 8 ) + + (pwl + 0 -5 + 1 -5 + 2 5 + 3 5 + 4 -5 + 5 -5 + 6 5 + 7 5 + 8 -5 + 8 ) + + config))) + +(defun pos-2 () + (play (seq + (orbit (seq + (s-rest .125) (osc a3 1.75) + (s-rest .25) (osc b3 1.75) + (s-rest .25) (osc c4 1.75) + (s-rest .25) (osc d4 1.75) (s-rest .125)) + + 5 8 1) + (orbit (seq + (s-rest .125) (osc a3 1.75) + (s-rest .25) (osc b3 1.75) + (s-rest .25) (osc c4 1.75) + (s-rest .25) (osc d4 1.75) (s-rest .125)) + + 5 8 1)))) diff --git a/lib/spectrum.lsp b/lib/spectrum.lsp new file mode 100644 index 0000000..668c310 --- /dev/null +++ b/lib/spectrum.lsp @@ -0,0 +1,135 @@ +;; spectrum.lsp -- operations on spectral frames + +(defun raised-cosine () + (scale 0.5 + (sum (const 1) + (lfo (/ 1.0 (get-duration 1)) 1 *sine-table* 270)))) + +(defun fft-window (frame-size) + (control-srate-abs frame-size (raised-cosine))) + +;; fft-class -- an iterator converting sound to sequence of frames +;; +(setf fft-class (send class :new '(sound length skip window))) + +(send fft-class :answer :next '() '( + (snd-fft sound length skip window))) + +(send fft-class :answer :isnew '(snd len skp) '( + (setf sound snd) + (setf length len) + (setf skip skp) + (setf window (fft-window len)) )) + + +(defun make-fft-iterator (sound length skip) + (send fft-class :new (snd-copy sound) length skip)) + + +;; conversions -- assumes frame length is even + +(defun spectrum-to-amplitude (frame) + (let* ((n (length frame)) + (half-n (/ n 2)) + (amps (make-array (1+ half-n)))) + (setf (aref amps 0) (abs (aref frame 0))) + (dotimes (i (1- half-n)) + (let* ((i2 (+ i i)) + (c (aref frame (1+ i2))) + (s (aref frame (+ 2 i2)))) + (setf (aref amps (1+ i)) + (sqrt (+ (* c c) (* s s)))))) + (setf (aref amps half-n) (abs (aref frame (1- n)))) + amps)) + +(defun spectrum-by-amplitude (frame amps) + (let* ((n (length frame)) + (half-n (/ n 2))) + (setf (aref frame 0) (* (aref frame 0) (aref amps 0))) + (dotimes (i (1- half-n)) + (let* ((ip1 (1+ i)) + (i2 (+ i i)) + (i2p1 (1+ i2)) + (i2p2 (1+ i2p1))) + (setf (aref frame i2p1) (* (aref frame i2p1) + (aref amps ip1))) + (setf (aref frame i2p2) (* (aref frame i2p2) + (aref amps ip1))))) + (setf (aref frame (1- n)) (* (aref frame (1- n)) + (aref amps half-n))))) + + +(defun spectrum-rms (frame) + (let* ((n (length frame)) + (half-n (/ n 2)) + (sum (* (aref frame 0) (aref frame 0)))) + (dotimes (i (1- half-n)) + (let* ((i2 (+ i i)) + (c (aref frame (1+ i2))) + (s (aref frame (+ 2 i2)))) + (setf sum (+ sum (* c c) (* s s))))) + (setf sum (+ sum (* (aref frame (1- n)) (aref frame (1- n))))) + (sqrt sum))) + + +(defun amplitude-rms (frame) + (let* ((n (length frame)) + (sum 0)) + (dotimes (i n) + (setf sum (+ sum (* (aref frame i) (aref frame i))))) + (sqrt sum))) + +;; SMOOTH-AMPLITUDE -- simple local averaging to smooth out +;; an amplitude spectrum. This might be useful to broaden +;; spectral peaks from partials to better represent vocal +;; formants. It would be nice to have a "width" parameter, +;; but instead, the filter is fixed at (0.25, .5, 0.25) +;; +(defun smooth-amplitude (frame) + (let* ((len (length frame)) + (lenm1 (1- len)) + (lenm2 (1- lenm1)) + (rslt (make-array (length frame)))) + (setf (aref rslt 0) (+ (* 0.75 (aref frame 0)) + (* 0.25 (aref frame 1)))) + (dotimes (i lenm2) + (let* ((ip1 (1+ i)) + (ip2 (1+ ip1))) + (setf (aref rslt ip1) (+ (* 0.25 (aref frame i)) + (* 0.5 (aref frame ip1)) + (* 0.25 (aref frame ip2)))))) + (setf (aref rslt lenm1) (+ (* 0.25 (aref frame lenm2)) + (* 0.75 (aref frame lenm1)))) + rslt)) + +;; ARRAY-SCALE -- multiply a spectral frame or amplitude frame +;; by a scale factor +;; +(defun array-scale (frame x) + (dotimes (i (length frame)) + (setf (aref frame i) (* (aref frame i) x)))) + + +(defun array-copy (frame) + (let* ((len (length frame)) + (copy (make-array len))) + (dotimes (i len) + (setf (aref copy i) (aref frame i))) + copy)) + + + + +(defun amplitude-plot (frame) + (s-plot (snd-from-array 0 + (/ (float (1- (length frame))) + *default-sound-srate*) + frame))) + + +(defun spectrum-plot (frame) + (amplitude-plot (spectrum-to-amplitude frame))) + + +(defun spectrum-ifft (iterator len skip) + (snd-ifft (local-to-global 0.0) *sound-srate* iterator skip (fft-window len))) diff --git a/lib/statistics.lsp b/lib/statistics.lsp new file mode 100644 index 0000000..b805351 --- /dev/null +++ b/lib/statistics.lsp @@ -0,0 +1,428 @@ +;; statistics.lsp -- simple statistics functions + +;; to compute statistics, create an object: +;; (setf stats (send statistics-class :new t)) +;; use t to retain the data and nil to not retain the data +;; then call (send stats :point x) for each x in the data set +;; call (send stats :print-stats) to print some statistics +;; see methods below for other methods, e.g. :get-mean +;; +;; to compute histograms, see comments below + +(setf statistics-class (send class :new '(count sum sum-sqr max min retain data))) + +(send statistics-class :answer :isnew '(ret) '((send self :init ret))) + +(send statistics-class :answer :init '(ret) '( + (setf count 0 sum 0 sum-sqr 0 data nil + max nil min nil retain ret data nil))) + +(send statistics-class :answer :point '(x) '( + (incf count) + (setf sum (+ sum x)) + (setf sum-sqr (+ sum-sqr (* x x))) + (setf max (if max (max max x) x)) + (setf min (if min (min min x) x)) + (if retain (push x data)))) + +(send statistics-class :answer :get-count '() '(count)) +(send statistics-class :answer :get-data '() '(data)) +(send statistics-class :answer :get-min '() '(min)) +(send statistics-class :answer :get-max '() '(max)) + +(send statistics-class :answer :get-mean '() '( + (if (> count 0) (/ (float sum) count) + nil))) + + +(send statistics-class :answer :get-stddev '() '( + (if (> count 1) (sqrt (send self :get-variance)) nil))) + + +(send statistics-class :answer :get-variance '() '( + (if (> count 1) + (/ (- sum-sqr + (/ (* sum sum) (float count))) + (1- count)) + nil))) + + +(send statistics-class :answer :print-stats '() '( + (format t "Number of points: ~A~%Max: ~A~%Min: ~A~%" count max min) + (if retain + (format t "Median: ~A~%" (send self :get-median))) + (format t "Mean: ~A~%Std.Dev.: ~A~%" + (send self :get-mean) (send self :get-stddev)) + )) + + +(send statistics-class :answer :get-data '() '(data)) + + +(send statistics-class :answer :get-median '() '( + (let (i) + (cond ((not retain) nil) ;; no data retained to examine + ((< count 1) nil) ;; no data to compute from + (t + (setf data (bigsort data '<)) + (cond ((oddp count) + (nth (/ count 2) data)) + (t + (setf i (/ count 2)) + (* 0.5 (+ (nth i data) (nth (1- i) data)))))))))) + +;; This is the "usual estimator of the population kurtosis" based +;; on Wikipedia. In order for this to work, the statistics object +;; must be initialized to *retain* the data +;; +(send statistics-class :answer :get-kurtosis '() '( + (let ((x4 0) x2 + (n (float count)) ; "n" is just a new name for count + (mean (send self :get-mean)) + (variance (send self :get-variance))) + (dolist (x data) + (setf x2 (* (- x mean) (- x mean))) + (setf x4 (+ x4 (* x2 x2)))) + (display "kurtosis" x4 (* variance variance) n) + (if (> n 3) + (- (* (/ (* (1+ n) n) + (* (1- n) (- n 2) (- n 3))) + (/ x4 (* variance variance))) + (/ (* 3 (1- n) (1- n)) + (* (- n 2) (- n 3)))) + nil)))) + +;; :FRACTION-IN-RANGE -- proportion of values in a range +;; +(send statistics-class :answer :fraction-in-range '(low high) '( + (let ((n 0)) + (dolist (d data) + (if (and (<= low d) (< d high)) (setf n (1+ n)))) + (/ (float n) count)))) + + +;; The histogram-class. Make a histogram from data. +;; +;; To use histogram-class, first make an instance: +;; (setf my-histogram (send histogram-class :new)) +;; Then add points to the histogram. For each point x: +;; (send my-histogram :point x) +;; You can make a default histogram by calling: +;; (send my-histogram :configure-bins) +;; This will create the square root of N bins where N is the +;; number of points. The bins are evenly distributed across +;; the range of the data. +;; Alternatively, you can provide your own thresholds to +;; determine the bins by calling: +;; (send my-histogram :set-thresholds an-array) +;; Each element of an-array represents the lower bound for +;; elements in that bin. E.g. if x is a point, it goes in +;; bin 3 if (aref an-array 3) <= x < (aref an-array 4) +;; Note that nothing goes into bin L-1 where L is the length +;; of an-array. +;; To actually compute the histogram, call +;; (send my-histogram :make-hist) +;; And then you can print or plot it with: +;; (send my-histogram :print-hist) or +;; (send my-histogram :plot-hist) +;; You can change the thresholds with :set-thresholds or +;; :configure-bins without re-inserting all the points. +;; You can start over by calling +;; (send my-histogram :init) +;; but this probably has no advantage over making a new +;; instance. + +(setf histogram-class (send class :new '(stats counts thresholds))) + +(send histogram-class :answer :isnew '() '((send self :init))) + +(send histogram-class :answer :init '() '( + (setf counts nil thresholds nil) + ; create stats object and tell it to retain points + (setf stats (send statistics-class :new t)))) + +(send histogram-class :answer :point '(x) '( + (send stats :point x))) + +(send histogram-class :answer :configure-bins '() '( + (let* ((nbins (round (sqrt (float (send stats :get-count))))) + (minthreshold (send stats :get-min)) + (step (/ (- (send stats :get-max) (send stats :get-min)) nbins))) + (setf thresholds (make-array (1+ nbins))) + (dotimes (i (1+ nbins)) + (setf (aref thresholds i) (+ minthreshold (* i step))))) + thresholds)) + +(send histogram-class :answer :set-thresholds '(array) '( + (setf counts nil) + (setf thresholds array))) + + +(send histogram-class :answer :make-hist '(&key (verbose t)) '( + (let* ((data (send stats :get-data)) + (counter 0) (data-position 0)) + (if (null thresholds) + (send self :configure-bins)) + (cond ((null counts) + (setf counts (make-array (1- (length thresholds)))) + (dotimes (i (length counts)) + (setf (aref counts i) 0)))) + (dolist (x data) + (cond ((and verbose (> counter 100000)) + (format t "make-hist ~A% done\n" + (* 100 + (/ data-position (float (send stats :get-count))))) + (setf counter 0))) + ; increment the right bin -- allows different bin sizes but + ; could use a binary search for the right bin + (dotimes (i (length counts)) + (incf counter) + (cond ((and (< x (aref thresholds (1+ i))) + (>= x (aref thresholds i))) + (incf (aref counts i)) + (return)))) + (incf data-position)) ))) + + +(send histogram-class :answer :print-hist '() '( + (if (null counts) (send self :make-hist)) + (dotimes (i (length counts)) + (format t "~A to ~A: ~A~%" + (aref thresholds i) (aref thresholds (1+ i)) + (aref counts i))))) + +(send histogram-class :answer :plot-hist '(&optional (offset 0)) '( + (if (null counts) (send self :make-hist)) + (s-plot (snd-from-array 0 + (/ (- (aref thresholds 1) + (aref thresholds 0))) + counts)))) + +(send histogram-class :answer :get-min '() '( + (send stats :get-min))) + +(send histogram-class :answer :get-max '() '( + (send stats :get-max))) + +(send histogram-class :answer :get-count '() '( + (send stats :get-count))) + +(send histogram-class :answer :get-counts '() '( + counts)) + +(send histogram-class :answer :get-thresholds '() '( + thresholds)) + + +;; Pearson correlation - direct (unstable) algorithm +;; +;; I created this to get the "true" answer when I was trying to +;; debug the more complex version below. All three algorithms here +;; now agree (within numerical roundoff), and I believe the +;; pearson-class below is the best implementation. -RBD +;; +;(setf upearson-class (send class :new '(sumxy sumx sumy sumxx sumyy n))) +; +;(send upearson-class :answer :isnew '() '((send self :init))) +;(send upearson-class :answer :init '() '( +; (setf sumxy 0 sumx 0 sumy 0 sumxx 0 sumyy 0 n 0))) +;(send upearson-class :answer :points '(x y) '( +; (setf sumxy (+ sumxy (* x y))) +; (setf sumx (+ sumx x)) +; (setf sumy (+ sumy y)) +; (setf sumxx (+ sumxx (* x x))) +; (setf sumyy (+ sumyy (* y y))) +; (setf n (+ n 1)))) +;(send upearson-class :answer :correlation '() '( +; (/ (- (* n sumxy) (* sumx sumy)) +; (* (sqrt (- (* n sumxx) (* sumx sumx))) +; (sqrt (- (* n sumyy) (* sumy sumy))))))) + +;; Pearson correlation +;; +(setf pearson-class (send class :new '(sum-sq-x sum-sq-y sum-coproduct + mean-x mean-y n))) +(send pearson-class :answer :isnew '() '((send self :init))) +(send pearson-class :answer :init '() '( + (setf n 0) + (setf sum-sq-x 0 sum-sq-y 0 sum-coproduct 0))) + +(send pearson-class :answer :points '(x y) '( + (cond ((zerop n) + (setf mean-x x mean-y y n 1)) + (t + (setf n (1+ n)) + (let* ((sweep (/ (- n 1.0) n)) + (delta-x (- x mean-x)) + (delta-y (- y mean-y))) + (setf sum-sq-x (+ sum-sq-x (* delta-x delta-x sweep))) + (setf sum-sq-y (+ sum-sq-y (* delta-y delta-y sweep))) + (setf sum-coproduct (+ sum-coproduct (* delta-x delta-y sweep))) + (setf mean-x (+ mean-x (/ delta-x n))) + (setf mean-y (+ mean-y (/ delta-y n)))))))) + +(send pearson-class :answer :correlation '() '( + (let* ((pop-sd-x (sqrt (/ sum-sq-x n))) + (pop-sd-y (sqrt (/ sum-sq-y n))) + (cov-x-y (/ sum-coproduct n))) + (/ cov-x-y (* pop-sd-x pop-sd-y))))) + +;; This is a very direct implementation of the algorithm below, +;; but it stores the points -- I created this for debugging but +;; I don't see any reason to use it now. -RBD +;(setf npearson-class (send class :new '(pts))) +;(send npearson-class :answer :isnew '() '((send self :init))) +;(send npearson-class :answer :init '() '((setf pts nil))) +;(send npearson-class :answer :points '(x y) '( +; (setf pts (cons (cons x y) pts)))) +;(send npearson-class :answer :correlation '() '( +; (setf pts (reverse pts)) +; (let ((sum-sq-x 0) (sum-sq-y 0) (sum-coproduct 0) (mean-x (caar pts)) +; (mean-y (cdar pts)) i (n (length pts))) +; (dotimes (j (1- n)) +; (let* ((i (+ j 2)) +; (sweep (/ (- i 1.0) i)) +; (delta-x (- (car (nth (1- i) pts)) mean-x)) +; (delta-y (- (cdr (nth (1- i) pts)) mean-y))) +; (setf sum-sq-x (+ sum-sq-x (* delta-x delta-x sweep))) +; (setf sum-sq-y (+ sum-sq-y (* delta-y delta-y sweep))) +; (setf sum-coproduct (+ sum-coproduct (* delta-x delta-y sweep))) +; (setf mean-x (+ mean-x (/ delta-x i))) +; (setf mean-y (+ mean-y (/ delta-y i))))) +; (let ((pop-sd-x (sqrt (/ sum-sq-x n))) +; (pop-sd-y (sqrt (/ sum-sq-y n))) +; (cov-x-y (/ sum-coproduct n))) +; (/ cov-x-y (* pop-sd-x pop-sd-y)))))) + +;; the algorithm (from Wikipedia) +;sum_sq_x = 0 +;sum_sq_y = 0 +;sum_coproduct = 0 +;mean_x = x[1] +;mean_y = y[1] +;for i in 2 to N: +; sweep = (i - 1.0) / i +; delta_x = x[i] - mean_x +; delta_y = y[i] - mean_y +; sum_sq_x += delta_x * delta_x * sweep +; sum_sq_y += delta_y * delta_y * sweep +; sum_coproduct += delta_x * delta_y * sweep +; mean_x += delta_x / i +; mean_y += delta_y / i +;pop_sd_x = sqrt( sum_sq_x / N ) +;pop_sd_y = sqrt( sum_sq_y / N ) +;cov_x_y = sum_coproduct / N +;correlation = cov_x_y / (pop_sd_x * pop_sd_y) + +;; Welch's t-test to test the null hypothesis that 2 population means are +;; equal when the variances might be unequal +;; +;; returns list: (welchs-t degrees-of-freedom) +;; +(defun welchs-t-test (mean1 stddev1 n1 mean2 stddev2 n2) + (let* ((var1 (* stddev1 stddev1)) + (var2 (* stddev2 stddev2)) + (num (- mean1 mean2)) + (den (sqrt (+ (/ var1 n1) + (/ var2 n2)))) + (welchs-t (/ num den)) + (dof-a (+ (/ var1 n1) (/ var2 n2))) + (dof-num (* dof-a dof-a)) + (dof-den (+ (/ (* var1 var1) (* n1 n1 (- n1 1))) + (/ (* var2 var2) (* n2 n2 (- n2 1))))) + (dof (/ dof-num dof-den))) + (list welchs-t dof))) + +;; Levene's test to assess the equality of variances in different samples +;; based on Wikipedia article. This implementation is for 2 groups. If the +;; 2 groups can be assumed to be normal (Gaussian), then the F-test should +;; be considered. +;; +;; A variation on Levene's test is the Brown-Forsythe test, which uses +;; medians instead of means. The optional parameter, brown-forsythe can +;; be set to true to get a Browne-Forsythe test instead of Levene's test. +;; +;; The verbose flag defaults to t and prints some useful information +;; +;; The input to levenes-test is a pair of lists of samples. The return +;; value is W (see Wikipedia for details) +;; +(defun levenes-test (y1 y2 &optional brown-forsythe (verbose t)) + (let* ((n1 (float (length y1))) + (n2 (float (length y2))) + (n (+ n1 n2)) + m1 m2 z1 z2 z.. z1. z2. stat (den 0) w) + ;; compute means or medians + (cond (brown-forsythe + (setf m1 (vector-median y1)) + (setf m2 (vector-median y2))) + (t + (setf m1 (vector-mean y1)) + (setf m2 (vector-mean y2)))) + ;; compute zij (lists z1 and z2) + (dolist (y1j y1) (push (abs (- y1j m1)) z1)) + (dolist (y2j y2) (push (abs (- y2j m2)) z2)) + + ;; compute zi. sums + (setf z1. (vector-sum-elements z1)) + (setf z2. (vector-sum-elements z2)) + + ;; compute z.. + (setf z.. (/ (+ z1. z2.) n)) + + ;; convert zi. variables from sums to means + (setf z1. (/ z1. n1)) + (setf z2. (/ z2. n2)) + + ;; compute the big denominator term + (dolist (z1j z1) + (let ((diff (- z1j z1.))) + (setf den (+ den (* diff diff))))) + (dolist (z2j z2) + (let ((diff (- z2j z2.))) + (setf den (+ den (* diff diff))))) + + ;; compute w + (setf w (* (- n 2) (/ (+ (* n1 (* (- z1. z..) (- z1. z..))) + (* n2 (* (- z2. z..) (- z2. z..)))) + den))) + ;; print info if verbose + (cond (verbose + (format t "Summary of ~A test results: + Size of group 1: ~A, ~A: ~A + Size of group 2: ~A, ~A: ~A + W (result): ~A + The significance of W is tested against F(alpha, 1, ~A), + where alpha is the level of significance (usually 0.05 or + 0.01), and ~A is N-2.~%" + (if brown-forsythe "Brown-Forsythe" "Levene's") + n1 (if brown-forsythe "Median" "Mean") m1 + n2 (if brown-forsythe "Median" "Mean") m2 + w + (- n 2) (- n 2)))) + w)) + + +;; a simple test for levenes-test +;; this program uses distributions.lsp, which must be explicitly loaded +;; +(defun levenes-test-test () + (let (y1 y2 y3) + ;; make some data with sigma 0.1 and 0.2 + (dotimes (i 50) + (push (gaussian-dist 1.0 0.1) y1)) + (dotimes (i 75) + (push (gaussian-dist 1.0 0.2) y2)) + (dotimes (i 75) + (push (gaussian-dist 1.0 0.1) y3)) + (format t "\nTHE FOLLOWING HAVE UNEQUAL VARIANCE\n") + (levenes-test y1 y2) ;; levene's test + (format t "\n") + (levenes-test y1 y2 t) ;; brown-forsythe test + (format t "\nTHE FOLLOWING HAVE EQUAL VARIANCE\n") + (levenes-test y1 y3) ;; levene's test + (format t "\n") + (levenes-test y1 y3 t) ;; brown-forsythe test + (format t "\n") + 'done + )) diff --git a/lib/surround.lsp b/lib/surround.lsp new file mode 100644 index 0000000..b4198f9 --- /dev/null +++ b/lib/surround.lsp @@ -0,0 +1,368 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; SURROUND.LSP -- Implements Dolby Pro-Logic encoding +; and a 2D Sound Positioning Scheme +;; +;; Dave Borel (dborel) with minor changes by +;; Roger B. Dannenberg +;; +;; Features: +;; -Dolby Pro-Logic panning +;; -Doppler for moving sounds +;; -Distance attenuation +;; -Atmospheric damping of high frequencies +;; -Progagation delay +;; -Test programs + +(setf config 1) ;Distance between listener and speakers + +;--------------------------------------------------- +; Math Helpers +;--------------------------------------------------- + +; +; Distance between two points +; +(defun dist (x0 y0 x1 y1) + (let* ( (rx (sum x1 (mult -1.0 x0))) + (ry (sum y1 (mult -1.0 y0))) ) + (s-sqrt (sum (mult rx rx) (mult ry ry))))) + +; +; Raise x to each sample of snd +; +(defun s-expt (x snd) + (s-exp (mult (s-log x) snd))) + + +;--------------------------------------------------- +; Signal Processing +;--------------------------------------------------- + +;; +;; DOLBY HELPERS: +;; + +; +; Smooth FFT Frame Iterator +; (Inspired by Dannenberg's fft example) +; +(defun raised-cosine () + (scale 0.5 + (sum (const 1) + (lfo (/ 1.0 (get-duration 1)) 1 *sine-table* 270)))) + +(defun fft-window (frame-size) + (control-srate-abs frame-size (raised-cosine))) + +(setf fft-class (send class :new '(sound length skip window))) + +(send fft-class :answer :next '() '( + (snd-fft sound length skip window))) + +(send fft-class :answer :isnew '(snd len skp) '( + (setf sound snd) + (setf length len) + (setf skip skp) + (setf window (fft-window len)) )) + +(defun make-fft-iterator (sound length skip) + (send fft-class :new (snd-copy sound) length skip)) + + +;; +;; SPATIALIZATION HELPERS: +;; + +; +; Doppler effect +; +(defun doppler (snd r) + (let* ( (v (mult -1 (slope r))) + (ratio (recip (sum 1 (mult v (recip 344.31))))) + (map (integrate ratio)) ) + + (sound-warp map snd) )) + + +; +; Distance-based low-pass filter +; (see report) +; +(defun absorb (snd r_m) + (lp snd (mult 14763.67 (s-expt 0.97895 r_m)))) + + +; +; Distance-based attenuation +; (see report) +; +(defun atten (snd r) + +; (let* ( (log2_r (mult (s-log r) (recip (log 10.0)))) +; (db_ratio (mult 20 log2_r)) +; (ratio (db-to-linear db_ratio)) ) +; +; (mult (clip ratio 1.0) snd))) + (mult snd (clip (recip (mult r r)) 1))) + +; +; Top-level spatializer +; sound source at (x,y) +; speaker at (xs, ys) +; assumes listener at (0,0) +; +; You could use this with +; configurations other than +; pro-logic (e.g. 6.1, 7.1, etc) +; +(defun stage (snd x y xs ys) + (let* ( (r (dist x y 0 0)) + (rs (dist xs ys 0 0)) + (x_hat (mult x (recip r))) + (y_hat (mult y (recip r))) + (xs_hat (mult xs (recip rs))) + (ys_hat (mult ys (recip rs))) + + (dot (sum (mult x_hat xs_hat) (mult y_hat ys_hat))) + (overlap (mult 0.5 (sum dot (s-abs dot)))) ) + (mult overlap snd))) + + +;--------------------------------------------------- +; Speaker Mixing +;--------------------------------------------------- +; +; Dolby Pro-Logic Encoder +; +(defun prologic (left center right surround) + (let* ( (c (scale 0.5 center)) + (s (highpass2 (lowpass2 (scale 0.5 surround) 7000) 100) ) + (slfe (scale 0.25 (lp surround 100))) + (l (sim left center (mult -1.0 s) slfe)) + (r (sim right center s slfe)) ) + (vector l r))) + + +; +; Direct-to-speaker playback +; +(defun pl_left (snd) (let ((s (mult 0 snd))) (prologic snd s s s))) +(defun pl_center (snd) (let ((s (mult 0 snd))) (prologic s snd s s))) +(defun pl_right (snd) (let ((s (mult 0 snd))) (prologic s s snd s))) +(defun pl_rear (snd) (let ((s (mult 0 snd))) (prologic s s s snd))) + +; +; Pans a sound across the surround speakers +; (no realistic imaging or attenuation) +; Works like pan but y specifies depth +(defun pan2d (s_in x y) + (let ((snd (scale 0.5 s_in))) + (prologic (mult snd (sum 1.0 (mult -1.0 x) + (sum 1 (mult -1.0 y))) );left + (mult snd 0.0) ;center(null) + (mult snd x (sum 1.0 (mult -1.0 y) )) ;right + (mult snd y 0.5)))) ;rear + +; +; Position a sound in the 2D soundstage +; Includes spatialization effects +; +; (x,y) may be (flonum, flonum) or (behavior, behavior) +; +(defun position (s_in x y config) + (let* ( (r_m (dist x y 0 0)) + (r (mult r_m (recip config))) + (spd_snd (/ 344.31 config)) + (offset (if (soundp r_m) + (/ (aref (snd-samples r 1) 0) spd_snd) + (/ r spd_snd))) + (snd (seq (s-rest offset) + (if (soundp r_m) + (atten (absorb (doppler s_in r_m) r_m) r) + (atten (absorb s_in r_m) r)))) ) + + ; Two Notes: + ; 1.) The center channel is automatically imaged correctly + ; because sounds placed between the left-and-right channels + ; distribute linearly between the two channels. + ; + ; 2.) Although the below settings assume that all speakers are + ; equidistant from the listener, you can easily assume a + ; different layout by modifying the xs and ys values in + ; each channel's call to the stage function. + ; + (prologic (stage snd x y -.1913 -.4619) ;left + (scale 0.0 snd) ;center (null) + (stage snd x y .1913 -.4619) ;right + (stage snd x y 0.0 .5 )))) ;rear + + +;--------------------------------------------------- +; Diagnostics +;--------------------------------------------------- + +; +; Pro-Logic Channel Test Tones +; +(defun pl_test () + (play (prologic + ( osc-note a3 ) + (seq (s-rest 1.25) (osc-note b3)) + (seq (s-rest 2.5 ) (osc-note c4)) + (seq (s-rest 3.75) (osc-note d4)) ))) + + +; +; Pan Test +; +(defun pan_test () + (play (pan2d + (seq + (s-rest .25) (osc a3 .75) + (s-rest .25) (osc b3 .75) + (s-rest .25) (osc c4 .75) + (s-rest .25) (osc d4 .75)) + + (pwl + 0 0 + 0.99 0 + + 1 1 + 2.99 1 + + 3 0 + 4 0 + 4 ) + + (pwl + 0 0 + 1.99 0 + + 2 1 + 4 1 + 4 )))) + + +; +; Doppler test +; +(defun dop () + (play (doppler (osc c4 10) (pwl .25 0 .5 100 .75 100 1.0)))) + +; +; Attenuation test +; +(defun att () + (play (atten (osc-note c4 4) + (pwl 0 2 + 1 2 + 2 100 + 3 100 + 4 2 + 4 )))) + + +; +; Doppler positioning test (ambulance) +; +(defun ambulance () + (play (scale 0.2 + (position + + (stretch 16 (fmosc c4 (mult 1000 (lfo 2)))) + + (pwl + 0 -20 + 8 20 + 8 ) + + (pwl + 0 0 + 8 ) + + config)))) + + +; +; Position test +; + +; Make a sound orbit the listener +(defun orbit_x (r t times) + (let (k) + (seqrep (k times) + (pwl + 0.0 0.0 + (/ t 4) r + (/ t 2) 0.0 + (/ (* t 3) 4) (* -1 r) + t 0.0 + t ) ))) +(defun orbit_y (r t times) + (let (k) + (seqrep (k times) + (pwl + 0.0 (* -1 r) + (/ t 4.0) 0.0 + (/ t 2.0) r + (/ (* t 3.0)4.0) 0.0 + t (* -1 r) + t ) ))) +(defun orbit (snd r t times) + (position snd + (orbit_x r t times) + (orbit_y r t times) + config)) + + +; Play some tones +(defun pos_1 () + (play (position + (seq + (s-rest .125) (osc a3 1.75) + (s-rest .25) (osc b3 1.75) + (s-rest .25) (osc c4 1.75) + (s-rest .25) (osc d4 1.75) (s-rest .125)) + + (pwl + 0 -5 + 1 5 + 2 5 + 3 -5 + 4 -5 + 5 5 + 6 5 + 7 -5 + 8 -5 + 8 ) + + (pwl + 0 -5 + 1 -5 + 2 5 + 3 5 + 4 -5 + 5 -5 + 6 5 + 7 5 + 8 -5 + 8 ) + + config))) + +(defun pos_2 () + (play (seq + (orbit (seq + (s-rest .125) (osc a3 1.75) + (s-rest .25) (osc b3 1.75) + (s-rest .25) (osc c4 1.75) + (s-rest .25) (osc d4 1.75) (s-rest .125)) + + 5 8 1) + (orbit (seq + (s-rest .125) (osc a3 1.75) + (s-rest .25) (osc b3 1.75) + (s-rest .25) (osc c4 1.75) + (s-rest .25) (osc d4 1.75) (s-rest .125)) + + 5 8 1)))) diff --git a/lib/time-delay-fns.lsp b/lib/time-delay-fns.lsp new file mode 100644 index 0000000..551ac36 --- /dev/null +++ b/lib/time-delay-fns.lsp @@ -0,0 +1,90 @@ +;; a library of simple time delay functions (chorus, phaser, etc.) +;; +;; by Kathy Drye and Roger Dannenberg + + +;; phaser +;; The phaser uses all-pass filter to create the delay + +(defun phaser (s) (sim s (alpass s 1 20))) + +;; an example +;(play (phaser (s-read "example1.wav"))) + + +;; nyq:snd-tapv -- handles multichannel input sounds +;; +(defun nyq:snd-tapv (sound offset modulation maxdepth) + (multichan-expand #'snd-tapv sound offset modulation maxdepth)) + + +(defun delay-tapv (sound maxdelay delay depth rate saturation + &optional (phase 0.0)) + ;; delay a signal by delay plus a time-varying amount controlled + ;; by an LFO (sine) and add to the original sound + ;; delay + depth must be greater than zero and less than maxdelay + ;; maxdelay is a scalar + ;; rate is the frequency of the LFO + ;; saturation is the amount of modulated signal added to the + ;; original (normally 0 to 1) + ;; + (let ((modulation (sum delay + (prod depth + (lfo rate 10000.0 *sine-table* phase))))) + ;; add sound with variable delay to sound with fixed delay + (hp (sum (prod (nyq:snd-tapv sound 0.0 modulation maxdelay) + saturation) + sound) + 10))) + + +;; flanger: +;; The flanging effect uses a time-varied delay +;; This version uses 0-20ms delay modulated at 0.2Hz, +;; with a saturation of 0.8. This flange does not use +;; feedback. + +(defun flange (input-sound) + (delay-tapv input-sound .02 .01 .01 0.2 0.9)) + + + +;; chorus effect +;; +;; chorus: +;; The chorus effect uses a time-varied delay +;; The delay is generally a longer delay with an lfo controlling +;; the delay operating around 0.3Hz + + +(defun chorus (input-sound &key (delay 0.03) (depth 0.003) + (rate 0.3) (saturation 1.0) + (phase 0.0)) + (delay-tapv input-sound (+ delay depth) + delay depth rate saturation phase)) + + +(defun stereo-chorus (input-sound &key (delay 0.03) (depth 0.003) + (rate1 0.3) (rate2 0.1) + (saturation 1.0)) + (sim + (pan (chorus input-sound :delay delay :depth depth :rate rate1 + :saturation saturation) .3) + (pan (chorus input-sound :delay delay :depth depth :rate rate1 + :saturation saturation :phase 180.0) .7))) + + +;; examples +;(play (chorus (aref (s-read "example1.wav") 0))) +; +; you can apply different parameters to each channel using delay-tapv, +; e.g. here the rate is different on the left and right channels +; (works with mono or stereo input!) +;(play (delay-tapv (s-read "example1.wav") 0.1 0.05 0.005 (vector 0.4 0.1) 0.8)) +; +; the STEREO-CHORUS is intended for mono input. +;(play (stereo-chorus (mono-sound)) + + + + diff --git a/lib/vectors.lsp b/lib/vectors.lsp new file mode 100644 index 0000000..4a930d1 --- /dev/null +++ b/lib/vectors.lsp @@ -0,0 +1,137 @@ +;; vectors.lsp -- a small simple vector package +;; +;; vectors are lists, not arrays +;; probably one should be able to use either form (list or array) +;; and functions should accept either + +(defun vector-from-array (x) + (let (v (n (length x))) + (dotimes (i n) + (setf v (cons (aref x (- n i 1)) v))) + v)) + +(defun vector-cosine (x y) + (/ (vector-dot x y) (vector-norm x) (vector-norm y))) + +(defun vector-dot (x y) + (let ((d 0)) + (dolist (e x) + (setf d (+ d (* e (car y)))) + (setf y (cdr y))) + d)) + +;; VECTOR-NORM -- also Euclidean distance +;; +(defun vector-norm (x) + (sqrt (float (vector-sum-elements (vector-square x))))) + + +(defun vector-sum-elements (x) + (let ((sum 0)) + (dolist (e x) + (setf sum (+ sum e))) + sum)) + +(defun vector-sum (a b) + (let (v) + (dolist (e a) + (setf v (cons (+ e (car b)) v)) + (setf b (cdr b))) + (reverse v))) + +(defun vector-mean (x) + (/ (vector-sum-elements x) (length x))) + + +;; vector-median uses statistics.lsp -- you must load this explicitly +;; before calling vector-median +;; +(defun vector-median (x) + (let ((stats (send statistics-class :new t))) + (dolist (e x) (send stats :point e)) + (send stats :get-median))) + + +(defun vector-offset (x c) + (let (v) + (dolist (e x) + (setf v (cons (+ e c) v))) + (reverse v))) + +(defun vector-difference (a b) + (let (v) + (dolist (e a) + (setf v (cons (- e (car b)) v)) + (setf b (cdr b))) + (reverse v))) + + +(defun vector-divide (a b) + (let (v) + (dolist (e a) + (setf v (cons (/ e (car b)) v)) + (setf b (cdr b))) + (reverse v))) + + +(defun vector-scale (x c) + (let (v) + (dolist (e x) + (setf v (cons (* e c) v))) + (reverse v))) + + +(defun vector-zero (len) + (let (v) + (dotimes (i len) (setf v (cons 0.0 v))))) + + +(defun vector-square (a) + (let (v) + (dolist (e a) + (setf v (cons (* e e) v))) + (reverse v))) + + +(defun vector-variance (x) + (let ((n (length x)) + (sum 0.0) + (sum-sqr 0.0)) + (dotimes (i n) + (setf sum (+ sum (car x))) + (setf sum-sqr (+ sum-sqr (* (car x) (car x)))) + (setf x (cdr x))) + (/ (- sum-sqr (/ (* sum sum) n)) (1- n)))) + + +(defun vector-stddev (x) + (sqrt (vector-variance x))) + +;; compute autocorrelation with lag1 <= lag < lag2 +;; note that because of different overlap, the autocorrelation +;; will be over different numbers of points (but normalized +;; by dividing by the length). Note: It should be true that +;; 0 <= lag1 < lag2 < length(x) +;; Otherwise, nil is returned. +;; +;; Algorithm notes: len is length of input, +;; rsltlen is length of result. The range of lags is +;; from 0 to len - 1. +;; +(defun vector-autocorrelation (x lag1 lag2) + (prog ((len (length x)) rsltlen rslt y) + ;; return nil if lag conditions are not satisfied + (if (and (<= 0 lag1) (< lag1 lag2) (< lag2 len)) + 'ok (return nil)) + (setf rsltlen (- lag2 lag1)) + (setf y (nthcdr lag1 x)) + (dotimes (i rsltlen) + (let ((xp x) (yp y) (sum 0.0) + (alen (- len (+ lag1 i)))) + (dotimes (j alen) + (setf sum (+ sum (* (car xp) (car yp)))) + (setf xp (cdr xp) yp (cdr yp))) + (setf rslt (cons (/ sum alen) rslt)) + (setf y (cdr y)))) + (return (reverse rslt)))) + diff --git a/lib/xm-test.lsp b/lib/xm-test.lsp new file mode 100644 index 0000000..8fb34ff --- /dev/null +++ b/lib/xm-test.lsp @@ -0,0 +1,622 @@ +;; xm-test.lsp +;; +;; ============== some test code for xm.lsp =============== +;; + +;(load "xm") + +'(setf pat (make-heap '(a b c d e))) +'(dotimes (i 10) (print (next pat))) +'(print "heap test done: ") +'(read) + + +(defun about-equal (x y) + (cond ((null x) (null y)) + ((consp x) + (and (consp y) + (about-equal (car x) (car y)) + (about-equal (cdr x) (cdr y)))) + ((numberp x) + (and (numberp y) + (< (abs (- x y)) 0.000001))) + (t + (equal x y)))) + + +(defun test (name &rest pairs) + (format t "TEST ~A : " name) + (loop + (cond ((or (null pairs) (null (cdr pairs))) + (format t " --PASSED--~%") + (return)) + ((not (about-equal (car pairs) (cadr pairs))) + (format t " --FAILED-- ~A returned instead of ~A~%" + (car pairs) (cadr pairs)) + (break "a test failed") + (return))) + (setf pairs (cddr pairs)))) + + + +(setf xx (make-cycle '(x y z) :name "xx" :trace nil)) + +(test "test" (next xx) 'x (next xx) 'y (next xx t) '(z) (next xx t) '(x y z)) + +(setf aa (make-cycle '(a b) :name "aa" :trace nil)) + +(setf zz (make-cycle (list xx aa))) + +(test "test2" (next zz) 'x (next zz) 'y (next zz t) '(z) (next zz t) '(a b)) + +(setf zz1 (make-cycle (list xx aa) :for 1 :name "zz1")) + +(setf zz10 (make-cycle (list xx aa) :for 10 :name "zz10" :trace nil)) + +(test "test3" (next zz1 t) '(x y z) (next zz1 t) '(a b) + (next zz10 t) '(x y z) + (next zz10 t) '(a b)) + +(setf aa1 (make-cycle '(a b) :for 1 :name "aa1")) + +(setf zza1 (make-cycle (list xx aa1) :name "zza1")) + +(test "test4" (next zza1 t) '(x y z) (next zza1 t) '(a) + (next zza1 t) '(x y z) (next zza1 t) '(b)) + + +(setf zz2 (make-cycle (list xx aa) :for 1 :name "zz2")) +(setf zzz (make-cycle (list zz2 'q) :name "zzz")) + +(test "test5" (next zzz t) '(x y z) (next zzz t) '(q) + (next zzz t) '(a b) (next zzz t) '(q) + (next zzz t) '(x y z) (next zzz t) '(q)) + + ; test using cpat as items list +(setf cpat (make-cycle '(a b) :name "cpat" :trace nil)) +(setf recycpat (make-cycle cpat :for 3 :name "recycpat" :trace nil)) + +(test "test6" (next recycpat t) '(a b a) + (next recycpat t) '(a b a)) + +; test length-class +(setf lpat (make-length (make-cycle '(a b c)) 2)) +(test "length test 1" (next lpat t) '(a b) (next lpat t) '(c a)) + +(setf lpat2 (make-length (make-cycle '(a b c)) (make-cycle '(2 1 0)))) +(test "length test 2" (next lpat2 t) '(a b) (next lpat2 t) '(c) + (next lpat2 t) '() (next lpat2 t) '(a b)) + + +(setf pp1 (make-palindrome '(a b c) + :elide (make-cycle '(:first :last t nil) :name "pp1-elide-pattern") + :name "pp1")) +(test "palindrome test" (next pp1 t) '(a b c c b) (next pp1 t) '(a b c b a) + (next pp1 t) '(a b c b) (next pp1 t) '(a b c c b a) + (next pp1 1) '(a b c c b)) + + +(setf pp2 (make-palindrome '(a b c) + :elide (make-cycle '(:first :last t)) :for 3)) +(test "palindrome test 2" (next pp2 t) '(a b c) (next pp2 t) '(c b a) + (next pp2 t) '(a b c) (next pp2 t) '(b a b)) + + +(setf pp3 (make-palindrome '(a) :elide (make-cycle '(:first :last t nil)))) +(test "palindrome test 3" (next pp3 t) '(a) (next pp3 t) '(a) + (next pp3 t) nil (next pp3 t) '(a a)) + + +(setf pp4 (make-palindrome '(a b c) :elide (make-cycle '(:first :last)) + :for 6)) +(test "palindrome test 4" (next pp4 t) '(a b c c b a) + (next pp4 t) '(b c b a a b)) + +(setf ll1 (make-line '(a b c d))) +(test "line test" (next ll1 t) '(a b c d) (next ll1 t) '(d d d d)) + +(setf nn1 (make-cycle (list + (make-cycle (list + (make-cycle '(a b) :name "ab") + (make-cycle '(c) :name "c")) + :name "ab-c") + (make-cycle (list + (make-cycle '(x y) :name "xy") + (make-cycle '(u v) :name "uv")) + :name "xy-uv")) + :name "ab-c-xy-uv")) + +(test "nested test" (next nn1 t) '(a b) (next nn1 t) '(c) (next nn1 t) '(x y) + (next nn1 t) '(u v) (next nn1 t) '(a b) (next nn1 t) '(c)) + +(setf win1 (make-window (make-cycle '(a b c)) 3 1)) + +(test "window test 1" (next win1 t) '(a b c) + (next win1 t) '(b c a) (next win1 t) '(c a b)) + +(setf win2 (make-window (make-cycle '(a b c)) ; source + (make-cycle '(3 1)) ; length + (make-cycle '(1 1 3)))) ; skip + +(test "window test 2" (next win2 t) '(a b c) + (next win2 t) '(b) ; skip 1 length 1 + (next win2 t) '(a b c) ; skip 1 length 3 + (next win2 t) '(a) ; skip 3 length 1 + (next win2 t) '(b c a) ; skip 1 length 3 + (next win2 t) '(c) ; skip 1 length 1 + (next win2 t) '(a b c) ; skip 3 length 3 + (next win2 t) '(b) ; skip 1 length 1 + (next win2 t) '(a b c)) ; skip 1 length 3 + +(defun only-abc-n (lis n) + (and (= (length lis) n) + (dolist (item lis t) + (cond ((not (member item '(a b c))) + (return nil)))))) + +(defun abc2 (lis) (only-abc-n lis 2)) + +(defun abc3 (lis) (only-abc-n lis 3)) + +(setf rr1 (make-random '(a b c) :name "rr1")) +(display "rr1" (next rr1 t)) +(test "random 1" (abc3 (next rr1 t)) t (abc3 (next rr1 t)) t) + +(setf rr2 (make-random '(a b c) :for 2 :name "rr2" :trace nil)) +(test "random 2" (abc2 (next rr2 t)) t (abc2 (next rr2 t)) t) + + +; random using weights +(setf rr3 (make-random '((a :weight 1) (b :weight 10)))) +(setf a-count 0 b-count 0) +(setf *num-trials* 10000) ;; NORMALLY, SET THIS TO 10000 +(setf rr3-all nil) +(dotimes (i *num-trials*) + ;(display "weight test" i) + (if (eq (setf rr3-out (next rr3)) 'a) (incf a-count) (incf b-count)) + (push rr3-out rr3-all)) +;(print (reverse rr3-all)) + +(setf rr-ratio (/ (float a-count) b-count)) +(format t "test rr3 a/b should be 0.091, actual ratio is ~A~%" rr-ratio) +(test "weight test" (and (< rr-ratio 0.12) (> rr-ratio 0.08)) t) + + +; random using :min +(setf rr4 (make-random '((a :weight 1 :min 2) (b :weight 10 :min 1)))) +(setf sum 0) +(setf a-count 0 b-count 0) +(dotimes (i *num-trials*) + ;(display "min test" (next rr4)) + (if (eq (next rr4) 'a) (incf a-count) (incf b-count)) +) +(setf rr-ratio (/ (float a-count) b-count)) +(format t "test rr4 a/b should be about 0.191, actual ratio is ~A~%" rr-ratio) +(test "min test" (and (< rr-ratio 0.22) (> rr-ratio 0.16)) t) + + +; random using :max +(setf rr5 (make-random '((a :weight 1 :min 2) (b :weight 10 :max 5)))) +(setf sum 0) +(setf rr5-all nil) +(setf a-count 0 b-count 0) +(dotimes (i *num-trials*) + ;(display "max test" (next rr5)) + (if (eq (setf rr5-out (next rr5)) 'a) (incf a-count) (incf b-count)) + (push rr5-out rr5-all)) +(setf rr5-all (reverse rr5-all)) +(setf rr5-state 'a2) +(setf rr5-count 0) +(dolist (s rr5-all) + (incf rr5-count) + (cond ((and (eq rr5-state 'a1) (eq s 'a)) + (setf rr5-state 'a2)) + ((and (eq rr5-state 'a2) (eq s 'a))) + ((and (eq rr5-state 'a2) (eq s 'b)) + (setf rr5-state 'b1)) + ((and (eq rr5-state 'b1) (eq s 'b)) + (setf rr5-state 'b2)) + ((and (eq rr5-state 'b2) (eq s 'b)) + (setf rr5-state 'b3)) + ((and (eq rr5-state 'b3) (eq s 'b)) + (setf rr5-state 'b4)) + ((and (eq rr5-state 'b4) (eq s 'b)) + (setf rr5-state 'b5)) + ((and (eq rr5-state 'b1) (eq s 'a)) + (setf rr5-state 'a1)) + ((and (eq rr5-state 'b2) (eq s 'a)) + (setf rr5-state 'a1)) + ((and (eq rr5-state 'b3) (eq s 'a)) + (setf rr5-state 'a1)) + ((and (eq rr5-state 'b4) (eq s 'a)) + (setf rr5-state 'a1)) + ((and (eq rr5-state 'b5) (eq s 'a)) + (setf rr5-state 'a1)) + (t + (error "bad state")))) + +(setf rr-ratio (/ (float a-count) b-count)) +(format t "test rr5 a/b should be 0.503613, actual ratio is ~A~%" rr-ratio) +(test "max test" (and (> rr-ratio 0.4) (< rr-ratio 0.6)) t) + + +(setf hh1 (make-heap '(a b c))) +(test "heap 1" (abc3 (next hh1 t)) t (abc3 (next hh1 t)) t) + +(setf hh2 (make-heap '(a b c) :for 2 :name "hh2" :trace nil)) +(test "heap 2" (abc2 (next hh2 t)) t (abc2 (next hh2 t)) t) + +(setf xx (make-markov `((a -> a (b ,(make-cycle '(1 2)))) (b -> a)) + :past '(b) + :produces `(a ,(make-cycle '(0)) + b ,(make-cycle '(1 2 3 4) + :trace nil :name "b-produces")) + :is-nested t + :trace nil :name "markov")) +(setf xx-out nil) +(dotimes (i 12) (push (next xx) xx-out)) +(setf xx-out (reverse xx-out)) +(print xx-out) +;; this is a special test to see if the output is plausible +(defun markov-test-xx (lis) + (let (a b) + (setf a (car lis)) + (setf lis (cdr lis)) + (cond ((null lis) t) + ((and (setf b (car lis)) + (eq a 0) (member b '(0 1))) + (markov-test-xx lis)) + ((and (eq a 1) (eq b 2)) + (markov-test-xx lis)) + ((and (eq a 2) (eq b 3)) + (markov-test-xx lis)) + ((and (eq a 3) (eq b 4)) + (markov-test-xx lis)) + ((and (= a 4) (= b 0)) + (markov-test-xx lis)) + (t nil)))) +(format t "TEST markov test : ~A~%" (if (markov-test-xx xx-out) "--PASSED--" + (break "markov test failed"))) + + +(setf cc (make-copier (make-cycle '(a b) :name "ab" :trace nil) + :repeat 3 :name "copier" :trace nil :merge t)) + +(test "copier test 1" (next cc t) '(a b a b a b) (next cc t) '(a b a b a b)) + +(setf cc2 (make-copier (make-cycle '(a b) :name "ab" :trace nil) + :repeat 3 :name "copier" :trace nil)) + +(test "copier test 2" (next cc2 t) '(a b) (next cc2 t) '(a b) (next cc2 t) '(a b)) + +(setf cc3 (make-copier (make-cycle (list (make-cycle '(a)) (make-cycle '(b)))) + :repeat 3 :merge t)) + +(test "copier test 3" (next cc3 t) '(a a a) (next cc3 t) '(b b b) + (next cc3 t) '(a a a)) + +(setf cc4 (make-copier (make-cycle '(a b c d) :for 1) + :repeat (make-cycle '(2 -2 3 -3)) + :merge t)) +(test "copier test 4" (next cc4 t) '(a a) (next cc4 t) '(d d d) + (next cc4 t) '(d d) (next cc4 t) '(c c c)) + +(setf cc5 (make-copier (make-cycle '(a b c d) :for 1) + :repeat 3)) +(test "compier test 5" (next cc5 t) '(a) (next cc5 t) '(a) + (next cc5 t) '(a) (next cc5 t) '(b) (next cc5 t) '(b) + (next cc5 t) '(b) (next cc5 t) '(c) (next cc5 t) '(c) + (next cc5 t) '(c) (next cc5 t) '(d) (next cc5 t) '(d) + (next cc5 t) '(d) (next cc5 t) '(a) (next cc5 t) '(a)) + + +(setf acc1 (make-accumulate (make-cycle '(1 2 -3)))) + +(test "accumulate test 1" (next acc1 t) '(1 3 0) (next acc1 t) '(1 3 0)) + +(setf acc2 (make-accumulate (make-cycle '(1 2 -3) :for 2))) + +(test "accumulate test 2" (next acc2 t) '(1 3) (next acc2 t) '(0 1) + (next acc2 t) '(3 0)) + +(setf sum1 (make-sum (make-cycle '(1 2)) (make-cycle '(3 4 5)))) + +(test "sum test 1" (next sum1 t) '(4 6) (next sum1 t) '(6 5) + (next sum1 t) '(5 7)) + +(setf sum2 (make-sum (make-cycle '(1 2)) (make-cycle '(3 4 5)) :for 4)) + +(test "sum test 2" (next sum2 t) '(4 6 6 5) (next sum2 t) '(5 7 4 6)) + +(setf prod1 (make-product (make-cycle '(1 2)) (make-cycle '(3 4 5)))) + +(test "prod test 1" (next prod1 t) '(3 8) (next prod1 t) '(5 6) + (next prod1 t) '(4 10)) + +(setf prod2 (make-product (make-cycle '(1 2)) (make-cycle '(3 4 5)) :for 4)) + +(test "prod test 2" (next prod2 t) '(3 8 5 6) (next prod2 t) '(4 10 3 8)) + +(setf eval1 (make-eval '(+ 1 2) :for 3)) + +(test "eval test 1" (next eval1 t) '(3 3 3)) + +#| + +(setf testscore '((0 0 (score-begin-end 0 10)) + (0.1 1 (note :pitch 60 :vel 100)) + (1 1 (note :pitch 61 :vel 91)) + (1 0.5 (note :pitch 68 :vel 92)) + (1.5 0.5 (note :pitch 67 :vel 93)) + (2 1 (note :pitch 62 :vel 94)))) + +(test "basic1" (score-get-begin testscore) 0) +(test "basic2" (score-get-end testscore) 10) +(test "basic3" (score-set-begin testscore 1) + (cons '(0 0 (score-begin-end 1 10)) (cdr testscore))) +(test "basic4" (score-set-end testscore 4) + (cons '(0 0 (score-begin-end 0 4)) (cdr testscore))) +(test "basic5" (score-get-begin (cdr testscore)) 0.1) +(test "basic6" (score-get-end (cdr testscore)) 3) + +(test "score-shift" (score-shift testscore 5) + '((0 0 (SCORE-BEGIN-END 0 15)) + (5.1 1 (NOTE :PITCH 60 :VEL 100)) + (6 0.5 (NOTE :PITCH 68 :VEL 92)) + (6 1 (NOTE :PITCH 61 :VEL 91)) + (6.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (7 1 (NOTE :PITCH 62 :VEL 94)) + )) + +(test "score-stretch1" (setf xx (score-stretch testscore 2)) + (setf yy '((0 0 (SCORE-BEGIN-END 0 20)) + (0.2 2 (NOTE :PITCH 60 :VEL 100)) + (2 2 (NOTE :PITCH 61 :VEL 91)) + (2 1 (NOTE :PITCH 68 :VEL 92)) + (3 1 (NOTE :PITCH 67 :VEL 93)) + (4 2 (NOTE :PITCH 62 :VEL 94)) + ))) + +(test "score-stretch2" (score-stretch testscore 2 :dur nil) + '((0 0 (SCORE-BEGIN-END 0 20)) + (0.2 1 (NOTE :PITCH 60 :VEL 100)) + (2 1 (NOTE :PITCH 61 :VEL 91)) + (2 0.5 (NOTE :PITCH 68 :VEL 92)) + (3 0.5 (NOTE :PITCH 67 :VEL 93)) + (4 1 (NOTE :PITCH 62 :VEL 94)) + )) + +(test "score-stretch3" (score-stretch testscore 2 :from-index 2 :to-index 3) + '((0 0 (SCORE-BEGIN-END 0 10.5)) + (0.1 1.1 (NOTE :PITCH 60 :VEL 100)) + (1 1.5 (NOTE :PITCH 61 :VEL 91)) + (1 1 (NOTE :PITCH 68 :VEL 92)) + (2 0.5 (NOTE :PITCH 67 :VEL 93)) + (2.5 1 (NOTE :PITCH 62 :VEL 94)) + )) + +(test "score-stretch4" (score-stretch testscore 2 :from-time 1.5 :to-time 2.5) + '((0 0 (SCORE-BEGIN-END 0 11)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1 1.5 (NOTE :PITCH 61 :VEL 91)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)) + (1.5 1 (NOTE :PITCH 67 :VEL 93)) + (2.5 1.5 (NOTE :PITCH 62 :VEL 94)) + )) + + +(test "score-transpose1" (score-transpose testscore :pitch 5) + '((0 0 (score-begin-end 0 10)) + (0.1 1 (note :pitch 65 :vel 100)) + (1 1 (note :pitch 66 :vel 91)) + (1 0.5 (note :pitch 73 :vel 92)) + (1.5 0.5 (note :pitch 72 :vel 93)) + (2 1 (note :pitch 67 :vel 94)))) + +(test "score-transpose1" (score-transpose testscore :pitch 5 + :from-index 2 :to-index 3) + '((0 0 (score-begin-end 0 10)) + (0.1 1 (note :pitch 60 :vel 100)) + (1 1 (note :pitch 66 :vel 91)) + (1 0.5 (note :pitch 73 :vel 92)) + (1.5 0.5 (note :pitch 67 :vel 93)) + (2 1 (note :pitch 62 :vel 94)))) + +(test "score-scale1" (score-scale testscore :vel 0.5) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (NOTE :PITCH 60 :VEL 50)) + (1 1 (NOTE :PITCH 61 :VEL 45.5)) + (1 0.5 (NOTE :PITCH 68 :VEL 46)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 46.5)) + (2 1 (NOTE :PITCH 62 :VEL 47)) + )) + +(test "score-scale2" (score-scale testscore :vel 0.5 + :from-time 1 :to-time 1.5) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1 1 (NOTE :PITCH 61 :VEL 45.5)) + (1 0.5 (NOTE :PITCH 68 :VEL 46)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)) + )) + +(test "score-sustain1" (score-sustain testscore 2) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 2 (NOTE :PITCH 60 :VEL 100)) + (1 2 (NOTE :PITCH 61 :VEL 91)) + (1 1 (NOTE :PITCH 68 :VEL 92)) + (1.5 1 (NOTE :PITCH 67 :VEL 93)) + (2 2 (NOTE :PITCH 62 :VEL 94)))) + +(test "score-sustain2" (score-sustain testscore 2 + :from-index 0 :to-index 1) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 2 (NOTE :PITCH 60 :VEL 100)) + (1 1 (NOTE :PITCH 61 :VEL 91)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)))) + +(test "score-voice1" (score-voice testscore '((note violin))) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (VIOLIN :PITCH 60 :VEL 100)) + (1 1 (VIOLIN :PITCH 61 :VEL 91)) + (1 0.5 (VIOLIN :PITCH 68 :VEL 92)) + (1.5 0.5 (VIOLIN :PITCH 67 :VEL 93)) + (2 1 (VIOLIN :PITCH 62 :VEL 94)))) + +(test "score-voice2" (score-voice testscore '((flute horn) (note violin)) + :from-index 0 :to-index 10) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (VIOLIN :PITCH 60 :VEL 100)) + (1 1 (VIOLIN :PITCH 61 :VEL 91)) + (1 0.5 (VIOLIN :PITCH 68 :VEL 92)) + (1.5 0.5 (VIOLIN :PITCH 67 :VEL 93)) + (2 1 (VIOLIN :PITCH 62 :VEL 94)))) + +'(score-print (score-merge testscore + (score-shift + (score-voice testscore '((note violin))) + 0.1))) + + +(test "score-merge1" (score-merge testscore + (score-shift + (score-voice testscore '((note violin))) + 0.1)) + '((0 0 (SCORE-BEGIN-END 0 10.1)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (0.2 1 (VIOLIN :PITCH 60 :VEL 100)) + (1 1 (NOTE :PITCH 61 :VEL 91)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)) + (1.1 0.5 (VIOLIN :PITCH 68 :VEL 92)) + (1.1 1 (VIOLIN :PITCH 61 :VEL 91)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (1.6 0.5 (VIOLIN :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)) + (2.1 1 (VIOLIN :PITCH 62 :VEL 94)) + )) + +(test "score-merge2" (score-merge + '((0 0 (SCORE-BEGIN-END 0 10)) + (0 1 (NOTE :PITCH 60 :VEL 100))) + '((0 0 (SCORE-BEGIN-END 0 10)) + (1 1 (NOTE :PITCH 61 :VEL 91))) + '((0 0 (SCORE-BEGIN-END 0 10)) + (2 1 (NOTE :PITCH 62 :VEL 94)))) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0 1 (NOTE :PITCH 60 :VEL 100)) + (1 1 (NOTE :PITCH 61 :VEL 91)) + (2 1 (NOTE :PITCH 62 :VEL 94)))) + +(test "score-append1" + (score-append testscore testscore) + '((0 0 (SCORE-BEGIN-END 0 20)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1 1 (NOTE :PITCH 61 :VEL 91)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)) + (10.1 1 (NOTE :PITCH 60 :VEL 100)) + (11 1 (NOTE :PITCH 61 :VEL 91)) + (11 0.5 (NOTE :PITCH 68 :VEL 92)) + (11.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (12 1 (NOTE :PITCH 62 :VEL 94)))) + + +(test "score-select1" + (score-select testscore t :from-time 1 :to-time 1.5) + '((0 0 (SCORE-BEGIN-END 0 10)) + (1 1 (NOTE :PITCH 61 :VEL 91)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)))) + +(test "score-select2" + (score-select testscore + '(lambda (time dur expr) (eql (expr-get-attr expr :pitch) 61)) + :from-time 1 :to-time 1.5) + '((0 0 (SCORE-BEGIN-END 0 10)) + (1 1 (NOTE :PITCH 61 :VEL 91)))) + +(test "score-select3" + (score-select testscore + '(lambda (time dur expr) (eql (expr-get-attr expr :pitch) 61)) + :reject t) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)))) + +(test "score-filter-length" + (score-filter-length testscore 1.5) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)))) + +(test "score-repeat" + (score-repeat testscore 3) + '((0 0 (SCORE-BEGIN-END 0 30)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)) + (1 1 (NOTE :PITCH 61 :VEL 91)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)) + (10.1 1 (NOTE :PITCH 60 :VEL 100)) + (11 1 (NOTE :PITCH 61 :VEL 91)) + (11 0.5 (NOTE :PITCH 68 :VEL 92)) + (11.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (12 1 (NOTE :PITCH 62 :VEL 94)) + (20.1 1 (NOTE :PITCH 60 :VEL 100)) + (21 1 (NOTE :PITCH 61 :VEL 91)) + (21 0.5 (NOTE :PITCH 68 :VEL 92)) + (21.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (22 1 (NOTE :PITCH 62 :VEL 94)))) + +(test "score-stretch-to-length" + (score-stretch-to-length testscore 20) + '((0 0 (SCORE-BEGIN-END 0 20)) + (0.2 2 (NOTE :PITCH 60 :VEL 100)) + (2 2 (NOTE :PITCH 61 :VEL 91)) + (2 1 (NOTE :PITCH 68 :VEL 92)) + (3 1 (NOTE :PITCH 67 :VEL 93)) + (4 2 (NOTE :PITCH 62 :VEL 94)) + )) + +(test "score-filter-overlap" + (score-filter-overlap testscore) + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)))) + +(test "score-adjacent-events1" + (score-adjacent-events testscore #'(lambda (a b c) b)) + testscore) + +(test "score-adjacent-events2" + (score-adjacent-events testscore + #'(lambda (a b c) + (if (eql (event-get-attr b :pitch) 61) + nil b))) ; remove pitches with 61 + '((0 0 (SCORE-BEGIN-END 0 10)) + (0.1 1 (NOTE :PITCH 60 :VEL 100)) + (1 0.5 (NOTE :PITCH 68 :VEL 92)) + (1.5 0.5 (NOTE :PITCH 67 :VEL 93)) + (2 1 (NOTE :PITCH 62 :VEL 94)))) + +(test "score-indexof" + (score-indexof testscore #'(lambda (time dur expr) + (eql (expr-get-attr expr :pitch) 61))) + 2) + +(test "score-last-indexof" + (score-last-indexof testscore #'(lambda (time dur expr) + (> (expr-get-attr expr :pitch) 65))) + 4) + + +|# + + + diff --git a/liblo/AUTHORS b/liblo/AUTHORS new file mode 100644 index 0000000..bf27408 --- /dev/null +++ b/liblo/AUTHORS @@ -0,0 +1,30 @@ +Steve Harris +Nicholas J Humfrey +Uwe Koloska +Jesse Chappell +Topher Cyll +Sze'kelyi Szabolcs +Camille Troillard +Chris Hixon +Kentaro Fukuchi +Dave Robillard +Nicolas Humfrey +Stephen Sinclair +Dominic Sacré +Alex McLean +Mike Wozniewski + + +Guidelines for authors: + +As liblo is an implementation of a fairly widespread protocol I'd like to keep +any changes in check to try to prevent it deviating too far from the agreed OSC +standard and the intended niche of liblo (ie. easy to use). To help that, +please try to follow the following guidelines: + +* Keep to the current, fairly minimal, OO-C API style where possible +* Document any API changes in Doxygen style. my current docs aren't great, but + the're better than nothing :) +* Update the ChangeLog whenever neccesary. +* Add tests for any changes or discovered bugs to the regression test file. + diff --git a/liblo/COPYING b/liblo/COPYING new file mode 100644 index 0000000..5ab7695 --- /dev/null +++ b/liblo/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library 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 2.1 of the License, or (at your option) any later version. + + This library 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 library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/liblo/ChangeLog b/liblo/ChangeLog new file mode 100644 index 0000000..d6b8f2d --- /dev/null +++ b/liblo/ChangeLog @@ -0,0 +1,350 @@ +2009-03-07 Stephen Sinclair + * Fix some typos, grammar, and links in the documentation. + * Remove TCP from TODO list. + * Add recent contributors to the AUTHORS list. + * Add previous release notes to the NEWS file. + * Add note about MSVC in README. + * Release 0.26. + +2009-03-06 Stephen Sinclair + * Add a return value to lo_bundle_add_message(). + * Avoid pointer arithmetic on void* types for compilers that can't handle it. + * Move all local variable declarations to the top of the scope. + * Conditionally avoid the use of variable-argument macros if not GCC. + * Fix multicast on Windows: join multicast group after bind() instead of before. + * Avoid the use of C99 struct literals when giving timetag arguments. + * Add premake4, used to generate MSVC project/solution files. + * Add numerous typical kludges necessary to cover differences in MSVC. + * Use log() instead of a while loop to calculate new data size. + * Add return values for all functions that can potentially fail. + * Add premake4-related files to the dist build. + +2009-02-17 Stephen Sinclair + * For multicast, enable SO_REUSEPORT as well as SO_REUSEADDR. (Mike Wozniewski) + +2009-02-12 Stephen Sinclair + * Fix the definition of LO_TT_IMMEDIATE per the OSC spec. (Dominic Sacré) + +2009-02-01 Stephen Sinclair + * Add function lo_message_get_timestamp(). (Alex McLean) + * Fix magic constant in lo_timetag_diff. (Dominic Sacré) + * Bump the LO_SO_VERSION version major number to resolve ABI + incompatibilities with previous versions. In particular, the + addition of 'const' to an argument of lo_blob_new() in r80 + constituted an API add and removal, hence the reset of the 3rd + number ('age') according to the libtool manual. (SS) + +2009-01-04 Stephen Sinclair + * Add checks to configure.ac for select() and poll(). + * Use inet_addr if inet_aton is not available. (i.e., on Windows) + * Retry a TCP connection once if it failed to connect on send. + * Remove useless conditional call to freeaddrinfo(). + * Only implement gai_strerrorA if gai_strerror was not already defined. + * Make the TCP protocol retain session information for multiple connections. + +2008-12-23 Nicholas Humfrey + * Added a function called lo_server_wait() which waits for a message to be received. + +2008-11-23 Stephen Sinclair + * Use the \internal Doxygen command to hide internal functions. + +2008-10-11 Kentaro Fukuchi + * lo_url_get_protocol_id() has been added. + * lo_address_new_with_proto() has been added. + * Changed lo_address_new_from_url() to use lo_url_get_protocol_id(). + +2008-10-09 Kentaro Fukuchi + * src/tools/oscsend.c: Fixed compile-time error on OS X. + (thanks to Koichiro Ozaki) + +2008-10-07 Stephen Sinclair + * Move lo_arg_size(), lo_get_path(), lo_arg_host/network_endian() back to lo_lowlevel.h. + * Expose the lo_server_dispatch_data() function as public. + * Fix zero-padding of path and type strings in lo_message_deserialise(). + +2008-09-07 Kentaro Fukuchi + * Memory leak in lo_address_new_from_url() has been fixed. + * Memory leak in dispatch_method() has been fixed. + * Fix a typo and some missing free() in testlo.c. + +2008-09-04 Stephen Sinclair + * Change license of LibLo to LGPL 2.1 or later. + (With permission of all authors.) + +2008-07-11 Kentaro Fukuchi + * Some error checks have been added. + * oscsend now uses strtod() instead of strtof(). strtof of glibc returned + buggy results when --std=c99 is not given. (strtof is described in C99) + +2008-06-18 Stephen Sinclair + * Update AUTHORS + * Release version 0.25 + +2008-06-05 Stephen Sinclair + * Fix autogen.sh: Use glibtoolize if it exists, for OS X. + * Fix undefined MSG_NOSIGNAL in testlo.c. + * Fix warning on lo_message_deserialize(). + +2008-05-05 Stephen Sinclair + * Fix invalid pointer in lo_server_del_method() when doing pattern matching. (Camille Troillard) + +2008-04-28 Stephen Sinclair + * Add support for multicast groups to LibLo. + * Add test case for sending a crafted packet that would crash a lo_server without validation. + * Make validation-related functions internal to liblo. + * Add server input validation along with a function to deserialise an OSC message. (Chris Hixon) + * Fix bad socket number in lo_client_sockets when a server is freed. + +2008-04-21 Stephen Sinclair + * Added Daniel Lacroix's patch for level 2 broadcast support. + * Use resolved IP address to detect broadcast address. + +2008-02-25 Stephen Sinclair + * Fix bug where curly brackets didn't match the last item in the comma-separated list. + +2008-02-20 Stephen Sinclair + * Added lo_bundle_free_messages() to free a bundle and the messages it points to. (Kentaro Fukuchi) + +2008-01-27 Stephen Sinclair + * Fix for lo_message_add(), wrong argument order for lo_message_add_varargs_internal(). (Dave Robillard) + * Added test case for lo_message_add(). + +2008-01-20 Stephen Sinclair + + * Added lo_message_add_varargs() to play well with C functions taking a variable number of arguments. (Dave Robillard) + * Avoid unnecessary repetitive reallocation on lo_message_add_*(). (Dave Robillard) + * Fixed errors related to 64-bit in packing blob and MIDI messages. (Dave Robillard) + +2008-01-13 Stephen Sinclair + + * Fixed index increment in sendosc.c for string and symbol types + +2008-01-12 Nicholas Humfrey + + * Added tools from Kentaro Fukuchi + +2007-03-19 Nicholas Humfrey + + * Applied patch from Chris Hixon to check for buffer overflows + +2007-03-16 Nicholas Humfrey + + * Fixed several compiler warnings + * Changed address for package bug reports + * Released version 0.24 + +2007-03-09 Nicholas Humfrey + + * Changed lo_blob_new() to take const void* (thanks to Lars Luthman) + * Disable getnameinfo() method of getting hostname, when IPv6 is disabled + * Unlink Unix server socket when it is close (thanks to Dominic SacrŽ) + * Checks size of unix socket path properly + * Now accepts unix socket format osc.unix://localhost/tmp/mysocket.sock + * Released version 0.24pre1 + +2007-03-08 Nicholas Humfrey + + * Added lo_server_thread_new_with_proto(), as suggested by Dave Robillard + * Applied patch from Aron Stansvik to fix bug with FreeBSD/NetBSD systems + * Removed freeaddrinfo() from resolve_address() error case (thanks to Anthony Green) + * Only call connect() for TCP sessions (thanks to Roger B. Dannenberg) + +2006-03-29 Nicholas Humfrey + + * Applied lo_address_get_url() patch from Sze'kelyi Szabolcs + * Added lo_server_get_protocol() and lo_address_get_protocol() + * Added tests for lo_address_get_* tests to test tool + +2006-01-26 Nicholas Humfrey + + * IPv6 is now disabled by default + * Released version 0.23 + +2005-12-29 Nicholas Humfrey + + * Fixed pthread resource leak, when stopping thread + +2005-12-21 Nicholas Humfrey + + * Fixed bug where sockets weren't closed when replying to messages + * Split off resolve_address into seperate create_socket function + * Only creates new sockets when needed + +2005-12-05 Nicholas Humfrey + + * Added lo_send_from, lo_send_message_from and lo_send_bundle_from + * Merged guts of lo_send_message and lo_send_bundle into new static send_data() + +2005-09-04 Steve Harris + + * Released 0.22 + +2005-09-02 Steve Harris + + * address.c, server.c: Added patch from Martin Habets that redoes + parts of previous patches... + +2005-09-01 Steve Harris + + * address.c, server.c: Added patches from Jesse Chappell and Dave + Robillard to close various sockets when there no longer used. + +2005-08-19 Steve Harris + + * address.c, testlo.c: Added patch from Dave Robillard to fix parsing + of IPV6 addresses in URLs. + +2005-08-11 Martin Habets + + * message.c: Fix LO_CHAR sending on big endian architectures. + +2005-08-09 Martin Habets + + * server.c: Add lo_server_del_method() + * server_thread.c: Add lo_server_thread_del_method() + +2005-07-26 Steve Harris + + * bundle.c, server.c: Endianess fixed from Topher Cyll for bundle + timestamps. + + # Bundle delivery timing is still not right, theres an arithmetic + # errorsomewhere, but I cant see it. + +2005-06-05 Steve Harris + + * server.c: Patch from Lorenz Schori to optionally disable IPV6 support + with --disable-ipv6 + +2005-03-31 Steve Harris + + * server.c: Patch from Martin Habets that expands wildcarded patch to + the matching path where possible (eg. not when using the NULL + wildcard path). + +2005-03-04 Steve Harris + + * server.c: try to fix the global struct thing that keeps track of + server sockets. + +2005-02-03 Steve Harris + + * server.c: made UDP messages resolve back to thier originating server, + or something close to it. + +2005-02-03 Taybin Rutkin + + * server.c: commited resource leak fix from Jesse Chappell + +2005-01-22 Steve Harris + + * address.c: fixed bug when determining protocol of URL with + unspecified sub-protocol. Reported by Pix. + +2005-01-13 Steve Harris + + * bundle.c: patch from Dave Robillard that fixes bundles of more than 4 + messages. + +2005-01-13 Steve Harris + + * message.c: made the arguments to _add_string and _add_symbol const + char * for C++ compatibility. + +2005-01-10 Steve Harris + + * message.c: added a source field that represents the source from which + a message was received. Useful in method handlers to determine which + client sent the message. + +2004-12-21 Steve Harris + + * server.c: added patch from Walco van Loon and Pix that fixes a bug + in the hostname detection fallback code + +2004-11-19 Steve Harris + + * send.c: added lo_send_timestamped() + +2004-11-17 Steve Harris + + * server.c: added code to handle bundle reception + * bundle.c: code to build bundle objects + * timetag.c: code to manipulate and test timetags + +2004-10-19 Steve Harris + + Release 0.13 + * lo.h: removed reference to obsolete header lo_backcompat.h + +2004-10-17 Steve Harris + + * lo_server.c: added code to allow servers to poll() on the server + socket, if available. From Sean Bolton. + +2004-08-27 Steve Harris + + * lo_lowlevel.h, send.c: added OSX compatibility fixes from Taybin + Rutkin. + +2004-08-19 Steve Harris + + Release 0.9 + * testlo.c: added more URL tests + +2004-08-19 Steve Harris + + * address.c: more bugfixes to URL handling + +2004-08-02 Steve Harris + + * server.c, address.c: fixed bugs and ommisions in URL handling + +2004-07-28 Steve Harris + + * send.c, server.c: added code to handle UNIX domain sockets. + +2004-07-12 Steve Harris + + * server_thread.c: added a lo_server_thread_stop() function for + symmetry with lo_server_thread_start() + +2004-06-07 Steve Harris + + * server.c: added a lo_server_recv_noblock() that will not wait for + a packet to be received + +2004-03-26 Steve Harris + + * doc/, *.h: added doxygen documentation + * address.c: changed URL methods to accept/expect protocol + specifiers (eg. osc.udp://...) + * examples/*.c: added comments, slightly simplified + +2004-03-21 Steve Harris + + * server.c: made binding to unspecified ports work + +2004-03-21 Steve Harris + + * message.c: fixed coercion type bugs + * server.c: fixed endian conversion bug + * testlo.c: added lots of tests + * send.c: added implicit guard variable to end of send arguments + +2004-03-20 Steve Harris + + * message.c, send.c: added support for the remaining types OSC + +2004-03-15 Steve Harris + + * message.c: changed the definition of the string argument accessor + member (it was wrong before). + + * target.c, *.[ch]: lo_target* is now called lo_address*, this + makes the api much clearer, %s/lo_target/lo_address/g, should + bring all source files up to date. + +2004-02-29 Steve Harris + + * configure.in, Makefile.am: added auto* stuff diff --git a/liblo/INSTALL b/liblo/INSTALL new file mode 100644 index 0000000..54caf7c --- /dev/null +++ b/liblo/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/liblo/Makefile.am b/liblo/Makefile.am new file mode 100644 index 0000000..7108987 --- /dev/null +++ b/liblo/Makefile.am @@ -0,0 +1,11 @@ +SUBDIRS = src examples lo build @DOXYGEN@ + +EXTRA_DIST = libtool ltmain.sh autogen.sh + +ACLOCAL_AMFLAGS = -I m4 + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = liblo.pc + +test: all + (cd src && make test) diff --git a/liblo/Makefile.in b/liblo/Makefile.in new file mode 100644 index 0000000..5bf8e95 --- /dev/null +++ b/liblo/Makefile.in @@ -0,0 +1,776 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/liblo.pc.in $(top_srcdir)/configure AUTHORS COPYING \ + ChangeLog INSTALL NEWS TODO compile config.guess config.sub \ + depcomp install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = liblo.pc +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LO_SO_VERSION = @LO_SO_VERSION@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = src examples lo build @DOXYGEN@ +EXTRA_DIST = libtool ltmain.sh autogen.sh +ACLOCAL_AMFLAGS = -I m4 +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = liblo.pc +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +liblo.pc: $(top_builddir)/config.status $(srcdir)/liblo.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + ctags-recursive install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ + dist-gzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgconfigDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-pkgconfigDATA + + +test: all + (cd src && make test) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/liblo/Makefile.osx b/liblo/Makefile.osx new file mode 100644 index 0000000..4e2f790 --- /dev/null +++ b/liblo/Makefile.osx @@ -0,0 +1,4 @@ +OBJECTS = message.o blob.o server.o address.o method.o pattern_match.o send.o timetag.o bundle.o nonblocking_server_example.o + +example_client: $(OBJECTS) + g++ $(OBJECTS) $(LFLAGS) -o nonblocking_server_example diff --git a/liblo/NEWS b/liblo/NEWS new file mode 100644 index 0000000..0f5f893 --- /dev/null +++ b/liblo/NEWS @@ -0,0 +1,327 @@ + +-------------------------------------------- +2009-03-07: Release 0.26 +-------------------------------------------- + +We are pleased to present stable release 0.26 of LibLo, the +lightweight, easy to use implementation of the Open Sound Control +protocol. + +Open Sound Control (OSC) is a protocol for communication among +computers, sound synthesizers, and other multimedia devices that is +designed for use over modern network transports. + +This release marks the first release of LibLo under the LGPL license +version 2.1 or later, allowing the use of LibLo in non-GPL +applications as long as it is dynamically linked such that the LibLo +portion of the application can remain freely modifiable. We hope that +this will allow compatibility with a wider variety of audio +applications and encourage the use of open protocols even in +commercial software. (This change was motivated by receiving a number +of requests for special permission for the use of LibLo in non-GPL +software.) + +This release also introduces some new features, such as the ability to +use custom transports, proper TCP multi-session support, access to +bundle timestamp information, and wider C compiler compatibility. + +Details: +- Change license to LGPL 2.1 or later. +- Add return codes to all functions that may fail. +- Fix memory leaks in lo_address_new_from_url(), dispatch_method(), + lo_url_get_path() +- Move lo_arg_size(), lo_get_path(), lo_arg_host/network_endian() back + to lo_lowlevel.h. +- Expose the lo_server_dispatch_data() function as public, making it + possible to react to messages contained in an arbitrary block of + memory. (i.e., allows use with custom transport protocols) +- Get protocol by ID number. +- Keep TCP sessions open, and automatically track multiple open + sessions in a data structure. +- Allow access to bundle timestamp information. +- Fix bug in lo_timetag_diff(). +- Change the value of LO_TT_IMMEDIATE to correspond with the OSC + specification. +- Enable SO_REUSEPORT when initializing a multicast server. +- Update the "soname" describing API/ABI compatibility. +- Update documentation and various bug fixes. +- Compiles under MSVC, avoiding the use of gcc-isms when not using + gcc. + + +Contributions by: +- Mike Wozniewski +- Dominic Sacré +- Alex McLean +- Steve Harris +- Kentaro Fukuchi +- Koichiro Ozaki +- Stephen Sinclair + +Please feel free to download it at SourceForge: +http://downloads.sourceforge.net/liblo/liblo-0.26.tar.gz + +Or read the online documentation: +http://liblo.sourceforge.net + +Stephen Sinclair + LibLo maintainer + + +-------------------------------------------- +2008-07-18: Release 0.25 +-------------------------------------------- + +We are pleased to present stable release 0.25 of LibLo, the +lightweight, easy to use implementation of the Open Sound Control +protocol. + +Open Sound Control (OSC) is a protocol for communication among +computers, sound synthesizers, and other multimedia devices that is +optimized for modern networking technology. + +This release brings several new features, including support for +broadcast messages, multicast UDP groups, message deserialisation, and +input validation. + +Details: +- Check for buffer overflows +- Added oscsend and oscdump command-line tools +- Added lo_message_add_varargs() for variable-argument C functions. +- Added lo_bundle_free_messages() +- Bug fix for pattern matching. (curly braces) +- Broadcast support +- Added lo_message_deserialise() +- Multicast support +- Fixes for compiling on OS X +- General bug fixes + +Contributions by: +- Camille Troillard +- Chris Hixon +- Kentaro Fukuchi +- Dave Robillard +- Nicolas Humfrey +- Stephen Sinclair + +Please feel free to download it at SourceForge: +http://downloads.sourceforge.net/liblo/liblo-0.25.tar.gz + +Or read the online documentation: +http://liblo.sourceforge.net + +Stephen Sinclair + LibLo maintainer + + +-------------------------------------------- +2007-03-21: Release 0.24 +-------------------------------------------- + +About: +LibLO is a lightweight library for handling the sending and receiving of +messages according to the Open Sound Control (OSC) protocol on POSIX +systems. + +Changes: +lo_server_get_protocol() and lo_address_get_protocol() were added. Tests +for lo_address_get_* were added to the test tool. Several compiler +warnings were fixed. The address for package bug reports was changed. +lo_blob_new() was changed to take const void*. The getnameinfo() method of +getting hostname is disabled when IPv6 is disabled. A Unix server socket is +now unlinked when it is closed. The size of a Unix socket path is checked +properly. + + +-------------------------------------------- +2006-01-27: Release 0.23 +-------------------------------------------- + +Liblo, the Lite OSC library, is an implementation of the Open Sound +Control protocol for POSIX systems*. It is written in ANSI C99 and +released under the GNU General Public Licence. It is designed to make +developing OSC applictions as easy as possible. + +http://liblo.sourceforge.net/ + + +nick. + + +Changes: + * New Maintainer (me!) + * Fixed pthread resource leak, when stopping server + * IPv6 is now disabled by default + * Fixed bug where sockets weren't closed when replying to messages + * Split off resolve_address into seperate create_socket function + * Only creates new sockets when needed + * Added lo_send_from, lo_send_message_from and lo_send_bundle_from + + +-------------------------------------------- +2005-09-09: Release 0.22 +-------------------------------------------- + +Liblo, the Lite OSC library, is an implementation of the Open Sound +Control protocol for POSIX systems*. It is written in ANSI C99 and +released under the GNU General Public Licence. It is designed to make +developing OSC applictions as easy as possible. + +http://plugin.org.uk/liblo/ + +- Steve + +Changes: + Fixes for socket leaking from Martin Habets, Dave Robillard and + Jesse Chappell + + Fix for IPV6 numerical address parsing from Dave Robillard + + Fix for char handling on bigendian machines from Martin Habets + (and others) + + New lo_server(thread)_del_method() from Martin Habets + + Endianess and arithmetic fixes for bundle timestamps from Topher + Cyll - bundle delivery is still not accurate though + + Patch to optioanlly disable IPV6 support from Lorenz Schori + +* and MS Windows, under some environment or other + + +-------------------------------------------- +2005-03-03: Release 0.18 +-------------------------------------------- + +http://www.plugin.org.uk/liblo/releases/liblo-0.18.tar.gz + +This is bugfix release and fixes a critical bug in 0.17 that bites when +trying to connect multiple clients to one server. All users of 0.17 should +upgrade as soon as possible. + +Liblo is an implementation of the Open Sound Control protocol for POSIX +systems. It is released under the GNU General Public Licence. + +http://www.plugin.org.uk/liblo/ +http://www.cnmat.berkeley.edu/OpenSoundControl/ + +- Steve + + +-------------------------------------------- +2005-02-24: Release 0.17 +-------------------------------------------- + +Liblo, the Lite OSC library, is an implementation of the Open Sound +Control [1] protocol for POSIX systems. It is written in ANSI C99 and +released under the GNU General Public Licence. It is designed to make +developing OSC applictions as easy as possible. + +http://plugin.org.uk/liblo/ + +Changes: + Patch from Jesse Chappell to fix memory leak + Ability to directly reply to the sender of a UDP message + Preliminary support for the OSC method enumeration scheme + +- Steve + +[1] http://www.cnmat.berkeley.edu/OpenSoundControl/ + + +-------------------------------------------- +2005-01-26: Release 0.16 +-------------------------------------------- + +Liblo, the Lite OSC library, is an implementation of the Open Sound +Control [1] protocol for POSIX systems. It is written in ANSI C and +released under the GNU General Public Licence. It is designed to make +developing OSC applictions as easy as possible. + +http://plugin.org.uk/liblo/ + +Changes: + Patch from Dave Robillard that fixes bundles of more than 4 messages. + Some const char * for C++ compatibility. + Added a source field to messages that represents the source from + which a message was received. Useful in method handlers to + determine which client sent the message. + Added patch from Walco van Loon and Pix that fixes a bug in the + hostname detection fallback code + +- Steve + +[1] http://www.cnmat.berkeley.edu/OpenSoundControl/ + + +-------------------------------------------- +2004-10-19: Release 0.13 +-------------------------------------------- + +liblo is an implementation of the Open Sound Control[1] protocol for POSIX +systems. It is written in ANSI C and released under the GNU General Public +Licence. It is designed to make developing OSC applictions as easy as +possible. + +http://plugin.org.uk/liblo/ + +This release adds Mac OSX compatibility fixes from Taybin Rutkin, a +memory leak fix from Jesse Chappell and methods and examples to allow +server polling from exisitng threads from Sean Bolton. Some legacy +compatobility code has been removed, but this should not affect anyone. + +Documentation has been updated to reflect the changes. +[1] http://www.cnmat.berkeley.edu/OpenSoundControl/ [website is currently + down] + +-------------------------------------------- +2004-08-19: Release 0.9 +-------------------------------------------- + +liblo is an implementation of the Open Sound Control[1] protocol for POSIX +systems. It is released under the GPL. It is written in ANSI C. + +http://plugin.org.uk/liblo/ + +This release adds: (over the last stable release, 0.5) +* Nonblocking mesage dispatcher (useful for single GUI-thread +applications, eg Qt, GTK+) +* bugfixes to URL handling (0.6 - 0.8 broke DSSI) +* UNIX domain (FIFO) socket server/client support +* TCP domain socket server/client support +* A method to stop server threads +* Better regression tests (testlo) +* Fixed memory leaks +* More documentation +* Dynamic library building fixes + +- Steve + +[1] http://www.cnmat.berkeley.edu/OpenSoundControl/ + + +-------------------------------------------- +2004-03-29: Release 0.5 +-------------------------------------------- + +liblo is a easy to use OSC (Open Sound Control) implementation written in C. + +http://plugin.org.uk/liblo/ + +See the website for docs and example code. + +Changes since last release: + bugfixes + OSC URL handling + better IPV6 support + real documentation + better example code + support for all the types listed in the specification + automatic port number selection for servers + lo_target type has been deprecated, use lo_address now + some buffer overrun checks in lo_send() + +This version is not binary compatible with the previous release. + +- Steve diff --git a/liblo/README b/liblo/README new file mode 100644 index 0000000..9c0db5e --- /dev/null +++ b/liblo/README @@ -0,0 +1,54 @@ +liblo is a lightweight library that provides an easy to use implementation of +the OSC protocol. For more information about the OSC protocol, please see: + +- http://www.cnmat.berkeley.edu/OpenSoundControl/ +- http://www.opensoundcontrol.org/ + + +The official liblo homepage is here: + +- http://liblo.sourceforge.net/ + +liblo is portable to most UNIX systems (including OS X) and Windows. It is +released under the GNU Lesser General Public Licence (LGPL). + + +--- + + +To build and install liblo, read INSTALL in the main liblo directory. +liblo is configured as a dynamically-linked library. To use liblo +in a new application, you should install liblo with "make install" +so that the liblo library can be located by your application. + +To build with MS Visual Studio on Windows, first run the premake4.exe +application in the build directory with an argument describing which +IDE you are using. This will generate project and solution files. + +See examples for example source code for a simple client and two +servers: + + - example_server.c uses lo_server_thread_start() to create +a liblo server in an separate thread. + + - nonblocking_server_example.c uses select() to wait for either +console input or OSC messages, all in a single thread. + + - example_client.c uses liblo to send OSC messages to a server. + +These examples will work without installing liblo. This is accomplished by a shell script. For example, examples/client_example is a shell +script that runs the "real" program examples/.libs/example_client. +Because of this indirection, you cannot run example_client with +a debugger. + +To debug applications using liblo, one option is to include all the liblo source code in the application rather than linking with the liblo library. For more information about this, please see the libtool's manual: + +http://www.gnu.org/software/libtool/manual.html#Debugging-executables + + +--- + + +IPv6 NOTICE: +liblo was written to support both IPv4 and IPv6, however it has caused various problems along the way because most of the currently available OSC applications +like Pd and SuperCollider doesn't listen on ipv6 sockets. IPv6 is currently disabled by default, but you can enable it using ./configure --enable-ipv6 \ No newline at end of file diff --git a/liblo/README.txt b/liblo/README.txt new file mode 100644 index 0000000..edd39c5 --- /dev/null +++ b/liblo/README.txt @@ -0,0 +1,57 @@ +README.txt -- notes on installing liblo into Nyquist +Roger B. Dannenberg +Feb, 2009 + +To help manage version skew problems, the Nyquist sources include +a copy of Liblo sources. This additional file contains notes on +how to integrate Liblo into Nyquist. + +Note that Liblo has an LGPL license. To distribute Nyquist +binaries without sources, you may have to deal with Liblo +licensing restrictions. + +How to install and build Liblo. + +On OS X (all of these steps should be unnecessary if you simply + obtain Nyquist sources from CVS and build with Xcode) + + 1. Download liblo source tree to a scratch directory. + 2. Copy the entire source tree from scratch to nyquist/liblo + 3. Don't forget to keep the following files and directories + in nyquist/liblo: + README.txt (this file) + ser-to-osc (a directory) + test-client (a directory) + 4. In the scratch directory, run "sh autogen.sh" + 5. Make nyquist/liblo/osx + 6. Copy scratch/config.h to nyquist/liblo/osx/config.h + 7. Make sure the following are on search paths in Xcode: + liblo, liblo/src, liblo/osx + 8. NOTE: Xcode will include any .h file that is in the project + sources, so remove all config.h files from the source tree, + including those in nylsf, if any. + 9. The liblo sources include , but unless + you have installed sources to a system include path, this + will not be found. Solution: check the + Always Search User Path option in the target preferences + for all configuration. +10. Add HAVE_CONFIG_H to Preprocessor Macros in + All Configurations +11. Some files in liblo that do NOT belong in the liblo library: + subtest.c +12. Note that Serial.cpp is windows only. Don't put it in the + ser-to-osc target. +13. It should now build under Xcode. + +On Linux: (all of these steps should be unnecessary if you simply + obtan Nyquist sources from CVS and build with Xcode) + + 1. Download liblo source tree to a scratch directory + 2. Copy the entire source tree from scratch to nyquist/liblo + 3. Don't forget to keep the following files and directories + in nyquist/liblo: + README.txt (this file) + ser-to-osc (a directory) + test-client (a directory) + 4. In nyquist/liblo, run "sh autogen.sh --enable-static --disable-shared" + 5. Run make diff --git a/liblo/TODO b/liblo/TODO new file mode 100644 index 0000000..7b47105 --- /dev/null +++ b/liblo/TODO @@ -0,0 +1,14 @@ +* Full bundle support [needs NTP, argh], find budle timestamp delivery + artimetic bug + +* More/better regression tests + +* More/better example code + +* Normalise URI handling [needs discussion] + +* GTK/Qt/etc. linking code [belongs in another library] + +* Rendevous/OpenWhatever (eg. howl) service discovery [low priority] + +* Think about a JACK transport layer [maybe^W probably not, low priority] diff --git a/liblo/aclocal.m4 b/liblo/aclocal.m4 new file mode 100644 index 0000000..4c9ecf8 --- /dev/null +++ b/liblo/aclocal.m4 @@ -0,0 +1,1003 @@ +# generated automatically by aclocal 1.11.1 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, +[m4_warning([this file was generated for autoconf 2.68. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# +# 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. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# 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. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 +# Free Software Foundation, Inc. +# +# 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. + +# serial 10 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# 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. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 8 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# 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. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# 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. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# 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. + +# serial 6 + +# AM_PROG_CC_C_O +# -------------- +# Like AC_PROG_CC_C_O, but changed for automake. +AC_DEFUN([AM_PROG_CC_C_O], +[AC_REQUIRE([AC_PROG_CC_C_O])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# 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. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# 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. + +# serial 4 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# 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. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# +# 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. + +# serial 2 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) diff --git a/liblo/autogen.sh b/liblo/autogen.sh new file mode 100755 index 0000000..a1b23d7 --- /dev/null +++ b/liblo/autogen.sh @@ -0,0 +1,121 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +(test -f $srcdir/configure.ac) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level package directory" + exit 1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`autoconf' installed." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && { + (libtoolize --version) < /dev/null > /dev/null 2>&1 \ + && LIBTOOLIZE=libtoolize || { + (glibtoolize --version) < /dev/null > /dev/null 2>&1 \ + && LIBTOOLIZE=glibtoolize || { + echo + echo "**Error**: You must have \`libtool' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + } + } +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`automake' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + NO_AUTOMAKE=yes +} + + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing \`aclocal'. The version of \`automake'" + echo "installed doesn't appear recent enough." + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with no arguments." + echo "If you wish to pass any to it, please specify them on the" + echo \`$0\'" command line." + echo +fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + +for coin in `find $srcdir -name configure.ac -print` +do + dr=`dirname $coin` + if test -f $dr/NO-AUTO-GEN; then + echo skipping $dr -- flagged as no auto-gen + else + echo processing $dr + ( cd $dr + + aclocalinclude="$ACLOCAL_FLAGS" + + if grep "^AM_GLIB_GNU_GETTEXT" configure.ac >/dev/null; then + echo "Creating $dr/aclocal.m4 ..." + test -r $dr/aclocal.m4 || touch $dr/aclocal.m4 + echo "Running glib-gettextize... Ignore non-fatal messages." + echo "no" | glib-gettextize --force --copy + echo "Making $dr/aclocal.m4 writable ..." + test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4 + fi + if grep "^AC_PROG_INTLTOOL" configure.ac >/dev/null; then + echo "Running intltoolize..." + intltoolize --copy --force --automake + fi + if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then + if test -z "$NO_LIBTOOLIZE" ; then + echo "Running libtoolize..." + $LIBTOOLIZE --force --copy + fi + fi + echo "Running aclocal $aclocalinclude ..." + aclocal $aclocalinclude + if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then + echo "Running autoheader..." + autoheader + fi + echo "Running automake --gnu $am_opt ..." + automake --add-missing --gnu $am_opt + echo "Running autoconf ..." + autoconf + ) + fi +done + +conf_flags="--enable-maintainer-mode" + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile. || exit 1 +else + echo Skipping configure process. +fi diff --git a/liblo/build/Makefile.am b/liblo/build/Makefile.am new file mode 100644 index 0000000..ef42042 --- /dev/null +++ b/liblo/build/Makefile.am @@ -0,0 +1,4 @@ + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = config-msvc.h lo_endian-msvc.h premake4.exe premake4.lua diff --git a/liblo/build/Makefile.in b/liblo/build/Makefile.in new file mode 100644 index 0000000..51cd74e --- /dev/null +++ b/liblo/build/Makefile.in @@ -0,0 +1,355 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = build +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LO_SO_VERSION = @LO_SO_VERSION@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in +EXTRA_DIST = config-msvc.h lo_endian-msvc.h premake4.exe premake4.lua +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu build/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu build/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/liblo/build/lo_endian-msvc.h b/liblo/build/lo_endian-msvc.h new file mode 100644 index 0000000..1f1eded --- /dev/null +++ b/liblo/build/lo_endian-msvc.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_ENDIAN_H +#define LO_ENDIAN_H + +#include + +#ifdef _MSC_VER +#define inline __inline +#define uint64_t unsigned __int64 +#define uint32_t unsigned __int32 +#else +#include +#endif + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define lo_swap16(x) htons(x) + +#define lo_swap32(x) htonl(x) + +/* These macros come from the Linux kernel */ + +#ifndef lo_swap16 +#define lo_swap16(x) \ +({ \ + uint16_t __x = (x); \ + ((uint16_t)( \ + (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \ + (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \ +}) +#warning USING UNOPTIMISED ENDIAN STUFF +#endif + +#ifndef lo_swap32 +#define lo_swap32(x) \ +({ \ + uint32_t __x = (x); \ + ((uint32_t)( \ + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ +}) +#endif + +#if 0 +#ifndef lo_swap64 +#define lo_swap64(x) \ +({ \ + uint64_t __x = (x); \ + ((uint64_t)( \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ +}) +#endif +#else + +typedef union { + uint64_t all; + struct { + uint32_t a; + uint32_t b; + } part; +} lo_split64; + +static inline uint64_t lo_swap64(uint64_t x) +{ + lo_split64 in, out; + + in.all = x; + out.part.a = lo_swap32(in.part.b); + out.part.b = lo_swap32(in.part.a); + + return out.all; +} +#endif + +/* Host to OSC and OSC to Host conversion macros */ + +#if 0 +#define lo_htoo16(x) (x) +#define lo_htoo32(x) (x) +#define lo_htoo64(x) (x) +#define lo_otoh16(x) (x) +#define lo_otoh32(x) (x) +#define lo_otoh64(x) (x) +#else +#define lo_htoo16 lo_swap16 +#define lo_htoo32 lo_swap32 +#define lo_htoo64 lo_swap64 +#define lo_otoh16 lo_swap16 +#define lo_otoh32 lo_swap32 +#define lo_otoh64 lo_swap64 +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef _MSC_VER +#undef inline +#undef uint64_t +#undef uint32_t +#endif + +#endif + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/build/premake4.exe b/liblo/build/premake4.exe new file mode 100644 index 0000000..adc3257 Binary files /dev/null and b/liblo/build/premake4.exe differ diff --git a/liblo/build/premake4.lua b/liblo/build/premake4.lua new file mode 100644 index 0000000..324ddfb --- /dev/null +++ b/liblo/build/premake4.lua @@ -0,0 +1,210 @@ +---------------------------------------------------------------------- +-- Premake4 configuration script for LibLo +-- Adapted from ODE's build script by Jason Perkins. +-- For more information on Premake: http://industriousone.com/premake +---------------------------------------------------------------------- + +---------------------------------------------------------------------- +-- Configuration options +---------------------------------------------------------------------- + + -- always clean all of the optional components and toolsets + if _ACTION == "clean" then + for action in pairs(premake.actions) do + os.rmdir(action) + end + end + + + +---------------------------------------------------------------------- +-- The solution, and solution-wide settings +---------------------------------------------------------------------- + + solution "liblo" + + language "C" + location ( _OPTIONS["to"] or _ACTION ) + + includedirs { + "../lo", + "../src" + } + + -- define all the possible build configurations + configurations { + "DebugDLL", "ReleaseDLL", + "DebugLib", "ReleaseLib", + } + + configuration { "Debug*" } + defines { "_DEBUG" } + flags { "Symbols" } + + configuration { "Release*" } + flags { "OptimizeSpeed", "NoFramePointer" } + + configuration { "Windows" } + defines { "WIN32" } + + -- give each configuration a unique output directory + for _, name in ipairs(configurations()) do + configuration { name } + targetdir ( "../lib/" .. name ) + end + + -- disable Visual Studio security warnings + configuration { "vs*" } + defines { "_CRT_SECURE_NO_DEPRECATE" } + + -- tell source to use config.h + configuration { "vs*" } + defines { "HAVE_CONFIG_H" } + + -- don't remember why we had to do this (from ODE) + configuration { "vs2002 or vs2003", "*Lib" } + flags { "StaticRuntime" } + +---------------------------------------------------------------------- +-- Write a custom to .., based on the supplied flags +---------------------------------------------------------------------- + +-- First get the version number from "configure.ac" -- + + io.input("../configure.ac") + text = io.read("*all") + io.close() + text = string.sub(text,string.find(text, "AC_INIT.+")) + version = string.sub(text,string.find(text, "%d+%.%d+")) + +-- Replace it in "config.h" -- + + io.input("config-msvc.h") + local text = io.read("*all") + + text = string.gsub(text, '/%*VERSION%*/', '"'..version..'"') + + io.output("../config.h") + io.write(text) + io.close() + +---------------------------------------------------------------------- +-- Copy to ../lo +---------------------------------------------------------------------- + + io.input("lo_endian-msvc.h") + io.output("../lo/lo_endian.h") + local text = io.read("*all") + io.write(text) + io.close() + +---------------------------------------------------------------------- +-- The LibLo library project +---------------------------------------------------------------------- + + project "liblo" + + kind "StaticLib" + location ( _OPTIONS["to"] or _ACTION ) + + includedirs { + "..", + } + + files { + "../src/*.c", + "../src/*.h", + "../lo/*.h", + "../src/liblo.def", + } + + excludes { + "../src/testlo.c", + "../src/subtest.c", + "../src/tools", + } + + configuration { "windows" } + links { "user32", + "wsock32", + "ws2_32", + "pthreadVC2", + } + + configuration { "*Lib" } + kind "StaticLib" + defines "LIBLO_LIB" + + configuration { "*DLL" } + kind "SharedLib" + defines "LIBLO_DLL" + + configuration { "Debug*" } + targetname "liblo_d" + + configuration { "Release*" } + targetname "liblo" + + +---------------------------------------------------------------------- +-- The automated test application +---------------------------------------------------------------------- + + + project "testlo" + + kind "ConsoleApp" + location ( _OPTIONS["to"] or _ACTION ) + links { "user32", + "wsock32", + "ws2_32", + "pthreadVC2", + } + + includedirs { + "..", + } + + files { + "../src/testlo.c", + } + + configuration { "DebugDLL" } + links { "liblo_d" } + libdirs { "../lib/debugdll" } + + configuration { "DebugLib" } + links { "liblo_d" } + libdirs { "../lib/debuglib" } + + configuration { "Release*" } + links { "liblo" } + + project "subtest" + + kind "ConsoleApp" + location ( _OPTIONS["to"] or _ACTION ) + links { "user32", + "wsock32", + "ws2_32", + "pthreadVC2", + } + + includedirs { + "..", + } + + files { + "../src/subtest.c", + } + + configuration { "DebugDLL" } + links { "liblo_d" } + libdirs { "../lib/debugdll" } + + configuration { "DebugLib" } + links { "liblo_d" } + libdirs { "../lib/debuglib" } + + configuration { "Release*" } + links { "liblo" } diff --git a/liblo/build/vs2008/config-msvc.h b/liblo/build/vs2008/config-msvc.h new file mode 100644 index 0000000..96fbb0b --- /dev/null +++ b/liblo/build/vs2008/config-msvc.h @@ -0,0 +1,92 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define this to enable ipv6. */ +/* #undef ENABLE_IPV6 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if inet_aton() is available. */ +/* #undef HAVE_INET_ATON */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +/* #undef HAVE_LIBPTHREAD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IN_H */ + +/* Define to 1 if poll() is available. */ +/* #undef HAVE_POLL */ + +/* Define to 1 if select() is available. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* If machine is bigendian */ +#define LO_BIGENDIAN "0" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "liblo" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "liblo-devel@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "liblo" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "liblo " /*VERSION*/ + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "liblo" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION /*VERSION*/ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION /*VERSION*/ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/liblo/build/vs2008/config.h b/liblo/build/vs2008/config.h new file mode 100644 index 0000000..cba3f6a --- /dev/null +++ b/liblo/build/vs2008/config.h @@ -0,0 +1,2 @@ +// for windows compilation, here is a special config file and location +#include "config-msvc.h" diff --git a/liblo/build/vs2008/liblo.suo b/liblo/build/vs2008/liblo.suo new file mode 100644 index 0000000..ccc7ef7 Binary files /dev/null and b/liblo/build/vs2008/liblo.suo differ diff --git a/liblo/build/vs2008/liblo.vcproj b/liblo/build/vs2008/liblo.vcproj new file mode 100644 index 0000000..89c47c9 --- /dev/null +++ b/liblo/build/vs2008/liblo.vcproj @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblo/build/vs2008/subtest.vcproj b/liblo/build/vs2008/subtest.vcproj new file mode 100644 index 0000000..c95b3a8 --- /dev/null +++ b/liblo/build/vs2008/subtest.vcproj @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblo/build/vs2008/testlo.vcproj b/liblo/build/vs2008/testlo.vcproj new file mode 100644 index 0000000..a1392c7 --- /dev/null +++ b/liblo/build/vs2008/testlo.vcproj @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblo/compile b/liblo/compile new file mode 100755 index 0000000..1b1d232 --- /dev/null +++ b/liblo/compile @@ -0,0 +1,142 @@ +#! /bin/sh +# Wrapper for compilers which do not understand `-c -o'. + +scriptversion=2005-05-14.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand `-c -o'. +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file `INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; +esac + +ofile= +cfile= +eat= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we strip `-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no `-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # `.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` + +# Create the lock directory. +# Note: use `[/.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/liblo/config.guess b/liblo/config.guess new file mode 100755 index 0000000..da83314 --- /dev/null +++ b/liblo/config.guess @@ -0,0 +1,1561 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2009-04-27' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd | genuineintel) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/liblo/config.h.in b/liblo/config.h.in new file mode 100644 index 0000000..63e023a --- /dev/null +++ b/liblo/config.h.in @@ -0,0 +1,98 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define this to enable ipv6. */ +#undef ENABLE_IPV6 + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if inet_aton() is available. */ +#undef HAVE_INET_ATON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if poll() is available. */ +#undef HAVE_POLL + +/* Define to 1 if select() is available. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/liblo/config.sub b/liblo/config.sub new file mode 100755 index 0000000..a39437d --- /dev/null +++ b/liblo/config.sub @@ -0,0 +1,1686 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2009-04-17' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/liblo/configure b/liblo/configure new file mode 100755 index 0000000..70fb47a --- /dev/null +++ b/liblo/configure @@ -0,0 +1,13468 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for liblo 0.26. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: liblo-devel@lists.sourceforge.net about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$lt_ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +ECHO=${lt_ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<_LT_EOF +$* +_LT_EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$lt_ECHO"; then + if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if { echo_test_string=`eval $cmd`; } 2>/dev/null && + { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null + then + break + fi + done + fi + + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : + else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$ECHO" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + ECHO='print -r' + elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + ECHO='printf %s\n' + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + ECHO="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + ECHO=echo + fi + fi + fi + fi + fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +lt_ECHO=$ECHO +if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='liblo' +PACKAGE_TARNAME='liblo' +PACKAGE_VERSION='0.26' +PACKAGE_STRING='liblo 0.26' +PACKAGE_BUGREPORT='liblo-devel@lists.sourceforge.net' +PACKAGE_URL='' + +ac_unique_file="src/address.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +DOXYGEN +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +lt_ECHO +RANLIB +AR +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +LO_SO_VERSION +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_static +enable_shared +enable_ipv6 +enable_dependency_tracking +with_pic +enable_fast_install +with_gnu_ld +enable_libtool_lock +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures liblo 0.26 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/liblo] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of liblo 0.26:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-ipv6 Enable ipv6 support + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +liblo configure 0.26 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------------------ ## +## Report this to liblo-devel@lists.sourceforge.net ## +## ------------------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by liblo $as_me 0.26, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# libtool version: current:revision:age +# +# If the library source code has changed at all since the last update, then +# increment revision (`c:r:a' becomes `c:r+1:a'). +# +# If any interfaces have been added, removed, or changed since the last update, +# increment current, and set revision to 0. +# +# If any interfaces have been added since the last public release, then +# increment age. +# +# If any interfaces have been removed since the last public release, then set +# age to 0. +LO_SO_VERSION=7:0:0 + + + +ac_config_headers="$ac_config_headers config.h" + + +am__api_version='1.11' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='liblo' + VERSION='0.26' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + + +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=no +fi + + + + + + + + + +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# disable support for ipv6. +# Check whether --enable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then : + enableval=$enable_ipv6; want_ipv6=yes +fi + +if test "$want_ipv6" = "yes"; then + +$as_echo "#define ENABLE_IPV6 1" >>confdefs.h + +fi + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.2.6b' +macro_revision='1.3017' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$ac_tool_prefix"; then + for ac_prog in "dumpbin -symbols" "link -dump -symbols" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in "dumpbin -symbols" "link -dump -symbols" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:4634: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:4637: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:4640: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ + = "XX$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 5846 "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + + + + + + + + + + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7315: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7319: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl*) + # IBM XL C 8.0/Fortran 10.1 on PPC + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 +$as_echo "$lt_prog_compiler_pic" >&6; } + + + + + + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7654: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7658: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7759: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:7763: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7814: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:7818: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + 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 + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # 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. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + 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 + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag= + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + 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 + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + 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 + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + 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 + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + 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=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=echo + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + 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 + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # 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 "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + 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_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # 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*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo(void) {} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + 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 + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 +$as_echo "$archive_cmds_need_lc" >&6; } + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 10184 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 10280 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +if test "x$CC" != xcc; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 +$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 +$as_echo_n "checking whether cc understands -c and -o together... " >&6; } +fi +set dummy $CC; ac_cc=`$as_echo "$2" | + sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' +rm -f conftest2.* +if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.$ac_ext >&5' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' + rm -f conftest2.* + if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f core conftest* + +fi +if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h + +fi + +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi + + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DOXYGEN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DOXYGEN"; then + ac_cv_prog_DOXYGEN="$DOXYGEN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DOXYGEN="doc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DOXYGEN=$ac_cv_prog_DOXYGEN +if test -n "$DOXYGEN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5 +$as_echo "$DOXYGEN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + +# Checks for libraries. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 +$as_echo_n "checking for pthread_create in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_create=yes +else + ac_cv_lib_pthread_pthread_create=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } +if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing recvfrom" >&5 +$as_echo_n "checking for library containing recvfrom... " >&6; } +if ${ac_cv_search_recvfrom+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char recvfrom (); +int +main () +{ +return recvfrom (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_recvfrom=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_recvfrom+:} false; then : + break +fi +done +if ${ac_cv_search_recvfrom+:} false; then : + +else + ac_cv_search_recvfrom=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_recvfrom" >&5 +$as_echo "$ac_cv_search_recvfrom" >&6; } +ac_res=$ac_cv_search_recvfrom +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +ac_fn_c_check_func "$LINENO" "log" "ac_cv_func_log" +if test "x$ac_cv_func_log" = xyes; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for log in -lm" >&5 +$as_echo_n "checking for log in -lm... " >&6; } +if ${ac_cv_lib_m_log+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char log (); +int +main () +{ +return log (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_log=yes +else + ac_cv_lib_m_log=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_log" >&5 +$as_echo "$ac_cv_lib_m_log" >&6; } +if test "x$ac_cv_lib_m_log" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + +fi + + +# Checks for header files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +for ac_header in netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + +# Check for features +ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select" +if test "x$ac_cv_func_select" = xyes; then : + +$as_echo "#define HAVE_SELECT 1" >>confdefs.h + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for select in ws2_32" >&5 +$as_echo_n "checking for select in ws2_32... " >&6; } + LIBS="$LIBS -lws2_32" + # some winsock2 functions require XP, so WINNT=0x501 + CFLAGS="$CFLAGS -DWIN32 -D_WIN32_WINNT=0x501" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +select(0,0,0,0,0) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_SELECT 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + +ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll" +if test "x$ac_cv_func_poll" = xyes; then : + +$as_echo "#define HAVE_POLL 1" >>confdefs.h + +fi + +ac_fn_c_check_func "$LINENO" "inet_aton" "ac_cv_func_inet_aton" +if test "x$ac_cv_func_inet_aton" = xyes; then : + +$as_echo "#define HAVE_INET_ATON 1" >>confdefs.h + +fi + + +# to make Windows compilation easier, lo/lo_endian.h uses conditional +# compilation rather than configure to determine byte order + +#AC_C_BIGENDIAN([LO_BIGENDIAN="1"], [LO_BIGENDIAN="0"]) +#AC_DEFINE_UNQUOTED(LO_BIGENDIAN, "$LO_BIGENDIAN", [If machine is bigendian]) +#AC_SUBST(LO_BIGENDIAN) + +ac_config_files="$ac_config_files Makefile src/Makefile src/tools/Makefile examples/Makefile lo/Makefile lo/lo_endian.h liblo.pc doc/Makefile doc/reference.doxygen build/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by liblo $as_me 0.26, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +liblo config.status 0.26 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' +macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' +macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' +pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' +host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' +host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' +host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' +build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' +build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' +build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' +SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' +Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' +GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' +EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' +FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' +LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' +NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' +LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' +ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' +exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' +lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' +reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' +AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' +STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' +RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' +compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' +GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' +SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' +ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' +need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' +LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' +libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' +fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' +version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' +runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' +libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' +soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' +old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' +striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# Quote evaled strings. +for var in SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +AR \ +AR_FLAGS \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +SHELL \ +ECHO \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_wl \ +lt_prog_compiler_pic \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +fix_srcfile_path \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Fix-up fallback echo if it was mangled by the above quoting rules. +case \$lt_ECHO in +*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` + ;; +esac + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/tools/Makefile") CONFIG_FILES="$CONFIG_FILES src/tools/Makefile" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "lo/Makefile") CONFIG_FILES="$CONFIG_FILES lo/Makefile" ;; + "lo/lo_endian.h") CONFIG_FILES="$CONFIG_FILES lo/lo_endian.h" ;; + "liblo.pc") CONFIG_FILES="$CONFIG_FILES liblo.pc" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/reference.doxygen") CONFIG_FILES="$CONFIG_FILES doc/reference.doxygen" ;; + "build/Makefile") CONFIG_FILES="$CONFIG_FILES build/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that does not interpret backslashes. +ECHO=$lt_ECHO + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $* )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[^=]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$@"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1+=\$2" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1=\$$1\$2" +} + +_LT_EOF + ;; + esac + + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/liblo/configure.ac b/liblo/configure.ac new file mode 100644 index 0000000..5781522 --- /dev/null +++ b/liblo/configure.ac @@ -0,0 +1,90 @@ +AC_PREREQ(2.57) + +AC_INIT([liblo], [0.26], [liblo-devel@lists.sourceforge.net]) + +# libtool version: current:revision:age +# +# If the library source code has changed at all since the last update, then +# increment revision (`c:r:a' becomes `c:r+1:a'). +# +# If any interfaces have been added, removed, or changed since the last update, +# increment current, and set revision to 0. +# +# If any interfaces have been added since the last public release, then +# increment age. +# +# If any interfaces have been removed since the last public release, then set +# age to 0. +LO_SO_VERSION=7:0:0 + +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_SRCDIR([src/address.c]) +AM_CONFIG_HEADER([config.h]) + +AM_INIT_AUTOMAKE + +AC_ENABLE_STATIC(no) +AC_ENABLE_SHARED(yes) +AC_SUBST(LO_SO_VERSION) + +# disable support for ipv6. +AC_ARG_ENABLE(ipv6, [ --enable-ipv6 Enable ipv6 support],want_ipv6=yes,) +if test "$want_ipv6" = "yes"; then + AC_DEFINE(ENABLE_IPV6, 1, Define this to enable ipv6.) +fi + +# Checks for programs. +AC_PROG_CC +AM_PROG_LIBTOOL +AM_PROG_CC_C_O +AC_CHECK_PROG([DOXYGEN], [doxygen], [doc], []) +AC_SUBST(DOXYGEN) + +# Checks for libraries. +AC_CHECK_LIB([pthread], [pthread_create]) +AC_SEARCH_LIBS([recvfrom], [socket]) +AC_CHECK_FUNC([log], [], [AC_CHECK_LIB([m],[log])]) + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Check for features +AC_CHECK_FUNC([select], [AC_DEFINE(HAVE_SELECT, [1], [Define to 1 if select() is available.])], [ + AC_MSG_CHECKING([for select in ws2_32]) + LIBS="$LIBS -lws2_32" + # some winsock2 functions require XP, so WINNT=0x501 + CFLAGS="$CFLAGS -DWIN32 -D_WIN32_WINNT=0x501" + AC_TRY_LINK([#include ], + [select(0,0,0,0,0)], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SELECT, [1], [Define to 1 if select() is available.])], + [AC_MSG_RESULT(no)]) +]) +AC_CHECK_FUNC([poll], [AC_DEFINE(HAVE_POLL, [1], [Define to 1 if poll() is available.])]) +AC_CHECK_FUNC([inet_aton], [AC_DEFINE(HAVE_INET_ATON, [1], [Define to 1 if inet_aton() is available.])]) + +# to make Windows compilation easier, lo/lo_endian.h uses conditional +# compilation rather than configure to determine byte order + +#AC_C_BIGENDIAN([LO_BIGENDIAN="1"], [LO_BIGENDIAN="0"]) +#AC_DEFINE_UNQUOTED(LO_BIGENDIAN, "$LO_BIGENDIAN", [If machine is bigendian]) +#AC_SUBST(LO_BIGENDIAN) + +AC_CONFIG_FILES([ + Makefile + src/Makefile + src/tools/Makefile + examples/Makefile + lo/Makefile + lo/lo_endian.h + liblo.pc + doc/Makefile + doc/reference.doxygen + build/Makefile +]) +AC_OUTPUT() diff --git a/liblo/depcomp b/liblo/depcomp new file mode 100755 index 0000000..e5f9736 --- /dev/null +++ b/liblo/depcomp @@ -0,0 +1,589 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2007-03-29.01 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software +# Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/liblo/doc/Makefile.am b/liblo/doc/Makefile.am new file mode 100644 index 0000000..4fa11cc --- /dev/null +++ b/liblo/doc/Makefile.am @@ -0,0 +1,32 @@ +## Process this file with automake to produce Makefile.in +MAINTAINERCLEANFILES=Makefile.in + +CLEANFILES=doxygen-build.stamp + +DOX=reference.doxygen + +EXTRA_DIST= + +INSTIMAGES=html/doxygen.png + +DOC_STAMPS=html-build.stamp + +DOC_DIR=$(HTML_DIR) + +all-local: doxygen-build.stamp + +doxygen-build.stamp: $(DOX) ../lo/lo.h ../lo/lo_types.h ../lo/lo_lowlevel.h \ + ../lo/lo_osc_types.h + @echo '*** Running doxygen ***' + doxygen $(DOX) + touch doxygen-build.stamp + +clean-local: + rm -f *~ *.bak $(DOC_STAMPS) || true + if test -d html; then rm -fr html; fi + if test -d latex; then rm -fr latex; fi + if test -d man; then rm -fr man; fi + +distclean-local: clean + rm -f *.stamp || true + if test -d html; then rm -rf html; fi diff --git a/liblo/doc/Makefile.in b/liblo/doc/Makefile.in new file mode 100644 index 0000000..2f208c0 --- /dev/null +++ b/liblo/doc/Makefile.in @@ -0,0 +1,383 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/reference.doxygen.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = reference.doxygen +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LO_SO_VERSION = @LO_SO_VERSION@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in +CLEANFILES = doxygen-build.stamp +DOX = reference.doxygen +EXTRA_DIST = +INSTIMAGES = html/doxygen.png +DOC_STAMPS = html-build.stamp +DOC_DIR = $(HTML_DIR) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +reference.doxygen: $(top_builddir)/config.status $(srcdir)/reference.doxygen.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local distclean distclean-generic \ + distclean-libtool distclean-local distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +all-local: doxygen-build.stamp + +doxygen-build.stamp: $(DOX) ../lo/lo.h ../lo/lo_types.h ../lo/lo_lowlevel.h \ + ../lo/lo_osc_types.h + @echo '*** Running doxygen ***' + doxygen $(DOX) + touch doxygen-build.stamp + +clean-local: + rm -f *~ *.bak $(DOC_STAMPS) || true + if test -d html; then rm -fr html; fi + if test -d latex; then rm -fr latex; fi + if test -d man; then rm -fr man; fi + +distclean-local: clean + rm -f *.stamp || true + if test -d html; then rm -rf html; fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/liblo/doc/reference.doxygen b/liblo/doc/reference.doxygen new file mode 100644 index 0000000..1dff22c --- /dev/null +++ b/liblo/doc/reference.doxygen @@ -0,0 +1,1083 @@ +# Doxyfile 1.3.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = liblo + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.26 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper +# language. The default language is English, other supported languages +# are: Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, +# Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Norwegian, Polish, Portuguese, Romanian, Russian, Serbian, +# Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../lo/lo.h ../lo/lo_types.h ../lo/lo_osc_types.h ../lo/lo_lowlevel.h + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are +# excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = . + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output dir. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = A4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are +# alone on a line, have an all uppercase name, and do not end with a +# semicolon. Such function macros are typically used for boiler-plate +# code, and will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes +# with base or super classes. Setting the tag to NO turns the diagrams +# off. Note that this option is superceded by the HAVE_DOT option +# below. This is only a fallback. It is recommended to install and use +# dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similiar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of +# the graphs generated by dot. A depth value of 3 means that only +# nodes reachable from the root by following a path via at most 3 +# edges will be shown. Nodes that lay further from the root node will +# be omitted. Note that setting this option to 1 or 2 may greatly +# reduce the computation time needed for large code bases. Also note +# that a graph may be further truncated if the graph's image +# dimensions are not sufficient to fit the graph (see +# MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the +# depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/liblo/doc/reference.doxygen.in b/liblo/doc/reference.doxygen.in new file mode 100644 index 0000000..50142cc --- /dev/null +++ b/liblo/doc/reference.doxygen.in @@ -0,0 +1,1083 @@ +# Doxyfile 1.3.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = liblo + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper +# language. The default language is English, other supported languages +# are: Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, +# Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Norwegian, Polish, Portuguese, Romanian, Russian, Serbian, +# Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @top_srcdir@/lo/lo.h @top_srcdir@/lo/lo_types.h @top_srcdir@/lo/lo_osc_types.h @top_srcdir@/lo/lo_lowlevel.h + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are +# excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = . + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output dir. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = A4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are +# alone on a line, have an all uppercase name, and do not end with a +# semicolon. Such function macros are typically used for boiler-plate +# code, and will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes +# with base or super classes. Setting the tag to NO turns the diagrams +# off. Note that this option is superceded by the HAVE_DOT option +# below. This is only a fallback. It is recommended to install and use +# dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similiar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of +# the graphs generated by dot. A depth value of 3 means that only +# nodes reachable from the root by following a path via at most 3 +# edges will be shown. Nodes that lay further from the root node will +# be omitted. Note that setting this option to 1 or 2 may greatly +# reduce the computation time needed for large code bases. Also note +# that a graph may be further truncated if the graph's image +# dimensions are not sufficient to fit the graph (see +# MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the +# depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/liblo/examples/Makefile.am b/liblo/examples/Makefile.am new file mode 100644 index 0000000..d0e9675 --- /dev/null +++ b/liblo/examples/Makefile.am @@ -0,0 +1,13 @@ +MAINTAINERCLEANFILES = Makefile.in + +noinst_PROGRAMS = example_server example_client nonblocking_server_example +AM_CFLAGS = -Wall -I@top_srcdir@ + +example_server_SOURCES = example_server.c +example_server_LDADD = ../src/liblo.la + +example_client_SOURCES = example_client.c +example_client_LDADD = ../src/liblo.la + +nonblocking_server_example_SOURCES = nonblocking_server_example.c +nonblocking_server_example_LDADD = ../src/liblo.la diff --git a/liblo/examples/Makefile.in b/liblo/examples/Makefile.in new file mode 100644 index 0000000..ccc5212 --- /dev/null +++ b/liblo/examples/Makefile.in @@ -0,0 +1,496 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = example_server$(EXEEXT) example_client$(EXEEXT) \ + nonblocking_server_example$(EXEEXT) +subdir = examples +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_example_client_OBJECTS = example_client.$(OBJEXT) +example_client_OBJECTS = $(am_example_client_OBJECTS) +example_client_DEPENDENCIES = ../src/liblo.la +am_example_server_OBJECTS = example_server.$(OBJEXT) +example_server_OBJECTS = $(am_example_server_OBJECTS) +example_server_DEPENDENCIES = ../src/liblo.la +am_nonblocking_server_example_OBJECTS = \ + nonblocking_server_example.$(OBJEXT) +nonblocking_server_example_OBJECTS = \ + $(am_nonblocking_server_example_OBJECTS) +nonblocking_server_example_DEPENDENCIES = ../src/liblo.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(example_client_SOURCES) $(example_server_SOURCES) \ + $(nonblocking_server_example_SOURCES) +DIST_SOURCES = $(example_client_SOURCES) $(example_server_SOURCES) \ + $(nonblocking_server_example_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LO_SO_VERSION = @LO_SO_VERSION@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS = -Wall -I@top_srcdir@ +example_server_SOURCES = example_server.c +example_server_LDADD = ../src/liblo.la +example_client_SOURCES = example_client.c +example_client_LDADD = ../src/liblo.la +nonblocking_server_example_SOURCES = nonblocking_server_example.c +nonblocking_server_example_LDADD = ../src/liblo.la +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu examples/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +example_client$(EXEEXT): $(example_client_OBJECTS) $(example_client_DEPENDENCIES) + @rm -f example_client$(EXEEXT) + $(LINK) $(example_client_OBJECTS) $(example_client_LDADD) $(LIBS) +example_server$(EXEEXT): $(example_server_OBJECTS) $(example_server_DEPENDENCIES) + @rm -f example_server$(EXEEXT) + $(LINK) $(example_server_OBJECTS) $(example_server_LDADD) $(LIBS) +nonblocking_server_example$(EXEEXT): $(nonblocking_server_example_OBJECTS) $(nonblocking_server_example_DEPENDENCIES) + @rm -f nonblocking_server_example$(EXEEXT) + $(LINK) $(nonblocking_server_example_OBJECTS) $(nonblocking_server_example_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example_client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example_server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonblocking_server_example.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/liblo/examples/example_client.c b/liblo/examples/example_client.c new file mode 100644 index 0000000..40d52e7 --- /dev/null +++ b/liblo/examples/example_client.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2004 Steve Harris, Uwe Koloska + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include + +#include "lo/lo.h" + +const char testdata[5] = "ABCDE"; + +int main(int argc, char *argv[]) +{ + /* build a blob object from some data */ + lo_blob btest = lo_blob_new(sizeof(testdata), testdata); + + /* an address to send messages to. sometimes it is better to let the server + * pick a port number for you by passing NULL as the last argument */ +// lo_address t = lo_address_new_from_url( "osc.unix://localhost/tmp/mysocket" ); + lo_address t = lo_address_new(NULL, "7770"); + + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'q') { + /* send a message with no arguments to the path /quit */ + if (lo_send(t, "/quit", NULL) == -1) { + printf("OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t)); + } + } else { + /* send a message to /foo/bar with two float arguments, report any + * errors */ + if (lo_send(t, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) { + printf("OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t)); + } + + /* send a message to /a/b/c/d with a mixtrure of float and string + * arguments */ + lo_send(t, "/a/b/c/d", "sfsff", "one", 0.12345678f, "three", + -0.00000023001f, 1.0); + + /* send a 'blob' object to /a/b/c/d */ + lo_send(t, "/a/b/c/d", "b", btest); + + /* send a jamin scene change instruction with a 32bit integer argument */ + lo_send(t, "/jamin/scene", "i", 2); + } + + return 0; +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/examples/example_server.c b/liblo/examples/example_server.c new file mode 100644 index 0000000..3ea1396 --- /dev/null +++ b/liblo/examples/example_server.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2004 Steve Harris, Uwe Koloska + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include + +#include "lo/lo.h" + +int done = 0; + +void error(int num, const char *m, const char *path); + +int generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, void *user_data); + +int foo_handler(const char *path, const char *types, lo_arg **argv, int argc, + void *data, void *user_data); + +int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, + void *data, void *user_data); + +int main() +{ + /* start a new server on port 7770 */ + lo_server_thread st = lo_server_thread_new("7770", error); + + /* add method that will match any path and args */ + lo_server_thread_add_method(st, NULL, NULL, generic_handler, NULL); + + /* add method that will match the path /foo/bar, with two numbers, coerced + * to float and int */ + lo_server_thread_add_method(st, "/foo/bar", "fi", foo_handler, NULL); + + /* add method that will match the path /quit with no args */ + lo_server_thread_add_method(st, "/quit", "", quit_handler, NULL); + + lo_server_thread_start(st); + + while (!done) { +#ifdef WIN32 + Sleep(1); +#else + usleep(1000); +#endif + } + + lo_server_thread_free(st); + + return 0; +} + +void error(int num, const char *msg, const char *path) +{ + printf("liblo server error %d in path %s: %s\n", num, path, msg); + fflush(stdout); +} + +/* catch any incoming messages and display them. returning 1 means that the + * message has not been fully handled and the server should try other methods */ +int generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, void *user_data) +{ + int i; + + printf("path: <%s>\n", path); + for (i=0; if, argv[1]->i); + fflush(stdout); + + return 0; +} + +int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, + void *data, void *user_data) +{ + done = 1; + printf("quiting\n\n"); + fflush(stdout); + + return 0; +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/examples/nonblocking_server_example.c b/liblo/examples/nonblocking_server_example.c new file mode 100644 index 0000000..92d625c --- /dev/null +++ b/liblo/examples/nonblocking_server_example.c @@ -0,0 +1,197 @@ +/* + * nonblocking_server_example.c + * + * This code demonstrates two methods of monitoring both an lo_server + * and other I/O from a single thread. + * + * Copyright (C) 2004 Steve Harris, Uwe Koloska + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include + +#include "lo/lo.h" + +int done = 0; + +void error(int num, const char *m, const char *path); + +int generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, void *user_data); + +int foo_handler(const char *path, const char *types, lo_arg **argv, int argc, + void *data, void *user_data); + +int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, + void *data, void *user_data); + +void read_stdin(void); + +int main() +{ + int lo_fd; + fd_set rfds; + struct timeval tv; + int retval; + + /* start a new server on port 7770 */ + lo_server s = lo_server_new("7770", error); + + /* add method that will match any path and args */ + lo_server_add_method(s, NULL, NULL, generic_handler, NULL); + + /* add method that will match the path /foo/bar, with two numbers, coerced + * to float and int */ + lo_server_add_method(s, "/foo/bar", "fi", foo_handler, NULL); + + /* add method that will match the path /quit with no args */ + lo_server_add_method(s, "/quit", "", quit_handler, NULL); + + /* get the file descriptor of the server socket, if supported */ + lo_fd = lo_server_get_socket_fd(s); + + if (lo_fd > 0) { + + /* select() on lo_server fd is supported, so we'll use select() + * to watch both stdin and the lo_server fd. */ + + do { + + FD_ZERO(&rfds); +#ifndef WIN32 + FD_SET(0, &rfds); /* stdin */ +#endif + FD_SET(lo_fd, &rfds); + + retval = select(lo_fd + 1, &rfds, NULL, NULL, NULL); /* no timeout */ + + if (retval == -1) { + + printf("select() error\n"); + exit(1); + + } else if (retval > 0) { + + if (FD_ISSET(0, &rfds)) { + + read_stdin(); + + } + if (FD_ISSET(lo_fd, &rfds)) { + + lo_server_recv_noblock(s, 0); + + } + } + + } while (!done); + + } else { + + /* lo_server protocol does not support select(), so we'll watch + * stdin while polling the lo_server. */ +#ifdef WIN32 + printf("non-blocking input from stdin not supported under Windows\n"); + exit(1); +#else + do { + + FD_ZERO(&rfds); + FD_SET(0, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 10000; + + retval = select(1, &rfds, NULL, NULL, &tv); /* timeout every 10ms */ + + if (retval == -1) { + + printf("select() error\n"); + exit(1); + + } else if (retval > 0 && FD_ISSET(0, &rfds)) { + + read_stdin(); + + } + + lo_server_recv_noblock(s, 0); + + } while (!done); +#endif + } + + return 0; +} + +void error(int num, const char *msg, const char *path) +{ + printf("liblo server error %d in path %s: %s\n", num, path, msg); +} + +/* catch any incoming messages and display them. returning 1 means that the + * message has not been fully handled and the server should try other methods */ +int generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, void *user_data) +{ + int i; + + printf("path: <%s>\n", path); + for (i=0; if, argv[1]->i); + fflush(stdout); + + return 0; +} + +int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, + void *data, void *user_data) +{ + done = 1; + printf("quiting\n\n"); + + return 0; +} + +void read_stdin(void) +{ + char buf[256]; + int len = read(0, buf, 256); + if (len > 0) { + printf("stdin: "); + fwrite(buf, len, 1, stdout); + printf("\n"); + fflush(stdout); + } +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/install-sh b/liblo/install-sh new file mode 100755 index 0000000..6781b98 --- /dev/null +++ b/liblo/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/liblo/liblo.pc.in b/liblo/liblo.pc.in new file mode 100644 index 0000000..4029d9b --- /dev/null +++ b/liblo/liblo.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: liblo +Version: @PACKAGE_VERSION@ +Description: A lightweight OSC server/client library +Libs: -L${libdir} -llo -lpthread +Cflags: -I${includedir} diff --git a/liblo/lo/Makefile.am b/liblo/lo/Makefile.am new file mode 100644 index 0000000..d24ce25 --- /dev/null +++ b/liblo/lo/Makefile.am @@ -0,0 +1,4 @@ +libloincludedir = $(includedir)/lo + +libloinclude_HEADERS = lo_errors.h lo.h lo_lowlevel.h lo_throw.h lo_types.h \ + lo_osc_types.h lo_endian.h lo_macros.h diff --git a/liblo/lo/Makefile.in b/liblo/lo/Makefile.in new file mode 100644 index 0000000..57cd4ea --- /dev/null +++ b/liblo/lo/Makefile.in @@ -0,0 +1,456 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lo +DIST_COMMON = $(libloinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/lo_endian.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = lo_endian.h +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libloincludedir)" +HEADERS = $(libloinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LO_SO_VERSION = @LO_SO_VERSION@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +libloincludedir = $(includedir)/lo +libloinclude_HEADERS = lo_errors.h lo.h lo_lowlevel.h lo_throw.h lo_types.h \ + lo_osc_types.h lo_endian.h lo_macros.h + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lo/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lo/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +lo_endian.h: $(top_builddir)/config.status $(srcdir)/lo_endian.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-libloincludeHEADERS: $(libloinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(libloincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libloincludedir)" + @list='$(libloinclude_HEADERS)'; test -n "$(libloincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libloincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libloincludedir)" || exit $$?; \ + done + +uninstall-libloincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libloinclude_HEADERS)'; test -n "$(libloincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libloincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libloincludedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libloincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-libloincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libloincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libloincludeHEADERS install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libloincludeHEADERS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/liblo/lo/lo.h b/liblo/lo/lo.h new file mode 100644 index 0000000..89bd769 --- /dev/null +++ b/liblo/lo/lo.h @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_H +#define LO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file lo.h The liblo main headerfile and high-level API functions. + */ + +#include "lo/lo_endian.h" +#include "lo/lo_types.h" +#include "lo/lo_osc_types.h" +#include "lo/lo_errors.h" +#include "lo/lo_lowlevel.h" + +/** + * \defgroup liblo High-level OSC API + * + * Defines the high-level API functions necessary to implement OSC support. + * Should be adequate for most applications, but if you require lower level + * control you can use the functions defined in lo_lowlevel.h + * @{ + */ + +/** + * \brief Declare an OSC destination, given IP address and port number. + * Same as lo_address_new_with_proto(), but using UDP. + * + * \param host An IP address or number, or NULL for the local machine. + * \param port a decimal port number or service name. + * + * The lo_address object may be used as the target of OSC messages. + * + * Note: if you wish to receive replies from the target of this address, you + * must first create a lo_server_thread or lo_server object which will receive + * the replies. The last lo_server(_thread) object creted will be the receiver. + */ +lo_address lo_address_new(const char *host, const char *port); + +/** + * \brief Declare an OSC destination, given IP address and port number, + * specifying protocol. + * + * \param proto The protocol to use, must be one of LO_UDP, LO_TCP or LO_UNIX. + * \param host An IP address or number, or NULL for the local machine. + * \param port a decimal port number or service name. + * + * The lo_address object may be used as the target of OSC messages. + * + * Note: if you wish to receive replies from the target of this address, you + * must first create a lo_server_thread or lo_server object which will receive + * the replies. The last lo_server(_thread) object creted will be the receiver. + */ +lo_address lo_address_new_with_proto(int proto, const char *host, const char *port); + +/** + * \brief Create a lo_address object from an OSC URL. + * + * example: \c "osc.udp://localhost:4444/my/path/" + */ +lo_address lo_address_new_from_url(const char *url); + +/** + * \brief Free the memory used by the lo_address object + */ +void lo_address_free(lo_address t); + +/** + * \brief Set the Time-to-Live value for a given target address. + * + * This is required for sending multicast UDP messages. A value of 1 + * (the usual case) keeps the message within the subnet, while 255 + * means a global, unrestricted scope. + * + * \param t An OSC address. + * \param ttl An integer specifying the scope of a multicast UDP message. + */ +void lo_address_set_ttl(lo_address t, int ttl); + +/** + * \brief Get the Time-to-Live value for a given target address. + * + * \param t An OSC address. + * \return An integer specifying the scope of a multicast UDP message. + */ +int lo_address_get_ttl(lo_address t); + +/** + * \brief Send a OSC formatted message to the address specified. + * + * \param targ The target OSC address + * \param path The OSC path the message will be delivered to + * \param type The types of the data items in the message, types are defined in + * lo_osc_types.h + * \param ... The data values to be transmitted. The types of the arguments + * passed here must agree with the types specified in the type parameter. + * + * example: + * \code + * lo_send(t, "/foo/bar", "ff", 0.1f, 23.0f); + * \endcode + * + * \return -1 on failure. + */ +int lo_send(lo_address targ, const char *path, const char *type, ...); + +/** + * \brief Send a OSC formatted message to the address specified, + * from the same socket as the specificied server. + * + * \param targ The target OSC address + * \param from The server to send message from (can be NULL to use new socket) + * \param ts The OSC timetag timestamp at which the message will be processed + * (can be LO_TT_IMMEDIATE if you don't want to attach a timetag) + * \param path The OSC path the message will be delivered to + * \param type The types of the data items in the message, types are defined in + * lo_osc_types.h + * \param ... The data values to be transmitted. The types of the arguments + * passed here must agree with the types specified in the type parameter. + * + * example: + * \code + * serv = lo_server_new(NULL, err); + * lo_server_add_method(serv, "/reply", "ss", reply_handler, NULL); + * lo_send_from(t, serv, LO_TT_IMMEDIATE, "/foo/bar", "ff", 0.1f, 23.0f); + * \endcode + * + * \return on success, the number of bytes sent, or -1 on failure. + */ +int lo_send_from(lo_address targ, lo_server from, lo_timetag ts, + const char *path, const char *type, ...); + +/** + * \brief Send a OSC formatted message to the address specified, scheduled to + * be dispatch at some time in the future. + * + * \param targ The target OSC address + * \param ts The OSC timetag timestamp at which the message will be processed + * \param path The OSC path the message will be delivered to + * \param type The types of the data items in the message, types are defined in + * lo_osc_types.h + * \param ... The data values to be transmitted. The types of the arguments + * passed here must agree with the types specified in the type parameter. + * + * example: + * \code + * lo_timetag now;
    + * lo_timetag_now(&now);
    + * lo_send_timestamped(t, now, "/foo/bar", "ff", 0.1f, 23.0f); + * \endcode + * + * \return on success, the number of bytes sent, or -1 on failure. + */ +int lo_send_timestamped(lo_address targ, lo_timetag ts, const char *path, + const char *type, ...); + +/** + * \brief Return the error number from the last failed lo_send() or + * lo_address_new() call + */ +int lo_address_errno(lo_address a); + +/** + * \brief Return the error string from the last failed lo_send() or + * lo_address_new() call + */ +const char *lo_address_errstr(lo_address a); + +/** + * \brief Create a new server thread to handle incoming OSC + * messages. + * + * Server threads take care of the message reception and dispatch by + * transparently creating a system thread to handle incoming messages. + * Use this if you do not want to handle the threading yourself. + * + * \param port If NULL is passed then an unused port will be chosen by the + * system, its number may be retrieved with lo_server_thread_get_port() + * so it can be passed to clients. Otherwise a decimal port number, service + * name or UNIX domain socket path may be passed. + * \param err_h A function that will be called in the event of an error being + * raised. The function prototype is defined in lo_types.h + */ +lo_server_thread lo_server_thread_new(const char *port, lo_err_handler err_h); + +/** + * \brief Create a new server thread to handle incoming OSC + * messages, and join a UDP multicast group. + * + * Server threads take care of the message reception and dispatch by + * transparently creating a system thread to handle incoming messages. + * Use this if you do not want to handle the threading yourself. + * + * \param group The multicast group to join. See documentation on IP + * multicast for the acceptable address range; e.g., http://tldp.org/HOWTO/Multicast-HOWTO-2.html + * \param port If NULL is passed then an unused port will be chosen by the + * system, its number may be retrieved with lo_server_thread_get_port() + * so it can be passed to clients. Otherwise a decimal port number, service + * name or UNIX domain socket path may be passed. + * \param err_h A function that will be called in the event of an error being + * raised. The function prototype is defined in lo_types.h + */ +lo_server_thread lo_server_thread_new_multicast(const char *group, const char *port, + lo_err_handler err_h); + +/** + * \brief Create a new server thread to handle incoming OSC + * messages, specifying protocol. + * + * Server threads take care of the message reception and dispatch by + * transparently creating a system thread to handle incoming messages. + * Use this if you do not want to handle the threading yourself. + * + * \param port If NULL is passed then an unused port will be chosen by the + * system, its number may be retrieved with lo_server_thread_get_port() + * so it can be passed to clients. Otherwise a decimal port number, service + * name or UNIX domain socket path may be passed. + * \param proto The protocol to use, should be one of LO_UDP, LO_TCP or LO_UNIX. + * \param err_h A function that will be called in the event of an error being + * raised. The function prototype is defined in lo_types.h + */ +lo_server_thread lo_server_thread_new_with_proto(const char *port, int proto, + lo_err_handler err_h); + +/** + * \brief Free memory taken by a server thread + * + * Frees the memory, and, if currently running will stop the associated thread. + */ +void lo_server_thread_free(lo_server_thread st); + +/** + * \brief Add an OSC method to the specifed server thread. + * + * \param st The server thread the method is to be added to. + * \param path The OSC path to register the method to. If NULL is passed the + * method will match all paths. + * \param typespec The typespec the method accepts. Incoming messages with + * similar typespecs (e.g. ones with numerical types in the same position) will + * be coerced to the typespec given here. + * \param h The method handler callback function that will be called it a + * matching message is received + * \param user_data A value that will be passed to the callback function, h, + * when its invoked matching from this method. + */ +lo_method lo_server_thread_add_method(lo_server_thread st, const char *path, + const char *typespec, lo_method_handler h, + void *user_data); +/** + * \brief Delete an OSC method from the specifed server thread. + * + * \param st The server thread the method is to be removed from. + * \param path The OSC path of the method to delete. If NULL is passed the + * method will match the generic handler. + * \param typespec The typespec the method accepts. + */ +void lo_server_thread_del_method(lo_server_thread st, const char *path, + const char *typespec); + +/** + * \brief Start the server thread + * + * \param st the server thread to start. + * \return Less than 0 on failure, 0 on success. + */ +int lo_server_thread_start(lo_server_thread st); + +/** + * \brief Stop the server thread + * + * \param st the server thread to start. + * \return Less than 0 on failure, 0 on success. + */ +int lo_server_thread_stop(lo_server_thread st); + +/** + * \brief Return the port number that the server thread has bound to. + */ +int lo_server_thread_get_port(lo_server_thread st); + +/** + * \brief Return a URL describing the address of the server thread. + * + * Return value must be free()'d to reclaim memory. + */ +char *lo_server_thread_get_url(lo_server_thread st); + +/** + * \brief Return the lo_server for a lo_server_thread + * + * This function is useful for passing a thread's lo_server + * to lo_send_from(). + */ +lo_server lo_server_thread_get_server(lo_server_thread st); + +/** \brief Return true if there are scheduled events (eg. from bundles) waiting + * to be dispatched by the thread */ +int lo_server_thread_events_pending(lo_server_thread st); + +/** + * \brief Create a new OSC blob type. + * + * \param size The amount of space to allocate in the blob structure. + * \param data The data that will be used to initialise the blob, should be + * size bytes long. + */ +lo_blob lo_blob_new(int32_t size, const void *data); + +/** + * \brief Free the memory taken by a blob + */ +void lo_blob_free(lo_blob b); + +/** + * \brief Return the amount of valid data in a lo_blob object. + * + * If you want to know the storage size, use lo_arg_size(). + */ +uint32_t lo_blob_datasize(lo_blob b); + +/** + * \brief Return a pointer to the start of the blob data to allow contents to + * be changed. + */ +void *lo_blob_dataptr(lo_blob b); + +/** @} */ + +#include "lo/lo_macros.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/liblo/lo/lo_endian.h b/liblo/lo/lo_endian.h new file mode 100644 index 0000000..7ca8f4a --- /dev/null +++ b/liblo/lo/lo_endian.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_ENDIAN_H +#define LO_ENDIAN_H + +#include + +#ifdef _MSC_VER +#define inline __inline +#define uint64_t unsigned __int64 +#define uint32_t unsigned __int32 +#else +#include +#endif + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define lo_swap16(x) htons(x) + +#define lo_swap32(x) htonl(x) + +/* These macros come from the Linux kernel */ + +#ifndef lo_swap16 +#define lo_swap16(x) \ +({ \ + uint16_t __x = (x); \ + ((uint16_t)( \ + (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \ + (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \ +}) +#warning USING UNOPTIMISED ENDIAN STUFF +#endif + +#ifndef lo_swap32 +#define lo_swap32(x) \ +({ \ + uint32_t __x = (x); \ + ((uint32_t)( \ + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ +}) +#endif + +#if 0 +#ifndef lo_swap64 +#define lo_swap64(x) \ +({ \ + uint64_t __x = (x); \ + ((uint64_t)( \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ +}) +#endif +#else + +typedef union { + uint64_t all; + struct { + uint32_t a; + uint32_t b; + } part; +} lo_split64; + +static inline uint64_t lo_swap64(uint64_t x) +{ + lo_split64 in, out; + + in.all = x; + out.part.a = lo_swap32(in.part.b); + out.part.b = lo_swap32(in.part.a); + + return out.all; +} +#endif + +/* Host to OSC and OSC to Host conversion macros */ + +#if defined(__linux__) || defined(__GLIBC__) + #include // set __BYTE_ORDER +#endif + +#ifndef __BIG_ENDIAN + #define __BIG_ENDIAN 4321 + #define __LITTLE_ENDIAN 1234 +#endif + +#ifdef __APPLE__ + #include + #if defined(__LITTLE_ENDIAN__) + #define __BYTE_ORDER __LITTLE_ENDIAN + #endif + #if defined(__BIG_ENDIAN__) + #define __BYTE_ORDER __BIG_ENDIAN + #endif +#endif + +#ifdef WIN32 + #define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +#ifndef __BYTE_ORDER +#error __BYTE_ORDER not defined +#endif + + +#if __BYTE_ORDER == __BIG_ENDIAN +#define lo_htoo16(x) (x) +#define lo_htoo32(x) (x) +#define lo_htoo64(x) (x) +#define lo_otoh16(x) (x) +#define lo_otoh32(x) (x) +#define lo_otoh64(x) (x) +#else +#define lo_htoo16 lo_swap16 +#define lo_htoo32 lo_swap32 +#define lo_htoo64 lo_swap64 +#define lo_otoh16 lo_swap16 +#define lo_otoh32 lo_swap32 +#define lo_otoh64 lo_swap64 +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef _MSC_VER +#undef inline +#undef uint64_t +#undef uint32_t +#endif + +#endif + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/lo/lo_endian.h.in b/liblo/lo/lo_endian.h.in new file mode 100644 index 0000000..7ca8f4a --- /dev/null +++ b/liblo/lo/lo_endian.h.in @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_ENDIAN_H +#define LO_ENDIAN_H + +#include + +#ifdef _MSC_VER +#define inline __inline +#define uint64_t unsigned __int64 +#define uint32_t unsigned __int32 +#else +#include +#endif + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define lo_swap16(x) htons(x) + +#define lo_swap32(x) htonl(x) + +/* These macros come from the Linux kernel */ + +#ifndef lo_swap16 +#define lo_swap16(x) \ +({ \ + uint16_t __x = (x); \ + ((uint16_t)( \ + (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \ + (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \ +}) +#warning USING UNOPTIMISED ENDIAN STUFF +#endif + +#ifndef lo_swap32 +#define lo_swap32(x) \ +({ \ + uint32_t __x = (x); \ + ((uint32_t)( \ + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ +}) +#endif + +#if 0 +#ifndef lo_swap64 +#define lo_swap64(x) \ +({ \ + uint64_t __x = (x); \ + ((uint64_t)( \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ +}) +#endif +#else + +typedef union { + uint64_t all; + struct { + uint32_t a; + uint32_t b; + } part; +} lo_split64; + +static inline uint64_t lo_swap64(uint64_t x) +{ + lo_split64 in, out; + + in.all = x; + out.part.a = lo_swap32(in.part.b); + out.part.b = lo_swap32(in.part.a); + + return out.all; +} +#endif + +/* Host to OSC and OSC to Host conversion macros */ + +#if defined(__linux__) || defined(__GLIBC__) + #include // set __BYTE_ORDER +#endif + +#ifndef __BIG_ENDIAN + #define __BIG_ENDIAN 4321 + #define __LITTLE_ENDIAN 1234 +#endif + +#ifdef __APPLE__ + #include + #if defined(__LITTLE_ENDIAN__) + #define __BYTE_ORDER __LITTLE_ENDIAN + #endif + #if defined(__BIG_ENDIAN__) + #define __BYTE_ORDER __BIG_ENDIAN + #endif +#endif + +#ifdef WIN32 + #define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +#ifndef __BYTE_ORDER +#error __BYTE_ORDER not defined +#endif + + +#if __BYTE_ORDER == __BIG_ENDIAN +#define lo_htoo16(x) (x) +#define lo_htoo32(x) (x) +#define lo_htoo64(x) (x) +#define lo_otoh16(x) (x) +#define lo_otoh32(x) (x) +#define lo_otoh64(x) (x) +#else +#define lo_htoo16 lo_swap16 +#define lo_htoo32 lo_swap32 +#define lo_htoo64 lo_swap64 +#define lo_otoh16 lo_swap16 +#define lo_otoh32 lo_swap32 +#define lo_otoh64 lo_swap64 +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef _MSC_VER +#undef inline +#undef uint64_t +#undef uint32_t +#endif + +#endif + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/lo/lo_errors.h b/liblo/lo/lo_errors.h new file mode 100644 index 0000000..a099d9d --- /dev/null +++ b/liblo/lo/lo_errors.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_ERRORS_H +#define LO_ERRORS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LO_ENOPATH 9901 +#define LO_ENOTYPE 9902 +#define LO_UNKNOWNPROTO 9903 +#define LO_NOPORT 9904 +#define LO_TOOBIG 9905 +#define LO_INT_ERR 9906 +#define LO_EALLOC 9907 +#define LO_EINVALIDPATH 9908 +#define LO_EINVALIDTYPE 9909 +#define LO_EBADTYPE 9910 +#define LO_ESIZE 9911 +#define LO_EINVALIDARG 9912 +#define LO_ETERM 9913 +#define LO_EPAD 9914 +#define LO_EINVALIDBUND 9915 +#define LO_EINVALIDTIME 9916 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/liblo/lo/lo_lowlevel.h b/liblo/lo/lo_lowlevel.h new file mode 100644 index 0000000..91459c3 --- /dev/null +++ b/liblo/lo/lo_lowlevel.h @@ -0,0 +1,860 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_LOWLEVEL_H +#define LO_LOWLEVEL_H + +#include "lo/lo_osc_types.h" + +/** + * \file lo_lowlevel.h The liblo headerfile defining the low-level API + * functions. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _MSC_VER +#define ssize_t SSIZE_T +#define uint32_t unsigned __int32 +#else +#include +#endif + +#include "lo/lo_types.h" +#include "lo/lo_errors.h" + +/** + * \defgroup liblolowlevel Low-level OSC API + * + * Use these functions if you require more precise control over OSC message + * contruction or handling that what is provided in the high-level functions + * described in liblo. + * @{ + */ + +/** + * \brief Type used to represent numerical values in conversions between OSC + * types. + */ +typedef long double lo_hires; + + + + +/** + * \brief Send a lo_message object to target targ + * + * This is slightly more efficient than lo_send() if you want to send a lot of + * similar messages. The messages are constructed with the lo_message_new() and + * \ref lo_message_add_int32 "lo_message_add*()" functions. + */ +int lo_send_message(lo_address targ, const char *path, lo_message msg); + +/** + * \brief Send a lo_message object to target targ from address of serv + * + * This is slightly more efficient than lo_send() if you want to send a lot of + * similar messages. The messages are constructed with the lo_message_new() and + * \ref lo_message_add_int32 "lo_message_add*()" functions. + * + * \param targ The address to send the message to + * \param serv The server socket to send the message from + * (can be NULL to use new socket) + * \param path The path to send the message to + * \param msg The bundle itself + */ +int lo_send_message_from(lo_address targ, lo_server serv, + const char *path, lo_message msg); + +/** + * \brief Send a lo_bundle object to address targ + * + * Bundles are constructed with the + * lo_bundle_new() and lo_bundle_add_message() functions. + */ +int lo_send_bundle(lo_address targ, lo_bundle b); + +/** + * \brief Send a lo_bundle object to address targ from address of serv + * + * Bundles are constructed with the + * lo_bundle_new() and lo_bundle_add_message() functions. + * + * \param targ The address to send the bundle to + * \param serv The server socket to send the bundle from + * (can be NULL to use new socket) + * \param b The bundle itself + */ +int lo_send_bundle_from(lo_address targ, lo_server serv, lo_bundle b); + +/** + * \brief Create a new lo_message object + */ +lo_message lo_message_new(); + +/** + * \brief Free memory allocated by lo_message_new() and any subsequent + * \ref lo_message_add_int32 lo_message_add*() calls. + */ +void lo_message_free(lo_message m); + +/** + * \brief Append a number of arguments to a message. + * + * The data will be added in OSC byteorder (bigendian). + * + * \param m The message to be extended. + * \param types The types of the data items in the message, types are defined in + * lo_types_common.h + * \param ... The data values to be transmitted. The types of the arguments + * passed here must agree with the types specified in the type parameter. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add(lo_message m, const char *types, ...); + +/** \internal \brief the real message_add function (don't call directly) */ +int lo_message_add_internal(lo_message m, const char *file, const int line, + const char *types, ...); + +/** + * \brief Append a varargs list to a message. + * + * The data will be added in OSC byteorder (bigendian). + * IMPORTANT: args list must be terminated with LO_ARGS_END, or this call will + * fail. This is used to do simple error checking on the sizes of parameters + * passed. + * + * \param m The message to be extended. + * \param types The types of the data items in the message, types are defined in + * lo_types_common.h + * \param ap The va_list created by a C function declared with an + * ellipsis (...) argument, and pre-initialised with + * "va_start(ap)". The types of the arguments passed here must agree + * with the types specified in the type parameter. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_varargs(lo_message m, const char *types, va_list ap); + +/** \internal \brief the real message_add_varargs function (don't call directly) */ +int lo_message_add_varargs_internal(lo_message m, const char *types, va_list ap, + const char *file, const int line); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * + * The data will be added in OSC byteorder (bigendian). + * + * \param m The message to be extended. + * \param a The data item. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_int32(lo_message m, int32_t a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_float(lo_message m, float a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_string(lo_message m, const char *a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_blob(lo_message m, lo_blob a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_int64(lo_message m, int64_t a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_timetag(lo_message m, lo_timetag a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_double(lo_message m, double a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_symbol(lo_message m, const char *a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_char(lo_message m, char a); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_midi(lo_message m, uint8_t a[4]); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_true(lo_message m); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_false(lo_message m); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_nil(lo_message m); + +/** + * \brief Append a data item and typechar of the specified type to a message. + * See lo_message_add_int32() for details. + * + * \return Less than 0 on failure, 0 on success. + */ +int lo_message_add_infinitum(lo_message m); + +/** + * \brief Returns the source (lo_address) of an incoming message. + * + * Returns NULL if the message is outgoing. Do not free the returned address. + */ +lo_address lo_message_get_source(lo_message m); + +/** + * \brief Returns the timestamp (lo_timetag *) of a bundled incoming message. + * + * Returns LO_TT_IMMEDIATE if the message is outgoing, or did not arrive + * contained in a bundle. Do not free the returned timetag. + */ +lo_timetag lo_message_get_timestamp(lo_message m); + +/** + * \brief Return the message type tag string. + * + * The result is valid until further data is added with lo_message_add*(). + */ +char *lo_message_get_types(lo_message m); + +/** + * \brief Return the message argument count. + * + * The result is valid until further data is added with lo_message_add*(). + */ +int lo_message_get_argc(lo_message m); + +/** + * \brief Return the message arguments. Do not free the returned data. + * + * The result is valid until further data is added with lo_message_add*(). + */ +lo_arg **lo_message_get_argv(lo_message m); + +/** + * \brief Return the length of a message in bytes. + * + * \param m The message to be sized + * \param path The path the message will be sent to + */ +size_t lo_message_length(lo_message m, const char *path); + +/** + * \brief Serialise the lo_message object to an area of memory and return a + * pointer to the serialised form. Opposite of lo_message_deserialise(). + * + * \param m The message to be serialised + * \param path The path the message will be sent to + * \param to The address to serialise to, memory will be allocated if to is + * NULL. + * \param size If this pointer is non-NULL the size of the memory area + * will be written here + * + * The returned form is suitable to be sent over a low level OSC transport, + * having the correct endianess and bit-packed structure. + */ +void *lo_message_serialise(lo_message m, const char *path, void *to, + size_t *size); + +/** + * \brief Deserialise a raw OSC message and return a new lo_message object. + * Opposite of lo_message_serialise(). + * + * \param data Pointer to the raw OSC message data in network transmission form + * (network byte order where appropriate). + * \param size The size of data in bytes + * \param result If this pointer is non-NULL, the result or error code will + * be written here. + * + * Returns a new lo_message, or NULL if deserialisation fails. + * Use lo_message_free() to free the resulting object. + */ +lo_message lo_message_deserialise(void *data, size_t size, int *result); + +/** + * \brief Dispatch a raw block of memory containing an OSC message. + * + * This is useful when a raw block of memory is available that is + * structured as OSC, and you wish to use liblo to dispatch the + * message to a handler function as if it had been received over the + * network. + * + * \param s The lo_server to use for dispatching. + * \param data Pointer to the raw OSC message data in network transmission form + * (network byte order where appropriate). + * \param size The size of data in bytes + * + * Returns the number of bytes used if successful, or less than 0 otherwise. + */ +int lo_server_dispatch_data(lo_server s, void *data, size_t size); + +/** + * \brief Return the hostname of a lo_address object + * + * Returned value must not be modified or free'd. Value will be a dotted quad, + * colon'd IPV6 address, or resolvable name. + */ +const char *lo_address_get_hostname(lo_address a); + +/** + * \brief Return the port/service name of a lo_address object + * + * Returned value must not be modified or free'd. Value will be a service name + * or ASCII representation of the port number. + */ +const char *lo_address_get_port(lo_address a); + +/** + * \brief Return the protocol of a lo_address object + * + * Returned value will be one of LO_UDP, LO_TCP or LO_UNIX. + */ +int lo_address_get_protocol(lo_address a); + +/** + * \brief Return a URL representing an OSC address + * + * Returned value must be free'd. + */ +char *lo_address_get_url(lo_address a); + +/** + * \brief Set the Time-to-Live value for a given target address. + * + * This is required for sending multicast UDP messages. A value of 1 + * (the usual case) keeps the message within the subnet, while 255 + * means a global, unrestricted scope. + * + * \param t An OSC address. + * \param ttl An integer specifying the scope of a multicast UDP message. + */ +void lo_address_set_ttl(lo_address t, int ttl); + +/** + * \brief Get the Time-to-Live value for a given target address. + * + * \param t An OSC address. + * \return An integer specifying the scope of a multicast UDP message. + */ +int lo_address_get_ttl(lo_address t); + +/** + * \brief Create a new bundle object. + * + * OSC Bundles encapsulate one or more OSC messages and may include a timestamp + * indicating when the bundle should be dispatched. + * + * \param tt The timestamp when the bundle should be handled by the receiver. + * Pass LO_TT_IMMEDIATE if you want the receiving server to dispatch + * the bundle as soon as it receives it. + */ +lo_bundle lo_bundle_new(lo_timetag tt); + +/** + * \brief Adds an OSC message to an existing bundle. + * + * The message passed is appended to the list of messages in the bundle to be + * dispatched to 'path'. + * + * \return 0 if successful, less than 0 otherwise. + */ +int lo_bundle_add_message(lo_bundle b, const char *path, lo_message m); + +/** + * \brief Return the length of a bundle in bytes. + * + * Includes the marker and typetage length. + * + * \param b The bundle to be sized + */ +size_t lo_bundle_length(lo_bundle b); + +/** + * \brief Serialise the bundle object to an area of memory and return a + * pointer to the serialised form. + * + * \param b The bundle to be serialised + * \param to The address to serialise to, memory will be allocated if to is + * NULL. + * \param size If this pointer is non-NULL the size of the memory area + * will be written here + * + * The returned form is suitable to be sent over a low level OSC transport, + * having the correct endianess and bit-packed structure. + */ +void *lo_bundle_serialise(lo_bundle b, void *to, size_t *size); + +/** + * \brief Frees the memory taken by a bundle object. + * + * \param b The bundle to be freed. +*/ +void lo_bundle_free(lo_bundle b); + +/** + * \brief Frees the memory taken by a bundle object and messages in the bundle. + * + * \param b The bundle, which may contain messages, to be freed. +*/ +void lo_bundle_free_messages(lo_bundle b); + +/** + * \brief Return true if the type specified has a numerical value, such as + * LO_INT32, LO_FLOAT etc. + * + * \param a The type to be tested. + */ +int lo_is_numerical_type(lo_type a); + +/** + * \brief Return true if the type specified has a textual value, such as + * LO_STRING or LO_SYMBOL. + * + * \param a The type to be tested. + */ +int lo_is_string_type(lo_type a); + +/** + * \brief Attempt to convert one OSC type to another. + * + * Numerical types (eg LO_INT32, LO_FLOAT etc.) may be converted to other + * numerical types and string types (LO_STRING and LO_SYMBOL) may be converted + * to the other type. This is done automatically if a received message matches + * the path, but not the exact types, and is coercible (ie. all numerical + * types in numerical positions). + * + * On failure no translation occurs and false is returned. + * + * \param type_to The type of the destination variable. + * \param to A pointer to the destination variable. + * \param type_from The type of the source variable. + * \param from A pointer to the source variable. + */ +int lo_coerce(lo_type type_to, lo_arg *to, lo_type type_from, lo_arg *from); + +/** + * \brief Return the numerical value of the given argument with the + * maximum native system precision. + */ +lo_hires lo_hires_val(lo_type type, lo_arg *p); + +/** + * \brief Create a new server instance. + * + * Using lo_server_recv(), lo_servers block until they receive OSC + * messages. If you want non-blocking behaviour see + * lo_server_recv_noblock() or the \ref lo_server_thread_new + * "lo_server_thread_*" functions. + * + * \param port If NULL is passed then an unused UDP port will be chosen by the + * system, its number may be retrieved with lo_server_thread_get_port() + * so it can be passed to clients. Otherwise a decimal port number, service + * name or UNIX domain socket path may be passed. + * \param err_h An error callback function that will be called if there is an + * error in messge reception or server creation. Pass NULL if you do not want + * error handling. + */ +lo_server lo_server_new(const char *port, lo_err_handler err_h); + +/** + * \brief Create a new server instance, specifying protocol. + * + * Using lo_server_recv(), lo_servers block until they receive OSC + * messages. If you want non-blocking behaviour see + * lo_server_recv_noblock() or the \ref lo_server_thread_new + * "lo_server_thread_*" functions. + * + * \param port If using UDP then NULL may be passed to find an unused port. + * Otherwise a decimal port number orservice name or may be passed. + * If using UNIX domain sockets then a socket path should be passed here. + * \param proto The protocol to use, should be one of LO_UDP, LO_TCP or LO_UNIX. + * \param err_h An error callback function that will be called if there is an + * error in messge reception or server creation. Pass NULL if you do not want + * error handling. + */ +lo_server lo_server_new_with_proto(const char *port, int proto, + lo_err_handler err_h); + +/** + * \brief Create a new server instance, and join a UDP multicast group. + * + * \param group The multicast group to join. See documentation on IP + * multicast for the acceptable address range; e.g., http://tldp.org/HOWTO/Multicast-HOWTO-2.html + * \param port If using UDP then NULL may be passed to find an unused port. + * Otherwise a decimal port number or service name or may be passed. + * If using UNIX domain sockets then a socket path should be passed here. + * \param err_h An error callback function that will be called if there is an + * error in messge reception or server creation. Pass NULL if you do not want + * error handling. + */ +lo_server lo_server_new_multicast(const char *group, const char *port, + lo_err_handler err_h); + +/** + * \brief Free up memory used by the lo_server object + */ +void lo_server_free(lo_server s); + +/** + * \brief Wait for an OSC message to be received + * + * \param s The server to wait for connections on. + * \param timeout A timeout in milliseconds to wait for the incoming packet. + * a value of 0 will return immediately. + * + * The return value is 1 if there is a message waiting or 0 if + * there is no message. If there is a message waiting you can now + * call lo_server_recv() to receive that message. + */ +int lo_server_wait(lo_server s, int timeout); + +/** + * \brief Look for an OSC message waiting to be received + * + * \param s The server to wait for connections on. + * \param timeout A timeout in milliseconds to wait for the incoming packet. + * a value of 0 will return immediately. + * + * The return value is the number of bytes in the received message or 0 if + * there is no message. The message will be dispatched to a matching method + * if one is found. + */ +int lo_server_recv_noblock(lo_server s, int timeout); + +/** + * \brief Block, waiting for an OSC message to be received + * + * The return value is the number of bytes in the received message. The message + * will be dispatched to a matching method if one is found. + */ +int lo_server_recv(lo_server s); + +/** + * \brief Add an OSC method to the specifed server. + * + * \param s The server the method is to be added to. + * \param path The OSC path to register the method to. If NULL is passed the + * method will match all paths. + * \param typespec The typespec the method accepts. Incoming messages with + * similar typespecs (e.g. ones with numerical types in the same position) will + * be coerced to the typespec given here. + * \param h The method handler callback function that will be called if a + * matching message is received + * \param user_data A value that will be passed to the callback function, h, + * when its invoked matching from this method. + */ +lo_method lo_server_add_method(lo_server s, const char *path, + const char *typespec, lo_method_handler h, + void *user_data); + +/** + * \brief Delete an OSC method from the specifed server. + * + * \param s The server the method is to be removed from. + * \param path The OSC path of the method to delete. If NULL is passed the + * method will match the generic handler. + * \param typespec The typespec the method accepts. + */ +void lo_server_del_method(lo_server s, const char *path, + const char *typespec); + +/** + * \brief Return the file descriptor of the server socket. + * + * If the server protocol supports exposing the server's underlying + * receive mechanism for monitoring with select() or poll(), this function + * returns the file descriptor needed, otherwise, it returns -1. + * + * WARNING: when using this function beware that not all OSC packets that are + * received are dispatched immediately. lo_server_events_pending() and + * lo_server_next_event_delay() can be used to tell if there are pending + * events and how long before you should attempt to receive them. + */ +int lo_server_get_socket_fd(lo_server s); + +/** + * \brief Return the port number that the server has bound to. + * + * Useful when NULL is passed for the port number and you wish to know how to + * address the server. + */ +int lo_server_get_port(lo_server s); + +/** + * \brief Return the protocol that the server is using. + * + * Returned value will be one of LO_UDP, LO_TCP or LO_UNIX. + */ +int lo_server_get_protocol(lo_server s); + +/** + * \brief Return an OSC URL that can be used to contact the server. + * + * The return value should be free()'d when it is no longer needed. + */ +char *lo_server_get_url(lo_server s); + +/** + * \brief Return true if there are scheduled events (eg. from bundles) + * waiting to be dispatched by the server + */ +int lo_server_events_pending(lo_server s); + +/** + * \brief Return the time in seconds until the next scheduled event. + * + * If the delay is greater than 100 seconds then it will return 100.0. + */ +double lo_server_next_event_delay(lo_server s); + +/** + * \brief Return the protocol portion of an OSC URL, eg. udp, tcp. + * + * This library uses OSC URLs of the form: osc.prot://hostname:port/path if the + * prot part is missing, UDP is assumed. + * + * The return value should be free()'d when it is no longer needed. + */ +char *lo_url_get_protocol(const char *url); + +/** + * \brief Return the protocol ID of an OSC URL. + * + * This library uses OSC URLs of the form: osc.prot://hostname:port/path if the + * prot part is missing, UDP is assumed. + * Returned value will be one of LO_UDP, LO_TCP, LO_UNIX or -1. + * + * \return An integer specifying the protocol. Return -1 when the protocol is + * not supported by liblo. + * + */ +int lo_url_get_protocol_id(const char *url); + +/** + * \brief Return the hostname portion of an OSC URL. + * + * The return value should be free()'d when it is no longer needed. + */ +char *lo_url_get_hostname(const char *url); + +/** + * \brief Return the port portion of an OSC URL. + * + * The return value should be free()'d when it is no longer needed. + */ +char *lo_url_get_port(const char *url); + +/** + * \brief Return the path portion of an OSC URL. + * + * The return value should be free()'d when it is no longer needed. + */ +char *lo_url_get_path(const char *url); + +/* utility functions */ + +/** + * \brief A function to calculate the amount of OSC message space required by a + * C char *. + * + * Returns the storage size in bytes, which will always be a multiple of four. + */ +int lo_strsize(const char *s); + +/** + * \brief A function to calculate the amount of OSC message space required by a + * lo_blob object. + * + * Returns the storage size in bytes, which will always be a multiple of four. + */ +uint32_t lo_blobsize(lo_blob b); + +/** + * \brief Test a string against an OSC pattern glob + * + * \param str The string to test + * \param p The pattern to test against + */ +int lo_pattern_match(const char *str, const char *p); + +/** \internal \brief the real send function (don't call directly) */ +int lo_send_internal(lo_address t, const char *file, const int line, + const char *path, const char *types, ...); +/** \internal \brief the real send_timestamped function (don't call directly) */ +int lo_send_timestamped_internal(lo_address t, const char *file, const int line, + lo_timetag ts, const char *path, const char *types, ...); +/** \internal \brief the real lo_send_from() function (don't call directly) */ +int lo_send_from_internal(lo_address targ, lo_server from, const char *file, + const int line, const lo_timetag ts, + const char *path, const char *types, ...); + + +/** \brief Find the time difference between two timetags + * + * Returns a - b in seconds. + */ +double lo_timetag_diff(lo_timetag a, lo_timetag b); + +/** \brief Return a timetag for the current time + * + * On exit the timetag pointed to by t is filled with the OSC + * representation of this instant in time. + */ +void lo_timetag_now(lo_timetag *t); + +/** + * \brief Return the storage size, in bytes, of the given argument. + */ +size_t lo_arg_size(lo_type type, void *data); + +/** + * \brief Given a raw OSC message, return the message path. + * + * \param data A pointer to the raw OSC message data. + * \param size The size of data in bytes (total buffer bytes). + * + * Returns the message path or NULL if an error occurs. + * Do not free() the returned pointer. + */ +char *lo_get_path(void *data, ssize_t size); + +/** + * \brief Convert the specified argument to host byte order where necessary. + * + * \param type The OSC type of the data item (eg. LO_FLOAT). + * \param data A pointer to the data item to be converted. It is changed + * in-place. + */ +void lo_arg_host_endian(lo_type type, void *data); + +/** + * \brief Convert the specified argument to network byte order where necessary. + * + * \param type The OSC type of the data item (eg. LO_FLOAT). + * \param data A pointer to the data item to be converted. It is changed + * in-place. + */ +void lo_arg_network_endian(lo_type type, void *data); + +/** @} */ + +/* prettyprinters */ + +/** + * \defgroup pp Prettyprinting functions + * + * These functions all print an ASCII representation of their argument to + * stdout. Useful for debugging. + * @{ + */ + +/** \brief Pretty-print a lo_bundle object. */ +void lo_bundle_pp(lo_bundle b); + +/** \brief Pretty-print a lo_message object. */ +void lo_message_pp(lo_message m); + +/** \brief Pretty-print a set of typed arguments. + * \param type A type string in the form provided to lo_send(). + * \param data An OSC data pointer, like that provided in the + * lo_method_handler. + */ +void lo_arg_pp(lo_type type, void *data); + +/** \brief Pretty-print a lo_server object. */ +void lo_server_pp(lo_server s); + +/** \brief Pretty-print a lo_method object. */ +void lo_method_pp(lo_method m); + +/** \brief Pretty-print a lo_method object, but prepend a given prefix + * to all field names. */ +void lo_method_pp_prefix(lo_method m, const char *p); + +/** \brief Pretty-print a lo_server_thread object. */ +void lo_server_thread_pp(lo_server_thread st); +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/liblo/lo/lo_macros.h b/liblo/lo/lo_macros.h new file mode 100644 index 0000000..51b5a2a --- /dev/null +++ b/liblo/lo/lo_macros.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_MACROS_H +#define LO_MACROS_H + +/* macros that have to be defined after function signatures */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* \brief Maximum length of UDP messages in bytes + */ +#define LO_MAX_MSG_SIZE 32768 + +/* \brief A set of macros to represent different communications transports + */ +#define LO_DEFAULT 0x0 +#define LO_UDP 0x1 +#define LO_UNIX 0x2 +#define LO_TCP 0x4 + +/* an internal value, ignored in transmission but check against LO_MARKER in the + * argument list. Used to do primitive bounds checking */ +#define LO_MARKER_A 0xdeadbeef +#define LO_MARKER_B 0xf00baa23 +#define LO_ARGS_END LO_MARKER_A, LO_MARKER_B + +#define lo_message_add_varargs(msg, types, list) \ + lo_message_add_varargs_internal(msg, types, list, __FILE__, __LINE__) + +#ifdef __GNUC__ + +#define lo_message_add(msg, types...) \ + lo_message_add_internal(msg, __FILE__, __LINE__, types, \ + LO_MARKER_A, LO_MARKER_B) + +#define lo_send(targ, path, types...) \ + lo_send_internal(targ, __FILE__, __LINE__, path, types, \ + LO_MARKER_A, LO_MARKER_B) + +#define lo_send_timestamped(targ, ts, path, types...) \ + lo_send_timestamped_internal(targ, __FILE__, __LINE__, ts, path, \ + types, LO_MARKER_A, LO_MARKER_B) + +#define lo_send_from(targ, from, ts, path, types...) \ + lo_send_from_internal(targ, from, __FILE__, __LINE__, ts, path, \ + types, LO_MARKER_A, LO_MARKER_B) + +#else + +/* In non-GCC compilers, there is no support for variable-argument + * macros, so provide "internal" vararg functions directly instead. */ + +int lo_message_add(lo_message msg, const char *types, ...); +int lo_send(lo_address targ, const char *path, const char *types, ...); +int lo_send_timestamped(lo_address targ, lo_timetag ts, const char *path, const char *types, ...); +int lo_send_from(lo_address targ, lo_server from, lo_timetag ts, const char *path, const char *types, ...); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/liblo/lo/lo_osc_types.h b/liblo/lo/lo_osc_types.h new file mode 100644 index 0000000..f001032 --- /dev/null +++ b/liblo/lo/lo_osc_types.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_OSC_TYPES_H +#define LO_OSC_TYPES_H + +/** + * \file lo_osc_types.h A liblo header defining OSC-related types and + * constants. + */ + +#ifdef _MSC_VER +#define int32_t __int32 +#define int64_t __int64 +#define uint32_t unsigned __int32 +#define uint64_t unsigned __int64 +#define uint8_t unsigned __int8 +#else +#include +#endif + +/** + * \addtogroup liblo + * @{ + */ + +/** + * \brief A structure to store OSC TimeTag values. + */ +typedef struct { + /** The number of seconds since Jan 1st 1900 in the UTC timezone. */ + uint32_t sec; + /** The fractions of a second offset from above, expressed as 1/2^32nds + * of a second */ + uint32_t frac; +} lo_timetag; + +/** + * \brief An enumeration of the OSC types liblo can send and receive. + * + * The value of the enumeration is the typechar used to tag messages and to + * specify arguments with lo_send(). + */ +typedef enum { +/* basic OSC types */ + /** 32 bit signed integer. */ + LO_INT32 = 'i', + /** 32 bit IEEE-754 float. */ + LO_FLOAT = 'f', + /** Standard C, NULL terminated string. */ + LO_STRING = 's', + /** OSC binary blob type. Accessed using the lo_blob_*() functions. */ + LO_BLOB = 'b', + +/* extended OSC types */ + /** 64 bit signed integer. */ + LO_INT64 = 'h', + /** OSC TimeTag type, represented by the lo_timetag structure. */ + LO_TIMETAG = 't', + /** 64 bit IEEE-754 double. */ + LO_DOUBLE = 'd', + /** Standard C, NULL terminated, string. Used in systems which + * distinguish strings and symbols. */ + LO_SYMBOL = 'S', + /** Standard C, 8 bit, char variable. */ + LO_CHAR = 'c', + /** A 4 byte MIDI packet. */ + LO_MIDI = 'm', + /** Sybol representing the value True. */ + LO_TRUE = 'T', + /** Sybol representing the value False. */ + LO_FALSE = 'F', + /** Sybol representing the value Nil. */ + LO_NIL = 'N', + /** Sybol representing the value Infinitum. */ + LO_INFINITUM = 'I' +} lo_type; + + +/** + * \brief Union used to read values from incoming messages. + * + * Types can generally be read using argv[n]->t where n is the argument number + * and t is the type character, with the exception of strings and symbols which + * must be read with &argv[n]->t. + */ +typedef union { + /** 32 bit signed integer. */ + int32_t i; + /** 32 bit signed integer. */ + int32_t i32; + /** 64 bit signed integer. */ + int64_t h; + /** 64 bit signed integer. */ + int64_t i64; + /** 32 bit IEEE-754 float. */ + float f; + /** 32 bit IEEE-754 float. */ + float f32; + /** 64 bit IEEE-754 double. */ + double d; + /** 64 bit IEEE-754 double. */ + double f64; + /** Standard C, NULL terminated string. */ + char s; + /** Standard C, NULL terminated, string. Used in systems which + * distinguish strings and symbols. */ + char S; + /** Standard C, 8 bit, char. */ + unsigned char c; + /** A 4 byte MIDI packet. */ + uint8_t m[4]; + /** OSC TimeTag value. */ + lo_timetag t; +} lo_arg; + +/** \brief A timetag constant representing "now". */ +/* Note: No struct literals in MSVC */ +#ifdef _MSC_VER +lo_timetag lo_get_tt_immediate(); +#define LO_TT_IMMEDIATE lo_get_tt_immediate() +#else +#define LO_TT_IMMEDIATE ((lo_timetag){0U,1U}) +#endif + +/** @} */ + +#endif diff --git a/liblo/lo/lo_throw.h b/liblo/lo/lo_throw.h new file mode 100644 index 0000000..2493a97 --- /dev/null +++ b/liblo/lo/lo_throw.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_THROW_H +#define LO_THROW_H + +#ifdef __cplusplus +extern "C" { +#endif + +void lo_throw(lo_server s, int errnum, const char *message, const char *path); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/liblo/lo/lo_types.h b/liblo/lo/lo_types.h new file mode 100644 index 0000000..8b864bf --- /dev/null +++ b/liblo/lo/lo_types.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 + * 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. + * + * $Id$ + */ + +#ifndef LO_TYPES_H +#define LO_TYPES_H + +/** + * \file lo_types.h The liblo headerfile defining types used by this API. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +#include + +#include "lo/lo_osc_types.h" + +/** + * \brief A reference to an OSC service. + * + * Created by calls to lo_address_new() or lo_address_new_from_url(). + */ +typedef void *lo_address; + +/** + * \brief A object to store an opaque binary data object. + * + * Can be passed over OSC using the 'b' type. Created by calls to lo_blob_new(). + */ +typedef void *lo_blob; + +/** + * \brief A low-level object used to represent messages passed over OSC. + * + * Created by calls to lo_message_new(), arguments can be added with calls to + * lo_message_add_*(). + */ +typedef void *lo_message; + +/** + * \brief A low-level object used to represent bundles of messages passed over + * OSC. + * + * Created by calls to lo_bundle_new(), messages can be added with calls to + * lo_bundle_add_message(). + */ +typedef void *lo_bundle; + +/** + * \brief An object representing an method on a server. + * + * Returned by calls to lo_server_thread_add_method() and + * lo_server_add_method(). + */ +typedef void *lo_method; + +/** + * \brief An object representing an instance of an OSC server. + * + * Created by calls to lo_server_new(). If you with the library to take care of + * the threading as well you can just use server threads instead. + */ +typedef void *lo_server; + +/** + * \brief An object representing a thread containing an OSC server. + * + * Created by calls to lo_server_thread_new(). + */ +typedef void *lo_server_thread; + +/** + * \brief A callback function to receive notifcation of an error in a server or + * server thread. + * + * On callback the paramters will be set to the following values: + * + * \param num An error number that can be used to identify this condition. + * \param msg An error message describing the condidtion. + * \param where A string describing the place the error occured - typically + * either a function call or method path. + */ +typedef void (*lo_err_handler)(int num, const char *msg, const char *where); + +/** + * \brief A callback function to receive notifcation of matching message + * arriving in the server or server thread. + * + * The return value tells the method dispatcher whether this handler + * has dealt with the message correctly: a return value of 0 indicates + * that it has been handled, and it should not attempt to pass it on + * to any other handlers, non-0 means that it has not been handled and + * the dispatcher will attempt to find more handlers that match the + * path and types of the incoming message. + * + * On callback the paramters will be set to the following values: + * + * \param path That path that the incoming message was sent to + * \param types If you specided types in your method creation call then this + * will match those and the incoming types will have been coerced to match, + * otherwise it will be the types of the arguments of the incoming message. + * \param argv An array of lo_arg types containing the values, e.g. if the + * first argument of the incoming message is of type 'f' then the vlaue will be + * found in argv[0]->f. + * \param argc The number of argumets received. + * \param msg A structure containing the original raw message as received. No + * type coercion will have occured and the data will be in OSC byte order + * (bigendian). + * \param user_data This contains the user_data value passed in the call to + * lo_server_thread_add_method. + */ +typedef int (*lo_method_handler)(const char *path, const char *types, + lo_arg **argv, int argc, lo_message msg, + void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/liblo/ltmain.sh b/liblo/ltmain.sh new file mode 100755 index 0000000..a72f2fd --- /dev/null +++ b/liblo/ltmain.sh @@ -0,0 +1,8406 @@ +# Generated from ltmain.m4sh. + +# ltmain.sh (GNU libtool) 2.2.6b +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print informational messages (default) +# --version print version information +# -h, --help print short or long help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.2.6b +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=2.2.6b +TIMESTAMP="" +package_revision=1.3017 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# NLS nuisances: We save the old values to restore during execute mode. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done + +$lt_unset CDPATH + + + + + +: ${CP="cp -f"} +: ${ECHO="echo"} +: ${EGREP="/bin/grep -E"} +: ${FGREP="/bin/grep -F"} +: ${GREP="/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +# Generated shell functions inserted here. + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +# In the unlikely event $progname began with a '-', it would play havoc with +# func_echo (imagine progname=-n), so we prepend ./ in that case: +func_dirname_and_basename "$progpath" +progname=$func_basename_result +case $progname in + -*) progname=./$progname ;; +esac + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname${mode+: }$mode: $*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + done + my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "X$my_tmpdir" | $Xsed +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "X$1" | $Xsed \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + + + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $SED -n '/^# Usage:/,/# -h/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + $ECHO + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help +# Echo long help message to standard output and exit. +func_help () +{ + $SED -n '/^# Usage:/,/# Report bugs to/ { + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + }' < "$progpath" + exit $? +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + func_error "missing argument for $1" + exit_cmd=exit +} + +exit_cmd=: + + + + + +# Check that we have a working $ECHO. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell, and then maybe $ECHO will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# Parse options once, thoroughly. This comes as soon as possible in +# the script to make things like `libtool --version' happen quickly. +{ + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Parse non-mode specific arguments: + while test "$#" -gt 0; do + opt="$1" + shift + + case $opt in + --config) func_config ;; + + --debug) preserve_args="$preserve_args $opt" + func_echo "enabling shell trace mode" + opt_debug='set -x' + $opt_debug + ;; + + -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break + execute_dlfiles="$execute_dlfiles $1" + shift + ;; + + --dry-run | -n) opt_dry_run=: ;; + --features) func_features ;; + --finish) mode="finish" ;; + + --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break + case $1 in + # Valid mode arguments: + clean) ;; + compile) ;; + execute) ;; + finish) ;; + install) ;; + link) ;; + relink) ;; + uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; + esac + + mode="$1" + shift + ;; + + --preserve-dup-deps) + opt_duplicate_deps=: ;; + + --quiet|--silent) preserve_args="$preserve_args $opt" + opt_silent=: + ;; + + --verbose| -v) preserve_args="$preserve_args $opt" + opt_silent=false + ;; + + --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break + preserve_args="$preserve_args $opt $1" + func_enable_tag "$1" # tagname is set here + shift + ;; + + # Separate optargs to long options: + -dlopen=*|--mode=*|--tag=*) + func_opt_split "$opt" + set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} + shift + ;; + + -\?|-h) func_usage ;; + --help) opt_help=: ;; + --version) func_version ;; + + -*) func_fatal_help "unrecognized option \`$opt'" ;; + + *) nonopt="$opt" + break + ;; + esac + done + + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_duplicate_deps + ;; + esac + + # Having warned about all mis-specified options, bail out if + # anything was wrong. + $exit_cmd $EXIT_FAILURE +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +## ----------- ## +## Main. ## +## ----------- ## + +$opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + test -z "$mode" && func_fatal_error "error: you must specify a MODE." + + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$mode' for more information." +} + + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_ltwrapper_scriptname_result="" + if func_ltwrapper_executable_p "$1"; then + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + fi +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case "$@ " in + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + removelist="$removelist $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + removelist="$removelist $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + command="$command -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { +test "$mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$mode'" + ;; + esac + + $ECHO + $ECHO "Try \`$progname --help' for more information about other modes." + + exit $? +} + + # Now that we've collected a possible --mode arg, show help if necessary + $opt_help && func_mode_help + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_quote_for_eval "$file" + args="$args $func_quote_for_eval_result" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + $ECHO "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + $ECHO "X----------------------------------------------------------------------" | $Xsed + $ECHO "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + $ECHO + $ECHO "If you ever happen to want to link against installed libraries" + $ECHO "in a given directory, LIBDIR, you must either use libtool, and" + $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" + $ECHO "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" + $ECHO " during execution" + fi + if test -n "$runpath_var"; then + $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" + $ECHO " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $ECHO + + $ECHO "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" + $ECHO "pages." + ;; + *) + $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + $ECHO "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS +} + +test "$mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $ECHO "X$nonopt" | $GREP shtool >/dev/null; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + install_prog="$install_prog$func_quote_for_eval_result" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + install_prog="$install_prog $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_verbose "extracting global C symbols from \`$progfile'" + $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + $ECHO >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +" + case $host in + *cygwin* | *mingw* | *cegcc* ) + $ECHO >> "$output_objdir/$my_dlsyms" "\ +/* DATA imports from DLLs on WIN32 con't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs. */" + lt_dlsym_const= ;; + *osf5*) + echo >> "$output_objdir/$my_dlsyms" "\ +/* This system does not cope well with relocations in const data */" + lt_dlsym_const= ;; + *) + lt_dlsym_const=const ;; + esac + + $ECHO >> "$output_objdir/$my_dlsyms" "\ +extern $lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +$lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + $ECHO >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) symtab_cflags="$symtab_cflags $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + + +# func_emit_wrapper_part1 [arg=no] +# +# Emit the first part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part1 () +{ + func_emit_wrapper_part1_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part1_arg1=$1 + fi + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + ECHO=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$ECHO works! + : + else + # Restart under the correct shell, and then maybe \$ECHO will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $ECHO "\ + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done +" +} +# end: func_emit_wrapper_part1 + +# func_emit_wrapper_part2 [arg=no] +# +# Emit the second part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part2 () +{ + func_emit_wrapper_part2_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part2_arg1=$1 + fi + + $ECHO "\ + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} +# end: func_emit_wrapper_part2 + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=no + if test -n "$1" ; then + func_emit_wrapper_arg1=$1 + fi + + # split this up so that func_emit_cwrapperexe_src + # can call each part independently. + func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" + func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" +} + + +# func_to_host_path arg +# +# Convert paths to host format when used with build tools. +# Intended for use with "native" mingw (where libtool itself +# is running under the msys shell), or in the following cross- +# build environments: +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# where wine is equipped with the `winepath' executable. +# In the native mingw case, the (msys) shell automatically +# converts paths for any non-msys applications it launches, +# but that facility isn't available from inside the cwrapper. +# Similar accommodations are necessary for $host mingw and +# $build cygwin. Calling this function does no harm for other +# $host/$build combinations not listed above. +# +# ARG is the path (on $build) that should be converted to +# the proper representation for $host. The result is stored +# in $func_to_host_path_result. +func_to_host_path () +{ + func_to_host_path_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + case $build in + *mingw* ) # actually, msys + # awkward: cmd appends spaces to result + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_path_tmp1=`( cmd //c echo "$1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_path_tmp1=`cygpath -w "$1"` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # Unfortunately, winepath does not exit with a non-zero + # error code, so we are forced to check the contents of + # stdout. On the other hand, if the command is not + # found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both + # error code of zero AND non-empty stdout, which explains + # the odd construction: + func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + else + # Allow warning below. + func_to_host_path_result="" + fi + ;; + esac + if test -z "$func_to_host_path_result" ; then + func_error "Could not determine host path corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_path_result="$1" + fi + ;; + esac + fi +} +# end: func_to_host_path + +# func_to_host_pathlist arg +# +# Convert pathlists to host format when used with build tools. +# See func_to_host_path(), above. This function supports the +# following $build/$host combinations (but does no harm for +# combinations not listed here): +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# +# Path separators are also converted from $build format to +# $host format. If ARG begins or ends with a path separator +# character, it is preserved (but converted to $host format) +# on output. +# +# ARG is a pathlist (on $build) that should be converted to +# the proper representation on $host. The result is stored +# in $func_to_host_pathlist_result. +func_to_host_pathlist () +{ + func_to_host_pathlist_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_to_host_pathlist_tmp2="$1" + # Once set for this call, this variable should not be + # reassigned. It is used in tha fallback case. + func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e 's|^:*||' -e 's|:*$||'` + case $build in + *mingw* ) # Actually, msys. + # Awkward: cmd appends spaces to result. + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # unfortunately, winepath doesn't convert pathlists + func_to_host_pathlist_result="" + func_to_host_pathlist_oldIFS=$IFS + IFS=: + for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do + IFS=$func_to_host_pathlist_oldIFS + if test -n "$func_to_host_pathlist_f" ; then + func_to_host_path "$func_to_host_pathlist_f" + if test -n "$func_to_host_path_result" ; then + if test -z "$func_to_host_pathlist_result" ; then + func_to_host_pathlist_result="$func_to_host_path_result" + else + func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" + fi + fi + fi + IFS=: + done + IFS=$func_to_host_pathlist_oldIFS + ;; + esac + if test -z "$func_to_host_pathlist_result" ; then + func_error "Could not determine the host path(s) corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This may break if $1 contains DOS-style drive + # specifications. The fix is not to complicate the expression + # below, but for the user to provide a working wine installation + # with winepath so that path translation in the cross-to-mingw + # case works properly. + lt_replace_pathsep_nix_to_dos="s|:|;|g" + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_replace_pathsep_nix_to_dos"` + fi + # Now, add the leading and trailing path separators back + case "$1" in + :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" + ;; + esac + case "$1" in + *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + ;; + esac + ;; + esac + fi +} +# end: func_to_host_pathlist + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +# define setmode _setmode +#else +# include +# include +# ifdef __CYGWIN__ +# include +# define HAVE_SETENV +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +#ifdef _MSC_VER +# define S_IXUSR _S_IEXEC +# define stat _stat +# ifndef _INTPTR_T_DEFINED +# define intptr_t int +# endif +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifdef __CYGWIN__ +# define FOPEN_WB "wb" +#endif + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#undef LTWRAPPER_DEBUGPRINTF +#if defined DEBUGWRAPPER +# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args +static void +ltwrapper_debugprintf (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); +} +#else +# define LTWRAPPER_DEBUGPRINTF(args) +#endif + +const char *program_name = NULL; + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_fatal (const char *message, ...); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_opt_process_env_set (const char *arg); +void lt_opt_process_env_prepend (const char *arg); +void lt_opt_process_env_append (const char *arg); +int lt_split_name_value (const char *arg, char** name, char** value); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); + +static const char *script_text_part1 = +EOF + + func_emit_wrapper_part1 yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ "/' -e 's/$/\\n"/' + echo ";" + cat <"))); + for (i = 0; i < newargc; i++) + { + LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", + wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", + tmp_pathspec)); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + char *errstr = strerror (errno); + lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal ("Could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} + +void +lt_setenv (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", + (name ? name : ""), + (value ? value : ""))); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +int +lt_split_name_value (const char *arg, char** name, char** value) +{ + const char *p; + int len; + if (!arg || !*arg) + return 1; + + p = strchr (arg, (int)'='); + + if (!p) + return 1; + + *value = xstrdup (++p); + + len = strlen (arg) - strlen (*value); + *name = XMALLOC (char, len); + strncpy (*name, arg, len-1); + (*name)[len - 1] = '\0'; + + return 0; +} + +void +lt_opt_process_env_set (const char *arg) +{ + char *name = NULL; + char *value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); + } + + lt_setenv (name, value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_prepend (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_append (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 1); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + + +EOF +} +# end: func_emit_cwrapperexe_src + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) deplibs="$deplibs $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + weak_libs="$weak_libs $arg" + prev= + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname '-L' '' "$arg" + dir=$func_stripname_result + if test -z "$dir"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" + linker_flags="$linker_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_duplicate_deps ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + case $lib in + *.la) func_source "$lib" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + case " $weak_libs " in + *" $deplib_base "*) ;; + *) deplibs="$deplibs $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + dir=$func_stripname_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $ECHO + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because the file extensions .$libext of this argument makes me believe" + $ECHO "*** that it is just a static archive that I should not use here." + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) temp_rpath="$temp_rpath$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + notinst_deplibs="$notinst_deplibs $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + $ECHO + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $ECHO + $ECHO "*** And there doesn't seem to be a static archive available" + $ECHO "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $ECHO + $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $ECHO "*** But as you try to build a module library, libtool will still create " + $ECHO "*** a static module, that should work as long as the dlopening application" + $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_dirname "$deplib" "" "." + dir="$func_dirname_result" + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + libobjs="$libobjs $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` + # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` + # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ + -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + done + fi + if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | + $GREP . >/dev/null; then + $ECHO + if test "X$deplibs_check_method" = "Xnone"; then + $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + else + $ECHO "*** Warning: inter-library dependencies are not known to be supported." + fi + $ECHO "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $ECHO + $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + $ECHO "*** a static module, that should work as long as the dlopening" + $ECHO "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $ECHO "*** The inter-library dependencies that have been dropped here will be" + $ECHO "*** automatically added whenever a program is linked with this library" + $ECHO "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $ECHO + $ECHO "*** Since this library must not contain undefined symbols," + $ECHO "*** because either the platform does not support them or" + $ECHO "*** it was explicitly requested with -no-undefined," + $ECHO "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + delfiles="$delfiles $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + func_len " $cmd" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + $ECHO 'INPUT (' > $output + for obj in $save_libobjs + do + $ECHO "$obj" >> $output + done + $ECHO ')' >> $output + delfiles="$delfiles $output" + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + $ECHO "$obj" >> $output + done + delfiles="$delfiles $output" + output=$firstobj\"$file_list_spec$output\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + delfiles="$delfiles $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *cegcc) + # Disable wrappers for cegcc, we are cross compiling anyway. + wrappers_required=no + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $ECHO for shipping. + if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + oldobjs="$oldobjs $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $ECHO "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlfiles="$newdlfiles $libdir/$name" + ;; + *) newdlfiles="$newdlfiles $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlprefiles="$newdlprefiles $libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$mode" = link || test "$mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) RM="$RM $arg"; rmforce=yes ;; + -*) RM="$RM $arg" ;; + *) files="$files $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + rmfiles="$rmfiles $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$mode" = uninstall || test "$mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/liblo/m4/libtool.m4 b/liblo/m4/libtool.m4 new file mode 100644 index 0000000..671cde1 --- /dev/null +++ b/liblo/m4/libtool.m4 @@ -0,0 +1,7360 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 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. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 56 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl +_LT_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Fix-up fallback echo if it was mangled by the above quoting rules. +case \$lt_ECHO in +*'\\\[$]0 --fallback-echo"')dnl " + lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` + ;; +esac + +_LT_OUTPUT_LIBTOOL_INIT +]) + + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +cat >"$CONFIG_LT" <<_LTEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate a libtool stub with the current configuration. + +lt_cl_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AS_SHELL_SANITIZE +_AS_PREPARE + +exec AS_MESSAGE_FD>&1 +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2008 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +if test "$no_create" != yes; then + lt_cl_success=: + test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" + exec AS_MESSAGE_LOG_FD>/dev/null + $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false + exec AS_MESSAGE_LOG_FD>>config.log + $lt_cl_success || AS_EXIT(1) +fi +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_XSI_SHELLFNS + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES +# -------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=echo + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX +# ----------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_SHELL_INIT + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[_LT_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$lt_ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +ECHO=${lt_ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<_LT_EOF +[$]* +_LT_EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$lt_ECHO"; then + if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if { echo_test_string=`eval $cmd`; } 2>/dev/null && + { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null + then + break + fi + done + fi + + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : + else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$ECHO" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + ECHO='print -r' + elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + ECHO='printf %s\n' + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + ECHO="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + ECHO=echo + fi + fi + fi + fi + fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +lt_ECHO=$ECHO +if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(lt_ECHO) +]) +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], + [An echo program that does not interpret backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[AC_CHECK_TOOL(AR, ar, false) +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1]) + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ + = "XX$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line __oline__ "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method == "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC*) + # IBM XL 8.0 on PPC + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl*) + # IBM XL C 8.0/Fortran 10.1 on PPC + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac +AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + 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 + + _LT_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # 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. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag= + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=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 + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + 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 + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + 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 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + 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. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE(int foo(void) {}, + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + ) + LDFLAGS="$save_LDFLAGS" + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], + [[If ld is used when linking, flag to hardcode $libdir into a binary + during linking. This must work even if $libdir does not exist]]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [fix_srcfile_path], [1], + [Fix the shell variable $srcfile for the compiler]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_PROG_CXX +# ------------ +# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ +# compiler, we have our own version here. +m4_defun([_LT_PROG_CXX], +[ +pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) +AC_PROG_CXX +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi +popdef([AC_MSG_ERROR]) +])# _LT_PROG_CXX + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([_LT_PROG_CXX], []) + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[AC_REQUIRE([_LT_PROG_CXX])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + 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 + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + 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 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 will use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + xl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=echo + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +]) +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_PROG_F77 +# ------------ +# Since AC_PROG_F77 is broken, in that it returns the empty string +# if there is no fortran compiler, we have our own version here. +m4_defun([_LT_PROG_F77], +[ +pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) +AC_PROG_F77 +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi +popdef([AC_MSG_ERROR]) +])# _LT_PROG_F77 + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([_LT_PROG_F77], []) + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_REQUIRE([_LT_PROG_F77])dnl +AC_LANG_PUSH(Fortran 77) + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + CC=${F77-"f77"} + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_PROG_FC +# ----------- +# Since AC_PROG_FC is broken, in that it returns the empty string +# if there is no fortran compiler, we have our own version here. +m4_defun([_LT_PROG_FC], +[ +pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) +AC_PROG_FC +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi +popdef([AC_MSG_ERROR]) +])# _LT_PROG_FC + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([_LT_PROG_FC], []) + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_REQUIRE([_LT_PROG_FC])dnl +AC_LANG_PUSH(Fortran) + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + CC=${FC-"f95"} + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC="$lt_save_CC" +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC="$lt_save_CC" +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_XSI_SHELLFNS +# --------------------- +# Bourne and XSI compatible variants of some useful shell functions. +m4_defun([_LT_PROG_XSI_SHELLFNS], +[case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $[*] )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +dnl func_dirname_and_basename +dnl A portable version of this function is already defined in general.m4sh +dnl so there is no need for it here. + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[[^=]]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$[@]"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$[1]+=\$[2]" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$[1]=\$$[1]\$[2]" +} + +_LT_EOF + ;; + esac +]) diff --git a/liblo/m4/ltoptions.m4 b/liblo/m4/ltoptions.m4 new file mode 100644 index 0000000..34151a3 --- /dev/null +++ b/liblo/m4/ltoptions.m4 @@ -0,0 +1,368 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# 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. + +# serial 6 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [0], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/liblo/m4/ltsugar.m4 b/liblo/m4/ltsugar.m4 new file mode 100644 index 0000000..9000a05 --- /dev/null +++ b/liblo/m4/ltsugar.m4 @@ -0,0 +1,123 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# 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. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/liblo/m4/ltversion.m4 b/liblo/m4/ltversion.m4 new file mode 100644 index 0000000..f3c5309 --- /dev/null +++ b/liblo/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# 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. + +# Generated from ltversion.in. + +# serial 3017 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.2.6b]) +m4_define([LT_PACKAGE_REVISION], [1.3017]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.2.6b' +macro_revision='1.3017' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/liblo/m4/lt~obsolete.m4 b/liblo/m4/lt~obsolete.m4 new file mode 100644 index 0000000..637bb20 --- /dev/null +++ b/liblo/m4/lt~obsolete.m4 @@ -0,0 +1,92 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# 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. + +# serial 4 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) diff --git a/liblo/missing b/liblo/missing new file mode 100755 index 0000000..1c8ff70 --- /dev/null +++ b/liblo/missing @@ -0,0 +1,367 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2006-05-10.23 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case $1 in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $1 in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# 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: diff --git a/liblo/osx/config.h b/liblo/osx/config.h new file mode 100644 index 0000000..4a2a70c --- /dev/null +++ b/liblo/osx/config.h @@ -0,0 +1,92 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define this to enable ipv6. */ +/* #undef ENABLE_IPV6 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if inet_aton() is available. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if poll() is available. */ +#define HAVE_POLL 1 + +/* Define to 1 if select() is available. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* If machine is bigendian */ +#define LO_BIGENDIAN "0" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "liblo" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "liblo-devel@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "liblo" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "liblo 0.26" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "liblo" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.26" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.26" + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ diff --git a/liblo/pthreads.2/ANNOUNCE b/liblo/pthreads.2/ANNOUNCE new file mode 100644 index 0000000..86b87fa --- /dev/null +++ b/liblo/pthreads.2/ANNOUNCE @@ -0,0 +1,476 @@ + PTHREADS-WIN32 RELEASE 2.8.0 (2006-12-22) + ----------------------------------------- + Web Site: http://sources.redhat.com/pthreads-win32/ + FTP Site: ftp://sources.redhat.com/pub/pthreads-win32 + Maintainer: Ross Johnson + + +We are pleased to announce the availability of a new release of +Pthreads-win32, an Open Source Software implementation of the +Threads component of the POSIX 1003.1 2001 Standard for Microsoft's +Win32 environment. Some functions from other sections of POSIX +1003.1 2001 are also supported including semaphores and scheduling +functions. + +Some common non-portable functions are also implemented for +additional compatibility, as are a few functions specific +to pthreads-win32 for easier integration with Win32 applications. + +Pthreads-win32 is free software, distributed under the GNU Lesser +General Public License (LGPL). + + +Acknowledgements +---------------- +This library is based originally on a Win32 pthreads +implementation contributed by John Bossom . + +The implementation of Condition Variables uses algorithms developed +by Alexander Terekhov and Louis Thomas. + +The implementation of POSIX mutexes has been improved by Thomas Pfaff +and later by Alexander Terekhov. + +The implementation of Spinlocks and Barriers was contributed +by Ross Johnson. + +The implementation of read/write locks was contributed by +Aurelio Medina and improved by Alexander Terekhov. + +Many others have contributed significant time and effort to solve crutial +problems in order to make the library workable, robust and reliable. + +Thanks to Xavier Leroy for granting permission to use and modify his +LinuxThreads manual pages. + +Thanks to The Open Group for making the Single Unix Specification +publicly available - many of the manual pages included in the package +were extracted from it. + +There is also a separate CONTRIBUTORS file. This file and others are +on the web site: + + http://sources.redhat.com/pthreads-win32 + +As much as possible, the ChangeLog file acknowledges contributions to the +code base in more detail. + + +Changes since the last release +------------------------------ +These are now documented in the NEWS file. +See the ChangeLog file also. + + +Known Bugs +---------- +These are now documented in the BUGS file. + + +Level of standards conformance +------------------------------ + +The following POSIX 1003.1 2001 options are defined and set to 200112L: + + _POSIX_THREADS + _POSIX_THREAD_SAFE_FUNCTIONS + _POSIX_THREAD_ATTR_STACKSIZE + _POSIX_THREAD_PRIORITY_SCHEDULING + _POSIX_SEMAPHORES + _POSIX_READER_WRITER_LOCKS + _POSIX_SPIN_LOCKS + _POSIX_BARRIERS + + +The following POSIX 1003.1 2001 options are defined and set to -1: + + _POSIX_THREAD_ATTR_STACKADDR + _POSIX_THREAD_PRIO_INHERIT + _POSIX_THREAD_PRIO_PROTECT + _POSIX_THREAD_PROCESS_SHARED + + +The following POSIX 1003.1 2001 limits are defined and set: + + _POSIX_THREAD_THREADS_MAX + _POSIX_SEM_VALUE_MAX + _POSIX_SEM_NSEMS_MAX + _POSIX_THREAD_KEYS_MAX + _POSIX_THREAD_DESTRUCTOR_ITERATIONS + PTHREAD_STACK_MIN + PTHREAD_THREADS_MAX + SEM_VALUE_MAX + SEM_NSEMS_MAX + PTHREAD_KEYS_MAX + PTHREAD_DESTRUCTOR_ITERATIONS + + +The following functions are implemented: + + --------------------------- + PThreads + --------------------------- + pthread_attr_init + pthread_attr_destroy + pthread_attr_getdetachstate + pthread_attr_getstackaddr + pthread_attr_getstacksize + pthread_attr_setdetachstate + pthread_attr_setstackaddr + pthread_attr_setstacksize + + pthread_create + pthread_detach + pthread_equal + pthread_exit + pthread_join + pthread_once + pthread_self + + pthread_cancel + pthread_cleanup_pop + pthread_cleanup_push + pthread_setcancelstate + pthread_setcanceltype + pthread_testcancel + + --------------------------- + Thread Specific Data + --------------------------- + pthread_key_create + pthread_key_delete + pthread_setspecific + pthread_getspecific + + --------------------------- + Mutexes + --------------------------- + pthread_mutexattr_init + pthread_mutexattr_destroy + pthread_mutexattr_getpshared + pthread_mutexattr_setpshared + pthread_mutexattr_gettype + pthread_mutexattr_settype (types: PTHREAD_MUTEX_DEFAULT + PTHREAD_MUTEX_NORMAL + PTHREAD_MUTEX_ERRORCHECK + PTHREAD_MUTEX_RECURSIVE ) + pthread_mutex_init + pthread_mutex_destroy + pthread_mutex_lock + pthread_mutex_trylock + pthread_mutex_timedlock + pthread_mutex_unlock + + --------------------------- + Condition Variables + --------------------------- + pthread_condattr_init + pthread_condattr_destroy + pthread_condattr_getpshared + pthread_condattr_setpshared + + pthread_cond_init + pthread_cond_destroy + pthread_cond_wait + pthread_cond_timedwait + pthread_cond_signal + pthread_cond_broadcast + + --------------------------- + Read/Write Locks + --------------------------- + pthread_rwlock_init + pthread_rwlock_destroy + pthread_rwlock_tryrdlock + pthread_rwlock_trywrlock + pthread_rwlock_rdlock + pthread_rwlock_timedrdlock + pthread_rwlock_rwlock + pthread_rwlock_timedwrlock + pthread_rwlock_unlock + pthread_rwlockattr_init + pthread_rwlockattr_destroy + pthread_rwlockattr_getpshared + pthread_rwlockattr_setpshared + + --------------------------- + Spin Locks + --------------------------- + pthread_spin_init + pthread_spin_destroy + pthread_spin_lock + pthread_spin_unlock + pthread_spin_trylock + + --------------------------- + Barriers + --------------------------- + pthread_barrier_init + pthread_barrier_destroy + pthread_barrier_wait + pthread_barrierattr_init + pthread_barrierattr_destroy + pthread_barrierattr_getpshared + pthread_barrierattr_setpshared + + --------------------------- + Semaphores + --------------------------- + sem_init + sem_destroy + sem_post + sem_wait + sem_trywait + sem_timedwait + sem_getvalue (# free if +ve, # of waiters if -ve) + sem_open (returns an error ENOSYS) + sem_close (returns an error ENOSYS) + sem_unlink (returns an error ENOSYS) + + --------------------------- + RealTime Scheduling + --------------------------- + pthread_attr_getschedparam + pthread_attr_setschedparam + pthread_attr_getinheritsched + pthread_attr_setinheritsched + pthread_attr_getschedpolicy (only supports SCHED_OTHER) + pthread_attr_setschedpolicy (only supports SCHED_OTHER) + pthread_getschedparam + pthread_setschedparam + pthread_getconcurrency + pthread_setconcurrency + pthread_attr_getscope + pthread_attr_setscope (only supports PTHREAD_SCOPE_SYSTEM) + sched_get_priority_max + sched_get_priority_min + sched_rr_get_interval (returns an error ENOTSUP) + sched_setscheduler (only supports SCHED_OTHER) + sched_getscheduler (only supports SCHED_OTHER) + sched_yield + + --------------------------- + Signals + --------------------------- + pthread_sigmask + pthread_kill (only supports zero sig value, + for thread validity checking) + + --------------------------- + Non-portable routines (see the README.NONPORTABLE file for usage) + --------------------------- + pthread_getw32threadhandle_np + pthread_timechange_handler_np + pthread_delay_np + pthread_mutexattr_getkind_np + pthread_mutexattr_setkind_np (types: PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_TIMED_NP) + pthread_num_processors_np + pthread_win32_process_attach_np (Required when statically linking + the library) + pthread_win32_process_detach_np (Required when statically linking + the library) + pthread_win32_thread_attach_np (Required when statically linking + the library) + pthread_win32_thread_detach_np (Required when statically linking + the library) + + --------------------------- + Static Initializers + --------------------------- + PTHREAD_ONCE_INIT + PTHREAD_MUTEX_INITIALIZER + PTHREAD_RECURSIVE_MUTEX_INITIALIZER + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP + PTHREAD_COND_INITIALIZER + PTHREAD_RWLOCK_INITIALIZER + PTHREAD_SPINLOCK_INITIALIZER + + --------------------------- + Thread-Safe C Runtime Library (macros) + --------------------------- + strtok_r + asctime_r + ctime_r + gmtime_r + localtime_r + rand_r + + +The following functions are not implemented: + + --------------------------- + RealTime Scheduling + --------------------------- + pthread_mutex_getprioceiling + pthread_mutex_setprioceiling + pthread_mutex_attr_getprioceiling + pthread_mutex_attr_getprotocol + pthread_mutex_attr_setprioceiling + pthread_mutex_attr_setprotocol + + --------------------------- + Fork Handlers + --------------------------- + pthread_atfork + + --------------------------- + Stdio + --------------------------- + flockfile + ftrylockfile + funlockfile + getc_unlocked + getchar_unlocked + putc_unlocked + putchar_unlocked + + --------------------------- + Thread-Safe C Runtime Library + --------------------------- + readdir_r + getgrgid_r + getgrnam_r + getpwuid_r + getpwnam_r + + --------------------------- + Signals + --------------------------- + sigtimedwait + sigwait + sigwaitinfo + + --------------------------- + General + --------------------------- + sysconf + +The library includes two non-API functions for creating cancellation +points in applications and libraries: + + pthreadCancelableWait + pthreadCancelableTimedWait + + +Availability +------------ + +The prebuilt DLL, export libs (for both MSVC and Mingw32), and the header +files (pthread.h, semaphore.h, sched.h) are available along with the +complete source code. + +The source code can be found at: + + ftp://sources.redhat.com/pub/pthreads-win32 + +and as individual source code files at + + ftp://sources.redhat.com/pub/pthreads-win32/source + +The pre-built DLL, export libraries and include files can be found at: + + ftp://sources.redhat.com/pub/pthreads-win32/dll-latest + + + +Mailing List +------------ + +There is a mailing list for discussing pthreads on Win32. To join, +send email to: + + pthreads-win32-subscribe@sourceware.cygnus.com + + +Application Development Environments +------------------------------------ + +See the README file for more information. + +MSVC: +MSVC using SEH works. Distribute pthreadVSE.dll with your application. +MSVC using C++ EH works. Distribute pthreadVCE.dll with your application. +MSVC using C setjmp/longjmp works. Distribute pthreadVC.dll with your application. + + +Mingw32: +See the FAQ, Questions 6 and 10. + +Mingw using C++ EH works. Distribute pthreadGCE.dll with your application. +Mingw using C setjmp/longjmp works. Distribute pthreadGC.dll with your application. + + +Cygwin: (http://sourceware.cygnus.com/cygwin/) +Developers using Cygwin will not need pthreads-win32 since it has POSIX threads +support. Refer to its documentation for details and extent. + + +UWIN: +UWIN is a complete Unix-like environment for Windows from AT&T. Pthreads-win32 +doesn't currently support UWIN (and vice versa), but that may change in the +future. + +Generally: +For convenience, the following pre-built files are available on the FTP site +(see Availability above): + + pthread.h - for POSIX 1c threads + semaphore.h - for POSIX 1b semaphores + sched.h - for POSIX 1b scheduling + pthreadVCE.dll - built with MSVC++ compiler using C++ EH + pthreadVCE.lib + pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp + pthreadVC.lib + pthreadVSE.dll - built with MSVC compiler using SEH + pthreadVSE.lib + pthreadGCE.dll - built with Mingw32 G++ 2.95.2-1 + pthreadGC.dll - built with Mingw32 GCC 2.95.2-1 using setjmp/longjmp + libpthreadGCE.a - derived from pthreadGCE.dll + libpthreadGC.a - derived from pthreadGC.dll + gcc.dll - needed if distributing applications that use + pthreadGCE.dll (but see the FAQ Q 10 for the latest + related information) + +These are the only files you need in order to build POSIX threads +applications for Win32 using either MSVC or Mingw32. + +See the FAQ file in the source tree for additional information. + + +Documentation +------------- + +For the authoritative reference, see the online POSIX +standard reference at: + + http://www.OpenGroup.org + +For POSIX Thread API programming, several reference books are +available: + + Programming with POSIX Threads + David R. Butenhof + Addison-Wesley (pub) + + Pthreads Programming + By Bradford Nichols, Dick Buttlar & Jacqueline Proulx Farrell + O'Reilly (pub) + +On the web: see the links at the bottom of the pthreads-win32 site: + + http://sources.redhat.com/pthreads-win32/ + + Currently, there is no documentation included in the package apart + from the copious comments in the source code. + + + +Enjoy! + +Ross Johnson diff --git a/liblo/pthreads.2/BUGS b/liblo/pthreads.2/BUGS new file mode 100644 index 0000000..cb1780b --- /dev/null +++ b/liblo/pthreads.2/BUGS @@ -0,0 +1,133 @@ +---------- +Known bugs +---------- + +1. Not strictly a bug, more of a gotcha. + + Under MS VC++ (only tested with version 6.0), a term_func + set via the standard C++ set_terminate() function causes the + application to abort. + + Notes from the MSVC++ manual: + 1) A term_func() should call exit(), otherwise + abort() will be called on return to the caller. + A call to abort() raises SIGABRT and the default signal handler + for all signals terminates the calling program with + exit code 3. + 2) A term_func() must not throw an exception. Therefore + term_func() should not call pthread_exit(), which + works by throwing an exception (pthreadVCE or pthreadVSE) + or by calling longjmp (pthreadVC). + + Workaround: avoid using pthread_exit() in C++ applications. Exit + threads by dropping through the end of the thread routine. + +2. Cancellation problems in optimised code + - Milan Gardian + + This is suspected to be a compiler bug in VC6.0, and also seen in + VC7.0 and VS .NET 2003. The GNU C++ compiler does not have a problem + with this, and it has been reported that the Intel C++ 8.1 compiler + and Visual C++ 2005 Express Edition Beta2 pass tests\semaphore4.c + (which exposes the bug). + + Workaround [rpj - 2 Feb 2002] + ----------------------------- + [Please note: this workaround did not solve a similar problem in + snapshot-2004-11-03 or later, even though similar symptoms were seen. + tests\semaphore4.c fails in that snapshot for the VCE version of the + DLL.] + + The problem disappears when /Ob0 is used, i.e. /O2 /Ob0 works OK, + but if you want to use inlining optimisation you can be much more + specific about where it's switched off and on by using a pragma. + + So the inlining optimisation is interfering with the way that cleanup + handlers are run. It appears to relate to auto-inlining of class methods + since this is the only auto inlining that is performed at /O1 optimisation + (functions with the "inline" qualifier are also inlined, but the problem + doesn't appear to involve any such functions in the library or testsuite). + + In order to confirm the inlining culprit, the following use of pragmas + eliminate the problem but I don't know how to make it transparent, putting + it in, say, pthread.h where pthread_cleanup_push defined as a macro. + + #pragma inline_depth(0) + pthread_cleanup_push(handlerFunc, (void *) &arg); + + /* ... */ + + pthread_cleanup_pop(0); + #pragma inline_depth() + + Note the empty () pragma value after the pop macro. This resets depth to the + default. Or you can specify a non-zero depth here. + + The pragma is also needed (and now used) within the library itself wherever + cleanup handlers are used (condvar.c and rwlock.c). + + Use of these pragmas allows compiler optimisations /O1 and /O2 to be + used for either or both the library and applications. + + Experimenting further, I found that wrapping the actual cleanup handler + function with #pragma auto_inline(off|on) does NOT work. + + MSVC6.0 doesn't appear to support the C99 standard's _Pragma directive, + however, later versions may. This form is embeddable inside #define + macros, which would be ideal because it would mean that it could be added + to the push/pop macro definitions in pthread.h and hidden from the + application programmer. + + [/rpj] + + Original problem description + ---------------------------- + + The cancellation (actually, cleanup-after-cancel) tests fail when using VC + (professional) optimisation switches (/O1 or /O2) in pthreads library. I + have not investigated which concrete optimisation technique causes this + problem (/Og, /Oi, /Ot, /Oy, /Ob1, /Gs, /Gf, /Gy, etc.), but here is a + summary of builds and corresponding failures: + + * pthreads VSE (optimised tests): OK + * pthreads VCE (optimised tests): Failed "cleanup1" test (runtime) + + * pthreads VSE (DLL in CRT, optimised tests): OK + * pthreads VCE (DLL in CRT, optimised tests): Failed "cleanup1" test + (runtime) + + Please note that while in VSE version of the pthreads library the + optimisation does not really have any impact on the tests (they pass OK), in + VCE version addition of optimisation (/O2 in this case) causes the tests to + fail uniformly - either in "cleanup0" or "cleanup1" test cases. + + Please note that all the tests above use default pthreads DLL (no + optimisations, linked with either static or DLL CRT, based on test type). + Therefore the problem lies not within the pthreads DLL but within the + compiled client code (the application using pthreads -> involvement of + "pthread.h"). + + I think the message of this section is that usage of VCE version of pthreads + in applications relying on cancellation/cleanup AND using optimisations for + creation of production code is highly unreliable for the current version of + the pthreads library. + +3. The Borland Builder 5.5 version of the library produces memory read exceptions +in some tests. + +4. pthread_barrier_wait() can deadlock if the number of potential calling +threads for a particular barrier is greater than the barrier count parameter +given to pthread_barrier_init() for that barrier. + +This is due to the very lightweight implementation of pthread-win32 barriers. +To cope with more than "count" possible waiters, barriers must effectively +implement all the same safeguards as condition variables, making them much +"heavier" than at present. + +The workaround is to ensure that no more than "count" threads attempt to wait +at the barrier. + +5. Canceling a thread blocked on pthread_once appears not to work in the MSVC++ +version of the library "pthreadVCE.dll". The test case "once3.c" hangs. I have no +clues on this at present. All other versions pass this test ok - pthreadsVC.dll, +pthreadsVSE.dll, pthreadsGC.dll and pthreadsGCE.dll. diff --git a/liblo/pthreads.2/Bmakefile b/liblo/pthreads.2/Bmakefile new file mode 100644 index 0000000..4d06c71 --- /dev/null +++ b/liblo/pthreads.2/Bmakefile @@ -0,0 +1,266 @@ +# This makefile is compatible with BCB make. Use "make -fBMakefile" to compile. +# +# The variables $DLLDEST and $LIBDEST hold the destination directories for the +# dll and the lib, respectively. Probably all that needs to change is $DEVROOT. +# +# Currently only the recommended pthreadBC.dll is built by this makefile. +# + + +DLL_VER = 2 + +DEVROOT = . + +DLLDEST = $(DEVROOT)\DLL +LIBDEST = $(DEVROOT)\DLL + +DLLS = pthreadBC$(DLL_VER).dll + +OPTIM = /O2 + +RC = brcc32 +RCFLAGS = -i. + +CFLAGS = /q /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H=1 /4 /tWD /tWM \ + /w-aus /w-asc /w-par + +#C cleanup code +BCFLAGS = $(PTW32_FLAGS) $(CFLAGS) + +# Agregate modules for inlinability +DLL_OBJS = \ + attr.obj \ + barrier.obj \ + cancel.obj \ + cleanup.obj \ + condvar.obj \ + create.obj \ + dll.obj \ + errno.obj \ + exit.obj \ + fork.obj \ + global.obj \ + misc.obj \ + mutex.obj \ + nonportable.obj \ + private.obj \ + rwlock.obj \ + sched.obj \ + semaphore.obj \ + signal.obj \ + spin.obj \ + sync.obj \ + tsd.obj + +INCL = config.h implement.h semaphore.h pthread.h need_errno.h + +ATTR_SRCS = \ + pthread_attr_init.c \ + pthread_attr_destroy.c \ + pthread_attr_getdetachstate.c \ + pthread_attr_setdetachstate.c \ + pthread_attr_getstackaddr.c \ + pthread_attr_setstackaddr.c \ + pthread_attr_getstacksize.c \ + pthread_attr_setstacksize.c \ + pthread_attr_getscope.c \ + pthread_attr_setscope.c + +BARRIER_SRCS = \ + pthread_barrier_init.c \ + pthread_barrier_destroy.c \ + pthread_barrier_wait.c \ + pthread_barrierattr_init.c \ + pthread_barrierattr_destroy.c \ + pthread_barrierattr_setpshared.c \ + pthread_barrierattr_getpshared.c + +CANCEL_SRCS = \ + pthread_setcancelstate.c \ + pthread_setcanceltype.c \ + pthread_testcancel.c \ + pthread_cancel.c + +CONDVAR_SRCS = \ + ptw32_cond_check_need_init.c \ + pthread_condattr_destroy.c \ + pthread_condattr_getpshared.c \ + pthread_condattr_init.c \ + pthread_condattr_setpshared.c \ + pthread_cond_destroy.c \ + pthread_cond_init.c \ + pthread_cond_signal.c \ + pthread_cond_wait.c + +EXIT_SRCS = \ + pthread_exit.c + +MISC_SRCS = \ + pthread_equal.c \ + pthread_getconcurrency.c \ + pthread_once.c \ + pthread_self.c \ + pthread_setconcurrency.c \ + ptw32_calloc.c \ + ptw32_MCS_lock.c \ + ptw32_new.c \ + w32_CancelableWait.c + +MUTEX_SRCS = \ + ptw32_mutex_check_need_init.c \ + pthread_mutex_init.c \ + pthread_mutex_destroy.c \ + pthread_mutexattr_init.c \ + pthread_mutexattr_destroy.c \ + pthread_mutexattr_getpshared.c \ + pthread_mutexattr_setpshared.c \ + pthread_mutexattr_settype.c \ + pthread_mutexattr_gettype.c \ + pthread_mutex_lock.c \ + pthread_mutex_timedlock.c \ + pthread_mutex_unlock.c \ + pthread_mutex_trylock.c + +NONPORTABLE_SRCS = \ + pthread_mutexattr_setkind_np.c \ + pthread_mutexattr_getkind_np.c \ + pthread_getw32threadhandle_np.c \ + pthread_delay_np.c \ + pthread_num_processors_np.c \ + pthread_win32_attach_detach_np.c \ + pthread_timechange_handler_np.c + +PRIVATE_SRCS = \ + ptw32_is_attr.c \ + ptw32_processInitialize.c \ + ptw32_processTerminate.c \ + ptw32_threadStart.c \ + ptw32_threadDestroy.c \ + ptw32_tkAssocCreate.c \ + ptw32_tkAssocDestroy.c \ + ptw32_callUserDestroyRoutines.c \ + ptw32_timespec.c \ + ptw32_relmillisecs.c \ + ptw32_throw.c \ + ptw32_InterlockedCompareExchange.c \ + ptw32_getprocessors.c + +RWLOCK_SRCS = \ + ptw32_rwlock_check_need_init.c \ + ptw32_rwlock_cancelwrwait.c \ + pthread_rwlock_init.c \ + pthread_rwlock_destroy.c \ + pthread_rwlockattr_init.c \ + pthread_rwlockattr_destroy.c \ + pthread_rwlockattr_getpshared.c \ + pthread_rwlockattr_setpshared.c \ + pthread_rwlock_rdlock.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_wrlock.c \ + pthread_rwlock_timedwrlock.c \ + pthread_rwlock_unlock.c \ + pthread_rwlock_tryrdlock.c \ + pthread_rwlock_trywrlock.c + +SCHED_SRCS = \ + pthread_attr_setschedpolicy.c \ + pthread_attr_getschedpolicy.c \ + pthread_attr_setschedparam.c \ + pthread_attr_getschedparam.c \ + pthread_attr_setinheritsched.c \ + pthread_attr_getinheritsched.c \ + pthread_setschedparam.c \ + pthread_getschedparam.c \ + sched_get_priority_max.c \ + sched_get_priority_min.c \ + sched_setscheduler.c \ + sched_getscheduler.c \ + sched_yield.c + +SEMAPHORE_SRCS = \ + sem_init.c \ + sem_destroy.c \ + sem_trywait.c \ + sem_timedwait.c \ + sem_wait.c \ + sem_post.c \ + sem_post_multiple.c \ + sem_getvalue.c \ + sem_open.c \ + sem_close.c \ + sem_unlink.c + +SPIN_SRCS = \ + ptw32_spinlock_check_need_init.c \ + pthread_spin_init.c \ + pthread_spin_destroy.c \ + pthread_spin_lock.c \ + pthread_spin_unlock.c \ + pthread_spin_trylock.c + +SYNC_SRCS = \ + pthread_detach.c \ + pthread_join.c + +TSD_SRCS = \ + pthread_key_create.c \ + pthread_key_delete.c \ + pthread_setspecific.c \ + pthread_getspecific.c + + +all: clean $(DLLS) + +realclean: clean + if exist pthread*.dll del pthread*.dll + if exist pthread*.lib del pthread*.lib + if exist *.stamp del *.stamp + +clean: + if exist *.obj del *.obj + if exist *.ilk del *.ilk + if exist *.ilc del *.ilc + if exist *.ild del *.ild + if exist *.ilf del *.ilf + if exist *.ils del *.ils + if exist *.tds del *.tds + if exist *.pdb del *.pdb + if exist *.exp del *.exp + if exist *.map del *.map + if exist *.o del *.o + if exist *.i del *.i + if exist *.res del *.res + + +install: $(DLLS) + copy pthread*.dll $(DLLDEST) + copy pthread*.lib $(LIBDEST) + +$(DLLS): $(DLL_OBJS) version.res + ilink32 /Tpd /Gi c0d32x.obj $(DLL_OBJS), \ + $@, ,\ + cw32mti.lib import32.lib, ,\ + version.res + +.c.obj: + $(CC) $(OPTIM) $(BCFLAGS) -c $< + +.rc.res: + $(RC) $(RCFLAGS) $< + +attr.obj: attr.c $(ATTR_SRCS) $(INCL) +barrier.obj: barrier.c $(BARRIER_SRCS) $(INCL) +cancel.obj: cancel.c $(CANCEL_SRCS) $(INCL) +condvar.obj: condvar.c $(CONDVAR_SRCS) $(INCL) +exit.obj: exit.c $(EXIT_SRCS) $(INCL) +misc.obj: misc.c $(MISC_SRCS) $(INCL) +mutex.obj: mutex.c $(MUTEX_SRCS) $(INCL) +nonportable.obj: nonportable.c $(NONPORTABLE_SRCS) $(INCL) +private.obj: private.c $(PRIVATE_SRCS) $(INCL) +rwlock.obj: rwlock.c $(RWLOCK_SRCS) $(INCL) +sched.obj: sched.c $(SCHED_SRCS) $(INCL) +semaphore.obj: semaphore.c $(SEMAPHORE_SRCS) $(INCL) +spin.obj: spin.c $(SPIN_SRCS) $(INCL) +sync.obj: sync.c $(SYNC_SRCS) $(INCL) +tsd.obj: tsd.c $(TSD_SRCS) $(INCL) +version.res: version.rc $(INCL) diff --git a/liblo/pthreads.2/BuildLog.htm b/liblo/pthreads.2/BuildLog.htm new file mode 100644 index 0000000..8aebecb Binary files /dev/null and b/liblo/pthreads.2/BuildLog.htm differ diff --git a/liblo/pthreads.2/CONTRIBUTORS b/liblo/pthreads.2/CONTRIBUTORS new file mode 100644 index 0000000..2f70e38 --- /dev/null +++ b/liblo/pthreads.2/CONTRIBUTORS @@ -0,0 +1,129 @@ +Contributors (in approximate order of appearance) + +[See also the ChangeLog file where individuals are +attributed in log entries. Likewise in the FAQ file.] + +Ben Elliston bje at cygnus dot com + Initiated the project; + setup the project infrastructure (CVS, web page, etc.); + early prototype routines. +Ross Johnson rpj at callisto dot canberra dot edu dot au + early prototype routines; + ongoing project coordination/maintenance; + implementation of spin locks and barriers; + various enhancements; + bug fixes; + documentation; + testsuite. +Robert Colquhoun rjc at trump dot net dot au + Early bug fixes. +John E. Bossom John dot Bossom at cognos dot com + Contributed substantial original working implementation; + bug fixes; + ongoing guidance and standards interpretation. +Anders Norlander anorland at hem2 dot passagen dot se + Early enhancements and runtime checking for supported + Win32 routines. +Tor Lillqvist tml at iki dot fi + General enhancements; + early bug fixes to condition variables. +Scott Lightner scott at curriculum dot com + Bug fix. +Kevin Ruland Kevin dot Ruland at anheuser-busch dot com + Various bug fixes. +Mike Russo miker at eai dot com + Bug fix. +Mark E. Armstrong avail at pacbell dot net + Bug fixes. +Lorin Hochstein lmh at xiphos dot ca + general bug fixes; bug fixes to condition variables. +Peter Slacik Peter dot Slacik at tatramed dot sk + Bug fixes. +Mumit Khan khan at xraylith dot wisc dot edu + Fixes to work with Mingw32. +Milan Gardian mg at tatramed dot sk + Bug fixes and reports/analyses of obscure problems. +Aurelio Medina aureliom at crt dot com + First implementation of read-write locks. +Graham Dumpleton Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au + Bug fix in condition variables. +Tristan Savatier tristan at mpegtv dot com + WinCE port. +Erik Hensema erik at hensema dot xs4all dot nl + Bug fixes. +Rich Peters rpeters at micro-magic dot com +Todd Owen towen at lucidcalm dot dropbear dot id dot au + Bug fixes to dll loading. +Jason Nye jnye at nbnet dot nb dot ca + Implementation of async cancelation. +Fred Forester fforest at eticomm dot net +Kevin D. Clark kclark at cabletron dot com +David Baggett dmb at itasoftware dot com + Bug fixes. +Paul Redondo paul at matchvision dot com +Scott McCaskill scott at 3dfx dot com + Bug fixes. +Jef Gearhart jgearhart at tpssys dot com + Bug fix. +Arthur Kantor akantor at bexusa dot com + Mutex enhancements. +Steven Reddie smr at essemer dot com dot au + Bug fix. +Alexander Terekhov TEREKHOV at de dot ibm dot com + Re-implemented and improved read-write locks; + (with Louis Thomas) re-implemented and improved + condition variables; + enhancements to semaphores; + enhancements to mutexes; + new mutex implementation in 'futex' style; + suggested a robust implementation of pthread_once + similar to that implemented by V.Kliathcko; + system clock change handling re CV timeouts; + bug fixes. +Thomas Pfaff tpfaff at gmx dot net + Changes to make C version usable with C++ applications; + re-implemented mutex routines to avoid Win32 mutexes + and TryEnterCriticalSection; + procedure to fix Mingw32 thread-safety issues. +Franco Bez franco dot bez at gmx dot de + procedure to fix Mingw32 thread-safety issues. +Louis Thomas lthomas at arbitrade dot com + (with Alexander Terekhov) re-implemented and improved + condition variables. +David Korn dgk at research dot att dot com + Ported to UWIN. +Phil Frisbie, Jr. phil at hawksoft dot com + Bug fix. +Ralf Brese Ralf dot Brese at pdb4 dot siemens dot de + Bug fix. +prionx at juno dot com prionx at juno dot com + Bug fixes. +Max Woodbury mtew at cds dot duke dot edu + POSIX versioning conditionals; + reduced namespace pollution; + idea to separate routines to reduce statically + linked image sizes. +Rob Fanner rfanner at stonethree dot com + Bug fix. +Michael Johnson michaelj at maine dot rr dot com + Bug fix. +Nicolas Barry boozai at yahoo dot com + Bug fixes. +Piet van Bruggen pietvb at newbridges dot nl + Bug fix. +Makoto Kato raven at oldskool dot jp + AMD64 port. +Panagiotis E. Hadjidoukas peh at hpclab dot ceid dot upatras dot gr + Contributed the QueueUserAPCEx package which + makes preemptive async cancelation possible. +Will Bryant will dot bryant at ecosm dot com + Borland compiler patch and makefile. +Anuj Goyal anuj dot goyal at gmail dot com + Port to Digital Mars compiler. +Gottlob Frege gottlobfrege at gmail dot com + re-implemented pthread_once (version 2) + (pthread_once cancellation added by rpj). +Vladimir Kliatchko vladimir at kliatchko dot com + reimplemented pthread_once with the same form + as described by A.Terekhov (later version 2); + implementation of MCS (Mellor-Crummey/Scott) locks. diff --git a/liblo/pthreads.2/COPYING b/liblo/pthreads.2/COPYING new file mode 100644 index 0000000..af8e3db --- /dev/null +++ b/liblo/pthreads.2/COPYING @@ -0,0 +1,150 @@ + pthreads-win32 - a POSIX threads library for Microsoft Windows + + +This file is Copyrighted +------------------------ + + This file is covered under the following Copyright: + + Copyright (C) 2001,2006 Ross P. Johnson + All rights reserved. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Pthreads-win32 is covered by the GNU Lesser General Public License +------------------------------------------------------------------ + + Pthreads-win32 is open 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 version 2.1 of the + License. + + Pthreads-win32 is several binary link libraries, several modules, + associated interface definition files and scripts used to control + its compilation and installation. + + Pthreads-win32 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. + + A copy of the GNU Lesser General Public License is distributed with + pthreads-win32 under the filename: + + COPYING.LIB + + You should have received a copy of the version 2.1 GNU Lesser General + Public License with pthreads-win32; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place + Suite 330 + Boston, MA 02111-1307 + USA + + The contact addresses for pthreads-win32 is as follows: + + Web: http://sources.redhat.com/pthreads-win32 + Email: Ross Johnson + Please use: Firstname.Lastname@homemail.com.au + + + +Pthreads-win32 copyrights and exception files +--------------------------------------------- + + With the exception of the files listed below, Pthreads-win32 + is covered under the following GNU Lesser General Public License + Copyrights: + + Pthreads-win32 - POSIX Threads Library for Win32 + Copyright(C) 1998 John E. Bossom + Copyright(C) 1999,2006 Pthreads-win32 contributors + + The current list of contributors is contained + in the file CONTRIBUTORS included with the source + code distribution. The current list of CONTRIBUTORS + can also be seen at the following WWW location: + http://sources.redhat.com/pthreads-win32/contributors.html + + Contact Email: Ross Johnson + Please use: Firstname.Lastname@homemail.com.au + + These files are not covered under one of the Copyrights listed above: + + COPYING + COPYING.LIB + tests/rwlock7.c + + This file, COPYING, is distributed under the Copyright found at the + top of this file. It is important to note that you may distribute + verbatim copies of this file but you may not modify this file. + + The file COPYING.LIB, which contains a copy of the version 2.1 + GNU Lesser General Public License, is itself copyrighted by the + Free Software Foundation, Inc. Please note that the Free Software + Foundation, Inc. does NOT have a copyright over Pthreads-win32, + only the COPYING.LIB that is supplied with pthreads-win32. + + The file tests/rwlock7.c is derived from code written by + Dave Butenhof for his book 'Programming With POSIX(R) Threads'. + The original code was obtained by free download from his website + http://home.earthlink.net/~anneart/family/Threads/source.html + and did not contain a copyright or author notice. It is assumed to + be freely distributable. + + In all cases one may use and distribute these exception files freely. + And because one may freely distribute the LGPL covered files, the + entire pthreads-win32 source may be freely used and distributed. + + + +General Copyleft and License info +--------------------------------- + + For general information on Copylefts, see: + + http://www.gnu.org/copyleft/ + + For information on GNU Lesser General Public Licenses, see: + + http://www.gnu.org/copyleft/lesser.html + http://www.gnu.org/copyleft/lesser.txt + + +Why pthreads-win32 did not use the GNU General Public License +------------------------------------------------------------- + + The goal of the pthreads-win32 project has been to + provide a quality and complete implementation of the POSIX + threads API for Microsoft Windows within the limits imposed + by virtue of it being a stand-alone library and not + linked directly to other POSIX compliant libraries. For + example, some functions and features, such as those based + on POSIX signals, are missing. + + Pthreads-win32 is a library, available in several different + versions depending on supported compilers, and may be used + as a dynamically linked module or a statically linked set of + binary modules. It is not an application on it's own. + + It was fully intended that pthreads-win32 be usable with + commercial software not covered by either the GPL or the LGPL + licenses. Pthreads-win32 has many contributors to it's + code base, many of whom have done so because they have + used the library in commercial or proprietry software + projects. + + Releasing pthreads-win32 under the LGPL ensures that the + library can be used widely, while at the same time ensures + that bug fixes and improvements to the pthreads-win32 code + itself is returned to benefit all current and future users + of the library. + + Although pthreads-win32 makes it possible for applications + that use POSIX threads to be ported to Win32 platforms, the + broader goal of the project is to encourage the use of open + standards, and in particular, to make it just a little easier + for developers writing Win32 applications to consider + widening the potential market for their products. diff --git a/liblo/pthreads.2/COPYING.LIB b/liblo/pthreads.2/COPYING.LIB new file mode 100644 index 0000000..cbee875 --- /dev/null +++ b/liblo/pthreads.2/COPYING.LIB @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library 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 2.1 of the License, or (at your option) any later version. + + This library 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 library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/liblo/pthreads.2/ChangeLog b/liblo/pthreads.2/ChangeLog new file mode 100644 index 0000000..d26d980 --- /dev/null +++ b/liblo/pthreads.2/ChangeLog @@ -0,0 +1,4821 @@ +2006-12-20 Ross Johnson + + * sem_destroy.c: Fix the race involving invalidation of the sema; + fix incorrect return of EBUSY resulting from the mutex trylock + on the private mutex guard. + * sem_wait.c: Add check for invalid sem_t after acquiring the + sem_t state guard mutex and before affecting changes to sema state. + * sem_trywait.c: Likewise. + * sem_timedwait.c: Likewise. + * sem_getvalue.c: Likewise. + * sem_post.c: Similar. + * sem_post_multiple.c: Likewise. + * sem_init.c: Set max Win32 semaphore count to SEM_VALUE_MAX (was + _POSIX_SEM_VALUE_MAX, which is a lower value - the minimum). + + * pthread_win32_attach_detach_np.c (pthread_win32_process_attach_np): + Load COREDLL.DLL under WINCE to check existence of + InterlockedCompareExchange() routine. This used to be done to test + for TryEnterCriticalSection() but was removed when this was no + longer needed. + +2006-01-25 Prashant Thakre + + * pthread_cancel.c: Added _M_IA64 register context support. + +2005-05-13 Ross Johnson + + * pthread_kill.c (pthread_kill): Remove check for Win32 thread + priority (to confirm HANDLE validity). Useless since thread HANDLEs + a not recycle-unique. + +2005-05-30 Vladimir Kliatchko + + * pthread_once.c: Re-implement using an MCS queue-based lock. The form + of pthread_once is as proposed by Alexander Terekhov (see entry of + 2005-03-13). The MCS lock implementation does not require a unique + 'name' to identify the lock between threads. Attempts to get the Event + or Semaphore based versions of pthread_once to a satisfactory level + of robustness have thus far failed. The last problem (avoiding races + involving non recycle-unique Win32 HANDLEs) was giving everyone + grey hair trying to solve it. + + * ptw32_MCS_lock.c: New MCS queue-based lock implementation. These + locks are efficient: they have very low overhead in the uncontended case; + are efficient in contention and minimise cache-coherence updates in + managing the user level FIFO queue; do not require an ABI change in the + library. + +2005-05-27 Alexander Gottwald + + * pthread.h: Some things, like HANDLE, were only defined if + PTW32_LEVEL was >= 3. They should always be defined. + +2005-05-25 Vladimir Kliatchko + + * pthread_once.c: Eliminate all priority operations and other + complexity by replacing the event with a semaphore. The advantage + of the change is the ability to release just one waiter if the + init_routine thread is cancelled yet still release all waiters when + done. Simplify once_control state checks to improve efficiency + further. + +2005-05-24 Mikael Magnusson + + * GNUmakefile: Patched to allow cross-compile with mingw32 on Linux. + It uses macros instead of referencing dlltool, gcc and g++ directly; + added a call to ranlib. For example the GC static library can be + built with: + make CC=i586-mingw32msvc-gcc RC=i586-mingw32msvc-windres \ + RANLIB=i586-mingw32msvc-ranlib clean GC-static + +2005-05-13 Ross Johnson + + * pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np): + Move on-exit-only stuff from ptw32_threadDestroy() to here. + * ptw32_threadDestroy.c: It's purpose is now only to reclaim thread + resources for detached threads, or via pthread_join() or + pthread_detach() on joinable threads. + * ptw32_threadStart.c: Calling user destruct routines has moved to + pthread_win32_thread_detach_np(); call pthread_win32_thread_detach_np() + directly if statically linking, otherwise do so via dllMain; store + thread return value in thread struct for all cases, including + cancellation and exception exits; thread abnormal exits go via + pthread_win32_thread_detach_np. + * pthread_join.c (pthread_join): Don't try to get return code from + Win32 thread - always get it from he thread struct. + * pthread_detach.c (pthread_detach): reduce extent of the thread + existence check since we now don't care if the Win32 thread HANDLE has + been closed; reclaim thread resources if the thread has exited already. + * ptw32_throw.c (ptw32_throw): For Win32 threads that are not implicit, + only Call thread cleanup if statically linking, otherwise leave it to + dllMain. + * sem_post.c (_POSIX_SEM_VALUE_MAX): Change to SEM_VALUE_MAX. + * sem_post_multiple.c: Likewise. + * sem_init.c: Likewise. + +2005-05-10 Ross Johnson + + * pthread_join.c (pthread_join): Add missing check for thread ID + reference count in thread existence test; reduce extent of the + existence test since we don't care if the Win32 thread HANDLE has + been closed. + +2005-05-09 Ross Johnson + + * ptw32_callUserDestroyRoutines.c: Run destructor process (i.e. + loop over all keys calling destructors) up to + PTHREAD_DESTRUCTOR_ITERATIONS times if TSD value isn't NULL yet; + modify assoc management. + * pthread_key_delete.c: Modify assoc management. + * ptw32_tkAssocDestroy.c: Fix error in assoc removal from chains. + * pthread.h + (_POSIX_THREAD_DESTRUCTOR_ITERATIONS): Define to value specified by + POSIX. + (_POSIX_THREAD_KEYS_MAX): Define to value specified by POSIX. + (PTHREAD_KEYS_MAX): Redefine [upward] to minimum required by POSIX. + (SEM_NSEMS_MAX): Define to implementation value. + (SEM_VALUE_MAX): Define to implementation value. + (_POSIX_SEM_NSEMS_MAX): Redefine to value specified by POSIX. + (_POSIX_SEM_VALUE_MAX): Redefine to value specified by POSIX. + +2005-05-06 Ross Johnson + + * signal.c (sigwait): Add a cancellation point to this otherwise + no-op. + * sem_init.c (sem_init): Check for and return ERANGE error. + * sem_post.c (sem_post): Likewise. + * sem_post_multiple.c (sem_post_multiple): Likewise. + * manual (directory): Added; see ChangeLog inside. + +2005-05-02 Ross Johnson + + * implement.h (struct pthread_key_t_): Change threadsLock to keyLock + so as not to be confused with the per thread lock 'threadlock'; + change all references to it. + * implement.h (struct ThreadKeyAssoc): Remove lock; add prevKey + and prevThread pointers; re-implemented all routines that use this + struct. The effect of this is to save one handle per association, + which could potentially equal the number of keys multiplied by the + number of threads, accumulating over time - and to free the + association memory as soon as it is no longer referenced by either + the key or the thread. Previously, the handle and memory were + released only after BOTH key and thread no longer referenced the + association. That is, often no association resources were released + until the process itself exited. In addition, at least one race + condition has been removed - where two threads could attempt to + release the association resources simultaneously - one via + ptw32_callUserDestroyRoutines and the other via + pthread_key_delete. + - thanks to Richard Hughes at Aculab for discovering the problem. + * pthread_key_create.c: See above. + * pthread_key_delete.c: See above. + * pthread_setspecific.c: See above. + * ptw32_callUserDestroyRoutines.c: See above. + * ptw32_tkAssocCreate.c: See above. + * ptw32_tkAssocDestroy.c: See above. + +2005-04-27 Ross Johnson + + * sem_wait.c (ptw32_sem_wait_cleanup): after cancellation re-attempt + to acquire the semaphore to avoid a race with a late sem_post. + * sem_timedwait.c: Modify comments. + +2005-04-25 Ross Johnson + + * ptw32_relmillisecs.c: New module; converts future abstime to + milliseconds relative to 'now'. + * pthread_mutex_timedlock.c: Use new ptw32_relmillisecs routine in + place of internal code; remove the NEED_SEM code - this routine is now + implemented for builds that define NEED_SEM (WinCE etc) + * sem_timedwait.c: Likewise; after timeout or cancellation, + re-attempt to acquire the semaphore in case one has been posted since + the timeout/cancel occurred. Thanks to Stefan Mueller. + * Makefile: Add ptw32_relmillisecs.c module; remove + ptw32_{in,de}crease_semaphore.c modules. + * GNUmakefile: Likewise. + * Bmakefile: Likewise. + + * sem_init.c: Re-write the NEED_SEM code to be consistent with the + non-NEED_SEM code, but retaining use of an event in place of the w32 sema + for w32 systems that don't include semaphores (WinCE); + the NEED_SEM versions of semaphores has been broken for a long time but is + now fixed and supports all of the same routines as the non-NEED_SEM case. + * sem_destroy.c: Likewise. + * sem_wait.c: Likewise. + * sem_post.c: Likewise. + * sem_post_multple.c: Likewise. + * implement.h: Likewise. + * sem_timedwait.c: Likewise; this routine is now + implemented for builds that define NEED_SEM (WinCE etc). + * sem_trywait.c: Likewise. + * sem_getvalue.c: Likewise. + + * pthread_once.c: Yet more changes, reverting closer to Gottlob Frege's + first design, but retaining cancellation, priority boosting, and adding + preservation of W32 error codes to make pthread_once transparent to + GetLastError. + +2005-04-11 Ross Johnson + + * pthread_once.c (pthread_once): Added priority boosting to + solve starvation problem after once_routine cancellation. + See notes in file. + +2005-04-06 Kevin Lussier + + * Makefile: Added debug targets for all versions of the library. + +2005-04-01 Ross Johnson + + * GNUmakefile: Add target to build libpthreadGC1.a as a static link + library. + * Makefile: Likewise for pthreadGC1.lib. + +2005-04-01 Kevin Lussier + + * sem_timedwait.c (sem_timedwait): Increase size of temp variables to + avoid int overflows for large timeout values. + * implement.h (int64_t): Include or define. + +2005-03-31 Dimitar Panayotov ^M + + * pthread.h: Fix conditional defines for static linking. + * sched.h: Liekwise. + * semaphore.h: Likewise. + * dll.c (PTW32_STATIC_LIB): Module is conditionally included + in the build. + +2005-03-16 Ross Johnson ^M + + * pthread_setcancelstate.c: Undo the last change. + +2005-03-16 Ross Johnson ^M + + * pthread_setcancelstate.c: Don't check for an async cancel event + if the library is using alertable async cancel.. + +2005-03-14 Ross Johnson + + * pthread_once.c (pthread_once): Downgrade interlocked operations to simple + memory operations where these are protected by the critical section; edit + comments. + +2005-03-13 Ross Johnson + + * pthread_once.c (pthread_once): Completely redesigned; a change was + required to the ABI (pthread_once_t_), and resulting in a version + compatibility index increment. + + NOTES: + The design (based on pseudo code contributed by Gottlob Frege) avoids + creating a kernel object if there is no contention. See URL for details:- + http://sources.redhat.com/ml/pthreads-win32/2005/msg00029.html + This uses late initialisation similar to the technique already used for + pthreads-win32 mutexes and semaphores (from Alexander Terekhov). + + The subsequent cancelation cleanup additions (by rpj) could not be implemented + without sacrificing some of the efficiency in Gottlob's design. In particular, + although each once_control uses it's own event to block on, a global CS is + required to manage it - since the event must be either re-usable or + re-creatable under cancelation. This is not needed in the non-cancelable + design because it is able to mark the event as closed (forever). + + When uncontested, a CS operation is equivalent to an Interlocked operation + in speed. So, in the final design with cancelability, an uncontested + once_control operation involves a minimum of five interlocked operations + (including the LeaveCS operation). + + ALTERNATIVES: + An alternative design from Alexander Terekhov proposed using a named mutex, + as sketched below:- + + if (!once_control) { // May be in TLS + named_mutex::guard guard(&once_control2); + if (!once_control2) { + + once_control2 = true; + } + once_control = true; + } + + A more detailed description of this can be found here:- + http://groups.yahoo.com/group/boost/message/15442 + + [Although the definition of a suitable PTHREAD_ONCE_INIT precludes use of the + TLS located flag, this is not critical.] + + There are three primary concerns though:- + 1) The [named] mutex is 'created' even in the uncontended case. + 2) A system wide unique name must be generated. + 3) Win32 mutexes are VERY slow even in the uncontended case. An uncontested + Win32 mutex lock operation can be 50 (or more) times slower than an + uncontested EnterCS operation. + + Ultimately, the named mutex trick is making use of the global locks maintained + by the kernel. + + * pthread.h (pthread_once_t_): One flag and an event HANDLE added. + (PTHREAD_ONCE_INIT): Additional values included. + +2005-03-08 Ross Johnson + + * pthread_once.c (pthread_once): Redesigned to elliminate potential + starvation problem. + - reported by Gottlob Frege + + * ptw32_threadDestroy.c (ptw32_threadDestroy): Implicit threads were + not closing their Win32 thread duplicate handle. + - reported by Dmitrii Semii + +2005-01-25 Ralf Kubis + + * Attempted acquisition of recursive mutex was causing waiting + threads to not be woken when the mutex is released. + + * GNUmakefile (GCE): Generate correct version resource comments. + +2005-01-01 Konstantin Voronkov + + * pthread_mutex_lock.c (pthread_mutex_lock): The new atomic exchange + mutex algorithm is known to allow a thread to steal the lock off + FIFO waiting threads. The next waiting FIFO thread gets a spurious + wake-up and must attempt to re-acquire the lock. The woken thread + was setting itself as the mutex's owner before the re-acquisition. + +2004-11-22 Ross Johnson + + * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Undo change + from 2004-11-02. + * Makefile (DLL_VER): Added for DLL naming suffix - see README. + * GNUmakefile (DLL_VER): Likewise. + * Wmakefile (DLL_VER): Likewise. + * Bmakefile (DLL_VER): Likewise. + * pthread.dsw (version.rc): Added to MSVS workspace. + +2004-11-20 Boudewijn Dekker + + * pthread_getspecific.c (pthread_getspecific): Check for + invalid (NULL) key argument. + +2004-11-19 Ross Johnson + + * config.h (PTW32_THREAD_ID_REUSE_INCREMENT): Added to allow + building the library for either unique thread IDs like Solaris + or non-unique thread IDs like Linux; allows application developers + to override the library's default insensitivity to some apps + that may not be strictly POSIX compliant. + * version.rc: New resource module to encode version information + within the DLL. + * pthread.h: Added PTW32_VERSION* defines and grouped sections + required by resource compiler together; bulk of file is skipped + if RC_INVOKED. Defined some error numbers and other names for + Borland compiler. + +2004-11-02 Ross Johnson + + * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Lock CV mutex at + start of cleanup handler rather than at the end. + * implement.h (PTW32_THREAD_REUSE_EMPTY): Renamed from *_BOTTOM. + (ptw32_threadReuseBottom): New global variable. + * global.c (ptw32_threadReuseBottom): Declare new variable. + * ptw32_reuse.c (ptw32_reuse): Change reuse LIFO stack to LILO queue + to more evenly distribute use of reusable thread IDs; use renamed + PTW32_THREAD_REUSE_EMPTY. + * ptw32_processTerminate.c (ptw2_processTerminate): Use renamed + PTW32_THREAD_REUSE_EMPTY. + +2004-10-31 Ross Johnson + + * implement.h (PThreadState): Add new state value + 'PThreadStateCancelPending'. + * pthread_testcancel.c (pthread_testcancel): Use new thread + 'PThreadStateCancelPending' state as short cut to avoid entering + kernel space via WaitForSingleObject() call. This was obviated + by user space sema acquisition in sem_wait() and sem_timedwait(), + which are also cancelation points. A call to pthread_testcancel() + was required, which introduced a kernel call, effectively nullifying + any gains made by the user space sem acquisition checks. + * pthread_cancel.c (pthread_cancel): Set new thread + 'PThreadStateCancelPending' state. + +2004-10-29 Ross Johnson + + * implement.h (pthread_t): Renamed to ptw32_thread_t; struct contains + all thread state. + * pthread.h (ptw32_handle_t): New general purpose struct to serve + as a handle for various reusable object IDs - currently only used + by pthread_t; contains a pointer to ptw32_thread_t (thread state) + and a general purpose uint for use as a reuse counter or flags etc. + (pthread_t): typedef'ed to ptw32_handle_t; the uint is the reuse + counter that allows the library to maintain unique POSIX thread IDs. + When the pthread struct reuse stack was introduced, threads would + often acquire an identical ID to a previously destroyed thread. The + same was true for the pre-reuse stack library, by virtue of pthread_t + being the address of the thread struct. The new pthread_t retains + the reuse stack but provides virtually unique thread IDs. + * sem_wait.c (ptw32_sem_wait_cleanup): New routine used for + cancelation cleanup. + * sem_timedwait.c (ptw32_sem_timedwait_cleanup): Likewise. + +2004-10-22 Ross Johnson + + * sem_init.c (sem_init): Introduce a 'lock' element in order to + replace the interlocked operations with conventional serialisation. + This is needed in order to be able to atomically modify the sema + value and perform Win32 sema release operations. Win32 semaphores are + used instead of events in order to support efficient multiple posting. + If the whole modify/release isn't atomic, a race between + sem_timedwait() and sem_post() could result in a release when there is + no waiting semaphore, which would cause too many threads to proceed. + * sem_wait.c (sem_wait): Use new 'lock'element. + * sem_timedwait.c (sem_timedwait): Likewise. + * sem_trywait.c (sem_trywait): Likewise. + * sem_post.c (sem_post): Likewise. + * sem_post_multiple.c (sem_post_multiple): Likewise. + * sem_getvalue.c (sem_getvalue): Likewise. + * ptw32_semwait.c (ptw32_semwait): Likewise. + * sem_destroy.c (sem_destroy): Likewise; also tightened the conditions + for semaphore destruction; in particular, a semaphore will not be + destroyed if it has waiters. + * sem_timedwait.c (sem_timedwait): Added cancel cleanup handler to + restore sema value when cancelled. + * sem_wait.c (sem_wait): Likewise. + +2004-10-21 Ross Johnson + + * pthread_mutex_unlock.c (pthread_mutex_unlock): Must use PulseEvent() + rather than SetEvent() to reset the event if there are no waiters. + +2004-10-19 Ross Johnson + + * sem_init.c (sem_init): New semaphore model based on the same idea + as mutexes, i.e. user space interlocked check to avoid + unnecessarily entering kernel space. Wraps the Win32 semaphore and + keeps it's own counter. Although the motivation to do this has existed + for a long time, credit goes to Alexander Terekhov for providing + the logic. I have deviated slightly from AT's logic to add the waiters + count, which has made the code more complicated by adding cancelation + cleanup. This also appears to have broken the VCE (C++ EH) version of + the library (the same problem as previously reported - see BUGS #2), + only apparently not fixable using the usual workaround, nor by turning + all optimisation off. The GCE version works fine, so it is presumed to + be a bug in MSVC++ 6.0. The cancelation exception is thrown and caught + correctly, but the cleanup class destructor is never called. The failing + test is tests\semaphore4.c. + * sem_wait.c (sem_wait): Implemented user space check model. + * sem_post.c (sem_post): Likewise. + * sem_trywait.c (sem_trywait): Likewise. + * sem_timedwait.c (sem_timedwait): Likewise. + * sem_post_multiple.c (sem_post_multiple): Likewise. + * sem_getvalue.c (sem_getvalue): Likewise. + * ptw32_semwait.c (ptw32_semwait): Likewise. + * implement.h (sem_t_): Add counter element. + +2004-10-15 Ross Johnson + + * implement.h (pthread_mutex_t_): Use an event in place of + the POSIX semaphore. + * pthread_mutex_init.c: Create the event; remove semaphore init. + * pthread_mutex_destroy.c: Delete the event. + * pthread_mutex_lock.c: Replace the semaphore wait with the event wait. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_unlock.c: Set the event. + +2004-10-14 Ross Johnson + + * pthread_mutex_lock.c (pthread_mutex_lock): New algorithm using + Terekhov's xchg based variation of Drepper's cmpxchg model. + Theoretically, xchg uses fewer clock cycles than cmpxchg (using IA-32 + as a reference), however, in my opinion bus locking dominates the + equation on smp systems, so the model with the least number of bus + lock operations in the execution path should win, which is Terekhov's + variant. On IA-32 uni-processor systems, it's faster to use the + CMPXCHG instruction without locking the bus than to use the XCHG + instruction, which always locks the bus. This makes the two variants + equal for the non-contended lock (fast lane) execution path on up + IA-32. Testing shows that the xchg variant is faster on up IA-32 as + well if the test forces higher lock contention frequency, even though + kernel calls should be dominating the times (on up IA-32, both + variants used CMPXCHG instructions and neither locked the bus). + * pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly. + * pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly. + * pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly. + * ptw32_InterlockedCompareExchange.c (ptw32_InterlockExchange): New + function. + (PTW32_INTERLOCKED_EXCHANGE): Sets up macro to use inlined + ptw32_InterlockedExchange. + * implement.h (PTW32_INTERLOCKED_EXCHANGE): Set default to + InterlockedExchange(). + * Makefile: Building using /Ob2 so that asm sections within inline + functions are inlined. + +2004-10-08 Ross Johnson + + * pthread_mutex_destroy.c (pthread_mutex_destroy): Critical Section + element is no longer required. + * pthread_mutex_init.c (pthread_mutex_init): Likewise. + * pthread_mutex_lock.c (pthread_mutex_lock): New algorithm following + Drepper's paper at http://people.redhat.com/drepper/futex.pdf, but + using the existing semaphore in place of the futex described in the + paper. Idea suggested by Alexander Terekhov - see: + http://sources.redhat.com/ml/pthreads-win32/2003/msg00108.html + * pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly. + * pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly. + * pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly. + * pthread_barrier_wait.c (pthread_barrier_wait): Use inlined version + of InterlockedCompareExchange() if possible - determined at + build-time. + * pthread_spin_destroy.c pthread_spin_destroy(): Likewise. + * pthread_spin_lock.c pthread_spin_lock():Likewise. + * pthread_spin_trylock.c (pthread_spin_trylock):Likewise. + * pthread_spin_unlock.c (pthread_spin_unlock):Likewise. + * ptw32_InterlockedCompareExchange.c: Sets up macro for inlined use. + * implement.h (pthread_mutex_t_): Remove Critical Section element. + (PTW32_INTERLOCKED_COMPARE_EXCHANGE): Set to default non-inlined + version of InterlockedCompareExchange(). + * private.c: Include ptw32_InterlockedCompareExchange.c first for + inlining. + * GNUmakefile: Add commandline option to use inlined + InterlockedCompareExchange(). + * Makefile: Likewise. + +2004-09-27 Ross Johnson + + * pthread_mutex_lock.c (pthread_mutex_lock): Separate + PTHREAD_MUTEX_NORMAL logic since we do not need to keep or check some + state required by other mutex types; do not check mutex pointer arg + for validity - leave this to the system since we are only checking + for NULL pointers. This should improve speed of NORMAL mutexes and + marginally improve speed of other type. + * pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise. + * pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise; also avoid + entering the critical section for the no-waiters case, with approx. + 30% reduction in lock/unlock overhead for this case. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise; also + no longer keeps mutex if post-timeout second attempt succeeds - this + will assist applications that wish to impose strict lock deadlines, + rather than simply to escape from frozen locks. + +2004-09-09 Tristan Savatier + * pthread.h (struct pthread_once_t_): Qualify the 'done' element + as 'volatile'. + * pthread_once.c: Concerned about possible race condition, + specifically on MPU systems re concurrent access to multibyte types. + [Maintainer's note: the race condition is harmless on SPU systems + and only a problem on MPU systems if concurrent access results in an + exception (presumably generated by a hardware interrupt). There are + other instances of similar harmless race conditions that have not + been identified as issues.] + +2004-09-09 Ross Johnson + + * pthread.h: Declare additional types as volatile. + +2004-08-27 Ross Johnson + + * pthread_barrier_wait.c (pthread_barrier_wait): Remove excessive code + by substituting the internal non-cancelable version of sem_wait + (ptw32_semwait). + +2004-08-25 Ross Johnson + + * pthread_join.c (pthread_join): Rewrite and re-order the conditional + tests in an attempt to improve efficiency and remove a race + condition. + +2004-08-23 Ross Johnson + + * create.c (pthread_create): Don't create a thread if the thread + id pointer location (first arg) is inaccessible. A memory + protection fault will result if the thread id arg isn't an accessible + location. This is consistent with GNU/Linux but different to + Solaris or MKS (and possibly others), which accept NULL as meaning + 'don't return the created thread's ID'. Applications that run + using pthreads-win32 will run on all other POSIX threads + implementations, at least w.r.t. this feature. + + It was decided not to copy the Solaris et al behaviour because, + although it would have simplified some application porting (but only + from Solaris to Windows), the feature is not technically necessary, + and the alternative segfault behaviour helps avoid buggy application + code. + +2004-07-01 Anuj Goyal + + * builddmc.bat: New; Windows bat file to build the library. + * config.h (__DMC__): Support for Digital Mars compiler. + * create.c (__DMC__): Likewise. + * pthread_exit.c (__DMC__): Likewise. + * pthread_join.c (__DMC__): Likewise. + * ptw32_threadDestroy.c (__DMC__): Likewise. + * ptw32_threadStart.c (__DMC__): Likewise. + * ptw32_throw.c (__DMC__): Likewise. + +2004-06-29 Anuj Goyal + + * pthread.h (__DMC__): Initial support for Digital Mars compiler. + +2004-06-29 Will Bryant + + * README.Borland: New; description of Borland changes. + * Bmakefile: New makefile for the Borland make utility. + * ptw32_InterlockedCompareExchange.c: + Add Borland compatible asm code. + +2004-06-26 Jason Bard + + * pthread.h (HAVE_STRUCT_TIMESPEC): If undefined, define it + to avoid timespec struct redefined errors elsewhere in an + application. + +2004-06-21 Ross Johnson + + * pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Mutex + initialiser added for compatibility with Linux threads and + others; currently not included in SUSV3. + * pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER): Likewise. + * pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Likewise. + * pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise. + + * ptw32_mutex_check_need_init.c (ptw32_mutex_check_need_init): + Add new initialisers. + + * pthread_mutex_lock.c (pthread_mutex_lock): Check for new + initialisers. + * pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise. + * pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise. + * pthread_mutex_destroy.c (pthread_mutex_destroy): Likewise. + +2004-05-20 Ross Johnson + + * README.NONPORTABLE: Document pthread_win32_test_features_np(). + * FAQ: Update various answers. + +2004-05-19 Ross Johnson + + * Makefile: Don't define _WIN32_WINNT on compiler command line. + * GNUmakefile: Likewise. + +2004-05-16 Ross Johnson + + * pthread_cancel.c (pthread_cancel): Adapted to use auto-detected + QueueUserAPCEx features at run-time. + (ptw32_RegisterCancelation): Drop in replacement for QueueUserAPCEx() + if it can't be used. Provides older style non-preemptive async + cancelation. + * pthread_win32_attach_detach_np.c (pthread_win32_attach_np): + Auto-detect quserex.dll and the availability of alertdrv.sys; + initialise and close on process attach/detach. + * global.c (ptw32_register_cancelation): Pointer to either + QueueUserAPCEx() or ptw32_RegisterCancelation() depending on + availability. QueueUserAPCEx makes pre-emptive async cancelation + possible. + * implement.h: Add definitions and prototypes related to QueueUserAPC. + +2004-05-16 Panagiotis E. Hadjidoukas + + * QueueUserAPCEx (separate contributed package): Provides preemptive + APC feature. + * pthread_cancel.c (pthread_cancel): Initial integration of + QueueUserAPCEx into pthreads-win32 to provide true pre-emptive + async cancelation of threads, including blocked threads. + +2004-05-06 Makoto Kato + + * pthread.h (DWORD_PTR): Define typedef for older MSVC. + * pthread_cancel.c (AMD64): Add architecture specific Context register. + * ptw32_getprocessors.c: Use correct types (DWORD_PTR) for mask + variables. + +2004-04-06 P. van Bruggen + + * ptw32_threadDestroy.c: Destroy threadLock mutex to + close a memory leak. + +2004-02-13 Gustav Hallberg + + * pthread_equal.c: Remove redundant equality logic. + +2003-12-10 Philippe Di Cristo + + * sem_timedwait.c (sem_timedwait): Fix timeout calculations. + +2003-10-20 Alexander Terekhov + + * pthread_mutex_timedlock.c (ptw32_semwait): Move to individual module. + * ptw32_semwait.c: New module. + * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Replace cancelable + sem_wait() call with non-cancelable ptw32_semwait() call. + * pthread.c (private.c): Re-order for inlining. GNU C warned that + function ptw32_semwait() was defined 'inline' after it was called. + * pthread_cond_signal.c (ptw32_cond_unblock): Likewise. + * pthread_delay_np.c: Disable Watcom warning with comment. + * *.c (process.h): Remove include from .c files. This is conditionally + included by the common project include files. + +2003-10-20 James Ewing + + * ptw32_getprocessors.c: Some Win32 environments don't have + GetProcessAffinityMask(), so always return CPU count = 1 for them. + * config.h (NEED_PROCESSOR_AFFINITY_MASK): Define for WinCE. + +2003-10-15 Ross Johnson + + * Re-indented all .c files using default GNU style to remove assorted + editor ugliness (used GNU indent utility in default style). + +2003-10-15 Alex Blanco + + * sem_init.c (sem_init): Would call CreateSemaphore even if the sema + struct calloc failed; was not freeing calloced memory if either + CreateSemaphore or CreateEvent failed. + +2003-10-14 Ross Johnson + + * pthread.h: Add Watcom compiler compatibility. Esssentially just add + the cdecl attribute to all exposed function prototypes so that Watcom + generates function call code compatible with non-Watcom built libraries. + By default, Watcom uses registers to pass function args if possible rather + than pushing to stack. + * semaphore.h: Likewise. + * sched.h: Likewise. + * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Define with cdecl attribute + for Watcom compatibility. This routine is called via pthread_cleanup_push so + it had to match function arg definition. + * Wmakefile: New makefile for Watcom builds. + +2003-09-14 Ross Johnson + + * pthread_setschedparam.c (pthread_setschedparam): Attempt to map + all priority levels between max and min (as returned by + sched_get_priority_min/max) to reasonable Win32 priority levels - i.e. + levels between THREAD_PRIORITY_LOWEST/IDLE to THREAD_PRIORITY_LOWEST and + between THREAD_PRIORITY_HIGHEST/TIME_CRITICAL to THREAD_PRIORITY_HIGHEST + while others remain unchanged; record specified thread priority level + for return by pthread_getschedparam. + + Note that, previously, specified levels not matching Win32 priority levels + would silently leave the current thread priority unaltered. + + * pthread_getschedparam.c (pthread_getschedparam): Return the priority + level specified by the latest pthread_setschedparam or pthread_create rather + than the actual running thread priority as returned by GetThreadPriority - as + required by POSIX. I.e. temporary or adjusted actual priority levels are not + returned by this routine. + + * pthread_create.c (pthread_create): For priority levels specified via + pthread attributes, attempt to map all priority levels between max and + min (as returned by sched_get_priority_min/max) to reasonable Win32 + priority levels; record priority level given via attributes, or + inherited from parent thread, for later return by pthread_getschedparam. + + * ptw32_new.c (ptw32_new): Initialise pthread_t_ sched_priority element. + + * pthread_self.c (pthread_self): Set newly created implicit POSIX thread + sched_priority to Win32 thread's current actual priority. Temporarily + altered priorities can't be avoided in this case. + + * implement.h (struct pthread_t_): Add new sched_priority element. + +2003-09-12 Ross Johnson + + * sched_get_priority_min.c (sched_get_priority_min): On error should return -1 + with errno set. + * sched_get_priority_max.c (sched_get_priority_max): Likewise. + +2003-09-03 Ross Johnson + + * w32_cancelableWait.c (ptw32_cancelable_wait): Allow cancelation + of implicit POSIX threads as well. + +2003-09-02 Ross Johnson + + * pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np): + Add comment. + + * pthread_exit.c (pthread_exit): Fix to recycle the POSIX thread handle in + addition to calling user TSD destructors. Move the implicit POSIX thread exit + handling to ptw32_throw to centralise the logic. + + * ptw32_throw.c (ptw32_throw): Implicit POSIX threads have no point + to jump or throw to, so cleanup and exit the thread here in this case. For + processes using the C runtime, the exit code will be set to the POSIX + reason for the throw (i.e. PTHREAD_CANCEL or the value given to pthread_exit). + Note that pthread_exit() already had similar logic, which has been moved to + here. + + * ptw32_threadDestroy.c (ptw32_threadDestroy): Don't close the Win32 handle + of implicit POSIX threads - expect this to be done by Win32? + +2003-09-01 Ross Johnson + + * pthread_self.c (pthread_self): The newly aquired pthread_t must be + assigned to the reuse stack, not freed, if the routine fails somehow. + +2003-08-13 Ross Johnson + + * pthread_getschedparam.c (pthread_getschedparam): An invalid thread ID + parameter was returning an incorrect error value; now uses a more exhaustive + check for validity. + + * pthread_setschedparam.c (pthread_setschedparam): Likewise. + + * pthread_join.c (pthread_join): Now uses a more exhaustive + check for validity. + + * pthread_detach.c (pthread_detach): Likewise. + + * pthread_cancel.c (pthread_cancel): Likewise. + + * ptw32_threadDestroy.c (ptw32_threadDestroy): pthread_t structs are + never freed - push them onto a stack for reuse. + + * ptw32_new.c (ptw32_new): Check for reusable pthread_t before dynamically + allocating new memory for the struct. + + * pthread_kill.c (pthread_kill): New file; new routine; takes only a zero + signal arg so that applications can check the thread arg for validity; checks + that the underlying Win32 thread HANDLE is valid. + + * pthread.h (pthread_kill): Add prototype. + + * ptw32_reuse.c (ptw32_threadReusePop): New file; new routine; pop a + pthread_t off the reuse stack. pthread_t_ structs that have been destroyed, i.e. + have exited detached or have been joined, are cleaned up and put onto a reuse + stack. Consequently, thread IDs are no longer freed once calloced. The library + will attempt to get a struct off this stack before asking the system to alloc + new memory when creating threads. The stack is guarded by a global mutex. + (ptw32_threadReusePush): New routine; push a pthread_t onto the reuse stack. + + * implement.h (ptw32_threadReusePush): Add new prototype. + (ptw32_threadReusePop): Likewise. + (pthread_t): Add new element. + + * ptw32_processTerminate.c (ptw32_processTerminate): Delete the thread + reuse lock; free all thread ID structs on the thread reuse stack. + + * ptw32_processInitialize.c (ptw32_processInitialize): Initialise the + thread reuse lock. + +2003-07-19 Ross Johnson + + * GNUmakefile: modified to work under MsysDTK environment. + * pthread_spin_lock.c (pthread_spin_lock): Check for NULL arg. + * pthread_spin_unlock.c (pthread_spin_unlock): Likewise. + * pthread_spin_trylock.c (pthread_spin_trylock): Likewise; + fix incorrect pointer value if lock is dynamically initialised by + this function. + * sem_init.c (sem_init): Initialise sem_t value to quell compiler warning. + * sem_destroy.c (sem_destroy): Likewise. + * ptw32_threadStart.c (non-MSVC code sections): Include rather + than old-style ; fix all std:: namespace entities such as + std::terminate_handler instances and associated methods. + * ptw32_callUserDestroyRoutines.c (non-MSVC code sections): Likewise. + +2003-06-24 Piet van Bruggen + + * pthread_spin_destroy.c (pthread_spin_destroy): Was not freeing the + spinlock struct. + +2003-06-22 Nicolas Barry + + * pthread_mutex_destroy.c (pthread_mutex_destroy): When called + with a recursive mutex that was locked by the current thread, the + function was failing with a success return code. + +2003-05-15 Steven Reddie + + * pthread_win32_attach_detach_np.c (pthread_win32_process_detach_np): + NULLify ptw32_selfThreadKey after the thread is destroyed, otherwise + destructors calling pthreads routines might resurrect it again, creating + memory leaks. Call the underlying Win32 Tls routine directly rather than + pthread_setspecific(). + (pthread_win32_thread_detach_np): Likewise. + +2003-05-14 Viv + + * pthread.dsp: Change /MT compile flag to /MD. + +2003-03-04 Alexander Terekhov + + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Fix failure to + set ownership of mutex on second grab after abstime timeout. + - bug reported by Robert Strycek + +2002-12-17 Thomas Pfaff + + * pthread_mutex_lock.c (ptw32_semwait): New static routine to provide + a non-cancelable sem_wait() function. This is consistent with the + way that pthread_mutex_timedlock.c does it. + (pthread_mutex_lock): Use ptw32_semwait() instead of sem_wait(). + +2002-12-11 Thomas Pfaff + + * pthread_mutex_trylock.c: Should return EBUSY rather than EDEADLK. + * pthread_mutex_destroy.c: Remove redundant ownership test (the + trylock call does this for us); do not destroy a recursively locked + mutex. + +2002-09-20 Michael Johnson + + * pthread_cond_destroy.c (pthread_cond_destroy): + When two different threads exist, and one is attempting to + destroy a condition variable while the other is attempting to + initialize a condition variable that was created with + PTHREAD_COND_INITIALIZER, a deadlock can occur. Shrink + the ptw32_cond_list_lock critical section to fix it. + +2002-07-31 Ross Johnson + + * ptw32_threadStart.c (ptw32_threadStart): Thread cancelLock + destruction moved to ptw32_threadDestroy(). + + * ptw32_threadDestroy.c (ptw32_threadDestroy): Destroy + the thread's cancelLock. Moved here from ptw32_threadStart.c + to cleanup implicit threads as well. + +2002-07-30 Alexander Terekhov + + * pthread_cond_wait.c (ptw32_cond_wait_cleanup): + Remove code designed to avoid/prevent spurious wakeup + problems. It is believed that the sem_timedwait() call + is consuming a CV signal that it shouldn't and this is + breaking the avoidance logic. + +2002-07-30 Ross Johnson + + * sem_timedwait.c (sem_timedwait): Tighten checks for + unreasonable abstime values - that would result in + unexpected timeout values. + + * w32_CancelableWait.c (ptw32_cancelable_wait): + Tighten up return value checking and add comments. + + +2002-06-08 Ross Johnson + + * sem_getvalue.c (sem_getvalue): Now returns a value for the + NEED_SEM version (i.e. earlier versions of WinCE). + + +2002-06-04 Rob Fanner + + * sem_getvalue.c (sem_getvalue): The Johnson M. Hart + approach didn't work - we are forced to take an + intrusive approach. We try to decrement the sema + and then immediately release it again to get the + value. There is a small probability that this may + block other threads, but only momentarily. + +2002-06-03 Ross Johnson + + * sem_init.c (sem_init): Initialise Win32 semaphores + to _POSIX_SEM_VALUE_MAX (which this implementation + defines in pthread.h) so that sem_getvalue() can use + the trick described in the comments in sem_getvalue(). + * pthread.h (_POSIX_SEM_VALUE_MAX): Defined. + (_POSIX_SEM_NSEMS_MAX): Defined - not used but may be + useful for source code portability. + +2002-06-03 Rob Fanner + + * sem_getvalue.c (sem_getvalue): Did not work on NT. + Use approach suggested by Johnson M. Hart in his book + "Win32 System Programming". + +2002-02-28 Ross Johnson + + * errno.c: Compiler directive was incorrectly including code. + * pthread.h: Conditionally added some #defines from config.h + needed when not building the library. e.g. NEED_ERRNO, NEED_SEM. + (PTW32_DLLPORT): Now only defined if _DLL defined. + (_errno): Compiler directive was incorrectly including prototype. + * sched.h: Conditionally added some #defines from config.h + needed when not building the library. + * semaphore.h: Replace an instance of NEED_SEM that should + have been NEED_ERRNO. This change currently has nil effect. + + * GNUmakefile: Correct some recent changes. + + * Makefile: Add rule to generate pre-processor output. + +2002-02-23 Ross Johnson + + * pthread_rwlock_timedrdlock.c: New - untested. + * pthread_rwlock_timedwrlock.c: New - untested. + + * Testsuite passed (except known MSVC++ problems) + + * pthread_cond_destroy.c: Expand the time change + critical section to solve deadlock problem. + + * pthread.c: Add all remaining C modules. + * pthread.h: Use dllexport/dllimport attributes on functions + to avoid using pthread.def. + * sched.h: Likewise. + * semaphore.h: Likewise. + * GNUmakefile: Add new targets for single translation + unit build to maximise inlining potential; generate + pthread.def automatically. + * Makefile: Likewise, but no longer uses pthread.def. + +2002-02-20 Ross Johnson + + * pthread_cond_destroy.c (pthread_cond_destroy): + Enter the time change critical section earlier. + +2002-02-17 Ross Johnson + + * nonportable.c (pthread_delay_np): Make a true + cancelation point. Deferred cancels will interrupt the + wait. + +2002-02-07 Ross Johnson + + Reduced name space pollution. + ----------------------------- + When the appropriate symbols are defined, the headers + will restrict the definitions of new names. In particular, + it must be possible to NOT include the + header and related definitions with some combination + of symbol definitions. Secondly, it should be possible + that additional definitions should be limited to POSIX + compliant symbols by the definition of appropriate symbols. + + * pthread.h: POSIX conditionals. + * sched.h: POSIX conditionals. + * semaphore.h: POSIX conditionals. + + * semaphore.c: Included . + (sem_init): Changed magic 0x7FFFFFFFL to INT_MAX. + (sem_getvalue): Trial version. + + Reduce executable size. + ----------------------- + When linking with the static library, only those + routines actually called, either directly or indirectly + should be included. + + [Gcc has the -ffunction-segments option to do this but MSVC + doesn't have this feature as far as I can determine. Other + compilers are undetermined as well. - rpj] + + * semaphore.c: All routines are now in separate compilation units; + This file is used to congregate the separate modules for + potential inline optimisation and backward build compatibility. + * sem_close.c: Separated routine from semaphore.c. + * ptw32_decrease_semaphore.c: Likewise. + * sem_destroy.c: Likewise. + * sem_getvalue.c: Likewise. + * ptw32_increase_semaphore.c: Likewise. + * sem_init.c: Likewise. + * sem_open.c: Likewise. + * sem_post.c: Likewise. + * sem_post_multiple.c: Likewise. + * sem_timedwait.c: Likewise. + * sem_trywait.c: Likewise. + * sem_unlink.c: Likewise. + * sem_wait.c: Likewise. + +2002-02-04 Ross Johnson + + The following extends the idea above to the rest of pthreads-win32 - rpj + + * attr.c: All routines are now in separate compilation units; + This file is used to congregate the separate modules for + potential inline optimisation and backward build compatibility. + * pthread_attr_destroy.c: Separated routine from attr.c. + * pthread_attr_getdetachstate.c: Likewise. + * pthread_attr_getscope.c: Likewise. + * pthread_attr_getstackaddr.c: Likewise. + * pthread_attr_getstacksize.c: Likewise. + * pthread_attr_init.c: Likewise. + * pthread_attr_is_attr.c: Likewise. + * pthread_attr_setdetachstate.c: Likewise. + * pthread_attr_setscope.c: Likewise. + * pthread_attr_setstackaddr.c: Likewise. + * pthread_attr_setstacksize.c: Likewise. + + * pthread.c: Agregation of agregate modules for super-inlineability. + +2002-02-02 Ross Johnson + + * cancel.c: Rearranged some code and introduced checks + to disable cancelation at the start of a thread's cancelation + run to prevent double cancelation. The main problem + arises if a thread is canceling and then receives a subsequent + async cancel request. + * private.c: Likewise. + * condvar.c: Place pragmas around cleanup_push/pop to turn + off inline optimisation (/Obn where n>0 - MSVC only). Various + optimisation switches in MSVC turn this on, which interferes with + the way that cleanup handlers are run in C++ EH and SEH + code. Application code compiled with inline optimisation must + also wrap cleanup_push/pop blocks with the pragmas, e.g. + #pragma inline_depth(0) + pthread_cleanup_push(...) + ... + pthread_cleanup_pop(...) + #pragma inline_depth(8) + * rwlock.c: Likewise. + * mutex.c: Remove attempts to inline some functions. + * signal.c: Modify misleading comment. + +2002-02-01 Ross Johnson + + * semaphore.c (sem_trywait): Fix missing errno return + for systems that define NEED_SEM (e.g. early WinCE). + * mutex.c (pthread_mutex_timedlock): Return ENOTSUP + for systems that define NEED_SEM since they don't + have sem_trywait(). + +2002-01-27 Ross Johnson + + * mutex.c (pthread_mutex_timedlock): New function suggested by + Alexander Terekhov. The logic required to implement this + properly came from Alexander, with some collaboration + with Thomas Pfaff. + (pthread_mutex_unlock): Wrap the waiters check and sema + post in a critical section to prevent a race with + pthread_mutex_timedlock. + (ptw32_timed_semwait): New function; + returns a special result if the absolute timeout parameter + represents a time already passed when called; used by + pthread_mutex_timedwait(). Have deliberately not reused + the name "ptw32_sem_timedwait" because they are not the same + routine. + * condvar.c (ptw32_cond_timedwait): Use the new sem_timedwait() + instead of ptw32_sem_timedwait(), which now has a different + function. See previous. + * implement.h: Remove prototype for ptw32_sem_timedwait. + See next. + (pthread_mutex_t_): Add critical section element for access + to lock_idx during mutex post-timeout processing. + * semaphore.h (sem_timedwait): See next. + * semaphore.c (sem_timedwait): See next. + * private.c (ptw32_sem_timedwait): Move to semaphore.c + and rename as sem_timedwait(). + +2002-01-18 Ross Johnson + + * sync.c (pthread_join): Was getting the exit code from the + calling thread rather than the joined thread if + defined(__MINGW32__) && !defined(__MSVCRT__). + +2002-01-15 Ross Johnson + + * pthread.h: Unless the build explicitly defines __CLEANUP_SEH, + __CLEANUP_CXX, or __CLEANUP_C, then the build defaults to + __CLEANUP_C style cleanup. This style uses setjmp/longjmp + in the cancelation and thread exit implementations and therefore + won't do stack unwinding if linked to applications that have it + (e.g. C++ apps). This is currently consistent with most/all + commercial Unix POSIX threads implementations. + + * spin.c (pthread_spin_init): Edit renamed function call. + * nonportable.c (pthread_num_processors_np): New. + (pthread_getprocessors_np): Renamed to ptw32_getprocessors + and moved to private.c. + * private.c (pthread_getprocessors): Moved here from + nonportable.c. + * pthread.def (pthread_getprocessors_np): Removed + from export list. + + * rwlock.c (pthread_rwlockattr_init): New. + (pthread_rwlockattr_destroy): New. + (pthread_rwlockattr_getpshared): New. + (pthread_rwlockattr_setpshared): New. + +2002-01-14 Ross Johnson + + * attr.c (pthread_attr_setscope): Fix struct pointer + indirection error introduced 2002-01-04. + (pthread_attr_getscope): Likewise. + +2002-01-12 Ross Johnson + + * pthread.dsp (SOURCE): Add missing source files. + +2002-01-08 Ross Johnson + + * mutex.c (pthread_mutex_trylock): use + ptw32_interlocked_compare_exchange function pointer + rather than ptw32_InterlockedCompareExchange() directly + to retain portability to non-iX86 processors, + e.g. WinCE etc. The pointer will point to the native + OS version of InterlockedCompareExchange() if the + OS supports it (see ChangeLog entry of 2001-10-17). + +2002-01-07 Thomas Pfaff , Alexander Terekhov + + * mutex.c (pthread_mutex_init): Remove critical + section calls. + (pthread_mutex_destroy): Likewise. + (pthread_mutex_unlock): Likewise. + (pthread_mutex_trylock): Likewise; uses + ptw32_InterlockedCompareExchange() to avoid need for + critical section; library is no longer i386 compatible; + recursive mutexes now increment the lock count rather + than return EBUSY; errorcheck mutexes return EDEADLCK + rather than EBUSY. This behaviour is consistent with the + Solaris pthreads implementation. + * implement.h (pthread_mutex_t_): Remove critical + section element - no longer needed. + + +2002-01-04 Ross Johnson + + * attr.c (pthread_attr_setscope): Add more error + checking and actually store the scope value even + though it's not really necessary. + (pthread_attr_getscope): Return stored value. + * implement.h (pthread_attr_t_): Add new scope element. + * ANNOUNCE: Fix out of date comment next to + pthread_attr_setscope in conformance section. + +2001-12-21 Alexander Terekhov + + * mutex.c (pthread_mutex_lock): Decrementing lock_idx was + not thread-safe. + (pthread_mutex_trylock): Likewise. + +2001-10-26 prionx@juno.com + + * semaphore.c (sem_init): Fix typo and missing bracket + in conditionally compiled code. Only older versions of + WinCE require this code, hence it doesn't normally get + tested; somehow when sem_t reverted to an opaque struct + the calloc NULL check was left in the conditionally included + section. + (sem_destroy): Likewise, the calloced sem_t wasn't being freed. + +2001-10-25 Ross Johnson + + * GNUmakefile (libwsock32): Add to linker flags for + WSAGetLastError() and WSASetLastError(). + * Makefile (wsock32.lib): Likewise. + * create.c: Minor mostly inert changes. + * implement.h (PTW32_MAX): Move into here and renamed + from sched.h. + (PTW32_MIN): Likewise. + * GNUmakefile (TEST_ICE): Define if testing internal + implementation of InterlockedCompareExchange. + * Makefile (TEST_ICE): Likewise. + * private.c (TEST_ICE): Likewise. + +2001-10-24 Ross Johnson + + * attr.c (pthread_attr_setstacksize): Quell warning + from LCC by conditionally compiling the stacksize + validity check. LCC correctly warns that the condition + (stacksize < PTHREAD_STACK_MIN) is suspicious + because STACK_MIN is 0 and stacksize is of type + size_t (or unsigned int). + +2001-10-17 Ross Johnson + + * barrier.c: Move _LONG and _LPLONG defines into + implement.h; rename to PTW32_INTERLOCKED_LONG and + PTW32_INTERLOCKED_LPLONG respectively. + * spin.c: Likewise; ptw32_interlocked_compare_exchange used + in place of InterlockedCompareExchange directly. + * global.c (ptw32_interlocked_compare_exchange): Add + prototype for this new routine pointer to be used when + InterlockedCompareExchange isn't supported by Windows. + * nonportable.c (pthread_win32_process_attach_np): Check for + support of InterlockedCompareExchange in kernel32 and assign its + address to ptw32_interlocked_compare_exchange if it exists, or + our own ix86 specific implementation ptw32_InterlockedCompareExchange. + *private.c (ptw32_InterlockedCompareExchange): An + implementation of InterlockedCompareExchange() which is + specific to ix86; written directly in assembler for either + MSVC or GNU C; needed because Windows 95 doesn't support + InterlockedCompareExchange(). + + * sched.c (sched_get_priority_min): Extend to return + THREAD_PRIORITY_IDLE. + (sched_get_priority_max): Extend to return + THREAD_PRIORITY_CRITICAL. + +2001-10-15 Ross Johnson + + * spin.c (pthread_spin_lock): PTHREAD_SPINLOCK_INITIALIZER + was causing a program fault. + (pthread_spin_init): Could have alloced memory + without freeing under some error conditions. + + * mutex.c (pthread_mutex_init): Move memory + allocation of mutex struct after checking for + PROCESS_SHARED. + +2001-10-12 Ross Johnson + + * spin.c (pthread_spin_unlock): Was not returning + EPERM if the spinlock was not locked, for multi CPU + machines. + +2001-10-08 Ross Johnson + + * spin.c (pthread_spin_trylock): Was not returning + EBUSY for multi CPU machines. + +2001-08-24 Ross Johnson + + * condvar.c (pthread_cond_destroy): Remove cv element + that is no longer used. + * implement.h: Likewise. + +2001-08-23 Alexander Terekhov + + * condvar.c (pthread_cond_destroy): fix bug with + respect to deadlock in the case of concurrent + _destroy/_unblock; a condition variable can be destroyed + immediately after all the threads that are blocked on + it are awakened. + +2001-08-23 Phil Frisbie, Jr. + + * tsd.c (pthread_getspecific): Preserve the last + winsock error [from WSAGetLastError()]. + +2001-07-18 Scott McCaskill + + * mutex.c (pthread_mutexattr_init): Return ENOMEM + immediately and don't dereference the NULL pointer + if calloc fails. + (pthread_mutexattr_getpshared): Don't dereference + a pointer that is possibly NULL. + * barrier.c (pthread_barrierattr_init): Likewise + (pthread_barrierattr_getpshared): Don't dereference + a pointer that is possibly NULL. + * condvar.c (pthread_condattr_getpshared): Don't dereference + a pointer that is possibly NULL. + +2001-07-15 Ross Johnson + + * rwlock.c (pthread_rwlock_wrlock): Is allowed to be + a cancelation point; re-enable deferred cancelability + around the CV call. + +2001-07-10 Ross Johnson + + * barrier.c: Still more revamping. The exclusive access + mutex isn't really needed so it has been removed and replaced + by an InterlockedDecrement(). nSerial has been removed. + iStep is now dual-purpose. The process shared attribute + is now stored in the barrier struct. + * implement.h (pthread_barrier_t_): Lost some/gained one + elements. + * private.c (ptw32_threadStart): Removed some comments. + +2001-07-10 Ross Johnson + + * barrier.c: Revamped to fix the race condition. Two alternating + semaphores are used instead of the PulseEvent. Also improved + overall throughput by returning PTHREAD_BARRIER_SERIAL_THREAD + to the first waking thread. + * implement.h (pthread_barrier_t_): Revamped. + +2001-07-09 Ross Johnson + + * barrier.c: Fix several bugs in all routines. Now passes + tests/barrier5.c which is fairly rigorous. There is still + a non-optimal work-around for a race condition between + the barrier breeched event signal and event wait. Basically + the last (signalling) thread to hit the barrier yields + to allow any other threads, which may have lost the race, + to complete. + +2001-07-07 Ross Johnson + + * barrier.c: Changed synchronisation mechanism to a + Win32 manual reset Event and use PulseEvent to signal + waiting threads. If the implementation continued to use + a semaphore it would require a second semaphore and + some management to use them alternately as barriers. A + single semaphore allows threads to cascade from one barrier + through the next, leaving some threads blocked at the first. + * implement.h (pthread_barrier_t_): As per above. + * general: Made a number of other routines inlinable. + +2001-07-07 Ross Johnson + + * spin.c: Revamped and working; included static initialiser. + Now beta level. + * barrier.c: Likewise. + * condvar.c: Macro constant change; inline auto init routine. + * mutex.c: Likewise. + * rwlock.c: Likewise. + * private.c: Add support for spinlock initialiser. + * global.c: Likewise. + * implement.h: Likewise. + * pthread.h (PTHREAD_SPINLOCK_INITIALIZER): Fix typo. + +2001-07-05 Ross Johnson + + * barrier.c: Remove static initialisation - irrelevent + for this object. + * pthread.h (PTHREAD_BARRIER_INITIALIZER): Removed. + * rwlock.c (pthread_rwlock_wrlock): This routine is + not a cancelation point - disable deferred + cancelation around call to pthread_cond_wait(). + +2001-07-05 Ross Johnson + + * spin.c: New module implementing spin locks. + * barrier.c: New module implementing barriers. + * pthread.h (_POSIX_SPIN_LOCKS): defined. + (_POSIX_BARRIERS): Defined. + (pthread_spin_*): Defined. + (pthread_barrier*): Defined. + (PTHREAD_BARRIER_SERIAL_THREAD): Defined. + * implement.h (pthread_spinlock_t_): Defined. + (pthread_barrier_t_): Defined. + (pthread_barrierattr_t_): Defined. + + * mutex.c (pthread_mutex_lock): Return with the error + if an auto-initialiser initialisation fails. + + * nonportable.c (pthread_getprocessors_np): New; gets the + number of available processors for the current process. + +2001-07-03 Ross Johnson + + * pthread.h (_POSIX_READER_WRITER_LOCKS): Define it + if not already defined. + +2001-07-01 Alexander Terekhov + + * condvar.c: Fixed lost signal bug reported by Timur Aydin + (taydin@snet.net). + [RPJ (me) didn't translate the original algorithm + correctly.] + * semaphore.c: Added sem_post_multiple; this is a useful + routine, but it doesn't appear to be standard. For now it's + not an exported function. + +2001-06-25 Ross Johnson + + * create.c (pthread_create): Add priority inheritance + attributes. + * mutex.c (pthread_mutex_lock): Remove some overhead for + PTHREAD_MUTEX_NORMAL mutex types. Specifically, avoid + calling pthread_self() and pthread_equal() to check/set + the mutex owner. Introduce a new pseudo owner for this + type. Test results suggest increases in speed of up to + 90% for non-blocking locks. + This is the default type of mutex used internally by other + synchronising objects, ie. condition variables and + read-write locks. The test rwlock7.c shows about a + 30-35% speed increase over snapshot 2001-06-06. The + price of this is that the application developer + must ensure correct behaviour, or explicitly set the + mutex to a safer type such as PTHREAD_MUTEX_ERRORCHECK. + For example, PTHREAD_MUTEX_NORMAL (or PTHREAD_MUTEX_DEFAULT) + type mutexes will not return an error if a thread which is not + the owner calls pthread_mutex_unlock. The call will succeed + in unlocking the mutex if it is currently locked, but a + subsequent unlock by the true owner will then fail with EPERM. + This is however consistent with some other implementations. + (pthread_mutex_unlock): Likewise. + (pthread_mutex_trylock): Likewise. + (pthread_mutex_destroy): Likewise. + * attr.c (pthread_attr_init): PTHREAD_EXPLICIT_SCHED is the + default inheritance attribute; THREAD_PRIORITY_NORMAL is + the default priority for new threads. + * sched.c (pthread_attr_setschedpolicy): Added routine. + (pthread_attr_getschedpolicy): Added routine. + (pthread_attr_setinheritsched): Added routine. + (pthread_attr_getinheritsched): Added routine. + * pthread.h (sched_rr_set_interval): Added as a macro; + returns -1 with errno set to ENOSYS. + +2001-06-23 Ross Johnson + + *sched.c (pthread_attr_setschedparam): Add priority range + check. + (sched_setscheduler): New function; checks for a valid + pid and policy; checks for permission to set information + in the target process; expects pid to be a Win32 process ID, + not a process handle; the only scheduler policy allowed is + SCHED_OTHER. + (sched_getscheduler): Likewise, but checks for permission + to query. + * pthread.h (SCHED_*): Moved to sched.h as defined in the + POSIX standard. + * sched.h (SCHED_*): Moved from pthread.h. + (pid_t): Defined if necessary. + (sched_setscheduler): Defined. + (sched_getscheduler): Defined. + * pthread.def (sched_setscheduler): Exported. + (sched_getscheduler): Likewise. + +2001-06-23 Ralf Brese + + * create.c (pthread_create): Set thread priority from + thread attributes. + +2001-06-18 Ross Johnson + + * Made organisational-only changes to UWIN additions. + * dll.c (dllMain): Moved UWIN process attach code + to pthread_win32_process_attach_np(); moved + instance of pthread_count to global.c. + * global.c (pthread_count): Moved from dll.c. + * nonportable.c (pthread_win32_process_attach_np): + Moved _UWIN code to here from dll.c. + * implement.h (pthread_count): Define extern int. + * create.c (pthread_count): Remove extern int. + * private.c (pthread_count): Likewise. + * exit.c (pthread_count): Likewise. + +2001-06-18 David Korn + + * dll.c: Added changes necessary to work with UWIN. + * create.c: Likewise. + * pthread.h: Likewise. + * misc.c: Likewise. + * exit.c: Likewise. + * private.c: Likewise. + * implement.h: Likewise. + There is some room at the start of struct pthread_t_ + to implement the signal semantics in UWIN's posix.dll + although this is not yet complete. + * Nmakefile: Compatible with UWIN's Nmake utility. + * Nmakefile.tests: Likewise - for running the tests. + +2001-06-08 Ross Johnson + + * semaphore.h (sem_t): Fixed for compile and test. + * implement.h (sem_t_): Likewise. + * semaphore.c: Likewise. + * private.c (ptw32_sem_timedwait): Updated to use new + opaque sem_t. + +2001-06-06 Ross Johnson + + * semaphore.h (sem_t): Is now an opaque pointer; + moved actual definition to implement.h. + * implement.h (sem_t_): Move here from semaphore.h; + was the definition of sem_t. + * semaphore.c: Wherever necessary, changed use of sem + from that of a pointer to a pointer-pointer; added + extra checks for a valid sem_t; NULL sem_t when + it is destroyed; added extra checks when creating + and destroying sem_t elements in the NEED_SEM + code branches; changed from using a pthread_mutex_t + ((*sem)->mutex) to CRITICAL_SECTION ((*sem)->sem_lock_cs) + in NEED_SEM branches for access serialisation. + +2001-06-06 Ross Johnson + + * mutex.c (pthread_mutexattr_init): Remove + ptw32_mutex_default_kind. + +2001-06-05 Ross Johnson + + * nonportable.c (pthread_mutex_setdefaultkind_np): + Remove - should not have been included in the first place. + (pthread_mutex_getdefaultkind_np): Likewise. + * global.c (ptw32_mutex_default_kind): Likewise. + * mutex.c (pthread_mutex_init): Remove use of + ptw32_mutex_default_kind. + * pthread.h (pthread_mutex_setdefaultkind_np): Likewise. + (pthread_mutex_getdefaultkind_np): Likewise. + * pthread.def (pthread_mutexattr_setkind_np): Added. + (pthread_mutexattr_getkind_np): Likewise. + + * README: Many changes that should have gone in before + the last snapshot. + * README.NONPORTABLE: New - referred to by ANNOUNCE + but never created; documents the non-portable routines + included in the library - moved from README with new + routines added. + * ANNOUNCE (pthread_mutexattr_setkind_np): Added to + compliance list. + (pthread_mutexattr_getkind_np): Likewise. + +2001-06-04 Ross Johnson + + * condvar.c: Add original description of the algorithm as + developed by Terekhov and Thomas, plus reference to + README.CV. + +2001-06-03 Alexander Terekhov , Louis Thomas + + * condvar.c (pthread_cond_init): Completely revamped. + (pthread_cond_destroy): Likewise. + (ptw32_cond_wait_cleanup): Likewise. + (ptw32_cond_timedwait): Likewise. + (ptw32_cond_unblock): New general signaling routine. + (pthread_cond_signal): Now calls ptw32_cond_unblock. + (pthread_cond_broadcast): Likewise. + * implement.h (pthread_cond_t_): Revamped. + * README.CV: New; explanation of the above changes. + +2001-05-30 Ross Johnson + + * pthread.h (rand_r): Fake using _seed argument to quell + compiler warning (compiler should optimise this away later). + + * GNUmakefile (OPT): Leave symbolic information out of the library + and increase optimisation level - for smaller faster prebuilt + dlls. + +2001-05-29 Milan Gardian + + * Makefile: fix typo. + * pthreads.h: Fix problems with stdcall/cdecl conventions, in particular + remove the need for PT_STDCALL everywhere; remove warning supression. + * (errno): Fix the longstanding "inconsistent dll linkage" problem + with errno; now also works with /MD debugging libs - + warnings emerged when compiling pthreads library with /MD (or /MDd) + compiler switch, instead of /MT (or /MTd) (i.e. when compiling pthreads + using Multithreaded DLL CRT instead of Multithreaded statically linked + CRT). + * create.c (pthread_create): Likewise; fix typo. + * private.c (ptw32_threadStart): Eliminate use of terminate() which doesn't + throw exceptions. + * Remove unnecessary #includes from a number of modules - + [I had to #include malloc.h in implement.h for gcc - rpj]. + +2001-05-29 Thomas Pfaff + + * pthread.h (PTHREAD_MUTEX_DEFAULT): New; equivalent to + PTHREAD_MUTEX_DEFAULT_NP. + * (PTHREAD_MUTEX_NORMAL): Similarly. + * (PTHREAD_MUTEX_ERRORCHECK): Similarly. + * (PTHREAD_MUTEX_RECURSIVE): Similarly. + * (pthread_mutex_setdefaultkind_np): New; Linux compatibility stub + for pthread_mutexattr_settype. + * (pthread_mutexattr_getkind_np): New; Linux compatibility stub + for pthread_mutexattr_gettype. + * mutex.c (pthread_mutexattr_settype): New; allow + the following types of mutex: + PTHREAD_MUTEX_DEFAULT_NP + PTHREAD_MUTEX_NORMAL_NP + PTHREAD_MUTEX_ERRORCHECK_NP + PTHREAD_MUTEX_RECURSIVE_NP + * Note that PTHREAD_MUTEX_DEFAULT is equivalent to + PTHREAD_MUTEX_NORMAL - ie. mutexes should no longer + be recursive by default, and a thread will deadlock if it + tries to relock a mutex it already owns. This is inline with + other pthreads implementations. + * (pthread_mutex_lock): Process the lock request + according to the mutex type. + * (pthread_mutex_init): Eliminate use of Win32 mutexes as the + basis of POSIX mutexes - instead, a combination of one critical section + and one semaphore are used in conjunction with Win32 Interlocked* routines. + * (pthread_mutex_destroy): Likewise. + * (pthread_mutex_lock): Likewise. + * (pthread_mutex_trylock): Likewise. + * (pthread_mutex_unlock): Likewise. + * Use longjmp/setjmp to implement cancelation when building the library + using a C compiler which doesn't support exceptions, e.g. gcc -x c (note + that gcc -x c++ uses exceptions). + * Also fixed some of the same typos and eliminated PT_STDCALL as + Milan Gardian's patches above. + +2001-02-07 Alexander Terekhov + + * rwlock.c: Revamped. + * implement.h (pthread_rwlock_t_): Redefined. + This implementation does not have reader/writer starvation problem. + Rwlock attempts to behave more like a normal mutex with + races and scheduling policy determining who is more important; + It also supports recursive locking, + has less synchronization overhead (no broadcasts at all, + readers are not blocked on any condition variable) and seem to + be faster than the current implementation [W98 appears to be + approximately 15 percent faster at least - on top of speed increase + from Thomas Pfaff's changes to mutex.c - rpj]. + +2000-12-29 Ross Johnson + + * Makefile: Back-out "for" loops which don't work. + + * GNUmakefile: Remove the fake.a target; add the "realclean" + target; don't remove built libs under the "clean" target. + + * config.h: Add a guard against multiple inclusion. + + * semaphore.h: Add some defines from config.h to make + semaphore.h independent of config.h when building apps. + + * pthread.h (_errno): Back-out previous fix until we know how to + fix it properly. + + * implement.h (lockCount): Add missing element to pthread_mutex_t_. + + * sync.c (pthread_join): Spelling fix in comment. + + * private.c (ptw32_threadStart): Reset original termination + function (C++). + (ptw32_threadStart): Cleanup detached threads early in case + the library is statically linked. + (ptw32_callUserDestroyRoutines): Remove [SEH] __try block from + destructor call so that unhandled exceptions will be passed through + to the system; call terminate() from [C++] try block for the same + reason. + + * tsd.c (pthread_getspecific): Add comment. + + * mutex.c (pthread_mutex_init): Initialise new elements in + pthread_mutex_t. + (pthread_mutex_unlock): Invert "pthread_equal()" test. + +2000-12-28 Ross Johnson + + * semaphore.c (mode_t): Use ifndef HAVE_MODE_T to include definition. + + * config.h.in (HAVE_MODE_T): Added. + (_UWIN): Start adding defines for the UWIN package. + + * private.c (ptw32_threadStart): Unhandled exceptions are + now passed through to the system to deal with. This is consistent + with normal Windows behaviour. C++ applications may use + set_terminate() to override the default behaviour which is + to call ptw32_terminate(). Ptw32_terminate() cleans up some + POSIX thread stuff before calling the system default function + which calls abort(). The users termination function should conform + to standard C++ semantics which is to not return. It should + exit the thread (call pthread_exit()) or exit the application. + * private.c (ptw32_terminate): Added as the default set_terminate() + function. It calls the system default function after cleaning up + some POSIX thread stuff. + + * implement.h (ptw32_try_enter_critical_section): Move + declaration. + * global.c (ptw32_try_enter_critical_section): Moved + from dll.c. + * dll.c: Move process and thread attach/detach code into + functions in nonportable.c. + * nonportable.c (pthread_win32_process_attach_np): Process + attach code from dll.c is now available to static linked + applications. + * nonportable.c (pthread_win32_process_detach_np): Likewise. + * nonportable.c (pthread_win32_thread_attach_np): Likewise. + * nonportable.c (pthread_win32_thread_detach_np): Likewise. + + * pthread.h: Add new non-portable prototypes for static + linked applications. + + * GNUmakefile (OPT): Increase optimisation flag and remove + debug info flag. + + * pthread.def: Add new non-portable exports for static + linked applications. + +2000-12-11 Ross Johnson + + * FAQ: Update Answer 6 re getting a fully working + Mingw32 built library. + +2000-10-10 Steven Reddie + + * misc.c (pthread_self): Restore Win32 "last error" + cleared by TlsGetValue() call in + pthread_getspecific() + +2000-09-20 Arthur Kantor + + * mutex.c (pthread_mutex_lock): Record the owner + of the mutex. This requires also keeping count of + recursive locks ourselves rather than leaving it + to Win32 since we need to know when to NULL the + thread owner when the mutex is unlocked. + (pthread_mutex_trylock): Likewise. + (pthread_mutex_unlock): Check that the calling + thread owns the mutex, decrement the recursive + lock count, and NULL the owner if zero. Return + EPERM if the mutex is owned by another thread. + * implement.h (pthread_mutex_t_): Add ownerThread + and lockCount members. + +2000-09-13 Jef Gearhart + + * mutex.c (pthread_mutex_init): Call + TryEnterCriticalSection through the pointer + rather than directly so that the dll can load + on Windows versions that can't resolve the + function, eg. Windows 95 + +2000-09-09 Ross Johnson + + * pthread.h (ctime_r): Fix arg. + +2000-09-08 Ross Johnson + + * GNUmakefile(_WIN32_WINNT=0x400): Define in CFLAGS; + doesn't seem to be needed though. + + * cancel.c (pthread_cancel): Must get "self" through + calling pthread_self() which will ensure a POSIX thread + struct is built for non-POSIX threads; return an error + if this fails + - Ollie Leahy + (pthread_setcancelstate): Likewise. + (pthread_setcanceltype): Likewise. + * misc.c (ptw32_cancelable_wait): Likewise. + + * private.c (ptw32_tkAssocCreate): Remove unused #if 0 + wrapped code. + + * pthread.h (ptw32_get_exception_services_code): + Needed to be forward declared unconditionally. + +2000-09-06 Ross Johnson + + * cancel.c (pthread_cancel): If called from the main + thread "self" would be NULL; get "self" via pthread_self() + instead of directly from TLS so that an implicit + pthread object is created. + + * misc.c (pthread_equal): Strengthen test for NULLs. + +2000-09-02 Ross Johnson + + * condvar.c (ptw32_cond_wait_cleanup): Ensure that all + waking threads check if they are the last, and notify + the broadcaster if so - even if an error occurs in the + waiter. + + * semaphore.c (_decrease_semaphore): Should be + a call to ptw32_decrease_semaphore. + (_increase_semaphore): Should be a call to + ptw32_increase_semaphore. + + * misc.c (ptw32_cancelable_wait): Renamed from + CancelableWait. + * rwlock.c (_rwlock_check*): Renamed to + ptw32_rwlock_check*. + * mutex.c (_mutex_check*): Renamed to ptw32_mutex_check*. + * condvar.c (cond_timed*): Renamed to ptw32_cond_timed*. + (_cond_check*): Renamed to ptw32_cond_check*. + (cond_wait_cleanup*): Rename to ptw32_cond_wait_cleanup*. + (ptw32_cond_timedwait): Add comments. + +2000-08-22 Ross Johnson + + * private.c (ptw32_throw): Fix exception test; + move exceptionInformation declaration. + + * tsd.c (pthread_key_create): newkey wrongly declared. + + * pthread.h: Fix comment block. + +2000-08-18 Ross Johnson + + * mutex.c (pthread_mutex_destroy): Check that the mutex isn't + held; invalidate the mutex as early as possible to avoid + contention; not perfect - FIXME! + + * rwlock.c (pthread_rwlock_init): Remove redundant assignment + to "rw". + (pthread_rwlock_destroy): Invalidate the rwlock before + freeing up any of it's resources - to avoid contention. + + * private.c (ptw32_tkAssocCreate): Change assoc->lock + to use a dynamically initialised mutex - only consumes + a W32 mutex or critical section when first used, + not before. + + * mutex.c (pthread_mutex_init): Remove redundant assignment + to "mx". + (pthread_mutexattr_destroy): Set attribute to NULL + before freeing it's memory - to avoid contention. + + * implement.h (PTW32_EPS_CANCEL/PTW32_EPS_EXIT): + Must be defined for all compilers - used as generic + exception selectors by ptw32_throw(). + + * Several: Fix typos from scripted edit session + yesterday. + + * nonportable.c (pthread_mutexattr_setforcecs_np): + Moved this function from mutex.c. + (pthread_getw32threadhandle_np): New function to + return the win32 thread handle that the POSIX + thread is using. + * mutex.c (pthread_mutexattr_setforcecs_np): + Moved to new file "nonportable.c". + + * pthread.h (PTW32_BUILD): Only redefine __except + and catch compiler keywords if we aren't building + the library (ie. PTW32_BUILD is not defined) - + this is safer than defining and then undefining + if not building the library. + * implement.h: Remove __except and catch undefines. + * Makefile (CFLAGS): Define PTW32_BUILD. + * GNUmakefile (CFLAGS): Define PTW32_BUILD. + + * All appropriate: Change Pthread_exception* to + ptw32_exception* to be consistent with internal + identifier naming. + + * private.c (ptw32_throw): New function to provide + a generic exception throw for all internal + exceptions and EH schemes. + (ptw32_threadStart): pthread_exit() value is now + returned via the thread structure exitStatus + element. + * exit.c (pthread_exit): pthread_exit() value is now + returned via the thread structure exitStatus + element. + * cancel.c (ptw32_cancel_self): Now uses ptw32_throw. + (pthread_setcancelstate): Ditto. + (pthread_setcanceltype): Ditto. + (pthread_testcancel): Ditto. + (pthread_cancel): Ditto. + * misc.c (CancelableWait): Ditto. + * exit.c (pthread_exit): Ditto. + * All applicable: Change PTW32_ prefix to + PTW32_ prefix to remove leading underscores + from private library identifiers. + +2000-08-17 Ross Johnson + + * All applicable: Change _pthread_ prefix to + ptw32_ prefix to remove leading underscores + from private library identifiers (single + and double leading underscores are reserved in the + ANSI C standard for compiler implementations). + + * tsd.c (pthread_create_key): Initialise temporary + key before returning it's address to avoid race + conditions. + +2000-08-13 Ross Johnson + + * errno.c: Add _MD precompile condition; thus far + had no effect when using /MD compile option but I + thnk it should be there. + + * exit.c: Add __cplusplus to various #if lines; + was compiling SEH code even when VC++ had + C++ compile options. + + * private.c: ditto. + + * create.c (pthread_create): Add PT_STDCALL macro to + function pointer arg in _beginthread(). + + * pthread.h: PT_STDCALL really does need to be defined + in both this and impliment.h; don't set it to __cdecl + - this macro is only used to extend function pointer + casting for functions that will be passed as parameters. + (~PThreadCleanup): add cast and group expression. + (_errno): Add _MD compile conditional. + (PtW32NoCatchWarn): Change pragma message. + + * implement.h: Move and change PT_STDCALL define. + + * need_errno.h: Add _MD to compilation conditional. + + * GNUmakefile: Substantial rewrite for new naming + convention; set for nil optimisation (turn it up + when we have a working library build; add target + "fake.a" to build a libpthreadw32.a from the VC++ + built DLL pthreadVCE.dll. + + * pthread.def (LIBRARY): Don't specify in the .def + file - it is specified on the linker command line + since we now use the same .def file for variously + named .dlls. + + * Makefile: Substantial rewrite for new naming + convention; default nmake target only issues a + help message; run nmake with specific target + corresponding to the EH scheme being used. + + * README: Update information; add naming convention + explanation. + + * ANNOUNCE: Update information. + +2000-08-12 Ross Johnson + + * pthread.h: Add compile-time message when using + MSC_VER compiler and C++ EH to warn application + programmers to use PtW32Catch instead of catch(...) + if they want cancelation and pthread_exit to work. + + * implement.h: Remove #include ; we + use our own local semaphore.h. + +2000-08-10 Ross Johnson + + * cleanup.c (pthread_pop_cleanup): Remove _pthread + prefix from __except and catch keywords; implement.h + now simply undefines ptw32__except and + ptw32_catch if defined; VC++ was not textually + substituting ptw32_catch etc back to catch as + it was redefined; the reason for using the prefixed + version was to make it clear that it was not using + the pthread.h redefined catch keyword. + + * private.c (ptw32_threadStart): Ditto. + (ptw32_callUserDestroyRoutines): Ditto. + + * implement.h (ptw32__except): Remove #define. + (ptw32_catch): Remove #define. + + * GNUmakefile (pthread.a): New target to build + libpthread32.a from pthread.dll using dlltool. + + * buildlib.bat: Duplicate cl commands with args to + build C++ EH version of pthread.dll; use of .bat + files is redundant now that nmake compatible + Makefile is included; used as a kludge only now. + + * Makefile: Localise some macros and fix up the clean: + target to extend it and work properly. + + * CONTRIBUTORS: Add contributors. + + * ANNOUNCE: Updated. + + * README: Updated. + +2000-08-06 Ross Johnson + + * pthread.h: Remove #warning - VC++ doesn't accept it. + +2000-08-05 Ross Johnson + + * pthread.h (PtW32CatchAll): Add macro. When compiling + applications using VC++ with C++ EH rather than SEH + 'PtW32CatchAll' must be used in place of any 'catch( ... )' + if the application wants pthread cancelation or + pthread_exit() to work. + +2000-08-03 Ross Johnson + + * pthread.h: Add a base class ptw32_exception for + library internal exceptions and change the "catch" + re-define macro to use it. + +2000-08-02 Ross Johnson + + * GNUmakefile (CFLAGS): Add -mthreads. + Add new targets to generate cpp and asm output. + + * sync.c (pthread_join): Remove dead code. + +2000-07-25 Tristan Savatier + + * sched.c (sched_get_priority_max): Handle different WinCE and + Win32 priority values together. + (sched_get_priority_min): Ditto. + +2000-07-25 Ross Johnson + + * create.c (pthread_create): Force new threads to wait until + pthread_create has the new thread's handle; we also retain + a local copy of the handle for internal use until + pthread_create returns. + + * private.c (ptw32_threadStart): Initialise ei[]. + (ptw32_threadStart): When beginthread is used to start the + thread, force waiting until the creator thread had the + thread handle. + + * cancel.c (ptw32_cancel_thread): Include context switch + code for defined(_X86_) environments in addition to _M_IX86. + + * rwlock.c (pthread_rwlock_destroy): Assignment changed + to avoid compiler warning. + + * private.c (ptw32_get_exception_services_code): Cast + NULL return value to avoid compiler warning. + + * cleanup.c (pthread_pop_cleanup): Initialise "cleanup" variable + to avoid compiler warnings. + + * misc.c (ptw32_new): Change "new" variable to "t" to avoid + confusion with the C++ keyword of the same name. + + * condvar.c (cond_wait_cleanup): Initialise lastWaiter variable. + (cond_timedwait): Remove unused local variables. to avoid + compiler warnings. + + * dll.c (dllMain): Remove 2000-07-21 change - problem + appears to be in pthread_create(). + +2000-07-22 Ross Johnson + + * tsd.c (pthread_key_create): If a destructor was given + and the pthread_mutex_init failed, then would try to + reference a NULL pointer (*key); eliminate this section of + code by using a dynamically initialised mutex + (PTHREAD_MUTEX_INITIALIZER). + + * tsd.c (pthread_setspecific): Return an error if + unable to set the value; simplify cryptic conditional. + + * tsd.c (pthread_key_delete): Locking threadsLock relied + on mutex_lock returning an error if the key has no destructor. + ThreadsLock is only initialised if the key has a destructor. + Making this mutex a static could reduce the number of mutexes + used by an application since it is actually created only at + first use and it's often destroyed soon after. + +2000-07-22 Ross Johnson + + * FAQ: Added Q5 and Q6. + +2000-07-21 David Baggett + + * dll.c: Include resource leakage work-around. This is a + partial FIXME which doesn't stop all leakage. The real + problem needs to be found and fixed. + +2000-07-21 Ross Johnson + + * create.c (pthread_create): Set threadH to 0 (zero) + everywhere. Some assignments were using NULL. Maybe + it should be NULL everywhere - need to check. (I know + they are nearly always the same thing - but not by + definition.) + + * misc.c (pthread_self): Try to catch NULL thread handles + at the point where they might be generated, even though + they should always be valid at this point. + + * tsd.c (pthread_setspecific): return an error value if + pthread_self() returns NULL. + + * sync.c (pthread_join): return an error value if + pthread_self() returns NULL. + + * signal.c (pthread_sigmask): return an error value if + pthread_self() returns NULL. + +2000-03-02 Ross Johnson + + * attr.c (pthread_attr_init): Set default stacksize to zero (0) + rather than PTHREAD_STACK_MIN even though these are now the same. + + * pthread.h (PTHREAD_STACK_MIN): Lowered to 0. + +2000-01-28 Ross Johnson + + * mutex.c (pthread_mutex_init): Free mutex if it has been alloced; + if critical sections can be used instead of Win32 mutexes, test + that the critical section works and return an error if not. + +2000-01-07 Ross Johnson + + * cleanup.c (pthread_pop_cleanup): Include SEH code only if MSC is not + compiling as C++. + (pthread_push_cleanup): Include SEH code only if MSC is not + compiling as C++. + + * pthread.h: Include SEH code only if MSC is not + compiling as C++. + + * implement.h: Include SEH code only if MSC is not + compiling as C++. + + * cancel.c (ptw32_cancel_thread): Add _M_IX86 check. + (pthread_testcancel): Include SEH code only if MSC is not + compiling as C++. + (ptw32_cancel_self): Include SEH code only if MSC is not + compiling as C++. + +2000-01-06 Erik Hensema + + * Makefile: Remove inconsistencies in 'cl' args + +2000-01-04 Ross Johnson + + * private.c (ptw32_get_exception_services_code): New; returns + value of EXCEPTION_PTW32_SERVICES. + (ptw32_processInitialize): Remove initialisation of + ptw32_exception_services which is no longer needed. + + * pthread.h (ptw32_exception_services): Remove extern. + (ptw32_get_exception_services_code): Add function prototype; + use this to return EXCEPTION_PTW32_SERVICES value instead of + using the ptw32_exception_services variable which I had + trouble exporting through pthread.def. + + * global.c (ptw32_exception_services): Remove declaration. + +1999-11-22 Ross Johnson + + * implement.h: Forward declare ptw32_new(); + + * misc.c (ptw32_new): New; alloc and initialise a new pthread_t. + (pthread_self): New thread struct is generated by new routine + ptw32_new(). + + * create.c (pthread_create): New thread struct is generated + by new routine ptw32_new(). + +1999-11-21 Ross Johnson + + * global.c (ptw32_exception_services): Declare new variable. + + * private.c (ptw32_threadStart): Destroy thread's + cancelLock mutex; make 'catch' and '__except' usageimmune to + redfinitions in pthread.h. + (ptw32_processInitialize): Init new constant ptw32_exception_services. + + * create.c (pthread_create): Initialise thread's cancelLock + mutex. + + * cleanup.c (pthread_pop_cleanup): Make 'catch' and '__except' + usage immune to redfinition s in pthread.h. + + * private.c: Ditto. + + * pthread.h (catch): Redefine 'catch' so that C++ applications + won't catch our internal exceptions. + (__except): ditto for __except. + + * implement.h (ptw32_catch): Define internal version + of 'catch' because 'catch' is redefined by pthread.h. + (__except): ditto for __except. + (struct pthread_t_): Add cancelLock mutex for async cancel + safety. + +1999-11-21 Jason Nye , Erik Hensema + + * cancel.c (ptw32_cancel_self): New; part of the async + cancellation implementation. + (ptw32_cancel_thread): Ditto; this function is X86 + processor specific. + (pthread_setcancelstate): Add check for pending async + cancel request and cancel the calling thread if + required; add async-cancel safety lock. + (pthread_setcanceltype): Ditto. + +1999-11-13 Erik Hensema + + * configure.in (AC_OUTPUT): Put generated output into GNUmakefile + rather than Makefile. Makefile will become the MSC nmake compatible + version + +1999-11-13 John Bossom (John.Bossom@cognos.com> + + * misc.c (pthread_self): Add a note about GetCurrentThread + returning a pseudo-handle + +1999-11-10 Todd Owen + + * dll.c (dllMain): Free kernel32 ASAP. + If TryEnterCriticalSection is not being used, then free + the kernel32.dll handle now, rather than leaving it until + DLL_PROCESS_DETACH. + + Note: this is not a pedantic exercise in freeing unused + resources! It is a work-around for a bug in Windows 95 + (see microsoft knowledge base article, Q187684) which + does Bad Things when FreeLibrary is called within + the DLL_PROCESS_DETACH code, in certain situations. + Since w95 just happens to be a platform which does not + provide TryEnterCriticalSection, the bug will be + effortlessly avoided. + +1999-11-10 Ross Johnson + + * sync.c (pthread_join): Make it a deferred cancelation point. + + * misc.c (pthread_self): Explicitly initialise implicitly + created thread state to default values. + +1999-11-05 Tristan Savatier + + * pthread.h (winsock.h): Include unconditionally. + (ETIMEDOUT): Change fallback value to that defined by winsock.h. + + * general: Patched for portability to WinCE. The details are + described in the file WinCE-PORT. Follow the instructions + in README.WinCE to make the appropriate changes in config.h. + +1999-10-30 Erik Hensema + + * create.c (pthread_create): Explicitly initialise thread state to + default values. + + * cancel.c (pthread_setcancelstate): Check for NULL 'oldstate' + for compatibility with Solaris pthreads; + (pthread_setcanceltype): ditto: + +1999-10-23 Erik Hensema + + * pthread.h (ctime_r): Fix incorrect argument "_tm" + +1999-10-21 Aurelio Medina + + * pthread.h (_POSIX_THREADS): Only define it if it isn't + already defined. Projects may need to define this on + the CC command line under Win32 as it doesn't have unistd.h + +1999-10-17 Ross Johnson + + * rwlock.c (pthread_rwlock_destroy): Add cast to remove compile + warning. + + * condvar.c (pthread_cond_broadcast): Only release semaphores + if there are waiting threads. + +1999-10-15 Lorin Hochstein , Peter Slacik + + * condvar.c (cond_wait_cleanup): New static cleanup handler for + cond_timedwait; + (cond_timedwait): pthread_cleanup_push args changed; + canceling a thread while it's in pthread_cond_wait + will now decrement the waiters count and cleanup if it's the + last waiter. + +1999-10-15 Graham Dumpleton + + * condvar.c (cond_wait_cleanup): the last waiter will now reset the CV's + wasBroadcast flag + +Thu Sep 16 1999 Ross Johnson + + * rwlock.c (pthread_rwlock_destroy): Add serialisation. + (_rwlock_check_need_init): Check for detroyed rwlock. + * rwlock.c: Check return codes from _rwlock_check_need_init(); + modify comments; serialise access to rwlock objects during + operations; rename rw_mutex to rw_lock. + * implement.h: Rename rw_mutex to rw_lock. + * mutex.c (pthread_mutex_destroy): Add serialisation. + (_mutex_check_need_init): Check for detroyed mutex. + * condvar.c (pthread_cond_destroy): Add serialisation. + (_cond_check_need_init): Check for detroyed condvar. + * mutex.c: Modify comments. + * condvar.c: Modify comments. + +1999-08-10 Aurelio Medina + + * implement.h (pthread_rwlock_t_): Add. + * pthread.h (pthread_rwlock_t): Add. + (PTHREAD_RWLOCK_INITIALIZER): Add. + Add rwlock function prototypes. + * rwlock.c: New module. + * pthread.def: Add new rwlock functions. + * private.c (ptw32_processInitialize): initialise + ptw32_rwlock_test_init_lock critical section. + * global.c (ptw32_rwlock_test_init_lock): Add. + + * mutex.c (pthread_mutex_destroy): Don't free mutex memory + if mutex is PTHREAD_MUTEX_INITIALIZER and has not been + initialised yet. + +1999-08-08 Milan Gardian + + * mutex.c (pthread_mutex_destroy): Free mutex memory. + +1999-08-22 Ross Johnson + + * exit.c (pthread_exit): Fix reference to potentially + uninitialised pointer. + +1999-08-21 Ross Johnson + + * private.c (ptw32_threadStart): Apply fix of 1999-08-19 + this time to C++ and non-trapped C versions. Ommitted to + do this the first time through. + +1999-08-19 Ross Johnson + + * private.c (ptw32_threadStart): Return exit status from + the application thread startup routine. + - Milan Gardian + +1999-08-18 John Bossom + + * exit.c (pthread_exit): Put status into pthread_t->exitStatus + * private.c (ptw32_threadStart): Set pthread->exitStatus + on exit of try{} block. + * sync.c (pthread_join): use pthread_exitStatus value if the + thread exit doesn't return a value (for Mingw32 CRTDLL + which uses endthread instead of _endthreadex). + +Tue Aug 17 20:17:58 CDT 1999 Mumit Khan + + * create.c (pthread_create): Add CRTDLL suppport. + * exit.c (pthread_exit): Likewise. + * private.c (ptw32_threadStart): Likewise. + (ptw32_threadDestroy): Likewise. + * sync.c (pthread_join): Likewise. + * tests/join1.c (main): Warn about partial support for CRTDLL. + +Tue Aug 17 20:00:08 1999 Mumit Khan + + * Makefile.in (LD): Delete entry point. + * acconfig.h (STDCALL): Delete unused macro. + * configure.in: Remove test for STDCALL. + * config.h.in: Regenerate. + * errno.c (_errno): Fix self type. + * pthread.h (PT_STDCALL): Move from here to + * implement.h (PT_STDCALL): here. + (ptw32_threadStart): Fix prototype. + * private.c (ptw32_threadStart): Likewise. + +1999-08-14 Ross Johnson + + * exit.c (pthread_exit): Don't call pthread_self() but + get thread handle directly from TSD for efficiency. + +1999-08-12 Ross Johnson + + * private.c (ptw32_threadStart): ei[] only declared if _MSC_VER. + + * exit.c (pthread_exit): Check for implicitly created threads + to avoid raising an unhandled exception. + +1999-07-12 Peter Slacik + + * condvar.c (pthread_cond_destroy): Add critical section. + (cond_timedwait): Add critical section; check for timeout + waiting on semaphore. + (pthread_cond_broadcast): Add critical section. + +1999-07-09 Lorin Hochstein , John Bossom + + The problem was that cleanup handlers were not executed when + pthread_exit() was called. + + * implement.h (pthread_t_): Add exceptionInformation element for + C++ per-thread exception information. + (general): Define and rename exceptions. + +1999-07-09 Ross Johnson + + * misc.c (CancelableWait): PTW32_EPS_CANCEL (SEH) and + ptw32_exception_cancel (C++) used to identify the exception. + + * cancel.c (pthread_testcancel): PTW32_EPS_CANCEL (SEH) and + ptw32_exception_cancel (C++) used to identify the exception. + + * exit.c (pthread_exit): throw/raise an exception to return to + ptw32_threadStart() to exit the thread. PTW32_EPS_EXIT (SEH) + and ptw32_exception_exit (C++) used to identify the exception. + + * private.c (ptw32_threadStart): Add pthread_exit exception trap; + clean up and exit the thread directly rather than via pthread_exit(). + +Sun May 30 00:25:02 1999 Ross Johnson + + * semaphore.h (mode_t): Conditionally typedef it. + +Fri May 28 13:33:05 1999 Mark E. Armstrong + + * condvar.c (pthread_cond_broadcast): Fix possible memory fault + +Thu May 27 13:08:46 1999 Peter Slacik + + * condvar.c (pthread_cond_broadcast): Fix logic bug + +Thu May 27 13:08:46 1999 Bossom, John + + * condvar.c (pthread_cond_broadcast): optimise sem_post loop + +Fri May 14 12:13:18 1999 Mike Russo + + * attr.c (pthread_attr_setdetachstate): Fix logic bug + +Sat May 8 09:42:30 1999 Ross Johnson + + * pthread.def (sem_open): Add. + (sem_close): Add. + (sem_unlink): Add. + (sem_getvalue): Add. + + * FAQ (Question 3): Add. + +Thu Apr 8 01:16:23 1999 Ross Johnson + + * semaphore.c (sem_open): New function; returns an error (ENOSYS). + (sem_close): ditto. + (sem_unlink): ditto. + (sem_getvalue): ditto. + + * semaphore.h (_POSIX_SEMAPHORES): define. + +Wed Apr 7 14:09:52 1999 Ross Johnson + + * errno.c (_REENTRANT || _MT): Invert condition. + + * pthread.h (_errno): Conditionally include prototype. + +Wed Apr 7 09:37:00 1999 Ross Johnson + + * *.c (comments): Remove individual attributions - these are + documented sufficiently elsewhere. + + * implement.h (pthread.h): Remove extraneous include. + +Sun Apr 4 11:05:57 1999 Ross Johnson + + * sched.c (sched.h): Include. + + * sched.h: New file for POSIX 1b scheduling. + + * pthread.h: Move opaque structures to implement.h; move sched_* + prototypes out and into sched.h. + + * implement.h: Add opaque structures from pthread.h. + + * sched.c (sched_yield): New function. + + * condvar.c (ptw32_sem_*): Rename to sem_*; except for + ptw32_sem_timedwait which is an private function. + +Sat Apr 3 23:28:00 1999 Ross Johnson + + * Makefile.in (OBJS): Add errno.o. + +Fri Apr 2 11:08:50 1999 Ross Johnson + + * implement.h (ptw32_sem_*): Remove prototypes now defined in + semaphore.h. + + * pthread.h (sempahore.h): Include. + + * semaphore.h: New file for POSIX 1b semaphores. + + * semaphore.c (ptw32_sem_timedwait): Moved to private.c. + + * pthread.h (ptw32_sem_t): Change to sem_t. + + * private.c (ptw32_sem_timedwait): Moved from semaphore.c; + set errno on error. + + * pthread.h (pthread_t_): Add per-thread errno element. + +Fri Apr 2 11:08:50 1999 John Bossom + + * semaphore.c (ptw32_sem_*): Change to sem_*; these functions + will be exported from the library; set errno on error. + + * errno.c (_errno): New file. New function. + +Fri Mar 26 14:11:45 1999 Tor Lillqvist + + * semaphore.c (ptw32_sem_timedwait): Check for negative + milliseconds. + +Wed Mar 24 11:32:07 1999 John Bossom + + * misc.c (CancelableWait): Initialise exceptionInformation[2]. + (pthread_self): Get a real Win32 thread handle for implicit threads. + + * cancel.c (pthread_testcancel): Initialise exceptionInformation[2]. + + * implement.h (SE_INFORMATION): Fix values. + + * private.c (ptw32_threadDestroy): Close the thread handle. + +Fri Mar 19 12:57:27 1999 Ross Johnson + + * cancel.c (comments): Update and cleanup. + +Fri Mar 19 09:12:59 1999 Ross Johnson + + * private.c (ptw32_threadStart): status returns PTHREAD_CANCELED. + + * pthread.h (PTHREAD_CANCELED): defined. + +Tue Mar 16 1999 Ross Johnson + + * all: Add GNU LGPL and Copyright and Warranty. + +Mon Mar 15 00:20:13 1999 Ross Johnson + + * condvar.c (pthread_cond_init): fix possible uninitialised use + of cv. + +Sun Mar 14 21:01:59 1999 Ross Johnson + + * condvar.c (pthread_cond_destroy): don't do full cleanup if + static initialised cv has never been used. + (cond_timedwait): check result of auto-initialisation. + +Thu Mar 11 09:01:48 1999 Ross Johnson + + * pthread.h (pthread_mutex_t): revert to (pthread_mutex_t *); + define a value to serve as PTHREAD_MUTEX_INITIALIZER. + (pthread_mutex_t_): remove staticinit and valid elements. + (pthread_cond_t): revert to (pthread_cond_t_ *); + define a value to serve as PTHREAD_COND_INITIALIZER. + (pthread_cond_t_): remove staticinit and valid elements. + + * mutex.c (pthread_mutex_t args): adjust indirection of references. + (all functions): check for PTHREAD_MUTEX_INITIALIZER value; + check for NULL (invalid). + + * condvar.c (pthread_cond_t args): adjust indirection of references. + (all functions): check for PTHREAD_COND_INITIALIZER value; + check for NULL (invalid). + +Wed Mar 10 17:18:12 1999 Ross Johnson + + * misc.c (CancelableWait): Undo changes from Mar 8 and 7. + +Mon Mar 8 11:18:59 1999 Ross Johnson + + * misc.c (CancelableWait): Ensure cancelEvent handle is the lowest + indexed element in the handles array. Enhance test for abandoned + objects. + + * pthread.h (PTHREAD_MUTEX_INITIALIZER): Trailing elements not + initialised are set to zero by the compiler. This avoids the + problem of initialising the opaque critical section element in it. + (PTHREAD_COND_INITIALIZER): Ditto. + + * semaphore.c (ptw32_sem_timedwait): Check sem == NULL earlier. + +Sun Mar 7 12:31:14 1999 Ross Johnson + + * condvar.c (pthread_cond_init): set semaphore initial value + to 0, not 1. cond_timedwait was returning signaled immediately. + + * misc.c (CancelableWait): Place the cancel event handle first + in the handle table for WaitForMultipleObjects. This ensures that + the cancel event is recognised and acted apon if both objects + happen to be signaled together. + + * private.c (ptw32_cond_test_init_lock): Initialise and destroy. + + * implement.h (ptw32_cond_test_init_lock): Add extern. + + * global.c (ptw32_cond_test_init_lock): Add declaration. + + * condvar.c (pthread_cond_destroy): check for valid initialised CV; + flag destroyed CVs as invalid. + (pthread_cond_init): pthread_cond_t is no longer just a pointer. + This is because PTHREAD_COND_INITIALIZER needs state info to reside + in pthread_cond_t so that it can initialise on first use. Will work on + making pthread_cond_t (and other objects like it) opaque again, if + possible, later. + (cond_timedwait): add check for statically initialisation of + CV; initialise on first use. + (pthread_cond_signal): check for valid CV. + (pthread_cond_broadcast): check for valid CV. + (_cond_check_need_init): Add. + + * pthread.h (PTHREAD_COND_INITIALIZER): Fix. + (pthread_cond_t): no longer a pointer to pthread_cond_t_. + (pthread_cond_t_): add 'staticinit' and 'valid' elements. + +Sat Mar 6 1999 Ross Johnson + + * implement.h: Undate comments. + +Sun Feb 21 1999 Ross Johnson + + * pthread.h (PTHREAD_MUTEX_INITIALIZER): missing braces around + cs element initialiser. + +1999-02-21 Ben Elliston + + * pthread.h (pthread_exit): The return type of this function is + void, not int. + + * exit.c (pthread_exit): Do not return 0. + +Sat Feb 20 16:03:30 1999 Ross Johnson + + * dll.c (DLLMain): Expand TryEnterCriticalSection support test. + + * mutex.c (pthread_mutex_trylock): The check for + ptw32_try_enter_critical_section == NULL should have been + removed long ago. + +Fri Feb 19 16:03:30 1999 Ross Johnson + + * sync.c (pthread_join): Fix pthread_equal() test. + + * mutex.c (pthread_mutex_trylock): Check mutex != NULL before + using it. + +Thu Feb 18 16:17:30 1999 Ross Johnson + + * misc.c (pthread_equal): Fix inverted result. + + * Makefile.in: Use libpthread32.a as the name of the DLL export + library instead of pthread.lib. + + * condvar.c (pthread_cond_init): cv could have been used unitialised; + initialise. + + * create.c (pthread_create): parms could have been used unitialised; + initialise. + + * pthread.h (struct pthread_once_t_): Remove redefinition. + +Sat Feb 13 03:03:30 1999 Ross Johnson + + * pthread.h (struct pthread_once_t_): Replaced. + + * misc.c (pthread_once): Replace with John Bossom's version; + has lighter weight serialisation; fixes problem of not holding + competing threads until after the init_routine completes. + +Thu Feb 11 13:34:14 1999 Ross Johnson + + * misc.c (CancelableWait): Change C++ exception throw. + + * sync.c (pthread_join): Change FIXME comment - issue resolved. + +Wed Feb 10 12:49:11 1999 Ross Johnson + + * configure: Various temporary changes. + - Kevin Ruland + + * README: Update. + + * pthread.def (pthread_attr_getstackaddr): uncomment + (pthread_attr_setstackaddr): uncomment + +Fri Feb 5 13:42:30 1999 Ross Johnson + + * semaphore.c: Comment format changes. + +Thu Feb 4 10:07:28 1999 Ross Johnson + + * global.c: Remove ptw32_exception instantiation. + + * cancel.c (pthread_testcancel): Change C++ exception throw. + + * implement.h: Remove extern declaration. + +Wed Feb 3 13:04:44 1999 Ross Johnson + + * cleanup.c: Rename ptw32_*_cleanup() to pthread_*_cleanup(). + + * pthread.def: Ditto. + + * pthread.h: Ditto. + + * pthread.def (pthread_cleanup_push): Remove from export list; + the function is defined as a macro under all compilers. + (pthread_cleanup_pop): Ditto. + + * pthread.h: Remove #if defined(). + +Wed Feb 3 10:13:48 1999 Ross Johnson + + * sync.c (pthread_join): Check for NULL value_ptr arg; + check for detached threads. + +Tue Feb 2 18:07:43 1999 Ross Johnson + + * implement.h: Add #include . + Change sem_t to ptw32_sem_t. + +Tue Feb 2 18:07:43 1999 Kevin Ruland + + * signal.c (pthread_sigmask): Add and modify casts. + Reverse LHS/RHS bitwise assignments. + + * pthread.h: Remove #include . + (PTW32_ATTR_VALID): Add cast. + (struct pthread_t_): Add sigmask element. + + * dll.c: Add "extern C" for DLLMain. + (DllMain): Add cast. + + * create.c (pthread_create): Set sigmask in thread. + + * condvar.c: Remove #include. Change sem_* to ptw32_sem_*. + + * attr.c: Changed #include. + + * Makefile.in: Additional targets and changes to build the library + as a DLL. + +Fri Jan 29 11:56:28 1999 Ross Johnson + + * Makefile.in (OBJS): Add semaphore.o to list. + + * semaphore.c (ptw32_sem_timedwait): Move from private.c. + Rename sem_* to ptw32_sem_*. + + * pthread.h (pthread_cond_t): Change type of sem_t. + _POSIX_SEMAPHORES no longer defined. + + * semaphore.h: Contents moved to implement.h. + Removed from source tree. + + * implement.h: Add semaphore function prototypes and rename all + functions to prepend 'ptw32_'. They are + now private to the pthreads-win32 implementation. + + * private.c: Change #warning. + Move ptw32_sem_timedwait() to semaphore.c. + + * cleanup.c: Change #warning. + + * misc.c: Remove #include + + * pthread.def: Cleanup CVS merge conflicts. + + * global.c: Ditto. + + * ChangeLog: Ditto. + + * cleanup.c: Ditto. + +Sun Jan 24 01:34:52 1999 Ross Johnson + + * semaphore.c (sem_wait): Remove second arg to + pthreadCancelableWait() call. + +Sat Jan 23 17:36:40 1999 Ross Johnson + + * pthread.def: Add new functions to export list. + + * pthread.h (PTHREAD_MUTEX_AUTO_CS_NP): New. + (PTHREAD_MUTEX_FORCE_CS_NP): New. + + * README: Updated. + +Fri Jan 22 14:31:59 1999 Ross Johnson + + * Makefile.in (CFLAGS): Remove -fhandle-exceptions. Not needed + with egcs. Add -g for debugging. + + * create.c (pthread_create): Replace __stdcall with PT_STDCALL + macro. This is a hack and must be fixed. + + * misc.c (CancelableWait): Remove redundant statement. + + * mutex.c (pthread_mutexattr_init): Cast calloc return value. + + * misc.c (CancelableWait): Add cast. + (pthread_self): Add cast. + + * exit.c (pthread_exit): Add cast. + + * condvar.c (pthread_condattr_init): Cast calloc return value. + + * cleanup.c: Reorganise conditional compilation. + + * attr.c (pthread_attr_init): Remove unused 'result'. + Cast malloc return value. + + * private.c (ptw32_callUserDestroyRoutines): Redo conditional + compilation. + + * misc.c (CancelableWait): C++ version uses 'throw'. + + * cancel.c (pthread_testcancel): Ditto. + + * implement.h (class ptw32_exception): Define for C++. + + * pthread.h: Fix C, C++, and Win32 SEH condition compilation + mayhem around pthread_cleanup_* defines. C++ version now uses John + Bossom's cleanup handlers. + (pthread_attr_t): Make 'valid' unsigned. + Define '_timeb' as 'timeb' for Ming32. + Define PT_STDCALL as nothing for Mingw32. May be temporary. + + * cancel.c (pthread_testcancel): Cast return value. + +Wed Jan 20 09:31:28 1999 Ross Johnson + + * pthread.h (pthread_mutexattr_t): Changed to a pointer. + + * mutex.c (pthread_mutex_init): Conditionally create Win32 mutex + - from John Bossom's implementation. + (pthread_mutex_destroy): Conditionally close Win32 mutex + - from John Bossom's implementation. + (pthread_mutexattr_init): Replaced by John Bossom's version. + (pthread_mutexattr_destroy): Ditto. + (pthread_mutexattr_getpshared): New function from John Bossom's + implementation. + (pthread_mutexattr_setpshared): New function from John Bossom's + implementation. + +Tue Jan 19 18:27:42 1999 Ross Johnson + + * pthread.h (pthreadCancelableTimedWait): New prototype. + (pthreadCancelableWait): Remove second argument. + + * misc.c (CancelableWait): New static function is + pthreadCancelableWait() renamed. + (pthreadCancelableWait): Now just calls CancelableWait() with + INFINITE timeout. + (pthreadCancelableTimedWait): Just calls CancelableWait() + with passed in timeout. + +Tue Jan 19 18:27:42 1999 Scott Lightner + + * private.c (ptw32_sem_timedwait): 'abstime' arg really is + absolute time. Calculate relative time to wait from current + time before passing timeout to new routine + pthreadCancelableTimedWait(). + +Tue Jan 19 10:27:39 1999 Ross Johnson + + * pthread.h (pthread_mutexattr_setforcecs_np): New prototype. + + * mutex.c (pthread_mutexattr_init): Init 'pshared' and 'forcecs' + attributes to 0. + (pthread_mutexattr_setforcecs_np): New function (not portable). + + * pthread.h (pthread_mutex_t): + Add 'mutex' element. Set to NULL in PTHREAD_MUTEX_INITIALIZER. + The pthread_mutex_*() routines will try to optimise performance + by choosing either mutexes or critical sections as the basis + for pthread mutexes for each indevidual mutex. + (pthread_mutexattr_t_): Add 'forcecs' element. + Some applications may choose to force use of critical sections + if they know that:- + the mutex is PROCESS_PRIVATE and, + either the OS supports TryEnterCriticalSection() or + pthread_mutex_trylock() will never be called on the mutex. + This attribute will be setable via a non-portable routine. + + Note: We don't yet support PROCESS_SHARED mutexes, so the + implementation as it stands will default to Win32 mutexes only if + the OS doesn't support TryEnterCriticalSection. On Win9x, and early + versions of NT 'forcecs' will need to be set in order to get + critical section based mutexes. + +Sun Jan 17 12:01:26 1999 Ross Johnson + + * pthread.h (PTHREAD_MUTEX_INITIALIZER): Init new 'staticinit' + value to '1' and existing 'valid' value to '1'. + + * global.c (ptw32_mutex_test_init_lock): Add. + + * implement.h (ptw32_mutex_test_init_lock.): Add extern. + + * private.c (ptw32_processInitialize): Init critical section for + global lock used by _mutex_check_need_init(). + (ptw32_processTerminate): Ditto (:s/Init/Destroy/). + + * dll.c (dllMain): Move call to FreeLibrary() so that it is only + called once when the process detaches. + + * mutex.c (_mutex_check_need_init): New static function to test + and init PTHREAD_MUTEX_INITIALIZER mutexes. Provides serialised + access to the internal state of the uninitialised static mutex. + Called from pthread_mutex_trylock() and pthread_mutex_lock() which + do a quick unguarded test to check if _mutex_check_need_init() + needs to be called. This is safe as the test is conservative + and is repeated inside the guarded section of + _mutex_check_need_init(). Thus in all calls except the first + calls to lock static mutexes, the additional overhead to lock any + mutex is a single memory fetch and test for zero. + + * pthread.h (pthread_mutex_t_): Add 'staticinit' member. Mutexes + initialised by PTHREAD_MUTEX_INITIALIZER aren't really initialised + until the first attempt to lock it. Using the 'valid' + flag (which flags the mutex as destroyed or not) to record this + information would be messy. It is possible for a statically + initialised mutex such as this to be destroyed before ever being + used. + + * mutex.c (pthread_mutex_trylock): Call _mutex_check_need_init() + to test/init PTHREAD_MUTEX_INITIALIZER mutexes. + (pthread_mutex_lock): Ditto. + (pthread_mutex_unlock): Add check to ensure we don't try to unlock + an unitialised static mutex. + (pthread_mutex_destroy): Add check to ensure we don't try to delete + a critical section that we never created. Allows us to destroy + a static mutex that has never been locked (and hence initialised). + (pthread_mutex_init): Set 'staticinit' flag to 0 for the new mutex. + +Sun Jan 17 12:01:26 1999 Ross Johnson + + * private.c (ptw32_sem_timedwait): Move from semaphore.c. + + * semaphore.c : Remove redundant #includes. + (ptw32_sem_timedwait): Move to private.c. + (sem_wait): Add missing abstime arg to pthreadCancelableWait() call. + +Fri Jan 15 23:38:05 1999 Ross Johnson + + * condvar.c (cond_timedwait): Remove comment. + +Fri Jan 15 15:41:28 1999 Ross Johnson + + * pthread.h: Add new 'abstime' arg to pthreadCancelableWait() + prototype. + + * condvar.c (cond_timedwait): New generalised function called by + both pthread_cond_wait() and pthread_cond_timedwait(). This is + essentially pthread_cond_wait() renamed and modified to add the + 'abstime' arg and call the new ptw32_sem_timedwait() instead of + sem_wait(). + (pthread_cond_wait): Now just calls the internal static + function cond_timedwait() with an INFINITE wait. + (pthread_cond_timedwait): Now implemented. Calls the internal + static function cond_timedwait(). + + * implement.h (ptw32_sem_timedwait): New internal function + prototype. + + * misc.c (pthreadCancelableWait): Added new 'abstime' argument + to allow shorter than INFINITE wait. + + * semaphore.c (ptw32_sem_timedwait): New function for internal + use. This is essentially sem_wait() modified to add the + 'abstime' arg and call the modified (see above) + pthreadCancelableWait(). + +Thu Jan 14 14:27:13 1999 Ross Johnson + + * cleanup.c: Correct _cplusplus to __cplusplus wherever used. + + * Makefile.in: Add CC=g++ and add -fhandle-exceptions to CFLAGS. + The derived Makefile will compile all units of the package as C++ + so that those which include try/catch exception handling should work + properly. The package should compile ok if CC=gcc, however, exception + handling will not be included and thus thread cancellation, for + example, will not work. + + * cleanup.c (ptw32_pop_cleanup): Add #warning to compile this + file as C++ if using a cygwin32 environment. Perhaps the whole package + should be compiled using g++ under cygwin. + + * private.c (ptw32_threadStart): Change #error directive + into #warning and bracket for __CYGWIN__ and derivative compilers. + +Wed Jan 13 09:34:52 1999 Ross Johnson + + * build.bat: Delete old binaries before compiling/linking. + +Tue Jan 12 09:58:38 1999 Tor Lillqvist + + * dll.c: The Microsoft compiler pragmas probably are more + appropriately protected by _MSC_VER than by _WIN32. + + * pthread.h: Define ETIMEDOUT. This should be returned by + pthread_cond_timedwait which is not implemented yet as of + snapshot-1999-01-04-1305. It was implemented in the older version. + The Microsoft compiler pragmas probably are more appropriately + protected by _MSC_VER than by _WIN32. + + * pthread.def: pthread_mutex_destroy was missing from the def file + + * condvar.c (pthread_cond_broadcast): Ensure we only wait on threads + if there were any waiting on the condition. + I think pthread_cond_broadcast should do the WaitForSingleObject + only if cv->waiters > 0? Otherwise it seems to hang, at least in the + testg thread program from glib. + +Tue Jan 12 09:58:38 1999 Ross Johnson + + * condvar.c (pthread_cond_timedwait): Fix function description + comments. + + * semaphore.c (sem_post): Correct typo in comment. + +Mon Jan 11 20:33:19 1999 Ross Johnson + + * pthread.h: Re-arrange conditional compile of pthread_cleanup-* + macros. + + * cleanup.c (ptw32_push_cleanup): Provide conditional + compile of cleanup->prev. + +1999-01-11 Tor Lillqvist + + * condvar.c (pthread_cond_init): Invert logic when testing the + return value from calloc(). + +Sat Jan 9 14:32:08 1999 Ross Johnson + + * implement.h: Compile-time switch for CYGWIN derived environments + to use CreateThread instead of _beginthreadex. Ditto for ExitThread. + Patch provided by Anders Norlander . + +Tue Jan 5 16:33:04 1999 Ross Johnson + + * cleanup.c (ptw32_pop_cleanup): Add C++ version of __try/__except + block. Move trailing "}" out of #ifdef _WIN32 block left there by + (rpj's) mistake. + + * private.c: Remove #include which is included by pthread.h. + +1998-12-11 Ben Elliston + + * README: Update info about subscribing to the mailing list. + +Mon Jan 4 11:23:40 1999 Ross Johnson + + * all: No code changes, just cleanup. + - remove #if 0 /* Pre Bossom */ enclosed code. + - Remove some redundant #includes. + * pthread.h: Update implemented/unimplemented routines list. + * Tag the bossom merge branch getting ready to merge back to main + trunk. + +Tue Dec 29 13:11:16 1998 Ross Johnson + + * implement.h: Move the following struct definitions to pthread.h: + pthread_t_, pthread_attr_t_, pthread_mutex_t_, pthread_mutex_t_, + pthread_mutexattr_t_, pthread_key_t_, pthread_cond_t_, + pthread_condattr_t_, pthread_once_t_. + + * pthread.h: Add "_" prefix to pthread_push_cleanup and + pthread_pop_cleanup internal routines, and associated struct and + typedefs. + + * buildlib.bat: Add compile command for semaphore.c + + * pthread.def: Comment out pthread_atfork routine name. + Now unimplemented. + + * tsd.c (pthread_setspecific): Rename tkAssocCreate to + ptw32_tkAssocCreate. + (pthread_key_delete): Rename tkAssocDestroy to + ptw32_tkAssocDestroy. + + * sync.c (pthread_join): Rename threadDestroy to ptw32_threadDestroy + + * sched.c (is_attr): attr is now **attr (was *attr), so add extra + NULL pointer test. + (pthread_attr_setschedparam): Increase redirection for attr which is + now a **. + (pthread_attr_getschedparam): Ditto. + (pthread_setschedparam): Change thread validation and rename "thread" + Win32 thread Handle element name to match John Bossom's version. + (pthread_getschedparam): Ditto. + + * private.c (ptw32_threadDestroy): Rename call to + callUserDestroyRoutines() as ptw32_callUserDestroyRoutines() + + * misc.c: Add #include "implement.h". + + * dll.c: Remove defined(KLUDGE) wrapped code. + + * fork.c: Remove redefinition of ENOMEM. + Remove pthread_atfork() and fork() with #if 0/#endif. + + * create.c (pthread_create): Rename threadStart and threadDestroy calls + to ptw32_threadStart and ptw32_threadDestroy. + + * implement.h: Rename "detachedstate" to "detachstate". + + * attr.c: Rename "detachedstate" to "detachstate". + +Mon Dec 28 09:54:39 1998 John Bossom + + * semaphore.c: Initial version. + * semaphore.h: Initial version. + +Mon Dec 28 09:54:39 1998 Ross Johnson + + * pthread.h (pthread_attr_t_): Change to *pthread_attr_t. + +Mon Dec 28 09:54:39 1998 John Bossom, Ben Elliston + + * attr.c (pthread_attr_setstacksize): Merge with John's version. + (pthread_attr_getstacksize): Merge with John's version. + (pthread_attr_setstackaddr): Merge with John's version. + (pthread_attr_getstackaddr): Merge with John's version. + (pthread_attr_init): Merge with John's version. + (pthread_attr_destroy): Merge with John's version. + (pthread_attr_getdetachstate): Merge with John's version. + (pthread_attr_setdetachstate): Merge with John's version. + (is_attr): attr is now **attr (was *attr), so add extra NULL pointer + test. + +Mon Dec 28 09:54:39 1998 Ross Johnson + + * implement.h (pthread_attr_t_): Add and rename elements in JEB's + version to correspond to original, so that it can be used with + original attr routines. + + * pthread.h: Add #endif at end which was truncated in merging. + +Sun Dec 20 14:51:58 1998 Ross Johnson + + * misc.c (pthreadCancelableWait): New function by John Bossom. Non-standard + but provides a hook that can be used to implement cancellation points in + applications that use this library. + + * pthread.h (pthread_cleanup_pop): C++ (non-WIN32) version uses + try/catch to emulate John Bossom's WIN32 __try/__finally behaviour. + In the WIN32 version __finally block, add a test for AbnormalTermination otherwise + cleanup is only run if the cleanup_pop execute arg is non-zero. Cancellation + should cause the cleanup to run irrespective of the execute arg. + + * condvar.c (pthread_condattr_init): Replaced by John Bossom's version. + (pthread_condattr_destroy): Replaced by John Bossom's version. + (pthread_condattr_getpshared): Replaced by John Bossom's version. + (pthread_condattr_setpshared): Replaced by John Bossom's version. + (pthread_cond_init): Replaced by John Bossom's version. + Fix comment (refered to mutex rather than condition variable). + (pthread_cond_destroy): Replaced by John Bossom's version. + (pthread_cond_wait): Replaced by John Bossom's version. + (pthread_cond_timedwait): Replaced by John Bossom's version. + (pthread_cond_signal): Replaced by John Bossom's version. + (pthread_cond_broadcast): Replaced by John Bossom's version. + +Thu Dec 17 19:10:46 1998 Ross Johnson + + * tsd.c (pthread_key_create): Replaced by John Bossom's version. + (pthread_key_delete): Replaced by John Bossom's version. + (pthread_setspecific): Replaced by John Bossom's version. + (pthread_getspecific): Replaced by John Bossom's version. + +Mon Dec 7 09:44:40 1998 John Bossom + + * cancel.c (pthread_setcancelstate): Replaced. + (pthread_setcanceltype): Replaced. + (pthread_testcancel): Replaced. + (pthread_cancel): Replaced. + + * exit.c (pthread_exit): Replaced. + + * misc.c (pthread_self): Replaced. + (pthread_equal): Replaced. + + * sync.c (pthread_detach): Replaced. + (pthread_join): Replaced. + + * create.c (pthread_create): Replaced. + + * private.c (ptw32_processInitialize): New. + (ptw32_processTerminate): New. + (ptw32_threadStart): New. + (ptw32_threadDestroy): New. + (ptw32_cleanupStack): New. + (ptw32_tkAssocCreate): New. + (ptw32_tkAssocDestroy): New. + (ptw32_callUserDestroyRoutines): New. + + * implement.h: Added non-API structures and declarations. + + * dll.c (PthreadsEntryPoint): Cast return value of GetProcAddress + to resolve compile warning from MSVC. + + * dll.c (DLLmain): Replaced. + * dll.c (PthreadsEntryPoint): + Re-applied Anders Norlander's patch:- + Initialize ptw32_try_enter_critical_section at startup + and release kernel32 handle when DLL is being unloaded. + +Sun Dec 6 21:54:35 1998 Ross Johnson + + * buildlib.bat: Fix args to CL when building the .DLL + + * cleanup.c (ptw32_destructor_run_all): Fix TSD key management. + This is a tidy-up before TSD and Thread management is completely + replaced by John Bossom's code. + + * tsd.c (pthread_key_create): Fix TSD key management. + + * global.c (ptw32_key_virgin_next): Initialise. + + * build.bat: New DOS script to compile and link a pthreads app + using Microsoft's CL compiler linker. + * buildlib.bat: New DOS script to compile all the object files + and create pthread.lib and pthread.dll using Microsoft's CL + compiler linker. + +1998-12-05 Anders Norlander + + * implement.h (ptw32_try_enter_critical_section): New extern + * dll.c (ptw32_try_enter_critical_section): New pointer to + TryEnterCriticalSection if it exists; otherwise NULL. + * dll.c (PthreadsEntryPoint): + Initialize ptw32_try_enter_critical_section at startup + and release kernel32 handle when DLL is being unloaded. + * mutex.c (pthread_mutex_trylock): Replaced check for NT with + a check if ptw32_try_enter_critical_section is valid + pointer to a function. Call ptw32_try_enter_critical_section + instead of TryEnterCriticalSection to avoid errors on Win95. + +Thu Dec 3 13:32:00 1998 Ross Johnson + + * README: Correct cygwin32 compatibility statement. + +Sun Nov 15 21:24:06 1998 Ross Johnson + + * cleanup.c (ptw32_destructor_run_all): Declare missing void * arg. + Fixup CVS merge conflicts. + +1998-10-30 Ben Elliston + + * condvar.c (cond_wait): Fix semantic error. Test for equality + instead of making an assignment. + +Fri Oct 30 15:15:50 1998 Ross Johnson + + * cleanup.c (ptw32_handler_push): Fixed bug appending new + handler to list reported by Peter Slacik + . + (new_thread): Rename poorly named local variable to + "new_handler". + +Sat Oct 24 18:34:59 1998 Ross Johnson + + * global.c: Add TSD key management array and index declarations. + + * implement.h: Ditto for externs. + +Fri Oct 23 00:08:09 1998 Ross Johnson + + * implement.h (PTW32_TSD_KEY_REUSE): Add enum. + + * private.c (ptw32_delete_thread): Add call to + ptw32_destructor_run_all() to clean up the threads keys. + + * cleanup.c (ptw32_destructor_run_all): Check for no more dirty + keys to run destructors on. Assume that the destructor call always + succeeds and set the key value to NULL. + +Thu Oct 22 21:44:44 1998 Ross Johnson + + * tsd.c (pthread_setspecific): Add key management code. + (pthread_key_create): Ditto. + (pthread_key_delete): Ditto. + + * implement.h (struct ptw32_tsd_key): Add status member. + + * tsd.c: Add description of pthread_key_delete() from the + standard as a comment. + +Fri Oct 16 17:38:47 1998 Ross Johnson + + * cleanup.c (ptw32_destructor_run_all): Fix and improve + stepping through the key table. + +Thu Oct 15 14:05:01 1998 Ross Johnson + + * private.c (ptw32_new_thread): Remove init of destructorstack. + No longer an element of pthread_t. + + * tsd.c (pthread_setspecific): Fix type declaration and cast. + (pthread_getspecific): Ditto. + (pthread_getspecific): Change error return value to NULL if key + is not in use. + +Thu Oct 15 11:53:21 1998 Ross Johnson + + * global.c (ptw32_tsd_key_table): Fix declaration. + + * implement.h(ptw32_TSD_keys_TlsIndex): Add missing extern. + (ptw32_tsd_mutex): Ditto. + + * create.c (ptw32_start_call): Fix "keys" array declaration. + Add comment. + + * tsd.c (pthread_setspecific): Fix type declaration and cast. + (pthread_getspecific): Ditto. + + * cleanup.c (ptw32_destructor_run_all): Declare missing loop + counter. + +Wed Oct 14 21:09:24 1998 Ross Johnson + + * private.c (ptw32_new_thread): Increment ptw32_threads_count. + (ptw32_delete_thread): Decrement ptw32_threads_count. + Remove some comments. + + * exit.c (ptw32_exit): : Fix two pthread_mutex_lock() calls that + should have been pthread_mutex_unlock() calls. + (ptw32_vacuum): Remove call to ptw32_destructor_pop_all(). + + * create.c (pthread_create): Fix two pthread_mutex_lock() calls that + should have been pthread_mutex_unlock() calls. + + * global.c (ptw32_tsd_mutex): Add mutex for TSD operations. + + * tsd.c (pthread_key_create): Add critical section. + (pthread_setspecific): Ditto. + (pthread_getspecific): Ditto. + (pthread_key_delete): Ditto. + + * sync.c (pthread_join): Fix two pthread_mutex_lock() calls that + should have been pthread_mutex_unlock() calls. + +Mon Oct 12 00:00:44 1998 Ross Johnson + + * implement.h (ptw32_tsd_key_table): New. + + * create.c (ptw32_start_call): Initialise per-thread TSD keys + to NULL. + + * misc.c (pthread_once): Correct typo in comment. + + * implement.h (ptw32_destructor_push): Remove. + (ptw32_destructor_pop): Remove. + (ptw32_destructor_run_all): Rename from ptw32_destructor_pop_all. + (PTW32_TSD_KEY_DELETED): Add enum. + (PTW32_TSD_KEY_INUSE): Add enum. + + * cleanup.c (ptw32_destructor_push): Remove. + (ptw32_destructor_pop): Remove. + (ptw32_destructor_run_all): Totally revamped TSD. + + * dll.c (ptw32_TSD_keys_TlsIndex): Initialise. + + * tsd.c (pthread_setspecific): Totally revamped TSD. + (pthread_getspecific): Ditto. + (pthread_create): Ditto. + (pthread_delete): Ditto. + +Sun Oct 11 22:44:55 1998 Ross Johnson + + * global.c (ptw32_tsd_key_table): Add new global. + + * implement.h (ptw32_tsd_key_t and struct ptw32_tsd_key): + Add. + (struct _pthread): Remove destructorstack. + + * cleanup.c (ptw32_destructor_run_all): Rename from + ptw32_destructor_pop_all. The key destructor stack was made + global rather than per-thread. No longer removes destructor nodes + from the stack. Comments updated. + +1998-10-06 Ben Elliston + + * condvar.c (cond_wait): Use POSIX, not Win32 mutex calls. + (pthread_cond_broadcast): Likewise. + (pthread_cond_signal): Likewise. + +1998-10-05 Ben Elliston + + * pthread.def: Update. Some functions aren't available yet, others + are macros in . + + * tests/join.c: Remove; useless. + +Mon Oct 5 14:25:08 1998 Ross Johnson + + * pthread.def: New file for building the DLL. + +1998-10-05 Ben Elliston + + * misc.c (pthread_equal): Correct inverted logic bug. + (pthread_once): Use the POSIX mutex primitives, not Win32. Remove + irrelevant FIXME comment. + + * global.c (PTHREAD_MUTEX_INITIALIZER): Move to pthread.h. + + * pthread.h (PTHREAD_MUTEX_INITIALIZER): Define. + (pthread_mutex_t): Reimplement as a struct containing a valid + flag. If the flag is ever down upon entry to a mutex operation, + we call pthread_mutex_create() to initialise the object. This + fixes the problem of how to handle statically initialised objects + that can't call InitializeCriticalSection() due to their context. + (PTHREAD_ONCE_INIT): Define. + + * mutex.c (pthread_mutex_init): Set valid flag. + (pthread_mutex_destroy): Clear valid flag. + (pthread_mutex_lock): Check and handle the valid flag. + (pthread_mutex_unlock): Likewise. + (pthread_mutex_trylock): Likewise. + + * tests/mutex3.c: New file; test for the static initialisation + macro. Passes. + + * tests/create1.c: New file; test pthread_create(). Passes. + + * tests/equal.c: Poor test; remove. + + * tests/equal1.c New file; test pthread_equal(). Passes. + + * tests/once1.c: New file; test for pthread_once(). Passes. + + * tests/self.c: Remove; rename to self1.c. + + * tests/self1.c: This is the old self.c. + + * tests/self2.c: New file. Test pthread_self() with a single + thread. Passes. + + * tests/self3.c: New file. Test pthread_self() with a couple of + threads to ensure their thread IDs differ. Passes. + +1998-10-04 Ben Elliston + + * tests/mutex2.c: Test pthread_mutex_trylock(). Passes. + + * tests/mutex1.c: New basic test for mutex functions (it passes). + (main): Eliminate warning. + + * configure.in: Test for __stdcall, not _stdcall. Typo. + + * configure: Regenerate. + + * attr.c (pthread_attr_setstackaddr): Remove FIXME comment. Win32 + does know about ENOSYS after all. + (pthread_attr_setstackaddr): Likewise. + +1998-10-03 Ben Elliston + + * configure.in: Test for the `_stdcall' keyword. Define `STDCALL' + to `_stdcall' if we have it, null otherwise. + + * configure: Regenerate. + + * acconfig.h (STDCALL): New define. + + * config.h.in: Regenerate. + + * create.c (ptw32_start_call): Add STDCALL prefix. + + * mutex.c (pthread_mutex_init): Correct function signature. + + * attr.c (pthread_attr_init): Only zero out the `sigmask' member + if we have the sigset_t type. + + * pthread.h: No need to include . It doesn't even exist + on Win32! Again, an artifact of cross-compilation. + (pthread_sigmask): Only provide if we have the sigset_t type. + + * process.h: Remove. This was a stand-in before we started doing + native compilation under Win32. + + * pthread.h (pthread_mutex_init): Make `attr' argument const. + +1998-10-02 Ben Elliston + + * COPYING: Remove. + + * COPYING.LIB: Add. This library is under the LGPL. + +1998-09-13 Ben Elliston + + * configure.in: Test for required system features. + + * configure: Generate. + + * acconfig.h: New file. + + * config.h.in: Generate. + + * Makefile.in: Renamed from Makefile. + + * COPYING: Import from a recent GNU package. + + * config.guess: Likewise. + + * config.sub: Likewise. + + * install-sh: Likewise. + + * config.h: Remove. + + * Makefile: Likewise. + +1998-09-12 Ben Elliston + + * windows.h: No longer needed; remove. + + * windows.c: Likewise. + +Sat Sep 12 20:09:24 1998 Ross Johnson + + * windows.h: Remove error number definitions. These are in + + * tsd.c: Add comment explaining rationale for not building + POSIX TSD on top of Win32 TLS. + +1998-09-12 Ben Elliston + + * {most}.c: Include to get POSIX error values. + + * signal.c (pthread_sigmask): Only provide if HAVE_SIGSET_T is + defined. + + * config.h: #undef features, don't #define them. This will be + generated by autoconf very soon. + +1998-08-11 Ben Elliston + + * Makefile (LIB): Define. + (clean): Define target. + (all): Build a library not just the object files. + + * pthread.h: Provide a definition for struct timespec if we don't + already have one. + + * windows.c (TlsGetValue): Bug fix. + +Thu Aug 6 15:19:22 1998 Ross Johnson + + * misc.c (pthread_once): Fix arg 1 of EnterCriticalSection() + and LeaveCriticalSection() calls to pass address-of lock. + + * fork.c (pthread_atfork): Typecast (void (*)(void *)) funcptr + in each ptw32_handler_push() call. + + * exit.c (ptw32_exit): Fix attr arg in + pthread_attr_getdetachstate() call. + + * private.c (ptw32_new_thread): Typecast (HANDLE) NULL. + (ptw32_delete_thread): Ditto. + + * implement.h: (PTW32_MAX_THREADS): Add define. This keeps + changing in an attempt to make thread administration data types + opaque and cleanup DLL startup. + + * dll.c (PthreadsEntryPoint): + (ptw32_virgins): Remove malloc() and free() calls. + (ptw32_reuse): Ditto. + (ptw32_win32handle_map): Ditto. + (ptw32_threads_mutex_table): Ditto. + + * global.c (_POSIX_THREAD_THREADS_MAX): Initialise with + PTW32_MAX_THREADS. + (ptw32_virgins): Ditto. + (ptw32_reuse): Ditto. + (ptw32_win32handle_map): Ditto. + (ptw32_threads_mutex_table): Ditto. + + * create.c (pthread_create): Typecast (HANDLE) NULL. + Typecast (unsigned (*)(void *)) start_routine. + + * condvar.c (pthread_cond_init): Add address-of operator & to + arg 1 of pthread_mutex_init() call. + (pthread_cond_destroy): Add address-of operator & to + arg 1 of pthread_mutex_destroy() call. + + * cleanup.c (ptw32_destructor_pop_all): Add (int) cast to + pthread_getspecific() arg. + (ptw32_destructor_pop): Add (void *) cast to "if" conditional. + (ptw32_destructor_push): Add (void *) cast to + ptw32_handler_push() "key" arg. + (malloc.h): Add include. + + * implement.h (ptw32_destructor_pop): Add prototype. + + * tsd.c (implement.h): Add include. + + * sync.c (pthread_join): Remove target_thread_mutex and it's + initialisation. Rename getdetachedstate to getdetachstate. + Remove unused variable "exitcode". + (pthread_detach): Remove target_thread_mutex and it's + initialisation. Rename getdetachedstate to getdetachstate. + Rename setdetachedstate to setdetachstate. + + * signal.c (pthread_sigmask): Rename SIG_SET to SIG_SETMASK. + Cast "set" to (long *) in assignment to passify compiler warning. + Add address-of operator & to thread->attr.sigmask in memcpy() call + and assignment. + (pthread_sigmask): Add address-of operator & to thread->attr.sigmask + in memcpy() call and assignment. + + * windows.h (THREAD_PRIORITY_ERROR_RETURN): Add. + (THREAD_PRIORITY_LOWEST): Add. + (THREAD_PRIORITY_HIGHEST): Add. + + * sched.c (is_attr): Add function. + (implement.h): Add include. + (pthread_setschedparam): Rename all instances of "sched_policy" + to "sched_priority". + (pthread_getschedparam): Ditto. + +Tue Aug 4 16:57:58 1998 Ross Johnson + + * private.c (ptw32_delete_thread): Fix typo. Add missing ';'. + + * global.c (ptw32_virgins): Change types from pointer to + array pointer. + (ptw32_reuse): Ditto. + (ptw32_win32handle_map): Ditto. + (ptw32_threads_mutex_table): Ditto. + + * implement.h(ptw32_virgins): Change types from pointer to + array pointer. + (ptw32_reuse): Ditto. + (ptw32_win32handle_map): Ditto. + (ptw32_threads_mutex_table): Ditto. + + * private.c (ptw32_delete_thread): Fix "entry" should be "thread". + + * misc.c (pthread_self): Add extern for ptw32_threadID_TlsIndex. + + * global.c: Add comment. + + * misc.c (pthread_once): Fix member -> dereferences. + Change ptw32_once_flag to once_control->flag in "if" test. + +Tue Aug 4 00:09:30 1998 Ross Johnson + + * implement.h(ptw32_virgins): Add extern. + (ptw32_virgin_next): Ditto. + (ptw32_reuse): Ditto. + (ptw32_reuse_top): Ditto. + (ptw32_win32handle_map): Ditto. + (ptw32_threads_mutex_table): Ditto. + + * global.c (ptw32_virgins): Changed from array to pointer. + Storage allocation for the array moved into dll.c. + (ptw32_reuse): Ditto. + (ptw32_win32handle_map): Ditto. + (ptw32_threads_mutex_table): Ditto. + + * dll.c (PthreadsEntryPoint): Set up thread admin storage when + DLL is loaded. + + * fork.c (pthread_atfork): Fix function pointer arg to all + ptw32_handler_push() calls. Change "arg" arg to NULL in child push. + + * exit.c: Add windows.h and process.h includes. + (ptw32_exit): Add local detachstate declaration. + (ptw32_exit): Fix incorrect name for pthread_attr_getdetachstate(). + + * pthread.h (_POSIX_THREAD_ATTR_STACKSIZE): Move from global.c + (_POSIX_THREAD_ATTR_STACKADDR): Ditto. + + * create.c (pthread_create): Fix #if should be #ifdef. + (ptw32_start_call): Remove usused variables. + + * process.h: Create. + + * windows.h: Move _beginthreadex and _endthreadex into + process.h + +Mon Aug 3 21:19:57 1998 Ross Johnson + + * condvar.c (pthread_cond_init): Add NULL attr to + pthread_mutex_init() call - default attributes will be used. + (cond_wait): Fix typo. + (cond_wait): Fix typo - cv was ev. + (pthread_cond_broadcast): Fix two identical typos. + + * cleanup.c (ptw32_destructor_pop_all): Remove _ prefix from + PTHREAD_DESTRUCTOR_ITERATIONS. + + * pthread.h: Move _POSIX_* values into posix.h + + * pthread.h: Fix typo in pthread_mutex_init() prototype. + + * attr.c (pthread_attr_init): Fix error in priority member init. + + * windows.h (THREAD_PRIORITY_NORMAL): Add. + + * pthread.h (sched_param): Add missing ';' to struct definition. + + * attr.c (pthread_attr_init): Remove obsolete pthread_attr_t + member initialisation - cancelstate, canceltype, cancel_pending. + (is_attr): Make arg "attr" a const. + + * implement.h (PTW32_HANDLER_POP_LIFO): Remove definition. + (PTW32_HANDLER_POP_FIFO): Ditto. + (PTW32_VALID): Add missing newline escape (\). + (ptw32_handler_node): Make element "next" a pointer. + +1998-08-02 Ben Elliston + + * windows.h: Remove duplicate TlsSetValue() prototype. Add + TlsGetValue() prototype. + (FALSE): Define. + (TRUE): Likewise. + Add forgotten errno values. Guard against multiple #includes. + + * windows.c: New file. Implement stubs for Win32 functions. + + * Makefile (SRCS): Remove. Not explicitly needed. + (CFLAGS): Add -Wall for all warnings with GCC. + +Sun Aug 2 19:03:42 1998 Ross Johnson + + * config.h: Create. This is a temporary stand-in for autoconf yet + to be done. + (HAVE_SIGNAL_H): Add. + + * pthread.h: Minor rearrangement for temporary config.h. + +Fri Jul 31 14:00:29 1998 Ross Johnson + + * cleanup.c (ptw32_destructor_pop): Implement. Removes + destructors associated with a key without executing them. + (ptw32_destructor_pop_all): Add FIXME comment. + + * tsd.c (pthread_key_delete): Add call to ptw32_destructor_pop(). + +Fri Jul 31 00:05:45 1998 Ross Johnson + + * tsd.c (pthread_key_create): Update to properly associate + the destructor routine with the key. + (pthread_key_delete): Add FIXME comment. + + * exit.c (ptw32_vacuum): Add call to + ptw32_destructor_pop_all(). + + * implement.h (ptw32_handler_pop_all): Add prototype. + (ptw32_destructor_pop_all): Ditto. + + * cleanup.c (ptw32_destructor_push): Implement. This is just a + call to ptw32_handler_push(). + (ptw32_destructor_pop_all): Implement. This is significantly + different to ptw32_handler_pop_all(). + + * Makefile (SRCS): Create. Preliminary. + + * windows.h: Create. Contains Win32 definitions for compile + testing. This is just a standin for the real one. + + * pthread.h (SIG_UNBLOCK): Fix typo. Was SIG_BLOCK. + (windows.h): Add include. Required for CRITICAL_SECTION. + (pthread_cond_t): Move enum declaration outside of struct + definition. + (unistd.h): Add include - may be temporary. + + * condvar.c (windows.h): Add include. + + * implement.h (PTW32_THIS): Remove - no longer required. + (PTW32_STACK): Use pthread_self() instead of PTW32_THIS. + +Thu Jul 30 23:12:45 1998 Ross Johnson + + * implement.h: Remove ptw32_find_entry() prototype. + + * private.c: Extend comments. + Remove ptw32_find_entry() - no longer needed. + + * create.c (ptw32_start_call): Add call to TlsSetValue() to + store the thread ID. + + * dll.c (PthreadsEntryPoint): Implement. This is called + whenever a process loads the DLL. Used to initialise thread + local storage. + + * implement.h: Add ptw32_threadID_TlsIndex. + Add ()s around PTW32_VALID expression. + + * misc.c (pthread_self): Re-implement using Win32 TLS to store + the threads own ID. + +Wed Jul 29 11:39:03 1998 Ross Johnson + + * private.c: Corrections in comments. + (ptw32_new_thread): Alter "if" flow to be more natural. + + * cleanup.c (ptw32_handler_push): Same as below. + + * create.c (pthread_create): Same as below. + + * private.c (ptw32_new_thread): Rename "new" to "new_thread". + Since when has a C programmer been required to know C++? + +Tue Jul 28 14:04:29 1998 Ross Johnson + + * implement.h: Add PTW32_VALID macro. + + * sync.c (pthread_join): Modify to use the new thread + type and ptw32_delete_thread(). Rename "target" to "thread". + Remove extra local variable "target". + (pthread_detach): Ditto. + + * signal.c (pthread_sigmask): Move init of "us" out of inner block. + Fix instance of "this" should have been "us". Rename "us" to "thread". + + * sched.c (pthread_setschedparam): Modify to use the new thread + type. + (pthread_getschedparam): Ditto. + + * private.c (ptw32_find_thread): Fix return type and arg. + + * implement.h: Remove PTW32_YES and PTW32_NO. + (ptw32_new_thread): Add prototype. + (ptw32_find_thread): Ditto. + (ptw32_delete_thread): Ditto. + (ptw32_new_thread_entry): Remove prototype. + (ptw32_find_thread_entry): Ditto. + (ptw32_delete_thread_entry): Ditto. + ( PTW32_NEW, PTW32_INUSE, PTW32_EXITED, PTW32_REUSE): + Add. + + + * create.c (pthread_create): Minor rename "us" to "new" (I need + these cues but it doesn't stop me coming out with some major bugs + at times). + Load start_routine and arg into the thread so the wrapper can + call it. + + * exit.c (pthread_exit): Fix pthread_this should be pthread_self. + + * cancel.c (pthread_setcancelstate): Change + ptw32_threads_thread_t * to pthread_t and init with + pthread_this(). + (pthread_setcanceltype): Ditto. + + * exit.c (ptw32_exit): Add new pthread_t arg. + Rename ptw32_delete_thread_entry to ptw32_delete_thread. + Rename "us" to "thread". + (pthread_exit): Call ptw32_exit with added thread arg. + + * create.c (ptw32_start_call): Insert missing ")". + Add "us" arg to ptw32_exit() call. + (pthread_create): Modify to use new thread allocation scheme. + + * private.c: Added detailed explanation of the new thread + allocation scheme. + (ptw32_new_thread): Totally rewritten to use + new thread allocation scheme. + (ptw32_delete_thread): Ditto. + (ptw32_find_thread): Obsolete. + +Mon Jul 27 17:46:37 1998 Ross Johnson + + * create.c (pthread_create): Start of rewrite. Not completed yet. + + * private.c (ptw32_new_thread_entry): Start of rewrite. Not + complete. + + * implement.h (ptw32_threads_thread): Rename, remove thread + member, add win32handle and ptstatus members. + (ptw32_t): Add. + + * pthread.h: pthread_t is no longer mapped directly to a Win32 + HANDLE type. This is so we can let the Win32 thread terminate and + reuse the HANDLE while pthreads holds it's own thread ID until + the last waiting join exits. + +Mon Jul 27 00:20:37 1998 Ross Johnson + + * private.c (ptw32_delete_thread_entry): Destroy the thread + entry attribute object before deleting the thread entry itself. + + * attr.c (pthread_attr_init): Initialise cancel_pending = FALSE. + (pthread_attr_setdetachstate): Rename "detached" to "detachedstate". + (pthread_attr_getdetachstate): Ditto. + + * exit.c (ptw32_exit): Fix incorrect check for detachedstate. + + * implement.h (ptw32_call_t): Remove env member. + +Sun Jul 26 13:06:12 1998 Ross Johnson + + * implement.h (ptw32_new_thread_entry): Fix prototype. + (ptw32_find_thread_entry): Ditto. + (ptw32_delete_thread_entry): Ditto. + (ptw32_exit): Add prototype. + + * exit.c (ptw32_exit): New function. Called from pthread_exit() + and ptw32_start_call() to exit the thread. It allows an extra + argument which is the return code passed to _endthreadex(). + (ptw32_exit): Move thread entry delete call from ptw32_vacuum() + into here. Add more explanation of thread entry deletion. + (ptw32_exit): Clarify comment. + + * create.c (ptw32_start_call): Change pthread_exit() call to + ptw32_exit() call. + + * exit.c (ptw32_vacuum): Add thread entry deletion code + moved from ptw32_start_call(). See next item. + (pthread_exit): Remove longjmp(). Add mutex lock around thread table + manipulation code. This routine now calls _enthreadex(). + + * create.c (ptw32_start_call): Remove setjmp() call and move + cleanup code out. Call pthread_exit(NULL) to terminate the thread. + +1998-07-26 Ben Elliston + + * tsd.c (pthread_getspecific): Update comments. + + * mutex.c (pthread_mutexattr_setpshared): Not supported; remove. + (pthread_mutexattr_getpshared): Likewise. + + * pthread.h (pthread_mutexattr_setpshared): Remove prototype. + (pthread_mutexattr_getpshared): Likewise. + +Sun Jul 26 00:09:59 1998 Ross Johnson + + * sync.c: Rename all instances of ptw32_count_mutex to + ptw32_table_mutex. + + * implement.h: Rename ptw32_count_mutex to + ptw32_table_mutex. + + * global.c: Rename ptw32_count_mutex to + ptw32_table_mutex. + + * create.c (pthread_create): Add critical sections. + (ptw32_start_call): Rename ptw32_count_mutex to + ptw32_table_mutex. + + * cancel.c (pthread_setcancelstate): Fix indirection bug and rename + "this" to "us". + + * signal.c (pthread_sigmask): Rename "this" to "us" and fix some + minor syntax errors. Declare "us" and initialise it. + + * sync.c (pthread_detach): Rename "this" to "target". + + * pthread.h: Converting PTHREAD_* defines to alias the (const int) + values in global.c. + + * global.c: Started converting PTHREAD_* defines to (const int) as + a part of making the eventual pthreads DLL binary compatible + through version changes. + + * condvar.c (cond_wait): Add cancelation point. This applies the + point to both pthread_cond_wait() and pthread_cond_timedwait(). + + * exit.c (pthread_exit): Rename "this" to "us". + + * implement.h: Add comment. + + * sync.c (pthread_join): I've satisfied myself that pthread_detach() + does set the detached attribute in the thread entry attributes + to PTHREAD_CREATE_DETACHED. "if" conditions were changed to test + that attribute instead of a separate flag. + + * create.c (pthread_create): Rename "this" to "us". + (pthread_create): cancelstate and canceltype are not attributes + so the copy to thread entry attribute storage was removed. + Only the thread itself can change it's cancelstate or canceltype, + ie. the thread must exist already. + + * private.c (ptw32_delete_thread_entry): Mutex locks removed. + Mutexes must be applied at the caller level. + (ptw32_new_thread_entry): Ditto. + (ptw32_new_thread_entry): Init cancelstate, canceltype, and + cancel_pending to default values. + (ptw32_new_thread_entry): Rename "this" to "new". + (ptw32_find_thread_entry): Rename "this" to "entry". + (ptw32_delete_thread_entry): Rename "thread_entry" to "entry". + + * create.c (ptw32_start_call): Mutexes changed to + ptw32_count_mutex. All access to the threads table entries is + under the one mutex. Otherwise chaos reigns. + +Sat Jul 25 23:16:51 1998 Ross Johnson + + * implement.h (ptw32_threads_thread): Move cancelstate and + canceltype members out of pthread_attr_t into here. + + * fork.c (fork): Add comment. + +1998-07-25 Ben Elliston + + * fork.c (fork): Autoconfiscate. + +Sat Jul 25 00:00:13 1998 Ross Johnson + + * create.c (ptw32_start_call): Set thread priority. Ensure our + thread entry is removed from the thread table but only if + pthread_detach() was called and there are no waiting joins. + (pthread_create): Set detach flag in thread entry if the + thread is created PTHREAD_CREATE_DETACHED. + + * pthread.h (pthread_attr_t): Rename member "detachedstate". + + * attr.c (pthread_attr_init): Rename attr members. + + * exit.c (pthread_exit): Fix indirection mistake. + + * implement.h (PTW32_THREADS_TABLE_INDEX): Add. + + * exit.c (ptw32_vacuum): Fix incorrect args to + ptw32_handler_pop_all() calls. + Make thread entry removal conditional. + + * sync.c (pthread_join): Add multiple join and async detach handling. + + * implement.h (PTW32_THREADS_TABLE_INDEX): Add. + + * global.c (ptw32_threads_mutex_table): Add. + + * implement.h (ptw32_once_flag): Remove. + (ptw32_once_lock): Ditto. + (ptw32_threads_mutex_table): Add. + + * global.c (ptw32_once_flag): Remove. + (ptw32_once_lock): Ditto. + + * sync.c (pthread_join): Fix tests involving new return value + from ptw32_find_thread_entry(). + (pthread_detach): Ditto. + + * private.c (ptw32_find_thread_entry): Failure return code + changed from -1 to NULL. + +Fri Jul 24 23:09:33 1998 Ross Johnson + + * create.c (pthread_create): Change . to -> in sigmask memcpy() args. + + * pthread.h: (pthread_cancel): Add function prototype. + (pthread_testcancel): Ditto. + +1998-07-24 Ben Elliston + + * pthread.h (pthread_condattr_t): Rename dummy structure member. + (pthread_mutexattr_t): Likewise. + +Fri Jul 24 21:13:55 1998 Ross Johnson + + * cancel.c (pthread_cancel): Implement. + (pthread_testcancel): Implement. + + * exit.c (pthread_exit): Add comment explaining the longjmp(). + + * implement.h (ptw32_threads_thread_t): New member cancelthread. + (PTW32_YES): Define. + (PTW32_NO): Define. + (RND_SIZEOF): Remove. + + * create.c (pthread_create): Rename cancelability to cancelstate. + + * pthread.h (pthread_attr_t): Rename cancelability to cancelstate. + (PTHREAD_CANCELED): Define. + +1998-07-24 Ben Elliston + + * pthread.h (SIG_BLOCK): Define if not already defined. + (SIG_UNBLOCK): Likewise. + (SIG_SETMASK): Likewise. + (pthread_attr_t): Add signal mask member. + (pthread_sigmask): Add function prototype. + + * signal.c (pthread_sigmask): Implement. + + * create.c: #include to get a prototype for memcpy(). + (pthread_create): New threads inherit their creator's signal + mask. Copy the signal mask to the new thread structure if we know + about signals. + +Fri Jul 24 16:33:17 1998 Ross Johnson + + * fork.c (pthread_atfork): Add all the necessary push calls. + Local implementation semantics: + If we get an ENOMEM at any time then ALL handlers + (including those from previous pthread_atfork() calls) will be + popped off each of the three atfork stacks before we return. + (fork): Add all the necessary pop calls. Add the thread cancellation + and join calls to the child fork. + Add #includes. + + * implement.h: (ptw32_handler_push): Fix return type and stack arg + type in prototype. + (ptw32_handler_pop): Fix stack arg type in prototype. + (ptw32_handler_pop_all): Fix stack arg type in prototype. + + * cleanup.c (ptw32_handler_push): Change return type to int and + return ENOMEM if malloc() fails. + + * sync.c (pthread_detach): Use equality test, not assignment. + + * create.c (ptw32_start_call): Add call to Win32 CloseHandle() + if thread is detached. + +1998-07-24 Ben Elliston + + * sync.c (pthread_detach): Close the Win32 thread handle to + emulate detached (or daemon) threads. + +Fri Jul 24 03:00:25 1998 Ross Johnson + + * sync.c (pthread_join): Save valueptr arg in joinvalueptr for + pthread_exit() to use. + + * private.c (ptw32_new_thread_entry): Initialise joinvalueptr to + NULL. + + * create.c (ptw32_start_call): Rewrite to facilitate joins. + pthread_exit() will do a longjmp() back to here. Does appropriate + cleanup and exit/return from the thread. + (pthread_create): _beginthreadex() now passes a pointer to our + thread table entry instead of just the call member of that entry. + + * implement.h (ptw32_threads_thread): New member + void ** joinvalueptr. + (ptw32_call_t): New member jmpbuf env. + + * exit.c (pthread_exit): Major rewrite to handle joins and handing + value pointer to joining thread. Uses longjmp() back to + ptw32_start_call(). + + * create.c (pthread_create): Ensure values of new attribute members + are copied to the thread attribute object. + + * attr.c (pthread_attr_destroy): Fix merge conflicts. + (pthread_attr_getdetachstate): Fix merge conflicts. + (pthread_attr_setdetachstate): Fix merge conflicts. + + * pthread.h: Fix merge conflicts. + + * sync.c (pthread_join): Fix merge conflicts. + +Fri Jul 24 00:21:21 1998 Ross Johnson + + * sync.c (pthread_join): Add check for valid and joinable + thread. + (pthread_detach): Implement. After checking for a valid and joinable + thread, it's still a no-op. + + * private.c (ptw32_find_thread_entry): Bug prevented returning + an error value in some cases. + + * attr.c (pthread_attr_setdetachedstate): Implement. + (pthread_attr_getdetachedstate): Implement. + + * implement.h: Move more hidden definitions into here from + pthread.h. + +1998-07-24 Ben Elliston + + * pthread.h (PTHREAD_CREATE_JOINABLE): Define. + (PTHREAD_CREATE_DETACHED): Likewise. + (pthread_attr_t): Add new structure member `detached'. + (pthread_attr_getdetachstate): Add function prototype. + (pthread_attr_setdetachstate): Likewise. + + * sync.c (pthread_join): Return if the target thread is detached. + + * attr.c (pthread_attr_init): Initialise cancelability and + canceltype structure members. + (pthread_attr_getdetachstate): Implement. + (pthread_attr_setdetachstate): Likewise. + + * implement.h (PTW32_CANCEL_DEFAULTS): Remove. Bit fields + proved to be too cumbersome. Set the defaults in attr.c using the + public PTHREAD_CANCEL_* constants. + + * cancel.c: New file. + + * pthread.h (sched_param): Define this type. + (pthread_attr_getschedparam): Add function prototype. + (pthread_attr_setschedparam): Likewise. + (pthread_setcancelstate): Likewise. + (pthread_setcanceltype): Likewise. + (sched_get_priority_min): Likewise. + (sched_get_priority_max): Likewise. + (pthread_mutexattr_setprotocol): Remove; not supported. + (pthread_mutexattr_getprotocol): Likewise. + (pthread_mutexattr_setprioceiling): Likewise. + (pthread_mutexattr_getprioceiling): Likewise. + (pthread_attr_t): Add canceltype member. Update comments. + (SCHED_OTHER): Define this scheduling policy constant. + (SCHED_FIFO): Likewise. + (SCHED_RR): Likewise. + (SCHED_MIN): Define the lowest possible value for this constant. + (SCHED_MAX): Likewise, the maximum possible value. + (PTHREAD_CANCEL_ASYNCHRONOUS): Redefine. + (PTHREAD_CANCEL_DEFERRED): Likewise. + + * sched.c: New file. + (pthread_setschedparam): Implement. + (pthread_getschedparam): Implement. + (sched_get_priority_max): Validate policy argument. + (sched_get_priority_min): Likewise. + + * mutex.c (pthread_mutexattr_setprotocol): Remove; not supported. + (pthread_mutexattr_getprotocol): Likewise. + (pthread_mutexattr_setprioceiling): Likewise. + (pthread_mutexattr_getprioceiling): Likewise. + +Fri Jul 24 00:21:21 1998 Ross Johnson + + * create.c (pthread_create): Arg to ptw32_new_thread_entry() + changed. See next entry. Move mutex locks out. Changes made yesterday + and today allow us to start the new thread running rather than + temporarily suspended. + + * private.c (ptw32_new_thread_entry): ptw32_thread_table + was changed back to a table of thread structures rather than pointers. + As such we're trading storage for increaded speed. This routine + was modified to work with the new table. Mutex lock put in around + global data accesses. + (ptw32_find_thread_entry): Ditto + (ptw32_delete_thread_entry): Ditto + +Thu Jul 23 23:25:30 1998 Ross Johnson + + * global.c: New. Global data objects declared here. These moved from + pthread.h. + + * pthread.h: Move implementation hidden definitions into + implement.h. + + * implement.h: Move implementation hidden definitions from + pthread.h. Add constants to index into the different handler stacks. + + * cleanup.c (ptw32_handler_push): Simplify args. Restructure. + (ptw32_handler_pop): Simplify args. Restructure. + (ptw32_handler_pop_all): Simplify args. Restructure. + +Wed Jul 22 00:16:22 1998 Ross Johnson + + * attr.c, implement.h, pthread.h, ChangeLog: Resolve CVS merge + conflicts. + + * private.c (ptw32_find_thread_entry): Changes to return type + to support leaner ptw32_threads_table[] which now only stores + ptw32_thread_thread_t *. + (ptw32_new_thread_entry): Internal changes. + (ptw32_delete_thread_entry): Internal changes to avoid contention. + Calling routines changed accordingly. + + * pthread.h: Modified cleanup macros to use new generic push and pop. + Added destructor and atfork stacks to ptw32_threads_thread_t. + + * cleanup.c (ptw32_handler_push, ptw32_handler_pop, + ptw32_handler_pop_all): Renamed cleanup push and pop routines + and made generic to handle destructors and atfork handlers as + well. + + * create.c (ptw32_start_call): New function is a wrapper for + all new threads. It allows us to do some cleanup when the thread + returns, ie. that is otherwise only done if the thread is cancelled. + + * exit.c (ptw32_vacuum): New function contains code from + pthread_exit() that we need in the new ptw32_start_call() + as well. + + * implement.h: Various additions and minor changes. + + * pthread.h: Various additions and minor changes. + Change cleanup handler macros to use generic handler push and pop + functions. + + * attr.c: Minor mods to all functions. + (is_attr): Implemented missing function. + + * create.c (pthread_create): More clean up. + + * private.c (ptw32_find_thread_entry): Implement. + (ptw32_delete_thread_entry): Implement. + (ptw32_new_thread_entry): Implement. + These functions manipulate the implementations internal thread + table and are part of general code cleanup and modularisation. + They replace ptw32_getthreadindex() which was removed. + + * exit.c (pthread_exit): Changed to use the new code above. + + * pthread.h: Add cancelability constants. Update comments. + +1998-07-22 Ben Elliston + + * attr.c (pthread_setstacksize): Update test of attr argument. + (pthread_getstacksize): Likewise. + (pthread_setstackaddr): Likewise. + (pthread_getstackaddr): Likewise. + (pthread_attr_init): No need to allocate any storage. + (pthread_attr_destroy): No need to free any storage. + + * mutex.c (is_attr): Not likely to be needed; remove. + (remove_attr): Likewise. + (insert_attr): Likewise. + + * implement.h (ptw32_mutexattr_t): Moved to a public definition + in pthread.h. There was little gain in hiding these details. + (ptw32_condattr_t): Likewise. + (ptw32_attr_t): Likewise. + + * pthread.h (pthread_atfork): Add function prototype. + (pthread_attr_t): Moved here from implement.h. + + * fork.c (pthread_atfork): Preliminary implementation. + (ptw32_fork): Likewise. + +Wed Jul 22 00:16:22 1998 Ross Johnson + + * cleanup.c (ptw32_cleanup_push): Implement. + (ptw32_cleanup_pop): Implement. + (ptw32_do_cancellation): Implement. + These are private to the implementation. The real cleanup functions + are macros. See below. + + * pthread.h (pthread_cleanup_push): Implement as a macro. + (pthread_cleanup_pop): Implement as a macro. + Because these are macros which start and end a block, the POSIX scoping + requirement is observed. See the comment in the file. + + * exit.c (pthread_exit): Refine the code. + + * create.c (pthread_create): Code cleanup. + + * implement.h (RND_SIZEOF): Add RND_SIZEOF(T) to round sizeof(T) + up to multiple of DWORD. + Add function prototypes. + + * private.c (ptw32_getthreadindex): "*thread" should have been + "thread". Detect empty slot fail condition. + +1998-07-20 Ben Elliston + + * misc.c (pthread_once): Implement. Don't use a per-application + flag and mutex--make `pthread_once_t' contain these elements in + their structure. The earlier version had incorrect semantics. + + * pthread.h (ptw32_once_flag): Add new variable. Remove. + (ptw32_once_lock): Add new mutex lock to ensure integrity of + access to ptw32_once_flag. Remove. + (pthread_once): Add function prototype. + (pthread_once_t): Define this type. + +Mon Jul 20 02:31:05 1998 Ross Johnson + + * private.c (ptw32_getthreadindex): Implement. + + * pthread.h: Add application static data dependent on + _PTHREADS_BUILD_DLL define. This is needed to avoid allocating + non-sharable static data within the pthread DLL. + + * implement.h: Add ptw32_cleanup_stack_t, ptw32_cleanup_node_t + and PTW32_HASH_INDEX. + + * exit.c (pthread_exit): Begin work on cleanup and de-allocate + thread-private storage. + + * create.c (pthread_create): Add thread to thread table. + Keep a thread-private copy of the attributes with default values + filled in when necessary. Same for the cleanup stack. Make + pthread_create C run-time library friendly by using _beginthreadex() + instead of CreateThread(). Fix error returns. + +Sun Jul 19 16:26:23 1998 Ross Johnson + + * implement.h: Rename pthreads_thread_count to ptw32_threads_count. + Create ptw32_threads_thread_t struct to keep thread specific data. + + * create.c: Rename pthreads_thread_count to ptw32_threads_count. + (pthread_create): Handle errors from CreateThread(). + +1998-07-19 Ben Elliston + + * condvar.c (pthread_cond_wait): Generalise. Moved from here .. + (cond_wait): To here. + (pthread_cond_timedwait): Implement; use generalised cond_wait(). + + * pthread.h (pthread_key_t): Define this type. + (pthread_key_create): Add function prototype. + (pthread_setspecific): Likewise. + (pthread_getspecific): Likwise. + (pthread_key_delete): Likewise. + + * tsd.c (pthread_key_create): Implement. + (pthread_setspecific): Likewise. + (pthread_getspecific): Likewise. + (pthread_key_delete): Likewise. + + * mutex.c (pthread_mutex_trylock): Return ENOSYS if this function + is called on a Win32 platform which is not Windows NT. + +1998-07-18 Ben Elliston + + * condvar.c (pthread_condattr_init): Do not attempt to malloc any + storage; none is needed now that condattr_t is an empty struct. + (pthread_condattr_destory): Likewise; do not free storage. + (pthread_condattr_setpshared): No longer supported; return ENOSYS. + (pthread_condattr_getpshared): Likewise. + (pthread_cond_init): Implement with help from Douglas Schmidt. + Remember to initialise the cv's internal mutex. + (pthread_cond_wait): Likewise. + (pthread_cond_signal): Likewise. + (pthread_cond_broadcast): Likewise. + (pthread_cond_timedwait): Preliminary implementation, but I need + to see some API documentation for `WaitForMultipleObject'. + (pthread_destory): Implement. + + * pthread.h (pthread_cond_init): Add function protoype. + (pthread_cond_broadcast): Likewise. + (pthread_cond_signal): Likewise. + (pthread_cond_timedwait): Likewise. + (pthread_cond_wait): Likewise. + (pthread_cond_destroy): Likewise. + (pthread_cond_t): Define this type. Fix for u_int. Do not assume + that the mutex contained withing the pthread_cond_t structure will + be a critical section. Use our new POSIX type! + + * implement.h (ptw32_condattr_t): Remove shared attribute. + +1998-07-17 Ben Elliston + + * pthread.h (PTHREADS_PROCESS_PRIVATE): Remove. + (PTHREAD_PROCESS_SHARED): Likewise. No support for mutexes shared + across processes for now. + (pthread_mutex_t): Use a Win32 CRITICAL_SECTION type for better + performance. + + * implement.h (ptw32_mutexattr_t): Remove shared attribute. + + * mutex.c (pthread_mutexattr_setpshared): This optional function + is no longer supported, since we want to implement POSIX mutex + variables using the much more efficient Win32 critical section + primitives. Critical section objects in Win32 cannot be shared + between processes. + (pthread_mutexattr_getpshared): Likewise. + (pthread_mutexattr_init): No need to malloc any storage; the + attributes structure is now empty. + (pthread_mutexattr_destroy): This is now a nop. + (pthread_mutex_init): Use InitializeCriticalSection(). + (pthread_mutex_destroy): Use DeleteCriticalSection(). + (pthread_mutex_lock): Use EnterCriticalSection(). + (pthread_mutex_trylock): Use TryEnterCriticalSection(). This is + not supported by Windows 9x, but trylock is a hack anyway, IMHO. + (pthread_mutex_unlock): Use LeaveCriticalSection(). + +1998-07-14 Ben Elliston + + * attr.c (pthread_attr_setstacksize): Implement. + (pthread_attr_getstacksize): Likewise. + (pthread_attr_setstackaddr): Likewise. + (pthread_attr_getstackaddr): Likewise. + (pthread_attr_init): Likewise. + (pthread_attr_destroy): Likewise. + + * condvar.c (pthread_condattr_init): Add `_cond' to function name. + + * mutex.c (pthread_mutex_lock): Add `_mutex' to function name. + (pthread_mutex_trylock): Likewise. + (pthread_mutex_unlock): Likewise. + + * pthread.h (pthread_condattr_setpshared): Fix typo. + (pthread_attr_init): Add function prototype. + (pthread_attr_destroy): Likewise. + (pthread_attr_setstacksize): Likewise. + (pthread_attr_getstacksize): Likewise. + (pthread_attr_setstackaddr): Likewise. + (pthread_attr_getstackaddr): Likewise. + +Mon Jul 13 01:09:55 1998 Ross Johnson + + * implement.h: Wrap in #ifndef _IMPLEMENT_H + + * create.c (pthread_create): Map stacksize attr to Win32. + + * mutex.c: Include implement.h + +1998-07-13 Ben Elliston + + * condvar.c (pthread_condattr_init): Implement. + (pthread_condattr_destroy): Likewise. + (pthread_condattr_setpshared): Likewise. + (pthread_condattr_getpshared): Likewise. + + * implement.h (PTHREAD_THREADS_MAX): Remove trailing semicolon. + (PTHREAD_STACK_MIN): Specify; needs confirming. + (ptw32_attr_t): Define this type. + (ptw32_condattr_t): Likewise. + + * pthread.h (pthread_mutex_t): Define this type. + (pthread_condattr_t): Likewise. + (pthread_mutex_destroy): Add function prototype. + (pthread_lock): Likewise. + (pthread_trylock): Likewise. + (pthread_unlock): Likewise. + (pthread_condattr_init): Likewise. + (pthread_condattr_destroy): Likewise. + (pthread_condattr_setpshared): Likewise. + (pthread_condattr_getpshared): Likewise. + + * mutex.c (pthread_mutex_init): Implement. + (pthread_mutex_destroy): Likewise. + (pthread_lock): Likewise. + (pthread_trylock): Likewise. + (pthread_unlock): Likewise. + +1998-07-12 Ben Elliston + + * implement.h (ptw32_mutexattr_t): Define this implementation + internal type. Application programmers only see a mutex attribute + object as a void pointer. + + * pthread.h (pthread_mutexattr_t): Define this type. + (pthread_mutexattr_init): Add function prototype. + (pthread_mutexattr_destroy): Likewise. + (pthread_mutexattr_setpshared): Likewise. + (pthread_mutexattr_getpshared): Likewise. + (pthread_mutexattr_setprotocol): Likewise. + (pthread_mutexattr_getprotocol): Likewise. + (pthread_mutexattr_setprioceiling): Likewise. + (pthread_mutexattr_getprioceiling): Likewise. + (PTHREAD_PROCESS_PRIVATE): Define. + (PTHREAD_PROCESS_SHARED): Define. + + * mutex.c (pthread_mutexattr_init): Implement. + (pthread_mutexattr_destroy): Implement. + (pthread_mutexattr_setprotocol): Implement. + (pthread_mutexattr_getprotocol): Likewise. + (pthread_mutexattr_setprioceiling): Likewise. + (pthread_mutexattr_getprioceiling): Likewise. + (pthread_mutexattr_setpshared): Likewise. + (pthread_mutexattr_getpshared): Likewise. + (insert_attr): New function; very preliminary implementation! + (is_attr): Likewise. + (remove_attr): Likewise. + +Sat Jul 11 14:48:54 1998 Ross Johnson + + * implement.h: Preliminary implementation specific defines. + + * create.c (pthread_create): Preliminary implementation. + +1998-07-11 Ben Elliston + + * sync.c (pthread_join): Implement. + + * misc.c (pthread_equal): Likewise. + + * pthread.h (pthread_join): Add function prototype. + (pthread_equal): Likewise. + +1998-07-10 Ben Elliston + + * misc.c (pthread_self): Implement. + + * exit.c (pthread_exit): Implement. + + * pthread.h (pthread_exit): Add function prototype. + (pthread_self): Likewise. + (pthread_t): Define this type. + +1998-07-09 Ben Elliston + + * create.c (pthread_create): A dummy stub right now. + + * pthread.h (pthread_create): Add function prototype. diff --git a/liblo/pthreads.2/FAQ b/liblo/pthreads.2/FAQ new file mode 100644 index 0000000..ee8968b --- /dev/null +++ b/liblo/pthreads.2/FAQ @@ -0,0 +1,403 @@ + ========================================= + PTHREADS-WIN32 Frequently Asked Questions + ========================================= + +INDEX +----- + +Q 1 What is it? + +Q 2 Which of the several dll versions do I use? + or, + What are all these pthread*.dll and pthread*.lib files? + +Q 3 What is the library naming convention? + +Q 4 Cleanup code default style or: it used to work when I built + the library myself, but now it doesn't - why? + +Q 5 Why is the default library version now less exception-friendly? + +Q 6 Should I use Cygwin or Mingw32 as a development environment? + +Q 7 Now that pthreads-win32 builds under Mingw32, why do I get + memory access violations (segfaults)? + +Q 8 How do I use pthread.dll for Win32 (Visual C++ 5.0) + +Q 9 Cancelation doesn't work for me, why? + +Q 10 How do I generate pthreadGCE.dll and libpthreadw32.a for use + with Mingw32? + +============================================================================= + +Q 1 What is it? +--- + +Pthreads-win32 is an Open Source Software implementation of the +Threads component of the POSIX 1003.1c 1995 Standard for Microsoft's +Win32 environment. Some functions from POSIX 1003.1b are also +supported including semaphores. Other related functions include +the set of read-write lock functions. The library also supports +some of the functionality of the Open Group's Single Unix +specification, version 2, namely mutex types. + +See the file "ANNOUNCE" for more information including standards +conformance details and list of supported routines. + + +------------------------------------------------------------------------------ + +Q 2 Which of the several dll versions do I use? +--- or, + What are all these pthread*.dll and pthread*.lib files? + +Simply, you only use one of them, but you need to choose carefully. + +The most important choice you need to make is whether to use a +version that uses exceptions internally, or not (there are versions +of the library that use exceptions as part of the thread +cancelation and cleanup implementation, and one that uses +setjmp/longjmp instead). + +There is some contension amongst POSIX threads experts as +to how POSIX threads cancelation and exit should work +with languages that include exceptions and handlers, e.g. +C++ and even C (Microsoft's Structured Exceptions). + +The issue is: should cancelation of a thread in, say, +a C++ application cause object destructors and C++ exception +handlers to be invoked as the stack unwinds during thread +exit, or not? + +There seems to be more opinion in favour of using the +standard C version of the library (no EH) with C++ applications +since this appears to be the assumption commercial pthreads +implementations make. Therefore, if you use an EH version +of pthreads-win32 then you may be under the illusion that +your application will be portable, when in fact it is likely to +behave very differently linked with other pthreads libraries. + +Now you may be asking: why have you kept the EH versions of +the library? + +There are a couple of reasons: +- there is division amongst the experts and so the code may + be needed in the future. (Yes, it's in the repository and we + can get it out anytime in the future, but ...) +- pthreads-win32 is one of the few implementations, and possibly + the only freely available one, that has EH versions. It may be + useful to people who want to play with or study application + behaviour under these conditions. + + +------------------------------------------------------------------------------ + +Q 3 What is the library naming convention? +--- + +Because the library is being built using various exception +handling schemes and compilers - and because the library +may not work reliably if these are mixed in an application, +each different version of the library has it's own name. + +Note 1: the incompatibility is really between EH implementations +of the different compilers. It should be possible to use the +standard C version from either compiler with C++ applications +built with a different compiler. If you use an EH version of +the library, then you must use the same compiler for the +application. This is another complication and dependency that +can be avoided by using only the standard C library version. + +Note 2: if you use a standard C pthread*.dll with a C++ +application, then any functions that you define that are +intended to be called via pthread_cleanup_push() must be +__cdecl. + +Note 3: the intention is to also name either the VC or GC +version (it should be arbitrary) as pthread.dll, including +pthread.lib and libpthread.a as appropriate. + +In general: + pthread[VG]{SE,CE,C}.dll + pthread[VG]{SE,CE,C}.lib + +where: + [VG] indicates the compiler + V - MS VC + G - GNU C + + {SE,CE,C} indicates the exception handling scheme + SE - Structured EH + CE - C++ EH + C - no exceptions - uses setjmp/longjmp + +For example: + pthreadVSE.dll (MSVC/SEH) + pthreadGCE.dll (GNUC/C++ EH) + pthreadGC.dll (GNUC/not dependent on exceptions) + +The GNU library archive file names have changed to: + + libpthreadGCE.a + libpthreadGC.a + + +------------------------------------------------------------------------------ + +Q 4 Cleanup code default style or: it used to work when I built +--- the library myself, but now it doesn't - why? + +Up to and including snapshot 2001-07-12, if not defined, the cleanup +style was determined automatically from the compiler used, and one +of the following was defined accordingly: + + __CLEANUP_SEH MSVC only + __CLEANUP_CXX C++, including MSVC++, GNU G++ + __CLEANUP_C C, including GNU GCC, not MSVC + +These defines determine the style of cleanup (see pthread.h) and, +most importantly, the way that cancelation and thread exit (via +pthread_exit) is performed (see the routine ptw32_throw() in private.c). + +In short, the exceptions versions of the library throw an exception +when a thread is canceled or exits (via pthread_exit()), which is +caught by a handler in the thread startup routine, so that the +the correct stack unwinding occurs regardless of where the thread +is when it's canceled or exits via pthread_exit(). + +After snapshot 2001-07-12, unless your build explicitly defines (e.g. +via a compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then +the build now ALWAYS defaults to __CLEANUP_C style cleanup. This style +uses setjmp/longjmp in the cancelation and pthread_exit implementations, +and therefore won't do stack unwinding even when linked to applications +that have it (e.g. C++ apps). This is for consistency with most/all +commercial Unix POSIX threads implementations. + +Although it was not clearly documented before, it is still necessary to +build your application using the same __CLEANUP_* define as was +used for the version of the library that you link with, so that the +correct parts of pthread.h are included. That is, the possible +defines require the following library versions: + + __CLEANUP_SEH pthreadVSE.dll + __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll + __CLEANUP_C pthreadVC.dll or pthreadGC.dll + +THE POINT OF ALL THIS IS: if you have not been defining one of these +explicitly, then the defaults have been set according to the compiler +and language you are using, as described at the top of this +section. + +THIS NOW CHANGES, as has been explained above. For example: + +If you were building your application with MSVC++ i.e. using C++ +exceptions (rather than SEH) and not explicitly defining one of +__CLEANUP_*, then __CLEANUP_C++ was defined for you in pthread.h. +You should have been linking with pthreadVCE.dll, which does +stack unwinding. + +If you now build your application as you had before, pthread.h will now +set __CLEANUP_C as the default style, and you will need to link +with pthreadVC.dll. Stack unwinding will now NOT occur when a +thread is canceled, nor when the thread calls pthread_exit(). + +Your application will now most likely behave differently to previous +versions, and in non-obvious ways. Most likely is that local +objects may not be destroyed or cleaned up after a thread +is canceled. + +If you want the same behaviour as before, then you must now define +__CLEANUP_C++ explicitly using a compiler option and link with +pthreadVCE.dll as you did before. + + +------------------------------------------------------------------------------ + +Q 5 Why is the default library version now less exception-friendly? +--- + +Because most commercial Unix POSIX threads implementations don't allow you to +choose to have stack unwinding. (Compaq's TRU64 Unix is possibly an exception.) + +Therefore, providing it in pthread-win32 as a default could be dangerous +and non-portable. We still provide the choice but you must now consciously +make it. + +WHY NOT REMOVE THE EXCEPTIONS VERSIONS OF THE LIBRARY ALTOGETHER? +There are a few reasons: +- because there are well respected POSIX threads people who believe + that POSIX threads implementations should be exceptions-aware and + do the expected thing in that context. (There are equally respected + people who believe it should not be easily accessible, if it's there + at all.) +- because pthreads-win32 is one of the few implementations that has + the choice, perhaps the only freely available one, and so offers + a laboratory to people who may want to explore the effects; +- although the code will always be around somewhere for anyone who + wants it, once it's removed from the current version it will not be + nearly as visible to people who may have a use for it. + + +------------------------------------------------------------------------------ + +Q 6 Should I use Cygwin or Mingw32 as a development environment? +--- + +Important: see Q7 also. + +Use Mingw32 with the MSVCRT library to build applications that use +the pthreads DLL. + +Cygwin's own internal support for POSIX threads is growing. +Consult that project's documentation for more information. + +------------------------------------------------------------------------------ + +Q 7 Now that pthreads-win32 builds under Mingw32, why do I get +--- memory access violations (segfaults)? + +The latest Mingw32 package has thread-safe exception handling (see Q10). +Also, see Q6 above. + +------------------------------------------------------------------------------ + +Q 8 How do I use pthread.dll for Win32 (Visual C++ 5.0) +--- + +> +> I'm a "rookie" when it comes to your pthread implementation. I'm currently +> desperately trying to install the prebuilt .dll file into my MSVC compiler. +> Could you please provide me with explicit instructions on how to do this (or +> direct me to a resource(s) where I can acquire such information)? +> +> Thank you, +> + +You should have a .dll, .lib, .def, and three .h files. It is recommended +that you use pthreadVC.dll, rather than pthreadVCE.dll or pthreadVSE.dll +(see Q2 above). + +The .dll can go in any directory listed in your PATH environment +variable, so putting it into C:\WINDOWS should work. + +The .lib file can go in any directory listed in your LIB environment +variable. + +The .h files can go in any directory listed in your INCLUDE +environment variable. + +Or you might prefer to put the .lib and .h files into a new directory +and add its path to LIB and INCLUDE. You can probably do this easiest +by editing the file:- + +C:\Program Files\DevStudio\vc\bin\vcvars32.bat + +The .def file isn't used by anything in the pre-compiled version but +is included for information. + +Cheers. +Ross + +------------------------------------------------------------------------------ + +Q 9 Cancelation doesn't work for me, why? +--- + +> I'm investigating a problem regarding thread cancelation. The thread I want +> to cancel has PTHREAD_CANCEL_ASYNCHRONOUS, however, this piece of code +> blocks on the join(): +> +> if ((retv = Pthread_cancel( recvThread )) == 0) +> { +> retv = Pthread_join( recvThread, 0 ); +> } +> +> Pthread_* are just macro's; they call pthread_*. +> +> The thread recvThread seems to block on a select() call. It doesn't get +> cancelled. +> +> Two questions: +> +> 1) is this normal behaviour? +> +> 2) if not, how does the cancel mechanism work? I'm not very familliar to +> win32 programming, so I don't really understand how the *Event() family of +> calls work. + +The answer to your first question is, normal POSIX behaviour would +be to asynchronously cancel the thread. However, even that doesn't +guarantee cancelation as the standard only says it should be +cancelled as soon as possible. + +Snapshot 99-11-02 or earlier only partially supports asynchronous cancellation. +Snapshots since then simulate async cancelation by poking the address of +a cancelation routine into the PC of the threads context. This requires +the thread to be resumed in some way for the cancelation to actually +proceed. This is not true async cancelation, but it is as close as we've +been able to get to it. + +If the thread you're trying to cancel is blocked (for instance, it could be +waiting for data from the network), it will only get cancelled when it unblocks +(when the data arrives). For true pre-emptive cancelation in these cases, +pthreads-win32 from snapshot 2004-05-16 can automatically recognise and use the +QueueUserAPCEx package by Panagiotis E. Hadjidoukas. This package is available +from the pthreads-win32 ftp site and is included in the pthreads-win32 +self-unpacking zip from 2004-05-16 onwards. + +Using deferred cancelation would normally be the way to go, however, +even though the POSIX threads standard lists a number of C library +functions that are defined as deferred cancelation points, there is +no hookup between those which are provided by Windows and the +pthreads-win32 library. + +Incidently, it's worth noting for code portability that the older POSIX +threads standards cancelation point lists didn't include "select" because +(as I read in Butenhof) it wasn't part of POSIX. However, it does appear in +the SUSV3. + +Effectively, the only mandatory cancelation points that pthreads-win32 +recognises are those the library implements itself, ie. + + pthread_testcancel + pthread_cond_wait + pthread_cond_timedwait + pthread_join + sem_wait + sem_timedwait + pthread_delay_np + +The following routines from the non-mandatory list in SUSV3 are +cancelation points in pthreads-win32: + + pthread_rwlock_wrlock + pthread_rwlock_timedwrlock + +The following routines from the non-mandatory list in SUSV3 are not +cancelation points in pthreads-win32: + + pthread_rwlock_rdlock + pthread_rwlock_timedrdlock + +Pthreads-win32 also provides two functions that allow you to create +cancelation points within your application, but only for cases where +a thread is going to block on a Win32 handle. These are: + + pthreadCancelableWait(HANDLE waitHandle) /* Infinite wait */ + + pthreadCancelableTimedWait(HANDLE waitHandle, DWORD timeout) + +------------------------------------------------------------------------------ + + +Q 10 How do I create thread-safe applications using +---- pthreadGCE.dll, libpthreadw32.a and Mingw32? + +This should not be a problem with recent versions of MinGW32. + +For early versions, see Thomas Pfaff's email at: +http://sources.redhat.com/ml/pthreads-win32/2002/msg00000.html +------------------------------------------------------------------------------ + diff --git a/liblo/pthreads.2/GNUmakefile b/liblo/pthreads.2/GNUmakefile new file mode 100644 index 0000000..c70564e --- /dev/null +++ b/liblo/pthreads.2/GNUmakefile @@ -0,0 +1,583 @@ +# +# -------------------------------------------------------------------------- +# +# Pthreads-win32 - POSIX Threads Library for Win32 +# Copyright(C) 1998 John E. Bossom +# Copyright(C) 1999,2005 Pthreads-win32 contributors +# +# Contact Email: rpj@callisto.canberra.edu.au +# +# The current list of contributors is contained +# in the file CONTRIBUTORS included with the source +# code distribution. The list can also be seen at the +# following World Wide Web location: +# http://sources.redhat.com/pthreads-win32/contributors.html +# +# This library 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 2 of the License, or (at your option) any later version. +# +# This library 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 library in the file COPYING.LIB; +# if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# + +DLL_VER = 2 +DLL_VERD= $(DLL_VER)d + +DEVROOT = C:\PTHREADS + +DLLDEST = $(DEVROOT)\DLL +LIBDEST = $(DEVROOT)\DLL + +# If Running MsysDTK +RM = rm -f +MV = mv -f +CP = cp -f + +# If not. +#RM = erase +#MV = rename +#CP = copy + +# For cross compiling use e.g. +# make CROSS=i386-mingw32msvc- clean GC-inlined +CROSS = + +AR = $(CROSS)ar +DLLTOOL = $(CROSS)dlltool +CC = $(CROSS)gcc +CXX = $(CROSS)g++ +RANLIB = $(CROSS)ranlib +RC = $(CROSS)windres + +OPT = $(CLEANUP) -O3 -finline-functions +DOPT = $(CLEANUP) -g -O0 +XOPT = + +RCFLAGS = --include-dir=. +LFLAGS = -lwsock32 + +# ---------------------------------------------------------------------- +# The library can be built with some alternative behaviour to +# facilitate development of applications on Win32 that will be ported +# to other POSIX systems. Nothing definable here will make the library +# non-compliant, but applications that make assumptions that POSIX +# does not garrantee may fail or misbehave under some settings. +# +# PTW32_THREAD_ID_REUSE_INCREMENT +# Purpose: +# POSIX says that applications should assume that thread IDs can be +# recycled. However, Solaris and some other systems use a [very large] +# sequence number as the thread ID, which provides virtual uniqueness. +# Pthreads-win32 provides pseudo-unique IDs when the default increment +# (1) is used, but pthread_t is not a scalar type like Solaris's. +# +# Usage: +# Set to any value in the range: 0 <= value <= 2^wordsize +# +# Examples: +# Set to 0 to emulate non recycle-unique behaviour like Linux or *BSD. +# Set to 1 for recycle-unique thread IDs (this is the default). +# Set to some other +ve value to emulate smaller word size types +# (i.e. will wrap sooner). +# +#PTW32_FLAGS = "-DPTW32_THREAD_ID_REUSE_INCREMENT=0" +# +# ---------------------------------------------------------------------- + +GC_CFLAGS = $(PTW32_FLAGS) +GCE_CFLAGS = $(PTW32_FLAGS) -mthreads + +## Mingw32 +MAKE ?= make +CFLAGS = $(OPT) $(XOPT) -I. -DHAVE_CONFIG_H -Wall + +DLL_INLINED_OBJS = \ + pthread.o \ + version.o + +# Agregate modules for inlinability +DLL_OBJS = \ + attr.o \ + barrier.o \ + cancel.o \ + cleanup.o \ + condvar.o \ + create.o \ + dll.o \ + errno.o \ + exit.o \ + fork.o \ + global.o \ + misc.o \ + mutex.o \ + nonportable.o \ + private.o \ + rwlock.o \ + sched.o \ + semaphore.o \ + signal.o \ + spin.o \ + sync.o \ + tsd.o \ + version.o + +# Separate modules for minimum size statically linked images +SMALL_STATIC_OBJS = \ + pthread_attr_init.o \ + pthread_attr_destroy.o \ + pthread_attr_getdetachstate.o \ + pthread_attr_setdetachstate.o \ + pthread_attr_getstackaddr.o \ + pthread_attr_setstackaddr.o \ + pthread_attr_getstacksize.o \ + pthread_attr_setstacksize.o \ + pthread_attr_getscope.o \ + pthread_attr_setscope.o \ + pthread_attr_setschedpolicy.o \ + pthread_attr_getschedpolicy.o \ + pthread_attr_setschedparam.o \ + pthread_attr_getschedparam.o \ + pthread_attr_setinheritsched.o \ + pthread_attr_getinheritsched.o \ + pthread_barrier_init.o \ + pthread_barrier_destroy.o \ + pthread_barrier_wait.o \ + pthread_barrierattr_init.o \ + pthread_barrierattr_destroy.o \ + pthread_barrierattr_setpshared.o \ + pthread_barrierattr_getpshared.o \ + pthread_setcancelstate.o \ + pthread_setcanceltype.o \ + pthread_testcancel.o \ + pthread_cancel.o \ + cleanup.o \ + pthread_condattr_destroy.o \ + pthread_condattr_getpshared.o \ + pthread_condattr_init.o \ + pthread_condattr_setpshared.o \ + pthread_cond_destroy.o \ + pthread_cond_init.o \ + pthread_cond_signal.o \ + pthread_cond_wait.o \ + create.o \ + dll.o \ + errno.o \ + pthread_exit.o \ + fork.o \ + global.o \ + pthread_mutex_init.o \ + pthread_mutex_destroy.o \ + pthread_mutexattr_init.o \ + pthread_mutexattr_destroy.o \ + pthread_mutexattr_getpshared.o \ + pthread_mutexattr_setpshared.o \ + pthread_mutexattr_settype.o \ + pthread_mutexattr_gettype.o \ + pthread_mutex_lock.o \ + pthread_mutex_timedlock.o \ + pthread_mutex_unlock.o \ + pthread_mutex_trylock.o \ + pthread_mutexattr_setkind_np.o \ + pthread_mutexattr_getkind_np.o \ + pthread_getw32threadhandle_np.o \ + pthread_delay_np.o \ + pthread_num_processors_np.o \ + pthread_win32_attach_detach_np.o \ + pthread_equal.o \ + pthread_getconcurrency.o \ + pthread_once.o \ + pthread_self.o \ + pthread_setconcurrency.o \ + pthread_rwlock_init.o \ + pthread_rwlock_destroy.o \ + pthread_rwlockattr_init.o \ + pthread_rwlockattr_destroy.o \ + pthread_rwlockattr_getpshared.o \ + pthread_rwlockattr_setpshared.o \ + pthread_rwlock_rdlock.o \ + pthread_rwlock_wrlock.o \ + pthread_rwlock_unlock.o \ + pthread_rwlock_tryrdlock.o \ + pthread_rwlock_trywrlock.o \ + pthread_setschedparam.o \ + pthread_getschedparam.o \ + pthread_timechange_handler_np.o \ + ptw32_is_attr.o \ + ptw32_cond_check_need_init.o \ + ptw32_MCS_lock.o \ + ptw32_mutex_check_need_init.o \ + ptw32_processInitialize.o \ + ptw32_processTerminate.o \ + ptw32_threadStart.o \ + ptw32_threadDestroy.o \ + ptw32_tkAssocCreate.o \ + ptw32_tkAssocDestroy.o \ + ptw32_callUserDestroyRoutines.o \ + ptw32_timespec.o \ + ptw32_throw.o \ + ptw32_InterlockedCompareExchange.o \ + ptw32_getprocessors.o \ + ptw32_calloc.o \ + ptw32_new.o \ + ptw32_reuse.o \ + ptw32_semwait.o \ + ptw32_relmillisecs.o \ + ptw32_rwlock_check_need_init.o \ + sched_get_priority_max.o \ + sched_get_priority_min.o \ + sched_setscheduler.o \ + sched_getscheduler.o \ + sched_yield.o \ + sem_init.o \ + sem_destroy.o \ + sem_trywait.o \ + sem_timedwait.o \ + sem_wait.o \ + sem_post.o \ + sem_post_multiple.o \ + sem_getvalue.o \ + sem_open.o \ + sem_close.o \ + sem_unlink.o \ + signal.o \ + pthread_kill.o \ + ptw32_spinlock_check_need_init.o \ + pthread_spin_init.o \ + pthread_spin_destroy.o \ + pthread_spin_lock.o \ + pthread_spin_unlock.o \ + pthread_spin_trylock.o \ + pthread_detach.o \ + pthread_join.o \ + pthread_key_create.o \ + pthread_key_delete.o \ + pthread_setspecific.o \ + pthread_getspecific.o \ + w32_CancelableWait.o \ + version.o + +INCL = \ + config.h \ + implement.h \ + semaphore.h \ + pthread.h \ + need_errno.h + +ATTR_SRCS = \ + pthread_attr_init.c \ + pthread_attr_destroy.c \ + pthread_attr_getdetachstate.c \ + pthread_attr_setdetachstate.c \ + pthread_attr_getstackaddr.c \ + pthread_attr_setstackaddr.c \ + pthread_attr_getstacksize.c \ + pthread_attr_setstacksize.c \ + pthread_attr_getscope.c \ + pthread_attr_setscope.c + +BARRIER_SRCS = \ + pthread_barrier_init.c \ + pthread_barrier_destroy.c \ + pthread_barrier_wait.c \ + pthread_barrierattr_init.c \ + pthread_barrierattr_destroy.c \ + pthread_barrierattr_setpshared.c \ + pthread_barrierattr_getpshared.c + +CANCEL_SRCS = \ + pthread_setcancelstate.c \ + pthread_setcanceltype.c \ + pthread_testcancel.c \ + pthread_cancel.c + +CONDVAR_SRCS = \ + ptw32_cond_check_need_init.c \ + pthread_condattr_destroy.c \ + pthread_condattr_getpshared.c \ + pthread_condattr_init.c \ + pthread_condattr_setpshared.c \ + pthread_cond_destroy.c \ + pthread_cond_init.c \ + pthread_cond_signal.c \ + pthread_cond_wait.c + +EXIT_SRCS = \ + pthread_exit.c + +MISC_SRCS = \ + pthread_equal.c \ + pthread_getconcurrency.c \ + pthread_kill.c \ + pthread_once.c \ + pthread_self.c \ + pthread_setconcurrency.c \ + ptw32_calloc.c \ + ptw32_MCS_lock.c \ + ptw32_new.c \ + ptw32_reuse.c \ + w32_CancelableWait.c + +MUTEX_SRCS = \ + ptw32_mutex_check_need_init.c \ + pthread_mutex_init.c \ + pthread_mutex_destroy.c \ + pthread_mutexattr_init.c \ + pthread_mutexattr_destroy.c \ + pthread_mutexattr_getpshared.c \ + pthread_mutexattr_setpshared.c \ + pthread_mutexattr_settype.c \ + pthread_mutexattr_gettype.c \ + pthread_mutex_lock.c \ + pthread_mutex_timedlock.c \ + pthread_mutex_unlock.c \ + pthread_mutex_trylock.c + +NONPORTABLE_SRCS = \ + pthread_mutexattr_setkind_np.c \ + pthread_mutexattr_getkind_np.c \ + pthread_getw32threadhandle_np.c \ + pthread_delay_np.c \ + pthread_num_processors_np.c \ + pthread_win32_attach_detach_np.c \ + pthread_timechange_handler_np.c + +PRIVATE_SRCS = \ + ptw32_is_attr.c \ + ptw32_processInitialize.c \ + ptw32_processTerminate.c \ + ptw32_threadStart.c \ + ptw32_threadDestroy.c \ + ptw32_tkAssocCreate.c \ + ptw32_tkAssocDestroy.c \ + ptw32_callUserDestroyRoutines.c \ + ptw32_semwait.c \ + ptw32_relmillisecs.c \ + ptw32_timespec.c \ + ptw32_throw.c \ + ptw32_InterlockedCompareExchange.c \ + ptw32_getprocessors.c + +RWLOCK_SRCS = \ + ptw32_rwlock_check_need_init.c \ + ptw32_rwlock_cancelwrwait.c \ + pthread_rwlock_init.c \ + pthread_rwlock_destroy.c \ + pthread_rwlockattr_init.c \ + pthread_rwlockattr_destroy.c \ + pthread_rwlockattr_getpshared.c \ + pthread_rwlockattr_setpshared.c \ + pthread_rwlock_rdlock.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_wrlock.c \ + pthread_rwlock_timedwrlock.c \ + pthread_rwlock_unlock.c \ + pthread_rwlock_tryrdlock.c \ + pthread_rwlock_trywrlock.c + +SCHED_SRCS = \ + pthread_attr_setschedpolicy.c \ + pthread_attr_getschedpolicy.c \ + pthread_attr_setschedparam.c \ + pthread_attr_getschedparam.c \ + pthread_attr_setinheritsched.c \ + pthread_attr_getinheritsched.c \ + pthread_setschedparam.c \ + pthread_getschedparam.c \ + sched_get_priority_max.c \ + sched_get_priority_min.c \ + sched_setscheduler.c \ + sched_getscheduler.c \ + sched_yield.c + +SEMAPHORE_SRCS = \ + sem_init.c \ + sem_destroy.c \ + sem_trywait.c \ + sem_timedwait.c \ + sem_wait.c \ + sem_post.c \ + sem_post_multiple.c \ + sem_getvalue.c \ + sem_open.c \ + sem_close.c \ + sem_unlink.c + +SPIN_SRCS = \ + ptw32_spinlock_check_need_init.c \ + pthread_spin_init.c \ + pthread_spin_destroy.c \ + pthread_spin_lock.c \ + pthread_spin_unlock.c \ + pthread_spin_trylock.c + +SYNC_SRCS = \ + pthread_detach.c \ + pthread_join.c + +TSD_SRCS = \ + pthread_key_create.c \ + pthread_key_delete.c \ + pthread_setspecific.c \ + pthread_getspecific.c + + +GCE_DLL = pthreadGCE$(DLL_VER).dll +GCED_DLL= pthreadGCE$(DLL_VERD).dll +GCE_LIB = libpthreadGCE$(DLL_VER).a +GCED_LIB= libpthreadGCE$(DLL_VERD).a +GCE_INLINED_STAMP = pthreadGCE$(DLL_VER).stamp +GCED_INLINED_STAMP = pthreadGCE$(DLL_VERD).stamp + +GC_DLL = pthreadGC$(DLL_VER).dll +GCD_DLL = pthreadGC$(DLL_VERD).dll +GC_LIB = libpthreadGC$(DLL_VER).a +GCD_LIB = libpthreadGC$(DLL_VERD).a +GC_INLINED_STAMP = pthreadGC$(DLL_VER).stamp +GCD_INLINED_STAMP = pthreadGC$(DLL_VERD).stamp +GC_STATIC_STAMP = libpthreadGC$(DLL_VER).stamp +GCD_STATIC_STAMP = libpthreadGC$(DLL_VERD).stamp + +PTHREAD_DEF = pthread.def + +help: + @ echo "Run one of the following command lines:" + @ echo "make clean GC (to build the GNU C dll with C cleanup code)" + @ echo "make clean GCE (to build the GNU C dll with C++ exception handling)" + @ echo "make clean GC-inlined (to build the GNU C inlined dll with C cleanup code)" + @ echo "make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling)" + @ echo "make clean GC-static (to build the GNU C inlined static lib with C cleanup code)" + @ echo "make clean GC-debug (to build the GNU C debug dll with C cleanup code)" + @ echo "make clean GCE-debug (to build the GNU C debug dll with C++ exception handling)" + @ echo "make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code)" + @ echo "make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling)" + @ echo "make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code)" + +all: + @ $(MAKE) clean GCE + @ $(MAKE) clean GC + +GC: + $(MAKE) CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" $(GC_DLL) + +GC-debug: + $(MAKE) CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_DLL) + +GCE: + $(MAKE) CC=$(CXX) CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" $(GCE_DLL) + +GCE-debug: + $(MAKE) CC=$(CXX) CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCED_DLL) + +GC-inlined: + $(MAKE) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_INLINED_STAMP) + +GC-inlined-debug: + $(MAKE) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_INLINED_STAMP) + +GCE-inlined: + $(MAKE) CC=$(CXX) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GCE_INLINED_STAMP) + +GCE-inlined-debug: + $(MAKE) CC=$(CXX) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCED_INLINED_STAMP) + +GC-static: + $(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_STATIC_STAMP) + +GC-static-debug: + $(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_STATIC_STAMP) + +tests: + @ cd tests + @ $(MAKE) auto + +%.pre: %.c + $(CC) -E -o $@ $(CFLAGS) $^ + +%.s: %.c + $(CC) -c $(CFLAGS) -DPTW32_BUILD_INLINED -Wa,-ahl $^ > $@ + +%.o: %.rc + $(RC) $(RCFLAGS) $(CLEANUP) -o $@ $< + +.SUFFIXES: .dll .rc .c .o + +.c.o:; $(CC) -c -o $@ $(CFLAGS) $(XC_FLAGS) $< + + +$(GC_DLL) $(GCD_DLL): $(DLL_OBJS) + $(CC) $(OPT) -shared -o $(GC_DLL) $(DLL_OBJS) $(LFLAGS) + $(DLLTOOL) -z pthread.def $(DLL_OBJS) + $(DLLTOOL) -k --dllname $@ --output-lib $(GC_LIB) --def $(PTHREAD_DEF) + +$(GCE_DLL): $(DLL_OBJS) + $(CC) $(OPT) -mthreads -shared -o $(GCE_DLL) $(DLL_OBJS) $(LFLAGS) + $(DLLTOOL) -z pthread.def $(DLL_OBJS) + $(DLLTOOL) -k --dllname $@ --output-lib $(GCE_LIB) --def $(PTHREAD_DEF) + +$(GC_INLINED_STAMP) $(GCD_INLINED_STAMP): $(DLL_INLINED_OBJS) + $(CC) $(OPT) $(XOPT) -shared -o $(GC_DLL) $(DLL_INLINED_OBJS) $(LFLAGS) + $(DLLTOOL) -z pthread.def $(DLL_INLINED_OBJS) + $(DLLTOOL) -k --dllname $(GC_DLL) --output-lib $(GC_LIB) --def $(PTHREAD_DEF) + echo touched > $(GC_INLINED_STAMP) + +$(GCE_INLINED_STAMP) $(GCED_INLINED_STAMP): $(DLL_INLINED_OBJS) + $(CC) $(OPT) $(XOPT) -mthreads -shared -o $(GCE_DLL) $(DLL_INLINED_OBJS) $(LFLAGS) + $(DLLTOOL) -z pthread.def $(DLL_INLINED_OBJS) + $(DLLTOOL) -k --dllname $(GCE_DLL) --output-lib $(GCE_LIB) --def $(PTHREAD_DEF) + echo touched > $(GCE_INLINED_STAMP) + +$(GC_STATIC_STAMP) $(GCD_STATIC_STAMP): $(DLL_INLINED_OBJS) + $(RM) $(GC_LIB) + $(AR) -rv $(GC_LIB) $(DLL_INLINED_OBJS) + $(RANLIB) $(GC_LIB) + echo touched > $(GC_STATIC_STAMP) + +clean: + -$(RM) *~ + -$(RM) *.i + -$(RM) *.o + -$(RM) *.obj + -$(RM) *.exe + -$(RM) $(PTHREAD_DEF) + +realclean: clean + -$(RM) $(GC_LIB) + -$(RM) $(GCE_LIB) + -$(RM) $(GC_DLL) + -$(RM) $(GCE_DLL) + -$(RM) $(GC_INLINED_STAMP) + -$(RM) $(GCE_INLINED_STAMP) + -$(RM) $(GC_STATIC_STAMP) + -$(RM) $(GCD_LIB) + -$(RM) $(GCED_LIB) + -$(RM) $(GCD_DLL) + -$(RM) $(GCED_DLL) + -$(RM) $(GCD_INLINED_STAMP) + -$(RM) $(GCED_INLINED_STAMP) + -$(RM) $(GCD_STATIC_STAMP) + +attr.o: attr.c $(ATTR_SRCS) $(INCL) +barrier.o: barrier.c $(BARRIER_SRCS) $(INCL) +cancel.o: cancel.c $(CANCEL_SRCS) $(INCL) +condvar.o: condvar.c $(CONDVAR_SRCS) $(INCL) +exit.o: exit.c $(EXIT_SRCS) $(INCL) +misc.o: misc.c $(MISC_SRCS) $(INCL) +mutex.o: mutex.c $(MUTEX_SRCS) $(INCL) +nonportable.o: nonportable.c $(NONPORTABLE_SRCS) $(INCL) +private.o: private.c $(PRIVATE_SRCS) $(INCL) +rwlock.o: rwlock.c $(RWLOCK_SRCS) $(INCL) +sched.o: sched.c $(SCHED_SRCS) $(INCL) +semaphore.o: semaphore.c $(SEMAPHORE_SRCS) $(INCL) +spin.o: spin.c $(SPIN_SRCS) $(INCL) +sync.o: sync.c $(SYNC_SRCS) $(INCL) +tsd.o: tsd.c $(TSD_SRCS) $(INCL) +version.o: version.rc $(INCL) diff --git a/liblo/pthreads.2/MAINTAINERS b/liblo/pthreads.2/MAINTAINERS new file mode 100644 index 0000000..5b04e43 --- /dev/null +++ b/liblo/pthreads.2/MAINTAINERS @@ -0,0 +1,4 @@ +CVS Repository maintainers + +Ross Johnson rpj@ise.canberra.edu.au +Ben Elliston bje@cygnus.com diff --git a/liblo/pthreads.2/Makefile b/liblo/pthreads.2/Makefile new file mode 100644 index 0000000..f65448b --- /dev/null +++ b/liblo/pthreads.2/Makefile @@ -0,0 +1,504 @@ +# This makefile is compatible with MS nmake and can be used as a +# replacement for buildlib.bat. I've changed the target from an ordinary dll +# (/LD) to a debugging dll (/LDd). +# +# The variables $DLLDEST and $LIBDEST hold the destination directories for the +# dll and the lib, respectively. Probably all that needs to change is $DEVROOT. + + +# DLL_VER: +# See pthread.h and README - This number is computed as 'current - age' +DLL_VER = 2 +DLL_VERD= $(DLL_VER)d + +DEVROOT = C:\pthreads + +DLLDEST = $(DEVROOT)\DLL +LIBDEST = $(DEVROOT)\LIB +HDRDEST = $(DEVROOT)\INCLUDE + +DLLS = pthreadVCE$(DLL_VER).dll pthreadVSE$(DLL_VER).dll pthreadVC$(DLL_VER).dll \ + pthreadVCE$(DLL_VERD).dll pthreadVSE$(DLL_VERD).dll pthreadVC$(DLL_VERD).dll +INLINED_STAMPS = pthreadVCE$(DLL_VER).stamp pthreadVSE$(DLL_VER).stamp pthreadVC$(DLL_VER).stamp \ + pthreadVCE$(DLL_VERD).stamp pthreadVSE$(DLL_VERD).stamp pthreadVC$(DLL_VERD).stamp +STATIC_STAMPS = pthreadVCE$(DLL_VER).static pthreadVSE$(DLL_VER).static pthreadVC$(DLL_VER).static \ + pthreadVCE$(DLL_VERD).static pthreadVSE$(DLL_VERD).static pthreadVC$(DLL_VERD).static + +OPTIM = /O2 /Ob2 +OPTIMD = + +CFLAGS = /W3 /MD /nologo /Yd /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H +CFLAGSD = /Zi $(CFLAGS) + + +# Default cleanup style +CLEANUP = __CLEANUP_C + +# C++ Exceptions +VCEFLAGS = /GX /TP $(CFLAGS) +VCEFLAGSD = /GX /TP $(CFLAGSD) +#Structured Exceptions +VSEFLAGS = $(CFLAGS) +VSEFLAGSD = $(CFLAGSD) +#C cleanup code +VCFLAGS = $(CFLAGS) +VCFLAGSD= $(CFLAGSD) + +DLL_INLINED_OBJS = \ + pthread.obj \ + version.res + +# Aggregate modules for inlinability +DLL_OBJS = \ + attr.obj \ + barrier.obj \ + cancel.obj \ + cleanup.obj \ + condvar.obj \ + create.obj \ + dll.obj \ + errno.obj \ + exit.obj \ + fork.obj \ + global.obj \ + misc.obj \ + mutex.obj \ + nonportable.obj \ + private.obj \ + rwlock.obj \ + sched.obj \ + semaphore.obj \ + signal.obj \ + spin.obj \ + sync.obj \ + tsd.obj \ + version.res + +# Separate modules for minimising the size of statically linked images +SMALL_STATIC_OBJS = \ + pthread_attr_init.obj \ + pthread_attr_destroy.obj \ + pthread_attr_getdetachstate.obj \ + pthread_attr_setdetachstate.obj \ + pthread_attr_getstackaddr.obj \ + pthread_attr_setstackaddr.obj \ + pthread_attr_getstacksize.obj \ + pthread_attr_setstacksize.obj \ + pthread_attr_getscope.obj \ + pthread_attr_setscope.obj \ + pthread_attr_setschedpolicy.obj \ + pthread_attr_getschedpolicy.obj \ + pthread_attr_setschedparam.obj \ + pthread_attr_getschedparam.obj \ + pthread_attr_setinheritsched.obj \ + pthread_attr_getinheritsched.obj \ + pthread_barrier_init.obj \ + pthread_barrier_destroy.obj \ + pthread_barrier_wait.obj \ + pthread_barrierattr_init.obj \ + pthread_barrierattr_destroy.obj \ + pthread_barrierattr_setpshared.obj \ + pthread_barrierattr_getpshared.obj \ + pthread_setcancelstate.obj \ + pthread_setcanceltype.obj \ + pthread_testcancel.obj \ + pthread_cancel.obj \ + cleanup.obj \ + pthread_condattr_destroy.obj \ + pthread_condattr_getpshared.obj \ + pthread_condattr_init.obj \ + pthread_condattr_setpshared.obj \ + pthread_cond_destroy.obj \ + pthread_cond_init.obj \ + pthread_cond_signal.obj \ + pthread_cond_wait.obj \ + create.obj \ + dll.obj \ + errno.obj \ + pthread_exit.obj \ + fork.obj \ + global.obj \ + pthread_mutex_init.obj \ + pthread_mutex_destroy.obj \ + pthread_mutexattr_init.obj \ + pthread_mutexattr_destroy.obj \ + pthread_mutexattr_getpshared.obj \ + pthread_mutexattr_setpshared.obj \ + pthread_mutexattr_settype.obj \ + pthread_mutexattr_gettype.obj \ + pthread_mutex_lock.obj \ + pthread_mutex_timedlock.obj \ + pthread_mutex_unlock.obj \ + pthread_mutex_trylock.obj \ + pthread_mutexattr_setkind_np.obj \ + pthread_mutexattr_getkind_np.obj \ + pthread_getw32threadhandle_np.obj \ + pthread_delay_np.obj \ + pthread_num_processors_np.obj \ + pthread_win32_attach_detach_np.obj \ + pthread_equal.obj \ + pthread_getconcurrency.obj \ + pthread_once.obj \ + pthread_self.obj \ + pthread_setconcurrency.obj \ + pthread_rwlock_init.obj \ + pthread_rwlock_destroy.obj \ + pthread_rwlockattr_init.obj \ + pthread_rwlockattr_destroy.obj \ + pthread_rwlockattr_getpshared.obj \ + pthread_rwlockattr_setpshared.obj \ + pthread_rwlock_rdlock.obj \ + pthread_rwlock_wrlock.obj \ + pthread_rwlock_unlock.obj \ + pthread_rwlock_tryrdlock.obj \ + pthread_rwlock_trywrlock.obj \ + pthread_setschedparam.obj \ + pthread_getschedparam.obj \ + pthread_timechange_handler_np.obj \ + ptw32_is_attr.obj \ + ptw32_processInitialize.obj \ + ptw32_processTerminate.obj \ + ptw32_threadStart.obj \ + ptw32_threadDestroy.obj \ + ptw32_tkAssocCreate.obj \ + ptw32_tkAssocDestroy.obj \ + ptw32_callUserDestroyRoutines.obj \ + ptw32_timespec.obj \ + ptw32_throw.obj \ + ptw32_InterlockedCompareExchange.obj \ + ptw32_getprocessors.obj \ + ptw32_calloc.obj \ + ptw32_new.obj \ + ptw32_reuse.obj \ + ptw32_rwlock_check_need_init.obj \ + ptw32_cond_check_need_init.obj \ + ptw32_mutex_check_need_init.obj \ + ptw32_semwait.obj \ + ptw32_relmillisecs.obj \ + ptw32_MCS_lock.obj \ + sched_get_priority_max.obj \ + sched_get_priority_min.obj \ + sched_setscheduler.obj \ + sched_getscheduler.obj \ + sched_yield.obj \ + sem_init.obj \ + sem_destroy.obj \ + sem_trywait.obj \ + sem_timedwait.obj \ + sem_wait.obj \ + sem_post.obj \ + sem_post_multiple.obj \ + sem_getvalue.obj \ + sem_open.obj \ + sem_close.obj \ + sem_unlink.obj \ + signal.obj \ + pthread_kill.obj \ + ptw32_spinlock_check_need_init.obj \ + pthread_spin_init.obj \ + pthread_spin_destroy.obj \ + pthread_spin_lock.obj \ + pthread_spin_unlock.obj \ + pthread_spin_trylock.obj \ + pthread_detach.obj \ + pthread_join.obj \ + pthread_key_create.obj \ + pthread_key_delete.obj \ + pthread_setspecific.obj \ + pthread_getspecific.obj \ + w32_CancelableWait.obj \ + version.res + +INCL = config.h implement.h semaphore.h pthread.h need_errno.h + +ATTR_SRCS = \ + pthread_attr_init.c \ + pthread_attr_destroy.c \ + pthread_attr_getdetachstate.c \ + pthread_attr_setdetachstate.c \ + pthread_attr_getstackaddr.c \ + pthread_attr_setstackaddr.c \ + pthread_attr_getstacksize.c \ + pthread_attr_setstacksize.c \ + pthread_attr_getscope.c \ + pthread_attr_setscope.c + +BARRIER_SRCS = \ + pthread_barrier_init.c \ + pthread_barrier_destroy.c \ + pthread_barrier_wait.c \ + pthread_barrierattr_init.c \ + pthread_barrierattr_destroy.c \ + pthread_barrierattr_setpshared.c \ + pthread_barrierattr_getpshared.c + +CANCEL_SRCS = \ + pthread_setcancelstate.c \ + pthread_setcanceltype.c \ + pthread_testcancel.c \ + pthread_cancel.c + +CONDVAR_SRCS = \ + ptw32_cond_check_need_init.c \ + pthread_condattr_destroy.c \ + pthread_condattr_getpshared.c \ + pthread_condattr_init.c \ + pthread_condattr_setpshared.c \ + pthread_cond_destroy.c \ + pthread_cond_init.c \ + pthread_cond_signal.c \ + pthread_cond_wait.c + +EXIT_SRCS = \ + pthread_exit.c + +MISC_SRCS = \ + pthread_equal.c \ + pthread_getconcurrency.c \ + pthread_kill.c \ + pthread_once.c \ + pthread_self.c \ + pthread_setconcurrency.c \ + ptw32_calloc.c \ + ptw32_MCS_lock.c \ + ptw32_new.c \ + ptw32_reuse.c \ + ptw32_relmillisecs.c \ + w32_CancelableWait.c + +MUTEX_SRCS = \ + ptw32_mutex_check_need_init.c \ + pthread_mutex_init.c \ + pthread_mutex_destroy.c \ + pthread_mutexattr_init.c \ + pthread_mutexattr_destroy.c \ + pthread_mutexattr_getpshared.c \ + pthread_mutexattr_setpshared.c \ + pthread_mutexattr_settype.c \ + pthread_mutexattr_gettype.c \ + pthread_mutex_lock.c \ + pthread_mutex_timedlock.c \ + pthread_mutex_unlock.c \ + pthread_mutex_trylock.c + +NONPORTABLE_SRCS = \ + pthread_mutexattr_setkind_np.c \ + pthread_mutexattr_getkind_np.c \ + pthread_getw32threadhandle_np.c \ + pthread_delay_np.c \ + pthread_num_processors_np.c \ + pthread_win32_attach_detach_np.c \ + pthread_timechange_handler_np.c + +PRIVATE_SRCS = \ + ptw32_is_attr.c \ + ptw32_processInitialize.c \ + ptw32_processTerminate.c \ + ptw32_threadStart.c \ + ptw32_threadDestroy.c \ + ptw32_tkAssocCreate.c \ + ptw32_tkAssocDestroy.c \ + ptw32_callUserDestroyRoutines.c \ + ptw32_semwait.c \ + ptw32_timespec.c \ + ptw32_throw.c \ + ptw32_InterlockedCompareExchange.c \ + ptw32_getprocessors.c + +RWLOCK_SRCS = \ + ptw32_rwlock_check_need_init.c \ + ptw32_rwlock_cancelwrwait.c \ + pthread_rwlock_init.c \ + pthread_rwlock_destroy.c \ + pthread_rwlockattr_init.c \ + pthread_rwlockattr_destroy.c \ + pthread_rwlockattr_getpshared.c \ + pthread_rwlockattr_setpshared.c \ + pthread_rwlock_rdlock.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_wrlock.c \ + pthread_rwlock_timedwrlock.c \ + pthread_rwlock_unlock.c \ + pthread_rwlock_tryrdlock.c \ + pthread_rwlock_trywrlock.c + +SCHED_SRCS = \ + pthread_attr_setschedpolicy.c \ + pthread_attr_getschedpolicy.c \ + pthread_attr_setschedparam.c \ + pthread_attr_getschedparam.c \ + pthread_attr_setinheritsched.c \ + pthread_attr_getinheritsched.c \ + pthread_setschedparam.c \ + pthread_getschedparam.c \ + sched_get_priority_max.c \ + sched_get_priority_min.c \ + sched_setscheduler.c \ + sched_getscheduler.c \ + sched_yield.c + +SEMAPHORE_SRCS = \ + sem_init.c \ + sem_destroy.c \ + sem_trywait.c \ + sem_timedwait.c \ + sem_wait.c \ + sem_post.c \ + sem_post_multiple.c \ + sem_getvalue.c \ + sem_open.c \ + sem_close.c \ + sem_unlink.c + +SPIN_SRCS = \ + ptw32_spinlock_check_need_init.c \ + pthread_spin_init.c \ + pthread_spin_destroy.c \ + pthread_spin_lock.c \ + pthread_spin_unlock.c \ + pthread_spin_trylock.c + +SYNC_SRCS = \ + pthread_detach.c \ + pthread_join.c + +TSD_SRCS = \ + pthread_key_create.c \ + pthread_key_delete.c \ + pthread_setspecific.c \ + pthread_getspecific.c + + +help: + @ echo Run one of the following command lines: + @ echo nmake clean VCE (to build the MSVC dll with C++ exception handling) + @ echo nmake clean VSE (to build the MSVC dll with structured exception handling) + @ echo nmake clean VC (to build the MSVC dll with C cleanup code) + @ echo nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling) + @ echo nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling) + @ echo nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code) + @ echo nmake clean VC-static (to build the MSVC static lib with C cleanup code) + @ echo nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling) + @ echo nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling) + @ echo nmake clean VC-debug (to build the debug MSVC dll with C cleanup code) + @ echo nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling) + @ echo nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling) + @ echo nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code) + @ echo nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code) + +all: + @ nmake clean VCE-inlined + @ nmake clean VSE-inlined + @ nmake clean VC-inlined + @ nmake clean VCE-inlined-debug + @ nmake clean VSE-inlined-debug + @ nmake clean VC-inlined-debug + +VCE: + @ nmake /nologo EHFLAGS="$(OPTIM) $(VCEFLAGS)" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VER).dll + +VCE-debug: + @ nmake /nologo EHFLAGS="$(OPTIMD) $(VCEFLAGSD)" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VERD).dll + +VSE: + @ nmake /nologo EHFLAGS="$(OPTIM) $(VSEFLAGS)" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VER).dll + +VSE-debug: + @ nmake /nologo EHFLAGS="$(OPTIMD) $(VSEFLAGSD)" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VERD).dll + +VC: + @ nmake /nologo EHFLAGS="$(OPTIM) $(VCFLAGS)" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).dll + +VC-debug: + @ nmake /nologo EHFLAGS="$(OPTIMD) $(VCFLAGSD)" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).dll + +# +# The so-called inlined DLL is just a single translation unit with +# inlining optimisation turned on. +# +VCE-inlined: + @ nmake /nologo EHFLAGS="$(OPTIM) $(VCEFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VER).stamp + +VCE-inlined-debug: + @ nmake /nologo EHFLAGS="$(OPTIMD) $(VCEFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VERD).stamp + +VSE-inlined: + @ nmake /nologo EHFLAGS="$(OPTIM) $(VSEFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VER).stamp + +VSE-inlined-debug: + @ nmake /nologo EHFLAGS="$(OPTIMD) $(VSEFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VERD).stamp + +VC-inlined: + @ nmake /nologo EHFLAGS="$(OPTIM) $(VCFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).stamp + +VC-inlined-debug: + nmake /nologo EHFLAGS="$(OPTIMD) $(VCFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).stamp + +VC-static: + @ nmake /nologo EHFLAGS="$(OPTIM) $(VCFLAGS) /DPTW32_BUILD_INLINED /DPTW32_STATIC_LIB" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).static + +VC-static-debug: + @ nmake /nologo EHFLAGS="$(OPTIMD) $(VCFLAGSD) /DPTW32_BUILD_INLINED /DPTW32_STATIC_LIB" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).static + +realclean: clean + if exist pthread*.dll del pthread*.dll + if exist pthread*.lib del pthread*.lib + if exist *.stamp del *.stamp + +clean: + if exist *.obj del *.obj + if exist *.ilk del *.ilk + if exist *.pdb del *.pdb + if exist *.exp del *.exp + if exist *.map del *.map + if exist *.o del *.o + if exist *.i del *.i + if exist *.res del *.res + + +install: $(DLLS) + copy pthread*.dll $(DLLDEST) + copy pthread*.lib $(LIBDEST) + copy pthread.h $(HDRDEST) + copy sched.h $(HDRDEST) + copy semaphore.h $(HDRDEST) + +$(DLLS): $(DLL_OBJS) + cl /LDd /Zi /nologo $(DLL_OBJS) \ + /link /nodefaultlib:libcmt /implib:$*.lib \ + msvcrt.lib wsock32.lib /out:$@ + +$(INLINED_STAMPS): $(DLL_INLINED_OBJS) + cl /LDd /Zi /nologo $(DLL_INLINED_OBJS) \ + /link /nodefaultlib:libcmt /implib:$*.lib \ + msvcrt.lib wsock32.lib /out:$*.dll + +$(STATIC_STAMPS): $(DLL_INLINED_OBJS) + if exist $*.lib del $*.lib + lib $(DLL_INLINED_OBJS) /out:$*.lib + +.c.obj: + cl $(EHFLAGS) /D$(CLEANUP) -c $< + +.rc.res: + rc /dPTW32_RC_MSC /d$(CLEANUP) $< + +.c.i: + cl /P /O2 /Ob1 $(VCFLAGS) $< + +attr.obj: attr.c $(ATTR_SRCS) $(INCL) +barrier.obj: barrier.c $(BARRIER_SRCS) $(INCL) +cancel.obj: cancel.c $(CANCEL_SRCS) $(INCL) +condvar.obj: condvar.c $(CONDVAR_SRCS) $(INCL) +exit.obj: exit.c $(EXIT_SRCS) $(INCL) +misc.obj: misc.c $(MISC_SRCS) $(INCL) +mutex.obj: mutex.c $(MUTEX_SRCS) $(INCL) +nonportable.obj: nonportable.c $(NONPORTABLE_SRCS) $(INCL) +private.obj: private.c $(PRIVATE_SRCS) $(INCL) +rwlock.obj: rwlock.c $(RWLOCK_SRCS) $(INCL) +sched.obj: sched.c $(SCHED_SRCS) $(INCL) +semaphore.obj: semaphore.c $(SEMAPHORE_SRCS) $(INCL) +spin.obj: spin.c $(SPIN_SRCS) $(INCL) +sync.obj: sync.c $(SYNC_SRCS) $(INCL) +tsd.obj: tsd.c $(TSD_SRCS) $(INCL) +version.res: version.rc $(INCL) diff --git a/liblo/pthreads.2/NEWS b/liblo/pthreads.2/NEWS new file mode 100644 index 0000000..4cd25f7 --- /dev/null +++ b/liblo/pthreads.2/NEWS @@ -0,0 +1,1110 @@ +RELEASE 2.8.0 +------------- +(2006-12-22) + +General +------- +New bug fixes in this release since 2.7.0 have not been applied to the +version 1.x.x series. It is probably time to drop version 1. + +Testing and verification +------------------------ +This release has not yet been tested on SMP architechtures. All tests pass +on a uni-processor system. + +Bug fixes +--------- +Sem_destroy could return EBUSY even though no threads were waiting on the +semaphore. Other races around invalidating semaphore structs (internally) +have been removed as well. + +New tests +--------- +semaphore5.c - tests the bug fix referred to above. + + +RELEASE 2.7.0 +------------- +(2005-06-04) + +General +------- +All new features in this release have been back-ported in release 1.11.0, +including the incorporation of MCS locks in pthread_once, however, versions +1 and 2 remain incompatible even though they are now identical in +performance and functionality. + +Testing and verification +------------------------ +This release has been tested (passed the test suite) on both uni-processor +and multi-processor systems. +- Tim Theisen + +Bug fixes +--------- +Pthread_once has been re-implemented to remove priority boosting and other +complexity to improve robustness. Races for Win32 handles that are not +recycle-unique have been removed. The general form of pthread_once is now +the same as that suggested earlier by Alexander Terekhov, but instead of the +'named mutex', a queue-based lock has been implemented which has the required +properties of dynamic self initialisation and destruction. This lock is also +efficient. The ABI is unaffected in as much as the size of pthread_once_t has +not changed and PTHREAD_ONCE_INIT has not changed, however, applications that +peek inside pthread_once_t, which is supposed to be opaque, will break. +- Vladimir Kliatchko + +New features +------------ +* Support for Mingw cross development tools added to GNUmakefile. +Mingw cross tools allow building the libraries on Linux. +- Mikael Magnusson + + +RELEASE 2.6.0 +------------- +(2005-05-19) + +General +------- +All of the bug fixes and new features in this release have been +back-ported in release 1.10.0. + +Testing and verification +------------------------ +This release has been tested (passed the test suite) on both uni-processor +and multi-processor systems. Thanks to Tim Theisen at TomoTherapy for +exhaustively running the MP tests and for providing crutial observations +and data when faults are detected. + +Bugs fixed +---------- + +* pthread_detach() now reclaims remaining thread resources if called after +the target thread has terminated. Previously, this routine did nothing in +this case. + +New tests +--------- + +* detach1.c - tests that pthread_detach properly invalidates the target +thread, which indicates that the thread resources have been reclaimed. + + +RELEASE 2.5.0 +------------- +(2005-05-09) + +General +------- + +The package now includes a reference documentation set consisting of +HTML formatted Unix-style manual pages that have been edited for +consistency with Pthreads-w32. The set can also be read online at: +http://sources.redhat.com/pthreads-win32/manual/index.html + +Thanks again to Tim Theisen for running the test suite pre-release +on an MP system. + +All of the bug fixes and new features in this release have been +back-ported in release 1.9.0. + +Bugs fixed +---------- + +* Thread Specific Data (TSD) key management has been ammended to +eliminate a source of (what was effectively) resource leakage (a HANDLE +plus memory for each key destruct routine/thread association). This was +not a true leak because these resources were eventually reclaimed when +pthread_key_delete was run AND each thread referencing the key had exited. +The problem was that these two conditions are often not met until very +late, and often not until the process is about to exit. + +The ammended implementation avoids the need for the problematic HANDLE +and reclaims the memory as soon as either the key is deleted OR the +thread exits, whichever is first. + +Thanks to Richard Hughes at Aculab for identifying and locating the leak. + +* TSD key destructors are now processed up to PTHREAD_DESTRUCTOR_ITERATIONS +times instead of just once. PTHREAD_DESTRUCTOR_ITERATIONS has been +defined in pthread.h for some time but not used. + +* Fix a semaphore accounting race between sem_post/sem_post_multiple +and sem_wait cancellation. This is the same issue as with +sem_timedwait that was fixed in the last release. + +* sem_init, sem_post, and sem_post_multiple now check that the +semaphore count never exceeds _POSIX_SEM_VALUE_MAX. + +* Although sigwait() is nothing more than a no-op, it should at least +be a cancellation point to be consistent with the standard. + +New tests +--------- + +* stress1.c - attempts to expose problems in condition variable +and semaphore timed wait logic. This test was inspired by Stephan +Mueller's sample test code used to identify the sem_timedwait bug +from the last release. It's not a part of the regular test suite +because it can take awhile to run. To run it: +nmake clean VC-stress + +* tsd2.c - tests that key destructors are re-run if the tsd key value is +not NULL after the destructor routine has run. Also tests that +pthread_setspecific() and pthread_getspecific() are callable from +destructors. + + +RELEASE 2.4.0 +------------- +(2005-04-26) + +General +------- + +There is now no plan to release a version 3.0.0 to fix problems in +pthread_once(). Other possible implementations of pthread_once +will still be investigated for a possible future release in an attempt +to reduce the current implementation's complexity. + +All of the bug fixes and new features in this release have been +back-ported for release 1.8.0. + +Bugs fixed +---------- + +* Fixed pthread_once race (failures on an MP system). Thanks to +Tim Theisen for running exhaustive pre-release testing on his MP system +using a range of compilers: + VC++ 6 + VC++ 7.1 + Intel C++ version 8.0 +All tests passed. +Some minor speed improvements were also done. + +* Fix integer overrun error in pthread_mutex_timedlock() - missed when +sem_timedwait() was fixed in release 2.2.0. This routine no longer returns +ENOTSUP when NEED_SEM is defined - it is supported (NEED_SEM is only +required for WinCE versions prior to 3.0). + +* Fix timeout bug in sem_timedwait(). +- Thanks to Stephan Mueller for reporting, providing diagnostic output +and test code. + +* Fix several problems in the NEED_SEM conditionally included code. +NEED_SEM included code is provided for systems that don't implement W32 +semaphores, such as WinCE prior to version 3.0. An alternate implementation +of POSIX semaphores is built using W32 events for these systems when +NEED_SEM is defined. This code has been completely rewritten in this +release to reuse most of the default POSIX semaphore code, and particularly, +to implement all of the sem_* routines supported by pthreads-win32. Tim +Theisen also run the test suite over the NEED_SEM code on his MP system. All +tests passed. + +* The library now builds without errors for the Borland Builder 5.5 compiler. + +New features +------------ + +* pthread_mutex_timedlock() and all sem_* routines provided by +pthreads-win32 are now implemented for WinCE versions prior to 3.0. Those +versions did not implement W32 semaphores. Define NEED_SEM in config.h when +building the library for these systems. + +Known issues in this release +---------------------------- + +* pthread_once is too complicated - but it works as far as testing can +determine.. + +* The Borland version of the dll fails some of the tests with a memory read +exception. The cause is not yet known but a compiler bug has not been ruled +out. + + +RELEASE 2.3.0 +------------- +(2005-04-12) + +General +------- + +Release 1.7.0 is a backport of features and bug fixes new in +this release. See earlier notes under Release 2.0.0/General. + +Bugs fixed +---------- + +* Fixed pthread_once potential for post once_routine cancellation +hanging due to starvation. See comments in pthread_once.c. +Momentary priority boosting is used to ensure that, after a +once_routine is cancelled, the thread that will run the +once_routine is not starved by higher priority waiting threads at +critical times. Priority boosting occurs only AFTER a once_routine +cancellation, and is applied only to that once_control. The +once_routine is run at the thread's normal base priority. + +New tests +--------- + +* once4.c: Aggressively tests pthread_once() under realtime +conditions using threads with varying priorities. Windows' +random priority boosting does not occur for threads with realtime +priority levels. + + +RELEASE 2.2.0 +------------- +(2005-04-04) + +General +------- + +* Added makefile targets to build static link versions of the library. +Both MinGW and MSVC. Please note that this does not imply any change +to the LGPL licensing, which still imposes psecific conditions on +distributing software that has been statically linked with this library. + +* There is a known bug in pthread_once(). Cancellation of the init_routine +exposes a potential starvation (i.e. deadlock) problem if a waiting thread +has a higher priority than the initting thread. This problem will be fixed +in version 3.0.0 of the library. + +Bugs fixed +---------- + +* Fix integer overrun error in sem_timedwait(). +Kevin Lussier + +* Fix preprocessor directives for static linking. +Dimitar Panayotov + + +RELEASE 2.1.0 +------------- +(2005-03-16) + +Bugs fixed +---------- + +* Reverse change to pthread_setcancelstate() in 2.0.0. + + +RELEASE 2.0.0 +------------- +(2005-03-16) + +General +------- + +This release represents an ABI change and the DLL version naming has +incremented from 1 to 2, e.g. pthreadVC2.dll. + +Version 1.4.0 back-ports the new functionality included in this +release. Please distribute DLLs built from that version with updates +to applications built on pthreads-win32 version 1.x.x. + +The package naming has changed, replacing the snapshot date with +the version number + descriptive information. E.g. this +release is "pthreads-w32-2-0-0-release". + +Bugs fixed +---------- + +* pthread_setcancelstate() no longer checks for a pending +async cancel event if the library is using alertable async +cancel. See the README file (Prerequisites section) for info +on adding alertable async cancelation. + +New features +------------ + +* pthread_once() now supports init_routine cancellability. + +New tests +--------- + +* Agressively test pthread_once() init_routine cancellability. + + +SNAPSHOT 2005-03-08 +------------------- +Version 1.3.0 + +Bug reports (fixed) +------------------- + +* Implicitly created threads leave Win32 handles behind after exiting. +- Dmitrii Semii + +* pthread_once() starvation problem. +- Gottlob Frege + +New tests +--------- + +* More intense testing of pthread_once(). + + +SNAPSHOT 2005-01-25 +------------------- +Version 1.2.0 + +Bug fixes +--------- + +* Attempted acquisition of a recursive mutex could cause waiting threads +to not be woken when the mutex was released. +- Ralf Kubis + +* Various package omissions have been fixed. + + +SNAPSHOT 2005-01-03 +------------------- +Version 1.1.0 + +Bug fixes +--------- + +* Unlocking recursive or errorcheck mutexes would sometimes +unexpectedly return an EPERM error (bug introduced in +snapshot-2004-11-03). +- Konstantin Voronkov + + +SNAPSHOT 2004-11-22 +------------------- +Version 1.0.0 + +This snapshot primarily fixes the condvar bug introduced in +snapshot-2004-11-03. DLL versioning has also been included to allow +applications to runtime check the Microsoft compatible DLL version +information, and to extend the DLL naming system for ABI and major +(non-backward compatible) API changes. See the README file for details. + +Bug fixes +--------- + +* Condition variables no longer deadlock (bug introduced in +snapshot-2004-11-03). +- Alexander Kotliarov and Nicolas at saintmac + +* DLL naming extended to avoid 'DLL hell' in the future, and to +accommodate the ABI change introduced in snapshot-2004-11-03. Snapshot +2004-11-03 will be removed from FTP sites. + +New features +------------ + +* A Microsoft-style version resource has been added to the DLL for +applications that wish to check DLL compatibility at runtime. + +* Pthreads-win32 DLL naming has been extended to allow incompatible DLL +versions to co-exist in the same filesystem. See the README file for details, +but briefly: while the version information inside the DLL will change with +each release from now on, the DLL version names will only change if the new +DLL is not backward compatible with older applications. + +The versioning scheme has been borrowed from GNU Libtool, and the DLL +naming scheme is from Cygwin. Provided the Libtool-style numbering rules are +honoured, the Cygwin DLL naming scheme automatcally ensures that DLL name +changes are minimal and that applications will not load an incompatible +pthreads-win32 DLL. + +Those who use the pre-built DLLs will find that the DLL/LIB names have a new +suffix (1) in this snapshot. E.g. pthreadVC1.dll etc. + +* The POSIX thread ID reuse uniqueness feature introduced in the last snapshot +has been kept as default, but the behaviour can now be controlled when the DLL +is built to effectively switch it off. This makes the library much more +sensitive to applications that assume that POSIX thread IDs are unique, i.e. +are not strictly compliant with POSIX. See the PTW32_THREAD_ID_REUSE_INCREMENT +macro comments in config.h for details. + +Other changes +------------- +Certain POSIX macros have changed. + +These changes are intended to conform to the Single Unix Specification version 3, +which states that, if set to 0 (zero) or not defined, then applications may use +sysconf() to determine their values at runtime. Pthreads-win32 does not +implement sysconf(). + +The following macros are no longer undefined, but defined and set to -1 +(not implemented): + + _POSIX_THREAD_ATTR_STACKADDR + _POSIX_THREAD_PRIO_INHERIT + _POSIX_THREAD_PRIO_PROTECT + _POSIX_THREAD_PROCESS_SHARED + +The following macros are defined and set to 200112L (implemented): + + _POSIX_THREADS + _POSIX_THREAD_SAFE_FUNCTIONS + _POSIX_THREAD_ATTR_STACKSIZE + _POSIX_THREAD_PRIORITY_SCHEDULING + _POSIX_SEMAPHORES + _POSIX_READER_WRITER_LOCKS + _POSIX_SPIN_LOCKS + _POSIX_BARRIERS + +The following macros are defined and set to appropriate values: + + _POSIX_THREAD_THREADS_MAX + _POSIX_SEM_VALUE_MAX + _POSIX_SEM_NSEMS_MAX + PTHREAD_DESTRUCTOR_ITERATIONS + PTHREAD_KEYS_MAX + PTHREAD_STACK_MIN + PTHREAD_THREADS_MAX + + +SNAPSHOT 2004-11-03 +------------------- + +DLLs produced from this snapshot cannot be used with older applications without +recompiling the application, due to a change to pthread_t to provide unique POSIX +thread IDs. + +Although this snapshot passes the extended test suite, many of the changes are +fairly major, and some applications may show different behaviour than previously, +so adopt with care. Hopefully, any changed behaviour will be due to the library +being better at it's job, not worse. + +Bug fixes +--------- + +* pthread_create() no longer accepts NULL as the thread reference arg. +A segfault (memory access fault) will result, and no thread will be +created. + +* pthread_barrier_wait() no longer acts as a cancelation point. + +* Fix potential race condition in pthread_once() +- Tristan Savatier + +* Changes to pthread_cond_destroy() exposed some coding weaknesses in several +test suite mini-apps because pthread_cond_destroy() now returns EBUSY if the CV +is still in use. + +New features +------------ + +* Added for compatibility: +PTHREAD_RECURSIVE_MUTEX_INITIALIZER, +PTHREAD_ERRORCHECK_MUTEX_INITIALIZER, +PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, +PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP + +* Initial support for Digital Mars compiler +- Anuj Goyal + +* Faster Mutexes. These have been been rewritten following a model provided by +Alexander Terekhov that reduces kernel space checks, and eliminates some additional +critical sections used to manage a race between timedlock expiration and unlock. +Please be aware that the new mutexes do not enforce strict absolute FIFO scheduling +of mutexes, however any out-of-order lock acquisition should be very rare. + +* Faster semaphores. Following a similar model to mutexes above, these have been +rewritten to use preliminary users space checks. + +* sem_getvalue() now returns the number of waiters. + +* The POSIX thread ID now has much stronger uniqueness characteristics. The library +garrantees not to reuse the same thread ID for at least 2^(wordsize) thread +destruction/creation cycles. + +New tests +--------- + +* semaphore4.c: Tests cancelation of the new sem_wait(). + +* semaphore4t.c: Likewise for sem_timedwait(). + +* rwlock8.c: Tests and times the slow execution paths of r/w locks, and the CVs, +mutexes, and semaphores that they're built on. + + +SNAPSHOT 2004-05-16 +------------------- + +Attempt to add Watcom to the list of compilers that can build the library. +This failed in the end due to it's non-thread-aware errno. The library +builds but the test suite fails. See README.Watcom for more details. + +Bug fixes +--------- +* Bug and memory leak in sem_init() +- Alex Blanco + +* ptw32_getprocessors() now returns CPU count of 1 for WinCE. +- James Ewing + +* pthread_cond_wait() could be canceled at a point where it should not +be cancelable. Fixed. +- Alexander Terekhov + +* sem_timedwait() had an incorrect timeout calculation. +- Philippe Di Cristo + +* Fix a memory leak left behind after threads are destroyed. +- P. van Bruggen + +New features +------------ +* Ported to AMD64. +- Makoto Kato + +* True pre-emptive asynchronous cancelation of threads. This is optional +and requires that Panagiotis E. Hadjidoukas's QueueUserAPCEx package be +installed. This package is included in the pthreads-win32 self-unpacking +Zip archive starting from this snapshot. See the README.txt file inside +the package for installation details. + +Note: If you don't use async cancelation in your application, or don't need +to cancel threads that are blocked on system resources such as network I/O, +then the default non-preemptive async cancelation is probably good enough. +However, pthreads-win32 auto-detects the availability of these components +at run-time, so you don't need to rebuild the library from source if you +change your mind later. + +All of the advice available in books and elsewhere on the undesirability +of using async cancelation in any application still stands, but this +feature is a welcome addition with respect to the library's conformance to +the POSIX standard. + +SNAPSHOT 2003-09-18 +------------------- + +Cleanup of thread priority management. In particular, setting of thread +priority now attempts to map invalid Win32 values within the range returned +by sched_get_priority_min/max() to useful values. See README.NONPORTABLE +under "Thread priority". + +Bug fixes +--------- +* pthread_getschedparam() now returns the priority given by the most recent +call to pthread_setschedparam() or established by pthread_create(), as +required by the standard. Previously, pthread_getschedparam() incorrectly +returned the running thread priority at the time of the call, which may have +been adjusted or temporarily promoted/demoted. + +* sched_get_priority_min() and sched_get_priority_max() now return -1 on error +and set errno. Previously, they incorrectly returned the error value directly. + + +SNAPSHOT 2003-09-04 +------------------- + +Bug fixes +--------- +* ptw32_cancelableWait() now allows cancelation of waiting implicit POSIX +threads. + +New test +-------- +* cancel8.c tests cancelation of Win32 threads waiting at a POSIX cancelation +point. + + +SNAPSHOT 2003-09-03 +------------------- + +Bug fixes +--------- +* pthread_self() would free the newly created implicit POSIX thread handle if +DuplicateHandle failed instead of recycle it (very unlikely). + +* pthread_exit() was neither freeing nor recycling the POSIX thread struct +for implicit POSIX threads. + +New feature - Cancelation of/by Win32 (non-POSIX) threads +--------------------------------------------------------- +Since John Bossom's original implementation, the library has allowed non-POSIX +initialised threads (Win32 threads) to call pthreads-win32 routines and +therefore interact with POSIX threads. This is done by creating an on-the-fly +POSIX thread ID for the Win32 thread that, once created, allows fully +reciprical interaction. This did not extend to thread cancelation (async or +deferred). Now it does. + +Any thread can be canceled by any other thread (Win32 or POSIX) if the former +thread's POSIX pthread_t value is known. It's TSD destructors and POSIX +cleanup handlers will be run before the thread exits with an exit code of +PTHREAD_CANCELED (retrieved with GetExitCodeThread()). + +This allows a Win32 thread to, for example, call POSIX CV routines in the same way +that POSIX threads would/should, with pthread_cond_wait() cancelability and +cleanup handlers (pthread_cond_wait() is a POSIX cancelation point). + +By adding cancelation, Win32 threads should now be able to call all POSIX +threads routines that make sense including semaphores, mutexes, condition +variables, read/write locks, barriers, spinlocks, tsd, cleanup push/pop, +cancelation, pthread_exit, scheduling, etc. + +Note that these on-the-fly 'implicit' POSIX thread IDs are initialised as detached +(not joinable) with deferred cancelation type. The POSIX thread ID will be created +automatically by any POSIX routines that need a POSIX handle (unless the routine +needs a pthread_t as a parameter of course). A Win32 thread can discover it's own +POSIX thread ID by calling pthread_self(), which will create the handle if +necessary and return the pthread_t value. + +New tests +--------- +Test the above new feature. + + +SNAPSHOT 2003-08-19 +------------------- + +This snapshot fixes some accidental corruption to new test case sources. +There are no changes to the library source code. + + +SNAPSHOT 2003-08-15 +------------------- + +Bug fixes +--------- + +* pthread.dsp now uses correct compile flags (/MD). +- Viv + +* pthread_win32_process_detach_np() fixed memory leak. +- Steven Reddie + +* pthread_mutex_destroy() fixed incorrect return code. +- Nicolas Barry + +* pthread_spin_destroy() fixed memory leak. +- Piet van Bruggen + +* Various changes to tighten arg checking, and to work with later versions of +MinGW32 and MsysDTK. + +* pthread_getschedparam() etc, fixed dangerous thread validity checking. +- Nicolas Barry + +* POSIX thread handles are now reused and their memory is not freed on thread exit. +This allows for stronger thread validity checking. + +New standard routine +-------------------- + +* pthread_kill() added to provide thread validity checking to applications. +It does not accept any non zero values for the signal arg. + +New test cases +-------------- + +* New test cases to confirm validity checking, pthread_kill(), and thread reuse. + + +SNAPSHOT 2003-05-10 +------------------- + +Bug fixes +--------- + +* pthread_mutex_trylock() now returns correct error values. +pthread_mutex_destroy() will no longer destroy a recursively locked mutex. +pthread_mutex_lock() is no longer inadvertantly behaving as a cancelation point. +- Thomas Pfaff + +* pthread_mutex_timedlock() no longer occasionally sets incorrect mutex +ownership, causing deadlocks in some applications. +- Robert Strycek and Alexander Terekhov + + +SNAPSHOT 2002-11-04 +------------------- + +Bug fixes +--------- + +* sem_getvalue() now returns the correct value under Win NT and WinCE. +- Rob Fanner + +* sem_timedwait() now uses tighter checks for unreasonable +abstime values - that would result in unexpected timeout values. + +* ptw32_cond_wait_cleanup() no longer mysteriously consumes +CV signals but may produce more spurious wakeups. It is believed +that the sem_timedwait() call is consuming a CV signal that it +shouldn't. +- Alexander Terekhov + +* Fixed a memory leak in ptw32_threadDestroy() for implicit threads. + +* Fixed potential for deadlock in pthread_cond_destroy(). +A deadlock could occur for statically declared CVs (PTHREAD_COND_INITIALIZER), +when one thread is attempting to destroy the condition variable while another +is attempting to dynamically initialize it. +- Michael Johnson + + +SNAPSHOT 2002-03-02 +------------------- + +Cleanup code default style. (IMPORTANT) +---------------------------------------------------------------------- +Previously, if not defined, the cleanup style was determined automatically +from the compiler/language, and one of the following was defined accordingly: + + __CLEANUP_SEH MSVC only + __CLEANUP_CXX C++, including MSVC++, GNU G++ + __CLEANUP_C C, including GNU GCC, not MSVC + +These defines determine the style of cleanup (see pthread.h) and, +most importantly, the way that cancelation and thread exit (via +pthread_exit) is performed (see the routine ptw32_throw() in private.c). + +In short, the exceptions versions of the library throw an exception +when a thread is canceled or exits (via pthread_exit()), which is +caught by a handler in the thread startup routine, so that the +the correct stack unwinding occurs regardless of where the thread +is when it's canceled or exits via pthread_exit(). + +In this and future snapshots, unless the build explicitly defines (e.g. +via a compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then +the build NOW always defaults to __CLEANUP_C style cleanup. This style +uses setjmp/longjmp in the cancelation and pthread_exit implementations, +and therefore won't do stack unwinding even when linked to applications +that have it (e.g. C++ apps). This is for consistency with most +current commercial Unix POSIX threads implementations. Compaq's TRU64 +may be an exception (no pun intended) and possible future trend. + +Although it was not clearly documented before, it is still necessary to +build your application using the same __CLEANUP_* define as was +used for the version of the library that you link with, so that the +correct parts of pthread.h are included. That is, the possible +defines require the following library versions: + + __CLEANUP_SEH pthreadVSE.dll + __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll + __CLEANUP_C pthreadVC.dll or pthreadGC.dll + +E.g. regardless of whether your app is C or C++, if you link with +pthreadVC.lib or libpthreadGC.a, then you must define __CLEANUP_C. + + +THE POINT OF ALL THIS IS: if you have not been defining one of these +explicitly, then the defaults as described at the top of this +section were being used. + +THIS NOW CHANGES, as has been explained above, but to try to make this +clearer here's an example: + +If you were building your application with MSVC++ i.e. using C++ +exceptions and not explicitly defining one of __CLEANUP_*, then +__CLEANUP_C++ was automatically defined for you in pthread.h. +You should have been linking with pthreadVCE.dll, which does +stack unwinding. + +If you now build your application as you had before, pthread.h will now +automatically set __CLEANUP_C as the default style, and you will need to +link with pthreadVC.dll. Stack unwinding will now NOT occur when a thread +is canceled, or the thread calls pthread_exit(). + +Your application will now most likely behave differently to previous +versions, and in non-obvious ways. Most likely is that locally +instantiated objects may not be destroyed or cleaned up after a thread +is canceled. + +If you want the same behaviour as before, then you must now define +__CLEANUP_C++ explicitly using a compiler option and link with +pthreadVCE.dll as you did before. + + +WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY? +Because no commercial Unix POSIX threads implementation allows you to +choose to have stack unwinding. Therefore, providing it in pthread-win32 +as a default is dangerous. We still provide the choice but unless +you consciously choose to do otherwise, your pthreads applications will +now run or crash in similar ways irrespective of the threads platform +you use. Or at least this is the hope. + + +WHY NOT REMOVE THE EXCEPTIONS VERSIONS OF THE LIBRARY ALTOGETHER? +There are a few reasons: +- because there are well respected POSIX threads people who believe + that POSIX threads implementations should be exceptions aware and + do the expected thing in that context. (There are equally respected + people who believe it should not be easily accessible, if it's there + at all, for unconditional conformity to other implementations.) +- because pthreads-win32 is one of the few implementations that has + the choice, perhaps the only freely available one, and so offers + a laboratory to people who may want to explore the effects; +- although the code will always be around somewhere for anyone who + wants it, once it's removed from the current version it will not be + nearly as visible to people who may have a use for it. + + +Source module splitting +----------------------- +In order to enable smaller image sizes to be generated +for applications that link statically with the library, +most routines have been separated out into individual +source code files. + +This is being done in such a way as to be backward compatible. +The old source files are reused to congregate the individual +routine files into larger translation units (via a bunch of +# includes) so that the compiler can still optimise wherever +possible, e.g. through inlining, which can only be done +within the same translation unit. + +It is also possible to build the entire library by compiling +the single file named "pthread.c", which just #includes all +the secondary congregation source files. The compiler +may be able to use this to do more inlining of routines. + +Although the GNU compiler is able to produce libraries with +the necessary separation (the -ffunction-segments switch), +AFAIK, the MSVC and other compilers don't have this feature. + +Finally, since I use makefiles and command-line compilation, +I don't know what havoc this reorganisation may wreak amongst +IDE project file users. You should be able to continue +using your existing project files without modification. + + +New non-portable functions +-------------------------- +pthread_num_processors_np(): + Returns the number of processors in the system that are + available to the process, as determined from the processor + affinity mask. + +pthread_timechange_handler_np(): + To improve tolerance against operator or time service initiated + system clock changes. + + This routine can be called by an application when it + receives a WM_TIMECHANGE message from the system. At present + it broadcasts all condition variables so that waiting threads + can wake up and re-evaluate their conditions and restart + their timed waits if required. + - Suggested by Alexander Terekhov + + +Platform dependence +------------------- +As Win95 doesn't provide one, the library now contains +it's own InterlockedCompareExchange() routine, which is used +whenever Windows doesn't provide it. InterlockedCompareExchange() +is used to implement spinlocks and barriers, and also in mutexes. +This routine relies on the CMPXCHG machine instruction which +is not available on i386 CPUs. This library (from snapshot +20010712 onwards) is therefore no longer supported on i386 +processor platforms. + + +New standard routines +--------------------- +For source code portability only - rwlocks cannot be process shared yet. + + pthread_rwlockattr_init() + pthread_rwlockattr_destroy() + pthread_rwlockattr_setpshared() + pthread_rwlockattr_getpshared() + +As defined in the new POSIX standard, and the Single Unix Spec version 3: + + sem_timedwait() + pthread_mutex_timedlock() - Alexander Terekhov and Thomas Pfaff + pthread_rwlock_timedrdlock() - adapted from pthread_rwlock_rdlock() + pthread_rwlock_timedwrlock() - adapted from pthread_rwlock_wrlock() + + +pthread.h no longer includes windows.h +-------------------------------------- +[Not yet for G++] + +This was done to prevent conflicts. + +HANDLE, DWORD, and NULL are temporarily defined within pthread.h if +they are not already. + + +pthread.h, sched.h and semaphore.h now use dllexport/dllimport +-------------------------------------------------------------- +Not only to avoid the need for the pthread.def file, but to +improve performance. Apparently, declaring functions with dllimport +generates a direct call to the function and avoids the overhead +of a stub function call. + +Bug fixes +--------- +* Fixed potential NULL pointer dereferences in pthread_mutexattr_init, +pthread_mutexattr_getpshared, pthread_barrierattr_init, +pthread_barrierattr_getpshared, and pthread_condattr_getpshared. +- Scott McCaskill + +* Removed potential race condition in pthread_mutex_trylock and +pthread_mutex_lock; +- Alexander Terekhov + +* The behaviour of pthread_mutex_trylock in relation to +recursive mutexes was inconsistent with commercial implementations. +Trylock would return EBUSY if the lock was owned already by the +calling thread regardless of mutex type. Trylock now increments the +recursion count and returns 0 for RECURSIVE mutexes, and will +return EDEADLK rather than EBUSY for ERRORCHECK mutexes. This is +consistent with Solaris. +- Thomas Pfaff + +* Found a fix for the library and workaround for applications for +the known bug #2, i.e. where __CLEANUP_CXX or __CLEANUP_SEH is defined. +See the "Known Bugs in this snapshot" section below. + +This could be made transparent to applications by replacing the macros that +define the current C++ and SEH versions of pthread_cleanup_push/pop +with the C version, but AFAIK cleanup handlers would not then run in the +correct sequence with destructors and exception cleanup handlers when +an exception occurs. + +* Cancelation once started in a thread cannot now be inadvertantly +double canceled. That is, once a thread begins it's cancelation run, +cancelation is disabled and a subsequent cancel request will +return an error (ESRCH). + +* errno: An incorrect compiler directive caused a local version +of errno to be used instead of the Win32 errno. Both instances are +thread-safe but applications checking errno after a pthreads-win32 +call would be wrong. Fixing this also fixed a bad compiler +option in the testsuite (/MT should have been /MD) which is +needed to link with the correct library MSVCRT.LIB. + + +SNAPSHOT 2001-07-12 +------------------- + +To be added + + +SNAPSHOT 2001-07-03 +------------------- + +To be added + + +SNAPSHOT 2000-08-13 +------------------- + +New: +- Renamed DLL and LIB files: + pthreadVSE.dll (MS VC++/Structured EH) + pthreadVSE.lib + pthreadVCE.dll (MS VC++/C++ EH) + pthreadVCE.lib + pthreadGCE.dll (GNU G++/C++ EH) + libpthreadw32.a + + Both your application and the pthread dll should use the + same exception handling scheme. + +Bugs fixed: +- MSVC++ C++ exception handling. + +Some new tests have been added. + + +SNAPSHOT 2000-08-10 +------------------- + +New: +- asynchronous cancelation on X86 (Jason Nye) +- Makefile compatible with MS nmake to replace + buildlib.bat +- GNUmakefile for Mingw32 +- tests/Makefile for MS nmake replaces runall.bat +- tests/GNUmakefile for Mingw32 + +Bugs fixed: +- kernel32 load/free problem +- attempt to hide internel exceptions from application + exception handlers (__try/__except and try/catch blocks) +- Win32 thread handle leakage bug + (David Baggett/Paul Redondo/Eyal Lebedinsky) + +Some new tests have been added. + + +SNAPSHOT 1999-11-02 +------------------- + +Bugs fixed: +- ctime_r macro had an incorrect argument (Erik Hensema), +- threads were not being created + PTHREAD_CANCEL_DEFERRED. This should have + had little effect as deferred is the only + supported type. (Ross Johnson). + +Some compatibility improvements added, eg. +- pthread_setcancelstate accepts NULL pointer + for the previous value argument. Ditto for + pthread_setcanceltype. This is compatible + with Solaris but should not affect + standard applications (Erik Hensema) + +Some new tests have been added. + + +SNAPSHOT 1999-10-17 +------------------- + +Bug fix - Cancelation of threads waiting on condition variables +now works properly (Lorin Hochstein and Peter Slacik) + + +SNAPSHOT 1999-08-12 +------------------- + +Fixed exception stack cleanup if calling pthread_exit() +- (Lorin Hochstein and John Bossom). + +Fixed bugs in condition variables - (Peter Slacik): + - additional contention checks + - properly adjust number of waiting threads after timed + condvar timeout. + + +SNAPSHOT 1999-05-30 +------------------- + +Some minor bugs have been fixed. See the ChangeLog file for details. + +Some more POSIX 1b functions are now included but ony return an +error (ENOSYS) if called. They are: + + sem_open + sem_close + sem_unlink + sem_getvalue + + +SNAPSHOT 1999-04-07 +------------------- + +Some POSIX 1b functions which were internally supported are now +available as exported functions: + + sem_init + sem_destroy + sem_wait + sem_trywait + sem_post + sched_yield + sched_get_priority_min + sched_get_priority_max + +Some minor bugs have been fixed. See the ChangeLog file for details. + + +SNAPSHOT 1999-03-16 +------------------- + +Initial release. + diff --git a/liblo/pthreads.2/Nmakefile b/liblo/pthreads.2/Nmakefile new file mode 100644 index 0000000..73a976c --- /dev/null +++ b/liblo/pthreads.2/Nmakefile @@ -0,0 +1,24 @@ +/* + * nmake file for uwin pthread library + */ + +VERSION = - +CCFLAGS = -V -g $(CC.DLL) +HAVE_CONFIG_H == 1 +_MT == 1 +_timeb == timeb +_ftime == ftime +_errno == _ast_errno + +$(INCLUDEDIR) :INSTALLDIR: pthread.h sched.h + +pthread $(VERSION) :LIBRARY: attr.c barrier.c cancel.c cleanup.c condvar.c \ + create.c dll.c exit.c fork.c global.c misc.c mutex.c private.c \ + rwlock.c sched.c semaphore.c spin.c sync.c tsd.c nonportable.c + +:: ANNOUNCE CONTRIBUTORS COPYING.LIB ChangeLog FAQ GNUmakefile MAINTAINERS \ + Makefile Makefile.in Makefile.vc NEWS PROGRESS README README.WinCE \ + TODO WinCE-PORT install-sh errno.c tests tests.mk acconfig.h \ + config.guess config.h.in config.sub configure configure.in signal.c \ + README.CV README.NONPORTABLE pthread.dsp pthread.dsw + diff --git a/liblo/pthreads.2/Nmakefile.tests b/liblo/pthreads.2/Nmakefile.tests new file mode 100644 index 0000000..4647273 --- /dev/null +++ b/liblo/pthreads.2/Nmakefile.tests @@ -0,0 +1,260 @@ +/* for running tests */ +CCFLAGS = -g +_MT == 1 +_timeb == timeb +_ftime == ftime + +.SOURCE: tests +/* +:PACKAGE: pthread +*/ + +set keepgoing + +":test:" : .MAKE .OPERATOR + local I + $(<:D:B:S=.pass) : .IMPLICIT $(>:D:B:S=.pass) + for I $(<) $(>) + $(I:D:B:S=.pass) : .VIRTUAL .FORCE $(I) + $(>) + end +sizes:: sizes.c +loadfree:: loadfree.c +mutex1:: mutex1.c +mutex1e:: mutex1e.c +mutex1n:: mutex1n.c +mutex1r:: mutex1r.c +mutex2:: mutex2.c +mutex2r:: mutex2r.c +mutex2e:: mutex2e.c +exit1:: exit1.c +condvar1:: condvar1.c +condvar1_1:: condvar1_1.c +condvar1_2:: condvar1_2.c +self1:: self1.c +condvar2:: condvar2.c +condvar2_1:: condvar2_1.c +condvar3_1:: condvar3_1.c +condvar3_2:: condvar3_2.c +condvar3_3:: condvar3_3.c +create1.:: create1.c +create2.:: create2.c +cancel1:: cancel1.c +cancel2:: cancel2.c +mutex3:: mutex3.c +mutex3r:: mutex3r.c +mutex3e:: mutex3e.c +mutex4:: mutex4.c +mutex5:: mutex5.c +mutex6:: mutex6.c +mutex6e:: mutex6e.c +mutex6n:: mutex6n.c +mutex6r:: mutex6r.c +mutex7:: mutex7.c +mutex6s:: mutex6s.c +mutex6rs:: mutex6rs.c +mutex6es:: mutex6es.c +mutex7e:: mutex7e.c +mutex7n:: mutex7n.c +mutex7r:: mutex7r.c +mutex8:: mutex8.c +mutex8e:: mutex8e.c +mutex8n:: mutex8n.c +mutex8r:: mutex8r.c +equal1:: equal1.c +exit2:: exit2.c +exit3:: exit3.c +exit4:: exit4.c +exit5:: exit5.c +join0:: join0.c +join1:: join1.c +join2:: join2.c +join3:: join3.c +kill1:: kill1.c +count1:: count1.c +once1:: once1.c +tsd1:: tsd1.c +self2:: self2.c +eyal1:: eyal1.c +condvar3:: condvar3.c +condvar4:: condvar4.c +condvar5:: condvar5.c +condvar6:: condvar6.c +condvar7:: condvar7.c +condvar8:: condvar8.c +condvar9:: condvar9.c +errno1:: errno1.c +reuse1.:: reuse1.c +reuse2.:: reuse2.c +rwlock1:: rwlock1.c +rwlock2:: rwlock2.c +rwlock3:: rwlock3.c +rwlock4:: rwlock4.c +rwlock5:: rwlock5.c +rwlock6:: rwlock6.c +rwlock7:: rwlock7.c +rwlock8:: rwlock8.c +rwlock2_t:: rwlock2_t.c +rwlock3_t:: rwlock3_t.c +rwlock4_t:: rwlock4_t.c +rwlock5_t:: rwlock5_t.c +rwlock6_t:: rwlock6_t.c +rwlock6_t2:: rwlock6_t2.c +semaphore1:: semaphore1.c +semaphore2:: semaphore2.c +semaphore3:: semaphore3.c +context1:: context1.c +cancel3:: cancel3.c +cancel4:: cancel4.c +cancel5:: cancel5.c +cancel6a:: cancel6a.c +cancel6d:: cancel6d.c +cancel7:: cancel7.c +cleanup0:: cleanup0.c +cleanup1:: cleanup1.c +cleanup2:: cleanup2.c +cleanup3:: cleanup3.c +priority1:: priority1.c +priority2:: priority2.c +inherit1:: inherit1.c +spin1:: spin1.c +spin2:: spin2.c +spin3:: spin3.c +spin4:: spin4.c +barrier1:: barrier1.c +barrier2:: barrier2.c +barrier3:: barrier3.c +barrier4:: barrier4.c +barrier5:: barrier5.c +exception1:: exception1.c +exception2:: exception2.c +exception3:: exception3.c +benchtest1:: benchtest1.c +benchtest2:: benchtest2.c +benchtest3:: benchtest3.c +benchtest4:: benchtest4.c +benchtest5:: benchtest5.c +valid1:: valid1.c +valid2:: valid2.c +cancel9:: cancel9.c + +sizes: :test: sizes +loadfree: :test: +mutex5 :test: loadfree +mutex1 :test: loadfree +mutex1n :test: loadfree +mutex1r :test: loadfree +mutex1e :test: loadfree +semaphore1 :test: loadfree +semaphore2 :test: loadfree +semaphore3 :test: loadfree +mutex2 :test: loadfree +mutex2r :test: loadfree +mutex2e :test: loadfree +exit1 :test: loadfree +condvar1 :test: loadfree +kill1 :test: loadfree +condvar1_1 :test: condvar1 +condvar1_2 :test: join2 +self1 :test: loadfree +condvar2 :test: condvar1 +condvar2_1 :test: condvar2 +create1 :test: mutex2 +create2 :test: create1 +reuse1 :test: create2 +reuse2 :test: reuse1 +cancel1 :test: create1 +cancel2 :test: cancel1 +mutex3 :test: create1 +mutex3r :test: create1 +mutex3e :test: create1 +mutex4 :test: mutex3 +mutex6 :test: mutex4 +mutex6n :test: mutex4 +mutex6e :test: mutex4 +mutex6r :test: mutex4 +mutex6s :test: mutex6 +mutex6rs :test: mutex6r +mutex6es :test: mutex6e +mutex7 :test: mutex6 +mutex7n :test: mutex6n +mutex7e :test: mutex6e +mutex7r :test: mutex6r +mutex8 :test: mutex7 +mutex8n :test: mutex7n +mutex8e :test: mutex7e +mutex8r :test: mutex7r +equal1 :test: create1 +exit2 :test: create1 +exit3 :test: create1 +exit4 :test: kill1 +exit5 :test: exit4 +join0 :test: create1 +join1 :test: create1 +join2 :test: create1 +join3 :test: join2 +count1 :test: join1 +once1 :test: create1 +tsd1 :test: join1 +self2 :test: create1 +eyal1 :test: tsd1 +condvar3 :test: create1 +condvar3_1 :test: condvar3 +condvar3_2 :test: condvar3_1 +condvar3_3 :test: condvar3_2 +condvar4 :test: create1 +condvar5 :test: condvar4 +condvar6 :test: condvar5 +condvar7 :test: condvar6 cleanup1 +condvar8 :test: condvar7 +condvar9 :test: condvar8 +errno1 :test: mutex3 +rwlock1 :test: condvar6 +rwlock2 :test: rwlock1 +rwlock3 :test: rwlock2 +rwlock4 :test: rwlock3 +rwlock5 :test: rwlock4 +rwlock6 :test: rwlock5 +rwlock7 :test: rwlock6 +rwlock8 :test: rwlock7 +rwlock2_t :test: rwlock2 +rwlock3_t :test: rwlock2_t +rwlock4_t :test: rwlock3_t +rwlock5_t :test: rwlock4_t +rwlock6_t :test: rwlock5_t +rwlock6_t2 :test: rwlock6_t +context1 :test: cancel2 +cancel3 :test: context1 +cancel4 :test: cancel3 +cancel5 :test: cancel3 +cancel6a :test: cancel3 +cancel6d :test: cancel3 +cancel7 :test: kill1 +cleanup0 :test: cancel5 +cleanup1 :test: cleanup0 +cleanup2 :test: cleanup1 +cleanup3 :test: cleanup2 +priority1 :test: join1 +priority2 :test: priority1 +inherit1 :test: join1 +spin1 :test: +spin2 :test: spin1.c +spin3 :test: spin2.c +spin4 :test: spin3.c +barrier1 :test: +barrier2 :test: barrier1.c +barrier3 :test: barrier2.c +barrier4 :test: barrier3.c +barrier5 :test: barrier4.c +benchtest1 :test: mutex3 +benchtest2 :test: benchtest1 +benchtest3 :test: benchtest2 +benchtest4 :test: benchtest3 +benchtest5 :test: benchtest4 +exception1 :test: cancel4 +exception2 :test: exception1 +exception3 :test: exception2 +exit4 :test: exit3 +valid1 :test: join1 +valid2 :test: valid1 +cancel9 :test: cancel8 diff --git a/liblo/pthreads.2/PROGRESS b/liblo/pthreads.2/PROGRESS new file mode 100644 index 0000000..3e90bec --- /dev/null +++ b/liblo/pthreads.2/PROGRESS @@ -0,0 +1,4 @@ +Please see the ANNOUNCE file "Level of Standards Conformance" +or the web page: + +http://sources.redhat.com/pthreads-win32/conformance.html diff --git a/liblo/pthreads.2/README b/liblo/pthreads.2/README new file mode 100644 index 0000000..8c3af60 --- /dev/null +++ b/liblo/pthreads.2/README @@ -0,0 +1,593 @@ +PTHREADS-WIN32 +============== + +Pthreads-win32 is free software, distributed under the GNU Lesser +General Public License (LGPL). See the file 'COPYING.LIB' for terms +and conditions. Also see the file 'COPYING' for information +specific to pthreads-win32, copyrights and the LGPL. + + +What is it? +----------- + +Pthreads-win32 is an Open Source Software implementation of the +Threads component of the POSIX 1003.1c 1995 Standard (or later) +for Microsoft's Win32 environment. Some functions from POSIX +1003.1b are also supported including semaphores. Other related +functions include the set of read-write lock functions. The +library also supports some of the functionality of the Open +Group's Single Unix specification, version 2, namely mutex types, +plus some common and pthreads-win32 specific non-portable +routines (see README.NONPORTABLE). + +See the file "ANNOUNCE" for more information including standards +conformance details and the list of supported and unsupported +routines. + + +Prerequisites +------------- +MSVC or GNU C (MinGW32 MSys development kit) + To build from source. + +QueueUserAPCEx by Panagiotis E. Hadjidoukas + For true async cancelation of threads (including blocked threads). + This is a DLL and Windows driver that provides pre-emptive APC + by forcing threads into an alertable state when the APC is queued. + Both the DLL and driver are provided with the pthreads-win32.exe + self-unpacking ZIP, and on the pthreads-win32 FTP site (in source + and pre-built forms). Currently this is a separate LGPL package to + pthreads-win32. See the README in the QueueUserAPCEx folder for + installation instructions. + + Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL + QuserEx.DLL is available and whether the driver AlertDrv.sys is + loaded. If it is not available, pthreads-win32 will simulate async + cancelation, which means that it can async cancel only threads that + are runnable. The simulated async cancellation cannot cancel blocked + threads. + + +Library naming +-------------- + +Because the library is being built using various exception +handling schemes and compilers - and because the library +may not work reliably if these are mixed in an application, +each different version of the library has it's own name. + +Note 1: the incompatibility is really between EH implementations +of the different compilers. It should be possible to use the +standard C version from either compiler with C++ applications +built with a different compiler. If you use an EH version of +the library, then you must use the same compiler for the +application. This is another complication and dependency that +can be avoided by using only the standard C library version. + +Note 2: if you use a standard C pthread*.dll with a C++ +application, then any functions that you define that are +intended to be called via pthread_cleanup_push() must be +__cdecl. + +Note 3: the intention was to also name either the VC or GC +version (it should be arbitrary) as pthread.dll, including +pthread.lib and libpthread.a as appropriate. This is no longer +likely to happen. + +Note 4: the compatibility number was added so that applications +can differentiate between binary incompatible versions of the +libs and dlls. + +In general: + pthread[VG]{SE,CE,C}c.dll + pthread[VG]{SE,CE,C}c.lib + +where: + [VG] indicates the compiler + V - MS VC, or + G - GNU C + + {SE,CE,C} indicates the exception handling scheme + SE - Structured EH, or + CE - C++ EH, or + C - no exceptions - uses setjmp/longjmp + + c - DLL compatibility number indicating ABI and API + compatibility with applications built against + any snapshot with the same compatibility number. + See 'Version numbering' below. + +The name may also be suffixed by a 'd' to indicate a debugging version +of the library. E.g. pthreadVC2d.lib. Debugging versions contain +additional information for debugging (symbols etc) and are often not +optimised in any way (compiled with optimisation turned off). + +For example: + pthreadVSE.dll (MSVC/SEH) + pthreadGCE.dll (GNUC/C++ EH) + pthreadGC.dll (GNUC/not dependent on exceptions) + pthreadVC1.dll (MSVC/not dependent on exceptions - not binary + compatible with pthreadVC.dll) + pthreadVC2.dll (MSVC/not dependent on exceptions - not binary + compatible with pthreadVC1.dll or pthreadVC.dll) + +The GNU library archive file names have correspondingly changed to: + + libpthreadGCEc.a + libpthreadGCc.a + + +Versioning numbering +-------------------- + +Version numbering is separate from the snapshot dating system, and +is the canonical version identification system embedded within the +DLL using the Microsoft version resource system. The versioning +system chosen follows the GNU Libtool system. See +http://www.gnu.org/software/libtool/manual.html section 6.2. + +See the resource file 'version.rc'. + +Microsoft version numbers use 4 integers: + + 0.0.0.0 + +Pthreads-win32 uses the first 3 following the Libtool convention. +The fourth is commonly used for the build number, but will be reserved +for future use. + + current.revision.age.0 + +The numbers are changed as follows: + +1. If the library source code has changed at all since the last update, + then increment revision (`c:r:a' becomes `c:r+1:a'). +2. If any interfaces have been added, removed, or changed since the last + update, increment current, and set revision to 0. +3. If any interfaces have been added since the last public release, then + increment age. +4. If any interfaces have been removed or changed since the last public + release, then set age to 0. + + +DLL compatibility numbering is an attempt to ensure that applications +always load a compatible pthreads-win32 DLL by using a DLL naming system +that is consistent with the version numbering system. It also allows +older and newer DLLs to coexist in the same filesystem so that older +applications can continue to be used. For pre .NET Windows systems, +this inevitably requires incompatible versions of the same DLLs to have +different names. + +Pthreads-win32 has adopted the Cygwin convention of appending a single +integer number to the DLL name. The number used is based on the library +version number and is computed as 'current' - 'age'. + +(See http://home.att.net/~perlspinr/libversioning.html for a nicely +detailed explanation.) + +Using this method, DLL name/s will only change when the DLL's +backwards compatibility changes. Note that the addition of new +'interfaces' will not of itself change the DLL's compatibility for older +applications. + + +Which of the several dll versions to use? +----------------------------------------- +or, +--- +What are all these pthread*.dll and pthread*.lib files? +------------------------------------------------------- + +Simple, use either pthreadGCv.* if you use GCC, or pthreadVCv.* if you +use MSVC - where 'v' is the DLL versioning (compatibility) number. + +Otherwise, you need to choose carefully and know WHY. + +The most important choice you need to make is whether to use a +version that uses exceptions internally, or not. There are versions +of the library that use exceptions as part of the thread +cancelation and exit implementation. The default version uses +setjmp/longjmp. + +There is some contension amongst POSIX threads experts as +to how POSIX threads cancelation and exit should work +with languages that use exceptions, e.g. C++ and even C +(Microsoft's Structured Exceptions). + +The issue is: should cancelation of a thread in, say, +a C++ application cause object destructors and C++ exception +handlers to be invoked as the stack unwinds during thread +exit, or not? + +There seems to be more opinion in favour of using the +standard C version of the library (no EH) with C++ applications +for the reason that this appears to be the assumption commercial +pthreads implementations make. Therefore, if you use an EH version +of pthreads-win32 then you may be under the illusion that +your application will be portable, when in fact it is likely to +behave differently when linked with other pthreads libraries. + +Now you may be asking: then why have you kept the EH versions of +the library? + +There are a couple of reasons: +- there is division amongst the experts and so the code may + be needed in the future. Yes, it's in the repository and we + can get it out anytime in the future, but it would be difficult + to find. +- pthreads-win32 is one of the few implementations, and possibly + the only freely available one, that has EH versions. It may be + useful to people who want to play with or study application + behaviour under these conditions. + +Notes: + +[If you use either pthreadVCE or pthreadGCE] + +1. [See also the discussion in the FAQ file - Q2, Q4, and Q5] + +If your application contains catch(...) blocks in your POSIX +threads then you will need to replace the "catch(...)" with the macro +"PtW32Catch", eg. + + #ifdef PtW32Catch + PtW32Catch { + ... + } + #else + catch(...) { + ... + } + #endif + +Otherwise neither pthreads cancelation nor pthread_exit() will work +reliably when using versions of the library that use C++ exceptions +for cancelation and thread exit. + +This is due to what is believed to be a C++ compliance error in VC++ +whereby you may not have multiple handlers for the same exception in +the same try/catch block. GNU G++ doesn't have this restriction. + + +Other name changes +------------------ + +All snapshots prior to and including snapshot 2000-08-13 +used "_pthread_" as the prefix to library internal +functions, and "_PTHREAD_" to many library internal +macros. These have now been changed to "ptw32_" and "PTW32_" +respectively so as to not conflict with the ANSI standard's +reservation of identifiers beginning with "_" and "__" for +use by compiler implementations only. + +If you have written any applications and you are linking +statically with the pthreads-win32 library then you may have +included a call to _pthread_processInitialize. You will +now have to change that to ptw32_processInitialize. + + +Cleanup code default style +-------------------------- + +Previously, if not defined, the cleanup style was determined automatically +from the compiler used, and one of the following was defined accordingly: + + __CLEANUP_SEH MSVC only + __CLEANUP_CXX C++, including MSVC++, GNU G++ + __CLEANUP_C C, including GNU GCC, not MSVC + +These defines determine the style of cleanup (see pthread.h) and, +most importantly, the way that cancelation and thread exit (via +pthread_exit) is performed (see the routine ptw32_throw()). + +In short, the exceptions versions of the library throw an exception +when a thread is canceled, or exits via pthread_exit(). This exception is +caught by a handler in the thread startup routine, so that the +the correct stack unwinding occurs regardless of where the thread +is when it's canceled or exits via pthread_exit(). + +In this snapshot, unless the build explicitly defines (e.g. via a +compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then +the build NOW always defaults to __CLEANUP_C style cleanup. This style +uses setjmp/longjmp in the cancelation and pthread_exit implementations, +and therefore won't do stack unwinding even when linked to applications +that have it (e.g. C++ apps). This is for consistency with most/all +commercial Unix POSIX threads implementations. + +Although it was not clearly documented before, it is still necessary to +build your application using the same __CLEANUP_* define as was +used for the version of the library that you link with, so that the +correct parts of pthread.h are included. That is, the possible +defines require the following library versions: + + __CLEANUP_SEH pthreadVSE.dll + __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll + __CLEANUP_C pthreadVC.dll or pthreadGC.dll + +It is recommended that you let pthread.h use it's default __CLEANUP_C +for both library and application builds. That is, don't define any of +the above, and then link with pthreadVC.lib (MSVC or MSVC++) and +libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but +another reason is that the prebuilt pthreadVCE.dll is currently broken. +Versions built with MSVC++ later than version 6 may not be broken, but I +can't verify this yet. + +WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY? +Because no commercial Unix POSIX threads implementation allows you to +choose to have stack unwinding. Therefore, providing it in pthread-win32 +as a default is dangerous. We still provide the choice but unless +you consciously choose to do otherwise, your pthreads applications will +now run or crash in similar ways irrespective of the pthreads platform +you use. Or at least this is the hope. + + +Building under VC++ using C++ EH, Structured EH, or just C +---------------------------------------------------------- + +From the source directory run nmake without any arguments to list +help information. E.g. + +$ nmake + +Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 +Copyright (C) Microsoft Corp 1988-1998. All rights reserved. + +Run one of the following command lines: +nmake clean VCE (to build the MSVC dll with C++ exception handling) +nmake clean VSE (to build the MSVC dll with structured exception handling) +nmake clean VC (to build the MSVC dll with C cleanup code) +nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling) +nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling) +nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code) +nmake clean VC-static (to build the MSVC static lib with C cleanup code) +nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling) +nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling) +nmake clean VC-debug (to build the debug MSVC dll with C cleanup code) +nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling) +nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling) +nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code) +nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code) + + +The pre-built dlls are normally built using the *-inlined targets. + +You can run the testsuite by changing to the "tests" directory and +running nmake. E.g.: + +$ cd tests +$ nmake + +Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 +Copyright (C) Microsoft Corp 1988-1998. All rights reserved. + +Run one of the following command lines: +nmake clean VC (to test using VC dll with VC (no EH) applications) +nmake clean VCX (to test using VC dll with VC++ (EH) applications) +nmake clean VCE (to test using the VCE dll with VC++ EH applications) +nmake clean VSE (to test using VSE dll with VC (SEH) applications) +nmake clean VC-bench (to benchtest using VC dll with C bench app) +nmake clean VCX-bench (to benchtest using VC dll with C++ bench app) +nmake clean VCE-bench (to benchtest using VCE dll with C++ bench app) +nmake clean VSE-bench (to benchtest using VSE dll with SEH bench app) +nmake clean VC-static (to test using VC static lib with VC (no EH) applications) + + +Building under Mingw32 +---------------------- + +The dll can be built easily with recent versions of Mingw32. +(The distributed versions are built using Mingw32 and MsysDTK +from www.mingw32.org.) + +From the source directory, run make for help information. E.g.: + +$ make +Run one of the following command lines: +make clean GC (to build the GNU C dll with C cleanup code) +make clean GCE (to build the GNU C dll with C++ exception handling) +make clean GC-inlined (to build the GNU C inlined dll with C cleanup code) +make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling) +make clean GC-static (to build the GNU C inlined static lib with C cleanup code) +make clean GC-debug (to build the GNU C debug dll with C cleanup code) +make clean GCE-debug (to build the GNU C debug dll with C++ exception handling) +make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code) +make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling) +make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code) + + +The pre-built dlls are normally built using the *-inlined targets. + +You can run the testsuite by changing to the "tests" directory and +running make for help information. E.g.: + +$ cd tests +$ make +Run one of the following command lines: +make clean GC (to test using GC dll with C (no EH) applications) +make clean GCX (to test using GC dll with C++ (EH) applications) +make clean GCE (to test using GCE dll with C++ (EH) applications) +make clean GC-bench (to benchtest using GNU C dll with C cleanup code) +make clean GCE-bench (to benchtest using GNU C dll with C++ exception handling) +make clean GC-static (to test using GC static lib with C (no EH) applications) + + +Building under Linux using the Mingw32 cross development tools +-------------------------------------------------------------- + +You can build the library without leaving Linux by using the Mingw32 cross +development toolchain. See http://www.libsdl.org/extras/win32/cross/ for +tools and info. The GNUmakefile contains some support for this, for example: + +make CROSS=i386-mingw32msvc- clean GC-inlined + +will build pthreadGCn.dll and libpthreadGCn.a (n=version#), provided your +cross-tools/bin directory is in your PATH (or use the cross-make.sh script +at the URL above). + + +Building the library as a statically linkable library +----------------------------------------------------- + +General: PTW32_STATIC_LIB must be defined for both the library build and the +application build. The makefiles supplied and used by the following 'make' +command lines will define this for you. + +MSVC (creates pthreadVCn.lib as a static link lib): + +nmake clean VC-static + + +MinGW32 (creates libpthreadGCn.a as a static link lib): + +make clean GC-static + + +Define PTW32_STATIC_LIB when building your application. Also, your +application must call a two non-portable routines to initialise the +some state on startup and cleanup before exit. One other routine needs +to be called to cleanup after any Win32 threads have called POSIX API +routines. See README.NONPORTABLE or the html reference manual pages for +details on these routines: + +BOOL pthread_win32_process_attach_np (void); +BOOL pthread_win32_process_detach_np (void); +BOOL pthread_win32_thread_attach_np (void); // Currently a no-op +BOOL pthread_win32_thread_detach_np (void); + + +The tests makefiles have the same targets but only check that the +static library is statically linkable. They don't run the full +testsuite. To run the full testsuite, build the dlls and run the +dll test targets. + + +Building the library under Cygwin +--------------------------------- + +Cygwin is implementing it's own POSIX threads routines and these +will be the ones to use if you develop using Cygwin. + + +Ready to run binaries +--------------------- + +For convenience, the following ready-to-run files can be downloaded +from the FTP site (see under "Availability" below): + + pthread.h + semaphore.h + sched.h + pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp + pthreadVC.lib + pthreadVCE.dll - built with MSVC++ compiler using C++ EH + pthreadVCE.lib + pthreadVSE.dll - built with MSVC compiler using SEH + pthreadVSE.lib + pthreadGC.dll - built with Mingw32 GCC + libpthreadGC.a - derived from pthreadGC.dll + pthreadGCE.dll - built with Mingw32 G++ + libpthreadGCE.a - derived from pthreadGCE.dll + +As of August 2003 pthreads-win32 pthreadG* versions are built and tested +using the MinGW + MsysDTK environment current as of that date or later. +The following file MAY be needed for older MinGW environments. + + gcc.dll - needed to build and run applications that use + pthreadGCE.dll. + + +Building applications with GNU compilers +---------------------------------------- + +If you're using pthreadGC.dll: + +With the three header files, pthreadGC.dll and libpthreadGC.a in the +same directory as your application myapp.c, you could compile, link +and run myapp.c under Mingw32 as follows: + + gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC + myapp + +Or put pthreadGC.dll in an appropriate directory in your PATH, +put libpthreadGC.a in your system lib directory, and +put the three header files in your system include directory, +then use: + + gcc -o myapp.exe myapp.c -lpthreadGC + myapp + + +If you're using pthreadGCE.dll: + +With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a +in the same directory as your application myapp.c, you could compile, +link and run myapp.c under Mingw32 as follows: + + gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE + myapp + +Or put pthreadGCE.dll and gcc.dll in an appropriate directory in +your PATH, put libpthreadGCE.a in your system lib directory, and +put the three header files in your system include directory, +then use: + + gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE + myapp + + +Availability +------------ + +The complete source code in either unbundled, self-extracting +Zip file, or tar/gzipped format can be found at: + + ftp://sources.redhat.com/pub/pthreads-win32 + +The pre-built DLL, export libraries and matching pthread.h can +be found at: + + ftp://sources.redhat.com/pub/pthreads-win32/dll-latest + +Home page: + + http://sources.redhat.com/pthreads-win32/ + + +Mailing list +------------ + +There is a mailing list for discussing pthreads on Win32. +To join, send email to: + + pthreads-win32-subscribe@sources.redhat.com + +Unsubscribe by sending mail to: + + pthreads-win32-unsubscribe@sources.redhat.com + + +Acknowledgements +---------------- + +See the ANNOUNCE file for acknowledgements. +See the 'CONTRIBUTORS' file for the list of contributors. + +As much as possible, the ChangeLog file attributes +contributions and patches that have been incorporated +in the library to the individuals responsible. + +Finally, thanks to all those who work on and contribute to the +POSIX and Single Unix Specification standards. The maturity of an +industry can be measured by it's open standards. + +---- +Ross Johnson + + + + + + + + + diff --git a/liblo/pthreads.2/README.Borland b/liblo/pthreads.2/README.Borland new file mode 100644 index 0000000..5f836cd --- /dev/null +++ b/liblo/pthreads.2/README.Borland @@ -0,0 +1,57 @@ +In ptw32_InterlockedCompareExchange.c, I've added a section for +Borland's compiler; it's identical to that for the MS compiler except +that it uses /* ... */ comments instead of ; comments. + +[RPJ: need to define HAVE_TASM32 in config.h to use the above.] + + +The other file is a makefile suitable for use with Borland's compiler +(run "make -fBmakefile" in the directory). It builds a single version +of the library, pthreadBC.dll and the corresponding pthreadBC.lib +import library, which is comparable to the pthreadVC version; I can't +personally see any demand for the versions that include structured or +C++ exception cancellation handling so I haven't attempted to build +those versions of the library. (I imagine a static version might be +of use to some, but we can't legally use that on my commercial +projects so I can't try that out, unfortunately.) + +[RPJ: Added tests\Bmakefile as well.] + +Borland C++ doesn't define the ENOSYS constant used by pthreads-win32; +rather than make more extensive patches to the pthreads-win32 source I +have a mostly-arbitrary constant for it in the makefile. However this +doesn't make it visible to the application using the library, so if +anyone actually wants to use this constant in their apps (why?) +someone might like to make a seperate NEED_BCC_something define to add +this stuff. + +The makefile also #defines EDEADLK as EDEADLOCK, _timeb as timeb, and +_ftime as ftime, to deal with the minor differences between the two +RTLs' naming conventions, and sets the compiler flags as required to +get a normal compile of the library. + +[RPJ: Moved errno values and _timeb etc to pthread.h, so apps will also +use them.] + +(While I'm on the subject, the reason Borland users should recompile +the library, rather than using the impdef/implib technique suggested +previously on the mailing list, is that a) the errno constants are +different, so the results returned by the pthread_* functions can be +meaningless, and b) the errno variable/pseudo-variable itself is +different in the MS & BCC runtimes, so you can't access the +pthreadVC's errno from a Borland C++-compiled host application +correctly - I imagine there are other potential problems from the RTL +mismatch too.) + +[RPJ: Make sure you use the same RTL in both dll and application builds. +The dll and tests Bmakefiles use cw32mti.lib. Having some trouble with +memory read exceptions running the test suite using BCC55.] + +Best regards, +Will + +-- +Will Bryant +Systems Architect, eCOSM Limited +Cell +64 21 655 443, office +64 3 365 4176 +http://www.ecosm.com/ diff --git a/liblo/pthreads.2/README.CV b/liblo/pthreads.2/README.CV new file mode 100644 index 0000000..522fa60 --- /dev/null +++ b/liblo/pthreads.2/README.CV @@ -0,0 +1,3036 @@ +README.CV -- Condition Variables +-------------------------------- + +The original implementation of condition variables in +pthreads-win32 was based on a discussion paper: + +"Strategies for Implementing POSIX Condition Variables +on Win32": http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + +The changes suggested below were made on Feb 6 2001. This +file is included in the package for the benefit of anyone +interested in understanding the pthreads-win32 implementation +of condition variables and the (sometimes subtle) issues that +it attempts to resolve. + +Thanks go to the individuals whose names appear throughout +the following text. + +Ross Johnson + +-------------------------------------------------------------------- + +fyi.. (more detailed problem description/demos + possible fix/patch) + +regards, +alexander. + + +Alexander Terekhov +31.01.2001 17:43 + +To: ace-bugs@cs.wustl.edu +cc: +From: Alexander Terekhov/Germany/IBM@IBMDE +Subject: Implementation of POSIX CVs: spur.wakeups/lost + signals/deadlocks/unfairness + + + + ACE VERSION: + + 5.1.12 (pthread-win32 snapshot 2000-12-29) + + HOST MACHINE and OPERATING SYSTEM: + + IBM IntelliStation Z Pro, 2 x XEON 1GHz, Win2K + + TARGET MACHINE and OPERATING SYSTEM, if different from HOST: + COMPILER NAME AND VERSION (AND PATCHLEVEL): + + Microsoft Visual C++ 6.0 + + AREA/CLASS/EXAMPLE AFFECTED: + + Implementation of POSIX condition variables - OS.cpp/.h + + DOES THE PROBLEM AFFECT: + + EXECUTION? YES! + + SYNOPSIS: + + a) spurious wakeups (minor problem) + b) lost signals + c) broadcast deadlock + d) unfairness (minor problem) + + DESCRIPTION: + + Please see attached copy of discussion thread + from comp.programming.threads for more details on + some reported problems. (i've also posted a "fyi" + message to ace-users a week or two ago but + unfortunately did not get any response so far). + + It seems that current implementation suffers from + two essential problems: + + 1) cond.waiters_count does not accurately reflect + number of waiters blocked on semaphore - w/o + proper synchronisation that could result (in the + time window when counter is not accurate) + in spurious wakeups organised by subsequent + _signals and _broadcasts. + + 2) Always having (with no e.g. copy_and_clear/..) + the same queue in use (semaphore+counter) + neither signal nor broadcast provide 'atomic' + behaviour with respect to other threads/subsequent + calls to signal/broadcast/wait. + + Each problem and combination of both could produce + various nasty things: + + a) spurious wakeups (minor problem) + + it is possible that waiter(s) which was already + unblocked even so is still counted as blocked + waiter. signal and broadcast will release + semaphore which will produce a spurious wakeup + for a 'real' waiter coming later. + + b) lost signals + + signalling thread ends up consuming its own + signal. please see demo/discussion below. + + c) broadcast deadlock + + last_waiter processing code does not correctly + handle the case with multiple threads + waiting for the end of broadcast. + please see demo/discussion below. + + d) unfairness (minor problem) + + without SignalObjectAndWait some waiter(s) + may end up consuming broadcasted signals + multiple times (spurious wakeups) because waiter + thread(s) can be preempted before they call + semaphore wait (but after count++ and mtx.unlock). + + REPEAT BY: + + See below... run problem demos programs (tennis.cpp and + tennisb.cpp) number of times concurrently (on multiprocessor) + and in multiple sessions or just add a couple of "Sleep"s + as described in the attached copy of discussion thread + from comp.programming.threads + + SAMPLE FIX/WORKAROUND: + + See attached patch to pthread-win32.. well, I can not + claim that it is completely bug free but at least my + test and tests provided by pthreads-win32 seem to work. + Perhaps that will help. + + regards, + alexander. + + +>> Forum: comp.programming.threads +>> Thread: pthread_cond_* implementation questions +. +. +. +David Schwartz wrote: + +> terekhov@my-deja.com wrote: +> +>> BTW, could you please also share your view on other perceived +>> "problems" such as nested broadcast deadlock, spurious wakeups +>> and (the latest one) lost signals?? +> +>I'm not sure what you mean. The standard allows an implementation +>to do almost whatever it likes. In fact, you could implement +>pthread_cond_wait by releasing the mutex, sleeping a random +>amount of time, and then reacquiring the mutex. Of course, +>this would be a pretty poor implementation, but any code that +>didn't work under that implementation wouldn't be strictly +>compliant. + +The implementation you suggested is indeed correct +one (yes, now I see it :). However it requires from +signal/broadcast nothing more than to "{ return 0; }" +That is not the case for pthread-win32 and ACE +implementations. I do think that these implementations +(basically the same implementation) have some serious +problems with wait/signal/broadcast calls. I am looking +for help to clarify whether these problems are real +or not. I think that I can demonstrate what I mean +using one or two small sample programs. +. +. +. +========== +tennis.cpp +========== + +#include "ace/Synch.h" +#include "ace/Thread.h" + +enum GAME_STATE { + + START_GAME, + PLAYER_A, // Player A playes the ball + PLAYER_B, // Player B playes the ball + GAME_OVER, + ONE_PLAYER_GONE, + BOTH_PLAYERS_GONE + +}; + +enum GAME_STATE eGameState; +ACE_Mutex* pmtxGameStateLock; +ACE_Condition< ACE_Mutex >* pcndGameStateChange; + +void* + playerA( + void* pParm + ) +{ + + // For access to game state variable + pmtxGameStateLock->acquire(); + + // Play loop + while ( eGameState < GAME_OVER ) { + + // Play the ball + cout << endl << "PLAYER-A" << endl; + + // Now its PLAYER-B's turn + eGameState = PLAYER_B; + + // Signal to PLAYER-B that now it is his turn + pcndGameStateChange->signal(); + + // Wait until PLAYER-B finishes playing the ball + do { + + pcndGameStateChange->wait(); + + if ( PLAYER_B == eGameState ) + cout << endl << "----PLAYER-A: SPURIOUS WAKEUP!!!" << endl; + + } while ( PLAYER_B == eGameState ); + + } + + // PLAYER-A gone + eGameState = (GAME_STATE)(eGameState+1); + cout << endl << "PLAYER-A GONE" << endl; + + // No more access to state variable needed + pmtxGameStateLock->release(); + + // Signal PLAYER-A gone event + pcndGameStateChange->broadcast(); + + return 0; + +} + +void* + playerB( + void* pParm + ) +{ + + // For access to game state variable + pmtxGameStateLock->acquire(); + + // Play loop + while ( eGameState < GAME_OVER ) { + + // Play the ball + cout << endl << "PLAYER-B" << endl; + + // Now its PLAYER-A's turn + eGameState = PLAYER_A; + + // Signal to PLAYER-A that now it is his turn + pcndGameStateChange->signal(); + + // Wait until PLAYER-A finishes playing the ball + do { + + pcndGameStateChange->wait(); + + if ( PLAYER_A == eGameState ) + cout << endl << "----PLAYER-B: SPURIOUS WAKEUP!!!" << endl; + + } while ( PLAYER_A == eGameState ); + + } + + // PLAYER-B gone + eGameState = (GAME_STATE)(eGameState+1); + cout << endl << "PLAYER-B GONE" << endl; + + // No more access to state variable needed + pmtxGameStateLock->release(); + + // Signal PLAYER-B gone event + pcndGameStateChange->broadcast(); + + return 0; + +} + + +int +main (int, ACE_TCHAR *[]) +{ + + pmtxGameStateLock = new ACE_Mutex(); + pcndGameStateChange = new ACE_Condition< ACE_Mutex >( *pmtxGameStateLock +); + + // Set initial state + eGameState = START_GAME; + + // Create players + ACE_Thread::spawn( playerA ); + ACE_Thread::spawn( playerB ); + + // Give them 5 sec. to play + Sleep( 5000 );//sleep( 5 ); + + // Set game over state + pmtxGameStateLock->acquire(); + eGameState = GAME_OVER; + + // Let them know + pcndGameStateChange->broadcast(); + + // Wait for players to stop + do { + + pcndGameStateChange->wait(); + + } while ( eGameState < BOTH_PLAYERS_GONE ); + + // Cleanup + cout << endl << "GAME OVER" << endl; + pmtxGameStateLock->release(); + delete pcndGameStateChange; + delete pmtxGameStateLock; + + return 0; + +} + +=========== +tennisb.cpp +=========== +#include "ace/Synch.h" +#include "ace/Thread.h" + +enum GAME_STATE { + + START_GAME, + PLAYER_A, // Player A playes the ball + PLAYER_B, // Player B playes the ball + GAME_OVER, + ONE_PLAYER_GONE, + BOTH_PLAYERS_GONE + +}; + +enum GAME_STATE eGameState; +ACE_Mutex* pmtxGameStateLock; +ACE_Condition< ACE_Mutex >* pcndGameStateChange; + +void* + playerA( + void* pParm + ) +{ + + // For access to game state variable + pmtxGameStateLock->acquire(); + + // Play loop + while ( eGameState < GAME_OVER ) { + + // Play the ball + cout << endl << "PLAYER-A" << endl; + + // Now its PLAYER-B's turn + eGameState = PLAYER_B; + + // Signal to PLAYER-B that now it is his turn + pcndGameStateChange->broadcast(); + + // Wait until PLAYER-B finishes playing the ball + do { + + pcndGameStateChange->wait(); + + if ( PLAYER_B == eGameState ) + cout << endl << "----PLAYER-A: SPURIOUS WAKEUP!!!" << endl; + + } while ( PLAYER_B == eGameState ); + + } + + // PLAYER-A gone + eGameState = (GAME_STATE)(eGameState+1); + cout << endl << "PLAYER-A GONE" << endl; + + // No more access to state variable needed + pmtxGameStateLock->release(); + + // Signal PLAYER-A gone event + pcndGameStateChange->broadcast(); + + return 0; + +} + +void* + playerB( + void* pParm + ) +{ + + // For access to game state variable + pmtxGameStateLock->acquire(); + + // Play loop + while ( eGameState < GAME_OVER ) { + + // Play the ball + cout << endl << "PLAYER-B" << endl; + + // Now its PLAYER-A's turn + eGameState = PLAYER_A; + + // Signal to PLAYER-A that now it is his turn + pcndGameStateChange->broadcast(); + + // Wait until PLAYER-A finishes playing the ball + do { + + pcndGameStateChange->wait(); + + if ( PLAYER_A == eGameState ) + cout << endl << "----PLAYER-B: SPURIOUS WAKEUP!!!" << endl; + + } while ( PLAYER_A == eGameState ); + + } + + // PLAYER-B gone + eGameState = (GAME_STATE)(eGameState+1); + cout << endl << "PLAYER-B GONE" << endl; + + // No more access to state variable needed + pmtxGameStateLock->release(); + + // Signal PLAYER-B gone event + pcndGameStateChange->broadcast(); + + return 0; + +} + + +int +main (int, ACE_TCHAR *[]) +{ + + pmtxGameStateLock = new ACE_Mutex(); + pcndGameStateChange = new ACE_Condition< ACE_Mutex >( *pmtxGameStateLock +); + + // Set initial state + eGameState = START_GAME; + + // Create players + ACE_Thread::spawn( playerA ); + ACE_Thread::spawn( playerB ); + + // Give them 5 sec. to play + Sleep( 5000 );//sleep( 5 ); + + // Make some noise + pmtxGameStateLock->acquire(); + cout << endl << "---Noise ON..." << endl; + pmtxGameStateLock->release(); + for ( int i = 0; i < 100000; i++ ) + pcndGameStateChange->broadcast(); + cout << endl << "---Noise OFF" << endl; + + // Set game over state + pmtxGameStateLock->acquire(); + eGameState = GAME_OVER; + cout << endl << "---Stopping the game..." << endl; + + // Let them know + pcndGameStateChange->broadcast(); + + // Wait for players to stop + do { + + pcndGameStateChange->wait(); + + } while ( eGameState < BOTH_PLAYERS_GONE ); + + // Cleanup + cout << endl << "GAME OVER" << endl; + pmtxGameStateLock->release(); + delete pcndGameStateChange; + delete pmtxGameStateLock; + + return 0; + +} +. +. +. +David Schwartz wrote: +>> > It's compliant +>> +>> That is really good. +> +>> Tomorrow (I have to go urgently now) I will try to +>> demonstrate the lost-signal "problem" of current +>> pthread-win32 and ACE-(variant w/o SingleObjectAndWait) +>> implementations: players start suddenly drop their balls :-) +>> (with no change in source code). +> +>Signals aren't lost, they're going to the main thread, +>which isn't coded correctly to handle them. Try this: +> +> // Wait for players to stop +> do { +> +> pthread_cond_wait( &cndGameStateChange,&mtxGameStateLock ); +>printf("Main thread stole a signal\n"); +> +> } while ( eGameState < BOTH_PLAYERS_GONE ); +> +>I bet everytime you thing a signal is lost, you'll see that printf. +>The signal isn't lost, it was stolen by another thread. + +well, you can probably loose your bet.. it was indeed stolen +by "another" thread but not the one you seem to think of. + +I think that what actually happens is the following: + +H:\SA\UXX\pt\PTHREADS\TESTS>tennis3.exe + +PLAYER-A + +PLAYER-B + +----PLAYER-B: SPURIOUS WAKEUP!!! + +PLAYER-A GONE + +PLAYER-B GONE + +GAME OVER + +H:\SA\UXX\pt\PTHREADS\TESTS> + +here you can see that PLAYER-B after playing his first +ball (which came via signal from PLAYER-A) just dropped +it down. What happened is that his signal to player A +was consumed as spurious wakeup by himself (player B). + +The implementation has a problem: + +================ +waiting threads: +================ + +{ /** Critical Section + + inc cond.waiters_count + +} + + /* + /* Atomic only if using Win32 SignalObjectAndWait + /* + cond.mtx.release + + /*** ^^-- A THREAD WHICH DID SIGNAL MAY ACQUIRE THE MUTEX, + /*** GO INTO WAIT ON THE SAME CONDITION AND OVERTAKE + /*** ORIGINAL WAITER(S) CONSUMING ITS OWN SIGNAL! + + cond.sem.wait + +Player-A after playing game's initial ball went into +wait (called _wait) but was pre-empted before reaching +wait semaphore. He was counted as waiter but was not +actually waiting/blocked yet. + +=============== +signal threads: +=============== + +{ /** Critical Section + + waiters_count = cond.waiters_count + +} + + if ( waiters_count != 0 ) + + sem.post 1 + + endif + +Player-B after he received signal/ball from Player A +called _signal. The _signal did see that there was +one waiter blocked on the condition (Player-A) and +released the semaphore.. (but it did not unblock +Player-A because he was not actually blocked). +Player-B thread continued its execution, called _wait, +was counted as second waiter BUT was allowed to slip +through opened semaphore gate (which was opened for +Player-B) and received his own signal. Player B remained +blocked followed by Player A. Deadlock happened which +lasted until main thread came in and said game over. + +It seems to me that the implementation fails to +correctly implement the following statement +from specification: + +http://www.opengroup.org/ +onlinepubs/007908799/xsh/pthread_cond_wait.html + +"These functions atomically release mutex and cause +the calling thread to block on the condition variable +cond; atomically here means "atomically with respect +to access by another thread to the mutex and then the +condition variable". That is, if another thread is +able to acquire the mutex after the about-to-block +thread has released it, then a subsequent call to +pthread_cond_signal() or pthread_cond_broadcast() +in that thread behaves as if it were issued after +the about-to-block thread has blocked." + +Question: Am I right? + +(I produced the program output above by simply +adding ?Sleep( 1 )?: + +================ +waiting threads: +================ + +{ /** Critical Section + + inc cond.waiters_count + +} + + /* + /* Atomic only if using Win32 SignalObjectAndWait + /* + cond.mtx.release + +Sleep( 1 ); // Win32 + + /*** ^^-- A THREAD WHICH DID SIGNAL MAY ACQUIRE THE MUTEX, + /*** GO INTO WAIT ON THE SAME CONDITION AND OVERTAKE + /*** ORIGINAL WAITER(S) CONSUMING ITS OWN SIGNAL! + + cond.sem.wait + +to the source code of pthread-win32 implementation: + +http://sources.redhat.com/cgi-bin/cvsweb.cgi/pthreads/ +condvar.c?rev=1.36&content-type=text/ +x-cvsweb-markup&cvsroot=pthreads-win32 + + + /* + * We keep the lock held just long enough to increment the count of + * waiters by one (above). + * Note that we can't keep it held across the + * call to sem_wait since that will deadlock other calls + * to pthread_cond_signal + */ + cleanup_args.mutexPtr = mutex; + cleanup_args.cv = cv; + cleanup_args.resultPtr = &result; + + pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) +&cleanup_args); + + if ((result = pthread_mutex_unlock (mutex)) == 0) + {((result +Sleep( 1 ); // @AT + + /* + * Wait to be awakened by + * pthread_cond_signal, or + * pthread_cond_broadcast, or + * a timeout + * + * Note: + * ptw32_sem_timedwait is a cancelation point, + * hence providing the + * mechanism for making pthread_cond_wait a cancelation + * point. We use the cleanup mechanism to ensure we + * re-lock the mutex and decrement the waiters count + * if we are canceled. + */ + if (ptw32_sem_timedwait (&(cv->sema), abstime) == -1) { + result = errno; + } + } + + pthread_cleanup_pop (1); /* Always cleanup */ + + +BTW, on my system (2 CPUs) I can manage to get +signals lost even without any source code modification +if I run the tennis program many times in different +shell sessions. +. +. +. +David Schwartz wrote: +>terekhov@my-deja.com wrote: +> +>> well, it might be that the program is in fact buggy. +>> but you did not show me any bug. +> +>You're right. I was close but not dead on. I was correct, however, +>that the code is buggy because it uses 'pthread_cond_signal' even +>though not any thread waiting on the condition variable can do the +>job. I was wrong in which thread could be waiting on the cv but +>unable to do the job. + +Okay, lets change 'pthread_cond_signal' to 'pthread_cond_broadcast' +but also add some noise from main() right before declaring the game +to be over (I need it in order to demonstrate another problem of +pthread-win32/ACE implementations - broadcast deadlock)... +. +. +. +It is my understanding of POSIX conditions, +that on correct implementation added noise +in form of unnecessary broadcasts from main, +should not break the tennis program. The +only 'side effect' of added noise on correct +implementation would be 'spurious wakeups' of +players (in fact they are not spurious, +players just see them as spurious) unblocked, +not by another player but by main before +another player had a chance to acquire the +mutex and change the game state variable: +. +. +. + +PLAYER-B + +PLAYER-A + +---Noise ON... + +PLAYER-B + +PLAYER-A + +. +. +. + +PLAYER-B + +PLAYER-A + +----PLAYER-A: SPURIOUS WAKEUP!!! + +PLAYER-B + +PLAYER-A + +---Noise OFF + +PLAYER-B + +---Stopping the game... + +PLAYER-A GONE + +PLAYER-B GONE + +GAME OVER + +H:\SA\UXX\pt\PTHREADS\TESTS> + +On pthread-win32/ACE implementations the +program could stall: + +. +. +. + +PLAYER-A + +PLAYER-B + +PLAYER-A + +PLAYER-B + +PLAYER-A + +PLAYER-B + +PLAYER-A + +PLAYER-B + +---Noise ON... + +PLAYER-A + +---Noise OFF +^C +H:\SA\UXX\pt\PTHREADS\TESTS> + + +The implementation has problems: + +================ +waiting threads: +================ + +{ /** Critical Section + + inc cond.waiters_count + +} + + /* + /* Atomic only if using Win32 SignalObjectAndWait + /* + cond.mtx.release + cond.sem.wait + + /*** ^^-- WAITER CAN BE PREEMPTED AFTER BEING UNBLOCKED... + +{ /** Critical Section + + dec cond.waiters_count + + /*** ^^- ...AND BEFORE DECREMENTING THE COUNT (1) + + last_waiter = ( cond.was_broadcast && + cond.waiters_count == 0 ) + + if ( last_waiter ) + + cond.was_broadcast = FALSE + + endif + +} + + if ( last_waiter ) + + /* + /* Atomic only if using Win32 SignalObjectAndWait + /* + cond.auto_reset_event_or_sem.post /* Event for Win32 + cond.mtx.acquire + + /*** ^^-- ...AND BEFORE CALL TO mtx.acquire (2) + + /*** ^^-- NESTED BROADCASTS RESULT IN A DEADLOCK + + + else + + cond.mtx.acquire + + /*** ^^-- ...AND BEFORE CALL TO mtx.acquire (3) + + endif + + +================== +broadcast threads: +================== + +{ /** Critical Section + + waiters_count = cond.waiters_count + + if ( waiters_count != 0 ) + + cond.was_broadcast = TRUE + + endif + +} + +if ( waiters_count != 0 ) + + cond.sem.post waiters_count + + /*** ^^^^^--- SPURIOUS WAKEUPS DUE TO (1) + + cond.auto_reset_event_or_sem.wait /* Event for Win32 + + /*** ^^^^^--- DEADLOCK FOR FURTHER BROADCASTS IF THEY + HAPPEN TO GO INTO WAIT WHILE PREVIOUS + BROADCAST IS STILL IN PROGRESS/WAITING + +endif + +a) cond.waiters_count does not accurately reflect +number of waiters blocked on semaphore - that could +result (in the time window when counter is not accurate) +in spurios wakeups organised by subsequent _signals +and _broadcasts. From standard compliance point of view +that is OK but that could be a real problem from +performance/efficiency point of view. + +b) If subsequent broadcast happen to go into wait on +cond.auto_reset_event_or_sem before previous +broadcast was unblocked from cond.auto_reset_event_or_sem +by its last waiter, one of two blocked threads will +remain blocked because last_waiter processing code +fails to unblock both threads. + +In the situation with tennisb.c the Player-B was put +in a deadlock by noise (broadcast) coming from main +thread. And since Player-B holds the game state +mutex when it calls broadcast, the whole program +stalled: Player-A was deadlocked on mutex and +main thread after finishing with producing the noise +was deadlocked on mutex too (needed to declare the +game over) + +(I produced the program output above by simply +adding ?Sleep( 1 )?: + +================== +broadcast threads: +================== + +{ /** Critical Section + + waiters_count = cond.waiters_count + + if ( waiters_count != 0 ) + + cond.was_broadcast = TRUE + + endif + +} + +if ( waiters_count != 0 ) + +Sleep( 1 ); //Win32 + + cond.sem.post waiters_count + + /*** ^^^^^--- SPURIOUS WAKEUPS DUE TO (1) + + cond.auto_reset_event_or_sem.wait /* Event for Win32 + + /*** ^^^^^--- DEADLOCK FOR FURTHER BROADCASTS IF THEY + HAPPEN TO GO INTO WAIT WHILE PREVIOUS + BROADCAST IS STILL IN PROGRESS/WAITING + +endif + +to the source code of pthread-win32 implementation: + +http://sources.redhat.com/cgi-bin/cvsweb.cgi/pthreads/ +condvar.c?rev=1.36&content-type=text/ +x-cvsweb-markup&cvsroot=pthreads-win32 + + if (wereWaiters) + {(wereWaiters)sroot=pthreads-win32eb.cgi/pthreads/Yem...m + /* + * Wake up all waiters + */ + +Sleep( 1 ); //@AT + +#ifdef NEED_SEM + + result = (ptw32_increase_semaphore( &cv->sema, cv->waiters ) + ? 0 + : EINVAL); + +#else /* NEED_SEM */ + + result = (ReleaseSemaphore( cv->sema, cv->waiters, NULL ) + ? 0 + : EINVAL); + +#endif /* NEED_SEM */ + + } + + (void) pthread_mutex_unlock(&(cv->waitersLock)); + + if (wereWaiters && result == 0) + {(wereWaiters + /* + * Wait for all the awakened threads to acquire their part of + * the counting semaphore + */ + + if (WaitForSingleObject (cv->waitersDone, INFINITE) + == WAIT_OBJECT_0) + { + result = 0; + } + else + { + result = EINVAL; + } + + } + + return (result); + +} + +BTW, on my system (2 CPUs) I can manage to get +the program stalled even without any source code +modification if I run the tennisb program many +times in different shell sessions. + +=================== +pthread-win32 patch +=================== +struct pthread_cond_t_ { + long nWaitersBlocked; /* Number of threads blocked +*/ + long nWaitersUnblocked; /* Number of threads unblocked +*/ + long nWaitersToUnblock; /* Number of threads to unblock +*/ + sem_t semBlockQueue; /* Queue up threads waiting for the +*/ + /* condition to become signalled +*/ + sem_t semBlockLock; /* Semaphore that guards access to +*/ + /* | waiters blocked count/block queue +*/ + /* +-> Mandatory Sync.LEVEL-1 +*/ + pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to +*/ + /* | waiters (to)unblock(ed) counts +*/ + /* +-> Optional* Sync.LEVEL-2 +*/ +}; /* Opt*) for _timedwait and +cancellation*/ + +int +pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr) + int result = EAGAIN; + pthread_cond_t cv = NULL; + + if (cond == NULL) + {(cond + return EINVAL; + } + + if ((attr != NULL && *attr != NULL) && + ((*attr)->pshared == PTHREAD_PROCESS_SHARED)) + { + /* + * Creating condition variable that can be shared between + * processes. + */ + result = ENOSYS; + + goto FAIL0; + } + + cv = (pthread_cond_t) calloc (1, sizeof (*cv)); + + if (cv == NULL) + {(cv + result = ENOMEM; + goto FAIL0; + } + + cv->nWaitersBlocked = 0; + cv->nWaitersUnblocked = 0; + cv->nWaitersToUnblock = 0; + + if (sem_init (&(cv->semBlockLock), 0, 1) != 0) + {(sem_init + goto FAIL0; + } + + if (sem_init (&(cv->semBlockQueue), 0, 0) != 0) + {(sem_init + goto FAIL1; + } + + if (pthread_mutex_init (&(cv->mtxUnblockLock), 0) != 0) + {(pthread_mutex_init + goto FAIL2; + } + + + result = 0; + + goto DONE; + + /* + * ------------- + * Failed... + * ------------- + */ +FAIL2: + (void) sem_destroy (&(cv->semBlockQueue)); + +FAIL1: + (void) sem_destroy (&(cv->semBlockLock)); + +FAIL0: +DONE: + *cond = cv; + + return (result); + +} /* pthread_cond_init */ + +int +pthread_cond_destroy (pthread_cond_t * cond) +{ + int result = 0; + pthread_cond_t cv; + + /* + * Assuming any race condition here is harmless. + */ + if (cond == NULL + || *cond == NULL) + { + return EINVAL; + } + + if (*cond != (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) + {(*cond + cv = *cond; + + /* + * Synchronize access to waiters blocked count (LEVEL-1) + */ + if (sem_wait(&(cv->semBlockLock)) != 0) + {(sem_wait(&(cv->semBlockLock)) + return errno; + } + + /* + * Synchronize access to waiters (to)unblock(ed) counts (LEVEL-2) + */ + if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0) + {((result + (void) sem_post(&(cv->semBlockLock)); + return result; + } + + /* + * Check whether cv is still busy (still has waiters blocked) + */ + if (cv->nWaitersBlocked - cv->nWaitersUnblocked > 0) + {(cv->nWaitersBlocked + (void) sem_post(&(cv->semBlockLock)); + (void) pthread_mutex_unlock(&(cv->mtxUnblockLock)); + return EBUSY; + } + + /* + * Now it is safe to destroy + */ + (void) sem_destroy (&(cv->semBlockLock)); + (void) sem_destroy (&(cv->semBlockQueue)); + (void) pthread_mutex_unlock (&(cv->mtxUnblockLock)); + (void) pthread_mutex_destroy (&(cv->mtxUnblockLock)); + + free(cv); + *cond = NULL; + } + else + { + /* + * See notes in ptw32_cond_check_need_init() above also. + */ + EnterCriticalSection(&ptw32_cond_test_init_lock); + + /* + * Check again. + */ + if (*cond == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) + {(*cond + /* + * This is all we need to do to destroy a statically + * initialised cond that has not yet been used (initialised). + * If we get to here, another thread + * waiting to initialise this cond will get an EINVAL. + */ + *cond = NULL; + } + else + { + /* + * The cv has been initialised while we were waiting + * so assume it's in use. + */ + result = EBUSY; + } + + LeaveCriticalSection(&ptw32_cond_test_init_lock); + } + + return (result); +} + +/* + * Arguments for cond_wait_cleanup, since we can only pass a + * single void * to it. + */ +typedef struct { + pthread_mutex_t * mutexPtr; + pthread_cond_t cv; + int * resultPtr; +} ptw32_cond_wait_cleanup_args_t; + +static void +ptw32_cond_wait_cleanup(void * args) +{ + ptw32_cond_wait_cleanup_args_t * cleanup_args = +(ptw32_cond_wait_cleanup_args_t *) args; + pthread_cond_t cv = cleanup_args->cv; + int * resultPtr = cleanup_args->resultPtr; + int eLastSignal; /* enum: 1=yes 0=no -1=cancelled/timedout w/o signal(s) +*/ + int result; + + /* + * Whether we got here as a result of signal/broadcast or because of + * timeout on wait or thread cancellation we indicate that we are no + * longer waiting. The waiter is responsible for adjusting waiters + * (to)unblock(ed) counts (protected by unblock lock). + * Unblock lock/Sync.LEVEL-2 supports _timedwait and cancellation. + */ + if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0) + {((result + *resultPtr = result; + return; + } + + cv->nWaitersUnblocked++; + + eLastSignal = (cv->nWaitersToUnblock == 0) ? + -1 : (--cv->nWaitersToUnblock == 0); + + /* + * No more LEVEL-2 access to waiters (to)unblock(ed) counts needed + */ + if ((result = pthread_mutex_unlock(&(cv->mtxUnblockLock))) != 0) + {((result + *resultPtr = result; + return; + } + + /* + * If last signal... + */ + if (eLastSignal == 1) + {(eLastSignal + /* + * ...it means that we have end of 'atomic' signal/broadcast + */ + if (sem_post(&(cv->semBlockLock)) != 0) + {(sem_post(&(cv->semBlockLock)) + *resultPtr = errno; + return; + } + } + /* + * If not last signal and not timed out/cancelled wait w/o signal... + */ + else if (eLastSignal == 0) + { + /* + * ...it means that next waiter can go through semaphore + */ + if (sem_post(&(cv->semBlockQueue)) != 0) + {(sem_post(&(cv->semBlockQueue)) + *resultPtr = errno; + return; + } + } + + /* + * XSH: Upon successful return, the mutex has been locked and is owned + * by the calling thread + */ + if ((result = pthread_mutex_lock(cleanup_args->mutexPtr)) != 0) + {((result + *resultPtr = result; + } + +} /* ptw32_cond_wait_cleanup */ + +static int +ptw32_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime) +{ + int result = 0; + pthread_cond_t cv; + ptw32_cond_wait_cleanup_args_t cleanup_args; + + if (cond == NULL || *cond == NULL) + {(cond + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static condition variable. We check + * again inside the guarded section of ptw32_cond_check_need_init() + * to avoid race conditions. + */ + if (*cond == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) + {(*cond + result = ptw32_cond_check_need_init(cond); + } + + if (result != 0 && result != EBUSY) + {(result + return result; + } + + cv = *cond; + + /* + * Synchronize access to waiters blocked count (LEVEL-1) + */ + if (sem_wait(&(cv->semBlockLock)) != 0) + {(sem_wait(&(cv->semBlockLock)) + return errno; + } + + cv->nWaitersBlocked++; + + /* + * Thats it. Counted means waiting, no more access needed + */ + if (sem_post(&(cv->semBlockLock)) != 0) + {(sem_post(&(cv->semBlockLock)) + return errno; + } + + /* + * Setup this waiter cleanup handler + */ + cleanup_args.mutexPtr = mutex; + cleanup_args.cv = cv; + cleanup_args.resultPtr = &result; + + pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args); + + /* + * Now we can release 'mutex' and... + */ + if ((result = pthread_mutex_unlock (mutex)) == 0) + {((result + + /* + * ...wait to be awakened by + * pthread_cond_signal, or + * pthread_cond_broadcast, or + * timeout, or + * thread cancellation + * + * Note: + * + * ptw32_sem_timedwait is a cancellation point, + * hence providing the mechanism for making + * pthread_cond_wait a cancellation point. + * We use the cleanup mechanism to ensure we + * re-lock the mutex and adjust (to)unblock(ed) waiters + * counts if we are cancelled, timed out or signalled. + */ + if (ptw32_sem_timedwait (&(cv->semBlockQueue), abstime) != 0) + {(ptw32_sem_timedwait + result = errno; + } + } + + /* + * Always cleanup + */ + pthread_cleanup_pop (1); + + + /* + * "result" can be modified by the cleanup handler. + */ + return (result); + +} /* ptw32_cond_timedwait */ + + +static int +ptw32_cond_unblock (pthread_cond_t * cond, + int unblockAll) +{ + int result; + pthread_cond_t cv; + + if (cond == NULL || *cond == NULL) + {(cond + return EINVAL; + } + + cv = *cond; + + /* + * No-op if the CV is static and hasn't been initialised yet. + * Assuming that any race condition is harmless. + */ + if (cv == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) + {(cv + return 0; + } + + /* + * Synchronize access to waiters blocked count (LEVEL-1) + */ + if (sem_wait(&(cv->semBlockLock)) != 0) + {(sem_wait(&(cv->semBlockLock)) + return errno; + } + + /* + * Synchronize access to waiters (to)unblock(ed) counts (LEVEL-2) + * This sync.level supports _timedwait and cancellation + */ + if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0) + {((result + return result; + } + + /* + * Adjust waiters blocked and unblocked counts (collect garbage) + */ + if (cv->nWaitersUnblocked != 0) + {(cv->nWaitersUnblocked + cv->nWaitersBlocked -= cv->nWaitersUnblocked; + cv->nWaitersUnblocked = 0; + } + + /* + * If (after adjustment) there are still some waiters blocked counted... + */ + if ( cv->nWaitersBlocked > 0) + {( + /* + * We will unblock first waiter and leave semBlockLock/LEVEL-1 locked + * LEVEL-1 access is left disabled until last signal/unblock +completes + */ + cv->nWaitersToUnblock = (unblockAll) ? cv->nWaitersBlocked : 1; + + /* + * No more LEVEL-2 access to waiters (to)unblock(ed) counts needed + * This sync.level supports _timedwait and cancellation + */ + if ((result = pthread_mutex_unlock(&(cv->mtxUnblockLock))) != 0) + {((result + return result; + } + + + /* + * Now, with LEVEL-2 lock released let first waiter go through +semaphore + */ + if (sem_post(&(cv->semBlockQueue)) != 0) + {(sem_post(&(cv->semBlockQueue)) + return errno; + } + } + /* + * No waiter blocked - no more LEVEL-1 access to blocked count needed... + */ + else if (sem_post(&(cv->semBlockLock)) != 0) + { + return errno; + } + /* + * ...and no more LEVEL-2 access to waiters (to)unblock(ed) counts needed +too + * This sync.level supports _timedwait and cancellation + */ + else + { + result = pthread_mutex_unlock(&(cv->mtxUnblockLock)); + } + + return(result); + +} /* ptw32_cond_unblock */ + +int +pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex) +{ + /* The NULL abstime arg means INFINITE waiting. */ + return(ptw32_cond_timedwait(cond, mutex, NULL)); +} /* pthread_cond_wait */ + + +int +pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime) +{ + if (abstime == NULL) + {(abstime + return EINVAL; + } + + return(ptw32_cond_timedwait(cond, mutex, abstime)); +} /* pthread_cond_timedwait */ + + +int +pthread_cond_signal (pthread_cond_t * cond) +{ + /* The '0'(FALSE) unblockAll arg means unblock ONE waiter. */ + return(ptw32_cond_unblock(cond, 0)); +} /* pthread_cond_signal */ + +int +pthread_cond_broadcast (pthread_cond_t * cond) +{ + /* The '1'(TRUE) unblockAll arg means unblock ALL waiters. */ + return(ptw32_cond_unblock(cond, 1)); +} /* pthread_cond_broadcast */ + + + + +TEREKHOV@de.ibm.com on 17.01.2001 01:00:57 + +Please respond to TEREKHOV@de.ibm.com + +To: pthreads-win32@sourceware.cygnus.com +cc: schmidt@uci.edu +Subject: win32 conditions: sem+counter+event = broadcast_deadlock + + spur.wakeup/unfairness/incorrectness ?? + + + + + + + +Hi, + +Problem 1: broadcast_deadlock + +It seems that current implementation does not provide "atomic" +broadcasts. That may lead to "nested" broadcasts... and it seems +that nested case is not handled correctly -> producing a broadcast +DEADLOCK as a result. + +Scenario: + +N (>1) waiting threads W1..N are blocked (in _wait) on condition's +semaphore. + +Thread B1 calls pthread_cond_broadcast, which results in "releasing" N +W threads via incrementing semaphore counter by N (stored in +cv->waiters) BUT cv->waiters counter does not change!! The caller +thread B1 remains blocked on cv->waitersDone event (auto-reset!!) BUT +condition is not protected from starting another broadcast (when called +on another thread) while still waiting for the "old" broadcast to +complete on thread B1. + +M (>=0, waiters counter. + +L (N-M) "late" waiter W threads are a) still blocked/not returned from +their semaphore wait call or b) were preempted after sem_wait but before +lock( &cv->waitersLock ) or c) are blocked on cv->waitersLock. + +cv->waiters is still > 0 (= L). + +Another thread B2 (or some W thread from M group) calls +pthread_cond_broadcast and gains access to counter... neither a) nor b) +prevent thread B2 in pthread_cond_broadcast from gaining access to +counter and starting another broadcast ( for c) - it depends on +cv->waitersLock scheduling rules: FIFO=OK, PRTY=PROBLEM,... ) + +That call to pthread_cond_broadcast (on thread B2) will result in +incrementing semaphore by cv->waiters (=L) which is INCORRECT (all +W1..N were in fact already released by thread B1) and waiting on +_auto-reset_ event cv->waitersDone which is DEADLY WRONG (produces a +deadlock)... + +All late W1..L threads now have a chance to complete their _wait call. +Last W_L thread sets an auto-reselt event cv->waitersDone which will +release either B1 or B2 leaving one of B threads in a deadlock. + +Problem 2: spur.wakeup/unfairness/incorrectness + +It seems that: + +a) because of the same problem with counter which does not reflect the +actual number of NOT RELEASED waiters, the signal call may increment +a semaphore counter w/o having a waiter blocked on it. That will result +in (best case) spurious wake ups - performance degradation due to +unnecessary context switches and predicate re-checks and (in worth case) +unfairness/incorrectness problem - see b) + +b) neither signal nor broadcast prevent other threads - "new waiters" +(and in the case of signal, the caller thread as well) from going into +_wait and overtaking "old" waiters (already released but still not returned +from sem_wait on condition's semaphore). Win semaphore just [API DOC]: +"Maintains a count between zero and some maximum value, limiting the number +of threads that are simultaneously accessing a shared resource." Calling +ReleaseSemaphore does not imply (at least not documented) that on return +from ReleaseSemaphore all waiters will in fact become released (returned +from their Wait... call) and/or that new waiters calling Wait... afterwards +will become less importance. It is NOT documented to be an atomic release +of +waiters... And even if it would be there is still a problem with a thread +being preempted after Wait on semaphore and before Wait on cv->waitersLock +and scheduling rules for cv->waitersLock itself +(??WaitForMultipleObjects??) +That may result in unfairness/incorrectness problem as described +for SetEvent impl. in "Strategies for Implementing POSIX Condition +Variables +on Win32": http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + +Unfairness -- The semantics of the POSIX pthread_cond_broadcast function is +to wake up all threads currently blocked in wait calls on the condition +variable. The awakened threads then compete for the external_mutex. To +ensure +fairness, all of these threads should be released from their +pthread_cond_wait calls and allowed to recheck their condition expressions +before other threads can successfully complete a wait on the condition +variable. + +Unfortunately, the SetEvent implementation above does not guarantee that +all +threads sleeping on the condition variable when cond_broadcast is called +will +acquire the external_mutex and check their condition expressions. Although +the Pthreads specification does not mandate this degree of fairness, the +lack of fairness can cause starvation. + +To illustrate the unfairness problem, imagine there are 2 threads, C1 and +C2, +that are blocked in pthread_cond_wait on condition variable not_empty_ that +is guarding a thread-safe message queue. Another thread, P1 then places two +messages onto the queue and calls pthread_cond_broadcast. If C1 returns +from +pthread_cond_wait, dequeues and processes the message, and immediately +waits +again then it and only it may end up acquiring both messages. Thus, C2 will +never get a chance to dequeue a message and run. + +The following illustrates the sequence of events: + +1. Thread C1 attempts to dequeue and waits on CV non_empty_ +2. Thread C2 attempts to dequeue and waits on CV non_empty_ +3. Thread P1 enqueues 2 messages and broadcasts to CV not_empty_ +4. Thread P1 exits +5. Thread C1 wakes up from CV not_empty_, dequeues a message and runs +6. Thread C1 waits again on CV not_empty_, immediately dequeues the 2nd + message and runs +7. Thread C1 exits +8. Thread C2 is the only thread left and blocks forever since + not_empty_ will never be signaled + +Depending on the algorithm being implemented, this lack of fairness may +yield +concurrent programs that have subtle bugs. Of course, application +developers +should not rely on the fairness semantics of pthread_cond_broadcast. +However, +there are many cases where fair implementations of condition variables can +simplify application code. + +Incorrectness -- A variation on the unfairness problem described above +occurs +when a third consumer thread, C3, is allowed to slip through even though it +was not waiting on condition variable not_empty_ when a broadcast occurred. + +To illustrate this, we will use the same scenario as above: 2 threads, C1 +and +C2, are blocked dequeuing messages from the message queue. Another thread, +P1 +then places two messages onto the queue and calls pthread_cond_broadcast. +C1 +returns from pthread_cond_wait, dequeues and processes the message. At this +time, C3 acquires the external_mutex, calls pthread_cond_wait and waits on +the events in WaitForMultipleObjects. Since C2 has not had a chance to run +yet, the BROADCAST event is still signaled. C3 then returns from +WaitForMultipleObjects, and dequeues and processes the message in the +queue. +Thus, C2 will never get a chance to dequeue a message and run. + +The following illustrates the sequence of events: + +1. Thread C1 attempts to dequeue and waits on CV non_empty_ +2. Thread C2 attempts to dequeue and waits on CV non_empty_ +3. Thread P1 enqueues 2 messages and broadcasts to CV not_empty_ +4. Thread P1 exits +5. Thread C1 wakes up from CV not_empty_, dequeues a message and runs +6. Thread C1 exits +7. Thread C3 waits on CV not_empty_, immediately dequeues the 2nd + message and runs +8. Thread C3 exits +9. Thread C2 is the only thread left and blocks forever since + not_empty_ will never be signaled + +In the above case, a thread that was not waiting on the condition variable +when a broadcast occurred was allowed to proceed. This leads to incorrect +semantics for a condition variable. + + +COMMENTS??? + +regards, +alexander. + +----------------------------------------------------------------------------- + +Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* + implementation questions +Date: Wed, 21 Feb 2001 11:54:47 +0100 +From: TEREKHOV@de.ibm.com +To: lthomas@arbitrade.com +CC: rpj@ise.canberra.edu.au, Thomas Pfaff , + Nanbor Wang + +Hi Louis, + +generation number 8.. + +had some time to revisit timeouts/spurious wakeup problem.. +found some bugs (in 7.b/c/d) and something to improve +(7a - using IPC semaphores but it should speedup Win32 +version as well). + +regards, +alexander. + +---------- Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL ------ +given: +semBlockLock - bin.semaphore +semBlockQueue - semaphore +mtxExternal - mutex or CS +mtxUnblockLock - mutex or CS +nWaitersGone - int +nWaitersBlocked - int +nWaitersToUnblock - int + +wait( timeout ) { + + [auto: register int result ] // error checking omitted + [auto: register int nSignalsWasLeft ] + [auto: register int nWaitersWasGone ] + + sem_wait( semBlockLock ); + nWaitersBlocked++; + sem_post( semBlockLock ); + + unlock( mtxExternal ); + bTimedOut = sem_wait( semBlockQueue,timeout ); + + lock( mtxUnblockLock ); + if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { + if ( bTimeout ) { // timeout (or canceled) + if ( 0 != nWaitersBlocked ) { + nWaitersBlocked--; + } + else { + nWaitersGone++; // count spurious wakeups + } + } + if ( 0 == --nWaitersToUnblock ) { + if ( 0 != nWaitersBlocked ) { + sem_post( semBlockLock ); // open the gate + nSignalsWasLeft = 0; // do not open the gate below +again + } + else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { + nWaitersGone = 0; + } + } + } + else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious +semaphore :-) + sem_wait( semBlockLock ); + nWaitersBlocked -= nWaitersGone; // something is going on here - +test of timeouts? :-) + sem_post( semBlockLock ); + nWaitersGone = 0; + } + unlock( mtxUnblockLock ); + + if ( 1 == nSignalsWasLeft ) { + if ( 0 != nWaitersWasGone ) { + // sem_adjust( -nWaitersWasGone ); + while ( nWaitersWasGone-- ) { + sem_wait( semBlockLock ); // better now than spurious +later + } + } + sem_post( semBlockLock ); // open the gate + } + + lock( mtxExternal ); + + return ( bTimedOut ) ? ETIMEOUT : 0; +} + +signal(bAll) { + + [auto: register int result ] + [auto: register int nSignalsToIssue] + + lock( mtxUnblockLock ); + + if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! + if ( 0 == nWaitersBlocked ) { // NO-OP + return unlock( mtxUnblockLock ); + } + if (bAll) { + nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; + nWaitersBlocked = 0; + } + else { + nSignalsToIssue = 1; + nWaitersToUnblock++; + nWaitersBlocked--; + } + } + else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! + sem_wait( semBlockLock ); // close the gate + if ( 0 != nWaitersGone ) { + nWaitersBlocked -= nWaitersGone; + nWaitersGone = 0; + } + if (bAll) { + nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; + nWaitersBlocked = 0; + } + else { + nSignalsToIssue = nWaitersToUnblock = 1; + nWaitersBlocked--; + } + } + else { // NO-OP + return unlock( mtxUnblockLock ); + } + + unlock( mtxUnblockLock ); + sem_post( semBlockQueue,nSignalsToIssue ); + return result; +} + +---------- Algorithm 8b / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ONEBYONE +------ +given: +semBlockLock - bin.semaphore +semBlockQueue - bin.semaphore +mtxExternal - mutex or CS +mtxUnblockLock - mutex or CS +nWaitersGone - int +nWaitersBlocked - int +nWaitersToUnblock - int + +wait( timeout ) { + + [auto: register int result ] // error checking omitted + [auto: register int nWaitersWasGone ] + [auto: register int nSignalsWasLeft ] + + sem_wait( semBlockLock ); + nWaitersBlocked++; + sem_post( semBlockLock ); + + unlock( mtxExternal ); + bTimedOut = sem_wait( semBlockQueue,timeout ); + + lock( mtxUnblockLock ); + if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { + if ( bTimeout ) { // timeout (or canceled) + if ( 0 != nWaitersBlocked ) { + nWaitersBlocked--; + nSignalsWasLeft = 0; // do not unblock next waiter +below (already unblocked) + } + else { + nWaitersGone = 1; // spurious wakeup pending!! + } + } + if ( 0 == --nWaitersToUnblock && + if ( 0 != nWaitersBlocked ) { + sem_post( semBlockLock ); // open the gate + nSignalsWasLeft = 0; // do not open the gate below +again + } + else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { + nWaitersGone = 0; + } + } + } + else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious +semaphore :-) + sem_wait( semBlockLock ); + nWaitersBlocked -= nWaitersGone; // something is going on here - +test of timeouts? :-) + sem_post( semBlockLock ); + nWaitersGone = 0; + } + unlock( mtxUnblockLock ); + + if ( 1 == nSignalsWasLeft ) { + if ( 0 != nWaitersWasGone ) { + // sem_adjust( -1 ); + sem_wait( semBlockQueue ); // better now than spurious +later + } + sem_post( semBlockLock ); // open the gate + } + else if ( 0 != nSignalsWasLeft ) { + sem_post( semBlockQueue ); // unblock next waiter + } + + lock( mtxExternal ); + + return ( bTimedOut ) ? ETIMEOUT : 0; +} + +signal(bAll) { + + [auto: register int result ] + + lock( mtxUnblockLock ); + + if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! + if ( 0 == nWaitersBlocked ) { // NO-OP + return unlock( mtxUnblockLock ); + } + if (bAll) { + nWaitersToUnblock += nWaitersBlocked; + nWaitersBlocked = 0; + } + else { + nWaitersToUnblock++; + nWaitersBlocked--; + } + unlock( mtxUnblockLock ); + } + else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! + sem_wait( semBlockLock ); // close the gate + if ( 0 != nWaitersGone ) { + nWaitersBlocked -= nWaitersGone; + nWaitersGone = 0; + } + if (bAll) { + nWaitersToUnblock = nWaitersBlocked; + nWaitersBlocked = 0; + } + else { + nWaitersToUnblock = 1; + nWaitersBlocked--; + } + unlock( mtxUnblockLock ); + sem_post( semBlockQueue ); + } + else { // NO-OP + unlock( mtxUnblockLock ); + } + + return result; +} + +---------- Algorithm 8c / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ONEBYONE +--------- +given: +hevBlockLock - auto-reset event +hevBlockQueue - auto-reset event +mtxExternal - mutex or CS +mtxUnblockLock - mutex or CS +nWaitersGone - int +nWaitersBlocked - int +nWaitersToUnblock - int + +wait( timeout ) { + + [auto: register int result ] // error checking omitted + [auto: register int nSignalsWasLeft ] + [auto: register int nWaitersWasGone ] + + wait( hevBlockLock,INFINITE ); + nWaitersBlocked++; + set_event( hevBlockLock ); + + unlock( mtxExternal ); + bTimedOut = wait( hevBlockQueue,timeout ); + + lock( mtxUnblockLock ); + if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) { + if ( bTimeout ) { // timeout (or canceled) + if ( 0 != nWaitersBlocked ) { + nWaitersBlocked--; + nSignalsWasLeft = 0; // do not unblock next waiter +below (already unblocked) + } + else { + nWaitersGone = 1; // spurious wakeup pending!! + } + } + if ( 0 == --nWaitersToUnblock ) + if ( 0 != nWaitersBlocked ) { + set_event( hevBlockLock ); // open the gate + nSignalsWasLeft = 0; // do not open the gate below +again + } + else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { + nWaitersGone = 0; + } + } + } + else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious +event :-) + wait( hevBlockLock,INFINITE ); + nWaitersBlocked -= nWaitersGone; // something is going on here - +test of timeouts? :-) + set_event( hevBlockLock ); + nWaitersGone = 0; + } + unlock( mtxUnblockLock ); + + if ( 1 == nSignalsWasLeft ) { + if ( 0 != nWaitersWasGone ) { + reset_event( hevBlockQueue ); // better now than spurious +later + } + set_event( hevBlockLock ); // open the gate + } + else if ( 0 != nSignalsWasLeft ) { + set_event( hevBlockQueue ); // unblock next waiter + } + + lock( mtxExternal ); + + return ( bTimedOut ) ? ETIMEOUT : 0; +} + +signal(bAll) { + + [auto: register int result ] + + lock( mtxUnblockLock ); + + if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! + if ( 0 == nWaitersBlocked ) { // NO-OP + return unlock( mtxUnblockLock ); + } + if (bAll) { + nWaitersToUnblock += nWaitersBlocked; + nWaitersBlocked = 0; + } + else { + nWaitersToUnblock++; + nWaitersBlocked--; + } + unlock( mtxUnblockLock ); + } + else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! + wait( hevBlockLock,INFINITE ); // close the gate + if ( 0 != nWaitersGone ) { + nWaitersBlocked -= nWaitersGone; + nWaitersGone = 0; + } + if (bAll) { + nWaitersToUnblock = nWaitersBlocked; + nWaitersBlocked = 0; + } + else { + nWaitersToUnblock = 1; + nWaitersBlocked--; + } + unlock( mtxUnblockLock ); + set_event( hevBlockQueue ); + } + else { // NO-OP + unlock( mtxUnblockLock ); + } + + return result; +} + +---------- Algorithm 8d / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ALL ------ +given: +hevBlockLock - auto-reset event +hevBlockQueueS - auto-reset event // for signals +hevBlockQueueB - manual-reset even // for broadcasts +mtxExternal - mutex or CS +mtxUnblockLock - mutex or CS +eBroadcast - int // 0: no broadcast, 1: broadcast, 2: +broadcast after signal(s) +nWaitersGone - int +nWaitersBlocked - int +nWaitersToUnblock - int + +wait( timeout ) { + + [auto: register int result ] // error checking omitted + [auto: register int eWasBroadcast ] + [auto: register int nSignalsWasLeft ] + [auto: register int nWaitersWasGone ] + + wait( hevBlockLock,INFINITE ); + nWaitersBlocked++; + set_event( hevBlockLock ); + + unlock( mtxExternal ); + bTimedOut = waitformultiple( hevBlockQueueS,hevBlockQueueB,timeout,ONE ); + + lock( mtxUnblockLock ); + if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) { + if ( bTimeout ) { // timeout (or canceled) + if ( 0 != nWaitersBlocked ) { + nWaitersBlocked--; + nSignalsWasLeft = 0; // do not unblock next waiter +below (already unblocked) + } + else if ( 1 != eBroadcast ) { + nWaitersGone = 1; + } + } + if ( 0 == --nWaitersToUnblock ) { + if ( 0 != nWaitersBlocked ) { + set_event( hevBlockLock ); // open the gate + nSignalsWasLeft = 0; // do not open the gate below +again + } + else { + if ( 0 != (eWasBroadcast = eBroadcast) ) { + eBroadcast = 0; + } + if ( 0 != (nWaitersWasGone = nWaitersGone ) { + nWaitersGone = 0; + } + } + } + else if ( 0 != eBroadcast ) { + nSignalsWasLeft = 0; // do not unblock next waiter +below (already unblocked) + } + } + else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious +event :-) + wait( hevBlockLock,INFINITE ); + nWaitersBlocked -= nWaitersGone; // something is going on here - +test of timeouts? :-) + set_event( hevBlockLock ); + nWaitersGone = 0; + } + unlock( mtxUnblockLock ); + + if ( 1 == nSignalsWasLeft ) { + if ( 0 != eWasBroadcast ) { + reset_event( hevBlockQueueB ); + } + if ( 0 != nWaitersWasGone ) { + reset_event( hevBlockQueueS ); // better now than spurious +later + } + set_event( hevBlockLock ); // open the gate + } + else if ( 0 != nSignalsWasLeft ) { + set_event( hevBlockQueueS ); // unblock next waiter + } + + lock( mtxExternal ); + + return ( bTimedOut ) ? ETIMEOUT : 0; +} + +signal(bAll) { + + [auto: register int result ] + [auto: register HANDLE hevBlockQueue ] + + lock( mtxUnblockLock ); + + if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! + if ( 0 == nWaitersBlocked ) { // NO-OP + return unlock( mtxUnblockLock ); + } + if (bAll) { + nWaitersToUnblock += nWaitersBlocked; + nWaitersBlocked = 0; + eBroadcast = 2; + hevBlockQueue = hevBlockQueueB; + } + else { + nWaitersToUnblock++; + nWaitersBlocked--; + return unlock( mtxUnblockLock ); + } + } + else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! + wait( hevBlockLock,INFINITE ); // close the gate + if ( 0 != nWaitersGone ) { + nWaitersBlocked -= nWaitersGone; + nWaitersGone = 0; + } + if (bAll) { + nWaitersToUnblock = nWaitersBlocked; + nWaitersBlocked = 0; + eBroadcast = 1; + hevBlockQueue = hevBlockQueueB; + } + else { + nWaitersToUnblock = 1; + nWaitersBlocked--; + hevBlockQueue = hevBlockQueueS; + } + } + else { // NO-OP + return unlock( mtxUnblockLock ); + } + + unlock( mtxUnblockLock ); + set_event( hevBlockQueue ); + return result; +} +---------------------- Forwarded by Alexander Terekhov/Germany/IBM on +02/21/2001 09:13 AM --------------------------- + +Alexander Terekhov +02/20/2001 04:33 PM + +To: Louis Thomas +cc: + +From: Alexander Terekhov/Germany/IBM@IBMDE +Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio + n questions +Importance: Normal + +>Sorry, gotta take a break and work on something else for a while. +>Real work +>calls, unfortunately. I'll get back to you in two or three days. + +ok. no problem. here is some more stuff for pauses you might have +in between :) + +---------- Algorithm 7d / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ALL ------ +given: +hevBlockLock - auto-reset event +hevBlockQueueS - auto-reset event // for signals +hevBlockQueueB - manual-reset even // for broadcasts +mtxExternal - mutex or CS +mtxUnblockLock - mutex or CS +bBroadcast - int +nWaitersGone - int +nWaitersBlocked - int +nWaitersToUnblock - int + +wait( timeout ) { + + [auto: register int result ] // error checking omitted + [auto: register int bWasBroadcast ] + [auto: register int nSignalsWasLeft ] + + wait( hevBlockLock,INFINITE ); + nWaitersBlocked++; + set_event( hevBlockLock ); + + unlock( mtxExternal ); + bTimedOut = waitformultiple( hevBlockQueueS,hevBlockQueueB,timeout,ONE ); + + lock( mtxUnblockLock ); + if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) { + if ( bTimeout ) { // timeout (or canceled) + if ( 0 != nWaitersBlocked ) { + nWaitersBlocked--; + nSignalsWasLeft = 0; // do not unblock next waiter +below (already unblocked) + } + else if ( !bBroadcast ) { + wait( hevBlockQueueS,INFINITE ); // better now than spurious +later + } + } + if ( 0 == --nWaitersToUnblock ) { + if ( 0 != nWaitersBlocked ) { + if ( bBroadcast ) { + reset_event( hevBlockQueueB ); + bBroadcast = false; + } + set_event( hevBlockLock ); // open the gate + nSignalsWasLeft = 0; // do not open the gate below +again + } + else if ( false != (bWasBroadcast = bBroadcast) ) { + bBroadcast = false; + } + } + else { + bWasBroadcast = bBroadcast; + } + } + else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious +event :-) + wait( hevBlockLock,INFINITE ); + nWaitersBlocked -= nWaitersGone; // something is going on here - +test of timeouts? :-) + set_event( hevBlockLock ); + nWaitersGone = 0; + } + unlock( mtxUnblockLock ); + + if ( 1 == nSignalsWasLeft ) { + if ( bWasBroadcast ) { + reset_event( hevBlockQueueB ); + } + set_event( hevBlockLock ); // open the gate + } + else if ( 0 != nSignalsWasLeft && !bWasBroadcast ) { + set_event( hevBlockQueueS ); // unblock next waiter + } + + lock( mtxExternal ); + + return ( bTimedOut ) ? ETIMEOUT : 0; +} + +signal(bAll) { + + [auto: register int result ] + [auto: register HANDLE hevBlockQueue ] + + lock( mtxUnblockLock ); + + if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! + if ( 0 == nWaitersBlocked ) { // NO-OP + return unlock( mtxUnblockLock ); + } + if (bAll) { + nWaitersToUnblock += nWaitersBlocked; + nWaitersBlocked = 0; + bBroadcast = true; + hevBlockQueue = hevBlockQueueB; + } + else { + nWaitersToUnblock++; + nWaitersBlocked--; + return unlock( mtxUnblockLock ); + } + } + else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! + wait( hevBlockLock,INFINITE ); // close the gate + if ( 0 != nWaitersGone ) { + nWaitersBlocked -= nWaitersGone; + nWaitersGone = 0; + } + if (bAll) { + nWaitersToUnblock = nWaitersBlocked; + nWaitersBlocked = 0; + bBroadcast = true; + hevBlockQueue = hevBlockQueueB; + } + else { + nWaitersToUnblock = 1; + nWaitersBlocked--; + hevBlockQueue = hevBlockQueueS; + } + } + else { // NO-OP + return unlock( mtxUnblockLock ); + } + + unlock( mtxUnblockLock ); + set_event( hevBlockQueue ); + return result; +} + + +---------------------------------------------------------------------------- + +Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio + n questions +Date: Mon, 26 Feb 2001 22:20:12 -0600 +From: Louis Thomas +To: "'TEREKHOV@de.ibm.com'" +CC: rpj@ise.canberra.edu.au, Thomas Pfaff , + Nanbor Wang + + +Sorry all. Busy week. + +> this insures the fairness +> which POSIX does not (e.g. two subsequent broadcasts - the gate does +insure +> that first wave waiters will start the race for the mutex before waiters +> from the second wave - Linux pthreads process/unblock both waves +> concurrently...) + +I'm not sure how we are any more fair about this than Linux. We certainly +don't guarantee that the threads released by the first broadcast will get +the external mutex before the threads of the second wave. In fact, it is +possible that those threads will never get the external mutex if there is +enough contention for it. + +> e.g. i was thinking about implementation with a pool of +> N semaphores/counters [...] + +I considered that too. The problem is as you mentioned in a). You really +need to assign threads to semaphores once you know how you want to wake them +up, not when they first begin waiting which is the only time you can assign +them. + +> well, i am not quite sure that i've fully understood your scenario, + +Hmm. Well, it think it's an important example, so I'll try again. First, we +have thread A which we KNOW is waiting on a condition. As soon as it becomes +unblocked for any reason, we will know because it will set a flag. Since the +flag is not set, we are 100% confident that thread A is waiting on the +condition. We have another thread, thread B, which has acquired the mutex +and is about to wait on the condition. Thus it is pretty clear that at any +point, either just A is waiting, or A and B are waiting. Now thread C comes +along. C is about to do a broadcast on the condition. A broadcast is +guaranteed to unblock all threads currently waiting on a condition, right? +Again, we said that either just A is waiting, or A and B are both waiting. +So, when C does its broadcast, depending upon whether B has started waiting +or not, thread C will unblock A or unblock A and B. Either way, C must +unblock A, right? + +Now, you said anything that happens is correct so long as a) "a signal is +not lost between unlocking the mutex and waiting on the condition" and b) "a +thread must not steal a signal it sent", correct? Requirement b) is easy to +satisfy: in this scenario, thread C will never wait on the condition, so it +won't steal any signals. Requirement a) is not hard either. The only way we +could fail to meet requirement a) in this scenario is if thread B was +started waiting but didn't wake up because a signal was lost. This will not +happen. + +Now, here is what happens. Assume thread C beats thread B. Thread C looks to +see how many threads are waiting on the condition. Thread C sees just one +thread, thread A, waiting. It does a broadcast waking up just one thread +because just one thread is waiting. Next, before A can become unblocked, +thread B begins waiting. Now there are two threads waiting, but only one +will be unblocked. Suppose B wins. B will become unblocked. A will not +become unblocked, because C only unblocked one thread (sema_post cond, 1). +So at the end, B finishes and A remains blocked. + +We have met both of your requirements, so by your rules, this is an +acceptable outcome. However, I think that the spec says this is an +unacceptable outcome! We know for certain that A was waiting and that C did +a broadcast, but A did not become unblocked! Yet, the spec says that a +broadcast wakes up all waiting threads. This did not happen. Do you agree +that this shows your rules are not strict enough? + +> and what about N2? :) this one does allow almost everything. + +Don't get me started about rule #2. I'll NEVER advocate an algorithm that +uses rule 2 as an excuse to suck! + +> but it is done (decrement)under mutex protection - this is not a subject +> of a race condition. + +You are correct. My mistake. + +> i would remove "_bTimedOut=false".. after all, it was a real timeout.. + +I disagree. A thread that can't successfully retract its waiter status can't +really have timed out. If a thread can't return without executing extra code +to deal with the fact that someone tried to unblock it, I think it is a poor +idea to pretend we +didn't realize someone was trying to signal us. After all, a signal is more +important than a time out. + +> when nSignaled != 0, it is possible to update nWaiters (--) and do not +> touch nGone + +I realize this, but I was thinking that writing it the other ways saves +another if statement. + +> adjust only if nGone != 0 and save one cache memory write - probably much +slower than 'if' + +Hmm. You are probably right. + +> well, in a strange (e.g. timeout test) program you may (theoretically) +> have an overflow of nWaiters/nGone counters (with waiters repeatedly +timing +> out and no signals at all). + +Also true. Not only that, but you also have the possibility that one could +overflow the number of waiters as well! However, considering the limit you +have chosen for nWaitersGone, I suppose it is unlikely that anyone would be +able to get INT_MAX/2 threads waiting on a single condition. :) + +Analysis of 8a: + +It looks correct to me. + +What are IPC semaphores? + +In the line where you state, "else if ( nWaitersBlocked > nWaitersGone ) { +// HARMLESS RACE CONDITION!" there is no race condition for nWaitersGone +because nWaitersGone is never modified without holding mtxUnblockLock. You +are correct that there is a harmless race on nWaitersBlocked, which can +increase and make the condition become true just after we check it. If this +happens, we interpret it as the wait starting after the signal. + +I like your optimization of this. You could improve Alg. 6 as follows: +---------- Algorithm 6b ---------- +signal(bAll) { + _nSig=0 + lock counters + // this is safe because nWaiting can only be decremented by a thread that + // owns counters and nGone can only be changed by a thread that owns +counters. + if (nWaiting>nGone) { + if (0==nSignaled) { + sema_wait gate // close gate if not already closed + } + if (nGone>0) { + nWaiting-=nGone + nGone=0 + } + _nSig=bAll?nWaiting:1 + nSignaled+=_nSig + nWaiting-=_nSig + } + unlock counters + if (0!=_nSig) { + sema_post queue, _nSig + } +} +---------- ---------- ---------- +I guess this wouldn't apply to Alg 8a because nWaitersGone changes meanings +depending upon whether the gate is open or closed. + +In the loop "while ( nWaitersWasGone-- ) {" you do a sema_wait on +semBlockLock. Perhaps waiting on semBlockQueue would be a better idea. + +What have you gained by making the last thread to be signaled do the waits +for all the timed out threads, besides added complexity? It took me a long +time to figure out what your objective was with this, to realize you were +using nWaitersGone to mean two different things, and to verify that you +hadn't introduced any bug by doing this. Even now I'm not 100% sure. + +What has all this playing about with nWaitersGone really gained us besides a +lot of complexity (it is much harder to verify that this solution is +correct), execution overhead (we now have a lot more if statements to +evaluate), and space overhead (more space for the extra code, and another +integer in our data)? We did manage to save a lock/unlock pair in an +uncommon case (when a time out occurs) at the above mentioned expenses in +the common cases. + +As for 8b, c, and d, they look ok though I haven't studied them thoroughly. +What would you use them for? + + Later, + -Louis! :) + +----------------------------------------------------------------------------- + +Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio + n questions +Date: Tue, 27 Feb 2001 15:51:28 +0100 +From: TEREKHOV@de.ibm.com +To: Louis Thomas +CC: rpj@ise.canberra.edu.au, Thomas Pfaff , + Nanbor Wang + +Hi Louis, + +>> that first wave waiters will start the race for the mutex before waiters +>> from the second wave - Linux pthreads process/unblock both waves +>> concurrently...) +> +>I'm not sure how we are any more fair about this than Linux. We certainly +>don't guarantee that the threads released by the first broadcast will get +>the external mutex before the threads of the second wave. In fact, it is +>possible that those threads will never get the external mutex if there is +>enough contention for it. + +correct. but gate is nevertheless more fair than Linux because of the +barrier it establishes between two races (1st and 2nd wave waiters) for +the mutex which under 'normal' circumstances (e.g. all threads of equal +priorities,..) will 'probably' result in fair behaviour with respect to +mutex ownership. + +>> well, i am not quite sure that i've fully understood your scenario, +> +>Hmm. Well, it think it's an important example, so I'll try again. ... + +ok. now i seem to understand this example. well, now it seems to me +that the only meaningful rule is just: + +a) "a signal is not lost between unlocking the mutex and waiting on the +condition" + +and that the rule + +b) "a thread must not steal a signal it sent" + +is not needed at all because a thread which violates b) also violates a). + +i'll try to explain.. + +i think that the most important thing is how POSIX defines waiter's +visibility: + +"if another thread is able to acquire the mutex after the about-to-block +thread +has released it, then a subsequent call to pthread_cond_signal() or +pthread_cond_broadcast() in that thread behaves as if it were issued after +the about-to-block thread has blocked. " + +my understanding is the following: + +1) there is no guarantees whatsoever with respect to whether +signal/broadcast +will actually unblock any 'waiter' if it is done w/o acquiring the mutex +first +(note that a thread may release it before signal/broadcast - it does not +matter). + +2) it is guaranteed that waiters become 'visible' - eligible for unblock as +soon +as signalling thread acquires the mutex (but not before!!) + +so.. + +>So, when C does its broadcast, depending upon whether B has started +waiting +>or not, thread C will unblock A or unblock A and B. Either way, C must +>unblock A, right? + +right. but only if C did acquire the mutex prior to broadcast (it may +release it before broadcast as well). + +implementation will violate waiters visibility rule (signal will become +lost) +if C will not unblock A. + +>Now, here is what happens. Assume thread C beats thread B. Thread C looks +to +>see how many threads are waiting on the condition. Thread C sees just one +>thread, thread A, waiting. It does a broadcast waking up just one thread +>because just one thread is waiting. Next, before A can become unblocked, +>thread B begins waiting. Now there are two threads waiting, but only one +>will be unblocked. Suppose B wins. B will become unblocked. A will not +>become unblocked, because C only unblocked one thread (sema_post cond, 1). +>So at the end, B finishes and A remains blocked. + +thread C did acquire the mutex ("Thread C sees just one thread, thread A, +waiting"). beginning from that moment it is guaranteed that subsequent +broadcast will unblock A. Otherwise we will have a lost signal with respect +to A. I do think that it does not matter whether the signal was physically +(completely) lost or was just stolen by another thread (B) - in both cases +it was simply lost with respect to A. + +>..Do you agree that this shows your rules are not strict enough? + +probably the opposite.. :-) i think that it shows that the only meaningful +rule is + +a) "a signal is not lost between unlocking the mutex and waiting on the +condition" + +with clarification of waiters visibility as defined by POSIX above. + +>> i would remove "_bTimedOut=false".. after all, it was a real timeout.. +> +>I disagree. A thread that can't successfully retract its waiter status +can't +>really have timed out. If a thread can't return without executing extra +code +>to deal with the fact that someone tried to unblock it, I think it is a +poor +>idea to pretend we +>didn't realize someone was trying to signal us. After all, a signal is +more +>important than a time out. + +a) POSIX does allow timed out thread to consume a signal (cancelled is +not). +b) ETIMEDOUT status just says that: "The time specified by abstime to +pthread_cond_timedwait() has passed." +c) it seem to me that hiding timeouts would violate "The +pthread_cond_timedwait() +function is the same as pthread_cond_wait() except that an error is +returned if +the absolute time specified by abstime passes (that is, system time equals +or +exceeds abstime) before the condition cond is signaled or broadcasted" +because +the abs. time did really pass before cond was signaled (waiter was +released via semaphore). however, if it really matters, i could imaging +that we +can save an abs. time of signal/broadcast and compare it with timeout after +unblock to find out whether it was a 'real' timeout or not. absent this +check +i do think that hiding timeouts would result in technical violation of +specification.. but i think that this check is not important and we can +simply +trust timeout error code provided by wait since we are not trying to make +'hard' realtime implementation. + +>What are IPC semaphores? + + +int semctl(int, int, int, ...); +int semget(key_t, int, int); +int semop(int, struct sembuf *, size_t); + +they support adjustment of semaphore counter (semvalue) +in one single call - imaging Win32 ReleaseSemaphore( hsem,-N ) + +>In the line where you state, "else if ( nWaitersBlocked > nWaitersGone ) { +>// HARMLESS RACE CONDITION!" there is no race condition for nWaitersGone +>because nWaitersGone is never modified without holding mtxUnblockLock. You +>are correct that there is a harmless race on nWaitersBlocked, which can +>increase and make the condition become true just after we check it. If +this +>happens, we interpret it as the wait starting after the signal. + +well, the reason why i've asked on comp.programming.threads whether this +race +condition is harmless or not is that in order to be harmless it should not +violate the waiters visibility rule (see above). Fortunately, we increment +the counter under protection of external mutex.. so that any (signalling) +thread which will acquire the mutex next, should see the updated counter +(in signal) according to POSIX memory visibility rules and mutexes +(memory barriers). But i am not so sure how it actually works on +Win32/INTEL +which does not explicitly define any memory visibility rules :( + +>I like your optimization of this. You could improve Alg. 6 as follows: +>---------- Algorithm 6b ---------- +>signal(bAll) { +> _nSig=0 +> lock counters +> // this is safe because nWaiting can only be decremented by a thread +that +> // owns counters and nGone can only be changed by a thread that owns +>counters. +> if (nWaiting>nGone) { +> if (0==nSignaled) { +> sema_wait gate // close gate if not already closed +> } +> if (nGone>0) { +> nWaiting-=nGone +> nGone=0 +> } +> _nSig=bAll?nWaiting:1 +> nSignaled+=_nSig +> nWaiting-=_nSig +> } +> unlock counters +> if (0!=_nSig) { +> sema_post queue, _nSig +> } +>} +>---------- ---------- ---------- +>I guess this wouldn't apply to Alg 8a because nWaitersGone changes +meanings +>depending upon whether the gate is open or closed. + +agree. + +>In the loop "while ( nWaitersWasGone-- ) {" you do a sema_wait on +>semBlockLock. Perhaps waiting on semBlockQueue would be a better idea. + +you are correct. my mistake. + +>What have you gained by making the last thread to be signaled do the waits +>for all the timed out threads, besides added complexity? It took me a long +>time to figure out what your objective was with this, to realize you were +>using nWaitersGone to mean two different things, and to verify that you +>hadn't introduced any bug by doing this. Even now I'm not 100% sure. +> +>What has all this playing about with nWaitersGone really gained us besides +a +>lot of complexity (it is much harder to verify that this solution is +>correct), execution overhead (we now have a lot more if statements to +>evaluate), and space overhead (more space for the extra code, and another +>integer in our data)? We did manage to save a lock/unlock pair in an +>uncommon case (when a time out occurs) at the above mentioned expenses in +>the common cases. + +well, please consider the following: + +1) with multiple waiters unblocked (but some timed out) the trick with +counter +seem to ensure potentially higher level of concurrency by not delaying +most of unblocked waiters for semaphore cleanup - only the last one +will be delayed but all others would already contend/acquire/release +the external mutex - the critical section protected by mtxUnblockLock is +made smaller (increment + couple of IFs is faster than system/kernel call) +which i think is good in general. however, you are right, this is done +at expense of 'normal' waiters.. + +2) some semaphore APIs (e.g. POSIX IPC sems) do allow to adjust the +semaphore counter in one call => less system/kernel calls.. imagine: + +if ( 1 == nSignalsWasLeft ) { + if ( 0 != nWaitersWasGone ) { + ReleaseSemaphore( semBlockQueue,-nWaitersWasGone ); // better now +than spurious later + } + sem_post( semBlockLock ); // open the gate + } + +3) even on win32 a single thread doing multiple cleanup calls (to wait) +will probably result in faster execution (because of processor caching) +than multiple threads each doing a single call to wait. + +>As for 8b, c, and d, they look ok though I haven't studied them +thoroughly. +>What would you use them for? + +8b) for semaphores which do not allow to unblock multiple waiters +in a single call to post/release (e.g. POSIX realtime semaphores - +) + +8c/8d) for WinCE prior to 3.0 (WinCE 3.0 does have semaphores) + +ok. so, which one is the 'final' algorithm(s) which we should use in +pthreads-win32?? + +regards, +alexander. + +---------------------------------------------------------------------------- + +Louis Thomas on 02/27/2001 05:20:12 AM + +Please respond to Louis Thomas + +To: Alexander Terekhov/Germany/IBM@IBMDE +cc: rpj@ise.canberra.edu.au, Thomas Pfaff , Nanbor Wang + +Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio + n questions + +Sorry all. Busy week. + +> this insures the fairness +> which POSIX does not (e.g. two subsequent broadcasts - the gate does +insure +> that first wave waiters will start the race for the mutex before waiters +> from the second wave - Linux pthreads process/unblock both waves +> concurrently...) + +I'm not sure how we are any more fair about this than Linux. We certainly +don't guarantee that the threads released by the first broadcast will get +the external mutex before the threads of the second wave. In fact, it is +possible that those threads will never get the external mutex if there is +enough contention for it. + +> e.g. i was thinking about implementation with a pool of +> N semaphores/counters [...] + +I considered that too. The problem is as you mentioned in a). You really +need to assign threads to semaphores once you know how you want to wake +them +up, not when they first begin waiting which is the only time you can assign +them. + +> well, i am not quite sure that i've fully understood your scenario, + +Hmm. Well, it think it's an important example, so I'll try again. First, we +have thread A which we KNOW is waiting on a condition. As soon as it +becomes +unblocked for any reason, we will know because it will set a flag. Since +the +flag is not set, we are 100% confident that thread A is waiting on the +condition. We have another thread, thread B, which has acquired the mutex +and is about to wait on the condition. Thus it is pretty clear that at any +point, either just A is waiting, or A and B are waiting. Now thread C comes +along. C is about to do a broadcast on the condition. A broadcast is +guaranteed to unblock all threads currently waiting on a condition, right? +Again, we said that either just A is waiting, or A and B are both waiting. +So, when C does its broadcast, depending upon whether B has started waiting +or not, thread C will unblock A or unblock A and B. Either way, C must +unblock A, right? + +Now, you said anything that happens is correct so long as a) "a signal is +not lost between unlocking the mutex and waiting on the condition" and b) +"a +thread must not steal a signal it sent", correct? Requirement b) is easy to +satisfy: in this scenario, thread C will never wait on the condition, so it +won't steal any signals. Requirement a) is not hard either. The only way +we +could fail to meet requirement a) in this scenario is if thread B was +started waiting but didn't wake up because a signal was lost. This will not +happen. + +Now, here is what happens. Assume thread C beats thread B. Thread C looks +to +see how many threads are waiting on the condition. Thread C sees just one +thread, thread A, waiting. It does a broadcast waking up just one thread +because just one thread is waiting. Next, before A can become unblocked, +thread B begins waiting. Now there are two threads waiting, but only one +will be unblocked. Suppose B wins. B will become unblocked. A will not +become unblocked, because C only unblocked one thread (sema_post cond, 1). +So at the end, B finishes and A remains blocked. + +We have met both of your requirements, so by your rules, this is an +acceptable outcome. However, I think that the spec says this is an +unacceptable outcome! We know for certain that A was waiting and that C did +a broadcast, but A did not become unblocked! Yet, the spec says that a +broadcast wakes up all waiting threads. This did not happen. Do you agree +that this shows your rules are not strict enough? + +> and what about N2? :) this one does allow almost everything. + +Don't get me started about rule #2. I'll NEVER advocate an algorithm that +uses rule 2 as an excuse to suck! + +> but it is done (decrement)under mutex protection - this is not a subject +> of a race condition. + +You are correct. My mistake. + +> i would remove "_bTimedOut=false".. after all, it was a real timeout.. + +I disagree. A thread that can't successfully retract its waiter status +can't +really have timed out. If a thread can't return without executing extra +code +to deal with the fact that someone tried to unblock it, I think it is a +poor +idea to pretend we +didn't realize someone was trying to signal us. After all, a signal is more +important than a time out. + +> when nSignaled != 0, it is possible to update nWaiters (--) and do not +> touch nGone + +I realize this, but I was thinking that writing it the other ways saves +another if statement. + +> adjust only if nGone != 0 and save one cache memory write - probably much +slower than 'if' + +Hmm. You are probably right. + +> well, in a strange (e.g. timeout test) program you may (theoretically) +> have an overflow of nWaiters/nGone counters (with waiters repeatedly +timing +> out and no signals at all). + +Also true. Not only that, but you also have the possibility that one could +overflow the number of waiters as well! However, considering the limit you +have chosen for nWaitersGone, I suppose it is unlikely that anyone would be +able to get INT_MAX/2 threads waiting on a single condition. :) + +Analysis of 8a: + +It looks correct to me. + +What are IPC semaphores? + +In the line where you state, "else if ( nWaitersBlocked > nWaitersGone ) { +// HARMLESS RACE CONDITION!" there is no race condition for nWaitersGone +because nWaitersGone is never modified without holding mtxUnblockLock. You +are correct that there is a harmless race on nWaitersBlocked, which can +increase and make the condition become true just after we check it. If this +happens, we interpret it as the wait starting after the signal. + +I like your optimization of this. You could improve Alg. 6 as follows: +---------- Algorithm 6b ---------- +signal(bAll) { + _nSig=0 + lock counters + // this is safe because nWaiting can only be decremented by a thread that + // owns counters and nGone can only be changed by a thread that owns +counters. + if (nWaiting>nGone) { + if (0==nSignaled) { + sema_wait gate // close gate if not already closed + } + if (nGone>0) { + nWaiting-=nGone + nGone=0 + } + _nSig=bAll?nWaiting:1 + nSignaled+=_nSig + nWaiting-=_nSig + } + unlock counters + if (0!=_nSig) { + sema_post queue, _nSig + } +} +---------- ---------- ---------- +I guess this wouldn't apply to Alg 8a because nWaitersGone changes meanings +depending upon whether the gate is open or closed. + +In the loop "while ( nWaitersWasGone-- ) {" you do a sema_wait on +semBlockLock. Perhaps waiting on semBlockQueue would be a better idea. + +What have you gained by making the last thread to be signaled do the waits +for all the timed out threads, besides added complexity? It took me a long +time to figure out what your objective was with this, to realize you were +using nWaitersGone to mean two different things, and to verify that you +hadn't introduced any bug by doing this. Even now I'm not 100% sure. + +What has all this playing about with nWaitersGone really gained us besides +a +lot of complexity (it is much harder to verify that this solution is +correct), execution overhead (we now have a lot more if statements to +evaluate), and space overhead (more space for the extra code, and another +integer in our data)? We did manage to save a lock/unlock pair in an +uncommon case (when a time out occurs) at the above mentioned expenses in +the common cases. + +As for 8b, c, and d, they look ok though I haven't studied them thoroughly. +What would you use them for? + + Later, + -Louis! :) + diff --git a/liblo/pthreads.2/README.NONPORTABLE b/liblo/pthreads.2/README.NONPORTABLE new file mode 100644 index 0000000..ae76862 --- /dev/null +++ b/liblo/pthreads.2/README.NONPORTABLE @@ -0,0 +1,285 @@ +This file documents non-portable functions and other issues. + +Non-portable functions included in pthreads-win32 +------------------------------------------------- + +BOOL +pthread_win32_test_features_np(int mask) + + This routine allows an application to check which + run-time auto-detected features are available within + the library. + + The possible features are: + + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE + Return TRUE if the native version of + InterlockedCompareExchange() is being used. + PTW32_ALERTABLE_ASYNC_CANCEL + Return TRUE is the QueueUserAPCEx package + QUSEREX.DLL is available and the AlertDrv.sys + driver is loaded into Windows, providing + alertable (pre-emptive) asyncronous threads + cancelation. If this feature returns FALSE + then the default async cancel scheme is in + use, which cannot cancel blocked threads. + + Features may be Or'ed into the mask parameter, in which case + the routine returns TRUE if any of the Or'ed features would + return TRUE. At this stage it doesn't make sense to Or features + but it may some day. + + +void * +pthread_timechange_handler_np(void *) + + To improve tolerance against operator or time service + initiated system clock changes. + + This routine can be called by an application when it + receives a WM_TIMECHANGE message from the system. At + present it broadcasts all condition variables so that + waiting threads can wake up and re-evaluate their + conditions and restart their timed waits if required. + + It has the same return type and argument type as a + thread routine so that it may be called directly + through pthread_create(), i.e. as a separate thread. + + Parameters + + Although a parameter must be supplied, it is ignored. + The value NULL can be used. + + Return values + + It can return an error EAGAIN to indicate that not + all condition variables were broadcast for some reason. + Otherwise, 0 is returned. + + If run as a thread, the return value is returned + through pthread_join(). + + The return value should be cast to an integer. + + +HANDLE +pthread_getw32threadhandle_np(pthread_t thread); + + Returns the win32 thread handle that the POSIX + thread "thread" is running as. + + Applications can use the win32 handle to set + win32 specific attributes of the thread. + + +int +pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind) + +int +pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind) + + These two routines are included for Linux compatibility + and are direct equivalents to the standard routines + pthread_mutexattr_settype + pthread_mutexattr_gettype + + pthread_mutexattr_setkind_np accepts the following + mutex kinds: + PTHREAD_MUTEX_FAST_NP + PTHREAD_MUTEX_ERRORCHECK_NP + PTHREAD_MUTEX_RECURSIVE_NP + + These are really just equivalent to (respectively): + PTHREAD_MUTEX_NORMAL + PTHREAD_MUTEX_ERRORCHECK + PTHREAD_MUTEX_RECURSIVE + +int +pthread_delay_np (const struct timespec *interval); + + This routine causes a thread to delay execution for a specific period of time. + This period ends at the current time plus the specified interval. The routine + will not return before the end of the period is reached, but may return an + arbitrary amount of time after the period has gone by. This can be due to + system load, thread priorities, and system timer granularity. + + Specifying an interval of zero (0) seconds and zero (0) nanoseconds is + allowed and can be used to force the thread to give up the processor or to + deliver a pending cancelation request. + + This routine is a cancelation point. + + The timespec structure contains the following two fields: + + tv_sec is an integer number of seconds. + tv_nsec is an integer number of nanoseconds. + + Return Values + + If an error condition occurs, this routine returns an integer value + indicating the type of error. Possible return values are as follows: + + 0 Successful completion. + [EINVAL] The value specified by interval is invalid. + +int +pthread_num_processors_np + + This routine (found on HPUX systems) returns the number of processors + in the system. This implementation actually returns the number of + processors available to the process, which can be a lower number + than the system's number, depending on the process's affinity mask. + +BOOL +pthread_win32_process_attach_np (void); + +BOOL +pthread_win32_process_detach_np (void); + +BOOL +pthread_win32_thread_attach_np (void); + +BOOL +pthread_win32_thread_detach_np (void); + + These functions contain the code normally run via dllMain + when the library is used as a dll but which need to be + called explicitly by an application when the library + is statically linked. + + You will need to call pthread_win32_process_attach_np() before + you can call any pthread routines when statically linking. + You should call pthread_win32_process_detach_np() before + exiting your application to clean up. + + pthread_win32_thread_attach_np() is currently a no-op, but + pthread_win32_thread_detach_np() is needed to clean up + the implicit pthread handle that is allocated to a Win32 thread if + it calls certain pthreads routines. Call this routine when the + Win32 thread exits. + + These functions invariably return TRUE except for + pthread_win32_process_attach_np() which will return FALSE + if pthreads-win32 initialisation fails. + +int +pthreadCancelableWait (HANDLE waitHandle); + +int +pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout); + + These two functions provide hooks into the pthread_cancel + mechanism that will allow you to wait on a Windows handle + and make it a cancellation point. Both functions block + until either the given w32 handle is signaled, or + pthread_cancel has been called. It is implemented using + WaitForMultipleObjects on 'waitHandle' and a manually + reset w32 event used to implement pthread_cancel. + + +Non-portable issues +------------------- + +Thread priority + + POSIX defines a single contiguous range of numbers that determine a + thread's priority. Win32 defines priority classes and priority + levels relative to these classes. Classes are simply priority base + levels that the defined priority levels are relative to such that, + changing a process's priority class will change the priority of all + of it's threads, while the threads retain the same relativity to each + other. + + A Win32 system defines a single contiguous monotonic range of values + that define system priority levels, just like POSIX. However, Win32 + restricts individual threads to a subset of this range on a + per-process basis. + + The following table shows the base priority levels for combinations + of priority class and priority value in Win32. + + Process Priority Class Thread Priority Level + ----------------------------------------------------------------- + 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE + 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE + 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE + 17 REALTIME_PRIORITY_CLASS -7 + 18 REALTIME_PRIORITY_CLASS -6 + 19 REALTIME_PRIORITY_CLASS -5 + 20 REALTIME_PRIORITY_CLASS -4 + 21 REALTIME_PRIORITY_CLASS -3 + 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + 27 REALTIME_PRIORITY_CLASS 3 + 28 REALTIME_PRIORITY_CLASS 4 + 29 REALTIME_PRIORITY_CLASS 5 + 30 REALTIME_PRIORITY_CLASS 6 + 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + + Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported. + + + As you can see, the real priority levels available to any individual + Win32 thread are non-contiguous. + + An application using pthreads-win32 should not make assumptions about + the numbers used to represent thread priority levels, except that they + are monotonic between the values returned by sched_get_priority_min() + and sched_get_priority_max(). E.g. Windows 95, 98, NT, 2000, XP make + available a non-contiguous range of numbers between -15 and 15, while + at least one version of WinCE (3.0) defines the minimum priority + (THREAD_PRIORITY_LOWEST) as 5, and the maximum priority + (THREAD_PRIORITY_HIGHEST) as 1. + + Internally, pthreads-win32 maps any priority levels between + THREAD_PRIORITY_IDLE and THREAD_PRIORITY_LOWEST to THREAD_PRIORITY_LOWEST, + or between THREAD_PRIORITY_TIME_CRITICAL and THREAD_PRIORITY_HIGHEST to + THREAD_PRIORITY_HIGHEST. Currently, this also applies to + REALTIME_PRIORITY_CLASSi even if levels -7, -6, -5, -4, -3, 3, 4, 5, and 6 + are supported. + + If it wishes, a Win32 application using pthreads-win32 can use the Win32 + defined priority macros THREAD_PRIORITY_IDLE through + THREAD_PRIORITY_TIME_CRITICAL. diff --git a/liblo/pthreads.2/README.Watcom b/liblo/pthreads.2/README.Watcom new file mode 100644 index 0000000..2495516 --- /dev/null +++ b/liblo/pthreads.2/README.Watcom @@ -0,0 +1,62 @@ +Watcom compiler notes +===================== + +Status +------ +Not yet usable. Although the library builds under Watcom it +substantially fails the test suite. + +There is a working Wmakefile for wmake for the library build. + +invoke as any of: +wmake -f Wmakefile clean WC +wmake -f Wmakefile clean WC-inlined +wmake -f Wmakefile clean WCE +wmake -f Wmakefile clean WCE-inlined + +These build pthreadWC.dll and pthreadWCE.dll. + +There is a working Wmakefile for wmake for the test suite. + +invoke as any of: +wmake -f Wmakefile clean WC +wmake -f Wmakefile clean WCX +wmake -f Wmakefile clean WCE +wmake -f Wmakefile clean WC-bench +wmake -f Wmakefile clean WCX-bench +wmake -f Wmakefile clean WCE-bench + + +Current known problems +---------------------- + +Library build: +The Watcom compiler uses a different default call convention to MS C or GNU C and so +applications are not compatible with pthreadVC.dll etc using pre 2003-10-14 versions +of pthread.h, sched.h, or semaphore.h. The cdecl attribute can be used on exposed +function prototypes to force compatibility with MS C built DLLs. + +However, there appear to be other incompatibilities. Errno.h, for example, defines +different values for the standard C and POSIX errors to those defined by the MS C +errno.h. It may be that references to Watcom's threads compatible 'errno' do set +and return translated numbers consistently, but I have not verified this. + +Watcom defines errno as a dereferenced pointer returned by the function +_get_errno_ptr(). This is similar to both the MS and GNU C environments for +multithreaded use. However, the Watcom version appears to have a number of problems: + +- different threads return the same pointer value. Compare with the MS and GNU C +versions which correctly return different values (since each thread must maintain +a thread specific errno value). + +- an errno value set within the DLL appears as zero in the application even though +both share the same thread. + +Therefore applications built using the Watcom compiler may need to use +a Watcom built version of the library (pthreadWC.dll). If this is the case, then +the cdecl function attribute should not be required. + +Application builds: +The test suite fails with the Watcom compiler. + +Test semaphore1.c fails for pthreadWC.dll because errno returns 0 instead of EAGAIN. diff --git a/liblo/pthreads.2/README.WinCE b/liblo/pthreads.2/README.WinCE new file mode 100644 index 0000000..1e06429 --- /dev/null +++ b/liblo/pthreads.2/README.WinCE @@ -0,0 +1,6 @@ +WinCE port +---------- +(See the file WinCE-PORT for a detailed explanation.) + +Make sure you define "WINCE" amongst your compiler flags (eg. -DWINCE). +The config.h file will define all the necessary defines for you. diff --git a/liblo/pthreads.2/TODO b/liblo/pthreads.2/TODO new file mode 100644 index 0000000..f798e76 --- /dev/null +++ b/liblo/pthreads.2/TODO @@ -0,0 +1,7 @@ + Things that aren't done yet + --------------------------- + +1. Implement PTHREAD_PROCESS_SHARED for semaphores, mutexes, + condition variables, read/write locks, barriers. + + diff --git a/liblo/pthreads.2/WinCE-PORT b/liblo/pthreads.2/WinCE-PORT new file mode 100644 index 0000000..486d972 --- /dev/null +++ b/liblo/pthreads.2/WinCE-PORT @@ -0,0 +1,217 @@ +NOTE: The comments in this file relate to the original WinCE port +done by Tristan Savatier. The semaphore routines have been +completely rewritten since (2005-04-25), having been progressively +broken more and more by changes to the library. All of the semaphore +routines implemented for W9x/WNT/2000 and up should now also work for +WinCE. Also, pthread_mutex_timedlock should now work. [RPJ] + +---- + +Some interesting news: + +I have been able to port pthread-win32 to Windows-CE, +which uses a subset of the WIN32 API. + +Since we intend to keep using pthread-win32 for our +Commercial WinCE developments, I would be very interested +if WinCE support could be added to the main source tree +of pthread-win32. Also, I would like to be credited +for this port :-) + +Now, here is the story... + +The port was performed and tested on a Casio "Cassiopeia" +PalmSize PC, which runs a MIP processor. The OS in the +Casio is WinCE version 2.11, but I used VC++ 6.0 with +the WinCE SDK for version 2.01. + +I used pthread-win32 to port a heavily multithreaded +commercial application (real-time MPEG video player) +from Linux to WinCE. I consider the changes that +I have done to be quite well tested. + +Overall the modifications that we had to do are minor. + +The WinCE port were based on pthread-win32-snap-1999-05-30, +but I am certain that they can be integrated very easiely +to more recent versions of the source. + +I have attached the modified source code: +pthread-win32-snap-1999-05-30-WinCE. + +All the changes do not affect the code compiled on non-WinCE +environment, provided that the macros used for WinCE compilation +are not used, of course! + +Overall description of the WinCE port: +------------------------------------- + +Most of the changes had to be made in areas where +pthread-win32 was relying on some standard-C librairies +(e.g. _ftime, calloc, errno), which are not available +on WinCE. We have changed the code to use native Win32 +API instead (or in some cases we made wrappers). + +The Win32 Semaphores are not available, +so we had to re-implement Semaphores using mutexes +and events. + +Limitations / known problems of the WinCE port: +---------------------------------------------- + +Not all the semaphore routines have been ported +(semaphores are defined by Posix but are not part +pf pthread). I have just done enough to make +pthread routines (that rely internally on semaphores) +work, like signal conditions. + +I noticed that the Win32 threads work slightly +differently on WinCE. This may have some impact +on some tricky parts of pthread-win32, but I have +not really investigated. For example, on WinCE, +the process is killed if the main thread falls off +the bottom (or calls pthread_exit), regardless +of the existence of any other detached thread. +Microsoft manual indicates that this behavior is +deffirent from that of Windows Threads for other +Win32 platforms. + + +Detailed descriptions of the changes and rationals: + +------------------------------------ +- use a new macro NEED_ERRNO. + +If defined, the code in errno.c that defines a reentrant errno +is compiled, regardless of _MT and _REENTRANT. + +Rational: On WinCE, there is no support for , or +any other standard C library, i.e. even if _MT or _REENTRANT +is defined, errno is not provided by any library. NEED_ERRNO +must be set to compile for WinCE. + +------------------------------------ +- In implement.h, change #include to #include "semaphore.h". + +Rational: semaphore.h is provided in pthread-win32 and should not +be searched in the systems standard include. would not compile. +This change does not seem to create problems on "classic" win32 +(e.g. win95). + +------------------------------------ +- use a new macro NEED_CALLOC. + +If defined, some code in misc.c will provide a replacement +for calloc, which is not available on Win32. + + +------------------------------------ +- use a new macro NEED_CREATETHREAD. + +If defined, implement.h defines the macro _beginthreadex +and _endthreadex. + +Rational: On WinCE, the wrappers _beginthreadex and _endthreadex +do not exist. The native Win32 routines must be used. + +------------------------------------ +- in misc.c: + +#ifdef NEED_DUPLICATEHANDLE + /* DuplicateHandle does not exist on WinCE */ + self->threadH = GetCurrentThread(); +#else + if( !DuplicateHandle( + GetCurrentProcess(), + GetCurrentThread(), + GetCurrentProcess(), + &self->threadH, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ) ) + { + free( self ); + return (NULL); + } +#endif + +Rational: On WinCE, DuplicateHandle does not exist. I could not understand +why DuplicateHandle must be used. It seems to me that getting the current +thread handle with GetCurrentThread() is sufficient, and it seems to work +perfectly fine, so maybe DuplicateHandle was just plain useless to begin with ? + +------------------------------------ +- In private.c, added some code at the beginning of ptw32_processInitialize +to detect the case of multiple calls to ptw32_processInitialize. + +Rational: In order to debug pthread-win32, it is easier to compile +it as a regular library (it is not possible to debug DLL's on winCE). +In that case, the application must call ptw32_rocessInitialize() +explicitely, to initialize pthread-win32. It is safer in this circumstance +to handle the case where ptw32_processInitialize() is called on +an already initialized library: + +int +ptw32_processInitialize (void) +{ + if (ptw32_processInitialized) { + /* + * ignore if already initialized. this is useful for + * programs that uses a non-dll pthread + * library. such programs must call ptw32_processInitialize() explicitely, + * since this initialization routine is automatically called only when + * the dll is loaded. + */ + return TRUE; + } + ptw32_processInitialized = TRUE; + [...] +} + +------------------------------------ +- in private.c, if macro NEED_FTIME is defined, add routines to +convert timespec_to_filetime and filetime_to_timespec, and modified +code that was using _ftime() to use Win32 API instead. + +Rational: _ftime is not available on WinCE. It is necessary to use +the native Win32 time API instead. + +Note: the routine timespec_to_filetime is provided as a convenience and a mean +to test that filetime_to_timespec works, but it is not used by the library. + +------------------------------------ +- in semaphore.c, if macro NEED_SEM is defined, add code for the routines +_increase_semaphore and _decrease_semaphore, and modify significantly +the implementation of the semaphores so that it does not use CreateSemaphore. + +Rational: CreateSemaphore is not available on WinCE. I had to re-implement +semaphores using mutexes and Events. + +Note: Only the semaphore routines that are used by pthread are implemented +(i.e. signal conditions rely on a subset of the semaphores routines, and +this subset works). Some other semaphore routines (e.g. sem_trywait) are +not yet supported on my WinCE port (and since I don't need them, I am not +planning to do anything about them). + +------------------------------------ +- in tsd.c, changed the code that defines TLS_OUT_OF_INDEXES + +/* TLS_OUT_OF_INDEXES not defined on WinCE */ +#ifndef TLS_OUT_OF_INDEXES +#define TLS_OUT_OF_INDEXES 0xffffffff +#endif + +Rational: TLS_OUT_OF_INDEXES is not defined in any standard include file +on WinCE. + +------------------------------------ +- added file need_errno.h + +Rational: On WinCE, there is no errno.h file. need_errno.h is just a +copy of windows version of errno.h, with minor modifications due to the fact +that some of the error codes are defined by the WinCE socket library. +In pthread.h, if NEED_ERRNO is defined, the file need_errno.h is +included (instead of ). + + +-- eof diff --git a/liblo/pthreads.2/attr.c b/liblo/pthreads.2/attr.c new file mode 100644 index 0000000..0d0b560 --- /dev/null +++ b/liblo/pthreads.2/attr.c @@ -0,0 +1,53 @@ +/* + * attr.c + * + * Description: + * This translation unit agregates operations on thread attribute objects. + * It is used for inline optimisation. + * + * The included modules are used separately when static executable sizes + * must be minimised. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +#include "pthread_attr_init.c" +#include "pthread_attr_destroy.c" +#include "pthread_attr_getdetachstate.c" +#include "pthread_attr_setdetachstate.c" +#include "pthread_attr_getstackaddr.c" +#include "pthread_attr_setstackaddr.c" +#include "pthread_attr_getstacksize.c" +#include "pthread_attr_setstacksize.c" +#include "pthread_attr_getscope.c" +#include "pthread_attr_setscope.c" diff --git a/liblo/pthreads.2/barrier.c b/liblo/pthreads.2/barrier.c new file mode 100644 index 0000000..f95f4bd --- /dev/null +++ b/liblo/pthreads.2/barrier.c @@ -0,0 +1,47 @@ +/* + * barrier.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#include "pthread_barrier_init.c" +#include "pthread_barrier_destroy.c" +#include "pthread_barrier_wait.c" +#include "pthread_barrierattr_init.c" +#include "pthread_barrierattr_destroy.c" +#include "pthread_barrierattr_getpshared.c" +#include "pthread_barrierattr_setpshared.c" diff --git a/liblo/pthreads.2/builddmc.bat b/liblo/pthreads.2/builddmc.bat new file mode 100644 index 0000000..0d803d1 --- /dev/null +++ b/liblo/pthreads.2/builddmc.bat @@ -0,0 +1,9 @@ +; Build the pthreads library with the Digital Mars Compiler +; +set DMCDIR=c:\dm + +; RELEASE +%DMCDIR%\bin\dmc -D_WIN32_WINNT -D_MT -DHAVE_CONFIG_H -I.;c:\dm\include -o+all -WD pthread.c user32.lib+kernel32.lib+wsock32.lib -L/impl -L/NODEBUG -L/SU:WINDOWS + +; DEBUG +%DMCDIR%\bin\dmc -g -D_WIN32_WINNT -D_MT -DHAVE_CONFIG_H -I.;c:\dm\include -o+all -WD pthread.c user32.lib+kernel32.lib+wsock32.lib -L/impl -L/SU:WINDOWS diff --git a/liblo/pthreads.2/cancel.c b/liblo/pthreads.2/cancel.c new file mode 100644 index 0000000..28cf4eb --- /dev/null +++ b/liblo/pthreads.2/cancel.c @@ -0,0 +1,44 @@ +/* + * cancel.c + * + * Description: + * POSIX thread functions related to thread cancellation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#include "pthread_setcancelstate.c" +#include "pthread_setcanceltype.c" +#include "pthread_testcancel.c" +#include "pthread_cancel.c" diff --git a/liblo/pthreads.2/cleanup.c b/liblo/pthreads.2/cleanup.c new file mode 100644 index 0000000..8f65c5e --- /dev/null +++ b/liblo/pthreads.2/cleanup.c @@ -0,0 +1,148 @@ +/* + * cleanup.c + * + * Description: + * This translation unit implements routines associated + * with cleaning up threads. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +/* + * The functions ptw32_pop_cleanup and ptw32_push_cleanup + * are implemented here for applications written in C with no + * SEH or C++ destructor support. + */ + +ptw32_cleanup_t * +ptw32_pop_cleanup (int execute) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function pops the most recently pushed cleanup + * handler. If execute is nonzero, then the cleanup handler + * is executed if non-null. + * + * PARAMETERS + * execute + * if nonzero, execute the cleanup handler + * + * + * DESCRIPTION + * This function pops the most recently pushed cleanup + * handler. If execute is nonzero, then the cleanup handler + * is executed if non-null. + * NOTE: specify 'execute' as nonzero to avoid duplication + * of common cleanup code. + * + * RESULTS + * N/A + * + * ------------------------------------------------------ + */ +{ + ptw32_cleanup_t *cleanup; + + cleanup = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey); + + if (cleanup != NULL) + { + if (execute && (cleanup->routine != NULL)) + { + + (*cleanup->routine) (cleanup->arg); + + } + + pthread_setspecific (ptw32_cleanupKey, (void *) cleanup->prev); + + } + + return (cleanup); + +} /* ptw32_pop_cleanup */ + + +void +ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + ptw32_cleanup_callback_t routine, void *arg) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function pushes a new cleanup handler onto the thread's stack + * of cleanup handlers. Each cleanup handler pushed onto the stack is + * popped and invoked with the argument 'arg' when + * a) the thread exits by calling 'pthread_exit', + * b) when the thread acts on a cancellation request, + * c) or when the thread calls pthread_cleanup_pop with a nonzero + * 'execute' argument + * + * PARAMETERS + * cleanup + * a pointer to an instance of pthread_cleanup_t, + * + * routine + * pointer to a cleanup handler, + * + * arg + * parameter to be passed to the cleanup handler + * + * + * DESCRIPTION + * This function pushes a new cleanup handler onto the thread's stack + * of cleanup handlers. Each cleanup handler pushed onto the stack is + * popped and invoked with the argument 'arg' when + * a) the thread exits by calling 'pthread_exit', + * b) when the thread acts on a cancellation request, + * c) or when the thrad calls pthread_cleanup_pop with a nonzero + * 'execute' argument + * NOTE: pthread_push_cleanup, ptw32_pop_cleanup must be paired + * in the same lexical scope. + * + * RESULTS + * pthread_cleanup_t * + * pointer to the previous cleanup + * + * ------------------------------------------------------ + */ +{ + cleanup->routine = routine; + cleanup->arg = arg; + + cleanup->prev = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey); + + pthread_setspecific (ptw32_cleanupKey, (void *) cleanup); + +} /* ptw32_push_cleanup */ diff --git a/liblo/pthreads.2/condvar.c b/liblo/pthreads.2/condvar.c new file mode 100644 index 0000000..449235c --- /dev/null +++ b/liblo/pthreads.2/condvar.c @@ -0,0 +1,50 @@ +/* + * condvar.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#include "pthread.h" +#include "implement.h" + +#include "ptw32_cond_check_need_init.c" +#include "pthread_condattr_init.c" +#include "pthread_condattr_destroy.c" +#include "pthread_condattr_getpshared.c" +#include "pthread_condattr_setpshared.c" +#include "pthread_cond_init.c" +#include "pthread_cond_destroy.c" +#include "pthread_cond_wait.c" +#include "pthread_cond_signal.c" diff --git a/liblo/pthreads.2/config.h b/liblo/pthreads.2/config.h new file mode 100644 index 0000000..a446a84 --- /dev/null +++ b/liblo/pthreads.2/config.h @@ -0,0 +1,134 @@ +/* config.h */ + +#ifndef PTW32_CONFIG_H +#define PTW32_CONFIG_H + +/********************************************************************* + * Defaults: see target specific redefinitions below. + *********************************************************************/ + +/* We're building the pthreads-win32 library */ +#define PTW32_BUILD + +/* Do we know about the C type sigset_t? */ +#undef HAVE_SIGSET_T + +/* Define if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define if you have the Borland TASM32 or compatible assembler. */ +#undef HAVE_TASM32 + +/* Define if you don't have Win32 DuplicateHandle. (eg. WinCE) */ +#undef NEED_DUPLICATEHANDLE + +/* Define if you don't have Win32 _beginthreadex. (eg. WinCE) */ +#undef NEED_CREATETHREAD + +/* Define if you don't have Win32 errno. (eg. WinCE) */ +#undef NEED_ERRNO + +/* Define if you don't have Win32 calloc. (eg. WinCE) */ +#undef NEED_CALLOC + +/* Define if you don't have Win32 ftime. (eg. WinCE) */ +#undef NEED_FTIME + +/* Define if you don't have Win32 semaphores. (eg. WinCE 2.1 or earlier) */ +#undef NEED_SEM + +/* Define if you need to convert string parameters to unicode. (eg. WinCE) */ +#undef NEED_UNICODE_CONSTS + +/* Define if your C (not C++) compiler supports "inline" functions. */ +#undef HAVE_C_INLINE + +/* Do we know about type mode_t? */ +#undef HAVE_MODE_T + +/* Define if you have the timespec struct */ +#undef HAVE_STRUCT_TIMESPEC + +/* Define if you don't have the GetProcessAffinityMask() */ +#undef NEED_PROCESS_AFFINITY_MASK + +/* +# ---------------------------------------------------------------------- +# The library can be built with some alternative behaviour to better +# facilitate development of applications on Win32 that will be ported +# to other POSIX systems. +# +# Nothing described here will make the library non-compliant and strictly +# compliant applications will not be affected in any way, but +# applications that make assumptions that POSIX does not guarantee are +# not strictly compliant and may fail or misbehave with some settings. +# +# PTW32_THREAD_ID_REUSE_INCREMENT +# Purpose: +# POSIX says that applications should assume that thread IDs can be +# recycled. However, Solaris (and some other systems) use a [very large] +# sequence number as the thread ID, which provides virtual uniqueness. +# This provides a very high but finite level of safety for applications +# that are not meticulous in tracking thread lifecycles e.g. applications +# that call functions which target detached threads without some form of +# thread exit synchronisation. +# +# Usage: +# Set to any value in the range: 0 <= value < 2^wordsize. +# Set to 0 to emulate reusable thread ID behaviour like Linux or *BSD. +# Set to 1 for unique thread IDs like Solaris (this is the default). +# Set to some factor of 2^wordsize to emulate smaller word size types +# (i.e. will wrap sooner). This might be useful to emulate some embedded +# systems. +# +# define PTW32_THREAD_ID_REUSE_INCREMENT 0 +# +# ---------------------------------------------------------------------- + */ +#undef PTW32_THREAD_ID_REUSE_INCREMENT + + +/********************************************************************* + * Target specific groups + * + * If you find that these are incorrect or incomplete please report it + * to the pthreads-win32 maintainer. Thanks. + *********************************************************************/ +#ifdef WINCE +#define NEED_DUPLICATEHANDLE +#define NEED_CREATETHREAD +#define NEED_ERRNO +#define NEED_CALLOC +#define NEED_FTIME +//#define NEED_SEM +#define NEED_UNICODE_CONSTS +#define NEED_PROCESS_AFFINITY_MASK +#endif + +#ifdef _UWIN +#define HAVE_MODE_T +#define HAVE_STRUCT_TIMESPEC +#endif + +#ifdef __GNUC__ +#define HAVE_C_INLINE +#endif + +#ifdef __MINGW32__ +#define HAVE_MODE_T +#endif + +#ifdef __BORLANDC__ +#endif + +#ifdef __WATCOMC__ +#endif + +#ifdef __DMC__ +#define HAVE_SIGNAL_H +#define HAVE_C_INLINE +#endif + + + +#endif diff --git a/liblo/pthreads.2/create.c b/liblo/pthreads.2/create.c new file mode 100644 index 0000000..78ea45e --- /dev/null +++ b/liblo/pthreads.2/create.c @@ -0,0 +1,305 @@ +/* + * create.c + * + * Description: + * This translation unit implements routines associated with spawning a new + * thread. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#ifndef _UWIN +#include +#endif + +int +pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), void *arg) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function creates a thread running the start function, + * passing it the parameter value, 'arg'. The 'attr' + * argument specifies optional creation attributes. + * The identity of the new thread is returned + * via 'tid', which should not be NULL. + * + * PARAMETERS + * tid + * pointer to an instance of pthread_t + * + * attr + * optional pointer to an instance of pthread_attr_t + * + * start + * pointer to the starting routine for the new thread + * + * arg + * optional parameter passed to 'start' + * + * + * DESCRIPTION + * This function creates a thread running the start function, + * passing it the parameter value, 'arg'. The 'attr' + * argument specifies optional creation attributes. + * The identity of the new thread is returned + * via 'tid', which should not be the NULL pointer. + * + * RESULTS + * 0 successfully created thread, + * EINVAL attr invalid, + * EAGAIN insufficient resources. + * + * ------------------------------------------------------ + */ +{ + pthread_t thread; + ptw32_thread_t * tp; + register pthread_attr_t a; + HANDLE threadH = 0; + int result = EAGAIN; + int run = PTW32_TRUE; + ThreadParms *parms = NULL; + long stackSize; + int priority; + pthread_t self; + + /* + * Before doing anything, check that tid can be stored through + * without invoking a memory protection error (segfault). + * Make sure that the assignment below can't be optimised out by the compiler. + * This is assured by conditionally assigning *tid again at the end. + */ + tid->x = 0; + + if (attr != NULL) + { + a = *attr; + } + else + { + a = NULL; + } + + if ((thread = ptw32_new ()).p == NULL) + { + goto FAIL0; + } + + tp = (ptw32_thread_t *) thread.p; + + priority = tp->sched_priority; + + if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL) + { + goto FAIL0; + } + + parms->tid = thread; + parms->start = start; + parms->arg = arg; + +#if defined(HAVE_SIGSET_T) + + /* + * Threads inherit their initial sigmask from their creator thread. + */ + self = pthread_self(); + tp->sigmask = ((ptw32_thread_t *)self.p)->sigmask; + +#endif /* HAVE_SIGSET_T */ + + + if (a != NULL) + { + stackSize = a->stacksize; + tp->detachState = a->detachstate; + priority = a->param.sched_priority; + +#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) + /* WinCE */ +#else + /* Everything else */ + + /* + * Thread priority must be set to a valid system level + * without altering the value set by pthread_attr_setschedparam(). + */ + + /* + * PTHREAD_EXPLICIT_SCHED is the default because Win32 threads + * don't inherit their creator's priority. They are started with + * THREAD_PRIORITY_NORMAL (win32 value). The result of not supplying + * an 'attr' arg to pthread_create() is equivalent to defaulting to + * PTHREAD_EXPLICIT_SCHED and priority THREAD_PRIORITY_NORMAL. + */ + if (PTHREAD_INHERIT_SCHED == a->inheritsched) + { + /* + * If the thread that called pthread_create() is a Win32 thread + * then the inherited priority could be the result of a temporary + * system adjustment. This is not the case for POSIX threads. + */ +#if ! defined(HAVE_SIGSET_T) + self = pthread_self (); +#endif + priority = ((ptw32_thread_t *) self.p)->sched_priority; + } + +#endif + + } + else + { + /* + * Default stackSize + */ + stackSize = PTHREAD_STACK_MIN; + } + + tp->state = run ? PThreadStateInitial : PThreadStateSuspended; + + tp->keys = NULL; + + /* + * Threads must be started in suspended mode and resumed if necessary + * after _beginthreadex returns us the handle. Otherwise we set up a + * race condition between the creating and the created threads. + * Note that we also retain a local copy of the handle for use + * by us in case thread.p->threadH gets NULLed later but before we've + * finished with it here. + */ + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) + + tp->threadH = + threadH = + (HANDLE) _beginthreadex ((void *) NULL, /* No security info */ + (unsigned) stackSize, /* default stack size */ + ptw32_threadStart, + parms, + (unsigned) + CREATE_SUSPENDED, + (unsigned *) &(tp->thread)); + + if (threadH != 0) + { + if (a != NULL) + { + (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority); + } + + if (run) + { + ResumeThread (threadH); + } + } + +#else /* __MINGW32__ && ! __MSVCRT__ */ + + /* + * This lock will force pthread_threadStart() to wait until we have + * the thread handle and have set the priority. + */ + (void) pthread_mutex_lock (&tp->cancelLock); + + tp->threadH = + threadH = + (HANDLE) _beginthread (ptw32_threadStart, (unsigned) stackSize, /* default stack size */ + parms); + + /* + * Make the return code match _beginthreadex's. + */ + if (threadH == (HANDLE) - 1L) + { + tp->threadH = threadH = 0; + } + else + { + if (!run) + { + /* + * beginthread does not allow for create flags, so we do it now. + * Note that beginthread itself creates the thread in SUSPENDED + * mode, and then calls ResumeThread to start it. + */ + SuspendThread (threadH); + } + + if (a != NULL) + { + (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority); + } + } + + (void) pthread_mutex_unlock (&tp->cancelLock); + +#endif /* __MINGW32__ && ! __MSVCRT__ */ + + result = (threadH != 0) ? 0 : EAGAIN; + + /* + * Fall Through Intentionally + */ + + /* + * ------------ + * Failure Code + * ------------ + */ + +FAIL0: + if (result != 0) + { + + ptw32_threadDestroy (thread); + tp = NULL; + + if (parms != NULL) + { + free (parms); + } + } + else + { + *tid = thread; + } + +#ifdef _UWIN + if (result == 0) + pthread_count++; +#endif + return (result); + +} /* pthread_create */ diff --git a/liblo/pthreads.2/dll.c b/liblo/pthreads.2/dll.c new file mode 100644 index 0000000..067c98f --- /dev/null +++ b/liblo/pthreads.2/dll.c @@ -0,0 +1,92 @@ +/* + * dll.c + * + * Description: + * This translation unit implements DLL initialisation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef PTW32_STATIC_LIB + +#include "pthread.h" +#include "implement.h" + +#ifdef _MSC_VER +/* + * lpvReserved yields an unreferenced formal parameter; + * ignore it + */ +#pragma warning( disable : 4100 ) +#endif + +#ifdef __cplusplus +/* + * Dear c++: Please don't mangle this name. -thanks + */ +extern "C" +#endif /* __cplusplus */ + BOOL WINAPI +DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) +{ + BOOL result = PTW32_TRUE; + + switch (fdwReason) + { + + case DLL_PROCESS_ATTACH: + result = pthread_win32_process_attach_np (); + break; + + case DLL_THREAD_ATTACH: + /* + * A thread is being created + */ + result = pthread_win32_thread_attach_np (); + break; + + case DLL_THREAD_DETACH: + /* + * A thread is exiting cleanly + */ + result = pthread_win32_thread_detach_np (); + break; + + case DLL_PROCESS_DETACH: + (void) pthread_win32_thread_detach_np (); + result = pthread_win32_process_detach_np (); + break; + } + + return (result); + +} /* DllMain */ + +#endif /* PTW32_STATIC_LIB */ diff --git a/liblo/pthreads.2/errno.c b/liblo/pthreads.2/errno.c new file mode 100644 index 0000000..11fdd8a --- /dev/null +++ b/liblo/pthreads.2/errno.c @@ -0,0 +1,94 @@ +/* + * errno.c + * + * Description: + * This translation unit implements routines associated with spawning a new + * thread. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if defined(NEED_ERRNO) + +#include "pthread.h" +#include "implement.h" + +static int reallyBad = ENOMEM; + +/* + * Re-entrant errno. + * + * Each thread has it's own errno variable in pthread_t. + * + * The benefit of using the pthread_t structure + * instead of another TSD key is TSD keys are limited + * on Win32 to 64 per process. Secondly, to implement + * it properly without using pthread_t you'd need + * to dynamically allocate an int on starting the thread + * and store it manually into TLS and then ensure that you free + * it on thread termination. We get all that for free + * by simply storing the errno on the pthread_t structure. + * + * MSVC and Mingw32 already have their own thread-safe errno. + * + * #if defined( _REENTRANT ) || defined( _MT ) + * #define errno *_errno() + * + * int *_errno( void ); + * #else + * extern int errno; + * #endif + * + */ + +int * +_errno (void) +{ + pthread_t self; + int *result; + + if ((self = pthread_self ()) == NULL) + { + /* + * Yikes! unable to allocate a thread! + * Throw an exception? return an error? + */ + result = &reallyBad; + } + else + { + result = &(self->ptErrno); + } + + return (result); + +} /* _errno */ + +#endif /* (NEED_ERRNO) */ diff --git a/liblo/pthreads.2/exit.c b/liblo/pthreads.2/exit.c new file mode 100644 index 0000000..28c7196 --- /dev/null +++ b/liblo/pthreads.2/exit.c @@ -0,0 +1,44 @@ +/* + * exit.c + * + * Description: + * This translation unit implements routines associated with exiting from + * a thread. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#ifndef _UWIN +# include +#endif + +#include "pthread_exit.c" diff --git a/liblo/pthreads.2/fork.c b/liblo/pthreads.2/fork.c new file mode 100644 index 0000000..97d9ec2 --- /dev/null +++ b/liblo/pthreads.2/fork.c @@ -0,0 +1,39 @@ +/* + * fork.c + * + * Description: + * Implementation of fork() for POSIX threads. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "pthread.h" +#include "implement.h" diff --git a/liblo/pthreads.2/global.c b/liblo/pthreads.2/global.c new file mode 100644 index 0000000..0d90e97 --- /dev/null +++ b/liblo/pthreads.2/global.c @@ -0,0 +1,115 @@ +/* + * global.c + * + * Description: + * This translation unit instantiates data associated with the implementation + * as a whole. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int ptw32_processInitialized = PTW32_FALSE; +ptw32_thread_t * ptw32_threadReuseTop = PTW32_THREAD_REUSE_EMPTY; +ptw32_thread_t * ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY; +pthread_key_t ptw32_selfThreadKey = NULL; +pthread_key_t ptw32_cleanupKey = NULL; +pthread_cond_t ptw32_cond_list_head = NULL; +pthread_cond_t ptw32_cond_list_tail = NULL; + +int ptw32_concurrency = 0; + +/* What features have been auto-detaected */ +int ptw32_features = 0; + +BOOL ptw32_smp_system = PTW32_TRUE; /* Safer if assumed true initially. */ + +/* + * Function pointer to InterlockedCompareExchange if it exists, otherwise + * it will be set at runtime to a substitute local version with the same + * functionality but may be architecture specific. + */ +PTW32_INTERLOCKED_LONG + (WINAPI * ptw32_interlocked_compare_exchange) (PTW32_INTERLOCKED_LPLONG, + PTW32_INTERLOCKED_LONG, + PTW32_INTERLOCKED_LONG) = + NULL; + +/* + * Function pointer to QueueUserAPCEx if it exists, otherwise + * it will be set at runtime to a substitute routine which cannot unblock + * blocked threads. + */ +DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD) = NULL; + +/* + * Global lock for managing pthread_t struct reuse. + */ +CRITICAL_SECTION ptw32_thread_reuse_lock; + +/* + * Global lock for testing internal state of statically declared mutexes. + */ +CRITICAL_SECTION ptw32_mutex_test_init_lock; + +/* + * Global lock for testing internal state of PTHREAD_COND_INITIALIZER + * created condition variables. + */ +CRITICAL_SECTION ptw32_cond_test_init_lock; + +/* + * Global lock for testing internal state of PTHREAD_RWLOCK_INITIALIZER + * created read/write locks. + */ +CRITICAL_SECTION ptw32_rwlock_test_init_lock; + +/* + * Global lock for testing internal state of PTHREAD_SPINLOCK_INITIALIZER + * created spin locks. + */ +CRITICAL_SECTION ptw32_spinlock_test_init_lock; + +/* + * Global lock for condition variable linked list. The list exists + * to wake up CVs when a WM_TIMECHANGE message arrives. See + * w32_TimeChangeHandler.c. + */ +CRITICAL_SECTION ptw32_cond_list_lock; + +#ifdef _UWIN +/* + * Keep a count of the number of threads. + */ +int pthread_count = 0; +#endif diff --git a/liblo/pthreads.2/implement.h b/liblo/pthreads.2/implement.h new file mode 100644 index 0000000..6ee780c --- /dev/null +++ b/liblo/pthreads.2/implement.h @@ -0,0 +1,710 @@ +/* + * implement.h + * + * Definitions that don't need to be public. + * + * Keeps all the internals out of pthread.h + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef _IMPLEMENT_H +#define _IMPLEMENT_H + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x400 + +#include + +/* + * In case windows.h doesn't define it (e.g. WinCE perhaps) + */ +#ifdef WINCE +typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam); +#endif + +/* + * note: ETIMEDOUT is correctly defined in winsock.h + */ +#include + +/* + * In case ETIMEDOUT hasn't been defined above somehow. + */ +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#if !defined(malloc) +#include +#endif + +#if !defined(INT_MAX) +#include +#endif + +/* use local include files during development */ +#include "semaphore.h" +#include "sched.h" + +#if defined(HAVE_C_INLINE) || defined(__cplusplus) +#define INLINE inline +#else +#define INLINE +#endif + +#if defined (__MINGW32__) || (_MSC_VER >= 1300) +#define PTW32_INTERLOCKED_LONG long +#define PTW32_INTERLOCKED_LPLONG long* +#else +#define PTW32_INTERLOCKED_LONG PVOID +#define PTW32_INTERLOCKED_LPLONG PVOID* +#endif + +#if defined(__MINGW32__) +#include +#elif defined(__BORLANDC__) +#define int64_t ULONGLONG +#else +#define int64_t _int64 +#endif + +typedef enum +{ + /* + * This enumeration represents the state of the thread; + * The thread is still "alive" if the numeric value of the + * state is greater or equal "PThreadStateRunning". + */ + PThreadStateInitial = 0, /* Thread not running */ + PThreadStateRunning, /* Thread alive & kicking */ + PThreadStateSuspended, /* Thread alive but suspended */ + PThreadStateCancelPending, /* Thread alive but is */ + /* has cancelation pending. */ + PThreadStateCanceling, /* Thread alive but is */ + /* in the process of terminating */ + /* due to a cancellation request */ + PThreadStateException, /* Thread alive but exiting */ + /* due to an exception */ + PThreadStateLast +} +PThreadState; + + +typedef struct ptw32_thread_t_ ptw32_thread_t; + +struct ptw32_thread_t_ +{ +#ifdef _UWIN + DWORD dummy[5]; +#endif + DWORD thread; + HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */ + pthread_t ptHandle; /* This thread's permanent pthread_t handle */ + ptw32_thread_t * prevReuse; /* Links threads on reuse stack */ + volatile PThreadState state; + void *exitStatus; + void *parms; + int ptErrno; + int detachState; + pthread_mutex_t threadLock; /* Used for serialised access to public thread state */ + int sched_priority; /* As set, not as currently is */ + pthread_mutex_t cancelLock; /* Used for async-cancel safety */ + int cancelState; + int cancelType; + HANDLE cancelEvent; +#ifdef __CLEANUP_C + jmp_buf start_mark; +#endif /* __CLEANUP_C */ +#if HAVE_SIGSET_T + sigset_t sigmask; +#endif /* HAVE_SIGSET_T */ + int implicit:1; + void *keys; + void *nextAssoc; +}; + + +/* + * Special value to mark attribute objects as valid. + */ +#define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE) + +struct pthread_attr_t_ +{ + unsigned long valid; + void *stackaddr; + size_t stacksize; + int detachstate; + struct sched_param param; + int inheritsched; + int contentionscope; +#if HAVE_SIGSET_T + sigset_t sigmask; +#endif /* HAVE_SIGSET_T */ +}; + + +/* + * ==================== + * ==================== + * Semaphores, Mutexes and Condition Variables + * ==================== + * ==================== + */ + +struct sem_t_ +{ + int value; + pthread_mutex_t lock; + HANDLE sem; +#ifdef NEED_SEM + int leftToUnblock; +#endif +}; + +#define PTW32_OBJECT_AUTO_INIT ((void *) -1) +#define PTW32_OBJECT_INVALID NULL + +struct pthread_mutex_t_ +{ + LONG lock_idx; /* Provides exclusive access to mutex state + via the Interlocked* mechanism. + 0: unlocked/free. + 1: locked - no other waiters. + -1: locked - with possible other waiters. + */ + int recursive_count; /* Number of unlocks a thread needs to perform + before the lock is released (recursive + mutexes only). */ + int kind; /* Mutex type. */ + pthread_t ownerThread; + HANDLE event; /* Mutex release notification to waiting + threads. */ +}; + +struct pthread_mutexattr_t_ +{ + int pshared; + int kind; +}; + +/* + * Possible values, other than PTW32_OBJECT_INVALID, + * for the "interlock" element in a spinlock. + * + * In this implementation, when a spinlock is initialised, + * the number of cpus available to the process is checked. + * If there is only one cpu then "interlock" is set equal to + * PTW32_SPIN_USE_MUTEX and u.mutex is a initialised mutex. + * If the number of cpus is greater than 1 then "interlock" + * is set equal to PTW32_SPIN_UNLOCKED and the number is + * stored in u.cpus. This arrangement allows the spinlock + * routines to attempt an InterlockedCompareExchange on "interlock" + * immediately and, if that fails, to try the inferior mutex. + * + * "u.cpus" isn't used for anything yet, but could be used at + * some point to optimise spinlock behaviour. + */ +#define PTW32_SPIN_UNLOCKED (1) +#define PTW32_SPIN_LOCKED (2) +#define PTW32_SPIN_USE_MUTEX (3) + +struct pthread_spinlock_t_ +{ + long interlock; /* Locking element for multi-cpus. */ + union + { + int cpus; /* No. of cpus if multi cpus, or */ + pthread_mutex_t mutex; /* mutex if single cpu. */ + } u; +}; + +struct pthread_barrier_t_ +{ + unsigned int nCurrentBarrierHeight; + unsigned int nInitialBarrierHeight; + int iStep; + int pshared; + sem_t semBarrierBreeched[2]; +}; + +struct pthread_barrierattr_t_ +{ + int pshared; +}; + +struct pthread_key_t_ +{ + DWORD key; + void (*destructor) (void *); + pthread_mutex_t keyLock; + void *threads; +}; + + +typedef struct ThreadParms ThreadParms; +typedef struct ThreadKeyAssoc ThreadKeyAssoc; + +struct ThreadParms +{ + pthread_t tid; + void *(*start) (void *); + void *arg; +}; + + +struct pthread_cond_t_ +{ + long nWaitersBlocked; /* Number of threads blocked */ + long nWaitersGone; /* Number of threads timed out */ + long nWaitersToUnblock; /* Number of threads to unblock */ + sem_t semBlockQueue; /* Queue up threads waiting for the */ + /* condition to become signalled */ + sem_t semBlockLock; /* Semaphore that guards access to */ + /* | waiters blocked count/block queue */ + /* +-> Mandatory Sync.LEVEL-1 */ + pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */ + /* | waiters (to)unblock(ed) counts */ + /* +-> Optional* Sync.LEVEL-2 */ + pthread_cond_t next; /* Doubly linked list */ + pthread_cond_t prev; +}; + + +struct pthread_condattr_t_ +{ + int pshared; +}; + +#define PTW32_RWLOCK_MAGIC 0xfacade2 + +struct pthread_rwlock_t_ +{ + pthread_mutex_t mtxExclusiveAccess; + pthread_mutex_t mtxSharedAccessCompleted; + pthread_cond_t cndSharedAccessCompleted; + int nSharedAccessCount; + int nExclusiveAccessCount; + int nCompletedSharedAccessCount; + int nMagic; +}; + +struct pthread_rwlockattr_t_ +{ + int pshared; +}; + +/* + * MCS lock queue node - see ptw32_MCS_lock.c + */ +struct ptw32_mcs_node_t_ +{ + struct ptw32_mcs_node_t_ **lock; /* ptr to tail of queue */ + struct ptw32_mcs_node_t_ *next; /* ptr to successor in queue */ + LONG readyFlag; /* set after lock is released by + predecessor */ + LONG nextFlag; /* set after 'next' ptr is set by + successor */ +}; + +typedef struct ptw32_mcs_node_t_ ptw32_mcs_local_node_t; +typedef struct ptw32_mcs_node_t_ *ptw32_mcs_lock_t; + + +struct ThreadKeyAssoc +{ + /* + * Purpose: + * This structure creates an association between a thread and a key. + * It is used to implement the implicit invocation of a user defined + * destroy routine for thread specific data registered by a user upon + * exiting a thread. + * + * Graphically, the arrangement is as follows, where: + * + * K - Key with destructor + * (head of chain is key->threads) + * T - Thread that has called pthread_setspecific(Kn) + * (head of chain is thread->keys) + * A - Association. Each association is a node at the + * intersection of two doubly-linked lists. + * + * T1 T2 T3 + * | | | + * | | | + * K1 -----+-----A-----A-----> + * | | | + * | | | + * K2 -----A-----A-----+-----> + * | | | + * | | | + * K3 -----A-----+-----A-----> + * | | | + * | | | + * V V V + * + * Access to the association is guarded by two locks: the key's + * general lock (guarding the row) and the thread's general + * lock (guarding the column). This avoids the need for a + * dedicated lock for each association, which not only consumes + * more handles but requires that: before the lock handle can + * be released - both the key must be deleted and the thread + * must have called the destructor. The two-lock arrangement + * allows the resources to be freed as soon as either thread or + * key is concluded. + * + * To avoid deadlock: whenever both locks are required, the key + * and thread locks are always acquired in the order: key lock + * then thread lock. An exception to this exists when a thread + * calls the destructors, however this is done carefully to + * avoid deadlock. + * + * An association is created when a thread first calls + * pthread_setspecific() on a key that has a specified + * destructor. + * + * An association is destroyed either immediately after the + * thread calls the key destructor function on thread exit, or + * when the key is deleted. + * + * Attributes: + * thread + * reference to the thread that owns the + * association. This is actually the pointer to the + * thread struct itself. Since the association is + * destroyed before the thread exits, this can never + * point to a different logical thread to the one that + * created the assoc, i.e. after thread struct reuse. + * + * key + * reference to the key that owns the association. + * + * nextKey + * The pthread_t->keys attribute is the head of a + * chain of associations that runs through the nextKey + * link. This chain provides the 1 to many relationship + * between a pthread_t and all pthread_key_t on which + * it called pthread_setspecific. + * + * prevKey + * Similarly. + * + * nextThread + * The pthread_key_t->threads attribute is the head of + * a chain of assoctiations that runs through the + * nextThreads link. This chain provides the 1 to many + * relationship between a pthread_key_t and all the + * PThreads that have called pthread_setspecific for + * this pthread_key_t. + * + * prevThread + * Similarly. + * + * Notes: + * 1) As soon as either the key or the thread is no longer + * referencing the association, it can be destroyed. The + * association will be removed from both chains. + * + * 2) Under WIN32, an association is only created by + * pthread_setspecific if the user provided a + * destroyRoutine when they created the key. + * + * + */ + ptw32_thread_t * thread; + pthread_key_t key; + ThreadKeyAssoc *nextKey; + ThreadKeyAssoc *nextThread; + ThreadKeyAssoc *prevKey; + ThreadKeyAssoc *prevThread; +}; + + +#ifdef __CLEANUP_SEH +/* + * -------------------------------------------------------------- + * MAKE_SOFTWARE_EXCEPTION + * This macro constructs a software exception code following + * the same format as the standard Win32 error codes as defined + * in WINERROR.H + * Values are 32 bit values layed out as follows: + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---+-+-+-----------------------+-------------------------------+ + * |Sev|C|R| Facility | Code | + * +---+-+-+-----------------------+-------------------------------+ + * + * Severity Values: + */ +#define SE_SUCCESS 0x00 +#define SE_INFORMATION 0x01 +#define SE_WARNING 0x02 +#define SE_ERROR 0x03 + +#define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \ +( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \ + ( 1 << 29 ) | /* MS=0, User=1 */ \ + ( 0 << 28 ) | /* Reserved */ \ + ( (_facility) << 16 ) | /* Facility Code */ \ + ( (_exception) << 0 ) /* Exception Code */ \ + ) ) + +/* + * We choose one specific Facility/Error code combination to + * identify our software exceptions vs. WIN32 exceptions. + * We store our actual component and error code within + * the optional information array. + */ +#define EXCEPTION_PTW32_SERVICES \ + MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \ + PTW32_SERVICES_FACILITY, \ + PTW32_SERVICES_ERROR ) + +#define PTW32_SERVICES_FACILITY 0xBAD +#define PTW32_SERVICES_ERROR 0xDEED + +#endif /* __CLEANUP_SEH */ + +/* + * Services available through EXCEPTION_PTW32_SERVICES + * and also used [as parameters to ptw32_throw()] as + * generic exception selectors. + */ + +#define PTW32_EPS_EXIT (1) +#define PTW32_EPS_CANCEL (2) + + +/* Useful macros */ +#define PTW32_MAX(a,b) ((a)<(b)?(b):(a)) +#define PTW32_MIN(a,b) ((a)>(b)?(b):(a)) + + +/* Declared in global.c */ +extern PTW32_INTERLOCKED_LONG (WINAPI * + ptw32_interlocked_compare_exchange) + (PTW32_INTERLOCKED_LPLONG, PTW32_INTERLOCKED_LONG, PTW32_INTERLOCKED_LONG); + +/* Declared in pthread_cancel.c */ +extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD); + +/* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */ +#define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *) 1) + +extern int ptw32_processInitialized; +extern ptw32_thread_t * ptw32_threadReuseTop; +extern ptw32_thread_t * ptw32_threadReuseBottom; +extern pthread_key_t ptw32_selfThreadKey; +extern pthread_key_t ptw32_cleanupKey; +extern pthread_cond_t ptw32_cond_list_head; +extern pthread_cond_t ptw32_cond_list_tail; + +extern int ptw32_mutex_default_kind; + +extern int ptw32_concurrency; + +extern int ptw32_features; + +extern BOOL ptw32_smp_system; /* True: SMP system, False: Uni-processor system */ + +extern CRITICAL_SECTION ptw32_thread_reuse_lock; +extern CRITICAL_SECTION ptw32_mutex_test_init_lock; +extern CRITICAL_SECTION ptw32_cond_list_lock; +extern CRITICAL_SECTION ptw32_cond_test_init_lock; +extern CRITICAL_SECTION ptw32_rwlock_test_init_lock; +extern CRITICAL_SECTION ptw32_spinlock_test_init_lock; + +#ifdef _UWIN +extern int pthread_count; +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ===================== + * ===================== + * Forward Declarations + * ===================== + * ===================== + */ + + int ptw32_is_attr (const pthread_attr_t * attr); + + int ptw32_cond_check_need_init (pthread_cond_t * cond); + int ptw32_mutex_check_need_init (pthread_mutex_t * mutex); + int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock); + + PTW32_INTERLOCKED_LONG WINAPI + ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location, + PTW32_INTERLOCKED_LONG value, + PTW32_INTERLOCKED_LONG comparand); + + LONG WINAPI + ptw32_InterlockedExchange (LPLONG location, + LONG value); + + DWORD + ptw32_RegisterCancelation (PAPCFUNC callback, + HANDLE threadH, DWORD callback_arg); + + int ptw32_processInitialize (void); + + void ptw32_processTerminate (void); + + void ptw32_threadDestroy (pthread_t tid); + + void ptw32_pop_cleanup_all (int execute); + + pthread_t ptw32_new (void); + + pthread_t ptw32_threadReusePop (void); + + void ptw32_threadReusePush (pthread_t thread); + + int ptw32_getprocessors (int *count); + + int ptw32_setthreadpriority (pthread_t thread, int policy, int priority); + + void ptw32_rwlock_cancelwrwait (void *arg); + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + unsigned __stdcall +#else + void +#endif + ptw32_threadStart (void *vthreadParms); + + void ptw32_callUserDestroyRoutines (pthread_t thread); + + int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key); + + void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc); + + int ptw32_semwait (sem_t * sem); + + DWORD ptw32_relmillisecs (const struct timespec * abstime); + + void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node); + + void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node); + +#ifdef NEED_FTIME + void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft); + void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts); +#endif + +/* Declared in misc.c */ +#ifdef NEED_CALLOC +#define calloc(n, s) ptw32_calloc(n, s) + void *ptw32_calloc (size_t n, size_t s); +#endif + +/* Declared in private.c */ + void ptw32_throw (DWORD exception); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#ifdef _UWIN_ +# ifdef _MT +# ifdef __cplusplus +extern "C" +{ +# endif + _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *), + unsigned, void *); + _CRTIMP void __cdecl _endthread (void); + _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned, + unsigned (__stdcall *) (void *), + void *, unsigned, unsigned *); + _CRTIMP void __cdecl _endthreadex (unsigned); +# ifdef __cplusplus +} +# endif +# endif +#else +# include +#endif + + +/* + * Defaults. Could be overridden when building the inlined version of the dll. + * See ptw32_InterlockedCompareExchange.c + */ +#ifndef PTW32_INTERLOCKED_COMPARE_EXCHANGE +#define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_interlocked_compare_exchange +#endif + +#ifndef PTW32_INTERLOCKED_EXCHANGE +#define PTW32_INTERLOCKED_EXCHANGE InterlockedExchange +#endif + + +/* + * Check for old and new versions of cygwin. See the FAQ file: + * + * Question 1 - How do I get pthreads-win32 to link under Cygwin or Mingw32? + * + * Patch by Anders Norlander + */ +#if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(NEED_CREATETHREAD) + +/* + * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE + * in order to avoid warnings because of return type + */ + +#define _beginthreadex(security, \ + stack_size, \ + start_proc, \ + arg, \ + flags, \ + pid) \ + CreateThread(security, \ + stack_size, \ + (LPTHREAD_START_ROUTINE) start_proc, \ + arg, \ + flags, \ + pid) + +#define _endthreadex ExitThread + +#endif /* __CYGWIN32__ || __CYGWIN__ || NEED_CREATETHREAD */ + + +#endif /* _IMPLEMENT_H */ diff --git a/liblo/pthreads.2/manual/ChangeLog b/liblo/pthreads.2/manual/ChangeLog new file mode 100644 index 0000000..9550115 --- /dev/null +++ b/liblo/pthreads.2/manual/ChangeLog @@ -0,0 +1,62 @@ +2005-05-06 Ross Johnson + + * PortabilityIssues.html: Was nonPortableIssues.html. + * index.html: Updated; add table of contents at top. + * *.html: Add Pthreads-win32 header info; add link back to the + index page 'index.html'. + +2005-05-06 Ross Johnson + + * index.html: New. + * nonPortableIssues.html: New. + * pthread_attr_init.html: New. + * pthread_attr_setstackaddr.html: New. + * pthread_attr_setstacksize.html: New. + * pthread_barrierattr_init.html: New. + * pthread_barrierattr_setpshared.html: New. + * pthread_barrier_init.html: New. + * pthread_barrier_wait.html: New. + * pthreadCancelableWait.html: New. + * pthread_cancel.html: New. + * pthread_cleanup_push.html: New. + * pthread_condattr_init.html: New. + * pthread_condattr_setpshared.html: New. + * pthread_cond_init.html: New. + * pthread_create.html: New. + * pthread_delay_np.html: New. + * pthread_detach.html: New. + * pthread_equal.html: New. + * pthread_exit.html: New. + * pthread_getw32threadhandle_np.html: New. + * pthread_join.html: New. + * pthread_key_create.html: New. + * pthread_kill.html: New. + * pthread_mutexattr_init.html: New. + * pthread_mutexattr_setpshared.html: New. + * pthread_mutex_init.html: New. + * pthread_num_processors_np.html: New. + * pthread_once.html: New. + * pthread_rwlockattr_init.html: New. + * pthread_rwlockattr_setpshared.html: New. + * pthread_rwlock_init.html: New. + * pthread_rwlock_rdlock.html: New. + * pthread_rwlock_timedrdlock.html: New. + * pthread_rwlock_timedwrlock.html: New. + * pthread_rwlock_unlock.html: New. + * pthread_rwlock_wrlock.html: New. + * pthread_self.html: New. + * pthread_setcancelstate.html: New. + * pthread_setcanceltype.html: New. + * pthread_setconcurrency.html: New. + * pthread_setschedparam.html: New. + * pthread_spin_init.html: New. + * pthread_spin_lock.html: New. + * pthread_spin_unlock.html: New. + * pthread_timechange_handler_np.html: New. + * pthread_win32_attach_detach_np.html: New. + * pthread_win32_test_features_np.html: New. + * sched_get_priority_max.html: New. + * sched_getscheduler.html: New. + * sched_setscheduler.html: New. + * sched_yield.html: New. + * sem_init.html: New. diff --git a/liblo/pthreads.2/manual/PortabilityIssues.html b/liblo/pthreads.2/manual/PortabilityIssues.html new file mode 100644 index 0000000..d97d0bd --- /dev/null +++ b/liblo/pthreads.2/manual/PortabilityIssues.html @@ -0,0 +1,718 @@ + + + + + PORTABILITYISSUES manual page + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    Portability issues

    +

    Synopsis

    +

    Thread priority

    +

    Description

    +

    Thread priority

    +

    POSIX defines a single contiguous range +of numbers that determine a thread's priority. Win32 defines priority +classes - and priority levels relative to these classes. Classes are +simply priority base levels that the defined priority levels are +relative to such that, changing a process's priority class will +change the priority of all of it's threads, while the threads retain +the same relativity to each other.

    +

    A Win32 system defines a single +contiguous monotonic range of values that define system priority +levels, just like POSIX. However, Win32 restricts individual threads +to a subset of this range on a per-process basis.

    +

    The following table shows the base +priority levels for combinations of priority class and priority value +in Win32.

    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +


    +

    +
    +

    Process Priority Class

    +
    +

    Thread Priority Level

    +
    +

    1

    +
    +

    IDLE_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_IDLE

    +
    +

    1

    +
    +

    BELOW_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_IDLE

    +
    +

    1

    +
    +

    NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_IDLE

    +
    +

    1

    +
    +

    ABOVE_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_IDLE

    +
    +

    1

    +
    +

    HIGH_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_IDLE

    +
    +

    2

    +
    +

    IDLE_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_LOWEST

    +
    +

    3

    +
    +

    IDLE_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_BELOW_NORMAL

    +
    +

    4

    +
    +

    IDLE_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_NORMAL

    +
    +

    4

    +
    +

    BELOW_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_LOWEST

    +
    +

    5

    +
    +

    IDLE_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_ABOVE_NORMAL

    +
    +

    5

    +
    +

    BELOW_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_BELOW_NORMAL

    +
    +

    5

    +
    +

    Background NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_LOWEST

    +
    +

    6

    +
    +

    IDLE_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_HIGHEST

    +
    +

    6

    +
    +

    BELOW_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_NORMAL

    +
    +

    6

    +
    +

    Background NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_BELOW_NORMAL

    +
    +

    7

    +
    +

    BELOW_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_ABOVE_NORMAL

    +
    +

    7

    +
    +

    Background NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_NORMAL

    +
    +

    7

    +
    +

    Foreground NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_LOWEST

    +
    +

    8

    +
    +

    BELOW_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_HIGHEST

    +
    +

    8

    +
    +

    NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_ABOVE_NORMAL

    +
    +

    8

    +
    +

    Foreground NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_BELOW_NORMAL

    +
    +

    8

    +
    +

    ABOVE_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_LOWEST

    +
    +

    9

    +
    +

    NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_HIGHEST

    +
    +

    9

    +
    +

    Foreground NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_NORMAL

    +
    +

    9

    +
    +

    ABOVE_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_BELOW_NORMAL

    +
    +

    10

    +
    +

    Foreground NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_ABOVE_NORMAL

    +
    +

    10

    +
    +

    ABOVE_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_NORMAL

    +
    +

    11

    +
    +

    Foreground NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_HIGHEST

    +
    +

    11

    +
    +

    ABOVE_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_ABOVE_NORMAL

    +
    +

    11

    +
    +

    HIGH_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_LOWEST

    +
    +

    12

    +
    +

    ABOVE_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_HIGHEST

    +
    +

    12

    +
    +

    HIGH_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_BELOW_NORMAL

    +
    +

    13

    +
    +

    HIGH_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_NORMAL

    +
    +

    14

    +
    +

    HIGH_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_ABOVE_NORMAL

    +
    +

    15

    +
    +

    HIGH_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_HIGHEST

    +
    +

    15

    +
    +

    HIGH_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_TIME_CRITICAL

    +
    +

    15

    +
    +

    IDLE_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_TIME_CRITICAL

    +
    +

    15

    +
    +

    BELOW_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_TIME_CRITICAL

    +
    +

    15

    +
    +

    NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_TIME_CRITICAL

    +
    +

    15

    +
    +

    ABOVE_NORMAL_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_TIME_CRITICAL

    +
    +

    16

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_IDLE

    +
    +

    17

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    -7

    +
    +

    18

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    -6

    +
    +

    19

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    -5

    +
    +

    20

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    -4

    +
    +

    21

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    -3

    +
    +

    22

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_LOWEST

    +
    +

    23

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_BELOW_NORMAL

    +
    +

    24

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_NORMAL

    +
    +

    25

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_ABOVE_NORMAL

    +
    +

    26

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_HIGHEST

    +
    +

    27

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    3

    +
    +

    28

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    4

    +
    +

    29

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    5

    +
    +

    30

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    6

    +
    +

    31

    +
    +

    REALTIME_PRIORITY_CLASS

    +
    +

    THREAD_PRIORITY_TIME_CRITICAL

    +
    +
    +
    +

    Windows NT: Values -7, -6, -5, -4, -3, 3, +4, 5, and 6 are not supported.

    +

    As you can see, the real priority levels +available to any individual Win32 thread are non-contiguous.

    +

    An application using Pthreads-w32 should +not make assumptions about the numbers used to represent thread +priority levels, except that they are monotonic between the values +returned by sched_get_priority_min() and sched_get_priority_max(). +E.g. Windows 95, 98, NT, 2000, XP make available a non-contiguous +range of numbers between -15 and 15, while at least one version of +WinCE (3.0) defines the minimum priority (THREAD_PRIORITY_LOWEST) as +5, and the maximum priority (THREAD_PRIORITY_HIGHEST) as 1.

    +

    Internally, pthreads-win32 maps any +priority levels between THREAD_PRIORITY_IDLE and +THREAD_PRIORITY_LOWEST to THREAD_PRIORITY_LOWEST, or between +THREAD_PRIORITY_TIME_CRITICAL and THREAD_PRIORITY_HIGHEST to +THREAD_PRIORITY_HIGHEST. Currently, this also applies to +REALTIME_PRIORITY_CLASS even if levels -7, -6, -5, -4, -3, 3, 4, 5, +and 6 are supported.

    +

    If it wishes, a Win32 application using +pthreads-w32 can use the Win32 defined priority macros +THREAD_PRIORITY_IDLE through THREAD_PRIORITY_TIME_CRITICAL.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +

    See also

    +



    +

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/index.html b/liblo/pthreads.2/manual/index.html new file mode 100644 index 0000000..2fa01d2 --- /dev/null +++ b/liblo/pthreads.2/manual/index.html @@ -0,0 +1,146 @@ + + + + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Table of Contents

    +

    POSIX +threads API reference
    Miscellaneous +POSIX thread safe routines provided by Pthreads-w32
    Non-portable +Pthreads-w32 routines
    Other

    +

    POSIX threads API reference

    +

    pthread_attr_destroy

    +

    pthread_attr_getdetachstate

    +

    pthread_attr_getinheritsched

    +

    pthread_attr_getschedparam

    +

    pthread_attr_getschedpolicy

    +

    pthread_attr_getscope

    +

    pthread_attr_getstackaddr

    +

    pthread_attr_getstacksize

    +

    pthread_attr_init

    +

    pthread_attr_setdetachstate

    +

    pthread_attr_setinheritsched

    +

    pthread_attr_setschedparam

    +

    pthread_attr_setschedpolicy

    +

    pthread_attr_setscope

    +

    pthread_attr_setstackaddr

    +

    pthread_attr_setstacksize

    +

    pthread_barrierattr_destroy

    +

    pthread_barrierattr_getpshared

    +

    pthread_barrierattr_init

    +

    pthread_barrierattr_setpshared

    +

    pthread_barrier_destroy

    +

    pthread_barrier_init

    +

    pthread_barrier_wait

    +

    pthread_cancel

    +

    pthread_cleanup_pop

    +

    pthread_cleanup_push

    +

    pthread_condattr_destroy

    +

    pthread_condattr_getpshared

    +

    pthread_condattr_init

    +

    pthread_condattr_setpshared

    +

    pthread_cond_broadcast

    +

    pthread_cond_destroy

    +

    pthread_cond_init

    +

    pthread_cond_signal

    +

    pthread_cond_timedwait

    +

    pthread_cond_wait

    +

    pthread_create

    +

    pthread_detach

    +

    pthread_equal

    +

    pthread_exit

    +

    pthread_getconcurrency

    +

    pthread_getschedparam

    +

    pthread_getspecific

    +

    pthread_join

    +

    pthread_key_create

    +

    pthread_key_delete

    +

    pthread_kill

    +

    pthread_mutexattr_destroy

    +

    pthread_mutexattr_getkind_np

    +

    pthread_mutexattr_getpshared

    +

    pthread_mutexattr_gettype

    +

    pthread_mutexattr_init

    +

    pthread_mutexattr_setkind_np

    +

    pthread_mutexattr_setpshared

    +

    pthread_mutexattr_settype

    +

    pthread_mutex_destroy

    +

    pthread_mutex_init

    +

    pthread_mutex_lock

    +

    pthread_mutex_timedlock

    +

    pthread_mutex_trylock

    +

    pthread_mutex_unlock

    +

    pthread_once

    +

    pthread_rwlockattr_destroy

    +

    pthread_rwlockattr_getpshared

    +

    pthread_rwlockattr_init

    +

    pthread_rwlockattr_setpshared

    +

    pthread_rwlock_destroy

    +

    pthread_rwlock_init

    +

    pthread_rwlock_rdlock

    +

    pthread_rwlock_timedrdlock

    +

    pthread_rwlock_timedwrlock

    +

    pthread_rwlock_tryrdlock

    +

    pthread_rwlock_trywrlock

    +

    pthread_rwlock_unlock

    +

    pthread_rwlock_wrlock

    +

    pthread_self

    +

    pthread_setcancelstate

    +

    pthread_setcanceltype

    +

    pthread_setconcurrency

    +

    pthread_setschedparam

    +

    pthread_setspecific

    +

    pthread_sigmask

    +

    pthread_spin_destroy

    +

    pthread_spin_init

    +

    pthread_spin_lock

    +

    pthread_spin_trylock

    +

    pthread_spin_unlock

    +

    pthread_testcancel

    +

    sched_get_priority_max

    +

    sched_get_priority_min

    +

    sched_getscheduler

    +

    sched_setscheduler

    +

    sched_yield

    +

    sem_close

    +

    sem_destroy

    +

    sem_getvalue

    +

    sem_init

    +

    sem_open

    +

    sem_post

    +

    sem_post_multiple

    +

    sem_timedwait

    +

    sem_trywait

    +

    sem_unlink

    +

    sem_wait

    +

    sigwait

    +

    Miscellaneous POSIX thread safe +routines provided by Pthreads-w32

    +

    asctime_r

    +

    ctime_r

    +

    gmtime_r

    +

    localtime_r

    +

    rand_r

    +

    Non-portable Pthreads-w32 routines

    +

    pthreadCancelableTimedWait

    +

    pthreadCancelableWait

    +

    pthread_delay_np

    +

    pthread_getw32threadhandle_np

    +

    pthread_num_processors_np

    +

    pthread_win32_test_features_np

    +

    pthread_timechange_handler_np

    +

    pthread_win32_process_attach_np

    +

    pthread_win32_process_detach_np

    +

    pthread_win32_thread_attach_np

    +

    pthread_win32_thread_detach_np

    +

    Other

    +

    Portability +issues

    + + diff --git a/liblo/pthreads.2/manual/pthreadCancelableWait.html b/liblo/pthreads.2/manual/pthreadCancelableWait.html new file mode 100644 index 0000000..ae5e80d --- /dev/null +++ b/liblo/pthreads.2/manual/pthreadCancelableWait.html @@ -0,0 +1,86 @@ + + + + + PTHREADCANCELLABLEWAIT manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthreadCancelableTimedWait, +pthreadCancelableWait – provide cancellation hooks for user Win32 +routines

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthreadCancelableTimedWait (HANDLE waitHandle, +DWORD timeout);

    +

    int pthreadCancelableWait (HANDLE waitHandle);

    +

    Description

    +

    These two functions provide hooks into the pthread_cancel() +mechanism that will allow you to wait on a Windows handle and make it +a cancellation point. Both functions block until either the given +Win32 HANDLE is signalled, or pthread_cancel() +has been called. They are implemented using WaitForMultipleObjects +on waitHandle and the manually reset Win32 event handle that +is the target of pthread_cancel(). +These routines may be called from Win32 native threads but +pthread_cancel() will +require that thread's POSIX thread ID that the thread must retrieve +using pthread_self().

    +

    pthreadCancelableTimedWait is the timed version that will +return with the code ETIMEDOUT if the interval timeout +milliseconds elapses before waitHandle is signalled.

    +

    Cancellation

    +

    These routines allow routines that block on Win32 HANDLEs to be +cancellable via pthread_cancel().

    +

    Return Value

    +



    +

    +

    Errors

    +

    The pthreadCancelableTimedWait function returns the +following error code on error: +

    +
    +
    +
    ETIMEDOUT +
    +
    +

    +The interval timeout milliseconds elapsed before waitHandle +was signalled.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +

    See also

    +

    pthread_cancel(), +pthread_self()

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_attr_init.html b/liblo/pthreads.2/manual/pthread_attr_init.html new file mode 100644 index 0000000..7da0248 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_attr_init.html @@ -0,0 +1,280 @@ + + + + + PTHREAD_ATTR_INIT(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_attr_init, pthread_attr_destroy, +pthread_attr_setdetachstate, pthread_attr_getdetachstate, +pthread_attr_setschedparam, pthread_attr_getschedparam, +pthread_attr_setschedpolicy, pthread_attr_getschedpolicy, +pthread_attr_setinheritsched, pthread_attr_getinheritsched, +pthread_attr_setscope, pthread_attr_getscope - thread creation +attributes +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_attr_init(pthread_attr_t *attr); +

    +

    int pthread_attr_destroy(pthread_attr_t *attr); +

    +

    int pthread_attr_setdetachstate(pthread_attr_t *attr, +int detachstate); +

    +

    int pthread_attr_getdetachstate(const pthread_attr_t *attr, +int *detachstate); +

    +

    int pthread_attr_setschedpolicy(pthread_attr_t *attr, +int policy); +

    +

    int pthread_attr_getschedpolicy(const pthread_attr_t *attr, +int *policy); +

    +

    int pthread_attr_setschedparam(pthread_attr_t *attr, +const struct sched_param *param); +

    +

    int pthread_attr_getschedparam(const pthread_attr_t *attr, +struct sched_param *param); +

    +

    int pthread_attr_setinheritsched(pthread_attr_t *attr, +int inherit); +

    +

    int pthread_attr_getinheritsched(const pthread_attr_t *attr, +int *inherit); +

    +

    int pthread_attr_setscope(pthread_attr_t *attr, +int scope); +

    +

    int pthread_attr_getscope(const pthread_attr_t *attr, +int *scope); +

    +

    Description

    +

    Setting attributes for threads is achieved by filling a thread +attribute object attr of type pthread_attr_t, then +passing it as second argument to pthread_create(3) +. Passing NULL is equivalent to passing a thread attribute +object with all attributes set to their default values. +

    +

    pthread_attr_init initializes the thread attribute object +attr and fills it with default values for the attributes. (The +default values are listed below for each attribute.) +

    +

    Each attribute attrname (see below for a list of all +attributes) can be individually set using the function +pthread_attr_setattrname and retrieved using the +function pthread_attr_getattrname. +

    +

    pthread_attr_destroy destroys a thread attribute object, +which must not then be reused until it is reinitialized. +

    +

    Attribute objects are consulted only when creating a new thread. +The same attribute object can be used for creating several threads. +Modifying an attribute object after a call to pthread_create +does not change the attributes of the thread previously created. +

    +

    The following thread attributes are supported: +

    +

    detachstate

    +

    Control whether the thread is created in the joinable state (value +PTHREAD_CREATE_JOINABLE) or in the detached state ( +PTHREAD_CREATE_DETACHED). +

    +

    Default value: PTHREAD_CREATE_JOINABLE. +

    +

    In the joinable state, another thread can synchronize on the +thread termination and recover its termination code using +pthread_join(3) . When a +joinable thread terminates, some of the thread resources are kept +allocated, and released only when another thread performs +pthread_join(3) on that +thread. +

    +

    In the detached state, the thread's resources are released +immediately when it terminates. pthread_join(3) +cannot be used to synchronize on the thread termination. +

    +

    A thread created in the joinable state can later be put in the +detached thread using pthread_detach(3) +. +

    +

    schedpolicy

    +

    Select the scheduling policy for the thread: one of SCHED_OTHER +(regular, non-real-time scheduling), SCHED_RR (real-time, +round-robin) or SCHED_FIFO (real-time, first-in first-out). +

    +

    Pthreads-w32 only supports SCHED_OTHER - attempting +to set one of the other policies will return an error ENOTSUP.

    +

    Default value: SCHED_OTHER. +

    +

    Pthreads-w32 only supports SCHED_OTHER - attempting +to set one of the other policies will return an error ENOTSUP.

    +

    The scheduling policy of a thread can be changed after creation +with pthread_setschedparam(3) +. +

    +

    schedparam

    +

    Contain the scheduling parameters (essentially, the scheduling +priority) for the thread.

    +

    Pthreads-w32 supports the priority levels defined by the +Windows system it is running on. Under Windows, thread priorities are +relative to the process priority class, which must be set via the +Windows W32 API.

    +

    Default value: priority is 0 (Win32 level THREAD_PRIORITY_NORMAL). +

    +

    The scheduling priority of a thread can be changed after creation +with pthread_setschedparam(3) +. +

    +

    inheritsched

    +

    Indicate whether the scheduling policy and scheduling parameters +for the newly created thread are determined by the values of the +schedpolicy and schedparam attributes (value +PTHREAD_EXPLICIT_SCHED) or are inherited from the parent +thread (value PTHREAD_INHERIT_SCHED). +

    +

    Default value: PTHREAD_EXPLICIT_SCHED. +

    +

    scope

    +

    Define the scheduling contention scope for the created thread. The +only value supported in the Pthreads-w32 implementation is +PTHREAD_SCOPE_SYSTEM, meaning that the threads contend for CPU +time with all processes running on the machine. The other value +specified by the standard, PTHREAD_SCOPE_PROCESS, means that +scheduling contention occurs only between the threads of the running +process.

    +

    Pthreads-w32 only supports PTHREAD_SCOPE_SYSTEM.

    +

    Default value: PTHREAD_SCOPE_SYSTEM. +

    +

    Return Value

    +

    All functions return 0 on success and a non-zero error code on +error. On success, the pthread_attr_getattrname +functions also store the current value of the attribute attrname +in the location pointed to by their second argument. +

    +

    Errors

    +

    The pthread_attr_setdetachstate function returns the +following error codes on error: +

    +
    +
    +
    EINVAL +
    + the specified detachstate is not one of + PTHREAD_CREATE_JOINABLE or PTHREAD_CREATE_DETACHED. +
    +
    +

    +The pthread_attr_setschedparam function returns the following +error codes on error: +

    +
    +
    +
    EINVAL +
    + the priority specified in param is outside the range of + allowed priorities for the scheduling policy currently in attr + (1 to 99 for SCHED_FIFO and SCHED_RR; 0 for + SCHED_OTHER). +
    +
    +

    +The pthread_attr_setschedpolicy function returns the following +error codes on error: +

    +
    +
    +
    EINVAL +
    + the specified policy is not one of SCHED_OTHER, + SCHED_FIFO, or SCHED_RR. +
    + ENOTSUP +
    + policy is not SCHED_OTHER, the only value supported + by Pthreads-w32.
    +
    +

    +The pthread_attr_setinheritsched function returns the +following error codes on error: +

    +
    +
    +
    EINVAL +
    + the specified inherit is not one of PTHREAD_INHERIT_SCHED + or PTHREAD_EXPLICIT_SCHED. +
    +
    +

    +The pthread_attr_setscope function returns the following error +codes on error: +

    +
    +
    +
    EINVAL +
    + the specified scope is not one of PTHREAD_SCOPE_SYSTEM + or PTHREAD_SCOPE_PROCESS. +
    + ENOTSUP +
    + the specified scope is PTHREAD_SCOPE_PROCESS (not + supported by Pthreads-w32). +
    +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_create(3) , +pthread_join(3) , +pthread_detach(3) , +pthread_setschedparam(3) +. +

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_attr_setstackaddr.html b/liblo/pthreads.2/manual/pthread_attr_setstackaddr.html new file mode 100644 index 0000000..38a4355 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_attr_setstackaddr.html @@ -0,0 +1,158 @@ + + + + + "PTHREAD_ATTR_GETSTACKADDR"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_attr_getstackaddr, pthread_attr_setstackaddr - get and set +the stackaddr attribute +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_attr_getstackaddr(const pthread_attr_t *restrict +attr, void **restrict stackaddr);
    int +pthread_attr_setstackaddr(pthread_attr_t *
    attr, void +*stackaddr); +

    +

    Description

    +

    The pthread_attr_getstackaddr and pthread_attr_setstackaddr +functions, respectively, shall get and set the thread creation +stackaddr attribute in the attr object. +

    +

    The stackaddr attribute specifies the location of storage +to be used for the created thread’s stack. The size of the storage +shall be at least {PTHREAD_STACK_MIN}. +

    +

    Pthreads-w32 defines _POSIX_THREAD_ATTR_STACKADDR in +pthread.h as -1 to indicate that these routines are implemented but +cannot used to set or get the stack address. These routines always +return the error ENOSYS when called.

    +

    Return Value

    +

    Upon successful completion, pthread_attr_getstackaddr and +pthread_attr_setstackaddr shall return a value of 0; +otherwise, an error number shall be returned to indicate the error. +

    +

    The pthread_attr_getstackaddr function stores the stackaddr +attribute value in stackaddr if successful. +

    +

    Errors

    +

    The pthread_attr_setstackaddr function always returns the +following error code: +

    +
    +
    +
    ENOSYS
    + The function is not supported. +
    +
    +

    +The pthread_attr_getstackaddr function always returns the +following error code: +

    +
    +
    +
    ENOSYS
    + The function is not supported. +
    +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    The specification of the stackaddr attribute presents +several ambiguities that make portable use of these interfaces +impossible. The description of the single address parameter as a +"stack" does not specify a particular relationship between +the address and the "stack" implied by that address. For +example, the address may be taken as the low memory address of a +buffer intended for use as a stack, or it may be taken as the address +to be used as the initial stack pointer register value for the new +thread. These two are not the same except for a machine on which the +stack grows "up" from low memory to high, and on which a +"push" operation first stores the value in memory and then +increments the stack pointer register. Further, on a machine where +the stack grows "down" from high memory to low, +interpretation of the address as the "low memory" address +requires a determination of the intended size of the stack. +IEEE Std 1003.1-2001 has introduced the new interfaces +pthread_attr_setstack(3) +and pthread_attr_getstack(3) +to resolve these ambiguities. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_attr_destroy(3) +, pthread_attr_getdetachstate(3) +, pthread_attr_getstack(3) +, pthread_attr_getstacksize(3) +, pthread_attr_setstack(3) +, pthread_create(3) , the +Base Definitions volume of IEEE Std 1003.1-2001, +<limits.h>, <pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_attr_setstacksize.html b/liblo/pthreads.2/manual/pthread_attr_setstacksize.html new file mode 100644 index 0000000..0d9672b --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_attr_setstacksize.html @@ -0,0 +1,127 @@ + + + + + "PTHREAD_ATTR_GETSTACKSIZE"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_attr_getstacksize, pthread_attr_setstacksize - get and set +the stacksize attribute +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_attr_getstacksize(const pthread_attr_t *restrict +attr, size_t *restrict stacksize);
    int +pthread_attr_setstacksize(pthread_attr_t *
    attr, size_t +stacksize); +

    +

    Description

    +

    The pthread_attr_getstacksize and pthread_attr_setstacksize +functions, respectively, shall get and set the thread creation +stacksize attribute in the attr object. +

    +

    The stacksize attribute shall define the minimum stack size +(in bytes) allocated for the created threads stack. +

    +

    Pthreads-w32 defines _POSIX_THREAD_ATTR_STACKSIZE in +pthread.h to indicate that these routines are implemented and may be +used to set or get the stack size.

    +

    Default value: 0 (in Pthreads-w32 a value of 0 means the stack +will grow as required)

    +

    Return Value

    +

    Upon successful completion, pthread_attr_getstacksize and +pthread_attr_setstacksize shall return a value of 0; +otherwise, an error number shall be returned to indicate the error. +

    +

    The pthread_attr_getstacksize function stores the stacksize +attribute value in stacksize if successful. +

    +

    Errors

    +

    The pthread_attr_setstacksize function shall fail if: +

    +
    +
    EINVAL +
    + The value of stacksize is less than {PTHREAD_STACK_MIN} or + exceeds a system-imposed limit. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_attr_destroy(3) +, pthread_attr_getstackaddr(3) +, pthread_attr_getdetachstate(3) +, pthread_create(3) , +the Base Definitions volume of IEEE Std 1003.1-2001, +<limits.h>, <pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_barrier_init.html b/liblo/pthreads.2/manual/pthread_barrier_init.html new file mode 100644 index 0000000..bc3324c --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_barrier_init.html @@ -0,0 +1,200 @@ + + + + + "PTHREAD_BARRIER_DESTROY"(P) manual page + + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_barrier_destroy, pthread_barrier_init - destroy and +initialize a barrier object (ADVANCED REALTIME THREADS) +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_barrier_destroy(pthread_barrier_t *barrier); +
    int pthread_barrier_init(pthread_barrier_t *restrict
    barrier, +const pthread_barrierattr_t *restrict attr, unsigned +count); +

    +

    Description

    +

    The pthread_barrier_destroy function shall destroy the +barrier referenced by barrier and release any resources used +by the barrier. The effect of subsequent use of the barrier is +undefined until the barrier is reinitialized by another call to +pthread_barrier_init . An implementation may use this function +to set barrier to an invalid value. The results are undefined +if pthread_barrier_destroy is called when any thread is +blocked on the barrier, or if this function is called with an +uninitialized barrier. +

    +

    The pthread_barrier_init function shall allocate any +resources required to use the barrier referenced by barrier +and shall initialize the barrier with attributes referenced by attr. +If attr is NULL, the default barrier attributes shall be used; +the effect is the same as passing the address of a default barrier +attributes object. The results are undefined if pthread_barrier_init +is called when any thread is blocked on the barrier (that is, has not +returned from the pthread_barrier_wait(3) +call). The results are undefined if a barrier is used without first +being initialized. The results are undefined if pthread_barrier_init +is called specifying an already initialized barrier. +

    +

    The count argument specifies the number of threads that +must call pthread_barrier_wait(3) +before any of them successfully return from the call. The value +specified by count must be greater than zero. +

    +

    If the pthread_barrier_init function fails, the barrier +shall not be initialized and the contents of barrier are +undefined. +

    +

    Only the object referenced by barrier may be used for +performing synchronization. The result of referring to copies of that +object in calls to pthread_barrier_destroy or +pthread_barrier_wait(3) +is undefined.

    +

    Return Value

    +

    Upon successful completion, these functions shall return zero; +otherwise, an error number shall be returned to indicate the error. +

    +

    Errors

    +

    The pthread_barrier_destroy function may fail if: +

    +
    +
    EBUSY +
    + The implementation has detected an attempt to destroy a barrier + while it is in use (for example, while being used in a + pthread_barrier_wait(3) + call) by another thread. +
    + EINVAL +
    + The value specified by barrier is invalid. +
    +

    +The pthread_barrier_init function shall fail if: +

    +
    +
    EAGAIN +
    + The system lacks the necessary resources to initialize another + barrier. +
    + EINVAL +
    + The value specified by count is equal to zero. +
    + ENOMEM +
    + Insufficient memory exists to initialize the barrier. +
    +

    +The pthread_barrier_init function may fail if: +

    +
    +
    EBUSY +
    + The implementation has detected an attempt to reinitialize a barrier + while it is in use (for example, while being used in a + pthread_barrier_wait(3) + call) by another thread. +
    + EINVAL +
    + The value specified by attr is invalid. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    The pthread_barrier_destroy and pthread_barrier_init +functions are part of the Barriers option and need not be provided on +all implementations. +

    +

    Pthreads-w32 defines _POSIX_BARRIERS to indicate +that these routines are implemented and may be used.

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    Known Bugs

    +
    +
    In + pthreads-win32, + pthread_barrier_wait(3) + may deadlock if the number of running threads able to wait on the + barrier object exceeds the value given as the count + parameter in pthread_barrier_init. +
    +

    +See Also

    +

    pthread_barrier_wait(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/pthread_barrier_wait.html b/liblo/pthreads.2/manual/pthread_barrier_wait.html new file mode 100644 index 0000000..4db0594 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_barrier_wait.html @@ -0,0 +1,167 @@ + + + + + "PTHREAD_BARRIER_WAIT"(P) manual page + + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_barrier_wait - synchronize at a barrier (ADVANCED +REALTIME THREADS) +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_barrier_wait(pthread_barrier_t *barrier); + +

    +

    Description

    +

    The pthread_barrier_wait function shall synchronize +participating threads at the barrier referenced by barrier. +The calling thread shall block until the required number of threads +have called pthread_barrier_wait specifying the barrier. +

    +

    When the required number of threads have called +pthread_barrier_wait specifying the barrier, the constant +PTHREAD_BARRIER_SERIAL_THREAD shall be returned to one +unspecified thread and zero shall be returned to each of the +remaining threads. At this point, the barrier shall be reset to the +state it had as a result of the most recent pthread_barrier_init(3) +function that referenced it. +

    +

    The constant PTHREAD_BARRIER_SERIAL_THREAD is defined in +<pthread.h> and its value shall be distinct from any +other value returned by pthread_barrier_wait . +

    +

    The results are undefined if this function is called with an +uninitialized barrier. +

    +

    If a signal is delivered to a thread blocked on a barrier, upon +return from the signal handler the thread shall resume waiting at the +barrier if the barrier wait has not completed (that is, if the +required number of threads have not arrived at the barrier during the +execution of the signal handler); otherwise, the thread shall +continue as normal from the completed barrier wait. Until the thread +in the signal handler returns from it, it is unspecified whether +other threads may proceed past the barrier once they have all reached +it. +

    +

    A thread that has blocked on a barrier shall not prevent any +unblocked thread that is eligible to use the same processing +resources from eventually making forward progress in its execution. +Eligibility for processing resources shall be determined by the +scheduling policy. +

    +

    Return Value

    +

    Upon successful completion, the pthread_barrier_wait +function shall return PTHREAD_BARRIER_SERIAL_THREAD for a +single (arbitrary) thread synchronized at the barrier and zero for +each of the other threads. Otherwise, an error number shall be +returned to indicate the error. +

    +

    Errors

    +

    The pthread_barrier_wait function may fail if: +

    +
    +
    EINVAL +
    + The value specified by barrier does not refer to an + initialized barrier object. +
    +

    +This function shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Applications using this function may be subject to priority +inversion, as discussed in the Base Definitions volume of +IEEE Std 1003.1-2001, Section 3.285, Priority Inversion. +

    +

    The pthread_barrier_wait function is part of the Barriers +option and need not be provided on all implementations. +

    +

    Pthreads-w32 defines _POSIX_BARRIERS to indicate +that this routine is implemented and may be used.

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    Known Bugs

    +
    +
    In + pthreads-win32, + pthread_barrier_wait may deadlock if the number of running + threads able to wait on the barrier object exceeds the value given + as the count parameter in + pthread_barrier_init(3). +
    +

    +See Also

    +

    pthread_barrier_destroy(3), +pthread_barrier_init(3), +the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/pthread_barrierattr_init.html b/liblo/pthreads.2/manual/pthread_barrierattr_init.html new file mode 100644 index 0000000..87f846f --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_barrierattr_init.html @@ -0,0 +1,142 @@ + + + + + "PTHREAD_BARRIERATTR_DESTROY"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_barrierattr_destroy, pthread_barrierattr_init - destroy +and initialize the barrier attributes object (ADVANCED REALTIME +THREADS) +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_barrierattr_destroy(pthread_barrierattr_t *attr); +
    int pthread_barrierattr_init(pthread_barrierattr_t *
    attr); + +

    +

    Description

    +

    The pthread_barrierattr_destroy function shall destroy a +barrier attributes object. A destroyed attr attributes object +can be reinitialized using pthread_barrierattr_init ; the +results of otherwise referencing the object after it has been +destroyed are undefined. An implementation may cause +pthread_barrierattr_destroy to set the object referenced by +attr to an invalid value. +

    +

    The pthread_barrierattr_init function shall initialize a +barrier attributes object attr with the default value for all +of the attributes defined by the implementation. +

    +

    Results are undefined if pthread_barrierattr_init is called +specifying an already initialized attr attributes object. +

    +

    After a barrier attributes object has been used to initialize one +or more barriers, any function affecting the attributes object +(including destruction) shall not affect any previously initialized +barrier. +

    +

    Return Value

    +

    If successful, the pthread_barrierattr_destroy and +pthread_barrierattr_init functions shall return zero; +otherwise, an error number shall be returned to indicate the error. +

    +

    Errors

    +

    The pthread_barrierattr_destroy function may fail if: +

    +
    +
    EINVAL +
    + The value specified by attr is invalid. +
    +

    +The pthread_barrierattr_init function shall fail if: +

    +
    +
    ENOMEM +
    + Insufficient memory exists to initialize the barrier attributes + object. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    The pthread_barrierattr_destroy and +pthread_barrierattr_init functions are part of the Barriers +option and need not be provided on all implementations. +

    +

    Pthreads-w32 defines _POSIX_BARRIERS to indicate +that these routines are implemented and may be used.

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_barrierattr_getpshared(3) +, pthread_barrierattr_setpshared(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h>. +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_barrierattr_setpshared.html b/liblo/pthreads.2/manual/pthread_barrierattr_setpshared.html new file mode 100644 index 0000000..dc96543 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_barrierattr_setpshared.html @@ -0,0 +1,159 @@ + + + + + "PTHREAD_BARRIERATTR_GETPSHARED"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_barrierattr_getpshared, pthread_barrierattr_setpshared - +get and set the process-shared attribute of the barrier attributes +object (ADVANCED REALTIME THREADS) +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_barrierattr_getpshared(const pthread_barrierattr_t +* restrict attr, int *restrict pshared); +
    int pthread_barrierattr_setpshared(pthread_barrierattr_t *
    attr, +int pshared); +

    +

    Description

    +

    The pthread_barrierattr_getpshared function shall obtain +the value of the process-shared attribute from the attributes +object referenced by attr. The pthread_barrierattr_setpshared +function shall set the process-shared attribute in an +initialized attributes object referenced by attr. +

    +

    The process-shared attribute is set to +PTHREAD_PROCESS_SHARED to permit a barrier to be operated upon by any +thread that has access to the memory where the barrier is allocated. +If the process-shared attribute is PTHREAD_PROCESS_PRIVATE, +the barrier shall only be operated upon by threads created within the +same process as the thread that initialized the barrier; if threads +of different processes attempt to operate on such a barrier, the +behavior is undefined. The default value of the attribute shall be +PTHREAD_PROCESS_PRIVATE. Both constants PTHREAD_PROCESS_SHARED and +PTHREAD_PROCESS_PRIVATE are defined in <pthread.h>. +

    +

    Pthreads-w32 defines _POSIX_THREAD_PROCESS_SHARED in +pthread.h as -1 to indicate that these routines are implemented but +that the process shared attribute is not supported.

    +

    Additional attributes, their default values, and the names of the +associated functions to get and set those attribute values are +implementation-defined. +

    +

    Return Value

    +

    If successful, the pthread_barrierattr_getpshared function +shall return zero and store the value of the process-shared +attribute of attr into the object referenced by the pshared +parameter. Otherwise, an error number shall be returned to indicate +the error. +

    +

    If successful, the pthread_barrierattr_setpshared function +shall return zero; otherwise, an error number shall be returned to +indicate the error. +

    +

    Errors

    +

    These functions may fail if: +

    +
    +
    EINVAL +
    + The value specified by attr is invalid. +
    + The pthread_barrierattr_setpshared function may fail if: +
    + EINVAL +
    + The new value specified for the process-shared attribute is + not one of the legal values PTHREAD_PROCESS_SHARED or + PTHREAD_PROCESS_PRIVATE. +
    + ENOSYS +
    + The value specified by attr was PTHREAD_PROCESS_SHARED + (Pthreads-w32).
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    The pthread_barrierattr_getpshared and +pthread_barrierattr_setpshared functions are part of the +Barriers option and need not be provided on all implementations. +

    +

    Pthreads-w32 defines _POSIX_BARRIERS and +_POSIX_THREAD_PROCESS_SHARED in pthread.h as -1 to indicate +that these routines are implemented and may be used, but do not +support the process shared option.

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_barrier_destroy(3) +, pthread_barrierattr_destroy(3) +, pthread_barrierattr_init(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_cancel.html b/liblo/pthreads.2/manual/pthread_cancel.html new file mode 100644 index 0000000..99b5553 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_cancel.html @@ -0,0 +1,205 @@ + + + + + PTHREAD_CANCEL(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_cancel, pthread_setcancelstate, pthread_setcanceltype, +pthread_testcancel - thread cancellation +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_cancel(pthread_t thread); +

    +

    int pthread_setcancelstate(int state, int +*oldstate); +

    +

    int pthread_setcanceltype(int type, int +*oldtype); +

    +

    void pthread_testcancel(void); +

    +

    Description

    +

    Cancellation is the mechanism by which a thread can terminate the +execution of another thread. More precisely, a thread can send a +cancellation request to another thread. Depending on its settings, +the target thread can then either ignore the request, honor it +immediately, or defer it until it reaches a cancellation point. +

    +

    When a thread eventually honors a cancellation request, it +performs as if pthread_exit(PTHREAD_CANCELED) has been called +at that point: all cleanup handlers are executed in reverse order, +destructor functions for thread-specific data are called, and finally +the thread stops executing with the return value PTHREAD_CANCELED. +See pthread_exit(3) for more +information. +

    +

    pthread_cancel sends a cancellation request to the thread +denoted by the thread argument. +

    +

    pthread_setcancelstate changes the cancellation state for +the calling thread -- that is, whether cancellation requests are +ignored or not. The state argument is the new cancellation +state: either PTHREAD_CANCEL_ENABLE to enable cancellation, or +PTHREAD_CANCEL_DISABLE to disable cancellation (cancellation +requests are ignored). If oldstate is not NULL, the +previous cancellation state is stored in the location pointed to by +oldstate, and can thus be restored later by another call to +pthread_setcancelstate. +

    +

    pthread_setcanceltype changes the type of responses to +cancellation requests for the calling thread: asynchronous +(immediate) or deferred. The type argument is the new +cancellation type: either PTHREAD_CANCEL_ASYNCHRONOUS to +cancel the calling thread as soon as the cancellation request is +received, or PTHREAD_CANCEL_DEFERRED to keep the cancellation +request pending until the next cancellation point. If oldtype +is not NULL, the previous cancellation state is stored in the +location pointed to by oldtype, and can thus be restored later +by another call to pthread_setcanceltype. +

    +

    Pthreads-w32 provides two levels of support for +PTHREAD_CANCEL_ASYNCHRONOUS: full and partial. Full support +requires an additional DLL and driver be installed on the Windows +system (see the See Also section below) that allows blocked threads +to be cancelled immediately. Partial support means that the target +thread will not cancel until it resumes execution naturally. Partial +support is provided if either the DLL or the driver are not +automatically detected by the pthreads-w32 library at run-time.

    +

    Threads are always created by pthread_create(3) +with cancellation enabled and deferred. That is, the initial +cancellation state is PTHREAD_CANCEL_ENABLE and the initial +type is PTHREAD_CANCEL_DEFERRED. +

    +

    Cancellation points are those points in the program execution +where a test for pending cancellation requests is performed and +cancellation is executed if positive. The following POSIX threads +functions are cancellation points: +

    +

    pthread_join(3) +
    pthread_cond_wait(3) +
    pthread_cond_timedwait(3) +
    pthread_testcancel(3)
    sem_wait(3) +
    sem_timedwait(3)
    sigwait(3)

    +

    Pthreads-w32 provides two functions to enable additional +cancellation points to be created in user functions that block on +Win32 HANDLEs:

    +

    pthreadCancelableWait() +
    pthreadCancelableTimedWait()

    +

    All other POSIX threads functions are guaranteed not to be +cancellation points. That is, they never perform cancellation in +deferred cancellation mode. +

    +

    pthread_testcancel does nothing except testing for pending +cancellation and executing it. Its purpose is to introduce explicit +checks for cancellation in long sequences of code that do not call +cancellation point functions otherwise. +

    +

    Return Value

    +

    pthread_cancel, pthread_setcancelstate and +pthread_setcanceltype return 0 on success and a non-zero error +code on error. +

    +

    Errors

    +

    pthread_cancel returns the following error code on error: +

    +
    +
    +
    ESRCH +
    + no thread could be found corresponding to that specified by the + thread ID. +
    +
    +

    +pthread_setcancelstate returns the following error code on +error: +

    +
    +
    +
    EINVAL +
    + the state argument is not +
    +
    +
    +PTHREAD_CANCEL_ENABLE nor PTHREAD_CANCEL_DISABLE +
    +

    pthread_setcanceltype returns the following error code on +error: +

    +
    +
    +
    EINVAL +
    + the type argument is not +
    +
    +
    +PTHREAD_CANCEL_DEFERRED nor PTHREAD_CANCEL_ASYNCHRONOUS +
    +

    Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_exit(3) , +pthread_cleanup_push(3) +, pthread_cleanup_pop(3) +, Pthreads-w32 package README file 'Prerequisites' section. +

    +

    Bugs

    +

    POSIX specifies that a number of system calls (basically, all +system calls that may block, such as read(2) +, write(2) , wait(2) +, etc.) and library functions that may call these system calls (e.g. +fprintf(3) ) are cancellation +points. Pthreads-win32 is not integrated enough with the C +library to implement this, and thus none of the C library functions +is a cancellation point. +

    +

    A workaround for these calls is to temporarily switch to +asynchronous cancellation (assuming full asynchronous cancellation +support is installed). So, checking for cancellation during a read +system call, for instance, can be achieved as follows: +

    +


    +
    +
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldCancelType);
    +read(fd, buffer, length);
    +pthread_setcanceltype(oldCancelType, NULL);
    +
    +
    Table of Contents
    + + + diff --git a/liblo/pthreads.2/manual/pthread_cleanup_push.html b/liblo/pthreads.2/manual/pthread_cleanup_push.html new file mode 100644 index 0000000..052ea6e --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_cleanup_push.html @@ -0,0 +1,140 @@ + + + + + PTHREAD_CLEANUP(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_cleanup_push, pthread_cleanup_pop - install and remove +cleanup handlers +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    void pthread_cleanup_push(void (*routine) (void +*), void *arg); +

    +

    void pthread_cleanup_pop(int execute); +

    +

    Description

    +

    Cleanup handlers are functions that get called when a thread +terminates, either by calling pthread_exit(3) +or because of cancellation. Cleanup handlers are installed and +removed following a stack-like discipline. +

    +

    The purpose of cleanup handlers is to free the resources that a +thread may hold at the time it terminates. In particular, if a thread +exits or is cancelled while it owns a locked mutex, the mutex will +remain locked forever and prevent other threads from executing +normally. The best way to avoid this is, just before locking the +mutex, to install a cleanup handler whose effect is to unlock the +mutex. Cleanup handlers can be used similarly to free blocks +allocated with malloc(3) or close +file descriptors on thread termination. +

    +

    pthread_cleanup_push installs the routine function +with argument arg as a cleanup handler. From this point on to +the matching pthread_cleanup_pop, the function routine +will be called with arguments arg when the thread terminates, +either through pthread_exit(3) +or by cancellation. If several cleanup handlers are active at that +point, they are called in LIFO order: the most recently installed +handler is called first. +

    +

    pthread_cleanup_pop removes the most recently installed +cleanup handler. If the execute argument is not 0, it also +executes the handler, by calling the routine function with +arguments arg. If the execute argument is 0, the +handler is only removed but not executed. +

    +

    Matching pairs of pthread_cleanup_push and +pthread_cleanup_pop must occur in the same function, at the +same level of block nesting. Actually, pthread_cleanup_push +and pthread_cleanup_pop are macros, and the expansion of +pthread_cleanup_push introduces an open brace { with +the matching closing brace } being introduced by the expansion +of the matching pthread_cleanup_pop. +

    +

    Return Value

    +
    None. +
    +

    Errors

    +
    None. +
    +

    Author

    +
    Xavier Leroy +<Xavier.Leroy@inria.fr> +
    +
    Modified by +Ross Johnson for use with Pthreads-w32.
    +

    See Also

    +
    pthread_exit(3) +, pthread_cancel(3) , +pthread_setcanceltype(3) . +
    +

    Example

    +
    Here is how +to lock a mutex mut in such a way that it will be unlocked if +the thread is canceled while mut is locked: +
    +
    pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
    +pthread_mutex_lock(&mut);
    +/* do some work */
    +pthread_mutex_unlock(&mut);
    +pthread_cleanup_pop(0);
    +Equivalently, the last two lines can be replaced by +
    +
    pthread_cleanup_pop(1);
    +Notice that the code above is safe only in deferred cancellation mode +(see pthread_setcanceltype(3) +). In asynchronous cancellation mode, a cancellation can occur +between pthread_cleanup_push and pthread_mutex_lock, or +between pthread_mutex_unlock and pthread_cleanup_pop, +resulting in both cases in the thread trying to unlock a mutex not +locked by the current thread. This is the main reason why +asynchronous cancellation is difficult to use. +
    +
    If the code +above must also work in asynchronous cancellation mode, then it must +switch to deferred mode for locking and unlocking the mutex: +
    +
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
    +pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
    +pthread_mutex_lock(&mut);
    +/* do some work */
    +pthread_cleanup_pop(1);
    +pthread_setcanceltype(oldtype, NULL);
    +
    +
    +Table of Contents
    + + + diff --git a/liblo/pthreads.2/manual/pthread_cond_init.html b/liblo/pthreads.2/manual/pthread_cond_init.html new file mode 100644 index 0000000..ecbf6ae --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_cond_init.html @@ -0,0 +1,313 @@ + + + + + PTHREAD_COND(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_cond_init, pthread_cond_destroy, pthread_cond_signal, +pthread_cond_broadcast, pthread_cond_wait, pthread_cond_timedwait - +operations on conditions +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +

    +

    int pthread_cond_init(pthread_cond_t *cond, +pthread_condattr_t *cond_attr); +

    +

    int pthread_cond_signal(pthread_cond_t *cond); +

    +

    int pthread_cond_broadcast(pthread_cond_t *cond); +

    +

    int pthread_cond_wait(pthread_cond_t *cond, +pthread_mutex_t *mutex); +

    +

    int pthread_cond_timedwait(pthread_cond_t *cond, +pthread_mutex_t *mutex, const struct timespec +*abstime); +

    +

    int pthread_cond_destroy(pthread_cond_t *cond); +

    +

    Description

    +

    A condition (short for ‘‘condition variable’’) is a +synchronization device that allows threads to suspend execution and +relinquish the processors until some predicate on shared data is +satisfied. The basic operations on conditions are: signal the +condition (when the predicate becomes true), and wait for the +condition, suspending the thread execution until another thread +signals the condition. +

    +

    A condition variable must always be associated with a mutex, to +avoid the race condition where a thread prepares to wait on a +condition variable and another thread signals the condition just +before the first thread actually waits on it. +

    +

    pthread_cond_init initializes the condition variable cond, +using the condition attributes specified in cond_attr, or +default attributes if cond_attr is NULL. +

    +

    Variables of type pthread_cond_t can also be initialized +statically, using the constant PTHREAD_COND_INITIALIZER. In +the Pthreads-w32 implementation, an application should still +call pthread_cond_destroy at some point to ensure that any +resources consumed by the condition variable are released.

    +

    pthread_cond_signal restarts one of the threads that are +waiting on the condition variable cond. If no threads are +waiting on cond, nothing happens. If several threads are +waiting on cond, exactly one is restarted, but it is not +specified which. +

    +

    pthread_cond_broadcast restarts all the threads that are +waiting on the condition variable cond. Nothing happens if no +threads are waiting on cond. +

    +

    pthread_cond_wait atomically unlocks the mutex (as +per pthread_unlock_mutex) and waits for the condition variable +cond to be signalled. The thread execution is suspended and +does not consume any CPU time until the condition variable is +signalled. The mutex must be locked by the calling thread on +entrance to pthread_cond_wait. Before returning to the calling +thread, pthread_cond_wait re-acquires mutex (as per +pthread_lock_mutex). +

    +

    Unlocking the mutex and suspending on the condition variable is +done atomically. Thus, if all threads always acquire the mutex before +signalling the condition, this guarantees that the condition cannot +be signalled (and thus ignored) between the time a thread locks the +mutex and the time it waits on the condition variable. +

    +

    pthread_cond_timedwait atomically unlocks mutex and +waits on cond, as pthread_cond_wait does, but it also +bounds the duration of the wait. If cond has not been +signalled within the amount of time specified by abstime, the +mutex mutex is re-acquired and pthread_cond_timedwait +returns the error ETIMEDOUT. The abstime parameter +specifies an absolute time, with the same origin as time(2) +and gettimeofday(2). +

    +

    pthread_cond_destroy destroys a condition variable, freeing +the resources it might hold. No threads must be waiting on the +condition variable on entrance to pthread_cond_destroy.

    +

    Cancellation

    +

    pthread_cond_wait and pthread_cond_timedwait are +cancellation points. If a thread is cancelled while suspended in one +of these functions, the thread immediately resumes execution, then +locks again the mutex argument to pthread_cond_wait and +pthread_cond_timedwait, and finally executes the cancellation. +Consequently, cleanup handlers are assured that mutex is +locked when they are called. +

    +

    Async-signal Safety

    +

    The condition functions are not async-signal safe, and should not +be called from a signal handler. In particular, calling +pthread_cond_signal or pthread_cond_broadcast from a +signal handler may deadlock the calling thread. +

    +

    Return Value

    +

    All condition variable functions return 0 on success and a +non-zero error code on error. +

    +

    Errors

    +

    pthread_cond_init, pthread_cond_signal, +pthread_cond_broadcast, and pthread_cond_wait never +return an error code. +

    +

    The pthread_cond_init function returns the following error +codes on error: +

    +
    +
    +
    EINVAL +
    + The cond argument is invalid. +
    + ENOMEM +
    +
    +
    +There was not enough memory to allocate the condition variable. +
    +

    The pthread_cond_signal function returns the following +error codes on error: +

    +
    +
    +
    EINVAL +
    + The cond argument is invalid. +
    +
    +

    +The pthread_cond_broadcast function returns the following +error codes on error: +

    +
    +
    +
    EINVAL +
    + The cond argument is invalid. +
    +
    +

    +The pthread_cond_wait function returns the following error +codes on error: +

    +
    +
    +
    EINVAL +
    + The cond argument is invalid. +
    + ENOMEM +
    +
    +
    +There was not enough memory to allocate the statically initialised +condition variable. Statically initialised condition variables are +dynamically allocated by the first thread to wait on them.
    +

    The pthread_cond_timedwait function returns the following +error codes on error: +

    +
    +
    +
    EINVAL +
    +
    +

    +The cond argument is invalid. +

    +
    +
    +
    ETIMEDOUT +
    + The condition variable was not signalled before the timeout + specified by abstime +
    + ENOMEM +
    +
    +
    +There was not enough memory to allocate the statically initialised +condition variable. Statically initialised condition variables are +dynamically allocated by the first thread to wait on them. +
    +

    The pthread_cond_destroy function returns the following +error code on error: +

    +
    +
    +
    EINVAL +
    +
    +

    +The cond argument is invalid. +

    +
    +
    +
    EBUSY +
    + Some threads are currently waiting on cond. +
    +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_condattr_init(3) +, pthread_mutex_lock(3) +, pthread_mutex_unlock(3) +, pthread_cancel(3). +

    +

    Example

    +

    Consider two shared variables x and y, protected by +the mutex mut, and a condition variable cond that is to +be signaled whenever x becomes greater than y. +

    +
    int x,y;
    +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
    +pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    +Waiting until x is greater than y is performed as +follows: +
    +
    pthread_mutex_lock(&mut);
    +while (x <= y) {
    +        pthread_cond_wait(&cond, &mut);
    +}
    +/* operate on x and y */
    +pthread_mutex_unlock(&mut);
    +Modifications on x and y that may cause x to +become greater than y should signal the condition if needed: +
    +
    pthread_mutex_lock(&mut);
    +/* modify x and y */
    +if (x > y) pthread_cond_broadcast(&cond);
    +pthread_mutex_unlock(&mut);
    +If it can be proved that at most one waiting thread needs to be waken +up (for instance, if there are only two threads communicating through +x and y), pthread_cond_signal can be used as a +slightly more efficient alternative to pthread_cond_broadcast. +If in doubt, use pthread_cond_broadcast. +
    +
    To wait for x to +become greater than y with a timeout of 5 seconds, do: +
    +
    struct timeval now;
    +struct timespec timeout;
    +int retcode;
    +pthread_mutex_lock(&mut);
    +gettimeofday(&now);
    +timeout.tv_sec = now.tv_sec + 5;
    +timeout.tv_nsec = now.tv_usec * 1000;
    +retcode = 0;
    +while (x <= y && retcode != ETIMEDOUT) {
    +        retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
    +}
    +if (retcode == ETIMEDOUT) {
    +        /* timeout occurred */
    +} else {
    +        /* operate on x and y */
    +}
    +pthread_mutex_unlock(&mut);
    +
    +
    +Table of Contents
    + + + diff --git a/liblo/pthreads.2/manual/pthread_condattr_init.html b/liblo/pthreads.2/manual/pthread_condattr_init.html new file mode 100644 index 0000000..b799e18 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_condattr_init.html @@ -0,0 +1,98 @@ + + + + + PTHREAD_CONDATTR(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_condattr_init, pthread_condattr_destroy - condition +creation +

    +

    attributes +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_condattr_init(pthread_condattr_t *attr); +

    +

    int pthread_condattr_destroy(pthread_condattr_t *attr); +

    +

    Description

    +

    Condition attributes can be specified at condition creation time, +by passing a condition attribute object as second argument to +pthread_cond_init(3) . +Passing NULL is equivalent to passing a condition attribute +object with all attributes set to their default values. +

    +

    pthread_condattr_init initializes the condition attribute +object attr and fills it with default values for the +attributes. pthread_condattr_destroy destroys a condition +attribute object, which must not be reused until it is reinitialized.

    +

    Pthreads-w32 defines _POSIX_THREAD_PROCESS_SHARED in +pthread.h as -1 to indicate that the attribute routines are +implemented but that the process shared attribute is not supported.

    +

    Return Value

    +

    All condition variable functions return 0 on success and a +non-zero error code on error.

    +

    Errors

    +

    The pthread_condattr_init function returns the following +error code on error: +

    +
    +
    +
    ENOMEM +
    + The was insufficient memory to create the attribute. + +
    +
    +

    +The pthread_condattr_destroy function returns the following +error code on error: +

    +
    +
    +
    EINVAL +
    + The attr argument is not valid. + +
    +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_cond_init(3) . +

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_condattr_setpshared.html b/liblo/pthreads.2/manual/pthread_condattr_setpshared.html new file mode 100644 index 0000000..ff4fe22 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_condattr_setpshared.html @@ -0,0 +1,153 @@ + + + + + "PTHREAD_CONDATTR_GETPSHARED"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_condattr_getpshared, pthread_condattr_setpshared - get and +set the process-shared condition variable attributes +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_condattr_getpshared(const pthread_condattr_t +*restrict attr, int *restrict pshared); +
    int pthread_condattr_setpshared(pthread_condattr_t *
    attr, +int pshared); +

    +

    Description

    +

    The pthread_condattr_getpshared function shall obtain the +value of the process-shared attribute from the attributes +object referenced by attr. The pthread_condattr_setpshared +function shall set the process-shared attribute in an +initialized attributes object referenced by attr. +

    +

    The process-shared attribute is set to +PTHREAD_PROCESS_SHARED to permit a condition variable to be +operated upon by any thread that has access to the memory where the +condition variable is allocated, even if the condition variable is +allocated in memory that is shared by multiple processes. If the +process-shared attribute is PTHREAD_PROCESS_PRIVATE, +the condition variable shall only be operated upon by threads created +within the same process as the thread that initialized the condition +variable; if threads of differing processes attempt to operate on +such a condition variable, the behavior is undefined. The default +value of the attribute is PTHREAD_PROCESS_PRIVATE. +

    +

    Pthreads-w32 defines _POSIX_THREAD_PROCESS_SHARED in +pthread.h as -1 to indicate that these routines are implemented but +that the process shared attribute is not supported.

    +

    Return Value

    +

    If successful, the pthread_condattr_setpshared function +shall return zero; otherwise, an error number shall be returned to +indicate the error. +

    +

    If successful, the pthread_condattr_getpshared function +shall return zero and store the value of the process-shared +attribute of attr into the object referenced by the pshared +parameter. Otherwise, an error number shall be returned to indicate +the error. +

    +

    Errors

    +

    The pthread_condattr_getpshared and +pthread_condattr_setpshared functions may fail if: +

    +
    +
    EINVAL +
    + The value specified by attr is invalid. +
    +

    +The pthread_condattr_setpshared function may fail if: +

    +
    +
    EINVAL +
    + The new value specified for the attribute is outside the range of + legal values for that attribute. +
    + ENOSYS +
    + The value specified by attr was PTHREAD_PROCESS_SHARED + (Pthreads-w32).
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Pthreads-w32 defines _POSIX_THREAD_PROCESS_SHARED in +pthread.h as -1 to indicate that these routines are implemented and +may be used, but do not support the process shared option.

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_create(3) , +pthread_cond_destroy(3) , +pthread_condattr_destroy(3) +, pthread_mutex_destroy(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_create.html b/liblo/pthreads.2/manual/pthread_create.html new file mode 100644 index 0000000..c5d80ba --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_create.html @@ -0,0 +1,94 @@ + + + + + PTHREAD_CREATE(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_create - create a new thread +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_create(pthread_t * thread, +pthread_attr_t * attr, void * (*start_routine)(void +*), void * arg); +

    +

    Description

    +

    pthread_create creates a new thread of control that +executes concurrently with the calling thread. The new thread applies +the function start_routine passing it arg as first +argument. The new thread terminates either explicitly, by calling +pthread_exit(3) , or +implicitly, by returning from the start_routine function. The +latter case is equivalent to calling pthread_exit(3) +with the result returned by start_routine as exit code. +

    +

    The initial signal state of the new thread is inherited from it's +creating thread and there are no pending signals. Pthreads-w32 +does not yet implement signals.

    +

    The attr argument specifies thread attributes to be applied +to the new thread. See pthread_attr_init(3) +for a complete list of thread attributes. The attr argument +can also be NULL, in which case default attributes are used: +the created thread is joinable (not detached) and has default (non +real-time) scheduling policy. +

    +

    Return Value

    +

    On success, the identifier of the newly created thread is stored +in the location pointed by the thread argument, and a 0 is +returned. On error, a non-zero error code is returned. +

    +

    Errors

    +
    +
    EAGAIN +
    +
    +
    + Not enough system resources to create a process for the new + thread, or
    more than PTHREAD_THREADS_MAX threads are + already active. +
    +
    +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_exit(3) , +pthread_join(3) , +pthread_detach(3) , +pthread_attr_init(3) . +

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_delay_np.html b/liblo/pthreads.2/manual/pthread_delay_np.html new file mode 100644 index 0000000..99d5f39 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_delay_np.html @@ -0,0 +1,71 @@ + + + + + PTHREAD_DELAY_NP manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_delay_np – suspend the +thread for a specified period

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_delay_np (const struct timespec *interval);

    +

    Description

    +

    pthread_delay_np causes a thread to delay execution for a +specific period of time. This period ends at the current time plus +the specified interval. The routine will not return before the end of +the period is reached, but may return an arbitrary amount of time +after the period has gone by. This can be due to system load, thread +priorities, and system timer granularity.

    +

    Specifying an interval of zero (0) seconds and zero (0) +nanoseconds is allowed and can be used to force the thread to give up +the processor or to deliver a pending cancellation request.

    +

    Cancellation

    +

    pthread_delay_np is a cancellation point.

    +

    Return Value

    +

    If an error condition occurs, pthread_delay_np returns an +integer value indicating the type of error.

    +

    Errors

    +

    The pthread_delay_np function returns the following error +code on error: +

    +
    +
    +
    EINVAL +
    +
    +

    +The value specified by interval is invalid.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_detach.html b/liblo/pthreads.2/manual/pthread_detach.html new file mode 100644 index 0000000..4a588b4 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_detach.html @@ -0,0 +1,90 @@ + + + + + PTHREAD_DETACH(3) manual page + + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_detach - put a running thread in the detached state +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_detach(pthread_t th); +

    +

    Description

    +

    pthread_detach puts the thread th in the detached +state. This guarantees that the resources consumed by th will +be freed immediately when th terminates. However, this +prevents other threads from synchronizing on the termination of th +using pthread_join. If, when pthread_detach is called, +th has already terminated, all of th's remaining +resources will be freed.

    +

    A thread can be created initially in the detached state, using the +detachstate attribute to pthread_create(3) +. In contrast, pthread_detach applies to threads created in +the joinable state, and which need to be put in the detached state +later. +

    +

    After pthread_detach completes, subsequent attempts to +perform pthread_join on th will fail. If another thread +is already joining the thread th at the time pthread_detach +is called, th will be detached and pthread_join will +eventually return when th terminates but may not return with +th's correct return code. +

    +

    Return Value

    +

    On success, 0 is returned. On error, a non-zero error code is +returned. +

    +

    Errors

    +
    +
    ESRCH +
    + No thread could be found corresponding to that specified by th +
    + EINVAL +
    + the thread th is already in the detached state +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_create(3) , +pthread_join(3) , +pthread_attr_setdetachstate(3) +

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/pthread_equal.html b/liblo/pthreads.2/manual/pthread_equal.html new file mode 100644 index 0000000..0817909 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_equal.html @@ -0,0 +1,48 @@ + + + + + +PTHREAD_EQUAL(3) manual page + + +Table of Contents

    + +

    +

    Name

    +pthread_equal - compare two thread identifiers +

    +

    Synopsis

    +#include <pthread.h> + +

    int pthread_equal(pthread_t thread1, pthread_t thread2); +

    +

    Description

    +pthread_equal +determines if two thread identifiers refer to the same thread. +

    +

    Return Value

    +A +non-zero value is returned if thread1 and thread2 refer to the same thread. +Otherwise, 0 is returned. +

    +

    Author

    +Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    See Also

    +pthread_self(3) +. +

    + +


    +Table of Contents

    +

    + + diff --git a/liblo/pthreads.2/manual/pthread_exit.html b/liblo/pthreads.2/manual/pthread_exit.html new file mode 100644 index 0000000..f5aac31 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_exit.html @@ -0,0 +1,59 @@ + + + + + +PTHREAD_EXIT(3) manual page + + +Table of Contents

    + +

    +

    Name

    +pthread_exit - terminate the calling thread +

    +

    Synopsis

    +#include <pthread.h> + +

    void pthread_exit(void *retval); +

    +

    Description

    +pthread_exit terminates the +execution of the calling thread. All cleanup handlers that have been set +for the calling thread with pthread_cleanup_push(3) + are executed in reverse +order (the most recently pushed handler is executed first). Finalization +functions for thread-specific data are then called for all keys that have +non- NULL values associated with them in the calling thread (see pthread_key_create(3) +). +Finally, execution of the calling thread is stopped. +

    The retval argument +is the return value of the thread. It can be consulted from another thread +using pthread_join(3) +. +

    +

    Return Value

    +The pthread_exit function never returns. + +

    +

    Author

    +Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    See Also

    +pthread_create(3) +, pthread_join(3) +. +

    + +


    +Table of Contents

    +

    + + diff --git a/liblo/pthreads.2/manual/pthread_getw32threadhandle_np.html b/liblo/pthreads.2/manual/pthread_getw32threadhandle_np.html new file mode 100644 index 0000000..bc7b87a --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_getw32threadhandle_np.html @@ -0,0 +1,57 @@ + + + + + PTHREAD_GETW32THREADHANDLE_NP manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_getw32threadhandle_np – get +the Win32 thread handle associated with a thread

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    HANDLE pthread_getw32threadhandle_np(pthread_t thread);

    +

    Description

    +

    Returns the Win32 native thread HANDLE that the POSIX +thread thread is running as.

    +

    Applications can use the Win32 handle to set Win32 specific +attributes of the thread.

    +

    Cancellation

    +

    None.

    +

    Return Value

    +

    pthread_getw32threadhandle_np returns the Win32 native +thread HANDLE for the specified POSIX thread thread.

    +

    Errors

    +

    None.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_join.html b/liblo/pthreads.2/manual/pthread_join.html new file mode 100644 index 0000000..a66d4d4 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_join.html @@ -0,0 +1,118 @@ + + + + + PTHREAD_JOIN(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_join - wait for termination of another thread +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_join(pthread_t th, void +**thread_return); +

    +

    Description

    +

    pthread_join suspends the execution of the calling thread +until the thread identified by th terminates, either by +calling pthread_exit(3) or by +being cancelled. +

    +

    If thread_return is not NULL, the return value of th +is stored in the location pointed to by thread_return. The +return value of th is either the argument it gave to +pthread_exit(3) , or +PTHREAD_CANCELED if th was cancelled. +

    +

    The joined thread th must be in the joinable state: it must +not have been detached using pthread_detach(3) +or the PTHREAD_CREATE_DETACHED attribute to pthread_create(3) +. +

    +

    When a joinable thread terminates, its memory resources (thread +descriptor and stack) are not deallocated until another thread +performs pthread_join on it. Therefore, pthread_join +must be called once for each joinable thread created to avoid memory +leaks. +

    +

    At most one thread can wait for the termination of a given thread. +Calling pthread_join on a thread th on which another +thread is already waiting for termination returns an error. +

    +

    Cancellation

    +

    pthread_join is a cancellation point. If a thread is +cancelled while suspended in pthread_join, the thread +execution resumes immediately and the cancellation is executed +without waiting for the th thread to terminate. If +cancellation occurs during pthread_join, the th thread +remains not joined. +

    +

    Return Value

    +

    On success, the return value of th is stored in the +location pointed to by thread_return, and 0 is returned. On +error, a non-zero error code is returned. +

    +

    Errors

    +
    +
    ESRCH +
    + No thread could be found corresponding to that specified by th. +
    + EINVAL +
    + The th thread has been detached. +
    + EINVAL +
    + Another thread is already waiting on termination of th. +
    + EDEADLK +
    + The th argument refers to the calling thread. +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    See Also

    +

    pthread_exit(3) , +pthread_detach(3) , +pthread_create(3) , +pthread_attr_setdetachstate(3) +, pthread_cleanup_push(3) +, pthread_key_create(3) +. +

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_key_create.html b/liblo/pthreads.2/manual/pthread_key_create.html new file mode 100644 index 0000000..a94d6e6 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_key_create.html @@ -0,0 +1,211 @@ + + + + + PTHREAD_SPECIFIC(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_key_create, pthread_key_delete, pthread_setspecific, +pthread_getspecific - management of thread-specific data +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_key_create(pthread_key_t *key, void +(*destr_function) (void *)); +

    +

    int pthread_key_delete(pthread_key_t key); +

    +

    int pthread_setspecific(pthread_key_t key, const +void *pointer); +

    +

    void * pthread_getspecific(pthread_key_t key); +

    +

    Description

    +

    Programs often need global or static variables that have different +values in different threads. Since threads share one memory space, +this cannot be achieved with regular variables. Thread-specific data +is the POSIX threads answer to this need. +

    +

    Each thread possesses a private memory block, the thread-specific +data area, or TSD area for short. This area is indexed by TSD keys. +The TSD area associates values of type void * to TSD keys. TSD +keys are common to all threads, but the value associated with a given +TSD key can be different in each thread. +

    +

    For concreteness, the TSD areas can be viewed as arrays of void +* pointers, TSD keys as integer indices into these arrays, and +the value of a TSD key as the value of the corresponding array +element in the calling thread. +

    +

    When a thread is created, its TSD area initially associates NULL +with all keys. +

    +

    pthread_key_create allocates a new TSD key. The key is +stored in the location pointed to by key. There is a limit of +PTHREAD_KEYS_MAX on the number of keys allocated at a given +time. The value initially associated with the returned key is NULL +in all currently executing threads. +

    +

    The destr_function argument, if not NULL, specifies +a destructor function associated with the key. When a thread +terminates via pthread_exit or by cancellation, destr_function +is called with arguments the value associated with the key in that +thread. The destr_function is not called if that value is NULL +or the key has been deleted. The order in which destructor +functions are called at thread termination time is unspecified. +

    +

    Before the destructor function is called, the NULL value is +associated with the key in the current thread. A destructor function +might, however, re-associate non- NULL values to that key or +some other key. To deal with this, if after all the destructors have +been called for all non- NULL values, there are still some +non- NULL values with associated destructors, then the process +is repeated.

    +

    pthread_key_delete deallocates a TSD key. It does not check +whether non- NULL values are associated with that key in the +currently executing threads, nor call the destructor function +associated with the key. +

    +

    pthread_setspecific changes the value associated with key +in the calling thread, storing the given pointer instead. +

    +

    pthread_getspecific returns the value currently associated +with key in the calling thread. +

    +

    The routines pthread_setspecific, pthread_getspecific, +and pthread_key_delete can be called from destr_function +targeting any valid key including the key on which destr_function +is currently operating. If pthread_getspecific is called on +the key whose thread specific data is being destroyed, the value NULL +is returned, unless pthread_setspecific was called previously +on that key from within destr_function to set the value to +non-NULL. For some implementations the effect of calling +pthread_setspecific from within destr_function can be +either memory leakage or infinite loops if destr_function has +already been called at least PTHREAD_DESTRUCTOR_ITERATIONS +times.

    +

    Pthreads-w32 stops running key +destr_function routines after PTHREAD_DESTRUCTOR_ITERATIONS +iterations, even if some non- NULL values with associated +descriptors remain. If memory is allocated and associated with a key +from within destr_function, that memory may not be reclaimed +because that key's destr_function, may not run again.

    +

    Return Value

    +

    pthread_key_create, pthread_key_delete, and +pthread_setspecific return 0 on success and a non-zero error +code on failure. If successful, pthread_key_create stores the +newly allocated key in the location pointed to by its key +argument. +

    +

    pthread_getspecific returns the value associated with key +on success, and NULL on error. +

    +

    Errors

    +

    pthread_key_create returns the following error code on +error: +

    +
    +
    +
    EAGAIN +
    +
    +
    +PTHREAD_KEYS_MAX keys are already allocated +
    +
    +
    +
    ENOMEM +
    +
    +
    +Insufficient memory to allocate the key. +
    +

    pthread_key_delete and pthread_setspecific return +the following error code on error: +

    +
    +
    +
    EINVAL +
    + key is not a valid, allocated TSD key +
    +
    +

    +pthread_getspecific returns NULL if key is not a +valid, allocated TSD key. +

    +

    Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_create(3) , +pthread_exit(3) , +pthread_testcancel(3) . +

    +

    Example

    +

    The following code fragment allocates a thread-specific array of +100 characters, with automatic reclamation at thread exit: +

    +


    +
    +
    /* Key for the thread-specific buffer */
    +static pthread_key_t buffer_key;
    +/* Once-only initialisation of the key */
    +static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;
    +/* Allocate the thread-specific buffer */
    +void buffer_alloc(void)
    +{
    +  pthread_once(&buffer_key_once, buffer_key_alloc);
    +  pthread_setspecific(buffer_key, malloc(100));
    +}
    +/* Return the thread-specific buffer */
    +char * get_buffer(void)
    +{
    +  return (char *) pthread_getspecific(buffer_key);
    +}
    +/* Allocate the key */
    +static void buffer_key_alloc()
    +{
    +  pthread_key_create(&buffer_key, buffer_destroy);
    +}
    +/* Free the thread-specific buffer */
    +static void buffer_destroy(void * buf)
    +{
    +  free(buf);
    +}
    +
    +
    +Table of Contents
    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/pthread_kill.html b/liblo/pthreads.2/manual/pthread_kill.html new file mode 100644 index 0000000..4a66e0e --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_kill.html @@ -0,0 +1,152 @@ + + + + + PTHREAD_SIGNAL(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_sigmask, pthread_kill, sigwait - handling of signals in +threads +

    +

    Synopsis

    +

    #include <pthread.h>
    #include <signal.h> +

    +

    int pthread_sigmask(int how, const sigset_t +*newmask, sigset_t *oldmask); +

    +

    int pthread_kill(pthread_t thread, int signo); +

    +

    int sigwait(const sigset_t *set, int *sig);

    +

    Description

    +

    pthread_sigmask changes the signal mask for the calling +thread as described by the how and newmask arguments. +If oldmask is not NULL, the previous signal mask is +stored in the location pointed to by oldmask. Pthreads-w32 +implements this function but no other function uses the signal mask +yet.

    +

    The meaning of the how and newmask arguments is the +same as for sigprocmask(2). +If how is SIG_SETMASK, the signal mask is set to +newmask. If how is SIG_BLOCK, the signals +specified to newmask are added to the current signal mask. If +how is SIG_UNBLOCK, the signals specified to newmask +are removed from the current signal mask. +

    +

    Recall that signal masks are set on a per-thread basis, but signal +actions and signal handlers, as set with sigaction(2), are +shared between all threads. +

    +

    pthread_kill send signal number signo to the thread +thread. Pthreads-w32 only supports signal number 0, +which does not send any signal but causes pthread_kill to +return an error if thread is not valid.

    +

    sigwait suspends the calling thread until one of the +signals in set is delivered to the calling thread. It then +stores the number of the signal received in the location pointed to +by sig and returns. The signals in set must be blocked +and not ignored on entrance to sigwait. If the delivered +signal has a signal handler function attached, that function is not +called. Pthreads-w32 implements this function as a +cancellation point only - it does not wait for any signals and does +not change the location pointed to by sig.

    +

    Cancellation

    +

    sigwait is a cancellation point. +

    +

    Return Value

    +

    On success, 0 is returned. On failure, a non-zero error code is +returned. +

    +

    Errors

    +

    The pthread_sigmask function returns the following error +codes on error: +

    +
    +
    +
    EINVAL +
    + how is not one of SIG_SETMASK, SIG_BLOCK, or + SIG_UNBLOCK +
    +
    +

    +The pthread_kill function returns the following error codes on +error: +

    +
    +
    +
    EINVAL +
    + signo is not a valid signal number or is unsupported.
    + ESRCH +
    + the thread thread does not exist (e.g. it has already + terminated) +
    +
    +

    +The sigwait function never returns an error. +

    +

    Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    +

    +

    Notes

    +

    In any implementation, for sigwait to work reliably, the +signals being waited for must be blocked in all threads, not only in +the calling thread, since otherwise the POSIX semantics for signal +delivery do not guarantee that it’s the thread doing the sigwait +that will receive the signal. The best way to achieve this is to +block those signals before any threads are created, and never unblock +them in the program other than by calling sigwait. This works +because all threads inherit their initial sigmask from their creating +thread.

    +

    Bugs

    +

    Pthreads-w32 does not implement signals yet and so these +routines have almost no use except to prevent the compiler or linker +from complaining. pthread_kill is useful in determining if the +thread is a valid thread, but since many threads implementations +reuse thread IDs, the valid thread may no longer be the thread you +think it is, and so this method of determining thread validity is not +portable, and very risky. Pthreads-w32 from version 1.0.0 +onwards implements pseudo-unique thread IDs, so applications that use +this technique (but really shouldn't) have some protection.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_mutex_init.html b/liblo/pthreads.2/manual/pthread_mutex_init.html new file mode 100644 index 0000000..cf0db6c --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_mutex_init.html @@ -0,0 +1,277 @@ + + + + + PTHREAD_MUTEX(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock, +pthread_mutex_timedlock, pthread_mutex_unlock, pthread_mutex_destroy +- operations on mutexes +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    #include <time.h>

    +

    pthread_mutex_t fastmutex = +PTHREAD_MUTEX_INITIALIZER; +

    +

    pthread_mutex_t recmutex = +PTHREAD_RECURSIVE_MUTEX_INITIALIZER; +

    +

    pthread_mutex_t errchkmutex = +PTHREAD_ERRORCHECK_MUTEX_INITIALIZER; +

    +

    pthread_mutex_t recmutex = +PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +

    +

    pthread_mutex_t errchkmutex = +PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; +

    +

    int pthread_mutex_init(pthread_mutex_t *mutex, +const pthread_mutexattr_t *mutexattr); +

    +

    int pthread_mutex_lock(pthread_mutex_t *mutex); +

    +

    int pthread_mutex_trylock(pthread_mutex_t *mutex); +

    +

    int pthread_mutex_timedlock(pthread_mutex_t *mutex, +const struct timespec *abs_timeout); +

    +

    int pthread_mutex_unlock(pthread_mutex_t *mutex); +

    +

    int pthread_mutex_destroy(pthread_mutex_t *mutex); +

    +

    Description

    +

    A mutex is a MUTual EXclusion device, and is useful for protecting +shared data structures from concurrent modifications, and +implementing critical sections and monitors. +

    +

    A mutex has two possible states: unlocked (not owned by any +thread), and locked (owned by one thread). A mutex can never be owned +by two different threads simultaneously. A thread attempting to lock +a mutex that is already locked by another thread is suspended until +the owning thread unlocks the mutex first. +

    +

    pthread_mutex_init initializes the mutex object pointed to +by mutex according to the mutex attributes specified in +mutexattr. If mutexattr is NULL, default +attributes are used instead. +

    +

    The type of a mutex determines whether it can be locked again by a +thread that already owns it. The default type is “normalâ€. See +pthread_mutexattr_init(3) +for more information on mutex attributes. +

    +

    Variables of type pthread_mutex_t can also be initialized +statically, using the constants PTHREAD_MUTEX_INITIALIZER (for +normal “fast†mutexes), PTHREAD_RECURSIVE_MUTEX_INITIALIZER +(for recursive mutexes), and PTHREAD_ERRORCHECK_MUTEX_INITIALIZER +(for error checking mutexes). In +the Pthreads-w32 implementation, an application should still +call pthread_mutex_destroy at some point to ensure that any +resources consumed by the mutex are released.

    +

    pthread_mutex_lock locks the given mutex. If the mutex is +currently unlocked, it becomes locked and owned by the calling +thread, and pthread_mutex_lock returns immediately. If the +mutex is already locked by another thread, pthread_mutex_lock +suspends the calling thread until the mutex is unlocked. +

    +

    If the mutex is already locked by the calling thread, the behavior +of pthread_mutex_lock depends on the type of the mutex. If the +mutex is of the “normal†type, the calling thread is suspended +until the mutex is unlocked, thus effectively causing the calling +thread to deadlock. If the mutex is of the ‘‘error checking’’ +type, pthread_mutex_lock returns immediately with the error +code EDEADLK. If the mutex is of the ‘‘recursive’’ +type, pthread_mutex_lock succeeds and returns immediately, +recording the number of times the calling thread has locked the +mutex. An equal number of pthread_mutex_unlock operations must +be performed before the mutex returns to the unlocked state. +

    +

    pthread_mutex_trylock behaves identically to +pthread_mutex_lock, except that it does not block the calling +thread if the mutex is already locked by another thread (or by the +calling thread in the case of a “normal†mutex). Instead, +pthread_mutex_trylock returns immediately with the error code +EBUSY. +

    +

    pthread_mutex_timedlock behaves identically to +pthread_mutex_lock, except that if it cannot acquire the lock +before the abs_timeout time, the call returns with the error +code ETIMEDOUT. If the mutex can be locked immediately it is, +and the abs_timeout parameter is ignored.

    +

    pthread_mutex_unlock unlocks the given mutex. The mutex is +assumed to be locked and owned by the calling thread on entrance to +pthread_mutex_unlock. If the mutex is of the “normal†+type, pthread_mutex_unlock always returns it to the unlocked +state. If it is of the ‘‘recursive’’ type, it decrements the +locking count of the mutex (number of pthread_mutex_lock +operations performed on it by the calling thread), and only when this +count reaches zero is the mutex actually unlocked. +

    +

    On ‘‘error checking’’ mutexes, pthread_mutex_unlock +actually checks at run-time that the mutex is locked on entrance, and +that it was locked by the same thread that is now calling +pthread_mutex_unlock. If these conditions are not met, an +error code is returned and the mutex remains unchanged. ‘‘Normal’’ +mutexes perform no such checks, thus allowing a locked mutex to be +unlocked by a thread other than its owner. This is non-portable +behavior and is not meant to be used as a feature.

    +

    pthread_mutex_destroy destroys a mutex object, freeing the +resources it might hold. The mutex must be unlocked on entrance.

    +

    Cancellation

    +

    None of the mutex functions is a cancellation point, not even +pthread_mutex_lock, in spite of the fact that it can suspend a +thread for arbitrary durations. This way, the status of mutexes at +cancellation points is predictable, allowing cancellation handlers to +unlock precisely those mutexes that need to be unlocked before the +thread stops executing. Consequently, threads using deferred +cancellation should never hold a mutex for extended periods of time. +

    +

    Async-signal Safety

    +

    The mutex functions are not async-signal safe. What this means is +that they should not be called from a signal handler. In particular, +calling pthread_mutex_lock or pthread_mutex_unlock from +a signal handler may deadlock the calling thread. +

    +

    Return Value

    +

    pthread_mutex_init always returns 0. The other mutex +functions return 0 on success and a non-zero error code on error. +

    +

    Errors

    +

    The pthread_mutex_lock function returns the following error +code on error: +

    +
    +
    +
    EINVAL +
    + the mutex has not been properly initialized. +
    + EDEADLK +
    + the mutex is already locked by the calling thread (‘‘error + checking’’ mutexes only). +
    +
    +

    +The pthread_mutex_trylock function returns the following error +codes on error: +

    +
    +
    +
    EBUSY +
    + the mutex could not be acquired because it was currently locked. +
    + EINVAL +
    + the mutex has not been properly initialized. +
    +
    +

    +The pthread_mutex_timedlock function returns the following +error codes on error: +

    +
    +
    +
    ETIMEDOUT +
    + the mutex could not be acquired before the abs_timeout time + arrived. +
    + EINVAL +
    + the mutex has not been properly initialized. +
    +
    +

    +The pthread_mutex_unlock function returns the following error +code on error: +

    +
    +
    +
    EINVAL +
    + the mutex has not been properly initialized. +
    + EPERM +
    + the calling thread does not own the mutex (‘‘error checking’’ + mutexes only). +
    +
    +

    +The pthread_mutex_destroy function returns the following error +code on error: +

    +
    +
    +
    EBUSY +
    + the mutex is currently locked. +
    +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_mutexattr_init(3) +, pthread_mutexattr_settype(3) +, pthread_cancel(3) . +

    +

    Example

    +

    A shared global variable x can be protected by a mutex as +follows: +

    +
    int x;
    +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
    +All accesses and modifications to x should be bracketed by +calls to pthread_mutex_lock and pthread_mutex_unlock as +follows: +
    +
    pthread_mutex_lock(&mut);
    +/* operate on x */
    +pthread_mutex_unlock(&mut);
    +
    +
    Table of +Contents
    + + + diff --git a/liblo/pthreads.2/manual/pthread_mutexattr_init.html b/liblo/pthreads.2/manual/pthread_mutexattr_init.html new file mode 100644 index 0000000..4839832 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_mutexattr_init.html @@ -0,0 +1,157 @@ + + + + + PTHREAD_MUTEXATTR(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_mutexattr_init, pthread_mutexattr_destroy, +pthread_mutexattr_settype, pthread_mutexattr_gettype - mutex creation +attributes +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_mutexattr_init(pthread_mutexattr_t *attr); +

    +

    int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); +

    +

    int pthread_mutexattr_settype(pthread_mutexattr_t *attr, +int type); +

    +

    int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, +int *type); +

    +

    int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, +int type); +

    +

    int pthread_mutexattr_getkind_np(const pthread_mutexattr_t +*attr, int *type); +

    +

    Description

    +

    Mutex attributes can be specified at mutex creation time, by +passing a mutex attribute object as second argument to +pthread_mutex_init(3) . +Passing NULL is equivalent to passing a mutex attribute object +with all attributes set to their default values. +

    +

    pthread_mutexattr_init initializes the mutex attribute +object attr and fills it with default values for the +attributes. +

    +

    pthread_mutexattr_destroy destroys a mutex attribute +object, which must not be reused until it is reinitialized.

    +

    The following mutex types are supported:

    +

    PTHREAD_MUTEX_NORMAL - for +‘‘fast’’ mutexes.

    +

    PTHREAD_MUTEX_RECURSIVE - for +‘‘recursive’’ mutexes.

    +

    PTHREAD_MUTEX_ERRORCHECK - for +‘‘error checking’’ mutexes.

    +

    The mutex type determines what happens if a thread attempts to +lock a mutex it already owns with pthread_mutex_lock(3) +. If the mutex is of the “normal†or “fast†type, +pthread_mutex_lock(3) +simply suspends the calling thread forever. If the mutex is of the +‘‘error checking’’ type, pthread_mutex_lock(3) +returns immediately with the error code EDEADLK. If the mutex +is of the ‘‘recursive’’ type, the call to +pthread_mutex_lock(3) +returns immediately with a success return code. The number of times +the thread owning the mutex has locked it is recorded in the mutex. +The owning thread must call pthread_mutex_unlock(3) +the same number of times before the mutex returns to the unlocked +state. +

    +

    The default mutex type is PTHREAD_MUTEX_NORMAL

    +

    Pthreads-w32 also recognises the following equivalent types +that are used by Linux:

    +

    PTHREAD_MUTEX_FAST_NP +– equivalent to PTHREAD_MUTEX_NORMAL

    +

    PTHREAD_MUTEX_RECURSIVE_NP

    +

    PTHREAD_MUTEX_ERRORCHECK_NP

    +

    pthread_mutexattr_settype sets the mutex type attribute in +attr to the value specified by type. +

    +

    pthread_mutexattr_gettype retrieves the current value of +the mutex kind attribute in attr and stores it in the location +pointed to by type. +

    +

    Pthreads-w32 also recognises the following equivalent +functions that are used in Linux:

    +

    pthread_mutexattr_setkind_np is an alias for +pthread_mutexattr_settype. +

    +

    pthread_mutexattr_getkind_np is +an alias for pthread_mutexattr_gettype. +

    +

    Return Value

    +

    pthread_mutexattr_init, pthread_mutexattr_destroy +and pthread_mutexattr_gettype always return 0. +

    +

    pthread_mutexattr_settype returns 0 on success and a +non-zero error code on error. +

    +

    Errors

    +

    On error, pthread_mutexattr_settype returns the following +error code: +

    +
    +
    EINVAL +
    + type is none of:
    PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_FAST_NP,
    PTHREAD_MUTEX_RECURSIVE, + PTHREAD_MUTEX_RECURSIVE_NP,
    PTHREAD_MUTEX_ERRORCHECK
    , + PTHREAD_MUTEX_ERRORCHECK_NP +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_mutex_init(3) +, pthread_mutex_lock(3) +, pthread_mutex_unlock(3) +. +

    +

    Notes

    +

    For speed, Pthreads-w32 never checks the thread ownership +of mutexes of type PTHREAD_MUTEX_NORMAL (or +PTHREAD_MUTEX_FAST_NP) when performing operations on the +mutex. It is therefore possible for one thread to lock such a mutex +and another to unlock it.

    +

    When developing code, it is a +common precaution to substitute the error checking type, and drop in +the normal type for release if the extra performance is required.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_mutexattr_setpshared.html b/liblo/pthreads.2/manual/pthread_mutexattr_setpshared.html new file mode 100644 index 0000000..78b36b4 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_mutexattr_setpshared.html @@ -0,0 +1,151 @@ + + + + + "PTHREAD_MUTEXATTR_GETPSHARED"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_mutexattr_getpshared, pthread_mutexattr_setpshared - get +and set the process-shared attribute +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_mutexattr_getpshared(const pthread_mutexattr_t * +restrict attr, int *restrict pshared); +
    int pthread_mutexattr_setpshared(pthread_mutexattr_t *
    attr, +int pshared); +

    +

    Description

    +

    The pthread_mutexattr_getpshared function shall obtain the +value of the process-shared attribute from the attributes +object referenced by attr. The pthread_mutexattr_setpshared +function shall set the process-shared attribute in an +initialized attributes object referenced by attr. +

    +

    The process-shared attribute is set to +PTHREAD_PROCESS_SHARED to permit a mutex to be operated upon +by any thread that has access to the memory where the mutex is +allocated, even if the mutex is allocated in memory that is shared by +multiple processes. If the process-shared attribute is +PTHREAD_PROCESS_PRIVATE, the mutex shall only be operated upon +by threads created within the same process as the thread that +initialized the mutex; if threads of differing processes attempt to +operate on such a mutex, the behavior is undefined. The default value +of the attribute shall be PTHREAD_PROCESS_PRIVATE. +

    +

    Pthreads-w32 defines _POSIX_THREAD_PROCESS_SHARED in +pthread.h as -1 to indicate that these routines are implemented but +the process shared option is not supported.

    +

    Return Value

    +

    Upon successful completion, pthread_mutexattr_setpshared +shall return zero; otherwise, an error number shall be returned to +indicate the error. +

    +

    Upon successful completion, pthread_mutexattr_getpshared +shall return zero and store the value of the process-shared +attribute of attr into the object referenced by the pshared +parameter. Otherwise, an error number shall be returned to indicate +the error. +

    +

    Errors

    +

    The pthread_mutexattr_getpshared and +pthread_mutexattr_setpshared functions may fail if: +

    +
    +
    EINVAL +
    + The value specified by attr is invalid. +
    +

    +The pthread_mutexattr_setpshared function may fail if: +

    +
    +
    EINVAL +
    + The new value specified for the attribute is outside the range of + legal values for that attribute. +
    + ENOTSUP +
    + The new value specified for the attribute is PTHREAD_PROCESS_SHARED. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_cond_destroy(3) +, pthread_create(3) , +pthread_mutex_destroy(3) +, pthread_mutexattr_destroy(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_num_processors_np.html b/liblo/pthreads.2/manual/pthread_num_processors_np.html new file mode 100644 index 0000000..20d3b83 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_num_processors_np.html @@ -0,0 +1,57 @@ + + + + + PTHREAD_NUM_PROCESSORS_NP manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_num_processors_np – get the +number of processors (CPUs) in use by the process

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_num_processors_np(void);

    +

    Description

    +

    pthread_num_processors_np returns the number of processors +in the system. This implementation actually returns the number of +processors available to the process, which can be a lower number than +the system's number, depending on the process's affinity mask.

    +

    Cancellation

    +

    None.

    +

    Return Value

    +

    pthread_num_processors_np returns the number of processors +currently available to the process.

    +

    Errors

    +

    None.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_once.html b/liblo/pthreads.2/manual/pthread_once.html new file mode 100644 index 0000000..67b25e7 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_once.html @@ -0,0 +1,83 @@ + + + + + PTHREAD_ONCE(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_once - once-only initialization +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    pthread_once_t once_control = PTHREAD_ONCE_INIT; +

    +

    int pthread_once(pthread_once_t *once_control, +void (*init_routine) (void)); +

    +

    Description

    +

    The purpose of pthread_once is to ensure that a piece of +initialization code is executed at most once. The once_control +argument points to a static or extern variable statically initialized +to PTHREAD_ONCE_INIT. +

    +

    The first time pthread_once is called with a given +once_control argument, it calls init_routine with no +argument and changes the value of the once_control variable to +record that initialization has been performed. Subsequent calls to +pthread_once with the same once_control argument do +nothing. +

    +

    Cancellation

    +

    While pthread_once is not a cancellation point, +init_routine can be. The effect on once_control of a +cancellation inside the init_routine is to leave it as if +pthread_once had not been called by the cancelled thread.

    +

    Return Value

    +

    pthread_once +returns 0 on success, or an error code on failure.

    +

    Errors

    +

    The pthread_once function returns the following error code +on error: +

    +
    +
    +
    EINVAL +
    +
    +

    +The once_control or init_routine parameter is NULL.

    +

    Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/pthread_rwlock_init.html b/liblo/pthreads.2/manual/pthread_rwlock_init.html new file mode 100644 index 0000000..ef83b44 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlock_init.html @@ -0,0 +1,193 @@ + + + + + "PTHREAD_RWLOCK_DESTROY"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlock_destroy, pthread_rwlock_init - destroy and +initialize a read-write lock object +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    pthread_wrlock_t rwlock = +PTHREAD_RWLOCK_INITIALIZER;

    +

    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); +
    int pthread_rwlock_init(pthread_rwlock_t *restrict
    rwlock, +const pthread_rwlockattr_t *restrict attr); +

    +

    Description

    +

    The pthread_rwlock_destroy function shall destroy the +read-write lock object referenced by rwlock and release any +resources used by the lock. The effect of subsequent use of the lock +is undefined until the lock is reinitialized by another call to +pthread_rwlock_init. An implementation may cause +pthread_rwlock_destroy to set the object referenced by rwlock +to an invalid value. Results are undefined if pthread_rwlock_destroy +is called when any thread holds rwlock. Attempting to destroy +an uninitialized read-write lock results in undefined behavior. +

    +

    The pthread_rwlock_init function shall allocate any +resources required to use the read-write lock referenced by rwlock +and initializes the lock to an unlocked state with attributes +referenced by attr. If attr is NULL, the default +read-write lock attributes shall be used; the effect is the same as +passing the address of a default read-write lock attributes object. +Once initialized, the lock can be used any number of times without +being reinitialized. Results are undefined if pthread_rwlock_init +is called specifying an already initialized read-write lock. Results +are undefined if a read-write lock is used without first being +initialized. +

    +

    If the pthread_rwlock_init function fails, rwlock +shall not be initialized and the contents of rwlock are +undefined. +

    +

    Pthreads-w32 supports statically initialized rwlock +objects using PTHREAD_RWLOCK_INITIALIZER. +An application should still call pthread_rwlock_destroy at +some point to ensure that any resources consumed by the read/write +lock are released.

    +

    Only the object referenced by rwlock may be used for +performing synchronization. The result of referring to copies of that +object in calls to pthread_rwlock_destroy , +pthread_rwlock_rdlock , pthread_rwlock_timedrdlock , +pthread_rwlock_timedwrlock , pthread_rwlock_tryrdlock , +pthread_rwlock_trywrlock , pthread_rwlock_unlock , or +pthread_rwlock_wrlock is undefined. +

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    If successful, the pthread_rwlock_destroy and +pthread_rwlock_init functions shall return zero; otherwise, an +error number shall be returned to indicate the error. +

    +

    The [EBUSY] and [EINVAL] error checks, if implemented, act as if +they were performed immediately at the beginning of processing for +the function and caused an error return prior to modifying the state +of the read-write lock specified by rwlock. +

    +

    Errors

    +

    The pthread_rwlock_destroy function may fail if: +

    +
    +
    EBUSY +
    + The implementation has detected an attempt to destroy the object + referenced by rwlock while it is locked. +
    + EINVAL +
    + The value specified by rwlock is invalid. +
    +

    +The pthread_rwlock_init function shall fail if: +

    +
    +
    EAGAIN +
    + The system lacked the necessary resources (other than memory) to + initialize another read-write lock. +
    + ENOMEM +
    + Insufficient memory exists to initialize the read-write lock. +
    +

    +
    +

    +The pthread_rwlock_init function may fail if: +

    +
    +
    EINVAL +
    + The value specified by attr is invalid. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Applications using these and related read-write lock functions may +be subject to priority inversion, as discussed in the Base +Definitions volume of IEEE Std 1003.1-2001, Section 3.285, +Priority Inversion. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_rdlock(3) +, pthread_rwlock_timedrdlock(3) +, pthread_rwlock_timedwrlock(3) +, pthread_rwlock_tryrdlock(3) +, pthread_rwlock_trywrlock(3) +, pthread_rwlock_unlock(3) +, pthread_rwlock_wrlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_rwlock_rdlock.html b/liblo/pthreads.2/manual/pthread_rwlock_rdlock.html new file mode 100644 index 0000000..b6e79a8 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlock_rdlock.html @@ -0,0 +1,168 @@ + + + + + "PTHREAD_RWLOCK_RDLOCK"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlock_rdlock, pthread_rwlock_tryrdlock - lock a +read-write lock object for reading +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); +
    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); + +

    +

    Description

    +

    The pthread_rwlock_rdlock function shall apply a read lock +to the read-write lock referenced by rwlock. The calling +thread acquires the read lock if a writer does not hold the lock and +there are no writers blocked on the lock. +

    +

    Pthreads-win32 does not prefer either writers or readers in +acquiring the lock – all threads enter a single prioritised FIFO +queue. While this may not be optimally efficient for some +applications, it does ensure that one type does not starve the other.

    +

    A thread may hold multiple concurrent read locks on rwlock +(that is, successfully call the pthread_rwlock_rdlock function +n times). If so, the application shall ensure that the thread +performs matching unlocks (that is, it calls the +pthread_rwlock_unlock(3) +function n times). +

    +

    The pthread_rwlock_tryrdlock function shall apply a read +lock as in the pthread_rwlock_rdlock function, with the +exception that the function shall fail if the equivalent +pthread_rwlock_rdlock call would have blocked the calling +thread. In no case shall the pthread_rwlock_tryrdlock function +ever block; it always either acquires the lock or fails and returns +immediately. +

    +

    Results are undefined if any of these functions are called with an +uninitialized read-write lock. +

    +

    Pthreads-w32 does not detect deadlock if the thread already +owns the lock for writing.

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    If successful, the pthread_rwlock_rdlock function shall +return zero; otherwise, an error number shall be returned to indicate +the error. +

    +

    The pthread_rwlock_tryrdlock function shall return zero if +the lock for reading on the read-write lock object referenced by +rwlock is acquired. Otherwise, an error number shall be +returned to indicate the error. +

    +

    Errors

    +

    The pthread_rwlock_tryrdlock function shall fail if: +

    +
    +
    EBUSY +
    + The read-write lock could not be acquired for reading because a + writer holds the lock or a writer with the appropriate priority was + blocked on it. +
    +

    +The pthread_rwlock_rdlock and pthread_rwlock_tryrdlock +functions may fail if: +

    +
    +
    EINVAL +
    + The value specified by rwlock does not refer to an + initialized read-write lock object. +
    + EAGAIN +
    + The read lock could not be acquired because the maximum number of + read locks for rwlock has been exceeded. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Applications using these functions may be subject to priority +inversion, as discussed in the Base Definitions volume of +IEEE Std 1003.1-2001, Section 3.285, Priority Inversion. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_destroy(3) +, pthread_rwlock_timedrdlock(3) +, pthread_rwlock_timedwrlock(3) +, pthread_rwlock_trywrlock(3) +, pthread_rwlock_unlock(3) +, pthread_rwlock_wrlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_rwlock_timedrdlock.html b/liblo/pthreads.2/manual/pthread_rwlock_timedrdlock.html new file mode 100644 index 0000000..88bf8f8 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlock_timedrdlock.html @@ -0,0 +1,156 @@ + + + + + "PTHREAD_RWLOCK_TIMEDRDLOCK"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlock_timedrdlock - lock a read-write lock for reading +

    +

    Synopsis

    +

    #include <pthread.h>
    #include <time.h> +

    +

    int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict +rwlock, const struct timespec *restrict abs_timeout); + +

    +

    Description

    +

    The pthread_rwlock_timedrdlock function shall apply a read +lock to the read-write lock referenced by rwlock as in the +pthread_rwlock_rdlock(3) +function. However, if the lock cannot be acquired without waiting for +other threads to unlock the lock, this wait shall be terminated when +the specified timeout expires. The timeout shall expire when the +absolute time specified by abs_timeout passes, as measured by +the clock on which timeouts are based (that is, when the value of +that clock equals or exceeds abs_timeout), or if the absolute +time specified by abs_timeout has already been passed at the +time of the call. +

    +

    The timespec data type is defined in the <time.h> +header. Under no circumstances shall the function fail with a timeout +if the lock can be acquired immediately. The validity of the +abs_timeout parameter need not be checked if the lock can be +immediately acquired. +

    +

    The calling thread may deadlock if at the time the call is made it +holds a write lock on rwlock. The results are undefined if +this function is called with an uninitialized read-write lock. +

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    The pthread_rwlock_timedrdlock function shall return zero +if the lock for reading on the read-write lock object referenced by +rwlock is acquired. Otherwise, an error number shall be +returned to indicate the error. +

    +

    Errors

    +

    The pthread_rwlock_timedrdlock function shall fail if: +

    +
    +
    ETIMEDOUT +
    + The lock could not be acquired before the specified timeout expired. +
    +

    +The pthread_rwlock_timedrdlock function may fail if: +

    +
    +
    EAGAIN +
    + The read lock could not be acquired because the maximum number of + read locks for lock would be exceeded. +
    + EINVAL +
    + The value specified by rwlock does not refer to an + initialized read-write lock object, or the abs_timeout + nanosecond value is less than zero or greater than or equal to 1000 + million. +
    +

    +This function shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Applications using this function may be subject to priority +inversion, as discussed in the Base Definitions volume of +IEEE Std 1003.1-2001, Section 3.285, Priority Inversion. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_destroy(3) +, pthread_rwlock_rdlock(3) +, pthread_rwlock_timedwrlock(3) +, pthread_rwlock_tryrdlock(3) +, pthread_rwlock_trywrlock(3) +, pthread_rwlock_unlock(3) +, pthread_rwlock_wrlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h>, <time.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_rwlock_timedwrlock.html b/liblo/pthreads.2/manual/pthread_rwlock_timedwrlock.html new file mode 100644 index 0000000..2f72c55 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlock_timedwrlock.html @@ -0,0 +1,150 @@ + + + + + "PTHREAD_RWLOCK_TIMEDWRLOCK"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlock_timedwrlock - lock a read-write lock for writing +

    +

    Synopsis

    +

    #include <pthread.h>
    #include <time.h> +

    +

    int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict +rwlock, const struct timespec *restrict abs_timeout); + +

    +

    Description

    +

    The pthread_rwlock_timedwrlock function shall apply a write +lock to the read-write lock referenced by rwlock as in the +pthread_rwlock_wrlock(3) +function. However, if the lock cannot be acquired without waiting for +other threads to unlock the lock, this wait shall be terminated when +the specified timeout expires. The timeout shall expire when the +absolute time specified by abs_timeout passes, as measured by +the clock on which timeouts are based (that is, when the value of +that clock equals or exceeds abs_timeout), or if the absolute +time specified by abs_timeout has already been passed at the +time of the call. +

    +

    The timespec data type is defined in the <time.h> +header. Under no circumstances shall the function fail with a timeout +if the lock can be acquired immediately. The validity of the +abs_timeout parameter need not be checked if the lock can be +immediately acquired. +

    +

    The calling thread may deadlock if at the time the call is made it +holds the read-write lock. The results are undefined if this function +is called with an uninitialized read-write lock. +

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    The pthread_rwlock_timedwrlock function shall return zero +if the lock for writing on the read-write lock object referenced by +rwlock is acquired. Otherwise, an error number shall be +returned to indicate the error. +

    +

    Errors

    +

    The pthread_rwlock_timedwrlock function shall fail if: +

    +
    +
    ETIMEDOUT +
    + The lock could not be acquired before the specified timeout expired. +
    +

    +The pthread_rwlock_timedwrlock function may fail if: +

    +
    +
    EINVAL +
    + The value specified by rwlock does not refer to an initialized + read-write lock object, or the abs_timeout nanosecond value + is less than zero or greater than or equal to 1000 million. +
    +

    +This function shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Applications using this function may be subject to priority +inversion, as discussed in the Base Definitions volume of +IEEE Std 1003.1-2001, Section 3.285, Priority Inversion. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_destroy(3) +, pthread_rwlock_rdlock(3) +, pthread_rwlock_timedrdlock(3) +, pthread_rwlock_tryrdlock(3) +, pthread_rwlock_trywrlock(3) +, pthread_rwlock_unlock(3) +, pthread_rwlock_wrlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h>, <time.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_rwlock_unlock.html b/liblo/pthreads.2/manual/pthread_rwlock_unlock.html new file mode 100644 index 0000000..6c8d25a --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlock_unlock.html @@ -0,0 +1,141 @@ + + + + + "PTHREAD_RWLOCK_UNLOCK"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlock_unlock - unlock a read-write lock object +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); + +

    +

    Description

    +

    The pthread_rwlock_unlock function shall release a lock +held on the read-write lock object referenced by rwlock. +Results are undefined if the read-write lock rwlock is not +held by the calling thread. +

    +

    If this function is called to release a read lock from the +read-write lock object and there are other read locks currently held +on this read-write lock object, the read-write lock object remains in +the read locked state. If this function releases the last read lock +for this read-write lock object, the read-write lock object shall be +put in the unlocked state with no owners. +

    +

    If this function is called to release a write lock for this +read-write lock object, the read-write lock object shall be put in +the unlocked state. +

    +

    Pthreads-win32 does not prefer either writers or readers in +acquiring the lock – all threads enter a single prioritised FIFO +queue. While this may not be optimally efficient for some +applications, it does ensure that one type does not starve the other.

    +

    Results are undefined if any of these functions are called with an +uninitialized read-write lock. +

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    If successful, the pthread_rwlock_unlock function shall +return zero; otherwise, an error number shall be returned to indicate +the error. +

    +

    Errors

    +

    The pthread_rwlock_unlock function may fail if: +

    +
    +
    EINVAL +
    + The value specified by rwlock does not refer to an + initialized read-write lock object. +
    +

    +
    +

    +The pthread_rwlock_unlock function shall not return an error +code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_destroy(3) +, pthread_rwlock_rdlock(3) +, pthread_rwlock_timedrdlock(3) +, pthread_rwlock_timedwrlock(3) +, pthread_rwlock_tryrdlock(3) +, pthread_rwlock_trywrlock(3) +, pthread_rwlock_wrlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_rwlock_wrlock.html b/liblo/pthreads.2/manual/pthread_rwlock_wrlock.html new file mode 100644 index 0000000..f4ef782 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlock_wrlock.html @@ -0,0 +1,153 @@ + + + + + "PTHREAD_RWLOCK_TRYWRLOCK"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlock_trywrlock, pthread_rwlock_wrlock - lock a +read-write lock object for writing +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); +
    int pthread_rwlock_wrlock(pthread_rwlock_t *
    rwlock); + +

    +

    Description

    +

    The pthread_rwlock_trywrlock function shall apply a write +lock like the pthread_rwlock_wrlock function, with the +exception that the function shall fail if any thread currently holds +rwlock (for reading or writing). +

    +

    The pthread_rwlock_wrlock function shall apply a write lock +to the read-write lock referenced by rwlock. The calling +thread acquires the write lock if no other thread (reader or writer) +holds the read-write lock rwlock. Otherwise, the thread shall +block until it can acquire the lock. The calling thread may deadlock +if at the time the call is made it holds the read-write lock (whether +a read or write lock). +

    +

    Pthreads-win32 does not prefer either writers or readers in +acquiring the lock – all threads enter a single prioritised FIFO +queue. While this may not be optimally efficient for some +applications, it does ensure that one type does not starve the other.

    +

    Results are undefined if any of these functions are called with an +uninitialized read-write lock. +

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    The pthread_rwlock_trywrlock function shall return zero if +the lock for writing on the read-write lock object referenced by +rwlock is acquired. Otherwise, an error number shall be +returned to indicate the error. +

    +

    If successful, the pthread_rwlock_wrlock function shall +return zero; otherwise, an error number shall be returned to indicate +the error. +

    +

    Errors

    +

    The pthread_rwlock_trywrlock function shall fail if: +

    +
    +
    EBUSY +
    + The read-write lock could not be acquired for writing because it was + already locked for reading or writing. +
    +

    +The pthread_rwlock_trywrlock and pthread_rwlock_wrlock +functions may fail if: +

    +
    +
    EINVAL +
    + The value specified by rwlock does not refer to an + initialized read-write lock object. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Applications using these functions may be subject to priority +inversion, as discussed in the Base Definitions volume of +IEEE Std 1003.1-2001, Section 3.285, Priority Inversion. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_destroy(3) +, pthread_rwlock_rdlock(3) +, pthread_rwlock_timedrdlock(3) +, pthread_rwlock_timedwrlock(3) +, pthread_rwlock_tryrdlock(3) +, pthread_rwlock_unlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_rwlockattr_init.html b/liblo/pthreads.2/manual/pthread_rwlockattr_init.html new file mode 100644 index 0000000..4a24f7b --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlockattr_init.html @@ -0,0 +1,141 @@ + + + + + "PTHREAD_RWLOCKATTR_DESTROY"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlockattr_destroy, pthread_rwlockattr_init - destroy and +initialize the read-write lock attributes object +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr); +
    int pthread_rwlockattr_init(pthread_rwlockattr_t *
    attr); + +

    +

    Description

    +

    The pthread_rwlockattr_destroy function shall destroy a +read-write lock attributes object. A destroyed attr attributes +object can be reinitialized using pthread_rwlockattr_init ; +the results of otherwise referencing the object after it has been +destroyed are undefined. An implementation may cause +pthread_rwlockattr_destroy to set the object referenced by +attr to an invalid value. +

    +

    The pthread_rwlockattr_init function shall initialize a +read-write lock attributes object attr with the default value +for all of the attributes defined by the implementation. +

    +

    Results are undefined if pthread_rwlockattr_init is called +specifying an already initialized attr attributes object. +

    +

    After a read-write lock attributes object has been used to +initialize one or more read-write locks, any function affecting the +attributes object (including destruction) shall not affect any +previously initialized read-write locks. +

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    If successful, the pthread_rwlockattr_destroy and +pthread_rwlockattr_init functions shall return zero; +otherwise, an error number shall be returned to indicate the error. +

    +

    Errors

    +

    The pthread_rwlockattr_destroy function may fail if: +

    +
    +
    EINVAL +
    + The value specified by attr is invalid. +
    +

    +The pthread_rwlockattr_init function shall fail if: +

    +
    +
    ENOMEM +
    + Insufficient memory exists to initialize the read-write lock + attributes object. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_destroy(3) +, pthread_rwlockattr_getpshared(3) +, pthread_rwlockattr_setpshared(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_rwlockattr_setpshared.html b/liblo/pthreads.2/manual/pthread_rwlockattr_setpshared.html new file mode 100644 index 0000000..2a427fe --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_rwlockattr_setpshared.html @@ -0,0 +1,160 @@ + + + + + "PTHREAD_RWLOCKATTR_GETPSHARED"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_rwlockattr_getpshared, pthread_rwlockattr_setpshared - get +and set the process-shared attribute of the read-write lock +attributes object +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * +restrict attr, int *restrict pshared); +
    int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *
    attr, +int pshared); +

    +

    Description

    +

    The pthread_rwlockattr_getpshared function shall obtain the +value of the process-shared attribute from the initialized +attributes object referenced by attr. The +pthread_rwlockattr_setpshared function shall set the +process-shared attribute in an initialized attributes object +referenced by attr. +

    +

    The process-shared attribute shall be set to +PTHREAD_PROCESS_SHARED to permit a read-write lock to be +operated upon by any thread that has access to the memory where the +read-write lock is allocated, even if the read-write lock is +allocated in memory that is shared by multiple processes. If the +process-shared attribute is PTHREAD_PROCESS_PRIVATE, +the read-write lock shall only be operated upon by threads created +within the same process as the thread that initialized the read-write +lock; if threads of differing processes attempt to operate on such a +read-write lock, the behavior is undefined. The default value of the +process-shared attribute shall be PTHREAD_PROCESS_PRIVATE. +

    +

    Pthreads-w32 defines _POSIX_THREAD_PROCESS_SHARED in +pthread.h as -1 to indicate that these routines are implemented but +they do not support the process shared option.

    +

    Additional attributes, their default values, and the names of the +associated functions to get and set those attribute values are +implementation-defined. +

    +

    Pthreads-w32 defines _POSIX_READER_WRITER_LOCKS in +pthread.h as 200112L to indicate that the reader/writer routines are +implemented and may be used.

    +

    Return Value

    +

    Upon successful completion, the pthread_rwlockattr_getpshared +function shall return zero and store the value of the process-shared +attribute of attr into the object referenced by the pshared +parameter. Otherwise, an error number shall be returned to indicate +the error. +

    +

    If successful, the pthread_rwlockattr_setpshared function +shall return zero; otherwise, an error number shall be returned to +indicate the error. +

    +

    Errors

    +

    The pthread_rwlockattr_getpshared and +pthread_rwlockattr_setpshared functions may fail if: +

    +
    +
    EINVAL +
    + The value specified by attr is invalid. +
    +

    +The pthread_rwlockattr_setpshared function may fail if: +

    +
    +
    EINVAL +
    + The new value specified for the attribute is outside the range of + legal values for that attribute. +
    + ENOTSUP +
    + The new value specified for the attribute is PTHREAD_PROCESS_SHARED. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_rwlock_destroy(3) +, pthread_rwlockattr_destroy(3) +, pthread_rwlockattr_init(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_self.html b/liblo/pthreads.2/manual/pthread_self.html new file mode 100644 index 0000000..5af3cd5 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_self.html @@ -0,0 +1,70 @@ + + + + + PTHREAD_SELF(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_self - return identifier of current thread +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    pthread_t pthread_self(void); +

    +

    Description

    +

    pthread_self return the thread identifier for the calling +thread. +

    +

    Pthreads-w32 also provides support for Win32 native +threads to interact with POSIX threads through the pthreads API. +Whereas all threads created via a call to pthread_create have a POSIX +thread ID and thread state, the library ensures that any Win32 native +threads that interact through the Pthreads API also generate a POSIX +thread ID and thread state when and if necessary. This provides full +reciprocity between Win32 and POSIX +threads. Win32 native threads that generate a POSIX thread ID and +state are treated by the library as having been created with the +PTHREAD_CREATE_DETACHED attribute.

    +

    Any Win32 native thread may call pthread_self directly to +return it's POSIX thread identifier. The ID and state will be +generated if it does not already exist. Win32 native threads do not +need to call pthread_self before calling Pthreads-w32 routines +unless that routine requires a pthread_t parameter.

    +

    Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_equal(3) , +pthread_join(3) , +pthread_detach(3) , +pthread_setschedparam(3) +, pthread_getschedparam(3) +. +

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_setcancelstate.html b/liblo/pthreads.2/manual/pthread_setcancelstate.html new file mode 100644 index 0000000..1dd9ec3 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_setcancelstate.html @@ -0,0 +1,207 @@ + + + + + PTHREAD_CANCEL(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_cancel, pthread_setcancelstate, pthread_setcanceltype, +pthread_testcancel - thread cancellation +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_cancel(pthread_t thread); +

    +

    int pthread_setcancelstate(int state, int +*oldstate); +

    +

    int pthread_setcanceltype(int type, int +*oldtype); +

    +

    void pthread_testcancel(void); +

    +

    Description

    +

    Cancellation is the mechanism by which a thread can terminate the +execution of another thread. More precisely, a thread can send a +cancellation request to another thread. Depending on its settings, +the target thread can then either ignore the request, honor it +immediately, or defer it until it reaches a cancellation point. +

    +

    When a thread eventually honors a cancellation request, it +performs as if pthread_exit(PTHREAD_CANCELED) has been called +at that point: all cleanup handlers are executed in reverse order, +destructor functions for thread-specific data are called, and finally +the thread stops executing with the return value PTHREAD_CANCELED. +See pthread_exit(3) for more +information. +

    +

    pthread_cancel sends a cancellation request to the thread +denoted by the thread argument. +

    +

    pthread_setcancelstate changes the cancellation state for +the calling thread -- that is, whether cancellation requests are +ignored or not. The state argument is the new cancellation +state: either PTHREAD_CANCEL_ENABLE to enable cancellation, or +PTHREAD_CANCEL_DISABLE to disable cancellation (cancellation +requests are ignored). If oldstate is not NULL, the +previous cancellation state is stored in the location pointed to by +oldstate, and can thus be restored later by another call to +pthread_setcancelstate. +

    +

    pthread_setcanceltype changes the type of responses to +cancellation requests for the calling thread: asynchronous +(immediate) or deferred. The type argument is the new +cancellation type: either PTHREAD_CANCEL_ASYNCHRONOUS to +cancel the calling thread as soon as the cancellation request is +received, or PTHREAD_CANCEL_DEFERRED to keep the cancellation +request pending until the next cancellation point. If oldtype +is not NULL, the previous cancellation state is stored in the +location pointed to by oldtype, and can thus be restored later +by another call to pthread_setcanceltype. +

    +

    Pthreads-w32 provides two levels of support for +PTHREAD_CANCEL_ASYNCHRONOUS: full and partial. Full support +requires an additional DLL and driver be installed on the Windows +system (see the See Also section below) that allows blocked threads +to be cancelled immediately. Partial support means that the target +thread will not cancel until it resumes execution naturally. Partial +support is provided if either the DLL or the driver are not +automatically detected by the pthreads-w32 library at run-time.

    +

    Threads are always created by pthread_create(3) +with cancellation enabled and deferred. That is, the initial +cancellation state is PTHREAD_CANCEL_ENABLE and the initial +type is PTHREAD_CANCEL_DEFERRED. +

    +

    Cancellation points are those points in the program execution +where a test for pending cancellation requests is performed and +cancellation is executed if positive. The following POSIX threads +functions are cancellation points: +

    +

    pthread_join(3) +
    pthread_cond_wait(3) +
    pthread_cond_timedwait(3) +
    pthread_testcancel(3) +
    sem_wait(3)
    sem_timedwait(3) +
    sigwait(3) (not supported under +Pthreads-w32)

    +

    Pthreads-w32 provides two functions to enable additional +cancellation points to be created in user functions that block on +Win32 HANDLEs:

    +

    pthreadCancelableWait() +
    pthreadCancelableTimedWait()

    +

    All other POSIX threads functions are guaranteed not to be +cancellation points. That is, they never perform cancellation in +deferred cancellation mode. +

    +

    pthread_testcancel does nothing except testing for pending +cancellation and executing it. Its purpose is to introduce explicit +checks for cancellation in long sequences of code that do not call +cancellation point functions otherwise. +

    +

    Return Value

    +

    pthread_cancel, pthread_setcancelstate and +pthread_setcanceltype return 0 on success and a non-zero error +code on error. +

    +

    Errors

    +

    pthread_cancel returns the following error code on error: +

    +
    +
    +
    ESRCH +
    + no thread could be found corresponding to that specified by the + thread ID. +
    +
    +

    +pthread_setcancelstate returns the following error code on +error: +

    +
    +
    +
    EINVAL +
    + the state argument is not +
    +
    +
    +PTHREAD_CANCEL_ENABLE nor PTHREAD_CANCEL_DISABLE +
    +

    pthread_setcanceltype returns the following error code on +error: +

    +
    +
    +
    EINVAL +
    + the type argument is not +
    +
    +
    +PTHREAD_CANCEL_DEFERRED nor PTHREAD_CANCEL_ASYNCHRONOUS +
    +

    Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_exit(3) , +pthread_cleanup_push(3) +, pthread_cleanup_pop(3) +, Pthreads-w32 package README file 'Prerequisites' section. +

    +

    Bugs

    +

    POSIX specifies that a number of system calls (basically, all +system calls that may block, such as read(2) +, write(2) , wait(2) +, etc.) and library functions that may call these system calls (e.g. +fprintf(3) ) are cancellation +points. Pthreads-win32 is not integrated enough with the C +library to implement this, and thus none of the C library functions +is a cancellation point. +

    +

    A workaround for these calls is to temporarily switch to +asynchronous cancellation (assuming full asynchronous cancellation +support is installed). So, checking for cancellation during a read +system call, for instance, can be achieved as follows: +

    +


    +
    +
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldCancelType);
    +read(fd, buffer, length);
    +pthread_setcanceltype(oldCancelType, NULL);
    +
    +
    Table of Contents
    + + + diff --git a/liblo/pthreads.2/manual/pthread_setcanceltype.html b/liblo/pthreads.2/manual/pthread_setcanceltype.html new file mode 100644 index 0000000..27bb1e3 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_setcanceltype.html @@ -0,0 +1,207 @@ + + + + + PTHREAD_CANCEL(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_cancel, pthread_setcancelstate, pthread_setcanceltype, +pthread_testcancel - thread cancellation +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_cancel(pthread_t thread); +

    +

    int pthread_setcancelstate(int state, int +*oldstate); +

    +

    int pthread_setcanceltype(int type, int +*oldtype); +

    +

    void pthread_testcancel(void); +

    +

    Description

    +

    Cancellation is the mechanism by which a thread can terminate the +execution of another thread. More precisely, a thread can send a +cancellation request to another thread. Depending on its settings, +the target thread can then either ignore the request, honor it +immediately, or defer it until it reaches a cancellation point. +

    +

    When a thread eventually honors a cancellation request, it +performs as if pthread_exit(PTHREAD_CANCELED) has been called +at that point: all cleanup handlers are executed in reverse order, +destructor functions for thread-specific data are called, and finally +the thread stops executing with the return value PTHREAD_CANCELED. +See pthread_exit(3) for more +information. +

    +

    pthread_cancel sends a cancellation request to the thread +denoted by the thread argument. +

    +

    pthread_setcancelstate changes the cancellation state for +the calling thread -- that is, whether cancellation requests are +ignored or not. The state argument is the new cancellation +state: either PTHREAD_CANCEL_ENABLE to enable cancellation, or +PTHREAD_CANCEL_DISABLE to disable cancellation (cancellation +requests are ignored). If oldstate is not NULL, the +previous cancellation state is stored in the location pointed to by +oldstate, and can thus be restored later by another call to +pthread_setcancelstate. +

    +

    pthread_setcanceltype changes the type of responses to +cancellation requests for the calling thread: asynchronous +(immediate) or deferred. The type argument is the new +cancellation type: either PTHREAD_CANCEL_ASYNCHRONOUS to +cancel the calling thread as soon as the cancellation request is +received, or PTHREAD_CANCEL_DEFERRED to keep the cancellation +request pending until the next cancellation point. If oldtype +is not NULL, the previous cancellation state is stored in the +location pointed to by oldtype, and can thus be restored later +by another call to pthread_setcanceltype. +

    +

    Pthreads-w32 provides two levels of support for +PTHREAD_CANCEL_ASYNCHRONOUS: full and partial. Full support +requires an additional DLL and driver be installed on the Windows +system (see the See Also section below) that allows blocked threads +to be cancelled immediately. Partial support means that the target +thread will not cancel until it resumes execution naturally. Partial +support is provided if either the DLL or the driver are not +automatically detected by the pthreads-w32 library at run-time.

    +

    Threads are always created by pthread_create(3) +with cancellation enabled and deferred. That is, the initial +cancellation state is PTHREAD_CANCEL_ENABLE and the initial +type is PTHREAD_CANCEL_DEFERRED. +

    +

    Cancellation points are those points in the program execution +where a test for pending cancellation requests is performed and +cancellation is executed if positive. The following POSIX threads +functions are cancellation points: +

    +

    pthread_join(3) +
    pthread_cond_wait(3) +
    pthread_cond_timedwait(3) +
    pthread_testcancel(3) +
    sem_wait(3)
    sem_timedwait(3) +
    sigwait(3) (not supported under +Pthreads-w32)

    +

    Pthreads-w32 provides two functions to enable additional +cancellation points to be created in user functions that block on +Win32 HANDLEs:

    +

    pthreadCancelableWait() +
    pthreadCancelableTimedWait()

    +

    All other POSIX threads functions are guaranteed not to be +cancellation points. That is, they never perform cancellation in +deferred cancellation mode. +

    +

    pthread_testcancel does nothing except testing for pending +cancellation and executing it. Its purpose is to introduce explicit +checks for cancellation in long sequences of code that do not call +cancellation point functions otherwise. +

    +

    Return Value

    +

    pthread_cancel, pthread_setcancelstate and +pthread_setcanceltype return 0 on success and a non-zero error +code on error. +

    +

    Errors

    +

    pthread_cancel returns the following error code on error: +

    +
    +
    +
    ESRCH +
    + no thread could be found corresponding to that specified by the + thread ID. +
    +
    +

    +pthread_setcancelstate returns the following error code on +error: +

    +
    +
    +
    EINVAL +
    + the state argument is not +
    +
    +
    +PTHREAD_CANCEL_ENABLE nor PTHREAD_CANCEL_DISABLE +
    +

    pthread_setcanceltype returns the following error code on +error: +

    +
    +
    +
    EINVAL +
    + the type argument is not +
    +
    +
    +PTHREAD_CANCEL_DEFERRED nor PTHREAD_CANCEL_ASYNCHRONOUS +
    +

    Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_exit(3) , +pthread_cleanup_push(3) +, pthread_cleanup_pop(3) +, Pthreads-w32 package README file 'Prerequisites' section. +

    +

    Bugs

    +

    POSIX specifies that a number of system calls (basically, all +system calls that may block, such as read(2) +, write(2) , wait(2) +, etc.) and library functions that may call these system calls (e.g. +fprintf(3) ) are cancellation +points. Pthreads-win32 is not integrated enough with the C +library to implement this, and thus none of the C library functions +is a cancellation point. +

    +

    A workaround for these calls is to temporarily switch to +asynchronous cancellation (assuming full asynchronous cancellation +support is installed). So, checking for cancellation during a read +system call, for instance, can be achieved as follows: +

    +


    +
    +
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldCancelType);
    +read(fd, buffer, length);
    +pthread_setcanceltype(oldCancelType, NULL);
    +
    +
    Table of Contents
    + + + diff --git a/liblo/pthreads.2/manual/pthread_setconcurrency.html b/liblo/pthreads.2/manual/pthread_setconcurrency.html new file mode 100644 index 0000000..f3f598f --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_setconcurrency.html @@ -0,0 +1,155 @@ + + + + + "PTHREAD_GETCONCURRENCY"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_getconcurrency, pthread_setconcurrency - get and set the +level of concurrency +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_getconcurrency(void);
    int +pthread_setconcurrency(int new_level); +

    +

    Description

    +

    Unbound threads in a process may or may not be required to be +simultaneously active. By default, the threads implementation ensures +that a sufficient number of threads are active so that the process +can continue to make progress. While this conserves system resources, +it may not produce the most effective level of concurrency. +

    +

    The pthread_setconcurrency function allows an application +to inform the threads implementation of its desired concurrency +level, new_level. The actual level of concurrency provided by +the implementation as a result of this function call is unspecified. +

    +

    If new_level is zero, it causes the implementation to +maintain the concurrency level at its discretion as if +pthread_setconcurrency had never been called. +

    +

    The pthread_getconcurrency function shall return the value +set by a previous call to the pthread_setconcurrency function. +If the pthread_setconcurrency function was not previously +called, this function shall return zero to indicate that the +implementation is maintaining the concurrency level. +

    +

    A call to pthread_setconcurrency shall inform the +implementation of its desired concurrency level. The implementation +shall use this as a hint, not a requirement. +

    +

    If an implementation does not support multiplexing of user threads +on top of several kernel-scheduled entities, the +pthread_setconcurrency and pthread_getconcurrency +functions are provided for source code compatibility but they shall +have no effect when called. To maintain the function semantics, the +new_level parameter is saved when pthread_setconcurrency +is called so that a subsequent call to pthread_getconcurrency +shall return the same value. +

    +

    Pthreads-w32 provides these routines for source code +compatibility only, as described in the previous paragraph.

    +

    Return Value

    +

    If successful, the pthread_setconcurrency function shall +return zero; otherwise, an error number shall be returned to indicate +the error. +

    +

    The pthread_getconcurrency function shall always return the +concurrency level set by a previous call to pthread_setconcurrency +. If the pthread_setconcurrency function has never been +called, pthread_getconcurrency shall return zero. +

    +

    Errors

    +

    The pthread_setconcurrency function shall fail if: +

    +
    +
    EINVAL +
    + The value specified by new_level is negative. +
    + EAGAIN +
    + The value specific by new_level would cause a system resource + to be exceeded. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Use of these functions changes the state of the underlying +concurrency upon which the application depends. Library developers +are advised to not use the pthread_getconcurrency and +pthread_setconcurrency functions since their use may conflict +with an applications use of these functions. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    The Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_setschedparam.html b/liblo/pthreads.2/manual/pthread_setschedparam.html new file mode 100644 index 0000000..8337ce2 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_setschedparam.html @@ -0,0 +1,113 @@ + + + + + PTHREAD_SETSCHEDPARAM(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_setschedparam, pthread_getschedparam - control thread +scheduling +

    +

    parameters +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_setschedparam(pthread_t target_thread, +int policy, const struct sched_param *param); +

    +

    int pthread_getschedparam(pthread_t target_thread, +int *policy, struct sched_param *param); +

    +

    Description

    +

    pthread_setschedparam sets the scheduling parameters for +the thread target_thread as indicated by policy and +param. policy can be either SCHED_OTHER +(regular, non-real-time scheduling), SCHED_RR (real-time, +round-robin) or SCHED_FIFO (real-time, first-in first-out). +param specifies the scheduling priority for the two real-time +policies.

    +

    Pthreads-w32 only supports SCHED_OTHER and does not support +the real-time scheduling policies SCHED_RR and SCHED_FIFO. +

    +

    pthread_getschedparam retrieves the scheduling policy and +scheduling parameters for the thread target_thread and stores +them in the locations pointed to by policy and param, +respectively. +

    +

    Return Value

    +

    pthread_setschedparam and pthread_getschedparam +return 0 on success and a non-zero error code on error. +

    +

    Errors

    +

    On error, pthread_setschedparam returns the following error +codes: +

    +
    +
    +
    ENOTSUP +
    + policy is not SCHED_OTHER.
    + EINVAL +
    + One of the arguments is invalid, or the priority value specified by + param is not valid for the specified policy.
    + ESRCH +
    + The target_thread is invalid or has already terminated +
    +
    +

    +On error, pthread_getschedparam returns the following error +codes: +

    +
    +
    +
    ESRCH +
    + the target_thread is invalid or has already terminated +
    +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    sched_setscheduler(2) +, sched_getscheduler(2) +, sched_getparam(2) , +pthread_attr_setschedpolicy(3) +, pthread_attr_setschedparam(3) +. +

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/pthread_spin_init.html b/liblo/pthreads.2/manual/pthread_spin_init.html new file mode 100644 index 0000000..dbf21d5 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_spin_init.html @@ -0,0 +1,176 @@ + + + + + "PTHREAD_SPIN_DESTROY"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_spin_destroy, pthread_spin_init - destroy or initialize a +spin lock object (ADVANCED REALTIME THREADS) +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    pthread_spinlock_t lock = +PTHREAD_SPINLOCK_INITIALIZER;

    +

    int pthread_spin_destroy(pthread_spinlock_t *lock); +
    int pthread_spin_init(pthread_spinlock_t *
    lock, int +pshared); +

    +

    Description

    +

    The pthread_spin_destroy function shall destroy the spin +lock referenced by lock and release any resources used by the +lock. The effect of subsequent use of the lock is undefined until the +lock is reinitialized by another call to pthread_spin_init . +The results are undefined if pthread_spin_destroy is called +when a thread holds the lock, or if this function is called with an +uninitialized thread spin lock. +

    +

    The pthread_spin_init function shall allocate any resources +required to use the spin lock referenced by lock and +initialize the lock to an unlocked state. +

    +

    Pthreads-w32 supports single and multiple processor systems +as well as process CPU affinity masking by checking the mask when the +spin lock is initialized. If the process is using only a single +processor at the time pthread_spin_init is called then the +spin lock is initialized as a PTHREAD_MUTEX_NORMAL mutex object. A +thread that calls pthread_spin_lock(3) +will block rather than spin in this case. If the process CPU affinity +mask is altered after the spin lock has been initialised, the spin +lock is not modified, and may no longer be optimal for the number of +CPUs available.

    +

    Pthreads-w32 defines _POSIX_THREAD_PROCESS_SHARED in +pthread.h as -1 to indicate that these routines do not support the +PTHREAD_PROCESS_SHARED attribute. pthread_spin_init +will return the error ENOTSUP if the value of pshared +is not PTHREAD_PROCESS_PRIVATE.

    +

    The results are undefined if pthread_spin_init is called +specifying an already initialized spin lock. The results are +undefined if a spin lock is used without first being initialized. +

    +

    If the pthread_spin_init function fails, the lock is not +initialized and the contents of lock are undefined. +

    +

    Only the object referenced by lock may be used for +performing synchronization. +

    +

    The result of referring to copies of that object in calls to +pthread_spin_destroy , pthread_spin_lock(3) +, pthread_spin_trylock(3), +or pthread_spin_unlock(3) +is undefined. +

    +

    Pthreads-w32 supports statically initialized spin locks +using PTHREAD_SPINLOCK_INITIALIZER. An application should +still call pthread_spin_destroy at some point to ensure that +any resources consumed by the spin lock are released.

    +

    Return Value

    +

    Upon successful completion, these functions shall return zero; +otherwise, an error number shall be returned to indicate the error. +

    +

    Errors

    +

    These functions may fail if: +

    +
    +
    EBUSY +
    + The implementation has detected an attempt to initialize or destroy + a spin lock while it is in use (for example, while being used in a + pthread_spin_lock(3) + call) by another thread. +
    + EINVAL +
    + The value specified by lock is invalid. +
    +

    +The pthread_spin_init function shall fail if: +

    +
    +
    ENOTSUP +
    + The value of pshared is not PTHREAD_PROCESS_PRIVATE.
    + ENOMEM +
    + Insufficient memory exists to initialize the lock. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    The pthread_spin_destroy and pthread_spin_init +functions are part of the Spin Locks option and need not be provided +on all implementations. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_spin_lock(3) , +pthread_spin_unlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_spin_lock.html b/liblo/pthreads.2/manual/pthread_spin_lock.html new file mode 100644 index 0000000..398d2e4 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_spin_lock.html @@ -0,0 +1,141 @@ + + + + + "PTHREAD_SPIN_LOCK"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_spin_lock, pthread_spin_trylock - lock a spin lock object +(ADVANCED REALTIME THREADS) +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_spin_lock(pthread_spinlock_t *lock); +
    int pthread_spin_trylock(pthread_spinlock_t *
    lock); + +

    +

    Description

    +

    The pthread_spin_lock function shall lock the spin lock +referenced by lock. The calling thread shall acquire the lock +if it is not held by another thread. Otherwise, the thread shall spin +(that is, shall not return from the pthread_spin_lock call) +until the lock becomes available. The results are undefined if the +calling thread holds the lock at the time the call is made.

    +

    Pthreads-w32 supports single and multiple processor systems +as well as process CPU affinity masking by checking the mask when the +spin lock is initialized. If the process is using only a single +processor at the time pthread_spin_init(3) +is called then the spin lock is initialized as a PTHREAD_MUTEX_NORMAL +mutex object. A thread that calls pthread_spin_lock will block +rather than spin in this case. If the process CPU affinity mask is +altered after the spin lock has been initialised, the spin lock is +not modified, and may no longer be optimal for the number of CPUs +available.

    +

    The pthread_spin_trylock function shall lock the spin lock +referenced by lock if it is not held by any thread. Otherwise, +the function shall fail. +

    +

    The results are undefined if any of these functions is called with +an uninitialized spin lock. +

    +

    Return Value

    +

    Upon successful completion, these functions shall return zero; +otherwise, an error number shall be returned to indicate the error. +

    +

    Errors

    +

    These functions may fail if: +

    +
    +
    EINVAL +
    + The value specified by lock does not refer to an initialized + spin lock object. +
    +

    +The pthread_spin_trylock function shall fail if: +

    +
    +
    EBUSY +
    + A thread currently holds the lock. +
    +

    +These functions shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Applications using this function may be subject to priority +inversion, as discussed in the Base Definitions volume of +IEEE Std 1003.1-2001, Section 3.285, Priority Inversion. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_spin_destroy(3) +, pthread_spin_unlock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_spin_unlock.html b/liblo/pthreads.2/manual/pthread_spin_unlock.html new file mode 100644 index 0000000..cf8c4b1 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_spin_unlock.html @@ -0,0 +1,124 @@ + + + + + "PTHREAD_SPIN_UNLOCK"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_spin_unlock - unlock a spin lock object (ADVANCED +REALTIME THREADS) +

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    int pthread_spin_unlock(pthread_spinlock_t *lock); + +

    +

    Description

    +

    The pthread_spin_unlock function shall release the spin +lock referenced by lock which was locked via the +pthread_spin_lock(3) or +pthread_spin_trylock(3) +functions. If there are threads spinning on the lock when +pthread_spin_unlock is called, the lock becomes available and +an unspecified spinning thread shall acquire the lock. +

    +

    Pthreads-w32 does not check ownership of the lock and it is +therefore possible for a thread other than the locker to unlock the +spin lock. This is not a feature that should be exploited.

    +

    The results are undefined if this function is called with an +uninitialized thread spin lock. +

    +

    Return Value

    +

    Upon successful completion, the pthread_spin_unlock +function shall return zero; otherwise, an error number shall be +returned to indicate the error. +

    +

    Errors

    +

    The pthread_spin_unlock function may fail if: +

    +
    +
    EINVAL +
    + An invalid argument was specified. +
    +
    +
    +

    +This function shall not return an error code of [EINTR]. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    Pthreads-w32 does not check ownership of the lock and it is +therefore possible for a thread other than the locker to unlock the +spin lock. This is not a feature that should be exploited.

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    pthread_spin_destroy(3) +, pthread_spin_lock(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<pthread.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_timechange_handler_np.html b/liblo/pthreads.2/manual/pthread_timechange_handler_np.html new file mode 100644 index 0000000..2f9fc5d --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_timechange_handler_np.html @@ -0,0 +1,76 @@ + + + + + PTHREAD_TIMECHANGE_HANDLER_NP manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_timechange_handler_np – +alert timed waiting condition variables to system time changes.

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    void * pthread_timechange_handler_np(void * dummy);

    +

    Description

    +

    To improve tolerance against operator or time service initiated +system clock changes.

    +

    pthread_timechange_handler_np can be called by an +application when it receives a WM_TIMECHANGE message from the system. +At present it broadcasts all condition variables so that waiting +threads can wake up and re-evaluate their conditions and restart +their timed waits if required.

    +

    pthread_timechange_handler_np has the same return type and +argument type as a thread routine so that it may be called directly +through pthread_create(), i.e. as a separate thread. If run as a +thread, the return code must be retrieved through pthread_join().

    +

    Although the dummy parameter is required it is not used and +any value including NULL can be given.

    +

    Cancellation

    +

    None.

    +

    Return Value

    +

    pthread_timechange_handler_np returns 0 on success, or an +error code.

    +

    Errors

    +

    The pthread_timechange_handler_np function returns the +following error code on error: +

    +
    +
    +
    EAGAIN +
    +
    +

    +To indicate that not all condition variables were signalled for some +reason.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_win32_attach_detach_np.html b/liblo/pthreads.2/manual/pthread_win32_attach_detach_np.html new file mode 100644 index 0000000..1fb4a50 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_win32_attach_detach_np.html @@ -0,0 +1,74 @@ + + + + + PTHREAD_WIN32_ATTACH_DETACH_NP manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_win32_process_attach_np, +pthread_win32_process_detach_np, pthread_win32_thread_attach_np, +pthread_win32_thread_detach_np – exposed versions of the +pthreads-w32 DLL dllMain() switch functionality for use when +statically linking the library.

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    BOOL pthread_win32_process_attach_np (void);

    +

    BOOL pthread_win32_process_detach_np (void);

    +

    BOOL pthread_win32_thread_attach_np (void);

    +

    BOOL pthread_win32_thread_detach_np (void);

    +

    Description

    +

    These functions contain the code normally run via dllMain +when the library is used as a dll but which need to be called +explicitly by an application when the library is statically linked.

    +

    You will need to call pthread_win32_process_attach_np +before you can call any pthread routines when statically linking. You +should call pthread_win32_process_detach_np before exiting +your application to clean up.

    +

    pthread_win32_thread_attach_np is currently a no-op, but +pthread_win32_thread_detach_np is needed to clean up the +implicit pthread handle that is allocated to a Win32 thread if it +calls certain pthreads routines. Call this routine when the Win32 +thread exits.

    +

    These functions invariably return TRUE except for +pthread_win32_process_attach_np which will return FALSE if +pthreads-w32 initialisation fails.

    +

    Cancellation

    +

    None.

    +

    Return Value

    +

    These routines return TRUE (non-zero) on success, or FALSE (0) if +they fail.

    +

    Errors

    +

    None.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/pthread_win32_test_features_np.html b/liblo/pthreads.2/manual/pthread_win32_test_features_np.html new file mode 100644 index 0000000..7e6c665 --- /dev/null +++ b/liblo/pthreads.2/manual/pthread_win32_test_features_np.html @@ -0,0 +1,68 @@ + + + + + PTHREAD_WIN32_TEST_FEATURES_NP manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    pthread_win32_test_features_np – +find out what features were detected at process attach time.

    +

    Synopsis

    +

    #include <pthread.h> +

    +

    BOOL pthread_win32_test_features_np(int mask);

    +

    Description

    +

    pthread_win32_test_features_np allows an application to +check which run-time auto-detected features are available within the +library.

    +

    The possible features are:

    +

    PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE

    +

    Return TRUE if the Win32 version of +InterlockedCompareExchange() is being used. On IA32 systems the +library can use optimised and inlinable assembler versions of +InterlockedExchange() and InterlockedCompareExchange().

    +

    PTW32_ALERTABLE_ASYNC_CANCEL

    +

    Return TRUE if the QueueUserAPCEx package +QUSEREX.DLL and the AlertDrv.sys driver was detected. This package +provides alertable (pre-emptive) asynchronous threads cancellation. +If this feature returns FALSE then the default async cancel scheme is +in use, which cannot cancel blocked threads.

    +

    Cancellation

    +

    None.

    +

    Return Value

    +

    pthread_win32_test_features_np returns TRUE (non-zero) if +the specified feature is present, and FALSE (0) otherwise.

    +

    Errors

    +

    None.

    +

    Author

    +

    Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/sched_get_priority_max.html b/liblo/pthreads.2/manual/sched_get_priority_max.html new file mode 100644 index 0000000..f79f59b --- /dev/null +++ b/liblo/pthreads.2/manual/sched_get_priority_max.html @@ -0,0 +1,115 @@ + + + + + "SCHED_GET_PRIORITY_MAX"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    sched_get_priority_max, sched_get_priority_min - get priority +limits (REALTIME) +

    +

    Synopsis

    +

    #include <sched.h> +

    +

    int sched_get_priority_max(int policy);
    int +sched_get_priority_min(int
    policy); +

    +

    Description

    +

    The sched_get_priority_max and sched_get_priority_min +functions shall return the appropriate maximum or minimum, +respectively, for the scheduling policy specified by policy. +

    +

    The value of policy shall be one of the scheduling policy +values defined in <sched.h>. +

    +

    Return Value

    +

    If successful, the sched_get_priority_max and +sched_get_priority_min functions shall return the appropriate +maximum or minimum values, respectively. If unsuccessful, they shall +return a value of -1 and set errno to indicate the error. +

    +

    Errors

    +

    The sched_get_priority_max and sched_get_priority_min +functions shall fail if: +

    +
    +
    EINVAL +
    + The value of the policy parameter does not represent a + defined scheduling policy. +
    +

    +The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    sched_getscheduler(3) +, sched_setscheduler(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<sched.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/manual/sched_getscheduler.html b/liblo/pthreads.2/manual/sched_getscheduler.html new file mode 100644 index 0000000..dd1d964 --- /dev/null +++ b/liblo/pthreads.2/manual/sched_getscheduler.html @@ -0,0 +1,127 @@ + + + + + "SCHED_GETSCHEDULER"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    sched_getscheduler - get scheduling policy (REALTIME) +

    +

    Synopsis

    +

    #include <sched.h> +

    +

    int sched_getscheduler(pid_t pid); +

    +

    Description

    +

    The sched_getscheduler function shall return the scheduling +policy of the process specified by pid. If the value of pid +is negative, the behavior of the sched_getscheduler function +is unspecified. +

    +

    The values that can be returned by sched_getscheduler are +defined in the <sched.h> header. +

    +

    Pthreads-w32 only supports the SCHED_OTHER policy, +which is the only value that can be returned. However, checks on pid +and permissions are performed first so that the other useful side +effects of this routine are retained.

    +

    If a process specified by pid exists, and if the calling +process has permission, the scheduling policy shall be returned for +the process whose process ID is equal to pid. +

    +

    If pid is zero, the scheduling policy shall be returned for +the calling process. +

    +

    Return Value

    +

    Upon successful completion, the sched_getscheduler function +shall return the scheduling policy of the specified process. If +unsuccessful, the function shall return -1 and set errno to +indicate the error. +

    +

    Errors

    +

    The sched_getscheduler function shall fail if: +

    +
    +
    EPERM +
    + The requesting process does not have permission to determine the + scheduling policy of the specified process. +
    + ESRCH +
    + No process can be found corresponding to that specified by pid. +
    +

    +The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    sched_setscheduler(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<sched.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/sched_setscheduler.html b/liblo/pthreads.2/manual/sched_setscheduler.html new file mode 100644 index 0000000..206508d --- /dev/null +++ b/liblo/pthreads.2/manual/sched_setscheduler.html @@ -0,0 +1,181 @@ + + + + + "SCHED_SETSCHEDULER"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    sched_setscheduler - set scheduling policy and parameters +(REALTIME) +

    +

    Synopsis

    +

    #include <sched.h> +

    +

    int sched_setscheduler(pid_t pid, int policy, +const struct sched_param *param); +

    +

    Description

    +

    The sched_setscheduler function shall set the scheduling +policy and scheduling parameters of the process specified by pid +to policy and the parameters specified in the sched_param +structure pointed to by param, respectively. The value of the +sched_priority member in the sched_param structure +shall be any integer within the inclusive priority range for the +scheduling policy specified by policy. If the value of pid +is negative, the behavior of the sched_setscheduler function +is unspecified. +

    +

    The possible values for the policy parameter are defined in +the <sched.h> header. +

    +

    Pthreads-w32 only supports the SCHED_OTHER policy. +Any other value for policy will return failure with errno set +to ENOSYS. However, checks on pid and permissions are +performed first so that the other useful side effects of this routine +are retained.

    +

    If a process specified by pid exists, and if the calling +process has permission, the scheduling policy and scheduling +parameters shall be set for the process whose process ID is equal to +pid. +

    +

    If pid is zero, the scheduling policy and scheduling +parameters shall be set for the calling process. +

    +

    Implementations may require that the requesting process have +permission to set its own scheduling parameters or those of another +process. Additionally, implementation-defined restrictions may apply +as to the appropriate privileges required to set a process’ own +scheduling policy, or another process’ scheduling policy, to a +particular value. +

    +

    The sched_setscheduler function shall be considered +successful if it succeeds in setting the scheduling policy and +scheduling parameters of the process specified by pid to the +values specified by policy and the structure pointed to by +param, respectively. +

    +

    The effect of this function on individual threads is dependent on +the scheduling contention scope of the threads: +

    +
    +
    * +
    + For threads with system scheduling contention scope, these functions + shall have no effect on their scheduling. +
    + * +
    + For threads with process scheduling contention scope, the threads’ + scheduling policy and associated parameters shall not be affected. + However, the scheduling of these threads with respect to threads in + other processes may be dependent on the scheduling parameters of + their process, which are governed using these functions. +
    +

    +This function is not atomic with respect to other threads in the +process. Threads may continue to execute while this function call is +in the process of changing the scheduling policy and associated +scheduling parameters for the underlying kernel-scheduled entities +used by the process contention scope threads. +

    +

    Return Value

    +

    Upon successful completion, the function shall return the former +scheduling policy of the specified process. If the sched_setscheduler +function fails to complete successfully, the policy and scheduling +parameters shall remain unchanged, and the function shall return a +value of -1 and set errno to indicate the error. +

    +

    Errors

    +

    The sched_setscheduler function shall fail if: +

    +
    +
    EINVAL +
    + The value of the policy parameter is invalid, or one or more + of the parameters contained in param is outside the valid + range for the specified scheduling policy. +
    + EPERM +
    + The requesting process does not have permission to set either or + both of the scheduling parameters or the scheduling policy of the + specified process. +
    + ESRCH +
    + No process can be found corresponding to that specified by pid. +
    +

    +The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    sched_getscheduler(3) +, the Base Definitions volume of IEEE Std 1003.1-2001, +<sched.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/sched_yield.html b/liblo/pthreads.2/manual/sched_yield.html new file mode 100644 index 0000000..1691afb --- /dev/null +++ b/liblo/pthreads.2/manual/sched_yield.html @@ -0,0 +1,98 @@ + + + + + "SCHED_YIELD"(P) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    sched_yield - yield the processor +

    +

    Synopsis

    +

    #include <sched.h> +

    +

    int sched_yield(void); +

    +

    Description

    +

    The sched_yield function shall force the running thread to +relinquish the processor until it again becomes the head of its +thread list. It takes no arguments. +

    +

    Return Value

    +

    The sched_yield function shall return 0 if it completes +successfully; otherwise, it shall return a value of -1 and set errno +to indicate the error. +

    +

    Errors

    +

    No errors are defined. +

    +

    The following sections are informative. +

    +

    Examples

    +

    None. +

    +

    Application Usage

    +

    None. +

    +

    Rationale

    +

    None. +

    +

    Future Directions

    +

    None. +

    +

    See Also

    +

    The Base Definitions volume of IEEE Std 1003.1-2001, +<sched.h> +

    +

    Copyright

    +

    Portions of this text are reprinted and reproduced in electronic +form from IEEE Std 1003.1, 2003 Edition, Standard for Information +Technology -- Portable Operating System Interface (POSIX), The Open +Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the +Institute of Electrical and Electronics Engineers, Inc and The Open +Group. In the event of any discrepancy between this version and the +original IEEE and The Open Group Standard, the original IEEE and The +Open Group Standard is the referee document. The original Standard +can be obtained online at http://www.opengroup.org/unix/online.html +. +

    +
    +

    Table of Contents

    + + + diff --git a/liblo/pthreads.2/manual/sem_init.html b/liblo/pthreads.2/manual/sem_init.html new file mode 100644 index 0000000..338867e --- /dev/null +++ b/liblo/pthreads.2/manual/sem_init.html @@ -0,0 +1,200 @@ + + + + + SEMAPHORES(3) manual page + + + + + + + +

    POSIX Threads for Windows – REFERENCE - Pthreads-w32

    +

    Reference Index

    +

    Table of Contents

    +

    Name

    +

    sem_init, sem_wait, sem_trywait, sem_post, sem_getvalue, +sem_destroy - operations on semaphores +

    +

    Synopsis

    +

    #include <semaphore.h> +

    +

    int sem_init(sem_t *sem, int pshared, +unsigned int value); +

    +

    int sem_wait(sem_t * sem); +

    +

    int sem_timedwait(sem_t * sem, const struct +timespec *abstime); +

    +

    int sem_trywait(sem_t * sem); +

    +

    int sem_post(sem_t * sem); +

    +

    int sem_post_multiple(sem_t * sem, int +number); +

    +

    int sem_getvalue(sem_t * sem, int * sval); +

    +

    int sem_destroy(sem_t * sem); +

    +

    Description

    +

    Semaphores are counters for resources shared between threads. The +basic operations on semaphores are: increment the counter atomically, +and wait until the counter is non-null and decrement it atomically. +

    +

    sem_init initializes the semaphore object pointed to by +sem. The count associated with the semaphore is set initially +to value. The pshared argument indicates whether the +semaphore is local to the current process ( pshared is zero) +or is to be shared between several processes ( pshared is not +zero).

    +

    Pthreads-w32 currently does not support process-shared +semaphores, thus sem_init always returns with error EPERM +if pshared is not zero. +

    +

    sem_wait atomically decrements sem's count if it is +greater than 0 and returns immediately or it suspends the calling +thread until it can resume following a call to sem_post or +sem_post_multiple.

    +

    sem_timedwait atomically decrements sem's count if +it is greater than 0 and returns immediately, or it suspends the +calling thread. If abstime time arrives before the thread can +resume following a call to sem_post or sem_post_multiple, +then sem_timedwait returns with a return code of -1 after +having set errno to ETIMEDOUT. If the call can return +without suspending then abstime is not checked.

    +

    sem_trywait atomically decrements sem's count if it +is greater than 0 and returns immediately, or it returns immediately +with a return code of -1 after having set errno to EAGAIN. +sem_trywait never blocks.

    +

    sem_post either releases one thread if there are any +waiting on sem, or it atomically increments sem's +count.

    +

    sem_post_multiple either releases multiple threads if there +are any waiting on sem and/or it atomically increases sem's +count. If there are currently n waiters, where n the +largest number less than or equal to number, then n +waiters are released and sem's count is incremented by number +minus n.

    +

    sem_getvalue stores in the location pointed to by sval +the current count of the semaphore sem. In the Pthreads-w32 +implementation: if the value returned in sval is greater than +or equal to 0 it was the sem's count at some point during the +call to sem_getvalue. If the value returned in sval is +less than 0 then it's absolute value represents the number of threads +waiting on sem at some point during the call to sem_getvalue. +POSIX does not require an implementation of sem_getvalue +to return a value in sval that is less than 0, but if it does +then it's absolute value must represent the number of waiters.

    +

    sem_destroy destroys a semaphore object, freeing the +resources it might hold. No threads should be waiting on the +semaphore at the time sem_destroy is called.

    +

    Cancellation

    +

    sem_wait and sem_timedwait are cancellation points. +

    +

    Async-signal Safety

    +

    These routines are not async-cancel safe.

    +

    Return Value

    +

    All semaphore functions return 0 on success, or -1 on error in +which case they write an error code in errno. +

    +

    Errors

    +

    The sem_init function sets errno to the following +codes on error: +

    +
    +
    +
    EINVAL +
    + value exceeds the maximal counter value SEM_VALUE_MAX +
    + ENOSYS +
    +
    +
    +pshared is not zero +
    +

    The sem_timedwait function sets errno to the +following error code on error: +

    +
    +
    +
    ETIMEDOUT +
    +
    +
    +if abstime arrives before the waiting thread can resume +following a call to sem_post or sem_post_multiple. +
    +

    The sem_trywait function sets errno to the following +error code on error: +

    +
    +
    +
    EAGAIN +
    +
    +
    +if the semaphore count is currently 0 +
    +

    The sem_post and sem_post_multiple functions set +errno to the following error code on error: +

    +
    +
    +
    ERANGE +
    + if after incrementing, the semaphore count would exceed + SEM_VALUE_MAX (the semaphore count is left unchanged in this + case) +
    +
    +

    +The sem_destroy function sets errno to the following +error code on error: +

    +
    +
    +
    EBUSY +
    + if some threads are currently blocked waiting on the semaphore. +
    +
    +

    +Author

    +

    Xavier Leroy <Xavier.Leroy@inria.fr> +

    +

    Modified by Ross Johnson for use with Pthreads-w32.

    +

    See Also

    +

    pthread_mutex_init(3) +, pthread_cond_init(3) , +pthread_cancel(3) . +

    +
    +

    Table of Contents

    + + + \ No newline at end of file diff --git a/liblo/pthreads.2/misc.c b/liblo/pthreads.2/misc.c new file mode 100644 index 0000000..5853569 --- /dev/null +++ b/liblo/pthreads.2/misc.c @@ -0,0 +1,50 @@ +/* + * misc.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#include "pthread_kill.c" +#include "pthread_once.c" +#include "pthread_self.c" +#include "pthread_equal.c" +#include "pthread_setconcurrency.c" +#include "pthread_getconcurrency.c" +#include "ptw32_new.c" +#include "ptw32_calloc.c" +#include "ptw32_reuse.c" +#include "w32_CancelableWait.c" diff --git a/liblo/pthreads.2/mt.dep b/liblo/pthreads.2/mt.dep new file mode 100644 index 0000000..1d179c0 --- /dev/null +++ b/liblo/pthreads.2/mt.dep @@ -0,0 +1 @@ +Manifest resource last updated at 23:57:51.50 on Sun 10/25/2009 diff --git a/liblo/pthreads.2/mutex.c b/liblo/pthreads.2/mutex.c new file mode 100644 index 0000000..c199901 --- /dev/null +++ b/liblo/pthreads.2/mutex.c @@ -0,0 +1,59 @@ +/* + * mutex.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef _UWIN +# include +#endif +#ifndef NEED_FTIME +#include +#endif +#include "pthread.h" +#include "implement.h" + + +#include "ptw32_mutex_check_need_init.c" +#include "pthread_mutex_init.c" +#include "pthread_mutex_destroy.c" +#include "pthread_mutexattr_init.c" +#include "pthread_mutexattr_destroy.c" +#include "pthread_mutexattr_getpshared.c" +#include "pthread_mutexattr_setpshared.c" +#include "pthread_mutexattr_settype.c" +#include "pthread_mutexattr_gettype.c" +#include "pthread_mutex_lock.c" +#include "pthread_mutex_timedlock.c" +#include "pthread_mutex_unlock.c" +#include "pthread_mutex_trylock.c" diff --git a/liblo/pthreads.2/need_errno.h b/liblo/pthreads.2/need_errno.h new file mode 100644 index 0000000..d523135 --- /dev/null +++ b/liblo/pthreads.2/need_errno.h @@ -0,0 +1,132 @@ +/*** +* errno.h - system wide error numbers (set by system calls) +* +* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved. +* +* Purpose: +* This file defines the system-wide error numbers (set by +* system calls). Conforms to the XENIX standard. Extended +* for compatibility with Uniforum standard. +* [System V] +* +* [Public] +* +****/ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#ifndef _INC_ERRNO +#define _INC_ERRNO + +#if !defined(_WIN32) && !defined(_MAC) +#error ERROR: Only Mac or Win32 targets supported! +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* Define _CRTIMP */ + +#ifndef _CRTIMP +#ifdef _DLL +#define _CRTIMP __declspec(dllimport) +#else /* ndef _DLL */ +#define _CRTIMP +#endif /* _DLL */ +#endif /* _CRTIMP */ + + +/* Define __cdecl for non-Microsoft compilers */ + +#if ( !defined(_MSC_VER) && !defined(__cdecl) ) +#define __cdecl +#endif + +/* Define _CRTAPI1 (for compatibility with the NT SDK) */ + +#ifndef _CRTAPI1 +#if _MSC_VER >= 800 && _M_IX86 >= 300 +#define _CRTAPI1 __cdecl +#else +#define _CRTAPI1 +#endif +#endif + + +/* declare reference to errno */ + +#if (defined(_MT) || defined(_MD) || defined(_DLL)) && !defined(_MAC) +_CRTIMP extern int * __cdecl _errno(void); +#define errno (*_errno()) +#else /* ndef _MT && ndef _MD && ndef _DLL */ +_CRTIMP extern int errno; +#endif /* _MT || _MD || _DLL */ + +/* Error Codes */ + +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EDEADLK 36 + +/* defined differently in winsock.h on WinCE */ +#ifndef ENAMETOOLONG +#define ENAMETOOLONG 38 +#endif + +#define ENOLCK 39 +#define ENOSYS 40 + +/* defined differently in winsock.h on WinCE */ +#ifndef ENOTEMPTY +#define ENOTEMPTY 41 +#endif + +#define EILSEQ 42 + +/* + * Support EDEADLOCK for compatibiity with older MS-C versions. + */ +#define EDEADLOCK EDEADLK + +#ifdef __cplusplus +} +#endif + +#endif /* _INC_ERRNO */ diff --git a/liblo/pthreads.2/nonportable.c b/liblo/pthreads.2/nonportable.c new file mode 100644 index 0000000..d1b0976 --- /dev/null +++ b/liblo/pthreads.2/nonportable.c @@ -0,0 +1,46 @@ +/* + * nonportable.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +#include "pthread_mutexattr_setkind_np.c" +#include "pthread_mutexattr_getkind_np.c" +#include "pthread_getw32threadhandle_np.c" +#include "pthread_delay_np.c" +#include "pthread_num_processors_np.c" +#include "pthread_win32_attach_detach_np.c" +#include "pthread_timechange_handler_np.c" diff --git a/liblo/pthreads.2/private.c b/liblo/pthreads.2/private.c new file mode 100644 index 0000000..3755ef4 --- /dev/null +++ b/liblo/pthreads.2/private.c @@ -0,0 +1,57 @@ +/* + * private.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* Must be first to define HAVE_INLINABLE_INTERLOCKED_CMPXCHG */ +#include "ptw32_InterlockedCompareExchange.c" + +#include "ptw32_MCS_lock.c" +#include "ptw32_is_attr.c" +#include "ptw32_processInitialize.c" +#include "ptw32_processTerminate.c" +#include "ptw32_threadStart.c" +#include "ptw32_threadDestroy.c" +#include "ptw32_tkAssocCreate.c" +#include "ptw32_tkAssocDestroy.c" +#include "ptw32_callUserDestroyRoutines.c" +#include "ptw32_semwait.c" +#include "ptw32_timespec.c" +#include "ptw32_relmillisecs.c" +#include "ptw32_throw.c" +#include "ptw32_getprocessors.c" diff --git a/liblo/pthreads.2/pthread.c b/liblo/pthreads.2/pthread.c new file mode 100644 index 0000000..afcbba5 --- /dev/null +++ b/liblo/pthreads.2/pthread.c @@ -0,0 +1,65 @@ +/* + * pthread.c + * + * Description: + * This translation unit agregates pthreads-win32 translation units. + * It is used for inline optimisation of the library, + * maximising for speed at the expense of size. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* The following are ordered for inlining */ + +#include "private.c" +#include "attr.c" +#include "barrier.c" +#include "cancel.c" +#include "cleanup.c" +#include "condvar.c" +#include "create.c" +#include "dll.c" +#include "errno.c" +#include "exit.c" +#include "fork.c" +#include "global.c" +#include "misc.c" +#include "mutex.c" +#include "nonportable.c" +#include "rwlock.c" +#include "sched.c" +#include "semaphore.c" +#include "signal.c" +#include "spin.c" +#include "sync.c" +#include "tsd.c" diff --git a/liblo/pthreads.2/pthread.h b/liblo/pthreads.2/pthread.h new file mode 100644 index 0000000..9f2868b --- /dev/null +++ b/liblo/pthreads.2/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,8,0,0 +#define PTW32_VERSION_STRING "2, 8, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/liblo/pthreads.2/pthread.suo b/liblo/pthreads.2/pthread.suo new file mode 100644 index 0000000..73edf9c Binary files /dev/null and b/liblo/pthreads.2/pthread.suo differ diff --git a/liblo/pthreads.2/pthread.vcproj b/liblo/pthreads.2/pthread.vcproj new file mode 100644 index 0000000..fb08737 --- /dev/null +++ b/liblo/pthreads.2/pthread.vcproj @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblo/pthreads.2/pthreadVC2.dll.embed.manifest.res b/liblo/pthreads.2/pthreadVC2.dll.embed.manifest.res new file mode 100644 index 0000000..e85fe11 Binary files /dev/null and b/liblo/pthreads.2/pthreadVC2.dll.embed.manifest.res differ diff --git a/liblo/pthreads.2/pthread_attr_destroy.c b/liblo/pthreads.2/pthread_attr_destroy.c new file mode 100644 index 0000000..0ae40b5 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_destroy.c @@ -0,0 +1,79 @@ +/* + * pthread_attr_destroy.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_attr_destroy (pthread_attr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Destroys a thread attributes object. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * + * DESCRIPTION + * Destroys a thread attributes object. + * + * NOTES: + * 1) Does not affect threads created with 'attr'. + * + * RESULTS + * 0 successfully destroyed attr, + * EINVAL 'attr' is invalid. + * + * ------------------------------------------------------ + */ +{ + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + /* + * Set the attribute object to a specific invalid value. + */ + (*attr)->valid = 0; + free (*attr); + *attr = NULL; + + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_getdetachstate.c b/liblo/pthreads.2/pthread_attr_getdetachstate.c new file mode 100644 index 0000000..45eb4f2 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_getdetachstate.c @@ -0,0 +1,87 @@ +/* + * pthread_attr_getdetachstate.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function determines whether threads created with + * 'attr' will run detached. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * detachstate + * pointer to an integer into which is returned one + * of: + * + * PTHREAD_CREATE_JOINABLE + * Thread ID is valid, must be joined + * + * PTHREAD_CREATE_DETACHED + * Thread ID is invalid, cannot be joined, + * canceled, or modified + * + * + * DESCRIPTION + * This function determines whether threads created with + * 'attr' will run detached. + * + * NOTES: + * 1) You cannot join or cancel detached threads. + * + * RESULTS + * 0 successfully retrieved detach state, + * EINVAL 'attr' is invalid + * + * ------------------------------------------------------ + */ +{ + if (ptw32_is_attr (attr) != 0 || detachstate == NULL) + { + *detachstate = PTHREAD_CREATE_DETACHED; + return EINVAL; + } + + *detachstate = (*attr)->detachstate; + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_getinheritsched.c b/liblo/pthreads.2/pthread_attr_getinheritsched.c new file mode 100644 index 0000000..e9901f7 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_getinheritsched.c @@ -0,0 +1,51 @@ +/* + * pthread_attr_getinheritsched.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_attr_getinheritsched (pthread_attr_t * attr, int *inheritsched) +{ + if (ptw32_is_attr (attr) != 0 || inheritsched == NULL) + { + return EINVAL; + } + + *inheritsched = (*attr)->inheritsched; + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_getschedparam.c b/liblo/pthreads.2/pthread_attr_getschedparam.c new file mode 100644 index 0000000..7ec68cb --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_getschedparam.c @@ -0,0 +1,52 @@ +/* + * pthread_attr_getschedparam.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_attr_getschedparam (const pthread_attr_t * attr, + struct sched_param *param) +{ + if (ptw32_is_attr (attr) != 0 || param == NULL) + { + return EINVAL; + } + + memcpy (param, &(*attr)->param, sizeof (*param)); + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_getschedpolicy.c b/liblo/pthreads.2/pthread_attr_getschedpolicy.c new file mode 100644 index 0000000..ccd91fd --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_getschedpolicy.c @@ -0,0 +1,61 @@ +/* + * pthread_attr_getschedpolicy.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_attr_getschedpolicy (pthread_attr_t * attr, int *policy) +{ + if (ptw32_is_attr (attr) != 0 || policy == NULL) + { + return EINVAL; + } + + /* + * Validate the policy arg. + * Check that a policy constant wasn't passed rather than &policy. + */ + if (policy <= (int *) SCHED_MAX) + { + return EINVAL; + } + + *policy = SCHED_OTHER; + + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_getscope.c b/liblo/pthreads.2/pthread_attr_getscope.c new file mode 100644 index 0000000..d0ca1cd --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_getscope.c @@ -0,0 +1,54 @@ +/* + * pthread_attr_getscope.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* ignore warning "unreferenced formal parameter" */ +#ifdef _MSC_VER +#pragma warning( disable : 4100 ) +#endif + +int +pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope) +{ +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING + *contentionscope = (*attr)->contentionscope; + return 0; +#else + return ENOSYS; +#endif +} diff --git a/liblo/pthreads.2/pthread_attr_getstackaddr.c b/liblo/pthreads.2/pthread_attr_getstackaddr.c new file mode 100644 index 0000000..41bf162 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_getstackaddr.c @@ -0,0 +1,97 @@ +/* + * pthread_attr_getstackaddr.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* ignore warning "unreferenced formal parameter" */ +#ifdef _MSC_VER +#pragma warning( disable : 4100 ) +#endif + +int +pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function determines the address of the stack + * on which threads created with 'attr' will run. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * stackaddr + * pointer into which is returned the stack address. + * + * + * DESCRIPTION + * This function determines the address of the stack + * on which threads created with 'attr' will run. + * + * NOTES: + * 1) Function supported only if this macro is + * defined: + * + * _POSIX_THREAD_ATTR_STACKADDR + * + * 2) Create only one thread for each stack + * address.. + * + * RESULTS + * 0 successfully retreived stack address, + * EINVAL 'attr' is invalid + * ENOSYS function not supported + * + * ------------------------------------------------------ + */ +{ +#if defined( _POSIX_THREAD_ATTR_STACKADDR ) + + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + *stackaddr = (*attr)->stackaddr; + return 0; + +#else + + return ENOSYS; + +#endif /* _POSIX_THREAD_ATTR_STACKADDR */ +} diff --git a/liblo/pthreads.2/pthread_attr_getstacksize.c b/liblo/pthreads.2/pthread_attr_getstacksize.c new file mode 100644 index 0000000..9b4cbed --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_getstacksize.c @@ -0,0 +1,100 @@ +/* + * pthread_attr_getstacksize.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* ignore warning "unreferenced formal parameter" */ +#ifdef _MSC_VER +#pragma warning( disable : 4100 ) +#endif + +int +pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * stacksize) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function determines the size of the stack on + * which threads created with 'attr' will run. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * stacksize + * pointer to size_t into which is returned the + * stack size, in bytes. + * + * + * DESCRIPTION + * This function determines the size of the stack on + * which threads created with 'attr' will run. + * + * NOTES: + * 1) Function supported only if this macro is + * defined: + * + * _POSIX_THREAD_ATTR_STACKSIZE + * + * 2) Use on newly created attributes object to + * find the default stack size. + * + * RESULTS + * 0 successfully retrieved stack size, + * EINVAL 'attr' is invalid + * ENOSYS function not supported + * + * ------------------------------------------------------ + */ +{ +#ifdef _POSIX_THREAD_ATTR_STACKSIZE + + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + /* Everything is okay. */ + *stacksize = (*attr)->stacksize; + return 0; + +#else + + return ENOSYS; + +#endif /* _POSIX_THREAD_ATTR_STACKSIZE */ + +} diff --git a/liblo/pthreads.2/pthread_attr_init.c b/liblo/pthreads.2/pthread_attr_init.c new file mode 100644 index 0000000..bf13449 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_init.c @@ -0,0 +1,117 @@ +/* + * pthread_attr_init.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_attr_init (pthread_attr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Initializes a thread attributes object with default + * attributes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * + * DESCRIPTION + * Initializes a thread attributes object with default + * attributes. + * + * NOTES: + * 1) Used to define thread attributes + * + * RESULTS + * 0 successfully initialized attr, + * ENOMEM insufficient memory for attr. + * + * ------------------------------------------------------ + */ +{ + pthread_attr_t attr_result; + + if (attr == NULL) + { + /* This is disallowed. */ + return EINVAL; + } + + attr_result = (pthread_attr_t) malloc (sizeof (*attr_result)); + + if (attr_result == NULL) + { + return ENOMEM; + } + +#ifdef _POSIX_THREAD_ATTR_STACKSIZE + /* + * Default to zero size. Unless changed explicitly this + * will allow Win32 to set the size to that of the + * main thread. + */ + attr_result->stacksize = 0; +#endif + +#ifdef _POSIX_THREAD_ATTR_STACKADDR + /* FIXME: Set this to something sensible when we support it. */ + attr_result->stackaddr = NULL; +#endif + + attr_result->detachstate = PTHREAD_CREATE_JOINABLE; + +#if HAVE_SIGSET_T + memset (&(attr_result->sigmask), 0, sizeof (sigset_t)); +#endif /* HAVE_SIGSET_T */ + + /* + * Win32 sets new threads to THREAD_PRIORITY_NORMAL and + * not to that of the parent thread. We choose to default to + * this arrangement. + */ + attr_result->param.sched_priority = THREAD_PRIORITY_NORMAL; + attr_result->inheritsched = PTHREAD_EXPLICIT_SCHED; + attr_result->contentionscope = PTHREAD_SCOPE_SYSTEM; + + attr_result->valid = PTW32_ATTR_VALID; + + *attr = attr_result; + + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_setdetachstate.c b/liblo/pthreads.2/pthread_attr_setdetachstate.c new file mode 100644 index 0000000..d96c20c --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_setdetachstate.c @@ -0,0 +1,91 @@ +/* + * pthread_attr_setdetachstate.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function specifies whether threads created with + * 'attr' will run detached. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * detachstate + * an integer containing one of: + * + * PTHREAD_CREATE_JOINABLE + * Thread ID is valid, must be joined + * + * PTHREAD_CREATE_DETACHED + * Thread ID is invalid, cannot be joined, + * canceled, or modified + * + * + * DESCRIPTION + * This function specifies whether threads created with + * 'attr' will run detached. + * + * NOTES: + * 1) You cannot join or cancel detached threads. + * + * RESULTS + * 0 successfully set detach state, + * EINVAL 'attr' or 'detachstate' is invalid + * + * ------------------------------------------------------ + */ +{ + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + if (detachstate != PTHREAD_CREATE_JOINABLE && + detachstate != PTHREAD_CREATE_DETACHED) + { + return EINVAL; + } + + (*attr)->detachstate = detachstate; + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_setinheritsched.c b/liblo/pthreads.2/pthread_attr_setinheritsched.c new file mode 100644 index 0000000..8f92559 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_setinheritsched.c @@ -0,0 +1,57 @@ +/* + * pthread_attr_setinheritsched.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched) +{ + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + if (PTHREAD_INHERIT_SCHED != inheritsched + && PTHREAD_EXPLICIT_SCHED != inheritsched) + { + return EINVAL; + } + + (*attr)->inheritsched = inheritsched; + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_setschedparam.c b/liblo/pthreads.2/pthread_attr_setschedparam.c new file mode 100644 index 0000000..cf38057 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_setschedparam.c @@ -0,0 +1,63 @@ +/* + * pthread_attr_setschedparam.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_attr_setschedparam (pthread_attr_t * attr, + const struct sched_param *param) +{ + int priority; + + if (ptw32_is_attr (attr) != 0 || param == NULL) + { + return EINVAL; + } + + priority = param->sched_priority; + + /* Validate priority level. */ + if (priority < sched_get_priority_min (SCHED_OTHER) || + priority > sched_get_priority_max (SCHED_OTHER)) + { + return EINVAL; + } + + memcpy (&(*attr)->param, param, sizeof (*param)); + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_setschedpolicy.c b/liblo/pthreads.2/pthread_attr_setschedpolicy.c new file mode 100644 index 0000000..3a1ed66 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_setschedpolicy.c @@ -0,0 +1,55 @@ +/* + * pthread_attr_setschedpolicy.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy) +{ + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + if (policy != SCHED_OTHER) + { + return ENOTSUP; + } + + return 0; +} diff --git a/liblo/pthreads.2/pthread_attr_setscope.c b/liblo/pthreads.2/pthread_attr_setscope.c new file mode 100644 index 0000000..9892034 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_setscope.c @@ -0,0 +1,62 @@ +/* + * pthread_attr_setscope.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* ignore warning "unreferenced formal parameter" */ +#ifdef _MSC_VER +#pragma warning( disable : 4100 ) +#endif + +int +pthread_attr_setscope (pthread_attr_t * attr, int contentionscope) +{ +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING + switch (contentionscope) + { + case PTHREAD_SCOPE_SYSTEM: + (*attr)->contentionscope = contentionscope; + return 0; + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + default: + return EINVAL; + } +#else + return ENOSYS; +#endif +} diff --git a/liblo/pthreads.2/pthread_attr_setstackaddr.c b/liblo/pthreads.2/pthread_attr_setstackaddr.c new file mode 100644 index 0000000..ce35f31 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_setstackaddr.c @@ -0,0 +1,97 @@ +/* + * pthread_attr_setstackaddr.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Threads created with 'attr' will run on the stack + * starting at 'stackaddr'. + * Stack must be at least PTHREAD_STACK_MIN bytes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * stacksize + * stack size, in bytes. + * + * + * DESCRIPTION + * Threads created with 'attr' will run on the stack + * starting at 'stackaddr'. + * Stack must be at least PTHREAD_STACK_MIN bytes. + * + * NOTES: + * 1) Function supported only if this macro is + * defined: + * + * _POSIX_THREAD_ATTR_STACKADDR + * + * 2) Create only one thread for each stack + * address.. + * + * 3) Ensure that stackaddr is aligned. + * + * RESULTS + * 0 successfully set stack address, + * EINVAL 'attr' is invalid + * ENOSYS function not supported + * + * ------------------------------------------------------ + */ +{ +#if defined( _POSIX_THREAD_ATTR_STACKADDR ) + + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + (*attr)->stackaddr = stackaddr; + return 0; + +#else + + return ENOSYS; + +#endif /* _POSIX_THREAD_ATTR_STACKADDR */ +} diff --git a/liblo/pthreads.2/pthread_attr_setstacksize.c b/liblo/pthreads.2/pthread_attr_setstacksize.c new file mode 100644 index 0000000..f1bc263 --- /dev/null +++ b/liblo/pthreads.2/pthread_attr_setstacksize.c @@ -0,0 +1,110 @@ +/* + * pthread_attr_setstacksize.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function specifies the size of the stack on + * which threads created with 'attr' will run. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_attr_t + * + * stacksize + * stack size, in bytes. + * + * + * DESCRIPTION + * This function specifies the size of the stack on + * which threads created with 'attr' will run. + * + * NOTES: + * 1) Function supported only if this macro is + * defined: + * + * _POSIX_THREAD_ATTR_STACKSIZE + * + * 2) Find the default first (using + * pthread_attr_getstacksize), then increase + * by multiplying. + * + * 3) Only use if thread needs more than the + * default. + * + * RESULTS + * 0 successfully set stack size, + * EINVAL 'attr' is invalid or stacksize too + * small or too big. + * ENOSYS function not supported + * + * ------------------------------------------------------ + */ +{ +#ifdef _POSIX_THREAD_ATTR_STACKSIZE + +#if PTHREAD_STACK_MIN > 0 + + /* Verify that the stack size is within range. */ + if (stacksize < PTHREAD_STACK_MIN) + { + return EINVAL; + } + +#endif + + if (ptw32_is_attr (attr) != 0) + { + return EINVAL; + } + + /* Everything is okay. */ + (*attr)->stacksize = stacksize; + return 0; + +#else + + return ENOSYS; + +#endif /* _POSIX_THREAD_ATTR_STACKSIZE */ + +} diff --git a/liblo/pthreads.2/pthread_barrier_destroy.c b/liblo/pthreads.2/pthread_barrier_destroy.c new file mode 100644 index 0000000..bfff318 --- /dev/null +++ b/liblo/pthreads.2/pthread_barrier_destroy.c @@ -0,0 +1,67 @@ +/* + * pthread_barrier_destroy.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_barrier_destroy (pthread_barrier_t * barrier) +{ + int result = 0; + pthread_barrier_t b; + + if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID) + { + return EINVAL; + } + + b = *barrier; + *barrier = NULL; + + if (0 == (result = sem_destroy (&(b->semBarrierBreeched[0])))) + { + if (0 == (result = sem_destroy (&(b->semBarrierBreeched[1])))) + { + (void) free (b); + return 0; + } + (void) sem_init (&(b->semBarrierBreeched[0]), b->pshared, 0); + } + + *barrier = b; + return (result); +} diff --git a/liblo/pthreads.2/pthread_barrier_init.c b/liblo/pthreads.2/pthread_barrier_init.c new file mode 100644 index 0000000..b588e73 --- /dev/null +++ b/liblo/pthreads.2/pthread_barrier_init.c @@ -0,0 +1,81 @@ +/* + * pthread_barrier_init.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, unsigned int count) +{ + pthread_barrier_t b; + + if (barrier == NULL || count == 0) + { + return EINVAL; + } + + if (NULL != (b = (pthread_barrier_t) calloc (1, sizeof (*b)))) + { + b->pshared = (attr != NULL && *attr != NULL + ? (*attr)->pshared : PTHREAD_PROCESS_PRIVATE); + + b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count; + b->iStep = 0; + + /* + * Two semaphores are used in the same way as two stepping + * stones might be used in crossing a stream. Once all + * threads are safely on one stone, the other stone can + * be moved ahead, and the threads can start moving to it. + * If some threads decide to eat their lunch before moving + * then the other threads have to wait. + */ + if (0 == sem_init (&(b->semBarrierBreeched[0]), b->pshared, 0)) + { + if (0 == sem_init (&(b->semBarrierBreeched[1]), b->pshared, 0)) + { + *barrier = b; + return 0; + } + (void) sem_destroy (&(b->semBarrierBreeched[0])); + } + (void) free (b); + } + + return ENOMEM; +} diff --git a/liblo/pthreads.2/pthread_barrier_wait.c b/liblo/pthreads.2/pthread_barrier_wait.c new file mode 100644 index 0000000..cb9a08e --- /dev/null +++ b/liblo/pthreads.2/pthread_barrier_wait.c @@ -0,0 +1,99 @@ +/* + * pthread_barrier_wait.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_barrier_wait (pthread_barrier_t * barrier) +{ + int result; + int step; + pthread_barrier_t b; + + if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID) + { + return EINVAL; + } + + b = *barrier; + step = b->iStep; + + if (0 == InterlockedDecrement ((long *) &(b->nCurrentBarrierHeight))) + { + /* Must be done before posting the semaphore. */ + b->nCurrentBarrierHeight = b->nInitialBarrierHeight; + + /* + * There is no race condition between the semaphore wait and post + * because we are using two alternating semas and all threads have + * entered barrier_wait and checked nCurrentBarrierHeight before this + * barrier's sema can be posted. Any threads that have not quite + * entered sem_wait below when the multiple_post has completed + * will nevertheless continue through the semaphore (barrier) + * and will not be left stranded. + */ + result = (b->nInitialBarrierHeight > 1 + ? sem_post_multiple (&(b->semBarrierBreeched[step]), + b->nInitialBarrierHeight - 1) : 0); + } + else + { + /* + * Use the non-cancelable version of sem_wait(). + */ + result = ptw32_semwait (&(b->semBarrierBreeched[step])); + } + + /* + * The first thread across will be the PTHREAD_BARRIER_SERIAL_THREAD. + * This also sets up the alternate semaphore as the next barrier. + */ + if (0 == result) + { + result = ((PTW32_INTERLOCKED_LONG) step == + PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) + & (b->iStep), + (PTW32_INTERLOCKED_LONG) + (1L - step), + (PTW32_INTERLOCKED_LONG) + step) ? + PTHREAD_BARRIER_SERIAL_THREAD : 0); + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_barrierattr_destroy.c b/liblo/pthreads.2/pthread_barrierattr_destroy.c new file mode 100644 index 0000000..aabfc5f --- /dev/null +++ b/liblo/pthreads.2/pthread_barrierattr_destroy.c @@ -0,0 +1,83 @@ +/* + * pthread_barrier_attr_destroy.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_barrierattr_destroy (pthread_barrierattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Destroys a barrier attributes object. The object can + * no longer be used. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_barrierattr_t + * + * + * DESCRIPTION + * Destroys a barrier attributes object. The object can + * no longer be used. + * + * NOTES: + * 1) Does not affect barrieres created using 'attr' + * + * RESULTS + * 0 successfully released attr, + * EINVAL 'attr' is invalid. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if (attr == NULL || *attr == NULL) + { + result = EINVAL; + } + else + { + pthread_barrierattr_t ba = *attr; + + *attr = NULL; + free (ba); + } + + return (result); +} /* pthread_barrierattr_destroy */ diff --git a/liblo/pthreads.2/pthread_barrierattr_getpshared.c b/liblo/pthreads.2/pthread_barrierattr_getpshared.c new file mode 100644 index 0000000..93f7d41 --- /dev/null +++ b/liblo/pthreads.2/pthread_barrierattr_getpshared.c @@ -0,0 +1,95 @@ +/* + * pthread_barrier_attr_getpshared.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr, + int *pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Determine whether barriers created with 'attr' can be + * shared between processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_barrierattr_t + * + * pshared + * will be set to one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * + * DESCRIPTION + * Mutexes creatd with 'attr' can be shared between + * processes if pthread_barrier_t variable is allocated + * in memory shared by these processes. + * NOTES: + * 1) pshared barriers MUST be allocated in shared + * memory. + * 2) The following macro is defined if shared barriers + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully retrieved attribute, + * EINVAL 'attr' is invalid, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) && (pshared != NULL)) + { + *pshared = (*attr)->pshared; + result = 0; + } + else + { + result = EINVAL; + } + + return (result); +} /* pthread_barrierattr_getpshared */ diff --git a/liblo/pthreads.2/pthread_barrierattr_init.c b/liblo/pthreads.2/pthread_barrierattr_init.c new file mode 100644 index 0000000..1b880f1 --- /dev/null +++ b/liblo/pthreads.2/pthread_barrierattr_init.c @@ -0,0 +1,85 @@ +/* + * pthread_barrier_attr_init.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_barrierattr_init (pthread_barrierattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Initializes a barrier attributes object with default + * attributes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_barrierattr_t + * + * + * DESCRIPTION + * Initializes a barrier attributes object with default + * attributes. + * + * NOTES: + * 1) Used to define barrier types + * + * RESULTS + * 0 successfully initialized attr, + * ENOMEM insufficient memory for attr. + * + * ------------------------------------------------------ + */ +{ + pthread_barrierattr_t ba; + int result = 0; + + ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba)); + + if (ba == NULL) + { + result = ENOMEM; + } + else + { + ba->pshared = PTHREAD_PROCESS_PRIVATE; + } + + *attr = ba; + + return (result); +} /* pthread_barrierattr_init */ diff --git a/liblo/pthreads.2/pthread_barrierattr_setpshared.c b/liblo/pthreads.2/pthread_barrierattr_setpshared.c new file mode 100644 index 0000000..0ab9992 --- /dev/null +++ b/liblo/pthreads.2/pthread_barrierattr_setpshared.c @@ -0,0 +1,119 @@ +/* + * pthread_barrier_attr_setpshared.c + * + * Description: + * This translation unit implements barrier primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, int pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Barriers created with 'attr' can be shared between + * processes if pthread_barrier_t variable is allocated + * in memory shared by these processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_barrierattr_t + * + * pshared + * must be one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * DESCRIPTION + * Mutexes creatd with 'attr' can be shared between + * processes if pthread_barrier_t variable is allocated + * in memory shared by these processes. + * + * NOTES: + * 1) pshared barriers MUST be allocated in shared + * memory. + * + * 2) The following macro is defined if shared barriers + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully set attribute, + * EINVAL 'attr' or pshared is invalid, + * ENOSYS PTHREAD_PROCESS_SHARED not supported, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) && + ((pshared == PTHREAD_PROCESS_SHARED) || + (pshared == PTHREAD_PROCESS_PRIVATE))) + { + if (pshared == PTHREAD_PROCESS_SHARED) + { + +#if !defined( _POSIX_THREAD_PROCESS_SHARED ) + + result = ENOSYS; + pshared = PTHREAD_PROCESS_PRIVATE; + +#else + + result = 0; + +#endif /* _POSIX_THREAD_PROCESS_SHARED */ + + } + else + { + result = 0; + } + + (*attr)->pshared = pshared; + } + else + { + result = EINVAL; + } + + return (result); + +} /* pthread_barrierattr_setpshared */ diff --git a/liblo/pthreads.2/pthread_cancel.c b/liblo/pthreads.2/pthread_cancel.c new file mode 100644 index 0000000..d0b7987 --- /dev/null +++ b/liblo/pthreads.2/pthread_cancel.c @@ -0,0 +1,223 @@ +/* + * pthread_cancel.c + * + * Description: + * POSIX thread functions related to thread cancellation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +#if defined(_M_IX86) || defined(_X86_) +#define PTW32_PROGCTR(Context) ((Context).Eip) +#endif + +#if defined (_M_IA64) +#define PTW32_PROGCTR(Context) ((Context).StIIP) +#endif + +#if defined(_MIPS_) +#define PTW32_PROGCTR(Context) ((Context).Fir) +#endif + +#if defined(_ALPHA_) +#define PTW32_PROGCTR(Context) ((Context).Fir) +#endif + +#if defined(_PPC_) +#define PTW32_PROGCTR(Context) ((Context).Iar) +#endif + +#if defined(_AMD64_) +#define PTW32_PROGCTR(Context) ((Context).Rip) +#endif + +#if !defined(PTW32_PROGCTR) +#error Module contains CPU-specific code; modify and recompile. +#endif + +static void +ptw32_cancel_self (void) +{ + ptw32_throw (PTW32_EPS_CANCEL); + + /* Never reached */ +} + +static void CALLBACK +ptw32_cancel_callback (DWORD unused) +{ + ptw32_throw (PTW32_EPS_CANCEL); + + /* Never reached */ +} + +/* + * ptw32_RegisterCancelation() - + * Must have args of same type as QueueUserAPCEx because this function + * is a substitute for QueueUserAPCEx if it's not available. + */ +DWORD +ptw32_RegisterCancelation (PAPCFUNC unused1, HANDLE threadH, DWORD unused2) +{ + CONTEXT context; + + context.ContextFlags = CONTEXT_CONTROL; + GetThreadContext (threadH, &context); + PTW32_PROGCTR (context) = (DWORD_PTR) ptw32_cancel_self; + SetThreadContext (threadH, &context); + return 0; +} + +int +pthread_cancel (pthread_t thread) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function requests cancellation of 'thread'. + * + * PARAMETERS + * thread + * reference to an instance of pthread_t + * + * + * DESCRIPTION + * This function requests cancellation of 'thread'. + * NOTE: cancellation is asynchronous; use pthread_join to + * wait for termination of 'thread' if necessary. + * + * RESULTS + * 0 successfully requested cancellation, + * ESRCH no thread found corresponding to 'thread', + * ENOMEM implicit self thread create failed. + * ------------------------------------------------------ + */ +{ + int result; + int cancel_self; + pthread_t self; + ptw32_thread_t * tp; + + result = pthread_kill (thread, 0); + + if (0 != result) + { + return result; + } + + if ((self = pthread_self ()).p == NULL) + { + return ENOMEM; + }; + + /* + * FIXME!! + * + * Can a thread cancel itself? + * + * The standard doesn't + * specify an error to be returned if the target + * thread is itself. + * + * If it may, then we need to ensure that a thread can't + * deadlock itself trying to cancel itself asyncronously + * (pthread_cancel is required to be an async-cancel + * safe function). + */ + cancel_self = pthread_equal (thread, self); + + tp = (ptw32_thread_t *) thread.p; + + /* + * Lock for async-cancel safety. + */ + (void) pthread_mutex_lock (&tp->cancelLock); + + if (tp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS + && tp->cancelState == PTHREAD_CANCEL_ENABLE + && tp->state < PThreadStateCanceling) + { + if (cancel_self) + { + tp->state = PThreadStateCanceling; + tp->cancelState = PTHREAD_CANCEL_DISABLE; + + (void) pthread_mutex_unlock (&tp->cancelLock); + ptw32_throw (PTW32_EPS_CANCEL); + + /* Never reached */ + } + else + { + HANDLE threadH = tp->threadH; + + SuspendThread (threadH); + + if (WaitForSingleObject (threadH, 0) == WAIT_TIMEOUT) + { + tp->state = PThreadStateCanceling; + tp->cancelState = PTHREAD_CANCEL_DISABLE; + /* + * If alertdrv and QueueUserAPCEx is available then the following + * will result in a call to QueueUserAPCEx with the args given, otherwise + * this will result in a call to ptw32_RegisterCancelation and only + * the threadH arg will be used. + */ + ptw32_register_cancelation (ptw32_cancel_callback, threadH, 0); + (void) pthread_mutex_unlock (&tp->cancelLock); + ResumeThread (threadH); + } + } + } + else + { + /* + * Set for deferred cancellation. + */ + if (tp->state < PThreadStateCancelPending) + { + tp->state = PThreadStateCancelPending; + if (!SetEvent (tp->cancelEvent)) + { + result = ESRCH; + } + } + else if (tp->state >= PThreadStateCanceling) + { + result = ESRCH; + } + + (void) pthread_mutex_unlock (&tp->cancelLock); + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_cond_destroy.c b/liblo/pthreads.2/pthread_cond_destroy.c new file mode 100644 index 0000000..8d016af --- /dev/null +++ b/liblo/pthreads.2/pthread_cond_destroy.c @@ -0,0 +1,244 @@ +/* + * pthread_cond_destroy.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +int +pthread_cond_destroy (pthread_cond_t * cond) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function destroys a condition variable + * + * + * PARAMETERS + * cond + * pointer to an instance of pthread_cond_t + * + * + * DESCRIPTION + * This function destroys a condition variable. + * + * NOTES: + * 1) A condition variable can be destroyed + * immediately after all the threads that + * are blocked on it are awakened. e.g. + * + * struct list { + * pthread_mutex_t lm; + * ... + * } + * + * struct elt { + * key k; + * int busy; + * pthread_cond_t notbusy; + * ... + * } + * + * + * struct elt * + * list_find(struct list *lp, key k) + * { + * struct elt *ep; + * + * pthread_mutex_lock(&lp->lm); + * while ((ep = find_elt(l,k) != NULL) && ep->busy) + * pthread_cond_wait(&ep->notbusy, &lp->lm); + * if (ep != NULL) + * ep->busy = 1; + * pthread_mutex_unlock(&lp->lm); + * return(ep); + * } + * + * delete_elt(struct list *lp, struct elt *ep) + * { + * pthread_mutex_lock(&lp->lm); + * assert(ep->busy); + * ... remove ep from list ... + * ep->busy = 0; + * (A) pthread_cond_broadcast(&ep->notbusy); + * pthread_mutex_unlock(&lp->lm); + * (B) pthread_cond_destroy(&rp->notbusy); + * free(ep); + * } + * + * In this example, the condition variable + * and its list element may be freed (line B) + * immediately after all threads waiting for + * it are awakened (line A), since the mutex + * and the code ensure that no other thread + * can touch the element to be deleted. + * + * RESULTS + * 0 successfully released condition variable, + * EINVAL 'cond' is invalid, + * EBUSY 'cond' is in use, + * + * ------------------------------------------------------ + */ +{ + pthread_cond_t cv; + int result = 0, result1 = 0, result2 = 0; + + /* + * Assuming any race condition here is harmless. + */ + if (cond == NULL || *cond == NULL) + { + return EINVAL; + } + + if (*cond != PTHREAD_COND_INITIALIZER) + { + EnterCriticalSection (&ptw32_cond_list_lock); + + cv = *cond; + + /* + * Close the gate; this will synchronize this thread with + * all already signaled waiters to let them retract their + * waiter status - SEE NOTE 1 ABOVE!!! + */ + if (sem_wait (&(cv->semBlockLock)) != 0) + { + return errno; + } + + /* + * !TRY! lock mtxUnblockLock; try will detect busy condition + * and will not cause a deadlock with respect to concurrent + * signal/broadcast. + */ + if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0) + { + (void) sem_post (&(cv->semBlockLock)); + return result; + } + + /* + * Check whether cv is still busy (still has waiters) + */ + if (cv->nWaitersBlocked > cv->nWaitersGone) + { + if (sem_post (&(cv->semBlockLock)) != 0) + { + result = errno; + } + result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock)); + result2 = EBUSY; + } + else + { + /* + * Now it is safe to destroy + */ + *cond = NULL; + + if (sem_destroy (&(cv->semBlockLock)) != 0) + { + result = errno; + } + if (sem_destroy (&(cv->semBlockQueue)) != 0) + { + result1 = errno; + } + if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0) + { + result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock)); + } + + /* Unlink the CV from the list */ + + if (ptw32_cond_list_head == cv) + { + ptw32_cond_list_head = cv->next; + } + else + { + cv->prev->next = cv->next; + } + + if (ptw32_cond_list_tail == cv) + { + ptw32_cond_list_tail = cv->prev; + } + else + { + cv->next->prev = cv->prev; + } + + (void) free (cv); + } + + LeaveCriticalSection (&ptw32_cond_list_lock); + } + else + { + /* + * See notes in ptw32_cond_check_need_init() above also. + */ + EnterCriticalSection (&ptw32_cond_test_init_lock); + + /* + * Check again. + */ + if (*cond == PTHREAD_COND_INITIALIZER) + { + /* + * This is all we need to do to destroy a statically + * initialised cond that has not yet been used (initialised). + * If we get to here, another thread waiting to initialise + * this cond will get an EINVAL. That's OK. + */ + *cond = NULL; + } + else + { + /* + * The cv has been initialised while we were waiting + * so assume it's in use. + */ + result = EBUSY; + } + + LeaveCriticalSection (&ptw32_cond_test_init_lock); + } + + return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); +} diff --git a/liblo/pthreads.2/pthread_cond_init.c b/liblo/pthreads.2/pthread_cond_init.c new file mode 100644 index 0000000..f46799b --- /dev/null +++ b/liblo/pthreads.2/pthread_cond_init.c @@ -0,0 +1,165 @@ +/* + * pthread_cond_init.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function initializes a condition variable. + * + * PARAMETERS + * cond + * pointer to an instance of pthread_cond_t + * + * attr + * specifies optional creation attributes. + * + * + * DESCRIPTION + * This function initializes a condition variable. + * + * RESULTS + * 0 successfully created condition variable, + * EINVAL 'attr' is invalid, + * EAGAIN insufficient resources (other than + * memory, + * ENOMEM insufficient memory, + * EBUSY 'cond' is already initialized, + * + * ------------------------------------------------------ + */ +{ + int result; + pthread_cond_t cv = NULL; + + if (cond == NULL) + { + return EINVAL; + } + + if ((attr != NULL && *attr != NULL) && + ((*attr)->pshared == PTHREAD_PROCESS_SHARED)) + { + /* + * Creating condition variable that can be shared between + * processes. + */ + result = ENOSYS; + goto DONE; + } + + cv = (pthread_cond_t) calloc (1, sizeof (*cv)); + + if (cv == NULL) + { + result = ENOMEM; + goto DONE; + } + + cv->nWaitersBlocked = 0; + cv->nWaitersToUnblock = 0; + cv->nWaitersGone = 0; + + if (sem_init (&(cv->semBlockLock), 0, 1) != 0) + { + result = errno; + goto FAIL0; + } + + if (sem_init (&(cv->semBlockQueue), 0, 0) != 0) + { + result = errno; + goto FAIL1; + } + + if ((result = pthread_mutex_init (&(cv->mtxUnblockLock), 0)) != 0) + { + goto FAIL2; + } + + result = 0; + + goto DONE; + + /* + * ------------- + * Failed... + * ------------- + */ +FAIL2: + (void) sem_destroy (&(cv->semBlockQueue)); + +FAIL1: + (void) sem_destroy (&(cv->semBlockLock)); + +FAIL0: + (void) free (cv); + cv = NULL; + +DONE: + if (0 == result) + { + EnterCriticalSection (&ptw32_cond_list_lock); + + cv->next = NULL; + cv->prev = ptw32_cond_list_tail; + + if (ptw32_cond_list_tail != NULL) + { + ptw32_cond_list_tail->next = cv; + } + + ptw32_cond_list_tail = cv; + + if (ptw32_cond_list_head == NULL) + { + ptw32_cond_list_head = cv; + } + + LeaveCriticalSection (&ptw32_cond_list_lock); + } + + *cond = cv; + + return result; + +} /* pthread_cond_init */ diff --git a/liblo/pthreads.2/pthread_cond_signal.c b/liblo/pthreads.2/pthread_cond_signal.c new file mode 100644 index 0000000..e147831 --- /dev/null +++ b/liblo/pthreads.2/pthread_cond_signal.c @@ -0,0 +1,231 @@ +/* + * pthread_cond_signal.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * ------------------------------------------------------------- + * Algorithm: + * See the comments at the top of pthread_cond_wait.c. + */ + +#include "pthread.h" +#include "implement.h" + +static INLINE int +ptw32_cond_unblock (pthread_cond_t * cond, int unblockAll) + /* + * Notes. + * + * Does not use the external mutex for synchronisation, + * therefore semBlockLock is needed. + * mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the + * state where the external mutex is not necessarily locked by + * any thread, ie. between cond_wait unlocking and re-acquiring + * the lock after having been signaled or a timeout or + * cancellation. + * + * Uses the following CV elements: + * nWaitersBlocked + * nWaitersToUnblock + * nWaitersGone + * mtxUnblockLock + * semBlockLock + * semBlockQueue + */ +{ + int result; + pthread_cond_t cv; + int nSignalsToIssue; + + if (cond == NULL || *cond == NULL) + { + return EINVAL; + } + + cv = *cond; + + /* + * No-op if the CV is static and hasn't been initialised yet. + * Assuming that any race condition is harmless. + */ + if (cv == PTHREAD_COND_INITIALIZER) + { + return 0; + } + + if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0) + { + return result; + } + + if (0 != cv->nWaitersToUnblock) + { + if (0 == cv->nWaitersBlocked) + { + return pthread_mutex_unlock (&(cv->mtxUnblockLock)); + } + if (unblockAll) + { + cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked); + cv->nWaitersBlocked = 0; + } + else + { + nSignalsToIssue = 1; + cv->nWaitersToUnblock++; + cv->nWaitersBlocked--; + } + } + else if (cv->nWaitersBlocked > cv->nWaitersGone) + { + /* Use the non-cancellable version of sem_wait() */ + if (ptw32_semwait (&(cv->semBlockLock)) != 0) + { + result = errno; + (void) pthread_mutex_unlock (&(cv->mtxUnblockLock)); + return result; + } + if (0 != cv->nWaitersGone) + { + cv->nWaitersBlocked -= cv->nWaitersGone; + cv->nWaitersGone = 0; + } + if (unblockAll) + { + nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked; + cv->nWaitersBlocked = 0; + } + else + { + nSignalsToIssue = cv->nWaitersToUnblock = 1; + cv->nWaitersBlocked--; + } + } + else + { + return pthread_mutex_unlock (&(cv->mtxUnblockLock)); + } + + if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0) + { + if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0) + { + result = errno; + } + } + + return result; + +} /* ptw32_cond_unblock */ + +int +pthread_cond_signal (pthread_cond_t * cond) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function signals a condition variable, waking + * one waiting thread. + * If SCHED_FIFO or SCHED_RR policy threads are waiting + * the highest priority waiter is awakened; otherwise, + * an unspecified waiter is awakened. + * + * PARAMETERS + * cond + * pointer to an instance of pthread_cond_t + * + * + * DESCRIPTION + * This function signals a condition variable, waking + * one waiting thread. + * If SCHED_FIFO or SCHED_RR policy threads are waiting + * the highest priority waiter is awakened; otherwise, + * an unspecified waiter is awakened. + * + * NOTES: + * + * 1) Use when any waiter can respond and only one need + * respond (all waiters being equal). + * + * RESULTS + * 0 successfully signaled condition, + * EINVAL 'cond' is invalid, + * + * ------------------------------------------------------ + */ +{ + /* + * The '0'(FALSE) unblockAll arg means unblock ONE waiter. + */ + return (ptw32_cond_unblock (cond, 0)); + +} /* pthread_cond_signal */ + +int +pthread_cond_broadcast (pthread_cond_t * cond) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function broadcasts the condition variable, + * waking all current waiters. + * + * PARAMETERS + * cond + * pointer to an instance of pthread_cond_t + * + * + * DESCRIPTION + * This function signals a condition variable, waking + * all waiting threads. + * + * NOTES: + * + * 1) Use when more than one waiter may respond to + * predicate change or if any waiting thread may + * not be able to respond + * + * RESULTS + * 0 successfully signalled condition to all + * waiting threads, + * EINVAL 'cond' is invalid + * ENOSPC a required resource has been exhausted, + * + * ------------------------------------------------------ + */ +{ + /* + * The TRUE unblockAll arg means unblock ALL waiters. + */ + return (ptw32_cond_unblock (cond, PTW32_TRUE)); + +} /* pthread_cond_broadcast */ diff --git a/liblo/pthreads.2/pthread_cond_wait.c b/liblo/pthreads.2/pthread_cond_wait.c new file mode 100644 index 0000000..e33713b --- /dev/null +++ b/liblo/pthreads.2/pthread_cond_wait.c @@ -0,0 +1,567 @@ +/* + * pthread_cond_wait.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * ------------------------------------------------------------- + * Algorithm: + * The algorithm used in this implementation is that developed by + * Alexander Terekhov in colaboration with Louis Thomas. The bulk + * of the discussion is recorded in the file README.CV, which contains + * several generations of both colaborators original algorithms. The final + * algorithm used here is the one referred to as + * + * Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL + * + * presented below in pseudo-code as it appeared: + * + * + * given: + * semBlockLock - bin.semaphore + * semBlockQueue - semaphore + * mtxExternal - mutex or CS + * mtxUnblockLock - mutex or CS + * nWaitersGone - int + * nWaitersBlocked - int + * nWaitersToUnblock - int + * + * wait( timeout ) { + * + * [auto: register int result ] // error checking omitted + * [auto: register int nSignalsWasLeft ] + * [auto: register int nWaitersWasGone ] + * + * sem_wait( semBlockLock ); + * nWaitersBlocked++; + * sem_post( semBlockLock ); + * + * unlock( mtxExternal ); + * bTimedOut = sem_wait( semBlockQueue,timeout ); + * + * lock( mtxUnblockLock ); + * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { + * if ( bTimeout ) { // timeout (or canceled) + * if ( 0 != nWaitersBlocked ) { + * nWaitersBlocked--; + * } + * else { + * nWaitersGone++; // count spurious wakeups. + * } + * } + * if ( 0 == --nWaitersToUnblock ) { + * if ( 0 != nWaitersBlocked ) { + * sem_post( semBlockLock ); // open the gate. + * nSignalsWasLeft = 0; // do not open the gate + * // below again. + * } + * else if ( 0 != (nWaitersWasGone = nWaitersGone) ) { + * nWaitersGone = 0; + * } + * } + * } + * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or + * // spurious semaphore :-) + * sem_wait( semBlockLock ); + * nWaitersBlocked -= nWaitersGone; // something is going on here + * // - test of timeouts? :-) + * sem_post( semBlockLock ); + * nWaitersGone = 0; + * } + * unlock( mtxUnblockLock ); + * + * if ( 1 == nSignalsWasLeft ) { + * if ( 0 != nWaitersWasGone ) { + * // sem_adjust( semBlockQueue,-nWaitersWasGone ); + * while ( nWaitersWasGone-- ) { + * sem_wait( semBlockQueue ); // better now than spurious later + * } + * } sem_post( semBlockLock ); // open the gate + * } + * + * lock( mtxExternal ); + * + * return ( bTimedOut ) ? ETIMEOUT : 0; + * } + * + * signal(bAll) { + * + * [auto: register int result ] + * [auto: register int nSignalsToIssue] + * + * lock( mtxUnblockLock ); + * + * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! + * if ( 0 == nWaitersBlocked ) { // NO-OP + * return unlock( mtxUnblockLock ); + * } + * if (bAll) { + * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; + * nWaitersBlocked = 0; + * } + * else { + * nSignalsToIssue = 1; + * nWaitersToUnblock++; + * nWaitersBlocked--; + * } + * } + * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! + * sem_wait( semBlockLock ); // close the gate + * if ( 0 != nWaitersGone ) { + * nWaitersBlocked -= nWaitersGone; + * nWaitersGone = 0; + * } + * if (bAll) { + * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; + * nWaitersBlocked = 0; + * } + * else { + * nSignalsToIssue = nWaitersToUnblock = 1; + * nWaitersBlocked--; + * } + * } + * else { // NO-OP + * return unlock( mtxUnblockLock ); + * } + * + * unlock( mtxUnblockLock ); + * sem_post( semBlockQueue,nSignalsToIssue ); + * return result; + * } + * ------------------------------------------------------------- + * + * Algorithm 9 / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL + * + * presented below in pseudo-code; basically 8a... + * ...BUT W/O "spurious wakes" prevention: + * + * + * given: + * semBlockLock - bin.semaphore + * semBlockQueue - semaphore + * mtxExternal - mutex or CS + * mtxUnblockLock - mutex or CS + * nWaitersGone - int + * nWaitersBlocked - int + * nWaitersToUnblock - int + * + * wait( timeout ) { + * + * [auto: register int result ] // error checking omitted + * [auto: register int nSignalsWasLeft ] + * + * sem_wait( semBlockLock ); + * ++nWaitersBlocked; + * sem_post( semBlockLock ); + * + * unlock( mtxExternal ); + * bTimedOut = sem_wait( semBlockQueue,timeout ); + * + * lock( mtxUnblockLock ); + * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) { + * --nWaitersToUnblock; + * } + * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or + * // spurious semaphore :-) + * sem_wait( semBlockLock ); + * nWaitersBlocked -= nWaitersGone; // something is going on here + * // - test of timeouts? :-) + * sem_post( semBlockLock ); + * nWaitersGone = 0; + * } + * unlock( mtxUnblockLock ); + * + * if ( 1 == nSignalsWasLeft ) { + * sem_post( semBlockLock ); // open the gate + * } + * + * lock( mtxExternal ); + * + * return ( bTimedOut ) ? ETIMEOUT : 0; + * } + * + * signal(bAll) { + * + * [auto: register int result ] + * [auto: register int nSignalsToIssue] + * + * lock( mtxUnblockLock ); + * + * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!! + * if ( 0 == nWaitersBlocked ) { // NO-OP + * return unlock( mtxUnblockLock ); + * } + * if (bAll) { + * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked; + * nWaitersBlocked = 0; + * } + * else { + * nSignalsToIssue = 1; + * ++nWaitersToUnblock; + * --nWaitersBlocked; + * } + * } + * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION! + * sem_wait( semBlockLock ); // close the gate + * if ( 0 != nWaitersGone ) { + * nWaitersBlocked -= nWaitersGone; + * nWaitersGone = 0; + * } + * if (bAll) { + * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked; + * nWaitersBlocked = 0; + * } + * else { + * nSignalsToIssue = nWaitersToUnblock = 1; + * --nWaitersBlocked; + * } + * } + * else { // NO-OP + * return unlock( mtxUnblockLock ); + * } + * + * unlock( mtxUnblockLock ); + * sem_post( semBlockQueue,nSignalsToIssue ); + * return result; + * } + * ------------------------------------------------------------- + * + */ + +#include "pthread.h" +#include "implement.h" + +/* + * Arguments for cond_wait_cleanup, since we can only pass a + * single void * to it. + */ +typedef struct +{ + pthread_mutex_t *mutexPtr; + pthread_cond_t cv; + int *resultPtr; +} ptw32_cond_wait_cleanup_args_t; + +static void PTW32_CDECL +ptw32_cond_wait_cleanup (void *args) +{ + ptw32_cond_wait_cleanup_args_t *cleanup_args = + (ptw32_cond_wait_cleanup_args_t *) args; + pthread_cond_t cv = cleanup_args->cv; + int *resultPtr = cleanup_args->resultPtr; + int nSignalsWasLeft; + int result; + + /* + * Whether we got here as a result of signal/broadcast or because of + * timeout on wait or thread cancellation we indicate that we are no + * longer waiting. The waiter is responsible for adjusting waiters + * (to)unblock(ed) counts (protected by unblock lock). + */ + if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0) + { + *resultPtr = result; + return; + } + + if (0 != (nSignalsWasLeft = cv->nWaitersToUnblock)) + { + --(cv->nWaitersToUnblock); + } + else if (INT_MAX / 2 == ++(cv->nWaitersGone)) + { + /* Use the non-cancellable version of sem_wait() */ + if (ptw32_semwait (&(cv->semBlockLock)) != 0) + { + *resultPtr = errno; + /* + * This is a fatal error for this CV, + * so we deliberately don't unlock + * cv->mtxUnblockLock before returning. + */ + return; + } + cv->nWaitersBlocked -= cv->nWaitersGone; + if (sem_post (&(cv->semBlockLock)) != 0) + { + *resultPtr = errno; + /* + * This is a fatal error for this CV, + * so we deliberately don't unlock + * cv->mtxUnblockLock before returning. + */ + return; + } + cv->nWaitersGone = 0; + } + + if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) != 0) + { + *resultPtr = result; + return; + } + + if (1 == nSignalsWasLeft) + { + if (sem_post (&(cv->semBlockLock)) != 0) + { + *resultPtr = errno; + return; + } + } + + /* + * XSH: Upon successful return, the mutex has been locked and is owned + * by the calling thread. + */ + if ((result = pthread_mutex_lock (cleanup_args->mutexPtr)) != 0) + { + *resultPtr = result; + } +} /* ptw32_cond_wait_cleanup */ + +static INLINE int +ptw32_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, const struct timespec *abstime) +{ + int result = 0; + pthread_cond_t cv; + ptw32_cond_wait_cleanup_args_t cleanup_args; + + if (cond == NULL || *cond == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static condition variable. We check + * again inside the guarded section of ptw32_cond_check_need_init() + * to avoid race conditions. + */ + if (*cond == PTHREAD_COND_INITIALIZER) + { + result = ptw32_cond_check_need_init (cond); + } + + if (result != 0 && result != EBUSY) + { + return result; + } + + cv = *cond; + + /* Thread can be cancelled in sem_wait() but this is OK */ + if (sem_wait (&(cv->semBlockLock)) != 0) + { + return errno; + } + + ++(cv->nWaitersBlocked); + + if (sem_post (&(cv->semBlockLock)) != 0) + { + return errno; + } + + /* + * Setup this waiter cleanup handler + */ + cleanup_args.mutexPtr = mutex; + cleanup_args.cv = cv; + cleanup_args.resultPtr = &result; + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args); + + /* + * Now we can release 'mutex' and... + */ + if ((result = pthread_mutex_unlock (mutex)) == 0) + { + + /* + * ...wait to be awakened by + * pthread_cond_signal, or + * pthread_cond_broadcast, or + * timeout, or + * thread cancellation + * + * Note: + * + * sem_timedwait is a cancellation point, + * hence providing the mechanism for making + * pthread_cond_wait a cancellation point. + * We use the cleanup mechanism to ensure we + * re-lock the mutex and adjust (to)unblock(ed) waiters + * counts if we are cancelled, timed out or signalled. + */ + if (sem_timedwait (&(cv->semBlockQueue), abstime) != 0) + { + result = errno; + } + } + + /* + * Always cleanup + */ + pthread_cleanup_pop (1); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + /* + * "result" can be modified by the cleanup handler. + */ + return result; + +} /* ptw32_cond_timedwait */ + + +int +pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function waits on a condition variable until + * awakened by a signal or broadcast. + * + * Caller MUST be holding the mutex lock; the + * lock is released and the caller is blocked waiting + * on 'cond'. When 'cond' is signaled, the mutex + * is re-acquired before returning to the caller. + * + * PARAMETERS + * cond + * pointer to an instance of pthread_cond_t + * + * mutex + * pointer to an instance of pthread_mutex_t + * + * + * DESCRIPTION + * This function waits on a condition variable until + * awakened by a signal or broadcast. + * + * NOTES: + * + * 1) The function must be called with 'mutex' LOCKED + * by the calling thread, or undefined behaviour + * will result. + * + * 2) This routine atomically releases 'mutex' and causes + * the calling thread to block on the condition variable. + * The blocked thread may be awakened by + * pthread_cond_signal or + * pthread_cond_broadcast. + * + * Upon successful completion, the 'mutex' has been locked and + * is owned by the calling thread. + * + * + * RESULTS + * 0 caught condition; mutex released, + * EINVAL 'cond' or 'mutex' is invalid, + * EINVAL different mutexes for concurrent waits, + * EINVAL mutex is not held by the calling thread, + * + * ------------------------------------------------------ + */ +{ + /* + * The NULL abstime arg means INFINITE waiting. + */ + return (ptw32_cond_timedwait (cond, mutex, NULL)); + +} /* pthread_cond_wait */ + + +int +pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function waits on a condition variable either until + * awakened by a signal or broadcast; or until the time + * specified by abstime passes. + * + * PARAMETERS + * cond + * pointer to an instance of pthread_cond_t + * + * mutex + * pointer to an instance of pthread_mutex_t + * + * abstime + * pointer to an instance of (const struct timespec) + * + * + * DESCRIPTION + * This function waits on a condition variable either until + * awakened by a signal or broadcast; or until the time + * specified by abstime passes. + * + * NOTES: + * 1) The function must be called with 'mutex' LOCKED + * by the calling thread, or undefined behaviour + * will result. + * + * 2) This routine atomically releases 'mutex' and causes + * the calling thread to block on the condition variable. + * The blocked thread may be awakened by + * pthread_cond_signal or + * pthread_cond_broadcast. + * + * + * RESULTS + * 0 caught condition; mutex released, + * EINVAL 'cond', 'mutex', or abstime is invalid, + * EINVAL different mutexes for concurrent waits, + * EINVAL mutex is not held by the calling thread, + * ETIMEDOUT abstime ellapsed before cond was signaled. + * + * ------------------------------------------------------ + */ +{ + if (abstime == NULL) + { + return EINVAL; + } + + return (ptw32_cond_timedwait (cond, mutex, abstime)); + +} /* pthread_cond_timedwait */ diff --git a/liblo/pthreads.2/pthread_condattr_destroy.c b/liblo/pthreads.2/pthread_condattr_destroy.c new file mode 100644 index 0000000..2ca11b4 --- /dev/null +++ b/liblo/pthreads.2/pthread_condattr_destroy.c @@ -0,0 +1,86 @@ +/* + * condvar_attr_destroy.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_condattr_destroy (pthread_condattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Destroys a condition variable attributes object. + * The object can no longer be used. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_condattr_t + * + * + * DESCRIPTION + * Destroys a condition variable attributes object. + * The object can no longer be used. + * + * NOTES: + * 1) Does not affect condition variables created + * using 'attr' + * + * RESULTS + * 0 successfully released attr, + * EINVAL 'attr' is invalid. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if (attr == NULL || *attr == NULL) + { + result = EINVAL; + } + else + { + (void) free (*attr); + + *attr = NULL; + result = 0; + } + + return result; + +} /* pthread_condattr_destroy */ diff --git a/liblo/pthreads.2/pthread_condattr_getpshared.c b/liblo/pthreads.2/pthread_condattr_getpshared.c new file mode 100644 index 0000000..b7b854f --- /dev/null +++ b/liblo/pthreads.2/pthread_condattr_getpshared.c @@ -0,0 +1,97 @@ +/* + * pthread_condattr_getpshared.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Determine whether condition variables created with 'attr' + * can be shared between processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_condattr_t + * + * pshared + * will be set to one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * + * DESCRIPTION + * Condition Variables created with 'attr' can be shared + * between processes if pthread_cond_t variable is allocated + * in memory shared by these processes. + * NOTES: + * 1) pshared condition variables MUST be allocated in + * shared memory. + * + * 2) The following macro is defined if shared mutexes + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully retrieved attribute, + * EINVAL 'attr' or 'pshared' is invalid, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) && (pshared != NULL)) + { + *pshared = (*attr)->pshared; + result = 0; + } + else + { + result = EINVAL; + } + + return result; + +} /* pthread_condattr_getpshared */ diff --git a/liblo/pthreads.2/pthread_condattr_init.c b/liblo/pthreads.2/pthread_condattr_init.c new file mode 100644 index 0000000..da79e21 --- /dev/null +++ b/liblo/pthreads.2/pthread_condattr_init.c @@ -0,0 +1,87 @@ +/* + * pthread_condattr_init.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_condattr_init (pthread_condattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Initializes a condition variable attributes object + * with default attributes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_condattr_t + * + * + * DESCRIPTION + * Initializes a condition variable attributes object + * with default attributes. + * + * NOTES: + * 1) Use to define condition variable types + * 2) It is up to the application to ensure + * that it doesn't re-init an attribute + * without destroying it first. Otherwise + * a memory leak is created. + * + * RESULTS + * 0 successfully initialized attr, + * ENOMEM insufficient memory for attr. + * + * ------------------------------------------------------ + */ +{ + pthread_condattr_t attr_result; + int result = 0; + + attr_result = (pthread_condattr_t) calloc (1, sizeof (*attr_result)); + + if (attr_result == NULL) + { + result = ENOMEM; + } + + *attr = attr_result; + + return result; + +} /* pthread_condattr_init */ diff --git a/liblo/pthreads.2/pthread_condattr_setpshared.c b/liblo/pthreads.2/pthread_condattr_setpshared.c new file mode 100644 index 0000000..b8b2213 --- /dev/null +++ b/liblo/pthreads.2/pthread_condattr_setpshared.c @@ -0,0 +1,117 @@ +/* + * pthread_condattr_setpshared.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Mutexes created with 'attr' can be shared between + * processes if pthread_mutex_t variable is allocated + * in memory shared by these processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_mutexattr_t + * + * pshared + * must be one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * DESCRIPTION + * Mutexes creatd with 'attr' can be shared between + * processes if pthread_mutex_t variable is allocated + * in memory shared by these processes. + * + * NOTES: + * 1) pshared mutexes MUST be allocated in shared + * memory. + * + * 2) The following macro is defined if shared mutexes + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully set attribute, + * EINVAL 'attr' or pshared is invalid, + * ENOSYS PTHREAD_PROCESS_SHARED not supported, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) + && ((pshared == PTHREAD_PROCESS_SHARED) + || (pshared == PTHREAD_PROCESS_PRIVATE))) + { + if (pshared == PTHREAD_PROCESS_SHARED) + { + +#if !defined( _POSIX_THREAD_PROCESS_SHARED ) + result = ENOSYS; + pshared = PTHREAD_PROCESS_PRIVATE; +#else + result = 0; + +#endif /* _POSIX_THREAD_PROCESS_SHARED */ + + } + else + { + result = 0; + } + + (*attr)->pshared = pshared; + } + else + { + result = EINVAL; + } + + return result; + +} /* pthread_condattr_setpshared */ diff --git a/liblo/pthreads.2/pthread_delay_np.c b/liblo/pthreads.2/pthread_delay_np.c new file mode 100644 index 0000000..628cb78 --- /dev/null +++ b/liblo/pthreads.2/pthread_delay_np.c @@ -0,0 +1,171 @@ +/* + * pthreads_delay_np.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * pthread_delay_np + * + * DESCRIPTION + * + * This routine causes a thread to delay execution for a specific period of time. + * This period ends at the current time plus the specified interval. The routine + * will not return before the end of the period is reached, but may return an + * arbitrary amount of time after the period has gone by. This can be due to + * system load, thread priorities, and system timer granularity. + * + * Specifying an interval of zero (0) seconds and zero (0) nanoseconds is + * allowed and can be used to force the thread to give up the processor or to + * deliver a pending cancelation request. + * + * The timespec structure contains the following two fields: + * + * tv_sec is an integer number of seconds. + * tv_nsec is an integer number of nanoseconds. + * + * Return Values + * + * If an error condition occurs, this routine returns an integer value indicating + * the type of error. Possible return values are as follows: + * + * 0 + * Successful completion. + * [EINVAL] + * The value specified by interval is invalid. + * + * Example + * + * The following code segment would wait for 5 and 1/2 seconds + * + * struct timespec tsWait; + * int intRC; + * + * tsWait.tv_sec = 5; + * tsWait.tv_nsec = 500000000L; + * intRC = pthread_delay_np(&tsWait); + */ +int +pthread_delay_np (struct timespec *interval) +{ + DWORD wait_time; + DWORD secs_in_millisecs; + DWORD millisecs; + DWORD status; + pthread_t self; + ptw32_thread_t * sp; + + if (interval == NULL) + { + return EINVAL; + } + + if (interval->tv_sec == 0L && interval->tv_nsec == 0L) + { + pthread_testcancel (); + Sleep (0); + pthread_testcancel (); + return (0); + } + + /* convert secs to millisecs */ + secs_in_millisecs = interval->tv_sec * 1000L; + + /* convert nanosecs to millisecs (rounding up) */ + millisecs = (interval->tv_nsec + 999999L) / 1000000L; + +#if defined(__WATCOMC__) +#pragma disable_message (124) +#endif + + /* + * Most compilers will issue a warning 'comparison always 0' + * because the variable type is unsigned, but we need to keep this + * for some reason I can't recall now. + */ + if (0 > (wait_time = secs_in_millisecs + millisecs)) + { + return EINVAL; + } + +#if defined(__WATCOMC__) +#pragma enable_message (124) +#endif + + if (NULL == (self = pthread_self ()).p) + { + return ENOMEM; + } + + sp = (ptw32_thread_t *) self.p; + + if (sp->cancelState == PTHREAD_CANCEL_ENABLE) + { + /* + * Async cancelation won't catch us until wait_time is up. + * Deferred cancelation will cancel us immediately. + */ + if (WAIT_OBJECT_0 == + (status = WaitForSingleObject (sp->cancelEvent, wait_time))) + { + /* + * Canceling! + */ + (void) pthread_mutex_lock (&sp->cancelLock); + if (sp->state < PThreadStateCanceling) + { + sp->state = PThreadStateCanceling; + sp->cancelState = PTHREAD_CANCEL_DISABLE; + (void) pthread_mutex_unlock (&sp->cancelLock); + + ptw32_throw (PTW32_EPS_CANCEL); + } + + (void) pthread_mutex_unlock (&sp->cancelLock); + return ESRCH; + } + else if (status != WAIT_TIMEOUT) + { + return EINVAL; + } + } + else + { + Sleep (wait_time); + } + + return (0); +} diff --git a/liblo/pthreads.2/pthread_detach.c b/liblo/pthreads.2/pthread_detach.c new file mode 100644 index 0000000..3dbe2bb --- /dev/null +++ b/liblo/pthreads.2/pthread_detach.c @@ -0,0 +1,139 @@ +/* + * pthread_detach.c + * + * Description: + * This translation unit implements functions related to thread + * synchronisation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * Not needed yet, but defining it should indicate clashes with build target + * environment that should be fixed. + */ +#include + + +int +pthread_detach (pthread_t thread) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function detaches the given thread. + * + * PARAMETERS + * thread + * an instance of a pthread_t + * + * + * DESCRIPTION + * This function detaches the given thread. You may use it to + * detach the main thread or to detach a joinable thread. + * NOTE: detached threads cannot be joined; + * storage is freed immediately on termination. + * + * RESULTS + * 0 successfully detached the thread, + * EINVAL thread is not a joinable thread, + * ENOSPC a required resource has been exhausted, + * ESRCH no thread could be found for 'thread', + * + * ------------------------------------------------------ + */ +{ + int result; + BOOL destroyIt = PTW32_FALSE; + ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; + + EnterCriticalSection (&ptw32_thread_reuse_lock); + + if (NULL == tp + || thread.x != tp->ptHandle.x) + { + result = ESRCH; + } + else if (PTHREAD_CREATE_DETACHED == tp->detachState) + { + result = EINVAL; + } + else + { + /* + * Joinable ptw32_thread_t structs are not scavenged until + * a join or detach is done. The thread may have exited already, + * but all of the state and locks etc are still there. + */ + result = 0; + + if (pthread_mutex_lock (&tp->cancelLock) == 0) + { + if (tp->state != PThreadStateLast) + { + tp->detachState = PTHREAD_CREATE_DETACHED; + } + else if (tp->detachState != PTHREAD_CREATE_DETACHED) + { + /* + * Thread is joinable and has exited or is exiting. + */ + destroyIt = PTW32_TRUE; + } + (void) pthread_mutex_unlock (&tp->cancelLock); + } + else + { + /* cancelLock shouldn't fail, but if it does ... */ + result = ESRCH; + } + } + + LeaveCriticalSection (&ptw32_thread_reuse_lock); + + if (result == 0) + { + /* Thread is joinable */ + + if (destroyIt) + { + /* The thread has exited or is exiting but has not been joined or + * detached. Need to wait in case it's still exiting. + */ + (void) WaitForSingleObject(tp->threadH, INFINITE); + ptw32_threadDestroy (thread); + } + } + + return (result); + +} /* pthread_detach */ diff --git a/liblo/pthreads.2/pthread_equal.c b/liblo/pthreads.2/pthread_equal.c new file mode 100644 index 0000000..129bbb4 --- /dev/null +++ b/liblo/pthreads.2/pthread_equal.c @@ -0,0 +1,76 @@ +/* + * pthread_equal.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_equal (pthread_t t1, pthread_t t2) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function returns nonzero if t1 and t2 are equal, else + * returns nonzero + * + * PARAMETERS + * t1, + * t2 + * thread IDs + * + * + * DESCRIPTION + * This function returns nonzero if t1 and t2 are equal, else + * returns zero. + * + * RESULTS + * non-zero if t1 and t2 refer to the same thread, + * 0 t1 and t2 do not refer to the same thread + * + * ------------------------------------------------------ + */ +{ + int result; + + /* + * We also accept NULL == NULL - treating NULL as a thread + * for this special case, because there is no error that we can return. + */ + result = ( t1.p == t2.p && t1.x == t2.x ); + + return (result); + +} /* pthread_equal */ diff --git a/liblo/pthreads.2/pthread_exit.c b/liblo/pthreads.2/pthread_exit.c new file mode 100644 index 0000000..b401fb2 --- /dev/null +++ b/liblo/pthreads.2/pthread_exit.c @@ -0,0 +1,106 @@ +/* + * pthread_exit.c + * + * Description: + * This translation unit implements routines associated with exiting from + * a thread. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#ifndef _UWIN +//# include +#endif + +void +pthread_exit (void *value_ptr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function terminates the calling thread, returning + * the value 'value_ptr' to any joining thread. + * + * PARAMETERS + * value_ptr + * a generic data value (i.e. not the address of a value) + * + * + * DESCRIPTION + * This function terminates the calling thread, returning + * the value 'value_ptr' to any joining thread. + * NOTE: thread should be joinable. + * + * RESULTS + * N/A + * + * ------------------------------------------------------ + */ +{ + ptw32_thread_t * sp; + + /* + * Don't use pthread_self() to avoid creating an implicit POSIX thread handle + * unnecessarily. + */ + sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); + +#ifdef _UWIN + if (--pthread_count <= 0) + exit ((int) value_ptr); +#endif + + if (NULL == sp) + { + /* + * A POSIX thread handle was never created. I.e. this is a + * Win32 thread that has never called a pthreads-win32 routine that + * required a POSIX handle. + * + * Implicit POSIX handles are cleaned up in ptw32_throw() now. + */ + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) + _endthreadex ((unsigned) value_ptr); +#else + _endthread (); +#endif + + /* Never reached */ + } + + sp->exitStatus = value_ptr; + + ptw32_throw (PTW32_EPS_EXIT); + + /* Never reached. */ + +} diff --git a/liblo/pthreads.2/pthread_getconcurrency.c b/liblo/pthreads.2/pthread_getconcurrency.c new file mode 100644 index 0000000..52430c6 --- /dev/null +++ b/liblo/pthreads.2/pthread_getconcurrency.c @@ -0,0 +1,45 @@ +/* + * pthread_getconcurrency.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_getconcurrency (void) +{ + return ptw32_concurrency; +} diff --git a/liblo/pthreads.2/pthread_getschedparam.c b/liblo/pthreads.2/pthread_getschedparam.c new file mode 100644 index 0000000..997978f --- /dev/null +++ b/liblo/pthreads.2/pthread_getschedparam.c @@ -0,0 +1,75 @@ +/* + * sched_getschedparam.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param) +{ + int result; + + /* Validate the thread id. */ + result = pthread_kill (thread, 0); + if (0 != result) + { + return result; + } + + /* + * Validate the policy and param args. + * Check that a policy constant wasn't passed rather than &policy. + */ + if (policy <= (int *) SCHED_MAX || param == NULL) + { + return EINVAL; + } + + /* Fill out the policy. */ + *policy = SCHED_OTHER; + + /* + * This function must return the priority value set by + * the most recent pthread_setschedparam() or pthread_create() + * for the target thread. It must not return the actual thread + * priority as altered by any system priority adjustments etc. + */ + param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority; + + return 0; +} diff --git a/liblo/pthreads.2/pthread_getspecific.c b/liblo/pthreads.2/pthread_getspecific.c new file mode 100644 index 0000000..13e3a69 --- /dev/null +++ b/liblo/pthreads.2/pthread_getspecific.c @@ -0,0 +1,84 @@ +/* + * pthread_getspecific.c + * + * Description: + * POSIX thread functions which implement thread-specific data (TSD). + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +void * +pthread_getspecific (pthread_key_t key) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function returns the current value of key in the + * calling thread. If no value has been set for 'key' in + * the thread, NULL is returned. + * + * PARAMETERS + * key + * an instance of pthread_key_t + * + * + * DESCRIPTION + * This function returns the current value of key in the + * calling thread. If no value has been set for 'key' in + * the thread, NULL is returned. + * + * RESULTS + * key value or NULL on failure + * + * ------------------------------------------------------ + */ +{ + void * ptr; + + if (key == NULL) + { + ptr = NULL; + } + else + { + int lasterror = GetLastError (); + int lastWSAerror = WSAGetLastError (); + + ptr = TlsGetValue (key->key); + + SetLastError (lasterror); + WSASetLastError (lastWSAerror); + } + + return ptr; +} diff --git a/liblo/pthreads.2/pthread_getw32threadhandle_np.c b/liblo/pthreads.2/pthread_getw32threadhandle_np.c new file mode 100644 index 0000000..66bcff3 --- /dev/null +++ b/liblo/pthreads.2/pthread_getw32threadhandle_np.c @@ -0,0 +1,53 @@ +/* + * pthread_getw32threadhandle_np.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * pthread_getw32threadhandle_np() + * + * Returns the win32 thread handle that the POSIX + * thread "thread" is running as. + * + * Applications can use the win32 handle to set + * win32 specific attributes of the thread. + */ +HANDLE +pthread_getw32threadhandle_np (pthread_t thread) +{ + return ((ptw32_thread_t *)thread.p)->threadH; +} diff --git a/liblo/pthreads.2/pthread_join.c b/liblo/pthreads.2/pthread_join.c new file mode 100644 index 0000000..be6640b --- /dev/null +++ b/liblo/pthreads.2/pthread_join.c @@ -0,0 +1,154 @@ +/* + * pthread_join.c + * + * Description: + * This translation unit implements functions related to thread + * synchronisation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * Not needed yet, but defining it should indicate clashes with build target + * environment that should be fixed. + */ +#include + + +int +pthread_join (pthread_t thread, void **value_ptr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function waits for 'thread' to terminate and + * returns the thread's exit value if 'value_ptr' is not + * NULL. This also detaches the thread on successful + * completion. + * + * PARAMETERS + * thread + * an instance of pthread_t + * + * value_ptr + * pointer to an instance of pointer to void + * + * + * DESCRIPTION + * This function waits for 'thread' to terminate and + * returns the thread's exit value if 'value_ptr' is not + * NULL. This also detaches the thread on successful + * completion. + * NOTE: detached threads cannot be joined or canceled + * + * RESULTS + * 0 'thread' has completed + * EINVAL thread is not a joinable thread, + * ESRCH no thread could be found with ID 'thread', + * ENOENT thread couldn't find it's own valid handle, + * EDEADLK attempt to join thread with self + * + * ------------------------------------------------------ + */ +{ + int result; + pthread_t self; + ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; + + EnterCriticalSection (&ptw32_thread_reuse_lock); + + if (NULL == tp + || thread.x != tp->ptHandle.x) + { + result = ESRCH; + } + else if (PTHREAD_CREATE_DETACHED == tp->detachState) + { + result = EINVAL; + } + else + { + result = 0; + } + + LeaveCriticalSection (&ptw32_thread_reuse_lock); + + if (result == 0) + { + /* + * The target thread is joinable and can't be reused before we join it. + */ + self = pthread_self(); + + if (NULL == self.p) + { + result = ENOENT; + } + else if (pthread_equal (self, thread)) + { + result = EDEADLK; + } + else + { + /* + * Pthread_join is a cancelation point. + * If we are canceled then our target thread must not be + * detached (destroyed). This is guarranteed because + * pthreadCancelableWait will not return if we + * are canceled. + */ + result = pthreadCancelableWait (tp->threadH); + + if (0 == result) + { + if (value_ptr != NULL) + { + *value_ptr = tp->exitStatus; + } + + /* + * The result of making multiple simultaneous calls to + * pthread_join() or pthread_detach() specifying the same + * target is undefined. + */ + result = pthread_detach (thread); + } + else + { + result = ESRCH; + } + } + } + + return (result); + +} /* pthread_join */ diff --git a/liblo/pthreads.2/pthread_key_create.c b/liblo/pthreads.2/pthread_key_create.c new file mode 100644 index 0000000..b3b410a --- /dev/null +++ b/liblo/pthreads.2/pthread_key_create.c @@ -0,0 +1,108 @@ +/* + * pthread_key_create.c + * + * Description: + * POSIX thread functions which implement thread-specific data (TSD). + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +/* TLS_OUT_OF_INDEXES not defined on WinCE */ +#ifndef TLS_OUT_OF_INDEXES +#define TLS_OUT_OF_INDEXES 0xffffffff +#endif + +int +pthread_key_create (pthread_key_t * key, void (*destructor) (void *)) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function creates a thread-specific data key visible + * to all threads. All existing and new threads have a value + * NULL for key until set using pthread_setspecific. When any + * thread with a non-NULL value for key terminates, 'destructor' + * is called with key's current value for that thread. + * + * PARAMETERS + * key + * pointer to an instance of pthread_key_t + * + * + * DESCRIPTION + * This function creates a thread-specific data key visible + * to all threads. All existing and new threads have a value + * NULL for key until set using pthread_setspecific. When any + * thread with a non-NULL value for key terminates, 'destructor' + * is called with key's current value for that thread. + * + * RESULTS + * 0 successfully created semaphore, + * EAGAIN insufficient resources or PTHREAD_KEYS_MAX + * exceeded, + * ENOMEM insufficient memory to create the key, + * + * ------------------------------------------------------ + */ +{ + int result = 0; + pthread_key_t newkey; + + if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL) + { + result = ENOMEM; + } + else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES) + { + result = EAGAIN; + + free (newkey); + newkey = NULL; + } + else if (destructor != NULL) + { + /* + * Have to manage associations between thread and key; + * Therefore, need a lock that allows multiple threads + * to gain exclusive access to the key->threads list. + * + * The mutex will only be created when it is first locked. + */ + newkey->keyLock = PTHREAD_MUTEX_INITIALIZER; + newkey->destructor = destructor; + } + + *key = newkey; + + return (result); +} diff --git a/liblo/pthreads.2/pthread_key_delete.c b/liblo/pthreads.2/pthread_key_delete.c new file mode 100644 index 0000000..c6acc11 --- /dev/null +++ b/liblo/pthreads.2/pthread_key_delete.c @@ -0,0 +1,133 @@ +/* + * pthread_key_delete.c + * + * Description: + * POSIX thread functions which implement thread-specific data (TSD). + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_key_delete (pthread_key_t key) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function deletes a thread-specific data key. This + * does not change the value of the thread specific data key + * for any thread and does not run the key's destructor + * in any thread so it should be used with caution. + * + * PARAMETERS + * key + * pointer to an instance of pthread_key_t + * + * + * DESCRIPTION + * This function deletes a thread-specific data key. This + * does not change the value of the thread specific data key + * for any thread and does not run the key's destructor + * in any thread so it should be used with caution. + * + * RESULTS + * 0 successfully deleted the key, + * EINVAL key is invalid, + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if (key != NULL) + { + if (key->threads != NULL && + key->destructor != NULL && + pthread_mutex_lock (&(key->keyLock)) == 0) + { + ThreadKeyAssoc *assoc; + /* + * Run through all Thread<-->Key associations + * for this key. + * + * While we hold at least one of the locks guarding + * the assoc, we know that the assoc pointed to by + * key->threads is valid. + */ + while ((assoc = (ThreadKeyAssoc *) key->threads) != NULL) + { + ptw32_thread_t * thread = assoc->thread; + + if (assoc == NULL) + { + /* Finished */ + break; + } + + if (pthread_mutex_lock (&(thread->threadLock)) == 0) + { + /* + * Since we are starting at the head of the key's threads + * chain, this will also point key->threads at the next assoc. + * While we hold key->keyLock, no other thread can insert + * a new assoc via pthread_setspecific. + */ + ptw32_tkAssocDestroy (assoc); + (void) pthread_mutex_unlock (&(thread->threadLock)); + } + else + { + /* Thread or lock is no longer valid? */ + ptw32_tkAssocDestroy (assoc); + } + } + pthread_mutex_unlock (&(key->keyLock)); + } + + TlsFree (key->key); + if (key->destructor != NULL) + { + /* A thread could be holding the keyLock */ + while (EBUSY == pthread_mutex_destroy (&(key->keyLock))) + { + Sleep(1); // Ugly. + } + } + +#if defined( _DEBUG ) + memset ((char *) key, 0, sizeof (*key)); +#endif + free (key); + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_kill.c b/liblo/pthreads.2/pthread_kill.c new file mode 100644 index 0000000..89d73fa --- /dev/null +++ b/liblo/pthreads.2/pthread_kill.c @@ -0,0 +1,102 @@ +/* + * pthread_kill.c + * + * Description: + * This translation unit implements the pthread_kill routine. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * Not needed yet, but defining it should indicate clashes with build target + * environment that should be fixed. + */ +#include + +int +pthread_kill (pthread_t thread, int sig) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function requests that a signal be delivered to the + * specified thread. If sig is zero, error checking is + * performed but no signal is actually sent such that this + * function can be used to check for a valid thread ID. + * + * PARAMETERS + * thread reference to an instances of pthread_t + * sig signal. Currently only a value of 0 is supported. + * + * + * DESCRIPTION + * This function requests that a signal be delivered to the + * specified thread. If sig is zero, error checking is + * performed but no signal is actually sent such that this + * function can be used to check for a valid thread ID. + * + * RESULTS + * ESRCH the thread is not a valid thread ID, + * EINVAL the value of the signal is invalid + * or unsupported. + * 0 the signal was successfully sent. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + ptw32_thread_t * tp; + + EnterCriticalSection (&ptw32_thread_reuse_lock); + + tp = (ptw32_thread_t *) thread.p; + + if (NULL == tp + || thread.x != tp->ptHandle.x + || NULL == tp->threadH) + { + result = ESRCH; + } + + LeaveCriticalSection (&ptw32_thread_reuse_lock); + + if (0 == result && 0 != sig) + { + /* + * Currently does not support any signals. + */ + result = EINVAL; + } + + return result; + +} /* pthread_kill */ diff --git a/liblo/pthreads.2/pthread_mutex_destroy.c b/liblo/pthreads.2/pthread_mutex_destroy.c new file mode 100644 index 0000000..105f110 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutex_destroy.c @@ -0,0 +1,146 @@ +/* + * pthread_mutex_destroy.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutex_destroy (pthread_mutex_t * mutex) +{ + int result = 0; + pthread_mutex_t mx; + + /* + * Let the system deal with invalid pointers. + */ + + /* + * Check to see if we have something to delete. + */ + if (*mutex < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) + { + mx = *mutex; + + result = pthread_mutex_trylock (&mx); + + /* + * If trylock succeeded and the mutex is not recursively locked it + * can be destroyed. + */ + if (result == 0) + { + if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count) + { + /* + * FIXME!!! + * The mutex isn't held by another thread but we could still + * be too late invalidating the mutex below since another thread + * may already have entered mutex_lock and the check for a valid + * *mutex != NULL. + * + * Note that this would be an unusual situation because it is not + * common that mutexes are destroyed while they are still in + * use by other threads. + */ + *mutex = NULL; + + result = pthread_mutex_unlock (&mx); + + if (result == 0) + { + if (!CloseHandle (mx->event)) + { + *mutex = mx; + result = EINVAL; + } + else + { + free (mx); + } + } + else + { + /* + * Restore the mutex before we return the error. + */ + *mutex = mx; + } + } + else /* mx->recursive_count > 1 */ + { + /* + * The mutex must be recursive and already locked by us (this thread). + */ + mx->recursive_count--; /* Undo effect of pthread_mutex_trylock() above */ + result = EBUSY; + } + } + } + else + { + /* + * See notes in ptw32_mutex_check_need_init() above also. + */ + EnterCriticalSection (&ptw32_mutex_test_init_lock); + + /* + * Check again. + */ + if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) + { + /* + * This is all we need to do to destroy a statically + * initialised mutex that has not yet been used (initialised). + * If we get to here, another thread + * waiting to initialise this mutex will get an EINVAL. + */ + *mutex = NULL; + } + else + { + /* + * The mutex has been initialised while we were waiting + * so assume it's in use. + */ + result = EBUSY; + } + + LeaveCriticalSection (&ptw32_mutex_test_init_lock); + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_mutex_init.c b/liblo/pthreads.2/pthread_mutex_init.c new file mode 100644 index 0000000..cf0297b --- /dev/null +++ b/liblo/pthreads.2/pthread_mutex_init.c @@ -0,0 +1,104 @@ +/* + * pthread_mutex_init.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr) +{ + int result = 0; + pthread_mutex_t mx; + + if (mutex == NULL) + { + return EINVAL; + } + + if (attr != NULL + && *attr != NULL && (*attr)->pshared == PTHREAD_PROCESS_SHARED) + { + /* + * Creating mutex that can be shared between + * processes. + */ +#if _POSIX_THREAD_PROCESS_SHARED >= 0 + + /* + * Not implemented yet. + */ + +#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet. + +#else + + return ENOSYS; + +#endif /* _POSIX_THREAD_PROCESS_SHARED */ + + } + + mx = (pthread_mutex_t) calloc (1, sizeof (*mx)); + + if (mx == NULL) + { + result = ENOMEM; + } + else + { + mx->lock_idx = 0; + mx->recursive_count = 0; + mx->kind = (attr == NULL || *attr == NULL + ? PTHREAD_MUTEX_DEFAULT : (*attr)->kind); + mx->ownerThread.p = NULL; + + mx->event = CreateEvent (NULL, PTW32_FALSE, /* manual reset = No */ + PTW32_FALSE, /* initial state = not signaled */ + NULL); /* event name */ + + if (0 == mx->event) + { + result = ENOSPC; + free (mx); + mx = NULL; + } + } + + *mutex = mx; + + return (result); +} diff --git a/liblo/pthreads.2/pthread_mutex_lock.c b/liblo/pthreads.2/pthread_mutex_lock.c new file mode 100644 index 0000000..2e4da24 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutex_lock.c @@ -0,0 +1,139 @@ +/* + * pthread_mutex_lock.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef _UWIN +//# include +#endif +#include "pthread.h" +#include "implement.h" + +int +pthread_mutex_lock (pthread_mutex_t * mutex) +{ + int result = 0; + pthread_mutex_t mx; + + /* + * Let the system deal with invalid pointers. + */ + if (*mutex == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static mutex. We check + * again inside the guarded section of ptw32_mutex_check_need_init() + * to avoid race conditions. + */ + if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) + { + if ((result = ptw32_mutex_check_need_init (mutex)) != 0) + { + return (result); + } + } + + mx = *mutex; + + if (mx->kind == PTHREAD_MUTEX_NORMAL) + { + if ((LONG) PTW32_INTERLOCKED_EXCHANGE( + (LPLONG) &mx->lock_idx, + (LONG) 1) != 0) + { + while ((LONG) PTW32_INTERLOCKED_EXCHANGE( + (LPLONG) &mx->lock_idx, + (LONG) -1) != 0) + { + if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) + { + result = EINVAL; + break; + } + } + } + } + else + { + pthread_t self = pthread_self(); + + if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( + (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, + (PTW32_INTERLOCKED_LONG) 1, + (PTW32_INTERLOCKED_LONG) 0) == 0) + { + mx->recursive_count = 1; + mx->ownerThread = self; + } + else + { + if (pthread_equal (mx->ownerThread, self)) + { + if (mx->kind == PTHREAD_MUTEX_RECURSIVE) + { + mx->recursive_count++; + } + else + { + result = EDEADLK; + } + } + else + { + while ((LONG) PTW32_INTERLOCKED_EXCHANGE( + (LPLONG) &mx->lock_idx, + (LONG) -1) != 0) + { + if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE)) + { + result = EINVAL; + break; + } + } + + if (0 == result) + { + mx->recursive_count = 1; + mx->ownerThread = self; + } + } + } + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_mutex_timedlock.c b/liblo/pthreads.2/pthread_mutex_timedlock.c new file mode 100644 index 0000000..ad373ba --- /dev/null +++ b/liblo/pthreads.2/pthread_mutex_timedlock.c @@ -0,0 +1,196 @@ +/* + * pthread_mutex_timedlock.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +static INLINE int +ptw32_timed_eventwait (HANDLE event, const struct timespec *abstime) + /* + * ------------------------------------------------------ + * DESCRIPTION + * This function waits on an event until signaled or until + * abstime passes. + * If abstime has passed when this routine is called then + * it returns a result to indicate this. + * + * If 'abstime' is a NULL pointer then this function will + * block until it can successfully decrease the value or + * until interrupted by a signal. + * + * This routine is not a cancelation point. + * + * RESULTS + * 0 successfully signaled, + * ETIMEDOUT abstime passed + * EINVAL 'event' is not a valid event, + * + * ------------------------------------------------------ + */ +{ + + DWORD milliseconds; + DWORD status; + + if (event == NULL) + { + return EINVAL; + } + else + { + if (abstime == NULL) + { + milliseconds = INFINITE; + } + else + { + /* + * Calculate timeout as milliseconds from current system time. + */ + milliseconds = ptw32_relmillisecs (abstime); + } + + status = WaitForSingleObject (event, milliseconds); + + if (status == WAIT_OBJECT_0) + { + return 0; + } + else if (status == WAIT_TIMEOUT) + { + return ETIMEDOUT; + } + else + { + return EINVAL; + } + } + + return 0; + +} /* ptw32_timed_semwait */ + + +int +pthread_mutex_timedlock (pthread_mutex_t * mutex, + const struct timespec *abstime) +{ + int result; + pthread_mutex_t mx; + + /* + * Let the system deal with invalid pointers. + */ + + /* + * We do a quick check to see if we need to do more work + * to initialise a static mutex. We check + * again inside the guarded section of ptw32_mutex_check_need_init() + * to avoid race conditions. + */ + if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) + { + if ((result = ptw32_mutex_check_need_init (mutex)) != 0) + { + return (result); + } + } + + mx = *mutex; + + if (mx->kind == PTHREAD_MUTEX_NORMAL) + { + if ((LONG) PTW32_INTERLOCKED_EXCHANGE( + (LPLONG) &mx->lock_idx, + (LONG) 1) != 0) + { + while ((LONG) PTW32_INTERLOCKED_EXCHANGE( + (LPLONG) &mx->lock_idx, + (LONG) -1) != 0) + { + if (0 != (result = ptw32_timed_eventwait (mx->event, abstime))) + { + return result; + } + } + } + } + else + { + pthread_t self = pthread_self(); + + if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE( + (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, + (PTW32_INTERLOCKED_LONG) 1, + (PTW32_INTERLOCKED_LONG) 0) == 0) + { + mx->recursive_count = 1; + mx->ownerThread = self; + } + else + { + if (pthread_equal (mx->ownerThread, self)) + { + if (mx->kind == PTHREAD_MUTEX_RECURSIVE) + { + mx->recursive_count++; + } + else + { + return EDEADLK; + } + } + else + { + while ((LONG) PTW32_INTERLOCKED_EXCHANGE( + (LPLONG) &mx->lock_idx, + (LONG) -1) != 0) + { + if (0 != (result = ptw32_timed_eventwait (mx->event, abstime))) + { + return result; + } + } + + mx->recursive_count = 1; + mx->ownerThread = self; + } + } + } + + return 0; +} diff --git a/liblo/pthreads.2/pthread_mutex_trylock.c b/liblo/pthreads.2/pthread_mutex_trylock.c new file mode 100644 index 0000000..048869c --- /dev/null +++ b/liblo/pthreads.2/pthread_mutex_trylock.c @@ -0,0 +1,92 @@ +/* + * pthread_mutex_trylock.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutex_trylock (pthread_mutex_t * mutex) +{ + int result = 0; + pthread_mutex_t mx; + + /* + * Let the system deal with invalid pointers. + */ + + /* + * We do a quick check to see if we need to do more work + * to initialise a static mutex. We check + * again inside the guarded section of ptw32_mutex_check_need_init() + * to avoid race conditions. + */ + if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) + { + if ((result = ptw32_mutex_check_need_init (mutex)) != 0) + { + return (result); + } + } + + mx = *mutex; + + if (0 == (LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE ( + (PTW32_INTERLOCKED_LPLONG) &mx->lock_idx, + (PTW32_INTERLOCKED_LONG) 1, + (PTW32_INTERLOCKED_LONG) 0)) + { + if (mx->kind != PTHREAD_MUTEX_NORMAL) + { + mx->recursive_count = 1; + mx->ownerThread = pthread_self (); + } + } + else + { + if (mx->kind == PTHREAD_MUTEX_RECURSIVE && + pthread_equal (mx->ownerThread, pthread_self ())) + { + mx->recursive_count++; + } + else + { + result = EBUSY; + } + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_mutex_unlock.c b/liblo/pthreads.2/pthread_mutex_unlock.c new file mode 100644 index 0000000..ab8ec65 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutex_unlock.c @@ -0,0 +1,119 @@ +/* + * pthread_mutex_unlock.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutex_unlock (pthread_mutex_t * mutex) +{ + int result = 0; + pthread_mutex_t mx; + + /* + * Let the system deal with invalid pointers. + */ + + mx = *mutex; + + /* + * If the thread calling us holds the mutex then there is no + * race condition. If another thread holds the + * lock then we shouldn't be in here. + */ + if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) + { + if (mx->kind == PTHREAD_MUTEX_NORMAL) + { + LONG idx; + + idx = (LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx, + (LONG) 0); + if (idx != 0) + { + if (idx < 0) + { + /* + * Someone may be waiting on that mutex. + */ + if (SetEvent (mx->event) == 0) + { + result = EINVAL; + } + } + } + else + { + /* + * Was not locked (so can't be owned by us). + */ + result = EPERM; + } + } + else + { + if (pthread_equal (mx->ownerThread, pthread_self ())) + { + if (mx->kind != PTHREAD_MUTEX_RECURSIVE + || 0 == --mx->recursive_count) + { + mx->ownerThread.p = NULL; + + if ((LONG) PTW32_INTERLOCKED_EXCHANGE ((LPLONG) &mx->lock_idx, + (LONG) 0) < 0) + { + /* Someone may be waiting on that mutex */ + if (SetEvent (mx->event) == 0) + { + result = EINVAL; + } + } + } + } + else + { + result = EPERM; + } + } + } + else + { + result = EINVAL; + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_mutexattr_destroy.c b/liblo/pthreads.2/pthread_mutexattr_destroy.c new file mode 100644 index 0000000..5821f41 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_destroy.c @@ -0,0 +1,83 @@ +/* + * pthread_mutexattr_destroy.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutexattr_destroy (pthread_mutexattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Destroys a mutex attributes object. The object can + * no longer be used. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_mutexattr_t + * + * + * DESCRIPTION + * Destroys a mutex attributes object. The object can + * no longer be used. + * + * NOTES: + * 1) Does not affect mutexes created using 'attr' + * + * RESULTS + * 0 successfully released attr, + * EINVAL 'attr' is invalid. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if (attr == NULL || *attr == NULL) + { + result = EINVAL; + } + else + { + pthread_mutexattr_t ma = *attr; + + *attr = NULL; + free (ma); + } + + return (result); +} /* pthread_mutexattr_destroy */ diff --git a/liblo/pthreads.2/pthread_mutexattr_getkind_np.c b/liblo/pthreads.2/pthread_mutexattr_getkind_np.c new file mode 100644 index 0000000..51508fe --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_getkind_np.c @@ -0,0 +1,44 @@ +/* + * pthread_mutexattr_getkind_np.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +int +pthread_mutexattr_getkind_np (pthread_mutexattr_t * attr, int *kind) +{ + return pthread_mutexattr_gettype (attr, kind); +} diff --git a/liblo/pthreads.2/pthread_mutexattr_getpshared.c b/liblo/pthreads.2/pthread_mutexattr_getpshared.c new file mode 100644 index 0000000..64d1952 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_getpshared.c @@ -0,0 +1,95 @@ +/* + * pthread_mutexattr_getpshared.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Determine whether mutexes created with 'attr' can be + * shared between processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_mutexattr_t + * + * pshared + * will be set to one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * + * DESCRIPTION + * Mutexes creatd with 'attr' can be shared between + * processes if pthread_mutex_t variable is allocated + * in memory shared by these processes. + * NOTES: + * 1) pshared mutexes MUST be allocated in shared + * memory. + * 2) The following macro is defined if shared mutexes + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully retrieved attribute, + * EINVAL 'attr' is invalid, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) && (pshared != NULL)) + { + *pshared = (*attr)->pshared; + result = 0; + } + else + { + result = EINVAL; + } + + return (result); + +} /* pthread_mutexattr_getpshared */ diff --git a/liblo/pthreads.2/pthread_mutexattr_gettype.c b/liblo/pthreads.2/pthread_mutexattr_gettype.c new file mode 100644 index 0000000..f05bb68 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_gettype.c @@ -0,0 +1,56 @@ +/* + * pthread_mutexattr_gettype.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind) +{ + int result = 0; + + if (attr != NULL && *attr != NULL && kind != NULL) + { + *kind = (*attr)->kind; + } + else + { + result = EINVAL; + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_mutexattr_init.c b/liblo/pthreads.2/pthread_mutexattr_init.c new file mode 100644 index 0000000..3e7a1a2 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_init.c @@ -0,0 +1,86 @@ +/* + * pthread_mutexattr_init.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutexattr_init (pthread_mutexattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Initializes a mutex attributes object with default + * attributes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_mutexattr_t + * + * + * DESCRIPTION + * Initializes a mutex attributes object with default + * attributes. + * + * NOTES: + * 1) Used to define mutex types + * + * RESULTS + * 0 successfully initialized attr, + * ENOMEM insufficient memory for attr. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + pthread_mutexattr_t ma; + + ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma)); + + if (ma == NULL) + { + result = ENOMEM; + } + else + { + ma->pshared = PTHREAD_PROCESS_PRIVATE; + ma->kind = PTHREAD_MUTEX_DEFAULT; + } + + *attr = ma; + + return (result); +} /* pthread_mutexattr_init */ diff --git a/liblo/pthreads.2/pthread_mutexattr_setkind_np.c b/liblo/pthreads.2/pthread_mutexattr_setkind_np.c new file mode 100644 index 0000000..25549dd --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_setkind_np.c @@ -0,0 +1,44 @@ +/* + * pthread_mutexattr_setkind_np.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +int +pthread_mutexattr_setkind_np (pthread_mutexattr_t * attr, int kind) +{ + return pthread_mutexattr_settype (attr, kind); +} diff --git a/liblo/pthreads.2/pthread_mutexattr_setpshared.c b/liblo/pthreads.2/pthread_mutexattr_setpshared.c new file mode 100644 index 0000000..7ca78d1 --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_setpshared.c @@ -0,0 +1,119 @@ +/* + * pthread_mutexattr_setpshared.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Mutexes created with 'attr' can be shared between + * processes if pthread_mutex_t variable is allocated + * in memory shared by these processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_mutexattr_t + * + * pshared + * must be one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * DESCRIPTION + * Mutexes creatd with 'attr' can be shared between + * processes if pthread_mutex_t variable is allocated + * in memory shared by these processes. + * + * NOTES: + * 1) pshared mutexes MUST be allocated in shared + * memory. + * + * 2) The following macro is defined if shared mutexes + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully set attribute, + * EINVAL 'attr' or pshared is invalid, + * ENOSYS PTHREAD_PROCESS_SHARED not supported, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) && + ((pshared == PTHREAD_PROCESS_SHARED) || + (pshared == PTHREAD_PROCESS_PRIVATE))) + { + if (pshared == PTHREAD_PROCESS_SHARED) + { + +#if !defined( _POSIX_THREAD_PROCESS_SHARED ) + + result = ENOSYS; + pshared = PTHREAD_PROCESS_PRIVATE; + +#else + + result = 0; + +#endif /* _POSIX_THREAD_PROCESS_SHARED */ + + } + else + { + result = 0; + } + + (*attr)->pshared = pshared; + } + else + { + result = EINVAL; + } + + return (result); + +} /* pthread_mutexattr_setpshared */ diff --git a/liblo/pthreads.2/pthread_mutexattr_settype.c b/liblo/pthreads.2/pthread_mutexattr_settype.c new file mode 100644 index 0000000..62f77ba --- /dev/null +++ b/liblo/pthreads.2/pthread_mutexattr_settype.c @@ -0,0 +1,143 @@ +/* + * pthread_mutexattr_settype.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind) + /* + * ------------------------------------------------------ + * + * DOCPUBLIC + * The pthread_mutexattr_settype() and + * pthread_mutexattr_gettype() functions respectively set and + * get the mutex type attribute. This attribute is set in the + * type parameter to these functions. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_mutexattr_t + * + * type + * must be one of: + * + * PTHREAD_MUTEX_DEFAULT + * + * PTHREAD_MUTEX_NORMAL + * + * PTHREAD_MUTEX_ERRORCHECK + * + * PTHREAD_MUTEX_RECURSIVE + * + * DESCRIPTION + * The pthread_mutexattr_settype() and + * pthread_mutexattr_gettype() functions respectively set and + * get the mutex type attribute. This attribute is set in the + * type parameter to these functions. The default value of the + * type attribute is PTHREAD_MUTEX_DEFAULT. + * + * The type of mutex is contained in the type attribute of the + * mutex attributes. Valid mutex types include: + * + * PTHREAD_MUTEX_NORMAL + * This type of mutex does not detect deadlock. A + * thread attempting to relock this mutex without + * first unlocking it will deadlock. Attempting to + * unlock a mutex locked by a different thread + * results in undefined behavior. Attempting to + * unlock an unlocked mutex results in undefined + * behavior. + * + * PTHREAD_MUTEX_ERRORCHECK + * This type of mutex provides error checking. A + * thread attempting to relock this mutex without + * first unlocking it will return with an error. A + * thread attempting to unlock a mutex which another + * thread has locked will return with an error. A + * thread attempting to unlock an unlocked mutex will + * return with an error. + * + * PTHREAD_MUTEX_DEFAULT + * Same as PTHREAD_MUTEX_NORMAL. + * + * PTHREAD_MUTEX_RECURSIVE + * A thread attempting to relock this mutex without + * first unlocking it will succeed in locking the + * mutex. The relocking deadlock which can occur with + * mutexes of type PTHREAD_MUTEX_NORMAL cannot occur + * with this type of mutex. Multiple locks of this + * mutex require the same number of unlocks to + * release the mutex before another thread can + * acquire the mutex. A thread attempting to unlock a + * mutex which another thread has locked will return + * with an error. A thread attempting to unlock an + * unlocked mutex will return with an error. This + * type of mutex is only supported for mutexes whose + * process shared attribute is + * PTHREAD_PROCESS_PRIVATE. + * + * RESULTS + * 0 successfully set attribute, + * EINVAL 'attr' or 'type' is invalid, + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if ((attr != NULL && *attr != NULL)) + { + switch (kind) + { + case PTHREAD_MUTEX_FAST_NP: + case PTHREAD_MUTEX_RECURSIVE_NP: + case PTHREAD_MUTEX_ERRORCHECK_NP: + (*attr)->kind = kind; + break; + default: + result = EINVAL; + break; + } + } + else + { + result = EINVAL; + } + + return (result); +} /* pthread_mutexattr_settype */ diff --git a/liblo/pthreads.2/pthread_num_processors_np.c b/liblo/pthreads.2/pthread_num_processors_np.c new file mode 100644 index 0000000..897a1b2 --- /dev/null +++ b/liblo/pthreads.2/pthread_num_processors_np.c @@ -0,0 +1,56 @@ +/* + * pthread_num_processors_np.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * pthread_num_processors_np() + * + * Get the number of CPUs available to the process. + */ +int +pthread_num_processors_np (void) +{ + int count; + + if (ptw32_getprocessors (&count) != 0) + { + count = 1; + } + + return (count); +} diff --git a/liblo/pthreads.2/pthread_once.c b/liblo/pthreads.2/pthread_once.c new file mode 100644 index 0000000..19e63b4 --- /dev/null +++ b/liblo/pthreads.2/pthread_once.c @@ -0,0 +1,86 @@ +/* + * pthread_once.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +static void PTW32_CDECL +ptw32_once_on_init_cancel (void * arg) +{ + /* when the initting thread is cancelled we have to release the lock */ + ptw32_mcs_local_node_t *node = (ptw32_mcs_local_node_t *)arg; + ptw32_mcs_lock_release(node); +} + +int +pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) +{ + if (once_control == NULL || init_routine == NULL) + { + return EINVAL; + } + + if (!InterlockedExchangeAdd((LPLONG)&once_control->done, 0)) /* MBR fence */ + { + ptw32_mcs_local_node_t node; + + ptw32_mcs_lock_acquire((ptw32_mcs_lock_t *)&once_control->lock, &node); + + if (!once_control->done) + { + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + + pthread_cleanup_push(ptw32_once_on_init_cancel, (void *)&node); + (*init_routine)(); + pthread_cleanup_pop(0); + +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + once_control->done = PTW32_TRUE; + } + + ptw32_mcs_lock_release(&node); + } + + return 0; + +} /* pthread_once */ diff --git a/liblo/pthreads.2/pthread_once.x b/liblo/pthreads.2/pthread_once.x new file mode 100644 index 0000000..1d9197d --- /dev/null +++ b/liblo/pthreads.2/pthread_once.x @@ -0,0 +1,204 @@ +/* + * pthread_once.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +static void PTW32_CDECL +ptw32_once_init_routine_cleanup(void * arg) +{ + pthread_once_t * once_control = (pthread_once_t *) arg; + + /* + * Continue to direct new threads into the wait path until the waiter that we + * release can reset state to INIT. + */ + (void) PTW32_INTERLOCKED_EXCHANGE((LPLONG)&once_control->state, (LONG)PTW32_ONCE_CANCELLED); + + if (InterlockedExchangeAdd((LPLONG)&once_control->semaphore, 0L)) /* MBR fence */ + { + ReleaseSemaphore(once_control->semaphore, 1, NULL); + } +} + +int +pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * If any thread in a process with a once_control parameter + * makes a call to pthread_once(), the first call will summon + * the init_routine(), but subsequent calls will not. The + * once_control parameter determines whether the associated + * initialization routine has been called. The init_routine() + * is complete upon return of pthread_once(). + * This function guarantees that one and only one thread + * executes the initialization routine, init_routine when + * access is controlled by the pthread_once_t control + * key. + * + * pthread_once() is not a cancelation point, but the init_routine + * can be. If it's cancelled then the effect on the once_control is + * as if pthread_once had never been entered. + * + * + * PARAMETERS + * once_control + * pointer to an instance of pthread_once_t + * + * init_routine + * pointer to an initialization routine + * + * + * DESCRIPTION + * See above. + * + * RESULTS + * 0 success, + * EINVAL once_control or init_routine is NULL + * + * ------------------------------------------------------ + */ +{ + int result; + int state; + HANDLE sema; + + if (once_control == NULL || init_routine == NULL) + { + result = EINVAL; + goto FAIL0; + } + else + { + result = 0; + } + + while ((state = (int) + PTW32_INTERLOCKED_COMPARE_EXCHANGE((PTW32_INTERLOCKED_LPLONG)&once_control->state, + (PTW32_INTERLOCKED_LONG)PTW32_ONCE_STARTED, + (PTW32_INTERLOCKED_LONG)PTW32_ONCE_INIT)) + != PTW32_ONCE_DONE) + { + if (PTW32_ONCE_INIT == state) + { + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + + pthread_cleanup_push(ptw32_once_init_routine_cleanup, (void *) once_control); + (*init_routine)(); + pthread_cleanup_pop(0); + +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + (void) PTW32_INTERLOCKED_EXCHANGE((LPLONG)&once_control->state, + (LONG)PTW32_ONCE_DONE); + + /* + * we didn't create the semaphore. + * it is only there if there is someone waiting. + */ + if (InterlockedExchangeAdd((LPLONG)&once_control->semaphore, 0L)) /* MBR fence */ + { + ReleaseSemaphore(once_control->semaphore, + once_control->numSemaphoreUsers, NULL); + } + } + else + { + if (1 == InterlockedIncrement((LPLONG)&once_control->numSemaphoreUsers)) + +// if (!InterlockedExchangeAdd((LPLONG)&once_control->semaphore, 0L)) /* MBR fence */ + { + sema = CreateSemaphore(NULL, 0, INT_MAX, NULL); + + if (PTW32_INTERLOCKED_COMPARE_EXCHANGE((PTW32_INTERLOCKED_LPLONG)&once_control->semaphore, + (PTW32_INTERLOCKED_LONG)sema, + (PTW32_INTERLOCKED_LONG)0)) + { + CloseHandle(sema); + } + } + + /* + * If initter was cancelled then state is CANCELLED. + * Until state is reset to INIT, all new threads will enter the wait path. + * The woken waiter, if it exists, will also re-enter the wait path, but + * either it or a new thread will reset state = INIT here, continue around the Wait, + * and become the new initter. Any thread that is suspended in the wait path before + * this point will hit this check. Any thread suspended between this check and + * the Wait will wait on a valid semaphore, and possibly continue through it + * if the cancellation handler has incremented (released) it and there were + * no waiters. + */ + (void) PTW32_INTERLOCKED_COMPARE_EXCHANGE((PTW32_INTERLOCKED_LPLONG)&once_control->state, + (PTW32_INTERLOCKED_LONG)PTW32_ONCE_INIT, + (PTW32_INTERLOCKED_LONG)PTW32_ONCE_CANCELLED); + + /* + * Check 'state' again in case the initting thread has finished + * and left before seeing that there was a semaphore. + */ + if (InterlockedExchangeAdd((LPLONG)&once_control->state, 0L) >= PTW32_ONCE_STARTED) + { + WaitForSingleObject(once_control->semaphore, INFINITE); + } + + if (0 == InterlockedDecrement((LPLONG)&once_control->numSemaphoreUsers)) + { + /* we were last */ + if ((sema = + (HANDLE) PTW32_INTERLOCKED_EXCHANGE((LPLONG)&once_control->semaphore, (LONG)0))) + { + CloseHandle(sema); + } + } + } + } + + /* + * ------------ + * Failure Code + * ------------ + */ +FAIL0: + return (result); +} /* pthread_once */ diff --git a/liblo/pthreads.2/pthread_rwlock_destroy.c b/liblo/pthreads.2/pthread_rwlock_destroy.c new file mode 100644 index 0000000..7b6a6de --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_destroy.c @@ -0,0 +1,143 @@ +/* + * pthread_rwlock_destroy.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_destroy (pthread_rwlock_t * rwlock) +{ + pthread_rwlock_t rwl; + int result = 0, result1 = 0, result2 = 0; + + if (rwlock == NULL || *rwlock == NULL) + { + return EINVAL; + } + + if (*rwlock != PTHREAD_RWLOCK_INITIALIZER) + { + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) + { + return result; + } + + if ((result = + pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + + /* + * Check whether any threads own/wait for the lock (wait for ex.access); + * report "BUSY" if so. + */ + if (rwl->nExclusiveAccessCount > 0 + || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount) + { + result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); + result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + result2 = EBUSY; + } + else + { + rwl->nMagic = 0; + + if ((result = + pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + pthread_mutex_unlock (&rwl->mtxExclusiveAccess); + return result; + } + + if ((result = + pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0) + { + return result; + } + + *rwlock = NULL; /* Invalidate rwlock before anything else */ + result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted)); + result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted)); + result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess)); + (void) free (rwl); + } + } + else + { + /* + * See notes in ptw32_rwlock_check_need_init() above also. + */ + EnterCriticalSection (&ptw32_rwlock_test_init_lock); + + /* + * Check again. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + /* + * This is all we need to do to destroy a statically + * initialised rwlock that has not yet been used (initialised). + * If we get to here, another thread + * waiting to initialise this rwlock will get an EINVAL. + */ + *rwlock = NULL; + } + else + { + /* + * The rwlock has been initialised while we were waiting + * so assume it's in use. + */ + result = EBUSY; + } + + LeaveCriticalSection (&ptw32_rwlock_test_init_lock); + } + + return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); +} diff --git a/liblo/pthreads.2/pthread_rwlock_init.c b/liblo/pthreads.2/pthread_rwlock_init.c new file mode 100644 index 0000000..e49439d --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_init.c @@ -0,0 +1,110 @@ +/* + * pthread_rwlock_init.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_init (pthread_rwlock_t * rwlock, + const pthread_rwlockattr_t * attr) +{ + int result; + pthread_rwlock_t rwl = 0; + + if (rwlock == NULL) + { + return EINVAL; + } + + if (attr != NULL && *attr != NULL) + { + result = EINVAL; /* Not supported */ + goto DONE; + } + + rwl = (pthread_rwlock_t) calloc (1, sizeof (*rwl)); + + if (rwl == NULL) + { + result = ENOMEM; + goto DONE; + } + + rwl->nSharedAccessCount = 0; + rwl->nExclusiveAccessCount = 0; + rwl->nCompletedSharedAccessCount = 0; + + result = pthread_mutex_init (&rwl->mtxExclusiveAccess, NULL); + if (result != 0) + { + goto FAIL0; + } + + result = pthread_mutex_init (&rwl->mtxSharedAccessCompleted, NULL); + if (result != 0) + { + goto FAIL1; + } + + result = pthread_cond_init (&rwl->cndSharedAccessCompleted, NULL); + if (result != 0) + { + goto FAIL2; + } + + rwl->nMagic = PTW32_RWLOCK_MAGIC; + + result = 0; + goto DONE; + +FAIL2: + (void) pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted)); + +FAIL1: + (void) pthread_mutex_destroy (&(rwl->mtxExclusiveAccess)); + +FAIL0: + (void) free (rwl); + rwl = NULL; + +DONE: + *rwlock = rwl; + + return result; +} diff --git a/liblo/pthreads.2/pthread_rwlock_rdlock.c b/liblo/pthreads.2/pthread_rwlock_rdlock.c new file mode 100644 index 0000000..3c493ea --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_rdlock.c @@ -0,0 +1,103 @@ +/* + * pthread_rwlock_rdlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_rdlock (pthread_rwlock_t * rwlock) +{ + int result; + pthread_rwlock_t rwl; + + if (rwlock == NULL || *rwlock == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static rwlock. We check + * again inside the guarded section of ptw32_rwlock_check_need_init() + * to avoid race conditions. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + result = ptw32_rwlock_check_need_init (rwlock); + + if (result != 0 && result != EBUSY) + { + return result; + } + } + + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) + { + return result; + } + + if (++rwl->nSharedAccessCount == INT_MAX) + { + if ((result = + pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + + rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; + rwl->nCompletedSharedAccessCount = 0; + + if ((result = + pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + } + + return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))); +} diff --git a/liblo/pthreads.2/pthread_rwlock_timedrdlock.c b/liblo/pthreads.2/pthread_rwlock_timedrdlock.c new file mode 100644 index 0000000..92373ea --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_timedrdlock.c @@ -0,0 +1,110 @@ +/* + * pthread_rwlock_timedrdlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock, + const struct timespec *abstime) +{ + int result; + pthread_rwlock_t rwl; + + if (rwlock == NULL || *rwlock == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static rwlock. We check + * again inside the guarded section of ptw32_rwlock_check_need_init() + * to avoid race conditions. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + result = ptw32_rwlock_check_need_init (rwlock); + + if (result != 0 && result != EBUSY) + { + return result; + } + } + + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if ((result = + pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0) + { + return result; + } + + if (++rwl->nSharedAccessCount == INT_MAX) + { + if ((result = + pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted), + abstime)) != 0) + { + if (result == ETIMEDOUT) + { + ++rwl->nCompletedSharedAccessCount; + } + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + + rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; + rwl->nCompletedSharedAccessCount = 0; + + if ((result = + pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + } + + return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))); +} diff --git a/liblo/pthreads.2/pthread_rwlock_timedwrlock.c b/liblo/pthreads.2/pthread_rwlock_timedwrlock.c new file mode 100644 index 0000000..ca5e537 --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_timedwrlock.c @@ -0,0 +1,140 @@ +/* + * pthread_rwlock_timedwrlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock, + const struct timespec *abstime) +{ + int result; + pthread_rwlock_t rwl; + + if (rwlock == NULL || *rwlock == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static rwlock. We check + * again inside the guarded section of ptw32_rwlock_check_need_init() + * to avoid race conditions. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + result = ptw32_rwlock_check_need_init (rwlock); + + if (result != 0 && result != EBUSY) + { + return result; + } + } + + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if ((result = + pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0) + { + return result; + } + + if ((result = + pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted), + abstime)) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + + if (rwl->nExclusiveAccessCount == 0) + { + if (rwl->nCompletedSharedAccessCount > 0) + { + rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; + rwl->nCompletedSharedAccessCount = 0; + } + + if (rwl->nSharedAccessCount > 0) + { + rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount; + + /* + * This routine may be a cancelation point + * according to POSIX 1003.1j section 18.1.2. + */ +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl); + + do + { + result = + pthread_cond_timedwait (&(rwl->cndSharedAccessCompleted), + &(rwl->mtxSharedAccessCompleted), + abstime); + } + while (result == 0 && rwl->nCompletedSharedAccessCount < 0); + + pthread_cleanup_pop ((result != 0) ? 1 : 0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + if (result == 0) + { + rwl->nSharedAccessCount = 0; + } + } + } + + if (result == 0) + { + rwl->nExclusiveAccessCount++; + } + + return result; +} diff --git a/liblo/pthreads.2/pthread_rwlock_tryrdlock.c b/liblo/pthreads.2/pthread_rwlock_tryrdlock.c new file mode 100644 index 0000000..fbca910 --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_tryrdlock.c @@ -0,0 +1,103 @@ +/* + * pthread_rwlock_tryrdlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_tryrdlock (pthread_rwlock_t * rwlock) +{ + int result; + pthread_rwlock_t rwl; + + if (rwlock == NULL || *rwlock == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static rwlock. We check + * again inside the guarded section of ptw32_rwlock_check_need_init() + * to avoid race conditions. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + result = ptw32_rwlock_check_need_init (rwlock); + + if (result != 0 && result != EBUSY) + { + return result; + } + } + + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0) + { + return result; + } + + if (++rwl->nSharedAccessCount == INT_MAX) + { + if ((result = + pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + + rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; + rwl->nCompletedSharedAccessCount = 0; + + if ((result = + pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + } + + return (pthread_mutex_unlock (&rwl->mtxExclusiveAccess)); +} diff --git a/liblo/pthreads.2/pthread_rwlock_trywrlock.c b/liblo/pthreads.2/pthread_rwlock_trywrlock.c new file mode 100644 index 0000000..e17adb3 --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_trywrlock.c @@ -0,0 +1,123 @@ +/* + * pthread_rwlock_trywrlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_trywrlock (pthread_rwlock_t * rwlock) +{ + int result, result1; + pthread_rwlock_t rwl; + + if (rwlock == NULL || *rwlock == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static rwlock. We check + * again inside the guarded section of ptw32_rwlock_check_need_init() + * to avoid race conditions. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + result = ptw32_rwlock_check_need_init (rwlock); + + if (result != 0 && result != EBUSY) + { + return result; + } + } + + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0) + { + return result; + } + + if ((result = + pthread_mutex_trylock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return ((result1 != 0) ? result1 : result); + } + + if (rwl->nExclusiveAccessCount == 0) + { + if (rwl->nCompletedSharedAccessCount > 0) + { + rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; + rwl->nCompletedSharedAccessCount = 0; + } + + if (rwl->nSharedAccessCount > 0) + { + if ((result = + pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + + if ((result = + pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) == 0) + { + result = EBUSY; + } + } + else + { + rwl->nExclusiveAccessCount = 1; + } + } + else + { + result = EBUSY; + } + + return result; +} diff --git a/liblo/pthreads.2/pthread_rwlock_unlock.c b/liblo/pthreads.2/pthread_rwlock_unlock.c new file mode 100644 index 0000000..2a5c84b --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_unlock.c @@ -0,0 +1,94 @@ +/* + * pthread_rwlock_unlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_unlock (pthread_rwlock_t * rwlock) +{ + int result, result1; + pthread_rwlock_t rwl; + + if (rwlock == NULL || *rwlock == NULL) + { + return (EINVAL); + } + + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + /* + * Assume any race condition here is harmless. + */ + return 0; + } + + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if (rwl->nExclusiveAccessCount == 0) + { + if ((result = + pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + return result; + } + + if (++rwl->nCompletedSharedAccessCount == 0) + { + result = pthread_cond_signal (&(rwl->cndSharedAccessCompleted)); + } + + result1 = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); + } + else + { + rwl->nExclusiveAccessCount--; + + result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); + result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + + } + + return ((result != 0) ? result : result1); +} diff --git a/liblo/pthreads.2/pthread_rwlock_wrlock.c b/liblo/pthreads.2/pthread_rwlock_wrlock.c new file mode 100644 index 0000000..789c5aa --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlock_wrlock.c @@ -0,0 +1,134 @@ +/* + * pthread_rwlock_wrlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlock_wrlock (pthread_rwlock_t * rwlock) +{ + int result; + pthread_rwlock_t rwl; + + if (rwlock == NULL || *rwlock == NULL) + { + return EINVAL; + } + + /* + * We do a quick check to see if we need to do more work + * to initialise a static rwlock. We check + * again inside the guarded section of ptw32_rwlock_check_need_init() + * to avoid race conditions. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + result = ptw32_rwlock_check_need_init (rwlock); + + if (result != 0 && result != EBUSY) + { + return result; + } + } + + rwl = *rwlock; + + if (rwl->nMagic != PTW32_RWLOCK_MAGIC) + { + return EINVAL; + } + + if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) + { + return result; + } + + if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) + { + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); + return result; + } + + if (rwl->nExclusiveAccessCount == 0) + { + if (rwl->nCompletedSharedAccessCount > 0) + { + rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount; + rwl->nCompletedSharedAccessCount = 0; + } + + if (rwl->nSharedAccessCount > 0) + { + rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount; + + /* + * This routine may be a cancelation point + * according to POSIX 1003.1j section 18.1.2. + */ +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl); + + do + { + result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted), + &(rwl->mtxSharedAccessCompleted)); + } + while (result == 0 && rwl->nCompletedSharedAccessCount < 0); + + pthread_cleanup_pop ((result != 0) ? 1 : 0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + if (result == 0) + { + rwl->nSharedAccessCount = 0; + } + } + } + + if (result == 0) + { + rwl->nExclusiveAccessCount++; + } + + return result; +} diff --git a/liblo/pthreads.2/pthread_rwlockattr_destroy.c b/liblo/pthreads.2/pthread_rwlockattr_destroy.c new file mode 100644 index 0000000..c1971b5 --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlockattr_destroy.c @@ -0,0 +1,85 @@ +/* + * pthread_rwlockattr_destroy.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Destroys a rwlock attributes object. The object can + * no longer be used. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_rwlockattr_t + * + * + * DESCRIPTION + * Destroys a rwlock attributes object. The object can + * no longer be used. + * + * NOTES: + * 1) Does not affect rwlockss created using 'attr' + * + * RESULTS + * 0 successfully released attr, + * EINVAL 'attr' is invalid. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + + if (attr == NULL || *attr == NULL) + { + result = EINVAL; + } + else + { + pthread_rwlockattr_t rwa = *attr; + + *attr = NULL; + free (rwa); + } + + return (result); +} /* pthread_rwlockattr_destroy */ diff --git a/liblo/pthreads.2/pthread_rwlockattr_getpshared.c b/liblo/pthreads.2/pthread_rwlockattr_getpshared.c new file mode 100644 index 0000000..098e925 --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlockattr_getpshared.c @@ -0,0 +1,98 @@ +/* + * pthread_rwlockattr_getpshared.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Determine whether rwlocks created with 'attr' can be + * shared between processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_rwlockattr_t + * + * pshared + * will be set to one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * + * DESCRIPTION + * Rwlocks creatd with 'attr' can be shared between + * processes if pthread_rwlock_t variable is allocated + * in memory shared by these processes. + * NOTES: + * 1) pshared rwlocks MUST be allocated in shared + * memory. + * 2) The following macro is defined if shared rwlocks + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully retrieved attribute, + * EINVAL 'attr' is invalid, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) && (pshared != NULL)) + { + *pshared = (*attr)->pshared; + result = 0; + } + else + { + result = EINVAL; + } + + return (result); + +} /* pthread_rwlockattr_getpshared */ diff --git a/liblo/pthreads.2/pthread_rwlockattr_init.c b/liblo/pthreads.2/pthread_rwlockattr_init.c new file mode 100644 index 0000000..3126118 --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlockattr_init.c @@ -0,0 +1,84 @@ +/* + * pthread_rwlockattr_init.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlockattr_init (pthread_rwlockattr_t * attr) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Initializes a rwlock attributes object with default + * attributes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_rwlockattr_t + * + * + * DESCRIPTION + * Initializes a rwlock attributes object with default + * attributes. + * + * RESULTS + * 0 successfully initialized attr, + * ENOMEM insufficient memory for attr. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + pthread_rwlockattr_t rwa; + + rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa)); + + if (rwa == NULL) + { + result = ENOMEM; + } + else + { + rwa->pshared = PTHREAD_PROCESS_PRIVATE; + } + + *attr = rwa; + + return (result); +} /* pthread_rwlockattr_init */ diff --git a/liblo/pthreads.2/pthread_rwlockattr_setpshared.c b/liblo/pthreads.2/pthread_rwlockattr_setpshared.c new file mode 100644 index 0000000..b0c8160 --- /dev/null +++ b/liblo/pthreads.2/pthread_rwlockattr_setpshared.c @@ -0,0 +1,121 @@ +/* + * pthread_rwlockattr_setpshared.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include + +#include "pthread.h" +#include "implement.h" + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Rwlocks created with 'attr' can be shared between + * processes if pthread_rwlock_t variable is allocated + * in memory shared by these processes. + * + * PARAMETERS + * attr + * pointer to an instance of pthread_rwlockattr_t + * + * pshared + * must be one of: + * + * PTHREAD_PROCESS_SHARED + * May be shared if in shared memory + * + * PTHREAD_PROCESS_PRIVATE + * Cannot be shared. + * + * DESCRIPTION + * Rwlocks creatd with 'attr' can be shared between + * processes if pthread_rwlock_t variable is allocated + * in memory shared by these processes. + * + * NOTES: + * 1) pshared rwlocks MUST be allocated in shared + * memory. + * + * 2) The following macro is defined if shared rwlocks + * are supported: + * _POSIX_THREAD_PROCESS_SHARED + * + * RESULTS + * 0 successfully set attribute, + * EINVAL 'attr' or pshared is invalid, + * ENOSYS PTHREAD_PROCESS_SHARED not supported, + * + * ------------------------------------------------------ + */ +{ + int result; + + if ((attr != NULL && *attr != NULL) && + ((pshared == PTHREAD_PROCESS_SHARED) || + (pshared == PTHREAD_PROCESS_PRIVATE))) + { + if (pshared == PTHREAD_PROCESS_SHARED) + { + +#if !defined( _POSIX_THREAD_PROCESS_SHARED ) + + result = ENOSYS; + pshared = PTHREAD_PROCESS_PRIVATE; + +#else + + result = 0; + +#endif /* _POSIX_THREAD_PROCESS_SHARED */ + + } + else + { + result = 0; + } + + (*attr)->pshared = pshared; + } + else + { + result = EINVAL; + } + + return (result); + +} /* pthread_rwlockattr_setpshared */ diff --git a/liblo/pthreads.2/pthread_self.c b/liblo/pthreads.2/pthread_self.c new file mode 100644 index 0000000..fb2899c --- /dev/null +++ b/liblo/pthreads.2/pthread_self.c @@ -0,0 +1,138 @@ +/* + * pthread_self.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +pthread_t +pthread_self (void) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function returns a reference to the current running + * thread. + * + * PARAMETERS + * N/A + * + * + * DESCRIPTION + * This function returns a reference to the current running + * thread. + * + * RESULTS + * pthread_t reference to the current thread + * + * ------------------------------------------------------ + */ +{ + pthread_t self; + pthread_t nil = {NULL, 0}; + ptw32_thread_t * sp; + +#ifdef _UWIN + if (!ptw32_selfThreadKey) + return nil; +#endif + + sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); + + if (sp != NULL) + { + self = sp->ptHandle; + } + else + { + /* + * Need to create an implicit 'self' for the currently + * executing thread. + */ + self = ptw32_new (); + sp = (ptw32_thread_t *) self.p; + + if (sp != NULL) + { + /* + * This is a non-POSIX thread which has chosen to call + * a POSIX threads function for some reason. We assume that + * it isn't joinable, but we do assume that it's + * (deferred) cancelable. + */ + sp->implicit = 1; + sp->detachState = PTHREAD_CREATE_DETACHED; + sp->thread = GetCurrentThreadId (); + +#ifdef NEED_DUPLICATEHANDLE + /* + * DuplicateHandle does not exist on WinCE. + * + * NOTE: + * GetCurrentThread only returns a pseudo-handle + * which is only valid in the current thread context. + * Therefore, you should not pass the handle to + * other threads for whatever purpose. + */ + sp->threadH = GetCurrentThread (); +#else + if (!DuplicateHandle (GetCurrentProcess (), + GetCurrentThread (), + GetCurrentProcess (), + &sp->threadH, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + /* + * Should not do this, but we have no alternative if + * we can't get a Win32 thread handle. + * Thread structs are never freed. + */ + ptw32_threadReusePush (self); + return nil; + } +#endif + + /* + * No need to explicitly serialise access to sched_priority + * because the new handle is not yet public. + */ + sp->sched_priority = GetThreadPriority (sp->threadH); + + pthread_setspecific (ptw32_selfThreadKey, (void *) sp); + } + } + + return (self); + +} /* pthread_self */ diff --git a/liblo/pthreads.2/pthread_setcancelstate.c b/liblo/pthreads.2/pthread_setcancelstate.c new file mode 100644 index 0000000..d3efaae --- /dev/null +++ b/liblo/pthreads.2/pthread_setcancelstate.c @@ -0,0 +1,124 @@ +/* + * pthread_setcancelstate.c + * + * Description: + * POSIX thread functions related to thread cancellation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_setcancelstate (int state, int *oldstate) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function atomically sets the calling thread's + * cancelability state to 'state' and returns the previous + * cancelability state at the location referenced by + * 'oldstate' + * + * PARAMETERS + * state, + * oldstate + * PTHREAD_CANCEL_ENABLE + * cancellation is enabled, + * + * PTHREAD_CANCEL_DISABLE + * cancellation is disabled + * + * + * DESCRIPTION + * This function atomically sets the calling thread's + * cancelability state to 'state' and returns the previous + * cancelability state at the location referenced by + * 'oldstate'. + * + * NOTES: + * 1) Use to disable cancellation around 'atomic' code that + * includes cancellation points + * + * COMPATIBILITY ADDITIONS + * If 'oldstate' is NULL then the previous state is not returned + * but the function still succeeds. (Solaris) + * + * RESULTS + * 0 successfully set cancelability type, + * EINVAL 'state' is invalid + * + * ------------------------------------------------------ + */ +{ + int result = 0; + pthread_t self = pthread_self (); + ptw32_thread_t * sp = (ptw32_thread_t *) self.p; + + if (sp == NULL + || (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)) + { + return EINVAL; + } + + /* + * Lock for async-cancel safety. + */ + (void) pthread_mutex_lock (&sp->cancelLock); + + if (oldstate != NULL) + { + *oldstate = sp->cancelState; + } + + sp->cancelState = state; + + /* + * Check if there is a pending asynchronous cancel + */ + if (state == PTHREAD_CANCEL_ENABLE + && sp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS + && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0) + { + sp->state = PThreadStateCanceling; + sp->cancelState = PTHREAD_CANCEL_DISABLE; + ResetEvent (sp->cancelEvent); + (void) pthread_mutex_unlock (&sp->cancelLock); + ptw32_throw (PTW32_EPS_CANCEL); + + /* Never reached */ + } + + (void) pthread_mutex_unlock (&sp->cancelLock); + + return (result); + +} /* pthread_setcancelstate */ diff --git a/liblo/pthreads.2/pthread_setcanceltype.c b/liblo/pthreads.2/pthread_setcanceltype.c new file mode 100644 index 0000000..558ddc4 --- /dev/null +++ b/liblo/pthreads.2/pthread_setcanceltype.c @@ -0,0 +1,125 @@ +/* + * pthread_setcanceltype.c + * + * Description: + * POSIX thread functions related to thread cancellation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_setcanceltype (int type, int *oldtype) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function atomically sets the calling thread's + * cancelability type to 'type' and returns the previous + * cancelability type at the location referenced by + * 'oldtype' + * + * PARAMETERS + * type, + * oldtype + * PTHREAD_CANCEL_DEFERRED + * only deferred cancelation is allowed, + * + * PTHREAD_CANCEL_ASYNCHRONOUS + * Asynchronous cancellation is allowed + * + * + * DESCRIPTION + * This function atomically sets the calling thread's + * cancelability type to 'type' and returns the previous + * cancelability type at the location referenced by + * 'oldtype' + * + * NOTES: + * 1) Use with caution; most code is not safe for use + * with asynchronous cancelability. + * + * COMPATIBILITY ADDITIONS + * If 'oldtype' is NULL then the previous type is not returned + * but the function still succeeds. (Solaris) + * + * RESULTS + * 0 successfully set cancelability type, + * EINVAL 'type' is invalid + * + * ------------------------------------------------------ + */ +{ + int result = 0; + pthread_t self = pthread_self (); + ptw32_thread_t * sp = (ptw32_thread_t *) self.p; + + if (sp == NULL + || (type != PTHREAD_CANCEL_DEFERRED + && type != PTHREAD_CANCEL_ASYNCHRONOUS)) + { + return EINVAL; + } + + /* + * Lock for async-cancel safety. + */ + (void) pthread_mutex_lock (&sp->cancelLock); + + if (oldtype != NULL) + { + *oldtype = sp->cancelType; + } + + sp->cancelType = type; + + /* + * Check if there is a pending asynchronous cancel + */ + if (sp->cancelState == PTHREAD_CANCEL_ENABLE + && type == PTHREAD_CANCEL_ASYNCHRONOUS + && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0) + { + sp->state = PThreadStateCanceling; + sp->cancelState = PTHREAD_CANCEL_DISABLE; + ResetEvent (sp->cancelEvent); + (void) pthread_mutex_unlock (&sp->cancelLock); + ptw32_throw (PTW32_EPS_CANCEL); + + /* Never reached */ + } + + (void) pthread_mutex_unlock (&sp->cancelLock); + + return (result); + +} /* pthread_setcanceltype */ diff --git a/liblo/pthreads.2/pthread_setconcurrency.c b/liblo/pthreads.2/pthread_setconcurrency.c new file mode 100644 index 0000000..b1693da --- /dev/null +++ b/liblo/pthreads.2/pthread_setconcurrency.c @@ -0,0 +1,53 @@ +/* + * pthread_setconcurrency.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_setconcurrency (int level) +{ + if (level < 0) + { + return EINVAL; + } + else + { + ptw32_concurrency = level; + return 0; + } +} diff --git a/liblo/pthreads.2/pthread_setschedparam.c b/liblo/pthreads.2/pthread_setschedparam.c new file mode 100644 index 0000000..0e705bb --- /dev/null +++ b/liblo/pthreads.2/pthread_setschedparam.c @@ -0,0 +1,125 @@ +/* + * sched_setschedparam.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param) +{ + int result; + + /* Validate the thread id. */ + result = pthread_kill (thread, 0); + if (0 != result) + { + return result; + } + + /* Validate the scheduling policy. */ + if (policy < SCHED_MIN || policy > SCHED_MAX) + { + return EINVAL; + } + + /* Ensure the policy is SCHED_OTHER. */ + if (policy != SCHED_OTHER) + { + return ENOTSUP; + } + + return (ptw32_setthreadpriority (thread, policy, param->sched_priority)); +} + + +int +ptw32_setthreadpriority (pthread_t thread, int policy, int priority) +{ + int prio; + int result; + ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; + + prio = priority; + + /* Validate priority level. */ + if (prio < sched_get_priority_min (policy) || + prio > sched_get_priority_max (policy)) + { + return EINVAL; + } + +#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) +/* WinCE */ +#else +/* Everything else */ + + if (THREAD_PRIORITY_IDLE < prio && THREAD_PRIORITY_LOWEST > prio) + { + prio = THREAD_PRIORITY_LOWEST; + } + else if (THREAD_PRIORITY_TIME_CRITICAL > prio + && THREAD_PRIORITY_HIGHEST < prio) + { + prio = THREAD_PRIORITY_HIGHEST; + } + +#endif + + result = pthread_mutex_lock (&tp->threadLock); + + if (0 == result) + { + /* If this fails, the current priority is unchanged. */ + if (0 == SetThreadPriority (tp->threadH, prio)) + { + result = EINVAL; + } + else + { + /* + * Must record the thread's sched_priority as given, + * not as finally adjusted. + */ + tp->sched_priority = priority; + } + + (void) pthread_mutex_unlock (&tp->threadLock); + } + + return result; +} diff --git a/liblo/pthreads.2/pthread_setspecific.c b/liblo/pthreads.2/pthread_setspecific.c new file mode 100644 index 0000000..c3fcc29 --- /dev/null +++ b/liblo/pthreads.2/pthread_setspecific.c @@ -0,0 +1,168 @@ +/* + * pthread_setspecific.c + * + * Description: + * POSIX thread functions which implement thread-specific data (TSD). + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_setspecific (pthread_key_t key, const void *value) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function sets the value of the thread specific + * key in the calling thread. + * + * PARAMETERS + * key + * an instance of pthread_key_t + * value + * the value to set key to + * + * + * DESCRIPTION + * This function sets the value of the thread specific + * key in the calling thread. + * + * RESULTS + * 0 successfully set value + * EAGAIN could not set value + * ENOENT SERIOUS!! + * + * ------------------------------------------------------ + */ +{ + pthread_t self; + int result = 0; + + if (key != ptw32_selfThreadKey) + { + /* + * Using pthread_self will implicitly create + * an instance of pthread_t for the current + * thread if one wasn't explicitly created + */ + self = pthread_self (); + if (self.p == NULL) + { + return ENOENT; + } + } + else + { + /* + * Resolve catch-22 of registering thread with selfThread + * key + */ + ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); + + if (sp == NULL) + { + if (value == NULL) + { + return ENOENT; + } + self = *((pthread_t *) value); + } + else + { + self = sp->ptHandle; + } + } + + result = 0; + + if (key != NULL) + { + if (self.p != NULL && key->destructor != NULL && value != NULL) + { + /* + * Only require associations if we have to + * call user destroy routine. + * Don't need to locate an existing association + * when setting data to NULL for WIN32 since the + * data is stored with the operating system; not + * on the association; setting assoc to NULL short + * circuits the search. + */ + ThreadKeyAssoc *assoc; + + if (pthread_mutex_lock(&(key->keyLock)) == 0) + { + ptw32_thread_t * sp = (ptw32_thread_t *) self.p; + + (void) pthread_mutex_lock(&(sp->threadLock)); + + assoc = (ThreadKeyAssoc *) sp->keys; + /* + * Locate existing association + */ + while (assoc != NULL) + { + if (assoc->key == key) + { + /* + * Association already exists + */ + break; + } + assoc = assoc->nextKey; + } + + /* + * create an association if not found + */ + if (assoc == NULL) + { + result = ptw32_tkAssocCreate (sp, key); + } + + (void) pthread_mutex_unlock(&(sp->threadLock)); + } + (void) pthread_mutex_unlock(&(key->keyLock)); + } + + if (result == 0) + { + if (!TlsSetValue (key->key, (LPVOID) value)) + { + result = EAGAIN; + } + } + } + + return (result); +} /* pthread_setspecific */ diff --git a/liblo/pthreads.2/pthread_spin_destroy.c b/liblo/pthreads.2/pthread_spin_destroy.c new file mode 100644 index 0000000..80f2482 --- /dev/null +++ b/liblo/pthreads.2/pthread_spin_destroy.c @@ -0,0 +1,112 @@ +/* + * pthread_spin_destroy.c + * + * Description: + * This translation unit implements spin lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_spin_destroy (pthread_spinlock_t * lock) +{ + register pthread_spinlock_t s; + int result = 0; + + if (lock == NULL || *lock == NULL) + { + return EINVAL; + } + + if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER) + { + if (s->interlock == PTW32_SPIN_USE_MUTEX) + { + result = pthread_mutex_destroy (&(s->u.mutex)); + } + else if ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED != + PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) + & (s->interlock), + (PTW32_INTERLOCKED_LONG) + PTW32_OBJECT_INVALID, + (PTW32_INTERLOCKED_LONG) + PTW32_SPIN_UNLOCKED)) + { + result = EINVAL; + } + + if (0 == result) + { + /* + * We are relying on the application to ensure that all other threads + * have finished with the spinlock before destroying it. + */ + *lock = NULL; + (void) free (s); + } + } + else + { + /* + * See notes in ptw32_spinlock_check_need_init() above also. + */ + EnterCriticalSection (&ptw32_spinlock_test_init_lock); + + /* + * Check again. + */ + if (*lock == PTHREAD_SPINLOCK_INITIALIZER) + { + /* + * This is all we need to do to destroy a statically + * initialised spinlock that has not yet been used (initialised). + * If we get to here, another thread + * waiting to initialise this mutex will get an EINVAL. + */ + *lock = NULL; + } + else + { + /* + * The spinlock has been initialised while we were waiting + * so assume it's in use. + */ + result = EBUSY; + } + + LeaveCriticalSection (&ptw32_spinlock_test_init_lock); + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_spin_init.c b/liblo/pthreads.2/pthread_spin_init.c new file mode 100644 index 0000000..5d574f3 --- /dev/null +++ b/liblo/pthreads.2/pthread_spin_init.c @@ -0,0 +1,123 @@ +/* + * pthread_spin_init.c + * + * Description: + * This translation unit implements spin lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_spin_init (pthread_spinlock_t * lock, int pshared) +{ + pthread_spinlock_t s; + int cpus = 0; + int result = 0; + + if (lock == NULL) + { + return EINVAL; + } + + if (0 != ptw32_getprocessors (&cpus)) + { + cpus = 1; + } + + if (cpus > 1) + { + if (pshared == PTHREAD_PROCESS_SHARED) + { + /* + * Creating spinlock that can be shared between + * processes. + */ +#if _POSIX_THREAD_PROCESS_SHARED >= 0 + + /* + * Not implemented yet. + */ + +#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet. + +#else + + return ENOSYS; + +#endif /* _POSIX_THREAD_PROCESS_SHARED */ + + } + } + + s = (pthread_spinlock_t) calloc (1, sizeof (*s)); + + if (s == NULL) + { + return ENOMEM; + } + + if (cpus > 1) + { + s->u.cpus = cpus; + s->interlock = PTW32_SPIN_UNLOCKED; + } + else + { + pthread_mutexattr_t ma; + result = pthread_mutexattr_init (&ma); + + if (0 == result) + { + ma->pshared = pshared; + result = pthread_mutex_init (&(s->u.mutex), &ma); + if (0 == result) + { + s->interlock = PTW32_SPIN_USE_MUTEX; + } + } + (void) pthread_mutexattr_destroy (&ma); + } + + if (0 == result) + { + *lock = s; + } + else + { + (void) free (s); + *lock = NULL; + } + + return (result); +} diff --git a/liblo/pthreads.2/pthread_spin_lock.c b/liblo/pthreads.2/pthread_spin_lock.c new file mode 100644 index 0000000..7e9bd2e --- /dev/null +++ b/liblo/pthreads.2/pthread_spin_lock.c @@ -0,0 +1,83 @@ +/* + * pthread_spin_lock.c + * + * Description: + * This translation unit implements spin lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_spin_lock (pthread_spinlock_t * lock) +{ + register pthread_spinlock_t s; + + if (NULL == lock || NULL == *lock) + { + return (EINVAL); + } + + if (*lock == PTHREAD_SPINLOCK_INITIALIZER) + { + int result; + + if ((result = ptw32_spinlock_check_need_init (lock)) != 0) + { + return (result); + } + } + + s = *lock; + + while ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED == + PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) & + (s->interlock), + (PTW32_INTERLOCKED_LONG) + PTW32_SPIN_LOCKED, + (PTW32_INTERLOCKED_LONG) + PTW32_SPIN_UNLOCKED)) + { + } + + if (s->interlock == PTW32_SPIN_LOCKED) + { + return 0; + } + else if (s->interlock == PTW32_SPIN_USE_MUTEX) + { + return pthread_mutex_lock (&(s->u.mutex)); + } + + return EINVAL; +} diff --git a/liblo/pthreads.2/pthread_spin_trylock.c b/liblo/pthreads.2/pthread_spin_trylock.c new file mode 100644 index 0000000..caba165 --- /dev/null +++ b/liblo/pthreads.2/pthread_spin_trylock.c @@ -0,0 +1,80 @@ +/* + * pthread_spin_trylock.c + * + * Description: + * This translation unit implements spin lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_spin_trylock (pthread_spinlock_t * lock) +{ + register pthread_spinlock_t s; + + if (NULL == lock || NULL == *lock) + { + return (EINVAL); + } + + if (*lock == PTHREAD_SPINLOCK_INITIALIZER) + { + int result; + + if ((result = ptw32_spinlock_check_need_init (lock)) != 0) + { + return (result); + } + } + + s = *lock; + + switch ((long) + PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) & + (s->interlock), + (PTW32_INTERLOCKED_LONG) + PTW32_SPIN_LOCKED, + (PTW32_INTERLOCKED_LONG) + PTW32_SPIN_UNLOCKED)) + { + case PTW32_SPIN_UNLOCKED: + return 0; + case PTW32_SPIN_LOCKED: + return EBUSY; + case PTW32_SPIN_USE_MUTEX: + return pthread_mutex_trylock (&(s->u.mutex)); + } + + return EINVAL; +} diff --git a/liblo/pthreads.2/pthread_spin_unlock.c b/liblo/pthreads.2/pthread_spin_unlock.c new file mode 100644 index 0000000..c147816 --- /dev/null +++ b/liblo/pthreads.2/pthread_spin_unlock.c @@ -0,0 +1,75 @@ +/* + * pthread_spin_unlock.c + * + * Description: + * This translation unit implements spin lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +pthread_spin_unlock (pthread_spinlock_t * lock) +{ + register pthread_spinlock_t s; + + if (NULL == lock || NULL == *lock) + { + return (EINVAL); + } + + s = *lock; + + if (s == PTHREAD_SPINLOCK_INITIALIZER) + { + return EPERM; + } + + switch ((long) + PTW32_INTERLOCKED_COMPARE_EXCHANGE ((PTW32_INTERLOCKED_LPLONG) & + (s->interlock), + (PTW32_INTERLOCKED_LONG) + PTW32_SPIN_UNLOCKED, + (PTW32_INTERLOCKED_LONG) + PTW32_SPIN_LOCKED)) + { + case PTW32_SPIN_LOCKED: + return 0; + case PTW32_SPIN_UNLOCKED: + return EPERM; + case PTW32_SPIN_USE_MUTEX: + return pthread_mutex_unlock (&(s->u.mutex)); + } + + return EINVAL; +} diff --git a/liblo/pthreads.2/pthread_testcancel.c b/liblo/pthreads.2/pthread_testcancel.c new file mode 100644 index 0000000..10a846e --- /dev/null +++ b/liblo/pthreads.2/pthread_testcancel.c @@ -0,0 +1,102 @@ +/* + * pthread_testcancel.c + * + * Description: + * POSIX thread functions related to thread cancellation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +void +pthread_testcancel (void) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function creates a deferred cancellation point + * in the calling thread. The call has no effect if the + * current cancelability state is + * PTHREAD_CANCEL_DISABLE + * + * PARAMETERS + * N/A + * + * + * DESCRIPTION + * This function creates a deferred cancellation point + * in the calling thread. The call has no effect if the + * current cancelability state is + * PTHREAD_CANCEL_DISABLE + * + * NOTES: + * 1) Cancellation is asynchronous. Use pthread_join + * to wait for termination of thread if necessary + * + * RESULTS + * N/A + * + * ------------------------------------------------------ + */ +{ + pthread_t self = pthread_self (); + ptw32_thread_t * sp = (ptw32_thread_t *) self.p; + + if (sp == NULL) + { + return; + } + + /* + * Pthread_cancel() will have set sp->state to PThreadStateCancelPending + * and set an event, so no need to enter kernel space if + * sp->state != PThreadStateCancelPending - that only slows us down. + */ + if (sp->state != PThreadStateCancelPending) + { + return; + } + + (void) pthread_mutex_lock (&sp->cancelLock); + + if (sp->cancelState != PTHREAD_CANCEL_DISABLE) + { + ResetEvent(sp->cancelEvent); + sp->state = PThreadStateCanceling; + (void) pthread_mutex_unlock (&sp->cancelLock); + sp->cancelState = PTHREAD_CANCEL_DISABLE; + (void) pthread_mutex_unlock (&sp->cancelLock); + ptw32_throw (PTW32_EPS_CANCEL); + } + + (void) pthread_mutex_unlock (&sp->cancelLock); +} /* pthread_testcancel */ diff --git a/liblo/pthreads.2/pthread_timechange_handler_np.c b/liblo/pthreads.2/pthread_timechange_handler_np.c new file mode 100644 index 0000000..99a4d61 --- /dev/null +++ b/liblo/pthreads.2/pthread_timechange_handler_np.c @@ -0,0 +1,107 @@ +/* + * pthread_timechange_handler_np.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * Notes on handling system time adjustments (especially negative ones). + * --------------------------------------------------------------------- + * + * This solution was suggested by Alexander Terekhov, but any errors + * in the implementation are mine - [Ross Johnson] + * + * 1) The problem: threads doing a timedwait on a CV may expect to timeout + * at a specific absolute time according to a system timer. If the + * system clock is adjusted backwards then those threads sleep longer than + * expected. Also, pthreads-win32 converts absolute times to intervals in + * order to make use of the underlying Win32, and so waiting threads may + * awake before their proper abstimes. + * + * 2) We aren't able to distinquish between threads on timed or untimed waits, + * so we wake them all at the time of the adjustment so that they can + * re-evaluate their conditions and re-compute their timeouts. + * + * 3) We rely on correctly written applications for this to work. Specifically, + * they must be able to deal properly with spurious wakeups. That is, + * they must re-test their condition upon wakeup and wait again if + * the condition is not satisfied. + */ + +void * +pthread_timechange_handler_np (void *arg) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * Broadcasts all CVs to force re-evaluation and + * new timeouts if required. + * + * PARAMETERS + * NONE + * + * + * DESCRIPTION + * Broadcasts all CVs to force re-evaluation and + * new timeouts if required. + * + * This routine may be passed directly to pthread_create() + * as a new thread in order to run asynchronously. + * + * + * RESULTS + * 0 successfully broadcast all CVs + * EAGAIN Not all CVs were broadcast + * + * ------------------------------------------------------ + */ +{ + int result = 0; + pthread_cond_t cv; + + EnterCriticalSection (&ptw32_cond_list_lock); + + cv = ptw32_cond_list_head; + + while (cv != NULL && 0 == result) + { + result = pthread_cond_broadcast (&cv); + cv = cv->next; + } + + LeaveCriticalSection (&ptw32_cond_list_lock); + + return (void *) (result != 0 ? EAGAIN : 0); +} diff --git a/liblo/pthreads.2/pthread_win32_attach_detach_np.c b/liblo/pthreads.2/pthread_win32_attach_detach_np.c new file mode 100644 index 0000000..ebff33c --- /dev/null +++ b/liblo/pthreads.2/pthread_win32_attach_detach_np.c @@ -0,0 +1,303 @@ +/* + * pthread_win32_attach_detach_np.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * Handle to kernel32.dll + */ +static HINSTANCE ptw32_h_kernel32; + +/* + * Handle to quserex.dll + */ +static HINSTANCE ptw32_h_quserex; + +BOOL +pthread_win32_process_attach_np () +{ + BOOL result = TRUE; + DWORD_PTR vProcessCPUs; + DWORD_PTR vSystemCPUs; + + result = ptw32_processInitialize (); + +#ifdef _UWIN + pthread_count++; +#endif + + ptw32_features = 0; + + +#if defined(NEED_PROCESS_AFFINITY_MASK) + + ptw32_smp_system = PTW32_FALSE; + +#else + + if (GetProcessAffinityMask (GetCurrentProcess (), + &vProcessCPUs, &vSystemCPUs)) + { + int CPUs = 0; + DWORD_PTR bit; + + for (bit = 1; bit != 0; bit <<= 1) + { + if (vSystemCPUs & bit) + { + CPUs++; + } + } + ptw32_smp_system = (CPUs > 1); + } + else + { + ptw32_smp_system = PTW32_FALSE; + } + +#endif + +#ifdef WINCE + + /* + * Load COREDLL and try to get address of InterlockedCompareExchange + */ + ptw32_h_kernel32 = LoadLibrary (TEXT ("COREDLL.DLL")); + +#else + + /* + * Load KERNEL32 and try to get address of InterlockedCompareExchange + */ + ptw32_h_kernel32 = LoadLibrary (TEXT ("KERNEL32.DLL")); + +#endif + + ptw32_interlocked_compare_exchange = + (PTW32_INTERLOCKED_LONG (WINAPI *) + (PTW32_INTERLOCKED_LPLONG, PTW32_INTERLOCKED_LONG, + PTW32_INTERLOCKED_LONG)) +#if defined(NEED_UNICODE_CONSTS) + GetProcAddress (ptw32_h_kernel32, + (const TCHAR *) TEXT ("InterlockedCompareExchange")); +#else + GetProcAddress (ptw32_h_kernel32, (LPCSTR) "InterlockedCompareExchange"); +#endif + + if (ptw32_interlocked_compare_exchange == NULL) + { + ptw32_interlocked_compare_exchange = ptw32_InterlockedCompareExchange; + + /* + * If InterlockedCompareExchange is not being used, then free + * the kernel32.dll handle now, rather than leaving it until + * DLL_PROCESS_DETACH. + * + * Note: this is not a pedantic exercise in freeing unused + * resources! It is a work-around for a bug in Windows 95 + * (see microsoft knowledge base article, Q187684) which + * does Bad Things when FreeLibrary is called within + * the DLL_PROCESS_DETACH code, in certain situations. + * Since w95 just happens to be a platform which does not + * provide InterlockedCompareExchange, the bug will be + * effortlessly avoided. + */ + (void) FreeLibrary (ptw32_h_kernel32); + ptw32_h_kernel32 = 0; + } + else + { + ptw32_features |= PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE; + } + + /* + * Load QUSEREX.DLL and try to get address of QueueUserAPCEx + */ + ptw32_h_quserex = LoadLibrary (TEXT ("QUSEREX.DLL")); + + if (ptw32_h_quserex != NULL) + { + ptw32_register_cancelation = (DWORD (*)(PAPCFUNC, HANDLE, DWORD)) +#if defined(NEED_UNICODE_CONSTS) + GetProcAddress (ptw32_h_quserex, + (const TCHAR *) TEXT ("QueueUserAPCEx")); +#else + GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx"); +#endif + } + + if (NULL == ptw32_register_cancelation) + { + ptw32_register_cancelation = ptw32_RegisterCancelation; + + if (ptw32_h_quserex != NULL) + { + (void) FreeLibrary (ptw32_h_quserex); + } + ptw32_h_quserex = 0; + } + else + { + /* Initialise QueueUserAPCEx */ + BOOL (*queue_user_apc_ex_init) (VOID); + + queue_user_apc_ex_init = (BOOL (*)(VOID)) +#if defined(NEED_UNICODE_CONSTS) + GetProcAddress (ptw32_h_quserex, + (const TCHAR *) TEXT ("QueueUserAPCEx_Init")); +#else + GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Init"); +#endif + + if (queue_user_apc_ex_init == NULL || !queue_user_apc_ex_init ()) + { + ptw32_register_cancelation = ptw32_RegisterCancelation; + + (void) FreeLibrary (ptw32_h_quserex); + ptw32_h_quserex = 0; + } + } + + if (ptw32_h_quserex) + { + ptw32_features |= PTW32_ALERTABLE_ASYNC_CANCEL; + } + + return result; +} + + +BOOL +pthread_win32_process_detach_np () +{ + if (ptw32_processInitialized) + { + ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); + + if (sp != NULL) + { + /* + * Detached threads have their resources automatically + * cleaned up upon exit (others must be 'joined'). + */ + if (sp->detachState == PTHREAD_CREATE_DETACHED) + { + ptw32_threadDestroy (sp->ptHandle); + TlsSetValue (ptw32_selfThreadKey->key, NULL); + } + } + + /* + * The DLL is being unmapped from the process's address space + */ + ptw32_processTerminate (); + + if (ptw32_h_quserex) + { + /* Close QueueUserAPCEx */ + BOOL (*queue_user_apc_ex_fini) (VOID); + + queue_user_apc_ex_fini = (BOOL (*)(VOID)) +#if defined(NEED_UNICODE_CONSTS) + GetProcAddress (ptw32_h_quserex, + (const TCHAR *) TEXT ("QueueUserAPCEx_Fini")); +#else + GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Fini"); +#endif + + if (queue_user_apc_ex_fini != NULL) + { + (void) queue_user_apc_ex_fini (); + } + (void) FreeLibrary (ptw32_h_quserex); + } + + if (ptw32_h_kernel32) + { + (void) FreeLibrary (ptw32_h_kernel32); + } + } + + return TRUE; +} + +BOOL +pthread_win32_thread_attach_np () +{ + return TRUE; +} + +BOOL +pthread_win32_thread_detach_np () +{ + if (ptw32_processInitialized) + { + /* + * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle + * unnecessarily. + */ + ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); + + if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle. + { + ptw32_callUserDestroyRoutines (sp->ptHandle); + + (void) pthread_mutex_lock (&sp->cancelLock); + sp->state = PThreadStateLast; + /* + * If the thread is joinable at this point then it MUST be joined + * or detached explicitly by the application. + */ + (void) pthread_mutex_unlock (&sp->cancelLock); + + if (sp->detachState == PTHREAD_CREATE_DETACHED) + { + ptw32_threadDestroy (sp->ptHandle); + + TlsSetValue (ptw32_selfThreadKey->key, NULL); + } + } + } + + return TRUE; +} + +BOOL +pthread_win32_test_features_np (int feature_mask) +{ + return ((ptw32_features & feature_mask) == feature_mask); +} diff --git a/liblo/pthreads.2/ptw32_InterlockedCompareExchange.c b/liblo/pthreads.2/ptw32_InterlockedCompareExchange.c new file mode 100644 index 0000000..c446548 --- /dev/null +++ b/liblo/pthreads.2/ptw32_InterlockedCompareExchange.c @@ -0,0 +1,303 @@ +/* + * ptw32_InterlockedCompareExchange.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +/* + * ptw32_InterlockedCompareExchange -- + * + * Originally needed because W9x doesn't support InterlockedCompareExchange. + * We now use this version wherever possible so we can inline it. + */ + +PTW32_INTERLOCKED_LONG WINAPI +ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location, + PTW32_INTERLOCKED_LONG value, + PTW32_INTERLOCKED_LONG comparand) +{ + +#if defined(__WATCOMC__) +/* Don't report that result is not assigned a value before being referenced */ +#pragma disable_message (200) +#endif + + PTW32_INTERLOCKED_LONG result; + + /* + * Using the LOCK prefix on uni-processor machines is significantly slower + * and it is not necessary. The overhead of the conditional below is + * negligible in comparison. Since an optimised DLL will inline this + * routine, this will be faster than calling the system supplied + * Interlocked routine, which appears to avoid the LOCK prefix on + * uniprocessor systems. So one DLL works for all systems. + */ + if (ptw32_smp_system) + +/* *INDENT-OFF* */ + +#if defined(_M_IX86) || defined(_X86_) + +#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32)) +#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG + { + _asm { + PUSH ecx + PUSH edx + MOV ecx,dword ptr [location] + MOV edx,dword ptr [value] + MOV eax,dword ptr [comparand] + LOCK CMPXCHG dword ptr [ecx],edx + MOV dword ptr [result], eax + POP edx + POP ecx + } + } + else + { + _asm { + PUSH ecx + PUSH edx + MOV ecx,dword ptr [location] + MOV edx,dword ptr [value] + MOV eax,dword ptr [comparand] + CMPXCHG dword ptr [ecx],edx + MOV dword ptr [result], eax + POP edx + POP ecx + } + } + +#elif defined(__GNUC__) +#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG + + { + __asm__ __volatile__ + ( + "lock\n\t" + "cmpxchgl %2,%1" /* if (EAX == [location]) */ + /* [location] = value */ + /* else */ + /* EAX = [location] */ + :"=a" (result) + :"m" (*location), "r" (value), "a" (comparand)); + } + else + { + __asm__ __volatile__ + ( + "cmpxchgl %2,%1" /* if (EAX == [location]) */ + /* [location] = value */ + /* else */ + /* EAX = [location] */ + :"=a" (result) + :"m" (*location), "r" (value), "a" (comparand)); + } + +#endif + +#else + + /* + * If execution gets to here then we're running on a currently + * unsupported processor or compiler. + */ + + result = 0; + +#endif + +/* *INDENT-ON* */ + + return result; + +#if defined(__WATCOMC__) +#pragma enable_message (200) +#endif + +} + +/* + * ptw32_InterlockedExchange -- + * + * We now use this version wherever possible so we can inline it. + */ + +LONG WINAPI +ptw32_InterlockedExchange (LPLONG location, + LONG value) +{ + +#if defined(__WATCOMC__) +/* Don't report that result is not assigned a value before being referenced */ +#pragma disable_message (200) +#endif + + LONG result; + + /* + * The XCHG instruction always locks the bus with or without the + * LOCKED prefix. This makes it significantly slower than CMPXCHG on + * uni-processor machines. The Windows InterlockedExchange function + * is nearly 3 times faster than the XCHG instruction, so this routine + * is not yet very useful for speeding up pthreads. + */ + if (ptw32_smp_system) + +/* *INDENT-OFF* */ + +#if defined(_M_IX86) || defined(_X86_) + +#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32)) +#define HAVE_INLINABLE_INTERLOCKED_XCHG + + { + _asm { + PUSH ecx + MOV ecx,dword ptr [location] + MOV eax,dword ptr [value] + XCHG dword ptr [ecx],eax + MOV dword ptr [result], eax + POP ecx + } + } + else + { + /* + * Faster version of XCHG for uni-processor systems because + * it doesn't lock the bus. If an interrupt or context switch + * occurs between the MOV and the CMPXCHG then the value in + * 'location' may have changed, in which case we will loop + * back to do the MOV again. + * + * FIXME! Need memory barriers for the MOV+CMPXCHG combo? + * + * Tests show that this routine has almost identical timing + * to Win32's InterlockedExchange(), which is much faster than + * using the inlined 'xchg' instruction above, so it's probably + * doing something similar to this (on UP systems). + * + * Can we do without the PUSH/POP instructions? + */ + _asm { + PUSH ecx + PUSH edx + MOV ecx,dword ptr [location] + MOV edx,dword ptr [value] +L1: MOV eax,dword ptr [ecx] + CMPXCHG dword ptr [ecx],edx + JNZ L1 + MOV dword ptr [result], eax + POP edx + POP ecx + } + } + +#elif defined(__GNUC__) +#define HAVE_INLINABLE_INTERLOCKED_XCHG + + { + __asm__ __volatile__ + ( + "xchgl %2,%1" + :"=r" (result) + :"m" (*location), "0" (value)); + } + else + { + /* + * Faster version of XCHG for uni-processor systems because + * it doesn't lock the bus. If an interrupt or context switch + * occurs between the movl and the cmpxchgl then the value in + * 'location' may have changed, in which case we will loop + * back to do the movl again. + * + * FIXME! Need memory barriers for the MOV+CMPXCHG combo? + * + * Tests show that this routine has almost identical timing + * to Win32's InterlockedExchange(), which is much faster than + * using the an inlined 'xchg' instruction, so it's probably + * doing something similar to this (on UP systems). + */ + __asm__ __volatile__ + ( + "0:\n\t" + "movl %1,%%eax\n\t" + "cmpxchgl %2,%1\n\t" + "jnz 0b" + :"=&a" (result) + :"m" (*location), "r" (value)); + } + +#endif + +#else + + /* + * If execution gets to here then we're running on a currently + * unsupported processor or compiler. + */ + + result = 0; + +#endif + +/* *INDENT-ON* */ + + return result; + +#if defined(__WATCOMC__) +#pragma enable_message (200) +#endif + +} + + +#if 1 + +#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_CMPXCHG) +#undef PTW32_INTERLOCKED_COMPARE_EXCHANGE +#define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_InterlockedCompareExchange +#endif + +#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_XCHG) +#undef PTW32_INTERLOCKED_EXCHANGE +#define PTW32_INTERLOCKED_EXCHANGE ptw32_InterlockedExchange +#endif + +#endif diff --git a/liblo/pthreads.2/ptw32_MCS_lock.c b/liblo/pthreads.2/ptw32_MCS_lock.c new file mode 100644 index 0000000..86b4d1a --- /dev/null +++ b/liblo/pthreads.2/ptw32_MCS_lock.c @@ -0,0 +1,210 @@ +/* + * ptw32_MCS_lock.c + * + * Description: + * This translation unit implements queue-based locks. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* + * About MCS locks: + * + * MCS locks are queue-based locks, where the queue nodes are local to the + * thread. The 'lock' is nothing more than a global pointer that points to + * the last node in the queue, or is NULL if the queue is empty. + * + * Originally designed for use as spin locks requiring no kernel resources + * for synchronisation or blocking, the implementation below has adapted + * the MCS spin lock for use as a general mutex that will suspend threads + * when there is lock contention. + * + * Because the queue nodes are thread-local, most of the memory read/write + * operations required to add or remove nodes from the queue do not trigger + * cache-coherence updates. + * + * Like 'named' mutexes, MCS locks consume system resources transiently - + * they are able to acquire and free resources automatically - but MCS + * locks do not require any unique 'name' to identify the lock to all + * threads using it. + * + * Usage of MCS locks: + * + * - you need a global ptw32_mcs_lock_t instance initialised to 0 or NULL. + * - you need a local thread-scope ptw32_mcs_local_node_t instance, which + * may serve several different locks but you need at least one node for + * every lock held concurrently by a thread. + * + * E.g.: + * + * ptw32_mcs_lock_t lock1 = 0; + * ptw32_mcs_lock_t lock2 = 0; + * + * void *mythread(void *arg) + * { + * ptw32_mcs_local_node_t node; + * + * ptw32_mcs_acquire (&lock1, &node); + * ptw32_mcs_release (&node); + * + * ptw32_mcs_acquire (&lock2, &node); + * ptw32_mcs_release (&node); + * { + * ptw32_mcs_local_node_t nodex; + * + * ptw32_mcs_acquire (&lock1, &node); + * ptw32_mcs_acquire (&lock2, &nodex); + * + * ptw32_mcs_release (&nodex); + * ptw32_mcs_release (&node); + * } + * return (void *)0; + * } + */ + +#include "implement.h" +#include "pthread.h" + +/* + * ptw32_mcs_flag_set -- notify another thread about an event. + * + * Set event if an event handle has been stored in the flag, and + * set flag to -1 otherwise. Note that -1 cannot be a valid handle value. + */ +INLINE void +ptw32_mcs_flag_set (LONG * flag) +{ + HANDLE e = (HANDLE)PTW32_INTERLOCKED_COMPARE_EXCHANGE( + (PTW32_INTERLOCKED_LPLONG)flag, + (PTW32_INTERLOCKED_LONG)-1, + (PTW32_INTERLOCKED_LONG)0); + if ((HANDLE)0 != e) + { + /* another thread has already stored an event handle in the flag */ + SetEvent(e); + } +} + +/* + * ptw32_mcs_flag_set -- wait for notification from another. + * + * Store an event handle in the flag and wait on it if the flag has not been + * set, and proceed without creating an event otherwise. + */ +INLINE void +ptw32_mcs_flag_wait (LONG * flag) +{ + if (0 == InterlockedExchangeAdd((LPLONG)flag, 0)) /* MBR fence */ + { + /* the flag is not set. create event. */ + + HANDLE e = CreateEvent(NULL, PTW32_FALSE, PTW32_FALSE, NULL); + + if (0 == PTW32_INTERLOCKED_COMPARE_EXCHANGE( + (PTW32_INTERLOCKED_LPLONG)flag, + (PTW32_INTERLOCKED_LONG)e, + (PTW32_INTERLOCKED_LONG)0)) + { + /* stored handle in the flag. wait on it now. */ + WaitForSingleObject(e, INFINITE); + } + + CloseHandle(e); + } +} + +/* + * ptw32_mcs_lock_acquire -- acquire an MCS lock. + * + * See: + * J. M. Mellor-Crummey and M. L. Scott. + * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors. + * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991. + */ +INLINE void +ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node) +{ + ptw32_mcs_local_node_t *pred; + + node->lock = lock; + node->nextFlag = 0; + node->readyFlag = 0; + node->next = 0; /* initially, no successor */ + + /* queue for the lock */ + pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE((LPLONG)lock, + (LONG)node); + + if (0 != pred) + { + /* the lock was not free. link behind predecessor. */ + pred->next = node; + ptw32_mcs_flag_set(&pred->nextFlag); + ptw32_mcs_flag_wait(&node->readyFlag); + } +} + +/* + * ptw32_mcs_lock_release -- release an MCS lock. + * + * See: + * J. M. Mellor-Crummey and M. L. Scott. + * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors. + * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991. + */ +INLINE void +ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node) +{ + ptw32_mcs_lock_t *lock = node->lock; + ptw32_mcs_local_node_t *next = (ptw32_mcs_local_node_t *) + InterlockedExchangeAdd((LPLONG)&node->next, 0); /* MBR fence */ + + if (0 == next) + { + /* no known successor */ + + if (node == (ptw32_mcs_local_node_t *) + PTW32_INTERLOCKED_COMPARE_EXCHANGE((PTW32_INTERLOCKED_LPLONG)lock, + (PTW32_INTERLOCKED_LONG)0, + (PTW32_INTERLOCKED_LONG)node)) + { + /* no successor, lock is free now */ + return; + } + + /* wait for successor */ + ptw32_mcs_flag_wait(&node->nextFlag); + next = (ptw32_mcs_local_node_t *) + InterlockedExchangeAdd((LPLONG)&node->next, 0); /* MBR fence */ + } + + /* pass the lock */ + ptw32_mcs_flag_set(&next->readyFlag); +} diff --git a/liblo/pthreads.2/ptw32_callUserDestroyRoutines.c b/liblo/pthreads.2/ptw32_callUserDestroyRoutines.c new file mode 100644 index 0000000..48ea23c --- /dev/null +++ b/liblo/pthreads.2/ptw32_callUserDestroyRoutines.c @@ -0,0 +1,220 @@ +/* + * ptw32_callUserDestroyRoutines.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +#ifdef __cplusplus +# if ! defined (_MSC_VER) && ! (defined(__GNUC__) && __GNUC__ < 3) && ! defined(__WATCOMC__) +using + std::terminate; +# endif +#endif + +void +ptw32_callUserDestroyRoutines (pthread_t thread) + /* + * ------------------------------------------------------------------- + * DOCPRIVATE + * + * This the routine runs through all thread keys and calls + * the destroy routines on the user's data for the current thread. + * It simulates the behaviour of POSIX Threads. + * + * PARAMETERS + * thread + * an instance of pthread_t + * + * RETURNS + * N/A + * ------------------------------------------------------------------- + */ +{ + ThreadKeyAssoc * assoc; + + if (thread.p != NULL) + { + int assocsRemaining; + int iterations = 0; + ptw32_thread_t * sp = (ptw32_thread_t *) thread.p; + + /* + * Run through all Thread<-->Key associations + * for the current thread. + * + * Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times. + */ + do + { + assocsRemaining = 0; + iterations++; + + (void) pthread_mutex_lock(&(sp->threadLock)); + /* + * The pointer to the next assoc is stored in the thread struct so that + * the assoc destructor in pthread_key_delete can adjust it + * if it deletes this assoc. This can happen if we fail to acquire + * both locks below, and are forced to release all of our locks, + * leaving open the opportunity for pthread_key_delete to get in + * before us. + */ + sp->nextAssoc = sp->keys; + (void) pthread_mutex_unlock(&(sp->threadLock)); + + for (;;) + { + void * value; + pthread_key_t k; + void (*destructor) (void *); + + /* + * First we need to serialise with pthread_key_delete by locking + * both assoc guards, but in the reverse order to our convention, + * so we must be careful to avoid deadlock. + */ + (void) pthread_mutex_lock(&(sp->threadLock)); + + if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL) + { + /* Finished */ + pthread_mutex_unlock(&(sp->threadLock)); + break; + } + else + { + /* + * assoc->key must be valid because assoc can't change or be + * removed from our chain while we hold at least one lock. If + * the assoc was on our key chain then the key has not been + * deleted yet. + * + * Now try to acquire the second lock without deadlocking. + * If we fail, we need to relinquish the first lock and the + * processor and then try to acquire them all again. + */ + if (pthread_mutex_trylock(&(assoc->key->keyLock)) == EBUSY) + { + pthread_mutex_unlock(&(sp->threadLock)); + Sleep(1); // Ugly but necessary to avoid priority effects. + /* + * Go around again. + * If pthread_key_delete has removed this assoc in the meantime, + * sp->nextAssoc will point to a new assoc. + */ + continue; + } + } + + /* We now hold both locks */ + + sp->nextAssoc = assoc->nextKey; + + /* + * Key still active; pthread_key_delete + * will block on these same mutexes before + * it can release actual key; therefore, + * key is valid and we can call the destroy + * routine; + */ + k = assoc->key; + destructor = k->destructor; + value = TlsGetValue(k->key); + TlsSetValue (k->key, NULL); + + // Every assoc->key exists and has a destructor + if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS) + { + /* + * Unlock both locks before the destructor runs. + * POSIX says pthread_key_delete can be run from destructors, + * and that probably includes with this key as target. + * pthread_setspecific can also be run from destructors and + * also needs to be able to access the assocs. + */ + (void) pthread_mutex_unlock(&(sp->threadLock)); + (void) pthread_mutex_unlock(&(k->keyLock)); + + assocsRemaining++; + +#ifdef __cplusplus + + try + { + /* + * Run the caller's cleanup routine. + */ + destructor (value); + } + catch (...) + { + /* + * A system unexpected exception has occurred + * running the user's destructor. + * We get control back within this block in case + * the application has set up it's own terminate + * handler. Since we are leaving the thread we + * should not get any internal pthreads + * exceptions. + */ + terminate (); + } + +#else /* __cplusplus */ + + /* + * Run the caller's cleanup routine. + */ + destructor (value); + +#endif /* __cplusplus */ + + } + else + { + /* + * Remove association from both the key and thread chains + * and reclaim it's memory resources. + */ + ptw32_tkAssocDestroy (assoc); + (void) pthread_mutex_unlock(&(sp->threadLock)); + (void) pthread_mutex_unlock(&(k->keyLock)); + } + } + } + while (assocsRemaining); + } +} /* ptw32_callUserDestroyRoutines */ diff --git a/liblo/pthreads.2/ptw32_calloc.c b/liblo/pthreads.2/ptw32_calloc.c new file mode 100644 index 0000000..5389335 --- /dev/null +++ b/liblo/pthreads.2/ptw32_calloc.c @@ -0,0 +1,56 @@ +/* + * ptw32_calloc.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#ifdef NEED_CALLOC +void * +ptw32_calloc (size_t n, size_t s) +{ + unsigned int m = n * s; + void *p; + + p = malloc (m); + if (p == NULL) + return NULL; + + memset (p, 0, m); + + return p; +} +#endif diff --git a/liblo/pthreads.2/ptw32_cond_check_need_init.c b/liblo/pthreads.2/ptw32_cond_check_need_init.c new file mode 100644 index 0000000..d4e1634 --- /dev/null +++ b/liblo/pthreads.2/ptw32_cond_check_need_init.c @@ -0,0 +1,94 @@ +/* + * ptw32_cond_check_need_init.c + * + * Description: + * This translation unit implements condition variables and their primitives. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +INLINE int +ptw32_cond_check_need_init (pthread_cond_t * cond) +{ + int result = 0; + + /* + * The following guarded test is specifically for statically + * initialised condition variables (via PTHREAD_OBJECT_INITIALIZER). + * + * Note that by not providing this synchronisation we risk + * introducing race conditions into applications which are + * correctly written. + * + * Approach + * -------- + * We know that static condition variables will not be PROCESS_SHARED + * so we can serialise access to internal state using + * Win32 Critical Sections rather than Win32 Mutexes. + * + * If using a single global lock slows applications down too much, + * multiple global locks could be created and hashed on some random + * value associated with each mutex, the pointer perhaps. At a guess, + * a good value for the optimal number of global locks might be + * the number of processors + 1. + * + */ + EnterCriticalSection (&ptw32_cond_test_init_lock); + + /* + * We got here possibly under race + * conditions. Check again inside the critical section. + * If a static cv has been destroyed, the application can + * re-initialise it only by calling pthread_cond_init() + * explicitly. + */ + if (*cond == PTHREAD_COND_INITIALIZER) + { + result = pthread_cond_init (cond, NULL); + } + else if (*cond == NULL) + { + /* + * The cv has been destroyed while we were waiting to + * initialise it, so the operation that caused the + * auto-initialisation should fail. + */ + result = EINVAL; + } + + LeaveCriticalSection (&ptw32_cond_test_init_lock); + + return result; +} diff --git a/liblo/pthreads.2/ptw32_getprocessors.c b/liblo/pthreads.2/ptw32_getprocessors.c new file mode 100644 index 0000000..7772ec7 --- /dev/null +++ b/liblo/pthreads.2/ptw32_getprocessors.c @@ -0,0 +1,91 @@ +/* + * ptw32_getprocessors.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +/* + * ptw32_getprocessors() + * + * Get the number of CPUs available to the process. + * + * If the available number of CPUs is 1 then pthread_spin_lock() + * will block rather than spin if the lock is already owned. + * + * pthread_spin_init() calls this routine when initialising + * a spinlock. If the number of available processors changes + * (after a call to SetProcessAffinityMask()) then only + * newly initialised spinlocks will notice. + */ +int +ptw32_getprocessors (int *count) +{ + DWORD_PTR vProcessCPUs; + DWORD_PTR vSystemCPUs; + int result = 0; + +#if defined(NEED_PROCESS_AFFINITY_MASK) + + *count = 1; + +#else + + if (GetProcessAffinityMask (GetCurrentProcess (), + &vProcessCPUs, &vSystemCPUs)) + { + DWORD_PTR bit; + int CPUs = 0; + + for (bit = 1; bit != 0; bit <<= 1) + { + if (vProcessCPUs & bit) + { + CPUs++; + } + } + *count = CPUs; + } + else + { + result = EAGAIN; + } + +#endif + + return (result); +} diff --git a/liblo/pthreads.2/ptw32_is_attr.c b/liblo/pthreads.2/ptw32_is_attr.c new file mode 100644 index 0000000..fc6fd6b --- /dev/null +++ b/liblo/pthreads.2/ptw32_is_attr.c @@ -0,0 +1,47 @@ +/* + * ptw32_is_attr.c + * + * Description: + * This translation unit implements operations on thread attribute objects. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +int +ptw32_is_attr (const pthread_attr_t * attr) +{ + /* Return 0 if the attr object is valid, non-zero otherwise. */ + + return (attr == NULL || + *attr == NULL || (*attr)->valid != PTW32_ATTR_VALID); +} diff --git a/liblo/pthreads.2/ptw32_mutex_check_need_init.c b/liblo/pthreads.2/ptw32_mutex_check_need_init.c new file mode 100644 index 0000000..4ab3e7e --- /dev/null +++ b/liblo/pthreads.2/ptw32_mutex_check_need_init.c @@ -0,0 +1,112 @@ +/* + * ptw32_mutex_check_need_init.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +static struct pthread_mutexattr_t_ ptw32_recursive_mutexattr_s = + {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_RECURSIVE}; +static struct pthread_mutexattr_t_ ptw32_errorcheck_mutexattr_s = + {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_ERRORCHECK}; +static pthread_mutexattr_t ptw32_recursive_mutexattr = &ptw32_recursive_mutexattr_s; +static pthread_mutexattr_t ptw32_errorcheck_mutexattr = &ptw32_errorcheck_mutexattr_s; + + +INLINE int +ptw32_mutex_check_need_init (pthread_mutex_t * mutex) +{ + register int result = 0; + register pthread_mutex_t mtx; + + /* + * The following guarded test is specifically for statically + * initialised mutexes (via PTHREAD_MUTEX_INITIALIZER). + * + * Note that by not providing this synchronisation we risk + * introducing race conditions into applications which are + * correctly written. + * + * Approach + * -------- + * We know that static mutexes will not be PROCESS_SHARED + * so we can serialise access to internal state using + * Win32 Critical Sections rather than Win32 Mutexes. + * + * If using a single global lock slows applications down too much, + * multiple global locks could be created and hashed on some random + * value associated with each mutex, the pointer perhaps. At a guess, + * a good value for the optimal number of global locks might be + * the number of processors + 1. + * + */ + EnterCriticalSection (&ptw32_mutex_test_init_lock); + + /* + * We got here possibly under race + * conditions. Check again inside the critical section + * and only initialise if the mutex is valid (not been destroyed). + * If a static mutex has been destroyed, the application can + * re-initialise it only by calling pthread_mutex_init() + * explicitly. + */ + mtx = *mutex; + + if (mtx == PTHREAD_MUTEX_INITIALIZER) + { + result = pthread_mutex_init (mutex, NULL); + } + else if (mtx == PTHREAD_RECURSIVE_MUTEX_INITIALIZER) + { + result = pthread_mutex_init (mutex, &ptw32_recursive_mutexattr); + } + else if (mtx == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) + { + result = pthread_mutex_init (mutex, &ptw32_errorcheck_mutexattr); + } + else if (mtx == NULL) + { + /* + * The mutex has been destroyed while we were waiting to + * initialise it, so the operation that caused the + * auto-initialisation should fail. + */ + result = EINVAL; + } + + LeaveCriticalSection (&ptw32_mutex_test_init_lock); + + return (result); +} diff --git a/liblo/pthreads.2/ptw32_new.c b/liblo/pthreads.2/ptw32_new.c new file mode 100644 index 0000000..fa4c15d --- /dev/null +++ b/liblo/pthreads.2/ptw32_new.c @@ -0,0 +1,91 @@ +/* + * ptw32_new.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +pthread_t +ptw32_new (void) +{ + pthread_t t; + pthread_t nil = {NULL, 0}; + ptw32_thread_t * tp; + + /* + * If there's a reusable pthread_t then use it. + */ + t = ptw32_threadReusePop (); + + if (NULL != t.p) + { + tp = (ptw32_thread_t *) t.p; + } + else + { + /* No reuse threads available */ + tp = (ptw32_thread_t *) calloc (1, sizeof(ptw32_thread_t)); + + if (tp == NULL) + { + return nil; + } + + /* ptHandle.p needs to point to it's parent ptw32_thread_t. */ + t.p = tp->ptHandle.p = tp; + t.x = tp->ptHandle.x = 0; + } + + /* Set default state. */ + tp->sched_priority = THREAD_PRIORITY_NORMAL; + tp->detachState = PTHREAD_CREATE_JOINABLE; + tp->cancelState = PTHREAD_CANCEL_ENABLE; + tp->cancelType = PTHREAD_CANCEL_DEFERRED; + tp->cancelLock = PTHREAD_MUTEX_INITIALIZER; + tp->threadLock = PTHREAD_MUTEX_INITIALIZER; + tp->cancelEvent = CreateEvent (0, (int) PTW32_TRUE, /* manualReset */ + (int) PTW32_FALSE, /* setSignaled */ + NULL); + + if (tp->cancelEvent == NULL) + { + ptw32_threadReusePush (tp->ptHandle); + return nil; + } + + return t; + +} diff --git a/liblo/pthreads.2/ptw32_processInitialize.c b/liblo/pthreads.2/ptw32_processInitialize.c new file mode 100644 index 0000000..075e03a --- /dev/null +++ b/liblo/pthreads.2/ptw32_processInitialize.c @@ -0,0 +1,102 @@ +/* + * ptw32_processInitialize.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +ptw32_processInitialize (void) + /* + * ------------------------------------------------------ + * DOCPRIVATE + * This function performs process wide initialization for + * the pthread library. + * + * PARAMETERS + * N/A + * + * DESCRIPTION + * This function performs process wide initialization for + * the pthread library. + * If successful, this routine sets the global variable + * ptw32_processInitialized to TRUE. + * + * RESULTS + * TRUE if successful, + * FALSE otherwise + * + * ------------------------------------------------------ + */ +{ + if (ptw32_processInitialized) + { + /* + * Ignore if already initialized. this is useful for + * programs that uses a non-dll pthread + * library. Such programs must call ptw32_processInitialize() explicitly, + * since this initialization routine is automatically called only when + * the dll is loaded. + */ + return PTW32_TRUE; + } + + ptw32_processInitialized = PTW32_TRUE; + + /* + * Initialize Keys + */ + if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) || + (pthread_key_create (&ptw32_cleanupKey, NULL) != 0)) + { + + ptw32_processTerminate (); + } + + /* + * Set up the global locks. + */ + InitializeCriticalSection (&ptw32_thread_reuse_lock); + InitializeCriticalSection (&ptw32_mutex_test_init_lock); + InitializeCriticalSection (&ptw32_cond_list_lock); + InitializeCriticalSection (&ptw32_cond_test_init_lock); + InitializeCriticalSection (&ptw32_rwlock_test_init_lock); + InitializeCriticalSection (&ptw32_spinlock_test_init_lock); + + return (ptw32_processInitialized); + +} /* processInitialize */ diff --git a/liblo/pthreads.2/ptw32_processTerminate.c b/liblo/pthreads.2/ptw32_processTerminate.c new file mode 100644 index 0000000..dd641bc --- /dev/null +++ b/liblo/pthreads.2/ptw32_processTerminate.c @@ -0,0 +1,114 @@ +/* + * ptw32_processTerminate.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +void +ptw32_processTerminate (void) + /* + * ------------------------------------------------------ + * DOCPRIVATE + * This function performs process wide termination for + * the pthread library. + * + * PARAMETERS + * N/A + * + * DESCRIPTION + * This function performs process wide termination for + * the pthread library. + * This routine sets the global variable + * ptw32_processInitialized to FALSE + * + * RESULTS + * N/A + * + * ------------------------------------------------------ + */ +{ + if (ptw32_processInitialized) + { + ptw32_thread_t * tp, * tpNext; + + if (ptw32_selfThreadKey != NULL) + { + /* + * Release ptw32_selfThreadKey + */ + pthread_key_delete (ptw32_selfThreadKey); + + ptw32_selfThreadKey = NULL; + } + + if (ptw32_cleanupKey != NULL) + { + /* + * Release ptw32_cleanupKey + */ + pthread_key_delete (ptw32_cleanupKey); + + ptw32_cleanupKey = NULL; + } + + EnterCriticalSection (&ptw32_thread_reuse_lock); + + tp = ptw32_threadReuseTop; + while (tp != PTW32_THREAD_REUSE_EMPTY) + { + tpNext = tp->prevReuse; + free (tp); + tp = tpNext; + } + + LeaveCriticalSection (&ptw32_thread_reuse_lock); + + /* + * Destroy the global locks and other objects. + */ + DeleteCriticalSection (&ptw32_spinlock_test_init_lock); + DeleteCriticalSection (&ptw32_rwlock_test_init_lock); + DeleteCriticalSection (&ptw32_cond_test_init_lock); + DeleteCriticalSection (&ptw32_cond_list_lock); + DeleteCriticalSection (&ptw32_mutex_test_init_lock); + DeleteCriticalSection (&ptw32_thread_reuse_lock); + + ptw32_processInitialized = PTW32_FALSE; + } + +} /* processTerminate */ diff --git a/liblo/pthreads.2/ptw32_relmillisecs.c b/liblo/pthreads.2/ptw32_relmillisecs.c new file mode 100644 index 0000000..a2e476f --- /dev/null +++ b/liblo/pthreads.2/ptw32_relmillisecs.c @@ -0,0 +1,120 @@ +/* + * ptw32_relmillisecs.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef _UWIN +//#include +#endif +#include "pthread.h" +#include "implement.h" +#ifndef NEED_FTIME +#include +#endif + + +INLINE DWORD +ptw32_relmillisecs (const struct timespec * abstime) +{ + const int64_t NANOSEC_PER_MILLISEC = 1000000; + const int64_t MILLISEC_PER_SEC = 1000; + DWORD milliseconds; + int64_t tmpAbsMilliseconds; + int64_t tmpCurrMilliseconds; +#ifdef NEED_FTIME + struct timespec currSysTime; + FILETIME ft; + SYSTEMTIME st; +#else /* ! NEED_FTIME */ + struct _timeb currSysTime; +#endif /* NEED_FTIME */ + + + /* + * Calculate timeout as milliseconds from current system time. + */ + + /* + * subtract current system time from abstime in a way that checks + * that abstime is never in the past, or is never equivalent to the + * defined INFINITE value (0xFFFFFFFF). + * + * Assume all integers are unsigned, i.e. cannot test if less than 0. + */ + tmpAbsMilliseconds = (int64_t)abstime->tv_sec * MILLISEC_PER_SEC; + tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC; + + /* get current system time */ + +#ifdef NEED_FTIME + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + /* + * GetSystemTimeAsFileTime(&ft); would be faster, + * but it does not exist on WinCE + */ + + ptw32_filetime_to_timespec(&ft, &currSysTime); + + tmpCurrMilliseconds = (int64_t)currSysTime.tv_sec * MILLISEC_PER_SEC; + tmpCurrMilliseconds += ((int64_t)currSysTime.tv_nsec + (NANOSEC_PER_MILLISEC/2)) + / NANOSEC_PER_MILLISEC; + +#else /* ! NEED_FTIME */ + + _ftime(&currSysTime); + + tmpCurrMilliseconds = (int64_t) currSysTime.time * MILLISEC_PER_SEC; + tmpCurrMilliseconds += (int64_t) currSysTime.millitm; + +#endif /* NEED_FTIME */ + + if (tmpAbsMilliseconds > tmpCurrMilliseconds) + { + milliseconds = (DWORD) (tmpAbsMilliseconds - tmpCurrMilliseconds); + if (milliseconds == INFINITE) + { + /* Timeouts must be finite */ + milliseconds--; + } + } + else + { + /* The abstime given is in the past */ + milliseconds = 0; + } + + return milliseconds; +} diff --git a/liblo/pthreads.2/ptw32_reuse.c b/liblo/pthreads.2/ptw32_reuse.c new file mode 100644 index 0000000..950759b --- /dev/null +++ b/liblo/pthreads.2/ptw32_reuse.c @@ -0,0 +1,147 @@ +/* + * ptw32_threadReuse.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +/* + * How it works: + * A pthread_t is a struct (2x32 bit scalar types on IA-32, 2x64 bit on IA-64) + * which is normally passed/returned by value to/from pthreads routines. + * Applications are therefore storing a copy of the struct as it is at that + * time. + * + * The original pthread_t struct plus all copies of it contain the address of + * the thread state struct ptw32_thread_t_ (p), plus a reuse counter (x). Each + * ptw32_thread_t contains the original copy of it's pthread_t. + * Once malloced, a ptw32_thread_t_ struct is not freed until the process exits. + * + * The thread reuse stack is a simple LILO stack managed through a singly + * linked list element in the ptw32_thread_t. + * + * Each time a thread is destroyed, the ptw32_thread_t address is pushed onto the + * reuse stack after it's ptHandle's reuse counter has been incremented. + * + * The following can now be said from this: + * - two pthread_t's are identical if their ptw32_thread_t reference pointers + * are equal and their reuse counters are equal. That is, + * + * equal = (a.p == b.p && a.x == b.x) + * + * - a pthread_t copy refers to a destroyed thread if the reuse counter in + * the copy is not equal to the reuse counter in the original. + * + * threadDestroyed = (copy.x != ((ptw32_thread_t *)copy.p)->ptHandle.x) + * + */ + +/* + * Pop a clean pthread_t struct off the reuse stack. + */ +pthread_t +ptw32_threadReusePop (void) +{ + pthread_t t = {NULL, 0}; + + EnterCriticalSection (&ptw32_thread_reuse_lock); + + if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop) + { + ptw32_thread_t * tp; + + tp = ptw32_threadReuseTop; + + ptw32_threadReuseTop = tp->prevReuse; + + if (PTW32_THREAD_REUSE_EMPTY == ptw32_threadReuseTop) + { + ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY; + } + + tp->prevReuse = NULL; + + t = tp->ptHandle; + } + + LeaveCriticalSection (&ptw32_thread_reuse_lock); + + return t; + +} + +/* + * Push a clean pthread_t struct onto the reuse stack. + * Must be re-initialised when reused. + * All object elements (mutexes, events etc) must have been either + * detroyed before this, or never initialised. + */ +void +ptw32_threadReusePush (pthread_t thread) +{ + ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; + pthread_t t; + + EnterCriticalSection (&ptw32_thread_reuse_lock); + + t = tp->ptHandle; + memset(tp, 0, sizeof(ptw32_thread_t)); + + /* Must restore the original POSIX handle that we just wiped. */ + tp->ptHandle = t; + + /* Bump the reuse counter now */ +#ifdef PTW32_THREAD_ID_REUSE_INCREMENT + tp->ptHandle.x += PTW32_THREAD_ID_REUSE_INCREMENT; +#else + tp->ptHandle.x++; +#endif + + tp->prevReuse = PTW32_THREAD_REUSE_EMPTY; + + if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseBottom) + { + ptw32_threadReuseBottom->prevReuse = tp; + } + else + { + ptw32_threadReuseTop = tp; + } + + ptw32_threadReuseBottom = tp; + + LeaveCriticalSection (&ptw32_thread_reuse_lock); +} diff --git a/liblo/pthreads.2/ptw32_rwlock_cancelwrwait.c b/liblo/pthreads.2/ptw32_rwlock_cancelwrwait.c new file mode 100644 index 0000000..7649a3e --- /dev/null +++ b/liblo/pthreads.2/ptw32_rwlock_cancelwrwait.c @@ -0,0 +1,50 @@ +/* + * ptw32_rwlock_cancelwrwait.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +void +ptw32_rwlock_cancelwrwait (void *arg) +{ + pthread_rwlock_t rwl = (pthread_rwlock_t) arg; + + rwl->nSharedAccessCount = -rwl->nCompletedSharedAccessCount; + rwl->nCompletedSharedAccessCount = 0; + + (void) pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted)); + (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)); +} diff --git a/liblo/pthreads.2/ptw32_rwlock_check_need_init.c b/liblo/pthreads.2/ptw32_rwlock_check_need_init.c new file mode 100644 index 0000000..f615e7c --- /dev/null +++ b/liblo/pthreads.2/ptw32_rwlock_check_need_init.c @@ -0,0 +1,93 @@ +/* + * pthread_rwlock_check_need_init.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +INLINE int +ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock) +{ + int result = 0; + + /* + * The following guarded test is specifically for statically + * initialised rwlocks (via PTHREAD_RWLOCK_INITIALIZER). + * + * Note that by not providing this synchronisation we risk + * introducing race conditions into applications which are + * correctly written. + * + * Approach + * -------- + * We know that static rwlocks will not be PROCESS_SHARED + * so we can serialise access to internal state using + * Win32 Critical Sections rather than Win32 Mutexes. + * + * If using a single global lock slows applications down too much, + * multiple global locks could be created and hashed on some random + * value associated with each mutex, the pointer perhaps. At a guess, + * a good value for the optimal number of global locks might be + * the number of processors + 1. + * + */ + EnterCriticalSection (&ptw32_rwlock_test_init_lock); + + /* + * We got here possibly under race + * conditions. Check again inside the critical section + * and only initialise if the rwlock is valid (not been destroyed). + * If a static rwlock has been destroyed, the application can + * re-initialise it only by calling pthread_rwlock_init() + * explicitly. + */ + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + { + result = pthread_rwlock_init (rwlock, NULL); + } + else if (*rwlock == NULL) + { + /* + * The rwlock has been destroyed while we were waiting to + * initialise it, so the operation that caused the + * auto-initialisation should fail. + */ + result = EINVAL; + } + + LeaveCriticalSection (&ptw32_rwlock_test_init_lock); + + return result; +} diff --git a/liblo/pthreads.2/ptw32_semwait.c b/liblo/pthreads.2/ptw32_semwait.c new file mode 100644 index 0000000..209c8a6 --- /dev/null +++ b/liblo/pthreads.2/ptw32_semwait.c @@ -0,0 +1,118 @@ +/* + * ptw32_semwait.c + * + * Description: + * This translation unit implements mutual exclusion (mutex) primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef _UWIN +//# include +#endif +#include "pthread.h" +#include "implement.h" + + +int +ptw32_semwait (sem_t * sem) + /* + * ------------------------------------------------------ + * DESCRIPTION + * This function waits on a POSIX semaphore. If the + * semaphore value is greater than zero, it decreases + * its value by one. If the semaphore value is zero, then + * the calling thread (or process) is blocked until it can + * successfully decrease the value. + * + * Unlike sem_wait(), this routine is non-cancelable. + * + * RESULTS + * 0 successfully decreased semaphore, + * -1 failed, error in errno. + * ERRNO + * EINVAL 'sem' is not a valid semaphore, + * ENOSYS semaphores are not supported, + * EINTR the function was interrupted by a signal, + * EDEADLK a deadlock condition was detected. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + sem_t s = *sem; + + if (s == NULL) + { + result = EINVAL; + } + else + { + if ((result = pthread_mutex_lock (&s->lock)) == 0) + { + int v = --s->value; + + (void) pthread_mutex_unlock (&s->lock); + + if (v < 0) + { + /* Must wait */ + if (WaitForSingleObject (s->sem, INFINITE) == WAIT_OBJECT_0) + { +#ifdef NEED_SEM + if (pthread_mutex_lock (&s->lock) == 0) + { + if (s->leftToUnblock > 0) + { + --s->leftToUnblock; + SetEvent(s->sem); + } + (void) pthread_mutex_unlock (&s->lock); + } +#endif + return 0; + } + } + else + { + return 0; + } + } + } + + if (result != 0) + { + errno = result; + return -1; + } + + return 0; + +} /* ptw32_semwait */ diff --git a/liblo/pthreads.2/ptw32_spinlock_check_need_init.c b/liblo/pthreads.2/ptw32_spinlock_check_need_init.c new file mode 100644 index 0000000..dcc8b98 --- /dev/null +++ b/liblo/pthreads.2/ptw32_spinlock_check_need_init.c @@ -0,0 +1,81 @@ +/* + * ptw32_spinlock_check_need_init.c + * + * Description: + * This translation unit implements spin lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +INLINE int +ptw32_spinlock_check_need_init (pthread_spinlock_t * lock) +{ + int result = 0; + + /* + * The following guarded test is specifically for statically + * initialised spinlocks (via PTHREAD_SPINLOCK_INITIALIZER). + * + * Note that by not providing this synchronisation we risk + * introducing race conditions into applications which are + * correctly written. + */ + EnterCriticalSection (&ptw32_spinlock_test_init_lock); + + /* + * We got here possibly under race + * conditions. Check again inside the critical section + * and only initialise if the spinlock is valid (not been destroyed). + * If a static spinlock has been destroyed, the application can + * re-initialise it only by calling pthread_spin_init() + * explicitly. + */ + if (*lock == PTHREAD_SPINLOCK_INITIALIZER) + { + result = pthread_spin_init (lock, PTHREAD_PROCESS_PRIVATE); + } + else if (*lock == NULL) + { + /* + * The spinlock has been destroyed while we were waiting to + * initialise it, so the operation that caused the + * auto-initialisation should fail. + */ + result = EINVAL; + } + + LeaveCriticalSection (&ptw32_spinlock_test_init_lock); + + return (result); +} diff --git a/liblo/pthreads.2/ptw32_threadDestroy.c b/liblo/pthreads.2/ptw32_threadDestroy.c new file mode 100644 index 0000000..a88a2b0 --- /dev/null +++ b/liblo/pthreads.2/ptw32_threadDestroy.c @@ -0,0 +1,82 @@ +/* + * ptw32_threadDestroy.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +void +ptw32_threadDestroy (pthread_t thread) +{ + ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; + ptw32_thread_t threadCopy; + + if (tp != NULL) + { + /* + * Copy thread state so that the thread can be atomically NULLed. + */ + memcpy (&threadCopy, tp, sizeof (threadCopy)); + + /* + * Thread ID structs are never freed. They're NULLed and reused. + * This also sets the thread to PThreadStateInitial (invalid). + */ + ptw32_threadReusePush (thread); + + /* Now work on the copy. */ + if (threadCopy.cancelEvent != NULL) + { + CloseHandle (threadCopy.cancelEvent); + } + + (void) pthread_mutex_destroy(&threadCopy.cancelLock); + (void) pthread_mutex_destroy(&threadCopy.threadLock); + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) + /* + * See documentation for endthread vs endthreadex. + */ + if (threadCopy.threadH != 0) + { + CloseHandle (threadCopy.threadH); + } +#endif + + } +} /* ptw32_threadDestroy */ + diff --git a/liblo/pthreads.2/ptw32_threadStart.c b/liblo/pthreads.2/ptw32_threadStart.c new file mode 100644 index 0000000..fbee09d --- /dev/null +++ b/liblo/pthreads.2/ptw32_threadStart.c @@ -0,0 +1,360 @@ +/* + * ptw32_threadStart.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +#ifdef __CLEANUP_SEH + +static DWORD +ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei) +{ + switch (ep->ExceptionRecord->ExceptionCode) + { + case EXCEPTION_PTW32_SERVICES: + { + DWORD param; + DWORD numParams = ep->ExceptionRecord->NumberParameters; + + numParams = (numParams > 3) ? 3 : numParams; + + for (param = 0; param < numParams; param++) + { + ei[param] = ep->ExceptionRecord->ExceptionInformation[param]; + } + + return EXCEPTION_EXECUTE_HANDLER; + break; + } + default: + { + /* + * A system unexpected exception has occurred running the user's + * routine. We need to cleanup before letting the exception + * out of thread scope. + */ + pthread_t self = pthread_self (); + + (void) pthread_mutex_destroy (&((ptw32_thread_t *)self.p)->cancelLock); + ptw32_callUserDestroyRoutines (self); + + return EXCEPTION_CONTINUE_SEARCH; + break; + } + } +} + +#elif defined(__CLEANUP_CXX) + +#if defined(_MSC_VER) +# include +#elif defined(__WATCOMC__) +# include +# include +typedef terminate_handler + terminate_function; +#else +# if defined(__GNUC__) && __GNUC__ < 3 +# include +# else +# include +using + std::terminate_handler; +using + std::terminate; +using + std::set_terminate; +# endif +typedef terminate_handler + terminate_function; +#endif + +static terminate_function + ptw32_oldTerminate; + +void +ptw32_terminate () +{ + set_terminate (ptw32_oldTerminate); + (void) pthread_win32_thread_detach_np (); + terminate (); +} + +#endif + +#if ! defined (__MINGW32__) || (defined (__MSVCRT__) && ! defined (__DMC__)) +unsigned + __stdcall +#else +void +#endif +ptw32_threadStart (void *vthreadParms) +{ + ThreadParms * threadParms = (ThreadParms *) vthreadParms; + pthread_t self; + ptw32_thread_t * sp; + void *(*start) (void *); + void * arg; + +#ifdef __CLEANUP_SEH + DWORD + ei[] = { 0, 0, 0 }; +#endif + +#ifdef __CLEANUP_C + int setjmp_rc; +#endif + + void * status = (void *) 0; + + self = threadParms->tid; + sp = (ptw32_thread_t *) self.p; + start = threadParms->start; + arg = threadParms->arg; + + free (threadParms); + +#if defined (__MINGW32__) && ! defined (__MSVCRT__) + /* + * beginthread does not return the thread id and is running + * before it returns us the thread handle, and so we do it here. + */ + sp->thread = GetCurrentThreadId (); + /* + * Here we're using cancelLock as a general-purpose lock + * to make the new thread wait until the creating thread + * has the new handle. + */ + if (pthread_mutex_lock (&sp->cancelLock) == 0) + { + (void) pthread_mutex_unlock (&sp->cancelLock); + } +#endif + + pthread_setspecific (ptw32_selfThreadKey, sp); + + sp->state = PThreadStateRunning; + +#ifdef __CLEANUP_SEH + + __try + { + /* + * Run the caller's routine; + */ + status = sp->exitStatus = (*start) (arg); + +#ifdef _UWIN + if (--pthread_count <= 0) + exit (0); +#endif + + } + __except (ExceptionFilter (GetExceptionInformation (), ei)) + { + switch (ei[0]) + { + case PTW32_EPS_CANCEL: + status = sp->exitStatus = PTHREAD_CANCELED; +#ifdef _UWIN + if (--pthread_count <= 0) + exit (0); +#endif + break; + case PTW32_EPS_EXIT: + status = sp->exitStatus; + break; + default: + status = sp->exitStatus = PTHREAD_CANCELED; + break; + } + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + setjmp_rc = setjmp (sp->start_mark); + + if (0 == setjmp_rc) + { + + /* + * Run the caller's routine; + */ + status = sp->exitStatus = (*start) (arg); + } + else + { + switch (setjmp_rc) + { + case PTW32_EPS_CANCEL: + status = sp->exitStatus = PTHREAD_CANCELED; + break; + case PTW32_EPS_EXIT: + status = sp->exitStatus; + break; + default: + status = sp->exitStatus = PTHREAD_CANCELED; + break; + } + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + ptw32_oldTerminate = set_terminate (&ptw32_terminate); + + try + { + /* + * Run the caller's routine in a nested try block so that we + * can run the user's terminate function, which may call + * pthread_exit() or be canceled. + */ + try + { + status = sp->exitStatus = (*start) (arg); + } + catch (ptw32_exception &) + { + /* + * Pass these through to the outer block. + */ + throw; + } + catch (...) + { + /* + * We want to run the user's terminate function if supplied. + * That function may call pthread_exit() or be canceled, which will + * be handled by the outer try block. + * + * ptw32_terminate() will be called if there is no user + * supplied function. + */ + + terminate_function + term_func = set_terminate (0); + set_terminate (term_func); + + if (term_func != 0) + { + term_func (); + } + + throw; + } + } + catch (ptw32_exception_cancel &) + { + /* + * Thread was canceled. + */ + status = sp->exitStatus = PTHREAD_CANCELED; + } + catch (ptw32_exception_exit &) + { + /* + * Thread was exited via pthread_exit(). + */ + status = sp->exitStatus; + } + catch (...) + { + /* + * A system unexpected exception has occurred running the user's + * terminate routine. We get control back within this block - cleanup + * and release the exception out of thread scope. + */ + status = sp->exitStatus = PTHREAD_CANCELED; + (void) pthread_mutex_lock (&sp->cancelLock); + sp->state = PThreadStateException; + (void) pthread_mutex_unlock (&sp->cancelLock); + (void) pthread_win32_thread_detach_np (); + (void) set_terminate (ptw32_oldTerminate); + throw; + + /* + * Never reached. + */ + } + + (void) set_terminate (ptw32_oldTerminate); + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ +#endif /* __CLEANUP_C */ +#endif /* __CLEANUP_SEH */ + +#if defined(PTW32_STATIC_LIB) + /* + * We need to cleanup the pthread now if we have + * been statically linked, in which case the cleanup + * in dllMain won't get done. Joinable threads will + * only be partially cleaned up and must be fully cleaned + * up by pthread_join() or pthread_detach(). + * + * Note: if this library has been statically linked, + * implicitly created pthreads (those created + * for Win32 threads which have called pthreads routines) + * must be cleaned up explicitly by the application + * (by calling pthread_win32_thread_detach_np()). + * For the dll, dllMain will do the cleanup automatically. + */ + (void) pthread_win32_thread_detach_np (); +#endif + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) + _endthreadex ((unsigned) status); +#else + _endthread (); +#endif + + /* + * Never reached. + */ + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) + return (unsigned) status; +#endif + +} /* ptw32_threadStart */ diff --git a/liblo/pthreads.2/ptw32_throw.c b/liblo/pthreads.2/ptw32_throw.c new file mode 100644 index 0000000..cc9ee86 --- /dev/null +++ b/liblo/pthreads.2/ptw32_throw.c @@ -0,0 +1,167 @@ +/* + * ptw32_throw.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * ptw32_throw + * + * All canceled and explicitly exited POSIX threads go through + * here. This routine knows how to exit both POSIX initiated threads and + * 'implicit' POSIX threads for each of the possible language modes (C, + * C++, and SEH). + */ +void +ptw32_throw (DWORD exception) +{ + /* + * Don't use pthread_self() to avoid creating an implicit POSIX thread handle + * unnecessarily. + */ + ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); + +#ifdef __CLEANUP_SEH + DWORD exceptionInformation[3]; +#endif + + if (exception != PTW32_EPS_CANCEL && exception != PTW32_EPS_EXIT) + { + /* Should never enter here */ + exit (1); + } + + if (NULL == sp || sp->implicit) + { + /* + * We're inside a non-POSIX initialised Win32 thread + * so there is no point to jump or throw back to. Just do an + * explicit thread exit here after cleaning up POSIX + * residue (i.e. cleanup handlers, POSIX thread handle etc). + */ + unsigned exitCode = 0; + + switch (exception) + { + case PTW32_EPS_CANCEL: + exitCode = (unsigned) PTHREAD_CANCELED; + break; + case PTW32_EPS_EXIT: + exitCode = (unsigned) sp->exitStatus;; + break; + } + +#if defined(PTW32_STATIC_LIB) + + pthread_win32_thread_detach_np (); + +#endif + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__) + _endthreadex (exitCode); +#else + _endthread (); +#endif + + } + +#ifdef __CLEANUP_SEH + + + exceptionInformation[0] = (DWORD) (exception); + exceptionInformation[1] = (DWORD) (0); + exceptionInformation[2] = (DWORD) (0); + + RaiseException (EXCEPTION_PTW32_SERVICES, 0, 3, exceptionInformation); + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + ptw32_pop_cleanup_all (1); + longjmp (sp->start_mark, exception); + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + switch (exception) + { + case PTW32_EPS_CANCEL: + throw ptw32_exception_cancel (); + break; + case PTW32_EPS_EXIT: + throw ptw32_exception_exit (); + break; + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + + /* Never reached */ +} + + +void +ptw32_pop_cleanup_all (int execute) +{ + while (NULL != ptw32_pop_cleanup (execute)) + { + } +} + + +DWORD +ptw32_get_exception_services_code (void) +{ +#ifdef __CLEANUP_SEH + + return EXCEPTION_PTW32_SERVICES; + +#else + + return (DWORD) NULL; + +#endif +} diff --git a/liblo/pthreads.2/ptw32_timespec.c b/liblo/pthreads.2/ptw32_timespec.c new file mode 100644 index 0000000..629be15 --- /dev/null +++ b/liblo/pthreads.2/ptw32_timespec.c @@ -0,0 +1,83 @@ +/* + * ptw32_timespec.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#ifdef NEED_FTIME + +/* + * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds + */ +#define PTW32_TIMESPEC_TO_FILETIME_OFFSET \ + ( ((LONGLONG) 27111902 << 32) + (LONGLONG) 3577643008 ) + +INLINE void +ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft) + /* + * ------------------------------------------------------------------- + * converts struct timespec + * where the time is expressed in seconds and nanoseconds from Jan 1, 1970. + * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is + * expressed in 100 nanoseconds from Jan 1, 1601, + * ------------------------------------------------------------------- + */ +{ + *(LONGLONG *) ft = ts->tv_sec * 10000000 + + (ts->tv_nsec + 50) / 100 + PTW32_TIMESPEC_TO_FILETIME_OFFSET; +} + +INLINE void +ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts) + /* + * ------------------------------------------------------------------- + * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is + * expressed in 100 nanoseconds from Jan 1, 1601, + * into struct timespec + * where the time is expressed in seconds and nanoseconds from Jan 1, 1970. + * ------------------------------------------------------------------- + */ +{ + ts->tv_sec = + (int) ((*(LONGLONG *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET) / 10000000); + ts->tv_nsec = + (int) ((*(LONGLONG *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET - + ((LONGLONG) ts->tv_sec * (LONGLONG) 10000000)) * 100); +} + +#endif /* NEED_FTIME */ diff --git a/liblo/pthreads.2/ptw32_tkAssocCreate.c b/liblo/pthreads.2/ptw32_tkAssocCreate.c new file mode 100644 index 0000000..411c9cd --- /dev/null +++ b/liblo/pthreads.2/ptw32_tkAssocCreate.c @@ -0,0 +1,118 @@ +/* + * ptw32_tkAssocCreate.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +int +ptw32_tkAssocCreate (ptw32_thread_t * sp, pthread_key_t key) + /* + * ------------------------------------------------------------------- + * This routine creates an association that + * is unique for the given (thread,key) combination.The association + * is referenced by both the thread and the key. + * This association allows us to determine what keys the + * current thread references and what threads a given key + * references. + * See the detailed description + * at the beginning of this file for further details. + * + * Notes: + * 1) New associations are pushed to the beginning of the + * chain so that the internal ptw32_selfThreadKey association + * is always last, thus allowing selfThreadExit to + * be implicitly called last by pthread_exit. + * 2) + * + * Parameters: + * thread + * current running thread. + * key + * key on which to create an association. + * Returns: + * 0 - if successful, + * ENOMEM - not enough memory to create assoc or other object + * EINVAL - an internal error occurred + * ENOSYS - an internal error occurred + * ------------------------------------------------------------------- + */ +{ + ThreadKeyAssoc *assoc; + + /* + * Have to create an association and add it + * to both the key and the thread. + * + * Both key->keyLock and thread->threadLock are locked on + * entry to this routine. + */ + assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc)); + + if (assoc == NULL) + { + return ENOMEM; + } + + assoc->thread = sp; + assoc->key = key; + + /* + * Register assoc with key + */ + assoc->prevThread = NULL; + assoc->nextThread = (ThreadKeyAssoc *) key->threads; + if (assoc->nextThread != NULL) + { + assoc->nextThread->prevThread = assoc; + } + key->threads = (void *) assoc; + + /* + * Register assoc with thread + */ + assoc->prevKey = NULL; + assoc->nextKey = (ThreadKeyAssoc *) sp->keys; + if (assoc->nextKey != NULL) + { + assoc->nextKey->prevKey = assoc; + } + sp->keys = (void *) assoc; + + return (0); + +} /* ptw32_tkAssocCreate */ diff --git a/liblo/pthreads.2/ptw32_tkAssocDestroy.c b/liblo/pthreads.2/ptw32_tkAssocDestroy.c new file mode 100644 index 0000000..d50178f --- /dev/null +++ b/liblo/pthreads.2/ptw32_tkAssocDestroy.c @@ -0,0 +1,114 @@ +/* + * ptw32_tkAssocDestroy.c + * + * Description: + * This translation unit implements routines which are private to + * the implementation and may be used throughout it. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +void +ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc) + /* + * ------------------------------------------------------------------- + * This routine releases all resources for the given ThreadKeyAssoc + * once it is no longer being referenced + * ie) either the key or thread has stopped referencing it. + * + * Parameters: + * assoc + * an instance of ThreadKeyAssoc. + * Returns: + * N/A + * ------------------------------------------------------------------- + */ +{ + + /* + * Both key->keyLock and thread->threadLock are locked on + * entry to this routine. + */ + if (assoc != NULL) + { + ThreadKeyAssoc * prev, * next; + + /* Remove assoc from thread's keys chain */ + prev = assoc->prevKey; + next = assoc->nextKey; + if (prev != NULL) + { + prev->nextKey = next; + } + if (next != NULL) + { + next->prevKey = prev; + } + + if (assoc->thread->keys == assoc) + { + /* We're at the head of the thread's keys chain */ + assoc->thread->keys = next; + } + if (assoc->thread->nextAssoc == assoc) + { + /* + * Thread is exiting and we're deleting the assoc to be processed next. + * Hand thread the assoc after this one. + */ + assoc->thread->nextAssoc = next; + } + + /* Remove assoc from key's threads chain */ + prev = assoc->prevThread; + next = assoc->nextThread; + if (prev != NULL) + { + prev->nextThread = next; + } + if (next != NULL) + { + next->prevThread = prev; + } + + if (assoc->key->threads == assoc) + { + /* We're at the head of the key's threads chain */ + assoc->key->threads = next; + } + + free (assoc); + } + +} /* ptw32_tkAssocDestroy */ diff --git a/liblo/pthreads.2/rwlock.c b/liblo/pthreads.2/rwlock.c new file mode 100644 index 0000000..85d39c7 --- /dev/null +++ b/liblo/pthreads.2/rwlock.c @@ -0,0 +1,51 @@ +/* + * rwlock.c + * + * Description: + * This translation unit implements read/write lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "ptw32_rwlock_check_need_init.c" +#include "ptw32_rwlock_cancelwrwait.c" +#include "pthread_rwlock_init.c" +#include "pthread_rwlock_destroy.c" +#include "pthread_rwlockattr_init.c" +#include "pthread_rwlockattr_destroy.c" +#include "pthread_rwlockattr_getpshared.c" +#include "pthread_rwlockattr_setpshared.c" +#include "pthread_rwlock_rdlock.c" +#include "pthread_rwlock_timedrdlock.c" +#include "pthread_rwlock_wrlock.c" +#include "pthread_rwlock_timedwrlock.c" +#include "pthread_rwlock_unlock.c" +#include "pthread_rwlock_tryrdlock.c" +#include "pthread_rwlock_trywrlock.c" diff --git a/liblo/pthreads.2/sched.c b/liblo/pthreads.2/sched.c new file mode 100644 index 0000000..ec90e85 --- /dev/null +++ b/liblo/pthreads.2/sched.c @@ -0,0 +1,53 @@ +/* + * sched.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +#include "pthread_attr_setschedpolicy.c" +#include "pthread_attr_getschedpolicy.c" +#include "pthread_attr_setschedparam.c" +#include "pthread_attr_getschedparam.c" +#include "pthread_attr_setinheritsched.c" +#include "pthread_attr_getinheritsched.c" +#include "pthread_setschedparam.c" +#include "pthread_getschedparam.c" +#include "sched_get_priority_max.c" +#include "sched_get_priority_min.c" +#include "sched_setscheduler.c" +#include "sched_getscheduler.c" +#include "sched_yield.c" diff --git a/liblo/pthreads.2/sched.h b/liblo/pthreads.2/sched.h new file mode 100644 index 0000000..10ecb5d --- /dev/null +++ b/liblo/pthreads.2/sched.h @@ -0,0 +1,178 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/liblo/pthreads.2/sched_get_priority_max.c b/liblo/pthreads.2/sched_get_priority_max.c new file mode 100644 index 0000000..b69f82e --- /dev/null +++ b/liblo/pthreads.2/sched_get_priority_max.c @@ -0,0 +1,134 @@ +/* + * sched_get_priority_max.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +/* + * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and + * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine. + * + * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5 + * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny: + * highest priority use smaller numbers) and the following happens: + * + * sched_get_priority_min() returns 5 + * sched_get_priority_max() returns 1 + * + * The following table shows the base priority levels for combinations + * of priority class and priority value in Win32. + * + * Process Priority Class Thread Priority Level + * ----------------------------------------------------------------- + * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 17 REALTIME_PRIORITY_CLASS -7 + * 18 REALTIME_PRIORITY_CLASS -6 + * 19 REALTIME_PRIORITY_CLASS -5 + * 20 REALTIME_PRIORITY_CLASS -4 + * 21 REALTIME_PRIORITY_CLASS -3 + * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 27 REALTIME_PRIORITY_CLASS 3 + * 28 REALTIME_PRIORITY_CLASS 4 + * 29 REALTIME_PRIORITY_CLASS 5 + * 30 REALTIME_PRIORITY_CLASS 6 + * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * + * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported. + */ + + +int +sched_get_priority_max (int policy) +{ + if (policy < SCHED_MIN || policy > SCHED_MAX) + { + errno = EINVAL; + return -1; + } + +#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) + /* WinCE? */ + return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); +#else + /* This is independent of scheduling policy in Win32. */ + return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); +#endif +} diff --git a/liblo/pthreads.2/sched_get_priority_min.c b/liblo/pthreads.2/sched_get_priority_min.c new file mode 100644 index 0000000..3c6d24a --- /dev/null +++ b/liblo/pthreads.2/sched_get_priority_min.c @@ -0,0 +1,135 @@ +/* + * sched_get_priority_min.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +/* + * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and + * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine. + * + * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5 + * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny: + * highest priority use smaller numbers) and the following happens: + * + * sched_get_priority_min() returns 5 + * sched_get_priority_max() returns 1 + * + * The following table shows the base priority levels for combinations + * of priority class and priority value in Win32. + * + * Process Priority Class Thread Priority Level + * ----------------------------------------------------------------- + * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE + * 17 REALTIME_PRIORITY_CLASS -7 + * 18 REALTIME_PRIORITY_CLASS -6 + * 19 REALTIME_PRIORITY_CLASS -5 + * 20 REALTIME_PRIORITY_CLASS -4 + * 21 REALTIME_PRIORITY_CLASS -3 + * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST + * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL + * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL + * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL + * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST + * 27 REALTIME_PRIORITY_CLASS 3 + * 28 REALTIME_PRIORITY_CLASS 4 + * 29 REALTIME_PRIORITY_CLASS 5 + * 30 REALTIME_PRIORITY_CLASS 6 + * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL + * + * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported. + * + */ + + +int +sched_get_priority_min (int policy) +{ + if (policy < SCHED_MIN || policy > SCHED_MAX) + { + errno = EINVAL; + return -1; + } + +#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) + /* WinCE? */ + return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); +#else + /* This is independent of scheduling policy in Win32. */ + return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); +#endif +} diff --git a/liblo/pthreads.2/sched_getscheduler.c b/liblo/pthreads.2/sched_getscheduler.c new file mode 100644 index 0000000..1f0957c --- /dev/null +++ b/liblo/pthreads.2/sched_getscheduler.c @@ -0,0 +1,69 @@ +/* + * sched_getscheduler.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +sched_getscheduler (pid_t pid) +{ + /* + * Win32 only has one policy which we call SCHED_OTHER. + * However, we try to provide other valid side-effects + * such as EPERM and ESRCH errors. + */ + if (0 != pid) + { + int selfPid = (int) GetCurrentProcessId (); + + if (pid != selfPid) + { + HANDLE h = + OpenProcess (PROCESS_QUERY_INFORMATION, PTW32_FALSE, (DWORD) pid); + + if (NULL == h) + { + errno = + (GetLastError () == + (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH; + return -1; + } + } + } + + return SCHED_OTHER; +} diff --git a/liblo/pthreads.2/sched_setscheduler.c b/liblo/pthreads.2/sched_setscheduler.c new file mode 100644 index 0000000..06f7790 --- /dev/null +++ b/liblo/pthreads.2/sched_setscheduler.c @@ -0,0 +1,81 @@ +/* + * sched_setscheduler.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +sched_setscheduler (pid_t pid, int policy) +{ + /* + * Win32 only has one policy which we call SCHED_OTHER. + * However, we try to provide other valid side-effects + * such as EPERM and ESRCH errors. Choosing to check + * for a valid policy last allows us to get the most value out + * of this function. + */ + if (0 != pid) + { + int selfPid = (int) GetCurrentProcessId (); + + if (pid != selfPid) + { + HANDLE h = + OpenProcess (PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) pid); + + if (NULL == h) + { + errno = + (GetLastError () == + (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH; + return -1; + } + } + } + + if (SCHED_OTHER != policy) + { + errno = ENOSYS; + return -1; + } + + /* + * Don't set anything because there is nothing to set. + * Just return the current (the only possible) value. + */ + return SCHED_OTHER; +} diff --git a/liblo/pthreads.2/sched_yield.c b/liblo/pthreads.2/sched_yield.c new file mode 100644 index 0000000..4220cc6 --- /dev/null +++ b/liblo/pthreads.2/sched_yield.c @@ -0,0 +1,71 @@ +/* + * sched_yield.c + * + * Description: + * POSIX thread functions that deal with thread scheduling. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" +#include "sched.h" + +int +sched_yield (void) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function indicates that the calling thread is + * willing to give up some time slices to other threads. + * + * PARAMETERS + * N/A + * + * + * DESCRIPTION + * This function indicates that the calling thread is + * willing to give up some time slices to other threads. + * NOTE: Since this is part of POSIX 1003.1b + * (realtime extensions), it is defined as returning + * -1 if an error occurs and sets errno to the actual + * error. + * + * RESULTS + * 0 successfully created semaphore, + * ENOSYS sched_yield not supported, + * + * ------------------------------------------------------ + */ +{ + Sleep (0); + + return 0; +} diff --git a/liblo/pthreads.2/sem_close.c b/liblo/pthreads.2/sem_close.c new file mode 100644 index 0000000..c778bef --- /dev/null +++ b/liblo/pthreads.2/sem_close.c @@ -0,0 +1,58 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_close.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + +/* ignore warning "unreferenced formal parameter" */ +#ifdef _MSC_VER +#pragma warning( disable : 4100 ) +#endif + +int +sem_close (sem_t * sem) +{ + errno = ENOSYS; + return -1; +} /* sem_close */ diff --git a/liblo/pthreads.2/sem_destroy.c b/liblo/pthreads.2/sem_destroy.c new file mode 100644 index 0000000..e2bdf86 --- /dev/null +++ b/liblo/pthreads.2/sem_destroy.c @@ -0,0 +1,144 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_destroy.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +int +sem_destroy (sem_t * sem) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function destroys an unnamed semaphore. + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * DESCRIPTION + * This function destroys an unnamed semaphore. + * + * RESULTS + * 0 successfully destroyed semaphore, + * -1 failed, error in errno + * ERRNO + * EINVAL 'sem' is not a valid semaphore, + * ENOSYS semaphores are not supported, + * EBUSY threads (or processes) are currently + * blocked on 'sem' + * + * ------------------------------------------------------ + */ +{ + int result = 0; + sem_t s = NULL; + + if (sem == NULL || *sem == NULL) + { + result = EINVAL; + } + else + { + s = *sem; + + if ((result = pthread_mutex_lock (&s->lock)) == 0) + { + if (s->value < 0) + { + (void) pthread_mutex_unlock (&s->lock); + result = EBUSY; + } + else + { + /* There are no threads currently blocked on this semaphore. */ + + if (!CloseHandle (s->sem)) + { + (void) pthread_mutex_unlock (&s->lock); + result = EINVAL; + } + else + { + /* + * Invalidate the semaphore handle when we have the lock. + * Other sema operations should test this after acquiring the lock + * to check that the sema is still valid, i.e. before performing any + * operations. This may only be necessary before the sema op routine + * returns so that the routine can return EINVAL - e.g. if setting + * s->value to SEM_VALUE_MAX below does force a fall-through. + */ + *sem = NULL; + + /* Prevent anyone else actually waiting on or posting this sema. + */ + s->value = SEM_VALUE_MAX; + + (void) pthread_mutex_unlock (&s->lock); + + do + { + /* Give other threads a chance to run and exit any sema op + * routines. Due to the SEM_VALUE_MAX value, if sem_post or + * sem_wait were blocked by us they should fall through. + */ + Sleep(0); + } + while (pthread_mutex_destroy (&s->lock) == EBUSY); + } + } + } + } + + if (result != 0) + { + errno = result; + return -1; + } + + free (s); + + return 0; + +} /* sem_destroy */ diff --git a/liblo/pthreads.2/sem_getvalue.c b/liblo/pthreads.2/sem_getvalue.c new file mode 100644 index 0000000..233635b --- /dev/null +++ b/liblo/pthreads.2/sem_getvalue.c @@ -0,0 +1,110 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_getvalue.c + * + * Purpose: + * Semaphores aren't actually part of PThreads. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1-2001 + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +int +sem_getvalue (sem_t * sem, int *sval) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function stores the current count value of the + * semaphore. + * RESULTS + * + * Return value + * + * 0 sval has been set. + * -1 failed, error in errno + * + * in global errno + * + * EINVAL 'sem' is not a valid semaphore, + * ENOSYS this function is not supported, + * + * + * PARAMETERS + * + * sem pointer to an instance of sem_t + * + * sval pointer to int. + * + * DESCRIPTION + * This function stores the current count value of the semaphore + * pointed to by sem in the int pointed to by sval. + */ +{ + if (sem == NULL || *sem == NULL || sval == NULL) + { + errno = EINVAL; + return -1; + } + else + { + long value; + register sem_t s = *sem; + int result = 0; + + if ((result = pthread_mutex_lock(&s->lock)) == 0) + { + /* See sem_destroy.c + */ + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + value = s->value; + (void) pthread_mutex_unlock(&s->lock); + *sval = value; + } + + return result; + } + +} /* sem_getvalue */ diff --git a/liblo/pthreads.2/sem_init.c b/liblo/pthreads.2/sem_init.c new file mode 100644 index 0000000..8e5e3f3 --- /dev/null +++ b/liblo/pthreads.2/sem_init.c @@ -0,0 +1,169 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_init.c + * + * Purpose: + * Semaphores aren't actually part of PThreads. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1-2001 + * + * ------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + +int +sem_init (sem_t * sem, int pshared, unsigned int value) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function initializes a semaphore. The + * initial value of the semaphore is 'value' + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * pshared + * if zero, this semaphore may only be shared between + * threads in the same process. + * if nonzero, the semaphore can be shared between + * processes + * + * value + * initial value of the semaphore counter + * + * DESCRIPTION + * This function initializes a semaphore. The + * initial value of the semaphore is set to 'value'. + * + * RESULTS + * 0 successfully created semaphore, + * -1 failed, error in errno + * ERRNO + * EINVAL 'sem' is not a valid semaphore, or + * 'value' >= SEM_VALUE_MAX + * ENOMEM out of memory, + * ENOSPC a required resource has been exhausted, + * ENOSYS semaphores are not supported, + * EPERM the process lacks appropriate privilege + * + * ------------------------------------------------------ + */ +{ + int result = 0; + sem_t s = NULL; + + if (pshared != 0) + { + /* + * Creating a semaphore that can be shared between + * processes + */ + result = EPERM; + } + else if (value > (unsigned int)SEM_VALUE_MAX) + { + result = EINVAL; + } + else + { + s = (sem_t) calloc (1, sizeof (*s)); + + if (NULL == s) + { + result = ENOMEM; + } + else + { + + s->value = value; + if (pthread_mutex_init(&s->lock, NULL) == 0) + { + +#ifdef NEED_SEM + + s->sem = CreateEvent (NULL, + PTW32_FALSE, /* auto (not manual) reset */ + PTW32_FALSE, /* initial state is unset */ + NULL); + + if (0 == s->sem) + { + free (s); + (void) pthread_mutex_destroy(&s->lock); + result = ENOSPC; + } + else + { + s->leftToUnblock = 0; + } + +#else /* NEED_SEM */ + + if ((s->sem = CreateSemaphore (NULL, /* Always NULL */ + (long) 0, /* Force threads to wait */ + (long) SEM_VALUE_MAX, /* Maximum value */ + NULL)) == 0) /* Name */ + { + (void) pthread_mutex_destroy(&s->lock); + result = ENOSPC; + } + +#endif /* NEED_SEM */ + + } + else + { + result = ENOSPC; + } + + if (result != 0) + { + free(s); + } + } + } + + if (result != 0) + { + errno = result; + return -1; + } + + *sem = s; + + return 0; + +} /* sem_init */ diff --git a/liblo/pthreads.2/sem_open.c b/liblo/pthreads.2/sem_open.c new file mode 100644 index 0000000..3e2d668 --- /dev/null +++ b/liblo/pthreads.2/sem_open.c @@ -0,0 +1,58 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_open.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + +/* ignore warning "unreferenced formal parameter" */ +#ifdef _MSC_VER +#pragma warning( disable : 4100 ) +#endif + +int +sem_open (const char *name, int oflag, mode_t mode, unsigned int value) +{ + errno = ENOSYS; + return -1; +} /* sem_open */ diff --git a/liblo/pthreads.2/sem_post.c b/liblo/pthreads.2/sem_post.c new file mode 100644 index 0000000..5c88794 --- /dev/null +++ b/liblo/pthreads.2/sem_post.c @@ -0,0 +1,128 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_post.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +int +sem_post (sem_t * sem) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function posts a wakeup to a semaphore. + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * DESCRIPTION + * This function posts a wakeup to a semaphore. If there + * are waiting threads (or processes), one is awakened; + * otherwise, the semaphore value is incremented by one. + * + * RESULTS + * 0 successfully posted semaphore, + * -1 failed, error in errno + * ERRNO + * EINVAL 'sem' is not a valid semaphore, + * ENOSYS semaphores are not supported, + * ERANGE semaphore count is too big + * + * ------------------------------------------------------ + */ +{ + int result = 0; + sem_t s = *sem; + + if (s == NULL) + { + result = EINVAL; + } + else if ((result = pthread_mutex_lock (&s->lock)) == 0) + { + /* See sem_destroy.c + */ + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + result = EINVAL; + return -1; + } + + if (s->value < SEM_VALUE_MAX) + { +#ifdef NEED_SEM + if (++s->value <= 0 + && !SetEvent(s->sem)) + { + s->value--; + result = EINVAL; + } +#else + if (++s->value <= 0 + && !ReleaseSemaphore (s->sem, 1, NULL)) + { + s->value--; + result = EINVAL; + } +#endif /* NEED_SEM */ + } + else + { + result = ERANGE; + } + + (void) pthread_mutex_unlock (&s->lock); + } + + if (result != 0) + { + errno = result; + return -1; + } + + return 0; + +} /* sem_post */ diff --git a/liblo/pthreads.2/sem_post_multiple.c b/liblo/pthreads.2/sem_post_multiple.c new file mode 100644 index 0000000..f7c8d65 --- /dev/null +++ b/liblo/pthreads.2/sem_post_multiple.c @@ -0,0 +1,142 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_post_multiple.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +int +sem_post_multiple (sem_t * sem, int count) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function posts multiple wakeups to a semaphore. + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * count + * counter, must be greater than zero. + * + * DESCRIPTION + * This function posts multiple wakeups to a semaphore. If there + * are waiting threads (or processes), n <= count are awakened; + * the semaphore value is incremented by count - n. + * + * RESULTS + * 0 successfully posted semaphore, + * -1 failed, error in errno + * ERRNO + * EINVAL 'sem' is not a valid semaphore + * or count is less than or equal to zero. + * ERANGE semaphore count is too big + * + * ------------------------------------------------------ + */ +{ + int result = 0; + long waiters; + sem_t s = *sem; + + if (s == NULL || count <= 0) + { + result = EINVAL; + } + else if ((result = pthread_mutex_lock (&s->lock)) == 0) + { + /* See sem_destroy.c + */ + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + result = EINVAL; + return -1; + } + + if (s->value <= (SEM_VALUE_MAX - count)) + { + waiters = -s->value; + s->value += count; + if (waiters > 0) + { +#ifdef NEED_SEM + if (SetEvent(s->sem)) + { + waiters--; + s->leftToUnblock += count - 1; + if (s->leftToUnblock > waiters) + { + s->leftToUnblock = waiters; + } + } +#else + if (ReleaseSemaphore (s->sem, (waiters<=count)?waiters:count, 0)) + { + /* No action */ + } +#endif + else + { + s->value -= count; + result = EINVAL; + } + } + } + else + { + result = ERANGE; + } + (void) pthread_mutex_unlock (&s->lock); + } + + if (result != 0) + { + errno = result; + return -1; + } + + return 0; + +} /* sem_post_multiple */ diff --git a/liblo/pthreads.2/sem_timedwait.c b/liblo/pthreads.2/sem_timedwait.c new file mode 100644 index 0000000..af001ca --- /dev/null +++ b/liblo/pthreads.2/sem_timedwait.c @@ -0,0 +1,238 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_timedwait.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +typedef struct { + sem_t sem; + int * resultPtr; +} sem_timedwait_cleanup_args_t; + + +static void PTW32_CDECL +ptw32_sem_timedwait_cleanup (void * args) +{ + sem_timedwait_cleanup_args_t * a = (sem_timedwait_cleanup_args_t *)args; + sem_t s = a->sem; + + if (pthread_mutex_lock (&s->lock) == 0) + { + /* + * We either timed out or were cancelled. + * If someone has posted between then and now we try to take the semaphore. + * Otherwise the semaphore count may be wrong after we + * return. In the case of a cancellation, it is as if we + * were cancelled just before we return (after taking the semaphore) + * which is ok. + */ + if (WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0) + { + /* We got the semaphore on the second attempt */ + *(a->resultPtr) = 0; + } + else + { + /* Indicate we're no longer waiting */ + s->value++; +#ifdef NEED_SEM + if (s->value > 0) + { + s->leftToUnblock = 0; + } +#else + /* + * Don't release the W32 sema, it doesn't need adjustment + * because it doesn't record the number of waiters. + */ +#endif + } + (void) pthread_mutex_unlock (&s->lock); + } +} + + +int +sem_timedwait (sem_t * sem, const struct timespec *abstime) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function waits on a semaphore possibly until + * 'abstime' time. + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * abstime + * pointer to an instance of struct timespec + * + * DESCRIPTION + * This function waits on a semaphore. If the + * semaphore value is greater than zero, it decreases + * its value by one. If the semaphore value is zero, then + * the calling thread (or process) is blocked until it can + * successfully decrease the value or until interrupted by + * a signal. + * + * If 'abstime' is a NULL pointer then this function will + * block until it can successfully decrease the value or + * until interrupted by a signal. + * + * RESULTS + * 0 successfully decreased semaphore, + * -1 failed, error in errno + * ERRNO + * EINVAL 'sem' is not a valid semaphore, + * ENOSYS semaphores are not supported, + * EINTR the function was interrupted by a signal, + * EDEADLK a deadlock condition was detected. + * ETIMEDOUT abstime elapsed before success. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + sem_t s = *sem; + + pthread_testcancel(); + + if (sem == NULL) + { + result = EINVAL; + } + else + { + DWORD milliseconds; + + if (abstime == NULL) + { + milliseconds = INFINITE; + } + else + { + /* + * Calculate timeout as milliseconds from current system time. + */ + milliseconds = ptw32_relmillisecs (abstime); + } + + if ((result = pthread_mutex_lock (&s->lock)) == 0) + { + int v; + + /* See sem_destroy.c + */ + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + v = --s->value; + (void) pthread_mutex_unlock (&s->lock); + + if (v < 0) + { +#ifdef NEED_SEM + int timedout; +#endif + sem_timedwait_cleanup_args_t cleanup_args; + + cleanup_args.sem = s; + cleanup_args.resultPtr = &result; + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + /* Must wait */ + pthread_cleanup_push(ptw32_sem_timedwait_cleanup, (void *) &cleanup_args); +#ifdef NEED_SEM + timedout = +#endif + result = pthreadCancelableTimedWait (s->sem, milliseconds); + pthread_cleanup_pop(result); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + +#ifdef NEED_SEM + + if (!timedout && pthread_mutex_lock (&s->lock) == 0) + { + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + if (s->leftToUnblock > 0) + { + --s->leftToUnblock; + SetEvent(s->sem); + } + (void) pthread_mutex_unlock (&s->lock); + } + +#endif /* NEED_SEM */ + + } + } + + } + + if (result != 0) + { + + errno = result; + return -1; + + } + + return 0; + +} /* sem_timedwait */ diff --git a/liblo/pthreads.2/sem_trywait.c b/liblo/pthreads.2/sem_trywait.c new file mode 100644 index 0000000..a9169c0 --- /dev/null +++ b/liblo/pthreads.2/sem_trywait.c @@ -0,0 +1,117 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_trywait.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +int +sem_trywait (sem_t * sem) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function tries to wait on a semaphore. + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * DESCRIPTION + * This function tries to wait on a semaphore. If the + * semaphore value is greater than zero, it decreases + * its value by one. If the semaphore value is zero, then + * this function returns immediately with the error EAGAIN + * + * RESULTS + * 0 successfully decreased semaphore, + * -1 failed, error in errno + * ERRNO + * EAGAIN the semaphore was already locked, + * EINVAL 'sem' is not a valid semaphore, + * ENOTSUP sem_trywait is not supported, + * EINTR the function was interrupted by a signal, + * EDEADLK a deadlock condition was detected. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + sem_t s = *sem; + + if (s == NULL) + { + result = EINVAL; + } + else if ((result = pthread_mutex_lock (&s->lock)) == 0) + { + /* See sem_destroy.c + */ + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + if (s->value > 0) + { + s->value--; + } + else + { + result = EAGAIN; + } + + (void) pthread_mutex_unlock (&s->lock); + } + + if (result != 0) + { + errno = result; + return -1; + } + + return 0; + +} /* sem_trywait */ diff --git a/liblo/pthreads.2/sem_unlink.c b/liblo/pthreads.2/sem_unlink.c new file mode 100644 index 0000000..27aed87 --- /dev/null +++ b/liblo/pthreads.2/sem_unlink.c @@ -0,0 +1,58 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_unlink.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + +/* ignore warning "unreferenced formal parameter" */ +#ifdef _MSC_VER +#pragma warning( disable : 4100 ) +#endif + +int +sem_unlink (const char *name) +{ + errno = ENOSYS; + return -1; +} /* sem_unlink */ diff --git a/liblo/pthreads.2/sem_wait.c b/liblo/pthreads.2/sem_wait.c new file mode 100644 index 0000000..1b5c4f3 --- /dev/null +++ b/liblo/pthreads.2/sem_wait.c @@ -0,0 +1,187 @@ +/* + * ------------------------------------------------------------- + * + * Module: sem_wait.c + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +static void PTW32_CDECL +ptw32_sem_wait_cleanup(void * sem) +{ + sem_t s = (sem_t) sem; + + if (pthread_mutex_lock (&s->lock) == 0) + { + /* + * If sema is destroyed do nothing, otherwise:- + * If the sema is posted between us being cancelled and us locking + * the sema again above then we need to consume that post but cancel + * anyway. If we don't get the semaphore we indicate that we're no + * longer waiting. + */ + if (*((sem_t *)sem) != NULL && !(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)) + { + ++s->value; +#ifdef NEED_SEM + if (s->value > 0) + { + s->leftToUnblock = 0; + } +#else + /* + * Don't release the W32 sema, it doesn't need adjustment + * because it doesn't record the number of waiters. + */ +#endif /* NEED_SEM */ + } + (void) pthread_mutex_unlock (&s->lock); + } +} + +int +sem_wait (sem_t * sem) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function waits on a semaphore. + * + * PARAMETERS + * sem + * pointer to an instance of sem_t + * + * DESCRIPTION + * This function waits on a semaphore. If the + * semaphore value is greater than zero, it decreases + * its value by one. If the semaphore value is zero, then + * the calling thread (or process) is blocked until it can + * successfully decrease the value or until interrupted by + * a signal. + * + * RESULTS + * 0 successfully decreased semaphore, + * -1 failed, error in errno + * ERRNO + * EINVAL 'sem' is not a valid semaphore, + * ENOSYS semaphores are not supported, + * EINTR the function was interrupted by a signal, + * EDEADLK a deadlock condition was detected. + * + * ------------------------------------------------------ + */ +{ + int result = 0; + sem_t s = *sem; + + pthread_testcancel(); + + if (s == NULL) + { + result = EINVAL; + } + else + { + if ((result = pthread_mutex_lock (&s->lock)) == 0) + { + int v; + + /* See sem_destroy.c + */ + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + v = --s->value; + (void) pthread_mutex_unlock (&s->lock); + + if (v < 0) + { +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + /* Must wait */ + pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s); + result = pthreadCancelableWait (s->sem); + /* Cleanup if we're canceled or on any other error */ + pthread_cleanup_pop(result); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + } +#ifdef NEED_SEM + + if (!result && pthread_mutex_lock (&s->lock) == 0) + { + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + if (s->leftToUnblock > 0) + { + --s->leftToUnblock; + SetEvent(s->sem); + } + (void) pthread_mutex_unlock (&s->lock); + } + +#endif /* NEED_SEM */ + + } + + } + + if (result != 0) + { + errno = result; + return -1; + } + + return 0; + +} /* sem_wait */ diff --git a/liblo/pthreads.2/semaphore.c b/liblo/pthreads.2/semaphore.c new file mode 100644 index 0000000..0a5131f --- /dev/null +++ b/liblo/pthreads.2/semaphore.c @@ -0,0 +1,69 @@ +/* + * ------------------------------------------------------------- + * + * Module: semaphore.c + * + * Purpose: + * Concatenated version of separate modules to allow + * inlining optimisation, which it is assumed can only + * be effective within a single module. + * + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * ------------------------------------------------------------- + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef NEED_FTIME +# include +#endif + +#include + +#include "pthread.h" +#include "semaphore.h" +#include "implement.h" + + +#include "sem_init.c" +#include "sem_destroy.c" +#include "sem_trywait.c" +#include "sem_wait.c" +#include "sem_timedwait.c" +#include "sem_post.c" +#include "sem_post_multiple.c" +#include "sem_getvalue.c" +#include "sem_open.c" +#include "sem_close.c" +#include "sem_unlink.c" diff --git a/liblo/pthreads.2/semaphore.h b/liblo/pthreads.2/semaphore.h new file mode 100644 index 0000000..ea42ce3 --- /dev/null +++ b/liblo/pthreads.2/semaphore.h @@ -0,0 +1,166 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/liblo/pthreads.2/signal.c b/liblo/pthreads.2/signal.c new file mode 100644 index 0000000..b95b3ea --- /dev/null +++ b/liblo/pthreads.2/signal.c @@ -0,0 +1,179 @@ +/* + * signal.c + * + * Description: + * Thread-aware signal functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* + * Possible future strategy for implementing pthread_kill() + * ======================================================== + * + * Win32 does not implement signals. + * Signals are simply software interrupts. + * pthread_kill() asks the system to deliver a specified + * signal (interrupt) to a specified thread in the same + * process. + * Signals are always asynchronous (no deferred signals). + * Pthread-win32 has an async cancelation mechanism. + * A similar system can be written to deliver signals + * within the same process (on ix86 processors at least). + * + * Each thread maintains information about which + * signals it will respond to. Handler routines + * are set on a per-process basis - not per-thread. + * When signalled, a thread will check it's sigmask + * and, if the signal is not being ignored, call the + * handler routine associated with the signal. The + * thread must then (except for some signals) return to + * the point where it was interrupted. + * + * Ideally the system itself would check the target thread's + * mask before possibly needlessly bothering the thread + * itself. This could be done by pthread_kill(), that is, + * in the signaling thread since it has access to + * all pthread_t structures. It could also retrieve + * the handler routine address to minimise the target + * threads response overhead. This may also simplify + * serialisation of the access to the per-thread signal + * structures. + * + * pthread_kill() eventually calls a routine similar to + * ptw32_cancel_thread() which manipulates the target + * threads processor context to cause the thread to + * run the handler launcher routine. pthread_kill() must + * save the target threads current context so that the + * handler launcher routine can restore the context after + * the signal handler has returned. Some handlers will not + * return, eg. the default SIGKILL handler may simply + * call pthread_exit(). + * + * The current context is saved in the target threads + * pthread_t structure. + */ + +#include "pthread.h" +#include "implement.h" + +#if HAVE_SIGSET_T + +static void +ptw32_signal_thread () +{ +} + +static void +ptw32_signal_callhandler () +{ +} + +int +pthread_sigmask (int how, sigset_t const *set, sigset_t * oset) +{ + pthread_t thread = pthread_self (); + + if (thread.p == NULL) + { + return ENOENT; + } + + /* Validate the `how' argument. */ + if (set != NULL) + { + switch (how) + { + case SIG_BLOCK: + break; + case SIG_UNBLOCK: + break; + case SIG_SETMASK: + break; + default: + /* Invalid `how' argument. */ + return EINVAL; + } + } + + /* Copy the old mask before modifying it. */ + if (oset != NULL) + { + memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t)); + } + + if (set != NULL) + { + unsigned int i; + + /* FIXME: this code assumes that sigmask is an even multiple of + the size of a long integer. */ + + unsigned long *src = (unsigned long const *) set; + unsigned long *dest = (unsigned long *) &(thread.p->sigmask); + + switch (how) + { + case SIG_BLOCK: + for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++) + { + /* OR the bit field longword-wise. */ + *dest++ |= *src++; + } + break; + case SIG_UNBLOCK: + for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++) + { + /* XOR the bitfield longword-wise. */ + *dest++ ^= *src++; + } + case SIG_SETMASK: + /* Replace the whole sigmask. */ + memcpy (&(thread.p->sigmask), set, sizeof (sigset_t)); + break; + } + } + + return 0; +} + +int +sigwait (const sigset_t * set, int *sig) +{ + /* This routine is a cancellation point */ + pthread_test_cancel(); +} + +int +sigaction (int signum, const struct sigaction *act, struct sigaction *oldact) +{ +} + +#endif /* HAVE_SIGSET_T */ diff --git a/liblo/pthreads.2/spin.c b/liblo/pthreads.2/spin.c new file mode 100644 index 0000000..92b9bed --- /dev/null +++ b/liblo/pthreads.2/spin.c @@ -0,0 +1,46 @@ +/* + * spin.c + * + * Description: + * This translation unit implements spin lock primitives. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#include "ptw32_spinlock_check_need_init.c" +#include "pthread_spin_init.c" +#include "pthread_spin_destroy.c" +#include "pthread_spin_lock.c" +#include "pthread_spin_unlock.c" +#include "pthread_spin_trylock.c" diff --git a/liblo/pthreads.2/sync.c b/liblo/pthreads.2/sync.c new file mode 100644 index 0000000..03c9881 --- /dev/null +++ b/liblo/pthreads.2/sync.c @@ -0,0 +1,43 @@ +/* + * sync.c + * + * Description: + * This translation unit implements functions related to thread + * synchronisation. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#include "pthread_detach.c" +#include "pthread_join.c" diff --git a/liblo/pthreads.2/tests/Bmakefile b/liblo/pthreads.2/tests/Bmakefile new file mode 100644 index 0000000..b21d241 --- /dev/null +++ b/liblo/pthreads.2/tests/Bmakefile @@ -0,0 +1,350 @@ +# Makefile for the pthreads test suite. +# If all of the .pass files can be created, the test suite has passed. +# +# -------------------------------------------------------------------------- +# +# Pthreads-win32 - POSIX Threads Library for Win32 +# Copyright(C) 1998 John E. Bossom +# Copyright(C) 1999,2005 Pthreads-win32 contributors +# +# Contact Email: rpj@callisto.canberra.edu.au +# +# The current list of contributors is contained +# in the file CONTRIBUTORS included with the source +# code distribution. The list can also be seen at the +# following World Wide Web location: +# http://sources.redhat.com/pthreads-win32/contributors.html +# +# This library 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 2 of the License, or (at your option) any later version. +# +# This library 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 library in the file COPYING.LIB; +# if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# + +DLL_VER = 2 + +CP = copy +RM = erase +CAT = type +MKDIR = mkdir +TOUCH = echo Passed > +ECHO = @echo + +QAPC = ..\QueueUserAPCEx\User\quserex.dll + +CPHDR = pthread.h semaphore.h sched.h + +OPTIM = -O2 + +XXLIBS = cw32mti.lib ws2_32.lib + +# C++ Exceptions +BCEFLAGS = -P -DPtW32NoCatchWarn -D__CLEANUP_CXX +BCELIB = pthreadBCE$(DLL_VER).lib +BCEDLL = pthreadBCE$(DLL_VER).dll +# C cleanup code +BCFLAGS = -D__CLEANUP_C +BCLIB = pthreadBC$(DLL_VER).lib +BCDLL = pthreadBC$(DLL_VER).dll +# C++ Exceptions in application - using VC version of pthreads dll +BCXFLAGS = -D__CLEANUP_C + +# Defaults +CPLIB = $(BCLIB) +CPDLL = $(BCDLL) + +CFLAGS= -q $(OPTIM) /D_WIN32_WINNT=0x400 -w -tWC -tWM -4 -w-aus -w-asc -w-par +LFLAGS= +INCLUDES=-I. +BUILD_DIR=.. + +COPYFILES = $(CPHDR) $(CPLIB) $(CPDLL) $(QAPC) + +EHFLAGS = + +# If a test case returns a non-zero exit code to the shell, make will +# stop. + +PASSES= loadfree.pass \ + errno1.pass \ + self1.pass mutex5.pass \ + mutex1.pass mutex1n.pass mutex1e.pass mutex1r.pass \ + semaphore1.pass semaphore2.pass semaphore3.pass \ + mutex2.pass mutex3.pass \ + mutex2r.pass mutex2e.pass mutex3r.pass mutex3e.pass \ + condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass \ + exit1.pass create1.pass create2.pass reuse1.pass reuse2.pass equal1.pass \ + kill1.pass valid1.pass valid2.pass \ + exit2.pass exit3.pass exit4.pass exit5.pass \ + join0.pass join1.pass detach1.pass join2.pass join3.pass \ + mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass \ + mutex6s.pass mutex6es.pass mutex6rs.pass \ + mutex7.pass mutex7n.pass mutex7e.pass mutex7r.pass \ + mutex8.pass mutex8n.pass mutex8e.pass mutex8r.pass \ + count1.pass \ + once1.pass once2.pass once3.pass once4.pass \ + self2.pass \ + cancel1.pass cancel2.pass \ + semaphore4.pass semaphore4t.pass semaphore5.pass \ + barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass \ + tsd1.pass tsd2.pass delay1.pass delay2.pass eyal1.pass \ + condvar3.pass condvar3_1.pass condvar3_2.pass condvar3_3.pass \ + condvar4.pass condvar5.pass condvar6.pass \ + condvar7.pass condvar8.pass condvar9.pass \ + rwlock1.pass rwlock2.pass rwlock3.pass rwlock4.pass \ + rwlock5.pass rwlock6.pass rwlock7.pass rwlock8.pass \ + rwlock2_t.pass rwlock3_t.pass rwlock4_t.pass rwlock5_t.pass rwlock6_t.pass rwlock6_t2.pass \ + context1.pass \ + cancel3.pass cancel4.pass cancel5.pass cancel6a.pass cancel6d.pass \ + cancel7.pass cancel8.pass \ + cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass \ + priority1.pass priority2.pass inherit1.pass \ + spin1.pass spin2.pass spin3.pass spin4.pass \ + exception1.pass exception2.pass exception3.pass \ + cancel9.pass create3.pass stress1.pass + +BENCHRESULTS = \ + benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench + +help: + @ $(ECHO) Run one of the following command lines: + @ $(ECHO) make clean BC (to test using BC dll with VC (no EH) applications) + @ $(ECHO) make clean BCX (to test using BC dll with VC++ (EH) applications) + @ $(ECHO) make clean BCE (to test using the BCE dll with VC++ EH applications) + @ $(ECHO) make clean BC-bench (to benchtest using BC dll with C bench app) + @ $(ECHO) make clean BCX-bench (to benchtest using BC dll with C++ bench app) + @ $(ECHO) make clean BCE-bench (to benchtest using BCE dll with C++ bench app) + +all: + @ make clean BC + @ make clean BCX + @ make clean BCE + @ make clean BC-bench + +# This allows an individual test application to be made using the default lib. +# e.g. make clean test cancel3.exe +test: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) + +tests: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) sizes.pass $(PASSES) + @ $(ECHO) ALL TESTS PASSED! Congratulations! + +benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(BENCHRESULTS) + @ $(ECHO) ALL BENCH TESTS DONE. + +sizes.pass: sizes.exe + @ $(ECHO) ... Running $(TEST) test: $*.exe + @ .\$*.exe > SIZES.$(TEST) + @ $(CAT) SIZES.$(TEST) + @ $(ECHO) ...... Passed + @ $(TOUCH) $*.pass + +BCE: + @ make -f Bmakefile TEST="$@" CPLIB="$(BCELIB)" CPDLL="$(BCEDLL)" EHFLAGS="$(BCEFLAGS)" tests + +BC: + @ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCFLAGS)" tests + +BCX: + @ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCXFLAGS)" tests + +BCE-bench: + @ make -f Bmakefile TEST="$@" CPLIB="$(BCELIB)" CPDLL="$(BCEDLL)" EHFLAGS="$(BCEFLAGS)" XXLIBS="benchlib.o" benchtests + +BC-bench: + @ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCFLAGS)" XXLIBS="benchlib.o" benchtests + +BCX-bench: + @ make -f Bmakefile TEST="$@" CPLIB="$(BCLIB)" CPDLL="$(BCDLL)" EHFLAGS="$(BCXFLAGS)" XXLIBS="benchlib.o" benchtests + +.exe.pass: + @ $(ECHO) ... Running $(TEST) test: $< + @ .\$< + @ $(ECHO) ...... Passed + @ $(TOUCH) $@ + +.exe.bench: + @ $(ECHO) ... Running $(TEST) benchtest: $< + @ .\$< + @ $(ECHO) ...... Done + @ $(TOUCH) $@ + +.c.exe: + @ $(ECHO) $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< -e$@ $(LFLAGS) $(CPLIB) $(XXLIBS) + @ $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< -e$@ $(LFLAGS) $(CPLIB) $(XXLIBS) + +.c.o: + @ $(ECHO) $(CC) $(EHFLAGS) -c $(CFLAGS) $(INCLUDES) $< -o$@ + @ $(CC) $(EHFLAGS) $(CFLAGS) -c $(INCLUDES) $< -o$@ + + +.c.i: + @ $(CC) /P $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< + +$(COPYFILES): + @ $(ECHO) Copying $@ + @ $(CP) $(BUILD_DIR)\$@ . + +pthread.dll: $(CPDLL) + @ $(CP) $(CPDLL) pthread.dll + @ $(CP) $(CPLIB) pthread.lib + +clean: + - $(RM) *.dll + - $(RM) *.lib + - $(RM) pthread.h + - $(RM) semaphore.h + - $(RM) sched.h + - $(RM) *.e + - $(RM) *.i + - $(RM) *.obj + - $(RM) *.tds + - $(RM) *.pdb + - $(RM) *.o + - $(RM) *.asm + - $(RM) *.exe + - $(RM) *.pass + - $(RM) *.bench + - $(RM) *.log + +benchtest1.bench: +benchtest2.bench: +benchtest3.bench: +benchtest4.bench: +benchtest5.bench: +barrier1.pass: semaphore4.pass +barrier2.pass: barrier1.pass +barrier3.pass: barrier2.pass +barrier4.pass: barrier3.pass +barrier5.pass: barrier4.pass +cancel1.pass: create1.pass +cancel2.pass: cancel1.pass +cancel3.pass: context1.pass +cancel4.pass: cancel3.pass +cancel5.pass: cancel3.pass +cancel6a.pass: cancel3.pass +cancel6d.pass: cancel3.pass +cancel7.pass: kill1.pass +cancel8.pass: cancel7.pass +cancel9.pass: cancel8.pass +cleanup0.pass: cancel5.pass +cleanup1.pass: cleanup0.pass +cleanup2.pass: cleanup1.pass +cleanup3.pass: cleanup2.pass +condvar1.pass: +condvar1_1.pass: condvar1.pass +condvar1_2.pass: join2.pass +condvar2.pass: condvar1.pass +condvar2_1.pass: condvar2.pass join2.pass +condvar3.pass: create1.pass condvar2.pass +condvar3_1.pass: condvar3.pass join2.pass +condvar3_2.pass: condvar3_1.pass +condvar3_3.pass: condvar3_2.pass +condvar4.pass: create1.pass +condvar5.pass: condvar4.pass +condvar6.pass: condvar5.pass +condvar7.pass: condvar6.pass cleanup1.pass +condvar8.pass: condvar7.pass +condvar9.pass: condvar8.pass +context1.pass: cancel2.pass +count1.pass: join1.pass +create1.pass: mutex2.pass +create2.pass: create1.pass +create3.pass: +delay1.pass: +delay2.pass: delay1.pass +detach1.pass: join0.pass +equal1.pass: create1.pass +errno1.pass: mutex3.pass +exception1.pass: cancel4.pass +exception2.pass: exception1.pass +exception3.pass: exception2.pass +exit1.pass: +exit2.pass: create1.pass +exit3.pass: create1.pass +exit4.pass: +exit5.pass: kill1.pass +eyal1.pass: tsd1.pass +inherit1.pass: join1.pass priority1.pass +join0.pass: create1.pass +join1.pass: create1.pass +join2.pass: create1.pass +join3.pass: join2.pass +kill1.pass: +loadfree.pass: pthread.dll +mutex1.pass: self1.pass +mutex1n.pass: mutex1.pass +mutex1e.pass: mutex1.pass +mutex1r.pass: mutex1.pass +mutex2.pass: mutex1.pass +mutex2r.pass: mutex2.pass +mutex2e.pass: mutex2.pass +mutex3.pass: create1.pass +mutex3r.pass: mutex3.pass +mutex3e.pass: mutex3.pass +mutex4.pass: mutex3.pass +mutex5.pass: +mutex6.pass: mutex4.pass +mutex6n.pass: mutex4.pass +mutex6e.pass: mutex4.pass +mutex6r.pass: mutex4.pass +mutex6s.pass: mutex6.pass +mutex6rs.pass: mutex6r.pass +mutex6es.pass: mutex6e.pass +mutex7.pass: mutex6.pass +mutex7n.pass: mutex6n.pass +mutex7e.pass: mutex6e.pass +mutex7r.pass: mutex6r.pass +mutex8.pass: mutex7.pass +mutex8n.pass: mutex7n.pass +mutex8e.pass: mutex7e.pass +mutex8r.pass: mutex7r.pass +once1.pass: create1.pass +once2.pass: once1.pass +once3.pass: once2.pass +once4.pass: once3.pass +priority1.pass: join1.pass +priority2.pass: priority1.pass barrier3.pass +reuse1.pass: create2.pass +reuse2.pass: reuse1.pass +rwlock1.pass: condvar6.pass +rwlock2.pass: rwlock1.pass +rwlock3.pass: rwlock2.pass +rwlock4.pass: rwlock3.pass +rwlock5.pass: rwlock4.pass +rwlock6.pass: rwlock5.pass +rwlock7.pass: rwlock6.pass +rwlock8.pass: rwlock7.pass +rwlock2_t.pass: rwlock2.pass +rwlock3_t.pass: rwlock2_t.pass +rwlock4_t.pass: rwlock3_t.pass +rwlock5_t.pass: rwlock4_t.pass +rwlock6_t.pass: rwlock5_t.pass +rwlock6_t2.pass: rwlock6_t.pass +self1.pass: +self2.pass: create1.pass +semaphore1.pass: +semaphore2.pass: +semaphore3.pass: semaphore2.pass +semaphore4.pass: semaphore3.pass cancel1.pass +semaphore4t.pass: semaphore4.pass +semaphore5.pass: semaphore4.pass +sizes.pass: +spin1.pass: +spin2.pass: spin1.pass +spin3.pass: spin2.pass +spin4.pass: spin3.pass +stress1.pass: +tsd1.pass: barrier5.pass join1.pass +tsd2.pass: tsd1.pass +valid1.pass: join1.pass +valid2.pass: valid1.pass diff --git a/liblo/pthreads.2/tests/ChangeLog b/liblo/pthreads.2/tests/ChangeLog new file mode 100644 index 0000000..d1f71ad --- /dev/null +++ b/liblo/pthreads.2/tests/ChangeLog @@ -0,0 +1,894 @@ +2005-06-12 Ross Johnson + + * stress1.c (millisecondsFromNow): Remove limit 0 <= millisecs < 1000; + now works for -INT_MAX <= millisecs <= INT_MAX; not needed for + stress1.c but should be general anyway. + +2005-05-18 Ross Johnson + + * reuse2.c (main): Must use a read with memory barrier semantics + when polling 'done' to force the cache into coherence on MP systems. + +2005-05-15 Ross Johnson + + * detach1.c: New test. + * join1.c: Reduce sleep times. + * join0.c: Remove MSVCRT conditional compile - join should always + return the thread exit code. + * join1.c: Likewise. + * join2.c: Likewise. + * join3.c: Likewise. + +2005-04-18 Ross Johnson + + * condvar3.c: Remove locks from around signalling calls - should not + be required for normal operation and only serve to mask deficiencies; + ensure that CV destruction is not premature after removing guards. + * condvar3_1.c: Likewise. + * condvar3_2.c: Likewise. + * condvar3_3.c: Likewise. + * condvar4.c: Likewise. + * condvar5.c: Likewise. + * condvar6.c: Likewise. + * condvar7.c: Likewise. + * condvar8.c: Likewise. + * condvar9.c: Likewise. + +2005-04-11 Ross Johnson + + * once4.c: New test; tries to test priority adjustments + in pthread_once(); set priority class to realtime so that + any failures can be seen. + +2005-04-06 Ross Johnson + + * cleanup0.c: Fix unguarded global variable accesses. + * cleanup1.c: Likewise. + * cleanup2.c: Likewise. + * cleanup3.c: Likewise. + * once2.c: Likewise. + * once3.c: Likewise. + +2005-04-01 Ross Johnson + + * GNUmakefile: Add target to test linking static link library. + * Makefile: Likewise. + * self1.c: Run process attach/detach routines when static linked. + +2005-03-16 Ross Johnson + + * mutex5.c: Prevent optimiser from removing asserts. + +2005-03-12 Ross Johnson + + * once3.c: New test. + +2005-03-08 Ross Johnson + + * once2.c: New test. + +2004-11-19 Ross Johnson + + * Bmakefile: New makefile for Borland. + * Makefile (DLL_VER): Added. + * GNUmakefile (DLL_VER): Added. + * Wmakefile (DLL_VER): Added. + +2004-10-29 Ross Johnson + + * semaphore4.c: New test. + * semaphore4t.c: New test. + * Debug.dsp (et al): Created MSVC Workspace project to aid debugging. + * All: Many tests have been modified to work with the new pthread + ID type; some other corrections were made after some library + functions were semantically strengthened. For example, + pthread_cond_destroy() no longer destroys a busy CV, which + required minor redesigns of some tests, including some where + the mutex associated with the CV was not locked during + signaling and broadcasting. + +2004-10-23 Ross Johnson + + * condvar3.c: Fixed mutex operations that were incorrectly + placed in relation to their condition variable operations. + The error became evident after sem_destroy() was rewritten + and conditions for destroing the semaphore were tightened. + As a result, pthread_cond_destroy() was not able to + destroy the cv queueing sempahore. + * condvar3_1.c: Likewise. + * condvar3_2.c: Likewise. + * condvar4.c: Likewise. + * condvar5.c: Likewise. + * condvar6.c: Likewise. + * condvar7.c: Likewise. + * condvar8.c: Likewise. + * condvar9.c: Likewise. + +2004-10-19 Ross Johnson + + * semaphore3.c: New test. + +2004-10-14 Ross Johnson + + * rwlock7.c (main): Tidy up statistics reporting; randomise + update accesses. + * rwlock8.c: New test. + +2004-09-08 Alexandre Girao + + * cancel7.c (main): Win98 wants a valid (non-NULL) location + for the last arg of _beginthreadex(). + * cancel8.c (main): Likewise. + * exit4.c (main): Likewise. + * exit5.c (main): Likewise. + +2004-08-26 Ross Johnson + + * create3.c: New test. + +2004-06-21 Ross Johnson + + * mutex2r.c: New test. + * mutex2e.c: New test. + * mutex3r.c: New test. + * mutex3e.c: New test. + * mutex6s.c: New test. + * mutex6rs.c: New test. + * mutex6es.c: New test. + +2004-05-21 Ross Johnson + + * join3.c: New test. + +2004-05-16 Ross Johnson + + * condvar2.c (WIN32_WINNT): Define to avoid redefinition warning + from inclusion of implement.h. + * convar2_1.c: Likewise. + * condvar3_1.c: Likewise. + * condvar3_2.c: Likewise. + * context1.c: Likewise. + * sizes.c: Likewise. + * Makefile: Don't define _WIN32_WINNT on compiler command line. + * GNUmakefile: Likewise. + * priority1.c (main): Add column to output for actual win32 + priority. + +2004-05-16 Ross Johnson + + * cancel9.c: New test. + * cancel3.c: Remove inappropriate conditional compilation; + GNU C version of test suite no longer quietly skips this test. + * cancel5.c: Likewise. + * GNUmakefile: Can now build individual test app using default + C version of library using 'make clean testname.c'. + * Makefile: Likewise for VC using 'nmake clean test testname.c'. + +2003-10-14 Ross Johnson + + * Wmakefile: New makefile for Watcom testing. + +2003-09-18 Ross Johnson + + * benchtest.h: Move old mutex code into benchlib.c. + * benchlib.c: New statically linked module to ensure that + bench apps don't inline the code and therefore have an unfair + advantage over the pthreads lib routines. Made little or no + difference. + * benchtest1.c: Minor change to avoid compiler warnings. + * benchtest5.c: Likewise. + * benchtest2.c: Fix misinformation in output report. + * README.BENCH: Add comments on results. + +2003-09-14 Ross Johnson + + * priority1.c: Reworked to comply with modified priority + management and provide additional output. + * priority2.c: Likewise. + * inherit1.c: Likewise. + +2003-09-03 Ross Johnson + + * exit4.c: New test. + * exit5.c: New test. + * cancel7.c: New test. + * cancel8.c: New test. + +2003-08-13 Ross Johnson + + * reuse1.c: New test. + * reuse1.c: New test. + * valid1.c: New test. + * valid2.c: New test. + * kill1.c: New test. + * create2.c: Now included in test regime. + +2003-07-19 Ross Johnson + + * eyal1.c (waste_time): Make threads do more work to ensure that + all threads get to do some work. + * semaphore1.c: Make it clear that certain errors are expected. + * exception2.c (non_MSVC code sections): Change to include + C++ standard include file, i.e. change to . + * exception3.c (non_MSVC code sections): Likewise; qualify std:: + namespace entities where necessary. + * GNUmakefile: modified to work in the MsysDTK (newer MinGW) + environment; define CC as gcc or g++ as appropriate because + using gcc -x c++ doesn't link with required c++ libs by default, + but g++ does. + +2002-12-11 Ross Johnson + + * mutex7e.c: Assert EBUSY return instead of EDEADLK. + +2002-06-03 Ross Johnson + + * semaphore2.c: New test. + +2002-03-02 Ross Johnson + + * Makefile (CFLAGS): Changed /MT to /MD to link with + the correct library MSVCRT.LIB. Otherwise errno doesn't + work. + +2002-02-28 Ross Johnson + + * exception3.c: Correct recent change. + + * semaphore1.c: New test. + + * Makefile: Add rule to generate pre-processor output. + +2002-02-28 Ross Johnson + + * exception3.c (terminateFunction): For MSVC++, call + exit() rather than pthread_exit(). Add comments to explain + why. + * Notes from the MSVC++ manual: + * 1) A term_func() should call exit(), otherwise + * abort() will be called on return to the caller. + * abort() raises SIGABRT. The default signal handler + * for all signals terminates the calling program with + * exit code 3. + * 2) A term_func() must not throw an exception. Therefore + * term_func() should not call pthread_exit() if an + * an exception-using version of pthreads-win32 library + * is being used (i.e. either pthreadVCE or pthreadVSE). + + +2002-02-23 Ross Johnson + + * rwlock2_t.c: New test. + * rwlock3_t.c: New test. + * rwlock4_t.c: New test. + * rwlock5_t.c: New test. + * rwlock6_t.c: New test. + * rwlock6_t2.c: New test. + * rwlock6.c (main): Swap thread and result variables + to correspond to actual thread functions. + * rwlock1.c: Change test description comment to correspond + to the actual test. + + * condvar1_2.c: Loop over the test many times in the hope + of detecting any intermittent deadlocks. This is to + test a fixed problem in pthread_cond_destroy.c. + + * spin4.c: Remove unused variable. + +2002-02-17 Ross Johnson + + * condvar1_1.c: New test. + * condvar1_2.c: New test. + +2002-02-07 Ross Johnson + + * delay1.c: New test. + * delay2.c: New test. + * exit4.c: New test. + +2002-02-02 Ross Johnson + + * mutex8: New test. + * mutex8n: New test. + * mutex8e: New test. + * mutex8r: New test. + * cancel6a: New test. + * cancel6d: New test. + * cleanup0.c: Add pragmas for inline optimisation control. + * cleanup1.c: Add pragmas for inline optimisation control. + * cleanup2.c: Add pragmas for inline optimisation control. + * cleanup3.c: Add pragmas for inline optimisation control. + * condvar7.c: Add pragmas for inline optimisation control. + * condvar8.c: Add pragmas for inline optimisation control. + * condvar9.c: Add pragmas for inline optimisation control. + +2002-01-30 Ross Johnson + + * cleanup1.c (): Must be declared __cdecl when compiled + as C++ AND testing the standard C library version. + +2002-01-16 Ross Johnson + + * spin4.c (main): Fix renamed function call. + +2002-01-14 Ross Johnson + + * exception3.c (main): Shorten wait time. + +2002-01-09 Ross Johnson + + * mutex7.c: New test. + * mutex7n.c: New test. + * mutex7e.c: New test. + * mutex7r.c: New test. + * mutex6.c: Modified to avoid leaving the locked mutex + around on exit. + +2001-10-25 Ross Johnson + + * condvar2.c: Remove reference to cv->nWaitersUnblocked. + * condvar2_1.c: Likewise; lower NUMTHREADS from 60 to 30. + * condvar3_1.c: Likewise. + * condvar3_2.c: Likewise. + * count1.c: lower NUMTHREADS from 60 to 30. + * inherit1.c: Determine valid priority values and then + assert values returned by POSIX routines are the same. + * priority1.c: Likewise. + * priority2.c: Likewise. + +2001-07-12 Ross Johnson + + * barrier5.c: Assert that precisely one thread receives + PTHREAD_BARRIER_SERIAL_THREAD at each barrier. + +2001-07-09 Ross Johnson + + * barrier3.c: Fixed. + * barrier4.c: Fixed. + * barrier5.c: New; proves that all threads in the group + reaching the barrier wait and then resume together. Repeats the test + using groups of 1 to 16 threads. Each group of threads must negotiate + a large number of barriers (10000). + * spin4.c: Fixed. + * test.h (error_string): Modified the success (0) value. + +2001-07-07 Ross Johnson + + * spin3.c: Changed test and fixed. + * spin4.c: Fixed. + * barrier3.c: Fixed. + * barrier4.c: Fixed. + +2001-07-05 Ross Johnson + + * spin1.c: New; testing spinlocks. + * spin2.c: New; testing spinlocks. + * spin3.c: New; testing spinlocks. + * spin4.c: New; testing spinlocks. + * barrier1.c: New; testing barriers. + * barrier2.c: New; testing barriers. + * barrier3.c: New; testing barriers. + * barrier4.c: New; testing barriers. + * GNUmakefile: Add new tests. + * Makefile: Add new tests. + +2001-07-01 Ross Johnson + + * benchtest3.c: New; timing mutexes. + * benchtest4.c: New; time mutexes. + * condvar3_1.c: Fixed bug - Alexander Terekhov + * condvar3_3.c: New test. + +2001-06-25 Ross Johnson + + * priority1.c: New test. + * priority2.c: New test. + * inherit1.c: New test. + * benchtest1.c: New; timing mutexes. + * benchtest2.c: New; timing mutexes. + * mutex4.c: Modified to test all mutex types. + +2001-06-8 Ross Johnson + + * mutex5.c: Insert inert change to quell compiler warnings. + * condvar3_2.c: Remove unused variable. + +2001-06-3 Ross Johnson + + * condvar2_1.c: New test. + * condvar3_1.c: New test. + * condvar3_2.c: New test. + +2001-05-30 Ross Johnson + + * mutex1n.c: New test. + * mutex1e.c: New test. + * mutex1r.c: New test. + * mutex4.c: Now locks and unlocks a mutex. + * mutex5.c: New test. + * mutex6.c: New test. + * mutex6n.c: New test. + * mutex6e.c: New test. + * mutex6r.c: New test. + * Makefile: Added new tests; reorganised. + * GNUmakefile: Likewise. + * rwlock6.c: Fix to properly prove read-while-write locking + and single writer locking. + +2001-05-29 Ross Johnson + + * Makefile: Reorganisation. + * GNUmakefile: Likewise. + - Thomas Pfaff + + * exception1.c: Add stdio.h include to define fprintf and stderr + in non-exception C version of main(). + * exception2.c: Likewise. + * exception3.c: Likewise. + + * Makefile (rwlock7): Add new test. + * GNUmakefile (rwlock7): Add new test. + * rwlock7.c: New test. + * rwlock6.c: Changed to test that writer has priority. + + * eyal1.c (main): Unlock each mutex_start lock before destroying + it. + +2000-12-29 Ross Johnson + + * GNUmakefile: Add mutex4 test; ensure libpthreadw32.a is + removed for "clean" target. + * Makefile: Add mutex4 test. + + * exception3.c: Remove SEH code; automatically pass the test + under SEH (which is an N/A environment). + + * mutex4.c: New test. + + * eyal1.c (do_work_unit): Add a dummy "if" to force the + optimiser to retain code; reduce thread work loads. + + * condvar8.c (main): Add an additional "assert" for debugging; + increase pthread_cond_signal timeout. + +2000-12-28 Ross Johnson + + * eyal1.c: Increase thread work loads. + * exception2.c: New test. + * exception3.c: New test. + * Makefile: Add new tests exception2.c and exception3.c. + * GNUmakefile: Likewise. + +2000-12-11 Ross Johnson + + * cleanup3.c: Remove unused variable. + * cleanup2.c: Likewise. + * exception1.c: Throw an exception rather than use + a deliberate zero divide so that catch(...) will + handle it under Mingw32. Mingw32 now builds the + library correctly to pass all tests - see Thomas + Pfaff's detailed instructions re needed changes + to Mingw32 in the Pthreads-Win32 FAQ. + +2000-09-08 Ross Johnson + + * cancel5.c: New; tests calling pthread_cancel() + from the main thread without first creating a + POSIX thread struct for the non-POSIX main thread + - this forces pthread_cancel() to create one via + pthread_self(). + * Makefile (cancel5): Add new test. + * GNUmakefile (cancel5): Likewise. + +2000-08-17 Ross Johnson + + * create2.c: New; Test that pthread_t contains + the W32 HANDLE before it calls the thread routine + proper. + +2000-08-13 Ross Johnson + + * condvar3.c: Minor change to eliminate compiler + warning. + + * condvar4.c: ditto. + + * condvar5.c: ditto. + + * condvar6.c: ditto. + + * condvar7.c: ditto. + + * condvar8.c: ditto. + + * condvar9.c: ditto. + + * exit1.c: Function needed return statement. + + * cleanup1.c: Remove unnecessary printf arg. + + * cleanup2.c: Fix cast. + + * rwlock6.c: Fix casts. + + * exception1.c (PtW32CatchAll): Had the wrong name; + fix casts. + + * cancel3.c: Remove unused waitLock variable. + + * GNUmakefile: Change library/dll naming; add new tests; + general minor changes. + + * Makefile: Change library/dll naming; add targets for + testing each of the two VC++ EH scheme versions; + default target now issues help message; compile warnings + now interpreted as errors to stop the make; add new + tests; restructure to remove prerequisites needed + otherwise. + + * README: Updated. + + +2000-08-10 Ross Johnson + + * eyal1.c (main): Change implicit cast to explicit + cast when passing "print_server" function pointer; + G++ no longer allows implicit func parameter casts. + + * cleanup1.c: Remove unused "waitLock". + (main): Fix implicit parameter cast. + + * cancel2.c (main): Fix implicit parameter cast. + + * cancel4.c (main): Fix implicit parameter cast. + + * cancel3.c (main): Fix implicit parameter cast. + + * GNUmakefile: Renamed from Makefile; Add missing + cancel1 and cancel2 test targets. + + * Makefile: Converted for use with MS nmake. + +2000-08-06 Ross Johnson + + * ccl.bat: Add /nologo to remove extraneous output. + + * exception1.c (exceptionedThread): Init 'dummy'; + put expression into if condition to prevent optimising away; + remove unused variable. + + * cancel4.c (mythread): Cast return value to avoid warnings. + + * cancel2.c (mythread): Missing #endif. + + * condvar9.c (mythread): Cast return value to avoid warnings. + + * condvar8.c (mythread): Cast return value to avoid warnings. + + * condvar7.c (mythread): Cast return value to avoid warnings. + + * cleanup3.c (mythread): Cast return value to avoid warnings. + + * cleanup2.c (mythread): Cast return value to avoid warnings. + + * cleanup1.c (mythread): Cast return value to avoid warnings. + + * condvar5.c (mythread): Cast return value to avoid warnings. + + * condvar3.c (mythread): Cast return value to avoid warnings. + + * condvar6.c (mythread): Cast return value to avoid warnings. + + * condvar4.c (mythread): Cast return value to avoid warnings. + +2000-08-05 Ross Johnson + + * cancel2.c: Use PtW32CatchAll macro if defined. + + * exception1.c: Use PtW32CatchAll macro if defined. + +2000-08-02 Ross Johnson + + * tsd1.c: Fix typecasts of &result [g++ is now very fussy]. + + * test.h (assert): Return 0's explicitly to allay + g++ errors. + + * join2.c: Add explicit typecasts. + + * join1.c: Add explicit typecasts. + + * join0.c: Add explicit typecasts. + + * eyal1.c: Add explicit typecasts. + + * count1.c (main): Add type cast to remove g++ parse warning + [gcc-2.95.2 seems to have tightened up on this]. + + * Makefile (GLANG): Use c++ explicitly. + Remove MSVC sections (was commented out). + Add target to generate cpp output. + +2000-07-25 Ross Johnson + + * runtest.bat: modified to work under W98. + + * runall.bat: Add new tests; modified to work under W98. + It was ok under NT. + + * Makefile: Add new tests. + + * exception1.c: New; Test passing exceptions back to the + application and retaining library internal exceptions. + + * join0.c: New; Test a single join. + +2000-01-06 Ross Johnson + + * cleanup1.c: New; Test cleanup handler executes (when thread is + canceled). + + * cleanup2.c: New; Test cleanup handler executes (when thread is + not canceled). + + * cleanup3.c: New; Test cleanup handler does not execute + (when thread is not canceled). + +2000-01-04 Ross Johnson + + * cancel4.c: New; Test cancelation does not occur in deferred + cancelation threads with no cancelation points. + + * cancel3.c: New; Test asynchronous cancelation. + + * context1.c: New; Test context switching method for async + cancelation. + +1999-11-23 Ross Johnson + + * test.h: Add header includes; include local header versions rather + than system versions; rearrange the assert macro defines. + +1999-11-07 Ross Johnson + + * loadfree.c: New. Test loading and freeing the library (DLL). + +1999-10-30 Ross Johnson + + * cancel1.c: New. Test pthread_setcancelstate and + pthread_setcanceltype functions. + * eyal1.c (waste_time): Change calculation to avoid FP exception + on Aplhas + - Rich Peters + +Oct 14 1999 Ross Johnson + + * condvar7.c: New. Test broadcast after waiting thread is canceled. + * condvar8.c: New. Test multiple broadcasts. + * condvar9.c: New. Test multiple broadcasts with thread + cancelation. + +Sep 16 1999 Ross Johnson + + * rwlock6.c: New test. + +Sep 15 1999 Ross Johnson + + * rwlock1.c: New test. + * rwlock2.c: New test. + * rwlock3.c: New test. + * rwlock4.c: New test. + * rwlock5.c: New test. + +Aug 22 1999 Ross Johnson + + * runall.bat (join2): Add test. + +Aug 19 1999 Ross Johnson + + * join2.c: New test. + +Wed Aug 12 1999 Ross Johnson + + * Makefile (LIBS): Add -L. + +Mon May 31 10:25:01 1999 Ross Johnson + + * Makefile (GLANG): Add GCC language option. + +Sat May 29 23:29:04 1999 Ross Johnson + + * runall.bat (condvar5): Add new test. + + * runall.bat (condvar6): Add new test. + + * Makefile (condvar5) : Add new test. + + * Makefile (condvar6) : Add new test. + + * condvar5.c: New test for pthread_cond_broadcast(). + + * condvar6.c: New test for pthread_cond_broadcast(). + +Sun Apr 4 12:04:28 1999 Ross Johnson + + * tsd1.c (mythread): Change Sleep(0) to sched_yield(). + (sched.h): Include. + + * condvar3.c (mythread): Remove redundant Sleep(). + + * runtest.bat: Re-organised to make more informative. + +Fri Mar 19 1999 Ross Johnson + + * *.bat: redirect unwanted output to nul: + + * runall.bat: new. + + * cancel1.c: new. Not part of suite yet. + +Mon Mar 15 00:17:55 1999 Ross Johnson + + * mutex1.c: only test mutex init and destroy; add assertions. + + * count1.c: raise number of spawned threads to 60 (appears to + be the limit under Win98). + +Sun Mar 14 21:31:02 1999 Ross Johnson + + * test.h (assert): add assertion trace option. + Use: + "#define ASSERT_TRACE 1" to turn it on, + "#define ASSERT_TRACE 0" to turn it off (default). + + * condvar3.c (main): add more assertions. + + * condvar4.c (main): add more assertions. + + * condvar1.c (main): add more assertions. + +Fri Mar 12 08:34:15 1999 Ross Johnson + + * condvar4.c (cvthing): switch the order of the INITIALIZERs. + + * eyal1.c (main): Fix trylock loop; was not waiting for thread to lock + the "started" mutex. + +Wed Mar 10 10:41:52 1999 Ross Johnson + + * tryentercs.c: Apply typo patch from bje. + + * tryentercs2.c: Ditto. + +Sun Mar 7 10:41:52 1999 Ross Johnson + + * Makefile (condvar3, condvar4): Add tests. + + * condvar4.c (General): Reduce to simple test case; prerequisite + is condvar3.c; add description. + + * condvar3.c (General): Reduce to simple test case; prerequisite + is condvar2.c; add description. + + * condvar2.c (General): Reduce to simple test case; prerequisite + is condvar1.c; add description. + + * condvar1.c (General): Reduce to simple test case; add + description. + + * Template.c (Comments): Add generic test detail. + +1999-02-23 Ross Johnson + + * Template.c: Revamp. + + * condvar1.c: Add. + + * condvar2.c: Add. + + * Makefile: Add condvar1 condvar2 tests. + + * exit1.c, exit2.c, exit3.c: Cosmetic changes. + +1999-02-23 Ross Johnson + + * Makefile: Some refinement. + + * *.c: More exhaustive checking through assertions; clean up; + add some more tests. + + * Makefile: Now actually runs the tests. + + * tests.h: Define our own assert macro. The Mingw32 + version pops up a dialog but we want to run non-interactively. + + * equal1.c: use assert a little more directly so that it + prints the actual call statement. + + * exit1.c: Modify to return 0 on success, 1 on failure. + +1999-02-22 Ross Johnson + + * self2.c: Bring up to date. + + * self3.c: Ditto. + +1999-02-21 Ben Elliston + + * README: Update. + + * Makefile: New file. Run all tests automatically. Primitive tests + are run first; more complex tests are run last. + + * count1.c: New test. Validate the thread count. + + * exit2.c: Perform a simpler test. + + * exit3.c: New test. Replaces exit2.c, since exit2.c needs to + perform simpler checking first. + + * create1.c: Update to use the new testsuite exiting convention. + + * equal1.c: Likewise. + + * mutex1.c: Likewise. + + * mutex2.c: Likewise. + + * once1.c: Likewise. + + * self2.c: Likewise. + + * self3.c: Likewise. + + * tsd1.c: Likewise. + +1999-02-20 Ross Johnson + + * mutex2.c: Test static mutex initialisation. + + * test.h: New. Declares a table mapping error numbers to + error names. + +1999-01-17 Ross Johnson + + * runtest: New script to build and run a test in the tests directory. + +Wed Dec 30 11:22:44 1998 Ross Johnson + + * tsd1.c: Re-written. See comments at start of file. + * Template.c: New. Contains skeleton code and comment template + intended to fully document the test. + +Fri Oct 16 17:59:49 1998 Ross Johnson + + * tsd1.c (destroy_key): Add function. Change diagnostics. + +Thu Oct 15 17:42:37 1998 Ross Johnson + + * tsd1.c (mythread): Fix some casts and add some message + output. Fix inverted conditional. + +Mon Oct 12 02:12:29 1998 Ross Johnson + + * tsd1.c: New. Test TSD using 1 key and 2 threads. + +1998-09-13 Ben Elliston + + * eyal1.c: New file; contributed by Eyal Lebedinsky + . + +1998-09-12 Ben Elliston + + * exit2.c (func): Return a value. + (main): Call the right thread entry function. + +1998-07-22 Ben Elliston + + * exit2.c (main): Fix size of pthread_t array. + +1998-07-10 Ben Elliston + + * exit2.c: New file; test pthread_exit() harder. + + * exit1.c: New file; test pthread_exit(). diff --git a/liblo/pthreads.2/tests/Debug.dsp b/liblo/pthreads.2/tests/Debug.dsp new file mode 100644 index 0000000..7a35ffd --- /dev/null +++ b/liblo/pthreads.2/tests/Debug.dsp @@ -0,0 +1,93 @@ +# Microsoft Developer Studio Project File - Name="Debug" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Debug - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Debug.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Debug.mak" CFG="Debug - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Debug - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Debug - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Debug - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0xc09 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "Debug - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /WX /Gm /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "CLEANUP_C" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0xc09 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pthreadVC2d.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:".." + +!ENDIF + +# Begin Target + +# Name "Debug - Win32 Release" +# Name "Debug - Win32 Debug" +# Begin Source File + +SOURCE=.\Debug.txt +# End Source File +# Begin Source File + +SOURCE=.\semaphore1.c +# End Source File +# End Target +# End Project diff --git a/liblo/pthreads.2/tests/Debug.dsw b/liblo/pthreads.2/tests/Debug.dsw new file mode 100644 index 0000000..cb90db8 --- /dev/null +++ b/liblo/pthreads.2/tests/Debug.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Debug"=.\Debug.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/liblo/pthreads.2/tests/Debug.txt b/liblo/pthreads.2/tests/Debug.txt new file mode 100644 index 0000000..16b1da7 --- /dev/null +++ b/liblo/pthreads.2/tests/Debug.txt @@ -0,0 +1,6 @@ +This project is used to debug individual test case programs. + +To build and debug a test case: +- add the .c file to this project; +- remove any .c files from other test cases from this project. +- build and debug as usual. \ No newline at end of file diff --git a/liblo/pthreads.2/tests/GNUmakefile b/liblo/pthreads.2/tests/GNUmakefile new file mode 100644 index 0000000..3ea79ee --- /dev/null +++ b/liblo/pthreads.2/tests/GNUmakefile @@ -0,0 +1,375 @@ +# Makefile for the pthreads test suite. +# If all of the .pass files can be created, the test suite has passed. +# +# -------------------------------------------------------------------------- +# +# Pthreads-win32 - POSIX Threads Library for Win32 +# Copyright(C) 1998 John E. Bossom +# Copyright(C) 1999,2005 Pthreads-win32 contributors +# +# Contact Email: rpj@callisto.canberra.edu.au +# +# The current list of contributors is contained +# in the file CONTRIBUTORS included with the source +# code distribution. The list can also be seen at the +# following World Wide Web location: +# http://sources.redhat.com/pthreads-win32/contributors.html +# +# This library 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 2 of the License, or (at your option) any later version. +# +# This library 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 library in the file COPYING.LIB; +# if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# + +DLL_VER = 2 + +CP = cp -f +MV = mv -f +RM = rm -f +CAT = cat +#CP = copy +#MV = rename +#RM = erase +#CAT = type +MKDIR = mkdir +TOUCH = echo Passed > +ECHO = @echo +MAKE = make + +# +# Mingw32 +# +XXCFLAGS = +XXLIBS = -lws2_32 +#CFLAGS = -O3 -UNDEBUG -Wall $(XXCFLAGS) +CFLAGS = -g -UNDEBUG -Wall $(XXCFLAGS) +BUILD_DIR = .. +INCLUDES = -I. + + +TEST = GC + +# Default lib version +GCX = $(TEST)$(DLL_VER) + +# Files we need to run the tests +# - paths are relative to pthreads build dir. +HDR = pthread.h semaphore.h sched.h +LIB = libpthread$(GCX).a +DLL = pthread$(GCX).dll +QAPC = ../QueueUserAPCEx/User/quserex.dll + +COPYFILES = $(HDR) $(LIB) $(DLL) $(QAPC) + +# If a test case returns a non-zero exit code to the shell, make will +# stop. + +TESTS = sizes loadfree \ + self1 mutex5 mutex1 mutex1e mutex1n mutex1r \ + semaphore1 semaphore2 semaphore3 \ + condvar1 condvar1_1 condvar1_2 condvar2 condvar2_1 exit1 \ + create1 create2 reuse1 reuse2 equal1 \ + kill1 valid1 valid2 \ + exit2 exit3 exit4 exit5 \ + join0 join1 detach1 join2 join3 \ + mutex2 mutex2r mutex2e mutex3 mutex3r mutex3e \ + mutex4 mutex6 mutex6n mutex6e mutex6r \ + mutex6s mutex6es mutex6rs \ + mutex7 mutex7n mutex7e mutex7r mutex8 mutex8n mutex8e mutex8r \ + count1 \ + once1 once2 once3 once4 self2 \ + cancel1 cancel2 \ + semaphore4 semaphore4t semaphore5 \ + barrier1 barrier2 barrier3 barrier4 barrier5 \ + tsd1 tsd2 delay1 delay2 eyal1 \ + condvar3 condvar3_1 condvar3_2 condvar3_3 \ + condvar4 condvar5 condvar6 condvar7 condvar8 condvar9 \ + errno1 \ + rwlock1 rwlock2 rwlock3 rwlock4 rwlock5 rwlock6 rwlock7 rwlock8 \ + rwlock2_t rwlock3_t rwlock4_t rwlock5_t rwlock6_t rwlock6_t2 \ + context1 cancel3 cancel4 cancel5 cancel6a cancel6d \ + cancel7 cancel8 \ + cleanup0 cleanup1 cleanup2 cleanup3 \ + priority1 priority2 inherit1 \ + spin1 spin2 spin3 spin4 \ + exception1 exception2 exception3 \ + cancel9 create3 stress1 + +STRESSTESTS = \ + stress1 + +BENCHTESTS = \ + benchtest1 benchtest2 benchtest3 benchtest4 benchtest5 + +STATICTESTS = \ + self1 + +PASSES = $(TESTS:%=%.pass) +BENCHRESULTS = $(BENCHTESTS:%=%.bench) +STRESSRESULTS = $(STRESSTESTS:%=%.pass) +STATICRESULTS = $(STATICTESTS:%=%.pass) + +help: + @ $(ECHO) "Run one of the following command lines:" + @ $(ECHO) "make clean GC (to test using GC dll with C (no EH) applications)" + @ $(ECHO) "make clean GCX (to test using GC dll with C++ (EH) applications)" + @ $(ECHO) "make clean GCE (to test using GCE dll with C++ (EH) applications)" + @ $(ECHO) "make clean GC-bench (to benchtest using GNU C dll with C cleanup code)" + @ $(ECHO) "make clean GCE-bench (to benchtest using GNU C dll with C++ exception handling)" + @ $(ECHO) "make clean GC-stress (to stresstest using GNU C dll with C cleanup code)" + @ $(ECHO) "make clean GCE-stress (to stresstest using GNU C dll with C++ exception handling)" + @ $(ECHO) "make clean GC-static (to test using GC static lib with C (no EH) applications)" + +all: + @ $(MAKE) clean GC + @ $(MAKE) clean GCX + @ $(MAKE) clean GCE + +GC: + $(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" all-pass + +GCE: + $(MAKE) TEST=GCE CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_CXX" all-pass + +GCX: + $(MAKE) TEST=GC CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_C" all-pass + +GC-bench: + $(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" XXLIBS="benchlib.o" all-bench + +GCE-bench: + $(MAKE) TEST=GCE CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_CXX" XXLIBS="benchlib." all-bench + +GC-debug: + $(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" DLL_VER="$(DLL_VER)d" all-pass + +GC-static: + $(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C -DPTW32_STATIC_LIB" DLL="" all-static + +GC-stress: + $(ECHO) Stress tests can take a long time since they are trying to + $(ECHO) expose weaknesses that may be intermittant or statistically rare. + $(ECHO) A pass does not prove correctness, but may give greater confidence. + $(MAKE) TEST=GC CC=gcc XXCFLAGS="-D__CLEANUP_C" all-stress + +GCE-stress: + $(MAKE) TEST=GCE CC=g++ XXCFLAGS="-mthreads -D__CLEANUP_CXX" all-stress + +all-pass: $(PASSES) + @ $(ECHO) ALL TESTS PASSED! Congratulations! + +all-bench: $(BENCHRESULTS) + @ $(ECHO) BENCH TESTS COMPLETED. + +all-stress: $(STRESSRESULTS) + @ $(ECHO) STRESS TESTS COMPLETED. + +all-static: $(STATICRESULTS) + @ $(ECHO) ALL STATIC TESTS PASSED! Congratulations! + @ $(ECHO) Build and test the DLL to run all tests. + @ $(ECHO) This test only confirms that the static lib links correctly. + +benchtest1.bench: +benchtest2.bench: +benchtest3.bench: +benchtest4.bench: +benchtest5.bench: + +barrier1.pass: semaphore4.pass +barrier2.pass: barrier1.pass +barrier3.pass: barrier2.pass +barrier4.pass: barrier3.pass +barrier5.pass: barrier4.pass +cancel1.pass: create1.pass +cancel2.pass: cancel1.pass +cancel2_1.pass: cancel2.pass +cancel3.pass: context1.pass +cancel4.pass: cancel3.pass +cancel5.pass: cancel3.pass +cancel6a.pass: cancel3.pass +cancel6d.pass: cancel3.pass +cancel7.pass: kill1.pass +cancel8.pass: cancel7.pass +cancel9.pass: cancel8.pass +cleanup0.pass: cancel5.pass +cleanup1.pass: cleanup0.pass +cleanup2.pass: cleanup1.pass +cleanup3.pass: cleanup2.pass +condvar1.pass: +condvar1_1.pass: condvar1.pass +condvar1_2.pass: join2.pass +condvar2.pass: condvar1.pass +condvar2_1.pass: condvar2.pass join2.pass +condvar3.pass: create1.pass condvar2.pass +condvar3_1.pass: condvar3.pass join2.pass +condvar3_2.pass: condvar3_1.pass +condvar3_3.pass: condvar3_2.pass +condvar4.pass: create1.pass +condvar5.pass: condvar4.pass +condvar6.pass: condvar5.pass +condvar7.pass: condvar6.pass cleanup1.pass +condvar8.pass: condvar7.pass +condvar9.pass: condvar8.pass +context1.pass: cancel2.pass +count1.pass: join1.pass +create1.pass: mutex2.pass +create2.pass: create1.pass +create3.pass: +delay1.pass: cancel2.pass +delay2.pass: delay1.pass +detach1.pass: join0.pass +equal1.pass: create1.pass +errno1.pass: mutex3.pass +exception1.pass: cancel4.pass +exception2.pass: exception1.pass +exception3.pass: exception2.pass +exit1.pass: +exit2.pass: create1.pass +exit3.pass: create1.pass +exit4.pass: +exit5.pass: exit4.pass kill1.pass +eyal1.pass: tsd1.pass +inherit1.pass: join1.pass priority1.pass +join0.pass: create1.pass +join1.pass: create1.pass +join2.pass: create1.pass +join3.pass: join2.pass +kill1.pass: +loadfree.pass: pthread.dll +mutex1.pass: self1.pass +mutex1n.pass: mutex1.pass +mutex1e.pass: mutex1.pass +mutex1r.pass: mutex1.pass +mutex2.pass: mutex1.pass +mutex2r.pass: mutex2.pass +mutex2e.pass: mutex2.pass +mutex3.pass: create1.pass +mutex3r.pass: mutex3.pass +mutex3e.pass: mutex3.pass +mutex4.pass: mutex3.pass +mutex5.pass: +mutex6.pass: mutex4.pass +mutex6n.pass: mutex4.pass +mutex6e.pass: mutex4.pass +mutex6r.pass: mutex4.pass +mutex6s.pass: mutex6.pass +mutex6rs.pass: mutex6r.pass +mutex6es.pass: mutex6e.pass +mutex7.pass: mutex6.pass +mutex7n.pass: mutex6n.pass +mutex7e.pass: mutex6e.pass +mutex7r.pass: mutex6r.pass +mutex8.pass: mutex7.pass +mutex8n.pass: mutex7n.pass +mutex8e.pass: mutex7e.pass +mutex8r.pass: mutex7r.pass +once1.pass: create1.pass +once2.pass: once1.pass +once3.pass: once2.pass +once4.pass: once3.pass +priority1.pass: join1.pass +priority2.pass: priority1.pass barrier3.pass +reuse1.pass: create2.pass +reuse2.pass: reuse1.pass +rwlock1.pass: condvar6.pass +rwlock2.pass: rwlock1.pass +rwlock3.pass: rwlock2.pass +rwlock4.pass: rwlock3.pass +rwlock5.pass: rwlock4.pass +rwlock6.pass: rwlock5.pass +rwlock7.pass: rwlock6.pass +rwlock8.pass: rwlock7.pass +rwlock2_t.pass: rwlock2.pass +rwlock3_t.pass: rwlock2_t.pass +rwlock4_t.pass: rwlock3_t.pass +rwlock5_t.pass: rwlock4_t.pass +rwlock6_t.pass: rwlock5_t.pass +rwlock6_t2.pass: rwlock6_t.pass +self1.pass: +self2.pass: create1.pass +semaphore1.pass: +semaphore2.pass: +semaphore3.pass: semaphore2.pass +semaphore4.pass: semaphore3.pass cancel1.pass +semaphore4t.pass: semaphore4.pass +semaphore5.pass: semaphore4.pass +sizes.pass: +spin1.pass: +spin2.pass: spin1.pass +spin3.pass: spin2.pass +spin4.pass: spin3.pass +stress1.pass: +tsd1.pass: barrier5.pass join1.pass +tsd2.pass: tsd1.pass +valid1.pass: join1.pass +valid2.pass: valid1.pass + +sizes.pass: sizes.exe + @ $(ECHO) Running $* + $< > SIZES.$(TEST) + @ $(CAT) SIZES.$(TEST) + @ $(ECHO) Passed + @ $(TOUCH) $@ + +%.pass: %.exe + @ $(ECHO) Running $* + $* + @ $(ECHO) Passed + @ $(TOUCH) $@ + +%.bench: $(LIB) $(DLL) $(HDR) $(QAPC) $(XXLIBS) %.exe + @ $(ECHO) Running $* + $* + @ $(ECHO) Done + @ $(TOUCH) $@ + +%.exe: %.c $(LIB) $(DLL) $(HDR) $(QAPC) + @ $(ECHO) Compiling $@ + @ $(ECHO) $(CC) $(CFLAGS) -o $@ $< $(INCLUDES) -L. -lpthread$(GCX) -lsupc++ $(XXLIBS) + @ $(CC) $(CFLAGS) -o $@ $< $(INCLUDES) -L. -lpthread$(GCX) -lsupc++ $(XXLIBS) + +%.pre: %.c $(HDR) + @ $(CC) -E $(CFLAGS) -o $@ $< $(INCLUDES) + +%.s: %.c $(HDR) + @ $(CC) -S $(CFLAGS) -o $@ $< $(INCLUDES) + +$(COPYFILES): + @ $(ECHO) Copying $@ + @ $(CP) $(BUILD_DIR)/$@ . + +benchlib.o: benchlib.c + @ $(ECHO) Compiling $@ + @ $(ECHO) $(CC) -c $(CFLAGS) $< $(INCLUDES) + @ $(CC) -c $(CFLAGS) $< $(INCLUDES) + +pthread.dll: $(DLL) + @ $(CP) $(DLL) $@ + +clean: + - $(RM) *.dll + - $(RM) *.lib + - $(RM) pthread.h + - $(RM) semaphore.h + - $(RM) sched.h + - $(RM) *.a + - $(RM) *.e + - $(RM) *.i + - $(RM) *.o + - $(RM) *.obj + - $(RM) *.pdb + - $(RM) *.exe + - $(RM) *.pass + - $(RM) *.bench + - $(RM) *.static + - $(RM) *.log diff --git a/liblo/pthreads.2/tests/Makefile b/liblo/pthreads.2/tests/Makefile new file mode 100644 index 0000000..9b4c635 --- /dev/null +++ b/liblo/pthreads.2/tests/Makefile @@ -0,0 +1,404 @@ +# Makefile for the pthreads test suite. +# If all of the .pass files can be created, the test suite has passed. +# +# -------------------------------------------------------------------------- +# +# Pthreads-win32 - POSIX Threads Library for Win32 +# Copyright(C) 1998 John E. Bossom +# Copyright(C) 1999,2005 Pthreads-win32 contributors +# +# Contact Email: rpj@callisto.canberra.edu.au +# +# The current list of contributors is contained +# in the file CONTRIBUTORS included with the source +# code distribution. The list can also be seen at the +# following World Wide Web location: +# http://sources.redhat.com/pthreads-win32/contributors.html +# +# This library 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 2 of the License, or (at your option) any later version. +# +# This library 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 library in the file COPYING.LIB; +# if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# + +DLL_VER = 2 + +CP = copy +RM = erase +CAT = type +MKDIR = mkdir +TOUCH = echo Passed > +ECHO = @echo + +QAPC = ..\QueueUserAPCEx\User\quserex.dll + +CPHDR = pthread.h semaphore.h sched.h + +OPTIM = /O2 /Ob0 + +XXLIBS = ws2_32.lib + +# C++ Exceptions +VCEFLAGS = /GX /TP /DPtW32NoCatchWarn /D__CLEANUP_CXX +VCELIB = pthreadVCE$(DLL_VER).lib +VCEDLL = pthreadVCE$(DLL_VER).dll +# Structured Exceptions +VSEFLAGS = /D__CLEANUP_SEH +VSELIB = pthreadVSE$(DLL_VER).lib +VSEDLL = pthreadVSE$(DLL_VER).dll +# C cleanup code +VCFLAGS = /D__CLEANUP_C +VCLIB = pthreadVC$(DLL_VER).lib +VCDLL = pthreadVC$(DLL_VER).dll +# C++ Exceptions in application - using VC version of pthreads dll +VCXFLAGS = /GX /TP /D__CLEANUP_C + +# Defaults +CPLIB = $(VCLIB) +CPDLL = $(VCDLL) + +CFLAGS= $(OPTIM) /W3 /WX /MD /nologo /Yd /Zi +LFLAGS= /INCREMENTAL:NO +INCLUDES=-I. +BUILD_DIR=.. + +COPYFILES = $(CPHDR) $(CPLIB) $(CPDLL) $(QAPC) + +TEST = +EHFLAGS = + +# If a test case returns a non-zero exit code to the shell, make will +# stop. + +PASSES= sizes.pass loadfree.pass \ + self1.pass mutex5.pass \ + mutex1.pass mutex1n.pass mutex1e.pass mutex1r.pass \ + semaphore1.pass semaphore2.pass semaphore3.pass \ + mutex2.pass mutex3.pass \ + mutex2r.pass mutex2e.pass mutex3r.pass mutex3e.pass \ + condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass \ + exit1.pass create1.pass create2.pass reuse1.pass reuse2.pass equal1.pass \ + kill1.pass valid1.pass valid2.pass \ + exit2.pass exit3.pass exit4.pass exit5.pass \ + join0.pass join1.pass detach1.pass join2.pass join3.pass \ + mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass \ + mutex6s.pass mutex6es.pass mutex6rs.pass \ + mutex7.pass mutex7n.pass mutex7e.pass mutex7r.pass \ + mutex8.pass mutex8n.pass mutex8e.pass mutex8r.pass \ + count1.pass \ + once1.pass once2.pass once3.pass once4.pass \ + self2.pass \ + cancel1.pass cancel2.pass \ + semaphore4.pass semaphore4t.pass semaphore5.pass \ + barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass \ + tsd1.pass tsd2.pass delay1.pass delay2.pass eyal1.pass \ + condvar3.pass condvar3_1.pass condvar3_2.pass condvar3_3.pass \ + condvar4.pass condvar5.pass condvar6.pass \ + condvar7.pass condvar8.pass condvar9.pass \ + errno1.pass \ + rwlock1.pass rwlock2.pass rwlock3.pass rwlock4.pass \ + rwlock5.pass rwlock6.pass rwlock7.pass rwlock8.pass \ + rwlock2_t.pass rwlock3_t.pass rwlock4_t.pass rwlock5_t.pass rwlock6_t.pass rwlock6_t2.pass \ + context1.pass \ + cancel3.pass cancel4.pass cancel5.pass cancel6a.pass cancel6d.pass \ + cancel7.pass cancel8.pass \ + cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass \ + priority1.pass priority2.pass inherit1.pass \ + spin1.pass spin2.pass spin3.pass spin4.pass \ + exception1.pass exception2.pass exception3.pass \ + cancel9.pass create3.pass stress1.pass + +BENCHRESULTS = \ + benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench + +STRESSRESULTS = \ + stress1.stress + +STATICRESULTS = \ + self1.pass + +help: + @ $(ECHO) Run one of the following command lines: + @ $(ECHO) nmake clean VC (to test using VC dll with VC (no EH) apps) + @ $(ECHO) nmake clean VC-bench (to benchtest using VC dll with C bench apps) + @ $(ECHO) nmake clean VC-stress (to stresstest using VC dll with C stress apps) + @ $(ECHO) nmake clean VC-static (to test using VC static lib with VC (no EH) apps) + @ $(ECHO) nmake clean VCX (to test using VC dll with VC++ (EH) applications) + @ $(ECHO) nmake clean VCX-bench (to benchtest using VC dll with C++ bench apps) + @ $(ECHO) nmake clean VCX-stress (to stresstest using VC dll with C++ stress apps) + @ $(ECHO) nmake clean VCE (to test using the VCE dll with VC++ EH applications) + @ $(ECHO) nmake clean VCE-bench (to benchtest using VCE dll with C++ bench apps) + @ $(ECHO) nmake clean VCE-stress (to stresstest using VCE dll with C++ stress apps) + @ $(ECHO) nmake clean VSE (to test using VSE dll with VC (SEH) apps) + @ $(ECHO) nmake clean VSE-bench (to benchtest using VSE dll with SEH bench apps) + @ $(ECHO) nmake clean VSE-stress (to stresstest using VSE dll with SEH stress apps) + +all: + @ nmake clean VC + @ nmake clean VCX + @ nmake clean VCE + @ nmake clean VSE + @ nmake clean VC-bench + @ nmake clean VC-stress + +# This allows an individual test application to be made using the default lib. +# e.g. nmake clean test cancel3.exe +test: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) + +tests: $(CPLIB) $(CPDLL) $(CPHDR) $(QAPC) $(PASSES) + @ $(ECHO) ALL TESTS PASSED! Congratulations! + +benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(XXLIBS) $(BENCHRESULTS) + @ $(ECHO) ALL BENCH TESTS DONE. + +stresstests: $(CPLIB) $(CPDLL) $(CPHDR) $(STRESSRESULTS) + @ $(ECHO) ALL STRESS TESTS DONE. + +statictests: $(CPLIB) $(CPDLL) $(CPHDR) $(STATICRESULTS) + @ $(ECHO) ALL STATIC TESTS DONE. + @ $(ECHO) Build and test the DLL to run all tests. + @ $(ECHO) The static test only confirms that the .lib links correctly. + +sizes.pass: sizes.exe + @ $(ECHO) ... Running $(TEST)$(DLL_VER) test: $*.exe + @ .\$*.exe > SIZES.$(TEST) + @ $(CAT) SIZES.$(TEST) + @ $(ECHO) ...... Passed + @ $(TOUCH) $*.pass + +$(PASSES): $*.exe + @ $(ECHO) ... Running $(TEST) test: $*.exe + @ .\$*.exe + @ $(ECHO) ...... Passed + @ $(TOUCH) $*.pass + +$(BENCHRESULTS): $*.exe + @ $(ECHO) ... Running $(TEST) benchtest: $*.exe + @ .\$*.exe + @ $(ECHO) ...... Done + @ $(TOUCH) $*.bench + +$(STRESSRESULTS): $*.exe + @ $(ECHO) ... Running $(TEST) stresstest: $*.exe + @ .\$*.exe + @ $(ECHO) ...... Done + @ $(TOUCH) $*.pass + +VC: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" tests + +VCE: + @ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" tests + +VSE: + @ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" tests + +VCX: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" tests + +VC-bench: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" XXLIBS="benchlib.o" benchtests + +VCE-bench: + @ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" XXLIBS="benchlib.o" benchtests + +VSE-bench: + @ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" XXLIBS="benchlib.o" benchtests + +VCX-bench: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" XXLIBS="benchlib.o" benchtests + +VC-stress: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCFLAGS)" stresstests + +VCE-stress: + @ nmake TEST="$@" CPLIB="$(VCELIB)" CPDLL="$(VCEDLL)" EHFLAGS="$(VCEFLAGS)" stresstests + +VSE-stress: + @ nmake TEST="$@" CPLIB="$(VSELIB)" CPDLL="$(VSEDLL)" EHFLAGS="$(VSEFLAGS)" stresstests + +VCX-stress: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="$(VCDLL)" EHFLAGS="$(VCXFLAGS)" stresstests + +VC-static: + @ nmake TEST="$@" CPLIB="$(VCLIB)" CPDLL="" EHFLAGS="$(VCFLAGS) /DPTW32_STATIC_LIB" statictests + +.c.exe: + @ $(ECHO) $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< /Fe$@ /link $(LFLAGS) $(CPLIB) $(XXLIBS) + @ $(CC) $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< /Fe$@ /link $(LFLAGS) $(CPLIB) $(XXLIBS) + +.c.o: + @ $(ECHO) $(CC) $(EHFLAGS) /c $(CFLAGS) $(INCLUDES) $< /Fo$@ + @ $(CC) $(EHFLAGS) $(CFLAGS) /c $(INCLUDES) $< /Fo$@ + +.c.i: + @ $(CC) /P $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< + +$(COPYFILES): + @ $(ECHO) Copying $@ + @ $(CP) $(BUILD_DIR)\$@ . + +pthread.dll: $(CPDLL) + @ $(CP) $(CPDLL) pthread.dll + @ $(CP) $(CPLIB) pthread.lib + +clean: + - $(RM) *.dll + - $(RM) *.lib + - $(RM) pthread.h + - $(RM) semaphore.h + - $(RM) sched.h + - $(RM) *.e + - $(RM) *.i + - $(RM) *.obj + - $(RM) *.pdb + - $(RM) *.o + - $(RM) *.asm + - $(RM) *.exe + - $(RM) *.pass + - $(RM) *.bench + - $(RM) *.log + +benchtest1.bench: +benchtest2.bench: +benchtest3.bench: +benchtest4.bench: +benchtest5.bench: + +barrier1.pass: semaphore4.pass +barrier2.pass: barrier1.pass +barrier3.pass: barrier2.pass +barrier4.pass: barrier3.pass +barrier5.pass: barrier4.pass +cancel1.pass: create1.pass +cancel2.pass: cancel1.pass +cancel3.pass: context1.pass +cancel4.pass: cancel3.pass +cancel5.pass: cancel3.pass +cancel6a.pass: cancel3.pass +cancel6d.pass: cancel3.pass +cancel7.pass: kill1.pass +cancel8.pass: cancel7.pass +cancel9.pass: cancel8.pass +cleanup0.pass: cancel5.pass +cleanup1.pass: cleanup0.pass +cleanup2.pass: cleanup1.pass +cleanup3.pass: cleanup2.pass +condvar1.pass: +condvar1_1.pass: condvar1.pass +condvar1_2.pass: join2.pass +condvar2.pass: condvar1.pass +condvar2_1.pass: condvar2.pass join2.pass +condvar3.pass: create1.pass condvar2.pass +condvar3_1.pass: condvar3.pass join2.pass +condvar3_2.pass: condvar3_1.pass +condvar3_3.pass: condvar3_2.pass +condvar4.pass: create1.pass +condvar5.pass: condvar4.pass +condvar6.pass: condvar5.pass +condvar7.pass: condvar6.pass cleanup1.pass +condvar8.pass: condvar7.pass +condvar9.pass: condvar8.pass +context1.pass: cancel2.pass +count1.pass: join1.pass +create1.pass: mutex2.pass +create2.pass: create1.pass +create3.pass: +delay1.pass: +delay2.pass: delay1.pass +detach1.pass: join0.pass +equal1.pass: create1.pass +errno1.pass: mutex3.pass +exception1.pass: cancel4.pass +exception2.pass: exception1.pass +exception3.pass: exception2.pass +exit1.pass: +exit2.pass: create1.pass +exit3.pass: create1.pass +exit4.pass: +exit5.pass: kill1.pass +eyal1.pass: tsd1.pass +inherit1.pass: join1.pass priority1.pass +join0.pass: create1.pass +join1.pass: create1.pass +join2.pass: create1.pass +join3.pass: join2.pass +kill1.pass: +loadfree.pass: pthread.dll +mutex1.pass: self1.pass +mutex1n.pass: mutex1.pass +mutex1e.pass: mutex1.pass +mutex1r.pass: mutex1.pass +mutex2.pass: mutex1.pass +mutex2r.pass: mutex2.pass +mutex2e.pass: mutex2.pass +mutex3.pass: create1.pass +mutex3r.pass: mutex3.pass +mutex3e.pass: mutex3.pass +mutex4.pass: mutex3.pass +mutex5.pass: +mutex6.pass: mutex4.pass +mutex6n.pass: mutex4.pass +mutex6e.pass: mutex4.pass +mutex6r.pass: mutex4.pass +mutex6s.pass: mutex6.pass +mutex6rs.pass: mutex6r.pass +mutex6es.pass: mutex6e.pass +mutex7.pass: mutex6.pass +mutex7n.pass: mutex6n.pass +mutex7e.pass: mutex6e.pass +mutex7r.pass: mutex6r.pass +mutex8.pass: mutex7.pass +mutex8n.pass: mutex7n.pass +mutex8e.pass: mutex7e.pass +mutex8r.pass: mutex7r.pass +once1.pass: create1.pass +once2.pass: once1.pass +once3.pass: once2.pass +once4.pass: once3.pass +priority1.pass: join1.pass +priority2.pass: priority1.pass barrier3.pass +reuse1.pass: create2.pass +reuse2.pass: reuse1.pass +rwlock1.pass: condvar6.pass +rwlock2.pass: rwlock1.pass +rwlock3.pass: rwlock2.pass +rwlock4.pass: rwlock3.pass +rwlock5.pass: rwlock4.pass +rwlock6.pass: rwlock5.pass +rwlock7.pass: rwlock6.pass +rwlock8.pass: rwlock7.pass +rwlock2_t.pass: rwlock2.pass +rwlock3_t.pass: rwlock2_t.pass +rwlock4_t.pass: rwlock3_t.pass +rwlock5_t.pass: rwlock4_t.pass +rwlock6_t.pass: rwlock5_t.pass +rwlock6_t2.pass: rwlock6_t.pass +self1.pass: +self2.pass: create1.pass +semaphore1.pass: +semaphore2.pass: +semaphore3.pass: semaphore2.pass +semaphore4.pass: semaphore3.pass cancel1.pass +semaphore4t.pass: semaphore4.pass +semaphore5.pass: semaphore4.pass +sizes.pass: +spin1.pass: +spin2.pass: spin1.pass +spin3.pass: spin2.pass +spin4.pass: spin3.pass +stress1.pass: condvar9.pass barrier5.pass +tsd1.pass: barrier5.pass join1.pass +tsd2.pass: tsd1.pass +valid1.pass: join1.pass +valid2.pass: valid1.pass diff --git a/liblo/pthreads.2/tests/README.BENCHTESTS b/liblo/pthreads.2/tests/README.BENCHTESTS new file mode 100644 index 0000000..adb8cbd --- /dev/null +++ b/liblo/pthreads.2/tests/README.BENCHTESTS @@ -0,0 +1,74 @@ + +------------ +Benchmarking +------------ +There is a set a benchmarking programs in the +"tests" directory. These should be runnable using the +following command-lines corresponding to each of the possible +library builds: + +MSVC: +nmake clean VC-bench +nmake clean VCE-bench +nmake clean VSE-bench + +Mingw32: +make clean GC-bench +make clean GCE-bench + +UWIN: +The benchtests are run as part of the testsuite. + + +Mutex benchtests +---------------- + +benchtest1 - Lock plus unlock on an unlocked mutex. +benchtest2 - Lock plus unlock on a locked mutex. +benchtest3 - Trylock on a locked mutex. +benchtest4 - Trylock plus unlock on an unlocked mutex. + + +Each test times up to three alternate synchronisation +implementations as a reference, and then times each of +the four mutex types provided by the library. Each is +described below: + +Simple Critical Section +- uses a simple Win32 critical section. There is no +additional overhead for this case as there is in the +remaining cases. + +POSIX mutex implemented using a Critical Section +- The old implementation which uses runtime adaptation +depending on the Windows variant being run on. When +the pthreads DLL was run on WinNT or higher then +POSIX mutexes would use Win32 Critical Sections. + +POSIX mutex implemented using a Win32 Mutex +- The old implementation which uses runtime adaptation +depending on the Windows variant being run on. When +the pthreads DLL was run on Win9x then POSIX mutexes +would use Win32 Mutexes (because TryEnterCriticalSection +is not implemented on Win9x). + +PTHREAD_MUTEX_DEFAULT +PTHREAD_MUTEX_NORMAL +PTHREAD_MUTEX_ERRORCHECK +PTHREAD_MUTEX_RECURSIVE +- The current implementation supports these mutex types. +The underlying basis of POSIX mutexes is now the same +irrespective of the Windows variant, and should therefore +have consistent performance. + + +Semaphore benchtests +-------------------- + +benchtest5 - Timing for various uncontended cases. + + +In all benchtests, the operation is repeated a large +number of times and an average is calculated. Loop +overhead is measured and subtracted from all test times. + diff --git a/liblo/pthreads.2/tests/SIZES.VCE b/liblo/pthreads.2/tests/SIZES.VCE new file mode 100644 index 0000000..d010b21 --- /dev/null +++ b/liblo/pthreads.2/tests/SIZES.VCE @@ -0,0 +1,21 @@ +Sizes of pthreads-win32 structs +------------------------------- + pthread_t 8 + ptw32_thread_t 76 + pthread_attr_t_ 28 + sem_t_ 12 + pthread_mutex_t_ 24 + pthread_mutexattr_t_ 8 + pthread_spinlock_t_ 8 + pthread_barrier_t_ 24 + pthread_barrierattr_t_ 4 + pthread_key_t_ 16 + pthread_cond_t_ 32 + pthread_condattr_t_ 4 + pthread_rwlock_t_ 28 + pthread_rwlockattr_t_ 4 + pthread_once_t_ 16 + ptw32_cleanup_t 12 + ptw32_mcs_node_t_ 16 + sched_param 4 +------------------------------- diff --git a/liblo/pthreads.2/tests/Wmakefile b/liblo/pthreads.2/tests/Wmakefile new file mode 100644 index 0000000..da53ab6 --- /dev/null +++ b/liblo/pthreads.2/tests/Wmakefile @@ -0,0 +1,346 @@ +# Watcom makefile for the pthreads test suite. +# If all of the .pass files can be created, the test suite has passed. +# +# -------------------------------------------------------------------------- +# +# Pthreads-win32 - POSIX Threads Library for Win32 +# Copyright(C) 1998 John E. Bossom +# Copyright(C) 1999,2005 Pthreads-win32 contributors +# +# Contact Email: rpj@callisto.canberra.edu.au +# +# The current list of contributors is contained +# in the file CONTRIBUTORS included with the source +# code distribution. The list can also be seen at the +# following World Wide Web location: +# http://sources.redhat.com/pthreads-win32/contributors.html +# +# This library 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 2 of the License, or (at your option) any later version. +# +# This library 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 library in the file COPYING.LIB; +# if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# + + +DLL_VER = 2 + +.EXTENSIONS: + +.EXTENSIONS: .pass .exe .obj .i .c + +CP = copy +RM = erase +CAT = type +MKDIR = mkdir +TOUCH = echo Passed > +ECHO = @echo + +CPHDR = pthread.h semaphore.h sched.h + +OPTIM = -od + +XXLIBS = + +# C++ Exceptions +WCEFLAGS = -xs -dPtW32NoCatchWarn -d__CLEANUP_CXX +WCELIB = pthreadWCE$(DLL_VER).lib +WCEDLL = pthreadWCE$(DLL_VER).dll +# C cleanup code +WCFLAGS = -d__CLEANUP_C +WCLIB = pthreadWC$(DLL_VER).lib +WCDLL = pthreadWC$(DLL_VER).dll +# C++ Exceptions in application - using WC version of pthreads dll +WCXFLAGS = -xs -d__CLEANUP_C + +CFLAGS= -w4 -e25 -d_WIN32_WINNT=0x400 -d_REENTRANT -zq -bm $(OPTIM) -5r -bt=nt -mf -d2 + +LFLAGS= +INCLUDES= -i=. +BUILD_DIR=.. + +COPYFILES = $(CPHDR) $(CPLIB) $(CPDLL) + +TEST = +EHFLAGS = + +# If a test case returns a non-zero exit code to the shell, make will +# stop. + +PASSES = sizes.pass loadfree.pass & + self1.pass mutex5.pass & + mutex1.pass mutex1n.pass mutex1e.pass mutex1r.pass & + semaphore1.pass semaphore2.pass semaphore3.pass & + mutex2.pass mutex3.pass & + mutex2r.pass mutex2e.pass mutex3r.pass mutex3e.pass & + condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass & + exit1.pass create1.pass create2.pass reuse1.pass reuse2.pass equal1.pass & + kill1.pass valid1.pass valid2.pass & + exit2.pass exit3.pass exit4 exit5 & + join0.pass join1.pass detach1.pass join2.pass join3.pass & + mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass & + mutex6s.pass mutex6es.pass mutex6rs.pass & + mutex7.pass mutex7n.pass mutex7e.pass mutex7r.pass & + mutex8.pass mutex8n.pass mutex8e.pass mutex8r.pass & + count1.pass & + once1.pass once2.pass once3.pass once4.pass tsd1.pass & + self2.pass & + cancel1.pass cancel2.pass & + semaphore4.pass semaphore4t.pass semaphore5.pass & + delay1.pass delay2.pass eyal1.pass & + condvar3.pass condvar3_1.pass condvar3_2.pass condvar3_3.pass & + condvar4.pass condvar5.pass condvar6.pass & + condvar7.pass condvar8.pass condvar9.pass & + errno1.pass & + rwlock1.pass rwlock2.pass rwlock3.pass rwlock4.pass rwlock5.pass & + rwlock6.pass rwlock7.pass rwlock8.pass & + rwlock2_t.pass rwlock3_t.pass rwlock4_t.pass rwlock5_t.pass rwlock6_t.pass rwlock6_t2.pass & + context1.pass & + cancel3.pass cancel4.pass cancel5.pass cancel6a.pass cancel6d.pass & + cancel7 cancel8 & + cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass & + priority1.pass priority2.pass inherit1.pass & + spin1.pass spin2.pass spin3.pass spin4.pass & + barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass & + exception1.pass exception2.pass exception3.pass & + cancel9.pass create3.pass stress1.pass + +BENCHRESULTS = & + benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench + +help: .SYMBOLIC + @ $(ECHO) Run one of the following command lines: + @ $(ECHO) wmake /f Wmakefile clean WC (to test using WC dll with wcc386 (no EH) applications) + @ $(ECHO) wmake /f Wmakefile clean WCX (to test using WC dll with wpp386 (EH) applications) + @ $(ECHO) wmake /f Wmakefile clean WCE (to test using the WCE dll with wpp386 EH applications) + @ $(ECHO) wmake /f Wmakefile clean WC-bench (to benchtest using WC dll with C bench app) + @ $(ECHO) wmake /f Wmakefile clean WCX-bench (to benchtest using WC dll with C++ bench app) + @ $(ECHO) wmake /f Wmakefile clean WCE-bench (to benchtest using WCE dll with C++ bench app) + +all: .SYMBOLIC + @ wmake /f Wmakefile clean WC + @ wmake /f Wmakefile clean WCX + @ wmake /f Wmakefile clean WCE + @ wmake /f Wmakefile clean WSE + @ wmake /f Wmakefile clean WC-bench + +tests: $(CPLIB) $(CPDLL) $(CPHDR) $(PASSES) .SYMBOLIC + @ $(ECHO) ALL TESTS PASSED! Congratulations! + +benchtests: $(CPLIB) $(CPDLL) $(CPHDR) $(XXLIBS) $(BENCHRESULTS) .SYMBOLIC + @ $(ECHO) ALL BENCH TESTS DONE. + +$(BENCHRESULTS): ($[*).exe + @ $(ECHO) ... Running $(TEST) benchtest: ($[*).exe + @ .\($[*).exe + @ $(ECHO) ...... Done + @ $(TOUCH) ($[*).bench + +WCE: .SYMBOLIC + @ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCELIB)" CPDLL="$(WCEDLL)" EHFLAGS="$(WCEFLAGS)" tests + +WC: .SYMBOLIC + @ wmake /f Wmakefile CC=wcc386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCFLAGS)" tests + +WCX: .SYMBOLIC + @ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCXFLAGS)" tests + +WCE-bench: .SYMBOLIC + @ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCELIB)" CPDLL="$(WCEDLL)" EHFLAGS="$(WCEFLAGS)" XXLIBS="benchlib.o" benchtests + +WC-bench: .SYMBOLIC + @ wmake /f Wmakefile CC=wcc386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCFLAGS)" XXLIBS="benchlib.o" benchtests + +WCX-bench: .SYMBOLIC + @ wmake /f Wmakefile CC=wpp386 TEST="$@" CPLIB="$(WCLIB)" CPDLL="$(WCDLL)" EHFLAGS="$(WCXFLAGS)" XXLIBS="benchlib.o" benchtests + +sizes.pass: sizes.exe + @ $(ECHO) ... Running $(TEST) test: $^* + @ $[@ > SIZES.$(TEST) + @ $(CAT) SIZES.$(TEST) + @ $(ECHO) ...... Passed + @ $(TOUCH) $^@ + +.exe.pass: + @ $(ECHO) ... Running $(TEST) test: $^* + @ $[@ + @ $(ECHO) ...... Passed + @ $(TOUCH) $^@ + +.obj.exe: + @ $(ECHO) wlink NAME $^@ FILE $[@ LIBRARY $(CPLIB) OPTION quiet + @ wlink NAME $^@ FILE $[@ LIBRARY $(CPLIB) OPTION quiet + +.c.obj: + @ $(ECHO) $(CC) $^* $(EHFLAGS) $(CFLAGS) $(INCLUDES) + @ $(CC) $^* $(EHFLAGS) $(CFLAGS) $(INCLUDES) + +.c.i: + @ $(CC) /P $(EHFLAGS) $(CFLAGS) $(INCLUDES) $< + +$(COPYFILES): .SYMBOLIC + @ $(ECHO) Copying $@ + @ $(CP) $(BUILD_DIR)\$@ . + +pthread.dll: + @ $(CP) $(CPDLL) $*.dll + @ $(CP) $(CPLIB) $*.lib + +clean: .SYMBOLIC + @ if exist *.dll $(RM) *.dll + @ if exist *.lib $(RM) *.lib + @ if exist *.err $(RM) *.err + @ if exist pthread.h $(RM) pthread.h + @ if exist semaphore.h $(RM) semaphore.h + @ if exist sched.h $(RM) sched.h + @ if exist *.e $(RM) *.e + @ if exist *.i $(RM) *.i + @ if exist *.obj $(RM) *.obj + @ if exist *.pdb $(RM) *.pdb + @ if exist *.o $(RM) *.o + @ if exist *.asm $(RM) *.asm + @ if exist *.exe $(RM) *.exe + @ if exist *.pass $(RM) *.pass + @ if exist *.bench $(RM) *.bench + @ if exist *.log $(RM) *.log + @ $(ECHO) Clean completed. + +benchtest1.bench: +benchtest2.bench: +benchtest3.bench: +benchtest4.bench: +benchtest5.bench: +barrier1.pass: +barrier2.pass: barrier1.pass +barrier3.pass: barrier2.pass +barrier4.pass: barrier3.pass +barrier5.pass: barrier4.pass +cancel1.pass: create1.pass +cancel2.pass: cancel1.pass +cancel3.pass: context1.pass +cancel4.pass: cancel3.pass +cancel5.pass: cancel3.pass +cancel6a.pass: cancel3.pass +cancel6d.pass: cancel3.pass +cancel7.pass: kill1.pass +cancel8.pass: cancel7.pass +cleanup0.pass: cancel5.pass +cleanup1.pass: cleanup0.pass +cleanup2.pass: cleanup1.pass +cleanup3.pass: cleanup2.pass +condvar1.pass: +condvar1_1.pass: condvar1.pass +condvar1_2.pass: join2.pass +condvar2.pass: condvar1.pass +condvar2_1.pass: condvar2.pass join2.pass +condvar3.pass: create1.pass condvar2.pass +condvar3_1.pass: condvar3.pass join2.pass +condvar3_2.pass: condvar3_1.pass +condvar3_3.pass: condvar3_2.pass +condvar4.pass: create1.pass +condvar5.pass: condvar4.pass +condvar6.pass: condvar5.pass +condvar7.pass: condvar6.pass cleanup1.pass +condvar8.pass: condvar7.pass +condvar9.pass: condvar8.pass +context1.pass: cancel2.pass +count1.pass: join1.pass +create1.pass: mutex2.pass +create2.pass: create1.pass +create3.pass: +delay1.pass: +delay2.pass: delay1.pass +detach1.pass: join0.pass +equal1.pass: create1.pass +errno1.pass: mutex3.pass +exception1.pass: cancel4.pass +exception2.pass: exception1.pass +exception3.pass: exception2.pass +exit1.pass: +exit2.pass: create1.pass +exit3.pass: create1.pass +exit4.pass: +exit5.pass: kill1.pass +eyal1.pass: tsd1.pass +inherit1.pass: join1.pass priority1.pass +join0.pass: create1.pass +join1.pass: create1.pass +join2.pass: create1.pass +join3.pass: join2.pass +kill1.pass: +loadfree.pass: pthread.dll +mutex1.pass: self1.pass +mutex1n.pass: mutex1.pass +mutex1e.pass: mutex1.pass +mutex1r.pass: mutex1.pass +mutex2.pass: mutex1.pass +mutex2r.pass: mutex2.pass +mutex2e.pass: mutex2.pass +mutex3.pass: create1.pass +mutex3r.pass: mutex3.pass +mutex3e.pass: mutex3.pass +mutex4.pass: mutex3.pass +mutex5.pass: +mutex6.pass: mutex4.pass +mutex6n.pass: mutex4.pass +mutex6e.pass: mutex4.pass +mutex6r.pass: mutex4.pass +mutex6s.pass: mutex6.pass +mutex6rs.pass: mutex6r.pass +mutex6es.pass: mutex6e.pass +mutex7.pass: mutex6.pass +mutex7n.pass: mutex6n.pass +mutex7e.pass: mutex6e.pass +mutex7r.pass: mutex6r.pass +mutex8.pass: mutex7.pass +mutex8n.pass: mutex7n.pass +mutex8e.pass: mutex7e.pass +mutex8r.pass: mutex7r.pass +once1.pass: create1.pass +once2.pass: once1.pass +once3.pass: once2.pass +once4.pass: once3.pass +priority1.pass: join1.pass +priority2.pass: priority1.pass barrier3.pass +reuse1.pass: create2.pass +reuse2.pass: reuse1.pass +rwlock1.pass: condvar6.pass +rwlock2.pass: rwlock1.pass +rwlock3.pass: rwlock2.pass +rwlock4.pass: rwlock3.pass +rwlock5.pass: rwlock4.pass +rwlock6.pass: rwlock5.pass +rwlock7.pass: rwlock6.pass +rwlock2_t.pass: rwlock2.pass +rwlock3_t.pass: rwlock2_t.pass +rwlock4_t.pass: rwlock3_t.pass +rwlock5_t.pass: rwlock4_t.pass +rwlock6_t.pass: rwlock5_t.pass +rwlock6_t2.pass: rwlock6_t.pass +self1.pass: +self2.pass: create1.pass +semaphore1.pass: +semaphore2.pass: +semaphore3.pass: semaphore2.pass +semaphore4.pass: semaphore3.pass cancel1.pass +semaphore4t.pass: semaphore4.pass +semaphore5.pass: semaphore4.pass +sizes.pass: +spin1.pass: +spin2.pass: spin1.pass +spin3.pass: spin2.pass +spin4.pass: spin3.pass +stress1.pass: +tsd1.pass: join1.pass +valid1.pass: join1.pass +valid2.pass: valid1.pass +cancel9.pass: cancel8.pass diff --git a/liblo/pthreads.2/tests/barrier1.c b/liblo/pthreads.2/tests/barrier1.c new file mode 100644 index 0000000..4854e1a --- /dev/null +++ b/liblo/pthreads.2/tests/barrier1.c @@ -0,0 +1,58 @@ +/* + * barrier1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create a barrier object and then destroy it. + * + */ + +#include "test.h" + +pthread_barrier_t barrier = NULL; + +int +main() +{ + assert(barrier == NULL); + + assert(pthread_barrier_init(&barrier, NULL, 1) == 0); + + assert(barrier != NULL); + + assert(pthread_barrier_destroy(&barrier) == 0); + + assert(barrier == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/barrier2.c b/liblo/pthreads.2/tests/barrier2.c new file mode 100644 index 0000000..a35a4ce --- /dev/null +++ b/liblo/pthreads.2/tests/barrier2.c @@ -0,0 +1,55 @@ +/* + * barrier2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a single barrier object, wait on it, + * and then destroy it. + * + */ + +#include "test.h" + +pthread_barrier_t barrier = NULL; + +int +main() +{ + assert(pthread_barrier_init(&barrier, NULL, 1) == 0); + + assert(pthread_barrier_wait(&barrier) == PTHREAD_BARRIER_SERIAL_THREAD); + + assert(pthread_barrier_destroy(&barrier) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/barrier3.c b/liblo/pthreads.2/tests/barrier3.c new file mode 100644 index 0000000..dbc8d4a --- /dev/null +++ b/liblo/pthreads.2/tests/barrier3.c @@ -0,0 +1,71 @@ +/* + * barrier3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a single barrier object with barrier attribute, wait on it, + * and then destroy it. + * + */ + +#include "test.h" + +pthread_barrier_t barrier = NULL; +static int result = 1; + +void * func(void * arg) +{ + return (void *) pthread_barrier_wait(&barrier); +} + +int +main() +{ + pthread_t t; + pthread_barrierattr_t ba; + + assert(pthread_barrierattr_init(&ba) == 0); + assert(pthread_barrierattr_setpshared(&ba, PTHREAD_PROCESS_PRIVATE) == 0); + assert(pthread_barrier_init(&barrier, &ba, 1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + + assert(result == PTHREAD_BARRIER_SERIAL_THREAD); + + assert(pthread_barrier_destroy(&barrier) == 0); + assert(pthread_barrierattr_destroy(&ba) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/barrier4.c b/liblo/pthreads.2/tests/barrier4.c new file mode 100644 index 0000000..30f4380 --- /dev/null +++ b/liblo/pthreads.2/tests/barrier4.c @@ -0,0 +1,110 @@ +/* + * barrier4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a single barrier object, multiple wait on it, + * and then destroy it. + * + */ + +#include "test.h" + +enum { + NUMTHREADS = 16 +}; + +pthread_barrier_t barrier = NULL; +pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; +static int serialThreadCount = 0; +static int otherThreadCount = 0; + +void * +func(void * arg) +{ + int result = pthread_barrier_wait(&barrier); + + assert(pthread_mutex_lock(&mx) == 0); + + if (result == PTHREAD_BARRIER_SERIAL_THREAD) + { + serialThreadCount++; + } + else if (0 == result) + { + otherThreadCount++; + } + else + { + printf("Barrier wait failed: error = %s\n", error_string[result]); + fflush(stdout); + return NULL; + } + assert(pthread_mutex_unlock(&mx) == 0); + + return NULL; +} + +int +main() +{ + int i, j; + pthread_t t[NUMTHREADS + 1]; + + for (j = 1; j <= NUMTHREADS; j++) + { + printf("Barrier height = %d\n", j); + + serialThreadCount = 0; + + assert(pthread_barrier_init(&barrier, NULL, j) == 0); + + for (i = 1; i <= j; i++) + { + assert(pthread_create(&t[i], NULL, func, NULL) == 0); + } + + for (i = 1; i <= j; i++) + { + assert(pthread_join(t[i], NULL) == 0); + } + + assert(serialThreadCount == 1); + + assert(pthread_barrier_destroy(&barrier) == 0); + } + + assert(pthread_mutex_destroy(&mx) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/barrier5.c b/liblo/pthreads.2/tests/barrier5.c new file mode 100644 index 0000000..1ddac6a --- /dev/null +++ b/liblo/pthreads.2/tests/barrier5.c @@ -0,0 +1,128 @@ +/* + * barrier5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a single barrier object, set up a sequence of + * barrier points to prove lockstepness, and then destroy it. + * + */ + +#include "test.h" + +enum { + NUMTHREADS = 16, + BARRIERS = 10000 +}; + +pthread_barrier_t barrier = NULL; +pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; + +int barrierReleases[BARRIERS + 1]; + +void * +func(void * barrierHeight) +{ + int i; + int result; + int serialThreads = 0; + + for (i = 1; i < BARRIERS; i++) + { + result = pthread_barrier_wait(&barrier); + + assert(pthread_mutex_lock(&mx) == 0); + barrierReleases[i]++; + assert(pthread_mutex_unlock(&mx) == 0); + /* + * Confirm the correct number of releases from the previous + * barrier. We can't do the current barrier yet because there may + * still be threads waking up. + */ + if (result == PTHREAD_BARRIER_SERIAL_THREAD) + { + serialThreads++; + assert(barrierReleases[i - 1] == (int) barrierHeight); + barrierReleases[i + 1] = 0; + } + else if (result != 0) + { + printf("Barrier failed: result = %s\n", error_string[result]); + fflush(stdout); + return NULL; + } + } + + return (void *) serialThreads; +} + +int +main() +{ + int i, j; + int result; + int serialThreadsTotal; + pthread_t t[NUMTHREADS + 1]; + + for (j = 1; j <= NUMTHREADS; j++) + { + printf("Barrier height = %d\n", j); + + barrierReleases[0] = j; + barrierReleases[1] = 0; + + assert(pthread_barrier_init(&barrier, NULL, j) == 0); + + for (i = 1; i <= j; i++) + { + assert(pthread_create(&t[i], NULL, func, (void *) j) == 0); + } + + serialThreadsTotal = 0; + for (i = 1; i <= j; i++) + { + assert(pthread_join(t[i], (void **) &result) == 0); + serialThreadsTotal += result; + } + + assert(serialThreadsTotal == BARRIERS - 1); + assert(barrierReleases[BARRIERS - 1] == j); + assert(barrierReleases[BARRIERS] == 0); + + assert(pthread_barrier_destroy(&barrier) == 0); + } + + assert(pthread_mutex_destroy(&mx) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/benchlib.c b/liblo/pthreads.2/tests/benchlib.c new file mode 100644 index 0000000..d28490a --- /dev/null +++ b/liblo/pthreads.2/tests/benchlib.c @@ -0,0 +1,363 @@ +/* + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#include "../config.h" + +#include "pthread.h" +#include "sched.h" +#include "semaphore.h" +#include +#include + +#ifdef __GNUC__ +#include +#endif + +#include "benchtest.h" + +int old_mutex_use = OLD_WIN32CS; + +BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL; +HINSTANCE ptw32_h_kernel32; + +void +dummy_call(int * a) +{ +} + +void +interlocked_inc_with_conditionals(int * a) +{ + if (a != NULL) + if (InterlockedIncrement((long *) a) == -1) + { + *a = 0; + } +} + +void +interlocked_dec_with_conditionals(int * a) +{ + if (a != NULL) + if (InterlockedDecrement((long *) a) == -1) + { + *a = 0; + } +} + +int +old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr) +{ + int result = 0; + old_mutex_t mx; + + if (mutex == NULL) + { + return EINVAL; + } + + mx = (old_mutex_t) calloc(1, sizeof(*mx)); + + if (mx == NULL) + { + result = ENOMEM; + goto FAIL0; + } + + mx->mutex = 0; + + if (attr != NULL + && *attr != NULL + && (*attr)->pshared == PTHREAD_PROCESS_SHARED + ) + { + result = ENOSYS; + } + else + { + CRITICAL_SECTION cs; + + /* + * Load KERNEL32 and try to get address of TryEnterCriticalSection + */ + ptw32_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL")); + ptw32_try_enter_critical_section = (BOOL (WINAPI *)(LPCRITICAL_SECTION)) + +#if defined(NEED_UNICODE_CONSTS) + GetProcAddress(ptw32_h_kernel32, + (const TCHAR *)TEXT("TryEnterCriticalSection")); +#else + GetProcAddress(ptw32_h_kernel32, + (LPCSTR) "TryEnterCriticalSection"); +#endif + + if (ptw32_try_enter_critical_section != NULL) + { + InitializeCriticalSection(&cs); + if ((*ptw32_try_enter_critical_section)(&cs)) + { + LeaveCriticalSection(&cs); + } + else + { + /* + * Not really supported (Win98?). + */ + ptw32_try_enter_critical_section = NULL; + } + DeleteCriticalSection(&cs); + } + + if (ptw32_try_enter_critical_section == NULL) + { + (void) FreeLibrary(ptw32_h_kernel32); + ptw32_h_kernel32 = 0; + } + + if (old_mutex_use == OLD_WIN32CS) + { + InitializeCriticalSection(&mx->cs); + } + else if (old_mutex_use == OLD_WIN32MUTEX) + { + mx->mutex = CreateMutex (NULL, + FALSE, + NULL); + + if (mx->mutex == 0) + { + result = EAGAIN; + } + } + else + { + result = EINVAL; + } + } + + if (result != 0 && mx != NULL) + { + free(mx); + mx = NULL; + } + +FAIL0: + *mutex = mx; + + return(result); +} + + +int +old_mutex_lock(old_mutex_t *mutex) +{ + int result = 0; + old_mutex_t mx; + + if (mutex == NULL || *mutex == NULL) + { + return EINVAL; + } + + if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT) + { + /* + * Don't use initialisers when benchtesting. + */ + result = EINVAL; + } + + mx = *mutex; + + if (result == 0) + { + if (mx->mutex == 0) + { + EnterCriticalSection(&mx->cs); + } + else + { + result = (WaitForSingleObject(mx->mutex, INFINITE) + == WAIT_OBJECT_0) + ? 0 + : EINVAL; + } + } + + return(result); +} + +int +old_mutex_unlock(old_mutex_t *mutex) +{ + int result = 0; + old_mutex_t mx; + + if (mutex == NULL || *mutex == NULL) + { + return EINVAL; + } + + mx = *mutex; + + if (mx != (old_mutex_t) PTW32_OBJECT_AUTO_INIT) + { + if (mx->mutex == 0) + { + LeaveCriticalSection(&mx->cs); + } + else + { + result = (ReleaseMutex (mx->mutex) ? 0 : EINVAL); + } + } + else + { + result = EINVAL; + } + + return(result); +} + + +int +old_mutex_trylock(old_mutex_t *mutex) +{ + int result = 0; + old_mutex_t mx; + + if (mutex == NULL || *mutex == NULL) + { + return EINVAL; + } + + if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT) + { + /* + * Don't use initialisers when benchtesting. + */ + result = EINVAL; + } + + mx = *mutex; + + if (result == 0) + { + if (mx->mutex == 0) + { + if (ptw32_try_enter_critical_section == NULL) + { + result = 0; + } + else if ((*ptw32_try_enter_critical_section)(&mx->cs) != TRUE) + { + result = EBUSY; + } + } + else + { + DWORD status; + + status = WaitForSingleObject (mx->mutex, 0); + + if (status != WAIT_OBJECT_0) + { + result = ((status == WAIT_TIMEOUT) + ? EBUSY + : EINVAL); + } + } + } + + return(result); +} + + +int +old_mutex_destroy(old_mutex_t *mutex) +{ + int result = 0; + old_mutex_t mx; + + if (mutex == NULL + || *mutex == NULL) + { + return EINVAL; + } + + if (*mutex != (old_mutex_t) PTW32_OBJECT_AUTO_INIT) + { + mx = *mutex; + + if ((result = old_mutex_trylock(&mx)) == 0) + { + *mutex = NULL; + + (void) old_mutex_unlock(&mx); + + if (mx->mutex == 0) + { + DeleteCriticalSection(&mx->cs); + } + else + { + result = (CloseHandle (mx->mutex) ? 0 : EINVAL); + } + + if (result == 0) + { + mx->mutex = 0; + free(mx); + } + else + { + *mutex = mx; + } + } + } + else + { + result = EINVAL; + } + + if (ptw32_try_enter_critical_section != NULL) + { + (void) FreeLibrary(ptw32_h_kernel32); + ptw32_h_kernel32 = 0; + } + + return(result); +} + +/****************************************************************************************/ diff --git a/liblo/pthreads.2/tests/benchtest.h b/liblo/pthreads.2/tests/benchtest.h new file mode 100644 index 0000000..93b3125 --- /dev/null +++ b/liblo/pthreads.2/tests/benchtest.h @@ -0,0 +1,70 @@ +/* + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#include "../config.h" + +enum { + OLD_WIN32CS, + OLD_WIN32MUTEX +}; + +extern int old_mutex_use; + +struct old_mutex_t_ { + HANDLE mutex; + CRITICAL_SECTION cs; +}; + +typedef struct old_mutex_t_ * old_mutex_t; + +struct old_mutexattr_t_ { + int pshared; +}; + +typedef struct old_mutexattr_t_ * old_mutexattr_t; + +extern BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION); +extern HINSTANCE ptw32_h_kernel32; + +#define PTW32_OBJECT_AUTO_INIT ((void *) -1) + +void dummy_call(int * a); +void interlocked_inc_with_conditionals(int *a); +void interlocked_dec_with_conditionals(int *a); +int old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr); +int old_mutex_lock(old_mutex_t *mutex); +int old_mutex_unlock(old_mutex_t *mutex); +int old_mutex_trylock(old_mutex_t *mutex); +int old_mutex_destroy(old_mutex_t *mutex); +/****************************************************************************************/ diff --git a/liblo/pthreads.2/tests/benchtest1.c b/liblo/pthreads.2/tests/benchtest1.c new file mode 100644 index 0000000..da0380e --- /dev/null +++ b/liblo/pthreads.2/tests/benchtest1.c @@ -0,0 +1,249 @@ +/* + * benchtest1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Measure time taken to complete an elementary operation. + * + * - Mutex + * Single thread iteration over lock/unlock for each mutex type. + */ + +#include "test.h" +#include + +#ifdef __GNUC__ +#include +#endif + +#include "benchtest.h" + +#define PTW32_MUTEX_TYPES +#define ITERATIONS 10000000L + +pthread_mutex_t mx; +pthread_mutexattr_t ma; +struct _timeb currSysTimeStart; +struct _timeb currSysTimeStop; +long durationMilliSecs; +long overHeadMilliSecs = 0; +int one = 1; +int zero = 0; + +#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \ + - (_TStart.time*1000+_TStart.millitm)) + +/* + * Dummy use of j, otherwise the loop may be removed by the optimiser + * when doing the overhead timing with an empty loop. + */ +#define TESTSTART \ + { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++; + +#define TESTSTOP \ + }; _ftime(&currSysTimeStop); if (j + k == i) j++; } + + +void +runTest (char * testNameString, int mType) +{ +#ifdef PTW32_MUTEX_TYPES + assert(pthread_mutexattr_settype(&ma, mType) == 0); +#endif + assert(pthread_mutex_init(&mx, &ma) == 0); + + TESTSTART + assert(pthread_mutex_lock(&mx) == zero); + assert(pthread_mutex_unlock(&mx) == zero); + TESTSTOP + + assert(pthread_mutex_destroy(&mx) == 0); + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + testNameString, + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); +} + + +int +main (int argc, char *argv[]) +{ + int i = 0; + CRITICAL_SECTION cs; + old_mutex_t ox; + pthread_mutexattr_init(&ma); + + printf( "=============================================================================\n"); + printf( "\nLock plus unlock on an unlocked mutex.\n%ld iterations\n\n", + ITERATIONS); + printf( "%-45s %15s %15s\n", + "Test", + "Total(msec)", + "average(usec)"); + printf( "-----------------------------------------------------------------------------\n"); + + /* + * Time the loop overhead so we can subtract it from the actual test times. + */ + + TESTSTART + assert(1 == one); + assert(1 == one); + TESTSTOP + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + overHeadMilliSecs = durationMilliSecs; + + + TESTSTART + assert((dummy_call(&i), 1) == one); + assert((dummy_call(&i), 1) == one); + TESTSTOP + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + "Dummy call x 2", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + + TESTSTART + assert((interlocked_inc_with_conditionals(&i), 1) == one); + assert((interlocked_dec_with_conditionals(&i), 1) == one); + TESTSTOP + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + "Dummy call -> Interlocked with cond x 2", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + + TESTSTART + assert((InterlockedIncrement((LPLONG)&i), 1) == (LONG)one); + assert((InterlockedDecrement((LPLONG)&i), 1) == (LONG)one); + TESTSTOP + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + "InterlockedOp x 2", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + + InitializeCriticalSection(&cs); + + TESTSTART + assert((EnterCriticalSection(&cs), 1) == one); + assert((LeaveCriticalSection(&cs), 1) == one); + TESTSTOP + + DeleteCriticalSection(&cs); + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + "Simple Critical Section", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + + old_mutex_use = OLD_WIN32CS; + assert(old_mutex_init(&ox, NULL) == 0); + + TESTSTART + assert(old_mutex_lock(&ox) == zero); + assert(old_mutex_unlock(&ox) == zero); + TESTSTOP + + assert(old_mutex_destroy(&ox) == 0); + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Critical Section (WNT)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + + old_mutex_use = OLD_WIN32MUTEX; + assert(old_mutex_init(&ox, NULL) == 0); + + TESTSTART + assert(old_mutex_lock(&ox) == zero); + assert(old_mutex_unlock(&ox) == zero); + TESTSTOP + + assert(old_mutex_destroy(&ox) == 0); + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Win32 Mutex (W9x)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + printf( ".............................................................................\n"); + + /* + * Now we can start the actual tests + */ +#ifdef PTW32_MUTEX_TYPES + runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT); + + runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL); + + runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK); + + runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE); +#else + runTest("Non-blocking lock", 0); +#endif + + printf( "=============================================================================\n"); + + /* + * End of tests. + */ + + pthread_mutexattr_destroy(&ma); + + one = i; /* Dummy assignment to avoid 'variable unused' warning */ + return 0; +} diff --git a/liblo/pthreads.2/tests/benchtest2.c b/liblo/pthreads.2/tests/benchtest2.c new file mode 100644 index 0000000..7ce18b3 --- /dev/null +++ b/liblo/pthreads.2/tests/benchtest2.c @@ -0,0 +1,311 @@ +/* + * benchtest1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Measure time taken to complete an elementary operation. + * + * - Mutex + * Two threads iterate over lock/unlock for each mutex type. + * The two threads are forced into lock-step using two mutexes, + * forcing the threads to block on each lock operation. The + * time measured is therefore the worst case senario. + */ + +#include "test.h" +#include + +#ifdef __GNUC__ +#include +#endif + +#include "benchtest.h" + +#define PTW32_MUTEX_TYPES +#define ITERATIONS 100000L + +pthread_mutex_t gate1, gate2; +old_mutex_t ox1, ox2; +CRITICAL_SECTION cs1, cs2; +pthread_mutexattr_t ma; +long durationMilliSecs; +long overHeadMilliSecs = 0; +struct _timeb currSysTimeStart; +struct _timeb currSysTimeStop; +pthread_t worker; +int running = 0; + +#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \ + - (_TStart.time*1000+_TStart.millitm)) + +/* + * Dummy use of j, otherwise the loop may be removed by the optimiser + * when doing the overhead timing with an empty loop. + */ +#define TESTSTART \ + { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++; + +#define TESTSTOP \ + }; _ftime(&currSysTimeStop); if (j + k == i) j++; } + + +void * +overheadThread(void * arg) +{ + do + { + sched_yield(); + } + while (running); + + return NULL; +} + + +void * +oldThread(void * arg) +{ + do + { + (void) old_mutex_lock(&ox1); + (void) old_mutex_lock(&ox2); + (void) old_mutex_unlock(&ox1); + sched_yield(); + (void) old_mutex_unlock(&ox2); + } + while (running); + + return NULL; +} + +void * +workerThread(void * arg) +{ + do + { + (void) pthread_mutex_lock(&gate1); + (void) pthread_mutex_lock(&gate2); + (void) pthread_mutex_unlock(&gate1); + sched_yield(); + (void) pthread_mutex_unlock(&gate2); + } + while (running); + + return NULL; +} + +void * +CSThread(void * arg) +{ + do + { + EnterCriticalSection(&cs1); + EnterCriticalSection(&cs2); + LeaveCriticalSection(&cs1); + sched_yield(); + LeaveCriticalSection(&cs2); + } + while (running); + + return NULL; +} + +void +runTest (char * testNameString, int mType) +{ +#ifdef PTW32_MUTEX_TYPES + assert(pthread_mutexattr_settype(&ma, mType) == 0); +#endif + assert(pthread_mutex_init(&gate1, &ma) == 0); + assert(pthread_mutex_init(&gate2, &ma) == 0); + assert(pthread_mutex_lock(&gate1) == 0); + assert(pthread_mutex_lock(&gate2) == 0); + running = 1; + assert(pthread_create(&worker, NULL, workerThread, NULL) == 0); + TESTSTART + (void) pthread_mutex_unlock(&gate1); + sched_yield(); + (void) pthread_mutex_unlock(&gate2); + (void) pthread_mutex_lock(&gate1); + (void) pthread_mutex_lock(&gate2); + TESTSTOP + running = 0; + assert(pthread_mutex_unlock(&gate2) == 0); + assert(pthread_mutex_unlock(&gate1) == 0); + assert(pthread_join(worker, NULL) == 0); + assert(pthread_mutex_destroy(&gate2) == 0); + assert(pthread_mutex_destroy(&gate1) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + testNameString, + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS / 4 /* Four locks/unlocks per iteration */); +} + + +int +main (int argc, char *argv[]) +{ + assert(pthread_mutexattr_init(&ma) == 0); + + printf( "=============================================================================\n"); + printf( "\nLock plus unlock on a locked mutex.\n"); + printf("%ld iterations, four locks/unlocks per iteration.\n\n", ITERATIONS); + + printf( "%-45s %15s %15s\n", + "Test", + "Total(msec)", + "average(usec)"); + printf( "-----------------------------------------------------------------------------\n"); + + /* + * Time the loop overhead so we can subtract it from the actual test times. + */ + + running = 1; + assert(pthread_create(&worker, NULL, overheadThread, NULL) == 0); + TESTSTART + sched_yield(); + sched_yield(); + TESTSTOP + running = 0; + assert(pthread_join(worker, NULL) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + overHeadMilliSecs = durationMilliSecs; + + + InitializeCriticalSection(&cs1); + InitializeCriticalSection(&cs2); + EnterCriticalSection(&cs1); + EnterCriticalSection(&cs2); + running = 1; + assert(pthread_create(&worker, NULL, CSThread, NULL) == 0); + TESTSTART + LeaveCriticalSection(&cs1); + sched_yield(); + LeaveCriticalSection(&cs2); + EnterCriticalSection(&cs1); + EnterCriticalSection(&cs2); + TESTSTOP + running = 0; + LeaveCriticalSection(&cs2); + LeaveCriticalSection(&cs1); + assert(pthread_join(worker, NULL) == 0); + DeleteCriticalSection(&cs2); + DeleteCriticalSection(&cs1); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + "Simple Critical Section", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS / 4 ); + + + old_mutex_use = OLD_WIN32CS; + assert(old_mutex_init(&ox1, NULL) == 0); + assert(old_mutex_init(&ox2, NULL) == 0); + assert(old_mutex_lock(&ox1) == 0); + assert(old_mutex_lock(&ox2) == 0); + running = 1; + assert(pthread_create(&worker, NULL, oldThread, NULL) == 0); + TESTSTART + (void) old_mutex_unlock(&ox1); + sched_yield(); + (void) old_mutex_unlock(&ox2); + (void) old_mutex_lock(&ox1); + (void) old_mutex_lock(&ox2); + TESTSTOP + running = 0; + assert(old_mutex_unlock(&ox1) == 0); + assert(old_mutex_unlock(&ox2) == 0); + assert(pthread_join(worker, NULL) == 0); + assert(old_mutex_destroy(&ox2) == 0); + assert(old_mutex_destroy(&ox1) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Critical Section (WNT)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS / 4); + + + old_mutex_use = OLD_WIN32MUTEX; + assert(old_mutex_init(&ox1, NULL) == 0); + assert(old_mutex_init(&ox2, NULL) == 0); + assert(old_mutex_lock(&ox1) == 0); + assert(old_mutex_lock(&ox2) == 0); + running = 1; + assert(pthread_create(&worker, NULL, oldThread, NULL) == 0); + TESTSTART + (void) old_mutex_unlock(&ox1); + sched_yield(); + (void) old_mutex_unlock(&ox2); + (void) old_mutex_lock(&ox1); + (void) old_mutex_lock(&ox2); + TESTSTOP + running = 0; + assert(old_mutex_unlock(&ox1) == 0); + assert(old_mutex_unlock(&ox2) == 0); + assert(pthread_join(worker, NULL) == 0); + assert(old_mutex_destroy(&ox2) == 0); + assert(old_mutex_destroy(&ox1) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Win32 Mutex (W9x)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS / 4); + + printf( ".............................................................................\n"); + + /* + * Now we can start the actual tests + */ +#ifdef PTW32_MUTEX_TYPES + runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT); + + runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL); + + runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK); + + runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE); +#else + runTest("Blocking locks", 0); +#endif + + printf( "=============================================================================\n"); + /* + * End of tests. + */ + + pthread_mutexattr_destroy(&ma); + + return 0; +} diff --git a/liblo/pthreads.2/tests/benchtest3.c b/liblo/pthreads.2/tests/benchtest3.c new file mode 100644 index 0000000..a64b3af --- /dev/null +++ b/liblo/pthreads.2/tests/benchtest3.c @@ -0,0 +1,201 @@ +/* + * benchtest3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Measure time taken to complete an elementary operation. + * + * - Mutex + * Single thread iteration over a trylock on a locked mutex for each mutex type. + */ + +#include "test.h" +#include + +#ifdef __GNUC__ +#include +#endif + +#include "benchtest.h" + +#define PTW32_MUTEX_TYPES +#define ITERATIONS 10000000L + +pthread_mutex_t mx; +old_mutex_t ox; +pthread_mutexattr_t ma; +struct _timeb currSysTimeStart; +struct _timeb currSysTimeStop; +long durationMilliSecs; +long overHeadMilliSecs = 0; + +#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \ + - (_TStart.time*1000+_TStart.millitm)) + +/* + * Dummy use of j, otherwise the loop may be removed by the optimiser + * when doing the overhead timing with an empty loop. + */ +#define TESTSTART \ + { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++; + +#define TESTSTOP \ + }; _ftime(&currSysTimeStop); if (j + k == i) j++; } + + +void * +trylockThread (void * arg) +{ + TESTSTART + (void) pthread_mutex_trylock(&mx); + TESTSTOP + + return NULL; +} + + +void * +oldTrylockThread (void * arg) +{ + TESTSTART + (void) old_mutex_trylock(&ox); + TESTSTOP + + return NULL; +} + + +void +runTest (char * testNameString, int mType) +{ + pthread_t t; + +#ifdef PTW32_MUTEX_TYPES + (void) pthread_mutexattr_settype(&ma, mType); +#endif + assert(pthread_mutex_init(&mx, &ma) == 0); + assert(pthread_mutex_lock(&mx) == 0); + assert(pthread_create(&t, NULL, trylockThread, 0) == 0); + assert(pthread_join(t, NULL) == 0); + assert(pthread_mutex_unlock(&mx) == 0); + assert(pthread_mutex_destroy(&mx) == 0); + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + testNameString, + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); +} + + +int +main (int argc, char *argv[]) +{ + pthread_t t; + + assert(pthread_mutexattr_init(&ma) == 0); + + printf( "=============================================================================\n"); + printf( "\nTrylock on a locked mutex.\n"); + printf( "%ld iterations.\n\n", ITERATIONS); + printf( "%-45s %15s %15s\n", + "Test", + "Total(msec)", + "average(usec)"); + printf( "-----------------------------------------------------------------------------\n"); + + /* + * Time the loop overhead so we can subtract it from the actual test times. + */ + + TESTSTART + TESTSTOP + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + overHeadMilliSecs = durationMilliSecs; + + + old_mutex_use = OLD_WIN32CS; + assert(old_mutex_init(&ox, NULL) == 0); + assert(old_mutex_lock(&ox) == 0); + assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0); + assert(pthread_join(t, NULL) == 0); + assert(old_mutex_unlock(&ox) == 0); + assert(old_mutex_destroy(&ox) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Critical Section (WNT)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + old_mutex_use = OLD_WIN32MUTEX; + assert(old_mutex_init(&ox, NULL) == 0); + assert(old_mutex_lock(&ox) == 0); + assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0); + assert(pthread_join(t, NULL) == 0); + assert(old_mutex_unlock(&ox) == 0); + assert(old_mutex_destroy(&ox) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Win32 Mutex (W9x)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + printf( ".............................................................................\n"); + + /* + * Now we can start the actual tests + */ +#ifdef PTW32_MUTEX_TYPES + runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT); + + runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL); + + runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK); + + runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE); +#else + runTest("Non-blocking lock", 0); +#endif + + printf( "=============================================================================\n"); + + /* + * End of tests. + */ + + pthread_mutexattr_destroy(&ma); + + return 0; +} diff --git a/liblo/pthreads.2/tests/benchtest4.c b/liblo/pthreads.2/tests/benchtest4.c new file mode 100644 index 0000000..6ad51a4 --- /dev/null +++ b/liblo/pthreads.2/tests/benchtest4.c @@ -0,0 +1,182 @@ +/* + * benchtest4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Measure time taken to complete an elementary operation. + * + * - Mutex + * Single thread iteration over trylock/unlock for each mutex type. + */ + +#include "test.h" +#include + +#ifdef __GNUC__ +#include +#endif + +#include "benchtest.h" + +#define PTW32_MUTEX_TYPES +#define ITERATIONS 10000000L + +pthread_mutex_t mx; +old_mutex_t ox; +pthread_mutexattr_t ma; +struct _timeb currSysTimeStart; +struct _timeb currSysTimeStop; +long durationMilliSecs; +long overHeadMilliSecs = 0; + +#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \ + - (_TStart.time*1000+_TStart.millitm)) + +/* + * Dummy use of j, otherwise the loop may be removed by the optimiser + * when doing the overhead timing with an empty loop. + */ +#define TESTSTART \ + { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++; + +#define TESTSTOP \ + }; _ftime(&currSysTimeStop); if (j + k == i) j++; } + + +void +oldRunTest (char * testNameString, int mType) +{ +} + + +void +runTest (char * testNameString, int mType) +{ +#ifdef PTW32_MUTEX_TYPES + pthread_mutexattr_settype(&ma, mType); +#endif + pthread_mutex_init(&mx, &ma); + + TESTSTART + (void) pthread_mutex_trylock(&mx); + (void) pthread_mutex_unlock(&mx); + TESTSTOP + + pthread_mutex_destroy(&mx); + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + testNameString, + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); +} + + +int +main (int argc, char *argv[]) +{ + pthread_mutexattr_init(&ma); + + printf( "=============================================================================\n"); + printf( "Trylock plus unlock on an unlocked mutex.\n"); + printf( "%ld iterations.\n\n", ITERATIONS); + printf( "%-45s %15s %15s\n", + "Test", + "Total(msec)", + "average(usec)"); + printf( "-----------------------------------------------------------------------------\n"); + + /* + * Time the loop overhead so we can subtract it from the actual test times. + */ + + TESTSTART + TESTSTOP + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + overHeadMilliSecs = durationMilliSecs; + + old_mutex_use = OLD_WIN32CS; + assert(old_mutex_init(&ox, NULL) == 0); + TESTSTART + (void) old_mutex_trylock(&ox); + (void) old_mutex_unlock(&ox); + TESTSTOP + assert(old_mutex_destroy(&ox) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Critical Section (WNT)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + old_mutex_use = OLD_WIN32MUTEX; + assert(old_mutex_init(&ox, NULL) == 0); + TESTSTART + (void) old_mutex_trylock(&ox); + (void) old_mutex_unlock(&ox); + TESTSTOP + assert(old_mutex_destroy(&ox) == 0); + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + printf( "%-45s %15ld %15.3f\n", + "Old PT Mutex using a Win32 Mutex (W9x)", + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); + + printf( ".............................................................................\n"); + + /* + * Now we can start the actual tests + */ +#ifdef PTW32_MUTEX_TYPES + runTest("PTHREAD_MUTEX_DEFAULT (W9x,WNT)", PTHREAD_MUTEX_DEFAULT); + + runTest("PTHREAD_MUTEX_NORMAL (W9x,WNT)", PTHREAD_MUTEX_NORMAL); + + runTest("PTHREAD_MUTEX_ERRORCHECK (W9x,WNT)", PTHREAD_MUTEX_ERRORCHECK); + + runTest("PTHREAD_MUTEX_RECURSIVE (W9x,WNT)", PTHREAD_MUTEX_RECURSIVE); +#else + runTest("Non-blocking lock", 0); +#endif + + printf( "=============================================================================\n"); + + /* + * End of tests. + */ + + pthread_mutexattr_destroy(&ma); + + return 0; +} diff --git a/liblo/pthreads.2/tests/benchtest5.c b/liblo/pthreads.2/tests/benchtest5.c new file mode 100644 index 0000000..2fba9e3 --- /dev/null +++ b/liblo/pthreads.2/tests/benchtest5.c @@ -0,0 +1,159 @@ +/* + * benchtest5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Measure time taken to complete an elementary operation. + * + * - Semaphore + * Single thread iteration over post/wait for a semaphore. + */ + +#include "test.h" +#include + +#ifdef __GNUC__ +#include +#endif + +#include "benchtest.h" + +#define ITERATIONS 1000000L + +sem_t sema; +HANDLE w32sema; + +struct _timeb currSysTimeStart; +struct _timeb currSysTimeStop; +long durationMilliSecs; +long overHeadMilliSecs = 0; +int one = 1; +int zero = 0; + +#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \ + - (_TStart.time*1000+_TStart.millitm)) + +/* + * Dummy use of j, otherwise the loop may be removed by the optimiser + * when doing the overhead timing with an empty loop. + */ +#define TESTSTART \ + { int i, j = 0, k = 0; _ftime(&currSysTimeStart); for (i = 0; i < ITERATIONS; i++) { j++; + +#define TESTSTOP \ + }; _ftime(&currSysTimeStop); if (j + k == i) j++; } + + +void +reportTest (char * testNameString) +{ + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + + printf( "%-45s %15ld %15.3f\n", + testNameString, + durationMilliSecs, + (float) durationMilliSecs * 1E3 / ITERATIONS); +} + + +int +main (int argc, char *argv[]) +{ + printf( "=============================================================================\n"); + printf( "\nOperations on a semaphore.\n%ld iterations\n\n", + ITERATIONS); + printf( "%-45s %15s %15s\n", + "Test", + "Total(msec)", + "average(usec)"); + printf( "-----------------------------------------------------------------------------\n"); + + /* + * Time the loop overhead so we can subtract it from the actual test times. + */ + + TESTSTART + assert(1 == one); + TESTSTOP + + durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; + overHeadMilliSecs = durationMilliSecs; + + + /* + * Now we can start the actual tests + */ + assert((w32sema = CreateSemaphore(NULL, (long) 0, (long) ITERATIONS, NULL)) != 0); + TESTSTART + assert(ReleaseSemaphore(w32sema, 1, NULL) != zero); + TESTSTOP + assert(CloseHandle(w32sema) != 0); + + reportTest("W32 Post with no waiters"); + + + assert((w32sema = CreateSemaphore(NULL, (long) ITERATIONS, (long) ITERATIONS, NULL)) != 0); + TESTSTART + assert(WaitForSingleObject(w32sema, INFINITE) == WAIT_OBJECT_0); + TESTSTOP + assert(CloseHandle(w32sema) != 0); + + reportTest("W32 Wait without blocking"); + + + assert(sem_init(&sema, 0, 0) == 0); + TESTSTART + assert(sem_post(&sema) == zero); + TESTSTOP + assert(sem_destroy(&sema) == 0); + + reportTest("POSIX Post with no waiters"); + + + assert(sem_init(&sema, 0, ITERATIONS) == 0); + TESTSTART + assert(sem_wait(&sema) == zero); + TESTSTOP + assert(sem_destroy(&sema) == 0); + + reportTest("POSIX Wait without blocking"); + + + printf( "=============================================================================\n"); + + /* + * End of tests. + */ + + return 0; +} diff --git a/liblo/pthreads.2/tests/cancel1.c b/liblo/pthreads.2/tests/cancel1.c new file mode 100644 index 0000000..6f152bf --- /dev/null +++ b/liblo/pthreads.2/tests/cancel1.c @@ -0,0 +1,179 @@ +/* + * File: cancel1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test setting cancel state and cancel type. + * - + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - pthread_setcancelstate function + * - pthread_setcanceltype function + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - pthread_create, pthread_self work. + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 2 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +void * +mythread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* ... */ + { + int oldstate; + int oldtype; + + assert(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) == 0); + assert(oldstate == PTHREAD_CANCEL_ENABLE); /* Check default */ + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + assert(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) == 0); + assert(pthread_setcancelstate(oldstate, &oldstate) == 0); + assert(oldstate == PTHREAD_CANCEL_DISABLE); /* Check setting */ + + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype) == 0); + assert(oldtype == PTHREAD_CANCEL_DEFERRED); /* Check default */ + assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0); + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + assert(pthread_setcanceltype(oldtype, &oldtype) == 0); + assert(oldtype == PTHREAD_CANCEL_ASYNCHRONOUS); /* Check setting */ + } + + return 0; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 1000); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + failed = !threadbag[i].started; + + if (failed) + { + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print ouput on failure. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + /* ... */ + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/cancel2.c b/liblo/pthreads.2/tests/cancel2.c new file mode 100644 index 0000000..703e36c --- /dev/null +++ b/liblo/pthreads.2/tests/cancel2.c @@ -0,0 +1,251 @@ +/* + * File: cancel2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test SEH or C++ cancel exception handling within + * application exception blocks. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 1 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +static pthread_mutex_t waitLock = PTHREAD_MUTEX_INITIALIZER; + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + switch (bag->threadnum % 2) + { + case 0: + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + result = 0; + break; + case 1: + assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0); + result = 1; + break; + } + +#if defined(_MSC_VER) && !defined(__cplusplus) + __try +#else + try +#endif + { + /* Wait for go from main */ + assert(pthread_mutex_lock(&waitLock) == 0); + assert(pthread_mutex_unlock(&waitLock) == 0); + sched_yield(); + + for (;;) + { + pthread_testcancel(); + } + } +#if defined(_MSC_VER) && !defined(__cplusplus) + __except(EXCEPTION_EXECUTE_HANDLER) +#else +#if defined(PtW32CatchAll) + PtW32CatchAll +#else + catch(...) +#endif +#endif + { + /* + * Should not get into here. + */ + result += 100; + } + + /* + * Should not get to here either. + */ + result += 1000; + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()).p != NULL); + assert(pthread_mutex_lock(&waitLock) == 0); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + assert(pthread_mutex_unlock(&waitLock) == 0); + + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + assert(pthread_join(t[i], (void **) &result) == 0); + fail = (result != (int) PTHREAD_CANCELED); + if (fail) + { + fprintf(stderr, "Thread %d: started %d: location %d: cancel type %s\n", + i, + threadbag[i].started, + result, + ((result % 2) == 0) ? "ASYNCHRONOUS" : "DEFERRED"); + } + failed |= fail; + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/cancel3.c b/liblo/pthreads.2/tests/cancel3.c new file mode 100644 index 0000000..ccaec21 --- /dev/null +++ b/liblo/pthreads.2/tests/cancel3.c @@ -0,0 +1,201 @@ +/* + * File: cancel3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test asynchronous cancelation (alertable or non-alertable). + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - Async cancel if thread is not blocked (i.e. voluntarily resumes if blocked). + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join. + * - quserex.dll and alertdrv.sys are not available. + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum +{ + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ +{ + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +void * +mythread (void *arg) +{ + int result = ((int) PTHREAD_CANCELED + 1); + bag_t *bag = (bag_t *) arg; + + assert (bag == &threadbag[bag->threadnum]); + assert (bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 100; bag->count++) + Sleep (100); + + return (void *) result; +} + +int +main () +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert ((t[0] = pthread_self ()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert (pthread_create (&t[i], NULL, mythread, (void *) &threadbag[i]) + == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep (500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert (pthread_cancel (t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep (NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf (stderr, "Thread %d: started %d\n", i, + threadbag[i].started); + } + } + + assert (!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + /* + * The thread does not contain any cancelation points, so + * a return value of PTHREAD_CANCELED confirms that async + * cancelation succeeded. + */ + assert (pthread_join (t[i], (void **) &result) == 0); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf (stderr, "Thread %d: started %d: count %d\n", + i, threadbag[i].started, threadbag[i].count); + } + failed = (failed || fail); + } + + assert (!failed); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/cancel4.c b/liblo/pthreads.2/tests/cancel4.c new file mode 100644 index 0000000..49d41bf --- /dev/null +++ b/liblo/pthreads.2/tests/cancel4.c @@ -0,0 +1,203 @@ +/* + * File: cancel4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test cancelation does not occur in deferred + * cancelation threads with no cancelation points. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - pthread_create + * pthread_self + * pthread_cancel + * pthread_join + * pthread_setcancelstate + * pthread_setcanceltype + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +void * +mythread(void * arg) +{ + int result = ((int)PTHREAD_CANCELED + 1); + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0); + + /* + * We wait up to 2 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 20; bag->count++) + Sleep(100); + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + /* + * The thread does not contain any cancelation points, so + * a return value of PTHREAD_CANCELED indicates that async + * cancelation occurred. + */ + assert(pthread_join(t[i], (void **) &result) == 0); + + fail = (result == (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/cancel5.c b/liblo/pthreads.2/tests/cancel5.c new file mode 100644 index 0000000..34b6166 --- /dev/null +++ b/liblo/pthreads.2/tests/cancel5.c @@ -0,0 +1,199 @@ +/* + * File: cancel5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test calling pthread_cancel from the main thread + * without calling pthread_self() in main. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum +{ + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ +{ + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +void * +mythread (void *arg) +{ + int result = ((int) PTHREAD_CANCELED + 1); + bag_t *bag = (bag_t *) arg; + + assert (bag == &threadbag[bag->threadnum]); + assert (bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 100; bag->count++) + Sleep (100); + + return (void *) result; +} + +int +main () +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert (pthread_create (&t[i], NULL, mythread, (void *) &threadbag[i]) + == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep (500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert (pthread_cancel (t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep (NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf (stderr, "Thread %d: started %d\n", i, + threadbag[i].started); + } + } + + assert (!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + /* + * The thread does not contain any cancelation points, so + * a return value of PTHREAD_CANCELED confirms that async + * cancelation succeeded. + */ + assert (pthread_join (t[i], (void **) &result) == 0); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf (stderr, "Thread %d: started %d: count %d\n", + i, threadbag[i].started, threadbag[i].count); + } + failed = (failed || fail); + } + + assert (!failed); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/cancel6a.c b/liblo/pthreads.2/tests/cancel6a.c new file mode 100644 index 0000000..f830602 --- /dev/null +++ b/liblo/pthreads.2/tests/cancel6a.c @@ -0,0 +1,191 @@ +/* + * File: cancel6a.c + * + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 Ben Elliston and Ross Johnson + * Copyright (C) 1999,2000,2001 Ross Johnson + * + * Contact Email: rpj@ise.canberra.edu.au + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test double cancelation - asynchronous. + * Second attempt should fail (ESRCH). + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +void * +mythread(void * arg) +{ + int result = ((int)PTHREAD_CANCELED + 1); + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 100; bag->count++) + Sleep(100); + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + assert(pthread_cancel(t[i]) == ESRCH); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + /* + * The thread does not contain any cancelation points, so + * a return value of PTHREAD_CANCELED confirms that async + * cancelation succeeded. + */ + assert(pthread_join(t[i], (void **) &result) == 0); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/cancel6d.c b/liblo/pthreads.2/tests/cancel6d.c new file mode 100644 index 0000000..0f3f983 --- /dev/null +++ b/liblo/pthreads.2/tests/cancel6d.c @@ -0,0 +1,190 @@ +/* + * File: cancel6d.c + * + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 Ben Elliston and Ross Johnson + * Copyright (C) 1999,2000,2001 Ross Johnson + * + * Contact Email: rpj@ise.canberra.edu.au + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test double cancelation - deferred. + * Second attempt should succeed (unless the canceled thread has started + * cancelation already - not tested here). + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +void * +mythread(void * arg) +{ + int result = ((int)PTHREAD_CANCELED + 1); + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0); + + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 100; bag->count++) + { + Sleep(100); + pthread_testcancel(); + } + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + assert(pthread_cancel(t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + assert(pthread_join(t[i], (void **) &result) == 0); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/cancel7.c b/liblo/pthreads.2/tests/cancel7.c new file mode 100644 index 0000000..9e99cd7 --- /dev/null +++ b/liblo/pthreads.2/tests/cancel7.c @@ -0,0 +1,216 @@ +/* + * File: cancel7.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test canceling a Win32 thread having created an + * implicit POSIX handle for it. + * + * Test Method (Validation or Falsification): + * - Validate return value and that POSIX handle is created and destroyed. + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#ifndef _UWIN +#include +#endif + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; + pthread_t self; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) +unsigned __stdcall +#else +void +#endif +Win32thread(void * arg) +{ + int i; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + assert((bag->self = pthread_self()).p != NULL); + assert(pthread_kill(bag->self, 0) == 0); + + for (i = 0; i < 100; i++) + { + Sleep(100); + pthread_testcancel(); + } + + return 0; +} + +int +main() +{ + int failed = 0; + int i; + HANDLE h[NUMTHREADS + 1]; + unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */ + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr); +#else + h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]); +#endif + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + /* + * Cancel all threads. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_kill(threadbag[i].self, 0) == 0); + assert(pthread_cancel(threadbag[i].self) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE); +#else + /* + * Can't get a result code. + */ + result = (int) PTHREAD_CANCELED; +#endif + + assert(threadbag[i].self.p != NULL); + assert(pthread_kill(threadbag[i].self, 0) == ESRCH); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/cancel8.c b/liblo/pthreads.2/tests/cancel8.c new file mode 100644 index 0000000..e3c3646 --- /dev/null +++ b/liblo/pthreads.2/tests/cancel8.c @@ -0,0 +1,217 @@ +/* + * File: cancel8.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test cancelling a blocked Win32 thread having created an + * implicit POSIX handle for it. + * + * Test Method (Validation or Falsification): + * - Validate return value and that POSIX handle is created and destroyed. + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#ifndef _UWIN +#include +#endif + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; + pthread_t self; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +pthread_cond_t CV = PTHREAD_COND_INITIALIZER; +pthread_mutex_t CVLock = PTHREAD_MUTEX_INITIALIZER; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) +unsigned __stdcall +#else +void +#endif +Win32thread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + assert((bag->self = pthread_self()).p != NULL); + assert(pthread_kill(bag->self, 0) == 0); + + assert(pthread_mutex_lock(&CVLock) == 0); + pthread_cleanup_push(pthread_mutex_unlock, &CVLock); + pthread_cond_wait(&CV, &CVLock); + pthread_cleanup_pop(1); + + return 0; +} + +int +main() +{ + int failed = 0; + int i; + HANDLE h[NUMTHREADS + 1]; + unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */ + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr); +#else + h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]); +#endif + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + /* + * Cancel all threads. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_kill(threadbag[i].self, 0) == 0); + assert(pthread_cancel(threadbag[i].self) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE); +#else + /* + * Can't get a result code. + */ + result = (int) PTHREAD_CANCELED; +#endif + + assert(threadbag[i].self.p != NULL); + assert(pthread_kill(threadbag[i].self, 0) == ESRCH); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/cancel9.c b/liblo/pthreads.2/tests/cancel9.c new file mode 100644 index 0000000..3e980d4 --- /dev/null +++ b/liblo/pthreads.2/tests/cancel9.c @@ -0,0 +1,202 @@ +/* + * File: cancel9.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test true asynchronous cancelation with Alert driver. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - Cancel threads, including those blocked on system recources + * such as network I/O. + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + + +void * +test_udp (void *arg) +{ + struct sockaddr_in serverAddress; + struct sockaddr_in clientAddress; + SOCKET UDPSocket; + int addr_len; + int nbyte, bytes; + char buffer[4096]; + WORD wsaVersion = MAKEWORD (2, 2); + WSADATA wsaData; + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + if (WSAStartup (wsaVersion, &wsaData) != 0) + { + return NULL; + } + + UDPSocket = socket (AF_INET, SOCK_DGRAM, 0); + if ((int)UDPSocket == -1) + { + printf ("Server: socket ERROR \n"); + exit (-1); + } + + serverAddress.sin_family = AF_INET; + serverAddress.sin_addr.s_addr = INADDR_ANY; + serverAddress.sin_port = htons (9003); + + if (bind + (UDPSocket, (struct sockaddr *) &serverAddress, + sizeof (struct sockaddr_in))) + { + printf ("Server: ERROR can't bind UDPSocket"); + exit (-1); + } + + addr_len = sizeof (struct sockaddr); + + nbyte = 512; + + bytes = + recvfrom (UDPSocket, (char *) buffer, nbyte, 0, + (struct sockaddr *) &clientAddress, &addr_len); + + closesocket (UDPSocket); + WSACleanup (); + + return NULL; +} + + +void * +test_sleep (void *arg) +{ + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + Sleep (1000); + return NULL; + +} + +void * +test_wait (void *arg) +{ + HANDLE hEvent; + DWORD dwEvent; + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + + dwEvent = WaitForSingleObject (hEvent, 1000); /* WAIT_IO_COMPLETION */ + + return NULL; +} + + +int +main () +{ + pthread_t t; + void *result; + + if (pthread_win32_test_features_np (PTW32_ALERTABLE_ASYNC_CANCEL)) + { + printf ("Cancel sleeping thread.\n"); + assert (pthread_create (&t, NULL, test_sleep, NULL) == 0); + /* Sleep for a while; then cancel */ + Sleep (100); + assert (pthread_cancel (t) == 0); + assert (pthread_join (t, &result) == 0); + assert (result == PTHREAD_CANCELED && "test_sleep" != NULL); + + printf ("Cancel waiting thread.\n"); + assert (pthread_create (&t, NULL, test_wait, NULL) == 0); + /* Sleep for a while; then cancel. */ + Sleep (100); + assert (pthread_cancel (t) == 0); + assert (pthread_join (t, &result) == 0); + assert (result == PTHREAD_CANCELED && "test_wait"); + + printf ("Cancel blocked thread (blocked on network I/O).\n"); + assert (pthread_create (&t, NULL, test_udp, NULL) == 0); + /* Sleep for a while; then cancel. */ + Sleep (100); + assert (pthread_cancel (t) == 0); + assert (pthread_join (t, &result) == 0); + assert (result == PTHREAD_CANCELED && "test_udp" != NULL); + } + else + { + printf ("Alertable async cancel not available.\n"); + } + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/cleanup0.c b/liblo/pthreads.2/tests/cleanup0.c new file mode 100644 index 0000000..c4a1da5 --- /dev/null +++ b/liblo/pthreads.2/tests/cleanup0.c @@ -0,0 +1,229 @@ +/* + * File: cleanup1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test cleanup handler executes (when thread is not canceled). + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 10 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct { + int i; + CRITICAL_SECTION cs; +} sharedInt_t; + +static sharedInt_t pop_count = {0, {0}}; + +static void +increment_pop_count(void * arg) +{ + sharedInt_t * sI = (sharedInt_t *) arg; + + EnterCriticalSection(&sI->cs); + sI->i++; + LeaveCriticalSection(&sI->cs); +} + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(increment_pop_count, (void *) &pop_count); + + Sleep(100); + + pthread_cleanup_pop(1); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + InitializeCriticalSection(&pop_count.cs); + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + assert(pthread_join(t[i], (void **) &result) == 0); + + fail = (result == (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: result %d\n", + i, + threadbag[i].started, + result); + fflush(stderr); + } + failed = (failed || fail); + } + + assert(!failed); + + assert(pop_count.i == NUMTHREADS); + + DeleteCriticalSection(&pop_count.cs); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/cleanup1.c b/liblo/pthreads.2/tests/cleanup1.c new file mode 100644 index 0000000..0c1bd2c --- /dev/null +++ b/liblo/pthreads.2/tests/cleanup1.c @@ -0,0 +1,242 @@ +/* + * File: cleanup1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test cleanup handler executes (when thread is canceled). + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 10 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct { + int i; + CRITICAL_SECTION cs; +} sharedInt_t; + +static sharedInt_t pop_count = {0, {0}}; + +static void +#ifdef __CLEANUP_C +__cdecl +#endif +increment_pop_count(void * arg) +{ + sharedInt_t * sI = (sharedInt_t *) arg; + + EnterCriticalSection(&sI->cs); + sI->i++; + LeaveCriticalSection(&sI->cs); +} + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Set to known state and type */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(increment_pop_count, (void *) &pop_count); + /* + * We don't have true async cancelation - it relies on the thread + * at least re-entering the run state at some point. + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (bag->count = 0; bag->count < 100; bag->count++) + Sleep(100); + + pthread_cleanup_pop(0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + InitializeCriticalSection(&pop_count.cs); + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_cancel(t[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + assert(pthread_join(t[i], (void **) &result) == 0); + + fail = (result != (int) PTHREAD_CANCELED); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: result %d\n", + i, + threadbag[i].started, + result); + } + failed = (failed || fail); + } + + assert(!failed); + + assert(pop_count.i == NUMTHREADS); + + DeleteCriticalSection(&pop_count.cs); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/cleanup2.c b/liblo/pthreads.2/tests/cleanup2.c new file mode 100644 index 0000000..4ec9663 --- /dev/null +++ b/liblo/pthreads.2/tests/cleanup2.c @@ -0,0 +1,217 @@ +/* + * File: cleanup2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test cleanup handler executes (when thread is not canceled). + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 10 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct { + int i; + CRITICAL_SECTION cs; +} sharedInt_t; + +static sharedInt_t pop_count = {0, {0}}; + +static void +increment_pop_count(void * arg) +{ + sharedInt_t * sI = (sharedInt_t *) arg; + + EnterCriticalSection(&sI->cs); + sI->i++; + LeaveCriticalSection(&sI->cs); +} + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(increment_pop_count, (void *) &pop_count); + + sched_yield(); + + pthread_cleanup_pop(1); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + InitializeCriticalSection(&pop_count.cs); + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(1000); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + assert(pthread_join(t[i], (void **) &result) == 0); + + fail = (result != 0); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: result: %d\n", + i, + threadbag[i].started, + result); + } + failed = (failed || fail); + } + + assert(!failed); + + assert(pop_count.i == NUMTHREADS); + + DeleteCriticalSection(&pop_count.cs); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/cleanup3.c b/liblo/pthreads.2/tests/cleanup3.c new file mode 100644 index 0000000..8508e4c --- /dev/null +++ b/liblo/pthreads.2/tests/cleanup3.c @@ -0,0 +1,222 @@ +/* + * File: cleanup3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test cleanup handler does not execute (when thread is + * not canceled). + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 10 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct { + int i; + CRITICAL_SECTION cs; +} sharedInt_t; + +static sharedInt_t pop_count = {0, {0}}; + +static void +increment_pop_count(void * arg) +{ + sharedInt_t * sI = (sharedInt_t *) arg; + + EnterCriticalSection(&sI->cs); + sI->i++; + LeaveCriticalSection(&sI->cs); +} + +void * +mythread(void * arg) +{ + int result = 0; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(increment_pop_count, (void *) &pop_count); + + sched_yield(); + + EnterCriticalSection(&pop_count.cs); + pop_count.i--; + LeaveCriticalSection(&pop_count.cs); + + pthread_cleanup_pop(0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + InitializeCriticalSection(&pop_count.cs); + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(1000); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + assert(pthread_join(t[i], (void **) &result) == 0); + + fail = (result != 0); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: result: %d\n", + i, + threadbag[i].started, + result); + } + failed = (failed || fail); + } + + assert(!failed); + + assert(pop_count.i == -(NUMTHREADS)); + + DeleteCriticalSection(&pop_count.cs); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +int +main() +{ + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/condvar1.c b/liblo/pthreads.2/tests/condvar1.c new file mode 100644 index 0000000..4dcdff0 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar1.c @@ -0,0 +1,97 @@ +/* + * File: condvar1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test initialisation and destruction of a CV. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Creates and then imediately destroys a CV. Does not + * test the CV. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_init returns 0, and + * - pthread_cond_destroy returns 0. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_init returns non-zero, or + * - pthread_cond_destroy returns non-zero. + * - Process returns non-zero exit status. + */ + +#include "test.h" + +static pthread_cond_t cv = NULL; + +int +main() +{ + assert(cv == NULL); + + assert(pthread_cond_init(&cv, NULL) == 0); + + assert(cv != NULL); + + assert(pthread_cond_destroy(&cv) == 0); + + assert(cv == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar1_1.c b/liblo/pthreads.2/tests/condvar1_1.c new file mode 100644 index 0000000..5cf19e3 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar1_1.c @@ -0,0 +1,115 @@ +/* + * File: condvar1_1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test CV linked list management. + * + * Test Method (Validation or Falsification): + * - Validation: + * Initiate and destroy several CVs in random order. + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Creates and then imediately destroys a CV. Does not + * test the CV. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - All initialised CVs destroyed without segfault. + * - Successfully broadcasts all remaining CVs after + * each CV is removed. + * + * Fail Criteria: + */ + +#include +#include "test.h" + +enum { + NUM_CV = 100 +}; + +static pthread_cond_t cv[NUM_CV]; + +int +main() +{ + int i, j; + + for (i = 0; i < NUM_CV; i++) + { + /* Traverse the list before every init of a CV. */ + assert(pthread_timechange_handler_np(NULL) == (void *) 0); + assert(pthread_cond_init(&cv[i], NULL) == 0); + } + + j = NUM_CV; + (void) srand((unsigned)time(NULL)); + + do + { + i = (NUM_CV - 1) * rand() / RAND_MAX; + if (cv[i] != NULL) + { + j--; + assert(pthread_cond_destroy(&cv[i]) == 0); + /* Traverse the list every time we remove a CV. */ + assert(pthread_timechange_handler_np(NULL) == (void *) 0); + } + } + while (j > 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar1_2.c b/liblo/pthreads.2/tests/condvar1_2.c new file mode 100644 index 0000000..e9eac99 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar1_2.c @@ -0,0 +1,124 @@ +/* + * File: condvar1_2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test CV linked list management and serialisation. + * + * Test Method (Validation or Falsification): + * - Validation: + * Initiate and destroy several CVs in random order. + * Asynchronously traverse the CV list and broadcast. + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Creates and then imediately destroys a CV. Does not + * test the CV. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - All initialised CVs destroyed without segfault. + * - Successfully broadcasts all remaining CVs after + * each CV is removed. + * + * Fail Criteria: + */ + +#include +#include "test.h" + +enum { + NUM_CV = 5, + NUM_LOOPS = 5 +}; + +static pthread_cond_t cv[NUM_CV]; + +int +main() +{ + int i, j, k; + int result = -1; + pthread_t t; + + for (k = 0; k < NUM_LOOPS; k++) + { + for (i = 0; i < NUM_CV; i++) + { + assert(pthread_cond_init(&cv[i], NULL) == 0); + } + + j = NUM_CV; + (void) srand((unsigned)time(NULL)); + + /* Traverse the list asynchronously. */ + assert(pthread_create(&t, NULL, pthread_timechange_handler_np, NULL) == 0); + + do + { + i = (NUM_CV - 1) * rand() / RAND_MAX; + if (cv[i] != NULL) + { + j--; + assert(pthread_cond_destroy(&cv[i]) == 0); + } + } + while (j > 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert (result == 0); + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar2.c b/liblo/pthreads.2/tests/condvar2.c new file mode 100644 index 0000000..08f472c --- /dev/null +++ b/liblo/pthreads.2/tests/condvar2.c @@ -0,0 +1,125 @@ +/* + * File: condvar2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test timed wait on a CV. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Because the CV is never signaled, we expect the wait to time out. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait does not return ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +#define _WIN32_WINNT 0x400 + +#include "test.h" +#include + +pthread_cond_t cv; +pthread_mutex_t mutex; + +#include "../implement.h" + +int +main() +{ + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert(pthread_cond_init(&cv, NULL) == 0); + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + assert(pthread_mutex_lock(&mutex) == 0); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == ETIMEDOUT); + + assert(pthread_mutex_unlock(&mutex) == 0); + + { + int result = pthread_cond_destroy(&cv); + if (result != 0) + { + fprintf(stderr, "Result = %s\n", error_string[result]); + fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked); + fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone); + fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock); + fflush(stderr); + } + assert(result == 0); + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar2_1.c b/liblo/pthreads.2/tests/condvar2_1.c new file mode 100644 index 0000000..6d56180 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar2_1.c @@ -0,0 +1,153 @@ +/* + * File: condvar2_1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test timeout of multiple waits on a CV with no signal/broadcast. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Because the CV is never signaled, we expect the waits to time out. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait does not return ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +#define _WIN32_WINNT 0x400 + +#include "test.h" +#include + +static pthread_cond_t cv; +static pthread_mutex_t mutex; +static struct timespec abstime = { 0, 0 }; + +enum { + NUMTHREADS = 30 +}; + +void * +mythread(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == ETIMEDOUT); + + assert(pthread_mutex_unlock(&mutex) == 0); + + return arg; +} + +#include "../implement.h" + +int +main() +{ + int i; + pthread_t t[NUMTHREADS + 1]; + int result = 0; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert(pthread_cond_init(&cv, NULL) == 0); + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + assert(pthread_mutex_lock(&mutex) == 0); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0); + } + + assert(pthread_mutex_unlock(&mutex) == 0); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_join(t[i], (void **) &result) == 0); + assert(result == i); + } + + { + int result = pthread_cond_destroy(&cv); + if (result != 0) + { + fprintf(stderr, "Result = %s\n", error_string[result]); + fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked); + fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone); + fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock); + fflush(stderr); + } + assert(result == 0); + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar3.c b/liblo/pthreads.2/tests/condvar3.c new file mode 100644 index 0000000..60cd0e7 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar3.c @@ -0,0 +1,148 @@ +/* + * File: condvar3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test basic function of a CV + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - The primary thread takes the lock before creating any threads. + * The secondary thread blocks on the lock allowing the primary + * thread to enter the cv wait state which releases the lock. + * The secondary thread then takes the lock and signals the waiting + * primary thread. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns 0. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + +static pthread_cond_t cv; +static pthread_mutex_t mutex; +static int shared = 0; + +enum { + NUMTHREADS = 2 /* Including the primary thread. */ +}; + +void * +mythread(void * arg) +{ + int result = 0; + + assert(pthread_mutex_lock(&mutex) == 0); + shared++; + assert(pthread_mutex_unlock(&mutex) == 0); + + if ((result = pthread_cond_signal(&cv)) != 0) + { + printf("Error = %s\n", error_string[result]); + } + assert(result == 0); + + + return (void *) 0; +} + +int +main() +{ + pthread_t t[NUMTHREADS]; + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert((t[0] = pthread_self()).p != NULL); + + assert(pthread_cond_init(&cv, NULL) == 0); + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + assert(pthread_mutex_lock(&mutex) == 0); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0); + + abstime.tv_sec += 5; + + while (! (shared > 0)) + assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == 0); + + assert(shared > 0); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_join(t[1], NULL) == 0); + + assert(pthread_cond_destroy(&cv) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar3_1.c b/liblo/pthreads.2/tests/condvar3_1.c new file mode 100644 index 0000000..369c07c --- /dev/null +++ b/liblo/pthreads.2/tests/condvar3_1.c @@ -0,0 +1,201 @@ +/* + * File: condvar3_1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test timeout of multiple waits on a CV with some signaled. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Because some CVs are never signaled, we expect their waits to time out. + * Some are signaled, the rest time out. Pthread_cond_destroy() will fail + * unless all are accounted for, either signaled or timedout. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait does not return ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +#define _WIN32_WINNT 0x400 + +#include "test.h" +#include + +static pthread_cond_t cv; +static pthread_cond_t cv1; +static pthread_mutex_t mutex; +static pthread_mutex_t mutex1; +static struct timespec abstime = { 0, 0 }; +static int timedout = 0; +static int signaled = 0; +static int awoken = 0; +static int waiting = 0; + +enum { + NUMTHREADS = 30 +}; + +void * +mythread(void * arg) +{ + int result; + + assert(pthread_mutex_lock(&mutex1) == 0); + ++waiting; + assert(pthread_mutex_unlock(&mutex1) == 0); + assert(pthread_cond_signal(&cv1) == 0); + + assert(pthread_mutex_lock(&mutex) == 0); + result = pthread_cond_timedwait(&cv, &mutex, &abstime); + if (result == ETIMEDOUT) + { + timedout++; + } + else + { + awoken++; + } + assert(pthread_mutex_unlock(&mutex) == 0); + + return arg; +} + +#include "../implement.h" + +int +main() +{ + int i; + pthread_t t[NUMTHREADS + 1]; + int result = 0; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert(pthread_cond_init(&cv, NULL) == 0); + assert(pthread_cond_init(&cv1, NULL) == 0); + + assert(pthread_mutex_init(&mutex, NULL) == 0); + assert(pthread_mutex_init(&mutex1, NULL) == 0); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + assert(pthread_mutex_lock(&mutex1) == 0); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0); + } + + do { + assert(pthread_cond_wait(&cv1,&mutex1) == 0); + } while ( NUMTHREADS > waiting ); + + assert(pthread_mutex_unlock(&mutex1) == 0); + + for (i = NUMTHREADS/3; i <= 2*NUMTHREADS/3; i++) + { +// assert(pthread_mutex_lock(&mutex) == 0); + assert(pthread_cond_signal(&cv) == 0); +// assert(pthread_mutex_unlock(&mutex) == 0); + + signaled++; + } + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_join(t[i], (void **) &result) == 0); + assert(result == i); + } + + fprintf(stderr, "awk = %d\n", awoken); + fprintf(stderr, "sig = %d\n", signaled); + fprintf(stderr, "tot = %d\n", timedout); + + assert(signaled == awoken); + assert(timedout == NUMTHREADS - signaled); + + assert(pthread_cond_destroy(&cv1) == 0); + + { + int result = pthread_cond_destroy(&cv); + if (result != 0) + { + fprintf(stderr, "Result = %s\n", error_string[result]); + fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked); + fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone); + fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock); + fflush(stderr); + } + assert(result == 0); + } + + assert(pthread_mutex_destroy(&mutex1) == 0); + assert(pthread_mutex_destroy(&mutex) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar3_2.c b/liblo/pthreads.2/tests/condvar3_2.c new file mode 100644 index 0000000..c9d58ad --- /dev/null +++ b/liblo/pthreads.2/tests/condvar3_2.c @@ -0,0 +1,193 @@ +/* + * File: condvar3_2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test timeout of multiple waits on a CV with remainder broadcast awoken. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Because some CVs are never signaled, we expect their waits to time out. + * Some time out, the rest are broadcast signaled. Pthread_cond_destroy() will fail + * unless all are accounted for, either signaled or timedout. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait does not return ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +#define _WIN32_WINNT 0x400 + +#include "test.h" +#include + +static pthread_cond_t cv; +static pthread_mutex_t mutex; +static struct timespec abstime = { 0, 0 }; +static struct timespec abstime2 = { 0, 0 }; +static int timedout = 0; +static int awoken = 0; + +enum { + NUMTHREADS = 30 +}; + +void * +mythread(void * arg) +{ + int result; + + assert(pthread_mutex_lock(&mutex) == 0); + + abstime2.tv_sec = abstime.tv_sec; + + if ((int) arg % 3 == 0) + { + abstime2.tv_sec += 2; + } + + result = pthread_cond_timedwait(&cv, &mutex, &abstime2); + assert(pthread_mutex_unlock(&mutex) == 0); + if (result == ETIMEDOUT) + { + InterlockedIncrement((LPLONG)&timedout); + } + else + { + InterlockedIncrement((LPLONG)&awoken); + } + + + return arg; +} + +#include "../implement.h" + +int +main() +{ + int i; + pthread_t t[NUMTHREADS + 1]; + int result = 0; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert(pthread_cond_init(&cv, NULL) == 0); + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = abstime.tv_sec = currSysTime.time + 5; + abstime.tv_nsec = abstime2.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + assert(pthread_mutex_lock(&mutex) == 0); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0); + } + + assert(pthread_mutex_unlock(&mutex) == 0); + + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_join(t[i], (void **) &result) == 0); + assert(result == i); + /* + * Approximately 2/3rds of the threads are expected to time out. + * Signal the remainder after some threads have woken up and exited + * and while some are still waking up after timeout. + * Also tests that redundant broadcasts don't return errors. + */ + +// assert(pthread_mutex_lock(&mutex) == 0); + + if (InterlockedExchangeAdd((LPLONG)&awoken, 0L) > NUMTHREADS/3) + { + assert(pthread_cond_broadcast(&cv) == 0); + } + +// assert(pthread_mutex_unlock(&mutex) == 0); + + } + + assert(awoken == NUMTHREADS - timedout); + + { + int result = pthread_cond_destroy(&cv); + if (result != 0) + { + fprintf(stderr, "Result = %s\n", error_string[result]); + fprintf(stderr, "\tWaitersBlocked = %ld\n", cv->nWaitersBlocked); + fprintf(stderr, "\tWaitersGone = %ld\n", cv->nWaitersGone); + fprintf(stderr, "\tWaitersToUnblock = %ld\n", cv->nWaitersToUnblock); + fflush(stderr); + } + assert(result == 0); + } + + assert(pthread_mutex_destroy(&mutex) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar3_3.c b/liblo/pthreads.2/tests/condvar3_3.c new file mode 100644 index 0000000..840a83b --- /dev/null +++ b/liblo/pthreads.2/tests/condvar3_3.c @@ -0,0 +1,132 @@ +/* + * File: condvar3_3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test timeouts and lost signals on a CV. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait does not return ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +/* Timur Aydin (taydin@snet.net) */ + +#include "test.h" + +#include + +pthread_cond_t cnd; +pthread_mutex_t mtx; + +int main() +{ + int rc; + + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert(pthread_cond_init(&cnd, 0) == 0); + assert(pthread_mutex_init(&mtx, 0) == 0); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + abstime.tv_sec += 1; + + /* Here pthread_cond_timedwait should time out after one second. */ + + assert(pthread_mutex_lock(&mtx) == 0); + + assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT); + + assert(pthread_mutex_unlock(&mtx) == 0); + + /* Here, the condition variable is signaled, but there are no + threads waiting on it. The signal should be lost and + the next pthread_cond_timedwait should time out too. */ + +// assert(pthread_mutex_lock(&mtx) == 0); + + assert((rc = pthread_cond_signal(&cnd)) == 0); + +// assert(pthread_mutex_unlock(&mtx) == 0); + + assert(pthread_mutex_lock(&mtx) == 0); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + abstime.tv_sec += 1; + + assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT); + + assert(pthread_mutex_unlock(&mtx) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar4.c b/liblo/pthreads.2/tests/condvar4.c new file mode 100644 index 0000000..89fa855 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar4.c @@ -0,0 +1,169 @@ +/* + * File: condvar4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test PTHREAD_COND_INITIALIZER. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Test basic CV function but starting with a static initialised + * CV. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns 0. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + +typedef struct cvthing_t_ cvthing_t; + +struct cvthing_t_ { + pthread_cond_t notbusy; + pthread_mutex_t lock; + int shared; +}; + +static cvthing_t cvthing = { + PTHREAD_COND_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + 0 +}; + +enum { + NUMTHREADS = 2 +}; + +void * +mythread(void * arg) +{ + assert(pthread_mutex_lock(&cvthing.lock) == 0); + cvthing.shared++; + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + assert(pthread_cond_signal(&cvthing.notbusy) == 0); + + return (void *) 0; +} + +int +main() +{ + pthread_t t[NUMTHREADS]; + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + cvthing.shared = 0; + + assert((t[0] = pthread_self()).p != NULL); + + assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER); + + assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + + assert(cvthing.lock != PTHREAD_MUTEX_INITIALIZER); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT); + + assert(cvthing.notbusy != PTHREAD_COND_INITIALIZER); + + assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0); + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + while (! (cvthing.shared > 0)) + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0); + + assert(cvthing.shared > 0); + + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + assert(pthread_join(t[1], NULL) == 0); + + assert(pthread_mutex_destroy(&cvthing.lock) == 0); + + assert(cvthing.lock == NULL); + + assert(pthread_cond_destroy(&cvthing.notbusy) == 0); + + assert(cvthing.notbusy == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar5.c b/liblo/pthreads.2/tests/condvar5.c new file mode 100644 index 0000000..4836676 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar5.c @@ -0,0 +1,168 @@ +/* + * File: condvar5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test pthread_cond_broadcast. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Test broadcast with one waiting CV. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - pthread_cond_timedwait returns 0. + * - Process returns zero exit status. + * + * Fail Criteria: + * - pthread_cond_timedwait returns ETIMEDOUT. + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + +typedef struct cvthing_t_ cvthing_t; + +struct cvthing_t_ { + pthread_cond_t notbusy; + pthread_mutex_t lock; + int shared; +}; + +static cvthing_t cvthing = { + PTHREAD_COND_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + 0 +}; + +enum { + NUMTHREADS = 2 +}; + +void * +mythread(void * arg) +{ + assert(pthread_mutex_lock(&cvthing.lock) == 0); + cvthing.shared++; + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + assert(pthread_cond_broadcast(&cvthing.notbusy) == 0); + + return (void *) 0; +} + +int +main() +{ + pthread_t t[NUMTHREADS]; + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + cvthing.shared = 0; + + assert((t[0] = pthread_self()).p != NULL); + + assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER); + + assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + + assert(cvthing.lock != PTHREAD_MUTEX_INITIALIZER); + + /* get current system time */ + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT); + + assert(cvthing.notbusy != PTHREAD_COND_INITIALIZER); + + assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0); + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + while (! (cvthing.shared > 0)) + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0); + + assert(cvthing.shared > 0); + + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + assert(pthread_join(t[1], NULL) == 0); + + assert(pthread_mutex_destroy(&cvthing.lock) == 0); + + assert(cvthing.lock == NULL); + + assert(pthread_cond_destroy(&cvthing.notbusy) == 0); + + assert(cvthing.notbusy == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar6.c b/liblo/pthreads.2/tests/condvar6.c new file mode 100644 index 0000000..1cb1d9e --- /dev/null +++ b/liblo/pthreads.2/tests/condvar6.c @@ -0,0 +1,242 @@ +/* + * File: condvar6.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test pthread_cond_broadcast. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Test broadcast with NUMTHREADS (=5) waiting CVs. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 5 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct cvthing_t_ cvthing_t; + +struct cvthing_t_ { + pthread_cond_t notbusy; + pthread_mutex_t lock; + int shared; +}; + +static cvthing_t cvthing = { + PTHREAD_COND_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + 0 +}; + +static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER; + +static struct timespec abstime = { 0, 0 }; + +static int awoken; + +void * +mythread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Wait for the start gun */ + assert(pthread_mutex_lock(&start_flag) == 0); + assert(pthread_mutex_unlock(&start_flag) == 0); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + + while (! (cvthing.shared > 0)) + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0); + + assert(cvthing.shared > 0); + + awoken++; + + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + return (void *) 0; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + cvthing.shared = 0; + + assert((t[0] = pthread_self()).p != NULL); + + assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER); + + assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER); + + assert(pthread_mutex_lock(&start_flag) == 0); + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + assert((t[0] = pthread_self()).p != NULL); + + awoken = 0; + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + + assert(pthread_mutex_unlock(&start_flag) == 0); + + /* + * Give threads time to start. + */ + Sleep(1000); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + cvthing.shared++; + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + assert(pthread_cond_broadcast(&cvthing.notbusy) == 0); + + /* + * Give threads time to complete. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + assert(pthread_join(t[i], NULL) == 0); + } + + /* + * Cleanup the CV. + */ + + assert(pthread_mutex_destroy(&cvthing.lock) == 0); + + assert(cvthing.lock == NULL); + + assert(pthread_cond_destroy(&cvthing.notbusy) == 0); + + assert(cvthing.notbusy == NULL); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + failed = !threadbag[i].started; + + if (failed) + { + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. + */ + + assert(awoken == NUMTHREADS); + + /* + * Success. + */ + return 0; +} + + diff --git a/liblo/pthreads.2/tests/condvar7.c b/liblo/pthreads.2/tests/condvar7.c new file mode 100644 index 0000000..696a18e --- /dev/null +++ b/liblo/pthreads.2/tests/condvar7.c @@ -0,0 +1,257 @@ +/* + * File: condvar7.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test pthread_cond_broadcast with thread cancelation. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Test broadcast with NUMTHREADS (=5) waiting CVs, one is canceled while waiting. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 5 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct cvthing_t_ cvthing_t; + +struct cvthing_t_ { + pthread_cond_t notbusy; + pthread_mutex_t lock; + int shared; +}; + +static cvthing_t cvthing = { + PTHREAD_COND_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + 0 +}; + +static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER; + +static struct timespec abstime = { 0, 0 }; + +static int awoken; + +void * +mythread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Wait for the start gun */ + assert(pthread_mutex_lock(&start_flag) == 0); + assert(pthread_mutex_unlock(&start_flag) == 0); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock); + + while (! (cvthing.shared > 0)) + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0); + + pthread_cleanup_pop(0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + assert(cvthing.shared > 0); + + awoken++; + + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + return (void *) 0; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + cvthing.shared = 0; + + assert((t[0] = pthread_self()).p != NULL); + + assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER); + + assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER); + + assert(pthread_mutex_lock(&start_flag) == 0); + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 10; + + assert((t[0] = pthread_self()).p != NULL); + + awoken = 0; + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + + assert(pthread_mutex_unlock(&start_flag) == 0); + + /* + * Give threads time to start. + */ + Sleep(1000); + + /* + * Cancel one of the threads. + */ + assert(pthread_cancel(t[1]) == 0); + assert(pthread_join(t[1], NULL) == 0); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + cvthing.shared++; + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + /* + * Signal all remaining waiting threads. + */ + assert(pthread_cond_broadcast(&cvthing.notbusy) == 0); + + /* + * Wait for all threads to complete. + */ + for (i = 2; i <= NUMTHREADS; i++) + assert(pthread_join(t[i], NULL) == 0); + + /* + * Cleanup the CV. + */ + + assert(pthread_mutex_destroy(&cvthing.lock) == 0); + + assert(cvthing.lock == NULL); + + assert(pthread_cond_destroy(&cvthing.notbusy) == 0); + + assert(cvthing.notbusy == NULL); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + failed = !threadbag[i].started; + + if (failed) + { + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. + */ + + assert(awoken == (NUMTHREADS - 1)); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar8.c b/liblo/pthreads.2/tests/condvar8.c new file mode 100644 index 0000000..890970e --- /dev/null +++ b/liblo/pthreads.2/tests/condvar8.c @@ -0,0 +1,258 @@ +/* + * File: condvar8.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test multiple pthread_cond_broadcasts. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Make NUMTHREADS threads wait on CV, broadcast signal them, and then repeat. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 5 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct cvthing_t_ cvthing_t; + +struct cvthing_t_ { + pthread_cond_t notbusy; + pthread_mutex_t lock; + int shared; +}; + +static cvthing_t cvthing = { + PTHREAD_COND_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + 0 +}; + +static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER; + +static struct timespec abstime = { 0, 0 }; + +static int awoken; + +static void * +mythread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Wait for the start gun */ + assert(pthread_mutex_lock(&start_flag) == 0); + assert(pthread_mutex_unlock(&start_flag) == 0); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock); + + while (! (cvthing.shared > 0)) + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0); + + pthread_cleanup_pop(0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + assert(cvthing.shared > 0); + + awoken++; + + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + return (void *) 0; +} + +int +main() +{ + int failed = 0; + int i; + int first, last; + pthread_t t[NUMTHREADS + 1]; + + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert((t[0] = pthread_self()).p != NULL); + + assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER); + + assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER); + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 10; + + assert((t[0] = pthread_self()).p != NULL); + + awoken = 0; + + for (first = 1, last = NUMTHREADS / 2; + first < NUMTHREADS; + first = last + 1, last = NUMTHREADS) + { + assert(pthread_mutex_lock(&start_flag) == 0); + + for (i = first; i <= last; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + cvthing.shared = 0; + + assert(pthread_mutex_unlock(&start_flag) == 0); + + /* + * Give threads time to start. + */ + Sleep(100); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + cvthing.shared++; + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + assert(pthread_cond_broadcast(&cvthing.notbusy) == 0); + + /* + * Give threads time to complete. + */ + for (i = first; i <= last; i++) + { + assert(pthread_join(t[i], NULL) == 0); + } + + assert(awoken == (i - 1)); + } + + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + failed = !threadbag[i].started; + + if (failed) + { + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + /* + * Cleanup the CV. + */ + + assert(pthread_mutex_destroy(&cvthing.lock) == 0); + + assert(cvthing.lock == NULL); + + assert(pthread_cond_destroy(&cvthing.notbusy) == 0); + + assert(cvthing.notbusy == NULL); + + assert(!failed); + + /* + * Check any results here. + */ + + assert(awoken == NUMTHREADS); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/condvar9.c b/liblo/pthreads.2/tests/condvar9.c new file mode 100644 index 0000000..6610af7 --- /dev/null +++ b/liblo/pthreads.2/tests/condvar9.c @@ -0,0 +1,267 @@ +/* + * File: condvar9.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test multiple pthread_cond_broadcasts with thread cancelation. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - Make NUMTHREADS threads wait on CV, cancel one, broadcast signal them, + * and then repeat. + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#include + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 9 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + int finished; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +typedef struct cvthing_t_ cvthing_t; + +struct cvthing_t_ { + pthread_cond_t notbusy; + pthread_mutex_t lock; + int shared; +}; + +static cvthing_t cvthing = { + PTHREAD_COND_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + 0 +}; + +static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER; + +static struct timespec abstime = { 0, 0 }; + +static int awoken; + +static void * +mythread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* Wait for the start gun */ + assert(pthread_mutex_lock(&start_flag) == 0); + assert(pthread_mutex_unlock(&start_flag) == 0); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + + /* + * pthread_cond_timedwait is a cancelation point and we're + * going to cancel some threads deliberately. + */ +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock); + + while (! (cvthing.shared > 0)) + assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0); + + pthread_cleanup_pop(0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + assert(cvthing.shared > 0); + + awoken++; + bag->finished = 1; + + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + return (void *) 0; +} + +int +main() +{ + int failed = 0; + int i; + int first, last; + int canceledThreads = 0; + pthread_t t[NUMTHREADS + 1]; + + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + assert((t[0] = pthread_self()).p != NULL); + + assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER); + + assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER); + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 5; + + assert((t[0] = pthread_self()).p != NULL); + + awoken = 0; + + for (first = 1, last = NUMTHREADS / 2; + first < NUMTHREADS; + first = last + 1, last = NUMTHREADS) + { + int ct; + + assert(pthread_mutex_lock(&start_flag) == 0); + + for (i = first; i <= last; i++) + { + threadbag[i].started = threadbag[i].finished = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + cvthing.shared = 0; + + assert(pthread_mutex_unlock(&start_flag) == 0); + + /* + * Give threads time to start. + */ + Sleep(1000); + + ct = (first + last) / 2; + assert(pthread_cancel(t[ct]) == 0); + canceledThreads++; + assert(pthread_join(t[ct], NULL) == 0); + + assert(pthread_mutex_lock(&cvthing.lock) == 0); + cvthing.shared++; + assert(pthread_mutex_unlock(&cvthing.lock) == 0); + + assert(pthread_cond_broadcast(&cvthing.notbusy) == 0); + + /* + * Standard check that all threads started - and wait for them to finish. + */ + for (i = first; i <= last; i++) + { + failed = !threadbag[i].started; + + if (failed) + { + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + else + { + assert(pthread_join(t[i], NULL) == 0 || threadbag[i].finished == 0); +// fprintf(stderr, "Thread %d: finished %d\n", i, threadbag[i].finished); + } + } + } + + /* + * Cleanup the CV. + */ + + assert(pthread_mutex_destroy(&cvthing.lock) == 0); + + assert(cvthing.lock == NULL); + + assert_e(pthread_cond_destroy(&cvthing.notbusy), ==, 0); + + assert(cvthing.notbusy == NULL); + + assert(!failed); + + /* + * Check any results here. + */ + + assert(awoken == NUMTHREADS - canceledThreads); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/context1.c b/liblo/pthreads.2/tests/context1.c new file mode 100644 index 0000000..ebfc1f4 --- /dev/null +++ b/liblo/pthreads.2/tests/context1.c @@ -0,0 +1,144 @@ +/* + * File: context1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test context switching method. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - pthread_create + * pthread_exit + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#define _WIN32_WINNT 0x400 + +#include "test.h" +#include "../implement.h" + +static int washere = 0; + +static void * func(void * arg) +{ + washere = 1; + + Sleep(1000); + + return 0; +} + +static void +anotherEnding () +{ + /* + * Switched context + */ + washere++; + + pthread_exit(0); +} + +int +main() +{ + pthread_t t; + HANDLE hThread; + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + hThread = ((ptw32_thread_t *)t.p)->threadH; + + Sleep(500); + + SuspendThread(hThread); + + if (WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT) + { + /* + * Ok, thread did not exit before we got to it. + */ + CONTEXT context; + + context.ContextFlags = CONTEXT_CONTROL; + + GetThreadContext(hThread, &context); + /* + *_x86 only!!! + */ + context.Eip = (DWORD) anotherEnding; + SetThreadContext(hThread, &context); + ResumeThread(hThread); + } + else + { + printf("Exited early\n"); + fflush(stdout); + } + + Sleep(1000); + + assert(washere == 2); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/count1.c b/liblo/pthreads.2/tests/count1.c new file mode 100644 index 0000000..d1508cc --- /dev/null +++ b/liblo/pthreads.2/tests/count1.c @@ -0,0 +1,90 @@ +/* + * count1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Description: + * Test some basic assertions about the number of threads at runtime. + */ + +#include "test.h" + +#define NUMTHREADS (30) + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_t threads[NUMTHREADS]; +static unsigned numThreads = 0; + +void * +myfunc(void *arg) +{ + pthread_mutex_lock(&lock); + numThreads++; + pthread_mutex_unlock(&lock); + + Sleep(1000); + return 0; +} +int +main() +{ + int i; + int maxThreads = sizeof(threads) / sizeof(pthread_t); + + /* + * Spawn NUMTHREADS threads. Each thread should increment the + * numThreads variable, sleep for one second. + */ + for (i = 0; i < maxThreads; i++) + { + assert(pthread_create(&threads[i], NULL, myfunc, 0) == 0); + } + + /* + * Wait for all the threads to exit. + */ + for (i = 0; i < maxThreads; i++) + { + assert(pthread_join(threads[i], NULL) == 0); + } + + /* + * Check the number of threads created. + */ + assert((int) numThreads == maxThreads); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/create1.c b/liblo/pthreads.2/tests/create1.c new file mode 100644 index 0000000..61fc9be --- /dev/null +++ b/liblo/pthreads.2/tests/create1.c @@ -0,0 +1,66 @@ +/* + * create1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Description: + * Create a thread and check that it ran. + * + * Depends on API functions: None. + */ + +#include "test.h" + +static int washere = 0; + +void * func(void * arg) +{ + washere = 1; + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + /* A dirty hack, but we cannot rely on pthread_join in this + primitive test. */ + Sleep(2000); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/create2.c b/liblo/pthreads.2/tests/create2.c new file mode 100644 index 0000000..07dbffb --- /dev/null +++ b/liblo/pthreads.2/tests/create2.c @@ -0,0 +1,108 @@ +/* + * File: create2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test that threads have a Win32 handle when started. + * + * Test Method (Validation or Falsification): + * - Statistical, not absolute (depends on sample size). + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +enum { + NUMTHREADS = 10000 +}; + +static int washere = 0; + +void * func(void * arg) +{ + washere = 1; + return (void *) 0; +} + +int +main() +{ + pthread_t t; + pthread_attr_t attr; + void * result = NULL; + int i; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + for (i = 0; i < NUMTHREADS; i++) + { + washere = 0; + assert(pthread_create(&t, &attr, func, NULL) == 0); + pthread_join(t, &result); + assert(washere == 1); + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/create3.c b/liblo/pthreads.2/tests/create3.c new file mode 100644 index 0000000..4ab51e4 --- /dev/null +++ b/liblo/pthreads.2/tests/create3.c @@ -0,0 +1,122 @@ +/* + * File: create3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2003 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test passing NULL as thread id arg to pthread_create. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + + +#ifdef __GNUC__ +#include +#endif + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 1 +}; + + +void * +threadFunc(void * arg) +{ + return (void *) 0; +} + +int +main(int argc, char * argv[]) +{ + int i; + pthread_t mt; + + if (argc <= 1) + { + int result; + + printf("You should see an application memory write error message\n"); + fflush(stdout); + result = system("create3.exe die"); + exit(0); + } + + assert((mt = pthread_self()).p != NULL); + + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_create(NULL, NULL, threadFunc, NULL) == 0); + } + + /* + * Success. + */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/delay1.c b/liblo/pthreads.2/tests/delay1.c new file mode 100644 index 0000000..aaf58d8 --- /dev/null +++ b/liblo/pthreads.2/tests/delay1.c @@ -0,0 +1,51 @@ +/* + * delay1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: + * pthread_delay_np + */ + +#include "test.h" + +int +main(int argc, char * argv[]) +{ + struct timespec interval = {1L, 500000000L}; + + assert(pthread_delay_np(&interval) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/delay2.c b/liblo/pthreads.2/tests/delay2.c new file mode 100644 index 0000000..9885031 --- /dev/null +++ b/liblo/pthreads.2/tests/delay2.c @@ -0,0 +1,82 @@ +/* + * delay1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: + * pthread_delay_np + */ + +#include "test.h" + +pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; + +void * +func(void * arg) +{ + struct timespec interval = {5, 500000000L}; + + assert(pthread_mutex_lock(&mx) == 0); + +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(pthread_mutex_unlock, &mx); + assert(pthread_delay_np(&interval) == 0); + pthread_cleanup_pop(1); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + + return (void *) 1; +} + +int +main(int argc, char * argv[]) +{ + pthread_t t; + int result = 0; + + assert(pthread_mutex_lock(&mx) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + assert(pthread_cancel(t) == 0); + + assert(pthread_mutex_unlock(&mx) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result == (int) PTHREAD_CANCELED); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/detach1.c b/liblo/pthreads.2/tests/detach1.c new file mode 100644 index 0000000..b237fc9 --- /dev/null +++ b/liblo/pthreads.2/tests/detach1.c @@ -0,0 +1,93 @@ +/* + * Test for pthread_detach(). + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: pthread_create(), pthread_detach(), pthread_exit(). + */ + +#include "test.h" + + +enum { + NUMTHREADS = 100 +}; + +void * +func(void * arg) +{ + int i = (int) arg; + + Sleep(i * 10); + + pthread_exit(arg); + + /* Never reached. */ + exit(1); +} + +int +main(int argc, char * argv[]) +{ + pthread_t id[NUMTHREADS]; + int i; + + /* Create a few threads and then exit. */ + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); + } + + /* Some threads will finish before they are detached, some after. */ + Sleep(NUMTHREADS/2 * 10 + 50); + + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_detach(id[i]) == 0); + } + + Sleep(NUMTHREADS * 10 + 100); + + /* + * Check that all threads are now invalid. + * This relies on unique thread IDs - e.g. works with + * pthreads-w32 or Solaris, but may not work for Linux, BSD etc. + */ + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_kill(id[i], 0) == ESRCH); + } + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/equal1.c b/liblo/pthreads.2/tests/equal1.c new file mode 100644 index 0000000..01639d9 --- /dev/null +++ b/liblo/pthreads.2/tests/equal1.c @@ -0,0 +1,66 @@ +/* + * Test for pthread_equal. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on functions: pthread_create(). + */ + +#include "test.h" + +void * func(void * arg) +{ + Sleep(2000); + return 0; +} + +int +main() +{ + pthread_t t1, t2; + + assert(pthread_create(&t1, NULL, func, (void *) 1) == 0); + + assert(pthread_create(&t2, NULL, func, (void *) 2) == 0); + + assert(pthread_equal(t1, t2) == 0); + + assert(pthread_equal(t1,t1) != 0); + + /* This is a hack. We don't want to rely on pthread_join + yet if we can help it. */ + Sleep(4000); + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/errno1.c b/liblo/pthreads.2/tests/errno1.c new file mode 100644 index 0000000..7f10cb0 --- /dev/null +++ b/liblo/pthreads.2/tests/errno1.c @@ -0,0 +1,177 @@ +/* + * File: errno1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test thread-safety of errno + * - + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 3 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +pthread_mutex_t stop_here = PTHREAD_MUTEX_INITIALIZER; + +void * +mythread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + errno = bag->threadnum; + + Sleep(1000); + + pthread_mutex_lock(&stop_here); + + assert(errno == bag->threadnum); + + pthread_mutex_unlock(&stop_here); + + Sleep(1000); + + return 0; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t t[NUMTHREADS + 1]; + + pthread_mutex_lock(&stop_here); + errno = 0; + + assert((t[0] = pthread_self()).p != NULL); + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; + assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(2000); + pthread_mutex_unlock(&stop_here); + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 1000); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + failed = !threadbag[i].started; + + if (failed) + { + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print ouput on failure. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + /* ... */ + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} diff --git a/liblo/pthreads.2/tests/exception1.c b/liblo/pthreads.2/tests/exception1.c new file mode 100644 index 0000000..432b218 --- /dev/null +++ b/liblo/pthreads.2/tests/exception1.c @@ -0,0 +1,263 @@ +/* + * File: exception1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test passing of exceptions back to the application. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#if defined(_MSC_VER) || defined(__cplusplus) + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +void * +exceptionedThread(void * arg) +{ + int dummy = 0; + int result = ((int)PTHREAD_CANCELED + 1); + /* Set to async cancelable */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + + Sleep(100); + +#if defined(_MSC_VER) && !defined(__cplusplus) + __try + { + int zero = (int) arg; /* Passed in from arg to avoid compiler error */ + int one = 1; + /* + * The deliberate exception condition (zero divide) is + * in an "if" to avoid being optimised out. + */ + if (dummy == one/zero) + Sleep(0); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + /* Should get into here. */ + result = ((int)PTHREAD_CANCELED + 2); + } +#elif defined(__cplusplus) + try + { + /* + * I had a zero divide exception here but it + * wasn't being caught by the catch(...) + * below under Mingw32. That could be a problem. + */ + throw dummy; + } +#if defined(PtW32CatchAll) + PtW32CatchAll +#else + catch (...) +#endif + { + /* Should get into here. */ + result = ((int)PTHREAD_CANCELED + 2); + } +#endif + + return (void *) result; +} + +void * +canceledThread(void * arg) +{ + int result = ((int)PTHREAD_CANCELED + 1); + int count; + + /* Set to async cancelable */ + + assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0); + + assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0); + +#if defined(_MSC_VER) && !defined(__cplusplus) + __try + { + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (count = 0; count < 100; count++) + Sleep(100); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + /* Should NOT get into here. */ + result = ((int)PTHREAD_CANCELED + 2); + } +#elif defined(__cplusplus) + try + { + /* + * We wait up to 10 seconds, waking every 0.1 seconds, + * for a cancelation to be applied to us. + */ + for (count = 0; count < 100; count++) + Sleep(100); + } +#if defined(PtW32CatchAll) + PtW32CatchAll +#else + catch (...) +#endif + { + /* Should NOT get into here. */ + result = ((int)PTHREAD_CANCELED + 2); + } +#endif + + return (void *) result; +} + +int +main() +{ + int failed = 0; + int i; + pthread_t mt; + pthread_t et[NUMTHREADS]; + pthread_t ct[NUMTHREADS]; + + assert((mt = pthread_self()).p != NULL); + + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_create(&et[i], NULL, exceptionedThread, (void *) 0) == 0); + assert(pthread_create(&ct[i], NULL, canceledThread, NULL) == 0); + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(1000); + + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_cancel(ct[i]) == 0); + } + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 1000); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 0; i < NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + + /* Canceled thread */ + assert(pthread_join(ct[i], (void **) &result) == 0); + assert(!(fail = (result != (int) PTHREAD_CANCELED))); + + failed = (failed || fail); + + /* Exceptioned thread */ + assert(pthread_join(et[i], (void **) &result) == 0); + assert(!(fail = (result != ((int) PTHREAD_CANCELED + 2)))); + + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +#include + +int +main() +{ + fprintf(stderr, "Test N/A for this compiler environment.\n"); + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/exception2.c b/liblo/pthreads.2/tests/exception2.c new file mode 100644 index 0000000..fe17a1a --- /dev/null +++ b/liblo/pthreads.2/tests/exception2.c @@ -0,0 +1,158 @@ +/* + * File: exception2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test passing of exceptions out of thread scope. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + + +#if defined(_MSC_VER) || defined(__cplusplus) + +#if defined(_MSC_VER) && defined(__cplusplus) +#include +#elif defined(__cplusplus) +#include +#endif + +#ifdef __GNUC__ +#include +#endif + +#include "test.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 1 +}; + + +void * +exceptionedThread(void * arg) +{ + int dummy = 0x1; + +#if defined(_MSC_VER) && !defined(__cplusplus) + + RaiseException(dummy, 0, 0, NULL); + +#elif defined(__cplusplus) + + throw dummy; + +#endif + + return (void *) 100; +} + +int +main(int argc, char argv[]) +{ + int i; + pthread_t mt; + pthread_t et[NUMTHREADS]; + + if (argc <= 1) + { + int result; + + printf("You should see an \"abnormal termination\" message\n"); + fflush(stdout); + result = system("exception2.exe die"); + exit(0); + } + + assert((mt = pthread_self()).p != NULL); + + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_create(&et[i], NULL, exceptionedThread, NULL) == 0); + } + + Sleep(1000); + + /* + * Success. + */ + return 0; +} + +#else /* defined(_MSC_VER) || defined(__cplusplus) */ + +#include + +int +main() +{ + fprintf(stderr, "Test N/A for this compiler environment.\n"); + return 0; +} + +#endif /* defined(_MSC_VER) || defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/exception3.c b/liblo/pthreads.2/tests/exception3.c new file mode 100644 index 0000000..4511357 --- /dev/null +++ b/liblo/pthreads.2/tests/exception3.c @@ -0,0 +1,196 @@ +/* + * File: exception3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test running of user supplied terminate() function. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +#if defined(__cplusplus) + +#if defined(_MSC_VER) +# include +#else +# if defined(__GNUC__) && __GNUC__ < 3 +# include +# else +# include + using std::set_terminate; +# endif +#endif + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 1 +}; + +int caught = 0; +pthread_mutex_t caughtLock; + +void +terminateFunction () +{ + assert(pthread_mutex_lock(&caughtLock) == 0); + caught++; +#if 1 + { + FILE * fp = fopen("pthread.log", "a"); + fprintf(fp, "Caught = %d\n", caught); + fclose(fp); + } +#endif + assert(pthread_mutex_unlock(&caughtLock) == 0); + +#if defined(__MINGW32__) + /* + * Seems to work. That is, threads exit and the process + * continues. Note: need to check correct POSIX behaviour. + * My guess is: this is because of the + * eh incompatibility between g++ and MSVC++. That is, + * an exception thrown in g++ code doesn't propogate + * through or to MSVC++ code, and vice versa. + * Applications should probably not depend on this. + */ + pthread_exit((void *) 0); +#else + /* + * Notes from the MSVC++ manual: + * 1) A term_func() should call exit(), otherwise + * abort() will be called on return to the caller. + * abort() raises SIGABRT. The default signal handler + * for all signals terminates the calling program with + * exit code 3. + * 2) A term_func() must not throw an exception. Therefore + * term_func() should not call pthread_exit() if an + * an exception-using version of pthreads-win32 library + * is being used (i.e. either pthreadVCE or pthreadVSE). + */ + exit(0); +#endif +} + +void * +exceptionedThread(void * arg) +{ + int dummy = 0x1; + + (void) set_terminate(&terminateFunction); + + throw dummy; + + return (void *) 0; +} + +int +main() +{ + int i; + pthread_t mt; + pthread_t et[NUMTHREADS]; + pthread_mutexattr_t ma; + + assert((mt = pthread_self()).p != NULL); + + printf("See the notes inside of exception3.c re term_funcs.\n"); + + assert(pthread_mutexattr_init(&ma) == 0); + assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK) == 0); + assert(pthread_mutex_init(&caughtLock, &ma) == 0); + assert(pthread_mutexattr_destroy(&ma) == 0); + + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_create(&et[i], NULL, exceptionedThread, NULL) == 0); + } + + Sleep(5000); + + assert(caught == NUMTHREADS); + + /* + * Success. + */ + return 0; +} + +#else /* defined(__cplusplus) */ + +#include + +int +main() +{ + fprintf(stderr, "Test N/A for this compiler environment.\n"); + return 0; +} + +#endif /* defined(__cplusplus) */ diff --git a/liblo/pthreads.2/tests/exit1.c b/liblo/pthreads.2/tests/exit1.c new file mode 100644 index 0000000..715aedd --- /dev/null +++ b/liblo/pthreads.2/tests/exit1.c @@ -0,0 +1,50 @@ +/* + * Test for pthread_exit(). + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: None. + */ + +#include "test.h" + +int +main(int argc, char * argv[]) +{ + /* A simple test first. */ + pthread_exit((void *) 0); + + /* Not reached */ + assert(0); + return 0; +} diff --git a/liblo/pthreads.2/tests/exit2.c b/liblo/pthreads.2/tests/exit2.c new file mode 100644 index 0000000..2c81237 --- /dev/null +++ b/liblo/pthreads.2/tests/exit2.c @@ -0,0 +1,64 @@ +/* + * Test for pthread_exit(). + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: + * pthread_create() + * pthread_exit() + */ + +#include "test.h" + +void * +func(void * arg) +{ + pthread_exit(arg); + + /* Never reached. */ + assert(0); + + return NULL; +} + +int +main(int argc, char * argv[]) +{ + pthread_t t; + + assert(pthread_create(&t, NULL, func, (void *) NULL) == 0); + + Sleep(1000); + + return 0; +} diff --git a/liblo/pthreads.2/tests/exit3.c b/liblo/pthreads.2/tests/exit3.c new file mode 100644 index 0000000..ef383fd --- /dev/null +++ b/liblo/pthreads.2/tests/exit3.c @@ -0,0 +1,68 @@ +/* + * Test for pthread_exit(). + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: pthread_create(). + */ + +#include "test.h" + +void * +func(void * arg) +{ + pthread_exit(arg); + + /* Never reached. */ + assert(0); + + return NULL; +} + +int +main(int argc, char * argv[]) +{ + pthread_t id[4]; + int i; + + /* Create a few threads and then exit. */ + for (i = 0; i < 4; i++) + { + assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); + } + + Sleep(1000); + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/exit4.c b/liblo/pthreads.2/tests/exit4.c new file mode 100644 index 0000000..bb36fdb --- /dev/null +++ b/liblo/pthreads.2/tests/exit4.c @@ -0,0 +1,199 @@ +/* + * File: exit4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test calling pthread_exit from a Win32 thread + * without having created an implicit POSIX handle for it. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#ifndef _UWIN +#include +#endif + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) +unsigned __stdcall +#else +void +#endif +Win32thread(void * arg) +{ + int result = 1; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + /* + * Doesn't return and doesn't create an implicit POSIX handle. + */ + pthread_exit((void *) result); + + return 0; +} + +int +main() +{ + int failed = 0; + int i; + HANDLE h[NUMTHREADS + 1]; + unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */ + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr); +#else + h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]); +#endif + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE); +#else + /* + * Can't get a result code. + */ + result = 1; +#endif + + fail = (result != 1); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/exit5.c b/liblo/pthreads.2/tests/exit5.c new file mode 100644 index 0000000..18531fb --- /dev/null +++ b/liblo/pthreads.2/tests/exit5.c @@ -0,0 +1,205 @@ +/* + * File: exit5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Test calling pthread_exit from a Win32 thread + * having created an implicit POSIX handle for it. + * + * Test Method (Validation or Falsification): + * - Validate return value and that POSIX handle is created and destroyed. + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock + * pthread_testcancel, pthread_cancel, pthread_join + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" +#ifndef _UWIN +#include +#endif + +/* + * Create NUMTHREADS threads in addition to the Main thread. + */ +enum { + NUMTHREADS = 4 +}; + +typedef struct bag_t_ bag_t; +struct bag_t_ { + int threadnum; + int started; + /* Add more per-thread state variables here */ + int count; + pthread_t self; +}; + +static bag_t threadbag[NUMTHREADS + 1]; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) +unsigned __stdcall +#else +void +#endif +Win32thread(void * arg) +{ + int result = 1; + bag_t * bag = (bag_t *) arg; + + assert(bag == &threadbag[bag->threadnum]); + assert(bag->started == 0); + bag->started = 1; + + assert((bag->self = pthread_self()).p != NULL); + assert(pthread_kill(bag->self, 0) == 0); + + /* + * Doesn't return. + */ + pthread_exit((void *) result); + + return 0; +} + +int +main() +{ + int failed = 0; + int i; + HANDLE h[NUMTHREADS + 1]; + unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */ + + for (i = 1; i <= NUMTHREADS; i++) + { + threadbag[i].started = 0; + threadbag[i].threadnum = i; +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr); +#else + h[i] = (HANDLE) _beginthread(Win32thread, 0, (void *) &threadbag[i]); +#endif + } + + /* + * Code to control or munipulate child threads should probably go here. + */ + Sleep(500); + + /* + * Give threads time to run. + */ + Sleep(NUMTHREADS * 100); + + /* + * Standard check that all threads started. + */ + for (i = 1; i <= NUMTHREADS; i++) + { + if (!threadbag[i].started) + { + failed |= !threadbag[i].started; + fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started); + } + } + + assert(!failed); + + /* + * Check any results here. Set "failed" and only print output on failure. + */ + failed = 0; + for (i = 1; i <= NUMTHREADS; i++) + { + int fail = 0; + int result = 0; + +#if ! defined (__MINGW32__) || defined (__MSVCRT__) + assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE); +#else + /* + * Can't get a result code. + */ + result = 1; +#endif + + assert(threadbag[i].self.p != NULL && pthread_kill(threadbag[i].self, 0) == ESRCH); + + fail = (result != 1); + + if (fail) + { + fprintf(stderr, "Thread %d: started %d: count %d\n", + i, + threadbag[i].started, + threadbag[i].count); + } + failed = (failed || fail); + } + + assert(!failed); + + /* + * Success. + */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/eyal1.c b/liblo/pthreads.2/tests/eyal1.c new file mode 100644 index 0000000..d18b731 --- /dev/null +++ b/liblo/pthreads.2/tests/eyal1.c @@ -0,0 +1,367 @@ +/* Simple POSIX threads program. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Author: Eyal Lebedinsky eyal@eyal.emu.id.au + * Written: Sep 1998. + * Version Date: 12 Sep 1998 + * + * Do we need to lock stdout or is it thread safe? + * + * Used: + * pthread_t + * pthread_attr_t + * pthread_create() + * pthread_join() + * pthread_mutex_t + * PTHREAD_MUTEX_INITIALIZER + * pthread_mutex_init() [not used now] + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + * + * What this program does is establish a work queue (implemented using + * four mutexes for each thread). It then schedules work (by storing + * a number in 'todo') and releases the threads. When the work is done + * the threads will block. The program then repeats the same thing once + * more (just to test the logic) and when the work is done it destroyes + * the threads. + * + * The 'work' we do is simply burning CPU cycles in a loop. + * The 'todo' work queue is trivial - each threads pops one element + * off it by incrementing it, the poped number is the 'work' to do. + * When 'todo' reaches the limit (nwork) the queue is considered + * empty. + * + * The number displayed at the end is the amount of work each thread + * did, so we can see if the load was properly distributed. + * + * The program was written to test a threading setup (not seen here) + * rather than to demonstrate correct usage of the pthread facilities. + * + * Note how each thread is given access to a thread control structure + * (TC) which is used for communicating to/from the main program (e.g. + * the threads knows its 'id' and also filles in the 'work' done). +*/ + +#include "test.h" + +#include +#include + +struct thread_control { + int id; + pthread_t thread; /* thread id */ + pthread_mutex_t mutex_start; + pthread_mutex_t mutex_started; + pthread_mutex_t mutex_end; + pthread_mutex_t mutex_ended; + long work; /* work done */ + int stat; /* pthread_init status */ +}; + +typedef struct thread_control TC; + +static TC *tcs = NULL; +static int nthreads = 10; +static int nwork = 100; +static int quiet = 0; + +static int todo = -1; + +static pthread_mutex_t mutex_todo = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mutex_stdout = PTHREAD_MUTEX_INITIALIZER; + + +static void +die (int ret) +{ + if (NULL != tcs) + { + free (tcs); + tcs = NULL; + } + + if (ret) + exit (ret); +} + + +static double +waste_time (int n) +{ + int i; + double f, g, h, s; + + s = 0.0; + + /* + * Useless work. + */ + for (i = n*100; i > 0; --i) + { + f = rand (); + g = rand (); + h = rand (); + s += 2.0 * f * g / (h != 0.0 ? (h * h) : 1.0); + } + return s; +} + +static int +do_work_unit (int who, int n) +{ + int i; + static int nchars = 0; + double f = 0.0; + + if (quiet) + i = 0; + else { + /* + * get lock on stdout + */ + assert(pthread_mutex_lock (&mutex_stdout) == 0); + + /* + * do our job + */ + i = printf ("%c", "0123456789abcdefghijklmnopqrstuvwxyz"[who]); + + if (!(++nchars % 50)) + printf ("\n"); + + fflush (stdout); + + /* + * release lock on stdout + */ + assert(pthread_mutex_unlock (&mutex_stdout) == 0); + } + + n = rand () % 10000; /* ignore incoming 'n' */ + f = waste_time (n); + + /* This prevents the statement above from being optimised out */ + if (f > 0.0) + return(n); + + return (n); +} + +static int +print_server (void *ptr) +{ + int mywork; + int n; + TC *tc = (TC *)ptr; + + assert(pthread_mutex_lock (&tc->mutex_started) == 0); + + for (;;) + { + assert(pthread_mutex_lock (&tc->mutex_start) == 0); + assert(pthread_mutex_unlock (&tc->mutex_start) == 0); + assert(pthread_mutex_lock (&tc->mutex_ended) == 0); + assert(pthread_mutex_unlock (&tc->mutex_started) == 0); + + for (;;) + { + + /* + * get lock on todo list + */ + assert(pthread_mutex_lock (&mutex_todo) == 0); + + mywork = todo; + if (todo >= 0) + { + ++todo; + if (todo >= nwork) + todo = -1; + } + assert(pthread_mutex_unlock (&mutex_todo) == 0); + + if (mywork < 0) + break; + + assert((n = do_work_unit (tc->id, mywork)) >= 0); + tc->work += n; + } + + assert(pthread_mutex_lock (&tc->mutex_end) == 0); + assert(pthread_mutex_unlock (&tc->mutex_end) == 0); + assert(pthread_mutex_lock (&tc->mutex_started) == 0); + assert(pthread_mutex_unlock (&tc->mutex_ended) == 0); + + if (-2 == mywork) + break; + } + + assert(pthread_mutex_unlock (&tc->mutex_started) == 0); + + return (0); +} + +static void +dosync (void) +{ + int i; + + for (i = 0; i < nthreads; ++i) + { + assert(pthread_mutex_lock (&tcs[i].mutex_end) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_start) == 0); + assert(pthread_mutex_lock (&tcs[i].mutex_started) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0); + } + + /* + * Now threads do their work + */ + for (i = 0; i < nthreads; ++i) + { + assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_end) == 0); + assert(pthread_mutex_lock (&tcs[i].mutex_ended) == 0); + assert(pthread_mutex_unlock (&tcs[i].mutex_ended) == 0); + } +} + +static void +dowork (void) +{ + todo = 0; + dosync(); + + todo = 0; + dosync(); +} + +int +main (int argc, char *argv[]) +{ + int i; + + assert(NULL != (tcs = (TC *) calloc (nthreads, sizeof (*tcs)))); + + /* + * Launch threads + */ + for (i = 0; i < nthreads; ++i) + { + tcs[i].id = i; + + assert(pthread_mutex_init (&tcs[i].mutex_start, NULL) == 0); + assert(pthread_mutex_init (&tcs[i].mutex_started, NULL) == 0); + assert(pthread_mutex_init (&tcs[i].mutex_end, NULL) == 0); + assert(pthread_mutex_init (&tcs[i].mutex_ended, NULL) == 0); + + tcs[i].work = 0; + + assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0); + assert((tcs[i].stat = + pthread_create (&tcs[i].thread, + NULL, + (void *(*)(void *))print_server, + (void *) &tcs[i]) + ) == 0); + + /* + * Wait for thread initialisation + */ + { + int trylock = 0; + + while (trylock == 0) + { + trylock = pthread_mutex_trylock(&tcs[i].mutex_started); + assert(trylock == 0 || trylock == EBUSY); + + if (trylock == 0) + { + assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0); + } + } + } + } + + dowork (); + + /* + * Terminate threads + */ + todo = -2; /* please terminate */ + dosync(); + + for (i = 0; i < nthreads; ++i) + { + if (0 == tcs[i].stat) + assert(pthread_join (tcs[i].thread, NULL) == 0); + } + + /* + * destroy locks + */ + assert(pthread_mutex_destroy (&mutex_stdout) == 0); + assert(pthread_mutex_destroy (&mutex_todo) == 0); + + /* + * Cleanup + */ + printf ("\n"); + + /* + * Show results + */ + for (i = 0; i < nthreads; ++i) + { + printf ("%2d ", i); + if (0 == tcs[i].stat) + printf ("%10ld\n", tcs[i].work); + else + printf ("failed %d\n", tcs[i].stat); + + assert(pthread_mutex_unlock(&tcs[i].mutex_start) == 0); + + assert(pthread_mutex_destroy (&tcs[i].mutex_start) == 0); + assert(pthread_mutex_destroy (&tcs[i].mutex_started) == 0); + assert(pthread_mutex_destroy (&tcs[i].mutex_end) == 0); + assert(pthread_mutex_destroy (&tcs[i].mutex_ended) == 0); + } + + die (0); + + return (0); +} diff --git a/liblo/pthreads.2/tests/inherit1.c b/liblo/pthreads.2/tests/inherit1.c new file mode 100644 index 0000000..53e5533 --- /dev/null +++ b/liblo/pthreads.2/tests/inherit1.c @@ -0,0 +1,177 @@ +/* + * File: inherit1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test thread priority inheritance. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +enum { + PTW32TEST_THREAD_INIT_PRIO = 0, + PTW32TEST_MAXPRIORITIES = 512 +}; + +int minPrio; +int maxPrio; +int validPriorities[PTW32TEST_MAXPRIORITIES]; + + +void * func(void * arg) +{ + int policy; + struct sched_param param; + + assert(pthread_getschedparam(pthread_self(), &policy, ¶m) == 0); + return (void *) param.sched_priority; +} + + +void * +getValidPriorities(void * arg) +{ + int prioSet; + pthread_t thread = pthread_self(); + HANDLE threadH = pthread_getw32threadhandle_np(thread); + struct sched_param param; + + for (prioSet = minPrio; + prioSet <= maxPrio; + prioSet++) + { + /* + * If prioSet is invalid then the threads priority is unchanged + * from the previous value. Make the previous value a known + * one so that we can check later. + */ + param.sched_priority = prioSet; + assert(pthread_setschedparam(thread, SCHED_OTHER, ¶m) == 0); + validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)] = GetThreadPriority(threadH); + } + + return (void *) 0; +} + + +int +main() +{ + pthread_t t; + pthread_t mainThread = pthread_self(); + pthread_attr_t attr; + void * result = NULL; + struct sched_param param; + struct sched_param mainParam; + int prio; + int policy; + int inheritsched = -1; + pthread_t threadID = pthread_self(); + HANDLE threadH = pthread_getw32threadhandle_np(threadID); + + assert((maxPrio = sched_get_priority_max(SCHED_OTHER)) != -1); + assert((minPrio = sched_get_priority_min(SCHED_OTHER)) != -1); + + assert(pthread_create(&t, NULL, getValidPriorities, NULL) == 0); + assert(pthread_join(t, &result) == 0); + + assert(pthread_attr_init(&attr) == 0); + assert(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) == 0); + assert(pthread_attr_getinheritsched(&attr, &inheritsched) == 0); + assert(inheritsched == PTHREAD_INHERIT_SCHED); + + for (prio = minPrio; prio <= maxPrio; prio++) + { + mainParam.sched_priority = prio; + + /* Set the thread's priority to a known initial value. */ + SetThreadPriority(threadH, PTW32TEST_THREAD_INIT_PRIO); + + /* Change the main thread priority */ + assert(pthread_setschedparam(mainThread, SCHED_OTHER, &mainParam) == 0); + assert(pthread_getschedparam(mainThread, &policy, &mainParam) == 0); + assert(policy == SCHED_OTHER); + /* Priority returned below should be the level set by pthread_setschedparam(). */ + assert(mainParam.sched_priority == prio); + assert(GetThreadPriority(threadH) == + validPriorities[prio+(PTW32TEST_MAXPRIORITIES/2)]); + + for (param.sched_priority = prio; + param.sched_priority <= maxPrio; + param.sched_priority++) + { + /* The new thread create should ignore this new priority */ + assert(pthread_attr_setschedparam(&attr, ¶m) == 0); + assert(pthread_create(&t, &attr, func, NULL) == 0); + pthread_join(t, &result); + assert((int) result == mainParam.sched_priority); + } + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/join0.c b/liblo/pthreads.2/tests/join0.c new file mode 100644 index 0000000..2105869 --- /dev/null +++ b/liblo/pthreads.2/tests/join0.c @@ -0,0 +1,67 @@ +/* + * Test for pthread_join(). + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: pthread_create(), pthread_exit(). + */ + +#include "test.h" + +void * +func(void * arg) +{ + Sleep(2000); + + pthread_exit(arg); + + /* Never reached. */ + exit(1); +} + +int +main(int argc, char * argv[]) +{ + pthread_t id; + int result; + + /* Create a single thread and wait for it to exit. */ + assert(pthread_create(&id, NULL, func, (void *) 123) == 0); + + assert(pthread_join(id, (void **) &result) == 0); + + assert(result == 123); + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/join1.c b/liblo/pthreads.2/tests/join1.c new file mode 100644 index 0000000..cf50c8f --- /dev/null +++ b/liblo/pthreads.2/tests/join1.c @@ -0,0 +1,78 @@ +/* + * Test for pthread_join(). + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: pthread_create(), pthread_join(), pthread_exit(). + */ + +#include "test.h" + +void * +func(void * arg) +{ + int i = (int) arg; + + Sleep(i * 100); + + pthread_exit(arg); + + /* Never reached. */ + exit(1); +} + +int +main(int argc, char * argv[]) +{ + pthread_t id[4]; + int i; + int result; + + /* Create a few threads and then exit. */ + for (i = 0; i < 4; i++) + { + assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); + } + + /* Some threads will finish before they are joined, some after. */ + Sleep(2 * 100 + 50); + + for (i = 0; i < 4; i++) + { + assert(pthread_join(id[i], (void **) &result) == 0); + assert(result == i); + } + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/join2.c b/liblo/pthreads.2/tests/join2.c new file mode 100644 index 0000000..bcd0df1 --- /dev/null +++ b/liblo/pthreads.2/tests/join2.c @@ -0,0 +1,69 @@ +/* + * Test for pthread_join() returning return value from threads. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: pthread_create(). + */ + +#include "test.h" + +void * +func(void * arg) +{ + Sleep(1000); + return arg; +} + +int +main(int argc, char * argv[]) +{ + pthread_t id[4]; + int i; + int result; + + /* Create a few threads and then exit. */ + for (i = 0; i < 4; i++) + { + assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); + } + + for (i = 0; i < 4; i++) + { + assert(pthread_join(id[i], (void **) &result) == 0); + assert(result == i); + } + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/join3.c b/liblo/pthreads.2/tests/join3.c new file mode 100644 index 0000000..a7608db --- /dev/null +++ b/liblo/pthreads.2/tests/join3.c @@ -0,0 +1,75 @@ +/* + * Test for pthread_join() returning return value from threads. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Depends on API functions: pthread_create(). + */ + +#include "test.h" + +void * +func(void * arg) +{ + sched_yield(); + return arg; +} + +int +main(int argc, char * argv[]) +{ + pthread_t id[4]; + int i; + int result; + + /* Create a few threads and then exit. */ + for (i = 0; i < 4; i++) + { + assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); + } + + /* + * Let threads exit before we join them. + * We should still retrieve the exit code for the threads. + */ + Sleep(1000); + + for (i = 0; i < 4; i++) + { + assert(pthread_join(id[i], (void **) &result) == 0); + assert(result == i); + } + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/kill1.c b/liblo/pthreads.2/tests/kill1.c new file mode 100644 index 0000000..a1e1a83 --- /dev/null +++ b/liblo/pthreads.2/tests/kill1.c @@ -0,0 +1,83 @@ +/* + * File: kill1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - pthread_kill() does not support non zero signals.. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + + +int +main() +{ + assert(pthread_kill(pthread_self(), 1) == EINVAL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/loadfree.c b/liblo/pthreads.2/tests/loadfree.c new file mode 100644 index 0000000..f7f3b72 --- /dev/null +++ b/liblo/pthreads.2/tests/loadfree.c @@ -0,0 +1,70 @@ +/* + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * From: Todd Owen + * To: pthreads-win32@sourceware.cygnus.com + * Subject: invalid page fault when using LoadLibrary/FreeLibrary + * + * hi, + * for me, pthread.dll consistently causes an "invalid page fault in + * kernel32.dll" when I load it "explicitly"...to be precise, loading (with + * LoadLibrary) isn't a problem, it gives the error when I call FreeLibrary. + * I guess that the dll's cleanup must be causing the error. + * + * Implicit linkage of the dll has never given me this problem. Here's a + * program (console application) that gives me the error. + * + * I compile with: mingw32 (gcc-2.95 release), with the MSVCRT add-on (not + * that the compiler should make much difference in this case). + * PTHREAD.DLL: is the precompiled 1999-11-02 one (I tried an older one as + * well, with the same result). + * + * Fascinatingly, if you have your own dll (mycode.dll) which implicitly + * loads pthread.dll, and then do LoadLibrary/FreeLibrary on _this_ dll, the + * same thing happens. + * + */ + +#include "test.h" + +int main() { + HINSTANCE hinst; + + assert((hinst = LoadLibrary("pthread")) != (HINSTANCE) 0); + + Sleep(100); + + FreeLibrary(hinst); + return 0; +} + diff --git a/liblo/pthreads.2/tests/multiPCcaBetter.c b/liblo/pthreads.2/tests/multiPCcaBetter.c new file mode 100644 index 0000000..fe130e3 --- /dev/null +++ b/liblo/pthreads.2/tests/multiPCcaBetter.c @@ -0,0 +1,282 @@ +/* Session 7. multiPCca.c Lab 7-1 */ +/* Maintain a producer thread and several consumer threads */ +/* The producer periodically creates checksummed data buffers, */ +/* or "message block" which the consumers display as soon */ +/* as possible. The conusmers read the NEXT complete */ +/* set of data, and each consumer validates the data before */ +/* before display. */ +/* Consumers are created and cancelled on demand based */ +/* user input. */ +/* Usage: multiPCca maxconsumer */ + +#if defined (_MSC_VER) +#include +#define sleep(i) Sleep(i*1000) +#endif +#include +//#include "errors.h" +//#include "utility.h" +#include +#include +#define DATA_SIZE 256 + +typedef struct msg_block_tag { /* Message block */ + pthread_mutex_t mguard; /* Guard the message block */ + pthread_cond_t mready; /* Message ready */ + pthread_cond_t mok; /* Ok for the producer to produce */ + volatile int f_ready; + volatile int f_stop; + /* ready state flag; producer stopped flag */ + volatile int sequence; /* Message block sequence number */ + time_t timestamp; + int checksum; /* Message contents checksum */ + int data[DATA_SIZE]; /* Message Contents */ + +} msg_block_t; + +/* The invariant and condition variable predicates are: */ +/* Invariant - */ +/* f_ready && data is valid */ +/* && checksum and timestamp are valid */ +/* Condition variable predicate */ +/* mready if and only if f_ready and a new message */ +/* has just been generated */ + + +/* Single message block, ready to fill with a new message */ +struct msg_block_tag mblock = { PTHREAD_MUTEX_INITIALIZER, + PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0, 0 }; + +void * produce (void *), * consume (void *); +void message_fill (msg_block_t *); +void message_display (int, msg_block_t *); +static volatile int ShutDown = 0; + +int main (int argc, char * argv[]) +{ + int tstatus, nthread, ithread; + int * f_consumer; /* Array of flags to indicate corresponding thread exists */ + void *join_result; + pthread_t *consume_t; + char command [10]; + + if (argc != 2) { + printf ("Usage: multiPCca maxconsumer\n"); + return 1; + } + + nthread = atoi(argv[1]); + consume_t = calloc (nthread, sizeof(pthread_t)); + f_consumer = (int *)calloc (nthread, sizeof(int)); + + while (!ShutDown) { + printf ("Enter command: nc (new consumer), cc (cancel), "); + printf ("pr (produce msg), sh (shutdown):"); + fflush (stdout); + scanf ("%s", command); + printf ("Command received: %s.\n", command); fflush (stdout); + if (strcmp (command, "nc") == 0) { /* New consumer thread */ + /* Look for empty thread slot */ + for (ithread = 0; ithread < nthread; ithread++) { + if (!f_consumer[ithread]) break; + } + if (ithread >= nthread) { + printf ("Maximum # consumers (%d) already exist\n", nthread); + fflush (stdout); + continue; + } + + tstatus = pthread_create (&consume_t[ithread], NULL, + consume, (void *)ithread); +// if (tstatus != 0) +// err_abort (tstatus, "Cannot create consumer thread"); + f_consumer[ithread] = 1; + printf ("Consumer number %d created successfully.\n", ithread); + fflush (stdout); + + } else if (strcmp (command, "cc") == 0) { /* cancel consumer thread */ + printf ("Enter consumer number: 0 to %d:", nthread-1); + fflush (stdout); + scanf ("%d", &ithread); + if (ithread < 0 || ithread >= nthread || !f_consumer[ithread]) { + printf ("Thread %d does not exist.\n", ithread); fflush (stdout); + fflush (stdout); + } else { + printf ("About to cancel thread # %d.\n", ithread); fflush (stdout); + tstatus = pthread_cancel (consume_t[ithread]); + printf ("Cancel status: %d. About to join thread # %d\n", tstatus, ithread); fflush (stdout); + tstatus = pthread_join (consume_t[ithread], &join_result); + printf ("Join status: %d after joining thread # %d. Result: %d\n", tstatus, ithread, (int) join_result); fflush (stdout); + f_consumer[ithread] = 0; + } + continue; + + } else if (strcmp (command, "pr") == 0) { /* Produce a message */ + printf ("About to produce a new message.\n"); fflush (stdout); + produce(NULL); + /* Note the race to prompt before/after message display */ + } else if (strcmp (command, "sh") == 0) { /* shutdown system */ + printf ("Shutdown command received\n"); + for (ithread = 0; ithread < nthread; ithread++) + printf ("Thread #: %d. Flag: %d.\n", ithread, f_consumer[ithread]); + + fflush (stdout); + ShutDown = 1; /* Cancel and join all running threads */ + for (ithread = 0; ithread < nthread; ithread++) { + printf ("Thread #: %d. Flag: %d.\n", ithread, f_consumer[ithread]); + fflush (stdout); + if (f_consumer[ithread]) { + printf ("About to cancel consumer thread #: %d.\n", ithread); + fflush (stdout); + tstatus = pthread_cancel (consume_t[ithread]); + if (tstatus != 0) + printf ("Cannot cancel consumer thread %d", ithread); + printf ("About to join consumer thread #: %d.\n", ithread); + fflush (stdout); + tstatus = pthread_join (consume_t[ithread], &join_result); + if (tstatus != 0 || join_result != PTHREAD_CANCELED) + printf ("Error joining thread #: %d. tstatus: %d.\n", + ithread, tstatus); + printf ("Joined consumer thread #: %d.\n", ithread); + fflush (stdout); + + } + } + fflush (stdout); + printf ("All consumer threads cancelled and joined.\n"); + fflush (stdout); + + } else { /* Illegal command */ + printf ("Illegal command. %s. Try again\n", command); + fflush (stdout); + } + } + + free (consume_t); + printf ("Producer and consumer threads have terminated\n"); + fflush (stdout); + return 0; +} + + +void * produce (void *arg) +/* Producer function. Create new message when called, and notify consumers */ +/* The arg is there as this was derived from a thread function. */ +{ + int tstatus = 1; + /* Get the buffer, fill it,*/ + /* and inform all consumers with a broadcast */ + printf ("Entering producer.\n"); fflush (stdout); + while (tstatus != 0) { + tstatus = pthread_mutex_trylock (&mblock.mguard); + printf ("Trylock status: %d\n", tstatus); fflush (stdout); + if (tstatus != 0) sleep (1); + } + message_fill (&mblock); + mblock.sequence++; + mblock.f_ready = 1; + pthread_cond_broadcast (&mblock.mready); + printf ("Producer produced one message.\n"); fflush (stdout); + pthread_mutex_unlock (&mblock.mguard); + return NULL; +} + +/* Mutex cleanup handler used by the consumers */ +void free_mutex (void * arg) +{ + int tstatus; + printf ("Entering free_mutex cleanup handler.\n"); + tstatus = pthread_mutex_unlock ((pthread_mutex_t *)arg); + printf ("Unlocked mutex. Status: %d\n", tstatus); fflush (stdout); +} + +/* Cleanup handler for the consumer thread */ +void cancel_consumer (void * arg) +{ + int ithread; + + ithread = (int) arg; + printf ("Thread number %d cancellation handler. Curently, does nothing.\n", ithread); + fflush (stdout); +} + +void *consume (void *arg) +{ + int ithread, old_state, old_type; + struct timespec timeout; + timeout.tv_nsec = 0; + + ithread = (int)arg; + + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old_state); + pthread_cleanup_push (cancel_consumer, (void *)ithread); + pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old_type); + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old_state); + + /* Consume the NEXT message */ + do { + pthread_testcancel(); + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old_state); + pthread_mutex_lock (&mblock.mguard); + pthread_cleanup_push (free_mutex, &mblock.mguard); + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old_state); + if (!mblock.f_stop) { + do { /* Wait for the NEXT message */ + pthread_testcancel(); + printf ("Thread #: %d about to wait for mready.\n", ithread); fflush (stdout); + pthread_cond_wait (&mblock.mready, &mblock.mguard); + printf ("Thread #: %d after wait for mready.\n", ithread); fflush (stdout); + } while (!mblock.f_ready && !ShutDown); + message_display (ithread, &mblock); + pthread_testcancel(); + } + /* Free the mutex through the free_mutex cleanup handler (a macro) */ + pthread_cleanup_pop (1); + } while (!ShutDown); + pthread_cleanup_pop(1); /* NOTE: Try removing this!! Compiler error! + Why?? Because it's a macro */ + printf ("Consumer number %d is shutting down\n", ithread); + fflush (stdout); + return NULL; +} + +void message_fill (msg_block_t *mblock) +{ + /* Fill the message buffer, and include checksum and timestamp */ + /* This function is called from the producer thread while it */ + /* owns the message block mutex */ + + int i; + + mblock->checksum = 0; + for (i = 0; i < DATA_SIZE; i++) { + mblock->data[i] = rand(); + mblock->checksum ^= mblock->data[i]; + } + mblock->timestamp = time(NULL); + return; +} + +void message_display (int ithread, msg_block_t *mblock) +{ + /* Display message buffer and timestamp, validate checksum */ + /* This function is called from the consumer thread while it */ + /* owns the message block mutex */ + int i, tcheck = 0; + + for (i = 0; i < DATA_SIZE; i++) + tcheck ^= mblock->data[i]; + printf ("\nConsumer thread #: %d\n", ithread); + printf ("Message number %d generated at: %s", + mblock->sequence, ctime (&(mblock->timestamp))); + printf ("First and last entries: %x %x\n", + mblock->data[0], mblock->data[DATA_SIZE-1]); + fflush (stdout); + if (tcheck == mblock->checksum) + printf ("GOOD ->Checksum was validated.\n"); + else + printf ("BAD ->Checksum failed. message was corrupted\n"); + fflush (stdout); + return; + +} diff --git a/liblo/pthreads.2/tests/mutex1.c b/liblo/pthreads.2/tests/mutex1.c new file mode 100644 index 0000000..3ed2c44 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex1.c @@ -0,0 +1,68 @@ +/* + * mutex1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create a simple mutex object, lock it, and then unlock it again. + * This is the simplest test of the pthread mutex family that we can do. + * + * Depends on API functions: + * pthread_mutex_init() + * pthread_mutex_lock() + * pthread_mutex_unlock() + * pthread_mutex_destroy() + */ + +#include "test.h" + +pthread_mutex_t mutex = NULL; + +int +main() +{ + assert(mutex == NULL); + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + assert(mutex != NULL); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_mutex_destroy(&mutex) == 0); + + assert(mutex == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex1e.c b/liblo/pthreads.2/tests/mutex1e.c new file mode 100644 index 0000000..0f88be7 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex1e.c @@ -0,0 +1,74 @@ +/* + * mutex1e.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * As for mutex1.c but with type set to PTHREAD_MUTEX_ERRORCHECK. + * + * Create a simple mutex object, lock it, unlock it, then destroy it. + * This is the simplest test of the pthread mutex family that we can do. + * + * Depends on API functions: + * pthread_mutexattr_settype() + * pthread_mutex_init() + * pthread_mutex_destroy() + */ + +#include "test.h" + +pthread_mutex_t mutex = NULL; +pthread_mutexattr_t mxAttr; + +int +main() +{ + assert(pthread_mutexattr_init(&mxAttr) == 0); + + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0); + + assert(mutex == NULL); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(mutex != NULL); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_mutex_destroy(&mutex) == 0); + + assert(mutex == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex1n.c b/liblo/pthreads.2/tests/mutex1n.c new file mode 100644 index 0000000..26abbb5 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex1n.c @@ -0,0 +1,74 @@ +/* + * mutex1n.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * As for mutex1.c but with type set to PTHREAD_MUTEX_NORMAL. + * + * Create a simple mutex object, lock it, unlock it, then destroy it. + * This is the simplest test of the pthread mutex family that we can do. + * + * Depends on API functions: + * pthread_mutexattr_settype() + * pthread_mutex_init() + * pthread_mutex_destroy() + */ + +#include "test.h" + +pthread_mutex_t mutex = NULL; +pthread_mutexattr_t mxAttr; + +int +main() +{ + assert(pthread_mutexattr_init(&mxAttr) == 0); + + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0); + + assert(mutex == NULL); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(mutex != NULL); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_mutex_destroy(&mutex) == 0); + + assert(mutex == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex1r.c b/liblo/pthreads.2/tests/mutex1r.c new file mode 100644 index 0000000..53e829f --- /dev/null +++ b/liblo/pthreads.2/tests/mutex1r.c @@ -0,0 +1,74 @@ +/* + * mutex1r.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * As for mutex1.c but with type set to PTHREAD_MUTEX_RECURSIVE. + * + * Create a simple mutex object, lock it, unlock it, then destroy it. + * This is the simplest test of the pthread mutex family that we can do. + * + * Depends on API functions: + * pthread_mutexattr_settype() + * pthread_mutex_init() + * pthread_mutex_destroy() + */ + +#include "test.h" + +pthread_mutex_t mutex = NULL; +pthread_mutexattr_t mxAttr; + +int +main() +{ + assert(pthread_mutexattr_init(&mxAttr) == 0); + + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0); + + assert(mutex == NULL); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(mutex != NULL); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_mutex_destroy(&mutex) == 0); + + assert(mutex == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex2.c b/liblo/pthreads.2/tests/mutex2.c new file mode 100644 index 0000000..68dda97 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex2.c @@ -0,0 +1,66 @@ +/* + * mutex2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static mutex object, lock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +int +main() +{ + assert(mutex == PTHREAD_MUTEX_INITIALIZER); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(mutex != PTHREAD_MUTEX_INITIALIZER); + + assert(mutex != NULL); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_mutex_destroy(&mutex) == 0); + + assert(mutex == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex2e.c b/liblo/pthreads.2/tests/mutex2e.c new file mode 100644 index 0000000..ef7389e --- /dev/null +++ b/liblo/pthreads.2/tests/mutex2e.c @@ -0,0 +1,66 @@ +/* + * mutex2e.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static mutex object, lock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER; + +int +main() +{ + assert(mutex == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(mutex != PTHREAD_ERRORCHECK_MUTEX_INITIALIZER); + + assert(mutex != NULL); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_mutex_destroy(&mutex) == 0); + + assert(mutex == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex2r.c b/liblo/pthreads.2/tests/mutex2r.c new file mode 100644 index 0000000..126166a --- /dev/null +++ b/liblo/pthreads.2/tests/mutex2r.c @@ -0,0 +1,66 @@ +/* + * mutex2r.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static mutex object, lock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; + +int +main() +{ + assert(mutex == PTHREAD_RECURSIVE_MUTEX_INITIALIZER); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(mutex != PTHREAD_RECURSIVE_MUTEX_INITIALIZER); + + assert(mutex != NULL); + + assert(pthread_mutex_unlock(&mutex) == 0); + + assert(pthread_mutex_destroy(&mutex) == 0); + + assert(mutex == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex3.c b/liblo/pthreads.2/tests/mutex3.c new file mode 100644 index 0000000..98b3038 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex3.c @@ -0,0 +1,75 @@ +/* + * mutex3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static mutex object, lock it, trylock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_mutex_trylock(&mutex1) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_mutex_lock(&mutex1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + assert(pthread_join(t, NULL) == 0); + + assert(pthread_mutex_unlock(&mutex1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex3e.c b/liblo/pthreads.2/tests/mutex3e.c new file mode 100644 index 0000000..20271ec --- /dev/null +++ b/liblo/pthreads.2/tests/mutex3e.c @@ -0,0 +1,75 @@ +/* + * mutex3e.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static mutex object, lock it, trylock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +pthread_mutex_t mutex1 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_mutex_trylock(&mutex1) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_mutex_lock(&mutex1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + assert(pthread_join(t, NULL) == 0); + + assert(pthread_mutex_unlock(&mutex1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex3r.c b/liblo/pthreads.2/tests/mutex3r.c new file mode 100644 index 0000000..eeafb3e --- /dev/null +++ b/liblo/pthreads.2/tests/mutex3r.c @@ -0,0 +1,75 @@ +/* + * mutex3r.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static mutex object, lock it, trylock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +pthread_mutex_t mutex1 = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_mutex_trylock(&mutex1) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_mutex_lock(&mutex1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + assert(pthread_join(t, NULL) == 0); + + assert(pthread_mutex_unlock(&mutex1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex4.c b/liblo/pthreads.2/tests/mutex4.c new file mode 100644 index 0000000..83b0a28 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex4.c @@ -0,0 +1,111 @@ +/* + * mutex4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Thread A locks mutex - thread B tries to unlock. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int wasHere = 0; + +static pthread_mutex_t mutex1; + +void * unlocker(void * arg) +{ + int expectedResult = (int) arg; + + wasHere++; + assert(pthread_mutex_unlock(&mutex1) == expectedResult); + wasHere++; + return NULL; +} + +int +main() +{ + pthread_t t; + pthread_mutexattr_t ma; + + assert(pthread_mutexattr_init(&ma) == 0); + + wasHere = 0; + assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_DEFAULT) == 0); + assert(pthread_mutex_init(&mutex1, &ma) == 0); + assert(pthread_mutex_lock(&mutex1) == 0); + /* + * NORMAL (fast) mutexes don't check ownership. + */ + assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0); + assert(pthread_join(t, NULL) == 0); + assert(pthread_mutex_unlock(&mutex1) == EPERM); + assert(wasHere == 2); + + wasHere = 0; + assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_NORMAL) == 0); + assert(pthread_mutex_init(&mutex1, &ma) == 0); + assert(pthread_mutex_lock(&mutex1) == 0); + /* + * NORMAL (fast) mutexes don't check ownership. + */ + assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0); + assert(pthread_join(t, NULL) == 0); + assert(pthread_mutex_unlock(&mutex1) == EPERM); + assert(wasHere == 2); + + wasHere = 0; + assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK) == 0); + assert(pthread_mutex_init(&mutex1, &ma) == 0); + assert(pthread_mutex_lock(&mutex1) == 0); + assert(pthread_create(&t, NULL, unlocker, (void *) EPERM) == 0); + assert(pthread_join(t, NULL) == 0); + assert(pthread_mutex_unlock(&mutex1) == 0); + assert(wasHere == 2); + + wasHere = 0; + assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE) == 0); + assert(pthread_mutex_init(&mutex1, &ma) == 0); + assert(pthread_mutex_lock(&mutex1) == 0); + assert(pthread_create(&t, NULL, unlocker, (void *) EPERM) == 0); + assert(pthread_join(t, NULL) == 0); + assert(pthread_mutex_unlock(&mutex1) == 0); + assert(wasHere == 2); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex5.c b/liblo/pthreads.2/tests/mutex5.c new file mode 100644 index 0000000..4df9356 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex5.c @@ -0,0 +1,67 @@ +/* + * mutex5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Confirm the equality/inequality of the various mutex types, + * and the default not-set value. + */ + +#include "test.h" + +static pthread_mutexattr_t mxAttr; + +/* Prevent optimiser from removing dead or obvious asserts. */ +int _optimiseFoil; +#define FOIL(x) (_optimiseFoil = x) + +int +main() +{ + int mxType = -1; + + assert(FOIL(PTHREAD_MUTEX_DEFAULT) == PTHREAD_MUTEX_NORMAL); + assert(FOIL(PTHREAD_MUTEX_DEFAULT) != PTHREAD_MUTEX_ERRORCHECK); + assert(FOIL(PTHREAD_MUTEX_DEFAULT) != PTHREAD_MUTEX_RECURSIVE); + assert(FOIL(PTHREAD_MUTEX_RECURSIVE) != PTHREAD_MUTEX_ERRORCHECK); + + assert(FOIL(PTHREAD_MUTEX_NORMAL) == PTHREAD_MUTEX_FAST_NP); + assert(FOIL(PTHREAD_MUTEX_RECURSIVE) == PTHREAD_MUTEX_RECURSIVE_NP); + assert(FOIL(PTHREAD_MUTEX_ERRORCHECK) == PTHREAD_MUTEX_ERRORCHECK_NP); + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_NORMAL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex6.c b/liblo/pthreads.2/tests/mutex6.c new file mode 100644 index 0000000..2452c4a --- /dev/null +++ b/liblo/pthreads.2/tests/mutex6.c @@ -0,0 +1,93 @@ +/* + * mutex6.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test the default (type not set) mutex type. + * Should be the same as PTHREAD_MUTEX_NORMAL. + * Thread locks mutex twice (recursive lock). + * Locking thread should deadlock on second attempt. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + + /* Should wait here (deadlocked) */ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(1000); + + assert(lockCount == 1); + + /* + * Should succeed even though we don't own the lock + * because FAST mutexes don't check ownership. + */ + assert(pthread_mutex_unlock(&mutex) == 0); + + Sleep (1000); + + assert(lockCount == 2); + + exit(0); + + /* Never reached */ + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex6e.c b/liblo/pthreads.2/tests/mutex6e.c new file mode 100644 index 0000000..974810f --- /dev/null +++ b/liblo/pthreads.2/tests/mutex6e.c @@ -0,0 +1,102 @@ +/* + * mutex6e.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_ERRORCHECK mutex type. + * Thread locks mutex twice (recursive lock). + * This should fail with an EDEADLK error. + * The second unlock attempt should fail with an EPERM error. + * + * Depends on API functions: + * pthread_create() + * pthread_join() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_lock(&mutex) == EDEADLK); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == EPERM); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int result = 0; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_ERRORCHECK); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result == 555); + + assert(lockCount == 2); + + assert(pthread_mutex_destroy(&mutex) == 0); + assert(pthread_mutexattr_destroy(&mxAttr) == 0); + + exit(0); + + /* Never reached */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/mutex6es.c b/liblo/pthreads.2/tests/mutex6es.c new file mode 100644 index 0000000..7bd6575 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex6es.c @@ -0,0 +1,94 @@ +/* + * mutex6es.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_ERRORCHECK static mutex type. + * Thread locks mutex twice (recursive lock). + * This should fail with an EDEADLK error. + * The second unlock attempt should fail with an EPERM error. + * + * Depends on API functions: + * pthread_create() + * pthread_join() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_lock(&mutex) == EDEADLK); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == EPERM); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int result = 0; + + assert(mutex == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result == 555); + + assert(lockCount == 2); + + assert(pthread_mutex_destroy(&mutex) == 0); + + exit(0); + + /* Never reached */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/mutex6n.c b/liblo/pthreads.2/tests/mutex6n.c new file mode 100644 index 0000000..6654ca8 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex6n.c @@ -0,0 +1,104 @@ +/* + * mutex6n.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_NORMAL mutex type. + * Thread locks mutex twice (recursive lock). + * The thread should deadlock. + * + * Depends on API functions: + * pthread_create() + * pthread_mutexattr_init() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + + /* Should wait here (deadlocked) */ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_NORMAL); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(1000); + + assert(lockCount == 1); + + /* + * Should succeed even though we don't own the lock + * because FAST mutexes don't check ownership. + */ + assert(pthread_mutex_unlock(&mutex) == 0); + + Sleep (1000); + + assert(lockCount == 2); + + exit(0); + + /* Never reached */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/mutex6r.c b/liblo/pthreads.2/tests/mutex6r.c new file mode 100644 index 0000000..4051e0f --- /dev/null +++ b/liblo/pthreads.2/tests/mutex6r.c @@ -0,0 +1,100 @@ +/* + * mutex6r.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_RECURSIVE mutex type. + * Thread locks mutex twice (recursive lock). + * Both locks and unlocks should succeed. + * + * Depends on API functions: + * pthread_create() + * pthread_join() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == 0); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int result = 0; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_RECURSIVE); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result == 555); + + assert(lockCount == 2); + + assert(pthread_mutex_destroy(&mutex) == 0); + assert(pthread_mutexattr_destroy(&mxAttr) == 0); + + exit(0); + + /* Never reached */ + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex6rs.c b/liblo/pthreads.2/tests/mutex6rs.c new file mode 100644 index 0000000..fa2763b --- /dev/null +++ b/liblo/pthreads.2/tests/mutex6rs.c @@ -0,0 +1,92 @@ +/* + * mutex6rs.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_RECURSIVE static mutex type. + * Thread locks mutex twice (recursive lock). + * Both locks and unlocks should succeed. + * + * Depends on API functions: + * pthread_create() + * pthread_join() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == 0); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int result = 0; + + assert(mutex == PTHREAD_RECURSIVE_MUTEX_INITIALIZER); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result == 555); + + assert(lockCount == 2); + + assert(pthread_mutex_destroy(&mutex) == 0); + + exit(0); + + /* Never reached */ + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex6s.c b/liblo/pthreads.2/tests/mutex6s.c new file mode 100644 index 0000000..31f2b5d --- /dev/null +++ b/liblo/pthreads.2/tests/mutex6s.c @@ -0,0 +1,93 @@ +/* + * mutex6s.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test the default (type not set) static mutex type. + * Should be the same as PTHREAD_MUTEX_NORMAL. + * Thread locks mutex twice (recursive lock). + * Locking thread should deadlock on second attempt. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + + /* Should wait here (deadlocked) */ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(mutex == PTHREAD_MUTEX_INITIALIZER); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(1000); + + assert(lockCount == 1); + + /* + * Should succeed even though we don't own the lock + * because FAST mutexes don't check ownership. + */ + assert(pthread_mutex_unlock(&mutex) == 0); + + Sleep (1000); + + assert(lockCount == 2); + + exit(0); + + /* Never reached */ + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex7.c b/liblo/pthreads.2/tests/mutex7.c new file mode 100644 index 0000000..79b4689 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex7.c @@ -0,0 +1,82 @@ +/* + * mutex7.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test the default (type not set) mutex type. + * Should be the same as PTHREAD_MUTEX_NORMAL. + * Thread locks then trylocks mutex (attempted recursive lock). + * The thread should lock first time and EBUSY second time. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_trylock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_trylock(&mutex) == EBUSY); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == EPERM); + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(1000); + + assert(lockCount == 2); + + exit(0); + + /* Never reached */ + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex7e.c b/liblo/pthreads.2/tests/mutex7e.c new file mode 100644 index 0000000..ab6b69a --- /dev/null +++ b/liblo/pthreads.2/tests/mutex7e.c @@ -0,0 +1,102 @@ +/* + * mutex7e.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_ERRORCHECK mutex type. + * Thread locks and then trylocks mutex (attempted recursive lock). + * Trylock should fail with an EBUSY error. + * The second unlock attempt should fail with an EPERM error. + * + * Depends on API functions: + * pthread_create() + * pthread_join() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_trylock(&mutex) == EBUSY); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == EPERM); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int result = 0; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_ERRORCHECK); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result == 555); + + assert(lockCount == 2); + + assert(pthread_mutex_destroy(&mutex) == 0); + assert(pthread_mutexattr_destroy(&mxAttr) == 0); + + exit(0); + + /* Never reached */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/mutex7n.c b/liblo/pthreads.2/tests/mutex7n.c new file mode 100644 index 0000000..08f24f7 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex7n.c @@ -0,0 +1,93 @@ +/* + * mutex7n.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_NORMAL mutex type. + * Thread locks then trylocks mutex (attempted recursive lock). + * The thread should lock first time and EBUSY second time. + * + * Depends on API functions: + * pthread_create() + * pthread_mutexattr_init() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_trylock(&mutex) == EBUSY); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == EPERM); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_NORMAL); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(1000); + + assert(lockCount == 2); + + exit(0); + + /* Never reached */ + return 0; +} + diff --git a/liblo/pthreads.2/tests/mutex7r.c b/liblo/pthreads.2/tests/mutex7r.c new file mode 100644 index 0000000..a1c394a --- /dev/null +++ b/liblo/pthreads.2/tests/mutex7r.c @@ -0,0 +1,100 @@ +/* + * mutex7r.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_RECURSIVE mutex type. + * Thread locks mutex then trylocks mutex (recursive lock twice). + * Both locks and unlocks should succeed. + * + * Depends on API functions: + * pthread_create() + * pthread_join() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_unlock() + */ + +#include "test.h" + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + assert(pthread_mutex_lock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_trylock(&mutex) == 0); + lockCount++; + assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_unlock(&mutex) == 0); + + return (void *) 555; +} + +int +main() +{ + pthread_t t; + int result = 0; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_RECURSIVE); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result == 555); + + assert(lockCount == 2); + + assert(pthread_mutex_destroy(&mutex) == 0); + assert(pthread_mutexattr_destroy(&mxAttr) == 0); + + exit(0); + + /* Never reached */ + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex8.c b/liblo/pthreads.2/tests/mutex8.c new file mode 100644 index 0000000..ed7bcf5 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex8.c @@ -0,0 +1,82 @@ +/* + * mutex8.c + * + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 Ben Elliston and Ross Johnson + * Copyright (C) 1999,2000,2001 Ross Johnson + * + * Contact Email: rpj@ise.canberra.edu.au + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * + * Test the default (type not set) mutex type exercising timedlock. + * Thread locks mutex, another thread timedlocks the mutex. + * Timed thread should timeout. + * + * Depends on API functions: + * pthread_mutex_lock() + * pthread_mutex_timedlock() + * pthread_mutex_unlock() + */ + +#include "test.h" +#include + +static int lockCount = 0; + +static pthread_mutex_t mutex; + +void * locker(void * arg) +{ + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT); + + lockCount++; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_mutex_init(&mutex, NULL) == 0); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(2000); + + assert(lockCount == 1); + + assert(pthread_mutex_unlock(&mutex) == 0); + + return 0; +} diff --git a/liblo/pthreads.2/tests/mutex8e.c b/liblo/pthreads.2/tests/mutex8e.c new file mode 100644 index 0000000..af6e7f7 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex8e.c @@ -0,0 +1,97 @@ +/* + * mutex8e.c + * + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 Ben Elliston and Ross Johnson + * Copyright (C) 1999,2000,2001 Ross Johnson + * + * Contact Email: rpj@ise.canberra.edu.au + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_ERRORCHECK mutex type exercising timedlock. + * Thread locks mutex, another thread timedlocks the mutex. + * Timed thread should timeout. + * + * Depends on API functions: + * pthread_create() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_timedlock() + * pthread_mutex_unlock() + */ + +#include "test.h" +#include + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT); + + lockCount++; + + return 0; +} + +int +main() +{ + pthread_t t; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_ERRORCHECK); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(2000); + + assert(lockCount == 1); + + assert(pthread_mutex_unlock(&mutex) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/mutex8n.c b/liblo/pthreads.2/tests/mutex8n.c new file mode 100644 index 0000000..a4c14ae --- /dev/null +++ b/liblo/pthreads.2/tests/mutex8n.c @@ -0,0 +1,97 @@ +/* + * mutex8n.c + * + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 Ben Elliston and Ross Johnson + * Copyright (C) 1999,2000,2001 Ross Johnson + * + * Contact Email: rpj@ise.canberra.edu.au + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_NORMAL mutex type exercising timedlock. + * Thread locks mutex, another thread timedlocks the mutex. + * Timed thread should timeout. + * + * Depends on API functions: + * pthread_create() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_timedlock() + * pthread_mutex_unlock() + */ + +#include "test.h" +#include + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT); + + lockCount++; + + return 0; +} + +int +main() +{ + pthread_t t; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_NORMAL); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(2000); + + assert(lockCount == 1); + + assert(pthread_mutex_unlock(&mutex) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/mutex8r.c b/liblo/pthreads.2/tests/mutex8r.c new file mode 100644 index 0000000..7763109 --- /dev/null +++ b/liblo/pthreads.2/tests/mutex8r.c @@ -0,0 +1,97 @@ +/* + * mutex8r.c + * + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 Ben Elliston and Ross Johnson + * Copyright (C) 1999,2000,2001 Ross Johnson + * + * Contact Email: rpj@ise.canberra.edu.au + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * + * Tests PTHREAD_MUTEX_RECURSIVE mutex type exercising timedlock. + * Thread locks mutex, another thread timedlocks the mutex. + * Timed thread should timeout. + * + * Depends on API functions: + * pthread_create() + * pthread_mutexattr_init() + * pthread_mutexattr_destroy() + * pthread_mutexattr_settype() + * pthread_mutexattr_gettype() + * pthread_mutex_init() + * pthread_mutex_destroy() + * pthread_mutex_lock() + * pthread_mutex_timedlock() + * pthread_mutex_unlock() + */ + +#include "test.h" +#include + +static int lockCount = 0; + +static pthread_mutex_t mutex; +static pthread_mutexattr_t mxAttr; + +void * locker(void * arg) +{ + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_mutex_timedlock(&mutex, &abstime) == ETIMEDOUT); + + lockCount++; + + return 0; +} + +int +main() +{ + pthread_t t; + int mxType = -1; + + assert(pthread_mutexattr_init(&mxAttr) == 0); + assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0); + assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); + assert(mxType == PTHREAD_MUTEX_RECURSIVE); + + assert(pthread_mutex_init(&mutex, &mxAttr) == 0); + + assert(pthread_mutex_lock(&mutex) == 0); + + assert(pthread_create(&t, NULL, locker, NULL) == 0); + + Sleep(2000); + + assert(lockCount == 1); + + assert(pthread_mutex_unlock(&mutex) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/once1.c b/liblo/pthreads.2/tests/once1.c new file mode 100644 index 0000000..ac58e63 --- /dev/null +++ b/liblo/pthreads.2/tests/once1.c @@ -0,0 +1,77 @@ +/* + * once1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create a static pthread_once and test that it calls myfunc once. + * + * Depends on API functions: + * pthread_once() + * pthread_create() + */ + +#include "test.h" + +pthread_once_t once = PTHREAD_ONCE_INIT; + +static int washere = 0; + +void +myfunc(void) +{ + washere++; +} + +void * +mythread(void * arg) +{ + assert(pthread_once(&once, myfunc) == 0); + + return 0; +} + +int +main() +{ + pthread_t t1, t2; + + assert(pthread_create(&t1, NULL, mythread, NULL) == 0); + + assert(pthread_create(&t2, NULL, mythread, NULL) == 0); + + Sleep(2000); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/once2.c b/liblo/pthreads.2/tests/once2.c new file mode 100644 index 0000000..175dd4d --- /dev/null +++ b/liblo/pthreads.2/tests/once2.c @@ -0,0 +1,109 @@ +/* + * once2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create several static pthread_once objects and channel several threads + * through each. + * + * Depends on API functions: + * pthread_once() + * pthread_create() + */ + +#include "test.h" + +#define NUM_THREADS 100 /* Targeting each once control */ +#define NUM_ONCE 10 + +pthread_once_t o = PTHREAD_ONCE_INIT; +pthread_once_t once[NUM_ONCE]; + +typedef struct { + int i; + CRITICAL_SECTION cs; +} sharedInt_t; + +static sharedInt_t numOnce = {0, {0}}; +static sharedInt_t numThreads = {0, {0}}; + +void +myfunc(void) +{ + EnterCriticalSection(&numOnce.cs); + numOnce.i++; + LeaveCriticalSection(&numOnce.cs); + /* Simulate slow once routine so that following threads pile up behind it */ + Sleep(100); +} + +void * +mythread(void * arg) +{ + assert(pthread_once(&once[(int) arg], myfunc) == 0); + EnterCriticalSection(&numThreads.cs); + numThreads.i++; + LeaveCriticalSection(&numThreads.cs); + return 0; +} + +int +main() +{ + pthread_t t[NUM_THREADS][NUM_ONCE]; + int i, j; + + InitializeCriticalSection(&numThreads.cs); + InitializeCriticalSection(&numOnce.cs); + + for (j = 0; j < NUM_ONCE; j++) + { + once[j] = o; + + for (i = 0; i < NUM_THREADS; i++) + assert(pthread_create(&t[i][j], NULL, mythread, (void *) j) == 0); + } + + for (j = 0; j < NUM_ONCE; j++) + for (i = 0; i < NUM_THREADS; i++) + if (pthread_join(t[i][j], NULL) != 0) + printf("Join failed for [thread,once] = [%d,%d]\n", i, j); + + assert(numOnce.i == NUM_ONCE); + assert(numThreads.i == NUM_THREADS * NUM_ONCE); + + DeleteCriticalSection(&numOnce.cs); + DeleteCriticalSection(&numThreads.cs); + + return 0; +} diff --git a/liblo/pthreads.2/tests/once3.c b/liblo/pthreads.2/tests/once3.c new file mode 100644 index 0000000..3d47875 --- /dev/null +++ b/liblo/pthreads.2/tests/once3.c @@ -0,0 +1,132 @@ +/* + * once3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create several pthread_once objects and channel several threads + * through each. Make the init_routine cancelable and cancel them with + * waiters waiting. + * + * Depends on API functions: + * pthread_once() + * pthread_create() + * pthread_testcancel() + * pthread_cancel() + * pthread_once() + */ + +#define ASSERT_TRACE + +#include "test.h" + +#define NUM_THREADS 100 /* Targeting each once control */ +#define NUM_ONCE 10 + +pthread_once_t o = PTHREAD_ONCE_INIT; +pthread_once_t once[NUM_ONCE]; + +typedef struct { + int i; + CRITICAL_SECTION cs; +} sharedInt_t; + +static sharedInt_t numOnce = {0, {0}}; +static sharedInt_t numThreads = {0, {0}}; + +void +myfunc(void) +{ + EnterCriticalSection(&numOnce.cs); + numOnce.i++; + assert(numOnce.i > 0); + LeaveCriticalSection(&numOnce.cs); + /* Simulate slow once routine so that following threads pile up behind it */ + Sleep(10); + /* test for cancelation late so we're sure to have waiters. */ + pthread_testcancel(); +} + +void * +mythread(void * arg) +{ + /* + * Cancel every thread. These threads are deferred cancelable only, so + * only the thread performing the once routine (my_func) will see it (there are + * no other cancelation points here). The result will be that every thread + * eventually cancels only when it becomes the new once thread. + */ + assert(pthread_cancel(pthread_self()) == 0); + assert(pthread_once(&once[(int) arg], myfunc) == 0); + EnterCriticalSection(&numThreads.cs); + numThreads.i++; + LeaveCriticalSection(&numThreads.cs); + return 0; +} + +int +main() +{ + pthread_t t[NUM_THREADS][NUM_ONCE]; + int i, j; + + InitializeCriticalSection(&numThreads.cs); + InitializeCriticalSection(&numOnce.cs); + + for (j = 0; j < NUM_ONCE; j++) + { + once[j] = o; + + for (i = 0; i < NUM_THREADS; i++) + { + assert(pthread_create(&t[i][j], NULL, mythread, (void *) j) == 0); + } + } + + for (j = 0; j < NUM_ONCE; j++) + for (i = 0; i < NUM_THREADS; i++) + if (pthread_join(t[i][j], NULL) != 0) + printf("Join failed for [thread,once] = [%d,%d]\n", i, j); + + /* + * All threads will cancel, none will return normally from + * pthread_once and so numThreads should never be incremented. However, + * numOnce should be incremented by every thread (NUM_THREADS*NUM_ONCE). + */ + assert(numOnce.i == NUM_ONCE * NUM_THREADS); + assert(numThreads.i == 0); + + DeleteCriticalSection(&numOnce.cs); + DeleteCriticalSection(&numThreads.cs); + + return 0; +} diff --git a/liblo/pthreads.2/tests/once4.c b/liblo/pthreads.2/tests/once4.c new file mode 100644 index 0000000..69e9384 --- /dev/null +++ b/liblo/pthreads.2/tests/once4.c @@ -0,0 +1,191 @@ +/* + * once4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create several pthread_once objects and channel several threads + * through each. Make the init_routine cancelable and cancel them + * waiters waiting. Vary the priorities. + * + * Depends on API functions: + * pthread_once() + * pthread_create() + * pthread_testcancel() + * pthread_cancel() + * pthread_once() + */ + +#include "test.h" + +#define NUM_THREADS 100 /* Targeting each once control */ +#define NUM_ONCE 10 + +pthread_once_t o = PTHREAD_ONCE_INIT; +pthread_once_t once[NUM_ONCE]; + +typedef struct { + int i; + CRITICAL_SECTION cs; +} sharedInt_t; + +static sharedInt_t numOnce = {0, {0}}; +static sharedInt_t numThreads = {0, {0}}; + +typedef struct { + int threadnum; + int oncenum; + int myPrio; + HANDLE w32Thread; +} bag_t; + +static bag_t threadbag[NUM_THREADS][NUM_ONCE]; + +CRITICAL_SECTION print_lock; + +void +mycleanupfunc(void * arg) +{ + bag_t * bag = (bag_t *) arg; + EnterCriticalSection(&print_lock); + /* once thrd prio error */ + printf("%4d %4d %4d %4d\n", + bag->oncenum, + bag->threadnum, + bag->myPrio, + bag->myPrio - GetThreadPriority(bag->w32Thread)); + LeaveCriticalSection(&print_lock); +} + +void +myinitfunc(void) +{ + EnterCriticalSection(&numOnce.cs); + numOnce.i++; + LeaveCriticalSection(&numOnce.cs); + /* Simulate slow once routine so that following threads pile up behind it */ + Sleep(10); + /* test for cancelation late so we're sure to have waiters. */ + pthread_testcancel(); +} + +void * +mythread(void * arg) +{ + bag_t * bag = (bag_t *) arg; + struct sched_param param; + + /* + * Cancel every thread. These threads are deferred cancelable only, so + * only the thread performing the init_routine will see it (there are + * no other cancelation points here). The result will be that every thread + * eventually cancels only when it becomes the new initter. + */ + pthread_t self = pthread_self(); + bag->w32Thread = pthread_getw32threadhandle_np(self); + /* + * Set priority between -2 and 2 inclusive. + */ + bag->myPrio = (bag->threadnum % 5) - 2; + param.sched_priority = bag->myPrio; + pthread_setschedparam(self, SCHED_OTHER, ¶m); + + /* Trigger a cancellation at the next cancellation point in this thread */ + pthread_cancel(self); +#if 0 + pthread_cleanup_push(mycleanupfunc, arg); + assert(pthread_once(&once[bag->oncenum], myinitfunc) == 0); + pthread_cleanup_pop(1); +#else + assert(pthread_once(&once[bag->oncenum], myinitfunc) == 0); +#endif + EnterCriticalSection(&numThreads.cs); + numThreads.i++; + LeaveCriticalSection(&numThreads.cs); + return 0; +} + +int +main() +{ + pthread_t t[NUM_THREADS][NUM_ONCE]; + int i, j; + + InitializeCriticalSection(&print_lock); + InitializeCriticalSection(&numThreads.cs); + InitializeCriticalSection(&numOnce.cs); + +#if 0 + /* once thrd prio change */ + printf("once thrd prio error\n"); +#endif + + /* + * Set the priority class to realtime - otherwise normal + * Windows random priority boosting will obscure any problems. + */ + SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + /* Set main thread to lower prio than threads */ + SetThreadPriority(GetCurrentThread(), -2); + + for (j = 0; j < NUM_ONCE; j++) + { + once[j] = o; + + for (i = 0; i < NUM_THREADS; i++) + { + bag_t * bag = &threadbag[i][j]; + bag->threadnum = i; + bag->oncenum = j; + assert(pthread_create(&t[i][j], NULL, mythread, (void *) bag) == 0); + } + } + + for (j = 0; j < NUM_ONCE; j++) + for (i = 0; i < NUM_THREADS; i++) + if (pthread_join(t[i][j], NULL) != 0) + printf("Join failed for [thread,once] = [%d,%d]\n", i, j); + + /* + * All threads will cancel, none will return normally from + * pthread_once and so numThreads should never be incremented. However, + * numOnce should be incremented by every thread (NUM_THREADS*NUM_ONCE). + */ + assert(numOnce.i == NUM_ONCE * NUM_THREADS); + assert(numThreads.i == 0); + + DeleteCriticalSection(&numOnce.cs); + DeleteCriticalSection(&numThreads.cs); + DeleteCriticalSection(&print_lock); + + return 0; +} diff --git a/liblo/pthreads.2/tests/priority1.c b/liblo/pthreads.2/tests/priority1.c new file mode 100644 index 0000000..3b7235b --- /dev/null +++ b/liblo/pthreads.2/tests/priority1.c @@ -0,0 +1,172 @@ +/* + * File: priority1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test thread priority explicit setting using thread attribute. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +enum { + PTW32TEST_THREAD_INIT_PRIO = 0, + PTW32TEST_MAXPRIORITIES = 512 +}; + +int minPrio; +int maxPrio; +int validPriorities[PTW32TEST_MAXPRIORITIES]; + +void * +func(void * arg) +{ + int policy; + struct sched_param param; + pthread_t threadID = pthread_self(); + + assert(pthread_getschedparam(threadID, &policy, ¶m) == 0); + assert(policy == SCHED_OTHER); + return (void *) (param.sched_priority); +} + +void * +getValidPriorities(void * arg) +{ + int prioSet; + pthread_t threadID = pthread_self(); + HANDLE threadH = pthread_getw32threadhandle_np(threadID); + + printf("Using GetThreadPriority\n"); + printf("%10s %10s\n", "Set value", "Get value"); + + for (prioSet = minPrio; + prioSet <= maxPrio; + prioSet++) + { + /* + * If prioSet is invalid then the threads priority is unchanged + * from the previous value. Make the previous value a known + * one so that we can check later. + */ + if (prioSet < 0) + SetThreadPriority(threadH, THREAD_PRIORITY_LOWEST); + else + SetThreadPriority(threadH, THREAD_PRIORITY_HIGHEST); + SetThreadPriority(threadH, prioSet); + validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)] = GetThreadPriority(threadH); + printf("%10d %10d\n", prioSet, validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)]); + } + + return (void *) 0; +} + + +int +main() +{ + pthread_t t; + pthread_attr_t attr; + void * result = NULL; + struct sched_param param; + + assert((maxPrio = sched_get_priority_max(SCHED_OTHER)) != -1); + assert((minPrio = sched_get_priority_min(SCHED_OTHER)) != -1); + + assert(pthread_create(&t, NULL, getValidPriorities, NULL) == 0); + assert(pthread_join(t, &result) == 0); + + assert(pthread_attr_init(&attr) == 0); + assert(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0); + + /* Set the thread's priority to a known initial value. */ + SetThreadPriority(pthread_getw32threadhandle_np(pthread_self()), + PTW32TEST_THREAD_INIT_PRIO); + + printf("Using pthread_getschedparam\n"); + printf("%10s %10s %10s\n", "Set value", "Get value", "Win priority"); + + for (param.sched_priority = minPrio; + param.sched_priority <= maxPrio; + param.sched_priority++) + { + int prio; + + assert(pthread_attr_setschedparam(&attr, ¶m) == 0); + assert(pthread_create(&t, &attr, func, (void *) &attr) == 0); + + assert((prio = GetThreadPriority(pthread_getw32threadhandle_np(t))) + == validPriorities[param.sched_priority+(PTW32TEST_MAXPRIORITIES/2)]); + + assert(pthread_join(t, &result) == 0); + + assert(param.sched_priority == (int) result); + printf("%10d %10d %10d\n", param.sched_priority, (int) result, prio); + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/priority2.c b/liblo/pthreads.2/tests/priority2.c new file mode 100644 index 0000000..768c10e --- /dev/null +++ b/liblo/pthreads.2/tests/priority2.c @@ -0,0 +1,169 @@ +/* + * File: priority2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test thread priority setting after creation. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +enum { + PTW32TEST_THREAD_INIT_PRIO = 0, + PTW32TEST_MAXPRIORITIES = 512 +}; + +int minPrio; +int maxPrio; +int validPriorities[PTW32TEST_MAXPRIORITIES]; +pthread_barrier_t startBarrier, endBarrier; + +void * func(void * arg) +{ + int policy; + int result; + struct sched_param param; + + result = pthread_barrier_wait(&startBarrier); + assert(result == 0 || result == PTHREAD_BARRIER_SERIAL_THREAD); + assert(pthread_getschedparam(pthread_self(), &policy, ¶m) == 0); + assert(policy == SCHED_OTHER); + result = pthread_barrier_wait(&endBarrier); + assert(result == 0 || result == PTHREAD_BARRIER_SERIAL_THREAD); + return (void *) param.sched_priority; +} + + +void * +getValidPriorities(void * arg) +{ + int prioSet; + pthread_t thread = pthread_self(); + HANDLE threadH = pthread_getw32threadhandle_np(thread); + struct sched_param param; + + for (prioSet = minPrio; + prioSet <= maxPrio; + prioSet++) + { + /* + * If prioSet is invalid then the threads priority is unchanged + * from the previous value. Make the previous value a known + * one so that we can check later. + */ + param.sched_priority = prioSet; + assert(pthread_setschedparam(thread, SCHED_OTHER, ¶m) == 0); + validPriorities[prioSet+(PTW32TEST_MAXPRIORITIES/2)] = GetThreadPriority(threadH); + } + + return (void *) 0; +} + + +int +main() +{ + pthread_t t; + void * result = NULL; + int result2; + struct sched_param param; + + assert((maxPrio = sched_get_priority_max(SCHED_OTHER)) != -1); + assert((minPrio = sched_get_priority_min(SCHED_OTHER)) != -1); + + assert(pthread_create(&t, NULL, getValidPriorities, NULL) == 0); + assert(pthread_join(t, &result) == 0); + + assert(pthread_barrier_init(&startBarrier, NULL, 2) == 0); + assert(pthread_barrier_init(&endBarrier, NULL, 2) == 0); + + /* Set the thread's priority to a known initial value. + * If the new priority is invalid then the threads priority + * is unchanged from the previous value. + */ + SetThreadPriority(pthread_getw32threadhandle_np(pthread_self()), + PTW32TEST_THREAD_INIT_PRIO); + + for (param.sched_priority = minPrio; + param.sched_priority <= maxPrio; + param.sched_priority++) + { + assert(pthread_create(&t, NULL, func, NULL) == 0); + assert(pthread_setschedparam(t, SCHED_OTHER, ¶m) == 0); + result2 = pthread_barrier_wait(&startBarrier); + assert(result2 == 0 || result2 == PTHREAD_BARRIER_SERIAL_THREAD); + result2 = pthread_barrier_wait(&endBarrier); + assert(result2 == 0 || result2 == PTHREAD_BARRIER_SERIAL_THREAD); + assert(GetThreadPriority(pthread_getw32threadhandle_np(t)) == + validPriorities[param.sched_priority+(PTW32TEST_MAXPRIORITIES/2)]); + pthread_join(t, &result); + assert(param.sched_priority == (int)result); + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/readme b/liblo/pthreads.2/tests/readme new file mode 100644 index 0000000..9ab4f58 --- /dev/null +++ b/liblo/pthreads.2/tests/readme @@ -0,0 +1,44 @@ +Running test cases in this directory +------------------------------------ + +These make scripts expect to be able to copy the dll, library +and header files from this directory's parent directory, +which should be the pthreads-win32 source directory. + +MS VC nmake +------------- + +Run the target corresponding to the DLL version being tested: + +nmake clean VC + +or: + +nmake clean VS + + +GNU GCC make +------------ + +Run "make clean" and then "make". See the "Known bugs" section +in ..\README. + + +Writing Test Cases +------------------ + +Tests written in this test suite should behave in the following manner: + + * If a test fails, leave main() with a result of 1. + + * If a test succeeds, leave main() with a result of 0. + + * No diagnostic output should appear when the test is succeeding. + Diagnostic output may be emitted if something in the test + fails, to help determine the cause of the test failure. + +Notes: +------ + +Many test cases use knowledge of implementation internals which are supposed +to be opaque to portable applications. diff --git a/liblo/pthreads.2/tests/reuse1.c b/liblo/pthreads.2/tests/reuse1.c new file mode 100644 index 0000000..6694435 --- /dev/null +++ b/liblo/pthreads.2/tests/reuse1.c @@ -0,0 +1,124 @@ +/* + * File: reuse1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Confirm that thread reuse works for joined threads. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +enum { + NUMTHREADS = 100 +}; + +static int washere = 0; + +void * func(void * arg) +{ + washere = 1; + return arg; +} + +int +main() +{ + pthread_t t, + last_t; + pthread_attr_t attr; + void * result = NULL; + int i; + + assert(pthread_attr_init(&attr) == 0);; + assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) == 0); + + washere = 0; + assert(pthread_create(&t, &attr, func, NULL) == 0); + assert(pthread_join(t, &result) == 0);; + assert(result == 0); + assert(washere == 1); + last_t = t; + + for (i = 1; i < NUMTHREADS; i++) + { + washere = 0; + assert(pthread_create(&t, &attr, func, (void *) i) == 0); + pthread_join(t, &result); + assert((int) result == i); + assert(washere == 1); + /* thread IDs should be unique */ + assert(!pthread_equal(t, last_t)); + /* thread struct pointers should be the same */ + assert(t.p == last_t.p); + /* thread handle reuse counter should be different by one */ + assert(t.x == last_t.x+1); + last_t = t; + } + + return 0; +} diff --git a/liblo/pthreads.2/tests/reuse2.c b/liblo/pthreads.2/tests/reuse2.c new file mode 100644 index 0000000..7cfa01e --- /dev/null +++ b/liblo/pthreads.2/tests/reuse2.c @@ -0,0 +1,167 @@ +/* + * File: reuse2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test that thread reuse works for detached threads. + * - Analyse thread struct reuse. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - This test is implementation specific + * because it uses knowledge of internals that should be + * opaque to an application. + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +/* + */ + +enum { + NUMTHREADS = 10000 +}; + + +static long done = 0; + +void * func(void * arg) +{ + sched_yield(); + + InterlockedIncrement(&done); + + return (void *) 0; +} + +int +main() +{ + pthread_t t[NUMTHREADS]; + pthread_attr_t attr; + int i; + unsigned int notUnique = 0, + totalHandles = 0, + reuseMax = 0, + reuseMin = NUMTHREADS; + + assert(pthread_attr_init(&attr) == 0); + assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0); + + for (i = 0; i < NUMTHREADS; i++) + { + assert(pthread_create(&t[i], &attr, func, NULL) == 0); + } + + while (NUMTHREADS > InterlockedExchangeAdd((LPLONG)&done, 0L)) + Sleep(100); + + Sleep(100); + + /* + * Analyse reuse by computing min and max number of times pthread_create() + * returned the same pthread_t value. + */ + for (i = 0; i < NUMTHREADS; i++) + { + if (t[i].p != NULL) + { + unsigned int j, thisMax; + + thisMax = t[i].x; + + for (j = i+1; j < NUMTHREADS; j++) + if (t[i].p == t[j].p) + { + if (t[i].x == t[j].x) + notUnique++; + if (thisMax < t[j].x) + thisMax = t[j].x; + t[j].p = NULL; + } + + if (reuseMin > thisMax) + reuseMin = thisMax; + + if (reuseMax < thisMax) + reuseMax = thisMax; + } + } + + for (i = 0; i < NUMTHREADS; i++) + if (t[i].p != NULL) + totalHandles++; + + /* + * pthread_t reuse counts start at 0, so we need to add 1 + * to the max and min values derived above. + */ + printf("For %d total threads:\n", NUMTHREADS); + printf("Non-unique IDs = %d\n", notUnique); + printf("Reuse maximum = %d\n", reuseMax + 1); + printf("Reuse minimum = %d\n", reuseMin + 1); + printf("Total handles = %d\n", totalHandles); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock1.c b/liblo/pthreads.2/tests/rwlock1.c new file mode 100644 index 0000000..4b74a12 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock1.c @@ -0,0 +1,61 @@ +/* + * rwlock1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create a simple rwlock object and then destroy it. + * + * Depends on API functions: + * pthread_rwlock_init() + * pthread_rwlock_destroy() + */ + +#include "test.h" + +pthread_rwlock_t rwlock = NULL; + +int +main() +{ + assert(rwlock == NULL); + + assert(pthread_rwlock_init(&rwlock, NULL) == 0); + + assert(rwlock != NULL); + + assert(pthread_rwlock_destroy(&rwlock) == 0); + + assert(rwlock == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock2.c b/liblo/pthreads.2/tests/rwlock2.c new file mode 100644 index 0000000..9f02240 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock2.c @@ -0,0 +1,66 @@ +/* + * rwlock2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, lock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_rdlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" + +pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; + +int +main() +{ + assert(rwlock == PTHREAD_RWLOCK_INITIALIZER); + + assert(pthread_rwlock_rdlock(&rwlock) == 0); + + assert(rwlock != PTHREAD_RWLOCK_INITIALIZER); + + assert(rwlock != NULL); + + assert(pthread_rwlock_unlock(&rwlock) == 0); + + assert(pthread_rwlock_destroy(&rwlock) == 0); + + assert(rwlock == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock2_t.c b/liblo/pthreads.2/tests/rwlock2_t.c new file mode 100644 index 0000000..dc4e54c --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock2_t.c @@ -0,0 +1,78 @@ +/* + * rwlock2_t.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, timed-lock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_timedrdlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" +#include + +pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; + +int +main() +{ + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(rwlock == PTHREAD_RWLOCK_INITIALIZER); + + assert(pthread_rwlock_timedrdlock(&rwlock, &abstime) == 0); + + assert(rwlock != PTHREAD_RWLOCK_INITIALIZER); + + assert(rwlock != NULL); + + assert(pthread_rwlock_unlock(&rwlock) == 0); + + assert(pthread_rwlock_destroy(&rwlock) == 0); + + assert(rwlock == NULL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock3.c b/liblo/pthreads.2/tests/rwlock3.c new file mode 100644 index 0000000..39f4a17 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock3.c @@ -0,0 +1,76 @@ +/* + * rwlock3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, wrlock it, trywrlock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_wrlock() + * pthread_rwlock_trywrlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" + +pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_rwlock_wrlock(&rwlock1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + Sleep(2000); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock3_t.c b/liblo/pthreads.2/tests/rwlock3_t.c new file mode 100644 index 0000000..0a383dd --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock3_t.c @@ -0,0 +1,87 @@ +/* + * rwlock3_t.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, timed-wrlock it, trywrlock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_timedwrlock() + * pthread_rwlock_trywrlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" +#include + +pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_rwlock_timedwrlock(&rwlock1, &abstime) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + Sleep(2000); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock4.c b/liblo/pthreads.2/tests/rwlock4.c new file mode 100644 index 0000000..6e66386 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock4.c @@ -0,0 +1,76 @@ +/* + * rwlock4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, rdlock it, trywrlock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_rdlock() + * pthread_rwlock_trywrlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" + +pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_rwlock_rdlock(&rwlock1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + Sleep(2000); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock4_t.c b/liblo/pthreads.2/tests/rwlock4_t.c new file mode 100644 index 0000000..c5be432 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock4_t.c @@ -0,0 +1,87 @@ +/* + * rwlock4_t.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, timed-rdlock it, trywrlock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_timedrdlock() + * pthread_rwlock_trywrlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" +#include + +pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_rwlock_trywrlock(&rwlock1) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + Sleep(2000); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock5.c b/liblo/pthreads.2/tests/rwlock5.c new file mode 100644 index 0000000..591f013 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock5.c @@ -0,0 +1,78 @@ +/* + * rwlock5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, rdlock it, tryrdlock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_rdlock() + * pthread_rwlock_tryrdlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" + +pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_rwlock_tryrdlock(&rwlock1) == 0); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_rwlock_rdlock(&rwlock1) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + Sleep(2000); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock5_t.c b/liblo/pthreads.2/tests/rwlock5_t.c new file mode 100644 index 0000000..55476bc --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock5_t.c @@ -0,0 +1,89 @@ +/* + * rwlock5_t.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static rwlock object, timed-rdlock it, tryrdlock it, + * and then unlock it again. + * + * Depends on API functions: + * pthread_rwlock_timedrdlock() + * pthread_rwlock_tryrdlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" +#include + +pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_rwlock_tryrdlock(&rwlock1) == 0); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + Sleep(2000); + + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock6.c b/liblo/pthreads.2/tests/rwlock6.c new file mode 100644 index 0000000..14d5e63 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock6.c @@ -0,0 +1,101 @@ +/* + * rwlock6.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Check writer and reader locking + * + * Depends on API functions: + * pthread_rwlock_rdlock() + * pthread_rwlock_wrlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" + +static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int bankAccount = 0; + +void * wrfunc(void * arg) +{ + int ba; + + assert(pthread_rwlock_wrlock(&rwlock1) == 0); + Sleep(2000); + bankAccount += 10; + ba = bankAccount; + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + return ((void *) ba); +} + +void * rdfunc(void * arg) +{ + int ba; + + assert(pthread_rwlock_rdlock(&rwlock1) == 0); + ba = bankAccount; + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + return ((void *) ba); +} + +int +main() +{ + pthread_t wrt1; + pthread_t wrt2; + pthread_t rdt; + int wr1Result = 0; + int wr2Result = 0; + int rdResult = 0; + + bankAccount = 0; + + assert(pthread_create(&wrt1, NULL, wrfunc, NULL) == 0); + Sleep(500); + assert(pthread_create(&rdt, NULL, rdfunc, NULL) == 0); + Sleep(500); + assert(pthread_create(&wrt2, NULL, wrfunc, NULL) == 0); + + assert(pthread_join(wrt1, (void **) &wr1Result) == 0); + assert(pthread_join(rdt, (void **) &rdResult) == 0); + assert(pthread_join(wrt2, (void **) &wr2Result) == 0); + + assert(wr1Result == 10); + assert(rdResult == 10); + assert(wr2Result == 20); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock6_t.c b/liblo/pthreads.2/tests/rwlock6_t.c new file mode 100644 index 0000000..caad473 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock6_t.c @@ -0,0 +1,126 @@ +/* + * rwlock6_t.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Check writer and reader locking with reader timeouts + * + * Depends on API functions: + * pthread_rwlock_timedrdlock() + * pthread_rwlock_wrlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" +#include + +static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int bankAccount = 0; + +void * wrfunc(void * arg) +{ + assert(pthread_rwlock_wrlock(&rwlock1) == 0); + Sleep(2000); + bankAccount += 10; + assert(pthread_rwlock_unlock(&rwlock1) == 0); + + return ((void *) bankAccount); +} + +void * rdfunc(void * arg) +{ + int ba = -1; + struct timespec abstime = { 0, 0 }; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + + if ((int) arg == 1) + { + abstime.tv_sec += 1; + assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == ETIMEDOUT); + ba = 0; + } + else if ((int) arg == 2) + { + abstime.tv_sec += 3; + assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == 0); + ba = bankAccount; + assert(pthread_rwlock_unlock(&rwlock1) == 0); + } + + return ((void *) ba); +} + +int +main() +{ + pthread_t wrt1; + pthread_t wrt2; + pthread_t rdt1; + pthread_t rdt2; + int wr1Result = 0; + int wr2Result = 0; + int rd1Result = 0; + int rd2Result = 0; + + bankAccount = 0; + + assert(pthread_create(&wrt1, NULL, wrfunc, NULL) == 0); + Sleep(500); + assert(pthread_create(&rdt1, NULL, rdfunc, (void *) 1) == 0); + Sleep(500); + assert(pthread_create(&wrt2, NULL, wrfunc, NULL) == 0); + Sleep(500); + assert(pthread_create(&rdt2, NULL, rdfunc, (void *) 2) == 0); + + assert(pthread_join(wrt1, (void **) &wr1Result) == 0); + assert(pthread_join(rdt1, (void **) &rd1Result) == 0); + assert(pthread_join(wrt2, (void **) &wr2Result) == 0); + assert(pthread_join(rdt2, (void **) &rd2Result) == 0); + + assert(wr1Result == 10); + assert(rd1Result == 0); + assert(wr2Result == 20); + assert(rd2Result == 20); + + return 0; +} + + diff --git a/liblo/pthreads.2/tests/rwlock6_t2.c b/liblo/pthreads.2/tests/rwlock6_t2.c new file mode 100644 index 0000000..67bb7fc --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock6_t2.c @@ -0,0 +1,119 @@ +/* + * rwlock6_t2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Check writer and reader timeouts. + * + * Depends on API functions: + * pthread_rwlock_timedrdlock() + * pthread_rwlock_timedwrlock() + * pthread_rwlock_unlock() + */ + +#include "test.h" +#include + +static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; + +static int bankAccount = 0; +struct timespec abstime = { 0, 0 }; + +void * wrfunc(void * arg) +{ + int result; + + result = pthread_rwlock_timedwrlock(&rwlock1, &abstime); + if ((int) arg == 1) + { + assert(result == 0); + Sleep(2000); + bankAccount += 10; + assert(pthread_rwlock_unlock(&rwlock1) == 0); + return ((void *) bankAccount); + } + else if ((int) arg == 2) + { + assert(result == ETIMEDOUT); + return ((void *) 100); + } + + return ((void *) -1); +} + +void * rdfunc(void * arg) +{ + int ba = 0; + + assert(pthread_rwlock_timedrdlock(&rwlock1, &abstime) == ETIMEDOUT); + + return ((void *) ba); +} + +int +main() +{ + pthread_t wrt1; + pthread_t wrt2; + pthread_t rdt; + int wr1Result = 0; + int wr2Result = 0; + int rdResult = 0; + struct _timeb currSysTime; + const DWORD NANOSEC_PER_MILLISEC = 1000000; + + _ftime(&currSysTime); + + abstime.tv_sec = currSysTime.time; + abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; + + abstime.tv_sec += 1; + + bankAccount = 0; + + assert(pthread_create(&wrt1, NULL, wrfunc, (void *) 1) == 0); + Sleep(100); + assert(pthread_create(&rdt, NULL, rdfunc, NULL) == 0); + Sleep(100); + assert(pthread_create(&wrt2, NULL, wrfunc, (void *) 2) == 0); + + assert(pthread_join(wrt1, (void **) &wr1Result) == 0); + assert(pthread_join(rdt, (void **) &rdResult) == 0); + assert(pthread_join(wrt2, (void **) &wr2Result) == 0); + + assert(wr1Result == 10); + assert(rdResult == 0); + assert(wr2Result == 100); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock7.c b/liblo/pthreads.2/tests/rwlock7.c new file mode 100644 index 0000000..8c8b829 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock7.c @@ -0,0 +1,199 @@ +/* + * rwlock7.c + * + * Hammer on a bunch of rwlocks to test robustness and fairness. + * Printed stats should be roughly even for each thread. + */ + +#include "test.h" +#include + +#ifdef __GNUC__ +#include +#endif + +#define THREADS 5 +#define DATASIZE 7 +#define ITERATIONS 1000000 + +/* + * Keep statistics for each thread. + */ +typedef struct thread_tag { + int thread_num; + pthread_t thread_id; + int updates; + int reads; + int changed; + int seed; +} thread_t; + +/* + * Read-write lock and shared data + */ +typedef struct data_tag { + pthread_rwlock_t lock; + int data; + int updates; +} data_t; + +static thread_t threads[THREADS]; +static data_t data[DATASIZE]; + +/* + * Thread start routine that uses read-write locks + */ +void *thread_routine (void *arg) +{ + thread_t *self = (thread_t*)arg; + int iteration; + int element = 0; + int seed = self->seed; + int interval = 1 + rand_r (&seed) % 71; + + self->changed = 0; + + for (iteration = 0; iteration < ITERATIONS; iteration++) + { + if (iteration % (ITERATIONS / 10) == 0) + { + putchar('.'); + fflush(stdout); + } + /* + * Each "self->interval" iterations, perform an + * update operation (write lock instead of read + * lock). + */ + if ((iteration % interval) == 0) + { + assert(pthread_rwlock_wrlock (&data[element].lock) == 0); + data[element].data = self->thread_num; + data[element].updates++; + self->updates++; + interval = 1 + rand_r (&seed) % 71; + assert(pthread_rwlock_unlock (&data[element].lock) == 0); + } else { + /* + * Look at the current data element to see whether + * the current thread last updated it. Count the + * times, to report later. + */ + assert(pthread_rwlock_rdlock (&data[element].lock) == 0); + + self->reads++; + + if (data[element].data != self->thread_num) + { + self->changed++; + interval = 1 + self->changed % 71; + } + + assert(pthread_rwlock_unlock (&data[element].lock) == 0); + } + + element = (element + 1) % DATASIZE; + + } + + return NULL; +} + +int +main (int argc, char *argv[]) +{ + int count; + int data_count; + int thread_updates = 0; + int data_updates = 0; + int seed = 1; + + struct _timeb currSysTime1; + struct _timeb currSysTime2; + + /* + * Initialize the shared data. + */ + for (data_count = 0; data_count < DATASIZE; data_count++) + { + data[data_count].data = 0; + data[data_count].updates = 0; + + assert(pthread_rwlock_init (&data[data_count].lock, NULL) == 0); + } + + _ftime(&currSysTime1); + + /* + * Create THREADS threads to access shared data. + */ + for (count = 0; count < THREADS; count++) + { + threads[count].thread_num = count; + threads[count].updates = 0; + threads[count].reads = 0; + threads[count].seed = 1 + rand_r (&seed) % 71; + + assert(pthread_create (&threads[count].thread_id, + NULL, thread_routine, (void*)&threads[count]) == 0); + } + + /* + * Wait for all threads to complete, and collect + * statistics. + */ + for (count = 0; count < THREADS; count++) + { + assert(pthread_join (threads[count].thread_id, NULL) == 0); + } + + putchar('\n'); + fflush(stdout); + + for (count = 0; count < THREADS; count++) + { + if (threads[count].changed > 0) + { + printf ("Thread %d found changed elements %d times\n", + count, threads[count].changed); + } + } + + putchar('\n'); + fflush(stdout); + + for (count = 0; count < THREADS; count++) + { + thread_updates += threads[count].updates; + printf ("%02d: seed %d, updates %d, reads %d\n", + count, threads[count].seed, + threads[count].updates, threads[count].reads); + } + + putchar('\n'); + fflush(stdout); + + /* + * Collect statistics for the data. + */ + for (data_count = 0; data_count < DATASIZE; data_count++) + { + data_updates += data[data_count].updates; + printf ("data %02d: value %d, %d updates\n", + data_count, data[data_count].data, data[data_count].updates); + assert(pthread_rwlock_destroy (&data[data_count].lock) == 0); + } + + printf ("%d thread updates, %d data updates\n", + thread_updates, data_updates); + + _ftime(&currSysTime2); + + printf( "\nstart: %ld/%d, stop: %ld/%d, duration:%ld\n", + currSysTime1.time,currSysTime1.millitm, + currSysTime2.time,currSysTime2.millitm, + (currSysTime2.time*1000+currSysTime2.millitm) - + (currSysTime1.time*1000+currSysTime1.millitm)); + + return 0; +} diff --git a/liblo/pthreads.2/tests/rwlock8.c b/liblo/pthreads.2/tests/rwlock8.c new file mode 100644 index 0000000..3db7287 --- /dev/null +++ b/liblo/pthreads.2/tests/rwlock8.c @@ -0,0 +1,205 @@ +/* + * rwlock8.c + * + * Hammer on a bunch of rwlocks to test robustness and fairness. + * Printed stats should be roughly even for each thread. + * + * Yield during each access to exercise lock contention code paths + * more than rwlock7.c does (particularly on uni-processor systems). + */ + +#include "test.h" +#include + +#ifdef __GNUC__ +#include +#endif + +#define THREADS 5 +#define DATASIZE 7 +#define ITERATIONS 100000 + +/* + * Keep statistics for each thread. + */ +typedef struct thread_tag { + int thread_num; + pthread_t thread_id; + int updates; + int reads; + int changed; + int seed; +} thread_t; + +/* + * Read-write lock and shared data + */ +typedef struct data_tag { + pthread_rwlock_t lock; + int data; + int updates; +} data_t; + +static thread_t threads[THREADS]; +static data_t data[DATASIZE]; + +/* + * Thread start routine that uses read-write locks + */ +void *thread_routine (void *arg) +{ + thread_t *self = (thread_t*)arg; + int iteration; + int element = 0; + int seed = self->seed; + int interval = 1 + rand_r (&seed) % 71; + + self->changed = 0; + + for (iteration = 0; iteration < ITERATIONS; iteration++) + { + if (iteration % (ITERATIONS / 10) == 0) + { + putchar('.'); + fflush(stdout); + } + /* + * Each "self->interval" iterations, perform an + * update operation (write lock instead of read + * lock). + */ + if ((iteration % interval) == 0) + { + assert(pthread_rwlock_wrlock (&data[element].lock) == 0); + data[element].data = self->thread_num; + data[element].updates++; + self->updates++; + interval = 1 + rand_r (&seed) % 71; + sched_yield(); + assert(pthread_rwlock_unlock (&data[element].lock) == 0); + } else { + /* + * Look at the current data element to see whether + * the current thread last updated it. Count the + * times, to report later. + */ + assert(pthread_rwlock_rdlock (&data[element].lock) == 0); + + self->reads++; + + if (data[element].data != self->thread_num) + { + self->changed++; + interval = 1 + self->changed % 71; + } + + sched_yield(); + + assert(pthread_rwlock_unlock (&data[element].lock) == 0); + } + + element = (element + 1) % DATASIZE; + + } + + return NULL; +} + +int +main (int argc, char *argv[]) +{ + int count; + int data_count; + int thread_updates = 0; + int data_updates = 0; + int seed = 1; + + struct _timeb currSysTime1; + struct _timeb currSysTime2; + + /* + * Initialize the shared data. + */ + for (data_count = 0; data_count < DATASIZE; data_count++) + { + data[data_count].data = 0; + data[data_count].updates = 0; + + assert(pthread_rwlock_init (&data[data_count].lock, NULL) == 0); + } + + _ftime(&currSysTime1); + + /* + * Create THREADS threads to access shared data. + */ + for (count = 0; count < THREADS; count++) + { + threads[count].thread_num = count; + threads[count].updates = 0; + threads[count].reads = 0; + threads[count].seed = 1 + rand_r (&seed) % 71; + + assert(pthread_create (&threads[count].thread_id, + NULL, thread_routine, (void*)&threads[count]) == 0); + } + + /* + * Wait for all threads to complete, and collect + * statistics. + */ + for (count = 0; count < THREADS; count++) + { + assert(pthread_join (threads[count].thread_id, NULL) == 0); + } + + putchar('\n'); + fflush(stdout); + + for (count = 0; count < THREADS; count++) + { + if (threads[count].changed > 0) + { + printf ("Thread %d found changed elements %d times\n", + count, threads[count].changed); + } + } + + putchar('\n'); + fflush(stdout); + + for (count = 0; count < THREADS; count++) + { + thread_updates += threads[count].updates; + printf ("%02d: seed %d, updates %d, reads %d\n", + count, threads[count].seed, + threads[count].updates, threads[count].reads); + } + + putchar('\n'); + fflush(stdout); + + /* + * Collect statistics for the data. + */ + for (data_count = 0; data_count < DATASIZE; data_count++) + { + data_updates += data[data_count].updates; + printf ("data %02d: value %d, %d updates\n", + data_count, data[data_count].data, data[data_count].updates); + assert(pthread_rwlock_destroy (&data[data_count].lock) == 0); + } + + printf ("%d thread updates, %d data updates\n", + thread_updates, data_updates); + + _ftime(&currSysTime2); + + printf( "\nstart: %ld/%d, stop: %ld/%d, duration:%ld\n", + currSysTime1.time,currSysTime1.millitm, + currSysTime2.time,currSysTime2.millitm, + (currSysTime2.time*1000+currSysTime2.millitm) - + (currSysTime1.time*1000+currSysTime1.millitm)); + + return 0; +} diff --git a/liblo/pthreads.2/tests/self1.c b/liblo/pthreads.2/tests/self1.c new file mode 100644 index 0000000..7b4a23b --- /dev/null +++ b/liblo/pthreads.2/tests/self1.c @@ -0,0 +1,69 @@ +/* + * self1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test for pthread_self(). + * + * Depends on API functions: + * pthread_self() + * + * Implicitly depends on: + * pthread_getspecific() + * pthread_setspecific() + */ + +#include "test.h" + +int +main(int argc, char * argv[]) +{ + /* + * This should always succeed unless the system has no + * resources (memory) left. + */ + pthread_t self; + +#ifdef PTW32_STATIC_LIB + pthread_win32_process_attach_np(); +#endif + + self = pthread_self(); + + assert(self.p != NULL); + +#ifdef PTW32_STATIC_LIB + pthread_win32_process_detach_np(); +#endif + return 0; +} diff --git a/liblo/pthreads.2/tests/self2.c b/liblo/pthreads.2/tests/self2.c new file mode 100644 index 0000000..abb0528 --- /dev/null +++ b/liblo/pthreads.2/tests/self2.c @@ -0,0 +1,73 @@ +/* + * self2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test for pthread_self(). + * + * Depends on API functions: + * pthread_create() + * pthread_self() + * + * Implicitly depends on: + * pthread_getspecific() + * pthread_setspecific() + */ + +#include "test.h" +#include + +static pthread_t me; + +void * +entry(void * arg) +{ + me = pthread_self(); + + return arg; +} + +int +main() +{ + pthread_t t; + + assert(pthread_create(&t, NULL, entry, NULL) == 0); + + Sleep(100); + + assert(pthread_equal(t, me) != 0); + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/semaphore1.c b/liblo/pthreads.2/tests/semaphore1.c new file mode 100644 index 0000000..f63f539 --- /dev/null +++ b/liblo/pthreads.2/tests/semaphore1.c @@ -0,0 +1,161 @@ +/* + * File: semaphore1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Verify trywait() returns -1 and sets EAGAIN. + * - + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +void * +thr(void * arg) +{ + sem_t s; + int result; + + assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0); + + assert((result = sem_trywait(&s)) == -1); + + if ( result == -1 ) + { + int err = errno; + printf("thread: sem_trywait 1: expecting error %s: got %s\n", + error_string[EAGAIN], error_string[err]); fflush(stdout); + assert(err == EAGAIN); + } + else + { + printf("thread: ok 1\n"); + } + + assert((result = sem_post(&s)) == 0); + + assert((result = sem_trywait(&s)) == 0); + + if ( result == -1 ) + { + perror("thread: sem_trywait 2"); + } + else + { + printf("thread: ok 2\n"); + } + + assert(sem_post(&s) == 0); + + return 0; +} + + +int +main() +{ + pthread_t t; + sem_t s; + int result; + + assert(pthread_create(&t, NULL, thr, NULL) == 0); + assert(pthread_join(t, (void **)&result) == 0); + assert(result == 0); + + assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0); + + assert((result = sem_trywait(&s)) == -1); + + if ( result == -1 ) + { + int err = errno; + printf("main: sem_trywait 1: expecting error %s: got %s\n", + error_string[EAGAIN], error_string[err]); fflush(stdout); + assert(err == EAGAIN); + } + else + { + printf("main: ok 1\n"); + } + + assert((result = sem_post(&s)) == 0); + + assert((result = sem_trywait(&s)) == 0); + + if ( result == -1 ) + { + perror("main: sem_trywait 2"); + } + else + { + printf("main: ok 2\n"); + } + + assert(sem_post(&s) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/semaphore2.c b/liblo/pthreads.2/tests/semaphore2.c new file mode 100644 index 0000000..5075415 --- /dev/null +++ b/liblo/pthreads.2/tests/semaphore2.c @@ -0,0 +1,108 @@ +/* + * File: semaphore2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Verify sem_getvalue returns the correct value. + * - + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +#define MAX_COUNT 100 + +int +main() +{ + sem_t s; + int value = 0; + int i; + + assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, MAX_COUNT) == 0); + assert(sem_getvalue(&s, &value) == 0); + assert(value == MAX_COUNT); +// printf("Value = %ld\n", value); + + for (i = MAX_COUNT - 1; i >= 0; i--) + { + assert(sem_wait(&s) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %ld\n", value); + assert(value == i); + } + + for (i = 1; i <= MAX_COUNT; i++) + { + assert(sem_post(&s) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %ld\n", value); + assert(value == i); + } + + return 0; +} + diff --git a/liblo/pthreads.2/tests/semaphore3.c b/liblo/pthreads.2/tests/semaphore3.c new file mode 100644 index 0000000..dd1ccc3 --- /dev/null +++ b/liblo/pthreads.2/tests/semaphore3.c @@ -0,0 +1,121 @@ +/* + * File: semaphore3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Verify sem_getvalue returns the correct number of waiters. + * - + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +#define MAX_COUNT 100 + +sem_t s; + +void * +thr (void * arg) +{ + assert(sem_wait(&s) == 0); + assert(pthread_detach(pthread_self()) == 0); + return NULL; +} + +int +main() +{ + int value = 0; + int i; + pthread_t t[MAX_COUNT+1]; + + assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %d\n", value); fflush(stdout); + assert(value == 0); + + for (i = 1; i <= MAX_COUNT; i++) + { + assert(pthread_create(&t[i], NULL, thr, NULL) == 0); + do { + sched_yield(); + assert(sem_getvalue(&s, &value) == 0); + } while (value != -i); +// printf("Value = %d\n", value); fflush(stdout); + assert(-value == i); + } + + for (i = MAX_COUNT - 1; i >= 0; i--) + { + assert(sem_post(&s) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %d\n", value); fflush(stdout); + assert(-value == i); + } + + return 0; +} + diff --git a/liblo/pthreads.2/tests/semaphore4.c b/liblo/pthreads.2/tests/semaphore4.c new file mode 100644 index 0000000..2514540 --- /dev/null +++ b/liblo/pthreads.2/tests/semaphore4.c @@ -0,0 +1,138 @@ +/* + * File: semaphore4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Verify sem_getvalue returns the correct number of waiters + * after threads are cancelled. + * - + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +#define MAX_COUNT 100 + +sem_t s; + +void * +thr (void * arg) +{ + assert(sem_wait(&s) == 0); + return NULL; +} + +int +main() +{ + int value = 0; + int i; + pthread_t t[MAX_COUNT+1]; + + assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %d\n", value); fflush(stdout); + assert(value == 0); + + for (i = 1; i <= MAX_COUNT; i++) + { + assert(pthread_create(&t[i], NULL, thr, NULL) == 0); + do { + sched_yield(); + assert(sem_getvalue(&s, &value) == 0); + } while (value != -i); +// printf("Value = %d\n", value); fflush(stdout); + assert(-value == i); + } + + assert(sem_getvalue(&s, &value) == 0); + assert(-value == MAX_COUNT); +//printf("value = %d\n", -value); fflush(stdout); + assert(pthread_cancel(t[50]) == 0); + { + int result; + assert(pthread_join(t[50], (void **) &result) == 0); +// printf("result = %d\n", result); fflush(stdout); + } + assert(sem_getvalue(&s, &value) == 0); +//printf("value = %d\n", -value); fflush(stdout); + assert(-value == (MAX_COUNT - 1)); + + for (i = MAX_COUNT - 2; i >= 0; i--) + { + assert(sem_post(&s) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %d\n", value); fflush(stdout); + assert(-value == i); + } + + for (i = 1; i <= MAX_COUNT; i++) + if (i != 50) + assert(pthread_join(t[i], NULL) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/semaphore4t.c b/liblo/pthreads.2/tests/semaphore4t.c new file mode 100644 index 0000000..ef465a7 --- /dev/null +++ b/liblo/pthreads.2/tests/semaphore4t.c @@ -0,0 +1,132 @@ +/* + * File: semaphore4t.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Verify sem_getvalue returns the correct number of waiters + * after threads are cancelled. + * - + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - sem_timedwait cancellation. + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +#define MAX_COUNT 100 + +sem_t s; + +void * +thr (void * arg) +{ + assert(sem_timedwait(&s, NULL) == 0); + return NULL; +} + +int +main() +{ + int value = 0; + int i; + pthread_t t[MAX_COUNT+1]; + + assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %d\n", value); fflush(stdout); + assert(value == 0); + + for (i = 1; i <= MAX_COUNT; i++) + { + assert(pthread_create(&t[i], NULL, thr, NULL) == 0); + do { + sched_yield(); + assert(sem_getvalue(&s, &value) == 0); + } while (value != -i); +// printf("Value = %d\n", value); fflush(stdout); + assert(-value == i); + } + + assert(sem_getvalue(&s, &value) == 0); + assert(-value == MAX_COUNT); + assert(pthread_cancel(t[50]) == 0); + assert(pthread_join(t[50], NULL) == 0); + assert(sem_getvalue(&s, &value) == 0); + assert(-value == MAX_COUNT - 1); + + for (i = MAX_COUNT - 2; i >= 0; i--) + { + assert(sem_post(&s) == 0); + assert(sem_getvalue(&s, &value) == 0); +// printf("Value = %d\n", value); fflush(stdout); + assert(-value == i); + } + + for (i = 1; i <= MAX_COUNT; i++) + if (i != 50) + assert(pthread_join(t[i], NULL) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/semaphore5.c b/liblo/pthreads.2/tests/semaphore5.c new file mode 100644 index 0000000..15fbd9d --- /dev/null +++ b/liblo/pthreads.2/tests/semaphore5.c @@ -0,0 +1,103 @@ +/* + * File: semaphore5.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: Verify sem_destroy EBUSY race avoidance + * - + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +// #define ASSERT_TRACE + +#include "test.h" + +void * +thr(void * arg) +{ + assert(sem_post((sem_t *)arg) == 0); + + return 0; +} + + +int +main() +{ + pthread_t t; + sem_t s; + + assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, 0) == 0); + assert(pthread_create(&t, NULL, thr, (void *)&s) == 0); + + assert(sem_wait(&s) == 0); + assert(sem_destroy(&s) == 0); + + assert(pthread_join(t, NULL) == 0); + + return 0; +} + diff --git a/liblo/pthreads.2/tests/sizes.c b/liblo/pthreads.2/tests/sizes.c new file mode 100644 index 0000000..e8aecf2 --- /dev/null +++ b/liblo/pthreads.2/tests/sizes.c @@ -0,0 +1,32 @@ +#define _WIN32_WINNT 0x400 + +#include "test.h" +#include "../implement.h" + +int +main() +{ + printf("Sizes of pthreads-win32 structs\n"); + printf("-------------------------------\n"); + printf("%30s %4d\n", "pthread_t", sizeof(pthread_t)); + printf("%30s %4d\n", "ptw32_thread_t", sizeof(ptw32_thread_t)); + printf("%30s %4d\n", "pthread_attr_t_", sizeof(struct pthread_attr_t_)); + printf("%30s %4d\n", "sem_t_", sizeof(struct sem_t_)); + printf("%30s %4d\n", "pthread_mutex_t_", sizeof(struct pthread_mutex_t_)); + printf("%30s %4d\n", "pthread_mutexattr_t_", sizeof(struct pthread_mutexattr_t_)); + printf("%30s %4d\n", "pthread_spinlock_t_", sizeof(struct pthread_spinlock_t_)); + printf("%30s %4d\n", "pthread_barrier_t_", sizeof(struct pthread_barrier_t_)); + printf("%30s %4d\n", "pthread_barrierattr_t_", sizeof(struct pthread_barrierattr_t_)); + printf("%30s %4d\n", "pthread_key_t_", sizeof(struct pthread_key_t_)); + printf("%30s %4d\n", "pthread_cond_t_", sizeof(struct pthread_cond_t_)); + printf("%30s %4d\n", "pthread_condattr_t_", sizeof(struct pthread_condattr_t_)); + printf("%30s %4d\n", "pthread_rwlock_t_", sizeof(struct pthread_rwlock_t_)); + printf("%30s %4d\n", "pthread_rwlockattr_t_", sizeof(struct pthread_rwlockattr_t_)); + printf("%30s %4d\n", "pthread_once_t_", sizeof(struct pthread_once_t_)); + printf("%30s %4d\n", "ptw32_cleanup_t", sizeof(struct ptw32_cleanup_t)); + printf("%30s %4d\n", "ptw32_mcs_node_t_", sizeof(struct ptw32_mcs_node_t_)); + printf("%30s %4d\n", "sched_param", sizeof(struct sched_param)); + printf("-------------------------------\n"); + + return 0; +} diff --git a/liblo/pthreads.2/tests/sizes.gc b/liblo/pthreads.2/tests/sizes.gc new file mode 100644 index 0000000..0add063 --- /dev/null +++ b/liblo/pthreads.2/tests/sizes.gc @@ -0,0 +1,21 @@ +Sizes of pthreads-win32 structs +------------------------------- + pthread_t 8 + ptw32_thread_t 140 + pthread_attr_t_ 28 + sem_t_ 12 + pthread_mutex_t_ 24 + pthread_mutexattr_t_ 8 + pthread_spinlock_t_ 8 + pthread_barrier_t_ 24 + pthread_barrierattr_t_ 4 + pthread_key_t_ 16 + pthread_cond_t_ 32 + pthread_condattr_t_ 4 + pthread_rwlock_t_ 28 + pthread_rwlockattr_t_ 4 + pthread_once_t_ 16 + ptw32_cleanup_t 12 + ptw32_mcs_node_t_ 16 + sched_param 4 +------------------------------- diff --git a/liblo/pthreads.2/tests/sizes.gce b/liblo/pthreads.2/tests/sizes.gce new file mode 100644 index 0000000..d010b21 --- /dev/null +++ b/liblo/pthreads.2/tests/sizes.gce @@ -0,0 +1,21 @@ +Sizes of pthreads-win32 structs +------------------------------- + pthread_t 8 + ptw32_thread_t 76 + pthread_attr_t_ 28 + sem_t_ 12 + pthread_mutex_t_ 24 + pthread_mutexattr_t_ 8 + pthread_spinlock_t_ 8 + pthread_barrier_t_ 24 + pthread_barrierattr_t_ 4 + pthread_key_t_ 16 + pthread_cond_t_ 32 + pthread_condattr_t_ 4 + pthread_rwlock_t_ 28 + pthread_rwlockattr_t_ 4 + pthread_once_t_ 16 + ptw32_cleanup_t 12 + ptw32_mcs_node_t_ 16 + sched_param 4 +------------------------------- diff --git a/liblo/pthreads.2/tests/sizes.vc b/liblo/pthreads.2/tests/sizes.vc new file mode 100644 index 0000000..0add063 --- /dev/null +++ b/liblo/pthreads.2/tests/sizes.vc @@ -0,0 +1,21 @@ +Sizes of pthreads-win32 structs +------------------------------- + pthread_t 8 + ptw32_thread_t 140 + pthread_attr_t_ 28 + sem_t_ 12 + pthread_mutex_t_ 24 + pthread_mutexattr_t_ 8 + pthread_spinlock_t_ 8 + pthread_barrier_t_ 24 + pthread_barrierattr_t_ 4 + pthread_key_t_ 16 + pthread_cond_t_ 32 + pthread_condattr_t_ 4 + pthread_rwlock_t_ 28 + pthread_rwlockattr_t_ 4 + pthread_once_t_ 16 + ptw32_cleanup_t 12 + ptw32_mcs_node_t_ 16 + sched_param 4 +------------------------------- diff --git a/liblo/pthreads.2/tests/sizes.vse b/liblo/pthreads.2/tests/sizes.vse new file mode 100644 index 0000000..d010b21 --- /dev/null +++ b/liblo/pthreads.2/tests/sizes.vse @@ -0,0 +1,21 @@ +Sizes of pthreads-win32 structs +------------------------------- + pthread_t 8 + ptw32_thread_t 76 + pthread_attr_t_ 28 + sem_t_ 12 + pthread_mutex_t_ 24 + pthread_mutexattr_t_ 8 + pthread_spinlock_t_ 8 + pthread_barrier_t_ 24 + pthread_barrierattr_t_ 4 + pthread_key_t_ 16 + pthread_cond_t_ 32 + pthread_condattr_t_ 4 + pthread_rwlock_t_ 28 + pthread_rwlockattr_t_ 4 + pthread_once_t_ 16 + ptw32_cleanup_t 12 + ptw32_mcs_node_t_ 16 + sched_param 4 +------------------------------- diff --git a/liblo/pthreads.2/tests/spin1.c b/liblo/pthreads.2/tests/spin1.c new file mode 100644 index 0000000..01d760d --- /dev/null +++ b/liblo/pthreads.2/tests/spin1.c @@ -0,0 +1,59 @@ +/* + * spin1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Create a simple spinlock object, lock it, and then unlock it again. + * This is the simplest test of the pthread mutex family that we can do. + * + */ + +#include "test.h" + +pthread_spinlock_t lock; + +int +main() +{ + assert(pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE) == 0); + + assert(pthread_spin_lock(&lock) == 0); + + assert(pthread_spin_unlock(&lock) == 0); + + assert(pthread_spin_destroy(&lock) == 0); + + assert(pthread_spin_lock(&lock) == EINVAL); + + return 0; +} diff --git a/liblo/pthreads.2/tests/spin2.c b/liblo/pthreads.2/tests/spin2.c new file mode 100644 index 0000000..c65d30e --- /dev/null +++ b/liblo/pthreads.2/tests/spin2.c @@ -0,0 +1,75 @@ +/* + * spin2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a spinlock object, lock it, trylock it, + * and then unlock it again. + * + */ + +#include "test.h" + +pthread_spinlock_t lock = NULL; + +static int washere = 0; + +void * func(void * arg) +{ + assert(pthread_spin_trylock(&lock) == EBUSY); + + washere = 1; + + return 0; +} + +int +main() +{ + pthread_t t; + + assert(pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE) == 0); + + assert(pthread_spin_lock(&lock) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + assert(pthread_join(t, NULL) == 0); + + assert(pthread_spin_unlock(&lock) == 0); + + assert(pthread_spin_destroy(&lock) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/spin3.c b/liblo/pthreads.2/tests/spin3.c new file mode 100644 index 0000000..1581fe2 --- /dev/null +++ b/liblo/pthreads.2/tests/spin3.c @@ -0,0 +1,72 @@ +/* + * spin3.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Thread A locks spin - thread B tries to unlock. + * This should succeed, but it's undefined behaviour. + * + */ + +#include "test.h" + +static int wasHere = 0; + +static pthread_spinlock_t spin; + +void * unlocker(void * arg) +{ + int expectedResult = (int) arg; + + wasHere++; + assert(pthread_spin_unlock(&spin) == expectedResult); + wasHere++; + return NULL; +} + +int +main() +{ + pthread_t t; + + wasHere = 0; + assert(pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE) == 0); + assert(pthread_spin_lock(&spin) == 0); + assert(pthread_create(&t, NULL, unlocker, (void *) 0) == 0); + assert(pthread_join(t, NULL) == 0); + assert(pthread_spin_unlock(&spin) == EPERM); + assert(pthread_spin_destroy(&spin) == 0); + assert(wasHere == 2); + + return 0; +} diff --git a/liblo/pthreads.2/tests/spin4.c b/liblo/pthreads.2/tests/spin4.c new file mode 100644 index 0000000..b9b2b85 --- /dev/null +++ b/liblo/pthreads.2/tests/spin4.c @@ -0,0 +1,103 @@ +/* + * spin4.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Declare a static spinlock object, lock it, spin on it, + * and then unlock it again. + */ + +#include "test.h" +#include + +pthread_spinlock_t lock = PTHREAD_SPINLOCK_INITIALIZER; +struct _timeb currSysTimeStart; +struct _timeb currSysTimeStop; + +#define GetDurationMilliSecs(_TStart, _TStop) ((_TStop.time*1000+_TStop.millitm) \ + - (_TStart.time*1000+_TStart.millitm)) + +static int washere = 0; + +void * func(void * arg) +{ + _ftime(&currSysTimeStart); + washere = 1; + assert(pthread_spin_lock(&lock) == 0); + assert(pthread_spin_unlock(&lock) == 0); + _ftime(&currSysTimeStop); + + return (void *) GetDurationMilliSecs(currSysTimeStart, currSysTimeStop); +} + +int +main() +{ + long result = 0; + pthread_t t; + int CPUs; + struct _timeb sysTime; + + if ((CPUs = pthread_num_processors_np()) == 1) + { + printf("Test not run - it requires multiple CPUs.\n"); + exit(0); + } + + assert(pthread_spin_lock(&lock) == 0); + + assert(pthread_create(&t, NULL, func, NULL) == 0); + + while (washere == 0) + { + sched_yield(); + } + + do + { + sched_yield(); + _ftime(&sysTime); + } + while (GetDurationMilliSecs(currSysTimeStart, sysTime) <= 1000); + + assert(pthread_spin_unlock(&lock) == 0); + + assert(pthread_join(t, (void **) &result) == 0); + assert(result > 1000); + + assert(pthread_spin_destroy(&lock) == 0); + + assert(washere == 1); + + return 0; +} diff --git a/liblo/pthreads.2/tests/stress1.c b/liblo/pthreads.2/tests/stress1.c new file mode 100644 index 0000000..6d03c15 --- /dev/null +++ b/liblo/pthreads.2/tests/stress1.c @@ -0,0 +1,278 @@ +/* + * stress1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Stress test condition variables, mutexes, semaphores. + * + * Test Method (Validation or Falsification): + * - Validation + * + * Requirements Tested: + * - Correct accounting of semaphore and condition variable waiters. + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * Attempting to expose race conditions in cond vars, semaphores etc. + * - Master attempts to signal slave close to when timeout is due. + * - Master and slave do battle continuously until main tells them to stop. + * - Afterwards, the CV must be successfully destroyed (will return an + * error if there are waiters (including any internal semaphore waiters, + * which, if there are, cannot not be real waiters). + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - CV is successfully destroyed. + * + * Fail Criteria: + * - CV destroy fails. + */ + +#include "test.h" +#include +#include + + +const unsigned int ITERATIONS = 1000; + +static pthread_t master, slave; +typedef struct { + int value; + pthread_cond_t cv; + pthread_mutex_t mx; +} mysig_t; + +static int allExit; +static mysig_t control = {0, PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER}; +static pthread_barrier_t startBarrier, readyBarrier, holdBarrier; +static int timeoutCount = 0; +static int signalsTakenCount = 0; +static int signalsSent = 0; +static int bias = 0; +static int timeout = 10; // Must be > 0 + +enum { + CTL_STOP = -1 +}; + +/* + * Returns abstime 'milliseconds' from 'now'. + * + * Works for: -INT_MAX <= millisecs <= INT_MAX + */ +struct timespec * +millisecondsFromNow (struct timespec * time, int millisecs) +{ + struct _timeb currSysTime; + int64_t nanosecs, secs; + const int64_t NANOSEC_PER_MILLISEC = 1000000; + const int64_t NANOSEC_PER_SEC = 1000000000; + + /* get current system time and add millisecs */ + _ftime(&currSysTime); + + secs = (int64_t)(currSysTime.time) + (millisecs / 1000); + nanosecs = ((int64_t) (millisecs%1000 + currSysTime.millitm)) * NANOSEC_PER_MILLISEC; + if (nanosecs >= NANOSEC_PER_SEC) + { + secs++; + nanosecs -= NANOSEC_PER_SEC; + } + else if (nanosecs < 0) + { + secs--; + nanosecs += NANOSEC_PER_SEC; + } + + time->tv_nsec = (long)nanosecs; + time->tv_sec = (long)secs; + + return time; +} + +void * +masterThread (void * arg) +{ + int dither = (int) arg; + + timeout = (int) arg; + + pthread_barrier_wait(&startBarrier); + + do + { + int sleepTime; + + assert(pthread_mutex_lock(&control.mx) == 0); + control.value = timeout; + assert(pthread_mutex_unlock(&control.mx) == 0); + + /* + * We are attempting to send the signal close to when the slave + * is due to timeout. We feel around by adding some [non-random] dither. + * + * dither is in the range 2*timeout peak-to-peak + * sleep time is the average of timeout plus dither. + * e.g. + * if timeout = 10 then dither = 20 and + * sleep millisecs is: 5 <= ms <= 15 + * + * The bias value attempts to apply some negative feedback to keep + * the ratio of timeouts to signals taken close to 1:1. + * bias changes more slowly than dither so as to average more. + * + * Finally, if abs(bias) exceeds timeout then timeout is incremented. + */ + if (signalsSent % timeout == 0) + { + if (timeoutCount > signalsTakenCount) + { + bias++; + } + else if (timeoutCount < signalsTakenCount) + { + bias--; + } + if (bias < -timeout || bias > timeout) + { + timeout++; + } + } + dither = (dither + 1 ) % (timeout * 2); + sleepTime = (timeout - bias + dither) / 2; + Sleep(sleepTime); + assert(pthread_cond_signal(&control.cv) == 0); + signalsSent++; + + pthread_barrier_wait(&holdBarrier); + pthread_barrier_wait(&readyBarrier); + } + while (!allExit); + + return NULL; +} + +void * +slaveThread (void * arg) +{ + struct timespec time; + + pthread_barrier_wait(&startBarrier); + + do + { + assert(pthread_mutex_lock(&control.mx) == 0); + if (pthread_cond_timedwait(&control.cv, + &control.mx, + millisecondsFromNow(&time, control.value)) == ETIMEDOUT) + { + timeoutCount++; + } + else + { + signalsTakenCount++; + } + assert(pthread_mutex_unlock(&control.mx) == 0); + + pthread_barrier_wait(&holdBarrier); + pthread_barrier_wait(&readyBarrier); + } + while (!allExit); + + return NULL; +} + +int +main () +{ + unsigned int i; + + assert(pthread_barrier_init(&startBarrier, NULL, 3) == 0); + assert(pthread_barrier_init(&readyBarrier, NULL, 3) == 0); + assert(pthread_barrier_init(&holdBarrier, NULL, 3) == 0); + + assert(pthread_create(&master, NULL, masterThread, (void *) timeout) == 0); + assert(pthread_create(&slave, NULL, slaveThread, NULL) == 0); + + allExit = FALSE; + + pthread_barrier_wait(&startBarrier); + + for (i = 1; !allExit; i++) + { + pthread_barrier_wait(&holdBarrier); + if (i >= ITERATIONS) + { + allExit = TRUE; + } + pthread_barrier_wait(&readyBarrier); + } + + assert(pthread_join(slave, NULL) == 0); + assert(pthread_join(master, NULL) == 0); + + printf("Signals sent = %d\nWait timeouts = %d\nSignals taken = %d\nBias = %d\nTimeout = %d\n", + signalsSent, + timeoutCount, + signalsTakenCount, + (int) bias, + timeout); + + /* Cleanup */ + assert(pthread_barrier_destroy(&holdBarrier) == 0); + assert(pthread_barrier_destroy(&readyBarrier) == 0); + assert(pthread_barrier_destroy(&startBarrier) == 0); + assert(pthread_cond_destroy(&control.cv) == 0); + assert(pthread_mutex_destroy(&control.mx) == 0); + + /* Success. */ + return 0; +} diff --git a/liblo/pthreads.2/tests/test.h b/liblo/pthreads.2/tests/test.h new file mode 100644 index 0000000..798e9d4 --- /dev/null +++ b/liblo/pthreads.2/tests/test.h @@ -0,0 +1,140 @@ +/* + * test.h + * + * Useful definitions and declarations for tests. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#ifndef _PTHREAD_TEST_H_ +#define _PTHREAD_TEST_H_ + +#include "pthread.h" +#include "sched.h" +#include "semaphore.h" + +#include +#include + +#define PTW32_THREAD_NULL_ID {NULL,0} + +#if defined(__MINGW32__) +#include +#elif defined(__BORLANDC__) +#define int64_t ULONGLONG +#else +#define int64_t _int64 +#endif + + +char * error_string[] = { + "ZERO_or_EOK", + "EPERM", + "ENOFILE_or_ENOENT", + "ESRCH", + "EINTR", + "EIO", + "ENXIO", + "E2BIG", + "ENOEXEC", + "EBADF", + "ECHILD", + "EAGAIN", + "ENOMEM", + "EACCES", + "EFAULT", + "UNKNOWN_15", + "EBUSY", + "EEXIST", + "EXDEV", + "ENODEV", + "ENOTDIR", + "EISDIR", + "EINVAL", + "ENFILE", + "EMFILE", + "ENOTTY", + "UNKNOWN_26", + "EFBIG", + "ENOSPC", + "ESPIPE", + "EROFS", + "EMLINK", + "EPIPE", + "EDOM", + "ERANGE", + "UNKNOWN_35", + "EDEADLOCK_or_EDEADLK", + "UNKNOWN_37", + "ENAMETOOLONG", + "ENOLCK", + "ENOSYS", + "ENOTEMPTY", + "EILSEQ", +}; + +/* + * The Mingw32 assert macro calls the CRTDLL _assert function + * which pops up a dialog. We want to run in batch mode so + * we define our own assert macro. + */ +#ifdef assert +# undef assert +#endif + +#ifndef ASSERT_TRACE +# define ASSERT_TRACE 0 +#else +# undef ASSERT_TRACE +# define ASSERT_TRACE 1 +#endif + +# define assert(e) \ + ((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \ + "Assertion succeeded: (%s), file %s, line %d\n", \ + #e, __FILE__, (int) __LINE__), \ + fflush(stderr) : \ + 0) : \ + (fprintf(stderr, "Assertion failed: (%s), file %s, line %d\n", \ + #e, __FILE__, (int) __LINE__), exit(1), 0)) + +int assertE; +# define assert_e(e, o, r) \ + (((assertE = e) o (r)) ? ((ASSERT_TRACE) ? fprintf(stderr, \ + "Assertion succeeded: (%s), file %s, line %d\n", \ + #e, __FILE__, (int) __LINE__), \ + fflush(stderr) : \ + 0) : \ + (fprintf(stderr, "Assertion failed: (%s %s %s), file %s, line %d, error %s\n", \ + #e,#o,#r, __FILE__, (int) __LINE__, error_string[assertE]), exit(1), 0)) + +#endif diff --git a/liblo/pthreads.2/tests/tryentercs.c b/liblo/pthreads.2/tests/tryentercs.c new file mode 100644 index 0000000..4ba3601 --- /dev/null +++ b/liblo/pthreads.2/tests/tryentercs.c @@ -0,0 +1,103 @@ +/* + * tryentercs.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * See if we have the TryEnterCriticalSection function. + * Does not use any part of pthreads. + */ + +#include +#include +#include + +/* + * Function pointer to TryEnterCriticalSection if it exists + * - otherwise NULL + */ +BOOL (WINAPI *_try_enter_critical_section)(LPCRITICAL_SECTION) = +NULL; + +/* + * Handle to kernel32.dll + */ +static HINSTANCE _h_kernel32; + + +int +main() +{ + CRITICAL_SECTION cs; + + SetLastError(0); + + printf("Last Error [main enter] %ld\n", (long) GetLastError()); + + /* + * Load KERNEL32 and try to get address of TryEnterCriticalSection + */ + _h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL")); + _try_enter_critical_section = + (BOOL (PT_STDCALL *)(LPCRITICAL_SECTION)) + GetProcAddress(_h_kernel32, + (LPCSTR) "TryEnterCriticalSection"); + + if (_try_enter_critical_section != NULL) + { + InitializeCriticalSection(&cs); + + SetLastError(0); + + if ((*_try_enter_critical_section)(&cs) != 0) + { + LeaveCriticalSection(&cs); + } + else + { + printf("Last Error [try enter] %ld\n", (long) GetLastError()); + + _try_enter_critical_section = NULL; + } + DeleteCriticalSection(&cs); + } + + (void) FreeLibrary(_h_kernel32); + + printf("This system %s TryEnterCriticalSection.\n", + (_try_enter_critical_section == NULL) ? "DOES NOT SUPPORT" : "SUPPORTS"); + printf("POSIX Mutexes will be based on Win32 %s.\n", + (_try_enter_critical_section == NULL) ? "Mutexes" : "Critical Sections"); + + return(0); +} + diff --git a/liblo/pthreads.2/tests/tryentercs2.c b/liblo/pthreads.2/tests/tryentercs2.c new file mode 100644 index 0000000..487c757 --- /dev/null +++ b/liblo/pthreads.2/tests/tryentercs2.c @@ -0,0 +1,92 @@ +/* + * tryentercs.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * See if we have the TryEnterCriticalSection function. + * Does not use any part of pthreads. + */ + +#include +#include +#include + +/* + * Function pointer to TryEnterCriticalSection if it exists + * - otherwise NULL + */ +BOOL (WINAPI *_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL; + +/* + * Handle to kernel32.dll + */ +static HINSTANCE _h_kernel32; + + +int +main() +{ + LPCRITICAL_SECTION lpcs = NULL; + + SetLastError(0); + + printf("Last Error [main enter] %ld\n", (long) GetLastError()); + + /* + * Load KERNEL32 and try to get address of TryEnterCriticalSection + */ + _h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL")); + _try_enter_critical_section = + (BOOL (PT_STDCALL *)(LPCRITICAL_SECTION)) + GetProcAddress(_h_kernel32, + (LPCSTR) "TryEnterCriticalSection"); + + if (_try_enter_critical_section != NULL) + { + SetLastError(0); + + (*_try_enter_critical_section)(lpcs); + + printf("Last Error [try enter] %ld\n", (long) GetLastError()); + } + + (void) FreeLibrary(_h_kernel32); + + printf("This system %s TryEnterCriticalSection.\n", + (_try_enter_critical_section == NULL) ? "DOES NOT SUPPORT" : "SUPPORTS"); + printf("POSIX Mutexes will be based on Win32 %s.\n", + (_try_enter_critical_section == NULL) ? "Mutexes" : "Critical Sections"); + + return(0); +} + diff --git a/liblo/pthreads.2/tests/tsd1.c b/liblo/pthreads.2/tests/tsd1.c new file mode 100644 index 0000000..da59a08 --- /dev/null +++ b/liblo/pthreads.2/tests/tsd1.c @@ -0,0 +1,211 @@ +/* + * tsd1.c + * + * Test Thread Specific Data (TSD) key creation and destruction. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * + * -------------------------------------------------------------------------- + * + * Description: + * - + * + * Test Method (validation or falsification): + * - validation + * + * Requirements Tested: + * - keys are created for each existing thread including the main thread + * - keys are created for newly created threads + * - keys are thread specific + * - destroy routine is called on each thread exit including the main thread + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Environment: + * - + * + * Input: + * - none + * + * Output: + * - text to stdout + * + * Assumptions: + * - already validated: pthread_create() + * pthread_once() + * - main thread also has a POSIX thread identity + * + * Pass Criteria: + * - stdout matches file reference/tsd1.out + * + * Fail Criteria: + * - fails to match file reference/tsd1.out + * - output identifies failed component + */ + +#include +#include "test.h" + +enum { + NUM_THREADS = 100 +}; + +static pthread_key_t key = NULL; +static int accesscount[NUM_THREADS]; +static int thread_set[NUM_THREADS]; +static int thread_destroyed[NUM_THREADS]; +static pthread_barrier_t startBarrier; + +static void +destroy_key(void * arg) +{ + int * j = (int *) arg; + + (*j)++; + + assert(*j == 2); + + thread_destroyed[j - accesscount] = 1; +} + +static void +setkey(void * arg) +{ + int * j = (int *) arg; + + thread_set[j - accesscount] = 1; + + assert(*j == 0); + + assert(pthread_getspecific(key) == NULL); + + assert(pthread_setspecific(key, arg) == 0); + assert(pthread_setspecific(key, arg) == 0); + assert(pthread_setspecific(key, arg) == 0); + + assert(pthread_getspecific(key) == arg); + + (*j)++; + + assert(*j == 1); +} + +static void * +mythread(void * arg) +{ + (void) pthread_barrier_wait(&startBarrier); + + setkey(arg); + + return 0; + + /* Exiting the thread will call the key destructor. */ +} + +int +main() +{ + int i; + int fail = 0; + pthread_t thread[NUM_THREADS]; + + assert(pthread_barrier_init(&startBarrier, NULL, NUM_THREADS/2) == 0); + + for (i = 1; i < NUM_THREADS/2; i++) + { + accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; + assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); + } + + /* + * Here we test that existing threads will get a key created + * for them. + */ + assert(pthread_key_create(&key, destroy_key) == 0); + + (void) pthread_barrier_wait(&startBarrier); + + /* + * Test main thread key. + */ + accesscount[0] = 0; + setkey((void *) &accesscount[0]); + + /* + * Here we test that new threads will get a key created + * for them. + */ + for (i = NUM_THREADS/2; i < NUM_THREADS; i++) + { + accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; + assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); + } + + /* + * Wait for all threads to complete. + */ + for (i = 1; i < NUM_THREADS; i++) + { + int result = 0; + + assert(pthread_join(thread[i], (void **) &result) == 0); + } + + assert(pthread_key_delete(key) == 0); + + assert(pthread_barrier_destroy(&startBarrier) == 0); + + for (i = 1; i < NUM_THREADS; i++) + { + /* + * The counter is incremented once when the key is set to + * a value, and again when the key is destroyed. If the key + * doesn't get set for some reason then it will still be + * NULL and the destroy function will not be called, and + * hence accesscount will not equal 2. + */ + if (accesscount[i] != 2) + { + fail++; + fprintf(stderr, "Thread %d key, set = %d, destroyed = %d\n", + i, thread_set[i], thread_destroyed[i]); + } + } + + fflush(stderr); + + return (fail); +} diff --git a/liblo/pthreads.2/tests/tsd2.c b/liblo/pthreads.2/tests/tsd2.c new file mode 100644 index 0000000..5b7bfa7 --- /dev/null +++ b/liblo/pthreads.2/tests/tsd2.c @@ -0,0 +1,215 @@ +/* + * tsd2.c + * + * Test Thread Specific Data (TSD) key creation and destruction. + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * + * -------------------------------------------------------------------------- + * + * Description: + * - + * + * Test Method (validation or falsification): + * - validation + * + * Requirements Tested: + * - keys are created for each existing thread including the main thread + * - keys are created for newly created threads + * - keys are thread specific + * - destroy routine is called on each thread exit including the main thread + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Environment: + * - + * + * Input: + * - none + * + * Output: + * - text to stdout + * + * Assumptions: + * - already validated: pthread_create() + * pthread_once() + * - main thread also has a POSIX thread identity + * + * Pass Criteria: + * - stdout matches file reference/tsd1.out + * + * Fail Criteria: + * - fails to match file reference/tsd1.out + * - output identifies failed component + */ + +#include +#include "test.h" + +enum { + NUM_THREADS = 100 +}; + +static pthread_key_t key = NULL; +static int accesscount[NUM_THREADS]; +static int thread_set[NUM_THREADS]; +static int thread_destroyed[NUM_THREADS]; +static pthread_barrier_t startBarrier; + +static void +destroy_key(void * arg) +{ + int * j = (int *) arg; + + (*j)++; + + /* Set TSD key from the destructor to test destructor iteration */ + if (*j == 2) + assert(pthread_setspecific(key, arg) == 0); + else + assert(*j == 3); + + thread_destroyed[j - accesscount] = 1; +} + +static void +setkey(void * arg) +{ + int * j = (int *) arg; + + thread_set[j - accesscount] = 1; + + assert(*j == 0); + + assert(pthread_getspecific(key) == NULL); + + assert(pthread_setspecific(key, arg) == 0); + assert(pthread_setspecific(key, arg) == 0); + assert(pthread_setspecific(key, arg) == 0); + + assert(pthread_getspecific(key) == arg); + + (*j)++; + + assert(*j == 1); +} + +static void * +mythread(void * arg) +{ + (void) pthread_barrier_wait(&startBarrier); + + setkey(arg); + + return 0; + + /* Exiting the thread will call the key destructor. */ +} + +int +main() +{ + int i; + int fail = 0; + pthread_t thread[NUM_THREADS]; + + assert(pthread_barrier_init(&startBarrier, NULL, NUM_THREADS/2) == 0); + + for (i = 1; i < NUM_THREADS/2; i++) + { + accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; + assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); + } + + /* + * Here we test that existing threads will get a key created + * for them. + */ + assert(pthread_key_create(&key, destroy_key) == 0); + + (void) pthread_barrier_wait(&startBarrier); + + /* + * Test main thread key. + */ + accesscount[0] = 0; + setkey((void *) &accesscount[0]); + + /* + * Here we test that new threads will get a key created + * for them. + */ + for (i = NUM_THREADS/2; i < NUM_THREADS; i++) + { + accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; + assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); + } + + /* + * Wait for all threads to complete. + */ + for (i = 1; i < NUM_THREADS; i++) + { + int result = 0; + + assert(pthread_join(thread[i], (void **) &result) == 0); + } + + assert(pthread_key_delete(key) == 0); + + assert(pthread_barrier_destroy(&startBarrier) == 0); + + for (i = 1; i < NUM_THREADS; i++) + { + /* + * The counter is incremented once when the key is set to + * a value, and again when the key is destroyed. If the key + * doesn't get set for some reason then it will still be + * NULL and the destroy function will not be called, and + * hence accesscount will not equal 2. + */ + if (accesscount[i] != 3) + { + fail++; + fprintf(stderr, "Thread %d key, set = %d, destroyed = %d\n", + i, thread_set[i], thread_destroyed[i]); + } + } + + fflush(stderr); + + return (fail); +} diff --git a/liblo/pthreads.2/tests/valid1.c b/liblo/pthreads.2/tests/valid1.c new file mode 100644 index 0000000..6c9dd35 --- /dev/null +++ b/liblo/pthreads.2/tests/valid1.c @@ -0,0 +1,103 @@ +/* + * File: valid1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Test that thread validation works. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +enum { + NUMTHREADS = 1 +}; + +static int washere = 0; + +void * func(void * arg) +{ + washere = 1; + return (void *) 0; +} + +int +main() +{ + pthread_t t; + void * result = NULL; + + washere = 0; + assert(pthread_create(&t, NULL, func, NULL) == 0); + assert(pthread_join(t, &result) == 0); + assert(result == 0); + assert(washere == 1); + sched_yield(); + assert(pthread_kill(t, 0) == ESRCH); + + return 0; +} diff --git a/liblo/pthreads.2/tests/valid2.c b/liblo/pthreads.2/tests/valid2.c new file mode 100644 index 0000000..19d2fa0 --- /dev/null +++ b/liblo/pthreads.2/tests/valid2.c @@ -0,0 +1,84 @@ +/* + * File: valid2.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - Confirm that thread validation fails for garbage thread ID. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - No output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - Process returns zero exit status. + * + * Fail Criteria: + * - Process returns non-zero exit status. + */ + +#include "test.h" + +int +main() +{ + pthread_t NullThread = PTW32_THREAD_NULL_ID; + + assert(pthread_kill(NullThread, 0) == ESRCH); + + return 0; +} diff --git a/liblo/pthreads.2/tsd.c b/liblo/pthreads.2/tsd.c new file mode 100644 index 0000000..ef49d4e --- /dev/null +++ b/liblo/pthreads.2/tsd.c @@ -0,0 +1,44 @@ +/* + * tsd.c + * + * Description: + * POSIX thread functions which implement thread-specific data (TSD). + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +#include "pthread_key_create.c" +#include "pthread_key_delete.c" +#include "pthread_setspecific.c" +#include "pthread_getspecific.c" diff --git a/liblo/pthreads.2/version.rc b/liblo/pthreads.2/version.rc new file mode 100644 index 0000000..2b35662 --- /dev/null +++ b/liblo/pthreads.2/version.rc @@ -0,0 +1,384 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include "pthread.h" + +/* + * Note: the correct __CLEANUP_* macro must be defined corresponding to + * the definition used for the object file builds. This is done in the + * relevent makefiles for the command line builds, but users should ensure + * that their resource compiler knows what it is too. + * If using the default (no __CLEANUP_* defined), pthread.h will define it + * as __CLEANUP_C. + */ + +#ifdef PTW32_RC_MSC +# if defined(__CLEANUP_C) +# define PTW32_VERSIONINFO_NAME "pthreadVC\0" +# define PTW32_VERSIONINFO_COMMENT "MS C build -- longjmp thread exiting\0" +# elif defined(__CLEANUP_CXX) +# define PTW32_VERSIONINFO_NAME "pthreadVCE\0" +# define PTW32_VERSIONINFO_COMMENT "MS C++ build -- C++ exception thread exiting\0" +# elif defined(__CLEANUP_SEH) +# define PTW32_VERSIONINFO_NAME "pthreadVSE\0" +# define PTW32_VERSIONINFO_COMMENT "MS C build -- structured exception thread exiting\0" +# else +# error Resource compiler doesn't know which cleanup style you're using - see version.rc +# endif +#elif defined(__GNUC__) +# if defined(__CLEANUP_C) +# define PTW32_VERSIONINFO_NAME "pthreadGC\0" +# define PTW32_VERSIONINFO_COMMENT "GNU C build -- longjmp thread exiting\0" +# elif defined(__CLEANUP_CXX) +# define PTW32_VERSIONINFO_NAME "pthreadGCE\0" +# define PTW32_VERSIONINFO_COMMENT "GNU C++ build -- C++ exception thread exiting\0" +# else +# error Resource compiler doesn't know which cleanup style you're using - see version.rc +# endif +#elif defined(__BORLANDC__) +# if defined(__CLEANUP_C) +# define PTW32_VERSIONINFO_NAME "pthreadBC\0" +# define PTW32_VERSIONINFO_COMMENT "BORLAND C build -- longjmp thread exiting\0" +# elif defined(__CLEANUP_CXX) +# define PTW32_VERSIONINFO_NAME "pthreadBCE\0" +# define PTW32_VERSIONINFO_COMMENT "BORLAND C++ build -- C++ exception thread exiting\0" +# else +# error Resource compiler doesn't know which cleanup style you're using - see version.rc +# endif +#elif defined(__WATCOMC__) +# if defined(__CLEANUP_C) +# define PTW32_VERSIONINFO_NAME "pthreadWC\0" +# define PTW32_VERSIONINFO_COMMENT "WATCOM C build -- longjmp thread exiting\0" +# elif defined(__CLEANUP_CXX) +# define PTW32_VERSIONINFO_NAME "pthreadWCE\0" +# define PTW32_VERSIONINFO_COMMENT "WATCOM C++ build -- C++ exception thread exiting\0" +# else +# error Resource compiler doesn't know which cleanup style you're using - see version.rc +# endif +#else +# error Resource compiler doesn't know which compiler you're using - see version.rc +#endif + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION PTW32_VERSION + PRODUCTVERSION PTW32_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "POSIX Threads for Windows32 Library\0" + VALUE "ProductVersion", PTW32_VERSION_STRING + VALUE "FileVersion", PTW32_VERSION_STRING + VALUE "InternalName", PTW32_VERSIONINFO_NAME + VALUE "OriginalFilename", PTW32_VERSIONINFO_NAME + VALUE "CompanyName", "Open Source Software community project\0" + VALUE "LegalCopyright", "Copyright (C) Project contributors 1998-2004\0" + VALUE "Licence", "LGPL\0" + VALUE "Info", "http://sources.redhat.com/pthreads-win32/\0" + VALUE "Comment", PTW32_VERSIONINFO_COMMENT + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +/* +VERSIONINFO Resource + +The VERSIONINFO resource-definition statement creates a version-information +resource. The resource contains such information about the file as its +version number, its intended operating system, and its original filename. +The resource is intended to be used with the Version Information functions. + +versionID VERSIONINFO fixed-info { block-statement...} + +versionID + Version-information resource identifier. This value must be 1. + +fixed-info + Version information, such as the file version and the intended operating + system. This parameter consists of the following statements. + + + Statement Description + -------------------------------------------------------------------------- + FILEVERSION + version Binary version number for the file. The version + consists of two 32-bit integers, defined by four + 16-bit integers. For example, "FILEVERSION 3,10,0,61" + is translated into two doublewords: 0x0003000a and + 0x0000003d, in that order. Therefore, if version is + defined by the DWORD values dw1 and dw2, they need + to appear in the FILEVERSION statement as follows: + HIWORD(dw1), LOWORD(dw1), HIWORD(dw2), LOWORD(dw2). + PRODUCTVERSION + version Binary version number for the product with which the + file is distributed. The version parameter is two + 32-bit integers, defined by four 16-bit integers. + For more information about version, see the + FILEVERSION description. + FILEFLAGSMASK + fileflagsmask Bits in the FILEFLAGS statement are valid. If a bit + is set, the corresponding bit in FILEFLAGS is valid. + FILEFLAGSfileflags Attributes of the file. The fileflags parameter must + be the combination of all the file flags that are + valid at compile time. For 16-bit Windows, this + value is 0x3f. + FILEOSfileos Operating system for which this file was designed. + The fileos parameter can be one of the operating + system values given in the Remarks section. + FILETYPEfiletype General type of file. The filetype parameter can be + one of the file type values listed in the Remarks + section. + FILESUBTYPE + subtype Function of the file. The subtype parameter is zero + unless the type parameter in the FILETYPE statement + is VFT_DRV, VFT_FONT, or VFT_VXD. For a list of file + subtype values, see the Remarks section. + +block-statement + Specifies one or more version-information blocks. A block can contain + string information or variable information. For more information, see + StringFileInfo Block or VarFileInfo Block. + +Remarks + +To use the constants specified with the VERSIONINFO statement, you must +include the Winver.h or Windows.h header file in the resource-definition file. + +The following list describes the parameters used in the VERSIONINFO statement: + +fileflags + A combination of the following values. + + Value Description + + VS_FF_DEBUG File contains debugging information or is compiled + with debugging features enabled. + VS_FF_PATCHED File has been modified and is not identical to the + original shipping file of the same version number. + VS_FF_PRERELEASE File is a development version, not a commercially + released product. + VS_FF_PRIVATEBUILD File was not built using standard release procedures. + If this value is given, the StringFileInfo block must + contain a PrivateBuild string. + VS_FF_SPECIALBUILD File was built by the original company using standard + release procedures but is a variation of the standard + file of the same version number. If this value is + given, the StringFileInfo block must contain a + SpecialBuild string. + +fileos + One of the following values. + + Value Description + + VOS_UNKNOWN The operating system for which the file was designed + is unknown. + VOS_DOS File was designed for MS-DOS. + VOS_NT File was designed for Windows Server 2003 family, + Windows XP, Windows 2000, or Windows NT. + VOS__WINDOWS16 File was designed for 16-bit Windows. + VOS__WINDOWS32 File was designed for 32-bit Windows. + VOS_DOS_WINDOWS16 File was designed for 16-bit Windows running with + MS-DOS. + VOS_DOS_WINDOWS32 File was designed for 32-bit Windows running with + MS-DOS. + VOS_NT_WINDOWS32 File was designed for Windows Server 2003 family, + Windows XP, Windows 2000, or Windows NT. + + The values 0x00002L, 0x00003L, 0x20000L and 0x30000L are reserved. + +filetype + One of the following values. + + Value Description + + VFT_UNKNOWN File type is unknown. + VFT_APP File contains an application. + VFT_DLL File contains a dynamic-link library (DLL). + VFT_DRV File contains a device driver. If filetype is + VFT_DRV, subtype contains a more specific + description of the driver. + VFT_FONT File contains a font. If filetype is VFT_FONT, + subtype contains a more specific description of the + font. + VFT_VXD File contains a virtual device. + VFT_STATIC_LIB File contains a static-link library. + + All other values are reserved for use by Microsoft. + +subtype + Additional information about the file type. + + If filetype specifies VFT_DRV, this parameter can be one of the + following values. + + Value Description + + VFT2_UNKNOWN Driver type is unknown. + VFT2_DRV_COMM File contains a communications driver. + VFT2_DRV_PRINTER File contains a printer driver. + VFT2_DRV_KEYBOARD File contains a keyboard driver. + VFT2_DRV_LANGUAGE File contains a language driver. + VFT2_DRV_DISPLAY File contains a display driver. + VFT2_DRV_MOUSE File contains a mouse driver. + VFT2_DRV_NETWORK File contains a network driver. + VFT2_DRV_SYSTEM File contains a system driver. + VFT2_DRV_INSTALLABLE File contains an installable driver. + VFT2_DRV_SOUND File contains a sound driver. + VFT2_DRV_VERSIONED_PRINTER File contains a versioned printer driver. + + If filetype specifies VFT_FONT, this parameter can be one of the + following values. + + Value Description + + VFT2_UNKNOWN Font type is unknown. + VFT2_FONT_RASTER File contains a raster font. + VFT2_FONT_VECTOR File contains a vector font. + VFT2_FONT_TRUETYPE File contains a TrueType font. + + If filetype specifies VFT_VXD, this parameter must be the virtual-device + identifier included in the virtual-device control block. + + All subtype values not listed here are reserved for use by Microsoft. + +langID + One of the following language codes. + + Code Language Code Language + + 0x0401 Arabic 0x0415 Polish + 0x0402 Bulgarian 0x0416 Portuguese (Brazil) + 0x0403 Catalan 0x0417 Rhaeto-Romanic + 0x0404 Traditional Chinese 0x0418 Romanian + 0x0405 Czech 0x0419 Russian + 0x0406 Danish 0x041A Croato-Serbian (Latin) + 0x0407 German 0x041B Slovak + 0x0408 Greek 0x041C Albanian + 0x0409 U.S. English 0x041D Swedish + 0x040A Castilian Spanish 0x041E Thai + 0x040B Finnish 0x041F Turkish + 0x040C French 0x0420 Urdu + 0x040D Hebrew 0x0421 Bahasa + 0x040E Hungarian 0x0804 Simplified Chinese + 0x040F Icelandic 0x0807 Swiss German + 0x0410 Italian 0x0809 U.K. English + 0x0411 Japanese 0x080A Mexican Spanish + 0x0412 Korean 0x080C Belgian French + 0x0413 Dutch 0x0C0C Canadian French + 0x0414 Norwegian – Bokmal 0x100C Swiss French + 0x0810 Swiss Italian 0x0816 Portuguese (Portugal) + 0x0813 Belgian Dutch 0x081A Serbo-Croatian (Cyrillic) + 0x0814 Norwegian – Nynorsk + +charsetID + One of the following character-set identifiers. + + Identifier Character Set + + 0 7-bit ASCII + 932 Japan (Shift %G–%@ JIS X-0208) + 949 Korea (Shift %G–%@ KSC 5601) + 950 Taiwan (Big5) + 1200 Unicode + 1250 Latin-2 (Eastern European) + 1251 Cyrillic + 1252 Multilingual + 1253 Greek + 1254 Turkish + 1255 Hebrew + 1256 Arabic + +string-name + One of the following predefined names. + + Name Description + + Comments Additional information that should be displayed for + diagnostic purposes. + CompanyName Company that produced the file%G—%@for example, + "Microsoft Corporation" or "Standard Microsystems + Corporation, Inc." This string is required. + FileDescription File description to be presented to users. This + string may be displayed in a list box when the user + is choosing files to install%G—%@for example, + "Keyboard Driver for AT-Style Keyboards". This + string is required. + FileVersion Version number of the file%G—%@for example, + "3.10" or "5.00.RC2". This string is required. + InternalName Internal name of the file, if one exists — for + example, a module name if the file is a dynamic-link + library. If the file has no internal name, this + string should be the original filename, without + extension. This string is required. + LegalCopyright Copyright notices that apply to the file. This + should include the full text of all notices, legal + symbols, copyright dates, and so on — for example, + "Copyright (C) Microsoft Corporation 1990–1999". + This string is optional. + LegalTrademarks Trademarks and registered trademarks that apply to + the file. This should include the full text of all + notices, legal symbols, trademark numbers, and so on. + This string is optional. + OriginalFilename Original name of the file, not including a path. + This information enables an application to determine + whether a file has been renamed by a user. The + format of the name depends on the file system for + which the file was created. This string is required. + PrivateBuild Information about a private version of the file — for + example, "Built by TESTER1 on \TESTBED". This string + should be present only if VS_FF_PRIVATEBUILD is + specified in the fileflags parameter of the root + block. + ProductName Name of the product with which the file is + distributed. This string is required. + ProductVersion Version of the product with which the file is + distributed — for example, "3.10" or "5.00.RC2". + This string is required. + SpecialBuild Text that indicates how this version of the file + differs from the standard version — for example, + "Private build for TESTER1 solving mouse problems + on M250 and M250E computers". This string should be + present only if VS_FF_SPECIALBUILD is specified in + the fileflags parameter of the root block. + */ diff --git a/liblo/pthreads.2/version.res b/liblo/pthreads.2/version.res new file mode 100644 index 0000000..539548a Binary files /dev/null and b/liblo/pthreads.2/version.res differ diff --git a/liblo/pthreads.2/w32_CancelableWait.c b/liblo/pthreads.2/w32_CancelableWait.c new file mode 100644 index 0000000..7fa54ec --- /dev/null +++ b/liblo/pthreads.2/w32_CancelableWait.c @@ -0,0 +1,160 @@ +/* + * w32_CancelableWait.c + * + * Description: + * This translation unit implements miscellaneous thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 2 of the License, or (at your option) any later version. + * + * This library 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 library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + + +static INLINE int +ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout) + /* + * ------------------------------------------------------------------- + * This provides an extra hook into the pthread_cancel + * mechanism that will allow you to wait on a Windows handle and make it a + * cancellation point. This function blocks until the given WIN32 handle is + * signaled or pthread_cancel has been called. It is implemented using + * WaitForMultipleObjects on 'waitHandle' and a manually reset WIN32 + * event used to implement pthread_cancel. + * + * Given this hook it would be possible to implement more of the cancellation + * points. + * ------------------------------------------------------------------- + */ +{ + int result; + pthread_t self; + ptw32_thread_t * sp; + HANDLE handles[2]; + DWORD nHandles = 1; + DWORD status; + + handles[0] = waitHandle; + + self = pthread_self(); + sp = (ptw32_thread_t *) self.p; + + if (sp != NULL) + { + /* + * Get cancelEvent handle + */ + if (sp->cancelState == PTHREAD_CANCEL_ENABLE) + { + + if ((handles[1] = sp->cancelEvent) != NULL) + { + nHandles++; + } + } + } + else + { + handles[1] = NULL; + } + + status = WaitForMultipleObjects (nHandles, handles, PTW32_FALSE, timeout); + + switch (status - WAIT_OBJECT_0) + { + case 0: + /* + * Got the handle. + * In the event that both handles are signalled, the smallest index + * value (us) is returned. As it has been arranged, this ensures that + * we don't drop a signal that we should act on (i.e. semaphore, + * mutex, or condition variable etc). + */ + result = 0; + break; + + case 1: + /* + * Got cancel request. + * In the event that both handles are signaled, the cancel will + * be ignored (see case 0 comment). + */ + ResetEvent (handles[1]); + + if (sp != NULL) + { + /* + * Should handle POSIX and implicit POSIX threads.. + * Make sure we haven't been async-canceled in the meantime. + */ + (void) pthread_mutex_lock (&sp->cancelLock); + if (sp->state < PThreadStateCanceling) + { + sp->state = PThreadStateCanceling; + sp->cancelState = PTHREAD_CANCEL_DISABLE; + (void) pthread_mutex_unlock (&sp->cancelLock); + ptw32_throw (PTW32_EPS_CANCEL); + + /* Never reached */ + } + (void) pthread_mutex_unlock (&sp->cancelLock); + } + + /* Should never get to here. */ + result = EINVAL; + break; + + default: + if (status == WAIT_TIMEOUT) + { + result = ETIMEDOUT; + } + else + { + result = EINVAL; + } + break; + } + + return (result); + +} /* CancelableWait */ + +int +pthreadCancelableWait (HANDLE waitHandle) +{ + return (ptw32_cancelable_wait (waitHandle, INFINITE)); +} + +int +pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout) +{ + return (ptw32_cancelable_wait (waitHandle, timeout)); +} diff --git a/liblo/ser-to-osc/README.txt b/liblo/ser-to-osc/README.txt new file mode 100644 index 0000000..02e8128 --- /dev/null +++ b/liblo/ser-to-osc/README.txt @@ -0,0 +1,21 @@ +ser-to-osc reads a serial port and sends OSC messages to Nyquist. + +usage: ser-to-osc [-q] [input-device] + +The default input is stdin, but another device can be specified +on the command line. The optional -q switch means "quiet": do not echo input. + + +The input format is +Channel +where is an ascii decimal integer, and + is an ascii decimal integer between 0 and 255. + +The input values are translated to the range 0-1. + +On the Mac, you build this with the ser-to-osc target in Xcode. +You can find the executable in: + nyquist/macosxproject/build/Development/ser-to-osc +and you can run this from a terminal window (or with Xcode) + + diff --git a/liblo/ser-to-osc/Serial.cpp b/liblo/ser-to-osc/Serial.cpp new file mode 100644 index 0000000..d0c0c11 --- /dev/null +++ b/liblo/ser-to-osc/Serial.cpp @@ -0,0 +1,1428 @@ +// Serial.cpp - Implementation of the CSerial class +// +// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl) +// +// This library 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 2.1 of the License, or (at your option) any later version. +// +// This library 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 library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +////////////////////////////////////////////////////////////////////// +// Include the standard header files + +#define STRICT +#include +#include +#include + + +////////////////////////////////////////////////////////////////////// +// Include module headerfile + +#include "Serial.h" + + +////////////////////////////////////////////////////////////////////// +// Disable warning C4127: conditional expression is constant, which +// is generated when using the _RPTF and _ASSERTE macros. + +#pragma warning(disable: 4127) + + +////////////////////////////////////////////////////////////////////// +// Enable debug memory manager + +#ifdef _DEBUG + +#ifdef THIS_FILE +#undef THIS_FILE +#endif + +static const char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW + +#endif + + +////////////////////////////////////////////////////////////////////// +// Helper methods + +inline void CSerial::CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const +{ +#ifdef SERIAL_NO_OVERLAPPED + + // Check if an overlapped structure has been specified + if (lpOverlapped || (dwTimeout != INFINITE)) + { + // Quit application + ::MessageBox(0,_T("Overlapped I/O and time-outs are not supported, when overlapped I/O is disabled."),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL); + ::DebugBreak(); + ::ExitProcess(0xFFFFFFF); + } + +#endif + +#ifdef SERIAL_NO_CANCELIO + + // Check if 0 or INFINITE time-out has been specified, because + // the communication I/O cannot be cancelled. + if ((dwTimeout != 0) && (dwTimeout != INFINITE)) + { + // Quit application + ::MessageBox(0,_T("Timeouts are not supported, when SERIAL_NO_CANCELIO is defined"),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL); + ::DebugBreak(); + ::ExitProcess(0xFFFFFFF); + } + +#endif // SERIAL_NO_CANCELIO + + // Avoid warnings + (void) dwTimeout; + (void) lpOverlapped; +} + +inline BOOL CSerial::CancelCommIo (void) +{ +#ifdef SERIAL_NO_CANCELIO + // CancelIo shouldn't have been called at this point + ::DebugBreak(); + return FALSE; +#else + + // Cancel the I/O request + return ::CancelIo(m_hFile); + +#endif // SERIAL_NO_CANCELIO +} + + +////////////////////////////////////////////////////////////////////// +// Code + +CSerial::CSerial () + : m_lLastError(ERROR_SUCCESS) + , m_hFile(0) + , m_eEvent(EEventNone) + , m_dwEventMask(0) +#ifndef SERIAL_NO_OVERLAPPED + , m_hevtOverlapped(0) +#endif +{ +} + +CSerial::~CSerial () +{ + // If the device is already closed, + // then we don't need to do anything. + if (m_hFile) + { + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::~CSerial - Serial port not closed\n"); + + // Close implicitly + Close(); + } +} + +CSerial::EPort CSerial::CheckPort (LPCTSTR lpszDevice) +{ + // Try to open the device + HANDLE hFile = ::CreateFile(lpszDevice, + GENERIC_READ|GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + 0, + 0); + + // Check if we could open the device + if (hFile == INVALID_HANDLE_VALUE) + { + // Display error + switch (::GetLastError()) + { + case ERROR_FILE_NOT_FOUND: + // The specified COM-port does not exist + return EPortNotAvailable; + + case ERROR_ACCESS_DENIED: + // The specified COM-port is in use + return EPortInUse; + + default: + // Something else is wrong + return EPortUnknownError; + } + } + + // Close handle + ::CloseHandle(hFile); + + // Port is available + return EPortAvailable; +} + +LONG CSerial::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fOverlapped) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the port isn't already opened + if (m_hFile) + { + m_lLastError = ERROR_ALREADY_INITIALIZED; + _RPTF0(_CRT_WARN,"CSerial::Open - Port already opened\n"); + return m_lLastError; + } + + // Open the device + m_hFile = ::CreateFile(lpszDevice, + GENERIC_READ|GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + fOverlapped?FILE_FLAG_OVERLAPPED:0, + 0); + if (m_hFile == INVALID_HANDLE_VALUE) + { + // Reset file handle + m_hFile = 0; + + // Display error + m_lLastError = ::GetLastError(); + _RPTF0(_CRT_WARN, "CSerial::Open - Unable to open port\n"); + return m_lLastError; + } + +#ifndef SERIAL_NO_OVERLAPPED + // We cannot have an event handle yet + _ASSERTE(m_hevtOverlapped == 0); + + // Create the event handle for internal overlapped operations (manual reset) + if (fOverlapped) + { + m_hevtOverlapped = ::CreateEvent(0,true,false,0); + if (m_hevtOverlapped == 0) + { + // Obtain the error information + m_lLastError = ::GetLastError(); + _RPTF0(_CRT_WARN,"CSerial::Open - Unable to create event\n"); + + // Close the port + ::CloseHandle(m_hFile); + m_hFile = 0; + + // Return the error + return m_lLastError; + } + } +#else + + // Overlapped flag shouldn't be specified + _ASSERTE(!fOverlapped); + +#endif + + // Setup the COM-port + if (dwInQueue || dwOutQueue) + { + // Make sure the queue-sizes are reasonable sized. Win9X systems crash + // if the input queue-size is zero. Both queues need to be at least + // 16 bytes large. + _ASSERTE(dwInQueue >= 16); + _ASSERTE(dwOutQueue >= 16); + + if (!::SetupComm(m_hFile,dwInQueue,dwOutQueue)) + { + // Display a warning + long lLastError = ::GetLastError(); + _RPTF0(_CRT_WARN,"CSerial::Open - Unable to setup the COM-port\n"); + + // Close the port + Close(); + + // Save last error from SetupComm + m_lLastError = lLastError; + return m_lLastError; + } + } + + // Setup the default communication mask + SetMask(); + + // Non-blocking reads is default + SetupReadTimeouts(EReadTimeoutNonblocking); + + // Setup the device for default settings + COMMCONFIG commConfig = {0}; + DWORD dwSize = sizeof(commConfig); + commConfig.dwSize = dwSize; + if (::GetDefaultCommConfig(lpszDevice,&commConfig,&dwSize)) + { + // Set the default communication configuration + if (!::SetCommConfig(m_hFile,&commConfig,dwSize)) + { + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::Open - Unable to set default communication configuration.\n"); + } + } + else + { + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::Open - Unable to obtain default communication configuration.\n"); + } + + // Return successful + return m_lLastError; +} + +LONG CSerial::Close (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // If the device is already closed, + // then we don't need to do anything. + if (m_hFile == 0) + { + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::Close - Method called when device is not open\n"); + return m_lLastError; + } + +#ifndef SERIAL_NO_OVERLAPPED + // Free event handle + if (m_hevtOverlapped) + { + ::CloseHandle(m_hevtOverlapped); + m_hevtOverlapped = 0; + } +#endif + + // Close COM port + ::CloseHandle(m_hFile); + m_hFile = 0; + + // Return successful + return m_lLastError; +} + +LONG CSerial::Setup (EBaudrate eBaudrate, EDataBits eDataBits, EParity eParity, EStopBits eStopBits) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Setup - Device is not opened\n"); + return m_lLastError; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = :: GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to obtain DCB information\n"); + return m_lLastError; + } + + // Set the new data + dcb.BaudRate = DWORD(eBaudrate); + dcb.ByteSize = BYTE(eDataBits); + dcb.Parity = BYTE(eParity); + dcb.StopBits = BYTE(eStopBits); + + // Determine if parity is used + dcb.fParity = (eParity != EParNone); + + // Set the new DCB structure + if (!::SetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to set DCB information\n"); + return m_lLastError; + } + + // Return successful + return m_lLastError; +} + +LONG CSerial::SetEventChar (BYTE bEventChar, bool fAdjustMask) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Device is not opened\n"); + return m_lLastError; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to obtain DCB information\n"); + return m_lLastError; + } + + // Set the new event character + dcb.EvtChar = char(bEventChar); + + // Adjust the event mask, to make sure the event will be received + if (fAdjustMask) + { + // Enable 'receive event character' event. Note that this + // will generate an EEventNone if there is an asynchronous + // WaitCommEvent pending. + SetMask(GetEventMask() | EEventRcvEv); + } + + // Set the new DCB structure + if (!::SetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to set DCB information\n"); + return m_lLastError; + } + + // Return successful + return m_lLastError; +} + +LONG CSerial::SetMask (DWORD dwEventMask) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::SetMask - Device is not opened\n"); + return m_lLastError; + } + + // Set the new mask. Note that this will generate an EEventNone + // if there is an asynchronous WaitCommEvent pending. + if (!::SetCommMask(m_hFile,dwEventMask)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::SetMask - Unable to set event mask\n"); + return m_lLastError; + } + + // Save event mask and return successful + m_dwEventMask = dwEventMask; + return m_lLastError; +} + +LONG CSerial::WaitEvent (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) +{ + // Check if time-outs are supported + CheckRequirements(lpOverlapped,dwTimeout); + + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Device is not opened\n"); + return m_lLastError; + } + +#ifndef SERIAL_NO_OVERLAPPED + + // Check if an overlapped structure has been specified + if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_FUNCTION; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Overlapped I/O is disabled, specified parameters are illegal.\n"); + return m_lLastError; + } + + // Wait for the event to happen + OVERLAPPED ovInternal; + if (!lpOverlapped && m_hevtOverlapped) + { + // Setup our own overlapped structure + memset(&ovInternal,0,sizeof(ovInternal)); + ovInternal.hEvent = m_hevtOverlapped; + + // Use our internal overlapped structure + lpOverlapped = &ovInternal; + } + + // Make sure the overlapped structure isn't busy + _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); + + // Wait for the COM event + if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),lpOverlapped)) + { + // Set the internal error code + long lLastError = ::GetLastError(); + + // Overlapped operation in progress is not an actual error + if (lLastError != ERROR_IO_PENDING) + { + // Save the error + m_lLastError = lLastError; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n"); + return m_lLastError; + } + + // We need to block if the client didn't specify an overlapped structure + if (lpOverlapped == &ovInternal) + { + // Wait for the overlapped operation to complete + switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) + { + case WAIT_OBJECT_0: + // The overlapped operation has completed + break; + + case WAIT_TIMEOUT: + // Cancel the I/O operation + CancelCommIo(); + + // The operation timed out. Set the internal error code and quit + m_lLastError = ERROR_TIMEOUT; + return m_lLastError; + + default: + // Set the internal error code + m_lLastError = ::GetLastError(); + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait until COM event has arrived\n"); + return m_lLastError; + } + } + } + else + { + // The operation completed immediatly. Just to be sure + // we'll set the overlapped structure's event handle. + if (lpOverlapped) + ::SetEvent(lpOverlapped->hEvent); + } +#else + + // Wait for the COM event + if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),0)) + { + // Set the internal error code + m_lLastError = ::GetLastError(); + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n"); + return m_lLastError; + } + +#endif + + // Return successfully + return m_lLastError; +} + + +LONG CSerial::SetupHandshaking (EHandshake eHandshake) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Device is not opened\n"); + return m_lLastError; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to obtain DCB information\n"); + return m_lLastError; + } + + // Set the handshaking flags + switch (eHandshake) + { + case EHandshakeOff: + dcb.fOutxCtsFlow = false; // Disable CTS monitoring + dcb.fOutxDsrFlow = false; // Disable DSR monitoring + dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR monitoring + dcb.fOutX = false; // Disable XON/XOFF for transmission + dcb.fInX = false; // Disable XON/XOFF for receiving + dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send) + break; + + case EHandshakeHardware: + dcb.fOutxCtsFlow = true; // Enable CTS monitoring + dcb.fOutxDsrFlow = true; // Enable DSR monitoring + dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; // Enable DTR handshaking + dcb.fOutX = false; // Disable XON/XOFF for transmission + dcb.fInX = false; // Disable XON/XOFF for receiving + dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; // Enable RTS handshaking + break; + + case EHandshakeSoftware: + dcb.fOutxCtsFlow = false; // Disable CTS (Clear To Send) + dcb.fOutxDsrFlow = false; // Disable DSR (Data Set Ready) + dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR (Data Terminal Ready) + dcb.fOutX = true; // Enable XON/XOFF for transmission + dcb.fInX = true; // Enable XON/XOFF for receiving + dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send) + break; + + default: + // This shouldn't be possible + _ASSERTE(false); + m_lLastError = E_INVALIDARG; + return m_lLastError; + } + + // Set the new DCB structure + if (!::SetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to set DCB information\n"); + return m_lLastError; + } + + // Return successful + return m_lLastError; +} + +LONG CSerial::SetupReadTimeouts (EReadTimeout eReadTimeout) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Device is not opened\n"); + return m_lLastError; + } + + // Determine the time-outs + COMMTIMEOUTS cto; + if (!::GetCommTimeouts(m_hFile,&cto)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to obtain timeout information\n"); + return m_lLastError; + } + + // Set the new timeouts + switch (eReadTimeout) + { + case EReadTimeoutBlocking: + cto.ReadIntervalTimeout = 0; + cto.ReadTotalTimeoutConstant = 0; + cto.ReadTotalTimeoutMultiplier = 0; + break; + case EReadTimeoutNonblocking: + cto.ReadIntervalTimeout = MAXDWORD; + cto.ReadTotalTimeoutConstant = 0; + cto.ReadTotalTimeoutMultiplier = 0; + break; + default: + // This shouldn't be possible + _ASSERTE(false); + m_lLastError = E_INVALIDARG; + return m_lLastError; + } + + // Set the new DCB structure + if (!::SetCommTimeouts(m_hFile,&cto)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to set timeout information\n"); + return m_lLastError; + } + + // Return successful + return m_lLastError; +} + +CSerial::EBaudrate CSerial::GetBaudrate (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Device is not opened\n"); + return EBaudUnknown; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Unable to obtain DCB information\n"); + return EBaudUnknown; + } + + // Return the appropriate baudrate + return EBaudrate(dcb.BaudRate); +} + +CSerial::EDataBits CSerial::GetDataBits (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Device is not opened\n"); + return EDataUnknown; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Unable to obtain DCB information\n"); + return EDataUnknown; + } + + // Return the appropriate bytesize + return EDataBits(dcb.ByteSize); +} + +CSerial::EParity CSerial::GetParity (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetParity - Device is not opened\n"); + return EParUnknown; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetParity - Unable to obtain DCB information\n"); + return EParUnknown; + } + + // Check if parity is used + if (!dcb.fParity) + { + // No parity + return EParNone; + } + + // Return the appropriate parity setting + return EParity(dcb.Parity); +} + +CSerial::EStopBits CSerial::GetStopBits (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Device is not opened\n"); + return EStopUnknown; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Unable to obtain DCB information\n"); + return EStopUnknown; + } + + // Return the appropriate stopbits + return EStopBits(dcb.StopBits); +} + +DWORD CSerial::GetEventMask (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetEventMask - Device is not opened\n"); + return 0; + } + + // Return the event mask + return m_dwEventMask; +} + +BYTE CSerial::GetEventChar (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Device is not opened\n"); + return 0; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Unable to obtain DCB information\n"); + return 0; + } + + // Set the new event character + return BYTE(dcb.EvtChar); +} + +CSerial::EHandshake CSerial::GetHandshaking (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Device is not opened\n"); + return EHandshakeUnknown; + } + + // Obtain the DCB structure for the device + CDCB dcb; + if (!::GetCommState(m_hFile,&dcb)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Unable to obtain DCB information\n"); + return EHandshakeUnknown; + } + + // Check if hardware handshaking is being used + if ((dcb.fDtrControl == DTR_CONTROL_HANDSHAKE) && (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE)) + return EHandshakeHardware; + + // Check if software handshaking is being used + if (dcb.fOutX && dcb.fInX) + return EHandshakeSoftware; + + // No handshaking is being used + return EHandshakeOff; +} + +LONG CSerial::Write (const void* pData, size_t iLen, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) +{ + // Check if time-outs are supported + CheckRequirements(lpOverlapped,dwTimeout); + + // Overlapped operation should specify the pdwWritten variable + _ASSERTE(!lpOverlapped || pdwWritten); + + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Use our own variable for read count + DWORD dwWritten; + if (pdwWritten == 0) + { + pdwWritten = &dwWritten; + } + + // Reset the number of bytes written + *pdwWritten = 0; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Write - Device is not opened\n"); + return m_lLastError; + } + +#ifndef SERIAL_NO_OVERLAPPED + + // Check if an overlapped structure has been specified + if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_FUNCTION; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped I/O is disabled, specified parameters are illegal.\n"); + return m_lLastError; + } + + // Wait for the event to happen + OVERLAPPED ovInternal; + if (!lpOverlapped && m_hevtOverlapped) + { + // Setup our own overlapped structure + memset(&ovInternal,0,sizeof(ovInternal)); + ovInternal.hEvent = m_hevtOverlapped; + + // Use our internal overlapped structure + lpOverlapped = &ovInternal; + } + + // Make sure the overlapped structure isn't busy + _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); + + // Write the data + if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,lpOverlapped)) + { + // Set the internal error code + long lLastError = ::GetLastError(); + + // Overlapped operation in progress is not an actual error + if (lLastError != ERROR_IO_PENDING) + { + // Save the error + m_lLastError = lLastError; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n"); + return m_lLastError; + } + + // We need to block if the client didn't specify an overlapped structure + if (lpOverlapped == &ovInternal) + { + // Wait for the overlapped operation to complete + switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) + { + case WAIT_OBJECT_0: + // The overlapped operation has completed + if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwWritten,FALSE)) + { + // Set the internal error code + m_lLastError = ::GetLastError(); + + _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped completed without result\n"); + return m_lLastError; + } + break; + + case WAIT_TIMEOUT: + // Cancel the I/O operation + CancelCommIo(); + + // The operation timed out. Set the internal error code and quit + m_lLastError = ERROR_TIMEOUT; + return m_lLastError; + + default: + // Set the internal error code + m_lLastError = ::GetLastError(); + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Write - Unable to wait until data has been sent\n"); + return m_lLastError; + } + } + } + else + { + // The operation completed immediatly. Just to be sure + // we'll set the overlapped structure's event handle. + if (lpOverlapped) + ::SetEvent(lpOverlapped->hEvent); + } + +#else + + // Write the data + if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,0)) + { + // Set the internal error code + m_lLastError = ::GetLastError(); + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n"); + return m_lLastError; + } + +#endif + + // Return successfully + return m_lLastError; +} + +LONG CSerial::Write (LPCSTR pString, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) +{ + // Check if time-outs are supported + CheckRequirements(lpOverlapped,dwTimeout); + + // Determine the length of the string + return Write(pString,strlen(pString),pdwWritten,lpOverlapped,dwTimeout); +} + +LONG CSerial::Read (void* pData, size_t iLen, DWORD* pdwRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) +{ + // Check if time-outs are supported + CheckRequirements(lpOverlapped,dwTimeout); + + // Overlapped operation should specify the pdwRead variable + _ASSERTE(!lpOverlapped || pdwRead); + + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Use our own variable for read count + DWORD dwRead; + if (pdwRead == 0) + { + pdwRead = &dwRead; + } + + // Reset the number of bytes read + *pdwRead = 0; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Read - Device is not opened\n"); + return m_lLastError; + } + +#ifdef _DEBUG + // The debug version fills the entire data structure with + // 0xDC bytes, to catch buffer errors as soon as possible. + memset(pData,0xDC,iLen); +#endif + +#ifndef SERIAL_NO_OVERLAPPED + + // Check if an overlapped structure has been specified + if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_FUNCTION; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped I/O is disabled, specified parameters are illegal.\n"); + return m_lLastError; + } + + // Wait for the event to happen + OVERLAPPED ovInternal; + if (lpOverlapped == 0) + { + // Setup our own overlapped structure + memset(&ovInternal,0,sizeof(ovInternal)); + ovInternal.hEvent = m_hevtOverlapped; + + // Use our internal overlapped structure + lpOverlapped = &ovInternal; + } + + // Make sure the overlapped structure isn't busy + _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); + + // Read the data + if (!::ReadFile(m_hFile,pData,iLen,pdwRead,lpOverlapped)) + { + // Set the internal error code + long lLastError = ::GetLastError(); + + // Overlapped operation in progress is not an actual error + if (lLastError != ERROR_IO_PENDING) + { + // Save the error + m_lLastError = lLastError; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n"); + return m_lLastError; + } + + // We need to block if the client didn't specify an overlapped structure + if (lpOverlapped == &ovInternal) + { + // Wait for the overlapped operation to complete + switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) + { + case WAIT_OBJECT_0: + // The overlapped operation has completed + if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwRead,FALSE)) + { + // Set the internal error code + m_lLastError = ::GetLastError(); + + _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped completed without result\n"); + return m_lLastError; + } + break; + + case WAIT_TIMEOUT: + // Cancel the I/O operation + CancelCommIo(); + + // The operation timed out. Set the internal error code and quit + m_lLastError = ERROR_TIMEOUT; + return m_lLastError; + + default: + // Set the internal error code + m_lLastError = ::GetLastError(); + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Read - Unable to wait until data has been read\n"); + return m_lLastError; + } + } + } + else + { + // The operation completed immediatly. Just to be sure + // we'll set the overlapped structure's event handle. + if (lpOverlapped) + ::SetEvent(lpOverlapped->hEvent); + } + +#else + + // Read the data + if (!::ReadFile(m_hFile,pData,iLen,pdwRead,0)) + { + // Set the internal error code + m_lLastError = ::GetLastError(); + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n"); + return m_lLastError; + } + +#endif + + // Return successfully + return m_lLastError; +} + +LONG CSerial::Purge() +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Purge - Device is not opened\n"); + return m_lLastError; + } + + if (!::PurgeComm(m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR)) + { + // Set the internal error code + m_lLastError = ::GetLastError(); + _RPTF0(_CRT_WARN,"CSerial::Purge - Overlapped completed without result\n"); + } + + // Return successfully + return m_lLastError; +} + +LONG CSerial::Break (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::Break - Device is not opened\n"); + return m_lLastError; + } + + // Set the RS-232 port in break mode for a little while + ::SetCommBreak(m_hFile); + ::Sleep(100); + ::ClearCommBreak(m_hFile); + + // Return successfully + return m_lLastError; +} + +CSerial::EEvent CSerial::GetEventType (void) +{ +#ifdef _DEBUG + // Check if the event is within the mask + if ((m_eEvent & m_dwEventMask) == 0) + _RPTF2(_CRT_WARN,"CSerial::GetEventType - Event %08Xh not within mask %08Xh.\n", m_eEvent, m_dwEventMask); +#endif + + // Obtain the event (mask unwanted events out) + EEvent eEvent = EEvent(m_eEvent & m_dwEventMask); + + // Reset internal event type + m_eEvent = EEventNone; + + // Return the current cause + return eEvent; +} + +CSerial::EError CSerial::GetError (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Check if the device is open + if (m_hFile == 0) + { + // Set the internal error code + m_lLastError = ERROR_INVALID_HANDLE; + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetError - Device is not opened\n"); + return EErrorUnknown; + } + + // Obtain COM status + DWORD dwErrors = 0; + if (!::ClearCommError(m_hFile,&dwErrors,0)) + { + // Set the internal error code + m_lLastError = ::GetLastError(); + + // Issue an error and quit + _RPTF0(_CRT_WARN,"CSerial::GetError - Unable to obtain COM status\n"); + return EErrorUnknown; + } + + // Return the error + return EError(dwErrors); +} + +bool CSerial::GetCTS (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Obtain the modem status + DWORD dwModemStat = 0; + if (!::GetCommModemStatus(m_hFile,&dwModemStat)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetCTS - Unable to obtain the modem status\n"); + return false; + } + + // Determine if CTS is on + return (dwModemStat & MS_CTS_ON) != 0; +} + +bool CSerial::GetDSR (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Obtain the modem status + DWORD dwModemStat = 0; + if (!::GetCommModemStatus(m_hFile,&dwModemStat)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetDSR - Unable to obtain the modem status\n"); + return false; + } + + // Determine if DSR is on + return (dwModemStat & MS_DSR_ON) != 0; +} + +bool CSerial::GetRing (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Obtain the modem status + DWORD dwModemStat = 0; + if (!::GetCommModemStatus(m_hFile,&dwModemStat)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetRing - Unable to obtain the modem status"); + return false; + } + + // Determine if Ring is on + return (dwModemStat & MS_RING_ON) != 0; +} + +bool CSerial::GetRLSD (void) +{ + // Reset error state + m_lLastError = ERROR_SUCCESS; + + // Obtain the modem status + DWORD dwModemStat = 0; + if (!::GetCommModemStatus(m_hFile,&dwModemStat)) + { + // Obtain the error code + m_lLastError = ::GetLastError(); + + // Display a warning + _RPTF0(_CRT_WARN,"CSerial::GetRLSD - Unable to obtain the modem status"); + return false; + } + + // Determine if RLSD is on + return (dwModemStat & MS_RLSD_ON) != 0; +} diff --git a/liblo/ser-to-osc/Serial.h b/liblo/ser-to-osc/Serial.h new file mode 100644 index 0000000..c4d1879 --- /dev/null +++ b/liblo/ser-to-osc/Serial.h @@ -0,0 +1,367 @@ +// Serial.h - Definition of the CSerial class +// +// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl) +// +// This library 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 2.1 of the License, or (at your option) any later version. +// +// This library 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 library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +#ifndef __SERIAL_H +#define __SERIAL_H + + +////////////////////////////////////////////////////////////////////// +// The SERIAL_DEFAULT_OVERLAPPED defines if the default open mode uses +// overlapped I/O. When overlapped I/O is available (normal Win32 +// platforms) it uses overlapped I/O. Windows CE doesn't allow the use +// of overlapped I/O, so it is disabled there by default. + +#ifndef SERIAL_DEFAULT_OVERLAPPED +#ifndef SERIAL_NO_OVERLAPPED +#define SERIAL_DEFAULT_OVERLAPPED true +#else +#define SERIAL_DEFAULT_OVERLAPPED false +#endif +#endif + + +////////////////////////////////////////////////////////////////////// +// +// CSerial - Win32 wrapper for serial communications +// +// Serial communication often causes a lot of problems. This class +// tries to supply an easy to use interface to deal with serial +// devices. +// +// The class is actually pretty ease to use. You only need to open +// the COM-port, where you need to specify the basic serial +// communication parameters. You can also choose to setup handshaking +// and read timeout behaviour. +// +// The following serial classes are available: +// +// CSerial - Serial communication support. +// CSerialEx - Serial communication with listener thread for events +// CSerialSync - Serial communication with synchronized event handler +// CSerialWnd - Asynchronous serial support, which uses the Win32 +// message queue for event notification. +// CSerialMFC - Preferred class to use in MFC-based GUI windows. +// +// +// Pros: +// ----- +// - Easy to use (hides a lot of nasty Win32 stuff) +// - Fully ANSI and Unicode aware +// +// Cons: +// ----- +// - Little less flexibility then native Win32 API, however you can +// use this API at the same time for features which are missing +// from this class. +// - Incompatible with Windows 95 or Windows NT v3.51 (or earlier), +// because CancelIo isn't support on these platforms. Define the +// SERIAL_NO_CANCELIO macro for support of these platforms as +// well. When this macro is defined, then only time-out values of +// 0 or INFINITE are valid. +// +// +// Copyright (C) 1999-2003 Ramon de Klein +// (Ramon.de.Klein@ict.nl) + +class CSerial +{ +// Class enumerations +public: + // Communication event + typedef enum + { + EEventUnknown = -1, // Unknown event + EEventNone = 0, // Event trigged without cause + EEventBreak = EV_BREAK, // A break was detected on input + EEventCTS = EV_CTS, // The CTS signal changed state + EEventDSR = EV_DSR, // The DSR signal changed state + EEventError = EV_ERR, // A line-status error occurred + EEventRing = EV_RING, // A ring indicator was detected + EEventRLSD = EV_RLSD, // The RLSD signal changed state + EEventRecv = EV_RXCHAR, // Data is received on input + EEventRcvEv = EV_RXFLAG, // Event character was received on input + EEventSend = EV_TXEMPTY, // Last character on output was sent + EEventPrinterError = EV_PERR, // Printer error occured + EEventRx80Full = EV_RX80FULL, // Receive buffer is 80 percent full + EEventProviderEvt1 = EV_EVENT1, // Provider specific event 1 + EEventProviderEvt2 = EV_EVENT2, // Provider specific event 2 + } + EEvent; + + // Baudrate + typedef enum + { + EBaudUnknown = -1, // Unknown + EBaud110 = CBR_110, // 110 bits/sec + EBaud300 = CBR_300, // 300 bits/sec + EBaud600 = CBR_600, // 600 bits/sec + EBaud1200 = CBR_1200, // 1200 bits/sec + EBaud2400 = CBR_2400, // 2400 bits/sec + EBaud4800 = CBR_4800, // 4800 bits/sec + EBaud9600 = CBR_9600, // 9600 bits/sec + EBaud14400 = CBR_14400, // 14400 bits/sec + EBaud19200 = CBR_19200, // 19200 bits/sec (default) + EBaud38400 = CBR_38400, // 38400 bits/sec + EBaud56000 = CBR_56000, // 56000 bits/sec + EBaud57600 = CBR_57600, // 57600 bits/sec + EBaud115200 = CBR_115200, // 115200 bits/sec + EBaud128000 = CBR_128000, // 128000 bits/sec + EBaud256000 = CBR_256000, // 256000 bits/sec + } + EBaudrate; + + // Data bits (5-8) + typedef enum + { + EDataUnknown = -1, // Unknown + EData5 = 5, // 5 bits per byte + EData6 = 6, // 6 bits per byte + EData7 = 7, // 7 bits per byte + EData8 = 8 // 8 bits per byte (default) + } + EDataBits; + + // Parity scheme + typedef enum + { + EParUnknown = -1, // Unknown + EParNone = NOPARITY, // No parity (default) + EParOdd = ODDPARITY, // Odd parity + EParEven = EVENPARITY, // Even parity + EParMark = MARKPARITY, // Mark parity + EParSpace = SPACEPARITY // Space parity + } + EParity; + + // Stop bits + typedef enum + { + EStopUnknown = -1, // Unknown + EStop1 = ONESTOPBIT, // 1 stopbit (default) + EStop1_5 = ONE5STOPBITS,// 1.5 stopbit + EStop2 = TWOSTOPBITS // 2 stopbits + } + EStopBits; + + // Handshaking + typedef enum + { + EHandshakeUnknown = -1, // Unknown + EHandshakeOff = 0, // No handshaking + EHandshakeHardware = 1, // Hardware handshaking (RTS/CTS) + EHandshakeSoftware = 2 // Software handshaking (XON/XOFF) + } + EHandshake; + + // Timeout settings + typedef enum + { + EReadTimeoutUnknown = -1, // Unknown + EReadTimeoutNonblocking = 0, // Always return immediately + EReadTimeoutBlocking = 1 // Block until everything is retrieved + } + EReadTimeout; + + // Communication errors + typedef enum + { + EErrorUnknown = 0, // Unknown + EErrorBreak = CE_BREAK, // Break condition detected + EErrorFrame = CE_FRAME, // Framing error + EErrorIOE = CE_IOE, // I/O device error + EErrorMode = CE_MODE, // Unsupported mode + EErrorOverrun = CE_OVERRUN, // Character buffer overrun, next byte is lost + EErrorRxOver = CE_RXOVER, // Input buffer overflow, byte lost + EErrorParity = CE_RXPARITY,// Input parity error + EErrorTxFull = CE_TXFULL // Output buffer full + } + EError; + + // Port availability + typedef enum + { + EPortUnknownError = -1, // Unknown error occurred + EPortAvailable = 0, // Port is available + EPortNotAvailable = 1, // Port is not present + EPortInUse = 2 // Port is in use + + } + EPort; + +// Construction +public: + CSerial(); + virtual ~CSerial(); + +// Operations +public: + // Check if particular COM-port is available (static method). + static EPort CheckPort (LPCTSTR lpszDevice); + + // Open the serial communications for a particular COM port. You + // need to use the full devicename (i.e. "COM1") to open the port. + // It's possible to specify the size of the input/output queues. + virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED); + + // Close the serial port. + virtual LONG Close (void); + + // Setup the communication settings such as baudrate, databits, + // parity and stopbits. The default settings are applied when the + // device has been opened. Call this function if these settings do + // not apply for your application. If you prefer to use integers + // instead of the enumerated types then just cast the integer to + // the required type. So the following two initializations are + // equivalent: + // + // Setup(EBaud9600,EData8,EParNone,EStop1) + // + // or + // + // Setup(EBaudrate(9600),EDataBits(8),EParity(NOPARITY),EStopBits(ONESTOPBIT)) + // + // In the latter case, the types are not validated. So make sure + // that you specify the appropriate values. + virtual LONG Setup (EBaudrate eBaudrate = EBaud9600, + EDataBits eDataBits = EData8, + EParity eParity = EParNone, + EStopBits eStopBits = EStop1); + + // Set/clear the event character. When this byte is being received + // on the serial port then the EEventRcvEv event is signalled, + // when the mask has been set appropriately. If the fAdjustMask flag + // has been set, then the event mask is automatically adjusted. + virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true); + + // Set the event mask, which indicates what events should be + // monitored. The WaitEvent method can only monitor events that + // have been enabled. The default setting only monitors the + // error events and data events. An application may choose to + // monitor CTS. DSR, RLSD, etc as well. + virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv); + + // The WaitEvent method waits for one of the events that are + // enabled (see SetMask). + virtual LONG WaitEvent (LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); + + // Setup the handshaking protocol. There are three forms of + // handshaking: + // + // 1) No handshaking, so data is always send even if the receiver + // cannot handle the data anymore. This can lead to data loss, + // when the sender is able to transmit data faster then the + // receiver can handle. + // 2) Hardware handshaking, where the RTS/CTS lines are used to + // indicate if data can be sent. This mode requires that both + // ports and the cable support hardware handshaking. Hardware + // handshaking is the most reliable and efficient form of + // handshaking available, but is hardware dependant. + // 3) Software handshaking, where the XON/XOFF characters are used + // to throttle the data. A major drawback of this method is that + // these characters cannot be used for data anymore. + virtual LONG SetupHandshaking (EHandshake eHandshake); + + // Read operations can be blocking or non-blocking. You can use + // this method to setup wether to use blocking or non-blocking + // reads. Non-blocking reads is the default, which is required + // for most applications. + // + // 1) Blocking reads, which will cause the 'Read' method to block + // until the requested number of bytes have been read. This is + // useful if you know how many data you will receive. + // 2) Non-blocking reads, which will read as many bytes into your + // buffer and returns almost immediately. This is often the + // preferred setting. + virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout); + + // Obtain communication settings + virtual EBaudrate GetBaudrate (void); + virtual EDataBits GetDataBits (void); + virtual EParity GetParity (void); + virtual EStopBits GetStopBits (void); + virtual EHandshake GetHandshaking (void); + virtual DWORD GetEventMask (void); + virtual BYTE GetEventChar (void); + + // Write data to the serial port. Note that we are only able to + // send ANSI strings, because it probably doesn't make sense to + // transmit Unicode strings to an application. + virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); + virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); + + // Read data from the serial port. Refer to the description of + // the 'SetupReadTimeouts' for an explanation about (non) blocking + // reads and how to use this. + virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); + + // Send a break + LONG Break (void); + + // Determine what caused the event to trigger + EEvent GetEventType (void); + + // Obtain the error + EError GetError (void); + + // Obtain the COMM and event handle + HANDLE GetCommHandle (void) { return m_hFile; } + + // Check if com-port is opened + bool IsOpen (void) const { return (m_hFile != 0); } + + // Obtain last error status + LONG GetLastError (void) const { return m_lLastError; } + + // Obtain CTS/DSR/RING/RLSD settings + bool GetCTS (void); + bool GetDSR (void); + bool GetRing (void); + bool GetRLSD (void); + + // Purge all buffers + LONG Purge (void); + +protected: + // Internal helper class which wraps DCB structure + class CDCB : public DCB + { + public: + CDCB() { DCBlength = sizeof(DCB); } + }; + +// Attributes +protected: + LONG m_lLastError; // Last serial error + HANDLE m_hFile; // File handle + EEvent m_eEvent; // Event type + DWORD m_dwEventMask; // Event mask + +#ifndef SERIAL_NO_OVERLAPPED + HANDLE m_hevtOverlapped; // Event handle for internal overlapped operations +#endif + +protected: + // Check the requirements + void CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const; + + // CancelIo wrapper (for Win95 compatibility) + BOOL CancelCommIo (void); +}; + +#endif // __SERIAL_H diff --git a/liblo/ser-to-osc/ser-to-osc.cpp b/liblo/ser-to-osc/ser-to-osc.cpp new file mode 100644 index 0000000..db81b51 --- /dev/null +++ b/liblo/ser-to-osc/ser-to-osc.cpp @@ -0,0 +1,245 @@ +/* + * ser-to-osc.cpp -- Roger Dannenberg, 2006 + * + * Usage: ser-to-osc inputdevice + * + * Note: this is C++ only because the Windows version uses the Serial class + * for USB-Serial I/O. Hopefully compiling this as C++ will not cause + * problems on Mac and Linux. + * + */ + +#include +#include +#ifdef WIN32 +#else +#include +#include +#include "string.h" +#endif + +#define _WIN32_WINNT 0x1000 +#include "lo/lo.h" + +#ifdef WIN32 +#include "Serial.h" + +enum { EOF_Char = 27 }; + +CSerial serial; + +typedef CSerial *port_type; + +#define MAX_LINE 256 +char inp_line[MAX_LINE]; +int inp_len; + +CSerial *port_open(char *inputname) +{ + LONG lLastError = serial.Open(inputname, 0, 0, false); + if (lLastError != ERROR_SUCCESS) return NULL; + // Setup the serial port (9600,8N1, which is the default setting) + lLastError = serial.Setup(CSerial::EBaud9600, CSerial::EData8, + CSerial::EParNone, CSerial::EStop1); + if (lLastError != ERROR_SUCCESS) return NULL; + // Register only for the receive event + lLastError = serial.SetMask(CSerial::EEventBreak | + CSerial::EEventCTS | + CSerial::EEventDSR | + CSerial::EEventError | + CSerial::EEventRing | + CSerial::EEventRLSD | + CSerial::EEventRecv); + if (lLastError != ERROR_SUCCESS) return NULL; + // Use 'non-blocking' reads, because we don't know how many bytes + // will be received. This is normally the most convenient mode + // (and also the default mode for reading data). + lLastError = serial.SetupReadTimeouts(CSerial::EReadTimeoutNonblocking); + if (lLastError != ERROR_SUCCESS) return NULL; + inp_len = 0; + return &serial; +} + + +char *port_getln(CSerial *serial, size_t *len_ptr) +{ + // Keep reading data, until an EOF (CTRL-Z) has been received + bool done = false; + LONG lLastError; + *len_ptr = 0; + while (!done) { + // Wait for an event + lLastError = serial->WaitEvent(); + if (lLastError != ERROR_SUCCESS) return NULL; + // Save event + const CSerial::EEvent eEvent = serial->GetEventType(); + // Handle break event + if (eEvent & CSerial::EEventBreak) { + // printf("\n### BREAK received ###\n"); + } + // Handle CTS event + if (eEvent & CSerial::EEventCTS) { + // printf("\n### Clear to send %s ###\n", serial->GetCTS()?"on":"off"); + } + // Handle DSR event + if (eEvent & CSerial::EEventDSR) { + // printf("\n### Data set ready %s ###\n", serial->GetDSR()?"on":"off"); + } + // Handle error event + if (eEvent & CSerial::EEventError) { + printf("\n### ERROR: "); + switch (serial->GetError()) { + case CSerial::EErrorBreak: + printf("Break condition"); + break; + case CSerial::EErrorFrame: + printf("Framing error"); + break; + case CSerial::EErrorIOE: + printf("IO device error"); + break; + case CSerial::EErrorMode: + printf("Unsupported mode"); + break; + case CSerial::EErrorOverrun: + printf("Buffer overrun"); + break; + case CSerial::EErrorRxOver: + printf("Input buffer overflow"); + break; + case CSerial::EErrorParity: + printf("Input parity error"); + break; + case CSerial::EErrorTxFull: + printf("Output buffer full"); + break; + default: + printf("Unknown"); + break; + } + printf(" ###\n"); + } + + // Handle ring event + if (eEvent & CSerial::EEventRing) { + // printf("\n### RING ###\n"); + } + // Handle RLSD/CD event + if (eEvent & CSerial::EEventRLSD) { + // printf("\n### RLSD/CD %s ###\n", serial->GetRLSD()?"on":"off"); + } + // Handle data receive event + if (eEvent & CSerial::EEventRecv) { + // Read data, until there is nothing left + while (true) { + // Read data from the COM-port + DWORD dwBytesRead = 0; + lLastError = serial->Read(inp_line + inp_len, 1, &dwBytesRead); + if (lLastError != ERROR_SUCCESS) return NULL; + if (dwBytesRead == 0) break; + // printf("Read %c (%d)\n", inp_line[inp_len], inp_line[inp_len]); + if (inp_line[inp_len] == '\n' || + // inp_line[inp_len] == '\r' || + inp_line[inp_len] == EOF_Char || + inp_len >= MAX_LINE - 2) { + inp_line[inp_len + 1] = '\0'; + *len_ptr = inp_len + 1; + inp_len = 0; + done = true; + break; + } + inp_len++; + } + } + } + return inp_line; +} + + +void port_close(CSerial *serial) +{ + serial->Close(); +} + + +#else +typedef FILE *port_type; + +FILE *port_open(char *inputname) +{ + return fopen(inputname, "r"); +} + +char *port_getln(FILE *input, size_t *len_ptr) +{ + // linux does not have fgetln (must be bsd only) + // return fgetln(input, len_ptr); + static char line[256]; + char *result = fgets(line, 256, input); + if (result) *len_ptr = strlen(line); + return result; +} + +void port_close(FILE *input) +{ + fclose(input); +} +#endif + +int main(int argc, char *argv[]) +{ + /* an address to send messages to. sometimes it is better to let the server + * pick a port number for you by passing NULL as the last argument */ + lo_address t = lo_address_new(NULL, "7770"); + char *inputname = NULL; + port_type input = NULL; + int verbose = 1; + int argptr = 1; + while (argptr < argc) { + char *arg = argv[argptr]; + if (*arg == '-') { + if (arg[1] == 'q') { + verbose = 0; + } + } else if (!inputname) { + inputname = arg; + } + argptr++; + } + if (inputname) input = port_open(inputname); + if (!input) { + printf("Could not open %s\n", inputname); + exit(EXIT_FAILURE); + } + + /* send messages to /slider with two arguments, report any errors */ + while (1) { + /* get input data, report errors */ + size_t len; + char *s = port_getln(input, &len); + int slider_no, value; + float x; + char channel[64]; /* buffer to hold "Channel" */ + if (!s) exit(EXIT_SUCCESS); + /* we don't need the newline, but we do want an EOS */ + s[len - 1] = 0; + len--; + while (isspace(s[len - 1])) s[--len] = 0; /* trim white space */ + if (verbose) printf("%s: ", s); + if (sscanf(s, "%s %d %d", channel, &slider_no, &value) != 3) { + puts("Error: expected 2 integers\n"); + fflush(stdout); + } + x = value / 255.0F; + if (x > 1) x = 1; + if (x < 0) x = 0; + if (verbose) printf("/slider %d %g\n", slider_no, x); + if (lo_send(t, "/slider", "if", slider_no, x) == -1) { + printf("OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t)); + break; + } + } + port_close(input); + return 0; /* make compiler happy */ +} + diff --git a/liblo/ser-to-osc/ser-to-osc.vcproj b/liblo/ser-to-osc/ser-to-osc.vcproj new file mode 100644 index 0000000..3730b80 --- /dev/null +++ b/liblo/ser-to-osc/ser-to-osc.vcproj @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblo/src/Makefile.am b/liblo/src/Makefile.am new file mode 100644 index 0000000..2e3c02e --- /dev/null +++ b/liblo/src/Makefile.am @@ -0,0 +1,33 @@ +SUBDIRS = . tools + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = liblo.def + +noinst_HEADERS = lo_types_internal.h lo_internal.h + +SOURCE_FILES = address.c send.c message.c server.c method.c \ + server_thread.c blob.c bundle.c timetag.c pattern_match.c + +lib_LTLIBRARIES = liblo.la + +liblo_la_CFLAGS = -Wall -I$(top_srcdir) +liblo_la_SOURCES = $(SOURCE_FILES) +liblo_la_LIBADD = -lpthread +liblo_la_LDFLAGS = -export-dynamic -version-info @LO_SO_VERSION@ + +noinst_PROGRAMS = testlo subtest + +testlo_CFLAGS = -Wall -I$(top_srcdir) +testlo_SOURCES = testlo.c +testlo_LDADD = liblo.la + +subtest_CFLAGS = -Wall -I$(top_srcdir) +subtest_SOURCES = subtest.c +subtest_LDADD = liblo.la + +test: all + ./testlo + +memtest: all + LD_LIBRARY_PATH=.libs valgrind --tool=memcheck .libs/testlo diff --git a/liblo/src/Makefile.in b/liblo/src/Makefile.in new file mode 100644 index 0000000..e15ce8a --- /dev/null +++ b/liblo/src/Makefile.in @@ -0,0 +1,842 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = testlo$(EXEEXT) subtest$(EXEEXT) +subdir = src +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +liblo_la_DEPENDENCIES = +am__objects_1 = liblo_la-address.lo liblo_la-send.lo \ + liblo_la-message.lo liblo_la-server.lo liblo_la-method.lo \ + liblo_la-server_thread.lo liblo_la-blob.lo liblo_la-bundle.lo \ + liblo_la-timetag.lo liblo_la-pattern_match.lo +am_liblo_la_OBJECTS = $(am__objects_1) +liblo_la_OBJECTS = $(am_liblo_la_OBJECTS) +liblo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(liblo_la_CFLAGS) $(CFLAGS) \ + $(liblo_la_LDFLAGS) $(LDFLAGS) -o $@ +PROGRAMS = $(noinst_PROGRAMS) +am_subtest_OBJECTS = subtest-subtest.$(OBJEXT) +subtest_OBJECTS = $(am_subtest_OBJECTS) +subtest_DEPENDENCIES = liblo.la +subtest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(subtest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_testlo_OBJECTS = testlo-testlo.$(OBJEXT) +testlo_OBJECTS = $(am_testlo_OBJECTS) +testlo_DEPENDENCIES = liblo.la +testlo_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(testlo_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(liblo_la_SOURCES) $(subtest_SOURCES) $(testlo_SOURCES) +DIST_SOURCES = $(liblo_la_SOURCES) $(subtest_SOURCES) \ + $(testlo_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +HEADERS = $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LO_SO_VERSION = @LO_SO_VERSION@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = . tools +MAINTAINERCLEANFILES = Makefile.in +EXTRA_DIST = liblo.def +noinst_HEADERS = lo_types_internal.h lo_internal.h +SOURCE_FILES = address.c send.c message.c server.c method.c \ + server_thread.c blob.c bundle.c timetag.c pattern_match.c + +lib_LTLIBRARIES = liblo.la +liblo_la_CFLAGS = -Wall -I$(top_srcdir) +liblo_la_SOURCES = $(SOURCE_FILES) +liblo_la_LIBADD = -lpthread +liblo_la_LDFLAGS = -export-dynamic -version-info @LO_SO_VERSION@ +testlo_CFLAGS = -Wall -I$(top_srcdir) +testlo_SOURCES = testlo.c +testlo_LDADD = liblo.la +subtest_CFLAGS = -Wall -I$(top_srcdir) +subtest_SOURCES = subtest.c +subtest_LDADD = liblo.la +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +liblo.la: $(liblo_la_OBJECTS) $(liblo_la_DEPENDENCIES) + $(liblo_la_LINK) -rpath $(libdir) $(liblo_la_OBJECTS) $(liblo_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +subtest$(EXEEXT): $(subtest_OBJECTS) $(subtest_DEPENDENCIES) + @rm -f subtest$(EXEEXT) + $(subtest_LINK) $(subtest_OBJECTS) $(subtest_LDADD) $(LIBS) +testlo$(EXEEXT): $(testlo_OBJECTS) $(testlo_DEPENDENCIES) + @rm -f testlo$(EXEEXT) + $(testlo_LINK) $(testlo_OBJECTS) $(testlo_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-address.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-blob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-bundle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-method.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-pattern_match.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-send.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-server.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-server_thread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblo_la-timetag.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subtest-subtest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testlo-testlo.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +liblo_la-address.lo: address.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-address.lo -MD -MP -MF $(DEPDIR)/liblo_la-address.Tpo -c -o liblo_la-address.lo `test -f 'address.c' || echo '$(srcdir)/'`address.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-address.Tpo $(DEPDIR)/liblo_la-address.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='address.c' object='liblo_la-address.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-address.lo `test -f 'address.c' || echo '$(srcdir)/'`address.c + +liblo_la-send.lo: send.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-send.lo -MD -MP -MF $(DEPDIR)/liblo_la-send.Tpo -c -o liblo_la-send.lo `test -f 'send.c' || echo '$(srcdir)/'`send.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-send.Tpo $(DEPDIR)/liblo_la-send.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='send.c' object='liblo_la-send.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-send.lo `test -f 'send.c' || echo '$(srcdir)/'`send.c + +liblo_la-message.lo: message.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-message.lo -MD -MP -MF $(DEPDIR)/liblo_la-message.Tpo -c -o liblo_la-message.lo `test -f 'message.c' || echo '$(srcdir)/'`message.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-message.Tpo $(DEPDIR)/liblo_la-message.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='message.c' object='liblo_la-message.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-message.lo `test -f 'message.c' || echo '$(srcdir)/'`message.c + +liblo_la-server.lo: server.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-server.lo -MD -MP -MF $(DEPDIR)/liblo_la-server.Tpo -c -o liblo_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-server.Tpo $(DEPDIR)/liblo_la-server.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='server.c' object='liblo_la-server.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c + +liblo_la-method.lo: method.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-method.lo -MD -MP -MF $(DEPDIR)/liblo_la-method.Tpo -c -o liblo_la-method.lo `test -f 'method.c' || echo '$(srcdir)/'`method.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-method.Tpo $(DEPDIR)/liblo_la-method.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='method.c' object='liblo_la-method.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-method.lo `test -f 'method.c' || echo '$(srcdir)/'`method.c + +liblo_la-server_thread.lo: server_thread.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-server_thread.lo -MD -MP -MF $(DEPDIR)/liblo_la-server_thread.Tpo -c -o liblo_la-server_thread.lo `test -f 'server_thread.c' || echo '$(srcdir)/'`server_thread.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-server_thread.Tpo $(DEPDIR)/liblo_la-server_thread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='server_thread.c' object='liblo_la-server_thread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-server_thread.lo `test -f 'server_thread.c' || echo '$(srcdir)/'`server_thread.c + +liblo_la-blob.lo: blob.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-blob.lo -MD -MP -MF $(DEPDIR)/liblo_la-blob.Tpo -c -o liblo_la-blob.lo `test -f 'blob.c' || echo '$(srcdir)/'`blob.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-blob.Tpo $(DEPDIR)/liblo_la-blob.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='blob.c' object='liblo_la-blob.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-blob.lo `test -f 'blob.c' || echo '$(srcdir)/'`blob.c + +liblo_la-bundle.lo: bundle.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-bundle.lo -MD -MP -MF $(DEPDIR)/liblo_la-bundle.Tpo -c -o liblo_la-bundle.lo `test -f 'bundle.c' || echo '$(srcdir)/'`bundle.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-bundle.Tpo $(DEPDIR)/liblo_la-bundle.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bundle.c' object='liblo_la-bundle.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-bundle.lo `test -f 'bundle.c' || echo '$(srcdir)/'`bundle.c + +liblo_la-timetag.lo: timetag.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-timetag.lo -MD -MP -MF $(DEPDIR)/liblo_la-timetag.Tpo -c -o liblo_la-timetag.lo `test -f 'timetag.c' || echo '$(srcdir)/'`timetag.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-timetag.Tpo $(DEPDIR)/liblo_la-timetag.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='timetag.c' object='liblo_la-timetag.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-timetag.lo `test -f 'timetag.c' || echo '$(srcdir)/'`timetag.c + +liblo_la-pattern_match.lo: pattern_match.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -MT liblo_la-pattern_match.lo -MD -MP -MF $(DEPDIR)/liblo_la-pattern_match.Tpo -c -o liblo_la-pattern_match.lo `test -f 'pattern_match.c' || echo '$(srcdir)/'`pattern_match.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liblo_la-pattern_match.Tpo $(DEPDIR)/liblo_la-pattern_match.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pattern_match.c' object='liblo_la-pattern_match.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblo_la_CFLAGS) $(CFLAGS) -c -o liblo_la-pattern_match.lo `test -f 'pattern_match.c' || echo '$(srcdir)/'`pattern_match.c + +subtest-subtest.o: subtest.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(subtest_CFLAGS) $(CFLAGS) -MT subtest-subtest.o -MD -MP -MF $(DEPDIR)/subtest-subtest.Tpo -c -o subtest-subtest.o `test -f 'subtest.c' || echo '$(srcdir)/'`subtest.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/subtest-subtest.Tpo $(DEPDIR)/subtest-subtest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='subtest.c' object='subtest-subtest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(subtest_CFLAGS) $(CFLAGS) -c -o subtest-subtest.o `test -f 'subtest.c' || echo '$(srcdir)/'`subtest.c + +subtest-subtest.obj: subtest.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(subtest_CFLAGS) $(CFLAGS) -MT subtest-subtest.obj -MD -MP -MF $(DEPDIR)/subtest-subtest.Tpo -c -o subtest-subtest.obj `if test -f 'subtest.c'; then $(CYGPATH_W) 'subtest.c'; else $(CYGPATH_W) '$(srcdir)/subtest.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/subtest-subtest.Tpo $(DEPDIR)/subtest-subtest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='subtest.c' object='subtest-subtest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(subtest_CFLAGS) $(CFLAGS) -c -o subtest-subtest.obj `if test -f 'subtest.c'; then $(CYGPATH_W) 'subtest.c'; else $(CYGPATH_W) '$(srcdir)/subtest.c'; fi` + +testlo-testlo.o: testlo.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testlo_CFLAGS) $(CFLAGS) -MT testlo-testlo.o -MD -MP -MF $(DEPDIR)/testlo-testlo.Tpo -c -o testlo-testlo.o `test -f 'testlo.c' || echo '$(srcdir)/'`testlo.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/testlo-testlo.Tpo $(DEPDIR)/testlo-testlo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testlo.c' object='testlo-testlo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testlo_CFLAGS) $(CFLAGS) -c -o testlo-testlo.o `test -f 'testlo.c' || echo '$(srcdir)/'`testlo.c + +testlo-testlo.obj: testlo.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testlo_CFLAGS) $(CFLAGS) -MT testlo-testlo.obj -MD -MP -MF $(DEPDIR)/testlo-testlo.Tpo -c -o testlo-testlo.obj `if test -f 'testlo.c'; then $(CYGPATH_W) 'testlo.c'; else $(CYGPATH_W) '$(srcdir)/testlo.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/testlo-testlo.Tpo $(DEPDIR)/testlo-testlo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testlo.c' object='testlo-testlo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testlo_CFLAGS) $(CFLAGS) -c -o testlo-testlo.obj `if test -f 'testlo.c'; then $(CYGPATH_W) 'testlo.c'; else $(CYGPATH_W) '$(srcdir)/testlo.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-libLTLIBRARIES + + +test: all + ./testlo + +memtest: all + LD_LIBRARY_PATH=.libs valgrind --tool=memcheck .libs/testlo + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/liblo/src/address.c b/liblo/src/address.c new file mode 100644 index 0000000..3620353 --- /dev/null +++ b/liblo/src/address.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#define snprintf _snprintf +#else +#include +#endif + +#ifdef WIN32 +#include +#include +#else +#include +#include +#endif + +#include "lo_types_internal.h" +#include "lo/lo.h" +#include "config.h" + +lo_address lo_address_new_with_proto(int proto, const char *host, const char *port) +{ + lo_address a; + + if(proto != LO_UDP && proto != LO_TCP && proto != LO_UNIX) return NULL; + + a = calloc(1, sizeof(struct _lo_address)); + if(a == NULL) return NULL; + + a->ai = NULL; + a->socket = -1; + a->protocol = proto; + switch(proto) { + default: + case LO_UDP: + case LO_TCP: + if (host) { + a->host = strdup(host); + } else { + a->host = strdup("localhost"); + } + break; + case LO_UNIX: + a->host = strdup("localhost"); + break; + } + if (port) { + a->port = strdup(port); + } else { + a->port = NULL; + } + + a->ttl = -1; + + return a; +} + +lo_address lo_address_new(const char *host, const char *port) +{ + return lo_address_new_with_proto(LO_UDP, host ,port); +} + +lo_address lo_address_new_from_url(const char *url) +{ + lo_address a; + int protocol; + char *host, *port, *proto; + + if (!url || !*url) { + return NULL; + } + + protocol = lo_url_get_protocol_id(url); + if (protocol == LO_UDP || protocol == LO_TCP) { + host = lo_url_get_hostname(url); + port = lo_url_get_port(url); + a = lo_address_new_with_proto(protocol, host, port); + if(host) free(host); + if(port) free(port); +#ifndef WIN32 + } else if (protocol == LO_UNIX) { + port = lo_url_get_path(url); + a = lo_address_new_with_proto(LO_UNIX, NULL, port); + if(port) free(port); +#endif + } else { + proto = lo_url_get_protocol(url); + fprintf(stderr, PACKAGE_NAME ": protocol '%s' not supported by this " + "version\n", proto); + if(proto) free(proto); + + return NULL; + } + + return a; +} + +const char *lo_address_get_hostname(lo_address a) +{ + if (!a) { + return NULL; + } + + return a->host; +} + +int lo_address_get_protocol(lo_address a) +{ + if (!a) { + return -1; + } + + return a->protocol; +} + +const char *lo_address_get_port(lo_address a) +{ + if (!a) { + return NULL; + } + + return a->port; +} + +static const char* get_protocol_name(int proto) +{ + switch(proto) { + case LO_UDP: + return "udp"; + case LO_TCP: + return "tcp"; +#ifndef WIN32 + case LO_UNIX: + return "unix"; +#endif + } + return NULL; +} + + +char *lo_address_get_url(lo_address a) +{ + char *buf; + int ret=0; + int needquote = strchr(a->host, ':') ? 1 : 0; + char *fmt; + + if (needquote) { + fmt = "osc.%s://[%s]:%s/"; + } else { + fmt = "osc.%s://%s:%s/"; + } +#ifndef _MSC_VER + ret = snprintf(NULL, 0, fmt, + get_protocol_name(a->protocol), a->host, a->port); +#endif + if (ret <= 0) { + /* this libc is not C99 compliant, guess a size */ + ret = 1023; + } + buf = malloc((ret + 2) * sizeof(char)); + snprintf(buf, ret+1, fmt, + get_protocol_name(a->protocol), a->host, a->port); + + return buf; +} + +void lo_address_free(lo_address a) +{ + if (a) { + if (a->socket != -1) { + close(a->socket); + } + if (a->host) free(a->host); + if (a->port) free(a->port); + if (a->ai) freeaddrinfo(a->ai); + free(a); + } +} + +int lo_address_errno(lo_address a) +{ + return a->errnum; +} + +const char *lo_address_errstr(lo_address a) +{ + char *msg; + + if (a->errstr) { + return a->errstr; + } + + msg = strerror(a->errnum); + if (msg) { + return msg; + } else { + return "unknown error"; + } + + return "unknown error"; +} + +char *lo_url_get_protocol(const char *url) +{ + char *protocol,*ret; + + if (!url) { + return NULL; + } + + protocol = malloc(strlen(url)); + + if (sscanf(url, "osc://%s", protocol)) { + fprintf(stderr, PACKAGE_NAME " warning: no protocol specified in URL, " + "assuming UDP.\n"); + ret = strdup("udp"); + } else if (sscanf(url, "osc.%[^:/[]", protocol)) { + ret = strdup(protocol); + } else { + ret = NULL; + } + + free(protocol); + + return ret; +} + +int lo_url_get_protocol_id(const char *url) +{ + if(!url) { + return -1; + } + + if(!strncmp(url, "osc:", 4)) { + fprintf(stderr, PACKAGE_NAME " warning: no protocol specified in URL, " + "assuming UDP.\n"); + return LO_UDP; // should be LO_DEFAULT? + } else if(!strncmp(url, "osc.udp:", 8)) { + return LO_UDP; + } else if(!strncmp(url, "osc.tcp:", 8)) { + return LO_TCP; + } else if(!strncmp(url, "osc.unix:", 9)) { + return LO_UNIX; + } + return -1; +} + +char *lo_url_get_hostname(const char *url) +{ + char *hostname = malloc(strlen(url)); + + if (sscanf(url, "osc://%[^[:/]", hostname)) { + return hostname; + } + if (sscanf(url, "osc.%*[^:/]://[%[^]/]]", hostname)) { + return hostname; + } + if (sscanf(url, "osc.%*[^:/]://%[^[:/]", hostname)) { + return hostname; + } + + /* doesnt look like an OSC URL */ + free(hostname); + + return NULL; +} + +char *lo_url_get_port(const char *url) +{ + char *port = malloc(strlen(url)); + + if (sscanf(url, "osc://%*[^:]:%[0-9]", port)) { + return port; + } + if (sscanf(url, "osc.%*[^:]://%*[^:]:%[0-9]", port)) { + return port; + } + if (sscanf(url, "osc://[%*[^]]]:%[0-9]", port)) { + return port; + } + if (sscanf(url, "osc.%*[^:]://[%*[^]]]:%[0-9]", port)) { + return port; + } + + /* doesnt look like an OSC URL with port number */ + free(port); + + return NULL; +} + +char *lo_url_get_path(const char *url) +{ + char *path = malloc(strlen(url)); + + if (sscanf(url, "osc://%*[^:]:%*[0-9]%s", path)) { + return path; + } + if (sscanf(url, "osc.%*[^:]://%*[^:]:%*[0-9]%s", path) == 1) { + return path; + } + if (sscanf(url, "osc.unix://%*[^/]%s", path) == 1) { + return path; + } + if (sscanf(url, "osc.%*[^:]://%s", path)) { + return path; + } + + /* doesnt look like an OSC URL with port number and path*/ + free(path); + + return NULL; +} + +void lo_address_set_ttl(lo_address t, int ttl) +{ + if (t->protocol == LO_UDP) + t->ttl = ttl; +} + +int lo_address_get_ttl(lo_address t) +{ + return t->ttl; +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/blob.c b/liblo/src/blob.c new file mode 100644 index 0000000..3ff7d87 --- /dev/null +++ b/liblo/src/blob.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include + +#include "lo_types_internal.h" +#include "lo/lo.h" + +lo_blob lo_blob_new(int32_t size, const void *data) +{ + lo_blob b; + + if (size < 1) { + return NULL; + } + + b = malloc(sizeof(size) + size); + + b->size = size; + + if (data) { + memcpy((char*)b + sizeof(uint32_t), data, size); + } + + return b; +} + +void lo_blob_free(lo_blob b) +{ + free(b); +} + +uint32_t lo_blob_datasize(lo_blob b) +{ + return b->size; +} + +void *lo_blob_dataptr(lo_blob b) +{ + return (char*)b + sizeof(uint32_t); +} + +uint32_t lo_blobsize(lo_blob b) +{ + const uint32_t len = sizeof(uint32_t) + b->size; + + return 4 * (len / 4 + 1); +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/bundle.c b/liblo/src/bundle.c new file mode 100644 index 0000000..7539018 --- /dev/null +++ b/liblo/src/bundle.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include + +#include "lo_types_internal.h" +#include "lo/lo.h" + +lo_bundle lo_bundle_new(lo_timetag tt) +{ + lo_bundle b = calloc(1, sizeof(struct _lo_bundle)); + + b->size = 4; + b->len = 0; + b->ts = tt; + b->msgs = calloc(b->size, sizeof(lo_message)); + b->paths = calloc(b->size, sizeof(char *)); + + return b; +} + +int lo_bundle_add_message(lo_bundle b, const char *path, lo_message m) +{ + if (!m) + return 0; + + if (b->len >= b->size) { + b->size *= 2; + b->msgs = realloc(b->msgs, b->size * sizeof(lo_message)); + b->paths = realloc(b->paths, b->size * sizeof(char *)); + if (!b->msgs || !b->paths) + return -1; + } + + b->msgs[b->len] = m; + b->paths[b->len] = (char *)path; + + (b->len)++; + return 0; +} + +size_t lo_bundle_length(lo_bundle b) +{ + size_t size = 16; /* "#bundle" and the timetag */ + int i; + + if (!b) { + return 0; + } + + size += b->len * 4; /* sizes */ + for (i = 0; i < b->len; i++) { + size += lo_message_length(b->msgs[i], b->paths[i]); + } + + return size; +} + +void *lo_bundle_serialise(lo_bundle b, void *to, size_t *size) +{ + size_t s, skip; + int32_t *bes; + int i; + char *pos; + lo_pcast32 be; + + if (!b) { + return NULL; + } + + s = lo_bundle_length(b); + if (size) { + *size = s; + } + + if (!to) { + to = calloc(1, s); + } + + pos = to; + strcpy(pos, "#bundle"); + pos += 8; + + be.nl = lo_htoo32(b->ts.sec); + memcpy(pos, &be, 4); + pos += 4; + be.nl = lo_htoo32(b->ts.frac); + memcpy(pos, &be, 4); + pos += 4; + + for (i = 0; i < b->len; i++) { + lo_message_serialise(b->msgs[i], b->paths[i], pos + 4, &skip); + bes = (int32_t *)pos; + *bes = lo_htoo32(skip); + pos += skip + 4; + + if (pos > (char *)to + s) { + fprintf(stderr, "liblo: data integrity error at message %d\n", i); + + return NULL; + } + } + if (pos != (char*)to + s) { + fprintf(stderr, "liblo: data integrity error\n"); + + return NULL; + } + + return to; +} + +void lo_bundle_free(lo_bundle b) +{ + if (!b) { + return; + } + + free(b->msgs); + free(b->paths); + free(b); +} + +static int _lo_internal_compare_ptrs( const void* a, const void* b ) +{ + if (*(void**)a < *(void**)b) return -1; + if (*(void**)a == *(void**)b) return 0; + return 1; +} + +void lo_bundle_free_messages(lo_bundle b) +{ + int i; + lo_message tmp = 0; + + if (!b) + return; + + /* avoid freeing the same message twice */ + if (b->len > 2) + qsort(b->msgs, b->len, sizeof(lo_message*), _lo_internal_compare_ptrs); + + for(i = 0; i < b->len; i++) { + if (b->msgs[i] != tmp) { + tmp = b->msgs[i]; + lo_message_free(b->msgs[i]); + } + } + free(b->msgs); + free(b->paths); + free(b); +} + +void lo_bundle_pp(lo_bundle b) +{ + int i; + + if (!b) return; + + printf("bundle(%f):\n", (double)b->ts.sec + b->ts.frac / 4294967296.0); + for (i = 0; i < b->len; i++) { + lo_message_pp(b->msgs[i]); + } + printf("\n"); +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/liblo.def b/liblo/src/liblo.def new file mode 100644 index 0000000..1d422ad --- /dev/null +++ b/liblo/src/liblo.def @@ -0,0 +1,113 @@ + +DESCRIPTION 'Lightweight OSC implementation' +EXPORTS + lo_address_errno @1 + lo_address_errstr @2 + lo_address_free @3 + lo_address_get_hostname @4 + lo_address_get_port @5 + lo_address_get_protocol @6 + lo_address_get_ttl @7 + lo_address_get_url @8 + lo_address_new @9 + lo_address_new_from_url @10 + lo_address_new_with_proto @11 + lo_address_set_ttl @12 + lo_arg_host_endian @13 + lo_arg_network_endian @14 + lo_arg_pp @15 + lo_arg_size @16 + lo_blob_dataptr @17 + lo_blob_datasize @18 + lo_blob_free @19 + lo_blob_new @20 + lo_blobsize @21 + lo_bundle_add_message @22 + lo_bundle_free @23 + lo_bundle_free_messages @24 + lo_bundle_length @25 + lo_bundle_new @26 + lo_bundle_pp @27 + lo_bundle_serialise @28 + lo_coerce @29 + lo_get_path @30 + lo_get_tt_immediate @31 + lo_hires_val @32 + lo_is_numerical_type @33 + lo_is_string_type @34 + lo_message_add @35 + lo_message_add_blob @36 + lo_message_add_char @37 + lo_message_add_double @38 + lo_message_add_false @39 + lo_message_add_float @40 + lo_message_add_infinitum @41 + lo_message_add_int32 @42 + lo_message_add_int64 @43 + lo_message_add_midi @44 + lo_message_add_nil @45 + lo_message_add_string @46 + lo_message_add_symbol @47 + lo_message_add_timetag @48 + lo_message_add_true @49 + lo_message_add_varargs_internal @50 + lo_message_deserialise @51 + lo_message_free @52 + lo_message_get_argc @53 + lo_message_get_argv @54 + lo_message_get_source @55 + lo_message_get_timestamp @56 + lo_message_get_types @57 + lo_message_length @58 + lo_message_new @59 + lo_message_pp @60 + lo_message_serialise @61 + lo_method_pp @62 + lo_method_pp_prefix @63 + lo_pattern_match @64 + lo_send @65 + lo_send_bundle @66 + lo_send_bundle_from @67 + lo_send_from @68 + lo_send_message @69 + lo_send_message_from @70 + lo_send_timestamped @71 + lo_server_add_method @72 + lo_server_del_method @73 + lo_server_dispatch_data @74 + lo_server_events_pending @75 + lo_server_free @76 + lo_server_get_port @77 + lo_server_get_protocol @78 + lo_server_get_socket_fd @79 + lo_server_get_url @80 + lo_server_new @81 + lo_server_new_multicast @82 + lo_server_new_with_proto @83 + lo_server_next_event_delay @84 + lo_server_pp @85 + lo_server_recv @86 + lo_server_recv_noblock @87 + lo_server_thread_add_method @88 + lo_server_thread_del_method @89 + lo_server_thread_events_pending @90 + lo_server_thread_free @91 + lo_server_thread_get_port @92 + lo_server_thread_get_server @93 + lo_server_thread_get_url @94 + lo_server_thread_new @95 + lo_server_thread_new_multicast @96 + lo_server_thread_new_with_proto @97 + lo_server_thread_pp @98 + lo_server_thread_start @99 + lo_server_thread_stop @100 + lo_server_wait @101 + lo_strsize @102 + lo_throw @103 + lo_timetag_diff @104 + lo_timetag_now @105 + lo_url_get_hostname @106 + lo_url_get_path @107 + lo_url_get_port @108 + lo_url_get_protocol @109 + lo_url_get_protocol_id @110 diff --git a/liblo/src/lo_internal.h b/liblo/src/lo_internal.h new file mode 100644 index 0000000..6448be7 --- /dev/null +++ b/liblo/src/lo_internal.h @@ -0,0 +1,63 @@ +#ifndef LO_INTERNAL_H +#define LO_INTERNAL_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/** + * \brief Validate raw OSC string data. Where applicable, data should be + * in network byte order. + * + * This function is used internally to parse and validate raw OSC data. + * + * Returns length of string or < 0 if data is invalid. + * + * \param data A pointer to the data. + * \param size The size of data in bytes (total bytes remaining). + */ +ssize_t lo_validate_string(void *data, ssize_t size); + +/** + * \brief Validate raw OSC blob data. Where applicable, data should be + * in network byte order. + * + * This function is used internally to parse and validate raw OSC data. + * + * Returns length of blob or < 0 if data is invalid. + * + * \param data A pointer to the data. + * \param size The size of data in bytes (total bytes remaining). + */ +ssize_t lo_validate_blob(void *data, ssize_t size); + +/** + * \brief Validate raw OSC bundle data. Where applicable, data should be + * in network byte order. + * + * This function is used internally to parse and validate raw OSC data. + * + * Returns length of bundle or < 0 if data is invalid. + * + * \param data A pointer to the data. + * \param size The size of data in bytes (total bytes remaining). + */ +ssize_t lo_validate_bundle(void *data, ssize_t size); + +/** + * \brief Validate raw OSC argument data. Where applicable, data should be + * in network byte order. + * + * This function is used internally to parse and validate raw OSC data. + * + * Returns length of argument data or < 0 if data is invalid. + * + * \param type The OSC type of the data item (eg. LO_FLOAT). + * \param data A pointer to the data. + * \param size The size of data in bytes (total bytes remaining). + */ +ssize_t lo_validate_arg(lo_type type, void *data, ssize_t size); + +#endif diff --git a/liblo/src/lo_types_internal.h b/liblo/src/lo_types_internal.h new file mode 100644 index 0000000..ddf71d2 --- /dev/null +++ b/liblo/src/lo_types_internal.h @@ -0,0 +1,139 @@ +#ifndef LO_TYPES_H +#define LO_TYPES_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_POLL +#include +#endif + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +#ifdef _MSC_VER +typedef SSIZE_T ssize_t; +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef __int32 int32_t; +#endif + +#include + +#include "lo/lo_osc_types.h" + +typedef void (*lo_err_handler)(int num, const char *msg, const char *path); + +struct _lo_method; + +typedef struct _lo_address { + char *host; + int socket; + char *port; + int protocol; + struct addrinfo *ai; + int errnum; + const char *errstr; + int ttl; +} *lo_address; + +typedef struct _lo_blob { + uint32_t size; + char *data; +} *lo_blob; + +typedef struct _lo_message { + char *types; + size_t typelen; + size_t typesize; + void *data; + size_t datalen; + size_t datasize; + lo_address source; + lo_arg **argv; + /* timestamp from bundle (LO_TT_IMMEDIATE for unbundled messages) */ + lo_timetag ts; +} *lo_message; + +typedef int (*lo_method_handler)(const char *path, const char *types, + lo_arg **argv, int argc, struct _lo_message + *msg, void *user_data); + +typedef struct _lo_method { + const char *path; + const char *typespec; + lo_method_handler handler; + char *user_data; + struct _lo_method *next; +} *lo_method; + +typedef struct _lo_server { + struct addrinfo *ai; + lo_method first; + lo_err_handler err_h; + int port; + char *hostname; + char *path; + int protocol; + void *queued; + struct sockaddr_storage addr; + socklen_t addr_len; + int sockets_len; + int sockets_alloc; +#ifdef HAVE_POLL + struct pollfd *sockets; +#else + struct { int fd; } *sockets; +#endif +} *lo_server; + +typedef struct _lo_server_thread { +lo_server s; + pthread_t thread; + volatile int active; + volatile int done; +} *lo_server_thread; + +typedef struct _lo_bundle { + size_t size; + size_t len; + lo_timetag ts; + lo_message *msgs; + char **paths; +} *lo_bundle; + +typedef struct _lo_strlist { + char *str; + struct _lo_strlist *next; +} lo_strlist; + +typedef union { + int32_t i; + float f; + char c; + uint32_t nl; +} lo_pcast32; + +typedef union { + int64_t i; + double f; + uint64_t nl; + lo_timetag tt; +} lo_pcast64; + +extern struct lo_cs { + int udp; + int tcp; +} lo_client_sockets; + +#endif diff --git a/liblo/src/message.c b/liblo/src/message.c new file mode 100644 index 0000000..8b2fabc --- /dev/null +++ b/liblo/src/message.c @@ -0,0 +1,1081 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +#include "lo_types_internal.h" +#include "lo_internal.h" +#include "lo/lo.h" + +#define LO_DEF_TYPE_SIZE 8 +#define LO_DEF_DATA_SIZE 8 + +static char lo_numerical_types[] = { + LO_INT32, + LO_FLOAT, + LO_INT64, + LO_DOUBLE, + '\0' +}; + +static char lo_string_types[] = { + LO_STRING, + LO_SYMBOL, + '\0' +}; + +static int lo_message_add_typechar(lo_message m, char t); +static void *lo_message_add_data(lo_message m, size_t s); +void lo_arg_pp_internal(lo_type type, void *data, int bigendian); + +// Used for calculating new sizes when expanding message data buffers. +// Note that log(x)/0.69315 = log2(x): this simply finds the next +// highest power of 2. +#if 1 +#define lo_pow2_over(a,b) \ + a = ((b > a) ? (a << ((int)((log(((double)b/(double)a))/0.69315)+1))) : a); +#else +#define lo_pow2_over(a,b) \ + while (b > a) {a *= 2;} +#endif + +lo_message lo_message_new() +{ + lo_message m = malloc(sizeof(struct _lo_message)); + if (!m) { + return m; + } + + m->types = calloc(LO_DEF_TYPE_SIZE, sizeof(char)); + m->types[0] = ','; + m->types[1] = '\0'; + m->typelen = 1; + m->typesize = LO_DEF_TYPE_SIZE; + m->data = NULL; + m->datalen = 0; + m->datasize = 0; + m->source = NULL; + m->argv = NULL; + m->ts = LO_TT_IMMEDIATE; + + return m; +} + +void lo_message_free(lo_message m) +{ + if (m) { + free(m->types); + free(m->data); + free(m->argv); + } + free(m); +} + +/* Don't call lo_message_add_varargs_internal directly, use + * lo_message_add_varargs, a macro wrapping this function with + * appropriate values for file and line */ + +int lo_message_add_varargs_internal(lo_message msg, const char *types, + va_list ap, const char *file, int line) +{ + int count = 0; + int i; + int64_t i64; + float f; + char *s; + lo_blob b; + uint8_t *m; + lo_timetag tt; + double d; + int ret = 0; + + while (types && *types) { + count++; + i=0; + i64=0; + f=0; + s=0; + b=0; + m=0; + d=0; + switch (*types++) { + + case LO_INT32: + i = va_arg(ap, int32_t); + lo_message_add_int32(msg, i); + break; + + case LO_FLOAT: + f = (float)va_arg(ap, double); + lo_message_add_float(msg, f); + break; + + case LO_STRING: + s = va_arg(ap, char *); +#ifdef __GNUC__ + if (s == (char *)LO_MARKER_A) { + fprintf(stderr, "liblo error: lo_send or lo_message_add called with " + "invalid string pointer for arg %d, probably arg mismatch\n" + "at %s:%d, exiting.\n", count, file, line); + } +#endif + lo_message_add_string(msg, s); + break; + + case LO_BLOB: + b = va_arg(ap, lo_blob); + lo_message_add_blob(msg, b); + break; + + case LO_INT64: + i64 = va_arg(ap, int64_t); + lo_message_add_int64(msg, i64); + break; + + case LO_TIMETAG: + tt = va_arg(ap, lo_timetag); + lo_message_add_timetag(msg, tt); + break; + + case LO_DOUBLE: + d = va_arg(ap, double); + lo_message_add_double(msg, d); + break; + + case LO_SYMBOL: + s = va_arg(ap, char *); +#ifdef __GNUC__ + if (s == (char *)LO_MARKER_A) { + fprintf(stderr, "liblo error: lo_send or lo_message_add called with " + "invalid symbol pointer for arg %d, probably arg mismatch\n" + "at %s:%d, exiting.\n", count, file, line); + va_end(ap); + return -2; + } +#endif + lo_message_add_symbol(msg, s); + break; + + case LO_CHAR: + i = va_arg(ap, int); + lo_message_add_char(msg, i); + break; + + case LO_MIDI: + m = va_arg(ap, uint8_t *); + lo_message_add_midi(msg, m); + break; + + case LO_TRUE: + lo_message_add_true(msg); + break; + + case LO_FALSE: + lo_message_add_false(msg); + break; + + case LO_NIL: + lo_message_add_nil(msg); + break; + + case LO_INFINITUM: + lo_message_add_infinitum(msg); + break; + + default: + ret = -1; // unknown type + fprintf(stderr, "liblo warning: unknown type '%c' at %s:%d\n", + *(types-1), file, line); + break; + } + } +#ifdef __GNUC__ + i = va_arg(ap, uint32_t); + if (i != LO_MARKER_A) { + ret = -2; // bad format/args + fprintf(stderr, "liblo error: lo_send, lo_message_add, or lo_message_add_varargs called with " + "mismatching types and data at\n%s:%d, exiting.\n", file, line); + va_end(ap); + return ret; + } + i = va_arg(ap, uint32_t); + if (i != LO_MARKER_B) { + ret = -2; // bad format/args + fprintf(stderr, "liblo error: lo_send, lo_message_add, or lo_message_add_varargs called with " + "mismatching types and data at\n%s:%d, exiting.\n", file, line); + } +#endif + va_end(ap); + + return ret; +} + +/* Don't call lo_message_add_internal directly, use lo_message_add, + * a macro wrapping this function with appropriate values for file and line */ + +#ifdef __GNUC__ +int lo_message_add_internal(lo_message msg, const char *file, const int line, + const char *types, ...) +#else +int lo_message_add(lo_message msg, const char *types, ...) +#endif +{ + va_list ap; + int ret = 0; + +#ifndef __GNUC__ + const char *file = ""; + const int line = 0; +#endif + + va_start(ap, types); + ret = lo_message_add_varargs_internal(msg, types, ap, file, line); + + return ret; +} + +int lo_message_add_int32(lo_message m, int32_t a) +{ + lo_pcast32 b; + int32_t *nptr = lo_message_add_data(m, sizeof(a)); + if (!nptr) return -1; + b.i = a; + + if (lo_message_add_typechar(m, LO_INT32)) + return -1; + *nptr = b.nl; + return 0; +} + +int lo_message_add_float(lo_message m, float a) +{ + lo_pcast32 b; + int32_t *nptr = lo_message_add_data(m, sizeof(a)); + if (!nptr) return -1; + b.f = a; + + if (lo_message_add_typechar(m, LO_FLOAT)) + return -1; + *nptr = b.nl; + return 0; +} + +int lo_message_add_string(lo_message m, const char *a) +{ + const int size = lo_strsize(a); + char *nptr = lo_message_add_data(m, size); + if (!nptr) return -1; + + if (lo_message_add_typechar(m, LO_STRING)) + return -1; + strncpy(nptr, a, size); + return 0; +} + +int lo_message_add_blob(lo_message m, lo_blob a) +{ + const uint32_t size = lo_blobsize(a); + const uint32_t dsize = lo_blob_datasize(a); + char *nptr = lo_message_add_data(m, size); + if (!nptr) return -1; + + if (lo_message_add_typechar(m, LO_BLOB)) + return -1; + memset(nptr + size - 4, 0, 4); + + memcpy(nptr, &dsize, sizeof(dsize)); + memcpy(nptr + sizeof(int32_t), lo_blob_dataptr(a), lo_blob_datasize(a)); + return 0; +} + +int lo_message_add_int64(lo_message m, int64_t a) +{ + lo_pcast64 b; + uint64_t *nptr = lo_message_add_data(m, sizeof(a)); + if (!nptr) return -1; + b.i = a; + + if (lo_message_add_typechar(m, LO_INT64)) + return -1; + *nptr = b.nl; + return 0; +} + +int lo_message_add_timetag(lo_message m, lo_timetag a) +{ + lo_pcast64 b; + uint64_t *nptr = lo_message_add_data(m, sizeof(a)); + if (!nptr) return -1; + b.tt = a; + + if (lo_message_add_typechar(m, LO_TIMETAG)) + return -1; + *nptr = b.nl; + return 0; +} + +int lo_message_add_double(lo_message m, double a) +{ + lo_pcast64 b; + uint64_t *nptr = lo_message_add_data(m, sizeof(a)); + if (!nptr) return -1; + b.f = a; + + if (lo_message_add_typechar(m, LO_DOUBLE)) + return -1; + *nptr = b.nl; + return 0; +} + +int lo_message_add_symbol(lo_message m, const char *a) +{ + const int size = lo_strsize(a); + char *nptr = lo_message_add_data(m, size); + if (!nptr) return -1; + + if (lo_message_add_typechar(m, LO_SYMBOL)) + return -1; + strncpy(nptr, a, size); + return 0; +} + +int lo_message_add_char(lo_message m, char a) +{ + lo_pcast32 b; + int32_t *nptr = lo_message_add_data(m, sizeof(int32_t)); + if (!nptr) return -1; + + b.c = a; + + if (lo_message_add_typechar(m, LO_CHAR)) + return -1; + *nptr = b.nl; + return 0; +} + +int lo_message_add_midi(lo_message m, uint8_t a[4]) +{ + char *nptr = lo_message_add_data(m, 4); + if (!nptr) return -1; + + if (lo_message_add_typechar(m, LO_MIDI)) + return -1; + + memcpy(nptr, a, sizeof(a)); + return 0; +} + +int lo_message_add_true(lo_message m) +{ + return lo_message_add_typechar(m, LO_TRUE); +} + +int lo_message_add_false(lo_message m) +{ + return lo_message_add_typechar(m, LO_FALSE); +} + +int lo_message_add_nil(lo_message m) +{ + return lo_message_add_typechar(m, LO_NIL); +} + +int lo_message_add_infinitum(lo_message m) +{ + return lo_message_add_typechar(m, LO_INFINITUM); +} + +static int lo_message_add_typechar(lo_message m, char t) +{ + if (m->typelen + 1 >= m->typesize) { + int new_typesize = m->typesize * 2; + char *new_types = 0; + if (!new_typesize) + new_typesize = LO_DEF_TYPE_SIZE; + new_types = realloc(m->types, new_typesize); + if (!new_types) return -1; + m->types = new_types; + m->typesize = new_typesize; + } + m->types[m->typelen] = t; + m->typelen++; + m->types[m->typelen] = '\0'; + if (m->argv) { + free(m->argv); + m->argv = NULL; + } + return 0; +} + +static void *lo_message_add_data(lo_message m, size_t s) +{ + uint32_t old_dlen = m->datalen; + int new_datasize = m->datasize; + int new_datalen = m->datalen + s; + void *new_data = 0; + + if (!new_datasize) + new_datasize = LO_DEF_DATA_SIZE; + + lo_pow2_over(new_datasize, new_datalen); + new_data = realloc(m->data, new_datasize); + if (!new_data) + return 0; + + m->datalen = new_datalen; + m->datasize = new_datasize; + m->data = new_data; + + if (m->argv) { + free(m->argv); + m->argv = NULL; + } + + return (void*)((char*)m->data + old_dlen); +} + +int lo_strsize(const char *s) +{ + return 4 * (strlen(s) / 4 + 1); +} + +size_t lo_arg_size(lo_type type, void *data) +{ + switch (type) { + case LO_TRUE: + case LO_FALSE: + case LO_NIL: + case LO_INFINITUM: + return 0; + + case LO_INT32: + case LO_FLOAT: + case LO_MIDI: + case LO_CHAR: + return 4; + + case LO_INT64: + case LO_TIMETAG: + case LO_DOUBLE: + return 8; + + case LO_STRING: + case LO_SYMBOL: + return lo_strsize((char *)data); + + case LO_BLOB: + return lo_blobsize((lo_blob)data); + + default: + fprintf(stderr, "liblo warning: unhandled OSC type '%c' at %s:%d\n", type, __FILE__, __LINE__); + return 0; + } + + return 0; +} + +char *lo_get_path(void *data, ssize_t size) +{ + ssize_t result = lo_validate_string(data, size); + return (result >= 4) ? (char *)data : NULL; +} + +ssize_t lo_validate_string(void *data, ssize_t size) +{ + ssize_t i = 0, len = 0; + char *pos = data; + + if (size < 0) { + return -LO_ESIZE; // invalid size + } + for (i = 0; i < size; ++i) { + if (pos[i] == '\0') { + len = 4 * (i / 4 + 1); + break; + } + } + if (0 == len) { + return -LO_ETERM; // string not terminated + } + if (len > size) { + return -LO_ESIZE; // would overflow buffer + } + for (; i < len; ++i) { + if (pos[i] != '\0') { + return -LO_EPAD; // non-zero char found in pad area + } + } + return len; +} + + +ssize_t lo_validate_blob(void *data, ssize_t size) +{ + ssize_t i, end, len; + uint32_t dsize; + char *pos = (char *)data; + + if (size < 0) { + return -LO_ESIZE; // invalid size + } + dsize = lo_otoh32(*(uint32_t*)data); + if (dsize > LO_MAX_MSG_SIZE) { // avoid int overflow in next step + return -LO_ESIZE; + } + end = sizeof(uint32_t) + dsize; // end of data + len = 4 * (end / 4 + 1); // full padded size + if (len > size) { + return -LO_ESIZE; // would overflow buffer + } + for (i = end; i < len; ++i) { + if (pos[i] != '\0') { + return -LO_EPAD; // non-zero char found in pad area + } + } + return len; +} + + +ssize_t lo_validate_bundle(void *data, ssize_t size) +{ + ssize_t len = 0, remain = size; + char *pos = data; + uint32_t elem_len; + + len = lo_validate_string(data, size); + if (len < 0) { + return -LO_ESIZE; // invalid size + } + if (0 != strcmp(data, "#bundle")) { + return -LO_EINVALIDBUND; // not a bundle + } + pos += len; + remain -= len; + + // time tag + if (remain < 8) { + return -LO_ESIZE; + } + pos += 8; + remain -= 8; + + while (remain >= 4) { + elem_len = lo_otoh32(*((uint32_t *)pos)); + pos += 4; + remain -= 4; + if (elem_len > remain) { + return -LO_ESIZE; + } + pos += elem_len; + remain -= elem_len; + } + if (0 != remain) { + return -LO_ESIZE; + } + return size; +} + + +ssize_t lo_validate_arg(lo_type type, void *data, ssize_t size) +{ + if (size < 0) { + return -1; + } + switch (type) { + case LO_TRUE: + case LO_FALSE: + case LO_NIL: + case LO_INFINITUM: + return 0; + + case LO_INT32: + case LO_FLOAT: + case LO_MIDI: + case LO_CHAR: + return size >= 4 ? 4 : -LO_ESIZE; + + case LO_INT64: + case LO_TIMETAG: + case LO_DOUBLE: + return size >= 8 ? 8 : -LO_ESIZE; + + case LO_STRING: + case LO_SYMBOL: + return lo_validate_string((char *)data, size); + + case LO_BLOB: + return lo_validate_blob((lo_blob)data, size); + + default: + return -LO_EINVALIDTYPE; + } + return -LO_INT_ERR; +} + +/* convert endianness of arg pointed to by data from network to host */ +void lo_arg_host_endian(lo_type type, void *data) +{ + switch (type) { + case LO_INT32: + case LO_FLOAT: + case LO_BLOB: + case LO_CHAR: + *(int32_t *)data = lo_otoh32(*(int32_t *)data); + break; + + case LO_INT64: + case LO_TIMETAG: + case LO_DOUBLE: + *(int64_t *)data = lo_otoh64(*(int64_t *)data); + break; + + case LO_STRING: + case LO_SYMBOL: + case LO_MIDI: + case LO_TRUE: + case LO_FALSE: + case LO_NIL: + case LO_INFINITUM: + /* these are fine */ + break; + + default: + fprintf(stderr, "liblo warning: unhandled OSC type '%c' at %s:%d\n", + type, __FILE__, __LINE__); + break; + } +} + +/* convert endianness of arg pointed to by data from host to network */ +void lo_arg_network_endian(lo_type type, void *data) +{ + switch (type) { + case LO_INT32: + case LO_FLOAT: + case LO_BLOB: + case LO_CHAR: + *(int32_t *)data = lo_htoo32(*(int32_t *)data); + break; + + case LO_INT64: + case LO_TIMETAG: + case LO_DOUBLE: + *(int64_t *)data = lo_htoo64(*(int64_t *)data); + break; + + case LO_STRING: + case LO_SYMBOL: + case LO_MIDI: + case LO_TRUE: + case LO_FALSE: + case LO_NIL: + case LO_INFINITUM: + /* these are fine */ + break; + + default: + fprintf(stderr, "liblo warning: unhandled OSC type '%c' at %s:%d\n", + type, __FILE__, __LINE__); + break; + } +} + +lo_address lo_message_get_source(lo_message m) +{ + return m->source; +} + +lo_timetag lo_message_get_timestamp(lo_message m) +{ + return m->ts; +} + +size_t lo_message_length(lo_message m, const char *path) +{ + return lo_strsize(path) + lo_strsize(m->types) + m->datalen; +} + +int lo_message_get_argc(lo_message m) +{ + return m->typelen - 1; +} + +lo_arg **lo_message_get_argv(lo_message m) +{ + int i, argc; + char *types, *ptr; + lo_arg **argv; + + if (NULL != m->argv) { return m->argv; } + + i = 0; + argc = m->typelen - 1; + types = m->types + 1; + ptr = m->data; + + argv = calloc(argc, sizeof(lo_arg *)); + for (i = 0; i < argc; ++i) { + size_t len = lo_arg_size(types[i], ptr); + argv[i] = len ? (lo_arg*)ptr : NULL; + ptr += len; + } + m->argv = argv; + return argv; +} + +char *lo_message_get_types(lo_message m) +{ + return m->types + 1; +} + +void *lo_message_serialise(lo_message m, const char *path, void *to, + size_t *size) +{ + int i, argc; + char *types, *ptr; + size_t s = lo_message_length(m, path); + + if (size) { + *size = s; + } + + if (!to) { + to = calloc(1, s); + } + memset((char*)to + lo_strsize(path) - 4, 0, 4); // ensure zero-padding + strcpy(to, path); + memset((char*)to + lo_strsize(path) + lo_strsize(m->types) - 4, 0, 4); + strcpy((char*)to + lo_strsize(path), m->types); + + types = m->types + 1; + ptr = (char*)to + lo_strsize(path) + lo_strsize(m->types); + memcpy(ptr, m->data, m->datalen); + + i = 0; + argc = m->typelen - 1; + for (i = 0; i < argc; ++i) { + size_t len = lo_arg_size(types[i], ptr); + lo_arg_network_endian(types[i], ptr); + ptr += len; + } + return to; +} + + +lo_message lo_message_deserialise(void *data, size_t size, int *result) +{ + lo_message msg = NULL; + char *types = NULL, *ptr = NULL; + int i = 0, argc = 0, remain = size, res = 0, len; + + if (remain <= 0) { res = LO_ESIZE; goto fail; } + + msg = malloc(sizeof(struct _lo_message)); + if (!msg) { res = LO_EALLOC; goto fail; } + + msg->types = NULL; + msg->typelen = 0; + msg->typesize = 0; + msg->data = NULL; + msg->datalen = 0; + msg->datasize = 0; + msg->source = NULL; + msg->argv = NULL; + msg->ts = LO_TT_IMMEDIATE; + + // path + len = lo_validate_string(data, remain); + if (len < 0) { + res = LO_EINVALIDPATH; // invalid path string + goto fail; + } + remain -= len; + + // types + if (remain <= 0) { + res = LO_ENOTYPE; // no type tag string + goto fail; + } + types = (char*)data + len; + len = lo_validate_string(types, remain); + if (len < 0) { + res = LO_EINVALIDTYPE; // invalid type tag string + goto fail; + } + if (types[0] != ',') { + res = LO_EBADTYPE; // type tag string missing initial comma + goto fail; + } + remain -= len; + + msg->typelen = strlen(types); + msg->typesize = len; + msg->types = malloc(msg->typesize); + if (NULL == msg->types) { res = LO_EALLOC; goto fail; } + memcpy(msg->types, types, msg->typesize); + + // args + msg->data = malloc(remain); + if (NULL == msg->data) { res = LO_EALLOC; goto fail; } + memcpy(msg->data, types + len, remain); + msg->datalen = msg->datasize = remain; + ptr = msg->data; + + ++types; + argc = msg->typelen - 1; + if (argc) { + msg->argv = calloc(argc, sizeof(lo_arg *)); + if (NULL == msg->argv) { res = LO_EALLOC; goto fail; } + } + + for (i = 0; remain >= 0 && i < argc; ++i) { + len = lo_validate_arg((lo_type)types[i], ptr, remain); + if (len < 0) { + res = LO_EINVALIDARG; // invalid argument + goto fail; + } + lo_arg_host_endian((lo_type)types[i], ptr); + msg->argv[i] = len ? (lo_arg*)ptr : NULL; + remain -= len; + ptr += len; + } + if (0 != remain || i != argc) { + res = LO_ESIZE; // size/argument mismatch + goto fail; + } + + if (result) { *result = res; } + return msg; + +fail: + if (msg) { lo_message_free(msg); } + if (result) { *result = res; } + return NULL; +} + +void lo_message_pp(lo_message m) +{ + void *d = m->data; + void *end = (char*)m->data + m->datalen; + int i; + + printf("%s ", m->types); + for (i = 1; m->types[i]; i++) { + if (i > 1) { + printf(" "); + } + + lo_arg_pp_internal(m->types[i], d, 1); + d = (char*)d + lo_arg_size(m->types[i], d); + } + putchar('\n'); + if (d != end) { + fprintf(stderr, "liblo warning: type and data do not match (off by %d) in message %p\n", + abs((char*)d - (char*)end), m); + } +} + +void lo_arg_pp(lo_type type, void *data) +{ + lo_arg_pp_internal(type, data, 0); +} + +void lo_arg_pp_internal(lo_type type, void *data, int bigendian) +{ + lo_pcast32 val32; + lo_pcast64 val64; + int size; + int i; + + size = lo_arg_size(type, data); + if (size == 4 || type == LO_BLOB) { + if (bigendian) { + val32.nl = lo_otoh32(*(int32_t *)data); + } else { + val32.nl = *(int32_t *)data; + } + } else if (size == 8) { + if (bigendian) { + val64.nl = lo_otoh64(*(int64_t *)data); + } else { + val64.nl = *(int64_t *)data; + } + } + + switch (type) { + case LO_INT32: + printf("%d", val32.i); + break; + + case LO_FLOAT: + printf("%f", val32.f); + break; + + case LO_STRING: + printf("\"%s\"", (char *)data); + break; + + case LO_BLOB: + printf("["); + if (val32.i > 12) { + printf("%d byte blob", val32.i); + } else { + printf("%db ", val32.i); + for (i=0; ii = (uint32_t)lo_hires_val(type_from, from); + break; + + case LO_INT64: + to->i64 = (uint64_t)lo_hires_val(type_from, from); + break; + + case LO_FLOAT: + to->f = (float)lo_hires_val(type_from, from); + break; + + case LO_DOUBLE: + to->d = (double)lo_hires_val(type_from, from); + break; + + default: + fprintf(stderr, "liblo: bad coercion: %c -> %c\n", type_from, + type_to); + return 0; + } + return 1; + } + + return 0; +} + +lo_hires lo_hires_val(lo_type type, lo_arg *p) +{ + switch (type) { + case LO_INT32: + return p->i; + case LO_INT64: + return p->h; + case LO_FLOAT: + return p->f; + case LO_DOUBLE: + return p->d; + default: + fprintf(stderr, "liblo: hires val requested of non numerical type '%c' at %s:%d\n", type, __FILE__, __LINE__); + break; + } + + return 0.0l; +} + + + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/method.c b/liblo/src/method.c new file mode 100644 index 0000000..f0cb036 --- /dev/null +++ b/liblo/src/method.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include + +#include "lo_types_internal.h" +#include "lo/lo.h" + +void lo_method_pp(lo_method m) +{ + lo_method_pp_prefix(m, ""); +} + +void lo_method_pp_prefix(lo_method m, const char *p) +{ + printf("%spath: %s\n", p, m->path); + printf("%stypespec: %s\n", p, m->typespec); + printf("%shandler: %p\n", p, m->handler); + printf("%suser-data: %p\n", p, m->user_data); +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/pattern_match.c b/liblo/src/pattern_match.c new file mode 100644 index 0000000..fb27091 --- /dev/null +++ b/liblo/src/pattern_match.c @@ -0,0 +1,248 @@ +/* Open SoundControl kit in C++ */ +/* Copyright (C) 2002-2004 libOSC++ contributors. See AUTHORS */ +/* */ +/* This library 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 2.1 of the License, or (at your option) any later version. */ +/* */ +/* This library 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 library; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* */ +/* For questions regarding this program contact */ +/* Daniel Holth or visit */ +/* http://wiretap.stetson.edu/ */ + +/* In the sprit of the public domain, my modifications to this file are also */ +/* dedicated to the public domain. Daniel Holth, Oct. 2004 */ + +/* ChangeLog: + * + * 2004-10-29 Import, convert to C++, begin OSC syntax changes. -dwh + * OSC syntax changes are now working, needs more testing. + * + */ + +// Original header and syntax: + +/* + * robust glob pattern matcher + * ozan s. yigit/dec 1994 + * public domain + * + * glob patterns: + * * matches zero or more characters + * ? matches any single character + * [set] matches any character in the set + * [^set] matches any character NOT in the set + * where a set is a group of characters or ranges. a range + * is written as two characters seperated with a hyphen: a-z denotes + * all characters between a to z inclusive. + * [-set] set matches a literal hypen and any character in the set + * []set] matches a literal close bracket and any character in the set + * + * char matches itself except where char is '*' or '?' or '[' + * \char matches char, including any pattern character + * + * examples: + * a*c ac abc abbc ... + * a?c acc abc aXc ... + * a[a-z]c aac abc acc ... + * a[-a-z]c a-c aac abc ... + * + * $Log$ + * Revision 1.1 2004/11/19 23:00:57 theno23 + * Added lo_send_timestamped + * + * Revision 1.3 1995/09/14 23:24:23 oz + * removed boring test/main code. + * + * Revision 1.2 94/12/11 10:38:15 oz + * cset code fixed. it is now robust and interprets all + * variations of cset [i think] correctly, including [z-a] etc. + * + * Revision 1.1 94/12/08 12:45:23 oz + * Initial revision + */ + +#include "lo/lo.h" + +#ifndef NEGATE +#define NEGATE '!' +#endif + +#ifndef true +#define true 1 +#endif +#ifndef false +#define false 0 +#endif + +int lo_pattern_match(const char *str, const char *p) +{ + int negate; + int match; + char c; + + while (*p) { + if (!*str && *p != '*') + return false; + + switch (c = *p++) { + + case '*': + while (*p == '*' && *p != '/') + p++; + + if (!*p) + return true; + +// if (*p != '?' && *p != '[' && *p != '\\') + if (*p != '?' && *p != '[' && *p != '{') + while (*str && *p != *str) + str++; + + while (*str) { + if (lo_pattern_match(str, p)) + return true; + str++; + } + return false; + + case '?': + if (*str) + break; + return false; + /* + * set specification is inclusive, that is [a-z] is a, z and + * everything in between. this means [z-a] may be interpreted + * as a set that contains z, a and nothing in between. + */ + case '[': + if (*p != NEGATE) + negate = false; + else { + negate = true; + p++; + } + + match = false; + + while (!match && (c = *p++)) { + if (!*p) + return false; + if (*p == '-') { /* c-c */ + if (!*++p) + return false; + if (*p != ']') { + if (*str == c || *str == *p || + (*str > c && *str < *p)) + match = true; + } + else { /* c-] */ + if (*str >= c) + match = true; + break; + } + } + else { /* cc or c] */ + if (c == *str) + match = true; + if (*p != ']') { + if (*p == *str) + match = true; + } + else + break; + } + } + + if (negate == match) + return false; + /* + * if there is a match, skip past the cset and continue on + */ + while (*p && *p != ']') + p++; + if (!*p++) /* oops! */ + return false; + break; + + /* + * {astring,bstring,cstring} + */ + case '{': + { + // *p is now first character in the {brace list} + const char *place = str; // to backtrack + const char *remainder = p; // to forwardtrack + + // find the end of the brace list + while (*remainder && *remainder != '}') + remainder++; + if (!*remainder++) /* oops! */ + return false; + + c = *p++; + + while (c) { + if (c == ',') { + if(lo_pattern_match(str, remainder)) { + return true; + } else { + // backtrack on test string + str = place; + // continue testing, + // skip comma + if (!*p++) // oops + return false; + } + } + else if (c == '}') { + // continue normal pattern matching + if (!*p && !*str) return true; + str--; // str is incremented again below + break; + } else if (c == *str) { + str++; + if (!*str && *remainder) + return false; + } else { // skip to next comma + str = place; + while (*p != ',' && *p != '}' && *p) + p++; + if (*p == ',') + p++; + else if (*p == '}') { + return false; + } + } + c = *p++; + } + } + + break; + + /* Not part of OSC pattern matching + case '\\': + if (*p) + c = *p++; + */ + + default: + if (c != *str) + return false; + break; + + } + str++; + } + + return !*str; +} diff --git a/liblo/src/send.c b/liblo/src/send.c new file mode 100644 index 0000000..336ceb7 --- /dev/null +++ b/liblo/src/send.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h"xxx +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#else +#include +#endif + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#endif + +#include "lo_types_internal.h" +#include "lo/lo.h" + +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +#ifdef WIN32 +int initWSock(); +#endif + +#ifdef WIN32 +#define geterror() WSAGetLastError() +#else +#define geterror() errno +#endif + +static int resolve_address(lo_address a); +static int create_socket(lo_address a); +static int send_data(lo_address a, lo_server from, char *data, const size_t data_len); + +// message.c +int lo_message_add_varargs_internal(lo_message m, const char *types, va_list ap, + const char *file, int line); + + + +/* Don't call lo_send_internal directly, use lo_send, a macro wrapping this + * function with appropriate values for file and line */ + +#ifdef __GNUC__ +int lo_send_internal(lo_address t, const char *file, const int line, + const char *path, const char *types, ...) +#else +int lo_send(lo_address t, const char *path, const char *types, ...) +#endif +{ + va_list ap; + int ret; +#ifndef __GNUC__ + const char *file = ""; + int line = 0; +#endif + + lo_message msg = lo_message_new(); + + t->errnum = 0; + t->errstr = NULL; + + va_start(ap, types); + ret = lo_message_add_varargs_internal(msg, types, ap, file, line); + + if (ret) { + lo_message_free(msg); + t->errnum = ret; + if (ret == -1) t->errstr = "unknown type"; + else t->errstr = "bad format/args"; + return ret; + } + + ret = lo_send_message(t, path, msg); + lo_message_free(msg); + + return ret; +} + + +/* Don't call lo_send_timestamped_internal directly, use lo_send_timestamped, a + * macro wrapping this function with appropriate values for file and line */ + +#ifdef __GNUC__ +int lo_send_timestamped_internal(lo_address t, const char *file, + const int line, lo_timetag ts, + const char *path, const char *types, ...) +#else +int lo_send_timestamped(lo_address t, lo_timetag ts, + const char *path, const char *types, ...) +#endif +{ + va_list ap; + int ret; + + lo_message msg = lo_message_new(); + lo_bundle b = lo_bundle_new(ts); + +#ifndef __GNUC__ + const char *file = ""; + int line = 0; +#endif + + t->errnum = 0; + t->errstr = NULL; + + va_start(ap, types); + ret = lo_message_add_varargs_internal(msg, types, ap, file, line); + + if (t->errnum) { + lo_message_free(msg); + return t->errnum; + } + + lo_bundle_add_message(b, path, msg); + ret = lo_send_bundle(t, b); + lo_message_free(msg); + lo_bundle_free(b); + + return ret; +} + +/* Don't call lo_send_from_internal directly, use macros wrapping this + * function with appropriate values for file and line */ + +#ifdef __GNUC__ +int lo_send_from_internal(lo_address to, lo_server from, const char *file, + const int line, lo_timetag ts, + const char *path, const char *types, ...) +#else +int lo_send_from(lo_address to, lo_server from, lo_timetag ts, + const char *path, const char *types, ...) +#endif +{ + lo_bundle b = NULL; + va_list ap; + int ret; + +#ifndef __GNUC__ + const char *file = ""; + int line = 0; +#endif + + lo_message msg = lo_message_new(); + if (ts.sec!=LO_TT_IMMEDIATE.sec || ts.frac!=LO_TT_IMMEDIATE.frac) + b = lo_bundle_new(ts); + + // Clear any previous errors + to->errnum = 0; + to->errstr = NULL; + + va_start(ap, types); + ret = lo_message_add_varargs_internal(msg, types, ap, file, line); + + if (to->errnum) { + if (b) lo_bundle_free(b); + lo_message_free(msg); + return to->errnum; + } + + if (b) { + lo_bundle_add_message(b, path, msg); + ret = lo_send_bundle_from(to, from, b); + } else { + ret = lo_send_message_from(to, from, path, msg); + } + + // Free-up memory + lo_message_free(msg); + if (b) lo_bundle_free(b); + + return ret; +} + + +#if 0 + +This (incomplete) function converts from printf-style formats to OSC typetags, +but I think its dangerous and mislieading so its not available at the moment. + +static char *format_to_types(const char *format); + +static char *format_to_types(const char *format) +{ + const char *ptr; + char *types = malloc(sizeof(format) + 1); + char *out = types; + int inspec = 0; + int width = 0; + int number = 0; + + if (!format) { + return NULL; + } + + for (ptr = format; *ptr; ptr++) { + if (inspec) { + if (*ptr == 'l') { + width++; + } else if (*ptr >= '0' && *ptr <= '9') { + number *= 10; + number += *ptr - '0'; + } else if (*ptr == 'd') { + if (width < 2 && number < 64) { + *out++ = LO_INT32; + } else { + *out++ = LO_INT64; + } + } else if (*ptr == 'f') { + if (width < 2 && number < 64) { + *out++ = LO_FLOAT; + } else { + *out++ = LO_DOUBLE; + } + } else if (*ptr == '%') { + fprintf(stderr, "liblo warning, unexpected '%%' in format\n"); + inspec = 1; + width = 0; + number = 0; + } else { + fprintf(stderr, "liblo warning, unrecognised character '%c' " + "in format\n", *ptr); + } + } else { + if (*ptr == '%') { + inspec = 1; + width = 0; + number = 0; + } else if (*ptr == LO_TRUE || *ptr == LO_FALSE || *ptr == LO_NIL || + *ptr == LO_INFINITUM) { + *out++ = *ptr; + } else { + fprintf(stderr, "liblo warning, unrecognised character '%c' " + "in format\n", *ptr); + } + } + } + *out++ = '\0'; + + return types; +} + +#endif + + +static int resolve_address(lo_address a) +{ + int ret; + + if (a->protocol == LO_UDP || a->protocol == LO_TCP) { + struct addrinfo *ai; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); +#ifdef ENABLE_IPV6 + hints.ai_family = PF_UNSPEC; +#else + hints.ai_family = PF_INET; +#endif + hints.ai_socktype = a->protocol == LO_UDP ? SOCK_DGRAM : SOCK_STREAM; + + if ((ret = getaddrinfo(a->host, a->port, &hints, &ai))) { + a->errnum = ret; + a->errstr = gai_strerror(ret); + a->ai = NULL; + return -1; + } + + a->ai = ai; + } + + return 0; +} + +static int create_socket(lo_address a) +{ + if (a->protocol == LO_UDP || a->protocol == LO_TCP) { + + a->socket = socket(a->ai->ai_family, a->ai->ai_socktype, 0); + if (a->socket == -1) { + a->errnum = geterror(); + a->errstr = NULL; + return -1; + } + + if (a->protocol == LO_TCP) { + // Only call connect() for TCP sockets - we use sendto() for UDP + if ((connect(a->socket, a->ai->ai_addr, a->ai->ai_addrlen))) { + a->errnum = geterror(); + a->errstr = NULL; + close(a->socket); + a->socket = -1; + return -1; + } + } + // if UDP and destination address is broadcast allow broadcast on the + // socket + else if (a->protocol == LO_UDP && a->ai->ai_family == AF_INET) + { + // If UDP, and destination address is broadcast, + // then allow broadcast on the socket. + struct sockaddr_in* si = (struct sockaddr_in*)a->ai->ai_addr; + unsigned char* ip = (unsigned char*)&(si->sin_addr); + + if (ip[0]==255 && ip[1]==255 && ip[2]==255 && ip[3]==255) + { + int opt = 1; + setsockopt(a->socket, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int)); + } + } + + } +#ifndef WIN32 + else if (a->protocol == LO_UNIX) { + struct sockaddr_un sa; + + a->socket = socket(PF_UNIX, SOCK_DGRAM, 0); + if (a->socket == -1) { + a->errnum = geterror(); + a->errstr = NULL; + return -1; + } + + sa.sun_family = AF_UNIX; + strncpy(sa.sun_path, a->port, sizeof(sa.sun_path)-1); + + if ((connect(a->socket, (struct sockaddr *)&sa, sizeof(sa))) < 0) { + a->errnum = geterror(); + a->errstr = NULL; + close(a->socket); + a->socket = -1; + return -1; + } + } +#endif + else { + /* unknown protocol */ + return -2; + } + + return 0; +} + +static int send_data(lo_address a, lo_server from, char *data, const size_t data_len) +{ + int ret=0; + int sock=-1; + +#ifdef WIN32 + if(!initWSock()) return -1; +#endif + + if (data_len > LO_MAX_MSG_SIZE) { + a->errnum = 99; + a->errstr = "Attempted to send message in excess of maximum " + "message size"; + return -1; + } + + // Resolve the destination address, if not done already + if (!a->ai) { + ret = resolve_address( a ); + if (ret) return ret; + } + + // Re-use existing socket? + if (from) { + sock = from->sockets[0].fd; + } else if (a->protocol == LO_UDP && lo_client_sockets.udp!=-1) { + sock = lo_client_sockets.udp; + } else { + if (a->socket==-1) { + ret = create_socket( a ); + if (ret) return ret; + } + sock = a->socket; + } + + + + // Send Length of the following data + if (a->protocol == LO_TCP) { + int32_t size = htonl(data_len); + ret = send(sock, &size, sizeof(size), MSG_NOSIGNAL); + } + + // Send the data + if (a->protocol == LO_UDP) { + if (a->ttl >= 0) { + unsigned char ttl = (unsigned char)a->ttl; + setsockopt(sock,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl)); + } + ret = sendto(sock, data, data_len, MSG_NOSIGNAL, + a->ai->ai_addr, a->ai->ai_addrlen); + } else { + ret = send(sock, data, data_len, MSG_NOSIGNAL); + } + + if (a->protocol == LO_TCP && ret == -1) { + close(a->socket); + a->socket=-1; + } + + if (ret == -1) { + a->errnum = geterror(); + a->errstr = NULL; + } else { + a->errnum = 0; + a->errstr = NULL; + } + + return ret; +} + + +int lo_send_message(lo_address a, const char *path, lo_message msg) +{ + return lo_send_message_from( a, NULL, path, msg ); +} + +int lo_send_message_from(lo_address a, lo_server from, const char *path, lo_message msg) +{ + const size_t data_len = lo_message_length(msg, path); + char *data = lo_message_serialise(msg, path, NULL, NULL); + + // Send the message + int ret = send_data( a, from, data, data_len ); + + // For TCP, retry once if it failed. The first try will return + // error if the connection was closed, so the second try will + // attempt to re-open the connection. + if (ret == -1 && a->protocol == LO_TCP) + ret = send_data( a, from, data, data_len ); + + // Free the memory allocated by lo_message_serialise + if (data) free( data ); + + return ret; +} + + +int lo_send_bundle(lo_address a, lo_bundle b) +{ + return lo_send_bundle_from( a, NULL, b ); +} + + +int lo_send_bundle_from(lo_address a, lo_server from, lo_bundle b) +{ + const size_t data_len = lo_bundle_length(b); + char *data = lo_bundle_serialise(b, NULL, NULL); + + // Send the bundle + int ret = send_data( a, from, data, data_len ); + + // Free the memory allocated by lo_bundle_serialise + if (data) free( data ); + + return ret; +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/server.c b/liblo/src/server.c new file mode 100644 index 0000000..15121e9 --- /dev/null +++ b/liblo/src/server.c @@ -0,0 +1,1400 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define _WINSOCKAPI_ +#define snprintf _snprintf +#else +#include +#endif + +#ifdef WIN32 +#include +#include +#define EADDRINUSE WSAEADDRINUSE +#else +#include +#include +#ifdef HAVE_POLL +#include +#endif +#include +#include +#endif + +#ifdef WIN32 +#define geterror() WSAGetLastError() +#else +#define geterror() errno +#endif + +#include "lo_types_internal.h" +#include "lo_internal.h" +#include "lo/lo.h" +#include "lo/lo_throw.h" + +#define LO_HOST_SIZE 1024 + +typedef struct { + lo_timetag ts; + char *path; + lo_message msg; + void *next; +} queued_msg_list; + +struct lo_cs lo_client_sockets = {-1, -1}; + +static int lo_can_coerce_spec(const char *a, const char *b); +static int lo_can_coerce(char a, char b); +static void dispatch_method(lo_server s, const char *path, + lo_message msg); +static int dispatch_queued(lo_server s); +static void queue_data(lo_server s, lo_timetag ts, const char *path, + lo_message msg); +static lo_server lo_server_new_with_proto_internal(const char *group, + const char *port, int proto, + lo_err_handler err_h); +static int lo_server_add_socket(lo_server s, int socket); +static void lo_server_del_socket(lo_server s, int index, int socket); +static int lo_server_join_multicast_group(lo_server s, const char *group); + +#ifdef WIN32 +#ifndef gai_strerror +// Copied from the Win32 SDK + +// WARNING: The gai_strerror inline functions below use static buffers, +// and hence are not thread-safe. We'll use buffers long enough to hold +// 1k characters. Any system error messages longer than this will be +// returned as empty strings. However 1k should work for the error codes +// used by getaddrinfo(). +#define GAI_STRERROR_BUFFER_SIZE 1024 + +char *WSAAPI gai_strerrorA(int ecode) +{ + DWORD dwMsgLen; + static char buff[GAI_STRERROR_BUFFER_SIZE + 1]; + + dwMsgLen = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM + |FORMAT_MESSAGE_IGNORE_INSERTS + |FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, + ecode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)buff, + GAI_STRERROR_BUFFER_SIZE, + NULL); + return buff; +} +#endif + +static int stateWSock = -1; + +int initWSock() +{ + WORD reqversion; + WSADATA wsaData; + if(stateWSock >= 0) return stateWSock; + /* TODO - which version of Winsock do we actually need? */ + + reqversion = MAKEWORD( 2, 2 ); + if(WSAStartup(reqversion,&wsaData) != 0) { + /* Couldn't initialize Winsock */ + stateWSock = 0; + } + else if ( LOBYTE( wsaData.wVersion ) != LOBYTE(reqversion) || + HIBYTE( wsaData.wVersion ) != HIBYTE(reqversion) ) { + /* wrong version */ + WSACleanup(); + stateWSock = 0; + } + else + stateWSock = 1; + + return stateWSock; +} +#endif + +lo_server lo_server_new(const char *port, lo_err_handler err_h) +{ + return lo_server_new_with_proto(port, LO_DEFAULT, err_h); +} + +lo_server lo_server_new_multicast(const char *group, const char *port, + lo_err_handler err_h) +{ + return lo_server_new_with_proto_internal(group, port, LO_UDP, err_h); +} + +lo_server lo_server_new_with_proto(const char *port, int proto, + lo_err_handler err_h) +{ + return lo_server_new_with_proto_internal(NULL, port, proto, err_h); +} + +lo_server lo_server_new_with_proto_internal(const char *group, + const char *port, int proto, + lo_err_handler err_h) +{ + lo_server s; + struct addrinfo *ai = NULL, *it, *used; + struct addrinfo hints; + int ret = -1; + int tries = 0; + char pnum[16]; + const char *service; + char hostname[LO_HOST_SIZE]; + + // Set real protocol, if Default is requested + if (proto==LO_DEFAULT) { +#ifndef WIN32 + if (port && *port == '/') proto = LO_UNIX; + else +#endif + proto = LO_UDP; + } + + +#ifdef WIN32 + if(!initWSock()) return NULL; +#endif + + s = calloc(1, sizeof(struct _lo_server)); + if (!s) return 0; + + s->err_h = err_h; + s->first = NULL; + s->ai = NULL; + s->hostname = NULL; + s->protocol = proto; + s->port = 0; + s->path = NULL; + s->queued = NULL; + s->sockets_len = 1; + s->sockets_alloc = 2; + s->sockets = calloc(2, sizeof(*(s->sockets))); + + if (!s->sockets) { + free(s); + return 0; + } + + s->sockets[0].fd = -1; + + memset(&hints, 0, sizeof(hints)); + + if (proto == LO_UDP) { + hints.ai_socktype = SOCK_DGRAM; + } else if (proto == LO_TCP) { + hints.ai_socktype = SOCK_STREAM; + } +#ifndef WIN32 + else if (proto == LO_UNIX) { + + struct sockaddr_un sa; + + s->sockets[0].fd = socket(PF_UNIX, SOCK_DGRAM, 0); + if (s->sockets[0].fd == -1) { + int err = geterror(); + used = NULL; + lo_throw(s, err, strerror(err), "socket()"); + lo_server_free(s); + + return NULL; + } + + sa.sun_family = AF_UNIX; + strncpy(sa.sun_path, port, sizeof(sa.sun_path)-1); + + if ((ret = bind(s->sockets[0].fd, + (struct sockaddr *)&sa, sizeof(sa))) < 0) { + int err = geterror(); + lo_throw(s, err, strerror(err), "bind()"); + + lo_server_free(s); + return NULL; + } + + s->path = strdup(port); + + return s; + } +#endif + else { + lo_throw(s, LO_UNKNOWNPROTO, "Unknown protocol", NULL); + lo_server_free(s); + + return NULL; + } + +#ifdef ENABLE_IPV6 + hints.ai_family = PF_UNSPEC; +#else + hints.ai_family = PF_INET; +#endif + hints.ai_flags = AI_PASSIVE; + + if (!port) { + service = pnum; + } else { + service = port; + } + do { + if (!port) { + /* not a good way to get random numbers, but its not critical */ + snprintf(pnum, 15, "%ld", 10000 + ((unsigned int)rand() + + time(NULL)) % 10000); + } + + if ((ret = getaddrinfo(NULL, service, &hints, &ai))) { + lo_throw(s, ret, gai_strerror(ret), NULL); + freeaddrinfo(ai); + + return NULL; + } + + used = NULL; + s->ai = ai; + s->sockets[0].fd = -1; + s->port = 0; + + for (it = ai; it && s->sockets[0].fd == -1; it = it->ai_next) { + used = it; + s->sockets[0].fd = socket(it->ai_family, hints.ai_socktype, 0); + } + if (s->sockets[0].fd == -1) { + int err = geterror(); + used = NULL; + lo_throw(s, err, strerror(err), "socket()"); + + lo_server_free(s); + return NULL; + } + + /* Join multicast group if specified. */ + /* This must be done before bind() on POSIX, but after bind() Windows. */ +#ifndef WIN32 + if (group != NULL) + if (lo_server_join_multicast_group(s, group)) + return NULL; +#endif + + if ((ret = bind(s->sockets[0].fd, used->ai_addr, used->ai_addrlen)) < 0) { + int err = geterror(); + if (err == EINVAL || err == EADDRINUSE) { + used = NULL; + + continue; + } + lo_throw(s, err, strerror(err), "bind()"); + + lo_server_free(s); + + return NULL; + } + } while (!used && tries++ < 16); + + /* Join multicast group if specified (see above). */ +#ifdef WIN32 + if (group != NULL) + if (lo_server_join_multicast_group(s, group)) + return NULL; +#endif + + if (proto == LO_TCP) { + listen(s->sockets[0].fd, 8); + } + + if (!used) { + lo_throw(s, LO_NOPORT, "cannot find free port", NULL); + + lo_server_free(s); + return NULL; + } + + if (proto == LO_UDP) { + lo_client_sockets.udp = s->sockets[0].fd; + } else if (proto == LO_TCP) { + lo_client_sockets.tcp = s->sockets[0].fd; + } + + /* Set hostname to empty string */ + hostname[0] = '\0'; + +#ifdef ENABLE_IPV6 + /* Try it the IPV6 friendly way first */ + for (it = ai; it; it = it->ai_next) { + if (getnameinfo(it->ai_addr, it->ai_addrlen, hostname, + sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) { + break; + } + } + + /* check to make sure getnameinfo() didn't just set the hostname to "::". + Needed on Darwin. */ + if (hostname[0] == ':') { + hostname[0] = '\0'; + } +#endif + + + /* Fallback to the oldschool (i.e. more reliable) way */ + if (!hostname[0]) { + struct hostent *he; + + gethostname(hostname, sizeof(hostname)); + he = gethostbyname(hostname); + if (he) { + strncpy(hostname, he->h_name, sizeof(hostname)); + } + } + + /* soethings gone really wrong, just hope its local only */ + if (!hostname[0]) { + strcpy(hostname, "localhost"); + } + s->hostname = strdup(hostname); + + if (used->ai_family == PF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)used->ai_addr; + + s->port = htons(addr->sin6_port); + } else if (used->ai_family == PF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *)used->ai_addr; + + s->port = htons(addr->sin_port); + } else { + lo_throw(s, LO_UNKNOWNPROTO, "unknown protocol family", NULL); + s->port = atoi(port); + } + + return s; +} + +int lo_server_join_multicast_group(lo_server s, const char *group) +{ + struct ip_mreq mreq; + unsigned int yes = 1; + memset(&mreq, 0, sizeof(mreq)); +#ifdef HAVE_INET_ATON + if (inet_aton(group, &mreq.imr_multiaddr)==0) { + int err = geterror(); + lo_throw(s, err, strerror(err), "inet_aton()"); + lo_server_free(s); + return err; + } +#else + mreq.imr_multiaddr.s_addr = inet_addr(group); + if (mreq.imr_multiaddr.s_addr == INADDR_ANY + || mreq.imr_multiaddr.s_addr == INADDR_NONE) + { + int err = geterror(); + lo_throw(s, err, strerror(err), "inet_addr()"); + lo_server_free(s); + return err; + } +#endif + mreq.imr_interface.s_addr=htonl(INADDR_ANY); + + if (setsockopt(s->sockets[0].fd,IPPROTO_IP,IP_ADD_MEMBERSHIP, + &mreq,sizeof(mreq)) < 0) + { + int err = geterror(); + lo_throw(s, err, strerror(err), "setsockopt(IP_ADD_MEMBERSHIP)"); + lo_server_free(s); + return err; + } + + if (setsockopt(s->sockets[0].fd,SOL_SOCKET,SO_REUSEADDR, + &yes,sizeof(yes)) < 0) + { + int err = geterror(); + lo_throw(s, err, strerror(err), "setsockopt(SO_REUSEADDR)"); + lo_server_free(s); + return err; + } + +#ifdef SO_REUSEPORT + if (setsockopt(s->sockets[0].fd,SOL_SOCKET,SO_REUSEPORT, + &yes,sizeof(yes)) < 0) + { + int err = geterror(); + lo_throw(s, err, strerror(err), "setsockopt(SO_REUSEPORT)"); + lo_server_free(s); + return err; + } +#endif + + return 0; +} + +void lo_server_free(lo_server s) +{ + if (s) { + lo_method it; + lo_method next; + int i; + + for (i=s->sockets_len-1; i >= 0; i--) + { + if (s->sockets[i].fd != -1) { + if (s->protocol == LO_UDP + && s->sockets[i].fd == lo_client_sockets.udp) + { + lo_client_sockets.udp = -1; + } + else if (s->protocol == LO_TCP + && s->sockets[0].fd == lo_client_sockets.tcp) + { + lo_client_sockets.tcp = -1; + } + + close(s->sockets[i].fd); + s->sockets[i].fd = -1; + } + } + if (s->ai) { + freeaddrinfo(s->ai); + s->ai=NULL; + } + if (s->hostname) { + free(s->hostname); + s->hostname = NULL; + } + if (s->path) { + if (s->protocol == LO_UNIX) unlink( s->path ); + free(s->path); + s->path = NULL; + } + for (it = s->first; it; it = next) { + next = it->next; + free((char *)it->path); + free((char *)it->typespec); + free(it); + } + free(s->sockets); + free(s); + } +} + +void *lo_server_recv_raw(lo_server s, size_t *size) +{ + char buffer[LO_MAX_MSG_SIZE]; + int ret; + void *data = NULL; + +#ifdef WIN32 + if(!initWSock()) return NULL; +#endif + + s->addr_len = sizeof(s->addr); + + ret = recvfrom(s->sockets[0].fd, buffer, LO_MAX_MSG_SIZE, 0, + (struct sockaddr *)&s->addr, &s->addr_len); + if (ret <= 0) { + return NULL; + } + data = malloc(ret); + memcpy(data, buffer, ret); + + if (size) *size = ret; + + return data; +} + +void *lo_server_recv_raw_stream(lo_server s, size_t *size) +{ + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + char buffer[LO_MAX_MSG_SIZE]; + int32_t read_size; + int ret=0, i; + void *data = NULL; + int sock = -1; + int repeat = 1; +#ifdef HAVE_SELECT +#ifndef HAVE_POLL + fd_set ps; + int nfds=0; +#endif +#endif + + /* check sockets in reverse order so that already-open sockets + * have priority. this allows checking for closed sockets even + * when new connections are being requested. it also allows to + * continue looping through the list of sockets after closing and + * deleting a socket, since deleting sockets doesn't affect the + * order of the array to the left of the index. */ + +#ifdef HAVE_POLL + for (i=0; i < s->sockets_len; i++) { + s->sockets[i].events = POLLIN | POLLPRI; + s->sockets[i].revents = 0; + } + + poll(s->sockets, s->sockets_len, -1); + + for (i=(s->sockets_len-1); i >= 0; --i) { + if (s->sockets[i].revents == POLLERR + || s->sockets[i].revents == POLLHUP) + { + if (i>0) { + close(s->sockets[i].fd); + lo_server_del_socket(s, i, s->sockets[i].fd); + continue; + } + else + return NULL; + } + if (s->sockets[i].revents) { + sock = s->sockets[i].fd; + +#else +#ifdef HAVE_SELECT + if(!initWSock()) return NULL; + + FD_ZERO(&ps); + for (i=(s->sockets_len-1); i >= 0; --i) { + FD_SET(s->sockets[i].fd, &ps); + if (s->sockets[i].fd > nfds) + nfds = s->sockets[i].fd; + } + + if (select(nfds+1,&ps,NULL,NULL,NULL) == SOCKET_ERROR) + return NULL; + + for (i=0; i < s->sockets_len; i++) { + if (FD_ISSET(s->sockets[i].fd, &ps)) { + sock = s->sockets[i].fd; + +#endif +#endif + + if (sock == -1 || !repeat) + return NULL; + + /* zeroeth socket is listening for new connections */ + if (sock == s->sockets[0].fd) { + sock = accept(sock, (struct sockaddr *)&addr, &addr_len); + i = lo_server_add_socket(s, sock); + + /* only repeat this loop for sockets other than the listening + * socket, (otherwise i will be wrong next time around) */ + repeat = 0; + } + + if (i<0) { + close(sock); + return NULL; + } + + ret = recv(sock, &read_size, sizeof(read_size), 0); + read_size = ntohl(read_size); + if (read_size > LO_MAX_MSG_SIZE || ret <= 0) { + close(sock); + lo_server_del_socket(s, i, sock); + if (ret > 0) + lo_throw(s, LO_TOOBIG, "Message too large", "recv()"); + continue; + } + ret = recv(sock, buffer, read_size, 0); + if (ret <= 0) { + close(sock); + lo_server_del_socket(s, i, sock); + continue; + } + + /* end of loop over sockets: successfully read data */ + break; + } + } + + data = malloc(ret); + memcpy(data, buffer, ret); + + if (size) *size = ret; + + return data; +} + +int lo_server_wait(lo_server s, int timeout) +{ + int sched_timeout = lo_server_next_event_delay(s) * 1000; + int i; +#ifdef HAVE_SELECT +#ifndef HAVE_POLL + fd_set ps; + struct timeval stimeout; +#endif +#endif + +#ifdef HAVE_POLL + for (i=0; i < s->sockets_len; i++) { + s->sockets[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP; + s->sockets[i].revents = 0; + } + + poll(s->sockets, s->sockets_len, + timeout > sched_timeout ? sched_timeout : timeout); + + if (lo_server_next_event_delay(s) < 0.01) + return 1; + + for (i=0; i < s->sockets_len; i++) { + if (s->sockets[i].revents == POLLERR + || s->sockets[i].revents == POLLHUP) + return 0; + if (s->sockets[i].revents) + return 1; + } +#else +#ifdef HAVE_SELECT + int res,to,nfds=0; + + if(!initWSock()) return 0; + + to = timeout > sched_timeout ? sched_timeout : timeout; + stimeout.tv_sec = to/1000; + stimeout.tv_usec = (to%1000)*1000; + + FD_ZERO(&ps); + for (i=0; i < s->sockets_len; i++) { + FD_SET(s->sockets[i].fd,&ps); + if (s->sockets[i].fd > nfds) + nfds = s->sockets[i].fd; + } + + res = select(nfds+1,&ps,NULL,NULL,&stimeout); + + if(res == SOCKET_ERROR) + return 0; + + if (res || lo_server_next_event_delay(s) < 0.01) + return 1; +#endif +#endif + + return 0; +} + +int lo_server_recv_noblock(lo_server s, int timeout) +{ + int result = lo_server_wait(s,timeout); + if (result>0) { + return lo_server_recv(s); + } else { + return 0; + } +} + +int lo_server_recv(lo_server s) +{ + void *data; + size_t size; + double sched_time = lo_server_next_event_delay(s); + int i; +#ifdef HAVE_SELECT +#ifndef HAVE_POLL + fd_set ps; + struct timeval stimeout; + int res,nfds=0; +#endif +#endif + +again: + if (sched_time > 0.01) { + if (sched_time > 10.0) { + sched_time = 10.0; + } + +#ifdef HAVE_POLL + for (i=0; i < s->sockets_len; i++) { + s->sockets[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP; + s->sockets[i].revents = 0; + } + + poll(s->sockets, s->sockets_len, (int)(sched_time * 1000.0)); + + for (i=0; i < s->sockets_len; i++) + { + if ( s->sockets[i].revents == POLLERR + || s->sockets[i].revents == POLLHUP) + return 0; + + if (s->sockets[i].revents) + break; + } + + if (i >= s->sockets_len) + { + sched_time = lo_server_next_event_delay(s); + + if (sched_time > 0.01) + goto again; + + return dispatch_queued(s); + } +#else +#ifdef HAVE_SELECT + if(!initWSock()) return 0; + + FD_ZERO(&ps); + for (i=0; i < s->sockets_len; i++) { + FD_SET(s->sockets[i].fd,&ps); + if (s->sockets[i].fd > nfds) + nfds = s->sockets[i].fd; + } + + stimeout.tv_sec = sched_time; + stimeout.tv_usec = (sched_time-stimeout.tv_sec)*1.e6; + res = select(nfds+1,&ps,NULL,NULL,&stimeout); + if(res == SOCKET_ERROR) { + return 0; + } + + if(!res) { + sched_time = lo_server_next_event_delay(s); + + if (sched_time > 0.01) + goto again; + + return dispatch_queued(s); + } +#endif +#endif + } else { + return dispatch_queued(s); + } + if (s->protocol == LO_TCP) { + data = lo_server_recv_raw_stream(s, &size); + } else { + data = lo_server_recv_raw(s, &size); + } + + if (!data) { + return 0; + } + if (lo_server_dispatch_data(s, data, size) < 0) { + free(data); + return -1; + } + free(data); + return size; +} + +/** \internal \brief Add a socket to this server's list of sockets. + * \param s The lo_server + * \param socket The socket number to add. + * \return The index number of the added socket, or -1 on failure. + */ +int lo_server_add_socket(lo_server s, int socket) +{ + if ((s->sockets_len+1) > s->sockets_alloc) { + void *sp = realloc(s->sockets, + sizeof(*(s->sockets))*(s->sockets_alloc*2)); + if (!sp) + return -1; + s->sockets = sp; + s->sockets_alloc *= 2; + } + + s->sockets[s->sockets_len].fd = socket; + s->sockets_len ++; + + return s->sockets_len-1; +} + +/** \internal \brief Delete a socket from this server's list of sockets. + * \param s The lo_server + * \param index The index of the socket to delete, -1 if socket is provided. + * \param socket The socket number to delete, -1 if index is provided. + * \return The index number of the added socket. + */ +void lo_server_del_socket(lo_server s, int index, int socket) +{ + int i; + + if (index < 0 && socket != -1) { + for (index=0; index < s->sockets_len; index++) + if (s->sockets[index].fd == socket) + break; + } + + if (index < 0 || index >= s->sockets_len) + return; + + for (i=index+1; i < s->sockets_len; i++) + s->sockets[i-1] = s->sockets[i]; + s->sockets_len --; +} + +int lo_server_dispatch_data(lo_server s, void *data, size_t size) +{ + int result = 0; + char *path = data; + ssize_t len = lo_validate_string(data, size); + if (len < 0) { + lo_throw(s, -len, "Invalid message path", NULL); + return len; + } + + if (!strcmp(data, "#bundle")) { + char *pos; + int remain; + uint32_t elem_len; + lo_timetag ts, now; + + ssize_t bundle_result = lo_validate_bundle(data, size); + if (bundle_result < 0) { + lo_throw(s, -bundle_result, "Invalid bundle", NULL); + return bundle_result; + } + pos = (char *)data + len; + remain = size - len; + + lo_timetag_now(&now); + ts.sec = lo_otoh32(*((uint32_t *)pos)); + pos += 4; + ts.frac = lo_otoh32(*((uint32_t *)pos)); + pos += 4; + remain -= 8; + + while (remain >= 4) { + lo_message msg; + elem_len = lo_otoh32(*((uint32_t *)pos)); + pos += 4; + remain -= 4; + msg = lo_message_deserialise(pos, elem_len, &result); + if (!msg) { + lo_throw(s, result, "Invalid bundle element received", path); + return -result; + } + + // set timetag from bundle + msg->ts = ts; + + // test for immediate dispatch + if ((ts.sec == LO_TT_IMMEDIATE.sec + && ts.frac == LO_TT_IMMEDIATE.frac) || + lo_timetag_diff(ts, now) <= 0.0) { + dispatch_method(s, pos, msg); + lo_message_free(msg); + } else { + queue_data(s, ts, pos, msg); + } + pos += elem_len; + remain -= elem_len; + } + } else { + lo_message msg = lo_message_deserialise(data, size, &result); + if (NULL == msg) { + lo_throw(s, result, "Invalid message received", path); + return -result; + } + dispatch_method(s, data, msg); + lo_message_free(msg); + } + return size; +} + +/* returns the time in seconds until the next scheduled event */ +double lo_server_next_event_delay(lo_server s) +{ + if (s->queued) { + lo_timetag now; + double delay; + + lo_timetag_now(&now); + delay = lo_timetag_diff(((queued_msg_list *)s->queued)->ts, now); + + delay = delay > 100.0 ? 100.0 : delay; + delay = delay < 0.0 ? 0.0 : delay; + + return delay; + } + + return 100.0; +} + +static void dispatch_method(lo_server s, const char *path, + lo_message msg) +{ + char *types = msg->types + 1; + int argc = strlen(types); + lo_arg **argv = msg->argv; + lo_method it; + int ret = 1; + int err; + int pattern = strpbrk(path, " #*,?[]{}") != NULL; + lo_address src = lo_address_new(NULL, NULL); + char hostname[LO_HOST_SIZE]; + char portname[32]; + const char *pptr; + + msg->source = src; + + //inet_ntop(s->addr.ss_family, &s->addr.padding, hostname, sizeof(hostname)); + if (s->protocol == LO_UDP && s->addr_len>0) { + err = getnameinfo((struct sockaddr *)&s->addr, sizeof(s->addr), + hostname, sizeof(hostname), portname, sizeof(portname), + NI_NUMERICHOST | NI_NUMERICSERV); + if (err) { + switch (err) { + case EAI_AGAIN: + lo_throw(s, err, "Try again", path); + break; + case EAI_BADFLAGS: + lo_throw(s, err, "Bad flags", path); + break; + case EAI_FAIL: + lo_throw(s, err, "Failed", path); + break; + case EAI_FAMILY: + lo_throw(s, err, "Cannot resolve address family", path); + break; + case EAI_MEMORY: + lo_throw(s, err, "Out of memory", path); + break; + case EAI_NONAME: + lo_throw(s, err, "Cannot resolve", path); + break; +#ifndef WIN32 + case EAI_SYSTEM: + lo_throw(s, err, strerror(err), path); + break; +#endif + default: + lo_throw(s, err, "Unknown error", path); + break; + } + + return; + } + } else { + hostname[0] = '\0'; + portname[0] = '\0'; + } + + + // Store the source information in the lo_address + if (src->host) free(src->host); + if (src->host) free(src->port); + src->host = strdup(hostname); + src->port = strdup(portname); + src->protocol = s->protocol; + + for (it = s->first; it; it = it->next) { + /* If paths match or handler is wildcard */ + if (!it->path || !strcmp(path, it->path) || + (pattern && lo_pattern_match(it->path, path))) { + /* If types match or handler is wildcard */ + if (!it->typespec || !strcmp(types, it->typespec)) { + /* Send wildcard path to generic handler, expanded path + to others. + */ + pptr = path; + if (it->path) pptr = it->path; + ret = it->handler(pptr, types, argv, argc, msg, + it->user_data); + + } else if (lo_can_coerce_spec(types, it->typespec)) { + int i; + int opsize = 0; + char *ptr = msg->data; + char *data_co, *data_co_ptr; + + argv = calloc(argc, sizeof(lo_arg *)); + for (i=0; itypespec[i], ptr); + ptr += lo_arg_size(types[i], ptr); + } + + data_co = malloc(opsize); + data_co_ptr = data_co; + ptr = msg->data; + for (i=0; itypespec[i], (lo_arg *)data_co_ptr, + types[i], (lo_arg *)ptr); + data_co_ptr += lo_arg_size(it->typespec[i], data_co_ptr); + ptr += lo_arg_size(types[i], ptr); + } + + /* Send wildcard path to generic handler, expanded path + to others. + */ + pptr = path; + if (it->path) pptr = it->path; + ret = it->handler(pptr, it->typespec, argv, argc, msg, + it->user_data); + free(argv); + free(data_co); + argv = NULL; + } + + if (ret == 0 && !pattern) { + break; + } + } + } + + /* If we find no matching methods, check for protocol level stuff */ + if (ret == 1 && s->protocol == LO_UDP) { + char *pos = strrchr(path, '/'); + + /* if its a method enumeration call */ + if (pos && *(pos+1) == '\0') { + lo_message reply = lo_message_new(); + int len = strlen(path); + lo_strlist *sl = NULL, *slit, *slnew, *slend; + + if (!strcmp(types, "i")) { + lo_message_add_int32(reply, argv[0]->i); + } + lo_message_add_string(reply, path); + + for (it = s->first; it; it = it->next) { + /* If paths match */ + if (it->path && !strncmp(path, it->path, len)) { + char *tmp; + char *sec; + + tmp = malloc(strlen(it->path + len) + 1); + strcpy(tmp, it->path + len); +#ifdef WIN32 + sec = strchr(tmp,'/'); +#else + sec = index(tmp, '/'); +#endif + if (sec) *sec = '\0'; + slend = sl; + for (slit = sl; slit; slend = slit, slit = slit->next) { + if (!strcmp(slit->str, tmp)) { + free(tmp); + tmp = NULL; + break; + } + } + if (tmp) { + slnew = calloc(1, sizeof(lo_strlist)); + slnew->str = tmp; + slnew->next = NULL; + if (!slend) { + sl = slnew; + } else { + slend->next = slnew; + } + } + } + } + + slit = sl; + while(slit) { + lo_message_add_string(reply, slit->str); + slnew = slit; + slit = slit->next; + free(slnew->str); + free(slnew); + } + lo_send_message(src, "#reply", reply); + lo_message_free(reply); + } + } + + lo_address_free(src); + msg->source = NULL; +} + +int lo_server_events_pending(lo_server s) +{ + return s->queued != 0; +} + +static void queue_data(lo_server s, lo_timetag ts, const char *path, + lo_message msg) +{ + /* insert blob into future dispatch queue */ + queued_msg_list *it = s->queued; + queued_msg_list *prev = NULL; + queued_msg_list *ins = calloc(1, sizeof(queued_msg_list)); + + ins->ts = ts; + ins->path = strdup(path); + ins->msg = msg; + + while (it) { + if (lo_timetag_diff(it->ts, ts) > 0.0) { + if (prev) { + prev->next = ins; + } else { + s->queued = ins; + ins->next = NULL; + } + ins->next = it; + + return; + } + prev = it; + it = it->next; + } + + /* fell through, so this event is last */ + if (prev) { + prev->next = ins; + } else { + s->queued = ins; + } + ins->next = NULL; +} + +static int dispatch_queued(lo_server s) +{ + queued_msg_list *head = s->queued; + queued_msg_list *tailhead; + lo_timetag disp_time; + + if (!head) { + lo_throw(s, LO_INT_ERR, "attempted to dispatch with empty queue", + "timeout"); + return 1; + } + + disp_time = head->ts; + + do { + char *path; + lo_message msg; + tailhead = head->next; + path = ((queued_msg_list *)s->queued)->path; + msg = ((queued_msg_list *)s->queued)->msg; + dispatch_method(s, path, msg); + free(path); + lo_message_free(msg); + free((queued_msg_list *)s->queued); + + s->queued = tailhead; + head = tailhead; + } while (head && lo_timetag_diff(head->ts, disp_time) < FLT_EPSILON); + + return 0; +} + +lo_method lo_server_add_method(lo_server s, const char *path, + const char *typespec, lo_method_handler h, + void *user_data) +{ + lo_method m = calloc(1, sizeof(struct _lo_method)); + lo_method it; + + if (path && strpbrk(path, " #*,?[]{}")) { + return NULL; + } + + if (path) { + m->path = strdup(path); + } else { + m->path = NULL; + } + + if (typespec) { + m->typespec = strdup(typespec); + } else { + m->typespec = NULL; + } + + m->handler = h; + m->user_data = user_data; + m->next = NULL; + + /* append the new method to the list */ + if (!s->first) { + s->first = m; + } else { + /* get to the last member of the list */ + for (it=s->first; it->next; it=it->next); + it->next = m; + } + + return m; +} + +void lo_server_del_method(lo_server s, const char *path, + const char *typespec) +{ + lo_method it, prev, next; + int pattern = 0; + + if (!s->first) return; + if (path) pattern = strpbrk(path, " #*,?[]{}") != NULL; + + it = s->first; + prev = it; + while (it) { + /* incase we free it */ + next = it->next; + + /* If paths match or handler is wildcard */ + if ((it->path == path) || + (path && it->path && !strcmp(path, it->path)) || + (pattern && it->path && lo_pattern_match(it->path, path))) { + /* If types match or handler is wildcard */ + if ((it->typespec == typespec) || + (typespec && it->typespec && !strcmp(typespec, it->typespec)) + ) { + /* Take care when removing the head. */ + if (it == s->first) { + s->first = it->next; + } else { + prev->next = it->next; + } + next = it->next; + free((void *)it->path); + free((void *)it->typespec); + free(it); + it = prev; + } + } + prev = it; + if (it) it = next; + } +} + +int lo_server_get_socket_fd(lo_server s) +{ + if (s->protocol != LO_UDP && + s->protocol != LO_TCP +#ifndef WIN32 + && s->protocol != LO_UNIX +#endif + ) { + return -1; /* assume it is not supported */ + } + return s->sockets[0].fd; +} + +int lo_server_get_port(lo_server s) +{ + if (!s) { + return 0; + } + + return s->port; +} + +int lo_server_get_protocol(lo_server s) +{ + if (!s) { + return -1; + } + + return s->protocol; +} + + +char *lo_server_get_url(lo_server s) +{ + int ret=0; + char *buf; + + if (!s) { + return NULL; + } + + if (s->protocol == LO_UDP || s->protocol == LO_TCP) { + char *proto = s->protocol == LO_UDP ? "udp" : "tcp"; + +#ifndef _MSC_VER + ret = snprintf(NULL, 0, "osc.%s://%s:%d/", proto, s->hostname, s->port); +#endif + if (ret <= 0) { + /* this libc is not C99 compliant, guess a size */ + ret = 1023; + } + buf = malloc((ret + 2) * sizeof(char)); + snprintf(buf, ret+1, "osc.%s://%s:%d/", proto, s->hostname, s->port); + + return buf; + } +#ifndef WIN32 + else if (s->protocol == LO_UNIX) { + ret = snprintf(NULL, 0, "osc.unix:///%s", s->path); + if (ret <= 0) { + /* this libc is not C99 compliant, guess a size */ + ret = 1023; + } + buf = malloc((ret + 2) * sizeof(char)); + snprintf(buf, ret+1, "osc.unix:///%s", s->path); + + return buf; + } +#endif + return NULL; +} + +void lo_server_pp(lo_server s) +{ + lo_method it; + + printf("socket: %d\n\n", s->sockets[0].fd); + printf("Methods\n"); + for (it = s->first; it; it = it->next) { + printf("\n"); + lo_method_pp_prefix(it, " "); + } +} + +static int lo_can_coerce_spec(const char *a, const char *b) +{ + unsigned int i; + + if (strlen(a) != strlen(b)) { + return 0; + } + + for (i=0; a[i]; i++) { + if (!lo_can_coerce(a[i], b[i])) { + return 0; + } + } + + return 1; +} + +static int lo_can_coerce(char a, char b) +{ + return ((a == b) || + (lo_is_numerical_type(a) && lo_is_numerical_type(b)) || + (lo_is_string_type(a) && lo_is_string_type (b))); +} + +void lo_throw(lo_server s, int errnum, const char *message, const char *path) +{ + if (s->err_h) { + (*s->err_h)(errnum, message, path); + } +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/server_thread.c b/liblo/src/server_thread.c new file mode 100644 index 0000000..4b715a5 --- /dev/null +++ b/liblo/src/server_thread.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#endif + +#include "lo_types_internal.h" +#include "lo/lo.h" +#include "lo/lo_throw.h" + +static void thread_func(void *data); + +lo_server_thread lo_server_thread_new(const char *port, lo_err_handler err_h) +{ + return lo_server_thread_new_with_proto(port, LO_DEFAULT, err_h); +} + +lo_server_thread lo_server_thread_new_multicast(const char *group, const char *port, + lo_err_handler err_h) +{ + lo_server_thread st = malloc(sizeof(struct _lo_server_thread)); + st->s = lo_server_new_multicast(group, port, err_h); + st->active = 0; + st->done = 0; + + if (!st->s) { + free(st); + + return NULL; + } + + return st; +} + +lo_server_thread lo_server_thread_new_with_proto(const char *port, int proto, + lo_err_handler err_h) +{ + lo_server_thread st = malloc(sizeof(struct _lo_server_thread)); + st->s = lo_server_new_with_proto(port, proto, err_h); + st->active = 0; + st->done = 0; + + if (!st->s) { + free(st); + + return NULL; + } + + return st; +} + + +void lo_server_thread_free(lo_server_thread st) +{ + if (st) { + if (st->active) { + lo_server_thread_stop(st); + } + lo_server_free(st->s); + } + free(st); +} + +lo_method lo_server_thread_add_method(lo_server_thread st, const char *path, + const char *typespec, lo_method_handler h, + void *user_data) +{ + return lo_server_add_method(st->s, path, typespec, h, user_data); +} + +void lo_server_thread_del_method(lo_server_thread st, const char *path, + const char *typespec) +{ + lo_server_del_method(st->s, path, typespec); +} + +int lo_server_thread_start(lo_server_thread st) +{ + int result; + + if (!st->active) { + st->active = 1; + st->done = 0; + + // Create the server thread + result = pthread_create(&(st->thread), NULL, (void *)&thread_func, st); + if (result) { + fprintf(stderr, "Failed to create thread: pthread_create(), %s", + strerror(result)); + return -result; + } + + } + return 0; +} + +int lo_server_thread_stop(lo_server_thread st) +{ + int result; + + if (st->active) { + // Signal thread to stop + st->active = 0; + + // pthread_join waits for thread to terminate + // and then releases the thread's resources + result = pthread_join( st->thread, NULL ); + if (result) { + fprintf(stderr, "Failed to stop thread: pthread_join(), %s", + strerror(result)); + return -result; + } + } + + return 0; +} + +int lo_server_thread_get_port(lo_server_thread st) +{ + return lo_server_get_port(st->s); +} + +char *lo_server_thread_get_url(lo_server_thread st) +{ + return lo_server_get_url(st->s); +} + +lo_server lo_server_thread_get_server(lo_server_thread st) +{ + return st->s; +} + +int lo_server_thread_events_pending(lo_server_thread st) +{ + return lo_server_events_pending(st->s); +} + +static void thread_func(void *data) +{ + lo_server_thread st = (lo_server_thread)data; + + while (st->active) { + lo_server_recv_noblock(st->s, 10); + } + st->done = 1; + + pthread_exit(NULL); +} + +void lo_server_thread_pp(lo_server_thread st) +{ + lo_server_pp(st->s); +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/subtest.c b/liblo/src/subtest.c new file mode 100644 index 0000000..dc010b5 --- /dev/null +++ b/liblo/src/subtest.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2005 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include +#include +#include +#ifndef _MSC_VER +#include +#endif + +#include "lo/lo.h" + +int subtest_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data); + +int main(int argc, char *argv[]) +{ + lo_server st = lo_server_thread_new(NULL, NULL); + lo_address t; + + if (argc != 2) { + fprintf(stderr, "Usage: subtest \n"); + + return 1; + } + + lo_server_thread_add_method(st, NULL, "i", subtest_handler, NULL); + lo_server_thread_start(st); + + t = lo_address_new_from_url(argv[1]); + lo_send(t, "/subtest", "i", 0xf00); + +#ifdef WIN32 + Sleep(4000); +#else + sleep(4); +#endif + + return 0; +} + +int subtest_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data) +{ + int i; + lo_address a = lo_message_get_source(data); + static char *uri = NULL; + + printf("subtest: got reply (%s)\n", path); + if (!uri) { + uri = lo_address_get_url(a); + } else { + char *new_uri = lo_address_get_url(a); + + if (strcmp(uri, new_uri)) { + printf("ERROR: %s != %s\n", uri, new_uri); + + exit(1); + } + free(new_uri); + } + lo_send(a, "/subtest-reply", "i", 0xbaa); + if (lo_address_errno(a)) { + fprintf(stderr, "subtest error %d: %s\n", lo_address_errno(a), + lo_address_errstr(a)); + + exit(1); + } + + for (i=0; i<10; i++) { +#ifdef WIN32 + /* TODO: Wait time of 2.233 not easily doable in Windows */ + Sleep(2); +#else + usleep(2233); +#endif + lo_send(a, "/subtest-reply", "i", 0xbaa+i); + } + + return 0; +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/testlo.c b/liblo/src/testlo.c new file mode 100644 index 0000000..9718aa9 --- /dev/null +++ b/liblo/src/testlo.c @@ -0,0 +1,1193 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +/* + * This is some testcase code - it exercises the internals of liblo, so its not + * a good example to learn from, see examples/ for example code + */ + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#else +#include +#endif + +#include "lo_types_internal.h" +#include "lo_internal.h" +#include "lo/lo.h" +#include "config.h" + +#ifdef WIN32 +#define PATHDELIM "\\" +#else +#define PATHDELIM "/" +#endif + +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +#define TEST(cond) if (!(cond)) { fprintf(stderr, "FAILED " #cond \ + " at %s:%d\n", __FILE__, __LINE__); \ + exit(1); } \ + else { printf("passed " #cond "\n"); } + +union end_test32 { + uint32_t i; + char c[4]; +}; + +union end_test64 { + uint64_t i; + char c[8]; +}; + +static int done = 0; +static int bundle_count = 0; +static int pattern_count = 0; +static int reply_count = 0; +static int subtest_count = 0; +static int subtest_reply_count = 0; +static int error_okay = 0; + +char testdata[5] = "ABCDE"; + +static int jitter_count = 0; +static float jitter_total = 0.0f; +static float jitter_max = 0.0f; +static float jitter_min = 1000.0f; + +void exitcheck(void); +void test_deserialise(void); +void test_validation(lo_address a); +void test_multicast(lo_server_thread st); +void error(int num, const char *m, const char *path); +void rep_error(int num, const char *m, const char *path); + +int generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data); + +int foo_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data); + +int reply_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data); + +int lots_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data); + +int coerce_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data); + +int bundle_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data); + +int timestamp_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data); + +int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data); + +int pattern_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data); + +int subtest_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data); + +int subtest_reply_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data); + +int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data); + +int test_varargs(lo_address a, const char *path, const char *types, ...); + +int main() +{ + lo_blob btest = lo_blob_new(sizeof(testdata), testdata); + lo_server_thread st, sta, stb; + lo_server s = lo_server_new(NULL, error); + lo_bundle b; + lo_message m1, m2; + char *server_url, *path, *protocol, *host, *port; + const char *host2, *port2; + lo_address a; + uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00}; + union end_test32 et32; + union end_test64 et64; + lo_timetag tt = {0x1, 0x80000000}, sched; + int count; + int proto; + char cmd[256]; + + test_deserialise(); + + sta = lo_server_thread_new("7591", error); + stb = lo_server_thread_new("7591", rep_error); + if (stb) { + fprintf(stderr, "FAILED: create bad server thread object!\n"); + exit(1); + } + lo_server_thread_free(sta); + + /* leak check */ + st = lo_server_thread_new(NULL, error); + lo_server_thread_start(st); +#ifdef WIN32 + Sleep(4); +#else + usleep(4000); +#endif + lo_server_thread_stop(st); + lo_server_thread_free(st); + st = lo_server_thread_new(NULL, error); + lo_server_thread_start(st); + lo_server_thread_stop(st); + lo_server_thread_free(st); + st = lo_server_thread_new(NULL, error); + lo_server_thread_free(st); + st = lo_server_thread_new(NULL, error); + lo_server_thread_free(st); + st = lo_server_thread_new(NULL, error); + + a = lo_address_new_from_url("osc://localhost/"); + TEST(a != NULL); + lo_address_free(a); + + a = lo_address_new_from_url("osc.://localhost/"); + TEST(a == NULL); + + + atexit(exitcheck); + + printf("type tests\n"); + TEST(sizeof(float) == sizeof(int32_t)); + TEST(sizeof(double) == sizeof(int64_t)); + + et32.i = 0x23242526U; + et32.i = lo_htoo32(et32.i); + if (et32.c[0] != 0x23 || et32.c[1] != 0x24 || et32.c[2] != 0x25 || + et32.c[3] != 0x26) { + fprintf(stderr, "failed 32bit endian conversion test\n"); + fprintf(stderr, "0x23242526 -> %X\n", et32.i); + exit(1); + } else { + printf("passed 32bit endian conversion test\n"); + } + + et64.i = 0x232425262728292AULL; + et64.i = lo_htoo64(et64.i); + if (et64.c[0] != 0x23 || et64.c[1] != 0x24 || et64.c[2] != 0x25 || + et64.c[3] != 0x26 || et64.c[4] != 0x27 || et64.c[5] != 0x28 || + et64.c[6] != 0x29 || et64.c[7] != 0x2A) { + fprintf(stderr, "failed 64bit endian conversion\n"); + fprintf(stderr, "0x232425262728292A -> %llX\n", (long long unsigned int)et64.i); + exit(1); + } else { + printf("passed 64bit endian conversion\n"); + } + printf("\n"); + + /* OSC URL tests */ + path = lo_url_get_path("osc.udp://localhost:9999/a/path/is/here"); + if (strcmp(path, "/a/path/is/here")) { + printf("failed lo_url_get_path() test1\n"); + printf("'%s' != '/a/path/is/here'\n", path); + exit(1); + } else { + printf("passed lo_url_get_path() test1\n"); + } + free(path); + + protocol = lo_url_get_protocol("osc.udp://localhost:9999/a/path/is/here"); + if (strcmp(protocol, "udp")) { + printf("failed lo_url_get_protocol() test1\n"); + printf("'%s' != 'udp'\n", protocol); + exit(1); + } else { + printf("passed lo_url_get_protocol() test1\n"); + } + free(protocol); + + protocol = lo_url_get_protocol("osc.tcp://localhost:9999/a/path/is/here"); + if (strcmp(protocol, "tcp")) { + printf("failed lo_url_get_protocol() test2\n"); + printf("'%s' != 'tcp'\n", protocol); + exit(1); + } else { + printf("passed lo_url_get_protocol() test2\n"); + } + free(protocol); + + protocol = lo_url_get_protocol("osc.udp://[::ffff:localhost]:9999/a/path/is/here"); + if (strcmp(protocol, "udp")) { + printf("failed lo_url_get_protocol() test1 (IPv6)\n"); + printf("'%s' != 'udp'\n", protocol); + exit(1); + } else { + printf("passed lo_url_get_protocol() test1 (IPv6)\n"); + } + free(protocol); + + proto = lo_url_get_protocol_id("osc.udp://localhost:9999/a/path/is/here"); + if (proto != LO_UDP) { + printf("failed lo_url_get_protocol_id() test1\n"); + printf("'%d' != LO_UDP\n", proto); + exit(1); + } else { + printf("passed lo_url_get_protocol_id() test1\n"); + } + + proto = lo_url_get_protocol_id("osc.tcp://localhost:9999/a/path/is/here"); + if (proto != LO_TCP) { + printf("failed lo_url_get_protocol_id() test2\n"); + printf("'%d' != LO_TCP\n", proto); + exit(1); + } else { + printf("passed lo_url_get_protocol_id() test2\n"); + } + + proto = lo_url_get_protocol_id("osc.invalid://localhost:9999/a/path/is/here"); + if (proto != -1) { + printf("failed lo_url_get_protocol_id() test3\n"); + printf("'%d' != -1\n", proto); + exit(1); + } else { + printf("passed lo_url_get_protocol_id() test3\n"); + } + + proto = lo_url_get_protocol_id("osc.udp://[::ffff:localhost]:9999/a/path/is/here"); + if (proto != LO_UDP) { + printf("failed lo_url_get_protocol_id() test1 (IPv6)\n"); + printf("'%d' != LO_UDP\n", proto); + exit(1); + } else { + printf("passed lo_url_get_protocol_id() test1 (IPv6)\n"); + } + + host = lo_url_get_hostname("osc.udp://foo.example.com:9999/a/path/is/here"); + if (strcmp(host, "foo.example.com")) { + printf("failed lo_url_get_hostname() test1\n"); + printf("'%s' != 'foo.example.com'\n", host); + exit(1); + } else { + printf("passed lo_url_get_hostname() test1\n"); + } + free(host); + + host = lo_url_get_hostname("osc.udp://[0000::::0001]:9999/a/path/is/here"); + if (strcmp(host, "0000::::0001")) { + printf("failed lo_url_get_hostname() test2 (IPv6)\n"); + printf("'%s' != '0000::::0001'\n", host); + exit(1); + } else { + printf("passed lo_url_get_hostname() test2 (IPv6)\n"); + } + free(host); + + port = lo_url_get_port("osc.udp://localhost:9999/a/path/is/here"); + if (strcmp(port, "9999")) { + printf("failed lo_url_get_port() test1\n"); + printf("'%s' != '9999'\n", port); + exit(1); + } else { + printf("passed lo_url_get_port() test1\n"); + } + free(port); + + port = lo_url_get_port("osc.udp://[::ffff:127.0.0.1]:9999/a/path/is/here"); + if (strcmp(port, "9999")) { + printf("failed lo_url_get_port() test1 (IPv6)\n"); + printf("'%s' != '9999'\n", port); + exit(1); + } else { + printf("passed lo_url_get_port() test1 (IPv6)\n"); + } + free(port); + printf("\n"); + + + + + + a = lo_address_new_from_url("osc.tcp://foo.example.com:9999/"); + host2 = lo_address_get_hostname(a); + if (strcmp(host2, "foo.example.com")) { + printf("failed lo_address_get_hostname() test\n"); + printf("'%s' != 'foo.example.com'\n", host2); + exit(1); + } else { + printf("passed lo_address_get_hostname() test\n"); + } + + port2 = lo_address_get_port(a); + if (strcmp(port2, "9999")) { + printf("failed lo_address_get_port() test\n"); + printf("'%s' != '9999'\n", port2); + exit(1); + } else { + printf("passed lo_address_get_port() test\n"); + } + + proto = lo_address_get_protocol(a); + if (proto != LO_TCP) { + printf("failed lo_address_get_protocol() test\n"); + printf("'%d' != '%d'\n", proto, LO_TCP); + exit(1); + } else { + printf("passed lo_address_get_protocol() test\n"); + } + + server_url = lo_address_get_url(a); + if (strcmp(server_url, "osc.tcp://foo.example.com:9999/")) { + printf("failed lo_address_get_url() test\n"); + printf("'%s' != '%s'\n", server_url, "osc.tcp://foo.example.com:9999/"); + exit(1); + } else { + printf("passed lo_address_get_url() test\n"); + } + free(server_url); + lo_address_free( a ); + printf("\n"); + + + /* Test blod sizes */ + if (lo_blob_datasize(btest) != 5 || lo_blobsize(btest) != 12) { + printf("blob is %d (%d) bytes long, should be 5 (12)\n", + lo_blob_datasize(btest), lo_blobsize(btest)); + lo_arg_pp(LO_BLOB, btest); + printf(" <- blob\n"); + exit(1); + } + + + + /* Server method handler tests */ + server_url = lo_server_thread_get_url(st); + a = lo_address_new_from_url(server_url); + printf("Server URL: %s\n", server_url); + free(server_url); + + /* add method that will match the path /foo/bar, with two numbers, coerced + * to float and int */ + + lo_server_thread_add_method(st, "/foo/bar", "fi", foo_handler, lo_server_thread_get_server(st)); + + lo_server_thread_add_method(st, "/reply", "s", reply_handler, NULL); + + lo_server_thread_add_method(st, "/lotsofformats", "fisbmhtdSccTFNI", + lots_handler, NULL); + + lo_server_thread_add_method(st, "/coerce", "dfhiSs", + coerce_handler, NULL); + + lo_server_thread_add_method(st, "/bundle", NULL, + bundle_handler, NULL); + lo_server_thread_add_method(st, "/timestamp", NULL, + timestamp_handler, NULL); + lo_server_thread_add_method(st, "/jitter", "ti", + jitter_handler, NULL); + + lo_server_thread_add_method(st, "/pattern/foo", NULL, + pattern_handler, "foo"); + lo_server_thread_add_method(st, "/pattern/bar", NULL, + pattern_handler, "bar"); + lo_server_thread_add_method(st, "/pattern/baz", NULL, + pattern_handler, "baz"); + + lo_server_thread_add_method(st, "/subtest", "i", + subtest_handler, st); + + lo_server_thread_add_method(st, "/subtest-reply", "i", + subtest_reply_handler, NULL); + + /* add method that will match any path and args */ + lo_server_thread_add_method(st, NULL, NULL, generic_handler, NULL); + + /* add method that will match the path /quit with no args */ + lo_server_thread_add_method(st, "/quit", "", quit_handler, NULL); + + /* check that the thread restarts */ + lo_server_thread_start(st); + lo_server_thread_stop(st); + lo_server_thread_start(st); + + if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) { + printf("OSC error A %d: %s\n", lo_address_errno(a), lo_address_errstr(a)); + exit(1); + } + + if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) { + printf("OSC error B %d: %s\n", lo_address_errno(a), lo_address_errstr(a)); + exit(1); + } + + test_validation(a); + test_multicast(st); + + lo_send(a, "/", "i", 242); + lo_send(a, "/pattern/", "i", 243); + +#ifndef _MSC_VER /* MS compiler refuses to compile this case */ + lo_send(a, "/bar", "ff", 0.12345678f, 1.0/0.0); +#endif + lo_send(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123, "123", + btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym", + 'X', 'Y'); + lo_send(a, "/coerce", "fdihsS", 0.1f, 0.2, 123, 124LL, "aaa", "bbb"); + lo_send(a, "/coerce", "ffffss", 0.1f, 0.2f, 123.0, 124.0, "aaa", "bbb"); + lo_send(a, "/coerce", "ddddSS", 0.1, 0.2, 123.0, 124.0, "aaa", "bbb"); + lo_send(a, "/a/b/c/d", "sfsff", "one", 0.12345678f, "three", + -0.00000023001f, 1.0); + lo_send(a, "/a/b/c/d", "b", btest); + + TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123, + "123", btest, midi_data, 0x0123456789abcdefULL, tt, + 0.9999, "sym", 'X', 'Y', LO_ARGS_END) == 0); + +#ifdef __GNUC__ + // Note: Lack of support for variable-argument macros in non-GCC compilers + // does not allow us to test for these conditions. + + // too many args + TEST(test_varargs(a, "/lotsofformats", "f", 0.12345678f, 123, + "123", btest, midi_data, 0x0123456789abcdefULL, tt, + 0.9999, "sym", 'X', 'Y', LO_ARGS_END) != 0); + // too many types + TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123, + "123", btest, midi_data, 0x0123456789abcdefULL, tt, 0.5, + LO_ARGS_END) != 0); +#endif + + // test lo_message_add + m1 = lo_message_new(); + TEST(lo_message_add(m1, "fisbmhtdSccTFNI", 0.12345678f, 123, "123", + btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym", + 'X', 'Y') == 0); + lo_send_message(a, "/lotsofformats", m1); + lo_message_free(m1); + + lo_blob_free(btest); + + lo_send(a, "/pattern/*", "s", "a"); + lo_send(a, "/pattern/ba[rz]", "s", "b"); + + server_url = lo_server_thread_get_url(st); + sprintf(cmd, "." PATHDELIM "subtest %s &", server_url); + if (system(cmd) != 0) { + fprintf(stderr, "Cannot execute subtest command\n"); + exit(1); + } + system(cmd); + free(server_url); + +#ifdef WIN32 + Sleep(2000); +#else + sleep(2); +#endif + TEST(reply_count == 3); + TEST(pattern_count == 5); + TEST(subtest_count == 2); + TEST(subtest_reply_count == 22); + printf("\n"); + + { + lo_timetag t = {10,0xFFFFFFFC}; + b = lo_bundle_new(t); + } + m1 = lo_message_new(); + lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz"); + lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + lo_bundle_add_message(b, "/bundle", m1); + lo_send_bundle(a, b); + + /* This should be safe for multiple copies of the same message. */ + lo_bundle_free_messages(b); + + { + lo_timetag t = {1,2}; + b = lo_bundle_new(t); + } + m1 = lo_message_new(); + lo_message_add_int32(m1, 23); + lo_message_add_string(m1, "23"); + lo_bundle_add_message(b, "/bundle", m1); + m2 = lo_message_new(); + lo_message_add_string(m2, "24"); + lo_message_add_int32(m2, 24); + lo_bundle_add_message(b, "/bundle", m2); + lo_bundle_add_message(b, "/bundle", m1); + +/* + lo_send_bundle(a, b); + if (a->errnum) { + printf("error %d: %s\n", a->errnum, a->errstr); + exit(1); + } +*/ + TEST(lo_send_bundle(a, b) == 88); + + /* Test freeing out-of-order copies of messages in a bundle. */ + lo_bundle_free_messages(b); + + { + lo_timetag t = {10,0xFFFFFFFE}; + b = lo_bundle_new(t); + } + m1 = lo_message_new(); + lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz"); + lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + lo_bundle_add_message(b, "/bundle", m1); + lo_send_bundle(a, b); + lo_message_free(m1); + lo_bundle_free(b); + + lo_timetag_now(&sched); + + sched.sec += 5; + b = lo_bundle_new(sched); + m1 = lo_message_new(); + lo_message_add_string(m1, "future"); + lo_message_add_string(m1, "time"); + lo_message_add_string(m1, "test"); + lo_bundle_add_message(b, "/bundle", m1); + + lo_send_bundle(a, b); + lo_message_free(m1); + lo_bundle_free(b); + + lo_send_timestamped(a, sched, "/bundle", "s", "lo_send_timestamped() test"); + + /* test bundle timestamp ends up in message struct (and doesn't end up in + unbundled messages) */ + lo_timetag_now(&sched); + lo_send_timestamped(a, sched, "/timestamp", "it", 1, sched); + lo_send(a, "/timestamp", "it", 0, sched); + +#define JITTER_ITS 25 + /* jitter tests */ + { + lo_timetag stamps[JITTER_ITS]; + lo_timetag now; + int i; + + for (i=0; i= 1000) { + printf("lo_server_recv_noblock() test failed\n"); + + exit(1); + } + + /* Delete methods */ + lo_server_thread_del_method(st, "/coerce", "dfhiSs"); + lo_server_del_method(s, NULL, NULL); + + lo_address_free(a); + lo_server_free(s); + free(server_url); + +#ifndef WIN32 + { /* UNIX domain tests */ + lo_address ua; + lo_server us; + char *addr; + + unlink("/tmp/testlo.osc"); + us = lo_server_new_with_proto("/tmp/testlo.osc", LO_UNIX, error); + ua = lo_address_new_from_url("osc.unix:///tmp/testlo.osc"); + TEST(lo_server_get_protocol(us) == LO_UNIX); + TEST(lo_send(ua, "/unix", "f", 23.0) == 16); + TEST(lo_server_recv(us) == 16); + addr = lo_server_get_url(us); + TEST(!strcmp("osc.unix:////tmp/testlo.osc", addr)); + free(addr); + lo_address_free(ua); + ua = lo_address_new_with_proto(LO_UNIX, NULL, "/tmp/testlo.osc"); + TEST(lo_send(ua, "/unix", "f", 23.0) == 16); + TEST(lo_server_recv(us) == 16); + lo_server_free(us); + lo_address_free(ua); + } +#endif + + { /* TCP tests */ + lo_address ta; + lo_server ts; + char *addr; + + ts = lo_server_new_with_proto(NULL, LO_TCP, error); + addr = lo_server_get_url(ts); + ta = lo_address_new_from_url(addr); + if (lo_address_errno(ta)) { + printf("err: %s\n", lo_address_errstr(ta)); + exit(1); + } + TEST(lo_server_get_protocol(ts) == LO_TCP); + TEST(lo_send(ta, "/tcp", "f", 23.0) == 16); + TEST(lo_send(ta, "/tcp", "f", 23.0) == 16); + TEST(lo_server_recv(ts) == 16); + TEST(lo_server_recv(ts) == 16); + free(addr); + lo_server_free(ts); + lo_address_free(ta); + } + + server_url = lo_server_thread_get_url(st); + a = lo_address_new_from_url(server_url); + /* exit */ + lo_send(a, "/quit", NULL); + lo_address_free(a); + + while (!done) { +#ifdef WIN32 + Sleep(1); +#else + usleep(1000); +#endif + } + + lo_server_thread_free(st); + free(server_url); + + + return 0; +} + +void exitcheck(void) +{ + if (!done) { + fprintf(stderr, "\ntest run not completed\n" PACKAGE_NAME + " test FAILED\n"); + } else { + printf(PACKAGE_NAME " test PASSED\n"); + } +} + +void error(int num, const char *msg, const char *path) +{ + printf("liblo server error %d in %s: %s", num, path, msg); + if (!error_okay) + exit(1); + else + printf(" (expected)\n"); +} + +void rep_error(int num, const char *msg, const char *path) +{ + if (num != 9904) { + error(num, msg, path); + } +} + +int generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data) +{ + int i; + + printf("path: <%s>\n", path); + for (i=0; if, argv[1]->i); + if (lo_send_from(src, serv, LO_TT_IMMEDIATE, "/reply", "s", "a reply") == -1) { + printf("OSC reply error %d: %s\nSending to %s\n", lo_address_errno(src), lo_address_errstr(src), url); + exit(1); + } else { + printf("Reply sent to %s\n\n", url); + } + free(server_url); + free(url); + + return 0; +} + +int reply_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data) +{ + lo_address src = lo_message_get_source(data); + char *url = lo_address_get_url(src); + printf("Reply received from %s\n", url); + free(url); + reply_count++; + + return 0; +} + +int lots_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data) +{ + lo_blob b; + unsigned char *d; + + if (strcmp(path, "/lotsofformats")) { + fprintf(stderr, "path != /lotsofformats\n"); + exit(1); + } + printf("path = %s\n", path); + TEST(types[0] == 'f' && argv[0]->f == 0.12345678f); + TEST(types[1] == 'i' && argv[1]->i == 123); + TEST(types[2] == 's' && !strcmp(&argv[2]->s, "123")); + b = (lo_blob)argv[3]; + d = lo_blob_dataptr(b); + TEST(types[3] == 'b' && lo_blob_datasize(b) == 5); + TEST(d[0] == 'A' && d[1] == 'B' && d[2] == 'C' && d[3] == 'D' && + d[4] == 'E'); + d = argv[4]->m; + TEST(d[0] == 0xff && d[1] == 0xf7 && d[2] == 0xaa && d[3] == 0x00); + TEST(types[5] == 'h' && argv[5]->h == 0x0123456789ABCDEFULL); + TEST(types[6] == 't' && argv[6]->t.sec == 1 && \ + argv[6]->t.frac == 0x80000000); + TEST(types[7] == 'd' && argv[7]->d == 0.9999); + TEST(types[8] == 'S' && !strcmp(&argv[8]->S, "sym")); +printf("char: %d\n", argv[9]->c); + TEST(types[9] == 'c' && argv[9]->c == 'X'); + TEST(types[10] == 'c' && argv[10]->c == 'Y'); + TEST(types[11] == 'T'); + TEST(types[12] == 'F'); + TEST(types[13] == 'N'); + TEST(types[14] == 'I'); + + printf("\n"); + + return 0; +} + +int coerce_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data) +{ + printf("path = %s\n", path); + TEST(types[0] == 'd' && fabs(argv[0]->d - 0.1) < FLT_EPSILON); + TEST(types[1] == 'f' && fabs(argv[1]->f - 0.2) < FLT_EPSILON); + TEST(types[2] == 'h' && argv[2]->h == 123); + TEST(types[3] == 'i' && argv[3]->i == 124); + TEST(types[4] == 'S' && !strcmp(&argv[4]->S, "aaa")); + TEST(types[5] == 's' && !strcmp(&argv[5]->s, "bbb")); + printf("\n"); + + return 0; +} + +int bundle_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data) +{ + bundle_count++; + printf("received bundle\n"); + + return 0; +} + +int timestamp_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data) +{ + int bundled = argv[0]->i; + + lo_timetag ts, arg_ts; + ts = lo_message_get_timestamp(data); + arg_ts = argv[1]->t; + + if (bundled) { + TEST((ts.sec == arg_ts.sec) && (ts.frac == arg_ts.frac)); + } + else { + TEST(ts.sec == LO_TT_IMMEDIATE.sec && ts.frac == LO_TT_IMMEDIATE.frac); + } + return 0; +} + +int jitter_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data) +{ + lo_timetag now; + float jitter; + + lo_timetag_now(&now); + jitter = fabs(lo_timetag_diff(now, argv[0]->t)); + jitter_count++; + //printf("jitter: %f\n", jitter); + printf("%d expected: %x:%x received %x:%x\n", argv[1]->i, argv[0]->t.sec, + argv[0]->t.frac, now.sec, now.frac); + jitter_total += jitter; + if (jitter > jitter_max) jitter_max = jitter; + if (jitter < jitter_min) jitter_min = jitter; + + return 0; +} + +int pattern_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data) +{ + pattern_count++; + printf("pattern matched %s\n", (char *)user_data); + + return 0; +} + +int subtest_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data) +{ + lo_address a = lo_message_get_source(data); + + subtest_count++; + printf("got subtest message %d\n", subtest_count); + lo_send_from(a, lo_server_thread_get_server(user_data), + LO_TT_IMMEDIATE, "/subtest", "i", subtest_count); + + return 0; +} + +int subtest_reply_handler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message data, void *user_data) +{ + subtest_reply_count++; + //printf("got subtest reply message %d\n", subtest_reply_count); + + return 0; +} + +int quit_handler(const char *path, const char *types, lo_arg **argv, int argc, + lo_message data, void *user_data) +{ + done = 1; + + return 0; +} + +int test_varargs(lo_address a, const char *path, const char *types, ...) +{ + va_list ap; + lo_message m = lo_message_new(); + int error; + va_start(ap, types); + if ((error=lo_message_add_varargs(m, types, ap))==0) + lo_send_message(a, path, m); + else + printf("lo_message_add_varargs returned %d\n", error); + lo_message_free(m); + return error<0; +} + +void replace_char(char *str, size_t size, const char find, const char replace) +{ + char *p = str; + while(size--) + { + if (find == *p) { *p = replace; } + ++p; + } +} + +void test_deserialise() +{ + char *buf, *buf2, *tmp; + const char *types = NULL, *path; + lo_arg **argv = NULL; + size_t len, size; + char data[256]; + int result = 0; + + lo_blob btest = lo_blob_new(sizeof(testdata), testdata); + uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00}; + lo_timetag tt = {0x1, 0x80000000}; + lo_blob b = NULL; + + // build a message + lo_message msg = lo_message_new(); + TEST(0 == lo_message_get_argc(msg)); + lo_message_add_float(msg, 0.12345678f); // 0 f + lo_message_add_int32(msg, 123); // 1 i + lo_message_add_string(msg, "123"); // 2 s + lo_message_add_blob(msg, btest); // 3 b + lo_message_add_midi(msg, midi_data); // 4 m + lo_message_add_int64(msg, 0x0123456789abcdefULL); // 5 h + lo_message_add_timetag(msg, tt); // 6 t + lo_message_add_double(msg, 0.9999); // 7 d + lo_message_add_symbol(msg, "sym"); // 8 S + lo_message_add_char(msg, 'X'); // 9 c + lo_message_add_char(msg, 'Y'); // 10 c + lo_message_add_true(msg); // 11 T + lo_message_add_false(msg); // 12 F + lo_message_add_nil(msg); // 13 N + lo_message_add_infinitum(msg); // 14 I + + // test types, args + TEST(15 == lo_message_get_argc(msg)); + types = lo_message_get_types(msg); + TEST(NULL != types); + argv = lo_message_get_argv(msg); + TEST(NULL != argv); + TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON); + TEST('i' == types[1] && 123 == argv[1]->i); + TEST('s' == types[2] && !strcmp(&argv[2]->s, "123")); + TEST('b' == types[3]); + b = (lo_blob)argv[3]; + TEST(lo_blob_datasize(b) == sizeof(testdata)); + TEST(12 == lo_blobsize(b)); + TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata))); + TEST('m' == types[4] && !memcmp(&argv[4]->m, midi_data, 4)); + TEST('h' == types[5] && 0x0123456789abcdefULL == argv[5]->h); + TEST('t' == types[6] && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac); + TEST('d' == types[7] && fabs(argv[7]->d - 0.9999) < FLT_EPSILON); + TEST('S' == types[8] && !strcmp(&argv[8]->s, "sym")); + TEST('c' == types[9] && 'X' == argv[9]->c); + TEST('c' == types[10] && 'Y' == argv[10]->c); + TEST('T' == types[11] && NULL == argv[11]); + TEST('F' == types[12] && NULL == argv[12]); + TEST('N' == types[13] && NULL == argv[13]); + TEST('I' == types[14] && NULL == argv[14]); + + // serialise it + len = lo_message_length(msg, "/foo"); + printf("serialise message_length=%d\n", (int)len); + buf = calloc(len, sizeof(char)); + size = 0; + tmp = lo_message_serialise(msg, "/foo", buf, &size); + TEST(tmp == buf && size == len && 92 == len); + lo_message_free(msg); + + // deserialise it + printf("deserialise\n"); + path = lo_get_path(buf, len); + TEST(NULL != path && !strcmp(path, "/foo")); + msg = lo_message_deserialise(buf, size, NULL); + TEST(NULL != msg); + + // repeat same test as above + TEST(15 == lo_message_get_argc(msg)); + types = lo_message_get_types(msg); + TEST(NULL != types); + argv = lo_message_get_argv(msg); + TEST(NULL != argv); + TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON); + TEST('i' == types[1] && 123 == argv[1]->i); + TEST('s' == types[2] && !strcmp(&argv[2]->s, "123")); + TEST('b' == types[3]); + b = (lo_blob)argv[3]; + TEST(lo_blob_datasize(b) == sizeof(testdata)); + TEST(12 == lo_blobsize(b)); + TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata))); + TEST('m' == types[4] && !memcmp(&argv[4]->m, midi_data, 4)); + TEST('h' == types[5] && 0x0123456789abcdefULL == argv[5]->h); + TEST('t' == types[6] && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac); + TEST('d' == types[7] && fabs(argv[7]->d - 0.9999) < FLT_EPSILON); + TEST('S' == types[8] && !strcmp(&argv[8]->s, "sym")); + TEST('c' == types[9] && 'X' == argv[9]->c); + TEST('c' == types[10] && 'Y' == argv[10]->c); + TEST('T' == types[11] && NULL == argv[11]); + TEST('F' == types[12] && NULL == argv[12]); + TEST('N' == types[13] && NULL == argv[13]); + TEST('I' == types[14] && NULL == argv[14]); + + // serialise it again, compare + len = lo_message_length(msg, "/foo"); + printf("serialise message_length=%d\n", (int)len); + buf2 = calloc(len, sizeof(char)); + size = 0; + tmp = lo_message_serialise(msg, "/foo", buf2, &size); + TEST(tmp == buf2 && size == len && 92 == len); + TEST(!memcmp(buf, buf2, len)); + lo_message_free(msg); + + lo_blob_free(btest); + free(buf); + free(buf2); + + // deserialise failure tests with invalid message data + + msg = lo_message_deserialise(data, 0, &result); // 0 size + TEST(NULL == msg && LO_ESIZE == result); + + snprintf(data, 256, "%s", "/foo"); // unterminated path string + msg = lo_message_deserialise(data, 4, &result); + TEST(NULL == msg && LO_EINVALIDPATH == result); + + snprintf(data, 256, "%s", "/f_o"); // non-0 in pad area + msg = lo_message_deserialise(data, 4, &result); + TEST(NULL == msg && LO_EINVALIDPATH == result); + + snprintf(data, 256, "%s", "/t__"); // types missing + replace_char(data, 4, '_', '\0'); + msg = lo_message_deserialise(data, 4, &result); + TEST(NULL == msg && LO_ENOTYPE == result); + + snprintf(data, 256, "%s%s", "/t__", "____"); // types empty + replace_char(data, 8, '_', '\0'); + msg = lo_message_deserialise(data, 8, &result); + TEST(NULL == msg && LO_EBADTYPE == result); + + snprintf(data, 256, "%s%s", "/t__", ",f_"); // short message + replace_char(data, 7, '_', '\0'); + msg = lo_message_deserialise(data, 7, &result); + TEST(NULL == msg && LO_EINVALIDTYPE == result); + + snprintf(data, 256, "%s%s", "/t__", "ifi_"); // types missing comma + replace_char(data, 8, '_', '\0'); + msg = lo_message_deserialise(data, 8, &result); + TEST(NULL == msg && LO_EBADTYPE == result); + + snprintf(data, 256, "%s%s", "/t__", ",ifi"); // types unterminated + replace_char(data, 8, '_', '\0'); + msg = lo_message_deserialise(data, 8, &result); + TEST(NULL == msg && LO_EINVALIDTYPE == result); + + snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data + replace_char(data, 8, '_', '\0'); + msg = lo_message_deserialise(data, 12, &result); + TEST(NULL == msg && LO_EINVALIDARG == result); + + snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data again + replace_char(data, 8, '_', '\0'); + msg = lo_message_deserialise(data, 15, &result); + TEST(NULL == msg && LO_EINVALIDARG == result); + + snprintf(data, 256, "%s%s", "/t__", ",f__"); // too much arg data + replace_char(data, 8, '_', '\0'); + msg = lo_message_deserialise(data, 16, &result); + TEST(NULL == msg && LO_ESIZE == result); + + snprintf(data, 256, "%s%s", "/t__", ",bs_"); // blob longer than msg length + replace_char(data, 8, '_', '\0'); + *(uint32_t *)(data + 8) = lo_htoo32((uint32_t)99999); + msg = lo_message_deserialise(data, 256, &result); + TEST(NULL == msg && LO_EINVALIDARG == result); +} + +void test_validation(lo_address a) +{ + /* packet crafted to crash a lo_server when no input validation is performed */ + char mem[] = {"/\0\0\0,bs\0,\x00\x0F\x42\x3F"}; // OSC: "/" ",bs" 999999 + int eok = error_okay; + int sock = a->socket; + + /* This code won't work with MSVC because the lo_client_sockets data structure + * is not explicitly made available to external programs. We could expose it + * in debug mode, perhaps, but let's just skip this test for now. (Can be tested + * on Windows using MingW.) */ +#ifdef _MSC_VER + return; +#else + + printf("validation\n"); + + if (sock == -1) + sock = lo_client_sockets.udp; + if (sock == -1) { + fprintf(stderr, "Couldn't get socket in test_validation(), %s:%d\n", __FILE__, __LINE__); + exit(1); + } + + error_okay = 1; + if (sendto(sock, &mem, sizeof(mem), MSG_NOSIGNAL, + a->ai->ai_addr, a->ai->ai_addrlen)==-1) { + fprintf(stderr, "Error sending packet in test_validation(), %s:%d\n", __FILE__, __LINE__); + } +#ifndef WIN32 + usleep(10000); +#else + Sleep(10); +#endif + error_okay = eok; +#endif +} + +void test_multicast(lo_server_thread st) +{ + /* test multicast server and sender */ + /* message is sent from st otherwise reply doesn't work */ + lo_server ms = lo_server_new_multicast("224.0.1.1", "15432", error); + lo_address ma = lo_address_new("224.0.1.1", "15432"); + lo_address_set_ttl(ma, 1); + lo_server_add_method(ms, "/foo/bar", "fi", foo_handler, ms); + lo_server_add_method(ms, "/reply", "s", reply_handler, NULL); + if (lo_send_from(ma, lo_server_thread_get_server(st), LO_TT_IMMEDIATE, + "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) { + printf("multicast send error %d: %s\n", lo_address_errno(ma), lo_address_errstr(ma)); + exit(1); + } + TEST(lo_server_recv(ms)==24); + lo_server_free(ms); + lo_address_free(ma); +} + +/* vi:set ts=8 sts=4 sw=4: */ diff --git a/liblo/src/timetag.c b/liblo/src/timetag.c new file mode 100644 index 0000000..e5b0966 --- /dev/null +++ b/liblo/src/timetag.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2004 Steve Harris + * + * 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 2.1 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. + * + * $Id$ + */ + +#include "lo_types_internal.h" +#include "lo/lo.h" + +#ifdef _MSC_VER +lo_timetag lo_get_tt_immediate() { lo_timetag tt = {0U,1U}; return tt; } +#else +#include +#endif +#include + +#define JAN_1970 0x83aa7e80 /* 2208988800 1970 - 1900 in seconds */ + +double lo_timetag_diff(lo_timetag a, lo_timetag b) +{ + return (double)a.sec - (double)b.sec + + ((double)a.frac - (double)b.frac) * 0.00000000023283064365; +} + +void lo_timetag_now(lo_timetag *t) +{ +#ifdef WIN32 + /* + FILETIME is the time in units of 100 nsecs from 1601-Jan-01 + 1601 and 1900 are 9435484800 seconds apart. + */ + FILETIME ftime; + double dtime; + GetSystemTimeAsFileTime(&ftime); + dtime = + ((ftime.dwHighDateTime*4294967296.e-7)-9435484800.)+ + (ftime.dwLowDateTime*1.e-7); + + t->sec = (uint32_t)dtime; + t->frac = (uint32_t)((dtime-t->sec)*4294967296.); +#else + struct timeval tv; + + gettimeofday(&tv, NULL); + t->sec = tv.tv_sec + JAN_1970; + t->frac = tv.tv_usec * 4294.967295; +#endif +} diff --git a/liblo/src/tools/Makefile.am b/liblo/src/tools/Makefile.am new file mode 100644 index 0000000..34f9e17 --- /dev/null +++ b/liblo/src/tools/Makefile.am @@ -0,0 +1,11 @@ +AUTOMAKE_OPTIONS = foreign + +SUBDIRS = . + +bin_PROGRAMS = oscsend oscdump +oscsend_SOURCES = oscsend.c +oscsend_CFLAGS = $(LIBLO_CFLAGS) +oscsend_LDADD = ../liblo.la +oscdump_SOURCES = oscdump.c +oscdump_CFLAGS = $(LIBLO_CFLAGS) +oscdump_LDADD = ../liblo.la diff --git a/liblo/src/tools/Makefile.in b/liblo/src/tools/Makefile.in new file mode 100644 index 0000000..5111066 --- /dev/null +++ b/liblo/src/tools/Makefile.in @@ -0,0 +1,708 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = oscsend$(EXEEXT) oscdump$(EXEEXT) +subdir = src/tools +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_oscdump_OBJECTS = oscdump-oscdump.$(OBJEXT) +oscdump_OBJECTS = $(am_oscdump_OBJECTS) +oscdump_DEPENDENCIES = ../liblo.la +oscdump_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(oscdump_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_oscsend_OBJECTS = oscsend-oscsend.$(OBJEXT) +oscsend_OBJECTS = $(am_oscsend_OBJECTS) +oscsend_DEPENDENCIES = ../liblo.la +oscsend_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(oscsend_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(oscdump_SOURCES) $(oscsend_SOURCES) +DIST_SOURCES = $(oscdump_SOURCES) $(oscsend_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LO_SO_VERSION = @LO_SO_VERSION@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +SUBDIRS = . +oscsend_SOURCES = oscsend.c +oscsend_CFLAGS = $(LIBLO_CFLAGS) +oscsend_LDADD = ../liblo.la +oscdump_SOURCES = oscdump.c +oscdump_CFLAGS = $(LIBLO_CFLAGS) +oscdump_LDADD = ../liblo.la +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/tools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/tools/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +oscdump$(EXEEXT): $(oscdump_OBJECTS) $(oscdump_DEPENDENCIES) + @rm -f oscdump$(EXEEXT) + $(oscdump_LINK) $(oscdump_OBJECTS) $(oscdump_LDADD) $(LIBS) +oscsend$(EXEEXT): $(oscsend_OBJECTS) $(oscsend_DEPENDENCIES) + @rm -f oscsend$(EXEEXT) + $(oscsend_LINK) $(oscsend_OBJECTS) $(oscsend_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oscdump-oscdump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oscsend-oscsend.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +oscdump-oscdump.o: oscdump.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscdump_CFLAGS) $(CFLAGS) -MT oscdump-oscdump.o -MD -MP -MF $(DEPDIR)/oscdump-oscdump.Tpo -c -o oscdump-oscdump.o `test -f 'oscdump.c' || echo '$(srcdir)/'`oscdump.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/oscdump-oscdump.Tpo $(DEPDIR)/oscdump-oscdump.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oscdump.c' object='oscdump-oscdump.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscdump_CFLAGS) $(CFLAGS) -c -o oscdump-oscdump.o `test -f 'oscdump.c' || echo '$(srcdir)/'`oscdump.c + +oscdump-oscdump.obj: oscdump.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscdump_CFLAGS) $(CFLAGS) -MT oscdump-oscdump.obj -MD -MP -MF $(DEPDIR)/oscdump-oscdump.Tpo -c -o oscdump-oscdump.obj `if test -f 'oscdump.c'; then $(CYGPATH_W) 'oscdump.c'; else $(CYGPATH_W) '$(srcdir)/oscdump.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/oscdump-oscdump.Tpo $(DEPDIR)/oscdump-oscdump.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oscdump.c' object='oscdump-oscdump.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscdump_CFLAGS) $(CFLAGS) -c -o oscdump-oscdump.obj `if test -f 'oscdump.c'; then $(CYGPATH_W) 'oscdump.c'; else $(CYGPATH_W) '$(srcdir)/oscdump.c'; fi` + +oscsend-oscsend.o: oscsend.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscsend_CFLAGS) $(CFLAGS) -MT oscsend-oscsend.o -MD -MP -MF $(DEPDIR)/oscsend-oscsend.Tpo -c -o oscsend-oscsend.o `test -f 'oscsend.c' || echo '$(srcdir)/'`oscsend.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/oscsend-oscsend.Tpo $(DEPDIR)/oscsend-oscsend.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oscsend.c' object='oscsend-oscsend.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscsend_CFLAGS) $(CFLAGS) -c -o oscsend-oscsend.o `test -f 'oscsend.c' || echo '$(srcdir)/'`oscsend.c + +oscsend-oscsend.obj: oscsend.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscsend_CFLAGS) $(CFLAGS) -MT oscsend-oscsend.obj -MD -MP -MF $(DEPDIR)/oscsend-oscsend.Tpo -c -o oscsend-oscsend.obj `if test -f 'oscsend.c'; then $(CYGPATH_W) 'oscsend.c'; else $(CYGPATH_W) '$(srcdir)/oscsend.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/oscsend-oscsend.Tpo $(DEPDIR)/oscsend-oscsend.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oscsend.c' object='oscsend-oscsend.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(oscsend_CFLAGS) $(CFLAGS) -c -o oscsend-oscsend.obj `if test -f 'oscsend.c'; then $(CYGPATH_W) 'oscsend.c'; else $(CYGPATH_W) '$(srcdir)/oscsend.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags ctags-recursive distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-binPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/liblo/src/tools/README b/liblo/src/tools/README new file mode 100644 index 0000000..2c4dfbc --- /dev/null +++ b/liblo/src/tools/README @@ -0,0 +1,71 @@ +oscsend and oscdump 1.0.0 - Send/receive OpenSound Control messages. + +GENERAL INFORMATION +=================== +oscsend and oscdump are OpenSound Control (OSC) tools using liblo. oscsend +sends an OSC message specified by command line arguments, while oscdump +receives OSC messages and prints to standard output. Both tools uses UDP for +networking. + + +INSTALL +======= + +Requirements +------------ +Liblo is required to compile oscsend and oscdump. See + +http://liblo.sourceforge.net/ + + +Compile & install +----------------- +Just try + +./configure +make +make install + +This compiles and installs oscsend and oscdump to the appropriate directories. +By default, /usr/local/bin. You can change the destination directory by passing +some options to the configure script. Run "./configure --help" to see the list +of options. + + +USAGE +===== +Please invoke the command without any arguments to show usage. + +Oscsend and oscdump are incompatible with Matt Wright's well known tools, +sendOSC and dumpOSC. + + +LICENSING INFORMATION +===================== +Copyright (C) 2008 Kentaro Fukuchi + +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 2.1 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 Lesser General Public +Licensealong with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + + +CONTACTS +======== +Visit the homepage at: + +http://megaui.net/fukuchi/works/oscsend/index.en.html + +Please mail any bug reports, suggestions, comments and questions to +Kentaro Fukuchi . Questions of license compliance +are also welcome. diff --git a/liblo/src/tools/oscdump.c b/liblo/src/tools/oscdump.c new file mode 100644 index 0000000..d52189e --- /dev/null +++ b/liblo/src/tools/oscdump.c @@ -0,0 +1,85 @@ +/* + * oscdump - Receive and dump OpenSound Control messages. + * + * Copyright (C) 2008 Kentaro Fukuchi + * + * 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 2.1 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 Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +void usage(void) +{ + printf("oscdump version %s\n" + "Copyright (C) 2008 Kentaro Fukuchi\n\n" + "Usage: oscdump port\n" + "Receive OpenSound Control messages via UDP and dump to standard output.\n\n" + "Description\n" + "port : specifies the listening port number.\n\n", + VERSION); +} + +void errorHandler(int num, const char *msg, const char *where) +{ + printf("liblo server error %d in path %s: %s\n", num, where, msg); +} + +int messageHandler(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data) +{ + int i; + + printf("%s %s", path, types); + + for(i=0; i + * + * 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 2.1 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 Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * TODO: + * - support binary blob. + * - support TimeTag. + * - receive replies. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) +{ + printf("oscsend version %s\n" + "Copyright (C) 2008 Kentaro Fukuchi\n\n" + "Usage: oscsend hostname port address types values...\n" + "Send OpenSound Control message via UDP.\n\n" + "Description\n" + "hostname: specifies the remote host's name.\n" + "port : specifies the port number to connect to the remote host.\n" + "address : the OSC address where the message to be sent.\n" + "types : specifies the types of the following values.\n", + VERSION); + printf(" %c - 32bit integer\n", LO_INT32); + printf(" %c - 64bit integer\n", LO_INT64); + printf(" %c - 32bit floating point number\n", LO_FLOAT); + printf(" %c - 64bit (double) floating point number\n", LO_DOUBLE); + printf(" %c - string\n", LO_STRING); + printf(" %c - symbol\n", LO_SYMBOL); + printf(" %c - char\n", LO_CHAR); + printf(" %c - 4 byte midi packet (8 digits hexadecimal)\n", LO_MIDI); + printf(" %c - TRUE (no value required)\n", LO_TRUE); + printf(" %c - FALSE (no value required)\n", LO_FALSE); + printf(" %c - NIL (no value required)\n", LO_NIL); + printf(" %c - INFINITUM (no value required)\n", LO_INFINITUM); + printf("values : space separated values.\n\n" + "Example\n" + "$ oscsend localhost 7777 /sample/address %c%c%c%c 1 3.14 hello\n", + LO_INT32, LO_TRUE, LO_FLOAT, LO_STRING); +} + +lo_message create_message(char **argv) +{ + /* Note: + * argv[1] <- hostname + * argv[2] <- port + * argv[3] <- OSC address + * argv[4] <- types + * argv[5..] <- values + */ + int i, argi; + lo_message message; + const char *types, *arg; + int values; + + message = lo_message_new(); + if(argv[4] == NULL) { + /* empty message is allowed. */ + values = 0; + } else { + types = argv[4]; + values = strlen(types); + } + + argi = 5; + for(i=0; i INT_MAX || v < INT_MIN) { + fprintf(stderr, "Value out of range: '%s'\n", arg); + goto EXIT; + } + lo_message_add_int32(message, (int32_t)v); + argi++; + break; + } + case LO_INT64: + { + char *endp; + int64_t v; + + v = strtoll(arg, &endp, 10); + if(*endp != '\0') { + fprintf(stderr, "An invalid value was given: '%s'\n", arg); + goto EXIT; + } + if((v == LONG_MAX || v == LONG_MIN) && errno == ERANGE) { + fprintf(stderr, "Value out of range: '%s'\n", arg); + goto EXIT; + } + lo_message_add_int64(message, v); + argi++; + break; + } + case LO_FLOAT: + { + char *endp; + float v; + +#ifdef __USE_ISOC99 + v = strtof(arg, &endp); +#else + v = (float)strtod(arg, &endp); +#endif /* __USE_ISOC99 */ + if(*endp != '\0') { + fprintf(stderr, "An invalid value was given: '%s'\n", arg); + goto EXIT; + } + lo_message_add_float(message, v); + argi++; + break; + } + case LO_DOUBLE: + { + char *endp; + double v; + + v = strtod(arg, &endp); + if(*endp != '\0') { + perror(NULL); + fprintf(stderr, "An invalid value was given: '%s'\n", arg); + goto EXIT; + } + lo_message_add_double(message, v); + argi++; + break; + } + case LO_STRING: + lo_message_add_string(message, arg); + argi++; + break; + case LO_SYMBOL: + lo_message_add_symbol(message, arg); + argi++; + break; + case LO_CHAR: + lo_message_add_char(message, arg[0]); + argi++; + break; + case LO_MIDI: + { + unsigned int midi; + uint8_t packet[4]; + int ret; + + ret = sscanf(arg, "%08x", &midi); + if(ret != 1) { + fprintf(stderr, "An invalid hexadecimal value was given: '%s'\n", arg); + goto EXIT; + } + packet[0] = (midi>>24) & 0xff; + packet[1] = (midi>>16) & 0xff; + packet[2] = (midi>> 8) & 0xff; + packet[3] = midi & 0xff; + lo_message_add_midi(message, packet); + argi++; + break; + } + case LO_TRUE: + lo_message_add_true(message); + break; + case LO_FALSE: + lo_message_add_false(message); + break; + case LO_NIL: + lo_message_add_nil(message); + break; + case LO_INFINITUM: + lo_message_add_infinitum(message); + break; + default: + fprintf(stderr, "Type '%c' is not supported or invalid.\n", types[i]); + goto EXIT; + break; + } + } + + return message; +EXIT: + lo_message_free(message); + return NULL; +} + +int main(int argc, char **argv) +{ + lo_address target; + lo_message message; + int ret; + + if(argc < 4) { + usage(); + exit(1); + } + + if(argv[1] == NULL) { + fprintf(stderr, "No hostname is given.\n"); + exit(1); + } + if(argv[2] == NULL) { + fprintf(stderr, "No port number is given.\n"); + exit(1); + } + + target = lo_address_new(argv[1], argv[2]); + if(target == NULL) { + fprintf(stderr, "Failed to open %s:%s\n", argv[1], argv[2]); + exit(1); + } + + if(argv[3] == NULL) { + fprintf(stderr, "No path is given.\n"); + exit(1); + } + + message = create_message(argv); + if(message == NULL) { + fprintf(stderr, "Failed to create OSC message.\n"); + exit(1); + } + + ret = lo_send_message(target, argv[3], message); + if(ret == -1) { + fprintf(stderr, "An error occured: %s\n", lo_address_errstr(target)); + exit(1); + } + + return 0; +} diff --git a/liblo/test-client/README.txt b/liblo/test-client/README.txt new file mode 100644 index 0000000..071d90a --- /dev/null +++ b/liblo/test-client/README.txt @@ -0,0 +1,10 @@ +test-client sends OSC messages to Nyquist. + +The default behavior is to generate a low frequency triangle that +simulates ramping slider 0 up and down. + +On the Mac, you build this with the osc-test-client target in Xcode. +You can find the executable in: + nyquist/macosxproject/build/Development/osc-test-client +and you can run this from a terminal window (or with Xcode) + diff --git a/liblo/test-client/osc-test-client.vcproj b/liblo/test-client/osc-test-client.vcproj new file mode 100644 index 0000000..67e49ad --- /dev/null +++ b/liblo/test-client/osc-test-client.vcproj @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/liblo/test-client/test-client.c b/liblo/test-client/test-client.c new file mode 100644 index 0000000..52a1a20 --- /dev/null +++ b/liblo/test-client/test-client.c @@ -0,0 +1,73 @@ +/* + * test-client.c -- Roger Dannenberg, 2006 + * + * based on example_client.c by Steve Harris, Uwe Koloska + * + * Usage: test-client [mode], where mode is: + * h -- help + * ? -- help + * t -- triangle (up/down ramp), default behavior + * i -- interactive, type returns to advance + */ + +#include +#include +#ifdef WIN32 +#define usleep(x) Sleep((x)/1000) +#else +#include +#endif + +#include "lo/lo.h" + +int main(int argc, char *argv[]) +{ + /* an address to send messages to. sometimes it is better to let the server + * pick a port number for you by passing NULL as the last argument */ + lo_address t = lo_address_new(NULL, "7770"); + char mode = 't'; + float x = 0.0; + float delta = 0.1; + int n = 0; /* slider number */ + + if (argc == 2) { + mode = argv[1][0]; + if (mode == '?' || mode == 'h' || + (mode != 'i' && mode != 't')) { + printf("usage: test-client [?hti]\n"); + printf(" default (t) is triangle, (i)nteractive sends msg after each return\n"); + exit(1); + } + } + + printf("lo_address_new done\n"); + + /* send messages to /slider with two arguments, report any + * errors */ + while (1) { + if (lo_send(t, "/slider", "if", n, x) == -1) { + printf("OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t)); + break; + } else { + printf("/slider %d %g\n", n, x); + } + x = x + delta; + if (x > 1.0 - delta * 0.5) { + x = 1.0; + delta = -delta; + } else if (x < -delta * 0.5) { + x = 0.0; + delta = -delta; + } + if (mode == 'i') { + while (getchar() != '\n') ; + } else { + usleep(100000); + } + } + + printf("done calling lo_send\n"); + + return 0; +} + diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..3b320cc --- /dev/null +++ b/license.txt @@ -0,0 +1,116 @@ +LICENSE INFORMATION + +Nyquist is built upon and derived from XLISP. Both are copyrighted software. +Two copyright notices and licenses appear below. + +In addition, Nyquist uses two LGPL libraries: libsndfile and liblo. +These libraries are NOT covered by the Nyquist license, and Nyquist +is NOT licensed under or restricted by GPL or LGPL licenses. The +license agreements for libsndfile and liblo can be found in the +Nyquist source libraries nyquist/nylsf and nyquist/liblo, respectively. + +-------------------------------------------------------------------------------- +COPYRIGHT AND LICENSE INFORMATION FOR NYQUIST + +Copyright (c) 2000-2002, by Roger B. Dannenberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. + +Redistributions of source code must retain the copyright notice, the +list of conditions, and the disclaimer, all three of which appear below under +"COPYRIGHT AND LICENSE INFORMATION FOR XLISP." + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +Redistributions in binary form must reproduce the copyright notice, the +list of conditions, and the disclaimer, all three of which appear below under +"COPYRIGHT AND LICENSE INFORMATION FOR XLISP," in the documentation and/or +other materials provided with the distribution. + +Neither the name of Roger B. Dannenberg, Carnegie Mellon University, nor the +names of any contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +What follows is not a part of the license: + +Please send bug fixes and improvements to me at the address below. + +Please do not distribute modified versions of Nyquist without permission. + +Any redistribution of Nyquist should include a notice that Nyquist can be +obtained free from http://www.cs.cmu.edu/~music. + +In addition, as a courtesy, I ask that you send me a copy of any product that +makes substantial use of Nyquist. Please contact me at the address below for my +current mailing address. I am asking this because I enjoy learning about +applications of my software. + +When Nyquist is used to generate music and conduct research, please mention +and acknowledge the use of Nyquist in program notes, acknowledgement sections +of papers, and whereever thanks or credits would normally be given. + +Roger B. Dannenberg + +roger.dannenberg@cs.cmu.edu + +-------------------------------------------------------------------------------- +COPYRIGHT AND LICENSE INFORMATION FOR XLISP + +Copyright (c) 1984-2002, by David Michael Betz +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +Neither the name of David Michael Betz nor the names of any contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +What follows is not a part of the license: + +Please send bug fixes and improvements to me at the address below. + +In addition, as a courtesy, I ask that you send me a copy of any product that +makes substantial use of XLISP. Please contact me at the address below for my +current mailing address. I am asking this because I enjoy learning about +applications of my software. + +David Betz + +dbetz@xlisper.mv.com diff --git a/lpc/compile.txt b/lpc/compile.txt new file mode 100644 index 0000000..bbfab59 --- /dev/null +++ b/lpc/compile.txt @@ -0,0 +1,101 @@ +How to compile Nyquist with LPC functions + +Note: this is compiled with MSVC 6 in Windows + +1. Translate lpreson.alg : Result lpreson.h, lpreson.c +2. Translate allpoles.alg: Result allpoles.h, allpoles.c +3. lpanal.h and lpanal.c are coded in C (no alg file) +4. Modify the files + sndfint.c + sndfnintptrs.h + sndfintdefs.h + as it is show below + (I modify this "by hand" although it may be automatized) +5. Add all these files to Nyquist project +6. Compile + +---------------------------------------------------------------------------------- + +To add these functions to Nyquist "by hand" edit the files and add this C code + + + + + + + +SOURCE CODE FOR sndfint.c + + + +#include "lpanal.h" + +/* xlc_snd_lpanal -- interface to C routine snd_lpanal */ +/**/ +LVAL xlc_snd_lpanal(void) +{ + LVAL arg1 = xlgetarg(); + long arg2 = getfixnum(xlgafixnum()); + LVAL result; + + xllastarg(); + result = snd_lpanal(arg1,arg2); + return (result); +} + +#include "allpoles.h" + +/* xlc_snd_allpoles -- interface to C routine snd_allpoles */ +/**/ +LVAL xlc_snd_allpoles(void) +{ + sound_type arg1 = getsound(xlgasound()); + LVAL arg2 = xlgetarg(); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_allpoles(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "lpreson.h" + +/* xlc_snd_lpreson -- interface to C routine snd_lpreson */ +/**/ +LVAL xlc_snd_lpreson(void) +{ + sound_type arg1 = getsound(xlgasound()); + LVAL arg2 = xlgetarg(); + double arg3 = testarg2(xlgaanynum()); + LVAL result; + + xllastarg(); + result = snd_lpreson(arg1, arg2, arg3); + return cvsound(result); +} + + +========================================================================= + + +SOURCE CODE FOR sndfintptrs.h + + { "SND-LPANAL", S, xlc_snd_lpanal}, + { "SND-ALLPOLES", S, xlc_snd_allpoles}, + { "SND-LPRESON", S, xlc_snd_lpreson}, + + +========================================================================= + +SOURCE CODE FOR sndfintdefs.h + +extern LVAL xlc_snd_lpanal(void); +extern LVAL xlc_snd_allpoles(void); +extern LVAL xlc_snd_lpreson(void); + + + + + diff --git a/lpc/lpc-example.dat b/lpc/lpc-example.dat new file mode 100644 index 0000000..525a93d --- /dev/null +++ b/lpc/lpc-example.dat @@ -0,0 +1 @@ +#((0.0205328 0.000539653 0.162119 #(0.0172437 -0.00206371 0.0199834 0.0140023 -0.107106 0.105376 -0.014147 -0.0456254 -0.035733 0.000526876 0.024559 -0.077979 0.0379572 0.0550832 0.0251978 -0.0158793 0.000201547 0.0183836 0.0120267 -0.0145289 0.0270053 0.0215023 -0.0674045 0.0868633 -0.0759818 0.0123872 -0.100426 0.0670379 0.153223 -0.160887 0.0200027 0.00857184 -0.0319345 0.0372642 -0.039906 0.0370124 -0.0406953 0.0916241 -0.0794324 0.0994091 -0.152256 0.122422 -0.131096 0.143904 -0.182573 0.107067 -0.216319 0.338997 -0.171402 1.04299)) (0.0746031 0.000883533 0.108826 #(0.043002 -0.0168565 0.0116234 -0.031321 -0.0728684 0.134856 0.0052372 -0.0477521 -0.0767405 0.0307031 0.00286882 -0.0188694 -0.0103552 0.0410824 -0.00991496 0.0129631 -0.0070764 0.0446677 -0.0316206 0.0103328 -0.00314631 0.0721652 -0.028264 0.0429488 -0.0757499 0.0355948 -0.124679 0.0341884 0.147169 -0.115948 0.0350534 -0.022784 0.00255128 0.000132609 0.00266292 0.0235752 -0.0270638 0.00319338 -0.0405898 0.0510949 -0.0525406 0.112875 -0.120262 0.103579 -0.140658 0.030511 -0.195171 0.226418 -0.194436 1.19625)) (7.90651 0.00254103 0.0179272 #(0.0298438 -0.0150177 0.00856811 0.00178307 -0.156251 0.141521 0.0377321 -0.00862076 0.0358013 -0.0526648 -0.0746482 0.0176761 0.0180553 0.0110547 -0.0149859 -0.00274912 0.00753696 0.0570906 -0.00985159 -0.0460384 -0.0312089 0.0275762 -0.00179828 0.0498972 -0.0462076 0.111785 -0.101277 -0.0429219 0.135046 -0.118618 0.0320909 0.0152628 0.00229011 0.000619642 -0.00148223 0.0698463 -0.0192731 -0.061608 -0.105966 0.00760205 -0.0556964 0.172818 -0.0018539 0.14807 -0.115714 0.0485711 -0.341883 0.118442 -0.644804 1.76356)) (16.8204 0.00353871 0.0145046 #(0.0242379 0.0163801 -0.0441124 0.0515951 -0.165318 0.0553254 0.118888 -0.00888211 0.0686623 -0.103195 -0.109872 0.0873954 -0.00312068 -0.0157818 0.00793753 -0.0102677 0.0385871 0.0402539 0.0275778 -0.124176 -0.0224998 -0.0083091 0.139262 -0.0326057 -0.0686154 0.152026 -0.0710961 -0.100093 0.0921394 -0.0886168 0.0962788 0.0235546 -0.0835561 0.0289921 -0.0519826 0.0819953 0.0677047 -0.04636 -0.154177 0.0188317 -0.0733893 0.18706 -0.117089 0.276443 -0.188078 0.136406 -0.348012 0.354862 -1.21044 2.05642)) (15.7527 0.00488585 0.0176113 #(0.0410332 -0.0212341 -0.0186016 0.0139835 -0.10253 0.0317464 0.098534 0.0577219 -0.00603218 -0.119189 -0.0560336 0.0600247 0.00563636 -0.00741701 -0.022568 0.0551003 0.0172174 -0.0145449 0.0377798 -0.0774387 -0.0623132 0.0156745 0.116856 0.0167625 -0.0740776 0.0976961 -0.0589157 -0.0592283 0.0621122 -0.0668073 0.0672344 0.0433492 -0.0724394 -0.0149194 -0.0174723 0.0940844 0.0192709 -0.037947 -0.145742 0.0166333 -0.0382952 0.137928 -0.0235971 0.142885 -0.0641163 -0.0401743 -0.14418 0.182686 -1.00692 1.93978)) (16.3531 0.0136897 0.0289333 #(-0.024896 0.016421 0.00786502 -0.0118406 0.00603457 0.0343453 0.0250988 -0.00670104 -0.0483285 -0.0402459 0.00284676 0.0223309 0.00649693 -0.0116516 0.00923614 0.0111503 -0.000440774 -0.0275555 0.00682401 -0.0125723 0.00263826 0.0153074 0.0242379 0.0142031 0.0060273 0.0192062 -0.0368178 0.00965019 0.0058204 -0.00736851 0.0414994 0.00440613 -0.0394615 -0.0217087 0.0132956 0.0116567 -0.024931 -0.0592983 -0.0327111 0.00831445 0.0282831 0.0678891 0.00450369 0.00915988 -0.0181229 -0.0469828 -0.0555707 -0.0913728 -0.228273 1.41019)) (22.7776 0.0128829 0.0237823 #(-0.0244512 0.00852192 0.00355279 0.0100932 -0.00419528 0.0237172 0.0103759 -0.0137028 -0.0251104 -0.0134613 -0.000615256 0.00165147 -0.00407305 -0.00344569 -0.00120993 0.0089017 0.000495352 -0.000238208 0.00294549 0.00112805 0.00425276 0.0266437 0.0165051 -0.0296654 -0.00157895 0.0406957 -0.0203225 0.000875471 0.0187371 -0.00604564 0.0124178 0.00848914 -0.00870932 -0.0345038 -0.0166086 -0.00777551 -0.0127552 -0.0198208 -0.018883 0.00170381 0.0281818 0.0335668 0.00621638 0.000123257 -0.0400046 -0.0251494 -0.0599436 -0.0484318 -0.0953316 1.26394)) (25.9418 0.014063 0.023283 #(-0.0146976 0.0123669 -0.00238331 -0.00566441 0.000213927 0.0251708 0.0058586 -0.0152624 -0.0096643 0.000380473 -0.00692432 -0.0103325 -0.00570062 -0.00779317 -0.00373097 -0.00244446 0.0232326 0.00687431 -0.0123666 0.0136142 0.000873428 0.01297 0.00157535 -0.0189359 0.0103542 0.0149338 -0.00232667 0.018195 0.0122806 0.000705099 0.0180465 -0.00723085 -0.0333543 -0.0209618 -0.00258482 -0.00346647 -0.0161793 -0.00443528 -0.0107334 -0.00729346 0.0212632 0.017004 -0.0134609 -0.0122188 -0.0266593 -0.0240987 -0.0584669 -0.0204726 -0.0728998 1.23429)) (26.411 0.0454326 0.0414755 #(-0.0109339 -0.0010968 -0.0010053 0.00617609 0.00306015 0.000136934 0.00372594 -0.00564924 -0.00591968 -0.00522412 -0.00509402 -3.17432e-006 -0.00446083 0.00456961 0.00243643 0.00451923 0.00334826 0.00559344 0.00805774 0.000849614 0.00365901 -0.000214671 -0.00258062 0.00132718 0.00916179 0.00321858 -0.00441098 0.00674969 0.00362521 0.00233835 0.00103611 -0.00365412 -0.0110665 -0.0113001 -0.00483079 -0.00471838 -0.0072024 -0.0112189 -0.00842469 -0.00122134 0.00258161 -0.00404681 -0.0108012 -0.0163903 -0.0156165 -0.0101237 -0.0119205 -0.0127908 -0.0241693 1.1353)) (26.023 0.0171174 0.0256472 #(-0.00659148 -0.0022813 0.00245043 0.0119932 0.00673879 0.0106215 0.000193227 -0.0118672 -0.00229731 -8.44562e-005 -0.010244 -0.0224172 -0.0074773 0.00139424 0.00442344 -0.00372009 0.00631038 0.00399001 0.00074413 0.00143648 0.0117816 0.0167116 -0.011429 0.00660101 -0.0154429 0.0245051 0.00954568 0.00221017 0.00972422 0.00691179 0.00198784 0.00641321 -0.0164092 -0.0286664 -0.00348171 -0.00646432 -0.0149224 -0.00929398 0.000946284 -0.00786511 0.0105857 0.0116371 -0.0208869 -0.0167969 -0.039235 -0.0416232 -0.0188724 -0.0395318 -0.0672928 1.2529)) (20.1471 0.0413173 0.0452855 #(0.0028042 0.00238915 0.00320531 0.00204744 -0.00128491 -0.000625469 0.00121502 -0.00053792 -0.00926453 -0.00168529 -0.0176347 -0.00451895 0.000996928 0.00430582 0.00194222 -0.00398466 0.00259957 0.00390882 0.0116503 0.00167209 -0.001884 0.00309071 0.00380416 0.00551039 0.0052082 0.00707811 -0.00293764 0.0110331 0.0118179 0.000155053 0.0029885 -0.0120471 -0.00528422 -0.0186305 -0.00389795 -0.01138 -0.0130287 -0.0114016 -0.00348096 0.00720399 -0.00393767 -0.00782219 -0.00889679 -0.0106665 -0.0241594 -0.0212916 -0.0261109 -0.0222356 -0.042137 1.1898)) (15.5487 0.0153078 0.0313768 #(0.0038797 -0.00898583 -0.00129375 0.0135476 0.00658722 0.0365788 0.00343157 -0.0308747 -0.0106992 -0.00551437 0.00041832 -0.0139702 -0.0154675 -0.0119801 -0.00961124 0.0151818 0.00235315 -0.00360607 -0.00300882 0.0133151 0.00953059 0.00235415 -1.91313e-005 0.00280704 0.0099642 0.0205634 0.00397632 0.00529698 0.023866 -0.00799138 0.0100504 0.0079582 -0.0250386 -0.029848 -0.0097943 -0.00418491 -0.0133331 -0.0233978 -0.00335522 0.0048438 0.0168547 0.0205229 -0.0161785 -0.0256227 -0.0427417 -0.0322054 -0.0493791 -0.0330071 -0.0981295 1.29245)) (19.0253 0.00596731 0.0177102 #(-0.0146168 -0.0100904 0.00214927 0.0184939 0.01049 0.0612408 -0.00438104 -0.0265871 -0.026429 0.00668405 0.0269023 -0.0263329 -0.0230587 -0.0429497 0.00384385 0.0294333 -0.00318107 -0.0136982 -0.00792112 0.0090845 0.0366004 -0.0174499 -0.00897093 -0.00784815 -0.00441435 0.0551205 -0.0163865 0.00471411 0.0446577 -0.0132054 0.0401863 0.0217569 -0.0372981 -0.0637524 -0.0140608 0.0379691 -0.012396 -0.0571539 -0.0387487 0.0285809 0.0555209 0.0533837 -0.020053 -0.00430533 -0.102708 -0.0554588 -0.0775484 0.00345876 -0.257812 1.45669)) (24.3361 0.00252815 0.0101924 #(-0.0257512 -0.0008726 0.0176086 0.0124685 -0.0534896 0.100064 0.0398205 -0.0701561 -0.0307596 0.00460567 0.0732452 -0.00591591 -0.0655563 -0.0244842 0.0128442 0.0333025 -0.0171489 -0.0529101 -0.0145168 -0.00558627 0.0716373 0.0169233 -0.00522713 0.00671804 -0.0615778 0.0634442 -0.0921752 0.00951979 0.120483 -0.077487 0.0914363 0.104565 -0.0653618 -0.089458 -0.0420491 0.0741933 -0.0368942 -0.0224205 -0.159684 0.0706304 0.0604807 0.156387 -0.0368354 0.00141878 -0.11703 -0.0250188 -0.215087 0.140998 -0.528956 1.65826)) (25.4722 0.00168582 0.00813527 #(-0.0361914 0.0503908 -0.052739 0.0874611 -0.161167 0.205034 -0.030822 -0.0297436 -0.0881124 0.0515133 0.029009 0.0911085 -0.133234 0.00447612 -0.0102752 0.0672411 -0.0743354 0.0278325 -0.088049 0.0254583 0.00378763 0.110739 -0.0335123 0.0437825 -0.111471 0.143021 -0.205556 0.0105061 0.178276 -0.139079 0.108138 0.100769 -0.0514441 -0.061891 -0.0335699 0.078663 -0.0342434 -0.0322647 -0.218112 0.133516 -0.053587 0.327015 -0.200594 0.23237 -0.331232 0.175309 -0.44634 0.403636 -0.874447 1.84189)) (24.4789 0.00660193 0.0164225 #(-0.0129511 0.000294328 -0.0197443 0.0228973 0.0144379 0.0576108 -0.00978518 -0.00793303 -0.0138883 -0.0222251 0.0319748 -0.0148723 -0.0204648 -0.0414119 -0.0116904 0.010987 -0.0113676 0.0117234 -0.00638076 0.0237907 0.020048 0.00399678 -0.00498899 -0.00973827 -0.00584135 0.0192609 -0.0220209 0.0192987 0.0427776 -0.0141488 0.0260689 0.053246 -0.0359298 -0.0407085 -0.0153808 0.000894089 -0.0255827 -0.0505249 -0.0252819 0.0272812 0.0597201 0.0367404 0.00457889 -0.0014007 -0.0717525 -0.0699291 -0.107446 -0.0187547 -0.27242 1.49509)) (26.2758 0.0176864 0.0259442 #(0.0033549 -0.00945348 0.0065972 0.011377 0.00754275 0.0138938 0.00853247 0.000314037 -0.00732074 -0.0137922 -0.008441 -0.0188535 -0.0266481 -0.0205979 0.00421144 0.0117094 0.0169971 -0.0179554 -0.00098244 0.035148 0.00857569 -0.0052743 -0.000887931 0.00311146 -0.00552477 0.00948484 -0.000848823 0.0254957 0.0295882 -0.0096005 0.019213 0.00984905 -0.0239854 -0.0251062 -0.0378088 -0.00656597 -0.0252241 -0.0322219 0.024789 0.0259035 0.0228412 0.0272441 -0.00713364 -0.0104557 -0.0465321 -0.0714479 -0.0841954 -0.0538046 -0.134946 1.37684)) (33.8769 0.00801222 0.0153789 #(-0.00258214 -0.00821759 0.0196898 -0.000392261 0.0140521 0.00440578 -0.0286329 0.000567736 0.0125327 0.00426797 -0.0066993 0.0334311 -0.0281124 -0.0422645 -0.0221943 0.0377913 -0.00618192 -0.0265775 -0.00448782 0.027992 0.0456436 0.00158737 -0.0145791 -0.00474223 -0.0115839 0.0136965 -0.0283794 0.032301 0.000935378 -0.0386639 0.0497046 0.0790239 -0.0338661 -0.0499984 -0.00571791 0.0381896 -0.0512542 -0.0879677 -0.0317509 0.0295627 0.0690141 0.0544617 0.0545729 0.0472211 -0.0781932 -0.090823 -0.112884 -0.113677 -0.42381 1.68183)) (47.5854 0.03461 0.0269689 #(0.00703504 0.0042176 -0.007448 0.00601103 0.00320568 0.00838487 0.0062723 -0.0120179 0.000336154 0.000458805 -0.00549983 -0.000896449 -0.0239517 -0.0277963 -0.00199031 0.00441657 0.0118858 -0.00555538 0.0186382 0.000599233 0.0253149 0.00947596 -0.0151058 -0.0109278 -0.00257833 0.0161187 -0.000843106 0.0151509 0.00682266 0.00837561 0.0212141 0.019091 -0.0166389 -0.0383569 -0.0276626 -0.0067535 -0.0278646 -0.0358582 -0.00485826 0.02398 0.0407189 0.0544763 0.0300379 -0.00650959 -0.0404744 -0.0715788 -0.100036 -0.13855 -0.218292 1.50233)) (67.1502 0.0503262 0.0273762 #(0.00163764 0.00156368 0.000896518 -0.00356924 0.0146311 0.0115155 0.000718131 -0.010003 -0.00103783 0.00202199 -0.00199034 -0.0161105 -0.0194743 -0.0104963 -0.00591896 0.0121449 0.00486055 -0.00401805 0.00316407 0.00376875 0.0156482 0.00483055 -0.00410957 -0.00432992 -0.00485066 0.0143753 0.00558336 0.0130507 0.00596937 0.00550279 0.0213288 0.00884339 -0.00423094 -0.0320471 -0.0225288 -0.0132194 -0.0288979 -0.0323811 -0.0196434 0.0287962 0.0448142 0.0421381 0.0389864 -0.00463365 -0.0331114 -0.0584344 -0.112601 -0.149007 -0.247096 1.5331)) (87.0259 0.146162 0.040982 #(0.0066813 0.0031666 0.00524609 -0.0082533 -0.00391559 0.0131647 0.0226346 0.00201689 -0.0300066 -0.0164448 0.00249676 0.012122 -0.0120514 -0.0290936 -0.00477291 0.0062677 0.00679358 0.00355967 0.0074764 0.00641204 0.00203213 -0.000103927 0.00208319 0.00592471 -0.00531212 -0.00286345 0.0194362 0.0235452 0.0145299 0.000873052 0.0170015 0.00926635 -0.0249864 -0.0345525 -0.026674 -0.0209155 -0.0204941 -0.0180144 -0.000742368 0.0206704 0.0347392 0.0281013 0.0231078 0.00568184 -0.0455544 -0.0687793 -0.0774324 -0.112311 -0.16092 1.413)) (103.805 0.0839127 0.0284317 #(0.0305305 -0.0232935 -0.0123279 -0.00539001 0.00241112 0.0181144 0.0198195 -0.0119952 -0.00946969 -0.00768942 0.0176179 0.0159392 -0.0270933 -0.0533804 -0.0238979 0.042285 0.0419821 -0.0130642 -0.02037 0.00470052 0.0265474 0.00800111 -0.0193407 -0.00539329 -0.00768145 -0.00352887 0.00818424 0.0306883 0.00191179 -0.011258 0.0201576 0.0424102 0.000582659 -0.0480861 -0.0335357 0.00238416 -0.000149278 -0.0762318 -0.0235003 0.0537691 0.0525345 0.0284459 0.0125174 0.044311 -0.0359816 -0.0879433 -0.0942918 -0.141744 -0.328099 1.59425)) (124.841 0.162496 0.036078 #(0.0154669 -9.72884e-006 -0.0101342 -0.00793859 0.0059567 0.0228617 0.00768918 -0.0107367 -0.0153092 -0.00690622 0.00137529 0.00756771 -0.0173113 -0.0348903 -0.015329 0.0277865 0.0313134 0.00105124 -0.0143057 -0.00667794 0.011448 0.00558312 -0.00253005 0.000195594 -0.00582771 0.00497205 0.0183721 0.0241788 0.0151434 -0.0120356 0.00834879 0.019273 -0.0189529 -0.0436641 -0.017064 0.0110478 -0.0142619 -0.0454921 -0.0275606 0.0195142 0.0430997 0.0479311 0.0369613 0.00241956 -0.049964 -0.0670036 -0.063226 -0.132439 -0.269048 1.51163)) (180.716 0.293325 0.040288 #(0.0258335 -0.0119538 -0.0193954 -0.00626257 0.0234294 0.0231874 0.0109882 -0.0140674 -0.0204807 -0.0175573 0.000633931 0.000397377 -0.011624 -0.022438 -0.0107618 0.0178291 0.0325036 0.0112156 -0.0171066 -0.00548084 0.00984786 -0.00170732 -0.00485124 -0.00691943 -0.00247698 0.0118085 0.0178137 0.0244233 0.0229053 0.003698 -0.0103266 -0.00441229 -0.00122563 -0.0243714 -0.0381239 -0.0309188 -0.0100181 -0.00337076 -0.00420997 0.0204227 0.0439681 0.0382338 0.00823855 -0.0138448 -0.0326542 -0.0661078 -0.097244 -0.115524 -0.154429 1.42031)) (234.118 0.205985 0.029662 #(0.0192157 -0.0031935 -0.00784433 -0.00677489 0.00286156 0.0114244 0.0199407 0.00873447 -0.0210833 -0.0382217 0.00335562 0.018978 -0.0148748 -0.0242473 -0.0051396 0.0205883 0.00181457 -0.0139292 0.0109887 0.0201683 0.00322887 -0.00941825 -0.00196576 0.0112985 -0.0102269 -0.0019795 0.0216591 0.0239712 0.00292886 -0.0126777 0.0229174 0.0228922 -0.0279371 -0.0544655 -0.0105665 0.0201515 -0.0232041 -0.0500812 -0.0122807 0.0286273 0.0377097 0.0333467 0.0362003 0.00682096 -0.0421918 -0.0623608 -0.0697533 -0.142768 -0.286476 1.53382)) (240.477 0.393671 0.0404604 #(0.0141351 -0.00376777 -0.0127499 0.00507208 0.0136482 0.0136646 0.00963351 -0.00969488 -0.0204225 -0.0195809 -0.00608936 0.0113476 -0.00348937 -0.0263493 -0.00860379 0.0196824 0.0270435 0.00279308 -0.0216122 -0.00311376 0.0167268 0.0026715 -0.00951989 -0.00655211 -0.000521916 0.00286717 0.0195184 0.0369098 0.0212964 -0.00938696 -0.00852238 0.0157752 -0.010538 -0.0511757 -0.0367333 -0.00701777 -0.00496757 -0.0218476 -0.00180121 0.0358277 0.0423497 0.0250602 0.0161893 -0.00886896 -0.0517459 -0.0757613 -0.0763744 -0.0986088 -0.163602 1.41088)) (208.983 0.298555 0.0377969 #(0.0164121 0.0048719 -0.0123277 -0.0082839 0.00553303 0.0215874 0.00343585 -0.0106931 -0.0143605 -0.0149133 -0.000867135 0.00882374 -0.00160873 -0.0229544 -0.0199348 0.0112933 0.0268215 0.00930974 -0.0129465 0.00684308 0.00823984 -0.00100629 -0.00874536 -0.0125536 0.0018266 0.00222032 0.0179517 0.0318532 0.0216125 -0.00395573 0.00757547 0.000995567 -0.0228842 -0.0368795 -0.018438 -0.00111154 -0.0249076 -0.0299492 0.000929623 0.034715 0.0335621 0.0270658 0.0181262 -0.000710647 -0.0431774 -0.0595626 -0.0734814 -0.128686 -0.215031 1.46608)) (169.872 0.295057 0.0416766 #(0.0319486 -0.0152698 -0.0178871 -0.00121978 0.0101795 0.0113419 0.00466058 -0.0163847 -0.00962441 -0.00255257 0.0034453 0.00333557 -0.00638092 -0.0185545 -0.0171695 0.00620859 0.027439 0.00889597 -0.00634335 0.00222882 0.00733991 0.00272018 -0.00324214 -0.00743471 -0.0202102 -0.0144455 0.0143375 0.0353734 0.03177 0.0180433 0.00470567 0.00350029 -0.0211588 -0.0400762 -0.0312031 -0.00502416 -0.0137467 -0.0287056 -0.00591527 0.0317417 0.0557392 0.030424 0.00295205 -0.00796262 -0.0331349 -0.0705161 -0.0935693 -0.117755 -0.17632 1.44112)) (198.736 0.583121 0.0541678 #(0.0239533 -0.0108176 -0.0102808 0.00564068 0.0150349 0.00994732 -0.00604523 -0.00984589 -0.0142772 -0.0121714 -0.00415331 -9.11199e-005 -0.00732939 -0.0188397 -0.00379378 0.0155464 0.0238681 0.0102193 -0.00649659 -0.0166725 -0.00159701 0.0168372 0.00555774 -0.0076568 -0.0152812 0.00621925 0.0304524 0.0302777 0.0179796 -7.1259e-005 -0.0110991 -0.0120554 -0.0207771 -0.0196221 -0.019649 -0.0276093 -0.0267218 -0.00462518 0.0217483 0.0300955 0.0254635 0.0179527 0.00908021 -0.0147737 -0.0434505 -0.0549393 -0.067622 -0.0980195 -0.11752 1.34832)) (235.893 0.196632 0.0288715 #(0.0304126 -0.0184424 -0.0165599 -0.000407823 0.00801631 0.0195737 0.0118165 -0.00905007 -0.0134561 -0.0135 -0.00394936 0.00567199 0.00352691 -0.0209869 -0.0335421 0.00501761 0.033716 0.0178405 0.00147093 -0.011718 -0.00133608 -0.00135017 0.00902945 0.00737444 -0.0033788 -0.00925621 -0.0209713 0.0180258 0.0548861 0.0175237 -0.0085279 -0.00515863 -0.0139746 -0.031351 -0.0115241 0.00705294 -0.0364894 -0.0527857 -0.0113735 0.0463322 0.0573369 0.0344311 0.019218 0.00187843 -0.0302693 -0.0656353 -0.0907326 -0.155003 -0.284321 1.55441)) (250.351 0.920652 0.0606419 #(0.0221283 -0.00175026 -0.00689412 0.000872708 0.00825388 0.00110956 -0.00632789 -0.0125022 -0.0104057 -0.00936074 -0.00616766 0.00522704 0.000860839 -0.00548061 -0.0014818 0.00943791 0.00798624 0.000154997 -0.00816161 -0.00716682 0.000403966 0.00149304 0.00596023 0.00691071 0.00706264 0.0106029 0.0144444 0.01869 0.0103569 -0.00377258 -0.00598677 -0.011182 -0.0229358 -0.0277385 -0.0171593 -0.00963866 -0.0130767 -0.00448601 0.01284 0.0232398 0.0183027 0.00684207 0.000345183 -0.017907 -0.0388241 -0.0491714 -0.0555385 -0.0671155 -0.080383 1.27961)) (265.144 0.37479 0.037597 #(0.0178487 0.0013791 -0.0116388 -0.00507206 0.0138357 0.0176418 0.0040927 -0.0179262 -0.017936 -0.00558455 0.00209339 -0.00600955 -0.011245 -0.00868085 -0.00205561 0.000295947 0.0125599 0.0156985 -0.00318278 -0.0132323 -0.000274777 0.00777626 -0.00183865 0.00266585 0.0125194 0.00603461 -0.00305746 0.0220627 0.0328774 0.00937883 -0.00296813 -0.0139498 -0.023661 -0.0265224 -0.0152562 -0.00981502 -0.0187505 -0.0249964 -0.00613381 0.0245956 0.0383716 0.0292479 -0.00259061 -0.00982094 -0.0297847 -0.0422148 -0.0701577 -0.115859 -0.177598 1.41175)) (250.53 0.735674 0.0541892 #(0.0238545 -0.00486949 -0.00173591 0.00252099 0.00404998 0.00118642 -0.00418862 -0.0123793 -0.0138166 -0.00838696 -0.00266911 -0.000717441 -0.00433613 -0.00087901 3.08753e-005 0.00695944 0.00812309 0.00161619 -0.00106495 -0.00230766 -0.00318343 -0.00717512 0.00130251 0.0107457 0.00679086 0.00860716 0.0173261 0.0173051 0.0100283 0.00988019 0.00145606 -0.0181773 -0.0255863 -0.0227028 -0.0191551 -0.0156616 -0.0149123 -0.00943028 0.00703709 0.0185155 0.0208948 0.0180594 0.00541843 -0.016114 -0.0379061 -0.0507604 -0.0578965 -0.0768728 -0.0909356 1.29924)) (197.598 0.485401 0.0495631 #(0.0248193 -0.00306678 -0.00667275 -0.0014236 0.0114491 0.0091926 -0.0023926 -0.0167224 -0.0201609 -0.00339142 -0.00311447 -0.00213343 -0.00661917 -0.00708419 0.00117074 0.0105285 0.010503 0.000885714 -0.00157855 -0.00449273 -0.0024985 -0.000379483 -0.0043849 0.0022342 0.0114984 0.0120889 0.0118227 0.0206663 0.0203387 0.01268 -0.00367646 -0.0148372 -0.0196786 -0.0256279 -0.0246386 -0.0201119 -0.0148319 -0.00916508 -0.00126804 0.0198383 0.0319355 0.0159117 0.00101828 -0.0089909 -0.0292361 -0.0476222 -0.0687146 -0.089934 -0.113823 1.33378)) (125.124 0.316632 0.0503045 #(0.0130568 -0.00225892 0.00216152 0.0102169 0.00996052 -0.00255912 -0.0097279 -0.0196243 -0.00656228 -0.000937932 -6.12063e-005 -0.000608431 -0.00526008 -0.00223335 0.00268855 0.00317693 0.00183598 0.00660908 0.00583385 -0.00116981 -0.00278075 -0.00730575 -0.0127456 -0.00600758 0.00295042 0.00742113 0.0148913 0.0264792 0.0296855 0.00264396 -0.00385496 -0.00327753 -0.023196 -0.0218689 -0.015055 -0.00831472 -0.0139174 -0.0128882 -0.000967953 0.012294 0.0210776 0.0214656 0.0105105 -0.0134574 -0.0314187 -0.0453388 -0.0664272 -0.107779 -0.148171 1.37876)) (71.37 0.227496 0.0564585 #(-0.0142429 0.012727 0.0152038 0.013247 0.0124478 0.00703828 -0.0126102 -0.0229412 -0.0168578 -0.00561364 0.00559436 0.00298623 -0.0049227 -0.00038521 -0.00127981 0.00423441 0.000763587 0.00976382 0.0108994 0.00630644 -0.00368733 -0.0148032 -0.023322 -0.0161698 -0.000889858 0.011531 0.0186532 0.0329139 0.0305486 0.00665483 -0.0125951 -0.0144017 -0.0205354 -0.0305956 -0.0183857 -0.000585577 0.0114074 0.00891327 0.00153785 0.00446643 0.00473343 0.015059 0.0101803 -0.0146464 -0.0351526 -0.0511088 -0.0647666 -0.0850186 -0.118079 1.33668)) (40.4377 0.0852366 0.0459113 #(-0.0335089 0.029908 0.0183897 0.0176984 0.0101193 0.00829117 -0.0170098 -0.0268985 -0.022606 0.00232026 0.0189546 -0.0045041 -0.00575308 -0.0100939 0.00425405 0.00177554 0.00632439 0.0070991 0.0135077 0.0172888 -0.00309632 -0.0159993 -0.0288205 -0.0254887 -0.0108957 0.00733041 0.0214328 0.0301479 0.0306404 0.0070994 -0.0123194 -0.025963 -0.0100594 -0.00332728 -0.00658321 -0.000959254 0.00177248 0.00985076 -0.0049481 -0.00260225 0.00144116 0.00476165 0.00342908 -0.0128849 -0.0221734 -0.0326228 -0.0534822 -0.0924536 -0.143692 1.34984)) (27.3832 0.070801 0.0508484 #(-0.0140748 0.0135211 0.0169284 0.0134048 0.00664361 -0.000844623 -0.025384 -0.00976012 0.00801802 0.00636203 -0.00289115 -0.0127367 0.000562452 0.00700169 0.00416503 0.00548033 0.00503239 0.00518513 0.00212309 -0.00811506 -0.0249022 -0.0165552 -0.00808011 -0.0032732 -0.00323997 0.0128592 0.0143886 0.0210239 0.0149843 -0.0102482 -0.00523455 -0.0127067 -0.00629629 -0.0118239 -0.00186732 0.00661671 0.000807708 0.0076143 -0.00151332 -0.0141276 0.000588052 0.013716 -0.00222398 -0.0188076 -0.0188453 -0.0187286 -0.0391334 -0.0564238 -0.0793644 1.23514)) (30.7375 0.040934 0.0364929 #(-0.0243691 0.00812592 0.015261 0.01097 0.0205355 0.0101767 -0.0151796 -0.0251579 0.00184063 0.0088331 0.00252205 0.000583772 -0.00157531 -0.000798763 0.00905121 0.00117476 0.00355867 -0.00185548 0.00468458 -0.00729399 -0.0289016 -0.0190386 0.00930854 -0.00472978 -0.0131431 -0.00543118 0.00841419 0.0272355 0.0256443 -0.00636553 -0.00757628 -0.00558504 -0.000516058 -0.00121443 -0.0138289 0.00110727 0.00668947 0.00434654 -0.00919808 -0.0198922 0.00235468 0.0144602 -0.000975259 -0.0245124 -0.0246625 -0.015985 -0.0371288 -0.0397989 -0.0669062 1.22136)) (42.0859 0.00626129 0.0121973 #(-0.0734655 0.0296172 0.013634 0.0452539 0.00702914 0.057469 -0.0232954 -0.0727147 -0.0229838 0.0545064 0.022556 -0.0378221 -0.0116609 -0.0131154 0.0381253 0.0259823 -0.0219215 -0.0248628 0.0469329 -0.00591986 0.0161304 -0.0248895 -0.0474258 -0.0134104 -0.011063 0.0414246 -0.0607445 0.0508991 0.0641952 0.00526139 -0.0600509 0.00150282 0.00627574 -0.070137 0.0242186 0.0169948 0.0408282 0.0438345 -0.0204922 -0.0610643 -0.0804496 0.0966152 0.0588874 -0.0136561 -0.0697122 0.00834575 -0.047428 -0.0855743 -0.478215 1.63444)) (48.3822 0.0133138 0.0165886 #(-0.0991241 0.0620696 0.0256428 0.0325504 0.030601 0.0200286 -0.0346818 -0.0543453 -0.000353481 0.0292389 0.0225596 -0.0231814 -0.0230041 -0.00406665 0.0324386 0.00882869 -0.0235801 0.0419879 0.00354304 -0.0088214 0.00179125 -0.0386059 -0.020162 -0.0161291 -0.0274193 0.0200131 0.00125343 0.0450822 0.0571638 -0.0335057 -0.0273933 -0.0201817 -0.0220575 -0.0085605 -0.000251926 0.0202286 0.0402841 0.0305421 -0.0148375 -0.0251732 -0.04472 0.0420287 0.0255921 -0.0131808 -0.0380019 -0.0228509 -0.0479855 -0.104387 -0.277699 1.47947)) (52.3586 0.0659523 0.0354912 #(-0.0350294 0.0226496 0.0266707 0.0151374 0.00559978 -0.00178336 -0.0131273 -0.00792491 0.00702189 0.00803718 0.000224972 -0.0104286 -0.0107735 0.000890825 0.000619345 0.00514007 -0.000477151 0.00445113 0.0122391 0.00292333 -0.0091859 -0.0264601 -0.0178257 -0.00867586 0.00144957 0.00389939 -0.00103973 0.00526759 0.0114127 0.00266532 -0.0114983 -0.0129203 -0.0101913 0.00682779 0.023871 0.0120872 0.00875099 0.0033859 -0.00336156 -0.00727741 -0.00798061 0.00279848 -0.00798744 -0.0160221 -0.02748 -0.0249909 -0.0413176 -0.0503363 -0.0665837 1.23408)) (57.2864 0.0998289 0.0417448 #(-0.0107891 0.0182459 0.0133387 0.00654529 0.00351746 -0.0028236 -0.00652551 -0.00276973 0.00189705 0.00363537 -0.00543967 -0.00428984 -4.74181e-005 0.00728144 -0.000418819 -0.00318095 0.00296512 0.00149376 0.00209253 -0.0105876 -0.0105755 -0.00732988 -0.0124828 -0.00540931 -0.00364074 0.00253872 -0.000591894 0.0020125 0.00672111 -0.0103777 -0.00817489 -0.00341224 0.00892754 0.00393065 0.00183264 0.0170761 0.0103609 0.0093558 -0.00221637 -0.00689539 -0.00883095 -0.00260063 -0.00561736 -0.0152408 -0.0198652 -0.0251051 -0.0359384 -0.043327 -0.0516084 1.19939)) (63.2886 0.0659521 0.0322813 #(-0.0395131 0.0278336 0.0226114 0.0208169 0.00156559 -0.00586198 -0.00373168 -0.0129797 -0.000442788 0.00591266 0.00384389 -0.00649693 -0.000432298 0.00820201 0.00205019 -0.00693928 -0.00561469 0.00651516 0.00426545 -0.00287469 -0.0195372 -0.0148713 -0.00282639 -0.00135895 0.00476877 0.00385195 -0.00114983 0.00160519 0.0150339 -0.00888809 -0.0157333 -0.00871617 -0.00192295 0.00638566 0.00653376 0.0147419 0.00964909 0.00830972 -0.00471322 -0.00721979 -0.00854983 -0.00297041 0.000582071 -0.00321452 -0.0251575 -0.0448269 -0.0465566 -0.0617166 -0.0814745 1.26877)) (68.2143 0.127344 0.0432067 #(-0.00650372 0.0166661 0.0110006 0.0046084 -0.000191608 -0.000655383 -0.0075612 -0.00289214 0.00188358 0.00579054 0.000329202 -0.00681358 -0.00225101 -0.000353251 0.0031628 -0.0053415 -0.000525401 0.00656196 0.00272409 0.00256422 -0.0160209 -0.0140322 -0.00207772 -0.00301927 -0.000189949 -0.00236457 0.00311191 0.00706533 -0.000524762 -0.00984277 -0.0108244 -0.00768298 0.000888997 0.00214318 0.0071796 0.0118653 0.0159322 0.00963205 -0.00200409 -0.0107815 -0.00688397 0.000662548 0.00124322 -0.0216095 -0.024252 -0.0275861 -0.0290191 -0.0455658 -0.0594961 1.20854)) (74.5766 0.00960274 0.0113474 #(-0.0930925 0.0474147 0.0783675 0.00847634 -0.0083235 0.0389507 -0.0156469 -0.0811489 -0.00383005 0.0271399 0.0027488 -0.0036905 -0.0380551 0.0424861 0.036423 -0.0258928 -0.0261861 0.00709007 0.0423739 0.0478494 -0.0457433 -0.0682701 -0.0230027 0.0330979 0.0021217 -0.00664132 -0.0268997 0.0548632 0.100473 -0.0711387 -0.0110561 -0.0158289 -0.0476065 -0.0351137 0.00284219 0.0323319 0.0313311 0.0736398 0.0142766 -0.10177 -0.0582263 0.0770375 0.0914699 0.0357695 -0.12508 -0.0345359 -0.0237482 -0.0585581 -0.687455 1.80702)) (89.851 0.0668036 0.0272671 #(-0.047951 0.0391961 0.0312392 0.0264315 0.0152606 -0.0229461 -0.0203805 -0.0182092 -0.00178092 0.00435629 -0.00460121 -0.00718773 -0.00219992 0.00637422 0.00988643 0.00875952 0.00355863 0.0092556 -0.00376029 -0.00369781 -0.0084366 -0.0248106 -0.00997018 -0.00992863 -0.00298569 0.00552284 0.0193635 0.0324098 0.00560115 -0.0147652 -0.0174123 -0.0176175 -0.017063 -0.00976483 0.00645685 0.0115746 0.0243375 0.0212918 0.0038104 -0.00756 0.00845826 0.00991446 0.00809276 -0.000765567 -0.0407473 -0.0481121 -0.0785197 -0.118162 -0.175228 1.42139)) (111.491 0.0612596 0.0234406 #(-0.071768 0.0568083 0.0427606 0.0216603 -0.00175519 0.00236969 -0.0168044 -0.027955 -0.00413897 0.00759891 0.00307185 -0.0137154 -0.021489 0.00188837 0.0194342 0.0167963 0.0109949 -0.00132022 0.0129203 0.00409717 -0.016515 -0.035451 -0.0211164 -0.0147696 -0.00623048 0.017651 0.0231703 0.0352329 0.0277801 -0.0201851 -0.0270755 -0.0333369 -0.0135395 -0.0048966 -0.00213377 0.01776 0.0243864 0.0268 0.00479255 -0.0136091 0.00196506 0.0109521 0.0263541 0.00149658 -0.0351393 -0.0414662 -0.0804536 -0.15343 -0.262886 1.52039)) (131.563 0.0385887 0.0171263 #(-0.0518673 0.0134846 0.0263128 0.0468026 0.024454 0.0220736 -0.0400596 -0.0676488 -0.0114445 0.0413724 0.0448596 -0.0289181 -0.0607654 0.00419211 0.039212 0.0198165 -0.0106986 -0.00978497 0.0268256 0.0153281 -0.014289 -0.0258232 -0.021492 0.00140582 -0.0194537 -0.0176859 0.00346931 0.0616223 0.0476843 0.000242224 -0.0396149 -0.0480542 -0.0287999 0.00734256 0.00921102 0.0219239 0.0281868 0.0214498 0.0045841 -0.0526773 -0.0290021 0.0477786 0.066508 -0.00482082 -0.060896 0.00723903 0.00689539 -0.17291 -0.656903 1.81153)) (151.886 0.102626 0.0259939 #(-0.070856 0.0486957 0.0480601 0.0368429 0.0182886 -0.00829156 -0.0513057 -0.0475156 -0.00697538 0.0443591 0.0264049 -0.0186967 -0.046636 -0.00991082 0.0358113 0.0296259 -0.00965236 -0.00183771 0.0116684 0.0166791 -0.0164862 -0.0397139 -0.0181811 -0.0084272 -0.01239 -0.000257272 0.0267701 0.0470878 0.0342028 -0.0154802 -0.0370322 -0.0415501 -0.0235126 1.97047e-005 0.0225005 0.0265028 0.0239742 0.0125777 -0.00895148 -0.0232263 -0.000947537 0.0428729 0.0258008 -0.0298816 -0.037036 -0.00471161 -0.0249833 -0.174155 -0.397768 1.60503)) (165.11 0.169794 0.0320682 #(-0.0409658 0.0441689 0.0293712 0.0214998 0.0154116 -0.00248447 -0.0422952 -0.0478381 -0.00388453 0.0270632 0.0266513 -0.00557179 -0.022944 -0.0116277 0.0116475 0.0182246 0.00737678 -0.00598205 -0.00128794 0.00345216 -0.00394256 -0.00695017 -0.0256291 -0.0322332 -0.012631 0.0176517 0.0309905 0.0230604 0.0224319 -0.0106256 -0.0268479 -0.0207674 -0.00587152 -0.00570336 -0.00197812 0.0122906 0.0205968 0.031643 0.00252642 -0.0332331 -0.00542228 0.0405915 0.0309338 -0.0143715 -0.0384462 -0.0185082 -0.0347614 -0.166035 -0.349634 1.55773)) (177.174 0.178624 0.0317519 #(-0.0375195 0.0292643 0.0300942 0.0307154 0.0193178 -0.00509529 -0.0345436 -0.0373165 -0.0172528 0.0236766 0.0201161 -0.0183973 -0.0276741 0.00996924 0.0330329 0.0152227 -0.00951397 -0.0122329 -0.00113485 0.0194899 -0.0119267 -0.0292984 -0.015638 -0.0142287 -0.0148578 -0.000859865 0.0260062 0.0534978 0.0402742 -0.0219816 -0.040437 -0.0341774 -0.0049463 -0.0116811 -0.0123897 0.0190348 0.0504628 0.0449273 -0.00894907 -0.0495895 -0.0187866 0.0407222 0.046073 -0.00801632 -0.0446076 -0.0182126 -0.03077 -0.167466 -0.369669 1.57394)) (179.99 0.221245 0.03506 #(-0.037004 0.0260371 0.0372679 0.0497295 0.0157299 -0.0244911 -0.0537488 -0.0510671 0.00512908 0.05199 0.0203676 -0.0338469 -0.0238147 0.0127183 0.0230843 0.00442021 -0.0115414 0.00421587 0.0188467 -0.00272606 -0.0256457 -0.0344065 -0.0104499 -0.00267908 -0.00204974 0.00352165 0.02398 0.0343543 0.0255179 -0.0152773 -0.0303301 -0.0266642 -0.0139434 -0.00355751 -0.0084824 0.0107571 0.0423518 0.0526576 -0.00233367 -0.0445417 -0.0249914 0.0319504 0.0506834 -0.0160456 -0.0561795 -0.0084321 -0.00738221 -0.153557 -0.379863 1.55632)) (166.887 0.252327 0.038884 #(-0.0419053 0.0366535 0.0498127 0.0359369 0.00208074 -0.0250268 -0.0524974 -0.0402762 0.00682585 0.0354895 0.0297739 -0.0147708 -0.0304251 -0.00374599 0.0183841 0.0130221 0.00121661 0.00411938 0.00494517 0.000507366 -0.0263356 -0.0463632 -0.0168647 0.0149596 0.0144969 0.00307392 0.0082568 0.0288554 0.0295293 -0.00737698 -0.0363064 -0.0244228 -0.0110509 -0.00137184 -0.01354 0.00159516 0.0392046 0.0550105 0.0155153 -0.0394186 -0.0271276 0.0202588 0.0342747 -0.0055672 -0.0407041 -0.0119139 -0.0198007 -0.157004 -0.344951 1.53129)) (164.943 0.182476 0.0332611 #(-0.0614847 0.034366 0.0618075 0.0440773 0.010115 -0.0176925 -0.0502932 -0.0698586 -0.0117179 0.0583499 0.0553452 -0.0141319 -0.052825 -0.00920142 0.0291995 0.0159293 -0.00586749 -0.00306322 0.0226316 0.00427445 -0.0340741 -0.0437776 -0.0123615 0.00698813 0.00470649 0.00949797 0.00789906 0.0335011 0.0219034 -0.00266724 -0.0265675 -0.030155 -0.0143053 -0.0093868 -0.00158663 0.0163901 0.0203923 0.0417646 0.0187303 -0.0392964 -0.037276 0.0437944 0.0678762 -0.016769 -0.0789091 -0.0197703 0.0398731 -0.156601 -0.511722 1.65878)) (176.99 0.261053 0.0384053 #(-0.06 0.056536 0.045999 0.0280942 0.0117416 -0.0124533 -0.0449422 -0.0463361 -0.00718186 0.0308653 0.0198448 -0.0192072 -0.0242862 0.0065568 0.031481 0.0162032 -0.00801501 -0.00216827 0.0134013 -0.00587761 -0.0383848 -0.0362193 -0.0129257 0.0157857 0.00474063 -0.00184301 0.0202611 0.041013 0.0198278 -0.0191734 -0.029208 -0.0221024 -0.0116136 -0.0121702 -0.00611537 0.0173498 0.0404119 0.0315245 -0.00593292 -0.0237962 -0.000431722 0.0439062 0.0334822 -0.0297822 -0.0607389 -0.0164012 -0.00830834 -0.154607 -0.362478 1.54998)) (176.048 0.159462 0.0300963 #(-0.0377232 0.0103334 0.036835 0.0488153 0.0179723 -0.00819109 -0.0460628 -0.0619188 -0.00111458 0.0446256 0.032363 -0.00836746 -0.0360712 -0.00850298 0.0216202 0.0175984 -0.000914048 -0.0173185 0.00126597 0.0264074 -0.00629105 -0.043736 -0.017196 0.00494882 -0.000320422 -0.012511 0.00430157 0.0466093 0.0305521 -0.0031329 -0.0376142 -0.024873 0.00750779 -0.012678 -0.0104912 0.00134055 0.0376222 0.0412994 -0.0218273 -0.0452171 -0.0128663 0.072725 0.0680508 -0.0173601 -0.0684261 -0.0212582 0.0188153 -0.175166 -0.561992 1.72452)) (171.946 0.2352 0.0369847 #(-0.0512015 0.0329072 0.0503361 0.0280294 0.00184622 -0.0107644 -0.0348259 -0.0337681 0.00209173 0.0265416 0.028044 -0.0189349 -0.0371111 -0.000802031 0.0279831 0.0122725 -0.00874739 -0.00112342 0.0180879 0.000223799 -0.0259366 -0.0351892 -0.00449204 0.00197593 -0.0162875 -0.011366 0.0181628 0.0541492 0.0395807 -0.0167336 -0.0418708 -0.0160073 -0.00774302 -0.00128406 -0.00712924 -0.00703709 0.0178146 0.0397532 0.00726889 -0.0174794 -0.00498909 0.0427668 0.0408804 -0.0175914 -0.0525046 -0.0244365 -0.014682 -0.171468 -0.395718 1.59284)) (185.859 0.163683 0.0296764 #(-0.0468658 0.0116617 0.0555765 0.036102 0.0116869 -0.0136073 -0.0419413 -0.0311445 -0.015847 0.0536179 0.0374088 -0.0318291 -0.0562696 -0.0204646 0.0520056 0.0366832 -0.00267281 -0.0268453 0.00390152 0.0151844 -0.0141306 -0.026449 -0.00214409 -0.00146158 -0.0202671 -0.0306729 0.00986482 0.0542944 0.0595679 0.00293662 -0.0374089 -0.0316308 -0.0279362 -0.00383883 -0.00461755 -0.00381387 0.0302674 0.0462364 0.00234255 -0.0420869 -0.0176493 0.0621579 0.0781717 -0.0259631 -0.0837177 -0.0197173 0.0222038 -0.172749 -0.543442 1.71216)) (211.324 0.258974 0.0350069 #(-0.0303184 0.0212199 0.0351346 0.0323836 0.0108293 -0.0194528 -0.0440712 -0.0258231 0.0179244 0.0423101 0.00743043 -0.040367 -0.0363898 0.0067014 0.0337238 0.0109171 -0.0145224 -0.00777405 0.0187512 0.010748 -0.0157507 -0.020169 -0.00503133 -0.00636303 -0.0319918 -0.0279937 0.0172805 0.0607111 0.0519986 -0.00764891 -0.0419867 -0.0321224 0.0100713 0.00236086 -0.0196657 -0.0170583 0.0223451 0.0362193 0.000122523 -0.0184589 0.0140273 0.0644042 0.0497302 -0.0380606 -0.0744375 -0.0264989 -0.0209174 -0.164711 -0.384479 1.59087)) (230.546 0.254813 0.0332454 #(-0.0214216 0.00872379 0.0339929 0.0315809 0.0174031 -0.0232373 -0.0489485 -0.0241287 0.0209643 0.0453702 0.0190406 -0.0440306 -0.0441669 -0.00157853 0.0268724 0.0234296 -0.000401617 -0.0057701 0.000344993 -0.0054568 -0.0178071 0.0024068 0.0155485 0.000746876 -0.0375718 -0.0484998 0.00853225 0.0571187 0.0551759 -0.0142224 -0.0451274 -0.0277836 0.0263546 0.0402985 -0.0197452 -0.0401687 -0.00351748 0.0313089 0.00705256 -0.0369839 -0.00653953 0.0851077 0.0978434 -0.0156217 -0.102129 -0.0527658 0.00792703 -0.158984 -0.494505 1.67382)) (251.512 0.22152 0.0296775 #(0.00271906 -0.0125085 0.0301646 0.0306547 0.00855251 -0.0179234 -0.0350287 -0.0305762 0.00779454 0.053486 0.0394365 -0.0393962 -0.0650717 -0.0198502 0.0326874 0.039916 -0.0010092 -0.0179188 0.00205602 -0.00398159 -0.00877683 0.0106262 0.0187416 -0.0120917 -0.0564597 -0.0545574 0.0119312 0.0765 0.0649359 -0.0149672 -0.0521681 -0.0268912 0.0228738 0.0277597 -0.00505434 -0.0391086 -0.000955081 0.0337932 -0.00277864 -0.0493297 -0.0119853 0.100552 0.124828 -0.0159932 -0.127861 -0.0612138 0.0295559 -0.144989 -0.555044 1.70991)) (254.186 0.155867 0.0247629 #(0.011018 -0.035849 0.0315776 0.0392745 0.01848 -0.0184897 -0.0290829 -0.049739 -0.000114797 0.0517803 0.04403 -0.0251357 -0.0530782 -0.0079027 0.0214459 0.0319004 -0.0185972 -0.0210457 -0.00556451 0.0118538 0.000887009 0.0257463 0.0265477 -0.0284303 -0.0724463 -0.0721507 0.0469847 0.0785231 0.069301 -0.026447 -0.064972 -0.032767 0.00653783 0.0563972 0.0303594 -0.0350536 -0.0475477 0.0379776 0.00958391 -0.0490296 -0.0492565 0.0859668 0.161288 -0.000991608 -0.140484 -0.0439296 0.0763862 -0.147115 -0.750695 1.84834)) (225.37 0.0803291 0.0188794 #(0.0290101 -0.0687017 0.0407707 0.0383633 -0.0152389 0.00254714 0.0114647 -0.0328925 -0.021924 0.00257726 0.0623568 -0.00416147 -0.0660898 -0.0300196 0.0572706 0.0552422 -0.027837 -0.0653128 0.00149151 0.0264922 -0.00315019 0.0193053 0.0486365 0.00427569 -0.0987687 -0.0861261 0.00501995 0.0945006 0.109231 -0.0131216 -0.077788 -0.0512939 -0.00858637 0.0620822 0.041699 -0.0369608 -0.0380424 0.0273551 0.0409665 -0.0644617 -0.0854918 0.0805598 0.178136 0.0300991 -0.186435 -0.0584791 0.205418 -0.075875 -1.13303 2.07226)) (198.485 0.0417265 0.0144991 #(0.0414603 -0.0623938 0.0061811 0.0288222 -0.0158102 0.0252802 0.00307337 -0.00304176 0.00367747 -0.0489033 0.0357009 0.0204158 -0.0552591 -0.0256414 0.0346049 0.0958179 -0.0284009 -0.100873 -0.00722169 0.0205522 0.0295442 0.033256 0.0421494 0.00768483 -0.110423 -0.0846969 -0.0244979 0.0889337 0.157045 0.00102777 -0.0813333 -0.0900497 -0.0138341 0.0341514 0.0721558 0.00377355 -0.033424 0.010766 0.0245269 -0.0515001 -0.119286 0.0335791 0.213235 0.125951 -0.204453 -0.179761 0.270221 0.202002 -1.65027 2.32378)) (171.548 0.1509 0.0296587 #(0.0250778 -0.0426171 0.00843798 0.0396997 0.0226322 -0.0146932 -0.0283293 -0.01936 0.0069322 0.0354412 0.0250028 -0.0357834 -0.0414478 -0.0136723 0.0292158 0.020287 -0.00117164 -0.00726955 -0.00706735 0.000159039 -0.00407658 0.0190887 0.0257392 -0.0278326 -0.0682253 -0.0552612 0.0202806 0.0931883 0.0784599 -0.037487 -0.082894 -0.0424946 0.0518775 0.0627942 0.000169138 -0.0458972 -0.0190695 0.0107115 -0.00659794 -0.0314802 0.00511231 0.0991288 0.0788463 -0.0108271 -0.0699992 -0.0146887 -0.00873203 -0.228192 -0.553044 1.75651)) (138.651 0.0571929 0.02031 #(0.0213914 -0.0306978 0.00848927 0.0130779 0.00721775 0.00427365 0.00961346 -0.0314829 -0.018867 0.036295 0.03503 -0.0305203 -0.0463152 -0.0107846 0.0382213 0.0409777 -0.0373991 -0.0384969 0.0128019 0.00295524 0.0157249 0.0419502 0.0294107 -0.0318793 -0.11091 -0.0681277 0.0179675 0.131618 0.114326 -0.0427296 -0.109902 -0.0736138 0.0191553 0.091943 0.0543933 -0.0340794 -0.0436619 0.00746334 -0.0066161 -0.0679531 -0.0238454 0.0924077 0.161235 0.0122723 -0.139703 -0.0326624 0.115233 -0.166794 -0.931623 1.99133)) (113.308 0.193753 0.0413518 #(-0.0270571 0.018724 0.0316812 0.0297654 0.00202789 -0.0163134 -0.0290023 -0.0123064 0.0176842 0.0233915 -0.00357253 -0.0336344 -0.0271282 0.00653117 0.0284495 0.0179925 -0.004167 -0.0157728 -0.00964692 0.000267421 0.00122534 0.0146035 0.00149512 -0.0396562 -0.058053 -0.0255875 0.0451789 0.0754793 0.044493 -0.0379303 -0.0597916 -0.015322 0.0420665 0.0354546 -0.0132543 -0.0383832 -0.0285421 0.000937585 0.0195054 0.0265873 0.0502106 0.0593278 0.0136192 -0.0502636 -0.0466451 -0.0180557 -0.0524014 -0.164365 -0.318595 1.53476)) (103.037 0.0623253 0.0245944 #(-0.00724495 -0.00593484 0.0107629 0.0261896 0.0129414 0.00340164 -0.0251773 -0.0270683 0.00747135 0.0385192 0.018441 -0.0377958 -0.0304305 0.00450653 0.0229534 0.00567204 -0.0264594 -0.0176736 0.000876183 0.0471199 0.0172663 0.0124283 0.00241253 -0.0617734 -0.103682 -0.0406255 0.0578767 0.121063 0.0822661 -0.0454017 -0.102194 -0.042812 0.0321046 0.0833275 0.00602523 -0.0478943 -0.043304 0.000262387 0.00598665 -0.00374976 0.0385322 0.079333 0.0654235 -0.0354309 -0.092082 0.00159915 0.0131218 -0.204327 -0.571633 1.75234)) (92.5577 0.120027 0.0360108 #(-0.0398489 0.0324612 0.0367935 0.0220619 0.00704562 -0.0272926 -0.0200099 -0.00659618 0.0169783 0.015708 -0.00599385 -0.0153675 -0.0128987 0.0082064 0.0102226 -0.000522355 -0.00199441 -0.00674596 -0.00220103 -0.00689017 -0.00809083 0.00336812 -0.0126411 -0.0439452 -0.04063 0.00361202 0.0505336 0.0555444 0.02238 -0.0310165 -0.038806 -0.00364963 0.0180895 0.00954 -0.00503501 -0.0195219 -0.0205427 0.00318622 0.0185383 0.0345637 0.0376351 0.0372337 0.00566722 -0.0260961 -0.0314731 -0.0229805 -0.0612615 -0.148592 -0.24421 1.45165)) (66.5989 0.0842179 0.0355606 #(-0.0384904 0.0427509 0.0324356 0.0194716 -0.00585732 -0.0144022 -0.0118444 -0.00525952 0.0111836 0.00537657 -0.00948216 -0.00957872 -0.000929858 0.00996204 0.00650146 0.00151737 -0.00610687 -0.00883977 -0.0111524 -0.00821151 -0.0121669 -0.00254634 -0.0339117 -0.0355781 -0.013952 0.0280202 0.0436449 0.0292268 0.00874941 -0.0239858 -0.0194654 -0.00890681 0.0037191 -0.00475951 -0.00518569 -0.00236431 0.00776458 0.0118334 0.0107269 0.0178917 0.0261446 0.0384696 0.0138593 -0.0230752 -0.043364 -0.0319342 -0.0459236 -0.112816 -0.180369 1.35766)) (42.7254 0.0264534 0.0248827 #(-0.0413135 0.0213958 0.036281 0.0248983 -0.0151715 -0.0222269 -0.00567853 0.00505671 0.017208 0.024368 -0.0203921 -0.0162792 0.000440382 0.0151094 0.0109901 -0.000613158 -0.00984668 -0.00906093 -0.00789341 0.00260445 0.0124987 -0.0123556 -0.0457957 -0.0562666 -0.0106157 0.0486385 0.0540115 0.0360568 -0.00307563 -0.0466828 -0.0306841 0.00913136 0.0174993 0.00528422 -0.0273256 -0.0166686 0.00261137 0.0230377 0.0120899 -0.00600584 0.0223933 0.0459099 0.00977329 -0.0223494 -0.0479412 -0.0230021 -0.0404154 -0.102133 -0.204478 1.38436)) (30.9113 0.0516676 0.0408837 #(-0.014936 0.00941983 0.0118751 0.000575508 0.00581291 -0.00413739 -0.012136 0.0103523 0.00720992 0.0100773 -0.000124851 -0.00765056 0.00255218 0.000894253 0.00544408 0.000794387 -0.00215897 -0.00898489 -0.0117924 -0.00653947 -0.0064785 -0.00840759 -0.0105823 -0.0100678 0.000175767 0.0102663 0.00786819 0.0237505 -0.00215373 -0.0266525 -0.00900966 -0.00600343 -0.0028658 -0.00373159 -0.00238924 -0.00278976 -0.00429102 -0.00212087 0.00253061 0.0127614 0.0230914 0.0151189 0.00146143 -0.0117057 -0.00462498 -0.00318648 -0.0265484 -0.0369997 -0.0675645 1.14867)) (15.3693 0.00836665 0.0233319 #(-0.0341159 0.00806944 0.0216334 0.0174292 -0.0149921 0.016248 -0.0180928 -0.00306738 0.0350942 0.00513288 -0.00769301 0.00579646 -0.0107035 0.0131971 0.00589453 -0.00674269 0.00261838 -0.00786856 -0.00176616 0.00564664 -0.0345646 -0.0240044 -0.0148234 -0.0133658 -0.00412353 0.0369617 0.00196105 0.0368174 0.00564198 -0.0501549 -0.0297051 0.0178704 0.0210161 -0.0155626 -0.00837293 -0.0178571 0.00812323 0.00816448 0.00151141 0.0221456 -0.00390799 0.026406 0.0064334 -0.00797861 -0.0261832 0.013857 -0.0837799 -0.0591936 -0.120175 1.27127)) (7.76696 0.0131245 0.041107 #(-0.0123117 0.00617644 -0.00098044 0.00751582 -0.00251782 -0.00337365 -0.00106648 -0.00202962 0.024234 0.000865013 -0.000377017 0.00388929 -0.00333191 0.0133695 -0.00022004 -0.00378028 -0.00320862 -0.00759729 0.010062 -0.0256383 -0.0192849 -0.0214377 -0.0114302 -0.00124626 0.00155824 0.0193932 0.00236924 0.0225305 0.00325289 -0.026002 -0.0156565 0.0123504 0.013013 -0.00652565 -0.00493443 -0.0110295 -0.00472477 0.0120849 0.0080524 0.00918786 -0.00908903 0.0273415 -0.00444183 -0.0233399 -0.0047778 -0.00719849 -0.0426428 -0.018549 -0.0650151 1.15688)) (8.89632 0.0142545 0.0400286 #(-0.00575181 0.0168131 -0.000191827 -0.023498 -0.00423681 0.025755 -0.0183111 -0.00376236 0.0252077 0.008183 -0.0122062 -0.003721 0.00288939 0.0148372 0.00886276 0.00423061 -0.00963574 0.000873132 0.00541097 -0.0280967 -0.00998672 -0.0238806 -0.0217161 -0.00753574 0.000230236 0.0280799 -0.00512027 0.00849866 0.0322065 -0.0343016 -0.00927757 0.00120511 0.0135002 -0.00237087 -0.0093355 -0.00156968 -0.00792312 0.012794 0.00838747 -0.0119611 0.00605868 -0.00193377 0.0117903 0.00816965 -0.0157005 -0.000300004 -0.0367019 -0.0246368 -0.0709357 1.15223)) (9.78194 0.0170927 0.0418016 #(-0.0124638 0.0024989 -0.00185738 -0.00369259 -0.00329147 0.0015451 0.00184027 0.00970003 0.0141567 0.0120678 0.00775671 -0.00277263 0.00105104 0.000310846 0.00513042 -0.0141369 -0.008812 0.00521768 -0.00206552 -0.00604551 -0.0120649 -0.0176494 -0.0204137 -0.0115251 0.00627893 0.0162767 0.0108663 0.00560173 0.00467505 -0.02242 -0.0112209 0.000456198 0.00829053 2.30481e-005 0.00913467 -0.00846952 0.00517986 0.00864013 -0.00133154 0.00581594 -0.00610526 0.00869507 0.00727336 -0.00365842 -0.0143366 -0.0169279 -0.0336561 -0.0311221 -0.071088 1.16895)) (11.5445 0.0160741 0.0373143 #(-0.0249007 -0.00275895 -0.000517276 0.00756758 -0.00172192 0.0176724 0.00486407 0.00102775 0.0190812 0.027876 -0.00029893 -0.00443258 -0.00532617 -0.0133783 -0.00615458 -0.00822798 -0.00903328 0.00488343 0.0122464 -0.0119956 -0.0122127 -0.0164293 -0.0183456 -0.00082874 -0.00101657 0.00939199 0.0092591 0.0164931 -0.0114048 -0.0252425 -0.0161846 -0.00699262 0.00668263 0.0180297 0.000800448 0.00638066 0.00681553 0.0168308 0.0103385 -0.00081722 -0.00148622 0.00392006 -0.00755191 -0.0011792 -0.0241647 -0.0123012 -0.0393747 -0.0402423 -0.0754633 1.19146)) (13.3295 0.0127553 0.0309342 #(-0.0231698 0.0191559 -0.0139377 0.0092944 0.0121271 -0.000232179 -0.0124583 0.0134314 0.0164421 0.024357 -7.36386e-005 -0.0199401 -0.00337023 0.0151218 -0.00455778 -0.0115682 -0.0172743 0.000976708 0.017724 -0.0074562 -0.0285266 -0.0151716 -0.030822 0.00497904 0.00790638 0.0099445 0.0162362 0.0264739 0.0175367 -0.0501894 -0.0343044 -0.00901378 0.014952 0.0105903 -0.0101648 -0.000755211 0.0171476 0.0293293 0.00838466 -0.0102206 0.00315026 0.0306831 -0.00269206 0.00531439 -0.0326658 -0.0252288 -0.0474296 -0.0704353 -0.143764 1.28812)) (15.3429 0.0120405 0.0280135 #(-0.0309064 0.0271264 0.0147487 0.00498133 0.00106183 0.0147637 -0.040844 -0.0169095 0.0389369 0.0194572 -0.00221378 -0.0170094 -0.00138509 0.0162374 0.00582746 -0.0230331 -0.0117961 -0.00156591 0.0229133 0.027122 -0.0540262 -0.0410968 -0.013133 -0.00158327 -0.0109391 0.0261228 0.0330272 0.0405228 0.0323432 -0.0623613 -0.0561195 -0.00527043 0.00668445 0.0267738 -0.00936441 -0.0283996 0.0234758 0.0255722 0.014511 -0.0129606 0.00174176 0.0403901 0.0353441 -0.000116604 -0.0455759 -0.0479024 -0.0481118 -0.0843258 -0.209947 1.37135)) (17.6721 0.019402 0.0331344 #(-0.0350609 0.0339703 0.0145886 0.000690795 0.000922172 0.00738286 -0.01517 -0.0088783 0.0201723 0.0122574 -0.0158588 -0.0119165 -0.0019645 0.020945 -0.000870479 -0.0108681 -0.00586048 0.00538485 0.0104022 -0.00321434 -0.0157964 -0.0469299 -0.0215821 -0.00373954 0.00283885 0.0148254 0.0275313 0.0364303 0.0161417 -0.0308895 -0.0417433 -0.00377748 0.0165364 0.00397155 -0.0227846 -0.0260575 0.00618754 0.0551286 0.0147865 -0.0176932 0.00941883 0.0495573 0.031147 -0.00860301 -0.0380403 -0.0458936 -0.0610949 -0.096874 -0.18716 1.3588)) (20.0442 0.0140521 0.0264774 #(-0.0709867 0.0453836 0.0460421 0.0146813 -0.0179832 0.00433517 -0.0165851 -0.00628279 0.0245804 0.0150767 -0.0114593 -0.0368579 0.00386748 0.0248403 0.00774181 -0.0237615 -0.0110972 0.00908011 0.0143327 0.012267 0.00781146 -0.0256289 -0.0705544 -0.0244927 -0.0213969 0.0392408 0.0426976 0.0769561 0.011974 -0.0784876 -0.0580746 0.0130622 0.0449024 0.0142022 -0.0384532 -0.0269607 0.00680663 0.0207385 0.0149218 -0.0149792 0.0278171 0.0648385 0.0568704 -0.00419316 -0.0892845 -0.0271809 -0.0635848 -0.137194 -0.290703 1.49428)) (22.8017 0.0273646 0.0346427 #(-0.0720317 0.0448821 0.0348815 0.0233662 -0.000985435 0.00226309 -0.0135519 -0.0209769 0.0167468 0.0101012 -0.0194102 -0.00439263 0.00504041 0.0156837 0.00598467 -0.0264652 -0.0115608 0.0185426 -0.0068165 0.0100013 -0.00188157 -0.018496 -0.0458203 -0.0312296 -0.00116534 0.0335279 0.0330629 0.0395021 0.0183978 -0.0427994 -0.0459782 0.0054253 0.0243994 -0.00582722 -0.0111125 -0.0241409 0.0054475 0.0251814 0.00891366 -0.000905372 0.0228307 0.0523174 0.0382179 -0.00320691 -0.0354807 -0.0419394 -0.0835182 -0.139596 -0.249583 1.45587)) (26.3474 0.0219953 0.0288932 #(-0.0765435 0.0426832 0.0419785 0.0283921 0.00340572 -0.00535423 -0.0212032 -0.0116924 0.00206213 0.00816488 -0.0127589 0.00934433 0.0163962 0.00930891 -0.00568188 -0.0355663 -0.0130979 0.0042239 0.0221761 0.0294585 -0.00590132 -0.0300225 -0.0529725 -0.04428 -0.00514512 0.0547305 0.0372759 0.0478592 0.0239117 -0.0702372 -0.0687804 0.0195622 0.0191373 0.0223794 0.0135526 -0.038104 -0.00282542 0.00433172 0.00929822 -0.00582157 0.0154465 0.0665377 0.0342229 0.00927136 -0.0205276 -0.0192793 -0.0956723 -0.177253 -0.343554 1.56045)) (30.1984 0.030065 0.0315528 #(-0.0979213 0.0706986 0.0397353 0.027229 -0.00146723 -0.00438662 -0.0236935 -0.0188674 0.00900385 0.011066 0.00529251 -0.00704211 0.00609007 0.00670222 0.011048 -0.0216173 -0.0263168 0.00421382 0.0169606 0.0205924 -0.018071 -0.0136472 -0.0356033 -0.0382373 0.00240587 0.00751786 0.0412371 0.0584634 0.033329 -0.0663578 -0.0641406 -0.00811986 0.0285871 0.0444783 -0.00260303 -0.0335565 -0.018181 0.00985673 0.00558086 0.0118218 0.023386 0.0433098 0.0400329 0.0116843 -0.0148176 -0.058095 -0.0779079 -0.157939 -0.31358 1.52513)) (32.1428 0.0318259 0.0314665 #(-0.0775589 0.051683 0.0288251 0.0187194 0.00984706 0.00338128 -0.0202275 -0.00651548 0.0136416 -0.00760369 0.00215332 -0.0233182 0.0134451 0.0247162 -0.00404254 -0.0118734 -0.018538 0.0113604 0.00736548 0.00204067 -0.0115196 -0.0197442 -0.0154772 -0.0363295 -0.0150368 0.0175515 0.0394107 0.053815 0.00585165 -0.0330152 -0.054677 -0.0159929 0.0341672 0.015965 -0.00299163 -0.0189119 -0.0067154 0.0143037 -0.000256563 -0.00532035 0.0260945 0.0429435 0.0476952 0.0109455 -0.0235557 -0.0298008 -0.0826709 -0.176099 -0.325686 1.54201)) (31.4202 0.0318335 0.0318301 #(-0.0971744 0.0647286 0.0577288 0.0197214 -0.00649152 -0.0216951 -0.0189122 0.00437908 0.0284074 -0.000966733 -0.0171446 -0.0107114 0.00440035 0.0142388 0.00532634 -0.0126468 -0.02169 0.00523199 0.0297256 2.45184e-005 -0.00810739 -0.0215433 -0.0335994 -0.053856 -0.00465438 0.037238 0.0491757 0.0548962 0.014561 -0.073022 -0.0403319 -0.0130117 0.00834094 0.0434427 -0.00417276 -0.0078477 -0.0118494 0.00744896 -0.00313036 -0.0123154 0.0214602 0.059643 0.056315 0.00853147 -0.0377529 -0.0250175 -0.0860953 -0.178818 -0.327932 1.55029)) (32.4444 0.0301064 0.0304621 #(-0.0807 0.057348 0.0412646 0.0366669 -0.00996071 -0.0130091 -0.0387371 -0.00774177 0.0350818 0.0241313 -0.0154081 -0.0231186 0.00127267 0.0151109 -0.000317825 -0.0114935 -0.0136006 -0.00971232 0.0131985 0.0123626 0.0233086 -0.0265093 -0.0606854 -0.0258504 -0.0165391 0.0251411 0.0470309 0.053574 0.0180307 -0.0502542 -0.0485886 -0.0164236 0.019835 0.0329606 -0.00101179 -0.0302517 -0.0018849 0.0308459 -0.00743693 -0.0159462 0.0094627 0.0539938 0.0554317 0.0208811 -0.0307534 -0.0204858 -0.0821197 -0.181269 -0.37734 1.5857)) (40.9172 0.0650495 0.0398721 #(-0.0572582 0.0414552 0.0350494 0.0183922 0.00440463 -0.00850967 -0.00613651 -0.0179503 -0.00262387 0.0195232 -0.0131559 -0.00454892 0.00177392 0.0065445 0.00194393 -0.00781929 -0.00616173 -0.00313379 -0.000702812 -0.00178652 -0.014563 -0.0209123 -0.0269462 -0.0162782 0.00491859 0.0228838 0.0258315 0.027738 0.00459301 -0.0176909 -0.0295674 -0.0017052 0.0107792 -0.00448647 -0.00151116 -0.00392171 -0.00643332 0.00597558 0.0150378 0.0149934 0.0222908 0.0451681 0.0323751 0.00353828 -0.0263688 -0.050642 -0.0923144 -0.142247 -0.194605 1.40832)) (42.9245 0.0380718 0.0297817 #(-0.0619835 0.0538987 0.0254833 0.0191851 0.000713942 -0.00965684 -0.0114323 -0.0178469 0.0175577 0.0131995 -0.0072923 -0.00832834 -0.00811007 0.00959091 0.00557504 -0.00996733 -0.00855112 -0.00974844 0.00913783 0.0117909 -0.0045425 -0.0256592 -0.0292943 -0.0307577 -0.00238131 0.0201101 0.0259082 0.0446931 0.0181626 -0.0452096 -0.0297406 -0.0143662 0.023201 0.0203186 -0.00421108 -0.0211625 -0.00441318 0.019116 0.000645667 -0.00607597 0.0221206 0.0483723 0.0479185 0.015123 -0.02304 -0.0353189 -0.100976 -0.171954 -0.291149 1.51649)) (35.4435 0.0741689 0.0457449 #(-0.0592469 0.0408393 0.0310192 0.0213087 0.000897261 -0.0097075 -0.0127374 0.00034184 0.00697528 0.00416767 -0.00709337 -0.00543548 -0.00262597 -0.000460251 0.00462508 -0.000103108 -0.00210094 -0.000600998 -0.0064083 -0.00812498 -0.0110879 -0.014929 -0.0210607 -0.0126928 -0.00625044 0.0121755 0.0253735 0.0353037 0.00209597 -0.0177743 -0.0179092 -0.0111032 0.00635534 -0.000694276 -0.00804003 -0.00382186 0.00598897 0.00926817 0.00874331 0.0115986 0.0207321 0.0434171 0.0317387 0.00501884 -0.0295828 -0.0488442 -0.0859817 -0.140721 -0.179372 1.38875)) (31.5655 0.0508454 0.0401347 #(-0.0590031 0.0481201 0.0415922 0.0145118 -0.00625927 -0.010634 -0.022698 0.00794115 0.0129372 0.011031 -0.00684227 -0.0269145 0.000574552 0.0097944 0.00870401 -0.0154143 -0.00608816 -0.00337432 0.00658044 -0.000562268 -0.0114323 -0.0168882 -0.0267139 -0.0354475 -0.00491647 0.0324642 0.0368173 0.0353376 5.39129e-005 -0.039796 -0.021031 -0.00123375 0.0136188 -0.00348024 -0.00871654 0.00380723 0.0164729 0.0135323 -0.00439517 -0.0080045 0.0109003 0.0528155 0.0444091 0.0206946 -0.0118078 -0.0443984 -0.10415 -0.168437 -0.257971 1.47706)) (30.9527 0.0382595 0.0351577 #(-0.0677928 0.0651594 0.0430938 0.00356799 -0.0158889 0.000628987 -0.0127898 -0.00558382 0.0158968 -0.00226313 -0.00538957 -0.00778266 0.00155987 0.00443769 0.00375692 -0.0105507 -0.0224075 0.00426307 0.00792974 0.000294564 -0.000787178 -0.0161313 -0.0342735 -0.0403149 -0.00675935 0.0293195 0.0435918 0.0478281 0.00545949 -0.0534773 -0.037442 -0.0111263 0.0321929 0.020819 -0.00755799 -0.00482975 -0.00528935 0.0154923 0.00365394 -0.00549552 0.0121106 0.053678 0.0478409 0.019575 -0.0286409 -0.0335462 -0.0765612 -0.177995 -0.331 1.53233)) (31.4075 0.0364452 0.0340646 #(-0.0649986 0.0576299 0.0324902 0.00773543 -0.00458665 0.00495247 -0.0191388 0.000145591 0.000613326 0.00395394 0.000636622 -0.0207581 0.00467082 0.0155624 0.0110861 -0.0131649 -0.0232556 -0.00176555 0.00395216 0.00802351 -0.00893858 -0.021152 -0.016588 -0.0283998 -0.0138537 0.0249458 0.0287153 0.0452579 0.0204232 -0.053952 -0.0535749 0.00280977 0.0440965 0.0328232 -0.0150095 -0.0388665 -0.0096805 0.0162576 0.0154429 -0.00290426 0.029801 0.0596534 0.0460045 -0.00865289 -0.0497685 -0.0141297 -0.0805603 -0.160605 -0.335686 1.53526)) (31.6576 0.0348485 0.0331782 #(-0.0618954 0.0523533 0.0235303 0.0153525 0.00172889 -0.00168407 -0.0110182 -0.0142045 0.0170727 1.99435e-006 0.0017121 -0.0190737 -0.0111033 0.0169703 0.0280168 -0.01063 -0.0322064 0.00426402 -0.00485 0.0146215 -0.00758876 -0.0226077 -0.0252398 -0.0189545 -0.00568113 0.00980641 0.0269183 0.0392206 0.0257317 -0.0475402 -0.0534524 0.00178895 0.0586262 0.0278462 -0.0327184 -0.0414883 -0.0120922 0.029826 0.0131607 0.00598402 0.00931486 0.0642811 0.057244 -0.00679361 -0.0464739 -0.04173 -0.072625 -0.161229 -0.31275 1.52407)) (34.7383 0.0559897 0.0401467 #(-0.0415582 0.026703 0.0259679 0.0111422 0.00204608 -0.00618647 -0.00950887 0.0120808 0.0102095 -0.00150538 -0.0114168 -0.0193223 -0.00463892 0.0133971 0.0187653 -0.00583736 -0.0127744 -0.0100488 0.0111868 0.0106626 -0.0205418 -0.0312655 -0.0304695 -0.0160161 -0.00137347 0.0194299 0.0309445 0.0366569 0.00705069 -0.0166283 -0.0404884 -0.00764167 0.0169512 0.0132674 -0.00907035 -0.0275286 -0.0054365 0.0307347 0.0158178 0.00474018 0.0264909 0.0460957 0.0291759 -0.00850643 -0.0359522 -0.0586856 -0.0731063 -0.11696 -0.205816 1.40186)) (36.4119 0.0463771 0.0356887 #(-0.0389951 0.0307876 0.0205879 0.00908905 0.00555359 -0.0121034 -0.00687764 0.00752914 0.0176609 0.00566536 -0.0208413 -0.0229413 0.00156059 0.00543264 0.00694066 0.00249693 -0.00335328 0.000401892 0.0138262 0.00128668 -0.0283111 -0.0256373 -0.0237493 -0.0291584 -0.00703129 0.0152271 0.0393229 0.0452958 0.0231804 -0.0291094 -0.0417306 -0.00489797 0.0160917 0.000583816 -0.0194554 -0.0235409 0.00563181 0.0393978 0.0237208 -0.00447947 0.0171657 0.0551852 0.0282278 -0.022097 -0.0371377 -0.0598215 -0.0687185 -0.118988 -0.195594 1.40087)) (31.5195 0.0823719 0.0511211 #(-0.0506811 0.032627 0.0260271 0.0133287 0.00707792 -0.00716418 -0.00792555 -0.00164158 4.37169e-005 0.00655899 -0.00403331 -0.00510847 -0.00250636 0.00465444 0.012035 0.0010902 -0.00567664 -0.00723898 -0.00466529 -0.00771452 -0.0268553 -0.0264261 -0.00282889 0.000687852 0.00062155 0.00777579 0.0113666 0.0250398 0.020167 -0.0104087 -0.0261586 -0.0112883 -0.00423545 0.0070317 -0.000811418 -0.0200803 0.00317688 0.0237687 0.0201803 0.0121356 0.0175142 0.033371 0.0253085 -0.00456846 -0.0415392 -0.0596395 -0.0783815 -0.0936876 -0.114877 1.30627)) (25.4029 0.0602808 0.0487134 #(-0.0551556 0.0394576 0.0270103 0.0236226 0.00186073 -0.00761447 -0.00740441 -0.00712806 0.00591052 -0.00309897 -0.00157216 -0.0120145 -0.00111416 0.0139671 0.00880658 -0.0012513 0.00244409 -0.0133322 -0.00925009 0.00123142 -0.034305 -0.0168858 -0.00914378 -0.0110158 0.000306792 0.0116358 0.0236282 0.0251389 0.00218792 -0.00727665 -0.0207191 -0.00825958 0.00274023 -0.00288428 -0.00666814 -0.0172675 0.00904082 0.0154382 0.0150386 0.0254515 0.0314402 0.0294853 0.0295901 -0.00445611 -0.0469681 -0.0574121 -0.0877862 -0.106583 -0.135491 1.339)) (22.7468 0.078061 0.0585811 #(-0.04486 0.0298865 0.0293551 0.0157202 0.00558635 -0.00166327 -0.0153884 -0.00699228 0.00676223 0.00247051 -0.00958823 -0.00736895 0.00134663 0.00697311 0.0112086 -0.000206178 -0.00881016 -0.00624388 -0.00932781 -0.0197023 -0.0190608 -0.011131 -0.0120463 0.000508607 0.00205883 0.0130596 0.00678453 0.017637 0.0173591 -0.00929612 -0.0146321 -0.00917131 -0.0076256 0.0010683 -0.00392937 -0.00849227 0.006057 0.0173038 0.0170559 0.0185356 0.0307804 0.0321241 0.0197208 -0.00024348 -0.0379323 -0.0627024 -0.0771216 -0.096205 -0.116027 1.29578)) (22.8884 0.0716601 0.055954 #(-0.0482403 0.0307585 0.0275873 0.0182651 0.000529184 -0.0022478 -0.00768153 -0.00720601 0.00320312 0.000542559 -0.00613952 -0.00509576 0.000853576 0.00746592 0.00241067 0.00149092 -0.0103518 -0.00548361 0.00260866 -0.00854271 -0.0165325 -0.024049 -0.0159926 -0.0106845 0.00539235 0.0217353 0.013189 0.0138549 0.0113874 -0.00669787 -0.0144154 -0.00952096 -0.00989752 0.000984178 -0.00567269 -0.0075391 0.00597343 0.0157336 0.0231019 0.0212661 0.0260539 0.0267702 0.0234177 -0.00360673 -0.0411499 -0.0479637 -0.0797028 -0.101779 -0.123467 1.30416)) (25.0679 0.0404904 0.04019 #(-0.0569264 0.0393012 0.0442286 0.0105388 -0.0280166 0.0130403 -0.000293758 0.00097423 0.0019422 -0.0135517 -0.0129558 -0.00137247 0.0176797 0.0111486 -0.00223964 -0.00550807 -0.00602055 -0.00683842 -0.0111893 0.0040559 -0.00320025 -0.0210676 -0.0166252 -0.0273107 -0.00925243 0.0352852 0.0153395 0.028238 0.0100151 -0.0296035 -0.0250562 0.00185137 0.0255143 0.00681541 -0.0269629 -0.0225865 0.00339151 0.0176583 0.0135256 0.0128693 0.0308694 0.0396139 0.0268478 -0.00453411 -0.0321182 -0.0411832 -0.0894552 -0.13549 -0.18868 1.40068)) (26.172 0.0414675 0.0398048 #(-0.0630411 0.0445934 0.0340673 0.0179641 -0.0126086 -0.000847251 0.000227371 0.00106207 0.0131494 -0.0118745 -0.0160848 -0.00908814 0.00502605 0.0118554 0.0134411 0.006348 -0.0203072 1.60219e-005 -0.0092216 -0.0131313 0.00614179 -0.023434 -0.0225044 -0.0205765 -0.00759216 0.0190882 0.0216325 0.0341826 0.0139076 -0.0241181 -0.0163891 -0.0082327 0.0124357 -0.00390939 -0.0224453 -0.0154005 0.00127452 0.0147405 0.0170827 0.0260113 0.0421892 0.0303767 0.0235349 -0.0138023 -0.0474366 -0.0434775 -0.0753137 -0.111706 -0.172436 1.36862)) (24.9425 0.0127896 0.0226443 #(-0.0733194 0.0354206 0.0577736 0.0308347 -0.0289842 -0.00604918 -0.014531 -0.0101977 0.0240066 0.0242339 -0.0217081 -0.0255996 0.00547605 0.0210583 0.0282309 -0.0144568 -0.0284572 -0.0338683 0.0165173 0.0371958 0.00744609 0.00585112 -0.0600074 -0.0549116 0.000340121 0.0385451 -0.00124994 0.0513382 0.0555081 -0.0592178 -0.0733577 -0.0170409 0.0586459 0.0553344 -0.0225186 -0.0556362 -0.0233135 0.0506938 -0.00436045 -0.0332437 0.00902178 0.0879455 0.0599741 -0.000640262 -0.0442607 -0.0220114 -0.0610923 -0.165358 -0.458725 1.64915)) (22.7641 0.0174743 0.027706 #(-0.0584102 0.0459445 0.031618 0.0172284 -0.0102017 -0.00307119 -0.0147159 -0.0128069 0.0192186 0.0263737 -0.0162587 -0.0214138 -0.00164627 0.0164729 0.0190751 -0.00745766 -0.0243652 -0.0185078 -0.0136905 0.043886 0.0129518 -0.0298972 -0.0265289 -0.0403765 -0.00958069 0.0232809 0.0161453 0.044125 0.0361099 -0.0522329 -0.0619475 -0.000899218 0.0508566 0.0368301 -0.0180012 -0.0430501 -0.00970191 0.00226846 0.0163143 0.00440859 0.00654716 0.0745107 0.0559268 -0.0237278 -0.0297872 -0.0202482 -0.0711893 -0.150335 -0.394529 1.58051)) (19.5777 0.0125371 0.0253057 #(-0.0826795 0.0683275 0.0428367 0.02936 -0.021953 -0.0169267 -0.0348315 -0.00679442 0.025703 0.045118 -0.00592805 -0.0419876 -0.00936561 0.0199536 0.035517 -0.0131276 -0.0408877 -0.0219309 0.0500002 -0.0214081 0.0310525 -0.0126166 -0.046124 -0.0345309 -0.027267 0.0407647 0.00779675 0.0551954 0.0525408 -0.0538993 -0.0680158 -0.0475148 0.0549138 0.0610506 0.00643009 -0.0500036 -0.0294172 0.0234389 0.0124404 -0.0212963 0.0223014 0.0563873 0.0415865 0.0218463 -0.0398211 0.00419091 -0.103894 -0.150699 -0.43171 1.62141)) (18.2418 0.0253117 0.0372501 #(-0.0607523 0.0562677 0.0384613 0.00424439 -0.0162383 -0.00801906 -0.00889723 -0.00153158 0.0178735 0.00687857 -0.00841403 -0.0109761 -0.000752748 0.0188549 0.0145737 -0.0116472 -0.0244779 -0.0102738 0.00684694 -0.00289441 -0.0144796 -0.0119951 -0.0216497 -0.0176858 0.000835 0.00693356 0.0142641 0.0338318 0.0169442 -0.0304174 -0.03766 -0.00345847 0.0310024 0.00119207 -0.0121249 -0.0113758 -0.00784907 0.0241519 0.0161341 0.0165755 0.0178807 0.0323894 0.0223039 0.0113459 -0.0211709 -0.0354951 -0.0753201 -0.130449 -0.212926 1.39061)) (18.2633 0.0252861 0.0372093 #(-0.045203 0.0314978 0.0349495 0.00211169 -0.00893727 0.00352343 -0.0123056 -0.00291805 0.0126091 0.00904179 -0.00646769 -0.0145041 -0.00502528 0.0120276 0.0164997 -0.0114284 -0.0165834 -0.00612101 0.0129625 0.0025109 -0.0220033 -0.00506117 -0.0341916 -0.0253116 0.0116913 0.0206707 0.00947406 0.0215501 0.018648 -0.0253815 -0.0210033 -0.00128285 0.00803003 0.00165846 -0.00961188 -0.0112029 -0.00390969 0.018762 0.0176612 0.0141336 0.0162613 0.0423988 0.0169786 0.00664183 -0.0149723 -0.0514017 -0.0758318 -0.125953 -0.214712 1.39864)) (17.5015 0.0281862 0.0401311 #(-0.0467037 0.0285618 0.0290192 0.00889659 0.00523947 -0.0106185 -0.00584188 0.00343646 0.0078645 0.00378798 -0.0136156 -0.012084 0.00284047 0.0112584 0.00930852 -0.0112164 -0.00383024 -0.00982824 0.0153711 -0.00475254 -0.018373 -0.0203009 -0.0232701 -0.0175478 0.00286289 0.0183034 0.0126237 0.036949 0.00550275 -0.0201175 -0.0171514 0.000764537 0.00264071 -0.0167697 -0.00575089 -0.00377642 -0.00121029 0.0205625 0.019458 0.00863159 0.025104 0.0386815 0.0262647 -0.00411803 -0.0406888 -0.0471502 -0.083648 -0.103756 -0.174039 1.36212)) (17.2526 0.0295366 0.0413764 #(-0.0459645 0.0347026 0.0174516 0.0140821 0.00442935 -0.00595253 0.000786888 -0.00770935 0.00586936 0.00240675 0.00201615 -0.0114029 -0.00715992 0.0219725 0.00668619 -0.00508303 -0.0104611 -0.00929612 -0.00120529 -0.00989537 -0.0169932 -0.0133932 -0.0188951 -0.000876892 -0.000297876 0.000200907 0.0129674 0.0262989 0.00787067 -0.0241803 -0.0115058 -0.000143185 0.0150916 0.0138443 -0.0335769 -0.0206819 -0.00174932 0.0245576 0.0198266 0.017498 0.020447 0.0325335 0.0246589 0.00835593 -0.033657 -0.0520807 -0.0742558 -0.105502 -0.158577 1.3385)) (17.7939 0.0194564 0.0330671 #(-0.0393023 0.0249954 0.0281254 0.00881808 -0.0170303 -0.000254086 -0.0238422 0.0104953 0.0267727 0.0218212 -0.00832039 -0.0378733 -0.00966003 0.0208957 0.0258569 0.00523595 -0.0125616 -0.0198685 -0.00261361 0.0267587 -0.00756953 -0.0295961 -0.0220904 -0.0216108 -0.022352 0.010996 0.018242 0.0477541 0.0378138 -0.0342758 -0.0460006 -0.0110206 0.0200271 0.0216202 -0.0010694 -0.0481358 -0.00989713 0.0183853 0.0178495 0.0123016 0.00932306 0.0462944 0.0355045 0.00738312 -0.0433972 -0.0431022 -0.0752448 -0.111662 -0.22808 1.41783)) (16.2645 0.0198753 0.0349571 #(-0.0444276 0.0359794 0.0176339 0.0166024 -0.00509977 -0.00228653 -0.0161215 0.0145134 0.0174299 0.000749843 -0.00504707 -0.026946 -0.00241593 0.0172678 0.024325 -0.00596551 -0.0248575 -0.0135324 0.0111395 0.00225044 -0.0129778 -0.0134113 -0.0270257 -0.0234719 -0.000202711 0.0218519 0.00693315 0.0315688 0.0147574 -0.0374582 -0.0197909 -0.0087806 0.0357156 0.00379843 -0.0129535 -0.0288524 -0.0066429 0.02112 0.00394448 0.0222445 0.0191879 0.0458149 0.0290641 0.00188522 -0.0291704 -0.0394177 -0.0755161 -0.123621 -0.231673 1.41693)) (13.9843 0.0203448 0.0381422 #(-0.0406508 0.0247845 0.0280528 0.016247 -0.00667394 0.00575473 -0.00883099 -0.00538796 0.0124414 0.00246849 -0.0144231 -0.0122821 5.65498e-006 0.0240839 0.00861459 -0.00217033 -0.0235125 -0.0168742 0.0055966 -0.00328378 -0.00988276 -0.0124962 -0.0202922 -0.0046567 0.00286656 0.0025336 0.000137633 0.0296567 0.0200221 -0.0189908 -0.0237597 -0.000666055 0.0173422 0.0148898 -0.028545 -0.0280338 -0.00862389 0.0107104 0.0292579 0.0223673 0.0356336 0.027171 0.0365469 -0.00876548 -0.0413912 -0.0440555 -0.0862704 -0.0992445 -0.175119 1.36053)) (13.7519 0.0318418 0.0481192 #(-0.0439203 0.0286811 0.019099 0.0131209 0.00116507 0.00239283 -0.00349781 -0.00764389 0.00731754 0.00111961 -0.0119648 -0.0166307 0.0112826 0.0209392 0.00437699 0.00510248 -0.00768695 -0.0223086 -0.0103192 -0.00707175 -0.0131623 -0.0187769 0.00250121 -0.00532104 -0.0114664 0.00451569 0.0158921 0.0267952 0.00829616 -0.0112708 -0.0156018 -0.00644018 0.00364066 -0.00682353 -0.0102232 -0.0152849 -0.00104906 0.0131723 0.0312335 0.0306407 0.0224566 0.0393104 0.00734389 -0.0167909 -0.0521184 -0.0325935 -0.0547162 -0.0785076 -0.107318 1.25643)) (14.1001 0.036371 0.0507887 #(-0.0416909 0.0311513 0.0216856 0.010757 0.0023053 -0.00539498 -0.0122303 -0.00307753 0.0143497 -0.0013006 -0.00140553 -0.0114054 0.00277976 0.0180154 0.00290372 -0.000693336 -0.0231679 -0.00686742 -0.00978564 -0.00577415 -0.00821437 -0.0128852 -0.00872088 -0.0119665 0.00729519 0.00605096 0.00574081 0.0229577 0.00811213 -0.0167 -0.00908976 0.00335362 -0.00364028 -0.00150706 -0.00937789 -0.0185555 -0.000902989 0.0273121 0.0204276 0.0180267 0.0271863 0.0347298 0.0131781 -0.0189297 -0.042958 -0.0488664 -0.0552135 -0.0687342 -0.0978135 1.24792)) (14.2751 0.0340747 0.048857 #(-0.0375261 0.024581 0.0173357 0.0105803 0.00152478 5.81223e-005 -0.0049663 0.000233414 -0.0059578 0.0172982 -0.0123975 -0.0121001 0.00817213 0.00614464 0.0063125 0.00277281 -0.0072908 -0.00298882 -0.00532286 -0.0151193 -0.0130224 -0.0190079 -0.00477871 -0.00682809 -0.00484661 0.0136435 0.0106479 0.0201277 0.016766 -0.0148155 -0.0230016 0.0010569 0.00368719 -0.00836747 -0.0108471 -0.0115598 -0.000523546 0.020508 0.0238148 0.0105346 0.0278912 0.030346 0.015747 -0.00584426 -0.0429999 -0.0557868 -0.0671162 -0.0745447 -0.115248 1.28424)) (15.2833 0.022009 0.0379483 #(-0.0444502 0.0319226 0.0206898 0.00408402 0.0038444 0.00518289 -0.0102187 0.00644884 0.0154201 0.00243678 -0.0155881 -0.0226183 -0.00535144 0.0143481 0.0263679 -0.00816404 -0.00439294 -0.00726711 0.00245852 -0.0075432 -0.0210695 -0.022927 -0.0121272 -0.00257655 -0.0142863 0.0116892 0.0195945 0.0314798 0.0171628 -0.026222 -0.0236029 -0.00279915 0.0139127 -0.00411994 -0.0220793 -0.0223499 0.0130053 0.0163297 0.014851 0.0168635 0.030113 0.0393203 0.0185481 -0.0032677 -0.0508295 -0.049786 -0.0681459 -0.100596 -0.141854 1.3324)) (16.2369 0.0167683 0.0321361 #(-0.0461453 0.0336128 0.0171639 0.00638196 0.00304988 0.00700732 -0.0124934 -0.0014443 0.0229149 0.00812651 -0.0156464 -0.027978 0.00155632 0.0148617 0.0236262 -0.0053183 -0.0306435 0.0156539 0.00576177 -0.00936416 -0.019092 -0.0214782 -0.0106117 -0.0139679 -0.00487678 0.0153928 -0.000839796 0.0328364 0.0370444 -0.0267438 -0.0258321 -0.0084227 0.00140206 0.0170352 -0.0249207 -0.0137748 0.00622318 0.00877071 0.0176743 0.0140944 0.0160371 0.0299227 0.0280204 0.00486572 -0.0471303 -0.0549004 -0.0792787 -0.0862093 -0.156202 1.34944)) (15.8715 0.00862119 0.0233064 #(-0.0416665 0.0196847 0.0351245 0.00540738 0.000268711 0.000455022 -0.00585776 -0.00906765 0.019069 0.0231938 -0.0242396 -0.0320143 0.00375507 0.0115636 0.0160781 -0.00497688 0.0104297 -0.0136434 0.0112971 0.000516813 -0.0335269 -0.00981996 -0.0165414 -0.0128344 -0.00386654 0.0142686 -0.0124378 0.0254652 0.0577827 -0.0404511 -0.0399016 0.00257038 0.0284287 0.00205934 -0.00698707 -0.0282862 -0.0129552 0.0375839 -0.00052652 -0.00139833 0.010455 0.0601005 0.027725 0.00917528 -0.0452916 -0.0495308 -0.114218 -0.0824053 -0.228428 1.43507)) (14.8358 0.0137405 0.030433 #(-0.035238 0.0325776 0.00811017 0.00564153 0.00956963 0.00160376 -0.00735718 -0.0106363 0.00927161 0.0156551 -0.014077 -0.0256614 0.00892661 0.0141185 0.0219964 0.00497017 -0.0213388 -0.00393183 0.00307147 -0.00527207 -0.00932004 -0.0149748 -0.0293915 -0.0137217 0.0110029 0.00820573 -0.00731358 0.0228706 0.0342061 -0.0270083 -0.0231551 -0.00456665 0.0112681 -0.00073322 -0.00608638 -0.0299522 0.00616215 0.0218085 0.0147894 0.01267 0.0171617 0.0382049 0.0155666 0.00222878 -0.0301421 -0.0626113 -0.101723 -0.0618076 -0.14028 1.33014)) (12.9037 0.0170322 0.0363311 #(-0.0361427 0.0205666 0.0172627 0.017552 -0.00678439 0.00380304 -0.00573859 0.00913126 0.0155822 -0.00543546 -0.00759378 -0.0190302 -0.00357661 0.0192382 0.00804061 0.000652122 0.000361389 -0.0179953 -0.00446666 0.00560995 -0.0184849 -0.0113776 -0.0232038 -0.00865374 -0.000620224 0.00406897 0.00305195 0.0334702 0.0202773 -0.0270967 -0.0247178 0.00910172 -0.000104248 0.000138012 -0.0102208 -0.0169238 0.00120545 0.0203969 0.0133169 0.0181668 0.0202681 0.0266863 0.021128 -0.0131285 -0.0365628 -0.0378504 -0.0756192 -0.0782206 -0.137483 1.31255)) (10.7606 0.0176641 0.0405161 #(-0.0483414 0.0247989 0.0315676 0.00585319 -0.00234617 0.009571 0.00527321 -0.010687 0.0163059 0.00885164 -0.0125577 -0.0134762 -0.00967633 0.0164184 0.00952228 -0.00630756 -0.0123339 0.00271924 -0.00671046 -0.0020015 -0.00886391 -0.0281787 -0.0135787 -0.0134191 0.00144693 0.00931767 0.000242524 0.0183011 0.0329657 -0.0164957 -0.0380229 0.00540505 0.0215291 -0.00189809 -0.0201857 -0.0100815 0.00201447 0.0118938 0.00726428 0.0202927 0.0107608 0.0392477 0.0177106 -0.00825438 -0.0278289 -0.0360925 -0.0803767 -0.0690058 -0.118693 1.27992)) (9.692 0.0163592 0.0410842 #(-0.0435487 0.0238735 0.0221766 0.0130095 -0.0102838 0.0102648 -0.00263138 0.00405493 0.0139175 0.00368894 -0.0144828 -0.0187693 0.000191167 0.0191079 0.0188621 -0.00391941 -0.0163057 -0.0108496 0.0112138 -0.0054916 -0.0242603 -0.0107545 -0.03524 -0.00986785 0.00436468 0.0159444 0.00288566 0.0280451 0.0177601 -0.0226378 -0.0232638 -0.00458616 0.0132367 -0.00669003 -0.00879428 -0.0174804 -0.00444567 0.0183938 0.0174463 0.0192643 0.0206223 0.0364433 0.00547454 0.00493223 -0.0256411 -0.0374557 -0.0770796 -0.0699102 -0.107736 1.2591)) (10.6083 0.0116637 0.0331585 #(-0.0339536 0.0239064 0.0193139 -0.00206308 -0.00420809 0.0162964 -0.00446401 -0.00723342 0.032238 0.00872946 -0.0187994 -0.0242643 -0.0134408 0.0259891 0.0161434 0.00132369 -0.0197008 -0.00519451 0.00655926 -0.00738285 -0.0172127 -0.0237242 -0.0212511 -0.0206254 0.0103538 0.0122223 -0.00456432 0.0447003 0.0352811 -0.0406705 -0.0316736 0.00797188 0.00656864 -0.0115901 -0.0027629 -0.0128048 -0.00570429 0.0118761 0.0188073 0.0222462 0.0124456 0.0410702 0.00791332 -0.00379496 -0.0170523 -0.0476136 -0.0781826 -0.0542285 -0.143112 1.28919)) (13.6333 0.00775797 0.0238547 #(-0.0364152 0.0291058 0.0227928 0.00502204 -0.0253292 0.048831 -0.0291211 -0.014896 0.0320535 0.00774532 0.000503408 -0.0316866 -0.00546139 0.0360913 0.00840064 -0.0208066 -0.0145649 0.000116066 0.00307052 -0.0122648 -0.0118387 -0.0277435 -0.0112472 -0.0110968 0.0148855 -0.00123177 -0.021587 0.0284518 0.0631961 -0.0358807 -0.0443364 0.00976814 0.00940558 0.00815862 -0.0182798 -0.0167586 0.0109045 0.0136983 0.0074112 0.00384714 0.0165089 0.0481128 0.0182451 0.00169633 -0.0279793 -0.0379538 -0.093019 -0.0760834 -0.15798 1.33196)) (14.9529 0.0090799 0.0246421 #(-0.0173912 0.0117589 0.0215592 -0.000100125 -0.00958332 0.0178238 -0.0220747 0.00944662 0.0241577 0.0100921 -0.0118245 -0.0308733 -0.0111011 0.0260419 0.0364623 -0.0174218 -0.0250652 -0.02109 0.0203074 0.00684312 -0.0399599 -0.0207732 -0.0171705 -0.0007063 0.00839398 0.0148383 -0.0116208 0.0395184 0.0320917 -0.0477367 -0.0288544 -0.013006 0.0343035 0.0151606 -0.0250012 -0.0238014 0.010687 0.0287551 0.00443121 -0.00885899 0.0187292 0.0305535 0.0398672 0.0256628 -0.0622547 -0.0391768 -0.0803045 -0.063373 -0.174028 1.33167)) (15.4713 0.0103036 0.0258065 #(-0.0317778 0.0220012 0.023046 0.0107401 -0.00700271 0.0157947 -0.0168062 -0.0275037 0.0367403 0.0183112 -0.0155777 -0.0184876 0.00537082 0.00657688 0.00920857 -0.00738122 -0.0258576 -0.00495231 0.0158989 0.0138713 -0.0316929 -0.0372503 -0.00456503 0.00398878 -8.80907e-005 0.00931697 -0.0254795 0.0441872 0.0447222 -0.0413425 -0.0365677 -0.00544457 0.0244433 0.0112955 -0.0182531 -0.0124006 0.00266321 0.0168735 0.014526 -0.0109792 0.0141278 0.0440501 0.000770168 0.0424379 -0.0278247 -0.0526684 -0.0777227 -0.0873046 -0.175866 1.34552)) (14.1187 0.00916422 0.0254771 #(-0.045858 0.0400202 0.0205128 0.00743514 -0.00145771 0.00837235 -0.0248272 -0.00172827 0.0233621 0.0100241 -0.0135858 -0.0126684 -0.00336266 0.0149539 0.0171219 -0.016675 -0.0227132 -0.000102549 0.020379 0.00582718 -0.016864 -0.0320013 -0.0340711 0.00940389 -0.00660789 0.0171697 -0.029894 0.0563412 0.0606243 -0.07549 -0.0483998 -0.000330146 0.0359239 0.0257492 -0.00142432 -0.0289091 -0.0018749 0.012466 0.00260386 -0.0152575 0.00862908 0.053457 0.03697 0.0345913 -0.0435553 -0.039316 -0.0996627 -0.0778146 -0.205904 1.3743)) (12.5142 0.0109789 0.0296196 #(-0.0372881 0.0196089 0.0233113 0.000903561 -0.0047855 0.0192033 -0.00402685 -0.00304796 0.0072131 0.000961789 -0.00506267 -0.0118756 0.00342084 0.015397 0.00417627 0.00558174 -0.014547 -0.00178372 -0.00917506 0.0153024 -0.021183 -0.0321192 -0.0190146 -0.0116695 0.0083767 0.00252157 0.0031781 0.03148 0.0255226 -0.0305256 -0.0148153 0.00160903 0.010152 0.00196973 -0.0133266 -0.0138634 -0.0111339 0.0246016 0.00657759 0.0046415 0.0102237 0.0405588 0.0267124 -0.0205946 -0.0262742 -0.0302408 -0.0733365 -0.0751875 -0.141942 1.30887)) (13.1881 0.0149057 0.033619 #(-0.0392646 0.0235916 0.0113109 0.0165674 0.000356377 0.0096727 -0.00454504 -0.0118521 0.0189847 5.30982e-006 -0.00576891 -0.00829558 -0.00267612 0.0116296 0.0180062 -0.00463104 -0.015852 -0.0119515 0.00220159 0.00224108 -0.027798 -0.0126524 -0.0149994 -0.00157439 -0.00384594 0.00016854 0.00338744 0.0262442 0.0138858 -0.0262235 -0.0060537 -0.000456936 0.0188089 0.00153812 -0.0108762 -0.0196819 -0.00571758 0.0244648 0.0111209 0.00558558 0.0127132 0.0348169 0.015571 -0.0175171 -0.0217261 -0.045869 -0.0708379 -0.0505154 -0.114525 1.26721)) (12.7999 0.015072 0.0343149 #(-0.0333835 0.0122214 0.0259325 -0.000845576 -0.00411607 0.0249855 -0.00362802 -0.00123161 0.00374519 0.00881159 -0.00779002 -0.0221836 -0.00150112 0.0259934 0.00794084 -0.00206094 -0.0134564 -0.00876726 -0.00201227 -0.0224425 0.00930002 -0.0259136 -0.0165928 -0.00342897 -0.00262414 0.00704048 -0.00242533 0.0235934 0.0114056 -0.0151016 -0.0109616 0.00159531 0.0111167 -0.000793585 -0.00855475 -0.0193289 0.00818316 0.0173823 0.00418687 0.0104691 0.0231481 0.0104235 0.0158543 -0.00351913 -0.0424822 -0.0357488 -0.0522538 -0.0381995 -0.0936292 1.22602)) (12.2473 0.0193377 0.0397359 #(-0.0208312 0.0113622 0.0107963 0.0102407 -0.0113957 0.00688707 0.00914879 -0.00983215 0.00520417 0.00334524 -0.0068846 -0.004754 -0.00291994 0.0137996 0.0146112 -0.00155131 -0.0176285 0.00365784 -0.0104858 -0.0192718 -0.000923549 -0.0131308 -0.0111267 -0.00719019 0.000579761 0.0111471 -0.00676168 0.0234209 0.0115352 -0.0168934 0.0025673 -0.00926516 0.00685466 -0.00665536 -0.00981694 0.000390394 0.00485606 0.00488992 0.00723448 0.0167406 0.00949511 0.00968203 0.0148381 -0.0192989 -0.0238238 -0.0274632 -0.0505583 -0.0318813 -0.0690697 1.18902)) (12.5963 0.016594 0.0362957 #(-0.022897 0.0164408 0.00922307 0.00712825 0.00029965 0.0126678 -0.00781488 -0.00903336 0.00276701 0.00841422 -0.00438664 -0.00758085 0.00516114 0.00530365 0.00871018 -0.00177273 -0.00100205 -0.00497492 -0.00829477 -0.00643409 -0.0175788 -0.016037 -0.0116676 -0.00203718 -0.000523905 0.0101769 -0.00147634 0.0081845 0.0146411 -0.0119274 -0.00436797 -0.000224399 -0.00513704 -0.00984378 0.0115129 -0.0102507 0.00516442 0.00549147 0.00572397 0.0118901 0.0113157 0.0218897 0.00945389 -0.0113134 -0.0298536 -0.0302538 -0.053088 -0.0372686 -0.0642578 1.19366)) (13.5525 0.01008 0.0272723 #(-0.0123657 0.0053427 0.019458 -0.0176663 -0.0176549 0.0404966 -0.00390325 -0.00579765 0.00887555 0.00317001 0.00172718 -0.00829583 0.010417 0.0153962 -0.00556122 -0.00680748 -0.00745445 -0.00852993 -0.00462103 -0.0159715 -0.000628177 -0.0183191 -0.0147015 -0.00193298 -0.00415885 0.0236506 -0.0098982 0.015603 0.0132994 -0.0134173 -0.00543716 0.00140853 -0.000410987 -0.0155814 -0.00399504 -0.000352762 -0.00284362 0.0100352 0.0139833 0.0156556 0.00280102 0.00782334 -5.04827e-005 -0.0182239 -0.0189623 -0.0239327 -0.0540221 -0.0168124 -0.0578101 1.18215)) (12.068 0.00596845 0.0222389 #(-0.00770466 -0.00247063 0.020446 -0.00341433 -0.0175267 0.0299728 -0.00334073 -0.021708 0.0222189 0.00349176 -0.00219307 0.000507939 -0.000906229 0.0251413 -0.00347692 -0.0193672 -0.008356 0.0107288 -0.00522202 -0.0373399 0.0110019 0.00334983 -0.0260176 -0.00508717 0.0076833 0.0123874 -0.0218113 0.0217126 0.0137616 -0.0343426 0.00107652 -0.0108971 0.00723602 -0.0140256 0.00945629 0.008111 -0.013161 0.0263409 0.00322294 0.0169951 0.0125402 0.00634017 -0.0281478 0.00833678 -0.0210252 -0.0480639 -0.0657505 0.00962592 -0.0670183 1.193)) (8.95623 0.00286173 0.0178752 #(-0.0299596 -0.00271054 0.0316405 0.00830122 -0.0430843 0.052154 0.00778072 -0.0218403 0.015222 0.00900955 0.000450335 -0.0294424 0.0109118 0.0305165 0.0185617 -0.0211344 -0.00754338 0.000348268 -0.015125 0.000259483 -0.00953378 0.00744751 -0.0392438 -0.0133562 -0.0140394 0.0473366 -0.0574915 0.0274957 0.0739216 -0.0633229 -0.00625577 -0.00332914 0.0318236 -0.039495 -0.0259531 0.0239393 -0.0180297 0.0156937 0.0245471 0.0241233 0.00445331 0.0143366 -0.0112595 0.0136985 -0.0568217 -0.0400073 -0.106216 0.040655 -0.0915969 1.22924)) (6.49921 0.00445611 0.0261847 #(-0.0170517 -0.0101715 0.0184278 0.00588615 -0.0192503 0.0377397 -0.00414877 -0.0237132 0.0261238 0.0049736 -0.00638682 0.00527185 -0.00923617 0.0111306 0.0255296 -0.0039067 -0.0151077 0.00377979 7.06266e-005 -0.0208127 0.00467839 -0.022734 -0.0168833 -0.00336075 -0.01055 0.033853 -0.0379811 0.010155 0.0492233 -0.0412482 -0.00933746 -0.0204949 0.0208357 0.00125835 -0.0115378 -0.000968487 0.00445165 0.00835097 0.00622662 0.0115168 0.000545416 0.00342692 -0.00927968 0.0260598 -0.0528268 -0.0332704 -0.0524391 0.0325668 -0.0789734 1.17526)) (5.25729 0.00395311 0.0274213 #(-0.0240403 0.0205123 0.0153895 -0.0123595 -0.0220413 0.0554869 -0.00704868 -0.0433425 0.0501927 -0.00331648 -0.0181042 -0.0055328 -0.0079657 0.0218988 0.0184512 0.000216515 -0.0131423 -0.00679136 0.0172376 -0.0200239 0.00385909 -0.0187232 -0.0339574 -0.0205053 0.00639417 0.0217717 -0.022982 0.0227078 0.0735146 -0.0648862 -0.0373938 0.00153798 0.00527095 0.0142592 -0.0107342 -0.0298141 0.00548001 0.0163492 -0.00212356 0.00278833 0.0101466 0.0397622 0.0149 0.023642 -0.01529 -0.0428728 -0.0909119 0.00412615 -0.130688 1.23334)) (4.64889 0.00405787 0.0295443 #(-0.0083154 0.00615811 0.0229795 -0.0118895 -0.011159 0.0234972 -0.00391371 -0.0106054 0.0152195 0.0045161 -0.0309345 -0.0133451 0.0142733 0.0022754 0.0224104 0.00053866 -0.0105869 0.014126 -0.00594441 -0.016928 0.000217074 -0.00374499 -0.0370543 -0.0101543 -0.0131152 0.0467066 -0.0290259 0.0361985 0.048131 -0.0712857 -0.010248 0.0200725 -0.00527912 -0.033853 0.00625684 -0.0132771 -0.00059062 0.00807303 0.0207666 -0.005388 0.00403096 0.0390784 0.0263475 0.00420176 -0.0247701 -0.0169901 -0.0981137 0.00202813 -0.122794 1.22287)) (4.2687 0.00527028 0.0351374 #(0.0119431 0.000370011 0.00297805 -0.0086345 -0.00619318 0.0209268 -0.0214211 -0.00264095 0.000795118 0.0018904 0.00504403 -0.00221174 0.000734628 0.0115394 0.00269348 0.00862158 -0.0112626 0.0128954 -0.0100209 -0.0261409 -0.00341844 -0.00612675 -0.023003 0.0109423 -0.00282099 0.0203828 -0.0265252 0.0270202 0.0322998 -0.0362086 -0.00119129 -0.0153138 -0.00350063 0.00240223 -0.0210972 -0.00135233 -0.00711855 0.000712969 0.0123906 -0.00078104 0.000209776 0.0312843 -0.00727613 0.0274143 -0.0141633 -0.0350039 -0.0442454 0.0167168 -0.0482093 1.11671)) (5.08667 0.00434494 0.0292264 #(-0.00272251 0.00941567 0.00822995 -0.014127 -0.00472909 0.0256388 -0.0205545 -0.00637778 -0.0112651 0.0378657 -0.0158337 -0.00984417 0.00216444 0.030978 -0.00207667 -0.00625094 -0.00241573 0.000887676 -0.0113091 -0.0167408 -0.00726853 -0.00532588 -0.0106122 0.000375745 -0.00057362 0.0254724 -0.018358 0.0306097 0.0326059 -0.0225176 -0.0471872 0.00568396 -0.0101327 -0.0167238 -0.0112461 -0.0017848 -0.00424018 0.0120333 0.0037898 0.0135469 0.0227388 0.0193921 -0.0318962 0.0246949 -0.0262602 -0.0227707 -0.0672516 0.0572928 -0.0571018 1.11738)) (5.64243 0.00660276 0.0342082 #(0.00180166 0.00187813 0.00574493 -0.000219231 -0.0214208 0.0292124 -0.0171232 -0.0116133 0.0143524 -0.0080191 0.00040181 -0.000264368 0.00500117 0.0156718 0.00494422 0.00107104 -0.0174182 0.00156305 -0.00116767 -0.0143132 -0.00873124 0.00879861 -0.0235025 -0.00555377 0.0159542 0.0120798 -0.00968709 0.0101018 0.0241207 -0.0283285 -0.00464771 0.00488285 -0.0317064 0.000691314 -0.0122031 -0.0076785 0.00264264 0.00947001 0.0122303 0.00967777 0.0183964 0.00361356 -0.0121287 0.0116267 -0.0186891 -0.0143781 -0.0485434 0.0242676 -0.0335089 1.09521)) (4.34906 0.00506972 0.0341424 #(0.0023974 -0.00279862 0.0120042 -0.00157989 -0.0157521 0.0239786 -0.0126398 -0.0135926 -0.0020871 0.00151955 -0.00174203 -0.00773394 0.0159697 0.00780768 0.021657 0.00663021 -0.0142795 0.00149963 -0.00494957 -0.00158777 -0.0254905 -0.0117564 -0.017529 -0.00628616 0.00849666 0.00422017 -0.0116558 0.0310608 0.0345892 -0.0316539 -0.0132967 -0.00584913 0.00354922 -0.0173338 -0.0110622 -0.0096414 0.00859083 -0.0039589 0.0226801 0.0154026 0.00896204 0.0230092 0.00481482 0.00292927 -0.0234833 -0.0254714 -0.0981472 0.0441442 -0.0688532 1.14897)) (2.61565 0.00474862 0.0426083 #(0.00879548 -0.00707132 0.0105265 0.00589761 -0.0181165 0.0122799 0.000610275 -0.0196829 -0.011157 0.0120507 -0.0115164 -0.0105635 0.0167566 0.0110644 0.0208706 0.00165262 0.00444448 -0.00889109 -0.00448973 -0.00204069 -0.0176097 -0.0204983 -0.00444134 -0.0102928 -0.000729621 0.00828533 -0.0156112 0.0249824 0.046813 -0.034427 -0.0110774 -0.0109798 -0.00690826 -0.00195731 -0.0157386 -0.00195138 0.00642795 -0.00283065 0.0119922 0.0211103 0.0124749 0.0247881 0.0132657 -0.00455936 -0.0371286 -0.0106291 -0.0739445 0.0263266 -0.0843839 1.15059)) (2.02703 0.00255318 0.0354904 #(0.0134249 -0.00506588 0.00680395 0.0105582 -0.0323818 0.0493337 -0.0217674 -0.0241798 0.00928927 -0.023553 0.0104105 -0.0160771 0.00235487 0.00839372 0.0312377 0.00805041 0.000414273 -0.0136668 -0.0141831 0.0145558 -0.01835 -0.0176581 0.00780919 -0.0178566 -0.00798348 0.0228851 -0.0520132 0.0414188 0.066511 -0.0612651 0.00654983 -0.0331677 0.0129804 -0.0240143 0.0167766 -0.000209965 -0.0232557 0.0166038 0.0163538 0.0123617 -0.00410349 0.0241719 -0.00992855 0.0157116 -0.0186285 -0.0253129 -0.0767908 0.0521641 -0.0693304 1.12793)) (2.64432 0.00171959 0.0255009 #(-0.0191815 0.0127539 0.0107323 0.00105373 -0.0253985 0.0548691 -0.00350344 -0.0407332 0.00805417 -0.00516293 0.0269923 -0.0481122 0.045745 -0.00949443 0.029402 0.00253762 -0.0224486 0.00621702 -0.0126075 -0.000360755 -0.0107886 -0.00802914 -0.0263488 -0.00418882 0.00777657 0.0122917 -0.0655835 0.0318259 0.0745041 -0.046913 -0.0178272 -0.014913 0.00287156 -0.0266232 0.016267 0.00797917 0.00580041 0.0114133 0.00738462 0.0441676 -0.0136994 0.0335519 -0.0324743 0.0188773 -0.0348701 -0.0234333 -0.174669 0.177908 -0.0964444 1.12857)) (3.49525 0.0028907 0.0287582 #(-0.022997 0.00390569 0.0195987 -0.00368246 -0.0249804 0.0205793 -0.000749982 -0.0146779 0.0253093 -0.027436 -0.00506964 0.0229678 0.0122114 -0.00660955 0.0289347 0.00446956 -0.0240813 0.0124458 -0.000533498 -0.0357979 -0.00426894 0.00482643 -0.0216519 0.00376066 -0.0166858 0.0254196 -0.047756 0.0296842 0.05304 -0.053725 0.0233847 -0.00627376 -0.0327575 0.0242391 -0.00986949 0.0018908 0.0199183 -0.001377 0.00140167 0.0246927 0.00391399 0.00494078 -0.0242442 0.0174991 -0.0272264 -0.0343578 -0.0611368 0.0862893 -0.0566336 1.08269)) (3.59173 0.00241115 0.0259096 #(-0.0280463 0.00239539 0.0275002 -0.0139323 -0.0348279 0.0607939 -0.0263654 -0.0111383 0.00125177 0.0134574 -0.0201514 0.0256755 0.0152298 -0.0129894 0.040595 -0.0242227 0.0223003 -0.0198948 -0.00945686 -0.0104881 -0.0149074 0.000106048 -0.0155021 0.00164234 -0.0275243 0.0334275 -0.0597113 0.0490029 0.0458835 -0.0406038 -0.00296535 0.00162114 0.00027736 -0.0194494 0.0124248 -0.00222679 0.0104655 -0.00167292 0.00815926 0.0283748 -0.0225562 0.0143205 -0.0188394 0.00579293 -0.0147764 -0.0167599 -0.050156 0.0847534 -0.0659405 1.07315)) (2.26719 0.00255288 0.0335561 #(-0.0136514 -0.00925972 0.0167188 -0.00485284 -0.0336646 0.0412232 -0.000246899 -0.0298077 0.00712888 0.0134616 0.0103107 -0.00485241 -0.00127703 0.0164119 0.0132654 -0.019095 0.00456902 -0.00259853 -0.000275873 -0.0127027 -0.00593184 0.0101047 -0.0413224 0.018843 -0.0107773 0.0150738 -0.0289957 0.0254439 0.0380609 -0.0406301 -0.00392326 0.0172783 -0.00857435 -0.0223009 0.00749708 -0.0165367 0.0238457 0.018136 -0.00458933 0.00245699 0.00172918 0.00670983 -0.024566 0.00660529 -0.0205404 0.00950086 -0.0578217 0.0939725 -0.0510117 1.04425)) (0.609353 0.00163717 0.0518337 #(0.00316256 -0.0122567 0.00518264 0.0126123 -0.0397706 0.0392831 0.0116002 -0.0471934 0.00805918 -0.00560564 0.000558784 -0.00409364 -0.00452707 -0.00113856 0.0257756 -0.00932488 0.00381936 -0.00247659 0.00301922 0.00335715 -0.00619763 0.0345422 -0.0321831 0.00519092 -0.00104381 -0.021393 -0.028818 0.0308446 0.0615516 -0.0569711 -0.0213437 0.00541473 0.00891156 -0.00345845 -0.00526036 -0.0140875 0.0217332 0.0150425 0.00302012 0.000750344 -0.0227373 0.0355403 -0.0606219 0.0543924 -0.0197096 0.0106198 -0.0761164 0.133679 -0.0540805 1.00403)) (0.116473 0.000738204 0.0796116 #(-0.0020667 -0.00708028 0.00649903 0.00525495 -0.0577545 0.0708488 0.0241519 -0.0957537 0.0444855 0.00816514 -0.0260424 -0.00887706 0.0161092 -0.00643925 0.0365329 -0.0114855 -0.0214506 0.00323551 4.06337e-005 0.00984418 0.00579543 0.0340158 -0.0244511 -0.00303321 -0.0329481 0.0117391 -0.0672089 0.0657941 0.120411 -0.0823802 -0.0449917 0.00125354 0.00608117 -0.0209081 -0.0254859 0.0413741 -0.00546445 0.0228035 -0.0102555 0.0282721 -0.0411615 0.0264412 -0.0625765 0.0651369 -0.0960416 0.0914793 -0.12826 0.244372 -0.0968032 0.978677)) (0.0472545 0.000482073 0.101003 #(-0.0132409 -0.00177229 -0.00651967 0.0181785 -0.057867 0.0886454 -0.0060562 -0.0415304 -0.00604645 0.00809692 -0.0261498 0.0308232 -0.0207518 0.039377 0.0286866 -0.00414628 -0.101779 0.0925687 -0.0566329 0.0285281 -0.0124488 0.0429751 -0.0231868 0.00492606 -0.0382182 0.0353667 -0.0854897 0.072105 0.138783 -0.152908 0.0118608 -0.0236536 0.0280545 -0.0358662 -0.00158007 0.0410328 -0.0307116 0.0351427 -0.0487812 0.0650863 -0.105127 0.0931477 -0.118991 0.157664 -0.204664 0.186411 -0.180145 0.351459 -0.130844 0.92427)) (0.0200657 0.000490229 0.156305 #(-0.0167117 0.0226238 -0.0290179 0.0310399 -0.05596 0.0754746 -0.00102182 -0.0240663 -0.00557826 -0.00226293 0.00760277 0.00121096 -0.0371931 0.0368175 0.00439128 -0.00121828 -0.0701961 0.0851828 -0.0429475 0.0221135 -0.0202851 0.0294757 0.0173632 -0.014941 0.0101552 -0.0156045 -0.0714142 0.0373879 0.140392 -0.155288 0.0474913 -0.015392 0.010226 -0.0506144 0.00775825 0.0425248 -0.0111819 0.0198418 -0.0465491 0.0473969 -0.0958641 0.069069 -0.0800155 0.135248 -0.167486 0.159519 -0.163318 0.341011 -0.122999 0.899713)) (0.0189561 0.000463645 0.156394 #(0.0136824 -0.010146 -0.00340101 0.00501791 -0.052312 0.0825702 -0.0198587 -0.00941267 0.00742931 -0.00822124 -0.00559287 0.0070671 -0.0295775 0.0163785 -0.000200317 -0.0124918 -0.0388802 0.0517694 -0.0148913 -0.0019372 0.0130002 0.0529274 -0.051331 0.0468511 -0.0493757 0.0488883 -0.0877978 0.0390208 0.120372 -0.130924 0.00454228 0.0284801 -0.0370236 -0.0207961 0.00413483 0.0556726 -0.0461664 0.043992 -0.0572133 0.0680651 -0.129146 0.0933036 -0.0903923 0.0963898 -0.115223 0.173486 -0.16108 0.327376 -0.109485 0.877362)) (0.0157623 0.000457797 0.170422 #(0.00679172 0.0179331 -0.0180012 0.00985177 -0.0710897 0.0804711 -0.0138887 -0.00160079 -0.0130131 -0.0116605 -0.00195402 0.0102408 0.00544203 -0.00882841 -0.00664669 -0.000185585 -0.0333044 0.0571107 -0.0324269 0.00482369 0.00173713 0.0817342 -0.0689869 0.0314419 -0.0416472 0.0452527 -0.104628 0.0733021 0.109757 -0.112525 -0.040671 0.0457447 -0.033124 0.0189072 -0.0182032 0.0382207 -0.0430175 0.0633007 -0.0880582 0.0891837 -0.145313 0.126151 -0.130188 0.133809 -0.156576 0.210072 -0.192572 0.343954 -0.102867 0.867452)) (0.0193939 0.000457706 0.153625 #(-0.00460792 0.0355563 -0.0550596 0.043009 -0.0897849 0.0978742 -0.0187992 0.00582897 -0.0109002 0.000631806 -0.0163601 0.0133513 -0.0165699 0.0221935 -0.0312557 0.04581 -0.0629084 0.0434437 -0.0167021 0.0323193 -0.0250667 0.0627469 -0.0306966 -0.00490861 -0.0368386 0.0217197 -0.0728413 0.0668549 0.145474 -0.169416 0.0122649 0.00448438 0.013949 -0.0353851 0.020688 0.00875267 -0.0340474 0.0569403 -0.0747049 0.0865628 -0.127027 0.0997718 -0.118786 0.172951 -0.208013 0.216935 -0.215728 0.401293 -0.19069 0.923122)) (0.0267348 0.000456167 0.130624 #(0.0221721 0.012707 -0.0342673 0.0498141 -0.125798 0.0945948 -0.009383 -0.0118047 -0.00833615 0.0354772 -0.041698 0.0220065 -0.043747 0.0427328 -0.0334768 0.0279624 -0.0268537 0.00968139 0.00111546 0.0377293 -0.0348329 0.0808209 -0.0457136 0.00457449 -0.0453242 -0.0107467 -0.0188348 0.0300905 0.173791 -0.194862 0.0537233 -0.0419804 0.0496971 -0.0701674 0.0499813 -0.00747099 -0.0222291 0.0273433 -0.0549461 0.0661543 -0.122178 0.0944649 -0.101576 0.17229 -0.189446 0.207714 -0.21558 0.418696 -0.215629 0.931565)) (0.0200745 0.000471228 0.153212 #(0.0163527 0.00660207 -0.0143944 0.046632 -0.126296 0.118434 -0.0369965 -0.00451566 -0.0201182 0.0417401 -0.0308534 -0.00543496 -0.0172945 0.0438493 -0.0319897 -0.0176332 -0.00909391 0.00684448 0.00776292 0.0226499 -0.00129345 0.0597638 -0.057499 0.0439582 -0.0376084 -0.009205 -0.0282326 0.0349981 0.136497 -0.137021 0.0108061 -0.0220325 0.0138336 -0.0341895 0.00554748 0.0125278 -0.0174402 0.0430164 -0.0595981 0.048263 -0.112704 0.102835 -0.101221 0.15651 -0.167554 0.189205 -0.200076 0.383302 -0.1668 0.902884)) (0.0178948 0.000884452 0.222317 #(-0.00627428 0.017076 -0.0217517 0.0596357 -0.115011 0.137658 -0.140797 0.0413646 -0.025147 0.0409271 -0.0298679 0.0230878 -0.00804102 0.0133819 -0.0343905 0.081481 -0.0160831 0.031044 -0.0362416 0.0814956 -0.0892642 -0.0230409 -0.0232022 0.112084 -0.0729296 -0.0349948 0.00901226 -0.0373362 0.140441 -0.0702999 -0.00257567 -0.0348515 -0.00258082 0.0140751 -0.0718087 0.0880132 -0.061838 0.0690842 -0.118292 0.142831 -0.185955 0.190591 -0.155962 0.45873 -0.106312 0.127302 -0.523777 0.419269 -0.501987 1.22411)) (0.014956 0.000914502 0.247278 #(-0.023965 0.0260125 -0.0174047 0.0515138 -0.0830966 0.07056 -0.0839288 -0.00253678 0.0274258 -0.000953763 -0.00370321 0.0051892 0.0273904 -0.020619 -0.0100326 0.0564985 0.00785514 0.0225726 -0.0248022 0.0636671 -0.0849298 -0.0493795 0.0247842 0.0783257 -0.054683 -0.0485245 0.00161631 -0.0165824 0.139226 -0.0743001 -0.00122059 -0.0566757 0.0247024 0.00172735 -0.0647441 0.0783151 -0.0575751 0.0609131 -0.105484 0.127889 -0.170536 0.193175 -0.164876 0.462587 -0.105663 0.112055 -0.495609 0.396188 -0.497893 1.21815)) (0.00871568 0.000567858 0.255252 #(-0.0124666 0.0309579 -0.00109739 0.0135459 -0.057433 0.0477187 -0.0502651 0.00271826 0.0372547 0.0164188 -0.0446111 -0.0127535 -0.0377459 0.05085 -0.0332468 0.0648767 -0.0421368 0.0453716 -0.00560286 0.010505 -0.0502685 0.0272348 -0.0168195 0.0334298 -0.045445 0.0609193 -0.0939262 0.0603289 0.127758 -0.127759 -0.0161537 -0.0241133 0.0220789 0.0501327 -0.0297039 0.0276074 -0.0749799 0.0195223 -0.134458 0.0784379 -0.103965 0.143044 -0.0238226 0.243323 -0.14168 0.124602 -0.245754 0.281028 -0.225522 0.993662)) (0.0086891 0.000454286 0.228653 #(0.000182833 -0.00254678 0.0082363 -0.0153415 -0.0299224 0.0849131 -0.0489407 0.00623273 0.00330074 0.015936 -0.0400408 -0.020401 -0.0247914 0.0710104 -0.015902 0.00164445 -0.0397469 0.0223963 0.0144133 0.00597068 -0.0101367 0.0517253 -0.0400181 0.0204692 -0.0703128 0.0792271 -0.0877888 0.0647522 0.100521 -0.114483 -0.00566729 -0.0255629 0.0314529 0.0182582 -0.0152464 0.0337968 -0.0685177 0.0350596 -0.0735331 0.0771414 -0.107742 0.0609778 -0.0612328 0.122617 -0.132552 0.162598 -0.143835 0.327107 -0.115002 0.855719))) diff --git a/lpc/lpc-exmpl.dat b/lpc/lpc-exmpl.dat new file mode 100644 index 0000000..66332d3 --- /dev/null +++ b/lpc/lpc-exmpl.dat @@ -0,0 +1,162 @@ +(0.0205328 0.000539653 0.162119 #(0.0172437 -0.00206371 0.0199834 0.0140023 -0.107106 0.105376 -0.014147 -0.0456254 -0.035733 0.000526876 0.024559 -0.077979 0.0379572 0.0550832 0.0251978 -0.0158793 0.000201547 0.0183836 0.0120267 -0.0145289 0.0270053 0.0215023 -0.0674045 0.0868633 -0.0759818 0.0123872 -0.100426 0.0670379 0.153223 -0.160887 0.0200027 0.00857184 -0.0319345 0.0372642 -0.039906 0.0370124 -0.0406953 0.0916241 -0.0794324 0.0994091 -0.152256 0.122422 -0.131096 0.143904 -0.182573 0.107067 -0.216319 0.338997 -0.171402 1.04299)) +(0.0746031 0.000883533 0.108826 #(0.043002 -0.0168565 0.0116234 -0.031321 -0.0728684 0.134856 0.0052372 -0.0477521 -0.0767405 0.0307031 0.00286882 -0.0188694 -0.0103552 0.0410824 -0.00991496 0.0129631 -0.0070764 0.0446677 -0.0316206 0.0103328 -0.00314631 0.0721652 -0.028264 0.0429488 -0.0757499 0.0355948 -0.124679 0.0341884 0.147169 -0.115948 0.0350534 -0.022784 0.00255128 0.000132609 0.00266292 0.0235752 -0.0270638 0.00319338 -0.0405898 0.0510949 -0.0525406 0.112875 -0.120262 0.103579 -0.140658 0.030511 -0.195171 0.226418 -0.194436 1.19625)) +(7.90651 0.00254103 0.0179272 #(0.0298438 -0.0150177 0.00856811 0.00178307 -0.156251 0.141521 0.0377321 -0.00862076 0.0358013 -0.0526648 -0.0746482 0.0176761 0.0180553 0.0110547 -0.0149859 -0.00274912 0.00753696 0.0570906 -0.00985159 -0.0460384 -0.0312089 0.0275762 -0.00179828 0.0498972 -0.0462076 0.111785 -0.101277 -0.0429219 0.135046 -0.118618 0.0320909 0.0152628 0.00229011 0.000619642 -0.00148223 0.0698463 -0.0192731 -0.061608 -0.105966 0.00760205 -0.0556964 0.172818 -0.0018539 0.14807 -0.115714 0.0485711 -0.341883 0.118442 -0.644804 1.76356)) +(16.8204 0.00353871 0.0145046 #(0.0242379 0.0163801 -0.0441124 0.0515951 -0.165318 0.0553254 0.118888 -0.00888211 0.0686623 -0.103195 -0.109872 0.0873954 -0.00312068 -0.0157818 0.00793753 -0.0102677 0.0385871 0.0402539 0.0275778 -0.124176 -0.0224998 -0.0083091 0.139262 -0.0326057 -0.0686154 0.152026 -0.0710961 -0.100093 0.0921394 -0.0886168 0.0962788 0.0235546 -0.0835561 0.0289921 -0.0519826 0.0819953 0.0677047 -0.04636 -0.154177 0.0188317 -0.0733893 0.18706 -0.117089 0.276443 -0.188078 0.136406 -0.348012 0.354862 -1.21044 2.05642)) +(15.7527 0.00488585 0.0176113 #(0.0410332 -0.0212341 -0.0186016 0.0139835 -0.10253 0.0317464 0.098534 0.0577219 -0.00603218 -0.119189 -0.0560336 0.0600247 0.00563636 -0.00741701 -0.022568 0.0551003 0.0172174 -0.0145449 0.0377798 -0.0774387 -0.0623132 0.0156745 0.116856 0.0167625 -0.0740776 0.0976961 -0.0589157 -0.0592283 0.0621122 -0.0668073 0.0672344 0.0433492 -0.0724394 -0.0149194 -0.0174723 0.0940844 0.0192709 -0.037947 -0.145742 0.0166333 -0.0382952 0.137928 -0.0235971 0.142885 -0.0641163 -0.0401743 -0.14418 0.182686 -1.00692 1.93978)) +(16.3531 0.0136897 0.0289333 #(-0.024896 0.016421 0.00786502 -0.0118406 0.00603457 0.0343453 0.0250988 -0.00670104 -0.0483285 -0.0402459 0.00284676 0.0223309 0.00649693 -0.0116516 0.00923614 0.0111503 -0.000440774 -0.0275555 0.00682401 -0.0125723 0.00263826 0.0153074 0.0242379 0.0142031 0.0060273 0.0192062 -0.0368178 0.00965019 0.0058204 -0.00736851 0.0414994 0.00440613 -0.0394615 -0.0217087 0.0132956 0.0116567 -0.024931 -0.0592983 -0.0327111 0.00831445 0.0282831 0.0678891 0.00450369 0.00915988 -0.0181229 -0.0469828 -0.0555707 -0.0913728 -0.228273 1.41019)) +(22.7776 0.0128829 0.0237823 #(-0.0244512 0.00852192 0.00355279 0.0100932 -0.00419528 0.0237172 0.0103759 -0.0137028 -0.0251104 -0.0134613 -0.000615256 0.00165147 -0.00407305 -0.00344569 -0.00120993 0.0089017 0.000495352 -0.000238208 0.00294549 0.00112805 0.00425276 0.0266437 0.0165051 -0.0296654 -0.00157895 0.0406957 -0.0203225 0.000875471 0.0187371 -0.00604564 0.0124178 0.00848914 -0.00870932 -0.0345038 -0.0166086 -0.00777551 -0.0127552 -0.0198208 -0.018883 0.00170381 0.0281818 0.0335668 0.00621638 0.000123257 -0.0400046 -0.0251494 -0.0599436 -0.0484318 -0.0953316 1.26394)) +(25.9418 0.014063 0.023283 #(-0.0146976 0.0123669 -0.00238331 -0.00566441 0.000213927 0.0251708 0.0058586 -0.0152624 -0.0096643 0.000380473 -0.00692432 -0.0103325 -0.00570062 -0.00779317 -0.00373097 -0.00244446 0.0232326 0.00687431 -0.0123666 0.0136142 0.000873428 0.01297 0.00157535 -0.0189359 0.0103542 0.0149338 -0.00232667 0.018195 0.0122806 0.000705099 0.0180465 -0.00723085 -0.0333543 -0.0209618 -0.00258482 -0.00346647 -0.0161793 -0.00443528 -0.0107334 -0.00729346 0.0212632 0.017004 -0.0134609 -0.0122188 -0.0266593 -0.0240987 -0.0584669 -0.0204726 -0.0728998 1.23429)) +(26.411 0.0454326 0.0414755 #(-0.0109339 -0.0010968 -0.0010053 0.00617609 0.00306015 0.000136934 0.00372594 -0.00564924 -0.00591968 -0.00522412 -0.00509402 -3.17432e-006 -0.00446083 0.00456961 0.00243643 0.00451923 0.00334826 0.00559344 0.00805774 0.000849614 0.00365901 -0.000214671 -0.00258062 0.00132718 0.00916179 0.00321858 -0.00441098 0.00674969 0.00362521 0.00233835 0.00103611 -0.00365412 -0.0110665 -0.0113001 -0.00483079 -0.00471838 -0.0072024 -0.0112189 -0.00842469 -0.00122134 0.00258161 -0.00404681 -0.0108012 -0.0163903 -0.0156165 -0.0101237 -0.0119205 -0.0127908 -0.0241693 1.1353)) +(26.023 0.0171174 0.0256472 #(-0.00659148 -0.0022813 0.00245043 0.0119932 0.00673879 0.0106215 0.000193227 -0.0118672 -0.00229731 -8.44562e-005 -0.010244 -0.0224172 -0.0074773 0.00139424 0.00442344 -0.00372009 0.00631038 0.00399001 0.00074413 0.00143648 0.0117816 0.0167116 -0.011429 0.00660101 -0.0154429 0.0245051 0.00954568 0.00221017 0.00972422 0.00691179 0.00198784 0.00641321 -0.0164092 -0.0286664 -0.00348171 -0.00646432 -0.0149224 -0.00929398 0.000946284 -0.00786511 0.0105857 0.0116371 -0.0208869 -0.0167969 -0.039235 -0.0416232 -0.0188724 -0.0395318 -0.0672928 1.2529)) +(20.1471 0.0413173 0.0452855 #(0.0028042 0.00238915 0.00320531 0.00204744 -0.00128491 -0.000625469 0.00121502 -0.00053792 -0.00926453 -0.00168529 -0.0176347 -0.00451895 0.000996928 0.00430582 0.00194222 -0.00398466 0.00259957 0.00390882 0.0116503 0.00167209 -0.001884 0.00309071 0.00380416 0.00551039 0.0052082 0.00707811 -0.00293764 0.0110331 0.0118179 0.000155053 0.0029885 -0.0120471 -0.00528422 -0.0186305 -0.00389795 -0.01138 -0.0130287 -0.0114016 -0.00348096 0.00720399 -0.00393767 -0.00782219 -0.00889679 -0.0106665 -0.0241594 -0.0212916 -0.0261109 -0.0222356 -0.042137 1.1898)) +(15.5487 0.0153078 0.0313768 #(0.0038797 -0.00898583 -0.00129375 0.0135476 0.00658722 0.0365788 0.00343157 -0.0308747 -0.0106992 -0.00551437 0.00041832 -0.0139702 -0.0154675 -0.0119801 -0.00961124 0.0151818 0.00235315 -0.00360607 -0.00300882 0.0133151 0.00953059 0.00235415 -1.91313e-005 0.00280704 0.0099642 0.0205634 0.00397632 0.00529698 0.023866 -0.00799138 0.0100504 0.0079582 -0.0250386 -0.029848 -0.0097943 -0.00418491 -0.0133331 -0.0233978 -0.00335522 0.0048438 0.0168547 0.0205229 -0.0161785 -0.0256227 -0.0427417 -0.0322054 -0.0493791 -0.0330071 -0.0981295 1.29245)) +(19.0253 0.00596731 0.0177102 #(-0.0146168 -0.0100904 0.00214927 0.0184939 0.01049 0.0612408 -0.00438104 -0.0265871 -0.026429 0.00668405 0.0269023 -0.0263329 -0.0230587 -0.0429497 0.00384385 0.0294333 -0.00318107 -0.0136982 -0.00792112 0.0090845 0.0366004 -0.0174499 -0.00897093 -0.00784815 -0.00441435 0.0551205 -0.0163865 0.00471411 0.0446577 -0.0132054 0.0401863 0.0217569 -0.0372981 -0.0637524 -0.0140608 0.0379691 -0.012396 -0.0571539 -0.0387487 0.0285809 0.0555209 0.0533837 -0.020053 -0.00430533 -0.102708 -0.0554588 -0.0775484 0.00345876 -0.257812 1.45669)) +(24.3361 0.00252815 0.0101924 #(-0.0257512 -0.0008726 0.0176086 0.0124685 -0.0534896 0.100064 0.0398205 -0.0701561 -0.0307596 0.00460567 0.0732452 -0.00591591 -0.0655563 -0.0244842 0.0128442 0.0333025 -0.0171489 -0.0529101 -0.0145168 -0.00558627 0.0716373 0.0169233 -0.00522713 0.00671804 -0.0615778 0.0634442 -0.0921752 0.00951979 0.120483 -0.077487 0.0914363 0.104565 -0.0653618 -0.089458 -0.0420491 0.0741933 -0.0368942 -0.0224205 -0.159684 0.0706304 0.0604807 0.156387 -0.0368354 0.00141878 -0.11703 -0.0250188 -0.215087 0.140998 -0.528956 1.65826)) +(25.4722 0.00168582 0.00813527 #(-0.0361914 0.0503908 -0.052739 0.0874611 -0.161167 0.205034 -0.030822 -0.0297436 -0.0881124 0.0515133 0.029009 0.0911085 -0.133234 0.00447612 -0.0102752 0.0672411 -0.0743354 0.0278325 -0.088049 0.0254583 0.00378763 0.110739 -0.0335123 0.0437825 -0.111471 0.143021 -0.205556 0.0105061 0.178276 -0.139079 0.108138 0.100769 -0.0514441 -0.061891 -0.0335699 0.078663 -0.0342434 -0.0322647 -0.218112 0.133516 -0.053587 0.327015 -0.200594 0.23237 -0.331232 0.175309 -0.44634 0.403636 -0.874447 1.84189)) +(24.4789 0.00660193 0.0164225 #(-0.0129511 0.000294328 -0.0197443 0.0228973 0.0144379 0.0576108 -0.00978518 -0.00793303 -0.0138883 -0.0222251 0.0319748 -0.0148723 -0.0204648 -0.0414119 -0.0116904 0.010987 -0.0113676 0.0117234 -0.00638076 0.0237907 0.020048 0.00399678 -0.00498899 -0.00973827 -0.00584135 0.0192609 -0.0220209 0.0192987 0.0427776 -0.0141488 0.0260689 0.053246 -0.0359298 -0.0407085 -0.0153808 0.000894089 -0.0255827 -0.0505249 -0.0252819 0.0272812 0.0597201 0.0367404 0.00457889 -0.0014007 -0.0717525 -0.0699291 -0.107446 -0.0187547 -0.27242 1.49509)) +(26.2758 0.0176864 0.0259442 #(0.0033549 -0.00945348 0.0065972 0.011377 0.00754275 0.0138938 0.00853247 0.000314037 -0.00732074 -0.0137922 -0.008441 -0.0188535 -0.0266481 -0.0205979 0.00421144 0.0117094 0.0169971 -0.0179554 -0.00098244 0.035148 0.00857569 -0.0052743 -0.000887931 0.00311146 -0.00552477 0.00948484 -0.000848823 0.0254957 0.0295882 -0.0096005 0.019213 0.00984905 -0.0239854 -0.0251062 -0.0378088 -0.00656597 -0.0252241 -0.0322219 0.024789 0.0259035 0.0228412 0.0272441 -0.00713364 -0.0104557 -0.0465321 -0.0714479 -0.0841954 -0.0538046 -0.134946 1.37684)) +(33.8769 0.00801222 0.0153789 #(-0.00258214 -0.00821759 0.0196898 -0.000392261 0.0140521 0.00440578 -0.0286329 0.000567736 0.0125327 0.00426797 -0.0066993 0.0334311 -0.0281124 -0.0422645 -0.0221943 0.0377913 -0.00618192 -0.0265775 -0.00448782 0.027992 0.0456436 0.00158737 -0.0145791 -0.00474223 -0.0115839 0.0136965 -0.0283794 0.032301 0.000935378 -0.0386639 0.0497046 0.0790239 -0.0338661 -0.0499984 -0.00571791 0.0381896 -0.0512542 -0.0879677 -0.0317509 0.0295627 0.0690141 0.0544617 0.0545729 0.0472211 -0.0781932 -0.090823 -0.112884 -0.113677 -0.42381 1.68183)) +(47.5854 0.03461 0.0269689 #(0.00703504 0.0042176 -0.007448 0.00601103 0.00320568 0.00838487 0.0062723 -0.0120179 0.000336154 0.000458805 -0.00549983 -0.000896449 -0.0239517 -0.0277963 -0.00199031 0.00441657 0.0118858 -0.00555538 0.0186382 0.000599233 0.0253149 0.00947596 -0.0151058 -0.0109278 -0.00257833 0.0161187 -0.000843106 0.0151509 0.00682266 0.00837561 0.0212141 0.019091 -0.0166389 -0.0383569 -0.0276626 -0.0067535 -0.0278646 -0.0358582 -0.00485826 0.02398 0.0407189 0.0544763 0.0300379 -0.00650959 -0.0404744 -0.0715788 -0.100036 -0.13855 -0.218292 1.50233)) +(67.1502 0.0503262 0.0273762 #(0.00163764 0.00156368 0.000896518 -0.00356924 0.0146311 0.0115155 0.000718131 -0.010003 -0.00103783 0.00202199 -0.00199034 -0.0161105 -0.0194743 -0.0104963 -0.00591896 0.0121449 0.00486055 -0.00401805 0.00316407 0.00376875 0.0156482 0.00483055 -0.00410957 -0.00432992 -0.00485066 0.0143753 0.00558336 0.0130507 0.00596937 0.00550279 0.0213288 0.00884339 -0.00423094 -0.0320471 -0.0225288 -0.0132194 -0.0288979 -0.0323811 -0.0196434 0.0287962 0.0448142 0.0421381 0.0389864 -0.00463365 -0.0331114 -0.0584344 -0.112601 -0.149007 -0.247096 1.5331)) +(87.0259 0.146162 0.040982 #(0.0066813 0.0031666 0.00524609 -0.0082533 -0.00391559 0.0131647 0.0226346 0.00201689 -0.0300066 -0.0164448 0.00249676 0.012122 -0.0120514 -0.0290936 -0.00477291 0.0062677 0.00679358 0.00355967 0.0074764 0.00641204 0.00203213 -0.000103927 0.00208319 0.00592471 -0.00531212 -0.00286345 0.0194362 0.0235452 0.0145299 0.000873052 0.0170015 0.00926635 -0.0249864 -0.0345525 -0.026674 -0.0209155 -0.0204941 -0.0180144 -0.000742368 0.0206704 0.0347392 0.0281013 0.0231078 0.00568184 -0.0455544 -0.0687793 -0.0774324 -0.112311 -0.16092 1.413)) +(103.805 0.0839127 0.0284317 #(0.0305305 -0.0232935 -0.0123279 -0.00539001 0.00241112 0.0181144 0.0198195 -0.0119952 -0.00946969 -0.00768942 0.0176179 0.0159392 -0.0270933 -0.0533804 -0.0238979 0.042285 0.0419821 -0.0130642 -0.02037 0.00470052 0.0265474 0.00800111 -0.0193407 -0.00539329 -0.00768145 -0.00352887 0.00818424 0.0306883 0.00191179 -0.011258 0.0201576 0.0424102 0.000582659 -0.0480861 -0.0335357 0.00238416 -0.000149278 -0.0762318 -0.0235003 0.0537691 0.0525345 0.0284459 0.0125174 0.044311 -0.0359816 -0.0879433 -0.0942918 -0.141744 -0.328099 1.59425)) +(124.841 0.162496 0.036078 #(0.0154669 -9.72884e-006 -0.0101342 -0.00793859 0.0059567 0.0228617 0.00768918 -0.0107367 -0.0153092 -0.00690622 0.00137529 0.00756771 -0.0173113 -0.0348903 -0.015329 0.0277865 0.0313134 0.00105124 -0.0143057 -0.00667794 0.011448 0.00558312 -0.00253005 0.000195594 -0.00582771 0.00497205 0.0183721 0.0241788 0.0151434 -0.0120356 0.00834879 0.019273 -0.0189529 -0.0436641 -0.017064 0.0110478 -0.0142619 -0.0454921 -0.0275606 0.0195142 0.0430997 0.0479311 0.0369613 0.00241956 -0.049964 -0.0670036 -0.063226 -0.132439 -0.269048 1.51163)) +(180.716 0.293325 0.040288 #(0.0258335 -0.0119538 -0.0193954 -0.00626257 0.0234294 0.0231874 0.0109882 -0.0140674 -0.0204807 -0.0175573 0.000633931 0.000397377 -0.011624 -0.022438 -0.0107618 0.0178291 0.0325036 0.0112156 -0.0171066 -0.00548084 0.00984786 -0.00170732 -0.00485124 -0.00691943 -0.00247698 0.0118085 0.0178137 0.0244233 0.0229053 0.003698 -0.0103266 -0.00441229 -0.00122563 -0.0243714 -0.0381239 -0.0309188 -0.0100181 -0.00337076 -0.00420997 0.0204227 0.0439681 0.0382338 0.00823855 -0.0138448 -0.0326542 -0.0661078 -0.097244 -0.115524 -0.154429 1.42031)) +(234.118 0.205985 0.029662 #(0.0192157 -0.0031935 -0.00784433 -0.00677489 0.00286156 0.0114244 0.0199407 0.00873447 -0.0210833 -0.0382217 0.00335562 0.018978 -0.0148748 -0.0242473 -0.0051396 0.0205883 0.00181457 -0.0139292 0.0109887 0.0201683 0.00322887 -0.00941825 -0.00196576 0.0112985 -0.0102269 -0.0019795 0.0216591 0.0239712 0.00292886 -0.0126777 0.0229174 0.0228922 -0.0279371 -0.0544655 -0.0105665 0.0201515 -0.0232041 -0.0500812 -0.0122807 0.0286273 0.0377097 0.0333467 0.0362003 0.00682096 -0.0421918 -0.0623608 -0.0697533 -0.142768 -0.286476 1.53382)) +(240.477 0.393671 0.0404604 #(0.0141351 -0.00376777 -0.0127499 0.00507208 0.0136482 0.0136646 0.00963351 -0.00969488 -0.0204225 -0.0195809 -0.00608936 0.0113476 -0.00348937 -0.0263493 -0.00860379 0.0196824 0.0270435 0.00279308 -0.0216122 -0.00311376 0.0167268 0.0026715 -0.00951989 -0.00655211 -0.000521916 0.00286717 0.0195184 0.0369098 0.0212964 -0.00938696 -0.00852238 0.0157752 -0.010538 -0.0511757 -0.0367333 -0.00701777 -0.00496757 -0.0218476 -0.00180121 0.0358277 0.0423497 0.0250602 0.0161893 -0.00886896 -0.0517459 -0.0757613 -0.0763744 -0.0986088 -0.163602 1.41088)) +(208.983 0.298555 0.0377969 #(0.0164121 0.0048719 -0.0123277 -0.0082839 0.00553303 0.0215874 0.00343585 -0.0106931 -0.0143605 -0.0149133 -0.000867135 0.00882374 -0.00160873 -0.0229544 -0.0199348 0.0112933 0.0268215 0.00930974 -0.0129465 0.00684308 0.00823984 -0.00100629 -0.00874536 -0.0125536 0.0018266 0.00222032 0.0179517 0.0318532 0.0216125 -0.00395573 0.00757547 0.000995567 -0.0228842 -0.0368795 -0.018438 -0.00111154 -0.0249076 -0.0299492 0.000929623 0.034715 0.0335621 0.0270658 0.0181262 -0.000710647 -0.0431774 -0.0595626 -0.0734814 -0.128686 -0.215031 1.46608)) +(169.872 0.295057 0.0416766 #(0.0319486 -0.0152698 -0.0178871 -0.00121978 0.0101795 0.0113419 0.00466058 -0.0163847 -0.00962441 -0.00255257 0.0034453 0.00333557 -0.00638092 -0.0185545 -0.0171695 0.00620859 0.027439 0.00889597 -0.00634335 0.00222882 0.00733991 0.00272018 -0.00324214 -0.00743471 -0.0202102 -0.0144455 0.0143375 0.0353734 0.03177 0.0180433 0.00470567 0.00350029 -0.0211588 -0.0400762 -0.0312031 -0.00502416 -0.0137467 -0.0287056 -0.00591527 0.0317417 0.0557392 0.030424 0.00295205 -0.00796262 -0.0331349 -0.0705161 -0.0935693 -0.117755 -0.17632 1.44112)) +(198.736 0.583121 0.0541678 #(0.0239533 -0.0108176 -0.0102808 0.00564068 0.0150349 0.00994732 -0.00604523 -0.00984589 -0.0142772 -0.0121714 -0.00415331 -9.11199e-005 -0.00732939 -0.0188397 -0.00379378 0.0155464 0.0238681 0.0102193 -0.00649659 -0.0166725 -0.00159701 0.0168372 0.00555774 -0.0076568 -0.0152812 0.00621925 0.0304524 0.0302777 0.0179796 -7.1259e-005 -0.0110991 -0.0120554 -0.0207771 -0.0196221 -0.019649 -0.0276093 -0.0267218 -0.00462518 0.0217483 0.0300955 0.0254635 0.0179527 0.00908021 -0.0147737 -0.0434505 -0.0549393 -0.067622 -0.0980195 -0.11752 1.34832)) +(235.893 0.196632 0.0288715 #(0.0304126 -0.0184424 -0.0165599 -0.000407823 0.00801631 0.0195737 0.0118165 -0.00905007 -0.0134561 -0.0135 -0.00394936 0.00567199 0.00352691 -0.0209869 -0.0335421 0.00501761 0.033716 0.0178405 0.00147093 -0.011718 -0.00133608 -0.00135017 0.00902945 0.00737444 -0.0033788 -0.00925621 -0.0209713 0.0180258 0.0548861 0.0175237 -0.0085279 -0.00515863 -0.0139746 -0.031351 -0.0115241 0.00705294 -0.0364894 -0.0527857 -0.0113735 0.0463322 0.0573369 0.0344311 0.019218 0.00187843 -0.0302693 -0.0656353 -0.0907326 -0.155003 -0.284321 1.55441)) +(250.351 0.920652 0.0606419 #(0.0221283 -0.00175026 -0.00689412 0.000872708 0.00825388 0.00110956 -0.00632789 -0.0125022 -0.0104057 -0.00936074 -0.00616766 0.00522704 0.000860839 -0.00548061 -0.0014818 0.00943791 0.00798624 0.000154997 -0.00816161 -0.00716682 0.000403966 0.00149304 0.00596023 0.00691071 0.00706264 0.0106029 0.0144444 0.01869 0.0103569 -0.00377258 -0.00598677 -0.011182 -0.0229358 -0.0277385 -0.0171593 -0.00963866 -0.0130767 -0.00448601 0.01284 0.0232398 0.0183027 0.00684207 0.000345183 -0.017907 -0.0388241 -0.0491714 -0.0555385 -0.0671155 -0.080383 1.27961)) +(265.144 0.37479 0.037597 #(0.0178487 0.0013791 -0.0116388 -0.00507206 0.0138357 0.0176418 0.0040927 -0.0179262 -0.017936 -0.00558455 0.00209339 -0.00600955 -0.011245 -0.00868085 -0.00205561 0.000295947 0.0125599 0.0156985 -0.00318278 -0.0132323 -0.000274777 0.00777626 -0.00183865 0.00266585 0.0125194 0.00603461 -0.00305746 0.0220627 0.0328774 0.00937883 -0.00296813 -0.0139498 -0.023661 -0.0265224 -0.0152562 -0.00981502 -0.0187505 -0.0249964 -0.00613381 0.0245956 0.0383716 0.0292479 -0.00259061 -0.00982094 -0.0297847 -0.0422148 -0.0701577 -0.115859 -0.177598 1.41175)) +(250.53 0.735674 0.0541892 #(0.0238545 -0.00486949 -0.00173591 0.00252099 0.00404998 0.00118642 -0.00418862 -0.0123793 -0.0138166 -0.00838696 -0.00266911 -0.000717441 -0.00433613 -0.00087901 3.08753e-005 0.00695944 0.00812309 0.00161619 -0.00106495 -0.00230766 -0.00318343 -0.00717512 0.00130251 0.0107457 0.00679086 0.00860716 0.0173261 0.0173051 0.0100283 0.00988019 0.00145606 -0.0181773 -0.0255863 -0.0227028 -0.0191551 -0.0156616 -0.0149123 -0.00943028 0.00703709 0.0185155 0.0208948 0.0180594 0.00541843 -0.016114 -0.0379061 -0.0507604 -0.0578965 -0.0768728 -0.0909356 1.29924)) +(197.598 0.485401 0.0495631 #(0.0248193 -0.00306678 -0.00667275 -0.0014236 0.0114491 0.0091926 -0.0023926 -0.0167224 -0.0201609 -0.00339142 -0.00311447 -0.00213343 -0.00661917 -0.00708419 0.00117074 0.0105285 0.010503 0.000885714 -0.00157855 -0.00449273 -0.0024985 -0.000379483 -0.0043849 0.0022342 0.0114984 0.0120889 0.0118227 0.0206663 0.0203387 0.01268 -0.00367646 -0.0148372 -0.0196786 -0.0256279 -0.0246386 -0.0201119 -0.0148319 -0.00916508 -0.00126804 0.0198383 0.0319355 0.0159117 0.00101828 -0.0089909 -0.0292361 -0.0476222 -0.0687146 -0.089934 -0.113823 1.33378)) +(125.124 0.316632 0.0503045 #(0.0130568 -0.00225892 0.00216152 0.0102169 0.00996052 -0.00255912 -0.0097279 -0.0196243 -0.00656228 -0.000937932 -6.12063e-005 -0.000608431 -0.00526008 -0.00223335 0.00268855 0.00317693 0.00183598 0.00660908 0.00583385 -0.00116981 -0.00278075 -0.00730575 -0.0127456 -0.00600758 0.00295042 0.00742113 0.0148913 0.0264792 0.0296855 0.00264396 -0.00385496 -0.00327753 -0.023196 -0.0218689 -0.015055 -0.00831472 -0.0139174 -0.0128882 -0.000967953 0.012294 0.0210776 0.0214656 0.0105105 -0.0134574 -0.0314187 -0.0453388 -0.0664272 -0.107779 -0.148171 1.37876)) +(71.37 0.227496 0.0564585 #(-0.0142429 0.012727 0.0152038 0.013247 0.0124478 0.00703828 -0.0126102 -0.0229412 -0.0168578 -0.00561364 0.00559436 0.00298623 -0.0049227 -0.00038521 -0.00127981 0.00423441 0.000763587 0.00976382 0.0108994 0.00630644 -0.00368733 -0.0148032 -0.023322 -0.0161698 -0.000889858 0.011531 0.0186532 0.0329139 0.0305486 0.00665483 -0.0125951 -0.0144017 -0.0205354 -0.0305956 -0.0183857 -0.000585577 0.0114074 0.00891327 0.00153785 0.00446643 0.00473343 0.015059 0.0101803 -0.0146464 -0.0351526 -0.0511088 -0.0647666 -0.0850186 -0.118079 1.33668)) +(40.4377 0.0852366 0.0459113 #(-0.0335089 0.029908 0.0183897 0.0176984 0.0101193 0.00829117 -0.0170098 -0.0268985 -0.022606 0.00232026 0.0189546 -0.0045041 -0.00575308 -0.0100939 0.00425405 0.00177554 0.00632439 0.0070991 0.0135077 0.0172888 -0.00309632 -0.0159993 -0.0288205 -0.0254887 -0.0108957 0.00733041 0.0214328 0.0301479 0.0306404 0.0070994 -0.0123194 -0.025963 -0.0100594 -0.00332728 -0.00658321 -0.000959254 0.00177248 0.00985076 -0.0049481 -0.00260225 0.00144116 0.00476165 0.00342908 -0.0128849 -0.0221734 -0.0326228 -0.0534822 -0.0924536 -0.143692 1.34984)) +(27.3832 0.070801 0.0508484 #(-0.0140748 0.0135211 0.0169284 0.0134048 0.00664361 -0.000844623 -0.025384 -0.00976012 0.00801802 0.00636203 -0.00289115 -0.0127367 0.000562452 0.00700169 0.00416503 0.00548033 0.00503239 0.00518513 0.00212309 -0.00811506 -0.0249022 -0.0165552 -0.00808011 -0.0032732 -0.00323997 0.0128592 0.0143886 0.0210239 0.0149843 -0.0102482 -0.00523455 -0.0127067 -0.00629629 -0.0118239 -0.00186732 0.00661671 0.000807708 0.0076143 -0.00151332 -0.0141276 0.000588052 0.013716 -0.00222398 -0.0188076 -0.0188453 -0.0187286 -0.0391334 -0.0564238 -0.0793644 1.23514)) +(30.7375 0.040934 0.0364929 #(-0.0243691 0.00812592 0.015261 0.01097 0.0205355 0.0101767 -0.0151796 -0.0251579 0.00184063 0.0088331 0.00252205 0.000583772 -0.00157531 -0.000798763 0.00905121 0.00117476 0.00355867 -0.00185548 0.00468458 -0.00729399 -0.0289016 -0.0190386 0.00930854 -0.00472978 -0.0131431 -0.00543118 0.00841419 0.0272355 0.0256443 -0.00636553 -0.00757628 -0.00558504 -0.000516058 -0.00121443 -0.0138289 0.00110727 0.00668947 0.00434654 -0.00919808 -0.0198922 0.00235468 0.0144602 -0.000975259 -0.0245124 -0.0246625 -0.015985 -0.0371288 -0.0397989 -0.0669062 1.22136)) +(42.0859 0.00626129 0.0121973 #(-0.0734655 0.0296172 0.013634 0.0452539 0.00702914 0.057469 -0.0232954 -0.0727147 -0.0229838 0.0545064 0.022556 -0.0378221 -0.0116609 -0.0131154 0.0381253 0.0259823 -0.0219215 -0.0248628 0.0469329 -0.00591986 0.0161304 -0.0248895 -0.0474258 -0.0134104 -0.011063 0.0414246 -0.0607445 0.0508991 0.0641952 0.00526139 -0.0600509 0.00150282 0.00627574 -0.070137 0.0242186 0.0169948 0.0408282 0.0438345 -0.0204922 -0.0610643 -0.0804496 0.0966152 0.0588874 -0.0136561 -0.0697122 0.00834575 -0.047428 -0.0855743 -0.478215 1.63444)) +(48.3822 0.0133138 0.0165886 #(-0.0991241 0.0620696 0.0256428 0.0325504 0.030601 0.0200286 -0.0346818 -0.0543453 -0.000353481 0.0292389 0.0225596 -0.0231814 -0.0230041 -0.00406665 0.0324386 0.00882869 -0.0235801 0.0419879 0.00354304 -0.0088214 0.00179125 -0.0386059 -0.020162 -0.0161291 -0.0274193 0.0200131 0.00125343 0.0450822 0.0571638 -0.0335057 -0.0273933 -0.0201817 -0.0220575 -0.0085605 -0.000251926 0.0202286 0.0402841 0.0305421 -0.0148375 -0.0251732 -0.04472 0.0420287 0.0255921 -0.0131808 -0.0380019 -0.0228509 -0.0479855 -0.104387 -0.277699 1.47947)) +(52.3586 0.0659523 0.0354912 #(-0.0350294 0.0226496 0.0266707 0.0151374 0.00559978 -0.00178336 -0.0131273 -0.00792491 0.00702189 0.00803718 0.000224972 -0.0104286 -0.0107735 0.000890825 0.000619345 0.00514007 -0.000477151 0.00445113 0.0122391 0.00292333 -0.0091859 -0.0264601 -0.0178257 -0.00867586 0.00144957 0.00389939 -0.00103973 0.00526759 0.0114127 0.00266532 -0.0114983 -0.0129203 -0.0101913 0.00682779 0.023871 0.0120872 0.00875099 0.0033859 -0.00336156 -0.00727741 -0.00798061 0.00279848 -0.00798744 -0.0160221 -0.02748 -0.0249909 -0.0413176 -0.0503363 -0.0665837 1.23408)) +(57.2864 0.0998289 0.0417448 #(-0.0107891 0.0182459 0.0133387 0.00654529 0.00351746 -0.0028236 -0.00652551 -0.00276973 0.00189705 0.00363537 -0.00543967 -0.00428984 -4.74181e-005 0.00728144 -0.000418819 -0.00318095 0.00296512 0.00149376 0.00209253 -0.0105876 -0.0105755 -0.00732988 -0.0124828 -0.00540931 -0.00364074 0.00253872 -0.000591894 0.0020125 0.00672111 -0.0103777 -0.00817489 -0.00341224 0.00892754 0.00393065 0.00183264 0.0170761 0.0103609 0.0093558 -0.00221637 -0.00689539 -0.00883095 -0.00260063 -0.00561736 -0.0152408 -0.0198652 -0.0251051 -0.0359384 -0.043327 -0.0516084 1.19939)) +(63.2886 0.0659521 0.0322813 #(-0.0395131 0.0278336 0.0226114 0.0208169 0.00156559 -0.00586198 -0.00373168 -0.0129797 -0.000442788 0.00591266 0.00384389 -0.00649693 -0.000432298 0.00820201 0.00205019 -0.00693928 -0.00561469 0.00651516 0.00426545 -0.00287469 -0.0195372 -0.0148713 -0.00282639 -0.00135895 0.00476877 0.00385195 -0.00114983 0.00160519 0.0150339 -0.00888809 -0.0157333 -0.00871617 -0.00192295 0.00638566 0.00653376 0.0147419 0.00964909 0.00830972 -0.00471322 -0.00721979 -0.00854983 -0.00297041 0.000582071 -0.00321452 -0.0251575 -0.0448269 -0.0465566 -0.0617166 -0.0814745 1.26877)) +(68.2143 0.127344 0.0432067 #(-0.00650372 0.0166661 0.0110006 0.0046084 -0.000191608 -0.000655383 -0.0075612 -0.00289214 0.00188358 0.00579054 0.000329202 -0.00681358 -0.00225101 -0.000353251 0.0031628 -0.0053415 -0.000525401 0.00656196 0.00272409 0.00256422 -0.0160209 -0.0140322 -0.00207772 -0.00301927 -0.000189949 -0.00236457 0.00311191 0.00706533 -0.000524762 -0.00984277 -0.0108244 -0.00768298 0.000888997 0.00214318 0.0071796 0.0118653 0.0159322 0.00963205 -0.00200409 -0.0107815 -0.00688397 0.000662548 0.00124322 -0.0216095 -0.024252 -0.0275861 -0.0290191 -0.0455658 -0.0594961 1.20854)) +(74.5766 0.00960274 0.0113474 #(-0.0930925 0.0474147 0.0783675 0.00847634 -0.0083235 0.0389507 -0.0156469 -0.0811489 -0.00383005 0.0271399 0.0027488 -0.0036905 -0.0380551 0.0424861 0.036423 -0.0258928 -0.0261861 0.00709007 0.0423739 0.0478494 -0.0457433 -0.0682701 -0.0230027 0.0330979 0.0021217 -0.00664132 -0.0268997 0.0548632 0.100473 -0.0711387 -0.0110561 -0.0158289 -0.0476065 -0.0351137 0.00284219 0.0323319 0.0313311 0.0736398 0.0142766 -0.10177 -0.0582263 0.0770375 0.0914699 0.0357695 -0.12508 -0.0345359 -0.0237482 -0.0585581 -0.687455 1.80702)) +(89.851 0.0668036 0.0272671 #(-0.047951 0.0391961 0.0312392 0.0264315 0.0152606 -0.0229461 -0.0203805 -0.0182092 -0.00178092 0.00435629 -0.00460121 -0.00718773 -0.00219992 0.00637422 0.00988643 0.00875952 0.00355863 0.0092556 -0.00376029 -0.00369781 -0.0084366 -0.0248106 -0.00997018 -0.00992863 -0.00298569 0.00552284 0.0193635 0.0324098 0.00560115 -0.0147652 -0.0174123 -0.0176175 -0.017063 -0.00976483 0.00645685 0.0115746 0.0243375 0.0212918 0.0038104 -0.00756 0.00845826 0.00991446 0.00809276 -0.000765567 -0.0407473 -0.0481121 -0.0785197 -0.118162 -0.175228 1.42139)) +(111.491 0.0612596 0.0234406 #(-0.071768 0.0568083 0.0427606 0.0216603 -0.00175519 0.00236969 -0.0168044 -0.027955 -0.00413897 0.00759891 0.00307185 -0.0137154 -0.021489 0.00188837 0.0194342 0.0167963 0.0109949 -0.00132022 0.0129203 0.00409717 -0.016515 -0.035451 -0.0211164 -0.0147696 -0.00623048 0.017651 0.0231703 0.0352329 0.0277801 -0.0201851 -0.0270755 -0.0333369 -0.0135395 -0.0048966 -0.00213377 0.01776 0.0243864 0.0268 0.00479255 -0.0136091 0.00196506 0.0109521 0.0263541 0.00149658 -0.0351393 -0.0414662 -0.0804536 -0.15343 -0.262886 1.52039)) +(131.563 0.0385887 0.0171263 #(-0.0518673 0.0134846 0.0263128 0.0468026 0.024454 0.0220736 -0.0400596 -0.0676488 -0.0114445 0.0413724 0.0448596 -0.0289181 -0.0607654 0.00419211 0.039212 0.0198165 -0.0106986 -0.00978497 0.0268256 0.0153281 -0.014289 -0.0258232 -0.021492 0.00140582 -0.0194537 -0.0176859 0.00346931 0.0616223 0.0476843 0.000242224 -0.0396149 -0.0480542 -0.0287999 0.00734256 0.00921102 0.0219239 0.0281868 0.0214498 0.0045841 -0.0526773 -0.0290021 0.0477786 0.066508 -0.00482082 -0.060896 0.00723903 0.00689539 -0.17291 -0.656903 1.81153)) +(151.886 0.102626 0.0259939 #(-0.070856 0.0486957 0.0480601 0.0368429 0.0182886 -0.00829156 -0.0513057 -0.0475156 -0.00697538 0.0443591 0.0264049 -0.0186967 -0.046636 -0.00991082 0.0358113 0.0296259 -0.00965236 -0.00183771 0.0116684 0.0166791 -0.0164862 -0.0397139 -0.0181811 -0.0084272 -0.01239 -0.000257272 0.0267701 0.0470878 0.0342028 -0.0154802 -0.0370322 -0.0415501 -0.0235126 1.97047e-005 0.0225005 0.0265028 0.0239742 0.0125777 -0.00895148 -0.0232263 -0.000947537 0.0428729 0.0258008 -0.0298816 -0.037036 -0.00471161 -0.0249833 -0.174155 -0.397768 1.60503)) +(165.11 0.169794 0.0320682 #(-0.0409658 0.0441689 0.0293712 0.0214998 0.0154116 -0.00248447 -0.0422952 -0.0478381 -0.00388453 0.0270632 0.0266513 -0.00557179 -0.022944 -0.0116277 0.0116475 0.0182246 0.00737678 -0.00598205 -0.00128794 0.00345216 -0.00394256 -0.00695017 -0.0256291 -0.0322332 -0.012631 0.0176517 0.0309905 0.0230604 0.0224319 -0.0106256 -0.0268479 -0.0207674 -0.00587152 -0.00570336 -0.00197812 0.0122906 0.0205968 0.031643 0.00252642 -0.0332331 -0.00542228 0.0405915 0.0309338 -0.0143715 -0.0384462 -0.0185082 -0.0347614 -0.166035 -0.349634 1.55773)) +(177.174 0.178624 0.0317519 #(-0.0375195 0.0292643 0.0300942 0.0307154 0.0193178 -0.00509529 -0.0345436 -0.0373165 -0.0172528 0.0236766 0.0201161 -0.0183973 -0.0276741 0.00996924 0.0330329 0.0152227 -0.00951397 -0.0122329 -0.00113485 0.0194899 -0.0119267 -0.0292984 -0.015638 -0.0142287 -0.0148578 -0.000859865 0.0260062 0.0534978 0.0402742 -0.0219816 -0.040437 -0.0341774 -0.0049463 -0.0116811 -0.0123897 0.0190348 0.0504628 0.0449273 -0.00894907 -0.0495895 -0.0187866 0.0407222 0.046073 -0.00801632 -0.0446076 -0.0182126 -0.03077 -0.167466 -0.369669 1.57394)) +(179.99 0.221245 0.03506 #(-0.037004 0.0260371 0.0372679 0.0497295 0.0157299 -0.0244911 -0.0537488 -0.0510671 0.00512908 0.05199 0.0203676 -0.0338469 -0.0238147 0.0127183 0.0230843 0.00442021 -0.0115414 0.00421587 0.0188467 -0.00272606 -0.0256457 -0.0344065 -0.0104499 -0.00267908 -0.00204974 0.00352165 0.02398 0.0343543 0.0255179 -0.0152773 -0.0303301 -0.0266642 -0.0139434 -0.00355751 -0.0084824 0.0107571 0.0423518 0.0526576 -0.00233367 -0.0445417 -0.0249914 0.0319504 0.0506834 -0.0160456 -0.0561795 -0.0084321 -0.00738221 -0.153557 -0.379863 1.55632)) +(166.887 0.252327 0.038884 #(-0.0419053 0.0366535 0.0498127 0.0359369 0.00208074 -0.0250268 -0.0524974 -0.0402762 0.00682585 0.0354895 0.0297739 -0.0147708 -0.0304251 -0.00374599 0.0183841 0.0130221 0.00121661 0.00411938 0.00494517 0.000507366 -0.0263356 -0.0463632 -0.0168647 0.0149596 0.0144969 0.00307392 0.0082568 0.0288554 0.0295293 -0.00737698 -0.0363064 -0.0244228 -0.0110509 -0.00137184 -0.01354 0.00159516 0.0392046 0.0550105 0.0155153 -0.0394186 -0.0271276 0.0202588 0.0342747 -0.0055672 -0.0407041 -0.0119139 -0.0198007 -0.157004 -0.344951 1.53129)) +(164.943 0.182476 0.0332611 #(-0.0614847 0.034366 0.0618075 0.0440773 0.010115 -0.0176925 -0.0502932 -0.0698586 -0.0117179 0.0583499 0.0553452 -0.0141319 -0.052825 -0.00920142 0.0291995 0.0159293 -0.00586749 -0.00306322 0.0226316 0.00427445 -0.0340741 -0.0437776 -0.0123615 0.00698813 0.00470649 0.00949797 0.00789906 0.0335011 0.0219034 -0.00266724 -0.0265675 -0.030155 -0.0143053 -0.0093868 -0.00158663 0.0163901 0.0203923 0.0417646 0.0187303 -0.0392964 -0.037276 0.0437944 0.0678762 -0.016769 -0.0789091 -0.0197703 0.0398731 -0.156601 -0.511722 1.65878)) +(176.99 0.261053 0.0384053 #(-0.06 0.056536 0.045999 0.0280942 0.0117416 -0.0124533 -0.0449422 -0.0463361 -0.00718186 0.0308653 0.0198448 -0.0192072 -0.0242862 0.0065568 0.031481 0.0162032 -0.00801501 -0.00216827 0.0134013 -0.00587761 -0.0383848 -0.0362193 -0.0129257 0.0157857 0.00474063 -0.00184301 0.0202611 0.041013 0.0198278 -0.0191734 -0.029208 -0.0221024 -0.0116136 -0.0121702 -0.00611537 0.0173498 0.0404119 0.0315245 -0.00593292 -0.0237962 -0.000431722 0.0439062 0.0334822 -0.0297822 -0.0607389 -0.0164012 -0.00830834 -0.154607 -0.362478 1.54998)) +(176.048 0.159462 0.0300963 #(-0.0377232 0.0103334 0.036835 0.0488153 0.0179723 -0.00819109 -0.0460628 -0.0619188 -0.00111458 0.0446256 0.032363 -0.00836746 -0.0360712 -0.00850298 0.0216202 0.0175984 -0.000914048 -0.0173185 0.00126597 0.0264074 -0.00629105 -0.043736 -0.017196 0.00494882 -0.000320422 -0.012511 0.00430157 0.0466093 0.0305521 -0.0031329 -0.0376142 -0.024873 0.00750779 -0.012678 -0.0104912 0.00134055 0.0376222 0.0412994 -0.0218273 -0.0452171 -0.0128663 0.072725 0.0680508 -0.0173601 -0.0684261 -0.0212582 0.0188153 -0.175166 -0.561992 1.72452)) +(171.946 0.2352 0.0369847 #(-0.0512015 0.0329072 0.0503361 0.0280294 0.00184622 -0.0107644 -0.0348259 -0.0337681 0.00209173 0.0265416 0.028044 -0.0189349 -0.0371111 -0.000802031 0.0279831 0.0122725 -0.00874739 -0.00112342 0.0180879 0.000223799 -0.0259366 -0.0351892 -0.00449204 0.00197593 -0.0162875 -0.011366 0.0181628 0.0541492 0.0395807 -0.0167336 -0.0418708 -0.0160073 -0.00774302 -0.00128406 -0.00712924 -0.00703709 0.0178146 0.0397532 0.00726889 -0.0174794 -0.00498909 0.0427668 0.0408804 -0.0175914 -0.0525046 -0.0244365 -0.014682 -0.171468 -0.395718 1.59284)) +(185.859 0.163683 0.0296764 #(-0.0468658 0.0116617 0.0555765 0.036102 0.0116869 -0.0136073 -0.0419413 -0.0311445 -0.015847 0.0536179 0.0374088 -0.0318291 -0.0562696 -0.0204646 0.0520056 0.0366832 -0.00267281 -0.0268453 0.00390152 0.0151844 -0.0141306 -0.026449 -0.00214409 -0.00146158 -0.0202671 -0.0306729 0.00986482 0.0542944 0.0595679 0.00293662 -0.0374089 -0.0316308 -0.0279362 -0.00383883 -0.00461755 -0.00381387 0.0302674 0.0462364 0.00234255 -0.0420869 -0.0176493 0.0621579 0.0781717 -0.0259631 -0.0837177 -0.0197173 0.0222038 -0.172749 -0.543442 1.71216)) +(211.324 0.258974 0.0350069 #(-0.0303184 0.0212199 0.0351346 0.0323836 0.0108293 -0.0194528 -0.0440712 -0.0258231 0.0179244 0.0423101 0.00743043 -0.040367 -0.0363898 0.0067014 0.0337238 0.0109171 -0.0145224 -0.00777405 0.0187512 0.010748 -0.0157507 -0.020169 -0.00503133 -0.00636303 -0.0319918 -0.0279937 0.0172805 0.0607111 0.0519986 -0.00764891 -0.0419867 -0.0321224 0.0100713 0.00236086 -0.0196657 -0.0170583 0.0223451 0.0362193 0.000122523 -0.0184589 0.0140273 0.0644042 0.0497302 -0.0380606 -0.0744375 -0.0264989 -0.0209174 -0.164711 -0.384479 1.59087)) +(230.546 0.254813 0.0332454 #(-0.0214216 0.00872379 0.0339929 0.0315809 0.0174031 -0.0232373 -0.0489485 -0.0241287 0.0209643 0.0453702 0.0190406 -0.0440306 -0.0441669 -0.00157853 0.0268724 0.0234296 -0.000401617 -0.0057701 0.000344993 -0.0054568 -0.0178071 0.0024068 0.0155485 0.000746876 -0.0375718 -0.0484998 0.00853225 0.0571187 0.0551759 -0.0142224 -0.0451274 -0.0277836 0.0263546 0.0402985 -0.0197452 -0.0401687 -0.00351748 0.0313089 0.00705256 -0.0369839 -0.00653953 0.0851077 0.0978434 -0.0156217 -0.102129 -0.0527658 0.00792703 -0.158984 -0.494505 1.67382)) +(251.512 0.22152 0.0296775 #(0.00271906 -0.0125085 0.0301646 0.0306547 0.00855251 -0.0179234 -0.0350287 -0.0305762 0.00779454 0.053486 0.0394365 -0.0393962 -0.0650717 -0.0198502 0.0326874 0.039916 -0.0010092 -0.0179188 0.00205602 -0.00398159 -0.00877683 0.0106262 0.0187416 -0.0120917 -0.0564597 -0.0545574 0.0119312 0.0765 0.0649359 -0.0149672 -0.0521681 -0.0268912 0.0228738 0.0277597 -0.00505434 -0.0391086 -0.000955081 0.0337932 -0.00277864 -0.0493297 -0.0119853 0.100552 0.124828 -0.0159932 -0.127861 -0.0612138 0.0295559 -0.144989 -0.555044 1.70991)) +(254.186 0.155867 0.0247629 #(0.011018 -0.035849 0.0315776 0.0392745 0.01848 -0.0184897 -0.0290829 -0.049739 -0.000114797 0.0517803 0.04403 -0.0251357 -0.0530782 -0.0079027 0.0214459 0.0319004 -0.0185972 -0.0210457 -0.00556451 0.0118538 0.000887009 0.0257463 0.0265477 -0.0284303 -0.0724463 -0.0721507 0.0469847 0.0785231 0.069301 -0.026447 -0.064972 -0.032767 0.00653783 0.0563972 0.0303594 -0.0350536 -0.0475477 0.0379776 0.00958391 -0.0490296 -0.0492565 0.0859668 0.161288 -0.000991608 -0.140484 -0.0439296 0.0763862 -0.147115 -0.750695 1.84834)) +(225.37 0.0803291 0.0188794 #(0.0290101 -0.0687017 0.0407707 0.0383633 -0.0152389 0.00254714 0.0114647 -0.0328925 -0.021924 0.00257726 0.0623568 -0.00416147 -0.0660898 -0.0300196 0.0572706 0.0552422 -0.027837 -0.0653128 0.00149151 0.0264922 -0.00315019 0.0193053 0.0486365 0.00427569 -0.0987687 -0.0861261 0.00501995 0.0945006 0.109231 -0.0131216 -0.077788 -0.0512939 -0.00858637 0.0620822 0.041699 -0.0369608 -0.0380424 0.0273551 0.0409665 -0.0644617 -0.0854918 0.0805598 0.178136 0.0300991 -0.186435 -0.0584791 0.205418 -0.075875 -1.13303 2.07226)) +(198.485 0.0417265 0.0144991 #(0.0414603 -0.0623938 0.0061811 0.0288222 -0.0158102 0.0252802 0.00307337 -0.00304176 0.00367747 -0.0489033 0.0357009 0.0204158 -0.0552591 -0.0256414 0.0346049 0.0958179 -0.0284009 -0.100873 -0.00722169 0.0205522 0.0295442 0.033256 0.0421494 0.00768483 -0.110423 -0.0846969 -0.0244979 0.0889337 0.157045 0.00102777 -0.0813333 -0.0900497 -0.0138341 0.0341514 0.0721558 0.00377355 -0.033424 0.010766 0.0245269 -0.0515001 -0.119286 0.0335791 0.213235 0.125951 -0.204453 -0.179761 0.270221 0.202002 -1.65027 2.32378)) +(171.548 0.1509 0.0296587 #(0.0250778 -0.0426171 0.00843798 0.0396997 0.0226322 -0.0146932 -0.0283293 -0.01936 0.0069322 0.0354412 0.0250028 -0.0357834 -0.0414478 -0.0136723 0.0292158 0.020287 -0.00117164 -0.00726955 -0.00706735 0.000159039 -0.00407658 0.0190887 0.0257392 -0.0278326 -0.0682253 -0.0552612 0.0202806 0.0931883 0.0784599 -0.037487 -0.082894 -0.0424946 0.0518775 0.0627942 0.000169138 -0.0458972 -0.0190695 0.0107115 -0.00659794 -0.0314802 0.00511231 0.0991288 0.0788463 -0.0108271 -0.0699992 -0.0146887 -0.00873203 -0.228192 -0.553044 1.75651)) +(138.651 0.0571929 0.02031 #(0.0213914 -0.0306978 0.00848927 0.0130779 0.00721775 0.00427365 0.00961346 -0.0314829 -0.018867 0.036295 0.03503 -0.0305203 -0.0463152 -0.0107846 0.0382213 0.0409777 -0.0373991 -0.0384969 0.0128019 0.00295524 0.0157249 0.0419502 0.0294107 -0.0318793 -0.11091 -0.0681277 0.0179675 0.131618 0.114326 -0.0427296 -0.109902 -0.0736138 0.0191553 0.091943 0.0543933 -0.0340794 -0.0436619 0.00746334 -0.0066161 -0.0679531 -0.0238454 0.0924077 0.161235 0.0122723 -0.139703 -0.0326624 0.115233 -0.166794 -0.931623 1.99133)) +(113.308 0.193753 0.0413518 #(-0.0270571 0.018724 0.0316812 0.0297654 0.00202789 -0.0163134 -0.0290023 -0.0123064 0.0176842 0.0233915 -0.00357253 -0.0336344 -0.0271282 0.00653117 0.0284495 0.0179925 -0.004167 -0.0157728 -0.00964692 0.000267421 0.00122534 0.0146035 0.00149512 -0.0396562 -0.058053 -0.0255875 0.0451789 0.0754793 0.044493 -0.0379303 -0.0597916 -0.015322 0.0420665 0.0354546 -0.0132543 -0.0383832 -0.0285421 0.000937585 0.0195054 0.0265873 0.0502106 0.0593278 0.0136192 -0.0502636 -0.0466451 -0.0180557 -0.0524014 -0.164365 -0.318595 1.53476)) +(103.037 0.0623253 0.0245944 #(-0.00724495 -0.00593484 0.0107629 0.0261896 0.0129414 0.00340164 -0.0251773 -0.0270683 0.00747135 0.0385192 0.018441 -0.0377958 -0.0304305 0.00450653 0.0229534 0.00567204 -0.0264594 -0.0176736 0.000876183 0.0471199 0.0172663 0.0124283 0.00241253 -0.0617734 -0.103682 -0.0406255 0.0578767 0.121063 0.0822661 -0.0454017 -0.102194 -0.042812 0.0321046 0.0833275 0.00602523 -0.0478943 -0.043304 0.000262387 0.00598665 -0.00374976 0.0385322 0.079333 0.0654235 -0.0354309 -0.092082 0.00159915 0.0131218 -0.204327 -0.571633 1.75234)) +(92.5577 0.120027 0.0360108 #(-0.0398489 0.0324612 0.0367935 0.0220619 0.00704562 -0.0272926 -0.0200099 -0.00659618 0.0169783 0.015708 -0.00599385 -0.0153675 -0.0128987 0.0082064 0.0102226 -0.000522355 -0.00199441 -0.00674596 -0.00220103 -0.00689017 -0.00809083 0.00336812 -0.0126411 -0.0439452 -0.04063 0.00361202 0.0505336 0.0555444 0.02238 -0.0310165 -0.038806 -0.00364963 0.0180895 0.00954 -0.00503501 -0.0195219 -0.0205427 0.00318622 0.0185383 0.0345637 0.0376351 0.0372337 0.00566722 -0.0260961 -0.0314731 -0.0229805 -0.0612615 -0.148592 -0.24421 1.45165)) +(66.5989 0.0842179 0.0355606 #(-0.0384904 0.0427509 0.0324356 0.0194716 -0.00585732 -0.0144022 -0.0118444 -0.00525952 0.0111836 0.00537657 -0.00948216 -0.00957872 -0.000929858 0.00996204 0.00650146 0.00151737 -0.00610687 -0.00883977 -0.0111524 -0.00821151 -0.0121669 -0.00254634 -0.0339117 -0.0355781 -0.013952 0.0280202 0.0436449 0.0292268 0.00874941 -0.0239858 -0.0194654 -0.00890681 0.0037191 -0.00475951 -0.00518569 -0.00236431 0.00776458 0.0118334 0.0107269 0.0178917 0.0261446 0.0384696 0.0138593 -0.0230752 -0.043364 -0.0319342 -0.0459236 -0.112816 -0.180369 1.35766)) +(42.7254 0.0264534 0.0248827 #(-0.0413135 0.0213958 0.036281 0.0248983 -0.0151715 -0.0222269 -0.00567853 0.00505671 0.017208 0.024368 -0.0203921 -0.0162792 0.000440382 0.0151094 0.0109901 -0.000613158 -0.00984668 -0.00906093 -0.00789341 0.00260445 0.0124987 -0.0123556 -0.0457957 -0.0562666 -0.0106157 0.0486385 0.0540115 0.0360568 -0.00307563 -0.0466828 -0.0306841 0.00913136 0.0174993 0.00528422 -0.0273256 -0.0166686 0.00261137 0.0230377 0.0120899 -0.00600584 0.0223933 0.0459099 0.00977329 -0.0223494 -0.0479412 -0.0230021 -0.0404154 -0.102133 -0.204478 1.38436)) +(30.9113 0.0516676 0.0408837 #(-0.014936 0.00941983 0.0118751 0.000575508 0.00581291 -0.00413739 -0.012136 0.0103523 0.00720992 0.0100773 -0.000124851 -0.00765056 0.00255218 0.000894253 0.00544408 0.000794387 -0.00215897 -0.00898489 -0.0117924 -0.00653947 -0.0064785 -0.00840759 -0.0105823 -0.0100678 0.000175767 0.0102663 0.00786819 0.0237505 -0.00215373 -0.0266525 -0.00900966 -0.00600343 -0.0028658 -0.00373159 -0.00238924 -0.00278976 -0.00429102 -0.00212087 0.00253061 0.0127614 0.0230914 0.0151189 0.00146143 -0.0117057 -0.00462498 -0.00318648 -0.0265484 -0.0369997 -0.0675645 1.14867)) +(15.3693 0.00836665 0.0233319 #(-0.0341159 0.00806944 0.0216334 0.0174292 -0.0149921 0.016248 -0.0180928 -0.00306738 0.0350942 0.00513288 -0.00769301 0.00579646 -0.0107035 0.0131971 0.00589453 -0.00674269 0.00261838 -0.00786856 -0.00176616 0.00564664 -0.0345646 -0.0240044 -0.0148234 -0.0133658 -0.00412353 0.0369617 0.00196105 0.0368174 0.00564198 -0.0501549 -0.0297051 0.0178704 0.0210161 -0.0155626 -0.00837293 -0.0178571 0.00812323 0.00816448 0.00151141 0.0221456 -0.00390799 0.026406 0.0064334 -0.00797861 -0.0261832 0.013857 -0.0837799 -0.0591936 -0.120175 1.27127)) +(7.76696 0.0131245 0.041107 #(-0.0123117 0.00617644 -0.00098044 0.00751582 -0.00251782 -0.00337365 -0.00106648 -0.00202962 0.024234 0.000865013 -0.000377017 0.00388929 -0.00333191 0.0133695 -0.00022004 -0.00378028 -0.00320862 -0.00759729 0.010062 -0.0256383 -0.0192849 -0.0214377 -0.0114302 -0.00124626 0.00155824 0.0193932 0.00236924 0.0225305 0.00325289 -0.026002 -0.0156565 0.0123504 0.013013 -0.00652565 -0.00493443 -0.0110295 -0.00472477 0.0120849 0.0080524 0.00918786 -0.00908903 0.0273415 -0.00444183 -0.0233399 -0.0047778 -0.00719849 -0.0426428 -0.018549 -0.0650151 1.15688)) +(8.89632 0.0142545 0.0400286 #(-0.00575181 0.0168131 -0.000191827 -0.023498 -0.00423681 0.025755 -0.0183111 -0.00376236 0.0252077 0.008183 -0.0122062 -0.003721 0.00288939 0.0148372 0.00886276 0.00423061 -0.00963574 0.000873132 0.00541097 -0.0280967 -0.00998672 -0.0238806 -0.0217161 -0.00753574 0.000230236 0.0280799 -0.00512027 0.00849866 0.0322065 -0.0343016 -0.00927757 0.00120511 0.0135002 -0.00237087 -0.0093355 -0.00156968 -0.00792312 0.012794 0.00838747 -0.0119611 0.00605868 -0.00193377 0.0117903 0.00816965 -0.0157005 -0.000300004 -0.0367019 -0.0246368 -0.0709357 1.15223)) +(9.78194 0.0170927 0.0418016 #(-0.0124638 0.0024989 -0.00185738 -0.00369259 -0.00329147 0.0015451 0.00184027 0.00970003 0.0141567 0.0120678 0.00775671 -0.00277263 0.00105104 0.000310846 0.00513042 -0.0141369 -0.008812 0.00521768 -0.00206552 -0.00604551 -0.0120649 -0.0176494 -0.0204137 -0.0115251 0.00627893 0.0162767 0.0108663 0.00560173 0.00467505 -0.02242 -0.0112209 0.000456198 0.00829053 2.30481e-005 0.00913467 -0.00846952 0.00517986 0.00864013 -0.00133154 0.00581594 -0.00610526 0.00869507 0.00727336 -0.00365842 -0.0143366 -0.0169279 -0.0336561 -0.0311221 -0.071088 1.16895)) +(11.5445 0.0160741 0.0373143 #(-0.0249007 -0.00275895 -0.000517276 0.00756758 -0.00172192 0.0176724 0.00486407 0.00102775 0.0190812 0.027876 -0.00029893 -0.00443258 -0.00532617 -0.0133783 -0.00615458 -0.00822798 -0.00903328 0.00488343 0.0122464 -0.0119956 -0.0122127 -0.0164293 -0.0183456 -0.00082874 -0.00101657 0.00939199 0.0092591 0.0164931 -0.0114048 -0.0252425 -0.0161846 -0.00699262 0.00668263 0.0180297 0.000800448 0.00638066 0.00681553 0.0168308 0.0103385 -0.00081722 -0.00148622 0.00392006 -0.00755191 -0.0011792 -0.0241647 -0.0123012 -0.0393747 -0.0402423 -0.0754633 1.19146)) +(13.3295 0.0127553 0.0309342 #(-0.0231698 0.0191559 -0.0139377 0.0092944 0.0121271 -0.000232179 -0.0124583 0.0134314 0.0164421 0.024357 -7.36386e-005 -0.0199401 -0.00337023 0.0151218 -0.00455778 -0.0115682 -0.0172743 0.000976708 0.017724 -0.0074562 -0.0285266 -0.0151716 -0.030822 0.00497904 0.00790638 0.0099445 0.0162362 0.0264739 0.0175367 -0.0501894 -0.0343044 -0.00901378 0.014952 0.0105903 -0.0101648 -0.000755211 0.0171476 0.0293293 0.00838466 -0.0102206 0.00315026 0.0306831 -0.00269206 0.00531439 -0.0326658 -0.0252288 -0.0474296 -0.0704353 -0.143764 1.28812)) +(15.3429 0.0120405 0.0280135 #(-0.0309064 0.0271264 0.0147487 0.00498133 0.00106183 0.0147637 -0.040844 -0.0169095 0.0389369 0.0194572 -0.00221378 -0.0170094 -0.00138509 0.0162374 0.00582746 -0.0230331 -0.0117961 -0.00156591 0.0229133 0.027122 -0.0540262 -0.0410968 -0.013133 -0.00158327 -0.0109391 0.0261228 0.0330272 0.0405228 0.0323432 -0.0623613 -0.0561195 -0.00527043 0.00668445 0.0267738 -0.00936441 -0.0283996 0.0234758 0.0255722 0.014511 -0.0129606 0.00174176 0.0403901 0.0353441 -0.000116604 -0.0455759 -0.0479024 -0.0481118 -0.0843258 -0.209947 1.37135)) +(17.6721 0.019402 0.0331344 #(-0.0350609 0.0339703 0.0145886 0.000690795 0.000922172 0.00738286 -0.01517 -0.0088783 0.0201723 0.0122574 -0.0158588 -0.0119165 -0.0019645 0.020945 -0.000870479 -0.0108681 -0.00586048 0.00538485 0.0104022 -0.00321434 -0.0157964 -0.0469299 -0.0215821 -0.00373954 0.00283885 0.0148254 0.0275313 0.0364303 0.0161417 -0.0308895 -0.0417433 -0.00377748 0.0165364 0.00397155 -0.0227846 -0.0260575 0.00618754 0.0551286 0.0147865 -0.0176932 0.00941883 0.0495573 0.031147 -0.00860301 -0.0380403 -0.0458936 -0.0610949 -0.096874 -0.18716 1.3588)) +(20.0442 0.0140521 0.0264774 #(-0.0709867 0.0453836 0.0460421 0.0146813 -0.0179832 0.00433517 -0.0165851 -0.00628279 0.0245804 0.0150767 -0.0114593 -0.0368579 0.00386748 0.0248403 0.00774181 -0.0237615 -0.0110972 0.00908011 0.0143327 0.012267 0.00781146 -0.0256289 -0.0705544 -0.0244927 -0.0213969 0.0392408 0.0426976 0.0769561 0.011974 -0.0784876 -0.0580746 0.0130622 0.0449024 0.0142022 -0.0384532 -0.0269607 0.00680663 0.0207385 0.0149218 -0.0149792 0.0278171 0.0648385 0.0568704 -0.00419316 -0.0892845 -0.0271809 -0.0635848 -0.137194 -0.290703 1.49428)) +(22.8017 0.0273646 0.0346427 #(-0.0720317 0.0448821 0.0348815 0.0233662 -0.000985435 0.00226309 -0.0135519 -0.0209769 0.0167468 0.0101012 -0.0194102 -0.00439263 0.00504041 0.0156837 0.00598467 -0.0264652 -0.0115608 0.0185426 -0.0068165 0.0100013 -0.00188157 -0.018496 -0.0458203 -0.0312296 -0.00116534 0.0335279 0.0330629 0.0395021 0.0183978 -0.0427994 -0.0459782 0.0054253 0.0243994 -0.00582722 -0.0111125 -0.0241409 0.0054475 0.0251814 0.00891366 -0.000905372 0.0228307 0.0523174 0.0382179 -0.00320691 -0.0354807 -0.0419394 -0.0835182 -0.139596 -0.249583 1.45587)) +(26.3474 0.0219953 0.0288932 #(-0.0765435 0.0426832 0.0419785 0.0283921 0.00340572 -0.00535423 -0.0212032 -0.0116924 0.00206213 0.00816488 -0.0127589 0.00934433 0.0163962 0.00930891 -0.00568188 -0.0355663 -0.0130979 0.0042239 0.0221761 0.0294585 -0.00590132 -0.0300225 -0.0529725 -0.04428 -0.00514512 0.0547305 0.0372759 0.0478592 0.0239117 -0.0702372 -0.0687804 0.0195622 0.0191373 0.0223794 0.0135526 -0.038104 -0.00282542 0.00433172 0.00929822 -0.00582157 0.0154465 0.0665377 0.0342229 0.00927136 -0.0205276 -0.0192793 -0.0956723 -0.177253 -0.343554 1.56045)) +(30.1984 0.030065 0.0315528 #(-0.0979213 0.0706986 0.0397353 0.027229 -0.00146723 -0.00438662 -0.0236935 -0.0188674 0.00900385 0.011066 0.00529251 -0.00704211 0.00609007 0.00670222 0.011048 -0.0216173 -0.0263168 0.00421382 0.0169606 0.0205924 -0.018071 -0.0136472 -0.0356033 -0.0382373 0.00240587 0.00751786 0.0412371 0.0584634 0.033329 -0.0663578 -0.0641406 -0.00811986 0.0285871 0.0444783 -0.00260303 -0.0335565 -0.018181 0.00985673 0.00558086 0.0118218 0.023386 0.0433098 0.0400329 0.0116843 -0.0148176 -0.058095 -0.0779079 -0.157939 -0.31358 1.52513)) +(32.1428 0.0318259 0.0314665 #(-0.0775589 0.051683 0.0288251 0.0187194 0.00984706 0.00338128 -0.0202275 -0.00651548 0.0136416 -0.00760369 0.00215332 -0.0233182 0.0134451 0.0247162 -0.00404254 -0.0118734 -0.018538 0.0113604 0.00736548 0.00204067 -0.0115196 -0.0197442 -0.0154772 -0.0363295 -0.0150368 0.0175515 0.0394107 0.053815 0.00585165 -0.0330152 -0.054677 -0.0159929 0.0341672 0.015965 -0.00299163 -0.0189119 -0.0067154 0.0143037 -0.000256563 -0.00532035 0.0260945 0.0429435 0.0476952 0.0109455 -0.0235557 -0.0298008 -0.0826709 -0.176099 -0.325686 1.54201)) +(31.4202 0.0318335 0.0318301 #(-0.0971744 0.0647286 0.0577288 0.0197214 -0.00649152 -0.0216951 -0.0189122 0.00437908 0.0284074 -0.000966733 -0.0171446 -0.0107114 0.00440035 0.0142388 0.00532634 -0.0126468 -0.02169 0.00523199 0.0297256 2.45184e-005 -0.00810739 -0.0215433 -0.0335994 -0.053856 -0.00465438 0.037238 0.0491757 0.0548962 0.014561 -0.073022 -0.0403319 -0.0130117 0.00834094 0.0434427 -0.00417276 -0.0078477 -0.0118494 0.00744896 -0.00313036 -0.0123154 0.0214602 0.059643 0.056315 0.00853147 -0.0377529 -0.0250175 -0.0860953 -0.178818 -0.327932 1.55029)) +(32.4444 0.0301064 0.0304621 #(-0.0807 0.057348 0.0412646 0.0366669 -0.00996071 -0.0130091 -0.0387371 -0.00774177 0.0350818 0.0241313 -0.0154081 -0.0231186 0.00127267 0.0151109 -0.000317825 -0.0114935 -0.0136006 -0.00971232 0.0131985 0.0123626 0.0233086 -0.0265093 -0.0606854 -0.0258504 -0.0165391 0.0251411 0.0470309 0.053574 0.0180307 -0.0502542 -0.0485886 -0.0164236 0.019835 0.0329606 -0.00101179 -0.0302517 -0.0018849 0.0308459 -0.00743693 -0.0159462 0.0094627 0.0539938 0.0554317 0.0208811 -0.0307534 -0.0204858 -0.0821197 -0.181269 -0.37734 1.5857)) +(40.9172 0.0650495 0.0398721 #(-0.0572582 0.0414552 0.0350494 0.0183922 0.00440463 -0.00850967 -0.00613651 -0.0179503 -0.00262387 0.0195232 -0.0131559 -0.00454892 0.00177392 0.0065445 0.00194393 -0.00781929 -0.00616173 -0.00313379 -0.000702812 -0.00178652 -0.014563 -0.0209123 -0.0269462 -0.0162782 0.00491859 0.0228838 0.0258315 0.027738 0.00459301 -0.0176909 -0.0295674 -0.0017052 0.0107792 -0.00448647 -0.00151116 -0.00392171 -0.00643332 0.00597558 0.0150378 0.0149934 0.0222908 0.0451681 0.0323751 0.00353828 -0.0263688 -0.050642 -0.0923144 -0.142247 -0.194605 1.40832)) +(42.9245 0.0380718 0.0297817 #(-0.0619835 0.0538987 0.0254833 0.0191851 0.000713942 -0.00965684 -0.0114323 -0.0178469 0.0175577 0.0131995 -0.0072923 -0.00832834 -0.00811007 0.00959091 0.00557504 -0.00996733 -0.00855112 -0.00974844 0.00913783 0.0117909 -0.0045425 -0.0256592 -0.0292943 -0.0307577 -0.00238131 0.0201101 0.0259082 0.0446931 0.0181626 -0.0452096 -0.0297406 -0.0143662 0.023201 0.0203186 -0.00421108 -0.0211625 -0.00441318 0.019116 0.000645667 -0.00607597 0.0221206 0.0483723 0.0479185 0.015123 -0.02304 -0.0353189 -0.100976 -0.171954 -0.291149 1.51649)) +(35.4435 0.0741689 0.0457449 #(-0.0592469 0.0408393 0.0310192 0.0213087 0.000897261 -0.0097075 -0.0127374 0.00034184 0.00697528 0.00416767 -0.00709337 -0.00543548 -0.00262597 -0.000460251 0.00462508 -0.000103108 -0.00210094 -0.000600998 -0.0064083 -0.00812498 -0.0110879 -0.014929 -0.0210607 -0.0126928 -0.00625044 0.0121755 0.0253735 0.0353037 0.00209597 -0.0177743 -0.0179092 -0.0111032 0.00635534 -0.000694276 -0.00804003 -0.00382186 0.00598897 0.00926817 0.00874331 0.0115986 0.0207321 0.0434171 0.0317387 0.00501884 -0.0295828 -0.0488442 -0.0859817 -0.140721 -0.179372 1.38875)) +(31.5655 0.0508454 0.0401347 #(-0.0590031 0.0481201 0.0415922 0.0145118 -0.00625927 -0.010634 -0.022698 0.00794115 0.0129372 0.011031 -0.00684227 -0.0269145 0.000574552 0.0097944 0.00870401 -0.0154143 -0.00608816 -0.00337432 0.00658044 -0.000562268 -0.0114323 -0.0168882 -0.0267139 -0.0354475 -0.00491647 0.0324642 0.0368173 0.0353376 5.39129e-005 -0.039796 -0.021031 -0.00123375 0.0136188 -0.00348024 -0.00871654 0.00380723 0.0164729 0.0135323 -0.00439517 -0.0080045 0.0109003 0.0528155 0.0444091 0.0206946 -0.0118078 -0.0443984 -0.10415 -0.168437 -0.257971 1.47706)) +(30.9527 0.0382595 0.0351577 #(-0.0677928 0.0651594 0.0430938 0.00356799 -0.0158889 0.000628987 -0.0127898 -0.00558382 0.0158968 -0.00226313 -0.00538957 -0.00778266 0.00155987 0.00443769 0.00375692 -0.0105507 -0.0224075 0.00426307 0.00792974 0.000294564 -0.000787178 -0.0161313 -0.0342735 -0.0403149 -0.00675935 0.0293195 0.0435918 0.0478281 0.00545949 -0.0534773 -0.037442 -0.0111263 0.0321929 0.020819 -0.00755799 -0.00482975 -0.00528935 0.0154923 0.00365394 -0.00549552 0.0121106 0.053678 0.0478409 0.019575 -0.0286409 -0.0335462 -0.0765612 -0.177995 -0.331 1.53233)) +(31.4075 0.0364452 0.0340646 #(-0.0649986 0.0576299 0.0324902 0.00773543 -0.00458665 0.00495247 -0.0191388 0.000145591 0.000613326 0.00395394 0.000636622 -0.0207581 0.00467082 0.0155624 0.0110861 -0.0131649 -0.0232556 -0.00176555 0.00395216 0.00802351 -0.00893858 -0.021152 -0.016588 -0.0283998 -0.0138537 0.0249458 0.0287153 0.0452579 0.0204232 -0.053952 -0.0535749 0.00280977 0.0440965 0.0328232 -0.0150095 -0.0388665 -0.0096805 0.0162576 0.0154429 -0.00290426 0.029801 0.0596534 0.0460045 -0.00865289 -0.0497685 -0.0141297 -0.0805603 -0.160605 -0.335686 1.53526)) +(31.6576 0.0348485 0.0331782 #(-0.0618954 0.0523533 0.0235303 0.0153525 0.00172889 -0.00168407 -0.0110182 -0.0142045 0.0170727 1.99435e-006 0.0017121 -0.0190737 -0.0111033 0.0169703 0.0280168 -0.01063 -0.0322064 0.00426402 -0.00485 0.0146215 -0.00758876 -0.0226077 -0.0252398 -0.0189545 -0.00568113 0.00980641 0.0269183 0.0392206 0.0257317 -0.0475402 -0.0534524 0.00178895 0.0586262 0.0278462 -0.0327184 -0.0414883 -0.0120922 0.029826 0.0131607 0.00598402 0.00931486 0.0642811 0.057244 -0.00679361 -0.0464739 -0.04173 -0.072625 -0.161229 -0.31275 1.52407)) +(34.7383 0.0559897 0.0401467 #(-0.0415582 0.026703 0.0259679 0.0111422 0.00204608 -0.00618647 -0.00950887 0.0120808 0.0102095 -0.00150538 -0.0114168 -0.0193223 -0.00463892 0.0133971 0.0187653 -0.00583736 -0.0127744 -0.0100488 0.0111868 0.0106626 -0.0205418 -0.0312655 -0.0304695 -0.0160161 -0.00137347 0.0194299 0.0309445 0.0366569 0.00705069 -0.0166283 -0.0404884 -0.00764167 0.0169512 0.0132674 -0.00907035 -0.0275286 -0.0054365 0.0307347 0.0158178 0.00474018 0.0264909 0.0460957 0.0291759 -0.00850643 -0.0359522 -0.0586856 -0.0731063 -0.11696 -0.205816 1.40186)) +(36.4119 0.0463771 0.0356887 #(-0.0389951 0.0307876 0.0205879 0.00908905 0.00555359 -0.0121034 -0.00687764 0.00752914 0.0176609 0.00566536 -0.0208413 -0.0229413 0.00156059 0.00543264 0.00694066 0.00249693 -0.00335328 0.000401892 0.0138262 0.00128668 -0.0283111 -0.0256373 -0.0237493 -0.0291584 -0.00703129 0.0152271 0.0393229 0.0452958 0.0231804 -0.0291094 -0.0417306 -0.00489797 0.0160917 0.000583816 -0.0194554 -0.0235409 0.00563181 0.0393978 0.0237208 -0.00447947 0.0171657 0.0551852 0.0282278 -0.022097 -0.0371377 -0.0598215 -0.0687185 -0.118988 -0.195594 1.40087)) +(31.5195 0.0823719 0.0511211 #(-0.0506811 0.032627 0.0260271 0.0133287 0.00707792 -0.00716418 -0.00792555 -0.00164158 4.37169e-005 0.00655899 -0.00403331 -0.00510847 -0.00250636 0.00465444 0.012035 0.0010902 -0.00567664 -0.00723898 -0.00466529 -0.00771452 -0.0268553 -0.0264261 -0.00282889 0.000687852 0.00062155 0.00777579 0.0113666 0.0250398 0.020167 -0.0104087 -0.0261586 -0.0112883 -0.00423545 0.0070317 -0.000811418 -0.0200803 0.00317688 0.0237687 0.0201803 0.0121356 0.0175142 0.033371 0.0253085 -0.00456846 -0.0415392 -0.0596395 -0.0783815 -0.0936876 -0.114877 1.30627)) +(25.4029 0.0602808 0.0487134 #(-0.0551556 0.0394576 0.0270103 0.0236226 0.00186073 -0.00761447 -0.00740441 -0.00712806 0.00591052 -0.00309897 -0.00157216 -0.0120145 -0.00111416 0.0139671 0.00880658 -0.0012513 0.00244409 -0.0133322 -0.00925009 0.00123142 -0.034305 -0.0168858 -0.00914378 -0.0110158 0.000306792 0.0116358 0.0236282 0.0251389 0.00218792 -0.00727665 -0.0207191 -0.00825958 0.00274023 -0.00288428 -0.00666814 -0.0172675 0.00904082 0.0154382 0.0150386 0.0254515 0.0314402 0.0294853 0.0295901 -0.00445611 -0.0469681 -0.0574121 -0.0877862 -0.106583 -0.135491 1.339)) +(22.7468 0.078061 0.0585811 #(-0.04486 0.0298865 0.0293551 0.0157202 0.00558635 -0.00166327 -0.0153884 -0.00699228 0.00676223 0.00247051 -0.00958823 -0.00736895 0.00134663 0.00697311 0.0112086 -0.000206178 -0.00881016 -0.00624388 -0.00932781 -0.0197023 -0.0190608 -0.011131 -0.0120463 0.000508607 0.00205883 0.0130596 0.00678453 0.017637 0.0173591 -0.00929612 -0.0146321 -0.00917131 -0.0076256 0.0010683 -0.00392937 -0.00849227 0.006057 0.0173038 0.0170559 0.0185356 0.0307804 0.0321241 0.0197208 -0.00024348 -0.0379323 -0.0627024 -0.0771216 -0.096205 -0.116027 1.29578)) +(22.8884 0.0716601 0.055954 #(-0.0482403 0.0307585 0.0275873 0.0182651 0.000529184 -0.0022478 -0.00768153 -0.00720601 0.00320312 0.000542559 -0.00613952 -0.00509576 0.000853576 0.00746592 0.00241067 0.00149092 -0.0103518 -0.00548361 0.00260866 -0.00854271 -0.0165325 -0.024049 -0.0159926 -0.0106845 0.00539235 0.0217353 0.013189 0.0138549 0.0113874 -0.00669787 -0.0144154 -0.00952096 -0.00989752 0.000984178 -0.00567269 -0.0075391 0.00597343 0.0157336 0.0231019 0.0212661 0.0260539 0.0267702 0.0234177 -0.00360673 -0.0411499 -0.0479637 -0.0797028 -0.101779 -0.123467 1.30416)) +(25.0679 0.0404904 0.04019 #(-0.0569264 0.0393012 0.0442286 0.0105388 -0.0280166 0.0130403 -0.000293758 0.00097423 0.0019422 -0.0135517 -0.0129558 -0.00137247 0.0176797 0.0111486 -0.00223964 -0.00550807 -0.00602055 -0.00683842 -0.0111893 0.0040559 -0.00320025 -0.0210676 -0.0166252 -0.0273107 -0.00925243 0.0352852 0.0153395 0.028238 0.0100151 -0.0296035 -0.0250562 0.00185137 0.0255143 0.00681541 -0.0269629 -0.0225865 0.00339151 0.0176583 0.0135256 0.0128693 0.0308694 0.0396139 0.0268478 -0.00453411 -0.0321182 -0.0411832 -0.0894552 -0.13549 -0.18868 1.40068)) +(26.172 0.0414675 0.0398048 #(-0.0630411 0.0445934 0.0340673 0.0179641 -0.0126086 -0.000847251 0.000227371 0.00106207 0.0131494 -0.0118745 -0.0160848 -0.00908814 0.00502605 0.0118554 0.0134411 0.006348 -0.0203072 1.60219e-005 -0.0092216 -0.0131313 0.00614179 -0.023434 -0.0225044 -0.0205765 -0.00759216 0.0190882 0.0216325 0.0341826 0.0139076 -0.0241181 -0.0163891 -0.0082327 0.0124357 -0.00390939 -0.0224453 -0.0154005 0.00127452 0.0147405 0.0170827 0.0260113 0.0421892 0.0303767 0.0235349 -0.0138023 -0.0474366 -0.0434775 -0.0753137 -0.111706 -0.172436 1.36862)) +(24.9425 0.0127896 0.0226443 #(-0.0733194 0.0354206 0.0577736 0.0308347 -0.0289842 -0.00604918 -0.014531 -0.0101977 0.0240066 0.0242339 -0.0217081 -0.0255996 0.00547605 0.0210583 0.0282309 -0.0144568 -0.0284572 -0.0338683 0.0165173 0.0371958 0.00744609 0.00585112 -0.0600074 -0.0549116 0.000340121 0.0385451 -0.00124994 0.0513382 0.0555081 -0.0592178 -0.0733577 -0.0170409 0.0586459 0.0553344 -0.0225186 -0.0556362 -0.0233135 0.0506938 -0.00436045 -0.0332437 0.00902178 0.0879455 0.0599741 -0.000640262 -0.0442607 -0.0220114 -0.0610923 -0.165358 -0.458725 1.64915)) +(22.7641 0.0174743 0.027706 #(-0.0584102 0.0459445 0.031618 0.0172284 -0.0102017 -0.00307119 -0.0147159 -0.0128069 0.0192186 0.0263737 -0.0162587 -0.0214138 -0.00164627 0.0164729 0.0190751 -0.00745766 -0.0243652 -0.0185078 -0.0136905 0.043886 0.0129518 -0.0298972 -0.0265289 -0.0403765 -0.00958069 0.0232809 0.0161453 0.044125 0.0361099 -0.0522329 -0.0619475 -0.000899218 0.0508566 0.0368301 -0.0180012 -0.0430501 -0.00970191 0.00226846 0.0163143 0.00440859 0.00654716 0.0745107 0.0559268 -0.0237278 -0.0297872 -0.0202482 -0.0711893 -0.150335 -0.394529 1.58051)) +(19.5777 0.0125371 0.0253057 #(-0.0826795 0.0683275 0.0428367 0.02936 -0.021953 -0.0169267 -0.0348315 -0.00679442 0.025703 0.045118 -0.00592805 -0.0419876 -0.00936561 0.0199536 0.035517 -0.0131276 -0.0408877 -0.0219309 0.0500002 -0.0214081 0.0310525 -0.0126166 -0.046124 -0.0345309 -0.027267 0.0407647 0.00779675 0.0551954 0.0525408 -0.0538993 -0.0680158 -0.0475148 0.0549138 0.0610506 0.00643009 -0.0500036 -0.0294172 0.0234389 0.0124404 -0.0212963 0.0223014 0.0563873 0.0415865 0.0218463 -0.0398211 0.00419091 -0.103894 -0.150699 -0.43171 1.62141)) +(18.2418 0.0253117 0.0372501 #(-0.0607523 0.0562677 0.0384613 0.00424439 -0.0162383 -0.00801906 -0.00889723 -0.00153158 0.0178735 0.00687857 -0.00841403 -0.0109761 -0.000752748 0.0188549 0.0145737 -0.0116472 -0.0244779 -0.0102738 0.00684694 -0.00289441 -0.0144796 -0.0119951 -0.0216497 -0.0176858 0.000835 0.00693356 0.0142641 0.0338318 0.0169442 -0.0304174 -0.03766 -0.00345847 0.0310024 0.00119207 -0.0121249 -0.0113758 -0.00784907 0.0241519 0.0161341 0.0165755 0.0178807 0.0323894 0.0223039 0.0113459 -0.0211709 -0.0354951 -0.0753201 -0.130449 -0.212926 1.39061)) +(18.2633 0.0252861 0.0372093 #(-0.045203 0.0314978 0.0349495 0.00211169 -0.00893727 0.00352343 -0.0123056 -0.00291805 0.0126091 0.00904179 -0.00646769 -0.0145041 -0.00502528 0.0120276 0.0164997 -0.0114284 -0.0165834 -0.00612101 0.0129625 0.0025109 -0.0220033 -0.00506117 -0.0341916 -0.0253116 0.0116913 0.0206707 0.00947406 0.0215501 0.018648 -0.0253815 -0.0210033 -0.00128285 0.00803003 0.00165846 -0.00961188 -0.0112029 -0.00390969 0.018762 0.0176612 0.0141336 0.0162613 0.0423988 0.0169786 0.00664183 -0.0149723 -0.0514017 -0.0758318 -0.125953 -0.214712 1.39864)) +(17.5015 0.0281862 0.0401311 #(-0.0467037 0.0285618 0.0290192 0.00889659 0.00523947 -0.0106185 -0.00584188 0.00343646 0.0078645 0.00378798 -0.0136156 -0.012084 0.00284047 0.0112584 0.00930852 -0.0112164 -0.00383024 -0.00982824 0.0153711 -0.00475254 -0.018373 -0.0203009 -0.0232701 -0.0175478 0.00286289 0.0183034 0.0126237 0.036949 0.00550275 -0.0201175 -0.0171514 0.000764537 0.00264071 -0.0167697 -0.00575089 -0.00377642 -0.00121029 0.0205625 0.019458 0.00863159 0.025104 0.0386815 0.0262647 -0.00411803 -0.0406888 -0.0471502 -0.083648 -0.103756 -0.174039 1.36212)) +(17.2526 0.0295366 0.0413764 #(-0.0459645 0.0347026 0.0174516 0.0140821 0.00442935 -0.00595253 0.000786888 -0.00770935 0.00586936 0.00240675 0.00201615 -0.0114029 -0.00715992 0.0219725 0.00668619 -0.00508303 -0.0104611 -0.00929612 -0.00120529 -0.00989537 -0.0169932 -0.0133932 -0.0188951 -0.000876892 -0.000297876 0.000200907 0.0129674 0.0262989 0.00787067 -0.0241803 -0.0115058 -0.000143185 0.0150916 0.0138443 -0.0335769 -0.0206819 -0.00174932 0.0245576 0.0198266 0.017498 0.020447 0.0325335 0.0246589 0.00835593 -0.033657 -0.0520807 -0.0742558 -0.105502 -0.158577 1.3385)) +(17.7939 0.0194564 0.0330671 #(-0.0393023 0.0249954 0.0281254 0.00881808 -0.0170303 -0.000254086 -0.0238422 0.0104953 0.0267727 0.0218212 -0.00832039 -0.0378733 -0.00966003 0.0208957 0.0258569 0.00523595 -0.0125616 -0.0198685 -0.00261361 0.0267587 -0.00756953 -0.0295961 -0.0220904 -0.0216108 -0.022352 0.010996 0.018242 0.0477541 0.0378138 -0.0342758 -0.0460006 -0.0110206 0.0200271 0.0216202 -0.0010694 -0.0481358 -0.00989713 0.0183853 0.0178495 0.0123016 0.00932306 0.0462944 0.0355045 0.00738312 -0.0433972 -0.0431022 -0.0752448 -0.111662 -0.22808 1.41783)) +(16.2645 0.0198753 0.0349571 #(-0.0444276 0.0359794 0.0176339 0.0166024 -0.00509977 -0.00228653 -0.0161215 0.0145134 0.0174299 0.000749843 -0.00504707 -0.026946 -0.00241593 0.0172678 0.024325 -0.00596551 -0.0248575 -0.0135324 0.0111395 0.00225044 -0.0129778 -0.0134113 -0.0270257 -0.0234719 -0.000202711 0.0218519 0.00693315 0.0315688 0.0147574 -0.0374582 -0.0197909 -0.0087806 0.0357156 0.00379843 -0.0129535 -0.0288524 -0.0066429 0.02112 0.00394448 0.0222445 0.0191879 0.0458149 0.0290641 0.00188522 -0.0291704 -0.0394177 -0.0755161 -0.123621 -0.231673 1.41693)) +(13.9843 0.0203448 0.0381422 #(-0.0406508 0.0247845 0.0280528 0.016247 -0.00667394 0.00575473 -0.00883099 -0.00538796 0.0124414 0.00246849 -0.0144231 -0.0122821 5.65498e-006 0.0240839 0.00861459 -0.00217033 -0.0235125 -0.0168742 0.0055966 -0.00328378 -0.00988276 -0.0124962 -0.0202922 -0.0046567 0.00286656 0.0025336 0.000137633 0.0296567 0.0200221 -0.0189908 -0.0237597 -0.000666055 0.0173422 0.0148898 -0.028545 -0.0280338 -0.00862389 0.0107104 0.0292579 0.0223673 0.0356336 0.027171 0.0365469 -0.00876548 -0.0413912 -0.0440555 -0.0862704 -0.0992445 -0.175119 1.36053)) +(13.7519 0.0318418 0.0481192 #(-0.0439203 0.0286811 0.019099 0.0131209 0.00116507 0.00239283 -0.00349781 -0.00764389 0.00731754 0.00111961 -0.0119648 -0.0166307 0.0112826 0.0209392 0.00437699 0.00510248 -0.00768695 -0.0223086 -0.0103192 -0.00707175 -0.0131623 -0.0187769 0.00250121 -0.00532104 -0.0114664 0.00451569 0.0158921 0.0267952 0.00829616 -0.0112708 -0.0156018 -0.00644018 0.00364066 -0.00682353 -0.0102232 -0.0152849 -0.00104906 0.0131723 0.0312335 0.0306407 0.0224566 0.0393104 0.00734389 -0.0167909 -0.0521184 -0.0325935 -0.0547162 -0.0785076 -0.107318 1.25643)) +(14.1001 0.036371 0.0507887 #(-0.0416909 0.0311513 0.0216856 0.010757 0.0023053 -0.00539498 -0.0122303 -0.00307753 0.0143497 -0.0013006 -0.00140553 -0.0114054 0.00277976 0.0180154 0.00290372 -0.000693336 -0.0231679 -0.00686742 -0.00978564 -0.00577415 -0.00821437 -0.0128852 -0.00872088 -0.0119665 0.00729519 0.00605096 0.00574081 0.0229577 0.00811213 -0.0167 -0.00908976 0.00335362 -0.00364028 -0.00150706 -0.00937789 -0.0185555 -0.000902989 0.0273121 0.0204276 0.0180267 0.0271863 0.0347298 0.0131781 -0.0189297 -0.042958 -0.0488664 -0.0552135 -0.0687342 -0.0978135 1.24792)) +(14.2751 0.0340747 0.048857 #(-0.0375261 0.024581 0.0173357 0.0105803 0.00152478 5.81223e-005 -0.0049663 0.000233414 -0.0059578 0.0172982 -0.0123975 -0.0121001 0.00817213 0.00614464 0.0063125 0.00277281 -0.0072908 -0.00298882 -0.00532286 -0.0151193 -0.0130224 -0.0190079 -0.00477871 -0.00682809 -0.00484661 0.0136435 0.0106479 0.0201277 0.016766 -0.0148155 -0.0230016 0.0010569 0.00368719 -0.00836747 -0.0108471 -0.0115598 -0.000523546 0.020508 0.0238148 0.0105346 0.0278912 0.030346 0.015747 -0.00584426 -0.0429999 -0.0557868 -0.0671162 -0.0745447 -0.115248 1.28424)) +(15.2833 0.022009 0.0379483 #(-0.0444502 0.0319226 0.0206898 0.00408402 0.0038444 0.00518289 -0.0102187 0.00644884 0.0154201 0.00243678 -0.0155881 -0.0226183 -0.00535144 0.0143481 0.0263679 -0.00816404 -0.00439294 -0.00726711 0.00245852 -0.0075432 -0.0210695 -0.022927 -0.0121272 -0.00257655 -0.0142863 0.0116892 0.0195945 0.0314798 0.0171628 -0.026222 -0.0236029 -0.00279915 0.0139127 -0.00411994 -0.0220793 -0.0223499 0.0130053 0.0163297 0.014851 0.0168635 0.030113 0.0393203 0.0185481 -0.0032677 -0.0508295 -0.049786 -0.0681459 -0.100596 -0.141854 1.3324)) +(16.2369 0.0167683 0.0321361 #(-0.0461453 0.0336128 0.0171639 0.00638196 0.00304988 0.00700732 -0.0124934 -0.0014443 0.0229149 0.00812651 -0.0156464 -0.027978 0.00155632 0.0148617 0.0236262 -0.0053183 -0.0306435 0.0156539 0.00576177 -0.00936416 -0.019092 -0.0214782 -0.0106117 -0.0139679 -0.00487678 0.0153928 -0.000839796 0.0328364 0.0370444 -0.0267438 -0.0258321 -0.0084227 0.00140206 0.0170352 -0.0249207 -0.0137748 0.00622318 0.00877071 0.0176743 0.0140944 0.0160371 0.0299227 0.0280204 0.00486572 -0.0471303 -0.0549004 -0.0792787 -0.0862093 -0.156202 1.34944)) +(15.8715 0.00862119 0.0233064 #(-0.0416665 0.0196847 0.0351245 0.00540738 0.000268711 0.000455022 -0.00585776 -0.00906765 0.019069 0.0231938 -0.0242396 -0.0320143 0.00375507 0.0115636 0.0160781 -0.00497688 0.0104297 -0.0136434 0.0112971 0.000516813 -0.0335269 -0.00981996 -0.0165414 -0.0128344 -0.00386654 0.0142686 -0.0124378 0.0254652 0.0577827 -0.0404511 -0.0399016 0.00257038 0.0284287 0.00205934 -0.00698707 -0.0282862 -0.0129552 0.0375839 -0.00052652 -0.00139833 0.010455 0.0601005 0.027725 0.00917528 -0.0452916 -0.0495308 -0.114218 -0.0824053 -0.228428 1.43507)) +(14.8358 0.0137405 0.030433 #(-0.035238 0.0325776 0.00811017 0.00564153 0.00956963 0.00160376 -0.00735718 -0.0106363 0.00927161 0.0156551 -0.014077 -0.0256614 0.00892661 0.0141185 0.0219964 0.00497017 -0.0213388 -0.00393183 0.00307147 -0.00527207 -0.00932004 -0.0149748 -0.0293915 -0.0137217 0.0110029 0.00820573 -0.00731358 0.0228706 0.0342061 -0.0270083 -0.0231551 -0.00456665 0.0112681 -0.00073322 -0.00608638 -0.0299522 0.00616215 0.0218085 0.0147894 0.01267 0.0171617 0.0382049 0.0155666 0.00222878 -0.0301421 -0.0626113 -0.101723 -0.0618076 -0.14028 1.33014)) +(12.9037 0.0170322 0.0363311 #(-0.0361427 0.0205666 0.0172627 0.017552 -0.00678439 0.00380304 -0.00573859 0.00913126 0.0155822 -0.00543546 -0.00759378 -0.0190302 -0.00357661 0.0192382 0.00804061 0.000652122 0.000361389 -0.0179953 -0.00446666 0.00560995 -0.0184849 -0.0113776 -0.0232038 -0.00865374 -0.000620224 0.00406897 0.00305195 0.0334702 0.0202773 -0.0270967 -0.0247178 0.00910172 -0.000104248 0.000138012 -0.0102208 -0.0169238 0.00120545 0.0203969 0.0133169 0.0181668 0.0202681 0.0266863 0.021128 -0.0131285 -0.0365628 -0.0378504 -0.0756192 -0.0782206 -0.137483 1.31255)) +(10.7606 0.0176641 0.0405161 #(-0.0483414 0.0247989 0.0315676 0.00585319 -0.00234617 0.009571 0.00527321 -0.010687 0.0163059 0.00885164 -0.0125577 -0.0134762 -0.00967633 0.0164184 0.00952228 -0.00630756 -0.0123339 0.00271924 -0.00671046 -0.0020015 -0.00886391 -0.0281787 -0.0135787 -0.0134191 0.00144693 0.00931767 0.000242524 0.0183011 0.0329657 -0.0164957 -0.0380229 0.00540505 0.0215291 -0.00189809 -0.0201857 -0.0100815 0.00201447 0.0118938 0.00726428 0.0202927 0.0107608 0.0392477 0.0177106 -0.00825438 -0.0278289 -0.0360925 -0.0803767 -0.0690058 -0.118693 1.27992)) +(9.692 0.0163592 0.0410842 #(-0.0435487 0.0238735 0.0221766 0.0130095 -0.0102838 0.0102648 -0.00263138 0.00405493 0.0139175 0.00368894 -0.0144828 -0.0187693 0.000191167 0.0191079 0.0188621 -0.00391941 -0.0163057 -0.0108496 0.0112138 -0.0054916 -0.0242603 -0.0107545 -0.03524 -0.00986785 0.00436468 0.0159444 0.00288566 0.0280451 0.0177601 -0.0226378 -0.0232638 -0.00458616 0.0132367 -0.00669003 -0.00879428 -0.0174804 -0.00444567 0.0183938 0.0174463 0.0192643 0.0206223 0.0364433 0.00547454 0.00493223 -0.0256411 -0.0374557 -0.0770796 -0.0699102 -0.107736 1.2591)) +(10.6083 0.0116637 0.0331585 #(-0.0339536 0.0239064 0.0193139 -0.00206308 -0.00420809 0.0162964 -0.00446401 -0.00723342 0.032238 0.00872946 -0.0187994 -0.0242643 -0.0134408 0.0259891 0.0161434 0.00132369 -0.0197008 -0.00519451 0.00655926 -0.00738285 -0.0172127 -0.0237242 -0.0212511 -0.0206254 0.0103538 0.0122223 -0.00456432 0.0447003 0.0352811 -0.0406705 -0.0316736 0.00797188 0.00656864 -0.0115901 -0.0027629 -0.0128048 -0.00570429 0.0118761 0.0188073 0.0222462 0.0124456 0.0410702 0.00791332 -0.00379496 -0.0170523 -0.0476136 -0.0781826 -0.0542285 -0.143112 1.28919)) +(13.6333 0.00775797 0.0238547 #(-0.0364152 0.0291058 0.0227928 0.00502204 -0.0253292 0.048831 -0.0291211 -0.014896 0.0320535 0.00774532 0.000503408 -0.0316866 -0.00546139 0.0360913 0.00840064 -0.0208066 -0.0145649 0.000116066 0.00307052 -0.0122648 -0.0118387 -0.0277435 -0.0112472 -0.0110968 0.0148855 -0.00123177 -0.021587 0.0284518 0.0631961 -0.0358807 -0.0443364 0.00976814 0.00940558 0.00815862 -0.0182798 -0.0167586 0.0109045 0.0136983 0.0074112 0.00384714 0.0165089 0.0481128 0.0182451 0.00169633 -0.0279793 -0.0379538 -0.093019 -0.0760834 -0.15798 1.33196)) +(14.9529 0.0090799 0.0246421 #(-0.0173912 0.0117589 0.0215592 -0.000100125 -0.00958332 0.0178238 -0.0220747 0.00944662 0.0241577 0.0100921 -0.0118245 -0.0308733 -0.0111011 0.0260419 0.0364623 -0.0174218 -0.0250652 -0.02109 0.0203074 0.00684312 -0.0399599 -0.0207732 -0.0171705 -0.0007063 0.00839398 0.0148383 -0.0116208 0.0395184 0.0320917 -0.0477367 -0.0288544 -0.013006 0.0343035 0.0151606 -0.0250012 -0.0238014 0.010687 0.0287551 0.00443121 -0.00885899 0.0187292 0.0305535 0.0398672 0.0256628 -0.0622547 -0.0391768 -0.0803045 -0.063373 -0.174028 1.33167)) +(15.4713 0.0103036 0.0258065 #(-0.0317778 0.0220012 0.023046 0.0107401 -0.00700271 0.0157947 -0.0168062 -0.0275037 0.0367403 0.0183112 -0.0155777 -0.0184876 0.00537082 0.00657688 0.00920857 -0.00738122 -0.0258576 -0.00495231 0.0158989 0.0138713 -0.0316929 -0.0372503 -0.00456503 0.00398878 -8.80907e-005 0.00931697 -0.0254795 0.0441872 0.0447222 -0.0413425 -0.0365677 -0.00544457 0.0244433 0.0112955 -0.0182531 -0.0124006 0.00266321 0.0168735 0.014526 -0.0109792 0.0141278 0.0440501 0.000770168 0.0424379 -0.0278247 -0.0526684 -0.0777227 -0.0873046 -0.175866 1.34552)) +(14.1187 0.00916422 0.0254771 #(-0.045858 0.0400202 0.0205128 0.00743514 -0.00145771 0.00837235 -0.0248272 -0.00172827 0.0233621 0.0100241 -0.0135858 -0.0126684 -0.00336266 0.0149539 0.0171219 -0.016675 -0.0227132 -0.000102549 0.020379 0.00582718 -0.016864 -0.0320013 -0.0340711 0.00940389 -0.00660789 0.0171697 -0.029894 0.0563412 0.0606243 -0.07549 -0.0483998 -0.000330146 0.0359239 0.0257492 -0.00142432 -0.0289091 -0.0018749 0.012466 0.00260386 -0.0152575 0.00862908 0.053457 0.03697 0.0345913 -0.0435553 -0.039316 -0.0996627 -0.0778146 -0.205904 1.3743)) +(12.5142 0.0109789 0.0296196 #(-0.0372881 0.0196089 0.0233113 0.000903561 -0.0047855 0.0192033 -0.00402685 -0.00304796 0.0072131 0.000961789 -0.00506267 -0.0118756 0.00342084 0.015397 0.00417627 0.00558174 -0.014547 -0.00178372 -0.00917506 0.0153024 -0.021183 -0.0321192 -0.0190146 -0.0116695 0.0083767 0.00252157 0.0031781 0.03148 0.0255226 -0.0305256 -0.0148153 0.00160903 0.010152 0.00196973 -0.0133266 -0.0138634 -0.0111339 0.0246016 0.00657759 0.0046415 0.0102237 0.0405588 0.0267124 -0.0205946 -0.0262742 -0.0302408 -0.0733365 -0.0751875 -0.141942 1.30887)) +(13.1881 0.0149057 0.033619 #(-0.0392646 0.0235916 0.0113109 0.0165674 0.000356377 0.0096727 -0.00454504 -0.0118521 0.0189847 5.30982e-006 -0.00576891 -0.00829558 -0.00267612 0.0116296 0.0180062 -0.00463104 -0.015852 -0.0119515 0.00220159 0.00224108 -0.027798 -0.0126524 -0.0149994 -0.00157439 -0.00384594 0.00016854 0.00338744 0.0262442 0.0138858 -0.0262235 -0.0060537 -0.000456936 0.0188089 0.00153812 -0.0108762 -0.0196819 -0.00571758 0.0244648 0.0111209 0.00558558 0.0127132 0.0348169 0.015571 -0.0175171 -0.0217261 -0.045869 -0.0708379 -0.0505154 -0.114525 1.26721)) +(12.7999 0.015072 0.0343149 #(-0.0333835 0.0122214 0.0259325 -0.000845576 -0.00411607 0.0249855 -0.00362802 -0.00123161 0.00374519 0.00881159 -0.00779002 -0.0221836 -0.00150112 0.0259934 0.00794084 -0.00206094 -0.0134564 -0.00876726 -0.00201227 -0.0224425 0.00930002 -0.0259136 -0.0165928 -0.00342897 -0.00262414 0.00704048 -0.00242533 0.0235934 0.0114056 -0.0151016 -0.0109616 0.00159531 0.0111167 -0.000793585 -0.00855475 -0.0193289 0.00818316 0.0173823 0.00418687 0.0104691 0.0231481 0.0104235 0.0158543 -0.00351913 -0.0424822 -0.0357488 -0.0522538 -0.0381995 -0.0936292 1.22602)) +(12.2473 0.0193377 0.0397359 #(-0.0208312 0.0113622 0.0107963 0.0102407 -0.0113957 0.00688707 0.00914879 -0.00983215 0.00520417 0.00334524 -0.0068846 -0.004754 -0.00291994 0.0137996 0.0146112 -0.00155131 -0.0176285 0.00365784 -0.0104858 -0.0192718 -0.000923549 -0.0131308 -0.0111267 -0.00719019 0.000579761 0.0111471 -0.00676168 0.0234209 0.0115352 -0.0168934 0.0025673 -0.00926516 0.00685466 -0.00665536 -0.00981694 0.000390394 0.00485606 0.00488992 0.00723448 0.0167406 0.00949511 0.00968203 0.0148381 -0.0192989 -0.0238238 -0.0274632 -0.0505583 -0.0318813 -0.0690697 1.18902)) +(12.5963 0.016594 0.0362957 #(-0.022897 0.0164408 0.00922307 0.00712825 0.00029965 0.0126678 -0.00781488 -0.00903336 0.00276701 0.00841422 -0.00438664 -0.00758085 0.00516114 0.00530365 0.00871018 -0.00177273 -0.00100205 -0.00497492 -0.00829477 -0.00643409 -0.0175788 -0.016037 -0.0116676 -0.00203718 -0.000523905 0.0101769 -0.00147634 0.0081845 0.0146411 -0.0119274 -0.00436797 -0.000224399 -0.00513704 -0.00984378 0.0115129 -0.0102507 0.00516442 0.00549147 0.00572397 0.0118901 0.0113157 0.0218897 0.00945389 -0.0113134 -0.0298536 -0.0302538 -0.053088 -0.0372686 -0.0642578 1.19366)) +(13.5525 0.01008 0.0272723 #(-0.0123657 0.0053427 0.019458 -0.0176663 -0.0176549 0.0404966 -0.00390325 -0.00579765 0.00887555 0.00317001 0.00172718 -0.00829583 0.010417 0.0153962 -0.00556122 -0.00680748 -0.00745445 -0.00852993 -0.00462103 -0.0159715 -0.000628177 -0.0183191 -0.0147015 -0.00193298 -0.00415885 0.0236506 -0.0098982 0.015603 0.0132994 -0.0134173 -0.00543716 0.00140853 -0.000410987 -0.0155814 -0.00399504 -0.000352762 -0.00284362 0.0100352 0.0139833 0.0156556 0.00280102 0.00782334 -5.04827e-005 -0.0182239 -0.0189623 -0.0239327 -0.0540221 -0.0168124 -0.0578101 1.18215)) +(12.068 0.00596845 0.0222389 #(-0.00770466 -0.00247063 0.020446 -0.00341433 -0.0175267 0.0299728 -0.00334073 -0.021708 0.0222189 0.00349176 -0.00219307 0.000507939 -0.000906229 0.0251413 -0.00347692 -0.0193672 -0.008356 0.0107288 -0.00522202 -0.0373399 0.0110019 0.00334983 -0.0260176 -0.00508717 0.0076833 0.0123874 -0.0218113 0.0217126 0.0137616 -0.0343426 0.00107652 -0.0108971 0.00723602 -0.0140256 0.00945629 0.008111 -0.013161 0.0263409 0.00322294 0.0169951 0.0125402 0.00634017 -0.0281478 0.00833678 -0.0210252 -0.0480639 -0.0657505 0.00962592 -0.0670183 1.193)) +(8.95623 0.00286173 0.0178752 #(-0.0299596 -0.00271054 0.0316405 0.00830122 -0.0430843 0.052154 0.00778072 -0.0218403 0.015222 0.00900955 0.000450335 -0.0294424 0.0109118 0.0305165 0.0185617 -0.0211344 -0.00754338 0.000348268 -0.015125 0.000259483 -0.00953378 0.00744751 -0.0392438 -0.0133562 -0.0140394 0.0473366 -0.0574915 0.0274957 0.0739216 -0.0633229 -0.00625577 -0.00332914 0.0318236 -0.039495 -0.0259531 0.0239393 -0.0180297 0.0156937 0.0245471 0.0241233 0.00445331 0.0143366 -0.0112595 0.0136985 -0.0568217 -0.0400073 -0.106216 0.040655 -0.0915969 1.22924)) +(6.49921 0.00445611 0.0261847 #(-0.0170517 -0.0101715 0.0184278 0.00588615 -0.0192503 0.0377397 -0.00414877 -0.0237132 0.0261238 0.0049736 -0.00638682 0.00527185 -0.00923617 0.0111306 0.0255296 -0.0039067 -0.0151077 0.00377979 7.06266e-005 -0.0208127 0.00467839 -0.022734 -0.0168833 -0.00336075 -0.01055 0.033853 -0.0379811 0.010155 0.0492233 -0.0412482 -0.00933746 -0.0204949 0.0208357 0.00125835 -0.0115378 -0.000968487 0.00445165 0.00835097 0.00622662 0.0115168 0.000545416 0.00342692 -0.00927968 0.0260598 -0.0528268 -0.0332704 -0.0524391 0.0325668 -0.0789734 1.17526)) +(5.25729 0.00395311 0.0274213 #(-0.0240403 0.0205123 0.0153895 -0.0123595 -0.0220413 0.0554869 -0.00704868 -0.0433425 0.0501927 -0.00331648 -0.0181042 -0.0055328 -0.0079657 0.0218988 0.0184512 0.000216515 -0.0131423 -0.00679136 0.0172376 -0.0200239 0.00385909 -0.0187232 -0.0339574 -0.0205053 0.00639417 0.0217717 -0.022982 0.0227078 0.0735146 -0.0648862 -0.0373938 0.00153798 0.00527095 0.0142592 -0.0107342 -0.0298141 0.00548001 0.0163492 -0.00212356 0.00278833 0.0101466 0.0397622 0.0149 0.023642 -0.01529 -0.0428728 -0.0909119 0.00412615 -0.130688 1.23334)) +(4.64889 0.00405787 0.0295443 #(-0.0083154 0.00615811 0.0229795 -0.0118895 -0.011159 0.0234972 -0.00391371 -0.0106054 0.0152195 0.0045161 -0.0309345 -0.0133451 0.0142733 0.0022754 0.0224104 0.00053866 -0.0105869 0.014126 -0.00594441 -0.016928 0.000217074 -0.00374499 -0.0370543 -0.0101543 -0.0131152 0.0467066 -0.0290259 0.0361985 0.048131 -0.0712857 -0.010248 0.0200725 -0.00527912 -0.033853 0.00625684 -0.0132771 -0.00059062 0.00807303 0.0207666 -0.005388 0.00403096 0.0390784 0.0263475 0.00420176 -0.0247701 -0.0169901 -0.0981137 0.00202813 -0.122794 1.22287)) +(4.2687 0.00527028 0.0351374 #(0.0119431 0.000370011 0.00297805 -0.0086345 -0.00619318 0.0209268 -0.0214211 -0.00264095 0.000795118 0.0018904 0.00504403 -0.00221174 0.000734628 0.0115394 0.00269348 0.00862158 -0.0112626 0.0128954 -0.0100209 -0.0261409 -0.00341844 -0.00612675 -0.023003 0.0109423 -0.00282099 0.0203828 -0.0265252 0.0270202 0.0322998 -0.0362086 -0.00119129 -0.0153138 -0.00350063 0.00240223 -0.0210972 -0.00135233 -0.00711855 0.000712969 0.0123906 -0.00078104 0.000209776 0.0312843 -0.00727613 0.0274143 -0.0141633 -0.0350039 -0.0442454 0.0167168 -0.0482093 1.11671)) +(5.08667 0.00434494 0.0292264 #(-0.00272251 0.00941567 0.00822995 -0.014127 -0.00472909 0.0256388 -0.0205545 -0.00637778 -0.0112651 0.0378657 -0.0158337 -0.00984417 0.00216444 0.030978 -0.00207667 -0.00625094 -0.00241573 0.000887676 -0.0113091 -0.0167408 -0.00726853 -0.00532588 -0.0106122 0.000375745 -0.00057362 0.0254724 -0.018358 0.0306097 0.0326059 -0.0225176 -0.0471872 0.00568396 -0.0101327 -0.0167238 -0.0112461 -0.0017848 -0.00424018 0.0120333 0.0037898 0.0135469 0.0227388 0.0193921 -0.0318962 0.0246949 -0.0262602 -0.0227707 -0.0672516 0.0572928 -0.0571018 1.11738)) +(5.64243 0.00660276 0.0342082 #(0.00180166 0.00187813 0.00574493 -0.000219231 -0.0214208 0.0292124 -0.0171232 -0.0116133 0.0143524 -0.0080191 0.00040181 -0.000264368 0.00500117 0.0156718 0.00494422 0.00107104 -0.0174182 0.00156305 -0.00116767 -0.0143132 -0.00873124 0.00879861 -0.0235025 -0.00555377 0.0159542 0.0120798 -0.00968709 0.0101018 0.0241207 -0.0283285 -0.00464771 0.00488285 -0.0317064 0.000691314 -0.0122031 -0.0076785 0.00264264 0.00947001 0.0122303 0.00967777 0.0183964 0.00361356 -0.0121287 0.0116267 -0.0186891 -0.0143781 -0.0485434 0.0242676 -0.0335089 1.09521)) +(4.34906 0.00506972 0.0341424 #(0.0023974 -0.00279862 0.0120042 -0.00157989 -0.0157521 0.0239786 -0.0126398 -0.0135926 -0.0020871 0.00151955 -0.00174203 -0.00773394 0.0159697 0.00780768 0.021657 0.00663021 -0.0142795 0.00149963 -0.00494957 -0.00158777 -0.0254905 -0.0117564 -0.017529 -0.00628616 0.00849666 0.00422017 -0.0116558 0.0310608 0.0345892 -0.0316539 -0.0132967 -0.00584913 0.00354922 -0.0173338 -0.0110622 -0.0096414 0.00859083 -0.0039589 0.0226801 0.0154026 0.00896204 0.0230092 0.00481482 0.00292927 -0.0234833 -0.0254714 -0.0981472 0.0441442 -0.0688532 1.14897)) +(2.61565 0.00474862 0.0426083 #(0.00879548 -0.00707132 0.0105265 0.00589761 -0.0181165 0.0122799 0.000610275 -0.0196829 -0.011157 0.0120507 -0.0115164 -0.0105635 0.0167566 0.0110644 0.0208706 0.00165262 0.00444448 -0.00889109 -0.00448973 -0.00204069 -0.0176097 -0.0204983 -0.00444134 -0.0102928 -0.000729621 0.00828533 -0.0156112 0.0249824 0.046813 -0.034427 -0.0110774 -0.0109798 -0.00690826 -0.00195731 -0.0157386 -0.00195138 0.00642795 -0.00283065 0.0119922 0.0211103 0.0124749 0.0247881 0.0132657 -0.00455936 -0.0371286 -0.0106291 -0.0739445 0.0263266 -0.0843839 1.15059)) +(2.02703 0.00255318 0.0354904 #(0.0134249 -0.00506588 0.00680395 0.0105582 -0.0323818 0.0493337 -0.0217674 -0.0241798 0.00928927 -0.023553 0.0104105 -0.0160771 0.00235487 0.00839372 0.0312377 0.00805041 0.000414273 -0.0136668 -0.0141831 0.0145558 -0.01835 -0.0176581 0.00780919 -0.0178566 -0.00798348 0.0228851 -0.0520132 0.0414188 0.066511 -0.0612651 0.00654983 -0.0331677 0.0129804 -0.0240143 0.0167766 -0.000209965 -0.0232557 0.0166038 0.0163538 0.0123617 -0.00410349 0.0241719 -0.00992855 0.0157116 -0.0186285 -0.0253129 -0.0767908 0.0521641 -0.0693304 1.12793)) +(2.64432 0.00171959 0.0255009 #(-0.0191815 0.0127539 0.0107323 0.00105373 -0.0253985 0.0548691 -0.00350344 -0.0407332 0.00805417 -0.00516293 0.0269923 -0.0481122 0.045745 -0.00949443 0.029402 0.00253762 -0.0224486 0.00621702 -0.0126075 -0.000360755 -0.0107886 -0.00802914 -0.0263488 -0.00418882 0.00777657 0.0122917 -0.0655835 0.0318259 0.0745041 -0.046913 -0.0178272 -0.014913 0.00287156 -0.0266232 0.016267 0.00797917 0.00580041 0.0114133 0.00738462 0.0441676 -0.0136994 0.0335519 -0.0324743 0.0188773 -0.0348701 -0.0234333 -0.174669 0.177908 -0.0964444 1.12857)) +(3.49525 0.0028907 0.0287582 #(-0.022997 0.00390569 0.0195987 -0.00368246 -0.0249804 0.0205793 -0.000749982 -0.0146779 0.0253093 -0.027436 -0.00506964 0.0229678 0.0122114 -0.00660955 0.0289347 0.00446956 -0.0240813 0.0124458 -0.000533498 -0.0357979 -0.00426894 0.00482643 -0.0216519 0.00376066 -0.0166858 0.0254196 -0.047756 0.0296842 0.05304 -0.053725 0.0233847 -0.00627376 -0.0327575 0.0242391 -0.00986949 0.0018908 0.0199183 -0.001377 0.00140167 0.0246927 0.00391399 0.00494078 -0.0242442 0.0174991 -0.0272264 -0.0343578 -0.0611368 0.0862893 -0.0566336 1.08269)) +(3.59173 0.00241115 0.0259096 #(-0.0280463 0.00239539 0.0275002 -0.0139323 -0.0348279 0.0607939 -0.0263654 -0.0111383 0.00125177 0.0134574 -0.0201514 0.0256755 0.0152298 -0.0129894 0.040595 -0.0242227 0.0223003 -0.0198948 -0.00945686 -0.0104881 -0.0149074 0.000106048 -0.0155021 0.00164234 -0.0275243 0.0334275 -0.0597113 0.0490029 0.0458835 -0.0406038 -0.00296535 0.00162114 0.00027736 -0.0194494 0.0124248 -0.00222679 0.0104655 -0.00167292 0.00815926 0.0283748 -0.0225562 0.0143205 -0.0188394 0.00579293 -0.0147764 -0.0167599 -0.050156 0.0847534 -0.0659405 1.07315)) +(2.26719 0.00255288 0.0335561 #(-0.0136514 -0.00925972 0.0167188 -0.00485284 -0.0336646 0.0412232 -0.000246899 -0.0298077 0.00712888 0.0134616 0.0103107 -0.00485241 -0.00127703 0.0164119 0.0132654 -0.019095 0.00456902 -0.00259853 -0.000275873 -0.0127027 -0.00593184 0.0101047 -0.0413224 0.018843 -0.0107773 0.0150738 -0.0289957 0.0254439 0.0380609 -0.0406301 -0.00392326 0.0172783 -0.00857435 -0.0223009 0.00749708 -0.0165367 0.0238457 0.018136 -0.00458933 0.00245699 0.00172918 0.00670983 -0.024566 0.00660529 -0.0205404 0.00950086 -0.0578217 0.0939725 -0.0510117 1.04425)) +(0.609353 0.00163717 0.0518337 #(0.00316256 -0.0122567 0.00518264 0.0126123 -0.0397706 0.0392831 0.0116002 -0.0471934 0.00805918 -0.00560564 0.000558784 -0.00409364 -0.00452707 -0.00113856 0.0257756 -0.00932488 0.00381936 -0.00247659 0.00301922 0.00335715 -0.00619763 0.0345422 -0.0321831 0.00519092 -0.00104381 -0.021393 -0.028818 0.0308446 0.0615516 -0.0569711 -0.0213437 0.00541473 0.00891156 -0.00345845 -0.00526036 -0.0140875 0.0217332 0.0150425 0.00302012 0.000750344 -0.0227373 0.0355403 -0.0606219 0.0543924 -0.0197096 0.0106198 -0.0761164 0.133679 -0.0540805 1.00403)) +(0.116473 0.000738204 0.0796116 #(-0.0020667 -0.00708028 0.00649903 0.00525495 -0.0577545 0.0708488 0.0241519 -0.0957537 0.0444855 0.00816514 -0.0260424 -0.00887706 0.0161092 -0.00643925 0.0365329 -0.0114855 -0.0214506 0.00323551 4.06337e-005 0.00984418 0.00579543 0.0340158 -0.0244511 -0.00303321 -0.0329481 0.0117391 -0.0672089 0.0657941 0.120411 -0.0823802 -0.0449917 0.00125354 0.00608117 -0.0209081 -0.0254859 0.0413741 -0.00546445 0.0228035 -0.0102555 0.0282721 -0.0411615 0.0264412 -0.0625765 0.0651369 -0.0960416 0.0914793 -0.12826 0.244372 -0.0968032 0.978677)) +(0.0472545 0.000482073 0.101003 #(-0.0132409 -0.00177229 -0.00651967 0.0181785 -0.057867 0.0886454 -0.0060562 -0.0415304 -0.00604645 0.00809692 -0.0261498 0.0308232 -0.0207518 0.039377 0.0286866 -0.00414628 -0.101779 0.0925687 -0.0566329 0.0285281 -0.0124488 0.0429751 -0.0231868 0.00492606 -0.0382182 0.0353667 -0.0854897 0.072105 0.138783 -0.152908 0.0118608 -0.0236536 0.0280545 -0.0358662 -0.00158007 0.0410328 -0.0307116 0.0351427 -0.0487812 0.0650863 -0.105127 0.0931477 -0.118991 0.157664 -0.204664 0.186411 -0.180145 0.351459 -0.130844 0.92427)) +(0.0200657 0.000490229 0.156305 #(-0.0167117 0.0226238 -0.0290179 0.0310399 -0.05596 0.0754746 -0.00102182 -0.0240663 -0.00557826 -0.00226293 0.00760277 0.00121096 -0.0371931 0.0368175 0.00439128 -0.00121828 -0.0701961 0.0851828 -0.0429475 0.0221135 -0.0202851 0.0294757 0.0173632 -0.014941 0.0101552 -0.0156045 -0.0714142 0.0373879 0.140392 -0.155288 0.0474913 -0.015392 0.010226 -0.0506144 0.00775825 0.0425248 -0.0111819 0.0198418 -0.0465491 0.0473969 -0.0958641 0.069069 -0.0800155 0.135248 -0.167486 0.159519 -0.163318 0.341011 -0.122999 0.899713)) +(0.0189561 0.000463645 0.156394 #(0.0136824 -0.010146 -0.00340101 0.00501791 -0.052312 0.0825702 -0.0198587 -0.00941267 0.00742931 -0.00822124 -0.00559287 0.0070671 -0.0295775 0.0163785 -0.000200317 -0.0124918 -0.0388802 0.0517694 -0.0148913 -0.0019372 0.0130002 0.0529274 -0.051331 0.0468511 -0.0493757 0.0488883 -0.0877978 0.0390208 0.120372 -0.130924 0.00454228 0.0284801 -0.0370236 -0.0207961 0.00413483 0.0556726 -0.0461664 0.043992 -0.0572133 0.0680651 -0.129146 0.0933036 -0.0903923 0.0963898 -0.115223 0.173486 -0.16108 0.327376 -0.109485 0.877362)) +(0.0157623 0.000457797 0.170422 #(0.00679172 0.0179331 -0.0180012 0.00985177 -0.0710897 0.0804711 -0.0138887 -0.00160079 -0.0130131 -0.0116605 -0.00195402 0.0102408 0.00544203 -0.00882841 -0.00664669 -0.000185585 -0.0333044 0.0571107 -0.0324269 0.00482369 0.00173713 0.0817342 -0.0689869 0.0314419 -0.0416472 0.0452527 -0.104628 0.0733021 0.109757 -0.112525 -0.040671 0.0457447 -0.033124 0.0189072 -0.0182032 0.0382207 -0.0430175 0.0633007 -0.0880582 0.0891837 -0.145313 0.126151 -0.130188 0.133809 -0.156576 0.210072 -0.192572 0.343954 -0.102867 0.867452)) +(0.0193939 0.000457706 0.153625 #(-0.00460792 0.0355563 -0.0550596 0.043009 -0.0897849 0.0978742 -0.0187992 0.00582897 -0.0109002 0.000631806 -0.0163601 0.0133513 -0.0165699 0.0221935 -0.0312557 0.04581 -0.0629084 0.0434437 -0.0167021 0.0323193 -0.0250667 0.0627469 -0.0306966 -0.00490861 -0.0368386 0.0217197 -0.0728413 0.0668549 0.145474 -0.169416 0.0122649 0.00448438 0.013949 -0.0353851 0.020688 0.00875267 -0.0340474 0.0569403 -0.0747049 0.0865628 -0.127027 0.0997718 -0.118786 0.172951 -0.208013 0.216935 -0.215728 0.401293 -0.19069 0.923122)) +(0.0267348 0.000456167 0.130624 #(0.0221721 0.012707 -0.0342673 0.0498141 -0.125798 0.0945948 -0.009383 -0.0118047 -0.00833615 0.0354772 -0.041698 0.0220065 -0.043747 0.0427328 -0.0334768 0.0279624 -0.0268537 0.00968139 0.00111546 0.0377293 -0.0348329 0.0808209 -0.0457136 0.00457449 -0.0453242 -0.0107467 -0.0188348 0.0300905 0.173791 -0.194862 0.0537233 -0.0419804 0.0496971 -0.0701674 0.0499813 -0.00747099 -0.0222291 0.0273433 -0.0549461 0.0661543 -0.122178 0.0944649 -0.101576 0.17229 -0.189446 0.207714 -0.21558 0.418696 -0.215629 0.931565)) +(0.0200745 0.000471228 0.153212 #(0.0163527 0.00660207 -0.0143944 0.046632 -0.126296 0.118434 -0.0369965 -0.00451566 -0.0201182 0.0417401 -0.0308534 -0.00543496 -0.0172945 0.0438493 -0.0319897 -0.0176332 -0.00909391 0.00684448 0.00776292 0.0226499 -0.00129345 0.0597638 -0.057499 0.0439582 -0.0376084 -0.009205 -0.0282326 0.0349981 0.136497 -0.137021 0.0108061 -0.0220325 0.0138336 -0.0341895 0.00554748 0.0125278 -0.0174402 0.0430164 -0.0595981 0.048263 -0.112704 0.102835 -0.101221 0.15651 -0.167554 0.189205 -0.200076 0.383302 -0.1668 0.902884)) +(0.0178948 0.000884452 0.222317 #(-0.00627428 0.017076 -0.0217517 0.0596357 -0.115011 0.137658 -0.140797 0.0413646 -0.025147 0.0409271 -0.0298679 0.0230878 -0.00804102 0.0133819 -0.0343905 0.081481 -0.0160831 0.031044 -0.0362416 0.0814956 -0.0892642 -0.0230409 -0.0232022 0.112084 -0.0729296 -0.0349948 0.00901226 -0.0373362 0.140441 -0.0702999 -0.00257567 -0.0348515 -0.00258082 0.0140751 -0.0718087 0.0880132 -0.061838 0.0690842 -0.118292 0.142831 -0.185955 0.190591 -0.155962 0.45873 -0.106312 0.127302 -0.523777 0.419269 -0.501987 1.22411)) +(0.014956 0.000914502 0.247278 #(-0.023965 0.0260125 -0.0174047 0.0515138 -0.0830966 0.07056 -0.0839288 -0.00253678 0.0274258 -0.000953763 -0.00370321 0.0051892 0.0273904 -0.020619 -0.0100326 0.0564985 0.00785514 0.0225726 -0.0248022 0.0636671 -0.0849298 -0.0493795 0.0247842 0.0783257 -0.054683 -0.0485245 0.00161631 -0.0165824 0.139226 -0.0743001 -0.00122059 -0.0566757 0.0247024 0.00172735 -0.0647441 0.0783151 -0.0575751 0.0609131 -0.105484 0.127889 -0.170536 0.193175 -0.164876 0.462587 -0.105663 0.112055 -0.495609 0.396188 -0.497893 1.21815)) +(0.00871568 0.000567858 0.255252 #(-0.0124666 0.0309579 -0.00109739 0.0135459 -0.057433 0.0477187 -0.0502651 0.00271826 0.0372547 0.0164188 -0.0446111 -0.0127535 -0.0377459 0.05085 -0.0332468 0.0648767 -0.0421368 0.0453716 -0.00560286 0.010505 -0.0502685 0.0272348 -0.0168195 0.0334298 -0.045445 0.0609193 -0.0939262 0.0603289 0.127758 -0.127759 -0.0161537 -0.0241133 0.0220789 0.0501327 -0.0297039 0.0276074 -0.0749799 0.0195223 -0.134458 0.0784379 -0.103965 0.143044 -0.0238226 0.243323 -0.14168 0.124602 -0.245754 0.281028 -0.225522 0.993662)) +(0.0086891 0.000454286 0.228653 #(0.000182833 -0.00254678 0.0082363 -0.0153415 -0.0299224 0.0849131 -0.0489407 0.00623273 0.00330074 0.015936 -0.0400408 -0.020401 -0.0247914 0.0710104 -0.015902 0.00164445 -0.0397469 0.0223963 0.0144133 0.00597068 -0.0101367 0.0517253 -0.0400181 0.0204692 -0.0703128 0.0792271 -0.0877888 0.0647522 0.100521 -0.114483 -0.00566729 -0.0255629 0.0314529 0.0182582 -0.0152464 0.0337968 -0.0685177 0.0350596 -0.0735331 0.0771414 -0.107742 0.0609778 -0.0612328 0.122617 -0.132552 0.162598 -0.143835 0.327107 -0.115002 0.855719)) diff --git a/lpc/lpc-orig.lsp b/lpc/lpc-orig.lsp new file mode 100644 index 0000000..d264ad8 --- /dev/null +++ b/lpc/lpc-orig.lsp @@ -0,0 +1,151 @@ +;--------------------------------------------------------------------- +; LPANAL. Performs LPC analysis +; +; snd sound for analysis +; an-dur duration of analysis (= duration of sound) +; skiptime step frame to frame +; npoles number of poles +; +; RESULT: analysis data in list format. +; Every element of the list is a list of the form +; +; (RMS1 RMS2 ERR FILTER-COEFS) +; +; RMS1 Energy (not rms value) of input signal +; RMS2 Energy (not rms value) of residual signal +; ERR = sqrt(RMS2/RMS1) If it is small then VOICED sound, +; else UNVOICED +; FILTER-COEFS Array of filter coefs. +; +; +; The z transform of filter is H(z) = 1/A(z) +; +; where A(z) is a polynome of the form: +; +; +; A(z) = 1 + a1 z + a2 z^2 + a3 z^3 + ... + aP z^P +; +; FILTER-COEFS is the array +; +; #(-aP -aP-1 -aP-2 ... a3 a2 a1) +; +; (this format is suited for the filter ALLPOLES) +; + + +(defun lpanal (snd an-dur skiptime npoles) + (let* ((sr (snd-srate snd)) + (skipsize (round (* sr skiptime))) + (numframes (round (- (/ (* sr an-dur) skipsize) 0.5))) + (sndcpy (snd-copy snd)) + (result (make-array numframes))) + (dotimes (i numframes) + (setf (aref result i) + (snd-lpanal + (snd-fetch-array sndcpy (* 2 skipsize) skipsize) + npoles))) + (format t "LPANAL: duration: ~A frames: ~A framedur: ~A skip: ~A poles ~A\n" + an-dur numframes (* skiptime 2) skiptime npoles) + result)) + + +;; this code is based on fft_demo.lsp -- the idea is that an object +;; will return a stream of LPC frames. Other objects can manipulate +;; these frames, creating a new stream, or turn the frames back into +;; sound. + +(setf lpc-class (send class :new '(sound framesize skipsize npoles))) + +(send lpc-class :answer :isnew '(snd framedur skiptime np) '( + (let ((sr (snd-srate snd))) + (setf sound snd) + (setf framesize (round (* sr framedur))) + (setf skiptime (round (* sr skiptime))) + (setf npoles np))) + +(send lpc-class :next '() '( + (let ((samps (snd-fetch-array framesize skipsize))) + (cond ((null samps) nil) + (t + (snd-lpanal samps npoles))))) + +(defun make-lpanal-iterator (sound framedur skiptime npoles) + (send lpc-class :new (snd-copy sound) framedur skiptime npoles)) + + +;--------------------------------------------------------------------- +; SHOW-LPC-DATA. Show values of LPC analysis frames +; +; lpc-data data generated by LPANAL +; iniframe first frame to show +; endframe last frame to show +; poles? T or NIL show or not filter coefs + +(defun show-lpc-data (lpc-data iniframe endframe &optional (poles? NIL)) + (if (> endframe (length lpc-data)) (setf endframe (length lpc-data))) + (dotimes (i (- endframe iniframe)) + (if poles? (format t "FRM ~A : ~A\n" (+ i iniframe) (aref lpc-data (+ i iniframe))) + (format t "FRM ~A : ~A\n" (+ i iniframe) (reverse (cdr (reverse (aref lpc-data (+ i iniframe))))))))) + + + +;---------------------------------------------------------------------- +; LPC-FREQ. Show frequency response of ALLPOLES filter. +; NEEDS MATLAB or OCTAVE +; +; +; HELPER FUNS : GET-FILTER-COEFS from a LPC analysis data +; lpc-data: data generated by LPCANAL +; numframe: index of frame data +; +; LPC-COEFS-TO-MATLAB : transforms LPC coefs format to Matlab format +; +; LPC-FREQ. +; +; varname : the name of variable that holds coef array in MATLAB +; lpc-data : as above +; numframe : as above +; + +(defun get-filter-coefs (lpc-data numframe) + (nth 3 (aref lpc-data numframe))) + + +(defun lpc-coefs-to-matlab (lpc-data numframe) + (let* ((lpc-coefs (get-filter-coefs lpc-data numframe)) + (lencoefs (length lpc-coefs)) + (result (make-array (1+ lencoefs)))) + (setf (aref result 0) 1.0) + (dotimes (i lencoefs) + (setf (aref result (1+ i)) + (- (aref lpc-coefs (- lencoefs i 1))))) + result)) + + +(defun lpc-freq (varname lpc-data numframe) + (octave (list (list (lpc-coefs-to-matlab lpc-data numframe) varname 'ARR)))) + + +;---------------------------------------------------------------------------- +; ALLPOLES +; + +(defun get-allpoles-gain (lpc-data numframe) + (nth 2 (aref lpc-data numframe))) ; se toma ERR para que la amplitud de + ; la salida se aproxime a 1 + +(defun allpoles-from-lpc (snd lpc-data numframe) + (snd-allpoles snd (get-filter-coefs lpc-data numframe) (get-allpoles-gain lpc-data numframe))) + +;------------------------------------------------------------------------------- +; LPRESON + +(defun get-lpreson-gain (lpc-data numframe) + (sqrt (nth 1 (aref lpc-data numframe)))) ; se toma (sqrt RMS2) para que la amplitud se + ; aproxime a la original + + +(defun get-lpreson-coefs (lpc-data numframe) + (nth 3 (aref lpc-data numframe))) + + diff --git a/lpc/lpc.lsp b/lpc/lpc.lsp new file mode 100644 index 0000000..d1008f4 --- /dev/null +++ b/lpc/lpc.lsp @@ -0,0 +1,178 @@ +;--------------------------------------------------------------------- +; LPANAL. Performs LPC analysis +; +; snd sound for analysis +; an-dur duration of analysis (= duration of sound) +; skiptime step frame to frame +; npoles number of poles +; +; RESULT: analysis data in list format. +; Every element of the list is a list of the form +; +; (RMS1 RMS2 ERR FILTER-COEFS) +; +; RMS1 Energy (not rms value) of input signal +; RMS2 Energy (not rms value) of residual signal +; ERR = sqrt(RMS2/RMS1) If it is small then VOICED sound, +; else UNVOICED +; FILTER-COEFS Array of filter coefs. +; +; +; The z transform of filter is H(z) = 1/A(z) +; +; where A(z) is a polynome of the form: +; +; +; A(z) = 1 + a1 z + a2 z^2 + a3 z^3 + ... + aP z^P +; +; FILTER-COEFS is the array +; +; #(-aP -aP-1 -aP-2 ... a3 a2 a1) +; +; (this format is suited for the filter ALLPOLES) +; + +(setfn lpc-frame-rms1 car) +(setfn lpc-frame-rms2 cadr) +(setfn lpc-frame-err caddr) +(setfn lpc-frame-filter-coefs cadddr) + +;; LPANAL-CLASS -- does lpc analysis. Frames are returned +;; from an iterator object + +(setf lpanal-class (send class :new '(sound framesize skipsize npoles))) + +(send lpanal-class :answer :isnew '(snd framedur skiptime np) '( + (let ((sr (snd-srate snd))) + (setf sound snd) + (setf framesize (round (* sr framedur))) + (setf skiptime (round (* sr skiptime))) + (setf npoles np)))) + +(send lpanal-class :answer :next '() '( + (let ((samps (snd-fetch-array framesize skipsize))) + (cond ((null samps) nil) + (t + (snd-lpanal samps npoles)))))) + +(defun make-lpanal-iterator (sound framedur skiptime npoles) + (send lpanal-class :new (snd-copy sound) framedur skiptime npoles)) + +;; LPC-FILE-CLASS -- iterator returns frames from file +;; +(setf lpc-file-class (send class :new '(file))) + +(send lpc-file-class :answer :isnew '(filename) '( + (setf file (open filename)))) + +(send lpc-file-class :answer :next '() '( + (read file))) + +(defun make-lpc-file-iterator (filename) + (send lpc-file-class :new filename)) + + +;; SAVE-LPC-FILE -- create a file from an iterator. This file can +;; be turned back into an iterator using make-lpc-file-iterator. +;; +(defun save-lpc-file (lpc-iterator filename) + (let ((fp (open filename :direction :output)) + (frame t)) + (while frame + (setf frame (send lpc-iterator :next)) + (if frame (format fp "~A~%" frame))) + (close fp))) + + + +;; SHOW-LPC-DATA. Show values of LPC analysis frames from interator. +;; +(defun show-lpc-data (lpc-iterator iniframe endframe &optional (poles? NIL)) + (dotimes (i iniframe) (send lpc-iterator :next)) + (dotimes (i (- endframe iniframe)) + (let ((frame (send lpc-iterator :next))) + (cond ((null frame) (return)) + (poles? + (format t "FRM ~A : ~A\n" (+ i iniframe) frame)) + (t + (format t "FRM ~A : ~A\n" (+ i iniframe) + (reverse (cdr (reverse frame))))))))) + + +;---------------------------------------------------------------------- +; LPC-FREQ. Show frequency response of ALLPOLES filter. +; NEEDS MATLAB or OCTAVE +; +; +; HELPER FUNS : GET-FILTER-COEFS from a LPC analysis data +; lpc-data: data generated by LPCANAL +; numframe: index of frame data +; +; LPC-COEFS-TO-MATLAB : transforms LPC coefs format to Matlab format +; +; LPC-FREQ. +; +; varname : the name of variable that holds coef array in MATLAB +; lpc-data : as above +; numframe : as above +; + + +; THIS CODE TO GET FREQUENCY ASSUMES AN ARRAY OF LPC FRAMES AND REQUIRES +; MATLAB OR OCTAVE. I HAVE NOT ADAPTED THIS TO USE THE STREAM OF FRAMES +; APPROACH. -RBD +; +;(defun get-filter-coefs (lpc-data numframe) +; (nth 3 (aref lpc-data numframe))) +; +; +;(defun lpc-coefs-to-matlab (lpc-data numframe) +; (let* ((lpc-coefs (get-filter-coefs lpc-data numframe)) +; (lencoefs (length lpc-coefs)) +; (result (make-array (1+ lencoefs)))) +; (setf (aref result 0) 1.0) +; (dotimes (i lencoefs) +; (setf (aref result (1+ i)) +; (- (aref lpc-coefs (- lencoefs i 1))))) +; result)) +; +; +;(defun lpc-freq (varname lpc-data numframe) +; (octave (list (list (lpc-coefs-to-matlab lpc-data numframe) varname 'ARR)))) + + +;---------------------------------------------------------------------------- +; ALLPOLES +; +; THIS VERSION IS FOR ARRAY OF FRAMES +; +;(defun get-allpoles-gain (lpc-data numframe) +; (nth 2 (aref lpc-data numframe))) ; se toma ERR para que la amplitud de +; ; la salida se aproxime a 1 +; +;(defun allpoles-from-lpc (snd lpc-data numframe) +; (snd-allpoles snd (get-filter-coefs lpc-data numframe) (get-allpoles-gain lpc-data numframe))) + +; ALLPOLES USES A SINGLE FRAME TO CREATE A FILTER +; +; We introduce two functions: +; NTH-FRAME runs the interator to get the nth frame; +; ALLPOLES-FROM-LPC filters a sound given a frame from an iterator + +;; NTH-FRAME - get the nth frame from lpc iterator, +;; first frame is numbered zero +(defun nth-frame (lpc-iterator numframe) + (dotimes (i numframe) (send lpc-iterator :next)) + (send lpc-iterator :next)) + + +;; ALLPOLES-FROM-LPC -- filter a sound using an LPC frame +;; +(defun allpoles-from-lpc (snd lpc-frame) + (snd-allpoles snd (lpc-frame-filter-coefs lpc-frame) + (lpc-frame-err lpc-frame))) ;; use ERR for gain + +;------------------------------------------------------------------------------- +; LPRESON + +(setfn lpreson snd-lpreson) diff --git a/lpc/lpcdemo-orig.lsp b/lpc/lpcdemo-orig.lsp new file mode 100644 index 0000000..b5f62e6 --- /dev/null +++ b/lpc/lpcdemo-orig.lsp @@ -0,0 +1,301 @@ +;;; LPC demo 1 +;;; Pedro J. Morales. +;;; February, 04 + +; PLEASE config ====================================================== + + +; don't need this because file-io utilities are embedded in this file +; (setf *file-io* "c:/04-nyquist/nyqdoc/tools/file-io.lsp") + +; where is the file lpc-example.dat +(setf *lpc-data* "d:/rbd/nyquist/lpc/lpc-example.dat") + + +; this file generated by Nyquist will be loaded by Octave (or Matlab) +(setf *default-octave-file* + "d:/rbd/temp/nyquist.dat") + +; config END =========================================================== + + + +; file-io tools ======================================================== + +(defun load-file-data (filename) + (let (result + (fp (open filename :direction :input))) + (when fp (setf result (read fp))) + (close fp) + result)) + + +(defun save-file-data (data filename) + (let ((fp (open filename :direction :output))) + (when fp (format fp "~A" data)) + (close fp))) + +(defun octave-1 (outf data varname datatype &optional (n 1000)) + (prog ((points (case datatype + (SND (snd-samples data (1+ n))) + (ARR data))) + len) + (setf len (length points)) + (cond ((> len n) + (setf len n) + (format t "WARNING: DATA TRUNCATED TO ~A POINTS~%" len))) + (format outf "# name: ~A\n" varname) + (format outf "# type: matrix\n# rows: 1\n# columns: ~A\n " len) + (dotimes (i len) + (format outf "~A " (aref points i))) + (format outf "\n"))) + +(defun octave (data-lists) ; (data varname datatype &optional (n 1000)) + (prog ((filename *default-octave-file*) + outf) + (setf outf (open filename :direction :output)) + (cond ((null outf) + (format t "octave: could not open ~A!~%" filename) + (return nil))) + (format t "octave: writing ~A ... ~%" filename) + (cond ((null outf) + (format t "octave: could not open ~A!~%" filename) + (return nil))) + ;(format t "octave: writing ~A ... ~%" filename) + (dolist (l data-lists) + (apply #'octave-1 (cons outf l))) + (close outf))) + + + +; load file-io --------------------------------------------------- + +; (load *file-io*) + + +; file-io END ==================================================== + + + + + + +; LPANAL ====================================================== + +; get lpc data --------------------------------------------------- + + +(defun do-lpc-analysis () + (prog () + (setf *myfile* "d:/rbd/nyquist/voice.wav") + (setf mysound (s-read *myfile*)) + ; duration 6.5 skiptime 20ms npoles 50 + (setf lpc-example (lpanal (cue mysound) 1.3 0.04 50)))) + +;(if (not (boundp 'lpc-example)) +; (do-lpc-analysis)) + +(if (not (boundp 'lpc-example)) + (setf lpc-example (load-file-data *lpc-data*))) + +;----------------------------------------------------------------- + + +; SHOW-LPC-DATA ------------------------------------------------ +; show values of LPC analysis frames ---------------------------- + + +(defun ex-1 () + (show-lpc-data lpc-example 100 120 NIL)) ; do not show filter coefs + + +; ------- SAVE-FILE-DATA --------------------------------------- +(defun ex-2 () + (save-file-data lpc-example *lpc-data*)) + + +;----------- LPC-FREQ ------------------------------------------ +; LPC-FREQ. Show frequency response of ALLPOLES filter. +; NEEDS MATLAB or OCTAVE +; + +(defun ex-3 () + (lpc-freq "frm70" lpc-example 70)) + + +; in MATLAB/OCTAVE: +; >> load -force nyquist.dat +; >> [H,W] = freqz(1, frm70, 512); +; >> plot(W,20*log10(abs(H))); + + +;------------------------------------------------------------------------- +; LPC-STABILITY Check for Stability of LPC filters +; NEEDS MATLAB/OCTAVE + +; EXAMPLE + +; (ex-3) + +; in MATLAB/OCTAVE: +; >> load -force nyquist.dat +; >> find(abs(roots(frm70)) > 1) +; if any abs root is > 1.0 then UNSTABLE + +;-------------------------------------------------------------------------- +; ALLPOLES LPC allpoles filter +; WARNING: this is a static filter +; for LPC resynthesis a dinamic LPC filter is needed + + +; EXAMPLE + +(defun ex-4 () + (play (seq + (allpoles-from-lpc (buzz 12 f2 (lfo 5.0 4.0)) lpc-example 30) + (allpoles-from-lpc (buzz 12 f2 (lfo 5.1 4.0)) lpc-example 60) + (allpoles-from-lpc (buzz 12 g2 (lfo 5.3 4.0)) lpc-example 100)))) + + +(setf a-lpcdata +'(63.2144 0.674387 0.103287 + #(-0.0381026 0.00804115 0.0109905 0.0145117 0.00199174 -0.00129314 0.0171826 + 0.0181176 0.00179391 -0.0114089 -0.0120949 -0.000410595 -0.0122539 + -0.0209354 -0.00804976 -0.00345041 -0.00409532 -0.00227011 0.014224 0.0135451 + 0.0056023 -0.00651142 -0.00564953 -0.0168921 -0.0377939 -0.0449506 -0.0355592 + -0.0339316 -0.0454434 1.19336))) + +(setf e-lpcdata +'(40.7157 0.149753 0.0606467 + #(0.0244574 -0.0225545 -0.0172724 -0.0122709 -0.0042946 0.00886974 0.0121516 0.0120936 + 0.00197545 -0.00582163 -0.018367 -0.0201546 -0.00440599 0.00638936 0.0166275 0.0185066 + 0.00890464 -0.00158013 -0.00494974 -0.00479037 0.0130814 0.0138648 -0.0022018 -0.021368 + -0.0343532 -0.0312712 -0.0574975 -0.0918824 -0.112016 1.31398))) + + +(setf i-lpcdata +'(5.5391 0.0321825 0.0762238 #(-0.0341124 -0.0149688 -0.00585657 -0.0111572 + 0.00769712 0.0190367 0.00885366 0.0112762 0.0118286 -0.00059044 -0.0140864 -0.0123688 + -0.0151128 0.00214354 -0.00810219 -0.00538188 0.00631382 0.020771 0.0356498 0.0295531 + 0.0242797 0.0124296 0.00445127 -0.013062 -0.0387178 -0.0527783 -0.0685511 -0.076575 + -0.0846335 1.24521))) + +(defun noise-vocal (lpcdata dur) + (snd-allpoles (noise dur) (nth 3 lpcdata) (nth 2 lpcdata))) + +(defun ex-5 () + (play + (seq (noise-vocal a-lpcdata 1)(noise-vocal e-lpcdata 1)(noise-vocal i-lpcdata 1)))) + +(defun buzz-vocal (lpcdata dur) + (snd-allpoles (buzz 16 e2 (const 0.0 dur)) (nth 3 lpcdata) (nth 2 lpcdata))) + +(defun ex-6 () + (play + (seq (buzz-vocal a-lpcdata 1)(buzz-vocal e-lpcdata 1)(buzz-vocal i-lpcdata 1)))) + + +; ---- LPRESON ------------------------------------------------------------ +; +(setf example-lpc-class (send class :new '(cnt limit))) + +(send example-lpc-class :answer :isnew '() + '((setf cnt 0) + (setf limit (length lpc-example)))) + +(send example-lpc-class :answer :reset '() + '((setf cnt 0))) + +(send example-lpc-class :answer :next '() + '((setf cnt (1+ cnt)) + (if (= cnt limit) (setf cnt 0)) + (if (< cnt limit) + (list (get-lpreson-gain lpc-example cnt) + (get-lpreson-coefs lpc-example cnt)) + NIL))) + + +(setf mylpc (send example-lpc-class :new)) + +(defun ex-7a () + (send mylpc :reset) + (snd-lpreson (noise 6.5) mylpc 0.04)) + +(defun ex-7 () + (play (ex-7a))) + +(defun ex-8a (p dur) + (send mylpc :reset) + (snd-lpreson (buzz 16 p (scale 1.5 (lfo 3.0 dur))) mylpc 0.04)) + +(defun ex-8 () + (play + (sim (seq (ex-8a c4 1)(ex-8a g3 1)(ex-8a a3 1)(ex-8a b3 1)(ex-8a c4 1)) + (seq (ex-8a c2 2)(ex-8a f2 1)(ex-8a g2 1)(ex-8a e2 1))))) + +(defun noalias-buzz (p nmax) + (min + (round (/ *sound-srate* (* 2.0 (step-to-hz p)))) + nmax)) + +(defun ex-9a (p dur skiptime) + (send mylpc :reset) + (mult (env 0.01 0.01 0.1 1.0 1.0 1.0 dur) + (snd-lpreson (buzz (noalias-buzz p 16) p (scale 1.5 (lfo 3.0 dur))) mylpc skiptime))) + + +(defun ex-9b (stretch skiptime) + (play + (sim (seq (ex-9a c4 (* 1 stretch) skiptime)(ex-9a g3 (* 1 stretch) skiptime) + (ex-9a a3 (* 1 stretch) skiptime) + (ex-9a b3 (* 1 stretch) skiptime)(ex-9a c4 (* 1 stretch) skiptime)) + (seq (ex-9a c2 (* 2 stretch) skiptime)(ex-9a f2 (* 1 stretch) skiptime) + (ex-9a g2 (* 1 stretch) skiptime)(ex-9a e2 (* 1 stretch) skiptime))))) + + +(defun ex-9 () + (ex-9b 1.0 0.04)) + +(defun ex-10 () + (ex-9b 1.0 0.02)) + +(defun ex-11 () + (ex-9b 2.0 0.04)) + +(defun ex-12 () + (ex-9b 0.5 0.02)) + +(defun ex-13 () + (ex-9b 4 0.02)) + +(defun ex-14a (p dur skiptime) + (send mylpc :reset) + (mult (env 0.01 0.01 0.1 1.0 1.0 1.0 dur) + (snd-lpreson (osc-saw (sim (step-to-hz (+ p 0)) (scale 1.5 (lfo 3.0 dur)))) + mylpc skiptime))) + +(defun ex-14b (stretch skiptime) + (play + (sim (seq (ex-14a c4 (* 1 stretch) skiptime)(ex-14a g3 (* 1 stretch) skiptime) + (ex-14a a3 (* 1 stretch) skiptime) + (ex-14a b3 (* 1 stretch) skiptime)(ex-14a c4 (* 1 stretch) skiptime)) + (seq (ex-14a c2 (* 2 stretch) skiptime)(ex-14a f2 (* 1 stretch) skiptime) + (ex-14a g2 (* 1 stretch) skiptime)(ex-14a e2 (* 1 stretch) skiptime))))) + + +(defun ex-14 () + (ex-14b 1 0.04)) + +(defun ex-15 () + (ex-14b 4 0.02)) + +(defun ex-16 () + (ex-14b 8 0.08)) + + + + + + + + diff --git a/lpc/lpcdemo.lsp b/lpc/lpcdemo.lsp new file mode 100644 index 0000000..2f02999 --- /dev/null +++ b/lpc/lpcdemo.lsp @@ -0,0 +1,275 @@ +;;; LPC demo 1 +;;; Pedro J. Morales. +;;; February, 04 +;;; Roger B. Dannenberg +;;; July, 04 + +; PLEASE config ====================================================== + + +; where is the file lpc-example.dat +(setf *lpc-data* "d:/rbd/nyquist/lpc/lpc-exmpl.dat") + + +; this file generated by Nyquist will be loaded by Octave (or Matlab) +(setf *default-octave-file* + "d:/rbd/temp/nyquist.dat") + +; config END =========================================================== + + + +; file-io tools ======================================================== + + +(defun octave-1 (outf data varname datatype &optional (n 1000)) + (prog ((points (case datatype + (SND (snd-samples data (1+ n))) + (ARR data))) + len) + (setf len (length points)) + (cond ((> len n) + (setf len n) + (format t "WARNING: DATA TRUNCATED TO ~A POINTS~%" len))) + (format outf "# name: ~A\n" varname) + (format outf "# type: matrix\n# rows: 1\n# columns: ~A\n " len) + (dotimes (i len) + (format outf "~A " (aref points i))) + (format outf "\n"))) + +(defun octave (data-lists) ; (data varname datatype &optional (n 1000)) + (prog ((filename *default-octave-file*) + outf) + (setf outf (open filename :direction :output)) + (cond ((null outf) + (format t "octave: could not open ~A!~%" filename) + (return nil))) + (format t "octave: writing ~A ... ~%" filename) + (cond ((null outf) + (format t "octave: could not open ~A!~%" filename) + (return nil))) + ;(format t "octave: writing ~A ... ~%" filename) + (dolist (l data-lists) + (apply #'octave-1 (cons outf l))) + (close outf))) + + +; LPANAL ====================================================== + +; get lpc data --------------------------------------------------- + + +(defun do-lpc-analysis () + (setf *myfile* "d:/rbd/nyquist/voice.wav") + (save-lpc-file (make-lpanal-iterator (s-read *myfile*) 0.08 0.04 50) + "temp.dat")) + +;(if (not (boundp 'lpc-example)) +; (do-lpc-analysis)) + +;(if (not (boundp 'lpc-example)) +; (setf lpc-example (load-file-data *lpc-data*))) + +;----------------------------------------------------------------- + + +; SHOW-LPC-DATA ------------------------------------------------ +; show values of LPC analysis frames ---------------------------- + + +(defun ex-1 () + ; do not show filter coefs + (show-lpc-data (make-lpc-file-iterator *lpc-data*) 100 120 NIL)) + + +; ------- SAVE-FILE-DATA --------------------------------------- +(defun ex-2 () + (save-lpc-file (make-lpc-file-iterator *lpc-data*) "temp.dat")) + + +;----------- LPC-FREQ ------------------------------------------ +; LPC-FREQ. Show frequency response of ALLPOLES filter. +; NEEDS MATLAB or OCTAVE +; + +(defun ex-3 () + (lpc-freq "frm70" (make-lpc-file-iterator *lpc-data*) 70)) + + +; in MATLAB/OCTAVE: +; >> load -force nyquist.dat +; >> [H,W] = freqz(1, frm70, 512); +; >> plot(W,20*log10(abs(H))); + + +;------------------------------------------------------------------------- +; LPC-STABILITY Check for Stability of LPC filters +; NEEDS MATLAB/OCTAVE + +; EXAMPLE + +; (ex-3) + +; in MATLAB/OCTAVE: +; >> load -force nyquist.dat +; >> find(abs(roots(frm70)) > 1) +; if any abs root is > 1.0 then UNSTABLE + +;-------------------------------------------------------------------------- +; ALLPOLES LPC allpoles filter +; WARNING: this is a static filter +; for LPC resynthesis a dynamic LPC filter is needed + + +; EXAMPLE + +(defun ex-4 () + (play (seq + (allpoles-from-lpc (buzz 12 f2 (lfo 5.0 4.0)) + (nth-frame (make-lpc-file-iterator *lpc-data*) + 30)) + (allpoles-from-lpc (buzz 12 f2 (lfo 5.1 4.0)) + (nth-frame (make-lpc-file-iterator *lpc-data*) + 60)) + (allpoles-from-lpc (buzz 12 g2 (lfo 5.3 4.0)) + (nth-frame (make-lpc-file-iterator *lpc-data*) + 100)) ))) + + +(setf a-lpcdata +'(63.2144 0.674387 0.103287 + #(-0.0381026 0.00804115 0.0109905 0.0145117 0.00199174 -0.00129314 0.0171826 + 0.0181176 0.00179391 -0.0114089 -0.0120949 -0.000410595 -0.0122539 + -0.0209354 -0.00804976 -0.00345041 -0.00409532 -0.00227011 0.014224 0.0135451 + 0.0056023 -0.00651142 -0.00564953 -0.0168921 -0.0377939 -0.0449506 -0.0355592 + -0.0339316 -0.0454434 1.19336))) + +(setf e-lpcdata +'(40.7157 0.149753 0.0606467 + #(0.0244574 -0.0225545 -0.0172724 -0.0122709 -0.0042946 0.00886974 0.0121516 0.0120936 + 0.00197545 -0.00582163 -0.018367 -0.0201546 -0.00440599 0.00638936 0.0166275 0.0185066 + 0.00890464 -0.00158013 -0.00494974 -0.00479037 0.0130814 0.0138648 -0.0022018 -0.021368 + -0.0343532 -0.0312712 -0.0574975 -0.0918824 -0.112016 1.31398))) + + +(setf i-lpcdata +'(5.5391 0.0321825 0.0762238 #(-0.0341124 -0.0149688 -0.00585657 -0.0111572 + 0.00769712 0.0190367 0.00885366 0.0112762 0.0118286 -0.00059044 -0.0140864 -0.0123688 + -0.0151128 0.00214354 -0.00810219 -0.00538188 0.00631382 0.020771 0.0356498 0.0295531 + 0.0242797 0.0124296 0.00445127 -0.013062 -0.0387178 -0.0527783 -0.0685511 -0.076575 + -0.0846335 1.24521))) + +(defun noise-vocal (lpcdata dur) + (allpoles-from-lpc (noise dur) lpcdata)) + +(defun ex-5 () + (play + (seq (noise-vocal a-lpcdata 1) + (noise-vocal e-lpcdata 1) + (noise-vocal i-lpcdata 1)))) + +(defun buzz-vocal (lpcdata dur) + (allpoles-from-lpc (buzz 16 e2 (const 0.0 dur)) + lpcdata)) + +(defun ex-6 () + (play + (seq (buzz-vocal a-lpcdata 1) + (buzz-vocal e-lpcdata 1) + (buzz-vocal i-lpcdata 1)))) + + +; ---- LPRESON ------------------------------------------------------------ +; +(defun ex-7a () + ;; parameters are sound, lpc-iterator, skiptime + (lpreson (noise 6.5) (make-lpc-file-iterator *lpc-data*) 0.04)) + +(defun ex-7 () + (play (ex-7a))) + +(defun ex-8a (p dur) + (lpreson (buzz 16 p (scale 1.5 (lfo 3.0 dur))) + (make-lpc-file-iterator *lpc-data*) + 0.04)) + +(defun ex-8 () + (play + (sim (seq (ex-8a c4 1) (ex-8a g3 1) (ex-8a a3 1) (ex-8a b3 1) (ex-8a c4 1)) + (seq (ex-8a c2 2) (ex-8a f2 1) (ex-8a g2 1) (ex-8a e2 1))))) + +(defun noalias-buzz (p nmax) + (min + (round (/ *sound-srate* (* 2.0 (step-to-hz p)))) + nmax)) + +(defun ex-9a (p dur skiptime) + (mult (env 0.01 0.01 0.1 1.0 1.0 1.0 dur) + (lpreson (buzz (noalias-buzz p 16) p (scale 1.5 (lfo 3.0 dur))) + (make-lpc-file-iterator *lpc-data*) + skiptime))) + + +(defun ex-9b (stretch skiptime) + (play + (sim (seq (ex-9a c4 (* 1 stretch) skiptime) + (ex-9a g3 (* 1 stretch) skiptime) + (ex-9a a3 (* 1 stretch) skiptime) + (ex-9a b3 (* 1 stretch) skiptime) + (ex-9a c4 (* 1 stretch) skiptime)) + (seq (ex-9a c2 (* 2 stretch) skiptime) + (ex-9a f2 (* 1 stretch) skiptime) + (ex-9a g2 (* 1 stretch) skiptime) + (ex-9a e2 (* 1 stretch) skiptime))))) + + +(defun ex-9 () + (ex-9b 1.0 0.04)) + +(defun ex-10 () + (ex-9b 1.0 0.02)) + +(defun ex-11 () + (ex-9b 2.0 0.04)) + +(defun ex-12 () + (ex-9b 0.5 0.02)) + +(defun ex-13 () + (ex-9b 4 0.02)) + +(defun ex-14a (p dur skiptime) + (mult (env 0.01 0.01 0.1 1.0 1.0 1.0 dur) + (lpreson (osc-saw (sim (step-to-hz (+ p 0)) (scale 1.5 (lfo 3.0 dur)))) + (make-lpc-file-iterator *lpc-data*) + skiptime))) + +(defun ex-14b (stretch skiptime) + (play + (sim (seq (ex-14a c4 (* 1 stretch) skiptime) + (ex-14a g3 (* 1 stretch) skiptime) + (ex-14a a3 (* 1 stretch) skiptime) + (ex-14a b3 (* 1 stretch) skiptime) + (ex-14a c4 (* 1 stretch) skiptime)) + (seq (ex-14a c2 (* 2 stretch) skiptime) + (ex-14a f2 (* 1 stretch) skiptime) + (ex-14a g2 (* 1 stretch) skiptime) + (ex-14a e2 (* 1 stretch) skiptime))))) + + +(defun ex-14 () + (ex-14b 1 0.04)) + +(defun ex-15 () + (ex-14b 4 0.02)) + +(defun ex-16 () + (ex-14b 8 0.08)) + + + + + + + + diff --git a/lpc/prims-ref.txt b/lpc/prims-ref.txt new file mode 100644 index 0000000..da073e0 --- /dev/null +++ b/lpc/prims-ref.txt @@ -0,0 +1,57 @@ +==================================== +Reference of LPC primitive functions +==================================== + + + + +snd-lpanal ARGS: snd-array npoles + + snd-array: array of samples from a sound to be analyzed + npoles: number of poles for LPC analysis + + returns: a list (RMS1 RMS2 ERR VECTOR) + where RMS1: energy of input data (not rms value!) + RMS2: energy of residual + ERR: sqrt(RMS2/RMS1) + VECTOR: array of LPC filter coefficients + + Note: this analysis lacks pitch detection + +------------------------------------------------------------------- + +snd-allpoles ARGS: snd coefs gain + + snd: A sound + coefs: Array of coefficients of an allpoles filter. + The format of this array is the same of the fourth + element of the list returned by snd-lpcanal. + (see details in lpc.lsp) + gain: gain of the LPC filter (a FLONUM) + + returns: The sound filtered by the specified allpoles filter + + Note: This is a static filter. Coefficients do not change. + +-------------------------------------------------------------------- + +snd-lpreson ARGS: snd lpc-obj skiptime + + snd: A sound + lpc-obj A Lisp object such as when a :next message is send to + this object it returns a list of two elements (GAIN COEFS) + where: + GAIN: gain of the filter + COEFS: coefficients of LPC filter + skiptime: a FLONUM. This is the frame duration for resyntesis. + + returns: The sound snd filtered by a dinamic LPC filter. + The coefficients and gain of LPC filter are changed every frame + The data for every frame is obtained by sending a :next message to + lpc-obj. + The output sound finish when input sound finish or when lpc-obj + returns NIL + + + + diff --git a/lpc/readme.txt b/lpc/readme.txt new file mode 100644 index 0000000..92a91ab --- /dev/null +++ b/lpc/readme.txt @@ -0,0 +1,28 @@ +; LPC functions for Nyquist +; Pedro J. Morales, 2004 + +1. Compile Nyquist with LPC functions + See file compile.txt for details + Source code is in src folder + +2. Reference of LPC primitives. + See file prims-ref.txt + +3. Implementation of high level LPC Lisp functions + File: lpc.lsp + +4. Reference of high level LPC Lisp functions + See file lpc.lsp + +5. LPC demo + 5.1. Compile and start Nyquist + 5.2. Load lpc.lsp + 5.3. Edit lpcdemo.lsp and configure it. + 5.4. Load lpcdemo.lsp + Note: lpcdemo should perform an analysis of an audio file. + This audio file is not supplied (for size reasons) + Instead, the result is supplied as a Lisp data structure + contained in the file lpc-example.dat that is loaded by lpcdemo. + 5.5. Run the examples. + Note: You don't have to run all the examples + diff --git a/lpc/src/allpoles.alg b/lpc/src/allpoles.alg new file mode 100644 index 0000000..ca03055 --- /dev/null +++ b/lpc/src/allpoles.alg @@ -0,0 +1,70 @@ +(ALLPOLES-ALG +(NAME "allpoles") +(ARGUMENTS ("sound_type" "x_snd")("LVAL" "ak_array")("double" "gain")) +(START (MIN x_snd)) +(NOT-IN-INNER-LOOP "ak_array") +(ALWAYS-SCALE x_snd) +(TERMINATE (MIN x_snd)) +(LOGICAL-STOP (MIN x_snd)) + +(STATE + ("long" "ak_len" "0") ; length of coefs ak array + ("LVAL" "ak_array" "ak_array") + ("double" "gain" "gain") + ("double *" "ak_coefs" "NULL") ; coefs array + ("double *" "zk_buf" "NULL") ; last values of output + ("long" "index" "0") +) + +(OUTER-LOOP " + if (susp->ak_array == NULL) { +out: togo = 0; /* indicate termination */ + break; /* we're done */ + } + else if (!vectorp(susp->ak_array)) + xlerror(\"array expected\", susp->ak_array); + else if (susp->ak_coefs == NULL) + { + long i; + susp->ak_len = getsize(susp->ak_array); + if (susp->ak_len < 1) xlerror(\"array has not elements\", susp->ak_array); + susp->ak_coefs = (double *) calloc(susp->ak_len, sizeof(double)); + susp->zk_buf = (double *) calloc(susp->ak_len, sizeof(double)); + + /* at this point we have a new array and a place to put ak coefs */ + for(i=0; i < susp->ak_len; i++) { + LVAL elem = getelement(susp->ak_array,i); + if (ntype(elem) != FLONUM) { + xlerror(\"flonum expected\", elem); + } + susp->ak_coefs[i] = getflonum(elem); + } + + } +") + + +(CONSTANT "ak_array" "ak_coefs" "ak_len" "gain") +(SAMPLE-RATE "x_snd->sr") +(INNER-LOOP-LOCALS "double z0; long xi; long xj;") + +(INNER-LOOP " + z0 = x_snd*gain; + for (xi=0; xi < ak_len ; xi++) + { + xj = index + xi; if (xj >= ak_len) xj -= ak_len; + z0 += ak_coefs[xi] * zk_buf[xj]; + } + zk_buf[index] = z0; + index++; if (index == ak_len) index = 0; + output = (sample_type) z0; +") + +(FINALIZATION " + free(susp->zk_buf); + free(susp->ak_coefs); + susp->ak_array = NULL; /* free array */ +") +) + + diff --git a/lpc/src/lpanal.c b/lpc/src/lpanal.c new file mode 100644 index 0000000..d6baf98 --- /dev/null +++ b/lpc/src/lpanal.c @@ -0,0 +1,177 @@ +/* lpc.c -- implement LPC analysis */ + +#include + +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" + + +void abs_max(double *x, long desde, long hasta, double *x_maxptr, long *indptr) +{ + /* use: + abs_max(s,0,10,&mimax,&miind); + */ + + double x_max = x[desde]; + long ind = desde; + long i; + for(i = desde+1; i x_max) + { + x_max = fabs(x[i]); + ind = i; + } + *x_maxptr = x_max; + *indptr = ind; + +} + +void xcorr(double *s, double *rxx, long N) +{ + /* use: + xcorr(s,rxx,N); + */ + long i,j; + for(i=0; i < N; i++) + { + rxx[i] = 0.0; + for(j=0; j < N-i; j++) + rxx[i] += s[j]*s[j+i]; + } +} + + + + +// SOUND PARAMETERS +// w Lisp vector containinig signal values +// P number of poles +// N length of sound + +// AUTOCORRELEATION PARAMETERS +// rxx array containing autocorrelation coefs +// max_rxx temporal maximun value of rxx +// i_max index of max_rxx + +// LPC PARAMETERS +// alpha array of filter coefs +// k reflection coef +// E residual energy +// rms1 energy of input signal (not RMS) +// rms2 residual energy = E +// unv voiced/unvoiced parameter = ERR = rms2/rms1 + +// PITCH DETECTION ALGORITHM: Implemented separately + + + +LVAL snd_lpanal(LVAL w, long P) +{ + + double *s, *rxx; + long N; + double *alpha; + // double *k, *E; THIS ONLY FOR VECTORIZED k AND E + double k, E; + double rms1; // rms2=E; + double unv; + double suma, alphatemp; // help variables + + + long i,j; + LVAL result; + + xlsave1(result); + + + + //// end vars ///////////// + + + + //// allocate memory /////// + N = getsize(w); + s = calloc(sizeof(double),N); //signal + rxx = calloc(sizeof(double),N); //autocorrelation + alpha = calloc(sizeof(double), P); // filter coefs + //k = calloc(sizeof(double), P); // reflection coefs + //E = calloc(sizeof(double), P); // residual energy + + + ////// copy Lisp array sound data to array of double /////// + for(i=0; i> 1); j++) + { + //alphatemp = alpha[j] - k[i] * alpha[i-j-1]; + //alpha[i-j-1] -= k[i] * alpha[j]; + //alpha[j] = alphatemp; + alphatemp = alpha[j] - k * alpha[i-j-1]; + alpha[i-j-1] -= k * alpha[j]; + alpha[j] = alphatemp; + + } + //E[i] = E[i-1] * (1 - pow(k[i],2)); + E *= (1 - pow(k,2)); + + } + + // input signal energy = rxx[0]; + rms1 = rxx[0]; + + // voiced/unvoiced + unv= sqrt(E/rms1); + + ///// HERE: CHECK STABILITY AND MODIFY COEFS ///////////// + ///// not implemented + + + + // prepare output result + result = newvector(P); + for (i = 0; i < P; i++) setelement(result, i, cvflonum(alpha[P-i-1])); // alpoles format + + xlpop(); + + // free memory + free(s); free(rxx); free(alpha); + + return (cons (cvflonum(rms1), // input signal energy + cons(cvflonum(E), // residual energy + cons(cvflonum(unv), // ERR, voiced/unvoiced + cons(result, NULL))))); // coefs + +} diff --git a/lpc/src/lpanal.h b/lpc/src/lpanal.h new file mode 100644 index 0000000..3236f7b --- /dev/null +++ b/lpc/src/lpanal.h @@ -0,0 +1,5 @@ +/* lpanal.h -- LPC analysis */ + +LVAL snd_lpanal (LVAL v, long P); + + /* LISP: (SND-LPC ANY FIXNUM) */ diff --git a/lpc/src/lpreson.alg b/lpc/src/lpreson.alg new file mode 100644 index 0000000..9d66c6c --- /dev/null +++ b/lpc/src/lpreson.alg @@ -0,0 +1,104 @@ +(LPRESON-ALG +(NAME "lpreson") +(ARGUMENTS ("sound_type" "x_snd")("LVAL" "src")("time_type" "frame_time")) +(SUPPORT-FUNCTIONS " + #include \"samples.h\" +") +(START (MIN x_snd)) +(ALWAYS-SCALE x_snd) +(TERMINATE (MIN x_snd)) +(LOGICAL-STOP (MIN x_snd)) +(SAMPLE-RATE "x_snd->sr") +(STATE + ("long" "fr_indx" "0") + ("long" "ak_len" "0") ; length of coefs ak array + ("long" "frame_length" "(long) (frame_time*x_snd->sr)") ; samples length + ("LVAL" "src" "src") + ("LVAL" "array" "NULL") + ("double *" "ak_coefs" "NULL") ; coefs array + ("double *" "zk_buf" "NULL") ; last values of output + ("double" "gain" "1.0") + ("long" "index" "0") + + ) + +(OUTER-LOOP " + if (susp->src == NULL) { +out: togo = 0; /* indicate termination */ + break; /* we're done */ + } + + if(susp->fr_indx >= susp->frame_length) + susp->fr_indx -= susp->frame_length; + + if (susp->fr_indx==0) + { + long i; + susp->array = xleval(cons(s_send, cons(susp->src, consa(s_next)))); + if (susp->array == NULL) { + susp->src = NULL; + goto out; + } +/* en susp->array tenemos la lista proporcionada por el objeto */ + else if (!listp(susp->array)) + xlerror(\"list expected\", susp->array); + + susp->gain = getflonum(car(susp->array)); + susp->array=car(cdr(susp->array)); + if (!vectorp(susp->array)) { + xlerror(\"array expected\", susp->array); + } + else if (susp->ak_coefs == NULL) { + susp->ak_len = getsize(susp->array); + if (susp->ak_len < 1) xlerror(\"array has no elements\", susp->array); + susp->ak_coefs = (double *) calloc(susp->ak_len, sizeof(double)); + susp->zk_buf = (double *) calloc(susp->ak_len, sizeof(double)); + } + /* at this point we have a new array and a place to put ak coefs */ + + for(i=0; i < susp->ak_len; i++) { + LVAL elem = getelement(susp->array,i); + if (ntype(elem) != FLONUM) { + xlerror(\"flonum expected\", elem); + } + susp->ak_coefs[i] = getflonum(elem); + } + + // printf(\"NUEVO FILTRO: \"); /* here for debug */ + // for(k=0; k < susp->ak_len; k++) printf(\" %g \", susp->ak_coefs[k]); + // printf(\"GAIN %g AKLEN %d \", susp->gain, susp->ak_len); + + + + susp->array = NULL; /* free the array */ + + +} + + togo = min(susp->frame_length - susp->fr_indx, togo); + +") + +(INNER-LOOP-LOCALS "double z0; long xi; long xj;") + +(INNER-LOOP " + z0 = x_snd * gain; + for (xi=0; xi < ak_len; xi++) { + xj = index + xi; if (xj >= ak_len) xj -= ak_len; + z0 += ak_coefs[xi] * zk_buf[xj]; + } + zk_buf[index] = z0; + index++; if (index == ak_len) index = 0; + fr_indx++; + output = (sample_type) z0; +") + +(CONSTANT "frame_length" "src") + +(FINALIZATION " free(susp->ak_coefs); + free(susp->zk_buf); +") + +) + + diff --git a/macosxproject/.DS_Store b/macosxproject/.DS_Store new file mode 100644 index 0000000..b60d825 Binary files /dev/null and b/macosxproject/.DS_Store differ diff --git a/macosxproject/Nyquist.icns b/macosxproject/Nyquist.icns new file mode 100644 index 0000000..efa9a7e Binary files /dev/null and b/macosxproject/Nyquist.icns differ diff --git a/macosxproject/NyquistIDE-Info.plist b/macosxproject/NyquistIDE-Info.plist new file mode 100644 index 0000000..05427a4 --- /dev/null +++ b/macosxproject/NyquistIDE-Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + NyquistIDE + CFBundleIconFile + Nyquist.icns + CFBundleIdentifier + edu.cmu.cs.nyquist + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + NyquistIDE + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CFBundleShortVersionString + 1.0 + Java + + ClassPath + $JAVAROOT/jnyqide.jar + JVMVersion + 1.5+ + MainClass + jnyqide.Main + WorkingDirectory + $JAVAROOT + Properties + + apple.laf.useScreenMenuBar + true + + + + diff --git a/macosxproject/README.txt b/macosxproject/README.txt new file mode 100644 index 0000000..3454958 --- /dev/null +++ b/macosxproject/README.txt @@ -0,0 +1 @@ +See ../sys/mac/README.txt diff --git a/macosxproject/alternate.icns b/macosxproject/alternate.icns new file mode 100644 index 0000000..8867742 Binary files /dev/null and b/macosxproject/alternate.icns differ diff --git a/macosxproject/nycon2008.gif b/macosxproject/nycon2008.gif new file mode 100644 index 0000000..cca898d Binary files /dev/null and b/macosxproject/nycon2008.gif differ diff --git a/macosxproject/nycon2008.png b/macosxproject/nycon2008.png new file mode 100644 index 0000000..5f1b542 Binary files /dev/null and b/macosxproject/nycon2008.png differ diff --git a/macosxproject/nycon2008.xcf b/macosxproject/nycon2008.xcf new file mode 100644 index 0000000..0038ba8 Binary files /dev/null and b/macosxproject/nycon2008.xcf differ diff --git a/macosxproject/nyquist.pbproj/project.pbxproj b/macosxproject/nyquist.pbproj/project.pbxproj new file mode 100644 index 0000000..f2bdacd --- /dev/null +++ b/macosxproject/nyquist.pbproj/project.pbxproj @@ -0,0 +1,6120 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 38; + objects = { + 014CEA520018CE5811CA2923 = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = NO; + OPTIMIZATION_CFLAGS = "-O0"; + }; + isa = PBXBuildStyle; + name = Development; + }; + 014CEA530018CE5811CA2923 = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = YES; + DEPLOYMENT_LOCATION = YES; + DEPLOYMENT_POSTPROCESSING = YES; + DSTROOT = /Users/rbd/tmp; + }; + isa = PBXBuildStyle; + name = Deployment; + }; +//010 +//011 +//012 +//013 +//014 +//030 +//031 +//032 +//033 +//034 + 034768E8FF38A79811DB9C8B = { + isa = PBXExecutableFileReference; + path = ny; + refType = 3; + }; +//030 +//031 +//032 +//033 +//034 +//080 +//081 +//082 +//083 +//084 + 08FB7793FE84155DC02AAC07 = { + buildStyles = ( + 014CEA520018CE5811CA2923, + 014CEA530018CE5811CA2923, + ); + hasScannedForEncodings = 1; + isa = PBXProject; + mainGroup = 08FB7794FE84155DC02AAC07; + projectDirPath = ""; + targets = ( + 08FB779FFE84155DC02AAC07, + F5C6A9B703A10C0501029006, + 3DF21F2604FD4FDC0002CE69, + ); + }; + 08FB7794FE84155DC02AAC07 = { + children = ( + F5DA143903A1108C01029006, + F510BDB903A0314301029006, + F543F19F0375E1E401029006, + 1AB674ADFE9D54B511CA2CBB, + 3DA446C00789FF350002CE69, + 3DA446C20789FF430002CE69, + 3D676BB907CE68A90002CE69, + ); + isa = PBXGroup; + name = MacOSXProject; + refType = 4; + }; + 08FB7795FE84155DC02AAC07 = { + children = ( + 3D9E08110779F7050002CE69, + 3D9E07E60779F63A0002CE69, + F510BCA7039F84FD01029006, + F510BCDA039F84FE01029006, + F510BD73039FB49C01029006, + F5FF5F48039D84B901029006, + F5FF5F9E039D863401029006, + F543EE570375CD5801029006, + 3D35A7C405690E180002CE69, + F5FF60A6039D87B001029006, + F543EF940375CD8D01029006, + F543EF3D0375CD7101029006, + F543EF990375CD9901029006, + 3DF21F3104FD526A0002CE69, + ); + isa = PBXGroup; + name = nyquist; + path = ..; + refType = 2; + }; + 08FB779FFE84155DC02AAC07 = { + buildPhases = ( + 08FB77A0FE84155DC02AAC07, + 08FB77A1FE84155DC02AAC07, + 08FB77A3FE84155DC02AAC07, + 08FB77A5FE84155DC02AAC07, + C6A0FF2D029079AD04C91782, + ); + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ""; + HEADER_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers\" ../fft ../snd ../cmt ../sys/unix ../xlisp ../tran ../nyqsrc ../nyqstk/include ../pa/pa_common"; + LIBRARY_SEARCH_PATHS = ""; + OPTIMIZATION_CFLAGS = "-O3"; + OTHER_CFLAGS = "-DCMTSTUFF -Dmacintosh -DPA_USE_COREAUDIO"; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = ny; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXToolTarget; + name = Nyquist; + productName = MacOSXProject; + productReference = 034768E8FF38A79811DB9C8B; + }; + 08FB77A0FE84155DC02AAC07 = { + buildActionMask = 2147483647; + files = ( + F543EF980375CD8D01029006, + F5FF5F84039D84DB01029006, + F5FF5F86039D84DF01029006, + F5FF5F92039D850B01029006, + F5FF6010039D866201029006, + F5FF6012039D866201029006, + F5FF6014039D866201029006, + F5FF6016039D866201029006, + F5FF6018039D866201029006, + F5FF601A039D866201029006, + F5FF601C039D866201029006, + F5FF601E039D866201029006, + F5FF6020039D866201029006, + F5FF6022039D866201029006, + F5FF6024039D866201029006, + F5FF6026039D866201029006, + F5FF6028039D866201029006, + F5FF602A039D866201029006, + F5FF602C039D866201029006, + F5FF6030039D866201029006, + F5FF6034039D866201029006, + F5FF6036039D866201029006, + F5FF6038039D866201029006, + F5FF603A039D866201029006, + F5FF603C039D866201029006, + F5FF603E039D866201029006, + F5FF6040039D866201029006, + F5FF6042039D866201029006, + F5FF6044039D866201029006, + F5FF6046039D866201029006, + F5FF6048039D866201029006, + F5FF604A039D866201029006, + F5FF604C039D866201029006, + F5FF604E039D866201029006, + F5FF6050039D866201029006, + F5FF6052039D866201029006, + F5FF6054039D866201029006, + F5FF6056039D866201029006, + F5FF605A039D866201029006, + F5FF605C039D866201029006, + F5FF605E039D866201029006, + F5FF6060039D866201029006, + F5FF6062039D866201029006, + F5FF6064039D866201029006, + F5FF6066039D866201029006, + F5FF6068039D866201029006, + F5FF606A039D866201029006, + F5FF606C039D866201029006, + F5FF606E039D866201029006, + F5FF6070039D866201029006, + F5FF6072039D866201029006, + F5FF6074039D866201029006, + F5FF6076039D866201029006, + F5FF6078039D866201029006, + F5FF607A039D866201029006, + F5FF607C039D866201029006, + F5FF6085039D871B01029006, + F5FF6087039D871E01029006, + F5FF6089039D872001029006, + F5FF608B039D872301029006, + F5FF608D039D873001029006, + F5FF608F039D873501029006, + F5FF6091039D874001029006, + F5FF6093039D874101029006, + F5FF6095039D874601029006, + F5FF6097039D874E01029006, + F5FF6099039D875301029006, + F5FF609C039D875F01029006, + F5FF609D039D876001029006, + F5FF609F039D876401029006, + F5FF60A1039D876B01029006, + F5FF60A3039D876D01029006, + F5FF60A5039D876F01029006, + F5FF612E039D87DC01029006, + F5FF6130039D87E101029006, + F5FF6132039D87E601029006, + F5FF6135039D87EF01029006, + F5FF613A039D87FE01029006, + F5FF613B039D880001029006, + F5FF613D039D880401029006, + F5FF613F039D880901029006, + F5FF6141039D880E01029006, + F5FF6143039D881C01029006, + F5FF6145039D882001029006, + F5FF6147039D882901029006, + F5FF6149039D884301029006, + F5FF614B039D885401029006, + F5FF614F039D885D01029006, + F5FF6151039D886201029006, + F5FF6153039D886D01029006, + F5FF6155039D887501029006, + F5FF6157039D887B01029006, + F5FF6159039D888201029006, + F5FF615B039D888601029006, + F5FF6160039D899F01029006, + F5FF6161039D899F01029006, + F5FF6166039D89B101029006, + F5FF6167039D89B101029006, + F5FF616C039D8A5401029006, + F5FF6172039D8A6C01029006, + F5779DA4039D8E1901029006, + F5779DB1039D99D901029006, + 3D9867CF04FFDD6B0002CE69, + 3D9867DA050920140002CE69, + 3D9867DC0509202C0002CE69, + 3D9867E0050920400002CE69, + 3D9867E4050920730002CE69, + 3D9E07DF0779F4800002CE69, + 3D9E07E30779F4DC0002CE69, + 3D9E07FC0779F6820002CE69, + 3D9E07FE0779F6820002CE69, + 3D9E08000779F6820002CE69, + 3D9E08020779F6820002CE69, + 3D9E08030779F6820002CE69, + 3D9E08050779F6820002CE69, + 3D9E08070779F6820002CE69, + 3D9E080A0779F6820002CE69, + 3D9E080C0779F6820002CE69, + 3D9E080D0779F6820002CE69, + 3D9E080E0779F6820002CE69, + 3D9E08130779F7370002CE69, + 3D9E08150779F74D0002CE69, + 3D9E08230779F7680002CE69, + 3D9E08240779F7680002CE69, + 3D9E08250779F7680002CE69, + 3D9E08260779F7680002CE69, + 3D9E08270779F7680002CE69, + 3D9E08280779F7680002CE69, + 3D9E08290779F7680002CE69, + 3D9E082A0779F7680002CE69, + 3D9E082B0779F7680002CE69, + 3D9E082D0779F7680002CE69, + 3D9E082E0779F7680002CE69, + 3D9E082F0779F7680002CE69, + 3D9E08330779F78B0002CE69, + 3D9E0851077C6FC00002CE69, + 3D9E086D0789D6000002CE69, + 3D9E08710789D81B0002CE69, + 3D9E08750789D82F0002CE69, + 3D9E08790789D8520002CE69, + 3D9E087D0789D8B20002CE69, + 3D9E08810789D8CF0002CE69, + 3D9E08850789D8E70002CE69, + 3D9E08890789D9100002CE69, + 3D9E088D0789D9230002CE69, + 3D9E08910789D9430002CE69, + 3D9E08950789D9680002CE69, + 3D6032F40790A48F007A3CA5, + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 08FB77A1FE84155DC02AAC07 = { + buildActionMask = 2147483647; + files = ( + F543EF970375CD8D01029006, + F543F0100375CD9901029006, + F5FF5F83039D84DB01029006, + F5FF5F85039D84DF01029006, + F5FF5F87039D84E301029006, + F5FF5F88039D84E801029006, + F5FF5F89039D84EF01029006, + F5FF5F8A039D84F301029006, + F5FF5F8B039D84F701029006, + F5FF5F8C039D84FB01029006, + F5FF5F8D039D84FE01029006, + F5FF5F8E039D850301029006, + F5FF5F8F039D850701029006, + F5FF5F90039D850801029006, + F5FF5F91039D850A01029006, + F5FF5F93039D850E01029006, + F5FF5F94039D851101029006, + F5FF5F95039D851201029006, + F5FF5F96039D851501029006, + F5FF5F97039D851801029006, + F5FF5F98039D851A01029006, + F5FF5F99039D851D01029006, + F5FF5F9A039D852201029006, + F5FF5F9B039D852301029006, + F5FF5F9C039D852401029006, + F5FF5F9D039D852601029006, + F5FF600F039D866201029006, + F5FF6011039D866201029006, + F5FF6013039D866201029006, + F5FF6015039D866201029006, + F5FF6017039D866201029006, + F5FF6019039D866201029006, + F5FF601B039D866201029006, + F5FF601D039D866201029006, + F5FF601F039D866201029006, + F5FF6021039D866201029006, + F5FF6023039D866201029006, + F5FF6025039D866201029006, + F5FF6027039D866201029006, + F5FF6029039D866201029006, + F5FF602B039D866201029006, + F5FF602F039D866201029006, + F5FF6033039D866201029006, + F5FF6035039D866201029006, + F5FF6037039D866201029006, + F5FF6039039D866201029006, + F5FF603B039D866201029006, + F5FF603D039D866201029006, + F5FF603F039D866201029006, + F5FF6041039D866201029006, + F5FF6043039D866201029006, + F5FF6045039D866201029006, + F5FF6047039D866201029006, + F5FF6049039D866201029006, + F5FF604B039D866201029006, + F5FF604D039D866201029006, + F5FF604F039D866201029006, + F5FF6051039D866201029006, + F5FF6053039D866201029006, + F5FF6055039D866201029006, + F5FF6059039D866201029006, + F5FF605B039D866201029006, + F5FF605D039D866201029006, + F5FF605F039D866201029006, + F5FF6061039D866201029006, + F5FF6063039D866201029006, + F5FF6065039D866201029006, + F5FF6067039D866201029006, + F5FF6069039D866201029006, + F5FF606B039D866201029006, + F5FF606D039D866201029006, + F5FF606F039D866201029006, + F5FF6071039D866201029006, + F5FF6073039D866201029006, + F5FF6075039D866201029006, + F5FF6077039D866201029006, + F5FF6079039D866201029006, + F5FF607B039D866201029006, + F5FF6084039D871B01029006, + F5FF6086039D871D01029006, + F5FF6088039D872001029006, + F5FF608A039D872301029006, + F5FF608C039D872E01029006, + F5FF608E039D873401029006, + F5FF6090039D873F01029006, + F5FF6092039D874101029006, + F5FF6094039D874501029006, + F5FF6096039D874D01029006, + F5FF6098039D875201029006, + F5FF609A039D875B01029006, + F5FF609B039D875E01029006, + F5FF609E039D876301029006, + F5FF60A0039D876B01029006, + F5FF60A2039D876C01029006, + F5FF60A4039D876F01029006, + F5FF612D039D87DC01029006, + F5FF612F039D87E001029006, + F5FF6131039D87E401029006, + F5FF6133039D87E801029006, + F5FF6134039D87EE01029006, + F5FF6136039D87F301029006, + F5FF6138039D87F801029006, + F5FF6139039D87FD01029006, + F5FF613C039D880301029006, + F5FF613E039D880801029006, + F5FF6140039D880D01029006, + F5FF6142039D881B01029006, + F5FF6144039D881F01029006, + F5FF6146039D882701029006, + F5FF6148039D884201029006, + F5FF614A039D885301029006, + F5FF614C039D885701029006, + F5FF614E039D885C01029006, + F5FF6150039D886101029006, + F5FF6152039D886C01029006, + F5FF6154039D887401029006, + F5FF6156039D887A01029006, + F5FF6158039D888101029006, + F5FF615A039D888601029006, + F5FF615F039D899F01029006, + F5FF6165039D89B101029006, + F5FF616A039D8A3701029006, + F5FF616F039D8A5C01029006, + F5FF6170039D8A6601029006, + F5FF6171039D8A6B01029006, + F5779DA8039D8E9501029006, + F5779DB2039D99DA01029006, + 3D9867CD04FFDD3C0002CE69, + 3D9867D104FFDDA30002CE69, + 3D9867D204FFDDAC0002CE69, + 3D9867D404FFE8E20002CE69, + 3D9867D605091F760002CE69, + 3D9867D8050920060002CE69, + 3D9867DF050920400002CE69, + 3D9867E3050920730002CE69, + 3D9867E6050921720002CE69, + 3D9E07DE0779F4800002CE69, + 3D9E07E20779F4DC0002CE69, + 3D9E07E50779F61B0002CE69, + 3D9E07FB0779F6820002CE69, + 3D9E07FD0779F6820002CE69, + 3D9E07FF0779F6820002CE69, + 3D9E08010779F6820002CE69, + 3D9E08040779F6820002CE69, + 3D9E08060779F6820002CE69, + 3D9E08080779F6820002CE69, + 3D9E08090779F6820002CE69, + 3D9E080B0779F6820002CE69, + 3D9E08100779F6A20002CE69, + 3D9E08320779F78B0002CE69, + 3D9E08350779F7A30002CE69, + 3D9E08420779F7B80002CE69, + 3D9E08430779F7B80002CE69, + 3D9E08440779F7B80002CE69, + 3D9E08450779F7B80002CE69, + 3D9E08460779F7B80002CE69, + 3D9E08470779F7B80002CE69, + 3D9E08480779F7B80002CE69, + 3D9E08490779F7B80002CE69, + 3D9E084A0779F7B80002CE69, + 3D9E084B0779F7B80002CE69, + 3D9E084C0779F7B80002CE69, + 3D9E084D0779F7B80002CE69, + 3D9E0850077C6FC00002CE69, + 3D9E086C0789D6000002CE69, + 3D9E08700789D81B0002CE69, + 3D9E08740789D82F0002CE69, + 3D9E08780789D8520002CE69, + 3D9E087C0789D8B20002CE69, + 3D9E08800789D8CF0002CE69, + 3D9E08840789D8E70002CE69, + 3D9E08880789D9100002CE69, + 3D9E088C0789D9230002CE69, + 3D9E08900789D9430002CE69, + 3D9E08940789D9680002CE69, + 3D9E08970789D9E30002CE69, + 3D6032F30790A48F007A3CA5, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 08FB77A3FE84155DC02AAC07 = { + buildActionMask = 2147483647; + files = ( + 3DA446C10789FF350002CE69, + 3DA446C30789FF430002CE69, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 08FB77A5FE84155DC02AAC07 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; +//080 +//081 +//082 +//083 +//084 +//1A0 +//1A1 +//1A2 +//1A3 +//1A4 + 1AB674ADFE9D54B511CA2CBB = { + children = ( + 034768E8FF38A79811DB9C8B, + F5C6A9B803A10C0501029006, + 3DF21F2704FD4FDC0002CE69, + ); + isa = PBXGroup; + name = Products; + refType = 4; + }; +//1A0 +//1A1 +//1A2 +//1A3 +//1A4 +//3D0 +//3D1 +//3D2 +//3D3 +//3D4 + 3D35A7C405690E180002CE69 = { + children = ( + 3D35A7C505690E180002CE69, + 3D6032F50790A600007A3CA5, + 3D35A7C605690E180002CE69, + 3D35A7C705690E180002CE69, + 3D35A7C805690E180002CE69, + 3D35A7C905690E180002CE69, + 3D35A7CA05690E180002CE69, + 3D6032F80790A618007A3CA5, + 3D35A7CB05690E180002CE69, + 3D35A7CC05690E180002CE69, + 3D35A7CD05690E180002CE69, + 3D35A7CE05690E180002CE69, + 3D35A7CF05690E180002CE69, + 3D35A7D005690E180002CE69, + 3D35A7D105690E180002CE69, + 3D6032FA0790A62C007A3CA5, + 3D35A7D205690E180002CE69, + 3D35A7D305690E180002CE69, + 3D36DDE60796D6D40002CE69, + ); + isa = PBXGroup; + path = jnyqide; + refType = 4; + }; + 3D35A7C505690E180002CE69 = { + isa = PBXFileReference; + path = closeFile.gif; + refType = 4; + }; + 3D35A7C605690E180002CE69 = { + isa = PBXFileReference; + path = help.gif; + refType = 4; + }; + 3D35A7C705690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = LispFileFilter.java; + refType = 4; + }; + 3D35A7C805690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = Main.java; + refType = 4; + }; + 3D35A7C905690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = MainFrame.java; + refType = 4; + }; + 3D35A7CA05690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = MainFrame_AboutBox.java; + refType = 4; + }; + 3D35A7CB05690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = NyqPlot.java; + refType = 4; + }; + 3D35A7CC05690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = NyquistFile.java; + refType = 4; + }; + 3D35A7CD05690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = NyquistThread.java; + refType = 4; + }; + 3D35A7CE05690E180002CE69 = { + isa = PBXFileReference; + path = openFile.gif; + refType = 4; + }; + 3D35A7CF05690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = Pair.java; + refType = 4; + }; + 3D35A7D005690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = PlotFrame.java; + refType = 4; + }; + 3D35A7D105690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = PlotMouseAdapter.java; + refType = 4; + }; + 3D35A7D205690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = SyntaxThread.java; + refType = 4; + }; + 3D35A7D305690E180002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = TextColor.java; + refType = 4; + }; + 3D35A7D405690E180002CE69 = { + fileRef = 3D35A7C505690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7D505690E180002CE69 = { + fileRef = 3D35A7C605690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7D605690E180002CE69 = { + fileRef = 3D35A7C705690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7D705690E180002CE69 = { + fileRef = 3D35A7C805690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7D805690E180002CE69 = { + fileRef = 3D35A7C905690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7D905690E180002CE69 = { + fileRef = 3D35A7CA05690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7DA05690E180002CE69 = { + fileRef = 3D35A7CB05690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7DB05690E180002CE69 = { + fileRef = 3D35A7CC05690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7DC05690E180002CE69 = { + fileRef = 3D35A7CD05690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7DD05690E180002CE69 = { + fileRef = 3D35A7CE05690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7DE05690E180002CE69 = { + fileRef = 3D35A7CF05690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7DF05690E180002CE69 = { + fileRef = 3D35A7D005690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7E005690E180002CE69 = { + fileRef = 3D35A7D105690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7E105690E180002CE69 = { + fileRef = 3D35A7D205690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D35A7E205690E180002CE69 = { + fileRef = 3D35A7D305690E180002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D36DDE60796D6D40002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = keywords.txt; + refType = 4; + }; + 3D36DDE70796D6D40002CE69 = { + fileRef = 3D36DDE60796D6D40002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D36DDEC0796D71B0002CE69 = { + fileRef = F510BD73039FB49C01029006; + isa = PBXBuildFile; + settings = { + }; + }; + 3D36DDED0796E1AB0002CE69 = { + fileRef = F510BCDA039F84FE01029006; + isa = PBXBuildFile; + settings = { + }; + }; + 3D36DDEE0796E5CA0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = run; + path = osx/run; + refType = 4; + }; + 3D36DDEF0796E5CA0002CE69 = { + fileRef = 3D36DDEE0796E5CA0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D36DDF00796E5DE0002CE69 = { + children = ( + 3D36DDEE0796E5CA0002CE69, + 3D36DDF20796E60F0002CE69, + ); + isa = PBXGroup; + name = osx; + refType = 4; + }; + 3D36DDF10796E5E80002CE69 = { + fileRef = 3D36DDEE0796E5CA0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D36DDF20796E60F0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = system.lsp; + path = osx/system.lsp; + refType = 4; + }; + 3D36DDF30796E60F0002CE69 = { + fileRef = 3D36DDF20796E60F0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D36DDF40796E6170002CE69 = { + fileRef = 3D36DDF20796E60F0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D6032F10790A48F007A3CA5 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ringofframes.c; + path = portaudio/pa_mac_core/ringofframes.c; + refType = 4; + }; + 3D6032F20790A48F007A3CA5 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ringofframes.h; + path = portaudio/pa_mac_core/ringofframes.h; + refType = 4; + }; + 3D6032F30790A48F007A3CA5 = { + fileRef = 3D6032F10790A48F007A3CA5; + isa = PBXBuildFile; + settings = { + }; + }; + 3D6032F40790A48F007A3CA5 = { + fileRef = 3D6032F20790A48F007A3CA5; + isa = PBXBuildFile; + settings = { + }; + }; + 3D6032F50790A600007A3CA5 = { + fileEncoding = 30; + isa = PBXFileReference; + path = FindDialog.java; + refType = 4; + }; + 3D6032F60790A600007A3CA5 = { + fileRef = 3D6032F50790A600007A3CA5; + isa = PBXBuildFile; + settings = { + }; + }; + 3D6032F80790A618007A3CA5 = { + fileEncoding = 30; + isa = PBXFileReference; + path = NotFoundDialog.java; + refType = 4; + }; + 3D6032F90790A618007A3CA5 = { + fileRef = 3D6032F80790A618007A3CA5; + isa = PBXBuildFile; + settings = { + }; + }; + 3D6032FA0790A62C007A3CA5 = { + fileEncoding = 30; + isa = PBXFileReference; + path = ReplaceDialog.java; + refType = 4; + }; + 3D6032FB0790A62C007A3CA5 = { + fileRef = 3D6032FA0790A62C007A3CA5; + isa = PBXBuildFile; + settings = { + }; + }; + 3D676BB907CE68A90002CE69 = { + fileEncoding = 4; + isa = PBXFileReference; + name = xlisppath; + path = /Users/rbd/nyquist/xlisppath; + refType = 0; + }; + 3D9867CC04FFDD3C0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tapf.c; + refType = 4; + }; + 3D9867CD04FFDD3C0002CE69 = { + fileRef = 3D9867CC04FFDD3C0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867CE04FFDD6B0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tapf.h; + refType = 4; + }; + 3D9867CF04FFDD6B0002CE69 = { + fileRef = 3D9867CE04FFDD6B0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867D104FFDDA30002CE69 = { + fileRef = F53626EE03761E6C01029006; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867D204FFDDAC0002CE69 = { + fileRef = F543EF4A0375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867D304FFE8E20002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = term.c; + refType = 4; + }; + 3D9867D404FFE8E20002CE69 = { + fileRef = 3D9867D304FFE8E20002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867D505091F760002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = yin.c; + refType = 4; + }; + 3D9867D605091F760002CE69 = { + fileRef = 3D9867D505091F760002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867D7050920060002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = alpasscv.c; + path = ../tran/alpasscv.c; + refType = 4; + }; + 3D9867D8050920060002CE69 = { + fileRef = 3D9867D7050920060002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867D9050920140002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = yin.h; + refType = 4; + }; + 3D9867DA050920140002CE69 = { + fileRef = 3D9867D9050920140002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867DB0509202C0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = alpasscv.h; + path = ../tran/alpasscv.h; + refType = 4; + }; + 3D9867DC0509202C0002CE69 = { + fileRef = 3D9867DB0509202C0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867DD050920400002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = alpassvv.c; + path = ../tran/alpassvv.c; + refType = 4; + }; + 3D9867DE050920400002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = alpassvv.h; + path = ../tran/alpassvv.h; + refType = 4; + }; + 3D9867DF050920400002CE69 = { + fileRef = 3D9867DD050920400002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867E0050920400002CE69 = { + fileRef = 3D9867DE050920400002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867E1050920730002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = eqbandvvv.c; + path = ../tran/eqbandvvv.c; + refType = 4; + }; + 3D9867E2050920730002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = eqbandvvv.h; + path = ../tran/eqbandvvv.h; + refType = 4; + }; + 3D9867E3050920730002CE69 = { + fileRef = 3D9867E1050920730002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867E4050920730002CE69 = { + fileRef = 3D9867E2050920730002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9867E5050921720002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = path.c; + path = ../xlisp/path.c; + refType = 4; + }; + 3D9867E6050921720002CE69 = { + fileRef = 3D9867E5050921720002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07DC0779F4800002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = convolve.c; + refType = 4; + }; + 3D9E07DD0779F4800002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = convolve.h; + refType = 4; + }; + 3D9E07DE0779F4800002CE69 = { + fileRef = 3D9E07DC0779F4800002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07DF0779F4800002CE69 = { + fileRef = 3D9E07DD0779F4800002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07E00779F4DC0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = delaycc.c; + refType = 4; + }; + 3D9E07E10779F4DC0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = delaycc.h; + refType = 4; + }; + 3D9E07E20779F4DC0002CE69 = { + fileRef = 3D9E07E00779F4DC0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07E30779F4DC0002CE69 = { + fileRef = 3D9E07E10779F4DC0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07E40779F61B0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_mac_hostapis.c; + path = portaudio/pa_mac/pa_mac_hostapis.c; + refType = 4; + }; + 3D9E07E50779F61B0002CE69 = { + fileRef = 3D9E07E40779F61B0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07E60779F63A0002CE69 = { + children = ( + 3D9E07E70779F6820002CE69, + 3D9E07E80779F6820002CE69, + 3D9E07E90779F6820002CE69, + 3D9E07EA0779F6820002CE69, + 3D9E07EB0779F6820002CE69, + 3D9E07EC0779F6820002CE69, + 3D9E07ED0779F6820002CE69, + 3D9E07EE0779F6820002CE69, + 3D9E07EF0779F6820002CE69, + 3D9E07F00779F6820002CE69, + 3D9E07F10779F6820002CE69, + 3D9E07F20779F6820002CE69, + 3D9E07F30779F6820002CE69, + 3D9E07F40779F6820002CE69, + 3D9E07F50779F6820002CE69, + 3D9E07F60779F6820002CE69, + 3D9E07F70779F6820002CE69, + 3D9E07F80779F6820002CE69, + 3D9E07F90779F6820002CE69, + 3D9E07FA0779F6820002CE69, + 3D9E080F0779F6A20002CE69, + 3D9E07E40779F61B0002CE69, + 3D6032F10790A48F007A3CA5, + 3D6032F20790A48F007A3CA5, + ); + isa = PBXGroup; + name = portaudio; + refType = 4; + }; + 3D9E07E70779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_allocation.c; + path = portaudio/pa_common/pa_allocation.c; + refType = 4; + }; + 3D9E07E80779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_allocation.h; + path = portaudio/pa_common/pa_allocation.h; + refType = 4; + }; + 3D9E07E90779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_converters.c; + path = portaudio/pa_common/pa_converters.c; + refType = 4; + }; + 3D9E07EA0779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_converters.h; + path = portaudio/pa_common/pa_converters.h; + refType = 4; + }; + 3D9E07EB0779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_cpuload.c; + path = portaudio/pa_common/pa_cpuload.c; + refType = 4; + }; + 3D9E07EC0779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_cpuload.h; + path = portaudio/pa_common/pa_cpuload.h; + refType = 4; + }; + 3D9E07ED0779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_dither.c; + path = portaudio/pa_common/pa_dither.c; + refType = 4; + }; + 3D9E07EE0779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_dither.h; + path = portaudio/pa_common/pa_dither.h; + refType = 4; + }; + 3D9E07EF0779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_endianness.h; + path = portaudio/pa_common/pa_endianness.h; + refType = 4; + }; + 3D9E07F00779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_front.c; + path = portaudio/pa_common/pa_front.c; + refType = 4; + }; + 3D9E07F10779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_hostapi.h; + path = portaudio/pa_common/pa_hostapi.h; + refType = 4; + }; + 3D9E07F20779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_process.c; + path = portaudio/pa_common/pa_process.c; + refType = 4; + }; + 3D9E07F30779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_process.h; + path = portaudio/pa_common/pa_process.h; + refType = 4; + }; + 3D9E07F40779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_skeleton.c; + path = portaudio/pa_common/pa_skeleton.c; + refType = 4; + }; + 3D9E07F50779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_stream.c; + path = portaudio/pa_common/pa_stream.c; + refType = 4; + }; + 3D9E07F60779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_stream.h; + path = portaudio/pa_common/pa_stream.h; + refType = 4; + }; + 3D9E07F70779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_trace.c; + path = portaudio/pa_common/pa_trace.c; + refType = 4; + }; + 3D9E07F80779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_trace.h; + path = portaudio/pa_common/pa_trace.h; + refType = 4; + }; + 3D9E07F90779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_util.h; + path = portaudio/pa_common/pa_util.h; + refType = 4; + }; + 3D9E07FA0779F6820002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = portaudio.h; + path = portaudio/pa_common/portaudio.h; + refType = 4; + }; + 3D9E07FB0779F6820002CE69 = { + fileRef = 3D9E07E70779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07FC0779F6820002CE69 = { + fileRef = 3D9E07E80779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07FD0779F6820002CE69 = { + fileRef = 3D9E07E90779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07FE0779F6820002CE69 = { + fileRef = 3D9E07EA0779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E07FF0779F6820002CE69 = { + fileRef = 3D9E07EB0779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08000779F6820002CE69 = { + fileRef = 3D9E07EC0779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08010779F6820002CE69 = { + fileRef = 3D9E07ED0779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08020779F6820002CE69 = { + fileRef = 3D9E07EE0779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08030779F6820002CE69 = { + fileRef = 3D9E07EF0779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08040779F6820002CE69 = { + fileRef = 3D9E07F00779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08050779F6820002CE69 = { + fileRef = 3D9E07F10779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08060779F6820002CE69 = { + fileRef = 3D9E07F20779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08070779F6820002CE69 = { + fileRef = 3D9E07F30779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08080779F6820002CE69 = { + fileRef = 3D9E07F40779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08090779F6820002CE69 = { + fileRef = 3D9E07F50779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E080A0779F6820002CE69 = { + fileRef = 3D9E07F60779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E080B0779F6820002CE69 = { + fileRef = 3D9E07F70779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E080C0779F6820002CE69 = { + fileRef = 3D9E07F80779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E080D0779F6820002CE69 = { + fileRef = 3D9E07F90779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E080E0779F6820002CE69 = { + fileRef = 3D9E07FA0779F6820002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E080F0779F6A20002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_mac_core.c; + path = portaudio/pa_mac_core/pa_mac_core.c; + refType = 4; + }; + 3D9E08100779F6A20002CE69 = { + fileRef = 3D9E080F0779F6A20002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08110779F7050002CE69 = { + children = ( + 3D9E08120779F7370002CE69, + 3D9E08140779F74C0002CE69, + 3D9E08160779F7680002CE69, + 3D9E08170779F7680002CE69, + 3D9E08180779F7680002CE69, + 3D9E08190779F7680002CE69, + 3D9E081A0779F7680002CE69, + 3D9E081B0779F7680002CE69, + 3D9E081C0779F7680002CE69, + 3D9E081D0779F7680002CE69, + 3D9E081E0779F7680002CE69, + 3D9E081F0779F7680002CE69, + 3D9E08300779F78B0002CE69, + 3D9E08310779F78B0002CE69, + 3D9E08340779F7A30002CE69, + 3D9E08360779F7B80002CE69, + 3D9E08370779F7B80002CE69, + 3D9E08380779F7B80002CE69, + 3D9E08390779F7B80002CE69, + 3D9E083A0779F7B80002CE69, + 3D9E083B0779F7B80002CE69, + 3D9E083C0779F7B80002CE69, + 3D9E083D0779F7B80002CE69, + 3D9E083E0779F7B80002CE69, + 3D9E083F0779F7B80002CE69, + 3D9E08400779F7B80002CE69, + 3D9E08410779F7B80002CE69, + 3D9E084E077C6FC00002CE69, + 3D9E084F077C6FC00002CE69, + 3D9E08200779F7680002CE69, + 3D9E08210779F7680002CE69, + 3D9E08220779F7680002CE69, + ); + isa = PBXGroup; + name = stk; + refType = 4; + }; + 3D9E08120779F7370002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Clarinet.h; + path = nyqstk/include/Clarinet.h; + refType = 4; + }; + 3D9E08130779F7370002CE69 = { + fileRef = 3D9E08120779F7370002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08140779F74C0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = globals.h; + path = nyqstk/globals.h; + refType = 4; + }; + 3D9E08150779F74D0002CE69 = { + fileRef = 3D9E08140779F74C0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08160779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Delay.h; + path = nyqstk/include/Delay.h; + refType = 4; + }; + 3D9E08170779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DelayL.h; + path = nyqstk/include/DelayL.h; + refType = 4; + }; + 3D9E08180779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Envelope.h; + path = nyqstk/include/Envelope.h; + refType = 4; + }; + 3D9E08190779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Filter.h; + path = nyqstk/include/Filter.h; + refType = 4; + }; + 3D9E081A0779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Instrmnt.h; + path = nyqstk/include/Instrmnt.h; + refType = 4; + }; + 3D9E081B0779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Noise.h; + path = nyqstk/include/Noise.h; + refType = 4; + }; + 3D9E081C0779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = OneZero.h; + path = nyqstk/include/OneZero.h; + refType = 4; + }; + 3D9E081D0779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ReedTabl.h; + path = nyqstk/include/ReedTabl.h; + refType = 4; + }; + 3D9E081E0779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Saxofony.h; + path = nyqstk/include/Saxofony.h; + refType = 4; + }; + 3D9E081F0779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = SKINI.msg; + path = nyqstk/include/SKINI.msg; + refType = 4; + }; + 3D9E08200779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Stk.h; + path = nyqstk/include/Stk.h; + refType = 4; + }; + 3D9E08210779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = WaveLoop.h; + path = nyqstk/include/WaveLoop.h; + refType = 4; + }; + 3D9E08220779F7680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = WvIn.h; + path = nyqstk/include/WvIn.h; + refType = 4; + }; + 3D9E08230779F7680002CE69 = { + fileRef = 3D9E08160779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08240779F7680002CE69 = { + fileRef = 3D9E08170779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08250779F7680002CE69 = { + fileRef = 3D9E08180779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08260779F7680002CE69 = { + fileRef = 3D9E08190779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08270779F7680002CE69 = { + fileRef = 3D9E081A0779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08280779F7680002CE69 = { + fileRef = 3D9E081B0779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08290779F7680002CE69 = { + fileRef = 3D9E081C0779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E082A0779F7680002CE69 = { + fileRef = 3D9E081D0779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E082B0779F7680002CE69 = { + fileRef = 3D9E081E0779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E082C0779F7680002CE69 = { + fileRef = 3D9E081F0779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E082D0779F7680002CE69 = { + fileRef = 3D9E08200779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E082E0779F7680002CE69 = { + fileRef = 3D9E08210779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E082F0779F7680002CE69 = { + fileRef = 3D9E08220779F7680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08300779F78B0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instr.cpp; + path = nyqstk/instr.cpp; + refType = 4; + }; + 3D9E08310779F78B0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instr.h; + path = nyqstk/instr.h; + refType = 4; + }; + 3D9E08320779F78B0002CE69 = { + fileRef = 3D9E08300779F78B0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08330779F78B0002CE69 = { + fileRef = 3D9E08310779F78B0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08340779F7A30002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Clarinet.cpp; + path = nyqstk/src/Clarinet.cpp; + refType = 4; + }; + 3D9E08350779F7A30002CE69 = { + fileRef = 3D9E08340779F7A30002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08360779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Delay.cpp; + path = nyqstk/src/Delay.cpp; + refType = 4; + }; + 3D9E08370779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DelayL.cpp; + path = nyqstk/src/DelayL.cpp; + refType = 4; + }; + 3D9E08380779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Envelope.cpp; + path = nyqstk/src/Envelope.cpp; + refType = 4; + }; + 3D9E08390779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Filter.cpp; + path = nyqstk/src/Filter.cpp; + refType = 4; + }; + 3D9E083A0779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Instrmnt.cpp; + path = nyqstk/src/Instrmnt.cpp; + refType = 4; + }; + 3D9E083B0779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Noise.cpp; + path = nyqstk/src/Noise.cpp; + refType = 4; + }; + 3D9E083C0779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = OneZero.cpp; + path = nyqstk/src/OneZero.cpp; + refType = 4; + }; + 3D9E083D0779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ReedTabl.cpp; + path = nyqstk/src/ReedTabl.cpp; + refType = 4; + }; + 3D9E083E0779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Saxofony.cpp; + path = nyqstk/src/Saxofony.cpp; + refType = 4; + }; + 3D9E083F0779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Stk.cpp; + path = nyqstk/src/Stk.cpp; + refType = 4; + }; + 3D9E08400779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = WaveLoop.cpp; + path = nyqstk/src/WaveLoop.cpp; + refType = 4; + }; + 3D9E08410779F7B80002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = WvIn.cpp; + path = nyqstk/src/WvIn.cpp; + refType = 4; + }; + 3D9E08420779F7B80002CE69 = { + fileRef = 3D9E08360779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08430779F7B80002CE69 = { + fileRef = 3D9E08370779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08440779F7B80002CE69 = { + fileRef = 3D9E08380779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08450779F7B80002CE69 = { + fileRef = 3D9E08390779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08460779F7B80002CE69 = { + fileRef = 3D9E083A0779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08470779F7B80002CE69 = { + fileRef = 3D9E083B0779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08480779F7B80002CE69 = { + fileRef = 3D9E083C0779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08490779F7B80002CE69 = { + fileRef = 3D9E083D0779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E084A0779F7B80002CE69 = { + fileRef = 3D9E083E0779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E084B0779F7B80002CE69 = { + fileRef = 3D9E083F0779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E084C0779F7B80002CE69 = { + fileRef = 3D9E08400779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E084D0779F7B80002CE69 = { + fileRef = 3D9E08410779F7B80002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E084E077C6FC00002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = stkinit.cpp; + path = nyqstk/stkinit.cpp; + refType = 4; + }; + 3D9E084F077C6FC00002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = stkinit.h; + path = nyqstk/stkinit.h; + refType = 4; + }; + 3D9E0850077C6FC00002CE69 = { + fileRef = 3D9E084E077C6FC00002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E0851077C6FC00002CE69 = { + fileRef = 3D9E084F077C6FC00002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E086A0789D6000002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = lpanal.c; + refType = 4; + }; + 3D9E086B0789D6000002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = lpanal.h; + refType = 4; + }; + 3D9E086C0789D6000002CE69 = { + fileRef = 3D9E086A0789D6000002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E086D0789D6000002CE69 = { + fileRef = 3D9E086B0789D6000002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E086E0789D81B0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = alpassvc.c; + path = ../tran/alpassvc.c; + refType = 4; + }; + 3D9E086F0789D81B0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = alpassvc.h; + path = ../tran/alpassvc.h; + refType = 4; + }; + 3D9E08700789D81B0002CE69 = { + fileRef = 3D9E086E0789D81B0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08710789D81B0002CE69 = { + fileRef = 3D9E086F0789D81B0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08720789D82F0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = allpoles.c; + path = ../tran/allpoles.c; + refType = 4; + }; + 3D9E08730789D82F0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = allpoles.h; + path = ../tran/allpoles.h; + refType = 4; + }; + 3D9E08740789D82F0002CE69 = { + fileRef = 3D9E08720789D82F0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08750789D82F0002CE69 = { + fileRef = 3D9E08730789D82F0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08760789D8520002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = f0.cpp; + refType = 4; + }; + 3D9E08770789D8520002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = f0.h; + refType = 4; + }; + 3D9E08780789D8520002CE69 = { + fileRef = 3D9E08760789D8520002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08790789D8520002CE69 = { + fileRef = 3D9E08770789D8520002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E087A0789D8B20002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrclar.c; + path = ../tran/instrclar.c; + refType = 4; + }; + 3D9E087B0789D8B20002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrclar.h; + path = ../tran/instrclar.h; + refType = 4; + }; + 3D9E087C0789D8B20002CE69 = { + fileRef = 3D9E087A0789D8B20002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E087D0789D8B20002CE69 = { + fileRef = 3D9E087B0789D8B20002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E087E0789D8CF0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrsaxall.c; + path = ../tran/instrsaxall.c; + refType = 4; + }; + 3D9E087F0789D8CF0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrsaxall.h; + path = ../tran/instrsaxall.h; + refType = 4; + }; + 3D9E08800789D8CF0002CE69 = { + fileRef = 3D9E087E0789D8CF0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08810789D8CF0002CE69 = { + fileRef = 3D9E087F0789D8CF0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08820789D8E70002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = lpreson.c; + path = /Users/rbd/nyquist/tran/lpreson.c; + refType = 0; + }; + 3D9E08830789D8E70002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = lpreson.h; + path = ../tran/lpreson.h; + refType = 4; + }; + 3D9E08840789D8E70002CE69 = { + fileRef = 3D9E08820789D8E70002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08850789D8E70002CE69 = { + fileRef = 3D9E08830789D8E70002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08860789D9100002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrclarall.c; + path = ../tran/instrclarall.c; + refType = 4; + }; + 3D9E08870789D9100002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrclarall.h; + path = ../tran/instrclarall.h; + refType = 4; + }; + 3D9E08880789D9100002CE69 = { + fileRef = 3D9E08860789D9100002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08890789D9100002CE69 = { + fileRef = 3D9E08870789D9100002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E088A0789D9230002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrsaxfreq.c; + path = ../tran/instrsaxfreq.c; + refType = 4; + }; + 3D9E088B0789D9230002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrsaxfreq.h; + path = ../tran/instrsaxfreq.h; + refType = 4; + }; + 3D9E088C0789D9230002CE69 = { + fileRef = 3D9E088A0789D9230002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E088D0789D9230002CE69 = { + fileRef = 3D9E088B0789D9230002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E088E0789D9430002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrclarfreq.c; + path = ../tran/instrclarfreq.c; + refType = 4; + }; + 3D9E088F0789D9430002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrclarfreq.h; + path = ../tran/instrclarfreq.h; + refType = 4; + }; + 3D9E08900789D9430002CE69 = { + fileRef = 3D9E088E0789D9430002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08910789D9430002CE69 = { + fileRef = 3D9E088F0789D9430002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08920789D9680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrsax.c; + path = ../tran/instrsax.c; + refType = 4; + }; + 3D9E08930789D9680002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = instrsax.h; + path = ../tran/instrsax.h; + refType = 4; + }; + 3D9E08940789D9680002CE69 = { + fileRef = 3D9E08920789D9680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08950789D9680002CE69 = { + fileRef = 3D9E08930789D9680002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3D9E08960789D9E30002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + name = pa_unix_util.c; + path = ../portaudio/pa_unix/pa_unix_util.c; + refType = 4; + }; + 3D9E08970789D9E30002CE69 = { + fileRef = 3D9E08960789D9E30002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3DA446C00789FF350002CE69 = { + isa = PBXFrameworkReference; + name = AudioToolbox.framework; + path = /System/Library/Frameworks/AudioToolbox.framework; + refType = 0; + }; + 3DA446C10789FF350002CE69 = { + fileRef = 3DA446C00789FF350002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3DA446C20789FF430002CE69 = { + isa = PBXFrameworkReference; + name = CoreAudio.framework; + path = /System/Library/Frameworks/CoreAudio.framework; + refType = 0; + }; + 3DA446C30789FF430002CE69 = { + fileRef = 3DA446C20789FF430002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3DF21F2204FD4FDC0002CE69 = { + buildActionMask = 2147483647; + files = ( + 3DF21F5104FD526A0002CE69, + 3DF21F5204FD526A0002CE69, + 3DF21F5404FD526A0002CE69, + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 3DF21F2304FD4FDC0002CE69 = { + buildActionMask = 2147483647; + files = ( + 3DF21F5304FD526A0002CE69, + 3DF21F6104FD52BC0002CE69, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 3DF21F2404FD4FDC0002CE69 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 3DF21F2504FD4FDC0002CE69 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 3DF21F2604FD4FDC0002CE69 = { + buildPhases = ( + 3DF21F2204FD4FDC0002CE69, + 3DF21F2304FD4FDC0002CE69, + 3DF21F2404FD4FDC0002CE69, + 3DF21F2504FD4FDC0002CE69, + ); + buildSettings = { + HEADER_SEARCH_PATHS = ../sys/unix; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = intgen; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXToolTarget; + name = InterfaceGenerator; + productInstallPath = /usr/local/bin; + productName = InterfaceGenerator; + productReference = 3DF21F2704FD4FDC0002CE69; + }; + 3DF21F2704FD4FDC0002CE69 = { + isa = PBXExecutableFileReference; + path = intgen; + refType = 3; + }; + 3DF21F3104FD526A0002CE69 = { + children = ( + 3DF21F3204FD526A0002CE69, + 3DF21F3304FD526A0002CE69, + 3DF21F3404FD526A0002CE69, + 3DF21F3504FD526A0002CE69, + 3DF21F3604FD526A0002CE69, + 3DF21F3C04FD526A0002CE69, + 3DF21F3D04FD526A0002CE69, + 3DF21F3E04FD526A0002CE69, + 3DF21F3F04FD526A0002CE69, + 3DF21F4004FD526A0002CE69, + 3DF21F4104FD526A0002CE69, + 3DF21F4204FD526A0002CE69, + 3DF21F4404FD526A0002CE69, + 3DF21F4504FD526A0002CE69, + 3DF21F4604FD526A0002CE69, + 3DF21F4704FD526A0002CE69, + 3DF21F4804FD526A0002CE69, + 3DF21F4904FD526A0002CE69, + 3DF21F4A04FD526A0002CE69, + 3DF21F4B04FD526A0002CE69, + 3DF21F4C04FD526A0002CE69, + 3DF21F4D04FD526A0002CE69, + 3DF21F4E04FD526A0002CE69, + 3DF21F4F04FD526A0002CE69, + 3DF21F5004FD526A0002CE69, + ); + isa = PBXGroup; + path = misc; + refType = 4; + }; + 3DF21F3204FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = args.h; + refType = 4; + }; + 3DF21F3304FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cext.h; + refType = 4; + }; + 3DF21F3404FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmdline.c; + refType = 4; + }; + 3DF21F3504FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmdline.h; + refType = 4; + }; + 3DF21F3604FD526A0002CE69 = { + children = ( + 3DF21F3704FD526A0002CE69, + 3DF21F3804FD526A0002CE69, + 3DF21F3904FD526A0002CE69, + 3DF21F3A04FD526A0002CE69, + 3DF21F3B04FD526A0002CE69, + ); + isa = PBXGroup; + path = cmu; + refType = 4; + }; + 3DF21F3704FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cleanup.bat; + refType = 4; + }; + 3DF21F3804FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = "cmu-linux-install.lsp"; + refType = 4; + }; + 3DF21F3904FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmuinstall.bat; + refType = 4; + }; + 3DF21F3A04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = init.lsp; + refType = 4; + }; + 3DF21F3B04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = restore.bat; + refType = 4; + }; + 3DF21F3C04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = convert.c; + refType = 4; + }; + 3DF21F3D04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = convert.h; + refType = 4; + }; + 3DF21F3E04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = filelist.c; + refType = 4; + }; + 3DF21F3F04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = filelist.dsp; + refType = 4; + }; + 3DF21F4004FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = intgen.c; + refType = 4; + }; + 3DF21F4104FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = intgen2.c; + refType = 4; + }; + 3DF21F4204FD526A0002CE69 = { + children = ( + 3DF21F4304FD526A0002CE69, + ); + isa = PBXGroup; + path = intgen_win32; + refType = 4; + }; + 3DF21F4304FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = intgen.dsp; + refType = 4; + }; + 3DF21F4404FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = "mac-to-win.lsp"; + refType = 4; + }; + 3DF21F4504FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = Makefile; + refType = 4; + }; + 3DF21F4604FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = makefile.lsp; + refType = 4; + }; + 3DF21F4704FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = packer.c; + refType = 4; + }; + 3DF21F4804FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = packer.dsp; + refType = 4; + }; + 3DF21F4904FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = play.c; + refType = 4; + }; + 3DF21F4A04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = plot.c; + refType = 4; + }; + 3DF21F4B04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sampleprint.c; + refType = 4; + }; + 3DF21F4C04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sine.c; + refType = 4; + }; + 3DF21F4D04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = stdefs2.h; + refType = 4; + }; + 3DF21F4E04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = transfiles.lsp; + refType = 4; + }; + 3DF21F4F04FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = unpacker.c; + refType = 4; + }; + 3DF21F5004FD526A0002CE69 = { + fileEncoding = 30; + isa = PBXFileReference; + path = unpacker.dsp; + refType = 4; + }; + 3DF21F5104FD526A0002CE69 = { + fileRef = 3DF21F3204FD526A0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3DF21F5204FD526A0002CE69 = { + fileRef = 3DF21F3304FD526A0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3DF21F5304FD526A0002CE69 = { + fileRef = 3DF21F3404FD526A0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3DF21F5404FD526A0002CE69 = { + fileRef = 3DF21F3504FD526A0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; + 3DF21F6104FD52BC0002CE69 = { + fileRef = 3DF21F4004FD526A0002CE69; + isa = PBXBuildFile; + settings = { + }; + }; +//3D0 +//3D1 +//3D2 +//3D3 +//3D4 +//C60 +//C61 +//C62 +//C63 +//C64 + C6A0FF2D029079AD04C91782 = { + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + 3D9E082C0779F7680002CE69, + ); + isa = PBXCopyFilesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; +//C60 +//C61 +//C62 +//C63 +//C64 +//F50 +//F51 +//F52 +//F53 +//F54 + F510BCA7039F84FD01029006 = { + includeInIndex = 1; + isa = PBXFolderReference; + path = lib; + refType = 4; + }; + F510BCDA039F84FE01029006 = { + includeInIndex = 1; + isa = PBXFolderReference; + path = runtime; + refType = 4; + }; + F510BD73039FB49C01029006 = { + includeInIndex = 1; + isa = PBXFolderReference; + path = doc; + refType = 4; + }; + F510BDB903A0314301029006 = { + children = ( + F543E76B0375C24D01029006, + F543E7750375C25A01029006, + ); + isa = PBXGroup; + name = Frameworks; + path = /System/Library/Frameworks; + refType = 0; + }; + F53626EE03761E6C01029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = audiopa.c; + refType = 4; + }; + F543E76B0375C24D01029006 = { + isa = PBXFrameworkReference; + path = CoreAudio.framework; + refType = 4; + }; + F543E7750375C25A01029006 = { + isa = PBXFrameworkReference; + path = AudioToolbox.framework; + refType = 4; + }; + F543EE570375CD5801029006 = { + children = ( + F543EE580375CD5801029006, + F543EE590375CD5801029006, + F543EE5A0375CD5801029006, + F543EE5B0375CD5801029006, + F543EE5C0375CD5801029006, + F543EE5D0375CD5801029006, + F543EE5E0375CD5801029006, + F543EE5F0375CD5801029006, + F543EE600375CD5801029006, + F543EE610375CD5801029006, + F543EE620375CD5801029006, + F543EE630375CD5801029006, + F543EE640375CD5801029006, + F543EE650375CD5801029006, + F543EE660375CD5801029006, + F543EE670375CD5801029006, + F543EE680375CD5801029006, + F543EE690375CD5801029006, + F543EE6A0375CD5801029006, + F543EE6B0375CD5801029006, + F543EE6C0375CD5801029006, + F543EE6D0375CD5801029006, + F543EE6E0375CD5801029006, + F543EE6F0375CD5801029006, + F543EE700375CD5801029006, + F543EE710375CD5801029006, + F543EE720375CD5801029006, + F543EE730375CD5801029006, + F543EE740375CD5801029006, + F543EE750375CD5801029006, + F543EE760375CD5801029006, + F543EE770375CD5801029006, + F543EE780375CD5801029006, + F543EE790375CD5801029006, + F543EE7A0375CD5801029006, + F543EE7B0375CD5801029006, + F543EE7C0375CD5801029006, + F543EE7D0375CD5801029006, + F543EE7E0375CD5801029006, + F543EE7F0375CD5801029006, + F543EE800375CD5801029006, + F543EE810375CD5801029006, + F543EE820375CD5801029006, + F543EE830375CD5801029006, + F543EE840375CD5801029006, + F543EE850375CD5801029006, + F543EE860375CD5801029006, + F543EE870375CD5801029006, + ); + isa = PBXGroup; + path = cmt; + refType = 4; + }; + F543EE580375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cext.c; + refType = 4; + }; + F543EE590375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cext.h; + refType = 4; + }; + F543EE5A0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cleanup.c; + refType = 4; + }; + F543EE5B0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cleanup.h; + refType = 4; + }; + F543EE5C0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmdline.c; + refType = 4; + }; + F543EE5D0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmdline.h; + refType = 4; + }; + F543EE5E0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmtcmd.c; + refType = 4; + }; + F543EE5F0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmtcmd.h; + refType = 4; + }; + F543EE600375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmtio.c; + refType = 4; + }; + F543EE610375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cmtio.h; + refType = 4; + }; + F543EE620375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = hash.h; + refType = 4; + }; + F543EE630375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = hashrout.h; + refType = 4; + }; + F543EE640375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = mem.c; + refType = 4; + }; + F543EE650375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = mem.h; + refType = 4; + }; + F543EE660375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = mfmidi.h; + refType = 4; + }; + F543EE670375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midibuff.h; + refType = 4; + }; + F543EE680375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midicode.h; + refType = 4; + }; + F543EE690375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midierr.h; + refType = 4; + }; + F543EE6A0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midifile.c; + refType = 4; + }; + F543EE6B0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midifile.h; + refType = 4; + }; + F543EE6C0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midifns.c; + refType = 4; + }; + F543EE6D0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midifns.h; + refType = 4; + }; + F543EE6E0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midimgr.c; + refType = 4; + }; + F543EE6F0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = midimgr.h; + refType = 4; + }; + F543EE700375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = moxc.c; + refType = 4; + }; + F543EE710375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = moxc.h; + refType = 4; + }; + F543EE720375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = musiprog.h; + refType = 4; + }; + F543EE730375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = pitch.h; + refType = 4; + }; + F543EE740375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = record.c; + refType = 4; + }; + F543EE750375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = record.h; + refType = 4; + }; + F543EE760375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seq.c; + refType = 4; + }; + F543EE770375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seq.h; + refType = 4; + }; + F543EE780375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqdecls.h; + refType = 4; + }; + F543EE790375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqmread.c; + refType = 4; + }; + F543EE7A0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqmread.h; + refType = 4; + }; + F543EE7B0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqmwrite.c; + refType = 4; + }; + F543EE7C0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqmwrite.h; + refType = 4; + }; + F543EE7D0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqread.c; + refType = 4; + }; + F543EE7E0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqread.h; + refType = 4; + }; + F543EE7F0375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqwrite.c; + refType = 4; + }; + F543EE800375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqwrite.h; + refType = 4; + }; + F543EE810375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = swlogic.h; + refType = 4; + }; + F543EE820375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tempomap.c; + refType = 4; + }; + F543EE830375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tempomap.h; + refType = 4; + }; + F543EE840375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = timebase.c; + refType = 4; + }; + F543EE850375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = timebase.h; + refType = 4; + }; + F543EE860375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = userio.c; + refType = 4; + }; + F543EE870375CD5801029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = userio.h; + refType = 4; + }; + F543EF3D0375CD7101029006 = { + children = ( + F53626EE03761E6C01029006, + F543EF4A0375CD7101029006, + F543EF4B0375CD7101029006, + F543EF4D0375CD7101029006, + F543EF4E0375CD7101029006, + F543EF510375CD7101029006, + F543EF520375CD7101029006, + F543EF550375CD7101029006, + F543EF570375CD7101029006, + F543EF580375CD7101029006, + F543EF590375CD7101029006, + F543EF5A0375CD7101029006, + F543EF5D0375CD7101029006, + F543EF5E0375CD7101029006, + F543EF620375CD7101029006, + F543EF630375CD7101029006, + F543EF660375CD7101029006, + ); + isa = PBXGroup; + path = snd; + refType = 4; + }; + F543EF4A0375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = ieeecvt.c; + refType = 4; + }; + F543EF4B0375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = ieeecvt.h; + refType = 4; + }; + F543EF4D0375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = snd.c; + refType = 4; + }; + F543EF4E0375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = snd.h; + refType = 4; + }; + F543EF510375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndconfig.h; + refType = 4; + }; + F543EF520375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndcvt.c; + refType = 4; + }; + F543EF550375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndfileio.h; + refType = 4; + }; + F543EF570375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndhead.h; + refType = 4; + }; + F543EF580375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndheader.c; + refType = 4; + }; + F543EF590375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndheader.h; + refType = 4; + }; + F543EF5A0375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndio.c; + refType = 4; + }; + F543EF5D0375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndmac.c; + refType = 4; + }; + F543EF5E0375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndmac.h; + refType = 4; + }; + F543EF620375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndsystem.h; + refType = 4; + }; + F543EF630375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndsystemmac.h; + refType = 4; + }; + F543EF660375CD7101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndwrite.h; + refType = 4; + }; + F543EF940375CD8D01029006 = { + children = ( + F543EF950375CD8D01029006, + F543EF960375CD8D01029006, + ); + isa = PBXGroup; + path = fft; + refType = 4; + }; + F543EF950375CD8D01029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fftn.c; + refType = 4; + }; + F543EF960375CD8D01029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fftn.h; + refType = 4; + }; + F543EF970375CD8D01029006 = { + fileRef = F543EF950375CD8D01029006; + isa = PBXBuildFile; + settings = { + }; + }; + F543EF980375CD8D01029006 = { + fileRef = F543EF960375CD8D01029006; + isa = PBXBuildFile; + settings = { + }; + }; + F543EF990375CD9901029006 = { + children = ( + F543EFB10375CD9901029006, + ); + isa = PBXGroup; + path = sys; + refType = 4; + }; + F543EFB10375CD9901029006 = { + children = ( + 3D36DDF00796E5DE0002CE69, + F543EFBF0375CD9901029006, + 3D9867D304FFE8E20002CE69, + ); + isa = PBXGroup; + path = unix; + refType = 4; + }; + F543EFBF0375CD9901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = osstuff.c; + refType = 4; + }; + F543F0100375CD9901029006 = { + fileRef = F543EFBF0375CD9901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F543F19F0375E1E401029006 = { + children = ( + 08FB7795FE84155DC02AAC07, + ); + isa = PBXGroup; + name = Source; + path = ""; + refType = 2; + }; + F5779DA4039D8E1901029006 = { + fileRef = F543EF5E0375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5779DA8039D8E9501029006 = { + fileRef = F5FF60D9039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5779DB1039D99D901029006 = { + fileRef = F543EF4E0375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5779DB2039D99DA01029006 = { + fileRef = F543EF4D0375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5C6A9B303A10C0501029006 = { + buildActionMask = 2147483647; + files = ( + 3D35A7D605690E180002CE69, + 3D35A7D705690E180002CE69, + 3D35A7D805690E180002CE69, + 3D35A7D905690E180002CE69, + 3D35A7DA05690E180002CE69, + 3D35A7DB05690E180002CE69, + 3D35A7DC05690E180002CE69, + 3D35A7DE05690E180002CE69, + 3D35A7DF05690E180002CE69, + 3D35A7E005690E180002CE69, + 3D35A7E105690E180002CE69, + 3D35A7E205690E180002CE69, + 3D6032F60790A600007A3CA5, + 3D6032F90790A618007A3CA5, + 3D6032FB0790A62C007A3CA5, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F5C6A9B403A10C0501029006 = { + buildActionMask = 2147483647; + files = ( + 3D35A7D405690E180002CE69, + 3D35A7D505690E180002CE69, + 3D35A7DD05690E180002CE69, + 3D36DDE70796D6D40002CE69, + 3D36DDEF0796E5CA0002CE69, + 3D36DDF30796E60F0002CE69, + ); + isa = PBXResourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F5C6A9B503A10C0501029006 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXJavaArchiveBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F5C6A9B603A10C0501029006 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F5C6A9B703A10C0501029006 = { + buildPhases = ( + F5C6A9B303A10C0501029006, + F5C6A9B403A10C0501029006, + F5C6A9B503A10C0501029006, + F5C6A9B603A10C0501029006, + F5DA146003A112BF01029006, + ); + buildSettings = { + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = Applications; + JAVA_CLASS_SEARCH_PATHS = ../jnyqide; + JAVA_COMPILER = /usr/bin/javac; + JAVA_ONLY = YES; + JAVA_SOURCE_SUBDIR = .; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = NyquistIDE; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + WRAPPER_EXTENSION = app; + }; + dependencies = ( + F5DA143703A10FDA01029006, + ); + isa = PBXApplicationTarget; + name = NyquistIDE; + productInstallPath = Applications; + productName = NyquistIDE; + productReference = F5C6A9B803A10C0501029006; + productSettingsXML = " + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + + CFBundleGetInfoString + + CFBundleIconFile + + CFBundleIdentifier + + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + + CFBundlePackageType + APPL + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Java + + ClassPath + + $JAVAROOT/NyquistIDE.jar + + MainClass + jnyqide.Main + Properties + + com.apple.macos.useScreenMenuBar + true + + WorkingDirectory + $APP_PACKAGE/Contents/Resources/Java + + NSJavaNeeded + YES + NSJavaPath + + NyquistIDE.jar + + NSJavaRoot + Contents/Resources/Java + + +"; + }; + F5C6A9B803A10C0501029006 = { + isa = PBXApplicationReference; + path = NyquistIDE.app; + refType = 3; + }; + F5C6A9C903A10C6201029006 = { + fileRef = 034768E8FF38A79811DB9C8B; + isa = PBXBuildFile; + settings = { + JAVA_ARCHIVE_SUBDIR = build; + }; + }; + F5C6A9CA03A10C6401029006 = { + fileRef = F510BCA7039F84FD01029006; + isa = PBXBuildFile; + settings = { + JAVA_ARCHIVE_SUBDIR = ..; + }; + }; + F5DA143703A10FDA01029006 = { + isa = PBXTargetDependency; + target = 08FB779FFE84155DC02AAC07; + }; + F5DA143903A1108C01029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = README; + refType = 4; + }; + F5DA146003A112BF01029006 = { + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 15; + files = ( + F5C6A9C903A10C6201029006, + 3D36DDEC0796D71B0002CE69, + F5C6A9CA03A10C6401029006, + 3D36DDED0796E1AB0002CE69, + 3D36DDF10796E5E80002CE69, + 3D36DDF40796E6170002CE69, + ); + isa = PBXCopyFilesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F5FF5F48039D84B901029006 = { + children = ( + F5FF5F49039D84B901029006, + F5FF5F4A039D84B901029006, + F5FF5F4B039D84B901029006, + F5FF5F4C039D84B901029006, + F5FF5F4D039D84B901029006, + F5FF5F4E039D84B901029006, + F5FF5F4F039D84B901029006, + F5FF5F50039D84B901029006, + F5FF5F51039D84B901029006, + F5FF5F52039D84B901029006, + F5FF5F53039D84B901029006, + F5FF5F54039D84B901029006, + F5FF5F55039D84B901029006, + F5FF5F56039D84B901029006, + F5FF5F57039D84B901029006, + F5FF5F58039D84B901029006, + F5FF5F59039D84B901029006, + F5FF5F5A039D84B901029006, + F5FF5F5B039D84B901029006, + F5FF5F5C039D84B901029006, + F5FF5F5D039D84B901029006, + F5FF5F5E039D84B901029006, + F5FF5F5F039D84B901029006, + F5FF5F60039D84B901029006, + F5FF5F61039D84B901029006, + F5FF5F62039D84B901029006, + F5FF5F63039D84B901029006, + F5FF5F64039D84B901029006, + F5FF5F65039D84B901029006, + ); + isa = PBXGroup; + path = xlisp; + refType = 4; + }; + F5FF5F49039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = extern.c; + refType = 4; + }; + F5FF5F4A039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = extern.h; + refType = 4; + }; + F5FF5F4B039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = osdefs.h; + refType = 4; + }; + F5FF5F4C039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = osptrs.h; + refType = 4; + }; + F5FF5F4D039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlbfun.c; + refType = 4; + }; + F5FF5F4E039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlcont.c; + refType = 4; + }; + F5FF5F4F039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xldbug.c; + refType = 4; + }; + F5FF5F50039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xldmem.c; + refType = 4; + }; + F5FF5F51039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xldmem.h; + refType = 4; + }; + F5FF5F52039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xleval.c; + refType = 4; + }; + F5FF5F53039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlfio.c; + refType = 4; + }; + F5FF5F54039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlftab.c; + refType = 4; + }; + F5FF5F55039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlglob.c; + refType = 4; + }; + F5FF5F56039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlimage.c; + refType = 4; + }; + F5FF5F57039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlinit.c; + refType = 4; + }; + F5FF5F58039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlio.c; + refType = 4; + }; + F5FF5F59039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlisp.c; + refType = 4; + }; + F5FF5F5A039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlisp.h; + refType = 4; + }; + F5FF5F5B039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xljump.c; + refType = 4; + }; + F5FF5F5C039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xllist.c; + refType = 4; + }; + F5FF5F5D039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlmath.c; + refType = 4; + }; + F5FF5F5E039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlobj.c; + refType = 4; + }; + F5FF5F5F039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlpp.c; + refType = 4; + }; + F5FF5F60039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlprin.c; + refType = 4; + }; + F5FF5F61039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlread.c; + refType = 4; + }; + F5FF5F62039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlstr.c; + refType = 4; + }; + F5FF5F63039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlsubr.c; + refType = 4; + }; + F5FF5F64039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlsym.c; + refType = 4; + }; + F5FF5F65039D84B901029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = xlsys.c; + refType = 4; + }; + F5FF5F83039D84DB01029006 = { + fileRef = F5FF5F49039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F84039D84DB01029006 = { + fileRef = F5FF5F4A039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F85039D84DF01029006 = { + fileRef = F5FF5F50039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F86039D84DF01029006 = { + fileRef = F5FF5F51039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F87039D84E301029006 = { + fileRef = F5FF5F4D039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F88039D84E801029006 = { + fileRef = F5FF5F4E039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F89039D84EF01029006 = { + fileRef = F5FF5F4F039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F8A039D84F301029006 = { + fileRef = F5FF5F52039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F8B039D84F701029006 = { + fileRef = F5FF5F53039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F8C039D84FB01029006 = { + fileRef = F5FF5F54039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F8D039D84FE01029006 = { + fileRef = F5FF5F55039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F8E039D850301029006 = { + fileRef = F5FF5F56039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F8F039D850701029006 = { + fileRef = F5FF5F57039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F90039D850801029006 = { + fileRef = F5FF5F58039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F91039D850A01029006 = { + fileRef = F5FF5F59039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F92039D850B01029006 = { + fileRef = F5FF5F5A039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F93039D850E01029006 = { + fileRef = F5FF5F5B039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F94039D851101029006 = { + fileRef = F5FF5F5C039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F95039D851201029006 = { + fileRef = F5FF5F5D039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F96039D851501029006 = { + fileRef = F5FF5F5E039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F97039D851801029006 = { + fileRef = F5FF5F5F039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F98039D851A01029006 = { + fileRef = F5FF5F60039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F99039D851D01029006 = { + fileRef = F5FF5F61039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F9A039D852201029006 = { + fileRef = F5FF5F62039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F9B039D852301029006 = { + fileRef = F5FF5F63039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F9C039D852401029006 = { + fileRef = F5FF5F64039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F9D039D852601029006 = { + fileRef = F5FF5F65039D84B901029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF5F9E039D863401029006 = { + children = ( + F5FF5FA1039D866201029006, + F5FF5FA2039D866201029006, + F5FF5FA3039D866201029006, + F5FF5FA4039D866201029006, + F5FF5FA5039D866201029006, + F5FF5FA6039D866201029006, + F5FF5FA7039D866201029006, + F5FF5FA8039D866201029006, + F5FF5FA9039D866201029006, + F5FF5FAA039D866201029006, + F5FF5FAB039D866201029006, + F5FF5FAC039D866201029006, + F5FF5FAD039D866201029006, + F5FF5FAE039D866201029006, + F5FF5FAF039D866201029006, + F5FF5FB0039D866201029006, + F5FF5FB1039D866201029006, + F5FF5FB2039D866201029006, + F5FF5FB3039D866201029006, + F5FF5FB4039D866201029006, + F5FF5FB5039D866201029006, + F5FF5FB6039D866201029006, + F5FF5FB7039D866201029006, + F5FF5FB8039D866201029006, + F5FF5FB9039D866201029006, + F5FF5FBA039D866201029006, + F5FF5FBB039D866201029006, + F5FF5FBC039D866201029006, + F5FF5FBD039D866201029006, + F5FF5FBE039D866201029006, + F5FF5FC1039D866201029006, + F5FF5FC2039D866201029006, + 3D9E07E00779F4DC0002CE69, + 3D9E07E10779F4DC0002CE69, + F5FF5FC5039D866201029006, + F5FF5FC6039D866201029006, + F5FF5FC7039D866201029006, + F5FF5FC8039D866201029006, + F5FF5FC9039D866201029006, + F5FF5FCA039D866201029006, + F5FF5FCB039D866201029006, + F5FF5FCC039D866201029006, + F5FF5FCD039D866201029006, + F5FF5FCE039D866201029006, + F5FF5FCF039D866201029006, + F5FF5FD0039D866201029006, + F5FF5FD1039D866201029006, + F5FF5FD2039D866201029006, + F5FF5FD3039D866201029006, + F5FF5FD4039D866201029006, + F5FF5FD5039D866201029006, + F5FF5FD6039D866201029006, + F5FF5FD7039D866201029006, + F5FF5FD8039D866201029006, + F5FF5FD9039D866201029006, + F5FF5FDA039D866201029006, + F5FF5FDB039D866201029006, + F5FF5FDC039D866201029006, + F5FF5FDD039D866201029006, + F5FF5FDE039D866201029006, + F5FF5FDF039D866201029006, + F5FF5FE0039D866201029006, + F5FF5FE1039D866201029006, + F5FF5FE2039D866201029006, + F5FF5FE3039D866201029006, + F5FF5FE4039D866201029006, + F5FF5FE5039D866201029006, + F5FF5FE6039D866201029006, + F5FF5FE7039D866201029006, + F5FF5FE8039D866201029006, + F5FF5FEB039D866201029006, + F5FF5FEC039D866201029006, + F5FF5FED039D866201029006, + F5FF5FEE039D866201029006, + F5FF5FEF039D866201029006, + F5FF5FF0039D866201029006, + F5FF5FF1039D866201029006, + F5FF5FF2039D866201029006, + F5FF5FF3039D866201029006, + F5FF5FF4039D866201029006, + F5FF5FF5039D866201029006, + F5FF5FF6039D866201029006, + F5FF5FF7039D866201029006, + F5FF5FF8039D866201029006, + F5FF5FF9039D866201029006, + F5FF5FFA039D866201029006, + F5FF5FFB039D866201029006, + F5FF5FFC039D866201029006, + F5FF5FFD039D866201029006, + F5FF5FFE039D866201029006, + F5FF5FFF039D866201029006, + F5FF6000039D866201029006, + F5FF6001039D866201029006, + F5FF6002039D866201029006, + F5FF6003039D866201029006, + F5FF6004039D866201029006, + 3D9867CC04FFDD3C0002CE69, + 3D9867CE04FFDD6B0002CE69, + F5FF6005039D866201029006, + F5FF6006039D866201029006, + F5FF6007039D866201029006, + F5FF6008039D866201029006, + F5FF6009039D866201029006, + F5FF600A039D866201029006, + F5FF600B039D866201029006, + F5FF600C039D866201029006, + F5FF600D039D866201029006, + F5FF600E039D866201029006, + ); + isa = PBXGroup; + path = tran; + refType = 4; + }; + F5FF5FA1039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = abs.c; + refType = 4; + }; + F5FF5FA2039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = abs.h; + refType = 4; + }; + F5FF5FA3039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = alpass.c; + refType = 4; + }; + F5FF5FA4039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = alpass.h; + refType = 4; + }; + F5FF5FA5039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = amosc.c; + refType = 4; + }; + F5FF5FA6039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = amosc.h; + refType = 4; + }; + F5FF5FA7039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = areson.c; + refType = 4; + }; + F5FF5FA8039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = areson.h; + refType = 4; + }; + F5FF5FA9039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = aresoncv.c; + refType = 4; + }; + F5FF5FAA039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = aresoncv.h; + refType = 4; + }; + F5FF5FAB039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = aresonvc.c; + refType = 4; + }; + F5FF5FAC039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = aresonvc.h; + refType = 4; + }; + F5FF5FAD039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = aresonvv.c; + refType = 4; + }; + F5FF5FAE039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = aresonvv.h; + refType = 4; + }; + F5FF5FAF039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = atone.c; + refType = 4; + }; + F5FF5FB0039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = atone.h; + refType = 4; + }; + F5FF5FB1039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = atonev.c; + refType = 4; + }; + F5FF5FB2039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = atonev.h; + refType = 4; + }; + F5FF5FB3039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = biquad.c; + refType = 4; + }; + F5FF5FB4039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = biquad.h; + refType = 4; + }; + F5FF5FB5039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = buzz.c; + refType = 4; + }; + F5FF5FB6039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = buzz.h; + refType = 4; + }; + F5FF5FB7039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = chase.c; + refType = 4; + }; + F5FF5FB8039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = chase.h; + refType = 4; + }; + F5FF5FB9039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = clip.c; + refType = 4; + }; + F5FF5FBA039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = clip.h; + refType = 4; + }; + F5FF5FBB039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = congen.c; + refType = 4; + }; + F5FF5FBC039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = congen.h; + refType = 4; + }; + F5FF5FBD039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = const.c; + refType = 4; + }; + F5FF5FBE039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = const.h; + refType = 4; + }; + F5FF5FC1039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = coterm.c; + refType = 4; + }; + F5FF5FC2039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = coterm.h; + refType = 4; + }; + F5FF5FC5039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = delaycv.c; + refType = 4; + }; + F5FF5FC6039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = delaycv.h; + refType = 4; + }; + F5FF5FC7039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = exp.c; + refType = 4; + }; + F5FF5FC8039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = exp.h; + refType = 4; + }; + F5FF5FC9039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fmosc.c; + refType = 4; + }; + F5FF5FCA039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fmosc.h; + refType = 4; + }; + F5FF5FCB039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = follow.c; + refType = 4; + }; + F5FF5FCC039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = follow.h; + refType = 4; + }; + F5FF5FCD039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fromarraystream.c; + refType = 4; + }; + F5FF5FCE039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fromarraystream.h; + refType = 4; + }; + F5FF5FCF039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fromobject.c; + refType = 4; + }; + F5FF5FD0039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fromobject.h; + refType = 4; + }; + F5FF5FD1039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = gate.c; + refType = 4; + }; + F5FF5FD2039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = gate.h; + refType = 4; + }; + F5FF5FD3039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = ifft.c; + refType = 4; + }; + F5FF5FD4039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = ifft.h; + refType = 4; + }; + F5FF5FD5039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = integrate.c; + refType = 4; + }; + F5FF5FD6039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = integrate.h; + refType = 4; + }; + F5FF5FD7039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = log.c; + refType = 4; + }; + F5FF5FD8039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = log.h; + refType = 4; + }; + F5FF5FD9039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = maxv.c; + refType = 4; + }; + F5FF5FDA039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = maxv.h; + refType = 4; + }; + F5FF5FDB039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = offset.c; + refType = 4; + }; + F5FF5FDC039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = offset.h; + refType = 4; + }; + F5FF5FDD039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = oneshot.c; + refType = 4; + }; + F5FF5FDE039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = oneshot.h; + refType = 4; + }; + F5FF5FDF039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = osc.c; + refType = 4; + }; + F5FF5FE0039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = osc.h; + refType = 4; + }; + F5FF5FE1039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = partial.c; + refType = 4; + }; + F5FF5FE2039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = partial.h; + refType = 4; + }; + F5FF5FE3039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = pluck.c; + refType = 4; + }; + F5FF5FE4039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = pluck.h; + refType = 4; + }; + F5FF5FE5039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = prod.c; + refType = 4; + }; + F5FF5FE6039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = prod.h; + refType = 4; + }; + F5FF5FE7039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = pwl.c; + refType = 4; + }; + F5FF5FE8039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = pwl.h; + refType = 4; + }; + F5FF5FEB039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = quantize.c; + refType = 4; + }; + F5FF5FEC039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = quantize.h; + refType = 4; + }; + F5FF5FED039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = recip.c; + refType = 4; + }; + F5FF5FEE039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = recip.h; + refType = 4; + }; + F5FF5FEF039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = reson.c; + refType = 4; + }; + F5FF5FF0039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = reson.h; + refType = 4; + }; + F5FF5FF1039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resoncv.c; + refType = 4; + }; + F5FF5FF2039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resoncv.h; + refType = 4; + }; + F5FF5FF3039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resonvc.c; + refType = 4; + }; + F5FF5FF4039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resonvc.h; + refType = 4; + }; + F5FF5FF5039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resonvv.c; + refType = 4; + }; + F5FF5FF6039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resonvv.h; + refType = 4; + }; + F5FF5FF7039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sampler.c; + refType = 4; + }; + F5FF5FF8039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sampler.h; + refType = 4; + }; + F5FF5FF9039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = scale.c; + refType = 4; + }; + F5FF5FFA039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = scale.h; + refType = 4; + }; + F5FF5FFB039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = shape.c; + refType = 4; + }; + F5FF5FFC039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = shape.h; + refType = 4; + }; + F5FF5FFD039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sine.c; + refType = 4; + }; + F5FF5FFE039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sine.h; + refType = 4; + }; + F5FF5FFF039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = siosc.c; + refType = 4; + }; + F5FF6000039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = siosc.h; + refType = 4; + }; + F5FF6001039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = slope.c; + refType = 4; + }; + F5FF6002039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = slope.h; + refType = 4; + }; + F5FF6003039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sqrt.c; + refType = 4; + }; + F5FF6004039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sqrt.h; + refType = 4; + }; + F5FF6005039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tapv.c; + refType = 4; + }; + F5FF6006039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tapv.h; + refType = 4; + }; + F5FF6007039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tone.c; + refType = 4; + }; + F5FF6008039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tone.h; + refType = 4; + }; + F5FF6009039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tonev.c; + refType = 4; + }; + F5FF600A039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = tonev.h; + refType = 4; + }; + F5FF600B039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = upsample.c; + refType = 4; + }; + F5FF600C039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = upsample.h; + refType = 4; + }; + F5FF600D039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = white.c; + refType = 4; + }; + F5FF600E039D866201029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = white.h; + refType = 4; + }; + F5FF600F039D866201029006 = { + fileRef = F5FF5FA1039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6010039D866201029006 = { + fileRef = F5FF5FA2039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6011039D866201029006 = { + fileRef = F5FF5FA3039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6012039D866201029006 = { + fileRef = F5FF5FA4039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6013039D866201029006 = { + fileRef = F5FF5FA5039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6014039D866201029006 = { + fileRef = F5FF5FA6039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6015039D866201029006 = { + fileRef = F5FF5FA7039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6016039D866201029006 = { + fileRef = F5FF5FA8039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6017039D866201029006 = { + fileRef = F5FF5FA9039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6018039D866201029006 = { + fileRef = F5FF5FAA039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6019039D866201029006 = { + fileRef = F5FF5FAB039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF601A039D866201029006 = { + fileRef = F5FF5FAC039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF601B039D866201029006 = { + fileRef = F5FF5FAD039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF601C039D866201029006 = { + fileRef = F5FF5FAE039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF601D039D866201029006 = { + fileRef = F5FF5FAF039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF601E039D866201029006 = { + fileRef = F5FF5FB0039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF601F039D866201029006 = { + fileRef = F5FF5FB1039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6020039D866201029006 = { + fileRef = F5FF5FB2039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6021039D866201029006 = { + fileRef = F5FF5FB3039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6022039D866201029006 = { + fileRef = F5FF5FB4039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6023039D866201029006 = { + fileRef = F5FF5FB5039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6024039D866201029006 = { + fileRef = F5FF5FB6039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6025039D866201029006 = { + fileRef = F5FF5FB7039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6026039D866201029006 = { + fileRef = F5FF5FB8039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6027039D866201029006 = { + fileRef = F5FF5FB9039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6028039D866201029006 = { + fileRef = F5FF5FBA039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6029039D866201029006 = { + fileRef = F5FF5FBB039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF602A039D866201029006 = { + fileRef = F5FF5FBC039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF602B039D866201029006 = { + fileRef = F5FF5FBD039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF602C039D866201029006 = { + fileRef = F5FF5FBE039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF602F039D866201029006 = { + fileRef = F5FF5FC1039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6030039D866201029006 = { + fileRef = F5FF5FC2039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6033039D866201029006 = { + fileRef = F5FF5FC5039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6034039D866201029006 = { + fileRef = F5FF5FC6039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6035039D866201029006 = { + fileRef = F5FF5FC7039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6036039D866201029006 = { + fileRef = F5FF5FC8039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6037039D866201029006 = { + fileRef = F5FF5FC9039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6038039D866201029006 = { + fileRef = F5FF5FCA039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6039039D866201029006 = { + fileRef = F5FF5FCB039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF603A039D866201029006 = { + fileRef = F5FF5FCC039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF603B039D866201029006 = { + fileRef = F5FF5FCD039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF603C039D866201029006 = { + fileRef = F5FF5FCE039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF603D039D866201029006 = { + fileRef = F5FF5FCF039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF603E039D866201029006 = { + fileRef = F5FF5FD0039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF603F039D866201029006 = { + fileRef = F5FF5FD1039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6040039D866201029006 = { + fileRef = F5FF5FD2039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6041039D866201029006 = { + fileRef = F5FF5FD3039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6042039D866201029006 = { + fileRef = F5FF5FD4039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6043039D866201029006 = { + fileRef = F5FF5FD5039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6044039D866201029006 = { + fileRef = F5FF5FD6039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6045039D866201029006 = { + fileRef = F5FF5FD7039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6046039D866201029006 = { + fileRef = F5FF5FD8039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6047039D866201029006 = { + fileRef = F5FF5FD9039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6048039D866201029006 = { + fileRef = F5FF5FDA039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6049039D866201029006 = { + fileRef = F5FF5FDB039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF604A039D866201029006 = { + fileRef = F5FF5FDC039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF604B039D866201029006 = { + fileRef = F5FF5FDD039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF604C039D866201029006 = { + fileRef = F5FF5FDE039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF604D039D866201029006 = { + fileRef = F5FF5FDF039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF604E039D866201029006 = { + fileRef = F5FF5FE0039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF604F039D866201029006 = { + fileRef = F5FF5FE1039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6050039D866201029006 = { + fileRef = F5FF5FE2039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6051039D866201029006 = { + fileRef = F5FF5FE3039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6052039D866201029006 = { + fileRef = F5FF5FE4039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6053039D866201029006 = { + fileRef = F5FF5FE5039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6054039D866201029006 = { + fileRef = F5FF5FE6039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6055039D866201029006 = { + fileRef = F5FF5FE7039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6056039D866201029006 = { + fileRef = F5FF5FE8039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6059039D866201029006 = { + fileRef = F5FF5FEB039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF605A039D866201029006 = { + fileRef = F5FF5FEC039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF605B039D866201029006 = { + fileRef = F5FF5FED039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF605C039D866201029006 = { + fileRef = F5FF5FEE039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF605D039D866201029006 = { + fileRef = F5FF5FEF039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF605E039D866201029006 = { + fileRef = F5FF5FF0039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF605F039D866201029006 = { + fileRef = F5FF5FF1039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6060039D866201029006 = { + fileRef = F5FF5FF2039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6061039D866201029006 = { + fileRef = F5FF5FF3039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6062039D866201029006 = { + fileRef = F5FF5FF4039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6063039D866201029006 = { + fileRef = F5FF5FF5039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6064039D866201029006 = { + fileRef = F5FF5FF6039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6065039D866201029006 = { + fileRef = F5FF5FF7039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6066039D866201029006 = { + fileRef = F5FF5FF8039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6067039D866201029006 = { + fileRef = F5FF5FF9039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6068039D866201029006 = { + fileRef = F5FF5FFA039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6069039D866201029006 = { + fileRef = F5FF5FFB039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF606A039D866201029006 = { + fileRef = F5FF5FFC039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF606B039D866201029006 = { + fileRef = F5FF5FFD039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF606C039D866201029006 = { + fileRef = F5FF5FFE039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF606D039D866201029006 = { + fileRef = F5FF5FFF039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF606E039D866201029006 = { + fileRef = F5FF6000039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF606F039D866201029006 = { + fileRef = F5FF6001039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6070039D866201029006 = { + fileRef = F5FF6002039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6071039D866201029006 = { + fileRef = F5FF6003039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6072039D866201029006 = { + fileRef = F5FF6004039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6073039D866201029006 = { + fileRef = F5FF6005039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6074039D866201029006 = { + fileRef = F5FF6006039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6075039D866201029006 = { + fileRef = F5FF6007039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6076039D866201029006 = { + fileRef = F5FF6008039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6077039D866201029006 = { + fileRef = F5FF6009039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6078039D866201029006 = { + fileRef = F5FF600A039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6079039D866201029006 = { + fileRef = F5FF600B039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF607A039D866201029006 = { + fileRef = F5FF600C039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF607B039D866201029006 = { + fileRef = F5FF600D039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF607C039D866201029006 = { + fileRef = F5FF600E039D866201029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6084039D871B01029006 = { + fileRef = F543EE580375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6085039D871B01029006 = { + fileRef = F543EE590375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6086039D871D01029006 = { + fileRef = F543EE5A0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6087039D871E01029006 = { + fileRef = F543EE5B0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6088039D872001029006 = { + fileRef = F543EE5C0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6089039D872001029006 = { + fileRef = F543EE5D0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF608A039D872301029006 = { + fileRef = F543EE5E0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF608B039D872301029006 = { + fileRef = F543EE5F0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF608C039D872E01029006 = { + fileRef = F543EE700375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF608D039D873001029006 = { + fileRef = F543EE710375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF608E039D873401029006 = { + fileRef = F543EE640375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF608F039D873501029006 = { + fileRef = F543EE650375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6090039D873F01029006 = { + fileRef = F543EE6A0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6091039D874001029006 = { + fileRef = F543EE6B0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6092039D874101029006 = { + fileRef = F543EE6C0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6093039D874101029006 = { + fileRef = F543EE6D0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6094039D874501029006 = { + fileRef = F543EE740375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6095039D874601029006 = { + fileRef = F543EE750375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6096039D874D01029006 = { + fileRef = F543EE760375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6097039D874E01029006 = { + fileRef = F543EE770375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6098039D875201029006 = { + fileRef = F543EE790375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6099039D875301029006 = { + fileRef = F543EE7A0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF609A039D875B01029006 = { + fileRef = F543EE7B0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF609B039D875E01029006 = { + fileRef = F543EE7D0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF609C039D875F01029006 = { + fileRef = F543EE7E0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF609D039D876001029006 = { + fileRef = F543EE7C0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF609E039D876301029006 = { + fileRef = F543EE7F0375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF609F039D876401029006 = { + fileRef = F543EE800375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF60A0039D876B01029006 = { + fileRef = F543EE820375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF60A1039D876B01029006 = { + fileRef = F543EE830375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF60A2039D876C01029006 = { + fileRef = F543EE840375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF60A3039D876D01029006 = { + fileRef = F543EE850375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF60A4039D876F01029006 = { + fileRef = F543EE860375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF60A5039D876F01029006 = { + fileRef = F543EE870375CD5801029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF60A6039D87B001029006 = { + children = ( + F5FF615C039D899F01029006, + F5FF615D039D899F01029006, + F5FF615E039D899F01029006, + F5FF6162039D89B101029006, + F5FF6163039D89B101029006, + F5FF6164039D89B101029006, + F5FF60A7039D87B001029006, + F5FF60A8039D87B001029006, + 3D9867D7050920060002CE69, + 3D9867DB0509202C0002CE69, + 3D9867DD050920400002CE69, + 3D9867DE050920400002CE69, + F5FF60A9039D87B001029006, + F5FF60AA039D87B001029006, + F5FF60AB039D87B001029006, + F5FF60AC039D87B001029006, + F5FF60AD039D87B001029006, + F5FF60AE039D87B001029006, + F5FF60AF039D87B001029006, + F5FF60B0039D87B001029006, + F5FF60B1039D87B001029006, + 3D9867E1050920730002CE69, + 3D9867E2050920730002CE69, + F5FF60B2039D87B001029006, + F5FF60B3039D87B001029006, + F5FF60B4039D87B001029006, + F5FF60B5039D87B001029006, + F5FF60B6039D87B001029006, + F5FF60B7039D87B001029006, + F5FF60B8039D87B001029006, + F5FF60B9039D87B001029006, + F5FF60BA039D87B001029006, + F5FF60BB039D87B001029006, + F5FF60BC039D87B001029006, + F5FF60BD039D87B001029006, + F5FF60BE039D87B001029006, + F5FF60BF039D87B001029006, + F5FF60C0039D87B001029006, + F5FF60C1039D87B001029006, + F5FF60C2039D87B001029006, + F5FF60C3039D87B001029006, + F5FF60C4039D87B001029006, + F5FF60C5039D87B001029006, + F5FF60C6039D87B001029006, + F5FF60C7039D87B001029006, + F5FF60C8039D87B001029006, + 3D9867E5050921720002CE69, + F5FF60C9039D87B001029006, + F5FF60CA039D87B001029006, + F5FF60CB039D87B001029006, + F5FF60CC039D87B001029006, + F5FF60CD039D87B001029006, + F5FF60CE039D87B001029006, + F5FF60CF039D87B001029006, + F5FF60D0039D87B001029006, + F5FF60D1039D87B001029006, + F5FF60D2039D87B001029006, + F5FF60D3039D87B001029006, + F5FF60D4039D87B001029006, + F5FF60D5039D87B001029006, + F5FF60D6039D87B001029006, + F5FF60D7039D87B001029006, + F5FF60D8039D87B001029006, + F5FF60D9039D87B001029006, + F5FF60DA039D87B001029006, + F5FF60DB039D87B001029006, + F5FF60DC039D87B001029006, + F5FF60DD039D87B001029006, + F5FF60DE039D87B001029006, + F5FF60DF039D87B001029006, + F5FF60E0039D87B001029006, + F5FF60E1039D87B001029006, + F5FF60E2039D87B001029006, + F5FF60E4039D87B001029006, + F5FF60E5039D87B001029006, + F5FF60E6039D87B001029006, + 3D9E086A0789D6000002CE69, + 3D9E086B0789D6000002CE69, + 3D9E086E0789D81B0002CE69, + 3D9E086F0789D81B0002CE69, + 3D9E08720789D82F0002CE69, + 3D9E08730789D82F0002CE69, + 3D9E08760789D8520002CE69, + 3D9E08770789D8520002CE69, + 3D9E087A0789D8B20002CE69, + 3D9E087B0789D8B20002CE69, + 3D9E087E0789D8CF0002CE69, + 3D9E087F0789D8CF0002CE69, + 3D9E08820789D8E70002CE69, + 3D9E08830789D8E70002CE69, + 3D9E08860789D9100002CE69, + 3D9E08870789D9100002CE69, + 3D9E088A0789D9230002CE69, + 3D9E088B0789D9230002CE69, + 3D9E088E0789D9430002CE69, + 3D9E088F0789D9430002CE69, + 3D9E08920789D9680002CE69, + 3D9E08930789D9680002CE69, + 3D9E08960789D9E30002CE69, + F5FF60E7039D87B001029006, + F5FF60E8039D87B001029006, + F5FF60E9039D87B001029006, + 3D9867D505091F760002CE69, + 3D9867D9050920140002CE69, + 3D9E07DC0779F4800002CE69, + 3D9E07DD0779F4800002CE69, + ); + isa = PBXGroup; + path = nyqsrc; + refType = 4; + }; + F5FF60A7039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = add.c; + refType = 4; + }; + F5FF60A8039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = add.h; + refType = 4; + }; + F5FF60A9039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = avg.c; + refType = 4; + }; + F5FF60AA039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = avg.h; + refType = 4; + }; + F5FF60AB039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = compose.c; + refType = 4; + }; + F5FF60AC039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = compose.h; + refType = 4; + }; + F5FF60AD039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = cque.h; + refType = 4; + }; + F5FF60AE039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = debug.c; + refType = 4; + }; + F5FF60AF039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = debug.h; + refType = 4; + }; + F5FF60B0039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = downsample.c; + refType = 4; + }; + F5FF60B1039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = downsample.h; + refType = 4; + }; + F5FF60B2039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = falloc.c; + refType = 4; + }; + F5FF60B3039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = falloc.h; + refType = 4; + }; + F5FF60B4039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = ffilterkit.c; + refType = 4; + }; + F5FF60B5039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = ffilterkit.h; + refType = 4; + }; + F5FF60B6039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = "fft-rbd.c"; + refType = 4; + }; + F5FF60B7039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fft.c; + refType = 4; + }; + F5FF60B8039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fft.h; + refType = 4; + }; + F5FF60B9039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fftr4.c; + refType = 4; + }; + F5FF60BA039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fftw.h; + refType = 4; + }; + F5FF60BB039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fresample.h; + refType = 4; + }; + F5FF60BC039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = fsmallfilter.h; + refType = 4; + }; + F5FF60BD039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = handlers.c; + refType = 4; + }; + F5FF60BE039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = inverse.c; + refType = 4; + }; + F5FF60BF039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = inverse.h; + refType = 4; + }; + F5FF60C0039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = local.c; + refType = 4; + }; + F5FF60C1039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = localdefs.h; + refType = 4; + }; + F5FF60C2039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = localptrs.h; + refType = 4; + }; + F5FF60C3039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = multiread.c; + refType = 4; + }; + F5FF60C4039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = multiread.h; + refType = 4; + }; + F5FF60C5039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = multiseq.c; + refType = 4; + }; + F5FF60C6039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = multiseq.h; + refType = 4; + }; + F5FF60C7039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = nfilterkit.c; + refType = 4; + }; + F5FF60C8039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = nfilterkit.h; + refType = 4; + }; + F5FF60C9039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = probe.c; + refType = 4; + }; + F5FF60CA039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = probe.h; + refType = 4; + }; + F5FF60CB039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resamp.c; + refType = 4; + }; + F5FF60CC039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resamp.h; + refType = 4; + }; + F5FF60CD039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resampv.c; + refType = 4; + }; + F5FF60CE039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = resampv.h; + refType = 4; + }; + F5FF60CF039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = rfftw.h; + refType = 4; + }; + F5FF60D0039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = samples.c; + refType = 4; + }; + F5FF60D1039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = samples.h; + refType = 4; + }; + F5FF60D2039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqext.c; + refType = 4; + }; + F5FF60D3039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqext.h; + refType = 4; + }; + F5FF60D4039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqfn.wcl; + refType = 4; + }; + F5FF60D5039D87B001029006 = { + isa = PBXFileReference; + path = seqfnint; + refType = 4; + }; + F5FF60D6039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqfnint.lsp; + refType = 4; + }; + F5FF60D7039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqinterf.c; + refType = 4; + }; + F5FF60D8039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqinterf.h; + refType = 4; + }; + F5FF60D9039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndfail.c; + refType = 4; + }; + F5FF60DA039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndfn.wcl; + refType = 4; + }; + F5FF60DB039D87B001029006 = { + isa = PBXFileReference; + path = sndfnint; + refType = 4; + }; + F5FF60DC039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndfnint.lsp; + refType = 4; + }; + F5FF60DD039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndmax.c; + refType = 4; + }; + F5FF60DE039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndmax.h; + refType = 4; + }; + F5FF60DF039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndread.c; + refType = 4; + }; + F5FF60E0039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndread.h; + refType = 4; + }; + F5FF60E1039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndseq.c; + refType = 4; + }; + F5FF60E2039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndseq.h; + refType = 4; + }; + F5FF60E4039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndwrite.h; + refType = 4; + }; + F5FF60E5039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndwritepa.c; + refType = 4; + }; + F5FF60E6039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sound.c; + refType = 4; + }; + F5FF60E7039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sound.h; + refType = 4; + }; + F5FF60E8039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = stats.c; + refType = 4; + }; + F5FF60E9039D87B001029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = stdefs.h; + refType = 4; + }; + F5FF612D039D87DC01029006 = { + fileRef = F5FF60AE039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF612E039D87DC01029006 = { + fileRef = F5FF60AF039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF612F039D87E001029006 = { + fileRef = F5FF60B2039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6130039D87E101029006 = { + fileRef = F5FF60B3039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6131039D87E401029006 = { + fileRef = F5FF60A7039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6132039D87E601029006 = { + fileRef = F5FF60A8039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6133039D87E801029006 = { + fileRef = F5FF60C0039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6134039D87EE01029006 = { + fileRef = F5FF60B0039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6135039D87EF01029006 = { + fileRef = F5FF60B1039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6136039D87F301029006 = { + fileRef = F5FF60BD039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6138039D87F801029006 = { + fileRef = F5FF60C3039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6139039D87FD01029006 = { + fileRef = F5FF60C5039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF613A039D87FE01029006 = { + fileRef = F5FF60C4039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF613B039D880001029006 = { + fileRef = F5FF60C6039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF613C039D880301029006 = { + fileRef = F5FF60D0039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF613D039D880401029006 = { + fileRef = F5FF60D1039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF613E039D880801029006 = { + fileRef = F5FF60D2039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF613F039D880901029006 = { + fileRef = F5FF60D3039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6140039D880D01029006 = { + fileRef = F5FF60D7039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6141039D880E01029006 = { + fileRef = F5FF60D8039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6142039D881B01029006 = { + fileRef = F5FF60DF039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6143039D881C01029006 = { + fileRef = F5FF60E0039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6144039D881F01029006 = { + fileRef = F5FF60E1039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6145039D882001029006 = { + fileRef = F5FF60E2039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6146039D882701029006 = { + fileRef = F5FF60E5039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6147039D882901029006 = { + fileRef = F5FF60E4039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6148039D884201029006 = { + fileRef = F5FF60DD039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6149039D884301029006 = { + fileRef = F5FF60DE039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF614A039D885301029006 = { + fileRef = F5FF60E6039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF614B039D885401029006 = { + fileRef = F5FF60E7039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF614C039D885701029006 = { + fileRef = F5FF60E8039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF614E039D885C01029006 = { + fileRef = F5FF60AB039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF614F039D885D01029006 = { + fileRef = F5FF60AC039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6150039D886101029006 = { + fileRef = F5FF60BE039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6151039D886201029006 = { + fileRef = F5FF60BF039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6152039D886C01029006 = { + fileRef = F5FF60CB039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6153039D886D01029006 = { + fileRef = F5FF60CC039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6154039D887401029006 = { + fileRef = F5FF60CD039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6155039D887501029006 = { + fileRef = F5FF60CE039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6156039D887A01029006 = { + fileRef = F5FF60B4039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6157039D887B01029006 = { + fileRef = F5FF60B5039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6158039D888101029006 = { + fileRef = F5FF60A9039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6159039D888201029006 = { + fileRef = F5FF60AA039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF615A039D888601029006 = { + fileRef = F5FF60B7039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF615B039D888601029006 = { + fileRef = F5FF60B8039D87B001029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF615C039D899F01029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqfnint.c; + refType = 4; + }; + F5FF615D039D899F01029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqfnintdefs.h; + refType = 4; + }; + F5FF615E039D899F01029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = seqfnintptrs.h; + refType = 4; + }; + F5FF615F039D899F01029006 = { + fileRef = F5FF615C039D899F01029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6160039D899F01029006 = { + fileRef = F5FF615D039D899F01029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6161039D899F01029006 = { + fileRef = F5FF615E039D899F01029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6162039D89B101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndfnint.c; + refType = 4; + }; + F5FF6163039D89B101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndfnintdefs.h; + refType = 4; + }; + F5FF6164039D89B101029006 = { + fileEncoding = 30; + isa = PBXFileReference; + path = sndfnintptrs.h; + refType = 4; + }; + F5FF6165039D89B101029006 = { + fileRef = F5FF6162039D89B101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6166039D89B101029006 = { + fileRef = F5FF6163039D89B101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6167039D89B101029006 = { + fileRef = F5FF6164039D89B101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF616A039D8A3701029006 = { + fileRef = F543EF5D0375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF616C039D8A5401029006 = { + fileRef = F543EF4B0375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF616F039D8A5C01029006 = { + fileRef = F543EF520375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6170039D8A6601029006 = { + fileRef = F543EF5A0375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6171039D8A6B01029006 = { + fileRef = F543EF580375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + F5FF6172039D8A6C01029006 = { + fileRef = F543EF590375CD7101029006; + isa = PBXBuildFile; + settings = { + }; + }; + }; + rootObject = 08FB7793FE84155DC02AAC07; +} diff --git a/macosxproject/nyquist.xcodeproj/project.pbxproj b/macosxproject/nyquist.xcodeproj/project.pbxproj new file mode 100644 index 0000000..db9891a --- /dev/null +++ b/macosxproject/nyquist.xcodeproj/project.pbxproj @@ -0,0 +1,3137 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXAggregateTarget section */ + 3D7327A5125BF5D8009AAF15 /* CompileJava */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 3D7327A9125BF5F7009AAF15 /* Build configuration list for PBXAggregateTarget "CompileJava" */; + buildPhases = ( + 3D7327A4125BF5D8009AAF15 /* ShellScript */, + ); + dependencies = ( + ); + name = CompileJava; + productName = CompileJava; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 3D0817D40AD02A210051B745 /* test-client.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D0817BA0AD0219B0051B745 /* test-client.c */; }; + 3D177689125CB411007B2152 /* jnyqide.jar in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D177688125CB40C007B2152 /* jnyqide.jar */; }; + 3D177699125CB593007B2152 /* closeFile.gif in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D35A7C505690E180002CE69 /* closeFile.gif */; }; + 3D17769A125CB593007B2152 /* help.gif in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D35A7C605690E180002CE69 /* help.gif */; }; + 3D17769B125CB593007B2152 /* openFile.gif in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D35A7CE05690E180002CE69 /* openFile.gif */; }; + 3D17769C125CB593007B2152 /* NyquistWords.txt in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D7A6FD10A7A85F900098CAB /* NyquistWords.txt */; }; + 3D17769D125CB593007B2152 /* runtime in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = F510BCDA039F84FE01029006 /* runtime */; }; + 3D17769E125CB593007B2152 /* lib in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = F510BCA7039F84FD01029006 /* lib */; }; + 3D17769F125CB593007B2152 /* demos in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D7A6F830A7A6AB500098CAB /* demos */; }; + 3D1776A0125CB593007B2152 /* system.lsp in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D36DDF20796E60F0002CE69 /* system.lsp */; }; + 3D1776A1125CB5B3007B2152 /* Nyquist.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3D1472C70A799DFF00F00E71 /* Nyquist.icns */; }; + 3D3221540F53D42D00F074EF /* blob.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221400F53D42D00F074EF /* blob.c */; }; + 3D3221550F53D42D00F074EF /* bundle.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221410F53D42D00F074EF /* bundle.c */; }; + 3D3221560F53D42D00F074EF /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221450F53D42D00F074EF /* message.c */; }; + 3D3221570F53D42D00F074EF /* method.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221460F53D42D00F074EF /* method.c */; }; + 3D3221580F53D42D00F074EF /* pattern_match.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221470F53D42D00F074EF /* pattern_match.c */; }; + 3D3221590F53D42D00F074EF /* send.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221480F53D42D00F074EF /* send.c */; }; + 3D32215E0F53D42D00F074EF /* timetag.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D32214D0F53D42D00F074EF /* timetag.c */; }; + 3D3221770F53D51D00F074EF /* address.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D32213F0F53D42D00F074EF /* address.c */; }; + 3D3221780F53D51D00F074EF /* blob.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221400F53D42D00F074EF /* blob.c */; }; + 3D3221790F53D51D00F074EF /* bundle.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221410F53D42D00F074EF /* bundle.c */; }; + 3D32217C0F53D51D00F074EF /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221450F53D42D00F074EF /* message.c */; }; + 3D32217D0F53D51D00F074EF /* method.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221460F53D42D00F074EF /* method.c */; }; + 3D32217E0F53D51D00F074EF /* pattern_match.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221470F53D42D00F074EF /* pattern_match.c */; }; + 3D3221820F53D51D00F074EF /* timetag.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D32214D0F53D42D00F074EF /* timetag.c */; }; + 3D3223290F544BBB00F074EF /* nyq-osc-server.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3223280F544BBB00F074EF /* nyq-osc-server.c */; }; + 3D3223740F54539B00F074EF /* libliblo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3221700F53D4C300F074EF /* libliblo.a */; }; + 3D3223770F5453DE00F074EF /* send.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221480F53D42D00F074EF /* send.c */; }; + 3D3223780F5453DE00F074EF /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3221490F53D42D00F074EF /* server.c */; }; + 3D3223970F5455FA00F074EF /* libliblo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3221700F53D4C300F074EF /* libliblo.a */; }; + 3D3223990F54561400F074EF /* libliblo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3221700F53D4C300F074EF /* libliblo.a */; }; + 3D3223A30F54582900F074EF /* ser-to-osc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D3223A20F54582900F074EF /* ser-to-osc.cpp */; }; + 3D35338D0F0BD7C60059CD05 /* sndfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35338B0F0BD7C60059CD05 /* sndfile.c */; }; + 3D3533A90F0BDA290059CD05 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533A80F0BDA290059CD05 /* common.c */; }; + 3D3533AD0F0BDA7C0059CD05 /* file_io.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533AC0F0BDA7C0059CD05 /* file_io.c */; }; + 3D3533B30F0BDDE40059CD05 /* liblibsndfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D3533820F0BD6CA0059CD05 /* liblibsndfile.a */; }; + 3D3533BB0F0BDE2E0059CD05 /* aiff.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533B50F0BDE2E0059CD05 /* aiff.c */; }; + 3D3533BC0F0BDE2E0059CD05 /* alaw.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533B60F0BDE2E0059CD05 /* alaw.c */; }; + 3D3533BD0F0BDE2E0059CD05 /* au.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533B70F0BDE2E0059CD05 /* au.c */; }; + 3D3533BE0F0BDE2E0059CD05 /* avr.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533B80F0BDE2E0059CD05 /* avr.c */; }; + 3D3533BF0F0BDE2E0059CD05 /* broadcast.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533B90F0BDE2E0059CD05 /* broadcast.c */; }; + 3D3533C00F0BDE2E0059CD05 /* caf.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533BA0F0BDE2E0059CD05 /* caf.c */; }; + 3D3533C40F0BDE610059CD05 /* dither.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533C10F0BDE610059CD05 /* dither.c */; }; + 3D3533C50F0BDE610059CD05 /* double64.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533C20F0BDE610059CD05 /* double64.c */; }; + 3D3533C60F0BDE610059CD05 /* dwd.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533C30F0BDE610059CD05 /* dwd.c */; }; + 3D3533CA0F0BDE930059CD05 /* flac.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533C70F0BDE930059CD05 /* flac.c */; }; + 3D3533CC0F0BDE930059CD05 /* float32.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533C90F0BDE930059CD05 /* float32.c */; }; + 3D3533CE0F0BDEAA0059CD05 /* htk.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533CD0F0BDEAA0059CD05 /* htk.c */; }; + 3D3533D10F0BDEC30059CD05 /* mat4.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533CF0F0BDEC30059CD05 /* mat4.c */; }; + 3D3533D20F0BDEC30059CD05 /* mat5.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533D00F0BDEC30059CD05 /* mat5.c */; }; + 3D3533D90F0BDEE70059CD05 /* nist.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533D30F0BDEE70059CD05 /* nist.c */; }; + 3D3533DA0F0BDEE70059CD05 /* ogg.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533D40F0BDEE70059CD05 /* ogg.c */; }; + 3D3533DB0F0BDEE70059CD05 /* paf.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533D50F0BDEE70059CD05 /* paf.c */; }; + 3D3533DC0F0BDEE70059CD05 /* pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533D60F0BDEE70059CD05 /* pcm.c */; }; + 3D3533DD0F0BDEE70059CD05 /* pvf.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533D70F0BDEE70059CD05 /* pvf.c */; }; + 3D3533DE0F0BDEE70059CD05 /* raw.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533D80F0BDEE70059CD05 /* raw.c */; }; + 3D3533E20F0BDF060059CD05 /* rx2.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533DF0F0BDF060059CD05 /* rx2.c */; }; + 3D3533E30F0BDF060059CD05 /* sd2.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533E00F0BDF060059CD05 /* sd2.c */; }; + 3D3533E40F0BDF060059CD05 /* sds.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533E10F0BDF060059CD05 /* sds.c */; }; + 3D3533E70F0BDF3B0059CD05 /* ircam.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533E60F0BDF3B0059CD05 /* ircam.c */; }; + 3D3533EB0F0BDF5E0059CD05 /* dwvw.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533E80F0BDF5E0059CD05 /* dwvw.c */; }; + 3D3533F50F0BDFA20059CD05 /* vox_adpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533EE0F0BDFA20059CD05 /* vox_adpcm.c */; }; + 3D3533F60F0BDFA20059CD05 /* w64.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533EF0F0BDFA20059CD05 /* w64.c */; }; + 3D3533F70F0BDFA20059CD05 /* wav_w64.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533F00F0BDFA20059CD05 /* wav_w64.c */; }; + 3D3533F90F0BDFA20059CD05 /* wav.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533F20F0BDFA20059CD05 /* wav.c */; }; + 3D3533FA0F0BDFA20059CD05 /* wve.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533F30F0BDFA20059CD05 /* wve.c */; }; + 3D3533FB0F0BDFA20059CD05 /* xi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533F40F0BDFA20059CD05 /* xi.c */; }; + 3D3533FF0F0BDFD80059CD05 /* command.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533FC0F0BDFD80059CD05 /* command.c */; }; + 3D35340D0F0BE0470059CD05 /* strings.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35340B0F0BE0470059CD05 /* strings.c */; }; + 3D35340E0F0BE0470059CD05 /* svx.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35340C0F0BE0470059CD05 /* svx.c */; }; + 3D3534110F0BE27E0059CD05 /* ima_adpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534100F0BE27E0059CD05 /* ima_adpcm.c */; }; + 3D3534160F0BE2AA0059CD05 /* txw.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534130F0BE2AA0059CD05 /* txw.c */; }; + 3D3534170F0BE2AA0059CD05 /* ulaw.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534140F0BE2AA0059CD05 /* ulaw.c */; }; + 3D3534180F0BE2AA0059CD05 /* voc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534150F0BE2AA0059CD05 /* voc.c */; }; + 3D35341B0F0BE3240059CD05 /* ms_adpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35341A0F0BE3240059CD05 /* ms_adpcm.c */; }; + 3D35341E0F0BE41E0059CD05 /* g72x.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533E90F0BDF5E0059CD05 /* g72x.c */; }; + 3D35341F0F0BE4290059CD05 /* gsm610.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3533EA0F0BDF5E0059CD05 /* gsm610.c */; }; + 3D35342A0F0BE5370059CD05 /* g72x.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534280F0BE5370059CD05 /* g72x.c */; }; + 3D3534300F0BE5510059CD05 /* gsm_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35342C0F0BE5510059CD05 /* gsm_create.c */; }; + 3D3534310F0BE5510059CD05 /* gsm_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35342D0F0BE5510059CD05 /* gsm_decode.c */; }; + 3D3534320F0BE5510059CD05 /* gsm_destroy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35342E0F0BE5510059CD05 /* gsm_destroy.c */; }; + 3D3534330F0BE5510059CD05 /* gsm_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35342F0F0BE5510059CD05 /* gsm_encode.c */; }; + 3D35343A0F0BE58D0059CD05 /* code.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534350F0BE58D0059CD05 /* code.c */; }; + 3D35343C0F0BE58D0059CD05 /* decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534370F0BE58D0059CD05 /* decode.c */; }; + 3D35343D0F0BE58D0059CD05 /* gsm_option.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534380F0BE58D0059CD05 /* gsm_option.c */; }; + 3D3534430F0BE5B50059CD05 /* g721.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35343F0F0BE5B50059CD05 /* g721.c */; }; + 3D3534440F0BE5B50059CD05 /* g723_16.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534400F0BE5B50059CD05 /* g723_16.c */; }; + 3D3534450F0BE5B50059CD05 /* g723_24.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534410F0BE5B50059CD05 /* g723_24.c */; }; + 3D3534460F0BE5B50059CD05 /* g723_40.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534420F0BE5B50059CD05 /* g723_40.c */; }; + 3D35344B0F0BE5EB0059CD05 /* long_term.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534480F0BE5EB0059CD05 /* long_term.c */; }; + 3D35344C0F0BE5EB0059CD05 /* lpc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534490F0BE5EB0059CD05 /* lpc.c */; }; + 3D35344D0F0BE5EB0059CD05 /* preprocess.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35344A0F0BE5EB0059CD05 /* preprocess.c */; }; + 3D3534520F0BE6190059CD05 /* rpe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D35344F0F0BE6190059CD05 /* rpe.c */; }; + 3D3534530F0BE6190059CD05 /* short_term.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534500F0BE6190059CD05 /* short_term.c */; }; + 3D3534540F0BE6190059CD05 /* table.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534510F0BE6190059CD05 /* table.c */; }; + 3D3534580F0BE6420059CD05 /* add.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D3534560F0BE6420059CD05 /* add.c */; }; + 3D48B84C0F5993750073A251 /* fftlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D48B84B0F5993750073A251 /* fftlib.c */; }; + 3D48B8500F5993A60073A251 /* fftext.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D48B84F0F5993A60073A251 /* fftext.c */; }; + 3D48B86E0F599EE90073A251 /* matlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D48B86D0F599EE90073A251 /* matlib.c */; }; + 3D5CD8340B5BC75E00DF426B /* osstuff.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EFBF0375CD9901029006 /* osstuff.c */; }; + 3D5CD8350B5BC75E00DF426B /* extern.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F49039D84B901029006 /* extern.c */; }; + 3D5CD8360B5BC75E00DF426B /* xldmem.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F50039D84B901029006 /* xldmem.c */; }; + 3D5CD8370B5BC75E00DF426B /* xlbfun.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F4D039D84B901029006 /* xlbfun.c */; }; + 3D5CD8380B5BC75E00DF426B /* xlcont.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F4E039D84B901029006 /* xlcont.c */; }; + 3D5CD8390B5BC75E00DF426B /* xldbug.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F4F039D84B901029006 /* xldbug.c */; }; + 3D5CD83A0B5BC75E00DF426B /* xleval.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F52039D84B901029006 /* xleval.c */; }; + 3D5CD83B0B5BC75E00DF426B /* xlfio.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F53039D84B901029006 /* xlfio.c */; }; + 3D5CD83C0B5BC75E00DF426B /* xlftab.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F54039D84B901029006 /* xlftab.c */; }; + 3D5CD83D0B5BC75E00DF426B /* xlglob.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F55039D84B901029006 /* xlglob.c */; }; + 3D5CD83E0B5BC75E00DF426B /* xlimage.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F56039D84B901029006 /* xlimage.c */; }; + 3D5CD83F0B5BC75E00DF426B /* xlinit.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F57039D84B901029006 /* xlinit.c */; }; + 3D5CD8400B5BC75E00DF426B /* xlio.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F58039D84B901029006 /* xlio.c */; }; + 3D5CD8410B5BC75E00DF426B /* xlisp.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F59039D84B901029006 /* xlisp.c */; }; + 3D5CD8420B5BC75E00DF426B /* xljump.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F5B039D84B901029006 /* xljump.c */; }; + 3D5CD8430B5BC75E00DF426B /* xllist.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F5C039D84B901029006 /* xllist.c */; }; + 3D5CD8440B5BC75E00DF426B /* xlmath.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F5D039D84B901029006 /* xlmath.c */; }; + 3D5CD8450B5BC75E00DF426B /* xlobj.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F5E039D84B901029006 /* xlobj.c */; }; + 3D5CD8460B5BC75E00DF426B /* xlpp.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F5F039D84B901029006 /* xlpp.c */; }; + 3D5CD8470B5BC75E00DF426B /* xlprin.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F60039D84B901029006 /* xlprin.c */; }; + 3D5CD8480B5BC75E00DF426B /* xlread.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F61039D84B901029006 /* xlread.c */; }; + 3D5CD8490B5BC75E00DF426B /* xlstr.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F62039D84B901029006 /* xlstr.c */; }; + 3D5CD84A0B5BC75E00DF426B /* xlsubr.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F63039D84B901029006 /* xlsubr.c */; }; + 3D5CD84B0B5BC75E00DF426B /* xlsym.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F64039D84B901029006 /* xlsym.c */; }; + 3D5CD84C0B5BC75E00DF426B /* xlsys.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5F65039D84B901029006 /* xlsys.c */; }; + 3D5CD84D0B5BC75E00DF426B /* abs.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FA1039D866201029006 /* abs.c */; }; + 3D5CD84E0B5BC75E00DF426B /* alpass.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FA3039D866201029006 /* alpass.c */; }; + 3D5CD84F0B5BC75E00DF426B /* amosc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FA5039D866201029006 /* amosc.c */; }; + 3D5CD8500B5BC75E00DF426B /* areson.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FA7039D866201029006 /* areson.c */; }; + 3D5CD8510B5BC75E00DF426B /* aresoncv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FA9039D866201029006 /* aresoncv.c */; }; + 3D5CD8520B5BC75E00DF426B /* aresonvc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FAB039D866201029006 /* aresonvc.c */; }; + 3D5CD8530B5BC75E00DF426B /* aresonvv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FAD039D866201029006 /* aresonvv.c */; }; + 3D5CD8540B5BC75E00DF426B /* atone.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FAF039D866201029006 /* atone.c */; }; + 3D5CD8550B5BC75E00DF426B /* atonev.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FB1039D866201029006 /* atonev.c */; }; + 3D5CD8570B5BC75E00DF426B /* buzz.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FB5039D866201029006 /* buzz.c */; }; + 3D5CD8580B5BC75E00DF426B /* chase.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FB7039D866201029006 /* chase.c */; }; + 3D5CD8590B5BC75E00DF426B /* clip.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FB9039D866201029006 /* clip.c */; }; + 3D5CD85A0B5BC75E00DF426B /* congen.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FBB039D866201029006 /* congen.c */; }; + 3D5CD85B0B5BC75E00DF426B /* const.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FBD039D866201029006 /* const.c */; }; + 3D5CD85C0B5BC75E00DF426B /* coterm.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FC1039D866201029006 /* coterm.c */; }; + 3D5CD85D0B5BC75E00DF426B /* delaycv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FC5039D866201029006 /* delaycv.c */; }; + 3D5CD85E0B5BC75E00DF426B /* exp.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FC7039D866201029006 /* exp.c */; }; + 3D5CD85F0B5BC75E00DF426B /* fmosc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FC9039D866201029006 /* fmosc.c */; }; + 3D5CD8600B5BC75E00DF426B /* follow.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FCB039D866201029006 /* follow.c */; }; + 3D5CD8610B5BC75E00DF426B /* fromarraystream.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FCD039D866201029006 /* fromarraystream.c */; }; + 3D5CD8620B5BC75E00DF426B /* fromobject.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FCF039D866201029006 /* fromobject.c */; }; + 3D5CD8630B5BC75E00DF426B /* gate.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FD1039D866201029006 /* gate.c */; }; + 3D5CD8640B5BC75E00DF426B /* ifft.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FD3039D866201029006 /* ifft.c */; }; + 3D5CD8650B5BC75E00DF426B /* integrate.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FD5039D866201029006 /* integrate.c */; }; + 3D5CD8660B5BC75E00DF426B /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FD7039D866201029006 /* log.c */; }; + 3D5CD8670B5BC75E00DF426B /* maxv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FD9039D866201029006 /* maxv.c */; }; + 3D5CD8680B5BC75E00DF426B /* offset.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FDB039D866201029006 /* offset.c */; }; + 3D5CD8690B5BC75E00DF426B /* oneshot.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FDD039D866201029006 /* oneshot.c */; }; + 3D5CD86A0B5BC75E00DF426B /* osc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FDF039D866201029006 /* osc.c */; }; + 3D5CD86B0B5BC75E00DF426B /* partial.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FE1039D866201029006 /* partial.c */; }; + 3D5CD86C0B5BC75E00DF426B /* pluck.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FE3039D866201029006 /* pluck.c */; }; + 3D5CD86D0B5BC75E00DF426B /* prod.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FE5039D866201029006 /* prod.c */; }; + 3D5CD86E0B5BC75E00DF426B /* pwl.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FE7039D866201029006 /* pwl.c */; }; + 3D5CD86F0B5BC75E00DF426B /* quantize.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FEB039D866201029006 /* quantize.c */; }; + 3D5CD8700B5BC75E00DF426B /* recip.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FED039D866201029006 /* recip.c */; }; + 3D5CD8710B5BC75E00DF426B /* reson.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FEF039D866201029006 /* reson.c */; }; + 3D5CD8720B5BC75E00DF426B /* resoncv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FF1039D866201029006 /* resoncv.c */; }; + 3D5CD8730B5BC75E00DF426B /* resonvc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FF3039D866201029006 /* resonvc.c */; }; + 3D5CD8740B5BC75E00DF426B /* resonvv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FF5039D866201029006 /* resonvv.c */; }; + 3D5CD8750B5BC75E00DF426B /* sampler.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FF7039D866201029006 /* sampler.c */; }; + 3D5CD8760B5BC75E00DF426B /* scale.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FF9039D866201029006 /* scale.c */; }; + 3D5CD8770B5BC75E00DF426B /* shape.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FFB039D866201029006 /* shape.c */; }; + 3D5CD8780B5BC75E00DF426B /* sine.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FFD039D866201029006 /* sine.c */; }; + 3D5CD8790B5BC75E00DF426B /* siosc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF5FFF039D866201029006 /* siosc.c */; }; + 3D5CD87A0B5BC75E00DF426B /* slope.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF6001039D866201029006 /* slope.c */; }; + 3D5CD87B0B5BC75E00DF426B /* sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF6003039D866201029006 /* sqrt.c */; }; + 3D5CD87C0B5BC75E00DF426B /* tapv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF6005039D866201029006 /* tapv.c */; }; + 3D5CD87D0B5BC75E00DF426B /* tone.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF6007039D866201029006 /* tone.c */; }; + 3D5CD87E0B5BC75E00DF426B /* tonev.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF6009039D866201029006 /* tonev.c */; }; + 3D5CD87F0B5BC75E00DF426B /* upsample.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF600B039D866201029006 /* upsample.c */; }; + 3D5CD8800B5BC75E00DF426B /* white.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF600D039D866201029006 /* white.c */; }; + 3D5CD8810B5BC75E00DF426B /* cext.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE580375CD5801029006 /* cext.c */; }; + 3D5CD8820B5BC75E00DF426B /* cleanup.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE5A0375CD5801029006 /* cleanup.c */; }; + 3D5CD8830B5BC75E00DF426B /* cmdline.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE5C0375CD5801029006 /* cmdline.c */; }; + 3D5CD8840B5BC75E00DF426B /* cmtcmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE5E0375CD5801029006 /* cmtcmd.c */; }; + 3D5CD8850B5BC75E00DF426B /* moxc.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE700375CD5801029006 /* moxc.c */; }; + 3D5CD8860B5BC75E00DF426B /* mem.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE640375CD5801029006 /* mem.c */; }; + 3D5CD8870B5BC75E00DF426B /* midifile.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE6A0375CD5801029006 /* midifile.c */; }; + 3D5CD8880B5BC75E00DF426B /* midifns.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE6C0375CD5801029006 /* midifns.c */; }; + 3D5CD8890B5BC75E00DF426B /* record.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE740375CD5801029006 /* record.c */; }; + 3D5CD88A0B5BC75E00DF426B /* seq.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE760375CD5801029006 /* seq.c */; }; + 3D5CD88B0B5BC75E00DF426B /* seqmread.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE790375CD5801029006 /* seqmread.c */; }; + 3D5CD88C0B5BC75E00DF426B /* seqmwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE7B0375CD5801029006 /* seqmwrite.c */; }; + 3D5CD88D0B5BC75E00DF426B /* seqread.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE7D0375CD5801029006 /* seqread.c */; }; + 3D5CD88E0B5BC75E00DF426B /* seqwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE7F0375CD5801029006 /* seqwrite.c */; }; + 3D5CD88F0B5BC75E00DF426B /* tempomap.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE820375CD5801029006 /* tempomap.c */; }; + 3D5CD8900B5BC75E00DF426B /* timebase.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE840375CD5801029006 /* timebase.c */; }; + 3D5CD8910B5BC75E00DF426B /* userio.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EE860375CD5801029006 /* userio.c */; }; + 3D5CD8920B5BC75E00DF426B /* debug.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60AE039D87B001029006 /* debug.c */; }; + 3D5CD8930B5BC75E00DF426B /* falloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60B2039D87B001029006 /* falloc.c */; }; + 3D5CD8940B5BC75E00DF426B /* add.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60A7039D87B001029006 /* add.c */; }; + 3D5CD8950B5BC75E00DF426B /* local.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60C0039D87B001029006 /* local.c */; }; + 3D5CD8960B5BC75E00DF426B /* downsample.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60B0039D87B001029006 /* downsample.c */; }; + 3D5CD8970B5BC75E00DF426B /* handlers.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60BD039D87B001029006 /* handlers.c */; }; + 3D5CD8980B5BC75E00DF426B /* multiread.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60C3039D87B001029006 /* multiread.c */; }; + 3D5CD8990B5BC75E00DF426B /* multiseq.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60C5039D87B001029006 /* multiseq.c */; }; + 3D5CD89A0B5BC75E00DF426B /* samples.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60D0039D87B001029006 /* samples.c */; }; + 3D5CD89B0B5BC75E00DF426B /* seqext.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60D2039D87B001029006 /* seqext.c */; }; + 3D5CD89C0B5BC75E00DF426B /* seqinterf.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60D7039D87B001029006 /* seqinterf.c */; }; + 3D5CD89D0B5BC75E00DF426B /* sndread.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60DF039D87B001029006 /* sndread.c */; }; + 3D5CD89E0B5BC75E00DF426B /* sndseq.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60E1039D87B001029006 /* sndseq.c */; }; + 3D5CD89F0B5BC75E00DF426B /* sndwritepa.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60E5039D87B001029006 /* sndwritepa.c */; }; + 3D5CD8A00B5BC75E00DF426B /* sndmax.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60DD039D87B001029006 /* sndmax.c */; }; + 3D5CD8A10B5BC75E00DF426B /* sound.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60E6039D87B001029006 /* sound.c */; }; + 3D5CD8A20B5BC75E00DF426B /* stats.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60E8039D87B001029006 /* stats.c */; }; + 3D5CD8A30B5BC75E00DF426B /* compose.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60AB039D87B001029006 /* compose.c */; }; + 3D5CD8A40B5BC75E00DF426B /* inverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60BE039D87B001029006 /* inverse.c */; }; + 3D5CD8A50B5BC75E00DF426B /* resamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60CB039D87B001029006 /* resamp.c */; }; + 3D5CD8A60B5BC75E00DF426B /* resampv.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60CD039D87B001029006 /* resampv.c */; }; + 3D5CD8A70B5BC75E00DF426B /* ffilterkit.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60B4039D87B001029006 /* ffilterkit.c */; }; + 3D5CD8A80B5BC75E00DF426B /* avg.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60A9039D87B001029006 /* avg.c */; }; + 3D5CD8A90B5BC75E00DF426B /* fft.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF60B7039D87B001029006 /* fft.c */; }; + 3D5CD8AA0B5BC75E00DF426B /* seqfnint.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF615C039D899F01029006 /* seqfnint.c */; }; + 3D5CD8AB0B5BC75E00DF426B /* sndfnint.c in Sources */ = {isa = PBXBuildFile; fileRef = F5FF6162039D89B101029006 /* sndfnint.c */; }; + 3D5CD8B20B5BC75E00DF426B /* tapf.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9867CC04FFDD3C0002CE69 /* tapf.c */; }; + 3D5CD8B40B5BC75E00DF426B /* ieeecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = F543EF4A0375CD7101029006 /* ieeecvt.c */; }; + 3D5CD8B50B5BC75E00DF426B /* term.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9867D304FFE8E20002CE69 /* term.c */; }; + 3D5CD8B60B5BC75E00DF426B /* yin.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9867D505091F760002CE69 /* yin.c */; }; + 3D5CD8B70B5BC75E00DF426B /* alpasscv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9867D7050920060002CE69 /* alpasscv.c */; }; + 3D5CD8B80B5BC75E00DF426B /* alpassvv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9867DD050920400002CE69 /* alpassvv.c */; }; + 3D5CD8B90B5BC75E00DF426B /* eqbandvvv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9867E1050920730002CE69 /* eqbandvvv.c */; }; + 3D5CD8BA0B5BC75E00DF426B /* path.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9867E5050921720002CE69 /* path.c */; }; + 3D5CD8BB0B5BC75E00DF426B /* convolve.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E07DC0779F4800002CE69 /* convolve.c */; }; + 3D5CD8BC0B5BC75E00DF426B /* delaycc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E07E00779F4DC0002CE69 /* delaycc.c */; }; + 3D5CD8C80B5BC75E00DF426B /* instr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08300779F78B0002CE69 /* instr.cpp */; }; + 3D5CD8C90B5BC75E00DF426B /* Clarinet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08340779F7A30002CE69 /* Clarinet.cpp */; }; + 3D5CD8CA0B5BC75E00DF426B /* Delay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08360779F7B80002CE69 /* Delay.cpp */; }; + 3D5CD8CB0B5BC75E00DF426B /* DelayL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08370779F7B80002CE69 /* DelayL.cpp */; }; + 3D5CD8CC0B5BC75E00DF426B /* Envelope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08380779F7B80002CE69 /* Envelope.cpp */; }; + 3D5CD8CD0B5BC75E00DF426B /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08390779F7B80002CE69 /* Filter.cpp */; }; + 3D5CD8CE0B5BC75E00DF426B /* Instrmnt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E083A0779F7B80002CE69 /* Instrmnt.cpp */; }; + 3D5CD8CF0B5BC75E00DF426B /* Noise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E083B0779F7B80002CE69 /* Noise.cpp */; }; + 3D5CD8D00B5BC75E00DF426B /* OneZero.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E083C0779F7B80002CE69 /* OneZero.cpp */; }; + 3D5CD8D20B5BC75E00DF426B /* Saxofony.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E083E0779F7B80002CE69 /* Saxofony.cpp */; }; + 3D5CD8D30B5BC75E00DF426B /* Stk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E083F0779F7B80002CE69 /* Stk.cpp */; }; + 3D5CD8D40B5BC75E00DF426B /* WaveLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08400779F7B80002CE69 /* WaveLoop.cpp */; }; + 3D5CD8D50B5BC75E00DF426B /* WvIn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08410779F7B80002CE69 /* WvIn.cpp */; }; + 3D5CD8D60B5BC75E00DF426B /* stkinit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E084E077C6FC00002CE69 /* stkinit.cpp */; }; + 3D5CD8D70B5BC75E00DF426B /* lpanal.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E086A0789D6000002CE69 /* lpanal.c */; }; + 3D5CD8D80B5BC75E00DF426B /* alpassvc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E086E0789D81B0002CE69 /* alpassvc.c */; }; + 3D5CD8D90B5BC75E00DF426B /* allpoles.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08720789D82F0002CE69 /* allpoles.c */; }; + 3D5CD8DA0B5BC75E00DF426B /* f0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08760789D8520002CE69 /* f0.cpp */; }; + 3D5CD8DB0B5BC75E00DF426B /* instrclar.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E087A0789D8B20002CE69 /* instrclar.c */; }; + 3D5CD8DC0B5BC75E00DF426B /* instrsaxall.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E087E0789D8CF0002CE69 /* instrsaxall.c */; }; + 3D5CD8DD0B5BC75E00DF426B /* lpreson.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08820789D8E70002CE69 /* lpreson.c */; }; + 3D5CD8DE0B5BC75E00DF426B /* instrclarall.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08860789D9100002CE69 /* instrclarall.c */; }; + 3D5CD8DF0B5BC75E00DF426B /* instrsaxfreq.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E088A0789D9230002CE69 /* instrsaxfreq.c */; }; + 3D5CD8E00B5BC75E00DF426B /* instrclarfreq.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E088E0789D9430002CE69 /* instrclarfreq.c */; }; + 3D5CD8E10B5BC75E00DF426B /* instrsax.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E08920789D9680002CE69 /* instrsax.c */; }; + 3D5CD8E40B5BC75E00DF426B /* sliders.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D81ED240A76B1290053113C /* sliders.c */; }; + 3D5CD8EE0B5BC75E00DF426B /* trigger.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DAB7FB20B30690F00A51A49 /* trigger.c */; }; + 3D5CD9050B5BC78900DF426B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DA446C00789FF350002CE69 /* AudioToolbox.framework */; }; + 3D5CD9060B5BC78900DF426B /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DA446C20789FF430002CE69 /* CoreAudio.framework */; }; + 3D7327DF125BFB31009AAF15 /* JavaApplicationStub in Copy Executable */ = {isa = PBXBuildFile; fileRef = 3D7327DE125BFB19009AAF15 /* JavaApplicationStub */; }; + 3D7327FC125BFCCE009AAF15 /* ny in Copy Java Resources */ = {isa = PBXBuildFile; fileRef = 3D5CD82D0B5BC73700DF426B /* ny */; }; + 3DA1194A0D2DE1BF00948714 /* DelayA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119350D2DE1BF00948714 /* DelayA.cpp */; }; + 3DA1194B0D2DE1BF00948714 /* Effect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119360D2DE1BF00948714 /* Effect.cpp */; }; + 3DA1194C0D2DE1BF00948714 /* FileRead.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119370D2DE1BF00948714 /* FileRead.cpp */; }; + 3DA1194D0D2DE1BF00948714 /* FileWvIn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119380D2DE1BF00948714 /* FileWvIn.cpp */; }; + 3DA1194E0D2DE1BF00948714 /* Flute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119390D2DE1BF00948714 /* Flute.cpp */; }; + 3DA1194F0D2DE1BF00948714 /* Function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1193A0D2DE1BF00948714 /* Function.cpp */; }; + 3DA119500D2DE1BF00948714 /* Generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1193B0D2DE1BF00948714 /* Generator.cpp */; }; + 3DA119510D2DE1BF00948714 /* JCRev.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1193C0D2DE1BF00948714 /* JCRev.cpp */; }; + 3DA119520D2DE1BF00948714 /* JetTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1193D0D2DE1BF00948714 /* JetTable.cpp */; }; + 3DA119530D2DE1BF00948714 /* Mandolin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1193E0D2DE1BF00948714 /* Mandolin.cpp */; }; + 3DA119540D2DE1BF00948714 /* Modal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1193F0D2DE1BF00948714 /* Modal.cpp */; }; + 3DA119550D2DE1BF00948714 /* ModalBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119400D2DE1BF00948714 /* ModalBar.cpp */; }; + 3DA119560D2DE1BF00948714 /* NRev.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119410D2DE1BF00948714 /* NRev.cpp */; }; + 3DA119570D2DE1BF00948714 /* OnePole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119420D2DE1BF00948714 /* OnePole.cpp */; }; + 3DA119580D2DE1BF00948714 /* PitShift.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119430D2DE1BF00948714 /* PitShift.cpp */; }; + 3DA119590D2DE1BF00948714 /* PluckTwo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119440D2DE1BF00948714 /* PluckTwo.cpp */; }; + 3DA1195A0D2DE1BF00948714 /* PoleZero.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119450D2DE1BF00948714 /* PoleZero.cpp */; }; + 3DA1195B0D2DE1BF00948714 /* PRCRev.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119460D2DE1BF00948714 /* PRCRev.cpp */; }; + 3DA1195C0D2DE1BF00948714 /* ReedTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119470D2DE1BF00948714 /* ReedTable.cpp */; }; + 3DA1195D0D2DE1BF00948714 /* SineWave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119480D2DE1BF00948714 /* SineWave.cpp */; }; + 3DA1195E0D2DE1BF00948714 /* Sitar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119490D2DE1BF00948714 /* Sitar.cpp */; }; + 3DA119680D2DE2AA00948714 /* ADSR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119620D2DE2AA00948714 /* ADSR.cpp */; }; + 3DA119690D2DE2AA00948714 /* BandedWG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119630D2DE2AA00948714 /* BandedWG.cpp */; }; + 3DA1196A0D2DE2AA00948714 /* BiQuad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119640D2DE2AA00948714 /* BiQuad.cpp */; }; + 3DA1196B0D2DE2AA00948714 /* Bowed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119650D2DE2AA00948714 /* Bowed.cpp */; }; + 3DA1196C0D2DE2AA00948714 /* BowTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119660D2DE2AA00948714 /* BowTable.cpp */; }; + 3DA1196D0D2DE2AA00948714 /* Chorus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119670D2DE2AA00948714 /* Chorus.cpp */; }; + 3DA119710D2DE52400948714 /* instrbanded.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1196F0D2DE52400948714 /* instrbanded.c */; }; + 3DA119740D2DE54500948714 /* instrbow.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119720D2DE54500948714 /* instrbow.c */; }; + 3DA119770D2DE56200948714 /* instrbowedfreq.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119750D2DE56200948714 /* instrbowedfreq.c */; }; + 3DA1197A0D2DE57100948714 /* instrflute.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119780D2DE57100948714 /* instrflute.c */; }; + 3DA1197D0D2DE58A00948714 /* instrfluteall.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1197B0D2DE58A00948714 /* instrfluteall.c */; }; + 3DA119800D2DE59A00948714 /* instrflutefreq.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA1197E0D2DE59A00948714 /* instrflutefreq.c */; }; + 3DA119830D2DE5AA00948714 /* instrsitar.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119810D2DE5AA00948714 /* instrsitar.c */; }; + 3DA119860D2DE5BA00948714 /* stkpitshift.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119840D2DE5BA00948714 /* stkpitshift.c */; }; + 3DA119890D2DE5CF00948714 /* stkrev.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119870D2DE5CF00948714 /* stkrev.c */; }; + 3DA119950D2DE71700948714 /* biquadfilt.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119930D2DE71700948714 /* biquadfilt.c */; }; + 3DA1199A0D2DE88B00948714 /* stkint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DA119980D2DE88B00948714 /* stkint.cpp */; }; + 3DA120FD0D313E1B00948714 /* stkchorus.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA120FC0D313E1B00948714 /* stkchorus.c */; }; + 3DA120FF0D313E5500948714 /* instrmandolin.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA120FE0D313E5500948714 /* instrmandolin.c */; }; + 3DA121020D313E7C00948714 /* instrmodalbar.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA121000D313E7C00948714 /* instrmodalbar.c */; }; + 3DA7D7CC12B93C74008E62B1 /* cmdline.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DF21F3404FD526A0002CE69 /* cmdline.c */; }; + 3DA7D7CD12B93C8A008E62B1 /* intgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DF21F4004FD526A0002CE69 /* intgen.c */; }; + 3DBB0A6A1290422300024DD7 /* pa_allocation.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A691290422300024DD7 /* pa_allocation.c */; }; + 3DBB0A82129042A500024DD7 /* pa_converters.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A6C129042A500024DD7 /* pa_converters.c */; }; + 3DBB0A83129042A500024DD7 /* pa_cpuload.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A6E129042A500024DD7 /* pa_cpuload.c */; }; + 3DBB0A84129042A500024DD7 /* pa_debugprint.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A70129042A500024DD7 /* pa_debugprint.c */; }; + 3DBB0A85129042A500024DD7 /* pa_dither.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A72129042A500024DD7 /* pa_dither.c */; }; + 3DBB0A86129042A500024DD7 /* pa_front.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A75129042A500024DD7 /* pa_front.c */; }; + 3DBB0A87129042A500024DD7 /* pa_process.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A77129042A500024DD7 /* pa_process.c */; }; + 3DBB0A89129042A500024DD7 /* pa_skeleton.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A7B129042A500024DD7 /* pa_skeleton.c */; }; + 3DBB0A8A129042A500024DD7 /* pa_stream.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A7C129042A500024DD7 /* pa_stream.c */; }; + 3DBB0A8B129042A500024DD7 /* pa_trace.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A7E129042A500024DD7 /* pa_trace.c */; }; + 3DBB0A8E1290437E00024DD7 /* pa_mac_hostapis.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A8D1290437E00024DD7 /* pa_mac_hostapis.c */; }; + 3DBB0A90129043A900024DD7 /* pa_mac_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A8F129043A900024DD7 /* pa_mac_core.c */; }; + 3DBB0A9C129048D400024DD7 /* pa_mac_core_blocking.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A99129048D400024DD7 /* pa_mac_core_blocking.c */; }; + 3DBB0A9F129048F700024DD7 /* pa_mac_core_utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0A9D129048F700024DD7 /* pa_mac_core_utilities.c */; }; + 3DBB0AAB12904B5E00024DD7 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DBB0AAA12904B5E00024DD7 /* CoreServices.framework */; }; + 3DBB0AB012904BBB00024DD7 /* pa_unix_util.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0AAE12904BBB00024DD7 /* pa_unix_util.c */; }; + 3DBB0AB512904C0800024DD7 /* pa_ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DBB0AB312904C0800024DD7 /* pa_ringbuffer.c */; }; + 3DBB0ABA12904C2600024DD7 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DBB0AA412904AEB00024DD7 /* AudioUnit.framework */; }; + 3DC916F60D4036DC00DD66C0 /* fmfb.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DC916F40D4036DC00DD66C0 /* fmfb.c */; }; + 3DC916F90D4036F000DD66C0 /* fmfbv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DC916F70D4036F000DD66C0 /* fmfbv.c */; }; + 3DE80D670F7EA825003761D2 /* pvshell.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DE80D660F7EA825003761D2 /* pvshell.c */; }; + 3DE80D690F7EA840003761D2 /* phasevocoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DE80D680F7EA840003761D2 /* phasevocoder.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 3D3221710F53D4DF00F074EF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3D32216F0F53D4C300F074EF; + remoteInfo = liblo; + }; + 3D3533A40F0BD8A80059CD05 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3D3533810F0BD6CA0059CD05; + remoteInfo = libsndfile; + }; + 3D6C06C512D8FE6A0027E89B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3D32216F0F53D4C300F074EF; + remoteInfo = liblo; + }; + 3D6C06D012D8FF430027E89B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3D32216F0F53D4C300F074EF; + remoteInfo = liblo; + }; + 3D7327DB125BF99D009AAF15 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3D7327A5125BF5D8009AAF15; + remoteInfo = CompileJava; + }; + 3DBB0A5512903B0200024DD7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3D5CD82C0B5BC73700DF426B; + remoteInfo = ny; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 3D7327B9125BF675009AAF15 /* Copy Executable */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 6; + files = ( + 3D7327DF125BFB31009AAF15 /* JavaApplicationStub in Copy Executable */, + ); + name = "Copy Executable"; + runOnlyForDeploymentPostprocessing = 0; + }; + 3D7327C8125BF6BA009AAF15 /* Copy Java Resources */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 15; + files = ( + 3D177689125CB411007B2152 /* jnyqide.jar in Copy Java Resources */, + 3D7327FC125BFCCE009AAF15 /* ny in Copy Java Resources */, + 3D177699125CB593007B2152 /* closeFile.gif in Copy Java Resources */, + 3D17769A125CB593007B2152 /* help.gif in Copy Java Resources */, + 3D17769B125CB593007B2152 /* openFile.gif in Copy Java Resources */, + 3D17769C125CB593007B2152 /* NyquistWords.txt in Copy Java Resources */, + 3D17769D125CB593007B2152 /* runtime in Copy Java Resources */, + 3D17769E125CB593007B2152 /* lib in Copy Java Resources */, + 3D17769F125CB593007B2152 /* demos in Copy Java Resources */, + 3D1776A0125CB593007B2152 /* system.lsp in Copy Java Resources */, + ); + name = "Copy Java Resources"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 3D0817550AD01DB10051B745 /* osc-test-client */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "osc-test-client"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3D0817BA0AD0219B0051B745 /* test-client.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = "test-client.c"; path = "liblo/test-client/test-client.c"; sourceTree = ""; }; + 3D1472C70A799DFF00F00E71 /* Nyquist.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Nyquist.icns; sourceTree = ""; }; + 3D1472CD0A799E8500F00E71 /* browser.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = browser.java; sourceTree = ""; }; + 3D1472CF0A799E9B00F00E71 /* InstrumentCharacteristics.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = InstrumentCharacteristics.java; sourceTree = ""; }; + 3D1472D20A799ECC00F00E71 /* SpringUtilities.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = SpringUtilities.java; sourceTree = ""; }; + 3D16EA010A866123006DADB6 /* ReplaceDialog.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = ReplaceDialog.java; sourceTree = ""; }; + 3D177688125CB40C007B2152 /* jnyqide.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; name = jnyqide.jar; path = ../jnyqide/jnyqide.jar; sourceTree = SOURCE_ROOT; }; + 3D32213F0F53D42D00F074EF /* address.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = address.c; sourceTree = ""; }; + 3D3221400F53D42D00F074EF /* blob.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = blob.c; sourceTree = ""; }; + 3D3221410F53D42D00F074EF /* bundle.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bundle.c; sourceTree = ""; }; + 3D3221420F53D42D00F074EF /* lo_internal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_internal.h; sourceTree = ""; }; + 3D3221430F53D42D00F074EF /* lo_types_internal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_types_internal.h; sourceTree = ""; }; + 3D3221450F53D42D00F074EF /* message.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = message.c; sourceTree = ""; }; + 3D3221460F53D42D00F074EF /* method.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = method.c; sourceTree = ""; }; + 3D3221470F53D42D00F074EF /* pattern_match.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = pattern_match.c; sourceTree = ""; }; + 3D3221480F53D42D00F074EF /* send.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = send.c; sourceTree = ""; }; + 3D3221490F53D42D00F074EF /* server.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; + 3D32214B0F53D42D00F074EF /* subtest.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = subtest.c; sourceTree = ""; }; + 3D32214D0F53D42D00F074EF /* timetag.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = timetag.c; sourceTree = ""; }; + 3D3221620F53D47600F074EF /* lo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo.h; sourceTree = ""; }; + 3D3221630F53D47600F074EF /* lo_endian.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_endian.h; sourceTree = ""; }; + 3D3221640F53D47600F074EF /* lo_endian.h.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = lo_endian.h.in; sourceTree = ""; }; + 3D3221650F53D47600F074EF /* lo_errors.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_errors.h; sourceTree = ""; }; + 3D3221660F53D47600F074EF /* lo_lowlevel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_lowlevel.h; sourceTree = ""; }; + 3D3221670F53D47600F074EF /* lo_macros.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_macros.h; sourceTree = ""; }; + 3D3221680F53D47600F074EF /* lo_osc_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_osc_types.h; sourceTree = ""; }; + 3D3221690F53D47600F074EF /* lo_throw.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_throw.h; sourceTree = ""; }; + 3D32216A0F53D47600F074EF /* lo_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lo_types.h; sourceTree = ""; }; + 3D3221700F53D4C300F074EF /* libliblo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libliblo.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 3D3223280F544BBB00F074EF /* nyq-osc-server.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "nyq-osc-server.c"; sourceTree = ""; }; + 3D3223A20F54582900F074EF /* ser-to-osc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "ser-to-osc.cpp"; path = "liblo/ser-to-osc/ser-to-osc.cpp"; sourceTree = ""; }; + 3D3223A40F54585500F074EF /* Serial.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Serial.cpp; path = "liblo/ser-to-osc/Serial.cpp"; sourceTree = ""; }; + 3D3223A50F54585500F074EF /* Serial.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Serial.h; path = "liblo/ser-to-osc/Serial.h"; sourceTree = ""; }; + 3D3533820F0BD6CA0059CD05 /* liblibsndfile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblibsndfile.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 3D35338A0F0BD7C60059CD05 /* sndfile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sndfile.h; path = nylsf/sndfile.h; sourceTree = ""; }; + 3D35338B0F0BD7C60059CD05 /* sndfile.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sndfile.c; path = nylsf/sndfile.c; sourceTree = ""; }; + 3D3533A80F0BDA290059CD05 /* common.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = common.c; path = nylsf/common.c; sourceTree = ""; }; + 3D3533AC0F0BDA7C0059CD05 /* file_io.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = file_io.c; path = nylsf/file_io.c; sourceTree = ""; }; + 3D3533B50F0BDE2E0059CD05 /* aiff.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = aiff.c; path = nylsf/aiff.c; sourceTree = ""; }; + 3D3533B60F0BDE2E0059CD05 /* alaw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = alaw.c; path = nylsf/alaw.c; sourceTree = ""; }; + 3D3533B70F0BDE2E0059CD05 /* au.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = au.c; path = nylsf/au.c; sourceTree = ""; }; + 3D3533B80F0BDE2E0059CD05 /* avr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = avr.c; path = nylsf/avr.c; sourceTree = ""; }; + 3D3533B90F0BDE2E0059CD05 /* broadcast.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = broadcast.c; path = nylsf/broadcast.c; sourceTree = ""; }; + 3D3533BA0F0BDE2E0059CD05 /* caf.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = caf.c; path = nylsf/caf.c; sourceTree = ""; }; + 3D3533C10F0BDE610059CD05 /* dither.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dither.c; path = nylsf/dither.c; sourceTree = ""; }; + 3D3533C20F0BDE610059CD05 /* double64.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = double64.c; path = nylsf/double64.c; sourceTree = ""; }; + 3D3533C30F0BDE610059CD05 /* dwd.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dwd.c; path = nylsf/dwd.c; sourceTree = ""; }; + 3D3533C70F0BDE930059CD05 /* flac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = flac.c; path = nylsf/flac.c; sourceTree = ""; }; + 3D3533C80F0BDE930059CD05 /* float_cast.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = float_cast.h; path = nylsf/float_cast.h; sourceTree = ""; }; + 3D3533C90F0BDE930059CD05 /* float32.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = float32.c; path = nylsf/float32.c; sourceTree = ""; }; + 3D3533CD0F0BDEAA0059CD05 /* htk.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = htk.c; path = nylsf/htk.c; sourceTree = ""; }; + 3D3533CF0F0BDEC30059CD05 /* mat4.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = mat4.c; path = nylsf/mat4.c; sourceTree = ""; }; + 3D3533D00F0BDEC30059CD05 /* mat5.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = mat5.c; path = nylsf/mat5.c; sourceTree = ""; }; + 3D3533D30F0BDEE70059CD05 /* nist.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = nist.c; path = nylsf/nist.c; sourceTree = ""; }; + 3D3533D40F0BDEE70059CD05 /* ogg.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ogg.c; path = nylsf/ogg.c; sourceTree = ""; }; + 3D3533D50F0BDEE70059CD05 /* paf.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = paf.c; path = nylsf/paf.c; sourceTree = ""; }; + 3D3533D60F0BDEE70059CD05 /* pcm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = pcm.c; path = nylsf/pcm.c; sourceTree = ""; }; + 3D3533D70F0BDEE70059CD05 /* pvf.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = pvf.c; path = nylsf/pvf.c; sourceTree = ""; }; + 3D3533D80F0BDEE70059CD05 /* raw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = raw.c; path = nylsf/raw.c; sourceTree = ""; }; + 3D3533DF0F0BDF060059CD05 /* rx2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = rx2.c; path = nylsf/rx2.c; sourceTree = ""; }; + 3D3533E00F0BDF060059CD05 /* sd2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sd2.c; path = nylsf/sd2.c; sourceTree = ""; }; + 3D3533E10F0BDF060059CD05 /* sds.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sds.c; path = nylsf/sds.c; sourceTree = ""; }; + 3D3533E60F0BDF3B0059CD05 /* ircam.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ircam.c; path = nylsf/ircam.c; sourceTree = ""; }; + 3D3533E80F0BDF5E0059CD05 /* dwvw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dwvw.c; path = nylsf/dwvw.c; sourceTree = ""; }; + 3D3533E90F0BDF5E0059CD05 /* g72x.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = g72x.c; path = nylsf/g72x.c; sourceTree = ""; }; + 3D3533EA0F0BDF5E0059CD05 /* gsm610.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = gsm610.c; path = nylsf/gsm610.c; sourceTree = ""; }; + 3D3533EE0F0BDFA20059CD05 /* vox_adpcm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = vox_adpcm.c; path = nylsf/vox_adpcm.c; sourceTree = ""; }; + 3D3533EF0F0BDFA20059CD05 /* w64.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = w64.c; path = nylsf/w64.c; sourceTree = ""; }; + 3D3533F00F0BDFA20059CD05 /* wav_w64.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = wav_w64.c; path = nylsf/wav_w64.c; sourceTree = ""; }; + 3D3533F10F0BDFA20059CD05 /* wav_w64.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = wav_w64.h; path = nylsf/wav_w64.h; sourceTree = ""; }; + 3D3533F20F0BDFA20059CD05 /* wav.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = wav.c; path = nylsf/wav.c; sourceTree = ""; }; + 3D3533F30F0BDFA20059CD05 /* wve.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = wve.c; path = nylsf/wve.c; sourceTree = ""; }; + 3D3533F40F0BDFA20059CD05 /* xi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = xi.c; path = nylsf/xi.c; sourceTree = ""; }; + 3D3533FC0F0BDFD80059CD05 /* command.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = command.c; path = nylsf/command.c; sourceTree = ""; }; + 3D3533FD0F0BDFD80059CD05 /* common.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = common.h; path = nylsf/common.h; sourceTree = ""; }; + 3D35340B0F0BE0470059CD05 /* strings.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = strings.c; path = nylsf/strings.c; sourceTree = ""; }; + 3D35340C0F0BE0470059CD05 /* svx.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = svx.c; path = nylsf/svx.c; sourceTree = ""; }; + 3D3534100F0BE27E0059CD05 /* ima_adpcm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ima_adpcm.c; path = nylsf/ima_adpcm.c; sourceTree = ""; }; + 3D3534130F0BE2AA0059CD05 /* txw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = txw.c; path = nylsf/txw.c; sourceTree = ""; }; + 3D3534140F0BE2AA0059CD05 /* ulaw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ulaw.c; path = nylsf/ulaw.c; sourceTree = ""; }; + 3D3534150F0BE2AA0059CD05 /* voc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = voc.c; path = nylsf/voc.c; sourceTree = ""; }; + 3D35341A0F0BE3240059CD05 /* ms_adpcm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ms_adpcm.c; path = nylsf/ms_adpcm.c; sourceTree = ""; }; + 3D3534280F0BE5370059CD05 /* g72x.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = g72x.c; path = nylsf/G72x/g72x.c; sourceTree = ""; }; + 3D3534290F0BE5370059CD05 /* g72x.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = g72x.h; path = nylsf/G72x/g72x.h; sourceTree = ""; }; + 3D35342C0F0BE5510059CD05 /* gsm_create.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = gsm_create.c; path = nylsf/GSM610/gsm_create.c; sourceTree = ""; }; + 3D35342D0F0BE5510059CD05 /* gsm_decode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = gsm_decode.c; path = nylsf/GSM610/gsm_decode.c; sourceTree = ""; }; + 3D35342E0F0BE5510059CD05 /* gsm_destroy.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = gsm_destroy.c; path = nylsf/GSM610/gsm_destroy.c; sourceTree = ""; }; + 3D35342F0F0BE5510059CD05 /* gsm_encode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = gsm_encode.c; path = nylsf/GSM610/gsm_encode.c; sourceTree = ""; }; + 3D3534350F0BE58D0059CD05 /* code.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = code.c; path = nylsf/GSM610/code.c; sourceTree = ""; }; + 3D3534370F0BE58D0059CD05 /* decode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = decode.c; path = nylsf/GSM610/decode.c; sourceTree = ""; }; + 3D3534380F0BE58D0059CD05 /* gsm_option.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = gsm_option.c; path = nylsf/GSM610/gsm_option.c; sourceTree = ""; }; + 3D3534390F0BE58D0059CD05 /* gsm.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = gsm.h; path = nylsf/GSM610/gsm.h; sourceTree = ""; }; + 3D35343F0F0BE5B50059CD05 /* g721.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = g721.c; path = nylsf/G72x/g721.c; sourceTree = ""; }; + 3D3534400F0BE5B50059CD05 /* g723_16.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = g723_16.c; path = nylsf/G72x/g723_16.c; sourceTree = ""; }; + 3D3534410F0BE5B50059CD05 /* g723_24.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = g723_24.c; path = nylsf/G72x/g723_24.c; sourceTree = ""; }; + 3D3534420F0BE5B50059CD05 /* g723_40.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = g723_40.c; path = nylsf/G72x/g723_40.c; sourceTree = ""; }; + 3D3534480F0BE5EB0059CD05 /* long_term.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = long_term.c; path = nylsf/GSM610/long_term.c; sourceTree = ""; }; + 3D3534490F0BE5EB0059CD05 /* lpc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = lpc.c; path = nylsf/GSM610/lpc.c; sourceTree = ""; }; + 3D35344A0F0BE5EB0059CD05 /* preprocess.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = preprocess.c; path = nylsf/GSM610/preprocess.c; sourceTree = ""; }; + 3D35344F0F0BE6190059CD05 /* rpe.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = rpe.c; path = nylsf/GSM610/rpe.c; sourceTree = ""; }; + 3D3534500F0BE6190059CD05 /* short_term.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = short_term.c; path = nylsf/GSM610/short_term.c; sourceTree = ""; }; + 3D3534510F0BE6190059CD05 /* table.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = table.c; path = nylsf/GSM610/table.c; sourceTree = ""; }; + 3D3534560F0BE6420059CD05 /* add.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = add.c; path = nylsf/GSM610/add.c; sourceTree = ""; }; + 3D3534570F0BE6420059CD05 /* gsm610_priv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = gsm610_priv.h; path = nylsf/GSM610/gsm610_priv.h; sourceTree = ""; }; + 3D35345A0F0BE6520059CD05 /* g72x_priv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = g72x_priv.h; path = nylsf/G72x/g72x_priv.h; sourceTree = ""; }; + 3D35A7C505690E180002CE69 /* closeFile.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = closeFile.gif; sourceTree = ""; }; + 3D35A7C605690E180002CE69 /* help.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = help.gif; sourceTree = ""; }; + 3D35A7C705690E180002CE69 /* LispFileFilter.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = LispFileFilter.java; sourceTree = ""; }; + 3D35A7C805690E180002CE69 /* Main.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = Main.java; sourceTree = ""; }; + 3D35A7C905690E180002CE69 /* MainFrame.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = MainFrame.java; sourceTree = ""; }; + 3D35A7CA05690E180002CE69 /* MainFrame_AboutBox.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = MainFrame_AboutBox.java; sourceTree = ""; }; + 3D35A7CB05690E180002CE69 /* NyqPlot.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = NyqPlot.java; sourceTree = ""; }; + 3D35A7CC05690E180002CE69 /* NyquistFile.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = NyquistFile.java; sourceTree = ""; }; + 3D35A7CD05690E180002CE69 /* NyquistThread.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = NyquistThread.java; sourceTree = ""; }; + 3D35A7CE05690E180002CE69 /* openFile.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = openFile.gif; sourceTree = ""; }; + 3D35A7CF05690E180002CE69 /* Pair.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = Pair.java; sourceTree = ""; }; + 3D35A7D005690E180002CE69 /* PlotFrame.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PlotFrame.java; sourceTree = ""; }; + 3D35A7D105690E180002CE69 /* PlotMouseAdapter.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PlotMouseAdapter.java; sourceTree = ""; }; + 3D36DDE60796D6D40002CE69 /* keywords.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = keywords.txt; sourceTree = ""; }; + 3D36DDEE0796E5CA0002CE69 /* run */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = run; path = osx/run; sourceTree = ""; }; + 3D36DDF20796E60F0002CE69 /* system.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = system.lsp; path = osx/system.lsp; sourceTree = ""; }; + 3D48B84B0F5993750073A251 /* fftlib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fftlib.c; path = ffts/src/fftlib.c; sourceTree = ""; }; + 3D48B84F0F5993A60073A251 /* fftext.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fftext.c; path = ffts/src/fftext.c; sourceTree = ""; }; + 3D48B86D0F599EE90073A251 /* matlib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = matlib.c; path = ffts/src/matlib.c; sourceTree = ""; }; + 3D587FD80B67A053002E40F9 /* SpecialMacHandler.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = SpecialMacHandler.java; sourceTree = ""; }; + 3D5CD82D0B5BC73700DF426B /* ny */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ny; sourceTree = BUILT_PRODUCTS_DIR; }; + 3D6032F50790A600007A3CA5 /* FindDialog.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = FindDialog.java; sourceTree = ""; }; + 3D6032F80790A618007A3CA5 /* NotFoundDialog.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = NotFoundDialog.java; sourceTree = ""; }; + 3D6032FA0790A62C007A3CA5 /* PreferencesDialog.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PreferencesDialog.java; sourceTree = ""; }; + 3D647D290AC9E7B800E699B7 /* EnvelopeFrame.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = EnvelopeFrame.java; sourceTree = ""; }; + 3D6D6B520D14CD8C00B20822 /* CodePane.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = CodePane.java; sourceTree = ""; }; + 3D6D6C200D178B7E00B20822 /* SalWordList.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; path = SalWordList.java; sourceTree = ""; }; + 3D7327B0125BF624009AAF15 /* NyquistIDE.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NyquistIDE.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3D7327B2125BF624009AAF15 /* NyquistIDE-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NyquistIDE-Info.plist"; sourceTree = ""; }; + 3D7327DE125BFB19009AAF15 /* JavaApplicationStub */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = JavaApplicationStub; path = /System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/MacOS/JavaApplicationStub; sourceTree = ""; }; + 3D7A6F830A7A6AB500098CAB /* demos */ = {isa = PBXFileReference; lastKnownFileType = folder; name = demos; path = ../demos; sourceTree = SOURCE_ROOT; }; + 3D7A6FC90A7A851B00098CAB /* Trie.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = Trie.java; sourceTree = ""; }; + 3D7A6FCA0A7A851B00098CAB /* WordList.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = WordList.java; sourceTree = ""; }; + 3D7A6FD10A7A85F900098CAB /* NyquistWords.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = NyquistWords.txt; sourceTree = ""; }; + 3D7E28BD0B3E3E540078F9A3 /* Piano_Roll.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = Piano_Roll.java; sourceTree = ""; }; + 3D7E29000B3EC8F90078F9A3 /* Jslide.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = Jslide.java; sourceTree = ""; }; + 3D81ED240A76B1290053113C /* sliders.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sliders.c; sourceTree = ""; }; + 3D81ED250A76B1290053113C /* sliders.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sliders.h; sourceTree = ""; }; + 3D91FF8B0B97CB3300565C3F /* BareBonesBrowserLaunch.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = BareBonesBrowserLaunch.java; sourceTree = ""; }; + 3D9867CC04FFDD3C0002CE69 /* tapf.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tapf.c; sourceTree = ""; }; + 3D9867CE04FFDD6B0002CE69 /* tapf.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tapf.h; sourceTree = ""; }; + 3D9867D304FFE8E20002CE69 /* term.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = term.c; sourceTree = ""; }; + 3D9867D505091F760002CE69 /* yin.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = yin.c; sourceTree = ""; }; + 3D9867D7050920060002CE69 /* alpasscv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = alpasscv.c; path = ../tran/alpasscv.c; sourceTree = ""; }; + 3D9867D9050920140002CE69 /* yin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = yin.h; sourceTree = ""; }; + 3D9867DB0509202C0002CE69 /* alpasscv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = alpasscv.h; path = ../tran/alpasscv.h; sourceTree = ""; }; + 3D9867DD050920400002CE69 /* alpassvv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = alpassvv.c; path = ../tran/alpassvv.c; sourceTree = ""; }; + 3D9867DE050920400002CE69 /* alpassvv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = alpassvv.h; path = ../tran/alpassvv.h; sourceTree = ""; }; + 3D9867E1050920730002CE69 /* eqbandvvv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = eqbandvvv.c; path = ../tran/eqbandvvv.c; sourceTree = ""; }; + 3D9867E2050920730002CE69 /* eqbandvvv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = eqbandvvv.h; path = ../tran/eqbandvvv.h; sourceTree = ""; }; + 3D9867E5050921720002CE69 /* path.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = path.c; path = ../xlisp/path.c; sourceTree = ""; }; + 3D9E07DC0779F4800002CE69 /* convolve.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = convolve.c; sourceTree = ""; }; + 3D9E07DD0779F4800002CE69 /* convolve.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = convolve.h; sourceTree = ""; }; + 3D9E07E00779F4DC0002CE69 /* delaycc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = delaycc.c; sourceTree = ""; }; + 3D9E07E10779F4DC0002CE69 /* delaycc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = delaycc.h; sourceTree = ""; }; + 3D9E08120779F7370002CE69 /* Clarinet.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Clarinet.h; path = nyqstk/include/Clarinet.h; sourceTree = ""; }; + 3D9E08140779F74C0002CE69 /* globals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = globals.h; path = nyqstk/globals.h; sourceTree = ""; }; + 3D9E08160779F7680002CE69 /* Delay.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Delay.h; path = nyqstk/include/Delay.h; sourceTree = ""; }; + 3D9E08170779F7680002CE69 /* DelayL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DelayL.h; path = nyqstk/include/DelayL.h; sourceTree = ""; }; + 3D9E08180779F7680002CE69 /* Envelope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Envelope.h; path = nyqstk/include/Envelope.h; sourceTree = ""; }; + 3D9E08190779F7680002CE69 /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Filter.h; path = nyqstk/include/Filter.h; sourceTree = ""; }; + 3D9E081A0779F7680002CE69 /* Instrmnt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Instrmnt.h; path = nyqstk/include/Instrmnt.h; sourceTree = ""; }; + 3D9E081B0779F7680002CE69 /* Noise.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Noise.h; path = nyqstk/include/Noise.h; sourceTree = ""; }; + 3D9E081C0779F7680002CE69 /* OneZero.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = OneZero.h; path = nyqstk/include/OneZero.h; sourceTree = ""; }; + 3D9E081E0779F7680002CE69 /* Saxofony.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Saxofony.h; path = nyqstk/include/Saxofony.h; sourceTree = ""; }; + 3D9E081F0779F7680002CE69 /* SKINI.msg */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = SKINI.msg; path = nyqstk/include/SKINI.msg; sourceTree = ""; }; + 3D9E08200779F7680002CE69 /* Stk.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Stk.h; path = nyqstk/include/Stk.h; sourceTree = ""; }; + 3D9E08210779F7680002CE69 /* WaveLoop.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = WaveLoop.h; path = nyqstk/include/WaveLoop.h; sourceTree = ""; }; + 3D9E08220779F7680002CE69 /* WvIn.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = WvIn.h; path = nyqstk/include/WvIn.h; sourceTree = ""; }; + 3D9E08300779F78B0002CE69 /* instr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = instr.cpp; path = nyqstk/instr.cpp; sourceTree = ""; }; + 3D9E08310779F78B0002CE69 /* instr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = instr.h; path = nyqstk/instr.h; sourceTree = ""; }; + 3D9E08340779F7A30002CE69 /* Clarinet.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Clarinet.cpp; path = nyqstk/src/Clarinet.cpp; sourceTree = ""; }; + 3D9E08360779F7B80002CE69 /* Delay.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Delay.cpp; path = nyqstk/src/Delay.cpp; sourceTree = ""; }; + 3D9E08370779F7B80002CE69 /* DelayL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DelayL.cpp; path = nyqstk/src/DelayL.cpp; sourceTree = ""; }; + 3D9E08380779F7B80002CE69 /* Envelope.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Envelope.cpp; path = nyqstk/src/Envelope.cpp; sourceTree = ""; }; + 3D9E08390779F7B80002CE69 /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Filter.cpp; path = nyqstk/src/Filter.cpp; sourceTree = ""; }; + 3D9E083A0779F7B80002CE69 /* Instrmnt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Instrmnt.cpp; path = nyqstk/src/Instrmnt.cpp; sourceTree = ""; }; + 3D9E083B0779F7B80002CE69 /* Noise.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Noise.cpp; path = nyqstk/src/Noise.cpp; sourceTree = ""; }; + 3D9E083C0779F7B80002CE69 /* OneZero.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = OneZero.cpp; path = nyqstk/src/OneZero.cpp; sourceTree = ""; }; + 3D9E083E0779F7B80002CE69 /* Saxofony.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Saxofony.cpp; path = nyqstk/src/Saxofony.cpp; sourceTree = ""; }; + 3D9E083F0779F7B80002CE69 /* Stk.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Stk.cpp; path = nyqstk/src/Stk.cpp; sourceTree = ""; }; + 3D9E08400779F7B80002CE69 /* WaveLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = WaveLoop.cpp; path = nyqstk/src/WaveLoop.cpp; sourceTree = ""; }; + 3D9E08410779F7B80002CE69 /* WvIn.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = WvIn.cpp; path = nyqstk/src/WvIn.cpp; sourceTree = ""; }; + 3D9E084E077C6FC00002CE69 /* stkinit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stkinit.cpp; path = nyqstk/stkinit.cpp; sourceTree = ""; }; + 3D9E084F077C6FC00002CE69 /* stkinit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = stkinit.h; path = nyqstk/stkinit.h; sourceTree = ""; }; + 3D9E086A0789D6000002CE69 /* lpanal.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = lpanal.c; sourceTree = ""; }; + 3D9E086B0789D6000002CE69 /* lpanal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lpanal.h; sourceTree = ""; }; + 3D9E086E0789D81B0002CE69 /* alpassvc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = alpassvc.c; path = ../tran/alpassvc.c; sourceTree = ""; }; + 3D9E086F0789D81B0002CE69 /* alpassvc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = alpassvc.h; path = ../tran/alpassvc.h; sourceTree = ""; }; + 3D9E08720789D82F0002CE69 /* allpoles.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = allpoles.c; path = ../tran/allpoles.c; sourceTree = ""; }; + 3D9E08730789D82F0002CE69 /* allpoles.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = allpoles.h; path = ../tran/allpoles.h; sourceTree = ""; }; + 3D9E08760789D8520002CE69 /* f0.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = f0.cpp; sourceTree = ""; }; + 3D9E08770789D8520002CE69 /* f0.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = f0.h; sourceTree = ""; }; + 3D9E087A0789D8B20002CE69 /* instrclar.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = instrclar.c; path = ../tran/instrclar.c; sourceTree = ""; }; + 3D9E087B0789D8B20002CE69 /* instrclar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = instrclar.h; path = ../tran/instrclar.h; sourceTree = ""; }; + 3D9E087E0789D8CF0002CE69 /* instrsaxall.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = instrsaxall.c; path = ../tran/instrsaxall.c; sourceTree = ""; }; + 3D9E087F0789D8CF0002CE69 /* instrsaxall.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = instrsaxall.h; path = ../tran/instrsaxall.h; sourceTree = ""; }; + 3D9E08820789D8E70002CE69 /* lpreson.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = lpreson.c; path = ../tran/lpreson.c; sourceTree = ""; }; + 3D9E08830789D8E70002CE69 /* lpreson.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = lpreson.h; path = ../tran/lpreson.h; sourceTree = ""; }; + 3D9E08860789D9100002CE69 /* instrclarall.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = instrclarall.c; path = ../tran/instrclarall.c; sourceTree = ""; }; + 3D9E08870789D9100002CE69 /* instrclarall.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = instrclarall.h; path = ../tran/instrclarall.h; sourceTree = ""; }; + 3D9E088A0789D9230002CE69 /* instrsaxfreq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = instrsaxfreq.c; path = ../tran/instrsaxfreq.c; sourceTree = ""; }; + 3D9E088B0789D9230002CE69 /* instrsaxfreq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = instrsaxfreq.h; path = ../tran/instrsaxfreq.h; sourceTree = ""; }; + 3D9E088E0789D9430002CE69 /* instrclarfreq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = instrclarfreq.c; path = ../tran/instrclarfreq.c; sourceTree = ""; }; + 3D9E088F0789D9430002CE69 /* instrclarfreq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = instrclarfreq.h; path = ../tran/instrclarfreq.h; sourceTree = ""; }; + 3D9E08920789D9680002CE69 /* instrsax.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = instrsax.c; path = ../tran/instrsax.c; sourceTree = ""; }; + 3D9E08930789D9680002CE69 /* instrsax.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = instrsax.h; path = ../tran/instrsax.h; sourceTree = ""; }; + 3DA119350D2DE1BF00948714 /* DelayA.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DelayA.cpp; path = nyqstk/src/DelayA.cpp; sourceTree = ""; }; + 3DA119360D2DE1BF00948714 /* Effect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Effect.cpp; path = nyqstk/src/Effect.cpp; sourceTree = ""; }; + 3DA119370D2DE1BF00948714 /* FileRead.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = FileRead.cpp; path = nyqstk/src/FileRead.cpp; sourceTree = ""; }; + 3DA119380D2DE1BF00948714 /* FileWvIn.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = FileWvIn.cpp; path = nyqstk/src/FileWvIn.cpp; sourceTree = ""; }; + 3DA119390D2DE1BF00948714 /* Flute.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Flute.cpp; path = nyqstk/src/Flute.cpp; sourceTree = ""; }; + 3DA1193A0D2DE1BF00948714 /* Function.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Function.cpp; path = nyqstk/src/Function.cpp; sourceTree = ""; }; + 3DA1193B0D2DE1BF00948714 /* Generator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Generator.cpp; path = nyqstk/src/Generator.cpp; sourceTree = ""; }; + 3DA1193C0D2DE1BF00948714 /* JCRev.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JCRev.cpp; path = nyqstk/src/JCRev.cpp; sourceTree = ""; }; + 3DA1193D0D2DE1BF00948714 /* JetTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JetTable.cpp; path = nyqstk/src/JetTable.cpp; sourceTree = ""; }; + 3DA1193E0D2DE1BF00948714 /* Mandolin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Mandolin.cpp; path = nyqstk/src/Mandolin.cpp; sourceTree = ""; }; + 3DA1193F0D2DE1BF00948714 /* Modal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Modal.cpp; path = nyqstk/src/Modal.cpp; sourceTree = ""; }; + 3DA119400D2DE1BF00948714 /* ModalBar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ModalBar.cpp; path = nyqstk/src/ModalBar.cpp; sourceTree = ""; }; + 3DA119410D2DE1BF00948714 /* NRev.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = NRev.cpp; path = nyqstk/src/NRev.cpp; sourceTree = ""; }; + 3DA119420D2DE1BF00948714 /* OnePole.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = OnePole.cpp; path = nyqstk/src/OnePole.cpp; sourceTree = ""; }; + 3DA119430D2DE1BF00948714 /* PitShift.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PitShift.cpp; path = nyqstk/src/PitShift.cpp; sourceTree = ""; }; + 3DA119440D2DE1BF00948714 /* PluckTwo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PluckTwo.cpp; path = nyqstk/src/PluckTwo.cpp; sourceTree = ""; }; + 3DA119450D2DE1BF00948714 /* PoleZero.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PoleZero.cpp; path = nyqstk/src/PoleZero.cpp; sourceTree = ""; }; + 3DA119460D2DE1BF00948714 /* PRCRev.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PRCRev.cpp; path = nyqstk/src/PRCRev.cpp; sourceTree = ""; }; + 3DA119470D2DE1BF00948714 /* ReedTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ReedTable.cpp; path = nyqstk/src/ReedTable.cpp; sourceTree = ""; }; + 3DA119480D2DE1BF00948714 /* SineWave.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SineWave.cpp; path = nyqstk/src/SineWave.cpp; sourceTree = ""; }; + 3DA119490D2DE1BF00948714 /* Sitar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sitar.cpp; path = nyqstk/src/Sitar.cpp; sourceTree = ""; }; + 3DA119620D2DE2AA00948714 /* ADSR.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ADSR.cpp; path = nyqstk/src/ADSR.cpp; sourceTree = ""; }; + 3DA119630D2DE2AA00948714 /* BandedWG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = BandedWG.cpp; path = nyqstk/src/BandedWG.cpp; sourceTree = ""; }; + 3DA119640D2DE2AA00948714 /* BiQuad.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = BiQuad.cpp; path = nyqstk/src/BiQuad.cpp; sourceTree = ""; }; + 3DA119650D2DE2AA00948714 /* Bowed.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Bowed.cpp; path = nyqstk/src/Bowed.cpp; sourceTree = ""; }; + 3DA119660D2DE2AA00948714 /* BowTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = BowTable.cpp; path = nyqstk/src/BowTable.cpp; sourceTree = ""; }; + 3DA119670D2DE2AA00948714 /* Chorus.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Chorus.cpp; path = nyqstk/src/Chorus.cpp; sourceTree = ""; }; + 3DA1196F0D2DE52400948714 /* instrbanded.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrbanded.c; sourceTree = ""; }; + 3DA119700D2DE52400948714 /* instrbanded.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrbanded.h; sourceTree = ""; }; + 3DA119720D2DE54500948714 /* instrbow.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrbow.c; sourceTree = ""; }; + 3DA119730D2DE54500948714 /* instrbow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrbow.h; sourceTree = ""; }; + 3DA119750D2DE56200948714 /* instrbowedfreq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrbowedfreq.c; sourceTree = ""; }; + 3DA119760D2DE56200948714 /* instrbowedfreq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrbowedfreq.h; sourceTree = ""; }; + 3DA119780D2DE57100948714 /* instrflute.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrflute.c; sourceTree = ""; }; + 3DA119790D2DE57100948714 /* instrflute.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrflute.h; sourceTree = ""; }; + 3DA1197B0D2DE58A00948714 /* instrfluteall.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrfluteall.c; sourceTree = ""; }; + 3DA1197C0D2DE58A00948714 /* instrfluteall.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrfluteall.h; sourceTree = ""; }; + 3DA1197E0D2DE59A00948714 /* instrflutefreq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrflutefreq.c; sourceTree = ""; }; + 3DA1197F0D2DE59A00948714 /* instrflutefreq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrflutefreq.h; sourceTree = ""; }; + 3DA119810D2DE5AA00948714 /* instrsitar.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrsitar.c; sourceTree = ""; }; + 3DA119820D2DE5AA00948714 /* instrsitar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrsitar.h; sourceTree = ""; }; + 3DA119840D2DE5BA00948714 /* stkpitshift.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = stkpitshift.c; sourceTree = ""; }; + 3DA119850D2DE5BA00948714 /* stkpitshift.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stkpitshift.h; sourceTree = ""; }; + 3DA119870D2DE5CF00948714 /* stkrev.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = stkrev.c; sourceTree = ""; }; + 3DA119880D2DE5CF00948714 /* stkrev.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stkrev.h; sourceTree = ""; }; + 3DA119930D2DE71700948714 /* biquadfilt.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = biquadfilt.c; sourceTree = ""; }; + 3DA119940D2DE71700948714 /* biquadfilt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = biquadfilt.h; sourceTree = ""; }; + 3DA119980D2DE88B00948714 /* stkint.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stkint.cpp; path = ../nyqstk/stkint.cpp; sourceTree = SOURCE_ROOT; }; + 3DA119990D2DE88B00948714 /* stkint.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = stkint.h; path = ../nyqstk/stkint.h; sourceTree = SOURCE_ROOT; }; + 3DA120FC0D313E1B00948714 /* stkchorus.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = stkchorus.c; sourceTree = ""; }; + 3DA120FE0D313E5500948714 /* instrmandolin.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrmandolin.c; sourceTree = ""; }; + 3DA121000D313E7C00948714 /* instrmodalbar.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instrmodalbar.c; sourceTree = ""; }; + 3DA121010D313E7C00948714 /* instrmodalbar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = instrmodalbar.h; sourceTree = ""; }; + 3DA446C00789FF350002CE69 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; + 3DA446C20789FF430002CE69 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; + 3DA7D7C412B93C08008E62B1 /* intgen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = intgen; sourceTree = BUILT_PRODUCTS_DIR; }; + 3DA7D7D212B93D20008E62B1 /* switches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = switches.h; path = ../sys/mac/switches.h; sourceTree = SOURCE_ROOT; }; + 3DA7D7DD12B9406B008E62B1 /* switches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = switches.h; path = ../sys/unix/switches.h; sourceTree = SOURCE_ROOT; }; + 3DAB7F290B2E172300A51A49 /* ser-to-osc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ser-to-osc"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3DAB7FB20B30690F00A51A49 /* trigger.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = trigger.c; sourceTree = ""; }; + 3DBB0A691290422300024DD7 /* pa_allocation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_allocation.c; path = portaudio/src/common/pa_allocation.c; sourceTree = ""; }; + 3DBB0A6B129042A500024DD7 /* pa_allocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_allocation.h; path = portaudio/src/common/pa_allocation.h; sourceTree = ""; }; + 3DBB0A6C129042A500024DD7 /* pa_converters.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_converters.c; path = portaudio/src/common/pa_converters.c; sourceTree = ""; }; + 3DBB0A6D129042A500024DD7 /* pa_converters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_converters.h; path = portaudio/src/common/pa_converters.h; sourceTree = ""; }; + 3DBB0A6E129042A500024DD7 /* pa_cpuload.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_cpuload.c; path = portaudio/src/common/pa_cpuload.c; sourceTree = ""; }; + 3DBB0A6F129042A500024DD7 /* pa_cpuload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_cpuload.h; path = portaudio/src/common/pa_cpuload.h; sourceTree = ""; }; + 3DBB0A70129042A500024DD7 /* pa_debugprint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_debugprint.c; path = portaudio/src/common/pa_debugprint.c; sourceTree = ""; }; + 3DBB0A71129042A500024DD7 /* pa_debugprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_debugprint.h; path = portaudio/src/common/pa_debugprint.h; sourceTree = ""; }; + 3DBB0A72129042A500024DD7 /* pa_dither.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_dither.c; path = portaudio/src/common/pa_dither.c; sourceTree = ""; }; + 3DBB0A73129042A500024DD7 /* pa_dither.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_dither.h; path = portaudio/src/common/pa_dither.h; sourceTree = ""; }; + 3DBB0A74129042A500024DD7 /* pa_endianness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_endianness.h; path = portaudio/src/common/pa_endianness.h; sourceTree = ""; }; + 3DBB0A75129042A500024DD7 /* pa_front.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_front.c; path = portaudio/src/common/pa_front.c; sourceTree = ""; }; + 3DBB0A76129042A500024DD7 /* pa_hostapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_hostapi.h; path = portaudio/src/common/pa_hostapi.h; sourceTree = ""; }; + 3DBB0A77129042A500024DD7 /* pa_process.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_process.c; path = portaudio/src/common/pa_process.c; sourceTree = ""; }; + 3DBB0A78129042A500024DD7 /* pa_process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_process.h; path = portaudio/src/common/pa_process.h; sourceTree = ""; }; + 3DBB0A7B129042A500024DD7 /* pa_skeleton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_skeleton.c; path = portaudio/src/common/pa_skeleton.c; sourceTree = ""; }; + 3DBB0A7C129042A500024DD7 /* pa_stream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_stream.c; path = portaudio/src/common/pa_stream.c; sourceTree = ""; }; + 3DBB0A7D129042A500024DD7 /* pa_stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_stream.h; path = portaudio/src/common/pa_stream.h; sourceTree = ""; }; + 3DBB0A7E129042A500024DD7 /* pa_trace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_trace.c; path = portaudio/src/common/pa_trace.c; sourceTree = ""; }; + 3DBB0A7F129042A500024DD7 /* pa_trace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_trace.h; path = portaudio/src/common/pa_trace.h; sourceTree = ""; }; + 3DBB0A80129042A500024DD7 /* pa_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_types.h; path = portaudio/src/common/pa_types.h; sourceTree = ""; }; + 3DBB0A81129042A500024DD7 /* pa_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_util.h; path = portaudio/src/common/pa_util.h; sourceTree = ""; }; + 3DBB0A8C1290433500024DD7 /* portaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = portaudio.h; path = portaudio/include/portaudio.h; sourceTree = ""; }; + 3DBB0A8D1290437E00024DD7 /* pa_mac_hostapis.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_mac_hostapis.c; path = portaudio/src/os/mac_osx/pa_mac_hostapis.c; sourceTree = ""; }; + 3DBB0A8F129043A900024DD7 /* pa_mac_core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_mac_core.c; path = portaudio/src/hostapi/coreaudio/pa_mac_core.c; sourceTree = ""; }; + 3DBB0A99129048D400024DD7 /* pa_mac_core_blocking.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_mac_core_blocking.c; path = portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c; sourceTree = ""; }; + 3DBB0A9A129048D400024DD7 /* pa_mac_core_blocking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_mac_core_blocking.h; path = portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h; sourceTree = ""; }; + 3DBB0A9B129048D400024DD7 /* pa_mac_core_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_mac_core_internal.h; path = portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h; sourceTree = ""; }; + 3DBB0A9D129048F700024DD7 /* pa_mac_core_utilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_mac_core_utilities.c; path = portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c; sourceTree = ""; }; + 3DBB0A9E129048F700024DD7 /* pa_mac_core_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_mac_core_utilities.h; path = portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.h; sourceTree = ""; }; + 3DBB0AA412904AEB00024DD7 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; + 3DBB0AAA12904B5E00024DD7 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; + 3DBB0AAE12904BBB00024DD7 /* pa_unix_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_unix_util.c; path = portaudio/src/os/unix/pa_unix_util.c; sourceTree = ""; }; + 3DBB0AAF12904BBB00024DD7 /* pa_unix_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_unix_util.h; path = portaudio/src/os/unix/pa_unix_util.h; sourceTree = ""; }; + 3DBB0AB312904C0800024DD7 /* pa_ringbuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pa_ringbuffer.c; path = portaudio/src/common/pa_ringbuffer.c; sourceTree = ""; }; + 3DBB0AB412904C0800024DD7 /* pa_ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_ringbuffer.h; path = portaudio/src/common/pa_ringbuffer.h; sourceTree = ""; }; + 3DBF98A20D4196E300B4588F /* MiniBrowser.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = MiniBrowser.java; sourceTree = ""; }; + 3DC916F40D4036DC00DD66C0 /* fmfb.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fmfb.c; sourceTree = ""; }; + 3DC916F50D4036DC00DD66C0 /* fmfb.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fmfb.h; sourceTree = ""; }; + 3DC916F70D4036F000DD66C0 /* fmfbv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fmfbv.c; sourceTree = ""; }; + 3DC916F80D4036F000DD66C0 /* fmfbv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fmfbv.h; sourceTree = ""; }; + 3DE0D0680B319B30003EAC5F /* PopupListener.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PopupListener.java; sourceTree = ""; }; + 3DE80D660F7EA825003761D2 /* pvshell.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = pvshell.c; path = ../nyqsrc/pvshell.c; sourceTree = SOURCE_ROOT; }; + 3DE80D680F7EA840003761D2 /* phasevocoder.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = phasevocoder.c; path = ../nyqsrc/phasevocoder.c; sourceTree = SOURCE_ROOT; }; + 3DF21F3204FD526A0002CE69 /* args.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = args.h; sourceTree = ""; }; + 3DF21F3304FD526A0002CE69 /* cext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cext.h; sourceTree = ""; }; + 3DF21F3404FD526A0002CE69 /* cmdline.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmdline.c; sourceTree = ""; }; + 3DF21F3504FD526A0002CE69 /* cmdline.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cmdline.h; sourceTree = ""; }; + 3DF21F3704FD526A0002CE69 /* cleanup.bat */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = cleanup.bat; sourceTree = ""; }; + 3DF21F3804FD526A0002CE69 /* cmu-linux-install.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "cmu-linux-install.lsp"; sourceTree = ""; }; + 3DF21F3904FD526A0002CE69 /* cmuinstall.bat */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = cmuinstall.bat; sourceTree = ""; }; + 3DF21F3A04FD526A0002CE69 /* init.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = init.lsp; sourceTree = ""; }; + 3DF21F3B04FD526A0002CE69 /* restore.bat */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = restore.bat; sourceTree = ""; }; + 3DF21F3C04FD526A0002CE69 /* convert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = convert.c; sourceTree = ""; }; + 3DF21F3D04FD526A0002CE69 /* convert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = convert.h; sourceTree = ""; }; + 3DF21F3E04FD526A0002CE69 /* filelist.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = filelist.c; sourceTree = ""; }; + 3DF21F3F04FD526A0002CE69 /* filelist.dsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = filelist.dsp; sourceTree = ""; }; + 3DF21F4004FD526A0002CE69 /* intgen.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = intgen.c; sourceTree = ""; }; + 3DF21F4104FD526A0002CE69 /* intgen2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = intgen2.c; sourceTree = ""; }; + 3DF21F4304FD526A0002CE69 /* intgen.dsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = intgen.dsp; sourceTree = ""; }; + 3DF21F4404FD526A0002CE69 /* mac-to-win.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "mac-to-win.lsp"; sourceTree = ""; }; + 3DF21F4504FD526A0002CE69 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + 3DF21F4604FD526A0002CE69 /* makefile.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = makefile.lsp; sourceTree = ""; }; + 3DF21F4704FD526A0002CE69 /* packer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = packer.c; sourceTree = ""; }; + 3DF21F4804FD526A0002CE69 /* packer.dsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = packer.dsp; sourceTree = ""; }; + 3DF21F4904FD526A0002CE69 /* play.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = play.c; sourceTree = ""; }; + 3DF21F4A04FD526A0002CE69 /* plot.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = plot.c; sourceTree = ""; }; + 3DF21F4B04FD526A0002CE69 /* sampleprint.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sampleprint.c; sourceTree = ""; }; + 3DF21F4C04FD526A0002CE69 /* sine.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sine.c; sourceTree = ""; }; + 3DF21F4D04FD526A0002CE69 /* stdefs2.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stdefs2.h; sourceTree = ""; }; + 3DF21F4E04FD526A0002CE69 /* transfiles.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = transfiles.lsp; sourceTree = ""; }; + 3DF21F4F04FD526A0002CE69 /* unpacker.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = unpacker.c; sourceTree = ""; }; + 3DF21F5004FD526A0002CE69 /* unpacker.dsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = unpacker.dsp; sourceTree = ""; }; + 3DFA3F730D1F03B0003CFE6B /* SalFileFilter.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; path = SalFileFilter.java; sourceTree = ""; }; + 3DFA3FBF0D1F8139003CFE6B /* TextColor.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = TextColor.java; sourceTree = ""; }; + F510BCA7039F84FD01029006 /* lib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder; path = lib; sourceTree = ""; }; + F510BCDA039F84FE01029006 /* runtime */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder; path = runtime; sourceTree = ""; }; + F510BD73039FB49C01029006 /* doc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder; path = doc; sourceTree = ""; }; + F53626EE03761E6C01029006 /* audiopa.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = audiopa.c; sourceTree = ""; }; + F543E76B0375C24D01029006 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CoreAudio.framework; sourceTree = ""; }; + F543E7750375C25A01029006 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AudioToolbox.framework; sourceTree = ""; }; + F543EE580375CD5801029006 /* cext.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cext.c; sourceTree = ""; }; + F543EE590375CD5801029006 /* cext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cext.h; sourceTree = ""; }; + F543EE5A0375CD5801029006 /* cleanup.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cleanup.c; sourceTree = ""; }; + F543EE5B0375CD5801029006 /* cleanup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cleanup.h; sourceTree = ""; }; + F543EE5C0375CD5801029006 /* cmdline.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmdline.c; sourceTree = ""; }; + F543EE5D0375CD5801029006 /* cmdline.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cmdline.h; sourceTree = ""; }; + F543EE5E0375CD5801029006 /* cmtcmd.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmtcmd.c; sourceTree = ""; }; + F543EE5F0375CD5801029006 /* cmtcmd.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cmtcmd.h; sourceTree = ""; }; + F543EE600375CD5801029006 /* cmtio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmtio.c; sourceTree = ""; }; + F543EE610375CD5801029006 /* cmtio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cmtio.h; sourceTree = ""; }; + F543EE620375CD5801029006 /* hash.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; + F543EE630375CD5801029006 /* hashrout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = hashrout.h; sourceTree = ""; }; + F543EE640375CD5801029006 /* mem.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mem.c; sourceTree = ""; }; + F543EE650375CD5801029006 /* mem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = ""; }; + F543EE660375CD5801029006 /* mfmidi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mfmidi.h; sourceTree = ""; }; + F543EE670375CD5801029006 /* midibuff.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = midibuff.h; sourceTree = ""; }; + F543EE680375CD5801029006 /* midicode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = midicode.h; sourceTree = ""; }; + F543EE690375CD5801029006 /* midierr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = midierr.h; sourceTree = ""; }; + F543EE6A0375CD5801029006 /* midifile.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = midifile.c; sourceTree = ""; }; + F543EE6B0375CD5801029006 /* midifile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = midifile.h; sourceTree = ""; }; + F543EE6C0375CD5801029006 /* midifns.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = midifns.c; sourceTree = ""; }; + F543EE6D0375CD5801029006 /* midifns.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = midifns.h; sourceTree = ""; }; + F543EE6E0375CD5801029006 /* midimgr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = midimgr.c; sourceTree = ""; }; + F543EE6F0375CD5801029006 /* midimgr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = midimgr.h; sourceTree = ""; }; + F543EE700375CD5801029006 /* moxc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = moxc.c; sourceTree = ""; }; + F543EE710375CD5801029006 /* moxc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = moxc.h; sourceTree = ""; }; + F543EE720375CD5801029006 /* musiprog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = musiprog.h; sourceTree = ""; }; + F543EE730375CD5801029006 /* pitch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pitch.h; sourceTree = ""; }; + F543EE740375CD5801029006 /* record.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = record.c; sourceTree = ""; }; + F543EE750375CD5801029006 /* record.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = record.h; sourceTree = ""; }; + F543EE760375CD5801029006 /* seq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seq.c; sourceTree = ""; }; + F543EE770375CD5801029006 /* seq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seq.h; sourceTree = ""; }; + F543EE780375CD5801029006 /* seqdecls.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqdecls.h; sourceTree = ""; }; + F543EE790375CD5801029006 /* seqmread.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seqmread.c; sourceTree = ""; }; + F543EE7A0375CD5801029006 /* seqmread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqmread.h; sourceTree = ""; }; + F543EE7B0375CD5801029006 /* seqmwrite.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seqmwrite.c; sourceTree = ""; }; + F543EE7C0375CD5801029006 /* seqmwrite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqmwrite.h; sourceTree = ""; }; + F543EE7D0375CD5801029006 /* seqread.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seqread.c; sourceTree = ""; }; + F543EE7E0375CD5801029006 /* seqread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqread.h; sourceTree = ""; }; + F543EE7F0375CD5801029006 /* seqwrite.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seqwrite.c; sourceTree = ""; }; + F543EE800375CD5801029006 /* seqwrite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqwrite.h; sourceTree = ""; }; + F543EE810375CD5801029006 /* swlogic.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = swlogic.h; sourceTree = ""; }; + F543EE820375CD5801029006 /* tempomap.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tempomap.c; sourceTree = ""; }; + F543EE830375CD5801029006 /* tempomap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tempomap.h; sourceTree = ""; }; + F543EE840375CD5801029006 /* timebase.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = timebase.c; sourceTree = ""; }; + F543EE850375CD5801029006 /* timebase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = timebase.h; sourceTree = ""; }; + F543EE860375CD5801029006 /* userio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = userio.c; sourceTree = ""; }; + F543EE870375CD5801029006 /* userio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = userio.h; sourceTree = ""; }; + F543EF4A0375CD7101029006 /* ieeecvt.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ieeecvt.c; sourceTree = ""; }; + F543EF4B0375CD7101029006 /* ieeecvt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ieeecvt.h; sourceTree = ""; }; + F543EF4D0375CD7101029006 /* snd.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = snd.c; sourceTree = ""; }; + F543EF4E0375CD7101029006 /* snd.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = snd.h; sourceTree = ""; }; + F543EF510375CD7101029006 /* sndconfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndconfig.h; sourceTree = ""; }; + F543EF520375CD7101029006 /* sndcvt.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndcvt.c; sourceTree = ""; }; + F543EF550375CD7101029006 /* sndfileio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndfileio.h; sourceTree = ""; }; + F543EF570375CD7101029006 /* sndhead.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndhead.h; sourceTree = ""; }; + F543EF580375CD7101029006 /* sndheader.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndheader.c; sourceTree = ""; }; + F543EF590375CD7101029006 /* sndheader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndheader.h; sourceTree = ""; }; + F543EF5A0375CD7101029006 /* sndio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndio.c; sourceTree = ""; }; + F543EF5D0375CD7101029006 /* sndmac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndmac.c; sourceTree = ""; }; + F543EF5E0375CD7101029006 /* sndmac.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndmac.h; sourceTree = ""; }; + F543EF620375CD7101029006 /* sndsystem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndsystem.h; sourceTree = ""; }; + F543EF630375CD7101029006 /* sndsystemmac.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndsystemmac.h; sourceTree = ""; }; + F543EF660375CD7101029006 /* sndwrite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndwrite.h; sourceTree = ""; }; + F543EFBF0375CD9901029006 /* osstuff.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = osstuff.c; sourceTree = ""; }; + F5DA143903A1108C01029006 /* README */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README; sourceTree = ""; }; + F5FF5F49039D84B901029006 /* extern.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = extern.c; sourceTree = ""; }; + F5FF5F4A039D84B901029006 /* extern.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = ""; }; + F5FF5F4B039D84B901029006 /* osdefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osdefs.h; sourceTree = ""; }; + F5FF5F4C039D84B901029006 /* osptrs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osptrs.h; sourceTree = ""; }; + F5FF5F4D039D84B901029006 /* xlbfun.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlbfun.c; sourceTree = ""; }; + F5FF5F4E039D84B901029006 /* xlcont.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlcont.c; sourceTree = ""; }; + F5FF5F4F039D84B901029006 /* xldbug.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xldbug.c; sourceTree = ""; }; + F5FF5F50039D84B901029006 /* xldmem.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xldmem.c; sourceTree = ""; }; + F5FF5F51039D84B901029006 /* xldmem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = xldmem.h; sourceTree = ""; }; + F5FF5F52039D84B901029006 /* xleval.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xleval.c; sourceTree = ""; }; + F5FF5F53039D84B901029006 /* xlfio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlfio.c; sourceTree = ""; }; + F5FF5F54039D84B901029006 /* xlftab.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlftab.c; sourceTree = ""; }; + F5FF5F55039D84B901029006 /* xlglob.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlglob.c; sourceTree = ""; }; + F5FF5F56039D84B901029006 /* xlimage.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlimage.c; sourceTree = ""; }; + F5FF5F57039D84B901029006 /* xlinit.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlinit.c; sourceTree = ""; }; + F5FF5F58039D84B901029006 /* xlio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlio.c; sourceTree = ""; }; + F5FF5F59039D84B901029006 /* xlisp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlisp.c; sourceTree = ""; }; + F5FF5F5A039D84B901029006 /* xlisp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = xlisp.h; sourceTree = ""; }; + F5FF5F5B039D84B901029006 /* xljump.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xljump.c; sourceTree = ""; }; + F5FF5F5C039D84B901029006 /* xllist.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xllist.c; sourceTree = ""; }; + F5FF5F5D039D84B901029006 /* xlmath.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlmath.c; sourceTree = ""; }; + F5FF5F5E039D84B901029006 /* xlobj.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlobj.c; sourceTree = ""; }; + F5FF5F5F039D84B901029006 /* xlpp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlpp.c; sourceTree = ""; }; + F5FF5F60039D84B901029006 /* xlprin.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlprin.c; sourceTree = ""; }; + F5FF5F61039D84B901029006 /* xlread.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlread.c; sourceTree = ""; }; + F5FF5F62039D84B901029006 /* xlstr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlstr.c; sourceTree = ""; }; + F5FF5F63039D84B901029006 /* xlsubr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlsubr.c; sourceTree = ""; }; + F5FF5F64039D84B901029006 /* xlsym.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlsym.c; sourceTree = ""; }; + F5FF5F65039D84B901029006 /* xlsys.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = xlsys.c; sourceTree = ""; }; + F5FF5FA1039D866201029006 /* abs.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = abs.c; sourceTree = ""; }; + F5FF5FA2039D866201029006 /* abs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = abs.h; sourceTree = ""; }; + F5FF5FA3039D866201029006 /* alpass.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = alpass.c; sourceTree = ""; }; + F5FF5FA4039D866201029006 /* alpass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = alpass.h; sourceTree = ""; }; + F5FF5FA5039D866201029006 /* amosc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = amosc.c; sourceTree = ""; }; + F5FF5FA6039D866201029006 /* amosc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = amosc.h; sourceTree = ""; }; + F5FF5FA7039D866201029006 /* areson.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = areson.c; sourceTree = ""; }; + F5FF5FA8039D866201029006 /* areson.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = areson.h; sourceTree = ""; }; + F5FF5FA9039D866201029006 /* aresoncv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = aresoncv.c; sourceTree = ""; }; + F5FF5FAA039D866201029006 /* aresoncv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aresoncv.h; sourceTree = ""; }; + F5FF5FAB039D866201029006 /* aresonvc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = aresonvc.c; sourceTree = ""; }; + F5FF5FAC039D866201029006 /* aresonvc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aresonvc.h; sourceTree = ""; }; + F5FF5FAD039D866201029006 /* aresonvv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = aresonvv.c; sourceTree = ""; }; + F5FF5FAE039D866201029006 /* aresonvv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aresonvv.h; sourceTree = ""; }; + F5FF5FAF039D866201029006 /* atone.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = atone.c; sourceTree = ""; }; + F5FF5FB0039D866201029006 /* atone.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = atone.h; sourceTree = ""; }; + F5FF5FB1039D866201029006 /* atonev.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = atonev.c; sourceTree = ""; }; + F5FF5FB2039D866201029006 /* atonev.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = atonev.h; sourceTree = ""; }; + F5FF5FB5039D866201029006 /* buzz.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = buzz.c; sourceTree = ""; }; + F5FF5FB6039D866201029006 /* buzz.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = buzz.h; sourceTree = ""; }; + F5FF5FB7039D866201029006 /* chase.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = chase.c; sourceTree = ""; }; + F5FF5FB8039D866201029006 /* chase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = chase.h; sourceTree = ""; }; + F5FF5FB9039D866201029006 /* clip.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = clip.c; sourceTree = ""; }; + F5FF5FBA039D866201029006 /* clip.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clip.h; sourceTree = ""; }; + F5FF5FBB039D866201029006 /* congen.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = congen.c; sourceTree = ""; }; + F5FF5FBC039D866201029006 /* congen.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = congen.h; sourceTree = ""; }; + F5FF5FBD039D866201029006 /* const.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = const.c; sourceTree = ""; }; + F5FF5FBE039D866201029006 /* const.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = const.h; sourceTree = ""; }; + F5FF5FC1039D866201029006 /* coterm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = coterm.c; sourceTree = ""; }; + F5FF5FC2039D866201029006 /* coterm.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = coterm.h; sourceTree = ""; }; + F5FF5FC5039D866201029006 /* delaycv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = delaycv.c; sourceTree = ""; }; + F5FF5FC6039D866201029006 /* delaycv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = delaycv.h; sourceTree = ""; }; + F5FF5FC7039D866201029006 /* exp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = exp.c; sourceTree = ""; }; + F5FF5FC8039D866201029006 /* exp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = exp.h; sourceTree = ""; }; + F5FF5FC9039D866201029006 /* fmosc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fmosc.c; sourceTree = ""; }; + F5FF5FCA039D866201029006 /* fmosc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fmosc.h; sourceTree = ""; }; + F5FF5FCB039D866201029006 /* follow.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = follow.c; sourceTree = ""; }; + F5FF5FCC039D866201029006 /* follow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = follow.h; sourceTree = ""; }; + F5FF5FCD039D866201029006 /* fromarraystream.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fromarraystream.c; sourceTree = ""; }; + F5FF5FCE039D866201029006 /* fromarraystream.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fromarraystream.h; sourceTree = ""; }; + F5FF5FCF039D866201029006 /* fromobject.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fromobject.c; sourceTree = ""; }; + F5FF5FD0039D866201029006 /* fromobject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fromobject.h; sourceTree = ""; }; + F5FF5FD1039D866201029006 /* gate.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gate.c; sourceTree = ""; }; + F5FF5FD2039D866201029006 /* gate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gate.h; sourceTree = ""; }; + F5FF5FD3039D866201029006 /* ifft.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ifft.c; sourceTree = ""; }; + F5FF5FD4039D866201029006 /* ifft.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ifft.h; sourceTree = ""; }; + F5FF5FD5039D866201029006 /* integrate.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = integrate.c; sourceTree = ""; }; + F5FF5FD6039D866201029006 /* integrate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = integrate.h; sourceTree = ""; }; + F5FF5FD7039D866201029006 /* log.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = ""; }; + F5FF5FD8039D866201029006 /* log.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; + F5FF5FD9039D866201029006 /* maxv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = maxv.c; sourceTree = ""; }; + F5FF5FDA039D866201029006 /* maxv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = maxv.h; sourceTree = ""; }; + F5FF5FDB039D866201029006 /* offset.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = offset.c; sourceTree = ""; }; + F5FF5FDC039D866201029006 /* offset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = offset.h; sourceTree = ""; }; + F5FF5FDD039D866201029006 /* oneshot.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = oneshot.c; sourceTree = ""; }; + F5FF5FDE039D866201029006 /* oneshot.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oneshot.h; sourceTree = ""; }; + F5FF5FDF039D866201029006 /* osc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = osc.c; sourceTree = ""; }; + F5FF5FE0039D866201029006 /* osc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osc.h; sourceTree = ""; }; + F5FF5FE1039D866201029006 /* partial.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = partial.c; sourceTree = ""; }; + F5FF5FE2039D866201029006 /* partial.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = partial.h; sourceTree = ""; }; + F5FF5FE3039D866201029006 /* pluck.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = pluck.c; sourceTree = ""; }; + F5FF5FE4039D866201029006 /* pluck.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pluck.h; sourceTree = ""; }; + F5FF5FE5039D866201029006 /* prod.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = prod.c; sourceTree = ""; }; + F5FF5FE6039D866201029006 /* prod.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prod.h; sourceTree = ""; }; + F5FF5FE7039D866201029006 /* pwl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = pwl.c; sourceTree = ""; }; + F5FF5FE8039D866201029006 /* pwl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pwl.h; sourceTree = ""; }; + F5FF5FEB039D866201029006 /* quantize.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = quantize.c; sourceTree = ""; }; + F5FF5FEC039D866201029006 /* quantize.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = quantize.h; sourceTree = ""; }; + F5FF5FED039D866201029006 /* recip.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = recip.c; sourceTree = ""; }; + F5FF5FEE039D866201029006 /* recip.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = recip.h; sourceTree = ""; }; + F5FF5FEF039D866201029006 /* reson.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = reson.c; sourceTree = ""; }; + F5FF5FF0039D866201029006 /* reson.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reson.h; sourceTree = ""; }; + F5FF5FF1039D866201029006 /* resoncv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = resoncv.c; sourceTree = ""; }; + F5FF5FF2039D866201029006 /* resoncv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = resoncv.h; sourceTree = ""; }; + F5FF5FF3039D866201029006 /* resonvc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = resonvc.c; sourceTree = ""; }; + F5FF5FF4039D866201029006 /* resonvc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = resonvc.h; sourceTree = ""; }; + F5FF5FF5039D866201029006 /* resonvv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = resonvv.c; sourceTree = ""; }; + F5FF5FF6039D866201029006 /* resonvv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = resonvv.h; sourceTree = ""; }; + F5FF5FF7039D866201029006 /* sampler.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sampler.c; sourceTree = ""; }; + F5FF5FF8039D866201029006 /* sampler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sampler.h; sourceTree = ""; }; + F5FF5FF9039D866201029006 /* scale.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = scale.c; sourceTree = ""; }; + F5FF5FFA039D866201029006 /* scale.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = scale.h; sourceTree = ""; }; + F5FF5FFB039D866201029006 /* shape.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = shape.c; sourceTree = ""; }; + F5FF5FFC039D866201029006 /* shape.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = shape.h; sourceTree = ""; }; + F5FF5FFD039D866201029006 /* sine.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sine.c; sourceTree = ""; }; + F5FF5FFE039D866201029006 /* sine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sine.h; sourceTree = ""; }; + F5FF5FFF039D866201029006 /* siosc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = siosc.c; sourceTree = ""; }; + F5FF6000039D866201029006 /* siosc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = siosc.h; sourceTree = ""; }; + F5FF6001039D866201029006 /* slope.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = slope.c; sourceTree = ""; }; + F5FF6002039D866201029006 /* slope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = slope.h; sourceTree = ""; }; + F5FF6003039D866201029006 /* sqrt.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sqrt.c; sourceTree = ""; }; + F5FF6004039D866201029006 /* sqrt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sqrt.h; sourceTree = ""; }; + F5FF6005039D866201029006 /* tapv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tapv.c; sourceTree = ""; }; + F5FF6006039D866201029006 /* tapv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tapv.h; sourceTree = ""; }; + F5FF6007039D866201029006 /* tone.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tone.c; sourceTree = ""; }; + F5FF6008039D866201029006 /* tone.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tone.h; sourceTree = ""; }; + F5FF6009039D866201029006 /* tonev.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tonev.c; sourceTree = ""; }; + F5FF600A039D866201029006 /* tonev.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tonev.h; sourceTree = ""; }; + F5FF600B039D866201029006 /* upsample.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = upsample.c; sourceTree = ""; }; + F5FF600C039D866201029006 /* upsample.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = upsample.h; sourceTree = ""; }; + F5FF600D039D866201029006 /* white.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = white.c; sourceTree = ""; }; + F5FF600E039D866201029006 /* white.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = white.h; sourceTree = ""; }; + F5FF60A7039D87B001029006 /* add.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = add.c; sourceTree = ""; }; + F5FF60A8039D87B001029006 /* add.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = add.h; sourceTree = ""; }; + F5FF60A9039D87B001029006 /* avg.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = avg.c; sourceTree = ""; }; + F5FF60AA039D87B001029006 /* avg.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = avg.h; sourceTree = ""; }; + F5FF60AB039D87B001029006 /* compose.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = compose.c; sourceTree = ""; }; + F5FF60AC039D87B001029006 /* compose.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = compose.h; sourceTree = ""; }; + F5FF60AD039D87B001029006 /* cque.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cque.h; sourceTree = ""; }; + F5FF60AE039D87B001029006 /* debug.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = debug.c; sourceTree = ""; }; + F5FF60AF039D87B001029006 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; + F5FF60B0039D87B001029006 /* downsample.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = downsample.c; sourceTree = ""; }; + F5FF60B1039D87B001029006 /* downsample.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = downsample.h; sourceTree = ""; }; + F5FF60B2039D87B001029006 /* falloc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = falloc.c; sourceTree = ""; }; + F5FF60B3039D87B001029006 /* falloc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = falloc.h; sourceTree = ""; }; + F5FF60B4039D87B001029006 /* ffilterkit.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ffilterkit.c; sourceTree = ""; }; + F5FF60B5039D87B001029006 /* ffilterkit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ffilterkit.h; sourceTree = ""; }; + F5FF60B6039D87B001029006 /* fft-rbd.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "fft-rbd.c"; sourceTree = ""; }; + F5FF60B7039D87B001029006 /* fft.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fft.c; sourceTree = ""; }; + F5FF60B8039D87B001029006 /* fft.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fft.h; sourceTree = ""; }; + F5FF60B9039D87B001029006 /* fftr4.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fftr4.c; sourceTree = ""; }; + F5FF60BA039D87B001029006 /* fftw.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fftw.h; sourceTree = ""; }; + F5FF60BB039D87B001029006 /* fresample.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fresample.h; sourceTree = ""; }; + F5FF60BC039D87B001029006 /* fsmallfilter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fsmallfilter.h; sourceTree = ""; }; + F5FF60BD039D87B001029006 /* handlers.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = handlers.c; sourceTree = ""; }; + F5FF60BE039D87B001029006 /* inverse.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = inverse.c; sourceTree = ""; }; + F5FF60BF039D87B001029006 /* inverse.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = inverse.h; sourceTree = ""; }; + F5FF60C0039D87B001029006 /* local.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = local.c; sourceTree = ""; }; + F5FF60C1039D87B001029006 /* localdefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = localdefs.h; sourceTree = ""; }; + F5FF60C2039D87B001029006 /* localptrs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = localptrs.h; sourceTree = ""; }; + F5FF60C3039D87B001029006 /* multiread.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = multiread.c; sourceTree = ""; }; + F5FF60C4039D87B001029006 /* multiread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = multiread.h; sourceTree = ""; }; + F5FF60C5039D87B001029006 /* multiseq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = multiseq.c; sourceTree = ""; }; + F5FF60C6039D87B001029006 /* multiseq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = multiseq.h; sourceTree = ""; }; + F5FF60C7039D87B001029006 /* nfilterkit.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = nfilterkit.c; sourceTree = ""; }; + F5FF60C8039D87B001029006 /* nfilterkit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nfilterkit.h; sourceTree = ""; }; + F5FF60C9039D87B001029006 /* probe.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = probe.c; sourceTree = ""; }; + F5FF60CA039D87B001029006 /* probe.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = probe.h; sourceTree = ""; }; + F5FF60CB039D87B001029006 /* resamp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = resamp.c; sourceTree = ""; }; + F5FF60CC039D87B001029006 /* resamp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = resamp.h; sourceTree = ""; }; + F5FF60CD039D87B001029006 /* resampv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = resampv.c; sourceTree = ""; }; + F5FF60CE039D87B001029006 /* resampv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = resampv.h; sourceTree = ""; }; + F5FF60CF039D87B001029006 /* rfftw.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rfftw.h; sourceTree = ""; }; + F5FF60D0039D87B001029006 /* samples.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = samples.c; sourceTree = ""; }; + F5FF60D1039D87B001029006 /* samples.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = samples.h; sourceTree = ""; }; + F5FF60D2039D87B001029006 /* seqext.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seqext.c; sourceTree = ""; }; + F5FF60D3039D87B001029006 /* seqext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqext.h; sourceTree = ""; }; + F5FF60D4039D87B001029006 /* seqfn.wcl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = seqfn.wcl; sourceTree = ""; }; + F5FF60D6039D87B001029006 /* seqfnint.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = seqfnint.lsp; sourceTree = ""; }; + F5FF60D7039D87B001029006 /* seqinterf.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seqinterf.c; sourceTree = ""; }; + F5FF60D8039D87B001029006 /* seqinterf.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqinterf.h; sourceTree = ""; }; + F5FF60DA039D87B001029006 /* sndfn.wcl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = sndfn.wcl; sourceTree = ""; }; + F5FF60DC039D87B001029006 /* sndfnint.lsp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = sndfnint.lsp; sourceTree = ""; }; + F5FF60DD039D87B001029006 /* sndmax.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndmax.c; sourceTree = ""; }; + F5FF60DE039D87B001029006 /* sndmax.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndmax.h; sourceTree = ""; }; + F5FF60DF039D87B001029006 /* sndread.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndread.c; sourceTree = ""; }; + F5FF60E0039D87B001029006 /* sndread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndread.h; sourceTree = ""; }; + F5FF60E1039D87B001029006 /* sndseq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndseq.c; sourceTree = ""; }; + F5FF60E2039D87B001029006 /* sndseq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndseq.h; sourceTree = ""; }; + F5FF60E4039D87B001029006 /* sndwrite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndwrite.h; sourceTree = ""; }; + F5FF60E5039D87B001029006 /* sndwritepa.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndwritepa.c; sourceTree = ""; }; + F5FF60E6039D87B001029006 /* sound.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sound.c; sourceTree = ""; }; + F5FF60E7039D87B001029006 /* sound.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sound.h; sourceTree = ""; }; + F5FF60E8039D87B001029006 /* stats.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = stats.c; sourceTree = ""; }; + F5FF60E9039D87B001029006 /* stdefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stdefs.h; sourceTree = ""; }; + F5FF615C039D899F01029006 /* seqfnint.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = seqfnint.c; sourceTree = ""; }; + F5FF615D039D899F01029006 /* seqfnintdefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqfnintdefs.h; sourceTree = ""; }; + F5FF615E039D899F01029006 /* seqfnintptrs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seqfnintptrs.h; sourceTree = ""; }; + F5FF6162039D89B101029006 /* sndfnint.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sndfnint.c; sourceTree = ""; }; + F5FF6163039D89B101029006 /* sndfnintdefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndfnintdefs.h; sourceTree = ""; }; + F5FF6164039D89B101029006 /* sndfnintptrs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndfnintptrs.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3D0817530AD01DB10051B745 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D3223970F5455FA00F074EF /* libliblo.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D32216E0F53D4C300F074EF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D3533800F0BD6CA0059CD05 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D5CD82B0B5BC73700DF426B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D3223740F54539B00F074EF /* libliblo.a in Frameworks */, + 3D3533B30F0BDDE40059CD05 /* liblibsndfile.a in Frameworks */, + 3D5CD9050B5BC78900DF426B /* AudioToolbox.framework in Frameworks */, + 3D5CD9060B5BC78900DF426B /* CoreAudio.framework in Frameworks */, + 3DBB0AAB12904B5E00024DD7 /* CoreServices.framework in Frameworks */, + 3DBB0ABA12904C2600024DD7 /* AudioUnit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3DA7D7C212B93C08008E62B1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3DAB7F270B2E172300A51A49 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D3223990F54561400F074EF /* libliblo.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* MacOSXProject */ = { + isa = PBXGroup; + children = ( + 3DA7D7DD12B9406B008E62B1 /* switches.h */, + 3DA7D7D212B93D20008E62B1 /* switches.h */, + 3D7327DE125BFB19009AAF15 /* JavaApplicationStub */, + 3DE80D680F7EA840003761D2 /* phasevocoder.c */, + 3DE80D660F7EA825003761D2 /* pvshell.c */, + 3D7A6F830A7A6AB500098CAB /* demos */, + 3D1472C70A799DFF00F00E71 /* Nyquist.icns */, + F5DA143903A1108C01029006 /* README */, + F510BDB903A0314301029006 /* Frameworks */, + F543F19F0375E1E401029006 /* Source */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + 3DA446C00789FF350002CE69 /* AudioToolbox.framework */, + 3DA446C20789FF430002CE69 /* CoreAudio.framework */, + 3D7327B2125BF624009AAF15 /* NyquistIDE-Info.plist */, + 3DBB0AA412904AEB00024DD7 /* AudioUnit.framework */, + 3DBB0AAA12904B5E00024DD7 /* CoreServices.framework */, + ); + name = MacOSXProject; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* nyquist */ = { + isa = PBXGroup; + children = ( + 3D48B84E0F59937D0073A251 /* ffts */, + 3D3222F00F54475600F074EF /* nylsf */, + 3D32213D0F53D3B100F074EF /* liblo */, + 3D9E08110779F7050002CE69 /* stk */, + 3D9E07E60779F63A0002CE69 /* portaudio */, + F510BCA7039F84FD01029006 /* lib */, + F510BCDA039F84FE01029006 /* runtime */, + F510BD73039FB49C01029006 /* doc */, + F5FF5F48039D84B901029006 /* xlisp */, + F5FF5F9E039D863401029006 /* tran */, + F543EE570375CD5801029006 /* cmt */, + 3D35A7C405690E180002CE69 /* jnyqide */, + F5FF60A6039D87B001029006 /* nyqsrc */, + F543EF3D0375CD7101029006 /* snd */, + F543EF990375CD9901029006 /* sys */, + 3DF21F3104FD526A0002CE69 /* misc */, + ); + name = nyquist; + path = ..; + sourceTree = SOURCE_ROOT; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 3D0817550AD01DB10051B745 /* osc-test-client */, + 3D177688125CB40C007B2152 /* jnyqide.jar */, + 3DAB7F290B2E172300A51A49 /* ser-to-osc */, + 3D5CD82D0B5BC73700DF426B /* ny */, + 3D3533820F0BD6CA0059CD05 /* liblibsndfile.a */, + 3D3221700F53D4C300F074EF /* libliblo.a */, + 3D7327B0125BF624009AAF15 /* NyquistIDE.app */, + 3DA7D7C412B93C08008E62B1 /* intgen */, + ); + name = Products; + sourceTree = ""; + }; + 3D32213D0F53D3B100F074EF /* liblo */ = { + isa = PBXGroup; + children = ( + 3D3223A10F5457FB00F074EF /* ser-to-osc */, + 3D3223A00F5457EE00F074EF /* test-client */, + 3D3221610F53D47600F074EF /* lo */, + 3D32213E0F53D42D00F074EF /* src */, + ); + name = liblo; + sourceTree = ""; + }; + 3D32213E0F53D42D00F074EF /* src */ = { + isa = PBXGroup; + children = ( + 3D32213F0F53D42D00F074EF /* address.c */, + 3D3221400F53D42D00F074EF /* blob.c */, + 3D3221410F53D42D00F074EF /* bundle.c */, + 3D3221420F53D42D00F074EF /* lo_internal.h */, + 3D3221430F53D42D00F074EF /* lo_types_internal.h */, + 3D3221450F53D42D00F074EF /* message.c */, + 3D3221460F53D42D00F074EF /* method.c */, + 3D3221470F53D42D00F074EF /* pattern_match.c */, + 3D3221480F53D42D00F074EF /* send.c */, + 3D3221490F53D42D00F074EF /* server.c */, + 3D32214B0F53D42D00F074EF /* subtest.c */, + 3D32214D0F53D42D00F074EF /* timetag.c */, + ); + name = src; + path = liblo/src; + sourceTree = ""; + }; + 3D3221610F53D47600F074EF /* lo */ = { + isa = PBXGroup; + children = ( + 3D3221620F53D47600F074EF /* lo.h */, + 3D3221630F53D47600F074EF /* lo_endian.h */, + 3D3221640F53D47600F074EF /* lo_endian.h.in */, + 3D3221650F53D47600F074EF /* lo_errors.h */, + 3D3221660F53D47600F074EF /* lo_lowlevel.h */, + 3D3221670F53D47600F074EF /* lo_macros.h */, + 3D3221680F53D47600F074EF /* lo_osc_types.h */, + 3D3221690F53D47600F074EF /* lo_throw.h */, + 3D32216A0F53D47600F074EF /* lo_types.h */, + ); + name = lo; + path = liblo/lo; + sourceTree = ""; + }; + 3D3222F00F54475600F074EF /* nylsf */ = { + isa = PBXGroup; + children = ( + 3D3533E90F0BDF5E0059CD05 /* g72x.c */, + 3D3533EA0F0BDF5E0059CD05 /* gsm610.c */, + 3D3533E60F0BDF3B0059CD05 /* ircam.c */, + 3D3533DF0F0BDF060059CD05 /* rx2.c */, + 3D3533E00F0BDF060059CD05 /* sd2.c */, + 3D3533E10F0BDF060059CD05 /* sds.c */, + 3D3533D30F0BDEE70059CD05 /* nist.c */, + 3D3533D40F0BDEE70059CD05 /* ogg.c */, + 3D3533D50F0BDEE70059CD05 /* paf.c */, + 3D3533D60F0BDEE70059CD05 /* pcm.c */, + 3D3533D70F0BDEE70059CD05 /* pvf.c */, + 3D3533D80F0BDEE70059CD05 /* raw.c */, + 3D3533CF0F0BDEC30059CD05 /* mat4.c */, + 3D3533D00F0BDEC30059CD05 /* mat5.c */, + 3D3533CD0F0BDEAA0059CD05 /* htk.c */, + 3D3533C70F0BDE930059CD05 /* flac.c */, + 3D3533C80F0BDE930059CD05 /* float_cast.h */, + 3D3533C90F0BDE930059CD05 /* float32.c */, + 3D3533C10F0BDE610059CD05 /* dither.c */, + 3D3533C20F0BDE610059CD05 /* double64.c */, + 3D3533C30F0BDE610059CD05 /* dwd.c */, + 3D3533B50F0BDE2E0059CD05 /* aiff.c */, + 3D3533B60F0BDE2E0059CD05 /* alaw.c */, + 3D3533B70F0BDE2E0059CD05 /* au.c */, + 3D3533B80F0BDE2E0059CD05 /* avr.c */, + 3D3533B90F0BDE2E0059CD05 /* broadcast.c */, + 3D3533BA0F0BDE2E0059CD05 /* caf.c */, + 3D3533AC0F0BDA7C0059CD05 /* file_io.c */, + 3D3533A80F0BDA290059CD05 /* common.c */, + 3D35338A0F0BD7C60059CD05 /* sndfile.h */, + 3D35338B0F0BD7C60059CD05 /* sndfile.c */, + 3D35345A0F0BE6520059CD05 /* g72x_priv.h */, + 3D3534560F0BE6420059CD05 /* add.c */, + 3D3534570F0BE6420059CD05 /* gsm610_priv.h */, + 3D35344F0F0BE6190059CD05 /* rpe.c */, + 3D3534500F0BE6190059CD05 /* short_term.c */, + 3D3534510F0BE6190059CD05 /* table.c */, + 3D3534480F0BE5EB0059CD05 /* long_term.c */, + 3D3534490F0BE5EB0059CD05 /* lpc.c */, + 3D35344A0F0BE5EB0059CD05 /* preprocess.c */, + 3D35343F0F0BE5B50059CD05 /* g721.c */, + 3D3534400F0BE5B50059CD05 /* g723_16.c */, + 3D3534410F0BE5B50059CD05 /* g723_24.c */, + 3D3534420F0BE5B50059CD05 /* g723_40.c */, + 3D3534350F0BE58D0059CD05 /* code.c */, + 3D3534370F0BE58D0059CD05 /* decode.c */, + 3D3534380F0BE58D0059CD05 /* gsm_option.c */, + 3D3534390F0BE58D0059CD05 /* gsm.h */, + 3D35342C0F0BE5510059CD05 /* gsm_create.c */, + 3D35342D0F0BE5510059CD05 /* gsm_decode.c */, + 3D35342E0F0BE5510059CD05 /* gsm_destroy.c */, + 3D35342F0F0BE5510059CD05 /* gsm_encode.c */, + 3D3534280F0BE5370059CD05 /* g72x.c */, + 3D3534290F0BE5370059CD05 /* g72x.h */, + 3D35341A0F0BE3240059CD05 /* ms_adpcm.c */, + 3D3534130F0BE2AA0059CD05 /* txw.c */, + 3D3534140F0BE2AA0059CD05 /* ulaw.c */, + 3D3534150F0BE2AA0059CD05 /* voc.c */, + 3D3534100F0BE27E0059CD05 /* ima_adpcm.c */, + 3D35340B0F0BE0470059CD05 /* strings.c */, + 3D35340C0F0BE0470059CD05 /* svx.c */, + 3D3533FC0F0BDFD80059CD05 /* command.c */, + 3D3533FD0F0BDFD80059CD05 /* common.h */, + 3D3533EE0F0BDFA20059CD05 /* vox_adpcm.c */, + 3D3533EF0F0BDFA20059CD05 /* w64.c */, + 3D3533F00F0BDFA20059CD05 /* wav_w64.c */, + 3D3533F10F0BDFA20059CD05 /* wav_w64.h */, + 3D3533F20F0BDFA20059CD05 /* wav.c */, + 3D3533F30F0BDFA20059CD05 /* wve.c */, + 3D3533F40F0BDFA20059CD05 /* xi.c */, + 3D3533E80F0BDF5E0059CD05 /* dwvw.c */, + ); + name = nylsf; + sourceTree = ""; + }; + 3D3223A00F5457EE00F074EF /* test-client */ = { + isa = PBXGroup; + children = ( + 3D0817BA0AD0219B0051B745 /* test-client.c */, + ); + name = "test-client"; + sourceTree = ""; + }; + 3D3223A10F5457FB00F074EF /* ser-to-osc */ = { + isa = PBXGroup; + children = ( + 3D3223A40F54585500F074EF /* Serial.cpp */, + 3D3223A50F54585500F074EF /* Serial.h */, + 3D3223A20F54582900F074EF /* ser-to-osc.cpp */, + ); + name = "ser-to-osc"; + sourceTree = ""; + }; + 3D35A7C405690E180002CE69 /* jnyqide */ = { + isa = PBXGroup; + children = ( + 3D587FD80B67A053002E40F9 /* SpecialMacHandler.java */, + 3DFA3FBF0D1F8139003CFE6B /* TextColor.java */, + 3DFA3F730D1F03B0003CFE6B /* SalFileFilter.java */, + 3D6D6C200D178B7E00B20822 /* SalWordList.java */, + 3D6D6B520D14CD8C00B20822 /* CodePane.java */, + 3D91FF8B0B97CB3300565C3F /* BareBonesBrowserLaunch.java */, + 3D7E29000B3EC8F90078F9A3 /* Jslide.java */, + 3D7A6FC90A7A851B00098CAB /* Trie.java */, + 3D7A6FCA0A7A851B00098CAB /* WordList.java */, + 3D7A6FD10A7A85F900098CAB /* NyquistWords.txt */, + 3D1472D20A799ECC00F00E71 /* SpringUtilities.java */, + 3D1472CF0A799E9B00F00E71 /* InstrumentCharacteristics.java */, + 3D1472CD0A799E8500F00E71 /* browser.java */, + 3D35A7C505690E180002CE69 /* closeFile.gif */, + 3D6032F50790A600007A3CA5 /* FindDialog.java */, + 3D35A7C605690E180002CE69 /* help.gif */, + 3D35A7C705690E180002CE69 /* LispFileFilter.java */, + 3D35A7C805690E180002CE69 /* Main.java */, + 3D35A7C905690E180002CE69 /* MainFrame.java */, + 3DBF98A20D4196E300B4588F /* MiniBrowser.java */, + 3D35A7CA05690E180002CE69 /* MainFrame_AboutBox.java */, + 3D6032F80790A618007A3CA5 /* NotFoundDialog.java */, + 3D35A7CB05690E180002CE69 /* NyqPlot.java */, + 3D35A7CC05690E180002CE69 /* NyquistFile.java */, + 3D35A7CD05690E180002CE69 /* NyquistThread.java */, + 3D35A7CE05690E180002CE69 /* openFile.gif */, + 3D35A7CF05690E180002CE69 /* Pair.java */, + 3D7E28BD0B3E3E540078F9A3 /* Piano_Roll.java */, + 3D647D290AC9E7B800E699B7 /* EnvelopeFrame.java */, + 3D35A7D005690E180002CE69 /* PlotFrame.java */, + 3D35A7D105690E180002CE69 /* PlotMouseAdapter.java */, + 3DE0D0680B319B30003EAC5F /* PopupListener.java */, + 3D6032FA0790A62C007A3CA5 /* PreferencesDialog.java */, + 3D16EA010A866123006DADB6 /* ReplaceDialog.java */, + 3D36DDE60796D6D40002CE69 /* keywords.txt */, + ); + path = jnyqide; + sourceTree = ""; + }; + 3D36DDF00796E5DE0002CE69 /* osx */ = { + isa = PBXGroup; + children = ( + 3D36DDEE0796E5CA0002CE69 /* run */, + 3D36DDF20796E60F0002CE69 /* system.lsp */, + ); + name = osx; + sourceTree = ""; + }; + 3D48B84E0F59937D0073A251 /* ffts */ = { + isa = PBXGroup; + children = ( + 3D48B84B0F5993750073A251 /* fftlib.c */, + 3D48B84F0F5993A60073A251 /* fftext.c */, + 3D48B86D0F599EE90073A251 /* matlib.c */, + ); + name = ffts; + sourceTree = ""; + }; + 3D9E07E60779F63A0002CE69 /* portaudio */ = { + isa = PBXGroup; + children = ( + 3DBB0AB312904C0800024DD7 /* pa_ringbuffer.c */, + 3DBB0AB412904C0800024DD7 /* pa_ringbuffer.h */, + 3DBB0AAE12904BBB00024DD7 /* pa_unix_util.c */, + 3DBB0AAF12904BBB00024DD7 /* pa_unix_util.h */, + 3DBB0A9D129048F700024DD7 /* pa_mac_core_utilities.c */, + 3DBB0A9E129048F700024DD7 /* pa_mac_core_utilities.h */, + 3DBB0A99129048D400024DD7 /* pa_mac_core_blocking.c */, + 3DBB0A9A129048D400024DD7 /* pa_mac_core_blocking.h */, + 3DBB0A9B129048D400024DD7 /* pa_mac_core_internal.h */, + 3DBB0A8F129043A900024DD7 /* pa_mac_core.c */, + 3DBB0A8D1290437E00024DD7 /* pa_mac_hostapis.c */, + 3DBB0A8C1290433500024DD7 /* portaudio.h */, + 3DBB0A6B129042A500024DD7 /* pa_allocation.h */, + 3DBB0A6C129042A500024DD7 /* pa_converters.c */, + 3DBB0A6D129042A500024DD7 /* pa_converters.h */, + 3DBB0A6E129042A500024DD7 /* pa_cpuload.c */, + 3DBB0A6F129042A500024DD7 /* pa_cpuload.h */, + 3DBB0A70129042A500024DD7 /* pa_debugprint.c */, + 3DBB0A71129042A500024DD7 /* pa_debugprint.h */, + 3DBB0A72129042A500024DD7 /* pa_dither.c */, + 3DBB0A73129042A500024DD7 /* pa_dither.h */, + 3DBB0A74129042A500024DD7 /* pa_endianness.h */, + 3DBB0A75129042A500024DD7 /* pa_front.c */, + 3DBB0A76129042A500024DD7 /* pa_hostapi.h */, + 3DBB0A77129042A500024DD7 /* pa_process.c */, + 3DBB0A78129042A500024DD7 /* pa_process.h */, + 3DBB0A7B129042A500024DD7 /* pa_skeleton.c */, + 3DBB0A7C129042A500024DD7 /* pa_stream.c */, + 3DBB0A7D129042A500024DD7 /* pa_stream.h */, + 3DBB0A7E129042A500024DD7 /* pa_trace.c */, + 3DBB0A7F129042A500024DD7 /* pa_trace.h */, + 3DBB0A80129042A500024DD7 /* pa_types.h */, + 3DBB0A81129042A500024DD7 /* pa_util.h */, + 3DBB0A691290422300024DD7 /* pa_allocation.c */, + ); + name = portaudio; + sourceTree = ""; + }; + 3D9E08110779F7050002CE69 /* stk */ = { + isa = PBXGroup; + children = ( + 3DA119620D2DE2AA00948714 /* ADSR.cpp */, + 3DA119630D2DE2AA00948714 /* BandedWG.cpp */, + 3DA119640D2DE2AA00948714 /* BiQuad.cpp */, + 3DA119650D2DE2AA00948714 /* Bowed.cpp */, + 3DA119660D2DE2AA00948714 /* BowTable.cpp */, + 3DA119670D2DE2AA00948714 /* Chorus.cpp */, + 3DA119350D2DE1BF00948714 /* DelayA.cpp */, + 3DA119360D2DE1BF00948714 /* Effect.cpp */, + 3DA119370D2DE1BF00948714 /* FileRead.cpp */, + 3DA119380D2DE1BF00948714 /* FileWvIn.cpp */, + 3DA119390D2DE1BF00948714 /* Flute.cpp */, + 3DA1193A0D2DE1BF00948714 /* Function.cpp */, + 3DA1193B0D2DE1BF00948714 /* Generator.cpp */, + 3DA1193C0D2DE1BF00948714 /* JCRev.cpp */, + 3DA1193D0D2DE1BF00948714 /* JetTable.cpp */, + 3DA1193E0D2DE1BF00948714 /* Mandolin.cpp */, + 3DA1193F0D2DE1BF00948714 /* Modal.cpp */, + 3DA119400D2DE1BF00948714 /* ModalBar.cpp */, + 3DA119410D2DE1BF00948714 /* NRev.cpp */, + 3DA119420D2DE1BF00948714 /* OnePole.cpp */, + 3DA119430D2DE1BF00948714 /* PitShift.cpp */, + 3DA119440D2DE1BF00948714 /* PluckTwo.cpp */, + 3DA119450D2DE1BF00948714 /* PoleZero.cpp */, + 3DA119460D2DE1BF00948714 /* PRCRev.cpp */, + 3DA119470D2DE1BF00948714 /* ReedTable.cpp */, + 3DA119480D2DE1BF00948714 /* SineWave.cpp */, + 3DA119490D2DE1BF00948714 /* Sitar.cpp */, + 3D9E08120779F7370002CE69 /* Clarinet.h */, + 3D9E08140779F74C0002CE69 /* globals.h */, + 3D9E08160779F7680002CE69 /* Delay.h */, + 3D9E08170779F7680002CE69 /* DelayL.h */, + 3D9E08180779F7680002CE69 /* Envelope.h */, + 3D9E08190779F7680002CE69 /* Filter.h */, + 3D9E081A0779F7680002CE69 /* Instrmnt.h */, + 3D9E081B0779F7680002CE69 /* Noise.h */, + 3D9E081C0779F7680002CE69 /* OneZero.h */, + 3D9E081E0779F7680002CE69 /* Saxofony.h */, + 3D9E081F0779F7680002CE69 /* SKINI.msg */, + 3D9E08300779F78B0002CE69 /* instr.cpp */, + 3D9E08310779F78B0002CE69 /* instr.h */, + 3D9E08340779F7A30002CE69 /* Clarinet.cpp */, + 3D9E08360779F7B80002CE69 /* Delay.cpp */, + 3D9E08370779F7B80002CE69 /* DelayL.cpp */, + 3D9E08380779F7B80002CE69 /* Envelope.cpp */, + 3D9E08390779F7B80002CE69 /* Filter.cpp */, + 3D9E083A0779F7B80002CE69 /* Instrmnt.cpp */, + 3D9E083B0779F7B80002CE69 /* Noise.cpp */, + 3D9E083C0779F7B80002CE69 /* OneZero.cpp */, + 3D9E083E0779F7B80002CE69 /* Saxofony.cpp */, + 3D9E083F0779F7B80002CE69 /* Stk.cpp */, + 3D9E08400779F7B80002CE69 /* WaveLoop.cpp */, + 3D9E08410779F7B80002CE69 /* WvIn.cpp */, + 3D9E084E077C6FC00002CE69 /* stkinit.cpp */, + 3D9E084F077C6FC00002CE69 /* stkinit.h */, + 3D9E08200779F7680002CE69 /* Stk.h */, + 3D9E08210779F7680002CE69 /* WaveLoop.h */, + 3D9E08220779F7680002CE69 /* WvIn.h */, + ); + name = stk; + sourceTree = ""; + }; + 3DF21F3104FD526A0002CE69 /* misc */ = { + isa = PBXGroup; + children = ( + 3DF21F3204FD526A0002CE69 /* args.h */, + 3DF21F3304FD526A0002CE69 /* cext.h */, + 3DF21F3404FD526A0002CE69 /* cmdline.c */, + 3DF21F3504FD526A0002CE69 /* cmdline.h */, + 3DF21F3604FD526A0002CE69 /* cmu */, + 3DF21F3C04FD526A0002CE69 /* convert.c */, + 3DF21F3D04FD526A0002CE69 /* convert.h */, + 3DF21F3E04FD526A0002CE69 /* filelist.c */, + 3DF21F3F04FD526A0002CE69 /* filelist.dsp */, + 3DF21F4004FD526A0002CE69 /* intgen.c */, + 3DF21F4104FD526A0002CE69 /* intgen2.c */, + 3DF21F4204FD526A0002CE69 /* intgen_win32 */, + 3DF21F4404FD526A0002CE69 /* mac-to-win.lsp */, + 3DF21F4504FD526A0002CE69 /* Makefile */, + 3DF21F4604FD526A0002CE69 /* makefile.lsp */, + 3DF21F4704FD526A0002CE69 /* packer.c */, + 3DF21F4804FD526A0002CE69 /* packer.dsp */, + 3DF21F4904FD526A0002CE69 /* play.c */, + 3DF21F4A04FD526A0002CE69 /* plot.c */, + 3DF21F4B04FD526A0002CE69 /* sampleprint.c */, + 3DF21F4C04FD526A0002CE69 /* sine.c */, + 3DF21F4D04FD526A0002CE69 /* stdefs2.h */, + 3DF21F4E04FD526A0002CE69 /* transfiles.lsp */, + 3DF21F4F04FD526A0002CE69 /* unpacker.c */, + 3DF21F5004FD526A0002CE69 /* unpacker.dsp */, + ); + path = misc; + sourceTree = ""; + }; + 3DF21F3604FD526A0002CE69 /* cmu */ = { + isa = PBXGroup; + children = ( + 3DF21F3704FD526A0002CE69 /* cleanup.bat */, + 3DF21F3804FD526A0002CE69 /* cmu-linux-install.lsp */, + 3DF21F3904FD526A0002CE69 /* cmuinstall.bat */, + 3DF21F3A04FD526A0002CE69 /* init.lsp */, + 3DF21F3B04FD526A0002CE69 /* restore.bat */, + ); + path = cmu; + sourceTree = ""; + }; + 3DF21F4204FD526A0002CE69 /* intgen_win32 */ = { + isa = PBXGroup; + children = ( + 3DF21F4304FD526A0002CE69 /* intgen.dsp */, + ); + path = intgen_win32; + sourceTree = ""; + }; + F510BDB903A0314301029006 /* Frameworks */ = { + isa = PBXGroup; + children = ( + F543E76B0375C24D01029006 /* CoreAudio.framework */, + F543E7750375C25A01029006 /* AudioToolbox.framework */, + ); + name = Frameworks; + path = /System/Library/Frameworks; + sourceTree = ""; + }; + F543EE570375CD5801029006 /* cmt */ = { + isa = PBXGroup; + children = ( + F543EE580375CD5801029006 /* cext.c */, + F543EE590375CD5801029006 /* cext.h */, + F543EE5A0375CD5801029006 /* cleanup.c */, + F543EE5B0375CD5801029006 /* cleanup.h */, + F543EE5C0375CD5801029006 /* cmdline.c */, + F543EE5D0375CD5801029006 /* cmdline.h */, + F543EE5E0375CD5801029006 /* cmtcmd.c */, + F543EE5F0375CD5801029006 /* cmtcmd.h */, + F543EE600375CD5801029006 /* cmtio.c */, + F543EE610375CD5801029006 /* cmtio.h */, + F543EE620375CD5801029006 /* hash.h */, + F543EE630375CD5801029006 /* hashrout.h */, + F543EE640375CD5801029006 /* mem.c */, + F543EE650375CD5801029006 /* mem.h */, + F543EE660375CD5801029006 /* mfmidi.h */, + F543EE670375CD5801029006 /* midibuff.h */, + F543EE680375CD5801029006 /* midicode.h */, + F543EE690375CD5801029006 /* midierr.h */, + F543EE6A0375CD5801029006 /* midifile.c */, + F543EE6B0375CD5801029006 /* midifile.h */, + F543EE6C0375CD5801029006 /* midifns.c */, + F543EE6D0375CD5801029006 /* midifns.h */, + F543EE6E0375CD5801029006 /* midimgr.c */, + F543EE6F0375CD5801029006 /* midimgr.h */, + F543EE700375CD5801029006 /* moxc.c */, + F543EE710375CD5801029006 /* moxc.h */, + F543EE720375CD5801029006 /* musiprog.h */, + F543EE730375CD5801029006 /* pitch.h */, + F543EE740375CD5801029006 /* record.c */, + F543EE750375CD5801029006 /* record.h */, + F543EE760375CD5801029006 /* seq.c */, + F543EE770375CD5801029006 /* seq.h */, + F543EE780375CD5801029006 /* seqdecls.h */, + F543EE790375CD5801029006 /* seqmread.c */, + F543EE7A0375CD5801029006 /* seqmread.h */, + F543EE7B0375CD5801029006 /* seqmwrite.c */, + F543EE7C0375CD5801029006 /* seqmwrite.h */, + F543EE7D0375CD5801029006 /* seqread.c */, + F543EE7E0375CD5801029006 /* seqread.h */, + F543EE7F0375CD5801029006 /* seqwrite.c */, + F543EE800375CD5801029006 /* seqwrite.h */, + F543EE810375CD5801029006 /* swlogic.h */, + F543EE820375CD5801029006 /* tempomap.c */, + F543EE830375CD5801029006 /* tempomap.h */, + F543EE840375CD5801029006 /* timebase.c */, + F543EE850375CD5801029006 /* timebase.h */, + F543EE860375CD5801029006 /* userio.c */, + F543EE870375CD5801029006 /* userio.h */, + ); + path = cmt; + sourceTree = ""; + }; + F543EF3D0375CD7101029006 /* snd */ = { + isa = PBXGroup; + children = ( + F53626EE03761E6C01029006 /* audiopa.c */, + F543EF4A0375CD7101029006 /* ieeecvt.c */, + F543EF4B0375CD7101029006 /* ieeecvt.h */, + F543EF4D0375CD7101029006 /* snd.c */, + F543EF4E0375CD7101029006 /* snd.h */, + F543EF510375CD7101029006 /* sndconfig.h */, + F543EF520375CD7101029006 /* sndcvt.c */, + F543EF550375CD7101029006 /* sndfileio.h */, + F543EF570375CD7101029006 /* sndhead.h */, + F543EF580375CD7101029006 /* sndheader.c */, + F543EF590375CD7101029006 /* sndheader.h */, + F543EF5A0375CD7101029006 /* sndio.c */, + F543EF5D0375CD7101029006 /* sndmac.c */, + F543EF5E0375CD7101029006 /* sndmac.h */, + F543EF620375CD7101029006 /* sndsystem.h */, + F543EF630375CD7101029006 /* sndsystemmac.h */, + F543EF660375CD7101029006 /* sndwrite.h */, + ); + path = snd; + sourceTree = ""; + }; + F543EF990375CD9901029006 /* sys */ = { + isa = PBXGroup; + children = ( + F543EFB10375CD9901029006 /* unix */, + ); + path = sys; + sourceTree = ""; + }; + F543EFB10375CD9901029006 /* unix */ = { + isa = PBXGroup; + children = ( + 3D36DDF00796E5DE0002CE69 /* osx */, + F543EFBF0375CD9901029006 /* osstuff.c */, + 3D9867D304FFE8E20002CE69 /* term.c */, + ); + path = unix; + sourceTree = ""; + }; + F543F19F0375E1E401029006 /* Source */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* nyquist */, + ); + name = Source; + sourceTree = SOURCE_ROOT; + }; + F5FF5F48039D84B901029006 /* xlisp */ = { + isa = PBXGroup; + children = ( + F5FF5F49039D84B901029006 /* extern.c */, + F5FF5F4A039D84B901029006 /* extern.h */, + F5FF5F4B039D84B901029006 /* osdefs.h */, + F5FF5F4C039D84B901029006 /* osptrs.h */, + F5FF5F4D039D84B901029006 /* xlbfun.c */, + F5FF5F4E039D84B901029006 /* xlcont.c */, + F5FF5F4F039D84B901029006 /* xldbug.c */, + F5FF5F50039D84B901029006 /* xldmem.c */, + F5FF5F51039D84B901029006 /* xldmem.h */, + F5FF5F52039D84B901029006 /* xleval.c */, + F5FF5F53039D84B901029006 /* xlfio.c */, + F5FF5F54039D84B901029006 /* xlftab.c */, + F5FF5F55039D84B901029006 /* xlglob.c */, + F5FF5F56039D84B901029006 /* xlimage.c */, + F5FF5F57039D84B901029006 /* xlinit.c */, + F5FF5F58039D84B901029006 /* xlio.c */, + F5FF5F59039D84B901029006 /* xlisp.c */, + F5FF5F5A039D84B901029006 /* xlisp.h */, + F5FF5F5B039D84B901029006 /* xljump.c */, + F5FF5F5C039D84B901029006 /* xllist.c */, + F5FF5F5D039D84B901029006 /* xlmath.c */, + F5FF5F5E039D84B901029006 /* xlobj.c */, + F5FF5F5F039D84B901029006 /* xlpp.c */, + F5FF5F60039D84B901029006 /* xlprin.c */, + F5FF5F61039D84B901029006 /* xlread.c */, + F5FF5F62039D84B901029006 /* xlstr.c */, + F5FF5F63039D84B901029006 /* xlsubr.c */, + F5FF5F64039D84B901029006 /* xlsym.c */, + F5FF5F65039D84B901029006 /* xlsys.c */, + ); + path = xlisp; + sourceTree = ""; + }; + F5FF5F9E039D863401029006 /* tran */ = { + isa = PBXGroup; + children = ( + 3DA119980D2DE88B00948714 /* stkint.cpp */, + 3DA119990D2DE88B00948714 /* stkint.h */, + 3DA119930D2DE71700948714 /* biquadfilt.c */, + 3DA119940D2DE71700948714 /* biquadfilt.h */, + 3DA119870D2DE5CF00948714 /* stkrev.c */, + 3DA119880D2DE5CF00948714 /* stkrev.h */, + 3DA119840D2DE5BA00948714 /* stkpitshift.c */, + 3DA119850D2DE5BA00948714 /* stkpitshift.h */, + 3DA119810D2DE5AA00948714 /* instrsitar.c */, + 3DA119820D2DE5AA00948714 /* instrsitar.h */, + 3DA1197E0D2DE59A00948714 /* instrflutefreq.c */, + 3DA1197F0D2DE59A00948714 /* instrflutefreq.h */, + 3DA1197B0D2DE58A00948714 /* instrfluteall.c */, + 3DA1197C0D2DE58A00948714 /* instrfluteall.h */, + 3DA119780D2DE57100948714 /* instrflute.c */, + 3DA119790D2DE57100948714 /* instrflute.h */, + 3DA119750D2DE56200948714 /* instrbowedfreq.c */, + 3DA119760D2DE56200948714 /* instrbowedfreq.h */, + 3DA119720D2DE54500948714 /* instrbow.c */, + 3DA119730D2DE54500948714 /* instrbow.h */, + 3DA1196F0D2DE52400948714 /* instrbanded.c */, + 3DA119700D2DE52400948714 /* instrbanded.h */, + F5FF5FA1039D866201029006 /* abs.c */, + F5FF5FA2039D866201029006 /* abs.h */, + F5FF5FA3039D866201029006 /* alpass.c */, + F5FF5FA4039D866201029006 /* alpass.h */, + F5FF5FA5039D866201029006 /* amosc.c */, + F5FF5FA6039D866201029006 /* amosc.h */, + F5FF5FA7039D866201029006 /* areson.c */, + F5FF5FA8039D866201029006 /* areson.h */, + F5FF5FA9039D866201029006 /* aresoncv.c */, + 3DA121000D313E7C00948714 /* instrmodalbar.c */, + 3DA121010D313E7C00948714 /* instrmodalbar.h */, + 3DA120FE0D313E5500948714 /* instrmandolin.c */, + 3DA120FC0D313E1B00948714 /* stkchorus.c */, + F5FF5FAA039D866201029006 /* aresoncv.h */, + F5FF5FAB039D866201029006 /* aresonvc.c */, + F5FF5FAC039D866201029006 /* aresonvc.h */, + F5FF5FAD039D866201029006 /* aresonvv.c */, + F5FF5FAE039D866201029006 /* aresonvv.h */, + F5FF5FAF039D866201029006 /* atone.c */, + F5FF5FB0039D866201029006 /* atone.h */, + F5FF5FB1039D866201029006 /* atonev.c */, + F5FF5FB2039D866201029006 /* atonev.h */, + F5FF5FB5039D866201029006 /* buzz.c */, + F5FF5FB6039D866201029006 /* buzz.h */, + F5FF5FB7039D866201029006 /* chase.c */, + F5FF5FB8039D866201029006 /* chase.h */, + F5FF5FB9039D866201029006 /* clip.c */, + F5FF5FBA039D866201029006 /* clip.h */, + F5FF5FBB039D866201029006 /* congen.c */, + F5FF5FBC039D866201029006 /* congen.h */, + F5FF5FBD039D866201029006 /* const.c */, + F5FF5FBE039D866201029006 /* const.h */, + F5FF5FC1039D866201029006 /* coterm.c */, + F5FF5FC2039D866201029006 /* coterm.h */, + 3D9E07E00779F4DC0002CE69 /* delaycc.c */, + 3D9E07E10779F4DC0002CE69 /* delaycc.h */, + F5FF5FC5039D866201029006 /* delaycv.c */, + F5FF5FC6039D866201029006 /* delaycv.h */, + F5FF5FC7039D866201029006 /* exp.c */, + F5FF5FC8039D866201029006 /* exp.h */, + 3DC916F70D4036F000DD66C0 /* fmfbv.c */, + 3DC916F80D4036F000DD66C0 /* fmfbv.h */, + 3DC916F40D4036DC00DD66C0 /* fmfb.c */, + 3DC916F50D4036DC00DD66C0 /* fmfb.h */, + F5FF5FC9039D866201029006 /* fmosc.c */, + F5FF5FCA039D866201029006 /* fmosc.h */, + F5FF5FCB039D866201029006 /* follow.c */, + F5FF5FCC039D866201029006 /* follow.h */, + F5FF5FCD039D866201029006 /* fromarraystream.c */, + F5FF5FCE039D866201029006 /* fromarraystream.h */, + F5FF5FCF039D866201029006 /* fromobject.c */, + F5FF5FD0039D866201029006 /* fromobject.h */, + F5FF5FD1039D866201029006 /* gate.c */, + F5FF5FD2039D866201029006 /* gate.h */, + F5FF5FD3039D866201029006 /* ifft.c */, + F5FF5FD4039D866201029006 /* ifft.h */, + F5FF5FD5039D866201029006 /* integrate.c */, + F5FF5FD6039D866201029006 /* integrate.h */, + F5FF5FD7039D866201029006 /* log.c */, + F5FF5FD8039D866201029006 /* log.h */, + F5FF5FD9039D866201029006 /* maxv.c */, + F5FF5FDA039D866201029006 /* maxv.h */, + F5FF5FDB039D866201029006 /* offset.c */, + F5FF5FDC039D866201029006 /* offset.h */, + F5FF5FDD039D866201029006 /* oneshot.c */, + F5FF5FDE039D866201029006 /* oneshot.h */, + F5FF5FDF039D866201029006 /* osc.c */, + F5FF5FE0039D866201029006 /* osc.h */, + F5FF5FE1039D866201029006 /* partial.c */, + F5FF5FE2039D866201029006 /* partial.h */, + F5FF5FE3039D866201029006 /* pluck.c */, + F5FF5FE4039D866201029006 /* pluck.h */, + F5FF5FE5039D866201029006 /* prod.c */, + F5FF5FE6039D866201029006 /* prod.h */, + F5FF5FE7039D866201029006 /* pwl.c */, + F5FF5FE8039D866201029006 /* pwl.h */, + F5FF5FEB039D866201029006 /* quantize.c */, + F5FF5FEC039D866201029006 /* quantize.h */, + F5FF5FED039D866201029006 /* recip.c */, + F5FF5FEE039D866201029006 /* recip.h */, + F5FF5FEF039D866201029006 /* reson.c */, + F5FF5FF0039D866201029006 /* reson.h */, + F5FF5FF1039D866201029006 /* resoncv.c */, + F5FF5FF2039D866201029006 /* resoncv.h */, + F5FF5FF3039D866201029006 /* resonvc.c */, + F5FF5FF4039D866201029006 /* resonvc.h */, + F5FF5FF5039D866201029006 /* resonvv.c */, + F5FF5FF6039D866201029006 /* resonvv.h */, + F5FF5FF7039D866201029006 /* sampler.c */, + F5FF5FF8039D866201029006 /* sampler.h */, + F5FF5FF9039D866201029006 /* scale.c */, + F5FF5FFA039D866201029006 /* scale.h */, + F5FF5FFB039D866201029006 /* shape.c */, + F5FF5FFC039D866201029006 /* shape.h */, + F5FF5FFD039D866201029006 /* sine.c */, + F5FF5FFE039D866201029006 /* sine.h */, + F5FF5FFF039D866201029006 /* siosc.c */, + F5FF6000039D866201029006 /* siosc.h */, + F5FF6001039D866201029006 /* slope.c */, + F5FF6002039D866201029006 /* slope.h */, + F5FF6003039D866201029006 /* sqrt.c */, + F5FF6004039D866201029006 /* sqrt.h */, + 3D9867CC04FFDD3C0002CE69 /* tapf.c */, + 3D9867CE04FFDD6B0002CE69 /* tapf.h */, + F5FF6005039D866201029006 /* tapv.c */, + F5FF6006039D866201029006 /* tapv.h */, + F5FF6007039D866201029006 /* tone.c */, + F5FF6008039D866201029006 /* tone.h */, + F5FF6009039D866201029006 /* tonev.c */, + F5FF600A039D866201029006 /* tonev.h */, + F5FF600B039D866201029006 /* upsample.c */, + F5FF600C039D866201029006 /* upsample.h */, + F5FF600D039D866201029006 /* white.c */, + F5FF600E039D866201029006 /* white.h */, + ); + path = tran; + sourceTree = ""; + }; + F5FF60A6039D87B001029006 /* nyqsrc */ = { + isa = PBXGroup; + children = ( + 3D3223280F544BBB00F074EF /* nyq-osc-server.c */, + 3D81ED250A76B1290053113C /* sliders.h */, + F5FF615C039D899F01029006 /* seqfnint.c */, + F5FF615D039D899F01029006 /* seqfnintdefs.h */, + F5FF615E039D899F01029006 /* seqfnintptrs.h */, + F5FF6162039D89B101029006 /* sndfnint.c */, + F5FF6163039D89B101029006 /* sndfnintdefs.h */, + F5FF6164039D89B101029006 /* sndfnintptrs.h */, + F5FF60A7039D87B001029006 /* add.c */, + F5FF60A8039D87B001029006 /* add.h */, + 3D9867D7050920060002CE69 /* alpasscv.c */, + 3D9867DB0509202C0002CE69 /* alpasscv.h */, + 3D9867DD050920400002CE69 /* alpassvv.c */, + 3D9867DE050920400002CE69 /* alpassvv.h */, + F5FF60A9039D87B001029006 /* avg.c */, + F5FF60AA039D87B001029006 /* avg.h */, + F5FF60AB039D87B001029006 /* compose.c */, + F5FF60AC039D87B001029006 /* compose.h */, + F5FF60AD039D87B001029006 /* cque.h */, + F5FF60AE039D87B001029006 /* debug.c */, + F5FF60AF039D87B001029006 /* debug.h */, + F5FF60B0039D87B001029006 /* downsample.c */, + F5FF60B1039D87B001029006 /* downsample.h */, + 3D9867E1050920730002CE69 /* eqbandvvv.c */, + 3D9867E2050920730002CE69 /* eqbandvvv.h */, + F5FF60B2039D87B001029006 /* falloc.c */, + F5FF60B3039D87B001029006 /* falloc.h */, + F5FF60B4039D87B001029006 /* ffilterkit.c */, + F5FF60B5039D87B001029006 /* ffilterkit.h */, + F5FF60B6039D87B001029006 /* fft-rbd.c */, + F5FF60B7039D87B001029006 /* fft.c */, + F5FF60B8039D87B001029006 /* fft.h */, + F5FF60B9039D87B001029006 /* fftr4.c */, + F5FF60BA039D87B001029006 /* fftw.h */, + F5FF60BB039D87B001029006 /* fresample.h */, + F5FF60BC039D87B001029006 /* fsmallfilter.h */, + F5FF60BD039D87B001029006 /* handlers.c */, + F5FF60BE039D87B001029006 /* inverse.c */, + F5FF60BF039D87B001029006 /* inverse.h */, + F5FF60C0039D87B001029006 /* local.c */, + F5FF60C1039D87B001029006 /* localdefs.h */, + F5FF60C2039D87B001029006 /* localptrs.h */, + F5FF60C3039D87B001029006 /* multiread.c */, + F5FF60C4039D87B001029006 /* multiread.h */, + F5FF60C5039D87B001029006 /* multiseq.c */, + F5FF60C6039D87B001029006 /* multiseq.h */, + F5FF60C7039D87B001029006 /* nfilterkit.c */, + F5FF60C8039D87B001029006 /* nfilterkit.h */, + 3D9867E5050921720002CE69 /* path.c */, + F5FF60C9039D87B001029006 /* probe.c */, + F5FF60CA039D87B001029006 /* probe.h */, + F5FF60CB039D87B001029006 /* resamp.c */, + F5FF60CC039D87B001029006 /* resamp.h */, + F5FF60CD039D87B001029006 /* resampv.c */, + F5FF60CE039D87B001029006 /* resampv.h */, + F5FF60CF039D87B001029006 /* rfftw.h */, + F5FF60D0039D87B001029006 /* samples.c */, + F5FF60D1039D87B001029006 /* samples.h */, + F5FF60D2039D87B001029006 /* seqext.c */, + F5FF60D3039D87B001029006 /* seqext.h */, + F5FF60D4039D87B001029006 /* seqfn.wcl */, + F5FF60D6039D87B001029006 /* seqfnint.lsp */, + F5FF60D7039D87B001029006 /* seqinterf.c */, + F5FF60D8039D87B001029006 /* seqinterf.h */, + 3D81ED240A76B1290053113C /* sliders.c */, + F5FF60DA039D87B001029006 /* sndfn.wcl */, + F5FF60DC039D87B001029006 /* sndfnint.lsp */, + F5FF60DD039D87B001029006 /* sndmax.c */, + F5FF60DE039D87B001029006 /* sndmax.h */, + F5FF60DF039D87B001029006 /* sndread.c */, + F5FF60E0039D87B001029006 /* sndread.h */, + F5FF60E1039D87B001029006 /* sndseq.c */, + F5FF60E2039D87B001029006 /* sndseq.h */, + F5FF60E4039D87B001029006 /* sndwrite.h */, + F5FF60E5039D87B001029006 /* sndwritepa.c */, + F5FF60E6039D87B001029006 /* sound.c */, + 3DAB7FB20B30690F00A51A49 /* trigger.c */, + 3D9E086A0789D6000002CE69 /* lpanal.c */, + 3D9E086B0789D6000002CE69 /* lpanal.h */, + 3D9E086E0789D81B0002CE69 /* alpassvc.c */, + 3D9E086F0789D81B0002CE69 /* alpassvc.h */, + 3D9E08720789D82F0002CE69 /* allpoles.c */, + 3D9E08730789D82F0002CE69 /* allpoles.h */, + 3D9E08760789D8520002CE69 /* f0.cpp */, + 3D9E08770789D8520002CE69 /* f0.h */, + 3D9E087A0789D8B20002CE69 /* instrclar.c */, + 3D9E087B0789D8B20002CE69 /* instrclar.h */, + 3D9E087E0789D8CF0002CE69 /* instrsaxall.c */, + 3D9E087F0789D8CF0002CE69 /* instrsaxall.h */, + 3D9E08820789D8E70002CE69 /* lpreson.c */, + 3D9E08830789D8E70002CE69 /* lpreson.h */, + 3D9E08860789D9100002CE69 /* instrclarall.c */, + 3D9E08870789D9100002CE69 /* instrclarall.h */, + 3D9E088A0789D9230002CE69 /* instrsaxfreq.c */, + 3D9E088B0789D9230002CE69 /* instrsaxfreq.h */, + 3D9E088E0789D9430002CE69 /* instrclarfreq.c */, + 3D9E088F0789D9430002CE69 /* instrclarfreq.h */, + 3D9E08920789D9680002CE69 /* instrsax.c */, + 3D9E08930789D9680002CE69 /* instrsax.h */, + F5FF60E7039D87B001029006 /* sound.h */, + F5FF60E8039D87B001029006 /* stats.c */, + F5FF60E9039D87B001029006 /* stdefs.h */, + 3D9867D505091F760002CE69 /* yin.c */, + 3D9867D9050920140002CE69 /* yin.h */, + 3D9E07DC0779F4800002CE69 /* convolve.c */, + 3D9E07DD0779F4800002CE69 /* convolve.h */, + ); + path = nyqsrc; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3D32216C0F53D4C300F074EF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D35337E0F0BD6CA0059CD05 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3D0817540AD01DB10051B745 /* osc-test-client */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3D08175B0AD01DD00051B745 /* Build configuration list for PBXNativeTarget "osc-test-client" */; + buildPhases = ( + 3D0817520AD01DB10051B745 /* Sources */, + 3D0817530AD01DB10051B745 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 3D6C06C612D8FE6A0027E89B /* PBXTargetDependency */, + ); + name = "osc-test-client"; + productName = "osc-test-client"; + productReference = 3D0817550AD01DB10051B745 /* osc-test-client */; + productType = "com.apple.product-type.tool"; + }; + 3D32216F0F53D4C300F074EF /* liblo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3D3221730F53D4FD00F074EF /* Build configuration list for PBXNativeTarget "liblo" */; + buildPhases = ( + 3D32216C0F53D4C300F074EF /* Headers */, + 3D32216D0F53D4C300F074EF /* Sources */, + 3D32216E0F53D4C300F074EF /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = liblo; + productName = liblo; + productReference = 3D3221700F53D4C300F074EF /* libliblo.a */; + productType = "com.apple.product-type.library.static"; + }; + 3D3533810F0BD6CA0059CD05 /* libsndfile */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3D3533860F0BD6E00059CD05 /* Build configuration list for PBXNativeTarget "libsndfile" */; + buildPhases = ( + 3D35337E0F0BD6CA0059CD05 /* Headers */, + 3D35337F0F0BD6CA0059CD05 /* Sources */, + 3D3533800F0BD6CA0059CD05 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsndfile; + productName = libsndfile; + productReference = 3D3533820F0BD6CA0059CD05 /* liblibsndfile.a */; + productType = "com.apple.product-type.library.static"; + }; + 3D5CD82C0B5BC73700DF426B /* ny */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3D5CD82F0B5BC75600DF426B /* Build configuration list for PBXNativeTarget "ny" */; + buildPhases = ( + 3D5CD82A0B5BC73700DF426B /* Sources */, + 3D5CD82B0B5BC73700DF426B /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 3D3533A50F0BD8A80059CD05 /* PBXTargetDependency */, + 3D3221720F53D4DF00F074EF /* PBXTargetDependency */, + ); + name = ny; + productName = ny; + productReference = 3D5CD82D0B5BC73700DF426B /* ny */; + productType = "com.apple.product-type.tool"; + }; + 3D7327AF125BF624009AAF15 /* NyquistIDE */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3D7327B6125BF625009AAF15 /* Build configuration list for PBXNativeTarget "NyquistIDE" */; + buildPhases = ( + 3D7327B9125BF675009AAF15 /* Copy Executable */, + 3D1776D7125D4681007B2152 /* Rename Executable */, + 3D7327C8125BF6BA009AAF15 /* Copy Java Resources */, + 3D7327D0125BF735009AAF15 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3D7327DC125BF99D009AAF15 /* PBXTargetDependency */, + 3DBB0A5612903B0200024DD7 /* PBXTargetDependency */, + ); + name = NyquistIDE; + productName = "JNyqIDE-Application"; + productReference = 3D7327B0125BF624009AAF15 /* NyquistIDE.app */; + productType = "com.apple.product-type.application"; + }; + 3DA7D7C312B93C08008E62B1 /* intgen */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3DA7D7CB12B93C3F008E62B1 /* Build configuration list for PBXNativeTarget "intgen" */; + buildPhases = ( + 3DA7D7C112B93C08008E62B1 /* Sources */, + 3DA7D7C212B93C08008E62B1 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = intgen; + productName = intgen; + productReference = 3DA7D7C412B93C08008E62B1 /* intgen */; + productType = "com.apple.product-type.tool"; + }; + 3DAB7F280B2E172300A51A49 /* ser-to-osc */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3DAB7F2C0B2E175500A51A49 /* Build configuration list for PBXNativeTarget "ser-to-osc" */; + buildPhases = ( + 3DAB7F260B2E172300A51A49 /* Sources */, + 3DAB7F270B2E172300A51A49 /* Frameworks */, + ); + buildRules = ( + ); + comments = "Serial input to OSC messages for Nyquist"; + dependencies = ( + 3D6C06D112D8FF430027E89B /* PBXTargetDependency */, + ); + name = "ser-to-osc"; + productName = "ser-to-osc"; + productReference = 3DAB7F290B2E172300A51A49 /* ser-to-osc */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 3DEBDFD2095B177A001BCCB6 /* Build configuration list for PBXProject "nyquist" */; + compatibilityVersion = "Xcode 2.4"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* MacOSXProject */; + projectDirPath = ""; + projectRoot = ..; + targets = ( + 3D0817540AD01DB10051B745 /* osc-test-client */, + 3DAB7F280B2E172300A51A49 /* ser-to-osc */, + 3D5CD82C0B5BC73700DF426B /* ny */, + 3D3533810F0BD6CA0059CD05 /* libsndfile */, + 3D32216F0F53D4C300F074EF /* liblo */, + 3D7327A5125BF5D8009AAF15 /* CompileJava */, + 3D7327AF125BF624009AAF15 /* NyquistIDE */, + 3DA7D7C312B93C08008E62B1 /* intgen */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3D7327D0125BF735009AAF15 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D1776A1125CB5B3007B2152 /* Nyquist.icns in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3D1776D7125D4681007B2152 /* Rename Executable */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Rename Executable"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# there must be a better way, but in order to get Xcode to run the application, I\n# set the executable (JavaApplicationStub) to have the same name as the application\n# (NyquistIDE).\nmv $TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/JavaApplicationStub $TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/NyquistIDE\n"; + }; + 3D7327A4125BF5D8009AAF15 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + comments = "This is a brute-force script to recompile all java files. Dependencies are manually inserted because I don't know how to get Xcode to do it from the project window.\n"; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/../jnyqide/BareBonesBrowserLaunch.java", + "$(SRCROOT)/../jnyqide/CodePane.java", + "$(SRCROOT)/../jnyqide/EnvelopeFrame.java", + "$(SRCROOT)/../jnyqide/FindDialog.java", + "$(SRCROOT)/../jnyqide/InstrumentCharacteristics.java", + "$(SRCROOT)/../jnyqide/Jslide.java", + "$(SRCROOT)/../jnyqide/LispFileFilter.java", + "$(SRCROOT)/../jnyqide/MainFrame.java", + "$(SRCROOT)/../jnyqide/MainFrame_AboutBox.java", + "$(SRCROOT)/../jnyqide/MiniBrowser.java", + "$(SRCROOT)/../jnyqide/NotFoundDialog.java", + "$(SRCROOT)/../jnyqide/NyqPlot.java", + "$(SRCROOT)/../jnyqide/NyquistFile.java", + "$(SRCROOT)/../jnyqide/NyquistThread.java", + "$(SRCROOT)/../jnyqide/Pair.java", + "$(SRCROOT)/../nyqide/Piano_Roll.java", + "$(SRCROOT)/../jnyqide/PlotFrame.java", + "$(SRCROOT)/../jnyqide/PlotMouseAdapter.java", + "$(SRCROOT)/../jnyqide/PopupListener.java", + "$(SRCROOT)/../jnyqide/PreferencesDialog.java", + "$(SRCROOT)/../jnyqide/ReplaceDialog.java", + "$(SRCROOT)/../jnyqide/SalFileFilter.java", + "$(SRCROOT)/../jnyqide/SalWordList.java", + "$(SRCROOT)/../jnyqide/SpecialMacHandler.java", + "$(SRCROOT)/../jnyqide/SpringUtilities.java", + "$(SRCROOT)/../jnyqide/TextColor.java", + "$(SRCROOT)/../jnyqide/Trie.java", + "$(SRCROOT)/../jnyqide/WordList.java", + "$(SRCROOT)/../jnyqide/browser.java", + ); + outputPaths = ( + "$(SRCROOT)/jnyqide/jnyqide.jar", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# shell script goes here\ncd ..\necho \"compiling java sources\"\njavac jnyqide/*.java\nif [ -f jnyqide/jnyqide.jar ]\nthen\n echo \"removing jnyqide/jnyqide.jar\"\n rm -f jnyqide/jnyqide.jar\nelse\n echo \"jnyqide/jnyqide.jar does not exist\"\nfi\necho \"(re)creating jar file\"\njar -cfm jnyqide/jnyqide.jar jnyqide/manifest.txt jnyqide/*.class\necho \"end of script\"\nexit 0\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3D0817520AD01DB10051B745 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D0817D40AD02A210051B745 /* test-client.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D32216D0F53D4C300F074EF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D3223770F5453DE00F074EF /* send.c in Sources */, + 3D3223780F5453DE00F074EF /* server.c in Sources */, + 3D3221770F53D51D00F074EF /* address.c in Sources */, + 3D3221780F53D51D00F074EF /* blob.c in Sources */, + 3D3221790F53D51D00F074EF /* bundle.c in Sources */, + 3D32217C0F53D51D00F074EF /* message.c in Sources */, + 3D32217D0F53D51D00F074EF /* method.c in Sources */, + 3D32217E0F53D51D00F074EF /* pattern_match.c in Sources */, + 3D3221820F53D51D00F074EF /* timetag.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D35337F0F0BD6CA0059CD05 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D35338D0F0BD7C60059CD05 /* sndfile.c in Sources */, + 3D3533A90F0BDA290059CD05 /* common.c in Sources */, + 3D3533AD0F0BDA7C0059CD05 /* file_io.c in Sources */, + 3D3533BB0F0BDE2E0059CD05 /* aiff.c in Sources */, + 3D3533BC0F0BDE2E0059CD05 /* alaw.c in Sources */, + 3D3533BD0F0BDE2E0059CD05 /* au.c in Sources */, + 3D3533BE0F0BDE2E0059CD05 /* avr.c in Sources */, + 3D3533BF0F0BDE2E0059CD05 /* broadcast.c in Sources */, + 3D3533C00F0BDE2E0059CD05 /* caf.c in Sources */, + 3D3533C40F0BDE610059CD05 /* dither.c in Sources */, + 3D3533C50F0BDE610059CD05 /* double64.c in Sources */, + 3D3533C60F0BDE610059CD05 /* dwd.c in Sources */, + 3D3533CA0F0BDE930059CD05 /* flac.c in Sources */, + 3D3533CC0F0BDE930059CD05 /* float32.c in Sources */, + 3D3533CE0F0BDEAA0059CD05 /* htk.c in Sources */, + 3D3533D10F0BDEC30059CD05 /* mat4.c in Sources */, + 3D3533D20F0BDEC30059CD05 /* mat5.c in Sources */, + 3D3533D90F0BDEE70059CD05 /* nist.c in Sources */, + 3D3533DA0F0BDEE70059CD05 /* ogg.c in Sources */, + 3D3533DB0F0BDEE70059CD05 /* paf.c in Sources */, + 3D3533DC0F0BDEE70059CD05 /* pcm.c in Sources */, + 3D3533DD0F0BDEE70059CD05 /* pvf.c in Sources */, + 3D3533DE0F0BDEE70059CD05 /* raw.c in Sources */, + 3D3533E20F0BDF060059CD05 /* rx2.c in Sources */, + 3D3533E30F0BDF060059CD05 /* sd2.c in Sources */, + 3D3533E40F0BDF060059CD05 /* sds.c in Sources */, + 3D3533E70F0BDF3B0059CD05 /* ircam.c in Sources */, + 3D3533EB0F0BDF5E0059CD05 /* dwvw.c in Sources */, + 3D3533F50F0BDFA20059CD05 /* vox_adpcm.c in Sources */, + 3D3533F60F0BDFA20059CD05 /* w64.c in Sources */, + 3D3533F70F0BDFA20059CD05 /* wav_w64.c in Sources */, + 3D3533F90F0BDFA20059CD05 /* wav.c in Sources */, + 3D3533FA0F0BDFA20059CD05 /* wve.c in Sources */, + 3D3533FB0F0BDFA20059CD05 /* xi.c in Sources */, + 3D3533FF0F0BDFD80059CD05 /* command.c in Sources */, + 3D35340D0F0BE0470059CD05 /* strings.c in Sources */, + 3D35340E0F0BE0470059CD05 /* svx.c in Sources */, + 3D3534110F0BE27E0059CD05 /* ima_adpcm.c in Sources */, + 3D3534160F0BE2AA0059CD05 /* txw.c in Sources */, + 3D3534170F0BE2AA0059CD05 /* ulaw.c in Sources */, + 3D3534180F0BE2AA0059CD05 /* voc.c in Sources */, + 3D35341B0F0BE3240059CD05 /* ms_adpcm.c in Sources */, + 3D35341E0F0BE41E0059CD05 /* g72x.c in Sources */, + 3D35341F0F0BE4290059CD05 /* gsm610.c in Sources */, + 3D35342A0F0BE5370059CD05 /* g72x.c in Sources */, + 3D3534300F0BE5510059CD05 /* gsm_create.c in Sources */, + 3D3534310F0BE5510059CD05 /* gsm_decode.c in Sources */, + 3D3534320F0BE5510059CD05 /* gsm_destroy.c in Sources */, + 3D3534330F0BE5510059CD05 /* gsm_encode.c in Sources */, + 3D35343A0F0BE58D0059CD05 /* code.c in Sources */, + 3D35343C0F0BE58D0059CD05 /* decode.c in Sources */, + 3D35343D0F0BE58D0059CD05 /* gsm_option.c in Sources */, + 3D3534430F0BE5B50059CD05 /* g721.c in Sources */, + 3D3534440F0BE5B50059CD05 /* g723_16.c in Sources */, + 3D3534450F0BE5B50059CD05 /* g723_24.c in Sources */, + 3D3534460F0BE5B50059CD05 /* g723_40.c in Sources */, + 3D35344B0F0BE5EB0059CD05 /* long_term.c in Sources */, + 3D35344C0F0BE5EB0059CD05 /* lpc.c in Sources */, + 3D35344D0F0BE5EB0059CD05 /* preprocess.c in Sources */, + 3D3534520F0BE6190059CD05 /* rpe.c in Sources */, + 3D3534530F0BE6190059CD05 /* short_term.c in Sources */, + 3D3534540F0BE6190059CD05 /* table.c in Sources */, + 3D3534580F0BE6420059CD05 /* add.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D5CD82A0B5BC73700DF426B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D5CD8340B5BC75E00DF426B /* osstuff.c in Sources */, + 3D5CD8350B5BC75E00DF426B /* extern.c in Sources */, + 3D5CD8360B5BC75E00DF426B /* xldmem.c in Sources */, + 3D5CD8370B5BC75E00DF426B /* xlbfun.c in Sources */, + 3D5CD8380B5BC75E00DF426B /* xlcont.c in Sources */, + 3D5CD8390B5BC75E00DF426B /* xldbug.c in Sources */, + 3D5CD83A0B5BC75E00DF426B /* xleval.c in Sources */, + 3D5CD83B0B5BC75E00DF426B /* xlfio.c in Sources */, + 3D5CD83C0B5BC75E00DF426B /* xlftab.c in Sources */, + 3D5CD83D0B5BC75E00DF426B /* xlglob.c in Sources */, + 3D5CD83E0B5BC75E00DF426B /* xlimage.c in Sources */, + 3D5CD83F0B5BC75E00DF426B /* xlinit.c in Sources */, + 3D5CD8400B5BC75E00DF426B /* xlio.c in Sources */, + 3D5CD8410B5BC75E00DF426B /* xlisp.c in Sources */, + 3D5CD8420B5BC75E00DF426B /* xljump.c in Sources */, + 3D5CD8430B5BC75E00DF426B /* xllist.c in Sources */, + 3D5CD8440B5BC75E00DF426B /* xlmath.c in Sources */, + 3D5CD8450B5BC75E00DF426B /* xlobj.c in Sources */, + 3D5CD8460B5BC75E00DF426B /* xlpp.c in Sources */, + 3D5CD8470B5BC75E00DF426B /* xlprin.c in Sources */, + 3D5CD8480B5BC75E00DF426B /* xlread.c in Sources */, + 3D5CD8490B5BC75E00DF426B /* xlstr.c in Sources */, + 3D5CD84A0B5BC75E00DF426B /* xlsubr.c in Sources */, + 3D5CD84B0B5BC75E00DF426B /* xlsym.c in Sources */, + 3D5CD84C0B5BC75E00DF426B /* xlsys.c in Sources */, + 3D5CD84D0B5BC75E00DF426B /* abs.c in Sources */, + 3D5CD84E0B5BC75E00DF426B /* alpass.c in Sources */, + 3D5CD84F0B5BC75E00DF426B /* amosc.c in Sources */, + 3D5CD8500B5BC75E00DF426B /* areson.c in Sources */, + 3D5CD8510B5BC75E00DF426B /* aresoncv.c in Sources */, + 3D5CD8520B5BC75E00DF426B /* aresonvc.c in Sources */, + 3D5CD8530B5BC75E00DF426B /* aresonvv.c in Sources */, + 3D5CD8540B5BC75E00DF426B /* atone.c in Sources */, + 3D5CD8550B5BC75E00DF426B /* atonev.c in Sources */, + 3D5CD8570B5BC75E00DF426B /* buzz.c in Sources */, + 3D5CD8580B5BC75E00DF426B /* chase.c in Sources */, + 3D5CD8590B5BC75E00DF426B /* clip.c in Sources */, + 3D5CD85A0B5BC75E00DF426B /* congen.c in Sources */, + 3D5CD85B0B5BC75E00DF426B /* const.c in Sources */, + 3D5CD85C0B5BC75E00DF426B /* coterm.c in Sources */, + 3D5CD85D0B5BC75E00DF426B /* delaycv.c in Sources */, + 3D5CD85E0B5BC75E00DF426B /* exp.c in Sources */, + 3D5CD85F0B5BC75E00DF426B /* fmosc.c in Sources */, + 3D5CD8600B5BC75E00DF426B /* follow.c in Sources */, + 3D5CD8610B5BC75E00DF426B /* fromarraystream.c in Sources */, + 3D5CD8620B5BC75E00DF426B /* fromobject.c in Sources */, + 3D5CD8630B5BC75E00DF426B /* gate.c in Sources */, + 3D5CD8640B5BC75E00DF426B /* ifft.c in Sources */, + 3D5CD8650B5BC75E00DF426B /* integrate.c in Sources */, + 3D5CD8660B5BC75E00DF426B /* log.c in Sources */, + 3D5CD8670B5BC75E00DF426B /* maxv.c in Sources */, + 3D5CD8680B5BC75E00DF426B /* offset.c in Sources */, + 3D5CD8690B5BC75E00DF426B /* oneshot.c in Sources */, + 3D5CD86A0B5BC75E00DF426B /* osc.c in Sources */, + 3D5CD86B0B5BC75E00DF426B /* partial.c in Sources */, + 3D5CD86C0B5BC75E00DF426B /* pluck.c in Sources */, + 3D5CD86D0B5BC75E00DF426B /* prod.c in Sources */, + 3D5CD86E0B5BC75E00DF426B /* pwl.c in Sources */, + 3D5CD86F0B5BC75E00DF426B /* quantize.c in Sources */, + 3D5CD8700B5BC75E00DF426B /* recip.c in Sources */, + 3D5CD8710B5BC75E00DF426B /* reson.c in Sources */, + 3D5CD8720B5BC75E00DF426B /* resoncv.c in Sources */, + 3D5CD8730B5BC75E00DF426B /* resonvc.c in Sources */, + 3D5CD8740B5BC75E00DF426B /* resonvv.c in Sources */, + 3D5CD8750B5BC75E00DF426B /* sampler.c in Sources */, + 3D5CD8760B5BC75E00DF426B /* scale.c in Sources */, + 3D5CD8770B5BC75E00DF426B /* shape.c in Sources */, + 3D5CD8780B5BC75E00DF426B /* sine.c in Sources */, + 3D5CD8790B5BC75E00DF426B /* siosc.c in Sources */, + 3D5CD87A0B5BC75E00DF426B /* slope.c in Sources */, + 3D5CD87B0B5BC75E00DF426B /* sqrt.c in Sources */, + 3D5CD87C0B5BC75E00DF426B /* tapv.c in Sources */, + 3D5CD87D0B5BC75E00DF426B /* tone.c in Sources */, + 3D5CD87E0B5BC75E00DF426B /* tonev.c in Sources */, + 3D5CD87F0B5BC75E00DF426B /* upsample.c in Sources */, + 3D5CD8800B5BC75E00DF426B /* white.c in Sources */, + 3D5CD8810B5BC75E00DF426B /* cext.c in Sources */, + 3D5CD8820B5BC75E00DF426B /* cleanup.c in Sources */, + 3D5CD8830B5BC75E00DF426B /* cmdline.c in Sources */, + 3D5CD8840B5BC75E00DF426B /* cmtcmd.c in Sources */, + 3D5CD8850B5BC75E00DF426B /* moxc.c in Sources */, + 3D5CD8860B5BC75E00DF426B /* mem.c in Sources */, + 3D5CD8870B5BC75E00DF426B /* midifile.c in Sources */, + 3D5CD8880B5BC75E00DF426B /* midifns.c in Sources */, + 3D5CD8890B5BC75E00DF426B /* record.c in Sources */, + 3D5CD88A0B5BC75E00DF426B /* seq.c in Sources */, + 3D5CD88B0B5BC75E00DF426B /* seqmread.c in Sources */, + 3D5CD88C0B5BC75E00DF426B /* seqmwrite.c in Sources */, + 3D5CD88D0B5BC75E00DF426B /* seqread.c in Sources */, + 3D5CD88E0B5BC75E00DF426B /* seqwrite.c in Sources */, + 3D5CD88F0B5BC75E00DF426B /* tempomap.c in Sources */, + 3D5CD8900B5BC75E00DF426B /* timebase.c in Sources */, + 3D5CD8910B5BC75E00DF426B /* userio.c in Sources */, + 3D5CD8920B5BC75E00DF426B /* debug.c in Sources */, + 3D5CD8930B5BC75E00DF426B /* falloc.c in Sources */, + 3D5CD8940B5BC75E00DF426B /* add.c in Sources */, + 3D5CD8950B5BC75E00DF426B /* local.c in Sources */, + 3D5CD8960B5BC75E00DF426B /* downsample.c in Sources */, + 3D5CD8970B5BC75E00DF426B /* handlers.c in Sources */, + 3D5CD8980B5BC75E00DF426B /* multiread.c in Sources */, + 3D5CD8990B5BC75E00DF426B /* multiseq.c in Sources */, + 3D5CD89A0B5BC75E00DF426B /* samples.c in Sources */, + 3D5CD89B0B5BC75E00DF426B /* seqext.c in Sources */, + 3D5CD89C0B5BC75E00DF426B /* seqinterf.c in Sources */, + 3D5CD89D0B5BC75E00DF426B /* sndread.c in Sources */, + 3D5CD89E0B5BC75E00DF426B /* sndseq.c in Sources */, + 3D5CD89F0B5BC75E00DF426B /* sndwritepa.c in Sources */, + 3D5CD8A00B5BC75E00DF426B /* sndmax.c in Sources */, + 3D5CD8A10B5BC75E00DF426B /* sound.c in Sources */, + 3D5CD8A20B5BC75E00DF426B /* stats.c in Sources */, + 3D5CD8A30B5BC75E00DF426B /* compose.c in Sources */, + 3D5CD8A40B5BC75E00DF426B /* inverse.c in Sources */, + 3D5CD8A50B5BC75E00DF426B /* resamp.c in Sources */, + 3D5CD8A60B5BC75E00DF426B /* resampv.c in Sources */, + 3D5CD8A70B5BC75E00DF426B /* ffilterkit.c in Sources */, + 3D5CD8A80B5BC75E00DF426B /* avg.c in Sources */, + 3D5CD8A90B5BC75E00DF426B /* fft.c in Sources */, + 3D5CD8AA0B5BC75E00DF426B /* seqfnint.c in Sources */, + 3D5CD8AB0B5BC75E00DF426B /* sndfnint.c in Sources */, + 3D5CD8B20B5BC75E00DF426B /* tapf.c in Sources */, + 3D5CD8B40B5BC75E00DF426B /* ieeecvt.c in Sources */, + 3D5CD8B50B5BC75E00DF426B /* term.c in Sources */, + 3D5CD8B60B5BC75E00DF426B /* yin.c in Sources */, + 3D5CD8B70B5BC75E00DF426B /* alpasscv.c in Sources */, + 3D5CD8B80B5BC75E00DF426B /* alpassvv.c in Sources */, + 3D5CD8B90B5BC75E00DF426B /* eqbandvvv.c in Sources */, + 3D5CD8BA0B5BC75E00DF426B /* path.c in Sources */, + 3D5CD8BB0B5BC75E00DF426B /* convolve.c in Sources */, + 3D5CD8BC0B5BC75E00DF426B /* delaycc.c in Sources */, + 3DBB0A6A1290422300024DD7 /* pa_allocation.c in Sources */, + 3D5CD8C80B5BC75E00DF426B /* instr.cpp in Sources */, + 3D5CD8C90B5BC75E00DF426B /* Clarinet.cpp in Sources */, + 3D5CD8CA0B5BC75E00DF426B /* Delay.cpp in Sources */, + 3D5CD8CB0B5BC75E00DF426B /* DelayL.cpp in Sources */, + 3D5CD8CC0B5BC75E00DF426B /* Envelope.cpp in Sources */, + 3D5CD8CD0B5BC75E00DF426B /* Filter.cpp in Sources */, + 3D5CD8CE0B5BC75E00DF426B /* Instrmnt.cpp in Sources */, + 3D5CD8CF0B5BC75E00DF426B /* Noise.cpp in Sources */, + 3D5CD8D00B5BC75E00DF426B /* OneZero.cpp in Sources */, + 3D5CD8D20B5BC75E00DF426B /* Saxofony.cpp in Sources */, + 3D5CD8D30B5BC75E00DF426B /* Stk.cpp in Sources */, + 3D5CD8D40B5BC75E00DF426B /* WaveLoop.cpp in Sources */, + 3D5CD8D50B5BC75E00DF426B /* WvIn.cpp in Sources */, + 3D5CD8D60B5BC75E00DF426B /* stkinit.cpp in Sources */, + 3D5CD8D70B5BC75E00DF426B /* lpanal.c in Sources */, + 3D5CD8D80B5BC75E00DF426B /* alpassvc.c in Sources */, + 3D5CD8D90B5BC75E00DF426B /* allpoles.c in Sources */, + 3D5CD8DA0B5BC75E00DF426B /* f0.cpp in Sources */, + 3D5CD8DB0B5BC75E00DF426B /* instrclar.c in Sources */, + 3D5CD8DC0B5BC75E00DF426B /* instrsaxall.c in Sources */, + 3D5CD8DD0B5BC75E00DF426B /* lpreson.c in Sources */, + 3D5CD8DE0B5BC75E00DF426B /* instrclarall.c in Sources */, + 3D5CD8DF0B5BC75E00DF426B /* instrsaxfreq.c in Sources */, + 3D5CD8E00B5BC75E00DF426B /* instrclarfreq.c in Sources */, + 3D5CD8E10B5BC75E00DF426B /* instrsax.c in Sources */, + 3D5CD8E40B5BC75E00DF426B /* sliders.c in Sources */, + 3D5CD8EE0B5BC75E00DF426B /* trigger.c in Sources */, + 3DA1194A0D2DE1BF00948714 /* DelayA.cpp in Sources */, + 3DA1194B0D2DE1BF00948714 /* Effect.cpp in Sources */, + 3DA1194C0D2DE1BF00948714 /* FileRead.cpp in Sources */, + 3DA1194D0D2DE1BF00948714 /* FileWvIn.cpp in Sources */, + 3DA1194E0D2DE1BF00948714 /* Flute.cpp in Sources */, + 3DA1194F0D2DE1BF00948714 /* Function.cpp in Sources */, + 3DA119500D2DE1BF00948714 /* Generator.cpp in Sources */, + 3DA119510D2DE1BF00948714 /* JCRev.cpp in Sources */, + 3DA119520D2DE1BF00948714 /* JetTable.cpp in Sources */, + 3DA119530D2DE1BF00948714 /* Mandolin.cpp in Sources */, + 3DA119540D2DE1BF00948714 /* Modal.cpp in Sources */, + 3DA119550D2DE1BF00948714 /* ModalBar.cpp in Sources */, + 3DA119560D2DE1BF00948714 /* NRev.cpp in Sources */, + 3DA119570D2DE1BF00948714 /* OnePole.cpp in Sources */, + 3DA119580D2DE1BF00948714 /* PitShift.cpp in Sources */, + 3DA119590D2DE1BF00948714 /* PluckTwo.cpp in Sources */, + 3DA1195A0D2DE1BF00948714 /* PoleZero.cpp in Sources */, + 3DA1195B0D2DE1BF00948714 /* PRCRev.cpp in Sources */, + 3DA1195C0D2DE1BF00948714 /* ReedTable.cpp in Sources */, + 3DA1195D0D2DE1BF00948714 /* SineWave.cpp in Sources */, + 3DA1195E0D2DE1BF00948714 /* Sitar.cpp in Sources */, + 3DA119680D2DE2AA00948714 /* ADSR.cpp in Sources */, + 3DA119690D2DE2AA00948714 /* BandedWG.cpp in Sources */, + 3DA1196A0D2DE2AA00948714 /* BiQuad.cpp in Sources */, + 3DA1196B0D2DE2AA00948714 /* Bowed.cpp in Sources */, + 3DA1196C0D2DE2AA00948714 /* BowTable.cpp in Sources */, + 3DA1196D0D2DE2AA00948714 /* Chorus.cpp in Sources */, + 3DA119710D2DE52400948714 /* instrbanded.c in Sources */, + 3DA119740D2DE54500948714 /* instrbow.c in Sources */, + 3DA119770D2DE56200948714 /* instrbowedfreq.c in Sources */, + 3DA1197A0D2DE57100948714 /* instrflute.c in Sources */, + 3DA1197D0D2DE58A00948714 /* instrfluteall.c in Sources */, + 3DA119800D2DE59A00948714 /* instrflutefreq.c in Sources */, + 3DA119830D2DE5AA00948714 /* instrsitar.c in Sources */, + 3DA119860D2DE5BA00948714 /* stkpitshift.c in Sources */, + 3DA119890D2DE5CF00948714 /* stkrev.c in Sources */, + 3DA119950D2DE71700948714 /* biquadfilt.c in Sources */, + 3DA1199A0D2DE88B00948714 /* stkint.cpp in Sources */, + 3DA120FD0D313E1B00948714 /* stkchorus.c in Sources */, + 3DA120FF0D313E5500948714 /* instrmandolin.c in Sources */, + 3DA121020D313E7C00948714 /* instrmodalbar.c in Sources */, + 3DC916F60D4036DC00DD66C0 /* fmfb.c in Sources */, + 3DC916F90D4036F000DD66C0 /* fmfbv.c in Sources */, + 3D3221540F53D42D00F074EF /* blob.c in Sources */, + 3D3221550F53D42D00F074EF /* bundle.c in Sources */, + 3D3221560F53D42D00F074EF /* message.c in Sources */, + 3D3221570F53D42D00F074EF /* method.c in Sources */, + 3D3221580F53D42D00F074EF /* pattern_match.c in Sources */, + 3D3221590F53D42D00F074EF /* send.c in Sources */, + 3D32215E0F53D42D00F074EF /* timetag.c in Sources */, + 3D3223290F544BBB00F074EF /* nyq-osc-server.c in Sources */, + 3D48B84C0F5993750073A251 /* fftlib.c in Sources */, + 3D48B8500F5993A60073A251 /* fftext.c in Sources */, + 3D48B86E0F599EE90073A251 /* matlib.c in Sources */, + 3DE80D670F7EA825003761D2 /* pvshell.c in Sources */, + 3DE80D690F7EA840003761D2 /* phasevocoder.c in Sources */, + 3DBB0A82129042A500024DD7 /* pa_converters.c in Sources */, + 3DBB0A83129042A500024DD7 /* pa_cpuload.c in Sources */, + 3DBB0A84129042A500024DD7 /* pa_debugprint.c in Sources */, + 3DBB0A85129042A500024DD7 /* pa_dither.c in Sources */, + 3DBB0A86129042A500024DD7 /* pa_front.c in Sources */, + 3DBB0A87129042A500024DD7 /* pa_process.c in Sources */, + 3DBB0A89129042A500024DD7 /* pa_skeleton.c in Sources */, + 3DBB0A8A129042A500024DD7 /* pa_stream.c in Sources */, + 3DBB0A8B129042A500024DD7 /* pa_trace.c in Sources */, + 3DBB0A8E1290437E00024DD7 /* pa_mac_hostapis.c in Sources */, + 3DBB0A90129043A900024DD7 /* pa_mac_core.c in Sources */, + 3DBB0A9C129048D400024DD7 /* pa_mac_core_blocking.c in Sources */, + 3DBB0A9F129048F700024DD7 /* pa_mac_core_utilities.c in Sources */, + 3DBB0AB012904BBB00024DD7 /* pa_unix_util.c in Sources */, + 3DBB0AB512904C0800024DD7 /* pa_ringbuffer.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3DA7D7C112B93C08008E62B1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3DA7D7CC12B93C74008E62B1 /* cmdline.c in Sources */, + 3DA7D7CD12B93C8A008E62B1 /* intgen.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3DAB7F260B2E172300A51A49 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D3223A30F54582900F074EF /* ser-to-osc.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 3D3221720F53D4DF00F074EF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3D32216F0F53D4C300F074EF /* liblo */; + targetProxy = 3D3221710F53D4DF00F074EF /* PBXContainerItemProxy */; + }; + 3D3533A50F0BD8A80059CD05 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3D3533810F0BD6CA0059CD05 /* libsndfile */; + targetProxy = 3D3533A40F0BD8A80059CD05 /* PBXContainerItemProxy */; + }; + 3D6C06C612D8FE6A0027E89B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3D32216F0F53D4C300F074EF /* liblo */; + targetProxy = 3D6C06C512D8FE6A0027E89B /* PBXContainerItemProxy */; + }; + 3D6C06D112D8FF430027E89B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3D32216F0F53D4C300F074EF /* liblo */; + targetProxy = 3D6C06D012D8FF430027E89B /* PBXContainerItemProxy */; + }; + 3D7327DC125BF99D009AAF15 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3D7327A5125BF5D8009AAF15 /* CompileJava */; + targetProxy = 3D7327DB125BF99D009AAF15 /* PBXContainerItemProxy */; + }; + 3DBB0A5612903B0200024DD7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3D5CD82C0B5BC73700DF426B /* ny */; + targetProxy = 3DBB0A5512903B0200024DD7 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 3D08175C0AD01DD00051B745 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = "$(HOME)/bin"; + PREBINDING = NO; + PRODUCT_NAME = "osc-test-client"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../sys/unix ../cmt"; + ZERO_LINK = YES; + }; + name = Development; + }; + 3D08175D0AD01DD00051B745 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = "$(HOME)/bin"; + PREBINDING = NO; + PRODUCT_NAME = "osc-test-client"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../sys/unix ../cmt"; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3D08175E0AD01DD00051B745 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = "$(HOME)/bin"; + PREBINDING = NO; + PRODUCT_NAME = "osc-test-client"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../sys/unix ../cmt"; + ZERO_LINK = NO; + }; + name = Default; + }; + 3D3221740F53D4FD00F074EF /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = HAVE_CONFIG_H; + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + PRODUCT_NAME = liblo; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../liblo/src ../liblo/osx"; + ZERO_LINK = YES; + }; + name = Development; + }; + 3D3221750F53D4FD00F074EF /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PREPROCESSOR_DEFINITIONS = HAVE_CONFIG_H; + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + PRODUCT_NAME = liblo; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../liblo/src ../liblo/osx"; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3D3221760F53D4FD00F074EF /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_PREPROCESSOR_DEFINITIONS = HAVE_CONFIG_H; + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + PRODUCT_NAME = liblo; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../liblo/src ../liblo/osx"; + ZERO_LINK = YES; + }; + name = Default; + }; + 3D3533870F0BD6E00059CD05 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ../sys/unix; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRODUCT_NAME = libsndfile; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + ZERO_LINK = YES; + }; + name = Development; + }; + 3D3533880F0BD6E00059CD05 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = ../sys/unix; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRODUCT_NAME = libsndfile; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3D3533890F0BD6E00059CD05 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = ../sys/unix; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRODUCT_NAME = libsndfile; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + ZERO_LINK = YES; + }; + name = Default; + }; + 3D5CD8300B5BC75600DF426B /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + CMTSTUFF, + macintosh, + PA_USE_COREAUDIO, + OSC, + STK_NYQUIST, + ); + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + ); + LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Development\""; + OTHER_LDFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = ny; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "/usr/local/include $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers ../ffts/src ../snd ../cmt ../sys/unix ../xlisp ../tran ../nyqsrc ../nyqstk/include ../portaudio/include ../liblo $(inherited)"; + ZERO_LINK = YES; + }; + name = Development; + }; + 3D5CD8310B5BC75600DF426B /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PREPROCESSOR_DEFINITIONS = ( + CMTSTUFF, + macintosh, + PA_USE_COREAUDIO, + OSC, + STK_NYQUIST, + ); + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + ); + LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Development\""; + OTHER_LDFLAGS = ""; + PREBINDING = NO; + PRODUCT_NAME = ny; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "/usr/local/include $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers ../ffts/src ../snd ../cmt ../sys/unix ../xlisp ../tran ../nyqsrc ../nyqstk/include ../portaudio/include ../liblo $(inherited)"; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3D5CD8320B5BC75600DF426B /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_PREPROCESSOR_DEFINITIONS = ( + CMTSTUFF, + macintosh, + PA_USE_COREAUDIO, + OSC, + STK_NYQUIST, + ); + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + ); + LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Development\""; + OTHER_LDFLAGS = "-lsndfile"; + PREBINDING = NO; + PRODUCT_NAME = ny; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "/usr/local/include $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers ../ffts/src ../snd ../cmt ../sys/unix ../xlisp ../tran ../nyqsrc ../nyqstk/include ../portaudio/include ../liblo $(inherited)"; + ZERO_LINK = YES; + }; + name = Default; + }; + 3D7327A6125BF5D9009AAF15 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = CompileJava; + }; + name = Development; + }; + 3D7327A7125BF5D9009AAF15 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + PRODUCT_NAME = CompileJava; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3D7327A8125BF5D9009AAF15 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = CompileJava; + }; + name = Default; + }; + 3D7327B3125BF625009AAF15 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "NyquistIDE-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = NyquistIDE; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Development; + }; + 3D7327B4125BF625009AAF15 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "NyquistIDE-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = NyquistIDE; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3D7327B5125BF625009AAF15 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "NyquistIDE-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = NyquistIDE; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Default; + }; + 3DA7D7C612B93C08008E62B1 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = intgen; + }; + name = Development; + }; + 3DA7D7C712B93C08008E62B1 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = intgen; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3DA7D7C812B93C08008E62B1 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PREBINDING = NO; + PRODUCT_NAME = intgen; + }; + name = Default; + }; + 3DAB7F2D0B2E175500A51A49 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = "$(HOME)/bin"; + PREBINDING = NO; + PRODUCT_NAME = "ser-to-osc"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../sys/unix ../cmt"; + ZERO_LINK = YES; + }; + name = Development; + }; + 3DAB7F2E0B2E175500A51A49 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = "$(HOME)/bin"; + PREBINDING = NO; + PRODUCT_NAME = "ser-to-osc"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../sys/unix ../cmt"; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3DAB7F2F0B2E175500A51A49 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = "$(HOME)/bin"; + PREBINDING = NO; + PRODUCT_NAME = "ser-to-osc"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + USER_HEADER_SEARCH_PATHS = "../liblo ../sys/unix ../cmt"; + ZERO_LINK = YES; + }; + name = Default; + }; + 3DEBDFD3095B177A001BCCB6 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + GCC_PREPROCESSOR_DEFINITIONS = ""; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Development; + }; + 3DEBDFD4095B177A001BCCB6 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + GCC_PREPROCESSOR_DEFINITIONS = ""; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + }; + name = Deployment; + }; + 3DEBDFD5095B177A001BCCB6 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + GCC_PREPROCESSOR_DEFINITIONS = ""; + SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Default; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3D08175B0AD01DD00051B745 /* Build configuration list for PBXNativeTarget "osc-test-client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D08175C0AD01DD00051B745 /* Development */, + 3D08175D0AD01DD00051B745 /* Deployment */, + 3D08175E0AD01DD00051B745 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3D3221730F53D4FD00F074EF /* Build configuration list for PBXNativeTarget "liblo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D3221740F53D4FD00F074EF /* Development */, + 3D3221750F53D4FD00F074EF /* Deployment */, + 3D3221760F53D4FD00F074EF /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3D3533860F0BD6E00059CD05 /* Build configuration list for PBXNativeTarget "libsndfile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D3533870F0BD6E00059CD05 /* Development */, + 3D3533880F0BD6E00059CD05 /* Deployment */, + 3D3533890F0BD6E00059CD05 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3D5CD82F0B5BC75600DF426B /* Build configuration list for PBXNativeTarget "ny" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D5CD8300B5BC75600DF426B /* Development */, + 3D5CD8310B5BC75600DF426B /* Deployment */, + 3D5CD8320B5BC75600DF426B /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3D7327A9125BF5F7009AAF15 /* Build configuration list for PBXAggregateTarget "CompileJava" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D7327A6125BF5D9009AAF15 /* Development */, + 3D7327A7125BF5D9009AAF15 /* Deployment */, + 3D7327A8125BF5D9009AAF15 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3D7327B6125BF625009AAF15 /* Build configuration list for PBXNativeTarget "NyquistIDE" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D7327B3125BF625009AAF15 /* Development */, + 3D7327B4125BF625009AAF15 /* Deployment */, + 3D7327B5125BF625009AAF15 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3DA7D7CB12B93C3F008E62B1 /* Build configuration list for PBXNativeTarget "intgen" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3DA7D7C612B93C08008E62B1 /* Development */, + 3DA7D7C712B93C08008E62B1 /* Deployment */, + 3DA7D7C812B93C08008E62B1 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3DAB7F2C0B2E175500A51A49 /* Build configuration list for PBXNativeTarget "ser-to-osc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3DAB7F2D0B2E175500A51A49 /* Development */, + 3DAB7F2E0B2E175500A51A49 /* Deployment */, + 3DAB7F2F0B2E175500A51A49 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3DEBDFD2095B177A001BCCB6 /* Build configuration list for PBXProject "nyquist" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3DEBDFD3095B177A001BCCB6 /* Development */, + 3DEBDFD4095B177A001BCCB6 /* Deployment */, + 3DEBDFD5095B177A001BCCB6 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/macproject/NyquistIcon b/macproject/NyquistIcon new file mode 100644 index 0000000..e8c5c40 --- /dev/null +++ b/macproject/NyquistIcon @@ -0,0 +1 @@ +This file's resource fork holds the Nyquist Icon. \ No newline at end of file diff --git a/macproject/NyquistIcon.sit b/macproject/NyquistIcon.sit new file mode 100644 index 0000000..f25bd87 Binary files /dev/null and b/macproject/NyquistIcon.sit differ diff --git a/macproject/mac_port_changes.txt b/macproject/mac_port_changes.txt new file mode 100644 index 0000000..01473a5 --- /dev/null +++ b/macproject/mac_port_changes.txt @@ -0,0 +1,2 @@ +Changes to Nyquist: + In audiomac.c: (Do byteswap:) long samples = srclength / 2; short *srcs = (short *)src; short *dsts = (short *)dst; long i; for(i=0; i> 8)); } In sndwrite.c (sound_save_sound and sound_save_array both): cvtfn = find_cvt_to_fn(snd, buf); > #ifdef macintosh > if (player) { > gprintf(TRANS, "Playing audio: Click and hold mouse button to stop playback.\n"); > } > #endif while (n > 0) { long togo; float peak; sample_block_type sampblock = sound_get_next(s, &blocklen); #ifdef SNAPSHOTS printf("."); if (sound_created_flag) { printf("SNAPSHOT: "); sound_print_tree(printing_this_sound); sound_created_flag = false; } fflush(stdout); #endif if (sampblock == zero_block || blocklen == 0) { break; } togo = min(blocklen, n); buflen = (*cvtfn)((void *) buf, (void *) sampblock->samples, togo, s->scale, &peak); if (peak > max_sample) max_sample = peak; > #ifdef macintosh > if (Button()) { > if (player) { > snd_reset(player); > } > gprintf(TRANS, "\n\nStopping playback...\n\n\n"); > break; > } > #endif In cext.h: + #ifdef round + #undef round + #endif In fft.c: /* perform the fft: */ fftnf(1, (const int *)&len, temp_fft, temp_fft + len, 1, -1.0); ^^^^^^^^^^^^^ In userio.h: #ifdef MACINTOSH + #undef false + #undef true + #include #define TRANS (long) 0 #define ERROR (long) 1 #define FATAL (long) 2 #define GDEBUG (long) 3 #endif In tran/ifft.c: #ifndef macintosh #include "crtdbg.h" #endif #ifndef macintosh _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF); #endif In userio.c: strcpy((char *)Pstr, str); * C2PStr((char *)Pstr); strcpy((char *)Pfn, fn); * C2PStr((char *)Pfn); Get from Audacity: snd.c sndconfig.h sndheader.c sndio.c diff --git a/macproject/nyquist.mcp b/macproject/nyquist.mcp new file mode 100644 index 0000000..b37a413 Binary files /dev/null and b/macproject/nyquist.mcp differ diff --git a/macproject/nyquist.rsrc b/macproject/nyquist.rsrc new file mode 100644 index 0000000..e69de29 diff --git a/macproject/nyquistdata/CWSettingsMacOS.stg b/macproject/nyquistdata/CWSettingsMacOS.stg new file mode 100644 index 0000000..b0f57b6 Binary files /dev/null and b/macproject/nyquistdata/CWSettingsMacOS.stg differ diff --git a/macproject/packer/packer.mcp b/macproject/packer/packer.mcp new file mode 100644 index 0000000..eb63ccc Binary files /dev/null and b/macproject/packer/packer.mcp differ diff --git a/macproject/packer/packerdata/.DS_Store b/macproject/packer/packerdata/.DS_Store new file mode 100644 index 0000000..a7ad18a Binary files /dev/null and b/macproject/packer/packerdata/.DS_Store differ diff --git a/macproject/unpacker/unpacker.mcp b/macproject/unpacker/unpacker.mcp new file mode 100644 index 0000000..8c33a58 Binary files /dev/null and b/macproject/unpacker/unpacker.mcp differ diff --git a/macproject/unpacker/unpackerdata/CWSettingsMacOS.stg b/macproject/unpacker/unpackerdata/CWSettingsMacOS.stg new file mode 100644 index 0000000..e42471c Binary files /dev/null and b/macproject/unpacker/unpackerdata/CWSettingsMacOS.stg differ diff --git a/macproject/unpacker/unpackerdata/unpacker/TargetDataMacOS.tdt b/macproject/unpacker/unpackerdata/unpacker/TargetDataMacOS.tdt new file mode 100644 index 0000000..592e340 Binary files /dev/null and b/macproject/unpacker/unpackerdata/unpacker/TargetDataMacOS.tdt differ diff --git a/misc/Makefile b/misc/Makefile new file mode 100644 index 0000000..ea17c3a --- /dev/null +++ b/misc/Makefile @@ -0,0 +1,67 @@ +# +# FILE: Makefile +# BY: Christopher Lee Fraley +# and Roger B. Dannenberg. +# DESC: This file builds various utilities for Nyquist +# + +CC = gcc $(CFLAGS) + +# the unix path gets us switches.h: +# the cmt path gets us swlogic.h: +CFLAGS = -g -I../sys/unix -I../cmt + +# Directory info: +BINPATH = . + +# Intgen stuff: +intgen: cmdline.o intgen.o + $(CC) cmdline.o intgen.o -o $(BINPATH)/intgen + +cmdline.o: cext.h cmdline.h +intgen.o: cext.h cmdline.h + +#sampleprint - dumb but useful +sampleprint: sampleprint.o + $(CC) sampleprint.o -o $(BINPATH)/sampleprint + +sampleprint.o: sampleprint.c + +#sine +sne: sne.o + $(CC) sne.o -o $(BINPATH)/sne + +sne.o: sne.c + +#play +play: play.o + $(CC) play.o -o $(BINPATH)/play + +play.o: play.c + +#plot +plot: plot.o + $(CC) plot.o -o $(BINPATH)/plot + +plot.o: plot.c + +#unpacker +unpacker_o = unpacker.o convert.o + +unpacker: $(unpacker_o) + $(CC) $(unpacker_o) -o unpacker + +#packer +packer_o = packer.o convert.o + +packer: $(packer_o) + $(CC) $(packer_o) -o packer + +clean: + rm -f *.o + +cleaner: clean + rm -f intgen play sine plot packer unpacker + rm -f *.BAK + rm -f *~ + diff --git a/misc/args.h b/misc/args.h new file mode 100644 index 0000000..dc51ef2 --- /dev/null +++ b/misc/args.h @@ -0,0 +1,65 @@ +/* + * Argument processing macros + * I got tired of rethinking this everytime, + * and 4xbsd doesn't have getopt() + * + * The following is an example of the use of this stuff + * + +#include "args.h" +#include + +main(argc, argv) +char **argv; +{ + char *a = "a", *b = "b", *c = "c"; + int x = 0, y = 0, z = 0; + ARGLOOP + STRINGARG(a) a = p; ENDSTRINGARG + STRINGARG(b) b = p; ENDSTRINGARG + STRINGARG(c) c = p; ENDSTRINGARG + FLAGARG(x) x++; ENDFLAGARG + FLAGARG(y) y++; ENDFLAGARG + FLAGARG(z) z++; ENDFLAGARG + + BADARG + fprintf(stderr, "unknown option %c\n", *p); + fprintf(stderr, "Usage: usage\n"); + exit(1); + ENDBADARG + ENDARGLOOP + + Here, the remaining args are argv[0] to argv[argc - 1] + + printf("a=%s b=%s c=%s x=%d y=%d z=%d\nargs:", a, b, c, x, y, z); + { int i; for(i = 0; i < argc; i++) + printf(" %s", argv[i]); + } + printf("\n"); +} + + * + */ + + +#define ARGLOOP \ + while(--argc > 0 && **++argv == '-') { \ + register char *p; \ + for(p = *argv + 1; *p != '\0'; p++) { \ + switch(*p) { \ + +#define ENDARGLOOP \ + } \ + } \ +nextarg:; \ + } \ + +#define FLAGARG(c) case c: +#define ENDFLAGARG break; + +#define STRINGARG(c) case c: if(!*++p) p = *++argv, argc--; +#define ENDSTRINGARG goto nextarg; + +#define BADARG default: +#define ENDBADARG break; + diff --git a/misc/cext.h b/misc/cext.h new file mode 100644 index 0000000..1d03def --- /dev/null +++ b/misc/cext.h @@ -0,0 +1,7 @@ +/* cext.h -- extensions to c */ + +#define true 1 +#define false 0 +#define private static +#define boolean int +#define byte unsigned char diff --git a/misc/cmdline.c b/misc/cmdline.c new file mode 100644 index 0000000..5302353 --- /dev/null +++ b/misc/cmdline.c @@ -0,0 +1,406 @@ +/* cmdline.c -- command line parsing routines */ +/* + * This module is designed to allow various modules to scan (and rescan) + * the command line for applicable arguments. The goal is to hide as + * much information about switches and their names as possible so that + * switches become more consistent across applications and so that the + * author of an application need not do a lot of work to provide numerous + * options. Instead, each module scans the command line for its own + * arguments. + * + * Command lines are of the following form: + * command -s1 -s2 opt2 -s3 arg1 arg2 -s4 opt4 arg3 + * command @filename + * The @filename form reads commands of the first form from filename + * Note that there are three kinds of command line parameters: + * (1) A Switch is a "-" followed by a name, e.g. "-s1" + * (2) An Option is a Switch followed by a space and name, e.g. "-s2 opt2" + * (3) An Argument is a name by itself, e.g. "arg1" + * Note also that a switch followed by an argument looks just like an + * option, so a list of valid option names is necessary to disambiguate. + * + * A main program that uses cmdline.c should do the following: + * (1) create an array of pointers to strings (char *names[]) that + * contains every possible option name + * (2) create another array of pointers to strings that contains + * every possible switch name + * (2) call cl_init(switches, nsw, options, nopt, argv, argc) + * cl_init will report an error (to stderr) if it finds any illegal + * switch or option names. + * + * Afterward, switches, options, and arguments can be accessed by + * calling cl_switch, cl_option, and cl_arg. If cl_switch or cl_option + * is called with a switch name that was not mentioned in the call to + * cl_init, an error will result. This indicates that the application + * author omitted a valid switch or option name when calling cl_init. + * This is an error because the full set of names is needed for error + * checking and to distinguish arguments from options. + * + * cl_nswitch and cl_noption are similar to cl_switch and cl_option, + * except they each take a list of equivalent switch or option names. + * This makes it simple to allow both verbose (-debug) and terse (-d) names. + */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 13-Jun-86 | Created Change Log +* 6-Aug-86 | Modified for Lattice 3.0 -- use "void" to type some routines +* 27-Dec-93 | "@file" as first arg reads command line args from file +*****************************************************************************/ + +#include "stdlib.h" +#include "cext.h" +#include "stdio.h" +#include "ctype.h" +#include "cmdline.h" +#include "string.h" + +private char **voptions; /* valid options */ +private int noptions; /* number of options */ +private char **vswitches; /* valid switches */ +private int nswitches; /* number of switches */ +private char **argv; /* command line argument vector */ +private int argc; /* length of argv */ + +private int cl_rdy = false; /* set to true when initialized */ + +/***************************************************************************** +* Routines local to this module +*****************************************************************************/ +private void check_names(); +private int find_match(); +private int find_string(); +private void ready_check(); +void indirect_command(char *filename, char ***argvp, int *argcp, char *oldarg0); + + +/**************************************************************** +* check_names +* Inputs: +* char *names[]: array of alternative switch or option names +* int nnames: number of alternative switch or option names +* char *valid[]: array of valid names +* int nvalid: number of valid names +* Effect: +* Checks that all names are in validnames. If not, print +* an error message. +*****************************************************************/ + +private void check_names(names, nnames, valid, nvalid) + char *names[]; + int nnames; + char *valid[]; + int nvalid; +{ + int i; /* loop counters */ + for (i = 0; i < nnames; i++) { + if (find_string(names[i], valid, nvalid) >= nvalid) { + fprintf(stderr, "internal error detected by cmdline module:\n"); + fprintf(stderr, "\t'%s' should be in valid lists\n", names[i]); + } + } +} + +/**************************************************************** +* cl_arg +* Inputs: +* n: the index of the arg needed +* Results: +* pointer to the nth arg, or NULL if none exists +* arg 0 is the command name +*****************************************************************/ + +char *cl_arg(n) + int n; +{ + int i = 1; + if (n <= 0) return argv[0]; + while (i < argc) { + if (*argv[i] == '-') { + if (find_string(argv[i], voptions, noptions) < noptions) + i += 2; /* skip name and option */ + else i += 1; /* skip over switch name */ + } else if (n == 1) { + return argv[i]; + } else { /* skip over argument */ + n--; + i++; + } + } + return NULL; +} + +/***************************************************************************** +* cl_init +* Inputs: +* char *switches[]: array of switch names +* int nsw: number of switch names +* char *options[]: array of option names +* int nopt: number of option names +* char *av: array of command line fields (argv) +* int ac: number of command line fields (argc) +* Effect: +* Checks that all command line entries are valid. +* Saves info for use by other routines. +* Returns: +* True if syntax checks OK, otherwise false +*****************************************************************************/ + +boolean cl_init(switches, nsw, options, nopt, av, ac) + char *switches[]; + int nsw; + char *options[]; + int nopt; + char *av[]; + int ac; +{ + int i; /* index into argv */ + boolean result = true; + + vswitches = switches; nswitches = nsw; + voptions = options; noptions = nopt; + argv = av; argc = ac; + + if (ac == 2 && *(av[1]) == '@') { + /* read new args from file */ + indirect_command(av[1] + 1, &argv, &argc, av[0]); + } + + for (i = 1; i < argc; i++) { /* case fold lower */ + size_t j; + for (j = 0; j < strlen(argv[i]); j++) + if (isupper(argv[i][j])) + argv[i][j] = tolower(argv[i][j]); + } + + /* check command line syntax: */ + i = 1; + while (i < argc) { + if (*argv[i] == '-') { + if (find_string(argv[i], voptions, noptions) < noptions) { + i += 1; /* skip name and option */ + if (i < argc && *argv[i] == '-') { + fprintf(stderr, "missing argument after %s\n", argv[i-1]); + result = false; + i += 1; + } + } else if (find_string(argv[i], vswitches, nswitches) < + nswitches) { + i += 1; /* skip over switch name */ + } else { + fprintf(stderr, "invalid switch: %s\n", argv[i]); + i += 1; + result = false; + } + } else i++; /* skip over argument */ + } + cl_rdy = true; + return result; +} + +/**************************************************************** +* cl_noption +* Inputs: +* char *names[]: array of alternative switch names +* int nnames: number of alternative switch names +* Result: +* returns pointer to if one exists, otherwise null +* Effect: +* looks for pattern in command line of the form "-n s", +* where n is a member of names. Returns pointer to s. +* Implementation: +* find the option name, then +* see if the switch is followed by a string that does +* not start with "-" +*****************************************************************/ + +char *cl_noption(names, nnames) + char *names[]; + int nnames; +{ + int i; /* index of switch */ + + ready_check(); + check_names(names, nnames, voptions, noptions); + i = find_match(names, nnames) + 1; /* point at the option */ + if (i < argc) { /* make sure option exists */ + if (*(argv[i]) != '-') return argv[i]; + } + return NULL; +} + +/***************************************************************** +* cl_nswitch +* Inputs: +* char *names[]: array of alternative switch names +* int nnames: number of alternative switch names +* Effect: +* Checks that names is valid. +* Finds a pattern in command line of the form "-n", where +* n is a member of names. +* Result: +* returns pointer to command line switch if one exists, +* otherwise null +*****************************************************************/ + +char *cl_nswitch(names, nnames) + char *names[]; + int nnames; +{ + int i; /* index of switch */ + + ready_check(); + check_names(names, nnames, vswitches, nswitches); + i = find_match(names, nnames); + if (i < argc) return argv[i]; + /* else */ return NULL; +} + +/**************************************************************** +* cl_option +* Inputs: +* char *name: option name +* Outputs: +* returns char *: the option string if found, otherwise null +****************************************************************/ + +char *cl_option(name) + char *name; +{ + char *names[1]; /* array to hold name */ + + names[0] = name; + return cl_noption(names, 1); +} + +/**************************************************************** +* cl_switch +* Inputs: +* char *name: switch name +* Outputs: +* boolean: true if switch found +****************************************************************/ + +boolean cl_switch(name) + char *name; +{ + char *names[1]; /* array to hold name */ + + names[0] = name; + return cl_nswitch(names, 1) != NULL; +} + +/**************************************************************** +* find_match +* Inputs: +* char *names[]: array of alternative switch or option names +* int nnames: number of alternative switch or option names +* Effect: +* Looks for command line switch that matches one of names. +* Returns: +* Index of switch if found, argc if not found. +*****************************************************************/ + +private int find_match(names, nnames) + char *names[]; + int nnames; +{ + int j; /* loop counter */ + for (j = 0; j < argc; j++) { + if (find_string(argv[j], names, nnames) < nnames) return j; + } + return argc; +} + +/**************************************************************** +* find_string +* Inputs: +* char *s: string to find +* char *names[]: array of strings +* int nnames: number of strings +* Effect: +* Looks for s in names +* Returns: +* Index of s in names if found, nnames if not found +*****************************************************************/ + +private int find_string(s, names, nnames) + char *s; + char *names[]; + int nnames; +{ + int i; /* loop counter */ + for (i = 0; i < nnames; i++) { + if (strcmp(s, names[i]) == 0) { + return i; + } + } + return nnames; +} + +boolean is_whitespace(int c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; +} + +boolean get_arg(file, arg) + FILE *file; + char *arg; +{ + int c; + while ((c = getc(file)) != EOF && is_whitespace(c)) ; + if (c == EOF) return false; + ungetc(c, file); + while ((c = getc(file)) != EOF && !is_whitespace(c)) { + *arg++ = c; + } + *arg = 0; + return true; +} + + +void indirect_command(filename, argvp, argcp, oldarg0) + char *filename; + char ***argvp; + int *argcp; + char *oldarg0; +{ + FILE *argfile = fopen(filename, "r"); + if (!argfile) { + *argvp = (char **) malloc(sizeof(char *)); + (*argvp)[0] = oldarg0; + *argcp = 1; + } else { + int i = 1; + char arg[100]; + while (get_arg(argfile, arg)) i++; + fclose(argfile); + argfile = fopen(filename, "r"); + *argvp = (char **) malloc(sizeof(char *) * i); + (*argvp)[0] = oldarg0; + *argcp = i; + i = 1; + while (get_arg(argfile, arg)) { + (*argvp)[i] = (char *) malloc(strlen(arg) + 1); + strcpy((*argvp)[i], arg); + i++; + } + } +} + + +/**************************************************************** +* ready_check +* Effect: +* Halt program if cl_rdy is not true. +*****************************************************************/ +private void ready_check() +{ + if (!cl_rdy) { + fprintf(stderr, + "Internal error: cl_init was not called, see cmdline.c\n"); + exit(1); + } +} diff --git a/misc/cmdline.h b/misc/cmdline.h new file mode 100644 index 0000000..fe72b28 --- /dev/null +++ b/misc/cmdline.h @@ -0,0 +1,6 @@ +boolean cl_init(); +char *cl_option(); +char *cl_noption(); +boolean cl_switch(); +char *cl_nswitch(); +char *cl_arg(); diff --git a/misc/cmu/Projects.zip b/misc/cmu/Projects.zip new file mode 100644 index 0000000..cbb4c4a Binary files /dev/null and b/misc/cmu/Projects.zip differ diff --git a/misc/cmu/cleanup.bat b/misc/cmu/cleanup.bat new file mode 100644 index 0000000..e596d88 --- /dev/null +++ b/misc/cmu/cleanup.bat @@ -0,0 +1,53 @@ +rem erase everything but source so we can save sources to web + +cd ..\.. + +rmdir /s /q nyqrel +rmdir /s /q nyqrelide +rmdir /s /q nyqrelwin +rmdir /s /q misc\filelist_Release +rmdir /s /q misc\packer_Release +rmdir /s /q misc\intgen_win32 +rmdir /s /q misc\unpacker_Release + +del *.pac +del *.ncb +del unpacker.exe +del packer.exe +del mt.dep +del jnyqide\*.class +del nyquist.exe +del jnyqide\*.jar +del *.jar + +rmdir /s /q ..\nyquist-backup +mkdir ..\nyquist-backup +move idesetup ..\nyquist-backup +move winsetup ..\nyquist-backup +move setup ..\nyquist-backup + +move NyqWinDebug ..\nyquist-backup +move NyqWinRel ..\nyquist-backup +move WinDebug ..\nyquist-backup +move WinRel ..\nyquist-backup +move portaudio_test ..\nyquist-backup +move jones ..\nyquist-backup +move sjlib_103_DOS.tgz ..\nyquist-backup +move sjlib_DOS_104.tgz ..\nyquist-backup +move demos\plight ..\nyquist-backup +move nyqide ..\nyquist-backup + +del nyqide\nyquist.exe +del nyquist.opt + +rmdir /s /q misc\filelist_Debug +rmdir /s /q misc\intgen_Win32\WinDebug +rmdir /s /q misc\packer_Debug +rmdir /s /q misc\unpacker_Debug +rmdir /s /q liblo\ser-to-osc\Debug +rmdir /s /q liblo\ser-to-osc\Release +rmdir /s /q liblo\test-client\Debug +rmdir /s /q liblo\test-client\Release + +cd misc\cmu + diff --git a/misc/cmu/cmu-linux-install.lsp b/misc/cmu/cmu-linux-install.lsp new file mode 100644 index 0000000..eb00f13 --- /dev/null +++ b/misc/cmu/cmu-linux-install.lsp @@ -0,0 +1,68 @@ +;; edit music.software.html and copy zip file to web + +;; where is the html page for nyquist downloads?: +(setf ny-web-path "/afs/cs/project/music/web/") +;; where are the actual nyquist download files: +(setf ny-web-bin-path "/afs/cs/project/music/web/nyquist/") + +(defun ny-web (file) (strcat ny-web-path file)) + +;; verbose version of SYSTEM +;; +(defun vsystem (cmd) + (format t "system command: ~A~%" cmd) + (system cmd)) + +(defun linux-edit-music-software-html () + (let (inf outf input i prefix postfix postfix1 postfix2) + (setf inf (open (ny-web "music.software.html"))) + (setf outf (open (ny-web "new.html") :direction :output)) + (format t "Major version number (e.g. 2): ") + (setf *maj* (read)) + (format t "Minor version number (e.g. 27): ") + (setf *min* (read)) + + ;; find "source code for Linux" + (print "source code for Linux") + (setf input (read-line inf)) + (while (not (setf i (string-search "source code for Linux" input))) + (format outf "~A~%" input) + (setf input (read-line inf))) + ;; now we have the line with the reference to the zip file and + ;; also the text description, but we have to find the text to change + ;; (ignore the variable i, it's the wrong location to change) + (setf i (string-search "nyquist/nyquist" input)) + (setf prefix (subseq input 0 (+ i 15))) + (setf postfix (subseq input (+ i 15))) + (setf i (string-search ".zip" postfix)) + (setf postfix (subseq postfix i)) + (setf i (string-search "(v" postfix)) + (setf postfix1 (subseq postfix 0 (+ i 2))) + (setf postfix2 (subseq postfix (+ i 2))) + (setf i (string-search ")" postfix2)) + (setf postfix2 (subseq postfix2 i)) + (format outf "~A~A~A~A~A.~A~A~%" prefix *maj* *min* + postfix1 *maj* *min* postfix2) + + (setf input (read-line inf)) + (while input + (format outf "~A~%" input) + (setf input (read-line inf))) + + (close inf) + (close outf) + + (vsystem (strcat "rm " (ny-web "music.software.html"))) + (vsystem (strcat "mv " (ny-web "new.html") " " + (ny-web "music.software.html"))) + (vsystem (format nil "cp ../nyquist.zip ~Anyquist~A~A.zip" + ny-web-bin-path *maj* *min*)) + (vsystem (format nil "mv ../release.pac nyquist~A~A.pac" *maj* *min*)) + + )) + +(linux-edit-music-software-html) + + +(exit) + diff --git a/misc/cmu/cmuinstall.bat b/misc/cmu/cmuinstall.bat new file mode 100644 index 0000000..f6306f6 --- /dev/null +++ b/misc/cmu/cmuinstall.bat @@ -0,0 +1,7 @@ +rem run this to update the nyquist website + +copy q:\web\music.software.html music.software.html +rem edit music.software.html and build install.bat +del /q cmuinstall2.bat +..\..\winrel\nyquist.exe +cmuinstall2.bat diff --git a/misc/cmu/cmuinstall.sh b/misc/cmu/cmuinstall.sh new file mode 100644 index 0000000..3a527ca --- /dev/null +++ b/misc/cmu/cmuinstall.sh @@ -0,0 +1,8 @@ + +# source this to update the nyquist website + +scp rbd@linux.gp.cs.cmu.edu:music/web/music.software.html music.software.html +# edit music.software.html and build install.bat +rm -f cmuinstall2.sh +../../ny +s cmuinstall2.sh diff --git a/misc/cmu/cmuinstall2.bat b/misc/cmu/cmuinstall2.bat new file mode 100644 index 0000000..93f7fa6 --- /dev/null +++ b/misc/cmu/cmuinstall2.bat @@ -0,0 +1,10 @@ +copy ..\..\setup\setupnyqrun.exe q:\web\nyquist\setupnyqrun231.exe +copy ..\..\setup\setupnyqwinrun.exe q:\web\nyquist\setupnyqwinrun231.exe +copy ..\..\setup\setupnyqiderun.exe q:\web\nyquist\setupnyqiderun231.exe +copy new.html q:\web\music.software.html +call cleanup.bat +echo "In d:\rbd, make nyquist.zip from nyquist now...then type return to the pause..." +pause +move ..\..\..\nyquist.zip ..\..\..\nyquist231.zip +copy ..\..\..\nyquist231.zip q:\web\nyquist\nyqsrc231.zip +call restore.bat diff --git a/misc/cmu/cmuinstallmac.sh b/misc/cmu/cmuinstallmac.sh new file mode 100644 index 0000000..3f6ae1d --- /dev/null +++ b/misc/cmu/cmuinstallmac.sh @@ -0,0 +1,40 @@ +# cmuinstallmac.sh -- to update website with Mac OS X version of Nyquist +# run this like this: source cmuinstallmac.sh + +ls ~/nyquist/*/*~ +echo "build jNyqIDE deployment project with Xcode and type return" +read +mkdir -p ~/tmp/Applications +cd ~/tmp/Applications +## can't remove and replace plight -- if you do, it won't work. +## I don't know why. Also, the following fails without sudo... +# rm -rf NyquistIDE.app/Contents/Resources/Java/demos/plight +rm -rf nyquist +mkdir nyquist +mkdir nyquist/doc +cp ~/nyquist/doc/* nyquist/doc +echo "type the version string, e.g. \"232\" : " +read versionstring +tar cvfz "nyqosx"$versionstring".tgz" ~/nyquist/macosxproject/build/Deployment/NyquistIDE.app nyquist +mv nyqosx*.tgz ~/nyquist +# Make source release +cd ~/nyquist +rm -rf nyquist +svn export -r BASE . nyquist +rm -rf nyquist/demos/plight +zip -r "nyqsrc"$versionstring".zip" nyquist +# THE FOLLOWING PUTS THE VERSION AT CMU, BUT NOW RELEASES GO TO SOURCEFORGE +#scp "nyqosx"$versionstring".tgz" rbd@linux.gp.cs.cmu.edu:music/web/nyquist/ +# HERE IS THE LINE FOR SOURCEFORGE +#echo "when sftp connects..." +#echo "> put nyqosx"$versionstring".tgz" +#echo "> put nyqsrc"$versionstring".zip" +#echo "> exit" +#sftp rbd@frs.sourceforge.net +#echo "after sftp'ing mac, windows, and source release files, go to" +#echo "Admin : File Releases : Add Release to make a new release" + +echo go to sourceforge.net/projects/nyquist, Files, open nyquist +echo Add Folder for current version, click the folder to open it +echo Add File and browse to ~/nyquist/nyqsrcNNN.zip +echo Add File and browse to ~/nyquist/nyqosxNNN.zip diff --git a/misc/cmu/init.lsp b/misc/cmu/init.lsp new file mode 100644 index 0000000..191614f --- /dev/null +++ b/misc/cmu/init.lsp @@ -0,0 +1,190 @@ +;; edit music.software.html and make install.bat + +(load "nyinit.lsp") + +;; see if we are running on Windows +(setf *windowsp* (not (null (listdir "WinRel")))) + +(setf *remote* (if *windowsp* "q:\\web" "rbd@linux.gp.cs.cmu.edu:music/web")) + +(defun edit-music-software-html () + (let (inf outf input i prefix postfix postfix1 postfix2) + (setf inf (open "music.software.html")) + (if (null inf) (error "could not open music.software.html")) + (setf outf (open "new.html" :direction :output)) + (if (null outf) (error "could not open new.html for output")) + (format t "Major version number (e.g. 2): ") + (setf *maj* (read)) + (format t "Minor version number (e.g. 27): ") + (setf *min* (read)) + + ;; find version in heading + (print "find Executables") + (setf input (read-line inf)) + (while (not (setf i (string-search "Executables (v" input))) + (format outf "~A~%" input) + (setf input (read-line inf))) + (setf prefix (subseq input 0 (+ i 14))) + (setf postfix (subseq input (+ i 14))) + (setf i (string-search ")" postfix)) + (setf postfix (subseq postfix i)) + (format outf "~A~A.~A~A~%" prefix *maj* *min* postfix) + + ;; find nyquist/setupnyqrun + (print "find nyquist/setupnyqrun") + (setf input (read-line inf)) + (while (not (setf i (string-search "nyquist/setupnyqrun" input))) + (format outf "~A~%" input) + (setf input (read-line inf)) + ;(display "finding nyquist/setupnyqrun" input) + ) + (setf prefix (subseq input 0 (+ i 19))) + (setf postfix (subseq input (+ i 19))) + (setf i (string-search "\">" postfix)) + (setf postfix (subseq postfix i)) + (format outf "~A~A~A.exe~A~%" prefix *maj* *min* postfix) + + ;; find nyquist/setupnyqwinrun +; (print "find nyquist/setupnyqwinrun") +; (setf input (read-line inf)) +; (while (not (setf i (string-search "nyquist/setupnyqwinrun" input))) +; (format outf "~A~%" input) +; (setf input (read-line inf))) +; (setf prefix (subseq input 0 (+ i 22))) +; (setf postfix (subseq input (+ i 22))) +; (setf i (string-search "\">" postfix)) +; (setf postfix (subseq postfix i)) +; (format outf "~A~A~A.exe~A~%" prefix *maj* *min* postfix) + + ;; find nyquist/setupnyqiderun + (print "find nyquist/setupnyqiderun") + (setf input (read-line inf)) + (while (not (setf i (string-search "nyquist/setupnyqiderun" input))) + (format outf "~A~%" input) + (setf input (read-line inf))) + (setf prefix (subseq input 0 (+ i 22))) + (setf postfix (subseq input (+ i 22))) + (setf i (string-search "\">" postfix)) + (setf postfix (subseq postfix i)) + (format outf "~A~A~A.exe~A~%" prefix *maj* *min* postfix) + + ;; find nyquist/nyqosx + (print "find nyquist/nyqosx") + (setf input (read-line inf)) + (while (not (setf i (string-search "nyquist/nyqosx" input))) + (format outf "~A~%" input) + (setf input (read-line inf))) + (setf prefix (subseq input 0 (+ i 14))) + (setf postfix (subseq input (+ i 14))) + (setf i (string-search ".tgz" postfix)) + (setf postfix (subseq postfix i)) + (setf i (string-search "(v" postfix)) + (setf postfix1 (subseq postfix 0 (+ i 2))) + (setf postfix2 (subseq postfix (+ i 2))) + (setf i (string-search ")" postfix2)) + (setf postfix2 (subseq postfix2 i)) + (format outf "~A~A~A~A~A.~A~A~%" prefix *maj* *min* + postfix1 *maj* *min* postfix2) + + ;; find nyqosx + (print "find nyqosx") + (setf input (read-line inf)) + (while (not (setf i (string-search "nyqosx" input))) + (format outf "~A~%" input) + (setf input (read-line inf))) + (setf prefix (subseq input 0 (+ i 10))) + (setf postfix (subseq input (+ i 10))) + (setf i (string-search "" postfix)) + (setf postfix (subseq postfix i)) + (format outf "~A~A~A~A~%" prefix *maj* *min* postfix) + + ;; find nyquist/nyqsrc + (print "find nyquist/nyqsrc") + (setf input (read-line inf)) + (while (not (setf i (string-search "nyquist/nyqsrc" input))) + (format outf "~A~%" input) + (setf input (read-line inf))) + (setf prefix (subseq input 0 (+ i 14))) + (setf postfix (subseq input (+ i 14))) + (setf i (string-search ".zip" postfix)) + (setf postfix (subseq postfix i)) + (setf i (string-search "(v" postfix)) + (setf postfix1 (subseq postfix 0 (+ i 2))) + (setf postfix2 (subseq postfix (+ i 2))) + (setf i (string-search ")" postfix2)) + (setf postfix2 (subseq postfix2 i)) + (format outf "~A~A~A~A~A.~A~A~%" prefix *maj* *min* + postfix1 *maj* *min* postfix2) + + (setf input (read-line inf)) + (while input + (format outf "~A~%" input) + (setf input (read-line inf))) + + (close inf) + (close outf) + )) + +; " + +(defun make-install-bat () + (let (outf) + (setf outf (open "cmuinstall2.bat" :direction :output)) + (format outf "copy ..\\..\\setup\\setupnyqrun.exe ~A\\nyquist\\setupnyqrun~A~A.exe~%" + *remote* *maj* *min*) +; (format outf "copy ..\\..\\setup\\setupnyqwinrun.exe ~A\\nyquist\\setupnyqwinrun~A~A.exe~%" +; *remote* *maj* *min*) + (format outf "copy ..\\..\\setup\\setupnyqiderun.exe ~A\\nyquist\\setupnyqiderun~A~A.exe~%" + *remote* *maj* *min*) + (format outf "copy new.html ~A\\music.software.html~%" *remote*) + (format outf "call cleanup.bat~%") + (format outf "echo \"In d:\\rbd, make nyquist.zip from nyquist now...then type return to the pause...\"~%") + (format outf "pause~%") + (format outf "move ..\\..\\..\\nyquist.zip ..\\..\\..\\nyquist~A~A.zip~%" *maj* *min*) + (format outf "copy ..\\..\\..\\nyquist~A~A.zip ~A\\nyquist\\nyqsrc~A~A.zip~%" + *maj* *min* *remote* *maj* *min*) + (format outf "call restore.bat~%") + (close outf))) + +(defun make-install-sh () + (let (outf) + (setf outf (open "cmuinstall2.sh" :direction :output)) + (format outf "echo \"Make sure /Volumes/rbd is mounted...then type return\"~%") + (format outf "read~%"); + (format outf "scp /Volumes/rbd/nyquist/setup/setupnyqrun.exe ~A/nyquist/setupnyqrun~A~A.exe~%" + *remote* *maj* *min*) +; (format outf "scp /Volumes/rbd/nyquist/setup/setupnyqwinrun.exe ~A/nyquist/setupnyqwinrun~A~A.exe~%" +; *remote* *maj* *min*) + (format outf "scp /Volumes/rbd/nyquist/setup/setupnyqiderun.exe ~A/nyquist/setupnyqiderun~A~A.exe~%" + *remote* *maj* *min*) + (format outf "scp new.html ~A/music.software.html~%" *remote*) +#| + ;; this is the old way to make a source zip file + (format outf "echo \"In e:\\rbd\\nyquist\\misc\\cmu, run cleanup.bat now...then type return to the pause...\"~%") + (format outf "read~%") + (format outf "echo \"In e:\\rbd, make nyquist.zip from nyquist now...then type return to the pause...\"~%") + (format outf "read~%") + (format outf "mv /Volumes/rbd/nyquist.zip /Volumes/rbd/nyquist~A~A.zip~%" *maj* *min*) + (format outf "scp /Volumes/rbd/nyquist~A~A.zip ~A/nyquist/nyqsrc~A~A.zip~%" + *maj* *min* *remote* *maj* *min*) + (format outf "echo \"In e:\\rbd\\nyquist\\misc\\cmu, run restore.bat now...then type return to the pause...\"~%") +|# + ;; this is the new way to make a source zip file + (format outf "echo making source zip file...\n") + (format outf "cd ../..\n") + (format outf "cvs export -DNOW nyquist\n") + (format outf "rm -rf nyquist/demos/plight\n") + (format outf "zip -r nyquist.zip nyquist\n") + (format outf "scp nyquist.zip ~A/nyquist/nyqsrc~A~A.zip~%" + *remote* *maj* *min*) + (format outf "rm -rf nyquist.zip nyquist\n") + (format outf "cd misc/cmu\n") + (format outf "read~%") + (close outf))) + +(edit-music-software-html) +(if *windowsp* (make-install-bat) (make-install-sh)) + + +(exit) + diff --git a/misc/cmu/install-plight.sh b/misc/cmu/install-plight.sh new file mode 100644 index 0000000..c71830e --- /dev/null +++ b/misc/cmu/install-plight.sh @@ -0,0 +1,10 @@ +# +# this is a script to post the plight drum machine to the web +# +# usage: on the Mac, source install-plight.sh +# +cd ../../demos +zip -r plight.zip plight +scp plight.zip rbd@linux.gp.cs.cmu.edu:music/web/nyquist/plight-1.zip +rm plight.zip +cd ../misc/cmu diff --git a/misc/cmu/music.software.html b/misc/cmu/music.software.html new file mode 100644 index 0000000..c8b1314 --- /dev/null +++ b/misc/cmu/music.software.html @@ -0,0 +1,189 @@ + + + + + + The Computer Music Project Software + + + +

    +The Computer Music Project Software

    + +

    + PortMusic

    +Information about PortMusic +

    +Aura

    +Aura is not available for general distribution, but you can read +about Aura here. Send mail to Roger +Dannenberg to get a copy of work in progress. +

    + Nyquist

    +Nyquist is a sound synthesis and composition language based on a Lisp syntax. +Nyquist is an elegant and powerful system based on functional programming. +

    +Documentation

    + + + +

    +Executables (v2.27)

    + + + +

    +Source

    + + + +

    +Version 2.14 (older, but more tested than the latest release)

    + + +If you have problems getting Nyquist, please contact Roger Dannenberg (rbd@cs.cmu.edu).  +

    +CMU MIDI Toolkit

    +The CMU Midi Toolkit (CMT) is a collection of software for writing interactive +MIDI software in C. CMT includes a number of handy utilities allong with +an application "shell" that provides timing, scheduling, and MIDI interfaces +that are portable across DOS, Mac, SGI, and Amiga platforms. +

    CMT is distributed by the CMU School of Computer Science. For $30 to +cover our costs, we will send you 3.5" DS/DD disks (including executables +and source code) and an 100 page manual. Please indicate your machine type. +Checks should be payable to Carnegie Mellon University, and correspondence +should be addressed to Roger Dannenberg, School of Computer Science, Carnegie +Mellon University, Pittsburgh, PA 15213 USA. +

    CMT runs on the following systems: +

      Macintosh (requires Apple MIDI Manager), +

      DOS (requires MPU-401 compatible MIDI interface), and +

      Amiga (requires Commodore CAMD drivers),

    +using the following compilers: Think C v5, Borland C++ v3, Turbo C++ for +DOS v3, Microsoft C v7, Quick C v2.5, Lattice C v5 (Amiga), and Aztec C +v5 (Amiga). (Amiga code is retained in the release but is no longer supported.) +

    +Documentation

    + + + +

    +Executables

    + + + +

    +Source

    + + +Maintained by: +
    +rbd@cs.cmu.edu
    + + + diff --git a/misc/cmu/new.html b/misc/cmu/new.html new file mode 100644 index 0000000..0f45795 --- /dev/null +++ b/misc/cmu/new.html @@ -0,0 +1,189 @@ + + + + + + The Computer Music Project Software + + + +

    +The Computer Music Project Software

    + +

    + PortMusic

    +Information about PortMusic +

    +Aura

    +Aura is not available for general distribution, but you can read +about Aura here. Send mail to Roger +Dannenberg to get a copy of work in progress. +

    + Nyquist

    +Nyquist is a sound synthesis and composition language based on a Lisp syntax. +Nyquist is an elegant and powerful system based on functional programming. +

    +Documentation

    + + + +

    +Executables (v2.29)

    + + + +

    +Source

    + + + +

    +Version 2.14 (older, but more tested than the latest release)

    + + +If you have problems getting Nyquist, please contact Roger Dannenberg (rbd@cs.cmu.edu).  +

    +CMU MIDI Toolkit

    +The CMU Midi Toolkit (CMT) is a collection of software for writing interactive +MIDI software in C. CMT includes a number of handy utilities allong with +an application "shell" that provides timing, scheduling, and MIDI interfaces +that are portable across DOS, Mac, SGI, and Amiga platforms. +

    CMT is distributed by the CMU School of Computer Science. For $30 to +cover our costs, we will send you 3.5" DS/DD disks (including executables +and source code) and an 100 page manual. Please indicate your machine type. +Checks should be payable to Carnegie Mellon University, and correspondence +should be addressed to Roger Dannenberg, School of Computer Science, Carnegie +Mellon University, Pittsburgh, PA 15213 USA. +

    CMT runs on the following systems: +

      Macintosh (requires Apple MIDI Manager), +

      DOS (requires MPU-401 compatible MIDI interface), and +

      Amiga (requires Commodore CAMD drivers),

    +using the following compilers: Think C v5, Borland C++ v3, Turbo C++ for +DOS v3, Microsoft C v7, Quick C v2.5, Lattice C v5 (Amiga), and Aztec C +v5 (Amiga). (Amiga code is retained in the release but is no longer supported.) +

    +Documentation

    + + + +

    +Executables

    + + + +

    +Source

    + + +Maintained by: +
    +rbd@cs.cmu.edu
    + + + diff --git a/misc/cmu/nyqide_setup.sgp b/misc/cmu/nyqide_setup.sgp new file mode 100644 index 0000000..7070fa0 Binary files /dev/null and b/misc/cmu/nyqide_setup.sgp differ diff --git a/misc/cmu/nyquist_setup.sgp b/misc/cmu/nyquist_setup.sgp new file mode 100644 index 0000000..d72c3ec Binary files /dev/null and b/misc/cmu/nyquist_setup.sgp differ diff --git a/misc/cmu/nyqwin_setup.sgp b/misc/cmu/nyqwin_setup.sgp new file mode 100644 index 0000000..f61c971 Binary files /dev/null and b/misc/cmu/nyqwin_setup.sgp differ diff --git a/misc/cmu/restore.bat b/misc/cmu/restore.bat new file mode 100644 index 0000000..41bbc24 --- /dev/null +++ b/misc/cmu/restore.bat @@ -0,0 +1,17 @@ +rem restore what cleanup.bat did + +cd ..\.. +move ..\nyquist-backup\idesetup idesetup +move ..\nyquist-backup\winsetup winsetup +move ..\nyquist-backup\setup setup +move ..\nyquist-backup\NyqWinDebug NyqWinDebug +move ..\nyquist-backup\NyqWinRel NyqWinRel +move ..\nyquist-backup\WinDebug WinDebug +move ..\nyquist-backup\WinRel WinRel +move ..\nyquist-backup\portaudio_test portaudio_test +move ..\nyquist-backup\jones jones +move ..\nyquist-backup\sjlib_103_DOS.tgz sjlib_103_DOS.tgz +move ..\nyquist-backup\sjlib_DOS_104.tgz sjlib_DOS_104.tgz +move ..\nyquist-backup\plight demos\plight +move ..\nyquist-backup\nyqide nyqide +cd misc\cmu diff --git a/misc/convert.c b/misc/convert.c new file mode 100644 index 0000000..a242acd --- /dev/null +++ b/misc/convert.c @@ -0,0 +1,59 @@ +/* convert.c -- convert between file name notations */ + + +#include "switches.h" +#include "stdio.h" +#include "string.h" +#include "convert.h" + +char dir_separator = +#ifdef MACINTOSH +':'; +#endif +#ifdef DOS +'\\'; +#endif +#ifdef UNIX +'/'; +#endif +#ifdef AMIGA +'/'; +#endif +/* Note: syntax error if not one and only one is defined (this is a feature) */ + + +int pauseflag; + + +/* convert -- convert filename to local naming conventions */ +/**/ +void convert(char *filename) +{ + int i; + /* first test for problem characters */ + for (i = strlen(filename); i >= 0; i--) { + if (filename[i] == ':' || filename[i] == '\\') { + fprintf(stderr, "WARNING: %s has one of \":\\\" and may not port.\n", + filename); + fprintf(stderr, " '/' should be used as directory separator.\n"); + if (PAUSE) getchar(); + } + } +#ifdef MACINTOSH + /* prepend a ":" */ + for (i = strlen(filename); i >= 0; i--) { + filename[i + 1] = filename[i]; + } + filename[0] = ':'; +#endif +#ifndef UNIX +#ifndef AMIGA + /* replace '/' with local separator */ + for (i = strlen(filename); i >= 0; i--) { + if (filename[i] == '/') filename[i] = dir_separator; + } +#endif +#endif +} + + diff --git a/misc/convert.h b/misc/convert.h new file mode 100644 index 0000000..3c74cdc --- /dev/null +++ b/misc/convert.h @@ -0,0 +1,7 @@ +/* convert.h -- convert from packer internal filenames to local OS */ + +void convert(char *filename); + +extern int pauseflag; +#define PAUSE pauseflag + diff --git a/misc/filelist.c b/misc/filelist.c new file mode 100644 index 0000000..677fbe4 --- /dev/null +++ b/misc/filelist.c @@ -0,0 +1,222 @@ +/* filelist.c -- program to convert a DOS DIR listing into an input + * file for the packer program + * + * To use the program, first run DIR *.* /s > ..\xxx + * Then run filelist.exe ..\xxx files + * to create "files" + * Then you can run packer.exe files myproject.pac + * to create the pac file. + */ + +/* usage: filelist */ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "cext.h" +#include "cmdline.h" + +#define EOS '\0' + +FILE *inf; +FILE *out; + +#ifdef MAYBE_THIS_IS_FOR_WIN95_DIRECTORY_LISTINGS +/* findfilename -- look for pattern "*-*-*:* " in string */ +/**/ +int findfilename(char *line, char *rslt) +{ + char *ptr; + if (ptr = strchr(line, '-')) { + if (ptr = strchr(ptr, '-')) { + if (ptr = strchr(ptr, ':')) { + if (ptr = strchr(ptr, ' ')) { + strcpy(rslt, ptr + 1); + if (strcmp(rslt, ".") == 0 || + strcmp(rslt, "..") == 0 || + strstr(line, "")) return 0; + return 1; + } + } + } + } + return 0; +} +#endif + +/* findfilename -- look for pattern "***:* " in string */ +/* + * NOTE: the is "/", part of the file date; ":" is in the file time + * lines without these characters are not lines that contain filenames + */ +int findfilename(char *line, char *rslt) +{ + char *ptr; + if (ptr = strchr(line, '/')) { + if (ptr = strchr(ptr + 1, '/')) { + if (ptr = strchr(ptr + 1, ':')) { + if (ptr = strrchr(line, ' ')) { + // now ptr points to space before filename + strcpy(rslt, ptr + 1); + // make sure this is not directory + if (strstr(line, "")) return 0; + return 1; + } + } + } + } + return 0; +} + + +int directory_filter(char *directory) +{ + int skip = false;; + if (strstr(directory, "WinDebug") != NULL) skip = true; + if (strstr(directory, "trash") != NULL) skip = true; + return skip; +} + +/* fixup -- convert \ to / */ +/**/ +void fixup(char *s) +{ + while (*s) { + if (*s == '\\') *s = '/'; + s++; + } +} + + +/* giveup -- quit the program */ +/**/ +void giveup() +{ + printf("Type return."); + exit(1); +} + + +/* +/* main -- */ +/**/ +int main(int argc, char **argv) +{ +#define stringmax 128 + char in_file[stringmax]; + char out_file[stringmax]; + char inline[stringmax]; + char basedir[stringmax]; + char filename[stringmax]; + char directory[stringmax]; + char wholename[stringmax]; + char *s; + int skip_directory = false; + + basedir[0] = 0; /* empty string */ + + cl_init(NULL, 0, NULL, 0, argv, argc); + if ((s = cl_arg(1)) != NULL) { + strcpy(in_file, s); + inf = fopen(in_file, "r"); + if (inf == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", in_file); + exit(1); + } + } + if ((s = cl_arg(2)) != NULL) { + strcpy(out_file, s); + out = fopen(out_file, "w"); + if (out == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", out_file); + exit(1); + } + } else { + fprintf(stdout, "Error: no output file specified\n"); + exit(1); + } + + printf("writing %s ...\n", out_file); + + /* read a line at a time. + * if the line has "Directory of", then + * if you don't have base directory, grab it + * otherwise search for base directory and grab remainder + * if the line matches "*-*-*:* " then + * grab remainder as filename + * prepend directory and type ("a") and output + */ + while (fgets(inline, stringmax, inf)) { + inline[strlen(inline) - 1] = EOS; /* remove newline at end */ + if (inline[0] == EOS) continue; /* skip blank lines */ + /* search for Directory */ + s = strstr(inline, "Directory of "); + if (s) { + s += strlen("Directory of "); + if (!basedir[0]) { + strcpy(basedir, s); + strcat(basedir, "\\"); /* append a slash to complete directory name */ + strcpy(directory, ""); + } else { + s = strstr(s, basedir); + if (!s) { + printf("Expected %s at beginning of directory.\n"); + printf("Input line: %s\n"); + giveup(); + } else { + strcpy(directory, s + strlen(basedir)); + fixup(directory); + strcat(directory, "/"); + } + skip_directory = directory_filter(directory); + } + } else if (!skip_directory && findfilename(inline, filename)) { + char type_of_file = 'a'; + sprintf(wholename, "%s%s", directory, filename); + /* strlwr(wholename); */ + s = strchr(wholename, '.'); + if (s) s++; + else s = ""; + if (strcmp(s, "nh") == 0 || + strcmp(s, "rsrc") == 0 || + strcmp(s, "dsp") == 0 || + strcmp(s, "dsw") == 0 || + strcmp(s, "cod") == 0 || + strcmp(s, "tab") == 0 || + strcmp(s, "pcm") == 0 || + strcmp(s, "mp3") == 0 || + strcmp(s, "mid") == 0 || + strcmp(s, "aiff") == 0 || + false) + type_of_file = 'b'; + if (strcmp(s, "pac") == 0 || + strcmp(s, "ncb") == 0 || + strcmp(s, "opt") == 0 || + strcmp(s, "plg") == 0 || + strcmp(s, "tar") == 0 || + strcmp(s, "obj") == 0 || + strcmp(s, "vcp") == 0 || + strcmp(s, "exe") == 0 || + strcmp(s, "vcp") == 0 || + strcmp(s, "pdb") == 0 || + strcmp(s, "sbr") == 0 || + strcmp(s, "ilk") == 0 || + strcmp(s, "bsc") == 0 || + /* this last one says "only .lsp files in runtime directory + (strcmp(directory, "runtime/") == 0 && strcmp(s, "lsp") != 0) || */ + strstr(directory, "CVS/") || + false + ) { + /* do nothing */ + } else { + fprintf(out, "%c %s\n", type_of_file, wholename); + } + } + } + + fclose(inf); + fclose(out); + return 0; +} + + diff --git a/misc/filelist.dsp b/misc/filelist.dsp new file mode 100644 index 0000000..566e052 --- /dev/null +++ b/misc/filelist.dsp @@ -0,0 +1,109 @@ +# Microsoft Developer Studio Project File - Name="filelist" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=filelist - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "filelist.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "filelist.mak" CFG="filelist - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "filelist - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "filelist - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "filelist - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "filelist_Release" +# PROP Intermediate_Dir "filelist_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "filelist - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "filelist_Debug" +# PROP Intermediate_Dir "filelist_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../cmt" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /D "_DEBUG" /D "DEBUG_INPUT" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "filelist - Win32 Release" +# Name "filelist - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\cmdline.c +# End Source File +# Begin Source File + +SOURCE=.\filelist.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\tran\delaycc.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/misc/filelist.vcproj b/misc/filelist.vcproj new file mode 100644 index 0000000..c3172af --- /dev/null +++ b/misc/filelist.vcproj @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/misc/intgen.c b/misc/intgen.c new file mode 100644 index 0000000..d9228a7 --- /dev/null +++ b/misc/intgen.c @@ -0,0 +1,911 @@ +/* intgen.c -- an interface generator for xlisp */ + +/* (c) Copyright Carnegie Mellon University 1991 + * For a statement of limited permission to use, see Permission.doc + * + * HISTORY + * + * 5-Jul-95 Roger Dannenberg + * strip directory prefixes from files before writing include statements + * 24-Oct-88 Roger Dannenberg at CMU + * Changed so that if C routine returns void and has result parameters, + * then result parameters are returned by the lisp subr as well as + * assigned to *RSLT*. + * + * 13-Apr-88 Roger Dannenberg at CMU + * Modified for xlisp version 2.0 + * + * 22-Dec-87 Roger Dannenberg at NeXT + * Added FILE type. + * + * 21-May-87 Dale Amon at CMU CSD + * Included use of NODE *s_true under SCORE_EDITOR conditional. Standard + * xlisp code use NODE *true instead. + * + * 13-May-87 Dale Amon at CMU CSD + * Added conditional compilation switch SCORE_EDITOR so that this + * program will work with both standard XLISP sources and with Roger's + * (ahem) modified version. Also put in error checking for case where + * user does not specifiy an output file so program will exit instead + * of coredump. + */ + + +/* Summary and Design: (NOTE THAT AN INTGEN MANUAL IS AVAILABLE) + * The first command line argument gives the name of + * the .c file to generate. All following arguments are + * .h files to read and use as interface specifications. + * + * The main program opens the output file, calls + * write_prelude, and then process_file for each input + * file. Then call write_postlude and close the file. + * + * process_file opens an input file and reads each line + * into current_line. + * if the first characters of the file are "ih", then + * the rest of the file is processed as normal, except the + * .h extension of the file is replaced by .ih before the + * filename is written into an include statement in the + * output file. This is done to handle ".ih" files generated + * by the Andrew Toolkit Class processor. + * In any case, the first line of EVERY .h file is discarded. + * If #define is found, save the following identifier as + * macro_name. + * If "LISP:" is found, then see if it is preceded by one + * or two identifiers and an open paren. + * If yes, call routine_call, + * else call macro_call. + * + * routine_call gets the first one or two identifiers off the + * line into type_name and routine_name. If there is just one id, + * assign it to routine_name and make type_name = "void". + * If the routine_name starts with *, remove the * from + * routine_name and append "*" to type_name. + * Call write_interface with type_name, routine_name, and location + * of parameter type description after "LISP:". + * + * macro_call gets a type_name from the input line after + * "LISP:". + * Then call write_interface with type_name, macro_name, and + * location of parameter type description. + * + * lisp function names are saved in a table, and an + * initialization routine is written to install the new + * SUBRs into the xlisp symbol table, as well as to lookup + * RSLT_sym, the atom on which results are placed + * + * + */ + +/* Turn on special handling for Roger's Score Editor if the following #define + * is uncommented: + */ +/* #define SCORE_EDITOR */ + +/* Turn on special handling for Chris's Sound Editor if the following #define + * is uncommented: + */ +/* #define SOUND_EDITOR */ + +/* Turn on special handling for Nyquist if the following #define + * is uncommented: + */ +#define NYQUIST + +/* atom 't is named s_true if this is defined, o.w. named true: */ +#define S_TRUE 1 + +/* Turn on special handling for CMU MIDI Toolkit seq_type: + */ +#define SEQ_TYPE + +#define errfile stdout + +#define ident_max 100 +#define line_max 200 +#define subr_max 500 + +/* prefix for include files not to be included in interface module */ +#define no_include_prefix '~' + +#define false 0 +#define true 1 + +#include "switches.h" +#include "stdlib.h" +#include "cext.h" +#include +#ifndef boolean +typedef int boolean; +#endif +#include "stdio.h" +#include "ctype.h" +#include "cmdline.h" +#ifdef MACINTOSH +#include "console.h" +#endif + +#ifdef MACINTOSH +#define FILESEP ':' +#else +#ifdef WINDOWS +#define FILESEP '\\' +#else +#define FILESEP '/' +#endif +#endif + +static char *sindex(); + +#define whitep(c) ((c) == ' ' || (c) == '\t') +#define symbolp(c) (isalpha(c) || (c) == '*' || (c) == '_' || (c) == '-' ||\ + (c) == ':' || isdigit(c) || (c) == '^' || (c) == '*') + +/* c and Lisp parameters are encoded in the same table. + * Field type_id is the string name of the type. + * For c types (return types of C routines), code is 'C', + * convert gives the routine for making a lisp node from + * the c datum. + * listtype_or_special is "v" for types that should be + * returned as LISP NIL (e.g. "void"), "s" for types + * that when NULL should be returned as NIL, "r" + * for normal types, and "" to raise an error. + * ctype is not used and should be NULL. + * For Lisp types (from parameter specs), code is 'L'. + * convert gives the routine that extracts a C value + * from a lisp node whose type is given by the field + * getarg_or_special. + * c_type is the type of the local C variable which is + * passed as a parameter to the C routine. + * initializer is the initial value for result only parameters + * + * End of table is marked by a NULL type_id. + * + * Location 0 is reserved to indicate errors. + * Location 1 MUST BE type ANY + * + */ + +#define any_index 1 +struct { + char *type_id; + char code; + char *convert; + char *getarg_or_special; + char *ctype; + char *makenode; + char *initializer; +} type_table[] = { + {" ", ' ', NULL, NULL, NULL, NULL, NULL}, + {"ANY", 'L', "", "", "LVAL", "", "NIL"}, + {"ATOM", 'L', "", "xlgasymbol", "LVAL", "", "NIL"}, + {"FILE", 'L', "getfile", "xlgastream", "FILE *", "cvfile", "NULL"}, + {"FIXNUM", 'L', "getfixnum", "xlgafixnum", "long", "cvfixnum", "0"}, + {"FIXNUM", 'L', "getfixnum", "xlgafixnum", "int", "cvfixnum", "0"}, + {"FLOAT", 'L', "getflonum", "xlgaflonum", "float", "cvflonum", "0.0"}, + {"FLONUM", 'L', "getflonum", "xlgaflonum", "double", "cvflonum", "0.0"}, + {"ANYNUM", 'L', "testarg2", "xlgaanynum", "double", "cvflonum", "0.0"}, + {"STRING", 'L', "getstring", "xlgastring", "unsigned char *", "cvstring", "NULL"}, + {"BOOLEAN", 'L', "getboolean", "xlgetarg", "int", "cvboolean", "0"}, + {"atom_type", 'C', "", "r", NULL, NULL, NULL}, + {"LVAL", 'C', "", "r", NULL, NULL, "NIL"}, + +#ifdef SOUND_EDITOR + /* Extensions for Sound Type: */ + {"SOUND", 'L', "getsound", "xlgasound", "SoundPtr", "cvsound", "NULL"}, + {"SoundPtr", 'C', "cvsound", "r", NULL, NULL, NULL}, +#endif + +#ifdef NYQUIST + {"SOUND", 'L', "getsound", "xlgasound", "sound_type", "cvsound", "NULL"}, + {"sound_type", 'C', "cvsound", "r", NULL, NULL, NULL}, +#endif +#ifdef SEQ_TYPE + {"SEQ", 'L', "getseq", "xlgaseq", "seq_type", "cvseq", "NULL"}, + {"seq_type", 'C', "cvseq", "r", NULL, NULL, NULL}, +/* look out! event_type is treated as void to eliminate + * warning messages ... */ + {"event_type", 'C', "", "v", NULL, NULL, NULL}, +#endif +#ifdef SCORE_EDITOR + {"VALUE", 'L', "getval", "xlgaval", "value_type", "cvval", "NULL"}, + {"value_type", 'C', "cvval", "r", NULL, NULL, NULL}, + {"EVENT", 'L', "getevent", "xlgaevent", "event_type", "cvevent", "NULL"}, + {"event_type", 'C', "cvevent", "r", NULL, NULL, NULL}, + {"score_type", 'C', "cvevent", "r", NULL, NULL, NULL}, +#endif +#ifdef DMA_EXTENSIONS + /* begin DMA entries */ + {"DEXT", 'L', "getdext", "xlgadext", "ext_type", "cvdext", "NULL"}, + {"DEXT", 'C', "cvdext", "r", NULL, NULL, NULL}, + {"SEXT", 'L', "getsext", "xlgasext", "ext_type", "cvsext", "NULL"}, + {"SEXT", 'C', "cvsext", "r", NULL, NULL, NULL}, + /* end DMA entries */ +#endif + {"int", 'C', "cvfixnum", "r", NULL, NULL, NULL}, + {"long", 'C', "cvfixnum", "r", NULL, NULL, NULL}, + {"boolean", 'C', "cvboolean", "r", NULL, NULL, NULL}, + {"float", 'C', "cvflonum", "r", NULL, NULL, NULL}, + {"double", 'C', "cvflonum", "r", NULL, NULL, NULL}, + {"string", 'C', "cvstring", "s", NULL, NULL, NULL}, + {"char*", 'C', "cvstring", "s", NULL, NULL, NULL}, + {"char", 'C', "cvfixnum", "r", NULL, NULL, NULL}, + {"string_type", 'C', "cvstring", "s", NULL, NULL, NULL}, + {"FILE*", 'C', "cvfile", "s", NULL, NULL, NULL}, + {"void", 'C', "", "v", NULL, NULL, NULL}, +/*eot*/ {NULL, ' ', NULL, NULL, NULL, NULL, NULL}}; + +/* subr names get saved here: */ +char *subr_table[subr_max]; +int subr_table_x; + +#define get_c_special(i) type_table[(i)].getarg_or_special[0] +#define get_c_conversion(i) type_table[(i)].convert +#define get_lisp_extract(i) type_table[(i)].convert +#define get_lisp_getarg(i) type_table[(i)].getarg_or_special +#define get_lisp_ctype(i) type_table[(i)].ctype +#define get_lisp_makenode(i) type_table[(i)].makenode +#define get_lisp_initializer(i) type_table[(i)].initializer + +static void lisp_code(); +static int lookup(); +static void process_file(); +static void routine_call(); +static void write_interface(); +static void write_postlude(); +static void write_prelude(); +static void write_ptrfile(); + +char source_file[ident_max]; /* source file */ +char current_line[4 * line_max]; /* current line in source file */ +char out_file[ident_max]; /* output file name */ +char ptr_file[ident_max]; /* ptr.h file name */ +char def_file[ident_max]; /* def.h file name */ + +FILE *lispout = NULL; /* output for lisp source code (if any) */ + +#define EOS '\000' + +/* getarg -- get an identifier from a string */ +/**/ +int getarg(start, result, pos) + char *start; /* where to start scanning */ + char *result; /* where to put the identifier */ + char **pos; /* ptr to char after identifier in source */ +{ + *result = EOS; + while (whitep(*start) && *start != EOS) start++; + if (*start == EOS) return false; + if (!symbolp(*start)) return false; + while (symbolp(*start) && *start != EOS) { + *result = *start; + result++; + start++; + } + *result = EOS; + *pos = start; + return true; +} + + +/* error() -- print source file and line */ +/**/ +void error() +{ + fprintf(errfile, "\n%s: |%s|\n", source_file, current_line); +} + + +/* lisp_code -- write lisp code to file */ +/* + * read from inp if necessary until close comment found + */ +static void lisp_code(inp, s) + FILE *inp; + char *s; +{ + char lisp[line_max]; + char *endcomment; + char *inputline; /* for end of file detection */ + + if (lispout == NULL) { + char lisp_file_name[ident_max]; + char *extension; + strcpy(lisp_file_name, out_file); + extension = sindex(lisp_file_name, ".c"); + strcpy(extension, ".lsp"); /* overwrite .c with .lsp */ + lispout = fopen(lisp_file_name, "w"); + if (lispout == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", lisp_file_name); + exit(1); + } + printf("writing %s ...\n", lisp_file_name); + } + + strcpy(lisp, s); /* don't modify s */ + inputline = lisp; + while (inputline != NULL && + (endcomment = sindex(lisp, "*/")) == NULL) { + fputs(lisp, lispout); + inputline = fgets(lisp, line_max, inp); + } + strcpy(endcomment, "\n\n"); + fputs(lisp, lispout); +} + + +/* lookup -- find type data */ +/**/ +static int lookup(s, t) + char *s; + char t; +{ + int i = 1; + while (type_table[i].type_id != NULL) { + if (type_table[i].code == t && + strcmp(type_table[i].type_id, s) == 0) + return i; + i++; + } + return 0; +} + +/* macro_call -- generate xlisp interface for C routine */ +/**/ +void macro_call(in, out, curline, macro_name, arg_loc) + FILE *in; /* input file */ + FILE *out; /* output file */ + char *curline; /* input line */ + char *macro_name; /* name of the macro to call */ + char *arg_loc; /* location after "LISP:" */ +{ + char type_name[ident_max]; + if (!getarg(arg_loc, type_name, &arg_loc)) { + error(); + fprintf(errfile, "no type given for macro.\n"); + } else { + write_interface(in, out, type_name, macro_name, arg_loc, true); + } +} + + + +/* main -- generate an xlisp to c interface file */ +/**/ +int main(argc, argv) + int argc; + char *argv[]; +{ + char *s; + FILE *out; + FILE *ptrfile; + FILE *deffile; + int n; + +#ifdef MACINTOSH + argc = ccommand(&argv); +#endif + + for (n = 0; n < subr_max; n++) + { + subr_table[n] = (char *) malloc(ident_max); + subr_table[n][0] = EOS; + } + subr_table_x = 0; + + cl_init(NULL, 0, NULL, 0, argv, argc); + if ((s = cl_arg(1)) != NULL) { + strcpy(out_file, s); + if (sindex(out_file, ".") == 0) + strcat(out_file, ".c"); + else fprintf(stderr, + "1st command line argument should be a legal c identifier\n"); + out = fopen(out_file, "w"); + if (out == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", out_file); + exit(1); + } + strcpy(ptr_file, s); + strcat(ptr_file, "ptrs.h"); + ptrfile = fopen(ptr_file, "w"); + if (ptrfile == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", ptr_file); + exit(1); + } + strcpy(def_file, s); + strcat(def_file, "defs.h"); + deffile = fopen(def_file, "w"); + if (deffile == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", def_file); + exit(1); + } + } else { + fprintf(stdout, "Error: no output file specified\n"); + exit(1); + } + + printf("writing %s ...\n", out_file); + + write_prelude(out, out_file); + n = 2; + while ((s = cl_arg(n)) != NULL) { + printf(" %s\n", s); + process_file(s, out); + n++; + } + write_postlude(out); + fclose(out); + write_ptrfile(ptrfile, deffile); + fclose(ptrfile); + fclose(deffile); + if (lispout != NULL) fclose(lispout); + return 0; +} + + +static void process_file(fname, out) + char *fname; + FILE *out; +{ + FILE *in; + char *cp; + char *pos; + char incl_file[ident_max]; /* name of file to include */ + char type_name[ident_max]; /* the type of the routine */ + char routine_name[ident_max]; /* the name of the routine or macro */ + char flag = fname[0]; + boolean reading_parameters = false; /* says we've got a routine, and + we're skipping over parameter declarations */ + + if (flag == no_include_prefix) fname++; + + strcpy(source_file, fname); /* for error reporting */ + in = fopen(fname, "r"); + if (in == NULL) { + fprintf(errfile, "couldn't open %s\n", fname); + /* however, we still write the file as an #include ... */ + fprintf(out, "#include \"%s\"\n\n", fname); + return; + } + + /* first check out the first line: if the first two characters are + "ih", then replace fname with file.ih so that the CLASS ".ih" + file will be included instead of this ".h" file. This is a + hack to allow calls into Andrew Tool Kit objects. + */ + + strcpy(incl_file, fname); + if (fgets(current_line, line_max, in) != NULL) { + if (current_line[0] == 'i' && current_line[1] == 'h') { + cp = sindex(incl_file, ".h"); + if (cp != NULL) { + strcpy(cp, ".ih"); + } + } + } + + /* strip off leading directory prefix, if any */ + cp = strrchr(incl_file, FILESEP); /* find the last slash */ + if (cp) { + strcpy(incl_file, cp + 1 /* skip the slash */); + } + + if (flag != no_include_prefix) fprintf(out, "#include \"%s\"\n\n", incl_file); + + while (fgets(current_line, line_max, in) != NULL) { + cp = sindex(current_line, "#define"); + if (cp != NULL) { + cp += strlen("#define"); + if (!getarg(cp, routine_name, &cp)) { + error(); + fprintf(errfile, "#define not followed by identifier\n"); + } + /* watch out for multi-line macros: */ + while (sindex(current_line, "\\\n")) { + if (fgets(current_line, line_max, in) == NULL) return; + } + } else if ((cp = sindex(current_line, "LISP:")) != NULL) { + char type_str[ident_max]; + char routine_str[ident_max]; + if (!reading_parameters && + getarg(current_line, type_str, &pos) && + getarg(pos, routine_str, &pos) && + pos < cp) { + routine_call(in, out, current_line, type_str, routine_str, + cp + strlen("LISP:")); + } else if (getarg(cp + strlen("LISP:"), type_str, &pos)) { + macro_call(in, out, current_line, routine_name, + cp + strlen("LISP:")); + } else routine_call(in, out, current_line, type_name, routine_name, + cp + strlen("LISP:")); + } else if ((cp = sindex(current_line, "LISP-SRC:")) != NULL) { + lisp_code(in, cp + strlen("LISP-SRC:")); + } else if (reading_parameters && sindex(current_line, ")")) { + reading_parameters = false; + } else if (reading_parameters) { /* skip */ ; + } else if (getarg(current_line, type_name, &pos) && + getarg(pos, routine_name, &pos)) { + /* we grabbed the type and routine name. Check to see if the + * parameter list is open but not closed on this line: */ + if (sindex(current_line, "(") && !sindex(current_line, ")")) { + reading_parameters = true; + } + /* printf("saw %s %s\n", type_name, routine_name);*/ + } else { /* wipe out names for safety: */ + type_name[0] = EOS; + routine_name[0] = EOS; + } + } + + fclose(in); +} + + +/* routine_call -- generate xlisp interface for C routine */ +/**/ +static void routine_call(in, out, curline, type_name, routine_name, arg_loc) + FILE *in; /* input file */ + FILE *out; /* output file */ + char *curline; /* input line */ + char *type_name; /* type id */ + char *routine_name; /* routine id */ + char *arg_loc; /* location after "LISP:" */ +{ + + if (*routine_name == EOS) { + routine_name = type_name; + type_name = "void"; + } + if (*routine_name == '*') { + char *r = routine_name; + while (*r != EOS) { /* shift left */ + *r = *(r+1); + r++; + } + strcat(type_name, "*"); + } + write_interface(in, out, type_name, routine_name, arg_loc, false); +} + + +/* sindex -- find substring */ +/**/ +static char *sindex(sup, sub) + char *sup; /* the containing string */ + char *sub; /* the substring */ +{ + int i; + for ( ; *sup != EOS; sup++) { + for (i = 0; true; i++) { + if (*(sub+i) == EOS) return sup; + if (*(sup+i) != *(sub+i)) break; + } + } + return EOS; +} + + +/* write_interface -- write SUBR for xlisp */ +/* + * NOTE: if is_macro and there are no arguments, then + * do not write parens: e.g. "foo" instead of "foo()" + */ +static void write_interface(in, out, type_name, fn_name, arg_loc, is_macro) + FILE *in; /* input file */ + FILE *out; /* output file */ + char *type_name; /* c type for return value */ + char *fn_name; /* c function to be called */ + char *arg_loc; /* LISP arg type are described here */ + int is_macro; /* true if this is a macro */ +{ + char lispfn[ident_max]; /* lisp fn name */ + char *cp; /* a temporary */ + int len; /* a string length */ +#define args_max 20 + struct { + int index; /* table location for this type */ + int res_flag; /* is a result returned? */ + } args[args_max]; + char arg_type[ident_max]; /* the original type spec */ + char *c_type; /* c type for an argument */ + char *c_str; /* temp for a c code line */ + int argcnt = 0; /* counts arguments */ + int i; /* argument index */ + int result_flag = false; /* true if there are result parameters */ + int result_x; /* index of result type */ + char newline[line_max]; /* place to read continuation lines */ + + +/* printf("write_interface: %s %s %s", type_name, fn_name, arg_loc);*/ + if (*type_name == EOS || *fn_name == EOS) { + error(); + fprintf(errfile, "Error: bad syntax, maybe missing type\n"); + return; + } + + while (*arg_loc != '(' && *arg_loc != EOS) arg_loc++; + if (*arg_loc == EOS) { + error(); + fprintf(errfile, "Error: '(' expected after 'LISP:'\n"); + return; + } else arg_loc++; + if (!getarg(arg_loc, lispfn, &arg_loc)) { + error(); + fprintf(stdout, "Error: lisp function name expected\n"); + return; + } + /* make it upper case: */ + for (cp = lispfn; *cp != EOS; cp++) { + if (islower(*cp)) *cp = toupper(*cp); + } + + /* save SUBR name */ + strcpy(subr_table[subr_table_x], lispfn); + subr_table_x++; + + /* make lispfn lower case, dash, colon -> underscore: */ + for (cp = lispfn; *cp != EOS; cp++) { + if (isupper(*cp)) *cp = tolower(*cp); + if (*cp == '-' || *cp == ':') *cp = '_'; + } + + /* append continuation lines to arg_loc to handle multi-line specs */ + while (sindex(arg_loc, "*/") == NULL) { + /* remove newline */ + if (strlen(arg_loc) > 0) + arg_loc[strlen(arg_loc) - 1] = EOS; + if (fgets(newline, line_max, in) == NULL) { + error(); + fprintf(stdout, "Error: end of file unexpected\n"); + exit(1); + } + if ((strlen(arg_loc) + strlen(newline)) > (3 * line_max)) { + error(); + fprintf(stdout, + "Error: specification too long or missing end of comment.\n"); + exit(1); + } + strcat(arg_loc, newline); + } + + fprintf(out, "/%c xlc_%s -- interface to C routine %s */\n/**/\n", + '*', lispfn, fn_name); + + fprintf(out, "LVAL xlc_%s(void)\n{\n", lispfn); + while (getarg(arg_loc, arg_type, &arg_loc)) { + int result_only_flag = false; + + if (argcnt >= args_max) { + error(); + fprintf(errfile, + "Internal error: too many args, increase args_max\n"); + } + len = strlen(arg_type); + if (arg_type[len-1] == '*') { + arg_type[len-1] = EOS; + args[argcnt].res_flag = true; + result_flag = true; + } else if (arg_type[len-1] == '^') { + arg_type[len-1] = EOS; + args[argcnt].res_flag = true; + result_flag = true; + result_only_flag = true; + } else args[argcnt].res_flag = false; + + args[argcnt].index = lookup(arg_type, 'L'); + c_type = get_lisp_ctype(args[argcnt].index); + + if (c_type == NULL) { + error(); + fprintf(errfile, "Error: %s undefined, using int.\n", + arg_type); + c_type = "int"; + args[argcnt].index = lookup("FIXNUM", 'L'); + } + fprintf(out, " %s arg%d = ", c_type, argcnt+1); + if (result_only_flag) { + fprintf(out, "%s;\n", + get_lisp_initializer(args[argcnt].index)); + } else if (args[argcnt].index == any_index) { + fprintf(out, "xlgetarg();\n"); + } else { + c_str = "%s(%s());\n"; + fprintf(out,c_str, + get_lisp_extract(args[argcnt].index), + get_lisp_getarg(args[argcnt].index)); + } + argcnt++; + } + + if (*arg_loc != ')') { + fprintf(errfile, + "Warning: paren expected immediately after last arg of %s\n", + lispfn); + } + + /* check for close paren and close comment: */ + cp = sindex(arg_loc, ")"); + if (cp == NULL || sindex(cp+1, "*/") == NULL) { + error(); + fprintf(errfile, "Warning: close paren and close comment expected\n"); + } + + /* lookup result type */ + result_x = lookup(type_name, 'C'); + if (result_x == 0) { + fprintf(errfile, "(Warning) unknown type: %s, assuming void\n", + type_name); + result_x = lookup("void", 'C'); + } + + /* if there are result parameters then return them rather than NIL + * when the type is void + */ + if (get_c_special(result_x) == 'v' && result_flag) { + fprintf(out, " LVAL result;\n"); + } + + if (get_c_special(result_x) != 'v') { + /* declare result: */ + fprintf(out, " %s result;\n", type_name); + } + + /* check for end of argument list: */ + fprintf(out, "\n xllastarg();\n"); + + /* if there are results, we'll call cons, so + * protect the result from garbage collection + * if necessary + */ + if (result_flag && strcmp(type_name, "LVAL") == 0) { + fprintf(out, " xlprot1(result);\n"); + } + + /* call the c routine */ + if (get_c_special(result_x) != 'v') { + fprintf(out, " result = "); + } else fprintf(out, " "); + fprintf(out, "%s", fn_name); + if (!is_macro || argcnt > 0) fprintf(out, "("); + + /* pass arguments: */ + for (i = 0; i < argcnt; i++) { + if (i > 0) fprintf(out, ", "); + if (args[i].res_flag) fprintf(out, "&"); + fprintf(out, "arg%d", i+1); + } + if (!is_macro || argcnt > 0) fprintf(out, ")"); + fprintf(out, ";\n"); + + /* put results (if any) on *RSLT* */ + if (result_flag) { + int wrote_one_flag = false; + fprintf(out, " {\tLVAL *next = &getvalue(RSLT_sym);\n"); + for (i = 0; i < argcnt; i++) { + if (args[i].res_flag) { + if (wrote_one_flag) + fprintf(out, "\tnext = &cdr(*next);\n"); + wrote_one_flag = true; + fprintf(out, "\t*next = cons(NIL, NIL);\n"); + fprintf(out, "\tcar(*next) = %s(arg%d);", + get_lisp_makenode(args[i].index), i+1); + } + } + fprintf(out, "\n }\n"); + + /* copy *RSLT* to result if appropriate */ + if (get_c_special(result_x) == 'v') { + fprintf(out, " result = getvalue(RSLT_sym);\n"); + } + } + + + /* generate xlpop() if there was an xlprot1() */ + if (result_flag && strcmp(type_name, "LVAL") == 0) { + fprintf(out, " xlpop();\n"); + } + + + /* now return actual return value */ + if (get_c_special(result_x) == EOS) { + error(); + fprintf(errfile, "Warning: unknown type from C, coercing to int.\n"); + fprintf(out, " return cvfixnum((int) result);\n"); + } else if (get_c_special(result_x) == 'v' && !result_flag) { + fprintf(out, " return NIL;\n"); + } else if (get_c_special(result_x) == 'v' && result_flag) { + fprintf(out, " return result;\n"); + } else if (get_c_special(result_x) == 's') { + fprintf(out, " if (result == NULL) return NIL;\n"); + fprintf(out, " else return %s(result);\n", + get_c_conversion(result_x)); + } else { + fprintf(out, " return %s(result);\n", + get_c_conversion(result_x)); + } + fprintf(out, "}\n\n\n"); +} + + +/* write_postlude -- write stuff at end of file */ +/**/ +static void write_postlude(out) + FILE *out; +{ + /* nothing to do for version 2 */ +} + + +/* write_ptrfile -- write function definition table */ +/**/ +static void write_ptrfile(pf, df) + FILE *pf; + FILE *df; +{ + int n; + char *cp; + char cname[ident_max]; + + for (n = 0; n < subr_table_x; n++) { + strcpy(cname, subr_table[n]); + /* make cname lower case, dash,colon -> underscore: */ + for (cp = cname; *cp != EOS; cp++) { + if (isupper(*cp)) *cp = tolower(*cp); + if (*cp == '-' || *cp == ':') *cp = '_'; + } + fprintf(df, "extern LVAL xlc_%s(void);\n", cname); + fprintf(pf, " { \"%s\", S, xlc_%s}, \n", subr_table[n], cname); + } + printf(" Add %s to localdefs.h and add %s to localptrs.h\n", + def_file, ptr_file); +} + + +/* write_prelude -- write stuff at head of file */ +/**/ +static void write_prelude(out, out_file) + FILE *out; + char *out_file; +{ + int i = 2; + int col = strlen(out_file) + 21; + char *s; + fprintf(out, "/%c %s -- interface to ", + '*', out_file); + while ((s = cl_arg(i)) != NULL) { + if (i > 2) { + fprintf(out, ", "); + col += 2; + } + col += strlen(s) + 2; + if (col > 65) { + fprintf(out, "\n * "); + col = 4 + strlen(s) + 2; + } + fprintf(out, "%s", s); + i++; + } + fprintf(out, " */\n\n%cifndef mips\n%cinclude \"stdlib.h\"\n", '#', '#'); + fprintf(out, "%cendif\n%cinclude \"xlisp.h\"\n\n", '#', '#'); +#ifdef S_TRUE + fprintf(out, "extern LVAL s_true;\n"); + fprintf(out, "%cdefine cvboolean(i) ((i) ? s_true : NIL)\n", '#'); +#else + fprintf(out, "extern LVAL true;\n"); + fprintf(out, "%cdefine cvboolean(i) ((i) ? true : NIL)\n", '#'); +#endif + + fprintf(out, "%c%s\n", + '#', + "define testarg2(e) (moreargs() ? (e) : (getflonum(xltoofew())))"); + + fprintf(out, "%c%s\n%s\n%s\n", + '#', + "define xlgaanynum() (floatp(*xlargv) ? getflonum(nextarg()) : \\", + " (fixp(*xlargv) ? (double) getfixnum(nextarg()) : \\", +/* note: getflonum never gets called here, but this makes typechecking happy */ + " getflonum(xlbadtype(*xlargv))))"); + + fprintf(out, "%cdefine getboolean(lval) ((lval) != NIL)\n\n", '#'); + fprintf(out, "extern LVAL RSLT_sym;\n\n\n"); +} diff --git a/misc/intgen2.c b/misc/intgen2.c new file mode 100644 index 0000000..f462815 --- /dev/null +++ b/misc/intgen2.c @@ -0,0 +1,910 @@ +/* intgen.c -- an interface generator for xlisp */ + +/* (c) Copyright Carnegie Mellon University 1991 + * For a statement of limited permission to use, see Permission.doc + * + * HISTORY + * + * 5-Jul-95 Roger Dannenberg + * strip directory prefixes from files before writing include statements + * 24-Oct-88 Roger Dannenberg at CMU + * Changed so that if C routine returns void and has result parameters, + * then result parameters are returned by the lisp subr as well as + * assigned to *RSLT*. + * + * 13-Apr-88 Roger Dannenberg at CMU + * Modified for xlisp version 2.0 + * + * 22-Dec-87 Roger Dannenberg at NeXT + * Added FILE type. + * + * 21-May-87 Dale Amon at CMU CSD + * Included use of NODE *s_true under SCORE_EDITOR conditional. Standard + * xlisp code use NODE *true instead. + * + * 13-May-87 Dale Amon at CMU CSD + * Added conditional compilation switch SCORE_EDITOR so that this + * program will work with both standard XLISP sources and with Roger's + * (ahem) modified version. Also put in error checking for case where + * user does not specifiy an output file so program will exit instead + * of coredump. + */ + + +/* Summary and Design: (NOTE THAT AN INTGEN MANUAL IS AVAILABLE) + * The first command line argument gives the name of + * the .c file to generate. All following arguments are + * .h files to read and use as interface specifications. + * + * The main program opens the output file, calls + * write_prelude, and then process_file for each input + * file. Then call write_postlude and close the file. + * + * process_file opens an input file and reads each line + * into current_line. + * if the first characters of the file are "ih", then + * the rest of the file is processed as normal, except the + * .h extension of the file is replaced by .ih before the + * filename is written into an include statement in the + * output file. This is done to handle ".ih" files generated + * by the Andrew Toolkit Class processor. + * In any case, the first line of EVERY .h file is discarded. + * If #define is found, save the following identifier as + * macro_name. + * If "LISP:" is found, then see if it is preceded by one + * or two identifiers and an open paren. + * If yes, call routine_call, + * else call macro_call. + * + * routine_call gets the first one or two identifiers off the + * line into type_name and routine_name. If there is just one id, + * assign it to routine_name and make type_name = "void". + * If the routine_name starts with *, remove the * from + * routine_name and append "*" to type_name. + * Call write_interface with type_name, routine_name, and location + * of parameter type description after "LISP:". + * + * macro_call gets a type_name from the input line after + * "LISP:". + * Then call write_interface with type_name, macro_name, and + * location of parameter type description. + * + * lisp function names are saved in a table, and an + * initialization routine is written to install the new + * SUBRs into the xlisp symbol table, as well as to lookup + * RSLT_sym, the atom on which results are placed + * + * + */ + +/* Turn on special handling for Roger's Score Editor if the following #define + * is uncommented: + */ +/* #define SCORE_EDITOR */ + +/* Turn on special handling for Chris's Sound Editor if the following #define + * is uncommented: + */ +/* #define SOUND_EDITOR */ + +/* Turn on special handling for Nyquist if the following #define + * is uncommented: + */ +#define NYQUIST + +/* atom 't is named s_true if this is defined, o.w. named true: */ +#define S_TRUE 1 + +/* Turn on special handling for CMU MIDI Toolkit seq_type: + */ +#define SEQ_TYPE + +#define errfile stdout + +#define ident_max 100 +#define line_max 200 +#define subr_max 500 + +/* prefix for include files not to be included in interface module */ +#define no_include_prefix '~' + +#define false 0 +#define true 1 + +#include "stdlib.h" +#include "switches.h" +#include "cext.h" +#include +#ifndef boolean +typedef int boolean; +#endif +#include "stdio.h" +#include "ctype.h" +#include "cmdline.h" +#ifdef MACINTOSH +#include "console.h" +#endif + +#ifdef MACINTOSH +#define FILESEP ':' +#else +#ifdef WINDOWS +#define FILESEP '\\' +#else +#define FILESEP '/' +#endif +#endif + +static char *sindex(); + +#define whitep(c) ((c) == ' ' || (c) == '\t') +#define symbolp(c) (isalpha(c) || (c) == '*' || (c) == '_' || (c) == '-' ||\ + (c) == ':' || isdigit(c) || (c) == '^' || (c) == '*') + +/* c and Lisp parameters are encoded in the same table. + * Field type_id is the string name of the type. + * For c types (return types of C routines), code is 'C', + * convert gives the routine for making a lisp node from + * the c datum. + * listtype_or_special is "v" for types that should be + * returned as LISP NIL (e.g. "void"), "s" for types + * that when NULL should be returned as NIL, "r" + * for normal types, and "" to raise an error. + * ctype is not used and should be NULL. + * For Lisp types (from parameter specs), code is 'L'. + * convert gives the routine that extracts a C value + * from a lisp node whose type is given by the field + * getarg_or_special. + * c_type is the type of the local C variable which is + * passed as a parameter to the C routine. + * initializer is the initial value for result only parameters + * + * End of table is marked by a NULL type_id. + * + * Location 0 is reserved to indicate errors. + * Location 1 MUST BE type ANY + * + */ + +#define any_index 1 +struct { + char *type_id; + char code; + char *convert; + char *getarg_or_special; + char *ctype; + char *makenode; + char *initializer; +} type_table[] = { + {" ", ' ', NULL, NULL, NULL, NULL, NULL}, + {"ANY", 'L', "", "", "LVAL", "", "NIL"}, + {"ATOM", 'L', "", "xlgasymbol", "LVAL", "", "NIL"}, + {"FILE", 'L', "getfile", "xlgastream", "FILE *", "cvfile", "NULL"}, + {"FIXNUM", 'L', "getfixnum", "xlgafixnum", "long", "cvfixnum", "0"}, + {"FIXNUM", 'L', "getfixnum", "xlgafixnum", "int", "cvfixnum", "0"}, + {"FLOAT", 'L', "getflonum", "xlgaflonum", "float", "cvflonum", "0.0"}, + {"FLONUM", 'L', "getflonum", "xlgaflonum", "double", "cvflonum", "0.0"}, + {"ANYNUM", 'L', "testarg2", "xlgaanynum", "double", "cvflonum", "0.0"}, + {"STRING", 'L', "getstring", "xlgastring", "unsigned char *", "cvstring", "NULL"}, + {"BOOLEAN", 'L', "getboolean", "xlgetarg", "int", "cvboolean", "0"}, + {"atom_type", 'C', "", "r", NULL, NULL, NULL}, + {"LVAL", 'C', "", "r", NULL, NULL, "NIL"}, + +#ifdef SOUND_EDITOR + /* Extensions for Sound Type: */ + {"SOUND", 'L', "getsound", "xlgasound", "SoundPtr", "cvsound", "NULL"}, + {"SoundPtr", 'C', "cvsound", "r", NULL, NULL, NULL}, +#endif + +#ifdef NYQUIST + {"SOUND", 'L', "getsound", "xlgasound", "sound_type", "cvsound", "NULL"}, + {"sound_type", 'C', "cvsound", "r", NULL, NULL, NULL}, +#endif +#ifdef SEQ_TYPE + {"SEQ", 'L', "getseq", "xlgaseq", "seq_type", "cvseq", "NULL"}, + {"seq_type", 'C', "cvseq", "r", NULL, NULL, NULL}, +#endif +#ifdef SCORE_EDITOR + {"VALUE", 'L', "getval", "xlgaval", "value_type", "cvval", "NULL"}, + {"value_type", 'C', "cvval", "r", NULL, NULL, NULL}, + {"EVENT", 'L', "getevent", "xlgaevent", "event_type", "cvevent", "NULL"}, + {"event_type", 'C', "cvevent", "r", NULL, NULL, NULL}, + {"score_type", 'C', "cvevent", "r", NULL, NULL, NULL}, +#endif +#ifdef DMA_EXTENSIONS + /* begin DMA entries */ + {"DEXT", 'L', "getdext", "xlgadext", "ext_type", "cvdext", "NULL"}, + {"DEXT", 'C', "cvdext", "r", NULL, NULL, NULL}, + {"SEXT", 'L', "getsext", "xlgasext", "ext_type", "cvsext", "NULL"}, + {"SEXT", 'C', "cvsext", "r", NULL, NULL, NULL}, + /* end DMA entries */ +#endif + {"int", 'C', "cvfixnum", "r", NULL, NULL, NULL}, + {"long", 'C', "cvfixnum", "r", NULL, NULL, NULL}, + {"boolean", 'C', "cvboolean", "r", NULL, NULL, NULL}, + {"float", 'C', "cvflonum", "r", NULL, NULL, NULL}, + {"double", 'C', "cvflonum", "r", NULL, NULL, NULL}, + {"string", 'C', "cvstring", "s", NULL, NULL, NULL}, + {"char*", 'C', "cvstring", "s", NULL, NULL, NULL}, + {"char", 'C', "cvfixnum", "r", NULL, NULL, NULL}, + {"string_type", 'C', "cvstring", "s", NULL, NULL, NULL}, + {"FILE*", 'C', "cvfile", "s", NULL, NULL, NULL}, + {"void", 'C', "", "v", NULL, NULL, NULL}, +/*eot*/ {NULL, ' ', NULL, NULL, NULL, NULL, NULL}}; + +/* subr names get saved here: */ +char *subr_table[subr_max]; +int subr_table_x; + +#define get_c_special(i) type_table[(i)].getarg_or_special[0] +#define get_c_conversion(i) type_table[(i)].convert +#define get_lisp_extract(i) type_table[(i)].convert +#define get_lisp_getarg(i) type_table[(i)].getarg_or_special +#define get_lisp_ctype(i) type_table[(i)].ctype +#define get_lisp_makenode(i) type_table[(i)].makenode +#define get_lisp_initializer(i) type_table[(i)].initializer + +static void lisp_code(); +static int lookup(); +static void process_file(); +static void routine_call(); +static void write_interface(); +static void write_postlude(); +static void write_prelude(); +static void write_ptrfile(); + +char source_file[ident_max]; /* source file */ +char current_line[4 * line_max]; /* current line in source file */ +char out_file[ident_max]; /* output file name */ +char ptr_file[ident_max]; /* ptr.h file name */ +char def_file[ident_max]; /* def.h file name */ + +FILE *lispout = NULL; /* output for lisp source code (if any) */ + +#define EOS '\000' + +/* getarg -- get an identifier from a string */ +/**/ +int getarg(start, result, pos) + char *start; /* where to start scanning */ + char *result; /* where to put the identifier */ + char **pos; /* ptr to char after identifier in source */ +{ + char *save = result; + *result = EOS; + while (whitep(*start) && *start != EOS) start++; + if (*start == EOS) return false; + if (!symbolp(*start)) return false; + + while (symbolp(*start) && *start != EOS) { + *result = *start; + result++; + start++; + } + *result = EOS; + *pos = start; + printf("getarg got %s\n", save); + return true; +} + + +/* error() -- print source file and line */ +/**/ +error() +{ + fprintf(errfile, "\n%s: |%s|\n", source_file, current_line); +} + + +/* lisp_code -- write lisp code to file */ +/* + * read from inp if necessary until close comment found + */ +static void lisp_code(inp, s) + FILE *inp; + char *s; +{ + char lisp[line_max]; + char *endcomment; + char *inputline; /* for end of file detection */ + + if (lispout == NULL) { + char lisp_file_name[ident_max]; + char *extension; + strcpy(lisp_file_name, out_file); + extension = sindex(lisp_file_name, ".c"); + strcpy(extension, ".lsp"); /* overwrite .c with .lsp */ + lispout = fopen(lisp_file_name, "w"); + if (lispout == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", lisp_file_name); + exit(1); + } + printf("writing %s ...\n", lisp_file_name); + } + + strcpy(lisp, s); /* don't modify s */ + inputline = lisp; + while (inputline != NULL && + (endcomment = sindex(lisp, "*/")) == NULL) { + fputs(lisp, lispout); + inputline = fgets(lisp, line_max, inp); + } + strcpy(endcomment, "\n\n"); + fputs(lisp, lispout); +} + + +/* lookup -- find type data */ +/**/ +static int lookup(s, t) + char *s; + char t; +{ + int i = 1; + while (type_table[i].type_id != NULL) { + if (type_table[i].code == t && + strcmp(type_table[i].type_id, s) == 0) + return i; + i++; + } + return 0; +} + +/* macro_call -- generate xlisp interface for C routine */ +/**/ +void macro_call(in, out, curline, macro_name, arg_loc) + FILE *in; /* input file */ + FILE *out; /* output file */ + char *curline; /* input line */ + char *macro_name; /* name of the macro to call */ + char *arg_loc; /* location after "LISP:" */ +{ + char type_name[ident_max]; + if (!getarg(arg_loc, type_name, &arg_loc)) { + error(); + fprintf(errfile, "no type given for macro.\n"); + } else { + write_interface(in, out, type_name, macro_name, arg_loc, true); + } +} + + + +/* main -- generate an xlisp to c interface file */ +/**/ +int main(argc, argv) + int argc; + char *argv[]; +{ + char *s; + FILE *out; + FILE *ptrfile; + FILE *deffile; + int n; + +#ifdef MACINTOSH + argc = ccommand(&argv); +#endif + + for (n = 0; n < subr_max; n++) + { + subr_table[n] = (char *) malloc(ident_max); + subr_table[n][0] = EOS; + } + subr_table_x = 0; + + cl_init(NULL, 0, NULL, 0, argv, argc); + if ((s = cl_arg(1)) != NULL) { + strcpy(out_file, s); + if (sindex(out_file, ".") == 0) + strcat(out_file, ".c"); + else fprintf(stderr, + "1st command line argument should be a legal c identifier\n"); + out = fopen(out_file, "w"); + if (out == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", out_file); + exit(1); + } + strcpy(ptr_file, s); + strcat(ptr_file, "ptrs.h"); + ptrfile = fopen(ptr_file, "w"); + if (ptrfile == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", ptr_file); + exit(1); + } + strcpy(def_file, s); + strcat(def_file, "defs.h"); + deffile = fopen(def_file, "w"); + if (deffile == NULL) { + fprintf(stdout, "Error: couldn't open %s\n", def_file); + exit(1); + } + } else { + fprintf(stdout, "Error: no output file specified\n"); + exit(1); + } + + printf("writing %s ...\n", out_file); + + write_prelude(out, out_file); + n = 2; + while ((s = cl_arg(n)) != NULL) { + printf(" %s\n", s); + process_file(s, out); + n++; + } + write_postlude(out); + fclose(out); + write_ptrfile(ptrfile, deffile); + fclose(ptrfile); + fclose(deffile); + if (lispout != NULL) fclose(lispout); + exit(0); +} + + +static void process_file(fname, out) + char *fname; + FILE *out; +{ + FILE *in; + char *cp; + char *pos; + char incl_file[ident_max]; /* name of file to include */ + char type_name[ident_max]; /* the type of the routine */ + char routine_name[ident_max]; /* the name of the routine or macro */ + char flag = fname[0]; + boolean reading_parameters = false; /* says we've got a routine, and + we're skipping over parameter declarations */ + + if (flag == no_include_prefix) fname++; + + strcpy(source_file, fname); /* for error reporting */ + in = fopen(fname, "r"); + if (in == NULL) { + fprintf(errfile, "couldn't open %s\n", fname); + return; + } + + /* first check out the first line: if the first two characters are + "ih", then replace fname with file.ih so that the CLASS ".ih" + file will be included instead of this ".h" file. This is a + hack to allow calls into Andrew Tool Kit objects. + */ + + strcpy(incl_file, fname); + if (fgets(current_line, line_max, in) != NULL) { + if (current_line[0] == 'i' && current_line[1] == 'h') { + cp = sindex(incl_file, ".h"); + if (cp != NULL) { + strcpy(cp, ".ih"); + } + } + } + + /* strip off leading directory prefix, if any */ + cp = strrchr(incl_file, FILESEP); /* find the last slash */ + if (cp) { + strcpy(incl_file, cp + 1 /* skip the slash */); + } + + if (flag != no_include_prefix) fprintf(out, "#include \"%s\"\n\n", incl_file); + + while (fgets(current_line, line_max, in) != NULL) { + cp = sindex(current_line, "#define"); + if (cp != NULL) { + cp += strlen("#define"); + if (!getarg(cp, routine_name, &cp)) { + error(); + fprintf(errfile, "#define not followed by identifier\n"); + } + /* watch out for multi-line macros: */ + while (sindex(current_line, "\\\n")) { + if (fgets(current_line, line_max, in) == NULL) return; + } + } else if ((cp = sindex(current_line, "LISP:")) != NULL) { + char type_str[ident_max]; + char routine_str[ident_max]; + if (!reading_parameters && + getarg(current_line, type_str, &pos) && + getarg(pos, routine_str, &pos) && + pos < cp) { + routine_call(in, out, current_line, type_str, routine_str, + cp + strlen("LISP:")); + } else if (getarg(cp + strlen("LISP:"), type_str, &pos)) { + macro_call(in, out, current_line, routine_name, + cp + strlen("LISP:")); + } else routine_call(in, out, current_line, type_name, routine_name, + cp + strlen("LISP:")); + } else if ((cp = sindex(current_line, "LISP-SRC:")) != NULL) { + lisp_code(in, cp + strlen("LISP-SRC:")); + } else if (reading_parameters && sindex(current_line, ")")) { + reading_parameters = false; + } else if (reading_parameters) { /* skip */ ; + } else if (getarg(current_line, type_name, &pos) && + getarg(pos, routine_name, &pos)) { + /* we grabbed the type and routine name. Check to see if the + * parameter list is open but not closed on this line: */ + printf("type_name %s, routine_name %s\n", type_name, routine_name); + if (sindex(current_line, "(") && !sindex(current_line, ")")) { + reading_parameters = true; + } + /* printf("saw %s %s\n", type_name, routine_name);*/ + } else { /* wipe out names for safety: */ + type_name[0] = EOS; + routine_name[0] = EOS; + } + } + + fclose(in); +} + + +/* routine_call -- generate xlisp interface for C routine */ +/**/ +static void routine_call(in, out, curline, type_name, routine_name, arg_loc) + FILE *in; /* input file */ + FILE *out; /* output file */ + char *curline; /* input line */ + char *type_name; /* type id */ + char *routine_name; /* routine id */ + char *arg_loc; /* location after "LISP:" */ +{ + + if (*routine_name == EOS) { + routine_name = type_name; + type_name = "void"; + } + if (*routine_name == '*') { + char *r = routine_name; + while (*r != EOS) { /* shift left */ + *r = *(r+1); + r++; + } + strcat(type_name, "*"); + } + write_interface(in, out, type_name, routine_name, arg_loc, false); +} + + +/* sindex -- find substring */ +/**/ +static char *sindex(sup, sub) + char *sup; /* the containing string */ + char *sub; /* the substring */ +{ + int i; + for ( ; *sup != EOS; sup++) { + for (i = 0; true; i++) { + if (*(sub+i) == EOS) return sup; + if (*(sup+i) != *(sub+i)) break; + } + } + return EOS; +} + + +/* write_interface -- write SUBR for xlisp */ +/* + * NOTE: if is_macro and there are no arguments, then + * do not write parens: e.g. "foo" instead of "foo()" + */ +static void write_interface(in, out, type_name, fn_name, arg_loc, is_macro) + FILE *in; /* input file */ + FILE *out; /* output file */ + char *type_name; /* c type for return value */ + char *fn_name; /* c function to be called */ + char *arg_loc; /* LISP arg type are described here */ + int is_macro; /* true if this is a macro */ +{ + char lispfn[ident_max]; /* lisp fn name */ + char *cp; /* a temporary */ + int len; /* a string length */ +#define args_max 20 + struct { + int index; /* table location for this type */ + int res_flag; /* is a result returned? */ + } args[args_max]; + char arg_type[ident_max]; /* the original type spec */ + char *c_type; /* c type for an argument */ + char *c_str; /* temp for a c code line */ + int argcnt = 0; /* counts arguments */ + int i; /* argument index */ + int result_flag = false; /* true if there are result parameters */ + int result_x; /* index of result type */ + char newline[line_max]; /* place to read continuation lines */ + + +/* printf("write_interface: %s %s %s", type_name, fn_name, arg_loc);*/ + if (*type_name == EOS || *fn_name == EOS) { + error(); + fprintf(errfile, "Error: bad syntax, maybe missing type\n"); + return; + } + + while (*arg_loc != '(' && *arg_loc != EOS) arg_loc++; + if (*arg_loc == EOS) { + error(); + fprintf(errfile, "Error: '(' expected after 'LISP:'\n"); + return; + } else arg_loc++; + if (!getarg(arg_loc, lispfn, &arg_loc)) { + error(); + fprintf(stdout, "Error: lisp function name expected\n"); + return; + } + /* make it upper case: */ + for (cp = lispfn; *cp != EOS; cp++) { + if (islower(*cp)) *cp = toupper(*cp); + } + + /* save SUBR name */ + strcpy(subr_table[subr_table_x], lispfn); + subr_table_x++; + + /* make lispfn lower case, dash, colon -> underscore: */ + for (cp = lispfn; *cp != EOS; cp++) { + if (isupper(*cp)) *cp = tolower(*cp); + if (*cp == '-' || *cp == ':') *cp = '_'; + } + + /* append continuation lines to arg_loc to handle multi-line specs */ + while (sindex(arg_loc, "*/") == NULL) { + /* remove newline */ + if (strlen(arg_loc) > 0) + arg_loc[strlen(arg_loc) - 1] = EOS; + if (fgets(newline, line_max, in) == NULL) { + error(); + fprintf(stdout, "Error: end of file unexpected\n"); + exit(1); + } + if ((strlen(arg_loc) + strlen(newline)) > (3 * line_max)) { + error(); + fprintf(stdout, + "Error: specification too long or missing end of comment.\n"); + exit(1); + } + strcat(arg_loc, newline); + } + + fprintf(out, "/%c xlc_%s -- interface to C routine %s */\n/**/\n", + '*', lispfn, fn_name); + + fprintf(out, "LVAL xlc_%s(void)\n{\n", lispfn); + while (getarg(arg_loc, arg_type, &arg_loc)) { + int result_only_flag = false; + + if (argcnt >= args_max) { + error(); + fprintf(errfile, + "Internal error: too many args, increase args_max\n"); + } + len = strlen(arg_type); + if (arg_type[len-1] == '*') { + arg_type[len-1] = EOS; + args[argcnt].res_flag = true; + result_flag = true; + } else if (arg_type[len-1] == '^') { + arg_type[len-1] = EOS; + args[argcnt].res_flag = true; + result_flag = true; + result_only_flag = true; + } else args[argcnt].res_flag = false; + + args[argcnt].index = lookup(arg_type, 'L'); + c_type = get_lisp_ctype(args[argcnt].index); + + if (c_type == NULL) { + error(); + fprintf(errfile, "Error: %s undefined, using int.\n", + arg_type); + c_type = "int"; + args[argcnt].index = lookup("FIXNUM", 'L'); + } + fprintf(out, " %s arg%d = ", c_type, argcnt+1); + if (result_only_flag) { + fprintf(out, "%s;\n", + get_lisp_initializer(args[argcnt].index)); + } else if (args[argcnt].index == any_index) { + fprintf(out, "xlgetarg();\n"); + } else { + c_str = "%s(%s());\n"; + fprintf(out,c_str, + get_lisp_extract(args[argcnt].index), + get_lisp_getarg(args[argcnt].index)); + } + argcnt++; + } + + if (*arg_loc != ')') { + fprintf(errfile, + "Warning: paren expected immediately after last arg of %s\n", + lispfn); + } + + /* check for close paren and close comment: */ + cp = sindex(arg_loc, ")"); + if (cp == NULL || sindex(cp+1, "*/") == NULL) { + error(); + fprintf(errfile, "Warning: close paren and close comment expected\n"); + } + + /* lookup result type */ + result_x = lookup(type_name, 'C'); + if (result_x == 0) { + fprintf(errfile, "Error: unknown type: %s, assuming void\n", + type_name); + result_x = lookup("void", 'C'); + } + + /* if there are result parameters then return them rather than NIL + * when the type is void + */ + if (get_c_special(result_x) == 'v' && result_flag) { + fprintf(out, " LVAL result;\n"); + } + + if (get_c_special(result_x) != 'v') { + /* declare result: */ + fprintf(out, " %s result;\n", type_name); + } + + /* check for end of argument list: */ + fprintf(out, "\n xllastarg();\n"); + + /* if there are results, we'll call cons, so + * protect the result from garbage collection + * if necessary + */ + if (result_flag && strcmp(type_name, "LVAL") == 0) { + fprintf(out, " xlprot1(result);\n"); + } + + /* call the c routine */ + if (get_c_special(result_x) != 'v') { + fprintf(out, " result = "); + } else fprintf(out, " "); + fprintf(out, "%s", fn_name); + if (!is_macro || argcnt > 0) fprintf(out, "("); + + /* pass arguments: */ + for (i = 0; i < argcnt; i++) { + if (i > 0) fprintf(out, ", "); + if (args[i].res_flag) fprintf(out, "&"); + fprintf(out, "arg%d", i+1); + } + if (!is_macro || argcnt > 0) fprintf(out, ")"); + fprintf(out, ";\n"); + + /* put results (if any) on *RSLT* */ + if (result_flag) { + int wrote_one_flag = false; + fprintf(out, " {\tLVAL *next = &getvalue(RSLT_sym);\n"); + for (i = 0; i < argcnt; i++) { + if (args[i].res_flag) { + if (wrote_one_flag) + fprintf(out, "\tnext = &cdr(*next);\n"); + wrote_one_flag = true; + fprintf(out, "\t*next = cons(NIL, NIL);\n"); + fprintf(out, "\tcar(*next) = %s(arg%d);", + get_lisp_makenode(args[i].index), i+1); + } + } + fprintf(out, "\n }\n"); + + /* copy *RSLT* to result if appropriate */ + if (get_c_special(result_x) == 'v') { + fprintf(out, " result = getvalue(RSLT_sym);\n"); + } + } + + + /* generate xlpop() if there was an xlprot1() */ + if (result_flag && strcmp(type_name, "LVAL") == 0) { + fprintf(out, " xlpop();\n"); + } + + + /* now return actual return value */ + if (get_c_special(result_x) == EOS) { + error(); + fprintf(errfile, "Warning: unknown type from C, coercing to int.\n"); + fprintf(out, " return cvfixnum((int) result);\n"); + } else if (get_c_special(result_x) == 'v' && !result_flag) { + fprintf(out, " return NIL;\n"); + } else if (get_c_special(result_x) == 'v' && result_flag) { + fprintf(out, " return result;\n"); + } else if (get_c_special(result_x) == 's') { + fprintf(out, " if (result == NULL) return NIL;\n"); + fprintf(out, " else return %s(result);\n", + get_c_conversion(result_x)); + } else { + fprintf(out, " return %s(result);\n", + get_c_conversion(result_x)); + } + fprintf(out, "}\n\n\n"); +} + + +/* write_postlude -- write stuff at end of file */ +/**/ +static void write_postlude(out) + FILE *out; +{ + /* nothing to do for version 2 */ +} + + +/* write_ptrfile -- write function definition table */ +/**/ +static void write_ptrfile(pf, df) + FILE *pf; + FILE *df; +{ + int n; + char *cp; + char cname[ident_max]; + + for (n = 0; n < subr_table_x; n++) { + strcpy(cname, subr_table[n]); + /* make cname lower case, dash,colon -> underscore: */ + for (cp = cname; *cp != EOS; cp++) { + if (isupper(*cp)) *cp = tolower(*cp); + if (*cp == '-' || *cp == ':') *cp = '_'; + } + fprintf(df, "extern LVAL xlc_%s(void);\n", cname); + fprintf(pf, " { \"%s\", S, xlc_%s}, \n", subr_table[n], cname); + } + printf(" Add %s to localdefs.h and add %s to localptrs.h\n", + def_file, ptr_file); +} + + +/* write_prelude -- write stuff at head of file */ +/**/ +static void write_prelude(out, out_file) + FILE *out; + char *out_file; +{ + int i = 2; + int col = strlen(out_file) + 21; + char *s; + fprintf(out, "/%c %s -- interface to ", + '*', out_file); + while ((s = cl_arg(i)) != NULL) { + if (i > 2) { + fprintf(out, ", "); + col += 2; + } + col += strlen(s) + 2; + if (col > 65) { + fprintf(out, "\n * "); + col = 4 + strlen(s) + 2; + } + fprintf(out, "%s", s); + i++; + } + fprintf(out, " */\n\n%cifndef mips\n%cinclude \"stdlib.h\"\n", '#', '#'); + fprintf(out, "%cendif\n%cinclude \"xlisp.h\"\n\n", '#', '#'); +#ifdef S_TRUE + fprintf(out, "extern LVAL s_true;\n"); + fprintf(out, "%cdefine cvboolean(i) ((i) ? s_true : NIL)\n", '#'); +#else + fprintf(out, "extern LVAL true;\n"); + fprintf(out, "%cdefine cvboolean(i) ((i) ? true : NIL)\n", '#'); +#endif + + fprintf(out, "%c%s\n", + '#', + "define testarg2(e) (moreargs() ? (e) : (getflonum(xltoofew())))"); + + fprintf(out, "%c%s\n%s\n%s\n", + '#', + "define xlgaanynum() (floatp(*xlargv) ? getflonum(nextarg()) : \\", + " (fixp(*xlargv) ? (double) getfixnum(nextarg()) : \\", +/* note: getflonum never gets called here, but this makes typechecking happy */ + " getflonum(xlbadtype(*xlargv))))"); + + fprintf(out, "%cdefine getboolean(lval) ((lval) != NIL)\n\n", '#'); + fprintf(out, "extern LVAL RSLT_sym;\n\n\n"); +} diff --git a/misc/intgen_win32/intgen.dsp b/misc/intgen_win32/intgen.dsp new file mode 100644 index 0000000..f019567 --- /dev/null +++ b/misc/intgen_win32/intgen.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="intgen" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=intgen - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "intgen.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "intgen.mak" CFG="intgen - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "intgen - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "intgen - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "intgen - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\sys\win\msvc" /I "..\..\cmt" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "intgen - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\sys\win\msvc" /I "..\..\cmt" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /D "_DEBUG" /D "DEBUG_INPUT" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "intgen - Win32 Release" +# Name "intgen - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\cmdline.c +# End Source File +# Begin Source File + +SOURCE=..\intgen2.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\cmdline.h +# End Source File +# Begin Source File + +SOURCE=..\..\sys\win\msvc\switches.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/misc/intgen_win32/intgen.vcproj b/misc/intgen_win32/intgen.vcproj new file mode 100644 index 0000000..072a813 --- /dev/null +++ b/misc/intgen_win32/intgen.vcproj @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/misc/mac-to-win.lsp b/misc/mac-to-win.lsp new file mode 100644 index 0000000..1819ed8 --- /dev/null +++ b/misc/mac-to-win.lsp @@ -0,0 +1,41 @@ +;; mac-to-win -- convert text files in nyquist project + +;; NOTE: this might work to convert any source tree to the local newline +;; convention, but it was written to run under windows and convert mac +;; sources to windows so that I could run windiff on the files. -RBD + +;; files.txt is a listing of all the component files + +(defun mac-to-win (output-path) + (let (files filename) + (setf files (open "files.txt" :direction :input)) + (while (setf filename (read-line files)) + (process-file filename output-path)) + (close files))) + + +(defun process-file (filename output-path) + (let ((filetype (char filename 0))) + (cond ((eq filetype #\a) + (setf filename (subseq filename 2)) + (convert-file filename output-path))))) + +(defun convert-file (filename output-path) + (let (infile outfile outfilename line) + (setf outfilename (strcat output-path filename)) + (setf infile (open filename :direction :input)) + (setf outfile (open outfilename :direction :output)) + (cond ((null infile) + (format t "Could not open ~A~%" filename)) + ((null outfile) + (format t "Could not open ~A~%" outfilename)) + (t (format t "~A~%" filename) + (while (setf line (read-line infile)) + (format outfile "~A~%" line)) + (close infile) + (close outfile))))) + +(defun convert-mac-to-win () + (setdir "d:/rbd/icm_nyquist") + (mac-to-win "d:/rbd/icm_nyquist_win/")) + diff --git a/misc/makefile.lsp b/misc/makefile.lsp new file mode 100644 index 0000000..29d6990 --- /dev/null +++ b/misc/makefile.lsp @@ -0,0 +1,679 @@ +;; makefile.lsp -- builds makefiles for various machine types + +(setf old-system-types '(rs6k next pmax sparc sgi)) +(setf system-types '(alsa nonalsa)) + +(if (not (boundp 'system-type)) (setf system-type nil)) +(if (not (boundp 'target-file)) (setf target-file "ny")) + +(format t "System types: ~A~%" system-types) +(format t + "The following types are not maintained but might get close: ~A~%" + old-system-types) +(format t "Current type: ~A~%" system-type) +(format t "Current target: ~A~%" target-file) +(format t "~%Instructions: (run from top nyquist directory)~%") +(format t "Choose a system from the list above by typing:~%") +(format t "\t(setf system-type ')~%") +(format t "Override the executable name or location by:~%") +(format t "\t(setf target-file \"unix-path-name/ny\")~%") +(format t "To build the Makefile, type:~%") +(format t "\t(makefile)~%") +(format t "To make Makefiles for all system types, type:~%") +(format t "\t(makeall)~%") +(format t "To make sndfn.wcl and sndfn.cl, type:~%") +(format t "\t(commandline)~%") + +;(format t "To build the Makesrc file, type:~%") +;(format t "\t(makesrc)~%") +;(format t +;"Note: Makesrc is used to update sources from other directories. +; It isn't necessary if you got the sources from the normal +; .tar file release of Nyquist +;") + + +(setf xlfiles '("extern" "xldmem" + "xlbfun" "xlcont" "xldbug" "xleval" + "xlfio" "xlftab" "xlglob" "xlimage" "xlinit" "xlio" "xlisp" + "xljump" "xllist" "xlmath" "xlobj" "xlpp" "xlprin" "xlread" + "xlstr" "xlsubr" "xlsym" "xlsys" "path")) + +(setf xlfiles-h '("osdefs" "osptrs" "xldmem" "xlisp" "extern")) + +(setf xlfiles-lsp '("xlinit" "misc" "evalenv" "printrec")) + +; ************************************ +; CHANGED stksrcfiles. PJM July 2007 +; ************************************ + +(setf stksrcfiles '("Generator" "SineWave" "Function" "FileRead" "FileWvIn" "Effect" + "Clarinet" "Delay" "DelayL" "Envelope" "Filter" + "Instrmnt" "Noise" "OneZero" "ReedTable" "Saxofony" "Stk" + "WaveLoop" "WvIn" + "NRev" "JCRev" "PRCRev" "PitShift" "Chorus" + "Bowed" "BowTable" "ADSR" "OnePole" "BiQuad" + "BandedWG" "DelayA" + "Mandolin" "PluckTwo" + "Sitar" "ModalBar" "Modal" + "Flute" "JetTable" "PoleZero" +)) + +; *************************************************** +; CHANGED stkfiles. PJM July 2007 +; Added stkint, An interface for new stk instruments +; *************************************************** + +(setf stkfiles '("stkinit" "instr" "stkint")) + +(setf fftfiles '("fftext" "fftlib" "matlib")) + +; note: audio and snd will be prepended to this list, e.g. +; the strings "audiooss" and "sndlinux" will be added for linux systems +; +(defun init-sndfiles () + (setf sndfiles '("ieeecvt" "snd" "sndcvt" "sndio" "sndheader")) + (setf sndfiles-lsp '("snd"))) + +(init-sndfiles) + +(setf depends-exceptions '( + ("nyqsrc/handlers" "") + ;("nyqsrc/sndfail" "") + ("nyqsrc/local" "xlisp/xlisp.h nyqsrc/sound.h") + ("nyqsrc/stats" "nyqsrc/sound.h nyqsrc/falloc.h nyqsrc/cque.h") + ("snd/sndcvt" "snd/snd.h") + ("snd/sndio" "snd/snd.h") + ("snd/audiors6k" "snd/snd.h") + ("snd/audionext" "snd/snd.h") + ("snd/audiosgi" "snd/snd.h") + ("snd/audiopmax" "snd/snd.h") + ("snd/audiosparc" "snd/snd.h") + ("snd/audiolinux" "snd/snd.h") + ("snd/audiooss" "snd/snd.h") + ("nyqsrc/sndwritepa" "nyqsrc/sndwrite.h") + ("nyqsrc/sndfnint" "") ; sparc needs explicit rule for sndfnint.o + ("nyqsrc/seqfnint" "") ; ditto for seqfnint.o +)) + +(setf nyqfiles-lsp '("init" "nyquist" "seqmidi" "seq" "makefile" "update" "transfiles" "examples" "nyinit")) + +(setf system-types-as-strings (mapcar #'string-downcase + (mapcar #'symbol-name system-types))) +(setf nyqfiles-lsp (append nyqfiles-lsp system-types-as-strings)) + +(setf nyqfiles-h '("localdefs" "localptrs" "seqdecls" "cque" "switches")) + +(setf intfiles '("sndfnint" "seqfnint")) + +(setf extrafiles nil) +;(dolist (m system-types) +; (push (strcat "Makefile." +; (string-downcase (symbol-name m))) +; extrafiles)) +(push "export" extrafiles) +(push "README" extrafiles) +(push "howtorelease.doc" extrafiles) + +(setf cmtfiles '("cext" "cleanup" "cmdline" "cmtcmd" + "moxc" "mem" "midifile" "midifns" "record" + "seq" "seqmread" "seqmwrite" "seqread" "seqwrite" "tempomap" + "timebase" "userio")) ; "midimgr" - removed by RBD + +(setf cmtfiles-h '("mfmidi" "midicode" "midierr" "musiprog" + "pitch" "swlogic" "hash" "hashrout" "io" "midibuff")) + + +(setf nylsffiles '("aiff" "alaw" "au" "avr" "broadcast" + "caf" "command" "common" "dither" + "double64" "dwd" "dwvw" "file_io" + "flac" "float32" "gsm610" "htk" + "ima_adpcm" "interleave" "ircam" "macbinary3" + "macos" "mat4" "mat5" "ms_adpcm" + "nist" "ogg" "paf" + "pcm" "pvf" "raw" "rx2" "sd2" + "sds" "sndfile" "strings" "svx" + "txw" "ulaw" "voc" "vox_adpcm" + "w64" "wav" "wav_w64" "wve" + "xi" "g72x" + "GSM610/add" "GSM610/code" "GSM610/decode" + "GSM610/gsm_create" "GSM610/gsm_decode" + "GSM610/gsm_destroy" "GSM610/gsm_encode" + "GSM610/gsm_option" "GSM610/long_term" + "GSM610/lpc" "GSM610/preprocess" + "GSM610/rpe" "GSM610/short_term" + "GSM610/table" + "G72x/g721" "G72x/g723_16" "G72x/g723_24" + "G72x/g723_40" "G72x/g72x")) + +(setf nylsffiles-h '("common" "config" "float_cast" "sfconfig" + "endian" "sf_unistd" "sndfile" "wav_w64" + "GSM610/gsm610_priv.h" "GSM610/gsm.h" + "G72x/g72x.h" "G72x/g72x_priv.h")) + +(defun insert-separator (pre sep lis) + (mapcar #'(lambda (pair) + (cond ((= (length pair) 2) + (strcat pre (car pair) sep (cadr pair) ".h")) + (t + (strcat (car pair) pre (cadr pair) sep (caddr pair) ".h")))) + lis)) + +;; COMMAND-PREFIX -- insert prefix before each file +;; +(defun command-prefix (prefix lis) + (mapcar #'(lambda (item) (list prefix item)) + lis)) + +(defun fix-sndwritepa (lis) + ;; exception: sndwritepa.h -> sndwrite.h + (mapcar #'(lambda (f) + (cond ((equal f "sndwritepa") "sndwrite") + (t f))) + lis)) + +;; COMMAND-FILELIST -- build files for command line +;; +(defun command-filelist (prefix separator) + (let () + (setf filelist '(("snd" "snd"))) + (setf filelist (append filelist + (command-prefix "nyqsrc" + (fix-sndwritepa nyqsrcfiles)))) + (display "after nyqsrc" filelist nyqsrcfiles) + (setf filelist (append filelist '(("~" "nyqsrc" "sndheader")))) + (setf filelist (append filelist (command-prefix "tran" transfiles))) + (cons (strcat prefix "nyqsrc" separator "sndfnint") + (insert-separator prefix separator filelist)))) + + +;; COMMANDLINE -- build sndfn.cl and sndfn.wcl for mac and windows +;; versions of intgen; the files will be written to current directory +;; +(defun commandline () + (princ "Your current directory should be nyquist, and you should have\n") + (princ "just evaluated (load \"misc/makefile\") and (commandline).\n") + (load "misc/transfiles") ;; get current versions of transfiles and nyqsrcfiles + (let (filelist outf) + (setf filelist (command-filelist "" "\\")) + (setf outf (open "sndfn.wcl" :direction :output)) + (write-file-list outf filelist #\ ) + (close outf) + ; now do the mac + (setf filelist (command-filelist "" "/")) + (setf outf (open "sndfn.cl" :direction :output)) + (write-file-list outf filelist #\ ) + (close outf) + (princ "On Mac OS-X, you should now (exit) nyquist, and at the commandline\n") + (princ "run macosxproject/build/Development/intgen @sndfn.cl\n") + (princ "updates to sndfn.cl and sndfn.wcl should be moved to nyqsrc\n") + )) + +;; MAKEALL - makes all makefiles and copies them to nyqsrc +;; +;; run this in nyquist/src +;; +(defun makeall () +; (makesrc) +; (system "cp -p Makesrc nyqsrc") + (dolist (m system-types) + (setf system-type m) + (setf m (string-downcase (symbol-name m))) + (init-sndfiles) + (makefile))) + +;; MAKE-AUDIO-NAME -- (strcat "audio" system-name) +;; jlh1 is audiooss something I need to track down and consider changing? +(defun make-audio-name (system-name) + (cond ((eq system-type 'linux) + "audiooss") + (t (strcat "audio" system-name)))) + +;; MAKE-SND-NAME -- (strcat "audio" system-name) +(defun make-snd-name (system-name) + (strcat "snd" system-name)) + + +;; MAKEFILE - creates a Makefile from a list of sources +;; +;; reads sources from transfiles.lsp + +;; ********************************************************* +;; CHANGED. PJM July 2007 +;; JAVASRC separators must be double bar \\ +;; Added onlyny: to compile only Nyquist. javac not needed +;; ********************************************************* + +(defun makefile () + (let (system-name outf outf-name) + (load "misc/transfiles.lsp") ; just to make sure we're current + (while (null system-type) + (format t "Write Makefile for what system? One of:~A~%" system-types) + (setf system-type (read)) + (cond ((not (member system-type system-types)) + (format t "Unknown system type.~%") + (setf system-type nil)))) + (setf system-name (string-downcase + (symbol-name system-type))) + (setf outf-name (strcat "sys/unix/" system-name "/Makefile")) + (format t "Opening for output: ~A\n" outf-name) + (setf outf (open outf-name :direction :output)) + (cond ((null outf) + (error "could not open output file" outf-name))) + (setf sndfiles (cons (make-audio-name system-name) + (cons (make-snd-name system-name) sndfiles))) + (format outf + "# +# Makefile for Nyquist, SYSTEM-TYPE is ~A +# run make in the top-level Nyquist directory to compile Nyquist +# +# NOTE: this file is machine-generated. DO NOT EDIT! +# Instead, modify makefile.lsp and regenerate the makefile. +# Ports and bug fixes are welcome - please mail them to +# dannenberg@cs.cmu.edu. Thanks. +# + +# This is the resulting executable (normally \"ny\"): +NY = ~A + +OPT = -O2 -m32 +# OPT = -g -m32 + +EVERYTHING = $(NY) runtime/system.lsp jnyqide/jNyqIDE.jar \\ + bin/ser-to-osc bin/test-client + +CURRENT = $(EVERYTHING) + +current: $(CURRENT) + +onlyny: $(NY) runtime/system.lsp + +JAVASRC = jnyqide/browser.java jnyqide/NyquistThread.java \\ + jnyqide/Pair.java jnyqide/BareBonesBrowserLaunch.java \\ + jnyqide/EnvelopeFrame.java jnyqide/Piano_Roll.java \\ + jnyqide/FindDialog.java jnyqide/PlotFrame.java \\ + jnyqide/InstrumentCharacteristics.java \\ + jnyqide/PlotMouseAdapter.java \\ + jnyqide/Jslide.java jnyqide/PopupListener.java \\ + jnyqide/LispFileFilter.java jnyqide/PreferencesDialog.java \\ + jnyqide/MainFrame_AboutBox.java jnyqide/ReplaceDialog.java \\ + jnyqide/MainFrame.java jnyqide/SpringUtilities.java \\ + jnyqide/Main.java \\ + jnyqide/NotFoundDialog.java jnyqide/TextColor.java \\ + jnyqide/NyqPlot.java jnyqide/Trie.java \\ + jnyqide/NyquistFile.java jnyqide/WordList.java + + +jnyqide/jNyqIDE.jar: $(JAVASRC) + if [ -r jnyqide/SpecialMacHandler.java ] ; then \\ + mv jnyqide/SpecialMacHandler.java jnyqide/SpecialMacHandler.hidden ;\\ + fi + cd jnyqide; javac *.java + mv jnyqide/SpecialMacHandler.hidden jnyqide/SpecialMacHandler.java + rm -rf jnyqide/jNyqIDE.jar + jar -cfm jnyqide/jNyqIDE.jar jnyqide/manifest.txt jnyqide/*.class + +# Standard list of includes (common to all unix versions) +# Keeping portaudio and libsndfile sources local to nyquist +INCL = -Inyqsrc -Itran -Ixlisp -Isys/unix -Icmt -Iffts/src \\ + -Inyqstk/include -Inyqstk -Iportaudio/include -Iportaudio/src/common \\ + -Iportaudio/src/os/unix \\ + -Iliblo -Inylsf + +# system dependent stuff for ~A: +~A + +INTGEN = misc/intgen + +# Object files for Nyquist: +" system-type target-file system-name (system-defs)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (object-files outf) + (format outf "# Sound functions to add to xlisp~%") + (nyqheaders outf) + (cmtheaders outf) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (format outf " + +bin: +\tmkdir bin + +liblo/Makefile: +\tcd liblo; ./configure CFLAGS=-m32 LDFLAGS=-m32 CXXFLAGS=-m32 --enable-static --disable-shared +\t# sometimes, residual files cause problems +\tcd liblo; make clean + +$(LIBLO_PATH)/liblo.a: liblo/Makefile +\tcd liblo; make + +bin/ser-to-osc: bin $(LIBLO_PATH)/liblo.a +\t$(CC) -c $(CFLAGS) liblo/ser-to-osc/ser-to-osc.cpp \\ +\t -o liblo/ser-to-osc/ser-to-osc.o +\t$(LN) liblo/ser-to-osc/ser-to-osc.o -o bin/ser-to-osc $(LFLAGS) + +bin/test-client: bin $(LIBLO_PATH)/liblo.a +\t$(CC) -c $(CFLAGS) liblo/test-client/test-client.c \\ +\t -o liblo/test-client/test-client.o +\t$(LN) liblo/test-client/test-client.o -o bin/test-client $(LFLAGS) + +portaudio/Makefile: +\t# note: without-jack avoids 32/64-bit link error on Debian +\tcd portaudio; ./configure CFLAGS=-m32 LDFLAGS=-m32 CXXFLAGS=-m32 --enable-static --disable-shared --without-jack +\t# sometimes, residual files cause problems +\tcd portaudio; make clean + +$(LIBPA_PATH)/libportaudio.a: portaudio/Makefile +\tcd portaudio; make + +$(NY): $(OBJECTS) $(LIBPA_PATH)/libportaudio.a $(LIBLO_PATH)/liblo.a +\t$(LN) $(OBJECTS) $(LFLAGS) -o $(NY) + +# copy appropriate system.lsp and make it read-only; +# changes should be made to sys/unix//system.lsp +runtime/system.lsp: sys/unix/~A/system.lsp +\t# make sure it's there before you make it writeable +\ttouch runtime/system.lsp +\tchmod +w runtime/system.lsp +\tcp -p sys/unix/~A/system.lsp runtime/system.lsp +\tchmod -w runtime/system.lsp + +" system-name system-name) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (dependencies outf system-name) + (format outf (system-rules)) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (format outf + "misc/intgen: misc/intgen.c +\tcd misc; make intgen + +misc/unpacker: misc/unpacker.c misc/convert.c +\tcd misc; make unpacker + +misc/packer: misc/packer.c misc/convert.c +\tcd misc; make packer + +nyqsrc/sndfnintptrs.h: $(NYQHDRS) misc/intgen +\t$(INTGEN) nyqsrc/sndfnint $(NYQHDRS) + +nyqsrc/seqfnintptrs.h: $(CMTHDRS) misc/intgen +\t$(INTGEN) nyqsrc/seqfnint $(CMTHDRS) + +clean: +\tcd misc; make clean +\tcd liblo; test -f Makefile && make clean || true +\tcd portaudio; test -f Makefile && make clean || true +\trm -f $(OBJECTS) +# These could be deleted, but they're part of the release, so we won't +# Note that these files are machine-generated: +# \trm -f nyqsrc/sndfnintptrs.h nyqsrc/sndfnint.c nyqsrc/sndfnintdefs.h +# \trm -f nyqsrc/seqfnintptrs.h nyqsrc/seqfnint.c nyqsrc/seqfnintdefs.h + +cleaner: clean +\tcd misc; make cleaner +\trm -f *.backup */*.backup +\trm -f *~~ */*.*~~ +\trm -f #*# */#*# +\trm -f *.save */*.save +\trm -f *.CKP */*.CKP +\trm -f *.BAK */*.BAK +\trm -f *.old */*.old +\trm -f *.gold */*.gold +\trm -f playparms +\trm -f points.dat +\trm -f core.* core +\trm -f $(NY) + +release: cleaner +\tcd misc; make packer +\tmisc/packer files.txt release.pac +\trm -f *.wav +\tmv ny .. +\tmv -f *.pac .. +\trm -f unpacker +\trm -f packer +\tcd ..; zip -r nyquist.zip nyquist +\t../ny misc/cmu/cmu-linux-install.lsp +\tmv ../ny ./ny +") + + (cond ((eq system-type 'rs6k) + (format outf " +tar: cleaner +\tsh -v sys/unix/cmu/tar.script + +backup: cleaner +\tsh -v sys/unix/cmu/backup.script +"))) + (close outf) + )) + +;; system-defs looks for a string of system-dependent defs for the makefile +;; +(defun system-defs () (system-var "-DEFS")) + + +;; system-rules looks for a string of system-dependent rules for the makefile +;; +(defun system-rules () (system-var "-RULES")) + + +;; system-var returns a string stored in the variable (if any): +;; - +;; +(defun system-var (suffix) + (let ((v (intern (strcat (symbol-name system-type) suffix)))) + (cond ((boundp v) (symbol-value v)) + (t "")))) + + +(defun fix-sndsliders (lis) + (remove "sndsliders" lis :test #'string=)) + +;; object-files - writes names of all object files for linking +;; +(defun object-files (outf) + (let ((flist (append (add-prefix "xlisp/" xlfiles) + (add-prefix "tran/" transfiles) + (add-prefix "cmt/" cmtfiles) + (add-prefix "nylsf/" nylsffiles) + (add-prefix "nyqsrc/" nyqfiles) + (add-prefix "nyqsrc/" (fix-sndsliders nyqsrcfiles)) ; pjm January 2008 + (add-prefix "nyqstk/src/" stksrcfiles) + (add-prefix "nyqstk/" stkfiles) + (add-prefix "ffts/src/" fftfiles) + (add-prefix "nyqsrc/" intfiles) + ;(add-prefix "snd/" sndfiles) + '("sys/unix/osstuff" "sys/unix/term")))) + (setf flist (add-suffix flist ".o")) + (format outf "OBJECTS = ") + (write-file-list outf flist #\\))) + + +;; add-prefix - place string at beginning of each string in list +;; +(defun add-prefix (prefix lis) + (mapcar #'(lambda (str) (strcat prefix str)) lis)) + + +;; add-suffix - place string at end of each string in list +;; +(defun add-suffix (lis suffix) + (mapcar #'(lambda (str) (strcat str suffix)) lis)) + + +;; write-file-list - write file names to Make macro +;; +(defun write-file-list (outf flist continuation-char) + (while flist + (dotimes (i 2) + (format outf "~A " (car flist)) + (setf flist (cdr flist)) + (if (null flist) (return))) + (if flist (format outf " ~A~%\t" continuation-char))) + (format outf "~%~%")) + + +(defun nyqheaders (outf) + (let ((flist (append + (list "nyqsrc/sndfmt" "nylsf/sndfile") + (add-prefix "nyqsrc/" (fix-sndwritepa nyqsrcfiles)) + (add-prefix "tran/" transfiles)))) + (setf flist (mapcar #'(lambda (f) (strcat f ".h")) + flist)) + (format outf "NYQHDRS = ") + (write-file-list outf flist #\\))) + + +(defun cmtheaders (outf) + (let ((flist + (append '("cmt/seqdecls" "nyqsrc/seqext" "cmt/seq" + "nyqsrc/seqinterf") ; order is important here! + (add-prefix "cmt/" + '("seqread" "seqmread" "seqwrite" "seqmwrite"))))) + (setf flist (add-suffix flist ".h")) + (format outf "CMTHDRS = ") + (write-file-list outf flist #\\))) + + +(defun dependencies (outf system-name) + ;; this forces generation of sndfnintdefs.h, seqfnintdefs.h: + (dolist (f (append (add-prefix "nyqsrc/" nyqsrcfiles) + (add-prefix "nyqsrc/" nyqfiles) + ;(add-prefix "snd/" sndfiles) + (add-prefix "ffts/src/" fftfiles) + (add-prefix "tran/" transfiles) + (add-prefix "nyqsrc/" intfiles))) + (let ((ex (assoc f depends-exceptions :test #'equal))) + (cond ((and ex (cdr ex)) + (format outf "~A.o: ~A.c ~A~%" f f (cadr ex)) + (format outf "\t$(CC) -c ~A.c -o ~A.o $(CFLAGS)~%~%" f f)) + (t + (format outf "~A.o: ~A.c ~A.h nyqsrc/sound.h nyqsrc/falloc.h nyqsrc/cque.h~%" + f f f) + (format outf "\t$(CC) -c ~A.c -o ~A.o $(CFLAGS)~%~%" f f))))) + (dolist (f stkfiles) + (format outf "nyqstk/~A.o: nyqstk/~A.cpp nyqstk/~A.h~%" + f f f) + (format outf "\tg++ -c nyqstk/~A.cpp -o nyqstk/~A.o $(CFLAGS)~%~%" + f f)) + + (dolist (f stksrcfiles) + (format outf "nyqstk/src/~A.o: nyqstk/src/~A.cpp nyqstk/include/~A.h~%" + f f f) + (format outf "\tg++ -c nyqstk/src/~A.cpp -o nyqstk/src/~A.o $(CFLAGS)~%~%" + f f)) + + (format outf "xlisp/xlftab.o: nyqsrc/sndfnintptrs.h nyqsrc/sndfnintdefs.h") + (format outf " nyqsrc/seqfnintptrs.h nyqsrc/seqfnintdefs.h~%") + (format outf "\t$(CC) -c xlisp/xlftab.c -o xlisp/xlftab.o $(CFLAGS)~%~%") + (dolist (f (append (add-prefix "xlisp/" xlfiles) + (add-prefix "cmt/" cmtfiles) + (add-prefix "nylsf/" nylsffiles) + '("sys/unix/osstuff"))) + (cond ((and (not (equal f "xlisp/xlftab")) ; special case handled above + (not (and (equal f "xlisp/xljump") ; case handled below + (equal system-name "next")))) + (format outf "~A.o: ~A.c~%\t$(CC) -c ~A.c -o ~A.o $(CFLAGS)~%~%" + f f f f))))) + + +;;=================================================== +;; SYSTEM DEPENDENCIES +;;=================================================== + +(setf rs6k-defs " +MIDI = /afs/cs/project/music/rs6k/midilib +CC = cc +# change -g to -O for optimization +# to enable command line editing, add -DREADLINE +CFLAGS = -DCMTSTUFF -g $(INCL) -I$(MIDI) +XFLAGS = $(CFLAGS) -qlanglvl=extended +LN = xlc -qattr -qlist +# to enable command line editing, add -lreadline -lcurses +LFLAGS = -lm -lpthread -L$(MIDI) -lmidi -lbsd -lg +") + + +(setf next-defs " +CC = cc +# to enable command line editing, insert -DREADLINE +CFLAGS = -DCMTSTUFF -O $(INCL) +LN = cc +# to enable command line editing, insert -lreadline -lcurses +LFLAGS = -lm -lpthread +") + +(setf next-rules " +# this doesn't compile with the -O switch (a NeXT compiler bug?) +xlisp/xljump.o : xlisp/xljump.c xlisp/xlisp.h +\t$(CC) -DCMTSTUFF -c xlisp/xljump.c -o xlisp/xljump.o +") + +(setf pmax-defs " +CC = cc +# to enable command line editing, insert -DREADLINE +CFLAGS = -DCMTSTUFF -g $(INCL) +LN = cc +# to enable command line editing, insert -lreadline -lcurses +LFLAGS = -lm +") + + +(setf sgi-defs " +CC = cc +# to enable command line editing, insert -DREADLINE +CFLAGS = -DCMTSTUFF -g $(INCL) +LN = cc +# to enable command line editing, insert -lreadline -lcurses +LFLAGS = -lm -lpthread +# you would need -lmd if UNIX_IRIX_MIDIFNS were defined in midifns.c +") + + +(setf sparc-defs " +CC = gcc +# to enable command line editing, insert -DREADLINE +CFLAGS = -DCMTSTUFF -g $(INCL) +LN = g++ +# to enable command line editing, insert -lreadline -lcurses +LFLAGS = -lm -lpthread +") + +;; this is the general plan for linux, but Debian cannot link with -lasound, +;; so to this string you need to prepend a definition for AUDIOLIBS which +;; has extra link directives for audio libraries, e.g. -lasound (see below) +(setf linux-defs " +CC = gcc + +LIBPA_PATH = portaudio/lib/.libs + +LIBLO_PATH = liblo/src/.libs + +# to enable command line editing, use -DREADLINE. WARNING: THIS WILL +# DISABLE THE ABILITY TO INTERRUPT LISP AND USE SOME OTHER HANDY +# CONTROL CHARACTERS (You will also need the readline and curses libraries) +CFLAGS = -DOSC -DCMTSTUFF $(OPT) $(INCL) \\ + -DHAVE_LIBPTHREAD=1 -D_FILE_OFFSET_BITS=64 \\ + -DSTK_NYQUIST -DUSE_VSPRINTF \\ + -DHAVE_CONFIG_H +LN = g++ -m32 +AR = ar +# to enable command line editing, insert -lreadline -lcurses +LFLAGS = $(LIBPA_PATH)/libportaudio.a $(LIBLO_PATH)/liblo.a $(AUDIOLIBS) -lm -lpthread -lrt + +TAGS: + find . \( -name "*.c" -o -name "*.h" \) -print | etags - + +tags: TAGS +") + +(setf alsa-defs (strcat " +AUDIOLIBS = -lasound +" linux-defs)) + +(setf nonalsa-defs (strcat " +AUDIOLIBS = +" linux-defs)) diff --git a/misc/packer.c b/misc/packer.c new file mode 100644 index 0000000..ffd89fa --- /dev/null +++ b/misc/packer.c @@ -0,0 +1,311 @@ +/* packer -- a program to pack a list of files into one */ + +/* The input is a file with one line per file to be packed. + Each line starts with either 'a' or 'b' for ascii or binary. + The second character is a space or tab (it's ignored). + The third character to the end of the line is the file to be packed. + + The encoding is as follows: + A file starts with '!' for ascii or '#' for binary in column one. + The remainder of the line is a file name/path. + Ascii files have a special character in column 1: + 'A'-'~' indicates 0 to n blanks. Leading Tabs are converted to blanks + and included in this count. + '0'-'9' indicates 0 to 9 blank lines (always followed by an additional newline). + Otherwise, all characters are just copied to output except: + '$' is an escape character: + $$ indicates $, + $@ through $_ indicate 0x00 through 0x1F, + $\n indicates an empty string (useful for avoiding long lines on output) + After $\n, the following character is not treated specially even though + it is in column 1. + + Should we be doing more to compress files? It looks like the special + handling of leading blanks compresses files about 4%. This is not much, + but the encoding allows us to put markers (! and #) in column 1 to + separate files. Originally, leading blank handling also converted between + 8 and 4 character tab stops, but you can no longer assume tab stops under, + say, Windows, are 8 characters wide. Source files should not have + tabs. + + Further simple encoding such as run-length encoding and word + substitution doesn't buy too much and was deemed not worth the effort. + Run-length encoding seems to buy another couple of percent. + Substitution for common words like int, print, return, the, register, + etc. buys maybe .5% per word, but it seems unlikely this will buy + more than a total of 10%, so we're looking at a max of 15% to 20% + compression without starting to huffman encode at the bit level. + + For binary files, every 3 bytes are used to form a 24-bit number which is + split into 4 fields of 6 bits. Each field is encoded by adding ascii '0'. + If only one or two bytes are left at the end of the file, the encoding is + as if zeros were appended to the file, but only 2 or 3 ascii characters + (instead of the usual 4) are output. The ascii file encoding is terminated + with a period ('.'). Newlines are inserted to keep line lengths down but + should be ignored by the reader. + */ + + +#include "switches.h" +#include "stdlib.h" +#include "string.h" +#include "cext.h" +#include "convert.h" +/* since we aren't using the cleanup package, expose exit(): */ +#undef exit + +#include "stdio.h" +#ifdef MACINTOSH +#include "console.h" +#endif + +#define EOS 0 + +#define string_max 500 + +void pack_newline(); +void pack_ascii(); +void pack_binary(); +void put_binary(); + +/* main -- pack a list of files */ +/**/ +int main(argc, argv) + int argc; + char *argv[]; +{ + FILE *inf; /* input file: a list of file names to pack */ + FILE *outf; /* the packed output */ + char filename[string_max]; /* holds names of input files */ + char convname[string_max]; /* filename converted to local syntax */ + int base = 1; +#ifdef MACINTOSH + argc = ccommand(&argv); +#endif + if (argc != 3 && argc != 4) { + fprintf(stderr, "Usage: packer [-p] input-list-file output-file\n"); + exit(1); + } + if (argc == 4) { + base = 2; + if (strcmp(argv[1], "-p") == 0) { + pauseflag = 1; + } else { + fprintf(stderr, "Expected \"-p\" as 1st argument.\n"); + exit(1); + } + } + inf = fopen(argv[base], "r"); + if (!inf) { + fprintf(stderr, "Couldn't open |%s|\n", argv[base]); + exit(1); + } + outf = fopen(argv[base+1], "w"); + if (!outf) { + fclose(inf); + fprintf(stderr, "Couldn't open |%s|\n", argv[base + 1]); + exit(1); + } + printf("Using tab width of %d\n", TAB_WIDTH); + while (fgets(filename, string_max, inf)) { + filename[strlen(filename) - 1] = EOS; /* remove newline at end */ + if (filename[0] == EOS) continue; /* skip blank lines */ + puts(filename); + strcpy(convname, filename + 2); + convert(convname); + if (filename[0] == 'a') pack_ascii(filename + 2, convname, outf); + else if (filename[0] == 'b') pack_binary(filename + 2, convname, outf); + else { + fprintf(stderr, "Bad file spec (expecting a or b in col 1): %s\n", + filename); + if (PAUSE) getchar(); + } + + } + fclose(outf); + fclose(inf); + return 0; +} + + +/* pack_ascii -- open filename and append its encoding to outf */ +/**/ +void pack_ascii(filename, convname, outf) + char *filename; + char *convname; + FILE *outf; +{ + int line_len = 0; + int c; + FILE *inf; + + inf = fopen(convname, "r"); + /* printf("opened %lx\n", inf); */ + if (!inf) { + fprintf(stderr, "Couldn't open |%s| - skipped\n", convname); + if (PAUSE) getchar(); + return; + } + fprintf(outf, "!%s\n", filename); + + pack_newline(inf, outf, &line_len); + while ((c = getc(inf)) != EOF) { + if (c > 127) { + fprintf(stderr, "non-ascii char 0x%x in %s.\n", c, convname); + exit(1); + } else if (c == '\n') { + putc(c, outf); + line_len = 0; + pack_newline(inf, outf, &line_len); + } else if (c == '$') { + putc('$', outf); + putc('$', outf); + line_len += 2; + } else if (c < 32) { + putc('$', outf); + putc('@' + c, outf); + line_len += 2; + } else { + putc(c, outf); + line_len++; + } + if (line_len > 70) { + putc('$', outf); + putc('\n', outf); + line_len = 0; + } + } + if (line_len) { + fprintf(stderr, "missing newline added to the end of %s\n", convname); + putc('\n', outf); + if (PAUSE) getchar(); + } + /* printf("closing %lx\n", inf); */ + fclose(inf); +} + + +/* pack_binary -- open binary filename and append its encoding to outf */ +/**/ +void pack_binary(filename, convname, outf) + char *filename; + char *convname; + FILE *outf; +{ + int line_len = 0; + int c; + long data; + int n; + FILE *inf; + boolean isbinary = false; + + inf = fopen(convname, "rb"); + /* printf("opened %lx\n", inf); */ + if (!inf) { + fprintf(stderr, "Couldn't open |%s| - skipped\n", convname); + if (PAUSE) getchar(); + return; + } + fprintf(outf, "#%s\n", filename); + + n = 0; + data = 0; + while ((c = getc(inf)) != EOF) { + if (c > 127) isbinary = true; + data = (data << 8) | c; + n++; + if (n == 3) { + put_binary(data, outf); + n = 0; + data = 0; + line_len += 4; + if (line_len >= 70) { + putc('\n', outf); + line_len = 0; + } + } + } + if (n == 1) { + data = data << 16; + putc('0' + ((data >> 18) & 0x3F), outf); + putc('0' + ((data >> 12) & 0x3F), outf); + } + if (n == 2) { + data = data << 8; + putc('0' + ((data >> 18) & 0x3F), outf); + putc('0' + ((data >> 12) & 0x3F), outf); + putc('0' + ((data >> 6) & 0x3F), outf); + } + putc('.', outf); + putc('\n', outf); + if (!isbinary) { + fprintf(stderr, "%s seems to be an ascii file.\n", convname); + if (PAUSE) getchar(); + } + /* printf("closing %lx\n", inf); */ + fclose(inf); +} + + +/* pack_newline -- newline sequence encoding to outf */ +/**/ +void pack_newline(inf, outf, line_len) + FILE *inf; /* input file */ + FILE *outf; /* where to write output */ + int *line_len; +{ + int c; + int count = 0; + int outc; + + while (((c = getc(inf)) != EOF) && (c == '\n')) { + count++; + } + while (count >= 10) { + fprintf(outf, "9\n"); + *line_len = 0; + count -= 10; + } + if (count > 0) { + fprintf(outf, "%c\n", '0' + count - 1); + *line_len = 0; + } + + /* now run-length encode leading blanks... */ + count = 0; + while (c != EOF) { + if (c == ' ') count++; + /* we no longer convert tabs to spaces... + else if (c == '\t') count += TAB_WIDTH; + */ + else break; + c = getc(inf); + } + if (c != EOF || count) { + outc = 'A' + count; + if (outc > '~') outc = '~'; + putc(outc, outf); + (*line_len) += 1; + count -= (outc - 'A'); + while (count > 0) { + putc(' ', outf); + (*line_len) += 1; + count--; + } + } + /* now do the rest of the line */ + if (c != EOF) ungetc(c, inf); +} + + +/* put_binary -- write 3 binary bytes as 4 ascii bytes */ +/**/ +void put_binary(data, outf) + long data; + FILE *outf; +{ + putc('0' + ((data >> 18) & 0x3F), outf); + putc('0' + ((data >> 12) & 0x3F), outf); + putc('0' + ((data >> 6) & 0x3F), outf); + putc('0' + (data & 0x3F), outf); +} diff --git a/misc/packer.dsp b/misc/packer.dsp new file mode 100644 index 0000000..3a5086b --- /dev/null +++ b/misc/packer.dsp @@ -0,0 +1,109 @@ +# Microsoft Developer Studio Project File - Name="packer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=packer - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "packer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "packer.mak" CFG="packer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "packer - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "packer - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "packer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "packer_Release" +# PROP Intermediate_Dir "packer_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\cmt" /I "..\sys\win\msvc" /I "../cmt" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "packer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "packer___Win32_Debug" +# PROP BASE Intermediate_Dir "packer___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "packer_Debug" +# PROP Intermediate_Dir "packer_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\cmt" /I "..\sys\win\msvc" /I "../cmt" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /D "_DEBUG" /D "DEBUG_INPUT" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "packer - Win32 Release" +# Name "packer - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\convert.c +# End Source File +# Begin Source File + +SOURCE=.\packer.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\nyquist21\misc\convert.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/misc/packer.vcproj b/misc/packer.vcproj new file mode 100644 index 0000000..a50b912 --- /dev/null +++ b/misc/packer.vcproj @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/misc/play.c b/misc/play.c new file mode 100644 index 0000000..19bfac6 --- /dev/null +++ b/misc/play.c @@ -0,0 +1,90 @@ +/* + + A cheap command to play sample files to the D/A's. + The sample files should have no headers. They can be + eight or sixteen bits, with one or two channels. + Sample rate is eigher 44.1 or 22.05. + + NOTE: samples brought from the VAX may have byte order + reversed. Use "dd conv=swab" to fix this. + + William Walker, University of Illinois, 27 January 1989 + (walker@m.cs.uiuc.edu) +*/ + +#include +#include +#define THESIZE 3000000 + + +#include "args.h" + +#define TAG 9839283 + +main(argc, argv) +char **argv; +{ + int srate = SND_RATE_LOW; + int nchannels = 1; + int again = 1; + int i; + SNDSoundStruct *cow; + FILE *data; + + ARGLOOP + FLAGARG('h') srate = SND_RATE_HIGH; ENDFLAGARG + FLAGARG('s') nchannels = 2; ENDFLAGARG + STRINGARG('r') srate = atoi(p); ENDSTRINGARG + FLAGARG('o') again = 0; ENDFLAGARG + + BADARG + fprintf(stderr, "unknown option %c\n", *p); + goto error; + ENDBADARG + ENDARGLOOP + + if (argc != 1) goto error; + + cow = (SNDSoundStruct *) malloc(THESIZE); + + /* these fields should probably be invariant: */ + cow->magic = SND_MAGIC; + cow->dataLocation = sizeof(SNDSoundStruct); + cow->dataSize = 0; + cow->dataFormat = SND_FORMAT_LINEAR_16; + cow->samplingRate = srate; + cow->channelCount = nchannels; + + printf("%d Hz sample rate, %d channels\n", + cow->samplingRate, + nchannels); + + + do { + data = fopen(argv[0],"r"); + if (data == NULL) { printf("play: fopen error\n"); exit(1); } + printf("Read %d bytes\n",cow->dataSize = fread((char *)cow+sizeof(SNDSoundStruct),1,THESIZE-sizeof(SNDSoundStruct),data)); + fclose(data); + + /* printf("Reserve sound for playing (%d)\n",SNDReserve()); */ + printf("Play (%d)\n", SNDStartPlaying(cow,TAG,0,0,(SNDNotificationFun)NULL,(SNDNotificationFun)NULL)); + printf("Wait for played sound (%d)\n",SNDWait(TAG)); + /* printf("Query played sound (%d)\n",SNDQueryPlayedSound()); */ + /* printf("Unreserve sound for playing (%d)\n",SNDUnreserveSoundForPlaying()); */ + if(again) { + char line[100]; + printf("Again? [y] "); + gets(line); + if(line[0] != 'y' && line[0] != 'Y' && line[0] != '\0') + again = 0; + } + } while( again ); + exit(0); +error: + fprintf(stderr, "\nUsage: play [ -h ] [ -s ] [ -o ] file\n\n"); + fprintf(stderr, " -h 44.1KHz sample rate (default 22.1KHz)\n"); + fprintf(stderr, " -s stereo (default mono)\n"); + fprintf(stderr, " -o play only once (default asks to play again)\n"); + fprintf(stderr, "\n"); + exit(1); +} diff --git a/misc/plot.c b/misc/plot.c new file mode 100644 index 0000000..e540592 --- /dev/null +++ b/misc/plot.c @@ -0,0 +1,249 @@ +/* + * FILE: plot.c + * BY: Christopher Lee Fraley (cf0v@spice.cs.cmu.edu) + * DESC: graphs file of numbers on terminal + * + * 1.1 ( 1-JUN-88) - added lines from 0 to data points (cf0v) + * 1.2 ( 3-JUN-88) - added skip parameter (cf0v) + * 1.3 (23-JUN-88) - added -x and -y options (cf0v) + * 1.4 (30-JUN-88) - clean-up. (cf0v) + * 2.0 ( 5-JUL-88) - added binary sound file format option. Changed scaling + * for "-n" option to only consider those values being + * plotted, instead of whole file. + */ + +char plotVERSION[] = "2.0 (5-JUL-88, 11:40am)"; + +/* + * plot [ [-nxyab]] + * Accepts input stream of numbers from (or stdin, if no + * argument is present), drawing a graph to sdout. File is prescanned for + * min and max values, and the graph is scaled accordingly. If making the + * file's min non-zero delta equal to one char allows the entire graph to + * fit on the screen, then this scalar is used. If the -n option is + * used, then only every th number from the input stream is plotted. + * The -x option enables printing the line number in the file on the screen + * every 10 lines. The -y option enables printing the y value on the screen + * every line. Note -x and -y are NOT mutually exclusive. The -a option + * indicates the input file is in ascii format, while the -b option indicates + * the input file is in the binary sound file format. When neither of these + * is present, binary is assumed unless input is from stdin. + */ + +#include +#include "stdefs.h" + +#define MAXNUMINPUT 16*1024 +#define BINARY 0 +#define ASCII 1 + + +fail(s, arg) +char *s, *arg; +{ + fprintf(stderr,"\nplot: "); + fprintf(stderr, s, arg); + fprintf(stderr,"\n\n"); + exit(1); +} + + + +FILE *fain; /* Pointer to input file for ascii format */ +int fbin; /* Input file for binary format */ +int ftype; /* Type of input file */ + + +prescan(X, Num, Max, Min, Delta) +HWORD X[]; +int *Num, *Max, *Min, *Delta; +{ + int last, i, len; + + *Min = *Delta = 32767; + *Max = -32768; + *Num = last = 0; + if (ftype == ASCII) + while (fscanf(fain,"%d",&i) != EOF) + { + *Min = MIN(i, *Min); + *Max = MAX(i, *Max); + if (i != last) + *Delta = MIN(ABS(i-last), *Delta); + *Num += 1; + last = i; + *X++ = i; + } + else + { + printf("| binary prescan, fbin:%d\n", fbin); + len = read(fbin, (char *)X, MAXNUMINPUT*sizeof(HWORD)) / sizeof(HWORD); + if (len >= MAXNUMINPUT) + fprintf(stderr, "plot: input truncated to %d samples\n", + MAXNUMINPUT); + for (i=0; i] [-n/s] [-x/y/a/b]',\ + \n where: to plot (stdin is default),\ + \n -n plot every th value in file,\ + \n -s start at the th sample,\ + \n -x print line # in file every 10 lines,\ + \n -y print y coordinate every line,\ + \n -a indicates input file is in ascii format,\ + \n -b indicates input is in binary sound file format.\ + \n -x and -y are NOT mutually exclusive; -a and -b ARE.\ + \n -b is assumed unless input is stdin.", *argv); + file = *argv; + printf("| file:%s\n", file); + } + else if ((*argv)[1]=='x' || (*argv)[1]=='X') + *xPrint = TRUE; + else if ((*argv)[1]=='y' || (*argv)[1]=='Y') + *yPrint = TRUE; + else if ((*argv)[1]=='a' || (*argv)[1]=='A') + ftype = ASCII; + else if ((*argv)[1]=='b' || (*argv)[1]=='B') + ftype = BINARY; + else if ((*argv)[1]=='n' || (*argv)[1]=='N') + { + if (1 != sscanf(*argv+2, "%d", skip)) + fail("illegal -n parameter '%s'", *argv); + } + else if ((*argv)[1]=='s' || (*argv)[1]=='S') + { + if (1 != sscanf(*argv+2, "%d", start)) + fail("illegal -s parameter '%s'", *argv); + } + } + if (!file) + ftype = ASCII; + else if (ftype == ASCII) + { + if (NULL == (fain = fopen(file, "r"))) + fail("could not open ascii input file '%s'\n", file); + } + else + { + if (NULL > (fbin = open(file, 0))) + fail("could not open binary input file '%s'\n", file); + } +} + + + +main (argc,argv) +int argc; +char *argv[]; +{ + int Num, Max, Min, Delta, i; + HWORD X[MAXNUMINPUT]; + double factor; + int target, skip, start; + int xCount, xPrint, yPrint; + char *Star[41], *Space[41]; + + printf("\nData Plotting Program\n"); + printf("by: Christopher Lee Fraley\n"); + printf("Version: %s\n", plotVERSION); + + Star[40] = "****************************************"; + Space[40] = " "; + for (i=39; i>=0; i--) + { + Star[i] = Star[i+1] + 1; + Space[i] = Space[i+1] + 1; + } + + getargs(argc, argv, &skip, &xPrint, &yPrint, &start); + prescan(X, &Num, &Max, &Min, &Delta); + + factor = 1.0/Delta; + if (factor*Max>39) + factor = 39.0/Max; + if (factor*Min<-40) + factor = 40.0/-Min; + + printf("\n Number of Data Points:%d \t [%d:%d]\n",Num,Min,Max); + printf(" Scale: %g/char",1.0/factor); + if (skip > 1) + printf(" \t\t Plotting every %dth sample", skip); + if (start) + printf(" Starting plot at sample %d", start); + printf("\n\n=========3=========2=========1=========0=========1=========2\ +=========3=========\n"); + + if (xPrint) + xCount = 11; + else + xCount = -1; + for (i=start; i + +#define NPERLINE 10 + +main() +{ + short line[2][NPERLINE]; + register int n, i, j; + register int curline = 0; + int currently_printing = 1; + + for(i = 0; + (n = fread(line[curline], sizeof(short), NPERLINE, stdin)) > 0; + i += n, curline = 1-curline) { + if(i != 0 && n == NPERLINE && sameline(line[0], line[1])) { + if(currently_printing) { + printf("*\n"); + currently_printing = 0; + } + continue; + } + currently_printing = 1; + printf("%7d ", i); + for(j = 0; j < n; j++) + printf("%6d ", line[curline][j]); + printf("\n"); + } + printf("%4d\n", i); +} + +sameline(l1, l2) +register short *l1, *l2; +{ + register n = NPERLINE; + while(--n >= 0) + if(*l1++ != *l2++) + return 0; + return 1; +} diff --git a/misc/sine.c b/misc/sine.c new file mode 100644 index 0000000..e691b59 --- /dev/null +++ b/misc/sine.c @@ -0,0 +1,73 @@ +/* + * FILE: sine.c + * BY: Christopher Lee Fraley (cf0v@spice.cs.cmu.edu) + * DESC: Creates sine waves of given period, amplitude, and length. + * + * 1.0 ( 1-JUN-88) - created. (cf0v) + * 2.0 ( 5-JUL-88) - converted to binary sound file format. (cf0v) + */ + +/* + * sine [-outfile] + * Outputs integer sine wave of maximum , with + * samples per period, and number of periods to stdout. Illegal + * arguments cause the defaults 32767, 20, and 3 to be used, respectively. + * If the flag "-outfile" is present, the output is in binary format to the + * named file. If the flag is ommitted, the output is to stdout, and is in + * ascii format, one number per line. + */ + +#include +#include +#include "stdefs.h" + +#define PERMS 0644 /* -rw-r--r-- */ + +fails(s, s2) +char *s, *s2; +{ + fprintf(stderr, s, s2); + exit(1); +} + + +main (argc,argv) +int argc; +char *argv[]; +{ + double Amp, Samps, Perds; + int i; + + if (argc!=4 && argc!=5) + fails("format is 'sine %s'\n", + " <#-of-periods> [-outfile]"); + if (!sscanf(*++argv, "%lf", &Amp)) + Amp = 32767.0; + if (!sscanf(*++argv, "%lf", &Samps)) + Samps = 20.0; + if (!sscanf(*++argv, "%lf", &Perds)) + Perds = 3.0; + if (argc==5) + { + int fout; + HWORD *Data, *ptr; + unsigned int outLen, len; + + if (NULL > (fout = creat(*++argv+1, PERMS))) + fails("could not create '%s'\n", *argv+1); + outLen = Samps*Perds*sizeof(HWORD); + ptr = Data = (HWORD *)malloc(outLen); + if (NULL == Data) + fails("could not allocate enough memory for output", ""); + for (i=0; i<(Samps*Perds); i++) + *ptr++ = (HWORD) (sin(2*PI*i/Samps) * Amp); + len = write(fout, (char *)Data, outLen); + if (len != outLen) + fails("incorrect number of bytes written", ""); + } + else + { + for (i=0; i<(Samps*Perds); i++) + printf("%d\n", (int)(sin(2*PI*i/Samps)*Amp)); + } +} diff --git a/misc/stdefs2.h b/misc/stdefs2.h new file mode 100644 index 0000000..3254d02 --- /dev/null +++ b/misc/stdefs2.h @@ -0,0 +1,50 @@ +/* + * FILE: stdefs.h + * BY: Christopher Lee Fraley (cf0v@spice.cs.cmu.edu) + * DESC: Defines standard stuff for inclusion in C programs. + * + * 1.0 ( 6-JUN-88) - created. (cf0v) + * 1.1 (30-JUN-88) - moved GetUHWORD def here. (cf0v) + * 1.2 (11-JUL-88) - added ffail() defs. (cf0v) + * 1.3 (25-JUL-88) - added dB() and undB() defs. (cf0v) + * 1.4 ( 8-AUG-88) - added stuff used by apple & new NULL def. (cf0v) + */ + +/* General purpose constants: */ +/* #define TRUE 1 + #define FALSE 0 + */ + +#define FATAL 1 +#define WARN 0 + +#define PI (3.14159265358979232846) +#define PI2 (6.28318530717958465692) +#define D2R (0.01745329348) /* (2*pi)/360 */ +#define R2D (57.29577951) /* 360/(2*pi) */ + + +/* General purpose typedefs: */ +typedef int bool; +typedef char BOOL; +typedef short HWORD; +typedef unsigned short UHWORD; +typedef int WORD; +typedef unsigned int UWORD; + + +/* General purpose macros: */ +#define GetUHWORD(x,y,z) GetUShort(x,y,z) +#define ffail(x,y) fail(sprintf(ERROR,x,y)) +#define ffail2(x,y,z) fail(sprintf(ERROR,x,y,z)) +#define MAX(x,y) ((x)>(y) ?(x):(y)) +#define MIN(x,y) ((x)<(y) ?(x):(y)) +#define ABS(x) ((x)<0 ?(-(x)):(x)) +#define SGN(x) ((x)<0 ?(-1):((x)==0?(0):(1))) +#define round(x) ((int)((x) + 0.5)) + +/* Convert amplitudes to and from dB scale: */ +#define MINLIN undB(-100) +#define undB(x) (((double)(REF)) * pow(10.0, ((double)(x))/20.0)) +#define dB(x) (((x) January 2008: now ADDED +; and fixed in makefile.lsp +; RENAMED "sndwrite" -> "sndwritepa" +; ADDED "lpanal" +;****************************************************************** + + +;; these are files in /nyqsrc that implement nyquist primitives +;; they become arguments to intgen, which builds the stubs from lisp to C +;; +(setf nyqsrcfiles '("sound" "add" "avg" "compose" "convolve" "downsample" + "fft" "inverse" "multiseq" "resamp" "resampv" + "samples" "sndmax" "sndread" "sndseq" "sndsliders" + "sndwritepa" "yin" "nyq-osc-server" + "trigger" "lpanal" "phasevocoder" "pvshell" + )) + +;; these are additional files in /nyqsrc that need to be compiled +;; and linked to make nyquist + + +;******************************************************************** +; CHANGES. PJM July 2007 +; nyqfiles: DELETED "lpanal" +; DELETED "trigger" +;******************************************************************** + +(setf nyqfiles '("debug" "falloc" "local" + "handlers" "multiread" + "seqext" "seqinterf" "stats" + "ffilterkit" + "sliders" +)) + diff --git a/misc/unpacker.c b/misc/unpacker.c new file mode 100644 index 0000000..e38cd47 --- /dev/null +++ b/misc/unpacker.c @@ -0,0 +1,328 @@ +/* unpacker -- a program to unpack a set of files */ +/* See packer.c for a description of the input file format. */ + +#include "switches.h" +#ifdef MACINTOSH +#include +#include +#endif + +#include "cext.h" +#include "convert.h" +#include "string.h" + +/* since we aren't using the cleanup package, expose exit(): */ +#undef exit + +#include "stdio.h" +#ifdef THINK_C +#include "console.h" +#endif + +#define string_max 500 +#ifndef EOS +#define EOS 0 +#endif + +void escape(); +void unpack_ascii(); +void unpack_binary(); +void put_run(); + +#ifdef UNIX +#define FILESEP '/' +#include +#include + +int dir_isvaliddir(char *path) +{ + DIR *dir = opendir(path); + if (!dir) return false; + closedir(dir); + return true; +} + + +#include +int _mkdir(char *p) +{ + int rslt = mkdir(p, S_IRUSR | S_IWUSR | S_IXUSR | + S_IXGRP | S_IWGRP | S_IROTH | S_IXOTH); + printf("_mkdir: %s, rslt %d\n", p, rslt); + if (rslt == -1) { + printf("mkdir error\n"); + perror("unpacker mkdir"); + } + return rslt; +} + +#endif + +#ifdef WINDOWS +#define FILESEP '\\' + +// deal with some incompatible definitions +#undef byte +#undef boolean +#include "windows.h" +#include +/* + * Function: dir_isvaliddir + * + * Purpose: + * + * Is this a valid directory ? + */ +BOOL dir_isvaliddir(LPSTR path) +{ + DWORD dwAttrib; + dwAttrib = GetFileAttributes(path); + if (dwAttrib == -1) { + return(FALSE); } + if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) { + return(TRUE); + } + return(FALSE); +} /* dir_isvaliddir */ +#endif + +/* early_eof -- print error message and exit */ +void early_eof() +{ + fprintf(stderr, "Unexpected end of file while unpacking\n"); + exit(1); +} +#ifdef MACINTOSH + +#define FILESEP ':' + +int dir_isvaliddir(char *path) +{ + char filename[256]; + OSErr err; + FSSpec spec; + strcpy(filename, path); + c2pstr(filename); + err = FSMakeFSSpec(0, 0, (unsigned char *) filename, &spec); + if (err == noErr) { + /* if we can open this as a file, it's not a directory */ + SInt16 refnum; + err = FSpOpenDF(&spec, fsCurPerm, &refnum); + if (err == noErr) { + FSClose(refnum); + return false; + } + return true; + } + return false; +} + + +int _mkdir(char *p) +{ + OSErr err; + FSSpec spec; + SInt32 dirid; + spec.vRefNum = 0; + spec.parID = 0; + strcpy((char *) spec.name, p); + c2pstr(spec.name); + err = FSpDirCreate(&spec, smSystemScript, &dirid); + if (err == noErr) { + return 0; + } + + if (err != noErr) { + printf("mkdir error %d\n", err); + } + return -1; +} +#endif + + +void make_path(char *full_name) +// make directories as needed +{ + char directory[256]; + char *ptr = full_name; + while (ptr = strchr(ptr, FILESEP)) { + strcpy(directory, full_name); + directory[ptr - full_name] = 0; + if (!dir_isvaliddir(directory)) { + if (_mkdir(directory) != 0) { + printf("Could not create %s\n", directory); + return; + } else { + printf("Created directory %s\n", directory); + } + } + // now directory is valid, so move to next one + ptr++; + } +} + + +/* main -- unpack a set of files */ +/**/ +int main(argc, argv) + int argc; + char *argv[]; +{ + FILE *inf; /* input file: a packed set of files */ + FILE *outf; /* a file to unpack */ + char filename[string_max]; /* holds names of inptu files */ +#ifdef MACINTOSH + argc = ccommand(&argv); +#endif + if (argc != 2) { + fprintf(stderr, "Usage: unpack input-file\n"); + exit(1); + } + inf = fopen(argv[1], "r"); + if (!inf) { + fprintf(stderr, "Couldn't open |%s|\n", argv[1]); + exit(1); + } + while (fgets(filename, string_max, inf)) { + char *filetype = "w"; + filename[strlen(filename) - 1] = EOS; /* remove newline at end */ + puts(filename + 1); /* don't print the leading ! or # */ + convert(filename + 1); /* convert to local filename conventions */ + if (filename[0] == '#') filetype = "wb"; + outf = fopen(filename + 1, filetype); + if (!outf) { + make_path(filename + 1); + outf = fopen(filename + 1, filetype); + if (!outf) { + fprintf(stderr, "Couldn't open |%s|\n", filename + 1); + exit(1); + } + } + if (filename[0] == '!') { + unpack_ascii(inf, outf, filename + 1); + } else if (filename[0] == '#') { + unpack_binary(inf, outf); + } + if (outf) fclose(outf); + } + fclose(inf); + return 0; +} + + +/* put_run -- output a run of characters */ +/**/ +void put_run(f, c, n) + FILE *f; + int c; + int n; +{ + while (n--) putc(c, f); +} + + +/* unpack_ascii -- from inf to outf */ +/**/ +void unpack_ascii(inf, outf, filename) + FILE *inf; + FILE *outf; + char *filename; +{ + for (;;) { + int c = getc(inf); + if (c == EOF) return; + else if (c > 127) { + fprintf(stderr, "Non-ascii char 0x%x found while unpacking %s.\n", c, filename); + return; + } else if (c >= 'A' && c <= '~') { + int n = (c - 'A'); + //DO NOT OUTPUT LEADING TABS -- USE SPACES INSTEAD + // int tabs = (n / TAB_WIDTH); + // n -= tabs * TAB_WIDTH; + // put_run(outf, '\t', tabs); + put_run(outf, ' ', n); + } else if (c >= '0' && c <= '9') { + put_run(outf, '\n', c - '0'); + } else if (c == '!' || c == '#') { + ungetc(c, inf); + return; + } else { + fprintf(stderr, "Unexpected char in col 1 (%c) while unpacking %s.\n", + c, filename); + return; + } + + /* now get rest of the line */ + while ((c = getc(inf)) != EOF) { + if (c == '$') { + c = getc(inf); + if (c == EOF) { + early_eof(); + } else if (c == '$') { + putc('$', outf); + } else if (c >= '@' && c <= '_') { + putc(c - '@', outf); + } else if (c == '\n') { + ; /* do nothing */ + } else { + fprintf(stderr, "Bad char (%c) after '$' while unpacking %s.\n", + c, filename); + } + } else { + putc(c, outf); + if (c == '\n') break; /* go up and process col. 1 char */ + } + } + } +} + + +/* unpack_binary -- from inf to outf */ +/**/ +void unpack_binary(inf, outf) + FILE *inf; + FILE *outf; +{ + for (;;) { + long l; + int c = getc(inf); + if (c == EOF) { + early_eof(); + } else if (c == '.') { + break; + } else if (c == '\n') { + ; /* do nothing */ + } else { + l = c - '0'; + c = getc(inf); + if (c == EOF) { + early_eof(); + } else { + l = (l << 6) + (c - '0'); + c = getc(inf); + if (c == EOF) { + early_eof(); + } else if (c == '.') { + putc(l >> 4, outf); + break; + } else { + l = (l << 6) + (c - '0'); + c = getc(inf); + if (c == EOF) { + early_eof(); + } else if (c == '.') { + putc((l >> 10) & 0xFF, outf); + putc((l >> 2) & 0xFF, outf); + break; + } else { + l = (l << 6) + (c - '0'); + putc((l >> 16) & 0xFF, outf); + putc((l >> 8) & 0xFF, outf); + putc(l & 0xFF, outf); + } + } + } + } + } + getc(inf); /* read the final newline */ +} diff --git a/misc/unpacker.dsp b/misc/unpacker.dsp new file mode 100644 index 0000000..74f05a7 --- /dev/null +++ b/misc/unpacker.dsp @@ -0,0 +1,105 @@ +# Microsoft Developer Studio Project File - Name="unpacker" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=unpacker - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "unpacker.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "unpacker.mak" CFG="unpacker - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "unpacker - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "unpacker - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "unpacker - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "unpacker_Release" +# PROP Intermediate_Dir "unpacker_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\cmt" /I "..\sys\win\msvc" /I "../cmt" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "unpacker - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "unpacker___Win32_Debug" +# PROP BASE Intermediate_Dir "unpacker___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "unpacker_Debug" +# PROP Intermediate_Dir "unpacker_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\cmt" /I "..\sys\win\msvc" /I "../cmt" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /D "_DEBUG" /D "DEBUG_INPUT" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "unpacker - Win32 Release" +# Name "unpacker - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\convert.c +# End Source File +# Begin Source File + +SOURCE=.\unpacker.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/misc/unpacker.vcproj b/misc/unpacker.vcproj new file mode 100644 index 0000000..5273869 --- /dev/null +++ b/misc/unpacker.vcproj @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nylsf/COPYING b/nylsf/COPYING new file mode 100644 index 0000000..c396169 --- /dev/null +++ b/nylsf/COPYING @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library 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 2.1 of the License, or (at your option) any later version. + + This library 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 library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/nylsf/G72x/README.original b/nylsf/G72x/README.original new file mode 100644 index 0000000..23b0e7d --- /dev/null +++ b/nylsf/G72x/README.original @@ -0,0 +1,94 @@ +The files in this directory comprise ANSI-C language reference implementations +of the CCITT (International Telegraph and Telephone Consultative Committee) +G.711, G.721 and G.723 voice compressions. They have been tested on Sun +SPARCstations and passed 82 out of 84 test vectors published by CCITT +(Dec. 20, 1988) for G.721 and G.723. [The two remaining test vectors, +which the G.721 decoder implementation for u-law samples did not pass, +may be in error because they are identical to two other vectors for G.723_40.] + +This source code is released by Sun Microsystems, Inc. to the public domain. +Please give your acknowledgement in product literature if this code is used +in your product implementation. + +Sun Microsystems supports some CCITT audio formats in Solaris 2.0 system +software. However, Sun's implementations have been optimized for higher +performance on SPARCstations. + + +The source files for CCITT conversion routines in this directory are: + + g72x.h header file for g721.c, g723_24.c and g723_40.c + g711.c CCITT G.711 u-law and A-law compression + g72x.c common denominator of G.721 and G.723 ADPCM codes + g721.c CCITT G.721 32Kbps ADPCM coder (with g72x.c) + g723_24.c CCITT G.723 24Kbps ADPCM coder (with g72x.c) + g723_40.c CCITT G.723 40Kbps ADPCM coder (with g72x.c) + + +Simple conversions between u-law, A-law, and 16-bit linear PCM are invoked +as follows: + + unsigned char ucode, acode; + short pcm_val; + + ucode = linear2ulaw(pcm_val); + ucode = alaw2ulaw(acode); + + acode = linear2alaw(pcm_val); + acode = ulaw2alaw(ucode); + + pcm_val = ulaw2linear(ucode); + pcm_val = alaw2linear(acode); + + +The other CCITT compression routines are invoked as follows: + + #include "g72x.h" + + struct g72x_state state; + int sample, code; + + g72x_init_state(&state); + code = {g721,g723_24,g723_40}_encoder(sample, coding, &state); + sample = {g721,g723_24,g723_40}_decoder(code, coding, &state); + +where + coding = AUDIO_ENCODING_ULAW for 8-bit u-law samples + AUDIO_ENCODING_ALAW for 8-bit A-law samples + AUDIO_ENCODING_LINEAR for 16-bit linear PCM samples + + + +This directory also includes the following sample programs: + + encode.c CCITT ADPCM encoder + decode.c CCITT ADPCM decoder + Makefile makefile for the sample programs + + +The sample programs contain examples of how to call the various compression +routines and pack/unpack the bits. The sample programs read byte streams from +stdin and write to stdout. The input/output data is raw data (no file header +or other identifying information is embedded). The sample programs are +invoked as follows: + + encode [-3|4|5] [-a|u|l] outfile + decode [-3|4|5] [-a|u|l] outfile +where: + -3 encode to (decode from) G.723 24kbps (3-bit) data + -4 encode to (decode from) G.721 32kbps (4-bit) data [the default] + -5 encode to (decode from) G.723 40kbps (5-bit) data + -a encode from (decode to) A-law data + -u encode from (decode to) u-law data [the default] + -l encode from (decode to) 16-bit linear data + +Examples: + # Read 16-bit linear and output G.721 + encode -4 -l g721file + + # Read 40Kbps G.723 and output A-law + decode -5 -a alawfile + + # Compress and then decompress u-law data using 24Kbps G.723 + encode -3 ulawout + diff --git a/nylsf/G72x/g721.c b/nylsf/G72x/g721.c new file mode 100644 index 0000000..4f51bb1 --- /dev/null +++ b/nylsf/G72x/g721.c @@ -0,0 +1,162 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g721.c + * + * Description: + * + * g721_encoder(), g721_decoder() + * + * These routines comprise an implementation of the CCITT G.721 ADPCM + * coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which + * take advantage of work station attributes, such as hardware 2's + * complement arithmetic and large memory. Specifically, certain time + * consuming operations such as multiplications are replaced + * with lookup tables and software 2's complement operations are + * replaced with hardware 2's complement. + * + * The deviation from the bit level specification (lookup tables) + * preserves the bit level performance specifications. + * + * As outlined in the G.721 Recommendation, the algorithm is broken + * down into modules. Each section of code below is preceded by + * the name of the module which it is implementing. + * + */ + +#include "g72x.h" +#include "g72x_priv.h" + +static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400}; +/* + * Maps G.721 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, + 425, 373, 323, 273, 213, 135, 4, -2048}; + +/* Maps G.721 code word to log of scale factor multiplier. */ +static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, + 1122, 355, 198, 112, 64, 41, 18, -12}; +/* + * Maps G.721 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, + 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; + +/* + * g721_encoder() + * + * Encodes the input vale of linear PCM, A-law or u-law data sl and returns + * the resulting code. -1 is returned for unknown input coding value. + */ +int +g721_encoder( + int sl, + G72x_STATE *state_ptr) +{ + short sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short sr; /* ADDB */ + short y; /* MIX */ + short dqsez; /* ADDC */ + short dq, i; + + /* linearize input sample to 14-bit PCM */ + sl >>= 2; /* 14-bit dynamic range */ + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ + + d = sl - se; /* estimation difference */ + + /* quantize the prediction difference */ + y = step_size(state_ptr); /* quantizer step size */ + i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */ + + dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */ + + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ + + dqsez = sr + sez - se; /* pole prediction diff. */ + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g721_decoder() + * + * Description: + * + * Decodes a 4-bit code of G.721 encoded data of i and + * returns the resulting linear PCM, A-law or u-law value. + * return -1 for unknown out_coding value. + */ +int +g721_decoder( + int i, + G72x_STATE *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x0f; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* dynamic quantizer step size */ + + dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + /* sr was 14-bit dynamic range */ + return (sr << 2); +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 101b6e25-457d-490a-99ae-e2e74a26ea24 +*/ + diff --git a/nylsf/G72x/g723_16.c b/nylsf/G72x/g723_16.c new file mode 100644 index 0000000..0c31745 --- /dev/null +++ b/nylsf/G72x/g723_16.c @@ -0,0 +1,169 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* 16kbps version created, used 24kbps code and changing as little as possible. + * G.726 specs are available from ITU's gopher or WWW site (http://www.itu.ch) + * If any errors are found, please contact me at mrand@tamu.edu + * -Marc Randolph + */ + +/* + * g723_16.c + * + * Description: + * + * g723_16_encoder(), g723_16_decoder() + * + * These routines comprise an implementation of the CCITT G.726 16 Kbps + * ADPCM coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which take advantage + * of workstation attributes, such as hardware 2's complement arithmetic. + * + */ + +#include "g72x.h" +#include "g72x_priv.h" + +/* + * Maps G.723_16 code word to reconstructed scale factor normalized log + * magnitude values. Comes from Table 11/G.726 + */ +static short _dqlntab[4] = { 116, 365, 365, 116}; + +/* Maps G.723_16 code word to log of scale factor multiplier. + * + * _witab[4] is actually {-22 , 439, 439, -22}, but FILTD wants it + * as WI << 5 (multiplied by 32), so we'll do that here + */ +static short _witab[4] = {-704, 14048, 14048, -704}; + +/* + * Maps G.723_16 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ + +/* Comes from FUNCTF */ +static short _fitab[4] = {0, 0xE00, 0xE00, 0}; + +/* Comes from quantizer decision level tables (Table 7/G.726) + */ +static short qtab_723_16[1] = {261}; + + +/* + * g723_16_encoder() + * + * Encodes a linear PCM, A-law or u-law input sample and returns its 2-bit code. + * Returns -1 if invalid input coding value. + */ +int +g723_16_encoder( + int sl, + G72x_STATE *state_ptr) +{ + short sei, sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short y; /* MIX */ + short sr; /* ADDB */ + short dqsez; /* ADDC */ + short dq, i; + + /* linearize input sample to 14-bit PCM */ + sl >>= 2; /* sl of 14-bit dynamic range */ + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + d = sl - se; /* d = estimation diff. */ + + /* quantize prediction difference d */ + y = step_size(state_ptr); /* quantizer step size */ + i = quantize(d, y, qtab_723_16, 1); /* i = ADPCM code */ + + /* Since quantize() only produces a three level output + * (1, 2, or 3), we must create the fourth one on our own + */ + if (i == 3) /* i code for the zero region */ + if ((d & 0x8000) == 0) /* If d > 0, i=3 isn't right... */ + i = 0; + + dq = reconstruct(i & 2, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ + + dqsez = sr + sez - se; /* pole prediction diff. */ + + update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g723_16_decoder() + * + * Decodes a 2-bit CCITT G.723_16 ADPCM code and returns + * the resulting 16-bit linear PCM, A-law or u-law sample value. + * -1 is returned if the output coding is unknown. + */ +int +g723_16_decoder( + int i, + G72x_STATE *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x03; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* adaptive quantizer step size */ + dq = reconstruct(i & 0x02, _dqlntab[i], y); /* unquantize pred diff */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + /* sr was of 14-bit dynamic range */ + return (sr << 2); +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: ae265466-c3fc-4f83-bb32-edae488a5ca5 +*/ + diff --git a/nylsf/G72x/g723_24.c b/nylsf/G72x/g723_24.c new file mode 100644 index 0000000..8748459 --- /dev/null +++ b/nylsf/G72x/g723_24.c @@ -0,0 +1,146 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g723_24.c + * + * Description: + * + * g723_24_encoder(), g723_24_decoder() + * + * These routines comprise an implementation of the CCITT G.723 24 Kbps + * ADPCM coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which take advantage + * of workstation attributes, such as hardware 2's complement arithmetic. + * + */ + +#include "g72x.h" +#include "g72x_priv.h" + +/* + * Maps G.723_24 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048}; + +/* Maps G.723_24 code word to log of scale factor multiplier. */ +static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128}; + +/* + * Maps G.723_24 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0}; + +static short qtab_723_24[3] = {8, 218, 331}; + +/* + * g723_24_encoder() + * + * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. + * Returns -1 if invalid input coding value. + */ +int +g723_24_encoder( + int sl, + G72x_STATE *state_ptr) +{ + short sei, sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short y; /* MIX */ + short sr; /* ADDB */ + short dqsez; /* ADDC */ + short dq, i; + + /* linearize input sample to 14-bit PCM */ + sl >>= 2; /* sl of 14-bit dynamic range */ + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + d = sl - se; /* d = estimation diff. */ + + /* quantize prediction difference d */ + y = step_size(state_ptr); /* quantizer step size */ + i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */ + dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ + + dqsez = sr + sez - se; /* pole prediction diff. */ + + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g723_24_decoder() + * + * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns + * the resulting 16-bit linear PCM, A-law or u-law sample value. + * -1 is returned if the output coding is unknown. + */ +int +g723_24_decoder( + int i, + G72x_STATE *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x07; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* adaptive quantizer step size */ + dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (sr << 2); /* sr was of 14-bit dynamic range */ +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 75389236-650b-4427-98f3-0df6e8fb24bc +*/ + diff --git a/nylsf/G72x/g723_40.c b/nylsf/G72x/g723_40.c new file mode 100644 index 0000000..6ddb577 --- /dev/null +++ b/nylsf/G72x/g723_40.c @@ -0,0 +1,160 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g723_40.c + * + * Description: + * + * g723_40_encoder(), g723_40_decoder() + * + * These routines comprise an implementation of the CCITT G.723 40Kbps + * ADPCM coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which + * take advantage of workstation attributes, such as hardware 2's + * complement arithmetic. + * + * The deviation from the bit level specification (lookup tables), + * preserves the bit level performance specifications. + * + * As outlined in the G.723 Recommendation, the algorithm is broken + * down into modules. Each section of code below is preceded by + * the name of the module which it is implementing. + * + */ + +#include "g72x.h" +#include "g72x_priv.h" + +/* + * Maps G.723_40 code word to ructeconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318, + 358, 395, 429, 459, 488, 514, 539, 566, + 566, 539, 514, 488, 459, 429, 395, 358, + 318, 274, 224, 169, 104, 28, -66, -2048}; + +/* Maps G.723_40 code word to log of scale factor multiplier. */ +static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200, + 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272, + 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512, + 3200, 1856, 1312, 1280, 1248, 768, 448, 448}; + +/* + * Maps G.723_40 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200, + 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00, + 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200, + 0x200, 0x200, 0x200, 0, 0, 0, 0, 0}; + +static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339, + 378, 413, 445, 475, 502, 528, 553}; + +/* + * g723_40_encoder() + * + * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens + * the resulting 5-bit CCITT G.723 40Kbps code. + * Returns -1 if the input coding value is invalid. + */ +int g723_40_encoder (int sl, G72x_STATE *state_ptr) +{ + short sei, sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short y; /* MIX */ + short sr; /* ADDB */ + short dqsez; /* ADDC */ + short dq, i; + + /* linearize input sample to 14-bit PCM */ + sl >>= 2; /* sl of 14-bit dynamic range */ + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + d = sl - se; /* d = estimation difference */ + + /* quantize prediction difference */ + y = step_size(state_ptr); /* adaptive quantizer step size */ + i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */ + + dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */ + + sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */ + + dqsez = sr + sez - se; /* dqsez = pole prediction diff. */ + + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g723_40_decoder() + * + * Decodes a 5-bit CCITT G.723 40Kbps code and returns + * the resulting 16-bit linear PCM, A-law or u-law sample value. + * -1 is returned if the output coding is unknown. + */ +int g723_40_decoder (int i, G72x_STATE *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y ; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x1f; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* adaptive quantizer step size */ + dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */ + + sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (sr << 2); /* sr was of 14-bit dynamic range */ +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: eb8d9a00-32bf-4dd2-b287-01b0336d72bf +*/ + diff --git a/nylsf/G72x/g72x.c b/nylsf/G72x/g72x.c new file mode 100644 index 0000000..ea01d79 --- /dev/null +++ b/nylsf/G72x/g72x.c @@ -0,0 +1,652 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g72x.c + * + * Common routines for G.721 and G.723 conversions. + */ + +#include +#include +#include + +#include "g72x.h" +#include "g72x_priv.h" + +static G72x_STATE * g72x_state_new (void) ; +static int unpack_bytes (int bits, int blocksize, const unsigned char * block, short * samples) ; +static int pack_bytes (int bits, const short * samples, unsigned char * block) ; + +static +short power2 [15] = +{ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000 +} ; + +/* + * quan() + * + * quantizes the input val against the table of size short integers. + * It returns i if table[i - 1] <= val < table[i]. + * + * Using linear search for simple coding. + */ +static +int quan (int val, short *table, int size) +{ + int i; + + for (i = 0; i < size; i++) + if (val < *table++) + break; + return (i); +} + +/* + * fmult() + * + * returns the integer product of the 14-bit integer "an" and + * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". + */ +static +int fmult (int an, int srn) +{ + short anmag, anexp, anmant; + short wanexp, wanmant; + short retval; + + anmag = (an > 0) ? an : ((-an) & 0x1FFF); + anexp = quan(anmag, power2, 15) - 6; + anmant = (anmag == 0) ? 32 : + (anexp >= 0) ? anmag >> anexp : anmag << -anexp; + wanexp = anexp + ((srn >> 6) & 0xF) - 13; + + /* + ** The original was : + ** wanmant = (anmant * (srn & 0x37) + 0x30) >> 4 ; + ** but could see no valid reason for the + 0x30. + ** Removed it and it improved the SNR of the codec. + */ + + wanmant = (anmant * (srn & 0x37)) >> 4 ; + + retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : + (wanmant >> -wanexp); + + return (((an ^ srn) < 0) ? -retval : retval); +} + +static G72x_STATE * g72x_state_new (void) +{ return calloc (1, sizeof (G72x_STATE)) ; +} + +/* + * private_init_state() + * + * This routine initializes and/or resets the G72x_PRIVATE structure + * pointed to by 'state_ptr'. + * All the initial state values are specified in the CCITT G.721 document. + */ +void private_init_state (G72x_STATE *state_ptr) +{ + int cnta; + + state_ptr->yl = 34816; + state_ptr->yu = 544; + state_ptr->dms = 0; + state_ptr->dml = 0; + state_ptr->ap = 0; + for (cnta = 0; cnta < 2; cnta++) { + state_ptr->a[cnta] = 0; + state_ptr->pk[cnta] = 0; + state_ptr->sr[cnta] = 32; + } + for (cnta = 0; cnta < 6; cnta++) { + state_ptr->b[cnta] = 0; + state_ptr->dq[cnta] = 32; + } + state_ptr->td = 0; +} /* private_init_state */ + +struct g72x_state * g72x_reader_init (int codec, int *blocksize, int *samplesperblock) +{ G72x_STATE *pstate ; + + if ((pstate = g72x_state_new ()) == NULL) + return NULL ; + + private_init_state (pstate) ; + + pstate->encoder = NULL ; + + switch (codec) + { case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */ + pstate->decoder = g723_16_decoder ; + *blocksize = G723_16_BYTES_PER_BLOCK ; + *samplesperblock = G723_16_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 2 ; + pstate->blocksize = G723_16_BYTES_PER_BLOCK ; + pstate->samplesperblock = G723_16_SAMPLES_PER_BLOCK ; + break ; + + case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */ + pstate->decoder = g723_24_decoder ; + *blocksize = G723_24_BYTES_PER_BLOCK ; + *samplesperblock = G723_24_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 3 ; + pstate->blocksize = G723_24_BYTES_PER_BLOCK ; + pstate->samplesperblock = G723_24_SAMPLES_PER_BLOCK ; + break ; + + case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */ + pstate->decoder = g721_decoder ; + *blocksize = G721_32_BYTES_PER_BLOCK ; + *samplesperblock = G721_32_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 4 ; + pstate->blocksize = G721_32_BYTES_PER_BLOCK ; + pstate->samplesperblock = G721_32_SAMPLES_PER_BLOCK ; + break ; + + case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */ + pstate->decoder = g723_40_decoder ; + *blocksize = G721_40_BYTES_PER_BLOCK ; + *samplesperblock = G721_40_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 5 ; + pstate->blocksize = G721_40_BYTES_PER_BLOCK ; + pstate->samplesperblock = G721_40_SAMPLES_PER_BLOCK ; + break ; + + default : + free (pstate) ; + return NULL ; + } ; + + return pstate ; +} /* g72x_reader_init */ + +struct g72x_state * g72x_writer_init (int codec, int *blocksize, int *samplesperblock) +{ G72x_STATE *pstate ; + + if ((pstate = g72x_state_new ()) == NULL) + return NULL ; + + private_init_state (pstate) ; + pstate->decoder = NULL ; + + switch (codec) + { case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */ + pstate->encoder = g723_16_encoder ; + *blocksize = G723_16_BYTES_PER_BLOCK ; + *samplesperblock = G723_16_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 2 ; + pstate->blocksize = G723_16_BYTES_PER_BLOCK ; + pstate->samplesperblock = G723_16_SAMPLES_PER_BLOCK ; + break ; + + case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */ + pstate->encoder = g723_24_encoder ; + *blocksize = G723_24_BYTES_PER_BLOCK ; + *samplesperblock = G723_24_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 3 ; + pstate->blocksize = G723_24_BYTES_PER_BLOCK ; + pstate->samplesperblock = G723_24_SAMPLES_PER_BLOCK ; + break ; + + case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */ + pstate->encoder = g721_encoder ; + *blocksize = G721_32_BYTES_PER_BLOCK ; + *samplesperblock = G721_32_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 4 ; + pstate->blocksize = G721_32_BYTES_PER_BLOCK ; + pstate->samplesperblock = G721_32_SAMPLES_PER_BLOCK ; + break ; + + case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */ + pstate->encoder = g723_40_encoder ; + *blocksize = G721_40_BYTES_PER_BLOCK ; + *samplesperblock = G721_40_SAMPLES_PER_BLOCK ; + pstate->codec_bits = 5 ; + pstate->blocksize = G721_40_BYTES_PER_BLOCK ; + pstate->samplesperblock = G721_40_SAMPLES_PER_BLOCK ; + break ; + + default : + free (pstate) ; + return NULL ; + } ; + + return pstate ; +} /* g72x_writer_init */ + +int g72x_decode_block (G72x_STATE *pstate, const unsigned char *block, short *samples) +{ int k, count ; + + count = unpack_bytes (pstate->codec_bits, pstate->blocksize, block, samples) ; + + for (k = 0 ; k < count ; k++) + samples [k] = pstate->decoder (samples [k], pstate) ; + + return 0 ; +} /* g72x_decode_block */ + +int g72x_encode_block (G72x_STATE *pstate, short *samples, unsigned char *block) +{ int k, count ; + + for (k = 0 ; k < pstate->samplesperblock ; k++) + samples [k] = pstate->encoder (samples [k], pstate) ; + + count = pack_bytes (pstate->codec_bits, samples, block) ; + + return count ; +} /* g72x_encode_block */ + +/* + * predictor_zero() + * + * computes the estimated signal from 6-zero predictor. + * + */ +int predictor_zero (G72x_STATE *state_ptr) +{ + int i; + int sezi; + + sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]); + for (i = 1; i < 6; i++) /* ACCUM */ + sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); + return (sezi); +} +/* + * predictor_pole() + * + * computes the estimated signal from 2-pole predictor. + * + */ +int predictor_pole(G72x_STATE *state_ptr) +{ + return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + + fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); +} +/* + * step_size() + * + * computes the quantization step size of the adaptive quantizer. + * + */ +int step_size (G72x_STATE *state_ptr) +{ + int y; + int dif; + int al; + + if (state_ptr->ap >= 256) + return (state_ptr->yu); + else { + y = state_ptr->yl >> 6; + dif = state_ptr->yu - y; + al = state_ptr->ap >> 2; + if (dif > 0) + y += (dif * al) >> 6; + else if (dif < 0) + y += (dif * al + 0x3F) >> 6; + return (y); + } +} + +/* + * quantize() + * + * Given a raw sample, 'd', of the difference signal and a + * quantization step size scale factor, 'y', this routine returns the + * ADPCM codeword to which that sample gets quantized. The step + * size scale factor division operation is done in the log base 2 domain + * as a subtraction. + */ +int quantize( + int d, /* Raw difference signal sample */ + int y, /* Step size multiplier */ + short *table, /* quantization table */ + int size) /* table size of short integers */ +{ + short dqm; /* Magnitude of 'd' */ + short expon; /* Integer part of base 2 log of 'd' */ + short mant; /* Fractional part of base 2 log */ + short dl; /* Log of magnitude of 'd' */ + short dln; /* Step size scale factor normalized log */ + int i; + + /* + * LOG + * + * Compute base 2 log of 'd', and store in 'dl'. + */ + dqm = abs(d); + expon = quan(dqm >> 1, power2, 15); + mant = ((dqm << 7) >> expon) & 0x7F; /* Fractional portion. */ + dl = (expon << 7) + mant; + + /* + * SUBTB + * + * "Divide" by step size multiplier. + */ + dln = dl - (y >> 2); + + /* + * QUAN + * + * Obtain codword i for 'd'. + */ + i = quan(dln, table, size); + if (d < 0) /* take 1's complement of i */ + return ((size << 1) + 1 - i); + else if (i == 0) /* take 1's complement of 0 */ + return ((size << 1) + 1); /* new in 1988 */ + else + return (i); +} +/* + * reconstruct() + * + * Returns reconstructed difference signal 'dq' obtained from + * codeword 'i' and quantization step size scale factor 'y'. + * Multiplication is performed in log base 2 domain as addition. + */ +int +reconstruct( + int sign, /* 0 for non-negative value */ + int dqln, /* G.72x codeword */ + int y) /* Step size multiplier */ +{ + short dql; /* Log of 'dq' magnitude */ + short dex; /* Integer part of log */ + short dqt; + short dq; /* Reconstructed difference signal sample */ + + dql = dqln + (y >> 2); /* ADDA */ + + if (dql < 0) { + return ((sign) ? -0x8000 : 0); + } else { /* ANTILOG */ + dex = (dql >> 7) & 15; + dqt = 128 + (dql & 127); + dq = (dqt << 7) >> (14 - dex); + return ((sign) ? (dq - 0x8000) : dq); + } +} + + +/* + * update() + * + * updates the state variables for each output code + */ +void +update( + int code_size, /* distinguish 723_40 with others */ + int y, /* quantizer step size */ + int wi, /* scale factor multiplier */ + int fi, /* for long/short term energies */ + int dq, /* quantized prediction difference */ + int sr, /* reconstructed signal */ + int dqsez, /* difference from 2-pole predictor */ + G72x_STATE *state_ptr) /* coder state pointer */ +{ + int cnt; + short mag, expon; /* Adaptive predictor, FLOAT A */ + short a2p = 0; /* LIMC */ + short a1ul; /* UPA1 */ + short pks1; /* UPA2 */ + short fa1; + char tr; /* tone/transition detector */ + short ylint, thr2, dqthr; + short ylfrac, thr1; + short pk0; + + pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ + + mag = dq & 0x7FFF; /* prediction difference magnitude */ + /* TRANS */ + ylint = state_ptr->yl >> 15; /* exponent part of yl */ + ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ + thr1 = (32 + ylfrac) << ylint; /* threshold */ + thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ + dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ + if (state_ptr->td == 0) /* signal supposed voice */ + tr = 0; + else if (mag <= dqthr) /* supposed data, but small mag */ + tr = 0; /* treated as voice */ + else /* signal is data (modem) */ + tr = 1; + + /* + * Quantizer scale factor adaptation. + */ + + /* FUNCTW & FILTD & DELAY */ + /* update non-steady state step size multiplier */ + state_ptr->yu = y + ((wi - y) >> 5); + + /* LIMB */ + if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ + state_ptr->yu = 544; + else if (state_ptr->yu > 5120) + state_ptr->yu = 5120; + + /* FILTE & DELAY */ + /* update steady state step size multiplier */ + state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); + + /* + * Adaptive predictor coefficients. + */ + if (tr == 1) { /* reset a's and b's for modem signal */ + state_ptr->a[0] = 0; + state_ptr->a[1] = 0; + state_ptr->b[0] = 0; + state_ptr->b[1] = 0; + state_ptr->b[2] = 0; + state_ptr->b[3] = 0; + state_ptr->b[4] = 0; + state_ptr->b[5] = 0; + } else { /* update a's and b's */ + pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ + + /* update predictor pole a[1] */ + a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); + if (dqsez != 0) { + fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; + if (fa1 < -8191) /* a2p = function of fa1 */ + a2p -= 0x100; + else if (fa1 > 8191) + a2p += 0xFF; + else + a2p += fa1 >> 5; + + if (pk0 ^ state_ptr->pk[1]) + { /* LIMC */ + if (a2p <= -12160) + a2p = -12288; + else if (a2p >= 12416) + a2p = 12288; + else + a2p -= 0x80; + } + else if (a2p <= -12416) + a2p = -12288; + else if (a2p >= 12160) + a2p = 12288; + else + a2p += 0x80; + } + + /* TRIGB & DELAY */ + state_ptr->a[1] = a2p; + + /* UPA1 */ + /* update predictor pole a[0] */ + state_ptr->a[0] -= state_ptr->a[0] >> 8; + if (dqsez != 0) + { if (pks1 == 0) + state_ptr->a[0] += 192; + else + state_ptr->a[0] -= 192; + } ; + + /* LIMD */ + a1ul = 15360 - a2p; + if (state_ptr->a[0] < -a1ul) + state_ptr->a[0] = -a1ul; + else if (state_ptr->a[0] > a1ul) + state_ptr->a[0] = a1ul; + + /* UPB : update predictor zeros b[6] */ + for (cnt = 0; cnt < 6; cnt++) { + if (code_size == 5) /* for 40Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9; + else /* for G.721 and 24Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; + if (dq & 0x7FFF) { /* XOR */ + if ((dq ^ state_ptr->dq[cnt]) >= 0) + state_ptr->b[cnt] += 128; + else + state_ptr->b[cnt] -= 128; + } + } + } + + for (cnt = 5; cnt > 0; cnt--) + state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; + /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ + if (mag == 0) { + state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20; + } else { + expon = quan(mag, power2, 15); + state_ptr->dq[0] = (dq >= 0) ? + (expon << 6) + ((mag << 6) >> expon) : + (expon << 6) + ((mag << 6) >> expon) - 0x400; + } + + state_ptr->sr[1] = state_ptr->sr[0]; + /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ + if (sr == 0) { + state_ptr->sr[0] = 0x20; + } else if (sr > 0) { + expon = quan(sr, power2, 15); + state_ptr->sr[0] = (expon << 6) + ((sr << 6) >> expon); + } else if (sr > -32768) { + mag = -sr; + expon = quan(mag, power2, 15); + state_ptr->sr[0] = (expon << 6) + ((mag << 6) >> expon) - 0x400; + } else + state_ptr->sr[0] = (short) 0xFC20; + + /* DELAY A */ + state_ptr->pk[1] = state_ptr->pk[0]; + state_ptr->pk[0] = pk0; + + /* TONE */ + if (tr == 1) /* this sample has been treated as data */ + state_ptr->td = 0; /* next one will be treated as voice */ + else if (a2p < -11776) /* small sample-to-sample correlation */ + state_ptr->td = 1; /* signal may be data */ + else /* signal is voice */ + state_ptr->td = 0; + + /* + * Adaptation speed control. + */ + state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ + state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ + + if (tr == 1) + state_ptr->ap = 256; + else if (y < 1536) /* SUBTC */ + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (state_ptr->td == 1) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= + (state_ptr->dml >> 3)) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else + state_ptr->ap += (-state_ptr->ap) >> 4; + + return ; +} /* update */ + +/*------------------------------------------------------------------------------ +*/ + +static int +unpack_bytes (int bits, int blocksize, const unsigned char * block, short * samples) +{ unsigned int in_buffer = 0 ; + unsigned char in_byte ; + int k, in_bits = 0, bindex = 0 ; + + for (k = 0 ; bindex <= blocksize && k < G72x_BLOCK_SIZE ; k++) + { if (in_bits < bits) + { in_byte = block [bindex++] ; + + in_buffer |= (in_byte << in_bits); + in_bits += 8; + } + samples [k] = in_buffer & ((1 << bits) - 1); + in_buffer >>= bits; + in_bits -= bits; + } ; + + return k ; +} /* unpack_bytes */ + +static int +pack_bytes (int bits, const short * samples, unsigned char * block) +{ + unsigned int out_buffer = 0 ; + int k, bindex = 0, out_bits = 0 ; + unsigned char out_byte ; + + for (k = 0 ; k < G72x_BLOCK_SIZE ; k++) + { out_buffer |= (samples [k] << out_bits) ; + out_bits += bits ; + if (out_bits >= 8) + { out_byte = out_buffer & 0xFF ; + out_bits -= 8 ; + out_buffer >>= 8 ; + block [bindex++] = out_byte ; + } + } ; + + return bindex ; +} /* pack_bytes */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 6298dc75-fd0f-4062-9b90-f73ed69f22d4 +*/ + diff --git a/nylsf/G72x/g72x.h b/nylsf/G72x/g72x.h new file mode 100644 index 0000000..e6319e6 --- /dev/null +++ b/nylsf/G72x/g72x.h @@ -0,0 +1,99 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** This file is not the same as the original file from Sun Microsystems. Nearly +** all the original definitions and function prototypes that were in the file +** of this name have been moved to g72x_priv.h. +*/ + +#ifndef G72X_HEADER_FILE +#define G72X_HEADER_FILE + +/* +** Number of samples per block to process. +** Must be a common multiple of possible bits per sample : 2, 3, 4, 5 and 8. +*/ +#define G72x_BLOCK_SIZE (3 * 5 * 8) + +/* +** Identifiers for the differing kinds of G72x ADPCM codecs. +** The identifiers also define the number of encoded bits per sample. +*/ + +enum +{ G723_16_BITS_PER_SAMPLE = 2, + G723_24_BITS_PER_SAMPLE = 3, + G723_40_BITS_PER_SAMPLE = 5, + + G721_32_BITS_PER_SAMPLE = 4, + G721_40_BITS_PER_SAMPLE = 5, + + G723_16_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE, + G723_24_SAMPLES_PER_BLOCK = G723_24_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_24_BITS_PER_SAMPLE), + G723_40_SAMPLES_PER_BLOCK = G723_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_40_BITS_PER_SAMPLE), + + G721_32_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE, + G721_40_SAMPLES_PER_BLOCK = G721_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G721_40_BITS_PER_SAMPLE), + + G723_16_BYTES_PER_BLOCK = (G723_16_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, + G723_24_BYTES_PER_BLOCK = (G723_24_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, + G723_40_BYTES_PER_BLOCK = (G723_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, + + G721_32_BYTES_PER_BLOCK = (G721_32_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, + G721_40_BYTES_PER_BLOCK = (G721_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8 +} ; + +/* Forward declaration of of g72x_state. */ + +struct g72x_state ; + +/* External function definitions. */ + +struct g72x_state * g72x_reader_init (int codec, int *blocksize, int *samplesperblock) ; +struct g72x_state * g72x_writer_init (int codec, int *blocksize, int *samplesperblock) ; +/* +** Initialize the ADPCM state table for the given codec. +** Return 0 on success, 1 on fail. +*/ + +int g72x_decode_block (struct g72x_state *pstate, const unsigned char *block, short *samples) ; +/* +** The caller fills data->block with data->bytes bytes before calling the +** function. The value data->bytes must be an integer multiple of +** data->blocksize and be <= data->max_bytes. +** When it returns, the caller can read out data->samples samples. +*/ + +int g72x_encode_block (struct g72x_state *pstate, short *samples, unsigned char *block) ; +/* +** The caller fills state->samples some integer multiple data->samples_per_block +** (up to G72x_BLOCK_SIZE) samples before calling the function. +** When it returns, the caller can read out bytes encoded bytes. +*/ + +#endif /* !G72X_HEADER_FILE */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 6ca84e5f-f932-4ba1-87ee-37056d921621 +*/ + diff --git a/nylsf/G72x/g72x_priv.h b/nylsf/G72x/g72x_priv.h new file mode 100644 index 0000000..a88e96d --- /dev/null +++ b/nylsf/G72x/g72x_priv.h @@ -0,0 +1,118 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#ifndef G72X_PRIVATE_H +#define G72X_PRIVATE_H + +#ifdef __cplusplus +#error "This code is not designed to be compiled with a C++ compiler." +#endif + +/* +** The following is the definition of the state structure used by the +** G.721/G.723 encoder and decoder to preserve their internal state +** between successive calls. The meanings of the majority of the state +** structure fields are explained in detail in the CCITT Recommendation +** G.721. The field names are essentially identical to variable names +** in the bit level description of the coding algorithm included in this +** Recommendation. +*/ + +struct g72x_state +{ long yl; /* Locked or steady state step size multiplier. */ + short yu; /* Unlocked or non-steady state step size multiplier. */ + short dms; /* Short term energy estimate. */ + short dml; /* Long term energy estimate. */ + short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ + + short a[2]; /* Coefficients of pole portion of prediction filter. */ + short b[6]; /* Coefficients of zero portion of prediction filter. */ + short pk[2]; /* + ** Signs of previous two samples of a partially + ** reconstructed signal. + **/ + short dq[6]; /* + ** Previous 6 samples of the quantized difference + ** signal represented in an internal floating point + ** format. + **/ + short sr[2]; /* + ** Previous 2 samples of the quantized difference + ** signal represented in an internal floating point + ** format. + */ + char td; /* delayed tone detect, new in 1988 version */ + + /* The following struct members were added for libsndfile. The original + ** code worked by calling a set of functions on a sample by sample basis + ** which is slow on architectures like Intel x86. For libsndfile, this + ** was changed so that the encoding and decoding routines could work on + ** a block of samples at a time to reduce the function call overhead. + */ + int (*encoder) (int, struct g72x_state* state) ; + int (*decoder) (int, struct g72x_state* state) ; + + int codec_bits, blocksize, samplesperblock ; +} ; + +typedef struct g72x_state G72x_STATE ; + +int predictor_zero (G72x_STATE *state_ptr); + +int predictor_pole (G72x_STATE *state_ptr); + +int step_size (G72x_STATE *state_ptr); + +int quantize (int d, int y, short *table, int size); + +int reconstruct (int sign, int dqln, int y); + +void update (int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, G72x_STATE *state_ptr); + +int g721_encoder (int sample, G72x_STATE *state_ptr); +int g721_decoder (int code, G72x_STATE *state_ptr); + +int g723_16_encoder (int sample, G72x_STATE *state_ptr); +int g723_16_decoder (int code, G72x_STATE *state_ptr); + +int g723_24_encoder (int sample, G72x_STATE *state_ptr); +int g723_24_decoder (int code, G72x_STATE *state_ptr); + +int g723_40_encoder (int sample, G72x_STATE *state_ptr); +int g723_40_decoder (int code, G72x_STATE *state_ptr); + +void private_init_state (G72x_STATE *state_ptr) ; + +#endif /* G72X_PRIVATE_H */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: d9ad4da7-0fa3-471d-8020-720b5cfb5e5b +*/ + diff --git a/nylsf/G72x/g72x_test.c b/nylsf/G72x/g72x_test.c new file mode 100644 index 0000000..caf5846 --- /dev/null +++ b/nylsf/G72x/g72x_test.c @@ -0,0 +1,222 @@ +/* +** Copyright (C) 1999-2004 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include + +#include "g72x.h" +#include "g72x_priv.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338 +#endif + +#define BUFFER_SIZE (1<<14) /* Should be (1<<14) */ +#define SAMPLE_RATE 11025 + + +static void g721_test (void) ; +static void g723_test (double margin) ; + +static void gen_signal_double (double *data, double scale, int datalen) ; +static int error_function (double data, double orig, double margin) ; + +static int oct_save_short (short *a, short *b, int len) ; + +int +main (int argc, char *argv []) +{ int bDoAll = 0 ; + int nTests = 0 ; + + if (argc != 2) + { printf ("Usage : %s \n", argv [0]) ; + printf (" Where is one of the following:\n") ; + printf (" g721 - test G721 encoder and decoder\n") ; + printf (" g723 - test G721 encoder and decoder\n") ; + printf (" all - perform all tests\n") ; + exit (1) ; + } ; + + bDoAll=!strcmp (argv [1], "all"); + + if (bDoAll || ! strcmp (argv [1], "g721")) + { g721_test () ; + nTests++ ; + } ; + + if (bDoAll || ! strcmp (argv [1], "g723")) + { g723_test (0.53) ; + nTests++ ; + } ; + + if (nTests == 0) + { printf ("Mono : ************************************\n") ; + printf ("Mono : * No '%s' test defined.\n", argv [1]) ; + printf ("Mono : ************************************\n") ; + return 1 ; + } ; + + return 0 ; +} /* main */ + +static void +g721_test (void) +{ + return ; +} /* g721_test */ + +static void +g723_test (double margin) +{ static double orig_buffer [BUFFER_SIZE] ; + static short orig [BUFFER_SIZE] ; + static short data [BUFFER_SIZE] ; + + G72x_STATE encoder_state, decoder_state ; + + long k ; + int code, position, max_err ; + + private_init_state (&encoder_state) ; + encoder_state.encoder = g723_24_encoder ; + encoder_state.codec_bits = 3 ; + + private_init_state (&decoder_state) ; + decoder_state.decoder = g723_24_decoder ; + decoder_state.codec_bits = 3 ; + + memset (data, 0, BUFFER_SIZE * sizeof (short)) ; + memset (orig, 0, BUFFER_SIZE * sizeof (short)) ; + + printf (" g723_test : ") ; + fflush (stdout) ; + + gen_signal_double (orig_buffer, 32000.0, BUFFER_SIZE) ; + for (k = 0 ; k < BUFFER_SIZE ; k++) + orig [k] = (short) orig_buffer [k] ; + + /* Write and read data here. */ + position = 0 ; + max_err = 0 ; + for (k = 0 ; k < BUFFER_SIZE ; k++) + { code = encoder_state.encoder (orig [k], &encoder_state) ; + data [k] = decoder_state.decoder (code, &decoder_state) ; + if (abs (orig [k] - data [k]) > max_err) + { position = k ; + max_err = abs (orig [k] - data [k]) ; + } ; + } ; + + printf ("\n\nMax error of %d at postion %d.\n", max_err, position) ; + + for (k = 0 ; k < BUFFER_SIZE ; k++) + { if (error_function (data [k], orig [k], margin)) + { printf ("Line %d: Incorrect sample A (#%ld : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ; + oct_save_short (orig, data, BUFFER_SIZE) ; + exit (1) ; + } ; + } ; + + + printf ("ok\n") ; + + return ; +} /* g723_test */ + + +#define SIGNAL_MAXVAL 30000.0 +#define DECAY_COUNT 1000 + +static void +gen_signal_double (double *gendata, double scale, int gendatalen) +{ int k, ramplen ; + double amp = 0.0 ; + + ramplen = DECAY_COUNT ; + + for (k = 0 ; k < gendatalen ; k++) + { if (k <= ramplen) + amp = scale * k / ((double) ramplen) ; + else if (k > gendatalen - ramplen) + amp = scale * (gendatalen - k) / ((double) ramplen) ; + + gendata [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE)) + + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ; + } ; + + return ; +} /* gen_signal_double */ + +static int +error_function (double data, double orig, double margin) +{ double error ; + + if (fabs (orig) <= 500.0) + error = fabs (fabs (data) - fabs(orig)) / 2000.0 ; + else if (fabs (orig) <= 1000.0) + error = fabs (data - orig) / 3000.0 ; + else + error = fabs (data - orig) / fabs (orig) ; + + if (error > margin) + { printf ("\n\n*******************\nError : %f\n", error) ; + return 1 ; + } ; + return 0 ; +} /* error_function */ + +static int +oct_save_short (short *a, short *b, int len) +{ FILE *file ; + int k ; + + if (! (file = fopen ("error.dat", "w"))) + return 1 ; + + fprintf (file, "# Not created by Octave\n") ; + + fprintf (file, "# name: a\n") ; + fprintf (file, "# type: matrix\n") ; + fprintf (file, "# rows: %d\n", len) ; + fprintf (file, "# columns: 1\n") ; + + for (k = 0 ; k < len ; k++) + fprintf (file, "% d\n", a [k]) ; + + fprintf (file, "# name: b\n") ; + fprintf (file, "# type: matrix\n") ; + fprintf (file, "# rows: %d\n", len) ; + fprintf (file, "# columns: 1\n") ; + + for (k = 0 ; k < len ; k++) + fprintf (file, "% d\n", b [k]) ; + + fclose (file) ; + return 0 ; +} /* oct_save_short */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 0597b442-a5b0-4abf-92a4-92f6c24e85a6 +*/ + diff --git a/nylsf/GSM610/README b/nylsf/GSM610/README new file mode 100644 index 0000000..b57132b --- /dev/null +++ b/nylsf/GSM610/README @@ -0,0 +1,36 @@ +GSM 06.10 13 kbit/s RPE/LTP speech codec +---------------------------------------- + +All the file in this directory were written by Jutta Degener +and Carsten Borman for The Communications and Operating Systems +Research Group (KBS) at the Technische Universitaet Berlin. + +Their work was released under the following license which is +assumed to be compatible with The GNU Lesser General Public License. + +---------------------------------------------------------------------------- + +Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, +Technische Universitaet Berlin + +Any use of this software is permitted provided that this notice is not +removed and that neither the authors nor the Technische Universitaet Berlin +are deemed to have made any representations as to the suitability of this +software for any purpose nor are held responsible for any defects of +this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + +As a matter of courtesy, the authors request to be informed about uses +this software has found, about bugs in this software, and about any +improvements that may be of general interest. + +Berlin, 28.11.1994 +Jutta Degener (jutta@cs.tu-berlin.de) +Carsten Bormann (cabo@cs.tu-berlin.de) + +---------------------------------------------------------------------------- + +Jutta Degener and Carsten Bormann's work can be found on their homepage +at: + + http://kbs.cs.tu-berlin.de/~jutta/toast.html + diff --git a/nylsf/GSM610/add.c b/nylsf/GSM610/add.c new file mode 100644 index 0000000..613ed57 --- /dev/null +++ b/nylsf/GSM610/add.c @@ -0,0 +1,249 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* + * See private.h for the more commonly used macro versions. + */ + +#include +#include + +#include "config.h" // RBD +#include "gsm610_priv.h" +#include "gsm.h" + +#define saturate(x) \ + ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) + +word gsm_add ( word a, word b) +{ + longword sum = (longword)a + (longword)b; + return saturate(sum); +} + +word gsm_sub ( word a, word b) +{ + longword diff = (longword)a - (longword)b; + return saturate(diff); +} + +word gsm_mult ( word a, word b) +{ + if (a == MIN_WORD && b == MIN_WORD) + return MAX_WORD; + + return SASR_L( (longword)a * (longword)b, 15 ); +} + +word gsm_mult_r ( word a, word b) +{ + if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; + else { + longword prod = (longword)a * (longword)b + 16384; + prod >>= 15; + return prod & 0xFFFF; + } +} + +word gsm_abs (word a) +{ + return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; +} + +longword gsm_L_mult (word a, word b) +{ + assert( a != MIN_WORD || b != MIN_WORD ); + return ((longword)a * (longword)b) << 1; +} + +longword gsm_L_add ( longword a, longword b) +{ + if (a < 0) { + if (b >= 0) return a + b; + else { + ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); + return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; + } + } + else if (b <= 0) return a + b; + else { + ulongword A = (ulongword)a + (ulongword)b; + return A > MAX_LONGWORD ? MAX_LONGWORD : A; + } +} + +longword gsm_L_sub ( longword a, longword b) +{ + if (a >= 0) { + if (b >= 0) return a - b; + else { + /* a>=0, b<0 */ + + ulongword A = (ulongword)a + -(b + 1); + return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); + } + } + else if (b <= 0) return a - b; + else { + /* a<0, b>0 */ + + ulongword A = (ulongword)-(a + 1) + b; + return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; + } +} + +static unsigned char const bitoff[ 256 ] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +word gsm_norm (longword a ) +/* + * the number of left shifts needed to normalize the 32 bit + * variable L_var1 for positive values on the interval + * + * with minimum of + * minimum of 1073741824 (01000000000000000000000000000000) and + * maximum of 2147483647 (01111111111111111111111111111111) + * + * + * and for negative values on the interval with + * minimum of -2147483648 (-10000000000000000000000000000000) and + * maximum of -1073741824 ( -1000000000000000000000000000000). + * + * in order to normalize the result, the following + * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); + * + * (That's 'ffs', only from the left, not the right..) + */ +{ + assert(a != 0); + + if (a < 0) { + if (a <= -1073741824) return 0; + a = ~a; + } + + return a & 0xffff0000 + ? ( a & 0xff000000 + ? -1 + bitoff[ 0xFF & (a >> 24) ] + : 7 + bitoff[ 0xFF & (a >> 16) ] ) + : ( a & 0xff00 + ? 15 + bitoff[ 0xFF & (a >> 8) ] + : 23 + bitoff[ 0xFF & a ] ); +} + +longword gsm_L_asl (longword a, int n) +{ + if (n >= 32) return 0; + if (n <= -32) return -(a < 0); + if (n < 0) return gsm_L_asr(a, -n); + return a << n; +} + +word gsm_asr (word a, int n) +{ + if (n >= 16) return -(a < 0); + if (n <= -16) return 0; + if (n < 0) return a << -n; + + return SASR_W (a, (word) n); +} + +word gsm_asl (word a, int n) +{ + if (n >= 16) return 0; + if (n <= -16) return -(a < 0); + if (n < 0) return gsm_asr(a, -n); + return a << n; +} + +longword gsm_L_asr (longword a, int n) +{ + if (n >= 32) return -(a < 0); + if (n <= -32) return 0; + if (n < 0) return a << -n; + + return SASR_L (a, (word) n); +} + +/* +** word gsm_asr (word a, int n) +** { +** if (n >= 16) return -(a < 0); +** if (n <= -16) return 0; +** if (n < 0) return a << -n; +** +** # ifdef SASR_W +** return a >> n; +** # else +** if (a >= 0) return a >> n; +** else return -(word)( -(uword)a >> n ); +** # endif +** } +** +*/ +/* + * (From p. 46, end of section 4.2.5) + * + * NOTE: The following lines gives [sic] one correct implementation + * of the div(num, denum) arithmetic operation. Compute div + * which is the integer division of num by denum: with denum + * >= num > 0 + */ + +word gsm_div (word num, word denum) +{ + longword L_num = num; + longword L_denum = denum; + word div = 0; + int k = 15; + + /* The parameter num sometimes becomes zero. + * Although this is explicitly guarded against in 4.2.5, + * we assume that the result should then be zero as well. + */ + + /* assert(num != 0); */ + + assert(num >= 0 && denum >= num); + if (num == 0) + return 0; + + while (k--) { + div <<= 1; + L_num <<= 1; + + if (L_num >= L_denum) { + L_num -= L_denum; + div++; + } + } + + return div; +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: a7398579-e2e1-4733-aa2d-4c6efc0c58ff +*/ + diff --git a/nylsf/GSM610/code.c b/nylsf/GSM610/code.c new file mode 100644 index 0000000..02ec75b --- /dev/null +++ b/nylsf/GSM610/code.c @@ -0,0 +1,97 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + + +#include +#include + +#include "config.h" + +#include "gsm610_priv.h" +#include "gsm.h" + +/* + * 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER + */ + +void Gsm_Coder ( + + struct gsm_state * State, + + word * s, /* [0..159] samples IN */ + +/* + * The RPE-LTD coder works on a frame by frame basis. The length of + * the frame is equal to 160 samples. Some computations are done + * once per frame to produce at the output of the coder the + * LARc[1..8] parameters which are the coded LAR coefficients and + * also to realize the inverse filtering operation for the entire + * frame (160 samples of signal d[0..159]). These parts produce at + * the output of the coder: + */ + + word * LARc, /* [0..7] LAR coefficients OUT */ + +/* + * Procedure 4.2.11 to 4.2.18 are to be executed four times per + * frame. That means once for each sub-segment RPE-LTP analysis of + * 40 samples. These parts produce at the output of the coder: + */ + + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc /* [13*4] normalized RPE samples OUT */ +) +{ + int k; + word * dp = State->dp0 + 120; /* [ -120...-1 ] */ + word * dpp = dp; /* [ 0...39 ] */ + + word so[160]; + + Gsm_Preprocess (State, s, so); + Gsm_LPC_Analysis (State, so, LARc); + Gsm_Short_Term_Analysis_Filter (State, LARc, so); + + for (k = 0; k <= 3; k++, xMc += 13) { + + Gsm_Long_Term_Predictor ( State, + so+k*40, /* d [0..39] IN */ + dp, /* dp [-120..-1] IN */ + State->e + 5, /* e [0..39] OUT */ + dpp, /* dpp [0..39] OUT */ + Nc++, + bc++); + + Gsm_RPE_Encoding ( /*-S,-*/ + State->e + 5, /* e ][0..39][ IN/OUT */ + xmaxc++, Mc++, xMc ); + /* + * Gsm_Update_of_reconstructed_short_time_residual_signal + * ( dpp, e + 5, dp ); + */ + + { register int i; + for (i = 0; i <= 39; i++) + dp[ i ] = GSM_ADD( State->e[5 + i], dpp[i] ); + } + dp += 40; + dpp += 40; + + } + (void)memcpy( (char *)State->dp0, (char *)(State->dp0 + 160), + 120 * sizeof(*State->dp0) ); +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: ae8ef1b2-5a1e-4263-94cd-42b15dca81a3 +*/ + diff --git a/nylsf/GSM610/decode.c b/nylsf/GSM610/decode.c new file mode 100644 index 0000000..b47d1fe --- /dev/null +++ b/nylsf/GSM610/decode.c @@ -0,0 +1,69 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include + +#include "config.h" // RBD + +#include "gsm610_priv.h" +#include "gsm.h" + +/* + * 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER + */ + +static void Postprocessing ( + struct gsm_state * S, + register word * s) +{ + register int k; + register word msr = S->msr; + register word tmp; + + for (k = 160; k--; s++) { + tmp = GSM_MULT_R( msr, 28180 ); + msr = GSM_ADD(*s, tmp); /* Deemphasis */ + *s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */ + } + S->msr = msr; +} + +void Gsm_Decoder ( + struct gsm_state * S, + + word * LARcr, /* [0..7] IN */ + + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + + word * s) /* [0..159] OUT */ +{ + int j, k; + word erp[40], wt[160]; + word * drp = S->dp0 + 120; + + for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) { + + Gsm_RPE_Decoding( /*-S,-*/ *xmaxcr, *Mcr, xMcr, erp ); + Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp ); + + for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ]; + } + + Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s ); + Postprocessing(S, s); +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 11ae5b90-2e8b-400b-ac64-a69a1fc6cc41 +*/ + diff --git a/nylsf/GSM610/gsm.h b/nylsf/GSM610/gsm.h new file mode 100644 index 0000000..a13a606 --- /dev/null +++ b/nylsf/GSM610/gsm.h @@ -0,0 +1,58 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#ifndef GSM_H +#define GSM_H + +#include /* for FILE * */ + +/* + * Interface + */ + +typedef struct gsm_state * gsm; +typedef short gsm_signal; /* signed 16 bit */ +typedef unsigned char gsm_byte; +typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */ + +#define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */ + +#define GSM_PATCHLEVEL 10 +#define GSM_MINOR 0 +#define GSM_MAJOR 1 + +#define GSM_OPT_VERBOSE 1 +#define GSM_OPT_FAST 2 +#define GSM_OPT_LTP_CUT 3 +#define GSM_OPT_WAV49 4 +#define GSM_OPT_FRAME_INDEX 5 +#define GSM_OPT_FRAME_CHAIN 6 + +gsm gsm_create (void); + +/* Added for libsndfile : May 6, 2002 */ +void gsm_init (gsm); + +void gsm_destroy (gsm); + +int gsm_print (FILE *, gsm, gsm_byte *); +int gsm_option (gsm, int, int *); + +void gsm_encode (gsm, gsm_signal *, gsm_byte *); +int gsm_decode (gsm, gsm_byte *, gsm_signal *); + +int gsm_explode (gsm, gsm_byte *, gsm_signal *); +void gsm_implode (gsm, gsm_signal *, gsm_byte *); + +#endif /* GSM_H */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 8cfc7698-5433-4b6f-aeca-967c6fda4dec +*/ + diff --git a/nylsf/GSM610/gsm610_priv.h b/nylsf/GSM610/gsm610_priv.h new file mode 100644 index 0000000..3ebec31 --- /dev/null +++ b/nylsf/GSM610/gsm610_priv.h @@ -0,0 +1,312 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#ifndef PRIVATE_H +#define PRIVATE_H + +/* Added by Erik de Castro Lopo */ +#define USE_FLOAT_MUL +#define FAST +#define WAV49 + +#ifdef __cplusplus +#error "This code is not designed to be compiled with a C++ compiler." +#endif +/* Added by Erik de Castro Lopo */ + +#if defined(_MSC_VER) && _MSC_VER >= 1500 +// Visual C++ 2008 or beyond +#define inline __inline +#endif + + +typedef short word; /* 16 bit signed int */ +typedef int longword; /* 32 bit signed int */ + +typedef unsigned short uword; /* unsigned word */ +typedef unsigned int ulongword; /* unsigned longword */ + +struct gsm_state +{ word dp0[ 280 ] ; + + word z1; /* preprocessing.c, Offset_com. */ + longword L_z2; /* Offset_com. */ + int mp; /* Preemphasis */ + + word u[8] ; /* short_term_aly_filter.c */ + word LARpp[2][8] ; /* */ + word j; /* */ + + word ltp_cut; /* long_term.c, LTP crosscorr. */ + word nrp; /* 40 */ /* long_term.c, synthesis */ + word v[9] ; /* short_term.c, synthesis */ + word msr; /* decoder.c, Postprocessing */ + + char verbose; /* only used if !NDEBUG */ + char fast; /* only used if FAST */ + + char wav_fmt; /* only used if WAV49 defined */ + unsigned char frame_index; /* odd/even chaining */ + unsigned char frame_chain; /* half-byte to carry forward */ + + /* Moved here from code.c where it was defined as static */ + word e[50] ; +} ; + +typedef struct gsm_state GSM_STATE ; + +#define MIN_WORD (-32767 - 1) +#define MAX_WORD 32767 + +#define MIN_LONGWORD (-2147483647 - 1) +#define MAX_LONGWORD 2147483647 + +/* Signed arithmetic shift right. */ +static inline word +SASR_W (word x, word by) +{ return (x >> by) ; +} /* SASR */ + +static inline longword +SASR_L (longword x, word by) +{ return (x >> by) ; +} /* SASR */ + +/* + * Prototypes from add.c + */ +word gsm_mult (word a, word b) ; +longword gsm_L_mult (word a, word b) ; +word gsm_mult_r (word a, word b) ; + +word gsm_div (word num, word denum) ; + +word gsm_add (word a, word b ) ; +longword gsm_L_add (longword a, longword b ) ; + +word gsm_sub (word a, word b) ; +longword gsm_L_sub (longword a, longword b) ; + +word gsm_abs (word a) ; + +word gsm_norm (longword a ) ; + +longword gsm_L_asl (longword a, int n) ; +word gsm_asl (word a, int n) ; + +longword gsm_L_asr (longword a, int n) ; +word gsm_asr (word a, int n) ; + +/* + * Inlined functions from add.h + */ + +static inline longword +GSM_MULT_R (word a, word b) +{ return (((longword) (a)) * ((longword) (b)) + 16384) >> 15 ; +} /* GSM_MULT_R */ + +static inline longword +GSM_MULT (word a, word b) +{ return (((longword) (a)) * ((longword) (b))) >> 15 ; +} /* GSM_MULT */ + +static inline longword +GSM_L_MULT (word a, word b) +{ return ((longword) (a)) * ((longword) (b)) << 1 ; +} /* GSM_L_MULT */ + +static inline longword +GSM_L_ADD (longword a, longword b) +{ ulongword utmp ; + + if (a < 0 && b < 0) + { utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1) ; + return (utmp >= (ulongword) MAX_LONGWORD) ? MIN_LONGWORD : -(longword)utmp-2 ; + } ; + + if (a > 0 && b > 0) + { utmp = (ulongword) a + (ulongword) b ; + return (utmp >= (ulongword) MAX_LONGWORD) ? MAX_LONGWORD : utmp ; + } ; + + return a + b ; +} /* GSM_L_ADD */ + +static inline longword +GSM_ADD (word a, word b) +{ longword ltmp ; + + ltmp = ((longword) a) + ((longword) b) ; + + if (ltmp >= MAX_WORD) + return MAX_WORD ; + if (ltmp <= MIN_WORD) + return MIN_WORD ; + + return ltmp ; +} /* GSM_ADD */ + +static inline longword +GSM_SUB (word a, word b) +{ longword ltmp ; + + ltmp = ((longword) a) - ((longword) b) ; + + if (ltmp >= MAX_WORD) + ltmp = MAX_WORD ; + else if (ltmp <= MIN_WORD) + ltmp = MIN_WORD ; + + return ltmp ; +} /* GSM_SUB */ + +static inline word +GSM_ABS (word a) +{ + if (a > 0) + return a ; + if (a == MIN_WORD) + return MAX_WORD ; + return -a ; +} /* GSM_ADD */ + + +/* + * More prototypes from implementations.. + */ +void Gsm_Coder ( + struct gsm_state * S, + word * s, /* [0..159] samples IN */ + word * LARc, /* [0..7] LAR coefficients OUT */ + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc) ;/* [13*4] normalized RPE samples OUT */ + +void Gsm_Long_Term_Predictor ( /* 4x for 160 samples */ + struct gsm_state * S, + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + word * e, /* [0..40] OUT */ + word * dpp, /* [0..40] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc) ; /* gain factor OUT */ + +void Gsm_LPC_Analysis ( + struct gsm_state * S, + word * s, /* 0..159 signals IN/OUT */ + word * LARc) ; /* 0..7 LARc's OUT */ + +void Gsm_Preprocess ( + struct gsm_state * S, + word * s, word * so) ; + +void Gsm_Encoding ( + struct gsm_state * S, + word * e, + word * ep, + word * xmaxc, + word * Mc, + word * xMc) ; + +void Gsm_Short_Term_Analysis_Filter ( + struct gsm_state * S, + word * LARc, /* coded log area ratio [0..7] IN */ + word * d) ; /* st res. signal [0..159] IN/OUT */ + +void Gsm_Decoder ( + struct gsm_state * S, + word * LARcr, /* [0..7] IN */ + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + word * s) ; /* [0..159] OUT */ + +void Gsm_Decoding ( + struct gsm_state * S, + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12] IN */ + word * erp) ; /* [0..39] OUT */ + +void Gsm_Long_Term_Synthesis_Filtering ( + struct gsm_state* S, + word Ncr, + word bcr, + word * erp, /* [0..39] IN */ + word * drp) ; /* [-120..-1] IN, [0..40] OUT */ + +void Gsm_RPE_Decoding ( + /*-struct gsm_state *S,-*/ + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp) ; /* [0..39] OUT */ + +void Gsm_RPE_Encoding ( + /*-struct gsm_state * S,-*/ + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc) ; /* [0..12] OUT */ + +void Gsm_Short_Term_Synthesis_Filter ( + struct gsm_state * S, + word * LARcr, /* log area ratios [0..7] IN */ + word * drp, /* received d [0...39] IN */ + word * s) ; /* signal s [0..159] OUT */ + +void Gsm_Update_of_reconstructed_short_time_residual_signal ( + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp) ; /* [-120...-1] IN/OUT */ + +/* + * Tables from table.c + */ +#ifndef GSM_TABLE_C + +extern word gsm_A [8], gsm_B [8], gsm_MIC [8], gsm_MAC [8] ; +extern word gsm_INVA [8] ; +extern word gsm_DLB [4], gsm_QLB [4] ; +extern word gsm_H [11] ; +extern word gsm_NRFAC [8] ; +extern word gsm_FAC [8] ; + +#endif /* GSM_TABLE_C */ + +/* + * Debugging + */ +#ifdef NDEBUG + +# define gsm_debug_words(a, b, c, d) /* nil */ +# define gsm_debug_longwords(a, b, c, d) /* nil */ +# define gsm_debug_word(a, b) /* nil */ +# define gsm_debug_longword(a, b) /* nil */ + +#else /* !NDEBUG => DEBUG */ + + void gsm_debug_words (char * name, int, int, word *) ; + void gsm_debug_longwords (char * name, int, int, longword *) ; + void gsm_debug_longword (char * name, longword) ; + void gsm_debug_word (char * name, word) ; + +#endif /* !NDEBUG */ + +#endif /* PRIVATE_H */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 8bc5fdf2-e8c8-4686-9bd7-a30b512bef0c +*/ + diff --git a/nylsf/GSM610/gsm_create.c b/nylsf/GSM610/gsm_create.c new file mode 100644 index 0000000..94e8d7d --- /dev/null +++ b/nylsf/GSM610/gsm_create.c @@ -0,0 +1,44 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include + + + +#include "gsm.h" +#include "gsm610_priv.h" + +gsm gsm_create (void) +{ + gsm r; + + r = malloc (sizeof(struct gsm_state)); + if (!r) return r; + + memset((char *)r, 0, sizeof (struct gsm_state)); + r->nrp = 40; + + return r; +} + +/* Added for libsndfile : May 6, 2002. Not sure if it works. */ +void gsm_init (gsm state) +{ + memset (state, 0, sizeof (struct gsm_state)) ; + state->nrp = 40 ; +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 9fedb6b3-ed99-40c2-aac1-484c536261fe +*/ + diff --git a/nylsf/GSM610/gsm_decode.c b/nylsf/GSM610/gsm_decode.c new file mode 100644 index 0000000..668cfdc --- /dev/null +++ b/nylsf/GSM610/gsm_decode.c @@ -0,0 +1,368 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include "config.h" // RBD + +#include "gsm610_priv.h" + +#include "gsm.h" + +int gsm_decode (gsm s, gsm_byte * c, gsm_signal * target) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + + s->frame_index = !s->frame_index; + if (s->frame_index) { + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + } + } + else +#endif + { + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ + LARc[0] |= (*c >> 6) & 0x3; + LARc[1] = *c++ & 0x3F; + LARc[2] = (*c >> 3) & 0x1F; + LARc[3] = (*c++ & 0x7) << 2; + LARc[3] |= (*c >> 6) & 0x3; + LARc[4] = (*c >> 2) & 0xF; + LARc[5] = (*c++ & 0x3) << 2; + LARc[5] |= (*c >> 6) & 0x3; + LARc[6] = (*c >> 3) & 0x7; + LARc[7] = *c++ & 0x7; + Nc[0] = (*c >> 1) & 0x7F; + bc[0] = (*c++ & 0x1) << 1; + bc[0] |= (*c >> 7) & 0x1; + Mc[0] = (*c >> 5) & 0x3; + xmaxc[0] = (*c++ & 0x1F) << 1; + xmaxc[0] |= (*c >> 7) & 0x1; + xmc[0] = (*c >> 4) & 0x7; + xmc[1] = (*c >> 1) & 0x7; + xmc[2] = (*c++ & 0x1) << 2; + xmc[2] |= (*c >> 6) & 0x3; + xmc[3] = (*c >> 3) & 0x7; + xmc[4] = *c++ & 0x7; + xmc[5] = (*c >> 5) & 0x7; + xmc[6] = (*c >> 2) & 0x7; + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ + xmc[7] |= (*c >> 7) & 0x1; + xmc[8] = (*c >> 4) & 0x7; + xmc[9] = (*c >> 1) & 0x7; + xmc[10] = (*c++ & 0x1) << 2; + xmc[10] |= (*c >> 6) & 0x3; + xmc[11] = (*c >> 3) & 0x7; + xmc[12] = *c++ & 0x7; + Nc[1] = (*c >> 1) & 0x7F; + bc[1] = (*c++ & 0x1) << 1; + bc[1] |= (*c >> 7) & 0x1; + Mc[1] = (*c >> 5) & 0x3; + xmaxc[1] = (*c++ & 0x1F) << 1; + xmaxc[1] |= (*c >> 7) & 0x1; + xmc[13] = (*c >> 4) & 0x7; + xmc[14] = (*c >> 1) & 0x7; + xmc[15] = (*c++ & 0x1) << 2; + xmc[15] |= (*c >> 6) & 0x3; + xmc[16] = (*c >> 3) & 0x7; + xmc[17] = *c++ & 0x7; + xmc[18] = (*c >> 5) & 0x7; + xmc[19] = (*c >> 2) & 0x7; + xmc[20] = (*c++ & 0x3) << 1; + xmc[20] |= (*c >> 7) & 0x1; + xmc[21] = (*c >> 4) & 0x7; + xmc[22] = (*c >> 1) & 0x7; + xmc[23] = (*c++ & 0x1) << 2; + xmc[23] |= (*c >> 6) & 0x3; + xmc[24] = (*c >> 3) & 0x7; + xmc[25] = *c++ & 0x7; + Nc[2] = (*c >> 1) & 0x7F; + bc[2] = (*c++ & 0x1) << 1; /* 20 */ + bc[2] |= (*c >> 7) & 0x1; + Mc[2] = (*c >> 5) & 0x3; + xmaxc[2] = (*c++ & 0x1F) << 1; + xmaxc[2] |= (*c >> 7) & 0x1; + xmc[26] = (*c >> 4) & 0x7; + xmc[27] = (*c >> 1) & 0x7; + xmc[28] = (*c++ & 0x1) << 2; + xmc[28] |= (*c >> 6) & 0x3; + xmc[29] = (*c >> 3) & 0x7; + xmc[30] = *c++ & 0x7; + xmc[31] = (*c >> 5) & 0x7; + xmc[32] = (*c >> 2) & 0x7; + xmc[33] = (*c++ & 0x3) << 1; + xmc[33] |= (*c >> 7) & 0x1; + xmc[34] = (*c >> 4) & 0x7; + xmc[35] = (*c >> 1) & 0x7; + xmc[36] = (*c++ & 0x1) << 2; + xmc[36] |= (*c >> 6) & 0x3; + xmc[37] = (*c >> 3) & 0x7; + xmc[38] = *c++ & 0x7; + Nc[3] = (*c >> 1) & 0x7F; + bc[3] = (*c++ & 0x1) << 1; + bc[3] |= (*c >> 7) & 0x1; + Mc[3] = (*c >> 5) & 0x3; + xmaxc[3] = (*c++ & 0x1F) << 1; + xmaxc[3] |= (*c >> 7) & 0x1; + xmc[39] = (*c >> 4) & 0x7; + xmc[40] = (*c >> 1) & 0x7; + xmc[41] = (*c++ & 0x1) << 2; + xmc[41] |= (*c >> 6) & 0x3; + xmc[42] = (*c >> 3) & 0x7; + xmc[43] = *c++ & 0x7; /* 30 */ + xmc[44] = (*c >> 5) & 0x7; + xmc[45] = (*c >> 2) & 0x7; + xmc[46] = (*c++ & 0x3) << 1; + xmc[46] |= (*c >> 7) & 0x1; + xmc[47] = (*c >> 4) & 0x7; + xmc[48] = (*c >> 1) & 0x7; + xmc[49] = (*c++ & 0x1) << 2; + xmc[49] |= (*c >> 6) & 0x3; + xmc[50] = (*c >> 3) & 0x7; + xmc[51] = *c & 0x7; /* 33 */ + } + + Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target); + + return 0; +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 6a9b6628-821c-4a96-84c1-485ebd35f170 +*/ + diff --git a/nylsf/GSM610/gsm_destroy.c b/nylsf/GSM610/gsm_destroy.c new file mode 100644 index 0000000..9e2d6a4 --- /dev/null +++ b/nylsf/GSM610/gsm_destroy.c @@ -0,0 +1,31 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include "gsm.h" +#include "config.h" + +#ifdef HAS_STDLIB_H +# include +#else +# ifdef HAS_MALLOC_H +# include +# else + extern void free(); +# endif +#endif + +void gsm_destroy (gsm S) +{ + if (S) free((char *)S); +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: f423d09b-6ccc-47e0-9b18-ee1cf7a8e473 +*/ + diff --git a/nylsf/GSM610/gsm_encode.c b/nylsf/GSM610/gsm_encode.c new file mode 100644 index 0000000..f04674e --- /dev/null +++ b/nylsf/GSM610/gsm_encode.c @@ -0,0 +1,458 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include "config.h" // RBD + +#include "gsm610_priv.h" +#include "gsm.h" + +void gsm_encode (gsm s, gsm_signal * source, gsm_byte * c) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); + + + /* variable size + + GSM_MAGIC 4 + + LARc[0] 6 + LARc[1] 6 + LARc[2] 5 + LARc[3] 5 + LARc[4] 4 + LARc[5] 4 + LARc[6] 3 + LARc[7] 3 + + Nc[0] 7 + bc[0] 2 + Mc[0] 2 + xmaxc[0] 6 + xmc[0] 3 + xmc[1] 3 + xmc[2] 3 + xmc[3] 3 + xmc[4] 3 + xmc[5] 3 + xmc[6] 3 + xmc[7] 3 + xmc[8] 3 + xmc[9] 3 + xmc[10] 3 + xmc[11] 3 + xmc[12] 3 + + Nc[1] 7 + bc[1] 2 + Mc[1] 2 + xmaxc[1] 6 + xmc[13] 3 + xmc[14] 3 + xmc[15] 3 + xmc[16] 3 + xmc[17] 3 + xmc[18] 3 + xmc[19] 3 + xmc[20] 3 + xmc[21] 3 + xmc[22] 3 + xmc[23] 3 + xmc[24] 3 + xmc[25] 3 + + Nc[2] 7 + bc[2] 2 + Mc[2] 2 + xmaxc[2] 6 + xmc[26] 3 + xmc[27] 3 + xmc[28] 3 + xmc[29] 3 + xmc[30] 3 + xmc[31] 3 + xmc[32] 3 + xmc[33] 3 + xmc[34] 3 + xmc[35] 3 + xmc[36] 3 + xmc[37] 3 + xmc[38] 3 + + Nc[3] 7 + bc[3] 2 + Mc[3] 2 + xmaxc[3] 6 + xmc[39] 3 + xmc[40] 3 + xmc[41] 3 + xmc[42] 3 + xmc[43] 3 + xmc[44] 3 + xmc[45] 3 + xmc[46] 3 + xmc[47] 3 + xmc[48] 3 + xmc[49] 3 + xmc[50] 3 + xmc[51] 3 + */ + +#ifdef WAV49 + + if (s->wav_fmt) { + s->frame_index = !s->frame_index; + if (s->frame_index) { + + uword sr; + + sr = 0; + sr = sr >> 6 | LARc[0] << 10; + sr = sr >> 6 | LARc[1] << 10; + *c++ = sr >> 4; + sr = sr >> 5 | LARc[2] << 11; + *c++ = sr >> 7; + sr = sr >> 5 | LARc[3] << 11; + sr = sr >> 4 | LARc[4] << 12; + *c++ = sr >> 6; + sr = sr >> 4 | LARc[5] << 12; + sr = sr >> 3 | LARc[6] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | LARc[7] << 13; + sr = sr >> 7 | Nc[0] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[0] << 14; + sr = sr >> 2 | Mc[0] << 14; + sr = sr >> 6 | xmaxc[0] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[0] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[1] << 13; + sr = sr >> 3 | xmc[2] << 13; + sr = sr >> 3 | xmc[3] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[4] << 13; + sr = sr >> 3 | xmc[5] << 13; + sr = sr >> 3 | xmc[6] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[7] << 13; + sr = sr >> 3 | xmc[8] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[9] << 13; + sr = sr >> 3 | xmc[10] << 13; + sr = sr >> 3 | xmc[11] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[12] << 13; + sr = sr >> 7 | Nc[1] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[1] << 14; + sr = sr >> 2 | Mc[1] << 14; + sr = sr >> 6 | xmaxc[1] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[13] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[14] << 13; + sr = sr >> 3 | xmc[15] << 13; + sr = sr >> 3 | xmc[16] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[17] << 13; + sr = sr >> 3 | xmc[18] << 13; + sr = sr >> 3 | xmc[19] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[20] << 13; + sr = sr >> 3 | xmc[21] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[22] << 13; + sr = sr >> 3 | xmc[23] << 13; + sr = sr >> 3 | xmc[24] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[25] << 13; + sr = sr >> 7 | Nc[2] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[2] << 14; + sr = sr >> 2 | Mc[2] << 14; + sr = sr >> 6 | xmaxc[2] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[26] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[27] << 13; + sr = sr >> 3 | xmc[28] << 13; + sr = sr >> 3 | xmc[29] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[30] << 13; + sr = sr >> 3 | xmc[31] << 13; + sr = sr >> 3 | xmc[32] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[33] << 13; + sr = sr >> 3 | xmc[34] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[35] << 13; + sr = sr >> 3 | xmc[36] << 13; + sr = sr >> 3 | xmc[37] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[38] << 13; + sr = sr >> 7 | Nc[3] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[3] << 14; + sr = sr >> 2 | Mc[3] << 14; + sr = sr >> 6 | xmaxc[3] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[39] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[40] << 13; + sr = sr >> 3 | xmc[41] << 13; + sr = sr >> 3 | xmc[42] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[43] << 13; + sr = sr >> 3 | xmc[44] << 13; + sr = sr >> 3 | xmc[45] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[46] << 13; + sr = sr >> 3 | xmc[47] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[48] << 13; + sr = sr >> 3 | xmc[49] << 13; + sr = sr >> 3 | xmc[50] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[51] << 13; + sr = sr >> 4; + *c = sr >> 8; + s->frame_chain = *c; + } + else { + uword sr; + + sr = 0; + sr = sr >> 4 | s->frame_chain << 12; + sr = sr >> 6 | LARc[0] << 10; + *c++ = sr >> 6; + sr = sr >> 6 | LARc[1] << 10; + *c++ = sr >> 8; + sr = sr >> 5 | LARc[2] << 11; + sr = sr >> 5 | LARc[3] << 11; + *c++ = sr >> 6; + sr = sr >> 4 | LARc[4] << 12; + sr = sr >> 4 | LARc[5] << 12; + *c++ = sr >> 6; + sr = sr >> 3 | LARc[6] << 13; + sr = sr >> 3 | LARc[7] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[0] << 9; + sr = sr >> 2 | bc[0] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[0] << 14; + sr = sr >> 6 | xmaxc[0] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[0] << 13; + sr = sr >> 3 | xmc[1] << 13; + sr = sr >> 3 | xmc[2] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[3] << 13; + sr = sr >> 3 | xmc[4] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[5] << 13; + sr = sr >> 3 | xmc[6] << 13; + sr = sr >> 3 | xmc[7] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[8] << 13; + sr = sr >> 3 | xmc[9] << 13; + sr = sr >> 3 | xmc[10] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[11] << 13; + sr = sr >> 3 | xmc[12] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[1] << 9; + sr = sr >> 2 | bc[1] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[1] << 14; + sr = sr >> 6 | xmaxc[1] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[13] << 13; + sr = sr >> 3 | xmc[14] << 13; + sr = sr >> 3 | xmc[15] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[16] << 13; + sr = sr >> 3 | xmc[17] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[18] << 13; + sr = sr >> 3 | xmc[19] << 13; + sr = sr >> 3 | xmc[20] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[21] << 13; + sr = sr >> 3 | xmc[22] << 13; + sr = sr >> 3 | xmc[23] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[24] << 13; + sr = sr >> 3 | xmc[25] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[2] << 9; + sr = sr >> 2 | bc[2] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[2] << 14; + sr = sr >> 6 | xmaxc[2] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[26] << 13; + sr = sr >> 3 | xmc[27] << 13; + sr = sr >> 3 | xmc[28] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[29] << 13; + sr = sr >> 3 | xmc[30] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[31] << 13; + sr = sr >> 3 | xmc[32] << 13; + sr = sr >> 3 | xmc[33] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[34] << 13; + sr = sr >> 3 | xmc[35] << 13; + sr = sr >> 3 | xmc[36] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[37] << 13; + sr = sr >> 3 | xmc[38] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[3] << 9; + sr = sr >> 2 | bc[3] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[3] << 14; + sr = sr >> 6 | xmaxc[3] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[39] << 13; + sr = sr >> 3 | xmc[40] << 13; + sr = sr >> 3 | xmc[41] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[42] << 13; + sr = sr >> 3 | xmc[43] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[44] << 13; + sr = sr >> 3 | xmc[45] << 13; + sr = sr >> 3 | xmc[46] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[47] << 13; + sr = sr >> 3 | xmc[48] << 13; + sr = sr >> 3 | xmc[49] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[50] << 13; + sr = sr >> 3 | xmc[51] << 13; + *c++ = sr >> 8; + } + } + + else + +#endif /* WAV49 */ + { + + *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ + | ((LARc[0] >> 2) & 0xF); + *c++ = ((LARc[0] & 0x3) << 6) + | (LARc[1] & 0x3F); + *c++ = ((LARc[2] & 0x1F) << 3) + | ((LARc[3] >> 2) & 0x7); + *c++ = ((LARc[3] & 0x3) << 6) + | ((LARc[4] & 0xF) << 2) + | ((LARc[5] >> 2) & 0x3); + *c++ = ((LARc[5] & 0x3) << 6) + | ((LARc[6] & 0x7) << 3) + | (LARc[7] & 0x7); + *c++ = ((Nc[0] & 0x7F) << 1) + | ((bc[0] >> 1) & 0x1); + *c++ = ((bc[0] & 0x1) << 7) + | ((Mc[0] & 0x3) << 5) + | ((xmaxc[0] >> 1) & 0x1F); + *c++ = ((xmaxc[0] & 0x1) << 7) + | ((xmc[0] & 0x7) << 4) + | ((xmc[1] & 0x7) << 1) + | ((xmc[2] >> 2) & 0x1); + *c++ = ((xmc[2] & 0x3) << 6) + | ((xmc[3] & 0x7) << 3) + | (xmc[4] & 0x7); + *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ + | ((xmc[6] & 0x7) << 2) + | ((xmc[7] >> 1) & 0x3); + *c++ = ((xmc[7] & 0x1) << 7) + | ((xmc[8] & 0x7) << 4) + | ((xmc[9] & 0x7) << 1) + | ((xmc[10] >> 2) & 0x1); + *c++ = ((xmc[10] & 0x3) << 6) + | ((xmc[11] & 0x7) << 3) + | (xmc[12] & 0x7); + *c++ = ((Nc[1] & 0x7F) << 1) + | ((bc[1] >> 1) & 0x1); + *c++ = ((bc[1] & 0x1) << 7) + | ((Mc[1] & 0x3) << 5) + | ((xmaxc[1] >> 1) & 0x1F); + *c++ = ((xmaxc[1] & 0x1) << 7) + | ((xmc[13] & 0x7) << 4) + | ((xmc[14] & 0x7) << 1) + | ((xmc[15] >> 2) & 0x1); + *c++ = ((xmc[15] & 0x3) << 6) + | ((xmc[16] & 0x7) << 3) + | (xmc[17] & 0x7); + *c++ = ((xmc[18] & 0x7) << 5) + | ((xmc[19] & 0x7) << 2) + | ((xmc[20] >> 1) & 0x3); + *c++ = ((xmc[20] & 0x1) << 7) + | ((xmc[21] & 0x7) << 4) + | ((xmc[22] & 0x7) << 1) + | ((xmc[23] >> 2) & 0x1); + *c++ = ((xmc[23] & 0x3) << 6) + | ((xmc[24] & 0x7) << 3) + | (xmc[25] & 0x7); + *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ + | ((bc[2] >> 1) & 0x1); + *c++ = ((bc[2] & 0x1) << 7) + | ((Mc[2] & 0x3) << 5) + | ((xmaxc[2] >> 1) & 0x1F); + *c++ = ((xmaxc[2] & 0x1) << 7) + | ((xmc[26] & 0x7) << 4) + | ((xmc[27] & 0x7) << 1) + | ((xmc[28] >> 2) & 0x1); + *c++ = ((xmc[28] & 0x3) << 6) + | ((xmc[29] & 0x7) << 3) + | (xmc[30] & 0x7); + *c++ = ((xmc[31] & 0x7) << 5) + | ((xmc[32] & 0x7) << 2) + | ((xmc[33] >> 1) & 0x3); + *c++ = ((xmc[33] & 0x1) << 7) + | ((xmc[34] & 0x7) << 4) + | ((xmc[35] & 0x7) << 1) + | ((xmc[36] >> 2) & 0x1); + *c++ = ((xmc[36] & 0x3) << 6) + | ((xmc[37] & 0x7) << 3) + | (xmc[38] & 0x7); + *c++ = ((Nc[3] & 0x7F) << 1) + | ((bc[3] >> 1) & 0x1); + *c++ = ((bc[3] & 0x1) << 7) + | ((Mc[3] & 0x3) << 5) + | ((xmaxc[3] >> 1) & 0x1F); + *c++ = ((xmaxc[3] & 0x1) << 7) + | ((xmc[39] & 0x7) << 4) + | ((xmc[40] & 0x7) << 1) + | ((xmc[41] >> 2) & 0x1); + *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ + | ((xmc[42] & 0x7) << 3) + | (xmc[43] & 0x7); + *c++ = ((xmc[44] & 0x7) << 5) + | ((xmc[45] & 0x7) << 2) + | ((xmc[46] >> 1) & 0x3); + *c++ = ((xmc[46] & 0x1) << 7) + | ((xmc[47] & 0x7) << 4) + | ((xmc[48] & 0x7) << 1) + | ((xmc[49] >> 2) & 0x1); + *c++ = ((xmc[49] & 0x3) << 6) + | ((xmc[50] & 0x7) << 3) + | (xmc[51] & 0x7); + + } +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: cfe9c43d-d97c-4216-b5e5-ccd6a25b582b +*/ + diff --git a/nylsf/GSM610/gsm_option.c b/nylsf/GSM610/gsm_option.c new file mode 100644 index 0000000..5155988 --- /dev/null +++ b/nylsf/GSM610/gsm_option.c @@ -0,0 +1,76 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include "config.h" // RBD + +#include "gsm610_priv.h" + +#include "gsm.h" + +int gsm_option (gsm r, int opt, int * val) +{ + int result = -1; + + switch (opt) { + case GSM_OPT_LTP_CUT: +#ifdef LTP_CUT + result = r->ltp_cut; + if (val) r->ltp_cut = *val; +#endif + break; + + case GSM_OPT_VERBOSE: +#ifndef NDEBUG + result = r->verbose; + if (val) r->verbose = *val; +#endif + break; + + case GSM_OPT_FAST: + +#if defined(FAST) && defined(USE_FLOAT_MUL) + result = r->fast; + if (val) r->fast = !!*val; +#endif + break; + + case GSM_OPT_FRAME_CHAIN: + +#ifdef WAV49 + result = r->frame_chain; + if (val) r->frame_chain = *val; +#endif + break; + + case GSM_OPT_FRAME_INDEX: + +#ifdef WAV49 + result = r->frame_index; + if (val) r->frame_index = *val; +#endif + break; + + case GSM_OPT_WAV49: + +#ifdef WAV49 + result = r->wav_fmt; + if (val) r->wav_fmt = !!*val; +#endif + break; + + default: + break; + } + return result; +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 963ff156-506f-4359-9145-371e9060b030 +*/ + diff --git a/nylsf/GSM610/long_term.c b/nylsf/GSM610/long_term.c new file mode 100644 index 0000000..3eaa1f2 --- /dev/null +++ b/nylsf/GSM610/long_term.c @@ -0,0 +1,953 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include "config.h" // RBD + +#include +#include + +#include "gsm610_priv.h" + +#include "gsm.h" + +/* + * 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION + */ + + +/* + * This module computes the LTP gain (bc) and the LTP lag (Nc) + * for the long term analysis filter. This is done by calculating a + * maximum of the cross-correlation function between the current + * sub-segment short term residual signal d[0..39] (output of + * the short term analysis filter; for simplification the index + * of this array begins at 0 and ends at 39 for each sub-segment of the + * RPE-LTP analysis) and the previous reconstructed short term + * residual signal dp[ -120 .. -1 ]. A dynamic scaling must be + * performed to avoid overflow. + */ + + /* The next procedure exists in six versions. First two integer + * version (if USE_FLOAT_MUL is not defined); then four floating + * point versions, twice with proper scaling (USE_FLOAT_MUL defined), + * once without (USE_FLOAT_MUL and FAST defined, and fast run-time + * option used). Every pair has first a Cut version (see the -C + * option to toast or the LTP_CUT option to gsm_option()), then the + * uncut one. (For a detailed explanation of why this is altogether + * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered + * Harmful''.) + */ + +#ifndef USE_FLOAT_MUL + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters ( + + struct gsm_state * st, + + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word wt[40]; + + longword L_result; + longword L_max, L_power; + word R, S, dmax, scal, best_k; + word ltp_cut; + + register word temp, wt_k; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) { + dmax = temp; + best_k = k; + } + } + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + if (temp > 6) scal = 0; + else scal = 6 - temp; + assert(scal >= 0); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + wt_k = SASR_W(d[best_k], scal); + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = (longword)wt_k * dp[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + *Nc_out = Nc; + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR_W( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters ( + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word wt[40]; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k <= 39; k++) wt[k] = SASR_W( d[k], scal ); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + +# undef STEP +# define STEP(k) (longword)wt[k] * dp[k - lambda] + + register longword L_result; + + L_result = STEP(0) ; L_result += STEP(1) ; + L_result += STEP(2) ; L_result += STEP(3) ; + L_result += STEP(4) ; L_result += STEP(5) ; + L_result += STEP(6) ; L_result += STEP(7) ; + L_result += STEP(8) ; L_result += STEP(9) ; + L_result += STEP(10) ; L_result += STEP(11) ; + L_result += STEP(12) ; L_result += STEP(13) ; + L_result += STEP(14) ; L_result += STEP(15) ; + L_result += STEP(16) ; L_result += STEP(17) ; + L_result += STEP(18) ; L_result += STEP(19) ; + L_result += STEP(20) ; L_result += STEP(21) ; + L_result += STEP(22) ; L_result += STEP(23) ; + L_result += STEP(24) ; L_result += STEP(25) ; + L_result += STEP(26) ; L_result += STEP(27) ; + L_result += STEP(28) ; L_result += STEP(29) ; + L_result += STEP(30) ; L_result += STEP(31) ; + L_result += STEP(32) ; L_result += STEP(33) ; + L_result += STEP(34) ; L_result += STEP(35) ; + L_result += STEP(36) ; L_result += STEP(37) ; + L_result += STEP(38) ; L_result += STEP(39) ; + + if (L_result > L_max) { + + Nc = lambda; + L_max = L_result; + } + } + + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR_W( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR_L( L_max << temp, 16 ); + S = SASR_L( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#else /* USE_FLOAT_MUL */ + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters ( + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word ltp_cut; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + ltp_cut = (longword)SASR_W(dmax, scal) * st->ltp_cut / 100; + + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) { + register word w = SASR_W( d[k], scal ); + if (w < 0 ? w > -ltp_cut : w < ltp_cut) { + wt_float[k] = 0.0; + } + else { + wt_float[k] = w; + } + } + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + if ((W = wt_float[K]) != 0.0) { \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E; } else (a = lp[K]) + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR_W( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters ( + register word * din, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = din [k] ; + temp = GSM_ABS (temp) ; + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) wt_float[k] = SASR_W (din [k], scal) ; + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR_W( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR_L ( L_max << temp, 16 ); + S = SASR_L ( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#ifdef FAST +#ifdef LTP_CUT + +static void Cut_Fast_Calculation_of_the_LTP_parameters ( + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + register float wt_float; + word Nc, bc; + word wt_max, best_k, ltp_cut; + + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_result, L_max, L_power; + + wt_max = 0; + + for (k = 0; k < 40; ++k) { + if ( d[k] > wt_max) wt_max = d[best_k = k]; + else if (-d[k] > wt_max) wt_max = -d[best_k = k]; + } + + assert(wt_max >= 0); + wt_float = (float)wt_max; + + for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = wt_float * dp_float[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + + *Nc_out = Nc; + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Fast_Calculation_of_the_LTP_parameters ( + register word * din, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_max, L_power; + + for (k = 0; k < 40; ++k) wt_float[k] = (float) din [k] ; + for (k = -120; k < 0; ++k) dp_float[k] = (float) dp [k] ; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* FAST */ +#endif /* USE_FLOAT_MUL */ + + +/* 4.2.12 */ + +static void Long_term_analysis_filtering ( + word bc, /* IN */ + word Nc, /* IN */ + register word * dp, /* previous d [-120..-1] IN */ + register word * d, /* d [0..39] IN */ + register word * dpp, /* estimate [0..39] OUT */ + register word * e /* long term res. signal [0..39] OUT */ +) +/* + * In this part, we have to decode the bc parameter to compute + * the samples of the estimate dpp[0..39]. The decoding of bc needs the + * use of table 4.3b. The long term residual signal e[0..39] + * is then calculated to be fed to the RPE encoding section. + */ +{ + register int k; + +# undef STEP +# define STEP(BP) \ + for (k = 0; k <= 39; k++) { \ + dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \ + e[k] = GSM_SUB( d[k], dpp[k] ); \ + } + + switch (bc) { + case 0: STEP( 3277 ); break; + case 1: STEP( 11469 ); break; + case 2: STEP( 21299 ); break; + case 3: STEP( 32767 ); break; + } +} + +void Gsm_Long_Term_Predictor ( /* 4x for 160 samples */ + + struct gsm_state * S, + + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + + word * e, /* [0..39] OUT */ + word * dpp, /* [0..39] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */ +) +{ + assert( d ); assert( dp ); assert( e ); + assert( dpp); assert( Nc ); assert( bc ); + +#if defined(FAST) && defined(USE_FLOAT_MUL) + if (S->fast) +#if defined (LTP_CUT) + if (S->ltp_cut) + Cut_Fast_Calculation_of_the_LTP_parameters(S, + d, dp, bc, Nc); + else +#endif /* LTP_CUT */ + Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc ); + else +#endif /* FAST & USE_FLOAT_MUL */ +#ifdef LTP_CUT + if (S->ltp_cut) + Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); + else +#endif + Calculation_of_the_LTP_parameters(d, dp, bc, Nc); + + Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); +} + +/* 4.3.2 */ +void Gsm_Long_Term_Synthesis_Filtering ( + struct gsm_state * S, + + word Ncr, + word bcr, + register word * erp, /* [0..39] IN */ + register word * drp /* [-120..-1] IN, [-120..40] OUT */ +) +/* + * This procedure uses the bcr and Ncr parameter to realize the + * long term synthesis filtering. The decoding of bcr needs + * table 4.3b. + */ +{ + register int k; + word brp, drpp, Nr; + + /* Check the limits of Nr. + */ + Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr; + S->nrp = Nr; + assert(Nr >= 40 && Nr <= 120); + + /* Decoding of the LTP gain bcr + */ + brp = gsm_QLB[ bcr ]; + + /* Computation of the reconstructed short term residual + * signal drp[0..39] + */ + assert(brp != MIN_WORD); + + for (k = 0; k <= 39; k++) { + drpp = GSM_MULT_R( brp, drp[ k - Nr ] ); + drp[k] = GSM_ADD( erp[k], drpp ); + } + + /* + * Update of the reconstructed short term residual signal + * drp[ -1..-120 ] + */ + + for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ]; +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: b369b90d-0284-42a0-87b0-99a25bbd93ac +*/ + diff --git a/nylsf/GSM610/lpc.c b/nylsf/GSM610/lpc.c new file mode 100644 index 0000000..adaa417 --- /dev/null +++ b/nylsf/GSM610/lpc.c @@ -0,0 +1,343 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include +#include + +#include "config.h" // RBD + +#include "gsm610_priv.h" + +#include "gsm.h" + +/* + * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION + */ + +/* 4.2.4 */ + + +static void Autocorrelation ( + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +/* + * The goal is to compute the array L_ACF[k]. The signal s[i] must + * be scaled in order to avoid an overflow situation. + */ +{ + register int k, i; + + word temp, smax, scalauto; + +#ifdef USE_FLOAT_MUL + float float_s[160]; +#endif + + /* Dynamic scaling of the array s[0..159] + */ + + /* Search for the maximum. + */ + smax = 0; + for (k = 0; k <= 159; k++) { + temp = GSM_ABS( s[k] ); + if (temp > smax) smax = temp; + } + + /* Computation of the scaling factor. + */ + if (smax == 0) scalauto = 0; + else { + assert(smax > 0); + scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ + } + + /* Scaling of the array s[0...159] + */ + + if (scalauto > 0) { + +# ifdef USE_FLOAT_MUL +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + float_s[k] = (float) \ + (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ + break; +# else +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ + break; +# endif /* USE_FLOAT_MUL */ + + switch (scalauto) { + SCALE(1) + SCALE(2) + SCALE(3) + SCALE(4) + } +# undef SCALE + } +# ifdef USE_FLOAT_MUL + else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; +# endif + + /* Compute the L_ACF[..]. + */ + { +# ifdef USE_FLOAT_MUL + register float * sp = float_s; + register float sl = *sp; + +# define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); +# else + word * sp = s; + word sl = *sp; + +# define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); +# endif + +# define NEXTI sl = *++sp + + + for (k = 9; k--; L_ACF[k] = 0) ; + + STEP (0); + NEXTI; + STEP(0); STEP(1); + NEXTI; + STEP(0); STEP(1); STEP(2); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); + + for (i = 8; i <= 159; i++) { + + NEXTI; + + STEP(0); + STEP(1); STEP(2); STEP(3); STEP(4); + STEP(5); STEP(6); STEP(7); STEP(8); + } + + for (k = 9; k--; L_ACF[k] <<= 1) ; + + } + /* Rescaling of the array s[0..159] + */ + if (scalauto > 0) { + assert(scalauto <= 4); + for (k = 160; k--; *s++ <<= scalauto) ; + } +} + +#if defined(USE_FLOAT_MUL) && defined(FAST) + +static void Fast_Autocorrelation ( + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +{ + register int k, i; + float f_L_ACF[9]; + float scale; + + float s_f[160]; + register float *sf = s_f; + + for (i = 0; i < 160; ++i) sf[i] = s[i]; + for (k = 0; k <= 8; k++) { + register float L_temp2 = 0; + register float *sfl = sf - k; + for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; + f_L_ACF[k] = L_temp2; + } + scale = MAX_LONGWORD / f_L_ACF[0]; + + for (k = 0; k <= 8; k++) { + L_ACF[k] = f_L_ACF[k] * scale; + } +} +#endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ + +/* 4.2.5 */ + +static void Reflection_coefficients ( + longword * L_ACF, /* 0...8 IN */ + register word * r /* 0...7 OUT */ +) +{ + register int i, m, n; + register word temp; + word ACF[9]; /* 0..8 */ + word P[ 9]; /* 0..8 */ + word K[ 9]; /* 2..8 */ + + /* Schur recursion with 16 bits arithmetic. + */ + + if (L_ACF[0] == 0) { + for (i = 8; i--; *r++ = 0) ; + return; + } + + assert( L_ACF[0] != 0 ); + temp = gsm_norm( L_ACF[0] ); + + assert(temp >= 0 && temp < 32); + + /* ? overflow ? */ + for (i = 0; i <= 8; i++) ACF[i] = SASR_L( L_ACF[i] << temp, 16 ); + + /* Initialize array P[..] and K[..] for the recursion. + */ + + for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; + for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; + + /* Compute reflection coefficients + */ + for (n = 1; n <= 8; n++, r++) { + + temp = P[1]; + temp = GSM_ABS(temp); + if (P[0] < temp) { + for (i = n; i <= 8; i++) *r++ = 0; + return; + } + + *r = gsm_div( temp, P[0] ); + + assert(*r >= 0); + if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ + assert (*r != MIN_WORD); + if (n == 8) return; + + /* Schur recursion + */ + temp = GSM_MULT_R( P[1], *r ); + P[0] = GSM_ADD( P[0], temp ); + + for (m = 1; m <= 8 - n; m++) { + temp = GSM_MULT_R( K[ m ], *r ); + P[m] = GSM_ADD( P[ m+1 ], temp ); + + temp = GSM_MULT_R( P[ m+1 ], *r ); + K[m] = GSM_ADD( K[ m ], temp ); + } + } +} + +/* 4.2.6 */ + +static void Transformation_to_Log_Area_Ratios ( + register word * r /* 0..7 IN/OUT */ +) +/* + * The following scaling for r[..] and LAR[..] has been used: + * + * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. + * LAR[..] = integer( real_LAR[..] * 16384 ); + * with -1.625 <= real_LAR <= 1.625 + */ +{ + register word temp; + register int i; + + + /* Computation of the LAR[0..7] from the r[0..7] + */ + for (i = 1; i <= 8; i++, r++) { + + temp = *r; + temp = GSM_ABS(temp); + assert(temp >= 0); + + if (temp < 22118) { + temp >>= 1; + } else if (temp < 31130) { + assert( temp >= 11059 ); + temp -= 11059; + } else { + assert( temp >= 26112 ); + temp -= 26112; + temp <<= 2; + } + + *r = *r < 0 ? -temp : temp; + assert( *r != MIN_WORD ); + } +} + +/* 4.2.7 */ + +static void Quantization_and_coding ( + register word * LAR /* [0..7] IN/OUT */ +) +{ + register word temp; + + /* This procedure needs four tables; the following equations + * give the optimum scaling for the constants: + * + * A[0..7] = integer( real_A[0..7] * 1024 ) + * B[0..7] = integer( real_B[0..7] * 512 ) + * MAC[0..7] = maximum of the LARc[0..7] + * MIC[0..7] = minimum of the LARc[0..7] + */ + +# undef STEP +# define STEP( A, B, MAC, MIC ) \ + temp = GSM_MULT( A, *LAR ); \ + temp = GSM_ADD( temp, B ); \ + temp = GSM_ADD( temp, 256 ); \ + temp = SASR_W( temp, 9 ); \ + *LAR = temp>MAC ? MAC - MIC : (tempfast) Fast_Autocorrelation (s, L_ACF ); + else +#endif + Autocorrelation (s, L_ACF ); + Reflection_coefficients (L_ACF, LARc ); + Transformation_to_Log_Area_Ratios (LARc); + Quantization_and_coding (LARc); +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 63146664-a002-4e1e-8b7b-f0cc8a6a53da +*/ + diff --git a/nylsf/GSM610/preprocess.c b/nylsf/GSM610/preprocess.c new file mode 100644 index 0000000..3d5d634 --- /dev/null +++ b/nylsf/GSM610/preprocess.c @@ -0,0 +1,117 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include +#include + +#include "config.h" // RBD + +#include "gsm610_priv.h" + +#include "gsm.h" + +/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION + * + * After A-law to linear conversion (or directly from the + * Ato D converter) the following scaling is assumed for + * input to the RPE-LTP algorithm: + * + * in: 0.1.....................12 + * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.* + * + * Where S is the sign bit, v a valid bit, and * a "don't care" bit. + * The original signal is called sop[..] + * + * out: 0.1................... 12 + * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0 + */ + + +void Gsm_Preprocess ( + struct gsm_state * S, + word * s, + word * so ) /* [0..159] IN/OUT */ +{ + + word z1 = S->z1; + longword L_z2 = S->L_z2; + word mp = S->mp; + + word s1; + longword L_s2; + + longword L_temp; + + word msp, lsp; + word SO; + + register int k = 160; + + while (k--) { + + /* 4.2.1 Downscaling of the input signal + */ + SO = SASR_W( *s, 3 ) << 2; + s++; + + assert (SO >= -0x4000); /* downscaled by */ + assert (SO <= 0x3FFC); /* previous routine. */ + + + /* 4.2.2 Offset compensation + * + * This part implements a high-pass filter and requires extended + * arithmetic precision for the recursive part of this filter. + * The input of this procedure is the array so[0...159] and the + * output the array sof[ 0...159 ]. + */ + /* Compute the non-recursive part + */ + + s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */ + z1 = SO; + + assert(s1 != MIN_WORD); + + /* Compute the recursive part + */ + L_s2 = s1; + L_s2 <<= 15; + + /* Execution of a 31 bv 16 bits multiplication + */ + + msp = SASR_L( L_z2, 15 ); + lsp = L_z2-((longword)msp<<15); /* gsm_L_sub(L_z2,(msp<<15)); */ + + L_s2 += GSM_MULT_R( lsp, 32735 ); + L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/ + L_z2 = GSM_L_ADD( L_temp, L_s2 ); + + /* Compute sof[k] with rounding + */ + L_temp = GSM_L_ADD( L_z2, 16384 ); + + /* 4.2.3 Preemphasis + */ + + msp = GSM_MULT_R( mp, -28180 ); + mp = SASR_L( L_temp, 15 ); + *so++ = GSM_ADD( mp, msp ); + } + + S->z1 = z1; + S->L_z2 = L_z2; + S->mp = mp; +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: b760b0d9-3a05-4da3-9dc9-441ffb905d87 +*/ + diff --git a/nylsf/GSM610/rpe.c b/nylsf/GSM610/rpe.c new file mode 100644 index 0000000..e016aaa --- /dev/null +++ b/nylsf/GSM610/rpe.c @@ -0,0 +1,492 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include +#include + +#include "config.h" // RBD + +#include "gsm610_priv.h" + +#include "gsm.h" + +/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION + */ + +/* 4.2.13 */ + +static void Weighting_filter ( + register word * e, /* signal [-5..0.39.44] IN */ + word * x /* signal [0..39] OUT */ +) +/* + * The coefficients of the weighting filter are stored in a table + * (see table 4.4). The following scaling is used: + * + * H[0..10] = integer( real_H[ 0..10] * 8192 ); + */ +{ + /* word wt[ 50 ]; */ + + register longword L_result; + register int k /* , i */ ; + + /* Initialization of a temporary working array wt[0...49] + */ + + /* for (k = 0; k <= 4; k++) wt[k] = 0; + * for (k = 5; k <= 44; k++) wt[k] = *e++; + * for (k = 45; k <= 49; k++) wt[k] = 0; + * + * (e[-5..-1] and e[40..44] are allocated by the caller, + * are initially zero and are not written anywhere.) + */ + e -= 5; + + /* Compute the signal x[0..39] + */ + for (k = 0; k <= 39; k++) { + + L_result = 8192 >> 1; + + /* for (i = 0; i <= 10; i++) { + * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] ); + * L_result = GSM_L_ADD( L_result, L_temp ); + * } + */ + +#undef STEP +#define STEP( i, H ) (e[ k + i ] * (longword)H) + + /* Every one of these multiplications is done twice -- + * but I don't see an elegant way to optimize this. + * Do you? + */ + +#ifdef STUPID_COMPILER + L_result += STEP( 0, -134 ) ; + L_result += STEP( 1, -374 ) ; + /* + STEP( 2, 0 ) */ + L_result += STEP( 3, 2054 ) ; + L_result += STEP( 4, 5741 ) ; + L_result += STEP( 5, 8192 ) ; + L_result += STEP( 6, 5741 ) ; + L_result += STEP( 7, 2054 ) ; + /* + STEP( 8, 0 ) */ + L_result += STEP( 9, -374 ) ; + L_result += STEP( 10, -134 ) ; +#else + L_result += + STEP( 0, -134 ) + + STEP( 1, -374 ) + /* + STEP( 2, 0 ) */ + + STEP( 3, 2054 ) + + STEP( 4, 5741 ) + + STEP( 5, 8192 ) + + STEP( 6, 5741 ) + + STEP( 7, 2054 ) + /* + STEP( 8, 0 ) */ + + STEP( 9, -374 ) + + STEP(10, -134 ) + ; +#endif + + /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *) + * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *) + * + * x[k] = SASR( L_result, 16 ); + */ + + /* 2 adds vs. >>16 => 14, minus one shift to compensate for + * those we lost when replacing L_MULT by '*'. + */ + + L_result = SASR_L( L_result, 13 ); + x[k] = ( L_result < MIN_WORD ? MIN_WORD + : (L_result > MAX_WORD ? MAX_WORD : L_result )); + } +} + +/* 4.2.14 */ + +static void RPE_grid_selection ( + word * x, /* [0..39] IN */ + word * xM, /* [0..12] OUT */ + word * Mc_out /* OUT */ +) +/* + * The signal x[0..39] is used to select the RPE grid which is + * represented by Mc. + */ +{ + /* register word temp1; */ + register int /* m, */ i; + register longword L_result, L_temp; + longword EM; /* xxx should be L_EM? */ + word Mc; + + longword L_common_0_3; + + EM = 0; + Mc = 0; + + /* for (m = 0; m <= 3; m++) { + * L_result = 0; + * + * + * for (i = 0; i <= 12; i++) { + * + * temp1 = SASR_W( x[m + 3*i], 2 ); + * + * assert(temp1 != MIN_WORD); + * + * L_temp = GSM_L_MULT( temp1, temp1 ); + * L_result = GSM_L_ADD( L_temp, L_result ); + * } + * + * if (L_result > EM) { + * Mc = m; + * EM = L_result; + * } + * } + */ + +#undef STEP +#define STEP( m, i ) L_temp = SASR_W( x[m + 3 * i], 2 ); \ + L_result += L_temp * L_temp; + + /* common part of 0 and 3 */ + + L_result = 0; + STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 ); + STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 ); + STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12); + L_common_0_3 = L_result; + + /* i = 0 */ + + STEP( 0, 0 ); + L_result <<= 1; /* implicit in L_MULT */ + EM = L_result; + + /* i = 1 */ + + L_result = 0; + STEP( 1, 0 ); + STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 ); + STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 ); + STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 1; + EM = L_result; + } + + /* i = 2 */ + + L_result = 0; + STEP( 2, 0 ); + STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 ); + STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 ); + STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 2; + EM = L_result; + } + + /* i = 3 */ + + L_result = L_common_0_3; + STEP( 3, 12 ); + L_result <<= 1; + if (L_result > EM) { + Mc = 3; + EM = L_result; + } + + /**/ + + /* Down-sampling by a factor 3 to get the selected xM[0..12] + * RPE sequence. + */ + for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i]; + *Mc_out = Mc; +} + +/* 4.12.15 */ + +static void APCM_quantization_xmaxc_to_exp_mant ( + word xmaxc, /* IN */ + word * expon_out, /* OUT */ + word * mant_out ) /* OUT */ +{ + word expon, mant; + + /* Compute expononent and mantissa of the decoded version of xmaxc + */ + + expon = 0; + if (xmaxc > 15) expon = SASR_W(xmaxc, 3) - 1; + mant = xmaxc - (expon << 3); + + if (mant == 0) { + expon = -4; + mant = 7; + } + else { + while (mant <= 7) { + mant = mant << 1 | 1; + expon--; + } + mant -= 8; + } + + assert( expon >= -4 && expon <= 6 ); + assert( mant >= 0 && mant <= 7 ); + + *expon_out = expon; + *mant_out = mant; +} + +static void APCM_quantization ( + word * xM, /* [0..12] IN */ + word * xMc, /* [0..12] OUT */ + word * mant_out, /* OUT */ + word * expon_out, /* OUT */ + word * xmaxc_out /* OUT */ +) +{ + int i, itest; + + word xmax, xmaxc, temp, temp1, temp2; + word expon, mant; + + + /* Find the maximum absolute value xmax of xM[0..12]. + */ + + xmax = 0; + for (i = 0; i <= 12; i++) { + temp = xM[i]; + temp = GSM_ABS(temp); + if (temp > xmax) xmax = temp; + } + + /* Qantizing and coding of xmax to get xmaxc. + */ + + expon = 0; + temp = SASR_W( xmax, 9 ); + itest = 0; + + for (i = 0; i <= 5; i++) { + + itest |= (temp <= 0); + temp = SASR_W( temp, 1 ); + + assert(expon <= 5); + if (itest == 0) expon++; /* expon = add (expon, 1) */ + } + + assert(expon <= 6 && expon >= 0); + temp = expon + 5; + + assert(temp <= 11 && temp >= 0); + xmaxc = gsm_add( SASR_W(xmax, temp), (word) (expon << 3) ); + + /* Quantizing and coding of the xM[0..12] RPE sequence + * to get the xMc[0..12] + */ + + APCM_quantization_xmaxc_to_exp_mant( xmaxc, &expon, &mant ); + + /* This computation uses the fact that the decoded version of xmaxc + * can be calculated by using the expononent and the mantissa part of + * xmaxc (logarithmic table). + * So, this method avoids any division and uses only a scaling + * of the RPE samples by a function of the expononent. A direct + * multiplication by the inverse of the mantissa (NRFAC[0..7] + * found in table 4.5) gives the 3 bit coded version xMc[0..12] + * of the RPE samples. + */ + + + /* Direct computation of xMc[0..12] using table 4.5 + */ + + assert( expon <= 4096 && expon >= -4096); + assert( mant >= 0 && mant <= 7 ); + + temp1 = 6 - expon; /* normalization by the expononent */ + temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */ + + for (i = 0; i <= 12; i++) { + + assert(temp1 >= 0 && temp1 < 16); + + temp = xM[i] << temp1; + temp = GSM_MULT( temp, temp2 ); + temp = SASR_W(temp, 12); + xMc[i] = temp + 4; /* see note below */ + } + + /* NOTE: This equation is used to make all the xMc[i] positive. + */ + + *mant_out = mant; + *expon_out = expon; + *xmaxc_out = xmaxc; +} + +/* 4.2.16 */ + +static void APCM_inverse_quantization ( + register word * xMc, /* [0..12] IN */ + word mant, + word expon, + register word * xMp) /* [0..12] OUT */ +/* + * This part is for decoding the RPE sequence of coded xMc[0..12] + * samples to obtain the xMp[0..12] array. Table 4.6 is used to get + * the mantissa of xmaxc (FAC[0..7]). + */ +{ + int i; + word temp, temp1, temp2, temp3; + + assert( mant >= 0 && mant <= 7 ); + + temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */ + temp2 = gsm_sub( 6, expon ); /* see 4.2-15 for exp */ + temp3 = gsm_asl( 1, gsm_sub( temp2, 1 )); + + for (i = 13; i--;) { + + assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */ + + /* temp = gsm_sub( *xMc++ << 1, 7 ); */ + temp = (*xMc++ << 1) - 7; /* restore sign */ + assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */ + + temp <<= 12; /* 16 bit signed */ + temp = GSM_MULT_R( temp1, temp ); + temp = GSM_ADD( temp, temp3 ); + *xMp++ = gsm_asr( temp, temp2 ); + } +} + +/* 4.2.17 */ + +static void RPE_grid_positioning ( + word Mc, /* grid position IN */ + register word * xMp, /* [0..12] IN */ + register word * ep /* [0..39] OUT */ +) +/* + * This procedure computes the reconstructed long term residual signal + * ep[0..39] for the LTP analysis filter. The inputs are the Mc + * which is the grid position selection and the xMp[0..12] decoded + * RPE samples which are upsampled by a factor of 3 by inserting zero + * values. + */ +{ + int i = 13; + + assert(0 <= Mc && Mc <= 3); + + switch (Mc) { + case 3: *ep++ = 0; + case 2: do { + *ep++ = 0; + case 1: *ep++ = 0; + case 0: *ep++ = *xMp++; + } while (--i); + } + while (++Mc < 4) *ep++ = 0; + + /* + + int i, k; + for (k = 0; k <= 39; k++) ep[k] = 0; + for (i = 0; i <= 12; i++) { + ep[ Mc + (3*i) ] = xMp[i]; + } + */ +} + +/* 4.2.18 */ + +/* This procedure adds the reconstructed long term residual signal + * ep[0..39] to the estimated signal dpp[0..39] from the long term + * analysis filter to compute the reconstructed short term residual + * signal dp[-40..-1]; also the reconstructed short term residual + * array dp[-120..-41] is updated. + */ + +#if 0 /* Has been inlined in code.c */ +void Gsm_Update_of_reconstructed_short_time_residual_signal ( + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp) /* [-120...-1] IN/OUT */ +{ + int k; + + for (k = 0; k <= 79; k++) + dp[ -120 + k ] = dp[ -80 + k ]; + + for (k = 0; k <= 39; k++) + dp[ -40 + k ] = gsm_add( ep[k], dpp[k] ); +} +#endif /* Has been inlined in code.c */ + +void Gsm_RPE_Encoding ( + /*-struct gsm_state * S,-*/ + + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc) /* [0..12] OUT */ +{ + word x[40]; + word xM[13], xMp[13]; + word mant, expon; + + Weighting_filter(e, x); + RPE_grid_selection(x, xM, Mc); + + APCM_quantization( xM, xMc, &mant, &expon, xmaxc); + APCM_inverse_quantization( xMc, mant, expon, xMp); + + RPE_grid_positioning( *Mc, xMp, e ); + +} + +void Gsm_RPE_Decoding ( + /*-struct gsm_state * S,-*/ + + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp /* [0..39] OUT */ +) +{ + word expon, mant; + word xMp[ 13 ]; + + APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &expon, &mant ); + APCM_inverse_quantization( xMcr, mant, expon, xMp ); + RPE_grid_positioning( Mcr, xMp, erp ); + +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 82005b9e-1560-4e94-9ddb-00cb14867295 +*/ + diff --git a/nylsf/GSM610/short_term.c b/nylsf/GSM610/short_term.c new file mode 100644 index 0000000..12a277b --- /dev/null +++ b/nylsf/GSM610/short_term.c @@ -0,0 +1,429 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +#include +#include + +#include "config.h" // RBD + +#include "gsm610_priv.h" + +#include "gsm.h" + +/* + * SHORT TERM ANALYSIS FILTERING SECTION + */ + +/* 4.2.8 */ + +static void Decoding_of_the_coded_Log_Area_Ratios ( + word * LARc, /* coded log area ratio [0..7] IN */ + word * LARpp) /* out: decoded .. */ +{ + register word temp1 /* , temp2 */; + + /* This procedure requires for efficient implementation + * two tables. + * + * INVA[1..8] = integer( (32768 * 8) / real_A[1..8]) + * MIC[1..8] = minimum value of the LARc[1..8] + */ + + /* Compute the LARpp[1..8] + */ + + /* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) { + * + * temp1 = GSM_ADD( *LARc, *MIC ) << 10; + * temp2 = *B << 1; + * temp1 = GSM_SUB( temp1, temp2 ); + * + * assert(*INVA != MIN_WORD); + * + * temp1 = GSM_MULT_R( *INVA, temp1 ); + * *LARpp = GSM_ADD( temp1, temp1 ); + * } + */ + +#undef STEP +#define STEP( B, MIC, INVA ) \ + temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ + temp1 = GSM_SUB( temp1, B << 1 ); \ + temp1 = GSM_MULT_R( INVA, temp1 ); \ + *LARpp++ = GSM_ADD( temp1, temp1 ); + + STEP( 0, -32, 13107 ); + STEP( 0, -32, 13107 ); + STEP( 2048, -16, 13107 ); + STEP( -2560, -16, 13107 ); + + STEP( 94, -8, 19223 ); + STEP( -1792, -8, 17476 ); + STEP( -341, -4, 31454 ); + STEP( -1144, -4, 29708 ); + + /* NOTE: the addition of *MIC is used to restore + * the sign of *LARc. + */ +} + +/* 4.2.9 */ +/* Computation of the quantized reflection coefficients + */ + +/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] + */ + +/* + * Within each frame of 160 analyzed speech samples the short term + * analysis and synthesis filters operate with four different sets of + * coefficients, derived from the previous set of decoded LARs(LARpp(j-1)) + * and the actual set of decoded LARs (LARpp(j)) + * + * (Initial value: LARpp(j-1)[1..8] = 0.) + */ + +static void Coefficients_0_12 ( + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) { + *LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j_1, 1)); + } +} + +static void Coefficients_13_26 ( + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR_W( *LARpp_j_1, 1), SASR_W( *LARpp_j, 1 )); + } +} + +static void Coefficients_27_39 ( + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j, 1 )); + } +} + + +static void Coefficients_40_159 ( + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j++) + *LARp = *LARpp_j; +} + +/* 4.2.9.2 */ + +static void LARp_to_rp ( + register word * LARp) /* [0..7] IN/OUT */ +/* + * The input of this procedure is the interpolated LARp[0..7] array. + * The reflection coefficients, rp[i], are used in the analysis + * filter and in the synthesis filter. + */ +{ + register int i; + register word temp; + + for (i = 1; i <= 8; i++, LARp++) { + + /* temp = GSM_ABS( *LARp ); + * + * if (temp < 11059) temp <<= 1; + * else if (temp < 20070) temp += 11059; + * else temp = GSM_ADD( temp >> 2, 26112 ); + * + * *LARp = *LARp < 0 ? -temp : temp; + */ + + if (*LARp < 0) { + temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp); + *LARp = - ((temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( (word) (temp >> 2), (word) 26112 ))); + } else { + temp = *LARp; + *LARp = (temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( (word) (temp >> 2), (word) 26112 )); + } + } +} + + +/* 4.2.10 */ +static void Short_term_analysis_filtering ( + struct gsm_state * S, + register word * rp, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +/* + * This procedure computes the short term residual signal d[..] to be fed + * to the RPE-LTP loop from the s[..] signal and from the local rp[..] + * array (quantized reflection coefficients). As the call of this + * procedure can be done in many ways (see the interpolation of the LAR + * coefficient), it is assumed that the computation begins with index + * k_start (for arrays d[..] and s[..]) and stops with index k_end + * (k_start and k_end are defined in 4.2.9.1). This procedure also + * needs to keep the array u[0..7] in memory for each call. + */ +{ + register word * u = S->u; + register int i; + register word di, zzz, ui, sav, rpi; + + for (; k_n--; s++) { + + di = sav = *s; + + for (i = 0; i < 8; i++) { /* YYY */ + + ui = u[i]; + rpi = rp[i]; + u[i] = sav; + + zzz = GSM_MULT_R(rpi, di); + sav = GSM_ADD( ui, zzz); + + zzz = GSM_MULT_R(rpi, ui); + di = GSM_ADD( di, zzz ); + } + + *s = di; + } +} + +#if defined(USE_FLOAT_MUL) && defined(FAST) + +static void Fast_Short_term_analysis_filtering ( + struct gsm_state * S, + register word * rp, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +{ + register word * u = S->u; + register int i; + + float uf[8], + rpf[8]; + + register float scalef = 3.0517578125e-5; + register float sav, di, temp; + + for (i = 0; i < 8; ++i) { + uf[i] = u[i]; + rpf[i] = rp[i] * scalef; + } + for (; k_n--; s++) { + sav = di = *s; + for (i = 0; i < 8; ++i) { + register float rpfi = rpf[i]; + register float ufi = uf[i]; + + uf[i] = sav; + temp = rpfi * di + ufi; + di += rpfi * ufi; + sav = temp; + } + *s = di; + } + for (i = 0; i < 8; ++i) u[i] = uf[i]; +} +#endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */ + +static void Short_term_synthesis_filtering ( + struct gsm_state * S, + register word * rrp, /* [0..7] IN */ + register int k, /* k_end - k_start */ + register word * wt, /* [0..k-1] IN */ + register word * sr /* [0..k-1] OUT */ +) +{ + register word * v = S->v; + register int i; + register word sri, tmp1, tmp2; + + while (k--) { + sri = *wt++; + for (i = 8; i--;) { + + /* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) ); + */ + tmp1 = rrp[i]; + tmp2 = v[i]; + tmp2 = ( tmp1 == MIN_WORD && tmp2 == MIN_WORD + ? MAX_WORD + : 0x0FFFF & (( (longword)tmp1 * (longword)tmp2 + + 16384) >> 15)) ; + + sri = GSM_SUB( sri, tmp2 ); + + /* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) ); + */ + tmp1 = ( tmp1 == MIN_WORD && sri == MIN_WORD + ? MAX_WORD + : 0x0FFFF & (( (longword)tmp1 * (longword)sri + + 16384) >> 15)) ; + + v[i+1] = GSM_ADD( v[i], tmp1); + } + *sr++ = v[0] = sri; + } +} + + +#if defined(FAST) && defined(USE_FLOAT_MUL) + +static void Fast_Short_term_synthesis_filtering ( + struct gsm_state * S, + register word * rrp, /* [0..7] IN */ + register int k, /* k_end - k_start */ + register word * wt, /* [0..k-1] IN */ + register word * sr /* [0..k-1] OUT */ +) +{ + register word * v = S->v; + register int i; + + float va[9], rrpa[8]; + register float scalef = 3.0517578125e-5, temp; + + for (i = 0; i < 8; ++i) { + va[i] = v[i]; + rrpa[i] = (float)rrp[i] * scalef; + } + while (k--) { + register float sri = *wt++; + for (i = 8; i--;) { + sri -= rrpa[i] * va[i]; + if (sri < -32768.) sri = -32768.; + else if (sri > 32767.) sri = 32767.; + + temp = va[i] + rrpa[i] * sri; + if (temp < -32768.) temp = -32768.; + else if (temp > 32767.) temp = 32767.; + va[i+1] = temp; + } + *sr++ = va[0] = sri; + } + for (i = 0; i < 9; ++i) v[i] = va[i]; +} + +#endif /* defined(FAST) && defined(USE_FLOAT_MUL) */ + +void Gsm_Short_Term_Analysis_Filter ( + + struct gsm_state * S, + + word * LARc, /* coded log area ratio [0..7] IN */ + word * s /* signal [0..159] IN/OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ]; + + word LARp[8]; + +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) +# define FILTER (* (S->fast \ + ? Fast_Short_term_analysis_filtering \ + : Short_term_analysis_filtering )) + +#else +# define FILTER Short_term_analysis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, s); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 14, s + 13); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, s + 27); + + Coefficients_40_159( LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 120, s + 40); +} + +void Gsm_Short_Term_Synthesis_Filter ( + struct gsm_state * S, + + word * LARcr, /* received log area ratios [0..7] IN */ + word * wt, /* received d [0..159] IN */ + + word * s /* signal s [0..159] OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^=1 ]; + + word LARp[8]; + +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) + +# define FILTER (* (S->fast \ + ? Fast_Short_term_synthesis_filtering \ + : Short_term_synthesis_filtering )) +#else +# define FILTER Short_term_synthesis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt, s ); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 14, wt + 13, s + 13 ); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt + 27, s + 27 ); + + Coefficients_40_159( LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER(S, LARp, 120, wt + 40, s + 40); +} +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 019ac7ba-c6dd-4540-abf0-8644b6c4a633 +*/ + diff --git a/nylsf/GSM610/table.c b/nylsf/GSM610/table.c new file mode 100644 index 0000000..9dd3d98 --- /dev/null +++ b/nylsf/GSM610/table.c @@ -0,0 +1,70 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* Most of these tables are inlined at their point of use. + */ + +/* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP + * CODER AND DECODER + * + * (Most of them inlined, so watch out.) + */ + +#define GSM_TABLE_C +#include "sfconfig.h" // RBD +#include "gsm610_priv.h" +#include "gsm.h" + +/* Table 4.1 Quantization of the Log.-Area Ratios + */ +/* i 1 2 3 4 5 6 7 8 */ +word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036}; +word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144}; +word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 }; +word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 }; + + +/* Table 4.2 Tabulation of 1/A[1..8] + */ +word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 }; + + +/* Table 4.3a Decision level of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_DLB[4] = { 6554, 16384, 26214, 32767 }; + + +/* Table 4.3b Quantization levels of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_QLB[4] = { 3277, 11469, 21299, 32767 }; + + +/* Table 4.4 Coefficients of the weighting filter + */ +/* i 0 1 2 3 4 5 6 7 8 9 10 */ +word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 }; + + +/* Table 4.5 Normalized inverse mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 }; + + +/* Table 4.6 Normalized direct mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 }; +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 8957c531-e6b0-4097-9202-da7ca42729ca +*/ + diff --git a/nylsf/README.txt b/nylsf/README.txt new file mode 100644 index 0000000..b601c47 --- /dev/null +++ b/nylsf/README.txt @@ -0,0 +1,20 @@ +This is libsndfile-1.0.17. +I could not find an easy way to build a universal binary for libsndfile, so +I performed the following steps: + +1) configure and build libsndfile-1.0.17 for the Mac on an intel (i386) machine + (I don't know if this modifies the src directory at all) +2) cd to this directory +2) cp ~/libsndfile-1.0.17/src/*.[ch] . +3) mkdir nylsf/G72x/ +4) cp ~/libsndfile-1.0.17/src/G72x/*.[ch] G72x +5) cp ~/libsndfile-1.0.17/src/G72x/README.original G72x +6) mkdir nylsf/GSM610/ +7) cp ~/libsndfile-1.0.17/src/GSM610/*.[ch] GSM610 +8) cp ~/libsndfile-1.0.17/src/GSM610/README GSM610 +9) add libsndfile target to xcode project and add files to project + except G72x/g72x_test.c, interleave.c, macbinary3.c, macos.c, + test_endswap.c, test_file_io.c, test_log_printf.c + +10) modify config.h, replacing CPU_IS_LITTLE_ENDIAN and + CPU_IS_BIG_ENDIAN code to use defines diff --git a/nylsf/aiff.c b/nylsf/aiff.c new file mode 100644 index 0000000..0a5b6da --- /dev/null +++ b/nylsf/aiff.c @@ -0,0 +1,1516 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** Copyright (C) 2005 David Viens +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*------------------------------------------------------------------------------ + * Macros to handle big/little endian issues. + */ + +#define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M')) +#define AIFF_MARKER (MAKE_MARKER ('A', 'I', 'F', 'F')) +#define AIFC_MARKER (MAKE_MARKER ('A', 'I', 'F', 'C')) +#define COMM_MARKER (MAKE_MARKER ('C', 'O', 'M', 'M')) +#define SSND_MARKER (MAKE_MARKER ('S', 'S', 'N', 'D')) +#define MARK_MARKER (MAKE_MARKER ('M', 'A', 'R', 'K')) +#define INST_MARKER (MAKE_MARKER ('I', 'N', 'S', 'T')) +#define APPL_MARKER (MAKE_MARKER ('A', 'P', 'P', 'L')) + +#define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' ')) +#define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E')) +#define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H')) +#define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O')) +#define COMT_MARKER (MAKE_MARKER ('C', 'O', 'M', 'T')) +#define FVER_MARKER (MAKE_MARKER ('F', 'V', 'E', 'R')) +#define SFX_MARKER (MAKE_MARKER ('S', 'F', 'X', '!')) + +#define PEAK_MARKER (MAKE_MARKER ('P', 'E', 'A', 'K')) +#define basc_MARKER (MAKE_MARKER ('b', 'a', 's', 'c')) + +/* Supported AIFC encodings.*/ +#define NONE_MARKER (MAKE_MARKER ('N', 'O', 'N', 'E')) +#define sowt_MARKER (MAKE_MARKER ('s', 'o', 'w', 't')) +#define twos_MARKER (MAKE_MARKER ('t', 'w', 'o', 's')) +#define raw_MARKER (MAKE_MARKER ('r', 'a', 'w', ' ')) +#define in32_MARKER (MAKE_MARKER ('i', 'n', '3', '2')) +#define ni32_MARKER (MAKE_MARKER ('2', '3', 'n', 'i')) + +#define fl32_MARKER (MAKE_MARKER ('f', 'l', '3', '2')) +#define FL32_MARKER (MAKE_MARKER ('F', 'L', '3', '2')) +#define fl64_MARKER (MAKE_MARKER ('f', 'l', '6', '4')) +#define FL64_MARKER (MAKE_MARKER ('F', 'L', '6', '4')) + +#define ulaw_MARKER (MAKE_MARKER ('u', 'l', 'a', 'w')) +#define ULAW_MARKER (MAKE_MARKER ('U', 'L', 'A', 'W')) +#define alaw_MARKER (MAKE_MARKER ('a', 'l', 'a', 'w')) +#define ALAW_MARKER (MAKE_MARKER ('A', 'L', 'A', 'W')) + +#define DWVW_MARKER (MAKE_MARKER ('D', 'W', 'V', 'W')) +#define GSM_MARKER (MAKE_MARKER ('G', 'S', 'M', ' ')) +#define ima4_MARKER (MAKE_MARKER ('i', 'm', 'a', '4')) + +/* Unsupported AIFC encodings.*/ + +#define MAC3_MARKER (MAKE_MARKER ('M', 'A', 'C', '3')) +#define MAC6_MARKER (MAKE_MARKER ('M', 'A', 'C', '6')) +#define ADP4_MARKER (MAKE_MARKER ('A', 'D', 'P', '4')) + +/* Predfined chunk sizes. */ +#define SIZEOF_AIFF_COMM 18 +#define SIZEOF_AIFC_COMM_MIN 22 +#define SIZEOF_AIFC_COMM 24 +#define SIZEOF_SSND_CHUNK 8 +#define SIZEOF_INST_CHUNK 20 + +/* Is it constant? */ + +/* AIFC/IMA4 defines. */ +#define AIFC_IMA4_BLOCK_LEN 34 +#define AIFC_IMA4_SAMPLES_PER_BLOCK 64 + +#define AIFF_PEAK_CHUNK_SIZE(ch) (2 * sizeof (int) + ch * (sizeof (float) + sizeof (int))) + +/*------------------------------------------------------------------------------ + * Typedefs for file chunks. + */ + +enum +{ HAVE_FORM = 0x01, + HAVE_AIFF = 0x02, + HAVE_AIFC = 0x04, + HAVE_FVER = 0x08, + HAVE_COMM = 0x10, + HAVE_SSND = 0x20 +} ; + +typedef struct +{ unsigned int size ; + short numChannels ; + unsigned int numSampleFrames ; + short sampleSize ; + unsigned char sampleRate [10] ; + unsigned int encoding ; + char zero_bytes [2] ; +} COMM_CHUNK ; + +typedef struct +{ unsigned int offset ; + unsigned int blocksize ; +} SSND_CHUNK ; + +typedef struct +{ short playMode ; + unsigned short beginLoop ; + unsigned short endLoop ; +} INST_LOOP ; + +typedef struct +{ char baseNote ; /* all notes are MIDI note numbers */ + char detune ; /* cents off, only -50 to +50 are significant */ + char lowNote ; + char highNote ; + char lowVelocity ; /* 1 to 127 */ + char highVelocity ; /* 1 to 127 */ + short gain ; /* in dB, 0 is normal */ + INST_LOOP sustain_loop ; + INST_LOOP release_loop ; +} INST_CHUNK ; + + +enum +{ basc_SCALE_MINOR = 1, + basc_SCALE_MAJOR, + basc_SCALE_NEITHER, + basc_SCALE_BOTH +} ; + +enum +{ basc_TYPE_LOOP = 0, + basc_TYPE_ONE_SHOT +} ; + + +typedef struct +{ unsigned int version ; + unsigned int numBeats ; + unsigned short rootNote ; + unsigned short scaleType ; + unsigned short sigNumerator ; + unsigned short sigDenominator ; + unsigned short loopType ; +} basc_CHUNK ; + +typedef struct +{ unsigned short markerID ; + unsigned int position ; +} MARK_ID_POS ; + +typedef struct +{ sf_count_t comm_offset ; + sf_count_t ssnd_offset ; +} AIFF_PRIVATE ; + +/*------------------------------------------------------------------------------ + * Private static functions. + */ + +static int aiff_close (SF_PRIVATE *psf) ; + +static int tenbytefloat2int (unsigned char *bytes) ; +static void uint2tenbytefloat (unsigned int num, unsigned char *bytes) ; + +static int aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; + +static int aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; + +static int aiff_write_header (SF_PRIVATE *psf, int calc_length) ; +static int aiff_write_tailer (SF_PRIVATE *psf) ; +static void aiff_write_strings (SF_PRIVATE *psf, int location) ; + +static int aiff_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; + +static const char *get_loop_mode_str (short mode) ; + +static short get_loop_mode (short mode) ; + +static int aiff_read_basc_chunk (SF_PRIVATE * psf, int) ; + +static unsigned int marker_to_position (const MARK_ID_POS *m, unsigned short n, int marksize) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +aiff_open (SF_PRIVATE *psf) +{ COMM_CHUNK comm_fmt ; + int error, subformat ; + + memset (&comm_fmt, 0, sizeof (comm_fmt)) ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if ((psf->container_data = calloc (1, sizeof (AIFF_PRIVATE))) == NULL) + return SFE_MALLOC_FAILED ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = aiff_read_header (psf, &comm_fmt))) + return error ; + + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AIFF) + return SFE_BAD_OPEN_FORMAT ; + + if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) + { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + psf->peak_info->peak_loc = SF_PEAK_START ; + } ; + + if (psf->mode != SFM_RDWR || psf->filelength < 40) + { psf->filelength = 0 ; + psf->datalength = 0 ; + psf->dataoffset = 0 ; + psf->sf.frames = 0 ; + } ; + + psf->str_flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; + + if ((error = aiff_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = aiff_write_header ; + } ; + + psf->container_close = aiff_close ; + psf->command = aiff_command ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_U8 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_S8 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + + case SF_FORMAT_DWVW_12 : + error = dwvw_init (psf, 12) ; + break ; + + case SF_FORMAT_DWVW_16 : + error = dwvw_init (psf, 16) ; + break ; + + case SF_FORMAT_DWVW_24 : + error = dwvw_init (psf, 24) ; + break ; + + case SF_FORMAT_DWVW_N : + if (psf->mode != SFM_READ) + { error = SFE_DWVW_BAD_BITWIDTH ; + break ; + } ; + if (comm_fmt.sampleSize >= 8 && comm_fmt.sampleSize < 24) + { error = dwvw_init (psf, comm_fmt.sampleSize) ; + psf->sf.frames = comm_fmt.numSampleFrames ; + break ; + } ; + psf_log_printf (psf, "AIFC/DWVW : Bad bitwidth %d\n", comm_fmt.sampleSize) ; + error = SFE_DWVW_BAD_BITWIDTH ; + break ; + + case SF_FORMAT_IMA_ADPCM : + /* + ** IMA ADPCM encoded AIFF files always have a block length + ** of 34 which decodes to 64 samples. + */ + error = aiff_ima_init (psf, AIFC_IMA4_BLOCK_LEN, AIFC_IMA4_SAMPLES_PER_BLOCK) ; + break ; + /* Lite remove end */ + + case SF_FORMAT_GSM610 : + error = gsm610_init (psf) ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + + return error ; +} /* aiff_open */ + +/*========================================================================================== +** Private functions. +*/ + +/* This function ought to check size */ +static unsigned int +marker_to_position (const MARK_ID_POS *m, unsigned short n, int marksize) +{ int i ; + + for (i = 0 ; i < marksize ; i++) + if (m [i].markerID == n) + return m [i].position ; + return 0 ; +} /* marker_to_position */ + +static int +aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) +{ SSND_CHUNK ssnd_fmt ; + MARK_ID_POS *markstr = NULL ; + AIFF_PRIVATE *paiff ; + unsigned marker, dword, FORMsize, SSNDsize, bytesread ; + int k, found_chunk = 0, done = 0, error = 0 ; + char *cptr, byte ; + int instr_found = 0, mark_found = 0, mark_count = 0 ; + + if ((paiff = psf->container_data) == NULL) + return SFE_INTERNAL ; + + paiff->comm_offset = 0 ; + paiff->ssnd_offset = 0 ; + + /* Set position to start of file to begin reading header. */ + psf_binheader_readf (psf, "p", 0) ; + + memset (comm_fmt, 0, sizeof (COMM_CHUNK)) ; + + /* Until recently AIF* file were all BIG endian. */ + psf->endian = SF_ENDIAN_BIG ; + + /* AIFF files can apparently have their chunks in any order. However, they + ** must have a FORM chunk. Approach here is to read all the chunks one by + ** one and then check for the mandatory chunks at the end. + */ + while (! done) + { psf_binheader_readf (psf, "m", &marker) ; + + if (psf->mode == SFM_RDWR && (found_chunk & HAVE_SSND)) + return SFE_AIFF_RW_SSND_NOT_LAST ; + + switch (marker) + { case FORM_MARKER : + if (found_chunk) + return SFE_AIFF_NO_FORM ; + + psf_binheader_readf (psf, "E4", &FORMsize) ; + + if (psf->fileoffset > 0 && psf->filelength > FORMsize + 8) + { /* Set file length. */ + psf->filelength = FORMsize + 8 ; + psf_log_printf (psf, "FORM : %u\n", FORMsize) ; + } + else if (FORMsize != psf->filelength - 2 * SIGNED_SIZEOF (dword)) + { dword = psf->filelength - 2 * sizeof (dword) ; + psf_log_printf (psf, "FORM : %u (should be %u)\n", FORMsize, dword) ; + FORMsize = dword ; + } + else + psf_log_printf (psf, "FORM : %u\n", FORMsize) ; + found_chunk |= HAVE_FORM ; + break ; + + case AIFC_MARKER : + case AIFF_MARKER : + if ((found_chunk & HAVE_FORM) == 0) + return SFE_AIFF_AIFF_NO_FORM ; + psf_log_printf (psf, " %M\n", marker) ; + found_chunk |= (marker == AIFC_MARKER) ? (HAVE_AIFC | HAVE_AIFF) : HAVE_AIFF ; + break ; + + case COMM_MARKER : + paiff->comm_offset = psf_ftell (psf) - 4 ; + error = aiff_read_comm_chunk (psf, comm_fmt) ; + + psf->sf.samplerate = tenbytefloat2int (comm_fmt->sampleRate) ; + psf->sf.frames = comm_fmt->numSampleFrames ; + psf->sf.channels = comm_fmt->numChannels ; + psf->bytewidth = BITWIDTH2BYTES (comm_fmt->sampleSize) ; + + if (error) + return error ; + + found_chunk |= HAVE_COMM ; + break ; + + case PEAK_MARKER : + /* Must have COMM chunk before PEAK chunk. */ + if ((found_chunk & (HAVE_FORM | HAVE_AIFF | HAVE_COMM)) != (HAVE_FORM | HAVE_AIFF | HAVE_COMM)) + return SFE_AIFF_PEAK_B4_COMM ; + + psf_binheader_readf (psf, "E4", &dword) ; + + psf_log_printf (psf, "%M : %d\n", marker, dword) ; + if (dword != AIFF_PEAK_CHUNK_SIZE (psf->sf.channels)) + { psf_binheader_readf (psf, "j", dword) ; + psf_log_printf (psf, "*** File PEAK chunk too big.\n") ; + return SFE_WAV_BAD_PEAK ; + } ; + + if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + + /* read in rest of PEAK chunk. */ + psf_binheader_readf (psf, "E44", &(psf->peak_info->version), &(psf->peak_info->timestamp)) ; + + if (psf->peak_info->version != 1) + psf_log_printf (psf, " version : %d *** (should be version 1)\n", psf->peak_info->version) ; + else + psf_log_printf (psf, " version : %d\n", psf->peak_info->version) ; + + psf_log_printf (psf, " time stamp : %d\n", psf->peak_info->timestamp) ; + psf_log_printf (psf, " Ch Position Value\n") ; + + cptr = psf->u.cbuf ; + for (dword = 0 ; dword < (unsigned) psf->sf.channels ; dword++) + { float value ; + unsigned int position ; + + psf_binheader_readf (psf, "Ef4", &value, &position) ; + psf->peak_info->peaks [dword].value = value ; + psf->peak_info->peaks [dword].position = position ; + + LSF_SNPRINTF (cptr, sizeof (psf->u.scbuf), " %2d %-12ld %g\n", + dword, (long) psf->peak_info->peaks [dword].position, psf->peak_info->peaks [dword].value) ; + cptr [sizeof (psf->u.scbuf) - 1] = 0 ; + psf_log_printf (psf, cptr) ; + } ; + + break ; + + case SSND_MARKER : + if ((found_chunk & HAVE_AIFC) && (found_chunk & HAVE_FVER) == 0) + psf_log_printf (psf, "*** Valid AIFC files should have an FVER chunk.\n") ; + + paiff->ssnd_offset = psf_ftell (psf) - 4 ; + psf_binheader_readf (psf, "E444", &SSNDsize, &(ssnd_fmt.offset), &(ssnd_fmt.blocksize)) ; + + psf->datalength = SSNDsize - sizeof (ssnd_fmt) ; + psf->dataoffset = psf_ftell (psf) ; + + if (psf->datalength > psf->filelength - psf->dataoffset || psf->datalength < 0) + { psf_log_printf (psf, " SSND : %u (should be %D)\n", SSNDsize, psf->filelength - psf->dataoffset + sizeof (SSND_CHUNK)) ; + psf->datalength = psf->filelength - psf->dataoffset ; + } + else + psf_log_printf (psf, " SSND : %u\n", SSNDsize) ; + + /* Only set dataend if there really is data at the end. */ + if (psf->datalength + psf->dataoffset < psf->filelength) + psf->dataend = psf->datalength + psf->dataoffset ; + + psf_log_printf (psf, " Offset : %u\n", ssnd_fmt.offset) ; + psf_log_printf (psf, " Block Size : %u\n", ssnd_fmt.blocksize) ; + + found_chunk |= HAVE_SSND ; + + if (! psf->sf.seekable) + break ; + + /* Seek to end of SSND chunk. */ + psf_fseek (psf, psf->dataoffset + psf->datalength + (SSNDsize & 1), SEEK_SET) ; + break ; + + case c_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + if (dword == 0) + break ; + if (dword > SIGNED_SIZEOF (psf->u.scbuf) - 1) + { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; + return SFE_INTERNAL ; + } ; + + cptr = psf->u.cbuf ; + psf_binheader_readf (psf, "b", cptr, dword + (dword & 1)) ; + cptr [dword] = 0 ; + psf_log_printf (psf, " %M : %s\n", marker, cptr) ; + psf_store_string (psf, SF_STR_COPYRIGHT, cptr) ; + break ; + + case AUTH_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + if (dword == 0) + break ; + if (dword > SIGNED_SIZEOF (psf->u.scbuf) - 1) + { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; + return SFE_INTERNAL ; + } ; + + cptr = psf->u.cbuf ; + psf_binheader_readf (psf, "b", cptr, dword + (dword & 1)) ; + cptr [dword] = 0 ; + psf_log_printf (psf, " %M : %s\n", marker, cptr) ; + psf_store_string (psf, SF_STR_ARTIST, cptr) ; + break ; + + case COMT_MARKER : + { unsigned short count, id, len ; + unsigned int timestamp ; + + psf_binheader_readf (psf, "E42", &dword, &count) ; + psf_log_printf (psf, " %M : %d\n count : %d\n", marker, dword, count) ; + dword += (dword & 1) ; + if (dword == 0) + break ; + dword -= 2 ; + + for (k = 0 ; k < count ; k++) + { dword -= psf_binheader_readf (psf, "E422", ×tamp, &id, &len) ; + psf_log_printf (psf, " time : 0x%x\n marker : %x\n length : %d\n", timestamp, id, len) ; + + if (len + 1 > SIGNED_SIZEOF (psf->u.scbuf)) + { psf_log_printf (psf, "\nError : string length (%d) too big.\n", len) ; + return SFE_INTERNAL ; + } ; + + cptr = psf->u.cbuf ; + dword -= psf_binheader_readf (psf, "b", cptr, len) ; + cptr [len] = 0 ; + psf_log_printf (psf, " string : %s\n", cptr) ; + } ; + + if (dword > 0) + psf_binheader_readf (psf, "j", dword) ; + } ; + break ; + + case APPL_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + if (dword == 0) + break ; + if (dword >= SIGNED_SIZEOF (psf->u.scbuf) - 1) + { psf_log_printf (psf, " %M : %d (too big, skipping)\n", marker, dword) ; + psf_binheader_readf (psf, "j", dword + (dword & 1)) ; + break ; + } ; + + cptr = psf->u.cbuf ; + psf_binheader_readf (psf, "b", cptr, dword + (dword & 1)) ; + cptr [dword] = 0 ; + + for (k = 0 ; k < (int) dword ; k++) + if (! isprint (cptr [k])) + { cptr [k] = 0 ; + break ; + } ; + + psf_log_printf (psf, " %M : %s\n", marker, cptr) ; + psf_store_string (psf, SF_STR_SOFTWARE, cptr) ; + break ; + + case NAME_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + if (dword == 0) + break ; + if (dword > SIGNED_SIZEOF (psf->u.scbuf) - 2) + { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; + return SFE_INTERNAL ; + } ; + + cptr = psf->u.cbuf ; + psf_binheader_readf (psf, "b", cptr, dword + (dword & 1)) ; + cptr [dword] = 0 ; + psf_log_printf (psf, " %M : %s\n", marker, cptr) ; + psf_store_string (psf, SF_STR_TITLE, cptr) ; + break ; + + case ANNO_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + if (dword == 0) + break ; + if (dword > SIGNED_SIZEOF (psf->u.scbuf) - 2) + { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; + return SFE_INTERNAL ; + } ; + + cptr = psf->u.cbuf ; + psf_binheader_readf (psf, "b", cptr, dword + (dword & 1)) ; + cptr [dword] = 0 ; + psf_log_printf (psf, " %M : %s\n", marker, cptr) ; + psf_store_string (psf, SF_STR_COMMENT, cptr) ; + break ; + + case INST_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + if (dword != SIZEOF_INST_CHUNK) + { psf_log_printf (psf, " %M : %d (should be %d)\n", marker, dword, SIZEOF_INST_CHUNK) ; + psf_binheader_readf (psf, "j", dword) ; + break ; + } ; + psf_log_printf (psf, " %M : %d\n", marker, dword) ; + { unsigned char bytes [6] ; + short gain ; + + if (psf->instrument == NULL && (psf->instrument = psf_instrument_alloc ()) == NULL) + return SFE_MALLOC_FAILED ; + + psf_binheader_readf (psf, "b", bytes, 6) ; + psf_log_printf (psf, " Base Note : %u\n Detune : %u\n" + " Low Note : %u\n High Note : %u\n" + " Low Vel. : %u\n High Vel. : %u\n", + bytes [0], bytes [1], bytes [2], bytes [3], bytes [4], bytes [5]) ; + psf->instrument->basenote = bytes [0] ; + psf->instrument->detune = bytes [1] ; + psf->instrument->key_lo = bytes [2] ; + psf->instrument->key_hi = bytes [3] ; + psf->instrument->velocity_lo = bytes [4] ; + psf->instrument->velocity_hi = bytes [5] ; + psf_binheader_readf (psf, "E2", &gain) ; + psf->instrument->gain = gain ; + psf_log_printf (psf, " Gain (dB) : %d\n", gain) ; + } ; + { short mode ; /* 0 - no loop, 1 - forward looping, 2 - backward looping */ + const char *loop_mode ; + unsigned short begin, end ; + + psf_binheader_readf (psf, "E222", &mode, &begin, &end) ; + loop_mode = get_loop_mode_str (mode) ; + mode = get_loop_mode (mode) ; + if (mode == SF_LOOP_NONE) + { psf->instrument->loop_count = 0 ; + psf->instrument->loops [0].mode = SF_LOOP_NONE ; + } + else + { psf->instrument->loop_count = 1 ; + psf->instrument->loops [0].mode = SF_LOOP_FORWARD ; + psf->instrument->loops [0].start = begin ; + psf->instrument->loops [0].end = end ; + psf->instrument->loops [0].count = 0 ; + } ; + psf_log_printf (psf, " Sustain\n mode : %d => %s\n begin : %u\n end : %u\n", + mode, loop_mode, begin, end) ; + psf_binheader_readf (psf, "E222", &mode, &begin, &end) ; + loop_mode = get_loop_mode_str (mode) ; + mode = get_loop_mode (mode) ; + if (mode == SF_LOOP_NONE) + psf->instrument->loops [0].mode = SF_LOOP_NONE ; + else + { psf->instrument->loop_count += 1 ; + psf->instrument->loops [1].mode = SF_LOOP_FORWARD ; + psf->instrument->loops [1].start = begin ; + psf->instrument->loops [1].end = end ; + psf->instrument->loops [1].count = 0 ; + } ; + psf_log_printf (psf, " Release\n mode : %d => %s\n begin : %u\n end : %u\n", + mode, loop_mode, begin, end) ; + } ; + instr_found++ ; + break ; + + case basc_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + psf_log_printf (psf, " basc : %u\n", dword) ; + + if ((error = aiff_read_basc_chunk (psf, dword))) + return error ; + break ; + + case MARK_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + psf_log_printf (psf, " %M : %d\n", marker, dword) ; + { unsigned short mark_id, n = 0 ; + unsigned char pstr_len ; + unsigned int position ; + + bytesread = psf_binheader_readf (psf, "E2", &n) ; + mark_count = n ; + markstr = calloc (mark_count, sizeof (MARK_ID_POS)) ; + psf_log_printf (psf, " Count : %d\n", mark_count) ; + + for (n = 0 ; n < mark_count && bytesread < dword ; n++) + { bytesread += psf_binheader_readf (psf, "E241", &mark_id, &position, &pstr_len) ; + psf_log_printf (psf, " Mark ID : %u\n Position : %u\n", mark_id, position) ; + + pstr_len += (pstr_len & 1) + 1 ; /* fudgy, fudgy, hack, hack */ + + bytesread += psf_binheader_readf (psf, "b", psf->u.scbuf, pstr_len) ; + psf_log_printf (psf, " Name : %s\n", psf->u.scbuf) ; + + markstr [n].markerID = mark_id ; + markstr [n].position = position ; + /* + ** TODO if psf->u.scbuf is equal to + ** either Beg_loop, Beg loop or beg loop and spam + ** if (psf->instrument == NULL && (psf->instrument = psf_instrument_alloc ()) == NULL) + ** return SFE_MALLOC_FAILED ; + */ + } ; + } ; + mark_found++ ; + psf_binheader_readf (psf, "j", dword - bytesread) ; + break ; + + case FVER_MARKER : + found_chunk |= HAVE_FVER ; + /* Fall through to next case. */ + + case SFX_MARKER : + psf_binheader_readf (psf, "E4", &dword) ; + psf_log_printf (psf, " %M : %d\n", marker, dword) ; + + psf_binheader_readf (psf, "j", dword) ; + break ; + + case NONE_MARKER : + /* Fix for broken AIFC files with incorrect COMM chunk length. */ + psf_binheader_readf (psf, "1", &byte) ; + dword = byte ; + psf_binheader_readf (psf, "j", dword) ; + break ; + + default : + if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF) + && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) + { psf_binheader_readf (psf, "E4", &dword) ; + psf_log_printf (psf, " %M : %d (unknown marker)\n", marker, dword) ; + + psf_binheader_readf (psf, "j", dword) ; + break ; + } ; + if ((dword = psf_ftell (psf)) & 0x03) + { psf_log_printf (psf, " Unknown chunk marker %X at position %d. Resyncing.\n", marker, dword - 4) ; + + psf_binheader_readf (psf, "j", -3) ; + break ; + } ; + psf_log_printf (psf, "*** Unknown chunk marker %X at position %D. Exiting parser.\n", marker, psf_ftell (psf)) ; + done = 1 ; + break ; + } ; /* switch (marker) */ + + if ((! psf->sf.seekable) && (found_chunk & HAVE_SSND)) + break ; + + if (psf_ftell (psf) >= psf->filelength - (2 * SIGNED_SIZEOF (dword))) + break ; + } ; /* while (1) */ + + if (instr_found && mark_found) + { int j ; + + for (j = 0 ; jinstrument->loop_count ; j ++) + { if (j < ARRAY_LEN (psf->instrument->loops)) + { psf->instrument->loops [j].start = marker_to_position (markstr, psf->instrument->loops [j].start, mark_count) ; + psf->instrument->loops [j].end = marker_to_position (markstr, psf->instrument->loops [j].end, mark_count) ; + psf->instrument->loops [j].mode = SF_LOOP_FORWARD ; + } ; + } ; + } ; + + if (markstr) + free (markstr) ; + + if (! (found_chunk & HAVE_FORM)) + return SFE_AIFF_NO_FORM ; + + if (! (found_chunk & HAVE_AIFF)) + return SFE_AIFF_COMM_NO_FORM ; + + if (! (found_chunk & HAVE_COMM)) + return SFE_AIFF_SSND_NO_COMM ; + + if (! psf->dataoffset) + return SFE_AIFF_NO_DATA ; + + return 0 ; +} /* aiff_read_header */ + +static int +aiff_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { aiff_write_tailer (psf) ; + aiff_write_header (psf, SF_TRUE) ; + } ; + + return 0 ; +} /* aiff_close */ + +static int +aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) +{ int error = 0, bytesread, subformat ; + + psf->u.scbuf [0] = 0 ; + + bytesread = psf_binheader_readf (psf, "E4", &(comm_fmt->size)) ; + + /* The COMM chunk has an int aligned to an odd word boundary. Some + ** procesors are not able to deal with this (ie bus fault) so we have + ** to take special care. + */ + comm_fmt->size += comm_fmt->size & 1 ; + + bytesread += + psf_binheader_readf (psf, "E242b", &(comm_fmt->numChannels), &(comm_fmt->numSampleFrames), + &(comm_fmt->sampleSize), &(comm_fmt->sampleRate), SIGNED_SIZEOF (comm_fmt->sampleRate)) ; + + if (comm_fmt->size == SIZEOF_AIFF_COMM) + comm_fmt->encoding = NONE_MARKER ; + else if (comm_fmt->size == SIZEOF_AIFC_COMM_MIN) + bytesread += psf_binheader_readf (psf, "Em", &(comm_fmt->encoding)) ; + else if (comm_fmt->size >= SIZEOF_AIFC_COMM) + { unsigned char encoding_len ; + + bytesread += psf_binheader_readf (psf, "Em1", &(comm_fmt->encoding), &encoding_len) ; + + memset (psf->u.scbuf, 0, comm_fmt->size) ; + + bytesread += psf_binheader_readf (psf, "b", psf->u.scbuf, + comm_fmt->size - SIZEOF_AIFC_COMM + 1) ; + psf->u.scbuf [encoding_len] = 0 ; + } ; + + psf_log_printf (psf, " COMM : %d\n", comm_fmt->size) ; + psf_log_printf (psf, " Sample Rate : %d\n", tenbytefloat2int (comm_fmt->sampleRate)) ; + psf_log_printf (psf, " Frames : %u%s\n", comm_fmt->numSampleFrames, (comm_fmt->numSampleFrames == 0 && psf->filelength > 104) ? " (Should not be 0)" : "") ; + psf_log_printf (psf, " Channels : %d\n", comm_fmt->numChannels) ; + + /* Found some broken 'fl32' files with comm.samplesize == 16. Fix it here. */ + if ((comm_fmt->encoding == fl32_MARKER || comm_fmt->encoding == FL32_MARKER) && comm_fmt->sampleSize != 32) + { psf_log_printf (psf, " Sample Size : %d (should be 32)\n", comm_fmt->sampleSize) ; + comm_fmt->sampleSize = 32 ; + } + else if ((comm_fmt->encoding == fl64_MARKER || comm_fmt->encoding == FL64_MARKER) && comm_fmt->sampleSize != 64) + { psf_log_printf (psf, " Sample Size : %d (should be 64)\n", comm_fmt->sampleSize) ; + comm_fmt->sampleSize = 64 ; + } + else + psf_log_printf (psf, " Sample Size : %d\n", comm_fmt->sampleSize) ; + + subformat = s_bitwidth_to_subformat (comm_fmt->sampleSize) ; + + psf->endian = SF_ENDIAN_BIG ; + + switch (comm_fmt->encoding) + { case NONE_MARKER : + psf->sf.format = (SF_FORMAT_AIFF | subformat) ; + break ; + + case twos_MARKER : + case in32_MARKER : + psf->sf.format = (SF_ENDIAN_BIG | SF_FORMAT_AIFF | subformat) ; + break ; + + case sowt_MARKER : + case ni32_MARKER : + psf->endian = SF_ENDIAN_LITTLE ; + psf->sf.format = (SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | subformat) ; + break ; + + case fl32_MARKER : + case FL32_MARKER : + psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ; + break ; + + case ulaw_MARKER : + case ULAW_MARKER : + psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_ULAW) ; + break ; + + case alaw_MARKER : + case ALAW_MARKER : + psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_ALAW) ; + break ; + + case fl64_MARKER : + case FL64_MARKER : + psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_DOUBLE) ; + break ; + + case raw_MARKER : + psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_PCM_U8) ; + break ; + + case DWVW_MARKER : + psf->sf.format = SF_FORMAT_AIFF ; + switch (comm_fmt->sampleSize) + { case 12 : + psf->sf.format |= SF_FORMAT_DWVW_12 ; + break ; + case 16 : + psf->sf.format |= SF_FORMAT_DWVW_16 ; + break ; + case 24 : + psf->sf.format |= SF_FORMAT_DWVW_24 ; + break ; + + default : + psf->sf.format |= SF_FORMAT_DWVW_N ; + break ; + } ; + break ; + + case GSM_MARKER : + psf->sf.format = SF_FORMAT_AIFF ; + psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_GSM610) ; + break ; + + + case ima4_MARKER : + psf->endian = SF_ENDIAN_BIG ; + psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM) ; + break ; + + default : + psf_log_printf (psf, "AIFC : Unimplemented format : %M\n", comm_fmt->encoding) ; + error = SFE_UNIMPLEMENTED ; + } ; + + if (! psf->u.scbuf [0]) + psf_log_printf (psf, " Encoding : %M\n", comm_fmt->encoding) ; + else + psf_log_printf (psf, " Encoding : %M => %s\n", comm_fmt->encoding, psf->u.scbuf) ; + + return error ; +} /* aiff_read_comm_chunk */ + + +static int +aiff_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + AIFF_PRIVATE *paiff ; + unsigned char comm_sample_rate [10], comm_zero_bytes [2] = { 0, 0 } ; + unsigned int comm_type, comm_size, comm_encoding, comm_frames ; + int k, endian ; + short bit_width ; + + if ((paiff = psf->container_data) == NULL) + return SFE_INTERNAL ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + if (psf->mode == SFM_RDWR && psf->dataoffset > 0) + { /* Assuming here that the header has already been written and just + ** needs to be corrected for new data length. That means that we + ** only change the length fields of the FORM and SSND chunks ; + ** everything else can be skipped over. + */ + + /* First write new FORM chunk. */ + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ; + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + /* Now write frame count field of COMM chunk header. */ + psf->headindex = 0 ; + psf_fseek (psf, paiff->comm_offset + 10, SEEK_SET) ; + + psf_binheader_writef (psf, "Et8", psf->sf.frames) ; + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + /* Now write new SSND chunk header. */ + psf->headindex = 0 ; + psf_fseek (psf, paiff->ssnd_offset, SEEK_SET) ; + + psf_binheader_writef (psf, "Etm8", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK) ; + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (current < psf->dataoffset) + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + else if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return 0 ; + } ; + + endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (CPU_IS_LITTLE_ENDIAN && endian == SF_ENDIAN_CPU) + endian = SF_ENDIAN_LITTLE ; + + /* Standard value here. */ + bit_width = psf->bytewidth * 8 ; + comm_frames = (psf->sf.frames > 0xFFFFFFFF) ? 0xFFFFFFFF : psf->sf.frames ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + switch (endian) + { case SF_ENDIAN_BIG : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = twos_MARKER ; + break ; + + case SF_ENDIAN_LITTLE : + psf->endian = SF_ENDIAN_LITTLE ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = sowt_MARKER ; + break ; + + default : /* SF_ENDIAN_FILE */ + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFF_MARKER ; + comm_size = SIZEOF_AIFF_COMM ; + comm_encoding = 0 ; + break ; + } ; + break ; + + case SF_FORMAT_FLOAT : /* Big endian floating point. */ + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = FL32_MARKER ; /* Use 'FL32' because its easier to read. */ + break ; + + case SF_FORMAT_DOUBLE : /* Big endian double precision floating point. */ + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = FL64_MARKER ; /* Use 'FL64' because its easier to read. */ + break ; + + case SF_FORMAT_ULAW : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = ulaw_MARKER ; + break ; + + case SF_FORMAT_ALAW : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = alaw_MARKER ; + break ; + + case SF_FORMAT_PCM_U8 : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = raw_MARKER ; + break ; + + case SF_FORMAT_DWVW_12 : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = DWVW_MARKER ; + + /* Override standard value here.*/ + bit_width = 12 ; + break ; + + case SF_FORMAT_DWVW_16 : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = DWVW_MARKER ; + + /* Override standard value here.*/ + bit_width = 16 ; + break ; + + case SF_FORMAT_DWVW_24 : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = DWVW_MARKER ; + + /* Override standard value here.*/ + bit_width = 24 ; + break ; + + case SF_FORMAT_GSM610 : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = GSM_MARKER ; + + /* Override standard value here.*/ + bit_width = 16 ; + break ; + + case SF_FORMAT_IMA_ADPCM : + psf->endian = SF_ENDIAN_BIG ; + comm_type = AIFC_MARKER ; + comm_size = SIZEOF_AIFC_COMM ; + comm_encoding = ima4_MARKER ; + + /* Override standard value here.*/ + bit_width = 16 ; + comm_frames = psf->sf.frames / AIFC_IMA4_SAMPLES_PER_BLOCK ; + break ; + + default : return SFE_BAD_OPEN_FORMAT ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ; + + /* Write AIFF/AIFC marker and COM chunk. */ + if (comm_type == AIFC_MARKER) + /* AIFC must have an FVER chunk. */ + psf_binheader_writef (psf, "Emm44m4", comm_type, FVER_MARKER, 4, 0xA2805140, COMM_MARKER, comm_size) ; + else + psf_binheader_writef (psf, "Emm4", comm_type, COMM_MARKER, comm_size) ; + + paiff->comm_offset = psf->headindex - 8 ; + + memset (comm_sample_rate, 0, sizeof (comm_sample_rate)) ; + uint2tenbytefloat (psf->sf.samplerate, comm_sample_rate) ; + + psf_binheader_writef (psf, "Et242", psf->sf.channels, comm_frames, bit_width) ; + psf_binheader_writef (psf, "b", comm_sample_rate, sizeof (comm_sample_rate)) ; + + /* AIFC chunks have some extra data. */ + if (comm_type == AIFC_MARKER) + psf_binheader_writef (psf, "mb", comm_encoding, comm_zero_bytes, sizeof (comm_zero_bytes)) ; + + if (psf->instrument != NULL) + { MARK_ID_POS m [4] ; + INST_CHUNK ch ; + unsigned short ct = 0 ; + + memset (m, 0, sizeof (m)) ; + memset (&ch, 0, sizeof (ch)) ; + + ch.baseNote = psf->instrument->basenote ; + ch.detune = psf->instrument->detune ; + ch.lowNote = psf->instrument->key_lo ; + ch.highNote = psf->instrument->key_hi ; + ch.lowVelocity = psf->instrument->velocity_lo ; + ch.highVelocity = psf->instrument->velocity_hi ; + ch.gain = psf->instrument->gain ; + if (psf->instrument->loops [0].mode != SF_LOOP_NONE) + { ch.sustain_loop.playMode = 1 ; + ch.sustain_loop.beginLoop = ct ; + m [0].markerID = ct++ ; + m [0].position = psf->instrument->loops [0].start ; + ch.sustain_loop.endLoop = ct ; + m [1].markerID = ct++ ; + m [1].position = psf->instrument->loops [0].end ; + } ; + if (psf->instrument->loops [1].mode != SF_LOOP_NONE) + { ch.release_loop.playMode = 1 ; + ch.release_loop.beginLoop = ct ; + m [2].markerID = ct++ ; + m [2].position = psf->instrument->loops [1].start ; + ch.release_loop.endLoop = ct ; + m [3].markerID = ct++ ; + m [3].position = psf->instrument->loops [1].end ; + } + else + { ch.release_loop.playMode = 0 ; + ch.release_loop.beginLoop = 0 ; + ch.release_loop.endLoop = 0 ; + } ; + + psf_binheader_writef (psf, "Em4111111", INST_MARKER, SIZEOF_INST_CHUNK, ch.baseNote, ch.detune, + ch.lowNote, ch.highNote, ch.lowVelocity, ch.highVelocity) ; + psf_binheader_writef (psf, "2222222", ch.gain, ch.sustain_loop.playMode, + ch.sustain_loop.beginLoop, ch.sustain_loop.endLoop, ch.release_loop.playMode, + ch.release_loop.beginLoop, ch.release_loop.endLoop) ; + + if (ct == 2) + psf_binheader_writef (psf, "Em42241b241b", + MARK_MARKER, 2 + 2 * (2 + 4 + 1 + 9), 2, + m [0].markerID, m [0].position, 8, "beg loop", make_size_t (9), + m [1].markerID, m [1].position, 8, "end loop", make_size_t (9)) ; + else if (ct == 4) + psf_binheader_writef (psf, "Em42 241b 241b 241b 241b", + MARK_MARKER, 2 + 4 * (2 + 4 + 1 + 9), 4, + m [0].markerID, m [0].position, 8, "beg loop", make_size_t (9), + m [1].markerID, m [1].position, 8, "end loop", make_size_t (9), + m [2].markerID, m [2].position, 8, "beg loop", make_size_t (9), + m [3].markerID, m [3].position, 8, "end loop", make_size_t (9)) ; + } ; + + if (psf->str_flags & SF_STR_LOCATE_START) + aiff_write_strings (psf, SF_STR_LOCATE_START) ; + + if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START) + { psf_binheader_writef (psf, "Em4", PEAK_MARKER, AIFF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; + psf_binheader_writef (psf, "E44", 1, time (NULL)) ; + for (k = 0 ; k < psf->sf.channels ; k++) + psf_binheader_writef (psf, "Eft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; + } ; + + /* Write SSND chunk. */ + paiff->ssnd_offset = psf->headindex ; + psf_binheader_writef (psf, "Etm844", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK, 0, 0) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current < psf->dataoffset) + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + else if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* aiff_write_header */ + +static int +aiff_write_tailer (SF_PRIVATE *psf) +{ int k ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + psf->dataend = psf_fseek (psf, 0, SEEK_END) ; + + /* Make sure tailer data starts at even byte offset. Pad if necessary. */ + if (psf->dataend % 2 == 1) + { psf_fwrite (psf->header, 1, 1, psf) ; + psf->dataend ++ ; + } ; + + if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_END) + { psf_binheader_writef (psf, "Em4", PEAK_MARKER, AIFF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; + psf_binheader_writef (psf, "E44", 1, time (NULL)) ; + for (k = 0 ; k < psf->sf.channels ; k++) + psf_binheader_writef (psf, "Eft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; + } ; + + if (psf->str_flags & SF_STR_LOCATE_END) + aiff_write_strings (psf, SF_STR_LOCATE_END) ; + + /* Write the tailer. */ + if (psf->headindex > 0) + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + return 0 ; +} /* aiff_write_tailer */ + +static void +aiff_write_strings (SF_PRIVATE *psf, int location) +{ int k ; + + for (k = 0 ; k < SF_MAX_STRINGS ; k++) + { if (psf->strings [k].type == 0) + break ; + + if (psf->strings [k].flags != location) + continue ; + + switch (psf->strings [k].type) + { case SF_STR_SOFTWARE : + psf_binheader_writef (psf, "EmS", APPL_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_TITLE : + psf_binheader_writef (psf, "EmS", NAME_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_COPYRIGHT : + psf_binheader_writef (psf, "EmS", c_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_ARTIST : + psf_binheader_writef (psf, "EmS", AUTH_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_COMMENT : + psf_binheader_writef (psf, "EmS", ANNO_MARKER, psf->strings [k].str) ; + break ; + + /* + case SF_STR_DATE : + psf_binheader_writef (psf, "Ems", ICRD_MARKER, psf->strings [k].str) ; + break ; + */ + } ; + } ; + + return ; +} /* aiff_write_strings */ + +static int +aiff_command (SF_PRIVATE *psf, int command, void *data, int datasize) +{ + /* Avoid compiler warnings. */ + psf = psf ; + data = data ; + datasize = datasize ; + + switch (command) + { default : break ; + } ; + + return 0 ; +} /* aiff_command */ + +static const char* +get_loop_mode_str (short mode) +{ switch (mode) + { case 0 : return "none" ; + case 1 : return "forward" ; + case 2 : return "backward" ; + } ; + + return "*** unknown" ; +} /* get_loop_mode_str */ + +static short +get_loop_mode (short mode) +{ switch (mode) + { case 0 : return SF_LOOP_NONE ; + case 1 : return SF_LOOP_FORWARD ; + case 2 : return SF_LOOP_BACKWARD ; + } ; + + return SF_LOOP_NONE ; +} /* get_loop_mode */ + +/*========================================================================================== +** Rough hack at converting from 80 bit IEEE float in AIFF header to an int and +** back again. It assumes that all sample rates are between 1 and 800MHz, which +** should be OK as other sound file formats use a 32 bit integer to store sample +** rate. +** There is another (probably better) version in the source code to the SoX but it +** has a copyright which probably prevents it from being allowable as GPL/LGPL. +*/ + +static int +tenbytefloat2int (unsigned char *bytes) +{ int val = 3 ; + + if (bytes [0] & 0x80) /* Negative number. */ + return 0 ; + + if (bytes [0] <= 0x3F) /* Less than 1. */ + return 1 ; + + if (bytes [0] > 0x40) /* Way too big. */ + return 0x4000000 ; + + if (bytes [0] == 0x40 && bytes [1] > 0x1C) /* Too big. */ + return 800000000 ; + + /* Ok, can handle it. */ + + val = (bytes [2] << 23) | (bytes [3] << 15) | (bytes [4] << 7) | (bytes [5] >> 1) ; + + val >>= (29 - bytes [1]) ; + + return val ; +} /* tenbytefloat2int */ + +static void +uint2tenbytefloat (unsigned int num, unsigned char *bytes) +{ unsigned int mask = 0x40000000 ; + int count ; + + if (num <= 1) + { bytes [0] = 0x3F ; + bytes [1] = 0xFF ; + bytes [2] = 0x80 ; + return ; + } ; + + bytes [0] = 0x40 ; + + if (num >= mask) + { bytes [1] = 0x1D ; + return ; + } ; + + for (count = 0 ; count <= 32 ; count ++) + { if (num & mask) + break ; + mask >>= 1 ; + } ; + + num <<= count + 1 ; + bytes [1] = 29 - count ; + bytes [2] = (num >> 24) & 0xFF ; + bytes [3] = (num >> 16) & 0xFF ; + bytes [4] = (num >> 8) & 0xFF ; + bytes [5] = num & 0xFF ; + +} /* uint2tenbytefloat */ + +static int +aiff_read_basc_chunk (SF_PRIVATE * psf, int datasize) +{ const char * type_str ; + basc_CHUNK bc ; + + psf_binheader_readf (psf, "E442", &bc.version, &bc.numBeats, &bc.rootNote) ; + psf_binheader_readf (psf, "E222", &bc.scaleType, &bc.sigNumerator, &bc.sigDenominator) ; + psf_binheader_readf (psf, "E2j", &bc.loopType, datasize - sizeof (bc)) ; + + psf_log_printf (psf, " Version ? : %u\n Num Beats : %u\n Root Note : 0x%x\n", + bc.version, bc.numBeats, bc.rootNote) ; + + switch (bc.scaleType) + { case basc_SCALE_MINOR : + type_str = "MINOR" ; + break ; + case basc_SCALE_MAJOR : + type_str = "MAJOR" ; + break ; + case basc_SCALE_NEITHER : + type_str = "NEITHER" ; + break ; + case basc_SCALE_BOTH : + type_str = "BOTH" ; + break ; + default : + type_str = "!!WRONG!!" ; + break ; + } ; + + psf_log_printf (psf, " ScaleType : 0x%x (%s)\n", bc.scaleType, type_str) ; + psf_log_printf (psf, " Time Sig : %d/%d\n", bc.sigNumerator, bc.sigDenominator) ; + + switch (bc.loopType) + { case basc_TYPE_ONE_SHOT : + type_str = "One Shot" ; + break ; + case basc_TYPE_LOOP : + type_str = "Loop" ; + break ; + default: + type_str = "!!WRONG!!" ; + break ; + } ; + + psf_log_printf (psf, " Loop Type : 0x%x (%s)\n", bc.loopType, type_str) ; + + if ((psf->loop_info = calloc (1, sizeof (SF_LOOP_INFO))) == NULL) + return SFE_MALLOC_FAILED ; + + psf->loop_info->time_sig_num = bc.sigNumerator ; + psf->loop_info->time_sig_den = bc.sigDenominator ; + psf->loop_info->loop_mode = (bc.loopType == basc_TYPE_ONE_SHOT) ? SF_LOOP_NONE : SF_LOOP_FORWARD ; + psf->loop_info->num_beats = bc.numBeats ; + + /* Can always be recalculated from other known fields. */ + psf->loop_info->bpm = (1.0 / psf->sf.frames) * psf->sf.samplerate + * ((bc.numBeats * 4.0) / bc.sigDenominator) * 60.0 ; + psf->loop_info->root_key = bc.rootNote ; + + return 0 ; +} /* aiff_read_basc_chunk */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 7dec56ca-d6f2-48cf-863b-a72e7e17a5d9 +*/ diff --git a/nylsf/alaw.c b/nylsf/alaw.c new file mode 100644 index 0000000..a2d27cb --- /dev/null +++ b/nylsf/alaw.c @@ -0,0 +1,544 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sndfile.h" +#include "float_cast.h" +#include "common.h" + +static sf_count_t alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static void alaw2s_array (unsigned char *buffer, int count, short *ptr) ; +static void alaw2i_array (unsigned char *buffer, int count, int *ptr) ; +static void alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) ; +static void alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact) ; + +static void s2alaw_array (const short *buffer, int count, unsigned char *ptr) ; +static void i2alaw_array (const int *buffer, int count, unsigned char *ptr) ; +static void f2alaw_array (const float *buffer, int count, unsigned char *ptr, float normfact) ; +static void d2alaw_array (const double *buffer, int count, unsigned char *ptr, double normfact) ; + + +int +alaw_init (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { psf->read_short = alaw_read_alaw2s ; + psf->read_int = alaw_read_alaw2i ; + psf->read_float = alaw_read_alaw2f ; + psf->read_double = alaw_read_alaw2d ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { psf->write_short = alaw_write_s2alaw ; + psf->write_int = alaw_write_i2alaw ; + psf->write_float = alaw_write_f2alaw ; + psf->write_double = alaw_write_d2alaw ; + } ; + + psf->bytewidth = 1 ; + psf->blockwidth = psf->sf.channels ; + + if (psf->filelength > psf->dataoffset) + psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; + else + psf->datalength = 0 ; + + psf->sf.frames = psf->datalength / psf->blockwidth ; + + return 0 ; +} /* alaw_init */ + +/*============================================================================== + * Private static functions and data. + */ + +static +short alaw_decode [256] = +{ -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, + -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, + -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, + -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848 +} ; /* alaw_decode */ + +static +unsigned char alaw_encode [2048 + 1] = +{ 0xd5, 0xd4, 0xd7, 0xd6, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, + 0xd9, 0xd8, 0xdb, 0xda, 0xc5, 0xc4, 0xc7, 0xc6, 0xc1, 0xc0, 0xc3, 0xc2, + 0xcd, 0xcc, 0xcf, 0xce, 0xc9, 0xc8, 0xcb, 0xca, 0xf5, 0xf5, 0xf4, 0xf4, + 0xf7, 0xf7, 0xf6, 0xf6, 0xf1, 0xf1, 0xf0, 0xf0, 0xf3, 0xf3, 0xf2, 0xf2, + 0xfd, 0xfd, 0xfc, 0xfc, 0xff, 0xff, 0xfe, 0xfe, 0xf9, 0xf9, 0xf8, 0xf8, + 0xfb, 0xfb, 0xfa, 0xfa, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe1, 0xe1, 0xe1, 0xe1, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, + 0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xef, 0xef, 0xef, 0xef, + 0xee, 0xee, 0xee, 0xee, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8, + 0xeb, 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a +} ; /* alaw_encode */ + +static inline void +alaw2s_array (unsigned char *buffer, int count, short *ptr) +{ while (--count >= 0) + ptr [count] = alaw_decode [(int) buffer [count]] ; +} /* alaw2s_array */ + +static inline void +alaw2i_array (unsigned char *buffer, int count, int *ptr) +{ while (--count >= 0) + ptr [count] = alaw_decode [(int) buffer [count]] << 16 ; +} /* alaw2i_array */ + +static inline void +alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) +{ while (--count >= 0) + ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; +} /* alaw2f_array */ + +static inline void +alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact) +{ while (--count >= 0) + ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; +} /* alaw2d_array */ + +static inline void +s2alaw_array (const short *ptr, int count, unsigned char *buffer) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = alaw_encode [ptr [count] / 16] ; + else + buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ; + } ; +} /* s2alaw_array */ + +static inline void +i2alaw_array (const int *ptr, int count, unsigned char *buffer) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ; + else + buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ; + } ; +} /* i2alaw_array */ + +static inline void +f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = alaw_encode [lrintf (normfact * ptr [count])] ; + else + buffer [count] = 0x7F & alaw_encode [- lrintf (normfact * ptr [count])] ; + } ; +} /* f2alaw_array */ + +static inline void +d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = alaw_encode [lrint (normfact * ptr [count])] ; + else + buffer [count] = 0x7F & alaw_encode [- lrint (normfact * ptr [count])] ; + } ; +} /* d2alaw_array */ + +/*============================================================================== +*/ + +static sf_count_t +alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + alaw2s_array (psf->u.ucbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* alaw_read_alaw2s */ + +static sf_count_t +alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + alaw2i_array (psf->u.ucbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* alaw_read_alaw2i */ + +static sf_count_t +alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + alaw2f_array (psf->u.ucbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* alaw_read_alaw2f */ + +static sf_count_t +alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double) ? 1.0 / ((double) 0x8000) : 1.0 ; + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + alaw2d_array (psf->u.ucbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* alaw_read_alaw2d */ + +/*============================================================================================= +*/ + +static sf_count_t +alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* alaw_write_s2alaw */ + +static sf_count_t +alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* alaw_write_i2alaw */ + +static sf_count_t +alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + f2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* alaw_write_f2alaw */ + +static sf_count_t +alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + d2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* alaw_write_d2alaw */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 289ccfc2-42a6-4f1f-a29f-4dcc9bfa8752 +*/ diff --git a/nylsf/au.c b/nylsf/au.c new file mode 100644 index 0000000..3a5f93b --- /dev/null +++ b/nylsf/au.c @@ -0,0 +1,453 @@ +/* +** Copyright (C) 1999-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define DOTSND_MARKER (MAKE_MARKER ('.', 's', 'n', 'd')) +#define DNSDOT_MARKER (MAKE_MARKER ('d', 'n', 's', '.')) + +#define AU_DATA_OFFSET 24 + +/*------------------------------------------------------------------------------ +** Known AU file encoding types. +*/ + +enum +{ AU_ENCODING_ULAW_8 = 1, /* 8-bit u-law samples */ + AU_ENCODING_PCM_8 = 2, /* 8-bit linear samples */ + AU_ENCODING_PCM_16 = 3, /* 16-bit linear samples */ + AU_ENCODING_PCM_24 = 4, /* 24-bit linear samples */ + AU_ENCODING_PCM_32 = 5, /* 32-bit linear samples */ + + AU_ENCODING_FLOAT = 6, /* floating-point samples */ + AU_ENCODING_DOUBLE = 7, /* double-precision float samples */ + AU_ENCODING_INDIRECT = 8, /* fragmented sampled data */ + AU_ENCODING_NESTED = 9, /* ? */ + AU_ENCODING_DSP_CORE = 10, /* DSP program */ + AU_ENCODING_DSP_DATA_8 = 11, /* 8-bit fixed-point samples */ + AU_ENCODING_DSP_DATA_16 = 12, /* 16-bit fixed-point samples */ + AU_ENCODING_DSP_DATA_24 = 13, /* 24-bit fixed-point samples */ + AU_ENCODING_DSP_DATA_32 = 14, /* 32-bit fixed-point samples */ + + AU_ENCODING_DISPLAY = 16, /* non-audio display data */ + AU_ENCODING_MULAW_SQUELCH = 17, /* ? */ + AU_ENCODING_EMPHASIZED = 18, /* 16-bit linear with emphasis */ + AU_ENCODING_NEXT = 19, /* 16-bit linear with compression (NEXT) */ + AU_ENCODING_COMPRESSED_EMPHASIZED = 20, /* A combination of the two above */ + AU_ENCODING_DSP_COMMANDS = 21, /* Music Kit DSP commands */ + AU_ENCODING_DSP_COMMANDS_SAMPLES = 22, /* ? */ + + AU_ENCODING_ADPCM_G721_32 = 23, /* G721 32 kbs ADPCM - 4 bits per sample. */ + AU_ENCODING_ADPCM_G722 = 24, /* G722 64 kbs ADPCM */ + AU_ENCODING_ADPCM_G723_24 = 25, /* G723 24 kbs ADPCM - 3 bits per sample. */ + AU_ENCODING_ADPCM_G723_40 = 26, /* G723 40 kbs ADPCM - 5 bits per sample. */ + + AU_ENCODING_ALAW_8 = 27 +} ; + +/*------------------------------------------------------------------------------ +** Typedefs. +*/ + +typedef struct +{ int dataoffset ; + int datasize ; + int encoding ; + int samplerate ; + int channels ; +} AU_FMT ; + + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int au_close (SF_PRIVATE *psf) ; + +static int au_format_to_encoding (int format) ; + +static int au_write_header (SF_PRIVATE *psf, int calc_length) ; +static int au_read_header (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +au_open (SF_PRIVATE *psf) +{ int subformat ; + int error = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = au_read_header (psf))) + return error ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AU) + return SFE_BAD_OPEN_FORMAT ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU) + psf->endian = SF_ENDIAN_LITTLE ; + else if (psf->endian != SF_ENDIAN_LITTLE) + psf->endian = SF_ENDIAN_BIG ; + + if (au_write_header (psf, SF_FALSE)) + return psf->error ; + + psf->write_header = au_write_header ; + } ; + + psf->container_close = au_close ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */ + ulaw_init (psf) ; + break ; + + case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */ + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ + case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */ + case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */ + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */ + alaw_init (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_FLOAT : /* 32-bit floats. */ + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : /* 64-bit double precision floats. */ + error = double64_init (psf) ; + break ; + + case SF_FORMAT_G721_32 : + error = g72x_init (psf) ; + psf->sf.seekable = SF_FALSE ; + break ; + + case SF_FORMAT_G723_24 : + error = g72x_init (psf) ; + psf->sf.seekable = SF_FALSE ; + break ; + + case SF_FORMAT_G723_40 : + error = g72x_init (psf) ; + psf->sf.seekable = SF_FALSE ; + break ; + /* Lite remove end */ + + default : break ; + } ; + + return error ; +} /* au_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +au_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + au_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* au_close */ + +static int +au_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + int encoding, datalength ; + + if (psf->pipeoffset > 0) + return 0 ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + encoding = au_format_to_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ; + if (! encoding) + return (psf->error = SFE_BAD_OPEN_FORMAT) ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + /* + ** Only attempt to seek if we are not writng to a pipe. If we are + ** writing to a pipe we shouldn't be here anyway. + */ + if (psf->is_pipe == SF_FALSE) + psf_fseek (psf, 0, SEEK_SET) ; + + /* + ** AU format files allow a datalength value of -1 if the datalength + ** is not know at the time the header is written. + ** Also use this value of -1 if the datalength > 2 gigabytes. + */ + if (psf->datalength < 0 || psf->datalength > 0x7FFFFFFF) + datalength = -1 ; + else + datalength = (int) (psf->datalength & 0x7FFFFFFF) ; + + if (psf->endian == SF_ENDIAN_BIG) + { psf_binheader_writef (psf, "Em4", DOTSND_MARKER, AU_DATA_OFFSET) ; + psf_binheader_writef (psf, "E4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ; + } + else if (psf->endian == SF_ENDIAN_LITTLE) + { psf_binheader_writef (psf, "em4", DNSDOT_MARKER, AU_DATA_OFFSET) ; + psf_binheader_writef (psf, "e4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ; + } + else + return (psf->error = SFE_BAD_OPEN_FORMAT) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* au_write_header */ + +static int +au_format_to_encoding (int format) +{ + switch (format) + { case SF_FORMAT_PCM_S8 : return AU_ENCODING_PCM_8 ; + case SF_FORMAT_PCM_16 : return AU_ENCODING_PCM_16 ; + case SF_FORMAT_PCM_24 : return AU_ENCODING_PCM_24 ; + case SF_FORMAT_PCM_32 : return AU_ENCODING_PCM_32 ; + + case SF_FORMAT_FLOAT : return AU_ENCODING_FLOAT ; + case SF_FORMAT_DOUBLE : return AU_ENCODING_DOUBLE ; + + case SF_FORMAT_ULAW : return AU_ENCODING_ULAW_8 ; + case SF_FORMAT_ALAW : return AU_ENCODING_ALAW_8 ; + + case SF_FORMAT_G721_32 : return AU_ENCODING_ADPCM_G721_32 ; + case SF_FORMAT_G723_24 : return AU_ENCODING_ADPCM_G723_24 ; + case SF_FORMAT_G723_40 : return AU_ENCODING_ADPCM_G723_40 ; + + default : break ; + } ; + return 0 ; +} /* au_format_to_encoding */ + +static int +au_read_header (SF_PRIVATE *psf) +{ AU_FMT au_fmt ; + int marker, dword ; + + memset (&au_fmt, 0, sizeof (au_fmt)) ; + psf_binheader_readf (psf, "pm", 0, &marker) ; + psf_log_printf (psf, "%M\n", marker) ; + + if (marker == DOTSND_MARKER) + { psf->endian = SF_ENDIAN_BIG ; + + psf_binheader_readf (psf, "E44444", &(au_fmt.dataoffset), &(au_fmt.datasize), + &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ; + } + else if (marker == DNSDOT_MARKER) + { psf->endian = SF_ENDIAN_LITTLE ; + psf_binheader_readf (psf, "e44444", &(au_fmt.dataoffset), &(au_fmt.datasize), + &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ; + } + else + return SFE_AU_NO_DOTSND ; + + psf_log_printf (psf, " Data Offset : %d\n", au_fmt.dataoffset) ; + + if (psf->fileoffset > 0 && au_fmt.datasize == -1) + { psf_log_printf (psf, " Data Size : -1\n") ; + return SFE_AU_EMBED_BAD_LEN ; + } ; + + if (psf->fileoffset > 0) + { psf->filelength = au_fmt.dataoffset + au_fmt.datasize ; + psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; + } + else if (au_fmt.datasize == -1 || au_fmt.dataoffset + au_fmt.datasize == psf->filelength) + psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; + else if (au_fmt.dataoffset + au_fmt.datasize < psf->filelength) + { psf->filelength = au_fmt.dataoffset + au_fmt.datasize ; + psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; + } + else + { dword = psf->filelength - au_fmt.dataoffset ; + psf_log_printf (psf, " Data Size : %d (should be %d)\n", au_fmt.datasize, dword) ; + au_fmt.datasize = dword ; + } ; + + psf->dataoffset = au_fmt.dataoffset ; + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf_ftell (psf) < psf->dataoffset) + psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ; + + psf->sf.samplerate = au_fmt.samplerate ; + psf->sf.channels = au_fmt.channels ; + + /* Only fill in type major. */ + if (psf->endian == SF_ENDIAN_BIG) + psf->sf.format = SF_FORMAT_AU ; + else if (psf->endian == SF_ENDIAN_LITTLE) + psf->sf.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU ; + + psf_log_printf (psf, " Encoding : %d => ", au_fmt.encoding) ; + + psf->sf.format = psf->sf.format & SF_FORMAT_ENDMASK ; + + switch (au_fmt.encoding) + { case AU_ENCODING_ULAW_8 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ULAW ; + psf->bytewidth = 1 ; /* Before decoding */ + psf_log_printf (psf, "8-bit ISDN u-law\n") ; + break ; + + case AU_ENCODING_PCM_8 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_S8 ; + psf->bytewidth = 1 ; + psf_log_printf (psf, "8-bit linear PCM\n") ; + break ; + + case AU_ENCODING_PCM_16 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + psf_log_printf (psf, "16-bit linear PCM\n") ; + break ; + + case AU_ENCODING_PCM_24 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_24 ; + psf->bytewidth = 3 ; + psf_log_printf (psf, "24-bit linear PCM\n") ; + break ; + + case AU_ENCODING_PCM_32 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_32 ; + psf->bytewidth = 4 ; + psf_log_printf (psf, "32-bit linear PCM\n") ; + break ; + + case AU_ENCODING_FLOAT : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_FLOAT ; + psf->bytewidth = 4 ; + psf_log_printf (psf, "32-bit float\n") ; + break ; + + case AU_ENCODING_DOUBLE : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_DOUBLE ; + psf->bytewidth = 8 ; + psf_log_printf (psf, "64-bit double precision float\n") ; + break ; + + case AU_ENCODING_ALAW_8 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ALAW ; + psf->bytewidth = 1 ; /* Before decoding */ + psf_log_printf (psf, "8-bit ISDN A-law\n") ; + break ; + + case AU_ENCODING_ADPCM_G721_32 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G721_32 ; + psf->bytewidth = 0 ; + psf_log_printf (psf, "G721 32kbs ADPCM\n") ; + break ; + + case AU_ENCODING_ADPCM_G723_24 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_24 ; + psf->bytewidth = 0 ; + psf_log_printf (psf, "G723 24kbs ADPCM\n") ; + break ; + + case AU_ENCODING_ADPCM_G723_40 : + psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_40 ; + psf->bytewidth = 0 ; + psf_log_printf (psf, "G723 40kbs ADPCM\n") ; + break ; + + case AU_ENCODING_ADPCM_G722 : + psf_log_printf (psf, "G722 64 kbs ADPCM (unsupported)\n") ; + break ; + + case AU_ENCODING_NEXT : + psf_log_printf (psf, "Weird NeXT encoding format (unsupported)\n") ; + break ; + + default : + psf_log_printf (psf, "Unknown!!\n") ; + break ; + } ; + + psf_log_printf (psf, " Sample Rate : %d\n", au_fmt.samplerate) ; + psf_log_printf (psf, " Channels : %d\n", au_fmt.channels) ; + + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + if (! psf->sf.frames && psf->blockwidth) + psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; + + return 0 ; +} /* au_read_header */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 31f691b1-cde9-4ed2-9469-6bca60fb9cd0 +*/ diff --git a/nylsf/avr.c b/nylsf/avr.c new file mode 100644 index 0000000..ad02c04 --- /dev/null +++ b/nylsf/avr.c @@ -0,0 +1,254 @@ +/* +** Copyright (C) 2004-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T')) +#define AVR_HDR_SIZE 128 + +#define SFE_AVR_X 666 + +/* +** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu) +** +** A lot of PD software exists to play Mac .snd files on the ST. One other +** format that seems pretty popular (used by a number of commercial packages) +** is the AVR format (from Audio Visual Research). This format has a 128 byte +** header that looks like this (its actually packed, but thats not portable): +*/ + +typedef struct +{ int marker ; /* 2BIT */ + char name [8] ; /* null-padded sample name */ + short mono ; /* 0 = mono, 0xffff = stereo */ + short rez ; /* 8 = 8 bit, 16 = 16 bit */ + short sign ; /* 0 = unsigned, 0xffff = signed */ + + short loop ; /* 0 = no loop, 0xffff = looping sample */ + short midi ; /* 0xffff = no MIDI note assigned, */ + /* 0xffXX = single key note assignment */ + /* 0xLLHH = key split, low/hi note */ + int srate ; /* sample frequency in hertz */ + int frames ; /* sample length in bytes or words (see rez) */ + int lbeg ; /* offset to start of loop in bytes or words. */ + /* set to zero if unused */ + int lend ; /* offset to end of loop in bytes or words. */ + /* set to sample length if unused */ + short res1 ; /* Reserved, MIDI keyboard split */ + short res2 ; /* Reserved, sample compression */ + short res3 ; /* Reserved */ + char ext [20] ; /* Additional filename space, used if (name[7] != 0) */ + char user [64] ; /* User defined. Typically ASCII message */ +} AVR_HEADER ; + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int avr_close (SF_PRIVATE *psf) ; + +static int avr_read_header (SF_PRIVATE *psf) ; +static int avr_write_header (SF_PRIVATE *psf, int calc_length) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +avr_open (SF_PRIVATE *psf) +{ int error = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = avr_read_header (psf))) + return error ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AVR) + return SFE_BAD_OPEN_FORMAT ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + psf->endian = SF_ENDIAN_BIG ; + + if (avr_write_header (psf, SF_FALSE)) + return psf->error ; + + psf->write_header = avr_write_header ; + } ; + + psf->container_close = avr_close ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + error = pcm_init (psf) ; + + return error ; +} /* avr_open */ + +static int +avr_read_header (SF_PRIVATE *psf) +{ AVR_HEADER hdr ; + + memset (&hdr, 0, sizeof (hdr)) ; + + psf_binheader_readf (psf, "pmb", 0, &hdr.marker, &hdr.name, sizeof (hdr.name)) ; + psf_log_printf (psf, "%M\n", hdr.marker) ; + + if (hdr.marker != TWOBIT_MARKER) + return SFE_AVR_X ; + + psf_log_printf (psf, " Name : %s\n", hdr.name) ; + + psf_binheader_readf (psf, "E22222", &hdr.mono, &hdr.rez, &hdr.sign, &hdr.loop, &hdr.midi) ; + + psf->sf.channels = (hdr.mono & 1) + 1 ; + + psf_log_printf (psf, " Channels : %d\n Bit width : %d\n Signed : %s\n", + (hdr.mono & 1) + 1, hdr.rez, hdr.sign ? "yes" : "no") ; + + switch ((hdr.rez << 16) + (hdr.sign & 1)) + { case ((8 << 16) + 0) : + psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_U8 ; + psf->bytewidth = 1 ; + break ; + + case ((8 << 16) + 1) : + psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_S8 ; + psf->bytewidth = 1 ; + break ; + + case ((16 << 16) + 1) : + psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + break ; + + default : + psf_log_printf (psf, "Error : bad rez/sign combination.\n") ; + return SFE_AVR_X ; + } ; + + psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ; + + psf->sf.frames = hdr.frames ; + psf->sf.samplerate = hdr.srate ; + + psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ; + psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ; + + psf_binheader_readf (psf, "E222", &hdr.res1, &hdr.res2, &hdr.res3) ; + psf_binheader_readf (psf, "bb", hdr.ext, sizeof (hdr.ext), hdr.user, sizeof (hdr.user)) ; + + psf_log_printf (psf, " Ext : %s\n User : %s\n", hdr.ext, hdr.user) ; + + psf->endian = SF_ENDIAN_BIG ; + + psf->dataoffset = AVR_HDR_SIZE ; + psf->datalength = hdr.frames * (hdr.rez / 8) ; + + if (psf->fileoffset > 0) + psf->filelength = AVR_HDR_SIZE + psf->datalength ; + + if (psf_ftell (psf) != psf->dataoffset) + psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ; + + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + if (psf->sf.frames == 0 && psf->blockwidth) + psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; + + return 0 ; +} /* avr_read_header */ + +static int +avr_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + int sign ; + + if (psf->pipeoffset > 0) + return 0 ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + /* + ** Only attempt to seek if we are not writng to a pipe. If we are + ** writing to a pipe we shouldn't be here anyway. + */ + if (psf->is_pipe == SF_FALSE) + psf_fseek (psf, 0, SEEK_SET) ; + + psf_binheader_writef (psf, "Emz22", TWOBIT_MARKER, make_size_t (8), + psf->sf.channels == 2 ? 0xFFFF : 0, psf->bytewidth * 8) ; + + sign = ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_U8) ? 0 : 0xFFFF ; + + psf_binheader_writef (psf, "E222", sign, 0, 0xFFFF) ; + psf_binheader_writef (psf, "E4444", psf->sf.samplerate, psf->sf.frames, 0, 0) ; + + psf_binheader_writef (psf, "E222zz", 0, 0, 0, make_size_t (20), make_size_t (64)) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* avr_write_header */ + +static int +avr_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + avr_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* avr_close */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 0823d454-f39a-4a28-a776-607f1ef33b52 +*/ diff --git a/nylsf/broadcast.c b/nylsf/broadcast.c new file mode 100644 index 0000000..e332277 --- /dev/null +++ b/nylsf/broadcast.c @@ -0,0 +1,89 @@ +/* +** Copyright (C) 2006 Paul Davis +** Copyright (C) 2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include + +#include "common.h" + +/* +** Allocate and initialize a broadcast info structure. +*/ + +SF_BROADCAST_INFO* +broadcast_info_alloc (void) +{ SF_BROADCAST_INFO* bext ; + + if ((bext = calloc (1, sizeof (SF_BROADCAST_INFO))) == NULL) + return NULL ; + + return bext ; +} /* broadcast_info_alloc */ + +int +broadcast_info_copy (SF_BROADCAST_INFO* dst, SF_BROADCAST_INFO* src) +{ memcpy (dst, src, sizeof (SF_BROADCAST_INFO)) ; + + /* Currently writing this version. */ + dst->version = 1 ; + + return SF_TRUE ; +} /* broadcast_info_copy */ + +int +broadcast_add_coding_history (SF_BROADCAST_INFO* bext, unsigned int channels, unsigned int samplerate) +{ char chnstr [16] ; + int count ; + + switch (channels) + { case 0 : + return SF_FALSE ; + + case 1 : + strncpy (chnstr, "mono", sizeof (chnstr)) ; + break ; + + case 2 : + strncpy (chnstr, "stereo", sizeof (chnstr)) ; + break ; + + default : + LSF_SNPRINTF (chnstr, sizeof (chnstr), "%uchn", channels) ; + break ; + } + + count = LSF_SNPRINTF (bext->coding_history, sizeof (bext->coding_history), "F=%u,A=PCM,M=%s,W=24,T=%s-%s", samplerate, chnstr, PACKAGE, VERSION) ; + + if (count >= SIGNED_SIZEOF (bext->coding_history)) + bext->coding_history_size = sizeof (bext->coding_history) ; + else + { count += count & 1 ; + bext->coding_history_size = count ; + } ; + + return SF_TRUE ; +} /* broadcast_add_coding_history */ + +/* +** Do not edit or modify anything in this comment block. +** The following line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 4b3b69c7-d710-4424-9da0-5048534a0beb +*/ diff --git a/nylsf/caf.c b/nylsf/caf.c new file mode 100644 index 0000000..7a1e5c9 --- /dev/null +++ b/nylsf/caf.c @@ -0,0 +1,538 @@ +/* +** Copyright (C) 2005, 2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define aac_MARKER MAKE_MARKER ('a', 'a', 'c', ' ') +#define alac_MARKER MAKE_MARKER ('a', 'l', 'a', 'c') +#define alaw_MARKER MAKE_MARKER ('a', 'l', 'a', 'w') +#define caff_MARKER MAKE_MARKER ('c', 'a', 'f', 'f') +#define chan_MARKER MAKE_MARKER ('c', 'h', 'a', 'n') +#define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a') +#define desc_MARKER MAKE_MARKER ('d', 'e', 's', 'c') +#define edct_MARKER MAKE_MARKER ('e', 'd', 'c', 't') +#define free_MARKER MAKE_MARKER ('f', 'r', 'e', 'e') +#define ima4_MARKER MAKE_MARKER ('i', 'm', 'a', '4') +#define info_MARKER MAKE_MARKER ('i', 'n', 'f', 'o') +#define inst_MARKER MAKE_MARKER ('i', 'n', 's', 't') +#define kuki_MARKER MAKE_MARKER ('k', 'u', 'k', 'i') +#define lpcm_MARKER MAKE_MARKER ('l', 'p', 'c', 'm') +#define mark_MARKER MAKE_MARKER ('m', 'a', 'r', 'k') +#define midi_MARKER MAKE_MARKER ('m', 'i', 'd', 'i') +#define mp1_MARKER MAKE_MARKER ('.', 'm', 'p', '1') +#define mp2_MARKER MAKE_MARKER ('.', 'm', 'p', '2') +#define mp3_MARKER MAKE_MARKER ('.', 'm', 'p', '3') +#define ovvw_MARKER MAKE_MARKER ('o', 'v', 'v', 'w') +#define pakt_MARKER MAKE_MARKER ('p', 'a', 'k', 't') +#define peak_MARKER MAKE_MARKER ('p', 'e', 'a', 'k') +#define regn_MARKER MAKE_MARKER ('r', 'e', 'g', 'n') +#define strg_MARKER MAKE_MARKER ('s', 't', 'r', 'g') +#define umid_MARKER MAKE_MARKER ('u', 'm', 'i', 'd') +#define uuid_MARKER MAKE_MARKER ('u', 'u', 'i', 'd') +#define ulaw_MARKER MAKE_MARKER ('u', 'l', 'a', 'w') +#define MAC3_MARKER MAKE_MARKER ('M', 'A', 'C', '3') +#define MAC6_MARKER MAKE_MARKER ('M', 'A', 'C', '6') + +#define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8))) + +#define SFE_CAF_NOT_CAF 666 +#define SFE_CAF_NO_DESC 667 +#define SFE_CAF_BAD_PEAK 668 + +/*------------------------------------------------------------------------------ +** Typedefs. +*/ + +typedef struct +{ unsigned char srate [8] ; + unsigned int fmt_id ; + unsigned int fmt_flags ; + unsigned int pkt_bytes ; + unsigned int pkt_frames ; + unsigned int channels_per_frame ; + unsigned int bits_per_chan ; +} DESC_CHUNK ; + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int caf_close (SF_PRIVATE *psf) ; +static int caf_read_header (SF_PRIVATE *psf) ; +static int caf_write_header (SF_PRIVATE *psf, int calc_length) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +caf_open (SF_PRIVATE *psf) +{ int subformat, format, error = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = caf_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + format = psf->sf.format & SF_FORMAT_TYPEMASK ; + if (format != SF_FORMAT_CAF) + return SFE_BAD_OPEN_FORMAT ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + if (psf->mode != SFM_RDWR || psf->filelength < 44) + { psf->filelength = 0 ; + psf->datalength = 0 ; + psf->dataoffset = 0 ; + psf->sf.frames = 0 ; + } ; + + psf->str_flags = SF_STR_ALLOW_START ; + + /* + ** By default, add the peak chunk to floating point files. Default behaviour + ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE). + */ + if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) + { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + psf->peak_info->peak_loc = SF_PEAK_START ; + } ; + + if ((error = caf_write_header (psf, SF_FALSE)) != 0) + return error ; + + psf->write_header = caf_write_header ; + } ; + + psf->container_close = caf_close ; + /*psf->command = caf_command ;*/ + + switch (subformat) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + /* Lite remove end */ + + default : + return SFE_UNSUPPORTED_ENCODING ; + } ; + + return error ; +} /* caf_open */ + +static int +caf_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + caf_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* caf_close */ + +/*------------------------------------------------------------------------------ +*/ + +static int +decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc) +{ int format ; + + psf->sf.channels = desc->channels_per_frame ; + + format = SF_FORMAT_CAF | (psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0) ; + + if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1) + { /* Floating point data. */ + if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame) + { psf->bytewidth = 4 ; + return format | SF_FORMAT_FLOAT ; + } ; + if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame) + { psf->bytewidth = 8 ; + return format | SF_FORMAT_DOUBLE ; + } ; + } ; + + if ((desc->fmt_flags & 1) != 0) + { psf_log_printf (psf, "**** Ooops, 'desc' chunk suggests float data, but other info invalid.\n") ; + return 0 ; + } ; + + if (desc->fmt_id == lpcm_MARKER) + { /* Integer data. */ + if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame) + { psf->bytewidth = 4 ; + return format | SF_FORMAT_PCM_32 ; + } ; + if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame) + { psf->bytewidth = 3 ; + return format | SF_FORMAT_PCM_24 ; + } ; + if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame) + { psf->bytewidth = 2 ; + return format | SF_FORMAT_PCM_16 ; + } ; + if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame) + { psf->bytewidth = 1 ; + return format | SF_FORMAT_PCM_S8 ; + } ; + } ; + + if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8) + { psf->bytewidth = 1 ; + return format | SF_FORMAT_ALAW ; + } ; + + if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8) + { psf->bytewidth = 1 ; + return format | SF_FORMAT_ULAW ; + } ; + + return 0 ; +} /* decode_desc_chunk */ + +static int +caf_read_header (SF_PRIVATE *psf) +{ DESC_CHUNK desc ; + sf_count_t chunk_size ; + double srate ; + short version, flags ; + int marker, k, have_data = 0 ; + + memset (&desc, 0, sizeof (desc)) ; + + /* Set position to start of file to begin reading header. */ + psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ; + psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ; + if (marker != caff_MARKER) + return SFE_CAF_NOT_CAF ; + + psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ; + srate = double64_be_read (psf->u.ucbuf) ; + LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ; + psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ; + if (marker != desc_MARKER) + return SFE_CAF_NO_DESC ; + + if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK)) + { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ; + return SFE_MALFORMED_FILE ; + } ; + + psf->sf.samplerate = lrint (srate) ; + + psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames, + &desc.channels_per_frame, &desc.bits_per_chan) ; + psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n" + " Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n", + desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ; + + if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK)) + psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ; + + psf->sf.channels = desc.channels_per_frame ; + + while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker)) + { psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ; + + switch (marker) + { case peak_MARKER : + psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; + if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) + { psf_binheader_readf (psf, "j", (int) chunk_size) ; + psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; + return SFE_CAF_BAD_PEAK ; + } ; + + if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + + /* read in rest of PEAK chunk. */ + psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ; + psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ; + + psf_log_printf (psf, " Ch Position Value\n") ; + for (k = 0 ; k < psf->sf.channels ; k++) + { sf_count_t position ; + float value ; + + psf_binheader_readf (psf, "Ef8", &value, &position) ; + psf->peak_info->peaks [k].value = value ; + psf->peak_info->peaks [k].position = position ; + + LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12ld %g\n", k, (long) position, value) ; + psf_log_printf (psf, psf->u.cbuf) ; + } ; + + psf->peak_info->peak_loc = SF_PEAK_START ; + break ; + + case free_MARKER : + psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; + psf_binheader_readf (psf, "j", (int) chunk_size) ; + break ; + + case data_MARKER : + psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; + psf_binheader_readf (psf, "E4", &k) ; + psf_log_printf (psf, " edit : %u\n", k) ; + have_data = 1 ; + break ; + + default : + psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ; + psf_binheader_readf (psf, "j", (int) chunk_size) ; + break ; + } ; + } ; + + if (have_data == 0) + { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ; + return SFE_MALFORMED_FILE ; + } ; + + psf_log_printf (psf, "End\n") ; + + psf->dataoffset = psf_ftell (psf) ; + psf->datalength = psf->filelength - psf->dataoffset ; + psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ; + + if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0) + return SFE_UNSUPPORTED_ENCODING ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / psf->bytewidth ; + + return 0 ; +} /* caf_read_header */ + +/*------------------------------------------------------------------------------ +*/ + +static int +caf_write_header (SF_PRIVATE *psf, int calc_length) +{ DESC_CHUNK desc ; + sf_count_t current, free_len ; + int subformat ; + + memset (&desc, 0, sizeof (desc)) ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* 'caff' marker, version and flags. */ + psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ; + + /* 'desc' marker and chunk size. */ + psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ; + + double64_be_write (1.0 * psf->sf.samplerate, psf->u.ucbuf) ; + psf_binheader_writef (psf, "b", psf->u.ucbuf, make_size_t (8)) ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + + if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) + psf->endian = SF_ENDIAN_BIG ; + else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU)) + psf->endian = SF_ENDIAN_LITTLE ; + + if (psf->endian == SF_ENDIAN_LITTLE) + desc.fmt_flags = 2 ; + else + psf->endian = SF_ENDIAN_BIG ; + + /* initial section (same for all, it appears) */ + switch (subformat) + { case SF_FORMAT_PCM_S8 : + desc.fmt_id = lpcm_MARKER ; + psf->bytewidth = 1 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 8 ; + break ; + + case SF_FORMAT_PCM_16 : + desc.fmt_id = lpcm_MARKER ; + psf->bytewidth = 2 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 16 ; + break ; + + case SF_FORMAT_PCM_24 : + psf->bytewidth = 3 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 24 ; + desc.fmt_id = lpcm_MARKER ; + break ; + + case SF_FORMAT_PCM_32 : + desc.fmt_id = lpcm_MARKER ; + psf->bytewidth = 4 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 32 ; + break ; + + case SF_FORMAT_FLOAT : + desc.fmt_id = lpcm_MARKER ; + desc.fmt_flags |= 1 ; + psf->bytewidth = 4 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 32 ; + break ; + + case SF_FORMAT_DOUBLE : + desc.fmt_id = lpcm_MARKER ; + desc.fmt_flags |= 1 ; + psf->bytewidth = 8 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 64 ; + break ; + + case SF_FORMAT_ALAW : + desc.fmt_id = alaw_MARKER ; + psf->bytewidth = 1 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 8 ; + break ; + + case SF_FORMAT_ULAW : + desc.fmt_id = ulaw_MARKER ; + psf->bytewidth = 1 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 8 ; + break ; + + default : + return SFE_UNIMPLEMENTED ; + } ; + + psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ; + +#if 0 + if (psf->str_flags & SF_STR_LOCATE_START) + caf_write_strings (psf, SF_STR_LOCATE_START) ; +#endif + + if (psf->peak_info != NULL) + { int k ; + psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ; + for (k = 0 ; k < psf->sf.channels ; k++) + psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; + } ; + + /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */ + free_len = 0x1000 - psf->headindex - 16 - 12 ; + while (free_len < 0) + free_len += 0x1000 ; + psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ; + + psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength, 0) ; + + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + if (current < psf->dataoffset) + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + else if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* caf_write_header */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 65883e65-bd3c-4618-9241-d3c02fd630bd +*/ diff --git a/nylsf/command.c b/nylsf/command.c new file mode 100644 index 0000000..edb793f --- /dev/null +++ b/nylsf/command.c @@ -0,0 +1,367 @@ +/* +** Copyright (C) 2001-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "common.h" + +static SF_FORMAT_INFO const simple_formats [] = +{ + { SF_FORMAT_AIFF | SF_FORMAT_PCM_16, + "AIFF (Apple/SGI 16 bit PCM)", "aiff" + }, + + { SF_FORMAT_AIFF | SF_FORMAT_FLOAT, + "AIFF (Apple/SGI 32 bit float)", "aifc" + }, + + { SF_FORMAT_AIFF | SF_FORMAT_PCM_S8, + "AIFF (Apple/SGI 8 bit PCM)", "aiff" + }, + + { SF_FORMAT_AU | SF_FORMAT_PCM_16, + "AU (Sun/Next 16 bit PCM)", "au" + }, + + { SF_FORMAT_AU | SF_FORMAT_ULAW, + "AU (Sun/Next 8-bit u-law)", "au" + }, + + { SF_FORMAT_CAF | SF_FORMAT_PCM_16, + "CAF (Apple 16 bit PCM)", "caf" + }, + +#ifdef HAVE_FLAC_ALL_H + { SF_FORMAT_FLAC | SF_FORMAT_PCM_16, + "FLAC 16 bit", "flac" + }, +#endif + + { SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, + "OKI Dialogic VOX ADPCM", "vox" + }, + + { SF_FORMAT_WAV | SF_FORMAT_PCM_16, + "WAV (Microsoft 16 bit PCM)", "wav" + }, + + { SF_FORMAT_WAV | SF_FORMAT_FLOAT, + "WAV (Microsoft 32 bit float)", "wav" + }, + + { SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, + "WAV (Microsoft 4 bit IMA ADPCM)", "wav" + }, + + { SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, + "WAV (Microsoft 4 bit MS ADPCM)", "wav" + }, + + { SF_FORMAT_WAV | SF_FORMAT_PCM_U8, + "WAV (Microsoft 8 bit PCM)", "wav" + }, + +} ; /* simple_formats */ + +int +psf_get_format_simple_count (void) +{ return (sizeof (simple_formats) / sizeof (SF_FORMAT_INFO)) ; +} /* psf_get_format_simple_count */ + +int +psf_get_format_simple (SF_FORMAT_INFO *data) +{ int indx ; + + if (data->format < 0 || data->format >= (SIGNED_SIZEOF (simple_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO))) + return SFE_BAD_CONTROL_CMD ; + + indx = data->format ; + memcpy (data, &(simple_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ; + + return 0 ; +} /* psf_get_format_simple */ + +/*============================================================================ +** Major format info. +*/ + +static SF_FORMAT_INFO const major_formats [] = +{ + { SF_FORMAT_AIFF, "AIFF (Apple/SGI)", "aiff" }, + { SF_FORMAT_AU, "AU (Sun/NeXT)", "au" }, + { SF_FORMAT_AVR, "AVR (Audio Visual Research)", "avr" }, + { SF_FORMAT_CAF, "CAF (Apple Core Audio File)", "caf" }, +#ifdef HAVE_FLAC_ALL_H + { SF_FORMAT_FLAC, "FLAC (FLAC Lossless Audio Codec)", "flac" }, +#endif + { SF_FORMAT_HTK, "HTK (HMM Tool Kit)", "htk" }, + { SF_FORMAT_SVX, "IFF (Amiga IFF/SVX8/SV16)", "iff" }, + { SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" }, + { SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" }, + { SF_FORMAT_PAF, "PAF (Ensoniq PARIS)", "paf" }, + { SF_FORMAT_PVF, "PVF (Portable Voice Format)", "pvf" }, + { SF_FORMAT_RAW, "RAW (header-less)", "raw" }, + { SF_FORMAT_SD2, "SD2 (Sound Designer II)", "sd2" }, + { SF_FORMAT_SDS, "SDS (Midi Sample Dump Standard)", "sds" }, + { SF_FORMAT_IRCAM, "SF (Berkeley/IRCAM/CARL)", "sf" }, + { SF_FORMAT_VOC, "VOC (Creative Labs)", "voc" }, + { SF_FORMAT_W64, "W64 (SoundFoundry WAVE 64)", "w64" }, + { SF_FORMAT_WAV, "WAV (Microsoft)", "wav" }, + { SF_FORMAT_NIST, "WAV (NIST Sphere)", "wav" }, + { SF_FORMAT_WAVEX, "WAVEX (Microsoft)", "wav" }, + { SF_FORMAT_XI, "XI (FastTracker 2)", "xi" }, + +} ; /* major_formats */ + +int +psf_get_format_major_count (void) +{ return (sizeof (major_formats) / sizeof (SF_FORMAT_INFO)) ; +} /* psf_get_format_major_count */ + +int +psf_get_format_major (SF_FORMAT_INFO *data) +{ int indx ; + + if (data->format < 0 || data->format >= (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO))) + return SFE_BAD_CONTROL_CMD ; + + indx = data->format ; + memcpy (data, &(major_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ; + + return 0 ; +} /* psf_get_format_major */ + +/*============================================================================ +** Subtype format info. +*/ + +static SF_FORMAT_INFO subtype_formats [] = +{ + { SF_FORMAT_PCM_S8, "Signed 8 bit PCM", NULL }, + { SF_FORMAT_PCM_16, "Signed 16 bit PCM", NULL }, + { SF_FORMAT_PCM_24, "Signed 24 bit PCM", NULL }, + { SF_FORMAT_PCM_32, "Signed 32 bit PCM", NULL }, + + { SF_FORMAT_PCM_U8, "Unsigned 8 bit PCM", NULL }, + + { SF_FORMAT_FLOAT, "32 bit float", NULL }, + { SF_FORMAT_DOUBLE, "64 bit float", NULL }, + + { SF_FORMAT_ULAW, "U-Law", NULL }, + { SF_FORMAT_ALAW, "A-Law", NULL }, + { SF_FORMAT_IMA_ADPCM, "IMA ADPCM", NULL }, + { SF_FORMAT_MS_ADPCM, "Microsoft ADPCM", NULL }, + + { SF_FORMAT_GSM610, "GSM 6.10", NULL }, + + { SF_FORMAT_G721_32, "32kbs G721 ADPCM", NULL }, + { SF_FORMAT_G723_24, "24kbs G723 ADPCM", NULL }, + + { SF_FORMAT_DWVW_12, "12 bit DWVW", NULL }, + { SF_FORMAT_DWVW_16, "16 bit DWVW", NULL }, + { SF_FORMAT_DWVW_24, "24 bit DWVW", NULL }, + { SF_FORMAT_VOX_ADPCM, "VOX ADPCM", "vox" }, + + { SF_FORMAT_DPCM_16, "16 bit DPCM", NULL }, + { SF_FORMAT_DPCM_8, "8 bit DPCM", NULL } +} ; /* subtype_formats */ + +int +psf_get_format_subtype_count (void) +{ return (sizeof (subtype_formats) / sizeof (SF_FORMAT_INFO)) ; +} /* psf_get_format_subtype_count */ + +int +psf_get_format_subtype (SF_FORMAT_INFO *data) +{ int indx ; + + if (data->format < 0 || data->format >= (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO))) + return SFE_BAD_CONTROL_CMD ; + + indx = data->format ; + memcpy (data, &(subtype_formats [indx]), sizeof (SF_FORMAT_INFO)) ; + + return 0 ; +} /* psf_get_format_subtype */ + +/*============================================================================== +*/ + +int +psf_get_format_info (SF_FORMAT_INFO *data) +{ int k, format ; + + if (data->format & SF_FORMAT_TYPEMASK) + { format = data->format & SF_FORMAT_TYPEMASK ; + + for (k = 0 ; k < (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++) + { if (format == major_formats [k].format) + { memcpy (data, &(major_formats [k]), sizeof (SF_FORMAT_INFO)) ; + return 0 ; + } ; + } ; + } + else if (data->format & SF_FORMAT_SUBMASK) + { format = data->format & SF_FORMAT_SUBMASK ; + + for (k = 0 ; k < (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++) + { if (format == subtype_formats [k].format) + { memcpy (data, &(subtype_formats [k]), sizeof (SF_FORMAT_INFO)) ; + return 0 ; + } ; + } ; + } ; + + memset (data, 0, sizeof (SF_FORMAT_INFO)) ; + + return SFE_BAD_CONTROL_CMD ; +} /* psf_get_format_info */ + +/*============================================================================== +*/ + +double +psf_calc_signal_max (SF_PRIVATE *psf, int normalize) +{ sf_count_t position ; + double max_val, temp, *data ; + int k, len, readcount, save_state ; + + /* If the file is not seekable, there is nothing we can do. */ + if (! psf->sf.seekable) + { psf->error = SFE_NOT_SEEKABLE ; + return 0.0 ; + } ; + + if (! psf->read_double) + { psf->error = SFE_UNIMPLEMENTED ; + return 0.0 ; + } ; + + save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ; + sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ; + + /* Brute force. Read the whole file and find the biggest sample. */ + /* Get current position in file */ + position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; + /* Go to start of file. */ + sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ; + + data = psf->u.dbuf ; + len = ARRAY_LEN (psf->u.dbuf) ; + + for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */) + { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; + for (k = 0 ; k < readcount ; k++) + { temp = fabs (data [k]) ; + max_val = temp > max_val ? temp : max_val ; + } ; + } ; + + /* Return to SNDFILE to original state. */ + sf_seek ((SNDFILE*) psf, position, SEEK_SET) ; + sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ; + + return max_val ; +} /* psf_calc_signal_max */ + +int +psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize) +{ sf_count_t position ; + double temp, *data ; + int k, len, readcount, save_state ; + int chan ; + + /* If the file is not seekable, there is nothing we can do. */ + if (! psf->sf.seekable) + return (psf->error = SFE_NOT_SEEKABLE) ; + + if (! psf->read_double) + return (psf->error = SFE_UNIMPLEMENTED) ; + + save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ; + sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ; + + memset (peaks, 0, sizeof (double) * psf->sf.channels) ; + + /* Brute force. Read the whole file and find the biggest sample for each channel. */ + position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; /* Get current position in file */ + sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ; /* Go to start of file. */ + + len = ARRAY_LEN (psf->u.dbuf) ; + + data = psf->u.dbuf ; + + chan = 0 ; + readcount = len ; + while (readcount > 0) + { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; + for (k = 0 ; k < readcount ; k++) + { temp = fabs (data [k]) ; + peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ; + chan = (chan + 1) % psf->sf.channels ; + } ; + } ; + + sf_seek ((SNDFILE*) psf, position, SEEK_SET) ; /* Return to original position. */ + + sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ; + + return 0 ; +} /* psf_calc_max_all_channels */ + +int +psf_get_signal_max (SF_PRIVATE *psf, double *peak) +{ int k ; + + if (psf->peak_info == NULL) + return SF_FALSE ; + + peak [0] = psf->peak_info->peaks [0].value ; + + for (k = 1 ; k < psf->sf.channels ; k++) + peak [0] = SF_MAX (peak [0], psf->peak_info->peaks [k].value) ; + + return SF_TRUE ; +} /* psf_get_signal_max */ + +int +psf_get_max_all_channels (SF_PRIVATE *psf, double *peaks) +{ int k ; + + if (psf->peak_info == NULL) + return SF_FALSE ; + + for (k = 0 ; k < psf->sf.channels ; k++) + peaks [k] = psf->peak_info->peaks [k].value ; + + return SF_TRUE ; +} /* psf_get_max_all_channels */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 0aae0d9d-ab2b-4d70-ade3-47a534666f8e +*/ diff --git a/nylsf/common.c b/nylsf/common.c new file mode 100644 index 0000000..ae2689b --- /dev/null +++ b/nylsf/common.c @@ -0,0 +1,1290 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*----------------------------------------------------------------------------------------------- +** psf_log_printf allows libsndfile internal functions to print to an internal logbuffer which +** can later be displayed. +** The format specifiers are as for printf but without the field width and other modifiers. +** Printing is performed to the logbuffer char array of the SF_PRIVATE struct. +** Printing is done in such a way as to guarantee that the log never overflows the end of the +** logbuffer array. +*/ + +static inline void +log_putchar (SF_PRIVATE *psf, char ch) +{ if (psf->logindex < SIGNED_SIZEOF (psf->logbuffer) - 1) + { psf->logbuffer [psf->logindex++] = ch ; + psf->logbuffer [psf->logindex] = 0 ; + } ; + return ; +} /* log_putchar */ + +void +psf_log_printf (SF_PRIVATE *psf, const char *format, ...) +{ va_list ap ; + unsigned int u ; + int d, tens, shift, width, width_specifier, left_align ; + char c, *strptr, istr [5], lead_char, sign_char ; + + va_start (ap, format) ; + + while ((c = *format++)) + { if (c != '%') + { log_putchar (psf, c) ; + continue ; + } ; + + if (format [0] == '%') /* Handle %% */ + { log_putchar (psf, '%') ; + format ++ ; + continue ; + } ; + + sign_char = 0 ; + left_align = SF_FALSE ; + while (1) + { switch (format [0]) + { case ' ' : + case '+' : + sign_char = format [0] ; + format ++ ; + continue ; + + case '-' : + left_align = SF_TRUE ; + format ++ ; + continue ; + + default : break ; + } ; + + break ; + } ; + + if (format [0] == 0) + break ; + + lead_char = ' ' ; + if (format [0] == '0') + lead_char = '0' ; + + width_specifier = 0 ; + while ((c = *format++) && isdigit (c)) + width_specifier = width_specifier * 10 + (c - '0') ; + + switch (c) + { case 0 : /* NULL character. */ + va_end (ap) ; + return ; + + case 's': /* string */ + strptr = va_arg (ap, char *) ; + if (strptr == NULL) + break ; + width_specifier -= strlen (strptr) ; + if (left_align == SF_FALSE) + while (width_specifier -- > 0) + log_putchar (psf, ' ') ; + while (*strptr) + log_putchar (psf, *strptr++) ; + while (width_specifier -- > 0) + log_putchar (psf, ' ') ; + break ; + + case 'd': /* int */ + d = va_arg (ap, int) ; + + if (d < 0) + { d = -d ; + sign_char = '-' ; + if (lead_char != '0' && left_align == SF_FALSE) + width_specifier -- ; + } ; + + tens = 1 ; + width = 1 ; + while (d / tens >= 10) + { tens *= 10 ; + width ++ ; + } ; + + width_specifier -= width ; + + if (sign_char == ' ') + { log_putchar (psf, ' ') ; + width_specifier -- ; + } ; + + if (left_align == SF_FALSE && lead_char != '0') + { if (sign_char == '+') + width_specifier -- ; + + while (width_specifier -- > 0) + log_putchar (psf, lead_char) ; + } ; + + if (sign_char == '+' || sign_char == '-') + { log_putchar (psf, sign_char) ; + width_specifier -- ; + } ; + + if (left_align == SF_FALSE) + while (width_specifier -- > 0) + log_putchar (psf, lead_char) ; + + while (tens > 0) + { log_putchar (psf, '0' + d / tens) ; + d %= tens ; + tens /= 10 ; + } ; + + while (width_specifier -- > 0) + log_putchar (psf, lead_char) ; + break ; + + case 'D': /* sf_count_t */ + { sf_count_t D, Tens ; + + D = va_arg (ap, sf_count_t) ; + + if (D == 0) + { while (-- width_specifier > 0) + log_putchar (psf, lead_char) ; + log_putchar (psf, '0') ; + break ; + } + if (D < 0) + { log_putchar (psf, '-') ; + D = -D ; + } ; + Tens = 1 ; + width = 1 ; + while (D / Tens >= 10) + { Tens *= 10 ; + width ++ ; + } ; + + while (width_specifier > width) + { log_putchar (psf, lead_char) ; + width_specifier-- ; + } ; + + while (Tens > 0) + { log_putchar (psf, '0' + D / Tens) ; + D %= Tens ; + Tens /= 10 ; + } ; + } ; + break ; + + case 'u': /* unsigned int */ + u = va_arg (ap, unsigned int) ; + + tens = 1 ; + width = 1 ; + while (u / tens >= 10) + { tens *= 10 ; + width ++ ; + } ; + + width_specifier -= width ; + + if (sign_char == ' ') + { log_putchar (psf, ' ') ; + width_specifier -- ; + } ; + + if (left_align == SF_FALSE && lead_char != '0') + { if (sign_char == '+') + width_specifier -- ; + + while (width_specifier -- > 0) + log_putchar (psf, lead_char) ; + } ; + + if (sign_char == '+' || sign_char == '-') + { log_putchar (psf, sign_char) ; + width_specifier -- ; + } ; + + if (left_align == SF_FALSE) + while (width_specifier -- > 0) + log_putchar (psf, lead_char) ; + + while (tens > 0) + { log_putchar (psf, '0' + u / tens) ; + u %= tens ; + tens /= 10 ; + } ; + + while (width_specifier -- > 0) + log_putchar (psf, lead_char) ; + break ; + + case 'c': /* char */ + c = va_arg (ap, int) & 0xFF ; + log_putchar (psf, c) ; + break ; + + case 'x': /* hex */ + case 'X': /* hex */ + d = va_arg (ap, int) ; + + if (d == 0) + { while (--width_specifier > 0) + log_putchar (psf, lead_char) ; + log_putchar (psf, '0') ; + break ; + } ; + shift = 28 ; + width = (width_specifier < 8) ? 8 : width_specifier ; + while (! ((0xF << shift) & d)) + { shift -= 4 ; + width -- ; + } ; + + while (width > 0 && width_specifier > width) + { log_putchar (psf, lead_char) ; + width_specifier-- ; + } ; + + while (shift >= 0) + { c = (d >> shift) & 0xF ; + log_putchar (psf, (c > 9) ? c + 'A' - 10 : c + '0') ; + shift -= 4 ; + } ; + break ; + + case 'M': /* int2str */ + d = va_arg (ap, int) ; + if (CPU_IS_LITTLE_ENDIAN) + { istr [0] = d & 0xFF ; + istr [1] = (d >> 8) & 0xFF ; + istr [2] = (d >> 16) & 0xFF ; + istr [3] = (d >> 24) & 0xFF ; + } + else + { istr [3] = d & 0xFF ; + istr [2] = (d >> 8) & 0xFF ; + istr [1] = (d >> 16) & 0xFF ; + istr [0] = (d >> 24) & 0xFF ; + } ; + istr [4] = 0 ; + strptr = istr ; + while (*strptr) + { c = *strptr++ ; + log_putchar (psf, c) ; + } ; + break ; + + default : + log_putchar (psf, '*') ; + log_putchar (psf, c) ; + log_putchar (psf, '*') ; + break ; + } /* switch */ + } /* while */ + + va_end (ap) ; + return ; +} /* psf_log_printf */ + +#ifndef PSF_LOG_PRINTF_ONLY +/*----------------------------------------------------------------------------------------------- +** ASCII header printf functions. +** Some formats (ie NIST) use ascii text in their headers. +** Format specifiers are the same as the standard printf specifiers (uses vsnprintf). +** If this generates a compile error on any system, the author should be notified +** so an alternative vsnprintf can be provided. +*/ + +void +psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...) +{ va_list argptr ; + int maxlen ; + char *start ; + + maxlen = strlen ((char*) psf->header) ; + start = ((char*) psf->header) + maxlen ; + maxlen = sizeof (psf->header) - maxlen ; + + va_start (argptr, format) ; + LSF_VSNPRINTF (start, maxlen, format, argptr) ; + va_end (argptr) ; + + /* Make sure the string is properly terminated. */ + start [maxlen - 1] = 0 ; + + psf->headindex = strlen ((char*) psf->header) ; + + return ; +} /* psf_asciiheader_printf */ + +/*----------------------------------------------------------------------------------------------- +** Binary header writing functions. Returns number of bytes written. +** +** Format specifiers for psf_binheader_writef are as follows +** m - marker - four bytes - no endian manipulation +** +** e - all following numerical values will be little endian +** E - all following numerical values will be big endian +** +** t - all following O types will be truncated to 4 bytes +** T - switch off truncation of all following O types +** +** 1 - single byte value +** 2 - two byte value +** 3 - three byte value +** 4 - four byte value +** 8 - eight byte value (sometimes written as 4 bytes) +** +** s - string preceded by a four byte length +** S - string including null terminator +** f - floating point data +** d - double precision floating point data +** h - 16 binary bytes value +** +** b - binary data (see below) +** z - zero bytes (ses below) +** j - jump forwards or backwards +** +** To write a word followed by an int (both little endian) use: +** psf_binheader_writef ("e24", wordval, longval) ; +** +** To write binary data use: +** psf_binheader_writef ("b", &bindata, sizeof (bindata)) ; +** +** To write N zero bytes use: +** NOTE: due to platform issues (ie x86-64) you should cast the +** argument to size_t or ensure the variable type is size_t. +** psf_binheader_writef ("z", N) ; +*/ + +/* These macros may seem a bit messy but do prevent problems with processors which +** seg. fault when asked to write an int or short to a non-int/short aligned address. +*/ + +static inline void +header_put_byte (SF_PRIVATE *psf, char x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 1) + psf->header [psf->headindex++] = x ; +} /* header_put_byte */ + +#if (CPU_IS_BIG_ENDIAN == 1) +static inline void +header_put_marker (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4) + { psf->header [psf->headindex++] = (x >> 24) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = x ; + } ; +} /* header_put_marker */ + +#elif (CPU_IS_LITTLE_ENDIAN == 1) +static inline void +header_put_marker (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4) + { psf->header [psf->headindex++] = x ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 24) ; + } ; +} /* header_put_marker */ + +#else +# error "Cannot determine endian-ness of processor." +#endif + + +static inline void +header_put_be_short (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 2) + { psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = x ; + } ; +} /* header_put_be_short */ + +static inline void +header_put_le_short (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 2) + { psf->header [psf->headindex++] = x ; + psf->header [psf->headindex++] = (x >> 8) ; + } ; +} /* header_put_le_short */ + +static inline void +header_put_be_3byte (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 3) + { psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = x ; + } ; +} /* header_put_be_3byte */ + +static inline void +header_put_le_3byte (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 3) + { psf->header [psf->headindex++] = x ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = (x >> 16) ; + } ; +} /* header_put_le_3byte */ + +static inline void +header_put_be_int (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4) + { psf->header [psf->headindex++] = (x >> 24) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = x ; + } ; +} /* header_put_be_int */ + +static inline void +header_put_le_int (SF_PRIVATE *psf, int x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4) + { psf->header [psf->headindex++] = x ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 24) ; + } ; +} /* header_put_le_int */ + +#if (SIZEOF_SF_COUNT_T == 4) + +static inline void +header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8) + { psf->header [psf->headindex++] = 0 ; + psf->header [psf->headindex++] = 0 ; + psf->header [psf->headindex++] = 0 ; + psf->header [psf->headindex++] = 0 ; + psf->header [psf->headindex++] = (x >> 24) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = x ; + } ; +} /* header_put_be_8byte */ + +static inline void +header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8) + { psf->header [psf->headindex++] = x ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 24) ; + psf->header [psf->headindex++] = 0 ; + psf->header [psf->headindex++] = 0 ; + psf->header [psf->headindex++] = 0 ; + psf->header [psf->headindex++] = 0 ; + } ; +} /* header_put_le_8byte */ + +#elif (SIZEOF_SF_COUNT_T == 8) + +static inline void +header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8) + { psf->header [psf->headindex++] = (x >> 56) ; + psf->header [psf->headindex++] = (x >> 48) ; + psf->header [psf->headindex++] = (x >> 40) ; + psf->header [psf->headindex++] = (x >> 32) ; + psf->header [psf->headindex++] = (x >> 24) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = x ; + } ; +} /* header_put_be_8byte */ + +static inline void +header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x) +{ if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8) + { psf->header [psf->headindex++] = x ; + psf->header [psf->headindex++] = (x >> 8) ; + psf->header [psf->headindex++] = (x >> 16) ; + psf->header [psf->headindex++] = (x >> 24) ; + psf->header [psf->headindex++] = (x >> 32) ; + psf->header [psf->headindex++] = (x >> 40) ; + psf->header [psf->headindex++] = (x >> 48) ; + psf->header [psf->headindex++] = (x >> 56) ; + } ; +} /* header_put_le_8byte */ + +#else +#error "SIZEOF_SF_COUNT_T is not defined." +#endif + +int +psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) +{ va_list argptr ; + sf_count_t countdata ; + unsigned long longdata ; + unsigned int data ; + float floatdata ; + double doubledata ; + void *bindata ; + size_t size ; + char c, *strptr ; + int count = 0, trunc_8to4 ; + + trunc_8to4 = SF_FALSE ; + + va_start (argptr, format) ; + + while ((c = *format++)) + { switch (c) + { case ' ' : /* Do nothing. Just used to space out format string. */ + break ; + + case 'e' : /* All conversions are now from LE to host. */ + psf->rwf_endian = SF_ENDIAN_LITTLE ; + break ; + + case 'E' : /* All conversions are now from BE to host. */ + psf->rwf_endian = SF_ENDIAN_BIG ; + break ; + + case 't' : /* All 8 byte values now get written as 4 bytes. */ + trunc_8to4 = SF_TRUE ; + break ; + + case 'T' : /* All 8 byte values now get written as 8 bytes. */ + trunc_8to4 = SF_FALSE ; + break ; + + case 'm' : + data = va_arg (argptr, unsigned int) ; + header_put_marker (psf, data) ; + count += 4 ; + break ; + + case '1' : + data = va_arg (argptr, unsigned int) ; + header_put_byte (psf, data) ; + count += 1 ; + break ; + + case '2' : + data = va_arg (argptr, unsigned int) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + { header_put_be_short (psf, data) ; + } + else + { header_put_le_short (psf, data) ; + } ; + count += 2 ; + break ; + + case '3' : /* tribyte */ + data = va_arg (argptr, unsigned int) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + { header_put_be_3byte (psf, data) ; + } + else + { header_put_le_3byte (psf, data) ; + } ; + count += 3 ; + break ; + + case '4' : + data = va_arg (argptr, unsigned int) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + { header_put_be_int (psf, data) ; + } + else + { header_put_le_int (psf, data) ; + } ; + count += 4 ; + break ; + + case '8' : + countdata = va_arg (argptr, sf_count_t) ; + if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_FALSE) + { header_put_be_8byte (psf, countdata) ; + count += 8 ; + } + else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_FALSE) + { header_put_le_8byte (psf, countdata) ; + count += 8 ; + } + else if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_TRUE) + { longdata = countdata & 0xFFFFFFFF ; + header_put_be_int (psf, longdata) ; + count += 4 ; + } + else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_TRUE) + { longdata = countdata & 0xFFFFFFFF ; + header_put_le_int (psf, longdata) ; + count += 4 ; + } + break ; + + case 'f' : + /* Floats are passed as doubles. Is this always true? */ + floatdata = (float) va_arg (argptr, double) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + float32_be_write (floatdata, psf->header + psf->headindex) ; + else + float32_le_write (floatdata, psf->header + psf->headindex) ; + psf->headindex += 4 ; + count += 4 ; + break ; + + case 'd' : + doubledata = va_arg (argptr, double) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + double64_be_write (doubledata, psf->header + psf->headindex) ; + else + double64_le_write (doubledata, psf->header + psf->headindex) ; + psf->headindex += 8 ; + count += 8 ; + break ; + + case 's' : + /* Write a C string (guaranteed to have a zero terminator). */ + strptr = va_arg (argptr, char *) ; + size = strlen (strptr) + 1 ; + size += (size & 1) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + header_put_be_int (psf, size) ; + else + header_put_le_int (psf, size) ; + memcpy (&(psf->header [psf->headindex]), strptr, size) ; + psf->headindex += size ; + psf->header [psf->headindex - 1] = 0 ; + count += 4 + size ; + break ; + + case 'S' : + /* + ** Write an AIFF style string (no zero terminator but possibly + ** an extra pad byte if the string length is odd). + */ + strptr = va_arg (argptr, char *) ; + size = strlen (strptr) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + header_put_be_int (psf, size) ; + else + header_put_le_int (psf, size) ; + memcpy (&(psf->header [psf->headindex]), strptr, size + 1) ; + size += (size & 1) ; + psf->headindex += size ; + psf->header [psf->headindex] = 0 ; + count += 4 + size ; + break ; + + case 'b' : + bindata = va_arg (argptr, void *) ; + size = va_arg (argptr, size_t) ; + memcpy (&(psf->header [psf->headindex]), bindata, size) ; + psf->headindex += size ; + count += size ; + break ; + + case 'z' : + size = va_arg (argptr, size_t) ; + count += size ; + while (size) + { psf->header [psf->headindex] = 0 ; + psf->headindex ++ ; + size -- ; + } ; + break ; + + case 'h' : + bindata = va_arg (argptr, void *) ; + memcpy (&(psf->header [psf->headindex]), bindata, 16) ; + psf->headindex += 16 ; + count += 16 ; + break ; + + case 'j' : + size = va_arg (argptr, size_t) ; + psf->headindex += size ; + count = size ; + break ; + + default : + psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ; + psf->error = SFE_INTERNAL ; + break ; + } ; + } ; + + va_end (argptr) ; + return count ; +} /* psf_binheader_writef */ + +/*----------------------------------------------------------------------------------------------- +** Binary header reading functions. Returns number of bytes read. +** +** Format specifiers are the same as for header write function above with the following +** additions: +** +** p - jump a given number of position from start of file. +** +** If format is NULL, psf_binheader_readf returns the current offset. +*/ + +#if (CPU_IS_BIG_ENDIAN == 1) +#define GET_MARKER(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \ + ((ptr) [2] << 8) | ((ptr) [3]) ) + +#elif (CPU_IS_LITTLE_ENDIAN == 1) +#define GET_MARKER(ptr) ( ((ptr) [0]) | ((ptr) [1] << 8) | \ + ((ptr) [2] << 16) | ((ptr) [3] << 24) ) + +#else +# error "Cannot determine endian-ness of processor." +#endif + +#define GET_LE_SHORT(ptr) ( ((ptr) [1] << 8) | ((ptr) [0]) ) +#define GET_BE_SHORT(ptr) ( ((ptr) [0] << 8) | ((ptr) [1]) ) + +#define GET_LE_3BYTE(ptr) ( ((ptr) [2] << 16) | ((ptr) [1] << 8) | ((ptr) [0]) ) +#define GET_BE_3BYTE(ptr) ( ((ptr) [0] << 16) | ((ptr) [1] << 8) | ((ptr) [2]) ) + +#define GET_LE_INT(ptr) ( ((ptr) [3] << 24) | ((ptr) [2] << 16) | \ + ((ptr) [1] << 8) | ((ptr) [0]) ) + +#define GET_BE_INT(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \ + ((ptr) [2] << 8) | ((ptr) [3]) ) + +#if (SIZEOF_LONG == 4) +#define GET_LE_8BYTE(ptr) ( ((ptr) [3] << 24) | ((ptr) [2] << 16) | \ + ((ptr) [1] << 8) | ((ptr) [0]) ) + +#define GET_BE_8BYTE(ptr) ( ((ptr) [4] << 24) | ((ptr) [5] << 16) | \ + ((ptr) [6] << 8) | ((ptr) [7]) ) +#else +#define GET_LE_8BYTE(ptr) ( (((ptr) [7] * 1L) << 56) | (((ptr) [6] * 1L) << 48) | \ + (((ptr) [5] * 1L) << 40) | (((ptr) [4] * 1L) << 32) | \ + (((ptr) [3] * 1L) << 24) | (((ptr) [2] * 1L) << 16) | \ + (((ptr) [1] * 1L) << 8 ) | ((ptr) [0])) + +#define GET_BE_8BYTE(ptr) ( (((ptr) [0] * 1L) << 56) | (((ptr) [1] * 1L) << 48) | \ + (((ptr) [2] * 1L) << 40) | (((ptr) [3] * 1L) << 32) | \ + (((ptr) [4] * 1L) << 24) | (((ptr) [5] * 1L) << 16) | \ + (((ptr) [6] * 1L) << 8 ) | ((ptr) [7])) + +#endif + +static int +header_read (SF_PRIVATE *psf, void *ptr, int bytes) +{ int count = 0 ; + + if (psf->headindex >= SIGNED_SIZEOF (psf->header)) + { memset (ptr, 0, SIGNED_SIZEOF (psf->header) - psf->headindex) ; + + /* This is the best that we can do. */ + psf_fseek (psf, bytes, SEEK_CUR) ; + return bytes ; + } ; + + if (psf->headindex + bytes > SIGNED_SIZEOF (psf->header)) + { int most ; + + most = SIGNED_SIZEOF (psf->header) - psf->headindex ; + psf_fread (psf->header + psf->headend, 1, most, psf) ; + memset ((char *) ptr + most, 0, bytes - most) ; + + psf_fseek (psf, bytes - most, SEEK_CUR) ; + return bytes ; + } ; + + if (psf->headindex + bytes > psf->headend) + { count = psf_fread (psf->header + psf->headend, 1, bytes - (psf->headend - psf->headindex), psf) ; + if (count != bytes - (int) (psf->headend - psf->headindex)) + { psf_log_printf (psf, "Error : psf_fread returned short count.\n") ; + return 0 ; + } ; + psf->headend += count ; + } ; + + memcpy (ptr, psf->header + psf->headindex, bytes) ; + psf->headindex += bytes ; + + return bytes ; +} /* header_read */ + +static void +header_seek (SF_PRIVATE *psf, sf_count_t position, int whence) +{ + + switch (whence) + { case SEEK_SET : + if (position > SIGNED_SIZEOF (psf->header)) + { /* Too much header to cache so just seek instead. */ + psf_fseek (psf, position, whence) ; + return ; + } ; + if (position > psf->headend) + psf->headend += psf_fread (psf->header + psf->headend, 1, position - psf->headend, psf) ; + psf->headindex = position ; + break ; + + case SEEK_CUR : + if (psf->headindex + position < 0) + break ; + + if (psf->headindex >= SIGNED_SIZEOF (psf->header)) + { psf_fseek (psf, position, whence) ; + return ; + } ; + + if (psf->headindex + position <= psf->headend) + { psf->headindex += position ; + break ; + } ; + + if (psf->headindex + position > SIGNED_SIZEOF (psf->header)) + { /* Need to jump this without caching it. */ + psf->headindex = psf->headend ; + psf_fseek (psf, position, SEEK_CUR) ; + break ; + } ; + + psf->headend += psf_fread (psf->header + psf->headend, 1, position - (psf->headend - psf->headindex), psf) ; + psf->headindex = psf->headend ; + break ; + + case SEEK_END : + default : + psf_log_printf (psf, "Bad whence param in header_seek().\n") ; + break ; + } ; + + return ; +} /* header_seek */ + +static int +header_gets (SF_PRIVATE *psf, char *ptr, int bufsize) +{ + int k ; + + for (k = 0 ; k < bufsize - 1 ; k++) + { if (psf->headindex < psf->headend) + { ptr [k] = psf->header [psf->headindex] ; + psf->headindex ++ ; + } + else + { psf->headend += psf_fread (psf->header + psf->headend, 1, 1, psf) ; + ptr [k] = psf->header [psf->headindex] ; + psf->headindex = psf->headend ; + } ; + + if (ptr [k] == '\n') + break ; + } ; + + ptr [k] = 0 ; + + return k ; +} /* header_gets */ + +int +psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) +{ va_list argptr ; + sf_count_t *countptr, countdata ; + unsigned char *ucptr, sixteen_bytes [16] ; + unsigned int *intptr, intdata ; + unsigned short *shortptr ; + char *charptr ; + float *floatptr ; + double *doubleptr ; + char c ; + int byte_count = 0, count ; + + if (! format) + return psf_ftell (psf) ; + + va_start (argptr, format) ; + + while ((c = *format++)) + { switch (c) + { case 'e' : /* All conversions are now from LE to host. */ + psf->rwf_endian = SF_ENDIAN_LITTLE ; + break ; + + case 'E' : /* All conversions are now from BE to host. */ + psf->rwf_endian = SF_ENDIAN_BIG ; + break ; + + case 'm' : + intptr = va_arg (argptr, unsigned int*) ; + ucptr = (unsigned char*) intptr ; + byte_count += header_read (psf, ucptr, sizeof (int)) ; + *intptr = GET_MARKER (ucptr) ; + break ; + + case 'h' : + intptr = va_arg (argptr, unsigned int*) ; + ucptr = (unsigned char*) intptr ; + byte_count += header_read (psf, sixteen_bytes, sizeof (sixteen_bytes)) ; + { int k ; + intdata = 0 ; + for (k = 0 ; k < 16 ; k++) + intdata ^= sixteen_bytes [k] << k ; + } + *intptr = intdata ; + break ; + + case '1' : + charptr = va_arg (argptr, char*) ; + *charptr = 0 ; + byte_count += header_read (psf, charptr, sizeof (char)) ; + break ; + + case '2' : + shortptr = va_arg (argptr, unsigned short*) ; + *shortptr = 0 ; + ucptr = (unsigned char*) shortptr ; + byte_count += header_read (psf, ucptr, sizeof (short)) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + *shortptr = GET_BE_SHORT (ucptr) ; + else + *shortptr = GET_LE_SHORT (ucptr) ; + break ; + + case '3' : + intptr = va_arg (argptr, unsigned int*) ; + *intptr = 0 ; + byte_count += header_read (psf, sixteen_bytes, 3) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + *intptr = GET_BE_3BYTE (sixteen_bytes) ; + else + *intptr = GET_LE_3BYTE (sixteen_bytes) ; + break ; + + case '4' : + intptr = va_arg (argptr, unsigned int*) ; + *intptr = 0 ; + ucptr = (unsigned char*) intptr ; + byte_count += header_read (psf, ucptr, sizeof (int)) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + *intptr = GET_BE_INT (ucptr) ; + else + *intptr = GET_LE_INT (ucptr) ; + break ; + + case '8' : + countptr = va_arg (argptr, sf_count_t *) ; + *countptr = 0 ; + byte_count += header_read (psf, sixteen_bytes, 8) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + countdata = GET_BE_8BYTE (sixteen_bytes) ; + else + countdata = GET_LE_8BYTE (sixteen_bytes) ; + *countptr = countdata ; + break ; + + case 'f' : /* Float conversion */ + floatptr = va_arg (argptr, float *) ; + *floatptr = 0.0 ; + byte_count += header_read (psf, floatptr, sizeof (float)) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + *floatptr = float32_be_read ((unsigned char*) floatptr) ; + else + *floatptr = float32_le_read ((unsigned char*) floatptr) ; + break ; + + case 'd' : /* double conversion */ + doubleptr = va_arg (argptr, double *) ; + *doubleptr = 0.0 ; + byte_count += header_read (psf, doubleptr, sizeof (double)) ; + if (psf->rwf_endian == SF_ENDIAN_BIG) + *doubleptr = double64_be_read ((unsigned char*) doubleptr) ; + else + *doubleptr = double64_le_read ((unsigned char*) doubleptr) ; + break ; + + case 's' : + psf_log_printf (psf, "Format conversion 's' not implemented yet.\n") ; + /* + strptr = va_arg (argptr, char *) ; + size = strlen (strptr) + 1 ; + size += (size & 1) ; + longdata = H2LE_INT (size) ; + get_int (psf, longdata) ; + memcpy (&(psf->header [psf->headindex]), strptr, size) ; + psf->headindex += size ; + */ + break ; + + case 'b' : + charptr = va_arg (argptr, char*) ; + count = va_arg (argptr, int) ; + if (count > 0) + byte_count += header_read (psf, charptr, count) ; + break ; + + case 'G' : + charptr = va_arg (argptr, char*) ; + count = va_arg (argptr, int) ; + if (count > 0) + byte_count += header_gets (psf, charptr, count) ; + break ; + + case 'z' : + psf_log_printf (psf, "Format conversion 'z' not implemented yet.\n") ; + /* + size = va_arg (argptr, size_t) ; + while (size) + { psf->header [psf->headindex] = 0 ; + psf->headindex ++ ; + size -- ; + } ; + */ + break ; + + case 'p' : + /* Get the seek position first. */ + count = va_arg (argptr, int) ; + header_seek (psf, count, SEEK_SET) ; + byte_count = count ; + break ; + + case 'j' : + /* Get the seek position first. */ + count = va_arg (argptr, int) ; + header_seek (psf, count, SEEK_CUR) ; + byte_count += count ; + break ; + + default : + psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ; + psf->error = SFE_INTERNAL ; + break ; + } ; + } ; + + va_end (argptr) ; + + return byte_count ; +} /* psf_binheader_readf */ + +/*----------------------------------------------------------------------------------------------- +*/ + +sf_count_t +psf_default_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) +{ sf_count_t position, retval ; + + if (! (psf->blockwidth && psf->dataoffset >= 0)) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (! psf->sf.seekable) + { psf->error = SFE_NOT_SEEKABLE ; + return PSF_SEEK_ERROR ; + } ; + + position = psf->dataoffset + psf->blockwidth * samples_from_start ; + + if ((retval = psf_fseek (psf, position, SEEK_SET)) != position) + { psf->error = SFE_SEEK_FAILED ; + return PSF_SEEK_ERROR ; + } ; + + mode = mode ; + + return samples_from_start ; +} /* psf_default_seek */ + +/*----------------------------------------------------------------------------------------------- +*/ + +void +psf_hexdump (void *ptr, int len) +{ char ascii [17], *data ; + int k, m ; + + if ((data = ptr) == NULL) + return ; + if (len <= 0) + return ; + + puts ("") ; + for (k = 0 ; k < len ; k += 16) + { memset (ascii, ' ', sizeof (ascii)) ; + + printf ("%08X: ", k) ; + for (m = 0 ; m < 16 && k + m < len ; m++) + { printf (m == 8 ? " %02X " : "%02X ", data [k + m] & 0xFF) ; + ascii [m] = isprint (data [k + m]) ? data [k + m] : '.' ; + } ; + + if (m <= 8) printf (" ") ; + for ( ; m < 16 ; m++) printf (" ") ; + + ascii [16] = 0 ; + printf (" %s\n", ascii) ; + } ; + + puts ("") ; +} /* psf_hexdump */ + +void +psf_log_SF_INFO (SF_PRIVATE *psf) +{ psf_log_printf (psf, "---------------------------------\n") ; + + psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ; + psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ; + psf_log_printf (psf, " Channels : %d\n", psf->sf.channels) ; + + psf_log_printf (psf, " Format : 0x%X\n", psf->sf.format) ; + psf_log_printf (psf, " Sections : %d\n", psf->sf.sections) ; + psf_log_printf (psf, " Seekable : %s\n", psf->sf.seekable ? "TRUE" : "FALSE") ; + + psf_log_printf (psf, "---------------------------------\n") ; +} /* psf_dump_SFINFO */ + +/*======================================================================================== +*/ + +SF_INSTRUMENT * +psf_instrument_alloc (void) +{ SF_INSTRUMENT *instr ; + + instr = calloc (1, sizeof (SF_INSTRUMENT)) ; + + if (instr == NULL) + return NULL ; + + /* Set non-zero default values. */ + instr->basenote = -1 ; + instr->velocity_lo = -1 ; + instr->velocity_hi = -1 ; + instr->key_lo = -1 ; + instr->key_hi = -1 ; + + return instr ; +} /* psf_instrument_alloc */ + +void* +psf_memset (void *s, int c, sf_count_t len) +{ char *ptr ; + int setcount ; + + ptr = (char *) s ; + + while (len > 0) + { setcount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + memset (ptr, c, setcount) ; + + ptr += setcount ; + len -= setcount ; + } ; + + return s ; +} /* psf_memset */ + +void psf_get_date_str (char *str, int maxlen) +{ time_t current ; + struct tm timedata, *tmptr ; + + time (¤t) ; + +#if defined (HAVE_GMTIME_R) + /* If the re-entrant version is available, use it. */ + tmptr = gmtime_r (¤t, &timedata) ; +#elif defined (HAVE_GMTIME) + /* Otherwise use the standard one and copy the data to local storage. */ + tmptr = gmtime (¤t) ; + memcpy (&timedata, tmptr, sizeof (timedata)) ; +#else + tmptr = NULL ; +#endif + + if (tmptr) + LSF_SNPRINTF (str, maxlen, "%4d-%02d-%02d %02d:%02d:%02d UTC", + 1900 + timedata.tm_year, timedata.tm_mon, timedata.tm_mday, + timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ; + else + LSF_SNPRINTF (str, maxlen, "Unknown date") ; + + return ; +} /* psf_get_date_str */ + +int +subformat_to_bytewidth (int format) +{ + switch (format) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_S8 : + return 1 ; + case SF_FORMAT_PCM_16 : + return 2 ; + case SF_FORMAT_PCM_24 : + return 3 ; + case SF_FORMAT_PCM_32 : + case SF_FORMAT_FLOAT : + return 4 ; + case SF_FORMAT_DOUBLE : + return 8 ; + } ; + + return 0 ; +} /* subformat_to_bytewidth */ + +int +s_bitwidth_to_subformat (int bits) +{ static int array [] = + { SF_FORMAT_PCM_S8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32 + } ; + + if (bits < 8 || bits > 32) + return 0 ; + + return array [((bits + 7) / 8) - 1] ; +} /* bitwidth_to_subformat */ + +int +u_bitwidth_to_subformat (int bits) +{ static int array [] = + { SF_FORMAT_PCM_U8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32 + } ; + + if (bits < 8 || bits > 32) + return 0 ; + + return array [((bits + 7) / 8) - 1] ; +} /* bitwidth_to_subformat */ + +#endif /* PSF_LOG_PRINTF_ONLY */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 33e9795e-f717-461a-9feb-65d083a56395 +*/ diff --git a/nylsf/common.h b/nylsf/common.h new file mode 100644 index 0000000..9edc133 --- /dev/null +++ b/nylsf/common.h @@ -0,0 +1,773 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef SNDFILE_COMMON_H +#define SNDFILE_COMMON_H + +#include "sfconfig.h" + +#include + +#if HAVE_STDINT_H +#include +#endif + +#ifndef SNDFILE_H +#include "sndfile.h" +#elif HAVE_INTTYPES_H +#include +#endif + +#ifdef __cplusplus +#error "This code is not designed to be compiled with a C++ compiler." +#endif + +#ifdef UNUSED +#elif defined (__GNUC__) +# define UNUSED(x) UNUSED_ ## x __attribute__ ((unused)) +#elif defined (__LCLINT__) +# define UNUSED(x) /*@unused@*/ x +#else +# define UNUSED(x) x +#endif + +#ifdef __GNUC__ +# define WARN_UNUSED __attribute__ ((warn_unused_result)) +#else +# define WARN_UNUSED +#endif + +#define SF_BUFFER_LEN (8192*2) +#define SF_FILENAME_LEN (512) +#define SF_SYSERR_LEN (256) +#define SF_MAX_STRINGS (16) +#define SF_STR_BUFFER_LEN (8192) +#define SF_HEADER_LEN (4100 + SF_STR_BUFFER_LEN) + +#define PSF_SEEK_ERROR ((sf_count_t) -1) + + +#define BITWIDTH2BYTES(x) (((x) + 7) / 8) + +/* For some reason sizeof returns an unsigned value which causes +** a warning when that value is added or subtracted from a signed +** value. Use SIGNED_SIZEOF instead. +*/ +#define SIGNED_SIZEOF(x) ((int) sizeof (x)) + +#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) + +#define SF_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define SF_MIN(a,b) ((a) < (b) ? (a) : (b)) + +enum +{ /* PEAK chunk location. */ + SF_PEAK_START = 42, + SF_PEAK_END = 43, + + /* PEAK chunk location. */ + SF_SCALE_MAX = 52, + SF_SCALE_MIN = 53, + + /* str_flags values. */ + SF_STR_ALLOW_START = 0x0100, + SF_STR_ALLOW_END = 0x0200, + + /* Location of strings. */ + SF_STR_LOCATE_START = 0x0400, + SF_STR_LOCATE_END = 0x0800, + + SFD_TYPEMASK = 0x0FFFFFFF +} ; + +#define SFM_MASK (SFM_READ | SFM_WRITE | SFM_RDWR) +#define SFM_UNMASK (~SFM_MASK) + +/*--------------------------------------------------------------------------------------- +** Formats that may be supported at some time in the future. +** When support is finalised, these values move to src/sndfile.h. +*/ + +enum +{ /* Work in progress. */ + + /* Formats supported read only. */ + SF_FORMAT_WVE = 0x4020000, /* Psion ALaw Sound File */ + SF_FORMAT_TXW = 0x4030000, /* Yamaha TX16 sampler file */ + SF_FORMAT_DWD = 0x4040000, /* DiamondWare Digirized */ + + /* Following are detected but not supported. */ + SF_FORMAT_OGG = 0x4090000, + + SF_FORMAT_REX = 0x40A0000, /* Propellorheads Rex/Rcy */ + SF_FORMAT_REX2 = 0x40D0000, /* Propellorheads Rex2 */ + SF_FORMAT_KRZ = 0x40E0000, /* Kurzweil sampler file */ + SF_FORMAT_WMA = 0x4100000, /* Windows Media Audio. */ + SF_FORMAT_SHN = 0x4110000, /* Shorten. */ + + /* Unsupported encodings. */ + SF_FORMAT_VORBIS = 0x1001, + + SF_FORMAT_SVX_FIB = 0x1020, /* SVX Fibonacci Delta encoding. */ + SF_FORMAT_SVX_EXP = 0x1021, /* SVX Exponential Delta encoding. */ + + SF_FORMAT_PCM_N = 0x1030 +} ; + +/*--------------------------------------------------------------------------------------- +** PEAK_CHUNK - This chunk type is common to both AIFF and WAVE files although their +** endian encodings are different. +*/ + +typedef struct +{ double value ; /* signed value of peak */ + sf_count_t position ; /* the sample frame for the peak */ +} PEAK_POS ; + +typedef struct +{ /* libsndfile internal : write a PEAK chunk at the start or end of the file? */ + int peak_loc ; + + /* WAV/AIFF */ + unsigned int version ; /* version of the PEAK chunk */ + unsigned int timestamp ; /* secs since 1/1/1970 */ + + /* CAF */ + unsigned int edit_number ; + +#if HAVE_FLEXIBLE_ARRAY + /* the per channel peak info */ + PEAK_POS peaks [] ; +#else + /* + ** This is not ISO compliant C. It works on some compilers which + ** don't support the ISO standard flexible struct array which is + ** used above. If your compiler doesn't like this I suggest you find + ** youself a 1999 ISO C standards compilant compiler. GCC-3.X is + ** highly recommended. + */ + PEAK_POS peaks [0] ; +#endif +} PEAK_INFO ; + +static inline PEAK_INFO * +peak_info_calloc (int channels) +{ return calloc (1, sizeof (PEAK_INFO) + channels * sizeof (PEAK_POS)) ; +} /* peak_info_calloc */ + +typedef struct +{ int type ; + int flags ; + char *str ; +} STR_DATA ; + +static inline size_t +make_size_t (int x) +{ return (size_t) x ; +} /* size_t_of_int */ + +/*======================================================================================= +** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the +** sf_open_XXXX functions. The caller however has no knowledge of the struct's +** contents. +*/ + +typedef struct sf_private_tag +{ /* Force the compiler to double align the start of buffer. */ + union + { double dbuf [SF_BUFFER_LEN / sizeof (double)] ; +#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8)) + int64_t lbuf [SF_BUFFER_LEN / sizeof (int64_t)] ; +#else + long lbuf [SF_BUFFER_LEN / sizeof (double)] ; +#endif + float fbuf [SF_BUFFER_LEN / sizeof (float)] ; + int ibuf [SF_BUFFER_LEN / sizeof (int)] ; + short sbuf [SF_BUFFER_LEN / sizeof (short)] ; + char cbuf [SF_BUFFER_LEN / sizeof (char)] ; + signed char scbuf [SF_BUFFER_LEN / sizeof (signed char)] ; + unsigned char ucbuf [SF_BUFFER_LEN / sizeof (signed char)] ; + } u ; + + char filepath [SF_FILENAME_LEN] ; + char rsrcpath [SF_FILENAME_LEN] ; + char directory [SF_FILENAME_LEN] ; + char filename [SF_FILENAME_LEN / 4] ; + + char syserr [SF_SYSERR_LEN] ; + + /* logbuffer and logindex should only be changed within the logging functions + ** of common.c + */ + char logbuffer [SF_BUFFER_LEN] ; + unsigned char header [SF_HEADER_LEN] ; /* Must be unsigned */ + int rwf_endian ; /* Header endian-ness flag. */ + + /* Storage and housekeeping data for adding/reading strings from + ** sound files. + */ + STR_DATA strings [SF_MAX_STRINGS] ; + char str_storage [SF_STR_BUFFER_LEN] ; + char *str_end ; + int str_flags ; + + /* Guard value. If this changes the buffers above have overflowed. */ + int Magick ; + + /* Index variables for maintaining logbuffer and header above. */ + int logindex ; + int headindex, headend ; + int has_text ; + int do_not_close_descriptor ; + +#if USE_WINDOWS_API + /* + ** These fields can only be used in src/file_io.c. + ** They are basically the same as a windows file HANDLE. + */ + void *hfile, *hrsrc, *hsaved ; +#else + /* These fields can only be used in src/file_io.c. */ + int filedes, rsrcdes, savedes ; +#endif + + int error ; + + int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */ + int endian ; /* File endianness : SF_ENDIAN_LITTLE or SF_ENDIAN_BIG. */ + int float_endswap ; /* Need to endswap float32s? */ + + /* + ** Maximum float value for calculating the multiplier for + ** float/double to short/int conversions. + */ + int float_int_mult ; + float float_max ; + + /* Vairables for handling pipes. */ + int is_pipe ; /* True if file is a pipe. */ + sf_count_t pipeoffset ; /* Number of bytes read from a pipe. */ + + /* True if clipping must be performed on float->int conversions. */ + int add_clipping ; + + SF_INFO sf ; + + int have_written ; /* Has a single write been done to the file? */ + PEAK_INFO *peak_info ; + + /* Loop Info */ + SF_LOOP_INFO *loop_info ; + SF_INSTRUMENT *instrument ; + + /* Broadcast (EBU) Info */ + SF_BROADCAST_INFO *broadcast_info ; + + /* Channel map data (if present) : an array of ints. */ + int *channel_map ; + + sf_count_t filelength ; /* Overall length of (embedded) file. */ + sf_count_t fileoffset ; /* Offset in number of bytes from beginning of file. */ + + sf_count_t rsrclength ; /* Length of the resource fork (if it exists). */ + + sf_count_t dataoffset ; /* Offset in number of bytes from beginning of file. */ + sf_count_t datalength ; /* Length in bytes of the audio data. */ + sf_count_t dataend ; /* Offset to file tailer. */ + + int blockwidth ; /* Size in bytes of one set of interleaved samples. */ + int bytewidth ; /* Size in bytes of one sample (one channel). */ + + void *dither ; + void *interleave ; + + int last_op ; /* Last operation; either SFM_READ or SFM_WRITE */ + sf_count_t read_current ; + sf_count_t write_current ; + + void *container_data ; /* This is a pointer to dynamically allocated file + ** container format specific data. + */ + + void *codec_data ; /* This is a pointer to dynamically allocated file + ** codec format specific data. + */ + + SF_DITHER_INFO write_dither ; + SF_DITHER_INFO read_dither ; + + int norm_double ; + int norm_float ; + + int auto_header ; + + int ieee_replace ; + /* A set of file specific function pointers */ + + sf_count_t (*read_short) (struct sf_private_tag*, short *ptr, sf_count_t len) ; + sf_count_t (*read_int) (struct sf_private_tag*, int *ptr, sf_count_t len) ; + sf_count_t (*read_float) (struct sf_private_tag*, float *ptr, sf_count_t len) ; + sf_count_t (*read_double) (struct sf_private_tag*, double *ptr, sf_count_t len) ; + + sf_count_t (*write_short) (struct sf_private_tag*, const short *ptr, sf_count_t len) ; + sf_count_t (*write_int) (struct sf_private_tag*, const int *ptr, sf_count_t len) ; + sf_count_t (*write_float) (struct sf_private_tag*, const float *ptr, sf_count_t len) ; + sf_count_t (*write_double) (struct sf_private_tag*, const double *ptr, sf_count_t len) ; + + sf_count_t (*seek) (struct sf_private_tag*, int mode, sf_count_t samples_from_start) ; + int (*write_header) (struct sf_private_tag*, int calc_length) ; + int (*command) (struct sf_private_tag*, int command, void *data, int datasize) ; + + /* + ** Separate close functions for the codec and the container. + ** The codec close function is always called first. + */ + int (*codec_close) (struct sf_private_tag*) ; + int (*container_close) (struct sf_private_tag*) ; + + char *format_desc ; + + /* Virtual I/O functions. */ + int virtual_io ; + SF_VIRTUAL_IO vio ; + void *vio_user_data ; +} SF_PRIVATE ; + + + +enum +{ SFE_NO_ERROR = SF_ERR_NO_ERROR, + SFE_BAD_OPEN_FORMAT = SF_ERR_UNRECOGNISED_FORMAT, + SFE_SYSTEM = SF_ERR_SYSTEM, + SFE_MALFORMED_FILE = SF_ERR_MALFORMED_FILE, + SFE_UNSUPPORTED_ENCODING = SF_ERR_UNSUPPORTED_ENCODING, + + SFE_BAD_FILE, + SFE_BAD_FILE_READ, + SFE_OPEN_FAILED, + SFE_BAD_SNDFILE_PTR, + SFE_BAD_SF_INFO_PTR, + SFE_BAD_SF_INCOMPLETE, + SFE_BAD_FILE_PTR, + SFE_BAD_INT_PTR, + SFE_BAD_STAT_SIZE, + SFE_MALLOC_FAILED, + SFE_UNIMPLEMENTED, + SFE_BAD_READ_ALIGN, + SFE_BAD_WRITE_ALIGN, + SFE_UNKNOWN_FORMAT, + SFE_NOT_READMODE, + SFE_NOT_WRITEMODE, + SFE_BAD_MODE_RW, + SFE_BAD_SF_INFO, + SFE_BAD_OFFSET, + SFE_NO_EMBED_SUPPORT, + SFE_NO_EMBEDDED_RDWR, + SFE_NO_PIPE_WRITE, + + SFE_INTERNAL, + SFE_BAD_CONTROL_CMD, + SFE_BAD_ENDIAN, + SFE_CHANNEL_COUNT, + SFE_BAD_RDWR_FORMAT, + + SFE_BAD_VIRTUAL_IO, + + SFE_INTERLEAVE_MODE, + SFE_INTERLEAVE_SEEK, + SFE_INTERLEAVE_READ, + + SFE_BAD_SEEK, + SFE_NOT_SEEKABLE, + SFE_AMBIGUOUS_SEEK, + SFE_WRONG_SEEK, + SFE_SEEK_FAILED, + + SFE_BAD_OPEN_MODE, + SFE_OPEN_PIPE_RDWR, + SFE_RDWR_POSITION, + SFE_RDWR_BAD_HEADER, + + SFE_STR_NO_SUPPORT, + SFE_STR_NOT_WRITE, + SFE_STR_MAX_DATA, + SFE_STR_MAX_COUNT, + SFE_STR_BAD_TYPE, + SFE_STR_NO_ADD_END, + SFE_STR_BAD_STRING, + SFE_STR_WEIRD, + + SFE_WAV_NO_RIFF, + SFE_WAV_NO_WAVE, + SFE_WAV_NO_FMT, + SFE_WAV_FMT_SHORT, + SFE_WAV_BAD_FACT, + SFE_WAV_BAD_PEAK, + SFE_WAV_PEAK_B4_FMT, + SFE_WAV_BAD_FORMAT, + SFE_WAV_BAD_BLOCKALIGN, + SFE_WAV_NO_DATA, + SFE_WAV_BAD_LIST, + SFE_WAV_ADPCM_NOT4BIT, + SFE_WAV_ADPCM_CHANNELS, + SFE_WAV_GSM610_FORMAT, + SFE_WAV_UNKNOWN_CHUNK, + SFE_WAV_WVPK_DATA, + + SFE_AIFF_NO_FORM, + SFE_AIFF_AIFF_NO_FORM, + SFE_AIFF_COMM_NO_FORM, + SFE_AIFF_SSND_NO_COMM, + SFE_AIFF_UNKNOWN_CHUNK, + SFE_AIFF_COMM_CHUNK_SIZE, + SFE_AIFF_BAD_COMM_CHUNK, + SFE_AIFF_PEAK_B4_COMM, + SFE_AIFF_BAD_PEAK, + SFE_AIFF_NO_SSND, + SFE_AIFF_NO_DATA, + SFE_AIFF_RW_SSND_NOT_LAST, + + SFE_AU_UNKNOWN_FORMAT, + SFE_AU_NO_DOTSND, + SFE_AU_EMBED_BAD_LEN, + + SFE_RAW_READ_BAD_SPEC, + SFE_RAW_BAD_BITWIDTH, + SFE_RAW_BAD_FORMAT, + + SFE_PAF_NO_MARKER, + SFE_PAF_VERSION, + SFE_PAF_UNKNOWN_FORMAT, + SFE_PAF_SHORT_HEADER, + + SFE_SVX_NO_FORM, + SFE_SVX_NO_BODY, + SFE_SVX_NO_DATA, + SFE_SVX_BAD_COMP, + SFE_SVX_BAD_NAME_LENGTH, + + SFE_NIST_BAD_HEADER, + SFE_NIST_CRLF_CONVERISON, + SFE_NIST_BAD_ENCODING, + + SFE_VOC_NO_CREATIVE, + SFE_VOC_BAD_FORMAT, + SFE_VOC_BAD_VERSION, + SFE_VOC_BAD_MARKER, + SFE_VOC_BAD_SECTIONS, + SFE_VOC_MULTI_SAMPLERATE, + SFE_VOC_MULTI_SECTION, + SFE_VOC_MULTI_PARAM, + SFE_VOC_SECTION_COUNT, + SFE_VOC_NO_PIPE, + + SFE_IRCAM_NO_MARKER, + SFE_IRCAM_BAD_CHANNELS, + SFE_IRCAM_UNKNOWN_FORMAT, + + SFE_W64_64_BIT, + SFE_W64_NO_RIFF, + SFE_W64_NO_WAVE, + SFE_W64_NO_FMT, + SFE_W64_NO_DATA, + SFE_W64_FMT_SHORT, + SFE_W64_FMT_TOO_BIG, + SFE_W64_ADPCM_NOT4BIT, + SFE_W64_ADPCM_CHANNELS, + SFE_W64_GSM610_FORMAT, + + SFE_MAT4_BAD_NAME, + SFE_MAT4_NO_SAMPLERATE, + SFE_MAT4_ZERO_CHANNELS, + + SFE_MAT5_BAD_ENDIAN, + SFE_MAT5_NO_BLOCK, + SFE_MAT5_SAMPLE_RATE, + SFE_MAT5_ZERO_CHANNELS, + + SFE_PVF_NO_PVF1, + SFE_PVF_BAD_HEADER, + SFE_PVF_BAD_BITWIDTH, + + SFE_DWVW_BAD_BITWIDTH, + SFE_G72X_NOT_MONO, + + SFE_XI_BAD_HEADER, + SFE_XI_EXCESS_SAMPLES, + SFE_XI_NO_PIPE, + + SFE_HTK_NO_PIPE, + + SFE_SDS_NOT_SDS, + SFE_SDS_BAD_BIT_WIDTH, + + SFE_SD2_FD_DISALLOWED, + SFE_SD2_BAD_DATA_OFFSET, + SFE_SD2_BAD_MAP_OFFSET, + SFE_SD2_BAD_DATA_LENGTH, + SFE_SD2_BAD_MAP_LENGTH, + SFE_SD2_BAD_RSRC, + SFE_SD2_BAD_SAMPLE_SIZE, + + SFE_FLAC_BAD_HEADER, + SFE_FLAC_NEW_DECODER, + SFE_FLAC_INIT_DECODER, + SFE_FLAC_LOST_SYNC, + SFE_FLAC_BAD_SAMPLE_RATE, + SFE_FLAC_UNKNOWN_ERROR, + + SFE_MAX_ERROR /* This must be last in list. */ +} ; + +int subformat_to_bytewidth (int format) ; +int s_bitwidth_to_subformat (int bits) ; +int u_bitwidth_to_subformat (int bits) ; + +/* Functions for reading and writing floats and doubles on processors +** with non-IEEE floats/doubles. +*/ +float float32_be_read (unsigned char *cptr) ; +float float32_le_read (unsigned char *cptr) ; +void float32_be_write (float in, unsigned char *out) ; +void float32_le_write (float in, unsigned char *out) ; + +double double64_be_read (unsigned char *cptr) ; +double double64_le_read (unsigned char *cptr) ; +void double64_be_write (double in, unsigned char *out) ; +void double64_le_write (double in, unsigned char *out) ; + +/* Functions for writing to the internal logging buffer. */ + +void psf_log_printf (SF_PRIVATE *psf, const char *format, ...) ; +void psf_log_SF_INFO (SF_PRIVATE *psf) ; + +void psf_hexdump (void *ptr, int len) ; + +/* Functions used when writing file headers. */ + +int psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) ; +void psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...) ; + +/* Functions used when reading file headers. */ + +int psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) ; + +/* Functions used in the write function for updating the peak chunk. */ + +void peak_update_short (SF_PRIVATE *psf, short *ptr, size_t items) ; +void peak_update_int (SF_PRIVATE *psf, int *ptr, size_t items) ; +void peak_update_double (SF_PRIVATE *psf, double *ptr, size_t items) ; + +/* Functions defined in command.c. */ + +int psf_get_format_simple_count (void) ; +int psf_get_format_simple (SF_FORMAT_INFO *data) ; + +int psf_get_format_info (SF_FORMAT_INFO *data) ; + +int psf_get_format_major_count (void) ; +int psf_get_format_major (SF_FORMAT_INFO *data) ; + +int psf_get_format_subtype_count (void) ; +int psf_get_format_subtype (SF_FORMAT_INFO *data) ; + +void psf_generate_format_desc (SF_PRIVATE *psf) ; + +double psf_calc_signal_max (SF_PRIVATE *psf, int normalize) ; +int psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize) ; + +int psf_get_signal_max (SF_PRIVATE *psf, double *peak) ; +int psf_get_max_all_channels (SF_PRIVATE *psf, double *peaks) ; + +/* Functions in strings.c. */ + +const char* psf_get_string (SF_PRIVATE *psf, int str_type) ; +int psf_set_string (SF_PRIVATE *psf, int str_type, const char *str) ; +int psf_store_string (SF_PRIVATE *psf, int str_type, const char *str) ; + +/* Default seek function. Use for PCM and float encoded data. */ +sf_count_t psf_default_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) ; + +/* Generate the currebt date as a string. */ +void psf_get_date_str (char *str, int maxlen) ; + +int macos_guess_file_type (SF_PRIVATE *psf, const char *filename) ; + +/*------------------------------------------------------------------------------------ +** File I/O functions which will allow access to large files (> 2 Gig) on +** some 32 bit OSes. Implementation in file_io.c. +*/ + +int psf_fopen (SF_PRIVATE *psf, const char *pathname, int flags) ; +int psf_set_stdio (SF_PRIVATE *psf, int mode) ; +int psf_file_valid (SF_PRIVATE *psf) ; +void psf_set_file (SF_PRIVATE *psf, int fd) ; +void psf_init_files (SF_PRIVATE *psf) ; +void psf_use_rsrc (SF_PRIVATE *psf, int on_off) ; + +sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) ; +sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ; +sf_count_t psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ; +sf_count_t psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) ; +sf_count_t psf_ftell (SF_PRIVATE *psf) ; +sf_count_t psf_get_filelen (SF_PRIVATE *psf) ; + +void psf_fsync (SF_PRIVATE *psf) ; + +int psf_is_pipe (SF_PRIVATE *psf) ; + +int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) ; +int psf_fclose (SF_PRIVATE *psf) ; + +/* Open and close the resource fork of a file. */ +int psf_open_rsrc (SF_PRIVATE *psf, int mode) ; +int psf_close_rsrc (SF_PRIVATE *psf) ; + +/* +void psf_fclearerr (SF_PRIVATE *psf) ; +int psf_ferror (SF_PRIVATE *psf) ; +*/ + +/*------------------------------------------------------------------------------------ +** Functions for reading and writing different file formats. +*/ + +int aiff_open (SF_PRIVATE *psf) ; +int au_open (SF_PRIVATE *psf) ; +int avr_open (SF_PRIVATE *psf) ; +int htk_open (SF_PRIVATE *psf) ; +int ircam_open (SF_PRIVATE *psf) ; +int mat4_open (SF_PRIVATE *psf) ; +int mat5_open (SF_PRIVATE *psf) ; +int nist_open (SF_PRIVATE *psf) ; +int paf_open (SF_PRIVATE *psf) ; +int pvf_open (SF_PRIVATE *psf) ; +int raw_open (SF_PRIVATE *psf) ; +int sd2_open (SF_PRIVATE *psf) ; +int sds_open (SF_PRIVATE *psf) ; +int svx_open (SF_PRIVATE *psf) ; +int voc_open (SF_PRIVATE *psf) ; +int w64_open (SF_PRIVATE *psf) ; +int wav_open (SF_PRIVATE *psf) ; +int xi_open (SF_PRIVATE *psf) ; +int flac_open (SF_PRIVATE *psf) ; +int caf_open (SF_PRIVATE *psf) ; + +/* In progress. Do not currently work. */ + +int mpeg_open (SF_PRIVATE *psf) ; +int ogg_open (SF_PRIVATE *psf) ; +int rx2_open (SF_PRIVATE *psf) ; +int txw_open (SF_PRIVATE *psf) ; +int wve_open (SF_PRIVATE *psf) ; +int dwd_open (SF_PRIVATE *psf) ; + +int macbinary3_open (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------------ +** Init functions for a number of common data encodings. +*/ + +int pcm_init (SF_PRIVATE *psf) ; +int ulaw_init (SF_PRIVATE *psf) ; +int alaw_init (SF_PRIVATE *psf) ; +int float32_init (SF_PRIVATE *psf) ; +int double64_init (SF_PRIVATE *psf) ; +int dwvw_init (SF_PRIVATE *psf, int bitwidth) ; +int gsm610_init (SF_PRIVATE *psf) ; +int vox_adpcm_init (SF_PRIVATE *psf) ; +int flac_init (SF_PRIVATE *psf) ; +int g72x_init (SF_PRIVATE * psf) ; + +int dither_init (SF_PRIVATE *psf, int mode) ; + +int wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; +int wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; + +int aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; + +int interleave_init (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------------ +** Other helper functions. +*/ + +void *psf_memset (void *s, int c, sf_count_t n) ; + +SF_INSTRUMENT * psf_instrument_alloc (void) ; + + +SF_BROADCAST_INFO* broadcast_info_alloc (void) ; +int broadcast_info_copy (SF_BROADCAST_INFO* dst, SF_BROADCAST_INFO* src) ; +int broadcast_add_coding_history (SF_BROADCAST_INFO* bext, unsigned int channels, unsigned int samplerate) ; + +/*------------------------------------------------------------------------------------ +** Here's how we fix systems which don't snprintf / vsnprintf. +** Systems without these functions should use the +*/ + +#if USE_WINDOWS_API +#define LSF_SNPRINTF _snprintf +#elif (HAVE_SNPRINTF && ! FORCE_MISSING_SNPRINTF) +#define LSF_SNPRINTF snprintf +#else +int missing_snprintf (char *str, size_t n, char const *fmt, ...) ; +#define LSF_SNPRINTF missing_snprintf +#endif + +#if USE_WINDOWS_API +#define LSF_VSNPRINTF _vsnprintf +#elif (HAVE_VSNPRINTF && ! FORCE_MISSING_SNPRINTF) +#define LSF_VSNPRINTF vsnprintf +#else +int missing_vsnprintf (char *str, size_t n, const char *fmt, ...) ; +#define LSF_VSNPRINTF missing_vsnprintf +#endif + +/*------------------------------------------------------------------------------------ +** Extra commands for sf_command(). Not for public use yet. +*/ + +enum +{ SFC_TEST_AIFF_ADD_INST_CHUNK = 0x2000, + SFC_TEST_WAV_ADD_INFO_CHUNK = 0x2010 +} ; + +/* +** Maybe, one day, make these functions or something like them, public. +** +** Buffer to buffer dithering. Pointer in and out are allowed to point +** to the same buffer for in-place dithering. +*/ + +#if 0 +int sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int count) ; +int sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int count) ; +int sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int count) ; +int sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int count) ; +#endif + +#endif /* SNDFILE_COMMON_H */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 7b45c0ee-5835-4a18-a4ef-994e4cd95b67 +*/ diff --git a/nylsf/config.h b/nylsf/config.h new file mode 100644 index 0000000..a1e2834 --- /dev/null +++ b/nylsf/config.h @@ -0,0 +1,47 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ +/* modified by RBD for Nyquist. Since Nyquist has a "config" file + * called switches.h, we'll put the stuff that matters in there. + * + * Some switches seem to be global or trivial to define in a system + * independent fashion -- those definitions are in this file. + */ + +#ifndef SWITCHES +#include "switches.h" +#endif + +/* Set to 1 to enable experimental code. */ +#define ENABLE_EXPERIMENTAL_CODE 0 + +/* Define to 1 if you have the header file. */ +#undef HAVE_FLAC_ALL_H + +/* Name of package */ +#define PACKAGE "libsndfile" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libsndfile" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.0.17" + +/* Set to maximum allowed value of sf_count_t type. */ +#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP sizeof(void *) + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.0.17" + +/* inline is only defined for C++ in Visual C++ compiler */ +#ifdef WIN32 + #define inline __inline +#endif + +/* libsndfile uses HAVE_STDLIB_H instead of HAS_STDLIB_H */ +#define HAVE_STDLIB_H HAS_STDLIB_H diff --git a/nylsf/dither.c b/nylsf/dither.c new file mode 100644 index 0000000..873f1bb --- /dev/null +++ b/nylsf/dither.c @@ -0,0 +1,535 @@ +/* +** Copyright (C) 2003,2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*============================================================================ +** Rule number 1 is to only apply dither when going from a larger bitwidth +** to a smaller bitwidth. This can happen on both read and write. +** +** Need to apply dither on all conversions marked X below. +** +** Dither on write: +** +** Input +** | short int float double +** --------+----------------------------------------------- +** O 8 bit | X X X X +** u 16 bit | none X X X +** t 24 bit | none X X X +** p 32 bit | none none X X +** u float | none none none none +** t double | none none none none +** +** Dither on read: +** +** Input +** O | 8 bit 16 bit 24 bit 32 bit float double +** u --------+------------------------------------------------- +** t short | none none X X X X +** p int | none none none X X X +** u float | none none none none none none +** t double | none none none none none none +*/ + +#define SFE_DITHER_BAD_PTR 666 +#define SFE_DITHER_BAD_TYPE 667 + +typedef struct +{ int read_short_dither_bits, read_int_dither_bits ; + int write_short_dither_bits, write_int_dither_bits ; + double read_float_dither_scale, read_double_dither_bits ; + double write_float_dither_scale, write_double_dither_bits ; + + sf_count_t (*read_short) (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; + sf_count_t (*read_int) (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; + sf_count_t (*read_float) (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; + sf_count_t (*read_double) (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + + sf_count_t (*write_short) (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; + sf_count_t (*write_int) (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; + sf_count_t (*write_float) (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; + sf_count_t (*write_double) (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + + double buffer [SF_BUFFER_LEN / sizeof (double)] ; +} DITHER_DATA ; + +static sf_count_t dither_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; + +static sf_count_t dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +int +dither_init (SF_PRIVATE *psf, int mode) +{ DITHER_DATA *pdither ; + + pdither = psf->dither ; /* This may be NULL. */ + + /* Turn off dither on read. */ + if (mode == SFM_READ && psf->read_dither.type == SFD_NO_DITHER) + { if (pdither == NULL) + return 0 ; /* Dither is already off, so just return. */ + + if (pdither->read_short) + psf->read_short = pdither->read_short ; + if (pdither->read_int) + psf->read_int = pdither->read_int ; + if (pdither->read_float) + psf->read_float = pdither->read_float ; + if (pdither->read_double) + psf->read_double = pdither->read_double ; + return 0 ; + } ; + + /* Turn off dither on write. */ + if (mode == SFM_WRITE && psf->write_dither.type == SFD_NO_DITHER) + { if (pdither == NULL) + return 0 ; /* Dither is already off, so just return. */ + + if (pdither->write_short) + psf->write_short = pdither->write_short ; + if (pdither->write_int) + psf->write_int = pdither->write_int ; + if (pdither->write_float) + psf->write_float = pdither->write_float ; + if (pdither->write_double) + psf->write_double = pdither->write_double ; + return 0 ; + } ; + + /* Turn on dither on read if asked. */ + if (mode == SFM_READ && psf->read_dither.type != 0) + { if (pdither == NULL) + pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ; + if (pdither == NULL) + return SFE_MALLOC_FAILED ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_DOUBLE : + case SF_FORMAT_FLOAT : + pdither->read_int = psf->read_int ; + psf->read_int = dither_read_int ; + + case SF_FORMAT_PCM_32 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_U8 : + pdither->read_short = psf->read_short ; + psf->read_short = dither_read_short ; + + default : break ; + } ; + } ; + + /* Turn on dither on write if asked. */ + if (mode == SFM_WRITE && psf->write_dither.type != 0) + { if (pdither == NULL) + pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ; + if (pdither == NULL) + return SFE_MALLOC_FAILED ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_DOUBLE : + case SF_FORMAT_FLOAT : + pdither->write_int = psf->write_int ; + psf->write_int = dither_write_int ; + + case SF_FORMAT_PCM_32 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_U8 : + + default : break ; + } ; + + pdither->write_short = psf->write_short ; + psf->write_short = dither_write_short ; + + pdither->write_int = psf->write_int ; + psf->write_int = dither_write_int ; + + pdither->write_float = psf->write_float ; + psf->write_float = dither_write_float ; + + pdither->write_double = psf->write_double ; + psf->write_double = dither_write_double ; + } ; + + return 0 ; +} /* dither_init */ + +/*============================================================================== +*/ + +static void dither_short (const short *in, short *out, int frames, int channels) ; +static void dither_int (const int *in, int *out, int frames, int channels) ; + +static void dither_float (const float *in, float *out, int frames, int channels) ; +static void dither_double (const double *in, double *out, int frames, int channels) ; + +static sf_count_t +dither_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ psf = psf ; + ptr = ptr ; + return len ; +} /* dither_read_short */ + +static sf_count_t +dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ psf = psf ; + ptr = ptr ; + return len ; +} /* dither_read_int */ + +/*------------------------------------------------------------------------------ +*/ + +static sf_count_t +dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ DITHER_DATA *pdither ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + + if ((pdither = psf->dither) == NULL) + { psf->error = SFE_DITHER_BAD_PTR ; + return 0 ; + } ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_U8 : + case SF_FORMAT_DPCM_8 : + break ; + + default : + return pdither->write_short (psf, ptr, len) ; + } ; + + bufferlen = sizeof (pdither->buffer) / sizeof (short) ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + writecount /= psf->sf.channels ; + writecount *= psf->sf.channels ; + + dither_short (ptr, (short*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; + + thiswrite = pdither->write_short (psf, (short*) pdither->buffer, writecount) ; + total += thiswrite ; + len -= thiswrite ; + if (thiswrite < writecount) + break ; + } ; + + return total ; +} /* dither_write_short */ + +static sf_count_t +dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ DITHER_DATA *pdither ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + + if ((pdither = psf->dither) == NULL) + { psf->error = SFE_DITHER_BAD_PTR ; + return 0 ; + } ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + + case SF_FORMAT_DPCM_8 : + case SF_FORMAT_DPCM_16 : + break ; + + default : + return pdither->write_int (psf, ptr, len) ; + } ; + + + bufferlen = sizeof (pdither->buffer) / sizeof (int) ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + writecount /= psf->sf.channels ; + writecount *= psf->sf.channels ; + + dither_int (ptr, (int*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; + + thiswrite = pdither->write_int (psf, (int*) pdither->buffer, writecount) ; + total += thiswrite ; + len -= thiswrite ; + if (thiswrite < writecount) + break ; + } ; + + return total ; +} /* dither_write_int */ + +static sf_count_t +dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ DITHER_DATA *pdither ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + + if ((pdither = psf->dither) == NULL) + { psf->error = SFE_DITHER_BAD_PTR ; + return 0 ; + } ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + + case SF_FORMAT_DPCM_8 : + case SF_FORMAT_DPCM_16 : + break ; + + default : + return pdither->write_float (psf, ptr, len) ; + } ; + + bufferlen = sizeof (pdither->buffer) / sizeof (float) ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (float) len ; + writecount /= psf->sf.channels ; + writecount *= psf->sf.channels ; + + dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; + + thiswrite = pdither->write_float (psf, (float*) pdither->buffer, writecount) ; + total += thiswrite ; + len -= thiswrite ; + if (thiswrite < writecount) + break ; + } ; + + return total ; +} /* dither_write_float */ + +static sf_count_t +dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ DITHER_DATA *pdither ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + + if ((pdither = psf->dither) == NULL) + { psf->error = SFE_DITHER_BAD_PTR ; + return 0 ; + } ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + + case SF_FORMAT_DPCM_8 : + case SF_FORMAT_DPCM_16 : + break ; + + default : + return pdither->write_double (psf, ptr, len) ; + } ; + + + bufferlen = sizeof (pdither->buffer) / sizeof (double) ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (double) len ; + writecount /= psf->sf.channels ; + writecount *= psf->sf.channels ; + + dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; + + thiswrite = pdither->write_double (psf, (double*) pdither->buffer, writecount) ; + total += thiswrite ; + len -= thiswrite ; + if (thiswrite < writecount) + break ; + } ; + + return total ; +} /* dither_write_double */ + +/*============================================================================== +*/ + +static void +dither_short (const short *in, short *out, int frames, int channels) +{ int ch, k ; + + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + +} /* dither_short */ + +static void +dither_int (const int *in, int *out, int frames, int channels) +{ int ch, k ; + + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + +} /* dither_int */ + +static void +dither_float (const float *in, float *out, int frames, int channels) +{ int ch, k ; + + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + +} /* dither_float */ + +static void +dither_double (const double *in, double *out, int frames, int channels) +{ int ch, k ; + + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + +} /* dither_double */ + +/*============================================================================== +*/ +#if 0 + +/* +** Not made public because this (maybe) requires storage of state information. +** +** Also maybe need separate state info for each channel!!!! +*/ + +int +DO_NOT_USE_sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int frames, int channels) +{ int ch, k ; + + if (! dither) + return SFE_DITHER_BAD_PTR ; + + switch (dither->type & SFD_TYPEMASK) + { case SFD_WHITE : + case SFD_TRIANGULAR_PDF : + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + break ; + + default : + return SFE_DITHER_BAD_TYPE ; + } ; + + return 0 ; +} /* DO_NOT_USE_sf_dither_short */ + +int +DO_NOT_USE_sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int frames, int channels) +{ int ch, k ; + + if (! dither) + return SFE_DITHER_BAD_PTR ; + + switch (dither->type & SFD_TYPEMASK) + { case SFD_WHITE : + case SFD_TRIANGULAR_PDF : + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + break ; + + default : + return SFE_DITHER_BAD_TYPE ; + } ; + + return 0 ; +} /* DO_NOT_USE_sf_dither_int */ + +int +DO_NOT_USE_sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int frames, int channels) +{ int ch, k ; + + if (! dither) + return SFE_DITHER_BAD_PTR ; + + switch (dither->type & SFD_TYPEMASK) + { case SFD_WHITE : + case SFD_TRIANGULAR_PDF : + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + break ; + + default : + return SFE_DITHER_BAD_TYPE ; + } ; + + return 0 ; +} /* DO_NOT_USE_sf_dither_float */ + +int +DO_NOT_USE_sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int frames, int channels) +{ int ch, k ; + + if (! dither) + return SFE_DITHER_BAD_PTR ; + + switch (dither->type & SFD_TYPEMASK) + { case SFD_WHITE : + case SFD_TRIANGULAR_PDF : + for (ch = 0 ; ch < channels ; ch++) + for (k = ch ; k < channels * frames ; k += channels) + out [k] = in [k] ; + break ; + + default : + return SFE_DITHER_BAD_TYPE ; + } ; + + return 0 ; +} /* DO_NOT_USE_sf_dither_double */ + +#endif +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 673fad58-5314-421c-9144-9d54bfdf104c +*/ diff --git a/nylsf/double64.c b/nylsf/double64.c new file mode 100644 index 0000000..6513f7d --- /dev/null +++ b/nylsf/double64.c @@ -0,0 +1,1008 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "float_cast.h" + +#if CPU_IS_LITTLE_ENDIAN + #define DOUBLE64_READ double64_le_read + #define DOUBLE64_WRITE double64_le_write +#elif CPU_IS_BIG_ENDIAN + #define DOUBLE64_READ double64_be_read + #define DOUBLE64_WRITE double64_be_write +#endif + +/* A 32 number which will not overflow when multiplied by sizeof (double). */ +#define SENSIBLE_LEN (0x8000000) + +/*-------------------------------------------------------------------------------------------- +** Processor floating point capabilities. double64_get_capability () returns one of the +** latter three values. +*/ + +enum +{ DOUBLE_UNKNOWN = 0x00, + DOUBLE_CAN_RW_LE = 0x23, + DOUBLE_CAN_RW_BE = 0x34, + DOUBLE_BROKEN_LE = 0x45, + DOUBLE_BROKEN_BE = 0x56 +} ; + +/*-------------------------------------------------------------------------------------------- +** Prototypes for private functions. +*/ + +static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static void double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx) ; + +static int double64_get_capability (SF_PRIVATE *psf) ; + +static sf_count_t replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static void d2bd_read (double *buffer, int count) ; +static void bd2d_write (double *buffer, int count) ; + +/*-------------------------------------------------------------------------------------------- +** Exported functions. +*/ + +int +double64_init (SF_PRIVATE *psf) +{ static int double64_caps ; + + double64_caps = double64_get_capability (psf) ; + + psf->blockwidth = sizeof (double) * psf->sf.channels ; + + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { switch (psf->endian + double64_caps) + { case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = host_read_d2s ; + psf->read_int = host_read_d2i ; + psf->read_float = host_read_d2f ; + psf->read_double = host_read_d ; + break ; + + case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = host_read_d2s ; + psf->read_int = host_read_d2i ; + psf->read_float = host_read_d2f ; + psf->read_double = host_read_d ; + break ; + + case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = host_read_d2s ; + psf->read_int = host_read_d2i ; + psf->read_float = host_read_d2f ; + psf->read_double = host_read_d ; + break ; + + case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = host_read_d2s ; + psf->read_int = host_read_d2i ; + psf->read_float = host_read_d2f ; + psf->read_double = host_read_d ; + break ; + + /* When the CPU is not IEEE compatible. */ + case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = replace_read_d2s ; + psf->read_int = replace_read_d2i ; + psf->read_float = replace_read_d2f ; + psf->read_double = replace_read_d ; + break ; + + case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = replace_read_d2s ; + psf->read_int = replace_read_d2i ; + psf->read_float = replace_read_d2f ; + psf->read_double = replace_read_d ; + break ; + + case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = replace_read_d2s ; + psf->read_int = replace_read_d2i ; + psf->read_float = replace_read_d2f ; + psf->read_double = replace_read_d ; + break ; + + case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = replace_read_d2s ; + psf->read_int = replace_read_d2i ; + psf->read_float = replace_read_d2f ; + psf->read_double = replace_read_d ; + break ; + + default : break ; + } ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { switch (psf->endian + double64_caps) + { case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = host_write_s2d ; + psf->write_int = host_write_i2d ; + psf->write_float = host_write_f2d ; + psf->write_double = host_write_d ; + break ; + + case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = host_write_s2d ; + psf->write_int = host_write_i2d ; + psf->write_float = host_write_f2d ; + psf->write_double = host_write_d ; + break ; + + case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = host_write_s2d ; + psf->write_int = host_write_i2d ; + psf->write_float = host_write_f2d ; + psf->write_double = host_write_d ; + break ; + + case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = host_write_s2d ; + psf->write_int = host_write_i2d ; + psf->write_float = host_write_f2d ; + psf->write_double = host_write_d ; + break ; + + /* When the CPU is not IEEE compatible. */ + case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = replace_write_s2d ; + psf->write_int = replace_write_i2d ; + psf->write_float = replace_write_f2d ; + psf->write_double = replace_write_d ; + break ; + + case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = replace_write_s2d ; + psf->write_int = replace_write_i2d ; + psf->write_float = replace_write_f2d ; + psf->write_double = replace_write_d ; + break ; + + case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = replace_write_s2d ; + psf->write_int = replace_write_i2d ; + psf->write_float = replace_write_f2d ; + psf->write_double = replace_write_d ; + break ; + + case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = replace_write_s2d ; + psf->write_int = replace_write_i2d ; + psf->write_float = replace_write_f2d ; + psf->write_double = replace_write_d ; + break ; + + default : break ; + } ; + } ; + + if (psf->filelength > psf->dataoffset) + { psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset : + psf->filelength - psf->dataoffset ; + } + else + psf->datalength = 0 ; + + psf->sf.frames = psf->datalength / psf->blockwidth ; + + return 0 ; +} /* double64_init */ + +/*---------------------------------------------------------------------------- +** From : http://www.hpcf.cam.ac.uk/fp_formats.html +** +** 64 bit double precision layout (big endian) +** Sign bit 0 +** Exponent bits 1-11 +** Mantissa bits 12-63 +** Exponent Offset 1023 +** +** double single +** +** +INF 7FF0000000000000 7F800000 +** -INF FFF0000000000000 FF800000 +** NaN 7FF0000000000001 7F800001 +** to to +** 7FFFFFFFFFFFFFFF 7FFFFFFF +** and and +** FFF0000000000001 FF800001 +** to to +** FFFFFFFFFFFFFFFF FFFFFFFF +** +OVER 7FEFFFFFFFFFFFFF 7F7FFFFF +** -OVER FFEFFFFFFFFFFFFF FF7FFFFF +** +UNDER 0010000000000000 00800000 +** -UNDER 8010000000000000 80800000 +*/ + +double +double64_be_read (unsigned char *cptr) +{ int exponent, negative, upper, lower ; + double dvalue ; + + negative = (cptr [0] & 0x80) ? 1 : 0 ; + exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ; + + /* Might not have a 64 bit long, so load the mantissa into a double. */ + upper = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ; + lower = (cptr [5] << 16) | (cptr [6] << 8) | cptr [7] ; + + if (exponent == 0 && upper == 0 && lower == 0) + return 0.0 ; + + dvalue = upper + lower / ((double) 0x1000000) ; + dvalue += 0x10000000 ; + + exponent = exponent - 0x3FF ; + + dvalue = dvalue / ((double) 0x10000000) ; + + if (negative) + dvalue *= -1 ; + + if (exponent > 0) + dvalue *= (1 << exponent) ; + else if (exponent < 0) + dvalue /= (1 << abs (exponent)) ; + + return dvalue ; +} /* double64_be_read */ + +double +double64_le_read (unsigned char *cptr) +{ int exponent, negative, upper, lower ; + double dvalue ; + + negative = (cptr [7] & 0x80) ? 1 : 0 ; + exponent = ((cptr [7] & 0x7F) << 4) | ((cptr [6] >> 4) & 0xF) ; + + /* Might not have a 64 bit long, so load the mantissa into a double. */ + upper = ((cptr [6] & 0xF) << 24) | (cptr [5] << 16) | (cptr [4] << 8) | cptr [3] ; + lower = (cptr [2] << 16) | (cptr [1] << 8) | cptr [0] ; + + if (exponent == 0 && upper == 0 && lower == 0) + return 0.0 ; + + dvalue = upper + lower / ((double) 0x1000000) ; + dvalue += 0x10000000 ; + + exponent = exponent - 0x3FF ; + + dvalue = dvalue / ((double) 0x10000000) ; + + if (negative) + dvalue *= -1 ; + + if (exponent > 0) + dvalue *= (1 << exponent) ; + else if (exponent < 0) + dvalue /= (1 << abs (exponent)) ; + + return dvalue ; +} /* double64_le_read */ + +void +double64_be_write (double in, unsigned char *out) +{ int exponent, mantissa ; + + memset (out, 0, sizeof (double)) ; + + if (fabs (in) < 1e-30) + return ; + + if (in < 0.0) + { in *= -1.0 ; + out [0] |= 0x80 ; + } ; + + in = frexp (in, &exponent) ; + + exponent += 1022 ; + + out [0] |= (exponent >> 4) & 0x7F ; + out [1] |= (exponent << 4) & 0xF0 ; + + in *= 0x20000000 ; + mantissa = lrint (floor (in)) ; + + out [1] |= (mantissa >> 24) & 0xF ; + out [2] = (mantissa >> 16) & 0xFF ; + out [3] = (mantissa >> 8) & 0xFF ; + out [4] = mantissa & 0xFF ; + + in = fmod (in, 1.0) ; + in *= 0x1000000 ; + mantissa = lrint (floor (in)) ; + + out [5] = (mantissa >> 16) & 0xFF ; + out [6] = (mantissa >> 8) & 0xFF ; + out [7] = mantissa & 0xFF ; + + return ; +} /* double64_be_write */ + +void +double64_le_write (double in, unsigned char *out) +{ int exponent, mantissa ; + + memset (out, 0, sizeof (double)) ; + + if (fabs (in) < 1e-30) + return ; + + if (in < 0.0) + { in *= -1.0 ; + out [7] |= 0x80 ; + } ; + + in = frexp (in, &exponent) ; + + exponent += 1022 ; + + out [7] |= (exponent >> 4) & 0x7F ; + out [6] |= (exponent << 4) & 0xF0 ; + + in *= 0x20000000 ; + mantissa = lrint (floor (in)) ; + + out [6] |= (mantissa >> 24) & 0xF ; + out [5] = (mantissa >> 16) & 0xFF ; + out [4] = (mantissa >> 8) & 0xFF ; + out [3] = mantissa & 0xFF ; + + in = fmod (in, 1.0) ; + in *= 0x1000000 ; + mantissa = lrint (floor (in)) ; + + out [2] = (mantissa >> 16) & 0xFF ; + out [1] = (mantissa >> 8) & 0xFF ; + out [0] = mantissa & 0xFF ; + + return ; +} /* double64_le_write */ + +/*============================================================================================== +** Private functions. +*/ + +static void +double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx) +{ int chan ; + int k, position ; + float fmaxval ; + + for (chan = 0 ; chan < psf->sf.channels ; chan++) + { fmaxval = fabs (buffer [chan]) ; + position = 0 ; + for (k = chan ; k < count ; k += psf->sf.channels) + if (fmaxval < fabs (buffer [k])) + { fmaxval = fabs (buffer [k]) ; + position = k ; + } ; + + if (fmaxval > psf->peak_info->peaks [chan].value) + { psf->peak_info->peaks [chan].value = fmaxval ; + psf->peak_info->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ; + } ; + } ; + + return ; +} /* double64_peak_update */ + +static int +double64_get_capability (SF_PRIVATE *psf) +{ union + { double d ; + unsigned char c [8] ; + } data ; + + data.d = 1.234567890123456789 ; /* Some abitrary value. */ + + if (! psf->ieee_replace) + { /* If this test is true ints and floats are compatible and little endian. */ + if (data.c [0] == 0xfb && data.c [1] == 0x59 && data.c [2] == 0x8c && data.c [3] == 0x42 && + data.c [4] == 0xca && data.c [5] == 0xc0 && data.c [6] == 0xf3 && data.c [7] == 0x3f) + return DOUBLE_CAN_RW_LE ; + + /* If this test is true ints and floats are compatible and big endian. */ + if (data.c [0] == 0x3f && data.c [1] == 0xf3 && data.c [2] == 0xc0 && data.c [3] == 0xca && + data.c [4] == 0x42 && data.c [5] == 0x8c && data.c [6] == 0x59 && data.c [7] == 0xfb) + return DOUBLE_CAN_RW_BE ; + } ; + + /* Doubles are broken. Don't expect reading or writing to be fast. */ + psf_log_printf (psf, "Using IEEE replacement code for double.\n") ; + + return (CPU_IS_LITTLE_ENDIAN) ? DOUBLE_BROKEN_LE : DOUBLE_BROKEN_BE ; +} /* double64_get_capability */ + +/*======================================================================================= +*/ + +static inline void +d2s_array (const double *src, int count, short *dest, double scale) +{ while (--count >= 0) + { dest [count] = lrint (scale * src [count]) ; + } ; +} /* d2s_array */ + +static inline void +d2i_array (const double *src, int count, int *dest, double scale) +{ while (--count >= 0) + { dest [count] = lrint (scale * src [count]) ; + } ; +} /* d2i_array */ + +static inline void +d2f_array (const double *src, int count, float *dest) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; +} /* d2f_array */ + +static inline void +s2d_array (const short *src, double *dest, int count) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; +} /* s2d_array */ + +static inline void +i2d_array (const int *src, double *dest, int count) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; +} /* i2d_array */ + +static inline void +f2d_array (const float *src, double *dest, int count) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; +} /* f2d_array */ + +/*---------------------------------------------------------------------------------------------- +*/ + +static sf_count_t +host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double scale ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, readcount) ; + + d2s_array (psf->u.dbuf, readcount, ptr + total, scale) ; + total += readcount ; + len -= readcount ; + if (readcount < bufferlen) + break ; + } ; + + return total ; +} /* host_read_d2s */ + +static sf_count_t +host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double scale ; + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + d2i_array (psf->u.dbuf, readcount, ptr + total, scale) ; + total += readcount ; + len -= readcount ; + if (readcount < bufferlen) + break ; + } ; + + return total ; +} /* host_read_d2i */ + +static sf_count_t +host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + d2f_array (psf->u.dbuf, readcount, ptr + total) ; + total += readcount ; + len -= readcount ; + if (readcount < bufferlen) + break ; + } ; + + return total ; +} /* host_read_d2f */ + +static sf_count_t +host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen ; + sf_count_t readcount, total = 0 ; + + readcount = psf_fread (ptr, sizeof (double), len, psf) ; + + if (psf->float_endswap != SF_TRUE) + return readcount ; + + /* If the read length was sensible, endswap output in one go. */ + if (readcount < SENSIBLE_LEN) + { endswap_double_array (ptr, readcount) ; + return readcount ; + } ; + + bufferlen = SENSIBLE_LEN ; + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + + endswap_double_array (ptr + total, bufferlen) ; + + total += bufferlen ; + len -= bufferlen ; + } ; + + return total ; +} /* host_read_d */ + +static sf_count_t +host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + + s2d_array (ptr + total, psf->u.dbuf, bufferlen) ; + + if (psf->peak_info) + double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_s2d */ + +static sf_count_t +host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2d_array (ptr + total, psf->u.dbuf, bufferlen) ; + + if (psf->peak_info) + double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_i2d */ + +static sf_count_t +host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + f2d_array (ptr + total, psf->u.dbuf, bufferlen) ; + + if (psf->peak_info) + double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_f2d */ + +static sf_count_t +host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + if (psf->peak_info) + double64_peak_update (psf, ptr, len, 0) ; + + if (psf->float_endswap != SF_TRUE) + return psf_fwrite (ptr, sizeof (double), len, psf) ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + + endswap_double_copy (psf->u.dbuf, ptr + total, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_d */ + +/*======================================================================================= +*/ + +static sf_count_t +replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double scale ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + d2bd_read (psf->u.dbuf, bufferlen) ; + + d2s_array (psf->u.dbuf, readcount, ptr + total, scale) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_d2s */ + +static sf_count_t +replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double scale ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + d2bd_read (psf->u.dbuf, bufferlen) ; + + d2i_array (psf->u.dbuf, readcount, ptr + total, scale) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_d2i */ + +static sf_count_t +replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + d2bd_read (psf->u.dbuf, bufferlen) ; + + memcpy (ptr + total, psf->u.dbuf, bufferlen * sizeof (double)) ; + + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_d2f */ + +static sf_count_t +replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + /* FIXME : This is probably nowhere near optimal. */ + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, readcount) ; + + d2bd_read (psf->u.dbuf, readcount) ; + + memcpy (ptr + total, psf->u.dbuf, readcount * sizeof (double)) ; + + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_d */ + +static sf_count_t +replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2d_array (ptr + total, psf->u.dbuf, bufferlen) ; + + if (psf->peak_info) + double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ; + + bd2d_write (psf->u.dbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_s2d */ + +static sf_count_t +replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2d_array (ptr + total, psf->u.dbuf, bufferlen) ; + + if (psf->peak_info) + double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ; + + bd2d_write (psf->u.dbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_i2d */ + +static sf_count_t +replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + f2d_array (ptr + total, psf->u.dbuf, bufferlen) ; + + bd2d_write (psf->u.dbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_f2d */ + +static sf_count_t +replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + /* FIXME : This is probably nowhere near optimal. */ + if (psf->peak_info) + double64_peak_update (psf, ptr, len, 0) ; + + bufferlen = ARRAY_LEN (psf->u.dbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + + memcpy (psf->u.dbuf, ptr + total, bufferlen * sizeof (double)) ; + + bd2d_write (psf->u.dbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_double_array (psf->u.dbuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_d */ + +/*---------------------------------------------------------------------------------------------- +*/ + +static void +d2bd_read (double *buffer, int count) +{ while (--count >= 0) + { buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ; + } ; +} /* d2bd_read */ + +static void +bd2d_write (double *buffer, int count) +{ while (--count >= 0) + { DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; + } ; +} /* bd2d_write */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 4ee243b7-8c7a-469b-869c-e9aa0ee3b77f +*/ diff --git a/nylsf/dwd.c b/nylsf/dwd.c new file mode 100644 index 0000000..a33bae0 --- /dev/null +++ b/nylsf/dwd.c @@ -0,0 +1,210 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#if (ENABLE_EXPERIMENTAL_CODE == 0) + +int +dwd_open (SF_PRIVATE *psf) +{ if (psf) + return SFE_UNIMPLEMENTED ; + return (psf && 0) ; +} /* dwd_open */ + +#else + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define SFE_DWD_NO_DWD 1666 +#define SFE_DWD_BAND_BIT_WIDTH 1667 +#define SFE_DWD_COMPRESSION 1668 + +#define DWD_IDENTIFIER "DiamondWare Digitized\n\0\x1a" +#define DWD_IDENTIFIER_LEN 24 + +#define DWD_HEADER_LEN 57 + +/*------------------------------------------------------------------------------ +** Typedefs. +*/ + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int dwd_read_header (SF_PRIVATE *psf) ; + +static int dwd_close (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +dwd_open (SF_PRIVATE *psf) +{ int subformat, error = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = dwd_read_header (psf))) + return error ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_DWD) + return SFE_BAD_OPEN_FORMAT ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { + /*-psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU) + psf->endian = SF_ENDIAN_LITTLE ; + else if (psf->endian != SF_ENDIAN_LITTLE) + psf->endian = SF_ENDIAN_BIG ; + + if (! (encoding = dwd_write_header (psf, SF_FALSE))) + return psf->error ; + + psf->write_header = dwd_write_header ; + -*/ + } ; + + psf->container_close = dwd_close ; + + /*-psf->blockwidth = psf->bytewidth * psf->sf.channels ;-*/ + + return error ; +} /* dwd_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +dwd_close (SF_PRIVATE *psf) +{ + psf = psf ; + + return 0 ; +} /* dwd_close */ + +/* This struct contains all the fields of interest om the DWD header, but does not +** do so in the same order and layout as the actual file, header. +** No assumptions are made about the packing of this struct. +*/ +typedef struct +{ unsigned char major, minor, compression, channels, bitwidth ; + unsigned short srate, maxval ; + unsigned int id, datalen, frames, offset ; +} DWD_HEADER ; + +static int +dwd_read_header (SF_PRIVATE *psf) +{ DWD_HEADER dwdh ; + + memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ; + /* Set position to start of file to begin reading header. */ + psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, DWD_IDENTIFIER_LEN) ; + + if (memcmp (psf->u.cbuf, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0) + return SFE_DWD_NO_DWD ; + + psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", psf->u.cbuf) ; + + psf_binheader_readf (psf, "11", &dwdh.major, &dwdh.minor) ; + psf_binheader_readf (psf, "e4j1", &dwdh.id, 1, &dwdh.compression) ; + psf_binheader_readf (psf, "e211", &dwdh.srate, &dwdh.channels, &dwdh.bitwidth) ; + psf_binheader_readf (psf, "e24", &dwdh.maxval, &dwdh.datalen) ; + psf_binheader_readf (psf, "e44", &dwdh.frames, &dwdh.offset) ; + + psf_log_printf (psf, " Version Major : %d\n Version Minor : %d\n Unique ID : %08X\n", + dwdh.major, dwdh.minor, dwdh.id) ; + psf_log_printf (psf, " Compression : %d => ", dwdh.compression) ; + + if (dwdh.compression != 0) + { psf_log_printf (psf, "Unsupported compression\n") ; + return SFE_DWD_COMPRESSION ; + } + else + psf_log_printf (psf, "None\n") ; + + psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n" + " Bit Width : %d\n", + dwdh.srate, dwdh.channels, dwdh.bitwidth) ; + + switch (dwdh.bitwidth) + { case 8 : + psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_S8 ; + psf->bytewidth = 1 ; + break ; + + case 16 : + psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + break ; + + default : + psf_log_printf (psf, "*** Bad bit width %d\n", dwdh.bitwidth) ; + return SFE_DWD_BAND_BIT_WIDTH ; + } ; + + if (psf->filelength != dwdh.offset + dwdh.datalen) + { psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ; + dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ; + } + else + psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ; + + psf_log_printf (psf, " Max Value : %d\n", dwdh.maxval) ; + psf_log_printf (psf, " Frames : %d\n", dwdh.frames) ; + psf_log_printf (psf, " Data Offset : %d\n", dwdh.offset) ; + + psf->datalength = dwdh.datalen ; + psf->dataoffset = dwdh.offset ; + + psf->endian = SF_ENDIAN_LITTLE ; + + psf->sf.samplerate = dwdh.srate ; + psf->sf.channels = dwdh.channels ; + psf->sf.sections = 1 ; + + return pcm_init (psf) ; +} /* dwd_read_header */ + +/*------------------------------------------------------------------------------ +*/ + +#endif +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: a5e1d2a6-a840-4039-a0e7-e1a43eb05a4f +*/ diff --git a/nylsf/dwvw.c b/nylsf/dwvw.c new file mode 100644 index 0000000..3e6663f --- /dev/null +++ b/nylsf/dwvw.c @@ -0,0 +1,671 @@ +/* +** Copyright (C) 2002-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/*=========================================================================== +** Delta Word Variable Width +** +** This decoder and encoder were implemented using information found in this +** document : http://home.swbell.net/rubywand/R011SNDFMTS.TXT +** +** According to the document, the algorithm "was invented 1991 by Magnus +** Lidstrom and is copyright 1993 by NuEdge Development". +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" + +typedef struct +{ int dwm_maxsize, bit_width, max_delta, span ; + int samplecount ; + int bit_count, bits, last_delta_width, last_sample ; + struct + { int index, end ; + unsigned char buffer [256] ; + } b ; +} DWVW_PRIVATE ; + +/*============================================================================================ +*/ + +static sf_count_t dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t dwvw_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static sf_count_t dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; +static int dwvw_close (SF_PRIVATE *psf) ; + +static int dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) ; +static int dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) ; + +static int dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, const int *ptr, int len) ; +static void dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits) ; +static void dwvw_read_reset (DWVW_PRIVATE *pdwvw) ; + +/*============================================================================================ +** DWVW initialisation function. +*/ + +int +dwvw_init (SF_PRIVATE *psf, int bitwidth) +{ DWVW_PRIVATE *pdwvw ; + + if (psf->codec_data != NULL) + { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ; + return SFE_INTERNAL ; + } ; + + if (bitwidth > 24) + return SFE_DWVW_BAD_BITWIDTH ; + + if (psf->mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + if ((pdwvw = calloc (1, sizeof (DWVW_PRIVATE))) == NULL) + return SFE_MALLOC_FAILED ; + + psf->codec_data = (void*) pdwvw ; + + pdwvw->bit_width = bitwidth ; + pdwvw->dwm_maxsize = bitwidth / 2 ; + pdwvw->max_delta = 1 << (bitwidth - 1) ; + pdwvw->span = 1 << bitwidth ; + + dwvw_read_reset (pdwvw) ; + + if (psf->mode == SFM_READ) + { psf->read_short = dwvw_read_s ; + psf->read_int = dwvw_read_i ; + psf->read_float = dwvw_read_f ; + psf->read_double = dwvw_read_d ; + } ; + + if (psf->mode == SFM_WRITE) + { psf->write_short = dwvw_write_s ; + psf->write_int = dwvw_write_i ; + psf->write_float = dwvw_write_f ; + psf->write_double = dwvw_write_d ; + } ; + + psf->codec_close = dwvw_close ; + psf->seek = dwvw_seek ; + + /* FIXME : This is bogus. */ + psf->sf.frames = SF_COUNT_MAX ; + psf->datalength = psf->sf.frames ; + /* EMXIF : This is bogus. */ + + return 0 ; +} /* dwvw_init */ + +/*-------------------------------------------------------------------------------------------- +*/ + +static int +dwvw_close (SF_PRIVATE *psf) +{ DWVW_PRIVATE *pdwvw ; + + if (psf->codec_data == NULL) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + if (psf->mode == SFM_WRITE) + { static int last_values [12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ; + + /* Write 8 zero samples to fully flush output. */ + dwvw_encode_data (psf, pdwvw, last_values, 12) ; + + /* Write the last buffer worth of data to disk. */ + psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ; + + if (psf->write_header) + psf->write_header (psf, SF_TRUE) ; + } ; + + return 0 ; +} /* dwvw_close */ + +static sf_count_t +dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ DWVW_PRIVATE *pdwvw ; + + mode = mode ; + + if (! psf->codec_data) + { psf->error = SFE_INTERNAL ; + return PSF_SEEK_ERROR ; + } ; + + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + if (offset == 0) + { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + dwvw_read_reset (pdwvw) ; + return 0 ; + } ; + + psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; +} /* dwvw_seek */ + + +/*============================================================================== +*/ + +static sf_count_t +dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int *iptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = iptr [k] >> 16 ; + + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* dwvw_read_s */ + +static sf_count_t +dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int readcount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + while (len > 0) + { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = dwvw_decode_data (psf, pdwvw, ptr, readcount) ; + + total += count ; + len -= count ; + + if (count != readcount) + break ; + } ; + + return total ; +} /* dwvw_read_i */ + +static sf_count_t +dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int *iptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (float) (iptr [k]) ; + + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* dwvw_read_f */ + +static sf_count_t +dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int *iptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (double) (iptr [k]) ; + + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* dwvw_read_d */ + +static int +dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) +{ int count ; + int delta_width_modifier, delta_width, delta_negative, delta, sample ; + + /* Restore state from last decode call. */ + delta_width = pdwvw->last_delta_width ; + sample = pdwvw->last_sample ; + + for (count = 0 ; count < len ; count++) + { /* If bit_count parameter is zero get the delta_width_modifier. */ + delta_width_modifier = dwvw_decode_load_bits (psf, pdwvw, -1) ; + + /* Check for end of input bit stream. Break loop if end. */ + if (delta_width_modifier < 0) + break ; + + if (delta_width_modifier && dwvw_decode_load_bits (psf, pdwvw, 1)) + delta_width_modifier = - delta_width_modifier ; + + /* Calculate the current word width. */ + delta_width = (delta_width + delta_width_modifier + pdwvw->bit_width) % pdwvw->bit_width ; + + /* Load the delta. */ + delta = 0 ; + if (delta_width) + { delta = dwvw_decode_load_bits (psf, pdwvw, delta_width - 1) | (1 << (delta_width - 1)) ; + delta_negative = dwvw_decode_load_bits (psf, pdwvw, 1) ; + if (delta == pdwvw->max_delta - 1) + delta += dwvw_decode_load_bits (psf, pdwvw, 1) ; + if (delta_negative) + delta = -delta ; + } ; + + /* Calculate the sample */ + sample += delta ; + + if (sample >= pdwvw->max_delta) + sample -= pdwvw->span ; + else if (sample < - pdwvw->max_delta) + sample += pdwvw->span ; + + /* Store the sample justifying to the most significant bit. */ + ptr [count] = sample << (32 - pdwvw->bit_width) ; + + if (pdwvw->b.end == 0 && pdwvw->bit_count == 0) + break ; + } ; + + pdwvw->last_delta_width = delta_width ; + pdwvw->last_sample = sample ; + + pdwvw->samplecount += count ; + + return count ; +} /* dwvw_decode_data */ + +static int +dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) +{ int output = 0, get_dwm = SF_FALSE ; + + /* + ** Depending on the value of parameter bit_count, either get the + ** required number of bits (ie bit_count > 0) or the + ** delta_width_modifier (otherwise). + */ + + if (bit_count < 0) + { get_dwm = SF_TRUE ; + /* modify bit_count to ensure we have enought bits for finding dwm. */ + bit_count = pdwvw->dwm_maxsize ; + } ; + + /* Load bits in bit reseviour. */ + while (pdwvw->bit_count < bit_count) + { if (pdwvw->b.index >= pdwvw->b.end) + { pdwvw->b.end = psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ; + pdwvw->b.index = 0 ; + } ; + + /* Check for end of input stream. */ + if (bit_count < 8 && pdwvw->b.end == 0) + return -1 ; + + pdwvw->bits = (pdwvw->bits << 8) ; + + if (pdwvw->b.index < pdwvw->b.end) + { pdwvw->bits |= pdwvw->b.buffer [pdwvw->b.index] ; + pdwvw->b.index ++ ; + } ; + pdwvw->bit_count += 8 ; + } ; + + /* If asked to get bits do so. */ + if (! get_dwm) + { output = (pdwvw->bits >> (pdwvw->bit_count - bit_count)) & ((1 << bit_count) - 1) ; + pdwvw->bit_count -= bit_count ; + return output ; + } ; + + /* Otherwise must have been asked to get delta_width_modifier. */ + while (output < (pdwvw->dwm_maxsize)) + { pdwvw->bit_count -= 1 ; + if (pdwvw->bits & (1 << pdwvw->bit_count)) + break ; + output += 1 ; + } ; + + return output ; +} /* dwvw_decode_load_bits */ + +static void +dwvw_read_reset (DWVW_PRIVATE *pdwvw) +{ pdwvw->samplecount = 0 ; + pdwvw->b.index = 0 ; + pdwvw->b.end = 0 ; + pdwvw->bit_count = 0 ; + pdwvw->bits = 0 ; + pdwvw->last_delta_width = 0 ; + pdwvw->last_sample = 0 ; +} /* dwvw_read_reset */ + +static void +dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits) +{ int byte ; + + /* Shift the bits into the resevoir. */ + pdwvw->bits = (pdwvw->bits << new_bits) | (data & ((1 << new_bits) - 1)) ; + pdwvw->bit_count += new_bits ; + + /* Transfer bit to buffer. */ + while (pdwvw->bit_count >= 8) + { byte = pdwvw->bits >> (pdwvw->bit_count - 8) ; + pdwvw->bit_count -= 8 ; + pdwvw->b.buffer [pdwvw->b.index] = byte & 0xFF ; + pdwvw->b.index ++ ; + } ; + + if (pdwvw->b.index > SIGNED_SIZEOF (pdwvw->b.buffer) - 4) + { psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ; + pdwvw->b.index = 0 ; + } ; + + return ; +} /* dwvw_encode_store_bits */ + +#if 0 +/* Debigging routine. */ +static void +dump_bits (DWVW_PRIVATE *pdwvw) +{ int k, mask ; + + for (k = 0 ; k < 10 && k < pdwvw->b.index ; k++) + { mask = 0x80 ; + while (mask) + { putchar (mask & pdwvw->b.buffer [k] ? '1' : '0') ; + mask >>= 1 ; + } ; + putchar (' ') ; + } + + for (k = pdwvw->bit_count - 1 ; k >= 0 ; k --) + putchar (pdwvw->bits & (1 << k) ? '1' : '0') ; + + putchar ('\n') ; +} /* dump_bits */ +#endif + +#define HIGHEST_BIT(x,count) \ + { int y = x ; \ + (count) = 0 ; \ + while (y) \ + { (count) ++ ; \ + y >>= 1 ; \ + } ; \ + } ; + +static int +dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, const int *ptr, int len) +{ int count ; + int delta_width_modifier, delta, delta_negative, delta_width, extra_bit ; + + for (count = 0 ; count < len ; count++) + { delta = (ptr [count] >> (32 - pdwvw->bit_width)) - pdwvw->last_sample ; + + /* Calculate extra_bit if needed. */ + extra_bit = -1 ; + delta_negative = 0 ; + if (delta < -pdwvw->max_delta) + delta = pdwvw->max_delta + (delta % pdwvw->max_delta) ; + else if (delta == -pdwvw->max_delta) + { extra_bit = 1 ; + delta_negative = 1 ; + delta = pdwvw->max_delta - 1 ; + } + else if (delta > pdwvw->max_delta) + { delta_negative = 1 ; + delta = pdwvw->span - delta ; + delta = abs (delta) ; + } + else if (delta == pdwvw->max_delta) + { extra_bit = 1 ; + delta = pdwvw->max_delta - 1 ; + } + else if (delta < 0) + { delta_negative = 1 ; + delta = abs (delta) ; + } ; + + if (delta == pdwvw->max_delta - 1 && extra_bit == -1) + extra_bit = 0 ; + + /* Find width in bits of delta */ + HIGHEST_BIT (delta, delta_width) ; + + /* Calculate the delta_width_modifier */ + delta_width_modifier = (delta_width - pdwvw->last_delta_width) % pdwvw->bit_width ; + if (delta_width_modifier > pdwvw->dwm_maxsize) + delta_width_modifier -= pdwvw->bit_width ; + if (delta_width_modifier < -pdwvw->dwm_maxsize) + delta_width_modifier += pdwvw->bit_width ; + + /* Write delta_width_modifier zeros, followed by terminating '1'. */ + dwvw_encode_store_bits (psf, pdwvw, 0, abs (delta_width_modifier)) ; + if (abs (delta_width_modifier) != pdwvw->dwm_maxsize) + dwvw_encode_store_bits (psf, pdwvw, 1, 1) ; + + /* Write delta_width_modifier sign. */ + if (delta_width_modifier < 0) + dwvw_encode_store_bits (psf, pdwvw, 1, 1) ; + if (delta_width_modifier > 0) + dwvw_encode_store_bits (psf, pdwvw, 0, 1) ; + + /* Write delta and delta sign bit. */ + if (delta_width) + { dwvw_encode_store_bits (psf, pdwvw, delta, abs (delta_width) - 1) ; + dwvw_encode_store_bits (psf, pdwvw, (delta_negative ? 1 : 0), 1) ; + } ; + + /* Write extra bit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + if (extra_bit >= 0) + dwvw_encode_store_bits (psf, pdwvw, extra_bit, 1) ; + + pdwvw->last_sample = ptr [count] >> (32 - pdwvw->bit_width) ; + pdwvw->last_delta_width = delta_width ; + } ; + + pdwvw->samplecount += count ; + + return count ; +} /* dwvw_encode_data */ + +static sf_count_t +dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int *iptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = ptr [total + k] << 16 ; + count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; + + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* dwvw_write_s */ + +static sf_count_t +dwvw_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int writecount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + while (len > 0) + { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = dwvw_encode_data (psf, pdwvw, ptr, writecount) ; + + total += count ; + len -= count ; + + if (count != writecount) + break ; + } ; + + return total ; +} /* dwvw_write_i */ + +static sf_count_t +dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int *iptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = lrintf (normfact * ptr [total + k]) ; + count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; + + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* dwvw_write_f */ + +static sf_count_t +dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ DWVW_PRIVATE *pdwvw ; + int *iptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + if (! psf->codec_data) + return 0 ; + pdwvw = (DWVW_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = lrint (normfact * ptr [total + k]) ; + count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; + + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* dwvw_write_d */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 1ca09552-b01f-4d7f-9bcf-612f834fe41d +*/ diff --git a/nylsf/file_io.c b/nylsf/file_io.c new file mode 100644 index 0000000..af5ccd6 --- /dev/null +++ b/nylsf/file_io.c @@ -0,0 +1,1537 @@ +/* +** Copyright (C) 2002-2005 Erik de Castro Lopo +** Copyright (C) 2003 Ross Bencina +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** The file is split into three sections as follows: +** - The top section (USE_WINDOWS_API == 0) for Linux, Unix and MacOSX +** systems (including Cygwin). +** - The middle section (USE_WINDOWS_API == 1) for microsoft windows +** (including MinGW) using the native windows API. +** - A legacy windows section which attempted to work around grevious +** bugs in microsoft's POSIX implementation. +*/ + +/* +** The header file sfconfig.h MUST be included before the others to ensure +** that large file support is enabled correctly on Unix systems. +*/ + +#include "sfconfig.h" + +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#if (HAVE_DECL_S_IRGRP == 0) +#include +#endif + +#include +#include +#include +#include + +#include "sndfile.h" +#include "common.h" + +#define SENSIBLE_SIZE (0x40000000) + +static void psf_log_syserr (SF_PRIVATE *psf, int error) ; + +#if (USE_WINDOWS_API == 0) + +/*------------------------------------------------------------------------------ +** Win32 stuff at the bottom of the file. Unix and other sensible OSes here. +*/ + +static int psf_close_fd (int fd) ; +static int psf_open_fd (const char * path, int mode) ; +static sf_count_t psf_get_filelen_fd (int fd) ; + +int +psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) +{ + psf->error = 0 ; + psf->filedes = psf_open_fd (pathname, open_mode) ; + + if (psf->filedes == - SFE_BAD_OPEN_MODE) + { psf->error = SFE_BAD_OPEN_MODE ; + psf->filedes = -1 ; + return psf->error ; + } ; + + if (psf->filedes == -1) + psf_log_syserr (psf, errno) ; + + psf->mode = open_mode ; + + return psf->error ; +} /* psf_fopen */ + +int +psf_fclose (SF_PRIVATE *psf) +{ int retval ; + + if (psf->virtual_io) + return 0 ; + + if (psf->do_not_close_descriptor) + { psf->filedes = -1 ; + return 0 ; + } ; + + if ((retval = psf_close_fd (psf->filedes)) == -1) + psf_log_syserr (psf, errno) ; + + psf->filedes = -1 ; + + return retval ; +} /* psf_fclose */ + +int +psf_open_rsrc (SF_PRIVATE *psf, int open_mode) +{ + if (psf->rsrcdes > 0) + return 0 ; + + /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ + LSF_SNPRINTF (psf->rsrcpath, sizeof (psf->rsrcpath), "%s/rsrc", psf->filepath) ; + psf->error = SFE_NO_ERROR ; + if ((psf->rsrcdes = psf_open_fd (psf->rsrcpath, open_mode)) >= 0) + { psf->rsrclength = psf_get_filelen_fd (psf->rsrcdes) ; + if (psf->rsrclength > 0 || (open_mode & SFM_WRITE)) + return SFE_NO_ERROR ; + psf_close_fd (psf->rsrcdes) ; + psf->rsrcdes = -1 ; + } ; + + if (psf->rsrcdes == - SFE_BAD_OPEN_MODE) + { psf->error = SFE_BAD_OPEN_MODE ; + return psf->error ; + } ; + + /* + ** Now try for a resource fork stored as a separate file in the same + ** directory, but preceded with a dot underscore. + */ + LSF_SNPRINTF (psf->rsrcpath, sizeof (psf->rsrcpath), "%s._%s", psf->directory, psf->filename) ; + psf->error = SFE_NO_ERROR ; + if ((psf->rsrcdes = psf_open_fd (psf->rsrcpath, open_mode)) >= 0) + { psf->rsrclength = psf_get_filelen_fd (psf->rsrcdes) ; + return SFE_NO_ERROR ; + } ; + + /* + ** Now try for a resource fork stored in a separate file in the + ** .AppleDouble/ directory. + */ + LSF_SNPRINTF (psf->rsrcpath, sizeof (psf->rsrcpath), "%s.AppleDouble/%s", psf->directory, psf->filename) ; + psf->error = SFE_NO_ERROR ; + if ((psf->rsrcdes = psf_open_fd (psf->rsrcpath, open_mode)) >= 0) + { psf->rsrclength = psf_get_filelen_fd (psf->rsrcdes) ; + return SFE_NO_ERROR ; + } ; + + /* No resource file found. */ + if (psf->rsrcdes == -1) + psf_log_syserr (psf, errno) ; + + psf->rsrcdes = -1 ; + + return psf->error ; +} /* psf_open_rsrc */ + +sf_count_t +psf_get_filelen (SF_PRIVATE *psf) +{ sf_count_t filelen ; + + if (psf->virtual_io) + return psf->vio.get_filelen (psf->vio_user_data) ; + + filelen = psf_get_filelen_fd (psf->filedes) ; + + if (filelen == -1) + { psf_log_syserr (psf, errno) ; + return (sf_count_t) -1 ; + } ; + + if (filelen == -SFE_BAD_STAT_SIZE) + { psf->error = SFE_BAD_STAT_SIZE ; + return (sf_count_t) -1 ; + } ; + + switch (psf->mode) + { case SFM_WRITE : + filelen = filelen - psf->fileoffset ; + break ; + + case SFM_READ : + if (psf->fileoffset > 0 && psf->filelength > 0) + filelen = psf->filelength ; + break ; + + case SFM_RDWR : + /* + ** Cannot open embedded files SFM_RDWR so we don't need to + ** subtract psf->fileoffset. We already have the answer we + ** need. + */ + break ; + + default : + /* Shouldn't be here, so return error. */ + filelen = -1 ; + } ; + + return filelen ; +} /* psf_get_filelen */ + +int +psf_close_rsrc (SF_PRIVATE *psf) +{ + if (psf->rsrcdes >= 0) + psf_close_fd (psf->rsrcdes) ; + psf->rsrcdes = -1 ; + return 0 ; +} /* psf_close_rsrc */ + +int +psf_set_stdio (SF_PRIVATE *psf, int mode) +{ int error = 0 ; + + switch (mode) + { case SFM_RDWR : + error = SFE_OPEN_PIPE_RDWR ; + break ; + + case SFM_READ : + psf->filedes = 0 ; + break ; + + case SFM_WRITE : + psf->filedes = 1 ; + break ; + + default : + error = SFE_BAD_OPEN_MODE ; + break ; + } ; + psf->filelength = 0 ; + + return error ; +} /* psf_set_stdio */ + +void +psf_set_file (SF_PRIVATE *psf, int fd) +{ psf->filedes = fd ; +} /* psf_set_file */ + +int +psf_file_valid (SF_PRIVATE *psf) +{ return (psf->filedes >= 0) ? SF_TRUE : SF_FALSE ; +} /* psf_set_file */ + +sf_count_t +psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) +{ sf_count_t new_position ; + + if (psf->virtual_io) + return psf->vio.seek (offset, whence, psf->vio_user_data) ; + + switch (whence) + { case SEEK_SET : + offset += psf->fileoffset ; + break ; + + case SEEK_END : + if (psf->mode == SFM_WRITE) + { new_position = lseek (psf->filedes, offset, whence) ; + + if (new_position < 0) + psf_log_syserr (psf, errno) ; + + return new_position - psf->fileoffset ; + } ; + + /* Transform SEEK_END into a SEEK_SET, ie find the file + ** length add the requested offset (should be <= 0) to + ** get the offset wrt the start of file. + */ + whence = SEEK_SET ; + offset = lseek (psf->filedes, 0, SEEK_END) + offset ; + break ; + + default : + /* No need to do anything about SEEK_CUR. */ + break ; + } ; + + new_position = lseek (psf->filedes, offset, whence) ; + + if (new_position < 0) + psf_log_syserr (psf, errno) ; + + new_position -= psf->fileoffset ; + + return new_position ; +} /* psf_fseek */ + +sf_count_t +psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) +{ sf_count_t total = 0 ; + ssize_t count ; + + if (psf->virtual_io) + return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ; + + items *= bytes ; + + /* Do this check after the multiplication above. */ + if (items <= 0) + return 0 ; + + while (items > 0) + { /* Break the read down to a sensible size. */ + count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; + + count = read (psf->filedes, ((char*) ptr) + total, (size_t) count) ; + + if (count == -1) + { if (errno == EINTR) + continue ; + + psf_log_syserr (psf, errno) ; + break ; + } ; + + if (count == 0) + break ; + + total += count ; + items -= count ; + } ; + + if (psf->is_pipe) + psf->pipeoffset += total ; + + return total / bytes ; +} /* psf_fread */ + +sf_count_t +psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) +{ sf_count_t total = 0 ; + ssize_t count ; + + if (psf->virtual_io) + return psf->vio.write (ptr, bytes*items, psf->vio_user_data) / bytes ; + + items *= bytes ; + + /* Do this check after the multiplication above. */ + if (items <= 0) + return 0 ; + + while (items > 0) + { /* Break the writes down to a sensible size. */ + count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ; + + count = write (psf->filedes, ((const char*) ptr) + total, count) ; + + if (count == -1) + { if (errno == EINTR) + continue ; + + psf_log_syserr (psf, errno) ; + break ; + } ; + + if (count == 0) + break ; + + total += count ; + items -= count ; + } ; + + if (psf->is_pipe) + psf->pipeoffset += total ; + + return total / bytes ; +} /* psf_fwrite */ + +sf_count_t +psf_ftell (SF_PRIVATE *psf) +{ sf_count_t pos ; + + if (psf->virtual_io) + return psf->vio.tell (psf->vio_user_data) ; + + if (psf->is_pipe) + return psf->pipeoffset ; + + pos = lseek (psf->filedes, 0, SEEK_CUR) ; + + if (pos == ((sf_count_t) -1)) + { psf_log_syserr (psf, errno) ; + return -1 ; + } ; + + return pos - psf->fileoffset ; +} /* psf_ftell */ + +static int +psf_close_fd (int fd) +{ int retval ; + + while ((retval = close (fd)) == -1 && errno == EINTR) + /* Do nothing. */ ; + + return retval ; +} /* psf_close_fd */ + +sf_count_t +psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) +{ sf_count_t k = 0 ; + sf_count_t count ; + + while (k < bufsize - 1) + { count = read (psf->filedes, &(buffer [k]), 1) ; + + if (count == -1) + { if (errno == EINTR) + continue ; + + psf_log_syserr (psf, errno) ; + break ; + } ; + + if (count == 0 || buffer [k++] == '\n') + break ; + } ; + + buffer [k] = 0 ; + + return k ; +} /* psf_fgets */ + +int +psf_is_pipe (SF_PRIVATE *psf) +{ struct stat statbuf ; + + if (psf->virtual_io) + return SF_FALSE ; + + if (fstat (psf->filedes, &statbuf) == -1) + { psf_log_syserr (psf, errno) ; + /* Default to maximum safety. */ + return SF_TRUE ; + } ; + + if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode)) + return SF_TRUE ; + + return SF_FALSE ; +} /* psf_is_pipe */ + +static sf_count_t +psf_get_filelen_fd (int fd) +{ struct stat statbuf ; + + /* + ** Sanity check. + ** If everything is OK, this will be optimised out. + */ + if (sizeof (statbuf.st_size) == 4 && sizeof (sf_count_t) == 8) + return (sf_count_t) -SFE_BAD_STAT_SIZE ; + + if (fstat (fd, &statbuf) == -1) + return (sf_count_t) -1 ; + + return statbuf.st_size ; +} /* psf_get_filelen_fd */ + +int +psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) +{ int retval ; + + /* Returns 0 on success, non-zero on failure. */ + if (len < 0) + return -1 ; + + if ((sizeof (off_t) < sizeof (sf_count_t)) && len > 0x7FFFFFFF) + return -1 ; + + retval = ftruncate (psf->filedes, len) ; + + if (retval == -1) + psf_log_syserr (psf, errno) ; + + return retval ; +} /* psf_ftruncate */ + +void +psf_init_files (SF_PRIVATE *psf) +{ psf->filedes = -1 ; + psf->rsrcdes = -1 ; + psf->savedes = -1 ; +} /* psf_init_files */ + +void +psf_use_rsrc (SF_PRIVATE *psf, int on_off) +{ + if (on_off) + { if (psf->filedes != psf->rsrcdes) + { psf->savedes = psf->filedes ; + psf->filedes = psf->rsrcdes ; + } ; + } + else if (psf->filedes == psf->rsrcdes) + psf->filedes = psf->savedes ; + + return ; +} /* psf_use_rsrc */ + +static int +psf_open_fd (const char * pathname, int open_mode) +{ int fd, oflag, mode ; + + /* + ** Sanity check. If everything is OK, this test and the printfs will + ** be optimised out. This is meant to catch the problems caused by + ** "sfconfig.h" being included after . + */ + if (sizeof (off_t) != sizeof (sf_count_t)) + { puts ("\n\n*** Fatal error : sizeof (off_t) != sizeof (sf_count_t)") ; + puts ("*** This means that libsndfile was not configured correctly.\n") ; + exit (1) ; + } ; + + switch (open_mode) + { case SFM_READ : + oflag = O_RDONLY ; + mode = 0 ; + break ; + + case SFM_WRITE : + oflag = O_WRONLY | O_CREAT | O_TRUNC ; + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ; + break ; + + case SFM_RDWR : + oflag = O_RDWR | O_CREAT ; + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ; + break ; + + default : + return - SFE_BAD_OPEN_MODE ; + break ; + } ; + +#if OS_IS_WIN32 + /* For Cygwin. */ + oflag |= O_BINARY ; +#endif + + if (mode == 0) + fd = open (pathname, oflag) ; + else + fd = open (pathname, oflag, mode) ; + + return fd ; +} /* psf_open_fd */ + +static void +psf_log_syserr (SF_PRIVATE *psf, int error) +{ + /* Only log an error if no error has been set yet. */ + if (psf->error == 0) + { psf->error = SFE_SYSTEM ; + LSF_SNPRINTF (psf->syserr, sizeof (psf->syserr), "System error : %s.", strerror (error)) ; + } ; + + return ; +} /* psf_log_syserr */ + +void +psf_fsync (SF_PRIVATE *psf) +{ +#if HAVE_FSYNC + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + fsync (psf->filedes) ; +#else + psf = NULL ; +#endif +} /* psf_fsync */ + +#elif USE_WINDOWS_API + +/* Win32 file i/o functions implemented using native Win32 API */ + +#include +#include + +#ifndef HAVE_SSIZE_T +typedef long ssize_t ; +#endif + +static int psf_close_handle (HANDLE handle) ; +static HANDLE psf_open_handle (const char * path, int mode) ; +static sf_count_t psf_get_filelen_handle (HANDLE handle) ; + +/* USE_WINDOWS_API */ int +psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) +{ + psf->error = 0 ; + psf->hfile = psf_open_handle (pathname, open_mode) ; + + if (psf->hfile == NULL) + psf_log_syserr (psf, GetLastError()) ; + + psf->mode = open_mode ; + + return psf->error ; +} /* psf_fopen */ + +/* USE_WINDOWS_API */ int +psf_fclose (SF_PRIVATE *psf) +{ int retval ; + + if (psf->virtual_io) + return 0 ; + + if (psf->do_not_close_descriptor) + { psf->hfile = NULL ; + return 0 ; + } ; + + if ((retval = psf_close_handle (psf->hfile)) == -1) + psf_log_syserr (psf, GetLastError ()) ; + + psf->hfile = NULL ; + + return retval ; +} /* psf_fclose */ + +/* USE_WINDOWS_API */ int +psf_open_rsrc (SF_PRIVATE *psf, int open_mode) +{ + if (psf->hrsrc != NULL) + return 0 ; + + /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ + LSF_SNPRINTF (psf->rsrcpath, sizeof (psf->rsrcpath), "%s/rsrc", psf->filepath) ; + psf->error = SFE_NO_ERROR ; + if ((psf->hrsrc = psf_open_handle (psf->rsrcpath, open_mode)) != NULL) + { psf->rsrclength = psf_get_filelen_handle (psf->hrsrc) ; + return SFE_NO_ERROR ; + } ; + + /* + ** Now try for a resource fork stored as a separate file in the same + ** directory, but preceded with a dot underscore. + */ + LSF_SNPRINTF (psf->rsrcpath, sizeof (psf->rsrcpath), "%s._%s", psf->directory, psf->filename) ; + psf->error = SFE_NO_ERROR ; + if ((psf->hrsrc = psf_open_handle (psf->rsrcpath, open_mode)) != NULL) + { psf->rsrclength = psf_get_filelen_handle (psf->hrsrc) ; + return SFE_NO_ERROR ; + } ; + + /* + ** Now try for a resource fork stored in a separate file in the + ** .AppleDouble/ directory. + */ + LSF_SNPRINTF (psf->rsrcpath, sizeof (psf->rsrcpath), "%s.AppleDouble/%s", psf->directory, psf->filename) ; + psf->error = SFE_NO_ERROR ; + if ((psf->hrsrc = psf_open_handle (psf->rsrcpath, open_mode)) != NULL) + { psf->rsrclength = psf_get_filelen_handle (psf->hrsrc) ; + return SFE_NO_ERROR ; + } ; + + /* No resource file found. */ + if (psf->hrsrc == NULL) + psf_log_syserr (psf, GetLastError ()) ; + + psf->hrsrc = NULL ; + + return psf->error ; +} /* psf_open_rsrc */ + +/* USE_WINDOWS_API */ sf_count_t +psf_get_filelen (SF_PRIVATE *psf) +{ sf_count_t filelen ; + + if (psf->virtual_io) + return psf->vio.get_filelen (psf->vio_user_data) ; + + filelen = psf_get_filelen_handle (psf->hfile) ; + + if (filelen == -1) + { psf_log_syserr (psf, errno) ; + return (sf_count_t) -1 ; + } ; + + if (filelen == -SFE_BAD_STAT_SIZE) + { psf->error = SFE_BAD_STAT_SIZE ; + return (sf_count_t) -1 ; + } ; + + switch (psf->mode) + { case SFM_WRITE : + filelen = filelen - psf->fileoffset ; + break ; + + case SFM_READ : + if (psf->fileoffset > 0 && psf->filelength > 0) + filelen = psf->filelength ; + break ; + + case SFM_RDWR : + /* + ** Cannot open embedded files SFM_RDWR so we don't need to + ** subtract psf->fileoffset. We already have the answer we + ** need. + */ + break ; + + default : + /* Shouldn't be here, so return error. */ + filelen = -1 ; + } ; + + return filelen ; +} /* psf_get_filelen */ + +/* USE_WINDOWS_API */ void +psf_init_files (SF_PRIVATE *psf) +{ psf->hfile = NULL ; + psf->hrsrc = NULL ; + psf->hsaved = NULL ; +} /* psf_init_files */ + +/* USE_WINDOWS_API */ void +psf_use_rsrc (SF_PRIVATE *psf, int on_off) +{ + if (on_off) + { if (psf->hfile != psf->hrsrc) + { psf->hsaved = psf->hfile ; + psf->hfile = psf->hrsrc ; + } ; + } + else if (psf->hfile == psf->hrsrc) + psf->hfile = psf->hsaved ; + + return ; +} /* psf_use_rsrc */ + +/* USE_WINDOWS_API */ static HANDLE +psf_open_handle (const char * pathname, int open_mode) +{ DWORD dwDesiredAccess ; + DWORD dwShareMode ; + DWORD dwCreationDistribution ; + HANDLE handle ; + + switch (open_mode) + { case SFM_READ : + dwDesiredAccess = GENERIC_READ ; + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ; + dwCreationDistribution = OPEN_EXISTING ; + break ; + + case SFM_WRITE : + dwDesiredAccess = GENERIC_WRITE ; + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ; + dwCreationDistribution = CREATE_ALWAYS ; + break ; + + case SFM_RDWR : + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE ; + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ; + dwCreationDistribution = OPEN_ALWAYS ; + break ; + + default : + return NULL ; + } ; + + handle = CreateFile ( + pathname, /* pointer to name of the file */ + dwDesiredAccess, /* access (read-write) mode */ + dwShareMode, /* share mode */ + 0, /* pointer to security attributes */ + dwCreationDistribution, /* how to create */ + FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ + NULL /* handle to file with attributes to copy */ + ) ; + + if (handle == INVALID_HANDLE_VALUE) + return NULL ; + + return handle ; +} /* psf_open_handle */ + +/* USE_WINDOWS_API */ static void +psf_log_syserr (SF_PRIVATE *psf, int error) +{ LPVOID lpMsgBuf ; + + /* Only log an error if no error has been set yet. */ + if (psf->error == 0) + { psf->error = SFE_SYSTEM ; + + FormatMessage ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + error, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL + ) ; + + LSF_SNPRINTF (psf->syserr, sizeof (psf->syserr), "System error : %s", lpMsgBuf) ; + LocalFree (lpMsgBuf) ; + } ; + + return ; +} /* psf_log_syserr */ + + +/* USE_WINDOWS_API */ int +psf_close_rsrc (SF_PRIVATE *psf) +{ + if (psf->hrsrc != NULL) + psf_close_handle (psf->hrsrc) ; + psf->hrsrc = NULL ; + return 0 ; +} /* psf_close_rsrc */ + + +/* USE_WINDOWS_API */ int +psf_set_stdio (SF_PRIVATE *psf, int mode) +{ HANDLE handle = NULL ; + int error = 0 ; + + switch (mode) + { case SFM_RDWR : + error = SFE_OPEN_PIPE_RDWR ; + break ; + + case SFM_READ : + handle = GetStdHandle (STD_INPUT_HANDLE) ; + psf->do_not_close_descriptor = 1 ; + break ; + + case SFM_WRITE : + handle = GetStdHandle (STD_OUTPUT_HANDLE) ; + psf->do_not_close_descriptor = 1 ; + break ; + + default : + error = SFE_BAD_OPEN_MODE ; + break ; + } ; + + psf->hfile = handle ; + psf->filelength = 0 ; + + return error ; +} /* psf_set_stdio */ + +/* USE_WINDOWS_API */ void +psf_set_file (SF_PRIVATE *psf, int fd) +{ HANDLE handle ; + long osfhandle ; + + osfhandle = _get_osfhandle (fd) ; + handle = (HANDLE) osfhandle ; + + psf->hfile = handle ; +} /* psf_set_file */ + +/* USE_WINDOWS_API */ int +psf_file_valid (SF_PRIVATE *psf) +{ if (psf->hfile == NULL) + return SF_FALSE ; + if (psf->hfile == INVALID_HANDLE_VALUE) + return SF_FALSE ; + return SF_TRUE ; +} /* psf_set_file */ + +/* USE_WINDOWS_API */ sf_count_t +psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) +{ sf_count_t new_position ; + LONG lDistanceToMove, lDistanceToMoveHigh ; + DWORD dwMoveMethod ; + DWORD dwResult, dwError ; + + if (psf->virtual_io) + return psf->vio.seek (offset, whence, psf->vio_user_data) ; + + switch (whence) + { case SEEK_SET : + offset += psf->fileoffset ; + dwMoveMethod = FILE_BEGIN ; + break ; + + case SEEK_END : + dwMoveMethod = FILE_END ; + break ; + + default : + dwMoveMethod = FILE_CURRENT ; + break ; + } ; + + lDistanceToMove = (DWORD) (offset & 0xFFFFFFFF) ; + lDistanceToMoveHigh = (DWORD) ((offset >> 32) & 0xFFFFFFFF) ; + + dwResult = SetFilePointer (psf->hfile, lDistanceToMove, &lDistanceToMoveHigh, dwMoveMethod) ; + + if (dwResult == 0xFFFFFFFF) + dwError = GetLastError () ; + else + dwError = NO_ERROR ; + + if (dwError != NO_ERROR) + { psf_log_syserr (psf, dwError) ; + return -1 ; + } ; + + new_position = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) - psf->fileoffset ; + + return new_position ; +} /* psf_fseek */ + +/* USE_WINDOWS_API */ sf_count_t +psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) +{ sf_count_t total = 0 ; + ssize_t count ; + DWORD dwNumberOfBytesRead ; + + if (psf->virtual_io) + return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ; + + items *= bytes ; + + /* Do this check after the multiplication above. */ + if (items <= 0) + return 0 ; + + while (items > 0) + { /* Break the writes down to a sensible size. */ + count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; + + if (ReadFile (psf->hfile, ((char*) ptr) + total, count, &dwNumberOfBytesRead, 0) == 0) + { psf_log_syserr (psf, GetLastError ()) ; + break ; + } + else + count = dwNumberOfBytesRead ; + + if (count == 0) + break ; + + total += count ; + items -= count ; + } ; + + if (psf->is_pipe) + psf->pipeoffset += total ; + + return total / bytes ; +} /* psf_fread */ + +/* USE_WINDOWS_API */ sf_count_t +psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) +{ sf_count_t total = 0 ; + ssize_t count ; + DWORD dwNumberOfBytesWritten ; + + if (psf->virtual_io) + return psf->vio.write (ptr, bytes * items, psf->vio_user_data) / bytes ; + + items *= bytes ; + + /* Do this check after the multiplication above. */ + if (items <= 0) + return 0 ; + + while (items > 0) + { /* Break the writes down to a sensible size. */ + count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; + + if (WriteFile (psf->hfile, ((const char*) ptr) + total, count, &dwNumberOfBytesWritten, 0) == 0) + { psf_log_syserr (psf, GetLastError ()) ; + break ; + } + else + count = dwNumberOfBytesWritten ; + + if (count == 0) + break ; + + total += count ; + items -= count ; + } ; + + if (psf->is_pipe) + psf->pipeoffset += total ; + + return total / bytes ; +} /* psf_fwrite */ + +/* USE_WINDOWS_API */ sf_count_t +psf_ftell (SF_PRIVATE *psf) +{ sf_count_t pos ; + LONG lDistanceToMoveLow, lDistanceToMoveHigh ; + DWORD dwResult, dwError ; + + if (psf->virtual_io) + return psf->vio.tell (psf->vio_user_data) ; + + if (psf->is_pipe) + return psf->pipeoffset ; + + lDistanceToMoveLow = 0 ; + lDistanceToMoveHigh = 0 ; + + dwResult = SetFilePointer (psf->hfile, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_CURRENT) ; + + if (dwResult == 0xFFFFFFFF) + dwError = GetLastError () ; + else + dwError = NO_ERROR ; + + if (dwError != NO_ERROR) + { psf_log_syserr (psf, dwError) ; + return -1 ; + } ; + + pos = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) ; + + return pos - psf->fileoffset ; +} /* psf_ftell */ + +/* USE_WINDOWS_API */ static int +psf_close_handle (HANDLE handle) +{ if (CloseHandle (handle) == 0) + return -1 ; + + return 0 ; +} /* psf_close_handle */ + +/* USE_WINDOWS_API */ sf_count_t +psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) +{ sf_count_t k = 0 ; + sf_count_t count ; + DWORD dwNumberOfBytesRead ; + + while (k < bufsize - 1) + { if (ReadFile (psf->hfile, &(buffer [k]), 1, &dwNumberOfBytesRead, 0) == 0) + { psf_log_syserr (psf, GetLastError ()) ; + break ; + } + else + { count = dwNumberOfBytesRead ; + /* note that we only check for '\n' not other line endings such as CRLF */ + if (count == 0 || buffer [k++] == '\n') + break ; + } ; + } ; + + buffer [k] = 0 ; + + return k ; +} /* psf_fgets */ + +/* USE_WINDOWS_API */ int +psf_is_pipe (SF_PRIVATE *psf) +{ + if (psf->virtual_io) + return SF_FALSE ; + + if (GetFileType (psf->hfile) == FILE_TYPE_DISK) + return SF_FALSE ; + + /* Default to maximum safety. */ + return SF_TRUE ; +} /* psf_is_pipe */ + +/* USE_WINDOWS_API */ sf_count_t +psf_get_filelen_handle (HANDLE handle) +{ sf_count_t filelen ; + DWORD dwFileSizeLow, dwFileSizeHigh, dwError = NO_ERROR ; + + dwFileSizeLow = GetFileSize (handle, &dwFileSizeHigh) ; + + if (dwFileSizeLow == 0xFFFFFFFF) + dwError = GetLastError () ; + + if (dwError != NO_ERROR) + return (sf_count_t) -1 ; + + filelen = dwFileSizeLow + ((__int64) dwFileSizeHigh << 32) ; + + return filelen ; +} /* psf_get_filelen_handle */ + +/* USE_WINDOWS_API */ void +psf_fsync (SF_PRIVATE *psf) +{ FlushFileBuffers (psf->hfile) ; +} /* psf_fsync */ + + +/* USE_WINDOWS_API */ int +psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) +{ int retval = 0 ; + LONG lDistanceToMoveLow, lDistanceToMoveHigh ; + DWORD dwResult, dwError = NO_ERROR ; + + /* This implementation trashes the current file position. + ** should it save and restore it? what if the current position is past + ** the new end of file? + */ + + /* Returns 0 on success, non-zero on failure. */ + if (len < 0) + return 1 ; + + lDistanceToMoveLow = (DWORD) (len & 0xFFFFFFFF) ; + lDistanceToMoveHigh = (DWORD) ((len >> 32) & 0xFFFFFFFF) ; + + dwResult = SetFilePointer (psf->hfile, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_BEGIN) ; + + if (dwResult == 0xFFFFFFFF) + dwError = GetLastError () ; + + if (dwError != NO_ERROR) + { retval = -1 ; + psf_log_syserr (psf, dwError) ; + } + else + { /* Note: when SetEndOfFile is used to extend a file, the contents of the + ** new portion of the file is undefined. This is unlike chsize(), + ** which guarantees that the new portion of the file will be zeroed. + ** Not sure if this is important or not. + */ + if (SetEndOfFile (psf->hfile) == 0) + { retval = -1 ; + psf_log_syserr (psf, GetLastError ()) ; + } ; + } ; + + return retval ; +} /* psf_ftruncate */ + + +#else +/* Win32 file i/o functions implemented using Unix-style file i/o API */ + +/* Win32 has a 64 file offset seek function: +** +** __int64 _lseeki64 (int handle, __int64 offset, int origin) ; +** +** It also has a 64 bit fstat function: +** +** int fstati64 (int, struct _stati64) ; +** +** but the fscking thing doesn't work!!!!! The file size parameter returned +** by this function is only valid up until more data is written at the end of +** the file. That makes this function completely 100% useless. +*/ + +#include +#include + +#ifndef HAVE_SSIZE_T +typedef long ssize_t ; +#endif + +/* Win32 */ int +psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) +{ int oflag, mode ; + + switch (open_mode) + { case SFM_READ : + oflag = O_RDONLY | O_BINARY ; + mode = 0 ; + break ; + + case SFM_WRITE : + oflag = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; + mode = S_IRUSR | S_IWUSR | S_IRGRP ; + break ; + + case SFM_RDWR : + oflag = O_RDWR | O_CREAT | O_BINARY ; + mode = S_IRUSR | S_IWUSR | S_IRGRP ; + break ; + + default : + psf->error = SFE_BAD_OPEN_MODE ; + return -1 ; + break ; + } ; + + if (mode == 0) + psf->filedes = open (pathname, oflag) ; + else + psf->filedes = open (pathname, oflag, mode) ; + + if (psf->filedes == -1) + psf_log_syserr (psf, errno) ; + + return psf->filedes ; +} /* psf_fopen */ + +/* Win32 */ sf_count_t +psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) +{ sf_count_t new_position ; + + if (psf->virtual_io) + return psf->vio.seek (offset, whence, psf->vio_user_data) ; + + switch (whence) + { case SEEK_SET : + offset += psf->fileoffset ; + break ; + + case SEEK_END : + if (psf->mode == SFM_WRITE) + { new_position = _lseeki64 (psf->filedes, offset, whence) ; + + if (new_position < 0) + psf_log_syserr (psf, errno) ; + + return new_position - psf->fileoffset ; + } ; + + /* Transform SEEK_END into a SEEK_SET, ie find the file + ** length add the requested offset (should be <= 0) to + ** get the offset wrt the start of file. + */ + whence = SEEK_SET ; + offset = _lseeki64 (psf->filedes, 0, SEEK_END) + offset ; + break ; + + default : + /* No need to do anything about SEEK_CUR. */ + break ; + } ; + + /* + ** Bypass weird Win32-ism if necessary. + ** _lseeki64() returns an "invalid parameter" error if called with the + ** offset == 0 and whence == SEEK_CUR. + *** Use the _telli64() function instead. + */ + if (offset == 0 && whence == SEEK_CUR) + new_position = _telli64 (psf->filedes) ; + else + new_position = _lseeki64 (psf->filedes, offset, whence) ; + + if (new_position < 0) + psf_log_syserr (psf, errno) ; + + new_position -= psf->fileoffset ; + + return new_position ; +} /* psf_fseek */ + +/* Win32 */ sf_count_t +psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) +{ sf_count_t total = 0 ; + ssize_t count ; + + if (psf->virtual_io) + return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ; + + items *= bytes ; + + /* Do this check after the multiplication above. */ + if (items <= 0) + return 0 ; + + while (items > 0) + { /* Break the writes down to a sensible size. */ + count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; + + count = read (psf->filedes, ((char*) ptr) + total, (size_t) count) ; + + if (count == -1) + { if (errno == EINTR) + continue ; + + psf_log_syserr (psf, errno) ; + break ; + } ; + + if (count == 0) + break ; + + total += count ; + items -= count ; + } ; + + return total / bytes ; +} /* psf_fread */ + +/* Win32 */ sf_count_t +psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) +{ sf_count_t total = 0 ; + ssize_t count ; + + if (psf->virtual_io) + return psf->vio.write (ptr, bytes*items, psf->vio_user_data) / bytes ; + + items *= bytes ; + + /* Do this check after the multiplication above. */ + if (items <= 0) + return 0 ; + + while (items > 0) + { /* Break the writes down to a sensible size. */ + count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ; + + count = write (psf->filedes, ((const char*) ptr) + total, count) ; + + if (count == -1) + { if (errno == EINTR) + continue ; + + psf_log_syserr (psf, errno) ; + break ; + } ; + + if (count == 0) + break ; + + total += count ; + items -= count ; + } ; + + return total / bytes ; +} /* psf_fwrite */ + +/* Win32 */ sf_count_t +psf_ftell (SF_PRIVATE *psf) +{ sf_count_t pos ; + + if (psf->virtual_io) + return psf->vio.tell (psf->vio_user_data) ; + + pos = _telli64 (psf->filedes) ; + + if (pos == ((sf_count_t) -1)) + { psf_log_syserr (psf, errno) ; + return -1 ; + } ; + + return pos - psf->fileoffset ; +} /* psf_ftell */ + +/* Win32 */ int +psf_fclose (SF_PRIVATE *psf) +{ int retval ; + + while ((retval = close (psf->filedes)) == -1 && errno == EINTR) + /* Do nothing. */ ; + + if (retval == -1) + psf_log_syserr (psf, errno) ; + + psf->filedes = -1 ; + + return retval ; +} /* psf_fclose */ + +/* Win32 */ sf_count_t +psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) +{ sf_count_t k = 0 ; + sf_count_t count ; + + while (k < bufsize - 1) + { count = read (psf->filedes, &(buffer [k]), 1) ; + + if (count == -1) + { if (errno == EINTR) + continue ; + + psf_log_syserr (psf, errno) ; + break ; + } ; + + if (count == 0 || buffer [k++] == '\n') + break ; + } ; + + buffer [k] = 0 ; + + return k ; +} /* psf_fgets */ + +/* Win32 */ int +psf_is_pipe (SF_PRIVATE *psf) +{ struct stat statbuf ; + + if (psf->virtual_io) + return SF_FALSE ; + + /* Not sure if this works. */ + if (fstat (psf->filedes, &statbuf) == -1) + { psf_log_syserr (psf, errno) ; + /* Default to maximum safety. */ + return SF_TRUE ; + } ; + + /* These macros are defined in Win32/unistd.h. */ + if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode)) + return SF_TRUE ; + + return SF_FALSE ; +} /* psf_checkpipe */ + +/* Win32 */ sf_count_t +psf_get_filelen (SF_PRIVATE *psf) +{ +#if 0 + /* + ** Windoze is SOOOOO FUCKED!!!!!!! + ** This code should work but doesn't. Why? + ** Code below does work. + */ + struct _stati64 statbuf ; + + if (_fstati64 (psf->filedes, &statbuf)) + { psf_log_syserr (psf, errno) ; + return (sf_count_t) -1 ; + } ; + + return statbuf.st_size ; +#else + sf_count_t current, filelen ; + + if (psf->virtual_io) + return psf->vio.get_filelen (psf->vio_user_data) ; + + if ((current = _telli64 (psf->filedes)) < 0) + { psf_log_syserr (psf, errno) ; + return (sf_count_t) -1 ; + } ; + + /* + ** Lets face it, windoze if FUBAR!!! + ** + ** For some reason, I have to call _lseeki64() TWICE to get to the + ** end of the file. + ** + ** This might have been avoided if windows had implemented the POSIX + ** standard function fsync() but NO, that would have been too easy. + ** + ** I am VERY close to saying that windoze will no longer be supported + ** by libsndfile and changing the license to GPL at the same time. + */ + + _lseeki64 (psf->filedes, 0, SEEK_END) ; + + if ((filelen = _lseeki64 (psf->filedes, 0, SEEK_END)) < 0) + { psf_log_syserr (psf, errno) ; + return (sf_count_t) -1 ; + } ; + + if (filelen > current) + _lseeki64 (psf->filedes, current, SEEK_SET) ; + + switch (psf->mode) + { case SFM_WRITE : + filelen = filelen - psf->fileoffset ; + break ; + + case SFM_READ : + if (psf->fileoffset > 0 && psf->filelength > 0) + filelen = psf->filelength ; + break ; + + case SFM_RDWR : + /* + ** Cannot open embedded files SFM_RDWR so we don't need to + ** subtract psf->fileoffset. We already have the answer we + ** need. + */ + break ; + + default : + filelen = 0 ; + } ; + + return filelen ; +#endif +} /* psf_get_filelen */ + +/* Win32 */ int +psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) +{ int retval ; + + /* Returns 0 on success, non-zero on failure. */ + if (len < 0) + return 1 ; + + /* The global village idiots at micorsoft decided to implement + ** nearly all the required 64 bit file offset functions except + ** for one, truncate. The fscking morons! + ** + ** This is not 64 bit file offset clean. Somone needs to clean + ** this up. + */ + if (len > 0x7FFFFFFF) + return -1 ; + + retval = chsize (psf->filedes, len) ; + + if (retval == -1) + psf_log_syserr (psf, errno) ; + + return retval ; +} /* psf_ftruncate */ + + +static void +psf_log_syserr (SF_PRIVATE *psf, int error) +{ + /* Only log an error if no error has been set yet. */ + if (psf->error == 0) + { psf->error = SFE_SYSTEM ; + LSF_SNPRINTF (psf->syserr, sizeof (psf->syserr), "System error : %s", strerror (error)) ; + } ; + + return ; +} /* psf_log_syserr */ + +#endif + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 749740d7-ecc7-47bd-8cf7-600f31d32e6d +*/ diff --git a/nylsf/flac.c b/nylsf/flac.c new file mode 100644 index 0000000..79fa2db --- /dev/null +++ b/nylsf/flac.c @@ -0,0 +1,1156 @@ +/* +** Copyright (C) 2004, 2005 Erik de Castro Lopo +** Copyright (C) 2004 Tobias Gehrig +** +** 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 2.1 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 Lesser General Public License +** along with this program ; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "common.h" + + +#ifndef HAVE_FLAC_ALL_H + +int +flac_open (SF_PRIVATE *psf) +{ if (psf) + return SFE_UNIMPLEMENTED ; + return (psf && 0) ; +} /* flac_open */ + + +#else + +#include + +#include "sfendian.h" +#include "float_cast.h" + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +#define ENC_BUFFER_SIZE 4096 + +typedef enum +{ PFLAC_PCM_SHORT = 0, + PFLAC_PCM_INT = 1, + PFLAC_PCM_FLOAT = 2, + PFLAC_PCM_DOUBLE = 3 +} PFLAC_PCM ; + +typedef struct +{ FLAC__SeekableStreamDecoder *fsd ; + FLAC__SeekableStreamEncoder *fse ; + PFLAC_PCM pcmtype ; + void* ptr ; + unsigned pos, len, remain ; + + const FLAC__int32 * const * wbuffer ; + FLAC__int32 * rbuffer [FLAC__MAX_CHANNELS] ; + + FLAC__int32* encbuffer ; + unsigned bufferpos ; + + const FLAC__Frame *frame ; + FLAC__bool bufferbackup ; +} FLAC_PRIVATE ; + +static sf_count_t flac_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; +static int flac_close (SF_PRIVATE *psf) ; + +static int flac_enc_init (SF_PRIVATE *psf) ; +static int flac_read_header (SF_PRIVATE *psf) ; + +static sf_count_t flac_read_flac2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t flac_read_flac2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t flac_read_flac2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t flac_read_flac2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t flac_write_s2flac (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t flac_write_i2flac (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t flac_write_f2flac (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t flac_write_d2flac (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static void f2flac8_array (const float *src, FLAC__int32 *dest, int count, int normalize) ; +static void f2flac16_array (const float *src, FLAC__int32 *dest, int count, int normalize) ; +static void f2flac24_array (const float *src, FLAC__int32 *dest, int count, int normalize) ; +static void f2flac8_clip_array (const float *src, FLAC__int32 *dest, int count, int normalize) ; +static void f2flac16_clip_array (const float *src, FLAC__int32 *dest, int count, int normalize) ; +static void f2flac24_clip_array (const float *src, FLAC__int32 *dest, int count, int normalize) ; +static void d2flac8_array (const double *src, FLAC__int32 *dest, int count, int normalize) ; +static void d2flac16_array (const double *src, FLAC__int32 *dest, int count, int normalize) ; +static void d2flac24_array (const double *src, FLAC__int32 *dest, int count, int normalize) ; +static void d2flac8_clip_array (const double *src, FLAC__int32 *dest, int count, int normalize) ; +static void d2flac16_clip_array (const double *src, FLAC__int32 *dest, int count, int normalize) ; +static void d2flac24_clip_array (const double *src, FLAC__int32 *dest, int count, int normalize) ; + +static int flac_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; + +/* Decoder Callbacks */ +static FLAC__SeekableStreamDecoderReadStatus sf_flac_read_callback (const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer [], unsigned *bytes, void *client_data) ; +static FLAC__SeekableStreamDecoderSeekStatus sf_flac_seek_callback (const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) ; +static FLAC__SeekableStreamDecoderTellStatus sf_flac_tell_callback (const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) ; +static FLAC__SeekableStreamDecoderLengthStatus sf_flac_length_callback (const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) ; +static FLAC__bool sf_flac_eof_callback (const FLAC__SeekableStreamDecoder *decoder, void *client_data) ; +static FLAC__StreamDecoderWriteStatus sf_flac_write_callback (const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer [], void *client_data) ; +static void sf_flac_meta_callback (const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) ; +static void sf_flac_error_callback (const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) ; + +/* Encoder Callbacks */ +static FLAC__SeekableStreamEncoderSeekStatus sf_flac_enc_seek_callback (const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) ; +#ifdef HAVE_FLAC_1_1_1 +static FLAC__SeekableStreamEncoderTellStatus sf_flac_enc_tell_callback (const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) ; +#endif +static FLAC__StreamEncoderWriteStatus sf_flac_enc_write_callback (const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer [], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) ; + +static const int legal_sample_rates [] = +{ 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000 +} ; + +static void +s2flac8_array (const short *src, FLAC__int32 *dest, int count) +{ while (--count >= 0) + dest [count] = src [count] >> 8 ; +} /* s2flac8_array */ + +static void +s2flac16_array (const short *src, FLAC__int32 *dest, int count) +{ while (--count >= 0) + dest [count] = src [count] ; +} /* s2flac16_array */ + +static void +s2flac24_array (const short *src, FLAC__int32 *dest, int count) +{ while (--count >= 0) + dest [count] = src [count] << 8 ; +} /* s2flac24_array */ + +static void +i2flac8_array (const int *src, FLAC__int32 *dest, int count) +{ while (--count >= 0) + dest [count] = src [count] >> 24 ; +} /* i2flac8_array */ + +static void +i2flac16_array (const int *src, FLAC__int32 *dest, int count) +{ + while (--count >= 0) + dest [count] = src [count] >> 16 ; +} /* i2flac16_array */ + +static void +i2flac24_array (const int *src, FLAC__int32 *dest, int count) +{ while (--count >= 0) + dest [count] = src [count] >> 8 ; +} /* i2flac24_array */ + +static sf_count_t +flac_buffer_copy (SF_PRIVATE *psf) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + const FLAC__Frame *frame = pflac->frame ; + const FLAC__int32* const *buffer = pflac->wbuffer ; + unsigned i = 0, j, offset ; + + if (pflac->ptr == NULL) + { /* + ** Not sure why this code is here and not elsewhere. + ** Removing it causes valgrind errors. + */ + pflac->bufferbackup = SF_TRUE ; + for (i = 0 ; i < frame->header.channels ; i++) + { if (pflac->rbuffer [i] == NULL) + pflac->rbuffer [i] = calloc (frame->header.blocksize, sizeof (FLAC__int32)) ; + memcpy (pflac->rbuffer [i], buffer [i], frame->header.blocksize * sizeof (FLAC__int32)) ; + } ; + pflac->wbuffer = (const FLAC__int32* const*) pflac->rbuffer ; + + return 0 ; + } ; + + switch (pflac->pcmtype) + { case PFLAC_PCM_SHORT : + { short *retpcm = ((short*) pflac->ptr) ; + int shift = 16 - frame->header.bits_per_sample ; + if (shift < 0) + { shift = abs (shift) ; + for (i = 0 ; i < frame->header.blocksize && pflac->remain > 0 ; i++) + { offset = pflac->pos + i * frame->header.channels ; + for (j = 0 ; j < frame->header.channels ; j++) + retpcm [offset + j] = buffer [j][pflac->bufferpos] >> shift ; + pflac->remain -= frame->header.channels ; + pflac->bufferpos++ ; + } + } + else + { for (i = 0 ; i < frame->header.blocksize && pflac->remain > 0 ; i++) + { offset = pflac->pos + i * frame->header.channels ; + + if (pflac->bufferpos >= frame->header.blocksize) + break ; + + for (j = 0 ; j < frame->header.channels ; j++) + retpcm [offset + j] = (buffer [j][pflac->bufferpos]) << shift ; + + pflac->remain -= frame->header.channels ; + pflac->bufferpos++ ; + } ; + } ; + } ; + break ; + + case PFLAC_PCM_INT : + { int *retpcm = ((int*) pflac->ptr) ; + int shift = 32 - frame->header.bits_per_sample ; + for (i = 0 ; i < frame->header.blocksize && pflac->remain > 0 ; i++) + { offset = pflac->pos + i * frame->header.channels ; + + if (pflac->bufferpos >= frame->header.blocksize) + break ; + + for (j = 0 ; j < frame->header.channels ; j++) + retpcm [offset + j] = buffer [j][pflac->bufferpos] << shift ; + pflac->remain -= frame->header.channels ; + pflac->bufferpos++ ; + } ; + } ; + break ; + + case PFLAC_PCM_FLOAT : + { float *retpcm = ((float*) pflac->ptr) ; + float norm = (psf->norm_float == SF_TRUE) ? 1.0 / (1 << (frame->header.bits_per_sample - 1)) : 1.0 ; + + for (i = 0 ; i < frame->header.blocksize && pflac->remain > 0 ; i++) + { offset = pflac->pos + i * frame->header.channels ; + + if (pflac->bufferpos >= frame->header.blocksize) + break ; + + for (j = 0 ; j < frame->header.channels ; j++) + retpcm [offset + j] = buffer [j][pflac->bufferpos] * norm ; + pflac->remain -= frame->header.channels ; + pflac->bufferpos++ ; + } ; + } ; + break ; + + case PFLAC_PCM_DOUBLE : + { double *retpcm = ((double*) pflac->ptr) ; + double norm = (psf->norm_double == SF_TRUE) ? 1.0 / (1 << (frame->header.bits_per_sample - 1)) : 1.0 ; + + for (i = 0 ; i < frame->header.blocksize && pflac->remain > 0 ; i++) + { offset = pflac->pos + i * frame->header.channels ; + + if (pflac->bufferpos >= frame->header.blocksize) + break ; + + for (j = 0 ; j < frame->header.channels ; j++) + retpcm [offset + j] = buffer [j][pflac->bufferpos] * norm ; + pflac->remain -= frame->header.channels ; + pflac->bufferpos++ ; + } ; + } ; + break ; + + default : + return 0 ; + } ; + + offset = i * frame->header.channels ; + pflac->pos += i * frame->header.channels ; + + return offset ; +} /* flac_buffer_copy */ + + +static FLAC__SeekableStreamDecoderReadStatus +sf_flac_read_callback (const FLAC__SeekableStreamDecoder * UNUSED (decoder), FLAC__byte buffer [], unsigned *bytes, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + *bytes = psf_fread (buffer, 1, *bytes, psf) ; + if (*bytes > 0 && psf->error == 0) + return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK ; + + return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR ; +} /* sf_flac_read_callback */ + +static FLAC__SeekableStreamDecoderSeekStatus +sf_flac_seek_callback (const FLAC__SeekableStreamDecoder * UNUSED (decoder), FLAC__uint64 absolute_byte_offset, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + psf_fseek (psf, absolute_byte_offset, SEEK_SET) ; + if (psf->error) + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR ; + + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK ; +} /* sf_flac_seek_callback */ + +static FLAC__SeekableStreamDecoderTellStatus +sf_flac_tell_callback (const FLAC__SeekableStreamDecoder * UNUSED (decoder), FLAC__uint64 *absolute_byte_offset, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + *absolute_byte_offset = psf_ftell (psf) ; + if (psf->error) + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR ; + + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK ; +} /* sf_flac_tell_callback */ + +static FLAC__SeekableStreamDecoderLengthStatus +sf_flac_length_callback (const FLAC__SeekableStreamDecoder * UNUSED (decoder), FLAC__uint64 *stream_length, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + if ((*stream_length = psf->filelength) == 0) + return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR ; + + return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK ; +} /* sf_flac_length_callback */ + +static FLAC__bool +sf_flac_eof_callback (const FLAC__SeekableStreamDecoder *UNUSED (decoder), void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + if (psf_ftell (psf) == psf->filelength) + return SF_TRUE ; + + return SF_FALSE ; +} /* sf_flac_eof_callback */ + +static FLAC__StreamDecoderWriteStatus +sf_flac_write_callback (const FLAC__SeekableStreamDecoder * UNUSED (decoder), const FLAC__Frame *frame, const FLAC__int32 * const buffer [], void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + + pflac->frame = frame ; + pflac->bufferpos = 0 ; + + pflac->bufferbackup = SF_FALSE ; + pflac->wbuffer = buffer ; + + flac_buffer_copy (psf) ; + + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE ; +} /* sf_flac_write_callback */ + +static void +sf_flac_meta_callback (const FLAC__SeekableStreamDecoder * UNUSED (decoder), const FLAC__StreamMetadata *metadata, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + switch (metadata->type) + { case FLAC__METADATA_TYPE_STREAMINFO : + psf->sf.channels = metadata->data.stream_info.channels ; + psf->sf.samplerate = metadata->data.stream_info.sample_rate ; + psf->sf.frames = metadata->data.stream_info.total_samples ; + + switch (metadata->data.stream_info.bits_per_sample) + { case 8 : + psf->sf.format |= SF_FORMAT_PCM_S8 ; + break ; + case 16 : + psf->sf.format |= SF_FORMAT_PCM_16 ; + break ; + case 24 : + psf->sf.format |= SF_FORMAT_PCM_24 ; + break ; + default : + psf_log_printf (psf, "sf_flac_meta_callback : bits_per_sample %d not yet implemented.\n", metadata->data.stream_info.bits_per_sample) ; + break ; + } ; + break ; + + default : + psf_log_printf (psf, "sf_flac_meta_callback : metadata-type %d not yet implemented.\n", metadata->type) ; + break ; + } ; + + return ; +} /* sf_flac_meta_callback */ + +static void +sf_flac_error_callback (const FLAC__SeekableStreamDecoder * UNUSED (decoder), FLAC__StreamDecoderErrorStatus status, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + psf_log_printf (psf, "ERROR : %s\n", FLAC__StreamDecoderErrorStatusString [status]) ; + + switch (status) + { case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC : + psf->error = SFE_FLAC_LOST_SYNC ; + break ; + case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER : + psf->error = SFE_FLAC_BAD_HEADER ; + break ; + default : + psf->error = SFE_FLAC_UNKNOWN_ERROR ; + break ; + } ; + + return ; +} /* sf_flac_error_callback */ + +static FLAC__SeekableStreamEncoderSeekStatus +sf_flac_enc_seek_callback (const FLAC__SeekableStreamEncoder * UNUSED (encoder), FLAC__uint64 absolute_byte_offset, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + psf_fseek (psf, absolute_byte_offset, SEEK_SET) ; + if (psf->error) + return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR ; + + return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK ; +} /* sf_flac_enc_seek_callback */ + +#ifdef HAVE_FLAC_1_1_1 +static FLAC__SeekableStreamEncoderTellStatus +sf_flac_enc_tell_callback (const FLAC__SeekableStreamEncoder *UNUSED (encoder), FLAC__uint64 *absolute_byte_offset, void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + *absolute_byte_offset = psf_ftell (psf) ; + if (psf->error) + return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR ; + + return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK ; +} /* sf_flac_enc_tell_callback */ +#endif + +static FLAC__StreamEncoderWriteStatus +sf_flac_enc_write_callback (const FLAC__SeekableStreamEncoder * UNUSED (encoder), const FLAC__byte buffer [], unsigned bytes, unsigned UNUSED (samples), unsigned UNUSED (current_frame), void *client_data) +{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ; + + if (psf_fwrite (buffer, 1, bytes, psf) == bytes && psf->error == 0) + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK ; + + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR ; +} /* sf_flac_enc_write_callback */ + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +flac_open (SF_PRIVATE *psf) +{ int subformat ; + int error = 0 ; + + FLAC_PRIVATE* pflac = calloc (1, sizeof (FLAC_PRIVATE)) ; + psf->codec_data = pflac ; + + if (psf->mode == SFM_RDWR) + return SFE_UNIMPLEMENTED ; + + if (psf->mode == SFM_READ) + { if ((error = flac_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE) + { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_FLAC) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = SF_ENDIAN_BIG ; + + if ((error = flac_enc_init (psf))) + return error ; + } ; + + psf->datalength = psf->filelength ; + psf->dataoffset = 0 ; + psf->blockwidth = 0 ; + psf->bytewidth = 1 ; + + psf->container_close = flac_close ; + psf->seek = flac_seek ; + psf->command = flac_command ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_PCM_S8 : /* 8-bit FLAC. */ + case SF_FORMAT_PCM_16 : /* 16-bit FLAC. */ + case SF_FORMAT_PCM_24 : /* 24-bit FLAC. */ + error = flac_init (psf) ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + return error ; +} /* flac_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +flac_close (SF_PRIVATE *psf) +{ FLAC_PRIVATE* pflac ; + int k ; + + if ((pflac = (FLAC_PRIVATE*) psf->codec_data) == NULL) + return 0 ; + + if (psf->mode == SFM_WRITE) + { FLAC__seekable_stream_encoder_finish (pflac->fse) ; + FLAC__seekable_stream_encoder_delete (pflac->fse) ; + if (pflac->encbuffer) + free (pflac->encbuffer) ; + } ; + + if (psf->mode == SFM_READ) + { FLAC__seekable_stream_decoder_finish (pflac->fsd) ; + FLAC__seekable_stream_decoder_delete (pflac->fsd) ; + } ; + + for (k = 0 ; k < ARRAY_LEN (pflac->rbuffer) ; k++) + free (pflac->rbuffer [k]) ; + + free (pflac) ; + psf->codec_data = NULL ; + + return 0 ; +} /* flac_close */ + +static int +flac_enc_init (SF_PRIVATE *psf) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + unsigned bps ; + int k, found ; + + found = 0 ; + for (k = 0 ; k < ARRAY_LEN (legal_sample_rates) ; k++) + if (psf->sf.samplerate == legal_sample_rates [k]) + { found = 1 ; + break ; + } ; + + if (found == 0) + return SFE_FLAC_BAD_SAMPLE_RATE ; + + psf_fseek (psf, 0, SEEK_SET) ; + if ((pflac->fse = FLAC__seekable_stream_encoder_new ()) == NULL) + return SFE_FLAC_NEW_DECODER ; + FLAC__seekable_stream_encoder_set_write_callback (pflac->fse, sf_flac_enc_write_callback) ; + FLAC__seekable_stream_encoder_set_seek_callback (pflac->fse, sf_flac_enc_seek_callback) ; + +#ifdef HAVE_FLAC_1_1_1 + FLAC__seekable_stream_encoder_set_tell_callback (pflac->fse, sf_flac_enc_tell_callback) ; +#endif + FLAC__seekable_stream_encoder_set_client_data (pflac->fse, psf) ; + FLAC__seekable_stream_encoder_set_channels (pflac->fse, psf->sf.channels) ; + FLAC__seekable_stream_encoder_set_sample_rate (pflac->fse, psf->sf.samplerate) ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + bps = 8 ; + break ; + case SF_FORMAT_PCM_16 : + bps = 16 ; + break ; + case SF_FORMAT_PCM_24 : + bps = 24 ; + break ; + + default : + bps = 0 ; + break ; + } ; + + FLAC__seekable_stream_encoder_set_bits_per_sample (pflac->fse, bps) ; + + if ((bps = FLAC__seekable_stream_encoder_init (pflac->fse)) != FLAC__SEEKABLE_STREAM_DECODER_OK) + { psf_log_printf (psf, "Error : FLAC encoder init returned error : %s\n", FLAC__seekable_stream_encoder_get_resolved_state_string (pflac->fse)) ; + return SFE_FLAC_INIT_DECODER ; + } ; + + if (psf->error == 0) + psf->dataoffset = psf_ftell (psf) ; + pflac->encbuffer = calloc (ENC_BUFFER_SIZE, sizeof (FLAC__int32)) ; + + return psf->error ; +} /* flac_enc_init */ + +static int +flac_read_header (SF_PRIVATE *psf) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + + psf_fseek (psf, 0, SEEK_SET) ; + if ((pflac->fsd = FLAC__seekable_stream_decoder_new ()) == NULL) + return SFE_FLAC_NEW_DECODER ; + + FLAC__seekable_stream_decoder_set_read_callback (pflac->fsd, sf_flac_read_callback) ; + FLAC__seekable_stream_decoder_set_seek_callback (pflac->fsd, sf_flac_seek_callback) ; + FLAC__seekable_stream_decoder_set_tell_callback (pflac->fsd, sf_flac_tell_callback) ; + FLAC__seekable_stream_decoder_set_length_callback (pflac->fsd, sf_flac_length_callback) ; + FLAC__seekable_stream_decoder_set_eof_callback (pflac->fsd, sf_flac_eof_callback) ; + FLAC__seekable_stream_decoder_set_write_callback (pflac->fsd, sf_flac_write_callback) ; + FLAC__seekable_stream_decoder_set_metadata_callback (pflac->fsd, sf_flac_meta_callback) ; + FLAC__seekable_stream_decoder_set_error_callback (pflac->fsd, sf_flac_error_callback) ; + FLAC__seekable_stream_decoder_set_client_data (pflac->fsd, psf) ; + + if (FLAC__seekable_stream_decoder_init (pflac->fsd) != FLAC__SEEKABLE_STREAM_DECODER_OK) + return SFE_FLAC_INIT_DECODER ; + + FLAC__seekable_stream_decoder_process_until_end_of_metadata (pflac->fsd) ; + if (psf->error == 0) + { FLAC__uint64 position ; + FLAC__seekable_stream_decoder_get_decode_position (pflac->fsd, &position) ; + psf->dataoffset = position ; + } ; + + return psf->error ; +} /* flac_read_header */ + +static int +flac_command (SF_PRIVATE *psf, int command, void *data, int datasize) +{ + /* Avoid compiler warnings. */ + psf = psf ; + data = data ; + datasize = datasize ; + + switch (command) + { default : break ; + } ; + + return 0 ; +} /* flac_command */ + +int +flac_init (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + if (psf->mode == SFM_READ) + { psf->read_short = flac_read_flac2s ; + psf->read_int = flac_read_flac2i ; + psf->read_float = flac_read_flac2f ; + psf->read_double = flac_read_flac2d ; + } ; + + if (psf->mode == SFM_WRITE) + { psf->write_short = flac_write_s2flac ; + psf->write_int = flac_write_i2flac ; + psf->write_float = flac_write_f2flac ; + psf->write_double = flac_write_d2flac ; + } ; + + psf->bytewidth = 1 ; + psf->blockwidth = psf->sf.channels ; + + if (psf->filelength > psf->dataoffset) + psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; + else + psf->datalength = 0 ; + + return 0 ; +} /* flac_init */ + +static unsigned +flac_read_loop (SF_PRIVATE *psf, unsigned len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + + pflac->pos = 0 ; + pflac->len = len ; + pflac->remain = len ; + if (pflac->frame != NULL && pflac->bufferpos < pflac->frame->header.blocksize) + flac_buffer_copy (psf) ; + + while (pflac->pos < pflac->len) + { if (FLAC__seekable_stream_decoder_process_single (pflac->fsd) == 0) + break ; + if (FLAC__seekable_stream_decoder_get_state (pflac->fsd) != FLAC__SEEKABLE_STREAM_DECODER_OK) + break ; + } ; + + pflac->ptr = NULL ; + + return pflac->pos ; +} /* flac_read_loop */ + +static sf_count_t +flac_read_flac2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0, current ; + unsigned readlen ; + + pflac->pcmtype = PFLAC_PCM_SHORT ; + + while (total < len) + { pflac->ptr = ptr + total ; + readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ; + current = flac_read_loop (psf, readlen) ; + if (current == 0) + break ; + total += current ; + } ; + + return total ; +} /* flac_read_flac2s */ + +static sf_count_t +flac_read_flac2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0, current ; + unsigned readlen ; + + pflac->pcmtype = PFLAC_PCM_INT ; + + while (total < len) + { pflac->ptr = ptr + total ; + readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ; + current = flac_read_loop (psf, readlen) ; + if (current == 0) + break ; + total += current ; + } ; + + return total ; +} /* flac_read_flac2i */ + +static sf_count_t +flac_read_flac2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0, current ; + unsigned readlen ; + + pflac->pcmtype = PFLAC_PCM_FLOAT ; + + while (total < len) + { pflac->ptr = ptr + total ; + readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ; + current = flac_read_loop (psf, readlen) ; + if (current == 0) + break ; + total += current ; + } ; + + return total ; +} /* flac_read_flac2f */ + +static sf_count_t +flac_read_flac2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0, current ; + unsigned readlen ; + + pflac->pcmtype = PFLAC_PCM_DOUBLE ; + + while (total < len) + { pflac->ptr = ptr + total ; + readlen = (len - total > 0x1000000) ? 0x1000000 : (unsigned) (len - total) ; + current = flac_read_loop (psf, readlen) ; + if (current == 0) + break ; + total += current ; + } ; + + return total ; +} /* flac_read_flac2d */ + +static sf_count_t +flac_write_s2flac (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + void (*convert) (const short *, FLAC__int32 *, int) ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + FLAC__int32* buffer = pflac->encbuffer ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + convert = s2flac8_array ; + break ; + case SF_FORMAT_PCM_16 : + convert = s2flac16_array ; + break ; + case SF_FORMAT_PCM_24 : + convert = s2flac24_array ; + break ; + default : + return -1 ; + } ; + + bufferlen = ENC_BUFFER_SIZE / (sizeof (FLAC__int32) * psf->sf.channels) ; + bufferlen *= psf->sf.channels ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + convert (ptr + total, buffer, writecount) ; + if (FLAC__seekable_stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels)) + thiswrite = writecount ; + else + break ; + total += thiswrite ; + if (thiswrite < writecount) + break ; + + len -= thiswrite ; + } ; + + return total ; +} /* flac_write_s2flac */ + +static sf_count_t +flac_write_i2flac (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + void (*convert) (const int *, FLAC__int32 *, int) ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + FLAC__int32* buffer = pflac->encbuffer ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + convert = i2flac8_array ; + break ; + case SF_FORMAT_PCM_16 : + convert = i2flac16_array ; + break ; + case SF_FORMAT_PCM_24 : + convert = i2flac24_array ; + break ; + default : + return -1 ; + } ; + + bufferlen = ENC_BUFFER_SIZE / (sizeof (FLAC__int32) * psf->sf.channels) ; + bufferlen *= psf->sf.channels ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + convert (ptr + total, buffer, writecount) ; + if (FLAC__seekable_stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels)) + thiswrite = writecount ; + else + break ; + total += thiswrite ; + if (thiswrite < writecount) + break ; + + len -= thiswrite ; + } ; + + return total ; +} /* flac_write_i2flac */ + +static sf_count_t +flac_write_f2flac (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + void (*convert) (const float *, FLAC__int32 *, int, int) ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + FLAC__int32* buffer = pflac->encbuffer ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + convert = (psf->add_clipping) ? f2flac8_clip_array : f2flac8_array ; + break ; + case SF_FORMAT_PCM_16 : + convert = (psf->add_clipping) ? f2flac16_clip_array : f2flac16_array ; + break ; + case SF_FORMAT_PCM_24 : + convert = (psf->add_clipping) ? f2flac24_clip_array : f2flac24_array ; + break ; + default : + return -1 ; + } ; + + bufferlen = ENC_BUFFER_SIZE / (sizeof (FLAC__int32) * psf->sf.channels) ; + bufferlen *= psf->sf.channels ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + convert (ptr + total, buffer, writecount, psf->norm_float) ; + if (FLAC__seekable_stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels)) + thiswrite = writecount ; + else + break ; + total += thiswrite ; + if (thiswrite < writecount) + break ; + + len -= thiswrite ; + } ; + + return total ; +} /* flac_write_f2flac */ + +static void +f2flac8_clip_array (const float *src, FLAC__int32 *dest, int count, int normalize) +{ float normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10) : 1.0 ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) + { dest [count] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) + { dest [count] = 0x80 ; + continue ; + } ; + dest [count] = lrintf (scaled_value) ; + } ; + + return ; +} /* f2flac8_clip_array */ + +static void +f2flac16_clip_array (const float *src, FLAC__int32 *dest, int count, int normalize) +{ + float normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x1000) : 1.0 ; + + while (--count >= 0) { + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) { + dest [count] = 0x7FFF ; + continue ; + } + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) { + dest [count] = 0x8000 ; + continue ; + } + dest [count] = lrintf (scaled_value) ; + } +} /* f2flac16_clip_array */ + +static void +f2flac24_clip_array (const float *src, FLAC__int32 *dest, int count, int normalize) +{ float normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x100000) : 1.0 ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) + { dest [count] = 0x7FFFFF ; + continue ; + } ; + + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) + { dest [count] = 0x800000 ; + continue ; + } + dest [count] = lrintf (scaled_value) ; + } ; + + return ; +} /* f2flac24_clip_array */ + +static void +f2flac8_array (const float *src, FLAC__int32 *dest, int count, int normalize) +{ float normfact = normalize ? (1.0 * 0x7F) : 1.0 ; + + while (--count >= 0) + dest [count] = lrintf (src [count] * normfact) ; +} /* f2flac8_array */ + +static void +f2flac16_array (const float *src, FLAC__int32 *dest, int count, int normalize) +{ float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; + + while (--count >= 0) + dest [count] = lrintf (src [count] * normfact) ; +} /* f2flac16_array */ + +static void +f2flac24_array (const float *src, FLAC__int32 *dest, int count, int normalize) +{ float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; + + while (--count >= 0) + dest [count] = lrintf (src [count] * normfact) ; +} /* f2flac24_array */ + +static sf_count_t +flac_write_d2flac (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + void (*convert) (const double *, FLAC__int32 *, int, int) ; + int bufferlen, writecount, thiswrite ; + sf_count_t total = 0 ; + FLAC__int32* buffer = pflac->encbuffer ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + convert = (psf->add_clipping) ? d2flac8_clip_array : d2flac8_array ; + break ; + case SF_FORMAT_PCM_16 : + convert = (psf->add_clipping) ? d2flac16_clip_array : d2flac16_array ; + break ; + case SF_FORMAT_PCM_24 : + convert = (psf->add_clipping) ? d2flac24_clip_array : d2flac24_array ; + break ; + default : + return -1 ; + } ; + + bufferlen = ENC_BUFFER_SIZE / (sizeof (FLAC__int32) * psf->sf.channels) ; + bufferlen *= psf->sf.channels ; + + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + convert (ptr + total, buffer, writecount, psf->norm_double) ; + if (FLAC__seekable_stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels)) + thiswrite = writecount ; + else + break ; + total += thiswrite ; + if (thiswrite < writecount) + break ; + + len -= thiswrite ; + } ; + + return total ; +} /* flac_write_d2flac */ + +static void +d2flac8_clip_array (const double *src, FLAC__int32 *dest, int count, int normalize) +{ double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10) : 1.0 ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) + { dest [count] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) + { dest [count] = 0x80 ; + continue ; + } ; + dest [count] = lrint (scaled_value) ; + } ; + + return ; +} /* d2flac8_clip_array */ + +static void +d2flac16_clip_array (const double *src, FLAC__int32 *dest, int count, int normalize) +{ double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x1000) : 1.0 ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) + { dest [count] = 0x7FFF ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) + { dest [count] = 0x8000 ; + continue ; + } ; + dest [count] = lrint (scaled_value) ; + } ; + + return ; +} /* d2flac16_clip_array */ + +static void +d2flac24_clip_array (const double *src, FLAC__int32 *dest, int count, int normalize) +{ double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x100000) : 1.0 ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) + { dest [count] = 0x7FFFFF ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) + { dest [count] = 0x800000 ; + continue ; + } ; + dest [count] = lrint (scaled_value) ; + } ; + + return ; +} /* d2flac24_clip_array */ + +static void +d2flac8_array (const double *src, FLAC__int32 *dest, int count, int normalize) +{ double normfact = normalize ? (1.0 * 0x7F) : 1.0 ; + + while (--count >= 0) + dest [count] = lrint (src [count] * normfact) ; +} /* d2flac8_array */ + +static void +d2flac16_array (const double *src, FLAC__int32 *dest, int count, int normalize) +{ double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; + + while (--count >= 0) + dest [count] = lrint (src [count] * normfact) ; +} /* d2flac16_array */ + +static void +d2flac24_array (const double *src, FLAC__int32 *dest, int count, int normalize) +{ double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; + + while (--count >= 0) + dest [count] = lrint (src [count] * normfact) ; +} /* d2flac24_array */ + +static sf_count_t +flac_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset) +{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ; + + if (pflac == NULL) + return 0 ; + + if (psf->dataoffset < 0) + { psf->error = SFE_BAD_SEEK ; + return ((sf_count_t) -1) ; + } ; + + pflac->frame = NULL ; + + if (psf->mode == SFM_READ) + { FLAC__uint64 position ; + if (FLAC__seekable_stream_decoder_seek_absolute (pflac->fsd, offset)) + { FLAC__seekable_stream_decoder_get_decode_position (pflac->fsd, &position) ; + return offset ; + } ; + + return ((sf_count_t) -1) ; + } ; + + /* Seeking in write mode not yet supported. */ + psf->error = SFE_BAD_SEEK ; + + return ((sf_count_t) -1) ; +} /* flac_seek */ + +#endif + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 46d49617-ebff-42b4-8f66-a0e428147360 +*/ diff --git a/nylsf/float32.c b/nylsf/float32.c new file mode 100644 index 0000000..b376e60 --- /dev/null +++ b/nylsf/float32.c @@ -0,0 +1,961 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "float_cast.h" + +#if CPU_IS_LITTLE_ENDIAN + #define FLOAT32_READ float32_le_read + #define FLOAT32_WRITE float32_le_write +#elif CPU_IS_BIG_ENDIAN + #define FLOAT32_READ float32_be_read + #define FLOAT32_WRITE float32_be_write +#endif + +/*-------------------------------------------------------------------------------------------- +** Processor floating point capabilities. float32_get_capability () returns one of the +** latter four values. +*/ + +enum +{ FLOAT_UNKNOWN = 0x00, + FLOAT_CAN_RW_LE = 0x12, + FLOAT_CAN_RW_BE = 0x23, + FLOAT_BROKEN_LE = 0x34, + FLOAT_BROKEN_BE = 0x45 +} ; + +/*-------------------------------------------------------------------------------------------- +** Prototypes for private functions. +*/ + +static sf_count_t host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static void float32_peak_update (SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx) ; + +static sf_count_t replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static void bf2f_array (float *buffer, int count) ; +static void f2bf_array (float *buffer, int count) ; + +static int float32_get_capability (SF_PRIVATE *psf) ; + +/*-------------------------------------------------------------------------------------------- +** Exported functions. +*/ + +int +float32_init (SF_PRIVATE *psf) +{ static int float_caps ; + + float_caps = float32_get_capability (psf) ; + + psf->blockwidth = sizeof (float) * psf->sf.channels ; + + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { switch (psf->endian + float_caps) + { case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = host_read_f2s ; + psf->read_int = host_read_f2i ; + psf->read_float = host_read_f ; + psf->read_double = host_read_f2d ; + break ; + + case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = host_read_f2s ; + psf->read_int = host_read_f2i ; + psf->read_float = host_read_f ; + psf->read_double = host_read_f2d ; + break ; + + case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = host_read_f2s ; + psf->read_int = host_read_f2i ; + psf->read_float = host_read_f ; + psf->read_double = host_read_f2d ; + break ; + + case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = host_read_f2s ; + psf->read_int = host_read_f2i ; + psf->read_float = host_read_f ; + psf->read_double = host_read_f2d ; + break ; + + /* When the CPU is not IEEE compatible. */ + case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = replace_read_f2s ; + psf->read_int = replace_read_f2i ; + psf->read_float = replace_read_f ; + psf->read_double = replace_read_f2d ; + break ; + + case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = replace_read_f2s ; + psf->read_int = replace_read_f2i ; + psf->read_float = replace_read_f ; + psf->read_double = replace_read_f2d ; + break ; + + case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) : + psf->float_endswap = SF_FALSE ; + psf->read_short = replace_read_f2s ; + psf->read_int = replace_read_f2i ; + psf->read_float = replace_read_f ; + psf->read_double = replace_read_f2d ; + break ; + + case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) : + psf->float_endswap = SF_TRUE ; + psf->read_short = replace_read_f2s ; + psf->read_int = replace_read_f2i ; + psf->read_float = replace_read_f ; + psf->read_double = replace_read_f2d ; + break ; + + default : break ; + } ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { switch (psf->endian + float_caps) + { case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = host_write_s2f ; + psf->write_int = host_write_i2f ; + psf->write_float = host_write_f ; + psf->write_double = host_write_d2f ; + break ; + + case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = host_write_s2f ; + psf->write_int = host_write_i2f ; + psf->write_float = host_write_f ; + psf->write_double = host_write_d2f ; + break ; + + case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = host_write_s2f ; + psf->write_int = host_write_i2f ; + psf->write_float = host_write_f ; + psf->write_double = host_write_d2f ; + break ; + + case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = host_write_s2f ; + psf->write_int = host_write_i2f ; + psf->write_float = host_write_f ; + psf->write_double = host_write_d2f ; + break ; + + /* When the CPU is not IEEE compatible. */ + case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = replace_write_s2f ; + psf->write_int = replace_write_i2f ; + psf->write_float = replace_write_f ; + psf->write_double = replace_write_d2f ; + break ; + + case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = replace_write_s2f ; + psf->write_int = replace_write_i2f ; + psf->write_float = replace_write_f ; + psf->write_double = replace_write_d2f ; + break ; + + case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) : + psf->float_endswap = SF_FALSE ; + psf->write_short = replace_write_s2f ; + psf->write_int = replace_write_i2f ; + psf->write_float = replace_write_f ; + psf->write_double = replace_write_d2f ; + break ; + + case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) : + psf->float_endswap = SF_TRUE ; + psf->write_short = replace_write_s2f ; + psf->write_int = replace_write_i2f ; + psf->write_float = replace_write_f ; + psf->write_double = replace_write_d2f ; + break ; + + default : break ; + } ; + } ; + + if (psf->filelength > psf->dataoffset) + { psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset : + psf->filelength - psf->dataoffset ; + } + else + psf->datalength = 0 ; + + psf->sf.frames = psf->datalength / psf->blockwidth ; + + return 0 ; +} /* float32_init */ + +float +float32_be_read (unsigned char *cptr) +{ int exponent, mantissa, negative ; + float fvalue ; + + negative = cptr [0] & 0x80 ; + exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ; + mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ; + + if (! (exponent || mantissa)) + return 0.0 ; + + mantissa |= 0x800000 ; + exponent = exponent ? exponent - 127 : 0 ; + + fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ; + + if (negative) + fvalue *= -1 ; + + if (exponent > 0) + fvalue *= (1 << exponent) ; + else if (exponent < 0) + fvalue /= (1 << abs (exponent)) ; + + return fvalue ; +} /* float32_be_read */ + +float +float32_le_read (unsigned char *cptr) +{ int exponent, mantissa, negative ; + float fvalue ; + + negative = cptr [3] & 0x80 ; + exponent = ((cptr [3] & 0x7F) << 1) | ((cptr [2] & 0x80) ? 1 : 0) ; + mantissa = ((cptr [2] & 0x7F) << 16) | (cptr [1] << 8) | (cptr [0]) ; + + if (! (exponent || mantissa)) + return 0.0 ; + + mantissa |= 0x800000 ; + exponent = exponent ? exponent - 127 : 0 ; + + fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ; + + if (negative) + fvalue *= -1 ; + + if (exponent > 0) + fvalue *= (1 << exponent) ; + else if (exponent < 0) + fvalue /= (1 << abs (exponent)) ; + + return fvalue ; +} /* float32_le_read */ + +void +float32_le_write (float in, unsigned char *out) +{ int exponent, mantissa, negative = 0 ; + + memset (out, 0, sizeof (int)) ; + + if (fabs (in) < 1e-30) + return ; + + if (in < 0.0) + { in *= -1.0 ; + negative = 1 ; + } ; + + in = frexp (in, &exponent) ; + + exponent += 126 ; + + in *= (float) 0x1000000 ; + mantissa = (((int) in) & 0x7FFFFF) ; + + if (negative) + out [3] |= 0x80 ; + + if (exponent & 0x01) + out [2] |= 0x80 ; + + out [0] = mantissa & 0xFF ; + out [1] = (mantissa >> 8) & 0xFF ; + out [2] |= (mantissa >> 16) & 0x7F ; + out [3] |= (exponent >> 1) & 0x7F ; + + return ; +} /* float32_le_write */ + +void +float32_be_write (float in, unsigned char *out) +{ int exponent, mantissa, negative = 0 ; + + memset (out, 0, sizeof (int)) ; + + if (fabs (in) < 1e-30) + return ; + + if (in < 0.0) + { in *= -1.0 ; + negative = 1 ; + } ; + + in = frexp (in, &exponent) ; + + exponent += 126 ; + + in *= (float) 0x1000000 ; + mantissa = (((int) in) & 0x7FFFFF) ; + + if (negative) + out [0] |= 0x80 ; + + if (exponent & 0x01) + out [1] |= 0x80 ; + + out [3] = mantissa & 0xFF ; + out [2] = (mantissa >> 8) & 0xFF ; + out [1] |= (mantissa >> 16) & 0x7F ; + out [0] |= (exponent >> 1) & 0x7F ; + + return ; +} /* float32_be_write */ + +/*============================================================================================== +** Private functions. +*/ + +static void +float32_peak_update (SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx) +{ int chan ; + int k, position ; + float fmaxval ; + + for (chan = 0 ; chan < psf->sf.channels ; chan++) + { fmaxval = fabs (buffer [chan]) ; + position = 0 ; + for (k = chan ; k < count ; k += psf->sf.channels) + if (fmaxval < fabs (buffer [k])) + { fmaxval = fabs (buffer [k]) ; + position = k ; + } ; + + if (fmaxval > psf->peak_info->peaks [chan].value) + { psf->peak_info->peaks [chan].value = fmaxval ; + psf->peak_info->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ; + } ; + } ; + + return ; +} /* float32_peak_update */ + +static int +float32_get_capability (SF_PRIVATE *psf) +{ union + { float f ; + int i ; + unsigned char c [4] ; + } data ; + + data.f = (float) 1.23456789 ; /* Some abitrary value. */ + + if (! psf->ieee_replace) + { /* If this test is true ints and floats are compatible and little endian. */ + if (data.c [0] == 0x52 && data.c [1] == 0x06 && data.c [2] == 0x9e && data.c [3] == 0x3f) + return FLOAT_CAN_RW_LE ; + + /* If this test is true ints and floats are compatible and big endian. */ + if (data.c [3] == 0x52 && data.c [2] == 0x06 && data.c [1] == 0x9e && data.c [0] == 0x3f) + return FLOAT_CAN_RW_BE ; + } ; + + /* Floats are broken. Don't expect reading or writing to be fast. */ + psf_log_printf (psf, "Using IEEE replacement code for float.\n") ; + + return (CPU_IS_LITTLE_ENDIAN) ? FLOAT_BROKEN_LE : FLOAT_BROKEN_BE ; +} /* float32_get_capability */ + +/*======================================================================================= +*/ + +static inline void +f2s_array (const float *src, int count, short *dest, float scale) +{ while (--count >= 0) + { dest [count] = lrintf (scale * src [count]) ; + } ; +} /* f2s_array */ + +static inline void +f2i_array (const float *src, int count, int *dest, float scale) +{ while (--count >= 0) + { dest [count] = lrintf (scale * src [count]) ; + } ; +} /* f2i_array */ + +static inline void +f2d_array (const float *src, int count, double *dest) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; +} /* f2d_array */ + +static inline void +s2f_array (const short *src, float *dest, int count) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; + +} /* s2f_array */ + +static inline void +i2f_array (const int *src, float *dest, int count) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; +} /* i2f_array */ + +static inline void +d2f_array (const double *src, float *dest, int count) +{ while (--count >= 0) + { dest [count] = src [count] ; + } ; +} /* d2f_array */ + +/*---------------------------------------------------------------------------------------------- +*/ + +static sf_count_t +host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float scale ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + +/* Fix me : Need lef2s_array */ + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + f2s_array (psf->u.fbuf, readcount, ptr + total, scale) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* host_read_f2s */ + +static sf_count_t +host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float scale ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + f2i_array (psf->u.fbuf, readcount, ptr + total, scale) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* host_read_f2i */ + +static sf_count_t +host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + if (psf->float_endswap != SF_TRUE) + return psf_fread (ptr, sizeof (float), len, psf) ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + + endswap_int_copy ((int*) (ptr + total), psf->u.ibuf, readcount) ; + + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* host_read_f */ + +static sf_count_t +host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + +/* Fix me : Need lef2d_array */ + f2d_array (psf->u.fbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* host_read_f2d */ + +static sf_count_t +host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2f_array (ptr + total, psf->u.fbuf, bufferlen) ; + + if (psf->peak_info) + float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_s2f */ + +static sf_count_t +host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2f_array (ptr + total, psf->u.fbuf, bufferlen) ; + + if (psf->peak_info) + float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_i2f */ + +static sf_count_t +host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + if (psf->peak_info) + float32_peak_update (psf, ptr, len, 0) ; + + if (psf->float_endswap != SF_TRUE) + return psf_fwrite (ptr, sizeof (float), len, psf) ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + + endswap_int_copy (psf->u.ibuf, (const int*) (ptr + total), bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_f */ + +static sf_count_t +host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + + d2f_array (ptr + total, psf->u.fbuf, bufferlen) ; + + if (psf->peak_info) + float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* host_write_d2f */ + +/*======================================================================================= +*/ + +static sf_count_t +replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float scale ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + bf2f_array (psf->u.fbuf, bufferlen) ; + + f2s_array (psf->u.fbuf, readcount, ptr + total, scale) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_f2s */ + +static sf_count_t +replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float scale ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + bf2f_array (psf->u.fbuf, bufferlen) ; + + f2i_array (psf->u.fbuf, readcount, ptr + total, scale) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_f2i */ + +static sf_count_t +replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + /* FIX THIS */ + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + bf2f_array (psf->u.fbuf, bufferlen) ; + + memcpy (ptr + total, psf->u.fbuf, bufferlen * sizeof (float)) ; + + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_f */ + +static sf_count_t +replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + bf2f_array (psf->u.fbuf, bufferlen) ; + + f2d_array (psf->u.fbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* replace_read_f2d */ + +static sf_count_t +replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2f_array (ptr + total, psf->u.fbuf, bufferlen) ; + + if (psf->peak_info) + float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ; + + f2bf_array (psf->u.fbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_s2f */ + +static sf_count_t +replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2f_array (ptr + total, psf->u.fbuf, bufferlen) ; + + if (psf->peak_info) + float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ; + + f2bf_array (psf->u.fbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_i2f */ + +static sf_count_t +replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + /* FIX THIS */ + if (psf->peak_info) + float32_peak_update (psf, ptr, len, 0) ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + + memcpy (psf->u.fbuf, ptr + total, bufferlen * sizeof (float)) ; + + f2bf_array (psf->u.fbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_f */ + +static sf_count_t +replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.fbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + d2f_array (ptr + total, psf->u.fbuf, bufferlen) ; + + if (psf->peak_info) + float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ; + + f2bf_array (psf->u.fbuf, bufferlen) ; + + if (psf->float_endswap == SF_TRUE) + endswap_int_array (psf->u.ibuf, bufferlen) ; + + writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* replace_write_d2f */ + +/*---------------------------------------------------------------------------------------------- +*/ + +static void +bf2f_array (float *buffer, int count) +{ while (--count >= 0) + { buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ; + } ; +} /* bf2f_array */ + +static void +f2bf_array (float *buffer, int count) +{ while (--count >= 0) + { FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; + } ; +} /* f2bf_array */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: b6c34917-488c-4145-9648-f4371fc4c889 +*/ diff --git a/nylsf/float_cast.h b/nylsf/float_cast.h new file mode 100644 index 0000000..099670a --- /dev/null +++ b/nylsf/float_cast.h @@ -0,0 +1,262 @@ +/* +** Copyright (C) 2001-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* Version 1.4 */ + +#ifndef FLOAT_CAST_HEADER +#define FLOAT_CAST_HEADER + +/*============================================================================ +** On Intel Pentium processors (especially PIII and probably P4), converting +** from float to int is very slow. To meet the C specs, the code produced by +** most C compilers targeting Pentium needs to change the FPU rounding mode +** before the float to int conversion is performed. +** +** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It +** is this flushing of the pipeline which is so slow. +** +** Fortunately the ISO C99 specifications define the functions lrint, lrintf, +** llrint and llrintf which fix this problem as a side effect. +** +** On Unix-like systems, the configure process should have detected the +** presence of these functions. If they weren't found we have to replace them +** here with a standard C cast. +*/ + +/* +** The C99 prototypes for lrint and lrintf are as follows: +** +** long int lrintf (float x) ; +** long int lrint (double x) ; +*/ + +#include "sfconfig.h" + +/* +** The presence of the required functions are detected during the configure +** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in +** the sfconfig.h file. +*/ + +#define HAVE_LRINT_REPLACEMENT 0 + +#if (HAVE_LRINT && HAVE_LRINTF) + + /* + ** These defines enable functionality introduced with the 1999 ISO C + ** standard. They must be defined before the inclusion of math.h to + ** engage them. If optimisation is enabled, these functions will be + ** inlined. With optimisation switched off, you have to link in the + ** maths library using -lm. + */ + + #define _ISOC9X_SOURCE 1 + #define _ISOC99_SOURCE 1 + + #define __USE_ISOC9X 1 + #define __USE_ISOC99 1 + + #include + +#elif (defined (__CYGWIN__)) + + #include + + #undef HAVE_LRINT_REPLACEMENT + #define HAVE_LRINT_REPLACEMENT 1 + + #undef lrint + #undef lrintf + + #define lrint double2int + #define lrintf float2int + + /* + ** The native CYGWIN lrint and lrintf functions are buggy: + ** http://sourceware.org/ml/cygwin/2005-06/msg00153.html + ** http://sourceware.org/ml/cygwin/2005-09/msg00047.html + ** and slow. + ** These functions (pulled from the Public Domain MinGW math.h header) + ** replace the native versions. + */ + + static inline long double2int (double in) + { long retval ; + + __asm__ __volatile__ + ( "fistpl %0" + : "=m" (retval) + : "t" (in) + : "st" + ) ; + + return retval ; + } /* double2int */ + + static inline long float2int (float in) + { long retval ; + + __asm__ __volatile__ + ( "fistpl %0" + : "=m" (retval) + : "t" (in) + : "st" + ) ; + + return retval ; + } /* float2int */ + +#elif (defined (WIN32) || defined (_WIN32)) + + #undef HAVE_LRINT_REPLACEMENT + #define HAVE_LRINT_REPLACEMENT 1 + + #include + + /* + ** Win32 doesn't seem to have these functions. + ** Therefore implement inline versions of these functions here. + */ + + __inline long int + lrint (double flt) + { int intgr ; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + + __inline long int + lrintf (float flt) + { int intgr ; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + +#elif (defined (__MWERKS__) && defined (macintosh)) + + /* This MacOS 9 solution was provided by Stephane Letz */ + + #undef HAVE_LRINT_REPLACEMENT + #define HAVE_LRINT_REPLACEMENT 1 + #include + + #undef lrint + #undef lrintf + + #define lrint double2int + #define lrintf float2int + + inline int + float2int (register float in) + { long res [2] ; + + asm + { fctiw in, in + stfd in, res + } + return res [1] ; + } /* float2int */ + + inline int + double2int (register double in) + { long res [2] ; + + asm + { fctiw in, in + stfd in, res + } + return res [1] ; + } /* double2int */ + +#elif (defined (__MACH__) && defined (__APPLE__)) + + /* For Apple MacOSX. */ + + #undef HAVE_LRINT_REPLACEMENT + #define HAVE_LRINT_REPLACEMENT 1 + #include + + #undef lrint + #undef lrintf + + #define lrint double2int + #define lrintf float2int + + inline static long + float2int (register float in) + { int res [2] ; + + __asm__ __volatile__ + ( "fctiw %1, %1\n\t" + "stfd %1, %0" + : "=m" (res) /* Output */ + : "f" (in) /* Input */ + : "memory" + ) ; + + return res [1] ; + } /* lrintf */ + + inline static long + double2int (register double in) + { int res [2] ; + + __asm__ __volatile__ + ( "fctiw %1, %1\n\t" + "stfd %1, %0" + : "=m" (res) /* Output */ + : "f" (in) /* Input */ + : "memory" + ) ; + + return res [1] ; + } /* lrint */ + +#else + #ifndef __sgi + #warning "Don't have the functions lrint() and lrintf()." + #warning "Replacing these functions with a standard C cast." + #endif + + #include + + #define lrint(dbl) ((long) (dbl)) + #define lrintf(flt) ((long) (flt)) + +#endif + + +#endif /* FLOAT_CAST_HEADER */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 42db1693-ff61-4051-bac1-e4d24c4e30b7 +*/ diff --git a/nylsf/g72x.c b/nylsf/g72x.c new file mode 100644 index 0000000..74ba596 --- /dev/null +++ b/nylsf/g72x.c @@ -0,0 +1,615 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" +#include "G72x/g72x.h" + +/* This struct is private to the G72x code. */ +struct g72x_state ; +typedef struct g72x_state G72x_STATE ; + +typedef struct +{ /* Private data. Don't mess with it. */ + struct g72x_state * private ; + + /* Public data. Read only. */ + int blocksize, samplesperblock, bytesperblock ; + + /* Public data. Read and write. */ + int blocks_total, block_curr, sample_curr ; + unsigned char block [G72x_BLOCK_SIZE] ; + short samples [G72x_BLOCK_SIZE] ; +} G72x_PRIVATE ; + +static int psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ; +static int psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ; + +static sf_count_t g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static sf_count_t g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; + +static int g72x_close (SF_PRIVATE *psf) ; + + +/*============================================================================================ +** WAV G721 Reader initialisation function. +*/ + +int +g72x_init (SF_PRIVATE * psf) +{ G72x_PRIVATE *pg72x ; + int bitspersample, bytesperblock, codec ; + + if (psf->codec_data != NULL) + { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ; + return SFE_INTERNAL ; + } ; + + psf->sf.seekable = SF_FALSE ; + + if (psf->sf.channels != 1) + return SFE_G72X_NOT_MONO ; + + if ((pg72x = calloc (1, sizeof (G72x_PRIVATE))) == NULL) + return SFE_MALLOC_FAILED ; + + psf->codec_data = (void*) pg72x ; + + pg72x->block_curr = 0 ; + pg72x->sample_curr = 0 ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_G721_32 : + codec = G721_32_BITS_PER_SAMPLE ; + bytesperblock = G721_32_BYTES_PER_BLOCK ; + bitspersample = G721_32_BITS_PER_SAMPLE ; + break ; + + case SF_FORMAT_G723_24: + codec = G723_24_BITS_PER_SAMPLE ; + bytesperblock = G723_24_BYTES_PER_BLOCK ; + bitspersample = G723_24_BITS_PER_SAMPLE ; + break ; + + case SF_FORMAT_G723_40: + codec = G723_40_BITS_PER_SAMPLE ; + bytesperblock = G723_40_BYTES_PER_BLOCK ; + bitspersample = G723_40_BITS_PER_SAMPLE ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + psf->blockwidth = psf->bytewidth = 1 ; + + psf->filelength = psf_get_filelen (psf) ; + if (psf->filelength < psf->dataoffset) + psf->filelength = psf->dataoffset ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend > 0) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->mode == SFM_READ) + { pg72x->private = g72x_reader_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ; + if (pg72x->private == NULL) + return SFE_MALLOC_FAILED ; + + pg72x->bytesperblock = bytesperblock ; + + psf->read_short = g72x_read_s ; + psf->read_int = g72x_read_i ; + psf->read_float = g72x_read_f ; + psf->read_double = g72x_read_d ; + + psf->seek = g72x_seek ; + + if (psf->datalength % pg72x->blocksize) + { psf_log_printf (psf, "*** Odd psf->datalength (%D) should be a multiple of %d\n", psf->datalength, pg72x->blocksize) ; + pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ; + } + else + pg72x->blocks_total = psf->datalength / pg72x->blocksize ; + + psf->sf.frames = pg72x->blocks_total * pg72x->samplesperblock ; + + psf_g72x_decode_block (psf, pg72x) ; + } + else if (psf->mode == SFM_WRITE) + { pg72x->private = g72x_writer_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ; + if (pg72x->private == NULL) + return SFE_MALLOC_FAILED ; + + pg72x->bytesperblock = bytesperblock ; + + psf->write_short = g72x_write_s ; + psf->write_int = g72x_write_i ; + psf->write_float = g72x_write_f ; + psf->write_double = g72x_write_d ; + + if (psf->datalength % pg72x->blocksize) + pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ; + else + pg72x->blocks_total = psf->datalength / pg72x->blocksize ; + + if (psf->datalength > 0) + psf->sf.frames = (8 * psf->datalength) / bitspersample ; + + if ((psf->sf.frames * bitspersample) / 8 != psf->datalength) + psf_log_printf (psf, "*** Warning : weird psf->datalength.\n") ; + } ; + + psf->codec_close = g72x_close ; + + return 0 ; +} /* g72x_init */ + +/*============================================================================================ +** G721 Read Functions. +*/ + +static int +psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) +{ int k ; + + pg72x->block_curr ++ ; + pg72x->sample_curr = 0 ; + + if (pg72x->block_curr > pg72x->blocks_total) + { memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ; + return 1 ; + } ; + + if ((k = psf_fread (pg72x->block, 1, pg72x->bytesperblock, psf)) != pg72x->bytesperblock) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pg72x->bytesperblock) ; + + pg72x->blocksize = k ; + g72x_decode_block (pg72x->private, pg72x->block, pg72x->samples) ; + + return 1 ; +} /* psf_g72x_decode_block */ + +static int +g72x_read_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { if (pg72x->block_curr > pg72x->blocks_total) + { memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ; + return total ; + } ; + + if (pg72x->sample_curr >= pg72x->samplesperblock) + psf_g72x_decode_block (psf, pg72x) ; + + count = pg72x->samplesperblock - pg72x->sample_curr ; + count = (len - indx > count) ? count : len - indx ; + + memcpy (&(ptr [indx]), &(pg72x->samples [pg72x->sample_curr]), count * sizeof (short)) ; + indx += count ; + pg72x->sample_curr += count ; + total = indx ; + } ; + + return total ; +} /* g72x_read_block */ + +static sf_count_t +g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + int readcount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + while (len > 0) + { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = g72x_read_block (psf, pg72x, ptr, readcount) ; + + total += count ; + len -= count ; + + if (count != readcount) + break ; + } ; + + return total ; +} /* g72x_read_s */ + +static sf_count_t +g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = SF_BUFFER_LEN / sizeof (short) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = g72x_read_block (psf, pg72x, sptr, readcount) ; + + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = sptr [k] << 16 ; + + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* g72x_read_i */ + +static sf_count_t +g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = SF_BUFFER_LEN / sizeof (short) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = g72x_read_block (psf, pg72x, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * sptr [k] ; + + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* g72x_read_f */ + +static sf_count_t +g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = SF_BUFFER_LEN / sizeof (short) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = g72x_read_block (psf, pg72x, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (double) (sptr [k]) ; + + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* g72x_read_d */ + +static sf_count_t +g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ + /* Prevent compiler warnings. */ + mode ++ ; + offset ++ ; + + psf_log_printf (psf, "seek unsupported\n") ; + + /* No simple solution. To do properly, would need to seek + ** to start of file and decode everything up to seek position. + ** Maybe implement SEEK_SET to 0 only? + */ + return 0 ; + +/* +** G72x_PRIVATE *pg72x ; +** int newblock, newsample, sample_curr ; +** +** if (psf->codec_data == NULL) +** return 0 ; +** pg72x = (G72x_PRIVATE*) psf->codec_data ; +** +** if (! (psf->datalength && psf->dataoffset)) +** { psf->error = SFE_BAD_SEEK ; +** return PSF_SEEK_ERROR ; +** } ; +** +** sample_curr = (8 * psf->datalength) / G721_32_BITS_PER_SAMPLE ; +** +** switch (whence) +** { case SEEK_SET : +** if (offset < 0 || offset > sample_curr) +** { psf->error = SFE_BAD_SEEK ; +** return PSF_SEEK_ERROR ; +** } ; +** newblock = offset / pg72x->samplesperblock ; +** newsample = offset % pg72x->samplesperblock ; +** break ; +** +** case SEEK_CUR : +** if (psf->current + offset < 0 || psf->current + offset > sample_curr) +** { psf->error = SFE_BAD_SEEK ; +** return PSF_SEEK_ERROR ; +** } ; +** newblock = (8 * (psf->current + offset)) / pg72x->samplesperblock ; +** newsample = (8 * (psf->current + offset)) % pg72x->samplesperblock ; +** break ; +** +** case SEEK_END : +** if (offset > 0 || sample_curr + offset < 0) +** { psf->error = SFE_BAD_SEEK ; +** return PSF_SEEK_ERROR ; +** } ; +** newblock = (sample_curr + offset) / pg72x->samplesperblock ; +** newsample = (sample_curr + offset) % pg72x->samplesperblock ; +** break ; +** +** default : +** psf->error = SFE_BAD_SEEK ; +** return PSF_SEEK_ERROR ; +** } ; +** +** if (psf->mode == SFM_READ) +** { psf_fseek (psf, psf->dataoffset + newblock * pg72x->blocksize, SEEK_SET) ; +** pg72x->block_curr = newblock ; +** psf_g72x_decode_block (psf, pg72x) ; +** pg72x->sample_curr = newsample ; +** } +** else +** { /+* What to do about write??? *+/ +** psf->error = SFE_BAD_SEEK ; +** return PSF_SEEK_ERROR ; +** } ; +** +** psf->current = newblock * pg72x->samplesperblock + newsample ; +** return psf->current ; +** +*/ +} /* g72x_seek */ + +/*========================================================================================== +** G72x Write Functions. +*/ + +static int +psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) +{ int k ; + + /* Encode the samples. */ + g72x_encode_block (pg72x->private, pg72x->samples, pg72x->block) ; + + /* Write the block to disk. */ + if ((k = psf_fwrite (pg72x->block, 1, pg72x->blocksize, psf)) != pg72x->blocksize) + psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pg72x->blocksize) ; + + pg72x->sample_curr = 0 ; + pg72x->block_curr ++ ; + + /* Set samples to zero for next block. */ + memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ; + + return 1 ; +} /* psf_g72x_encode_block */ + +static int +g72x_write_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, const short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { count = pg72x->samplesperblock - pg72x->sample_curr ; + + if (count > len - indx) + count = len - indx ; + + memcpy (&(pg72x->samples [pg72x->sample_curr]), &(ptr [indx]), count * sizeof (short)) ; + indx += count ; + pg72x->sample_curr += count ; + total = indx ; + + if (pg72x->sample_curr >= pg72x->samplesperblock) + psf_g72x_encode_block (psf, pg72x) ; + } ; + + return total ; +} /* g72x_write_block */ + +static sf_count_t +g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + int writecount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + while (len > 0) + { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = g72x_write_block (psf, pg72x, ptr, writecount) ; + + total += count ; + len -= count ; + if (count != writecount) + break ; + } ; + + return total ; +} /* g72x_write_s */ + +static sf_count_t +g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + short *sptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = ptr [total + k] >> 16 ; + count = g72x_write_block (psf, pg72x, sptr, writecount) ; + + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + return total ; +} /* g72x_write_i */ + +static sf_count_t +g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + short *sptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrintf (normfact * ptr [total + k]) ; + count = g72x_write_block (psf, pg72x, sptr, writecount) ; + + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* g72x_write_f */ + +static sf_count_t +g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ G72x_PRIVATE *pg72x ; + short *sptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->codec_data == NULL) + return 0 ; + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrint (normfact * ptr [total + k]) ; + count = g72x_write_block (psf, pg72x, sptr, writecount) ; + + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* g72x_write_d */ + +static int +g72x_close (SF_PRIVATE *psf) +{ G72x_PRIVATE *pg72x ; + + pg72x = (G72x_PRIVATE*) psf->codec_data ; + + if (psf->mode == SFM_WRITE) + { /* If a block has been partially assembled, write it out + ** as the final block. + */ + + if (pg72x->sample_curr && pg72x->sample_curr < G72x_BLOCK_SIZE) + psf_g72x_encode_block (psf, pg72x) ; + + if (psf->write_header) + psf->write_header (psf, SF_FALSE) ; + } ; + + /* Only free the pointer allocated by g72x_(reader|writer)_init. */ + free (pg72x->private) ; + + return 0 ; +} /* g72x_close */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 3cc5439e-7247-486b-b2e6-11a4affa5744 +*/ diff --git a/nylsf/gsm610.c b/nylsf/gsm610.c new file mode 100644 index 0000000..73c5ad1 --- /dev/null +++ b/nylsf/gsm610.c @@ -0,0 +1,628 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" +#include "wav_w64.h" +#include "GSM610/gsm.h" + +#define GSM610_BLOCKSIZE 33 +#define GSM610_SAMPLES 160 + +typedef struct gsm610_tag +{ int blocks ; + int blockcount, samplecount ; + int samplesperblock, blocksize ; + + int (*decode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ; + int (*encode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ; + + short samples [WAV_W64_GSM610_SAMPLES] ; + unsigned char block [WAV_W64_GSM610_BLOCKSIZE] ; + + /* Damn I hate typedef-ed pointers; yes, gsm is a pointer type. */ + gsm gsm_data ; +} GSM610_PRIVATE ; + +static sf_count_t gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static int gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) ; +static int gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len) ; + +static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; +static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; + +static int gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; +static int gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; + +static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; + +static int gsm610_close (SF_PRIVATE *psf) ; + +/*============================================================================================ +** WAV GSM610 initialisation function. +*/ + +int +gsm610_init (SF_PRIVATE *psf) +{ GSM610_PRIVATE *pgsm610 ; + int true_flag = 1 ; + + if (psf->codec_data != NULL) + { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ; + return SFE_INTERNAL ; + } ; + + if (psf->mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + psf->sf.seekable = SF_FALSE ; + + if ((pgsm610 = calloc (1, sizeof (GSM610_PRIVATE))) == NULL) + return SFE_MALLOC_FAILED ; + + psf->codec_data = pgsm610 ; + + memset (pgsm610, 0, sizeof (GSM610_PRIVATE)) ; + +/*============================================================ + +Need separate gsm_data structs for encode and decode. + +============================================================*/ + + if ((pgsm610->gsm_data = gsm_create ()) == NULL) + return SFE_MALLOC_FAILED ; + + switch (psf->sf.format & SF_FORMAT_TYPEMASK) + { case SF_FORMAT_WAV : + case SF_FORMAT_WAVEX : + case SF_FORMAT_W64 : + gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ; + + pgsm610->encode_block = gsm610_wav_encode_block ; + pgsm610->decode_block = gsm610_wav_decode_block ; + + pgsm610->samplesperblock = WAV_W64_GSM610_SAMPLES ; + pgsm610->blocksize = WAV_W64_GSM610_BLOCKSIZE ; + break ; + + case SF_FORMAT_AIFF : + case SF_FORMAT_RAW : + pgsm610->encode_block = gsm610_encode_block ; + pgsm610->decode_block = gsm610_decode_block ; + + pgsm610->samplesperblock = GSM610_SAMPLES ; + pgsm610->blocksize = GSM610_BLOCKSIZE ; + break ; + + default : + return SFE_INTERNAL ; + break ; + } ; + + if (psf->mode == SFM_READ) + { if (psf->datalength % pgsm610->blocksize == 0) + pgsm610->blocks = psf->datalength / pgsm610->blocksize ; + else if (psf->datalength % pgsm610->blocksize == 1 && pgsm610->blocksize == GSM610_BLOCKSIZE) + { /* + ** Weird AIFF specific case. + ** AIFF chunks must be at an even offset from the start of file and + ** GSM610_BLOCKSIZE is odd which can result in an odd length SSND + ** chunk. The SSND chunk then gets padded on write which means that + ** when it is read the datalength is too big by 1. + */ + pgsm610->blocks = psf->datalength / pgsm610->blocksize ; + } + else + { psf_log_printf (psf, "*** Warning : data chunk seems to be truncated.\n") ; + pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ; + } ; + + psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ; + + pgsm610->decode_block (psf, pgsm610) ; /* Read first block. */ + + psf->read_short = gsm610_read_s ; + psf->read_int = gsm610_read_i ; + psf->read_float = gsm610_read_f ; + psf->read_double = gsm610_read_d ; + } ; + + if (psf->mode == SFM_WRITE) + { pgsm610->blockcount = 0 ; + pgsm610->samplecount = 0 ; + + psf->write_short = gsm610_write_s ; + psf->write_int = gsm610_write_i ; + psf->write_float = gsm610_write_f ; + psf->write_double = gsm610_write_d ; + } ; + + psf->codec_close = gsm610_close ; + + psf->seek = gsm610_seek ; + + psf->filelength = psf_get_filelen (psf) ; + psf->datalength = psf->filelength - psf->dataoffset ; + + return 0 ; +} /* gsm610_init */ + +/*============================================================================================ +** GSM 6.10 Read Functions. +*/ + +static int +gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) +{ int k ; + + pgsm610->blockcount ++ ; + pgsm610->samplecount = 0 ; + + if (pgsm610->blockcount > pgsm610->blocks) + { memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ; + return 1 ; + } ; + + if ((k = psf_fread (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ; + + if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) + { psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ; + return 0 ; + } ; + + if (gsm_decode (pgsm610->gsm_data, pgsm610->block + (WAV_W64_GSM610_BLOCKSIZE + 1) / 2, pgsm610->samples + WAV_W64_GSM610_SAMPLES / 2) < 0) + { psf_log_printf (psf, "Error from gsm_decode() on frame : %d.5\n", pgsm610->blockcount) ; + return 0 ; + } ; + + return 1 ; +} /* gsm610_wav_decode_block */ + +static int +gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) +{ int k ; + + pgsm610->blockcount ++ ; + pgsm610->samplecount = 0 ; + + if (pgsm610->blockcount > pgsm610->blocks) + { memset (pgsm610->samples, 0, GSM610_SAMPLES * sizeof (short)) ; + return 1 ; + } ; + + if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ; + + if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) + { psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ; + return 0 ; + } ; + + return 1 ; +} /* gsm610_decode_block */ + +static int +gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { if (pgsm610->blockcount >= pgsm610->blocks && pgsm610->samplecount >= pgsm610->samplesperblock) + { memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ; + return total ; + } ; + + if (pgsm610->samplecount >= pgsm610->samplesperblock) + pgsm610->decode_block (psf, pgsm610) ; + + count = pgsm610->samplesperblock - pgsm610->samplecount ; + count = (len - indx > count) ? count : len - indx ; + + memcpy (&(ptr [indx]), &(pgsm610->samples [pgsm610->samplecount]), count * sizeof (short)) ; + indx += count ; + pgsm610->samplecount += count ; + total = indx ; + } ; + + return total ; +} /* gsm610_read_block */ + +static sf_count_t +gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + int readcount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + while (len > 0) + { readcount = (len > 0x10000000) ? 0x1000000 : (int) len ; + + count = gsm610_read_block (psf, pgsm610, ptr, readcount) ; + + total += count ; + len -= count ; + + if (count != readcount) + break ; + } ; + + return total ; +} /* gsm610_read_s */ + +static sf_count_t +gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = sptr [k] << 16 ; + + total += count ; + len -= readcount ; + } ; + return total ; +} /* gsm610_read_i */ + +static sf_count_t +gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * sptr [k] ; + + total += count ; + len -= readcount ; + } ; + return total ; +} /* gsm610_read_f */ + +static sf_count_t +gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * sptr [k] ; + + total += count ; + len -= readcount ; + } ; + return total ; +} /* gsm610_read_d */ + +static sf_count_t +gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ GSM610_PRIVATE *pgsm610 ; + int newblock, newsample ; + + mode = mode ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + if (psf->dataoffset < 0) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (offset == 0) + { int true_flag = 1 ; + + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + pgsm610->blockcount = 0 ; + + gsm_init (pgsm610->gsm_data) ; + if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV || + (psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_W64) + gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ; + + pgsm610->decode_block (psf, pgsm610) ; + pgsm610->samplecount = 0 ; + return 0 ; + } ; + + if (offset < 0 || offset > pgsm610->blocks * pgsm610->samplesperblock) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + newblock = offset / pgsm610->samplesperblock ; + newsample = offset % pgsm610->samplesperblock ; + + if (psf->mode == SFM_READ) + { if (psf->read_current != newblock * pgsm610->samplesperblock + newsample) + { psf_fseek (psf, psf->dataoffset + newblock * pgsm610->samplesperblock, SEEK_SET) ; + pgsm610->blockcount = newblock ; + pgsm610->decode_block (psf, pgsm610) ; + pgsm610->samplecount = newsample ; + } ; + + return newblock * pgsm610->samplesperblock + newsample ; + } ; + + /* What to do about write??? */ + psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; +} /* gsm610_seek */ + +/*========================================================================================== +** GSM 6.10 Write Functions. +*/ + +static int +gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) +{ int k ; + + /* Encode the samples. */ + gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; + + /* Write the block to disk. */ + if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) + psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ; + + pgsm610->samplecount = 0 ; + pgsm610->blockcount ++ ; + + /* Set samples to zero for next block. */ + memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ; + + return 1 ; +} /* gsm610_encode_block */ + +static int +gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) +{ int k ; + + /* Encode the samples. */ + gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; + gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAV_W64_GSM610_SAMPLES/2, pgsm610->block+WAV_W64_GSM610_BLOCKSIZE/2) ; + + /* Write the block to disk. */ + if ((k = psf_fwrite (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE) + psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ; + + pgsm610->samplecount = 0 ; + pgsm610->blockcount ++ ; + + /* Set samples to zero for next block. */ + memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ; + + return 1 ; +} /* gsm610_wav_encode_block */ + +static int +gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { count = pgsm610->samplesperblock - pgsm610->samplecount ; + + if (count > len - indx) + count = len - indx ; + + memcpy (&(pgsm610->samples [pgsm610->samplecount]), &(ptr [indx]), count * sizeof (short)) ; + indx += count ; + pgsm610->samplecount += count ; + total = indx ; + + if (pgsm610->samplecount >= pgsm610->samplesperblock) + pgsm610->encode_block (psf, pgsm610) ; + } ; + + return total ; +} /* gsm610_write_block */ + +static sf_count_t +gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + int writecount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + while (len > 0) + { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = gsm610_write_block (psf, pgsm610, ptr, writecount) ; + + total += count ; + len -= count ; + + if (count != writecount) + break ; + } ; + + return total ; +} /* gsm610_write_s */ + +static sf_count_t +gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + short *sptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = ptr [total + k] >> 16 ; + count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; + + total += count ; + len -= writecount ; + } ; + return total ; +} /* gsm610_write_i */ + +static sf_count_t +gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + short *sptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrintf (normfact * ptr [total + k]) ; + count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; + + total += count ; + len -= writecount ; + } ; + return total ; +} /* gsm610_write_f */ + +static sf_count_t +gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ GSM610_PRIVATE *pgsm610 ; + short *sptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->codec_data == NULL) + return 0 ; + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrint (normfact * ptr [total + k]) ; + count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; + + total += count ; + len -= writecount ; + } ; + return total ; +} /* gsm610_write_d */ + +static int +gsm610_close (SF_PRIVATE *psf) +{ GSM610_PRIVATE *pgsm610 ; + + if (psf->codec_data == NULL) + return 0 ; + + pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; + + if (psf->mode == SFM_WRITE) + { /* If a block has been partially assembled, write it out + ** as the final block. + */ + + if (pgsm610->samplecount && pgsm610->samplecount < pgsm610->samplesperblock) + pgsm610->encode_block (psf, pgsm610) ; + } ; + + if (pgsm610->gsm_data) + gsm_destroy (pgsm610->gsm_data) ; + + return 0 ; +} /* gsm610_close */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 8575187d-af4f-4acf-b9dd-6ff705628345 +*/ diff --git a/nylsf/htk.c b/nylsf/htk.c new file mode 100644 index 0000000..716868b --- /dev/null +++ b/nylsf/htk.c @@ -0,0 +1,225 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define SFE_HTK_BAD_FILE_LEN 1666 +#define SFE_HTK_NOT_WAVEFORM 1667 + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int htk_close (SF_PRIVATE *psf) ; + +static int htk_write_header (SF_PRIVATE *psf, int calc_length) ; +static int htk_read_header (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +htk_open (SF_PRIVATE *psf) +{ int subformat ; + int error = 0 ; + + if (psf->is_pipe) + return SFE_HTK_NO_PIPE ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = htk_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_HTK) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = SF_ENDIAN_BIG ; + + if (htk_write_header (psf, SF_FALSE)) + return psf->error ; + + psf->write_header = htk_write_header ; + } ; + + psf->container_close = htk_close ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ + error = pcm_init (psf) ; + break ; + + default : break ; + } ; + + return error ; +} /* htk_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +htk_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + htk_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* htk_close */ + +static int +htk_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + int sample_count, sample_period ; + + current = psf_ftell (psf) ; + + if (calc_length) + psf->filelength = psf_get_filelen (psf) ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + if (psf->filelength > 12) + sample_count = (psf->filelength - 12) / 2 ; + else + sample_count = 0 ; + + sample_period = 10000000 / psf->sf.samplerate ; + + psf_binheader_writef (psf, "E444", sample_count, sample_period, 0x20000) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* htk_write_header */ + +/* +** Found the following info in a comment block within Bill Schottstaedt's +** sndlib library. +** +** HTK format files consist of a contiguous sequence of samples preceded by a +** header. Each sample is a vector of either 2-byte integers or 4-byte floats. +** 2-byte integers are used for compressed forms as described below and for +** vector quantised data as described later in section 5.11. HTK format data +** files can also be used to store speech waveforms as described in section 5.8. +** +** The HTK file format header is 12 bytes long and contains the following data +** nSamples -- number of samples in file (4-byte integer) +** sampPeriod -- sample period in 100ns units (4-byte integer) +** sampSize -- number of bytes per sample (2-byte integer) +** parmKind -- a code indicating the sample kind (2-byte integer) +** +** The parameter kind consists of a 6 bit code representing the basic +** parameter kind plus additional bits for each of the possible qualifiers. +** The basic parameter kind codes are +** +** 0 WAVEFORM sampled waveform +** 1 LPC linear prediction filter coefficients +** 2 LPREFC linear prediction reflection coefficients +** 3 LPCEPSTRA LPC cepstral coefficients +** 4 LPDELCEP LPC cepstra plus delta coefficients +** 5 IREFC LPC reflection coef in 16 bit integer format +** 6 MFCC mel-frequency cepstral coefficients +** 7 FBANK log mel-filter bank channel outputs +** 8 MELSPEC linear mel-filter bank channel outputs +** 9 USER user defined sample kind +** 10 DISCRETE vector quantised data +** +** and the bit-encoding for the qualifiers (in octal) is +** _E 000100 has energy +** _N 000200 absolute energy suppressed +** _D 000400 has delta coefficients +** _A 001000 has acceleration coefficients +** _C 002000 is compressed +** _Z 004000 has zero mean static coef. +** _K 010000 has CRC checksum +** _O 020000 has 0'th cepstral coef. +*/ + +static int +htk_read_header (SF_PRIVATE *psf) +{ int sample_count, sample_period, marker ; + + psf_binheader_readf (psf, "pE444", 0, &sample_count, &sample_period, &marker) ; + + if (2 * sample_count + 12 != psf->filelength) + return SFE_HTK_BAD_FILE_LEN ; + + if (marker != 0x20000) + return SFE_HTK_NOT_WAVEFORM ; + + psf->sf.channels = 1 ; + psf->sf.samplerate = 10000000 / sample_period ; + + psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d => %d Hz\n", + sample_count, sample_period, psf->sf.samplerate) ; + + psf->sf.format = SF_FORMAT_HTK | SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + + /* HTK always has a 12 byte header. */ + psf->dataoffset = 12 ; + psf->endian = SF_ENDIAN_BIG ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + if (! psf->sf.frames && psf->blockwidth) + psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; + + return 0 ; +} /* htk_read_header */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: c350e972-082e-4c20-8934-03391a723560 +*/ diff --git a/nylsf/ima_adpcm.c b/nylsf/ima_adpcm.c new file mode 100644 index 0000000..49ffabe --- /dev/null +++ b/nylsf/ima_adpcm.c @@ -0,0 +1,976 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" + +typedef struct IMA_ADPCM_PRIVATE_tag +{ int (*decode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ; + int (*encode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ; + + int channels, blocksize, samplesperblock, blocks ; + int blockcount, samplecount ; + int previous [2] ; + int stepindx [2] ; + unsigned char *block ; + short *samples ; +#if HAVE_FLEXIBLE_ARRAY + short data [] ; /* ISO C99 struct flexible array. */ +#else + short data [0] ; /* This is a hack and might not work. */ +#endif +} IMA_ADPCM_PRIVATE ; + +/*============================================================================================ +** Predefined IMA ADPCM data. +*/ + +static int ima_indx_adjust [16] = +{ -1, -1, -1, -1, /* +0 - +3, decrease the step size */ + 2, 4, 6, 8, /* +4 - +7, increase the step size */ + -1, -1, -1, -1, /* -0 - -3, decrease the step size */ + 2, 4, 6, 8, /* -4 - -7, increase the step size */ +} ; + +static int ima_step_size [89] = +{ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, + 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, + 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, + 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, + 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767 +} ; + +static int ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; +static int ima_writer_init (SF_PRIVATE *psf, int blockalign) ; + +static int ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) ; +static int ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len) ; + +static sf_count_t ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static sf_count_t ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; + +static int ima_close (SF_PRIVATE *psf) ; + +static int wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; +static int wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; + +/*-static int aiff_ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;-*/ +static int aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; +static int aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; + + +/*============================================================================================ +** IMA ADPCM Reader initialisation function. +*/ + +int +wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) +{ int error ; + + if (psf->codec_data != NULL) + { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ; + return SFE_INTERNAL ; + } ; + + if (psf->mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + if (psf->mode == SFM_READ) + if ((error = ima_reader_init (psf, blockalign, samplesperblock))) + return error ; + + if (psf->mode == SFM_WRITE) + if ((error = ima_writer_init (psf, blockalign))) + return error ; + + psf->codec_close = ima_close ; + psf->seek = ima_seek ; + + return 0 ; +} /* wav_w64_ima_init */ + +int +aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) +{ int error ; + + if (psf->mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + if (psf->mode == SFM_READ) + if ((error = ima_reader_init (psf, blockalign, samplesperblock))) + return error ; + + if (psf->mode == SFM_WRITE) + if ((error = ima_writer_init (psf, blockalign))) + return error ; + + psf->codec_close = ima_close ; + + return 0 ; +} /* aiff_ima_init */ + +static int +ima_close (SF_PRIVATE *psf) +{ IMA_ADPCM_PRIVATE *pima ; + + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + if (psf->mode == SFM_WRITE) + { /* If a block has been partially assembled, write it out + ** as the final block. + */ + if (pima->samplecount && pima->samplecount < pima->samplesperblock) + pima->encode_block (psf, pima) ; + + psf->sf.frames = pima->samplesperblock * pima->blockcount / psf->sf.channels ; + } ; + + return 0 ; +} /* ima_close */ + +/*============================================================================================ +** IMA ADPCM Read Functions. +*/ + +static int +ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) +{ IMA_ADPCM_PRIVATE *pima ; + int pimasize, count ; + + if (psf->mode != SFM_READ) + return SFE_BAD_MODE_RW ; + + pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ; + + if (! (pima = malloc (pimasize))) + return SFE_MALLOC_FAILED ; + + psf->codec_data = (void*) pima ; + + memset (pima, 0, pimasize) ; + + pima->samples = pima->data ; + pima->block = (unsigned char*) (pima->data + samplesperblock * psf->sf.channels) ; + + pima->channels = psf->sf.channels ; + pima->blocksize = blockalign ; + pima->samplesperblock = samplesperblock ; + + psf->filelength = psf_get_filelen (psf) ; + psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : + psf->filelength - psf->dataoffset ; + + if (psf->datalength % pima->blocksize) + pima->blocks = psf->datalength / pima->blocksize + 1 ; + else + pima->blocks = psf->datalength / pima->blocksize ; + + switch (psf->sf.format & SF_FORMAT_TYPEMASK) + { case SF_FORMAT_WAV : + case SF_FORMAT_W64 : + count = 2 * (pima->blocksize - 4 * pima->channels) / pima->channels + 1 ; + + if (pima->samplesperblock != count) + psf_log_printf (psf, "*** Warning : samplesperblock should be %d.\n", count) ; + + pima->decode_block = wav_w64_ima_decode_block ; + + psf->sf.frames = pima->samplesperblock * pima->blocks ; + break ; + + case SF_FORMAT_AIFF : + psf_log_printf (psf, "still need to check block count\n") ; + pima->decode_block = aiff_ima_decode_block ; + psf->sf.frames = pima->samplesperblock * pima->blocks / pima->channels ; + break ; + + default : + psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ; + return SFE_INTERNAL ; + break ; + } ; + + pima->decode_block (psf, pima) ; /* Read first block. */ + + psf->read_short = ima_read_s ; + psf->read_int = ima_read_i ; + psf->read_float = ima_read_f ; + psf->read_double = ima_read_d ; + + return 0 ; +} /* ima_reader_init */ + +static int +aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) +{ unsigned char *blockdata ; + int chan, k, diff, bytecode ; + short step, stepindx, predictor, *sampledata ; + +static int count = 0 ; +count ++ ; + + pima->blockcount += pima->channels ; + pima->samplecount = 0 ; + + if (pima->blockcount > pima->blocks) + { memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ; + return 1 ; + } ; + + if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; + + /* Read and check the block header. */ + for (chan = 0 ; chan < pima->channels ; chan++) + { blockdata = pima->block + chan * 34 ; + sampledata = pima->samples + chan ; + + predictor = (blockdata [0] << 8) | (blockdata [1] & 0x80) ; + stepindx = blockdata [1] & 0x7F ; + +{ +if (count < 5) +printf ("\nchan: %d predictor: %d stepindx: %d (%d)\n", + chan, predictor, stepindx, ima_step_size [stepindx]) ; +} + /* FIXME : Do this a better way. */ + if (stepindx < 0) stepindx = 0 ; + else if (stepindx > 88) stepindx = 88 ; + + /* + ** Pull apart the packed 4 bit samples and store them in their + ** correct sample positions. + */ + for (k = 0 ; k < pima->blocksize - 2 ; k++) + { bytecode = blockdata [k + 2] ; + sampledata [pima->channels * (2 * k + 0)] = bytecode & 0xF ; + sampledata [pima->channels * (2 * k + 1)] = (bytecode >> 4) & 0xF ; + } ; + + /* Decode the encoded 4 bit samples. */ + for (k = 0 ; k < pima->samplesperblock ; k ++) + { step = ima_step_size [stepindx] ; + + bytecode = pima->samples [pima->channels * k + chan] ; + + stepindx += ima_indx_adjust [bytecode] ; + + if (stepindx < 0) stepindx = 0 ; + else if (stepindx > 88) stepindx = 88 ; + + diff = step >> 3 ; + if (bytecode & 1) diff += step >> 2 ; + if (bytecode & 2) diff += step >> 1 ; + if (bytecode & 4) diff += step ; + if (bytecode & 8) diff = -diff ; + + predictor += diff ; + + pima->samples [pima->channels * k + chan] = predictor ; + } ; + } ; + +if (count < 5) +{ + for (k = 0 ; k < 10 ; k++) + printf ("% 7d,", pima->samples [k]) ; + puts ("") ; +} + + return 1 ; +} /* aiff_ima_decode_block */ + +static int +aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) +{ int chan, k, step, diff, vpdiff, blockindx, indx ; + short bytecode, mask ; + +static int count = 0 ; +if (0 && count == 0) +{ pima->samples [0] = 0 ; + printf ("blocksize : %d\n", pima->blocksize) ; + printf ("pima->stepindx [0] : %d\n", pima->stepindx [0]) ; + } +count ++ ; + + /* Encode the block header. */ + for (chan = 0 ; chan < pima->channels ; chan ++) + { blockindx = chan * pima->blocksize ; + + pima->block [blockindx] = (pima->samples [chan] >> 8) & 0xFF ; + pima->block [blockindx + 1] = (pima->samples [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ; + + pima->previous [chan] = pima->samples [chan] ; + } ; + + /* Encode second and later samples for every block as a 4 bit value. */ + for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) + { chan = (pima->channels > 1) ? (k % 2) : 0 ; + + diff = pima->samples [k] - pima->previous [chan] ; + + bytecode = 0 ; + step = ima_step_size [pima->stepindx [chan]] ; + vpdiff = step >> 3 ; + if (diff < 0) + { bytecode = 8 ; + diff = -diff ; + } ; + mask = 4 ; + while (mask) + { if (diff >= step) + { bytecode |= mask ; + diff -= step ; + vpdiff += step ; + } ; + step >>= 1 ; + mask >>= 1 ; + } ; + + if (bytecode & 8) + pima->previous [chan] -= vpdiff ; + else + pima->previous [chan] += vpdiff ; + + if (pima->previous [chan] > 32767) + pima->previous [chan] = 32767 ; + else if (pima->previous [chan] < -32768) + pima->previous [chan] = -32768 ; + + pima->stepindx [chan] += ima_indx_adjust [bytecode] ; + if (pima->stepindx [chan] < 0) + pima->stepindx [chan] = 0 ; + else if (pima->stepindx [chan] > 88) + pima->stepindx [chan] = 88 ; + + pima->samples [k] = bytecode ; + } ; + + /* Pack the 4 bit encoded samples. */ + + for (chan = 0 ; chan < pima->channels ; chan ++) + { for (indx = pima->channels ; indx < pima->channels * pima->samplesperblock ; indx += 2 * pima->channels) + { blockindx = chan * pima->blocksize + 2 + indx / 2 ; + +if (0 && count ++ < 5) + printf ("chan: %d blockindx: %3d indx: %3d\n", chan, blockindx, indx) ; + + pima->block [blockindx] = pima->samples [indx] & 0x0F ; + pima->block [blockindx] |= (pima->samples [indx + pima->channels] << 4) & 0xF0 ; + } ; + } ; + + /* Write the block to disk. */ + + if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize) + psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ; + + memset (pima->samples, 0, pima->channels * pima->samplesperblock * sizeof (short)) ; + pima->samplecount = 0 ; + pima->blockcount ++ ; + + return 1 ; +} /* aiff_ima_encode_block */ + +static int +wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) +{ int chan, k, current, blockindx, indx, indxstart, diff ; + short step, bytecode, stepindx [2] ; + + pima->blockcount ++ ; + pima->samplecount = 0 ; + + if (pima->blockcount > pima->blocks) + { memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ; + return 1 ; + } ; + + if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; + + /* Read and check the block header. */ + + for (chan = 0 ; chan < pima->channels ; chan++) + { current = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ; + if (current & 0x8000) + current -= 0x10000 ; + + stepindx [chan] = pima->block [chan*4+2] ; + if (stepindx [chan] < 0) + stepindx [chan] = 0 ; + else if (stepindx [chan] > 88) + stepindx [chan] = 88 ; + + if (pima->block [chan*4+3] != 0) + psf_log_printf (psf, "IMA ADPCM synchronisation error.\n") ; + + pima->samples [chan] = current ; + } ; + + /* + ** Pull apart the packed 4 bit samples and store them in their + ** correct sample positions. + */ + + blockindx = 4 * pima->channels ; + + indxstart = pima->channels ; + while (blockindx < pima->blocksize) + { for (chan = 0 ; chan < pima->channels ; chan++) + { indx = indxstart + chan ; + for (k = 0 ; k < 4 ; k++) + { bytecode = pima->block [blockindx++] ; + pima->samples [indx] = bytecode & 0x0F ; + indx += pima->channels ; + pima->samples [indx] = (bytecode >> 4) & 0x0F ; + indx += pima->channels ; + } ; + } ; + indxstart += 8 * pima->channels ; + } ; + + /* Decode the encoded 4 bit samples. */ + + for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) + { chan = (pima->channels > 1) ? (k % 2) : 0 ; + + bytecode = pima->samples [k] & 0xF ; + + step = ima_step_size [stepindx [chan]] ; + current = pima->samples [k - pima->channels] ; + + diff = step >> 3 ; + if (bytecode & 1) + diff += step >> 2 ; + if (bytecode & 2) + diff += step >> 1 ; + if (bytecode & 4) + diff += step ; + if (bytecode & 8) + diff = -diff ; + + current += diff ; + + if (current > 32767) + current = 32767 ; + else if (current < -32768) + current = -32768 ; + + stepindx [chan] += ima_indx_adjust [bytecode] ; + + if (stepindx [chan] < 0) + stepindx [chan] = 0 ; + else if (stepindx [chan] > 88) + stepindx [chan] = 88 ; + + pima->samples [k] = current ; + } ; + + return 1 ; +} /* wav_w64_ima_decode_block */ + +static int +wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) +{ int chan, k, step, diff, vpdiff, blockindx, indx, indxstart ; + short bytecode, mask ; + + /* Encode the block header. */ + for (chan = 0 ; chan < pima->channels ; chan++) + { pima->block [chan*4] = pima->samples [chan] & 0xFF ; + pima->block [chan*4+1] = (pima->samples [chan] >> 8) & 0xFF ; + + pima->block [chan*4+2] = pima->stepindx [chan] ; + pima->block [chan*4+3] = 0 ; + + pima->previous [chan] = pima->samples [chan] ; + } ; + + /* Encode the samples as 4 bit. */ + + for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) + { chan = (pima->channels > 1) ? (k % 2) : 0 ; + + diff = pima->samples [k] - pima->previous [chan] ; + + bytecode = 0 ; + step = ima_step_size [pima->stepindx [chan]] ; + vpdiff = step >> 3 ; + if (diff < 0) + { bytecode = 8 ; + diff = -diff ; + } ; + mask = 4 ; + while (mask) + { if (diff >= step) + { bytecode |= mask ; + diff -= step ; + vpdiff += step ; + } ; + step >>= 1 ; + mask >>= 1 ; + } ; + + if (bytecode & 8) + pima->previous [chan] -= vpdiff ; + else + pima->previous [chan] += vpdiff ; + + if (pima->previous [chan] > 32767) + pima->previous [chan] = 32767 ; + else if (pima->previous [chan] < -32768) + pima->previous [chan] = -32768 ; + + pima->stepindx [chan] += ima_indx_adjust [bytecode] ; + if (pima->stepindx [chan] < 0) + pima->stepindx [chan] = 0 ; + else if (pima->stepindx [chan] > 88) + pima->stepindx [chan] = 88 ; + + pima->samples [k] = bytecode ; + } ; + + /* Pack the 4 bit encoded samples. */ + + blockindx = 4 * pima->channels ; + + indxstart = pima->channels ; + while (blockindx < pima->blocksize) + { for (chan = 0 ; chan < pima->channels ; chan++) + { indx = indxstart + chan ; + for (k = 0 ; k < 4 ; k++) + { pima->block [blockindx] = pima->samples [indx] & 0x0F ; + indx += pima->channels ; + pima->block [blockindx] |= (pima->samples [indx] << 4) & 0xF0 ; + indx += pima->channels ; + blockindx ++ ; + } ; + } ; + indxstart += 8 * pima->channels ; + } ; + + /* Write the block to disk. */ + + if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) + psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ; + + memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ; + pima->samplecount = 0 ; + pima->blockcount ++ ; + + return 1 ; +} /* wav_w64_ima_encode_block */ + +static int +ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { if (pima->blockcount >= pima->blocks && pima->samplecount >= pima->samplesperblock) + { memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ; + return total ; + } ; + + if (pima->samplecount >= pima->samplesperblock) + pima->decode_block (psf, pima) ; + + count = (pima->samplesperblock - pima->samplecount) * pima->channels ; + count = (len - indx > count) ? count : len - indx ; + + memcpy (&(ptr [indx]), &(pima->samples [pima->samplecount * pima->channels]), count * sizeof (short)) ; + indx += count ; + pima->samplecount += count / pima->channels ; + total = indx ; + } ; + + return total ; +} /* ima_read_block */ + +static sf_count_t +ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + int readcount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + while (len > 0) + { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = ima_read_block (psf, pima, ptr, readcount) ; + + total += count ; + len -= count ; + if (count != readcount) + break ; + } ; + + return total ; +} /* ima_read_s */ + +static sf_count_t +ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + short *sptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; + count = ima_read_block (psf, pima, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = ((int) sptr [k]) << 16 ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* ima_read_i */ + +static sf_count_t +ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + short *sptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; + count = ima_read_block (psf, pima, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (float) (sptr [k]) ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* ima_read_f */ + +static sf_count_t +ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + short *sptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; + count = ima_read_block (psf, pima, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (double) (sptr [k]) ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* ima_read_d */ + +static sf_count_t +ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ IMA_ADPCM_PRIVATE *pima ; + int newblock, newsample ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + if (psf->datalength < 0 || psf->dataoffset < 0) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (offset == 0) + { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + pima->blockcount = 0 ; + pima->decode_block (psf, pima) ; + pima->samplecount = 0 ; + return 0 ; + } ; + + if (offset < 0 || offset > pima->blocks * pima->samplesperblock) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + newblock = offset / pima->samplesperblock ; + newsample = offset % pima->samplesperblock ; + + if (mode == SFM_READ) + { psf_fseek (psf, psf->dataoffset + newblock * pima->blocksize, SEEK_SET) ; + pima->blockcount = newblock ; + pima->decode_block (psf, pima) ; + pima->samplecount = newsample ; + } + else + { /* What to do about write??? */ + psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + return newblock * pima->samplesperblock + newsample ; +} /* ima_seek */ + +/*========================================================================================== +** IMA ADPCM Write Functions. +*/ + +static int +ima_writer_init (SF_PRIVATE *psf, int blockalign) +{ IMA_ADPCM_PRIVATE *pima ; + int samplesperblock ; + unsigned int pimasize ; + + if (psf->mode != SFM_WRITE) + return SFE_BAD_MODE_RW ; + + samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; + + pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ; + + if ((pima = calloc (1, pimasize)) == NULL) + return SFE_MALLOC_FAILED ; + + psf->codec_data = (void*) pima ; + + pima->channels = psf->sf.channels ; + pima->blocksize = blockalign ; + pima->samplesperblock = samplesperblock ; + + pima->block = (unsigned char*) pima->data ; + pima->samples = (short*) (pima->data + blockalign) ; + + pima->samplecount = 0 ; + + switch (psf->sf.format & SF_FORMAT_TYPEMASK) + { case SF_FORMAT_WAV : + case SF_FORMAT_W64 : + pima->encode_block = wav_w64_ima_encode_block ; + break ; + + case SF_FORMAT_AIFF : + pima->encode_block = aiff_ima_encode_block ; + break ; + + default : + psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ; + return SFE_INTERNAL ; + break ; + } ; + + psf->write_short = ima_write_s ; + psf->write_int = ima_write_i ; + psf->write_float = ima_write_f ; + psf->write_double = ima_write_d ; + + return 0 ; +} /* ima_writer_init */ + +/*========================================================================================== +*/ + +static int +ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { count = (pima->samplesperblock - pima->samplecount) * pima->channels ; + + if (count > len - indx) + count = len - indx ; + + memcpy (&(pima->samples [pima->samplecount * pima->channels]), &(ptr [total]), count * sizeof (short)) ; + indx += count ; + pima->samplecount += count / pima->channels ; + total = indx ; + + if (pima->samplecount >= pima->samplesperblock) + pima->encode_block (psf, pima) ; + } ; + + return total ; +} /* ima_write_block */ + +static sf_count_t +ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + int writecount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + while (len) + { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = ima_write_block (psf, pima, ptr, writecount) ; + + total += count ; + len -= count ; + if (count != writecount) + break ; + } ; + + return total ; +} /* ima_write_s */ + +static sf_count_t +ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = ptr [total + k] >> 16 ; + count = ima_write_block (psf, pima, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* ima_write_i */ + +static sf_count_t +ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrintf (normfact * ptr [total + k]) ; + count = ima_write_block (psf, pima, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* ima_write_f */ + +static sf_count_t +ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ IMA_ADPCM_PRIVATE *pima ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (! psf->codec_data) + return 0 ; + pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrint (normfact * ptr [total + k]) ; + count = ima_write_block (psf, pima, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* ima_write_d */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 75a54b82-ad18-4758-9933-64e00a7f24e0 +*/ diff --git a/nylsf/interleave.c b/nylsf/interleave.c new file mode 100644 index 0000000..7c18bd4 --- /dev/null +++ b/nylsf/interleave.c @@ -0,0 +1,306 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfendian.h" + +#include + +#include "sndfile.h" +#include "common.h" + +#define INTERLEAVE_CHANNELS 6 + +typedef struct +{ double buffer [SF_BUFFER_LEN / sizeof (double)] ; + + sf_count_t channel_len ; + + sf_count_t (*read_short) (SF_PRIVATE*, short *ptr, sf_count_t len) ; + sf_count_t (*read_int) (SF_PRIVATE*, int *ptr, sf_count_t len) ; + sf_count_t (*read_float) (SF_PRIVATE*, float *ptr, sf_count_t len) ; + sf_count_t (*read_double) (SF_PRIVATE*, double *ptr, sf_count_t len) ; + +} INTERLEAVE_DATA ; + + + +static sf_count_t interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t interleave_seek (SF_PRIVATE*, int mode, sf_count_t samples_from_start) ; + + + + +int +interleave_init (SF_PRIVATE *psf) +{ INTERLEAVE_DATA *pdata ; + + if (psf->mode != SFM_READ) + return SFE_INTERLEAVE_MODE ; + + if (psf->interleave) + { psf_log_printf (psf, "*** Weird, already have interleave.\n") ; + return 666 ; + } ; + + /* Free this in sf_close() function. */ + if (! (pdata = malloc (sizeof (INTERLEAVE_DATA)))) + return SFE_MALLOC_FAILED ; + +puts ("interleave_init") ; + + psf->interleave = pdata ; + + /* Save the existing methods. */ + pdata->read_short = psf->read_short ; + pdata->read_int = psf->read_int ; + pdata->read_float = psf->read_float ; + pdata->read_double = psf->read_double ; + + pdata->channel_len = psf->sf.frames * psf->bytewidth ; + + /* Insert our new methods. */ + psf->read_short = interleave_read_short ; + psf->read_int = interleave_read_int ; + psf->read_float = interleave_read_float ; + psf->read_double = interleave_read_double ; + + psf->seek = interleave_seek ; + + return 0 ; +} /* pcm_interleave_init */ + +/*------------------------------------------------------------------------------ +*/ + +static sf_count_t +interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ INTERLEAVE_DATA *pdata ; + sf_count_t offset, templen ; + int chan, count, k ; + short *inptr, *outptr ; + + if (! (pdata = psf->interleave)) + return 0 ; + + inptr = (short*) pdata->buffer ; + + for (chan = 0 ; chan < psf->sf.channels ; chan++) + { outptr = ptr + chan ; + + offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ; + + if (psf_fseek (psf, offset, SEEK_SET) != offset) + { psf->error = SFE_INTERLEAVE_SEEK ; + return 0 ; + } ; + + templen = len / psf->sf.channels ; + + while (templen > 0) + { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short)) + count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short) ; + else + count = (int) templen ; + + if (pdata->read_short (psf, inptr, count) != count) + { psf->error = SFE_INTERLEAVE_READ ; + return 0 ; + } ; + + for (k = 0 ; k < count ; k++) + { *outptr = inptr [k] ; + outptr += psf->sf.channels ; + } ; + + templen -= count ; + } ; + } ; + + return len ; +} /* interleave_read_short */ + +static sf_count_t +interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ INTERLEAVE_DATA *pdata ; + sf_count_t offset, templen ; + int chan, count, k ; + int *inptr, *outptr ; + + if (! (pdata = psf->interleave)) + return 0 ; + + inptr = (int*) pdata->buffer ; + + for (chan = 0 ; chan < psf->sf.channels ; chan++) + { outptr = ptr + chan ; + + offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ; + + if (psf_fseek (psf, offset, SEEK_SET) != offset) + { psf->error = SFE_INTERLEAVE_SEEK ; + return 0 ; + } ; + + templen = len / psf->sf.channels ; + + while (templen > 0) + { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int)) + count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int) ; + else + count = (int) templen ; + + if (pdata->read_int (psf, inptr, count) != count) + { psf->error = SFE_INTERLEAVE_READ ; + return 0 ; + } ; + + for (k = 0 ; k < count ; k++) + { *outptr = inptr [k] ; + outptr += psf->sf.channels ; + } ; + + templen -= count ; + } ; + } ; + + return len ; +} /* interleave_read_int */ + +static sf_count_t +interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ INTERLEAVE_DATA *pdata ; + sf_count_t offset, templen ; + int chan, count, k ; + float *inptr, *outptr ; + + if (! (pdata = psf->interleave)) + return 0 ; + + inptr = (float*) pdata->buffer ; + + for (chan = 0 ; chan < psf->sf.channels ; chan++) + { outptr = ptr + chan ; + + offset = psf->dataoffset + pdata->channel_len * chan + psf->read_current * psf->bytewidth ; + +/*-printf ("chan : %d read_current : %6lld offset : %6lld\n", chan, psf->read_current, offset) ;-*/ + + if (psf_fseek (psf, offset, SEEK_SET) != offset) + { psf->error = SFE_INTERLEAVE_SEEK ; +/*-puts ("interleave_seek error") ; exit (1) ;-*/ + return 0 ; + } ; + + templen = len / psf->sf.channels ; + + while (templen > 0) + { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float)) + count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float) ; + else + count = (int) templen ; + + if (pdata->read_float (psf, inptr, count) != count) + { psf->error = SFE_INTERLEAVE_READ ; +/*-puts ("interleave_read error") ; exit (1) ;-*/ + return 0 ; + } ; + + for (k = 0 ; k < count ; k++) + { *outptr = inptr [k] ; + outptr += psf->sf.channels ; + } ; + + templen -= count ; + } ; + } ; + + return len ; +} /* interleave_read_float */ + +static sf_count_t +interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ INTERLEAVE_DATA *pdata ; + sf_count_t offset, templen ; + int chan, count, k ; + double *inptr, *outptr ; + + if (! (pdata = psf->interleave)) + return 0 ; + + inptr = (double*) pdata->buffer ; + + for (chan = 0 ; chan < psf->sf.channels ; chan++) + { outptr = ptr + chan ; + + offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ; + + if (psf_fseek (psf, offset, SEEK_SET) != offset) + { psf->error = SFE_INTERLEAVE_SEEK ; + return 0 ; + } ; + + templen = len / psf->sf.channels ; + + while (templen > 0) + { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double)) + count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double) ; + else + count = (int) templen ; + + if (pdata->read_double (psf, inptr, count) != count) + { psf->error = SFE_INTERLEAVE_READ ; + return 0 ; + } ; + + for (k = 0 ; k < count ; k++) + { *outptr = inptr [k] ; + outptr += psf->sf.channels ; + } ; + + templen -= count ; + } ; + } ; + + return len ; +} /* interleave_read_double */ + +/*------------------------------------------------------------------------------ +*/ + +static sf_count_t +interleave_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) +{ psf = psf ; mode = mode ; + + /* + ** Do nothing here. This is a place holder to prevent the default + ** seek function from being called. + */ + + return samples_from_start ; +} /* interleave_seek */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 82314e13-0225-4408-a2f2-e6dab3f38904 +*/ diff --git a/nylsf/ircam.c b/nylsf/ircam.c new file mode 100644 index 0000000..003809f --- /dev/null +++ b/nylsf/ircam.c @@ -0,0 +1,331 @@ +/* +** Copyright (C) 2001-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +/* The IRCAM magic number is weird in that one byte in the number can have +** values of 0x1, 0x2, 0x03 or 0x04. Hence the need for a marker and a mask. +*/ + +#define IRCAM_BE_MASK (MAKE_MARKER (0xFF, 0xFF, 0x00, 0xFF)) +#define IRCAM_BE_MARKER (MAKE_MARKER (0x64, 0xA3, 0x00, 0x00)) + +#define IRCAM_LE_MASK (MAKE_MARKER (0xFF, 0x00, 0xFF, 0xFF)) +#define IRCAM_LE_MARKER (MAKE_MARKER (0x00, 0x00, 0xA3, 0x64)) + +#define IRCAM_02B_MARKER (MAKE_MARKER (0x64, 0xA3, 0x02, 0x00)) +#define IRCAM_03L_MARKER (MAKE_MARKER (0x64, 0xA3, 0x03, 0x00)) + +#define IRCAM_DATA_OFFSET (1024) + +/*------------------------------------------------------------------------------ +** Typedefs. +*/ + +enum +{ IRCAM_PCM_16 = 0x00002, + IRCAM_FLOAT = 0x00004, + IRCAM_ALAW = 0x10001, + IRCAM_ULAW = 0x20001, + IRCAM_PCM_32 = 0x40004 +} ; + + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int ircam_close (SF_PRIVATE *psf) ; +static int ircam_write_header (SF_PRIVATE *psf, int calc_length) ; +static int ircam_read_header (SF_PRIVATE *psf) ; + +static int get_encoding (int subformat) ; + +static const char* get_encoding_str (int encoding) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +ircam_open (SF_PRIVATE *psf) +{ int subformat ; + int error = SFE_NO_ERROR ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = ircam_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_IRCAM) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU) + psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; + + psf->dataoffset = IRCAM_DATA_OFFSET ; + + if ((error = ircam_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = ircam_write_header ; + } ; + + psf->container_close = ircam_close ; + + switch (subformat) + { case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */ + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */ + error = alaw_init (psf) ; + break ; + + case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ + case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */ + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_FLOAT : /* 32-bit linear PCM. */ + error = float32_init (psf) ; + break ; + + default : break ; + } ; + + return error ; +} /* ircam_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +ircam_read_header (SF_PRIVATE *psf) +{ unsigned int marker, encoding ; + float samplerate ; + int error = SFE_NO_ERROR ; + + psf_binheader_readf (psf, "epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ; + + if (((marker & IRCAM_BE_MASK) != IRCAM_BE_MARKER) && ((marker & IRCAM_LE_MASK) != IRCAM_LE_MARKER)) + { psf_log_printf (psf, "marker: 0x%X\n", marker) ; + return SFE_IRCAM_NO_MARKER ; + } ; + + psf->endian = SF_ENDIAN_LITTLE ; + + if (psf->sf.channels > 256) + { psf_binheader_readf (psf, "Epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ; + + /* Sanity checking for endian-ness detection. */ + if (psf->sf.channels > 256) + { psf_log_printf (psf, "marker: 0x%X\n", marker) ; + return SFE_IRCAM_BAD_CHANNELS ; + } ; + + psf->endian = SF_ENDIAN_BIG ; + } ; + + psf_log_printf (psf, "marker: 0x%X\n", marker) ; + + psf->sf.samplerate = (int) samplerate ; + + psf_log_printf (psf, " Sample Rate : %d\n" + " Channels : %d\n" + " Encoding : %X => %s\n", psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ; + + switch (encoding) + { case IRCAM_PCM_16 : + psf->bytewidth = 2 ; + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_16 ; + break ; + + case IRCAM_PCM_32 : + psf->bytewidth = 4 ; + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_32 ; + break ; + + case IRCAM_FLOAT : + psf->bytewidth = 4 ; + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_FLOAT ; + break ; + + case IRCAM_ALAW : + psf->bytewidth = 1 ; + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ALAW ; + break ; + + case IRCAM_ULAW : + psf->bytewidth = 1 ; + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ULAW ; + break ; + + default : + error = SFE_IRCAM_UNKNOWN_FORMAT ; + break ; + } ; + + if (psf->endian == SF_ENDIAN_BIG) + psf->sf.format |= SF_ENDIAN_BIG ; + else + psf->sf.format |= SF_ENDIAN_LITTLE ; + + if (error) + return error ; + + psf->dataoffset = IRCAM_DATA_OFFSET ; + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->sf.frames == 0 && psf->blockwidth) + psf->sf.frames = psf->datalength / psf->blockwidth ; + + psf_log_printf (psf, " Samples : %d\n", psf->sf.frames) ; + + psf_binheader_readf (psf, "p", IRCAM_DATA_OFFSET) ; + + return 0 ; +} /* ircam_read_header */ + +static int +ircam_close (SF_PRIVATE *psf) +{ + psf_log_printf (psf, "close\n") ; + + return 0 ; +} /* ircam_close */ + +static int +ircam_write_header (SF_PRIVATE *psf, int calc_length) +{ int encoding ; + float samplerate ; + sf_count_t current ; + + if (psf->pipeoffset > 0) + return 0 ; + + current = psf_ftell (psf) ; + + calc_length = calc_length ; + + /* This also sets psf->endian. */ + encoding = get_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ; + + if (encoding == 0) + return SFE_BAD_OPEN_FORMAT ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + if (psf->is_pipe == SF_FALSE) + psf_fseek (psf, 0, SEEK_SET) ; + + samplerate = psf->sf.samplerate ; + + switch (psf->endian) + { case SF_ENDIAN_BIG : + psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ; + psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ; + break ; + + case SF_ENDIAN_LITTLE : + psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ; + psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ; + break ; + + default : return SFE_BAD_OPEN_FORMAT ; + } ; + + psf_binheader_writef (psf, "z", (size_t) (IRCAM_DATA_OFFSET - psf->headindex)) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* ircam_write_header */ + +static int +get_encoding (int subformat) +{ switch (subformat) + { case SF_FORMAT_PCM_16 : return IRCAM_PCM_16 ; + case SF_FORMAT_PCM_32 : return IRCAM_PCM_32 ; + + case SF_FORMAT_FLOAT : return IRCAM_FLOAT ; + + case SF_FORMAT_ULAW : return IRCAM_ULAW ; + case SF_FORMAT_ALAW : return IRCAM_ALAW ; + + default : break ; + } ; + + return 0 ; +} /* get_encoding */ + +static const char* +get_encoding_str (int encoding) +{ switch (encoding) + { case IRCAM_PCM_16 : return "16 bit PCM" ; + case IRCAM_FLOAT : return "32 bit float" ; + case IRCAM_ALAW : return "A law" ; + case IRCAM_ULAW : return "u law" ; + case IRCAM_PCM_32 : return "32 bit PCM" ; + } ; + return "Unknown encoding" ; +} /* get_encoding_str */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: f2714ab8-f286-4c94-9740-edaf673a1c71 +*/ diff --git a/nylsf/macbinary3.c b/nylsf/macbinary3.c new file mode 100644 index 0000000..7cad1d1 --- /dev/null +++ b/nylsf/macbinary3.c @@ -0,0 +1,58 @@ +/* +** Copyright (C) 2003-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#if (OS_IS_MACOSX == 1) + +#include + +int +macbinary3_open (SF_PRIVATE *psf) +{ + if (psf) + return 0 ; + + return 0 ; +} /* macbinary3_open */ + +#else + +int +macbinary3_open (SF_PRIVATE *psf) +{ + psf = psf ; + return 0 ; +} /* macbinary3_open */ + +#endif /* OS_IS_MACOSX */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: c397a7d7-1a31-4349-9684-bd29ef06211e +*/ diff --git a/nylsf/macos.c b/nylsf/macos.c new file mode 100644 index 0000000..bb5543a --- /dev/null +++ b/nylsf/macos.c @@ -0,0 +1,63 @@ +/* +** Copyright (C) 2003-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ') + +int +macos_guess_file_type (SF_PRIVATE *psf, const char *filename) +{ static char rsrc_name [1024] ; + struct stat statbuf ; + int format ; + + psf = psf ; + + snprintf (rsrc_name, sizeof (rsrc_name), "%s/rsrc", filename) ; + + /* If there is no resource fork, just return. */ + if (stat (rsrc_name, &statbuf) != 0) + { psf_log_printf (psf, "No resource fork.\n") ; + return 0 ; + } ; + + if (statbuf.st_size == 0) + { psf_log_printf (psf, "Have zero size resource fork.\n") ; + return 0 ; + } ; + + format = 0 ; + + return format ; +} /* macos_guess_file_type */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 5fbf66d7-9547-442a-9c73-92fd164f3a95 +*/ diff --git a/nylsf/mat4.c b/nylsf/mat4.c new file mode 100644 index 0000000..1be7d4c --- /dev/null +++ b/nylsf/mat4.c @@ -0,0 +1,394 @@ +/* +** Copyright (C) 2002-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "float_cast.h" + +/*------------------------------------------------------------------------------ +** Information on how to decode and encode this file was obtained in a PDF +** file which I found on http://www.wotsit.org/. +** Also did a lot of testing with GNU Octave but do not have access to +** Matlab (tm) and so could not test it there. +*/ + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define MAT4_BE_DOUBLE (MAKE_MARKER (0, 0, 0x03, 0xE8)) +#define MAT4_LE_DOUBLE (MAKE_MARKER (0, 0, 0, 0)) + +#define MAT4_BE_FLOAT (MAKE_MARKER (0, 0, 0x03, 0xF2)) +#define MAT4_LE_FLOAT (MAKE_MARKER (0x0A, 0, 0, 0)) + +#define MAT4_BE_PCM_32 (MAKE_MARKER (0, 0, 0x03, 0xFC)) +#define MAT4_LE_PCM_32 (MAKE_MARKER (0x14, 0, 0, 0)) + +#define MAT4_BE_PCM_16 (MAKE_MARKER (0, 0, 0x04, 0x06)) +#define MAT4_LE_PCM_16 (MAKE_MARKER (0x1E, 0, 0, 0)) + +/* Can't see any reason to ever implement this. */ +#define MAT4_BE_PCM_U8 (MAKE_MARKER (0, 0, 0x04, 0x1A)) +#define MAT4_LE_PCM_U8 (MAKE_MARKER (0x32, 0, 0, 0)) + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int mat4_close (SF_PRIVATE *psf) ; + +static int mat4_format_to_encoding (int format, int endian) ; + +static int mat4_write_header (SF_PRIVATE *psf, int calc_length) ; +static int mat4_read_header (SF_PRIVATE *psf) ; + +static const char * mat4_marker_to_str (int marker) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +mat4_open (SF_PRIVATE *psf) +{ int subformat, error = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = mat4_read_header (psf))) + return error ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT4) + return SFE_BAD_OPEN_FORMAT ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) + psf->endian = SF_ENDIAN_LITTLE ; + else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) + psf->endian = SF_ENDIAN_BIG ; + + if ((error = mat4_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = mat4_write_header ; + } ; + + psf->container_close = mat4_close ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + + default : break ; + } ; + + if (error) + return error ; + + return error ; +} /* mat4_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +mat4_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + mat4_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* mat4_close */ + +/*------------------------------------------------------------------------------ +*/ + +static int +mat4_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + int encoding ; + double samplerate ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + encoding = mat4_format_to_encoding (psf->sf.format & SF_FORMAT_SUBMASK, psf->endian) ; + + if (encoding == -1) + return SFE_BAD_OPEN_FORMAT ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* Need sample rate as a double for writing to the header. */ + samplerate = psf->sf.samplerate ; + + if (psf->endian == SF_ENDIAN_BIG) + { psf_binheader_writef (psf, "Em444", MAT4_BE_DOUBLE, 1, 1, 0) ; + psf_binheader_writef (psf, "E4bd", 11, "samplerate", make_size_t (11), samplerate) ; + psf_binheader_writef (psf, "tEm484", encoding, psf->sf.channels, psf->sf.frames, 0) ; + psf_binheader_writef (psf, "E4b", 9, "wavedata", make_size_t (9)) ; + } + else if (psf->endian == SF_ENDIAN_LITTLE) + { psf_binheader_writef (psf, "em444", MAT4_LE_DOUBLE, 1, 1, 0) ; + psf_binheader_writef (psf, "e4bd", 11, "samplerate", make_size_t (11), samplerate) ; + psf_binheader_writef (psf, "tem484", encoding, psf->sf.channels, psf->sf.frames, 0) ; + psf_binheader_writef (psf, "e4b", 9, "wavedata", make_size_t (9)) ; + } + else + return SFE_BAD_OPEN_FORMAT ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* mat4_write_header */ + +static int +mat4_read_header (SF_PRIVATE *psf) +{ int marker, namesize, rows, cols, imag ; + double value ; + const char *marker_str ; + char name [64] ; + + psf_binheader_readf (psf, "pm", 0, &marker) ; + + /* MAT4 file must start with a double for the samplerate. */ + if (marker == MAT4_BE_DOUBLE) + { psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ; + marker_str = "big endian double" ; + } + else if (marker == MAT4_LE_DOUBLE) + { psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ; + marker_str = "little endian double" ; + } + else + return SFE_UNIMPLEMENTED ; + + psf_log_printf (psf, "GNU Octave 2.0 / MATLAB v4.2 format\nMarker : %s\n", marker_str) ; + + psf_binheader_readf (psf, "444", &rows, &cols, &imag) ; + + psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ; + + psf_binheader_readf (psf, "4", &namesize) ; + + if (namesize >= SIGNED_SIZEOF (name)) + return SFE_MAT4_BAD_NAME ; + + psf_binheader_readf (psf, "b", name, namesize) ; + name [namesize] = 0 ; + + psf_log_printf (psf, " Name : %s\n", name) ; + + psf_binheader_readf (psf, "d", &value) ; + + LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), " Value : %f\n", value) ; + psf_log_printf (psf, psf->u.cbuf) ; + + if ((rows != 1) || (cols != 1)) + return SFE_MAT4_NO_SAMPLERATE ; + + psf->sf.samplerate = lrint (value) ; + + /* Now write out the audio data. */ + + psf_binheader_readf (psf, "m", &marker) ; + + psf_log_printf (psf, "Marker : %s\n", mat4_marker_to_str (marker)) ; + + psf_binheader_readf (psf, "444", &rows, &cols, &imag) ; + + psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ; + + psf_binheader_readf (psf, "4", &namesize) ; + + if (namesize >= SIGNED_SIZEOF (name)) + return SFE_MAT4_BAD_NAME ; + + psf_binheader_readf (psf, "b", name, namesize) ; + name [namesize] = 0 ; + + psf_log_printf (psf, " Name : %s\n", name) ; + + psf->dataoffset = psf_ftell (psf) ; + + if (rows == 0 && cols == 0) + { psf_log_printf (psf, "*** Error : zero channel count.\n") ; + return SFE_MAT4_ZERO_CHANNELS ; + } ; + + psf->sf.channels = rows ; + psf->sf.frames = cols ; + + psf->sf.format = psf->endian | SF_FORMAT_MAT4 ; + switch (marker) + { case MAT4_BE_DOUBLE : + case MAT4_LE_DOUBLE : + psf->sf.format |= SF_FORMAT_DOUBLE ; + psf->bytewidth = 8 ; + break ; + + case MAT4_BE_FLOAT : + case MAT4_LE_FLOAT : + psf->sf.format |= SF_FORMAT_FLOAT ; + psf->bytewidth = 4 ; + break ; + + case MAT4_BE_PCM_32 : + case MAT4_LE_PCM_32 : + psf->sf.format |= SF_FORMAT_PCM_32 ; + psf->bytewidth = 4 ; + break ; + + case MAT4_BE_PCM_16 : + case MAT4_LE_PCM_16 : + psf->sf.format |= SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + break ; + + default : + psf_log_printf (psf, "*** Error : Bad marker %08X\n", marker) ; + return SFE_UNIMPLEMENTED ; + } ; + + if ((psf->filelength - psf->dataoffset) < psf->sf.channels * psf->sf.frames * psf->bytewidth) + { psf_log_printf (psf, "*** File seems to be truncated. %D <--> %D\n", + psf->filelength - psf->dataoffset, psf->sf.channels * psf->sf.frames * psf->bytewidth) ; + } + else if ((psf->filelength - psf->dataoffset) > psf->sf.channels * psf->sf.frames * psf->bytewidth) + psf->dataend = psf->dataoffset + rows * cols * psf->bytewidth ; + + psf->datalength = psf->filelength - psf->dataoffset - psf->dataend ; + + psf->sf.sections = 1 ; + + return 0 ; +} /* mat4_read_header */ + +static int +mat4_format_to_encoding (int format, int endian) +{ + switch (format | endian) + { case (SF_FORMAT_PCM_16 | SF_ENDIAN_BIG) : + return MAT4_BE_PCM_16 ; + + case (SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE) : + return MAT4_LE_PCM_16 ; + + case (SF_FORMAT_PCM_32 | SF_ENDIAN_BIG) : + return MAT4_BE_PCM_32 ; + + case (SF_FORMAT_PCM_32 | SF_ENDIAN_LITTLE) : + return MAT4_LE_PCM_32 ; + + case (SF_FORMAT_FLOAT | SF_ENDIAN_BIG) : + return MAT4_BE_FLOAT ; + + case (SF_FORMAT_FLOAT | SF_ENDIAN_LITTLE) : + return MAT4_LE_FLOAT ; + + case (SF_FORMAT_DOUBLE | SF_ENDIAN_BIG) : + return MAT4_BE_DOUBLE ; + + case (SF_FORMAT_DOUBLE | SF_ENDIAN_LITTLE) : + return MAT4_LE_DOUBLE ; + + default : break ; + } ; + + return -1 ; +} /* mat4_format_to_encoding */ + +static const char * +mat4_marker_to_str (int marker) +{ static char str [32] ; + + switch (marker) + { + case MAT4_BE_PCM_16 : return "big endian 16 bit PCM" ; + case MAT4_LE_PCM_16 : return "little endian 16 bit PCM" ; + + case MAT4_BE_PCM_32 : return "big endian 32 bit PCM" ; + case MAT4_LE_PCM_32 : return "little endian 32 bit PCM" ; + + + case MAT4_BE_FLOAT : return "big endian float" ; + case MAT4_LE_FLOAT : return "big endian float" ; + + case MAT4_BE_DOUBLE : return "big endian double" ; + case MAT4_LE_DOUBLE : return "little endian double" ; + } ; + + /* This is a little unsafe but is really only for debugging. */ + str [sizeof (str) - 1] = 0 ; + LSF_SNPRINTF (str, sizeof (str) - 1, "%08X", marker) ; + return str ; +} /* mat4_marker_to_str */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: f7e5f5d6-fc39-452e-bc4a-59627116ff59 +*/ diff --git a/nylsf/mat5.c b/nylsf/mat5.c new file mode 100644 index 0000000..ecd0039 --- /dev/null +++ b/nylsf/mat5.c @@ -0,0 +1,507 @@ +/* +** Copyright (C) 2002-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "float_cast.h" + +/*------------------------------------------------------------------------------ +** Information on how to decode and encode this file was obtained in a PDF +** file which I found on http://www.wotsit.org/. +** Also did a lot of testing with GNU Octave but do not have access to +** Matlab (tm) and so could not test it there. +*/ + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define MATL_MARKER (MAKE_MARKER ('M', 'A', 'T', 'L')) + +#define IM_MARKER (('I' << 8) + 'M') +#define MI_MARKER (('M' << 8) + 'I') + +/*------------------------------------------------------------------------------ +** Enums and typedefs. +*/ + +enum +{ MAT5_TYPE_SCHAR = 0x1, + MAT5_TYPE_UCHAR = 0x2, + MAT5_TYPE_INT16 = 0x3, + MAT5_TYPE_UINT16 = 0x4, + MAT5_TYPE_INT32 = 0x5, + MAT5_TYPE_UINT32 = 0x6, + MAT5_TYPE_FLOAT = 0x7, + MAT5_TYPE_DOUBLE = 0x9, + MAT5_TYPE_ARRAY = 0xE, + + MAT5_TYPE_COMP_USHORT = 0x00020004, + MAT5_TYPE_COMP_UINT = 0x00040006 +} ; + +typedef struct +{ sf_count_t size ; + int rows, cols ; + char name [32] ; +} MAT5_MATRIX ; + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int mat5_close (SF_PRIVATE *psf) ; + +static int mat5_write_header (SF_PRIVATE *psf, int calc_length) ; +static int mat5_read_header (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +mat5_open (SF_PRIVATE *psf) +{ int subformat, error = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = mat5_read_header (psf))) + return error ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT5) + return SFE_BAD_OPEN_FORMAT ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) + psf->endian = SF_ENDIAN_LITTLE ; + else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) + psf->endian = SF_ENDIAN_BIG ; + + if ((error = mat5_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = mat5_write_header ; + } ; + + psf->container_close = mat5_close ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + + default : break ; + } ; + + return error ; +} /* mat5_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +mat5_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + mat5_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* mat5_close */ + +/*------------------------------------------------------------------------------ +*/ + +static int +mat5_write_header (SF_PRIVATE *psf, int calc_length) +{ static const char *filename = "MATLAB 5.0 MAT-file, written by " PACKAGE "-" VERSION ", " ; + static const char *sr_name = "samplerate\0\0\0\0\0\0\0\0\0\0\0" ; + static const char *wd_name = "wavedata\0" ; + sf_count_t current, datasize ; + int encoding ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf_fseek (psf, 0, SEEK_END) ; + psf->filelength = psf_ftell (psf) ; + psf_fseek (psf, 0, SEEK_SET) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_U8 : + encoding = MAT5_TYPE_UCHAR ; + break ; + + case SF_FORMAT_PCM_16 : + encoding = MAT5_TYPE_INT16 ; + break ; + + case SF_FORMAT_PCM_32 : + encoding = MAT5_TYPE_INT32 ; + break ; + + case SF_FORMAT_FLOAT : + encoding = MAT5_TYPE_FLOAT ; + break ; + + case SF_FORMAT_DOUBLE : + encoding = MAT5_TYPE_DOUBLE ; + break ; + + default : + return SFE_BAD_OPEN_FORMAT ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + psf_get_date_str (psf->u.cbuf, sizeof (psf->u.scbuf)) ; + psf_binheader_writef (psf, "bb", filename, strlen (filename), psf->u.cbuf, strlen (psf->u.cbuf) + 1) ; + + memset (psf->u.scbuf, ' ', 124 - psf->headindex) ; + psf_binheader_writef (psf, "b", psf->u.scbuf, make_size_t (124 - psf->headindex)) ; + + psf->rwf_endian = psf->endian ; + + if (psf->rwf_endian == SF_ENDIAN_BIG) + psf_binheader_writef (psf, "2b", 0x0100, "MI", make_size_t (2)) ; + else + psf_binheader_writef (psf, "2b", 0x0100, "IM", make_size_t (2)) ; + + psf_binheader_writef (psf, "444444", MAT5_TYPE_ARRAY, 64, MAT5_TYPE_UINT32, 8, 6, 0) ; + psf_binheader_writef (psf, "4444", MAT5_TYPE_INT32, 8, 1, 1) ; + psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (sr_name), sr_name, make_size_t (16)) ; + + if (psf->sf.samplerate > 0xFFFF) + psf_binheader_writef (psf, "44", MAT5_TYPE_COMP_UINT, psf->sf.samplerate) ; + else + { unsigned short samplerate = psf->sf.samplerate ; + + psf_binheader_writef (psf, "422", MAT5_TYPE_COMP_USHORT, samplerate, 0) ; + } ; + + datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; + + psf_binheader_writef (psf, "t484444", MAT5_TYPE_ARRAY, datasize + 64, MAT5_TYPE_UINT32, 8, 6, 0) ; + psf_binheader_writef (psf, "t4448", MAT5_TYPE_INT32, 8, psf->sf.channels, psf->sf.frames) ; + psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (wd_name), wd_name, strlen (wd_name)) ; + + datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; + if (datasize > 0x7FFFFFFF) + datasize = 0x7FFFFFFF ; + + psf_binheader_writef (psf, "t48", encoding, datasize) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* mat5_write_header */ + +static int +mat5_read_header (SF_PRIVATE *psf) +{ char name [32] ; + short version, endian ; + int type, size, flags1, flags2, rows, cols ; + + psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, 124) ; + + psf->u.scbuf [125] = 0 ; + + if (strlen (psf->u.cbuf) >= 124) + return SFE_UNIMPLEMENTED ; + + if (strstr (psf->u.cbuf, "MATLAB 5.0 MAT-file") == psf->u.cbuf) + psf_log_printf (psf, "%s\n", psf->u.scbuf) ; + + + psf_binheader_readf (psf, "E22", &version, &endian) ; + + if (endian == MI_MARKER) + { psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ; + if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_SHORT (version) ; + } + else if (endian == IM_MARKER) + { psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ; + if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_SHORT (version) ; + } + else + return SFE_MAT5_BAD_ENDIAN ; + + if ((CPU_IS_LITTLE_ENDIAN && endian == IM_MARKER) || + (CPU_IS_BIG_ENDIAN && endian == MI_MARKER)) + version = ENDSWAP_SHORT (version) ; + + psf_log_printf (psf, "Version : 0x%04X\n", version) ; + psf_log_printf (psf, "Endian : 0x%04X => %s\n", endian, + (psf->endian == SF_ENDIAN_LITTLE) ? "Little" : "Big") ; + + /*========================================================*/ + psf_binheader_readf (psf, "44", &type, &size) ; + psf_log_printf (psf, "Block\n Type : %X Size : %d\n", type, size) ; + + if (type != MAT5_TYPE_ARRAY) + return SFE_MAT5_NO_BLOCK ; + + psf_binheader_readf (psf, "44", &type, &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + + if (type != MAT5_TYPE_UINT32) + return SFE_MAT5_NO_BLOCK ; + + psf_binheader_readf (psf, "44", &flags1, &flags2) ; + psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ; + + psf_binheader_readf (psf, "44", &type, &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + + if (type != MAT5_TYPE_INT32) + return SFE_MAT5_NO_BLOCK ; + + psf_binheader_readf (psf, "44", &rows, &cols) ; + psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ; + + if (rows != 1 || cols != 1) + return SFE_MAT5_SAMPLE_RATE ; + + psf_binheader_readf (psf, "4", &type) ; + + if (type == MAT5_TYPE_SCHAR) + { psf_binheader_readf (psf, "4", &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + if (size > SIGNED_SIZEOF (name) - 1) + { psf_log_printf (psf, "Error : Bad name length.\n") ; + return SFE_MAT5_NO_BLOCK ; + } ; + + psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ; + name [size] = 0 ; + } + else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR) + { size = type >> 16 ; + if (size > 4) + { psf_log_printf (psf, "Error : Bad name length.\n") ; + return SFE_MAT5_NO_BLOCK ; + } ; + + psf_log_printf (psf, " Type : %X\n", type) ; + psf_binheader_readf (psf, "4", &name) ; + name [size] = 0 ; + } + else + return SFE_MAT5_NO_BLOCK ; + + psf_log_printf (psf, " Name : %s\n", name) ; + + /*-----------------------------------------*/ + + psf_binheader_readf (psf, "44", &type, &size) ; + + switch (type) + { case MAT5_TYPE_DOUBLE : + { double samplerate ; + + psf_binheader_readf (psf, "d", &samplerate) ; + LSF_SNPRINTF (name, sizeof (name), "%f\n", samplerate) ; + psf_log_printf (psf, " Val : %s\n", name) ; + + psf->sf.samplerate = lrint (samplerate) ; + } ; + break ; + + case MAT5_TYPE_COMP_USHORT : + { unsigned short samplerate ; + + psf_binheader_readf (psf, "j2j", -4, &samplerate, 2) ; + psf_log_printf (psf, " Val : %u\n", samplerate) ; + psf->sf.samplerate = samplerate ; + } + break ; + + case MAT5_TYPE_COMP_UINT : + psf_log_printf (psf, " Val : %u\n", size) ; + psf->sf.samplerate = size ; + break ; + + default : + psf_log_printf (psf, " Type : %X Size : %d ***\n", type, size) ; + return SFE_MAT5_SAMPLE_RATE ; + } ; + + /*-----------------------------------------*/ + + + psf_binheader_readf (psf, "44", &type, &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + + if (type != MAT5_TYPE_ARRAY) + return SFE_MAT5_NO_BLOCK ; + + psf_binheader_readf (psf, "44", &type, &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + + if (type != MAT5_TYPE_UINT32) + return SFE_MAT5_NO_BLOCK ; + + psf_binheader_readf (psf, "44", &flags1, &flags2) ; + psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ; + + psf_binheader_readf (psf, "44", &type, &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + + if (type != MAT5_TYPE_INT32) + return SFE_MAT5_NO_BLOCK ; + + psf_binheader_readf (psf, "44", &rows, &cols) ; + psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ; + + psf_binheader_readf (psf, "4", &type) ; + + if (type == MAT5_TYPE_SCHAR) + { psf_binheader_readf (psf, "4", &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + if (size > SIGNED_SIZEOF (name) - 1) + { psf_log_printf (psf, "Error : Bad name length.\n") ; + return SFE_MAT5_NO_BLOCK ; + } ; + + psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ; + name [size] = 0 ; + } + else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR) + { size = type >> 16 ; + if (size > 4) + { psf_log_printf (psf, "Error : Bad name length.\n") ; + return SFE_MAT5_NO_BLOCK ; + } ; + + psf_log_printf (psf, " Type : %X\n", type) ; + psf_binheader_readf (psf, "4", &name) ; + name [size] = 0 ; + } + else + return SFE_MAT5_NO_BLOCK ; + + psf_log_printf (psf, " Name : %s\n", name) ; + + psf_binheader_readf (psf, "44", &type, &size) ; + psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; + + /*++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + if (rows == 0 && cols == 0) + { psf_log_printf (psf, "*** Error : zero channel count.\n") ; + return SFE_MAT5_ZERO_CHANNELS ; + } ; + + psf->sf.channels = rows ; + psf->sf.frames = cols ; + + psf->sf.format = psf->endian | SF_FORMAT_MAT5 ; + + switch (type) + { case MAT5_TYPE_DOUBLE : + psf_log_printf (psf, "Data type : double\n") ; + psf->sf.format |= SF_FORMAT_DOUBLE ; + psf->bytewidth = 8 ; + break ; + + case MAT5_TYPE_FLOAT : + psf_log_printf (psf, "Data type : float\n") ; + psf->sf.format |= SF_FORMAT_FLOAT ; + psf->bytewidth = 4 ; + break ; + + case MAT5_TYPE_INT32 : + psf_log_printf (psf, "Data type : 32 bit PCM\n") ; + psf->sf.format |= SF_FORMAT_PCM_32 ; + psf->bytewidth = 4 ; + break ; + + case MAT5_TYPE_INT16 : + psf_log_printf (psf, "Data type : 16 bit PCM\n") ; + psf->sf.format |= SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + break ; + + case MAT5_TYPE_UCHAR : + psf_log_printf (psf, "Data type : unsigned 8 bit PCM\n") ; + psf->sf.format |= SF_FORMAT_PCM_U8 ; + psf->bytewidth = 1 ; + break ; + + default : + psf_log_printf (psf, "*** Error : Bad marker %08X\n", type) ; + return SFE_UNIMPLEMENTED ; + } ; + + psf->dataoffset = psf_ftell (psf) ; + psf->datalength = psf->filelength - psf->dataoffset ; + + return 0 ; +} /* mat5_read_header */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: dfdb6742-b2be-4be8-b390-d0c674e8bc8e +*/ diff --git a/nylsf/ms_adpcm.c b/nylsf/ms_adpcm.c new file mode 100644 index 0000000..0fc3403 --- /dev/null +++ b/nylsf/ms_adpcm.c @@ -0,0 +1,834 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" +#include "wav_w64.h" + +/* These required here because we write the header in this file. */ + +#define RIFF_MARKER (MAKE_MARKER ('R', 'I', 'F', 'F')) +#define WAVE_MARKER (MAKE_MARKER ('W', 'A', 'V', 'E')) +#define fmt_MARKER (MAKE_MARKER ('f', 'm', 't', ' ')) +#define fact_MARKER (MAKE_MARKER ('f', 'a', 'c', 't')) +#define data_MARKER (MAKE_MARKER ('d', 'a', 't', 'a')) + +#define WAVE_FORMAT_MS_ADPCM 0x0002 + +typedef struct +{ int channels, blocksize, samplesperblock, blocks, dataremaining ; + int blockcount ; + sf_count_t samplecount ; + short *samples ; + unsigned char *block ; +#if HAVE_FLEXIBLE_ARRAY + short dummydata [] ; /* ISO C99 struct flexible array. */ +#else + short dummydata [0] ; /* This is a hack an might not work. */ +#endif +} MSADPCM_PRIVATE ; + +/*============================================================================================ +** MS ADPCM static data and functions. +*/ + +static int AdaptationTable [] = +{ 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 +} ; + +/* TODO : The first 7 coef's are are always hardcode and must + appear in the actual WAVE file. They should be read in + in case a sound program added extras to the list. */ + +static int AdaptCoeff1 [MSADPCM_ADAPT_COEFF_COUNT] = +{ 256, 512, 0, 192, 240, 460, 392 +} ; + +static int AdaptCoeff2 [MSADPCM_ADAPT_COEFF_COUNT] = +{ 0, -256, 0, 64, 0, -208, -232 +} ; + +/*============================================================================================ +** MS ADPCM Block Layout. +** ====================== +** Block is usually 256, 512 or 1024 bytes depending on sample rate. +** For a mono file, the block is laid out as follows: +** byte purpose +** 0 block predictor [0..6] +** 1,2 initial idelta (positive) +** 3,4 sample 1 +** 5,6 sample 0 +** 7..n packed bytecodes +** +** For a stereo file, the block is laid out as follows: +** byte purpose +** 0 block predictor [0..6] for left channel +** 1 block predictor [0..6] for right channel +** 2,3 initial idelta (positive) for left channel +** 4,5 initial idelta (positive) for right channel +** 6,7 sample 1 for left channel +** 8,9 sample 1 for right channel +** 10,11 sample 0 for left channel +** 12,13 sample 0 for right channel +** 14..n packed bytecodes +*/ + +/*============================================================================================ +** Static functions. +*/ + +static int msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ; +static sf_count_t msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) ; + +static int msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ; +static sf_count_t msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, const short *ptr, int len) ; + +static sf_count_t msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static sf_count_t msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; +static int msadpcm_close (SF_PRIVATE *psf) ; + +static void choose_predictor (unsigned int channels, short *data, int *bpred, int *idelta) ; + +/*============================================================================================ +** MS ADPCM Read Functions. +*/ + +int +wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) +{ MSADPCM_PRIVATE *pms ; + unsigned int pmssize ; + int count ; + + if (psf->codec_data != NULL) + { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ; + return SFE_INTERNAL ; + } ; + + if (psf->mode == SFM_WRITE) + samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; + + pmssize = sizeof (MSADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ; + + if (! (psf->codec_data = malloc (pmssize))) + return SFE_MALLOC_FAILED ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + memset (pms, 0, pmssize) ; + + pms->samples = pms->dummydata ; + pms->block = (unsigned char*) (pms->dummydata + psf->sf.channels * samplesperblock) ; + + pms->channels = psf->sf.channels ; + pms->blocksize = blockalign ; + pms->samplesperblock = samplesperblock ; + + if (psf->mode == SFM_READ) + { pms->dataremaining = psf->datalength ; + + if (psf->datalength % pms->blocksize) + pms->blocks = psf->datalength / pms->blocksize + 1 ; + else + pms->blocks = psf->datalength / pms->blocksize ; + + count = 2 * (pms->blocksize - 6 * pms->channels) / pms->channels ; + if (pms->samplesperblock != count) + psf_log_printf (psf, "*** Warning : samplesperblock shoud be %d.\n", count) ; + + psf->sf.frames = (psf->datalength / pms->blocksize) * pms->samplesperblock ; + + psf_log_printf (psf, " bpred idelta\n") ; + + msadpcm_decode_block (psf, pms) ; + + psf->read_short = msadpcm_read_s ; + psf->read_int = msadpcm_read_i ; + psf->read_float = msadpcm_read_f ; + psf->read_double = msadpcm_read_d ; + } ; + + if (psf->mode == SFM_WRITE) + { pms->samples = pms->dummydata ; + + pms->samplecount = 0 ; + + psf->write_short = msadpcm_write_s ; + psf->write_int = msadpcm_write_i ; + psf->write_float = msadpcm_write_f ; + psf->write_double = msadpcm_write_d ; + } ; + + psf->codec_close = msadpcm_close ; + psf->seek = msadpcm_seek ; + + return 0 ; +} /* wav_w64_msadpcm_init */ + +static int +msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) +{ int chan, k, blockindx, sampleindx ; + short bytecode, bpred [2], chan_idelta [2] ; + + int predict ; + int current ; + int idelta ; + + pms->blockcount ++ ; + pms->samplecount = 0 ; + + if (pms->blockcount > pms->blocks) + { memset (pms->samples, 0, pms->samplesperblock * pms->channels) ; + return 1 ; + } ; + + if ((k = psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ; + + /* Read and check the block header. */ + + if (pms->channels == 1) + { bpred [0] = pms->block [0] ; + + if (bpred [0] >= 7) + psf_log_printf (psf, "MS ADPCM synchronisation error (%d).\n", bpred [0]) ; + + chan_idelta [0] = pms->block [1] | (pms->block [2] << 8) ; + chan_idelta [1] = 0 ; + + psf_log_printf (psf, "(%d) (%d)\n", bpred [0], chan_idelta [0]) ; + + pms->samples [1] = pms->block [3] | (pms->block [4] << 8) ; + pms->samples [0] = pms->block [5] | (pms->block [6] << 8) ; + blockindx = 7 ; + } + else + { bpred [0] = pms->block [0] ; + bpred [1] = pms->block [1] ; + + if (bpred [0] >= 7 || bpred [1] >= 7) + psf_log_printf (psf, "MS ADPCM synchronisation error (%d %d).\n", bpred [0], bpred [1]) ; + + chan_idelta [0] = pms->block [2] | (pms->block [3] << 8) ; + chan_idelta [1] = pms->block [4] | (pms->block [5] << 8) ; + + psf_log_printf (psf, "(%d, %d) (%d, %d)\n", bpred [0], bpred [1], chan_idelta [0], chan_idelta [1]) ; + + pms->samples [2] = pms->block [6] | (pms->block [7] << 8) ; + pms->samples [3] = pms->block [8] | (pms->block [9] << 8) ; + + pms->samples [0] = pms->block [10] | (pms->block [11] << 8) ; + pms->samples [1] = pms->block [12] | (pms->block [13] << 8) ; + + blockindx = 14 ; + } ; + + /*-------------------------------------------------------- + This was left over from a time when calculations were done + as ints rather than shorts. Keep this around as a reminder + in case I ever find a file which decodes incorrectly. + + if (chan_idelta [0] & 0x8000) + chan_idelta [0] -= 0x10000 ; + if (chan_idelta [1] & 0x8000) + chan_idelta [1] -= 0x10000 ; + --------------------------------------------------------*/ + + /* Pull apart the packed 4 bit samples and store them in their + ** correct sample positions. + */ + + sampleindx = 2 * pms->channels ; + while (blockindx < pms->blocksize) + { bytecode = pms->block [blockindx++] ; + pms->samples [sampleindx++] = (bytecode >> 4) & 0x0F ; + pms->samples [sampleindx++] = bytecode & 0x0F ; + } ; + + /* Decode the encoded 4 bit samples. */ + + for (k = 2 * pms->channels ; k < (pms->samplesperblock * pms->channels) ; k ++) + { chan = (pms->channels > 1) ? (k % 2) : 0 ; + + bytecode = pms->samples [k] & 0xF ; + + /* Compute next Adaptive Scale Factor (ASF) */ + idelta = chan_idelta [chan] ; + chan_idelta [chan] = (AdaptationTable [bytecode] * idelta) >> 8 ; /* => / 256 => FIXED_POINT_ADAPTATION_BASE == 256 */ + if (chan_idelta [chan] < 16) + chan_idelta [chan] = 16 ; + if (bytecode & 0x8) + bytecode -= 0x10 ; + + predict = ((pms->samples [k - pms->channels] * AdaptCoeff1 [bpred [chan]]) + + (pms->samples [k - 2 * pms->channels] * AdaptCoeff2 [bpred [chan]])) >> 8 ; /* => / 256 => FIXED_POINT_COEFF_BASE == 256 */ + current = (bytecode * idelta) + predict ; + + if (current > 32767) + current = 32767 ; + else if (current < -32768) + current = -32768 ; + + pms->samples [k] = current ; + } ; + + return 1 ; +} /* msadpcm_decode_block */ + +static sf_count_t +msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { if (pms->blockcount >= pms->blocks && pms->samplecount >= pms->samplesperblock) + { memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ; + return total ; + } ; + + if (pms->samplecount >= pms->samplesperblock) + msadpcm_decode_block (psf, pms) ; + + count = (pms->samplesperblock - pms->samplecount) * pms->channels ; + count = (len - indx > count) ? count : len - indx ; + + memcpy (&(ptr [indx]), &(pms->samples [pms->samplecount * pms->channels]), count * sizeof (short)) ; + indx += count ; + pms->samplecount += count / pms->channels ; + total = indx ; + } ; + + return total ; +} /* msadpcm_read_block */ + +static sf_count_t +msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + int readcount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + while (len > 0) + { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = msadpcm_read_block (psf, pms, ptr, readcount) ; + + total += count ; + len -= count ; + if (count != readcount) + break ; + } ; + + return total ; +} /* msadpcm_read_s */ + +static sf_count_t +msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = msadpcm_read_block (psf, pms, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = sptr [k] << 16 ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + return total ; +} /* msadpcm_read_i */ + +static sf_count_t +msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = msadpcm_read_block (psf, pms, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (float) (sptr [k]) ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + return total ; +} /* msadpcm_read_f */ + +static sf_count_t +msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + short *sptr ; + int k, bufferlen, readcount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = msadpcm_read_block (psf, pms, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (double) (sptr [k]) ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + return total ; +} /* msadpcm_read_d */ + +static sf_count_t +msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ MSADPCM_PRIVATE *pms ; + int newblock, newsample ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + if (psf->datalength < 0 || psf->dataoffset < 0) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (offset == 0) + { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + pms->blockcount = 0 ; + msadpcm_decode_block (psf, pms) ; + pms->samplecount = 0 ; + return 0 ; + } ; + + if (offset < 0 || offset > pms->blocks * pms->samplesperblock) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + newblock = offset / pms->samplesperblock ; + newsample = offset % pms->samplesperblock ; + + if (mode == SFM_READ) + { psf_fseek (psf, psf->dataoffset + newblock * pms->blocksize, SEEK_SET) ; + pms->blockcount = newblock ; + msadpcm_decode_block (psf, pms) ; + pms->samplecount = newsample ; + } + else + { /* What to do about write??? */ + psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + return newblock * pms->samplesperblock + newsample ; +} /* msadpcm_seek */ + +/*========================================================================================== +** MS ADPCM Write Functions. +*/ + +void +msadpcm_write_adapt_coeffs (SF_PRIVATE *psf) +{ int k ; + + for (k = 0 ; k < MSADPCM_ADAPT_COEFF_COUNT ; k++) + psf_binheader_writef (psf, "22", AdaptCoeff1 [k], AdaptCoeff2 [k]) ; +} /* msadpcm_write_adapt_coeffs */ + +/*========================================================================================== +*/ + +static int +msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) +{ unsigned int blockindx ; + unsigned char byte ; + int chan, k, predict, bpred [2], idelta [2], errordelta, newsamp ; + + choose_predictor (pms->channels, pms->samples, bpred, idelta) ; + + /* Write the block header. */ + + if (pms->channels == 1) + { pms->block [0] = bpred [0] ; + pms->block [1] = idelta [0] & 0xFF ; + pms->block [2] = idelta [0] >> 8 ; + pms->block [3] = pms->samples [1] & 0xFF ; + pms->block [4] = pms->samples [1] >> 8 ; + pms->block [5] = pms->samples [0] & 0xFF ; + pms->block [6] = pms->samples [0] >> 8 ; + + blockindx = 7 ; + byte = 0 ; + + /* Encode the samples as 4 bit. */ + + for (k = 2 ; k < pms->samplesperblock ; k++) + { predict = (pms->samples [k-1] * AdaptCoeff1 [bpred [0]] + pms->samples [k-2] * AdaptCoeff2 [bpred [0]]) >> 8 ; + errordelta = (pms->samples [k] - predict) / idelta [0] ; + if (errordelta < -8) + errordelta = -8 ; + else if (errordelta > 7) + errordelta = 7 ; + newsamp = predict + (idelta [0] * errordelta) ; + if (newsamp > 32767) + newsamp = 32767 ; + else if (newsamp < -32768) + newsamp = -32768 ; + if (errordelta < 0) + errordelta += 0x10 ; + + byte = (byte << 4) | (errordelta & 0xF) ; + if (k % 2) + { pms->block [blockindx++] = byte ; + byte = 0 ; + } ; + + idelta [0] = (idelta [0] * AdaptationTable [errordelta]) >> 8 ; + if (idelta [0] < 16) + idelta [0] = 16 ; + pms->samples [k] = newsamp ; + } ; + } + else + { /* Stereo file. */ + pms->block [0] = bpred [0] ; + pms->block [1] = bpred [1] ; + + pms->block [2] = idelta [0] & 0xFF ; + pms->block [3] = idelta [0] >> 8 ; + pms->block [4] = idelta [1] & 0xFF ; + pms->block [5] = idelta [1] >> 8 ; + + pms->block [6] = pms->samples [2] & 0xFF ; + pms->block [7] = pms->samples [2] >> 8 ; + pms->block [8] = pms->samples [3] & 0xFF ; + pms->block [9] = pms->samples [3] >> 8 ; + + pms->block [10] = pms->samples [0] & 0xFF ; + pms->block [11] = pms->samples [0] >> 8 ; + pms->block [12] = pms->samples [1] & 0xFF ; + pms->block [13] = pms->samples [1] >> 8 ; + + blockindx = 14 ; + byte = 0 ; + chan = 1 ; + + for (k = 4 ; k < 2 * pms->samplesperblock ; k++) + { chan = k & 1 ; + + predict = (pms->samples [k-2] * AdaptCoeff1 [bpred [chan]] + pms->samples [k-4] * AdaptCoeff2 [bpred [chan]]) >> 8 ; + errordelta = (pms->samples [k] - predict) / idelta [chan] ; + + + if (errordelta < -8) + errordelta = -8 ; + else if (errordelta > 7) + errordelta = 7 ; + newsamp = predict + (idelta [chan] * errordelta) ; + if (newsamp > 32767) + newsamp = 32767 ; + else if (newsamp < -32768) + newsamp = -32768 ; + if (errordelta < 0) + errordelta += 0x10 ; + + byte = (byte << 4) | (errordelta & 0xF) ; + + if (chan) + { pms->block [blockindx++] = byte ; + byte = 0 ; + } ; + + idelta [chan] = (idelta [chan] * AdaptationTable [errordelta]) >> 8 ; + if (idelta [chan] < 16) + idelta [chan] = 16 ; + pms->samples [k] = newsamp ; + } ; + } ; + + /* Write the block to disk. */ + + if ((k = psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) + psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ; + + memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ; + + pms->blockcount ++ ; + pms->samplecount = 0 ; + + return 1 ; +} /* msadpcm_encode_block */ + +static sf_count_t +msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, const short *ptr, int len) +{ int count, total = 0, indx = 0 ; + + while (indx < len) + { count = (pms->samplesperblock - pms->samplecount) * pms->channels ; + + if (count > len - indx) + count = len - indx ; + + memcpy (&(pms->samples [pms->samplecount * pms->channels]), &(ptr [total]), count * sizeof (short)) ; + indx += count ; + pms->samplecount += count / pms->channels ; + total = indx ; + + if (pms->samplecount >= pms->samplesperblock) + msadpcm_encode_block (psf, pms) ; + } ; + + return total ; +} /* msadpcm_write_block */ + +static sf_count_t +msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + int writecount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + while (len > 0) + { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = msadpcm_write_block (psf, pms, ptr, writecount) ; + + total += count ; + len -= count ; + if (count != writecount) + break ; + } ; + + return total ; +} /* msadpcm_write_s */ + +static sf_count_t +msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = ptr [total + k] >> 16 ; + count = msadpcm_write_block (psf, pms, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + return total ; +} /* msadpcm_write_i */ + +static sf_count_t +msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrintf (normfact * ptr [total + k]) ; + count = msadpcm_write_block (psf, pms, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + return total ; +} /* msadpcm_write_f */ + +static sf_count_t +msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ MSADPCM_PRIVATE *pms ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + if (! psf->codec_data) + return 0 ; + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrint (normfact * ptr [total + k]) ; + count = msadpcm_write_block (psf, pms, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + return total ; +} /* msadpcm_write_d */ + +/*======================================================================================== +*/ + +static int +msadpcm_close (SF_PRIVATE *psf) +{ MSADPCM_PRIVATE *pms ; + + pms = (MSADPCM_PRIVATE*) psf->codec_data ; + + if (psf->mode == SFM_WRITE) + { /* Now we know static int for certain the length of the file we can + ** re-write the header. + */ + + if (pms->samplecount && pms->samplecount < pms->samplesperblock) + msadpcm_encode_block (psf, pms) ; + } ; + + return 0 ; +} /* msadpcm_close */ + +/*======================================================================================== +** Static functions. +*/ + +/*---------------------------------------------------------------------------------------- +** Choosing the block predictor. +** Each block requires a predictor and an idelta for each channel. +** The predictor is in the range [0..6] which is an indx into the two AdaptCoeff tables. +** The predictor is chosen by trying all of the possible predictors on a small set of +** samples at the beginning of the block. The predictor with the smallest average +** abs (idelta) is chosen as the best predictor for this block. +** The value of idelta is chosen to to give a 4 bit code value of +/- 4 (approx. half the +** max. code value). If the average abs (idelta) is zero, the sixth predictor is chosen. +** If the value of idelta is less then 16 it is set to 16. +** +** Microsoft uses an IDELTA_COUNT (number of sample pairs used to choose best predictor) +** value of 3. The best possible results would be obtained by using all the samples to +** choose the predictor. +*/ + +#define IDELTA_COUNT 3 + +static void +choose_predictor (unsigned int channels, short *data, int *block_pred, int *idelta) +{ unsigned int chan, k, bpred, idelta_sum, best_bpred, best_idelta ; + + for (chan = 0 ; chan < channels ; chan++) + { best_bpred = best_idelta = 0 ; + + for (bpred = 0 ; bpred < 7 ; bpred++) + { idelta_sum = 0 ; + for (k = 2 ; k < 2 + IDELTA_COUNT ; k++) + idelta_sum += abs (data [k * channels] - ((data [(k - 1) * channels] * AdaptCoeff1 [bpred] + data [(k - 2) * channels] * AdaptCoeff2 [bpred]) >> 8)) ; + idelta_sum /= (4 * IDELTA_COUNT) ; + + if (bpred == 0 || idelta_sum < best_idelta) + { best_bpred = bpred ; + best_idelta = idelta_sum ; + } ; + + if (! idelta_sum) + { best_bpred = bpred ; + best_idelta = 16 ; + break ; + } ; + + } ; /* for bpred ... */ + if (best_idelta < 16) + best_idelta = 16 ; + + block_pred [chan] = best_bpred ; + idelta [chan] = best_idelta ; + } ; + + return ; +} /* choose_predictor */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: a98908a3-5305-4935-872b-77d6a86c330f +*/ diff --git a/nylsf/nist.c b/nylsf/nist.c new file mode 100644 index 0000000..2ab20db --- /dev/null +++ b/nylsf/nist.c @@ -0,0 +1,367 @@ +/* +** Copyright (C) 1999-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** Some of the information used to read NIST files was gleaned from +** reading the code of Bill Schottstaedt's sndlib library +** ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz +** However, no code from that package was used. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +*/ + +#define NIST_HEADER_LENGTH 1024 + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int nist_close (SF_PRIVATE *psf) ; +static int nist_write_header (SF_PRIVATE *psf, int calc_length) ; +static int nist_read_header (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +*/ + +int +nist_open (SF_PRIVATE *psf) +{ int error ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = nist_read_header (psf))) + return error ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_NIST) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU) + psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + psf->sf.frames = 0 ; + + if ((error = nist_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = nist_write_header ; + } ; + + psf->container_close = nist_close ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + default : error = SFE_UNIMPLEMENTED ; + break ; + } ; + + return error ; +} /* nist_open */ + +/*------------------------------------------------------------------------------ +*/ + +static char bad_header [] = +{ 'N', 'I', 'S', 'T', '_', '1', 'A', 0x0d, 0x0a, + ' ', ' ', ' ', '1', '0', '2', '4', 0x0d, 0x0a, + 0 +} ; + + static int +nist_read_header (SF_PRIVATE *psf) +{ char *psf_header ; + int bitwidth = 0, bytes = 0, count, encoding ; + char str [64], *cptr ; + long samples ; + + psf->sf.format = SF_FORMAT_NIST ; + + psf_header = psf->u.cbuf ; + + if (sizeof (psf->header) <= NIST_HEADER_LENGTH) + return SFE_INTERNAL ; + + /* Go to start of file and read in the whole header. */ + psf_binheader_readf (psf, "pb", 0, psf_header, NIST_HEADER_LENGTH) ; + + /* Header is a string, so make sure it is null terminated. */ + psf_header [NIST_HEADER_LENGTH] = 0 ; + + /* Now trim the header after the end marker. */ + if ((cptr = strstr (psf_header, "end_head"))) + { cptr += strlen ("end_head") + 1 ; + cptr [0] = 0 ; + } ; + + if (strstr (psf_header, bad_header) == psf_header) + return SFE_NIST_CRLF_CONVERISON ; + + /* Make sure its a NIST file. */ + if (strstr (psf_header, "NIST_1A\n") != psf_header) + { psf_log_printf (psf, "Not a NIST file.\n") ; + return SFE_NIST_BAD_HEADER ; + } ; + + if (sscanf (psf_header, "NIST_1A\n%d\n", &count) == 1) + psf->dataoffset = count ; + else + { psf_log_printf (psf, "*** Suspicious header length.\n") ; + psf->dataoffset = NIST_HEADER_LENGTH ; + } ; + + /* Determine sample encoding, start by assuming PCM. */ + encoding = SF_FORMAT_PCM_U8 ; + if ((cptr = strstr (psf_header, "sample_coding -s"))) + { sscanf (cptr, "sample_coding -s%d %63s", &count, str) ; + + if (strcmp (str, "pcm") == 0) + encoding = SF_FORMAT_PCM_U8 ; + else if (strcmp (str, "alaw") == 0) + encoding = SF_FORMAT_ALAW ; + else if ((strcmp (str, "ulaw") == 0) || (strcmp (str, "mu-law") == 0)) + encoding = SF_FORMAT_ULAW ; + else + { psf_log_printf (psf, "*** Unknown encoding : %s\n", str) ; + encoding = 0 ; + } ; + } ; + + if ((cptr = strstr (psf_header, "channel_count -i "))) + sscanf (cptr, "channel_count -i %d", &(psf->sf.channels)) ; + + if ((cptr = strstr (psf_header, "sample_rate -i "))) + sscanf (cptr, "sample_rate -i %d", &(psf->sf.samplerate)) ; + + if ((cptr = strstr (psf_header, "sample_count -i "))) + { sscanf (psf_header, "sample_count -i %ld", &samples) ; + psf->sf.frames = samples ; + } ; + + if ((cptr = strstr (psf_header, "sample_n_bytes -i "))) + sscanf (cptr, "sample_n_bytes -i %d", &(psf->bytewidth)) ; + + /* Default endian-ness (for 8 bit, u-law, A-law. */ + psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; + + /* This is where we figure out endian-ness. */ + if ((cptr = strstr (psf_header, "sample_byte_format -s"))) + { sscanf (cptr, "sample_byte_format -s%d %8s", &bytes, str) ; + if (bytes > 1) + { if (psf->bytewidth == 0) + psf->bytewidth = bytes ; + else if (psf->bytewidth != bytes) + { psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ; + return SFE_NIST_BAD_ENCODING ; + } ; + + if (strstr (str, "01") == str) + psf->endian = SF_ENDIAN_LITTLE ; + else if (strstr (str, "10")) + psf->endian = SF_ENDIAN_BIG ; + else + { psf_log_printf (psf, "Weird endian-ness : %s\n", str) ; + return SFE_NIST_BAD_ENCODING ; + } ; + } ; + + psf->sf.format |= psf->endian ; + } ; + + if ((cptr = strstr (psf_header, "sample_sig_bits -i "))) + sscanf (cptr, "sample_sig_bits -i %d", &bitwidth) ; + + if (strstr (psf_header, "channels_interleaved -s5 FALSE")) + { psf_log_printf (psf, "Non-interleaved data unsupported.\n", str) ; + return SFE_NIST_BAD_ENCODING ; + } ; + + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + psf->datalength = psf->filelength - psf->dataoffset ; + + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + + if (encoding == SF_FORMAT_PCM_U8) + { switch (psf->bytewidth) + { case 1 : + psf->sf.format |= SF_FORMAT_PCM_S8 ; + break ; + + case 2 : + psf->sf.format |= SF_FORMAT_PCM_16 ; + break ; + + case 3 : + psf->sf.format |= SF_FORMAT_PCM_24 ; + break ; + + case 4 : + psf->sf.format |= SF_FORMAT_PCM_32 ; + break ; + + default : break ; + } ; + } + else if (encoding != 0) + psf->sf.format |= encoding ; + else + return SFE_UNIMPLEMENTED ; + + return 0 ; +} /* nist_read_header */ + +static int +nist_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + nist_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* nist_close */ + +/*========================================================================= +*/ + +static int +nist_write_header (SF_PRIVATE *psf, int calc_length) +{ const char *end_str ; + long samples ; + sf_count_t current ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + if (psf->endian == SF_ENDIAN_BIG) + end_str = "10" ; + else if (psf->endian == SF_ENDIAN_LITTLE) + end_str = "01" ; + else + end_str = "error" ; + + /* Clear the whole header. */ + memset (psf->header, 0, sizeof (psf->header)) ; + psf->headindex = 0 ; + + psf_fseek (psf, 0, SEEK_SET) ; + + psf_asciiheader_printf (psf, "NIST_1A\n 1024\n") ; + psf_asciiheader_printf (psf, "channel_count -i %d\n", psf->sf.channels) ; + psf_asciiheader_printf (psf, "sample_rate -i %d\n", psf->sf.samplerate) ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n") ; + psf_asciiheader_printf (psf, "sample_n_bytes -i 1\n" + "sample_sig_bits -i 8\n") ; + break ; + + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + psf_asciiheader_printf (psf, "sample_n_bytes -i %d\n", psf->bytewidth) ; + psf_asciiheader_printf (psf, "sample_sig_bits -i %d\n", psf->bytewidth * 8) ; + psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n" + "sample_byte_format -s%d %s\n", psf->bytewidth, end_str) ; + break ; + + case SF_FORMAT_ALAW : + psf_asciiheader_printf (psf, "sample_coding -s4 alaw\n") ; + psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; + break ; + + case SF_FORMAT_ULAW : + psf_asciiheader_printf (psf, "sample_coding -s4 ulaw\n") ; + psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + psf->dataoffset = NIST_HEADER_LENGTH ; + + /* Fix this */ + samples = psf->sf.frames ; + psf_asciiheader_printf (psf, "sample_count -i %ld\n", samples) ; + psf_asciiheader_printf (psf, "end_head\n") ; + + /* Zero fill to dataoffset. */ + psf_binheader_writef (psf, "z", (size_t) (NIST_HEADER_LENGTH - psf->headindex)) ; + + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* nist_write_header */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: b45ed85d-9e22-4ad9-b78c-4b58b67152a8 +*/ diff --git a/nylsf/ogg.c b/nylsf/ogg.c new file mode 100644 index 0000000..869baa9 --- /dev/null +++ b/nylsf/ogg.c @@ -0,0 +1,44 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program ; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +int +ogg_open (SF_PRIVATE *psf) +{ if (psf) + return SFE_UNIMPLEMENTED ; + return (psf && 0) ; +} /* ogg_open */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 9ff1fe9c-629e-4e9c-9ef5-3d0eb1e427a0 +*/ diff --git a/nylsf/paf.c b/nylsf/paf.c new file mode 100644 index 0000000..d98263c --- /dev/null +++ b/nylsf/paf.c @@ -0,0 +1,843 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define FAP_MARKER (MAKE_MARKER ('f', 'a', 'p', ' ')) +#define PAF_MARKER (MAKE_MARKER (' ', 'p', 'a', 'f')) + +/*------------------------------------------------------------------------------ +** Other defines. +*/ + +#define PAF_HEADER_LENGTH 2048 + +#define PAF24_SAMPLES_PER_BLOCK 10 +#define PAF24_BLOCK_SIZE 32 + +/*------------------------------------------------------------------------------ +** Typedefs. +*/ + +typedef struct +{ int version ; + int endianness ; + int samplerate ; + int format ; + int channels ; + int source ; +} PAF_FMT ; + +typedef struct +{ int max_blocks, channels, samplesperblock, blocksize ; + int read_block, write_block, read_count, write_count ; + sf_count_t sample_count ; + int *samples ; + unsigned char *block ; +#if HAVE_FLEXIBLE_ARRAY + int data [] ; /* ISO C99 struct flexible array. */ +#else + int data [1] ; /* This is a hack and may not work. */ +#endif +} PAF24_PRIVATE ; + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int paf24_init (SF_PRIVATE *psf) ; + +static int paf_read_header (SF_PRIVATE *psf) ; +static int paf_write_header (SF_PRIVATE *psf, int calc_length) ; + +static sf_count_t paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t paf24_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static sf_count_t paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; + +enum +{ PAF_PCM_16 = 0, + PAF_PCM_24 = 1, + PAF_PCM_S8 = 2 +} ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +paf_open (SF_PRIVATE *psf) +{ int subformat, error, endian ; + + psf->dataoffset = PAF_HEADER_LENGTH ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = paf_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF) + return SFE_BAD_OPEN_FORMAT ; + + endian = psf->sf.format & SF_FORMAT_ENDMASK ; + + /* PAF is by default big endian. */ + psf->endian = SF_ENDIAN_BIG ; + + if (endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && (endian == SF_ENDIAN_CPU))) + psf->endian = SF_ENDIAN_LITTLE ; + + if ((error = paf_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = paf_write_header ; + } ; + + switch (subformat) + { case SF_FORMAT_PCM_S8 : + psf->bytewidth = 1 ; + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_16 : + psf->bytewidth = 2 ; + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_24 : + /* No bytewidth because of whacky 24 bit encoding. */ + error = paf24_init (psf) ; + break ; + + default : return SFE_PAF_UNKNOWN_FORMAT ; + } ; + + return error ; +} /* paf_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +paf_read_header (SF_PRIVATE *psf) +{ PAF_FMT paf_fmt ; + int marker ; + + memset (&paf_fmt, 0, sizeof (paf_fmt)) ; + psf_binheader_readf (psf, "pm", 0, &marker) ; + + psf_log_printf (psf, "Signature : '%M'\n", marker) ; + + if (marker == PAF_MARKER) + { psf_binheader_readf (psf, "E444444", &(paf_fmt.version), &(paf_fmt.endianness), + &(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ; + } + else if (marker == FAP_MARKER) + { psf_binheader_readf (psf, "e444444", &(paf_fmt.version), &(paf_fmt.endianness), + &(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ; + } + else + return SFE_PAF_NO_MARKER ; + + psf_log_printf (psf, "Version : %d\n", paf_fmt.version) ; + + if (paf_fmt.version != 0) + { psf_log_printf (psf, "*** Bad version number. should be zero.\n") ; + return SFE_PAF_VERSION ; + } ; + + psf_log_printf (psf, "Sample Rate : %d\n", paf_fmt.samplerate) ; + psf_log_printf (psf, "Channels : %d\n", paf_fmt.channels) ; + + psf_log_printf (psf, "Endianness : %d => ", paf_fmt.endianness) ; + if (paf_fmt.endianness) + { psf_log_printf (psf, "Little\n", paf_fmt.endianness) ; + psf->endian = SF_ENDIAN_LITTLE ; + } + else + { psf_log_printf (psf, "Big\n", paf_fmt.endianness) ; + psf->endian = SF_ENDIAN_BIG ; + } ; + + if (psf->filelength < PAF_HEADER_LENGTH) + return SFE_PAF_SHORT_HEADER ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + psf_binheader_readf (psf, "p", (int) psf->dataoffset) ; + + psf->sf.samplerate = paf_fmt.samplerate ; + psf->sf.channels = paf_fmt.channels ; + + /* Only fill in type major. */ + psf->sf.format = SF_FORMAT_PAF ; + + psf_log_printf (psf, "Format : %d => ", paf_fmt.format) ; + + /* PAF is by default big endian. */ + psf->sf.format |= paf_fmt.endianness ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ; + + switch (paf_fmt.format) + { case PAF_PCM_S8 : + psf_log_printf (psf, "8 bit linear PCM\n") ; + psf->bytewidth = 1 ; + + psf->sf.format |= SF_FORMAT_PCM_S8 ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + psf->sf.frames = psf->datalength / psf->blockwidth ; + break ; + + case PAF_PCM_16 : + psf_log_printf (psf, "16 bit linear PCM\n") ; + psf->bytewidth = 2 ; + + psf->sf.format |= SF_FORMAT_PCM_16 ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + psf->sf.frames = psf->datalength / psf->blockwidth ; + break ; + + case PAF_PCM_24 : + psf_log_printf (psf, "24 bit linear PCM\n") ; + psf->bytewidth = 3 ; + + psf->sf.format |= SF_FORMAT_PCM_24 ; + + psf->blockwidth = 0 ; + psf->sf.frames = PAF24_SAMPLES_PER_BLOCK * psf->datalength / + (PAF24_BLOCK_SIZE * psf->sf.channels) ; + break ; + + default : psf_log_printf (psf, "Unknown\n") ; + return SFE_PAF_UNKNOWN_FORMAT ; + break ; + } ; + + psf_log_printf (psf, "Source : %d => ", paf_fmt.source) ; + + switch (paf_fmt.source) + { case 1 : psf_log_printf (psf, "Analog Recording\n") ; + break ; + case 2 : psf_log_printf (psf, "Digital Transfer\n") ; + break ; + case 3 : psf_log_printf (psf, "Multi-track Mixdown\n") ; + break ; + case 5 : psf_log_printf (psf, "Audio Resulting From DSP Processing\n") ; + break ; + default : psf_log_printf (psf, "Unknown\n") ; + break ; + } ; + + return 0 ; +} /* paf_read_header */ + +static int +paf_write_header (SF_PRIVATE *psf, int calc_length) +{ int paf_format ; + + /* PAF header already written so no need to re-write. */ + if (psf_ftell (psf) >= PAF_HEADER_LENGTH) + return 0 ; + + psf->dataoffset = PAF_HEADER_LENGTH ; + + psf->dataoffset = PAF_HEADER_LENGTH ; + + /* Prevent compiler warning. */ + calc_length = calc_length ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + paf_format = PAF_PCM_S8 ; + break ; + + case SF_FORMAT_PCM_16 : + paf_format = PAF_PCM_16 ; + break ; + + case SF_FORMAT_PCM_24 : + paf_format = PAF_PCM_24 ; + break ; + + default : return SFE_PAF_UNKNOWN_FORMAT ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + if (psf->endian == SF_ENDIAN_BIG) + { /* Marker, version, endianness, samplerate */ + psf_binheader_writef (psf, "Em444", PAF_MARKER, 0, 0, psf->sf.samplerate) ; + /* format, channels, source */ + psf_binheader_writef (psf, "E444", paf_format, psf->sf.channels, 0) ; + } + else if (psf->endian == SF_ENDIAN_LITTLE) + { /* Marker, version, endianness, samplerate */ + psf_binheader_writef (psf, "em444", FAP_MARKER, 0, 1, psf->sf.samplerate) ; + /* format, channels, source */ + psf_binheader_writef (psf, "e444", paf_format, psf->sf.channels, 0) ; + } ; + + /* Zero fill to dataoffset. */ + psf_binheader_writef (psf, "z", (size_t) (psf->dataoffset - psf->headindex)) ; + + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + return psf->error ; +} /* paf_write_header */ + +/*=============================================================================== +** 24 bit PAF files have a really weird encoding. +** For a mono file, 10 samples (each being 3 bytes) are packed into a 32 byte +** block. The 8 ints in this 32 byte block are then endian swapped (as ints) +** if necessary before being written to disk. +** For a stereo file, blocks of 10 samples from the same channel are encoded +** into 32 bytes as for the mono case. The 32 byte blocks are then interleaved +** on disk. +** Reading has to reverse the above process :-). +** Weird!!! +** +** The code below attempts to gain efficiency while maintaining readability. +*/ + +static int paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ; +static int paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ; +static int paf24_close (SF_PRIVATE *psf) ; + + +static int +paf24_init (SF_PRIVATE *psf) +{ PAF24_PRIVATE *ppaf24 ; + int paf24size ; + + paf24size = sizeof (PAF24_PRIVATE) + psf->sf.channels * + (PAF24_BLOCK_SIZE + PAF24_SAMPLES_PER_BLOCK * sizeof (int)) ; + + /* + ** Not exatly sure why this needs to be here but the tests + ** fail without it. + */ + psf->last_op = 0 ; + + if (! (psf->codec_data = malloc (paf24size))) + return SFE_MALLOC_FAILED ; + + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + memset (ppaf24, 0, paf24size) ; + + ppaf24->channels = psf->sf.channels ; + ppaf24->samples = ppaf24->data ; + ppaf24->block = (unsigned char*) (ppaf24->data + PAF24_SAMPLES_PER_BLOCK * ppaf24->channels) ; + + ppaf24->blocksize = PAF24_BLOCK_SIZE * ppaf24->channels ; + ppaf24->samplesperblock = PAF24_SAMPLES_PER_BLOCK ; + + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { paf24_read_block (psf, ppaf24) ; /* Read first block. */ + + psf->read_short = paf24_read_s ; + psf->read_int = paf24_read_i ; + psf->read_float = paf24_read_f ; + psf->read_double = paf24_read_d ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { psf->write_short = paf24_write_s ; + psf->write_int = paf24_write_i ; + psf->write_float = paf24_write_f ; + psf->write_double = paf24_write_d ; + } ; + + psf->seek = paf24_seek ; + psf->container_close = paf24_close ; + + psf->filelength = psf_get_filelen (psf) ; + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->datalength % PAF24_BLOCK_SIZE) + { if (psf->mode == SFM_READ) + psf_log_printf (psf, "*** Warning : file seems to be truncated.\n") ; + ppaf24->max_blocks = psf->datalength / ppaf24->blocksize + 1 ; + } + else + ppaf24->max_blocks = psf->datalength / ppaf24->blocksize ; + + ppaf24->read_block = 0 ; + if (psf->mode == SFM_RDWR) + ppaf24->write_block = ppaf24->max_blocks ; + else + ppaf24->write_block = 0 ; + + psf->sf.frames = ppaf24->samplesperblock * ppaf24->max_blocks ; + ppaf24->sample_count = psf->sf.frames ; + + return 0 ; +} /* paf24_init */ + +static sf_count_t +paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ PAF24_PRIVATE *ppaf24 ; + int newblock, newsample ; + + if (psf->codec_data == NULL) + { psf->error = SFE_INTERNAL ; + return PSF_SEEK_ERROR ; + } ; + + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + if (mode == SFM_READ && ppaf24->write_count > 0) + paf24_write_block (psf, ppaf24) ; + + newblock = offset / ppaf24->samplesperblock ; + newsample = offset % ppaf24->samplesperblock ; + + switch (mode) + { case SFM_READ : + if (psf->last_op == SFM_WRITE && ppaf24->write_count) + paf24_write_block (psf, ppaf24) ; + + psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ; + ppaf24->read_block = newblock ; + paf24_read_block (psf, ppaf24) ; + ppaf24->read_count = newsample ; + break ; + + case SFM_WRITE : + if (offset > ppaf24->sample_count) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (psf->last_op == SFM_WRITE && ppaf24->write_count) + paf24_write_block (psf, ppaf24) ; + + psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ; + ppaf24->write_block = newblock ; + paf24_read_block (psf, ppaf24) ; + ppaf24->write_count = newsample ; + break ; + + default : + psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + return newblock * ppaf24->samplesperblock + newsample ; +} /* paf24_seek */ + +static int +paf24_close (SF_PRIVATE *psf) +{ PAF24_PRIVATE *ppaf24 ; + + if (psf->codec_data == NULL) + return 0 ; + + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (ppaf24->write_count > 0) + paf24_write_block (psf, ppaf24) ; + } ; + + return 0 ; +} /* paf24_close */ + +/*--------------------------------------------------------------------------- +*/ +static int +paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) +{ int k, channel ; + unsigned char *cptr ; + + ppaf24->read_block ++ ; + ppaf24->read_count = 0 ; + + if (ppaf24->read_block * ppaf24->samplesperblock > ppaf24->sample_count) + { memset (ppaf24->samples, 0, ppaf24->samplesperblock * ppaf24->channels) ; + return 1 ; + } ; + + /* Read the block. */ + if ((k = psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, ppaf24->blocksize) ; + + + if (CPU_IS_LITTLE_ENDIAN) + { /* Do endian swapping if necessary. */ + if (psf->endian == SF_ENDIAN_BIG) + endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; + + /* Unpack block. */ + for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) + { channel = k % ppaf24->channels ; + cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; + ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ; + } ; + } + else + { /* Do endian swapping if necessary. */ + if (psf->endian == SF_ENDIAN_BIG) + endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; + + /* Unpack block. */ + for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) + { channel = k % ppaf24->channels ; + cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; + ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ; + } ; + } ; + + return 1 ; +} /* paf24_read_block */ + +static int +paf24_read (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, int *ptr, int len) +{ int count, total = 0 ; + + while (total < len) + { if (ppaf24->read_block * ppaf24->samplesperblock >= ppaf24->sample_count) + { memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ; + return total ; + } ; + + if (ppaf24->read_count >= ppaf24->samplesperblock) + paf24_read_block (psf, ppaf24) ; + + count = (ppaf24->samplesperblock - ppaf24->read_count) * ppaf24->channels ; + count = (len - total > count) ? count : len - total ; + + memcpy (&(ptr [total]), &(ppaf24->samples [ppaf24->read_count * ppaf24->channels]), count * sizeof (int)) ; + total += count ; + ppaf24->read_count += count / ppaf24->channels ; + } ; + + return total ; +} /* paf24_read */ + +static sf_count_t +paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int *iptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = paf24_read (psf, ppaf24, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = iptr [k] >> 16 ; + total += count ; + len -= readcount ; + } ; + return total ; +} /* paf24_read_s */ + +static sf_count_t +paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int total ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + total = paf24_read (psf, ppaf24, ptr, len) ; + + return total ; +} /* paf24_read_i */ + +static sf_count_t +paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int *iptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = paf24_read (psf, ppaf24, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * iptr [k] ; + total += count ; + len -= readcount ; + } ; + return total ; +} /* paf24_read_f */ + +static sf_count_t +paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int *iptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = paf24_read (psf, ppaf24, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * iptr [k] ; + total += count ; + len -= readcount ; + } ; + return total ; +} /* paf24_read_d */ + +/*--------------------------------------------------------------------------- +*/ + +static int +paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) +{ int k, nextsample, channel ; + unsigned char *cptr ; + + /* First pack block. */ + + if (CPU_IS_LITTLE_ENDIAN) + { for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) + { channel = k % ppaf24->channels ; + cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; + nextsample = ppaf24->samples [k] >> 8 ; + cptr [0] = nextsample ; + cptr [1] = nextsample >> 8 ; + cptr [2] = nextsample >> 16 ; + } ; + + /* Do endian swapping if necessary. */ + if (psf->endian == SF_ENDIAN_BIG) + endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; + } + else if (CPU_IS_BIG_ENDIAN) + { /* This is correct. */ + for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) + { channel = k % ppaf24->channels ; + cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; + nextsample = ppaf24->samples [k] >> 8 ; + cptr [0] = nextsample ; + cptr [1] = nextsample >> 8 ; + cptr [2] = nextsample >> 16 ; + } ; + if (psf->endian == SF_ENDIAN_BIG) + endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; + } ; + + /* Write block to disk. */ + if ((k = psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) + psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, ppaf24->blocksize) ; + + if (ppaf24->sample_count < ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count) + ppaf24->sample_count = ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count ; + + if (ppaf24->write_count == ppaf24->samplesperblock) + { ppaf24->write_block ++ ; + ppaf24->write_count = 0 ; + } ; + + return 1 ; +} /* paf24_write_block */ + +static int +paf24_write (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, const int *ptr, int len) +{ int count, total = 0 ; + + while (total < len) + { count = (ppaf24->samplesperblock - ppaf24->write_count) * ppaf24->channels ; + + if (count > len - total) + count = len - total ; + + memcpy (&(ppaf24->samples [ppaf24->write_count * ppaf24->channels]), &(ptr [total]), count * sizeof (int)) ; + total += count ; + ppaf24->write_count += count / ppaf24->channels ; + + if (ppaf24->write_count >= ppaf24->samplesperblock) + paf24_write_block (psf, ppaf24) ; + } ; + + return total ; +} /* paf24_write */ + +static sf_count_t +paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int *iptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = ptr [total + k] << 16 ; + count = paf24_write (psf, ppaf24, iptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + return total ; +} /* paf24_write_s */ + +static sf_count_t +paf24_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int writecount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + while (len > 0) + { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = paf24_write (psf, ppaf24, ptr, writecount) ; + + total += count ; + len -= count ; + if (count != writecount) + break ; + } ; + + return total ; +} /* paf24_write_i */ + +static sf_count_t +paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int *iptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = lrintf (normfact * ptr [total + k]) ; + count = paf24_write (psf, ppaf24, iptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* paf24_write_f */ + +static sf_count_t +paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ PAF24_PRIVATE *ppaf24 ; + int *iptr ; + int k, bufferlen, writecount = 0, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->codec_data == NULL) + return 0 ; + ppaf24 = (PAF24_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = lrint (normfact * ptr [total+k]) ; + count = paf24_write (psf, ppaf24, iptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* paf24_write_d */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 477a5308-451e-4bbd-bab4-fab6caa4e884 +*/ diff --git a/nylsf/pcm.c b/nylsf/pcm.c new file mode 100644 index 0000000..bad607c --- /dev/null +++ b/nylsf/pcm.c @@ -0,0 +1,2899 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" + +/* Need to be able to handle 3 byte (24 bit) integers. So defined a +** type and use SIZEOF_TRIBYTE instead of (tribyte). +*/ + +typedef void tribyte ; + +#define SIZEOF_TRIBYTE 3 + +static sf_count_t pcm_read_sc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t pcm_read_uc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bes2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t pcm_read_les2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bet2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t pcm_read_let2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t pcm_read_lei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; + +static sf_count_t pcm_read_sc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t pcm_read_uc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bes2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t pcm_read_les2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bet2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t pcm_read_let2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t pcm_read_lei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; + +static sf_count_t pcm_read_sc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t pcm_read_uc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bes2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t pcm_read_les2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bet2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t pcm_read_let2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t pcm_read_lei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; + +static sf_count_t pcm_read_sc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; +static sf_count_t pcm_read_uc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bes2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; +static sf_count_t pcm_read_les2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bet2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; +static sf_count_t pcm_read_let2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; +static sf_count_t pcm_read_bei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; +static sf_count_t pcm_read_lei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t pcm_write_s2sc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t pcm_write_s2uc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t pcm_write_s2bes (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t pcm_write_s2les (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t pcm_write_s2bet (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t pcm_write_s2let (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t pcm_write_s2bei (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t pcm_write_s2lei (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; + +static sf_count_t pcm_write_i2sc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t pcm_write_i2uc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t pcm_write_i2bes (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t pcm_write_i2les (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t pcm_write_i2bet (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t pcm_write_i2let (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t pcm_write_i2bei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t pcm_write_i2lei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; + +static sf_count_t pcm_write_f2sc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t pcm_write_f2uc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t pcm_write_f2bes (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t pcm_write_f2les (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t pcm_write_f2bet (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t pcm_write_f2let (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t pcm_write_f2bei (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t pcm_write_f2lei (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; + +static sf_count_t pcm_write_d2sc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t pcm_write_d2uc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t pcm_write_d2bes (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t pcm_write_d2les (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t pcm_write_d2bet (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t pcm_write_d2let (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t pcm_write_d2bei (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; +static sf_count_t pcm_write_d2lei (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +/*----------------------------------------------------------------------------------------------- +*/ + +enum +{ /* Char type for 8 bit files. */ + SF_CHARS_SIGNED = 200, + SF_CHARS_UNSIGNED = 201 +} ; + +/*----------------------------------------------------------------------------------------------- +*/ + +int +pcm_init (SF_PRIVATE *psf) +{ int chars = 0 ; + + if (psf->bytewidth == 0 || psf->sf.channels == 0) + return SFE_INTERNAL ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_S8) + chars = SF_CHARS_SIGNED ; + else if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_U8) + chars = SF_CHARS_UNSIGNED ; + + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { switch (psf->bytewidth * 0x10000 + psf->endian + chars) + { case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_SIGNED) : + case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_SIGNED) : + psf->read_short = pcm_read_sc2s ; + psf->read_int = pcm_read_sc2i ; + psf->read_float = pcm_read_sc2f ; + psf->read_double = pcm_read_sc2d ; + break ; + case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_UNSIGNED) : + case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_UNSIGNED) : + psf->read_short = pcm_read_uc2s ; + psf->read_int = pcm_read_uc2i ; + psf->read_float = pcm_read_uc2f ; + psf->read_double = pcm_read_uc2d ; + break ; + + case (2 * 0x10000 + SF_ENDIAN_BIG) : + psf->read_short = pcm_read_bes2s ; + psf->read_int = pcm_read_bes2i ; + psf->read_float = pcm_read_bes2f ; + psf->read_double = pcm_read_bes2d ; + break ; + case (3 * 0x10000 + SF_ENDIAN_BIG) : + psf->read_short = pcm_read_bet2s ; + psf->read_int = pcm_read_bet2i ; + psf->read_float = pcm_read_bet2f ; + psf->read_double = pcm_read_bet2d ; + break ; + case (4 * 0x10000 + SF_ENDIAN_BIG) : + psf->read_short = pcm_read_bei2s ; + psf->read_int = pcm_read_bei2i ; + psf->read_float = pcm_read_bei2f ; + psf->read_double = pcm_read_bei2d ; + break ; + + case (2 * 0x10000 + SF_ENDIAN_LITTLE) : + psf->read_short = pcm_read_les2s ; + psf->read_int = pcm_read_les2i ; + psf->read_float = pcm_read_les2f ; + psf->read_double = pcm_read_les2d ; + break ; + case (3 * 0x10000 + SF_ENDIAN_LITTLE) : + psf->read_short = pcm_read_let2s ; + psf->read_int = pcm_read_let2i ; + psf->read_float = pcm_read_let2f ; + psf->read_double = pcm_read_let2d ; + break ; + case (4 * 0x10000 + SF_ENDIAN_LITTLE) : + psf->read_short = pcm_read_lei2s ; + psf->read_int = pcm_read_lei2i ; + psf->read_float = pcm_read_lei2f ; + psf->read_double = pcm_read_lei2d ; + break ; + default : + psf_log_printf (psf, "pcm.c returning SFE_UNIMPLEMENTED\n") ; + return SFE_UNIMPLEMENTED ; + } ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { switch (psf->bytewidth * 0x10000 + psf->endian + chars) + { case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_SIGNED) : + case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_SIGNED) : + psf->write_short = pcm_write_s2sc ; + psf->write_int = pcm_write_i2sc ; + psf->write_float = pcm_write_f2sc ; + psf->write_double = pcm_write_d2sc ; + break ; + case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_UNSIGNED) : + case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_UNSIGNED) : + psf->write_short = pcm_write_s2uc ; + psf->write_int = pcm_write_i2uc ; + psf->write_float = pcm_write_f2uc ; + psf->write_double = pcm_write_d2uc ; + break ; + + case (2 * 0x10000 + SF_ENDIAN_BIG) : + psf->write_short = pcm_write_s2bes ; + psf->write_int = pcm_write_i2bes ; + psf->write_float = pcm_write_f2bes ; + psf->write_double = pcm_write_d2bes ; + break ; + + case (3 * 0x10000 + SF_ENDIAN_BIG) : + psf->write_short = pcm_write_s2bet ; + psf->write_int = pcm_write_i2bet ; + psf->write_float = pcm_write_f2bet ; + psf->write_double = pcm_write_d2bet ; + break ; + + case (4 * 0x10000 + SF_ENDIAN_BIG) : + psf->write_short = pcm_write_s2bei ; + psf->write_int = pcm_write_i2bei ; + psf->write_float = pcm_write_f2bei ; + psf->write_double = pcm_write_d2bei ; + break ; + + case (2 * 0x10000 + SF_ENDIAN_LITTLE) : + psf->write_short = pcm_write_s2les ; + psf->write_int = pcm_write_i2les ; + psf->write_float = pcm_write_f2les ; + psf->write_double = pcm_write_d2les ; + break ; + + case (3 * 0x10000 + SF_ENDIAN_LITTLE) : + psf->write_short = pcm_write_s2let ; + psf->write_int = pcm_write_i2let ; + psf->write_float = pcm_write_f2let ; + psf->write_double = pcm_write_d2let ; + break ; + + case (4 * 0x10000 + SF_ENDIAN_LITTLE) : + psf->write_short = pcm_write_s2lei ; + psf->write_int = pcm_write_i2lei ; + psf->write_float = pcm_write_f2lei ; + psf->write_double = pcm_write_d2lei ; + break ; + + default : + psf_log_printf (psf, "pcm.c returning SFE_UNIMPLEMENTED\n") ; + return SFE_UNIMPLEMENTED ; + } ; + + } ; + + if (psf->filelength > psf->dataoffset) + { psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset : + psf->filelength - psf->dataoffset ; + } + else + psf->datalength = 0 ; + + psf->sf.frames = psf->datalength / psf->blockwidth ; + + return 0 ; +} /* pcm_init */ + +/*============================================================================== +*/ + +static inline void +sc2s_array (signed char *src, int count, short *dest) +{ while (--count >= 0) + { dest [count] = src [count] << 8 ; + } ; +} /* sc2s_array */ + +static inline void +uc2s_array (unsigned char *src, int count, short *dest) +{ while (--count >= 0) + { dest [count] = (((short) src [count]) - 0x80) << 8 ; + } ; +} /* uc2s_array */ + +static inline void +let2s_array (tribyte *src, int count, short *dest) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + dest [count] = LET2H_SHORT_PTR (ucptr) ; + } ; +} /* let2s_array */ + +static inline void +bet2s_array (tribyte *src, int count, short *dest) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + dest [count] = BET2H_SHORT_PTR (ucptr) ; + } ; +} /* bet2s_array */ + +static inline void +lei2s_array (int *src, int count, short *dest) +{ int value ; + + while (--count >= 0) + { value = LEI2H_INT (src [count]) ; + dest [count] = value >> 16 ; + } ; +} /* lei2s_array */ + +static inline void +bei2s_array (int *src, int count, short *dest) +{ int value ; + + while (--count >= 0) + { value = BEI2H_INT (src [count]) ; + dest [count] = value >> 16 ; + } ; +} /* bei2s_array */ + +/*-------------------------------------------------------------------------- +*/ + +static inline void +sc2i_array (signed char *src, int count, int *dest) +{ while (--count >= 0) + { dest [count] = ((int) src [count]) << 24 ; + } ; +} /* sc2i_array */ + +static inline void +uc2i_array (unsigned char *src, int count, int *dest) +{ while (--count >= 0) + { dest [count] = (((int) src [count]) - 128) << 24 ; + } ; +} /* uc2i_array */ + +static inline void +bes2i_array (short *src, int count, int *dest) +{ short value ; + + while (--count >= 0) + { value = BES2H_SHORT (src [count]) ; + dest [count] = value << 16 ; + } ; +} /* bes2i_array */ + +static inline void +les2i_array (short *src, int count, int *dest) +{ short value ; + + while (--count >= 0) + { value = LES2H_SHORT (src [count]) ; + dest [count] = value << 16 ; + } ; +} /* les2i_array */ + +static inline void +bet2i_array (tribyte *src, int count, int *dest) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + dest [count] = BET2H_INT_PTR (ucptr) ; + } ; +} /* bet2i_array */ + +static inline void +let2i_array (tribyte *src, int count, int *dest) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + dest [count] = LET2H_INT_PTR (ucptr) ; + } ; +} /* let2i_array */ + +/*-------------------------------------------------------------------------- +*/ + +static inline void +sc2f_array (signed char *src, int count, float *dest, float normfact) +{ while (--count >= 0) + dest [count] = ((float) src [count]) * normfact ; +} /* sc2f_array */ + +static inline void +uc2f_array (unsigned char *src, int count, float *dest, float normfact) +{ while (--count >= 0) + dest [count] = (((int) src [count]) - 128) * normfact ; +} /* uc2f_array */ + +static inline void +les2f_array (short *src, int count, float *dest, float normfact) +{ short value ; + + while (--count >= 0) + { value = src [count] ; + value = LES2H_SHORT (value) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* les2f_array */ + +static inline void +bes2f_array (short *src, int count, float *dest, float normfact) +{ short value ; + + while (--count >= 0) + { value = src [count] ; + value = BES2H_SHORT (value) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* bes2f_array */ + +static inline void +let2f_array (tribyte *src, int count, float *dest, float normfact) +{ unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = LET2H_INT_PTR (ucptr) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* let2f_array */ + +static inline void +bet2f_array (tribyte *src, int count, float *dest, float normfact) +{ unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = BET2H_INT_PTR (ucptr) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* bet2f_array */ + +static inline void +lei2f_array (int *src, int count, float *dest, float normfact) +{ int value ; + + while (--count >= 0) + { value = src [count] ; + value = LEI2H_INT (value) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* lei2f_array */ + +static inline void +bei2f_array (int *src, int count, float *dest, float normfact) +{ int value ; + + while (--count >= 0) + { value = src [count] ; + value = BEI2H_INT (value) ; + dest [count] = ((float) value) * normfact ; + } ; +} /* bei2f_array */ + +/*-------------------------------------------------------------------------- +*/ + +static inline void +sc2d_array (signed char *src, int count, double *dest, double normfact) +{ while (--count >= 0) + dest [count] = ((double) src [count]) * normfact ; +} /* sc2d_array */ + +static inline void +uc2d_array (unsigned char *src, int count, double *dest, double normfact) +{ while (--count >= 0) + dest [count] = (((int) src [count]) - 128) * normfact ; +} /* uc2d_array */ + +static inline void +les2d_array (short *src, int count, double *dest, double normfact) +{ short value ; + + while (--count >= 0) + { value = src [count] ; + value = LES2H_SHORT (value) ; + dest [count] = ((double) value) * normfact ; + } ; +} /* les2d_array */ + +static inline void +bes2d_array (short *src, int count, double *dest, double normfact) +{ short value ; + + while (--count >= 0) + { value = src [count] ; + value = BES2H_SHORT (value) ; + dest [count] = ((double) value) * normfact ; + } ; +} /* bes2d_array */ + +static inline void +let2d_array (tribyte *src, int count, double *dest, double normfact) +{ unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = LET2H_INT_PTR (ucptr) ; + dest [count] = ((double) value) * normfact ; + } ; +} /* let2d_array */ + +static inline void +bet2d_array (tribyte *src, int count, double *dest, double normfact) +{ unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) src) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = (ucptr [0] << 24) | (ucptr [1] << 16) | (ucptr [2] << 8) ; + dest [count] = ((double) value) * normfact ; + } ; +} /* bet2d_array */ + +static inline void +lei2d_array (int *src, int count, double *dest, double normfact) +{ int value ; + + while (--count >= 0) + { value = src [count] ; + value = LEI2H_INT (value) ; + dest [count] = ((double) value) * normfact ; + } ; +} /* lei2d_array */ + +static inline void +bei2d_array (int *src, int count, double *dest, double normfact) +{ int value ; + + while (--count >= 0) + { value = src [count] ; + value = BEI2H_INT (value) ; + dest [count] = ((double) value) * normfact ; + } ; +} /* bei2d_array */ + +/*-------------------------------------------------------------------------- +*/ + +static inline void +s2sc_array (const short *src, signed char *dest, int count) +{ while (--count >= 0) + dest [count] = src [count] >> 8 ; +} /* s2sc_array */ + +static inline void +s2uc_array (const short *src, unsigned char *dest, int count) +{ while (--count >= 0) + dest [count] = (src [count] >> 8) + 0x80 ; +} /* s2uc_array */ + +static inline void +s2let_array (const short *src, tribyte *dest, int count) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + ucptr [0] = 0 ; + ucptr [1] = src [count] ; + ucptr [2] = src [count] >> 8 ; + } ; +} /* s2let_array */ + +static inline void +s2bet_array (const short *src, tribyte *dest, int count) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + ucptr [2] = 0 ; + ucptr [1] = src [count] ; + ucptr [0] = src [count] >> 8 ; + } ; +} /* s2bet_array */ + +static inline void +s2lei_array (const short *src, int *dest, int count) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) dest) + 4 * count ; + while (--count >= 0) + { ucptr -= 4 ; + ucptr [0] = 0 ; + ucptr [1] = 0 ; + ucptr [2] = src [count] ; + ucptr [3] = src [count] >> 8 ; + } ; +} /* s2lei_array */ + +static inline void +s2bei_array (const short *src, int *dest, int count) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) dest) + 4 * count ; + while (--count >= 0) + { ucptr -= 4 ; + ucptr [0] = src [count] >> 8 ; + ucptr [1] = src [count] ; + ucptr [2] = 0 ; + ucptr [3] = 0 ; + } ; +} /* s2bei_array */ + +/*-------------------------------------------------------------------------- +*/ + +static inline void +i2sc_array (const int *src, signed char *dest, int count) +{ while (--count >= 0) + dest [count] = (src [count] >> 24) ; +} /* i2sc_array */ + +static inline void +i2uc_array (const int *src, unsigned char *dest, int count) +{ while (--count >= 0) + dest [count] = ((src [count] >> 24) + 128) ; +} /* i2uc_array */ + +static inline void +i2bes_array (const int *src, short *dest, int count) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) dest) + 2 * count ; + while (--count >= 0) + { ucptr -= 2 ; + ucptr [0] = src [count] >> 24 ; + ucptr [1] = src [count] >> 16 ; + } ; +} /* i2bes_array */ + +static inline void +i2les_array (const int *src, short *dest, int count) +{ unsigned char *ucptr ; + + ucptr = ((unsigned char*) dest) + 2 * count ; + while (--count >= 0) + { ucptr -= 2 ; + ucptr [0] = src [count] >> 16 ; + ucptr [1] = src [count] >> 24 ; + } ; +} /* i2les_array */ + +static inline void +i2let_array (const int *src, tribyte *dest, int count) +{ unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = src [count] >> 8 ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + } ; +} /* i2let_array */ + +static inline void +i2bet_array (const int *src, tribyte *dest, int count) +{ unsigned char *ucptr ; + int value ; + + ucptr = ((unsigned char*) dest) + 3 * count ; + while (--count >= 0) + { ucptr -= 3 ; + value = src [count] >> 8 ; + ucptr [2] = value ; + ucptr [1] = value >> 8 ; + ucptr [0] = value >> 16 ; + } ; +} /* i2bet_array */ + +/*=============================================================================================== +*/ + +static sf_count_t +pcm_read_sc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + sc2s_array (psf->u.scbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_sc2s */ + +static sf_count_t +pcm_read_uc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + uc2s_array (psf->u.ucbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_uc2s */ + +static sf_count_t +pcm_read_bes2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int total ; + + total = psf_fread (ptr, sizeof (short), len, psf) ; + if (CPU_IS_LITTLE_ENDIAN) + endswap_short_array (ptr, len) ; + + return total ; +} /* pcm_read_bes2s */ + +static sf_count_t +pcm_read_les2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int total ; + + total = psf_fread (ptr, sizeof (short), len, psf) ; + if (CPU_IS_BIG_ENDIAN) + endswap_short_array (ptr, len) ; + + return total ; +} /* pcm_read_les2s */ + +static sf_count_t +pcm_read_bet2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + bet2s_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bet2s */ + +static sf_count_t +pcm_read_let2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + let2s_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_let2s */ + +static sf_count_t +pcm_read_bei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + bei2s_array (psf->u.ibuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bei2s */ + +static sf_count_t +pcm_read_lei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + lei2s_array (psf->u.ibuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_lei2s */ + +/*----------------------------------------------------------------------------------------------- +*/ + +static sf_count_t +pcm_read_sc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + sc2i_array (psf->u.scbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_sc2i */ + +static sf_count_t +pcm_read_uc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + uc2i_array (psf->u.ucbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_uc2i */ + +static sf_count_t +pcm_read_bes2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + bes2i_array (psf->u.sbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bes2i */ + +static sf_count_t +pcm_read_les2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + les2i_array (psf->u.sbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_les2i */ + +static sf_count_t +pcm_read_bet2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + bet2i_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bet2i */ + +static sf_count_t +pcm_read_let2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + let2i_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_let2i */ + +static sf_count_t +pcm_read_bei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int total ; + + total = psf_fread (ptr, sizeof (int), len, psf) ; + if (CPU_IS_LITTLE_ENDIAN) + endswap_int_array (ptr, len) ; + + return total ; +} /* pcm_read_bei2i */ + +static sf_count_t +pcm_read_lei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int total ; + + total = psf_fread (ptr, sizeof (int), len, psf) ; + if (CPU_IS_BIG_ENDIAN) + endswap_int_array (ptr, len) ; + + return total ; +} /* pcm_read_lei2i */ + +/*----------------------------------------------------------------------------------------------- +*/ + +static sf_count_t +pcm_read_sc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + sc2f_array (psf->u.scbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_sc2f */ + +static sf_count_t +pcm_read_uc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + uc2f_array (psf->u.ucbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_uc2f */ + +static sf_count_t +pcm_read_bes2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + bes2f_array (psf->u.sbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bes2f */ + +static sf_count_t +pcm_read_les2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + les2f_array (psf->u.sbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_les2f */ + +static sf_count_t +pcm_read_bet2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + /* Special normfactor because tribyte value is read into an int. */ + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 / 256.0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + bet2f_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bet2f */ + +static sf_count_t +pcm_read_let2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + /* Special normfactor because tribyte value is read into an int. */ + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 / 256.0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + let2f_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_let2f */ + +static sf_count_t +pcm_read_bei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + bei2f_array (psf->u.ibuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bei2f */ + +static sf_count_t +pcm_read_lei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + lei2f_array (psf->u.ibuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_lei2f */ + +/*----------------------------------------------------------------------------------------------- +*/ + +static sf_count_t +pcm_read_sc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + sc2d_array (psf->u.scbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_sc2d */ + +static sf_count_t +pcm_read_uc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + uc2d_array (psf->u.ucbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_uc2d */ + +static sf_count_t +pcm_read_bes2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + bes2d_array (psf->u.sbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bes2d */ + +static sf_count_t +pcm_read_les2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + les2d_array (psf->u.sbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_les2d */ + +static sf_count_t +pcm_read_bet2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 / 256.0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + bet2d_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bet2d */ + +static sf_count_t +pcm_read_let2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + /* Special normfactor because tribyte value is read into an int. */ + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 / 256.0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + let2d_array ((tribyte*) (psf->u.ucbuf), readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_let2d */ + +static sf_count_t +pcm_read_bei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + bei2d_array (psf->u.ibuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_bei2d */ + +static sf_count_t +pcm_read_lei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + lei2d_array (psf->u.ibuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* pcm_read_lei2d */ + +/*=============================================================================================== +**----------------------------------------------------------------------------------------------- +**=============================================================================================== +*/ + +static sf_count_t +pcm_write_s2sc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2sc_array (ptr + total, psf->u.scbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2sc */ + +static sf_count_t +pcm_write_s2uc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2uc_array (ptr + total, psf->u.ucbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2uc */ + +static sf_count_t +pcm_write_s2bes (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + if (CPU_IS_BIG_ENDIAN) + return psf_fwrite (ptr, sizeof (short), len, psf) ; + else + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + endswap_short_copy (psf->u.sbuf, ptr + total, bufferlen) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2bes */ + +static sf_count_t +pcm_write_s2les (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + if (CPU_IS_LITTLE_ENDIAN) + return psf_fwrite (ptr, sizeof (short), len, psf) ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + endswap_short_copy (psf->u.sbuf, ptr + total, bufferlen) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2les */ + +static sf_count_t +pcm_write_s2bet (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2bet_array (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2bet */ + +static sf_count_t +pcm_write_s2let (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2let_array (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2let */ + +static sf_count_t +pcm_write_s2bei (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2bei_array (ptr + total, psf->u.ibuf, bufferlen) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2bei */ + +static sf_count_t +pcm_write_s2lei (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2lei_array (ptr + total, psf->u.ibuf, bufferlen) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_s2lei */ + +/*----------------------------------------------------------------------------------------------- +*/ + +static sf_count_t +pcm_write_i2sc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2sc_array (ptr + total, psf->u.scbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2sc */ + +static sf_count_t +pcm_write_i2uc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2uc_array (ptr + total, psf->u.ucbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.ucbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2uc */ + +static sf_count_t +pcm_write_i2bes (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2bes_array (ptr + total, psf->u.sbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2bes */ + +static sf_count_t +pcm_write_i2les (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2les_array (ptr + total, psf->u.sbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2les */ + +static sf_count_t +pcm_write_i2bet (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2bet_array (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2bet */ + +static sf_count_t +pcm_write_i2let (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2let_array (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2les */ + +static sf_count_t +pcm_write_i2bei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + if (CPU_IS_BIG_ENDIAN) + return psf_fwrite (ptr, sizeof (int), len, psf) ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + endswap_int_copy (psf->u.ibuf, ptr + total, bufferlen) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2bei */ + +static sf_count_t +pcm_write_i2lei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + if (CPU_IS_LITTLE_ENDIAN) + return psf_fwrite (ptr, sizeof (int), len, psf) ; + + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + endswap_int_copy (psf->u.ibuf, ptr + total, bufferlen) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_i2lei */ + +/*------------------------------------------------------------------------------ +**============================================================================== +**------------------------------------------------------------------------------ +*/ + +static void +f2sc_array (const float *src, signed char *dest, int count, int normalize) +{ float normfact ; + + normfact = normalize ? (1.0 * 0x7F) : 1.0 ; + + while (--count >= 0) + { dest [count] = lrintf (src [count] * normfact) ; + } ; +} /* f2sc_array */ + +static void +f2sc_clip_array (const float *src, signed char *dest, int count, int normalize) +{ float normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [count] = 127 ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { dest [count] = -128 ; + continue ; + } ; + + dest [count] = lrintf (scaled_value) >> 24 ; + } ; +} /* f2sc_clip_array */ + +static sf_count_t +pcm_write_f2sc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, signed char *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2sc_clip_array : f2sc_array ; + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.scbuf, bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2sc */ + +/*============================================================================== +*/ + +static void +f2uc_array (const float *src, unsigned char *dest, int count, int normalize) +{ float normfact ; + + normfact = normalize ? (1.0 * 0x7F) : 1.0 ; + + while (--count >= 0) + { dest [count] = lrintf (src [count] * normfact) + 128 ; + } ; +} /* f2uc_array */ + +static void +f2uc_clip_array (const float *src, unsigned char *dest, int count, int normalize) +{ float normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [count] = 0xFF ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { dest [count] = 0 ; + continue ; + } ; + + dest [count] = (lrintf (scaled_value) >> 24) + 128 ; + } ; +} /* f2uc_clip_array */ + +static sf_count_t +pcm_write_f2uc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, unsigned char *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2uc_clip_array : f2uc_array ; + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.ucbuf, bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2uc */ + +/*============================================================================== +*/ + +static void +f2bes_array (const float *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact ; + short value ; + + normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + value = lrintf (src [count] * normfact) ; + ucptr [1] = value ; + ucptr [0] = value >> 8 ; + } ; +} /* f2bes_array */ + +static void +f2bes_clip_array (const float *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact, scaled_value ; + int value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [1] = 0xFF ; + ucptr [0] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [1] = 0x00 ; + ucptr [0] = 0x80 ; + continue ; + } ; + + value = lrintf (scaled_value) ; + ucptr [1] = value >> 16 ; + ucptr [0] = value >> 24 ; + } ; +} /* f2bes_clip_array */ + +static sf_count_t +pcm_write_f2bes (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, short *t, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2bes_clip_array : f2bes_array ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.sbuf, bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2bes */ + +/*============================================================================== +*/ + +static void +f2les_array (const float *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact ; + int value ; + + normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + value = lrintf (src [count] * normfact) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + } ; +} /* f2les_array */ + +static void +f2les_clip_array (const float *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact, scaled_value ; + int value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0xFF ; + ucptr [1] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x00 ; + ucptr [1] = 0x80 ; + continue ; + } ; + + value = lrintf (scaled_value) ; + ucptr [0] = value >> 16 ; + ucptr [1] = value >> 24 ; + } ; +} /* f2les_clip_array */ + +static sf_count_t +pcm_write_f2les (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, short *t, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2les_clip_array : f2les_array ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.sbuf, bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2les */ + +/*============================================================================== +*/ + +static void +f2let_array (const float *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact ; + int value ; + + normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + value = lrintf (src [count] * normfact) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + } ; +} /* f2let_array */ + +static void +f2let_clip_array (const float *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact, scaled_value ; + int value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0xFF ; + ucptr [1] = 0xFF ; + ucptr [2] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x00 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x80 ; + continue ; + } ; + + value = lrintf (scaled_value) ; + ucptr [0] = value >> 8 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 24 ; + } ; +} /* f2let_clip_array */ + +static sf_count_t +pcm_write_f2let (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, tribyte *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2let_clip_array : f2let_array ; + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2let */ + +/*============================================================================== +*/ + +static void +f2bet_array (const float *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact ; + int value ; + + normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + value = lrintf (src [count] * normfact) ; + ucptr [0] = value >> 16 ; + ucptr [1] = value >> 8 ; + ucptr [2] = value ; + } ; +} /* f2bet_array */ + +static void +f2bet_clip_array (const float *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact, scaled_value ; + int value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0x7F ; + ucptr [1] = 0xFF ; + ucptr [2] = 0xFF ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x80 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x00 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [0] = value >> 24 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 8 ; + } ; +} /* f2bet_clip_array */ + +static sf_count_t +pcm_write_f2bet (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, tribyte *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2bet_clip_array : f2bet_array ; + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2bet */ + +/*============================================================================== +*/ + +static void +f2bei_array (const float *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact ; + int value ; + + normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + while (--count >= 0) + { ucptr -= 4 ; + value = lrintf (src [count] * normfact) ; + ucptr [0] = value >> 24 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 8 ; + ucptr [3] = value ; + } ; +} /* f2bei_array */ + +static void +f2bei_clip_array (const float *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact, scaled_value ; + int value ; + + normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + + while (--count >= 0) + { ucptr -= 4 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= 1.0 * 0x7FFFFFFF) + { ucptr [0] = 0x7F ; + ucptr [1] = 0xFF ; + ucptr [2] = 0xFF ; + ucptr [3] = 0xFF ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x80 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x00 ; + ucptr [3] = 0x00 ; + continue ; + } ; + + value = lrintf (scaled_value) ; + ucptr [0] = value >> 24 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 8 ; + ucptr [3] = value ; + } ; +} /* f2bei_clip_array */ + +static sf_count_t +pcm_write_f2bei (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, int *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2bei_clip_array : f2bei_array ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.ibuf, bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2bei */ + +/*============================================================================== +*/ + +static void +f2lei_array (const float *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact ; + int value ; + + normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + + while (--count >= 0) + { ucptr -= 4 ; + value = lrintf (src [count] * normfact) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + ucptr [3] = value >> 24 ; + } ; +} /* f2lei_array */ + +static void +f2lei_clip_array (const float *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + float normfact, scaled_value ; + int value ; + + normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + + while (--count >= 0) + { ucptr -= 4 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0xFF ; + ucptr [1] = 0xFF ; + ucptr [2] = 0xFF ; + ucptr [3] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x00 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x00 ; + ucptr [3] = 0x80 ; + continue ; + } ; + + value = lrintf (scaled_value) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + ucptr [3] = value >> 24 ; + } ; +} /* f2lei_clip_array */ + +static sf_count_t +pcm_write_f2lei (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ void (*convert) (const float *, int *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? f2lei_clip_array : f2lei_array ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.ibuf, bufferlen, psf->norm_float) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_f2lei */ + +/*============================================================================== +*/ + +static void +d2sc_array (const double *src, signed char *dest, int count, int normalize) +{ double normfact ; + + normfact = normalize ? (1.0 * 0x7F) : 1.0 ; + + while (--count >= 0) + { dest [count] = lrint (src [count] * normfact) ; + } ; +} /* d2sc_array */ + +static void +d2sc_clip_array (const double *src, signed char *dest, int count, int normalize) +{ double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [count] = 127 ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { dest [count] = -128 ; + continue ; + } ; + + dest [count] = lrintf (scaled_value) >> 24 ; + } ; +} /* d2sc_clip_array */ + +static sf_count_t +pcm_write_d2sc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, signed char *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2sc_clip_array : d2sc_array ; + bufferlen = ARRAY_LEN (psf->u.scbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.scbuf, bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2sc */ + +/*============================================================================== +*/ + +static void +d2uc_array (const double *src, unsigned char *dest, int count, int normalize) +{ double normfact ; + + normfact = normalize ? (1.0 * 0x7F) : 1.0 ; + + while (--count >= 0) + { dest [count] = lrint (src [count] * normfact) + 128 ; + } ; +} /* d2uc_array */ + +static void +d2uc_clip_array (const double *src, unsigned char *dest, int count, int normalize) +{ double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; + + while (--count >= 0) + { scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { dest [count] = 255 ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { dest [count] = 0 ; + continue ; + } ; + + dest [count] = (lrint (src [count] * normfact) >> 24) + 128 ; + } ; +} /* d2uc_clip_array */ + +static sf_count_t +pcm_write_d2uc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, unsigned char *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2uc_clip_array : d2uc_array ; + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.ucbuf, bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.ucbuf, sizeof (unsigned char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2uc */ + +/*============================================================================== +*/ + +static void +d2bes_array (const double *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + short value ; + double normfact ; + + normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + value = lrint (src [count] * normfact) ; + ucptr [1] = value ; + ucptr [0] = value >> 8 ; + } ; +} /* d2bes_array */ + +static void +d2bes_clip_array (const double *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + double normfact, scaled_value ; + int value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [1] = 0xFF ; + ucptr [0] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [1] = 0x00 ; + ucptr [0] = 0x80 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [1] = value >> 16 ; + ucptr [0] = value >> 24 ; + } ; +} /* d2bes_clip_array */ + +static sf_count_t +pcm_write_d2bes (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, short *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2bes_clip_array : d2bes_array ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.sbuf, bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2bes */ + +/*============================================================================== +*/ + +static void +d2les_array (const double *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + short value ; + double normfact ; + + normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + value = lrint (src [count] * normfact) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + } ; +} /* d2les_array */ + +static void +d2les_clip_array (const double *src, short *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; + ucptr = ((unsigned char*) dest) + 2 * count ; + + while (--count >= 0) + { ucptr -= 2 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0xFF ; + ucptr [1] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x00 ; + ucptr [1] = 0x80 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [0] = value >> 16 ; + ucptr [1] = value >> 24 ; + } ; +} /* d2les_clip_array */ + +static sf_count_t +pcm_write_d2les (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, short *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2les_clip_array : d2les_array ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.sbuf, bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2les */ + +/*============================================================================== +*/ + +static void +d2let_array (const double *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact ; + + normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + value = lrint (src [count] * normfact) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + } ; +} /* d2let_array */ + +static void +d2let_clip_array (const double *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0xFF ; + ucptr [1] = 0xFF ; + ucptr [2] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x00 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x80 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [0] = value >> 8 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 24 ; + } ; +} /* d2let_clip_array */ + +static sf_count_t +pcm_write_d2let (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, tribyte *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2let_clip_array : d2let_array ; + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2let */ + +/*============================================================================== +*/ + +static void +d2bet_array (const double *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact ; + + normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + value = lrint (src [count] * normfact) ; + ucptr [2] = value ; + ucptr [1] = value >> 8 ; + ucptr [0] = value >> 16 ; + } ; +} /* d2bet_array */ + +static void +d2bet_clip_array (const double *src, tribyte *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; + ucptr = ((unsigned char*) dest) + 3 * count ; + + while (--count >= 0) + { ucptr -= 3 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [2] = 0xFF ; + ucptr [1] = 0xFF ; + ucptr [0] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [2] = 0x00 ; + ucptr [1] = 0x00 ; + ucptr [0] = 0x80 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [2] = value >> 8 ; + ucptr [1] = value >> 16 ; + ucptr [0] = value >> 24 ; + } ; +} /* d2bet_clip_array */ + +static sf_count_t +pcm_write_d2bet (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, tribyte *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2bet_clip_array : d2bet_array ; + bufferlen = sizeof (psf->u.ucbuf) / SIZEOF_TRIBYTE ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, (tribyte*) (psf->u.ucbuf), bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2bet */ + +/*============================================================================== +*/ + +static void +d2bei_array (const double *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact ; + + normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + + while (--count >= 0) + { ucptr -= 4 ; + value = lrint (src [count] * normfact) ; + ucptr [0] = value >> 24 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 8 ; + ucptr [3] = value ; + } ; +} /* d2bei_array */ + +static void +d2bei_clip_array (const double *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + + while (--count >= 0) + { ucptr -= 4 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [3] = 0xFF ; + ucptr [2] = 0xFF ; + ucptr [1] = 0xFF ; + ucptr [0] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [3] = 0x00 ; + ucptr [2] = 0x00 ; + ucptr [1] = 0x00 ; + ucptr [0] = 0x80 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [0] = value >> 24 ; + ucptr [1] = value >> 16 ; + ucptr [2] = value >> 8 ; + ucptr [3] = value ; + } ; +} /* d2bei_clip_array */ + +static sf_count_t +pcm_write_d2bei (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, int *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2bei_clip_array : d2bei_array ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.ibuf, bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2bei */ + +/*============================================================================== +*/ + +static void +d2lei_array (const double *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact ; + + normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + + while (--count >= 0) + { ucptr -= 4 ; + value = lrint (src [count] * normfact) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + ucptr [3] = value >> 24 ; + } ; +} /* d2lei_array */ + +static void +d2lei_clip_array (const double *src, int *dest, int count, int normalize) +{ unsigned char *ucptr ; + int value ; + double normfact, scaled_value ; + + normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; + ucptr = ((unsigned char*) dest) + 4 * count ; + + while (--count >= 0) + { ucptr -= 4 ; + scaled_value = src [count] * normfact ; + if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) + { ucptr [0] = 0xFF ; + ucptr [1] = 0xFF ; + ucptr [2] = 0xFF ; + ucptr [3] = 0x7F ; + continue ; + } ; + if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) + { ucptr [0] = 0x00 ; + ucptr [1] = 0x00 ; + ucptr [2] = 0x00 ; + ucptr [3] = 0x80 ; + continue ; + } ; + + value = lrint (scaled_value) ; + ucptr [0] = value ; + ucptr [1] = value >> 8 ; + ucptr [2] = value >> 16 ; + ucptr [3] = value >> 24 ; + } ; +} /* d2lei_clip_array */ + +static sf_count_t +pcm_write_d2lei (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ void (*convert) (const double *, int *, int, int) ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + convert = (psf->add_clipping) ? d2lei_clip_array : d2lei_array ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + convert (ptr + total, psf->u.ibuf, bufferlen, psf->norm_double) ; + writecount = psf_fwrite (psf->u.ibuf, sizeof (int), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* pcm_write_d2lei */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: d8bc7c0e-1e2f-4ff3-a28f-10ce1fbade3b +*/ diff --git a/nylsf/ppc-config.h b/nylsf/ppc-config.h new file mode 100644 index 0000000..54d5d61 --- /dev/null +++ b/nylsf/ppc-config.h @@ -0,0 +1,254 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Set to 1 if the compile is GNU GCC. */ +#define COMPILER_IS_GCC 1 + +/* Target processor clips on negative float to int conversion. */ +#define CPU_CLIPS_NEGATIVE 1 + +/* Target processor clips on positive float to int conversion. */ +#define CPU_CLIPS_POSITIVE 1 + +/* Target processor is big endian. */ +#define CPU_IS_BIG_ENDIAN 1 + +/* Target processor is little endian. */ +#define CPU_IS_LITTLE_ENDIAN 0 + +/* Set to 1 to enable experimental code. */ +#define ENABLE_EXPERIMENTAL_CODE 0 + +/* Major version of GCC or 3 otherwise. */ +#define GCC_MAJOR_VERSION 4 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALSA_ASOUNDLIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BYTESWAP_H */ + +/* Define to 1 if you have the `calloc' function. */ +#define HAVE_CALLOC 1 + +/* Define to 1 if you have the `ceil' function. */ +#define HAVE_CEIL 1 + +/* Set to 1 if S_IRGRP is defined. */ +#define HAVE_DECL_S_IRGRP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ENDIAN_H */ + +/* Define to 1 if you have libflac 1.1.1 */ +/* #undef HAVE_FLAC_1_1_1 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FLAC_ALL_H */ + +/* Set to 1 if the compile supports the struct hack. */ +#define HAVE_FLEXIBLE_ARRAY 1 + +/* Define to 1 if you have the `floor' function. */ +#define HAVE_FLOOR 1 + +/* Define to 1 if you have the `fmod' function. */ +#define HAVE_FMOD 1 + +/* Define to 1 if you have the `free' function. */ +#define HAVE_FREE 1 + +/* Define to 1 if you have the `fstat' function. */ +#define HAVE_FSTAT 1 + +/* Define to 1 if you have the `fsync' function. */ +#define HAVE_FSYNC 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `gmtime' function. */ +#define HAVE_GMTIME 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you have C99's lrint function. */ +#define HAVE_LRINT 1 + +/* Define if you have C99's lrintf function. */ +#define HAVE_LRINTF 1 + +/* Define to 1 if you have the `lseek' function. */ +#define HAVE_LSEEK 1 + +/* Define to 1 if you have the `malloc' function. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `open' function. */ +#define HAVE_OPEN 1 + +/* Define to 1 if you have the `pread' function. */ +#define HAVE_PREAD 1 + +/* Define to 1 if you have the `pwrite' function. */ +#define HAVE_PWRITE 1 + +/* Define to 1 if you have the `read' function. */ +#define HAVE_READ 1 + +/* Define to 1 if you have the `realloc' function. */ +#define HAVE_REALLOC 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Set to 1 if you have libsqlite3. */ +#define HAVE_SQLITE3 0 + +/* Define to 1 if the system has the type `ssize_t'. */ +#define HAVE_SSIZE_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `write' function. */ +#define HAVE_WRITE 1 + +/* Set to 1 if compiling for MacOSX */ +#define OS_IS_MACOSX 1 + +/* Set to 1 if compiling for Win32 */ +#define OS_IS_WIN32 0 + +/* Name of package */ +#define PACKAGE "libsndfile" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "erikd@mega-nerd.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libsndfile" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libsndfile 1.0.17" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libsndfile" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.0.17" + +/* Set to maximum allowed value of sf_count_t type. */ +#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL + +/* The size of `double', as computed by sizeof. */ +#define SIZEOF_DOUBLE 8 + +/* The size of `float', as computed by sizeof. */ +#define SIZEOF_FLOAT 4 + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `int64_t', as computed by sizeof. */ +#define SIZEOF_INT64_T 8 + +/* The size of `loff_t', as computed by sizeof. */ +/* #undef SIZEOF_LOFF_T */ + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `off64_t', as computed by sizeof. */ +/* #undef SIZEOF_OFF64_T */ + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* Set to sizeof (long) if unknown. */ +#define SIZEOF_SF_COUNT_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `ssize_t', as computed by sizeof. */ +#define SIZEOF_SSIZE_T 4 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Set to long if unknown. */ +#define TYPEOF_SF_COUNT_T off_t + +/* Set to 1 to use the native windows API */ +#define USE_WINDOWS_API 0 + +/* Version number of package */ +#define VERSION "1.0.17" + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to make fseeko etc. visible, on some hosts. */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ diff --git a/nylsf/pvf.c b/nylsf/pvf.c new file mode 100644 index 0000000..1dab17c --- /dev/null +++ b/nylsf/pvf.c @@ -0,0 +1,199 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define PVF1_MARKER (MAKE_MARKER ('P', 'V', 'F', '1')) + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int pvf_close (SF_PRIVATE *psf) ; + +static int pvf_write_header (SF_PRIVATE *psf, int calc_length) ; +static int pvf_read_header (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +pvf_open (SF_PRIVATE *psf) +{ int subformat ; + int error = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = pvf_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PVF) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = SF_ENDIAN_BIG ; + + if (pvf_write_header (psf, SF_FALSE)) + return psf->error ; + + psf->write_header = pvf_write_header ; + } ; + + psf->container_close = pvf_close ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */ + case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ + case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */ + error = pcm_init (psf) ; + break ; + + default : break ; + } ; + + return error ; +} /* pvf_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +pvf_close (SF_PRIVATE *psf) +{ + psf = psf ; + + return 0 ; +} /* pvf_close */ + +static int +pvf_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + + if (psf->pipeoffset > 0) + return 0 ; + + calc_length = calc_length ; /* Avoid a compiler warning. */ + + current = psf_ftell (psf) ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + if (psf->is_pipe == SF_FALSE) + psf_fseek (psf, 0, SEEK_SET) ; + + LSF_SNPRINTF ((char*) psf->header, sizeof (psf->header), "PVF1\n%d %d %d\n", + psf->sf.channels, psf->sf.samplerate, psf->bytewidth * 8) ; + + psf->headindex = strlen ((char*) psf->header) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* pvf_write_header */ + +static int +pvf_read_header (SF_PRIVATE *psf) +{ char buffer [32] ; + int marker, channels, samplerate, bitwidth ; + + psf_binheader_readf (psf, "pmj", 0, &marker, 1) ; + psf_log_printf (psf, "%M\n", marker) ; + + if (marker != PVF1_MARKER) + return SFE_PVF_NO_PVF1 ; + + /* Grab characters up until a newline which is replaced by an EOS. */ + psf_binheader_readf (psf, "G", buffer, sizeof (buffer)) ; + + if (sscanf (buffer, "%d %d %d", &channels, &samplerate, &bitwidth) != 3) + return SFE_PVF_BAD_HEADER ; + + psf_log_printf (psf, " Channels : %d\n Sample rate : %d\n Bit width : %d\n", + channels, samplerate, bitwidth) ; + + psf->sf.channels = channels ; + psf->sf.samplerate = samplerate ; + + switch (bitwidth) + { case 8 : + psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_S8 ; + psf->bytewidth = 1 ; + break ; + + case 16 : + psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + break ; + case 32 : + psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_32 ; + psf->bytewidth = 4 ; + break ; + + default : + return SFE_PVF_BAD_BITWIDTH ; + } ; + + psf->dataoffset = psf_ftell (psf) ; + psf_log_printf (psf, " Data Offset : %D\n", psf->dataoffset) ; + + psf->endian = SF_ENDIAN_BIG ; + + psf->datalength = psf->filelength - psf->dataoffset ; + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + if (! psf->sf.frames && psf->blockwidth) + psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; + + return 0 ; +} /* pvf_read_header */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 20a26761-8bc1-41d7-b1f3-9793bf3d9864 +*/ diff --git a/nylsf/raw.c b/nylsf/raw.c new file mode 100644 index 0000000..65be491 --- /dev/null +++ b/nylsf/raw.c @@ -0,0 +1,111 @@ +/* +** Copyright (C) 1999-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include + +#include "sndfile.h" +#include "common.h" + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +raw_open (SF_PRIVATE *psf) +{ int subformat, error = SFE_NO_ERROR ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + + if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) + psf->endian = SF_ENDIAN_BIG ; + else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) + psf->endian = SF_ENDIAN_LITTLE ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + psf->dataoffset = 0 ; + psf->datalength = psf->filelength ; + + switch (subformat) + { case SF_FORMAT_PCM_S8 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_U8 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + case SF_FORMAT_GSM610 : + error = gsm610_init (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + + case SF_FORMAT_DWVW_12 : + error = dwvw_init (psf, 12) ; + break ; + + case SF_FORMAT_DWVW_16 : + error = dwvw_init (psf, 16) ; + break ; + + case SF_FORMAT_DWVW_24 : + error = dwvw_init (psf, 24) ; + break ; + + case SF_FORMAT_VOX_ADPCM : + error = vox_adpcm_init (psf) ; + break ; + /* Lite remove end */ + + default : return SFE_BAD_OPEN_FORMAT ; + } ; + + return error ; +} /* raw_open */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: f0066de7-d6ce-4f36-a1e0-e475c07d4e1a +*/ diff --git a/nylsf/rx2.c b/nylsf/rx2.c new file mode 100644 index 0000000..d95f11f --- /dev/null +++ b/nylsf/rx2.c @@ -0,0 +1,326 @@ +/* +** Copyright (C) 2001-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#if (ENABLE_EXPERIMENTAL_CODE == 0) + +int +rx2_open (SF_PRIVATE *psf) +{ if (psf) + return SFE_UNIMPLEMENTED ; + return (psf && 0) ; +} /* rx2_open */ + +#else + +/*------------------------------------------------------------------------------ + * Macros to handle big/little endian issues. +*/ + +#define CAT_MARKER (MAKE_MARKER ('C', 'A', 'T', ' ')) +#define GLOB_MARKER (MAKE_MARKER ('G', 'L', 'O', 'B')) + +#define RECY_MARKER (MAKE_MARKER ('R', 'E', 'C', 'Y')) + +#define SLCL_MARKER (MAKE_MARKER ('S', 'L', 'C', 'L')) +#define SLCE_MARKER (MAKE_MARKER ('S', 'L', 'C', 'E')) + +#define DEVL_MARKER (MAKE_MARKER ('D', 'E', 'V', 'L')) +#define TRSH_MARKER (MAKE_MARKER ('T', 'R', 'S', 'H')) + +#define EQ_MARKER (MAKE_MARKER ('E', 'Q', ' ', ' ')) +#define COMP_MARKER (MAKE_MARKER ('C', 'O', 'M', 'P')) + +#define SINF_MARKER (MAKE_MARKER ('S', 'I', 'N', 'F')) +#define SDAT_MARKER (MAKE_MARKER ('S', 'D', 'A', 'T')) + +/*------------------------------------------------------------------------------ + * Typedefs for file chunks. +*/ + + +/*------------------------------------------------------------------------------ + * Private static functions. +*/ +static int rx2_close (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public functions. +*/ + +int +rx2_open (SF_PRIVATE *psf) +{ static const char *marker_type [4] = + { "Original Enabled", "Enabled Hidden", + "Additional/PencilTool", "Disabled" + } ; + + int error, marker, length, glob_offset, slce_count, frames ; + + int sdat_length = 0, slce_total = 0 ; + + int n_channels ; + + + /* So far only doing read. */ + + psf_binheader_readf (psf, "Epm4", 0, &marker, &length) ; + + if (marker != CAT_MARKER) + { psf_log_printf (psf, "length : %d\n", length) ; + return -1000 ; + } ; + + if (length != psf->filelength - 8) + psf_log_printf (psf, "%M : %d (should be %d)\n", marker, length, psf->filelength - 8) ; + else + psf_log_printf (psf, "%M : %d\n", marker, length) ; + + /* 'REX2' marker */ + psf_binheader_readf (psf, "m", &marker) ; + psf_log_printf (psf, "%M", marker) ; + + /* 'HEAD' marker */ + psf_binheader_readf (psf, "m", &marker) ; + psf_log_printf (psf, "%M\n", marker) ; + + /* Grab 'GLOB' offset. */ + psf_binheader_readf (psf, "E4", &glob_offset) ; + glob_offset += 0x14 ; /* Add the current file offset. */ + + /* Jump to offset 0x30 */ + psf_binheader_readf (psf, "p", 0x30) ; + + /* Get name length */ + length = 0 ; + psf_binheader_readf (psf, "1", &length) ; + if (length >= SIGNED_SIZEOF (psf->u.cbuf)) + { psf_log_printf (psf, " Text : %d *** Error : Too sf_count_t!\n") ; + return -1001 ; + } + + memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ; + psf_binheader_readf (psf, "b", psf->u.cbuf, length) ; + psf_log_printf (psf, " Text : \"%s\"\n", psf->u.cbuf) ; + + /* Jump to GLOB offset position. */ + if (glob_offset & 1) + glob_offset ++ ; + + psf_binheader_readf (psf, "p", glob_offset) ; + + slce_count = 0 ; + /* GLOB */ + while (1) + { psf_binheader_readf (psf, "m", &marker) ; + + if (marker != SLCE_MARKER && slce_count > 0) + { psf_log_printf (psf, " SLCE count : %d\n", slce_count) ; + slce_count = 0 ; + } + switch (marker) + { case GLOB_MARKER: + psf_binheader_readf (psf, "E4", &length) ; + psf_log_printf (psf, " %M : %d\n", marker, length) ; + psf_binheader_readf (psf, "j", length) ; + break ; + + case RECY_MARKER: + psf_binheader_readf (psf, "E4", &length) ; + psf_log_printf (psf, " %M : %d\n", marker, length) ; + psf_binheader_readf (psf, "j", (length+1) & 0xFFFFFFFE) ; /* ?????? */ + break ; + + case CAT_MARKER: + psf_binheader_readf (psf, "E4", &length) ; + psf_log_printf (psf, " %M : %d\n", marker, length) ; + /*-psf_binheader_readf (psf, "j", length) ;-*/ + break ; + + case DEVL_MARKER: + psf_binheader_readf (psf, "mE4", &marker, &length) ; + psf_log_printf (psf, " DEVL%M : %d\n", marker, length) ; + if (length & 1) + length ++ ; + psf_binheader_readf (psf, "j", length) ; + break ; + + case EQ_MARKER: + case COMP_MARKER: + psf_binheader_readf (psf, "E4", &length) ; + psf_log_printf (psf, " %M : %d\n", marker, length) ; + /* This is weird!!!! why make this (length - 1) */ + if (length & 1) + length ++ ; + psf_binheader_readf (psf, "j", length) ; + break ; + + case SLCL_MARKER: + psf_log_printf (psf, " %M\n (Offset, Next Offset, Type)\n", marker) ; + slce_count = 0 ; + break ; + + case SLCE_MARKER: + { int len [4], indx ; + + psf_binheader_readf (psf, "E4444", &len [0], &len [1], &len [2], &len [3]) ; + + indx = ((len [3] & 0x0000FFFF) >> 8) & 3 ; + + if (len [2] == 1) + { if (indx != 1) + indx = 3 ; /* 2 cases, where next slice offset = 1 -> disabled & enabled/hidden */ + + psf_log_printf (psf, " %M : (%6d, ?: 0x%X, %s)\n", marker, len [1], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ; + } + else + { slce_total += len [2] ; + + psf_log_printf (psf, " %M : (%6d, SLCE_next_ofs:%d, ?: 0x%X, %s)\n", marker, len [1], len [2], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ; + } ; + + slce_count ++ ; + } ; + break ; + + case SINF_MARKER: + psf_binheader_readf (psf, "E4", &length) ; + psf_log_printf (psf, " %M : %d\n", marker, length) ; + + psf_binheader_readf (psf, "E2", &n_channels) ; + n_channels = (n_channels & 0x0000FF00) >> 8 ; + psf_log_printf (psf, " Channels : %d\n", n_channels) ; + + psf_binheader_readf (psf, "E44", &psf->sf.samplerate, &frames) ; + psf->sf.frames = frames ; + psf_log_printf (psf, " Sample Rate : %d\n", psf->sf.samplerate) ; + psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ; + + psf_binheader_readf (psf, "E4", &length) ; + psf_log_printf (psf, " ??????????? : %d\n", length) ; + + psf_binheader_readf (psf, "E4", &length) ; + psf_log_printf (psf, " ??????????? : %d\n", length) ; + break ; + + case SDAT_MARKER: + psf_binheader_readf (psf, "E4", &length) ; + + sdat_length = length ; + + /* Get the current offset. */ + psf->dataoffset = psf_binheader_readf (psf, NULL) ; + + if (psf->dataoffset + length != psf->filelength) + psf_log_printf (psf, " %M : %d (should be %d)\n", marker, length, psf->dataoffset + psf->filelength) ; + else + psf_log_printf (psf, " %M : %d\n", marker, length) ; + break ; + + default : + psf_log_printf (psf, "Unknown marker : 0x%X %M", marker, marker) ; + return -1003 ; + break ; + } ; + + /* SDAT always last marker in file. */ + if (marker == SDAT_MARKER) + break ; + } ; + + puts (psf->logbuffer) ; + puts ("-----------------------------------") ; + + printf ("SDAT length : %d\n", sdat_length) ; + printf ("SLCE count : %d\n", slce_count) ; + + /* Hack for zero slice count. */ + if (slce_count == 0 && slce_total == 1) + slce_total = frames ; + + printf ("SLCE samples : %d\n", slce_total) ; + + /* Two bytes per sample. */ + printf ("Comp Ratio : %f:1\n", (2.0 * slce_total * n_channels) / sdat_length) ; + + puts (" ") ; + + psf->logbuffer [0] = 0 ; + + /* OK, have the header although not too sure what it all means. */ + + psf->endian = SF_ENDIAN_BIG ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf_fseek (psf, psf->dataoffset, SEEK_SET)) + return SFE_BAD_SEEK ; + + psf->sf.format = (SF_FORMAT_REX2 | SF_FORMAT_DWVW_12) ; + + psf->sf.channels = 1 ; + psf->bytewidth = 2 ; + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + if ((error = dwvw_init (psf, 16))) + return error ; + + psf->container_close = rx2_close ; + + if (! psf->sf.frames && psf->blockwidth) + psf->sf.frames = psf->datalength / psf->blockwidth ; + + /* All done. */ + + return 0 ; +} /* rx2_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +rx2_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE) + { /* Now we know for certain the length of the file we can re-write + ** correct values for the FORM, 8SVX and BODY chunks. + */ + + } ; + + return 0 ; +} /* rx2_close */ + +#endif +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 7366e813-9fee-4d1f-881e-e4a691469370 +*/ diff --git a/nylsf/sd2.c b/nylsf/sd2.c new file mode 100644 index 0000000..7ef4814 --- /dev/null +++ b/nylsf/sd2.c @@ -0,0 +1,613 @@ +/* +** Copyright (C) 2001-2006 Erik de Castro Lopo +** Copyright (C) 2004 Paavo Jumppanen +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** The sd2 support implemented in this file was partially sponsored +** (financially) by Paavo Jumppanen. +*/ + +/* +** Documentation on the Mac resource fork was obtained here : +** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +/*------------------------------------------------------------------------------ + * Markers. +*/ + +#define Sd2f_MARKER MAKE_MARKER ('S', 'd', '2', 'f') +#define Sd2a_MARKER MAKE_MARKER ('S', 'd', '2', 'a') +#define ALCH_MARKER MAKE_MARKER ('A', 'L', 'C', 'H') +#define lsf1_MARKER MAKE_MARKER ('l', 's', 'f', '1') + +#define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ') +#define sdML_MARKER MAKE_MARKER ('s', 'd', 'M', 'L') + +enum +{ RSRC_STR = 111, + RSRC_BIN +} ; + +typedef struct +{ unsigned char * rsrc_data ; + int rsrc_len ; + + int data_offset, data_length ; + int map_offset, map_length ; + + int type_count, type_offset ; + int item_offset ; + + int str_index, str_count ; + + int string_offset ; + + /* All the above just to get these three. */ + int sample_size, sample_rate, channels ; +} SD2_RSRC ; + +typedef struct +{ int type ; + int id ; + char name [32] ; + char value [32] ; + int value_len ; +} STR_RSRC ; + +/*------------------------------------------------------------------------------ + * Private static functions. +*/ + +static int sd2_close (SF_PRIVATE *psf) ; + +static int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ; +static int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ; + +static int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ; + +/*------------------------------------------------------------------------------ +** Public functions. +*/ + +int +sd2_open (SF_PRIVATE *psf) +{ int subformat, error = 0, valid ; + + /* SD2 is always big endian. */ + psf->endian = SF_ENDIAN_BIG ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->rsrclength > 0)) + { psf_use_rsrc (psf, SF_TRUE) ; + valid = psf_file_valid (psf) ; + psf_use_rsrc (psf, SF_FALSE) ; + if (! valid) + { psf_log_printf (psf, "sd2_open : psf->rsrcdes < 0\n") ; + return SFE_SD2_BAD_RSRC ; + } ; + + error = sd2_parse_rsrc_fork (psf) ; + + if (error) + goto error_cleanup ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2) + { error = SFE_BAD_OPEN_FORMAT ; + goto error_cleanup ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + psf->dataoffset = 0 ; + + /* Only open and write the resource in RDWR mode is its current length is zero. */ + if (psf->mode == SFM_WRITE || (psf->mode == SFM_RDWR && psf->rsrclength == 0)) + { psf_open_rsrc (psf, psf->mode) ; + + error = sd2_write_rsrc_fork (psf, SF_FALSE) ; + + if (error) + goto error_cleanup ; + + /* Not needed. */ + psf->write_header = NULL ; + } ; + + psf->container_close = sd2_close ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */ + case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ + case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */ + error = pcm_init (psf) ; + break ; + + default : + error = SFE_UNIMPLEMENTED ; + break ; + } ; + + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + +error_cleanup: + + /* Close the resource fork regardless. We won't need it again. */ + psf_close_rsrc (psf) ; + + return error ; +} /* sd2_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +sd2_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE) + { /* Now we know for certain the audio_length of the file we can re-write + ** correct values for the FORM, 8SVX and BODY chunks. + */ + + } ; + + return 0 ; +} /* sd2_close */ + +/*------------------------------------------------------------------------------ +*/ + +static inline void +write_char (unsigned char * data, int offset, char value) +{ data [offset] = value ; +} /* write_char */ + +static inline void +write_short (unsigned char * data, int offset, short value) +{ data [offset] = value >> 8 ; + data [offset + 1] = value ; +} /* write_char */ + +static inline void +write_int (unsigned char * data, int offset, int value) +{ data [offset] = value >> 24 ; + data [offset + 1] = value >> 16 ; + data [offset + 2] = value >> 8 ; + data [offset + 3] = value ; +} /* write_int */ + +static inline void +write_marker (unsigned char * data, int offset, int value) +{ + if (CPU_IS_BIG_ENDIAN) + { data [offset] = value >> 24 ; + data [offset + 1] = value >> 16 ; + data [offset + 2] = value >> 8 ; + data [offset + 3] = value ; + } + else + { data [offset] = value ; + data [offset + 1] = value >> 8 ; + data [offset + 2] = value >> 16 ; + data [offset + 3] = value >> 24 ; + } ; +} /* write_marker */ + +static void +write_str (unsigned char * data, int offset, char * buffer, int buffer_len) +{ memcpy (data + offset, buffer, buffer_len) ; +} /* write_str */ + +static int +sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length)) +{ SD2_RSRC rsrc ; + STR_RSRC str_rsrc [] = + { { RSRC_STR, 1000, "_sample-size", "", 0 }, + { RSRC_STR, 1001, "_sample-rate", "", 0 }, + { RSRC_STR, 1002, "_channels", "", 0 }, + { RSRC_BIN, 1000, "_Markers", "", 8 } + } ; + + int k, str_offset, data_offset, next_str ; + + psf_use_rsrc (psf, SF_TRUE) ; + + memset (&rsrc, 0, sizeof (rsrc)) ; + + rsrc.sample_rate = psf->sf.samplerate ; + rsrc.sample_size = psf->bytewidth ; + rsrc.channels = psf->sf.channels ; + + rsrc.rsrc_data = psf->header ; + rsrc.rsrc_len = sizeof (psf->header) ; + memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ; + + LSF_SNPRINTF (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ; + LSF_SNPRINTF (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ; + LSF_SNPRINTF (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels) ; + + for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++) + { if (str_rsrc [k].value_len == 0) + { str_rsrc [k].value_len = strlen (str_rsrc [k].value) ; + str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ; + } ; + + /* Turn name string into a pascal string. */ + str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ; + } ; + + rsrc.data_offset = 0x100 ; + + /* + ** Calculate data length : + ** length of strings, plus the length of the sdML chunk. + */ + rsrc.data_length = 0 ; + for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++) + rsrc.data_length += str_rsrc [k].value_len + 4 ; + + rsrc.map_offset = rsrc.data_offset + rsrc.data_length ; + + /* Very start of resource fork. */ + write_int (rsrc.rsrc_data, 0, rsrc.data_offset) ; + write_int (rsrc.rsrc_data, 4, rsrc.map_offset) ; + write_int (rsrc.rsrc_data, 8, rsrc.data_length) ; + + write_char (rsrc.rsrc_data, 0x30, strlen (psf->filename)) ; + write_str (rsrc.rsrc_data, 0x31, psf->filename, strlen (psf->filename)) ; + + write_short (rsrc.rsrc_data, 0x50, 0) ; + write_marker (rsrc.rsrc_data, 0x52, Sd2f_MARKER) ; + write_marker (rsrc.rsrc_data, 0x56, lsf1_MARKER) ; + + /* Very start of resource map. */ + write_int (rsrc.rsrc_data, rsrc.map_offset + 0, rsrc.data_offset) ; + write_int (rsrc.rsrc_data, rsrc.map_offset + 4, rsrc.map_offset) ; + write_int (rsrc.rsrc_data, rsrc.map_offset + 8, rsrc.data_length) ; + + /* These I don't currently understand. */ + if (1) + { write_char (rsrc.rsrc_data, rsrc.map_offset+ 16, 1) ; + /* Next resource map. */ + write_int (rsrc.rsrc_data, rsrc.map_offset + 17, 0x12345678) ; + /* File ref number. */ + write_short (rsrc.rsrc_data, rsrc.map_offset + 21, 0xabcd) ; + /* Fork attributes. */ + write_short (rsrc.rsrc_data, rsrc.map_offset + 23, 0) ; + } ; + + /* Resource type offset. */ + rsrc.type_offset = rsrc.map_offset + 30 ; + write_short (rsrc.rsrc_data, rsrc.map_offset + 24, rsrc.type_offset - rsrc.map_offset - 2) ; + + /* Type index max. */ + rsrc.type_count = 2 ; + write_short (rsrc.rsrc_data, rsrc.map_offset + 28, rsrc.type_count - 1) ; + + rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ; + + rsrc.str_count = ARRAY_LEN (str_rsrc) ; + rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ; + write_short (rsrc.rsrc_data, rsrc.map_offset + 26, rsrc.string_offset) ; + + /* Write 'STR ' resource type. */ + rsrc.str_count = 3 ; + write_marker (rsrc.rsrc_data, rsrc.type_offset, STR_MARKER) ; + write_short (rsrc.rsrc_data, rsrc.type_offset + 4, rsrc.str_count - 1) ; + write_short (rsrc.rsrc_data, rsrc.type_offset + 6, 0x12) ; + + /* Write 'sdML' resource type. */ + write_marker (rsrc.rsrc_data, rsrc.type_offset + 8, sdML_MARKER) ; + write_short (rsrc.rsrc_data, rsrc.type_offset + 12, 0) ; + write_short (rsrc.rsrc_data, rsrc.type_offset + 14, 0x36) ; + + str_offset = rsrc.map_offset + rsrc.string_offset ; + next_str = 0 ; + data_offset = rsrc.data_offset ; + for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++) + { write_str (rsrc.rsrc_data, str_offset, str_rsrc [k].name, strlen (str_rsrc [k].name)) ; + + write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12, str_rsrc [k].id) ; + write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 2, next_str) ; + + str_offset += strlen (str_rsrc [k].name) ; + next_str += strlen (str_rsrc [k].name) ; + + write_int (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 4, data_offset - rsrc.data_offset) ; + + write_int (rsrc.rsrc_data, data_offset, str_rsrc [k].value_len) ; + write_str (rsrc.rsrc_data, data_offset + 4, str_rsrc [k].value, str_rsrc [k].value_len) ; + data_offset += 4 + str_rsrc [k].value_len ; + } ; + + /* Finally, calculate and set map length. */ + rsrc.map_length = str_offset - rsrc.map_offset ; + write_int (rsrc.rsrc_data, 12, rsrc.map_length) ; + write_int (rsrc.rsrc_data, rsrc.map_offset + 12, rsrc.map_length) ; + + rsrc.rsrc_len = rsrc.map_offset + rsrc.map_length ; + + psf_fwrite (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ; + + psf_use_rsrc (psf, SF_FALSE) ; + + if (psf->error) + return psf->error ; + + return 0 ; +} /* sd2_write_rsrc_fork */ + +/*------------------------------------------------------------------------------ +*/ + +static inline int +read_char (const unsigned char * data, int offset) +{ return data [offset] ; +} /* read_char */ + +static inline int +read_short (const unsigned char * data, int offset) +{ return (data [offset] << 8) + data [offset + 1] ; +} /* read_short */ + +static inline int +read_int (const unsigned char * data, int offset) +{ return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ; +} /* read_int */ + +static inline int +read_marker (const unsigned char * data, int offset) +{ + if (CPU_IS_BIG_ENDIAN) + return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ; + else if (CPU_IS_LITTLE_ENDIAN) + return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (data [offset + 3] << 24) ; + else + return 0x666 ; +} /* read_marker */ + +static void +read_str (const unsigned char * data, int offset, char * buffer, int buffer_len) +{ int k ; + + memset (buffer, 0, buffer_len) ; + + for (k = 0 ; k < buffer_len - 1 ; k++) + { if (isprint (data [offset + k]) == 0) + return ; + buffer [k] = data [offset + k] ; + } ; + return ; +} /* read_str */ + +static int +sd2_parse_rsrc_fork (SF_PRIVATE *psf) +{ SD2_RSRC rsrc ; + int k, marker, error = 0 ; + + psf_use_rsrc (psf, SF_TRUE) ; + + memset (&rsrc, 0, sizeof (rsrc)) ; + + rsrc.rsrc_len = psf_get_filelen (psf) ; + psf_log_printf (psf, "Resource length : %d (0x%04X)\n", rsrc.rsrc_len, rsrc.rsrc_len) ; + + if (rsrc.rsrc_len > SIGNED_SIZEOF (psf->header)) + rsrc.rsrc_data = calloc (1, rsrc.rsrc_len) ; + else + rsrc.rsrc_data = psf->header ; + + /* Read in the whole lot. */ + psf_fread (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ; + + /* Reset the header storage because we have changed to the rsrcdes. */ + psf->headindex = psf->headend = rsrc.rsrc_len ; + + rsrc.data_offset = read_int (rsrc.rsrc_data, 0) ; + rsrc.map_offset = read_int (rsrc.rsrc_data, 4) ; + rsrc.data_length = read_int (rsrc.rsrc_data, 8) ; + rsrc.map_length = read_int (rsrc.rsrc_data, 12) ; + + if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000) + { psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ; + rsrc.data_offset = read_int (rsrc.rsrc_data, 0x52 + 0) + 0x52 ; + rsrc.map_offset = read_int (rsrc.rsrc_data, 0x52 + 4) + 0x52 ; + rsrc.data_length = read_int (rsrc.rsrc_data, 0x52 + 8) ; + rsrc.map_length = read_int (rsrc.rsrc_data, 0x52 + 12) ; + } ; + + psf_log_printf (psf, " data offset : 0x%04X\n map offset : 0x%04X\n" + " data length : 0x%04X\n map length : 0x%04X\n", + rsrc.data_offset, rsrc.map_offset, rsrc.data_length, rsrc.map_length) ; + + if (rsrc.data_offset > rsrc.rsrc_len) + { psf_log_printf (psf, "Error : rsrc.data_offset (%d, 0x%x) > len\n", rsrc.data_offset, rsrc.data_offset) ; + error = SFE_SD2_BAD_DATA_OFFSET ; + goto parse_rsrc_fork_cleanup ; + } ; + + if (rsrc.map_offset > rsrc.rsrc_len) + { psf_log_printf (psf, "Error : rsrc.map_offset > len\n") ; + error = SFE_SD2_BAD_MAP_OFFSET ; + goto parse_rsrc_fork_cleanup ; + } ; + + if (rsrc.data_length > rsrc.rsrc_len) + { psf_log_printf (psf, "Error : rsrc.data_length > len\n") ; + error = SFE_SD2_BAD_DATA_LENGTH ; + goto parse_rsrc_fork_cleanup ; + } ; + + if (rsrc.map_length > rsrc.rsrc_len) + { psf_log_printf (psf, "Error : rsrc.map_length > len\n") ; + error = SFE_SD2_BAD_MAP_LENGTH ; + goto parse_rsrc_fork_cleanup ; + } ; + + if (rsrc.data_offset + rsrc.data_length != rsrc.map_offset || rsrc.map_offset + rsrc.map_length != rsrc.rsrc_len) + { psf_log_printf (psf, "Error : This does not look like a MacOSX resource fork.\n") ; + error = SFE_SD2_BAD_RSRC ; + goto parse_rsrc_fork_cleanup ; + } ; + + rsrc.string_offset = rsrc.map_offset + read_short (rsrc.rsrc_data, rsrc.map_offset + 26) ; + if (rsrc.string_offset > rsrc.rsrc_len) + { psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ; + error = SFE_SD2_BAD_RSRC ; + goto parse_rsrc_fork_cleanup ; + } ; + + rsrc.type_offset = rsrc.map_offset + 30 ; + + rsrc.type_count = read_short (rsrc.rsrc_data, rsrc.map_offset + 28) + 1 ; + if (rsrc.type_count < 1) + { psf_log_printf (psf, "Bad type count.\n") ; + error = SFE_SD2_BAD_RSRC ; + goto parse_rsrc_fork_cleanup ; + } ; + + rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ; + if (rsrc.item_offset < 0 || rsrc.item_offset > rsrc.rsrc_len) + { psf_log_printf (psf, "Bad item offset (%d).\n", rsrc.item_offset) ; + error = SFE_SD2_BAD_RSRC ; + goto parse_rsrc_fork_cleanup ; + } ; + + rsrc.str_index = -1 ; + for (k = 0 ; k < rsrc.type_count ; k ++) + { marker = read_marker (rsrc.rsrc_data, rsrc.type_offset + k * 8) ; + + if (marker == STR_MARKER) + { rsrc.str_index = k ; + rsrc.str_count = read_short (rsrc.rsrc_data, rsrc.type_offset + k * 8 + 4) + 1 ; + error = parse_str_rsrc (psf, &rsrc) ; + goto parse_rsrc_fork_cleanup ; + } ; + } ; + + psf_log_printf (psf, "No 'STR ' resource.\n") ; + error = SFE_SD2_BAD_RSRC ; + +parse_rsrc_fork_cleanup : + + psf_use_rsrc (psf, SF_FALSE) ; + + if ((void *) rsrc.rsrc_data < (void *) psf || (void *) rsrc.rsrc_data > (void *) (psf + 1)) + free (rsrc.rsrc_data) ; + + return error ; +} /* sd2_parse_rsrc_fork */ + +static int +parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) +{ char name [32], value [32] ; + int k, str_offset, data_offset, data_len, rsrc_id ; + + psf_log_printf (psf, "Finding parameters :\n") ; + + str_offset = rsrc->string_offset ; + for (k = 0 ; k < rsrc->str_count ; k++) + { int slen ; + + slen = read_char (rsrc->rsrc_data, str_offset) ; + read_str (rsrc->rsrc_data, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ; + str_offset += slen + 1 ; + + rsrc_id = read_short (rsrc->rsrc_data, rsrc->item_offset + k * 12) ; + + data_offset = rsrc->data_offset + read_int (rsrc->rsrc_data, rsrc->item_offset + k * 12 + 4) ; + if (data_offset < 0 || data_offset > rsrc->rsrc_len) + { psf_log_printf (psf, "Bad data offset (%d)\n", data_offset) ; + return SFE_SD2_BAD_DATA_OFFSET ; + } ; + + data_len = read_int (rsrc->rsrc_data, data_offset) ; + if (data_len < 0 || data_len > rsrc->rsrc_len) + { psf_log_printf (psf, "Bad data length (%d).\n", data_len) ; + return SFE_SD2_BAD_RSRC ; + } ; + + slen = read_char (rsrc->rsrc_data, data_offset + 4) ; + read_str (rsrc->rsrc_data, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ; + + psf_log_printf (psf, " %-12s 0x%04x %4d %2d %2d '%s'\n", name, data_offset, rsrc_id, data_len, slen, value) ; + + if (strcmp (name, "sample-size") == 0 && rsrc->sample_size == 0) + rsrc->sample_size = strtol (value, NULL, 10) ; + else if (strcmp (name, "sample-rate") == 0 && rsrc->sample_rate == 0) + rsrc->sample_rate = strtol (value, NULL, 10) ; + else if (strcmp (name, "channels") == 0 && rsrc->channels == 0) + rsrc->channels = strtol (value, NULL, 10) ; + } ; + + if (rsrc->sample_rate < 0) + { psf_log_printf (psf, "Bad sample rate (%d)\n", rsrc->sample_rate) ; + return SFE_SD2_BAD_RSRC ; + } ; + + if (rsrc->channels < 0) + { psf_log_printf (psf, "Bad channel count (%d)\n", rsrc->channels) ; + return SFE_SD2_BAD_RSRC ; + } ; + + psf->sf.samplerate = rsrc->sample_rate ; + psf->sf.channels = rsrc->channels ; + psf->bytewidth = rsrc->sample_size ; + + switch (rsrc->sample_size) + { case 1 : + psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_S8 ; + break ; + + case 2 : + psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ; + break ; + + case 3 : + psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ; + break ; + + default : + psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ; + return SFE_SD2_BAD_SAMPLE_SIZE ; + } ; + + psf_log_printf (psf, "ok\n") ; + + return 0 ; +} /* parse_str_rsrc */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 1ee183e5-6b9f-4c2c-bd0a-24f35595cefc +*/ diff --git a/nylsf/sds.c b/nylsf/sds.c new file mode 100644 index 0000000..710d211 --- /dev/null +++ b/nylsf/sds.c @@ -0,0 +1,993 @@ +/* +** Copyright (C) 2002-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "float_cast.h" + +/*------------------------------------------------------------------------------ +*/ + +#define SDS_DATA_OFFSET 0x15 +#define SDS_BLOCK_SIZE 127 + +#define SDS_AUDIO_BYTES_PER_BLOCK 120 + +#define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2)) +#define SDS_INT_TO_3BYTE_ENCODE(x) (((x) & 0x7F) | (((x) << 1) & 0x7F00) | (((x) << 2) & 0x7F0000)) + +/*------------------------------------------------------------------------------ +** Typedefs. +*/ + +typedef struct tag_SDS_PRIVATE +{ int bitwidth, frames ; + int samplesperblock, total_blocks ; + + int (*reader) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ; + int (*writer) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ; + + int read_block, read_count ; + unsigned char read_data [SDS_BLOCK_SIZE] ; + int read_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */ + + int write_block, write_count ; + unsigned char write_data [SDS_BLOCK_SIZE] ; + int write_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */ +} SDS_PRIVATE ; + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int sds_close (SF_PRIVATE *psf) ; + +static int sds_write_header (SF_PRIVATE *psf, int calc_length) ; +static int sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; + +static int sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; + +static sf_count_t sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; + +static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; +static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; +static int sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; + +static int sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int readcount) ; + +static int sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; +static int sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; +static int sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; + +static int sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, const int *iptr, int writecount) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +sds_open (SF_PRIVATE *psf) +{ SDS_PRIVATE *psds ; + int error = 0 ; + + /* Hmmmm, need this here to pass update_header_test. */ + psf->sf.frames = 0 ; + + if (! (psds = calloc (1, sizeof (SDS_PRIVATE)))) + return SFE_MALLOC_FAILED ; + psf->codec_data = psds ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = sds_read_header (psf, psds))) + return error ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SDS) + return SFE_BAD_OPEN_FORMAT ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (sds_write_header (psf, SF_FALSE)) + return psf->error ; + + psf->write_header = sds_write_header ; + + psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ; + } ; + + if ((error = sds_init (psf, psds)) != 0) + return error ; + + psf->seek = sds_seek ; + psf->container_close = sds_close ; + + psf->blockwidth = 0 ; + + return error ; +} /* sds_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +sds_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { SDS_PRIVATE *psds ; + + if ((psds = (SDS_PRIVATE *) psf->codec_data) == NULL) + { psf_log_printf (psf, "*** Bad psf->codec_data ptr.\n") ; + return SFE_INTERNAL ; + } ; + + if (psds->write_count > 0) + { memset (&(psds->write_data [psds->write_count]), 0, (psds->samplesperblock - psds->write_count) * sizeof (int)) ; + psds->writer (psf, psds) ; + } ; + + sds_write_header (psf, SF_TRUE) ; + } ; + + return 0 ; +} /* sds_close */ + +static int +sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ + if (psds->bitwidth < 8 || psds->bitwidth > 28) + return (psf->error = SFE_SDS_BAD_BIT_WIDTH) ; + + if (psds->bitwidth < 14) + { psds->reader = sds_2byte_read ; + psds->writer = sds_2byte_write ; + psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 2 ; + } + else if (psds->bitwidth < 21) + { psds->reader = sds_3byte_read ; + psds->writer = sds_3byte_write ; + psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 3 ; + } + else + { psds->reader = sds_4byte_read ; + psds->writer = sds_4byte_write ; + psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 4 ; + } ; + + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { psf->read_short = sds_read_s ; + psf->read_int = sds_read_i ; + psf->read_float = sds_read_f ; + psf->read_double = sds_read_d ; + + /* Read first block. */ + psds->reader (psf, psds) ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { psf->write_short = sds_write_s ; + psf->write_int = sds_write_i ; + psf->write_float = sds_write_f ; + psf->write_double = sds_write_d ; + } ; + + return 0 ; +} /* sds_init */ + +static int +sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ unsigned char channel, bitwidth, loop_type, byte ; + unsigned short sample_no, marker ; + unsigned int samp_period, data_length, sustain_loop_start, sustain_loop_end ; + int bytesread, blockcount ; + + /* Set position to start of file to begin reading header. */ + bytesread = psf_binheader_readf (psf, "pE211", 0, &marker, &channel, &byte) ; + + if (marker != 0xF07E || byte != 0x01) + return SFE_SDS_NOT_SDS ; + + psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n Midi Channel : %d\n", channel) ; + + bytesread += psf_binheader_readf (psf, "e213", &sample_no, &bitwidth, &samp_period) ; + + sample_no = SDS_3BYTE_TO_INT_DECODE (sample_no) ; + samp_period = SDS_3BYTE_TO_INT_DECODE (samp_period) ; + + psds->bitwidth = bitwidth ; + + psf->sf.samplerate = 1000000000 / samp_period ; + + psf_log_printf (psf, " Sample Number : %d\n" + " Bit Width : %d\n" + " Sample Rate : %d\n", + sample_no, psds->bitwidth, psf->sf.samplerate) ; + + bytesread += psf_binheader_readf (psf, "e3331", &data_length, &sustain_loop_start, &sustain_loop_end, &loop_type) ; + + data_length = SDS_3BYTE_TO_INT_DECODE (data_length) ; + + sustain_loop_start = SDS_3BYTE_TO_INT_DECODE (sustain_loop_start) ; + sustain_loop_end = SDS_3BYTE_TO_INT_DECODE (sustain_loop_end) ; + + psf_log_printf (psf, " Sustain Loop\n" + " Start : %d\n" + " End : %d\n" + " Loop Type : %d\n", + sustain_loop_start, sustain_loop_end, loop_type) ; + + psf->dataoffset = SDS_DATA_OFFSET ; + psf->datalength = psf->filelength - psf->dataoffset ; + + if (data_length != psf->filelength - psf->dataoffset) + { psf_log_printf (psf, " Datalength : %d (truncated data??? %d)\n", data_length, psf->filelength - psf->dataoffset) ; + data_length = psf->filelength - psf->dataoffset ; + } + else + psf_log_printf (psf, " Datalength : %d\n", data_length) ; + + bytesread += psf_binheader_readf (psf, "1", &byte) ; + if (byte != 0xF7) + psf_log_printf (psf, "bad end : %X\n", byte & 0xFF) ; + + for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++) + { + bytesread += psf_fread (&marker, 1, 2, psf) ; + + if (marker == 0) + break ; + + psf_fseek (psf, SDS_BLOCK_SIZE - 2, SEEK_CUR) ; + bytesread += SDS_BLOCK_SIZE - 2 ; + } ; + + psf_log_printf (psf, "\nBlocks : %d\n", blockcount) ; + psds->total_blocks = blockcount ; + + psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / ((psds->bitwidth + 6) / 7) ; + psf_log_printf (psf, "Samples/Block : %d\n", psds->samplesperblock) ; + + psf_log_printf (psf, "Frames : %d\n", blockcount * psds->samplesperblock) ; + + psf->sf.frames = blockcount * psds->samplesperblock ; + psds->frames = blockcount * psds->samplesperblock ; + + /* Always Mono */ + psf->sf.channels = 1 ; + psf->sf.sections = 1 ; + + /* + ** Lie to the user about PCM bit width. Always round up to + ** the next multiple of 8. + */ + switch ((psds->bitwidth + 7) / 8) + { case 1 : + psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_S8 ; + break ; + + case 2 : + psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_16 ; + break ; + + case 3 : + psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_24 ; + break ; + + case 4 : + psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_32 ; + break ; + + default : + psf_log_printf (psf, "*** Weird byte width (%d)\n", (psds->bitwidth + 7) / 8) ; + return SFE_SDS_BAD_BIT_WIDTH ; + } ; + + psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ; + + return 0 ; +} /* sds_read_header */ + +static int +sds_write_header (SF_PRIVATE *psf, int calc_length) +{ SDS_PRIVATE *psds ; + sf_count_t current ; + int samp_period, data_length, sustain_loop_start, sustain_loop_end ; + unsigned char loop_type = 0 ; + + if ((psds = (SDS_PRIVATE *) psf->codec_data) == NULL) + { psf_log_printf (psf, "*** Bad psf->codec_data ptr.\n") ; + return SFE_INTERNAL ; + } ; + + if (psf->pipeoffset > 0) + return 0 ; + + current = psf_ftell (psf) ; + + if (calc_length) + psf->sf.frames = psds->total_blocks * psds->samplesperblock + psds->write_count ; + + if (psds->write_count > 0) + { int current_count = psds->write_count ; + int current_block = psds->write_block ; + + psds->writer (psf, psds) ; + + psf_fseek (psf, -1 * SDS_BLOCK_SIZE, SEEK_CUR) ; + + psds->write_count = current_count ; + psds->write_block = current_block ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + if (psf->is_pipe == SF_FALSE) + psf_fseek (psf, 0, SEEK_SET) ; + + psf_binheader_writef (psf, "E211", 0xF07E, 0, 1) ; + + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + psds->bitwidth = 8 ; + break ; + case SF_FORMAT_PCM_16 : + psds->bitwidth = 16 ; + break ; + case SF_FORMAT_PCM_24 : + psds->bitwidth = 24 ; + break ; + default: + return SFE_SDS_BAD_BIT_WIDTH ; + } ; + + samp_period = SDS_INT_TO_3BYTE_ENCODE (1000000000 / psf->sf.samplerate) ; + + psf_binheader_writef (psf, "e213", 0, psds->bitwidth, samp_period) ; + + data_length = SDS_INT_TO_3BYTE_ENCODE (psds->total_blocks * SDS_BLOCK_SIZE) ; + sustain_loop_start = SDS_INT_TO_3BYTE_ENCODE (0) ; + sustain_loop_end = SDS_INT_TO_3BYTE_ENCODE (psf->sf.frames) ; + + psf_binheader_writef (psf, "e33311", data_length, sustain_loop_start, sustain_loop_end, loop_type, 0xF7) ; + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + psf->datalength = psds->write_block * SDS_BLOCK_SIZE ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* sds_write_header */ + + +/*------------------------------------------------------------------------------ +*/ + +static int +sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ unsigned char *ucptr, checksum ; + unsigned int sample ; + int k ; + + psds->read_block ++ ; + psds->read_count = 0 ; + + if (psds->read_block * psds->samplesperblock > psds->frames) + { memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ; + return 1 ; + } ; + + if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; + + if (psds->read_data [0] != 0xF0) + { printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ; + } ; + + checksum = psds->read_data [1] ; + if (checksum != 0x7E) + { printf ("Error 1 : %02X\n", checksum & 0xFF) ; + } + + for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) + checksum ^= psds->read_data [k] ; + + checksum &= 0x7F ; + + if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2]) + { psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ; + } ; + + ucptr = psds->read_data + 5 ; + for (k = 0 ; k < 120 ; k += 2) + { sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) ; + psds->read_samples [k / 2] = (int) (sample - 0x80000000) ; + } ; + + return 1 ; +} /* sds_2byte_read */ + +static int +sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ unsigned char *ucptr, checksum ; + unsigned int sample ; + int k ; + + psds->read_block ++ ; + psds->read_count = 0 ; + + if (psds->read_block * psds->samplesperblock > psds->frames) + { memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ; + return 1 ; + } ; + + if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; + + if (psds->read_data [0] != 0xF0) + { printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ; + } ; + + checksum = psds->read_data [1] ; + if (checksum != 0x7E) + { printf ("Error 1 : %02X\n", checksum & 0xFF) ; + } + + for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) + checksum ^= psds->read_data [k] ; + + checksum &= 0x7F ; + + if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2]) + { psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ; + } ; + + ucptr = psds->read_data + 5 ; + for (k = 0 ; k < 120 ; k += 3) + { sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) ; + psds->read_samples [k / 3] = (int) (sample - 0x80000000) ; + } ; + + return 1 ; +} /* sds_3byte_read */ + +static int +sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ unsigned char *ucptr, checksum ; + unsigned int sample ; + int k ; + + psds->read_block ++ ; + psds->read_count = 0 ; + + if (psds->read_block * psds->samplesperblock > psds->frames) + { memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ; + return 1 ; + } ; + + if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; + + if (psds->read_data [0] != 0xF0) + { printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ; + } ; + + checksum = psds->read_data [1] ; + if (checksum != 0x7E) + { printf ("Error 1 : %02X\n", checksum & 0xFF) ; + } + + for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) + checksum ^= psds->read_data [k] ; + + checksum &= 0x7F ; + + if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2]) + { psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ; + } ; + + ucptr = psds->read_data + 5 ; + for (k = 0 ; k < 120 ; k += 4) + { sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) + (ucptr [k + 3] << 4) ; + psds->read_samples [k / 4] = (int) (sample - 0x80000000) ; + } ; + + return 1 ; +} /* sds_4byte_read */ + + +static sf_count_t +sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int *iptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = sds_read (psf, psds, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = iptr [k] >> 16 ; + total += count ; + len -= readcount ; + } ; + + return total ; +} /* sds_read_s */ + +static sf_count_t +sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int total ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + total = sds_read (psf, psds, ptr, len) ; + + return total ; +} /* sds_read_i */ + +static sf_count_t +sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int *iptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + if (psf->norm_float == SF_TRUE) + normfact = 1.0 / 0x80000000 ; + else + normfact = 1.0 / (1 << psds->bitwidth) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = sds_read (psf, psds, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * iptr [k] ; + total += count ; + len -= readcount ; + } ; + + return total ; +} /* sds_read_f */ + +static sf_count_t +sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int *iptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + if (psf->norm_double == SF_TRUE) + normfact = 1.0 / 0x80000000 ; + else + normfact = 1.0 / (1 << psds->bitwidth) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = sds_read (psf, psds, iptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * iptr [k] ; + total += count ; + len -= readcount ; + } ; + + return total ; +} /* sds_read_d */ + +static int +sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *ptr, int len) +{ int count, total = 0 ; + + while (total < len) + { if (psds->read_block * psds->samplesperblock >= psds->frames) + { memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ; + return total ; + } ; + + if (psds->read_count >= psds->samplesperblock) + psds->reader (psf, psds) ; + + count = (psds->samplesperblock - psds->read_count) ; + count = (len - total > count) ? count : len - total ; + + memcpy (&(ptr [total]), &(psds->read_samples [psds->read_count]), count * sizeof (int)) ; + total += count ; + psds->read_count += count ; + } ; + + return total ; +} /* sds_read */ + +/*============================================================================== +*/ + +static sf_count_t +sds_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start) +{ SDS_PRIVATE *psds ; + sf_count_t file_offset ; + int newblock, newsample ; + + if ((psds = psf->codec_data) == NULL) + { psf->error = SFE_INTERNAL ; + return PSF_SEEK_ERROR ; + } ; + + if (psf->datalength < 0 || psf->dataoffset < 0) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (seek_from_start < 0 || seek_from_start > psf->sf.frames) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (mode == SFM_READ && psds->write_count > 0) + psds->writer (psf, psds) ; + + newblock = seek_from_start / psds->samplesperblock ; + newsample = seek_from_start % psds->samplesperblock ; + + switch (mode) + { case SFM_READ : + if (newblock > psds->total_blocks) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ; + + if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset) + { psf->error = SFE_SEEK_FAILED ; + return PSF_SEEK_ERROR ; + } ; + + psds->read_block = newblock ; + psds->reader (psf, psds) ; + psds->read_count = newsample ; + break ; + + case SFM_WRITE : + if (newblock > psds->total_blocks) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ; + + if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset) + { psf->error = SFE_SEEK_FAILED ; + return PSF_SEEK_ERROR ; + } ; + + psds->write_block = newblock ; + psds->reader (psf, psds) ; + psds->write_count = newsample ; + break ; + + default : + psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + break ; + } ; + + return seek_from_start ; +} /* sds_seek */ + +/*============================================================================== +*/ + +static int +sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ unsigned char *ucptr, checksum ; + unsigned int sample ; + int k ; + + psds->write_data [0] = 0xF0 ; + psds->write_data [1] = 0x7E ; + psds->write_data [2] = 0 ; /* Channel number */ + psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */ + + ucptr = psds->write_data + 5 ; + for (k = 0 ; k < 120 ; k += 2) + { sample = psds->write_samples [k / 2] ; + sample += 0x80000000 ; + ucptr [k] = (sample >> 25) & 0x7F ; + ucptr [k + 1] = (sample >> 18) & 0x7F ; + } ; + + checksum = psds->write_data [1] ; + for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) + checksum ^= psds->write_data [k] ; + checksum &= 0x7F ; + + psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; + psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; + + if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; + + psds->write_block ++ ; + psds->write_count = 0 ; + + if (psds->write_block > psds->total_blocks) + psds->total_blocks = psds->write_block ; + psds->frames = psds->total_blocks * psds->samplesperblock ; + + return 1 ; +} /* sds_2byte_write */ + +static int +sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ unsigned char *ucptr, checksum ; + unsigned int sample ; + int k ; + + psds->write_data [0] = 0xF0 ; + psds->write_data [1] = 0x7E ; + psds->write_data [2] = 0 ; /* Channel number */ + psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */ + + ucptr = psds->write_data + 5 ; + for (k = 0 ; k < 120 ; k += 3) + { sample = psds->write_samples [k / 3] ; + sample += 0x80000000 ; + ucptr [k] = (sample >> 25) & 0x7F ; + ucptr [k + 1] = (sample >> 18) & 0x7F ; + ucptr [k + 2] = (sample >> 11) & 0x7F ; + } ; + + checksum = psds->write_data [1] ; + for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) + checksum ^= psds->write_data [k] ; + checksum &= 0x7F ; + + psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; + psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; + + if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; + + psds->write_block ++ ; + psds->write_count = 0 ; + + if (psds->write_block > psds->total_blocks) + psds->total_blocks = psds->write_block ; + psds->frames = psds->total_blocks * psds->samplesperblock ; + + return 1 ; +} /* sds_3byte_write */ + +static int +sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) +{ unsigned char *ucptr, checksum ; + unsigned int sample ; + int k ; + + psds->write_data [0] = 0xF0 ; + psds->write_data [1] = 0x7E ; + psds->write_data [2] = 0 ; /* Channel number */ + psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */ + + ucptr = psds->write_data + 5 ; + for (k = 0 ; k < 120 ; k += 4) + { sample = psds->write_samples [k / 4] ; + sample += 0x80000000 ; + ucptr [k] = (sample >> 25) & 0x7F ; + ucptr [k + 1] = (sample >> 18) & 0x7F ; + ucptr [k + 2] = (sample >> 11) & 0x7F ; + ucptr [k + 3] = (sample >> 4) & 0x7F ; + } ; + + checksum = psds->write_data [1] ; + for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) + checksum ^= psds->write_data [k] ; + checksum &= 0x7F ; + + psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; + psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; + + if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) + psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; + + psds->write_block ++ ; + psds->write_count = 0 ; + + if (psds->write_block > psds->total_blocks) + psds->total_blocks = psds->write_block ; + psds->frames = psds->total_blocks * psds->samplesperblock ; + + return 1 ; +} /* sds_4byte_write */ + +static sf_count_t +sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int *iptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = ptr [total + k] << 16 ; + count = sds_write (psf, psds, iptr, writecount) ; + total += count ; + len -= writecount ; + } ; + + return total ; +} /* sds_write_s */ + +static sf_count_t +sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int total ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + total = sds_write (psf, psds, ptr, len) ; + + return total ; +} /* sds_write_i */ + +static sf_count_t +sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int *iptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + if (psf->norm_float == SF_TRUE) + normfact = 1.0 * 0x80000000 ; + else + normfact = 1.0 * (1 << psds->bitwidth) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = normfact * ptr [total + k] ; + count = sds_write (psf, psds, iptr, writecount) ; + total += count ; + len -= writecount ; + } ; + + return total ; +} /* sds_write_f */ + +static sf_count_t +sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ SDS_PRIVATE *psds ; + int *iptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->codec_data == NULL) + return 0 ; + psds = (SDS_PRIVATE*) psf->codec_data ; + + if (psf->norm_double == SF_TRUE) + normfact = 1.0 * 0x80000000 ; + else + normfact = 1.0 * (1 << psds->bitwidth) ; + + iptr = psf->u.ibuf ; + bufferlen = ARRAY_LEN (psf->u.ibuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : len ; + for (k = 0 ; k < writecount ; k++) + iptr [k] = normfact * ptr [total + k] ; + count = sds_write (psf, psds, iptr, writecount) ; + total += count ; + len -= writecount ; + } ; + + return total ; +} /* sds_write_d */ + +static int +sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, const int *ptr, int len) +{ int count, total = 0 ; + + while (total < len) + { count = psds->samplesperblock - psds->write_count ; + if (count > len - total) + count = len - total ; + + memcpy (&(psds->write_samples [psds->write_count]), &(ptr [total]), count * sizeof (int)) ; + total += count ; + psds->write_count += count ; + + if (psds->write_count >= psds->samplesperblock) + psds->writer (psf, psds) ; + } ; + + return total ; +} /* sds_write */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: d5d26aa3-368c-4ca6-bb85-377e5a2578cc +*/ diff --git a/nylsf/sf_unistd.h b/nylsf/sf_unistd.h new file mode 100644 index 0000000..f24ae67 --- /dev/null +++ b/nylsf/sf_unistd.h @@ -0,0 +1,67 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* Some defines that microsoft 'forgot' to implement. */ + +#ifndef S_IRWXU +#define S_IRWXU 0000700 /* rwx, owner */ +#endif + +#ifndef S_IRUSR +#define S_IRUSR 0000400 /* read permission, owner */ +#endif + +#ifndef S_IWUSR +#define S_IWUSR 0000200 /* write permission, owner */ +#endif + +#ifndef S_IXUSR +#define S_IXUSR 0000100 /* execute/search permission, owner */ +#endif + +#define S_IRWXG 0000070 /* rwx, group */ +#define S_IRGRP 0000040 /* read permission, group */ +#define S_IWGRP 0000020 /* write permission, grougroup */ +#define S_IXGRP 0000010 /* execute/search permission, group */ + +#define S_IRWXO 0000007 /* rwx, other */ +#define S_IROTH 0000004 /* read permission, other */ +#define S_IWOTH 0000002 /* write permission, other */ +#define S_IXOTH 0000001 /* execute/search permission, other */ + +#ifndef S_ISFIFO +#define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & _S_IFREG) == _S_IFREG) +#endif + +/* +** Don't know if these are still needed. +** +** #define _IFMT _S_IFMT +** #define _IFREG _S_IFREG +*/ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 253aea6d-6299-46fd-8d06-bc5f6224c8fe +*/ diff --git a/nylsf/sfconfig.h b/nylsf/sfconfig.h new file mode 100644 index 0000000..f12df6d --- /dev/null +++ b/nylsf/sfconfig.h @@ -0,0 +1,108 @@ +/* +** Copyright (C) 2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** Autoconf leaves many config parameters undefined. +** Here we change then from being undefined to defining them to 0. +** This allows things like: +** +** #if HAVE_CONFIG_PARAM +** +** and +** +** if (HAVE_CONFIG_PARAM) +** do_something () ; +*/ + +#ifndef SFCONFIG_H +#define SFCONFIG_H + +/* Include the Autoconf generated file. */ +#include "config.h" + +/* Now fiddle the values. */ + +#ifndef HAVE_ALSA_ASOUNDLIB_H +#define HAVE_ALSA_ASOUNDLIB_H 0 +#endif + +#ifndef HAVE_BYTESWAP_H +#define HAVE_BYTESWAP_H 0 +#endif + +#ifndef HAVE_DECL_S_IRGRP +#define HAVE_DECL_S_IRGRP 0 +#endif + +#ifndef HAVE_ENDIAN_H +#define HAVE_ENDIAN_H 0 +#endif + +#ifndef HAVE_FSYNC +#define HAVE_FSYNC 0 +#endif + +#ifndef HAVE_LOCALE_H +#define HAVE_LOCALE_H 0 +#endif + +#ifndef HAVE_LRINT +#define HAVE_LRINT 0 +#endif + +#ifndef HAVE_LRINTF +#define HAVE_LRINTF 0 +#endif + +#ifndef HAVE_MMAP +#define HAVE_MMAP 0 +#endif + +#ifndef HAVE_PREAD +#define HAVE_PREAD 0 +#endif + +#ifndef HAVE_PWRITE +#define HAVE_PWRITE 0 +#endif + +#ifndef HAVE_SETLOCALE +#define HAVE_SETLOCALE 0 +#endif + +#ifndef HAVE_SQLITE3 +#define HAVE_SQLITE3 0 +#endif + +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 0 +#endif + +#ifndef HAVE_UNISTD_H +#define HAVE_UNISTD_H 0 +#endif + +#endif + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 2df2316e-8f9d-4860-bba7-f3c16c63eed3 +*/ diff --git a/nylsf/sfendian.h b/nylsf/sfendian.h new file mode 100644 index 0000000..efc1c10 --- /dev/null +++ b/nylsf/sfendian.h @@ -0,0 +1,256 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#if HAVE_STDINT_H +#include +#elif HAVE_INTTYPES_H +#include +#endif + +#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8)) +/* Good, we have int64_t. */ +#elif (defined (SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)) +typedef long long int64_t ; +#elif (defined (SIZEOF_LONG) && (SIZEOF_LONG == 8)) +typedef long int64_t ; +#elif (defined (WIN32) || defined (_WIN32)) +typedef __int64 int64_t ; +#else +#error "No 64 bit integer type." +#endif + +#if HAVE_BYTESWAP_H + +#include + +#define ENDSWAP_SHORT(x) ((short) bswap_16 (x)) +#define ENDSWAP_INT(x) ((int) bswap_32 (x)) + +#else + +#define ENDSWAP_SHORT(x) ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8)) +#define ENDSWAP_INT(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24)) + +#endif + +/* +** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a +** marker indicating different sections of the file. +** The following MAKE_MARKER macro allows th creation of integer constants +** for these markers. +*/ + +#if (CPU_IS_LITTLE_ENDIAN == 1) + #define MAKE_MARKER(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) +#elif (CPU_IS_BIG_ENDIAN == 1) + #define MAKE_MARKER(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) +#else + #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h" +#endif + +/* +** Macros to handle reading of data of a specific endian-ness into host endian +** shorts and ints. The single input is an unsigned char* pointer to the start +** of the object. There are two versions of each macro as we need to deal with +** both big and little endian CPUs. +*/ + +#if (CPU_IS_LITTLE_ENDIAN == 1) + #define LES2H_SHORT(x) (x) + #define LEI2H_INT(x) (x) + + #define BES2H_SHORT(x) ENDSWAP_SHORT (x) + #define BEI2H_INT(x) ENDSWAP_INT (x) + + #define H2BE_SHORT(x) ENDSWAP_SHORT (x) + #define H2BE_INT(x) ENDSWAP_INT (x) + +#elif (CPU_IS_BIG_ENDIAN == 1) + #define LES2H_SHORT(x) ENDSWAP_SHORT (x) + #define LEI2H_INT(x) ENDSWAP_INT (x) + + #define BES2H_SHORT(x) (x) + #define BEI2H_INT(x) (x) + + #define H2LE_SHORT(x) ENDSWAP_SHORT (x) + #define H2LE_INT(x) ENDSWAP_INT (x) + +#else + #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h" +#endif + +#define LET2H_SHORT_PTR(x) ((x) [1] + ((x) [2] << 8)) +#define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24)) + +#define BET2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1]) +#define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8)) + +/*----------------------------------------------------------------------------------------------- +** Generic functions for performing endian swapping on integer arrays. +*/ + +static inline void +endswap_short_array (short *ptr, int len) +{ short temp ; + + while (--len >= 0) + { temp = ptr [len] ; + ptr [len] = ENDSWAP_SHORT (temp) ; + } ; +} /* endswap_short_array */ + +static inline void +endswap_short_copy (short *dest, const short *src, int len) +{ + while (--len >= 0) + { dest [len] = ENDSWAP_SHORT (src [len]) ; + } ; +} /* endswap_short_copy */ + +static inline void +endswap_int_array (int *ptr, int len) +{ int temp ; + + while (--len >= 0) + { temp = ptr [len] ; + ptr [len] = ENDSWAP_INT (temp) ; + } ; +} /* endswap_int_array */ + +static inline void +endswap_int_copy (int *dest, const int *src, int len) +{ + while (--len >= 0) + { dest [len] = ENDSWAP_INT (src [len]) ; + } ; +} /* endswap_int_copy */ + +/*======================================================================================== +*/ + +#if (HAVE_BYTESWAP_H && defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8)) + +static inline void +endswap_int64_t_array (int64_t *ptr, int len) +{ int64_t value ; + + while (--len >= 0) + { value = ptr [len] ; + ptr [len] = bswap_64 (value) ; + } ; +} /* endswap_int64_t_array */ + +static inline void +endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len) +{ int64_t value ; + + while (--len >= 0) + { value = src [len] ; + dest [len] = bswap_64 (value) ; + } ; +} /* endswap_int64_t_copy */ + +#else + +static inline void +endswap_int64_t_array (int64_t *ptr, int len) +{ unsigned char *ucptr, temp ; + + ucptr = (unsigned char *) ptr ; + ucptr += 8 * len ; + while (--len >= 0) + { ucptr -= 8 ; + + temp = ucptr [0] ; + ucptr [0] = ucptr [7] ; + ucptr [7] = temp ; + + temp = ucptr [1] ; + ucptr [1] = ucptr [6] ; + ucptr [6] = temp ; + + temp = ucptr [2] ; + ucptr [2] = ucptr [5] ; + ucptr [5] = temp ; + + temp = ucptr [3] ; + ucptr [3] = ucptr [4] ; + ucptr [4] = temp ; + } ; +} /* endswap_int64_t_array */ + +static inline void +endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len) +{ const unsigned char *psrc ; + unsigned char *pdest ; + + if (dest == src) + { endswap_int64_t_array (dest, len) ; + return ; + } ; + + psrc = ((const unsigned char *) src) + 8 * len ; + pdest = ((unsigned char *) dest) + 8 * len ; + while (--len >= 0) + { psrc -= 8 ; + pdest -= 8 ; + + pdest [0] = psrc [7] ; + pdest [2] = psrc [5] ; + pdest [4] = psrc [3] ; + pdest [6] = psrc [1] ; + pdest [7] = psrc [0] ; + pdest [1] = psrc [6] ; + pdest [3] = psrc [4] ; + pdest [5] = psrc [2] ; + } ; +} /* endswap_int64_t_copy */ + +#endif + +/* A couple of wrapper functions. */ + +static inline void +endswap_float_array (float *ptr, int len) +{ endswap_int_array ((void *) ptr, len) ; +} /* endswap_float_array */ + +static inline void +endswap_double_array (double *ptr, int len) +{ endswap_int64_t_array ((void *) ptr, len) ; +} /* endswap_double_array */ + +static inline void +endswap_float_copy (float *dest, const float *src, int len) +{ endswap_int_copy ((int *) dest, (const int *) src, len) ; +} /* endswap_float_copy */ + +static inline void +endswap_double_copy (double *dest, const double *src, int len) +{ endswap_int64_t_copy ((int64_t *) dest, (const int64_t *) src, len) ; +} /* endswap_double_copy */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: f0c5cd54-42d3-4237-90ec-11fe24995de7 +*/ diff --git a/nylsf/sndfile.c b/nylsf/sndfile.c new file mode 100644 index 0000000..1e5fa63 --- /dev/null +++ b/nylsf/sndfile.c @@ -0,0 +1,2707 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#define SNDFILE_MAGICK 0x1234C0DE + +typedef struct +{ int error ; + const char *str ; +} ErrorStruct ; + +static +ErrorStruct SndfileErrors [] = +{ + /* Public error values and their associated strings. */ + { SF_ERR_NO_ERROR , "No Error." }, + { SF_ERR_UNRECOGNISED_FORMAT , "File opened for read. Format not recognised." }, + { SF_ERR_SYSTEM , "System error." /* Often replaced. */ }, + { SF_ERR_MALFORMED_FILE , "Supported file format but file is malformed." }, + { SF_ERR_UNSUPPORTED_ENCODING , "Supported file format but unsupported encoding." }, + + /* Private error values and their associated strings. */ + { SFE_BAD_FILE , "File does not exist or is not a regular file (possibly a pipe?)." }, + { SFE_BAD_FILE_READ , "File exists but no data could be read." }, + { SFE_OPEN_FAILED , "Could not open file." }, + { SFE_BAD_SNDFILE_PTR , "Not a valid SNDFILE* pointer." }, + { SFE_BAD_SF_INFO_PTR , "NULL SF_INFO pointer passed to libsndfile." }, + { SFE_BAD_SF_INCOMPLETE , "SF_PRIVATE struct incomplete and end of header parsing." }, + { SFE_BAD_FILE_PTR , "Bad FILE pointer." }, + { SFE_BAD_INT_PTR , "Internal error, Bad pointer." }, + { SFE_BAD_STAT_SIZE , "Error : software was misconfigured at compile time (sizeof statbuf.st_size)." }, + + { SFE_MALLOC_FAILED , "Internal malloc () failed." }, + { SFE_UNIMPLEMENTED , "File contains data in an unimplemented format." }, + { SFE_BAD_READ_ALIGN , "Attempt to read a non-integer number of channels." }, + { SFE_BAD_WRITE_ALIGN , "Attempt to write a non-integer number of channels." }, + { SFE_UNKNOWN_FORMAT , "File contains data in an unknown format." }, + { SFE_NOT_READMODE , "Read attempted on file currently open for write." }, + { SFE_NOT_WRITEMODE , "Write attempted on file currently open for read." }, + { SFE_BAD_MODE_RW , "This file format does not support read/write mode." }, + { SFE_BAD_SF_INFO , "Internal error : SF_INFO struct incomplete." }, + { SFE_BAD_OFFSET , "Error : supplied offset beyond end of file." }, + { SFE_NO_EMBED_SUPPORT , "Error : embedding not supported for this file format." }, + { SFE_NO_EMBEDDED_RDWR , "Error : cannot open embedded file read/write." }, + { SFE_NO_PIPE_WRITE , "Error : this file format does not support pipe write." }, + { SFE_BAD_RDWR_FORMAT , "Attempted to open read only format for RDWR." }, + { SFE_BAD_VIRTUAL_IO , "Error : bad pointer on SF_VIRTUAL_IO struct." }, + + { SFE_INTERLEAVE_MODE , "Attempt to write to file with non-interleaved data." }, + { SFE_INTERLEAVE_SEEK , "Bad karma in seek during interleave read operation." }, + { SFE_INTERLEAVE_READ , "Bad karma in read during interleave read operation." }, + + { SFE_INTERNAL , "Unspecified internal error." }, + { SFE_BAD_CONTROL_CMD , "Bad command passed to function sf_command()." }, + { SFE_BAD_ENDIAN , "Bad endian-ness. Try default endian-ness" }, + { SFE_CHANNEL_COUNT , "Too many channels specified." }, + + { SFE_BAD_SEEK , "Internal psf_fseek() failed." }, + { SFE_NOT_SEEKABLE , "Seek attempted on unseekable file type." }, + { SFE_AMBIGUOUS_SEEK , "Error : combination of file open mode and seek command is ambiguous." }, + { SFE_WRONG_SEEK , "Error : invalid seek parameters." }, + { SFE_SEEK_FAILED , "Error : parameters OK, but psf_seek() failed." }, + + { SFE_BAD_OPEN_MODE , "Error : bad mode parameter for file open." }, + { SFE_OPEN_PIPE_RDWR , "Error : attempt toopen a pipe in read/write mode." }, + { SFE_RDWR_POSITION , "Error on RDWR position (cryptic)." }, + { SFE_RDWR_BAD_HEADER , "Error : Cannot open file in read/write mode due to string data in header." }, + + { SFE_STR_NO_SUPPORT , "Error : File type does not support string data." }, + { SFE_STR_NOT_WRITE , "Error : Trying to set a string when file is not in write mode." }, + { SFE_STR_MAX_DATA , "Error : Maximum string data storage reached." }, + { SFE_STR_MAX_COUNT , "Error : Maximum string data count reached." }, + { SFE_STR_BAD_TYPE , "Error : Bad string data type." }, + { SFE_STR_NO_ADD_END , "Error : file type does not support strings added at end of file." }, + { SFE_STR_BAD_STRING , "Error : bad string." }, + { SFE_STR_WEIRD , "Error : Weird string error." }, + + { SFE_WAV_NO_RIFF , "Error in WAV file. No 'RIFF' chunk marker." }, + { SFE_WAV_NO_WAVE , "Error in WAV file. No 'WAVE' chunk marker." }, + { SFE_WAV_NO_FMT , "Error in WAV file. No 'fmt ' chunk marker." }, + { SFE_WAV_FMT_SHORT , "Error in WAV file. Short 'fmt ' chunk." }, + + { SFE_WAV_BAD_FACT , "Error in WAV file. 'fact' chunk out of place." }, + { SFE_WAV_BAD_PEAK , "Error in WAV file. Bad 'PEAK' chunk." }, + { SFE_WAV_PEAK_B4_FMT , "Error in WAV file. 'PEAK' chunk found before 'fmt ' chunk." }, + + { SFE_WAV_BAD_FORMAT , "Error in WAV file. Errors in 'fmt ' chunk." }, + { SFE_WAV_BAD_BLOCKALIGN , "Error in WAV file. Block alignment in 'fmt ' chunk is incorrect." }, + { SFE_WAV_NO_DATA , "Error in WAV file. No 'data' chunk marker." }, + { SFE_WAV_BAD_LIST , "Error in WAV file. Malformed LIST chunk." }, + { SFE_WAV_UNKNOWN_CHUNK , "Error in WAV file. File contains an unknown chunk marker." }, + { SFE_WAV_WVPK_DATA , "Error in WAV file. Data is in WAVPACK format." }, + + { SFE_WAV_ADPCM_NOT4BIT , "Error in ADPCM WAV file. Invalid bit width." }, + { SFE_WAV_ADPCM_CHANNELS , "Error in ADPCM WAV file. Invalid number of channels." }, + { SFE_WAV_GSM610_FORMAT , "Error in GSM610 WAV file. Invalid format chunk." }, + + { SFE_AIFF_NO_FORM , "Error in AIFF file, bad 'FORM' marker." }, + { SFE_AIFF_AIFF_NO_FORM , "Error in AIFF file, 'AIFF' marker without 'FORM'." }, + { SFE_AIFF_COMM_NO_FORM , "Error in AIFF file, 'COMM' marker without 'FORM'." }, + { SFE_AIFF_SSND_NO_COMM , "Error in AIFF file, 'SSND' marker without 'COMM'." }, + { SFE_AIFF_UNKNOWN_CHUNK , "Error in AIFF file, unknown chunk." }, + { SFE_AIFF_COMM_CHUNK_SIZE, "Error in AIFF file, bad 'COMM' chunk size." }, + { SFE_AIFF_BAD_COMM_CHUNK , "Error in AIFF file, bad 'COMM' chunk." }, + { SFE_AIFF_PEAK_B4_COMM , "Error in AIFF file. 'PEAK' chunk found before 'COMM' chunk." }, + { SFE_AIFF_BAD_PEAK , "Error in AIFF file. Bad 'PEAK' chunk." }, + { SFE_AIFF_NO_SSND , "Error in AIFF file, bad 'SSND' chunk." }, + { SFE_AIFF_NO_DATA , "Error in AIFF file, no sound data." }, + { SFE_AIFF_RW_SSND_NOT_LAST, "Error in AIFF file, RDWR only possible if SSND chunk at end of file." }, + + { SFE_AU_UNKNOWN_FORMAT , "Error in AU file, unknown format." }, + { SFE_AU_NO_DOTSND , "Error in AU file, missing '.snd' or 'dns.' marker." }, + { SFE_AU_EMBED_BAD_LEN , "Embedded AU file with unknown length." }, + + { SFE_RAW_READ_BAD_SPEC , "Error while opening RAW file for read. Must specify format and channels.\n" + "Possibly trying to open unsupported format." + }, + { SFE_RAW_BAD_BITWIDTH , "Error. RAW file bitwidth must be a multiple of 8." }, + { SFE_RAW_BAD_FORMAT , "Error. Bad format field in SF_INFO struct when openning a RAW file for read." }, + + { SFE_PAF_NO_MARKER , "Error in PAF file, no marker." }, + { SFE_PAF_VERSION , "Error in PAF file, bad version." }, + { SFE_PAF_UNKNOWN_FORMAT , "Error in PAF file, unknown format." }, + { SFE_PAF_SHORT_HEADER , "Error in PAF file. File shorter than minimal header." }, + + { SFE_SVX_NO_FORM , "Error in 8SVX / 16SV file, no 'FORM' marker." }, + { SFE_SVX_NO_BODY , "Error in 8SVX / 16SV file, no 'BODY' marker." }, + { SFE_SVX_NO_DATA , "Error in 8SVX / 16SV file, no sound data." }, + { SFE_SVX_BAD_COMP , "Error in 8SVX / 16SV file, unsupported compression format." }, + { SFE_SVX_BAD_NAME_LENGTH , "Error in 8SVX / 16SV file, NAME chunk too long." }, + + { SFE_NIST_BAD_HEADER , "Error in NIST file, bad header." }, + { SFE_NIST_CRLF_CONVERISON, "Error : NIST file damaged by Windows CR -> CRLF conversion process." }, + { SFE_NIST_BAD_ENCODING , "Error in NIST file, unsupported compression format." }, + + { SFE_VOC_NO_CREATIVE , "Error in VOC file, no 'Creative Voice File' marker." }, + { SFE_VOC_BAD_FORMAT , "Error in VOC file, bad format." }, + { SFE_VOC_BAD_VERSION , "Error in VOC file, bad version number." }, + { SFE_VOC_BAD_MARKER , "Error in VOC file, bad marker in file." }, + { SFE_VOC_BAD_SECTIONS , "Error in VOC file, incompatible VOC sections." }, + { SFE_VOC_MULTI_SAMPLERATE, "Error in VOC file, more than one sample rate defined." }, + { SFE_VOC_MULTI_SECTION , "Unimplemented VOC file feature, file contains multiple sound sections." }, + { SFE_VOC_MULTI_PARAM , "Error in VOC file, file contains multiple bit or channel widths." }, + { SFE_VOC_SECTION_COUNT , "Error in VOC file, too many sections." }, + { SFE_VOC_NO_PIPE , "Error : not able to operate on VOC files over a pipe." }, + + { SFE_IRCAM_NO_MARKER , "Error in IRCAM file, bad IRCAM marker." }, + { SFE_IRCAM_BAD_CHANNELS , "Error in IRCAM file, bad channel count." }, + { SFE_IRCAM_UNKNOWN_FORMAT, "Error in IRCAM file, unknown encoding format." }, + + { SFE_W64_64_BIT , "Error in W64 file, file contains 64 bit offset." }, + + { SFE_W64_NO_RIFF , "Error in W64 file. No 'riff' chunk marker." }, + { SFE_W64_NO_WAVE , "Error in W64 file. No 'wave' chunk marker." }, + { SFE_W64_NO_FMT , "Error in W64 file. No 'fmt ' chunk marker." }, + { SFE_W64_NO_DATA , "Error in W64 file. No 'data' chunk marker." }, + + { SFE_W64_FMT_SHORT , "Error in W64 file. Short 'fmt ' chunk." }, + { SFE_W64_FMT_TOO_BIG , "Error in W64 file. 'fmt ' chunk too large." }, + + { SFE_W64_ADPCM_NOT4BIT , "Error in ADPCM W64 file. Invalid bit width." }, + { SFE_W64_ADPCM_CHANNELS , "Error in ADPCM W64 file. Invalid number of channels." }, + { SFE_W64_GSM610_FORMAT , "Error in GSM610 W64 file. Invalid format chunk." }, + + { SFE_MAT4_BAD_NAME , "Error in MAT4 file. No variable name." }, + { SFE_MAT4_NO_SAMPLERATE , "Error in MAT4 file. No sample rate." }, + { SFE_MAT4_ZERO_CHANNELS , "Error in MAT4 file. Channel count is zero." }, + + { SFE_MAT5_BAD_ENDIAN , "Error in MAT5 file. Not able to determine endian-ness." }, + { SFE_MAT5_NO_BLOCK , "Error in MAT5 file. Bad block structure." }, + { SFE_MAT5_SAMPLE_RATE , "Error in MAT5 file. Not able to determine sample rate." }, + { SFE_MAT5_ZERO_CHANNELS , "Error in MAT5 file. Channel count is zero." }, + + { SFE_PVF_NO_PVF1 , "Error in PVF file. No PVF1 marker." }, + { SFE_PVF_BAD_HEADER , "Error in PVF file. Bad header." }, + { SFE_PVF_BAD_BITWIDTH , "Error in PVF file. Bad bit width." }, + + { SFE_XI_BAD_HEADER , "Error in XI file. Bad header." }, + { SFE_XI_EXCESS_SAMPLES , "Error in XI file. Excess samples in file." }, + { SFE_XI_NO_PIPE , "Error : not able to operate on XI files over a pipe." }, + + { SFE_HTK_NO_PIPE , "Error : not able to operate on HTK files over a pipe." }, + + { SFE_SDS_NOT_SDS , "Error : not an SDS file." }, + { SFE_SDS_BAD_BIT_WIDTH , "Error : bad bit width for SDS file." }, + + { SFE_SD2_FD_DISALLOWED , "Error : cannot open SD2 file without a file name." }, + { SFE_SD2_BAD_DATA_OFFSET , "Error : bad data offset." }, + { SFE_SD2_BAD_MAP_OFFSET , "Error : bad map offset." }, + { SFE_SD2_BAD_DATA_LENGTH , "Error : bad data length." }, + { SFE_SD2_BAD_MAP_LENGTH , "Error : bad map length." }, + { SFE_SD2_BAD_RSRC , "Error : bad resource fork." }, + { SFE_SD2_BAD_SAMPLE_SIZE , "Error : bad sample size." }, + + { SFE_FLAC_BAD_HEADER , "Error : bad flac header." }, + { SFE_FLAC_NEW_DECODER , "Error : problem while creating flac decoder." }, + { SFE_FLAC_INIT_DECODER , "Error : problem while initialization of the flac decoder." }, + { SFE_FLAC_LOST_SYNC , "Error : flac decoder lost sync." }, + { SFE_FLAC_BAD_SAMPLE_RATE, "Error : flac does not support this sample rate." }, + { SFE_FLAC_UNKNOWN_ERROR , "Error : unknown error in flac decoder." }, + + { SFE_DWVW_BAD_BITWIDTH , "Error : Bad bit width for DWVW encoding. Must be 12, 16 or 24." }, + { SFE_G72X_NOT_MONO , "Error : G72x encoding does not support more than 1 channel." }, + + { SFE_MAX_ERROR , "Maximum error number." }, + { SFE_MAX_ERROR + 1 , NULL } +} ; + +/*------------------------------------------------------------------------------ +*/ + +static int format_from_extension (SF_PRIVATE *psf) ; +static int guess_file_type (SF_PRIVATE *psf) ; +static int validate_sfinfo (SF_INFO *sfinfo) ; +static int validate_psf (SF_PRIVATE *psf) ; +static void save_header_info (SF_PRIVATE *psf) ; +static void copy_filename (SF_PRIVATE *psf, const char *path) ; +static int psf_close (SF_PRIVATE *psf) ; +static int psf_open_file (SF_PRIVATE *psf, int mode, SF_INFO *sfinfo) ; + +static int try_resource_fork (SF_PRIVATE * psf, int mode) ; + +/*------------------------------------------------------------------------------ +** Private (static) variables. +*/ + +static int sf_errno = 0 ; +static char sf_logbuffer [SF_BUFFER_LEN] = { 0 } ; +static char sf_syserr [SF_SYSERR_LEN] = { 0 } ; + +/*------------------------------------------------------------------------------ +*/ + +#define VALIDATE_SNDFILE_AND_ASSIGN_PSF(a,b,c) \ + { if ((a) == NULL) \ + { sf_errno = SFE_BAD_SNDFILE_PTR ; \ + return 0 ; \ + } ; \ + (b) = (SF_PRIVATE*) (a) ; \ + if ((b)->virtual_io == SF_FALSE && \ + psf_file_valid (b) == 0) \ + { (b)->error = SFE_BAD_FILE_PTR ; \ + return 0 ; \ + } ; \ + if ((b)->Magick != SNDFILE_MAGICK) \ + { (b)->error = SFE_BAD_SNDFILE_PTR ; \ + return 0 ; \ + } ; \ + if (c) (b)->error = 0 ; \ + } + +/*------------------------------------------------------------------------------ +** Public functions. +*/ + +SNDFILE* +sf_open (const char *path, int mode, SF_INFO *sfinfo) +{ SF_PRIVATE *psf ; + int error = 0 ; + + if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL) + { sf_errno = SFE_MALLOC_FAILED ; + return NULL ; + } ; + + memset (psf, 0, sizeof (SF_PRIVATE)) ; + psf_init_files (psf) ; + + psf_log_printf (psf, "File : %s\n", path) ; + + copy_filename (psf, path) ; + + if (strcmp (path, "-") == 0) + error = psf_set_stdio (psf, mode) ; + else + error = psf_fopen (psf, path, mode) ; + + if (error == 0) + error = psf_open_file (psf, mode, sfinfo) ; + + if (error) + { sf_errno = error ; + if (error == SFE_SYSTEM) + LSF_SNPRINTF (sf_syserr, sizeof (sf_syserr), "%s", psf->syserr) ; + LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; + psf_close (psf) ; + return NULL ; + } ; + + memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; + + return (SNDFILE*) psf ; +} /* sf_open */ + +SNDFILE* +sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) +{ SF_PRIVATE *psf ; + int error ; + + if ((sfinfo->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) + { sf_errno = SFE_SD2_FD_DISALLOWED ; + return NULL ; + } ; + + if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL) + { sf_errno = SFE_MALLOC_FAILED ; + return NULL ; + } ; + + psf_init_files (psf) ; + + psf_set_file (psf, fd) ; + psf->is_pipe = psf_is_pipe (psf) ; + psf->fileoffset = psf_ftell (psf) ; + + if (! close_desc) + psf->do_not_close_descriptor = SF_TRUE ; + + error = psf_open_file (psf, mode, sfinfo) ; + + if (error) + { sf_errno = error ; + if (error == SFE_SYSTEM) + LSF_SNPRINTF (sf_syserr, sizeof (sf_syserr), "%s", psf->syserr) ; + LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; + psf_close (psf) ; + return NULL ; + } ; + + memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; + + return (SNDFILE*) psf ; +} /* sf_open_fd */ + +SNDFILE* +sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) +{ SF_PRIVATE *psf ; + int error = 0 ; + + /* Make sure we have a valid set ot virtual pointers. */ + if (sfvirtual->get_filelen == NULL || sfvirtual->seek == NULL || sfvirtual->tell == NULL) + { sf_errno = SFE_BAD_VIRTUAL_IO ; + LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "Bad vio_get_filelen / vio_seek / vio_tell in SF_VIRTUAL_IO struct.\n") ; + return NULL ; + } ; + + if ((mode == SFM_READ || mode == SFM_RDWR) && sfvirtual->read == NULL) + { sf_errno = SFE_BAD_VIRTUAL_IO ; + LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "Bad vio_read in SF_VIRTUAL_IO struct.\n") ; + return NULL ; + } ; + + if ((mode == SFM_WRITE || mode == SFM_RDWR) && sfvirtual->write == NULL) + { sf_errno = SFE_BAD_VIRTUAL_IO ; + LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "Bad vio_write in SF_VIRTUAL_IO struct.\n") ; + return NULL ; + } ; + + if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL) + { sf_errno = SFE_MALLOC_FAILED ; + return NULL ; + } ; + + psf_init_files (psf) ; + + psf->virtual_io = SF_TRUE ; + psf->vio = *sfvirtual ; + psf->vio_user_data = user_data ; + + psf->mode = mode ; + + error = psf_open_file (psf, mode, sfinfo) ; + + if (error) + { sf_errno = error ; + if (error == SFE_SYSTEM) + LSF_SNPRINTF (sf_syserr, sizeof (sf_syserr), "%s", psf->syserr) ; + LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; + psf_close (psf) ; + return NULL ; + } ; + + memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; + + return (SNDFILE*) psf ; +} /* sf_open_virtual */ + +int +sf_close (SNDFILE *sndfile) +{ SF_PRIVATE *psf ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + return psf_close (psf) ; +} /* sf_close */ + +void +sf_write_sync (SNDFILE *sndfile) +{ SF_PRIVATE *psf ; + + if ((psf = (SF_PRIVATE *) sndfile) == NULL) + return ; + + psf_fsync (psf) ; + + return ; +} /* sf_write_sync */ + +/*============================================================================== +*/ + +const char* +sf_error_number (int errnum) +{ static const char *bad_errnum = + "No error defined for this error number. This is a bug in libsndfile." ; + int k ; + + if (errnum == SFE_MAX_ERROR) + return SndfileErrors [0].str ; + + if (errnum < 0 || errnum > SFE_MAX_ERROR) + { /* This really shouldn't happen in release versions. */ + printf ("Not a valid error number (%d).\n", errnum) ; + return bad_errnum ; + } ; + + for (k = 0 ; SndfileErrors [k].str ; k++) + if (errnum == SndfileErrors [k].error) + return SndfileErrors [k].str ; + + return bad_errnum ; +} /* sf_error_number */ + +const char* +sf_strerror (SNDFILE *sndfile) +{ SF_PRIVATE *psf = NULL ; + int errnum ; + + if (sndfile == NULL) + { errnum = sf_errno ; + if (errnum == SFE_SYSTEM && sf_syserr [0]) + return sf_syserr ; + } + else + { psf = (SF_PRIVATE *) sndfile ; + + if (psf->Magick != SNDFILE_MAGICK) + return "sf_strerror : Bad magic number." ; + + errnum = psf->error ; + + if (errnum == SFE_SYSTEM && psf->syserr [0]) + return psf->syserr ; + } ; + + return sf_error_number (errnum) ; +} /* sf_strerror */ + +/*------------------------------------------------------------------------------ +*/ + +int +sf_error (SNDFILE *sndfile) +{ SF_PRIVATE *psf ; + + if (sndfile == NULL) + { if (sf_error != 0) + return sf_errno ; + return 0 ; + } ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; + + if (psf->error) + return psf->error ; + + return 0 ; +} /* sf_error */ + +/*------------------------------------------------------------------------------ +*/ + +int +sf_perror (SNDFILE *sndfile) +{ SF_PRIVATE *psf ; + int errnum ; + + if (sndfile == NULL) + { errnum = sf_errno ; + } + else + { VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; + errnum = psf->error ; + } ; + + fprintf (stderr, "%s\n", sf_error_number (errnum)) ; + return SFE_NO_ERROR ; +} /* sf_perror */ + + +/*------------------------------------------------------------------------------ +*/ + +int +sf_error_str (SNDFILE *sndfile, char *str, size_t maxlen) +{ SF_PRIVATE *psf ; + int errnum ; + + if (str == NULL) + return SFE_INTERNAL ; + + if (sndfile == NULL) + errnum = sf_errno ; + else + { VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; + errnum = psf->error ; + } ; + + LSF_SNPRINTF (str, maxlen, "%s", sf_error_number (errnum)) ; + + return SFE_NO_ERROR ; +} /* sf_error_str */ + +/*============================================================================== +*/ + +int +sf_format_check (const SF_INFO *info) +{ int subformat, endian ; + + subformat = info->format & SF_FORMAT_SUBMASK ; + endian = info->format & SF_FORMAT_ENDMASK ; + + /* This is the place where each file format can check if the suppiled + ** SF_INFO struct is valid. + ** Return 0 on failure, 1 ons success. + */ + + if (info->channels < 1 || info->channels > 256) + return 0 ; + + if (info->samplerate < 0) + return 0 ; + + switch (info->format & SF_FORMAT_TYPEMASK) + { case SF_FORMAT_WAV : + case SF_FORMAT_WAVEX : + /* WAV now allows both endian, RIFF or RIFX (little or big respectively) */ + if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if ((subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) && info->channels <= 2) + return 1 ; + if (subformat == SF_FORMAT_GSM610 && info->channels == 1) + return 1 ; + if (subformat == SF_FORMAT_G721_32 && info->channels == 1) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + break ; + + case SF_FORMAT_AIFF : + /* AIFF does allow both endian-nesses for PCM data.*/ + if (subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + /* Other encodings. Check for endian-ness. */ + if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) + return 0 ; + if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_S8) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) + return 1 ; + if ((subformat == SF_FORMAT_DWVW_12 || subformat == SF_FORMAT_DWVW_16 || + subformat == SF_FORMAT_DWVW_24) && info-> channels == 1) + return 1 ; + if (subformat == SF_FORMAT_GSM610 && info->channels == 1) + return 1 ; + if (subformat == SF_FORMAT_IMA_ADPCM && (info->channels == 1 || info->channels == 2)) + return 1 ; + break ; + + case SF_FORMAT_AU : + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + if (subformat == SF_FORMAT_G721_32 && info->channels == 1) + return 1 ; + if (subformat == SF_FORMAT_G723_24 && info->channels == 1) + return 1 ; + if (subformat == SF_FORMAT_G723_40 && info->channels == 1) + return 1 ; + break ; + + case SF_FORMAT_CAF : + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + break ; + + case SF_FORMAT_RAW : + if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + if (subformat == SF_FORMAT_ALAW || subformat == SF_FORMAT_ULAW) + return 1 ; + if ((subformat == SF_FORMAT_DWVW_12 || subformat == SF_FORMAT_DWVW_16 || + subformat == SF_FORMAT_DWVW_24) && info-> channels == 1) + return 1 ; + if (subformat == SF_FORMAT_GSM610 && info->channels == 1) + return 1 ; + if (subformat == SF_FORMAT_VOX_ADPCM && info->channels == 1) + return 1 ; + break ; + + case SF_FORMAT_PAF : + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + break ; + + case SF_FORMAT_SVX : + /* SVX currently does not support more than one channel for write. + ** Read will allow more than one channel but only allow one here. + */ + if (info->channels != 1) + return 0 ; + /* Always big endian. */ + if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) + return 0 ; + + if ((subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) && info->channels == 1) + return 1 ; + break ; + + case SF_FORMAT_NIST : + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) + return 1 ; + break ; + + case SF_FORMAT_IRCAM : + if (subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW || subformat == SF_FORMAT_FLOAT) + return 1 ; + break ; + + case SF_FORMAT_VOC : + /* VOC is strictly little endian. */ + if (endian == SF_ENDIAN_BIG || endian == SF_ENDIAN_CPU) + return 0 ; + if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) + return 1 ; + break ; + + case SF_FORMAT_W64 : + /* W64 is strictly little endian. */ + if (endian == SF_ENDIAN_BIG || endian == SF_ENDIAN_CPU) + return 0 ; + if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if ((subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) && info->channels <= 2) + return 1 ; + if (subformat == SF_FORMAT_GSM610 && info->channels == 1) + return 1 ; + if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + break ; + + case SF_FORMAT_MAT4 : + if (subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + break ; + + case SF_FORMAT_MAT5 : + if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_32) + return 1 ; + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) + return 1 ; + break ; + + case SF_FORMAT_PVF : + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_32) + return 1 ; + break ; + + case SF_FORMAT_XI : + if (info->channels != 1) + return 0 ; + if (subformat == SF_FORMAT_DPCM_8 || subformat == SF_FORMAT_DPCM_16) + return 1 ; + break ; + + case SF_FORMAT_HTK : + /* HTK is strictly big endian. */ + if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) + return 0 ; + if (info->channels != 1) + return 0 ; + if (subformat == SF_FORMAT_PCM_16) + return 1 ; + break ; + + case SF_FORMAT_SDS : + /* SDS is strictly big endian. */ + if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) + return 0 ; + if (info->channels != 1) + return 0 ; + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24) + return 1 ; + break ; + + case SF_FORMAT_AVR : + /* SDS is strictly big endian. */ + if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) + return 0 ; + if (info->channels > 2) + return 0 ; + if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) + return 1 ; + break ; + + case SF_FORMAT_FLAC : + /* FLAC can't do more than 8 channels. */ + if (info->channels > 8) + return 0 ; + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24) + return 1 ; + break ; + + case SF_FORMAT_SD2 : + /* SD2 is strictly big endian. */ + if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) + return 0 ; + if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24) + return 1 ; + break ; + + default : break ; + } ; + + return 0 ; +} /* sf_format_check */ + +/*------------------------------------------------------------------------------ +*/ + +int +sf_command (SNDFILE *sndfile, int command, void *data, int datasize) +{ SF_PRIVATE *psf = NULL ; + int old_value ; + + /* This set of commands do not need the sndfile parameter. */ + switch (command) + { case SFC_GET_LIB_VERSION : + if (data == NULL) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + if (ENABLE_EXPERIMENTAL_CODE) + LSF_SNPRINTF (data, datasize, "%s-%s-exp", PACKAGE_NAME, PACKAGE_VERSION) ; + else + LSF_SNPRINTF (data, datasize, "%s-%s", PACKAGE_NAME, PACKAGE_VERSION) ; + return strlen (data) ; + + case SFC_GET_SIMPLE_FORMAT_COUNT : + if (data == NULL || datasize != SIGNED_SIZEOF (int)) + return (sf_errno = SFE_BAD_CONTROL_CMD) ; + *((int*) data) = psf_get_format_simple_count () ; + return 0 ; + + case SFC_GET_SIMPLE_FORMAT : + if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) + return (sf_errno = SFE_BAD_CONTROL_CMD) ; + return psf_get_format_simple (data) ; + + case SFC_GET_FORMAT_MAJOR_COUNT : + if (data == NULL || datasize != SIGNED_SIZEOF (int)) + return (sf_errno = SFE_BAD_CONTROL_CMD) ; + *((int*) data) = psf_get_format_major_count () ; + return 0 ; + + case SFC_GET_FORMAT_MAJOR : + if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) + return (sf_errno = SFE_BAD_CONTROL_CMD) ; + return psf_get_format_major (data) ; + + case SFC_GET_FORMAT_SUBTYPE_COUNT : + if (data == NULL || datasize != SIGNED_SIZEOF (int)) + return (sf_errno = SFE_BAD_CONTROL_CMD) ; + *((int*) data) = psf_get_format_subtype_count () ; + return 0 ; + + case SFC_GET_FORMAT_SUBTYPE : + if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) + return (sf_errno = SFE_BAD_CONTROL_CMD) ; + return psf_get_format_subtype (data) ; + + case SFC_GET_FORMAT_INFO : + if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) + return (sf_errno = SFE_BAD_CONTROL_CMD) ; + return psf_get_format_info (data) ; + } ; + + if (sndfile == NULL && command == SFC_GET_LOG_INFO) + { if (data == NULL) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + LSF_SNPRINTF (data, datasize, "%s", sf_logbuffer) ; + return strlen (data) ; + } ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + switch (command) + { case SFC_SET_NORM_FLOAT : + old_value = psf->norm_float ; + psf->norm_float = (datasize) ? SF_TRUE : SF_FALSE ; + return old_value ; + + case SFC_SET_NORM_DOUBLE : + old_value = psf->norm_double ; + psf->norm_double = (datasize) ? SF_TRUE : SF_FALSE ; + return old_value ; + + case SFC_GET_NORM_FLOAT : + return psf->norm_float ; + + case SFC_GET_NORM_DOUBLE : + return psf->norm_double ; + + case SFC_SET_SCALE_FLOAT_INT_READ : + old_value = psf->float_int_mult ; + + psf->float_int_mult = (datasize != 0) ? SF_TRUE : SF_FALSE ; + if (psf->float_int_mult && psf->float_max < 0.0) + psf->float_max = psf_calc_signal_max (psf, SF_FALSE) ; + return old_value ; + + case SFC_SET_ADD_PEAK_CHUNK : + { int format = psf->sf.format & SF_FORMAT_TYPEMASK ; + + /* Only WAV and AIFF support the PEAK chunk. */ + if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX && format != SF_FORMAT_AIFF) + return SF_FALSE ; + + format = psf->sf.format & SF_FORMAT_SUBMASK ; + + /* Only files containg the following data types support the PEAK chunk. */ + if (format != SF_FORMAT_FLOAT && format != SF_FORMAT_DOUBLE) + return SF_FALSE ; + + } ; + /* Can only do this is in SFM_WRITE mode. */ + if (psf->mode != SFM_WRITE) + return SF_FALSE ; + /* If data has already been written this must fail. */ + if (psf->have_written) + return SF_FALSE ; + /* Everything seems OK, so set psf->has_peak and re-write header. */ + if (datasize == SF_FALSE && psf->peak_info != NULL) + { free (psf->peak_info) ; + psf->peak_info = NULL ; + } + else if (psf->peak_info == NULL) + { psf->peak_info = peak_info_calloc (psf->sf.channels) ; + psf->peak_info->peak_loc = SF_PEAK_START ; + } ; + + if (psf->write_header) + psf->write_header (psf, SF_TRUE) ; + return datasize ; + + case SFC_GET_LOG_INFO : + if (data == NULL) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + LSF_SNPRINTF (data, datasize, "%s", psf->logbuffer) ; + break ; + + case SFC_CALC_SIGNAL_MAX : + if (data == NULL || datasize != sizeof (double)) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + *((double*) data) = psf_calc_signal_max (psf, SF_FALSE) ; + break ; + + case SFC_CALC_NORM_SIGNAL_MAX : + if (data == NULL || datasize != sizeof (double)) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + *((double*) data) = psf_calc_signal_max (psf, SF_TRUE) ; + break ; + + case SFC_CALC_MAX_ALL_CHANNELS : + if (data == NULL || datasize != SIGNED_SIZEOF (double) * psf->sf.channels) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + return psf_calc_max_all_channels (psf, (double*) data, SF_FALSE) ; + + case SFC_CALC_NORM_MAX_ALL_CHANNELS : + if (data == NULL || datasize != SIGNED_SIZEOF (double) * psf->sf.channels) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + return psf_calc_max_all_channels (psf, (double*) data, SF_TRUE) ; + + case SFC_GET_SIGNAL_MAX : + if (data == NULL || datasize != sizeof (double)) + { psf->error = SFE_BAD_CONTROL_CMD ; + return SF_FALSE ; + } ; + return psf_get_signal_max (psf, (double *) data) ; + + case SFC_GET_MAX_ALL_CHANNELS : + if (data == NULL || datasize != SIGNED_SIZEOF (double) * psf->sf.channels) + { psf->error = SFE_BAD_CONTROL_CMD ; + return SF_FALSE ; + } ; + return psf_get_max_all_channels (psf, (double*) data) ; + + case SFC_UPDATE_HEADER_NOW : + if (psf->write_header) + psf->write_header (psf, SF_TRUE) ; + break ; + + case SFC_SET_UPDATE_HEADER_AUTO : + psf->auto_header = datasize ? SF_TRUE : SF_FALSE ; + return psf->auto_header ; + break ; + + case SFC_SET_ADD_DITHER_ON_WRITE : + case SFC_SET_ADD_DITHER_ON_READ : + /* + ** FIXME ! + ** These are obsolete. Just return. + ** Remove some time after version 1.0.8. + */ + break ; + + case SFC_SET_DITHER_ON_WRITE : + if (data == NULL || datasize != SIGNED_SIZEOF (SF_DITHER_INFO)) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + memcpy (&psf->write_dither, data, sizeof (psf->write_dither)) ; + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + dither_init (psf, SFM_WRITE) ; + break ; + + case SFC_SET_DITHER_ON_READ : + if (data == NULL || datasize != SIGNED_SIZEOF (SF_DITHER_INFO)) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + memcpy (&psf->read_dither, data, sizeof (psf->read_dither)) ; + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + dither_init (psf, SFM_READ) ; + break ; + + case SFC_FILE_TRUNCATE : + if (psf->mode != SFM_WRITE && psf->mode != SFM_RDWR) + return SF_TRUE ; + if (datasize != sizeof (sf_count_t)) + return SF_TRUE ; + { sf_count_t position ; + + position = *((sf_count_t*) data) ; + + if (sf_seek (sndfile, position, SEEK_SET) != position) + return SF_TRUE ; + + psf->sf.frames = position ; + + position = psf_fseek (psf, 0, SEEK_CUR) ; + + return psf_ftruncate (psf, position) ; + } ; + break ; + + case SFC_SET_RAW_START_OFFSET : + if (data == NULL || datasize != sizeof (sf_count_t)) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + + psf->dataoffset = *((sf_count_t*) data) ; + sf_seek (sndfile, 0, SEEK_CUR) ; + break ; + + case SFC_GET_EMBED_FILE_INFO : + if (data == NULL || datasize != sizeof (SF_EMBED_FILE_INFO)) + return (psf->error = SFE_BAD_CONTROL_CMD) ; + + ((SF_EMBED_FILE_INFO*) data)->offset = psf->fileoffset ; + ((SF_EMBED_FILE_INFO*) data)->length = psf->filelength ; + break ; + + /* Lite remove start */ + case SFC_TEST_IEEE_FLOAT_REPLACE : + psf->ieee_replace = (datasize) ? SF_TRUE : SF_FALSE ; + if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT) + float32_init (psf) ; + else if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_DOUBLE) + double64_init (psf) ; + else + return (psf->error = SFE_BAD_CONTROL_CMD) ; + break ; + /* Lite remove end */ + + case SFC_SET_CLIPPING : + psf->add_clipping = (datasize) ? SF_TRUE : SF_FALSE ; + return psf->add_clipping ; + + case SFC_GET_CLIPPING : + return psf->add_clipping ; + + case SFC_GET_LOOP_INFO : + if (datasize != sizeof (SF_LOOP_INFO) || data == NULL) + return SF_FALSE ; + if (psf->loop_info == NULL) + return SF_FALSE ; + memcpy (data, psf->loop_info, sizeof (SF_LOOP_INFO)) ; + return SF_TRUE ; + + case SFC_SET_BROADCAST_INFO : + { int format = psf->sf.format & SF_FORMAT_TYPEMASK ; + + /* Only WAV supports the BEXT (Broadcast) chunk. */ + if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX) + return SF_FALSE ; + } ; + + /* Can only do this is in SFM_WRITE mode. */ + if (psf->mode != SFM_WRITE) + return SF_FALSE ; + /* If data has already been written this must fail. */ + if (psf->have_written) + return SF_FALSE ; + + if (psf->broadcast_info == NULL) + psf->broadcast_info = broadcast_info_alloc () ; + + broadcast_info_copy (psf->broadcast_info, data) ; + broadcast_add_coding_history (psf->broadcast_info, psf->sf.channels, psf->sf.samplerate) ; + + if (psf->write_header) + psf->write_header (psf, SF_TRUE) ; + return SF_TRUE ; + + case SFC_GET_BROADCAST_INFO : + if (datasize != sizeof (SF_BROADCAST_INFO) || data == NULL) + return SF_FALSE ; + if (psf->broadcast_info == NULL) + return SF_FALSE ; + return broadcast_info_copy (data, psf->broadcast_info) ; + + case SFC_GET_INSTRUMENT : + if (datasize != sizeof (SF_INSTRUMENT) || data == NULL) + return SF_FALSE ; + if (psf->instrument == NULL) + return SF_FALSE ; + memcpy (data, psf->instrument, sizeof (SF_INSTRUMENT)) ; + return SF_TRUE ; + + case SFC_SET_INSTRUMENT : + /* If data has already been written this must fail. */ + if (psf->have_written) + return SF_FALSE ; + if (datasize != sizeof (SF_INSTRUMENT) || data == NULL) + return SF_FALSE ; + if (psf->instrument == NULL && (psf->instrument = psf_instrument_alloc ()) == NULL) + { psf->error = SFE_MALLOC_FAILED ; + return SF_FALSE ; + } ; + memcpy (psf->instrument, data, sizeof (SF_INSTRUMENT)) ; + return SF_TRUE ; + + default : + /* Must be a file specific command. Pass it on. */ + if (psf->command) + return psf->command (psf, command, data, datasize) ; + + psf_log_printf (psf, "*** sf_command : cmd = 0x%X\n", command) ; + return (psf->error = SFE_BAD_CONTROL_CMD) ; + } ; + + return 0 ; +} /* sf_command */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_seek (SNDFILE *sndfile, sf_count_t offset, int whence) +{ SF_PRIVATE *psf ; + sf_count_t seek_from_start = 0, retval ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (! psf->sf.seekable) + { psf->error = SFE_NOT_SEEKABLE ; + return PSF_SEEK_ERROR ; + } ; + + /* If the whence parameter has a mode ORed in, check to see that + ** it makes sense. + */ + if (((whence & SFM_MASK) == SFM_WRITE && psf->mode == SFM_READ) || + ((whence & SFM_MASK) == SFM_READ && psf->mode == SFM_WRITE)) + { psf->error = SFE_WRONG_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + /* Convert all SEEK_CUR and SEEK_END into seek_from_start to be + ** used with SEEK_SET. + */ + switch (whence) + { /* The SEEK_SET behaviour is independant of mode. */ + case SEEK_SET : + case SEEK_SET | SFM_READ : + case SEEK_SET | SFM_WRITE : + case SEEK_SET | SFM_RDWR : + seek_from_start = offset ; + break ; + + /* The SEEK_CUR is a little more tricky. */ + case SEEK_CUR : + if (offset == 0) + { if (psf->mode == SFM_READ) + return psf->read_current ; + if (psf->mode == SFM_WRITE) + return psf->write_current ; + } ; + if (psf->mode == SFM_READ) + seek_from_start = psf->read_current + offset ; + else if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + seek_from_start = psf->write_current + offset ; + else + psf->error = SFE_AMBIGUOUS_SEEK ; + break ; + + case SEEK_CUR | SFM_READ : + if (offset == 0) + return psf->read_current ; + seek_from_start = psf->read_current + offset ; + break ; + + case SEEK_CUR | SFM_WRITE : + if (offset == 0) + return psf->write_current ; + seek_from_start = psf->write_current + offset ; + break ; + + /* The SEEK_END */ + case SEEK_END : + case SEEK_END | SFM_READ : + case SEEK_END | SFM_WRITE : + seek_from_start = psf->sf.frames + offset ; + break ; + + default : + psf->error = SFE_BAD_SEEK ; + break ; + } ; + + if (psf->error) + return PSF_SEEK_ERROR ; + + if (seek_from_start < 0 || seek_from_start > psf->sf.frames) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (psf->seek) + { int new_mode = (whence & SFM_MASK) ? (whence & SFM_MASK) : psf->mode ; + + retval = psf->seek (psf, new_mode, seek_from_start) ; + + switch (new_mode) + { case SFM_READ : + psf->read_current = retval ; + break ; + case SFM_WRITE : + psf->write_current = retval ; + break ; + case SFM_RDWR : + psf->read_current = retval ; + psf->write_current = retval ; + new_mode = SFM_READ ; + break ; + } ; + + psf->last_op = new_mode ; + + return retval ; + } ; + + psf->error = SFE_AMBIGUOUS_SEEK ; + return PSF_SEEK_ERROR ; +} /* sf_seek */ + +/*------------------------------------------------------------------------------ +*/ + +const char* +sf_get_string (SNDFILE *sndfile, int str_type) +{ SF_PRIVATE *psf ; + + if ((psf = (SF_PRIVATE*) sndfile) == NULL) + return NULL ; + if (psf->Magick != SNDFILE_MAGICK) + return NULL ; + + return psf_get_string (psf, str_type) ; +} /* sf_get_string */ + +int +sf_set_string (SNDFILE *sndfile, int str_type, const char* str) +{ SF_PRIVATE *psf ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + return psf_set_string (psf, str_type, str) ; +} /* sf_get_string */ + +/*============================================================================== +*/ + +sf_count_t +sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) +{ SF_PRIVATE *psf ; + sf_count_t count ; + int bytewidth, blockwidth ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + bytewidth = (psf->bytewidth > 0) ? psf->bytewidth : 1 ; + blockwidth = (psf->blockwidth > 0) ? psf->blockwidth : 1 ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (bytes < 0 || psf->read_current >= psf->datalength) + { psf_memset (ptr, 0, bytes) ; + return 0 ; + } ; + + if (bytes % (psf->sf.channels * bytewidth)) + { psf->error = SFE_BAD_READ_ALIGN ; + return 0 ; + } ; + + count = psf_fread (ptr, 1, bytes, psf) ; + + if (count < bytes) + psf_memset (((char*) ptr) + count, 0, bytes - count) ; + + psf->read_current += count / blockwidth ; + + psf->last_op = SFM_READ ; + + return count ; +} /* sf_read_raw */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_READ_ALIGN ; + return 0 ; + } ; + + if (len <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, len * sizeof (short)) ; + return 0 ; /* End of file. */ + } ; + + if (psf->read_short == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_short (psf, ptr, len) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = len - count ; + psf_memset (ptr + count, 0, extra * sizeof (short)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count ; +} /* sf_read_short */ + +sf_count_t +sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (frames <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (short)) ; + return 0 ; /* End of file. */ + } ; + + if (psf->read_short == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_short (psf, ptr, frames * psf->sf.channels) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = frames * psf->sf.channels - count ; + psf_memset (ptr + count, 0, extra * sizeof (short)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count / psf->sf.channels ; +} /* sf_readf_short */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_READ_ALIGN ; + return 0 ; + } ; + + if (len <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, len * sizeof (int)) ; + return 0 ; + } ; + + if (psf->read_int == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_int (psf, ptr, len) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = len - count ; + psf_memset (ptr + count, 0, extra * sizeof (int)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count ; +} /* sf_read_int */ + +sf_count_t +sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (frames <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (int)) ; + return 0 ; + } ; + + if (psf->read_int == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_int (psf, ptr, frames * psf->sf.channels) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = frames * psf->sf.channels - count ; + psf_memset (ptr + count, 0, extra * sizeof (int)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count / psf->sf.channels ; +} /* sf_readf_int */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_READ_ALIGN ; + return 0 ; + } ; + + if (len <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, len * sizeof (float)) ; + return 0 ; + } ; + + if (psf->read_float == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_float (psf, ptr, len) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = len - count ; + psf_memset (ptr + count, 0, extra * sizeof (float)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count ; +} /* sf_read_float */ + +sf_count_t +sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (frames <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (float)) ; + return 0 ; + } ; + + if (psf->read_float == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_float (psf, ptr, frames * psf->sf.channels) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = frames * psf->sf.channels - count ; + psf_memset (ptr + count, 0, extra * sizeof (float)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count / psf->sf.channels ; +} /* sf_readf_float */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_READ_ALIGN ; + return 0 ; + } ; + + if (len <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, len * sizeof (double)) ; + return 0 ; + } ; + + if (psf->read_double == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_double (psf, ptr, len) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = len - count ; + psf_memset (ptr + count, 0, extra * sizeof (double)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count ; +} /* sf_read_double */ + +sf_count_t +sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count, extra ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_WRITE) + { psf->error = SFE_NOT_READMODE ; + return 0 ; + } ; + + if (frames <= 0 || psf->read_current >= psf->sf.frames) + { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (double)) ; + return 0 ; + } ; + + if (psf->read_double == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_READ) + if (psf->seek (psf, SFM_READ, psf->read_current) < 0) + return 0 ; + + count = psf->read_double (psf, ptr, frames * psf->sf.channels) ; + + if (psf->read_current + count / psf->sf.channels > psf->sf.frames) + { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; + extra = frames * psf->sf.channels - count ; + psf_memset (ptr + count, 0, extra * sizeof (double)) ; + psf->read_current = psf->sf.frames ; + } ; + + psf->read_current += count / psf->sf.channels ; + + psf->last_op = SFM_READ ; + + if (psf->read_current > psf->sf.frames) + { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; + psf->read_current = psf->sf.frames ; + } ; + + return count / psf->sf.channels ; +} /* sf_readf_double */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count ; + int bytewidth, blockwidth ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + bytewidth = (psf->bytewidth > 0) ? psf->bytewidth : 1 ; + blockwidth = (psf->blockwidth > 0) ? psf->blockwidth : 1 ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (len % (psf->sf.channels * bytewidth)) + { psf->error = SFE_BAD_WRITE_ALIGN ; + return 0 ; + } ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf_fwrite (ptr, 1, len, psf) ; + + psf->write_current += count / blockwidth ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + psf->last_op = SFM_WRITE ; + + return count ; +} /* sf_write_raw */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_WRITE_ALIGN ; + return 0 ; + } ; + + if (psf->write_short == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_short (psf, ptr, len) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count ; +} /* sf_write_short */ + +sf_count_t +sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (psf->write_short == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_short (psf, ptr, frames * psf->sf.channels) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count / psf->sf.channels ; +} /* sf_writef_short */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_WRITE_ALIGN ; + return 0 ; + } ; + + if (psf->write_int == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_int (psf, ptr, len) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count ; +} /* sf_write_int */ + +sf_count_t +sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (psf->write_int == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_int (psf, ptr, frames * psf->sf.channels) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count / psf->sf.channels ; +} /* sf_writef_int */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_WRITE_ALIGN ; + return 0 ; + } ; + + if (psf->write_float == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_float (psf, ptr, len) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count ; +} /* sf_write_float */ + +sf_count_t +sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (psf->write_float == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_float (psf, ptr, frames * psf->sf.channels) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count / psf->sf.channels ; +} /* sf_writef_float */ + +/*------------------------------------------------------------------------------ +*/ + +sf_count_t +sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t len) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (len % psf->sf.channels) + { psf->error = SFE_BAD_WRITE_ALIGN ; + return 0 ; + } ; + + if (psf->write_double == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_double (psf, ptr, len) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count ; +} /* sf_write_double */ + +sf_count_t +sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) +{ SF_PRIVATE *psf ; + sf_count_t count ; + + VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; + + if (psf->mode == SFM_READ) + { psf->error = SFE_NOT_WRITEMODE ; + return 0 ; + } ; + + if (psf->write_double == NULL || psf->seek == NULL) + { psf->error = SFE_UNIMPLEMENTED ; + return 0 ; + } ; + + if (psf->last_op != SFM_WRITE) + if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) + return 0 ; + + if (psf->have_written == SF_FALSE && psf->write_header != NULL) + psf->write_header (psf, SF_FALSE) ; + psf->have_written = SF_TRUE ; + + count = psf->write_double (psf, ptr, frames * psf->sf.channels) ; + + psf->write_current += count / psf->sf.channels ; + + psf->last_op = SFM_WRITE ; + + if (psf->auto_header && psf->write_header != NULL) + psf->write_header (psf, SF_TRUE) ; + + if (psf->write_current > psf->sf.frames) + psf->sf.frames = psf->write_current ; + + return count / psf->sf.channels ; +} /* sf_writef_double */ + +/*========================================================================= +** Private functions. +*/ + +static int +try_resource_fork (SF_PRIVATE * psf, int mode) +{ + if (psf_open_rsrc (psf, mode) != 0) + return 0 ; + + /* More checking here. */ + psf_log_printf (psf, "Resource fork : %s\n", psf->rsrcpath) ; + + return SF_FORMAT_SD2 ; +} /* try_resource_fork */ + +static int +format_from_extension (SF_PRIVATE *psf) +{ char *cptr ; + char buffer [16] ; + int format = 0 ; + + if (psf->filename == NULL) + return 0 ; + + if ((cptr = strrchr (psf->filename, '.')) == NULL) + return 0 ; + + cptr ++ ; + if (strlen (cptr) > sizeof (buffer) - 1) + return 0 ; + + strncpy (buffer, cptr, sizeof (buffer)) ; + buffer [sizeof (buffer) - 1] = 0 ; + + /* Convert everything in the buffer to lower case. */ + cptr = buffer ; + while (*cptr) + { *cptr = tolower (*cptr) ; + cptr ++ ; + } ; + + cptr = buffer ; + + if (strcmp (cptr, "au") == 0) + { psf->sf.channels = 1 ; + psf->sf.samplerate = 8000 ; + format = SF_FORMAT_RAW | SF_FORMAT_ULAW ; + } + else if (strcmp (cptr, "snd") == 0) + { psf->sf.channels = 1 ; + psf->sf.samplerate = 8000 ; + format = SF_FORMAT_RAW | SF_FORMAT_ULAW ; + } + else if (strcmp (cptr, "vox") == 0) + { psf->sf.channels = 1 ; + psf->sf.samplerate = 8000 ; + format = SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM ; + } + else if (strcmp (cptr, "gsm") == 0) + { psf->sf.channels = 1 ; + psf->sf.samplerate = 8000 ; + format = SF_FORMAT_RAW | SF_FORMAT_GSM610 ; + } + + /* For RAW files, make sure the dataoffset if set correctly. */ + if ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW) + psf->dataoffset = 0 ; + + return format ; +} /* format_from_extension */ + +static int +guess_file_type (SF_PRIVATE *psf) +{ int buffer [3], format ; + + if (psf_binheader_readf (psf, "b", &buffer, SIGNED_SIZEOF (buffer)) != SIGNED_SIZEOF (buffer)) + { psf->error = SFE_BAD_FILE_READ ; + return 0 ; + } ; + + if ((buffer [0] == MAKE_MARKER ('R', 'I', 'F', 'F') || buffer [0] == MAKE_MARKER ('R', 'I', 'F', 'X')) + && buffer [2] == MAKE_MARKER ('W', 'A', 'V', 'E')) + return SF_FORMAT_WAV ; + + if (buffer [0] == MAKE_MARKER ('F', 'O', 'R', 'M')) + { if (buffer [2] == MAKE_MARKER ('A', 'I', 'F', 'F') || buffer [2] == MAKE_MARKER ('A', 'I', 'F', 'C')) + return SF_FORMAT_AIFF ; + if (buffer [2] == MAKE_MARKER ('8', 'S', 'V', 'X') || buffer [2] == MAKE_MARKER ('1', '6', 'S', 'V')) + return SF_FORMAT_SVX ; + return 0 ; + } ; + + if (buffer [0] == MAKE_MARKER ('.', 's', 'n', 'd') || buffer [0] == MAKE_MARKER ('d', 'n', 's', '.')) + return SF_FORMAT_AU ; + + if ((buffer [0] == MAKE_MARKER ('f', 'a', 'p', ' ') || buffer [0] == MAKE_MARKER (' ', 'p', 'a', 'f'))) + return SF_FORMAT_PAF ; + + if (buffer [0] == MAKE_MARKER ('N', 'I', 'S', 'T')) + return SF_FORMAT_NIST ; + + if (buffer [0] == MAKE_MARKER ('C', 'r', 'e', 'a') && buffer [1] == MAKE_MARKER ('t', 'i', 'v', 'e')) + return SF_FORMAT_VOC ; + + if ((buffer [0] & MAKE_MARKER (0xFF, 0xFF, 0xF8, 0xFF)) == MAKE_MARKER (0x64, 0xA3, 0x00, 0x00) || + (buffer [0] & MAKE_MARKER (0xFF, 0xF8, 0xFF, 0xFF)) == MAKE_MARKER (0x00, 0x00, 0xA3, 0x64)) + return SF_FORMAT_IRCAM ; + + if (buffer [0] == MAKE_MARKER ('r', 'i', 'f', 'f')) + return SF_FORMAT_W64 ; + + if (buffer [0] == MAKE_MARKER (0, 0, 0x03, 0xE8) && buffer [1] == MAKE_MARKER (0, 0, 0, 1) && + buffer [2] == MAKE_MARKER (0, 0, 0, 1)) + return SF_FORMAT_MAT4 ; + + if (buffer [0] == MAKE_MARKER (0, 0, 0, 0) && buffer [1] == MAKE_MARKER (1, 0, 0, 0) && + buffer [2] == MAKE_MARKER (1, 0, 0, 0)) + return SF_FORMAT_MAT4 ; + + if (buffer [0] == MAKE_MARKER ('M', 'A', 'T', 'L') && buffer [1] == MAKE_MARKER ('A', 'B', ' ', '5')) + return SF_FORMAT_MAT5 ; + + if (buffer [0] == MAKE_MARKER ('P', 'V', 'F', '1')) + return SF_FORMAT_PVF ; + + if (buffer [0] == MAKE_MARKER ('E', 'x', 't', 'e') && buffer [1] == MAKE_MARKER ('n', 'd', 'e', 'd') && + buffer [2] == MAKE_MARKER (' ', 'I', 'n', 's')) + return SF_FORMAT_XI ; + + if (buffer [0] == MAKE_MARKER ('c', 'a', 'f', 'f') && buffer [2] == MAKE_MARKER ('d', 'e', 's', 'c')) + return SF_FORMAT_CAF ; + + if (ENABLE_EXPERIMENTAL_CODE && buffer [0] == MAKE_MARKER ('O', 'g', 'g', 'S')) + return SF_FORMAT_OGG ; + + if (buffer [0] == MAKE_MARKER ('A', 'L', 'a', 'w') && buffer [1] == MAKE_MARKER ('S', 'o', 'u', 'n') + && buffer [2] == MAKE_MARKER ('d', 'F', 'i', 'l')) + return SF_FORMAT_WVE ; + + if (buffer [0] == MAKE_MARKER ('D', 'i', 'a', 'm') && buffer [1] == MAKE_MARKER ('o', 'n', 'd', 'W') + && buffer [2] == MAKE_MARKER ('a', 'r', 'e', ' ')) + return SF_FORMAT_DWD ; + + if (buffer [0] == MAKE_MARKER ('L', 'M', '8', '9') || buffer [0] == MAKE_MARKER ('5', '3', 0, 0)) + return SF_FORMAT_TXW ; + + if ((buffer [0] & MAKE_MARKER (0xFF, 0xFF, 0x80, 0xFF)) == MAKE_MARKER (0xF0, 0x7E, 0, 0x01)) + return SF_FORMAT_SDS ; + + if (buffer [0] == MAKE_MARKER ('C', 'A', 'T', ' ') && buffer [2] == MAKE_MARKER ('R', 'E', 'X', '2')) + return SF_FORMAT_REX2 ; + + if (buffer [0] == MAKE_MARKER (0x30, 0x26, 0xB2, 0x75) && buffer [1] == MAKE_MARKER (0x8E, 0x66, 0xCF, 0x11)) + return 0 /*-SF_FORMAT_WMA-*/ ; + + /* HMM (Hidden Markov Model) Tool Kit. */ + if (2 * BEI2H_INT (buffer [0]) + 12 == psf->filelength && buffer [2] == MAKE_MARKER (0, 2, 0, 0)) + return SF_FORMAT_HTK ; + + if (buffer [0] == MAKE_MARKER ('f', 'L', 'a', 'C')) + return SF_FORMAT_FLAC ; + + /* Turtle Beach SMP 16-bit */ + if (buffer [0] == MAKE_MARKER ('S', 'O', 'U', 'N') && buffer [1] == MAKE_MARKER ('D', ' ', 'S', 'A')) + return 0 ; + + if (buffer [0] == MAKE_MARKER ('S', 'Y', '8', '0') || buffer [0] == MAKE_MARKER ('S', 'Y', '8', '5')) + return 0 ; + + if (buffer [0] == MAKE_MARKER ('a', 'j', 'k', 'g')) + return 0 /*-SF_FORMAT_SHN-*/ ; + + if (buffer [0] == MAKE_MARKER ('2', 'B', 'I', 'T')) + return SF_FORMAT_AVR ; + + /* This must be the second last one. */ + if (psf->filelength > 0 && (format = try_resource_fork (psf, SFM_READ)) != 0) + return format ; + + return 0 ; +} /* guess_file_type */ + + +static int +validate_sfinfo (SF_INFO *sfinfo) +{ if (sfinfo->samplerate < 1) + return 0 ; + if (sfinfo->frames < 0) + return 0 ; + if (sfinfo->channels < 1) + return 0 ; + if ((sfinfo->format & SF_FORMAT_TYPEMASK) == 0) + return 0 ; + if ((sfinfo->format & SF_FORMAT_SUBMASK) == 0) + return 0 ; + if (sfinfo->sections < 1) + return 0 ; + return 1 ; +} /* validate_sfinfo */ + +static int +validate_psf (SF_PRIVATE *psf) +{ + if (psf->datalength < 0) + { psf_log_printf (psf, "Invalid SF_PRIVATE field : datalength == %D.\n", psf->datalength) ; + return 0 ; + } ; + if (psf->dataoffset < 0) + { psf_log_printf (psf, "Invalid SF_PRIVATE field : dataoffset == %D.\n", psf->dataoffset) ; + return 0 ; + } ; + if (psf->blockwidth && psf->blockwidth != psf->sf.channels * psf->bytewidth) + { psf_log_printf (psf, "Invalid SF_PRIVATE field : channels * bytewidth == %d.\n", + psf->sf.channels * psf->bytewidth) ; + return 0 ; + } ; + return 1 ; +} /* validate_psf */ + +static void +save_header_info (SF_PRIVATE *psf) +{ LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; +} /* save_header_info */ + +static void +copy_filename (SF_PRIVATE *psf, const char *path) +{ const char *ccptr ; + char *cptr ; + + LSF_SNPRINTF (psf->filepath, sizeof (psf->filepath), "%s", path) ; + if ((ccptr = strrchr (path, '/')) || (ccptr = strrchr (path, '\\'))) + ccptr ++ ; + else + ccptr = path ; + + LSF_SNPRINTF (psf->filename, sizeof (psf->filename), "%s", ccptr) ; + + /* Now grab the directory. */ + LSF_SNPRINTF (psf->directory, sizeof (psf->directory), "%s", path) ; + if ((cptr = strrchr (psf->directory, '/')) || (cptr = strrchr (psf->directory, '\\'))) + cptr [1] = 0 ; + else + psf->directory [0] = 0 ; + + return ; +} /* copy_filename */ + +/*============================================================================== +*/ + +static int +psf_close (SF_PRIVATE *psf) +{ int error ; + + if (psf->codec_close) + error = psf->codec_close (psf) ; + if (psf->container_close) + error = psf->container_close (psf) ; + + psf_fclose (psf) ; + psf_close_rsrc (psf) ; + + if (psf->container_data) + free (psf->container_data) ; + + if (psf->codec_data) + free (psf->codec_data) ; + + if (psf->interleave) + free (psf->interleave) ; + + if (psf->dither) + free (psf->dither) ; + + if (psf->peak_info) + free (psf->peak_info) ; + + if (psf->broadcast_info) + free (psf->broadcast_info) ; + + if (psf->loop_info) + free (psf->loop_info) ; + + if (psf->instrument) + free (psf->instrument) ; + + if (psf->channel_map) + free (psf->channel_map) ; + + if (psf->format_desc) + { memset (psf->format_desc, 0, strlen (psf->format_desc)) ; + free (psf->format_desc) ; + } ; + + memset (psf, 0, sizeof (SF_PRIVATE)) ; + free (psf) ; + + return 0 ; +} /* psf_close */ + +static int +psf_open_file (SF_PRIVATE *psf, int mode, SF_INFO *sfinfo) +{ int error, format ; + + if (mode != SFM_READ && mode != SFM_WRITE && mode != SFM_RDWR) + return SFE_BAD_OPEN_MODE ; + + if (sfinfo == NULL) + return SFE_BAD_SF_INFO_PTR ; + + /* Zero out these fields. */ + sfinfo->frames = 0 ; + sfinfo->sections = 0 ; + sfinfo->seekable = 0 ; + + if (mode == SFM_READ) + { if ((sfinfo->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW) + { if (sf_format_check (sfinfo) == 0) + return SFE_RAW_BAD_FORMAT ; + } + else + memset (sfinfo, 0, sizeof (SF_INFO)) ; + } ; + + sf_errno = error = 0 ; + sf_logbuffer [0] = 0 ; + + memcpy (&(psf->sf), sfinfo, sizeof (SF_INFO)) ; + + psf->Magick = SNDFILE_MAGICK ; + psf->norm_float = SF_TRUE ; + psf->norm_double = SF_TRUE ; + psf->mode = mode ; + psf->dataoffset = -1 ; + psf->datalength = -1 ; + psf->read_current = -1 ; + psf->write_current = -1 ; + psf->auto_header = SF_FALSE ; + psf->rwf_endian = SF_ENDIAN_LITTLE ; + psf->seek = psf_default_seek ; + psf->float_int_mult = 0 ; + psf->float_max = -1.0 ; + + psf->sf.sections = 1 ; + + psf->is_pipe = psf_is_pipe (psf) ; + + if (psf->is_pipe) + { psf->sf.seekable = SF_FALSE ; + psf->filelength = SF_COUNT_MAX ; + } + else + { psf->sf.seekable = SF_TRUE ; + + /* File is open, so get the length. */ + psf->filelength = psf_get_filelen (psf) ; + } ; + + if (psf->fileoffset > 0) + { switch (psf->mode) + { case SFM_READ : + if (psf->filelength < 44) + { psf_log_printf (psf, "Short filelength: %D (fileoffset: %D)\n", psf->filelength, psf->fileoffset) ; + return SFE_BAD_OFFSET ; + } ; + break ; + + case SFM_WRITE : + psf->fileoffset = 0 ; + psf_fseek (psf, 0, SEEK_END) ; + psf->fileoffset = psf_ftell (psf) ; + break ; + + case SFM_RDWR : + return SFE_NO_EMBEDDED_RDWR ; + } ; + + psf_log_printf (psf, "Embedded file offset : %D\n", psf->fileoffset) ; + } ; + + if (psf->filelength == SF_COUNT_MAX) + psf_log_printf (psf, "Length : unknown\n") ; + else + psf_log_printf (psf, "Length : %D\n", psf->filelength) ; + + if (mode == SFM_WRITE || (mode == SFM_RDWR && psf->filelength == 0)) + { /* If the file is being opened for write or RDWR and the file is currently + ** empty, then the SF_INFO struct must contain valid data. + */ + if (sf_format_check (&(psf->sf)) == 0) + return SFE_BAD_OPEN_FORMAT ; + } + else if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW) + { /* If type RAW has not been specified then need to figure out file type. */ + psf->sf.format = guess_file_type (psf) ; + + if (psf->sf.format == 0) + psf->sf.format = format_from_extension (psf) ; + } ; + + /* Prevent unnecessary seeks */ + psf->last_op = psf->mode ; + + /* Set bytewidth if known. */ + switch (psf->sf.format & SF_FORMAT_SUBMASK) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_U8 : + case SF_FORMAT_ULAW : + case SF_FORMAT_ALAW : + case SF_FORMAT_DPCM_8 : + psf->bytewidth = 1 ; + break ; + + case SF_FORMAT_PCM_16 : + case SF_FORMAT_DPCM_16 : + psf->bytewidth = 2 ; + break ; + + case SF_FORMAT_PCM_24 : + psf->bytewidth = 3 ; + break ; + + case SF_FORMAT_PCM_32 : + case SF_FORMAT_FLOAT : + psf->bytewidth = 4 ; + break ; + + case SF_FORMAT_DOUBLE : + psf->bytewidth = 8 ; + break ; + } ; + + /* Call the initialisation function for the relevant file type. */ + switch (psf->sf.format & SF_FORMAT_TYPEMASK) + { case SF_FORMAT_WAV : + case SF_FORMAT_WAVEX : + error = wav_open (psf) ; + break ; + + case SF_FORMAT_AIFF : + error = aiff_open (psf) ; + break ; + + case SF_FORMAT_AU : + error = au_open (psf) ; + break ; + + case SF_FORMAT_RAW : + error = raw_open (psf) ; + break ; + + case SF_FORMAT_W64 : + error = w64_open (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_PAF : + error = paf_open (psf) ; + break ; + + case SF_FORMAT_SVX : + error = svx_open (psf) ; + break ; + + case SF_FORMAT_NIST : + error = nist_open (psf) ; + break ; + + case SF_FORMAT_IRCAM : + error = ircam_open (psf) ; + break ; + + case SF_FORMAT_VOC : + error = voc_open (psf) ; + break ; + + case SF_FORMAT_SDS : + error = sds_open (psf) ; + break ; + + case SF_FORMAT_OGG : + error = ogg_open (psf) ; + break ; + + case SF_FORMAT_TXW : + error = txw_open (psf) ; + break ; + + case SF_FORMAT_WVE : + error = wve_open (psf) ; + break ; + + case SF_FORMAT_DWD : + error = dwd_open (psf) ; + break ; + + case SF_FORMAT_MAT4 : + error = mat4_open (psf) ; + break ; + + case SF_FORMAT_MAT5 : + error = mat5_open (psf) ; + break ; + + case SF_FORMAT_PVF : + error = pvf_open (psf) ; + break ; + + case SF_FORMAT_XI : + error = xi_open (psf) ; + break ; + + case SF_FORMAT_HTK : + error = htk_open (psf) ; + break ; + + case SF_FORMAT_SD2 : + error = sd2_open (psf) ; + break ; + + case SF_FORMAT_REX2 : + error = rx2_open (psf) ; + break ; + + case SF_FORMAT_AVR : + error = avr_open (psf) ; + break ; + + case SF_FORMAT_FLAC : + error = flac_open (psf) ; + break ; + + case SF_FORMAT_CAF : + error = caf_open (psf) ; + break ; + + /* Lite remove end */ + + default : + error = SFE_UNKNOWN_FORMAT ; + } ; + + if (error) + { switch (error) + { case SF_ERR_SYSTEM : + case SF_ERR_UNSUPPORTED_ENCODING : + case SFE_UNIMPLEMENTED : + break ; + + default : + psf_log_printf (psf, "Parse error : %s\n", sf_error_number (error)) ; + error = SF_ERR_MALFORMED_FILE ; + } ; + + return error ; + } ; + + /* For now, check whether embedding is supported. */ + format = psf->sf.format & SF_FORMAT_TYPEMASK ; + if (psf->fileoffset > 0 && + (format != SF_FORMAT_WAV) && (format != SF_FORMAT_WAVEX) && + (format != SF_FORMAT_AIFF) && (format != SF_FORMAT_AU) + ) + return SFE_NO_EMBED_SUPPORT ; + + if (psf->fileoffset > 0) + psf_log_printf (psf, "Embedded file length : %D\n", psf->filelength) ; + + if (mode == SFM_RDWR && sf_format_check (&(psf->sf)) == 0) + return SFE_BAD_RDWR_FORMAT ; + + if (validate_sfinfo (&(psf->sf)) == 0) + { psf_log_SF_INFO (psf) ; + save_header_info (psf) ; + return SFE_BAD_SF_INFO ; + } ; + + if (validate_psf (psf) == 0) + { save_header_info (psf) ; + return SFE_INTERNAL ; + } ; + + psf->read_current = 0 ; + psf->write_current = (psf->mode == SFM_RDWR) ? psf->sf.frames : 0 ; + + memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; + + return 0 ; +} /* psf_open_file */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: cd4f9e91-a8ec-4154-9bf6-fe4b8c69a615 +*/ diff --git a/nylsf/sndfile.h b/nylsf/sndfile.h new file mode 100644 index 0000000..bc30e64 --- /dev/null +++ b/nylsf/sndfile.h @@ -0,0 +1,562 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** sndfile.h -- system-wide definitions +** +** API documentation is in the doc/ directory of the source code tarball +** and at http://www.mega-nerd.com/libsndfile/api.html. +*/ + +#ifndef SNDFILE_H +#define SNDFILE_H + +/* This is the version 1.0.X header file. */ +#define SNDFILE_1 + +#include + +/* For the Metrowerks CodeWarrior Pro Compiler (mainly MacOS) */ + +#if (defined (__MWERKS__)) +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* The following file types can be read and written. +** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise +** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and +** SF_FORMAT_SUBMASK can be used to separate the major and minor file +** types. +*/ + +enum +{ /* Major formats. */ + SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */ + SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ + SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ + SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ + SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ + SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ + SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ + SF_FORMAT_VOC = 0x080000, /* VOC files. */ + SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ + SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ + SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ + SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ + SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ + SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ + SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ + SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ + SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ + SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ + SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ + SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ + SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ + + /* Subtypes from here on. */ + + SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ + SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ + SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ + SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ + + SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ + + SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ + SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ + + SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ + SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ + SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ + SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ + + SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ + SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ + + SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ + SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ + SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ + + SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ + + SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ + SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ + + /* Endian-ness options. */ + + SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ + SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ + SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ + SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ + + SF_FORMAT_SUBMASK = 0x0000FFFF, + SF_FORMAT_TYPEMASK = 0x0FFF0000, + SF_FORMAT_ENDMASK = 0x30000000 +} ; + +/* +** The following are the valid command numbers for the sf_command() +** interface. The use of these commands is documented in the file +** command.html in the doc directory of the source code distribution. +*/ + +enum +{ SFC_GET_LIB_VERSION = 0x1000, + SFC_GET_LOG_INFO = 0x1001, + + SFC_GET_NORM_DOUBLE = 0x1010, + SFC_GET_NORM_FLOAT = 0x1011, + SFC_SET_NORM_DOUBLE = 0x1012, + SFC_SET_NORM_FLOAT = 0x1013, + SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, + + SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, + SFC_GET_SIMPLE_FORMAT = 0x1021, + + SFC_GET_FORMAT_INFO = 0x1028, + + SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, + SFC_GET_FORMAT_MAJOR = 0x1031, + SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, + SFC_GET_FORMAT_SUBTYPE = 0x1033, + + SFC_CALC_SIGNAL_MAX = 0x1040, + SFC_CALC_NORM_SIGNAL_MAX = 0x1041, + SFC_CALC_MAX_ALL_CHANNELS = 0x1042, + SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, + SFC_GET_SIGNAL_MAX = 0x1044, + SFC_GET_MAX_ALL_CHANNELS = 0x1045, + + SFC_SET_ADD_PEAK_CHUNK = 0x1050, + + SFC_UPDATE_HEADER_NOW = 0x1060, + SFC_SET_UPDATE_HEADER_AUTO = 0x1061, + + SFC_FILE_TRUNCATE = 0x1080, + + SFC_SET_RAW_START_OFFSET = 0x1090, + + SFC_SET_DITHER_ON_WRITE = 0x10A0, + SFC_SET_DITHER_ON_READ = 0x10A1, + + SFC_GET_DITHER_INFO_COUNT = 0x10A2, + SFC_GET_DITHER_INFO = 0x10A3, + + SFC_GET_EMBED_FILE_INFO = 0x10B0, + + SFC_SET_CLIPPING = 0x10C0, + SFC_GET_CLIPPING = 0x10C1, + + SFC_GET_INSTRUMENT = 0x10D0, + SFC_SET_INSTRUMENT = 0x10D1, + + SFC_GET_LOOP_INFO = 0x10E0, + + SFC_GET_BROADCAST_INFO = 0x10F0, + SFC_SET_BROADCAST_INFO = 0x10F1, + + /* Following commands for testing only. */ + SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, + + /* + ** SFC_SET_ADD_* values are deprecated and will disappear at some + ** time in the future. They are guaranteed to be here up to and + ** including version 1.0.8 to avoid breakage of existng software. + ** They currently do nothing and will continue to do nothing. + */ + SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, + SFC_SET_ADD_DITHER_ON_READ = 0x1071 +} ; + + +/* +** String types that can be set and read from files. Not all file types +** support this and even the file types which support one, may not support +** all string types. +*/ + +enum +{ SF_STR_TITLE = 0x01, + SF_STR_COPYRIGHT = 0x02, + SF_STR_SOFTWARE = 0x03, + SF_STR_ARTIST = 0x04, + SF_STR_COMMENT = 0x05, + SF_STR_DATE = 0x06 +} ; + +/* +** Use the following as the start and end index when doing metadata +** transcoding. +*/ + +#define SF_STR_FIRST SF_STR_TITLE +#define SF_STR_LAST SF_STR_DATE + +enum +{ /* True and false */ + SF_FALSE = 0, + SF_TRUE = 1, + + /* Modes for opening files. */ + SFM_READ = 0x10, + SFM_WRITE = 0x20, + SFM_RDWR = 0x30 +} ; + +/* Public error values. These are guaranteed to remain unchanged for the duration +** of the library major version number. +** There are also a large number of private error numbers which are internal to +** the library which can change at any time. +*/ + +enum +{ SF_ERR_NO_ERROR = 0, + SF_ERR_UNRECOGNISED_FORMAT = 1, + SF_ERR_SYSTEM = 2, + SF_ERR_MALFORMED_FILE = 3, + SF_ERR_UNSUPPORTED_ENCODING = 4 +} ; + +/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ + +typedef struct SNDFILE_tag SNDFILE ; + +/* The following typedef is system specific and is defined when libsndfile is. +** compiled. sf_count_t can be one of loff_t (Linux), off_t (*BSD), +** off64_t (Solaris), __int64_t (Win32) etc. +*/ + +/* NOTE: changed off_t to SF_COUNT_T to support compilation with Visual C++ */ +#ifdef _MSC_VER /* microsoft compiler */ + #define SF_COUNT_T __int64 +#else + #ifndef SF_COUNT_T + #define SF_COUNT_T off_t + #endif +#endif +typedef SF_COUNT_T sf_count_t ; + +#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL + +/* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in. +** On write, the SF_INFO structure is filled in by the user and passed into +** sf_open_write (). +*/ + +struct SF_INFO +{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ + int samplerate ; + int channels ; + int format ; + int sections ; + int seekable ; +} ; + +typedef struct SF_INFO SF_INFO ; + +/* The SF_FORMAT_INFO struct is used to retrieve information about the sound +** file formats libsndfile supports using the sf_command () interface. +** +** Using this interface will allow applications to support new file formats +** and encoding types when libsndfile is upgraded, without requiring +** re-compilation of the application. +** +** Please consult the libsndfile documentation (particularly the information +** on the sf_command () interface) for examples of its use. +*/ + +typedef struct +{ int format ; + const char *name ; + const char *extension ; +} SF_FORMAT_INFO ; + +/* +** Enums and typedefs for adding dither on read and write. +** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE +** and SFC_SET_DITHER_ON_READ. +*/ + +enum +{ SFD_DEFAULT_LEVEL = 0, + SFD_CUSTOM_LEVEL = 0x40000000, + + SFD_NO_DITHER = 500, + SFD_WHITE = 501, + SFD_TRIANGULAR_PDF = 502 +} ; + +typedef struct +{ int type ; + double level ; + const char *name ; +} SF_DITHER_INFO ; + +/* Struct used to retrieve information about a file embedded within a +** larger file. See SFC_GET_EMBED_FILE_INFO. +*/ + +typedef struct +{ sf_count_t offset ; + sf_count_t length ; +} SF_EMBED_FILE_INFO ; + +/* +** Structs used to retrieve music sample information from a file. +*/ + +enum +{ /* + ** The loop mode field in SF_INSTRUMENT will be one of the following. + */ + SF_LOOP_NONE = 800, + SF_LOOP_FORWARD, + SF_LOOP_BACKWARD, + SF_LOOP_ALTERNATING +} ; + +typedef struct +{ int gain ; + char basenote, detune ; + char velocity_lo, velocity_hi ; + char key_lo, key_hi ; + int loop_count ; + + struct + { int mode ; + unsigned int start ; + unsigned int end ; + unsigned int count ; + } loops [16] ; /* make variable in a sensible way */ +} SF_INSTRUMENT ; + + + +/* Struct used to retrieve loop information from a file.*/ +typedef struct +{ + short time_sig_num ; /* any positive integer > 0 */ + short time_sig_den ; /* any positive power of 2 > 0 */ + int loop_mode ; /* see SF_LOOP enum */ + + int num_beats ; /* this is NOT the amount of quarter notes !!!*/ + /* a full bar of 4/4 is 4 beats */ + /* a full bar of 7/8 is 7 beats */ + + float bpm ; /* suggestion, as it can be calculated using other fields:*/ + /* file's lenght, file's sampleRate and our time_sig_den*/ + /* -> bpms are always the amount of _quarter notes_ per minute */ + + int root_key ; /* MIDI note, or -1 for None */ + int future [6] ; +} SF_LOOP_INFO ; + + +/* Struct used to retrieve broadcast (EBU) information from a file. +** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE. +*/ +typedef struct +{ char description [256] ; + char originator [32] ; + char originator_reference [32] ; + char origination_date [10] ; + char origination_time [8] ; + int time_reference_low ; + int time_reference_high ; + short version ; + char umid [64] ; + char reserved [190] ; + unsigned int coding_history_size ; + char coding_history [256] ; +} SF_BROADCAST_INFO ; + +typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; +typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; +typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_tell) (void *user_data) ; + +struct SF_VIRTUAL_IO +{ sf_vio_get_filelen get_filelen ; + sf_vio_seek seek ; + sf_vio_read read ; + sf_vio_write write ; + sf_vio_tell tell ; +} ; + +typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ; + +/* Open the specified file for read, write or both. On error, this will +** return a NULL pointer. To find the error number, pass a NULL SNDFILE +** to sf_perror () or sf_error_str (). +** All calls to sf_open() should be matched with a call to sf_close(). +*/ + +SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; + +/* Use the existing file descriptor to create a SNDFILE object. If close_desc +** is TRUE, the file descriptor will be closed when sf_close() is called. If +** it is FALSE, the descritor will not be closed. +** When passed a descriptor like this, the library will assume that the start +** of file header is at the current file offset. This allows sound files within +** larger container files to be read and/or written. +** On error, this will return a NULL pointer. To find the error number, pass a +** NULL SNDFILE to sf_perror () or sf_error_str (). +** All calls to sf_open_fd() should be matched with a call to sf_close(). + +*/ + +SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; + +SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; + +/* sf_error () returns a error number which can be translated to a text +** string using sf_error_number(). +*/ + +int sf_error (SNDFILE *sndfile) ; + +/* sf_strerror () returns to the caller a pointer to the current error message for +** the given SNDFILE. +*/ + +const char* sf_strerror (SNDFILE *sndfile) ; + +/* sf_error_number () allows the retrieval of the error string for each internal +** error number. +** +*/ + +const char* sf_error_number (int errnum) ; + +/* The following three error functions are deprecated but they will remain in the +** library for the forseeable future. The function sf_strerror() should be used +** in their place. +*/ + +int sf_perror (SNDFILE *sndfile) ; +int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; + + +/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ + +int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; + +/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ + +int sf_format_check (const SF_INFO *info) ; + +/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses +** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as +** stdio.h function fseek (). +** An offset of zero with whence set to SEEK_SET will position the +** read / write pointer to the first data sample. +** On success sf_seek returns the current position in (multi-channel) +** samples from the start of the file. +** Please see the libsndfile documentation for moving the read pointer +** separately from the write pointer on files open in mode SFM_RDWR. +** On error all of these functions return -1. +*/ + +sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; + +/* Functions for retrieving and setting string data within sound files. +** Not all file types support this features; AIFF and WAV do. For both +** functions, the str_type parameter must be one of the SF_STR_* values +** defined above. +** On error, sf_set_string() returns non-zero while sf_get_string() +** returns NULL. +*/ + +int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; + +const char* sf_get_string (SNDFILE *sndfile, int str_type) ; + +/* Functions for reading/writing the waveform data of a sound file. +*/ + +sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; +sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ; + +/* Functions for reading and writing the data chunk in terms of frames. +** The number of items actually read/written = frames * number of channels. +** sf_xxxx_raw read/writes the raw data bytes from/to the file +** sf_xxxx_short passes data in the native short format +** sf_xxxx_int passes data in the native int format +** sf_xxxx_float passes data in the native float format +** sf_xxxx_double passes data in the native double format +** All of these read/write function return number of frames read/written. +*/ + +sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; +sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; +sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; +sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; +sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ; + +/* Functions for reading and writing the data chunk in terms of items. +** Otherwise similar to above. +** All of these read/write function return number of items read/written. +*/ + +sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ; + +sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ; + +sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ; + +sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; +sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ; + +/* Close the SNDFILE and clean up all memory allocations associated with this +** file. +** Returns 0 on success, or an error number. +*/ + +int sf_close (SNDFILE *sndfile) ; + +/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file +** to force the writing of data to disk. If the file is opened SFM_READ +** no action is taken. +*/ + +void sf_write_sync (SNDFILE *sndfile) ; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* SNDFILE_H */ diff --git a/nylsf/strings.c b/nylsf/strings.c new file mode 100644 index 0000000..2433f9b --- /dev/null +++ b/nylsf/strings.c @@ -0,0 +1,204 @@ +/* +** Copyright (C) 2001-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "common.h" + +#define STRINGS_DEBUG 0 +#if STRINGS_DEBUG +static void hexdump (void *data, int len) ; +#endif + +int +psf_store_string (SF_PRIVATE *psf, int str_type, const char *str) +{ static char lsf_name [] = PACKAGE "-" VERSION ; + static char bracket_name [] = " (" PACKAGE "-" VERSION ")" ; + int k, str_len, len_remaining, str_flags ; + + if (str == NULL) + return SFE_STR_BAD_STRING ; + + str_len = strlen (str) ; + + /* A few extra checks for write mode. */ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if ((psf->str_flags & SF_STR_ALLOW_START) == 0) + return SFE_STR_NO_SUPPORT ; + if ((psf->str_flags & SF_STR_ALLOW_END) == 0) + return SFE_STR_NO_SUPPORT ; + /* Only allow zero length strings for software. */ + if (str_type != SF_STR_SOFTWARE && str_len == 0) + return SFE_STR_BAD_STRING ; + } ; + + /* Determine flags */ + str_flags = SF_STR_LOCATE_START ; + if (psf->have_written) + { if ((psf->str_flags & SF_STR_ALLOW_END) == 0) + return SFE_STR_NO_ADD_END ; + str_flags = SF_STR_LOCATE_END ; + } ; + + /* Find next free slot in table. */ + for (k = 0 ; k < SF_MAX_STRINGS ; k++) + if (psf->strings [k].type == 0) + break ; + + /* More sanity checking. */ + if (k >= SF_MAX_STRINGS) + return SFE_STR_MAX_COUNT ; + + if (k == 0 && psf->str_end != NULL) + { psf_log_printf (psf, "SFE_STR_WEIRD : k == 0 && psf->str_end != NULL\n") ; + return SFE_STR_WEIRD ; + } ; + + if (k != 0 && psf->str_end == NULL) + { psf_log_printf (psf, "SFE_STR_WEIRD : k != 0 && psf->str_end == NULL\n") ; + return SFE_STR_WEIRD ; + } ; + + /* Special case for the first string. */ + if (k == 0) + psf->str_end = psf->str_storage ; + + +#if STRINGS_DEBUG + psf_log_printf (psf, "str_storage : %X\n", (int) psf->str_storage) ; + psf_log_printf (psf, "str_end : %X\n", (int) psf->str_end) ; + psf_log_printf (psf, "sizeof (str_storage) : %d\n", SIGNED_SIZEOF (psf->str_storage)) ; +#endif + + len_remaining = SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage) ; + + if (len_remaining < str_len + 2) + return SFE_STR_MAX_DATA ; + + switch (str_type) + { case SF_STR_SOFTWARE : + /* In write mode, want to append libsndfile-version to string. */ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { psf->strings [k].type = str_type ; + psf->strings [k].str = psf->str_end ; + psf->strings [k].flags = str_flags ; + + memcpy (psf->str_end, str, str_len + 1) ; + psf->str_end += str_len ; + + /* + ** If the supplied string does not already contain a + ** libsndfile-X.Y.Z component, then add it. + */ + if (strstr (str, PACKAGE) == NULL && len_remaining > (int) (strlen (bracket_name) + str_len + 2)) + { if (strlen (str) == 0) + strncat (psf->str_end, lsf_name, len_remaining) ; + else + strncat (psf->str_end, bracket_name, len_remaining) ; + psf->str_end += strlen (psf->str_end) ; + } ; + + /* Plus one to catch string terminator. */ + psf->str_end += 1 ; + break ; + } ; + + /* Fall though if not write mode. */ + + case SF_STR_TITLE : + case SF_STR_COPYRIGHT : + case SF_STR_ARTIST : + case SF_STR_COMMENT : + case SF_STR_DATE : + psf->strings [k].type = str_type ; + psf->strings [k].str = psf->str_end ; + psf->strings [k].flags = str_flags ; + + /* Plus one to catch string terminator. */ + memcpy (psf->str_end, str, str_len + 1) ; + psf->str_end += str_len + 1 ; + break ; + + default : + return SFE_STR_BAD_TYPE ; + } ; + + psf->str_flags |= (psf->have_written) ? SF_STR_LOCATE_END : SF_STR_LOCATE_START ; + +#if STRINGS_DEBUG + hexdump (psf->str_storage, 300) ; +#endif + + return 0 ; +} /* psf_store_string */ + +int +psf_set_string (SF_PRIVATE *psf, int str_type, const char *str) +{ if (psf->mode == SFM_READ) + return SFE_STR_NOT_WRITE ; + + return psf_store_string (psf, str_type, str) ; +} /* psf_set_string */ + +const char* +psf_get_string (SF_PRIVATE *psf, int str_type) +{ int k ; + + for (k = 0 ; k < SF_MAX_STRINGS ; k++) + if (str_type == psf->strings [k].type) + return psf->strings [k].str ; + + return NULL ; +} /* psf_get_string */ + +#if STRINGS_DEBUG + +#include +static void +hexdump (void *data, int len) +{ unsigned char *ptr ; + int k ; + + ptr = data ; + + puts ("---------------------------------------------------------") ; + while (len >= 16) + { for (k = 0 ; k < 16 ; k++) + printf ("%02X ", ptr [k] & 0xFF) ; + printf (" ") ; + for (k = 0 ; k < 16 ; k++) + printf ("%c", isprint (ptr [k]) ? ptr [k] : '.') ; + puts ("") ; + ptr += 16 ; + len -= 16 ; + } ; +} /* hexdump */ + +#endif +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 04393aa1-9389-46fe-baf2-58a7bd544fd6 +*/ diff --git a/nylsf/svx.c b/nylsf/svx.c new file mode 100644 index 0000000..3ef461d --- /dev/null +++ b/nylsf/svx.c @@ -0,0 +1,410 @@ +/* +** Copyright (C) 1999-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + + +/*------------------------------------------------------------------------------ + * Macros to handle big/little endian issues. +*/ + +#define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M')) +#define SVX8_MARKER (MAKE_MARKER ('8', 'S', 'V', 'X')) +#define SV16_MARKER (MAKE_MARKER ('1', '6', 'S', 'V')) +#define VHDR_MARKER (MAKE_MARKER ('V', 'H', 'D', 'R')) +#define BODY_MARKER (MAKE_MARKER ('B', 'O', 'D', 'Y')) + +#define ATAK_MARKER (MAKE_MARKER ('A', 'T', 'A', 'K')) +#define RLSE_MARKER (MAKE_MARKER ('R', 'L', 'S', 'E')) + +#define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' ')) +#define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E')) +#define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H')) +#define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O')) +#define CHAN_MARKER (MAKE_MARKER ('C', 'H', 'A', 'N')) + +/*------------------------------------------------------------------------------ + * Typedefs for file chunks. +*/ + +typedef struct +{ unsigned int oneShotHiSamples, repeatHiSamples, samplesPerHiCycle ; + unsigned short samplesPerSec ; + unsigned char octave, compression ; + unsigned int volume ; +} VHDR_CHUNK ; + +enum { + HAVE_FORM = 0x01, + + HAVE_SVX = 0x02, + HAVE_VHDR = 0x04, + HAVE_BODY = 0x08 +} ; + +/*------------------------------------------------------------------------------ + * Private static functions. +*/ + +static int svx_close (SF_PRIVATE *psf) ; +static int svx_write_header (SF_PRIVATE *psf, int calc_length) ; +static int svx_read_header (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +svx_open (SF_PRIVATE *psf) +{ int error ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = svx_read_header (psf))) + return error ; + + psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */ + + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + if (psf->blockwidth) + psf->sf.frames = psf->datalength / psf->blockwidth ; + + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SVX) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + + if (psf->endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)) + return SFE_BAD_ENDIAN ; + + psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */ + + error = svx_write_header (psf, SF_FALSE) ; + if (error) + return error ; + + psf->write_header = svx_write_header ; + } ; + + psf->container_close = svx_close ; + + if ((error = pcm_init (psf))) + return error ; + + return 0 ; +} /* svx_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +svx_read_header (SF_PRIVATE *psf) +{ VHDR_CHUNK vhdr ; + unsigned int FORMsize, vhdrsize, dword, marker ; + int filetype = 0, parsestage = 0, done = 0 ; + int bytecount = 0, channels ; + + memset (&vhdr, 0, sizeof (vhdr)) ; + psf_binheader_readf (psf, "p", 0) ; + + /* Set default number of channels. Currently can't handle stereo SVX files. */ + psf->sf.channels = 1 ; + + psf->sf.format = SF_FORMAT_SVX ; + + while (! done) + { psf_binheader_readf (psf, "m", &marker) ; + switch (marker) + { case FORM_MARKER : + if (parsestage) + return SFE_SVX_NO_FORM ; + + psf_binheader_readf (psf, "E4", &FORMsize) ; + + if (FORMsize != psf->filelength - 2 * sizeof (dword)) + { dword = psf->filelength - 2 * sizeof (dword) ; + psf_log_printf (psf, "FORM : %d (should be %d)\n", FORMsize, dword) ; + FORMsize = dword ; + } + else + psf_log_printf (psf, "FORM : %d\n", FORMsize) ; + parsestage |= HAVE_FORM ; + break ; + + case SVX8_MARKER : + case SV16_MARKER : + if (! (parsestage & HAVE_FORM)) + return SFE_SVX_NO_FORM ; + filetype = marker ; + psf_log_printf (psf, " %M\n", marker) ; + parsestage |= HAVE_SVX ; + break ; + + case VHDR_MARKER : + if (! (parsestage & (HAVE_FORM | HAVE_SVX))) + return SFE_SVX_NO_FORM ; + + psf_binheader_readf (psf, "E4", &vhdrsize) ; + + psf_log_printf (psf, " VHDR : %d\n", vhdrsize) ; + + psf_binheader_readf (psf, "E4442114", &(vhdr.oneShotHiSamples), &(vhdr.repeatHiSamples), + &(vhdr.samplesPerHiCycle), &(vhdr.samplesPerSec), &(vhdr.octave), &(vhdr.compression), + &(vhdr.volume)) ; + + psf_log_printf (psf, " OneShotHiSamples : %d\n", vhdr.oneShotHiSamples) ; + psf_log_printf (psf, " RepeatHiSamples : %d\n", vhdr.repeatHiSamples) ; + psf_log_printf (psf, " samplesPerHiCycle : %d\n", vhdr.samplesPerHiCycle) ; + psf_log_printf (psf, " Sample Rate : %d\n", vhdr.samplesPerSec) ; + psf_log_printf (psf, " Octave : %d\n", vhdr.octave) ; + + psf_log_printf (psf, " Compression : %d => ", vhdr.compression) ; + + switch (vhdr.compression) + { case 0 : psf_log_printf (psf, "None.\n") ; + break ; + case 1 : psf_log_printf (psf, "Fibonacci delta\n") ; + break ; + case 2 : psf_log_printf (psf, "Exponential delta\n") ; + break ; + } ; + + psf_log_printf (psf, " Volume : %d\n", vhdr.volume) ; + + psf->sf.samplerate = vhdr.samplesPerSec ; + + if (filetype == SVX8_MARKER) + { psf->sf.format |= SF_FORMAT_PCM_S8 ; + psf->bytewidth = 1 ; + } + else if (filetype == SV16_MARKER) + { psf->sf.format |= SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + } ; + + parsestage |= HAVE_VHDR ; + break ; + + case BODY_MARKER : + if (! (parsestage & HAVE_VHDR)) + return SFE_SVX_NO_BODY ; + + psf_binheader_readf (psf, "E4", &dword) ; + psf->datalength = dword ; + + psf->dataoffset = psf_ftell (psf) ; + + if (psf->datalength > psf->filelength - psf->dataoffset) + { psf_log_printf (psf, " BODY : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ; + psf->datalength = psf->filelength - psf->dataoffset ; + } + else + psf_log_printf (psf, " BODY : %D\n", psf->datalength) ; + + parsestage |= HAVE_BODY ; + + if (! psf->sf.seekable) + break ; + + psf_fseek (psf, psf->datalength, SEEK_CUR) ; + break ; + + case NAME_MARKER : + if (! (parsestage & HAVE_SVX)) + return SFE_SVX_NO_FORM ; + + psf_binheader_readf (psf, "E4", &dword) ; + + psf_log_printf (psf, " %M : %d\n", marker, dword) ; + + if (strlen (psf->filename) != dword) + { if (dword > sizeof (psf->filename) - 1) + return SFE_SVX_BAD_NAME_LENGTH ; + + psf_binheader_readf (psf, "b", psf->filename, dword) ; + psf->filename [dword] = 0 ; + } + else + psf_binheader_readf (psf, "j", dword) ; + break ; + + case ANNO_MARKER : + if (! (parsestage & HAVE_SVX)) + return SFE_SVX_NO_FORM ; + + psf_binheader_readf (psf, "E4", &dword) ; + + psf_log_printf (psf, " %M : %d\n", marker, dword) ; + + psf_binheader_readf (psf, "j", dword) ; + break ; + + case CHAN_MARKER : + if (! (parsestage & HAVE_SVX)) + return SFE_SVX_NO_FORM ; + + psf_binheader_readf (psf, "E4", &dword) ; + + psf_log_printf (psf, " %M : %d\n", marker, dword) ; + + bytecount += psf_binheader_readf (psf, "E4", &channels) ; + psf->sf.channels = channels ; + + psf_log_printf (psf, " Channels : %d\n", channels) ; + + psf_binheader_readf (psf, "j", dword - bytecount) ; + break ; + + + case AUTH_MARKER : + case c_MARKER : + if (! (parsestage & HAVE_SVX)) + return SFE_SVX_NO_FORM ; + + psf_binheader_readf (psf, "E4", &dword) ; + + psf_log_printf (psf, " %M : %d\n", marker, dword) ; + + psf_binheader_readf (psf, "j", dword) ; + break ; + + default : + if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF) + && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) + { psf_binheader_readf (psf, "E4", &dword) ; + + psf_log_printf (psf, "%M : %d (unknown marker)\n", marker, dword) ; + + psf_binheader_readf (psf, "j", dword) ; + break ; + } ; + if ((dword = psf_ftell (psf)) & 0x03) + { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ; + + psf_binheader_readf (psf, "j", -3) ; + break ; + } ; + psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ; + done = 1 ; + } ; /* switch (marker) */ + + if (! psf->sf.seekable && (parsestage & HAVE_BODY)) + break ; + + if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (dword)) + break ; + } ; /* while (1) */ + + if (vhdr.compression) + return SFE_SVX_BAD_COMP ; + + if (psf->dataoffset <= 0) + return SFE_SVX_NO_DATA ; + + return 0 ; +} /* svx_read_header */ + +static int +svx_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + svx_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* svx_close */ + +static int +svx_write_header (SF_PRIVATE *psf, int calc_length) +{ static char annotation [] = "libsndfile by Erik de Castro Lopo\0\0\0" ; + sf_count_t current ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* FORM marker and FORM size. */ + psf_binheader_writef (psf, "Etm8", FORM_MARKER, (psf->filelength < 8) ? + psf->filelength * 0 : psf->filelength - 8) ; + + psf_binheader_writef (psf, "m", (psf->bytewidth == 1) ? SVX8_MARKER : SV16_MARKER) ; + + /* VHDR chunk. */ + psf_binheader_writef (psf, "Em4", VHDR_MARKER, sizeof (VHDR_CHUNK)) ; + /* VHDR : oneShotHiSamples, repeatHiSamples, samplesPerHiCycle */ + psf_binheader_writef (psf, "E444", psf->sf.frames, 0, 0) ; + /* VHDR : samplesPerSec, octave, compression */ + psf_binheader_writef (psf, "E211", psf->sf.samplerate, 1, 0) ; + /* VHDR : volume */ + psf_binheader_writef (psf, "E4", (psf->bytewidth == 1) ? 0xFF : 0xFFFF) ; + + /* Filename and annotation strings. */ + psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->filename, ANNO_MARKER, annotation) ; + + /* BODY marker and size. */ + psf_binheader_writef (psf, "Etm8", BODY_MARKER, (psf->datalength < 0) ? + psf->datalength * 0 : psf->datalength) ; + + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* svx_write_header */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: a80ab6fb-7d75-4d32-a6b0-0061a3f05d95 +*/ diff --git a/nylsf/test_endswap.c b/nylsf/test_endswap.c new file mode 100644 index 0000000..0217d9e --- /dev/null +++ b/nylsf/test_endswap.c @@ -0,0 +1,245 @@ +/* +** Copyright (C) 2002-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#include +#include + +#include "common.h" +#include "sfendian.h" + +#define FMT_SHORT "0x%04x\n" +#define FMT_INT "0x%08x\n" + +#if SIZEOF_INT64_T == SIZEOF_LONG +#define FMT_INT64 "0x%016lx\n" +#else +#define FMT_INT64 "0x%016llx\n" +#endif + +static void test_endswap_short (void) ; +static void test_endswap_int (void) ; +static void test_endswap_int64_t (void) ; + + +int +main (void) +{ + test_endswap_short () ; + test_endswap_int () ; + test_endswap_int64_t () ; + + return 0 ; +} /* main */ + +/*============================================================================== +** Actual test functions. +*/ + + +static void +dump_short_array (const char * name, short * data, int datalen) +{ int k ; + + printf ("%-6s : ", name) ; + for (k = 0 ; k < datalen ; k++) + printf (FMT_SHORT, data [k]) ; + putchar ('\n') ; +} /* dump_short_array */ + +static void +test_endswap_short (void) +{ short orig [4], first [4], second [4] ; + int k ; + + printf (" %-24s : ", "test_endswap_short") ; + fflush (stdout) ; + + for (k = 0 ; k < ARRAY_LEN (orig) ; k++) + orig [k] = 0x3210 + k ; + + endswap_short_copy (first, orig, ARRAY_LEN (first)) ; + endswap_short_copy (second, first, ARRAY_LEN (second)) ; + + if (memcmp (orig, first, sizeof (orig)) == 0) + { printf ("\n\nLine %d : test 1 : these two array should not be the same:\n\n", __LINE__) ; + dump_short_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_short_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + if (memcmp (orig, second, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 2 : these two array should be the same:\n\n", __LINE__) ; + dump_short_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_short_array ("second", second, ARRAY_LEN (second)) ; + exit (1) ; + } ; + + endswap_short_array (first, ARRAY_LEN (first)) ; + + if (memcmp (orig, first, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 3 : these two array should be the same:\n\n", __LINE__) ; + dump_short_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_short_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + endswap_short_copy (first, orig, ARRAY_LEN (first)) ; + endswap_short_copy (first, first, ARRAY_LEN (first)) ; + + if (memcmp (orig, first, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 4 : these two array should be the same:\n\n", __LINE__) ; + dump_short_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_short_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + puts ("ok") ; +} /* test_endswap_short */ + +static void +dump_int_array (const char * name, int * data, int datalen) +{ int k ; + + printf ("%-6s : ", name) ; + for (k = 0 ; k < datalen ; k++) + printf (FMT_INT, data [k]) ; + putchar ('\n') ; +} /* dump_int_array */ + +static void +test_endswap_int (void) +{ int orig [4], first [4], second [4] ; + int k ; + + printf (" %-24s : ", "test_endswap_int") ; + fflush (stdout) ; + + for (k = 0 ; k < ARRAY_LEN (orig) ; k++) + orig [k] = 0x76543210 + k ; + + endswap_int_copy (first, orig, ARRAY_LEN (first)) ; + endswap_int_copy (second, first, ARRAY_LEN (second)) ; + + if (memcmp (orig, first, sizeof (orig)) == 0) + { printf ("\n\nLine %d : test 1 : these two array should not be the same:\n\n", __LINE__) ; + dump_int_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + if (memcmp (orig, second, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 2 : these two array should be the same:\n\n", __LINE__) ; + dump_int_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int_array ("second", second, ARRAY_LEN (second)) ; + exit (1) ; + } ; + + endswap_int_array (first, ARRAY_LEN (first)) ; + + if (memcmp (orig, first, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 3 : these two array should be the same:\n\n", __LINE__) ; + dump_int_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + endswap_int_copy (first, orig, ARRAY_LEN (first)) ; + endswap_int_copy (first, first, ARRAY_LEN (first)) ; + + if (memcmp (orig, first, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 4 : these two array should be the same:\n\n", __LINE__) ; + dump_int_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + puts ("ok") ; +} /* test_endswap_int */ + +static void +dump_int64_t_array (const char * name, int64_t * data, int datalen) +{ int k ; + + printf ("%-6s : ", name) ; + for (k = 0 ; k < datalen ; k++) + printf (FMT_INT64, data [k]) ; + putchar ('\n') ; +} /* dump_int64_t_array */ + +static void +test_endswap_int64_t (void) +{ int64_t orig [4], first [4], second [4] ; + int k ; + + printf (" %-24s : ", "test_endswap_int64_t") ; + fflush (stdout) ; + + for (k = 0 ; k < ARRAY_LEN (orig) ; k++) + orig [k] = 0x0807050540302010LL + k ; + + endswap_int64_t_copy (first, orig, ARRAY_LEN (first)) ; + endswap_int64_t_copy (second, first, ARRAY_LEN (second)) ; + + if (memcmp (orig, first, sizeof (orig)) == 0) + { printf ("\n\nLine %d : test 1 : these two array should not be the same:\n\n", __LINE__) ; + dump_int64_t_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int64_t_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + if (memcmp (orig, second, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 2 : these two array should be the same:\n\n", __LINE__) ; + dump_int64_t_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int64_t_array ("second", second, ARRAY_LEN (second)) ; + exit (1) ; + } ; + + endswap_int64_t_array (first, ARRAY_LEN (first)) ; + + if (memcmp (orig, first, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 3 : these two array should be the same:\n\n", __LINE__) ; + dump_int64_t_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int64_t_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + endswap_int64_t_copy (first, orig, ARRAY_LEN (first)) ; + endswap_int64_t_copy (first, first, ARRAY_LEN (first)) ; + + if (memcmp (orig, first, sizeof (orig)) != 0) + { printf ("\n\nLine %d : test 4 : these two array should be the same:\n\n", __LINE__) ; + dump_int64_t_array ("orig", orig, ARRAY_LEN (orig)) ; + dump_int64_t_array ("first", first, ARRAY_LEN (first)) ; + exit (1) ; + } ; + + puts ("ok") ; +} /* test_endswap_int64_t */ + + + + diff --git a/nylsf/test_file_io.c b/nylsf/test_file_io.c new file mode 100644 index 0000000..fa7b452 --- /dev/null +++ b/nylsf/test_file_io.c @@ -0,0 +1,448 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#include +#include + +#include "common.h" + +static void make_data (int *data, int len, int seed) ; + +static void file_open_test (const char *filename) ; +static void file_read_write_test (const char *filename) ; +static void file_truncate_test (const char *filename) ; + +static void test_open_or_die (SF_PRIVATE *psf, int linenum) ; +static void test_close_or_die (SF_PRIVATE *psf, int linenum) ; + +static void test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ; +static void test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ; +static void test_equal_or_die (int *array1, int *array2, int len, int linenum) ; +static void test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum) ; + + + +int +main (void) +{ const char *filename = "file_io.dat" ; + + file_open_test (filename) ; + file_read_write_test (filename) ; + file_truncate_test (filename) ; + + unlink (filename) ; + + return 0 ; +} /* main */ + +/*============================================================================== +** Actual test functions. +*/ + +static void +file_open_test (const char *filename) +{ SF_PRIVATE sf_data, *psf ; + int error ; + + printf (" %-24s : ", "file_open_test") ; + fflush (stdout) ; + + memset (&sf_data, 0, sizeof (sf_data)) ; + psf = &sf_data ; + + /* Ensure that the file doesn't already exist. */ + if (unlink (filename) != 0 && errno != ENOENT) + { printf ("\n\nLine %d: unlink failed (%d) : %s\n\n", __LINE__, errno, strerror (errno)) ; + exit (1) ; + } ; + + strncpy (psf->filename, filename, sizeof (psf->filename)) ; + + /* Test that open for read fails if the file doesn't exist. */ + error = psf_fopen (psf, psf->filename, SFM_READ) ; + if (error == 0) + { printf ("\n\nLine %d: psf_fopen() should have failed.\n\n", __LINE__) ; + exit (1) ; + } ; + + /* Reset error to zero. */ + psf->error = SFE_NO_ERROR ; + + /* Test file open in write mode. */ + psf->mode = SFM_WRITE ; + test_open_or_die (psf, __LINE__) ; + + test_close_or_die (psf, __LINE__) ; + + unlink (psf->filename) ; + + /* Test file open in read/write mode for a non-existant file. */ + psf->mode = SFM_RDWR ; + test_open_or_die (psf, __LINE__) ; + + test_close_or_die (psf, __LINE__) ; + + /* Test file open in read/write mode for an existing file. */ + psf->mode = SFM_RDWR ; + test_open_or_die (psf, __LINE__) ; + + test_close_or_die (psf, __LINE__) ; + + unlink (psf->filename) ; + puts ("ok") ; +} /* file_open_test */ + +static void +file_read_write_test (const char *filename) +{ static int data_out [512] ; + static int data_in [512] ; + + SF_PRIVATE sf_data, *psf ; + sf_count_t retval ; + + /* + ** Open a new file and write two blocks of data to the file. After each + ** write, test that psf_get_filelen() returns the new length. + */ + + printf (" %-24s : ", "file_write_test") ; + fflush (stdout) ; + + memset (&sf_data, 0, sizeof (sf_data)) ; + psf = &sf_data ; + strncpy (psf->filename, filename, sizeof (psf->filename)) ; + + /* Test file open in write mode. */ + psf->mode = SFM_WRITE ; + test_open_or_die (psf, __LINE__) ; + + make_data (data_out, ARRAY_LEN (data_out), 1) ; + test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), sizeof (data_out), __LINE__) ; + + if ((retval = psf_get_filelen (psf)) != sizeof (data_out)) + { printf ("\n\nLine %d: file length after write is not correct (%ld should be %d).\n\n", __LINE__, (long) retval, (int) sizeof (data_out)) ; + if (retval == 0) + printf ("An fsync() may be necessary before fstat() in psf_get_filelen().\n\n") ; + exit (1) ; + } ; + + make_data (data_out, ARRAY_LEN (data_out), 2) ; + test_write_or_die (psf, data_out, ARRAY_LEN (data_out), sizeof (data_out [0]), 2 * sizeof (data_out), __LINE__) ; + + if ((retval = psf_get_filelen (psf)) != 2 * sizeof (data_out)) + { printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 2 * ((int) sizeof (data_out))) ; + exit (1) ; + } ; + + test_close_or_die (psf, __LINE__) ; + puts ("ok") ; + + /* + ** Now open the file in read mode, check the file length and check + ** that the data is correct. + */ + + printf (" %-24s : ", "file_read_test") ; + fflush (stdout) ; + + /* Test file open in write mode. */ + psf->mode = SFM_READ ; + test_open_or_die (psf, __LINE__) ; + + make_data (data_out, ARRAY_LEN (data_out), 1) ; + test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + make_data (data_out, ARRAY_LEN (data_out), 2) ; + test_read_or_die (psf, data_in, sizeof (data_in [0]), ARRAY_LEN (data_in), 2 * sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + test_close_or_die (psf, __LINE__) ; + + puts ("ok") ; + + /* + ** Open the file in read/write mode, seek around a bit and then seek to + ** the end of the file and write another block of data (3rd block). Then + ** go back and check that all three blocks are correct. + */ + + printf (" %-24s : ", "file_seek_test") ; + fflush (stdout) ; + + /* Test file open in read/write mode. */ + psf->mode = SFM_RDWR ; + test_open_or_die (psf, __LINE__) ; + + test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ; + test_seek_or_die (psf, 0, SEEK_END, 2 * SIGNED_SIZEOF (data_out), __LINE__) ; + test_seek_or_die (psf, -1 * SIGNED_SIZEOF (data_out), SEEK_CUR, (sf_count_t) sizeof (data_out), __LINE__) ; + + test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_CUR, 2 * SIGNED_SIZEOF (data_out), __LINE__) ; + make_data (data_out, ARRAY_LEN (data_out), 3) ; + test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 3 * sizeof (data_out), __LINE__) ; + + test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ; + make_data (data_out, ARRAY_LEN (data_out), 1) ; + test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + test_seek_or_die (psf, 2 * SIGNED_SIZEOF (data_out), SEEK_SET, 2 * SIGNED_SIZEOF (data_out), __LINE__) ; + make_data (data_out, ARRAY_LEN (data_out), 3) ; + test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ; + make_data (data_out, ARRAY_LEN (data_out), 2) ; + test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + test_close_or_die (psf, __LINE__) ; + puts ("ok") ; + + /* + ** Now test operations with a non-zero psf->fileoffset field. This field + ** sets an artificial file start positions so that a seek to the start of + ** the file will actually be a seek to the value given by psf->fileoffset. + */ + + printf (" %-24s : ", "file_offset_test") ; + fflush (stdout) ; + + /* Test file open in read/write mode. */ + psf->mode = SFM_RDWR ; + psf->fileoffset = sizeof (data_out [0]) * ARRAY_LEN (data_out) ; + test_open_or_die (psf, __LINE__) ; + + if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out)) + { printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 3 * ((int) sizeof (data_out))) ; + exit (1) ; + } ; + + test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ; + make_data (data_out, ARRAY_LEN (data_out), 5) ; + test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 2 * sizeof (data_out), __LINE__) ; + test_close_or_die (psf, __LINE__) ; + + /* final test with psf->fileoffset == 0. */ + + psf->mode = SFM_RDWR ; + psf->fileoffset = 0 ; + test_open_or_die (psf, __LINE__) ; + + if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out)) + { printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 3 * ((int) sizeof (data_out))) ; + exit (1) ; + } ; + + make_data (data_out, ARRAY_LEN (data_out), 1) ; + test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + make_data (data_out, ARRAY_LEN (data_out), 2) ; + test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + make_data (data_out, ARRAY_LEN (data_out), 5) ; + test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ; + test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ; + + test_close_or_die (psf, __LINE__) ; + + puts ("ok") ; +} /* file_read_write_test */ + +static void +file_truncate_test (const char *filename) +{ SF_PRIVATE sf_data, *psf ; + unsigned char buffer [256] ; + int k ; + + /* + ** Open a new file and write two blocks of data to the file. After each + ** write, test that psf_get_filelen() returns the new length. + */ + + printf (" %-24s : ", "file_truncate_test") ; + fflush (stdout) ; + + memset (&sf_data, 0, sizeof (sf_data)) ; + memset (buffer, 0xEE, sizeof (buffer)) ; + + psf = &sf_data ; + strncpy (psf->filename, filename, sizeof (psf->filename)) ; + + /* + ** Open the file write mode, write 0xEE data and then extend the file + ** using truncate (the extended data should be 0x00). + */ + psf->mode = SFM_WRITE ; + test_open_or_die (psf, __LINE__) ; + test_write_or_die (psf, buffer, sizeof (buffer) / 2, 1, sizeof (buffer) / 2, __LINE__) ; + psf_ftruncate (psf, sizeof (buffer)) ; + test_close_or_die (psf, __LINE__) ; + + /* Open the file in read mode and check the data. */ + psf->mode = SFM_READ ; + test_open_or_die (psf, __LINE__) ; + test_read_or_die (psf, buffer, sizeof (buffer), 1, sizeof (buffer), __LINE__) ; + test_close_or_die (psf, __LINE__) ; + + for (k = 0 ; k < SIGNED_SIZEOF (buffer) / 2 ; k++) + if (buffer [k] != 0xEE) + { printf ("\n\nLine %d : buffer [%d] = %d (should be 0xEE)\n\n", __LINE__, k, buffer [k]) ; + exit (1) ; + } ; + + for (k = SIGNED_SIZEOF (buffer) / 2 ; k < SIGNED_SIZEOF (buffer) ; k++) + if (buffer [k] != 0) + { printf ("\n\nLine %d : buffer [%d] = %d (should be 0)\n\n", __LINE__, k, buffer [k]) ; + exit (1) ; + } ; + + /* Open the file in read/write and shorten the file using truncate. */ + psf->mode = SFM_RDWR ; + test_open_or_die (psf, __LINE__) ; + psf_ftruncate (psf, sizeof (buffer) / 4) ; + test_close_or_die (psf, __LINE__) ; + + /* Check the file length. */ + psf->mode = SFM_READ ; + test_open_or_die (psf, __LINE__) ; + test_seek_or_die (psf, 0, SEEK_END, SIGNED_SIZEOF (buffer) / 4, __LINE__) ; + test_close_or_die (psf, __LINE__) ; + + puts ("ok") ; +} /* file_truncate_test */ + +/*============================================================================== +** Testing helper functions. +*/ + +static void +test_open_or_die (SF_PRIVATE *psf, int linenum) +{ int error ; + + /* Test that open for read fails if the file doesn't exist. */ + error = psf_fopen (psf, psf->filename, psf->mode) ; + if (error) + { printf ("\n\nLine %d: psf_fopen() failed : %s\n\n", linenum, strerror (errno)) ; + exit (1) ; + } ; + +} /* test_open_or_die */ + +static void +test_close_or_die (SF_PRIVATE *psf, int linenum) +{ + psf_fclose (psf) ; + if (psf_file_valid (psf)) + { printf ("\n\nLine %d: psf->filedes should not be valid.\n\n", linenum) ; + exit (1) ; + } ; + +} /* test_close_or_die */ + +static void +test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) +{ sf_count_t retval ; + + retval = psf_fwrite (data, bytes, items, psf) ; + if (retval != items) + { printf ("\n\nLine %d: psf_write() returned %ld (should be %ld)\n\n", linenum, (long) retval, (long) items) ; + exit (1) ; + } ; + + if ((retval = psf_ftell (psf)) != new_position) + { printf ("\n\nLine %d: file length after write is not correct. (%ld should be %ld)\n\n", linenum, (long) retval, (long) new_position) ; + exit (1) ; + } ; + + return ; +} /* test_write_or_die */ + +static void +test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) +{ sf_count_t retval ; + + retval = psf_fread (data, bytes, items, psf) ; + if (retval != items) + { printf ("\n\nLine %d: psf_write() returned %ld (should be %ld)\n\n", linenum, (long) retval, (long) items) ; + exit (1) ; + } ; + + if ((retval = psf_ftell (psf)) != new_position) + { printf ("\n\nLine %d: file length after write is not correct. (%ld should be %ld)\n\n", linenum, (long) retval, (long) new_position) ; + exit (1) ; + } ; + + return ; +} /* test_write_or_die */ + +static void +test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum) +{ sf_count_t retval ; + + retval = psf_fseek (psf, offset, whence) ; + + if (retval != new_position) + { printf ("\n\nLine %d: psf_fseek() failed. New position is %ld (should be %ld).\n\n", + linenum, (long) retval, (long) new_position) ; + exit (1) ; + } ; + +} /* test_seek_or_die */ + +static void +test_equal_or_die (int *array1, int *array2, int len, int linenum) +{ int k ; + + for (k = 0 ; k < len ; k++) + if (array1 [k] != array2 [k]) + printf ("\n\nLine %d: error at index %d (%d != %d).\n\n", + linenum, k, array1 [k], array2 [k]) ; + + return ; +} /* test_equal_or_die */ + +static void +make_data (int *data, int len, int seed) +{ int k ; + + srand (seed * 3333333 + 14756123) ; + + for (k = 0 ; k < len ; k++) + data [k] = rand () ; + +} /* make_data */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 0a21fb93-78dd-4f72-8338-4bca9e77b8c8 +*/ diff --git a/nylsf/test_log_printf.c b/nylsf/test_log_printf.c new file mode 100644 index 0000000..2628dcf --- /dev/null +++ b/nylsf/test_log_printf.c @@ -0,0 +1,138 @@ +/* +** Copyright (C) 2003-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include + +#include "sfconfig.h" + +/* +** This is a bit rough, but it is the nicest way to do it. +*/ +#define PSF_LOG_PRINTF_ONLY +#include "common.c" + + +#define CMP_0_ARGS(line,err,fmt) \ + { psf->logindex = 0 ; \ + LSF_SNPRINTF (buffer, sizeof (buffer), (fmt)) ; \ + psf_log_printf (psf, (fmt)) ; \ + err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \ + } + +#define CMP_2_ARGS(line,err,fmt,a) \ + { psf->logindex = 0 ; \ + LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a)) ; \ + psf_log_printf (psf, (fmt), (a), (a)) ; \ + err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \ + } + +#define CMP_4_ARGS(line,err,fmt,a) \ + { psf->logindex = 0 ; \ + LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a), (a), (a)) ; \ + psf_log_printf (psf, (fmt), (a), (a), (a), (a)) ; \ + err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \ + } + +#define CMP_5_ARGS(line,err,fmt,a) \ + { psf->logindex = 0 ; \ + LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a), (a), (a), (a)) ; \ + psf_log_printf (psf, (fmt), (a), (a), (a), (a), (a)) ; \ + err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \ + } + +#define CMP_6_ARGS(line,err,fmt,a) \ + { psf->logindex = 0 ; \ + LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a), (a), (a), (a), (a)) ; \ + psf_log_printf (psf, (fmt), (a), (a), (a), (a), (a), (a)) ; \ + err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \ + } + +static int compare_strings_or_die (int linenum, const char *fmt, const char* s1, const char* s3) ; + +int +main (void) +{ static char buffer [2048] ; + SF_PRIVATE sf_private, *psf ; + int k, errors = 0 ; + int int_values [] = { 0, 1, 12, 123, 1234, 123456, -1, -12, -123, -1234, -123456 } ; + + printf (" %-24s : ", "psf_log_printf_test") ; + fflush (stdout) ; + + psf = &sf_private ; + memset (psf, 0, sizeof (sf_private)) ; + + CMP_0_ARGS (__LINE__, errors, " ->%%<- ") ; + + /* Test printing of ints. */ + for (k = 0 ; k < ARRAY_LEN (int_values) ; k++) + CMP_6_ARGS (__LINE__, errors, "int A : %d, % d, %4d, % 4d, %04d, % 04d", int_values [k]) ; + + for (k = 0 ; k < ARRAY_LEN (int_values) ; k++) + CMP_5_ARGS (__LINE__, errors, "int B : %+d, %+4d, %+04d, %-d, %-4d", int_values [k]) ; + + for (k = 0 ; k < ARRAY_LEN (int_values) ; k++) + CMP_2_ARGS (__LINE__, errors, "int C : %- d, %- 4d", int_values [k]) ; + + /* Test printing of unsigned ints. */ + for (k = 0 ; k < ARRAY_LEN (int_values) ; k++) + CMP_4_ARGS (__LINE__, errors, "D : %u, %4u, %04u, %0u", int_values [k]) ; + + /* Test printing of hex ints. */ + for (k = 0 ; k < ARRAY_LEN (int_values) ; k++) + CMP_4_ARGS (__LINE__, errors, "E : %X, %4X, %04X, %0X", int_values [k]) ; + + /* Test printing of strings. */ + CMP_4_ARGS (__LINE__, errors, "B %s, %3s, %8s, %-8s", "str") ; + + if (errors) + { puts ("\nExiting due to errors.\n") ; + exit (1) ; + } ; + + puts ("ok") ; + + return 0 ; +} /* main */ + +static int +compare_strings_or_die (int linenum, const char *fmt, const char* s1, const char* s2) +{ int errors = 0 ; +/*-puts (s1) ;puts (s2) ;-*/ + + if (strcmp (s1, s2) != 0) + { printf ("\n\nLine %d: string compare mismatch:\n\t", linenum) ; + printf ("\"%s\"\n", fmt) ; + printf ("\t\"%s\"\n\t\"%s\"\n", s1, s2) ; + errors ++ ; + } ; + + return errors ; +} /* compare_strings_or_die */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 45147310-868b-400a-97e8-cc0a572a6270 +*/ diff --git a/nylsf/txw.c b/nylsf/txw.c new file mode 100644 index 0000000..0f0add6 --- /dev/null +++ b/nylsf/txw.c @@ -0,0 +1,379 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/*=========================================================================== +** Yamaha TX16 Sampler Files. +** +** This header parser was written using information from the SoX source code +** and trial and error experimentation. The code here however is all original. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#if (ENABLE_EXPERIMENTAL_CODE == 0) + +int +txw_open (SF_PRIVATE *psf) +{ if (psf) + return SFE_UNIMPLEMENTED ; + return (psf && 0) ; +} /* txw_open */ + +#else + +/*------------------------------------------------------------------------------ +** Markers. +*/ + +#define TXW_DATA_OFFSET 32 + +#define TXW_LOOPED 0x49 +#define TXW_NO_LOOP 0xC9 + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int txw_read_header (SF_PRIVATE *psf) ; + +static sf_count_t txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; + +/*------------------------------------------------------------------------------ +** Public functions. +*/ + +/* + * ftp://ftp.t0.or.at/pub/sound/tx16w/samples.yamaha + * ftp://ftp.t0.or.at/pub/sound/tx16w/faq/tx16w.tec + * http://www.t0.or.at/~mpakesch/tx16w/ + * + * from tx16w.c sox 12.15: (7-Oct-98) (Mark Lakata and Leigh Smith) + * char filetype[6] "LM8953" + * nulls[10], + * dummy_aeg[6] + * format 0x49 = looped, 0xC9 = non-looped + * sample_rate 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz + * atc_length[3] if sample rate 0, [2]&0xfe = 6: 33kHz, 0x10:50, 0xf6: 16, + * depending on [5] but to heck with it + * rpt_length[3] (these are for looped samples, attack and loop lengths) + * unused[2] + */ + +typedef struct +{ unsigned char format, srate, sr2, sr3 ; + unsigned short srhash ; + unsigned int attacklen, repeatlen ; +} TXW_HEADER ; + +#define ERROR_666 666 + +int +txw_open (SF_PRIVATE *psf) +{ int error ; + + if (psf->mode != SFM_READ) + return SFE_UNIMPLEMENTED ; + + if ((error = txw_read_header (psf))) + return error ; + + if (psf_fseek (psf, psf->dataoffset, SEEK_SET) != psf->dataoffset) + return SFE_BAD_SEEK ; + + psf->read_short = txw_read_s ; + psf->read_int = txw_read_i ; + psf->read_float = txw_read_f ; + psf->read_double = txw_read_d ; + + psf->seek = txw_seek ; + + return 0 ; +} /* txw_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +txw_read_header (SF_PRIVATE *psf) +{ TXW_HEADER txwh ; + char *strptr ; + + memset (&txwh, 0, sizeof (txwh)) ; + memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ; + psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, 16) ; + + if (memcmp (psf->u.cbuf, "LM8953\0\0\0\0\0\0\0\0\0\0", 16) != 0) + return ERROR_666 ; + + psf_log_printf (psf, "Read only : Yamaha TX-16 Sampler (.txw)\nLM8953\n") ; + + /* Jump 6 bytes (dummp_aeg), read format, read sample rate. */ + psf_binheader_readf (psf, "j11", 6, &txwh.format, &txwh.srate) ; + + /* 8 bytes (atc_length[3], rpt_length[3], unused[2]). */ + psf_binheader_readf (psf, "e33j", &txwh.attacklen, &txwh.repeatlen, 2) ; + txwh.sr2 = (txwh.attacklen >> 16) & 0xFE ; + txwh.sr3 = (txwh.repeatlen >> 16) & 0xFE ; + txwh.attacklen &= 0x1FFFF ; + txwh.repeatlen &= 0x1FFFF ; + + switch (txwh.format) + { case TXW_LOOPED : + strptr = "looped" ; + break ; + + case TXW_NO_LOOP : + strptr = "non-looped" ; + break ; + + default : + psf_log_printf (psf, " Format : 0x%02x => ?????\n", txwh.format) ; + return ERROR_666 ; + } ; + + psf_log_printf (psf, " Format : 0x%02X => %s\n", txwh.format, strptr) ; + + strptr = NULL ; + + switch (txwh.srate) + { case 1 : + psf->sf.samplerate = 33333 ; + break ; + + case 2 : + psf->sf.samplerate = 50000 ; + break ; + + case 3 : + psf->sf.samplerate = 16667 ; + break ; + + default : + /* This is ugly and braindead. */ + txwh.srhash = ((txwh.sr2 & 0xFE) << 8) | (txwh.sr3 & 0xFE) ; + switch (txwh.srhash) + { case ((0x6 << 8) | 0x52) : + psf->sf.samplerate = 33333 ; + break ; + + case ((0x10 << 8) | 0x52) : + psf->sf.samplerate = 50000 ; + break ; + + case ((0xF6 << 8) | 0x52) : + psf->sf.samplerate = 166667 ; + break ; + + default : + strptr = " Sample Rate : Unknown : forcing to 33333\n" ; + psf->sf.samplerate = 33333 ; + break ; + } ; + } ; + + + if (strptr) + psf_log_printf (psf, strptr) ; + else if (txwh.srhash) + psf_log_printf (psf, " Sample Rate : %d (0x%X) => %d\n", txwh.srate, txwh.srhash, psf->sf.samplerate) ; + else + psf_log_printf (psf, " Sample Rate : %d => %d\n", txwh.srate, psf->sf.samplerate) ; + + if (txwh.format == TXW_LOOPED) + { psf_log_printf (psf, " Attack Len : %d\n", txwh.attacklen) ; + psf_log_printf (psf, " Repeat Len : %d\n", txwh.repeatlen) ; + } ; + + psf->dataoffset = TXW_DATA_OFFSET ; + psf->datalength = psf->filelength - TXW_DATA_OFFSET ; + psf->sf.frames = 2 * psf->datalength / 3 ; + + + if (psf->datalength % 3 == 1) + psf_log_printf (psf, "*** File seems to be truncated, %d extra bytes.\n", + (int) (psf->datalength % 3)) ; + + if (txwh.attacklen + txwh.repeatlen > psf->sf.frames) + psf_log_printf (psf, "*** File has been truncated.\n") ; + + psf->sf.format = SF_FORMAT_TXW | SF_FORMAT_PCM_16 ; + psf->sf.channels = 1 ; + psf->sf.sections = 1 ; + psf->sf.seekable = SF_TRUE ; + + return 0 ; +} /* txw_read_header */ + +static sf_count_t +txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ unsigned char *ucptr ; + short sample ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.cbuf) / 3 ; + bufferlen -= (bufferlen & 1) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = psf_fread (psf->u.cbuf, 3, readcount, psf) ; + + ucptr = psf->u.ucbuf ; + for (k = 0 ; k < readcount ; k += 2) + { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; + ptr [total + k] = sample ; + sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; + ptr [total + k + 1] = sample ; + ucptr += 3 ; + } ; + + total += count ; + len -= readcount ; + } ; + + return total ; +} /* txw_read_s */ + +static sf_count_t +txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ unsigned char *ucptr ; + short sample ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + + bufferlen = sizeof (psf->u.cbuf) / 3 ; + bufferlen -= (bufferlen & 1) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = psf_fread (psf->u.cbuf, 3, readcount, psf) ; + + ucptr = psf->u.ucbuf ; + for (k = 0 ; k < readcount ; k += 2) + { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; + ptr [total + k] = sample << 16 ; + sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; + ptr [total + k + 1] = sample << 16 ; + ucptr += 3 ; + } ; + + total += count ; + len -= readcount ; + } ; + + return total ; +} /* txw_read_i */ + +static sf_count_t +txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ unsigned char *ucptr ; + short sample ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (psf->norm_float == SF_TRUE) + normfact = 1.0 / 0x8000 ; + else + normfact = 1.0 / 0x10 ; + + bufferlen = sizeof (psf->u.cbuf) / 3 ; + bufferlen -= (bufferlen & 1) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = psf_fread (psf->u.cbuf, 3, readcount, psf) ; + + ucptr = psf->u.ucbuf ; + for (k = 0 ; k < readcount ; k += 2) + { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; + ptr [total + k] = normfact * sample ; + sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; + ptr [total + k + 1] = normfact * sample ; + ucptr += 3 ; + } ; + + total += count ; + len -= readcount ; + } ; + + return total ; +} /* txw_read_f */ + +static sf_count_t +txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ unsigned char *ucptr ; + short sample ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (psf->norm_double == SF_TRUE) + normfact = 1.0 / 0x8000 ; + else + normfact = 1.0 / 0x10 ; + + bufferlen = sizeof (psf->u.cbuf) / 3 ; + bufferlen -= (bufferlen & 1) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : len ; + count = psf_fread (psf->u.cbuf, 3, readcount, psf) ; + + ucptr = psf->u.ucbuf ; + for (k = 0 ; k < readcount ; k += 2) + { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; + ptr [total + k] = normfact * sample ; + sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; + ptr [total + k + 1] = normfact * sample ; + ucptr += 3 ; + } ; + + total += count ; + len -= readcount ; + } ; + + return total ; +} /* txw_read_d */ + +static sf_count_t +txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ if (psf && mode) + return offset ; + + return 0 ; +} /* txw_seek */ + +#endif +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 4d0ba7af-b1c5-46b4-a900-7c6f59fd9a89 +*/ diff --git a/nylsf/ulaw.c b/nylsf/ulaw.c new file mode 100644 index 0000000..e476c0a --- /dev/null +++ b/nylsf/ulaw.c @@ -0,0 +1,1047 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sndfile.h" +#include "float_cast.h" +#include "common.h" + +static sf_count_t ulaw_read_ulaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t ulaw_read_ulaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t ulaw_read_ulaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t ulaw_read_ulaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t ulaw_write_s2ulaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t ulaw_write_i2ulaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t ulaw_write_f2ulaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t ulaw_write_d2ulaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +int +ulaw_init (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { psf->read_short = ulaw_read_ulaw2s ; + psf->read_int = ulaw_read_ulaw2i ; + psf->read_float = ulaw_read_ulaw2f ; + psf->read_double = ulaw_read_ulaw2d ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { psf->write_short = ulaw_write_s2ulaw ; + psf->write_int = ulaw_write_i2ulaw ; + psf->write_float = ulaw_write_f2ulaw ; + psf->write_double = ulaw_write_d2ulaw ; + } ; + + psf->bytewidth = 1 ; + psf->blockwidth = psf->sf.channels ; + + if (psf->filelength > psf->dataoffset) + psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : + psf->filelength - psf->dataoffset ; + else + psf->datalength = 0 ; + + psf->sf.frames = psf->datalength / psf->blockwidth ; + + return 0 ; +} /* ulaw_init */ + +/*============================================================================== +*/ + +static short ulaw_decode [256] = +{ -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, + -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, + -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, + -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0 +} ; + +static +unsigned char ulaw_encode [8193] = +{ 0xff, 0xfe, 0xfe, 0xfd, 0xfd, 0xfc, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, + 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, + 0xf3, 0xf2, 0xf2, 0xf1, 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0xef, 0xee, + 0xee, 0xee, 0xee, 0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xeb, + 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, + 0xe8, 0xe8, 0xe8, 0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe5, + 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, + 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, + 0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, + 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, + 0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, + 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, + 0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, + 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, + 0xd2, 0xd2, 0xd2, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd0, + 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, + 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, + 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, + 0xce, 0xce, 0xce, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb, + 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, + 0xcb, 0xcb, 0xcb, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, + 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, + 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8, + 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, + 0xc8, 0xc8, 0xc8, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, + 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5, + 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, + 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, + 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, + 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00 +} ; + +static inline void +ulaw2s_array (unsigned char *buffer, int count, short *ptr) +{ while (--count >= 0) + ptr [count] = ulaw_decode [(int) buffer [count]] ; +} /* ulaw2s_array */ + +static inline void +ulaw2i_array (unsigned char *buffer, int count, int *ptr) +{ while (--count >= 0) + ptr [count] = ulaw_decode [buffer [count]] << 16 ; +} /* ulaw2i_array */ + +static inline void +ulaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) +{ while (--count >= 0) + ptr [count] = normfact * ulaw_decode [(int) buffer [count]] ; +} /* ulaw2f_array */ + +static inline void +ulaw2d_array (const unsigned char *buffer, int count, double *ptr, double normfact) +{ while (--count >= 0) + ptr [count] = normfact * ulaw_decode [(int) buffer [count]] ; +} /* ulaw2d_array */ + +static inline void +s2ulaw_array (const short *ptr, int count, unsigned char *buffer) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = ulaw_encode [ptr [count] / 4] ; + else + buffer [count] = 0x7F & ulaw_encode [ptr [count] / -4] ; + } ; +} /* s2ulaw_array */ + +static inline void +i2ulaw_array (const int *ptr, int count, unsigned char *buffer) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = ulaw_encode [ptr [count] >> (16 + 2)] ; + else + buffer [count] = 0x7F & ulaw_encode [-ptr [count] >> (16 + 2)] ; + } ; +} /* i2ulaw_array */ + +static inline void +f2ulaw_array (const float *ptr, int count, unsigned char *buffer, float normfact) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = ulaw_encode [lrintf (normfact * ptr [count])] ; + else + buffer [count] = 0x7F & ulaw_encode [- lrintf (normfact * ptr [count])] ; + } ; +} /* f2ulaw_array */ + +static inline void +d2ulaw_array (const double *ptr, int count, unsigned char *buffer, double normfact) +{ while (--count >= 0) + { if (ptr [count] >= 0) + buffer [count] = ulaw_encode [lrint (normfact * ptr [count])] ; + else + buffer [count] = 0x7F & ulaw_encode [- lrint (normfact * ptr [count])] ; + } ; +} /* d2ulaw_array */ + +/*============================================================================== +*/ + +static sf_count_t +ulaw_read_ulaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + ulaw2s_array (psf->u.ucbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* ulaw_read_ulaw2s */ + +static sf_count_t +ulaw_read_ulaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + ulaw2i_array (psf->u.ucbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* ulaw_read_ulaw2i */ + +static sf_count_t +ulaw_read_ulaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + ulaw2f_array (psf->u.ucbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* ulaw_read_ulaw2f */ + +static sf_count_t +ulaw_read_ulaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + normfact = (psf->norm_double) ? 1.0 / ((double) 0x8000) : 1.0 ; + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ; + ulaw2d_array (psf->u.ucbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* ulaw_read_ulaw2d */ + +/*============================================================================================= +*/ + +static sf_count_t +ulaw_write_s2ulaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2ulaw_array (ptr + total, bufferlen, psf->u.ucbuf) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* ulaw_write_s2ulaw */ + +static sf_count_t +ulaw_write_i2ulaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2ulaw_array (ptr + total, bufferlen, psf->u.ucbuf) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* ulaw_write_i2ulaw */ + +static sf_count_t +ulaw_write_f2ulaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + float normfact ; + + /* Factor in a divide by 4. */ + normfact = (psf->norm_float == SF_TRUE) ? (0.25 * 0x7FFF) : 0.25 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + f2ulaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* ulaw_write_f2ulaw */ + +static sf_count_t +ulaw_write_d2ulaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ int bufferlen, writecount ; + sf_count_t total = 0 ; + double normfact ; + + /* Factor in a divide by 4. */ + normfact = (psf->norm_double) ? (0.25 * 0x7FFF) : 0.25 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + d2ulaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ; + writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* ulaw_write_d2ulaw */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 655cc790-f058-45e8-89c9-86967cccc37e +*/ diff --git a/nylsf/voc.c b/nylsf/voc.c new file mode 100644 index 0000000..de7abf2 --- /dev/null +++ b/nylsf/voc.c @@ -0,0 +1,878 @@ +/* +** Copyright (C) 2001-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* RANT: +** The VOC file format is the most brain damaged format I have yet had to deal +** with. No one programmer could have bee stupid enough to put this together. +** Instead it looks like a series of manic, dyslexic assembly language programmers +** hacked it to fit their needs. +** Utterly woeful. +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + + +/*------------------------------------------------------------------------------ + * Typedefs for file chunks. +*/ + +#define VOC_MAX_SECTIONS 200 + +enum +{ VOC_TERMINATOR = 0, + VOC_SOUND_DATA = 1, + VOC_SOUND_CONTINUE = 2, + VOC_SILENCE = 3, + VOC_MARKER = 4, + VOC_ASCII = 5, + VOC_REPEAT = 6, + VOC_END_REPEAT = 7, + VOC_EXTENDED = 8, + VOC_EXTENDED_II = 9 +} ; + +typedef struct +{ int samples ; + int offset ; /* Offset of zero => silence. */ +} SND_DATA_BLOCKS ; + +typedef struct +{ unsigned int sections, section_types ; + int samplerate, channels, bitwidth ; + SND_DATA_BLOCKS blocks [VOC_MAX_SECTIONS] ; +} VOC_DATA ; + +/*------------------------------------------------------------------------------ + * Private static functions. +*/ + +static int voc_close (SF_PRIVATE *psf) ; +static int voc_write_header (SF_PRIVATE *psf, int calc_length) ; +static int voc_read_header (SF_PRIVATE *psf) ; + +static const char* voc_encoding2str (int encoding) ; + +#if 0 + +/* These functions would be required for files with more than one VOC_SOUND_DATA +** segment. Not sure whether to bother implementing this. +*/ + +static int voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc) ; + +static int voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len) ; +static int voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len) ; + +static int voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len) ; +static int voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len) ; + +static int voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len) ; +static int voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len) ; + +static int voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len) ; +static int voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len) ; +#endif + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +voc_open (SF_PRIVATE *psf) +{ int subformat, error = 0 ; + + if (psf->is_pipe) + return SFE_VOC_NO_PIPE ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = voc_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = SF_ENDIAN_LITTLE ; + + if ((error = voc_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = voc_write_header ; + } ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + psf->container_close = voc_close ; + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + return error ; +} /* voc_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +voc_read_header (SF_PRIVATE *psf) +{ VOC_DATA *pvoc ; + char creative [20] ; + unsigned char block_type, rate_byte ; + short version, checksum, encoding, dataoffset ; + int offset ; + + /* Set position to start of file to begin reading header. */ + offset = psf_binheader_readf (psf, "pb", 0, creative, SIGNED_SIZEOF (creative)) ; + + if (creative [sizeof (creative) - 1] != 0x1A) + return SFE_VOC_NO_CREATIVE ; + + /* Terminate the string. */ + creative [sizeof (creative) - 1] = 0 ; + + if (strcmp ("Creative Voice File", creative)) + return SFE_VOC_NO_CREATIVE ; + + psf_log_printf (psf, "%s\n", creative) ; + + offset += psf_binheader_readf (psf, "e222", &dataoffset, &version, &checksum) ; + + psf->dataoffset = dataoffset ; + + psf_log_printf (psf, "dataoffset : %d\n" + "version : 0x%X\n" + "checksum : 0x%X\n", psf->dataoffset, version, checksum) ; + + if (version != 0x010A && version != 0x0114) + return SFE_VOC_BAD_VERSION ; + + if (! (psf->codec_data = malloc (sizeof (VOC_DATA)))) + return SFE_MALLOC_FAILED ; + + pvoc = (VOC_DATA*) psf->codec_data ; + + memset (pvoc, 0, sizeof (VOC_DATA)) ; + + /* Set the default encoding now. */ + psf->sf.format = SF_FORMAT_VOC ; /* Major format */ + encoding = SF_FORMAT_PCM_U8 ; /* Minor format */ + psf->endian = SF_ENDIAN_LITTLE ; + + while (1) + { offset += psf_binheader_readf (psf, "1", &block_type) ; + + switch (block_type) + { case VOC_ASCII : + { int size ; + + offset += psf_binheader_readf (psf, "e3", &size) ; + + psf_log_printf (psf, " ASCII : %d\n", size) ; + + offset += psf_binheader_readf (psf, "b", psf->header, size) ; + psf->header [size] = 0 ; + psf_log_printf (psf, " text : %s\n", psf->header) ; + } ; + continue ; + + case VOC_SOUND_DATA : + case VOC_EXTENDED : + case VOC_EXTENDED_II : + break ; + + default : psf_log_printf (psf, "*** Weird block marker (%d)\n", block_type) ; + } ; + + break ; + } ; + + if (block_type == VOC_SOUND_DATA) + { unsigned char compression ; + int size ; + + offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ; + + psf->sf.samplerate = 1000000 / (256 - (rate_byte & 0xFF)) ; + + psf_log_printf (psf, " Sound Data : %d\n sr : %d => %dHz\n comp : %d\n", + size, rate_byte, psf->sf.samplerate, compression) ; + + if (offset + size - 1 > psf->filelength) + { psf_log_printf (psf, "Seems to be a truncated file.\n") ; + psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; + return SFE_VOC_BAD_SECTIONS ; + } + else if (offset + size - 1 < psf->filelength) + { psf_log_printf (psf, "Seems to be a multi-segment file (#1).\n") ; + psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; + return SFE_VOC_BAD_SECTIONS ; + } ; + + psf->dataoffset = offset ; + psf->dataend = psf->filelength - 1 ; + + psf->sf.channels = 1 ; + psf->bytewidth = 1 ; + + psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; + + return 0 ; + } ; + + if (block_type == VOC_EXTENDED) + { unsigned char pack, stereo, compression ; + unsigned short rate_short ; + int size ; + + offset += psf_binheader_readf (psf, "e3211", &size, &rate_short, &pack, &stereo) ; + + psf_log_printf (psf, " Extended : %d\n", size) ; + if (size == 4) + psf_log_printf (psf, " size : 4\n") ; + else + psf_log_printf (psf, " size : %d (should be 4)\n", size) ; + + psf_log_printf (psf, " pack : %d\n" + " stereo : %s\n", pack, (stereo ? "yes" : "no")) ; + + if (stereo) + { psf->sf.channels = 2 ; + psf->sf.samplerate = 128000000 / (65536 - rate_short) ; + } + else + { psf->sf.channels = 1 ; + psf->sf.samplerate = 256000000 / (65536 - rate_short) ; + } ; + + psf_log_printf (psf, " sr : %d => %dHz\n", (rate_short & 0xFFFF), psf->sf.samplerate) ; + + offset += psf_binheader_readf (psf, "1", &block_type) ; + + if (block_type != VOC_SOUND_DATA) + { psf_log_printf (psf, "*** Expecting VOC_SOUND_DATA section.\n") ; + return SFE_VOC_BAD_FORMAT ; + } ; + + offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ; + + psf_log_printf (psf, " Sound Data : %d\n" + " sr : %d\n" + " comp : %d\n", size, rate_byte, compression) ; + + + if (offset + size - 1 > psf->filelength) + { psf_log_printf (psf, "Seems to be a truncated file.\n") ; + psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; + return SFE_VOC_BAD_SECTIONS ; + } + else if (offset + size - 1 < psf->filelength) + { psf_log_printf (psf, "Seems to be a multi-segment file (#2).\n") ; + psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; + return SFE_VOC_BAD_SECTIONS ; + } ; + + psf->dataoffset = offset ; + psf->dataend = psf->filelength - 1 ; + + psf->bytewidth = 1 ; + + psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; + + return 0 ; + } + + if (block_type == VOC_EXTENDED_II) + { unsigned char bitwidth, channels ; + int size, fourbytes ; + + offset += psf_binheader_readf (psf, "e341124", &size, &psf->sf.samplerate, + &bitwidth, &channels, &encoding, &fourbytes) ; + + if (size * 2 == psf->filelength - 39) + { int temp_size = psf->filelength - 31 ; + + psf_log_printf (psf, " Extended II : %d (SoX bug: should be %d)\n", size, temp_size) ; + size = temp_size ; + } + else + psf_log_printf (psf, " Extended II : %d\n", size) ; + + psf_log_printf (psf, " sample rate : %d\n" + " bit width : %d\n" + " channels : %d\n", psf->sf.samplerate, bitwidth, channels) ; + + if (bitwidth == 16 && encoding == 0) + { encoding = 4 ; + psf_log_printf (psf, " encoding : 0 (SoX bug: should be 4 for 16 bit signed PCM)\n") ; + } + else + psf_log_printf (psf, " encoding : %d => %s\n", encoding, voc_encoding2str (encoding)) ; + + + psf_log_printf (psf, " fourbytes : %X\n", fourbytes) ; + + psf->sf.channels = channels ; + + psf->dataoffset = offset ; + psf->dataend = psf->filelength - 1 ; + + if (size + 31 == psf->filelength + 1) + { /* Hack for reading files produced using + ** sf_command (SFC_UPDATE_HEADER_NOW). + */ + psf_log_printf (psf, "Missing zero byte at end of file.\n") ; + size = psf->filelength - 30 ; + psf->dataend = 0 ; + } + else if (size + 31 > psf->filelength) + { psf_log_printf (psf, "Seems to be a truncated file.\n") ; + size = psf->filelength - 31 ; + } + else if (size + 31 < psf->filelength) + psf_log_printf (psf, "Seems to be a multi-segment file (#3).\n") ; + + switch (encoding) + { case 0 : + psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; + psf->bytewidth = 1 ; + break ; + + case 4 : + psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_16 ; + psf->bytewidth = 2 ; + break ; + + case 6 : + psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ALAW ; + psf->bytewidth = 1 ; + break ; + + case 7 : + psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ULAW ; + psf->bytewidth = 1 ; + break ; + + default : /* Unknown */ + return SFE_UNKNOWN_FORMAT ; + break ; + } ; + + } ; + + return 0 ; +} /* voc_read_header */ + +/*==================================================================================== +*/ + +static int +voc_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + int rate_const, subformat ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* VOC marker and 0x1A byte. */ + psf_binheader_writef (psf, "eb1", "Creative Voice File", make_size_t (19), 0x1A) ; + + /* Data offset, version and other. */ + psf_binheader_writef (psf, "e222", 26, 0x0114, 0x111F) ; + + /* Use same logic as SOX. + ** If the file is mono 8 bit data, use VOC_SOUND_DATA. + ** If the file is mono 16 bit data, use VOC_EXTENED. + ** Otherwise use VOC_EXTENED_2. + */ + + if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 1) + { /* samplerate = 1000000 / (256 - rate_const) ; */ + rate_const = 256 - 1000000 / psf->sf.samplerate ; + + /* First type marker, length, rate_const and compression */ + psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ; + } + else if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 2) + { /* sample_rate = 128000000 / (65536 - rate_short) ; */ + rate_const = 65536 - 128000000 / psf->sf.samplerate ; + + /* First write the VOC_EXTENDED section + ** marker, length, rate_const and compression + */ + psf_binheader_writef (psf, "e13211", VOC_EXTENDED, 4, rate_const, 0, 1) ; + + /* samplerate = 1000000 / (256 - rate_const) ; */ + rate_const = 256 - 1000000 / psf->sf.samplerate ; + + /* Now write the VOC_SOUND_DATA section + ** marker, length, rate_const and compression + */ + psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ; + } + else + { int length ; + + if (psf->sf.channels < 1 || psf->sf.channels > 2) + return SFE_CHANNEL_COUNT ; + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + psf->bytewidth = 1 ; + length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; + /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */ + psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ; + break ; + + case SF_FORMAT_PCM_16 : + psf->bytewidth = 2 ; + length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; + /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */ + psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ; + break ; + + case SF_FORMAT_ALAW : + psf->bytewidth = 1 ; + length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; + psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 6, 0) ; + break ; + + case SF_FORMAT_ULAW : + psf->bytewidth = 1 ; + length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; + psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 7, 0) ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + } ; + + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* voc_write_header */ + +static int +voc_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { /* Now we know for certain the length of the file we can re-write + ** correct values for the FORM, 8SVX and BODY chunks. + */ + unsigned byte = VOC_TERMINATOR ; + + + psf_fseek (psf, 0, SEEK_END) ; + + /* Write terminator */ + psf_fwrite (&byte, 1, 1, psf) ; + + voc_write_header (psf, SF_TRUE) ; + } ; + + return 0 ; +} /* voc_close */ + +static const char* +voc_encoding2str (int encoding) +{ + switch (encoding) + { case 0 : return "8 bit unsigned PCM" ; + case 4 : return "16 bit signed PCM" ; + case 6 : return "A-law" ; + case 7 : return "u-law" ; + default : break ; + } + return "*** Unknown ***" ; +} /* voc_encoding2str */ + +/*==================================================================================== +*/ + +#if 0 +static int +voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc) +{ + psf->sf.frames = 0 ; + + if (pvoc->bitwidth == 8) + { psf->read_short = voc_multi_read_uc2s ; + psf->read_int = voc_multi_read_uc2i ; + psf->read_float = voc_multi_read_uc2f ; + psf->read_double = voc_multi_read_uc2d ; + return 0 ; + } ; + + if (pvoc->bitwidth == 16) + { psf->read_short = voc_multi_read_les2s ; + psf->read_int = voc_multi_read_les2i ; + psf->read_float = voc_multi_read_les2f ; + psf->read_double = voc_multi_read_les2d ; + return 0 ; + } ; + + psf_log_printf (psf, "Error : bitwith != 8 && bitwidth != 16.\n") ; + + return SFE_UNIMPLEMENTED ; +} /* voc_multi_read_int */ + +/*------------------------------------------------------------------------------------ +*/ + +static int +voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_uc2s */ + +static int +voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_les2s */ + + +static int +voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_uc2i */ + +static int +voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_les2i */ + + +static int +voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_uc2f */ + +static int +voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_les2f */ + + +static int +voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_uc2d */ + +static int +voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len) +{ + + return 0 ; +} /* voc_multi_read_les2d */ + +#endif + +/*------------------------------------------------------------------------------------ + +Creative Voice (VOC) file format +-------------------------------- + +~From: galt@dsd.es.com + +(byte numbers are hex!) + + HEADER (bytes 00-19) + Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block] + +- --------------------------------------------------------------- + +HEADER: +======= + byte # Description + ------ ------------------------------------------ + 00-12 "Creative Voice File" + 13 1A (eof to abort printing of file) + 14-15 Offset of first datablock in .voc file (std 1A 00 + in Intel Notation) + 16-17 Version number (minor,major) (VOC-HDR puts 0A 01) + 18-19 1's Comp of Ver. # + 1234h (VOC-HDR puts 29 11) + +- --------------------------------------------------------------- + +DATA BLOCK: +=========== + + Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes) + NOTE: Terminator Block is an exception -- it has only the TYPE byte. + + TYPE Description Size (3-byte int) Info + ---- ----------- ----------------- ----------------------- + 00 Terminator (NONE) (NONE) + 01 Sound data 2+length of data * + 02 Sound continue length of data Voice Data + 03 Silence 3 ** + 04 Marker 2 Marker# (2 bytes) + 05 ASCII length of string null terminated string + 06 Repeat 2 Count# (2 bytes) + 07 End repeat 0 (NONE) + 08 Extended 4 *** + + *Sound Info Format: + --------------------- + 00 Sample Rate + 01 Compression Type + 02+ Voice Data + + **Silence Info Format: + ---------------------------- + 00-01 Length of silence - 1 + 02 Sample Rate + + + ***Extended Info Format: + --------------------- + 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate) + Stereo: 65536 - (25600000/(2*sample_rate)) + 02 Pack + 03 Mode: 0 = mono + 1 = stereo + + + Marker# -- Driver keeps the most recent marker in a status byte + Count# -- Number of repetitions + 1 + Count# may be 1 to FFFE for 0 - FFFD repetitions + or FFFF for endless repetitions + Sample Rate -- SR byte = 256-(1000000/sample_rate) + Length of silence -- in units of sampling cycle + Compression Type -- of voice data + 8-bits = 0 + 4-bits = 1 + 2.6-bits = 2 + 2-bits = 3 + Multi DAC = 3+(# of channels) [interesting-- + this isn't in the developer's manual] + + +--------------------------------------------------------------------------------- +Addendum submitted by Votis Kokavessis: + +After some experimenting with .VOC files I found out that there is a Data Block +Type 9, which is not covered in the VOC.TXT file. Here is what I was able to discover +about this block type: + + +TYPE: 09 +SIZE: 12 + length of data +INFO: 12 (twelve) bytes + +INFO STRUCTURE: + +Bytes 0-1: (Word) Sample Rate (e.g. 44100) +Bytes 2-3: zero (could be that bytes 0-3 are a DWord for Sample Rate) +Byte 4: Sample Size in bits (e.g. 16) +Byte 5: Number of channels (e.g. 1 for mono, 2 for stereo) +Byte 6: Unknown (equal to 4 in all files I examined) +Bytes 7-11: zero + + +-------------------------------------------------------------------------------------*/ + +/*===================================================================================== +**===================================================================================== +**===================================================================================== +**===================================================================================== +*/ + +/*------------------------------------------------------------------------ +The following is taken from the Audio File Formats FAQ dated 2-Jan-1995 +and submitted by Guido van Rossum . +-------------------------------------------------------------------------- +Creative Voice (VOC) file format +-------------------------------- + +From: galt@dsd.es.com + +(byte numbers are hex!) + + HEADER (bytes 00-19) + Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block] + +- --------------------------------------------------------------- + +HEADER: +------- + byte # Description + ------ ------------------------------------------ + 00-12 "Creative Voice File" + 13 1A (eof to abort printing of file) + 14-15 Offset of first datablock in .voc file (std 1A 00 + in Intel Notation) + 16-17 Version number (minor,major) (VOC-HDR puts 0A 01) + 18-19 2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11) + +- --------------------------------------------------------------- + +DATA BLOCK: +----------- + + Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes) + NOTE: Terminator Block is an exception -- it has only the TYPE byte. + + TYPE Description Size (3-byte int) Info + ---- ----------- ----------------- ----------------------- + 00 Terminator (NONE) (NONE) + 01 Sound data 2+length of data * + 02 Sound continue length of data Voice Data + 03 Silence 3 ** + 04 Marker 2 Marker# (2 bytes) + 05 ASCII length of string null terminated string + 06 Repeat 2 Count# (2 bytes) + 07 End repeat 0 (NONE) + 08 Extended 4 *** + + *Sound Info Format: **Silence Info Format: + --------------------- ---------------------------- + 00 Sample Rate 00-01 Length of silence - 1 + 01 Compression Type 02 Sample Rate + 02+ Voice Data + + ***Extended Info Format: + --------------------- + 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate) + Stereo: 65536 - (25600000/(2*sample_rate)) + 02 Pack + 03 Mode: 0 = mono + 1 = stereo + + + Marker# -- Driver keeps the most recent marker in a status byte + Count# -- Number of repetitions + 1 + Count# may be 1 to FFFE for 0 - FFFD repetitions + or FFFF for endless repetitions + Sample Rate -- SR byte = 256-(1000000/sample_rate) + Length of silence -- in units of sampling cycle + Compression Type -- of voice data + 8-bits = 0 + 4-bits = 1 + 2.6-bits = 2 + 2-bits = 3 + Multi DAC = 3+(# of channels) [interesting-- + this isn't in the developer's manual] + +Detailed description of new data blocks (VOC files version 1.20 and above): + + (Source is fax from Barry Boone at Creative Labs, 405/742-6622) + +BLOCK 8 - digitized sound attribute extension, must preceed block 1. + Used to define stereo, 8 bit audio + BYTE bBlockID; // = 8 + BYTE nBlockLen[3]; // 3 byte length + WORD wTimeConstant; // time constant = same as block 1 + BYTE bPackMethod; // same as in block 1 + BYTE bVoiceMode; // 0-mono, 1-stereo + + Data is stored left, right + +BLOCK 9 - data block that supersedes blocks 1 and 8. + Used for stereo, 16 bit. + + BYTE bBlockID; // = 9 + BYTE nBlockLen[3]; // length 12 plus length of sound + DWORD dwSamplesPerSec; // samples per second, not time const. + BYTE bBitsPerSample; // e.g., 8 or 16 + BYTE bChannels; // 1 for mono, 2 for stereo + WORD wFormat; // see below + BYTE reserved[4]; // pad to make block w/o data + // have a size of 16 bytes + + Valid values of wFormat are: + + 0x0000 8-bit unsigned PCM + 0x0001 Creative 8-bit to 4-bit ADPCM + 0x0002 Creative 8-bit to 3-bit ADPCM + 0x0003 Creative 8-bit to 2-bit ADPCM + 0x0004 16-bit signed PCM + 0x0006 CCITT a-Law + 0x0007 CCITT u-Law + 0x02000 Creative 16-bit to 4-bit ADPCM + + Data is stored left, right + +------------------------------------------------------------------------*/ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 40a50167-a81c-463a-9e1d-3282ff84e09d +*/ diff --git a/nylsf/vox_adpcm.c b/nylsf/vox_adpcm.c new file mode 100644 index 0000000..11f333f --- /dev/null +++ b/nylsf/vox_adpcm.c @@ -0,0 +1,537 @@ +/* +** Copyright (C) 2002-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** This is the OKI / Dialogic ADPCM encoder/decoder. It converts from +** 12 bit linear sample data to a 4 bit ADPCM. +** +** Implemented from the description found here: +** +** http://www.comptek.ru:8100/telephony/tnotes/tt1-13.html +** +** and compared against the encoder/decoder found here: +** +** http://ibiblio.org/pub/linux/apps/sound/convert/vox.tar.gz +*/ + +#include "sfconfig.h" + +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "float_cast.h" +#include "common.h" + +#define VOX_DATA_LEN 2048 +#define PCM_DATA_LEN (VOX_DATA_LEN *2) + +typedef struct +{ short last ; + short step_index ; + + int vox_bytes, pcm_samples ; + + unsigned char vox_data [VOX_DATA_LEN] ; + short pcm_data [PCM_DATA_LEN] ; +} VOX_ADPCM_PRIVATE ; + +static int vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox) ; +static int vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox) ; + +static short vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox) ; +static char vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox) ; + +static sf_count_t vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t vox_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static int vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) ; + +/*============================================================================================ +** Predefined OKI ADPCM encoder/decoder tables. +*/ + +static short step_size_table [49] = +{ 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, + 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, + 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1408, 1552 +} ; /* step_size_table */ + +static short step_adjust_table [8] = +{ -1, -1, -1, -1, 2, 4, 6, 8 +} ; /* step_adjust_table */ + +/*------------------------------------------------------------------------------ +*/ + +int +vox_adpcm_init (SF_PRIVATE *psf) +{ VOX_ADPCM_PRIVATE *pvox = NULL ; + + if (psf->mode == SFM_RDWR) + return SFE_BAD_MODE_RW ; + + if (psf->mode == SFM_WRITE && psf->sf.channels != 1) + return SFE_CHANNEL_COUNT ; + + if ((pvox = malloc (sizeof (VOX_ADPCM_PRIVATE))) == NULL) + return SFE_MALLOC_FAILED ; + + psf->codec_data = (void*) pvox ; + memset (pvox, 0, sizeof (VOX_ADPCM_PRIVATE)) ; + + if (psf->mode == SFM_WRITE) + { psf->write_short = vox_write_s ; + psf->write_int = vox_write_i ; + psf->write_float = vox_write_f ; + psf->write_double = vox_write_d ; + } + else + { psf_log_printf (psf, "Header-less OKI Dialogic ADPCM encoded file.\n") ; + psf_log_printf (psf, "Setting up for 8kHz, mono, Vox ADPCM.\n") ; + + psf->read_short = vox_read_s ; + psf->read_int = vox_read_i ; + psf->read_float = vox_read_f ; + psf->read_double = vox_read_d ; + } ; + + /* Standard sample rate chennels etc. */ + if (psf->sf.samplerate < 1) + psf->sf.samplerate = 8000 ; + psf->sf.channels = 1 ; + + psf->sf.frames = psf->filelength * 2 ; + + psf->sf.seekable = SF_FALSE ; + + /* Seek back to start of data. */ + if (psf_fseek (psf, 0 , SEEK_SET) == -1) + return SFE_BAD_SEEK ; + + return 0 ; +} /* vox_adpcm_init */ + +/*------------------------------------------------------------------------------ +*/ + +static char +vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox) +{ short code ; + short diff, error, stepsize ; + + stepsize = step_size_table [pvox->step_index] ; + code = 0 ; + + diff = samp - pvox->last ; + if (diff < 0) + { code = 0x08 ; + error = -diff ; + } + else + error = diff ; + + if (error >= stepsize) + { code = code | 0x04 ; + error -= stepsize ; + } ; + + if (error >= stepsize / 2) + { code = code | 0x02 ; + error -= stepsize / 2 ; + } ; + + if (error >= stepsize / 4) + code = code | 0x01 ; + + /* + ** To close the feedback loop, the deocder is used to set the + ** estimate of last sample and in doing so, also set the step_index. + */ + pvox->last = vox_adpcm_decode (code, pvox) ; + + return code ; +} /* vox_adpcm_encode */ + +static short +vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox) +{ short diff, error, stepsize, samp ; + + stepsize = step_size_table [pvox->step_index] ; + + error = stepsize / 8 ; + + if (code & 0x01) + error += stepsize / 4 ; + + if (code & 0x02) + error += stepsize / 2 ; + + if (code & 0x04) + error += stepsize ; + + diff = (code & 0x08) ? -error : error ; + samp = pvox->last + diff ; + + /* + ** Apply clipping. + */ + if (samp > 2048) + samp = 2048 ; + if (samp < -2048) + samp = -2048 ; + + pvox->last = samp ; + pvox->step_index += step_adjust_table [code & 0x7] ; + + if (pvox->step_index < 0) + pvox->step_index = 0 ; + if (pvox->step_index > 48) + pvox->step_index = 48 ; + + return samp ; +} /* vox_adpcm_decode */ + +static int +vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox) +{ unsigned char code ; + int j, k ; + + /* If data_count is odd, add an extra zero valued sample. */ + if (pvox->pcm_samples & 1) + pvox->pcm_data [pvox->pcm_samples++] = 0 ; + + for (j = k = 0 ; k < pvox->pcm_samples ; j++) + { code = vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) << 4 ; + code |= vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) ; + pvox->vox_data [j] = code ; + } ; + + pvox->vox_bytes = j ; + + return 0 ; +} /* vox_adpcm_encode_block */ + +static int +vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox) +{ unsigned char code ; + int j, k ; + + for (j = k = 0 ; j < pvox->vox_bytes ; j++) + { code = pvox->vox_data [j] ; + pvox->pcm_data [k++] = 16 * vox_adpcm_decode ((code >> 4) & 0x0f, pvox) ; + pvox->pcm_data [k++] = 16 * vox_adpcm_decode (code & 0x0f, pvox) ; + } ; + + pvox->pcm_samples = k ; + + return 0 ; +} /* vox_adpcm_decode_block */ + +/*============================================================================== +*/ + +static int +vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) +{ int indx = 0, k ; + + while (indx < len) + { pvox->vox_bytes = (len - indx > PCM_DATA_LEN) ? VOX_DATA_LEN : (len - indx + 1) / 2 ; + + if ((k = psf_fread (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes) + { if (psf_ftell (psf) + k != psf->filelength) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ; + if (k == 0) + break ; + } ; + + pvox->vox_bytes = k ; + + vox_adpcm_decode_block (pvox) ; + + memcpy (&(ptr [indx]), pvox->pcm_data, pvox->pcm_samples * sizeof (short)) ; + indx += pvox->pcm_samples ; + } ; + + return indx ; +} /* vox_read_block */ + + +static sf_count_t +vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + int readcount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + while (len > 0) + { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = vox_read_block (psf, pvox, ptr, readcount) ; + + total += count ; + len -= count ; + if (count != readcount) + break ; + } ; + + return total ; +} /* vox_read_s */ + +static sf_count_t +vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + short *sptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; + count = vox_read_block (psf, pvox, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = ((int) sptr [k]) << 16 ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* vox_read_i */ + +static sf_count_t +vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + short *sptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; + count = vox_read_block (psf, pvox, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (float) (sptr [k]) ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* vox_read_f */ + +static sf_count_t +vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + short *sptr ; + int k, bufferlen, readcount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { readcount = (len >= bufferlen) ? bufferlen : (int) len ; + count = vox_read_block (psf, pvox, sptr, readcount) ; + for (k = 0 ; k < readcount ; k++) + ptr [total + k] = normfact * (double) (sptr [k]) ; + total += count ; + len -= readcount ; + if (count != readcount) + break ; + } ; + + return total ; +} /* vox_read_d */ + +/*------------------------------------------------------------------------------ +*/ + +static int +vox_write_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, const short *ptr, int len) +{ int indx = 0, k ; + + while (indx < len) + { pvox->pcm_samples = (len - indx > PCM_DATA_LEN) ? PCM_DATA_LEN : len - indx ; + + memcpy (pvox->pcm_data, &(ptr [indx]), pvox->pcm_samples * sizeof (short)) ; + + vox_adpcm_encode_block (pvox) ; + + if ((k = psf_fwrite (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes) + psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ; + + indx += pvox->pcm_samples ; + } ; + + return indx ; +} /* vox_write_block */ + +static sf_count_t +vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + int writecount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + while (len) + { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; + + count = vox_write_block (psf, pvox, ptr, writecount) ; + + total += count ; + len -= count ; + if (count != writecount) + break ; + } ; + + return total ; +} /* vox_write_s */ + +static sf_count_t +vox_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = ptr [total + k] >> 16 ; + count = vox_write_block (psf, pvox, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* vox_write_i */ + +static sf_count_t +vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + float normfact ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrintf (normfact * ptr [total + k]) ; + count = vox_write_block (psf, pvox, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* vox_write_f */ + +static sf_count_t +vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ VOX_ADPCM_PRIVATE *pvox ; + short *sptr ; + int k, bufferlen, writecount, count ; + sf_count_t total = 0 ; + double normfact ; + + if (! psf->codec_data) + return 0 ; + pvox = (VOX_ADPCM_PRIVATE*) psf->codec_data ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + sptr = psf->u.sbuf ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (len > 0) + { writecount = (len >= bufferlen) ? bufferlen : (int) len ; + for (k = 0 ; k < writecount ; k++) + sptr [k] = lrint (normfact * ptr [total + k]) ; + count = vox_write_block (psf, pvox, sptr, writecount) ; + total += count ; + len -= writecount ; + if (count != writecount) + break ; + } ; + + return total ; +} /* vox_write_d */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: e15e97fe-ff9d-4b46-a489-7059fb2d0b1e +*/ diff --git a/nylsf/w64.c b/nylsf/w64.c new file mode 100644 index 0000000..756b093 --- /dev/null +++ b/nylsf/w64.c @@ -0,0 +1,578 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "wav_w64.h" + +/*------------------------------------------------------------------------------ +** W64 files use 16 byte markers as opposed to the four byte marker of +** WAV files. +** For comparison purposes, an integer is required, so make an integer +** hash for the 16 bytes using MAKE_HASH16 macro, but also create a 16 +** byte array containing the complete 16 bytes required when writing the +** header. +*/ + +#define MAKE_HASH16(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf) \ + ( (x0) ^ ((x1) << 1) ^ ((x2) << 2) ^ ((x3) << 3) ^ \ + ((x4) << 4) ^ ((x5) << 5) ^ ((x6) << 6) ^ ((x7) << 7) ^ \ + ((x8) << 8) ^ ((x9) << 9) ^ ((xa) << 10) ^ ((xb) << 11) ^ \ + ((xc) << 12) ^ ((xd) << 13) ^ ((xe) << 14) ^ ((xf) << 15) ) + +#define MAKE_MARKER16(name,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf) \ + static unsigned char name [16] = { (x0), (x1), (x2), (x3), (x4), (x5), \ + (x6), (x7), (x8), (x9), (xa), (xb), (xc), (xd), (xe), (xf) } + +#define riff_HASH16 MAKE_HASH16 ('r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11, 0xA5, \ + 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00) + +#define wave_HASH16 MAKE_HASH16 ('w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11, \ + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) + +#define fmt_HASH16 MAKE_HASH16 ('f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11, \ + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) + +#define fact_HASH16 MAKE_HASH16 ('f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11, \ + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) + +#define data_HASH16 MAKE_HASH16 ('d', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11, \ + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) + +#define ACID_HASH16 MAKE_HASH16 (0x6D, 0x07, 0x1C, 0xEA, 0xA3, 0xEF, 0x78, 0x4C, \ + 0x90, 0x57, 0x7F, 0x79, 0xEE, 0x25, 0x2A, 0xAE) + +MAKE_MARKER16 (riff_MARKER16, 'r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11, + 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00) ; + + +MAKE_MARKER16 (wave_MARKER16, 'w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11, + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; + +MAKE_MARKER16 (fmt_MARKER16, 'f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11, + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; + +MAKE_MARKER16 (fact_MARKER16, 'f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11, + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; + +MAKE_MARKER16 (data_MARKER16, 'd', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11, + 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; + +enum +{ HAVE_riff = 0x01, + HAVE_wave = 0x02, + HAVE_fmt = 0x04, + HAVE_fact = 0x08, + HAVE_data = 0x20 +} ; + +/*------------------------------------------------------------------------------ + * Private static functions. + */ + +static int w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ; +static int w64_write_header (SF_PRIVATE *psf, int calc_length) ; +static int w64_close (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +w64_open (SF_PRIVATE *psf) +{ int subformat, error, blockalign = 0, framesperblock = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR &&psf->filelength > 0)) + { if ((error = w64_read_header (psf, &blockalign, &framesperblock))) + return error ; + } ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_W64) + return SFE_BAD_OPEN_FORMAT ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + psf->endian = SF_ENDIAN_LITTLE ; /* All W64 files are little endian. */ + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) + { blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; + framesperblock = -1 ; + + /* FIXME : This block must go */ + psf->filelength = SF_COUNT_MAX ; + psf->datalength = psf->filelength ; + if (psf->sf.frames <= 0) + psf->sf.frames = (psf->blockwidth) ? psf->filelength / psf->blockwidth : psf->filelength ; + /* EMXIF : This block must go */ + } ; + + if ((error = w64_write_header (psf, SF_FALSE))) + return error ; + + psf->write_header = w64_write_header ; + } ; + + psf->container_close = w64_close ; + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + + case SF_FORMAT_IMA_ADPCM : + error = wav_w64_ima_init (psf, blockalign, framesperblock) ; + break ; + + case SF_FORMAT_MS_ADPCM : + error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ; + break ; + /* Lite remove end */ + + case SF_FORMAT_GSM610 : + error = gsm610_init (psf) ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + return error ; +} /* w64_open */ + +/*========================================================================= +** Private functions. +*/ + +static int +w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) +{ WAV_FMT wav_fmt ; + int dword = 0, marker, format = 0 ; + sf_count_t chunk_size, bytesread = 0 ; + int parsestage = 0, error, done = 0 ; + + /* Set position to start of file to begin reading header. */ + memset (&wav_fmt, 0, sizeof (wav_fmt)) ; + psf_binheader_readf (psf, "p", 0) ; + + while (! done) + { /* Read the 4 byte marker and jump 12 bytes. */ + bytesread += psf_binheader_readf (psf, "h", &marker) ; + chunk_size = 0 ; + + switch (marker) + { case riff_HASH16 : + if (parsestage) + return SFE_W64_NO_RIFF ; + + bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; + + if (psf->filelength < chunk_size) + psf_log_printf (psf, "riff : %D (should be %D)\n", chunk_size, psf->filelength) ; + else + psf_log_printf (psf, "riff : %D\n", chunk_size) ; + + parsestage |= HAVE_riff ; + break ; + + case ACID_HASH16: + psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ; + return SFE_UNIMPLEMENTED ; + + case wave_HASH16 : + if ((parsestage & HAVE_riff) != HAVE_riff) + return SFE_W64_NO_WAVE ; + psf_log_printf (psf, "wave\n") ; + parsestage |= HAVE_wave ; + break ; + + case fmt_HASH16 : + if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave)) + return SFE_W64_NO_FMT ; + + bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; + psf_log_printf (psf, " fmt : %D\n", chunk_size) ; + + /* size of 16 byte marker and 8 byte chunk_size value. */ + chunk_size -= 24 ; + + if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, (int) chunk_size))) + return error ; + + if (chunk_size % 8) + psf_binheader_readf (psf, "j", 8 - (chunk_size % 8)) ; + + format = wav_fmt.format ; + parsestage |= HAVE_fmt ; + break ; + + case fact_HASH16: + { sf_count_t frames ; + + psf_binheader_readf (psf, "e88", &chunk_size, &frames) ; + psf_log_printf (psf, " fact : %D\n frames : %D\n", + chunk_size, frames) ; + } ; + break ; + + + case data_HASH16 : + if ((parsestage & (HAVE_riff | HAVE_wave | HAVE_fmt)) != (HAVE_riff | HAVE_wave | HAVE_fmt)) + return SFE_W64_NO_DATA ; + + psf_binheader_readf (psf, "e8", &chunk_size) ; + + psf->dataoffset = psf_ftell (psf) ; + + psf->datalength = chunk_size - 24 ; + + if (chunk_size % 8) + chunk_size += 8 - (chunk_size % 8) ; + + psf_log_printf (psf, "data : %D\n", chunk_size) ; + + parsestage |= HAVE_data ; + + if (! psf->sf.seekable) + break ; + + /* Seek past data and continue reading header. */ + psf_fseek (psf, chunk_size, SEEK_CUR) ; + break ; + + default : + if (psf_ftell (psf) & 0x0F) + { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ; + psf_binheader_readf (psf, "j", -3) ; + break ; + } ; + psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ; + done = SF_TRUE ; + break ; + } ; /* switch (dword) */ + + if (psf->sf.seekable == 0 && (parsestage & HAVE_data)) + break ; + + if (psf_ftell (psf) >= (psf->filelength - (2 * SIGNED_SIZEOF (dword)))) + break ; + } ; /* while (1) */ + + if (! psf->dataoffset) + return SFE_W64_NO_DATA ; + + psf->endian = SF_ENDIAN_LITTLE ; /* All WAV files are little endian. */ + + if (psf_ftell (psf) != psf->dataoffset) + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + + if (psf->blockwidth) + { if (psf->filelength - psf->dataoffset < psf->datalength) + psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; + else + psf->sf.frames = psf->datalength / psf->blockwidth ; + } ; + + switch (format) + { case WAVE_FORMAT_PCM : + case WAVE_FORMAT_EXTENSIBLE : + /* extensible might be FLOAT, MULAW, etc as well! */ + psf->sf.format = SF_FORMAT_W64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ; + break ; + + case WAVE_FORMAT_MULAW : + psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ULAW) ; + break ; + + case WAVE_FORMAT_ALAW : + psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ALAW) ; + break ; + + case WAVE_FORMAT_MS_ADPCM : + psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM) ; + *blockalign = wav_fmt.msadpcm.blockalign ; + *framesperblock = wav_fmt.msadpcm.samplesperblock ; + break ; + + case WAVE_FORMAT_IMA_ADPCM : + psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM) ; + *blockalign = wav_fmt.ima.blockalign ; + *framesperblock = wav_fmt.ima.samplesperblock ; + break ; + + case WAVE_FORMAT_GSM610 : + psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_GSM610) ; + break ; + + case WAVE_FORMAT_IEEE_FLOAT : + psf->sf.format = SF_FORMAT_W64 ; + psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + return 0 ; +} /* w64_read_header */ + +static int +w64_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t fmt_size, current ; + size_t fmt_pad = 0 ; + int subformat, add_fact_chunk = SF_FALSE ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->bytewidth) + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* riff marker, length, wave and 'fmt ' markers. */ + psf_binheader_writef (psf, "eh8hh", riff_MARKER16, psf->filelength - 8, wave_MARKER16, fmt_MARKER16) ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; + fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; + fmt_size += fmt_pad ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; + break ; + + case SF_FORMAT_FLOAT : + case SF_FORMAT_DOUBLE : + fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; + fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; + fmt_size += fmt_pad ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; + + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_ULAW : + fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; + fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; + fmt_size += fmt_pad ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; + + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_ALAW : + fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; + fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; + fmt_size += fmt_pad ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; + + add_fact_chunk = SF_TRUE ; + break ; + + /* Lite remove start */ + case SF_FORMAT_IMA_ADPCM : + { int blockalign, framesperblock, bytespersec ; + + blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; + framesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; + bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; + + /* fmt chunk. */ + fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; + fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; + fmt_size += fmt_pad ; + + /* fmt : size, WAV format type, channels. */ + psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels) ; + + /* fmt : samplerate, bytespersec. */ + psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; + + /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ + psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ; + } ; + + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_MS_ADPCM : + { int blockalign, framesperblock, bytespersec, extrabytes ; + + blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; + framesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; + bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; + + /* fmt chunk. */ + extrabytes = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ; + fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ; + fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; + fmt_size += fmt_pad ; + + /* fmt : size, W64 format type, channels. */ + psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ; + + /* fmt : samplerate, bytespersec. */ + psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; + + /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ + psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ; + + msadpcm_write_adapt_coeffs (psf) ; + } ; + + add_fact_chunk = SF_TRUE ; + break ; + /* Lite remove end */ + + case SF_FORMAT_GSM610 : + { int bytespersec ; + + bytespersec = (psf->sf.samplerate * WAV_W64_GSM610_BLOCKSIZE) / WAV_W64_GSM610_SAMPLES ; + + /* fmt chunk. */ + fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; + fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; + fmt_size += fmt_pad ; + + /* fmt : size, WAV format type, channels. */ + psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ; + + /* fmt : samplerate, bytespersec. */ + psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; + + /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ + psf_binheader_writef (psf, "e2222", WAV_W64_GSM610_BLOCKSIZE, 0, 2, WAV_W64_GSM610_SAMPLES) ; + } ; + + add_fact_chunk = SF_TRUE ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + /* Pad to 8 bytes with zeros. */ + if (fmt_pad > 0) + psf_binheader_writef (psf, "z", fmt_pad) ; + + if (add_fact_chunk) + psf_binheader_writef (psf, "eh88", fact_MARKER16, (sf_count_t) (16 + 8 + 8), psf->sf.frames) ; + + psf_binheader_writef (psf, "eh8", data_MARKER16, psf->datalength + 24) ; + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* w64_write_header */ + +static int +w64_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + w64_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* w64_close */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 9aa4e141-538a-4dd9-99c9-b3f0f2dd4f4a +*/ diff --git a/nylsf/wav.c b/nylsf/wav.c new file mode 100644 index 0000000..92e7a5c --- /dev/null +++ b/nylsf/wav.c @@ -0,0 +1,1633 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** Copyright (C) 2004-2005 David Viens +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "wav_w64.h" + +/*------------------------------------------------------------------------------ + * Macros to handle big/little endian issues. + */ + +#define RIFF_MARKER (MAKE_MARKER ('R', 'I', 'F', 'F')) +#define RIFX_MARKER (MAKE_MARKER ('R', 'I', 'F', 'X')) +#define WAVE_MARKER (MAKE_MARKER ('W', 'A', 'V', 'E')) +#define fmt_MARKER (MAKE_MARKER ('f', 'm', 't', ' ')) +#define data_MARKER (MAKE_MARKER ('d', 'a', 't', 'a')) +#define fact_MARKER (MAKE_MARKER ('f', 'a', 'c', 't')) +#define PEAK_MARKER (MAKE_MARKER ('P', 'E', 'A', 'K')) + +#define cue_MARKER (MAKE_MARKER ('c', 'u', 'e', ' ')) +#define LIST_MARKER (MAKE_MARKER ('L', 'I', 'S', 'T')) +#define slnt_MARKER (MAKE_MARKER ('s', 'l', 'n', 't')) +#define wavl_MARKER (MAKE_MARKER ('w', 'a', 'v', 'l')) +#define INFO_MARKER (MAKE_MARKER ('I', 'N', 'F', 'O')) +#define plst_MARKER (MAKE_MARKER ('p', 'l', 's', 't')) +#define adtl_MARKER (MAKE_MARKER ('a', 'd', 't', 'l')) +#define labl_MARKER (MAKE_MARKER ('l', 'a', 'b', 'l')) +#define ltxt_MARKER (MAKE_MARKER ('l', 't', 'x', 't')) +#define note_MARKER (MAKE_MARKER ('n', 'o', 't', 'e')) +#define smpl_MARKER (MAKE_MARKER ('s', 'm', 'p', 'l')) +#define bext_MARKER (MAKE_MARKER ('b', 'e', 'x', 't')) +#define levl_MARKER (MAKE_MARKER ('l', 'e', 'v', 'l')) +#define MEXT_MARKER (MAKE_MARKER ('M', 'E', 'X', 'T')) +#define DISP_MARKER (MAKE_MARKER ('D', 'I', 'S', 'P')) +#define acid_MARKER (MAKE_MARKER ('a', 'c', 'i', 'd')) +#define strc_MARKER (MAKE_MARKER ('s', 't', 'r', 'c')) +#define PAD_MARKER (MAKE_MARKER ('P', 'A', 'D', ' ')) +#define afsp_MARKER (MAKE_MARKER ('a', 'f', 's', 'p')) +#define clm_MARKER (MAKE_MARKER ('c', 'l', 'm', ' ')) +#define elmo_MARKER (MAKE_MARKER ('e', 'l', 'm', 'o')) + +#define ISFT_MARKER (MAKE_MARKER ('I', 'S', 'F', 'T')) +#define ICRD_MARKER (MAKE_MARKER ('I', 'C', 'R', 'D')) +#define ICOP_MARKER (MAKE_MARKER ('I', 'C', 'O', 'P')) +#define IARL_MARKER (MAKE_MARKER ('I', 'A', 'R', 'L')) +#define IART_MARKER (MAKE_MARKER ('I', 'A', 'R', 'T')) +#define INAM_MARKER (MAKE_MARKER ('I', 'N', 'A', 'M')) +#define IENG_MARKER (MAKE_MARKER ('I', 'E', 'N', 'G')) +#define IART_MARKER (MAKE_MARKER ('I', 'A', 'R', 'T')) +#define ICOP_MARKER (MAKE_MARKER ('I', 'C', 'O', 'P')) +#define IPRD_MARKER (MAKE_MARKER ('I', 'P', 'R', 'D')) +#define ISRC_MARKER (MAKE_MARKER ('I', 'S', 'R', 'C')) +#define ISBJ_MARKER (MAKE_MARKER ('I', 'S', 'B', 'J')) +#define ICMT_MARKER (MAKE_MARKER ('I', 'C', 'M', 'T')) + +/* Weird WAVPACK marker which can show up at the start of the DATA section. */ +#define wvpk_MARKER (MAKE_MARKER ('w', 'v', 'p', 'k')) +#define OggS_MARKER (MAKE_MARKER ('O', 'g', 'g', 'S')) + +#define WAV_PEAK_CHUNK_SIZE(ch) (2 * sizeof (int) + ch * (sizeof (float) + sizeof (int))) +#define WAV_BEXT_CHUNK_SIZE 602 + +enum +{ HAVE_RIFF = 0x01, + HAVE_WAVE = 0x02, + HAVE_fmt = 0x04, + HAVE_fact = 0x08, + HAVE_PEAK = 0x10, + HAVE_data = 0x20, + HAVE_other = 0x80000000 +} ; + + + +/* known WAVEFORMATEXTENSIBLE GUIDS */ +static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM = +{ 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM = +{ 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT = +{ 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW = +{ 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW = +{ 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +/* +** the next two are from +** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html +*/ +static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM = +{ 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT = +{ 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } +} ; + + +#if 0 +/* maybe interesting one day to read the following through sf_read_raw */ +/* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */ +static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX = +{ 0x8312B9C2, 0x2E6E, 0x11d4, { 0xA8, 0x24, 0xDE, 0x5B, 0x96, 0xC3, 0xAB, 0x21 } +} ; +#endif + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ; +static int wav_write_header (SF_PRIVATE *psf, int calc_length) ; + +static int wavex_write_header (SF_PRIVATE *psf, int calc_length) ; + +static int wav_write_tailer (SF_PRIVATE *psf) ; +static void wav_write_strings (SF_PRIVATE *psf, int location) ; +static int wav_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; +static int wav_close (SF_PRIVATE *psf) ; + +static int wav_subchunk_parse (SF_PRIVATE *psf, int chunk) ; +static int wav_read_smpl_chunk (SF_PRIVATE *psf, unsigned int chunklen) ; +static int wav_read_acid_chunk (SF_PRIVATE *psf, unsigned int chunklen) ; +static int wav_read_bext_chunk (SF_PRIVATE *psf, unsigned int chunklen) ; +static int wav_write_bext_chunk (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +wav_open (SF_PRIVATE *psf) +{ int format, subformat, error, blockalign = 0, framesperblock = 0 ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = wav_read_header (psf, &blockalign, &framesperblock))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + format = psf->sf.format & SF_FORMAT_TYPEMASK ; + if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX) + return SFE_BAD_OPEN_FORMAT ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + /* RIFF WAVs are little-endian, RIFX WAVs are big-endian, default to little */ + psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; + if (CPU_IS_BIG_ENDIAN && psf->endian == SF_ENDIAN_CPU) + psf->endian = SF_ENDIAN_BIG ; + else if (psf->endian != SF_ENDIAN_BIG) + psf->endian = SF_ENDIAN_LITTLE ; + + if (psf->mode != SFM_RDWR || psf->filelength < 44) + { psf->filelength = 0 ; + psf->datalength = 0 ; + psf->dataoffset = 0 ; + psf->sf.frames = 0 ; + } ; + + if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) + { blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; + framesperblock = -1 ; /* Corrected later. */ + } ; + + psf->str_flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; + + /* By default, add the peak chunk to floating point files. Default behaviour + ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE). + */ + if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) + { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + psf->peak_info->peak_loc = SF_PEAK_START ; + } ; + + psf->write_header = (format == SF_FORMAT_WAV) ? wav_write_header : wavex_write_header ; + } ; + + psf->container_close = wav_close ; + psf->command = wav_command ; + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + + case SF_FORMAT_IMA_ADPCM : + error = wav_w64_ima_init (psf, blockalign, framesperblock) ; + break ; + + case SF_FORMAT_MS_ADPCM : + error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ; + break ; + + case SF_FORMAT_G721_32 : + error = g72x_init (psf) ; + break ; + /* Lite remove end */ + + case SF_FORMAT_GSM610 : + error = gsm610_init (psf) ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + if (psf->mode == SFM_WRITE || (psf->mode == SFM_RDWR && psf->filelength == 0)) + return psf->write_header (psf, SF_FALSE) ; + + return error ; +} /* wav_open */ + +/*========================================================================= +** Private functions. +*/ + +static int +wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) +{ WAV_FMT wav_fmt ; + FACT_CHUNK fact_chunk ; + unsigned dword = 0, marker, RIFFsize, done = 0 ; + int parsestage = 0, error, format = 0 ; + char *cptr ; + + memset (&wav_fmt, 0, sizeof (wav_fmt)) ; + /* Set position to start of file to begin reading header. */ + psf_binheader_readf (psf, "p", 0) ; + + while (! done) + { psf_binheader_readf (psf, "m", &marker) ; + + switch (marker) + { case RIFF_MARKER : + case RIFX_MARKER : + if (parsestage) + return SFE_WAV_NO_RIFF ; + + parsestage |= HAVE_RIFF ; + + /* RIFX signifies big-endian format for all header and data + ** to prevent lots of code copying here, we'll set the psf->rwf_endian + ** flag once here, and never specify endian-ness for all other header ops + */ + if (marker == RIFF_MARKER) + psf->rwf_endian = SF_ENDIAN_LITTLE ; + else + psf->rwf_endian = SF_ENDIAN_BIG ; + + psf_binheader_readf (psf, "4", &RIFFsize) ; + + if (psf->fileoffset > 0 && psf->filelength > RIFFsize + 8) + { /* Set file length. */ + psf->filelength = RIFFsize + 8 ; + if (marker == RIFF_MARKER) + psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ; + else + psf_log_printf (psf, "RIFX : %u\n", RIFFsize) ; + } + else if (psf->filelength < RIFFsize + 2 * SIGNED_SIZEOF (dword)) + { if (marker == RIFF_MARKER) + psf_log_printf (psf, "RIFF : %u (should be %D)\n", RIFFsize, psf->filelength - 2 * SIGNED_SIZEOF (dword)) ; + else + psf_log_printf (psf, "RIFX : %u (should be %D)\n", RIFFsize, psf->filelength - 2 * SIGNED_SIZEOF (dword)) ; + + RIFFsize = dword ; + } + else + { if (marker == RIFF_MARKER) + psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ; + else + psf_log_printf (psf, "RIFX : %u\n", RIFFsize) ; + } ; + break ; + + case WAVE_MARKER : + if ((parsestage & HAVE_RIFF) != HAVE_RIFF) + return SFE_WAV_NO_WAVE ; + parsestage |= HAVE_WAVE ; + + psf_log_printf (psf, "WAVE\n") ; + break ; + + case fmt_MARKER : + if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE)) + return SFE_WAV_NO_FMT ; + + /* If this file has a SECOND fmt chunk, I don't want to know about it. */ + if (parsestage & HAVE_fmt) + break ; + + parsestage |= HAVE_fmt ; + + psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, "fmt : %d\n", dword) ; + + if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, dword))) + return error ; + + format = wav_fmt.format ; + break ; + + case data_MARKER : + if ((parsestage & (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) + return SFE_WAV_NO_DATA ; + + if (psf->mode == SFM_RDWR && (parsestage & HAVE_other) != 0) + return SFE_RDWR_BAD_HEADER ; + + parsestage |= HAVE_data ; + + psf_binheader_readf (psf, "4", &dword) ; + + psf->datalength = dword ; + psf->dataoffset = psf_ftell (psf) ; + + if (dword == 0 && RIFFsize == 8 && psf->filelength > 44) + { psf_log_printf (psf, "*** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ; + psf->datalength = dword = psf->filelength - psf->dataoffset ; + } ; + + if (psf->datalength > psf->filelength - psf->dataoffset) + { psf_log_printf (psf, "data : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ; + psf->datalength = psf->filelength - psf->dataoffset ; + } + else + psf_log_printf (psf, "data : %D\n", psf->datalength) ; + + /* Only set dataend if there really is data at the end. */ + if (psf->datalength + psf->dataoffset < psf->filelength) + psf->dataend = psf->datalength + psf->dataoffset ; + + if (format == WAVE_FORMAT_MS_ADPCM && psf->datalength % 2) + { psf->datalength ++ ; + psf_log_printf (psf, "*** Data length odd. Increasing it by 1.\n") ; + } ; + + if (! psf->sf.seekable) + break ; + + /* Seek past data and continue reading header. */ + psf_fseek (psf, psf->datalength, SEEK_CUR) ; + + dword = psf_ftell (psf) ; + if (dword != (sf_count_t) (psf->dataoffset + psf->datalength)) + psf_log_printf (psf, "*** psf_fseek past end error ***\n", dword, psf->dataoffset + psf->datalength) ; + break ; + + case fact_MARKER : + if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE)) + return SFE_WAV_BAD_FACT ; + + parsestage |= HAVE_fact ; + + if ((parsestage & HAVE_fmt) != HAVE_fmt) + psf_log_printf (psf, "*** Should have 'fmt ' chunk before 'fact'\n") ; + + psf_binheader_readf (psf, "44", &dword, & (fact_chunk.frames)) ; + + if (dword > SIGNED_SIZEOF (fact_chunk)) + psf_binheader_readf (psf, "j", (int) (dword - SIGNED_SIZEOF (fact_chunk))) ; + + if (dword) + psf_log_printf (psf, "%M : %d\n", marker, dword) ; + else + psf_log_printf (psf, "%M : %d (should not be zero)\n", marker, dword) ; + + psf_log_printf (psf, " frames : %d\n", fact_chunk.frames) ; + break ; + + case PEAK_MARKER : + if ((parsestage & (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) + return SFE_WAV_PEAK_B4_FMT ; + + parsestage |= HAVE_PEAK ; + + psf_binheader_readf (psf, "4", &dword) ; + + psf_log_printf (psf, "%M : %d\n", marker, dword) ; + if (dword != WAV_PEAK_CHUNK_SIZE (psf->sf.channels)) + { psf_binheader_readf (psf, "j", dword) ; + psf_log_printf (psf, "*** File PEAK chunk size doesn't fit with number of channels (%d).\n", psf->sf.channels) ; + return SFE_WAV_BAD_PEAK ; + } ; + + if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + + /* read in rest of PEAK chunk. */ + psf_binheader_readf (psf, "44", & (psf->peak_info->version), & (psf->peak_info->timestamp)) ; + + if (psf->peak_info->version != 1) + psf_log_printf (psf, " version : %d *** (should be version 1)\n", psf->peak_info->version) ; + else + psf_log_printf (psf, " version : %d\n", psf->peak_info->version) ; + + psf_log_printf (psf, " time stamp : %d\n", psf->peak_info->timestamp) ; + psf_log_printf (psf, " Ch Position Value\n") ; + + cptr = psf->u.cbuf ; + for (dword = 0 ; dword < (unsigned) psf->sf.channels ; dword++) + { float value ; + unsigned int position ; + psf_binheader_readf (psf, "f4", &value, &position) ; + psf->peak_info->peaks [dword].value = value ; + psf->peak_info->peaks [dword].position = position ; + + LSF_SNPRINTF (cptr, sizeof (psf->u.cbuf), " %2d %-12ld %g\n", + dword, (long) psf->peak_info->peaks [dword].position, psf->peak_info->peaks [dword].value) ; + cptr [sizeof (psf->u.cbuf) - 1] = 0 ; + psf_log_printf (psf, cptr) ; + } ; + + psf->peak_info->peak_loc = ((parsestage & HAVE_data) == 0) ? SF_PEAK_START : SF_PEAK_END ; + break ; + + case cue_MARKER : + parsestage |= HAVE_other ; + + { unsigned bytesread, cue_count ; + int id, position, chunk_id, chunk_start, block_start, offset ; + + bytesread = psf_binheader_readf (psf, "44", &dword, &cue_count) ; + bytesread -= 4 ; /* Remove bytes for first dword. */ + psf_log_printf (psf, "%M : %u\n", marker, dword) ; + + if (cue_count > 10) + { psf_log_printf (psf, " Count : %d (skipping)\n", cue_count) ; + psf_binheader_readf (psf, "j", cue_count * 24) ; + break ; + } ; + + psf_log_printf (psf, " Count : %d\n", cue_count) ; + + while (cue_count) + { bytesread += psf_binheader_readf (psf, "444444", &id, &position, + &chunk_id, &chunk_start, &block_start, &offset) ; + psf_log_printf (psf, " Cue ID : %2d" + " Pos : %5u Chunk : %M" + " Chk Start : %d Blk Start : %d" + " Offset : %5d\n", + id, position, chunk_id, chunk_start, block_start, offset) ; + cue_count -- ; + } ; + + if (bytesread != dword) + { psf_log_printf (psf, "**** Chunk size weirdness (%d != %d)\n", dword, bytesread) ; + psf_binheader_readf (psf, "j", dword - bytesread) ; + } ; + } ; + break ; + + case smpl_MARKER : + parsestage |= HAVE_other ; + + psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, "smpl : %u\n", dword) ; + + if ((error = wav_read_smpl_chunk (psf, dword))) + return error ; + break ; + + case acid_MARKER : + parsestage |= HAVE_other ; + + psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, "acid : %u\n", dword) ; + + if ((error = wav_read_acid_chunk (psf, dword))) + return error ; + break ; + + case INFO_MARKER : + case LIST_MARKER : + parsestage |= HAVE_other ; + + if ((error = wav_subchunk_parse (psf, marker)) != 0) + return error ; + break ; + + case bext_MARKER : + parsestage |= HAVE_other ; + + psf_binheader_readf (psf, "4", &dword) ; + if (dword < WAV_BEXT_CHUNK_SIZE) + psf_log_printf (psf, "bext : %u (should be >= %d)\n", dword, WAV_BEXT_CHUNK_SIZE) ; + else + psf_log_printf (psf, "bext : %u\n", dword) ; + + if ((error = wav_read_bext_chunk (psf, dword))) + return error ; + break ; + + case strc_MARKER : /* Multiple of 32 bytes. */ + + case afsp_MARKER : + case clm_MARKER : + case elmo_MARKER : + case levl_MARKER : + case plst_MARKER : + case DISP_MARKER : + case MEXT_MARKER : + case PAD_MARKER : + parsestage |= HAVE_other ; + + psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, "%M : %u\n", marker, dword) ; + dword += (dword & 1) ; + psf_binheader_readf (psf, "j", dword) ; + break ; + + default : + parsestage |= HAVE_other ; + if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF) + && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) + { psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, "*** %M : %d (unknown marker)\n", marker, dword) ; + psf_binheader_readf (psf, "j", dword) ; + break ; + } ; + if (psf_ftell (psf) & 0x03) + { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ; + psf_binheader_readf (psf, "j", -3) ; + break ; + } ; + psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D. Exiting parser.\n", marker, psf_ftell (psf) - 4) ; + done = SF_TRUE ; + break ; + } ; /* switch (dword) */ + + if (! psf->sf.seekable && (parsestage & HAVE_data)) + break ; + + if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (dword)) + { psf_log_printf (psf, "End\n") ; + break ; + } ; + } ; /* while (1) */ + + if (! psf->dataoffset) + return SFE_WAV_NO_DATA ; + + /* WAVs can be little or big endian */ + psf->endian = psf->rwf_endian ; + + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + + if (psf->is_pipe == 0) + { /* + ** Check for 'wvpk' at the start of the DATA section. Not able to + ** handle this. + */ + psf_binheader_readf (psf, "4", &marker) ; + if (marker == wvpk_MARKER || marker == OggS_MARKER) + return SFE_WAV_WVPK_DATA ; + } ; + + /* Seek to start of DATA section. */ + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + + if (psf->blockwidth) + { if (psf->filelength - psf->dataoffset < psf->datalength) + psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; + else + psf->sf.frames = psf->datalength / psf->blockwidth ; + } ; + + switch (format) + { case WAVE_FORMAT_EXTENSIBLE : + if (psf->sf.format == (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM)) + { *blockalign = wav_fmt.msadpcm.blockalign ; + *framesperblock = wav_fmt.msadpcm.samplesperblock ; + } ; + break ; + + case WAVE_FORMAT_PCM : + psf->sf.format = SF_FORMAT_WAV | u_bitwidth_to_subformat (psf->bytewidth * 8) ; + break ; + + case WAVE_FORMAT_MULAW : + case IBM_FORMAT_MULAW : + psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ULAW) ; + break ; + + case WAVE_FORMAT_ALAW : + case IBM_FORMAT_ALAW : + psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ALAW) ; + break ; + + case WAVE_FORMAT_MS_ADPCM : + psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM) ; + *blockalign = wav_fmt.msadpcm.blockalign ; + *framesperblock = wav_fmt.msadpcm.samplesperblock ; + break ; + + case WAVE_FORMAT_IMA_ADPCM : + psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM) ; + *blockalign = wav_fmt.ima.blockalign ; + *framesperblock = wav_fmt.ima.samplesperblock ; + break ; + + case WAVE_FORMAT_GSM610 : + psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_GSM610) ; + break ; + + case WAVE_FORMAT_IEEE_FLOAT : + psf->sf.format = SF_FORMAT_WAV ; + psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ; + break ; + + case WAVE_FORMAT_G721_ADPCM : + psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_G721_32 ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + /* Only set the format endian-ness if its non-standard big-endian. */ + if (psf->endian == SF_ENDIAN_BIG) + psf->sf.format |= SF_ENDIAN_BIG ; + + return 0 ; +} /* wav_read_header */ + +static int +wav_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + int fmt_size, k, subformat, add_fact_chunk = SF_FALSE ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* + ** RIFX signifies big-endian format for all header and data. + ** To prevent lots of code copying here, we'll set the psf->rwf_endian flag + ** once here, and never specify endian-ness for all other header operations. + */ + + /* RIFF/RIFX marker, length, WAVE and 'fmt ' markers. */ + + if (psf->endian == SF_ENDIAN_LITTLE) + psf_binheader_writef (psf, "etm8", RIFF_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8) ; + else + psf_binheader_writef (psf, "Etm8", RIFX_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8) ; + + /* WAVE and 'fmt ' markers. */ + psf_binheader_writef (psf, "mm", WAVE_MARKER, fmt_MARKER) ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; + break ; + + case SF_FORMAT_FLOAT : + case SF_FORMAT_DOUBLE : + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; + + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_ULAW : + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, 8) ; + + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_ALAW : + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, 8) ; + + add_fact_chunk = SF_TRUE ; + break ; + + /* Lite remove start */ + case SF_FORMAT_IMA_ADPCM : + { int blockalign, framesperblock, bytespersec ; + + blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; + framesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; + bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; + + /* fmt chunk. */ + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; + + /* fmt : size, WAV format type, channels, samplerate, bytespersec */ + psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_IMA_ADPCM, + psf->sf.channels, psf->sf.samplerate, bytespersec) ; + + /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ + psf_binheader_writef (psf, "2222", blockalign, 4, 2, framesperblock) ; + } ; + + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_MS_ADPCM : + { int blockalign, framesperblock, bytespersec, extrabytes ; + + blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; + framesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; + bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; + + /* fmt chunk. */ + extrabytes = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ; + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ; + + /* fmt : size, WAV format type, channels. */ + psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ; + + /* fmt : samplerate, bytespersec. */ + psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ; + + /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ + psf_binheader_writef (psf, "22222", blockalign, 4, extrabytes, framesperblock, 7) ; + + msadpcm_write_adapt_coeffs (psf) ; + } ; + + add_fact_chunk = SF_TRUE ; + break ; + + + case SF_FORMAT_G721_32 : + /* fmt chunk. */ + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; + + /* fmt : size, WAV format type, channels, samplerate, bytespersec */ + psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_G721_ADPCM, + psf->sf.channels, psf->sf.samplerate, psf->sf.samplerate * psf->sf.channels / 2) ; + + /* fmt : blockalign, bitwidth, extrabytes, auxblocksize. */ + psf_binheader_writef (psf, "2222", 64, 4, 2, 0) ; + + add_fact_chunk = SF_TRUE ; + break ; + + /* Lite remove end */ + + case SF_FORMAT_GSM610 : + { int blockalign, framesperblock, bytespersec ; + + blockalign = WAV_W64_GSM610_BLOCKSIZE ; + framesperblock = WAV_W64_GSM610_SAMPLES ; + bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; + + /* fmt chunk. */ + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; + + /* fmt : size, WAV format type, channels. */ + psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ; + + /* fmt : samplerate, bytespersec. */ + psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ; + + /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ + psf_binheader_writef (psf, "2222", blockalign, 0, 2, framesperblock) ; + } ; + + add_fact_chunk = SF_TRUE ; + break ; + + default : return SFE_UNIMPLEMENTED ; + } ; + + if (add_fact_chunk) + psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ; + + if (psf->str_flags & SF_STR_LOCATE_START) + wav_write_strings (psf, SF_STR_LOCATE_START) ; + + if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START) + { psf_binheader_writef (psf, "m4", PEAK_MARKER, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)) ; + psf_binheader_writef (psf, "44", 1, time (NULL)) ; + for (k = 0 ; k < psf->sf.channels ; k++) + psf_binheader_writef (psf, "ft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; + } ; + + if (psf->broadcast_info != NULL) + wav_write_bext_chunk (psf) ; + + if (psf->instrument != NULL) + { int tmp ; + double dtune = (double) (0x40000000) / 25.0 ; + + psf_binheader_writef (psf, "m4", smpl_MARKER, 9 * 4 + psf->instrument->loop_count * 6 * 4) ; + psf_binheader_writef (psf, "44", 0, 0) ; /* Manufacturer zero is everyone */ + tmp = (int) (1.0e9 / psf->sf.samplerate) ; /* Sample period in nano seconds */ + psf_binheader_writef (psf, "44", tmp, psf->instrument->basenote) ; + tmp = (unsigned int) (psf->instrument->detune * dtune + 0.5) ; + psf_binheader_writef (psf, "4", tmp) ; + psf_binheader_writef (psf, "44", 0, 0) ; /* SMTPE format */ + psf_binheader_writef (psf, "44", psf->instrument->loop_count, 0) ; + + for (tmp = 0 ; tmp < psf->instrument->loop_count ; tmp++) + { int type ; + + type = psf->instrument->loops [tmp].mode ; + type = (type == SF_LOOP_FORWARD ? 0 : type==SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ; + + psf_binheader_writef (psf, "44", tmp, type) ; + psf_binheader_writef (psf, "44", psf->instrument->loops [tmp].start, psf->instrument->loops [tmp].end) ; + psf_binheader_writef (psf, "44", 0, psf->instrument->loops [tmp].count) ; + } ; + } ; + + psf_binheader_writef (psf, "tm8", data_MARKER, psf->datalength) ; + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current < psf->dataoffset) + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + else if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* wav_write_header */ + + + +static int +wavex_write_header (SF_PRIVATE *psf, int calc_length) +{ sf_count_t current ; + int fmt_size, k, subformat, add_fact_chunk = SF_FALSE ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* RIFX signifies big-endian format for all header and data + ** to prevent lots of code copying here, we'll set the psf->rwf_endian + ** flag once here, and never specify endian-ness for all other header ops + */ + + /* RIFF marker, length, WAVE and 'fmt ' markers. */ + + if (psf->endian == SF_ENDIAN_LITTLE) + { if (psf->filelength < 8) + psf_binheader_writef (psf, "tm8", RIFF_MARKER, 8) ; + else + psf_binheader_writef (psf, "tm8", RIFF_MARKER, psf->filelength - 8) ; + } + else + { if (psf->filelength < 8) + psf_binheader_writef (psf, "Etm8", RIFX_MARKER, 8) ; + else + psf_binheader_writef (psf, "Etm8", RIFX_MARKER, psf->filelength - 8) ; + } ; + + /* WAVE and 'fmt ' markers. */ + psf_binheader_writef (psf, "mm", WAVE_MARKER, fmt_MARKER) ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + /* initial section (same for all, it appears) */ + switch (subformat) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + case SF_FORMAT_FLOAT : + case SF_FORMAT_DOUBLE : + case SF_FORMAT_ULAW : + case SF_FORMAT_ALAW : + fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ; + + /* fmt : format, channels, samplerate */ + psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_EXTENSIBLE, psf->sf.channels, psf->sf.samplerate) ; + /* fmt : bytespersec */ + psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; + /* fmt : blockalign, bitwidth */ + psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; + + /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */ + psf_binheader_writef (psf, "2", 22) ; + + /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */ + psf_binheader_writef (psf, "2", psf->bytewidth * 8) ; + + /* + ** Ok some liberty is taken here to use the most commonly used channel masks + ** instead of "no mapping". If you really want to use "no mapping" for 8 channels and less + ** please don't use wavex. (otherwise we'll have to create a new SF_COMMAND) + */ + switch (psf->sf.channels) + { case 1 : /* center channel mono */ + psf_binheader_writef (psf, "4", 0x4) ; + break ; + + case 2 : /* front left and right */ + psf_binheader_writef (psf, "4", 0x1 | 0x2) ; + break ; + + case 4 : /* Quad */ + psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x10 | 0x20) ; + break ; + + case 6 : /* 5.1 */ + psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20) ; + break ; + + case 8 : /* 7.1 */ + psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80) ; + break ; + + default : /* 0 when in doubt , use direct out, ie NO mapping*/ + psf_binheader_writef (psf, "4", 0x0) ; + break ; + } + + break ; + + case SF_FORMAT_MS_ADPCM : /* Todo, GUID exists might have different header as per wav_write_header */ + default : + return SFE_UNIMPLEMENTED ; + } ; + + /* GUID section, different for each */ + + switch (subformat) + { case SF_FORMAT_PCM_U8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + wavex_write_guid (psf, &MSGUID_SUBTYPE_PCM) ; + break ; + + case SF_FORMAT_FLOAT : + case SF_FORMAT_DOUBLE : + wavex_write_guid (psf, &MSGUID_SUBTYPE_IEEE_FLOAT) ; + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_ULAW : + wavex_write_guid (psf, &MSGUID_SUBTYPE_MULAW) ; + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_ALAW : + wavex_write_guid (psf, &MSGUID_SUBTYPE_ALAW) ; + add_fact_chunk = SF_TRUE ; + break ; + + case SF_FORMAT_MS_ADPCM : /* todo, GUID exists */ + + default : return SFE_UNIMPLEMENTED ; + } ; + + if (add_fact_chunk) + psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ; + + if (psf->str_flags & SF_STR_LOCATE_START) + wav_write_strings (psf, SF_STR_LOCATE_START) ; + + if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START) + { psf_binheader_writef (psf, "m4", PEAK_MARKER, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)) ; + psf_binheader_writef (psf, "44", 1, time (NULL)) ; + for (k = 0 ; k < psf->sf.channels ; k++) + psf_binheader_writef (psf, "ft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; + } ; + + psf_binheader_writef (psf, "tm8", data_MARKER, psf->datalength) ; + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current < psf->dataoffset) + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + else if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* wavex_write_header */ + + + +static int +wav_write_tailer (SF_PRIVATE *psf) +{ int k ; + + /* Reset the current header buffer length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + + psf->dataend = psf_fseek (psf, 0, SEEK_END) ; + + /* Add a PEAK chunk if requested. */ + if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_END) + { psf_binheader_writef (psf, "m4", PEAK_MARKER, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)) ; + psf_binheader_writef (psf, "44", 1, time (NULL)) ; + for (k = 0 ; k < psf->sf.channels ; k++) + psf_binheader_writef (psf, "f4", psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; + } ; + + if (psf->str_flags & SF_STR_LOCATE_END) + wav_write_strings (psf, SF_STR_LOCATE_END) ; + + /* Write the tailer. */ + if (psf->headindex > 0) + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + return 0 ; +} /* wav_write_tailer */ + +static void +wav_write_strings (SF_PRIVATE *psf, int location) +{ int k, prev_head_index, saved_head_index ; + + prev_head_index = psf->headindex + 4 ; + + psf_binheader_writef (psf, "m4m", LIST_MARKER, 0xBADBAD, INFO_MARKER) ; + + for (k = 0 ; k < SF_MAX_STRINGS ; k++) + { if (psf->strings [k].type == 0) + break ; + if (psf->strings [k].flags != location) + continue ; + + switch (psf->strings [k].type) + { case SF_STR_SOFTWARE : + psf_binheader_writef (psf, "ms", ISFT_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_TITLE : + psf_binheader_writef (psf, "ms", INAM_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_COPYRIGHT : + psf_binheader_writef (psf, "ms", ICOP_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_ARTIST : + psf_binheader_writef (psf, "ms", IART_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_COMMENT : + psf_binheader_writef (psf, "ms", ICMT_MARKER, psf->strings [k].str) ; + break ; + + case SF_STR_DATE : + psf_binheader_writef (psf, "ms", ICRD_MARKER, psf->strings [k].str) ; + break ; + } ; + } ; + + saved_head_index = psf->headindex ; + psf->headindex = prev_head_index ; + psf_binheader_writef (psf, "4", saved_head_index - prev_head_index - 4) ; + psf->headindex = saved_head_index ; + +} /* wav_write_strings */ + +static int +wav_close (SF_PRIVATE *psf) +{ + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { wav_write_tailer (psf) ; + + psf->write_header (psf, SF_TRUE) ; + } ; + + return 0 ; +} /* wav_close */ + +static int +wav_command (SF_PRIVATE *psf, int command, void *data, int datasize) +{ + /* Avoid compiler warnings. */ + psf = psf ; + data = data ; + datasize = datasize ; + + switch (command) + { default : break ; + } ; + + return 0 ; +} /* wav_command */ + +static int +wav_subchunk_parse (SF_PRIVATE *psf, int chunk) +{ sf_count_t current_pos ; + char *cptr ; + int dword, bytesread, length ; + + current_pos = psf_fseek (psf, 0, SEEK_CUR) ; + + bytesread = psf_binheader_readf (psf, "4", &length) ; + + if (length <= 8) + { /* This case is for broken files generated by PEAK. */ + psf_log_printf (psf, "%M : %d (weird length)\n", chunk, length) ; + psf_binheader_readf (psf, "mj", &chunk, length - 4) ; + psf_log_printf (psf, " %M\n", chunk) ; + return 0 ; + } ; + + if (psf->headindex + length > SIGNED_SIZEOF (psf->header)) + { psf_log_printf (psf, "%M : %d (too long)\n", chunk, length) ; + psf_binheader_readf (psf, "j", length) ; + return 0 ; + } ; + + if (current_pos + length > psf->filelength) + { psf_log_printf (psf, "%M : %d (should be %d)\n", chunk, length, (int) (psf->filelength - current_pos)) ; + length = psf->filelength - current_pos ; + } + else + psf_log_printf (psf, "%M : %d\n", chunk, length) ; + + while (bytesread < length) + { bytesread += psf_binheader_readf (psf, "m", &chunk) ; + + switch (chunk) + { case adtl_MARKER : + case INFO_MARKER : + /* These markers don't contain anything. */ + psf_log_printf (psf, " %M\n", chunk) ; + break ; + + case data_MARKER: + psf_log_printf (psf, " %M inside a LIST block??? Backing out.\n", chunk) ; + /* Jump back four bytes and return to caller. */ + psf_binheader_readf (psf, "j", -4) ; + return 0 ; + + case ISFT_MARKER : + case ICOP_MARKER : + case IARL_MARKER : + case IART_MARKER : + case ICMT_MARKER : + case ICRD_MARKER : + case IENG_MARKER : + + case INAM_MARKER : + case IPRD_MARKER : + case ISBJ_MARKER : + case ISRC_MARKER : + bytesread += psf_binheader_readf (psf, "4", &dword) ; + dword += (dword & 1) ; + if (dword < 0 || dword > SIGNED_SIZEOF (psf->u.cbuf)) + { psf_log_printf (psf, " *** %M : %d (too big)\n", chunk, dword) ; + psf_binheader_readf (psf, "j", dword) ; + break ; + } ; + + cptr = psf->u.cbuf ; + psf_binheader_readf (psf, "b", cptr, dword) ; + bytesread += dword ; + cptr [dword - 1] = 0 ; + psf_log_printf (psf, " %M : %s\n", chunk, cptr) ; + break ; + + case labl_MARKER : + { int mark_id ; + + bytesread += psf_binheader_readf (psf, "44", &dword, &mark_id) ; + dword -= 4 ; + dword += (dword & 1) ; + if (dword < 1 || dword > SIGNED_SIZEOF (psf->u.cbuf)) + { psf_log_printf (psf, " *** %M : %d (too big)\n", chunk, dword) ; + psf_binheader_readf (psf, "j", dword) ; + break ; + } ; + + cptr = psf->u.cbuf ; + psf_binheader_readf (psf, "b", cptr, dword) ; + bytesread += dword ; + cptr [dword - 1] = 0 ; + psf_log_printf (psf, " %M : %d : %s\n", chunk, mark_id, cptr) ; + } ; + break ; + + + case DISP_MARKER : + case ltxt_MARKER : + case note_MARKER : + bytesread += psf_binheader_readf (psf, "4", &dword) ; + dword += (dword & 1) ; + psf_binheader_readf (psf, "j", dword) ; + bytesread += dword ; + psf_log_printf (psf, " %M : %d\n", chunk, dword) ; + break ; + + default : + psf_binheader_readf (psf, "4", &dword) ; + bytesread += sizeof (dword) ; + dword += (dword & 1) ; + psf_binheader_readf (psf, "j", dword) ; + bytesread += dword ; + psf_log_printf (psf, " *** %M : %d\n", chunk, dword) ; + if (dword > length) + return 0 ; + break ; + } ; + + switch (chunk) + { case ISFT_MARKER : + psf_store_string (psf, SF_STR_SOFTWARE, psf->u.cbuf) ; + break ; + case ICOP_MARKER : + psf_store_string (psf, SF_STR_COPYRIGHT, psf->u.cbuf) ; + break ; + case INAM_MARKER : + psf_store_string (psf, SF_STR_TITLE, psf->u.cbuf) ; + break ; + case IART_MARKER : + psf_store_string (psf, SF_STR_ARTIST, psf->u.cbuf) ; + break ; + case ICMT_MARKER : + psf_store_string (psf, SF_STR_COMMENT, psf->u.cbuf) ; + break ; + case ICRD_MARKER : + psf_store_string (psf, SF_STR_DATE, psf->u.cbuf) ; + break ; + } ; + } ; + + current_pos = psf_fseek (psf, 0, SEEK_CUR) - current_pos ; + + if (current_pos - 4 != length) + psf_log_printf (psf, "**** Bad chunk length %d sbould be %D\n", length, current_pos - 4) ; + + return 0 ; +} /* wav_subchunk_parse */ + +static int +wav_read_smpl_chunk (SF_PRIVATE *psf, unsigned int chunklen) +{ unsigned int bytesread = 0, dword, sampler_data, loop_count ; + unsigned int note, start, end, type = -1, count ; + int j, k ; + + chunklen += (chunklen & 1) ; + + bytesread += psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, " Manufacturer : %X\n", dword) ; + + bytesread += psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, " Product : %u\n", dword) ; + + bytesread += psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, " Period : %u nsec\n", dword) ; + + bytesread += psf_binheader_readf (psf, "4", ¬e) ; + psf_log_printf (psf, " Midi Note : %u\n", note) ; + + bytesread += psf_binheader_readf (psf, "4", &dword) ; + if (dword != 0) + { LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), "%f", + (1.0 * 0x80000000) / ((unsigned int) dword)) ; + psf_log_printf (psf, " Pitch Fract. : %s\n", psf->u.cbuf) ; + } + else + psf_log_printf (psf, " Pitch Fract. : 0\n") ; + + bytesread += psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, " SMPTE Format : %u\n", dword) ; + + bytesread += psf_binheader_readf (psf, "4", &dword) ; + LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), "%02d:%02d:%02d %02d", + (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, (dword >> 8) & 0x7F, dword & 0x7F) ; + psf_log_printf (psf, " SMPTE Offset : %s\n", psf->u.cbuf) ; + + bytesread += psf_binheader_readf (psf, "4", &loop_count) ; + psf_log_printf (psf, " Loop Count : %u\n", loop_count) ; + + /* Sampler Data holds the number of data bytes after the CUE chunks which + ** is not actually CUE data. Display value after CUE data. + */ + bytesread += psf_binheader_readf (psf, "4", &sampler_data) ; + + if ((psf->instrument = psf_instrument_alloc ()) == NULL) + return SFE_MALLOC_FAILED ; + + psf->instrument->loop_count = loop_count ; + + for (j = 0 ; loop_count > 0 && chunklen - bytesread >= 24 ; j ++) + { bytesread += psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, " Cue ID : %2u", dword) ; + + bytesread += psf_binheader_readf (psf, "4", &type) ; + psf_log_printf (psf, " Type : %2u", type) ; + + bytesread += psf_binheader_readf (psf, "4", &start) ; + psf_log_printf (psf, " Start : %5u", start) ; + + bytesread += psf_binheader_readf (psf, "4", &end) ; + psf_log_printf (psf, " End : %5u", end) ; + + bytesread += psf_binheader_readf (psf, "4", &dword) ; + psf_log_printf (psf, " Fraction : %5u", dword) ; + + bytesread += psf_binheader_readf (psf, "4", &count) ; + psf_log_printf (psf, " Count : %5u\n", count) ; + + if (j < ARRAY_LEN (psf->instrument->loops)) + { psf->instrument->loops [j].start = start ; + psf->instrument->loops [j].end = end ; + psf->instrument->loops [j].count = count ; + + switch (type) + { case 0 : + psf->instrument->loops [j].mode = SF_LOOP_FORWARD ; + break ; + case 1 : + psf->instrument->loops [j].mode = SF_LOOP_ALTERNATING ; + break ; + case 2 : + psf->instrument->loops [j].mode = SF_LOOP_BACKWARD ; + break ; + default: + psf->instrument->loops [j].mode = SF_LOOP_NONE ; + break ; + } ; + } ; + + loop_count -- ; + } ; + + if (chunklen - bytesread == 0) + { if (sampler_data != 0) + psf_log_printf (psf, " Sampler Data : %u (should be 0)\n", sampler_data) ; + else + psf_log_printf (psf, " Sampler Data : %u\n", sampler_data) ; + } + else + { if (sampler_data != chunklen - bytesread) + { psf_log_printf (psf, " Sampler Data : %u (should have been %u)\n", sampler_data, chunklen - bytesread) ; + sampler_data = chunklen - bytesread ; + } + else + psf_log_printf (psf, " Sampler Data : %u\n", sampler_data) ; + + psf_log_printf (psf, " ") ; + for (k = 0 ; k < (int) sampler_data ; k++) + { char ch ; + + if (k > 0 && (k % 20) == 0) + psf_log_printf (psf, "\n ") ; + + bytesread += psf_binheader_readf (psf, "1", &ch) ; + psf_log_printf (psf, "%02X ", ch & 0xFF) ; + } ; + + psf_log_printf (psf, "\n") ; + } ; + + psf->instrument->basenote = note ; + psf->instrument->gain = 1 ; + psf->instrument->velocity_lo = psf->instrument->key_lo = 0 ; + psf->instrument->velocity_hi = psf->instrument->key_hi = 127 ; + + return 0 ; +} /* wav_read_smpl_chunk */ + +/* +** The acid chunk goes a little something like this: +** +** 4 bytes 'acid' +** 4 bytes (int) length of chunk starting at next byte +** +** 4 bytes (int) type of file: +** this appears to be a bit mask,however some combinations +** are probably impossible and/or qualified as "errors" +** +** 0x01 On: One Shot Off: Loop +** 0x02 On: Root note is Set Off: No root +** 0x04 On: Stretch is On, Off: Strech is OFF +** 0x08 On: Disk Based Off: Ram based +** 0x10 On: ?????????? Off: ????????? (Acidizer puts that ON) +** +** 2 bytes (short) root note +** if type 0x10 is OFF : [C,C#,(...),B] -> [0x30 to 0x3B] +** if type 0x10 is ON : [C,C#,(...),B] -> [0x3C to 0x47] +** (both types fit on same MIDI pitch albeit different octaves, so who cares) +** +** 2 bytes (short) ??? always set to 0x8000 +** 4 bytes (float) ??? seems to be always 0 +** 4 bytes (int) number of beats +** 2 bytes (short) meter denominator //always 4 in SF/ACID +** 2 bytes (short) meter numerator //always 4 in SF/ACID +** //are we sure about the order?? usually its num/denom +** 4 bytes (float) tempo +** +*/ + +static int +wav_read_acid_chunk (SF_PRIVATE *psf, unsigned int chunklen) +{ unsigned int bytesread = 0 ; + int beats, flags ; + short rootnote, q1, meter_denom, meter_numer ; + float q2, tempo ; + + chunklen += (chunklen & 1) ; + + bytesread += psf_binheader_readf (psf, "422f", &flags, &rootnote, &q1, &q2) ; + + LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), "%f", q2) ; + + psf_log_printf (psf, " Flags : 0x%04x (%s,%s,%s,%s,%s)\n", flags, + (flags & 0x01) ? "OneShot" : "Loop", + (flags & 0x02) ? "RootNoteValid" : "RootNoteInvalid", + (flags & 0x04) ? "StretchOn" : "StretchOff", + (flags & 0x08) ? "DiskBased" : "RAMBased", + (flags & 0x10) ? "??On" : "??Off") ; + + psf_log_printf (psf, " Root note : 0x%x\n ???? : 0x%04x\n ???? : %s\n", + rootnote, q1, psf->u.cbuf) ; + + bytesread += psf_binheader_readf (psf, "422f", &beats, &meter_denom, &meter_numer, &tempo) ; + LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), "%f", tempo) ; + psf_log_printf (psf, " Beats : %d\n Meter : %d/%d\n Tempo : %s\n", + beats, meter_numer, meter_denom, psf->u.cbuf) ; + + psf_binheader_readf (psf, "j", chunklen - bytesread) ; + + if ((psf->loop_info = calloc (1, sizeof (SF_LOOP_INFO))) == NULL) + return SFE_MALLOC_FAILED ; + + psf->loop_info->time_sig_num = meter_numer ; + psf->loop_info->time_sig_den = meter_denom ; + psf->loop_info->loop_mode = (flags & 0x01) ? SF_LOOP_NONE : SF_LOOP_FORWARD ; + psf->loop_info->num_beats = beats ; + psf->loop_info->bpm = tempo ; + psf->loop_info->root_key = (flags & 0x02) ? rootnote : -1 ; + + return 0 ; +} /* wav_read_acid_chunk */ + +int +wav_read_bext_chunk (SF_PRIVATE *psf, unsigned int chunksize) +{ + SF_BROADCAST_INFO* b ; + + if ((psf->broadcast_info = calloc (1, sizeof (SF_BROADCAST_INFO))) == NULL) + { psf->error = SFE_MALLOC_FAILED ; + return -1 ; + } ; + + b = psf->broadcast_info ; + + psf_binheader_readf (psf, "b", b->description, sizeof (b->description)) ; + psf_binheader_readf (psf, "b", b->originator, sizeof (b->originator)) ; + psf_binheader_readf (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ; + psf_binheader_readf (psf, "b", b->origination_date, sizeof (b->origination_date)) ; + psf_binheader_readf (psf, "b", b->origination_time, sizeof (b->origination_time)) ; + psf_binheader_readf (psf, "442", &b->time_reference_low, &b->time_reference_high, &b->version) ; + psf_binheader_readf (psf, "bj", &b->umid, sizeof (b->umid), 190) ; + + if (chunksize > WAV_BEXT_CHUNK_SIZE) + { /* File has coding history data. */ + + b->coding_history_size = chunksize - WAV_BEXT_CHUNK_SIZE ; + + if (b->coding_history_size > SIGNED_SIZEOF (b->coding_history)) + { free (psf->broadcast_info) ; + psf->broadcast_info = NULL ; + psf->error = SFE_MALLOC_FAILED ; + return -1 ; + } ; + + /* We do not parse the coding history */ + psf_binheader_readf (psf, "b", b->coding_history, b->coding_history_size) ; + b->coding_history [sizeof (b->coding_history) - 1] = 0 ; + } ; + + return 0 ; +} /* wav_read_bext_chunk */ + +static int +wav_write_bext_chunk (SF_PRIVATE *psf) +{ SF_BROADCAST_INFO *b ; + + if ((b = psf->broadcast_info) == NULL) + return -1 ; + + psf_binheader_writef (psf, "m4", bext_MARKER, WAV_BEXT_CHUNK_SIZE + b->coding_history_size) ; + + /* + ** Note that it is very important the the field widths of the SF_BROADCAST_INFO + ** struct match those for the bext chunk fields. + */ + + psf_binheader_writef (psf, "b", b->description, sizeof (b->description)) ; + psf_binheader_writef (psf, "b", b->originator, sizeof (b->originator)) ; + psf_binheader_writef (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ; + psf_binheader_writef (psf, "b", b->origination_date, sizeof (b->origination_date)) ; + psf_binheader_writef (psf, "b", b->origination_time, sizeof (b->origination_time)) ; + psf_binheader_writef (psf, "442", b->time_reference_low, b->time_reference_high, b->version) ; + psf_binheader_writef (psf, "b", b->umid, sizeof (b->umid)) ; + psf_binheader_writef (psf, "z", make_size_t (190)) ; + + if (b->coding_history_size > 0) + psf_binheader_writef (psf, "b", b->coding_history, make_size_t (b->coding_history_size)) ; + + return 0 ; +} /* wav_write_bext_chunk */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 9c551689-a1d8-4905-9f56-26a204374f18 +*/ diff --git a/nylsf/wav_w64.c b/nylsf/wav_w64.c new file mode 100644 index 0000000..ed44442 --- /dev/null +++ b/nylsf/wav_w64.c @@ -0,0 +1,509 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** Copyright (C) 2004-2005 David Viens +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "wav_w64.h" + +/* Known WAVEFORMATEXTENSIBLE GUIDS. */ +static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM = +{ 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM = +{ 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT = +{ 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW = +{ 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW = +{ 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } +} ; + +/* +** the next two are from +** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html +*/ + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM = +{ 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } +} ; + +static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT = +{ 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } +} ; + + +#if 0 +/* maybe interesting one day to read the following through sf_read_raw */ +/* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */ +static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX = +{ 0x8312B9C2, 0x2E6E, 0x11d4, { 0xA8, 0x24, 0xDE, 0x5B, 0x96, 0xC3, 0xAB, 0x21 } +} ; +#endif + +/*------------------------------------------------------------------------------ + * Private static functions. + */ + +static int +wavex_write_guid_equal (const EXT_SUBFORMAT * first, const EXT_SUBFORMAT * second) +{ return !memcmp (first, second, sizeof (EXT_SUBFORMAT)) ; +} /* wavex_write_guid_equal */ + + + +int +wav_w64_read_fmt_chunk (SF_PRIVATE *psf, WAV_FMT *wav_fmt, int structsize) +{ int bytesread, k, bytespersec = 0 ; + + memset (wav_fmt, 0, sizeof (WAV_FMT)) ; + + if (structsize < 16) + return SFE_WAV_FMT_SHORT ; + + /* assume psf->rwf_endian is already properly set */ + + /* Read the minimal WAV file header here. */ + bytesread = psf_binheader_readf (psf, "224422", + &(wav_fmt->format), &(wav_fmt->min.channels), + &(wav_fmt->min.samplerate), &(wav_fmt->min.bytespersec), + &(wav_fmt->min.blockalign), &(wav_fmt->min.bitwidth)) ; + + psf_log_printf (psf, " Format : 0x%X => %s\n", wav_fmt->format, wav_w64_format_str (wav_fmt->format)) ; + psf_log_printf (psf, " Channels : %d\n", wav_fmt->min.channels) ; + psf_log_printf (psf, " Sample Rate : %d\n", wav_fmt->min.samplerate) ; + psf_log_printf (psf, " Block Align : %d\n", wav_fmt->min.blockalign) ; + + if (wav_fmt->format == WAVE_FORMAT_PCM && wav_fmt->min.bitwidth == 24 && + wav_fmt->min.blockalign == 4 * wav_fmt->min.channels) + { + psf_log_printf (psf, "\nInvalid file generated by Syntrillium's Cooledit!\n" + "Treating as WAVE_FORMAT_IEEE_FLOAT 32 bit floating point file.\n\n") ; + psf_log_printf (psf, " Bit Width : 24 (should be 32)\n") ; + wav_fmt->min.bitwidth = 32 ; + wav_fmt->format = WAVE_FORMAT_IEEE_FLOAT ; + } + else if (wav_fmt->min.bitwidth == 0) + { switch (wav_fmt->format) + { case WAVE_FORMAT_GSM610 : + case WAVE_FORMAT_IPP_ITU_G_723_1 : + psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; + break ; + default : + psf_log_printf (psf, " Bit Width : %d (should not be 0)\n", wav_fmt->min.bitwidth) ; + } + } + else + { switch (wav_fmt->format) + { case WAVE_FORMAT_GSM610 : + case WAVE_FORMAT_IPP_ITU_G_723_1 : + psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; + break ; + default : + psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; + } + } ; + + psf->sf.samplerate = wav_fmt->min.samplerate ; + psf->sf.frames = 0 ; /* Correct this when reading data chunk. */ + psf->sf.channels = wav_fmt->min.channels ; + + switch (wav_fmt->format) + { case WAVE_FORMAT_PCM : + case WAVE_FORMAT_IEEE_FLOAT : + bytespersec = wav_fmt->min.samplerate * wav_fmt->min.blockalign ; + if (wav_fmt->min.bytespersec != (unsigned) bytespersec) + psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; + else + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; + + psf->bytewidth = BITWIDTH2BYTES (wav_fmt->min.bitwidth) ; + break ; + + case WAVE_FORMAT_ALAW : + case WAVE_FORMAT_MULAW : + if (wav_fmt->min.bytespersec / wav_fmt->min.blockalign != wav_fmt->min.samplerate) + psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, wav_fmt->min.samplerate * wav_fmt->min.blockalign) ; + else + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; + + psf->bytewidth = 1 ; + if (structsize >= 18) + { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->size20.extrabytes)) ; + psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->size20.extrabytes) ; + } ; + break ; + + case WAVE_FORMAT_IMA_ADPCM : + if (wav_fmt->min.bitwidth != 4) + return SFE_WAV_ADPCM_NOT4BIT ; + if (wav_fmt->min.channels < 1 || wav_fmt->min.channels > 2) + return SFE_WAV_ADPCM_CHANNELS ; + + bytesread += + psf_binheader_readf (psf, "22", &(wav_fmt->ima.extrabytes), &(wav_fmt->ima.samplesperblock)) ; + + bytespersec = (wav_fmt->ima.samplerate * wav_fmt->ima.blockalign) / wav_fmt->ima.samplesperblock ; + if (wav_fmt->ima.bytespersec != (unsigned) bytespersec) + psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ima.bytespersec, bytespersec) ; + else + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ima.bytespersec) ; + + psf->bytewidth = 2 ; + psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->ima.extrabytes) ; + psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ; + break ; + + case WAVE_FORMAT_MS_ADPCM : + if (wav_fmt->msadpcm.bitwidth != 4) + return SFE_WAV_ADPCM_NOT4BIT ; + if (wav_fmt->msadpcm.channels < 1 || wav_fmt->msadpcm.channels > 2) + return SFE_WAV_ADPCM_CHANNELS ; + + bytesread += + psf_binheader_readf (psf, "222", &(wav_fmt->msadpcm.extrabytes), + &(wav_fmt->msadpcm.samplesperblock), &(wav_fmt->msadpcm.numcoeffs)) ; + + bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / wav_fmt->msadpcm.samplesperblock ; + if (wav_fmt->min.bytespersec == (unsigned) bytespersec) + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; + else if (wav_fmt->min.bytespersec == (wav_fmt->min.samplerate / wav_fmt->msadpcm.samplesperblock) * wav_fmt->min.blockalign) + psf_log_printf (psf, " Bytes/sec : %d (should be %d (MS BUG!))\n", wav_fmt->min.bytespersec, bytespersec) ; + else + psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; + + + psf->bytewidth = 2 ; + psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->msadpcm.extrabytes) ; + psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->msadpcm.samplesperblock) ; + if (wav_fmt->msadpcm.numcoeffs > SIGNED_SIZEOF (MS_ADPCM_WAV_FMT) / SIGNED_SIZEOF (int)) + { psf_log_printf (psf, " No. of Coeffs : %d ****\n", wav_fmt->msadpcm.numcoeffs) ; + wav_fmt->msadpcm.numcoeffs = SIGNED_SIZEOF (MS_ADPCM_WAV_FMT) / SIGNED_SIZEOF (int) ; + } + else + psf_log_printf (psf, " No. of Coeffs : %d\n", wav_fmt->msadpcm.numcoeffs) ; + + psf_log_printf (psf, " Index Coeffs1 Coeffs2\n") ; + for (k = 0 ; k < wav_fmt->msadpcm.numcoeffs ; k++) + { bytesread += + psf_binheader_readf (psf, "22", &(wav_fmt->msadpcm.coeffs [k].coeff1), &(wav_fmt->msadpcm.coeffs [k].coeff2)) ; + LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %7d %7d\n", k, wav_fmt->msadpcm.coeffs [k].coeff1, wav_fmt->msadpcm.coeffs [k].coeff2) ; + psf_log_printf (psf, psf->u.cbuf) ; + } ; + break ; + + case WAVE_FORMAT_GSM610 : + if (wav_fmt->gsm610.channels != 1 || wav_fmt->gsm610.blockalign != 65) + return SFE_WAV_GSM610_FORMAT ; + + bytesread += + psf_binheader_readf (psf, "22", &(wav_fmt->gsm610.extrabytes), &(wav_fmt->gsm610.samplesperblock)) ; + + if (wav_fmt->gsm610.samplesperblock != 320) + return SFE_WAV_GSM610_FORMAT ; + + bytespersec = (wav_fmt->gsm610.samplerate * wav_fmt->gsm610.blockalign) / wav_fmt->gsm610.samplesperblock ; + if (wav_fmt->gsm610.bytespersec != (unsigned) bytespersec) + psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->gsm610.bytespersec, bytespersec) ; + else + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->gsm610.bytespersec) ; + + psf->bytewidth = 2 ; + psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->gsm610.extrabytes) ; + psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->gsm610.samplesperblock) ; + break ; + + case WAVE_FORMAT_EXTENSIBLE : + if (wav_fmt->ext.bytespersec / wav_fmt->ext.blockalign != wav_fmt->ext.samplerate) + psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ext.bytespersec, wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) ; + else + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ext.bytespersec) ; + + bytesread += + psf_binheader_readf (psf, "224", &(wav_fmt->ext.extrabytes), &(wav_fmt->ext.validbits), + &(wav_fmt->ext.channelmask)) ; + + psf_log_printf (psf, " Valid Bits : %d\n", wav_fmt->ext.validbits) ; + psf_log_printf (psf, " Channel Mask : 0x%X\n", wav_fmt->ext.channelmask) ; + + bytesread += + psf_binheader_readf (psf, "422", &(wav_fmt->ext.esf.esf_field1), &(wav_fmt->ext.esf.esf_field2), + &(wav_fmt->ext.esf.esf_field3)) ; + + /* compare the esf_fields with each known GUID? and print? */ + psf_log_printf (psf, " Subformat\n") ; + psf_log_printf (psf, " esf_field1 : 0x%X\n", wav_fmt->ext.esf.esf_field1) ; + psf_log_printf (psf, " esf_field2 : 0x%X\n", wav_fmt->ext.esf.esf_field2) ; + psf_log_printf (psf, " esf_field3 : 0x%X\n", wav_fmt->ext.esf.esf_field3) ; + psf_log_printf (psf, " esf_field4 : ") ; + for (k = 0 ; k < 8 ; k++) + { bytesread += psf_binheader_readf (psf, "1", &(wav_fmt->ext.esf.esf_field4 [k])) ; + psf_log_printf (psf, "0x%X ", wav_fmt->ext.esf.esf_field4 [k] & 0xFF) ; + } ; + psf_log_printf (psf, "\n") ; + psf->bytewidth = BITWIDTH2BYTES (wav_fmt->ext.bitwidth) ; + + /* Compare GUIDs for known ones. */ + if (wavex_write_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_PCM) + || wavex_write_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM)) + { psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ; + psf_log_printf (psf, " format : pcm\n") ; + } + else if (wavex_write_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MS_ADPCM)) + { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM) ; + psf_log_printf (psf, " format : ms adpcm\n") ; + } + else if (wavex_write_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_IEEE_FLOAT) + || wavex_write_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM)) + { psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ; + psf_log_printf (psf, " format : IEEE float\n") ; + } + else if (wavex_write_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_ALAW)) + { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ALAW) ; + psf_log_printf (psf, " format : A-law\n") ; + } + else if (wavex_write_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MULAW)) + { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ULAW) ; + psf_log_printf (psf, " format : u-law\n") ; + } + else + return SFE_UNIMPLEMENTED ; + break ; + + case WAVE_FORMAT_G721_ADPCM : + psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->g72x.bytespersec) ; + if (structsize >= 20) + { bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->g72x.extrabytes), &(wav_fmt->g72x.auxblocksize)) ; + if (wav_fmt->g72x.extrabytes == 0) + psf_log_printf (psf, " Extra Bytes : %d (should be 2)\n", wav_fmt->g72x.extrabytes) ; + else + psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->g72x.extrabytes) ; + psf_log_printf (psf, " Aux Blk Size : %d\n", wav_fmt->g72x.auxblocksize) ; + } + else if (structsize == 18) + { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->g72x.extrabytes)) ; + psf_log_printf (psf, " Extra Bytes : %d%s\n", wav_fmt->g72x.extrabytes, wav_fmt->g72x.extrabytes != 0 ? " (should be 0)" : "") ; + } + else + psf_log_printf (psf, "*** 'fmt ' chunk should be bigger than this!\n") ; + break ; + + default : + psf_log_printf (psf, "*** No 'fmt ' chunk dumper for this format!\n") ; + break ; + } ; + + if (bytesread > structsize) + { psf_log_printf (psf, "*** wav_w64_read_fmt_chunk (bytesread > structsize)\n") ; + return SFE_W64_FMT_SHORT ; + } + else + psf_binheader_readf (psf, "j", structsize - bytesread) ; + + psf->blockwidth = wav_fmt->min.channels * psf->bytewidth ; + + return 0 ; +} /* wav_w64_read_fmt_chunk */ + +void +wavex_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat) +{ + psf_binheader_writef (psf, "422b", subformat->esf_field1, + subformat->esf_field2, subformat->esf_field3, + subformat->esf_field4, make_size_t (8)) ; +} /* wavex_write_guid */ + + +/*============================================================================== +*/ + +typedef struct +{ int ID ; + const char *name ; +} WAV_FORMAT_DESC ; + +#define STR(x) #x +#define FORMAT_TYPE(x) { x, STR (x) } + +static WAV_FORMAT_DESC wave_descs [] = +{ FORMAT_TYPE (WAVE_FORMAT_PCM), + FORMAT_TYPE (WAVE_FORMAT_MS_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_IEEE_FLOAT), + FORMAT_TYPE (WAVE_FORMAT_VSELP), + FORMAT_TYPE (WAVE_FORMAT_IBM_CVSD), + FORMAT_TYPE (WAVE_FORMAT_ALAW), + FORMAT_TYPE (WAVE_FORMAT_MULAW), + FORMAT_TYPE (WAVE_FORMAT_OKI_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_IMA_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_MEDIASPACE_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_SIERRA_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_G723_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_DIGISTD), + FORMAT_TYPE (WAVE_FORMAT_DIGIFIX), + FORMAT_TYPE (WAVE_FORMAT_DIALOGIC_OKI_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_MEDIAVISION_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_CU_CODEC), + FORMAT_TYPE (WAVE_FORMAT_YAMAHA_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_SONARC), + FORMAT_TYPE (WAVE_FORMAT_DSPGROUP_TRUESPEECH), + FORMAT_TYPE (WAVE_FORMAT_ECHOSC1), + FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF36), + FORMAT_TYPE (WAVE_FORMAT_APTX), + FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF10), + FORMAT_TYPE (WAVE_FORMAT_PROSODY_1612), + FORMAT_TYPE (WAVE_FORMAT_LRC), + FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC2), + FORMAT_TYPE (WAVE_FORMAT_GSM610), + FORMAT_TYPE (WAVE_FORMAT_MSNAUDIO), + FORMAT_TYPE (WAVE_FORMAT_ANTEX_ADPCME), + FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_VQLPC), + FORMAT_TYPE (WAVE_FORMAT_DIGIREAL), + FORMAT_TYPE (WAVE_FORMAT_DIGIADPCM), + FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_CR10), + FORMAT_TYPE (WAVE_FORMAT_NMS_VBXADPCM), + FORMAT_TYPE (WAVE_FORMAT_ROLAND_RDAC), + FORMAT_TYPE (WAVE_FORMAT_ECHOSC3), + FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_DIGITALK), + FORMAT_TYPE (WAVE_FORMAT_XEBEC), + FORMAT_TYPE (WAVE_FORMAT_G721_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_G728_CELP), + FORMAT_TYPE (WAVE_FORMAT_MSG723), + FORMAT_TYPE (WAVE_FORMAT_MPEG), + FORMAT_TYPE (WAVE_FORMAT_RT24), + FORMAT_TYPE (WAVE_FORMAT_PAC), + FORMAT_TYPE (WAVE_FORMAT_MPEGLAYER3), + FORMAT_TYPE (WAVE_FORMAT_LUCENT_G723), + FORMAT_TYPE (WAVE_FORMAT_CIRRUS), + FORMAT_TYPE (WAVE_FORMAT_ESPCM), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE), + FORMAT_TYPE (WAVE_FORMAT_CANOPUS_ATRAC), + FORMAT_TYPE (WAVE_FORMAT_G726_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_G722_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_DSAT), + FORMAT_TYPE (WAVE_FORMAT_DSAT_DISPLAY), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_BYTE_ALIGNED), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC8), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC10), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC16), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC20), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT24), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29HW), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR12), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR18), + FORMAT_TYPE (WAVE_FORMAT_VOXWARE_TQ40), + FORMAT_TYPE (WAVE_FORMAT_SOFTSOUND), + FORMAT_TYPE (WAVE_FORMAT_VOXARE_TQ60), + FORMAT_TYPE (WAVE_FORMAT_MSRT24), + FORMAT_TYPE (WAVE_FORMAT_G729A), + FORMAT_TYPE (WAVE_FORMAT_MVI_MV12), + FORMAT_TYPE (WAVE_FORMAT_DF_G726), + FORMAT_TYPE (WAVE_FORMAT_DF_GSM610), + FORMAT_TYPE (WAVE_FORMAT_ONLIVE), + FORMAT_TYPE (WAVE_FORMAT_SBC24), + FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC3_SPDIF), + FORMAT_TYPE (WAVE_FORMAT_ZYXEL_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_PHILIPS_LPCBB), + FORMAT_TYPE (WAVE_FORMAT_PACKED), + FORMAT_TYPE (WAVE_FORMAT_RHETOREX_ADPCM), + FORMAT_TYPE (IBM_FORMAT_MULAW), + FORMAT_TYPE (IBM_FORMAT_ALAW), + FORMAT_TYPE (IBM_FORMAT_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_VIVO_G723), + FORMAT_TYPE (WAVE_FORMAT_VIVO_SIREN), + FORMAT_TYPE (WAVE_FORMAT_DIGITAL_G723), + FORMAT_TYPE (WAVE_FORMAT_CREATIVE_ADPCM), + FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH8), + FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH10), + FORMAT_TYPE (WAVE_FORMAT_QUARTERDECK), + FORMAT_TYPE (WAVE_FORMAT_FM_TOWNS_SND), + FORMAT_TYPE (WAVE_FORMAT_BZV_DIGITAL), + FORMAT_TYPE (WAVE_FORMAT_VME_VMPCM), + FORMAT_TYPE (WAVE_FORMAT_OLIGSM), + FORMAT_TYPE (WAVE_FORMAT_OLIADPCM), + FORMAT_TYPE (WAVE_FORMAT_OLICELP), + FORMAT_TYPE (WAVE_FORMAT_OLISBC), + FORMAT_TYPE (WAVE_FORMAT_OLIOPR), + FORMAT_TYPE (WAVE_FORMAT_LH_CODEC), + FORMAT_TYPE (WAVE_FORMAT_NORRIS), + FORMAT_TYPE (WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS), + FORMAT_TYPE (WAVE_FORMAT_DVM), + FORMAT_TYPE (WAVE_FORMAT_INTERWAV_VSC112), + FORMAT_TYPE (WAVE_FORMAT_IPP_ITU_G_723_1), + FORMAT_TYPE (WAVE_FORMAT_EXTENSIBLE), +} ; + +char const* +wav_w64_format_str (int k) +{ int lower, upper, mid ; + + lower = -1 ; + upper = sizeof (wave_descs) / sizeof (WAV_FORMAT_DESC) ; + + /* binary search */ + if ((wave_descs [0].ID <= k) && (k <= wave_descs [upper - 1].ID)) + { + while (lower + 1 < upper) + { mid = (upper + lower) / 2 ; + + if (k == wave_descs [mid].ID) + return wave_descs [mid].name ; + if (k < wave_descs [mid].ID) + upper = mid ; + else + lower = mid ; + } ; + } ; + + return "Unknown format" ; +} /* wav_w64_format_str */ + +int +wav_w64_srate2blocksize (int srate_chan_product) +{ if (srate_chan_product < 12000) + return 256 ; + if (srate_chan_product < 23000) + return 512 ; + if (srate_chan_product < 44000) + return 1024 ; + return 2048 ; +} /* srate2blocksize */ +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 43c1b1dd-8abd-43da-a8cd-44da914b64a5 +*/ diff --git a/nylsf/wav_w64.h b/nylsf/wav_w64.h new file mode 100644 index 0000000..7d7ab1c --- /dev/null +++ b/nylsf/wav_w64.h @@ -0,0 +1,286 @@ +/* +** Copyright (C) 1999-2005 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* This file contains definitions commong to WAV and W64 files. */ + + +#ifndef WAV_W64_H_INCLUDED +#define WAV_W64_H_INCLUDED + +/*------------------------------------------------------------------------------ +** List of known WAV format tags +*/ + +enum +{ + /* keep sorted for wav_w64_format_str() */ + WAVE_FORMAT_UNKNOWN = 0x0000, /* Microsoft Corporation */ + WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM format */ + WAVE_FORMAT_MS_ADPCM = 0x0002, /* Microsoft ADPCM */ + WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* Micrososft 32 bit float format */ + WAVE_FORMAT_VSELP = 0x0004, /* Compaq Computer Corporation */ + WAVE_FORMAT_IBM_CVSD = 0x0005, /* IBM Corporation */ + WAVE_FORMAT_ALAW = 0x0006, /* Microsoft Corporation */ + WAVE_FORMAT_MULAW = 0x0007, /* Microsoft Corporation */ + WAVE_FORMAT_OKI_ADPCM = 0x0010, /* OKI */ + WAVE_FORMAT_IMA_ADPCM = 0x0011, /* Intel Corporation */ + WAVE_FORMAT_MEDIASPACE_ADPCM = 0x0012, /* Videologic */ + WAVE_FORMAT_SIERRA_ADPCM = 0x0013, /* Sierra Semiconductor Corp */ + WAVE_FORMAT_G723_ADPCM = 0x0014, /* Antex Electronics Corporation */ + WAVE_FORMAT_DIGISTD = 0x0015, /* DSP Solutions, Inc. */ + WAVE_FORMAT_DIGIFIX = 0x0016, /* DSP Solutions, Inc. */ + WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic Corporation */ + WAVE_FORMAT_MEDIAVISION_ADPCM = 0x0018, /* Media Vision, Inc. */ + WAVE_FORMAT_CU_CODEC = 0x0019, /* Hewlett-Packard Company */ + WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha Corporation of America */ + WAVE_FORMAT_SONARC = 0x0021, /* Speech Compression */ + WAVE_FORMAT_DSPGROUP_TRUESPEECH = 0x0022, /* DSP Group, Inc */ + WAVE_FORMAT_ECHOSC1 = 0x0023, /* Echo Speech Corporation */ + WAVE_FORMAT_AUDIOFILE_AF36 = 0x0024, /* Audiofile, Inc. */ + WAVE_FORMAT_APTX = 0x0025, /* Audio Processing Technology */ + WAVE_FORMAT_AUDIOFILE_AF10 = 0x0026, /* Audiofile, Inc. */ + WAVE_FORMAT_PROSODY_1612 = 0x0027, /* Aculab plc */ + WAVE_FORMAT_LRC = 0x0028, /* Merging Technologies S.A. */ + WAVE_FORMAT_DOLBY_AC2 = 0x0030, /* Dolby Laboratories */ + WAVE_FORMAT_GSM610 = 0x0031, /* Microsoft Corporation */ + WAVE_FORMAT_MSNAUDIO = 0x0032, /* Microsoft Corporation */ + WAVE_FORMAT_ANTEX_ADPCME = 0x0033, /* Antex Electronics Corporation */ + WAVE_FORMAT_CONTROL_RES_VQLPC = 0x0034, /* Control Resources Limited */ + WAVE_FORMAT_DIGIREAL = 0x0035, /* DSP Solutions, Inc. */ + WAVE_FORMAT_DIGIADPCM = 0x0036, /* DSP Solutions, Inc. */ + WAVE_FORMAT_CONTROL_RES_CR10 = 0x0037, /* Control Resources Limited */ + WAVE_FORMAT_NMS_VBXADPCM = 0x0038, /* Natural MicroSystems */ + WAVE_FORMAT_ROLAND_RDAC = 0x0039, /* Roland */ + WAVE_FORMAT_ECHOSC3 = 0x003A, /* Echo Speech Corporation */ + WAVE_FORMAT_ROCKWELL_ADPCM = 0x003B, /* Rockwell International */ + WAVE_FORMAT_ROCKWELL_DIGITALK = 0x003C, /* Rockwell International */ + WAVE_FORMAT_XEBEC = 0x003D, /* Xebec Multimedia Solutions Limited */ + WAVE_FORMAT_G721_ADPCM = 0x0040, /* Antex Electronics Corporation */ + WAVE_FORMAT_G728_CELP = 0x0041, /* Antex Electronics Corporation */ + WAVE_FORMAT_MSG723 = 0x0042, /* Microsoft Corporation */ + WAVE_FORMAT_MPEG = 0x0050, /* Microsoft Corporation */ + WAVE_FORMAT_RT24 = 0x0052, /* InSoft Inc. */ + WAVE_FORMAT_PAC = 0x0053, /* InSoft Inc. */ + WAVE_FORMAT_MPEGLAYER3 = 0x0055, /* MPEG 3 Layer 1 */ + WAVE_FORMAT_LUCENT_G723 = 0x0059, /* Lucent Technologies */ + WAVE_FORMAT_CIRRUS = 0x0060, /* Cirrus Logic */ + WAVE_FORMAT_ESPCM = 0x0061, /* ESS Technology */ + WAVE_FORMAT_VOXWARE = 0x0062, /* Voxware Inc */ + WAVE_FORMAT_CANOPUS_ATRAC = 0x0063, /* Canopus, Co., Ltd. */ + WAVE_FORMAT_G726_ADPCM = 0x0064, /* APICOM */ + WAVE_FORMAT_G722_ADPCM = 0x0065, /* APICOM */ + WAVE_FORMAT_DSAT = 0x0066, /* Microsoft Corporation */ + WAVE_FORMAT_DSAT_DISPLAY = 0x0067, /* Microsoft Corporation */ + WAVE_FORMAT_VOXWARE_BYTE_ALIGNED = 0x0069, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_AC8 = 0x0070, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_AC10 = 0x0071, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_AC16 = 0x0072, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_AC20 = 0x0073, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_RT24 = 0x0074, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_RT29 = 0x0075, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_RT29HW = 0x0076, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_VR12 = 0x0077, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_VR18 = 0x0078, /* Voxware Inc. */ + WAVE_FORMAT_VOXWARE_TQ40 = 0x0079, /* Voxware Inc. */ + WAVE_FORMAT_SOFTSOUND = 0x0080, /* Softsound, Ltd. */ + WAVE_FORMAT_VOXARE_TQ60 = 0x0081, /* Voxware Inc. */ + WAVE_FORMAT_MSRT24 = 0x0082, /* Microsoft Corporation */ + WAVE_FORMAT_G729A = 0x0083, /* AT&T Laboratories */ + WAVE_FORMAT_MVI_MV12 = 0x0084, /* Motion Pixels */ + WAVE_FORMAT_DF_G726 = 0x0085, /* DataFusion Systems (Pty) (Ltd) */ + WAVE_FORMAT_DF_GSM610 = 0x0086, /* DataFusion Systems (Pty) (Ltd) */ + /* removed because duplicate */ + /* WAVE_FORMAT_ISIAUDIO = 0x0088, */ /* Iterated Systems, Inc. */ + WAVE_FORMAT_ONLIVE = 0x0089, /* OnLive! Technologies, Inc. */ + WAVE_FORMAT_SBC24 = 0x0091, /* Siemens Business Communications Systems */ + WAVE_FORMAT_DOLBY_AC3_SPDIF = 0x0092, /* Sonic Foundry */ + WAVE_FORMAT_ZYXEL_ADPCM = 0x0097, /* ZyXEL Communications, Inc. */ + WAVE_FORMAT_PHILIPS_LPCBB = 0x0098, /* Philips Speech Processing */ + WAVE_FORMAT_PACKED = 0x0099, /* Studer Professional Audio AG */ + WAVE_FORMAT_RHETOREX_ADPCM = 0x0100, /* Rhetorex, Inc. */ + + /* removed because of the following */ + /* WAVE_FORMAT_IRAT = 0x0101,*/ /* BeCubed Software Inc. */ + + /* these three are unofficial */ + IBM_FORMAT_MULAW = 0x0101, /* IBM mu-law format */ + IBM_FORMAT_ALAW = 0x0102, /* IBM a-law format */ + IBM_FORMAT_ADPCM = 0x0103, /* IBM AVC Adaptive Differential PCM format */ + + WAVE_FORMAT_VIVO_G723 = 0x0111, /* Vivo Software */ + WAVE_FORMAT_VIVO_SIREN = 0x0112, /* Vivo Software */ + WAVE_FORMAT_DIGITAL_G723 = 0x0123, /* Digital Equipment Corporation */ + WAVE_FORMAT_CREATIVE_ADPCM = 0x0200, /* Creative Labs, Inc */ + WAVE_FORMAT_CREATIVE_FASTSPEECH8 = 0x0202, /* Creative Labs, Inc */ + WAVE_FORMAT_CREATIVE_FASTSPEECH10 = 0x0203, /* Creative Labs, Inc */ + WAVE_FORMAT_QUARTERDECK = 0x0220, /* Quarterdeck Corporation */ + WAVE_FORMAT_FM_TOWNS_SND = 0x0300, /* Fujitsu Corporation */ + WAVE_FORMAT_BZV_DIGITAL = 0x0400, /* Brooktree Corporation */ + WAVE_FORMAT_VME_VMPCM = 0x0680, /* AT&T Labs, Inc. */ + WAVE_FORMAT_OLIGSM = 0x1000, /* Ing C. Olivetti & C., S.p.A. */ + WAVE_FORMAT_OLIADPCM = 0x1001, /* Ing C. Olivetti & C., S.p.A. */ + WAVE_FORMAT_OLICELP = 0x1002, /* Ing C. Olivetti & C., S.p.A. */ + WAVE_FORMAT_OLISBC = 0x1003, /* Ing C. Olivetti & C., S.p.A. */ + WAVE_FORMAT_OLIOPR = 0x1004, /* Ing C. Olivetti & C., S.p.A. */ + WAVE_FORMAT_LH_CODEC = 0x1100, /* Lernout & Hauspie */ + WAVE_FORMAT_NORRIS = 0x1400, /* Norris Communications, Inc. */ + /* removed because duplicate */ + /* WAVE_FORMAT_ISIAUDIO = 0x1401, */ /* AT&T Labs, Inc. */ + WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS = 0x1500, /* AT&T Labs, Inc. */ + WAVE_FORMAT_DVM = 0x2000, /* FAST Multimedia AG */ + WAVE_FORMAT_INTERWAV_VSC112 = 0x7150, /* ????? */ + + WAVE_FORMAT_IPP_ITU_G_723_1 = 0x7230, /* Intel Performance Primitives g723 codec. */ + + WAVE_FORMAT_EXTENSIBLE = 0xFFFE +} ; + +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; +} MIN_WAV_FMT ; + +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; + unsigned short extrabytes ; + unsigned short dummy ; +} WAV_FMT_SIZE20 ; + +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; + unsigned short extrabytes ; + unsigned short samplesperblock ; + unsigned short numcoeffs ; + struct + { short coeff1 ; + short coeff2 ; + } coeffs [7] ; +} MS_ADPCM_WAV_FMT ; + +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; + unsigned short extrabytes ; + unsigned short samplesperblock ; +} IMA_ADPCM_WAV_FMT ; + +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; + unsigned short extrabytes ; + unsigned short auxblocksize ; +} G72x_ADPCM_WAV_FMT ; + + +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; + unsigned short extrabytes ; + unsigned short samplesperblock ; +} GSM610_WAV_FMT ; + +typedef struct +{ unsigned int esf_field1 ; + unsigned short esf_field2 ; + unsigned short esf_field3 ; + char esf_field4 [8] ; +} EXT_SUBFORMAT ; + +typedef struct +{ unsigned short format ; + unsigned short channels ; + unsigned int samplerate ; + unsigned int bytespersec ; + unsigned short blockalign ; + unsigned short bitwidth ; + unsigned short extrabytes ; + unsigned short validbits ; + unsigned int channelmask ; + EXT_SUBFORMAT esf ; +} EXTENSIBLE_WAV_FMT ; + +typedef union +{ unsigned short format ; + MIN_WAV_FMT min ; + IMA_ADPCM_WAV_FMT ima ; + MS_ADPCM_WAV_FMT msadpcm ; + G72x_ADPCM_WAV_FMT g72x ; + EXTENSIBLE_WAV_FMT ext ; + GSM610_WAV_FMT gsm610 ; + WAV_FMT_SIZE20 size20 ; + char padding [512] ; +} WAV_FMT ; + +typedef struct +{ int frames ; +} FACT_CHUNK ; + +#define WAV_W64_GSM610_BLOCKSIZE 65 +#define WAV_W64_GSM610_SAMPLES 320 + +/*------------------------------------------------------------------------------------ +** Functions defined in wav_ms_adpcm.c +*/ + +#define MSADPCM_ADAPT_COEFF_COUNT 7 + +void msadpcm_write_adapt_coeffs (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------------ +** Functions defined in wav_w64.c +*/ + +int wav_w64_srate2blocksize (int srate_chan_product) ; +char const* wav_w64_format_str (int k) ; +int wav_w64_read_fmt_chunk (SF_PRIVATE *psf, WAV_FMT *wav_fmt, int structsize) ; +void wavex_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat) ; + +#endif +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 877fde12-9be3-4a31-8a5a-fdae39958613 +*/ diff --git a/nylsf/wve.c b/nylsf/wve.c new file mode 100644 index 0000000..54a0833 --- /dev/null +++ b/nylsf/wve.c @@ -0,0 +1,125 @@ +/* +** Copyright (C) 2002-2004 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" + +#if (ENABLE_EXPERIMENTAL_CODE == 0) + +int +wve_open (SF_PRIVATE *psf) +{ if (psf) + return SFE_UNIMPLEMENTED ; + return (psf && 0) ; +} /* wve_open */ + +#else + +#define SFE_WVE_NOT_WVE 666 + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define ALAW_MARKER MAKE_MARKER ('A', 'L', 'a', 'w') +#define SOUN_MARKER MAKE_MARKER ('S', 'o', 'u', 'n') +#define DFIL_MARKER MAKE_MARKER ('d', 'F', 'i', 'l') + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int wve_read_header (SF_PRIVATE *psf) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +wve_open (SF_PRIVATE *psf) +{ int subformat, error = 0 ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + return SFE_UNIMPLEMENTED ; + + if ((error = wve_read_header (psf))) + return error ; + + if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_WVE) + return SFE_BAD_OPEN_FORMAT ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + return error ; +} /* wve_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +wve_read_header (SF_PRIVATE *psf) +{ int marker ; + + /* Set position to start of file to begin reading header. */ + psf_binheader_readf (psf, "pm", 0, &marker) ; + if (marker != ALAW_MARKER) + return SFE_WVE_NOT_WVE ; + + psf_binheader_readf (psf, "m", &marker) ; + if (marker != SOUN_MARKER) + return SFE_WVE_NOT_WVE ; + + psf_binheader_readf (psf, "m", &marker) ; + if (marker != DFIL_MARKER) + return SFE_WVE_NOT_WVE ; + + psf_log_printf (psf, "Read only : Psion Palmtop Alaw (.wve)\n" + " Sample Rate : 8000\n" + " Channels : 1\n" + " Encoding : A-law\n") ; + + psf->dataoffset = 0x20 ; + psf->datalength = psf->filelength - psf->dataoffset ; + + psf->sf.format = SF_FORMAT_WVE | SF_FORMAT_ALAW ; + psf->sf.samplerate = 8000 ; + psf->sf.frames = psf->datalength ; + psf->sf.channels = 1 ; + + return alaw_init (psf) ; +} /* wve_read_header */ + +/*------------------------------------------------------------------------------ +*/ + +#endif +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: ba368cb5-523f-45e4-98c1-5b99a102f73f +*/ diff --git a/nylsf/xi.c b/nylsf/xi.c new file mode 100644 index 0000000..dd7b085 --- /dev/null +++ b/nylsf/xi.c @@ -0,0 +1,1204 @@ +/* +** Copyright (C) 2003-2006 Erik de Castro Lopo +** +** 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 2.1 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 Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "float_cast.h" + +#define MAX_XI_SAMPLES 16 + +/*------------------------------------------------------------------------------ +** Private static functions and tyepdefs. +*/ + +typedef struct +{ /* Warning, this filename is NOT nul terminated. */ + char filename [22] ; + char software [20] ; + char sample_name [22] ; + + int loop_begin, loop_end ; + int sample_flags ; + + /* Data for encoder and decoder. */ + short last_16 ; +} XI_PRIVATE ; + +static int xi_close (SF_PRIVATE *psf) ; +static int xi_write_header (SF_PRIVATE *psf, int calc_length) ; +static int xi_read_header (SF_PRIVATE *psf) ; +static int dpcm_init (SF_PRIVATE *psf) ; + + +static sf_count_t dpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +xi_open (SF_PRIVATE *psf) +{ XI_PRIVATE *pxi ; + int subformat, error = 0 ; + + if (psf->is_pipe) + return SFE_XI_NO_PIPE ; + + if (psf->codec_data) + pxi = psf->codec_data ; + else if ((pxi = calloc (1, sizeof (XI_PRIVATE))) == NULL) + return SFE_MALLOC_FAILED ; + + psf->codec_data = pxi ; + + if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = xi_read_header (psf))) + return error ; + } ; + + subformat = psf->sf.format & SF_FORMAT_SUBMASK ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_XI) + return SFE_BAD_OPEN_FORMAT ; + + psf->endian = SF_ENDIAN_LITTLE ; + psf->sf.channels = 1 ; /* Always mono */ + psf->sf.samplerate = 44100 ; /* Always */ + + /* Set up default instrument and software name. */ + memcpy (pxi->filename, "Default Name ", sizeof (pxi->filename)) ; + memcpy (pxi->software, PACKAGE "-" VERSION " ", sizeof (pxi->software)) ; + + memset (pxi->sample_name, 0, sizeof (pxi->sample_name)) ; + LSF_SNPRINTF (pxi->sample_name, sizeof (pxi->sample_name), "%s", "Sample #1") ; + + pxi->sample_flags = (subformat == SF_FORMAT_DPCM_16) ? 16 : 0 ; + + if (xi_write_header (psf, SF_FALSE)) + return psf->error ; + + psf->write_header = xi_write_header ; + } ; + + psf->container_close = xi_close ; + psf->seek = dpcm_seek ; + + psf->sf.seekable = SF_FALSE ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + switch (subformat) + { case SF_FORMAT_DPCM_8 : /* 8-bit differential PCM. */ + case SF_FORMAT_DPCM_16 : /* 16-bit differential PCM. */ + error = dpcm_init (psf) ; + break ; + + default : break ; + } ; + + return error ; +} /* xi_open */ + +/*------------------------------------------------------------------------------ +*/ + +static int +xi_close (SF_PRIVATE *psf) +{ + psf = psf ; + + return 0 ; +} /* xi_close */ + +/*============================================================================== +*/ + +static sf_count_t dpcm_read_dsc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t dpcm_read_dsc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t dpcm_read_dsc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t dpcm_read_dsc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t dpcm_write_s2dsc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t dpcm_write_i2dsc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t dpcm_write_f2dsc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t dpcm_write_d2dsc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static sf_count_t dpcm_read_dles2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; +static sf_count_t dpcm_read_dles2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; +static sf_count_t dpcm_read_dles2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; +static sf_count_t dpcm_read_dles2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; + +static sf_count_t dpcm_write_s2dles (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; +static sf_count_t dpcm_write_i2dles (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; +static sf_count_t dpcm_write_f2dles (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; +static sf_count_t dpcm_write_d2dles (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; + +static int +dpcm_init (SF_PRIVATE *psf) +{ if (psf->bytewidth == 0 || psf->sf.channels == 0) + return SFE_INTERNAL ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) + { switch (psf->bytewidth) + { case 1 : + psf->read_short = dpcm_read_dsc2s ; + psf->read_int = dpcm_read_dsc2i ; + psf->read_float = dpcm_read_dsc2f ; + psf->read_double = dpcm_read_dsc2d ; + break ; + case 2 : + psf->read_short = dpcm_read_dles2s ; + psf->read_int = dpcm_read_dles2i ; + psf->read_float = dpcm_read_dles2f ; + psf->read_double = dpcm_read_dles2d ; + break ; + default : + psf_log_printf (psf, "dpcm_init() returning SFE_UNIMPLEMENTED\n") ; + return SFE_UNIMPLEMENTED ; + } ; + } ; + + if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) + { switch (psf->bytewidth) + { case 1 : + psf->write_short = dpcm_write_s2dsc ; + psf->write_int = dpcm_write_i2dsc ; + psf->write_float = dpcm_write_f2dsc ; + psf->write_double = dpcm_write_d2dsc ; + break ; + case 2 : + psf->write_short = dpcm_write_s2dles ; + psf->write_int = dpcm_write_i2dles ; + psf->write_float = dpcm_write_f2dles ; + psf->write_double = dpcm_write_d2dles ; + break ; + default : + psf_log_printf (psf, "dpcm_init() returning SFE_UNIMPLEMENTED\n") ; + return SFE_UNIMPLEMENTED ; + } ; + } ; + + psf->filelength = psf_get_filelen (psf) ; + psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : + psf->filelength - psf->dataoffset ; + psf->sf.frames = psf->datalength / psf->blockwidth ; + + return 0 ; +} /* dpcm_init */ + +/*============================================================================== +*/ + +static sf_count_t +dpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) +{ XI_PRIVATE *pxi ; + int total, bufferlen, len ; + + if ((pxi = psf->codec_data) == NULL) + return SFE_INTERNAL ; + + if (psf->datalength < 0 || psf->dataoffset < 0) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (offset == 0) + { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + pxi->last_16 = 0 ; + return 0 ; + } ; + + if (offset < 0 || offset > psf->sf.frames) + { psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + if (mode != SFM_READ) + { /* What to do about write??? */ + psf->error = SFE_BAD_SEEK ; + return PSF_SEEK_ERROR ; + } ; + + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + + if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_DPCM_16) + { total = offset ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (total > 0) + { len = (total > bufferlen) ? bufferlen : total ; + total -= dpcm_read_dles2s (psf, psf->u.sbuf, len) ; + } ; + } + else + { total = offset ; + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + while (total > 0) + { len = (total > bufferlen) ? bufferlen : total ; + total -= dpcm_read_dsc2s (psf, psf->u.sbuf, len) ; + } ; + } ; + + return offset ; +} /* dpcm_seek */ + + +static int +xi_write_header (SF_PRIVATE *psf, int calc_length) +{ XI_PRIVATE *pxi ; + sf_count_t current ; + const char *string ; + + if ((pxi = psf->codec_data) == NULL) + return SFE_INTERNAL ; + + calc_length = calc_length ; /* Avoid a compiler warning. */ + + current = psf_ftell (psf) ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + string = "Extended Instrument: " ; + psf_binheader_writef (psf, "b", string, strlen (string)) ; + psf_binheader_writef (psf, "b1", pxi->filename, sizeof (pxi->filename), 0x1A) ; + + /* Write software version and two byte XI version. */ + psf_binheader_writef (psf, "eb2", pxi->software, sizeof (pxi->software), (1 << 8) + 2) ; + + /* + ** Jump note numbers (96), volume envelope (48), pan envelope (48), + ** volume points (1), pan points (1) + */ + psf_binheader_writef (psf, "z", (size_t) (96 + 48 + 48 + 1 + 1)) ; + + /* Jump volume loop (3 bytes), pan loop (3), envelope flags (3), vibrato (3) + ** fade out (2), 22 unknown bytes, and then write sample_count (2 bytes). + */ + psf_binheader_writef (psf, "ez2z2", (size_t) (4 * 3), 0x1234, make_size_t (22), 1) ; + + pxi->loop_begin = 0 ; + pxi->loop_end = 0 ; + + psf_binheader_writef (psf, "et844", psf->sf.frames, pxi->loop_begin, pxi->loop_end) ; + + /* volume, fine tune, flags, pan, note, namelen */ + psf_binheader_writef (psf, "111111", 128, 0, pxi->sample_flags, 128, 0, strlen (pxi->sample_name)) ; + + psf_binheader_writef (psf, "b", pxi->sample_name, sizeof (pxi->sample_name)) ; + + + + + + /* Header construction complete so write it out. */ + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + + if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* xi_write_header */ + +static int +xi_read_header (SF_PRIVATE *psf) +{ char buffer [64], name [32] ; + short version, fade_out, sample_count ; + int k, loop_begin, loop_end ; + int sample_sizes [MAX_XI_SAMPLES] ; + + psf_binheader_readf (psf, "pb", 0, buffer, 21) ; + + memset (sample_sizes, 0, sizeof (sample_sizes)) ; + + buffer [20] = 0 ; + if (strcmp (buffer, "Extended Instrument:") != 0) + return SFE_XI_BAD_HEADER ; + + memset (buffer, 0, sizeof (buffer)) ; + psf_binheader_readf (psf, "b", buffer, 23) ; + + if (buffer [22] != 0x1A) + return SFE_XI_BAD_HEADER ; + + buffer [22] = 0 ; + psf_log_printf (psf, "Extended Instrument : %s\n", buffer) ; + + psf_binheader_readf (psf, "be2", buffer, 20, &version) ; + buffer [19] = 0 ; + psf_log_printf (psf, "Software : %s\nVersion : %d.%02d\n", buffer, version / 256, version % 256) ; + + /* Jump note numbers (96), volume envelope (48), pan envelope (48), + ** volume points (1), pan points (1) + */ + psf_binheader_readf (psf, "j", 96 + 48 + 48 + 1 + 1) ; + + psf_binheader_readf (psf, "b", buffer, 12) ; + psf_log_printf (psf, "Volume Loop\n sustain : %u\n begin : %u\n end : %u\n", + buffer [0], buffer [1], buffer [2]) ; + psf_log_printf (psf, "Pan Loop\n sustain : %u\n begin : %u\n end : %u\n", + buffer [3], buffer [4], buffer [5]) ; + psf_log_printf (psf, "Envelope Flags\n volume : 0x%X\n pan : 0x%X\n", + buffer [6] & 0xFF, buffer [7] & 0xFF) ; + + psf_log_printf (psf, "Vibrato\n type : %u\n sweep : %u\n depth : %u\n rate : %u\n", + buffer [8], buffer [9], buffer [10], buffer [11]) ; + + /* + ** Read fade_out then jump reserved (2 bytes) and ???? (20 bytes) and + ** sample_count. + */ + psf_binheader_readf (psf, "e2j2", &fade_out, 2 + 20, &sample_count) ; + psf_log_printf (psf, "Fade out : %d\n", fade_out) ; + + /* XI file can contain up to 16 samples. */ + if (sample_count > MAX_XI_SAMPLES) + return SFE_XI_EXCESS_SAMPLES ; + + if (psf->instrument == NULL && (psf->instrument = psf_instrument_alloc ()) == NULL) + return SFE_MALLOC_FAILED ; + + /* Log all data for each sample. */ + for (k = 0 ; k < sample_count ; k++) + { psf_binheader_readf (psf, "e444", &(sample_sizes [k]), &loop_begin, &loop_end) ; + + /* Read 5 know bytes, 1 unknown byte and 22 name bytes. */ + psf_binheader_readf (psf, "bb", buffer, 6, name, 22) ; + name [21] = 0 ; + + psf_log_printf (psf, "Sample #%d\n name : %s\n", k + 1, name) ; + + psf_log_printf (psf, " size : %d\n", sample_sizes [k]) ; + + + + psf_log_printf (psf, " loop\n begin : %d\n end : %d\n", loop_begin, loop_end) ; + + psf_log_printf (psf, " volume : %u\n f. tune : %d\n flags : 0x%02X ", + buffer [0] & 0xFF, buffer [1] & 0xFF, buffer [2] & 0xFF) ; + + psf_log_printf (psf, " (") ; + if (buffer [2] & 1) + psf_log_printf (psf, " Loop") ; + if (buffer [2] & 2) + psf_log_printf (psf, " PingPong") ; + psf_log_printf (psf, (buffer [2] & 16) ? " 16bit" : " 8bit") ; + psf_log_printf (psf, " )\n") ; + + psf_log_printf (psf, " pan : %u\n note : %d\n namelen : %d\n", + buffer [3] & 0xFF, buffer [4], buffer [5]) ; + + if (k != 0) + continue ; + + if (buffer [2] & 16) + { psf->sf.format = SF_FORMAT_XI | SF_FORMAT_DPCM_16 ; + psf->bytewidth = 2 ; + } + else + { psf->sf.format = SF_FORMAT_XI | SF_FORMAT_DPCM_8 ; + psf->bytewidth = 1 ; + } ; + } ; + + while (sample_count > 1 && sample_sizes [sample_count - 1] == 0) + sample_count -- ; + + /* Currently, we can only handle 1 sample per file. */ + + if (sample_count > 2) + { psf_log_printf (psf, "*** Sample count is less than 16 but more than 1.\n") ; + psf_log_printf (psf, " sample count : %d sample_sizes [%d] : %d\n", + sample_count, sample_count - 1, sample_sizes [sample_count - 1]) ; + return SFE_XI_EXCESS_SAMPLES ; + } ; + + psf->dataoffset = psf_fseek (psf, 0, SEEK_CUR) ; + psf_log_printf (psf, "Data Offset : %D\n", psf->dataoffset) ; + + psf->datalength = sample_sizes [0] ; + + if (psf->dataoffset + psf->datalength > psf->filelength) + { psf_log_printf (psf, "*** File seems to be truncated. Should be at least %D bytes long.\n", + psf->dataoffset + sample_sizes [0]) ; + psf->datalength = psf->filelength - psf->dataoffset ; + } ; + + if (psf_fseek (psf, psf->dataoffset, SEEK_SET) != psf->dataoffset) + return SFE_BAD_SEEK ; + + psf->endian = SF_ENDIAN_LITTLE ; + psf->sf.channels = 1 ; /* Always mono */ + psf->sf.samplerate = 44100 ; /* Always */ + + psf->blockwidth = psf->sf.channels * psf->bytewidth ; + + if (! psf->sf.frames && psf->blockwidth) + psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; + + psf->instrument->basenote = 0 ; + psf->instrument->gain = 1 ; + psf->instrument->velocity_lo = psf->instrument->key_lo = 0 ; + psf->instrument->velocity_hi = psf->instrument->key_hi = 127 ; + + return 0 ; +} /* xi_read_header */ + +/*============================================================================== +*/ + +static void dsc2s_array (XI_PRIVATE *pxi, signed char *src, int count, short *dest) ; +static void dsc2i_array (XI_PRIVATE *pxi, signed char *src, int count, int *dest) ; +static void dsc2f_array (XI_PRIVATE *pxi, signed char *src, int count, float *dest, float normfact) ; +static void dsc2d_array (XI_PRIVATE *pxi, signed char *src, int count, double *dest, double normfact) ; + +static void dles2s_array (XI_PRIVATE *pxi, short *src, int count, short *dest) ; +static void dles2i_array (XI_PRIVATE *pxi, short *src, int count, int *dest) ; +static void dles2f_array (XI_PRIVATE *pxi, short *src, int count, float *dest, float normfact) ; +static void dles2d_array (XI_PRIVATE *pxi, short *src, int count, double *dest, double normfact) ; + +static sf_count_t +dpcm_read_dsc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + dsc2s_array (pxi, psf->u.scbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dsc2s */ + +static sf_count_t +dpcm_read_dsc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + dsc2i_array (pxi, psf->u.scbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dsc2i */ + +static sf_count_t +dpcm_read_dsc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + dsc2f_array (pxi, psf->u.scbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dsc2f */ + +static sf_count_t +dpcm_read_dsc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + dsc2d_array (pxi, psf->u.scbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dsc2d */ + +/*------------------------------------------------------------------------------ +*/ + +static sf_count_t +dpcm_read_dles2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + dles2s_array (pxi, psf->u.sbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dles2s */ + +static sf_count_t +dpcm_read_dles2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + dles2i_array (pxi, psf->u.sbuf, readcount, ptr + total) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dles2i */ + +static sf_count_t +dpcm_read_dles2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + float normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + dles2f_array (pxi, psf->u.sbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dles2f */ + +static sf_count_t +dpcm_read_dles2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, readcount ; + sf_count_t total = 0 ; + double normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + readcount = psf_fread (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + dles2d_array (pxi, psf->u.sbuf, readcount, ptr + total, normfact) ; + total += readcount ; + if (readcount < bufferlen) + break ; + len -= readcount ; + } ; + + return total ; +} /* dpcm_read_dles2d */ + +/*============================================================================== +*/ + +static void s2dsc_array (XI_PRIVATE *pxi, const short *src, signed char *dest, int count) ; +static void i2dsc_array (XI_PRIVATE *pxi, const int *src, signed char *dest, int count) ; +static void f2dsc_array (XI_PRIVATE *pxi, const float *src, signed char *dest, int count, float normfact) ; +static void d2dsc_array (XI_PRIVATE *pxi, const double *src, signed char *dest, int count, double normfact) ; + +static void s2dles_array (XI_PRIVATE *pxi, const short *src, short *dest, int count) ; +static void i2dles_array (XI_PRIVATE *pxi, const int *src, short *dest, int count) ; +static void f2dles_array (XI_PRIVATE *pxi, const float *src, short *dest, int count, float normfact) ; +static void d2dles_array (XI_PRIVATE *pxi, const double *src, short *dest, int count, double normfact) ; + + +static sf_count_t +dpcm_write_s2dsc (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2dsc_array (pxi, ptr + total, psf->u.scbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_s2dsc */ + +static sf_count_t +dpcm_write_i2dsc (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2dsc_array (pxi, ptr + total, psf->u.scbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_i2dsc */ + +static sf_count_t +dpcm_write_f2dsc (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + float normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7F) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + f2dsc_array (pxi, ptr + total, psf->u.scbuf, bufferlen, normfact) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_f2dsc */ + +static sf_count_t +dpcm_write_d2dsc (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + double normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7F) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.ucbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + d2dsc_array (pxi, ptr + total, psf->u.scbuf, bufferlen, normfact) ; + writecount = psf_fwrite (psf->u.scbuf, sizeof (signed char), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_d2dsc */ + + +static sf_count_t +dpcm_write_s2dles (SF_PRIVATE *psf, const short *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + s2dles_array (pxi, ptr + total, psf->u.sbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_s2dles */ + +static sf_count_t +dpcm_write_i2dles (SF_PRIVATE *psf, const int *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + i2dles_array (pxi, ptr + total, psf->u.sbuf, bufferlen) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_i2dles */ + +static sf_count_t +dpcm_write_f2dles (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + float normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + f2dles_array (pxi, ptr + total, psf->u.sbuf, bufferlen, normfact) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_f2dles */ + +static sf_count_t +dpcm_write_d2dles (SF_PRIVATE *psf, const double *ptr, sf_count_t len) +{ XI_PRIVATE *pxi ; + int bufferlen, writecount ; + sf_count_t total = 0 ; + double normfact ; + + if ((pxi = psf->codec_data) == NULL) + return 0 ; + + normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; + + bufferlen = ARRAY_LEN (psf->u.sbuf) ; + + while (len > 0) + { if (len < bufferlen) + bufferlen = (int) len ; + d2dles_array (pxi, ptr + total, psf->u.sbuf, bufferlen, normfact) ; + writecount = psf_fwrite (psf->u.sbuf, sizeof (short), bufferlen, psf) ; + total += writecount ; + if (writecount < bufferlen) + break ; + len -= writecount ; + } ; + + return total ; +} /* dpcm_write_d2dles */ + + +/*============================================================================== +*/ + +static void +dsc2s_array (XI_PRIVATE *pxi, signed char *src, int count, short *dest) +{ signed char last_val ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { last_val += src [k] ; + dest [k] = last_val << 8 ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* dsc2s_array */ + +static void +dsc2i_array (XI_PRIVATE *pxi, signed char *src, int count, int *dest) +{ signed char last_val ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { last_val += src [k] ; + dest [k] = last_val << 24 ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* dsc2i_array */ + +static void +dsc2f_array (XI_PRIVATE *pxi, signed char *src, int count, float *dest, float normfact) +{ signed char last_val ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { last_val += src [k] ; + dest [k] = last_val * normfact ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* dsc2f_array */ + +static void +dsc2d_array (XI_PRIVATE *pxi, signed char *src, int count, double *dest, double normfact) +{ signed char last_val ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { last_val += src [k] ; + dest [k] = last_val * normfact ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* dsc2d_array */ + +/*------------------------------------------------------------------------------ +*/ + +static void +s2dsc_array (XI_PRIVATE *pxi, const short *src, signed char *dest, int count) +{ signed char last_val, current ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { current = src [k] >> 8 ; + dest [k] = current - last_val ; + last_val = current ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* s2dsc_array */ + +static void +i2dsc_array (XI_PRIVATE *pxi, const int *src, signed char *dest, int count) +{ signed char last_val, current ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { current = src [k] >> 24 ; + dest [k] = current - last_val ; + last_val = current ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* i2dsc_array */ + +static void +f2dsc_array (XI_PRIVATE *pxi, const float *src, signed char *dest, int count, float normfact) +{ signed char last_val, current ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { current = lrintf (src [k] * normfact) ; + dest [k] = current - last_val ; + last_val = current ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* f2dsc_array */ + +static void +d2dsc_array (XI_PRIVATE *pxi, const double *src, signed char *dest, int count, double normfact) +{ signed char last_val, current ; + int k ; + + last_val = pxi->last_16 >> 8 ; + + for (k = 0 ; k < count ; k++) + { current = lrint (src [k] * normfact) ; + dest [k] = current - last_val ; + last_val = current ; + } ; + + pxi->last_16 = last_val << 8 ; +} /* d2dsc_array */ + +/*============================================================================== +*/ + +static void +dles2s_array (XI_PRIVATE *pxi, short *src, int count, short *dest) +{ short last_val ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { last_val += LES2H_SHORT (src [k]) ; + dest [k] = last_val ; + } ; + + pxi->last_16 = last_val ; +} /* dles2s_array */ + +static void +dles2i_array (XI_PRIVATE *pxi, short *src, int count, int *dest) +{ short last_val ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { last_val += LES2H_SHORT (src [k]) ; + dest [k] = last_val << 16 ; + } ; + + pxi->last_16 = last_val ; +} /* dles2i_array */ + +static void +dles2f_array (XI_PRIVATE *pxi, short *src, int count, float *dest, float normfact) +{ short last_val ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { last_val += LES2H_SHORT (src [k]) ; + dest [k] = last_val * normfact ; + } ; + + pxi->last_16 = last_val ; +} /* dles2f_array */ + +static void +dles2d_array (XI_PRIVATE *pxi, short *src, int count, double *dest, double normfact) +{ short last_val ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { last_val += LES2H_SHORT (src [k]) ; + dest [k] = last_val * normfact ; + } ; + + pxi->last_16 = last_val ; +} /* dles2d_array */ + +/*------------------------------------------------------------------------------ +*/ + +static void +s2dles_array (XI_PRIVATE *pxi, const short *src, short *dest, int count) +{ short diff, last_val ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { diff = src [k] - last_val ; + dest [k] = LES2H_SHORT (diff) ; + last_val = src [k] ; + } ; + + pxi->last_16 = last_val ; +} /* s2dles_array */ + +static void +i2dles_array (XI_PRIVATE *pxi, const int *src, short *dest, int count) +{ short diff, last_val ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { diff = (src [k] >> 16) - last_val ; + dest [k] = LES2H_SHORT (diff) ; + last_val = src [k] >> 16 ; + } ; + + pxi->last_16 = last_val ; +} /* i2dles_array */ + +static void +f2dles_array (XI_PRIVATE *pxi, const float *src, short *dest, int count, float normfact) +{ short diff, last_val, current ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { current = lrintf (src [k] * normfact) ; + diff = current - last_val ; + dest [k] = LES2H_SHORT (diff) ; + last_val = current ; + } ; + + pxi->last_16 = last_val ; +} /* f2dles_array */ + +static void +d2dles_array (XI_PRIVATE *pxi, const double *src, short *dest, int count, double normfact) +{ short diff, last_val, current ; + int k ; + + last_val = pxi->last_16 ; + + for (k = 0 ; k < count ; k++) + { current = lrint (src [k] * normfact) ; + diff = current - last_val ; + dest [k] = LES2H_SHORT (diff) ; + last_val = current ; + } ; + + pxi->last_16 = last_val ; +} /* d2dles_array */ + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: 1ab2dbe0-29af-4d80-9c6f-cb21b67521bc +*/ diff --git a/nyqide/doc/nyqide_plot.gif b/nyqide/doc/nyqide_plot.gif new file mode 100644 index 0000000..9a5eec3 Binary files /dev/null and b/nyqide/doc/nyqide_plot.gif differ diff --git a/nyqide/doc/nyquistide.gif b/nyqide/doc/nyquistide.gif new file mode 100644 index 0000000..908baa1 Binary files /dev/null and b/nyqide/doc/nyquistide.gif differ diff --git a/nyqide/doc/tips.htm b/nyqide/doc/tips.htm new file mode 100644 index 0000000..4d11d5c --- /dev/null +++ b/nyqide/doc/tips.htm @@ -0,0 +1,122 @@ + + + + Untitled Document + + + + + +

    Tips for Nyquist IDE

    + +

    NyqIDE Interface +

    + +
      +
    • +
      +

      In the Command Line Window, use Alt + Up and Alt + Down +to retrieve recently entered commands. It can be retrieved up to last ten +commands.
      +

      +
      +
    • +
    • +
      +

      In the Command Line Window, use Alt + Enter to begin a new +line (for the purpose of inputting multiple lines). Only press Enter +will send the input to the Nyquist kernel.
      +

      +
      +
    • +
    • +
      +

      In the Command Line Window or Document Window, double click +or select the "Select Complete Paragraph" Item in the popup menu right +before an open paren, the system will automatically select the text that +begins with this open paren and ends with the corresponding close paren. +This will be helpful for checking the matching parens or loading a complete +function.

      +
      +
    • +
    • +
      +

      In the Command Window or Document Window, select the "Load Selected +Text" Item in the popup menu to load the selected text.

      +
      +
    • +
    • +
      +

      The way the Paren Matching works: When type in a close paren, +the cursor jumps to the corresponding open paren and blinks, then it returns +to the close paren. The function can be disabled from the main menu.
      +

      +
      +
    • +
    • +
      +

      NyqIDE Plot Window +To plot sounds in a window, either type (s-plot ...) function in the Command +Line Window/document to be loaded, or click the speed button S-Plot/through +the menu Process-->S-Plot, a Plot Window will pop up and +show the plots. Multiple Plot Windows can be displayed at the same time as +the children windows of the program. There are some shortcut keys for the +Plot Window: Shift + Mouse Drag to zoom in; Ctrl + Mouse Drag +to pan (move the center of the view); Shift + Mouse Left Click to +restore the original view of the plot; Mouse Right Click to pop up +the menu. Advanced functions are listed in the pop up menu, including figure +copy, view options, and zoom options.
      +

      +
      +
    • +
    • +
      +

      The program keeps the history of up to five most recently used (MRU) +documents. And you can speedily reopen those MRU documents by getting through +the menu File-->Reopen-->MRU List.
      +

      +
      +
    • +
    • +
      +

      The system working directory will be always set to the directory of +the most recently opened document, no matter whether the document is opened +from the open dialog or from the MRU List. It means that the temporary sound +file and the plot file (if created) will be also created in that working +directory.
      +

      +
      +
    • +
    • +
      +

      "Help Contents", "Topic Search" and "NyqIDE Tips" +are local or online documentations. The program will first try to locate +the documentations locally. If failed, the program will try to locate the +online documentations.
      +

      +
      +
    • +
    • +
      +

      Function keys F2-F12 are related to the functions with the +same key names. E.g. Press F2 (or click the speed button F2 +or go through the menu Process-->Function Keys-->Function F2) +is equivalent to typing "(F2)" in the Command Line Window. However, pressing F1 +will display the "Topic Search" documentation.
      +

      +
      +
    • +
    • We welcome your suggestion to improve this program. This program was +made in order to let Nyquist easier to use and friendlier to the programmers.
      +
      +
      Written by Ning Hu(ninghu@cs.cmu.edu)
      +Last update: Nov.2002
      +
      +


      +

      +
    • +
    + + diff --git a/nyqide/nyqide_src.zip b/nyqide/nyqide_src.zip new file mode 100644 index 0000000..93bb71c Binary files /dev/null and b/nyqide/nyqide_src.zip differ diff --git a/nyqide/readme-vcl.txt b/nyqide/readme-vcl.txt new file mode 100644 index 0000000..1355de4 --- /dev/null +++ b/nyqide/readme-vcl.txt @@ -0,0 +1,8 @@ +NyqIDE is using some free and open source VCL components listed as below: + +VCL Name URL +==================== ================================ +dfsMRUFileList v2.66 http://www.delphifreestuff.com +SGraph v2.4 http://pod0.chat.ru/prg_staf.htm +SimpleThread v1.0 eugene@actcom.co.il +SynEdit v1.1 http://synedit.sourceforge.net/ diff --git a/nyqsrc/add.c b/nyqsrc/add.c new file mode 100644 index 0000000..0b518f1 --- /dev/null +++ b/nyqsrc/add.c @@ -0,0 +1,917 @@ +/* add.c -- add two signals */ +/* CHANGE LOG + * 19May92 rbd fix t0 to mean time rather than samples + fix to logically stop and terminate at MAX of 2 inputs + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +/* DOCUMENTATION: + Most DSP modules in Nyquist select a single fetch routine +and use it until the signal terminates. The ADD operation +instead can use a number of different fetch routines in sequence. +This allows ADD to do the most efficient computation, such as +simply copying pointers when only one input signal is defined +(the other is zero.) + Here's what the functions assume and do: +add_s1_s2_nn_fetch: both arguments (s1, s2) have signals; add + them. +add_s1_nn_fetch: only s1 is active, so pass along pointers if + possible. Revert to add_s1_s2_nn_fetch when s2 becomes active. +add_s2_nn_fetch: symetric with add_s1_nn_fetch. +add_zero_fill_nn_fetch: fill in when one input has terminated and + the other hasn't begun. + +An important optimization (we think) is the ability to collapse +ADD operations. When one operand goes to zero, the ADD just +passes along pointers to blocks from the other operand. In some +cases, we can just splice out the ADD suspension and link +directly to the suspension of the second operand. + +Doing this requires that there be no scale factors, so ADD does +not deal with scaling. If an operand comes in with a scale +factor, ADD will create a rescaling of the operand. +*/ + +#include "switches.h" +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "cext.h" +#include "scale.h" +#include "multiseq.h" +#include "add.h" +#include "assert.h" + + +#define debugA 0 +#define A if (debugA) +/* I don't know how these debug switches (A and D) differ: */ +#define D A + +/* switch B is/was to look for a particular zero block length bug */ +#define debugB 0 +#define B if (debugB | debugA) + +/* #define GC_DEBUG 1 */ + + +void add_s1_s2_nn_fetch(add_susp_type, snd_list_type); +void add_s1_nn_fetch(add_susp_type, snd_list_type); +void add_s2_nn_fetch(add_susp_type, snd_list_type); +void add_zero_fill_nn_fetch(add_susp_type, snd_list_type); +void add_free(); + + +void add_s1_s2_nn_fetch(susp, snd_list) + register add_susp_type susp; + snd_list_type snd_list; +{ + int cnt = 0; /* how many samples computed */ + int togo; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + register sample_block_values_type s1_ptr_reg; + register sample_block_values_type s2_ptr_reg; + register sample_block_values_type out_ptr_reg; + +#ifdef GC_DEBUG + snd_list_report(snd_list, "add_s1_s2_nn_fetch"); +#endif + /* assume the snd_list is the one with a null block */ + /* put a fresh, clean block in the snd_list (get new snd_list later) */ + falloc_sample_block(out, "add_s1_s2_nn_fetch"); + snd_list->block = out; + out_ptr = out->samples; +A nyquist_printf("add[%p,%p] (s1_s2_nn) %p new block %p\n", + susp->s1, susp->s2, susp, out); + + /* fill up the new block */ + while (cnt < max_sample_block_len && susp->terminate_bits == 0) { +A nyquist_printf("add[%p,%p] (s1_s2_nn) %p starting outer loop, cnt %d\n", + susp->s1, susp->s2, susp, cnt); + + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = max_sample_block_len - cnt; + + /* don't run past the s1 input sample block: */ +A nyquist_printf("add[%p,%p]: look for samples (for s1) \n", susp->s1, susp->s2); +/* if (!susp->s1->list->block) watch_susp(susp->s1->list->u.susp); */ + susp_check_term_log_block_samples(s1, s1_bptr, s1_ptr, s1_cnt, 1, 3); +A nyquist_printf("add[%p,%p]: found samples (for s1) s1_cnt=%d\n", + susp->s1, susp->s2, (int)susp->s1_cnt); + togo = MIN(togo, susp->s1_cnt); + if (susp->terminate_bits & 1) { +A nyquist_printf("add[%p,%p]: terminate bits on (for s1) togo=%d\n", + susp->s1, susp->s2, togo); + } + + /* don't run past the s2 input sample block: */ +A nyquist_printf("add[%p,%p]: look for samples (for s2) \n", susp->s1, susp->s2); + susp_check_term_log_block_samples(s2, s2_bptr, s2_ptr, s2_cnt, 2, 3); +A nyquist_printf("add[%p,%p]: found samples (for s2) s2_cnt=%d\n", + susp->s1, susp->s2, (int)susp->s2_cnt); + togo = MIN(togo, susp->s2_cnt); +A if (susp->terminate_bits & 2) { + nyquist_printf("add[%p,%p]: terminate bits on (for s2) togo=%d\n", + susp->s1, susp->s2, togo); + } + + /* don't run past logical stop time (need to check this even + * if a sound has terminated) + */ +A nyquist_printf( + "add[%p,%p] (s1_s2_nn) %p: logically_stopped %d, logical_stop_cnt %d, s1 logical_stop_cnt %ld, s2 logical_stop_cnt %ld \n", + susp->s1, susp->s2, susp, susp->logically_stopped, + (int) susp->susp.log_stop_cnt, + susp->s1->logical_stop_cnt, + susp->s2->logical_stop_cnt); + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN && + (susp->logical_stop_bits == 3)) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); +A nyquist_printf("add[%p,%p]: to_stop = %d\n", susp->s1, susp->s2, to_stop); + /* logical stops have to be indicated on block boundaries */ + if (to_stop < togo) { + if (to_stop == 0) { + if (cnt) { + togo = 0; + break; /* block is non-empty, log-stop on next block */ + } else /* to_stop is 0, indicate logical stop immediately */ + susp->logically_stopped = true; + } else { + /* logical stop will take place on the following block, + * so compute up to logical stop and return partial block + */ + togo = to_stop; + } + } + } + + /* check please */ + if (susp->terminate_bits) { + break; + } + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); +D nyquist_printf("add[%p,%p]: togo = %d\n", susp->s1, susp->s2, togo); + if (togo == 0) break; + } + + n = togo; +A nyquist_printf("add[%p,%p] (s1_s2_nn) %p starting inner loop, n %d\n", + susp->s1, susp->s2, susp, n); + s1_ptr_reg = susp->s1_ptr; + s2_ptr_reg = susp->s2_ptr; + out_ptr_reg = out_ptr; + if (n) do { /* the inner sample computation loop */ + /* scale? */ +A nyquist_printf("add_s1_s2_nn: %g + %g\n", *s1_ptr_reg, *s2_ptr_reg); + *out_ptr_reg++ = *(s1_ptr_reg++) + *(s2_ptr_reg++); + } while (--n); /* inner loop */ + /* using s1_ptr_reg is a bad idea on RS/6000 */ + susp->s1_ptr += togo; + /* using s2_ptr_reg is a bad idea on RS/6000 */ + susp->s2_ptr += togo; + /* using out_ptr_reg is a bad idea on RS/6000 */ + out_ptr += togo; + susp_took(s1_cnt, togo); + susp_took(s2_cnt, togo); + cnt += togo; + } /* outer loop */ + +A nyquist_printf("add[%p,%p] (s1_s2_nn) %p ending outer loop, cnt %d\n", + susp->s1, susp->s2, susp, cnt); + + snd_list->block_len = cnt; + + /* test for logical stop - normally this is detected by + * susp.log_stop_cnt == susp->susp.current, but then the logical + * stop flag is set on the NEXT block. To remember to set on the + * NEXT block, set susp->logically_stopped, which is also tested + * below. One special case is if the current block should indicate + * logically stopped (this happens sometimes when the sounds have + * zero logical length) then susp->logically_stopped will be set + * (see above) and we just never test susp->susp.log_stop_cnt. + */ + if (susp->logically_stopped) { +A nyquist_printf("add[%p,%p] (s1_s2_nn) %p->logically_stopped already true\n", + susp->s1, susp->s2, susp); + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current && + susp->logical_stop_bits == 3) { +A nyquist_printf("add[%p,%p] (s1_s2_nn) %p->logically_stopped set to true\n", + susp->s1, susp->s2, susp); + susp->logically_stopped = true; + } + + /* test for termination of s1 */ + if (susp->terminate_bits == 3) { +D nyquist_printf("add[%p,%p] (s1_s2_nn) s1 and s2 terminated, unrefed\n", + susp->s1, susp->s2); + /* free susp and point to terminal zeros (leaving pending snd_lists)*/ + if (cnt) { + /* we have samples, put zero_block at end */ + snd_list_unref(snd_list->u.next); + snd_list->u.next = zero_snd_list; + } else { + /* no samples generated */ + snd_list_terminate(snd_list); + } +D nyquist_printf("add[%p,%p] (s1_s2_nn) %p terminated.\n", + susp->s1, susp->s2, susp); + } else { + if (susp->terminate_bits & 1) { +D nyquist_printf("add[%p,%p] (s1_s2_nn) s1 terminated, unrefed\n", + susp->s1, susp->s2); + sound_unref(susp->s1); + susp->s1 = NULL; + susp->susp.fetch = add_s2_nn_fetch; +D nyquist_printf("add_s1_s2_nn_fetch: add_s2_nn_fetch installed\n"); + if (cnt == 0) { +D nyquist_printf("add[%p,%p]: calling add_s2_nn_fetch\n", + susp->s1, susp->s2); + add_s2_nn_fetch(susp, snd_list); + } + } + else if (susp->terminate_bits & 2) { +D nyquist_printf("add[%p,%p] (s1_s2_nn) s2 terminated, unrefed\n", + susp->s1, susp->s2); + sound_unref(susp->s2); + susp->s2 = NULL; + susp->susp.fetch = add_s1_nn_fetch; +D stdputstr("add_s1_s2_nn_fetch: add_s1_nn_fetch installed\n"); + if (cnt == 0) { +D nyquist_printf("add[%p,%p]: calling add_s1_nn_fetch\n", + susp->s1, susp->s2); + add_s1_nn_fetch(susp, snd_list); + } + } + + /* add a new snd_list for the susp */ + susp->susp.current += cnt; + } + +} /* add_s1_s2_nn_fetch */ + + + +/* Note that add_s1_nn_fetch and add_s2_nn_fetch are symetric. + * They should probably be made into one routine, but for now, + * any changes to one should be made to the other. + */ +void add_s1_nn_fetch(susp, snd_list) + register add_susp_type susp; + snd_list_type snd_list; +{ + /* expansion of add_s_nn_fetch(snd_list,s1,s2,1); follows: */ + int togo, s2_start=0; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + +D nyquist_printf("add_s1_nn_fetch(susp %p, snd_list %p, s1_cnt %d)\n", + susp, snd_list, (int)susp->s1_cnt); + +#ifdef GC_DEBUG + snd_list_report(snd_list, "add_s1_nn_fetch"); +#endif + /* + * first compute how many samples to copy (or transfer) + */ + + /* see what the next samples look like */ + susp_check_term_log_block_samples(s1, s1_bptr, + s1_ptr, s1_cnt, 1, 3); +B if (susp->terminate_bits & 1) + nyquist_printf("add[%p,%p]: s1 terminates\n", susp->s1, susp->s2); + + /* don't run past the s1 input sample block: */ + togo = susp->s1_cnt; +B if (togo == 0) stdputstr("togo is zero at checkpoint 1\n"); + + /* don't run past terminate time of this signal */ +/* if (susp->s1_ptr == zero_block->samples) { -sep21 RBD*/ + if (susp->terminate_bits & 1) { + if (susp->s2) { + s2_start = (long) ((susp->s2->t0 - susp->susp.t0) * + susp->s2->sr + 0.5); +D nyquist_printf("add_s_nn_fetch: s2_start %d\n", s2_start); + } + togo = 0; +B if (togo == 0) stdputstr("togo is zero at checkpoint 2\n"); + if (susp->s2 && susp->susp.current == s2_start) { + /* s2 starting and s1 stops */ + /* go to s2 alone state */ + sound_unref(susp->s1); + susp->s1 = NULL; + susp->susp.fetch = add_s2_nn_fetch; +D stdputstr("add_s_nn_fetch: other installed, calling now...\n"); + add_s2_nn_fetch(susp, snd_list); + } else if (susp->s2 && susp->susp.current < s2_start) { + /* s2 not started and s1 stops */ + /* go to zero-fill state */ + sound_unref(susp->s1); + susp->s1 = NULL; + susp->susp.fetch = add_zero_fill_nn_fetch; +B stdputstr("add_s_nn_fetch: zero_fill installed\n"); + add_zero_fill_nn_fetch(susp, snd_list); + } else if (susp->s2) { +D stdputstr("add_s_nn_fetch: unexpected condition\n"); + EXIT(1); + } else /* no s2 */ { + snd_list_terminate(snd_list); + } +D nyquist_printf("add_s_nn_fetch: special return, susp %p\n", susp); + return; /* fetching taken care of by another routine */ + } +/* if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + togo) { + togo = susp->terminate_cnt - susp->susp.current; + } + */ + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN && + susp->logical_stop_bits == 3) { + int to_stop = susp->susp.log_stop_cnt - susp->susp.current; + if (to_stop < togo) { + if (to_stop == 0) { + susp->logically_stopped = true; + } else togo = to_stop; + } +B if (togo == 0) stdputstr("togo is zero at checkpoint 3\n"); +D nyquist_printf("add_s1_nn_fetch: to_stop %d togo %d\n", to_stop, togo); + } + + /* consider other signal? don't run past its start time... */ + if (susp->s2) { + s2_start = ROUND((susp->s2->t0 - susp->susp.t0) * + susp->s2->sr); + if (s2_start < susp->susp.current + togo) + togo = MIN(togo, s2_start - susp->susp.current); +B if (togo == 0) stdputstr("togo is zero at checkpoint 4\n"); + } + + /* + * two cases: copy a partial block or manipulate pointers for + * copyless transfer of whole block (may not be full block): + * + * copy partial block when: + * o samples begin in middle of block + * o stopping time is before end of block (when other signal + * splits the block for this signal) + * transfer (copyless) block when: + * o the block is of maximum size + * o the block is small due to logical stop time or termination + * time + */ + if (susp->s1_ptr == susp->s1_bptr->samples && + susp->s1_cnt == togo) { + /* + * we want to copy this whole block (starting at the beginning + * and going to the rest of the block) -- just do pointers. + */ + + /* just fetch and pass blocks on */ + if (0) nyquist_printf("add[%p,%p] (s%d_nn) %p starting uncopy, togo %d\n", susp->s1, susp->s2, + 1, susp, togo); + snd_list->block = susp->s1_bptr; + (susp->s1_bptr->refcnt)++; + if (0) nyquist_printf("add[%p,%p] (s%d_nn) %p shared block %p zero_block %p\n",susp->s1, susp->s2, + 1, susp, susp->s1_bptr, zero_block); + + susp_took(s1_cnt, togo); + snd_list->block_len = togo; + + /* if other is terminated and sound_types match, collapse */ + /* NOTE: in order to collapse, we need s2 to be generating + * blocks and linking them onto a sound list. This is true + * when the get_next fn is SND_get_next. (A counterexample is + * SND_get_zeros, which returns zero blocks but does not link + * them onto the sound list. + */ + if (0) nyquist_printf("s2 %p thissr %g suspsr %g get_next %d lsc %d\n", + susp->s2, susp->s1->sr, susp->susp.sr, + susp->s1->get_next == SND_get_next, + susp->s1->logical_stop_cnt == UNKNOWN); + if (susp->s2 == NULL && susp->s1->sr == susp->susp.sr && + susp->s1->get_next == SND_get_next && + susp->s1->logical_stop_cnt == UNKNOWN) { + snd_list_type addend_list; +D nyquist_printf("add[%p,%p]: collapsing! LSC %d\n", susp->s1, susp->s2, + (int)susp->s1->logical_stop_cnt); +D sound_print_tree(susp->s1); + /* will "current" values match? */ + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } + else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } + /* free the superfluous sound_type and susp */ + addend_list = susp->s1->list->u.next; + snd_list_ref(addend_list); + snd_list_unref(snd_list->u.next); + snd_list->u.next = addend_list; + return; + } + } else { + /* + * we want to copy a partial block + */ + + /* assume the snd_list is the one with a null block */ + /* + * put a fresh, clean block in the snd_list + * (get new snd_list later) + */ + falloc_sample_block(out, "add_s1_nn_fetch"); + snd_list->block = out; + out_ptr = out->samples; +B nyquist_printf("add[%p,%p] (s1_nn) %p new block %p, s1_ptr %p block %p s1_cnt %d togo %d\n", susp->s1, susp->s2, susp, out, susp->s1_ptr, susp->s1_bptr->samples, (int)susp->s1_cnt, togo); + n = togo; +B if (togo == 0) stdputstr("togo is zero at checkpoint 5\n"); +B if (togo == 0) nyquist_printf( + "add[%p,%p] (s%d_nn) %p starting copy loop, togo %d\n", + susp->s1, susp->s2, 1, susp, togo); + while (n--) { /* the inner sample computation loop */ + /* scale? */ + *out_ptr++ = *(susp->s1_ptr++); + } /* inner loop */ + + susp_took(s1_cnt, togo); + snd_list->block_len = togo; + } + + /* add a new snd_list for the susp */ + susp->susp.current += togo; + +D stdputstr("testing..."); + /* + * test for termination or change of state, + * note s2_start computed earlier + */ + if (susp->s2 && susp->susp.current == s2_start && + susp->s1->list != zero_snd_list) { + /* s2 starting and s1 continues */ + /* go to s1+s2 state */ + susp->susp.fetch = add_s1_s2_nn_fetch; +D stdputstr("add_s_nn_fetch: add_s1_s2_fetch installed\n"); + } else if (susp->terminate_bits == 3) { + /* s2 finished and s1 stops */ + /* go to terminal state */ + susp->s1 = NULL; +D nyquist_printf("add_s_nn_fetch: go to terminal state. susp->s2 %p, \ + susp->susp.current %d, s2_start %d, susp->s1->list %p, \ + zero_snd_list %p\n", susp->s2, (int)susp->susp.current, + s2_start, susp->s1->list, zero_snd_list); + /* !!! free resources and set up pointers to terminal snd_list */ + /* !!! logically stopped? */ + } + + /* test for logical stop */ + if (susp->logically_stopped) { +D stdputstr("add_s_nn_fetch: snd_list->logically_stopped\n"); + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current && + susp->logical_stop_bits == 3) { +D stdputstr("add_s_nn_fetch: susp->logically_stopped\n"); + susp->logically_stopped = true; + } +D { + if (susp->logically_stopped || snd_list->logically_stopped) + stdputstr("STOPPED\n"); + else nyquist_printf("ok: current %d\n", (int)susp->susp.current); } +} + + +void add_s2_nn_fetch(susp, snd_list) + register add_susp_type susp; + snd_list_type snd_list; +{ + int togo, s1_start=0; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + +D nyquist_printf("add_s2_nn_fetch(susp %p, snd_list %p)\n", + susp, snd_list); + +#ifdef GC_DEBUG + snd_list_report(snd_list, "add_s2_nn_fetch"); +#endif + + /* + * first compute how many samples to copy (or transfer) + */ + + /* see what the next samples look like */ + susp_check_term_log_block_samples(s2, s2_bptr, + s2_ptr, s2_cnt, 2, 3); + + /* don't run past the s2 input sample block: */ + togo = susp->s2_cnt; + assert(togo > 0); + + /* don't run past terminate time of this signal */ + /* if (susp->s2_ptr == zero_block->samples) { -sep21 RBD*/ + if (susp->terminate_bits & 2) { + if (susp->s1) { + s1_start = ROUND((susp->s1->t0 - susp->susp.t0) * + susp->s1->sr); + if (0) nyquist_printf("add_s_nn_fetch: s1_start %d\n", s1_start); + } + togo = 0; + if (susp->s1 && susp->susp.current == s1_start) { + /* s1 starting and s2 stops */ + /* go to s1 alone state */ + sound_unref(susp->s2); + susp->s2 = NULL; + susp->susp.fetch = add_s1_nn_fetch; +D stdputstr("add_s_nn_fetch: other installed, calling now...\n"); + add_s1_nn_fetch(susp, snd_list); + } else if (susp->s1 && susp->susp.current < s1_start) { + /* s1 not started and s2 stops */ + /* go to zero-fill state */ + sound_unref(susp->s2); + susp->s2 = NULL; + susp->susp.fetch = add_zero_fill_nn_fetch; +D stdputstr("add_s_nn_fetch: zero_fill installed\n"); + add_zero_fill_nn_fetch(susp, snd_list); + } else if (susp->s1) { +D stdputstr("add_s_nn_fetch: unexpected condition\n"); + EXIT(1); + } else /* no s1 */ { + snd_list_terminate(snd_list); + } +D nyquist_printf("add_s_nn_fetch: special return, susp %p\n", susp); + return; /* fetching taken care of by another routine */ + } +/* if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + togo) { + togo = susp->terminate_cnt - susp->susp.current; + } + */ + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN && + /* check if we've seen the logical stop from s2. If so then + log_stop_cnt is max of s1 and s2 stop times */ + (susp->logical_stop_bits & 2)) { + int to_stop; +D nyquist_printf("add_s2_nn_fetch: susp->susp.log_stop_cnt %d\n", + susp->susp.log_stop_cnt); +D nyquist_printf("add_s2_nn_fetch: susp->susp.current %d\n", + susp->susp.current); + to_stop = susp->susp.log_stop_cnt - susp->susp.current; + // to_stop can be less than zero if we've been adding in sounds with + // t0 less than the time when the sound is added. E.g. if the user + // wants a sequence of two sounds that start at 0, the second sound + // will be spliced onto the first because we don't look at it until + // the first finishes -- we cannot go back in time and start adding + // from time 0. This creates a mismatch between the sample count and + // the logical time, so we could actually set a logical stop time that + // is back in history, and therefore before susp.current, resulting + // in a negative to_stop. The problem is really with trying to + // sequence two sounds rather than two behaviors, and a warning has + // already been issued, so we'll just try not to crash here. It's too + // late to compute the correct answer, which would respect t0 of both + // sounds. + if (to_stop < 0) to_stop = 0; + if (to_stop < togo) { + if (to_stop == 0) { + susp->logically_stopped = true; + } else togo = to_stop; + } +B if (togo == 0) stdputstr("togo is zero at checkpoint 3\n"); +D nyquist_printf("add_s2_nn_fetch: to_stop %d togo %d\n", to_stop, togo); + } + + /* consider other signal? don't run past its start time... */ + if (susp->s1) { + s1_start = ROUND((susp->s1->t0 - susp->susp.t0) * + susp->s1->sr); + if (s1_start < susp->susp.current + togo) + togo = MIN(togo, s1_start - susp->susp.current); + assert(togo > 0); + } + + /* + * two cases: copy a partial block or manipulate pointers for + * copyless transfer of whole block (may not be full block): + * + * copy partial block when: + * o samples begin in middle of block + * o stopping time is before end of block (when other signal + * splits the block for this signal) + * transfer (copyless) block when: + * o the block is of maximum size + * o the block is small due to logical stop time or termination + * time + */ + if (susp->s2_ptr == susp->s2_bptr->samples && + susp->s2_cnt == togo) { + /* + * we want to copy this whole block (starting at the beginning + * and going to the rest of the block) -- just do pointers. + */ + + /* just fetch and pass blocks on */ +D nyquist_printf("add[%p,%p] (s%d_nn) %p starting uncopy, togo %d\n", susp->s2, susp->s1, + 2, susp, togo); + snd_list->block = susp->s2_bptr; + (susp->s2_bptr->refcnt)++; +D nyquist_printf("add[%p,%p] (s%d_nn) %p shared block %p zero_block %p\n",susp->s2, susp->s1, + 2, susp, susp->s2_bptr, zero_block); + + susp_took(s2_cnt, togo); + snd_list->block_len = togo; + + /* if other is terminated and sound_types match, collapse */ + /* NOTE: in order to collapse, we need s1 to be generating + * blocks and linking them onto a sound list. This is true + * when the get_next fn is SND_get_next. (A counterexample is + * SND_get_zeros, which returns zero blocks but does not link + * them onto the sound list. + */ + if (0) nyquist_printf("s1 %p thissr %g suspsr %g get_next %d lsc %d\n", + susp->s1, susp->s2->sr, susp->susp.sr, + susp->s2->get_next == SND_get_next, + susp->s2->logical_stop_cnt == UNKNOWN); + if (susp->s1 == NULL && susp->s2->sr == susp->susp.sr && + susp->s2->get_next == SND_get_next && + susp->s2->logical_stop_cnt == UNKNOWN) { + snd_list_type addend_list; +D nyquist_printf("add[%p,%p]: collapsing! LSC %d\n", + susp->s2, susp->s1, (int)susp->s2->logical_stop_cnt); +D sound_print_tree(susp->s2); + /* will "current" values match? */ + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } + else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } + /* free the superfluous sound_type and susp */ + addend_list = susp->s2->list->u.next; + snd_list_ref(addend_list); + snd_list_unref(snd_list->u.next); + snd_list->u.next = addend_list; + return; + } + } else { + /* + * we want to copy a partial block + */ + + /* assume the snd_list is the one with a null block */ + /* + * put a fresh, clean block in the snd_list + * (get new snd_list later) + */ + falloc_sample_block(out, "add_s2_nn_fetch"); + snd_list->block = out; + out_ptr = out->samples; +B nyquist_printf("add[%p,%p] (s2_nn) %p new block %p\n", + susp->s2, susp->s1, susp, out); + n = togo; + if (n == 0) + stdputstr("zero block length error in add_s2_nn_fetch\n"); + assert(n > 0); +B nyquist_printf( + "add[%p,%p] (s2_nn) %p starting copy loop, togo %d\n", + susp->s2, susp->s1, susp, togo); + while (n--) { /* the inner sample computation loop */ + /* scale? */ + *out_ptr++ = *(susp->s2_ptr++); + } /* inner loop */ + + susp_took(s2_cnt, togo); + snd_list->block_len = togo; + } + + /* add a new snd_list for the susp */ + susp->susp.current += togo; + + if (0) stdputstr("testing..."); + /* + * test for termination or change of state, + * note s1_start computed earlier + */ + if (susp->s1 && susp->susp.current == s1_start && + susp->s2->list != zero_snd_list) { + /* s1 starting and s2 continues */ + /* go to s1+s2 state */ + susp->susp.fetch = add_s1_s2_nn_fetch; +D stdputstr("add_s_nn_fetch: add_s1_s2_fetch installed\n"); + } +/* else if (!susp->s1 && susp->s2->list == zero_snd_list) { */ + else if (susp->terminate_bits == 3) { + /* s1 finished and s2 stops */ + /* go to terminal state */ + susp->s2 = NULL; +D nyquist_printf("add_s_nn_fetch: go to terminal state. susp->s1 %p, \ + susp->susp.current %d, s1_start %d, susp->s2->list %p, \ + zero_snd_list %p\n", susp->s1, (int)susp->susp.current, + s1_start, susp->s2->list, zero_snd_list); + /* !!! free resources and set up pointers to terminal snd_list */ + /* !!! logically stopped? */ + } + + /* test for logical stop */ + if (susp->logically_stopped) { +D stdputstr("add_s_nn_fetch: snd_list->logically_stopped\n"); + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current && + (susp->logical_stop_bits & 2)) { +D stdputstr("add_s_nn_fetch: susp->logically_stopped\n"); + susp->logically_stopped = true; + } + if (0) { + if (susp->logically_stopped || snd_list->logically_stopped) + stdputstr("STOPPED\n"); + else + nyquist_printf("ok: current %d\n", (int)susp->susp.current); + } +} + + + +void add_zero_fill_nn_fetch(susp, snd_list) + register add_susp_type susp; + snd_list_type snd_list; +{ + int togo, s_start=0; + +#ifdef GC_DEBUG + snd_list_report(snd_list, "add_zero_fill_nn_fetch"); +#endif + togo = max_sample_block_len; + + if (0) fprintf(STDERR, "add_zero_fill_nn_fetch, susp.current %d\n", + (int)susp->susp.current); + /* don't run past start time ... */ + if (susp->s1) { + s_start = ROUND((susp->s1->t0 - susp->susp.t0) * susp->s1->sr); + if (s_start < susp->susp.current + togo) { + togo = s_start - susp->susp.current; + } + } else if (susp->s2) { + s_start = ROUND((susp->s2->t0 - susp->susp.t0) * susp->s2->sr); + if (s_start < susp->susp.current + togo) { + togo = s_start - susp->susp.current; + } + } + + snd_list->block_len = togo; + susp->susp.current += togo; + /* + * test for change of state, + * note s_start computed earlier + */ + if (susp->s1 && susp->susp.current == s_start) { + /* s1 starting, go to s1 state */ + susp->susp.fetch = add_s1_nn_fetch; +D stdputstr("add_zero_fill_nn_fetch: add_s1_nn_fetch installed\n"); + } else if (susp->s2 && susp->susp.current == s_start) { + /* s2 starting, go to s2 state */ + susp->susp.fetch = add_s2_nn_fetch; +D stdputstr("add_zero_fill_nn_fetch: add_s2_nn_fetch installed\n"); + } +} /* add_zero_fill_nn_fetch */ + + +void add_free(add_susp_type susp) +{ + sound_unref(susp->s1); + sound_unref(susp->s2); + ffree_generic(susp, sizeof(add_susp_node), "add_free"); +} + + +void add_mark(add_susp_type susp) +{ +/* nyquist_printf("add_mark(%p)\n", susp);*/ +/* nyquist_printf("marking s1@%p in add@%p\n", susp->s1, susp);*/ + sound_xlmark(susp->s1); +/* nyquist_printf("marking s2@%p in add@%p\n", susp->s2, susp);*/ + sound_xlmark(susp->s2); + +} + + +void add_print_tree(add_susp_type susp, int n) +{ + indent(n); + nyquist_printf("logically_stopped %d logical_stop_bits %d terminate_bits %d\n", + susp->logically_stopped, susp->logical_stop_bits, susp->terminate_bits); + indent(n); + stdputstr("s1:"); + if (susp->s1) sound_print_tree_1(susp->s1, n); + else stdputstr(" NULL\n"); + + indent(n); + stdputstr("s2:"); + if (susp->s2) sound_print_tree_1(susp->s2, n); + else stdputstr(" NULL\n"); +} + + +sound_type snd_make_add(s1, s2) + sound_type s1; + sound_type s2; +{ + register add_susp_type susp; + rate_type sr = MAX(s1->sr, s2->sr); + time_type t0 = MIN(s1->t0, s2->t0); + int interp_desc = 0; + double sample_offset; + + /* sort commutative signals: (S1 S2) */ + snd_sort_2(&s1, &s2, sr); + + falloc_generic(susp, add_susp_node, "snd_make_add"); + + /* select a susp fn based on sample rates */ + interp_desc = (interp_style(s1, sr) << 2) + interp_style(s2, sr); + switch (interp_desc) { + case INTERP_nn: + case INTERP_ns: + case INTERP_ss: + /* eliminate scale factor on s1 if any */ + if (((interp_desc >> INTERP_SHIFT) & INTERP_MASK) == INTERP_s) { + /* stdputstr("add: prescaling s1\n");*/ + s1 = snd_make_normalize(s1); + } + /* eliminate scale factor on s2 if any */ + if ((interp_desc & INTERP_MASK) == INTERP_s) { + /* stdputstr("add: prescaling s2\n"); */ + s2 = snd_make_normalize(s2); + } + sample_offset = (s2->t0 - s1->t0) * sr; + if (sample_offset >= 0.5) { /* s1 starts first */ + susp->susp.fetch = add_s1_nn_fetch; +D stdputstr("snd_make_add: add_s1_nn_fetch installed\n"); + } else if (sample_offset < -0.5) { /* s2 starts first */ + susp->susp.fetch = add_s2_nn_fetch; +D stdputstr("snd_make_add: add_s2_nn_fetch installed\n"); + } else { /* equal start times */ + susp->susp.fetch = add_s1_s2_nn_fetch; +D stdputstr("snd_make_add: add_s1_s2_nn_fetch installed\n"); + } + break; + case INTERP_ni: + case INTERP_nr: + errputstr("add: can't interpolate!\n"); + EXIT(1); + default: + errputstr("add: can't add these operands!\n"); + EXIT(1); + } + + susp->terminate_cnt = UNKNOWN; + susp->terminate_bits = 0; /* bits for s1 and s2 termination */ + susp->logical_stop_bits = 0; /* bits for s1 and s2 logical stop */ + + /* initialize susp state */ + susp->susp.free = add_free; + susp->susp.sr = sr; + susp->susp.t0 = t0; + susp->susp.mark = add_mark; + susp->susp.print_tree = add_print_tree; + susp->susp.name = "add"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = UNKNOWN; + susp->started = false; + susp->susp.current = 0; + susp->s1 = s1; + susp->s1_cnt = 0; + susp->s2 = s2; + susp->s2_cnt = 0; +#ifdef UPSAMPLECODE + susp->susp.s2_phase = 0.0; + susp->susp.s2_phase_incr = s2->sr / sr; + susp->susp.output_per_s2 = sr / s2->sr; +#endif + return sound_create((snd_susp_type)susp, t0, sr, 1.0); +} + + +sound_type snd_add(s1, s2, t0) + sound_type s1; + sound_type s2; + time_type t0; +{ + sound_type s1_copy = sound_copy(s1); + sound_type s2_copy = sound_copy(s2); +/* nyquist_printf("snd_add %p %p copied to %p %p\n", s1, s2, s1_copy, s2_copy); */ + return snd_make_add(s1_copy, s2_copy, t0); +} diff --git a/nyqsrc/add.h b/nyqsrc/add.h new file mode 100644 index 0000000..e1835ac --- /dev/null +++ b/nyqsrc/add.h @@ -0,0 +1,44 @@ +/* this typedef goes here because it is needed by multiseq.c */ + +typedef struct add_susp_struct { + snd_susp_node susp; + boolean started; + int terminate_bits; + long terminate_cnt; + int logical_stop_bits; + boolean logically_stopped; + sound_type s1; + long s1_cnt; + sample_block_type s1_bptr; /* block pointer */ + sample_block_values_type s1_ptr; + sound_type s2; + long s2_cnt; + sample_block_type s2_bptr; /* block pointer */ + sample_block_values_type s2_ptr; + +#ifdef UPSAMPLECODE + /* support for interpolation of s2 */ + sample_type s2_x1_sample; + double s2_phase; + double s2_phase_incr; + + /* support for ramp between samples of s2 */ + double output_per_s2; +#endif + /* pointer used to synchronize adds in multiseq */ + struct multiseq_struct *multiseq; + long s1_prepend; /* offset to susp.current */ +} add_susp_node, *add_susp_type; + +sound_type snd_make_add(); +sound_type snd_add(); + /* LISP: (SND-ADD SOUND SOUND) */ + +/* we export these for seq.c and multiseq.c */ +void add_zero_fill_nn_fetch(add_susp_type susp, snd_list_type snd_list); +void add_s1_s2_nn_fetch(add_susp_type susp, snd_list_type snd_list); +void add_s2_nn_fetch(add_susp_type susp, snd_list_type snd_list); +void add_s1_nn_fetch(add_susp_type susp, snd_list_type snd_list); +void add_mark(add_susp_type susp); +void add_print_tree(add_susp_type susp, int n); +void add_free(add_susp_type susp); diff --git a/nyqsrc/avg.c b/nyqsrc/avg.c new file mode 100644 index 0000000..1a08ee1 --- /dev/null +++ b/nyqsrc/avg.c @@ -0,0 +1,273 @@ +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" + +#include "falloc.h" +#include "cext.h" +#include "avg.h" + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + + +void avg_free(); + +typedef sample_type (*process_block_type)(/* struct avg_susp_struct *susp */); + +typedef struct avg_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + sound_type s; + long s_cnt; + sample_block_values_type s_ptr; + /* blocksize is how many input samples to process for an output sample */ + long blocksize; + /* stepsize is how far to advance to get the next block of samples */ + long stepsize; + sample_type *buffer; + sample_type *fillptr; /* samples are added to buffer at fillptr */ + sample_type *endptr; /* until endptr is reached */ + process_block_type process_block; +} avg_susp_node, *avg_susp_type; + + +sample_type average_block(avg_susp_type susp) +{ + /* this version just computes average */ + double sum = 0.0; + int i; + for (i = 0; i < susp->blocksize; i++) { + sum += susp->buffer[i]; + } + for (i = susp->stepsize; i < susp->blocksize; i++) { + susp->buffer[i - susp->stepsize] = susp->buffer[i]; + } + return (sample_type) (sum / susp->blocksize); +} + + +sample_type peak_block(avg_susp_type susp) +{ + /* this version just computes average */ + sample_type peak = 0.0F; + sample_type minus_peak = 0.0F; + int i; + for (i = 0; i < susp->blocksize; i++) { + sample_type s = susp->buffer[i]; + if (s > peak) { + peak = s; minus_peak = -s; + } else if (s < minus_peak) { + minus_peak = s; peak = -s; + } + } + for (i = susp->stepsize; i < susp->blocksize; i++) { + susp->buffer[i - susp->stepsize] = susp->buffer[i]; + } + return peak; +} + + +void avg_s_fetch(avg_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + int togo = 0; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + + register sample_type *fillptr_reg; + register sample_type *endptr_reg = susp->endptr; + + register sample_block_values_type s_ptr_reg; + falloc_sample_block(out, "avg_s_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = (max_sample_block_len - cnt) * susp->stepsize; + + /* don't run past the s input sample block: */ + susp_check_term_log_samples(s, s_ptr, s_cnt); + togo = MIN(togo, susp->s_cnt); + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo/susp->stepsize) { + togo = (susp->terminate_cnt - (susp->susp.current + cnt)) * susp->stepsize; + if (togo == 0) break; + } + + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + /* break if to_stop == 0 (we're at the logical stop) + * AND cnt > 0 (we're not at the beginning of the + * output block). + */ + if (to_stop < togo/susp->stepsize) { + if (to_stop == 0) { + if (cnt) { + togo = 0; + break; + } else /* keep togo as is: since cnt == 0, we + * can set the logical stop flag on this + * output block + */ + susp->logically_stopped = true; + } else /* limit togo so we can start a new + * block at the LST + */ + togo = to_stop * susp->stepsize; + } + } + + n = togo; + s_ptr_reg = susp->s_ptr; + fillptr_reg = susp->fillptr; + if (n) do { /* the inner sample computation loop */ + *fillptr_reg++ = *s_ptr_reg++; + if (fillptr_reg >= endptr_reg) { + *out_ptr++ = (*(susp->process_block))(susp); + cnt++; + fillptr_reg -= susp->stepsize; + } + } while (--n); /* inner loop */ + + /* using s_ptr_reg is a bad idea on RS/6000: */ + susp->s_ptr += togo; + susp->fillptr = fillptr_reg; + susp_took(s_cnt, togo); + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* avg_s_fetch */ + + +void avg_toss_fetch(susp, snd_list) + avg_susp_type susp; + snd_list_type snd_list; +{ + long final_count = MIN(susp->susp.current + max_sample_block_len, + susp->susp.toss_cnt); + time_type final_time = susp->susp.t0 + final_count / susp->susp.sr; + long n; + + /* fetch samples from s up to final_time for this block of zeros */ + while (((long) ((final_time - susp->s->t0) * susp->s->sr + 0.5)) >= + susp->s->current) + susp_get_samples(s, s_ptr, s_cnt); + /* convert to normal processing when we hit final_count */ + /* we want each signal positioned at final_time */ + if (final_count == susp->susp.toss_cnt) { + n = ROUND((final_time - susp->s->t0) * susp->s->sr - + (susp->s->current - susp->s_cnt)); + susp->s_ptr += n; + susp_took(s_cnt, n); + susp->susp.fetch = susp->susp.keep_fetch; + } + snd_list->block_len = (short) (final_count - susp->susp.current); + susp->susp.current = final_count; + snd_list->u.next = snd_list_create((snd_susp_type) susp); + snd_list->block = internal_zero_block; +} + + +void avg_mark(avg_susp_type susp) +{ + sound_xlmark(susp->s); +} + + +void avg_free(avg_susp_type susp) +{ + sound_unref(susp->s); + free(susp->buffer); + ffree_generic(susp, sizeof(avg_susp_node), "avg_free"); +} + + +void avg_print_tree(avg_susp_type susp, int n) +{ + indent(n); + stdputstr("s:"); + sound_print_tree_1(susp->s, n); +} + + +sound_type snd_make_avg(sound_type s, long blocksize, long stepsize, long op) +{ + long buffersize; + register avg_susp_type susp; + rate_type sr = s->sr; + time_type t0 = s->t0; + time_type t0_min = t0; + + falloc_generic(susp, avg_susp_node, "snd_make_avg"); + susp->susp.fetch = avg_s_fetch; + susp->terminate_cnt = UNKNOWN; + /* handle unequal start times, if any */ + if (t0 < s->t0) sound_prepend_zeros(s, t0); + /* minimum start time over all inputs: */ + t0_min = MIN(s->t0, t0); + /* how many samples to toss before t0: */ + susp->susp.toss_cnt = ROUND((t0 - t0_min) * sr); + if (susp->susp.toss_cnt > 0) { + susp->susp.keep_fetch = susp->susp.fetch; + susp->susp.fetch = avg_toss_fetch; + t0 = t0_min; + } + + /* initialize susp state */ + susp->susp.free = avg_free; + susp->susp.sr = sr / stepsize; + susp->susp.t0 = t0; + susp->susp.mark = avg_mark; + susp->susp.print_tree = avg_print_tree; + susp->susp.name = "avg"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = logical_stop_cnt_cvt(s); + susp->susp.current = 0; + susp->s = s; + susp->s_cnt = 0; + susp->blocksize = blocksize; + susp->stepsize = stepsize; + /* We need at least blocksize samples in buffer, but if stepsize > blocksize, + it is convenient to put stepsize samples in buffer. This allows us to + step ahead by stepsize samples just by flushing the buffer. */ + buffersize = MAX(blocksize, stepsize); + susp->buffer = (sample_type *) malloc(buffersize * sizeof(sample_type)); + susp->fillptr = susp->buffer; + susp->endptr = susp->buffer + buffersize; + susp->process_block = average_block; + if (op == op_peak) susp->process_block = peak_block; + /* scale factor gets passed to output signal: */ + return sound_create((snd_susp_type) susp, t0, susp->susp.sr, susp->s->scale); +} + + +sound_type snd_avg(sound_type s, long blocksize, long stepsize, long op) +{ + sound_type s_copy = sound_copy(s); + return snd_make_avg(s_copy, blocksize, stepsize, op); +} diff --git a/nyqsrc/avg.h b/nyqsrc/avg.h new file mode 100644 index 0000000..4c21cc3 --- /dev/null +++ b/nyqsrc/avg.h @@ -0,0 +1,6 @@ +sound_type snd_make_avg(sound_type s, long blocksize, long stepsize, long op); +sound_type snd_avg(sound_type s, long blocksize, long stepsize, long op); + /* LISP: (snd-avg SOUND FIXNUM FIXNUM FIXNUM) */ +#define op_average 1 +#define op_peak 2 +/* LISP-SRC: (setf OP-AVERAGE 1) (setf OP-PEAK 2) */ diff --git a/nyqsrc/compose.c b/nyqsrc/compose.c new file mode 100644 index 0000000..a15fe34 --- /dev/null +++ b/nyqsrc/compose.c @@ -0,0 +1,304 @@ +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" + +#include "falloc.h" +#include "cext.h" +#include "compose.h" + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +void compose_free(); + + +typedef struct compose_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + sound_type f; + long f_cnt; + sample_block_values_type f_ptr; + sample_type f_prev; + double f_time; + double f_time_increment; + boolean started; + sound_type g; + long g_cnt; + sample_block_values_type g_ptr; +} compose_susp_node, *compose_susp_type; + + +/* compose_fetch -- computes f(g(t)) */ +/**/ +void compose_fetch(register compose_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + int togo = 0; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + + register sample_block_values_type out_ptr_reg; + + register sample_block_values_type g_ptr_reg; + register sample_block_values_type f_ptr_reg; + falloc_sample_block(out, "compose_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + /* make sure we are primed with first value of f */ + /* This is a lot of work just to prefetch susp->f_prev! */ + if (!susp->started) { + susp->started = true; + /* see comments below about susp_check_term_log_samples() */ + if (susp->f_cnt == 0) { + susp_get_samples(f, f_ptr, f_cnt); + if (susp->f_ptr == zero_block->samples) { + susp->terminate_cnt = susp->susp.current; + } + } + susp->f_prev = susp_fetch_sample(f, f_ptr, f_cnt); + susp->f_time += susp->f_time_increment; + } + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = max_sample_block_len - cnt; + + /* don't run past the f input sample block: */ + /* most fetch routines call susp_check_term_log_samples() here + * but we can't becasue susp_check_term_log_samples() assumes + * that output time progresses at the same rate as input time. + * Here, some time warping is going on, so this doesn't work. + * Instead, check for termination of f and fix terminate_cnt to + * be the current output count rather than the current input time. + */ + if (susp->f_cnt == 0) { + susp_get_samples(f, f_ptr, f_cnt); + if (susp->f->logical_stop_cnt == susp->f->current - susp->f_cnt) { + if (susp->susp.log_stop_cnt == UNKNOWN) { + susp->susp.log_stop_cnt = susp->susp.current + cnt; + } + } + if (susp->f_ptr == zero_block->samples) { + susp->terminate_cnt = susp->susp.current + cnt; + /* we can't simply terminate here because we might have + * some output samples computed already, in which case we + * want to return them now and terminate the NEXT time we're + * called. + */ + } + } + +#ifdef CUT + /* don't run past the f input sample block: */ + susp_check_term_log_samples(f, f_ptr, f_cnt); + togo = MIN(togo, susp->f_cnt); +#endif + /* don't run past the g input sample block: */ + susp_check_term_samples(g, g_ptr, g_cnt); + togo = MIN(togo, susp->g_cnt); + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); + if (togo == 0) break; + } + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + if (to_stop < togo && ((togo = to_stop) == 0)) break; + } + + n = togo; + + g_ptr_reg = susp->g_ptr; + f_ptr_reg = susp->f_ptr; + out_ptr_reg = out_ptr; + if (n) do { /* the inner sample computation loop */ + double g_of_t = *g_ptr_reg; + #if 0 + float tmp; /* for debugging */ + nyquist_printf("output sample %d, g_of_t %g", susp->susp.current + cnt, g_of_t); + #endif + /* now we scan f and interpolate at time point g_of_t */ + while (susp->f_time < g_of_t) { + susp->f_time += susp->f_time_increment; + susp->f_prev = *f_ptr_reg++; +/* nyquist_printf(", (f_time %g, f %g)", susp->f_time, *f_ptr_reg); */ + susp->f_ptr++; + susp->f_cnt--; + if (susp->f_cnt == 0) { + togo -= n; +/* stdputstr("\n\tf out of samples...\n"); */ + goto f_out_of_samples; + } + } + g_ptr_reg++; + *out_ptr_reg++ /* = tmp */ = + (sample_type) (*f_ptr_reg - (*f_ptr_reg - susp->f_prev) * + (susp->f_time - g_of_t) * susp->f->sr); +/* nyquist_printf(", output %g\n", tmp);*/ + } while (--n); /* inner loop */ +f_out_of_samples: + /* using g_ptr_reg is a bad idea on RS/6000: */ + susp->g_ptr += togo; + out_ptr += togo; + susp_took(g_cnt, togo); + cnt += togo; + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* compose_fetch */ + + +void compose_toss_fetch(susp, snd_list) + register compose_susp_type susp; + snd_list_type snd_list; +{ + long final_count = MIN(susp->susp.current + max_sample_block_len, + susp->susp.toss_cnt); + time_type final_time = susp->susp.t0 + final_count / susp->susp.sr; + long n; + + /* fetch samples from f up to final_time for this block of zeros */ + while (((long) ((final_time - susp->f->t0) * susp->f->sr + 0.5)) >= + susp->f->current) + susp_get_samples(f, f_ptr, f_cnt); + /* fetch samples from g up to final_time for this block of zeros */ + while (((long) ((final_time - susp->g->t0) * susp->g->sr + 0.5)) >= + susp->g->current) + susp_get_samples(g, g_ptr, g_cnt); + /* convert to normal processing when we hit final_count */ + /* we want each signal positioned at final_time */ + if (final_count == susp->susp.toss_cnt) { + n = ROUND((final_time - susp->f->t0) * susp->f->sr - + (susp->f->current - susp->f_cnt)); + susp->f_ptr += n; + susp_took(f_cnt, n); + n = ROUND((final_time - susp->g->t0) * susp->g->sr - + (susp->g->current - susp->g_cnt)); + susp->g_ptr += n; + susp_took(g_cnt, n); + susp->susp.fetch = susp->susp.keep_fetch; + } + snd_list->block_len = (short) (final_count - susp->susp.current); + susp->susp.current = final_count; + snd_list->u.next = snd_list_create((snd_susp_type) susp); + snd_list->block = internal_zero_block; +} + + +void compose_mark(compose_susp_type susp) +{ + sound_xlmark(susp->f); + sound_xlmark(susp->g); +} + + +void compose_free(compose_susp_type susp) +{ + sound_unref(susp->f); + sound_unref(susp->g); + ffree_generic(susp, sizeof(compose_susp_node), "compose_free"); +} + + +void compose_print_tree(compose_susp_type susp, int n) +{ + indent(n); + stdputstr("f:"); + sound_print_tree_1(susp->f, n); + + indent(n); + stdputstr("g:"); + sound_print_tree_1(susp->g, n); +} + + +sound_type snd_make_compose(sound_type f, sound_type g) +{ + register compose_susp_type susp; + rate_type sr = g->sr; + time_type t0 = g->t0; + + sample_type scale_factor = 1.0F; + time_type t0_min = t0; + + /* combine scale factors of linear inputs (S1 S2) */ + scale_factor *= f->scale; + f->scale = 1.0F; + + /* scale factor in g effectively scales sample rate of f: */ + f->sr *= g->scale; +/* BUG */ + /* probably need to correct f->t0, but I don't understand this, + so I'll leave this until we have some test cases */ + + falloc_generic(susp, compose_susp_node, "snd_make_compose"); + susp->susp.fetch = compose_fetch; + susp->terminate_cnt = UNKNOWN; + /* handle unequal start times, if any */ +/* BUG: do we need to prepend to f? + if (t0 < f->t0) sound_prepend_zeros(f, t0); */ + if (t0 < g->t0) sound_prepend_zeros(g, t0); + /* minimum start time over all inputs: */ + t0_min = MIN(g->t0, t0); + /* how many samples to toss before t0: */ + susp->susp.toss_cnt = ROUND((t0 - t0_min) * sr); + if (susp->susp.toss_cnt > 0) { + susp->susp.keep_fetch = susp->susp.fetch; + susp->susp.fetch = compose_toss_fetch; + t0 = t0_min; + } + + /* initialize susp state */ + susp->susp.free = compose_free; + susp->susp.sr = sr; + susp->susp.t0 = t0; + susp->susp.mark = compose_mark; + susp->susp.print_tree = compose_print_tree; + susp->susp.name = "compose"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = f->logical_stop_cnt; + if (susp->susp.log_stop_cnt > g->logical_stop_cnt) + susp->susp.log_stop_cnt = g->logical_stop_cnt; + susp->susp.current = 0; + susp->f = f; + susp->f_cnt = 0; + susp->f_time = 0; + susp->f_time_increment = 1 / f->sr; + susp->g = g; + susp->g_cnt = 0; + susp->started = false; + return sound_create((snd_susp_type)susp, t0, sr, scale_factor); +} + + +sound_type snd_compose(sound_type f, sound_type g) +{ + sound_type f_copy = sound_copy(f); + sound_type g_copy = sound_copy(g); + return snd_make_compose(f_copy, g_copy); +} diff --git a/nyqsrc/compose.h b/nyqsrc/compose.h new file mode 100644 index 0000000..efd773c --- /dev/null +++ b/nyqsrc/compose.h @@ -0,0 +1,3 @@ +sound_type snd_make_compose(sound_type f, sound_type g); +sound_type snd_compose(sound_type f, sound_type g); + /* LISP: (snd-compose SOUND SOUND) */ diff --git a/nyqsrc/convolve.c b/nyqsrc/convolve.c new file mode 100644 index 0000000..79d94dd --- /dev/null +++ b/nyqsrc/convolve.c @@ -0,0 +1,329 @@ +/* convolve.c -- implements (non-"fast") convolution */ +/* + * Note: this code is mostly generated by translate.lsp (see convole.tran + * in the tran directory), but it has been modified by hand to extend the + * stop time to include the "tail" of the convolution beyond the length + * of the first parameter. + */ + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" + +#include "falloc.h" +#include "cext.h" +#include "convolve.h" + +void convolve_free(); + + +typedef struct convolve_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + sound_type x_snd; + long x_snd_cnt; + sample_block_values_type x_snd_ptr; + + table_type table; + sample_type *h_buf; + double length_of_h; + long h_len; + long x_buf_len; + sample_type *x_buffer_pointer; + sample_type *x_buffer_current; +} convolve_susp_node, *convolve_susp_type; + + +void h_reverse(sample_type *h, long len) +{ + sample_type temp; + int i; + + for (i = 0; i < len; i++) { + temp = h[i]; + h[i] = h[len - 1]; + h[len - 1] = temp; + len--; + } +} + + +void convolve_s_fetch(register convolve_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + int togo; + int n, i; + int round; + int ready = 0; + float* Utb1; + short* BRLow; + long M; + + sample_block_type out; + register sample_block_values_type out_ptr; + + register sample_block_values_type out_ptr_reg; + + register sample_type * h_buf_reg; + register long h_len_reg; + register long x_buf_len_reg; + register sample_type * x_buffer_pointer_reg; + register sample_type * x_buffer_current_reg; + register sample_type x_snd_scale_reg = susp->x_snd->scale; + register sample_block_values_type x_snd_ptr_reg; + + sample_type* Yk; + sample_type* y_output_buffer; + sample_type* x_input_buffer; + + falloc_sample_block(out, "convolve_s_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = max_sample_block_len - cnt; + + /* don't run past the x_snd input sample block: */ + /* based on susp_check_term_log_samples, but offset by h_len */ + + /* THIS IS EXPANDED BELOW + * susp_check_term_log_samples(x_snd, x_snd_ptr, x_snd_cnt); + */ + if (susp->x_snd_cnt == 0) { + susp_get_samples(x_snd, x_snd_ptr, x_snd_cnt); + + /* THIS IS EXPANDED BELOW + *logical_stop_test(x_snd, susp->x_snd_cnt); + */ + if (susp->x_snd->logical_stop_cnt == + susp->x_snd->current - susp->x_snd_cnt) { + min_cnt(&susp->susp.log_stop_cnt, susp->x_snd, + (snd_susp_type) susp, susp->x_snd_cnt); + } + + /* THIS IS EXPANDED BELOW + * terminate_test(x_snd_ptr, x_snd, susp->x_snd_cnt); + */ + if (susp->x_snd_ptr == zero_block->samples) { + /* ### modify this to terminate at an offset of (susp->h_len) */ + /* Note: in the min_cnt function, susp->x_snd_cnt is *subtracted* + * from susp->x_snd->current to form the terminate time, so to + * increase the time, we need to *subtract* susp->h_len, which + * due to the double negative, *adds* susp->h_len to the ultimate + * terminate time calculation. + */ + min_cnt(&susp->terminate_cnt, susp->x_snd, + (snd_susp_type) susp, susp->x_snd_cnt - susp->h_len); + } + } + + + togo = min(togo, susp->x_snd_cnt); + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); + if (togo == 0) break; + } + + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + /* break if to_stop == 0 (we're at the logical stop) + * AND cnt > 0 (we're not at the beginning of the + * output block). + */ + if (to_stop < togo) { + if (to_stop == 0) { + if (cnt) { + togo = 0; + break; + } else /* keep togo as is: since cnt == 0, we + * can set the logical stop flag on this + * output block + */ + susp->logically_stopped = true; + } else /* limit togo so we can start a new + * block at the LST + */ + togo = to_stop; + } + } + + n = togo; + h_buf_reg = susp->h_buf; + h_len_reg = susp->h_len; + x_buf_len_reg = susp->x_buf_len; + x_buffer_pointer_reg = susp->x_buffer_pointer; + x_buffer_current_reg = susp->x_buffer_current; + x_snd_ptr_reg = susp->x_snd_ptr; + out_ptr_reg = out_ptr; + + //buffer's length is twice the h_len because convolution yields 2N-1 + y_output_buffer[2 * (int)h_len_reg]; + x_input_buffer[2 * (int)h_len_reg]; + memset(y_output_buffer, (sample_type)0.0f, 2 * h_len_reg * sizeof(sample_type)); + memset(x_input_buffer, (sample_type)0.0f, 2 * h_len_reg * sizeof(sample_type)); + + M = log(h_len_reg) / log(2); + round = (int)M; + if((long)round != M) + round++; + + fftCosInit(round, Utb1); + fftBRInit(round, BRLow); + + ffts1(h_buf_reg, round, 1.0, Utb1, BRLow); + if (n) do { /* the inner sample computation loop */ + if(ready <= 0){ + //shift output buffer + for(i = 0; i < x_buf_len_reg; i++){ + y_output_buffer[i] = y_output_buffer[i+h_len_reg]; + y_output_buffer[i+h_len_reg] = 0.0f; + } + + ffts1(x_input_buffer, round, 1L, Utb1, BRLow); + //multiply + for(i = 0; i < 2 * h_len_reg; i++) + Yk[i] = x_input_buffer[i] * h_buf_reg[i]; + + iffts1(Yk, round, 1.0, Utb1, BRLow); + //overlap add + for(i = 0; i < 2 * h_len_reg; i++) + y_output_buffer[i] += Yk[i]; + + ready = h_len_reg; + } + //ready describes the reciprocal of location in the input/output buffer + x_input_buffer[h_len_reg - ready] = x_snd_scale_reg * *x_snd_ptr_reg++; + *out_ptr_reg++ = y_output_buffer[h_len_reg - ready]; + ready--; + } while (--n); /* inner loop */ + + susp->x_buffer_pointer = x_buffer_pointer_reg; + susp->x_buffer_current = x_buffer_current_reg; + /* using x_snd_ptr_reg is a bad idea on RS/6000: */ + susp->x_snd_ptr += togo; + out_ptr += togo; + susp_took(x_snd_cnt, togo); + cnt += togo; + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* convolve_s_fetch */ + + +void convolve_toss_fetch(susp, snd_list) + register convolve_susp_type susp; + snd_list_type snd_list; +{ + time_type final_time = susp->susp.t0; + long n; + + /* fetch samples from x_snd up to final_time for this block of zeros */ + while ((round((final_time - susp->x_snd->t0) * susp->x_snd->sr)) >= + susp->x_snd->current) + susp_get_samples(x_snd, x_snd_ptr, x_snd_cnt); + /* convert to normal processing when we hit final_count */ + /* we want each signal positioned at final_time */ + n = round((final_time - susp->x_snd->t0) * susp->x_snd->sr - + (susp->x_snd->current - susp->x_snd_cnt)); + susp->x_snd_ptr += n; + susp_took(x_snd_cnt, n); + susp->susp.fetch = susp->susp.keep_fetch; + (*(susp->susp.fetch))(susp, snd_list); +} + + +void convolve_mark(convolve_susp_type susp) +{ + sound_xlmark(susp->x_snd); +} + + +void convolve_free(convolve_susp_type susp) +{ + table_unref(susp->table); + free(susp->x_buffer_pointer); sound_unref(susp->x_snd); + ffree_generic(susp, sizeof(convolve_susp_node), "convolve_free"); +} + + +void convolve_print_tree(convolve_susp_type susp, int n) +{ + indent(n); + stdputstr("x_snd:"); + sound_print_tree_1(susp->x_snd, n); +} + + +sound_type snd_make_convolve(sound_type x_snd, sound_type h_snd) +{ + register convolve_susp_type susp; + rate_type sr = x_snd->sr; + time_type t0 = x_snd->t0; + sample_type scale_factor = 1.0F; + time_type t0_min = t0; + falloc_generic(susp, convolve_susp_node, "snd_make_convolve"); + susp->table = sound_to_table(h_snd); + susp->h_buf = susp->table->samples; + susp->length_of_h = susp->table->length; + susp->h_len = (long) susp->length_of_h; + h_reverse(susp->h_buf, susp->h_len); + susp->x_buf_len = 2 * susp->h_len; + susp->x_buffer_pointer = calloc((2 * (susp->h_len)), sizeof(float)); + susp->x_buffer_current = susp->x_buffer_pointer; + susp->susp.fetch = convolve_s_fetch; + susp->terminate_cnt = UNKNOWN; + /* handle unequal start times, if any */ + if (t0 < x_snd->t0) sound_prepend_zeros(x_snd, t0); + /* minimum start time over all inputs: */ + t0_min = min(x_snd->t0, t0); + /* how many samples to toss before t0: */ + susp->susp.toss_cnt = (long) ((t0 - t0_min) * sr + 0.5); + if (susp->susp.toss_cnt > 0) { + susp->susp.keep_fetch = susp->susp.fetch; + susp->susp.fetch = convolve_toss_fetch; + } + + /* initialize susp state */ + susp->susp.free = convolve_free; + susp->susp.sr = sr; + susp->susp.t0 = t0; + susp->susp.mark = convolve_mark; + susp->susp.print_tree = convolve_print_tree; + susp->susp.name = "convolve"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = logical_stop_cnt_cvt(x_snd); + susp->susp.current = 0; + susp->x_snd = x_snd; + susp->x_snd_cnt = 0; + return sound_create((snd_susp_type)susp, t0, sr, scale_factor); +} + + +sound_type snd_convolve(sound_type x_snd, sound_type h_snd) +{ + sound_type x_snd_copy = sound_copy(x_snd); + return snd_make_convolve(x_snd_copy, h_snd); +} diff --git a/nyqsrc/convolve.h b/nyqsrc/convolve.h new file mode 100644 index 0000000..27eac33 --- /dev/null +++ b/nyqsrc/convolve.h @@ -0,0 +1,3 @@ +sound_type snd_make_convolve(sound_type x_snd, sound_type h_snd); +sound_type snd_convolve(sound_type x_snd, sound_type h_snd); + /* LISP: (snd-convolve SOUND SOUND) */ diff --git a/nyqsrc/cque.h b/nyqsrc/cque.h new file mode 100644 index 0000000..e001e3c --- /dev/null +++ b/nyqsrc/cque.h @@ -0,0 +1,25 @@ +/* + * cque.h + * macros for free lists. + */ + +typedef struct cque { + struct cque *qnext; +} CQUE; + +#define Qinit(q1) { (q1) = 0; } + +/* q1 points to a stack CQUE*, new is an element to insert */ +#define Qenter(q1,new) { \ + ((CQUE *)(new))->qnext = ((CQUE *)(q1)); \ + q1 = ((CQUE *)(new)); } + + +/* q1 points to a list of CQUE*: remove elt and assign to new */ +/* NOTE: q1 must be non-empty */ +#define Qget(q1,newtype,new) { \ + (new) = (newtype)(q1); \ + q1 = ((CQUE *)(q1))->qnext; } + + +#define Qempty(q1) ((q1) == 0) diff --git a/nyqsrc/debug.c b/nyqsrc/debug.c new file mode 100644 index 0000000..74a77f5 --- /dev/null +++ b/nyqsrc/debug.c @@ -0,0 +1,249 @@ +#include +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "debug.h" + +/* The DEBUG_MEM related routines are: + * dbg_mem_allocated: called when memory is allocated + * dbg_mem_freed: called when memory is freed + * dbg_mem_released: called when memory is released + */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + + +#if DEBUG_MEM +typedef struct { + long seq_num; + char *who; +} dbg_mem_node, *dbg_mem_type; + +static long dbg_mem_last_seq_num = 0; +long dbg_mem_seq_num = 0; +long dbg_mem_trace = 0x410988; + +void dbg_mem_pause(void) +{ + stdputstr("RETURN to continue: "); + getchar(); +} + + +void dbg_mem_allocated(void *p, char *who) +{ + dbg_mem_type info = (dbg_mem_type) p; + if (p == (void *) dbg_mem_trace) { + nyquist_printf("dbg_mem_allocated(%p, %s)\n", p, who); + } + info--; /* info is stored (hidden) BEFORE the data */ + dbg_mem_last_seq_num++; + if (dbg_mem_last_seq_num == dbg_mem_seq_num) { + nyquist_printf("dbg_mem_allocated: " + "%s just allocated %p as number %d\n", + who, p, (int)dbg_mem_last_seq_num); + dbg_mem_pause(); + } + info->seq_num = dbg_mem_last_seq_num; + info->who = who; +} + + +void dbg_mem_freed(void *p, char *who) +{ + dbg_mem_type info = (dbg_mem_type) p; + if (p == (void *) dbg_mem_trace) { + nyquist_printf("dbg_mem_freed(%p, %s)\n", p, who); + } + info--; /* info is stored (hidden) BEFORE the data */ + if (!info->who) { + nyquist_printf("MEMORY %p FREED TWICE!, " + "second time by: %s, seq_num %d\n", + p, who, (int)info->seq_num); + fflush(stdout); + dbg_mem_pause(); + } + if (info->seq_num == dbg_mem_seq_num) { + nyquist_printf("dbg_mem_freed: %s freeing %p, number %d\n", + who, p, (int)dbg_mem_seq_num); + dbg_mem_pause(); + } + info->who = NULL; +} + +void dbg_mem_released(void *p, char *who) +{ + dbg_mem_type info = (dbg_mem_type) p; + if (p == (void *) dbg_mem_trace) { + nyquist_printf("dbg_mem_released(%p, %s)\n", p, who); + } + info--; /* info is stored (hidden) BEFORE the data */ + if (!info->who) { + nyquist_printf("MEMORY %p RELEASED BUT NOT ALLOCATED!, " + "released by: %s, seq_num %d\n", + p, who, (int)info->seq_num); + fflush(stdout); + dbg_mem_pause(); + } + if (info->seq_num == dbg_mem_seq_num) { + nyquist_printf("dbg_mem_released: %s releasing %p, number %d\n", + who, p, (int)dbg_mem_seq_num); + dbg_mem_pause(); + } +} + + +void dbg_mem_check(void *p, char *who) +{ + dbg_mem_type info = (dbg_mem_type) p; + if (!info) { + nyquist_printf("DBG_MEM_CHECK (from %s): NULL POINTER!", who); + fflush(stdout); + dbg_mem_pause(); + } + info--; /* info is stored (hidden) BEFORE the data */ + if (!info->who) { + nyquist_printf("DBG_MEM_CHECK (from %s): %p IS FREE!, seq_num %d\n", + who, p, (int)info->seq_num); + fflush(stdout); + dbg_mem_pause(); + } +} + + +void dbg_mem_print(char *msg, void *p) +{ + dbg_mem_type info = (dbg_mem_type) p; + stdputstr(msg); + if (!info) { + stdputstr(" NULL POINTER"); + } else { + info--; /* info is stored (hidden) BEFORE the data */ + if (!info->who) { + nyquist_printf(" %p IS FREE!, ", p); + } else { + nyquist_printf(" %p allocated by %s, ", p, info->who); + } + nyquist_printf("seq_num %d\n", (int)info->seq_num); + } +} +#endif + + +void print_sound_type(sound_type s) +{ + snd_list_type list; + int blockcount; + + nyquist_printf("sound_type: 0x%p\n", s); + nyquist_printf("\tt0: %f\n", s->t0); + nyquist_printf("\tsr: %f\n", s->sr); + nyquist_printf("\tcurrent: %d\n", (int)s->current); + nyquist_printf("\tlogical_stop_cnt: %d\n", (int)s->logical_stop_cnt); + nyquist_printf("\tlist: 0x%p\n", s->list); + nyquist_printf("\tscale: %f\n", s->scale); + + list = s->list; + blockcount = 0; + nyquist_printf("\t(0x%p:0x%p)->", list, list->block); + while (list->block) { + list = list->u.next; + if (blockcount < 5) { + nyquist_printf("(0x%p:0x%p)->", list, list->block); + } + else if (blockcount == 5) { + stdputstr(" ... "); + break; + } + blockcount++; + } + stdputstr("\n"); +} + +void print_snd_list_type(snd_list_type list) +{ + nyquist_printf("%p: [%p[%d], %p] refcnt %d ls %d", list, list->block, + list->block_len, list->u.next, + list->refcnt, list->logically_stopped); +} + + + +void print_sample_block_type(char *label, + sample_block_type sampblock, + int len) +{ + int j; + sample_block_values_type samp; + + samp = sampblock->samples; + nyquist_printf("%s: [%p(ref %d): len %d]: =========>>", + label, sampblock, (int)sampblock->refcnt, len); + for (j = 0; j < len; j++) { + nyquist_printf("%6g ", *samp++); + } + stdputstr("\n"); +} + + +/*******/ +snd_susp_type susp_to_watch = NULL; + +void watch_susp(snd_susp_type s) +{ + if (!susp_to_watch) { + susp_to_watch = s; + nyquist_printf("watching susp %p\n", s); + } +} + +sound_type sound_to_watch = NULL; + +void watch_sound(sound_type s) +{ + if (!sound_to_watch) { + sound_to_watch = s; + nyquist_printf("watching sound %p\n", s); + } +} + + +snd_list_type snd_list_to_watch = NULL; + +void watch_snd_list(snd_list_type s) +{ + snd_list_to_watch = s; + nyquist_printf("watching snd_list %p\n", s); +} + + +void snd_list_debug(snd_list_type snd_list, char *s) +{ + if (snd_list == snd_list_to_watch) { + nyquist_printf("%s%s\n", s, + " appended to snd_list_to_watch."); + watch_snd_list(snd_list->u.next); + } +} + + +void snd_list_report(snd_list_type snd_list, char *s) +{ + if (snd_list == snd_list_to_watch) { + nyquist_printf("%s: fetching block for watched snd_list.\n", + s); + } +} + + +#ifdef IGNORE +void test_it() +{ + if (susp_to_watch && susp_to_watch->keep_fetch) + stdputstr("WE FOUND A SERIOUS PROBLEM\n"); +} +#endif + diff --git a/nyqsrc/debug.h b/nyqsrc/debug.h new file mode 100644 index 0000000..6874ed2 --- /dev/null +++ b/nyqsrc/debug.h @@ -0,0 +1,47 @@ +#ifndef DEBUG_H + +#ifdef PARTIAL_DECLARATIONS +typedef struct partial_susp_struct { + snd_susp_node susp; + boolean started; + long terminate_cnt; + long logical_stop_cnt; + boolean logically_stopped; + sound_type env; + long env_cnt; + sample_block_values_type env_ptr; + + /* support for interpolation of env */ + sample_type env_x1_sample; + double env_pHaSe; + double env_pHaSe_iNcR; + + /* support for ramp between samples of env */ + double output_per_env; + long env_n; + + long phase; + long ph_incr; + double max_diff; + double prev_output; +} partial_susp_node, *partial_susp_type; +#endif + +extern sound_type watch_table_sound; +extern int table_ptr_check_enable; + +void print_sound_type(sound_type s); +void print_sample_block_type(char *label, + sample_block_type sampblock, int len); +void watch_susp(snd_susp_type s); +void watch_sound(sound_type s); +void snd_list_debug(snd_list_type snd_list, char *s); +void watch_snd_list(snd_list_type s); +void dbg_mem_allocated(void *p, char *who); +void dbg_mem_freed(void *p, char *who); +void dbg_mem_print(char *msg, void *p); +void table_ptr_check(); +/* #define TRACESNDGC */ + +#define DEBUG_H +#endif diff --git a/nyqsrc/downsample.c b/nyqsrc/downsample.c new file mode 100644 index 0000000..a796ee5 --- /dev/null +++ b/nyqsrc/downsample.c @@ -0,0 +1,404 @@ +/* downsample.c -- linear interpolation to a lower sample rate */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + + + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "cext.h" +#include "downsample.h" + +void down_free(); + + +typedef struct down_susp_struct { + snd_susp_node susp; + boolean started; + long terminate_cnt; + boolean logically_stopped; + sound_type s; + long s_cnt; + sample_block_values_type s_ptr; + + /* support for interpolation of s */ + sample_type s_x1_sample; + double s_pHaSe; + double s_pHaSe_iNcR; + + /* support for ramp between samples of s */ + double output_per_s; + long s_n; +} down_susp_node, *down_susp_type; + + +void down_n_fetch(susp, snd_list) + register down_susp_type susp; + snd_list_type snd_list; +{ + int cnt = 0; /* how many samples computed */ + int togo = 0; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + + register sample_block_values_type out_ptr_reg; + + register sample_block_values_type s_ptr_reg; + falloc_sample_block(out, "down_n_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = max_sample_block_len - cnt; + + /* don't run past the s input sample block: */ + susp_check_term_log_samples(s, s_ptr, s_cnt); + togo = MIN(togo, susp->s_cnt); + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); + if (togo == 0) break; + } + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + if (to_stop < togo && ((togo = to_stop) == 0)) break; + } + + n = togo; + s_ptr_reg = susp->s_ptr; + out_ptr_reg = out_ptr; + if (n) do { /* the inner sample computation loop */ + *out_ptr_reg++ = *s_ptr_reg++; + } while (--n); /* inner loop */ + + /* using s_ptr_reg is a bad idea on RS/6000: */ + susp->s_ptr += togo; + out_ptr += togo; + susp_took(s_cnt, togo); + cnt += togo; + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* down_n_fetch */ + + +void down_s_fetch(susp, snd_list) + register down_susp_type susp; + snd_list_type snd_list; +{ + int cnt = 0; /* how many samples computed */ + int togo = 0; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + + register sample_block_values_type out_ptr_reg; + + register sample_type s_scale_reg = susp->s->scale; + register sample_block_values_type s_ptr_reg; + falloc_sample_block(out, "down_s_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = max_sample_block_len - cnt; + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); + if (togo == 0) break; + } + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + if (to_stop < togo && ((togo = to_stop) == 0)) break; + } + + n = togo; + s_ptr_reg = susp->s_ptr; + out_ptr_reg = out_ptr; + if (n) do { /* the inner sample computation loop */ + *out_ptr_reg++ = (s_scale_reg * *s_ptr_reg++); + } while (--n); /* inner loop */ + + susp->s_ptr = s_ptr_reg; + out_ptr += togo; + cnt += togo; + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* down_s_fetch */ + + +void down_i_fetch(susp, snd_list) + register down_susp_type susp; + snd_list_type snd_list; +{ + int cnt = 0; /* how many samples computed */ + sample_type s_x2_sample; + int togo = 0; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + + register sample_block_values_type out_ptr_reg; + + register sample_type s_pHaSe_iNcR_rEg = (sample_type) susp->s_pHaSe_iNcR; + register double s_pHaSe_ReG; + register sample_type s_x1_sample_reg; + + falloc_sample_block(out, "down_i_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + /* make sure sounds are primed with first values */ + if (!susp->started) { + susp->started = true; + susp_check_term_log_samples(s, s_ptr, s_cnt); + susp->s_x1_sample = susp_fetch_sample(s, s_ptr, s_cnt); + } + + susp_check_term_log_samples(s, s_ptr, s_cnt); + s_x2_sample = susp_current_sample(s, s_ptr); + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = max_sample_block_len - cnt; + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); + if (togo <= 0) { + togo = 0; + break; + } + } + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + if (to_stop < togo && ((togo = to_stop) <= 0)) { + togo = 0; + break; + } + } + + n = togo; + s_pHaSe_ReG = susp->s_pHaSe; + s_x1_sample_reg = susp->s_x1_sample; + out_ptr_reg = out_ptr; + if (n) do { /* the inner sample computation loop */ + while (s_pHaSe_ReG >= 1.0) { + s_x1_sample_reg = s_x2_sample; + /* pick up next sample as s_x2_sample: */ + susp->s_ptr++; + susp_took(s_cnt, 1); + s_pHaSe_ReG -= 1.0; + /* derived from susp_check_term_log_samples_break, but with + a goto instead of a break */ + if (susp->s_cnt == 0) { + susp_get_samples(s, s_ptr, s_cnt); + terminate_test(s_ptr, s, susp->s_cnt); + /* see if newly discovered logical stop time: */ + logical_stop_test(s, susp->s_cnt); + if ((susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt < + susp->susp.current + cnt + togo) || + (!susp->logically_stopped && + susp->susp.log_stop_cnt != UNKNOWN && + susp->susp.log_stop_cnt < + susp->susp.current + cnt + togo)) { + goto breakout; + } + } + s_x2_sample = susp_current_sample(s, s_ptr); + } + *out_ptr_reg++ = (sample_type) + (s_x1_sample_reg * (1 - s_pHaSe_ReG) + + s_x2_sample * s_pHaSe_ReG); + s_pHaSe_ReG += s_pHaSe_iNcR_rEg; + } while (--n); /* inner loop */ +breakout: + togo -= n; + susp->s_pHaSe = s_pHaSe_ReG; + susp->s_x1_sample = s_x1_sample_reg; + out_ptr += togo; + cnt += togo; + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* down_i_fetch */ + + +void down_toss_fetch(snd_list) + snd_list_type snd_list; +{ + register down_susp_type susp = (down_susp_type) snd_list->u.susp; + long final_count = MIN(susp->susp.current + max_sample_block_len, + susp->susp.toss_cnt); + time_type final_time = susp->susp.t0 + final_count / susp->susp.sr; + long n; + + /* fetch samples from s up to final_time for this block of zeros */ + while (((long) ((final_time - susp->s->t0) * susp->s->sr + 0.5)) >= + susp->s->current) + susp_get_samples(s, s_ptr, s_cnt); + /* convert to normal processing when we hit final_count */ + /* we want each signal positioned at final_time */ + if (final_count == susp->susp.toss_cnt) { + n = ROUND((final_time - susp->s->t0) * susp->s->sr - + (susp->s->current - susp->s_cnt)); + susp->s_ptr += n; + susp_took(s_cnt, n); + susp->susp.fetch = susp->susp.keep_fetch; + } + snd_list->block_len = (short) (final_count - susp->susp.current); + susp->susp.current = final_count; + snd_list->u.next = snd_list_create((snd_susp_type) susp); + snd_list->block = internal_zero_block; +} + + +void down_mark(down_susp_type susp) +{ + sound_xlmark(susp->s); +} + + +void down_free(down_susp_type susp) +{ + sound_unref(susp->s); + ffree_generic(susp, sizeof(down_susp_node), "down_free"); +} + + +void down_print_tree(down_susp_type susp, int n) +{ + indent(n); + stdputstr("s:"); + sound_print_tree_1(susp->s, n); +} + + +sound_type snd_make_down(sr, s) + rate_type sr; + sound_type s; +{ + register down_susp_type susp; + /* sr specified as input parameter */ + time_type t0 = s->t0; + sample_type scale_factor = 1.0F; + time_type t0_min = t0; + + if (s->sr < sr) { + sound_unref(s); + xlfail("snd-down: output sample rate must be lower than input"); + } + falloc_generic(susp, down_susp_node, "snd_make_down"); + + /* select a susp fn based on sample rates */ + if (s->sr == sr) { + susp->susp.fetch = ((s->scale == 1.0) ? + down_n_fetch : down_s_fetch); + } else { + susp->susp.fetch = down_i_fetch; + } + + susp->terminate_cnt = UNKNOWN; + /* handle unequal start times, if any */ + if (t0 < s->t0) sound_prepend_zeros(s, t0); + /* minimum start time over all inputs: */ + t0_min = MIN(s->t0, t0); + /* how many samples to toss before t0: */ + susp->susp.toss_cnt = ROUND((t0 - t0_min) * sr); + if (susp->susp.toss_cnt > 0) { + susp->susp.keep_fetch = susp->susp.fetch; + susp->susp.fetch = down_toss_fetch; + t0 = t0_min; + } + + /* initialize susp state */ + susp->susp.free = down_free; + susp->susp.sr = sr; + susp->susp.t0 = t0; + susp->susp.mark = down_mark; + susp->susp.print_tree = down_print_tree; + susp->susp.name = "down"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = logical_stop_cnt_cvt(s); + susp->started = false; + susp->susp.current = 0; + susp->s = s; + susp->s_cnt = 0; + susp->s_pHaSe = 0.0; + susp->s_pHaSe_iNcR = s->sr / sr; + susp->s_n = 0; + susp->output_per_s = sr / s->sr; + return sound_create((snd_susp_type)susp, t0, sr, scale_factor); +} + + +sound_type snd_down(sr, s) + rate_type sr; + sound_type s; +{ + sound_type s_copy = sound_copy(s); + return snd_make_down(sr, s_copy); +} diff --git a/nyqsrc/downsample.h b/nyqsrc/downsample.h new file mode 100644 index 0000000..1435a73 --- /dev/null +++ b/nyqsrc/downsample.h @@ -0,0 +1,3 @@ +sound_type snd_make_down(); +sound_type snd_down(); + /* LISP: (snd-down ANYNUM SOUND) */ diff --git a/nyqsrc/exitpa.h b/nyqsrc/exitpa.h new file mode 100644 index 0000000..ffdd22d --- /dev/null +++ b/nyqsrc/exitpa.h @@ -0,0 +1,3 @@ +/* exitpa.h -- declare portaudio_exit() */ + +void portaudio_exit(); diff --git a/nyqsrc/f0.cpp b/nyqsrc/f0.cpp new file mode 100644 index 0000000..7b4f08e --- /dev/null +++ b/nyqsrc/f0.cpp @@ -0,0 +1,139 @@ +// f0 -- frequency estimation + +#include + + + +// Estimate a local minimum (or maximum) using parabolic +// interpolation. The parabola is defined by the points +// (x1,y1),(x2,y2), and (x3,y3). +float parabolic_interp(float x1, float x2, float x3, float y1, float y2, float y3, float *min) +{ + float a, b, c; + float pos; + + // y1=a*x1^2+b*x1+c + // y2=a*x2^2+b*x2+c + // y3=a*x3^2+b*x3+c + + // y1-y2=a*(x1^2-x2^2)+b*(x1-x2) + // y2-y3=a*(x2^2-x3^2)+b*(x2-x3) + + // (y1-y2)/(x1-x2)=a*(x1+x2)+b + // (y2-y3)/(x2-x3)=a*(x2+x3)+b + + a= ((y1-y2)/(x1-x2)-(y2-y3)/(x2-x3))/(x1-x3); + b= (y1-y2)/(x1-x2) - a*(x1+x2); + c= y1-a*x1*x1-b*x1; + + *min= c; + + // dy/dx = 2a*x + b = 0 + + pos= -b/2.0/a; + + return pos; + +} + + + +float f0_estimate(float *samples, int n, int m, float threshold, float *results, float *min) + // samples is a buffer of samples + // n is the number of samples, equals twice longest period, must be even + // m is the shortest period in samples + // results is an array of size n/2 - m + 1, the number of different lags +{ + // work from the middle of the buffer: + int middle = n / 2; + int i, j; // loop counters + // how many different lags do we compute? + float left_energy = 0; + float right_energy = 0; + // for each window, we keep the energy so we can compute the next one + // incrementally. First, we need to compute the energies for lag m-1: + for (i = 0; i < m - 1; i++) { + float left = samples[middle - 1 - i]; + left_energy += left * left; + float right = samples[middle + i]; + right_energy += right * right; + } + for (i = m; i <= middle; i++) { + // i is the lag and the length of the window + // compute the energy for left and right + float left = samples[middle - i]; + left_energy += left * left; + float right = samples[middle - 1 + i]; + + right_energy += right * right; + // compute the autocorrelation + float auto_corr = 0; + for (j = 0; j < i; j++) { + auto_corr += samples[middle - i + j] * samples[middle + j]; + } + float non_periodic = (left_energy + right_energy - 2 * auto_corr);// / i; + results[i - m] = non_periodic; + + } + + + // normalize by the cumulative sum + float cum_sum=0.0; + for (i = m; i <= middle; i++) { + cum_sum+=results[i-m]; + results[i-m]=results[i-m]/(cum_sum/(i-m+1)); + + } + + int min_i=m; // value of initial estimate + for (i = m; i <= middle; i++) { + if (results[i - m] < threshold) { + min_i=i; + break; + } else if (results[i-m]m && i +#include +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" + +/* special free lists */ +CQUE *sample_block_free = NULL; /* really a sample_block_type */ + +/* special counts */ +int sample_block_used = 0; +int sample_block_low_water = 0; +int sample_block_total = 0; +int snd_list_used = 0; +int sound_used = 0; + +/* generic free lists */ +CQUE *generic_free[MAXLISTS]; + + +void falloc_init(void) +{ + int i; + for (i = 0; i < MAXLISTS; i++) generic_free[i] = NULL; +} + + +/* memory pool */ +char *poolp = NULL; +char *poolend = NULL; + +/* sample block memory pool */ +char *spoolp = NULL; +char *spoolend = NULL; + +int npools = 0; + +#if defined(TRACK_POOLS) && TRACK_POOLS +#define POOL_HEAD_SIZE (round_size(sizeof(CQUE))) +CQUE *pools = NULL; +#endif + +void sound_already_free_test(s) + sound_type s; +{ + sound_type sp; + for (sp = (sound_type) sound_free; sp; sp = (sound_type) ((CQUE *) sp)->qnext) { + if (s == sp) { + stdputstr("SOUND ALREADY FREE!!!"); + fflush(stdout); + sp = 0; sp->list = 0; /* trap to debugger */ + } + } +} + + +/* new_pool -- allocate a new pool from which mem is allocated */ +/**/ +void new_pool(void) +{ + poolp = (char *) malloc(MAXPOOLSIZE); + + if (poolp == NULL) { + fprintf(STDERR, "Nyquist: out of memory!\n"); + EXIT(1); + } + + poolend = poolp + MAXPOOLSIZE; + npools++; + /* stick to double word boundaries */ + poolp = (char *) round_size(((long) poolp)); +} + +/* new_spool -- allocate a new spool from which sample blocks are allocated */ +/**/ +void new_spool(void) +{ +#if defined(TRACK_POOLS) && TRACK_POOLS + spoolp = (char *) malloc(MAXSPOOLSIZE + POOL_HEAD_SIZE); +#else + spoolp = (char *) malloc(MAXSPOOLSIZE); +#endif + + if (spoolp == NULL) { + fprintf(STDERR, "Nyquist: out of memory!\n"); + EXIT(1); + } + +#if defined(TRACK_POOLS) && TRACK_POOLS + Qenter(pools, spoolp); + spoolp += POOL_HEAD_SIZE; +#endif + + spoolend = spoolp + MAXSPOOLSIZE; + npools++; + /* stick to double word boundaries */ + spoolp = (char *) round_size(((long) spoolp)); +} + + +/* find_sample_block -- get sample block when freelist is empty */ +/* Try these strategies in order: + 1) try free list + 2) use pool to get sample_blocks_low_water + BLOCKS_PER_GC blocks or until + pool runs out + 3) GC and try free list again, set sample_blocks_low_water to + sample_blocks_used + 4) try pool again + 5) allocate new pool and use it + */ +sample_block_type find_sample_block(void) +{ + sample_block_type sp; + if (sample_block_total < sample_block_low_water + BLOCKS_PER_GC && + check_spool(round_size(sizeof(sample_block_node)))) { + if (DEBUG_MEM) spoolp += DEBUG_MEM_INFO_SIZE; + sp = (sample_block_type) spoolp; + spoolp += round_size(sizeof(sample_block_node)); + sample_block_total++; +/* printf("fp%d ", sample_block_total - sample_block_low_water); */ + } else { +/* printf("falloc calling gc\n"); */ + gc(); + sample_block_low_water = sample_block_used; + if (!Qempty(sample_block_free)) { + Qget(sample_block_free, sample_block_type, sp); +/* printf("gc, then from freelist\n"); */ + } else if (check_spool(round_size(sizeof(sample_block_node)))) { + if (DEBUG_MEM) spoolp += DEBUG_MEM_INFO_SIZE; + sp = (sample_block_type) spoolp; + spoolp += round_size(sizeof(sample_block_node)); + sample_block_total++; +/* printf("gc, then from spool\n"); */ + } else { + new_spool(); + if (DEBUG_MEM) spoolp += DEBUG_MEM_INFO_SIZE; + sp = (sample_block_type) spoolp; + spoolp += round_size(sizeof(sample_block_node)); + sample_block_total++; +/* printf("gc, then new spool\n"); */ + } + } + return sp; +} + + + +/* get_from_pool -- return size bytes from pool memory */ +/**/ +char *get_from_pool(size_t siz) +{ + if (!check_pool(siz)) { + new_pool(); + } + poolp += siz; + if (DEBUG_MEM) poolp += DEBUG_MEM_INFO_SIZE; /* allow for debug info */ + return poolp - siz; +} + + +#if defined(TRACK_POOLS) && TRACK_POOLS + +/* falloc_gc -- return empty pools to the system */ +/* + * Algorithm: for each pool, move all free sample blocks + * (on the sample_block_free list) to tlist. If tlist + * has ALL of the blocks in the pool (determined by + * byte counts), the pool is returned to the heap. + */ +void falloc_gc() +{ + CQUE *lp = NULL; + CQUE *cp; + CQUE *np; + CQUE *tlist = NULL; + + /* Scan all allocated pools */ + for (cp = pools; cp; lp = cp, cp = np) { + char *str = ((char *)cp) + POOL_HEAD_SIZE; + char *end = str + MAXSPOOLSIZE; + long tsiz = end - str; + long csiz = 0; + CQUE *tsave = NULL; + CQUE *ln = NULL; + CQUE *cn; + CQUE *nn; + + /* Save pointer to next pool */ + np = cp->qnext; + + /* Remember head of temp free list */ + tsave = tlist; + + /* Scan all nodes on the free list */ + for (cn = sample_block_free; cn; ln = cn, cn = nn) { + + /* Get next node */ + nn = cn->qnext; + + /* Count it if the node belongs to this pool */ + if (cn >= (CQUE *) str && cn <= (CQUE *) end) { + csiz += round_size(sizeof(sample_block_node)); + + Qenter(tlist, cn); + + /* Unlink the node */ + if (cn == sample_block_free) { + sample_block_free = nn; + cn = NULL; + } + else { + ln->qnext = nn; + cn = ln; + } + } + } + + /* The pool had inuse nodes */ + if (csiz != tsiz) { + continue; + } + + /* Remove the nodes from the temp free list */ + tlist = tsave; + + /* Maintain stats */ + sample_block_total -= (tsiz / round_size(sizeof(sample_block_node))); + npools--; + + /* If this is the active pool, then reset current pointers */ + if (spoolp >= str && spoolp <= end) { + spoolp = NULL; + spoolend = NULL; + } + + /* Release the pool to the system */ + free(cp); + + /* Unlink this pool from the list */ + if (cp == pools) { + pools = np; + cp = NULL; + } + else { + /* lp cannot be null here: On 1st iteration, lp == NULL, but + * cp == pools, so code above is executed. Before the for-loop + * iterates, pools == np (assigned above), and cp == NULL. The + * for-loop update (lp=cp,cp=np) produces lp == NULL, cp == pools. + * Since cp == pools, this else branch will not be taken. + * The other path to this code is via the "continue" above. In that + * case, the update (lp=cp,cp=np) makes lp a valid pointer or else + * the loop exits. + * The assert(lp) is here to possibly make static analyzers happy. + */ + assert(lp); + lp->qnext = np; + cp = lp; + } + } + + /* Resave list of free nodes */ + sample_block_free = tlist; +} + +#endif + + diff --git a/nyqsrc/falloc.h b/nyqsrc/falloc.h new file mode 100644 index 0000000..1219bfd --- /dev/null +++ b/nyqsrc/falloc.h @@ -0,0 +1,253 @@ +/* + * falloc.h + * nyquist memory allocation data structures and macros + * + * there is an falloc and ffree for each major type of data structure + * there is an falloc and ffree for generic (not so common) structures + * there is an frelease for some structures. this reduces the + * reference count for the particular structure by 1; it + * does not continue recursively. + */ + +/* Debugging support: + * When DEBUG_MEM is set, each piece of allocated storage will contain + * a pointer to a string naming the caller or other allocation info, + * and a sequence number. (8 extra bytes are allocated for this info). + * + * When storage is freed, the ID is set to NULL, and the routine + * dbg_mem_check(ptr) will abort if ID is NULL. Call this routine to + * avoid following a pointer to data that was previously freed. + * + * The goal of this support is to allow you to "go back" to the point + * where memory is corrupted; specifically where a memory block is freed + * too early. + * + * When a memory-related bug is crashing the system: + * (1) Recompile with DEBUG_MEM on. + * (2) Develop some Nyquist code that will predictably crash the system. + * (3) When Nyquist crashes, use a debugger to find where the bad + * pointer came from. See if the source of the pointer was freed. + * (4) If the source of the pointer was freed, then notice the sequence + * number. + * (5) Rerun with dbg_mem_seq_num set to the number noted in (4). + * (6) Nyquist will print when the storage in question was allocated and + * freed. Use the debugger to find out why the storage is + * freed too early and who did it. + * (7) If the source of the pointer in (3) was not freed, you're on your + * own. + * + * The DEBUG_MEM related routines are: + * dbg_mem_allocated: called when memory is allocated + * dbg_mem_freed: called when memory is freed + * dbg_mem_released: called when memory is released + * dbg_mem_check: called to check memory + * + * see also xldmem.c: + * by setting xldmem_trace to a pointer, you can trace when the + * pointer is referenced by anything in the heap + */ + + +/* to get size_t on pmax: */ +#ifdef pmax +#include "sys/types.h" +#endif + +#include "cque.h" +#include "debug.h" + +#define DEBUG_MEM 0 +#define DEBUG_MEM_INFO_SIZE (sizeof(long) + sizeof(char *)) + +/* special free lists */ +extern CQUE *sample_block_free; /* really a sample_block_type */ + +/* special counts */ +extern int sample_block_total; +extern int sample_block_used; +extern int snd_list_used; +extern int sound_used; +extern long table_memory; + +/* generic free lists */ +#define MAXLISTS 128 +extern CQUE *generic_free[MAXLISTS]; + +/* general memory pool */ +#define MAXPOOLSIZE 1000000 +extern char *poolp; +extern char *poolend; + +/* sample block memory pool */ +#define MAXSPOOLSIZE (256 * round_size(sizeof(sample_block_node))) +extern char *spoolp; +extern char *spoolend; + +extern int npools; +extern int sample_blocks_since_gc; + +#if !defined(TRACK_POOLS) +#define TRACK_POOLS 1 +#endif + +#if defined(TRACK_POOLS) && TRACK_POOLS +// extern CQUE *pools; +void falloc_gc(); +#endif + +void falloc_init(void); +void new_pool(void); +void new_spool(void); +sample_block_type find_sample_block(void); + +char *get_from_pool(size_t siz); + +#define round_size(n) (((n) + 7) & ~7) + +/* check_pool -- returns true if enough bytes are available */ +#if DEBUG_MEM +#define check_pool(size) (poolp + (size) + DEBUG_MEM_INFO_SIZE <= poolend) +#define check_spool(size) (spoolp + (size) + DEBUG_MEM_INFO_SIZE <= spoolend) +#define DBG_MEM_ALLOCATED(p, who) dbg_mem_allocated(p, who) +#define DBG_MEM_FREED(p, who) dbg_mem_freed(p, who) +#define DBG_MEM_RELEASED(p, who) dbg_mem_released(p, who) +#else +#define check_pool(size) (poolp + (size) <= poolend) +#define check_spool(size) (spoolp + (size) <= spoolend) +#define DBG_MEM_ALLOCATED(p, who) +#define DBG_MEM_FREED(p, who) +#define DBG_MEM_RELEASED(p, who) +#endif + +#define BLOCKS_PER_GC 100 + +#define falloc_sample_block(sp, who) { \ + if (!Qempty(sample_block_free)) \ + Qget(sample_block_free, sample_block_type, sp) \ + else sp = find_sample_block(); \ + /* sample_block_test(sp, "falloc_sample_block"); */ \ + /* printf("[%x] ", sp); */ \ + DBG_MEM_ALLOCATED(sp, who); \ + sp->refcnt = 1; \ + sample_block_used++; \ +} + + +#define ffree_sample_block(sp, who) { \ + /* printf("freeing sample_block@%x\n", sp); */ \ + DBG_MEM_FREED(sp, who); \ + Qenter(sample_block_free, sp); \ + sample_block_used--; \ +} + +#define frelease_sample_block(sp, who) { \ + sp->refcnt--; \ + DBG_MEM_RELEASED(sp, who); \ + if (sp->refcnt <= 0) { \ + ffree_sample_block(sp); \ + } \ +} + + +/* NOTE: This must not cause garbage collection. + * LVAL parameters to snd_make_? functions are not + * protected and falloc_sound is invoked there. + */ +#define snd_list_free (generic_free[round_size(sizeof(snd_list_node)) >> 3]) + +#define falloc_snd_list(sp, who) { \ + if (!Qempty(snd_list_free)) \ + Qget(snd_list_free, snd_list_type, sp) \ + else \ + sp = (snd_list_type)get_from_pool(round_size(sizeof(snd_list_node)));\ + snd_list_used++; \ + DBG_MEM_ALLOCATED(sp, who); \ +} + + +#define ffree_snd_list(sp, who) { \ + DBG_MEM_FREED(sp, who); \ + Qenter(snd_list_free, sp); \ + snd_list_used--; \ +} + + +#define frelease_snd_list(sp, who) { \ + sp->refcnt--; \ + DBG_MEM_RELEASED(sp, who); \ + if (sp->refcnt <= 0) { \ + ffree_snd_list(sp, who); \ + } \ +} + + +#define sound_free (generic_free[round_size(sizeof(sound_node)) >> 3]) + +#define NORMALSOUNDALLOC +#ifdef NORMALSOUNDALLOC +#define falloc_sound(sp, who) { \ + if (!Qempty(sound_free)) { \ + Qget(sound_free, sound_type, sp); \ + } else { \ + sp = (sound_type) get_from_pool(round_size(sizeof(sound_node))); \ + } \ + sound_used++; \ + DBG_MEM_ALLOCATED(sp, who); \ +} +#else +#define falloc_sound(sp) \ + sp =(sound_type) \ + get_from_pool(round_size(sizeof(sound_node))) +#endif + +/* note: usually you call sound_unref, not this macro */ +#define ffree_sound(sp, who) { \ +/* sound_already_free_test(); */ \ + DBG_MEM_FREED(sp, who); \ + Qenter(sound_free, sp); \ + sound_used--; \ +} + + +/* falloc_generic -- sp gets new node of type sptype */ +/**/ +#define falloc_generic(sp, sptype, who) { \ + int size = round_size(sizeof(sptype)); \ + falloc_generic_bytes(sp, sptype, size, who) } + +/* falloc_generic_n -- sp gets new array of n sptype's */ +/**/ +#define falloc_generic_n(sp, sptype, n, who) { \ + int min_size = sizeof(sptype) * (n); \ + int size = round_size(min_size); \ + falloc_generic_bytes(sp, sptype, size, who) } + +#define falloc_generic_bytes(sp, sptype, size, who) \ + if ((size >> 3) >= MAXLISTS) { \ + stdputstr("falloc_generic problem\n"); \ + sp = (sptype *) malloc(size); \ + } else if (!Qempty(generic_free[size >> 3])) { \ + Qget(generic_free[size >> 3], sptype *, sp); \ + } else { \ + sp = (sptype *) get_from_pool(size); \ + } \ + DBG_MEM_ALLOCATED(sp, who); \ +/* printf("GENERIC ALLOC %x\n", sp); */ + + +/* ffree_generic puts an item back on proper freelist */ +/* NOTE: sIzE is capitalized funny so that it will not + * match an actual parameter, e.g. if the caller writes + * ffree_generic(ptr, size), we don't want the expanded + * code to include: "int size = round_size(size) >> 3"! + */ +#define ffree_generic(sp, nn, who) { \ + int sIzE = round_size(nn) >> 3; \ + DBG_MEM_FREED(sp, who); \ + /* printf("GENERIC FREE %x SIZE %d\n", sp, nnn); */ \ + if ((sIzE) >= MAXLISTS) { \ + free(sp); \ + } else { \ + Qenter(generic_free[sIzE], sp); \ + } \ +} diff --git a/nyqsrc/ffilterkit.c b/nyqsrc/ffilterkit.c new file mode 100644 index 0000000..d78d5c5 --- /dev/null +++ b/nyqsrc/ffilterkit.c @@ -0,0 +1,123 @@ +/* + * ffilterkit.c (library "filterkit.a"): + * Kaiser-windowed low-pass filter support. + */ + +/* ffilterkit.c + * + * FilterUp() - Applies a filter to a given sample when up-converting. + * FilterUD() - Applies a filter to a given sample when up- or down- + * converting. + */ + + /* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +#include +#include +#include +#include "stdefs.h" +#include "fresample.h" +#include "ffilterkit.h" + + +fast_float FilterUp(float Imp[], float ImpD[], + int Nwing, boolean Interp, + float *Xp, double Ph, int Inc) +{ + float *Hp, *Hdp = NULL, *End; + fast_float a = 0; + fast_float v, t; + double exact_index = Ph * Npc; + long index = (long) exact_index; /* convert fraction to filter index */ + +/* nyquist_printf("FilterUp, Inc %d, phase %g\n", Inc, Ph); */ + v=0; + Hp = &Imp[index]; + End = &Imp[Nwing]; + if (Interp) { + Hdp = &ImpD[index]; + a = exact_index - index; +/* nyquist_printf("fraction %g\n", a); */ + } + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + { /* ...then we've already skipped the */ + Hp += Npc; /* first sample, so we must also */ + Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */ + } + } + if (Interp) { + while (Hp < End) { + t = *Hp; /* Get filter coeff */ + /* t scaled by 2^(16 + NLpScl)/LpScl */ + t += *Hdp *a; /* t is now interp'd filter coeff */ + Hdp += Npc; /* Filter coeff differences step */ + t *= *Xp; /* Mult coeff by input sample */ + /* t scaled by 2^(16 + NLpScl)/LpScl */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } else { + while (Hp < End) { + t = *Hp; /* Get filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } + return(v); +} + +fast_float FilterUD( float Imp[], float ImpD[], + int Nwing, boolean Interp, + float *Xp, double Ph, int Inc, double dhb) +{ + double a; + float *Hp, *Hdp, *End; + fast_float v, t; + double Ho; + + v=0; + Ho = Ph*dhb; + End = &Imp[Nwing]; + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + Ho += dhb; /* ...then we've already skipped the */ + } /* first sample, so we must also */ + /* skip ahead in Imp[] and ImpD[] */ + if (Interp) { + long HoIndex = (long) Ho; + while ((Hp = &Imp[HoIndex]) < End) { + t = *Hp; /* Get IR sample */ + Hdp = &ImpD[HoIndex]; /* get interp (lower Na) bits from diff table*/ + a = Ho - HoIndex; /* a is logically between 0 and 1 */ + t += *Hdp * a; /* t is now interp'd filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + HoIndex = (long) Ho; + } + } else { + long HoIndex = (long) Ho; + while ((Hp = &Imp[HoIndex]) < End) { + t = *Hp; /* Get IR sample */ + t *= *Xp; /* Mult coeff by input sample */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + HoIndex = (long) Ho; + } + } + return(v); +} + diff --git a/nyqsrc/ffilterkit.h b/nyqsrc/ffilterkit.h new file mode 100644 index 0000000..d277e7d --- /dev/null +++ b/nyqsrc/ffilterkit.h @@ -0,0 +1,15 @@ +/*:filterkit.h */ + +/* + * FilterUp() - Applies a filter to a given sample when up-converting. + * FilterUD() - Applies a filter to a given sample when up- or down- + * converting. + */ + +fast_float FilterUp(mem_float Imp[], mem_float ImpD[], int Nwing, + boolean Interp, mem_float *Xp, double Ph, int Inc); + +fast_float FilterUD(mem_float Imp[], mem_float ImpD[], int Nwing, + boolean Interp, mem_float *Xp, double Ph, int Inc, + double dhb); + diff --git a/nyqsrc/fft-rbd.c b/nyqsrc/fft-rbd.c new file mode 100644 index 0000000..6d01e6a --- /dev/null +++ b/nyqsrc/fft-rbd.c @@ -0,0 +1,156 @@ +/* samples.c -- fugue sound data type */ + +#include +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "fft.h" + + +/* NOTE: this code does not properly handle start times that do not + * correspond to the time of the first actual sample + */ + + +/* snd_fetch_array -- fetch a lisp array of samples */ +/* + * storage layout: the extra field points to extra state that we'll use + * extra[0] -> length of extra storage + * extra[1] -> CNT (number of samples in current block) + * extra[2] -> INDEX (current sample index in current block) + * extra[3] -> FILLCNT (how many samples in buffer) + * extra[4] -> TERMCNT (how many samples until termination) + * extra[4 .. 4+len-1] -> samples (stored as floats) + * + * Termination details: + * Return NIL when the sound terminates. + * Termination is defined as the point where all original + * signal samples have been shifted out of the samples buffer + * so that all that's left are zeros from beyond the termination + * point. + * Implementation: when termination is discovered, set TERMCNT + * to the number of samples to be shifted out. TERMCNT is initially + * -1 as a flag that we haven't seen the termination yet. + * Each time samples are shifted, decrement TERMCNT by the shift amount. + * When TERMCNT goes to zero, return NULL. + */ + +#define CNT extra[1] +#define INDEX extra[2] +#define FILLCNT extra[3] +#define TERMCNT extra[4] +#define OFFSET 5 +#define SAMPLES list->block->samples + +LVAL snd_fft(sound_type s, long len, long step /* more parameters may belong here */) +{ + long i, maxlen, skip, fillptr; + float *samples; + LVAL result; + + if (len < 1) xlfail("len < 1"); + + if (!s->extra) { /* this is the first call, so fix up s */ + /* note: any storage required by fft must be allocated here in a contiguous + * block of memory who's size is given by the first long in the block. + * Here, there are 4 more longs after the size, and then room for len floats + * (assumes that floats and longs take equal space). + * + * The reason for this storage restriction is that when a sound is freed, the + * block of memory pointed to by extra is also freed. There is no function + * call that might free a more complex structure (this could be added in sound.c + * however if it's really necessary). + */ + falloc_generic_n(s->extra, long, len + OFFSET, "snd_fft"); + s->extra[0] = sizeof(long) * (len + OFFSET); + s->CNT = s->INDEX = s->FILLCNT = 0; + s->TERMCNT = -1; + maxlen = len; + } else { + maxlen = (s->extra[0] / sizeof(long)) - OFFSET; + if (maxlen < 1) xlfail("sound in use by another iterator"); + if (maxlen < len) xlfail("len grew"); + } + samples = (float *) &(s->extra[OFFSET]); + + /* step 1: refill buffer with samples */ + fillptr = s->FILLCNT; + while (fillptr < maxlen) { + if (s->INDEX == s->CNT) { + sound_get_next(s, &(s->CNT)); + if (s->SAMPLES == zero_block->samples) { + if (s->TERMCNT < 0) s->TERMCNT = fillptr; + } + s->INDEX = 0; + } + samples[fillptr++] = s->SAMPLES[s->INDEX++] * s->scale; + } + s->FILLCNT = fillptr; + + /* it is important to test here AFTER filling the buffer, because + * if fillptr WAS 0 when we hit the zero_block, then filling the + * buffer will set TERMCNT to 0. + */ + if (s->TERMCNT == 0) return NULL; + + /* logical stop time is ignored by this code -- to fix this, + * you would need a way to return the logical stop time to + * the caller. + */ + + /* HERE IS WHERE THE FFT SHOULD TAKE PLACE ON samples. DO NOT + * DESTROY SAMPLES IF YOU WANT TO ALLOW OVERLAPPED FFT'S. THE + * CURRENT CODE RETURNS SAMPLES, BUT A REAL FFT WOULD RETURN + * THE RESULT OF THE FFT IN STEP 2, WHICH FOLLOWS: + */ + + /* step 2: construct an array and return it */ + xlsave1(result); + result = newvector(len); + + for (i = 0; i < len; i++) { + setelement(result, i, cvflonum(samples[i])); + } + + /* step 3: shift samples by step */ + if (step < 0) xlfail("step < 0"); + s->FILLCNT -= step; + if (s->FILLCNT < 0) s->FILLCNT = 0; + for (i = 0; i < s->FILLCNT; i++) { + samples[i] = samples[i + step]; + } + + + if (s->TERMCNT >= 0) { + s->TERMCNT -= step; + if (s->TERMCNT < 0) s->TERMCNT = 0; + } + + + /* step 4: advance in sound to next sample we need + * (only does work if step > size of buffer) + */ + skip = step - maxlen; + while (skip > 0) { + long remaining = s->CNT - s->INDEX; + if (remaining >= skip) { + s->INDEX += skip; + skip = 0; + } else { + skip -= remaining; + sound_get_next(s, &(s->CNT)); + s->INDEX = 0; + } + } + + /* restore the stack */ + xlpop(); + return result; +} /* snd_fetch_array */ + + + + diff --git a/nyqsrc/fft.c b/nyqsrc/fft.c new file mode 100644 index 0000000..95095ac --- /dev/null +++ b/nyqsrc/fft.c @@ -0,0 +1,223 @@ +/* fft.c -- implement snd_fft */ + +#define _USE_MATH_DEFINES 1 /* for Visual C++ to get M_LN2 */ +#include +#include +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "fft.h" +#include "fftext.h" + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm change for portability: min->MIN + */ + + +/* NOTE: this code does not properly handle start times that do not + * correspond to the time of the first actual sample + */ + + +/* The snd_fft function is based on snd_fetch_array */ +/* + * storage layout: the extra field points to extra state that we'll use + * extra[0] -> length of extra storage + * extra[1] -> CNT (number of samples in current block) + * extra[2] -> INDEX (current sample index in current block) + * extra[3] -> FILLCNT (how many samples in buffer) + * extra[4] -> TERMCNT (how many samples until termination) + * extra[5 .. 5+len-1] -> samples (stored as floats) + * extra[5+len .. 5+2*len-1] -> array of samples to fft + * extra[5+2*len ... 5+3*len-1] -> window coefficients + * + * Termination details: + * Return NIL when the sound terminates. + * Termination is defined as the point where all original + * signal samples have been shifted out of the samples buffer + * so that all that's left are zeros from beyond the termination + * point. + * Implementation: when termination is discovered, set TERMCNT + * to the number of samples to be shifted out. TERMCNT is initially + * -1 as a flag that we haven't seen the termination yet. + * Each time samples are shifted, decrement TERMCNT by the shift amount. + * When TERMCNT goes to zero, return NULL. + */ + +#define CNT extra[1] +#define INDEX extra[2] +#define FILLCNT extra[3] +#define TERMCNT extra[4] +#define OFFSET 5 +#define SAMPLES list->block->samples + +/* DEBUGGING PRINT FUNCTION: + void printfloats(char *caption, float *data, int len) + { + int i; + printf("%s: ", caption); + for (i = 0; i < len; i++) { + printf("%d:%g ", i, data[i]); + } + printf("\n"); + } +*/ + +void n_samples_from_sound(sound_type s, long n, float *table) +{ + long blocklen; + sample_type scale_factor = s->scale; + s = sound_copy(s); + while (n > 0) { + sample_block_type sampblock = sound_get_next(s, &blocklen); + long togo = MIN(blocklen, n); + long i; + sample_block_values_type sbufp = sampblock->samples; + for (i = 0; i < togo; i++) { + *table++ = (float) (*sbufp++ * scale_factor); + } + n -= togo; + } + sound_unref(s); +} + + +LVAL snd_fft(sound_type s, long len, long step, LVAL winval) +{ + long i, m, maxlen, skip, fillptr; + float *samples; + float *temp_fft; + float *window; + LVAL result; + + if (len < 1) xlfail("len < 1"); + + if (!s->extra) { /* this is the first call, so fix up s */ + sound_type w = NULL; + if (winval) { + if (soundp(winval)) { + w = getsound(winval); + } else { + xlerror("expected a sound", winval); + } + } + /* note: any storage required by fft must be allocated here in a + * contiguous block of memory who's size is given by the first long + * in the block. Here, there are 4 more longs after the size, and + * then room for 3*len floats (assumes that floats and longs take + * equal space). + * + * The reason for 3*len floats is to provide space for: + * the samples to be transformed (len) + * the complex FFT result (len) + * the window coefficients (len) + * + * The reason for this storage restriction is that when a sound is + * freed, the block of memory pointed to by extra is also freed. + * There is no function call that might free a more complex + * structure (this could be added in sound.c, however, if it's + * really necessary). + */ + s->extra = (long *) malloc(sizeof(long) * (3 * len + OFFSET)); + s->extra[0] = sizeof(long) * (3 * len + OFFSET); + s->CNT = s->INDEX = s->FILLCNT = 0; + s->TERMCNT = -1; + maxlen = len; + window = (float *) &(s->extra[OFFSET + 2 * len]); + /* fill the window from w */ + if (!w) { + for (i = 0; i < len; i++) *window++ = 1.0F; + } else { + n_samples_from_sound(w, len, window); + } + } else { + maxlen = ((s->extra[0] / sizeof(long)) - OFFSET) / 3; + if (maxlen != len) xlfail("len changed from initial value"); + } + samples = (float *) &(s->extra[OFFSET]); + temp_fft = samples + len; + window = temp_fft + len; + /* step 1: refill buffer with samples */ + fillptr = s->FILLCNT; + while (fillptr < maxlen) { + if (s->INDEX == s->CNT) { + sound_get_next(s, &(s->CNT)); + if (s->SAMPLES == zero_block->samples) { + if (s->TERMCNT < 0) s->TERMCNT = fillptr; + } + s->INDEX = 0; + } + samples[fillptr++] = s->SAMPLES[s->INDEX++] * s->scale; + } + s->FILLCNT = fillptr; + + /* it is important to test here AFTER filling the buffer, because + * if fillptr WAS 0 when we hit the zero_block, then filling the + * buffer will set TERMCNT to 0. + */ + if (s->TERMCNT == 0) return NULL; + + /* logical stop time is ignored by this code -- to fix this, + * you would need a way to return the logical stop time to + * the caller. + */ + + /* step 2: construct an array and return it */ + xlsave1(result); + result = newvector(len); + + /* first len floats will be real part, second len floats imaginary + * copy buffer to temp_fft with windowing + */ + for (i = 0; i < len; i++) { + temp_fft[i] = samples[i] * *window++; + } + /* perform the fft: */ + m = round(log(len) / M_LN2); /* compute log-base-2(len) */ + if (!fftInit(m)) rffts(temp_fft, m, 1); + else xlfail("FFT initialization error"); + + /* move results to Lisp array */ + setelement(result, 0, cvflonum(temp_fft[0])); + setelement(result, len - 1, cvflonum(temp_fft[1])); + for (i = 2; i < len; i++) { + setelement(result, i - 1, cvflonum(temp_fft[i])); + } + + /* step 3: shift samples by step */ + if (step < 0) xlfail("step < 0"); + s->FILLCNT -= step; + if (s->FILLCNT < 0) s->FILLCNT = 0; + for (i = 0; i < s->FILLCNT; i++) { + samples[i] = samples[i + step]; + } + + if (s->TERMCNT >= 0) { + s->TERMCNT -= step; + if (s->TERMCNT < 0) s->TERMCNT = 0; + } + + /* step 4: advance in sound to next sample we need + * (only does work if step > size of buffer) + */ + skip = step - maxlen; + while (skip > 0) { + long remaining = s->CNT - s->INDEX; + if (remaining >= skip) { + s->INDEX += skip; + skip = 0; + } else { + skip -= remaining; + sound_get_next(s, &(s->CNT)); + s->INDEX = 0; + } + } + + /* restore the stack */ + xlpop(); + return result; +} /* snd_fetch_array */ diff --git a/nyqsrc/fft.h b/nyqsrc/fft.h new file mode 100644 index 0000000..74b2b24 --- /dev/null +++ b/nyqsrc/fft.h @@ -0,0 +1,4 @@ +/* fft.h -- fft returned through a lisp array */ + +LVAL snd_fft(sound_type s, long len, long step, LVAL w); + /* LISP: (SND-FFT SOUND FIXNUM FIXNUM ANY) */ diff --git a/nyqsrc/fftr4.c b/nyqsrc/fftr4.c new file mode 100644 index 0000000..d5dfcc9 --- /dev/null +++ b/nyqsrc/fftr4.c @@ -0,0 +1,264 @@ +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif + +#define PI 3.14159265359 +#define MAXPOW 24 + +struct complex +{ + double r; + double i; +}; + +int pow_2[MAXPOW]; +int pow_4[MAXPOW]; + +void twiddle(struct complex *W, int N, double stuff) +{ + W->r=cos(stuff*2.0*PI/(double)N); + W->i=-sin(stuff*2.0*PI/(double)N); +} + +void bit_reverse_reorder(struct complex *W, int N) +{ + int bits, i, j, k; + double tempr, tempi; + + for (i=0; ii) /** Only make "up" swaps */ + { + tempr=W[i].r; + tempi=W[i].i; + W[i].r=W[j].r; + W[i].i=W[j].i; + W[j].r=tempr; + W[j].i=tempi; + } + } +} +void bit_r4_reorder(struct complex *W, int N) +{ + int bits, i, j, k; + double tempr, tempi; + + for (i=0; ii) /** Only make "up" swaps */ + { + tempr=W[i].r; + tempi=W[i].i; + W[i].r=W[j].r; + W[i].i=W[j].i; + W[j].r=tempr; + W[j].i=tempi; + } + } +} + +/** RADIX-4 FFT ALGORITHM */ +void radix4(struct complex *x, int N) +{ + int n2, k1, N1, N2; + struct complex W, bfly[4]; + + N1=4; + N2=N/4; + + /** Do 4 Point DFT */ + for (n2=0; n2 +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Define for using single precision */ +/* + * If you can, use configure --enable-float instead of changing this + * flag directly + */ +/* #undef FFTW_ENABLE_FLOAT */ + +/* our real numbers */ +#ifdef FFTW_ENABLE_FLOAT +typedef float fftw_real; +#else +typedef double fftw_real; +#endif + +/********************************************* + * Complex numbers and operations + *********************************************/ +typedef struct { + fftw_real re, im; +} fftw_complex; + +#define c_re(c) ((c).re) +#define c_im(c) ((c).im) + +typedef enum { + FFTW_FORWARD = -1, FFTW_BACKWARD = 1 +} fftw_direction; + +/* backward compatibility with FFTW-1.3 */ +typedef fftw_complex FFTW_COMPLEX; +typedef fftw_real FFTW_REAL; + +#ifndef FFTW_1_0_COMPATIBILITY +#define FFTW_1_0_COMPATIBILITY 0 +#endif + +#if FFTW_1_0_COMPATIBILITY +/* backward compatibility with FFTW-1.0 */ +#define REAL fftw_real +#define COMPLEX fftw_complex +#endif + +/********************************************* + * Success or failure status + *********************************************/ + +typedef enum { + FFTW_SUCCESS = 0, FFTW_FAILURE = -1 +} fftw_status; + +/********************************************* + * Codelets + *********************************************/ +typedef void (fftw_notw_codelet) + (const fftw_complex *, fftw_complex *, int, int); +typedef void (fftw_twiddle_codelet) + (fftw_complex *, const fftw_complex *, int, + int, int); +typedef void (fftw_generic_codelet) + (fftw_complex *, const fftw_complex *, int, + int, int, int); +typedef void (fftw_real2hc_codelet) + (const fftw_real *, fftw_real *, fftw_real *, + int, int, int); +typedef void (fftw_hc2real_codelet) + (const fftw_real *, const fftw_real *, + fftw_real *, int, int, int); +typedef void (fftw_hc2hc_codelet) + (fftw_real *, const fftw_complex *, + int, int, int); +typedef void (fftw_rgeneric_codelet) + (fftw_real *, const fftw_complex *, int, + int, int, int); + +/********************************************* + * Configurations + *********************************************/ +/* + * A configuration is a database of all known codelets + */ + +enum fftw_node_type { + FFTW_NOTW, FFTW_TWIDDLE, FFTW_GENERIC, FFTW_RADER, + FFTW_REAL2HC, FFTW_HC2REAL, FFTW_HC2HC, FFTW_RGENERIC +}; + +/* description of a codelet */ +typedef struct { + const char *name; /* name of the codelet */ + void (*codelet) (); /* pointer to the codelet itself */ + int size; /* size of the codelet */ + fftw_direction dir; /* direction */ + enum fftw_node_type type; /* TWIDDLE or NO_TWIDDLE */ + int signature; /* unique id */ + int ntwiddle; /* number of twiddle factors */ + const int *twiddle_order; /* + * array that determines the order + * in which the codelet expects + * the twiddle factors + */ +} fftw_codelet_desc; + +/* On Win32, you need to do funny things to access global variables + in shared libraries. Thanks to Andrew Sterian for this hack. */ +#if defined(__WIN32__) || defined(WIN32) || defined(_WINDOWS) +# if defined(BUILD_FFTW_DLL) +# define DL_IMPORT(type) __declspec(dllexport) type +# elif defined(USE_FFTW_DLL) +# define DL_IMPORT(type) __declspec(dllimport) type +# else +# define DL_IMPORT(type) type +# endif +#else +# define DL_IMPORT(type) type +#endif + +extern DL_IMPORT(const char *) fftw_version; + +/***************************** + * Plans + *****************************/ +/* + * A plan is a sequence of reductions to compute a FFT of + * a given size. At each step, the FFT algorithm can: + * + * 1) apply a notw codelet, or + * 2) recurse and apply a twiddle codelet, or + * 3) apply the generic codelet. + */ + +/* structure that contains twiddle factors */ +typedef struct fftw_twiddle_struct { + int n; + const fftw_codelet_desc *cdesc; + fftw_complex *twarray; + struct fftw_twiddle_struct *next; + int refcnt; +} fftw_twiddle; + +typedef struct fftw_rader_data_struct { + struct fftw_plan_struct *plan; + fftw_complex *omega; + int g, ginv; + int p, flags, refcount; + struct fftw_rader_data_struct *next; + fftw_codelet_desc *cdesc; +} fftw_rader_data; + +typedef void (fftw_rader_codelet) + (fftw_complex *, const fftw_complex *, int, + int, int, fftw_rader_data *); + +/* structure that holds all the data needed for a given step */ +typedef struct fftw_plan_node_struct { + enum fftw_node_type type; + + union { + /* nodes of type FFTW_NOTW */ + struct { + int size; + fftw_notw_codelet *codelet; + const fftw_codelet_desc *codelet_desc; + } notw; + + /* nodes of type FFTW_TWIDDLE */ + struct { + int size; + fftw_twiddle_codelet *codelet; + fftw_twiddle *tw; + struct fftw_plan_node_struct *recurse; + const fftw_codelet_desc *codelet_desc; + } twiddle; + + /* nodes of type FFTW_GENERIC */ + struct { + int size; + fftw_generic_codelet *codelet; + fftw_twiddle *tw; + struct fftw_plan_node_struct *recurse; + } generic; + + /* nodes of type FFTW_RADER */ + struct { + int size; + fftw_rader_codelet *codelet; + fftw_rader_data *rader_data; + fftw_twiddle *tw; + struct fftw_plan_node_struct *recurse; + } rader; + + /* nodes of type FFTW_REAL2HC */ + struct { + int size; + fftw_real2hc_codelet *codelet; + const fftw_codelet_desc *codelet_desc; + } real2hc; + + /* nodes of type FFTW_HC2REAL */ + struct { + int size; + fftw_hc2real_codelet *codelet; + const fftw_codelet_desc *codelet_desc; + } hc2real; + + /* nodes of type FFTW_HC2HC */ + struct { + int size; + fftw_direction dir; + fftw_hc2hc_codelet *codelet; + fftw_twiddle *tw; + struct fftw_plan_node_struct *recurse; + const fftw_codelet_desc *codelet_desc; + } hc2hc; + + /* nodes of type FFTW_RGENERIC */ + struct { + int size; + fftw_direction dir; + fftw_rgeneric_codelet *codelet; + fftw_twiddle *tw; + struct fftw_plan_node_struct *recurse; + } rgeneric; + } nodeu; + + int refcnt; +} fftw_plan_node; + +struct fftw_plan_struct { + int n; + int refcnt; + fftw_direction dir; + int flags; + int wisdom_signature; + enum fftw_node_type wisdom_type; + struct fftw_plan_struct *next; + fftw_plan_node *root; + double cost; +}; + +/* a plan is just an array of instructions */ +typedef struct fftw_plan_struct *fftw_plan; + +/* flags for the planner */ +#define FFTW_ESTIMATE (0) +#define FFTW_MEASURE (1) + +#define FFTW_OUT_OF_PLACE (0) +#define FFTW_IN_PLACE (8) +#define FFTW_USE_WISDOM (16) + +#define FFTW_THREADSAFE (128) /* guarantee plan is read-only so that the + same plan can be used in parallel by + multiple threads */ + +#define FFTWND_FORCE_BUFFERED (256) /* internal, undocumented flag */ + +extern fftw_plan fftw_create_plan_specific(int n, fftw_direction dir, + int flags, + fftw_complex *in, int istride, + fftw_complex *out, int ostride); +#define FFTW_HAS_PLAN_SPECIFIC +extern fftw_plan fftw_create_plan(int n, fftw_direction dir, int flags); +extern void fftw_print_plan(fftw_plan plan); +extern void fftw_destroy_plan(fftw_plan plan); +extern void fftw(fftw_plan plan, int howmany, fftw_complex *in, int istride, + int idist, fftw_complex *out, int ostride, int odist); +extern void fftw_one(fftw_plan plan, fftw_complex *in, fftw_complex *out); +extern void fftw_die(const char *s); +extern void *fftw_malloc(size_t n); +extern void fftw_free(void *p); +extern void fftw_check_memory_leaks(void); +extern void fftw_print_max_memory_usage(void); + +typedef void *(*fftw_malloc_type_function) (size_t n); +typedef void (*fftw_free_type_function) (void *p); +typedef void (*fftw_die_type_function) (const char *errString); +extern DL_IMPORT(fftw_malloc_type_function) fftw_malloc_hook; +extern DL_IMPORT(fftw_free_type_function) fftw_free_hook; +extern DL_IMPORT(fftw_die_type_function) fftw_die_hook; + +extern size_t fftw_sizeof_fftw_real(void); + +/* Wisdom: */ +/* + * define this symbol so that users know we are using a version of FFTW + * with wisdom + */ +#define FFTW_HAS_WISDOM +extern void fftw_forget_wisdom(void); +extern void fftw_export_wisdom(void (*emitter) (char c, void *), void *data); +extern fftw_status fftw_import_wisdom(int (*g) (void *), void *data); +extern void fftw_export_wisdom_to_file(FILE *output_file); +extern fftw_status fftw_import_wisdom_from_file(FILE *input_file); +extern char *fftw_export_wisdom_to_string(void); +extern fftw_status fftw_import_wisdom_from_string(const char *input_string); + +/* + * define symbol so we know this function is available (it is not in + * older FFTWs) + */ +#define FFTW_HAS_FPRINT_PLAN +extern void fftw_fprint_plan(FILE *f, fftw_plan plan); + +/***************************** + * N-dimensional code + *****************************/ +typedef struct { + int is_in_place; /* 1 if for in-place FFTs, 0 otherwise */ + + int rank; /* + * the rank (number of dimensions) of the + * array to be FFTed + */ + int *n; /* + * the dimensions of the array to the + * FFTed + */ + fftw_direction dir; + + int *n_before; /* + * n_before[i] = product of n[j] for j < i + */ + int *n_after; /* n_after[i] = product of n[j] for j > i */ + + fftw_plan *plans; /* 1d fftw plans for each dimension */ + + int nbuffers, nwork; + fftw_complex *work; /* + * work array big enough to hold + * nbuffers+1 of the largest dimension + * (has nwork elements) + */ +} fftwnd_data; + +typedef fftwnd_data *fftwnd_plan; + +/* Initializing the FFTWND plan: */ +extern fftwnd_plan fftw2d_create_plan(int nx, int ny, fftw_direction dir, + int flags); +extern fftwnd_plan fftw3d_create_plan(int nx, int ny, int nz, + fftw_direction dir, int flags); +extern fftwnd_plan fftwnd_create_plan(int rank, const int *n, + fftw_direction dir, + int flags); + +extern fftwnd_plan fftw2d_create_plan_specific(int nx, int ny, + fftw_direction dir, + int flags, + fftw_complex *in, int istride, + fftw_complex *out, int ostride); +extern fftwnd_plan fftw3d_create_plan_specific(int nx, int ny, int nz, + fftw_direction dir, int flags, + fftw_complex *in, int istride, + fftw_complex *out, int ostride); +extern fftwnd_plan fftwnd_create_plan_specific(int rank, const int *n, + fftw_direction dir, + int flags, + fftw_complex *in, int istride, + fftw_complex *out, int ostride); + +/* Freeing the FFTWND plan: */ +extern void fftwnd_destroy_plan(fftwnd_plan plan); + +/* Printing the plan: */ +extern void fftwnd_fprint_plan(FILE *f, fftwnd_plan p); +extern void fftwnd_print_plan(fftwnd_plan p); +#define FFTWND_HAS_PRINT_PLAN + +/* Computing the N-Dimensional FFT */ +extern void fftwnd(fftwnd_plan plan, int howmany, + fftw_complex *in, int istride, int idist, + fftw_complex *out, int ostride, int odist); +extern void fftwnd_one(fftwnd_plan p, fftw_complex *in, fftw_complex *out); + +#ifdef __cplusplus +} /* extern "C" */ + +#endif /* __cplusplus */ +#endif /* FFTW_H */ diff --git a/nyqsrc/fresample.h b/nyqsrc/fresample.h new file mode 100644 index 0000000..be1a199 --- /dev/null +++ b/nyqsrc/fresample.h @@ -0,0 +1,75 @@ +/* + * FILE: fresample.h + * + * The configuration constants below govern + * the number of bits in the input sample and filter coefficients, the + * number of bits to the right of the binary-point for fixed-point math, etc. + * + */ + +/* #include "stdefs.h" */ + +typedef double SAMPLE_TYPE; +#define SCALE_FACTOR_TO_SHORT 32767 + +/* Conversion constants */ +#define Nhc 8 +/* #define Na 7 */ +/* #define Np (Nhc+Na)*/ +#define Npc (1<susp.current * susp->out_time_increment; + + register sample_block_values_type out_ptr; + + register sample_block_values_type s_ptr_reg; + falloc_sample_block(out, "inverse_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + /* make sure we are primed with first value */ + /* This is a lot of work just to prefetch susp->s_prev! */ + if (!susp->started) { + susp->started = true; + /* see comments below about susp_check_term_log_samples() */ + if (susp->s_cnt == 0) { + susp_get_samples(s, s_ptr, s_cnt); + if (susp->s_ptr == zero_block->samples) { + susp->terminate_cnt = susp->susp.current; + } + } + susp->s_prev = susp_fetch_sample(s, s_ptr, s_cnt); + } + + while (out_cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't run past the s input sample block: */ + /* most fetch routines call susp_check_term_log_samples() here + * but we can't becasue susp_check_term_log_samples() assumes + * that output time progresses at the same rate as input time. + * Here, some time warping is going on, so this doesn't work. + * Instead, check for termination of s and fix terminate_cnt to + * be the current output count rather than the current input time. + */ + if (susp->s_cnt == 0) { + susp_get_samples(s, s_ptr, s_cnt); + if (susp->s_ptr == zero_block->samples) { + susp->terminate_cnt = susp->susp.current + out_cnt; + /* we can't simply terminate here because we might have + * some output samples computed already, in which case we + * want to return them now and terminate the NEXT time we're + * called. + */ + } + } + togo = susp->s_cnt; + + /* if we ran past terminate time, fix up output */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + out_cnt) { + /* pretend like we computed the correct number of samples */ + togo = 0; + out_cnt = susp->terminate_cnt - susp->susp.current; + /* exit the loop to complete the termination */ + break; + } + n = togo; + s_ptr_reg = susp->s_ptr; + if (n) do { /* the inner sample computation loop */ + /* scan s_ptr_reg to time t, output and loop */ + register double next_value = *s_ptr_reg++; + while (out_time < next_value) { + *out_ptr++ = (float) (susp->s_time + + (out_time - susp->s_prev) / + (susp->s->sr * (next_value - susp->s_prev))); + out_time += susp->out_time_increment; + if (++out_cnt >= max_sample_block_len) goto output_full; + } + susp->s_prev = next_value; + susp->s_time += susp->s_time_increment; + } while (--n); /* inner loop */ + output_full: + /* using s_ptr_reg is a bad idea on RS/6000: */ + susp->s_ptr += (togo - n); + susp_took(s_cnt, (togo - n)); + cnt += (togo - n); + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && out_cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = out_cnt; + susp->susp.current += out_cnt; + } +} /* inverse_fetch */ + + +void inverse_toss_fetch(susp, snd_list) + register inverse_susp_type susp; + snd_list_type snd_list; +{ + long final_count = MIN(susp->susp.current + max_sample_block_len, + susp->susp.toss_cnt); + time_type final_time = susp->susp.t0 + final_count / susp->susp.sr; + long n; + + /* fetch samples from s up to final_time for this block of zeros */ + while (((long) ((final_time - susp->s->t0) * susp->s->sr + 0.5)) >= + susp->s->current) + susp_get_samples(s, s_ptr, s_cnt); + /* convert to normal processing when we hit final_count */ + /* we want each signal positioned at final_time */ + if (final_count == susp->susp.toss_cnt) { + n = ROUND((final_time - susp->s->t0) * susp->s->sr - + (susp->s->current - susp->s_cnt)); + susp->s_ptr += n; + susp_took(s_cnt, n); + susp->susp.fetch = susp->susp.keep_fetch; + } + snd_list->block_len = (short) (final_count - susp->susp.current); + susp->susp.current = final_count; + snd_list->u.next = snd_list_create((snd_susp_type) susp); + snd_list->block = internal_zero_block; +} + + +void inverse_mark(inverse_susp_type susp) +{ + sound_xlmark(susp->s); +} + + +void inverse_free(inverse_susp_type susp) +{ + sound_unref(susp->s); + ffree_generic(susp, sizeof(inverse_susp_node), "inverse_free"); +} + + +void inverse_print_tree(inverse_susp_type susp, int n) +{ + indent(n); + stdputstr("s:"); + sound_print_tree_1(susp->s, n); +} + + +sound_type snd_make_inverse(sound_type s, time_type t0, rate_type sr) +{ + register inverse_susp_type susp; + + falloc_generic(susp, inverse_susp_node, "snd_make_inverse"); + susp->susp.fetch = inverse_fetch; + susp->terminate_cnt = UNKNOWN; + + /* initialize susp state */ + susp->susp.free = inverse_free; + susp->susp.sr = sr; + susp->susp.t0 = t0; + susp->susp.mark = inverse_mark; + susp->susp.print_tree = inverse_print_tree; + susp->susp.name = "inverse"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = UNKNOWN; /* log stop time = term time */ + susp->susp.current = 0; + susp->s = s; + susp->s_cnt = 0; + susp->s_prev = 0; + susp->s_time = 0; + susp->s_time_increment = 1 / s->sr; + susp->out_time_increment = 1 / (sr * s->scale); + susp->started = false; + return sound_create((snd_susp_type)susp, t0, sr, 1.0 /* scale */); +} + + +sound_type snd_inverse(sound_type s, time_type t0, rate_type sr) +{ + sound_type s_copy = sound_copy(s); + return snd_make_inverse(s_copy, t0, sr); +} diff --git a/nyqsrc/inverse.h b/nyqsrc/inverse.h new file mode 100644 index 0000000..4ecf563 --- /dev/null +++ b/nyqsrc/inverse.h @@ -0,0 +1,3 @@ +sound_type snd_make_inverse(sound_type s, time_type t0, rate_type sr); +sound_type snd_inverse(sound_type s, time_type t0, rate_type sr); + /* LISP: (snd-inverse SOUND ANYNUM ANYNUM) */ diff --git a/nyqsrc/local.c b/nyqsrc/local.c new file mode 100644 index 0000000..1cd3eed --- /dev/null +++ b/nyqsrc/local.c @@ -0,0 +1,55 @@ +/* local.c -- call initialization code for all extensions */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +#include "xlisp.h" +#include "sound.h" +#include "samples.h" +#ifdef CMTSTUFF +#include "seqext.h" +#endif +#include "falloc.h" +#include "sine.h" +#include "stkinit.h" + +LVAL RSLT_sym; + +void localinit(void) +{ + falloc_init(); +/* probe_init(true);*/ + sound_init(); +#ifdef CMTSTUFF + seqext_init(); +#endif + sine_init(); + stk_init(); +} + + +void localsymbols(void) +{ + RSLT_sym = xlenter("*RSLT*"); + sound_symbols(); + samples_symbols(); +#ifdef CMTSTUFF + seqext_symbols(); +#endif +} + +extern int sample_block_total; +extern int sample_block_used; + +void print_local_gc_info(void) +{ + char buf[50]; + /* print sample blocks */ + sprintf(buf, "; samples %dKB, %dKB free", + (sample_block_total * max_sample_block_len) / 1024, + ((sample_block_total - sample_block_used) * + max_sample_block_len) / 1024); + stdputstr(buf); +} diff --git a/nyqsrc/localdefs.h b/nyqsrc/localdefs.h new file mode 100644 index 0000000..b227c2f --- /dev/null +++ b/nyqsrc/localdefs.h @@ -0,0 +1,3 @@ +/* include actual local file headers: */ +#include "sndfnintdefs.h" +#include "seqfnintdefs.h" diff --git a/nyqsrc/localptrs.h b/nyqsrc/localptrs.h new file mode 100644 index 0000000..8789cfa --- /dev/null +++ b/nyqsrc/localptrs.h @@ -0,0 +1,9 @@ +/* localptrs.h -- extend XLISP with these functions + * + * CHANGE LOG + * 28-Apr-03 rbd Removed "include switches.h" -- already included + */ + +/* extension to xlisp */ +#include "sndfnintptrs.h" +#include "seqfnintptrs.h" diff --git a/nyqsrc/lpanal.c b/nyqsrc/lpanal.c new file mode 100644 index 0000000..d6baf98 --- /dev/null +++ b/nyqsrc/lpanal.c @@ -0,0 +1,177 @@ +/* lpc.c -- implement LPC analysis */ + +#include + +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" + + +void abs_max(double *x, long desde, long hasta, double *x_maxptr, long *indptr) +{ + /* use: + abs_max(s,0,10,&mimax,&miind); + */ + + double x_max = x[desde]; + long ind = desde; + long i; + for(i = desde+1; i x_max) + { + x_max = fabs(x[i]); + ind = i; + } + *x_maxptr = x_max; + *indptr = ind; + +} + +void xcorr(double *s, double *rxx, long N) +{ + /* use: + xcorr(s,rxx,N); + */ + long i,j; + for(i=0; i < N; i++) + { + rxx[i] = 0.0; + for(j=0; j < N-i; j++) + rxx[i] += s[j]*s[j+i]; + } +} + + + + +// SOUND PARAMETERS +// w Lisp vector containinig signal values +// P number of poles +// N length of sound + +// AUTOCORRELEATION PARAMETERS +// rxx array containing autocorrelation coefs +// max_rxx temporal maximun value of rxx +// i_max index of max_rxx + +// LPC PARAMETERS +// alpha array of filter coefs +// k reflection coef +// E residual energy +// rms1 energy of input signal (not RMS) +// rms2 residual energy = E +// unv voiced/unvoiced parameter = ERR = rms2/rms1 + +// PITCH DETECTION ALGORITHM: Implemented separately + + + +LVAL snd_lpanal(LVAL w, long P) +{ + + double *s, *rxx; + long N; + double *alpha; + // double *k, *E; THIS ONLY FOR VECTORIZED k AND E + double k, E; + double rms1; // rms2=E; + double unv; + double suma, alphatemp; // help variables + + + long i,j; + LVAL result; + + xlsave1(result); + + + + //// end vars ///////////// + + + + //// allocate memory /////// + N = getsize(w); + s = calloc(sizeof(double),N); //signal + rxx = calloc(sizeof(double),N); //autocorrelation + alpha = calloc(sizeof(double), P); // filter coefs + //k = calloc(sizeof(double), P); // reflection coefs + //E = calloc(sizeof(double), P); // residual energy + + + ////// copy Lisp array sound data to array of double /////// + for(i=0; i> 1); j++) + { + //alphatemp = alpha[j] - k[i] * alpha[i-j-1]; + //alpha[i-j-1] -= k[i] * alpha[j]; + //alpha[j] = alphatemp; + alphatemp = alpha[j] - k * alpha[i-j-1]; + alpha[i-j-1] -= k * alpha[j]; + alpha[j] = alphatemp; + + } + //E[i] = E[i-1] * (1 - pow(k[i],2)); + E *= (1 - pow(k,2)); + + } + + // input signal energy = rxx[0]; + rms1 = rxx[0]; + + // voiced/unvoiced + unv= sqrt(E/rms1); + + ///// HERE: CHECK STABILITY AND MODIFY COEFS ///////////// + ///// not implemented + + + + // prepare output result + result = newvector(P); + for (i = 0; i < P; i++) setelement(result, i, cvflonum(alpha[P-i-1])); // alpoles format + + xlpop(); + + // free memory + free(s); free(rxx); free(alpha); + + return (cons (cvflonum(rms1), // input signal energy + cons(cvflonum(E), // residual energy + cons(cvflonum(unv), // ERR, voiced/unvoiced + cons(result, NULL))))); // coefs + +} diff --git a/nyqsrc/lpanal.h b/nyqsrc/lpanal.h new file mode 100644 index 0000000..87af9c0 --- /dev/null +++ b/nyqsrc/lpanal.h @@ -0,0 +1,4 @@ +/* lpanal.h -- LPC analysis */ + +LVAL snd_lpanal(LVAL v, long P); + /* LISP: (SND-LPANAL ANY FIXNUM) */ diff --git a/nyqsrc/multiread.c b/nyqsrc/multiread.c new file mode 100644 index 0000000..9c34be3 --- /dev/null +++ b/nyqsrc/multiread.c @@ -0,0 +1,298 @@ +/* multiread.c -- read multichannel sound file */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +#include "stdio.h" +#ifdef UNIX +#include "sys/file.h" +#endif +#ifndef mips +#include "stdlib.h" +#endif +#include "sndfmt.h" +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "sndfile.h" +#include "sndread.h" +#include "multiread.h" + +/* allocate input buffer space for this many bytes/frame, + * e.g. 8 allows 2 channels + * If frames are bigger, then multiple reads will be issued. + */ +#define max_bytes_per_frame (sizeof(float) * 2) +#define input_buffer_max (max_sample_block_len * max_bytes_per_frame) +#define input_buffer_samps (max_sample_block_len * 2) + + +/* multiread_fetch - read samples into multiple channels. */ +/* + * The susp is shared by all channels. The susp has backpointers + * to the tail-most snd_list node of each channels, and it is by + * extending the list at these nodes that sounds are read in. + * To avoid a circularity, the reference counts on snd_list nodes + * do not include the backpointers from this susp. When a snd_list + * node refcount goes to zero, the multiread susp's free routine + * is called. This must scan the backpointers to find the node that + * has a zero refcount (the free routine is called before the node + * is deallocated, so this is safe). The backpointer is then set + * to NULL. When all backpointers are NULL, the susp itself is + * deallocated, because it can only be referenced through the + * snd_list nodes to which there are backpointers. + */ +void multiread_fetch(susp, snd_list) + register read_susp_type susp; + snd_list_type snd_list; +{ + int i, j; + int frames_read = 0; /* total frames read in this call to fetch */ + int n; + sample_block_type out; + // char input_buffer[input_buffer_max]; + float input_buffer[input_buffer_samps]; + int file_frame_size; + + /* when we are called, the caller (SND_get_first) will insert a new + * snd_list node. We need to do this here for all other channels. + */ + for (j = 0; j < susp->sf_info.channels; j++) { + +/* nyquist_printf("multiread_fetch: chan[%d] = ", j); + print_snd_list_type(susp->chan[j]); + stdputstr("\n"); + */ + if (!susp->chan[j]) { /* ignore non-existent channels */ +/* nyquist_printf("multiread_fetch: ignore channel %d\n", j);*/ + continue; + } + falloc_sample_block(out, "multiread_fetch"); +/* nyquist_printf("multiread: allocated block %x\n", out); */ + /* Since susp->chan[i] exists, we want to append a block of samples. + * The block, out, has been allocated. Before we insert the block, + * we must figure out whether to insert a new snd_list_type node for + * the block. Recall that before SND_get_next is called, the last + * snd_list_type in the list will have a null block pointer, and the + * snd_list_type's susp field points to the suspension (in this case, + * susp). When SND_get_next (in sound.c) is called, it appends a new + * snd_list_type and points the previous one to internal_zero_block + * before calling this fetch routine. On the other hand, since + * SND_get_next is only going to be called on one of the channels, the + * other channels will not have had a snd_list_type appended. + * SND_get_next does not tell us directly which channel it wants (it + * doesn't know), but we can test by looking for a non-null block in the + * snd_list_type pointed to by our back-pointers in susp->chan[]. If + * the block is null, the channel was untouched by SND_get_next, and + * we should append a snd_list_type. If it is non-null, then it + * points to internal_zero_block (the block inserted by SND_get_next) + * and a new snd_list_type has already been appended. + */ + /* Before proceeding, it may be that garbage collection ran when we + * allocated out, so check again to see if susp->chan[j] is Null: + */ + if (!susp->chan[j]) { + ffree_sample_block(out, "multiread_fetch"); + continue; + } + if (!susp->chan[j]->block) { + snd_list_type snd_list = snd_list_create((snd_susp_type) susp); + /* Now we have a snd_list to append to the channel, but a very + * interesting thing can happen here. snd_list_create, which + * we just called, MAY have invoked the garbage collector, and + * the GC MAY have freed all references to this channel, in which + * case multread_free(susp) will have been called, and susp->chan[j] + * will now be NULL! + */ + if (!susp->chan[j]) { + nyquist_printf("susp %p Channel %d disappeared!\n", susp, j); + ffree_snd_list(snd_list, "multiread_fetch"); + } else { + susp->chan[j]->u.next = snd_list; + } + } + /* see the note above: we don't know if susp->chan still exists */ + /* Note: We DO know that susp still exists because even if we lost + * some channels in a GC, someone is still calling SND_get_next on + * some channel. I suppose that there might be some very pathological + * code that could free a global reference to a sound that is in the + * midst of being computed, perhaps by doing something bizarre in the + * closure that snd_seq activates at the logical stop time of its first + * sound, but I haven't thought that one through. + */ + if (susp->chan[j]) { + susp->chan[j]->block = out; + /* check some assertions */ + if (susp->chan[j]->u.next->u.susp != (snd_susp_type) susp) { + nyquist_printf("didn't find susp at end of list for chan %d\n", j); + } + } else { /* we allocated out, but don't need it anymore due to GC */ + ffree_sample_block(out, "multiread_fetch"); + } + } + + file_frame_size = susp->sf_info.channels; + + /* now fill sample blocks with frames from the file + until eof or end of blocks */ + while (true) { + + /* compute how many frames to read to fill sample blocks */ + long frame_count = max_sample_block_len - frames_read; + long actual; /* how many frames actually read */ + + /* make sure frames will fit in buffer */ + if (frame_count * file_frame_size > input_buffer_samps) { + frame_count = input_buffer_samps / file_frame_size; + } + + actual = sf_readf_float(susp->sndfile, input_buffer, frame_count); + n = actual; + + /* don't read too many */ + if (n > (susp->cnt - susp->susp.current)) { + n = susp->cnt - susp->susp.current; + } + + /* process one channel at a time, multiple passes through input */ + for (j = 0; j < susp->sf_info.channels; j++) { + register sample_block_values_type out_ptr; + /* offset by channel number: */ + float *float_ptr = input_buffer + j; + + /* ignore nonexistent channels */ + if (!susp->chan[j]) continue; + + /* find pointer to sample buffer */ + out_ptr = susp->chan[j]->block->samples + frames_read; + + /* copy samples */ + for (i = 0; i < n; i++) { + *out_ptr++ = *float_ptr; + float_ptr += susp->sf_info.channels; + } + susp->chan[j]->block_len = frames_read + n; + } + + /* jlh BECAUSE, at this point, all the code cares about is + that n frames have been read and the samples put into their + appropriate snd_node buffers. */ + + frames_read += n; + susp->susp.current += n; + + if (frames_read == 0) { + /* NOTE: this code should probably be removed -- how could we + ever get here? Since file formats know the sample count, we'll + always read frames. When we hit the end-of-file, the else + clause below will run and terminate the sound, so we'll never + try and read samples that are not there. The only exception is + an empty sound file with no samples, in which case we could omit + this if test and execute the else part below. + + This code *might* be good for formats that do not encode a + sample count and where reading the end of file is the only way + to detect the end of the data. + + Since it seeems to work, I'm going to leave this in place. + One tricky point of the algorithm: when we get here, we set up + susp->chan[j] to point to the right place and then call + snd_list_terminate(). This deletes the snd_list that chan[j] + is pointing to, but not before calling multiread_free(), which + upon detecting that the sound is being freed, sets chan[j] to + NULL. This works sequentially on each channel and than last + time, this susp is freed because no channels are active. + */ + /* we didn't read anything, but can't return length zero, so + * convert snd_list's to pointer to zero block. This loop + * will free the susp via snd_list_unref(). + */ + for (j = 0; j < susp->sf_info.channels; j++) { + if (susp->chan[j]) { + snd_list_type the_snd_list = susp->chan[j]; + /* this is done so that multiread_free works right: */ + susp->chan[j] = susp->chan[j]->u.next; + /* nyquist_printf("end of file, terminating channel %d\n", j); */ + /* this fixes up the tail of channel j */ + snd_list_terminate(the_snd_list); + } + } + return; + } else if (susp->cnt == susp->susp.current || actual < frame_count) { + /* we've read the requested number of frames or we + * reached end of file + * last iteration will close file and free susp: + */ + for (j = 0; j < susp->sf_info.channels; j++) { + snd_list_type the_snd_list = susp->chan[j]; + /* nyquist_printf("reached susp->cnt, terminating chan %d\n", j); */ + if (the_snd_list) { + /* assert: */ + if (the_snd_list->u.next->u.susp != (snd_susp_type) susp) { + stdputstr("assertion violation"); + } + /* this is done so that multiread_free works right: */ + susp->chan[j] = the_snd_list->u.next; + snd_list_unref(the_snd_list->u.next); + /* terminate by pointing to zero block */ + the_snd_list->u.next = zero_snd_list; + } + } + return; + } else if (frames_read >= max_sample_block_len) { + /* move pointer to next list node */ + for (j = 0; j < susp->sf_info.channels; j++) { + if (susp->chan[j]) susp->chan[j] = susp->chan[j]->u.next; + } + return; + } + } +} /* multiread__fetch */ + + +void multiread_free(read_susp_type susp) +{ + int j; + boolean active = false; +/* stdputstr("multiread_free: "); */ + for (j = 0; j < susp->sf_info.channels; j++) { + if (susp->chan[j]) { + if (susp->chan[j]->refcnt) active = true; + else { + susp->chan[j] = NULL; + /* nyquist_printf("deactivating channel %d\n", j); */ + } + } + } + if (!active) { + /* stdputstr("all channels freed, freeing susp now\n"); */ + read_free(susp); + } +} + + +LVAL multiread_create(susp) + read_susp_type susp; +{ + LVAL result; + int j; + + xlsave1(result); + + result = newvector(susp->sf_info.channels); /* create array for sounds */ + falloc_generic_n(susp->chan, snd_list_type, susp->sf_info.channels, + "multiread_create"); + /* create sounds to return */ + for (j = 0; j < susp->sf_info.channels; j++) { + sound_type snd = sound_create((snd_susp_type)susp, + susp->susp.t0, susp->susp.sr, 1.0); + LVAL snd_lval = cvsound(snd); +/* nyquist_printf("multiread_create: sound %d is %x, LVAL %x\n", j, snd, snd_lval); */ + setelement(result, j, snd_lval); + susp->chan[j] = snd->list; + } + xlpop(); + return result; +} diff --git a/nyqsrc/multiread.h b/nyqsrc/multiread.h new file mode 100644 index 0000000..7bd1b17 --- /dev/null +++ b/nyqsrc/multiread.h @@ -0,0 +1,3 @@ +LVAL multiread_create(read_susp_type susp); +void multiread_fetch(read_susp_type susp, snd_list_type snd_list); +void multiread_free(read_susp_type susp); diff --git a/nyqsrc/multiseq.c b/nyqsrc/multiseq.c new file mode 100644 index 0000000..367b5f6 --- /dev/null +++ b/nyqsrc/multiseq.c @@ -0,0 +1,673 @@ +/* multiseq.c -- return a multichannel signal until its logical stop, then + evaluate a closure to get another signal and convert to adds + of two multichannel signals */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "multiseq.h" +#include "add.h" +#include "scale.h" +#include "extern.h" +#include "cext.h" + +/* #define MULTISEQ_GC_DEBUG */ +#ifdef MULTISEQ_GC_DEBUG +extern snd_list_type snd_list_to_watch; +#endif + +/* #define GC_DEBUG */ +#ifdef GC_DEBUG +extern sound_type sound_to_watch; +#endif + + +#define D if(0) + +/* Design: + +This operator implements sequences of multichannel signals. +A single data structure manages an array of susps that +initially are used to fetch blocks from the first multichannel +signal. When the LAST logical stop is reached, a closure +is evaluated to yield a new multichannel signal. The component +sounds of this are stored into the susps which are then +converted into add suspensions. The other managing structures +are then freed. + +The main constraint here is that the conversion to add susps +must take place at the same time across all channels, so before +the conversion, a fetch from the susp can only be made if it is +known that the samples returned happen BEFORE the conversion will +take place. Since the conversion takes place at the maximum of +the logical stop times of all channels, we have to advance all +channels synchronously. We keep track of a greatest lower bound, +refered to as the horizon, on the maximum logical stop time. It +is safe to fetch blocks up to the horizon, but not beyond. + +This synchronous fetching is done by a single routine and an +auxilliarly structure that manages the whole multichannel array +of susps. The basic idea is that a fetch from a +suspension gets forwarded to the managing structure, which +uses its array of susps to fetch from ALL suspensions up to +the requested time or until the logical stop, whichever comes +first. These "synchronous" fetches are not made by calling the +fetch routines on the suspensions to avoid infinite recursion. + +At any time, there will be some set of channels whose logical +stop time is unknown. The "s1" fields (s1, s1_ptr, s1_bptr) of +these suspensions are used to look ahead by geting a block from +s1. If no logical stop is indicated, then we can append the block +to the snd_list and update the horizon, allowing fetches from other +susps. In other words, the s1_bptr of each susp provides a one +buffer lookahead by which we can obtain advance knowledge of the +maximum logical stop time. + +The algorithm is as follows: + +1. When fetch is called on a suspension, compute when any +prefetched samples will end (if there are none, then fetch +a block from s1 and compute the time at which the block ends). +This becomes the target time for other fetches. + +2. Call multiseq_advance(), passing the target time and the +manager structure (which has pointers to all other channels). +(Note: every susp has a pointer to the manager). +The function of multiseq_advance() is to push the horizon for +the logical stop forward. This is done by +iterating over the array of susps until the target is reached. +Actually, the array contains pointers to the snd_list_node that +points to each susp and where the next block will be linked. +The goal of this loop is to satisfy the original fetch, which +means we have to push low_water to greater than or equal to the +target. (Low water is the minimum time of the next sample to +be returned by any multiseq susp.) This goal will be met unless +we reach the last logical stop time, in which case we evaluate +the closure for the next multichannel sound, convert +everything to add's and let the additions take care of returning +blocks. + +3. The Iteration Loop: +low_water is the lowest sample count of the next sample +horizon is the greatest lower bound on the maximum logical stop time +Iterate over susps until low_water >= target +(Note: whenever data is fetched for a sound whose logical stop time +is unknown, update the horizon. If a logical stop time becomes known, +then test if the final maximum logical stop time is known (by keeping +a count of how many are still unknown), and if the count goes to zero, +evaluate the continuation and convert to multiple adds.) +(Another Note: we may reach the logical stop time and convert to +multiple adds before the loop terminates, in which case we return +without finishing the loop. Take care that the caller does the right +thing to produce a sample block in this case.) + +3a. If a block hasn't been prefetched, do it. + +3b. While the susp has prefetched a block that ends at or before horizon, +put the block on the snd_list and prefetch another block. + +3c. If the susp hasn't a known logical stop time, set new_horizon to +the end time of the last sample prefetched in 3b. + +3d. If new_horizon == horizon, signal an error, no progress was made. + +3d. Set horizon to new_horizon and repeat the loop. + +NOTE ON A BUG FIX (1 Jul 95): old code assumed that when a logical stop +was detected it was at the beginning of the next block, but if logical +stop is explicit, then it may be way in the future. We could convert +to adds at this point, but that would force early evaluation of the +closure, which we'd like to delay (be lazy when possible). Therefore, +we want to ignore knowledge of a logical stop time until the logical +stop time falls within the currently known block of samples. By "currently +known", I mean somewhere in the block referenced by ->s1_ptr and ->s1_cnt. + +*/ + +/* extern LVAL s_stdout; */ + +void multiseq_convert(multiseq_type ms); +void multiseq_free(add_susp_type susp); +sample_block_type multiseq_get_next(sound_type snd, long * cnt); +void multiseq_print_tree(add_susp_type susp, int n); + + +#define susp_cnt_time(ssp, ms, cnt) (ssp->susp.t0 - ms->t0 + (cnt)/ssp->s1->sr) +#define susp_time(ssp, ms) susp_cnt_time(ssp, ms, \ + (ssp->susp.current + ssp->s1_cnt)) +#define susp_low_water(ssp, ms) susp_cnt_time(ssp, ms, ssp->susp.current) +#define susp_log_stop_time(ssp, ms) susp_cnt_time(ssp, ms, ssp->susp.log_stop_cnt) + + +/* multiseq_advance fetches from each channel to advance to target time */ +/* + * If a channel terminates early, we must be careful: continuing to + * fetch will return pointers to the zero_block, but this will + * indicate termination to whoever is fetching from multiseq. We + * must check the pointers and substitute internal_zero_block to + * avoid premature termination. + */ +void multiseq_advance(multiseq_type ms, time_type target) +{ + int i; + time_type new_horizon; + time_type new_low_water; + +D nyquist_printf("multiseq_advance: %p->low_water %g, target %g\n", + ms, ms->low_water, target); + while (ms->low_water < target - 0.000001) { + new_horizon = 0.0; +D nyquist_printf("multiseq_advance loop: target %g low_water %g horizon %g\n", + target, ms->low_water, ms->horizon); + /* new_low_water will be a minimum over every + * channel, so start with a big number */ + new_low_water = target; + for (i = 0; i < ms->nchans; i++) { + snd_list_type snd_list = ms->chans[i]; + add_susp_type susp = (add_susp_type) snd_list->u.susp; + time_type my_hor; + time_type my_low_water; +D nyquist_printf("chans[%d]: ", i); + + /* fetch up to horizon */ + + /* see if susp has an unprocessed block (test on susp->s1_ptr + * is probably not necessary, in fact, it isn't initialized + * until the first block is fetched, but s1_cnt is + */ + if (susp->s1_cnt && susp->s1_ptr && + susp->s1_ptr == susp->s1_bptr->samples) { + /* do nothing, unprocessed block already there as a + * result of the initiating fetch + */ + } else if (susp->s1_cnt != 0) { + stdputstr("multiseq_advance: s1_cnt != 0\n"); + EXIT(1); /* this should never happen */ + } else { /* otherwise fetch it */ +D stdputstr("prefetching samples "); + susp_get_block_samples(s1, s1_bptr, s1_ptr, s1_cnt); + if (susp->s1_ptr == zero_block->samples) { + susp->terminate_bits = 1; + susp->s1_bptr = internal_zero_block; + susp->s1_ptr = internal_zero_block->samples; + } + /* see if we've reached a logical stop + * (I can't believe this code block is in 3 places - + * there must be a better way... RBD) + */ + if (!susp->logical_stop_bits) { + if (susp->s1->logical_stop_cnt != UNKNOWN) { + if (susp->susp.current + susp->s1_cnt >= + susp->s1->logical_stop_cnt) { + susp->logical_stop_bits = 1; + susp->susp.log_stop_cnt = + susp->s1->logical_stop_cnt; + ms->not_logically_stopped_cnt--; +D nyquist_printf( + "snd_make_multiseq: Logical stop reached, not_logically_stopped_cnt %d\n", + ms->not_logically_stopped_cnt); + } + } + } + } +D nyquist_printf(" current %d cnt %d ", + (int)susp->susp.current, (int)susp->s1_cnt); + + /* while the susp has prefetched a block that ends at or + * before horizon, put the block on the snd_list and + * prefetch another block + */ + while (susp_time(susp, ms) < ms->horizon + 0.000001) { + snd_list->block = susp->s1_bptr; + snd_list->block_len = (short) susp->s1_cnt; + susp->susp.current += susp->s1_cnt; + (susp->s1_bptr->refcnt)++; + susp->s1_cnt = 0; +#ifdef MULTISEQ_GC_DEBUG + nyquist_printf( + "multiseq: output block %p%s on snd_list %p to chan %d\n", + susp->s1_bptr, + (susp->s1_bptr == internal_zero_block ? + " (INTERNAL ZERO BLOCK)" : ""), + snd_list, i); +#endif + snd_list->u.next = snd_list_create(&(susp->susp)); +#ifdef MULTISEQ_GC_DEBUG + snd_list_debug(snd_list, "multiseq_advance"); +#endif + ms->chans[i] = snd_list = snd_list->u.next; + susp_get_block_samples(s1, s1_bptr, s1_ptr, s1_cnt); + if (susp->s1_ptr == zero_block->samples) { + susp->terminate_bits = 1; + susp->s1_bptr = internal_zero_block; + susp->s1_ptr = internal_zero_block->samples; + } + if (susp->s1_ptr != susp->s1_bptr->samples) { + stdputstr("bug in multiseq_advance\n"); + EXIT(1); + } + /* see if we've reached a logical stop + * (I can't believe this code block is in 3 places - + * there must be a better way... RBD) + */ + if (!susp->logical_stop_bits) { + if (susp->s1->logical_stop_cnt != UNKNOWN) { + if (susp->susp.current + susp->s1_cnt >= + susp->s1->logical_stop_cnt) { + susp->logical_stop_bits = 1; + susp->susp.log_stop_cnt = + susp->s1->logical_stop_cnt; + ms->not_logically_stopped_cnt--; +D nyquist_printf( + "snd_make_multiseq: Logical stop reached, not_logically_stopped_cnt %d\n", + ms->not_logically_stopped_cnt); + } + } + } +D nyquist_printf("\n\toutput block, current %d cnt %d ", + (int)susp->susp.current, (int)susp->s1_cnt); + } + if (!susp->logical_stop_bits) + my_hor = susp_time(susp, ms); + else my_hor = susp_log_stop_time(susp, ms); + if (new_horizon < my_hor) { +D nyquist_printf("new_horizon %g ", my_hor); + new_horizon = my_hor; + } + if (ms->not_logically_stopped_cnt == 0) { + ms->horizon = new_horizon; /* pass t0 to multiseq_convert */ +D stdputstr("Calling multiseq_convert\n"); + multiseq_convert(ms); + return; + } + my_low_water = susp_low_water(susp, ms); + if (my_low_water < new_low_water) { + new_low_water = my_low_water; + } +D stdputstr("\n"); + } + ms->low_water = new_low_water; + if (new_horizon <= ms->horizon) { + stdputstr("no progress in multiseq_advance\n"); + EXIT(1); + } else { + ms->horizon = new_horizon; + } + } +} + + +/* multiseq_convert -- eval closure and convert to adds */ +/**/ +void multiseq_convert(multiseq_type ms) +{ + LVAL result, new; + sound_type snd; + time_type now = ms->t0 + ms->horizon; + int i; + long size; + + xlsave1(result); + result = xleval(cons(ms->closure, consa(cvflonum(now)))); + if (exttypep(result, a_sound)) { + snd = sound_copy(getsound(result)); + result = newvector(ms->nchans); + setelement(result, 0, cvsound(snd)); + for (i = 1; i < ms->nchans; i++) { + setelement(result, i, cvsound(sound_zero(now, ms->sr))); + } + } else if (vectorp(result)) { + if (getsize(result) > ms->nchans) { + xlerror("too few channels", result); + } else if (getsize(result) < ms->nchans) { + new = newvector(ms->nchans); + for (i = 1; i < getsize(result); i++) { + setelement(new, i, getelement(result, i)); + } + for (i = getsize(result); i < ms->nchans; i++) { + setelement(new, i, cvsound(sound_zero(now, ms->sr))); + } + result = new; + } + } else xlerror("closure did not return a (multi-channel) sound", result); + + /* now result holds a vector of nchans, insert them into add_susp's */ + for (i = 0; i < ms->nchans; i++) { + snd_list_type snd_list = ms->chans[i]; + add_susp_type susp = (add_susp_type) snd_list->u.susp; + long sother_start; + + /* remove backpointer to ms */ + susp->multiseq = NULL; + susp->susp.print_tree = add_print_tree; + susp->susp.free = add_free; + susp->susp.mark = add_mark; + + susp->s2 = sound_copy(getsound(getelement(result, i))); + if (susp->s1->sr != susp->s2->sr) + xlfail("multiseq: sample rates must match"); + + if (susp->s2->scale != 1.0) { + susp->s2 = snd_make_normalize(susp->s2); + } + + sother_start = ROUND((susp->s2->t0 - susp->susp.t0) * susp->s2->sr); +D nyquist_printf("sother_start computed for %p: %d\n", + susp, (int)sother_start); + if (sother_start > susp->susp.current) { +D nyquist_printf("susp %p using add_s1_nn_fetch\n", susp); + susp->susp.fetch = add_s1_nn_fetch; + susp->susp.name = "multiseq:add_s1_nn_fetch"; + } else if (susp->terminate_bits) { /* s1 is done, just get s2 now */ + sound_unref(susp->s1); + susp->s1 = NULL; +D nyquist_printf("susp %p using add_s2_nn_fetch\n", susp); + susp->susp.fetch = add_s2_nn_fetch; + susp->susp.name = "multiseq:add_s2_nn_fetch"; + } else { +D nyquist_printf("susp %p using add_s1_s2_nn_fetch\n", susp); + susp->susp.fetch = add_s1_s2_nn_fetch; + susp->susp.name = "multiseq:add_s1_s2_nn_fetch"; + } + + /* fix up logical stop info */ + /* BUG: what if s2 is already stopped? */ + susp->susp.log_stop_cnt = UNKNOWN; + susp->logically_stopped = false; + + /* we need to compute at least 1 sample + * (at this point we don't really know if we've + * computed anything or not, so to be safe, do it. + */ + snd_list->u.next = snd_list_create(&(susp->susp)); + snd_list->block = internal_zero_block; + (*(susp->susp.fetch))(susp, snd_list); + } + + /* now free the multiseq struct */ + size = sizeof(snd_list_type) * ms->nchans; + ffree_generic(ms->chans, size, "multiseq_convert"); + ffree_generic(ms, sizeof(multiseq_node), "multiseq_convert(2)"); + + ms->closure = NIL; /* allow garbage collection now */ + xlpop(); +} + + +/* multiseq_fetch returns blocks of s1 until the logical stop time of s1's */ +/* + * Fetch routines (in particular, the add_*_fetch routines that will + * be installed on this susp at a later time) expect to be called with + * a new snd_list installed and ready for a new block. However, since + * we are going to call multiseq_advance to pull blocks out of susps + * that will not be set up with a fresh snd_list in this way, it is + * simpler to dispose of the preallocated snd_list so that all susps + * look alike to multiseq_advance. Of course, multiseq_advance will + * redo the work of allocating a snd_list. + * + * If a channel terminates early, we must be careful: continuing to + * fetch will return pointers to the zero_block, but this will + * indicate termination to whoever is fetching from multiseq. We + * must check the pointers and substitute internal_zero_block to + * avoid premature termination. + */ +void multiseq_fetch(susp, snd_list) + register add_susp_type susp; + snd_list_type snd_list; +{ + time_type block_end_time; + + /* undo the preallocation of a snd_list_node */ + /* we can bypass the reference counting code because we + * know that this snd_list was just allocated and has no + * other references + */ +#ifdef MULTISEQ_GC_DEBUG + if (snd_list_to_watch == snd_list->u.next) { + nyquist_printf("multiseq_fetch: backing out snd_list_to_watch from %p\n", + snd_list_to_watch); + watch_snd_list(snd_list); + } +#endif + ffree_snd_list(snd_list->u.next, "multiseq_fetch"); + snd_list->u.susp = (snd_susp_type) susp; + snd_list->block = NULL; + +D nyquist_printf("multiseq_fetch called: susp %p s1_cnt %d\n", + susp, (int)susp->s1_cnt); + + /* first compute how many samples we can generate from s1: */ + if (susp->s1_cnt == 0) { + susp_get_block_samples(s1, s1_bptr, s1_ptr, s1_cnt); + if (susp->s1_ptr == zero_block->samples) { + susp->terminate_bits = 1; /* mark s1 as terminated */ + susp->s1_bptr = internal_zero_block; + susp->s1_ptr = internal_zero_block->samples; + } + /* see if we've reached a logical stop + * (I can't believe this code block is in 3 places - + * there must be a better way... RBD) + */ + if (!susp->logical_stop_bits) { + if (susp->s1->logical_stop_cnt != UNKNOWN) { + if (susp->susp.current + susp->s1_cnt >= + susp->s1->logical_stop_cnt) { + susp->logical_stop_bits = 1; + susp->susp.log_stop_cnt = + susp->s1->logical_stop_cnt; + susp->multiseq->not_logically_stopped_cnt--; +D nyquist_printf( + "snd_make_multiseq: Logical stop reached, not_logically_stopped_cnt %d\n", + susp->multiseq->not_logically_stopped_cnt); + } + } + } + } + /* s1_cnt has the number of samples we can return */ + + /* now compute time of the last sample */ + block_end_time = susp_time(susp, susp->multiseq); +D nyquist_printf("block_end_time of %p: %g\n", susp, block_end_time); + multiseq_advance(susp->multiseq, block_end_time); +} + + +/* multiseq_mark -- mark routine for multiseq susps */ +/**/ +void multiseq_mark(add_susp_type susp) +{ + int i; + multiseq_type ms = susp->multiseq; +D nyquist_printf("multiseq_mark(%p)\n", susp); +/* nyquist_printf("marking s1@%p in add@%p\n", susp->s1, susp);*/ + if (ms->closure) mark(ms->closure); + + /* mark s1 of each susp in multiseq */ + for (i = 0; i < ms->nchans; i++) { + snd_list_type snd_list = ms->chans[i]; + if (snd_list) { + while (snd_list->block != NULL) { + if (snd_list == zero_snd_list) break; + snd_list = snd_list->u.next; + } + sound_xlmark(((add_susp_type) snd_list->u.susp)->s1); + } + } +} + + +/* snd_make_multiseq -- make a multiseq from an array and a closure */ +/* + * NOTE: the resulting array of sounds will not use the normal + * SND_get_first and SND_get_next routines to fetch new blocks + * because these extend the snd_list of the sound immediately, + * and this would confuse multiseq_advance() which has to extend + * multiple snd_lists synchronously. So, we use multiseq_get_next() + * instead. + */ +LVAL snd_make_multiseq(LVAL s1, LVAL closure) +{ + multiseq_type ms; + int i; + LVAL result; + + xlsave1(result); + + /* allocate multiseq */ + falloc_generic(ms, multiseq_node, "snd_make_multiseq"); + + /* install its array of snd_list_type */ + if (!vectorp(s1) || getsize(s1) == 0) { + ffree_generic(ms, sizeof(multiseq_node), "snd_make_multiseq"); + xlerror("bad argument type", s1); + } + ms->nchans = getsize(s1); + ms->closure = closure; + ms->not_logically_stopped_cnt = 0; + ms->low_water = 0.0; + ms->horizon = 0.0; + falloc_generic_n(ms->chans, snd_list_type, ms->nchans, + "snd_make_multiseq"); + + /* allocate sounds to return */ + result = newvector(ms->nchans); + + /* ms->t0 will be the minimum of all t0's in array */ + ms->t0 = (getsound(getelement(s1, 0)))->t0; + + /* create sounds to return */ + for (i = 0; i < ms->nchans; i++) { + add_susp_type susp; + sound_type snd; + falloc_generic(susp, add_susp_node, "snd_make_multiseq(add_susp)"); + susp->s1 = sound_copy(getsound(getelement(s1, i))); + /* we used to only incr this if lsc was UNKNOWN, but + that's wrong. Should move this out of the loop now. + */ + if (susp->s1->scale != 1.0) { + /* stdputstr("normalizing first sound in a seq\n"); */ + susp->s1 = snd_make_normalize(susp->s1); + } + + ms->not_logically_stopped_cnt++; +D nyquist_printf("snd_make_multiseq: not_logically_stopped_cnt %d\n", + ms->not_logically_stopped_cnt); + susp->s1_cnt = 0; + susp->s2 = NULL; + susp->s2_cnt = 0; + susp->susp.fetch = multiseq_fetch; + susp->susp.free = multiseq_free; + susp->susp.sr = susp->s1->sr; + susp->susp.mark = multiseq_mark; + susp->susp.print_tree = multiseq_print_tree; + susp->susp.name = "multiseq"; + susp->susp.t0 = susp->s1->t0; + susp->terminate_bits = 0; /* bits for s1 and s2 termination */ + susp->terminate_cnt = UNKNOWN; + susp->logical_stop_bits = 0; /* bits for s1 and s2 log. stop */ + susp->susp.log_stop_cnt = UNKNOWN; + susp->logically_stopped = false; + susp->started = false; + susp->susp.current = 0; + susp->multiseq = ms; + snd = sound_create((snd_susp_type) susp, susp->s1->t0, susp->susp.sr, + 1.0); +#ifdef GC_DEBUG + if (snd == sound_to_watch) { + nyquist_printf("watched sound is channel %d\n", i); + } +#endif + setelement(result, i, cvsound(snd)); + if (snd->list->block || !snd->list->u.susp) { + stdputstr("data inconsistency in snd_make_seq\n"); + EXIT(1); + } + ms->chans[i] = snd->list; +D nyquist_printf("ms->chans[%d] = %p, %p->u.susp = %p\n", + i, snd->list, snd->list, snd->list->u.susp); + ms->t0 = MIN(ms->t0, susp->s1->t0); + ms->sr = susp->s1->sr; /* assume all samp rates are equal */ +D nyquist_printf("Multiseq sound[%d]: \n", i); +D sound_print_tree(susp->s1); + } +D nyquist_printf("ms->t0 == %g\n", ms->t0); + xlpop(); + return result; +} + + +/* note: snd_multiseq is a noop, just call snd_make_multiseq */ + +void multiseq_free(add_susp_type susp) +{ + int i; + multiseq_type ms = susp->multiseq; + boolean dead = true; + sound_unref(susp->s1); + sound_unref(susp->s2); /* probably not necessary */ + /* tricky part: remove pointer from ms->chans */ + for (i = 0; i < ms->nchans; i++) { + if (ms->chans[i]) { + dead = false; + /* + * note that ms->chans is still a valid + * pointer (see snd_list_unref) + */ + if (ms->chans[i]->u.susp == (snd_susp_type) susp) { + ms->chans[i] = NULL; +D nyquist_printf("susp %p freed, ms@%p->chans[%d] = NULL\n", + susp, ms, i); + } + } + } + + /* if last element is freed, free the multiseq struct too */ + if (dead) { + i = sizeof(snd_list_type) * ms->nchans; + ffree_generic(ms->chans, i, "multiseq_free"); + ffree_generic(ms, sizeof(multiseq_node), "multiseq_free(2)"); + } + + susp->multiseq = NULL; /* just to be safe */ + ffree_generic(susp, sizeof(add_susp_node), "multiseq_free(3)"); +} + + +void multiseq_print_tree(add_susp_type susp, int n) +{ + int i; + + indent(n); + if (!susp->multiseq) { + xlfail("internal error: missing multiseq structure"); + } + nyquist_printf("multiseq@%p = [ ", susp->multiseq); + for (i = 0; i < susp->multiseq->nchans; i++) { + if (susp->multiseq->chans[i]) { + nyquist_printf("%p", susp->multiseq->chans[i]->u.susp); + } else { + stdputstr("NULL"); + } + } + + indent(n); + stdputstr("s1:"); + sound_print_tree_1(susp->s1, n); + + indent(n); + stdputstr("closure:"); + stdprint(susp->multiseq->closure); + + indent(n); +} + + diff --git a/nyqsrc/multiseq.h b/nyqsrc/multiseq.h new file mode 100644 index 0000000..921ba24 --- /dev/null +++ b/nyqsrc/multiseq.h @@ -0,0 +1,19 @@ +/* this typedef goes here because it is needed by add */ + +typedef struct multiseq_struct { + int not_logically_stopped_cnt; + int nchans; + /* greatest lower bound on logical stop time: */ + time_type horizon; + /* lowest time corresp to sample count on a snd_list: */ + time_type low_water; + snd_list_type *chans; + time_type t0; + rate_type sr; + LVAL closure; +} multiseq_node, *multiseq_type; + + + +LVAL snd_make_multiseq(LVAL s1, LVAL closure); + /* LISP: (SND-MULTISEQ ANY ANY) */ diff --git a/nyqsrc/nfilterkit.c b/nyqsrc/nfilterkit.c new file mode 100644 index 0000000..00e7f65 --- /dev/null +++ b/nyqsrc/nfilterkit.c @@ -0,0 +1,199 @@ +/* + * nfilterkit.c - windowed low-pass filter support. + * adapted from filterkit.c, by Julius Smith et al., CCRMA, Stanford University + * + +/* + * FilterUp() - Applies a filter to a given sample when up-converting. + * FilterUD() - Applies a filter to a given sample when up- or down- + * converting. + */ + +#include "soundstruct.h" +#include "nresample.h" +#include "nfilterkit.h" + +/* #include */ +#include +#include +#include + + +#include + +fast_float FilterUp(float Imp[], float ImpD[], + UHWORD Nwing, BOOL Interp, + float *Xp, double Ph, HWORD Inc) +{ + float *Hp, *Hdp = NULL, *End; + fast_float a = 0; + fast_float v, t; + double exact_index = Ph * Npc; + long index = exact_index; /* convert fraction to filter index */ + +/* printf("FilterUp, Inc %d, phase %g\n", Inc, Ph); */ + v=0; + Hp = &Imp[index]; + End = &Imp[Nwing]; + if (Interp) { + Hdp = &ImpD[index]; + a = exact_index - index; +/* printf("fraction %g\n", a); */ + } + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + { /* ...then we've already skipped the */ + printf("Ph == 0\n"); + Hp += Npc; /* first sample, so we must also */ + Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */ + } + } + if (Interp) { + while (Hp < End) { + t = *Hp; /* Get filter coeff */ + /* t scaled by 2^(16 + NLpScl)/LpScl */ +/* printf("coeff %g ", t); */ + t += *Hdp *a; /* t is now interp'd filter coeff */ +/* printf("interp'd coeff %g ", t);*/ + Hdp += Npc; /* Filter coeff differences step */ +/* printf("input sample %g ", *Xp); */ + t *= *Xp; /* Mult coeff by input sample */ + /* t scaled by 2^(16 + NLpScl)/LpScl */ +/* printf("product %g\n", t); */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } else { + while (Hp < End) { + t = *Hp; /* Get filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } +/* printf("FilterUp, Inc %d returns %g\n", Inc, v); */ + return(v); +} + +fast_float FilterUD( float Imp[], float ImpD[], + UHWORD Nwing, BOOL Interp, + float *Xp, double Ph, HWORD Inc, double dhb) +{ + double a; + float *Hp, *Hdp, *End; + fast_float v, t; + double Ho; + + v=0; + Ho = Ph*dhb; + End = &Imp[Nwing]; + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + Ho += dhb; /* ...then we've already skipped the */ + } /* first sample, so we must also */ + /* skip ahead in Imp[] and ImpD[] */ + if (Interp) { + long HoIndex = Ho; + while ((Hp = &Imp[HoIndex]) < End) { + t = *Hp; /* Get IR sample */ + Hdp = &ImpD[HoIndex]; /* get interp (lower Na) bits from diff table*/ + a = Ho - HoIndex; /* a is logically between 0 and 1 */ + t += *Hdp * a; /* t is now interp'd filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + HoIndex = Ho; + } + } else { + long HoIndex = Ho; + while ((Hp = &Imp[HoIndex]) < End) { + t = *Hp; /* Get IR sample */ + t *= *Xp; /* Mult coeff by input sample */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + HoIndex = Ho; + } + } + return(v); +} + +/* Sampling rate up-conversion only subroutine; + * Slightly faster than down-conversion; + */ +static int SrcUp(float X[], float Y[], double factor, double *Time, + UHWORD Nx, UHWORD Nwing, double LpScl, + float Imp[], float ImpD[], BOOL Interp) +{ + mem_float *Xp, *Ystart; + fast_float v; + + double dt; /* Step through input signal */ + double endTime; /* When Time reaches EndTime, return to user */ + +/* printf("SrcUp: interpFilt %d\n", Interp);*/ + + dt = 1.0/factor; /* Output sampling period */ + + Ystart = Y; + endTime = *Time + Nx; + while (*Time < endTime) + { + long iTime = *Time; + Xp = &X[iTime]; /* Ptr to current input sample */ + /* Perform left-wing inner product */ + v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, *Time - iTime, -1); + /* Perform right-wing inner product */ + v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, + (1 + iTime) - *Time, 1); + v *= LpScl; /* Normalize for unity filter gain */ +/* printf("SrcUp output sample %g\n", v); */ + *Y++ = v; + *Time += dt; /* Move to next sample by time increment */ + } + return (Y - Ystart); /* Return the number of output samples */ +} + + +/* Sampling rate conversion subroutine */ + +static int SrcUD(float X[], float Y[], double factor, double *Time, + UHWORD Nx, UHWORD Nwing, double LpScl, + float Imp[], float ImpD[], BOOL Interp) +{ + mem_float *Xp, *Ystart; + fast_float v; + + double dh; /* Step through filter impulse response */ + double dt; /* Step through input signal */ + double endTime; /* When Time reaches EndTime, return to user */ + + dt = 1.0/factor; /* Output sampling period */ + + dh = MIN(Npc, factor*Npc); /* Filter sampling period */ + + Ystart = Y; + endTime = *Time + Nx; + while (*Time < endTime) + { + long iTime = *Time; + Xp = &X[iTime]; /* Ptr to current input sample */ + v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, *Time - iTime, + -1, dh); /* Perform left-wing inner product */ + v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (1 + iTime) - *Time, + 1, dh); /* Perform right-wing inner product */ + v *= LpScl; /* Normalize for unity filter gain */ + *Y++ = v; + *Time += dt; /* Move to next sample by time increment */ + } + return (Y - Ystart); /* Return the number of output samples */ +} + + diff --git a/nyqsrc/nfilterkit.h b/nyqsrc/nfilterkit.h new file mode 100644 index 0000000..b7343e5 --- /dev/null +++ b/nyqsrc/nfilterkit.h @@ -0,0 +1,80 @@ +/* nfilterkit.h -- header for adapted version of filterkit */ + +typedef char BOOL; +typedef short HWORD; +typedef unsigned short UHWORD; +typedef int WORD; +typedef unsigned int UWORD; + +#define MAX_HWORD (32767) +#define MIN_HWORD (-32768) + +#ifdef DEBUG +#define INLINE +#else DEBUG +/* #define INLINE inline */ +#define INLINE +#endif DEBUG + +/* + * FilterUp() - Applies a filter to a given sample when up-converting. + * FilterUD() - Applies a filter to a given sample when up- or down- + */ + +/* Conversion constants */ +#define Nhc 8 +#define Np (Nhc+Na) + +/* Description of constants: + * + * Npc - is the number of look-up values available for the lowpass filter + * between the beginning of its impulse response and the "cutoff time" + * of the filter. The cutoff time is defined as the reciprocal of the + * lowpass-filter cut off frequence in Hz. For example, if the + * lowpass filter were a sinc function, Npc would be the index of the + * impulse-response lookup-table corresponding to the first zero- + * crossing of the sinc function. (The inverse first zero-crossing + * time of a sinc function equals its nominal cutoff frequency in Hz.) + * Npc must be a power of 2 due to the details of the current + * implementation. The default value of 512 is sufficiently high that + * using linear interpolation to fill in between the table entries + * gives approximately 16-bit accuracy in filter coefficients. + * + * Nhc - is log base 2 of Npc. + * + * Na - is the number of bits devoted to linear interpolation of the + * filter coefficients. + * + * Np - is Na + Nhc, the number of bits to the right of the binary point + * in the integer "time" variable. To the left of the point, it indexes + * the input array (X), and to the right, it is interpreted as a number + * between 0 and 1 sample of the input X. Np must be less than 16 in + * this implementation. + * + * Nh - is the number of bits in the filter coefficients. The sum of Nh and + * the number of bits in the input data (typically 16) cannot exceed 32. + * Thus Nh should be 16. The largest filter coefficient should nearly + * fill 16 bits (32767). + * + * Nb - is the number of bits in the input data. The sum of Nb and Nh cannot + * exceed 32. + * + * Nhxn - is the number of bits to right shift after multiplying each input + * sample times a filter coefficient. It can be as great as Nh and as + * small as 0. Nhxn = Nh-2 gives 2 guard bits in the multiply-add + * accumulation. If Nhxn=0, the accumulation will soon overflow 32 bits. + * + * Nhg - is the number of guard bits in mpy-add accumulation (equal to Nh-Nhxn) + * + * NLpScl - is the number of bits allocated to the unity-gain normalization + * factor. The output of the lowpass filter is multiplied by LpScl and + * then right-shifted NLpScl bits. To avoid overflow, we must have + * Nb+Nhg+NLpScl < 32. + */ + + +fast_float FilterUp(mem_float Imp[], mem_float ImpD[], UHWORD Nwing, BOOL Interp, + mem_float *Xp, double Ph, HWORD Inc); + +fast_float FilterUD(mem_float Imp[], mem_float ImpD[], UHWORD Nwing, BOOL Interp, + mem_float *Xp, double Ph, HWORD Inc, double dhb); diff --git a/nyqsrc/nyq-osc-server.c b/nyqsrc/nyq-osc-server.c new file mode 100644 index 0000000..49cc0ae --- /dev/null +++ b/nyqsrc/nyq-osc-server.c @@ -0,0 +1,112 @@ +/* nosc-server.c -- an OSC server for Nyquist */ +/* + * this enables OSC clients to set slider values in Nyquist + * for security reasons, OSC clients cannot invoke Lisp expressions + * the only operation allowed is to set a value in a Lisp array + * + * The API is: + * + * int nosc_init() -- initialize the server, return error, 0 means none + * int nosc_poll() -- poll for messages and process them, return error, 0 means none + * void nosc_finish() -- free data structures, return error, 0 means none + */ + +#ifdef OSC +#ifdef WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#endif +#include "xlisp.h" +#include "sound.h" /* to get nosc_enabled */ +#include "lo/lo.h" +#include "sliders.h" + +static lo_server the_server = NULL; +static int lo_fd; + +static void error(int num, const char *msg, const char *path) +{ + char s[256]; + sprintf(s, "liblo server error %d in path %s: %s\n", num, path, msg); + stdputstr(s); +} + + +static int slider_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, void *user_data) +{ + // printf("%s <- %d, %g\n", path, argv[0]->i, argv[1]->f); + // fflush(stdout); + set_slider(argv[0]->i, argv[1]->f); + return 0; +} + +// wii_orientation_handler -- controls sliders 0 and 1 in range [0, 1] +// using wii orientation messages from OSC +static int wii_orientation_handler(const char *path, const char *types, + lo_arg **argv, int argc, void *data, + void *user_data) +{ + set_slider(0, min(1.0F, max(0.0F, (argv[0]->f / 180) + 0.5))); + set_slider(1, min(1.0F, max(0.0F, (argv[1]->f / 180) + 0.5))); + return 0; +} + + +int nosc_init() +{ + the_server = lo_server_new("7770", error); + /* add method that will match the path /slider, with two numbers, coerced + * to int and float */ + lo_server_add_method(the_server, "/slider", "if", slider_handler, NULL); + lo_server_add_method(the_server, "/wii/orientation", "ff", + wii_orientation_handler, NULL); + lo_fd = lo_server_get_socket_fd(the_server); + nosc_enabled = true; + return 0; +} + + +int nosc_poll() +{ + fd_set rfds; + struct timeval tv; + int retval; + + // loop, receiving all pending OSC messages + while (true) { + FD_ZERO(&rfds); + FD_SET(lo_fd, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + + retval = select(lo_fd + 1, &rfds, NULL, NULL, &tv); + if (retval == -1) { + stdputstr("select() error in nosc_poll\n"); + return -1; + } else if (retval > 0 && FD_ISSET(lo_fd, &rfds)) { + /* printf("lo_server_recv_noblock 1\n"); */ + lo_server_recv_noblock(the_server, 0); + } else { + return 0; + } + } +} + + +void nosc_finish() +{ + lo_server_free(the_server); + nosc_enabled = false; +} + +#endif + diff --git a/nyqsrc/nyq-osc-server.h b/nyqsrc/nyq-osc-server.h new file mode 100644 index 0000000..655c7b5 --- /dev/null +++ b/nyqsrc/nyq-osc-server.h @@ -0,0 +1,9 @@ +/* + * nyq-osc-server.h + * nyquist + * + * Created by Roger Dannenberg on 10/1/06. + * Copyright 2006 __MyCompanyName__. All rights reserved. + * + */ + diff --git a/nyqsrc/nyx.c b/nyqsrc/nyx.c new file mode 100644 index 0000000..4cc1fea --- /dev/null +++ b/nyqsrc/nyx.c @@ -0,0 +1,1294 @@ +/********************************************************************** + + nyx.c + + Nyx: A very simple external interface to Nyquist + + Dominic Mazzoni + +**********************************************************************/ + +/* system includes */ +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#endif + +/* nyx includes */ +#include "nyx.h" + +/* xlisp includes */ +#include "switches.h" +#include "xlisp.h" +#include "cext.h" + +/* nyquist includes */ +#include "sound.h" +#include "samples.h" +#include "falloc.h" + +/* use full copy */ +#define NYX_FULL_COPY 1 + +/* show memory stats */ +// #define NYX_MEMORY_STATS 1 + +/* show details of obarray copy */ +// #define NYX_DEBUG_COPY 1 + +/* macro to compute the size of a segment (taken from xldmem.h) */ +#define segsize(n) (sizeof(SEGMENT)+((n)-1)*sizeof(struct node)) + +/* xldmem external variables */ +extern long nnodes; +extern long nfree; +extern long total; +extern int nsegs; +extern SEGMENT *segs; +extern SEGMENT *lastseg; +extern LVAL fnodes; + +/* nyquist externs */ +extern LVAL a_sound; +extern snd_list_type zero_snd_list; + +/* globals */ +LOCAL nyx_os_callback nyx_os_cb = NULL; +LOCAL void *nyx_os_ud; +LOCAL nyx_output_callback nyx_output_cb; +LOCAL void *nyx_output_ud; +LOCAL int nyx_expr_pos; +LOCAL int nyx_expr_len; +LOCAL const char *nyx_expr_string; +LOCAL LVAL nyx_result; +LOCAL nyx_rval nyx_result_type = nyx_error; +LOCAL XLCONTEXT nyx_cntxt; +LOCAL int nyx_first_time = 1; +LOCAL LVAL nyx_obarray; +LOCAL FLOTYPE nyx_warp_stretch; + +/* Suspension node */ +typedef struct nyx_susp_struct { + snd_susp_node susp; // Must be first + nyx_audio_callback callback; + void *userdata; + long len; + int channel; +} nyx_susp_node, *nyx_susp_type; + +#if defined(NYX_DEBUG_COPY) && NYX_DEBUG_COPY +static const char *_types_[] = +{ + "FREE_NODE", + "SUBR", + "FSUBR", + "CONS", + "SYMBOL", + "FIXNUM", + "FLONUM", + "STRING", + "OBJECT", + "STREAM", + "VECTOR", + "CLOSURE", + "CHAR", + "USTREAM", + "EXTERN" +}; + +// Dump the contents of the obarray +LOCAL void nyx_show_obarray() +{ + LVAL array = getvalue(obarray); + LVAL sym; + int i; + + for (i = 0; i < HSIZE; i++) { + for (sym = getelement(array, i); sym; sym = cdr(sym)) { + LVAL syma = car(sym); + + printf("_sym_ = "); + xlprint(getvalue(s_stdout), syma, TRUE); + + if (getvalue(syma)) { + printf(" _type_ = %s _val_ = ", _types_[ntype(getvalue(syma))]); + xlprint(getvalue(s_stdout), getvalue(syma), TRUE); + } + + if (getfunction(syma)) { + printf(" _type_ = %s _fun_ = ", _types_[ntype(getfunction(syma))]); + xlprint(getvalue(s_stdout), getfunction(syma), TRUE); + } + + printf("\n"); + } + } +} +#endif + +// +// Free empty segments +// +LOCAL void freesegs() +{ + SEGMENT *seg; + SEGMENT *next; + + // Free up as many nodes as possible + gc(); + + // Reset free node tracking + fnodes = NIL; + nfree = 0L; + + // Reset the last segment pointer + lastseg = NULL; + + // Scan all segments + for (seg = segs; seg != NULL; seg = next) { + int n = seg->sg_size; + int empty = TRUE; + int i; + LVAL p; + + // Check this segment for in-use nodes + p = &seg->sg_nodes[0]; + for (i = n; --i >= 0; ++p) { + if (ntype(p) != FREE_NODE) { + empty = FALSE; + break; + } + } + + // Retain pointer to next segment + next = seg->sg_next; + + // Was the current segment empty? + if (empty) { + // Free the segment; + free((void *) seg); + + // Unlink it from the list. No need to worry about a NULL lastseg + // pointer here since the fixnum and char segments will always exist + // at the head of the list and they will always have nodes. So, lastseg + // will have been set before we find any empty nodes. + lastseg->sg_next = next; + + // Reduce the stats + total -= (long) segsize(n); + nsegs--; + nnodes -= n; + } + else { + // Not empty, so remember this node as the last segment + lastseg = seg; + + // Add all of the free nodes in this segment to the free list + p = &seg->sg_nodes[0]; + for (i = n; --i >= 0; ++p) { + if (ntype(p) == FREE_NODE) { + rplaca(p, NIL); + rplacd(p, fnodes); + fnodes = p; + nfree++; + } + } + } + } +} + +#if defined(NYX_FULL_COPY) && NYX_FULL_COPY + +// Copy a node (recursively if appropriate) +LOCAL LVAL nyx_dup_value(LVAL val) +{ + LVAL nval = val; + + // Protect old and new values + xlprot1(val); + xlprot1(nval); + + // Copy the node + if (val != NIL) { + switch (ntype(val)) + { + case FIXNUM: + nval = cvfixnum(getfixnum(val)); + break; + + case FLONUM: + nval = cvflonum(getflonum(val)); + break; + + case CHAR: + nval = cvchar(getchcode(val)); + break; + + case STRING: + nval = cvstring((char *) getstring(val)); + break; + + case VECTOR: + { + int len = getsize(val); + int i; + + nval = newvector(len); + nval->n_type = ntype(val); + + for (i = 0; i < len; i++) { + if (getelement(val, i) == val) { + setelement(nval, i, val); + } + else { + setelement(nval, i, nyx_dup_value(getelement(val, i))); + } + } + } + break; + + case CONS: + nval = cons(nyx_dup_value(car(val)), nyx_dup_value(cdr(val))); + break; + + case SUBR: + case FSUBR: + nval = cvsubr(getsubr(val), ntype(val), getoffset(val)); + break; + + // Symbols should never be copied since their addresses are cached + // all over the place. + case SYMBOL: + nval = val; + break; + + // Streams are not copied (although USTREAM could be) and reference + // the original value. + case USTREAM: + case STREAM: + nval = val; + break; + + // Externals aren't copied because I'm not entirely certain they can be. + case EXTERN: + nval = val; + break; + + // For all other types, just allow them to reference the original + // value. Probably not the right thing to do, but easier. + case OBJECT: + case CLOSURE: + default: + nval = val; + break; + } + } + + xlpop(); + xlpop(); + + return nval; +} + +// Make a copy of the original obarray, leaving the original in place +LOCAL void nyx_save_obarray() +{ + LVAL newarray; + int i; + + // This provide permanent protection for nyx_obarray as we do not want it + // to be garbage-collected. + xlprot1(nyx_obarray); + nyx_obarray = getvalue(obarray); + + // Create and set the new vector. This allows us to use xlenter() to + // properly add the new symbol. Probably slower than adding directly, + // but guarantees proper hashing. + newarray = newvector(HSIZE); + setvalue(obarray, newarray); + + // Scan all obarray vectors + for (i = 0; i < HSIZE; i++) { + LVAL sym; + + // Scan all elements + for (sym = getelement(nyx_obarray, i); sym; sym = cdr(sym)) { + LVAL syma = car(sym); + char *name = (char *) getstring(getpname(syma)); + LVAL nsym = xlenter(name); + + // Ignore *OBARRAY* since there's no need to copy it + if (strcmp(name, "*OBARRAY*") == 0) { + continue; + } + + // Duplicate the symbol's values + setvalue(nsym, nyx_dup_value(getvalue(syma))); + setplist(nsym, nyx_dup_value(getplist(syma))); + setfunction(nsym, nyx_dup_value(getfunction(syma))); + } + } + + // Swap the obarrays, so that the original is put back into service + setvalue(obarray, nyx_obarray); + nyx_obarray = newarray; +} + +// Restore the symbol values to their original value and remove any added +// symbols. +LOCAL void nyx_restore_obarray() +{ + LVAL obvec = getvalue(obarray); + int i; + + // Scan all obarray vectors + for (i = 0; i < HSIZE; i++) { + LVAL last = NULL; + LVAL dcon; + + for (dcon = getelement(obvec, i); dcon; dcon = cdr(dcon)) { + LVAL dsym = car(dcon); + char *name = (char *)getstring(getpname(dsym)); + LVAL scon; + + // Ignore *OBARRAY* since setting it causes the input array to be + // truncated. + if (strcmp(name, "*OBARRAY*") == 0) { + continue; + } + + // Find the symbol in the original obarray. + for (scon = getelement(nyx_obarray, hash(name, HSIZE)); scon; scon = cdr(scon)) { + LVAL ssym = car(scon); + + // If found, then set the current symbols value to the original. + if (strcmp(name, (char *)getstring(getpname(ssym))) == 0) { + setvalue(dsym, nyx_dup_value(getvalue(ssym))); + setplist(dsym, nyx_dup_value(getplist(ssym))); + setfunction(dsym, nyx_dup_value(getfunction(ssym))); + break; + } + } + + // If we didn't find the symbol in the original obarray, then it must've + // been added since and must be removed from the current obarray. + if (scon == NULL) { + if (last) { + rplacd(last, cdr(dcon)); + } + else { + setelement(obvec, i, cdr(dcon)); + } + } + + // Must track the last dcon for symbol removal + last = dcon; + } + } +} + +#else + +LOCAL LVAL copylist(LVAL from) +{ + LVAL nsym; + if (from == NULL) { + return NULL; + } + + return cons(car(from), copylist(cdr(from))); +} + +/* Make a copy of the obarray so that we can erase any + changes the user makes to global variables */ +LOCAL void nyx_copy_obarray() +{ + LVAL newarray; + int i; + + // Create and set the new vector. + newarray = newvector(HSIZE); + setvalue(obarray, newarray); + + for (i = 0; i < HSIZE; i++) { + LVAL from = getelement(nyx_obarray, i); + if (from) { + setelement(newarray, i, copylist(from)); + } + } +} + +#endif + +void nyx_init() +{ + if (nyx_first_time) { + char *argv[1]; + argv[0] = "nyquist"; + xlisp_main_init(1, argv); + + nyx_os_cb = NULL; + nyx_output_cb = NULL; + + nyx_first_time = 0; + +#if defined(NYX_FULL_COPY) && NYX_FULL_COPY + // Save a copy of the original obarray's contents. + nyx_save_obarray(); +#else + // Permanently protect the original obarray value. This is needed since + // it would be unreferenced in the new obarray and would be garbage + // collected. We want to keep it around so we can make copies of it to + // refresh the execution state. + xlprot1(nyx_obarray); + nyx_obarray = getvalue(obarray); +#endif + } + +#if !defined(NYX_FULL_COPY) || !NYX_FULL_COPY + // Create a copy of the original obarray + nyx_copy_obarray(); +#endif + + // Keep nyx_result from being garbage-collected + xlprot1(nyx_result); + +#if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS + printf("\nnyx_init\n"); + xmem(); +#endif +} + +void nyx_cleanup() +{ + // Garbage-collect nyx_result + xlpop(); + +#if defined(NYX_FULL_COPY) && NYX_FULL_COPY + + // Restore the original symbol values + nyx_restore_obarray(); + +#else + + // Restore obarray to original state...but not the values + setvalue(obarray, nyx_obarray); + +#endif + + // Make sure the sound nodes can be garbage-collected. Sounds are EXTERN + // nodes whose value does not get copied during a full copy of the obarray. + setvalue(xlenter("S"), NIL); + + // Free excess memory segments - does a gc() + freesegs(); + + // No longer need the callbacks + nyx_output_cb = NULL; + nyx_os_cb = NULL; + +#if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS + printf("\nnyx_cleanup\n"); + xmem(); +#endif +} + +LOCAL void nyx_susp_fetch(register nyx_susp_type susp, snd_list_type snd_list) +{ + sample_block_type out; + sample_block_values_type out_ptr; + long n; + int err; + + falloc_sample_block(out, "nyx_susp_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + n = max_sample_block_len; + if (susp->susp.current + n > susp->len) + n = susp->len - susp->susp.current; + + err = susp->callback(out_ptr, susp->channel, + susp->susp.current, n, 0, susp->userdata); + if (err) { + // The user canceled or some other error occurred, so we use + // xlsignal() to jump back to our error handler. + xlsignal(NULL, NULL); + // never get here. + } + + snd_list->block_len = (short)n; + susp->susp.current += n; + + if (n == 0) { + /* we didn't read anything, but can't return length zero, so + convert snd_list to pointer to zero block */ + snd_list_terminate(snd_list); + } + else if (n < max_sample_block_len) { + /* should free susp */ + snd_list_unref(snd_list->u.next); + /* if something is in buffer, terminate by pointing to zero block */ + snd_list->u.next = zero_snd_list; + } +} + +LOCAL void nyx_susp_free(nyx_susp_type susp) +{ + ffree_generic(susp, sizeof(nyx_susp_node), "nyx_susp_free"); +} + +LOCAL void nyx_susp_print_tree(nyx_susp_type susp, int n) +{ +} + +void nyx_capture_output(nyx_output_callback callback, void *userdata) +{ + nyx_output_cb = callback; + nyx_output_ud = userdata; +} + +void nyx_set_audio_params(double rate, long len) +{ + double stretch_len = (len > 0 ? len / rate : 1.0); + LVAL warp; + + /* Bind the sample rate to the "*sound-srate*" global */ + setvalue(xlenter("*SOUND-SRATE*"), cvflonum(rate)); + + /* Bind selection len to "len" global */ + setvalue(xlenter("LEN"), cvflonum(len)); + + /* Set the "*warp*" global based on the length of the audio */ + xlprot1(warp); + warp = cons(cvflonum(0), /* time offset */ + cons(cvflonum(stretch_len), /* time stretch */ + cons(NULL, /* cont. time warp */ + NULL))); + setvalue(xlenter("*WARP*"), warp); + xlpop(); +} + +void nyx_set_input_audio(nyx_audio_callback callback, + void *userdata, + int num_channels, + long len, double rate) +{ + sample_type scale_factor = 1.0; + time_type t0 = 0.0; + nyx_susp_type *susp; + sound_type *snd; + int ch; + + nyx_set_audio_params(rate, len); + + susp = (nyx_susp_type *)malloc(num_channels * sizeof(nyx_susp_type)); + snd = (sound_type *)malloc(num_channels * sizeof(sound_type)); + + for(ch=0; ch < num_channels; ch++) { + falloc_generic(susp[ch], nyx_susp_node, "nyx_set_input_audio"); + + susp[ch]->callback = callback; + susp[ch]->userdata = userdata; + susp[ch]->len = len; + susp[ch]->channel = ch; + + susp[ch]->susp.fetch = nyx_susp_fetch; + susp[ch]->susp.keep_fetch = NULL; + susp[ch]->susp.free = nyx_susp_free; + susp[ch]->susp.mark = NULL; + susp[ch]->susp.print_tree = nyx_susp_print_tree; + susp[ch]->susp.name = "nyx"; + susp[ch]->susp.toss_cnt = 0; + susp[ch]->susp.current = 0; + susp[ch]->susp.sr = rate; + susp[ch]->susp.t0 = t0; + susp[ch]->susp.log_stop_cnt = 0; + + snd[ch] = sound_create((snd_susp_type)susp[ch], t0, + rate, + scale_factor); + } + + if (num_channels > 1) { + LVAL array = newvector(num_channels); + for(ch=0; chstop); + } + + while(result==0) { + for(ch=0; chget_next(snd, &cnt); + if (block == zero_block || cnt == 0) { + result = -1; + break; + } + + /* copy the data to a temporary buffer and scale it + by the appropriate scale factor */ + + if (cnt > bufferlen) { + if (buffer) + free(buffer); + + buffer = (float *)malloc(cnt * sizeof(float)); + if (buffer == NULL) { + goto finish; + } + + bufferlen = cnt; + } + + memcpy(buffer, block->samples, cnt * sizeof(float)); + + for(i=0; iscale; + + result = callback(buffer, ch, + totals[ch], cnt, lens[ch], userdata); + + if (result != 0) { + // The user canceled or some other error occurred, so we use + // xlsignal() to jump back to our error handler. + xlsignal(NULL, NULL); + // never get here. + } + + totals[ch] += cnt; + } + } + + success = TRUE; + + xltoplevel(); + + finish: + + gc(); + + if (buffer) { + free(buffer); + } + + if (lens) { + free(lens); + } + + if (totals) { + free(totals); + } + + if (snds) { + free(snds); + } + +#if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS + printf("\nnyx_get_audio after\n"); + xmem(); +#endif + + return success; +} + +int nyx_get_int() +{ + if (nyx_get_type(nyx_result) != nyx_int) + return -1; + + return getfixnum(nyx_result); +} + +double nyx_get_double() +{ + if (nyx_get_type(nyx_result) != nyx_double) + return -1.0; + + return getflonum(nyx_result); +} + +const char *nyx_get_string() +{ + if (nyx_get_type(nyx_result) != nyx_string) + return NULL; + + return (const char *)getstring(nyx_result); +} + +unsigned int nyx_get_num_labels() +{ + LVAL s = nyx_result; + int count = 0; + + if (nyx_get_type(nyx_result) != nyx_labels) + return 0; + + while(s) { + count++; + s = cdr(s); + } + + return count; +} + +void nyx_get_label(unsigned int index, + double *start_time, + double *end_time, + const char **label) +{ + LVAL s = nyx_result; + LVAL label_expr; + LVAL t0_expr; + LVAL t1_expr; + LVAL str_expr; + + if (nyx_get_type(nyx_result) != nyx_labels) + return; + + while(index) { + index--; + s = cdr(s); + if (s == NULL) { + // index was larger than number of labels + return; + } + } + + /* We either have (t0 "label") or (t0 t1 "label") */ + + label_expr = car(s); + t0_expr = car(label_expr); + t1_expr = car(cdr(label_expr)); + if (stringp(t1_expr)) { + str_expr = t1_expr; + t1_expr = t0_expr; + } + else + str_expr = car(cdr(cdr(label_expr))); + + if (floatp(t0_expr)) + *start_time = getflonum(t0_expr); + else if (fixp(t0_expr)) + *start_time = (double)getfixnum(t0_expr); + + if (floatp(t1_expr)) + *end_time = getflonum(t1_expr); + else if (fixp(t1_expr)) + *end_time = (double)getfixnum(t1_expr); + + *label = (const char *)getstring(str_expr); +} + +const char *nyx_get_error_str() +{ + return NULL; +} + +void nyx_set_os_callback(nyx_os_callback callback, void *userdata) +{ + nyx_os_cb = callback; + nyx_os_ud = userdata; +} + +void nyx_stop() +{ + xlflush(); + xltoplevel(); +} + +void nyx_break() +{ + xlflush(); + xlbreak("BREAK", s_unbound); +} + +void nyx_continue() +{ + xlflush(); + xlcontinue(); +} + +int ostgetc() +{ + if (nyx_expr_pos < nyx_expr_len) { + fflush(stdout); + return (nyx_expr_string[nyx_expr_pos++]); + } + else if (nyx_expr_pos == nyx_expr_len) { + /* Add whitespace at the end so that the parser + knows that this is the end of the expression */ + nyx_expr_pos++; + return '\n'; + } + else + return EOF; +} + +/* osinit - initialize */ +void osinit(char *banner) +{ +} + +/* osfinish - clean up before returning to the operating system */ +void osfinish(void) +{ +} + +/* oserror - print an error message */ +void oserror(char *msg) +{ + printf("nyx error: %s\n", msg); +} + +long osrand(long n) +{ + return (((int) rand()) % n); +} + +/* cd .. +open - open an ascii file */ +FILE *osaopen(name,mode) char *name,*mode; +{ + FILE *fp; + fp = fopen(name,mode); + return fp; +} + +/* osbopen - open a binary file */ +FILE *osbopen(char *name, char *mode) +{ + char bmode[10]; + FILE *fp; + + strncpy(bmode, mode, 8); + strcat(bmode,"b"); + fp = fopen(name,bmode); + return fp; +} + +/* osclose - close a file */ +int osclose(FILE *fp) +{ + return (fclose(fp)); +} + +/* osagetc - get a character from an ascii file */ +int osagetc(FILE *fp) +{ + return (getc(fp)); +} + +/* osaputc - put a character to an ascii file */ +int osaputc(int ch, FILE *fp) +{ + return (putc(ch,fp)); +} + +/* osoutflush - flush output to a file */ +void osoutflush(FILE *fp) { fflush(fp); } + +extern int dbgflg; + +/* osbgetc - get a character from a binary file */ +/* int osbgetc(fp) FILE *fp; {return (getc(fp));} */ +#ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 + int osbgetc(FILE *fp) + { + return (getc(fp)); + } +#endif + +/* osbputc - put a character to a binary file */ +int osbputc(int ch, FILE *fp) +{ + return (putc(ch,fp)); +} + +/* ostputc - put a character to the terminal */ +void ostputc(int ch) +{ + oscheck(); /* check for control characters */ + + if (nyx_output_cb) + nyx_output_cb(ch, nyx_output_ud); + else + putchar(((char) ch)); +} + +/* ostoutflush - flush output buffer */ +void ostoutflush() +{ + if (!nyx_output_cb) + fflush(stdout); +} + +/* osflush - flush the terminal input buffer */ +void osflush(void) +{ +} + +/* oscheck - check for control characters during execution */ +void oscheck(void) +{ + if (nyx_os_cb) { + nyx_os_cb(nyx_os_ud); + } + /* if they hit control-c: + xflush(); xltoplevel(); return; + */ +} + +/* xsystem - execute a system command */ +#ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 +LVAL xsystem() +{ + if (moreargs()) { + unsigned char *cmd; + cmd = (unsigned char *)getstring(xlgastring()); + fprintf(stderr, "Will not execute system command: %s\n", cmd); + } + return s_true; +} +#endif + +#ifndef WIN32 +/* xsetdir -- set current directory of the process */ +LVAL xsetdir() +{ + char *dir = (char *)getstring(xlgastring()); + int result; + LVAL cwd = NULL; + xllastarg(); + result = chdir(dir); + if (result) { + perror("SETDIR"); + } + dir = getcwd(NULL, 1000); + if (dir) { + cwd = cvstring(dir); + free(dir); + } + return cwd; +} +#endif + +/* xgetkey - get a key from the keyboard */ +#ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 + LVAL xgetkey() {xllastarg(); return (cvfixnum((FIXTYPE)getchar()));} +#endif + +/* ossymbols - enter os specific symbols */ +#ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 + void ossymbols(void) {} +#endif + +/* xsetupconsole -- used to configure window in Win32 version */ +#ifndef WIN32 // duplicated in winfun.c, per James Crook, 7/4/2003 + LVAL xsetupconsole() { return NULL; } +#endif + +const char os_pathchar = '/'; +const char os_sepchar = ':'; + +/* control-C handling */ +void ctcinit() {} + +/* xechoenabled -- set/clear echo_enabled flag (unix only) */ +LVAL xechoenabled() { return NULL; } + +/* osdir_list_start -- open a directory listing */ +int osdir_list_start(char *path) { return FALSE; } + +/* osdir_list_next -- read the next entry from a directory */ +char *osdir_list_next() { return NULL; } + +/* osdir_list_finish -- close an open directory */ +void osdir_list_finish() { return; } + +#ifndef WIN32 +/* xget_temp_path -- get a path to create temp files */ +LVAL xget_temp_path() +{ + char *tmp = getenv("TMPDIR"); + if (!tmp || !*tmp) { + tmp = getenv("TMP"); + if (!tmp || !*tmp) { + tmp = "/tmp/"; + } + } + return cvstring(tmp); +} +#endif + +#ifndef WIN32 +/* xget_user -- get a string identifying the user, for use in file names */ +LVAL xget_user() +{ + char *user = getenv("USER"); + if (!user || !*user) { + user = getenv("USERNAME"); + if (!user || !*user) { + errputstr("Warning: could not get user ID, using 'nyquist'\n"); + user = "nyquist"; + } + } + return cvstring(user); +} +#endif diff --git a/nyqsrc/nyx.h b/nyqsrc/nyx.h new file mode 100644 index 0000000..8dccb99 --- /dev/null +++ b/nyqsrc/nyx.h @@ -0,0 +1,66 @@ +/********************************************************************** + + nyx.h + + Nyx: A very simple external interface to Nyquist + + Dominic Mazzoni + +**********************************************************************/ + +#ifndef __NYX__ +#define __NYX__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + typedef enum { + nyx_error, + nyx_audio, + nyx_int, + nyx_double, + nyx_string, + nyx_labels + } nyx_rval; + + void nyx_init(); + void nyx_cleanup(); + + /* should return return 0 for success, -1 for error */ + typedef int (*nyx_audio_callback)(float *buffer, + int channel, + long start, long len, + void *userdata); + + void nyx_set_input_audio(nyx_audio_callback callback, + void *userdata, + int num_channels, + long len, double rate); + + nyx_rval nyx_eval_expression(const char *expr); + + int nyx_get_audio_num_channels(); + void nyx_get_audio(nyx_audio_callback callback, + void *userdata); + + int nyx_get_int(); + double nyx_get_double(); + const char *nyx_get_string(); + + int nyx_get_num_labels(); + void nyx_get_label(int index, + double *time, + const char **label); + + const char *nyx_get_error_str(); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __NYX__ */ + diff --git a/nyqsrc/oldyin.c b/nyqsrc/oldyin.c new file mode 100644 index 0000000..43387b1 --- /dev/null +++ b/nyqsrc/oldyin.c @@ -0,0 +1,466 @@ +/* yin.c -- partial implementation of the YIN algorithm, with some + * fixes by DM. This code should be replaced with the fall 2002 + * intro to computer music implementation project. + */ + +#include "stdio.h" +#ifdef UNIX +#include "sys/file.h" +#endif +#ifndef mips +#include "stdlib.h" +#endif +#include "snd.h" +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "yin.h" + +void yin_free(); + +/* for multiple channel results, one susp is shared by all sounds */ +/* the susp in turn must point back to all sound list tails */ + +typedef struct yin_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + sound_type s; + long s_cnt; + sample_block_values_type s_ptr; + long blocksize; + long stepsize; + sample_type *block; + float *temp; + sample_type *fillptr; + sample_type *endptr; + snd_list_type chan[2]; /* array of back pointers */ + long cnt; /* how many sample frames to read */ + long m; + long middle; +} yin_susp_node, *yin_susp_type; + + +// Uses cubic interpolation to return the value of x such +// that the function defined by f(0), f(1), f(2), and f(3) +// is maximized. +// +float CubicMaximize(float y0, float y1, float y2, float y3) +{ + // Find coefficients of cubic + + float a, b, c, d; + float da, db, dc; + float discriminant; + float x1, x2; + float dda, ddb; + + a = (float) (y0/-6.0 + y1/2.0 - y2/2.0 + y3/6.0); + b = (float) (y0 - 5.0*y1/2.0 + 2.0*y2 - y3/2.0); + c = (float) (-11.0*y0/6.0 + 3.0*y1 - 3.0*y2/2.0 + y3/3.0); + d = y0; + + // Take derivative + + da = 3*a; + db = 2*b; + dc = c; + + // Find zeroes of derivative using quadratic equation + + discriminant = db*db - 4*da*dc; + if (discriminant < 0.0) + return -1.0; // error + + x1 = (float) ((-db + sqrt(discriminant)) / (2 * da)); + x2 = (float) ((-db - sqrt(discriminant)) / (2 * da)); + + // The one which corresponds to a local _maximum_ in the + // cubic is the one we want - the one with a negative + // second derivative + + dda = 2*da; + ddb = db; + + if (dda*x1 + ddb < 0) + return x1; + else + return x2; +} + + +void yin_compute(yin_susp_type susp, float *pitch, float *harmonicity) +{ + float *samples = susp->block; + int middle = susp->middle; + /* int n = middle * 2; */ + int m = susp->m; + float threshold = 0.9F; + float *results = susp->temp; + + /* samples is a buffer of samples */ + /* n is the number of samples, equals twice longest period, must be even */ + /* m is the shortest period in samples */ + /* results is an array of size n/2 - m + 1, the number of different lags */ + + /* work from the middle of the buffer: */ + int i, j; /* loop counters */ + /* how many different lags do we compute? */ + /* int iterations = middle + 1 - m; */ + float left_energy = 0; + float right_energy = 0; + /* for each window, we keep the energy so we can compute the next one */ + /* incrementally. First, we need to compute the energies for lag m-1: */ + *pitch = 0; + for (i = 0; i < m - 1; i++) { + float left = samples[middle - 1 - i]; + float right = samples[middle + i]; + left_energy += left * left; + right_energy += right * right; + } + for (i = m; i <= middle; i++) { + /* i is the lag and the length of the window */ + /* compute the energy for left and right */ + float left, right, energy, a; + float harmonic; + left = samples[middle - i]; + left_energy += left * left; + right = samples[middle - 1 + i]; + right_energy += right * right; + /* compute the autocorrelation */ + a = 0; + for (j = 0; j < i; j++) { + a += samples[middle - i + j] * samples[middle + j]; + } + energy = left_energy + right_energy; + harmonic = (2 * a) / energy; + results[i - m] = harmonic; + } + for (i = m; i <= middle; i++) { + if (results[i - m] > threshold) { + float f_i = (i - 1) + + CubicMaximize(results[i - m - 1], results[i - m], + results[i - m + 1], results[i - m + 2]); + if (f_i < i - m - 1 || f_i > i - m + 2) f_i = (float) i; + *pitch = (float) hz_to_step((float) susp->susp.sr / f_i); + *harmonicity = results[i - m]; + break; + } + } +} + + +/* yin_fetch - compute F0 and harmonicity using YIN approach. */ +/* + * The pitch (F0) is determined by finding two periods whose + * inner product accounts for almost all of the energy. Let X and Y + * be adjacent vectors of length N in the sample stream. Then, + * if 2X*Y > threshold * (X*X + Y*Y) + * then the period is given by N + * In the algorithm, we compute different sizes until we find a + * peak above threshold. Then, we use cubic interpolation to get + * a precise value. If no peak above threshold is found, we return + * the first peak. The second channel returns the value 2X*Y/(X*X+Y*Y) + * which is refered to as the "harmonicity" -- the amount of energy + * accounted for by periodicity. + * + * Low sample rates are advised because of the high cost of computing + * inner products (fast autocorrelation is not used). + * + * The result is a 2-channel signal running at the requested rate. + * The first channel is the estimated pitch, and the second channel + * is the harmonicity. + * + * This code is adopted from multiread, currently the only other + * multichannel suspension in Nyquist. Comments from multiread include: + * The susp is shared by all channels. The susp has backpointers + * to the tail-most snd_list node of each channel, and it is by + * extending the list at these nodes that sounds are read in. + * To avoid a circularity, the reference counts on snd_list nodes + * do not include the backpointers from this susp. When a snd_list + * node refcount goes to zero, the yin susp's free routine + * is called. This must scan the backpointers to find the node that + * has a zero refcount (the free routine is called before the node + * is deallocated, so this is safe). The backpointer is then set + * to NULL. When all backpointers are NULL, the susp itself is + * deallocated, because it can only be referenced through the + * snd_list nodes to which there are backpointers. + */ +void yin_fetch(yin_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + int togo = 0; + int n; + sample_block_type f0; + sample_block_values_type f0_ptr = NULL; + sample_block_type harmonicity; + sample_block_values_type harmonicity_ptr = NULL; + + register sample_block_values_type s_ptr_reg; + register sample_type *fillptr_reg; + register sample_type *endptr_reg = susp->endptr; + + if (susp->chan[0]) { + falloc_sample_block(f0, "yin_fetch"); + f0_ptr = f0->samples; + /* Since susp->chan[i] exists, we want to append a block of samples. + * The block, out, has been allocated. Before we insert the block, + * we must figure out whether to insert a new snd_list_type node for + * the block. Recall that before SND_get_next is called, the last + * snd_list_type in the list will have a null block pointer, and the + * snd_list_type's susp field points to the suspension (in this case, + * susp). When SND_get_next (in sound.c) is called, it appends a new + * snd_list_type and points the previous one to internal_zero_block + * before calling this fetch routine. On the other hand, since + * SND_get_next is only going to be called on one of the channels, the + * other channels will not have had a snd_list_type appended. + * SND_get_next does not tell us directly which channel it wants (it + * doesn't know), but we can test by looking for a non-null block in the + * snd_list_type pointed to by our back-pointers in susp->chan[]. If + * the block is null, the channel was untouched by SND_get_next, and + * we should append a snd_list_type. If it is non-null, then it + * points to internal_zero_block (the block inserted by SND_get_next) + * and a new snd_list_type has already been appended. + */ + /* Before proceeding, it may be that garbage collection ran when we + * allocated out, so check again to see if susp->chan[j] is Null: + */ + if (!susp->chan[0]) { + ffree_sample_block(f0, "yin_fetch"); + f0 = NULL; /* make sure we don't free it again */ + f0_ptr = NULL; /* make sure we don't output f0 samples */ + } else if (!susp->chan[0]->block) { + snd_list_type snd_list = snd_list_create((snd_susp_type) susp); + /* Now we have a snd_list to append to the channel, but a very + * interesting thing can happen here. snd_list_create, which + * we just called, MAY have invoked the garbage collector, and + * the GC MAY have freed all references to this channel, in which + * case yin_free(susp) will have been called, and susp->chan[0] + * will now be NULL! + */ + if (!susp->chan[0]) { + ffree_snd_list(snd_list, "yin_fetch"); + } else { + susp->chan[0]->u.next = snd_list; + } + } + /* see the note above: we don't know if susp->chan still exists */ + /* Note: We DO know that susp still exists because even if we lost + * some channels in a GC, someone is still calling SND_get_next on + * some channel. I suppose that there might be some very pathological + * code that could free a global reference to a sound that is in the + * midst of being computed, perhaps by doing something bizarre in the + * closure that snd_seq activates at the logical stop time of its first + * sound, but I haven't thought that one through. + */ + if (susp->chan[0]) { + susp->chan[0]->block = f0; + /* check some assertions */ + if (susp->chan[0]->u.next->u.susp != (snd_susp_type) susp) { + nyquist_printf("didn't find susp at end of list for chan 0\n"); + } + } else if (f0) { /* we allocated f0, but don't need it anymore due to GC */ + ffree_sample_block(f0, "yin_fetch"); + f0_ptr = NULL; + } + } + + /* Now, repeat for channel 1 (comments omitted) */ + if (susp->chan[1]) { + falloc_sample_block(harmonicity, "yin_fetch"); + harmonicity_ptr = harmonicity->samples; + if (!susp->chan[1]) { + ffree_sample_block(harmonicity, "yin_fetch"); + harmonicity = NULL; /* make sure we don't free it again */ + harmonicity_ptr = NULL; + } else if (!susp->chan[1]->block) { + snd_list_type snd_list = snd_list_create((snd_susp_type) susp); + if (!susp->chan[1]) { + ffree_snd_list(snd_list, "yin_fetch"); + } else { + susp->chan[1]->u.next = snd_list; + } + } + if (susp->chan[1]) { + susp->chan[1]->block = harmonicity; + if (susp->chan[1]->u.next->u.susp != (snd_susp_type) susp) { + nyquist_printf("didn't find susp at end of list for chan 1\n"); + } + } else if (harmonicity) { /* we allocated harmonicity, but don't need it anymore due to GC */ + ffree_sample_block(harmonicity, "yin_fetch"); + harmonicity_ptr = NULL; + } + } + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first, compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block */ + togo = (max_sample_block_len - cnt) * susp->stepsize; + + /* don't run past the s input sample block */ + susp_check_term_log_samples(s, s_ptr, s_cnt); + togo = min(togo, susp->s_cnt); + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo/susp->stepsize) { + togo = (susp->terminate_cnt - (susp->susp.current + cnt)) * susp->stepsize; + if (togo == 0) break; + } + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + /* break if to_stop = 0 (we're at the logical stop) + * AND cnt > 0 (we're not at the beginning of the output block) + */ + if (to_stop < togo/susp->stepsize) { + if (to_stop == 0) { + if (cnt) { + togo = 0; + break; + } else /* keep togo as is: since cnt == 0, we can set + * the logical stop flag on this output block + */ + susp->logically_stopped = true; + } else /* limit togo so we can start a new block a the LST */ + togo = to_stop * susp->stepsize; + } + } + n = togo; + s_ptr_reg = susp->s_ptr; + fillptr_reg = susp->fillptr; + if (n) do { /* the inner sample computation loop */ + *fillptr_reg++ = *s_ptr_reg++; + if (fillptr_reg >= endptr_reg) { + float f0; + float harmonicity; + yin_compute(susp, &f0, &harmonicity); + if (f0_ptr) *f0_ptr++ = f0; + if (harmonicity_ptr) *harmonicity_ptr++ = harmonicity; + cnt++; + fillptr_reg -= susp->stepsize; + } + } while (--n); /* inner loop */ + + /* using s_ptr_reg is a bad idea on RS/6000: */ + susp->s_ptr += togo; + susp->fillptr = fillptr_reg; + susp_took(s_cnt, togo); + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } + + /* test for logical stop */ + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* yin_fetch */ + + +void yin_mark(yin_susp_type susp) +{ + sound_xlmark(susp->s); +} + + +void yin_free(yin_susp_type susp) +{ + int j; + boolean active = false; +/* stdputstr("yin_free: "); */ + + for (j = 0; j < 2; j++) { + if (susp->chan[j]) { + if (susp->chan[j]->refcnt) active = true; + else { + susp->chan[j] = NULL; + /* nyquist_printf("deactivating channel %d\n", j); */ + } + } + } + if (!active) { +/* stdputstr("all channels freed, freeing susp now\n"); */ + ffree_generic(susp, sizeof(yin_susp_node), "yin_free"); + sound_unref(susp->s); + free(susp->block); + free(susp->temp); + } +} + + +void yin_print_tree(yin_susp_type susp, int n) +{ + indent(n); + stdputstr("s:"); + sound_print_tree_1(susp->s, n); +} + + +LVAL snd_make_yin(sound_type s, double low_step, double high_step, long stepsize) +{ + LVAL result; + int j; + register yin_susp_type susp; + rate_type sr = s->sr; + time_type t0 = s->t0; + + falloc_generic(susp, yin_susp_node, "snd_make_yin"); + susp->susp.fetch = yin_fetch; + susp->terminate_cnt = UNKNOWN; + + /* initialize susp state */ + susp->susp.free = yin_free; + susp->susp.sr = sr / stepsize; + susp->susp.t0 = t0; + susp->susp.mark = yin_mark; + susp->susp.print_tree = yin_print_tree; + susp->susp.name = "yin"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = logical_stop_cnt_cvt(s); + susp->susp.current = 0; + susp->s = s; + susp->s_cnt = 0; + susp->m = (long) (sr / step_to_hz(high_step)); + if (susp->m < 2) susp->m = 2; + /* add 1 to make sure we round up */ + susp->middle = (long) (sr / step_to_hz(low_step)) + 1; + susp->blocksize = susp->middle * 2; + susp->stepsize = stepsize; + /* blocksize must be at least step size to implement stepping */ + if (susp->stepsize > susp->blocksize) susp->blocksize = susp->stepsize; + susp->block = (sample_type *) malloc(susp->blocksize * sizeof(sample_type)); + susp->temp = (float *) malloc((susp->middle - susp->m + 1) * sizeof(float)); + susp->fillptr = susp->block; + susp->endptr = susp->block + susp->blocksize; + + xlsave1(result); + + result = newvector(2); /* create array for F0 and harmonicity */ + /* create sounds to return */ + for (j = 0; j < 2; j++) { + sound_type snd = sound_create((snd_susp_type)susp, + susp->susp.t0, susp->susp.sr, 1.0); + LVAL snd_lval = cvsound(snd); +/* nyquist_printf("yin_create: sound %d is %x, LVAL %x\n", j, snd, snd_lval); */ + setelement(result, j, snd_lval); + susp->chan[j] = snd->list; + } + xlpop(); + return result; +} + + +LVAL snd_yin(sound_type s, double low_step, double high_step, long stepsize) +{ + sound_type s_copy = sound_copy(s); + return snd_make_yin(s_copy, low_step, high_step, stepsize); +} diff --git a/nyqsrc/oldyin.h b/nyqsrc/oldyin.h new file mode 100644 index 0000000..656aa81 --- /dev/null +++ b/nyqsrc/oldyin.h @@ -0,0 +1,6 @@ +/* yin.h -- Nyquist code for F0 estimation using YIN approach */ + + +LVAL snd_yin(sound_type s, double low_step, double high_step, long stepsize); +/* LISP: (SND-YIN SOUND ANYNUM ANYNUM FIXNUM) */ + diff --git a/nyqsrc/phasevocoder.c b/nyqsrc/phasevocoder.c new file mode 100644 index 0000000..d446095 --- /dev/null +++ b/nyqsrc/phasevocoder.c @@ -0,0 +1,102 @@ +/* phasevocoder.c -- this is a stub showing how you might hook a + phase vocoder into Nyquist using pvshell + */ + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" + +#include "falloc.h" +#include "cext.h" +#include "pvshell.h" + +#include "phasevocoder.h" + +/* use the state[] info for sample interpolation */ +#define X_VALUE state[0] /* a parameter value */ +#define F_COUNT state[1] /* counts samples of f */ +#define G_COUNT state[2] /* counts samples of g */ +#define G_PREV state[3] /* previous value from g */ +#define G_NEXT state[4] /* next (current?) value from g */ +/* invariant: G_NEXT is the G_COUNT'th sample of g */ + +/* pv_fetch -- this is an example, but it doesn't really do + * phase vocoding. Instead, it will just multiply f, g, and x + * + * To make things a bit more interesting, we will assume g has + * an arbitrary sample rate with respect to f, and will interpolate. + * + */ +long pv_fetch(pvshell_type susp, + sample_block_values_type out, long *n) +{ + int i; + for (i = 0; i < *n; i++) { + long new_flags; + sample_type f; + double g; + /* NOTE: in DSP terms, this is poor code because of the + * division operations -- it could be made faster + */ + /* To get a value from g, first compute the time */ + double f_time = susp->F_COUNT / susp->f->sr; + /* Now compute g count that is past the time */ + double g_count = f_time * susp->g->sr; + while (susp->G_COUNT < g_count) { + PVSHELL_TEST_G(susp); /* prepare to get a sample */ + /* ignore flags from g -- we could, if we wanted, + * terminate when either f or g terminated, etc. + */ + susp->G_PREV = susp->G_NEXT; + susp->G_NEXT = PVSHELL_FETCH_G(susp); + susp->G_COUNT++; + } + /* now interpolate to get the value of g at f_time */ + g = susp->G_PREV + (susp->G_NEXT - susp->G_PREV) * + (g_count - (susp->G_COUNT - 1)); + new_flags = PVSHELL_TEST_F(susp); + susp->flags |= new_flags; + if (new_flags) break; + f = PVSHELL_FETCH_F(susp); + susp->F_COUNT++; /* count how many samples we have taken */ + + /* now we have f, g, x */ + *out++ = f * g * susp->X_VALUE; + } + /* i is the number of samples we acutally computed */ + *n = i; + /* if we computed samples, we want to return them before + * returning flags that say we're done or stopped + */ + return (i ? 0 : susp->flags); +} + + +sound_type snd_phasevocoder(sound_type f, sound_type g, double x) +{ + /* we're using 5 doubles of state. The first is a parameter, + * and the rest are initialized to zero except for state[2], + * aka G_COUNT. This is the number of samples we have read + * from G. Since we're interpolating we need a one-sample + * lookahead, and initializing the count to -1 causes an + * extra fetch and hence 1-sample lookahead. This state is copied + * into the pvshell structure, so we don't need to allocate + * a vector on the heap. + */ + double state[5] = {0, 0, -1, 0, 0}; + state[0] = x; + /* If f and g do not start at the same time, we should really + * should do something about it, but we'll just throw an error. + * Be careful to allow small differences (within one sample). + */ + if (fabs(f->t0 - g->t0) * f->sr > 0.5) { + xlfail("phasevocoder inputs must start at the same time"); + } + /* output the same sample rate and start time as f */ + return snd_make_pvshell("snd_phasevocoder", f->sr, f->t0, + &pv_fetch, f, g, + state, sizeof(state) / sizeof(state[0])); +} diff --git a/nyqsrc/phasevocoder.h b/nyqsrc/phasevocoder.h new file mode 100644 index 0000000..8d941b3 --- /dev/null +++ b/nyqsrc/phasevocoder.h @@ -0,0 +1,6 @@ +/* phasevocoder.h -- this is a stub showing how you might hook a + phase vocoder into Nyquist using pvshell + */ + +sound_type snd_phasevocoder(sound_type f, sound_type g, double x); + /* LISP: (snd-phasevocoder SOUND SOUND ANYNUM) */ diff --git a/nyqsrc/probe.c b/nyqsrc/probe.c new file mode 100644 index 0000000..9a04b4a --- /dev/null +++ b/nyqsrc/probe.c @@ -0,0 +1,38 @@ +/* probe.c -- used to test resampling */ + +#include "stdio.h" +#include "string.h" +#include "xlisp.h" + +static FILE* probefile = NULL; +static long line_num = 0; + +void probe_init(int readflag) +{ + line_num = 0; + probefile = fopen("probe.log", (readflag ? "r" : "w")); +} + + +double probe(char *s, double x) +{ + fprintf(probefile, "%s %g\n", s, x); + return x; +} + + +double probe2(char *s, double x) +{ + char buf1[100], buf2[100]; + sprintf(buf1, "%s %g\n", s, x); + fgets(buf2, 100, probefile); + line_num++; + if (strcmp(buf1, buf2)) { + nyquist_printf("probe2: difference at line %ld: \n", line_num); + nyquist_printf("correct: %s", buf2); + nyquist_printf("actual: %s", buf1); + abort(); + } + return x; +} + diff --git a/nyqsrc/probe.h b/nyqsrc/probe.h new file mode 100644 index 0000000..ca727d6 --- /dev/null +++ b/nyqsrc/probe.h @@ -0,0 +1,6 @@ +/* probe.h -- used to test resampling */ + +void probe_init(int readflag); +double probe(char *s, double x); +double probe2(char *s, double x); + diff --git a/nyqsrc/pvshell.c b/nyqsrc/pvshell.c new file mode 100644 index 0000000..e281649 --- /dev/null +++ b/nyqsrc/pvshell.c @@ -0,0 +1,202 @@ +// pvshell.c -- This is a skeleton for a Nyquist primitive that +// returns a sound. The sound is obtained by calling a function +// with a request consisting of a location to put samples and +// a count of how many samples are needed. The function returns +// the actual number of samples computed and flags indicating +// if the signal has reached the logical stop or termination. +// In addition, there are interfaces for extracting samples +// from input sounds. +// This code is designed for a time-stretching phase vocoder, +// but could be used for other purposes. It is derived from +// compose.c, which might have been implmented with this +// skeleton had we started out with this abstraction. + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" + +#include "falloc.h" +#include "cext.h" +#include "pvshell.h" +#include "assert.h" + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +void pvshell_free(); + + +typedef struct pvshell_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + boolean started; + + pvshell_node pvshell; +} pvshell_susp_node, *pvshell_susp_type; + + +/* pvshell_test_f -- get next sample block and check flags + * + * Only call this from PVSHELL_TEST_F macro + */ +long pvshell_test_f(pvshell_type susp) +{ + long flags = 0; + susp_get_samples(f, f_ptr, f_cnt); /* warning: macro references susp */ + if (susp->f->logical_stop_cnt == susp->f->current - susp->f_cnt) { + flags |= PVSHELL_FLAG_LOGICAL_STOP; + } + if (susp->f_ptr == zero_block->samples) { + flags |= PVSHELL_FLAG_TERMINATE; + } + return flags; +} + + +/* pvshell_test_g -- get next sample block and check flags + * + * Only call this from PVSHELL_TEST_G macro + */ +long pvshell_test_g(pvshell_type susp) +{ + long flags = 0; + susp_get_samples(g, g_ptr, g_cnt); /* warning: macro references susp */ + if (susp->g->logical_stop_cnt == susp->g->current - susp->g_cnt) { + flags |= PVSHELL_FLAG_LOGICAL_STOP; + } + if (susp->g_ptr == zero_block->samples) { + flags |= PVSHELL_FLAG_TERMINATE; + } + return flags; +} + + +/* pvshell_fetch -- computes h(f, g, x, y) where f and g are + * sounds, x and y are doubles, and h implemented via a function + * pointer. This could certainly be generalized further, but + * maybe we should take this one step at a time. +/**/ +void pvshell_fetch(register pvshell_susp_type susp, snd_list_type snd_list) +{ + long n, flags; + sample_block_type out; + sample_block_values_type out_ptr; + + falloc_sample_block(out, "pvshell_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + /* don't run past the f input sample block: */ + /* most fetch routines call susp_check_term_log_samples() here + * but we can't becasue susp_check_term_log_samples() assumes + * that output time progresses at the same rate as input time. + * Here, some time warping might be going on, so this doesn't work. + * It is up to the user to tell us when it is the logical stop + * time and the terminate time. + */ + /* don't run past terminate time */ + // if (susp->terminate_cnt != UNKNOWN && + // susp->terminate_cnt <= susp->susp.current + cnt + togo) { + // togo = susp->terminate_cnt - (susp->susp.current + cnt); + // if (togo == 0) break; + // } + /* don't run past logical stop time */ + // if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + // int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + // if (to_stop < togo && ((togo = to_stop) == 0)) break; + // } + n = max_sample_block_len; // ideally, compute a whole block of samples + + flags = (susp->pvshell.h)(&(susp->pvshell), out_ptr, &n); + + /* test for termination */ + if (flags & PVSHELL_FLAG_TERMINATE) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = n; + susp->susp.current += n; + } + /* test for logical stop */ + if (flags & PVSHELL_FLAG_LOGICAL_STOP || susp->logically_stopped) { + snd_list->logically_stopped = true; + susp->logically_stopped = true; + } +} /* pvshell_fetch */ + + +void pvshell_mark(pvshell_susp_type susp) +{ + sound_xlmark(susp->pvshell.f); + sound_xlmark(susp->pvshell.g); +} + + +void pvshell_free(pvshell_susp_type susp) +{ + /* note that f or g can be NULL */ + sound_unref(susp->pvshell.f); + sound_unref(susp->pvshell.g); + ffree_generic(susp, sizeof(pvshell_susp_node), "pvshell_free"); +} + + +void pvshell_print_tree(pvshell_susp_type susp, int n) +{ + indent(n); + stdputstr("f:"); + sound_print_tree_1(susp->pvshell.f, n); + + indent(n); + stdputstr("g:"); + sound_print_tree_1(susp->pvshell.g, n); +} + + +sound_type snd_make_pvshell(char *name, rate_type sr, time_type t0, + h_fn_type h, sound_type f, sound_type g, + double *state, long n) +{ + register pvshell_susp_type susp; + int i; + + falloc_generic(susp, pvshell_susp_node, "snd_make_pvshell"); + susp->susp.fetch = pvshell_fetch; + susp->terminate_cnt = UNKNOWN; + + /* initialize susp state */ + susp->susp.free = pvshell_free; + susp->susp.sr = sr; + susp->susp.t0 = t0; + susp->susp.mark = pvshell_mark; + susp->susp.print_tree = pvshell_print_tree; + susp->susp.name = name; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = UNKNOWN; + susp->susp.current = 0; + + /* copy the sound so that we have a private "reader" object */ + susp->pvshell.f = (f ? sound_copy(f) : f); + susp->pvshell.f_cnt = 0; + + susp->pvshell.g = (g ? sound_copy(g) : g); + susp->pvshell.g_cnt = 0; + + susp->pvshell.h = h; + + susp->pvshell.flags = 0; /* terminated and logically stopped flags -- these + are for the client of pvshell to use */ + + assert(n <= PVSHELL_STATE_MAX); + for (i = 0; i < n; i++) { + susp->pvshell.state[i] = state[i]; + } + + susp->started = false; + return sound_create((snd_susp_type)susp, t0, sr, 1.0); +} diff --git a/nyqsrc/pvshell.h b/nyqsrc/pvshell.h new file mode 100644 index 0000000..6e925fb --- /dev/null +++ b/nyqsrc/pvshell.h @@ -0,0 +1,90 @@ +/* pvshell.h -- a generic Nyquist primitive, esp. for phase vocoder */ + +/* how many doubles to provide for miscellaneous state info */ +#define PVSHELL_STATE_MAX 8 + +/* define some bits to return conditions */ +#define PVSHELL_FLAG_TERMINATE 4 +#define PVSHELL_FLAG_LOGICAL_STOP 8 + +/* this function is called to compute samples. It should compute n + * samples (floats == sample_type) and store them at out[i]. + * You can return less than n samples by writing the actual number + * of samples computed into *n. Normally, you return zero. + * To indicate that the time of the FIRST sample is the logical stop + * time, return PVSHELL_FLAG_LOGICAL_STOP. (If the logical stop time + * is not at the first sample, but instead at sample j, then just + * return j samples (from 0 to j-1), save the rest of the samples, + * and the next time, the first sample will correspond to the logical + * stop time, so you can return PVSHELL_FLAG_LOGICAL_STOP. + * To indicate that the sound has terminated, return + * PVSHELL_FLAG_TERMINATE. This should be the only time you return + * zero samples. (As with logical stop time, if you have samples to + * return before termination, then do it, and return + * PVSHELL_FLAG_TERMINATE the next time you are called, at which + * point you've returned all the samples, so you can set *n = 0. + */ +struct pvshell_struct; + +typedef long (*h_fn_type)(struct pvshell_struct *susp, + sample_block_values_type out, long *n); + +typedef struct pvshell_struct { + sound_type f; + long f_cnt; + sample_block_values_type f_ptr; + + sound_type g; + long g_cnt; + sample_block_values_type g_ptr; + + long flags; /* for terminated and logically stopped flags */ + + // state is extra storage for whatever you like + double state[PVSHELL_STATE_MAX]; + + // h is a function that computes sound from f, g, x, y, state + h_fn_type h; +} pvshell_node, *pvshell_type; + + +/* to get samples from f or g, use these macros. For each sample, call + * PVSHELL_TEST_X to get logical stop and terminate flags (but do not + * fetch a sample). Then, if you want, call PVSHELL_FETCH_X to get the + * next sample. You can call PVSHELL_TEST_X multiple times before + * calling PVSHELL_FETCH_X, e.g. you can return exit a loop when you + * see a logical stop flag and later call PVSHELL_TEST_X again. You + * CANNOT call PVSHELL_FETCH_X multiples times without an intervening + * call to PVSHELL_TEST_X. Finally, the logical stop flag is only + * returned once. Normally you should write something like: + * new_flags = PVSHELL_TEST_F(susp); + * susp->flags | = new_flags; // remember flags + * if (new_flags) break; + * in the sample loop so that you will break when you see logical_stop. + * Outside the loop, you can return (*n ? 0 : susp->flags) which will + * return 0 if you computed samples before the logical stop was detected. + * Then the next time you are called, you will return the logical_stop + * flag because you saved it in susp->flags, and the flag applies to the + * *beginning* of the sample block. This code handles terminate too. + */ +#define PVSHELL_TEST_F(susp) ((susp)->f_cnt == 0 ? pvshell_test_f(susp) : 0) +#define PVSHELL_FETCH_F(susp) ((susp)->f_cnt--, (*(susp)->f_ptr++)) + +#define PVSHELL_TEST_G(susp) ((susp)->g_cnt == 0 ? pvshell_test_g(susp) : 0) +#define PVSHELL_FETCH_G(susp) ((susp)->g_cnt--, (*(susp)->g_ptr++)) + +/* snd_make_pvshell -- create an instance of pvshell. + name -- string name of the operation, for debugging & printing + (name is not copied. It must be a permanent, immutable string.) + sr -- sample rate of output sound + t0 -- start time of output sound + h -- function that computes samples of output + f -- first input sound, e.g. sound to be time-stretched + g -- second input sound, e.g. sound to control varying stretch factor + state -- initial state information needed by h + n -- number of doubles in state (< PVSHELL_STATE_MAX) +*/ +sound_type snd_make_pvshell(char *name, rate_type sr, time_type t0, + h_fn_type h, sound_type f, sound_type g, + double *state, long n); + diff --git a/nyqsrc/resamp.c b/nyqsrc/resamp.c new file mode 100644 index 0000000..e02e344 --- /dev/null +++ b/nyqsrc/resamp.c @@ -0,0 +1,348 @@ +/* resamp.c -- resample signal using sinc interpolation */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm min->MIN, max->MAX + */ + + + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "assert.h" + +#include "falloc.h" +#include "cext.h" +#include "resamp.h" +#include "fresample.h" +#include "ffilterkit.h" +#include "fsmallfilter.h" + +/* Algorithm: + To resample, we convolve a sinc function with the input stream at +times corresponding to the output samples. This requires a sliding +window on the input samples. Since samples are accessed a block at a +time, the places where the sliding window would span two blocks are +too tricky for me. Instead of trying to manage the breaks across +blocks, I copy the blocks into another buffer (called X). When the +sliding window reaches the end of X, the samples at the end of X +are copied to the beginning of X, the remainder of X is filled with +new samples, and the computation continues. The trickiest part of +all this is keeping all the pointers and phase accumulators correct +when the sliding window is relocated from the end of X to the +beginning. + Although there are different ways to do this, I decided that the +output would always go directly to a Nyquist sample block, so the +resampling routines (SrcUp and SrcUD) are always called upon to +compute max_sample_block_len samples (except that a partial block +may be computed when the input sound terminates). + To compute max_sample_block_len samples, the input buffer needs: + + - max_sample_block_len/factor samples, where factor is the ratio of + the new sample rate to the old one. I.e. if upsampling by a factor + of 2, the input buffer needs half the samples of the output block + size. + + - additional samples the size of the sliding window. Since the + output is taken from the center of the window, we can't take + samples from the first or last windowsize/2 samples. + + - to simplify rounding, we throw in some extra samples. This costs + only a bit of space and an extra copy for each spare sample. + + The window size is determined by the particular filter used and +by factor (the sample rate ratio). The filter size is Nmult, the +number of filter coefficients. When upsampling, this is the window +size (the filter acts as a reconstruction filter for the additional +samples). When downsampling, the filter is stretched by 1/factor +(the filter acts as an anti-aliasing low-pass filter). + +*/ + +void resample_free(); + +typedef struct resample_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + sound_type s; + long s_cnt; + sample_block_values_type s_ptr; + float *X; + long Xsize; + double Time; /* location (offset) in X of next output sample */ + double LpScl; + double factor; + sample_type *Imp; + sample_type *ImpD; + boolean interpFilt; + int Nmult; + int Nwing; + int Xp; /* first free location at end of X */ + int Xoff; /* number of extra samples at beginning and end of X */ +} resample_susp_node, *resample_susp_type; + +/* Sampling rate up-conversion only subroutine; + * Slightly faster than down-conversion; + */ +static int SrcUp(float X[], float Y[], double factor, double *Time, + int Nx, int Nwing, double LpScl, + float Imp[], float ImpD[], boolean Interp) +{ + mem_float *Xp, *Ystart; + fast_float v; + + double dt; /* Step through input signal */ + mem_float *Yend; /* When Y reaches Yend, return to user */ + +/* nyquist_printf("SrcUp: interpFilt %d\n", Interp);*/ + + dt = 1.0/factor; /* Output sampling period */ + + Ystart = Y; + Yend = Y + Nx; + while (Y < Yend) { + long iTime = (long) *Time; + Xp = &X[iTime]; /* Ptr to current input sample */ + /* Perform left-wing inner product */ + v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, *Time - iTime, -1); + /* Perform right-wing inner product */ + v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, + (1 + iTime) - *Time, 1); + v *= LpScl; /* Normalize for unity filter gain */ +/* nyquist_printf("SrcUp output sample %g\n", v); */ + *Y++ = (float) v; + *Time += dt; /* Move to next sample by time increment */ + } + return (Y - Ystart); /* Return the number of output samples */ +} + + +/* Sampling rate conversion subroutine */ + +static int SrcUD(float X[], float Y[], double factor, double *Time, + int Nx, int Nwing, double LpScl, + float Imp[], float ImpD[], boolean Interp) +{ + mem_float *Xp, *Ystart; + fast_float v; + + double dh; /* Step through filter impulse response */ + double dt; /* Step through input signal */ + mem_float *Yend; /* When Y reaches Yend, return to user */ + + dt = 1.0/factor; /* Output sampling period */ + + dh = MIN(Npc, factor*Npc); /* Filter sampling period */ + + Ystart = Y; + Yend = Y + Nx; + while (Y < Yend) { + long iTime = (long) *Time; + Xp = &X[iTime]; /* Ptr to current input sample */ + v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, *Time - iTime, + -1, dh); /* Perform left-wing inner product */ + v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (1 + iTime) - *Time, + 1, dh); /* Perform right-wing inner product */ + v *= LpScl; /* Normalize for unity filter gain */ + *Y++ = (float) v; + *Time += dt; /* Move to next sample by time increment */ + } + return (Y - Ystart); /* Return the number of output samples */ +} + + +void resample__fetch(register resample_susp_type susp, snd_list_type snd_list) +{ + int togo; + int n; + int Nout; + sample_block_type out; + /* note that in this fetch routine, out_ptr is used to remember where + * to put the "real" output, while X_ptr_reg is used in the inner + * loop that copies input samples into X, a buffer + */ + register sample_block_values_type out_ptr; + register sample_block_values_type X_ptr_reg; + + register sample_type *s_ptr_reg; + falloc_sample_block(out, "resample__fetch"); + out_ptr = out->samples; + snd_list->block = out; + +/* Algorithm: + Fetch samples until X (the buffered input) is full. X stores enough +contiguous samples that a sliding window convolving with the filter +coefficients can output a full block without sliding beyond the range +of X. Every time we reenter resample__fetch, we take the remaining +samples at the end of X, shift them to the beginning, and refill. + After X is full, call on SrcUp or SrcUD to compute an output block. + The first time resample__fetch is called, the fill pointer Xp will +point near the beginning of X, indicating that no previously read +samples need to be shifted from the end of X to the beginning. +*/ + + /* first, shift samples from end of X to beginning if necessary */ + if (susp->Xp > 2 * susp->Xoff) { + int i; + int shiftcount = (long) (susp->Time) - susp->Xoff; + +/* nyquist_printf("shift %d from %d to %lx\n", susp->Xsize + susp->Xoff - susp->Xp, susp->Xp - susp->Xoff, susp->X); */ + for (i = 0; i < susp->Xp - shiftcount; i++) { + susp->X[i] = susp->X[i + shiftcount]; +/* if (susp->X[i] == 0.0) nyquist_printf("shifted zero to X[%d]\n", i);*/ + } + susp->Time -= shiftcount; + susp->Xp -= shiftcount; + } + + while (susp->Xp < susp->Xsize) { /* outer loop */ + /* read samples from susp->s into X */ + togo = susp->Xsize - susp->Xp; + /* don't run past the s input sample block. If termination or + * logical stop info become available, translate to susp->terminate_cnt + * and susp->log_stop_cnt. + */ + susp_check_term_log_samples(s, s_ptr, s_cnt); + togo = MIN(togo, susp->s_cnt); + + memcpy(susp->X + susp->Xp, susp->s_ptr, togo * sizeof(sample_type)); + susp->s_ptr += togo; + susp_took(s_cnt, togo); + susp->Xp += togo; + } /* outer loop */ + + /* second, compute samples to output, this is done in one pass because + * we have enough data in X + */ + + /* don't run past terminate time */ + togo = max_sample_block_len; + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + max_sample_block_len) { + togo = susp->terminate_cnt - susp->susp.current; + } + if (!susp->logically_stopped && + susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - susp->susp.current; + assert(to_stop >= 0); + if (to_stop < togo) { + if (to_stop == 0) susp->logically_stopped = true; + else togo = to_stop; + } + } + if (togo == 0) { +/* stdputstr("resamp calling snd_list_terminate\n"); */ + snd_list_terminate(snd_list); + } else { + if (susp->factor >= 1) { /* SrcUp() is faster if we can use it */ + Nout = SrcUp(susp->X, out_ptr, susp->factor, &susp->Time, + togo, susp->Nwing, susp->LpScl, susp->Imp, + susp->ImpD, susp->interpFilt); + } else { + Nout = SrcUD(susp->X, out_ptr, susp->factor, &susp->Time, + togo, susp->Nwing, susp->LpScl, susp->Imp, + susp->ImpD, susp->interpFilt); + } + snd_list->block_len = togo; + susp->susp.current += togo; + } +#ifdef RESAMPTEST + for (n = 0; n < snd_list->block_len; n++) { + if (out->samples[n] == 0.0) { + nyquist_printf("resamp: zero at samples[%d]\n", n); + } + } +#endif +/* + if (susp->logically_stopped) { + snd_list->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } + */ +} /* resample__fetch */ + + +void resample_mark(resample_susp_type susp) +{ + sound_xlmark(susp->s); +} + + +void resample_free(resample_susp_type susp) +{ + sound_unref(susp->s); + free(susp->X); + ffree_generic(susp, sizeof(resample_susp_node), "resample_free"); +} + + +void resample_print_tree(resample_susp_type susp, int n) +{ + indent(n); + stdputstr("s:"); + sound_print_tree_1(susp->s, n); +} + + +sound_type snd_make_resample(sound_type s, rate_type sr) +{ + register resample_susp_type susp; + int i; + + falloc_generic(susp, resample_susp_node, "snd_make_resample"); + susp->susp.fetch = resample__fetch; + + susp->Nmult = SMALL_FILTER_NMULT; + susp->Imp = SMALL_FILTER_IMP; + susp->ImpD = SMALL_FILTER_IMPD; + /* these scale factors are here because filter coefficients + are expressed as integers, and so is SMALL_FILTER_SCALE: */ + susp->LpScl = SMALL_FILTER_SCALE / 32768.0; + susp->LpScl /= 16384.0; + /* this is just a fudge factor, is SMALL_FILTER_SCALE wrong? */ + susp->LpScl /= 1.0011; + + susp->Nwing = SMALL_FILTER_NWING; + susp->factor = sr / s->sr; + if (susp->factor < 1) susp->LpScl *= susp->factor; + + /* factor in the scale factor of s, since resample is linear */ + susp->LpScl *= s->scale; + + susp->terminate_cnt = UNKNOWN; + /* initialize susp state */ + susp->susp.free = resample_free; + susp->susp.sr = sr; + susp->susp.t0 = s->t0; + susp->susp.mark = resample_mark; + susp->susp.print_tree = resample_print_tree; + susp->susp.name = "resample"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = logical_stop_cnt_cvt(s); + susp->susp.current = 0; + susp->s = s; + susp->s_cnt = 0; + susp->Xoff = (int) (((susp->Nmult + 1) / 2.0) * MAX(1.0, 1.0 / susp->factor) + 10); + susp->Xsize = (long) ((max_sample_block_len / susp->factor) + 2 * susp->Xoff); + susp->X = calloc(susp->Xsize, sizeof(sample_type)); + susp->Xp = susp->Xoff; + susp->Time = susp->Xoff; + susp->interpFilt = true; + for (i = 0; i < susp->Xoff; i++) susp->X[i] = 0.0F; + + return sound_create((snd_susp_type)susp, susp->susp.t0, + susp->susp.sr, 1.0 /* scale factor */); +} + + +sound_type snd_resample(sound_type s, rate_type sr) +{ + sound_type s_copy = sound_copy(s); + return snd_make_resample(s_copy, sr); +} diff --git a/nyqsrc/resamp.h b/nyqsrc/resamp.h new file mode 100644 index 0000000..4f390b8 --- /dev/null +++ b/nyqsrc/resamp.h @@ -0,0 +1,3 @@ +sound_type snd_make_resample(sound_type s, rate_type sr); +sound_type snd_resample(sound_type s, rate_type sr); + /* LISP: (snd-resample SOUND ANYNUM) */ diff --git a/nyqsrc/resampv.c b/nyqsrc/resampv.c new file mode 100644 index 0000000..67dcf7b --- /dev/null +++ b/nyqsrc/resampv.c @@ -0,0 +1,394 @@ +/* resampv.c -- use sinc interpolation to resample at a time-varying sample rate */ + + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm min->MIN, max->MAX + */ + + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" + +#include "falloc.h" +#include "cext.h" +#include "resampv.h" +#include "fresample.h" +#include "ffilterkit.h" +#include "fsmallfilter.h" +#include "assert.h" + + +/* Algorithm: + First compute a factor = ratio of new sample rate to original sample rate. + We have Time, the offset into X + We want Xoff = ((susp->Nmult + 1) / 2.0) * MAX(1.0, 1.0 / factor) + 10 + samples on either side of Time before we interpolate. + If Xoff * 2 > Xsize, then we're in trouble because X is not big enough. + Assume this is a pathalogical case, raise the cutoff frequency to + reduce Xoff to less than Xsize/2. + If Time is too small, then we're in trouble because we've lost the + beginning of the buffer. Raise the cutoff frequency until Xoff is + less than Time. This should only happen if factor suddenly drops. + If Time is too big, we can handle it: shift X down and load X with new + samples. When X is shifted by N samples, N is subtracted from Time. + To minimize the "Time is too small" case, don't shift too far: leave + a cushion of Xoff * 2 samples rather than the usual Xoff. + + Now compute a sample at Time using SrcUD and output it. + + What is Time? + Time is the offset into X, so Time is g_of_now - (sum of all X shifts) + So, let Time = g_of_now - shift_sum + Whenever shift_sum or g_of_now is updated, recompute Time + + To compute the next g_of_now, do a lookup of g at now + 1/sr, + using linear interpolation (be sure to do computation with + doubles to minimize sampling time jitter). + + */ + +/* maximum ratio for downsampling (downsampling will still take place, + * but the lowest prefilter cutoff frequency will be + * (original_sample_rate/2) / MAX_FACTOR_INVERSE + */ +#define MAX_FACTOR_INVERSE 64 + +typedef struct resamplev_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + sound_type f; + long f_cnt; + sample_block_values_type f_ptr; + + sound_type g; + long g_cnt; + sample_block_values_type g_ptr; + double prev_g; /* data for interpolation: */ + double next_g; + double phase_in_g; + double phase_in_g_increment; + double g_of_now; + + float *X; + long Xsize; + double Time; /* location (offset) in X of next output sample */ + double shift_sum; /* total amount by which we have shifted X; also, the + sample number of X[0] */ + double LpScl; + double factor_inverse; /* computed at every sample from g */ + /* this is the amount by which we step through the input signal, so + factor_inverse is the output_sample_rate / input_sample_rate, and + factor is the input_sample_rate / output_sample_rate. Alternatively, + factor is the amount to downsample and + factor_inverse is the amount to upsample. */ + /* double factor; -- computed from factor_inverse */ + sample_type *Imp; + sample_type *ImpD; + boolean interpFilt; + int Nmult; + int Nwing; + int Xp; /* first free location at end of X */ + int Xoff; /* number of extra samples at beginning and end of X */ +} resamplev_susp_node, *resamplev_susp_type; + +void resamplev_free(); +void resampv_refill(resamplev_susp_type susp); + +/* Sampling rate conversion subroutine + * Note that this is not the same as SrcUD in resamp.c! + * X[] is the input signal to be resampled, + * dt is the ratio of sample rates; when dt=1, the skip size is + * Npc/dt = Npc, where Npc is how many filter coefficients to + * get the cutoff frequency equal to the Nyquist rate. As dt + * gets larger, we step through the filter more slowly, so low-pass + * filtering occurs. As dt gets smaller, it is X[] that limits + * frequency, and we use the filter to interpolate samples (upsample). + * Therefore, dt>1 means downsample, dt<1 means upsample. + * dt is how much we increment Time to compute each output sample. + * Time is the offset in samples, including fractional samples, of X + * Nwing is the size of one wing of the filter + * LpScl is a corrective scale factor to make the gain == 1 or whatever + * (Nyquist uses a gain of 0.95 to minimize clipping when peaks are + * interpolated.) + * Imp[] and ImpD[] are the filter coefficient table and table differences + * (for interpolation) + * Interp is true to interpolate filter coefficient lookup + */ +static float SrcUD(float X[], double dt, double Time, + int Nwing, double LpScl, + float Imp[], float ImpD[], boolean Interp) +{ + mem_float *Xp; + fast_float v; + + double dh; /* Step through filter impulse response */ + long iTime = (long) Time; + + dh = MIN(Npc, Npc/dt); /* Filter sampling period */ + + Xp = &X[iTime]; /* Ptr to current input sample */ + v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, Time - iTime, + -1, dh); /* Perform left-wing inner product */ + v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (1 + iTime) - Time, + 1, dh); /* Perform right-wing inner product */ + v *= LpScl; /* Normalize for unity filter gain */ + return (float) v; +} + + +void resamplev__fetch(register resamplev_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + sample_block_type out; + /* note that in this fetch routine, out_ptr is used to remember where + * to put the "real" output, while X_ptr_reg is used in the inner + * loop that copies input samples into X, a buffer + */ + register sample_block_values_type out_ptr; + + falloc_sample_block(out, "resamplev__fetch"); + out_ptr = out->samples; + snd_list->block = out; + + + while (cnt < max_sample_block_len) { /* outer loop */ + /* fetch g until we have points to interpolate */ + while (susp->phase_in_g >= 1.0) { + susp->prev_g = susp->next_g; + if (susp->g_cnt == 0) { + susp_get_samples(g, g_ptr, g_cnt); + if (susp->g->logical_stop_cnt == susp->g->current - susp->g_cnt) { + if (susp->susp.log_stop_cnt == UNKNOWN) { + susp->susp.log_stop_cnt = susp->susp.current + cnt; + } + } + if (susp->g_ptr == zero_block->samples && + susp->terminate_cnt == UNKNOWN) { + susp->terminate_cnt = susp->susp.current + cnt; + } + } + susp->next_g = susp_fetch_sample(g, g_ptr, g_cnt); + susp->phase_in_g -= 1.0; + + if (susp->next_g < susp->prev_g) { + susp->next_g = susp->prev_g; // prevent time from going backward + } + /* factor_inverse = 1/factor = how many samples of f per + * output sample = change-in-g / output-samples-per-g-sample + * = change-in-g * phase_in_g_increment + */ + susp->factor_inverse = susp->phase_in_g_increment * + (susp->next_g - susp->prev_g); + if (susp->factor_inverse > MAX_FACTOR_INVERSE) + susp->factor_inverse = MAX_FACTOR_INVERSE; + + /* update Xoff, which depends upon factor_inverse: */ + susp->Xoff = (int) (((susp->Nmult + 1) / 2.0) * + MAX(1.0, susp->factor_inverse)) + 10; + if (susp->Xoff * 2 > susp->Xsize) { + /* bad because X is not big enough for filter, so we'll + * raise the cutoff frequency as necessary + */ + susp->factor_inverse = ((susp->Xsize / 2) - 10 ) / + ((susp->Nmult + 1) / 2.0); + susp->Xoff = (susp->Xsize / 2) - 2 /* fudge factor */; + } + } + susp->g_of_now = susp->prev_g + + susp->phase_in_g * (susp->next_g - susp->prev_g); + susp->Time = susp->g_of_now - susp->shift_sum; + susp->phase_in_g += susp->phase_in_g_increment; + + /* now we have a position (g_of_now) and a factor */ + /* See if enough of f is in X */ + if (susp->Xoff > susp->Time) { + /* there are not enough samples before Time in X, so + * modify factor_inverse to fix it + */ + susp->factor_inverse = (susp->Time - 10.0) / + ((susp->Nmult + 1) / 2.0); + + } else if ((susp->Xsize - susp->Xoff) < susp->Time) { + /* Time is too close to the end of the buffer, slide the samples + down. If there's room, leave 2*Xoff samples at beginning of + * buffer. Otherwise leave as little as Xoff: */ + int i, dist, ntime; + ntime = susp->Xoff * 2; /* shift Time near to this index in X */ + dist = ((int) susp->Time) - ntime; + if (dist < 1 && (ntime * 2 < susp->Xsize)) { + /* not enough room, so leave at least Xoff. */ + ntime = susp->Xoff; + if (susp->Xsize / 2 - ntime > 2) { + /* There is some extra space. Use half to extend ntime, allowing + for a possible increase in Xoff that will require more history; + the other half reduces the amount of buffer copying needed. */ + ntime += (susp->Xsize / 2 - ntime) / 2; + } + dist = ((int) susp->Time) - ntime; + } + /* shift everything in X by dist, adjust Time etc. */ + for (i = 0; i < susp->Xsize - dist; i++) { + susp->X[i] = susp->X[i + dist]; + } + susp->Xp -= dist; + resampv_refill(susp); + susp->shift_sum += dist; + susp->Time = susp->g_of_now - susp->shift_sum; + } + + /* second, compute a sample to output */ + + /* don't run past terminate time */ + if (susp->terminate_cnt == susp->susp.current + cnt) { + snd_list->block_len = cnt; + if (cnt > 0) { + susp->susp.current += cnt; + snd_list = snd_list->u.next; + snd_list->u.next = snd_list_create(&susp->susp); + snd_list->block = internal_zero_block; + snd_list_terminate(snd_list); + } else { + snd_list_terminate(snd_list); + } + return; + } else { + double scale = susp->LpScl; + float tmp; + if (susp->factor_inverse > 1) scale /= susp->factor_inverse; + tmp = SrcUD(susp->X, susp->factor_inverse, + susp->Time, susp->Nwing, scale, susp->Imp, + susp->ImpD, susp->interpFilt); + *out_ptr++ = tmp; + } + cnt++; + } + snd_list->block_len = cnt; + susp->susp.current += cnt; + assert(cnt > 0); +} /* resamplev__fetch */ + + +void resampv_refill(resamplev_susp_type susp) { + int togo, n; + register sample_type *f_ptr_reg; + register sample_type *X_ptr_reg; + + while (susp->Xp < susp->Xsize) { /* outer loop */ + + /* read samples from susp->f into X */ + togo = susp->Xsize - susp->Xp; + + /* don't run past the f input sample block: */ + susp_check_samples(f, f_ptr, f_cnt); + togo = MIN(togo, susp->f_cnt); + + n = togo; + f_ptr_reg = susp->f_ptr; + X_ptr_reg = &(susp->X[susp->Xp]); + if (n) do { /* the inner sample computation loop */ + *X_ptr_reg++ = *f_ptr_reg++; + } while (--n); /* inner loop */ + + /* using f_ptr_reg is a bad idea on RS/6000: */ + susp->f_ptr += togo; + susp_took(f_cnt, togo); + susp->Xp += togo; + } /* outer loop */ +} + + + +void resamplev_mark(resamplev_susp_type susp) +{ + sound_xlmark(susp->f); + sound_xlmark(susp->g); +} + + +void resamplev_free(resamplev_susp_type susp) +{ + sound_unref(susp->f); + sound_unref(susp->g); + free(susp->X); + ffree_generic(susp, sizeof(resamplev_susp_node), "resamplev_free"); +} + + +void resamplev_print_tree(resamplev_susp_type susp, int n) +{ + indent(n); + nyquist_printf("f:"); + sound_print_tree_1(susp->f, n); + + indent(n); + nyquist_printf("g:"); + sound_print_tree_1(susp->g, n); +} + + +sound_type snd_make_resamplev(sound_type f, rate_type sr, sound_type g) +{ + register resamplev_susp_type susp; + int i; + + falloc_generic(susp, resamplev_susp_node, "snd_make_resamplev"); + susp->susp.fetch = resamplev__fetch; + + susp->Nmult = SMALL_FILTER_NMULT; + susp->Imp = SMALL_FILTER_IMP; + susp->ImpD = SMALL_FILTER_IMPD; + susp->LpScl = SMALL_FILTER_SCALE / 32768.0; + susp->LpScl /= 16384.0; + /* this is just a fudge factor, is SMALL_FILTER_SCALE wrong? */ + susp->LpScl /= 1.0011; + susp->Nwing = SMALL_FILTER_NWING; + + susp->terminate_cnt = UNKNOWN; + /* initialize susp state */ + susp->susp.free = resamplev_free; + susp->susp.sr = sr; + susp->susp.t0 = f->t0; + susp->susp.mark = resamplev_mark; + susp->susp.print_tree = resamplev_print_tree; + susp->susp.name = "resamplev"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = logical_stop_cnt_cvt(f); + susp->susp.current = 0; + susp->f = f; + susp->f_cnt = 0; + susp->g = g; + susp->g_cnt = 0; + susp->next_g = 0; + susp->phase_in_g_increment = g->sr / sr; + susp->phase_in_g = 2.0; + /* can't use susp->factor because it is unknown and variable */ + /* assume at most a down-sample by a factor of 2.0 and compute Xoff accordingly */ + susp->Xoff = (int) (((susp->Nmult + 1) / 2.0) * 2.0) /* MAX(1.0, 1.0 / susp->factor) */ + 10; + /* this size is not critical unless it is too small */ + /* allow the block size plus a buffer of 2*Xoff at both ends for the tails of the filter */ + susp->Xsize = max_sample_block_len + 4 * susp->Xoff; + susp->X = calloc(susp->Xsize, sizeof(sample_type)); + susp->Xp = susp->Xsize; + susp->shift_sum = -susp->Xsize; + susp->interpFilt = true; + for (i = 0; i < susp->Xoff; i++) susp->X[i] = 0.0F; + susp->LpScl *= 0.95; /* reduce probability of clipping */ + + return sound_create((snd_susp_type)susp, susp->susp.t0, susp->susp.sr, + 1.0 /* scale factor */); +} + + +sound_type snd_resamplev(sound_type f, rate_type sr, sound_type g) +{ + sound_type f_copy = sound_copy(f); + sound_type g_copy = sound_copy(g); + g_copy->scale *= (float) sr; /* put g_copy in units of samples */ + return snd_make_resamplev(f_copy, sr, g_copy); +} diff --git a/nyqsrc/resampv.h b/nyqsrc/resampv.h new file mode 100644 index 0000000..ceec942 --- /dev/null +++ b/nyqsrc/resampv.h @@ -0,0 +1,3 @@ +sound_type snd_make_resamplev(sound_type f, rate_type sr, sound_type g); +sound_type snd_resamplev(sound_type f, rate_type sr, sound_type g); + /* LISP: (snd-resamplev SOUND ANYNUM SOUND) */ diff --git a/nyqsrc/rfftw.h b/nyqsrc/rfftw.h new file mode 100644 index 0000000..1d71ec7 --- /dev/null +++ b/nyqsrc/rfftw.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1997-1999 Massachusetts Institute of Technology + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* rfftw.h -- system-wide definitions for rfftw */ +#ifndef RFFTW_H +#define RFFTW_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/****************************************************************************/ + +#define RFFTW_V2 + +typedef fftw_plan rfftw_plan; +typedef fftwnd_plan rfftwnd_plan; + +#define FFTW_REAL_TO_COMPLEX FFTW_FORWARD +#define FFTW_COMPLEX_TO_REAL FFTW_BACKWARD + +extern void rfftw(rfftw_plan plan, int howmany, fftw_real *in, int istride, + int idist, fftw_real *out, int ostride, int odist); +extern void rfftw_one(rfftw_plan plan, fftw_real *in, fftw_real *out); + +extern rfftw_plan rfftw_create_plan_specific(int n, fftw_direction dir, + int flags, + fftw_real *in, int istride, + fftw_real *out, int ostride); + +extern rfftw_plan rfftw_create_plan(int n, fftw_direction dir, int flags); +extern void rfftw_destroy_plan(rfftw_plan plan); + +extern void rfftw_fprint_plan(FILE *f, rfftw_plan p); +extern void rfftw_print_plan(rfftw_plan p); + +extern void rfftw_executor_simple(int n, fftw_real *in, + fftw_real *out, + fftw_plan_node *p, + int istride, + int ostride); + +extern rfftwnd_plan rfftwnd_create_plan_specific(int rank, const int *n, + fftw_direction dir, int flags, + fftw_real *in, int istride, + fftw_real *out, int ostride); +extern rfftwnd_plan rfftw2d_create_plan_specific(int nx, int ny, + fftw_direction dir, int flags, + fftw_real *in, int istride, + fftw_real *out, int ostride); +extern rfftwnd_plan rfftw3d_create_plan_specific(int nx, int ny, int nz, + fftw_direction dir, int flags, + fftw_real *in, int istride, + fftw_real *out, int ostride); +extern rfftwnd_plan rfftwnd_create_plan(int rank, const int *n, + fftw_direction dir, int flags); +extern rfftwnd_plan rfftw2d_create_plan(int nx, int ny, + fftw_direction dir, int flags); +extern rfftwnd_plan rfftw3d_create_plan(int nx, int ny, int nz, + fftw_direction dir, int flags); +extern void rfftwnd_destroy_plan(rfftwnd_plan plan); +extern void rfftwnd_fprint_plan(FILE *f, rfftwnd_plan plan); +extern void rfftwnd_print_plan(rfftwnd_plan plan); +extern void rfftwnd_real_to_complex(rfftwnd_plan p, int howmany, + fftw_real *in, int istride, int idist, + fftw_complex *out, int ostride, int odist); +extern void rfftwnd_complex_to_real(rfftwnd_plan p, int howmany, + fftw_complex *in, int istride, int idist, + fftw_real *out, int ostride, int odist); +extern void rfftwnd_one_real_to_complex(rfftwnd_plan p, + fftw_real *in, fftw_complex *out); +extern void rfftwnd_one_complex_to_real(rfftwnd_plan p, + fftw_complex *in, fftw_real *out); + +/****************************************************************************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ +#endif /* RFFTW_H */ diff --git a/nyqsrc/samples.c b/nyqsrc/samples.c new file mode 100644 index 0000000..e841f67 --- /dev/null +++ b/nyqsrc/samples.c @@ -0,0 +1,304 @@ +/* samples.c -- various functions for the Nyquist sound data type */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm min->MIN, max->MAX + */ + +#include +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "samples.h" + + +LVAL s_next = NULL; +LVAL s_send; + +void samples_symbols() +{ + s_next = xlenter(":NEXT"); + s_send = xlenter("SEND"); +} + +/* snd_from_array -- convert lisp array to sound type */ +/**/ +sound_type snd_from_array(double t0, double sr, LVAL array) +{ + sound_type result; + snd_list_type snd_list; + long total = 0; + + if (!vectorp(array)) xlerror("array expected", array); + + result = sound_create(NULL, t0, sr, 1.0); + snd_list = result->list; + while (total < getsize(array)) { + long togo = MIN(getsize(array) - total, max_sample_block_len); + sample_block_type block; + int i; + falloc_sample_block(block, "snd_from_array"); + snd_list->block = block; + for (i = 0; i < togo; i++) { + LVAL elem = getelement(array, total + i); + sample_type *ptr = block->samples + i; + if (fixp(elem)) *ptr = (sample_type) getfixnum(elem); + else if (floatp(elem)) *ptr = (sample_type) getflonum(elem); + else xlerror("expecting array elem to be number", elem); + } + total += togo; + snd_list->block_len = (short) togo; + snd_list->u.next = snd_list_create(NULL); + snd_list = snd_list->u.next; + } + snd_list->block_len = max_sample_block_len; + snd_list->block = zero_block; + snd_list->logically_stopped = true; + snd_list->u.next = zero_snd_list; + return result; +} + + +/* snd_length -- count how many samples are in a sound */ +/**/ +long snd_length(sound_type s, long len) +{ + long total = 0; + long blocklen; + + s = sound_copy(s); + if (len > s->stop) len = s->stop; + while (total < len) { + sample_block_type sampblock = sound_get_next(s, &blocklen); + if (sampblock == zero_block) break; + total += blocklen; + } + if (total > len) total = len; + sound_unref(s); + return total; +} + + +/* snd_maxsamp -- compute the maximum value of samples in s */ +/**/ +double snd_maxsamp(sound_type s) +{ + sample_type result = 0.0F; + long blocklen; + s = sound_copy(s); + + while (true) { + sample_block_type sampblock = sound_get_next(s, &blocklen); + long i; + sample_block_values_type sbufp = sampblock->samples; + if (sampblock == zero_block || blocklen == 0) { + break; + } + for (i = 0; i < blocklen; i++) { + register sample_type samp = *sbufp++; + if (result < samp) result = samp; + else if (result < -samp) result = -samp; + } + } + return (double) (s->scale * result); +} + + +/* snd_samples -- convert sound (prefix) to lisp array */ +/**/ +LVAL snd_samples(sound_type s, long len) +{ + LVAL v; + long vx = 0; + long blocklen; + register double scale_factor = s->scale; + len = snd_length(s, len); + s = sound_copy(s); + + xlsave1(v); + v = newvector(len); + + while (len > 0) { + sample_block_type sampblock = sound_get_next(s, &blocklen); + long togo = MIN(blocklen, len); + long i; + sample_block_values_type sbufp = sampblock->samples; + for (i = 0; i < togo; i++) { + setelement(v, vx++, cvflonum(*sbufp++ * scale_factor)); + } + len -= togo; + } + sound_unref(s); + + /* restore the stack */ + xlpop(); + return v; +} + + +/* NOTE: this code does not properly handle start times that do not + * correspond to the time of the first actual sample + */ + +/* NOTE: we need some addtional state to keep track of where we are. + * We'll use the extra field of sound_type; first long is length, + * so second field will be the count of how many samples we've read. + */ +#define CNT extra[1] +#define INDEX extra[2] +#define FIELDS 3 +#define SAMPLES list->block->samples + +LVAL snd_fetch(sound_type s) +{ + if (!s->extra) { /* this is the first call, so fix up s */ + s->extra = (long *) malloc(sizeof(long) * FIELDS); + s->extra[0] = sizeof(long) * FIELDS; + s->CNT = s->INDEX = 0; + } else if (s->extra[0] != sizeof(long) * FIELDS) { + xlfail("sound in use by another iterator"); + } + if (s->CNT == s->INDEX) { + sound_get_next(s, &(s->CNT)); + s->INDEX = 0; + } + if (s->SAMPLES == zero_block->samples) { + return NULL; + } + + /* logical stop time is ignored by this code -- to fix this, + * you would need a way to return the logical stop time to + * the caller. + */ + + return cvflonum(s->SAMPLES[s->INDEX++] * s->scale); +} /* snd_fetch */ + + +/* snd_fetch_array -- fetch a lisp array of samples */ +/* + * storage layout: the extra field points to extra state that we'll use + * extra[0] -> length of extra storage + * extra[1] -> CNT (number of samples in current block) + * extra[2] -> INDEX (current sample index in current block) + * extra[3] -> FILLCNT (how many samples in buffer) + * extra[4] -> TERMCNT (how many samples until termination) + * extra[4 .. 4+len-1] -> samples (stored as floats) + * + * Termination details: + * Return NIL when the sound terminates. + * Termination is defined as the point where all original + * signal samples have been shifted out of the samples buffer + * so that all that's left are zeros from beyond the termination + * point. + * Implementation: when termination is discovered, set TERMCNT + * to the number of samples to be shifted out. TERMCNT is initially + * -1 as a flag that we haven't seen the termination yet. + * Each time samples are shifted, decrement TERMCNT by the shift amount. + * When TERMCNT goes to zero, return NULL. + */ +/* these macros define entries in extra, more macros are defined above */ +#define FILLCNT extra[3] +#define TERMCNT extra[4] +#define OFFSET 5 + +LVAL snd_fetch_array(sound_type s, long len, long step) +{ + long i, maxlen, skip, fillptr; + float *samples; + LVAL result; + LVAL rslt_symbol = xlenter("*RSLT*"); + + setvalue(rslt_symbol, NULL); + + if (len < 1) xlfail("len < 1"); + + if (!s->extra) { /* this is the first call, so fix up s */ + s->extra = (long *) malloc(sizeof(long) * (len + OFFSET)); + s->extra[0] = sizeof(long) * (len + OFFSET); + s->CNT = s->INDEX = s->FILLCNT = 0; + s->TERMCNT = -1; + maxlen = len; + } else { + maxlen = (s->extra[0] / sizeof(long)) - OFFSET; + if (maxlen < 1) xlfail("sound in use by another iterator"); + if (maxlen < len) xlfail("len grew"); + } + samples = (float *) &(s->extra[OFFSET]); + + /* step 1: refill buffer with samples */ + fillptr = s->FILLCNT; + while (fillptr < maxlen) { + if (s->INDEX == s->CNT) { + sound_get_next(s, &(s->CNT)); + if (s->SAMPLES == zero_block->samples) { + setvalue(rslt_symbol, cvfixnum(fillptr)); + if (s->TERMCNT < 0) s->TERMCNT = fillptr; + } + s->INDEX = 0; + } + samples[fillptr++] = s->SAMPLES[s->INDEX++] * s->scale; + } + s->FILLCNT = fillptr; + + /* it is important to test here AFTER filling the buffer, because + * if fillptr WAS 0 when we hit the zero_block, then filling the + * buffer will set TERMCNT to 0. + */ + if (s->TERMCNT == 0) return NULL; + + /* logical stop time is ignored by this code -- to fix this, + * you would need a way to return the logical stop time to + * the caller. + */ + + /* step 2: construct an array and return it */ + xlsave1(result); + result = newvector(len); + + for (i = 0; i < len; i++) { + setelement(result, i, cvflonum(samples[i])); + } + + /* step 3: shift samples by step */ + if (step < 0) xlfail("step < 0"); + s->FILLCNT -= step; + if (s->FILLCNT < 0) s->FILLCNT = 0; + for (i = 0; i < s->FILLCNT; i++) { + samples[i] = samples[i + step]; + } + + + if (s->TERMCNT >= 0) { + s->TERMCNT -= step; + if (s->TERMCNT < 0) s->TERMCNT = 0; + } + + + /* step 4: advance in sound to next sample we need + * (only does work if step > size of buffer) + */ + skip = step - maxlen; + while (skip > 0) { + long remaining = s->CNT - s->INDEX; + if (remaining >= skip) { + s->INDEX += skip; + skip = 0; + } else { + skip -= remaining; + sound_get_next(s, &(s->CNT)); + s->INDEX = 0; + } + } + + /* restore the stack */ + xlpop(); + return result; +} /* snd_fetch_array */ + + + + diff --git a/nyqsrc/samples.h b/nyqsrc/samples.h new file mode 100644 index 0000000..8907241 --- /dev/null +++ b/nyqsrc/samples.h @@ -0,0 +1,20 @@ +/* samples.h -- convert sound (prefix) to lisp array */ + +/* these are used by snd_fromobject and snd_fromarraystream: */ +extern LVAL s_next; +extern LVAL s_send; + +void samples_symbols(); + +sound_type snd_from_array(double t0, double sr, LVAL array); + /* LISP: (SND-FROM-ARRAY ANYNUM ANYNUM ANY) */ + +LVAL snd_samples(sound_type s, long len); /* LISP: (SND-SAMPLES SOUND FIXNUM) */ +long snd_length(sound_type s, long len); /* LISP: (SND-LENGTH SOUND FIXNUM) */ + +double snd_maxsamp(sound_type s); /* LISP: (SND-MAXSAMP SOUND) */ + +LVAL snd_fetch(sound_type s); /* LISP: (SND-FETCH SOUND) */ + +LVAL snd_fetch_array(sound_type s, long len, long step); + /* LISP: (SND-FETCH-ARRAY SOUND FIXNUM FIXNUM) */ diff --git a/nyqsrc/seqext.c b/nyqsrc/seqext.c new file mode 100644 index 0000000..804641a --- /dev/null +++ b/nyqsrc/seqext.c @@ -0,0 +1,92 @@ +/* seqext.c -- seq extensions for xlisp */ +/* +This file extends xlisp with the data type SEQ, including functions +to print and free SEQ type objects. + */ + +/* (c) Copyright Carnegie Mellon University 1991, 1994 + * For a statement of limited permission to use, see Permission.doc + */ + + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm portability fix: use %p instead of %lx + */ + + +#include "stdio.h" +#include "xlisp.h" +#include "cext.h" +#include "userio.h" +#include "midifns.h" +#include "timebase.h" +#include "seq.h" +#include "moxc.h" +#include "seqread.h" +#include "seqext.h" +#include "extern.h" + +LVAL s_seq; + +xtype_desc seq_desc; + +static void xlseq_print(); + +void nop() {} + +boolean seqp(s) + LVAL s; +{ + return exttypep(s, s_seq); +} + + +/* xlseq_free gets called by xlisp when the GC frees a seq object. + * seq_free is a macro, so here we make it into a function pointer. + */ +static void xlseq_free(sequence) +seq_type sequence; +{ + seq_free(sequence); +} + + +static void xlseq_print(fptr, sequence) + LVAL fptr; + seq_type sequence; +{ + char s[32]; + sprintf(s, "#", sequence); + xlputstr(fptr, s); +} + +static void xlseq_save(fp, sequence) + FILE *fp; + seq_type sequence; +{ + errputstr("xlseq_save called\n"); +} + + +static unsigned char *xlseq_restore(fp) + FILE *fp; +{ + errputstr("xlseq_restore called\n"); + return 0; +} + + +void seqext_init() +{ +/* printf("localinit called\n"); */ + seq_desc = create_desc("SEQ", xlseq_free, xlseq_print, xlseq_save, + xlseq_restore, NULL); + moxcinit(0, (char **) NULL); +} + + +void seqext_symbols() +{ + s_seq = xlenter("SEQ"); +} diff --git a/nyqsrc/seqext.h b/nyqsrc/seqext.h new file mode 100644 index 0000000..0727e77 --- /dev/null +++ b/nyqsrc/seqext.h @@ -0,0 +1,14 @@ +/* seqext.h -- header for seq extensions for xlisp */ + + +void seqext_init(); +void seqext_symbols(); +boolean seqp(); + +extern xtype_desc seq_desc; +extern LVAL s_seq; + +#define cvptrbool(v) ((LVAL) ((v) ? s_true : NIL)) +#define cvseq(v) ((LVAL) ((v) ? cvextern(seq_desc, (void *)(v)) : NIL)) +#define xlgaseq() (testarg(typearg(seqp))) +#define getseq(x) ((seq_type) getinst(x)) diff --git a/nyqsrc/seqfn.cl b/nyqsrc/seqfn.cl new file mode 100644 index 0000000..2a22761 --- /dev/null +++ b/nyqsrc/seqfn.cl @@ -0,0 +1,2 @@ +:nyqsrc:seqfnint :cmt:seqdecls.h :nyqsrc:seqext.h :cmt:seq.h :nyqsrc:seqinterf.h +:cmt:seqread.h :cmt:seqmread.h :cmt:seqwrite.h :cmt:seqmwrite.h diff --git a/nyqsrc/seqfn.wcl b/nyqsrc/seqfn.wcl new file mode 100644 index 0000000..8f58d02 --- /dev/null +++ b/nyqsrc/seqfn.wcl @@ -0,0 +1,2 @@ +nyqsrc\seqfnint cmt\seqdecls.h nyqsrc\seqext.h cmt\seq.h nyqsrc\seqinterf.h +cmt\seqread.h cmt\seqmread.h cmt\seqwrite.h cmt\seqmwrite.h diff --git a/nyqsrc/seqfnint.c b/nyqsrc/seqfnint.c new file mode 100644 index 0000000..9424097 --- /dev/null +++ b/nyqsrc/seqfnint.c @@ -0,0 +1,249 @@ +/* nyqsrc/seqfnint.c -- interface to cmt/seqdecls.h, + * nyqsrc/seqext.h, cmt/seq.h, nyqsrc/seqinterf.h, + * cmt/seqread.h, cmt/seqmread.h, cmt/seqwrite.h, + * cmt/seqmwrite.h */ + +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" + +extern LVAL s_true; +#define cvboolean(i) ((i) ? s_true : NIL) +#define testarg2(e) (moreargs() ? (e) : (getflonum(xltoofew()))) +#define xlgaanynum() (floatp(*xlargv) ? getflonum(nextarg()) : \ + (fixp(*xlargv) ? (double) getfixnum(nextarg()) : \ + getflonum(xlbadtype(*xlargv)))) +#define getboolean(lval) ((lval) != NIL) + +extern LVAL RSLT_sym; + + +#include "seqdecls.h" + +#include "seqext.h" + +#include "seq.h" + +/* xlc_seq_reset -- interface to C routine seq_reset */ +/**/ +LVAL xlc_seq_reset(void) +{ + seq_type arg1 = getseq(xlgaseq()); + + xllastarg(); + seq_reset(arg1); + return NIL; +} + + +/* xlc_seq_insert_ctrl -- interface to C routine insert_ctrl */ +/**/ +LVAL xlc_seq_insert_ctrl(void) +{ + seq_type arg1 = getseq(xlgaseq()); + long arg2 = getfixnum(xlgafixnum()); + long arg3 = getfixnum(xlgafixnum()); + long arg4 = getfixnum(xlgafixnum()); + long arg5 = getfixnum(xlgafixnum()); + long arg6 = getfixnum(xlgafixnum()); + + xllastarg(); + insert_ctrl(arg1, arg2, arg3, arg4, arg5, arg6); + return NIL; +} + + +/* xlc_seq_insert_ramp -- interface to C routine insert_ctrlramp */ +/**/ +LVAL xlc_seq_insert_ramp(void) +{ + seq_type arg1 = getseq(xlgaseq()); + long arg2 = getfixnum(xlgafixnum()); + long arg3 = getfixnum(xlgafixnum()); + long arg4 = getfixnum(xlgafixnum()); + long arg5 = getfixnum(xlgafixnum()); + long arg6 = getfixnum(xlgafixnum()); + long arg7 = getfixnum(xlgafixnum()); + long arg8 = getfixnum(xlgafixnum()); + long arg9 = getfixnum(xlgafixnum()); + + xllastarg(); + insert_ctrlramp(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + return NIL; +} + + +/* xlc_seq_insert_macctrl -- interface to C routine insert_macctrl */ +/**/ +LVAL xlc_seq_insert_macctrl(void) +{ + seq_type arg1 = getseq(xlgaseq()); + long arg2 = getfixnum(xlgafixnum()); + long arg3 = getfixnum(xlgafixnum()); + long arg4 = getfixnum(xlgafixnum()); + long arg5 = getfixnum(xlgafixnum()); + long arg6 = getfixnum(xlgafixnum()); + + xllastarg(); + insert_macctrl(arg1, arg2, arg3, arg4, arg5, arg6); + return NIL; +} + + +/* xlc_seq_insert_note -- interface to C routine insert_note */ +/**/ +LVAL xlc_seq_insert_note(void) +{ + seq_type arg1 = getseq(xlgaseq()); + long arg2 = getfixnum(xlgafixnum()); + long arg3 = getfixnum(xlgafixnum()); + long arg4 = getfixnum(xlgafixnum()); + long arg5 = getfixnum(xlgafixnum()); + long arg6 = getfixnum(xlgafixnum()); + long arg7 = getfixnum(xlgafixnum()); + + xllastarg(); + insert_note(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return NIL; +} + + +/* xlc_seq_copy -- interface to C routine seq_copy */ +/**/ +LVAL xlc_seq_copy(void) +{ + seq_type arg1 = getseq(xlgaseq()); + seq_type result; + + xllastarg(); + result = seq_copy(arg1); + return cvseq(result); +} + + +/* xlc_seq_create -- interface to C routine seq_create */ +/**/ +LVAL xlc_seq_create(void) +{ + seq_type result; + + xllastarg(); + result = seq_create(); + return cvseq(result); +} + + +#include "seqinterf.h" + +/* xlc_seq_next -- interface to C routine seq_next */ +/**/ +LVAL xlc_seq_next(void) +{ + seq_type arg1 = getseq(xlgaseq()); + boolean result; + + xllastarg(); + result = seq_next(arg1); + return cvboolean(result); +} + + +/* xlc_seq_get -- interface to C routine seq_get */ +/**/ +LVAL xlc_seq_get(void) +{ + seq_type arg1 = getseq(xlgaseq()); + long arg2 = 0; + long arg3 = 0; + long arg4 = 0; + long arg5 = 0; + long arg6 = 0; + long arg7 = 0; + long arg8 = 0; + LVAL result; + + xllastarg(); + seq_get(arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8); + { LVAL *next = &getvalue(RSLT_sym); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg2); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg3); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg4); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg5); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg6); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg7); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg8); + } + result = getvalue(RSLT_sym); + return result; +} + + +#include "seqread.h" + +/* xlc_seq_read -- interface to C routine seq_read */ +/**/ +LVAL xlc_seq_read(void) +{ + seq_type arg1 = getseq(xlgaseq()); + FILE * arg2 = getfile(xlgastream()); + + xllastarg(); + seq_read(arg1, arg2); + return NIL; +} + + +#include "seqmread.h" + +/* xlc_seq_read_smf -- interface to C routine seq_read_smf */ +/**/ +LVAL xlc_seq_read_smf(void) +{ + seq_type arg1 = getseq(xlgaseq()); + FILE * arg2 = getfile(xlgastream()); + + xllastarg(); + seq_read_smf(arg1, arg2); + return NIL; +} + + +#include "seqwrite.h" + +/* xlc_seq_write -- interface to C routine seq_write */ +/**/ +LVAL xlc_seq_write(void) +{ + seq_type arg1 = getseq(xlgaseq()); + FILE * arg2 = getfile(xlgastream()); + int arg3 = getboolean(xlgetarg()); + + xllastarg(); + seq_write(arg1, arg2, arg3); + return NIL; +} + + +#include "seqmwrite.h" + +/* xlc_seq_write_smf -- interface to C routine seq_write_smf */ +/**/ +LVAL xlc_seq_write_smf(void) +{ + seq_type arg1 = getseq(xlgaseq()); + FILE * arg2 = getfile(xlgastream()); + + xllastarg(); + seq_write_smf(arg1, arg2); + return NIL; +} + + diff --git a/nyqsrc/seqfnint.lsp b/nyqsrc/seqfnint.lsp new file mode 100644 index 0000000..1f7b01b --- /dev/null +++ b/nyqsrc/seqfnint.lsp @@ -0,0 +1,31 @@ + + (setfn seq-tag first) + (setfn seq-time second) + (setfn seq-line third) + (setfn seq-channel fourth) + (defun seq-value1 (e) (nth 4 e)) + (setfn seq-pitch seq-value1) ; pitch of a note + (setfn seq-control seq-value1) ; control number of a control change + (setfn seq-program seq-value1) ; program number of a program change + (setfn seq-bend seq-value1) ; pitch bend amount + (setfn seq-touch seq-value1) ; aftertouch amount + (defun seq-value2 (e) (nth 5 e)) + (setfn seq-velocity seq-value2) ; velocity of a note + (setfn seq-value seq-value2) ; value of a control change + (defun seq-duration (e) (nth 6 e)) + + + (setf seq-done-tag 0) + + (setf seq-other-tag 1) + + (setf seq-note-tag 2) + + (setf seq-ctrl-tag 3) + + (setf seq-prgm-tag 4) + + (setf seq-touch-tag 5) + + (setf seq-bend-tag 6) + diff --git a/nyqsrc/seqfnintdefs.h b/nyqsrc/seqfnintdefs.h new file mode 100644 index 0000000..ba09956 --- /dev/null +++ b/nyqsrc/seqfnintdefs.h @@ -0,0 +1,13 @@ +extern LVAL xlc_seq_reset(void); +extern LVAL xlc_seq_insert_ctrl(void); +extern LVAL xlc_seq_insert_ramp(void); +extern LVAL xlc_seq_insert_macctrl(void); +extern LVAL xlc_seq_insert_note(void); +extern LVAL xlc_seq_copy(void); +extern LVAL xlc_seq_create(void); +extern LVAL xlc_seq_next(void); +extern LVAL xlc_seq_get(void); +extern LVAL xlc_seq_read(void); +extern LVAL xlc_seq_read_smf(void); +extern LVAL xlc_seq_write(void); +extern LVAL xlc_seq_write_smf(void); diff --git a/nyqsrc/seqfnintptrs.h b/nyqsrc/seqfnintptrs.h new file mode 100644 index 0000000..9defce5 --- /dev/null +++ b/nyqsrc/seqfnintptrs.h @@ -0,0 +1,13 @@ + { "SEQ-RESET", S, xlc_seq_reset}, + { "SEQ-INSERT-CTRL", S, xlc_seq_insert_ctrl}, + { "SEQ-INSERT-RAMP", S, xlc_seq_insert_ramp}, + { "SEQ-INSERT-MACCTRL", S, xlc_seq_insert_macctrl}, + { "SEQ-INSERT-NOTE", S, xlc_seq_insert_note}, + { "SEQ-COPY", S, xlc_seq_copy}, + { "SEQ-CREATE", S, xlc_seq_create}, + { "SEQ-NEXT", S, xlc_seq_next}, + { "SEQ-GET", S, xlc_seq_get}, + { "SEQ-READ", S, xlc_seq_read}, + { "SEQ-READ-SMF", S, xlc_seq_read_smf}, + { "SEQ-WRITE", S, xlc_seq_write}, + { "SEQ-WRITE-SMF", S, xlc_seq_write_smf}, diff --git a/nyqsrc/seqinterf.c b/nyqsrc/seqinterf.c new file mode 100644 index 0000000..dc886a0 --- /dev/null +++ b/nyqsrc/seqinterf.c @@ -0,0 +1,98 @@ +/* seqinterf.c -- interface to sequence data type for XLISP */ + +#include "switches.h" +#include "xlisp.h" +#include "stdio.h" +#include "cext.h" +#include "userio.h" +#include "midifns.h" +#include "timebase.h" +#include "moxc.h" +#include "seq.h" +#include "seqinterf.h" + +/* seq_next -- advance to the next event, return TRUE if found */ +/**/ +boolean seq_next(seq_type seq) +{ + if (seq->current) { + seq->current = seq->current->next; + } + return seq->current != NULL; +} + + +/* seq_get -- get event data for the current event */ +/**/ +void seq_get(seq_type seq, long *eventtype, long *ntime, long *line, long *chan, + long *value1, long *value2, long *dur) +{ + event_type ev = seq->current; + if (!ev) *eventtype = SEQ_DONE; + else if (is_note(ev)) { + if (ev->value != NO_PITCH) { + *eventtype = SEQ_NOTE; + *ntime = ev->ntime; + *line = ev->nline; + *chan = vc_voice(ev->nvoice); + *value1 = ev->value; + *value2 = ev->u.note.ndur & 0xFF; + *dur = ev->u.note.ndur >> 8; + } else { + *eventtype = SEQ_OTHER; + } + } else { + *eventtype = SEQ_CTRL; + *ntime = ev->ntime; + *line = ev->nline; + *chan = vc_voice(ev->nvoice); + *value2 = ev->value; + + switch (vc_ctrl(ev->nvoice)) { + case PSWITCH_CTRL: + *value1 = PORTASWITCH; + break; + case MODWHEEL_CTRL: + *value1 = MODWHEEL; + break; + case TOUCH_CTRL: + *eventtype = SEQ_TOUCH; + *value1 = ev->value; + break; + case VOLUME_CTRL: + *value1 = VOLUME; + break; + case BEND_CTRL: + *eventtype = SEQ_BEND; + *value1 = ev->value << 6; + break; + case PROGRAM_CTRL: + *eventtype = SEQ_PRGM; + *value1 = ev->value + 1; + break; + case ESC_CTRL: + switch (ev->value) { + case CALL_VALUE: + case CLOCK_VALUE: + case MACRO_VALUE: + case CTRLRAMP_VALUE: + case DEFRAMP_VALUE: + case SETI_VALUE: + *eventtype = SEQ_OTHER; + break; + case MACCTRL_VALUE: + *value1 = ev->u.macctrl.ctrl_number; + *value2 = ev->u.macctrl.value; + break; + default: + xlabort("unexpected ESC_CTRL value\n"); + break; + } + break; + default: + xlabort("unexpected seq data\n"); + break; + } + } +} + diff --git a/nyqsrc/seqinterf.h b/nyqsrc/seqinterf.h new file mode 100644 index 0000000..590ed84 --- /dev/null +++ b/nyqsrc/seqinterf.h @@ -0,0 +1,37 @@ +/* seqinterf.h -- interface to sequence data type for XLISP */ + +boolean seq_next(seq_type seq); /* LISP: (SEQ-NEXT SEQ) */ +void seq_get(seq_type seq, long *eventtype, long *time, long *line, long *chan, + long *value1, long *value2, long *dur); + /* LISP: (SEQ-GET SEQ FIXNUM^ FIXNUM^ FIXNUM^ FIXNUM^ FIXNUM^ FIXNUM^ FIXNUM^) */ +/* LISP-SRC: + (setfn seq-tag first) + (setfn seq-time second) + (setfn seq-line third) + (setfn seq-channel fourth) + (defun seq-value1 (e) (nth 4 e)) + (setfn seq-pitch seq-value1) ; pitch of a note + (setfn seq-control seq-value1) ; control number of a control change + (setfn seq-program seq-value1) ; program number of a program change + (setfn seq-bend seq-value1) ; pitch bend amount + (setfn seq-touch seq-value1) ; aftertouch amount + (defun seq-value2 (e) (nth 5 e)) + (setfn seq-velocity seq-value2) ; velocity of a note + (setfn seq-value seq-value2) ; value of a control change + (defun seq-duration (e) (nth 6 e)) + */ +#define SEQ_DONE 0 +/* LISP-SRC: (setf seq-done-tag 0) */ +#define SEQ_OTHER 1 +/* LISP-SRC: (setf seq-other-tag 1) */ +#define SEQ_NOTE 2 +/* LISP-SRC: (setf seq-note-tag 2) */ +#define SEQ_CTRL 3 +/* LISP-SRC: (setf seq-ctrl-tag 3) */ +#define SEQ_PRGM 4 +/* LISP-SRC: (setf seq-prgm-tag 4) */ +#define SEQ_TOUCH 5 +/* LISP-SRC: (setf seq-touch-tag 5) */ +#define SEQ_BEND 6 +/* LISP-SRC: (setf seq-bend-tag 6) */ + diff --git a/nyqsrc/sliders.c b/nyqsrc/sliders.c new file mode 100644 index 0000000..9e07132 --- /dev/null +++ b/nyqsrc/sliders.c @@ -0,0 +1,160 @@ +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" + +#include "falloc.h" +#include "cext.h" +#include "sliders.h" +#include "sndsliders.h" + +float slider_array[SLIDERS_MAX]; + + +void set_slider(int index, float value) +{ + if (index >= 0 && index < SLIDERS_MAX) { + slider_array[index] = value; + } +} + + +LVAL xslider_read(void) +{ + LVAL arg = xlgafixnum(); + int index = getfixnum(arg); + xllastarg(); + if (index >= 0 && index < SLIDERS_MAX) { + return cvflonum(slider_array[index]); + } + return NIL; +} + +LVAL xosc_enable(void) +{ + LVAL arg = xlgetarg(); + xllastarg(); +#ifdef OSC + if (nosc_enabled == !null(arg)) { + return arg; /* no change */ + } else if (null(arg)) { /* nosc_enabled must be true */ + nosc_finish(); + return s_true; + } else { /* nosc_enabled must be false */ + nosc_init(); + return NIL; + } +#else + return xlenter("DISABLED"); +#endif +} + + +void slider_free(); + + +typedef struct slider_susp_struct { + snd_susp_node susp; + long terminate_cnt; + + int index; +} slider_susp_node, *slider_susp_type; + + +void slider__fetch(register slider_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + int togo; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + + register sample_block_values_type out_ptr_reg; + + register sample_type c_reg; + int limit = ((long) susp->susp.sr) / 50; + falloc_sample_block(out, "slider__fetch"); + out_ptr = out->samples; + snd_list->block = out; + + /* compute no more than 20ms to preserve some interactivity */ + if (limit < 1) limit = 1; + if (limit > max_sample_block_len) limit = max_sample_block_len; + + while (cnt < limit) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block: */ + togo = limit - cnt; + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); + if (togo == 0) break; + } + + n = togo; + c_reg = slider_array[susp->index]; + out_ptr_reg = out_ptr; + if (n) do { /* the inner sample computation loop */ + *out_ptr_reg++ = c_reg; + } while (--n); /* inner loop */ + + out_ptr += togo; + cnt += togo; + } /* outer loop */ + /* printf("slider %d cnt %d\n", susp->index, cnt); */ + /* test for termination */ + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } +} /* slider__fetch */ + + +void slider_free(slider_susp_type susp) +{ + ffree_generic(susp, sizeof(slider_susp_node), "slider_free"); +} + + +void slider_print_tree(slider_susp_type susp, int n) +{ +} + + +sound_type snd_make_slider(int index, time_type t0, rate_type sr, time_type d) +{ + register slider_susp_type susp; + /* sr specified as input parameter */ + /* t0 specified as input parameter */ + sample_type scale_factor = 1.0F; + if (index < 0 || index >= SLIDERS_MAX) { + xlerror("slider index out of range", NIL); + } + falloc_generic(susp, slider_susp_node, "snd_make_slider"); + susp->susp.fetch = slider__fetch; + susp->index = index; + + susp->terminate_cnt = round((d) * sr); + /* initialize susp state */ + susp->susp.free = slider_free; + susp->susp.sr = sr; + susp->susp.t0 = t0; + susp->susp.mark = NULL; + susp->susp.print_tree = slider_print_tree; + susp->susp.name = "slider"; + susp->susp.log_stop_cnt = UNKNOWN; + susp->susp.current = 0; + return sound_create((snd_susp_type)susp, t0, sr, scale_factor); +} + + +sound_type snd_slider(int index, time_type t0, rate_type sr, time_type d) +{ + return snd_make_slider(index, t0, sr, d); +} diff --git a/nyqsrc/sliders.h b/nyqsrc/sliders.h new file mode 100644 index 0000000..6628990 --- /dev/null +++ b/nyqsrc/sliders.h @@ -0,0 +1,11 @@ +/* sliders.h -- support for graphical sliders in Nyquist IDE */ + +/* probably these 3 should be elsewhere */ +int nosc_init(); +int nosc_poll(); +void nosc_finish(); + +#define SLIDERS_MAX 1024 +extern float slider_array[SLIDERS_MAX]; +void set_slider(int index, float value); + diff --git a/nyqsrc/sndfail.c b/nyqsrc/sndfail.c new file mode 100644 index 0000000..35b29cb --- /dev/null +++ b/nyqsrc/sndfail.c @@ -0,0 +1,23 @@ + +#include "stdio.h" +#include "snd.h" +#include "stdlib.h" +#include "xlisp.h" +#include "string.h" + +void snd_fail(char *msg) +{ + char *bigger = (char *) malloc(strlen(msg) + 16); + if (!bigger) xlfail("no memory"); + strcpy(bigger, "(snd)"); + strcat(bigger, msg); + xlfail(bigger); + // NOTE: there is a memory leak here +} + + +void snd_warn(char *msg) +{ + stdputstr(msg); + stdputstr("\n"); +} diff --git a/nyqsrc/sndfmt.h b/nyqsrc/sndfmt.h new file mode 100644 index 0000000..2434005 --- /dev/null +++ b/nyqsrc/sndfmt.h @@ -0,0 +1,118 @@ +/* + * sndfmt.h -- format constants for Nyquist programs + */ +/* + * converted by Roger Dannenberg from snd.h, Jul 08 + */ +#ifdef SND_H +error here +#endif +#define SND_H + + +/* header formats */ + +#define SND_HEAD_NONE 0 +/* LISP-SRC: (setf snd-head-none 0) */ +#define SND_HEAD_AIFF 1 +/* LISP-SRC: (setf snd-head-AIFF 1) */ +#define SND_HEAD_IRCAM 2 +/* LISP-SRC: (setf snd-head-IRCAM 2) */ +#define SND_HEAD_NEXT 3 +/* LISP-SRC: (setf snd-head-NeXT 3) */ +#define SND_HEAD_WAVE 4 +/* LISP-SRC: (setf snd-head-Wave 4) */ +#define SND_HEAD_PAF 5 +/* LISP-SRC: (setf snd-head-PAF 5) */ +#define SND_HEAD_SVX 6 +/* LISP-SRC: (setf snd-head-SVX 6) */ +#define SND_HEAD_NIST 7 +/* LISP-SRC: (setf snd-head-NIST 7) */ +#define SND_HEAD_VOC 8 +/* LISP-SRC: (setf snd-head-VOC 8) */ +#define SND_HEAD_W64 9 +/* LISP-SRC: (setf snd-head-W64 9) */ +#define SND_HEAD_MAT4 10 +/* LISP-SRC: (setf snd-head-MAT4 10) */ +#define SND_HEAD_MAT5 11 +/* LISP-SRC: (setf snd-head-MAT5 11) */ +#define SND_HEAD_PVF 12 +/* LISP-SRC: (setf snd-head-PVF 12) */ +#define SND_HEAD_XI 13 +/* LISP-SRC: (setf snd-head-XI 13) */ +#define SND_HEAD_HTK 14 +/* LISP-SRC: (setf snd-head-HTK 14) */ +#define SND_HEAD_SDS 15 +/* LISP-SRC: (setf snd-head-SDS 15) */ +#define SND_HEAD_AVR 16 +/* LISP-SRC: (setf snd-head-AVR 16) */ +#define SND_HEAD_SD2 17 +/* LISP-SRC: (setf snd-head-SD2 17) */ +#define SND_HEAD_FLAC 18 +/* LISP-SRC: (setf snd-head-FLAC 18) */ +#define SND_HEAD_CAF 19 +/* LISP-SRC: (setf snd-head-CAF 19) */ +#define SND_HEAD_RAW 20 +/* LISP-SRC: (setf snd-head-raw 20) */ +#define SND_NUM_HEADS 21 + +/* bitfields for soundheaders */ +#define SND_HEAD_CHANNELS (1<<0) +/* LISP-SRC: (setf snd-head-channels 1) */ +#define SND_HEAD_MODE (1<<1) +/* LISP-SRC: (setf snd-head-mode 2) */ +#define SND_HEAD_BITS (1<<2) +/* LISP-SRC: (setf snd-head-bits 4) */ +#define SND_HEAD_SRATE (1<<3) +/* LISP-SRC: (setf snd-head-srate 8) */ + +/* when returned from lisp, len (samples) is converted to time (seconds) */ +#define SND_HEAD_LEN (1<<4) +/* LISP-SRC: (setf snd-head-dur 16) */ + +#define SND_HEAD_LATENCY (1<<5) +/* LISP-SRC: (setf snd-head-latency 32) */ +#define SND_HEAD_TYPE (1<<6) +/* LISP-SRC: (setf snd-head-type 64) */ + +/* modes */ +/* IMA ADPCM */ +#define SND_MODE_ADPCM 0 +/* LISP-SRC: (setf snd-mode-adpcm 0) */ +#define SND_MODE_PCM 1 +/* LISP-SRC: (setf snd-mode-pcm 1) */ +#define SND_MODE_ULAW 2 +/* LISP-SRC: (setf snd-mode-ulaw 2) */ +#define SND_MODE_ALAW 3 +/* LISP-SRC: (setf snd-mode-alaw 3) */ +#define SND_MODE_FLOAT 4 +/* LISP-SRC: (setf snd-mode-float 4) */ +/* unsigned pcm (e.g. Microsoft 8-bit wav format): */ +#define SND_MODE_UPCM 5 +/* LISP-SRC: (setf snd-mode-upcm 5) */ +#define SND_MODE_UNKNOWN 6 +/* LISP-SRC: (setf snd-mode-unknown 6) */ +#define SND_MODE_DOUBLE 7 +/* LISP-SRC: (setf snd-mode-double 7) */ +#define SND_MODE_GSM610 8 +/* LISP-SRC: (setf snd-mode-GSM610 8) */ +#define SND_MODE_DWVW 9 +/* LISP-SRC: (setf snd-mode-DWVW 9) */ +#define SND_MODE_DPCM 10 +/* LISP-SRC: (setf snd-mode-DPCM 10) */ +/* microsoft ADPCM */ +#define SND_MODE_MSADPCM 11 +/* LISP-SRC: (setf snd-mode-msadpcm 11) */ +#define SND_NUM_MODES 12 + + +#define SND_LOOP_NONE 0 +#define SND_LOOP_FORWARD 1 +#define SND_LOOP_FORWARD_BACKWARD 2 + +typedef struct { + int mode; + long begin; + long end; +} loop_node, *loop_type; + diff --git a/nyqsrc/sndfn.cl b/nyqsrc/sndfn.cl new file mode 100644 index 0000000..80e4ef3 --- /dev/null +++ b/nyqsrc/sndfn.cl @@ -0,0 +1,54 @@ +nyqsrc/sndfnint snd/snd.h + nyqsrc/sound.h nyqsrc/add.h + nyqsrc/avg.h nyqsrc/compose.h + nyqsrc/convolve.h nyqsrc/downsample.h + nyqsrc/fft.h nyqsrc/inverse.h + nyqsrc/multiseq.h nyqsrc/resamp.h + nyqsrc/resampv.h nyqsrc/samples.h + nyqsrc/sndmax.h nyqsrc/sndread.h + nyqsrc/sndseq.h nyqsrc/sndsliders.h + nyqsrc/sndwrite.h nyqsrc/yin.h + nyqsrc/nyq-osc-server.h nyqsrc/trigger.h + nyqsrc/lpanal.h nyqsrc/phasevocoder.h + nyqsrc/pvshell.h ~nyqsrc/sndheader.h + tran/abs.h tran/allpoles.h + tran/alpass.h tran/alpasscv.h + tran/alpassvv.h tran/amosc.h + tran/areson.h tran/aresonvc.h + tran/aresoncv.h tran/aresonvv.h + tran/atone.h tran/atonev.h + tran/biquadfilt.h tran/buzz.h + tran/chase.h tran/clip.h + tran/congen.h tran/const.h + tran/coterm.h tran/delaycc.h + tran/delaycv.h tran/eqbandvvv.h + tran/exp.h tran/follow.h + tran/fmosc.h tran/fromobject.h + tran/fromarraystream.h tran/gate.h + tran/ifft.h tran/instrclar.h + tran/instrclarall.h tran/instrclarfreq.h + tran/instrsax.h tran/instrsaxall.h + tran/instrsaxfreq.h tran/integrate.h + tran/log.h tran/lpreson.h + tran/maxv.h tran/offset.h + tran/oneshot.h tran/osc.h + tran/partial.h tran/pluck.h + tran/prod.h tran/pwl.h + tran/quantize.h tran/recip.h + tran/reson.h tran/resonvc.h + tran/resoncv.h tran/resonvv.h + tran/sampler.h tran/scale.h + tran/shape.h tran/sine.h + tran/siosc.h tran/slope.h + tran/sqrt.h tran/tapf.h + tran/tapv.h tran/tone.h + tran/tonev.h tran/upsample.h + tran/white.h tran/stkrev.h + tran/stkpitshift.h tran/stkchorus.h + tran/instrbow.h tran/instrbowedfreq.h + tran/instrbanded.h tran/instrmandolin.h + tran/instrsitar.h tran/instrmodalbar.h + tran/instrflute.h tran/instrflutefreq.h + tran/instrfluteall.h tran/fmfb.h + tran/fmfbv.h + diff --git a/nyqsrc/sndfn.wcl b/nyqsrc/sndfn.wcl new file mode 100644 index 0000000..6b7d445 --- /dev/null +++ b/nyqsrc/sndfn.wcl @@ -0,0 +1,54 @@ +nyqsrc\sndfnint snd\snd.h + nyqsrc\sound.h nyqsrc\add.h + nyqsrc\avg.h nyqsrc\compose.h + nyqsrc\convolve.h nyqsrc\downsample.h + nyqsrc\fft.h nyqsrc\inverse.h + nyqsrc\multiseq.h nyqsrc\resamp.h + nyqsrc\resampv.h nyqsrc\samples.h + nyqsrc\sndmax.h nyqsrc\sndread.h + nyqsrc\sndseq.h nyqsrc\sndsliders.h + nyqsrc\sndwrite.h nyqsrc\yin.h + nyqsrc\nyq-osc-server.h nyqsrc\trigger.h + nyqsrc\lpanal.h nyqsrc\phasevocoder.h + nyqsrc\pvshell.h ~nyqsrc\sndheader.h + tran\abs.h tran\allpoles.h + tran\alpass.h tran\alpasscv.h + tran\alpassvv.h tran\amosc.h + tran\areson.h tran\aresonvc.h + tran\aresoncv.h tran\aresonvv.h + tran\atone.h tran\atonev.h + tran\biquadfilt.h tran\buzz.h + tran\chase.h tran\clip.h + tran\congen.h tran\const.h + tran\coterm.h tran\delaycc.h + tran\delaycv.h tran\eqbandvvv.h + tran\exp.h tran\follow.h + tran\fmosc.h tran\fromobject.h + tran\fromarraystream.h tran\gate.h + tran\ifft.h tran\instrclar.h + tran\instrclarall.h tran\instrclarfreq.h + tran\instrsax.h tran\instrsaxall.h + tran\instrsaxfreq.h tran\integrate.h + tran\log.h tran\lpreson.h + tran\maxv.h tran\offset.h + tran\oneshot.h tran\osc.h + tran\partial.h tran\pluck.h + tran\prod.h tran\pwl.h + tran\quantize.h tran\recip.h + tran\reson.h tran\resonvc.h + tran\resoncv.h tran\resonvv.h + tran\sampler.h tran\scale.h + tran\shape.h tran\sine.h + tran\siosc.h tran\slope.h + tran\sqrt.h tran\tapf.h + tran\tapv.h tran\tone.h + tran\tonev.h tran\upsample.h + tran\white.h tran\stkrev.h + tran\stkpitshift.h tran\stkchorus.h + tran\instrbow.h tran\instrbowedfreq.h + tran\instrbanded.h tran\instrmandolin.h + tran\instrsitar.h tran\instrmodalbar.h + tran\instrflute.h tran\instrflutefreq.h + tran\instrfluteall.h tran\fmfb.h + tran\fmfbv.h + diff --git a/nyqsrc/sndfnint.c b/nyqsrc/sndfnint.c new file mode 100644 index 0000000..4cb5bfe --- /dev/null +++ b/nyqsrc/sndfnint.c @@ -0,0 +1,2232 @@ +/* nyqsrc/sndfnint.c -- interface to nyqsrc/sndfmt.h, + * nylsf/sndfile.h, nyqsrc/sound.h, nyqsrc/add.h, + * nyqsrc/avg.h, nyqsrc/compose.h, nyqsrc/convolve.h, + * nyqsrc/downsample.h, nyqsrc/fft.h, nyqsrc/inverse.h, + * nyqsrc/multiseq.h, nyqsrc/resamp.h, nyqsrc/resampv.h, + * nyqsrc/samples.h, nyqsrc/sndmax.h, nyqsrc/sndread.h, + * nyqsrc/sndseq.h, nyqsrc/sndsliders.h, nyqsrc/sndwrite.h, + * nyqsrc/yin.h, nyqsrc/nyq-osc-server.h, nyqsrc/trigger.h, + * nyqsrc/lpanal.h, nyqsrc/phasevocoder.h, + * nyqsrc/pvshell.h, tran/abs.h, tran/allpoles.h, + * tran/alpass.h, tran/alpasscv.h, tran/alpassvv.h, + * tran/amosc.h, tran/areson.h, tran/aresonvc.h, + * tran/aresoncv.h, tran/aresonvv.h, tran/atone.h, + * tran/atonev.h, tran/biquadfilt.h, tran/buzz.h, + * tran/chase.h, tran/clip.h, tran/congen.h, + * tran/const.h, tran/coterm.h, tran/delaycc.h, + * tran/delaycv.h, tran/eqbandvvv.h, tran/exp.h, + * tran/follow.h, tran/fmosc.h, tran/fromobject.h, + * tran/fromarraystream.h, tran/gate.h, tran/ifft.h, + * tran/instrclar.h, tran/instrclarall.h, + * tran/instrclarfreq.h, tran/instrsax.h, + * tran/instrsaxall.h, tran/instrsaxfreq.h, + * tran/integrate.h, tran/log.h, tran/lpreson.h, + * tran/maxv.h, tran/offset.h, tran/oneshot.h, + * tran/osc.h, tran/partial.h, tran/pluck.h, tran/prod.h, + * tran/pwl.h, tran/quantize.h, tran/recip.h, + * tran/reson.h, tran/resonvc.h, tran/resoncv.h, + * tran/resonvv.h, tran/sampler.h, tran/scale.h, + * tran/shape.h, tran/sine.h, tran/siosc.h, tran/slope.h, + * tran/sqrt.h, tran/tapf.h, tran/tapv.h, tran/tone.h, + * tran/tonev.h, tran/upsample.h, tran/white.h, + * tran/stkrev.h, tran/stkpitshift.h, tran/stkchorus.h, + * tran/instrbow.h, tran/instrbowedfreq.h, + * tran/instrbanded.h, tran/instrmandolin.h, + * tran/instrsitar.h, tran/instrmodalbar.h, + * tran/instrflute.h, tran/instrflutefreq.h, + * tran/instrfluteall.h, tran/fmfb.h, tran/fmfbv.h */ + +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" + +extern LVAL s_true; +#define cvboolean(i) ((i) ? s_true : NIL) +#define testarg2(e) (moreargs() ? (e) : (getflonum(xltoofew()))) +#define xlgaanynum() (floatp(*xlargv) ? getflonum(nextarg()) : \ + (fixp(*xlargv) ? (double) getfixnum(nextarg()) : \ + getflonum(xlbadtype(*xlargv)))) +#define getboolean(lval) ((lval) != NIL) + +extern LVAL RSLT_sym; + + +#include "sndfmt.h" + +#include "sndfile.h" + +#include "sound.h" + +/* xlc_snd_set_latency -- interface to C routine snd_set_latency */ +/**/ +LVAL xlc_snd_set_latency(void) +{ + double arg1 = getflonum(xlgaflonum()); + double result; + + xllastarg(); + result = snd_set_latency(arg1); + return cvflonum(result); +} + + +/* xlc_soundp -- interface to C routine soundp */ +/**/ +LVAL xlc_soundp(void) +{ + LVAL arg1 = xlgetarg(); + boolean result; + + xllastarg(); + result = soundp(arg1); + return cvboolean(result); +} + + +/* xlc_hz_to_step -- interface to C routine hz_to_step */ +/**/ +LVAL xlc_hz_to_step(void) +{ + double arg1 = testarg2(xlgaanynum()); + double result; + + xllastarg(); + result = hz_to_step(arg1); + return cvflonum(result); +} + + +/* xlc_snd_set_logical_stop -- interface to C routine set_logical_stop_time */ +/**/ +LVAL xlc_snd_set_logical_stop(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + + xllastarg(); + set_logical_stop_time(arg1, arg2); + return NIL; +} + + +/* xlc_log -- interface to C routine xlog */ +/**/ +LVAL xlc_log(void) +{ + double arg1 = getflonum(xlgaflonum()); + double result; + + xllastarg(); + result = xlog(arg1); + return cvflonum(result); +} + + +/* xlc_snd_sref -- interface to C routine snd_sref */ +/**/ +LVAL xlc_snd_sref(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double result; + + xllastarg(); + result = snd_sref(arg1, arg2); + return cvflonum(result); +} + + +/* xlc_sref_inverse -- interface to C routine snd_sref_inverse */ +/**/ +LVAL xlc_sref_inverse(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double result; + + xllastarg(); + result = snd_sref_inverse(arg1, arg2); + return cvflonum(result); +} + + +/* xlc_snd_stop_time -- interface to C routine snd_stop_time */ +/**/ +LVAL xlc_snd_stop_time(void) +{ + sound_type arg1 = getsound(xlgasound()); + double result; + + xllastarg(); + result = snd_stop_time(arg1); + return cvflonum(result); +} + + +/* xlc_snd_time -- interface to C routine snd_time */ +/**/ +LVAL xlc_snd_time(void) +{ + sound_type arg1 = getsound(xlgasound()); + double result; + + xllastarg(); + result = snd_time(arg1); + return cvflonum(result); +} + + +/* xlc_snd_srate -- interface to C routine snd_srate */ +/**/ +LVAL xlc_snd_srate(void) +{ + sound_type arg1 = getsound(xlgasound()); + double result; + + xllastarg(); + result = snd_srate(arg1); + return cvflonum(result); +} + + +/* xlc_snd_t0 -- interface to C routine snd_t0 */ +/**/ +LVAL xlc_snd_t0(void) +{ + sound_type arg1 = getsound(xlgasound()); + double result; + + xllastarg(); + result = snd_t0(arg1); + return cvflonum(result); +} + + +/* xlc_snd_xform -- interface to C routine snd_xform */ +/**/ +LVAL xlc_snd_xform(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + double arg6 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_xform(arg1, arg2, arg3, arg4, arg5, arg6); + return cvsound(result); +} + + +/* xlc_block_watch -- interface to C routine block_watch */ +/**/ +LVAL xlc_block_watch(void) +{ + long arg1 = getfixnum(xlgafixnum()); + + xllastarg(); + block_watch(arg1); + return NIL; +} + + +/* xlc_sound_nth_block -- interface to C routine sound_nth_block */ +/**/ +LVAL xlc_sound_nth_block(void) +{ + sound_type arg1 = getsound(xlgasound()); + long arg2 = getfixnum(xlgafixnum()); + long result; + + xllastarg(); + result = sound_nth_block(arg1, arg2); + return cvfixnum(result); +} + + +/* xlc_snd_copy -- interface to C routine sound_copy */ +/**/ +LVAL xlc_snd_copy(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = sound_copy(arg1); + return cvsound(result); +} + + +/* xlc_snd_print -- interface to C routine sound_print */ +/**/ +LVAL xlc_snd_print(void) +{ + LVAL arg1 = xlgetarg(); + long arg2 = getfixnum(xlgafixnum()); + + xllastarg(); + sound_print(arg1, arg2); + return NIL; +} + + +/* xlc_snd_play -- interface to C routine sound_play */ +/**/ +LVAL xlc_snd_play(void) +{ + LVAL arg1 = xlgetarg(); + + xllastarg(); + sound_play(arg1); + return NIL; +} + + +/* xlc_stats -- interface to C routine stats */ +/**/ +LVAL xlc_stats(void) +{ + + xllastarg(); + stats(); + return NIL; +} + + +/* xlc_snd_print_tree -- interface to C routine sound_print_tree */ +/**/ +LVAL xlc_snd_print_tree(void) +{ + sound_type arg1 = getsound(xlgasound()); + + xllastarg(); + sound_print_tree(arg1); + return NIL; +} + + +/* xlc_snd_scale -- interface to C routine sound_scale */ +/**/ +LVAL xlc_snd_scale(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = sound_scale(arg1, arg2); + return cvsound(result); +} + + +/* xlc_snd_zero -- interface to C routine sound_zero */ +/**/ +LVAL xlc_snd_zero(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = sound_zero(arg1, arg2); + return cvsound(result); +} + + +/* xlc_step_to_hz -- interface to C routine step_to_hz */ +/**/ +LVAL xlc_step_to_hz(void) +{ + double arg1 = testarg2(xlgaanynum()); + double result; + + xllastarg(); + result = step_to_hz(arg1); + return cvflonum(result); +} + + +#include "add.h" + +/* xlc_snd_add -- interface to C routine snd_add */ +/**/ +LVAL xlc_snd_add(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_add(arg1, arg2); + return cvsound(result); +} + + +#include "avg.h" + +/* xlc_snd_avg -- interface to C routine snd_avg */ +/**/ +LVAL xlc_snd_avg(void) +{ + sound_type arg1 = getsound(xlgasound()); + long arg2 = getfixnum(xlgafixnum()); + long arg3 = getfixnum(xlgafixnum()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_avg(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "compose.h" + +/* xlc_snd_compose -- interface to C routine snd_compose */ +/**/ +LVAL xlc_snd_compose(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_compose(arg1, arg2); + return cvsound(result); +} + + +#include "convolve.h" + +/* xlc_snd_convolve -- interface to C routine snd_convolve */ +/**/ +LVAL xlc_snd_convolve(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_convolve(arg1, arg2); + return cvsound(result); +} + + +#include "downsample.h" + +/* xlc_snd_down -- interface to C routine snd_down */ +/**/ +LVAL xlc_snd_down(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_down(arg1, arg2); + return cvsound(result); +} + + +#include "fft.h" + +/* xlc_snd_fft -- interface to C routine snd_fft */ +/**/ +LVAL xlc_snd_fft(void) +{ + sound_type arg1 = getsound(xlgasound()); + long arg2 = getfixnum(xlgafixnum()); + long arg3 = getfixnum(xlgafixnum()); + LVAL arg4 = xlgetarg(); + LVAL result; + + xllastarg(); + result = snd_fft(arg1, arg2, arg3, arg4); + return (result); +} + + +#include "inverse.h" + +/* xlc_snd_inverse -- interface to C routine snd_inverse */ +/**/ +LVAL xlc_snd_inverse(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_inverse(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "multiseq.h" + +/* xlc_snd_multiseq -- interface to C routine snd_make_multiseq */ +/**/ +LVAL xlc_snd_multiseq(void) +{ + LVAL arg1 = xlgetarg(); + LVAL arg2 = xlgetarg(); + LVAL result; + + xllastarg(); + result = snd_make_multiseq(arg1, arg2); + return (result); +} + + +#include "resamp.h" + +/* xlc_snd_resample -- interface to C routine snd_resample */ +/**/ +LVAL xlc_snd_resample(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_resample(arg1, arg2); + return cvsound(result); +} + + +#include "resampv.h" + +/* xlc_snd_resamplev -- interface to C routine snd_resamplev */ +/**/ +LVAL xlc_snd_resamplev(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_resamplev(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "samples.h" + +/* xlc_snd_from_array -- interface to C routine snd_from_array */ +/**/ +LVAL xlc_snd_from_array(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + LVAL arg3 = xlgetarg(); + sound_type result; + + xllastarg(); + result = snd_from_array(arg1, arg2, arg3); + return cvsound(result); +} + + +/* xlc_snd_samples -- interface to C routine snd_samples */ +/**/ +LVAL xlc_snd_samples(void) +{ + sound_type arg1 = getsound(xlgasound()); + long arg2 = getfixnum(xlgafixnum()); + LVAL result; + + xllastarg(); + result = snd_samples(arg1, arg2); + return (result); +} + + +/* xlc_snd_length -- interface to C routine snd_length */ +/**/ +LVAL xlc_snd_length(void) +{ + sound_type arg1 = getsound(xlgasound()); + long arg2 = getfixnum(xlgafixnum()); + long result; + + xllastarg(); + result = snd_length(arg1, arg2); + return cvfixnum(result); +} + + +/* xlc_snd_maxsamp -- interface to C routine snd_maxsamp */ +/**/ +LVAL xlc_snd_maxsamp(void) +{ + sound_type arg1 = getsound(xlgasound()); + double result; + + xllastarg(); + result = snd_maxsamp(arg1); + return cvflonum(result); +} + + +/* xlc_snd_fetch -- interface to C routine snd_fetch */ +/**/ +LVAL xlc_snd_fetch(void) +{ + sound_type arg1 = getsound(xlgasound()); + LVAL result; + + xllastarg(); + result = snd_fetch(arg1); + return (result); +} + + +/* xlc_snd_fetch_array -- interface to C routine snd_fetch_array */ +/**/ +LVAL xlc_snd_fetch_array(void) +{ + sound_type arg1 = getsound(xlgasound()); + long arg2 = getfixnum(xlgafixnum()); + long arg3 = getfixnum(xlgafixnum()); + LVAL result; + + xllastarg(); + result = snd_fetch_array(arg1, arg2, arg3); + return (result); +} + + +#include "sndmax.h" + +/* xlc_snd_max -- interface to C routine sound_max */ +/**/ +LVAL xlc_snd_max(void) +{ + LVAL arg1 = xlgetarg(); + long arg2 = getfixnum(xlgafixnum()); + double result; + + xllastarg(); + result = sound_max(arg1, arg2); + return cvflonum(result); +} + + +#include "sndread.h" + +/* xlc_snd_read -- interface to C routine snd_make_read */ +/**/ +LVAL xlc_snd_read(void) +{ + unsigned char * arg1 = getstring(xlgastring()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + long arg4 = getfixnum(xlgafixnum()); + long arg5 = getfixnum(xlgafixnum()); + long arg6 = getfixnum(xlgafixnum()); + long arg7 = getfixnum(xlgafixnum()); + long arg8 = getfixnum(xlgafixnum()); + double arg9 = testarg2(xlgaanynum()); + double arg10 = testarg2(xlgaanynum()); + long arg11 = 0; + long arg12 = 0; + LVAL result; + + xllastarg(); + xlprot1(result); + result = snd_make_read(arg1, arg2, arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, &arg10, &arg11, &arg12); + { LVAL *next = &getvalue(RSLT_sym); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg4); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg5); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg6); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg7); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg8); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvflonum(arg9); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvflonum(arg10); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg11); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg12); + } + xlpop(); + return (result); +} + + +#include "sndseq.h" + +/* xlc_snd_seq -- interface to C routine snd_sndseq */ +/**/ +LVAL xlc_snd_seq(void) +{ + sound_type arg1 = getsound(xlgasound()); + LVAL arg2 = xlgetarg(); + sound_type result; + + xllastarg(); + result = snd_sndseq(arg1, arg2); + return cvsound(result); +} + + +#include "sndsliders.h" + +/* xlc_snd_slider -- interface to C routine snd_slider */ +/**/ +LVAL xlc_snd_slider(void) +{ + long arg1 = getfixnum(xlgafixnum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_slider(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "sndwrite.h" + +/* xlc_snd_save -- interface to C routine sound_save */ +/**/ +LVAL xlc_snd_save(void) +{ + LVAL arg1 = xlgetarg(); + long arg2 = getfixnum(xlgafixnum()); + unsigned char * arg3 = getstring(xlgastring()); + long arg4 = getfixnum(xlgafixnum()); + long arg5 = getfixnum(xlgafixnum()); + long arg6 = getfixnum(xlgafixnum()); + long arg7 = getfixnum(xlgafixnum()); + double arg8 = 0.0; + long arg9 = 0; + double arg10 = 0.0; + LVAL arg11 = xlgetarg(); + double result; + + xllastarg(); + result = sound_save(arg1, arg2, arg3, arg4, arg5, arg6, arg7, &arg8, &arg9, &arg10, arg11); + { LVAL *next = &getvalue(RSLT_sym); + *next = cons(NIL, NIL); + car(*next) = cvflonum(arg8); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvfixnum(arg9); next = &cdr(*next); + *next = cons(NIL, NIL); + car(*next) = cvflonum(arg10); + } + return cvflonum(result); +} + + +/* xlc_snd_overwrite -- interface to C routine sound_overwrite */ +/**/ +LVAL xlc_snd_overwrite(void) +{ + LVAL arg1 = xlgetarg(); + long arg2 = getfixnum(xlgafixnum()); + unsigned char * arg3 = getstring(xlgastring()); + double arg4 = testarg2(xlgaanynum()); + long arg5 = getfixnum(xlgafixnum()); + long arg6 = getfixnum(xlgafixnum()); + long arg7 = getfixnum(xlgafixnum()); + long arg8 = getfixnum(xlgafixnum()); + double arg9 = 0.0; + double result; + + xllastarg(); + result = sound_overwrite(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, &arg9); + { LVAL *next = &getvalue(RSLT_sym); + *next = cons(NIL, NIL); + car(*next) = cvflonum(arg9); + } + return cvflonum(result); +} + + +#include "yin.h" + +/* xlc_snd_yin -- interface to C routine snd_yin */ +/**/ +LVAL xlc_snd_yin(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + long arg4 = getfixnum(xlgafixnum()); + LVAL result; + + xllastarg(); + result = snd_yin(arg1, arg2, arg3, arg4); + return (result); +} + + +#include "nyq-osc-server.h" + +#include "trigger.h" + +/* xlc_snd_trigger -- interface to C routine snd_trigger */ +/**/ +LVAL xlc_snd_trigger(void) +{ + sound_type arg1 = getsound(xlgasound()); + LVAL arg2 = xlgetarg(); + sound_type result; + + xllastarg(); + result = snd_trigger(arg1, arg2); + return cvsound(result); +} + + +#include "lpanal.h" + +/* xlc_snd_lpanal -- interface to C routine snd_lpanal */ +/**/ +LVAL xlc_snd_lpanal(void) +{ + LVAL arg1 = xlgetarg(); + long arg2 = getfixnum(xlgafixnum()); + LVAL result; + + xllastarg(); + result = snd_lpanal(arg1, arg2); + return (result); +} + + +#include "phasevocoder.h" + +/* xlc_snd_phasevocoder -- interface to C routine snd_phasevocoder */ +/**/ +LVAL xlc_snd_phasevocoder(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_phasevocoder(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "pvshell.h" + +#include "abs.h" + +/* xlc_snd_abs -- interface to C routine snd_abs */ +/**/ +LVAL xlc_snd_abs(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_abs(arg1); + return cvsound(result); +} + + +#include "allpoles.h" + +/* xlc_snd_allpoles -- interface to C routine snd_allpoles */ +/**/ +LVAL xlc_snd_allpoles(void) +{ + sound_type arg1 = getsound(xlgasound()); + LVAL arg2 = xlgetarg(); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_allpoles(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "alpass.h" + +/* xlc_snd_alpass -- interface to C routine snd_alpass */ +/**/ +LVAL xlc_snd_alpass(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_alpass(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "alpasscv.h" + +/* xlc_snd_alpasscv -- interface to C routine snd_alpasscv */ +/**/ +LVAL xlc_snd_alpasscv(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_alpasscv(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "alpassvv.h" + +/* xlc_snd_alpassvv -- interface to C routine snd_alpassvv */ +/**/ +LVAL xlc_snd_alpassvv(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_alpassvv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "amosc.h" + +/* xlc_snd_amosc -- interface to C routine snd_amosc */ +/**/ +LVAL xlc_snd_amosc(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type arg6 = getsound(xlgasound()); + double arg7 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_amosc(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return cvsound(result); +} + + +#include "areson.h" + +/* xlc_snd_areson -- interface to C routine snd_areson */ +/**/ +LVAL xlc_snd_areson(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_areson(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "aresonvc.h" + +/* xlc_snd_aresonvc -- interface to C routine snd_aresonvc */ +/**/ +LVAL xlc_snd_aresonvc(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_aresonvc(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "aresoncv.h" + +/* xlc_snd_aresoncv -- interface to C routine snd_aresoncv */ +/**/ +LVAL xlc_snd_aresoncv(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_aresoncv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "aresonvv.h" + +/* xlc_snd_aresonvv -- interface to C routine snd_aresonvv */ +/**/ +LVAL xlc_snd_aresonvv(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_aresonvv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "atone.h" + +/* xlc_snd_atone -- interface to C routine snd_atone */ +/**/ +LVAL xlc_snd_atone(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_atone(arg1, arg2); + return cvsound(result); +} + + +#include "atonev.h" + +/* xlc_snd_atonev -- interface to C routine snd_atonev */ +/**/ +LVAL xlc_snd_atonev(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_atonev(arg1, arg2); + return cvsound(result); +} + + +#include "biquadfilt.h" + +/* xlc_snd_biquad -- interface to C routine snd_biquadfilt */ +/**/ +LVAL xlc_snd_biquad(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + double arg6 = testarg2(xlgaanynum()); + double arg7 = testarg2(xlgaanynum()); + double arg8 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_biquadfilt(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + return cvsound(result); +} + + +#include "buzz.h" + +/* xlc_snd_buzz -- interface to C routine snd_buzz */ +/**/ +LVAL xlc_snd_buzz(void) +{ + long arg1 = getfixnum(xlgafixnum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + sound_type arg5 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_buzz(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "chase.h" + +/* xlc_snd_chase -- interface to C routine snd_chase */ +/**/ +LVAL xlc_snd_chase(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_chase(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "clip.h" + +/* xlc_snd_clip -- interface to C routine snd_clip */ +/**/ +LVAL xlc_snd_clip(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_clip(arg1, arg2); + return cvsound(result); +} + + +#include "congen.h" + +/* xlc_snd_congen -- interface to C routine snd_congen */ +/**/ +LVAL xlc_snd_congen(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_congen(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "const.h" + +/* xlc_snd_const -- interface to C routine snd_const */ +/**/ +LVAL xlc_snd_const(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_const(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "coterm.h" + +/* xlc_snd_coterm -- interface to C routine snd_coterm */ +/**/ +LVAL xlc_snd_coterm(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_coterm(arg1, arg2); + return cvsound(result); +} + + +#include "delaycc.h" + +/* xlc_snd_delay -- interface to C routine snd_delay */ +/**/ +LVAL xlc_snd_delay(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_delay(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "delaycv.h" + +/* xlc_snd_delaycv -- interface to C routine snd_delaycv */ +/**/ +LVAL xlc_snd_delaycv(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_delaycv(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "eqbandvvv.h" + +/* xlc_snd_eqbandvvv -- interface to C routine snd_eqbandvvv */ +/**/ +LVAL xlc_snd_eqbandvvv(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + sound_type arg4 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_eqbandvvv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "exp.h" + +/* xlc_snd_exp -- interface to C routine snd_exp */ +/**/ +LVAL xlc_snd_exp(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_exp(arg1); + return cvsound(result); +} + + +#include "follow.h" + +/* xlc_snd_follow -- interface to C routine snd_follow */ +/**/ +LVAL xlc_snd_follow(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + long arg5 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_follow(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "fmosc.h" + +/* xlc_snd_fmosc -- interface to C routine snd_fmosc */ +/**/ +LVAL xlc_snd_fmosc(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type arg6 = getsound(xlgasound()); + double arg7 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_fmosc(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return cvsound(result); +} + + +#include "fromobject.h" + +/* xlc_snd_fromobject -- interface to C routine snd_fromobject */ +/**/ +LVAL xlc_snd_fromobject(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + LVAL arg3 = xlgetarg(); + sound_type result; + + xllastarg(); + result = snd_fromobject(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "fromarraystream.h" + +/* xlc_snd_fromarraystream -- interface to C routine snd_fromarraystream */ +/**/ +LVAL xlc_snd_fromarraystream(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + LVAL arg3 = xlgetarg(); + sound_type result; + + xllastarg(); + result = snd_fromarraystream(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "gate.h" + +/* xlc_snd_gate -- interface to C routine snd_gate */ +/**/ +LVAL xlc_snd_gate(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + double arg6 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_gate(arg1, arg2, arg3, arg4, arg5, arg6); + return cvsound(result); +} + + +#include "ifft.h" + +/* xlc_snd_ifft -- interface to C routine snd_ifft */ +/**/ +LVAL xlc_snd_ifft(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + LVAL arg3 = xlgetarg(); + long arg4 = getfixnum(xlgafixnum()); + LVAL arg5 = xlgetarg(); + sound_type result; + + xllastarg(); + result = snd_ifft(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "instrclar.h" + +/* xlc_snd_clarinet -- interface to C routine snd_clarinet */ +/**/ +LVAL xlc_snd_clarinet(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_clarinet(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "instrclarall.h" + +/* xlc_snd_clarinet_all -- interface to C routine snd_clarinet_all */ +/**/ +LVAL xlc_snd_clarinet_all(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type arg6 = getsound(xlgasound()); + sound_type arg7 = getsound(xlgasound()); + double arg8 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_clarinet_all(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + return cvsound(result); +} + + +#include "instrclarfreq.h" + +/* xlc_snd_clarinet_freq -- interface to C routine snd_clarinet_freq */ +/**/ +LVAL xlc_snd_clarinet_freq(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_clarinet_freq(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "instrsax.h" + +/* xlc_snd_sax -- interface to C routine snd_sax */ +/**/ +LVAL xlc_snd_sax(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_sax(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "instrsaxall.h" + +/* xlc_snd_sax_all -- interface to C routine snd_sax_all */ +/**/ +LVAL xlc_snd_sax_all(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type arg6 = getsound(xlgasound()); + sound_type arg7 = getsound(xlgasound()); + sound_type arg8 = getsound(xlgasound()); + sound_type arg9 = getsound(xlgasound()); + double arg10 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_sax_all(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + return cvsound(result); +} + + +#include "instrsaxfreq.h" + +/* xlc_snd_sax_freq -- interface to C routine snd_sax_freq */ +/**/ +LVAL xlc_snd_sax_freq(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_sax_freq(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "integrate.h" + +/* xlc_snd_integrate -- interface to C routine snd_integrate */ +/**/ +LVAL xlc_snd_integrate(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_integrate(arg1); + return cvsound(result); +} + + +#include "log.h" + +/* xlc_snd_log -- interface to C routine snd_log */ +/**/ +LVAL xlc_snd_log(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_log(arg1); + return cvsound(result); +} + + +#include "lpreson.h" + +/* xlc_snd_lpreson -- interface to C routine snd_lpreson */ +/**/ +LVAL xlc_snd_lpreson(void) +{ + sound_type arg1 = getsound(xlgasound()); + LVAL arg2 = xlgetarg(); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_lpreson(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "maxv.h" + +/* xlc_snd_maxv -- interface to C routine snd_maxv */ +/**/ +LVAL xlc_snd_maxv(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_maxv(arg1, arg2); + return cvsound(result); +} + + +#include "offset.h" + +/* xlc_snd_offset -- interface to C routine snd_offset */ +/**/ +LVAL xlc_snd_offset(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_offset(arg1, arg2); + return cvsound(result); +} + + +#include "oneshot.h" + +/* xlc_snd_oneshot -- interface to C routine snd_oneshot */ +/**/ +LVAL xlc_snd_oneshot(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_oneshot(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "osc.h" + +/* xlc_snd_osc -- interface to C routine snd_osc */ +/**/ +LVAL xlc_snd_osc(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + double arg6 = testarg2(xlgaanynum()); + double arg7 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_osc(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return cvsound(result); +} + + +#include "partial.h" + +/* xlc_snd_partial -- interface to C routine snd_partial */ +/**/ +LVAL xlc_snd_partial(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_partial(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "pluck.h" + +/* xlc_snd_pluck -- interface to C routine snd_pluck */ +/**/ +LVAL xlc_snd_pluck(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_pluck(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "prod.h" + +/* xlc_snd_prod -- interface to C routine snd_prod */ +/**/ +LVAL xlc_snd_prod(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_prod(arg1, arg2); + return cvsound(result); +} + + +#include "pwl.h" + +/* xlc_snd_pwl -- interface to C routine snd_pwl */ +/**/ +LVAL xlc_snd_pwl(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + LVAL arg3 = xlgetarg(); + sound_type result; + + xllastarg(); + result = snd_pwl(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "quantize.h" + +/* xlc_snd_quantize -- interface to C routine snd_quantize */ +/**/ +LVAL xlc_snd_quantize(void) +{ + sound_type arg1 = getsound(xlgasound()); + long arg2 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_quantize(arg1, arg2); + return cvsound(result); +} + + +#include "recip.h" + +/* xlc_snd_recip -- interface to C routine snd_recip */ +/**/ +LVAL xlc_snd_recip(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_recip(arg1); + return cvsound(result); +} + + +#include "reson.h" + +/* xlc_snd_reson -- interface to C routine snd_reson */ +/**/ +LVAL xlc_snd_reson(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_reson(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "resonvc.h" + +/* xlc_snd_resonvc -- interface to C routine snd_resonvc */ +/**/ +LVAL xlc_snd_resonvc(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_resonvc(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "resoncv.h" + +/* xlc_snd_resoncv -- interface to C routine snd_resoncv */ +/**/ +LVAL xlc_snd_resoncv(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_resoncv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "resonvv.h" + +/* xlc_snd_resonvv -- interface to C routine snd_resonvv */ +/**/ +LVAL xlc_snd_resonvv(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + long arg4 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_resonvv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "sampler.h" + +/* xlc_snd_sampler -- interface to C routine snd_sampler */ +/**/ +LVAL xlc_snd_sampler(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + double arg6 = testarg2(xlgaanynum()); + sound_type arg7 = getsound(xlgasound()); + long arg8 = getfixnum(xlgafixnum()); + sound_type result; + + xllastarg(); + result = snd_sampler(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + return cvsound(result); +} + + +#include "scale.h" + +/* xlc_snd_normalize -- interface to C routine snd_normalize */ +/**/ +LVAL xlc_snd_normalize(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_normalize(arg1); + return cvsound(result); +} + + +#include "shape.h" + +/* xlc_snd_shape -- interface to C routine snd_shape */ +/**/ +LVAL xlc_snd_shape(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_shape(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "sine.h" + +/* xlc_snd_sine -- interface to C routine snd_sine */ +/**/ +LVAL xlc_snd_sine(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_sine(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "siosc.h" + +/* xlc_snd_siosc -- interface to C routine snd_siosc */ +/**/ +LVAL xlc_snd_siosc(void) +{ + LVAL arg1 = xlgetarg(); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + sound_type arg5 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_siosc(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "slope.h" + +/* xlc_snd_slope -- interface to C routine snd_slope */ +/**/ +LVAL xlc_snd_slope(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_slope(arg1); + return cvsound(result); +} + + +#include "sqrt.h" + +/* xlc_snd_sqrt -- interface to C routine snd_sqrt */ +/**/ +LVAL xlc_snd_sqrt(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_sqrt(arg1); + return cvsound(result); +} + + +#include "tapf.h" + +/* xlc_snd_tapf -- interface to C routine snd_tapf */ +/**/ +LVAL xlc_snd_tapf(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_tapf(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "tapv.h" + +/* xlc_snd_tapv -- interface to C routine snd_tapv */ +/**/ +LVAL xlc_snd_tapv(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_tapv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "tone.h" + +/* xlc_snd_tone -- interface to C routine snd_tone */ +/**/ +LVAL xlc_snd_tone(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_tone(arg1, arg2); + return cvsound(result); +} + + +#include "tonev.h" + +/* xlc_snd_tonev -- interface to C routine snd_tonev */ +/**/ +LVAL xlc_snd_tonev(void) +{ + sound_type arg1 = getsound(xlgasound()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_tonev(arg1, arg2); + return cvsound(result); +} + + +#include "upsample.h" + +/* xlc_snd_up -- interface to C routine snd_up */ +/**/ +LVAL xlc_snd_up(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_up(arg1, arg2); + return cvsound(result); +} + + +#include "white.h" + +/* xlc_snd_white -- interface to C routine snd_white */ +/**/ +LVAL xlc_snd_white(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_white(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "stkrev.h" + +/* xlc_snd_stkrev -- interface to C routine snd_stkrev */ +/**/ +LVAL xlc_snd_stkrev(void) +{ + long arg1 = getfixnum(xlgafixnum()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_stkrev(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "stkpitshift.h" + +/* xlc_snd_stkpitshift -- interface to C routine snd_stkpitshift */ +/**/ +LVAL xlc_snd_stkpitshift(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_stkpitshift(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "stkchorus.h" + +/* xlc_snd_stkchorus -- interface to C routine snd_stkchorus */ +/**/ +LVAL xlc_snd_stkchorus(void) +{ + sound_type arg1 = getsound(xlgasound()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + double arg6 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_stkchorus(arg1, arg2, arg3, arg4, arg5, arg6); + return cvsound(result); +} + + +#include "instrbow.h" + +/* xlc_snd_bowed -- interface to C routine snd_bowed */ +/**/ +LVAL xlc_snd_bowed(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_bowed(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "instrbowedfreq.h" + +/* xlc_snd_bowed_freq -- interface to C routine snd_bowed_freq */ +/**/ +LVAL xlc_snd_bowed_freq(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_bowed_freq(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "instrbanded.h" + +/* xlc_snd_bandedwg -- interface to C routine snd_bandedwg */ +/**/ +LVAL xlc_snd_bandedwg(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + long arg3 = getfixnum(xlgafixnum()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_bandedwg(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "instrmandolin.h" + +/* xlc_snd_mandolin -- interface to C routine snd_mandolin */ +/**/ +LVAL xlc_snd_mandolin(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + double arg6 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_mandolin(arg1, arg2, arg3, arg4, arg5, arg6); + return cvsound(result); +} + + +#include "instrsitar.h" + +/* xlc_snd_sitar -- interface to C routine snd_sitar */ +/**/ +LVAL xlc_snd_sitar(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_sitar(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "instrmodalbar.h" + +/* xlc_snd_modalbar -- interface to C routine snd_modalbar */ +/**/ +LVAL xlc_snd_modalbar(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + long arg3 = getfixnum(xlgafixnum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_modalbar(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "instrflute.h" + +/* xlc_snd_flute -- interface to C routine snd_flute */ +/**/ +LVAL xlc_snd_flute(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + double arg3 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_flute(arg1, arg2, arg3); + return cvsound(result); +} + + +#include "instrflutefreq.h" + +/* xlc_snd_flute_freq -- interface to C routine snd_flute_freq */ +/**/ +LVAL xlc_snd_flute_freq(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_flute_freq(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + +#include "instrfluteall.h" + +/* xlc_snd_flute_all -- interface to C routine snd_flute_all */ +/**/ +LVAL xlc_snd_flute_all(void) +{ + double arg1 = testarg2(xlgaanynum()); + sound_type arg2 = getsound(xlgasound()); + sound_type arg3 = getsound(xlgasound()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type arg6 = getsound(xlgasound()); + sound_type arg7 = getsound(xlgasound()); + double arg8 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_flute_all(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + return cvsound(result); +} + + +#include "fmfb.h" + +/* xlc_snd_fmfb -- interface to C routine snd_fmfb */ +/**/ +LVAL xlc_snd_fmfb(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + double arg4 = testarg2(xlgaanynum()); + double arg5 = testarg2(xlgaanynum()); + sound_type result; + + xllastarg(); + result = snd_fmfb(arg1, arg2, arg3, arg4, arg5); + return cvsound(result); +} + + +#include "fmfbv.h" + +/* xlc_snd_fmfbv -- interface to C routine snd_fmfbv */ +/**/ +LVAL xlc_snd_fmfbv(void) +{ + double arg1 = testarg2(xlgaanynum()); + double arg2 = testarg2(xlgaanynum()); + double arg3 = testarg2(xlgaanynum()); + sound_type arg4 = getsound(xlgasound()); + sound_type result; + + xllastarg(); + result = snd_fmfbv(arg1, arg2, arg3, arg4); + return cvsound(result); +} + + diff --git a/nyqsrc/sndfnint.lsp b/nyqsrc/sndfnint.lsp new file mode 100644 index 0000000..83c897c --- /dev/null +++ b/nyqsrc/sndfnint.lsp @@ -0,0 +1,86 @@ + (setf snd-head-none 0) + + (setf snd-head-AIFF 1) + + (setf snd-head-IRCAM 2) + + (setf snd-head-NeXT 3) + + (setf snd-head-Wave 4) + + (setf snd-head-PAF 5) + + (setf snd-head-SVX 6) + + (setf snd-head-NIST 7) + + (setf snd-head-VOC 8) + + (setf snd-head-W64 9) + + (setf snd-head-MAT4 10) + + (setf snd-head-MAT5 11) + + (setf snd-head-PVF 12) + + (setf snd-head-XI 13) + + (setf snd-head-HTK 14) + + (setf snd-head-SDS 15) + + (setf snd-head-AVR 16) + + (setf snd-head-SD2 17) + + (setf snd-head-FLAC 18) + + (setf snd-head-CAF 19) + + (setf snd-head-raw 20) + + (setf snd-head-channels 1) + + (setf snd-head-mode 2) + + (setf snd-head-bits 4) + + (setf snd-head-srate 8) + + (setf snd-head-dur 16) + + (setf snd-head-latency 32) + + (setf snd-head-type 64) + + (setf snd-mode-adpcm 0) + + (setf snd-mode-pcm 1) + + (setf snd-mode-ulaw 2) + + (setf snd-mode-alaw 3) + + (setf snd-mode-float 4) + + (setf snd-mode-upcm 5) + + (setf snd-mode-unknown 6) + + (setf snd-mode-double 7) + + (setf snd-mode-GSM610 8) + + (setf snd-mode-DWVW 9) + + (setf snd-mode-DPCM 10) + + (setf snd-mode-msadpcm 11) + + (SETF MAX-STOP-TIME 10E20) + + (SETF MIN-START-TIME -10E20) + + (setf OP-AVERAGE 1) (setf OP-PEAK 2) + diff --git a/nyqsrc/sndfnintdefs.h b/nyqsrc/sndfnintdefs.h new file mode 100644 index 0000000..694f47f --- /dev/null +++ b/nyqsrc/sndfnintdefs.h @@ -0,0 +1,127 @@ +extern LVAL xlc_snd_set_latency(void); +extern LVAL xlc_soundp(void); +extern LVAL xlc_hz_to_step(void); +extern LVAL xlc_snd_set_logical_stop(void); +extern LVAL xlc_log(void); +extern LVAL xlc_snd_sref(void); +extern LVAL xlc_sref_inverse(void); +extern LVAL xlc_snd_stop_time(void); +extern LVAL xlc_snd_time(void); +extern LVAL xlc_snd_srate(void); +extern LVAL xlc_snd_t0(void); +extern LVAL xlc_snd_xform(void); +extern LVAL xlc_block_watch(void); +extern LVAL xlc_sound_nth_block(void); +extern LVAL xlc_snd_copy(void); +extern LVAL xlc_snd_print(void); +extern LVAL xlc_snd_play(void); +extern LVAL xlc_stats(void); +extern LVAL xlc_snd_print_tree(void); +extern LVAL xlc_snd_scale(void); +extern LVAL xlc_snd_zero(void); +extern LVAL xlc_step_to_hz(void); +extern LVAL xlc_snd_add(void); +extern LVAL xlc_snd_avg(void); +extern LVAL xlc_snd_compose(void); +extern LVAL xlc_snd_convolve(void); +extern LVAL xlc_snd_down(void); +extern LVAL xlc_snd_fft(void); +extern LVAL xlc_snd_inverse(void); +extern LVAL xlc_snd_multiseq(void); +extern LVAL xlc_snd_resample(void); +extern LVAL xlc_snd_resamplev(void); +extern LVAL xlc_snd_from_array(void); +extern LVAL xlc_snd_samples(void); +extern LVAL xlc_snd_length(void); +extern LVAL xlc_snd_maxsamp(void); +extern LVAL xlc_snd_fetch(void); +extern LVAL xlc_snd_fetch_array(void); +extern LVAL xlc_snd_max(void); +extern LVAL xlc_snd_read(void); +extern LVAL xlc_snd_seq(void); +extern LVAL xlc_snd_slider(void); +extern LVAL xlc_snd_save(void); +extern LVAL xlc_snd_overwrite(void); +extern LVAL xlc_snd_yin(void); +extern LVAL xlc_snd_trigger(void); +extern LVAL xlc_snd_lpanal(void); +extern LVAL xlc_snd_phasevocoder(void); +extern LVAL xlc_snd_abs(void); +extern LVAL xlc_snd_allpoles(void); +extern LVAL xlc_snd_alpass(void); +extern LVAL xlc_snd_alpasscv(void); +extern LVAL xlc_snd_alpassvv(void); +extern LVAL xlc_snd_amosc(void); +extern LVAL xlc_snd_areson(void); +extern LVAL xlc_snd_aresonvc(void); +extern LVAL xlc_snd_aresoncv(void); +extern LVAL xlc_snd_aresonvv(void); +extern LVAL xlc_snd_atone(void); +extern LVAL xlc_snd_atonev(void); +extern LVAL xlc_snd_biquad(void); +extern LVAL xlc_snd_buzz(void); +extern LVAL xlc_snd_chase(void); +extern LVAL xlc_snd_clip(void); +extern LVAL xlc_snd_congen(void); +extern LVAL xlc_snd_const(void); +extern LVAL xlc_snd_coterm(void); +extern LVAL xlc_snd_delay(void); +extern LVAL xlc_snd_delaycv(void); +extern LVAL xlc_snd_eqbandvvv(void); +extern LVAL xlc_snd_exp(void); +extern LVAL xlc_snd_follow(void); +extern LVAL xlc_snd_fmosc(void); +extern LVAL xlc_snd_fromobject(void); +extern LVAL xlc_snd_fromarraystream(void); +extern LVAL xlc_snd_gate(void); +extern LVAL xlc_snd_ifft(void); +extern LVAL xlc_snd_clarinet(void); +extern LVAL xlc_snd_clarinet_all(void); +extern LVAL xlc_snd_clarinet_freq(void); +extern LVAL xlc_snd_sax(void); +extern LVAL xlc_snd_sax_all(void); +extern LVAL xlc_snd_sax_freq(void); +extern LVAL xlc_snd_integrate(void); +extern LVAL xlc_snd_log(void); +extern LVAL xlc_snd_lpreson(void); +extern LVAL xlc_snd_maxv(void); +extern LVAL xlc_snd_offset(void); +extern LVAL xlc_snd_oneshot(void); +extern LVAL xlc_snd_osc(void); +extern LVAL xlc_snd_partial(void); +extern LVAL xlc_snd_pluck(void); +extern LVAL xlc_snd_prod(void); +extern LVAL xlc_snd_pwl(void); +extern LVAL xlc_snd_quantize(void); +extern LVAL xlc_snd_recip(void); +extern LVAL xlc_snd_reson(void); +extern LVAL xlc_snd_resonvc(void); +extern LVAL xlc_snd_resoncv(void); +extern LVAL xlc_snd_resonvv(void); +extern LVAL xlc_snd_sampler(void); +extern LVAL xlc_snd_normalize(void); +extern LVAL xlc_snd_shape(void); +extern LVAL xlc_snd_sine(void); +extern LVAL xlc_snd_siosc(void); +extern LVAL xlc_snd_slope(void); +extern LVAL xlc_snd_sqrt(void); +extern LVAL xlc_snd_tapf(void); +extern LVAL xlc_snd_tapv(void); +extern LVAL xlc_snd_tone(void); +extern LVAL xlc_snd_tonev(void); +extern LVAL xlc_snd_up(void); +extern LVAL xlc_snd_white(void); +extern LVAL xlc_snd_stkrev(void); +extern LVAL xlc_snd_stkpitshift(void); +extern LVAL xlc_snd_stkchorus(void); +extern LVAL xlc_snd_bowed(void); +extern LVAL xlc_snd_bowed_freq(void); +extern LVAL xlc_snd_bandedwg(void); +extern LVAL xlc_snd_mandolin(void); +extern LVAL xlc_snd_sitar(void); +extern LVAL xlc_snd_modalbar(void); +extern LVAL xlc_snd_flute(void); +extern LVAL xlc_snd_flute_freq(void); +extern LVAL xlc_snd_flute_all(void); +extern LVAL xlc_snd_fmfb(void); +extern LVAL xlc_snd_fmfbv(void); diff --git a/nyqsrc/sndfnintptrs.h b/nyqsrc/sndfnintptrs.h new file mode 100644 index 0000000..67f48b5 --- /dev/null +++ b/nyqsrc/sndfnintptrs.h @@ -0,0 +1,127 @@ + { "SND-SET-LATENCY", S, xlc_snd_set_latency}, + { "SOUNDP", S, xlc_soundp}, + { "HZ-TO-STEP", S, xlc_hz_to_step}, + { "SND-SET-LOGICAL-STOP", S, xlc_snd_set_logical_stop}, + { "LOG", S, xlc_log}, + { "SND-SREF", S, xlc_snd_sref}, + { "SREF-INVERSE", S, xlc_sref_inverse}, + { "SND-STOP-TIME", S, xlc_snd_stop_time}, + { "SND-TIME", S, xlc_snd_time}, + { "SND-SRATE", S, xlc_snd_srate}, + { "SND-T0", S, xlc_snd_t0}, + { "SND-XFORM", S, xlc_snd_xform}, + { "BLOCK-WATCH", S, xlc_block_watch}, + { "SOUND-NTH-BLOCK", S, xlc_sound_nth_block}, + { "SND-COPY", S, xlc_snd_copy}, + { "SND-PRINT", S, xlc_snd_print}, + { "SND-PLAY", S, xlc_snd_play}, + { "STATS", S, xlc_stats}, + { "SND-PRINT-TREE", S, xlc_snd_print_tree}, + { "SND-SCALE", S, xlc_snd_scale}, + { "SND-ZERO", S, xlc_snd_zero}, + { "STEP-TO-HZ", S, xlc_step_to_hz}, + { "SND-ADD", S, xlc_snd_add}, + { "SND-AVG", S, xlc_snd_avg}, + { "SND-COMPOSE", S, xlc_snd_compose}, + { "SND-CONVOLVE", S, xlc_snd_convolve}, + { "SND-DOWN", S, xlc_snd_down}, + { "SND-FFT", S, xlc_snd_fft}, + { "SND-INVERSE", S, xlc_snd_inverse}, + { "SND-MULTISEQ", S, xlc_snd_multiseq}, + { "SND-RESAMPLE", S, xlc_snd_resample}, + { "SND-RESAMPLEV", S, xlc_snd_resamplev}, + { "SND-FROM-ARRAY", S, xlc_snd_from_array}, + { "SND-SAMPLES", S, xlc_snd_samples}, + { "SND-LENGTH", S, xlc_snd_length}, + { "SND-MAXSAMP", S, xlc_snd_maxsamp}, + { "SND-FETCH", S, xlc_snd_fetch}, + { "SND-FETCH-ARRAY", S, xlc_snd_fetch_array}, + { "SND-MAX", S, xlc_snd_max}, + { "SND-READ", S, xlc_snd_read}, + { "SND-SEQ", S, xlc_snd_seq}, + { "SND-SLIDER", S, xlc_snd_slider}, + { "SND-SAVE", S, xlc_snd_save}, + { "SND-OVERWRITE", S, xlc_snd_overwrite}, + { "SND-YIN", S, xlc_snd_yin}, + { "SND-TRIGGER", S, xlc_snd_trigger}, + { "SND-LPANAL", S, xlc_snd_lpanal}, + { "SND-PHASEVOCODER", S, xlc_snd_phasevocoder}, + { "SND-ABS", S, xlc_snd_abs}, + { "SND-ALLPOLES", S, xlc_snd_allpoles}, + { "SND-ALPASS", S, xlc_snd_alpass}, + { "SND-ALPASSCV", S, xlc_snd_alpasscv}, + { "SND-ALPASSVV", S, xlc_snd_alpassvv}, + { "SND-AMOSC", S, xlc_snd_amosc}, + { "SND-ARESON", S, xlc_snd_areson}, + { "SND-ARESONVC", S, xlc_snd_aresonvc}, + { "SND-ARESONCV", S, xlc_snd_aresoncv}, + { "SND-ARESONVV", S, xlc_snd_aresonvv}, + { "SND-ATONE", S, xlc_snd_atone}, + { "SND-ATONEV", S, xlc_snd_atonev}, + { "SND-BIQUAD", S, xlc_snd_biquad}, + { "SND-BUZZ", S, xlc_snd_buzz}, + { "SND-CHASE", S, xlc_snd_chase}, + { "SND-CLIP", S, xlc_snd_clip}, + { "SND-CONGEN", S, xlc_snd_congen}, + { "SND-CONST", S, xlc_snd_const}, + { "SND-COTERM", S, xlc_snd_coterm}, + { "SND-DELAY", S, xlc_snd_delay}, + { "SND-DELAYCV", S, xlc_snd_delaycv}, + { "SND-EQBANDVVV", S, xlc_snd_eqbandvvv}, + { "SND-EXP", S, xlc_snd_exp}, + { "SND-FOLLOW", S, xlc_snd_follow}, + { "SND-FMOSC", S, xlc_snd_fmosc}, + { "SND-FROMOBJECT", S, xlc_snd_fromobject}, + { "SND-FROMARRAYSTREAM", S, xlc_snd_fromarraystream}, + { "SND-GATE", S, xlc_snd_gate}, + { "SND-IFFT", S, xlc_snd_ifft}, + { "SND-CLARINET", S, xlc_snd_clarinet}, + { "SND-CLARINET_ALL", S, xlc_snd_clarinet_all}, + { "SND-CLARINET_FREQ", S, xlc_snd_clarinet_freq}, + { "SND-SAX", S, xlc_snd_sax}, + { "SND-SAX_ALL", S, xlc_snd_sax_all}, + { "SND-SAX_FREQ", S, xlc_snd_sax_freq}, + { "SND-INTEGRATE", S, xlc_snd_integrate}, + { "SND-LOG", S, xlc_snd_log}, + { "SND-LPRESON", S, xlc_snd_lpreson}, + { "SND-MAXV", S, xlc_snd_maxv}, + { "SND-OFFSET", S, xlc_snd_offset}, + { "SND-ONESHOT", S, xlc_snd_oneshot}, + { "SND-OSC", S, xlc_snd_osc}, + { "SND-PARTIAL", S, xlc_snd_partial}, + { "SND-PLUCK", S, xlc_snd_pluck}, + { "SND-PROD", S, xlc_snd_prod}, + { "SND-PWL", S, xlc_snd_pwl}, + { "SND-QUANTIZE", S, xlc_snd_quantize}, + { "SND-RECIP", S, xlc_snd_recip}, + { "SND-RESON", S, xlc_snd_reson}, + { "SND-RESONVC", S, xlc_snd_resonvc}, + { "SND-RESONCV", S, xlc_snd_resoncv}, + { "SND-RESONVV", S, xlc_snd_resonvv}, + { "SND-SAMPLER", S, xlc_snd_sampler}, + { "SND-NORMALIZE", S, xlc_snd_normalize}, + { "SND-SHAPE", S, xlc_snd_shape}, + { "SND-SINE", S, xlc_snd_sine}, + { "SND-SIOSC", S, xlc_snd_siosc}, + { "SND-SLOPE", S, xlc_snd_slope}, + { "SND-SQRT", S, xlc_snd_sqrt}, + { "SND-TAPF", S, xlc_snd_tapf}, + { "SND-TAPV", S, xlc_snd_tapv}, + { "SND-TONE", S, xlc_snd_tone}, + { "SND-TONEV", S, xlc_snd_tonev}, + { "SND-UP", S, xlc_snd_up}, + { "SND-WHITE", S, xlc_snd_white}, + { "SND-STKREV", S, xlc_snd_stkrev}, + { "SND-STKPITSHIFT", S, xlc_snd_stkpitshift}, + { "SND-STKCHORUS", S, xlc_snd_stkchorus}, + { "SND-BOWED", S, xlc_snd_bowed}, + { "SND-BOWED_FREQ", S, xlc_snd_bowed_freq}, + { "SND-BANDEDWG", S, xlc_snd_bandedwg}, + { "SND-MANDOLIN", S, xlc_snd_mandolin}, + { "SND-SITAR", S, xlc_snd_sitar}, + { "SND-MODALBAR", S, xlc_snd_modalbar}, + { "SND-FLUTE", S, xlc_snd_flute}, + { "SND-FLUTE_FREQ", S, xlc_snd_flute_freq}, + { "SND-FLUTE_ALL", S, xlc_snd_flute_all}, + { "SND-FMFB", S, xlc_snd_fmfb}, + { "SND-FMFBV", S, xlc_snd_fmfbv}, diff --git a/nyqsrc/sndmax.c b/nyqsrc/sndmax.c new file mode 100644 index 0000000..a91297b --- /dev/null +++ b/nyqsrc/sndmax.c @@ -0,0 +1,73 @@ +/* sndmax.c -- computes the maximum amplitude in a sound */ + + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm min->MIN; fix compiler warning + * 31Jan07 rbd handle negative scale factors + */ + +#ifdef UNIX +#include "sys/types.h" +#endif +#include +/* #include "snd.h" */ +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "sndmax.h" +#include "extern.h" + +double sound_max(LVAL snd_expr, long n) +{ + LVAL s_as_lval; + sound_type s = NULL; + long blocklen; + sample_block_values_type sbufp; + register double maximum = 0; + + s_as_lval = xleval(snd_expr); + /* BE CAREFUL - DO NOT ALLOW GC TO RUN WHILE LVAL IS UNPROTECTED */ + if (exttypep(s_as_lval, a_sound)) { + /* if snd_expr was simply a symbol, then s now points to + a shared sound_node. If we read samples from it, then + the sound bound to the symbol will be destroyed, so + copy it first. If snd_expr was a real expression that + computed a new value, then the next garbage collection + will reclaim the sound_node. We need to make the new + sound reachable by the garbage collector to that any + lisp data reachable from the sound do not get collected. + To make the sound reachable, we need to allocate a node, + and the GC might run, so we need to protect the OLD s + but then make it unreachable. + We will let the GC collect the sound in the end. + */ + xlprot1(s_as_lval); + s = sound_copy(getsound(s_as_lval)); + s_as_lval = cvsound(s); /* destroys only ref. to original */ + /* printf("sound_max: copy is %x, lval %x\n", s, s_as_lval); */ + while (n > 0) { + long togo, j; + sample_block_type sampblock = + sound_get_next(s, &blocklen); + if (sampblock == zero_block || blocklen == 0) { + break; + } + togo = MIN(blocklen, n); + sbufp = sampblock->samples; + for (j = 0; j < togo; j++) { + register double samp = *sbufp++; + if (samp > maximum) maximum = samp; + else if (-samp > maximum) maximum = -samp; + } + n -= togo; + } + xlpop(); + } else { + xlerror("sound_max: expression did not return a sound", + s_as_lval); + } + return fabs(maximum * s->scale); +} + + diff --git a/nyqsrc/sndmax.h b/nyqsrc/sndmax.h new file mode 100644 index 0000000..b18f294 --- /dev/null +++ b/nyqsrc/sndmax.h @@ -0,0 +1,4 @@ +/* sndmax.h -- header to write sounds to files */ + +double sound_max(LVAL snd_expr, long n); +/* LISP: (SND-MAX ANY FIXNUM) */ diff --git a/nyqsrc/sndread.c b/nyqsrc/sndread.c new file mode 100644 index 0000000..5087abb --- /dev/null +++ b/nyqsrc/sndread.c @@ -0,0 +1,297 @@ +/* sndread.c -- read sound files */ + +/* CHANGELOG + * + * 29Jun95 RBD ULAW fixed problems with signed chars + * 28Apr03 dm explicitly declare sndread_file_open_count as int + * 24Jul08 RBD & Judy Hawkins -- replace snd with PortAudio and libsndfile + */ + +#include "switches.h" +#include "stdio.h" +#include "string.h" +#ifdef UNIX +#include "sys/file.h" +#else +/* #include */ +#ifdef WINDOWS +#include +#include "io.h" +#else +#include +#endif +#define L_SET SEEK_SET +#define L_INCR SEEK_CUR +#define PROTECTION +#endif +#ifndef mips +#include "stdlib.h" +#endif +#include "sndfile.h" +#include "xlisp.h" +#include "sound.h" +#include "sndfmt.h" +#include "falloc.h" +#include "sndread.h" +#include "multiread.h" + +/* file.h doesn't define O_RDONLY under RS6K AIX */ +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif + +static int sndread_file_open_count = 0; + +void read__fetch(susp, snd_list) + register read_susp_type susp; + snd_list_type snd_list; +{ + long n; /* jlh Changed type to long, trying to make move_samples_... work */ + sample_block_type out; + register sample_block_values_type out_ptr; + /* allow up to 4 bytes/sample: jlh -- does this need to be 8? */ + /* FIX -- why 8? for doubles? Maybe it should be sizeof(sample). I think + this buffer was here to allow you to input any format and convert to + float. The assumption was no sample would be longer than 4 bytes and + after conversion, samples would be 4 byte floats. + */ + long in_count; /* jlh Trying to make move_samples_... work */ + + falloc_sample_block(out, "read__fetch"); + out_ptr = out->samples; + snd_list->block = out; + + in_count = sf_readf_float(susp->sndfile, out_ptr, max_sample_block_len); + + n = in_count; + + /* don't read too many */ + if (n > (susp->cnt - susp->susp.current)) { + n = susp->cnt - susp->susp.current; + } + + snd_list->block_len = n; + susp->susp.current += n; + + if (n == 0) { + /* we didn't read anything, but can't return length zero, so + convert snd_list to pointer to zero block */ + snd_list_terminate(snd_list); + } else if (n < max_sample_block_len) { + /* this should close file and free susp */ + snd_list_unref(snd_list->u.next); + /* if something is in buffer, terminate by pointing to zero block */ + snd_list->u.next = zero_snd_list; + } +} /* read__fetch */ + + +void read_free(read_susp_type susp) +{ + sf_close(susp->sndfile); + sndread_file_open_count--; + ffree_generic(susp, sizeof(read_susp_node), "read_free"); +} + + +void read_print_tree(read_susp_type susp, int n) +{ +} + + +LVAL snd_make_read( + unsigned char *filename, /* file to read */ + time_type offset, /* offset to skip (in seconds) */ + time_type t0, /* start time of resulting sound */ + long *format, /* AIFF, IRCAM, NeXT, etc. */ + long *channels, /* number of channels */ + long *mode, /* sample format: PCM, ALAW, etc. */ + long *bits, /* BPS: bits per sample */ + long *swap, /* swap bytes */ + double *srate, /* srate: sample rate */ + double *dur, /* duration (in seconds) to read */ + long *flags, /* which parameters have been set */ + long *byte_offset) /* byte offset in file of first sample */ +{ + register read_susp_type susp; + /* srate specified as input parameter */ + sample_type scale_factor = 1.0F; + sf_count_t frames; + double actual_dur; + + falloc_generic(susp, read_susp_node, "snd_make_read"); + memset(&(susp->sf_info), 0, sizeof(SF_INFO)); + + susp->sf_info.samplerate = ROUND(*srate); + susp->sf_info.channels = *channels; + + switch (*mode) { + case SND_MODE_ADPCM: + susp->sf_info.format = SF_FORMAT_IMA_ADPCM; + break; + case SND_MODE_PCM: + if (*bits == 8) susp->sf_info.format = SF_FORMAT_PCM_S8; + else if (*bits == 16) susp->sf_info.format = SF_FORMAT_PCM_16; + else if (*bits == 24) susp->sf_info.format = SF_FORMAT_PCM_24; + else if (*bits == 32) susp->sf_info.format = SF_FORMAT_PCM_32; + else { + susp->sf_info.format = SF_FORMAT_PCM_16; + *bits = 16; + } + break; + case SND_MODE_ULAW: + susp->sf_info.format = SF_FORMAT_ULAW; + break; + case SND_MODE_ALAW: + susp->sf_info.format = SF_FORMAT_ALAW; + break; + case SND_MODE_FLOAT: + susp->sf_info.format = SF_FORMAT_FLOAT; + break; + case SND_MODE_UPCM: + susp->sf_info.format = SF_FORMAT_PCM_U8; + *bits = 8; + break; + } + + if (*format == SND_HEAD_RAW) susp->sf_info.format |= SF_FORMAT_RAW; + + if (*swap) { + /* set format to perform a byte swap (change from cpu endian-ness) */ + /* write the code so it will only compile if one and only one + ENDIAN setting is defined */ +#ifdef XL_LITTLE_ENDIAN + long format = SF_ENDIAN_BIG; +#endif +#ifdef XL_BIG_ENDIAN + long format = SF_ENDIAN_LITTLE; +#endif + susp->sf_info.format |= format; + } + + susp->sndfile = sf_open((const char *) filename, SFM_READ, + &(susp->sf_info)); + + if (!susp->sndfile) { + char error[240]; + sprintf(error, "SND-READ: Cannot open file '%s'", filename); + xlfail(error); + } + if (susp->sf_info.channels < 1) { + sf_close(susp->sndfile); + xlfail("Must specify 1 or more channels"); + } + + /* report samplerate from file, but if user provided a double + * as sample rate, don't replace it with an integer. + */ + if ((susp->sf_info.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW) { + *srate = susp->sf_info.samplerate; + } + /* compute dur */ + frames = sf_seek(susp->sndfile, 0, SEEK_END); + actual_dur = ((double) frames) / *srate; + if (offset < 0) offset = 0; + /* round offset to an integer frame count */ + frames = (sf_count_t) (offset * *srate + 0.5); + offset = ((double) frames) / *srate; + actual_dur -= offset; + if (actual_dur < 0) { + sf_close(susp->sndfile); + xlfail("SND-READ: offset is beyond end of file"); + } + if (actual_dur < *dur) *dur = actual_dur; + + sf_seek(susp->sndfile, frames, SEEK_SET); /* return to read loc in file */ + + /* initialize susp state */ + susp->susp.sr = *srate; + susp->susp.t0 = t0; + susp->susp.mark = NULL; + susp->susp.print_tree = read_print_tree; /*jlh empty function... */ + susp->susp.current = 0; + susp->susp.log_stop_cnt = UNKNOWN; + /* watch for overflow */ + if (*dur * *srate + 0.5 > (unsigned long) 0xFFFFFFFF) { + susp->cnt = 0x7FFFFFFF; + } else { + susp->cnt = ROUND((*dur) * *srate); + } + + switch (susp->sf_info.format & SF_FORMAT_TYPEMASK) { + case SF_FORMAT_WAV: *format = SND_HEAD_WAVE; break; + case SF_FORMAT_AIFF: *format = SND_HEAD_AIFF; break; + case SF_FORMAT_AU: *format = SND_HEAD_NEXT; break; + case SF_FORMAT_RAW: *format = SND_HEAD_RAW; break; + case SF_FORMAT_PAF: *format = SND_HEAD_PAF; break; + case SF_FORMAT_SVX: *format = SND_HEAD_SVX; break; + case SF_FORMAT_NIST: *format = SND_HEAD_NIST; break; + case SF_FORMAT_VOC: *format = SND_HEAD_VOC; break; + case SF_FORMAT_W64: *format = SND_HEAD_W64; break; + case SF_FORMAT_MAT4: *format = SND_HEAD_MAT4; break; + case SF_FORMAT_MAT5: *format = SND_HEAD_MAT5; break; + case SF_FORMAT_PVF: *format = SND_HEAD_PVF; break; + case SF_FORMAT_XI: *format = SND_HEAD_XI; break; + case SF_FORMAT_HTK: *mode = SND_HEAD_HTK; break; + case SF_FORMAT_SDS: *mode = SND_HEAD_SDS; break; + case SF_FORMAT_AVR: *mode = SND_HEAD_AVR; break; + case SF_FORMAT_WAVEX: *format = SND_HEAD_WAVE; break; + case SF_FORMAT_SD2: *format = SND_HEAD_SD2; break; + case SF_FORMAT_FLAC: *format = SND_HEAD_FLAC; break; + case SF_FORMAT_CAF: *format = SND_HEAD_CAF; break; + default: *format = SND_HEAD_NONE; break; + } + *channels = susp->sf_info.channels; + switch (susp->sf_info.format & SF_FORMAT_SUBMASK) { + case SF_FORMAT_PCM_S8: *bits = 8; *mode = SND_MODE_PCM; break; + case SF_FORMAT_PCM_16: *bits = 16; *mode = SND_MODE_PCM; break; + case SF_FORMAT_PCM_24: *bits = 24; *mode = SND_MODE_PCM; break; + case SF_FORMAT_PCM_32: *bits = 32; *mode = SND_MODE_PCM; break; + case SF_FORMAT_PCM_U8: *bits = 8; *mode = SND_MODE_UPCM; break; + case SF_FORMAT_FLOAT: *bits = 32; *mode = SND_MODE_FLOAT; break; + case SF_FORMAT_DOUBLE: *bits = 64; *mode = SND_MODE_DOUBLE; break; + case SF_FORMAT_ULAW: *bits = 8; *mode = SND_MODE_ULAW; break; + case SF_FORMAT_ALAW: *bits = 8; *mode = SND_MODE_ALAW; break; + case SF_FORMAT_IMA_ADPCM: *bits = 16; *mode = SND_MODE_ADPCM; break; + case SF_FORMAT_MS_ADPCM: *bits = 16; *mode = SND_MODE_ADPCM; break; + case SF_FORMAT_GSM610: *bits = 16; *mode = SND_MODE_GSM610; break; + case SF_FORMAT_VOX_ADPCM: *bits = 16; *mode = SND_MODE_ADPCM; break; + case SF_FORMAT_G721_32: *bits = 16; *mode = SND_MODE_ADPCM; break; + case SF_FORMAT_G723_24: *bits = 16; *mode = SND_MODE_ADPCM; break; + case SF_FORMAT_G723_40: *bits = 16; *mode = SND_MODE_ADPCM; break; + case SF_FORMAT_DWVW_12: *bits = 12; *mode = SND_MODE_DWVW; break; + case SF_FORMAT_DWVW_16: *bits = 16; *mode = SND_MODE_DWVW; break; + case SF_FORMAT_DWVW_24: *bits = 24; *mode = SND_MODE_DWVW; break; + case SF_FORMAT_DWVW_N: *bits = 32; *mode = SND_MODE_DWVW; break; + case SF_FORMAT_DPCM_8: *bits = 8; *mode = SND_MODE_DPCM; break; + case SF_FORMAT_DPCM_16: *bits = 16; *mode = SND_MODE_DPCM; break; + default: *mode = SND_MODE_UNKNOWN; break; + } + sndread_file_open_count++; +#ifdef MACINTOSH + if (sndread_file_open_count > 24) { + nyquist_printf("Warning: more than 24 sound files are now open\n"); + } +#endif + /* report info back to caller */ + if ((susp->sf_info.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW) { + *flags = SND_HEAD_CHANNELS | SND_HEAD_MODE | SND_HEAD_BITS | + SND_HEAD_SRATE | SND_HEAD_LEN | SND_HEAD_TYPE; + } + if (susp->sf_info.channels == 1) { + susp->susp.fetch = read__fetch; + susp->susp.free = read_free; + susp->susp.name = "read"; + return cvsound(sound_create((snd_susp_type)susp, t0, *srate, + scale_factor)); + } else { + susp->susp.fetch = multiread_fetch; + susp->susp.free = multiread_free; + susp->susp.name = "multiread"; + return multiread_create(susp); + } +} + + + + diff --git a/nyqsrc/sndread.h b/nyqsrc/sndread.h new file mode 100644 index 0000000..73dd7fd --- /dev/null +++ b/nyqsrc/sndread.h @@ -0,0 +1,20 @@ +/* fileio.h -- Nyquist code to read sound files */ + +/* for multiple channel files, one susp is shared by all sounds */ +/* the susp in turn must point back to all sound list tails */ + +typedef struct read_susp_struct { + snd_susp_node susp; + SNDFILE *sndfile; + SF_INFO sf_info; + snd_list_type *chan; /* array of back pointers */ + long cnt; /* how many sample frames to read */ +} read_susp_node, *read_susp_type; + + +LVAL snd_make_read(unsigned char *filename, time_type offset, time_type t0, + long *format, long *channels, long *mode, long *bits, long *swap, + double *srate, double *dur, long *flags, long *byte_offset); +/* LISP: (SND-READ STRING ANYNUM ANYNUM FIXNUM* FIXNUM* FIXNUM* FIXNUM* FIXNUM* ANYNUM* ANYNUM* FIXNUM^ FIXNUM^) */ + +void read_free(); diff --git a/nyqsrc/sndseq.c b/nyqsrc/sndseq.c new file mode 100644 index 0000000..edeb8b2 --- /dev/null +++ b/nyqsrc/sndseq.c @@ -0,0 +1,349 @@ +/* sndseq.c -- return a signal until its logical stop, then + evaluate a closure to get a signal and convert to an add + of two signals */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "scale.h" +#include "add.h" +#include "extern.h" +#include "cext.h" +#include "assert.h" + +#define SNDSEQDBG 0 +#define D if (SNDSEQDBG) + +/* Note: this structure is identical to an add_susp structure up + to the field output_per_s2 so that we can convert this into + an add after eval'ing the closure. Since this struct is bigger + than an add, make sure not to clobber the "free" routine + (sndseq_free) or else we'll leak memory. + */ +typedef struct sndseq_susp_struct { + snd_susp_node susp; + boolean started; + int terminate_bits; + long terminate_cnt; + int logical_stop_bits; + boolean logically_stopped; + sound_type s1; + long s1_cnt; + sample_block_type s1_bptr; /* block pointer */ + sample_block_values_type s1_ptr; + sound_type s2; + long s2_cnt; + sample_block_type s2_bptr; /* block pointer */ + sample_block_values_type s2_ptr; + + /* support for interpolation of s2 */ + sample_type s2_x1_sample; + double s2_phase; + double s2_phase_incr; + + /* support for ramp between samples of s2 */ + double output_per_s2; + + /* sndseq-specific data starts here */ + LVAL closure; + +} sndseq_susp_node, *sndseq_susp_type; + + +void sndseq_fetch(sndseq_susp_type, snd_list_type); +void sndseq_zero_fill_fetch(sndseq_susp_type, snd_list_type); +void sndseq_free(); + +extern LVAL s_stdout; + +void sndseq_mark(sndseq_susp_type susp) +{ +/* nyquist_printf("sndseq_mark(%x)\n", susp);*/ +/* nyquist_printf("marking s1@%x in sndseq@%x\n", susp->s1, susp); */ + sound_xlmark(susp->s1); + if (susp->closure) mark(susp->closure); +} + + + +/* sndseq_fetch returns blocks of s1 until the logical stop time of s1 */ +/**/ +void sndseq_fetch(susp, snd_list) + register sndseq_susp_type susp; + snd_list_type snd_list; +{ + int togo; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + +/* nyquist_printf("sndseq_fetch called: s1_cnt %d\n", susp->s1_cnt); */ + /* + * first compute how many samples to copy (or transfer) + */ + + /* get next samples; in add, the call is: + * susp_check_term_log_block_samples(s1, s1_bptr, s1_ptr, s1_cnt, 1, 3); + * + * the plan here is tricky: if s1 has logically stopped, then evaluate + * the closure to get signal s2. Then convert sndseq into an add. + */ + if (susp->s1_cnt == 0) { + susp_get_block_samples(s1, s1_bptr, s1_ptr, s1_cnt); + if (susp->s1_ptr == zero_block->samples) { + susp->terminate_bits = 1; /* mark s1 as terminated */ + } +/* nyquist_printf("sndseq_fetch: s1-lsc %d, current %d cnt %d\n", + susp->s1->logical_stop_cnt, susp->s1->current, susp->s1_cnt); */ + } + + if (susp->s1->logical_stop_cnt != UNKNOWN && + susp->s1->logical_stop_cnt == susp->s1->current - susp->s1_cnt) { + time_type now = susp->susp.t0 + susp->susp.current / susp->susp.sr; + /* note: cons args are protected from GC: */ + LVAL result; + long delay; /* sample delay to s2 */ +/* stats();gc();stats();*/ + + xlsave1(result); + +D nyquist_printf("sndseq_fetch: about to eval closure at %g, " + "susp->susp.t0 %g, susp.current %d:\n", + now, susp->susp.t0, (int)susp->susp.current); + result = xleval(cons(susp->closure, consa(cvflonum(now)))); + + susp->logical_stop_bits = 1; /* mark s1 as logically stopped */ + if (exttypep(result, a_sound)) { + susp->s2 = sound_copy(getsound(result)); +D nyquist_printf("sndseq: copied result from closure is %p\n", + susp->s2); + } else xlerror("closure did not return a (monophonic) sound", result); +D nyquist_printf("in sndseq: logically stopped; " + "%p returned from evform\n", + susp->s2); + susp->closure = NULL; /* allow garbage collection now */ + result = NIL; + + /**** Now convert to add ****/ + susp->susp.mark = add_mark; + susp->susp.log_stop_cnt = UNKNOWN; /* will be recomputed by add */ + susp->susp.print_tree = add_print_tree; + + /* assume sample rates are the same */ + if (susp->s1->sr != susp->s2->sr) + xlfail("in sndseq: sample rates must match"); + + /* take care of scale factor, if any */ + if (susp->s2->scale != 1.0) { + // stdputstr("normalizing next sound in a seq\n"); + susp->s2 = snd_make_normalize(susp->s2); + } + + /* figure out which add fetch routine to use */ + delay = ROUND((susp->s2->t0 - now) * susp->s1->sr); + if (susp->terminate_bits) { /* s1 is done, just get s2 now */ + sound_unref(susp->s1); + susp->s1 = NULL; + if (delay > 0) { /* need to fill zeros */ + susp->susp.fetch = add_zero_fill_nn_fetch; + susp->susp.name = "sndseq:add_zero_fill_nn_fetch"; + } else { + susp->susp.fetch = add_s2_nn_fetch; + susp->susp.name = "sndseq:add_s2_nn_fetch"; + } + } else if (delay > 0) { /* fill hole between s1 and s2 */ +D stdputstr("using add_s1_nn_fetch\n"); + susp->susp.fetch = add_s1_nn_fetch; + susp->susp.name = "sndseq:add_s1_nn_fetch"; + } else { + susp->susp.fetch = add_s1_s2_nn_fetch; + susp->susp.name = "sndseq:add_s1_s2_nn_fetch"; + } + + susp->s2_phase_incr = susp->s2->sr / susp->susp.sr; + susp->output_per_s2 = susp->susp.sr / susp->s2->sr; + +D stdputstr("in sndseq: calling add's fetch\n"); + (*(susp->susp.fetch))(susp, snd_list); +D stdputstr("in sndseq: returned from add's fetch\n"); +/* gc();*/ + xlpop(); + return; + } + + /* don't run past the s1 input sample block: */ + togo = susp->s1_cnt; +/* nyquist_printf("sndseq_fetch: togo initially %d then ", togo); */ + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + togo) { + togo = susp->terminate_cnt - susp->susp.current; + } + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - susp->susp.current; + togo = MIN(togo, to_stop); + } + assert(togo >= 0); + +/* nyquist_printf("%d\n", togo);*/ + /* + * two cases: copy a partial block or manipulate pointers for copyless + * transfer of whole block (may not be full block): + * + * copy partial block when: + * o samples begin in middle of block + * o stopping time is before end of block (when other signal splits + * the block for this signal). This happens if the logical + * stop time was externally dictated and falls mid-block. + * transfer (copyless) block when: + * o the block is of maximum size + * o the block is small due to logical stop time or termination time + */ + if (susp->s1_ptr == susp->s1_bptr->samples && susp->s1_cnt == togo) { + /* + * we want to copy this whole block (starting at the beginning + * and going to the rest of the block) -- just do pointers. + */ + + /* just fetch and pass blocks on */ +/* nyquist_printf("sndseq (s1_nn) %x starting uncopy, togo %d\n", susp, togo); */ + snd_list->block = susp->s1_bptr; + /* the zero_block indicates termination, don't copy it! Use + * internal_zero_block instead. It is also filled with zeros, + * but does not indicate termination. We must check for zero_block + * because the signal may have a logical stop time specified that + * extends beyond its termination time. + */ + if (snd_list->block == zero_block) + snd_list->block = internal_zero_block; + (snd_list->block->refcnt)++; +/* nyquist_printf("sndseq (s1_nn) %x shared block %x\n", susp, susp->s1_bptr);*/ + + susp_took(s1_cnt, togo); + snd_list->block_len = togo; + } else { + /* + * we want to copy a partial block + */ + + /* snd_list is the one with a null block */ + /* put a fresh, clean block in the snd_list (get new snd_list later) */ + falloc_sample_block(out, "sndseq_fetch"); + snd_list->block = out; + out_ptr = out->samples; + /* nyquist_printf("sndseq (s1_nn) %x new block %x\n", susp, out); */ + + n = togo; + /* nyquist_printf("sndseq (s1_nn) %x starting copy loop, togo %d\n", susp, togo); */ + while (n--) { /* the inner sample computation loop */ + /* scale? */ + *out_ptr++ = *(susp->s1_ptr++); + } /* inner loop */ + + susp_took(s1_cnt, togo); + snd_list->block_len = togo; + } + + /* add a new snd_list for the susp */ + susp->susp.current += togo; + +} /* sndseq_fetch */ + + +void sndseq_free(sndseq_susp_type susp) +{ + sound_unref(susp->s1); + sound_unref(susp->s2); + ffree_generic(susp, sizeof(sndseq_susp_node), "sndseq_free"); +} + + +void sndseq_print_tree(sndseq_susp_type susp, int n) +{ + indent(n); + stdputstr("s1:"); + sound_print_tree_1(susp->s1, n); + + indent(n); + stdputstr("closure:"); + stdprint(susp->closure); + + indent(n); + stdputstr("s2:"); + sound_print_tree_1(susp->s2, n); +} + + + + +sound_type snd_make_sndseq(s1, closure) + sound_type s1; + LVAL closure; +{ + register sndseq_susp_type susp; + /* t0 specified as input parameter */ + sample_type scale_factor = 1.0F; + sound_type result; + + xlprot1(closure); + falloc_generic(susp, sndseq_susp_node, "snd_make_sndseq"); + + if (s1->scale != 1.0) { + /* stdputstr("normalizing first sound in a seq\n"); */ + s1 = snd_make_normalize(s1); + } + + susp->susp.fetch = sndseq_fetch; + + susp->terminate_cnt = UNKNOWN; + susp->terminate_bits = 0; /* bits for s1 and s2 termination */ + susp->logical_stop_bits = 0; /* bits for s1 and s2 logical stop */ + + /* initialize susp state */ + susp->susp.free = sndseq_free; + susp->susp.sr = s1->sr; + susp->susp.t0 = s1->t0; + susp->susp.mark = sndseq_mark; + susp->susp.print_tree = sndseq_print_tree; + susp->susp.name = "sndseq"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = s1->logical_stop_cnt; + if (!(susp->susp.log_stop_cnt >= 0 || susp->susp.log_stop_cnt == UNKNOWN)) { + xlerror("Behaviors in SEQ must appear in chronological order", closure); + } + susp->started = false; + susp->susp.current = 0; + susp->s1 = s1; + susp->s1_cnt = 0; + susp->s2 = NULL; + susp->s2_cnt = 0; + susp->s2_phase = 0.0; +/* susp->s2_phase_incr = ?? + susp->output_per_s2 = ?? */ + susp->closure = closure; + result = sound_create((snd_susp_type)susp, susp->susp.t0, susp->susp.sr, scale_factor); + xlpopn(1); + return result; +} + + +sound_type snd_sndseq(s1, closure) + sound_type s1; + LVAL closure; +{ + sound_type s1_copy; + s1_copy = sound_copy(s1); + return snd_make_sndseq(s1_copy, closure); +} diff --git a/nyqsrc/sndseq.h b/nyqsrc/sndseq.h new file mode 100644 index 0000000..03fdd11 --- /dev/null +++ b/nyqsrc/sndseq.h @@ -0,0 +1,3 @@ +sound_type snd_make_sndseq(); +sound_type snd_sndseq(); + /* LISP: (SND-SEQ SOUND ANY) */ diff --git a/nyqsrc/sndsliders.h b/nyqsrc/sndsliders.h new file mode 100644 index 0000000..ade86ba --- /dev/null +++ b/nyqsrc/sndsliders.h @@ -0,0 +1,5 @@ +/* sndsliders.h -- support for graphical sliders in Nyquist IDE */ + +sound_type snd_make_slider(int index, time_type t0, rate_type sr, time_type d); +sound_type snd_slider(int index, time_type t0, rate_type sr, time_type d); + /* LISP: (SND-SLIDER FIXNUM ANYNUM ANYNUM ANYNUM) */ diff --git a/nyqsrc/sndwrite.c b/nyqsrc/sndwrite.c new file mode 100644 index 0000000..653ce37 --- /dev/null +++ b/nyqsrc/sndwrite.c @@ -0,0 +1,640 @@ +/* sndwrite.c -- write sounds to files */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +#include "stdlib.h" +#include "switches.h" +#include "string.h" +#ifdef UNIX +#include "sys/types.h" +#endif +#ifdef WINDOWS +#include +#endif +#include +/* include sound.h first because it includes math.h + * which declares abs(). cext.h #defines abs()! + * sound.h depends on xlisp.h + */ +#include "xlisp.h" +#include "sound.h" +#include "cext.h" +#include "userio.h" +#include "falloc.h" +#include "sndwrite.h" +#include "extern.h" +#include "snd.h" +#ifdef UNIX +#include "sys/file.h" +/* #include */ +/* #include */ +#else +#ifdef MACINTOSH +#include +#include +#define L_SET SEEK_SET +#define L_INCR SEEK_CUR +#endif +#endif + +#define D if (0) + +int sndwrite_trace = 0; /* debugging */ + +sample_type sound_save_sound(LVAL s_as_lval, long n, snd_type snd, + char *buf, long *ntotal, snd_type player); + +sample_type sound_save_array(LVAL sa, long n, snd_type snd, + char *buf, long *ntotal, snd_type player); + +unsigned char st_linear_to_ulaw(int sample); + + +typedef struct { + sound_type sound; + long cnt; + sample_block_values_type ptr; + double scale; + int terminated; +} sound_state_node, *sound_state_type; + + +LVAL prepare_audio(LVAL play, snd_type snd, snd_type player) +{ + long flags; + if (play == NIL) return NIL; + player->format = snd->format; + player->u.audio.devicename[0] = 0; + player->u.audio.interfacename[0] = 0; + if (snd_open(player, &flags) != SND_SUCCESS) { + xlabort("snd_save -- could not open audio output"); + } + /* make sure player and snd are compatible -- if not, set player to NULL + * and print a warning message + */ + if (player->format.channels == snd->format.channels && + player->format.mode == snd->format.mode && + player->format.bits == snd->format.bits) { + /* ok so far, check out the sample rate */ + if (player->format.srate != snd->format.srate) { + char msg[100]; + sprintf(msg, "%s(%g)%s(%g).\n", + "Warning: file sample rate ", snd->format.srate, + " differs from audio playback sample rate ", + player->format.srate); + stdputstr(msg); + } + } else { + stdputstr("File format not supported by audio output.\n"); + return NIL; + } + return play; +} + + +/* finish_audio -- flush the remaining samples, then close */ +/**/ +void finish_audio(snd_type player) +{ + /* note that this is a busy loop! */ + while (snd_flush(player) != SND_SUCCESS) ; + snd_close(player); +} + + +/* write_to_audio -- handle audio output from buffer */ +/* + * We want to write as soon as space is available so that + * a full sound buffer can be queued up for output. This + * may require transferring only part of buf, so we keep + * track of progress and output whenever space is available. + */ +void write_to_audio(snd_type player, void *buf, long buflen) +{ + long rslt; + while (buflen) { + /* this loop is a busy-wait loop! */ + rslt = snd_poll(player); /* wait for buffer space */ + rslt = min(rslt, buflen); + if (rslt) { + snd_write(player, buf, rslt); + buf = (void *) ((char *) buf + + (rslt * snd_bytes_per_frame(player))); + buflen -= rslt; + } + } +} + + +double sound_save( + LVAL snd_expr, + long n, + unsigned char *filename, + long format, + long mode, + long bits, + long swap, + double *sr, + long *nchans, + double *duration, + LVAL play) +{ + LVAL result; + char *buf; + long ntotal; + double max_sample; + snd_node snd; + snd_node player; + long flags; + + snd.device = SND_DEVICE_FILE; + snd.write_flag = SND_WRITE; + strcpy(snd.u.file.filename, (char *) filename); + snd.u.file.file = -1; /* this is a marker that snd is unopened */ + snd.u.file.header = format; + snd.format.mode = mode; + snd.format.bits = bits; + snd.u.file.swap = swap; + + player.device = SND_DEVICE_AUDIO; + player.write_flag = SND_WRITE; + player.u.audio.devicename[0] = '\0'; + player.u.audio.descriptor = NULL; + player.u.audio.protocol = SND_COMPUTEAHEAD; + player.u.audio.latency = 1.0; + player.u.audio.granularity = 0.0; + + if ((buf = (char *) malloc(max_sample_block_len * MAX_SND_CHANNELS * + sizeof(float))) == NULL) { + xlabort("snd_save -- couldn't allocate memory"); + } + + result = xleval(snd_expr); + /* BE CAREFUL - DO NOT ALLOW GC TO RUN WHILE RESULT IS UNPROTECTED */ + if (vectorp(result)) { + /* make sure all elements are of type a_sound */ + long i = getsize(result); + *nchans = snd.format.channels = i; + while (i > 0) { + i--; + if (!exttypep(getelement(result, i), a_sound)) { + xlerror("sound_save: array has non-sound element", + result); + } + } + /* assume all are the same: */ + *sr = snd.format.srate = getsound(getelement(result, 0))->sr; + + /* note: if filename is "", then don't write file; therefore, + * write the file if (filename[0]) + */ + if (filename[0] && snd_open(&snd, &flags) != SND_SUCCESS) { + xlabort("snd_save -- could not open sound file"); + } + + play = prepare_audio(play, &snd, &player); + + max_sample = sound_save_array(result, n, &snd, + buf, &ntotal, (play == NIL ? NULL : &player)); + *duration = ntotal / *sr; + if (filename[0]) snd_close(&snd); + if (play != NIL) finish_audio(&player); + } else if (exttypep(result, a_sound)) { + *nchans = snd.format.channels = 1; + *sr = snd.format.srate = (getsound(result))->sr; + if (filename[0] && snd_open(&snd, &flags) != SND_SUCCESS) { + xlabort("snd_save -- could not open sound file"); + } + + play = prepare_audio(play, &snd, &player); + + max_sample = sound_save_sound(result, n, &snd, + buf, &ntotal, (play == NIL ? NULL : &player)); + *duration = ntotal / *sr; + if (filename[0]) snd_close(&snd); + if (play != NIL) finish_audio(&player); + } else { + xlerror("sound_save: expression did not return a sound", + result); + max_sample = 0.0; + } + free(buf); + return max_sample; +} + + +double sound_overwrite( + LVAL snd_expr, + long n, + unsigned char *filename, + long byte_offset, + long header, + long mode, + long bits, + long swap, + double sr, + long nchans, + double *duration) +{ + LVAL result; + char *buf; + char error[140]; + long ntotal; + double max_sample; + snd_node snd; + long flags; + + snd.device = SND_DEVICE_FILE; + snd.write_flag = SND_OVERWRITE; + strcpy(snd.u.file.filename, (char *) filename); + snd.u.file.header = header; + snd.u.file.byte_offset = byte_offset; + snd.format.channels = nchans; + snd.format.mode = mode; + snd.format.bits = bits; + snd.u.file.swap = swap; + snd.format.srate = sr; + + if ((buf = (char *) malloc(max_sample_block_len * MAX_SND_CHANNELS * + sizeof(float))) == NULL) { + xlabort("snd_overwrite: couldn't allocate memory"); + } + + if (snd_open(&snd, &flags) != SND_SUCCESS) { + sprintf(error, + "snd_overwrite: cannot open file %s and seek to %d", + filename, (int)byte_offset); + free(buf); + xlabort(error); + } + + result = xleval(snd_expr); + /* BE CAREFUL - DO NOT ALLOW GC TO RUN WHILE RESULT IS UNPROTECTED */ + if (vectorp(result)) { + /* make sure all elements are of type a_sound */ + long i = getsize(result); + if (nchans != i) { + sprintf(error, "%s%d%s%d%s", + "snd_overwrite: number of channels in sound (", + (int)i, + ") does not match\n number of channels in file (", + (int)nchans, + ")"); + free(buf); + snd_close(&snd); + xlabort(error); + } + while (i > 0) { + i--; + if (!exttypep(getelement(result, i), a_sound)) { + free(buf); + snd_close(&snd); + xlerror("sound_save: array has non-sound element", + result); + } + } + /* assume all are the same: */ + if (sr != getsound(getelement(result, 0))->sr) { + sprintf(error, "%s%g%s%g%s", + "snd_overwrite: sample rate in sound (", + getsound(getelement(result, 0))->sr, + ") does not match\n sample rate in file (", + sr, + ")"); + free(buf); + snd_close(&snd); + xlabort(error); + } + + max_sample = sound_save_array(result, n, &snd, buf, &ntotal, NULL); + *duration = ntotal / sr; + } else if (exttypep(result, a_sound)) { + if (nchans != 1) { + sprintf(error, "%s%s%d%s", + "snd_overwrite: number of channels in sound (1", + ") does not match\n number of channels in file (", + (int)nchans, + ")"); + free(buf); + snd_close(&snd); + xlabort(error); + } + + if (sr != getsound(result)->sr) { + sprintf(error, "%s%g%s%g%s", + "snd_overwrite: sample rate in sound (", + getsound(result)->sr, + ") does not match\n sample rate in file (", + sr, + ")"); + free(buf); + snd_close(&snd); + xlabort(error); + } + + max_sample = sound_save_sound(result, n, &snd, buf, &ntotal, NULL); + *duration = ntotal / sr; + } else { + free(buf); + snd_close(&snd); + xlerror("sound_save: expression did not return a sound", + result); + max_sample = 0.0; + } + free(buf); + snd_close(&snd); + return max_sample; +} + + +cvtfn_type find_cvt_to_fn(snd_type snd, char *buf) +{ + cvtfn_type cvtfn; + /* find the conversion function */ + if (snd->format.bits == 8) cvtfn = cvt_to_8[snd->format.mode]; + else if (snd->format.bits == 16) cvtfn = cvt_to_16[snd->format.mode]; + else if (snd->format.bits == 24) cvtfn = cvt_to_24[snd->format.mode]; + else if (snd->format.bits == 32) cvtfn = cvt_to_32[snd->format.mode]; + else cvtfn = cvt_to_unknown; + + if (cvtfn == cvt_to_unknown) { + char error[50]; + sprintf(error, "Cannot write %d-bit samples in mode %s", + (int)snd->format.bits, snd_mode_to_string(snd->format.mode)); + free(buf); + snd_close(snd); + xlabort(error); + } + return cvtfn; +} + + +sample_type sound_save_sound(LVAL s_as_lval, long n, snd_type snd, + char *buf, long *ntotal, snd_type player) +{ + long blocklen; + long buflen; + sound_type s; + long debug_unit; /* print messages at intervals of this many samples */ + long debug_count; /* next point at which to print a message */ + sample_type max_sample = 0.0F; + cvtfn_type cvtfn; + *ntotal = 0; + + /* if snd_expr was simply a symbol, then s now points to + a shared sound_node. If we read samples from it, then + the sound bound to the symbol will be destroyed, so + copy it first. If snd_expr was a real expression that + computed a new value, then the next garbage collection + will reclaim the sound_node. We need to make the new + sound reachable by the garbage collector to that any + lisp data reachable from the sound do not get collected. + To make the sound reachable, we need to allocate a node, + and the GC might run, so we need to protect the OLD s + but then make it unreachable. + We will let the GC collect the sound in the end. + */ + xlprot1(s_as_lval); + s = sound_copy(getsound(s_as_lval)); + s_as_lval = cvsound(s); /* destroys only ref. to original */ + + /* for debugging */ +/* printing_this_sound = s;*/ + + + debug_unit = debug_count = (long) max(snd->format.srate, 10000.0); + + cvtfn = find_cvt_to_fn(snd, buf); + +#ifdef MACINTOSH + if (player) { + gprintf(TRANS, "Playing audio: Click and hold mouse button to stop playback.\n"); + } +#endif + + while (n > 0) { + long togo; + float peak; + sample_block_type sampblock = sound_get_next(s, &blocklen); + oscheck(); +#ifdef SNAPSHOTS + stdputstr("."); + if (sound_created_flag) { + stdputstr("SNAPSHOT: "); + sound_print_tree(printing_this_sound); + sound_created_flag = false; + } + fflush(stdout); +#endif + if (sampblock == zero_block || blocklen == 0) { + break; + } + togo = min(blocklen, n); + + buflen = (*cvtfn)((void *) buf, (void *) sampblock->samples, + togo, s->scale, &peak); + if (peak > max_sample) max_sample = peak; + +#ifdef MACINTOSH + if (Button()) { + if (player) { + snd_reset(player); + } + gprintf(TRANS, "\n\nStopping playback...\n\n\n"); + break; + } +#endif + + if (snd->u.file.file != -1) snd_write(snd, (void *) buf, buflen); + if (player) write_to_audio(player, (void *) buf, buflen); + + n -= togo; + *ntotal += togo; + if (*ntotal > debug_count) { + gprintf(TRANS, " %d ", *ntotal); + fflush(stdout); + debug_count += debug_unit; + } + } + gprintf(TRANS, "\ntotal samples: %d\n", *ntotal); + xlpop(); + return max_sample; +} + + +sample_type sound_save_array(LVAL sa, long n, snd_type snd, + char *buf, long *ntotal, snd_type player) +{ + long i, chans; + long buflen; + sound_state_type state; + double start_time = HUGE_VAL; + float *float_bufp; + LVAL sa_copy; + long debug_unit; /* print messages at intervals of this many samples */ + long debug_count; /* next point at which to print a message */ + sample_type max_sample = 0.0F; + cvtfn_type cvtfn; + + *ntotal = 0; + + /* THE ALGORITHM: first merge floating point samples from N channels + * into consecutive multi-channel frames in buf. Then, treat buf + * as just one channel and use one of the cvt_to_* functions to + * convert the data IN PLACE in the buffer (this is ok because the + * converted data will never take more space than the original 32-bit + * floats, so the converted data will not overwrite any floats before + * the floats are converted + */ + + /* if snd_expr was simply a symbol, then sa now points to + a shared sound_node. If we read samples from it, then + the sounds bound to the symbol will be destroyed, so + copy it first. If snd_expr was a real expression that + computed a new value, then the next garbage collection + will reclaim the sound array. See also sound_save_sound() + */ + chans = getsize(sa); + if (chans > MAX_SND_CHANNELS) { + xlerror("sound_save: too many channels", sa); + free(buf); + snd_close(snd); + } + xlprot1(sa); + sa_copy = newvector(chans); + xlprot1(sa_copy); + + /* Why do we copy the array into an xlisp array instead of just + * the state[i] array? Because some of these sounds may reference + * the lisp heap. We must put the sounds in an xlisp array so that + * the gc will find and mark them. xlprot1(sa_copy) makes the array + * visible to gc. + */ + for (i = 0; i < chans; i++) { + sound_type s = getsound(getelement(sa, i)); + setelement(sa_copy, i, cvsound(sound_copy(s))); + } + sa = sa_copy; /* destroy original reference to allow GC */ + + state = (sound_state_type) malloc(sizeof(sound_state_node) * chans); + for (i = 0; i < chans; i++) { + state[i].sound = getsound(getelement(sa, i)); + state[i].scale = state[i].sound->scale; +D nyquist_printf("save scale factor %d = %g\n", (int)i, state[i].scale); + state[i].terminated = false; + state[i].cnt = 0; /* force a fetch */ + start_time = min(start_time, state[i].sound->t0); + } + + for (i = 0; i < chans; i++) { + if (state[i].sound->t0 > start_time) + sound_prepend_zeros(state[i].sound, start_time); + } + + /* for debugging */ +/* printing_this_sound = s;*/ + + cvtfn = find_cvt_to_fn(snd, buf); + +#ifdef MACINTOSH + if (player) { + gprintf(TRANS, "Playing audio: Click and hold mouse button to stop playback.\n"); + } +#endif + + debug_unit = debug_count = (long) max(snd->format.srate, 10000.0); + + while (n > 0) { + /* keep the following information for each sound: + has it terminated? + pointer to samples + number of samples remaining in block + scan to find the minimum remaining samples and + output that many in an inner loop. Stop outer + loop if all sounds have terminated + */ + int terminated = true; + int togo = n; + int j; + float peak; + + oscheck(); + + for (i = 0; i < chans; i++) { + if (state[i].cnt == 0) { + if (sndwrite_trace) { + nyquist_printf("CALLING SOUND_GET_NEXT " + "ON CHANNEL %d (%p)\n", + (int)i, state[i].sound); + sound_print_tree(state[i].sound); + } + state[i].ptr = sound_get_next(state[i].sound, + &(state[i].cnt))->samples; + if (sndwrite_trace) { + nyquist_printf("RETURNED FROM CALL TO SOUND_GET_NEXT " + "ON CHANNEL %d\n", (int)i); + } + if (state[i].ptr == zero_block->samples) { + state[i].terminated = true; + } + } + if (!state[i].terminated) terminated = false; + togo = min(togo, state[i].cnt); + } + + if (terminated) break; + + float_bufp = (float *) buf; + for (j = 0; j < togo; j++) { + for (i = 0; i < chans; i++) { + double s = *(state[i].ptr++) * state[i].scale; + *float_bufp++ = (float) s; + } + } + // we're treating sound as mono for the conversion, so multiply + // togo by chans to get proper number of samples, and divide by + // chans to convert back to frame count required by snd_write + buflen = (*cvtfn)((void *) buf, (void *) buf, togo * chans, 1.0F, + &peak) / chans; + if (peak > max_sample) max_sample = peak; +#ifdef MACINTOSH + if (Button()) { + if (player) { + snd_reset(player); + } + gprintf(TRANS, "\n\nStopping playback...\n\n\n"); + break; + } +#endif + + if (snd->u.file.file != -1) snd_write(snd, (void *) buf, buflen); + if (player) write_to_audio(player, (void *) buf, buflen); + + n -= togo; + for (i = 0; i < chans; i++) { + state[i].cnt -= togo; + } + *ntotal += togo; + if (*ntotal > debug_count) { + gprintf(TRANS, " %d ", *ntotal); + fflush(stdout); + debug_count += debug_unit; + } + } + gprintf(TRANS, "total samples: %d x %d channels\n", + *ntotal, chans); + + /* references to sounds are shared by sa_copy and state[]. + * here, we dispose of state[], allowing GC to do the + * sound_unref call that frees the sounds. (Freeing them now + * would be a bug.) + */ + free(state); + xlpop(); + return max_sample; +} + + diff --git a/nyqsrc/sndwrite.h b/nyqsrc/sndwrite.h new file mode 100644 index 0000000..192317e --- /dev/null +++ b/nyqsrc/sndwrite.h @@ -0,0 +1,12 @@ +/* sndwrite.h -- header to write sounds to files */ + +double sound_save(LVAL snd_expr, long n, + unsigned char *filename, long format, + long mode, long bits, long swap, double *sr, long *nchans, + double *duration, LVAL play); +/* LISP: (SND-SAVE ANY FIXNUM STRING FIXNUM FIXNUM FIXNUM FIXNUM ANYNUM^ FIXNUM^ ANYNUM^ ANY) */ + +double sound_overwrite(LVAL snd_expr, long n, + unsigned char *filename, double offset_secs, long format, + long mode, long bits, long swap, double *duration); +/* LISP: (SND-OVERWRITE ANY FIXNUM STRING ANYNUM FIXNUM FIXNUM FIXNUM FIXNUM ANYNUM^) */ diff --git a/nyqsrc/sndwritepa.c b/nyqsrc/sndwritepa.c new file mode 100644 index 0000000..2f1989d --- /dev/null +++ b/nyqsrc/sndwritepa.c @@ -0,0 +1,818 @@ +/* sndwrite.c -- write sounds to files */ + +#include "stdlib.h" +#include "switches.h" +#include "string.h" +#ifdef UNIX +#include "sys/types.h" +#endif +#ifdef WINDOWS +#include +#endif +#include +/* include sound.h first because it includes math.h + * which declares abs(). cext.h #defines abs()! + * sound.h depends on xlisp.h + */ +#include "xlisp.h" +#include "sound.h" +#include "cext.h" +#include "userio.h" +#include "falloc.h" +#include "sndfmt.h" +#include "sndwrite.h" +#include "extern.h" +#include "sndfile.h" + +#ifdef UNIX +#include "sys/file.h" +/* #include */ +#include +#else +#ifdef MACINTOSH +#include +#include +#define L_SET SEEK_SET +#define L_INCR SEEK_CUR +#endif +#endif + +/* Previously, Nyquist would wrap samples that + * overflowed -- this produces horrible output, + * but makes it really easy to detect clipping, + * which I found helpful in my own work and good + * for students too since the effect is impossible + * to ignore. Now that Nyquist is doing IO to + * libraries that clip, we're going to artificially + * generate the wrapping here. This is floating point + * wrapping, so +1.0 does not wrap (it would if it + * were an integer since the maximum sample value for + * 16-bit data is a bit less than 1.) Since this is extra + * overhead, I'm trying to be a bit clever by using + * the compare to max_sample to eliminate compares + * for clipping in the common case. + * + * INPUTS: max_sample -- initially 0.0 + * threshold -- initially 0.0 + * s -- the value of the current sample + * x -- if s has to be wrapped, put the value here + */ +#define COMPUTE_MAXIMUM_AND_WRAP(x) \ + if (s > threshold) { \ + if (s > max_sample) { \ + max_sample = s; \ + threshold = min(1.0, s); \ + } \ + if (s > 1.0) { \ + s = fmod(s + 1.0, 2.0) - 1.0; \ + (x) = s; \ + } \ + } else if (s < -threshold) { \ + if (s < -max_sample) { \ + max_sample = -s; \ + threshold = min(1.0, -s); \ + } \ + if (s < -1.0) { \ + s = -(fmod(-s + 1.0, 2.0) - 1.0); \ + (x) = s; \ + } \ + } +// the s < -threshold case is tricky: +// flip the signal, do the wrap, flip again +// in order to pass positive values to fmod + + +/* When not using PCM encodings, we do not wrap + * samples -- therefore float sample formats do + * not wrap or clip when written to sound files + */ +#define COMPUTE_MAXIMUM() \ + if (s > max_sample) { \ + max_sample = s; \ + } else if (s < -max_sample) { \ + max_sample = -s; \ + } + +// should be looking for local portaudio +#include "portaudio.h" + +long flush_count = 0; /* how many samples to write to finish */ + +#define D if (0) + +int sndwrite_trace = 0; /* debugging */ + +static int portaudio_initialized = false; /* is PortAudio initialized? */ + +void portaudio_exit() +{ + if (portaudio_initialized) { + Pa_Terminate(); + } +} + + +sample_type sound_save_sound(LVAL s_as_lval, long n, SF_INFO *sf_info, SNDFILE *snd_file, + float *buf, long *ntotal, PaStream *audio_stream); + +sample_type sound_save_array(LVAL sa, long n, SF_INFO *sf_info, SNDFILE *snd_file, + float *buf, long *ntotal, PaStream *audio_stream); + +unsigned char st_linear_to_ulaw(int sample);/* jlh not used anywhere */ + + +typedef struct { + sound_type sound; + long cnt; + sample_block_values_type ptr; + double scale; + int terminated; +} sound_state_node, *sound_state_type; + + +static int portaudio_error(PaError err, char *problem) +{ + char msgbuffer[256]; + if (err != paNoError) { + sprintf(msgbuffer, "%s, error %d, %s.", problem, (int) err, + Pa_GetErrorText(err)); + xlerrprint("warning", NULL, msgbuffer, s_unbound); + return true; + } + return false; +} + + +LVAL prepare_audio(LVAL play, SF_INFO *sf_info, PaStream **audio_stream) +{ + PaStreamParameters output_parameters; + int i; + int num_devices; + const PaDeviceInfo *device_info; + const PaHostApiInfo *host_info; + + if (!portaudio_initialized) { + if (portaudio_error(Pa_Initialize(), + "could not initialize portaudio")) { + return NIL; + } + portaudio_initialized = TRUE; + } + + output_parameters.device = Pa_GetDefaultOutputDevice(); + output_parameters.channelCount = sf_info->channels; + output_parameters.sampleFormat = paFloat32; + output_parameters.hostApiSpecificStreamInfo = NULL; + /* remember that Nyquist has to do GC */ + output_parameters.suggestedLatency = sound_latency; + + // Initialize the audio stream for output + // If this is Linux, prefer to open ALSA device + num_devices = Pa_GetDeviceCount(); + for (i = 0; i < num_devices; i++) { + device_info = Pa_GetDeviceInfo(i); + host_info = Pa_GetHostApiInfo(device_info->hostApi); + if (host_info->type == paALSA) { + output_parameters.device = i; + break; + } + } + + if (portaudio_error( + Pa_OpenStream(audio_stream, NULL /* input */, &output_parameters, + sf_info->samplerate, max_sample_block_len, + paClipOff, NULL /* callback */, NULL /* userdata */), + "could not open audio")) { + return NIL; + } + flush_count = (long) (sf_info->samplerate * (sound_latency + 0.2)); + + if (portaudio_error(Pa_StartStream(*audio_stream), + "could not start audio")) { + return NIL; + } + + return play; +} + + +/* finish_audio -- flush the remaining samples, then close */ +/**/ +void finish_audio(PaStream *audio_stream) +{ + /* portaudio_error(Pa_StopStream(audio_stream), "could not stop stream"); */ + /* write Latency frames of audio to make sure all samples are played */ + float zero[MAX_SND_CHANNELS * 16]; + int i; + for (i = 0; i < MAX_SND_CHANNELS * 16; i++) zero[i] = 0.0F; + while (flush_count > 0) { + Pa_WriteStream(audio_stream, zero, 16); + flush_count -= 16; + } + portaudio_error(Pa_CloseStream(audio_stream), "could not close audio"); +} + +long lookup_format(long format, long mode, long bits, long swap) +{ + long sf_mode; + long sf_format; + + switch (format) { + case SND_HEAD_NONE: return 0; break; // get info from file + case SND_HEAD_AIFF: sf_format = SF_FORMAT_AIFF; break; + case SND_HEAD_IRCAM: sf_format = SF_FORMAT_IRCAM; break; + case SND_HEAD_NEXT: sf_format = SF_FORMAT_AU; break; + case SND_HEAD_WAVE: sf_format = SF_FORMAT_WAV; break; + case SND_HEAD_PAF: sf_format = SF_FORMAT_PAF; break; + case SND_HEAD_SVX: sf_format = SF_FORMAT_SVX; break; + case SND_HEAD_NIST: sf_format = SF_FORMAT_NIST; break; + case SND_HEAD_VOC: sf_format = SF_FORMAT_VOC; break; + case SND_HEAD_W64: sf_format = SF_FORMAT_W64; break; + case SND_HEAD_MAT4: sf_format = SF_FORMAT_MAT4; break; + case SND_HEAD_MAT5: sf_format = SF_FORMAT_MAT5; break; + case SND_HEAD_PVF: sf_format = SF_FORMAT_PVF; break; + case SND_HEAD_XI: sf_format = SF_FORMAT_XI; break; + case SND_HEAD_HTK: sf_format = SF_FORMAT_HTK; break; + case SND_HEAD_SDS: sf_format = SF_FORMAT_SDS; break; + case SND_HEAD_AVR: sf_format = SF_FORMAT_AVR; break; + case SND_HEAD_SD2: sf_format = SF_FORMAT_SD2; break; + case SND_HEAD_FLAC: sf_format = SF_FORMAT_FLAC; break; + case SND_HEAD_CAF: sf_format = SF_FORMAT_CAF; break; + case SND_HEAD_RAW: + sf_format = SF_FORMAT_RAW; +#ifdef XL_BIG_ENDIAN + sf_format |= (swap ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG); +#endif +#ifdef XL_LITTLE_ENDIAN + sf_format |= (swap ? SF_ENDIAN_LITTLE : SF_ENDIAN_LITTLE); +#endif + break; + default: + sf_format = SF_FORMAT_WAV; + nyquist_printf("s-save: unrecognized format, using SND_HEAD_WAVE\n"); + break; + } + + switch (mode) { + case SND_MODE_ADPCM: sf_mode = SF_FORMAT_IMA_ADPCM; break; + case SND_MODE_UPCM: + if (bits <= 8) { + sf_mode = SF_FORMAT_PCM_U8; break; + } else { + nyquist_printf("s-save: SND_MODE_UPCM is for 8-bit samples only, " + "using PCM instead\n"); + } /* no break here, fall through to SND_MODE_PCM... */ + default: + nyquist_printf("s-save: unrecognized mode (%ld), using PCM\n", + mode); + /* no break, fall through as SND_MODE_PCM */ + case SND_MODE_PCM: + if (bits <= 8) sf_mode = SF_FORMAT_PCM_S8; + else if (bits <= 16) sf_mode = SF_FORMAT_PCM_16; + else if (bits <= 24) sf_mode = SF_FORMAT_PCM_24; + else if (bits <= 32) sf_mode = SF_FORMAT_PCM_32; + else { + sf_mode = SF_FORMAT_PCM_16; + nyquist_printf( + "s-save: bad bits parameter (%ld), using 16-bit PCM\n", + bits); + } + break; + case SND_MODE_ULAW: sf_mode = SF_FORMAT_ULAW; break; + case SND_MODE_ALAW: sf_mode = SF_FORMAT_ALAW; break; + case SND_MODE_FLOAT: sf_mode = SF_FORMAT_FLOAT; break; + case SND_MODE_DOUBLE: sf_mode = SF_FORMAT_DOUBLE; break; + case SND_MODE_UNKNOWN: sf_mode = SF_FORMAT_PCM_16; break; + case SND_MODE_GSM610: sf_mode = SF_FORMAT_GSM610; break; + case SND_MODE_DWVW: + if (bits <= 12) sf_mode = SF_FORMAT_DWVW_12; + else if (bits <= 16) sf_mode = SF_FORMAT_DWVW_16; + else if (bits <= 24) sf_mode = SF_FORMAT_DWVW_24; + else sf_mode = SF_FORMAT_DWVW_N; + break; + case SND_MODE_DPCM: + if (bits <= 8) sf_mode = SF_FORMAT_DPCM_8; + else if (bits <= 16) sf_mode = SF_FORMAT_DPCM_16; + else { + sf_mode = SF_FORMAT_DPCM_16; + nyquist_printf( + "s-save: bad bits parameter (%ld), using 16-bit DPCM\n", + bits); + } + break; + case SND_MODE_MSADPCM: sf_mode = SF_FORMAT_MS_ADPCM; break; + } + return sf_format | sf_mode; +} + + +double sound_save( + LVAL snd_expr, + long n, + unsigned char *filename, + long format, + long mode, + long bits, + long swap, + double *sr, + long *nchans, + double *duration, + LVAL play) +{ + LVAL result; + float *buf; + long ntotal; + double max_sample; + SNDFILE *sndfile = NULL; + SF_INFO sf_info; + PaStream *audio_stream = NULL; + + gc(); + + memset(&sf_info, 0, sizeof(sf_info)); + sf_info.format = lookup_format(format, mode, bits, swap); + + result = xleval(snd_expr); + /* BE CAREFUL - DO NOT ALLOW GC TO RUN WHILE RESULT IS UNPROTECTED */ + if (vectorp(result)) { + /* make sure all elements are of type a_sound */ + long i = getsize(result); + *nchans = sf_info.channels = i; + while (i > 0) { + i--; + if (!exttypep(getelement(result, i), a_sound)) { + xlerror("sound_save: array has non-sound element", + result); + } + } + /* assume all are the same: */ + *sr = sf_info.samplerate = ROUND(getsound(getelement(result, 0))->sr); + + /* note: if filename is "", then don't write file; therefore, + * write the file if (filename[0]) + */ + if (filename[0]) { + sndfile = sf_open((char *) filename, SFM_WRITE, &sf_info); + if (sndfile) { + /* use proper scale factor: 8000 vs 7FFF */ + sf_command(sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE); + } + } + + if (play) + play = prepare_audio(play, &sf_info, &audio_stream); + + if ((buf = (float *) malloc(max_sample_block_len * sf_info.channels * + sizeof(float))) == NULL) { + xlabort("snd_save -- couldn't allocate memory"); + } + + max_sample = sound_save_array(result, n, &sf_info, sndfile, + buf, &ntotal, audio_stream); + *duration = ntotal / *sr; + if (sndfile) sf_close(sndfile); + if (play != NIL) finish_audio(audio_stream); + } else if (exttypep(result, a_sound)) { + *nchans = sf_info.channels = 1; + sf_info.samplerate = ROUND((getsound(result))->sr); + *sr = sf_info.samplerate; + if (filename[0]) { + sndfile = sf_open((char *) filename, SFM_WRITE, &sf_info); + if (sndfile) { + /* use proper scale factor: 8000 vs 7FFF */ + sf_command(sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE); + } else xlabort("snd_save -- could not open file or bad parameters"); + } + if (play) + play = prepare_audio(play, &sf_info, &audio_stream); + + if ((buf = (float *) malloc(max_sample_block_len * + sizeof(float))) == NULL) { + xlabort("snd_save -- couldn't allocate memory"); + } + + max_sample = sound_save_sound(result, n, &sf_info, sndfile, + buf, &ntotal, audio_stream); + *duration = ntotal / *sr; + if (sndfile) sf_close(sndfile); + if (play != NIL) finish_audio(audio_stream); + } else { + xlerror("sound_save: expression did not return a sound", + result); + max_sample = 0.0; + } + free(buf); + return max_sample; +} + + +/* open_for_write -- helper function for sound_overwrite */ +/* + * if the format is RAW, then fill in sf_info according to + * sound sample rate and channels. Otherwise, open the file + * and see if the sample rate and channele match. + */ +SNDFILE *open_for_write(unsigned char *filename, long direction, + long format, SF_INFO *sf_info, int channels, + long srate, double offset, float **buf) +/* channels and srate are based on the sound we're writing to the file */ +{ + SNDFILE *sndfile; + sf_count_t frames; // frame count passed into sf_seek + char error[140]; // error messages are formatted here + sf_count_t rslt; // frame count returned from sf_seek + + if (format == SND_HEAD_RAW) { + sf_info->channels = channels; + sf_info->samplerate = srate; + } else { + sf_info->format = 0; + } + sndfile = sf_open((const char *) filename, direction, sf_info); + + if (!sndfile) { + sprintf(error, "snd_overwrite: cannot open file %s", filename); + xlabort(error); + } + /* use proper scale factor: 8000 vs 7FFF */ + sf_command(sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE); + + frames = round(offset * sf_info->samplerate); + rslt = sf_seek(sndfile, frames, SEEK_SET); + if (rslt < 0) { + sprintf(error, "snd_overwrite: cannot seek to frame %lld of %s", + frames, filename); + xlabort(error); + } + if (sf_info->channels != channels) { + sprintf(error, "%s%d%s%d%s", + "snd_overwrite: number of channels in sound (", + channels, + ") does not match\n number of channels in file (", + sf_info->channels, ")"); + sf_close(sndfile); + xlabort(error); + } + + if (sf_info->samplerate != srate) { + sprintf(error, "%s%ld%s%d%s", + "snd_overwrite: sample rate in sound (", + srate, + ") does not match\n sample rate in file (", + sf_info->samplerate, + ")"); + sf_close(sndfile); + xlabort(error); + } + + if ((*buf = (float *) malloc(max_sample_block_len * channels * + sizeof(float))) == NULL) { + xlabort("snd_overwrite: couldn't allocate memory"); + } + return sndfile; +} + + +double sound_overwrite( + LVAL snd_expr, + long n, + unsigned char *filename, + double offset_secs, + long format, + long mode, + long bits, + long swap, + double *duration) +{ + LVAL result; // the SOUND to be evaluated + SF_INFO sf_info; // info about the sound file + double max_sample; // return value + long ntotal; // how many samples were overwritten + /* + long flags; + */ + // first check if sound file exists, do not create new file + FILE *file = fopen((char *) filename, "rb"); + // if not then fail + if (!file) { + *duration = 0; + return 0.0; + } else { + fclose(file); + } + memset(&sf_info, 0, sizeof(sf_info)); + sf_info.format = lookup_format(format, mode, bits, swap); + result = xleval(snd_expr); + /* BE CAREFUL - DO NOT ALLOW GC TO RUN WHILE RESULT IS UNPROTECTED */ + if (vectorp(result)) { + SNDFILE *sndfile; // opened sound file + float *buf; // buffer for samples read in from sound file + /* make sure all elements are of type a_sound */ + long i = getsize(result); + long channels = i; + while (i > 0) { + i--; + if (!exttypep(getelement(result, i), a_sound)) { + xlerror("sound_save: array has non-sound element", + result); + } + } + sndfile = open_for_write(filename, SFM_RDWR, format, &sf_info, channels, + ROUND(getsound(getelement(result, 0))->sr), + offset_secs, &buf); + + max_sample = sound_save_array(result, n, &sf_info, sndfile, + buf, &ntotal, NULL); + *duration = ntotal / (double) sf_info.samplerate; + free(buf); + sf_close(sndfile); + } else if (exttypep(result, a_sound)) { + SNDFILE *sndfile; // opened sound file + float *buf; // buffer for samples read in from sound file + sndfile = open_for_write(filename, SFM_RDWR, format, &sf_info, 1, + ROUND(getsound(result)->sr), + offset_secs, &buf); + max_sample = sound_save_sound(result, n, &sf_info, sndfile, buf, + &ntotal, NULL); + *duration = ntotal / (double) sf_info.samplerate; + free(buf); + sf_close(sndfile); + } else { + xlerror("sound_save: expression did not return a sound", + result); + max_sample = 0.0; + } + return max_sample; +} + +int is_pcm(SF_INFO *sf_info) +{ + long subtype = sf_info->format & SF_FORMAT_SUBMASK; + return (subtype == SF_FORMAT_PCM_S8 || subtype == SF_FORMAT_PCM_16 || + subtype == SF_FORMAT_PCM_24 || subtype == SF_FORMAT_PCM_32); +} + + +sample_type sound_save_sound(LVAL s_as_lval, long n, SF_INFO *sf_info, + SNDFILE *sndfile, float *buf, long *ntotal, PaStream *audio_stream) +{ + long blocklen; + sound_type s; + int i; + sample_type *samps; + long debug_unit; /* print messages at intervals of this many samples */ + long debug_count; /* next point at which to print a message */ + sample_type max_sample = 0.0F; + sample_type threshold = 0.0F; + /* jlh cvtfn_type cvtfn; */ + *ntotal = 0; + + /* if snd_expr was simply a symbol, then s now points to + a shared sound_node. If we read samples from it, then + the sound bound to the symbol will be destroyed, so + copy it first. If snd_expr was a real expression that + computed a new value, then the next garbage collection + will reclaim the sound_node. We need to make the new + sound reachable by the garbage collector to that any + lisp data reachable from the sound do not get collected. + To make the sound reachable, we need to allocate a node, + and the GC might run, so we need to protect the OLD s + but then make it unreachable. + We will let the GC collect the sound in the end. + */ + xlprot1(s_as_lval); + s = sound_copy(getsound(s_as_lval)); + s_as_lval = cvsound(s); /* destroys only ref. to original */ + + /* for debugging */ +/* printing_this_sound = s;*/ + + + debug_unit = debug_count = (long) max(sf_info->samplerate, 10000.0); + + sound_frames = 0; + sound_srate = sf_info->samplerate; + + while (n > 0) { + long togo; + sample_block_type sampblock = sound_get_next(s, &blocklen); + oscheck(); +#ifdef SNAPSHOTS + stdputstr("."); + if (sound_created_flag) { + stdputstr("SNAPSHOT: "); + sound_print_tree(printing_this_sound); + sound_created_flag = false; + } + fflush(stdout); +#endif + if (sampblock == zero_block || blocklen == 0) { + break; + } + togo = min(blocklen, n); + if (s->scale != 1) { /* copy/scale samples into buf */ + for (i = 0; i < togo; i++) { + buf[i] = s->scale * sampblock->samples[i]; + } + samps = buf; + } else { + samps = sampblock->samples; + } + if (is_pcm(sf_info)) { + for (i = 0; i < togo; i++) { + sample_type s = samps[i]; + COMPUTE_MAXIMUM_AND_WRAP(samps[i]); + } + } else { + for (i = 0; i < togo; i++) { + sample_type s = samps[i]; + COMPUTE_MAXIMUM(); + } + } + if (sndfile) { + sf_writef_float(sndfile, samps, togo); + } + if (audio_stream) { + Pa_WriteStream(audio_stream, samps, togo); + sound_frames += togo; + } + + n -= togo; + *ntotal += togo; + if (*ntotal > debug_count) { + gprintf(TRANS, " %ld ", *ntotal); + fflush(stdout); + debug_count += debug_unit; + } + } + gprintf(TRANS, "\ntotal samples: %ld\n", *ntotal); + xlpop(); + return max_sample; +} + + +sample_type sound_save_array(LVAL sa, long n, SF_INFO *sf_info, + SNDFILE *sndfile, float *buf, long *ntotal, PaStream *audio_stream) +{ + long i, chans; + float *float_bufp; + sound_state_type state; + double start_time = HUGE_VAL; + LVAL sa_copy; + long debug_unit; /* print messages at intervals of this many samples */ + long debug_count; /* next point at which to print a message */ + sample_type max_sample = 0.0F; + sample_type threshold = 0.0F; + /* cvtfn_type cvtfn; jlh */ + + *ntotal = 0; + + /* THE ALGORITHM: first merge floating point samples from N channels + * into consecutive multi-channel frames in buf. Then, treat buf + * as just one channel and use one of the cvt_to_* functions to + * convert the data IN PLACE in the buffer (this is ok because the + * converted data will never take more space than the original 32-bit + * floats, so the converted data will not overwrite any floats before + * the floats are converted + */ + + /* if snd_expr was simply a symbol, then sa now points to + a shared sound_node. If we read samples from it, then + the sounds bound to the symbol will be destroyed, so + copy it first. If snd_expr was a real expression that + computed a new value, then the next garbage collection + will reclaim the sound array. See also sound_save_sound() + */ + + chans = getsize(sa); + if (chans > MAX_SND_CHANNELS) { + xlerror("sound_save: too many channels", sa); + free(buf); + sf_close(sndfile); + } + xlprot1(sa); + sa_copy = newvector(chans); + xlprot1(sa_copy); + + /* Why do we copy the array into an xlisp array instead of just + * the state[i] array? Because some of these sounds may reference + * the lisp heap. We must put the sounds in an xlisp array so that + * the gc will find and mark them. xlprot1(sa_copy) makes the array + * visible to gc. + */ + for (i = 0; i < chans; i++) { + sound_type s = getsound(getelement(sa, i)); + setelement(sa_copy, i, cvsound(sound_copy(s))); + } + sa = sa_copy; /* destroy original reference to allow GC */ + + state = (sound_state_type) malloc(sizeof(sound_state_node) * chans); + for (i = 0; i < chans; i++) { + state[i].sound = getsound(getelement(sa, i)); + state[i].scale = state[i].sound->scale; +D nyquist_printf("save scale factor %ld = %g\n", i, state[i].scale); + state[i].terminated = false; + state[i].cnt = 0; /* force a fetch */ + start_time = min(start_time, state[i].sound->t0); + } + + for (i = 0; i < chans; i++) { + if (state[i].sound->t0 > start_time) + sound_prepend_zeros(state[i].sound, start_time); + } + + debug_unit = debug_count = (long) max(sf_info->samplerate, 10000.0); + + sound_frames = 0; + sound_srate = sf_info->samplerate; + while (n > 0) { + /* keep the following information for each sound: + has it terminated? + pointer to samples + number of samples remaining in block + scan to find the minimum remaining samples and + output that many in an inner loop. Stop outer + loop if all sounds have terminated + */ + int terminated = true; + int togo = n; + int j; + + oscheck(); + + for (i = 0; i < chans; i++) { + if (state[i].cnt == 0) { + if (sndwrite_trace) { + nyquist_printf("CALLING SOUND_GET_NEXT ON CHANNEL %ld (%lx)\n", + i, (unsigned long) state[i].sound); /* jlh 64 bit issue */ + sound_print_tree(state[i].sound); + } + state[i].ptr = sound_get_next(state[i].sound, + &(state[i].cnt))->samples; + if (sndwrite_trace) { + nyquist_printf("RETURNED FROM CALL TO SOUND_GET_NEXT ON CHANNEL %ld\n", i); + } + if (state[i].ptr == zero_block->samples) { + state[i].terminated = true; + } + } + if (!state[i].terminated) terminated = false; + togo = min(togo, state[i].cnt); + } + + if (terminated) break; + + float_bufp = (float *) buf; + if (is_pcm(sf_info)) { + for (j = 0; j < togo; j++) { + for (i = 0; i < chans; i++) { + float s = (float) (*(state[i].ptr++) * (float) state[i].scale); + COMPUTE_MAXIMUM_AND_WRAP(s); + *float_bufp++ = s; + } + } + } else { + for (j = 0; j < togo; j++) { + for (i = 0; i < chans; i++) { + float s = (float) (*(state[i].ptr++) * (float) state[i].scale); + COMPUTE_MAXIMUM(); + *float_bufp++ = s; + } + } + } + /* Here we have interleaved floats. Before converting to the sound + file format, call PortAudio to play them. */ + if (audio_stream) { + PaError err = Pa_WriteStream(audio_stream, buf, togo); + if (err) { + printf("Pa_WriteStream error %d\n", err); + } + sound_frames += togo; + } + if (sndfile) sf_writef_float(sndfile, buf, togo); + + n -= togo; + for (i = 0; i < chans; i++) { + state[i].cnt -= togo; + } + *ntotal += togo; + if (*ntotal > debug_count) { + gprintf(TRANS, " %ld ", *ntotal); + fflush(stdout); + debug_count += debug_unit; + } + } + gprintf(TRANS, "total samples: %ld x %ld channels\n", + *ntotal, chans); + + /* references to sounds are shared by sa_copy and state[]. + * here, we dispose of state[], allowing GC to do the + * sound_unref call that frees the sounds. (Freeing them now + * would be a bug.) + */ + free(state); + xlpop(); + return max_sample; +} + + diff --git a/nyqsrc/sound.c b/nyqsrc/sound.c new file mode 100644 index 0000000..9892d10 --- /dev/null +++ b/nyqsrc/sound.c @@ -0,0 +1,1709 @@ +/* sound.c -- nyquist sound data type */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability and fix compiler warnings + */ + +/* define size_t: */ +#ifdef UNIX +#include "sys/types.h" +#endif +#include +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "samples.h" +#include "extern.h" +#include "debug.h" +#include "assert.h" +#ifdef OSC +#include "nyq-osc-server.h" +#endif +#include "cext.h" +#include "userio.h" + +/* #define GC_DEBUG */ +#ifdef GC_DEBUG +extern sound_type sound_to_watch; +#endif + +snd_list_type list_watch; //DBY + +/* #define SNAPSHOTS */ + +long table_memory; + +sample_block_type zero_block; +sample_block_type internal_zero_block; + +snd_list_type zero_snd_list; + +xtype_desc sound_desc; +LVAL a_sound; +LVAL s_audio_markers; + +static void sound_xlfree(); +static void sound_xlprint(); +static void sound_xlsave(); +static unsigned char *sound_xlrestore(); + +void sound_print_array(LVAL sa, long n); +void sound_print_sound(sound_type s, long n); +void sample_block_unref(sample_block_type sam); + +#ifdef SNAPSHOTS +boolean sound_created_flag = false; +#endif + +#ifdef OSC +int nosc_enabled = false; +#endif + +double sound_latency = 0.3; /* default value */ +/* these are used so get times for *AUDIO-MARKERS* */ +double sound_srate = 44100.0; +long sound_frames = 0; + +double snd_set_latency(double latency) +{ + double r = sound_latency; + sound_latency = latency; + return r; +} + + +/* xlbadsr - report a "bad combination of sample rates" error */ +LVAL snd_badsr(void) +{ + xlfail("bad combination of sample rates"); + return NIL; /* never happens */ +} + + +/* compute-phase - given a phase in radians, a wavetable specified as + * the nominal pitch (in half steps), the table length, and the sample + * rate, compute the sample number corresponding to the phase. This + * routine makes it easy to initialize the table pointer at the beginning + * of various oscillator implementations in Nyquist. Note that the table + * may represent several periods, in which case phase 360 is not the same + * as 0. Also note that the phase increment is also computed and returned + * through incr_ptr. + */ +double compute_phase(phase, key, n, srate, new_srate, freq, incr_ptr) + double phase; /* phase in degrees (depends on ANGLEBASE) */ + double key; /* the semitone number of the table played at srate */ + long n; /* number of samples */ + double srate; /* the sample rate of the table */ + double new_srate; /* sample rate of the result */ + double freq; /* the desired frequency */ + double *incr_ptr; /* the sample increment */ +{ + double period = 1.0 / step_to_hz(key); + + /* convert phase to sample units */ + phase = srate * period * (phase / (double) ANGLEBASE); + /* phase is now in sample units; if phase is less than zero, then increase + it by some number of sLength's to make it positive: + */ + if (phase < 0) + phase += (((int) ((-phase) / n)) + 1) * n; + + /* if phase is longer than the sample length, wrap it by subtracting the + integer part of the division by sLength: + */ + if (phase > n) + phase -= ((int) (phase / n)) * n; + + /* Now figure the phase increment: to reproduce original pitch + required incr = srate / new_srate. To get the new frequency, + scale by freq / nominal_freq = freq * period: + */ + *incr_ptr = (srate / new_srate) * freq * period; + return phase; +} +#ifndef GCBUG +snd_list_type gcbug_snd_list = 0; +long blocks_to_watch_len = 0; +sample_block_type blocks_to_watch[blocks_to_watch_max]; + +void block_watch(long sample_block) +{ + if (blocks_to_watch_len >= blocks_to_watch_max) { + stdputstr("block_watch - no more space to save pointers\n"); + return; + } + blocks_to_watch[blocks_to_watch_len++] = (sample_block_type) sample_block; + nyquist_printf("block_watch - added %d = %x\n", + (int)sample_block, (int)sample_block); +} + + +/* fetch_zeros -- the fetch function for appended zeros */ +/* + * zeros are appended when the logical stop time exceeds the + * (physical) terminate time. This fetch function is installed + * by snd_list_terminate(). When appending zeros, we just return + * a pointer to the internal_zero_block and increment current until + * it reaches log_stop_cnt. Then we call snd_list_terminate() to + * finish off the sound list. + */ + +void fetch_zeros(snd_susp_type susp, snd_list_type snd_list) +{ + int len = MIN(susp->log_stop_cnt - susp->current, + max_sample_block_len); +/* nyquist_printf("fetch_zeros, lsc %d current %d len %d\n", + susp->log_stop_cnt, susp->current, len); */ + if (len < 0) { + char error[80]; + sprintf(error, "fetch_zeros susp %p (%s) len %d", susp, susp->name, len); + xlabort(error); + } + if (len == 0) { /* we've reached the logical stop time */ + /* nyquist_printf("fetch_zeros: reached the logical stop in %s cnt %d\n", + susp->name, susp->log_stop_cnt); */ + snd_list_terminate(snd_list); + } else { + snd_list->block_len = len; + susp->current += len; + } +} + + +/* sound_nth_block - fetch the address of the nth sample block of a sound */ +/* + * NOTE: intended to be called from lisp. Lisp can then call block_watch + * to keep an eye on the block. + */ +long sound_nth_block(sound_type snd, long n) +{ + long i; + snd_list_type snd_list = snd->list; + for (i = 0; i < n; i++) { + if (i == 1) { + gcbug_snd_list = snd_list; + nyquist_printf("gcbug_snd_list = 0x%p\n", gcbug_snd_list); + } + if (!snd_list->block) return 0; + snd_list = snd_list->u.next; + } + if (snd_list->block) return (long) snd_list->block; + else return 0; +} + +#endif + + +/**************************************************************************** +* snd_list_create +* Inputs: +* snd_susp_type susp: A reference to the suspension +* Result: snd_list_type +* A newly-created sound list type +* Effect: +* Allocates and initializes a snd_list node: +* block refcnt block_len susp logically_stopped +* +--------+--------+-------+-------+---+ +* |////////| 1 | 0 | susp | F | +* +--------+--------+-------+-------+---+ +****************************************************************************/ + +/* snd_list_create -- alloc and initialize a snd_list node */ +/**/ +snd_list_type snd_list_create(snd_susp_type susp) +{ + snd_list_type snd_list; + + falloc_snd_list(snd_list, "snd_list_create"); + + snd_list->block = NULL; /* no block of samples */ + snd_list->u.susp = susp; /* point to suspension */ + snd_list->refcnt = 1; /* one ref */ + snd_list->block_len = 0; /* no samples */ + snd_list->logically_stopped = false;/* not stopped */ +/* nyquist_printf("snd_list_create => %p\n", snd_list);*/ + return snd_list; +} + + +/**************************************************************************** +* sound_create +* Inputs: +* snd_susp_type susp: The suspension block to be used for this sound +* time_type t0: The initial time for this sound +* rate_type sr: The sampling rate for this sound +* sample_type scale: The scaling factor for this sound +* sample_block_type (*proc)(...): The get_next_sound method +* Result: sound_type +* +* Effect: +* Creates and initializes a sound type +* Notes: +* The MSDOS conditional is actually a test for ANSI headers; the +* presence of float parameters means that an ANSI prototype and +* a non-ANSI header are incompatible. Better solution would be +* to ANSIfy source. +****************************************************************************/ + +sound_type last_sound = NULL; + +sound_type sound_create( + snd_susp_type susp, + time_type t0, + rate_type sr, + promoted_sample_type scale) +{ + sound_type sound; + falloc_sound(sound, "sound_create"); + if (((long) sound) & 3) errputstr("sound not word aligned\n"); + last_sound = sound; /* debug */ + if (t0 < 0) xlerror("attempt to create a sound with negative starting time", s_unbound); + /* nyquist_printf("sound_create %p gets %g\n", sound, t0); */ + sound->t0 = sound->true_t0 = sound->time = t0; + sound->stop = MAX_STOP; + sound->sr = sr; + sound->current = 0; + sound->scale = (float) scale; + sound->list = snd_list_create(susp); + sound->get_next = SND_get_first; + sound->logical_stop_cnt = UNKNOWN; + sound->table = NULL; + sound->extra = NULL; + /* nyquist_printf("sound_create susp %p snd_list %p\n", susp, sound->list); + nyquist_printf("sound_create'd %p\n", sound); */ +#ifdef SNAPSHOTS + sound_created_flag = true; +#endif +#ifdef GC_DEBUG + if (sound == sound_to_watch) { + nyquist_printf("Created watched sound\n"); + watch_snd_list(sound->list); + } +#endif + return sound; +} + + +/* sound_prepend_zeros -- modify sound_type so that it starts at t0 */ +/* + * assumes t0 is earlier than snd->t0, so the sound should return zeros + * until snd->t0 is reached, after which we revert to normal computation. + * When we return, the new snd->t0 will be t0, meaning that the first + * sample returned will be at time t0. + * NOTE: t0 may not be an exact multiple of samples earlier than snd->t0, + * but Nyquist allows any sound to be shifted by +/- 0.5 samples in + * order to achieve alignment. Since sound_prepend_zeros can be called + * many times on the same sound_type, there is a chance that rounding + * errors could accumulate. My first solution was to return with + * snd->t0 computed exactly and not reflecting any fractional sample + * shift of the signal, but this caused problems for the caller: a + * fractional sample shift at a low sample rate could correspond to + * many client samples,fooling the client into thinking that some + * initial samples should be discarded (or else requiring the client + * to be pretty smart). The solution used here is to return to the + * client with snd->t0 exactly equal to t0, but to save snd->true_t0 + * equal to the time of the first sample with no sound shifting. This + * time is used for any future sound_prepend_zeros operations so that + * any accumulated rounding errors are due only to floating point + * precision and not to accumulated fractional sample shifts of snd. + */ +void sound_prepend_zeros(sound_type snd, time_type t0) +{ + long n; + + /* first, see if we're already prepending some zeros */ + if (snd->get_next != SND_get_zeros) { +/* nyquist_printf("sound_prepend_zeros 1: snd->t0 %g t0 %g\n", snd->t0, t0); */ + + /* if not, then initialize some fields that support prepending */ + snd->prepend_cnt = 0; + snd->true_t0 = snd->t0; + + /* save old get_next and plug in special get_next function */ + snd->after_prepend = snd->get_next; + snd->get_next = SND_get_zeros; + } + + n = (long) (((snd->true_t0 - t0) * snd->sr) + 0.5); /* how many samples to prepend */ + + /* add to prepend_cnt so first sample will correspond to new t0 */ + snd->prepend_cnt += n; + /* compute the true t0 which corresponds to the time of first sample */ + snd->true_t0 -= (n / snd->sr); + /* make caller happy by claiming the sound now starts at exactly t0; + * this is always true within 0.5 samples as allowed by Nyquist. */ + snd->t0 = t0; +/* nyquist_printf("sound_prepend_zeros: snd %p true_t0 %g sr %g n %d\n", + snd, snd->true_t0, snd->sr, n);*/ +} + + +/* sound_array_copy -- copy an array of sounds */ +/* + * NOTE: be sure to protect the result from gc! + */ +LVAL sound_array_copy(LVAL sa) +{ + long i = getsize(sa); + LVAL new_sa = newvector(i); + xlprot1(new_sa); + + while (i > 0) { + i--; + setelement(new_sa, i, + cvsound(sound_copy(getsound(getelement(sa, i))))); + } + + xlpop(); + return new_sa; +} + + +/* sound_copy - copy a sound structure, do reference counts */ +/**/ +sound_type sound_copy(sound_type snd) +{ + sound_type sndcopy; + falloc_sound(sndcopy, "sound_copy"); + *sndcopy = *snd; /* copy the whole structure */ + sndcopy->extra = NULL; /* except for the (private) extra data */ + snd_list_ref(snd->list); /* copied a reference so fix the count */ +/* nyquist_printf("sound_copy'd %p to %p\n", snd, sndcopy); */ + if (snd->table) snd->table->refcount++; +#ifdef GC_DEBUG + if (sndcopy == sound_to_watch) + printf("sndcopy->table %x\n", sndcopy->table); +#endif + return sndcopy; +} + + +/* convert a sound to a wavetable, set length */ +/**/ +table_type sound_to_table(sound_type s) +{ + long len = snd_length(s, max_table_len); + long tx = 0; /* table index */ + long blocklen; + register double scale_factor = s->scale; + sound_type original_s = s; + table_type table; /* the new table */ + long table_bytes; /* how big is the table */ + + if (s->table) { + s->table->refcount++; + return s->table; + } + + if (len >= max_table_len) { + char emsg[100]; + sprintf(emsg, "maximum table size (%d) exceeded", max_table_len); + xlcerror("use truncated sound for table", emsg, NIL); + } else if (len == 0) { + xlabort("table size must be greater than 0"); + } + + + len++; /* allocate extra sample at end of table */ + s = sound_copy(s); + + /* nyquist_printf("sound_to_table: allocating table of size %d\n", len); */ + table_bytes = table_size_in_bytes(len); + table = (table_type) malloc(table_bytes); + if (!table) xlfail("osc_init couldn't allocate memory for table"); + table_memory += table_bytes; + + table->length = (double) (len - 1); + + while (len > 1) { + sample_block_type sampblock = sound_get_next(s, &blocklen); + long togo = MIN(blocklen, len); + long i; + sample_block_values_type sbufp = sampblock->samples; +/* nyquist_printf("in sound_to_table, sampblock = %d\n", sampblock);*/ + for (i = 0; i < togo; i++) { + table->samples[tx++] = (float) (*sbufp++ * scale_factor); + } + len -= togo; + } + /* for interpolation, duplicate first sample at end of table */ + table->samples[tx] = table->samples[0]; + table->refcount = 2; /* one for the user, one from original_s */ + + sound_unref(s); + s = NULL; + original_s->table = table; + return table; +} + + +void table_free(table_type table) +{ + long len = (long) (table->length) + 1; + long bytes = table_size_in_bytes(len); + free(table); + table_memory -= bytes; +} + + +void table_unref(table_type table) +{ + if (!table) return; + table->refcount--; + if (table->refcount <= 0) { + /* nyquist_printf("table refcount went to zero\n"); */ + table_free(table); + } +} + + +void sound_unref(sound_type snd) +/* note that sounds do not have ref counts, so sound_unref + * always frees the sound object + */ +{ + if (!snd) return; + snd_list_unref(snd->list); + table_unref(snd->table); +/* nyquist_printf("\t\t\t\t\tfreeing sound@%p\n", snd);*/ + if (snd->extra) free(snd->extra); + ffree_sound(snd, "sound_unref"); +} + + +void snd_list_ref(snd_list_type list) +{ + list->refcnt++; +} + + +void snd_list_terminate(snd_list) + snd_list_type snd_list; +{ + snd_susp_type susp = snd_list->u.next->u.susp; + long lsc = susp->log_stop_cnt; + long current = susp->current; + /* unreference the empty sample block that was allocated: */ + sample_block_unref(snd_list->block); + /* use zero_block instead */ + snd_list->block = zero_block; + /* either fetch more zeros or terminate now */ + if (lsc != UNKNOWN && lsc > current) { + /* nyquist_printf("snd_list_terminate: lsc %d current %d\n", + lsc, current); */ + susp->fetch = fetch_zeros; + fetch_zeros(susp, snd_list); + } else { + snd_list->block_len = max_sample_block_len; + snd_list->logically_stopped = true; + snd_list_unref(snd_list->u.next); + snd_list->u.next = zero_snd_list; /* be zero forever */ + } +} + + +void snd_list_unref(snd_list_type list) +{ + void (*freefunc)(); + + if (list == NULL || list == zero_snd_list) { + if (list == NULL) + nyquist_printf("why did snd_list_unref get %p?\n", list); + return; + } + list->refcnt--; +/* nyquist_printf("snd_list_unref "); print_snd_list_type(list); stdputstr("\n"); */ + if (list->refcnt == 0) { + if (list->block && list->block != zero_block) { + /* there is a next snd_list */ +/* stdputstr("["); */ + sample_block_unref(list->block); +/* stdputstr("]"); */ + snd_list_unref(list->u.next); + } + else if (list->block == NULL) { /* the next thing is the susp */ + /* free suspension structure */ + /* nyquist_printf("freeing susp@%p\n", list->u.susp); */ + freefunc = list->u.susp->free; + (*freefunc)(list->u.susp); + } + /* nyquist_printf("freeing snd_list@%p\n", list); */ + //DBY + if (list == list_watch) printf("freeing watched snd_list %p\n", list); + //DBY + ffree_snd_list(list, "snd_list_unref"); + } +} + + +void sample_block_ref(sample_block_type sam) +{ + sam->refcnt++; +} + + +void sample_block_test(sample_block_type sam, char *s) +{ + /* see if this block is being watched */ + int i; + for (i = 0; i < blocks_to_watch_len; i++) { + if ((sam > (blocks_to_watch[i] - 1)) && + (sam < (blocks_to_watch[i] + 1))) { + nyquist_printf( + "WOOPS! %s(0x%p) refers to a block 0x%p on the watch list!\n", + s, sam, blocks_to_watch[i]); + } + } +} + + +void sample_block_unref(sample_block_type sam) +{ + sam->refcnt--; + if (sam->refcnt == 0) { +#ifndef GCBUG + sample_block_test(sam, "sample_block_unref"); +#endif +/* nyquist_printf("freeing sample block %p\n", sam); */ + ffree_sample_block(sam, "sample_block_unref"); + } +} + + + +/**************************************************************************** +* interp_style +* Inputs: +* sound_type s: The sound we are using +* rate_type sr: The sampling rate +* Result: int +* A small integer which is one of the symbolic values: +* The values are ordered, smallest to largest, as +* INTERP_n - none +* INTERP_s - scale +* INTERP_i - interpolated +* INTERP_r - ramp +* +* Notes: +* The sampling rate s->sr and scale factor s->scale are compared +* with other values exactly (no fuzz). +****************************************************************************/ + +int interp_style(sound_type s, rate_type sr) +{ + if (s->sr == sr) + { /* same sample rate */ + return ((s->scale == 1.0) ? INTERP_n : INTERP_s); + } /* same sample rate */ + else + if (s->sr * 10.0 > sr) + { /* 10x sample rate */ + return INTERP_i; + } /* 10x sample rate */ + else + return INTERP_r; +} + + +/**************************************************************************** +* snd_sort_2 +* Inputs: +* sound_type * s1_ptr: +* sound_type * s2_ptr: +* rate_type sr: +* Result: void +* +* Effect: +* If the interp_style of s1 dominates the interp_style of s2, +* the sound_types input are interchanged. +****************************************************************************/ + +/* snd_sort_2 -- sort 2 arguments by interpolation method */ +void snd_sort_2(sound_type *s1_ptr, sound_type *s2_ptr, rate_type sr) +{ + if (interp_style(*s1_ptr, sr) > interp_style(*s2_ptr, sr)) { + sound_type s = *s1_ptr; + *s1_ptr = *s2_ptr; + *s2_ptr = s; + } +} + + +/* snd_sref -- access a sound at a given time point */ +/**/ +double snd_sref(sound_type s, time_type t) +{ + double exact_cnt; /* how many fractional samples to scan */ + int cnt; /* how many samples to flush */ + sample_block_type sampblock = NULL; + long blocklen; + sample_type x1, x2; /* interpolate between these samples */ + + /* changed true_t0 to just t0 based on comment that true_t0 is only + * for use by snd_prepend_zeros -RBD + */ + exact_cnt = (t - s->t0) * s->sr; + if (exact_cnt < 0.0) return 0.0; + + s = sound_copy(s); /* don't modify s, create new reader */ + cnt = (long) exact_cnt; /* rounds down */ + exact_cnt -= cnt; /* remember fractional remainder */ + + /* now flush cnt samples */ + while (cnt >= 0) { + sampblock = sound_get_next(s, &blocklen); + cnt -= blocklen; + if (sampblock == zero_block) { + sound_unref(s); + return 0.0; + } + } + /* -blocklen <= cnt <= -1 */ + + /* get next 2 samples and interpolate */ + x1 = sampblock->samples[blocklen + cnt]; + if (cnt == -1) { + sampblock = sound_get_next(s, &blocklen); + cnt -= blocklen; + } + x2 = sampblock->samples[blocklen + cnt + 1]; + sound_unref(s); /* free the reader */ + + return (x1 + exact_cnt * (x2 - x1)) * s->scale; +} + + +/* snd_sref_inverse -- find time point corresponding to some value */ +/**/ +double snd_sref_inverse(sound_type s, double val) +{ + double exact_cnt; /* how many fractional samples to scan */ + int i; + sample_block_type sampblock; + long blocklen; + sample_type x1, x2; /* interpolate between these samples */ + + if (val < 0) { + xlcerror("return 0", "negative value", cvflonum(val)); + return 0.0; + } + s = sound_copy(s); /* don't modify s, create new reader */ + + x1 = 0.0F; + /* now flush cnt samples */ + while (true) { + sampblock = sound_get_next(s, &blocklen); + x2 = sampblock->samples[blocklen - 1]; + if (x2 >= val) break; + x1 = x2; + if (sampblock == zero_block) { + xlcerror("return 0", "too large, no inverse", cvflonum(val)); + sound_unref(s); + return 0.0; + } + } + /* x1 = last sample of previous block, + sampblock contains a value larger than val + blocklen is the length of sampblock */ + + /* search for first element exceeding val - could + * use binary search, but maximum block size places + * an upper bound on how bad this can get and we + * search for the right block linearly anyway. + */ + for (i = 0; i < blocklen && sampblock->samples[i] <= val; i++) ; + + /* now i is index of element exceeding val */ + if (i > 1) x1 = sampblock->samples[i - 1]; + x2 = sampblock->samples[i]; + + /* now interpolate to get fractional part */ + if (x2 == x1) exact_cnt = 0; + else exact_cnt = (val - x1) / (x2 - x1); + + /* and add the sample count of x1 */ + exact_cnt += (s->current - blocklen) + (i - 1); + + /* negative counts are possible because the first x1 is at + * sample -1, so force the location to be at least 0 + */ + if (exact_cnt < 0) exact_cnt = 0; + + /* compute time = t0 + count / samplerate; */ + exact_cnt = s->t0 + exact_cnt / s->sr; + + sound_unref(s); /* free the reader */ + return exact_cnt; +} + + +time_type snd_stop_time(sound_type s) +{ + if (s->stop == MAX_STOP) return MAX_STOP_TIME; + else return s->t0 + (s->stop + 0.5) / s->sr; +} + + +/* snd_xform -- return a sound with transformations applied */ +/* + * The "logical" sound starts at snd->time and runs until some + * as yet unknown termination time. (There is also a possibly + * as yet unknown logical stop time that is irrelevant here.) + * The sound is clipped (zero) until snd->t0 and after snd->stop, + * the latter being a sample count, not a time_type. + * So, the "physical" sound starts at snd->t0 and runs for up to + * snd->stop samples (or less if the sound terminates beforehand). + * + * The snd_xform procedure operates at the "logical" level, shifting + * the sound from its snd->time to time. The sound is stretched as + * a result of setting the sample rate to sr. It is then (further) + * clipped between start_time and stop_time. If initial samples + * are clipped, the sound is shifted again so that it still starts + * at time. The sound is then scaled by scale. + * + * To support clipping of initial samples, the "physical" start time + * t0 is set to when the first unclipped sample will be returned, but + * the number of samples to clip is saved as a negative count. The + * fetch routine SND_flush is installed to flush the clipped samples + * at the time of the first fetch. SND_get_first is then installed + * for future fetches. + * + * An empty (zero) sound will be returned if all samples are clipped. + * + */ +sound_type snd_xform(sound_type snd, + rate_type sr, + time_type time, + time_type start_time, + time_type stop_time, + promoted_sample_type scale) +{ + long start_cnt, stop_cnt; /* clipping samples (sample 0 at new t0) */ + + /* start_cnt should reflect max of where the sound starts (t0) + * and the new start_time. + */ + if (start_time == MIN_START_TIME) { + start_cnt = 0; + } else { + double new_start_cnt = ((start_time - time) * sr) + 0.5; + start_cnt = ((new_start_cnt > 0) ? (long) new_start_cnt : 0); + } + /* if (start_cnt < -(snd->current)) start_cnt = -(snd->current); */ + + /* stop_cnt should reflect min of the new stop_time and the previous + * snd->stop. + */ + if (stop_time == MAX_STOP_TIME) { + stop_cnt = MAX_STOP; + } else { + double new_stop_cnt = ((stop_time - time) * sr) + 0.5; + if (new_stop_cnt < MAX_STOP) { + stop_cnt = (long) new_stop_cnt; + } else { + errputstr("Warning: stop count overflow in snd_xform\n"); + stop_cnt = MAX_STOP; + } + } + + if (stop_cnt > snd->stop) { + stop_cnt = snd->stop; + } + + if (stop_cnt < 0 || start_cnt >= stop_cnt) { + snd = sound_create(NULL, time, sr, 1.0); + /* sound_create goes ahead and allocates a snd_list node, so + * we need to free it. + * Calling snd_list_unref here seems like the right thing, but + * it assumes too much structure is in place. ffree_snd_list + * is simpler and more direct: + */ + ffree_snd_list(snd->list, "snd_xform"); + snd->list = zero_snd_list; + nyquist_printf("snd_xform: (stop_time < t0 or start >= stop) " + "-> zero sound = %p\n", snd); + + } else { + snd = sound_copy(snd); + snd->t0 = time; + if (start_cnt) { + snd->current -= start_cnt; /* indicate flush with negative num. */ + /* the following code assumes that SND_get_first is the + routine to be called to get the first samples from this + sound. We're going to replace it with SND_flush. First, + make sure that the assumption is correct: + */ + if ((snd->get_next != SND_get_first) && + (snd->get_next != SND_flush)) { + errputstr("snd_xform: SND_get_first expected\n"); + EXIT(1); + } + /* this will flush -current samples and revert to SND_get_first */ + snd->get_next = SND_flush; + stop_cnt -= start_cnt; + } + snd->stop = stop_cnt; + snd->sr = sr; + snd->scale *= (float) scale; + } + return snd; +} + + +/* SND_flush -- the get_next function for flushing clipped samples */ +/* + * this only gets called once: it flushes -current samples (a + * non-real-time operation) and installs SND_get_next to return + * blocks normally from then on. + */ +sample_block_type SND_flush(sound_type snd, long * cnt) +{ + long mycnt; + sample_block_type block = SND_get_first(snd, &mycnt); + /* changed from < to <= because we want to read at least the first sample */ + while (snd->current <= 0) { + block = SND_get_next(snd, &mycnt); + } + /* at this point, we've read to and including the block with + * the first samples we want to return. If the block boundary + * is in the right place, we can do a minimal fixup and return: + */ + if (snd->current == snd->list->block_len) { + *cnt = snd->current; /* == snd->list->block_len */ + /* snd->get_next = SND_get_next; -- done by SND_get_first */ + return block; + } else /* snd->current < snd->list->block_len */ { + long i; + sample_block_values_type from_ptr; + /* we have to return a partial block */ + /* NOTE: if we had been smart, we would have had SND_get_next + * return a pointer to samples rather than a pointer to the + * block, which has a reference count. Since the caller + * expects a pointer to a reference count, we have to copy + * snd->current samples to a new block + */ + snd_list_type snd_list = snd_list_create((snd_susp_type) snd->list->u.next); + snd_list->u.next->refcnt++; + falloc_sample_block(snd_list->block, "SND_flush"); + /* now copy samples */ + from_ptr = block->samples + snd->list->block_len - snd->current; + for (i = 0; i < snd->current; i++) { + snd_list->block->samples[i] = from_ptr[i]; + } + snd_list_unref(snd->list); + snd->list = snd_list; + *cnt = snd->current; + return snd_list->block; + } +} + + +/* SND_get_zeros -- the get_next function for prepended zeros */ +/* + * when prepending zeros, we just return a pointer to the internal_zero_block + * and decrement the prepend_cnt until it goes to zero. Then we revert to + * the normal (original) get_next function. + * + */ +sample_block_type SND_get_zeros(sound_type snd, long * cnt) +{ + int len = MIN(snd->prepend_cnt, max_sample_block_len); + /* stdputstr("SND_get_zeros: "); */ + if (len < 0) { + char error[80]; + sprintf(error, "SND_get_zeros snd %p len %d", snd, len); + xlabort(error); + } + if (len == 0) { /* we've finished prepending zeros */ + snd->get_next = snd->after_prepend; + /* stdputstr("done, calling sound_get_next\n"); fflush(stdout); */ + return sound_get_next(snd, cnt); + } else { + *cnt = len; + snd->current += len; + snd->prepend_cnt -= len; +/* nyquist_printf("returning internal_zero_block@%p\n", internal_zero_block); + fflush(stdout); */ + return internal_zero_block; + } +} + + +/**************************************************************************** +* SND_get_next +* Inputs: +* sound_type snd: The iterator whose next block is to be computed +* int * cnt: Place to put count of samples returned +* Result: snd_list_type +* Pointer to the sample block computed ---------------------------+ +* Effect: | +* force suspension to compute next block of samples | +* | +* Here's the protocol for using this and related functions: | +* Every client (sample reader) has a private sound_type (an iterator), | +* and the sound_type's 'list' field points to a header (of type | +* snd_list_type). The header in turn points to a block of samples. | +* | +* +---------------------------------------+ +* | +* | +* | sample_block_type +* (snd) V +---+--+--+--+--+--+--+-...-+--+ +* sound_type: snd_list_type +-->|ref| | | | |//|//| |//| +* +---------+ +----------+ | +---+--+--+--+--+--+--+-...-+--+ +* | list +------->| block +--+ ^ +* +---------+ +----------+ : +* | t0 | | block_len|....................: +* +---------+ +----------+ +* | sr | | refcnt | +* +---------+ +-+--------+ +* | current | | next +---->... Note: the union u +* +---------+ |u|........| snd_list_type points to only one +* | rate | | | susp +---->... of the indicated +* +---------+ +-+--------+ susp_type types +* | scalse | |log_stop | +* +---------+ +----------+ +* | lsc | +* +---------+ +* |get_next +-----> SND_get_next() +* +---------+ +* +* The sound_type keeps track of where the next sample block will +* come from. The field 'current' is the number of the first sample of +* the next block to be returned, where sample numbers start +* at zero. The normal fetch procedure is this one, although special +* cases may generate special block generators, e.g., CONST does not need +* to allocate and refill a block and can reuse the same block over and +* over again, so it may have its own fetch procedure. This is the +* general fetch procedure, which assumes that the generator function +* actually produces a slightly different value for each sample. +* +* The distinguishing characteristic of whether the 'u' field is to be +* interpreted as 'next', a link to the next list element, or 'susp', a +* reference to the suspension for generating a new sample block, is +* whether the 'block' parameter is NULL or not. If it is NULL, then +* u.susp tells how to generate the block; if it is not NULL, u.next is +* a pointer to the next sound block in the list. +* +* When the 'block' pointer is NULL, we create a block of samples, and +* create a new sound list element which follows it which has a NULL +* 'block' pointer; the 'u' field of the current list element is now +* interpreted as 'u.next'. +* +* The client calls SND_get_next to get a pointer to a block of samples. +* The count of samples generated is returned via a ref parameter, and +* SND_get_next will not be called again until this set is exhausted. +* +* The next time SND_get_next is called, it knows that the sample block +* has been exhausted. It releases its reference to the block (and if +* that was the last reference, frees the block to the block allocation +* pool), allocates a new block from the block pool, and proceeds to +* fill it with samples. +* +* Note that as an optimization, if the refcnt field goes to 0 it +* could immediately re-use the block without freeing back to the block +* pool and reallocating it. +* +* Because of the way we handle sound sample blocks, the sound sample blocks +* themselves are ref-counted, so freeing the snd_list_type may not free +* the sample block it references. At the level of this procedure, that +* is transparently handled by the snd_list_unref function. +* +* Logical stop: +* +* Logical stop is handled by several mechanisms. The /intrinsic/ logical +* stop is an immutable property of the signal, and is determined by the +* specification in the algorithm description file. When it is encountered, +* the 'logically_stopped' flag of the snd_list_node is set. +* The generators guarantee that the first time this is encountered, it +* will always be constructed so that the first sample of the block it +* references is the logical stop time. +* +* In addition, the client may have set the /explicit logical stop time/ of +* the iterator (e.g., in nyquist, the (set-logical-stop sound time) call copies +* the sound, altering its logical stop). The logical stop time, when set +* in this way, causes the logical_stop_cnt ('lsc' in the above diagram) +* to be set to the count of the last sample to be generated before the +* list; + /* + * If there is not a block of samples, we need to generate one. + */ + if (snd_list->block == NULL) { + /* + * Call the 'fetch' method for this sound_type to generate + * a new block of samples. + */ + snd_susp_type susp = snd_list->u.susp; + + snd_list->u.next = snd_list_create(susp); + snd_list->block = internal_zero_block; + /* nyquist_printf("SND_get_first: susp->fetch %p\n", + susp->fetch); */ + assert(susp->log_stop_cnt == UNKNOWN || susp->log_stop_cnt >= 0); + (*(susp->fetch))(susp, snd_list); +#ifdef GC_DEBUG + snd_list_debug(snd_list, "SND_get_first"); +#endif + /* nyquist_printf("SND_get_first: snd_list %p, block %p, length %d\n", + snd_list, snd_list->block, snd_list->block_len); */ + } + if ((snd->logical_stop_cnt == UNKNOWN) && snd_list->logically_stopped) { + /* nyquist_printf("SND_get_first/next: snd %p logically stopped at %d\n", + snd, snd->current); */ + snd->logical_stop_cnt = snd->current; + } + + /* see if clipping needs to be applied */ + if (snd->current + snd_list->block_len > snd->stop) { + /* need to clip: is clip on a block boundary? */ + if (snd->current == snd->stop) { + /* block boundary: replace with zero sound */ + snd->list = zero_snd_list; + snd_list_unref(snd_list); + } else { + /* not a block boundary: build new list */ + snd->list = snd_list_create((snd_susp_type) zero_snd_list); + snd->list->block_len = (short) (snd->stop - snd->current); + snd->list->block = snd_list->block; + snd->list->block->refcnt++; + snd_list_unref(snd_list); + } + snd_list = snd->list; /* used below to return block ptr */ + } + + *cnt = snd_list->block_len; + /* this should never happen */ + if (*cnt == 0) { + stdputstr("SND_get_first returned 0 samples\n"); +#if DEBUG_MEM + dbg_mem_print("snd_list info:", snd_list); + dbg_mem_print("block info:", snd_list->block); +#endif + sound_print_tree(snd); + stdputstr("It is possible that you created a recursive sound\n"); + stdputstr("using something like: (SETF X (SEQ (SOUND X) ...))\n"); + stdputstr("Nyquist aborts from non-recoverable error\n"); + abort(); + } + snd->current += snd_list->block_len; /* count how many we read */ + snd->get_next = SND_get_next; + return snd_list->block; +} + + +sample_block_type SND_get_next(sound_type snd, long * cnt) +{ + register snd_list_type snd_list = snd->list; + /* + * SND_get_next is installed by SND_get_first, so we know + * when we are called that we are done with the current block + * of samples, so free it now. + */ + snd_list_type cur = snd_list; + snd->list = snd_list = cur->u.next; + snd_list_ref(snd_list); + snd_list_unref(cur); /* release the reference to the current block */ + + /* now that we've deallocated, we can use SND_get_first to finish the job */ + return SND_get_first(snd, cnt); +} + + + +/**************************************************************************** +* make_zero_block +* Inputs: +* +* Result: +* +* Effect: +* +****************************************************************************/ + +sample_block_type make_zero_block(void) + { + sample_block_type zb; + int i; + + falloc_sample_block(zb, "make_zero_block"); + /* leave room for lots more references before overflow, + but set the count high so that even a large number of + dereferences will not lead to a deallocation */ + zb->refcnt = 0x6FFFFFFF; + + for (i = 0; i < max_sample_block_len; i++) + { /* fill with zeros */ + zb->samples[i] = 0.0F; + } /* fill with zeros */ + return zb; + } + + +/* min_cnt -- help compute the logical stop or terminate as minimum */ +/* + * take the sound (which has just logically stopped or terminated at + * current sample) and + * convert the stop sample into the equivalent sample count as produced by + * susp (which may have a different sample rate). If the count is less than + * the current *cnt_ptr, overwrite cnt_ptr with a new minimum. By calling + * this when each of S1, S2, ... Sn reach their logical stop or termiate + * points, *cnt_ptr will end up with the minimum stop count, which is what + * we want. NOTE: the logical stop time and terminate for signal addition + * should be the MAX of logical stop times of arguments, so this routine + * would not be used. + */ +void min_cnt(long *cnt_ptr, sound_type sound, snd_susp_type susp, long cnt) +{ + long c = (long) ((((sound->current - cnt) / sound->sr + sound->t0) - susp->t0) * + susp->sr + 0.5); + /* if *cnt_ptr is uninitialized, just plug in c, otherwise compute min */ + if ((*cnt_ptr == UNKNOWN) || (*cnt_ptr > c)) { +/* nyquist_printf("min_cnt %p: new count is %d\n", susp, c);*/ +/* if (c == 0) sound_print_tree(printing_this_sound);*/ + *cnt_ptr = c; + } +} + + + +/**************************************************************************** +* sound_init +* Result: void +* +* Effect: +* Module initialization +* Allocates the 'zero block', the infinitely linked block of +* 0-valued sounds. This is referenced by a list element which +* refers to itself. +****************************************************************************/ + +void sound_init(void) +{ + zero_block = make_zero_block(); + internal_zero_block = make_zero_block(); + + falloc_snd_list(zero_snd_list, "sound_init"); + + zero_snd_list->block = zero_block; + zero_snd_list->u.next = zero_snd_list; + zero_snd_list->refcnt = 2; + zero_snd_list->block_len = max_sample_block_len; + zero_snd_list->logically_stopped = true; +#ifdef GC_DEBUG + { long s; + stdputstr("sound_to_watch: "); + scanf("%p", &s); + watch_sound((sound_type) s); + } +#endif + sound_desc = create_desc("SOUND", sound_xlfree, sound_xlprint, + sound_xlsave, sound_xlrestore, sound_xlmark); +} + + +/* sound_scale -- copy and change scale factor of a sound */ +/**/ +sound_type sound_scale(double factor, sound_type snd) +{ + sound_type sndcopy = sound_copy(snd); + sndcopy->scale *= (float) factor; + return sndcopy; +} + + + + +/**************************************************************************** +* set_logical_stop_time +* Inputs: +* sound_type sound: The sound for which the logical stop time is +* being set +* time_type when: The logical stop time, expressed as an absolute +* time. +* Result: void +* +* Effect: +* Converts the time 'when' into a count of samples. +****************************************************************************/ + +void set_logical_stop_time(sound_type sound, time_type when) +{ + /* + 'when' is an absolute time. The number of samples to + be generated is the number of samples between 't0' and + 'when'. + + -----------+---+---+---+---+---+---+---+---+---+ + | | + t0 when + */ + long n = (long) ((when - sound->t0) * sound->sr + 0.5); + if (n < 0) { + xlcerror("retain the current logical stop", + "logical stop sample count is negative", NIL); + } else { + sound->logical_stop_cnt = n; + } +} + + + + +/* for debugging */ +sound_type printing_this_sound = NULL; +void ((**watch_me)()) = NULL; + +void set_watch(where) + void ((**where)()); +{ + if (watch_me == NULL) { + watch_me = where; + nyquist_printf("set_watch: watch_me = %p\n", watch_me); + } +} + + +/* + * additional routines + */ +void sound_print(snd_expr, n) + LVAL snd_expr; + long n; +{ + LVAL result; + + xlsave1(result); + result = xleval(snd_expr); + if (vectorp(result)) { + /* make sure all elements are of type a_sound */ + long i = getsize(result); + while (i > 0) { + i--; + if (!exttypep(getelement(result, i), a_sound)) { + xlerror("sound_print: array has non-sound element", + result); + } + } + sound_print_array(result, n); + } else if (exttypep(result, a_sound)) { + sound_print_sound(getsound(result), n); + } else { + xlerror("sound_print: expression did not return a sound", + result); + } + xlpop(); +} + + +void sound_print_sound(sound_type s, long n) +{ + int ntotal = 0; + long blocklen; + sample_block_type sampblock; + + /* for debugging */ + printing_this_sound = s; + + nyquist_printf("sound_print: start at time %g\n", s->t0); + + while (ntotal < n) { + if (s->logical_stop_cnt != UNKNOWN) + nyquist_printf("LST=%d ", (int)s->logical_stop_cnt); + sound_print_tree(s); + sampblock = sound_get_next(s, &blocklen); + if (sampblock == zero_block || blocklen == 0) { + break; + } + print_sample_block_type("sound_print", sampblock, + MIN(blocklen, n - ntotal)); + ntotal += blocklen; + } + nyquist_printf("total samples: %d\n", ntotal); +} + + +void sound_print_array(LVAL sa, long n) +{ + long blocklen; + long i, len; + long upper = 0; + sample_block_type sampblock; + time_type t0, tmax; + + len = getsize(sa); + if (len == 0) { + stdputstr("sound_print: 0 channels!\n"); + return; + } + + /* take care of prepending zeros if necessary */ + t0 = tmax = (getsound(getelement(sa, 0)))->t0; + for (i = 1; i < len; i++) { + sound_type s = getsound(getelement(sa, i)); + t0 = MIN(s->t0, t0); + tmax = MAX(s->t0, tmax); + } + + /* if necessary, prepend zeros */ + if (t0 != tmax) { + stdputstr("prepending zeros to channels: "); + for (i = 0; i < len; i++) { + sound_type s = getsound(getelement(sa, i)); + if (t0 < s->t0) { + nyquist_printf(" %d ", (int)i); + sound_prepend_zeros(s, t0); + } + } + stdputstr("\n"); + } + + nyquist_printf("sound_print: start at time %g\n", t0); + + while (upper < n) { + int i; + boolean done = true; + for (i = 0; i < len; i++) { + sound_type s = getsound(getelement(sa, i)); + long current = -1; /* always get first block */ + while (current < upper) { + sampblock = sound_get_next(s, &blocklen); + if (sampblock != zero_block && blocklen != 0) { + done = false; + } + current = s->current - blocklen; + nyquist_printf("chan %d current %d:\n", i, (int)current); + print_sample_block_type("sound_print", sampblock, + MIN(blocklen, n - current)); + current = s->current; + upper = MAX(upper, current); + } + } + if (done) break; + } + nyquist_printf("total: %d samples x %d channels\n", + (int)upper, (int)len); +} + + +/* sound_play -- compute sound, do not retain samples */ +/* + * NOTE: we want the capability of computing a sound without + * retaining samples. This requires that no references to + * the sound exist, but if the sound is passed as an argument, + * the argument stack will have a reference. So, we pass in + * an expression that evaluates to the sound we want. The + * expression is eval'd, the result copied (in case the + * expression was a sound or a global variable and we really + * want to preserve the sound), and then a GC is run to + * get rid of the original if there really are no other + * references. Finally, the copy is used to play the + * sounds. + */ + +void sound_play(snd_expr) + LVAL snd_expr; +{ + int ntotal; + long blocklen; + sample_block_type sampblock; + LVAL result; + sound_type s; + + xlsave1(result); + result = xleval(snd_expr); + if (!exttypep(result, a_sound)) { + xlerror("sound_play: expression did not return a sound", + result); + } + + ntotal = 0; + s = getsound(result); + /* if snd_expr was simply a symbol, then s now points to + a shared sound_node. If we read samples from it, then + the sound bound to the symbol will be destroyed, so + copy it first. If snd_expr was a real expression that + computed a new value, then the next garbage collection + will reclaim the sound_node. We need to explicitly + free the copy since the garbage collector cannot find + it. + */ + s = sound_copy(s); + while (1) { +#ifdef OSC + if (nosc_enabled) nosc_poll(); +#endif + sampblock = sound_get_next(s, &blocklen); + if (sampblock == zero_block || blocklen == 0) { + break; + } + /* print_sample_block_type("sound_play", sampblock, blocklen); */ + ntotal += blocklen; + } + nyquist_printf("total samples: %d\n", ntotal); + sound_unref(s); + xlpop(); +} + + +/* sound_print_tree -- print a tree version of sound structure */ +/**/ +void sound_print_tree(snd) + sound_type snd; +{ +/* nyquist_printf("sample_block_free %p\n", sample_block_free);*/ + nyquist_printf("SOUND PRINT TREE of %p\n", snd); + sound_print_tree_1(snd, 0); +} + + +void indent(int n) +{ + while (n-- > 0) stdputstr(" "); +} + + +void sound_print_tree_1(snd, n) + sound_type snd; + int n; +{ + int i; + snd_list_type snd_list; + if (n > 100) { + stdputstr("... (skipping remainder of sound)\n"); + return; + } + if (!snd) { + stdputstr("\n"); + return; + } + nyquist_printf("sound_type@%p(%s@%p)t0 " + "%g stop %d sr %g lsc %d scale %g pc %d", + snd, + (snd->get_next == SND_get_next ? "SND_get_next" : + (snd->get_next == SND_get_first ? "SND_get_first" : "?")), + snd->get_next, snd->t0, (int)snd->stop, snd->sr, + (int)snd->logical_stop_cnt, snd->scale, + (int)snd->prepend_cnt); + snd_list = snd->list; + nyquist_printf("->snd_list@%p", snd_list); + if (snd_list == zero_snd_list) { + stdputstr(" = zero_snd_list\n"); + return; + } + for (i = 0; ; i++) { + if (snd_list == zero_snd_list) { + if (i > 1) nyquist_printf(" (skipping %d) ", i-1); + stdputstr("->zero_snd_list\n"); + return; + } + if (!snd_list->block) { + if (i > 0) nyquist_printf(" (skipping %d) ", i); + stdputstr("->\n"); + indent(n + 2); + + nyquist_printf("susp@%p(%s)toss_cnt %d " + "current %d lsc %d sr %g t0 %g %p\n", + snd_list->u.susp, snd_list->u.susp->name, + (int)snd_list->u.susp->toss_cnt, + (int)snd_list->u.susp->current, + (int)snd_list->u.susp->log_stop_cnt, + snd_list->u.susp->sr, + snd_list->u.susp->t0, snd_list); +/* stdputstr("HI THERE AGAIN\n");*/ + susp_print_tree(snd_list->u.susp, n + 4); + return; + } + snd_list = snd_list->u.next; + } +} + + +/* mark_audio_time -- record the current playback time + * + * The global variable *audio-markers* is treated as a list. + * When the user types ^Q, this function pushes the current + * playback time onto the list + */ +void mark_audio_time() +{ + double playback_time = sound_frames / sound_srate - sound_latency; + LVAL time_node = cvflonum(playback_time); + setvalue(s_audio_markers, cons(time_node, getvalue(s_audio_markers))); + gprintf(TRANS, " %g ", playback_time); + fflush(stdout); +} + + +/* compute constants p1 and p2: + pitchconvert(0) * 2 = pitchconvert(12) - octaves + exp(p2) * 2 = exp(12 * p1 + p2) + 2 = exp(12 * p1) + log(2) = 12 * p1 + + p1 = log(2.0)/12; + + pitchconvert(69) gives 440Hz + exp(69 * p1 + p2) = 440 + 69 * p1 + p2 = log(440) + + p2 = log(440.0) - (69 * p1); +*/ + +#define p1 0.0577622650466621 +#define p2 2.1011784386926213 + + +double hz_to_step(double hz) +{ + return (log(hz) - p2) / p1; +} + + +double step_to_hz(steps) + double steps; +{ + return exp(steps * p1 + p2); +} + + +/* + * from old stuff... + */ + +static void sound_xlfree(s) +sound_type s; +{ +/* nyquist_printf("sound_xlfree(%p)\n", s);*/ + sound_unref(s); +} + + +static void sound_xlprint(LVAL fptr, sound_type s) +{ + /* the type cast from s to LVAL is OK because + * putatm does not dereference the 3rd parameter */ + putatm(fptr, "Sound", (LVAL) s); +} + + +static void sound_xlsave(fp, s) +FILE *fp; +sound_type s; +{ + stdputstr("sound_save called\n"); +} + + +static unsigned char *sound_xlrestore(FILE *fp) +{ + stdputstr("sound_restore called\n"); + return NULL; +} + + +/* sound_xlmark -- mark LVAL nodes reachable from this sound */ +/**/ +void sound_xlmark(s) +sound_type s; +{ + snd_list_type snd_list; + long counter = 0; +#ifdef TRACESNDGC + nyquist_printf("sound_xlmark(%p)\n", s); +#endif + if (!s) return; /* pointers to sounds are sometimes NULL */ + snd_list = s->list; + while (snd_list->block != NULL) { + if (snd_list == zero_snd_list) { +#ifdef TRACESNDGC + stdputstr(" terminates at zero_snd_list\n"); +#endif + return; + } else if (counter > 1000000) { + stdputstr("You created a recursive sound! This is a Nyquist bug.\n"); + stdputstr("The only known way to do this is by a SETF on a\n"); + stdputstr("local variable or parameter that is being passed to SEQ\n"); + stdputstr("or SEQREP. The garbage collector assumes that sounds are\n"); + stdputstr("not recursive or circular, and follows sounds to their\n"); + stdputstr("end. After following a million nodes, I'm pretty sure\n"); + stdputstr("that there is a cycle here, but since this is a bug,\n"); + stdputstr("I cannot promise to recover. Prepare to crash. If you\n"); + stdputstr("cannot locate the cause of this, contact the author -RBD.\n"); + } + snd_list = snd_list->u.next; + counter++; + } + if (snd_list->u.susp->mark) { +#ifdef TRACESNDGC + nyquist_printf(" found susp (%s) at %p with mark method\n", + snd_list->u.susp->name, snd_list->u.susp); +#endif + (*(snd_list->u.susp->mark))(snd_list->u.susp); + } else { +#ifdef TRACESNDGC + nyquist_printf(" no mark method on susp %p (%s)\n", + snd_list->u.susp, snd_list->u.susp->name); +#endif + } +} + + +void sound_symbols() +{ + a_sound = xlenter("SOUND"); + s_audio_markers = xlenter("*AUDIO-MARKERS*"); + setvalue(s_audio_markers, NIL); +} + + +/* The SOUND Type: */ + + +boolean soundp(s) +LVAL s; +{ + return (exttypep(s, a_sound)); +} + + +/* sound_zero - create and return a zero that terminates now */ +/**/ +sound_type sound_zero(time_type t0,rate_type sr) +{ + sound_type sound; + falloc_sound(sound, "sound_zero"); + + sound->get_next = SND_get_first; + sound->list = zero_snd_list; + sound->logical_stop_cnt = sound->current = 0; + sound->true_t0 = sound->t0 = sound->time = t0; + sound->stop = MAX_STOP; + sound->sr = sr; + sound->scale = 1.0F; + sound->table = NULL; + sound->extra = NULL; + + return sound; +} + + +LVAL cvsound(s) +sound_type s; +{ +/* nyquist_printf("cvsound(%p)\n", s);*/ + return (cvextern(sound_desc, (unsigned char *) s)); +} + diff --git a/nyqsrc/sound.h b/nyqsrc/sound.h new file mode 100644 index 0000000..70ace3c --- /dev/null +++ b/nyqsrc/sound.h @@ -0,0 +1,533 @@ +/* sound.h -- new nyquist sound data type */ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 28Apr03 dm changes for portability: moved some defns out of here + */ + +#include +#include "stdefs.h" + +/* used for *AUDIO-MARKERS* */ +extern long sound_frames; +extern double sound_srate; + +#if OSC +extern int nosc_enabled; /* enable polling for OSC messages */ +#endif + +#if USE_PRINTF +#define nyquist_printf printf +#endif + +#define PERMS 0644 /* -rw-r--r-- */ + +/* default stop sample count (for clipping) */ +#define MAX_STOP 0x7FFFFFFF + +/* default stop time (for clipping) */ +#define MAX_STOP_TIME 10E20 +/* LISP-SRC: (SETF MAX-STOP-TIME 10E20) */ +#define MIN_START_TIME -10E20 +/* LISP-SRC: (SETF MIN-START-TIME -10E20) */ + +/* conversion from float to integer */ +#define SCALE_FACTOR_TO_BYTE 127 +#define SCALE_FACTOR_TO_SHORT 32767 +#define SCALE_FACTOR_TO_24BIT 0x7FFFFF +#define SCALE_FACTOR_TO_LONG 2147483647 + +/* Note that the values assigned here are not arbitrary, but represent + a dominance relationship among the interpolation types. +*/ +#define INTERP_n 0 +#define INTERP_s 1 +#define INTERP_i 2 +#define INTERP_r 3 + +#define INTERP_nn 0 +#define INTERP_ns 1 +#define INTERP_ni 2 +#define INTERP_nr 3 +#define INTERP_sn 4 +#define INTERP_ss 5 +#define INTERP_si 6 +#define INTERP_sr 7 + +#define INTERP_nnn 0 +#define INTERP_nns 1 +#define INTERP_nni 2 +#define INTERP_nnr 3 +#define INTERP_nsn 4 +#define INTERP_nss 5 +#define INTERP_nsi 6 +#define INTERP_nsr 7 +#define INTERP_nin 8 +#define INTERP_nis 9 +#define INTERP_nii 10 +#define INTERP_nir 11 +#define INTERP_nrn 12 +#define INTERP_nrs 13 +#define INTERP_nri 14 +#define INTERP_nrr 15 +#define INTERP_snn 16 +#define INTERP_sns 17 +#define INTERP_sni 18 +#define INTERP_snr 19 +#define INTERP_ssn 20 +#define INTERP_sss 21 +#define INTERP_ssi 22 +#define INTERP_ssr 23 +#define INTERP_sin 24 +#define INTERP_sis 25 +#define INTERP_sii 26 +#define INTERP_sir 27 +#define INTERP_srn 28 +#define INTERP_srs 29 +#define INTERP_sri 30 +#define INTERP_srr 31 + +#define INTERP_nnnn 0 +#define INTERP_nnns 1 +#define INTERP_nnsn 4 +#define INTERP_nnss 5 +#define INTERP_nsnn 16 +#define INTERP_nsns 17 +#define INTERP_nssn 20 +#define INTERP_nsss 21 +#define INTERP_snnn 64 +#define INTERP_snns 65 +#define INTERP_snsn 68 +#define INTERP_snss 69 +#define INTERP_ssnn 80 +#define INTERP_ssns 81 +#define INTERP_sssn 84 +#define INTERP_ssss 85 +#define INTERP_niii 42 +#define INTERP_siii 106 +#define INTERP_nrrr 63 +#define INTERP_srrr 127 + +#define INTERP_nnnnnn 0 +#define INTERP_ssssss 1365 + +#define INTERP_nnnnnnnn 0 +#define INTERP_ssssssss 21845 + + +#define INTERP_MASK 3 +#define INTERP_SHIFT 2 + +LVAL snd_badsr(void); + +typedef double time_type; +typedef double rate_type; +typedef float sample_type; +typedef double promoted_sample_type; + +/* use radians or degrees for phase? */ +#define ANGLEBASE 360.0 + +/* used by sndwrite.c for output buffers. This should be + * eliminated: + */ +#define MAX_SND_CHANNELS 24 + +#define max_table_len 100000 +/* Set to 4 for debugging block allocation stuff, 1012? for + production +*/ +/* leave a few words short of 1024 in case we allocate powers of 2 */ +#define max_sample_block_len 1020 +/* #define max_sample_block_len 4 */ + +/* Defines needed for xlisp */ +#define getsound(x) ((sound_type) getinst(x)) +#define xlgasound() (testarg(typearg(soundp))) + +typedef short SFDataType, *SFDataPtr; + +typedef sample_type sample_block_values[max_sample_block_len], + *sample_block_values_type; + +typedef struct { + long refcnt; /* reference count */ + sample_block_values samples; +} sample_block_node, *sample_block_type; + + +typedef struct snd_susp_struct { + void (*fetch)(struct snd_susp_struct *, struct snd_susp_struct *); + void (*keep_fetch)(struct snd_susp_struct *); + void (*free)(struct snd_susp_struct *); + void (*mark)(struct snd_susp_struct *); /* marks LVAL nodes for GC */ + void (*print_tree)(struct snd_susp_struct *, int); /* debugging */ + char * name; /* string name for debugging */ + long toss_cnt; /* return this many zeros, then compute */ + long current; /* current sample number */ + double sr; /* sample rate */ + time_type t0; /* starting time */ + long log_stop_cnt; /* logical stop count */ + /* other susp dependent stuff will be here... */ +} snd_susp_node, *snd_susp_type; + + +typedef struct snd_list_struct { + sample_block_type block; /* pointer to block of samples */ + union { + struct snd_list_struct *next; + snd_susp_type susp; + } u; + short refcnt; + short block_len; + boolean logically_stopped; +} snd_list_node, *snd_list_type; + +extern snd_list_type list_watch; //DBY + + +typedef struct table_struct { + long refcount; /* reference count */ + double length; /* number of samples in table + (double allows fractional length)*/ + sample_type samples[1]; /* arbitrary length array of sample */ +} table_node, *table_type; + + +/* some counts are biased by -max_sample_block_len, so UNKNOWN can't be -1 + * Any number less than -max_sample_block should do + */ +#define UNKNOWN (-10-max_sample_block_len) + +typedef struct sound_struct { + sample_block_type (*get_next)(struct sound_struct *snd, long *cnt); + time_type time; /* logical starting time */ + time_type t0; /* quantized time of first sample */ + long stop; /* stop (clipping) sample no. */ + time_type true_t0; /* exact time of first sample */ + rate_type sr; /* sample rate */ + long current; /* current sample number, + if negative, then the first + -current samples must be dropped + in order to find the first sample */ + long logical_stop_cnt; /* log stop sample no, -1=unknwn */ + snd_list_type list; /* sample block list, starting at curr. samp */ + sample_type scale; /* scale factor for the result */ + long prepend_cnt; /* how many zeros to prepend */ + /* function to use as get_next after prepended zeros are generated: */ + sample_block_type (*after_prepend) + (struct sound_struct * snd, long * cnt); + table_type table; /* pointer to table-ized version of this sound */ + long *extra; /* used for extra state information, first word of extra + state should be the length of the extra state + (see sound_unref()) + */ +} sound_node, *sound_type; + +/* convert number of samples to memory size: */ +#define table_size_in_bytes(n) \ + (sizeof(table_node) + sizeof(sample_type) * ((n) - 1)) + +extern sample_block_type zero_block; +extern sample_block_type internal_zero_block; + +extern snd_list_type zero_snd_list; + +extern sound_type printing_this_sound; /* debugging global */ + +extern double sound_latency; /* controls output latency */ +double snd_set_latency(double latency); +/* LISP: (SND-SET-LATENCY FLONUM) */ + +double compute_phase(double phase, double key, long n, double srate, + double new_srate, double freq, double *incr_ptr); + +boolean soundp(LVAL); +/* LISP: (SOUNDP ANY) */ + +void snd_list_ref(snd_list_type list); +void sound_unref(sound_type snd); +void snd_list_unref(snd_list_type list); + +LVAL cvsound(sound_type); +extern LVAL a_sound; + +sample_block_type SND_get_next(sound_type snd, long * cnt); +sample_block_type SND_get_first(sound_type snd, long * cnt); +sample_block_type SND_get_zeros(sound_type snd, long * cnt); +sample_block_type SND_flush(sound_type snd, long * cnt); + +double hz_to_step(double); /* LISP: (HZ-TO-STEP ANYNUM) */ +int interp_style(sound_type s, rate_type sr); +void set_logical_stop_time(sound_type sound, time_type when); /* LISP: (SND-SET-LOGICAL-STOP SOUND ANYNUM) */ + +#define xlog(x) log(x) +/* LISP: double (LOG FLONUM) */ +snd_list_type snd_list_create(snd_susp_type susp); +void snd_list_terminate(snd_list_type snd_list); +void snd_sort_2(sound_type * s1_ptr, sound_type * s2_ptr, rate_type sr); + +double snd_sref(sound_type s, time_type t); + /* LISP: (SND-SREF SOUND ANYNUM) */ + +double snd_sref_inverse(sound_type s, double val); + /* LISP: (SREF-INVERSE SOUND ANYNUM) */ + +double snd_stop_time(sound_type s); /* LISP: (SND-STOP-TIME SOUND) */ +#define snd_time(s) (s)->time + /* LISP: double (SND-TIME SOUND) */ + +#define snd_srate(s) (s)->sr + /* LISP: double (SND-SRATE SOUND) */ +#define snd_t0(s) (s)->t0 + /* LISP: double (SND-T0 SOUND) */ + +sound_type snd_xform(sound_type snd, rate_type sr, time_type time, + time_type start_time, time_type stop_time, promoted_sample_type scale); + /* LISP: (SND-XFORM SOUND ANYNUM ANYNUM ANYNUM ANYNUM ANYNUM) */ +sound_type sound_create(snd_susp_type susp, time_type t0, rate_type sr, + promoted_sample_type scale); + +void min_cnt(long *cnt_ptr, sound_type sound, snd_susp_type susp, long cnt); +void indent(int n); +void sound_prepend_zeros(sound_type snd, time_type t0); + + + +#ifndef GCBUG +#define blocks_to_watch_max 50 +extern long blocks_to_watch_len; +extern sample_block_type blocks_to_watch[blocks_to_watch_max]; + +void block_watch(long sample_block); + /* LISP: (BLOCK-WATCH FIXNUM) */ +long sound_nth_block(sound_type snd, long n); + /* LISP: (SOUND-NTH-BLOCK SOUND FIXNUM) */ +#endif + +sound_type sound_copy(sound_type snd); + /* LISP: (SND-COPY SOUND) */ +void sound_xlmark(sound_type s); +void sound_print(LVAL snd_expr, long n); + /* LISP: (SND-PRINT ANY FIXNUM) */ +void sound_play(LVAL snd_expr); + /* LISP: (SND-PLAY ANY) */ +void stats(void); + /* LISP: (STATS) */ +void sound_print_tree(sound_type snd); + /* LISP: (SND-PRINT-TREE SOUND) */ + +void mark_audio_time(void); + +void sound_print_tree_1(sound_type snd, int n); + +sound_type sound_scale(double factor, sound_type snd); + /* LISP: (SND-SCALE ANYNUM SOUND) */ +void sound_init(void); + +void sound_symbols(void); + +table_type sound_to_table(sound_type s); + +void table_unref(table_type table); + +sound_type sound_zero(time_type t0, rate_type sr); + /* LISP: (SND-ZERO ANYNUM ANYNUM) */ + +#define sound_get_next(s, n) ((*(s->get_next))(s, n)) + +#define susp_print_tree(s, n) (*((s)->print_tree))(s, n) + +double step_to_hz(double); + /* LISP: (STEP-TO-HZ ANYNUM) */ + +/* macros for access to samples within a suspension */ +/* NOTE: assume suspension structure is named "susp" */ + +/* susp_check_samples points sample_ptr to a new sample block if necessary */ +#define susp_check_samples(sound, sample_ptr, sample_cnt) \ + if (susp->sample_cnt == 0) \ + susp_get_samples(sound, sample_ptr, sample_cnt) + +/* susp_check_samples_break is similar to susp_check_samples - "_break" + * normally means that this code will break out of the inner loop, but in + * this case, there is no reason (neither log nor term) to break. + * x2_sample is taken from sound + */ +#define susp_check_samples_break(sound, sample_ptr, sample_cnt, x2_sample) \ + if (susp->sample_cnt == 0) { \ + susp_get_samples(sound, sample_ptr, sample_cnt); \ + x2_sample = susp_current_sample(sound, sample_ptr); } + + +/* susp_get_samples always gets next block (useful only in initialization code) */ +#define susp_get_samples(sound, sample_ptr, sample_cnt) \ + susp->sample_ptr = sound_get_next(susp->sound, &(susp->sample_cnt))->samples + +/* susp_get_block_samples always gets next block (useful only in initialization code) */ +#define susp_get_block_samples(sound, sample_block_ptr, sample_ptr, sample_cnt) \ + susp->sample_block_ptr = sound_get_next(susp->sound, &susp->sample_cnt); \ + susp->sample_ptr = susp->sample_block_ptr->samples + +/* susp_took is called after you've taken n samples */ +#define susp_took(sample_cnt, n) susp->sample_cnt -= n + +/* susp_fetch_sample is used to grab just one sample, doesn't check for samples!, + * but applies scale factor: */ +#define susp_fetch_sample(sound, sample_ptr, sample_cnt) \ + (susp->sound->scale * (susp->sample_cnt--, *(susp->sample_ptr++))) + +/* susp_current_sample grabs sample without advancing to next, applies scale + * factor: */ +#define susp_current_sample(sound, sample_ptr) \ + (susp->sound->scale * (*(susp->sample_ptr))) + +/* susp_check_term_samples checks for samples; if new ones are fetched, then + * run termination test on signal and record result. + */ +#define susp_check_term_samples(sound, sample_ptr, sample_cnt) \ + if (susp->sample_cnt == 0) { \ + susp_get_samples(sound, sample_ptr, sample_cnt); \ + terminate_test(sample_ptr, sound, susp->sample_cnt); } + +/* susp_check_term_log_samples checks for samples + * if new ones are fetched, then run termination test and logical stop + * test on signal and record results. + */ +#define susp_check_term_log_samples(sound, sample_ptr, sample_cnt) \ + if (susp->sample_cnt == 0) { \ + susp_get_samples(sound, sample_ptr, sample_cnt); \ + logical_stop_test(sound, susp->sample_cnt); \ + terminate_test(sample_ptr, sound, susp->sample_cnt); } + +/* susp_check_term_log_block_samples checks for samples + * if new ones are fetched, then run termination test and logical stop + * test on signal and record results. In this case, termination and logical + * stop happen at the MAXIMUM of termination and logical stop times, resp. + * + * Originally, this code assumed that logical stops occurred on block boundaries, + * but because of the SET-LOGICAL-STOP function, which just writes a stop time + * into the sound_struct, the logical stop can be anywhere. As soon as the + * logical stop is known, we want to propagate the value from the sound being + * read into the sound being computed. The propagation should set the logical + * stop of the computed sound to the MAX of any current value and the new + * value. When the bit fields indicate that all logical stop times have been + * encountered, then the sound being computed will make the logical stop happen + * on a block boundary and set the flag on the block of samples where the stop + * occurs. + */ +#define susp_check_term_log_block_samples(sound, sample_block_ptr, sample_ptr, sample_cnt, bit, all) \ + if (susp->sample_cnt == 0) { \ + susp_get_block_samples(sound, sample_block_ptr, sample_ptr, sample_cnt); \ +/*OLD if (susp->sound->logical_stop_cnt == \ + susp->sound->current - susp->sample_cnt) { \ +*/ \ + if (susp->sound->logical_stop_cnt != UNKNOWN && \ + !(susp->logical_stop_bits & bit)) { \ + susp->logical_stop_bits |= bit; \ +/*OLD \ + if (susp->logical_stop_bits == all) { \ + susp->susp.log_stop_cnt = (long) \ + ((((susp->sound->current - susp->sample_cnt) / \ + susp->sound->sr + susp->sound->t0) - \ + susp->susp.t0) * susp->susp.sr + 0.5); \ + assert(susp->susp.log_stop_cnt >= 0); } } \ +*/ \ + susp->susp.log_stop_cnt = max(susp->susp.log_stop_cnt, \ + (((susp->sound->logical_stop_cnt / \ + susp->sound->sr + susp->sound->t0) - \ + susp->susp.t0) * susp->susp.sr + 0.5)); } \ + if (susp->sample_ptr == zero_block->samples) { \ + susp->terminate_bits |= bit; \ + if (susp->terminate_bits == all) { \ + susp->terminate_cnt = (long) \ + ((((susp->sound->current - susp->sample_cnt) / \ + susp->sound->sr + susp->sound->t0) - \ + susp->susp.t0) * susp->susp.sr + 0.5); \ + } } } + + +/* logical_stop_cnt_cvt is used to convert from the logical stop count + * at one sample rate to that of another sample rate -- this macro is + * used by the snd_make_ routine in every .c file, and assumes + * the target sample rate is susp->susp.sr. + * + * NOTE: this macro does not take into account the possibility of different + * start times - maybe it should. + */ +#define logical_stop_cnt_cvt(sound) \ + (sound->logical_stop_cnt == UNKNOWN ? UNKNOWN : \ + ROUND((sound->logical_stop_cnt / sound->sr) * susp->susp.sr)) + + +/* logical_stop_test tests to see if sound has logically stopped; if so, + * sets susp->susp.log_stop_cnt. The resulting logical_stop_cnt will reflect + * the minimum logical_stop time of all sounds to which this test is applied. + */ +#define logical_stop_test(sound, cnt) \ + if (susp->sound->logical_stop_cnt == susp->sound->current - (cnt)) {\ + min_cnt(&susp->susp.log_stop_cnt, susp->sound, (snd_susp_type) susp, cnt); } + +/* terminate_test checks to see if sound has terminated; if so, + * sets susp->terminate_cnt. The resulting terminate_cnt will reflect + * the minimum termination time of all sounds to which this test is applied. + */ +#define terminate_test(sample_ptr, sound, cnt) \ + if (susp->sample_ptr == zero_block->samples) { \ + min_cnt(&susp->terminate_cnt, susp->sound, (snd_susp_type) susp, cnt); } + + +/* susp_check_log_samples checks for new samples then checks for + * termination and logical stop conditions + */ +#define susp_check_log_samples(sound, sample_ptr, sample_cnt) \ + if (susp->sample_cnt == 0) { \ + susp_get_samples(sound, sample_ptr, sample_cnt); \ + logical_stop_test(sound, susp->sample_cnt); } + +/* susp_check_term_samples_break checks for new samples then checks for + * termination condition; breaks from inner loop + */ +#define susp_check_term_samples_break( \ + sound, sample_ptr, sample_cnt, x2_sample) \ + if (susp->sample_cnt == 0) { \ + susp_get_samples(sound, sample_ptr, sample_cnt); \ + x2_sample = susp_current_sample(sound, sample_ptr); \ + terminate_test(sample_ptr, sound, susp->sample_cnt); \ + if (susp->terminate_cnt < susp->susp.current + cnt + togo) { \ + break; }} \ + else x2_sample = susp_current_sample(sound, sample_ptr); + +/* susp_check_log_samples_break checks for new samples then checks for + * logical stop conditions; breaks from inner loop + */ +#define susp_check_log_samples_break( \ + sound, sample_ptr, sample_cnt, x2_sample) \ + if (susp->sample_cnt == 0) { \ + susp_get_samples(sound, sample_ptr, sample_cnt); \ + x2_sample = susp_current_sample(sound, sample_ptr); \ + logical_stop_test(sound, susp->sample_cnt); \ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN && \ + (susp->susp.log_stop_cnt < susp->susp.current + cnt + togo)) { \ + break; }} \ + else x2_sample = susp_current_sample(sound, sample_ptr); + + +/* susp_check_term_log_samples_break checks for new samples then checks for + * termination and logical stop conditions; breaks from inner loop + */ +#define susp_check_term_log_samples_break( \ + sound, sample_ptr, sample_cnt, x2_sample) \ + if (susp->sample_cnt == 0) { \ + susp_get_samples(sound, sample_ptr, sample_cnt); \ + x2_sample = susp_current_sample(sound, sample_ptr); \ + terminate_test(sample_ptr, sound, susp->sample_cnt); \ + logical_stop_test(sound, susp->sample_cnt); \ + if ((susp->terminate_cnt != UNKNOWN && \ + susp->terminate_cnt < susp->susp.current + cnt + togo) || \ + (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN && \ + susp->susp.log_stop_cnt < susp->susp.current + cnt + togo)) { \ + break; }} \ + else x2_sample = susp_current_sample(sound, sample_ptr); + + diff --git a/nyqsrc/stats.c b/nyqsrc/stats.c new file mode 100644 index 0000000..7f21612 --- /dev/null +++ b/nyqsrc/stats.c @@ -0,0 +1,27 @@ +/* + * stats.c + * + * produce statistics. + */ +#include "switches.h" +#include +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" + + +void stats() +{ + nyquist_printf("\n\nNyquist statistics:\n\n"); + nyquist_printf("Memory usage:\n"); + nyquist_printf("\tconsumed %d pools of size %d\n", npools, MAXPOOLSIZE); + nyquist_printf("\tdata structure usage:\n"); + nyquist_printf("\t\tsounds\t%d\n", sound_used); + nyquist_printf("\t\tsnd lists\t%d\n", snd_list_used); + nyquist_printf("\t\tsample blocks\t%d\n", sample_block_used); + nyquist_printf("\t\ttable space in bytes\t%ld\n", table_memory); + nyquist_printf("\n"); +} diff --git a/nyqsrc/stdefs.h b/nyqsrc/stdefs.h new file mode 100644 index 0000000..9eba22c --- /dev/null +++ b/nyqsrc/stdefs.h @@ -0,0 +1,49 @@ +/* stdefs.h */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef PI +#define PI (3.14159265358979323846) +#endif + +#ifndef PI2 +#define PI2 (6.28318530717958647693) +#endif + +#define D2R (0.01745329348) /* (2*pi)/360 */ +#define R2D (57.29577951) /* 360/(2*pi) */ + +#ifndef MAX +#define MAX(x,y) ((x)>(y) ?(x):(y)) +#endif +#ifndef MIN +#define MIN(x,y) ((x)<(y) ?(x):(y)) +#endif + +#ifndef ABS +#define ABS(x) ((x)<0 ?(-(x)):(x)) +#endif + +#ifndef SGN +#define SGN(x) ((x)<0 ?(-1):((x)==0?(0):(1))) +#endif + +typedef float mem_float; +typedef double fast_float; + +/* I took out this typedef because the same thing + * exists in cext.h which causes a conflict: -RBD +typedef unsigned char boolean; */ + +#include "cext.h" + +#define true 1 +#define false 0 + + diff --git a/nyqsrc/trigger.c b/nyqsrc/trigger.c new file mode 100644 index 0000000..f55ba95 --- /dev/null +++ b/nyqsrc/trigger.c @@ -0,0 +1,326 @@ +/* trigger.c -- return zero until input transitions from <=0 to >0, then + evaluate a closure to get a signal and convert to an add + of the new signal and a copy of this trigger object. + The sample rate of the output is the sample rate of the input, and + sounds returned by the closure must also have a matching sample rate. + The trigger will take place on the first input sample (zero delay) if the + first sample of the input is >0. + The input scale factor is assumed to be 1, so caller should force scaling + especially if the scale factor is negative (!) + The trigger terminates when the input signal terminates (but any adds + continue to run until all their inputs terminate). + +Some implementation notes: + +The closure gets evaluated at the time of the positive sample. +When the positive sample is encountered, first close off the +current output block. + +Next, evaluate the closure, clone the trigger, and convert +the current trigger to an add. The next fetch will therefore +go to the add susp and it will add the closure result to the +zeros that continue to be generated by (a clone of) the trigger. +It would be simple if we could back the clone up one sample: +on the first call to the add, it will ask for samples from the +trigger clone and the closure, but the trigger clone has already +processed the positive sample, so it is one sample ahead of +everyone else. Since we've just read a sample, we CAN back up +just by carefully updating the input pointer to one less than +we actually read, forcing a reread later. (We'll still store +the previous value so re-reading will not re-trigger.) +*/ + +/* CHANGE LOG + * -------------------------------------------------------------------- + * 13Dec06 rbd created from sndseq.c + */ + +#include "stdio.h" +#ifndef mips +#include "stdlib.h" +#endif +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "scale.h" +#include "add.h" +#include "extern.h" +#include "cext.h" +#include "assert.h" + +#define TRIGGERDBG 0 +#define D if (TRIGGERDBG) + +/* Note: this structure is identical to an add_susp structure up + to the field output_per_s2 so that we can convert this into + an add after eval'ing the closure. Since this struct is bigger + than an add, make sure not to clobber the "free" routine + (trigger_free) or else we'll leak memory. + */ +typedef struct trigger_susp_struct { + snd_susp_node susp; + boolean started; + int terminate_bits; + long terminate_cnt; + int logical_stop_bits; + boolean logically_stopped; + sound_type s1; + long s1_cnt; + sample_block_type s1_bptr; /* block pointer */ + sample_block_values_type s1_ptr; + sound_type s2; + long s2_cnt; + sample_block_type s2_bptr; /* block pointer */ + sample_block_values_type s2_ptr; + + /* trigger-specific data starts here */ + sample_type previous; + LVAL closure; + +} trigger_susp_node, *trigger_susp_type; + + +void trigger_fetch(trigger_susp_type, snd_list_type); +void trigger_free(); + +extern LVAL s_stdout; + +void trigger_mark(trigger_susp_type susp) +{ + sound_xlmark(susp->s1); + if (susp->closure) mark(susp->closure); +} + + + +/* trigger_fetch returns zero blocks until s1 goes from <=0 to >0 */ +/**/ +void trigger_fetch(trigger_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + int togo; + int n; + sample_block_type out; + register sample_block_values_type out_ptr; + register sample_block_values_type out_ptr_reg; + register sample_block_values_type input_ptr_reg; + falloc_sample_block(out, "trigger_fetch"); + out_ptr = out->samples; + snd_list->block = out; + + while (cnt < max_sample_block_len) { /* outer loop */ + /* first compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block */ + togo = max_sample_block_len - cnt; + + /* don't run past the input sample block: */ + susp_check_term_samples(s1, s1_ptr, s1_cnt); + togo = min(togo, susp->s1_cnt); + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo) { + togo = susp->terminate_cnt - (susp->susp.current + cnt); + if (togo == 0) break; + } + + n = togo; + input_ptr_reg = susp->s1_ptr; + out_ptr_reg = out_ptr; + if (n) do { /* the inner sample computation loop */ + sample_type s = *input_ptr_reg++; + if (susp->previous <= 0 && s > 0) { + trigger_susp_type new_trigger; + sound_type new_trigger_snd; + LVAL result; + long delay; /* sample delay to s2 */ + time_type now; + + susp->previous = s; /* don't retrigger */ + + /**** close off block ****/ + togo = togo - n; + susp->s1_ptr += togo; + susp_took(s1_cnt, togo); + cnt += togo; + snd_list->block_len = cnt; + susp->susp.current += cnt; + now = susp->susp.t0 + susp->susp.current / susp->susp.sr; + + /**** eval closure and add result ****/ +D nyquist_printf("trigger_fetch: about to eval closure at %g, " + "susp->susp.t0 %g, susp.current %d:\n", + now, susp->susp.t0, (int)susp->susp.current); + xlsave1(result); + result = xleval(cons(susp->closure, consa(cvflonum(now)))); + if (exttypep(result, a_sound)) { + susp->s2 = sound_copy(getsound(result)); +D nyquist_printf("trigger: copied result from closure is %p\n", + susp->s2); + } else xlerror("closure did not return a (monophonic) sound", + result); +D nyquist_printf("in trigger: after evaluation; " + "%p returned from evform\n", + susp->s2); + result = NIL; + + /**** cloan this trigger to become s1 ****/ + falloc_generic(new_trigger, trigger_susp_node, + "new_trigger"); + memcpy(new_trigger, susp, sizeof(trigger_susp_node)); + /* don't copy s2 -- it should only be referenced by add */ + new_trigger->s2 = NULL; + new_trigger_snd = sound_create((snd_susp_type) new_trigger, + now, susp->susp.sr, 1.0F); + susp->s1 = new_trigger_snd; + /* add will have to ask new_trigger for samples, new_trigger + * will continue reading samples from s1 (the original input) + */ + susp->s1_cnt = 0; + susp->s1_ptr = NULL; + + /**** convert to add ****/ + susp->susp.mark = add_mark; + /* logical stop will be recomputed by add: */ + susp->susp.log_stop_cnt = UNKNOWN; + susp->susp.print_tree = add_print_tree; + + /* assume sample rates are the same */ + if (susp->s1->sr != susp->s2->sr) + xlfail("in trigger: sample rates must match"); + + /* take care of scale factor, if any */ + if (susp->s2->scale != 1.0) { + // stdputstr("normalizing next sound in a seq\n"); + susp->s2 = snd_make_normalize(susp->s2); + } + + /* figure out which add fetch routine to use */ + delay = ROUND((susp->s2->t0 - now) * susp->s1->sr); + if (delay > 0) { /* fill hole between s1 and s2 */ + D stdputstr("using add_s1_nn_fetch\n"); + susp->susp.fetch = add_s1_nn_fetch; + susp->susp.name = "trigger:add_s1_nn_fetch"; + } else { + susp->susp.fetch = add_s1_s2_nn_fetch; + susp->susp.name = "trigger:add_s1_s2_nn_fetch"; + } + +D stdputstr("in trigger: calling add's fetch\n"); + /* fetch will get called later .. + (*(susp->susp.fetch))(susp, snd_list); */ +D stdputstr("in trigger: returned from add's fetch\n"); + xlpop(); + + susp->closure = NULL; /* allow garbage collection now */ + /**** calculation tree modified, time to exit ****/ + /* but if cnt == 0, then we haven't computed any samples */ + /* call on new fetch routine to get some samples */ + if (cnt == 0) { + ffree_sample_block(out, "trigger-pre-adder"); // because adder will reallocate + (*susp->susp.fetch)(susp, snd_list); + } + return; + } else { + susp->previous = s; + /* output zero until ready to add in closure */ + *out_ptr_reg++ = 0; + } + } while (--n); /* inner loop */ + + /* using input_ptr_reg is a bad idea on RS/6000: */ + susp->s1_ptr += togo; + out_ptr += togo; + susp_took(s1_cnt, togo); + cnt += togo; + } /* outer loop */ + + if (togo == 0 && cnt == 0) { + snd_list_terminate(snd_list); + } else { + snd_list->block_len = cnt; + susp->susp.current += cnt; + } +} /* trigger_fetch */ + + +void trigger_free(trigger_susp_type susp) +{ + sound_unref(susp->s1); + sound_unref(susp->s2); + ffree_generic(susp, sizeof(trigger_susp_node), "trigger_free"); +} + + +void trigger_print_tree(trigger_susp_type susp, int n) +{ + indent(n); + stdputstr("s1:"); + sound_print_tree_1(susp->s1, n); + + indent(n); + stdputstr("closure:"); + stdprint(susp->closure); + + indent(n); + stdputstr("s2:"); + sound_print_tree_1(susp->s2, n); +} + + + + +sound_type snd_make_trigger(s1, closure) + sound_type s1; + LVAL closure; +{ + register trigger_susp_type susp; + /* t0 specified as input parameter */ + sample_type scale_factor = 1.0F; + sound_type result; + + xlprot1(closure); + falloc_generic(susp, trigger_susp_node, "snd_make_trigger"); + + if (s1->scale != 1.0) { + /* stdputstr("normalizing first sound in a seq\n"); */ + s1 = snd_make_normalize(s1); + } + + susp->susp.fetch = trigger_fetch; + + susp->terminate_cnt = UNKNOWN; + susp->terminate_bits = 0; /* bits for s1 and s2 termination */ + susp->logical_stop_bits = 0; /* bits for s1 and s2 logical stop */ + + /* initialize susp state */ + susp->susp.free = trigger_free; + susp->susp.sr = s1->sr; + susp->susp.t0 = s1->t0; + susp->susp.mark = trigger_mark; + susp->susp.print_tree = trigger_print_tree; + susp->susp.name = "trigger"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = s1->logical_stop_cnt; + susp->started = false; + susp->susp.current = 0; + susp->s1 = s1; + susp->s1_cnt = 0; + susp->s2 = NULL; + susp->s2_cnt = 0; + susp->closure = closure; + susp->previous = 0; + result = sound_create((snd_susp_type)susp, susp->susp.t0, susp->susp.sr, scale_factor); + xlpopn(1); + return result; +} + + +sound_type snd_trigger(s1, closure) + sound_type s1; + LVAL closure; +{ + sound_type s1_copy; + s1_copy = sound_copy(s1); + return snd_make_trigger(s1_copy, closure); +} diff --git a/nyqsrc/trigger.h b/nyqsrc/trigger.h new file mode 100644 index 0000000..d300e92 --- /dev/null +++ b/nyqsrc/trigger.h @@ -0,0 +1,3 @@ +sound_type snd_make_trigger(); +sound_type snd_trigger(); + /* LISP: (SND-TRIGGER SOUND ANY) */ diff --git a/nyqsrc/yin.c b/nyqsrc/yin.c new file mode 100644 index 0000000..b034c4d --- /dev/null +++ b/nyqsrc/yin.c @@ -0,0 +1,579 @@ +#include "stdio.h" +#ifdef UNIX +#include "sys/file.h" +#endif +#ifndef mips +#include "stdlib.h" +#endif +#include "sndfmt.h" +#include "xlisp.h" +#include "sound.h" +#include "falloc.h" +#include "yin.h" + + +void yin_free(); + +/* for multiple channel results, one susp is shared by all sounds */ +/* the susp in turn must point back to all sound list tails */ + +typedef struct yin_susp_struct { + snd_susp_node susp; + long terminate_cnt; + boolean logically_stopped; + sound_type s; + long s_cnt; + sample_block_values_type s_ptr; + long blocksize; + long stepsize; + sample_type *block; + float *temp; + sample_type *fillptr; + sample_type *endptr; + snd_list_type chan[2]; /* array of back pointers */ + long cnt; /* how many sample frames to read */ + long m; + long middle; +} yin_susp_node, *yin_susp_type; + +/* DEBUG CODE: + * use this to print the sound created by yin + +sound_type ysnd[2]; + +void print_ysnds(char *label, yin_susp_type susp) +{ + int i; + printf("At %s:\n", label); + for (i = 0; i < 2; i++) { + snd_list_type snd_list; + if (!susp->chan[i]) continue; + snd_list = ysnd[i]->list; + printf(" ysnd[%d]:\n", i, label); + while (true) { + printf(" snd_list %p block %p\n", snd_list, snd_list->block); + if (snd_list == zero_snd_list) { + printf(" (zero_snd_list)\n"); + break; + } else if (!snd_list->block) { + printf(" susp %p (%s)\n", snd_list->u.susp, + snd_list->u.susp->name); + break; + } + snd_list = snd_list->u.next; + } + } + printf(" susp->chan[0] = %p, susp->chan[1] = %p\n", + susp->chan[0], susp->chan[1]); + +} + * END OF DEBUG CODE + */ + +// Uses cubic interpolation to return the value of x such +// that the function defined by f(0), f(1), f(2), and f(3) +// is maximized. +// +float CubicMaximize(float y0, float y1, float y2, float y3) +{ + // Find coefficients of cubic + + float a, b, c, d; + float da, db, dc; + float discriminant; + float x1, x2; + float dda, ddb; + + a = (float) (y0/-6.0 + y1/2.0 - y2/2.0 + y3/6.0); + b = (float) (y0 - 5.0*y1/2.0 + 2.0*y2 - y3/2.0); + c = (float) (-11.0*y0/6.0 + 3.0*y1 - 3.0*y2/2.0 + y3/3.0); + d = y0; + + // Take derivative + + da = 3*a; + db = 2*b; + dc = c; + + // Find zeroes of derivative using quadratic equation + + discriminant = db*db - 4*da*dc; + if (discriminant < 0.0) + return -1.0; // error + + x1 = (float) ((-db + sqrt(discriminant)) / (2 * da)); + x2 = (float) ((-db - sqrt(discriminant)) / (2 * da)); + + // The one which corresponds to a local _maximum_ in the + // cubic is the one we want - the one with a negative + // second derivative + + dda = 2*da; + ddb = db; + + if (dda*x1 + ddb < 0) + return x1; + else + return x2; +} + + +float parabolic_interp(float x1, float x2, float x3, float y1, float y2, + float y3, float *min) +{ + float a, b, c; + float pos; + + // y1=a*x1^2+b*x1+c + // y2=a*x2^2+b*x2+c + // y3=a*x3^2+b*x3+c + + // y1-y2=a*(x1^2-x2^2)+b*(x1-x2) + // y2-y3=a*(x2^2-x3^2)+b*(x2-x3) + + // (y1-y2)/(x1-x2)=a*(x1+x2)+b + // (y2-y3)/(x2-x3)=a*(x2+x3)+b + + a = ((y1 - y2) / (x1 - x2) - (y2 - y3) / (x2 - x3)) / (x1 - x3); + b = (y1 - y2) / (x1 - x2) - a * (x1 + x2); + c = y1 - a * x1 * x1 - b * x1; + + // dy/dx = 2a*x + b = 0 + + pos = (float) (-b / (a + a)); + *min = /* ax^2 + bx + c */ (a * pos + b) * pos + c; + return pos; +} + + +void yin_compute(yin_susp_type susp, float *pitch, float *harmonicity) + // samples is a buffer of samples + // n is the number of samples, equals twice longest period, must be even + // m is the shortest period in samples + // results is an array of size n/2 - m + 1, the number of different lags +{ + + float *samples = susp->block; + int middle = susp->middle; + int m = susp->m; + float threshold = 0.1F; + float *results = susp->temp; + + // work from the middle of the buffer: + int i, j; // loop counters + // how many different lags do we compute? + float left_energy = 0; + float right_energy = 0; + float left, right, non_periodic; + float auto_corr=0; + float cum_sum=0.0; + float period; + int min_i; + + // for each window, we keep the energy so we can compute the next one + // incrementally. First, we need to compute the energies for lag m-1: + for (i = 0; i < m - 1; i++) { + left = samples[middle - 1 - i]; + left_energy += left * left; + right = samples[middle + i]; + right_energy += right * right; + } + + for (i = m; i <= middle; i++) { + // i is the lag and the length of the window + // compute the energy for left and right + left = samples[middle - i]; + left_energy += left * left; + right = samples[middle - 1 + i]; + + right_energy += right * right; + // compute the autocorrelation + auto_corr = 0; + for (j = 0; j < i; j++) { + auto_corr += samples[middle - i + j] * samples[middle + j]; + } + non_periodic = (left_energy + right_energy - 2 * auto_corr);// / i; + results[i - m] = non_periodic; + + } + + // normalize by the cumulative sum + for (i = m; i <= middle; i++) { + cum_sum += results[i - m]; + results[i - m]=results[i - m] / (cum_sum / (i - m + 1)); + } + + min_i = m; // value of initial estimate + for (i = m; i <= middle; i++) { + if (results[i - m] < threshold) { + min_i=i; + break; + } else if (results[i - m] < results[min_i - m]) + min_i=i; + } + + // This step is not part of the published algorithm. Just because we + // found a point below the threshold does not mean we are at a local + // minimum. E.g. a sine input will go way below threshold, so the + // period estimate at the threshold crossing will be too low. In this + // step, we continue to scan forward until we reach a local minimum. + while (min_i < middle && results[min_i + 1 - m] < results[min_i - m]) { + min_i++; + } + + // use parabolic interpolation to improve estimate + if (i>m && isusp.sr * susp->stepsize) / period); +} + + +/* yin_fetch - compute F0 and harmonicity using YIN approach. */ +/* + * The pitch (F0) is determined by finding two periods whose + * inner product accounts for almost all of the energy. Let X and Y + * be adjacent vectors of length N in the sample stream. Then, + * if 2X*Y > threshold * (X*X + Y*Y) + * then the period is given by N + * In the algorithm, we compute different sizes until we find a + * peak above threshold. Then, we use cubic interpolation to get + * a precise value. If no peak above threshold is found, we return + * the first peak. The second channel returns the value 2X*Y/(X*X+Y*Y) + * which is refered to as the "harmonicity" -- the amount of energy + * accounted for by periodicity. + * + * Low sample rates are advised because of the high cost of computing + * inner products (fast autocorrelation is not used). + * + * The result is a 2-channel signal running at the requested rate. + * The first channel is the estimated pitch, and the second channel + * is the harmonicity. + * + * This code is adopted from multiread, currently the only other + * multichannel suspension in Nyquist. Comments from multiread include: + * The susp is shared by all channels. The susp has backpointers + * to the tail-most snd_list node of each channel, and it is by + * extending the list at these nodes that sounds are read in. + * To avoid a circularity, the reference counts on snd_list nodes + * do not include the backpointers from this susp. When a snd_list + * node refcount goes to zero, the yin susp's free routine + * is called. This must scan the backpointers to find the node that + * has a zero refcount (the free routine is called before the node + * is deallocated, so this is safe). The backpointer is then set + * to NULL. When all backpointers are NULL, the susp itself is + * deallocated, because it can only be referenced through the + * snd_list nodes to which there are backpointers. + */ +void yin_fetch(yin_susp_type susp, snd_list_type snd_list) +{ + int cnt = 0; /* how many samples computed */ + int togo; + int n; + int i; + sample_block_type f0; + sample_block_values_type f0_ptr = NULL; + sample_block_type harmonicity; + sample_block_values_type harmonicity_ptr = NULL; + + register sample_block_values_type s_ptr_reg; + register sample_type *fillptr_reg; + register sample_type *endptr_reg = susp->endptr; + + /* DEBUG: print_ysnds("top of yin_fetch", susp); */ + if (susp->chan[0]) { + falloc_sample_block(f0, "yin_fetch"); + f0_ptr = f0->samples; + /* Since susp->chan[i] exists, we want to append a block of samples. + * The block, out, has been allocated. Before we insert the block, + * we must figure out whether to insert a new snd_list_type node for + * the block. Recall that before SND_get_next is called, the last + * snd_list_type in the list will have a null block pointer, and the + * snd_list_type's susp field points to the suspension (in this case, + * susp). When SND_get_next (in sound.c) is called, it appends a new + * snd_list_type and points the previous one to internal_zero_block + * before calling this fetch routine. On the other hand, since + * SND_get_next is only going to be called on one of the channels, the + * other channels will not have had a snd_list_type appended. + * SND_get_next does not tell us directly which channel it wants (it + * doesn't know), but we can test by looking for a non-null block in the + * snd_list_type pointed to by our back-pointers in susp->chan[]. If + * the block is null, the channel was untouched by SND_get_next, and + * we should append a snd_list_type. If it is non-null, then it + * points to internal_zero_block (the block inserted by SND_get_next) + * and a new snd_list_type has already been appended. + */ + /* Before proceeding, it may be that garbage collection ran when we + * allocated out, so check again to see if susp->chan[j] is Null: + */ + if (!susp->chan[0]) { + ffree_sample_block(f0, "yin_fetch"); + f0 = NULL; /* make sure we don't free it again */ + f0_ptr = NULL; /* make sure we don't output f0 samples */ + } else if (!susp->chan[0]->block) { + snd_list_type snd_list = snd_list_create((snd_susp_type) susp); + /* printf("created snd_list %x for chan 0 with susp %x\n", + snd_list, snd_list->u.susp); */ + /* Now we have a snd_list to append to the channel, but a very + * interesting thing can happen here. snd_list_create, which + * we just called, MAY have invoked the garbage collector, and + * the GC MAY have freed all references to this channel, in which + * case yin_free(susp) will have been called, and susp->chan[0] + * will now be NULL! + */ + if (!susp->chan[0]) { + ffree_snd_list(snd_list, "yin_fetch"); + } else { + susp->chan[0]->u.next = snd_list; + } + } + /* see the note above: we don't know if susp->chan still exists */ + /* Note: We DO know that susp still exists because even if we lost + * some channels in a GC, someone is still calling SND_get_next on + * some channel. I suppose that there might be some very pathological + * code that could free a global reference to a sound that is in the + * midst of being computed, perhaps by doing something bizarre in the + * closure that snd_seq activates at the logical stop time of its first + * sound, but I haven't thought that one through. + */ + if (susp->chan[0]) { + susp->chan[0]->block = f0; + /* check some assertions */ + if (susp->chan[0]->u.next->u.susp != (snd_susp_type) susp) { + nyquist_printf("didn't find susp at end of list for chan 0\n"); + } + } else if (f0) { /* we allocated f0, but don't need it anymore due to GC */ + ffree_sample_block(f0, "yin_fetch"); + f0_ptr = NULL; + } + } + + /* Now, repeat for channel 1 (comments omitted) */ + if (susp->chan[1]) { + falloc_sample_block(harmonicity, "yin_fetch"); + harmonicity_ptr = harmonicity->samples; + if (!susp->chan[1]) { + ffree_sample_block(harmonicity, "yin_fetch"); + harmonicity = NULL; /* make sure we don't free it again */ + harmonicity_ptr = NULL; + } else if (!susp->chan[1]->block) { + snd_list_type snd_list = snd_list_create((snd_susp_type) susp); + /* printf("created snd_list %x for chan 1 with susp %x\n", + snd_list, snd_list->u.susp); */ + if (!susp->chan[1]) { + ffree_snd_list(snd_list, "yin_fetch"); + } else { + susp->chan[1]->u.next = snd_list; + } + } + if (susp->chan[1]) { + susp->chan[1]->block = harmonicity; + if (susp->chan[1]->u.next->u.susp != (snd_susp_type) susp) { + nyquist_printf("didn't find susp at end of list for chan 1\n"); + } + } else if (harmonicity) { /* we allocated harmonicity, but don't need it anymore due to GC */ + ffree_sample_block(harmonicity, "yin_fetch"); + harmonicity_ptr = NULL; + } + } + + /* DEBUG: print_ysnds("yin_fetch before outer loop", susp); */ + while (cnt < max_sample_block_len) { /* outer loop */ + /* first, compute how many samples to generate in inner loop: */ + /* don't overflow the output sample block */ + togo = (max_sample_block_len - cnt) * susp->stepsize; + + /* don't run past the s input sample block */ + susp_check_term_log_samples(s, s_ptr, s_cnt); + togo = min(togo, susp->s_cnt); + + /* don't run past terminate time */ + if (susp->terminate_cnt != UNKNOWN && + susp->terminate_cnt <= susp->susp.current + cnt + togo/susp->stepsize) { + togo = (susp->terminate_cnt - (susp->susp.current + cnt)) * susp->stepsize; + if (togo == 0) break; + } + + /* don't run past logical stop time */ + if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { + int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); + /* break if to_stop = 0 (we're at the logical stop) + * AND cnt > 0 (we're not at the beginning of the output block) + */ + if (to_stop < togo/susp->stepsize) { + if (to_stop == 0) { + if (cnt) { + togo = 0; + break; + } else /* keep togo as is: since cnt == 0, we can set + * the logical stop flag on this output block + */ + susp->logically_stopped = true; + } else /* limit togo so we can start a new block a the LST */ + togo = to_stop * susp->stepsize; + } + } + n = togo; + s_ptr_reg = susp->s_ptr; + fillptr_reg = susp->fillptr; + if (n) do { /* the inner sample computation loop */ + *fillptr_reg++ = *s_ptr_reg++; + if (fillptr_reg >= endptr_reg) { + float f0; + float harmonicity; + yin_compute(susp, &f0, &harmonicity); + if (f0_ptr) *f0_ptr++ = f0; + if (harmonicity_ptr) *harmonicity_ptr++ = harmonicity; + cnt++; + // shift block by stepsize + memmove(susp->block, susp->block + susp->stepsize, + sizeof(sample_type) * (susp->blocksize - susp->stepsize)); + fillptr_reg -= susp->stepsize; + } + } while (--n); /* inner loop */ + + /* using s_ptr_reg is a bad idea on RS/6000: */ + susp->s_ptr += togo; + susp->fillptr = fillptr_reg; + susp_took(s_cnt, togo); + } /* outer loop */ + + /* test for termination */ + if (togo == 0 && cnt == 0) { + /* single channels code: snd_list_terminate(snd_list); */ + for (i = 0; i < 2; i++) { + if (susp->chan[i]) { + snd_list_type the_snd_list = susp->chan[i]; + susp->chan[i] = the_snd_list->u.next; + snd_list_terminate(the_snd_list); + } + } + } else { + /* single channel code: + snd_list->block_len = cnt; + */ + susp->susp.current += cnt; + for (i = 0; i < 2; i++) { + if (susp->chan[i]) { + susp->chan[i]->block_len = cnt; + susp->chan[i] = susp->chan[i]->u.next; + } + } + } + + /* test for logical stop */ + if (susp->logically_stopped) { + /* single channel code: snd_list->logically_stopped = true; */ + if (susp->chan[0]) susp->chan[0]->logically_stopped = true; + if (susp->chan[1]) susp->chan[1]->logically_stopped = true; + } else if (susp->susp.log_stop_cnt == susp->susp.current) { + susp->logically_stopped = true; + } +} /* yin_fetch */ + + +void yin_mark(yin_susp_type susp) +{ + sound_xlmark(susp->s); +} + + +void yin_free(yin_susp_type susp) +{ + int j; + boolean active = false; +/* stdputstr("yin_free: "); */ + + for (j = 0; j < 2; j++) { + if (susp->chan[j]) { + if (susp->chan[j]->refcnt) active = true; + else { + susp->chan[j] = NULL; + /* nyquist_printf("deactivating channel %d\n", j); */ + } + } + } + if (!active) { +/* stdputstr("all channels freed, freeing susp now\n"); */ + ffree_generic(susp, sizeof(yin_susp_node), "yin_free"); + sound_unref(susp->s); + free(susp->block); + free(susp->temp); + } +} + + +void yin_print_tree(yin_susp_type susp, int n) +{ + indent(n); + stdputstr("s:"); + sound_print_tree_1(susp->s, n); +} + + +LVAL snd_make_yin(sound_type s, double low_step, double high_step, long stepsize) +{ + LVAL result; + int j; + register yin_susp_type susp; + rate_type sr = s->sr; + time_type t0 = s->t0; + + falloc_generic(susp, yin_susp_node, "snd_make_yin"); + susp->susp.fetch = yin_fetch; + susp->terminate_cnt = UNKNOWN; + + /* initialize susp state */ + susp->susp.free = yin_free; + susp->susp.sr = sr / stepsize; + susp->susp.t0 = t0; + susp->susp.mark = yin_mark; + susp->susp.print_tree = yin_print_tree; + susp->susp.name = "yin"; + susp->logically_stopped = false; + susp->susp.log_stop_cnt = logical_stop_cnt_cvt(s); + susp->susp.current = 0; + susp->s = s; + susp->s_cnt = 0; + susp->m = (long) (sr / step_to_hz(high_step)); + if (susp->m < 2) susp->m = 2; + /* add 1 to make sure we round up */ + susp->middle = (long) (sr / step_to_hz(low_step)) + 1; + susp->blocksize = susp->middle * 2; + susp->stepsize = stepsize; + /* blocksize must be at least step size to implement stepping */ + if (susp->stepsize > susp->blocksize) susp->blocksize = susp->stepsize; + susp->block = (sample_type *) malloc(susp->blocksize * sizeof(sample_type)); + susp->temp = (float *) malloc((susp->middle - susp->m + 1) * sizeof(float)); + susp->fillptr = susp->block; + susp->endptr = susp->block + susp->blocksize; + + xlsave1(result); + + result = newvector(2); /* create array for F0 and harmonicity */ + /* create sounds to return */ + for (j = 0; j < 2; j++) { + sound_type snd = sound_create((snd_susp_type)susp, + susp->susp.t0, susp->susp.sr, 1.0); + LVAL snd_lval = cvsound(snd); +/* nyquist_printf("yin_create: sound %d is %x, LVAL %x\n", j, snd, snd_lval); */ + setelement(result, j, snd_lval); + susp->chan[j] = snd->list; + /* DEBUG: ysnd[j] = snd; */ + } + xlpop(); + return result; +} + + +LVAL snd_yin(sound_type s, double low_step, double high_step, long stepsize) +{ + sound_type s_copy = sound_copy(s); + return snd_make_yin(s_copy, low_step, high_step, stepsize); +} diff --git a/nyqsrc/yin.h b/nyqsrc/yin.h new file mode 100644 index 0000000..656aa81 --- /dev/null +++ b/nyqsrc/yin.h @@ -0,0 +1,6 @@ +/* yin.h -- Nyquist code for F0 estimation using YIN approach */ + + +LVAL snd_yin(sound_type s, double low_step, double high_step, long stepsize); +/* LISP: (SND-YIN SOUND ANYNUM ANYNUM FIXNUM) */ + diff --git a/nyqstk/globals.h b/nyqstk/globals.h new file mode 100644 index 0000000..9c64170 --- /dev/null +++ b/nyqstk/globals.h @@ -0,0 +1,8 @@ +#ifndef _GLOBALS_H +#define _GLOBALS_H + +typedef double MY_FLOAT; + +#endif + + diff --git a/nyqstk/include/ADSR.h b/nyqstk/include/ADSR.h new file mode 100644 index 0000000..521514d --- /dev/null +++ b/nyqstk/include/ADSR.h @@ -0,0 +1,90 @@ +/***************************************************/ +/*! \class ADSR + \brief STK ADSR envelope class. + + This Envelope subclass implements a + traditional ADSR (Attack, Decay, + Sustain, Release) envelope. It + responds to simple keyOn and keyOff + messages, keeping track of its state. + The \e state = ADSR::DONE after the + envelope value reaches 0.0 in the + ADSR::RELEASE state. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_ADSR_H +#define STK_ADSR_H + +#include "Envelope.h" + +namespace Nyq +{ + +class ADSR : public Envelope +{ + public: + + //! Envelope states. + enum { ATTACK, DECAY, SUSTAIN, RELEASE, DONE }; + + //! Default constructor. + ADSR(void); + + //! Class destructor. + ~ADSR(void); + + //! Set target = 1, state = \e ADSR::ATTACK. + void keyOn(void); + + //! Set target = 0, state = \e ADSR::RELEASE. + void keyOff(void); + + //! Set the attack rate. + void setAttackRate(StkFloat rate); + + //! Set the decay rate. + void setDecayRate(StkFloat rate); + + //! Set the sustain level. + void setSustainLevel(StkFloat level); + + //! Set the release rate. + void setReleaseRate(StkFloat rate); + + //! Set the attack rate based on a time duration. + void setAttackTime(StkFloat time); + + //! Set the decay rate based on a time duration. + void setDecayTime(StkFloat time); + + //! Set the release rate based on a time duration. + void setReleaseTime(StkFloat time); + + //! Set sustain level and attack, decay, and release time durations. + void setAllTimes(StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime); + + //! Set the target value. + void setTarget(StkFloat target); + + //! Return the current envelope \e state (ATTACK, DECAY, SUSTAIN, RELEASE, DONE). + int getState(void) const; + + //! Set to state = ADSR::SUSTAIN with current and target values of \e aValue. + void setValue(StkFloat value); + + protected: + + StkFloat computeSample( void ); + + StkFloat attackRate_; + StkFloat decayRate_; + StkFloat sustainLevel_; + StkFloat releaseRate_; +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/BandedWG.h b/nyqstk/include/BandedWG.h new file mode 100644 index 0000000..9323a3e --- /dev/null +++ b/nyqstk/include/BandedWG.h @@ -0,0 +1,121 @@ +/***************************************************/ +/*! \class BandedWG + \brief Banded waveguide modeling class. + + This class uses banded waveguide techniques to + model a variety of sounds, including bowed + bars, glasses, and bowls. For more + information, see Essl, G. and Cook, P. "Banded + Waveguides: Towards Physical Modelling of Bar + Percussion Instruments", Proceedings of the + 1999 International Computer Music Conference. + + Control Change Numbers: + - Bow Pressure = 2 + - Bow Motion = 4 + - Strike Position = 8 (not implemented) + - Vibrato Frequency = 11 + - Gain = 1 + - Bow Velocity = 128 + - Set Striking = 64 + - Instrument Presets = 16 + - Uniform Bar = 0 + - Tuned Bar = 1 + - Glass Harmonica = 2 + - Tibetan Bowl = 3 + + by Georg Essl, 1999 - 2004. + Modified for Stk 4.0 by Gary Scavone. +*/ +/***************************************************/ + +#ifndef STK_BANDEDWG_H +#define STK_BANDEDWG_H + +namespace Nyq +{ + +const int MAX_BANDED_MODES = 20; + +} // namespace Nyq + +#include "Instrmnt.h" +#include "DelayL.h" +#include "BowTable.h" +#include "ADSR.h" +#include "BiQuad.h" + +namespace Nyq +{ + +class BandedWG : public Instrmnt +{ + public: + //! Class constructor. + BandedWG(); + + //! Class destructor. + ~BandedWG(); + + //! Reset and clear all internal state. + void clear(); + + //! Set strike position (0.0 - 1.0). + void setStrikePosition(StkFloat position); + + //! Select a preset. + void setPreset(int preset); + + //! Set instrument parameters for a particular frequency. + void setFrequency(StkFloat frequency); + + //! Apply bow velocity/pressure to instrument with given amplitude and rate of increase. + void startBowing(StkFloat amplitude, StkFloat rate); + + //! Decrease bow velocity/breath pressure with given rate of decrease. + void stopBowing(StkFloat rate); + + //! Pluck the instrument with given amplitude. + void pluck(StkFloat amp); + + //! Start a note with the given frequency and amplitude. + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Stop a note with the given amplitude (speed of decay). + void noteOff(StkFloat amplitude); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + void controlChange(int number, StkFloat value); + + protected: + + StkFloat computeSample( void ); + + bool doPluck_; + bool trackVelocity_; + int nModes_; + int presetModes_; + BowTable bowTable_; + ADSR adsr_; + BiQuad bandpass_[MAX_BANDED_MODES]; + DelayL delay_[MAX_BANDED_MODES]; + StkFloat maxVelocity_; + StkFloat modes_[MAX_BANDED_MODES]; + StkFloat frequency_; + StkFloat baseGain_; + StkFloat gains_[MAX_BANDED_MODES]; + StkFloat basegains_[MAX_BANDED_MODES]; + StkFloat excitation_[MAX_BANDED_MODES]; + StkFloat integrationConstant_; + StkFloat velocityInput_; + StkFloat bowVelocity_; + StkFloat bowTarget_; + StkFloat bowPosition_; + StkFloat strikeAmp_; + int strikePosition_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/BiQuad.h b/nyqstk/include/BiQuad.h new file mode 100644 index 0000000..d4e6cc8 --- /dev/null +++ b/nyqstk/include/BiQuad.h @@ -0,0 +1,117 @@ +/***************************************************/ +/*! \class BiQuad + \brief STK biquad (two-pole, two-zero) filter class. + + This protected Filter subclass implements a + two-pole, two-zero digital filter. A method + is provided for creating a resonance in the + frequency response while maintaining a constant + filter gain. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_BIQUAD_H +#define STK_BIQUAD_H + +#include "Filter.h" + +namespace Nyq +{ + +class BiQuad : protected Filter +{ +public: + + //! Default constructor creates a second-order pass-through filter. + BiQuad(); + + //! Class destructor. + virtual ~BiQuad(); + + //! Clears all internal states of the filter. + void clear(void); + + //! Set the b[0] coefficient value. + void setB0(StkFloat b0); + + //! Set the b[1] coefficient value. + void setB1(StkFloat b1); + + //! Set the b[2] coefficient value. + void setB2(StkFloat b2); + + //! Set the a[1] coefficient value. + void setA1(StkFloat a1); + + //! Set the a[2] coefficient value. + void setA2(StkFloat a2); + + //! Sets the filter coefficients for a resonance at \e frequency (in Hz). + /*! + This method determines the filter coefficients corresponding to + two complex-conjugate poles with the given \e frequency (in Hz) + and \e radius from the z-plane origin. If \e normalize is true, + the filter zeros are placed at z = 1, z = -1, and the coefficients + are then normalized to produce a constant unity peak gain + (independent of the filter \e gain parameter). The resulting + filter frequency response has a resonance at the given \e + frequency. The closer the poles are to the unit-circle (\e radius + close to one), the narrower the resulting resonance width. + */ + void setResonance(StkFloat frequency, StkFloat radius, bool normalize = false); + + //! Set the filter coefficients for a notch at \e frequency (in Hz). + /*! + This method determines the filter coefficients corresponding to + two complex-conjugate zeros with the given \e frequency (in Hz) + and \e radius from the z-plane origin. No filter normalization + is attempted. + */ + void setNotch(StkFloat frequency, StkFloat radius); + + //! Sets the filter zeroes for equal resonance gain. + /*! + When using the filter as a resonator, zeroes places at z = 1, z + = -1 will result in a constant gain at resonance of 1 / (1 - R), + where R is the pole radius setting. + + */ + void setEqualGainZeroes(); + + //! Set the filter gain. + /*! + The gain is applied at the filter input and does not affect the + coefficient values. The default gain value is 1.0. + */ + void setGain(StkFloat gain); + + //! Return the current filter gain. + StkFloat getGain(void) const; + + //! Return the last computed output value. + StkFloat lastOut(void) const; + + //! Input one sample to the filter and return one output. + virtual StkFloat tick(StkFloat sample); + + //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + + protected: + + // This function must be implemented in all subclasses. It is used + // to get around a C++ problem with overloaded virtual functions. + virtual StkFloat computeSample( StkFloat input ); +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/BowTable.h b/nyqstk/include/BowTable.h new file mode 100644 index 0000000..6604176 --- /dev/null +++ b/nyqstk/include/BowTable.h @@ -0,0 +1,56 @@ +/***************************************************/ +/*! \class BowTable + \brief STK bowed string table class. + + This class implements a simple bowed string + non-linear function, as described by Smith (1986). + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_BOWTABL_H +#define STK_BOWTABL_H + +#include "Function.h" + +namespace Nyq +{ + +class BowTable : public Function +{ +public: + //! Default constructor. + BowTable(); + + //! Class destructor. + ~BowTable(); + + //! Set the table offset value. + /*! + The table offset is a bias which controls the + symmetry of the friction. If you want the + friction to vary with direction, use a non-zero + value for the offset. The default value is zero. + */ + void setOffset(StkFloat offset); + + //! Set the table slope value. + /*! + The table slope controls the width of the friction + pulse, which is related to bow force. + */ + void setSlope(StkFloat slope); + +protected: + + StkFloat computeSample( StkFloat input ); + + StkFloat offset_; + StkFloat slope_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Bowed.h b/nyqstk/include/Bowed.h new file mode 100644 index 0000000..a4551f7 --- /dev/null +++ b/nyqstk/include/Bowed.h @@ -0,0 +1,91 @@ +/***************************************************/ +/*! \class Bowed + \brief STK bowed string instrument class. + + This class implements a bowed string model, a + la Smith (1986), after McIntyre, Schumacher, + Woodhouse (1983). + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + + Control Change Numbers: + - Bow Pressure = 2 + - Bow Position = 4 + - Vibrato Frequency = 11 + - Vibrato Gain = 1 + - Volume = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_BOWED_H +#define STK_BOWED_H + +#include "Instrmnt.h" +#include "DelayL.h" +#include "BowTable.h" +#include "OnePole.h" +#include "BiQuad.h" +#include "SineWave.h" +#include "ADSR.h" + +namespace Nyq +{ + +class Bowed : public Instrmnt +{ + public: + //! Class constructor, taking the lowest desired playing frequency. + Bowed(StkFloat lowestFrequency); + + //! Class destructor. + ~Bowed(); + + //! Reset and clear all internal state. + void clear(); + + //! Set instrument parameters for a particular frequency. + void setFrequency(StkFloat frequency); + + //! Set vibrato gain. + void setVibrato(StkFloat gain); + + //! Apply breath pressure to instrument with given amplitude and rate of increase. + void startBowing(StkFloat amplitude, StkFloat rate); + + //! Decrease breath pressure with given rate of decrease. + void stopBowing(StkFloat rate); + + //! Start a note with the given frequency and amplitude. + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Stop a note with the given amplitude (speed of decay). + void noteOff(StkFloat amplitude); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + void controlChange(int number, StkFloat value); + + protected: + + StkFloat computeSample( void ); + + DelayL neckDelay_; + DelayL bridgeDelay_; + BowTable bowTable_; + OnePole stringFilter_; + BiQuad bodyFilter_; + SineWave vibrato_; + ADSR adsr_; + StkFloat maxVelocity_; + StkFloat baseDelay_; + StkFloat vibratoGain_; + StkFloat betaRatio_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Chorus.h b/nyqstk/include/Chorus.h new file mode 100644 index 0000000..5da10e1 --- /dev/null +++ b/nyqstk/include/Chorus.h @@ -0,0 +1,56 @@ +/***************************************************/ +/*! \class Chorus + \brief STK chorus effect class. + + This class implements a chorus effect. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_CHORUS_H +#define STK_CHORUS_H + +#include "Effect.h" +#include "DelayL.h" +#include "SineWave.h" + +namespace Nyq +{ + +class Chorus : public Effect +{ + public: + //! Class constructor, taking the median desired delay length. + /*! + An StkError can be thrown if the rawwave path is incorrect. + */ + Chorus( StkFloat baseDelay = 6000 ); + + //! Class destructor. + ~Chorus(); + + //! Reset and clear all internal state. + void clear(); + + //! Set modulation depth. + void setModDepth(StkFloat depth); + + //! Set modulation frequency. + void setModFrequency(StkFloat frequency); + + protected: + + StkFloat computeSample( StkFloat input ); + + DelayL delayLine_[2]; + SineWave mods_[2]; + StkFloat baseLength_; + StkFloat modDepth_; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/Clarinet.h b/nyqstk/include/Clarinet.h new file mode 100644 index 0000000..fb7d43d --- /dev/null +++ b/nyqstk/include/Clarinet.h @@ -0,0 +1,91 @@ +/***************************************************/ +/*! \class Clarinet + \brief STK clarinet physical model class. + + This class implements a simple clarinet + physical model, as discussed by Smith (1986), + McIntyre, Schumacher, Woodhouse (1983), and + others. + + This is a digital waveguide model, making its + use possibly subject to patents held by Stanford + University, Yamaha, and others. + + Control Change Numbers: + - Reed Stiffness = 2 + - Noise Gain = 4 + - Vibrato Frequency = 11 + - Vibrato Gain = 1 + - Breath Pressure = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_CLARINET_H +#define STK_CLARINET_H + +#include "Instrmnt.h" +#include "DelayL.h" +#include "ReedTable.h" +#include "OneZero.h" +#include "Envelope.h" +#include "Noise.h" +#include "SineWave.h" + +namespace Nyq +{ + +class Clarinet : public Instrmnt +{ + public: + //! Class constructor, taking the lowest desired playing frequency. + /*! + An StkError will be thrown if the rawwave path is incorrectly set. + */ + Clarinet(StkFloat lowestFrequency); + + //! Class destructor. + ~Clarinet(); + + //! Reset and clear all internal state. + void clear(); + + //! Set instrument parameters for a particular frequency. + void setFrequency(StkFloat frequency); + + //! Apply breath pressure to instrument with given amplitude and rate of increase. + void startBlowing(StkFloat amplitude, StkFloat rate); + + //! Decrease breath pressure with given rate of decrease. + void stopBlowing(StkFloat rate); + + //! Start a note with the given frequency and amplitude. + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Stop a note with the given amplitude (speed of decay). + void noteOff(StkFloat amplitude); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + void controlChange(int number, StkFloat value); + + protected: + + StkFloat computeSample( void ); + + DelayL delayLine_; + ReedTable reedTable_; + OneZero filter_; + Envelope envelope_; + Noise noise_; + SineWave vibrato_; + long length_; + StkFloat outputGain_; + StkFloat noiseGain_; + StkFloat vibratoGain_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Delay.h b/nyqstk/include/Delay.h new file mode 100644 index 0000000..413944c --- /dev/null +++ b/nyqstk/include/Delay.h @@ -0,0 +1,115 @@ +/***************************************************/ +/*! \class Delay + \brief STK non-interpolating delay line class. + + This protected Filter subclass implements + a non-interpolating digital delay-line. + A fixed maximum length of 4095 and a delay + of zero is set using the default constructor. + Alternatively, the delay and maximum length + can be set during instantiation with an + overloaded constructor. + + A non-interpolating delay line is typically + used in fixed delay-length applications, such + as for reverberation. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_DELAY_H +#define STK_DELAY_H + +#include "Filter.h" + +namespace Nyq +{ + +class Delay : protected Filter +{ +public: + + //! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay. + Delay(); + + //! Overloaded constructor which specifies the current and maximum delay-line lengths. + /*! + An StkError will be thrown if the delay parameter is less than + zero, the maximum delay parameter is less than one, or the delay + parameter is greater than the maxDelay value. + */ + Delay(unsigned long delay, unsigned long maxDelay); + + //! Class destructor. + virtual ~Delay(); + + //! Clears the internal state of the delay line. + void clear(); + + //! Set the maximum delay-line length. + /*! + This method should generally only be used during initial setup + of the delay line. If it is used between calls to the tick() + function, without a call to clear(), a signal discontinuity will + likely occur. If the current maximum length is greater than the + new length, no change will be made. + */ + void setMaximumDelay(unsigned long delay); + + //! Set the delay-line length. + /*! + The valid range for \e theDelay is from 0 to the maximum delay-line length. + */ + void setDelay(unsigned long delay); + + //! Return the current delay-line length. + unsigned long getDelay(void) const; + + //! Calculate and return the signal energy in the delay-line. + StkFloat energy(void) const; + + //! Return the value at \e tapDelay samples from the delay-line input. + /*! + The tap point is determined modulo the delay-line length and is + relative to the last input value (i.e., a tapDelay of zero returns + the last input value). + */ + StkFloat contentsAt(unsigned long tapDelay); + + //! Return the last computed output value. + StkFloat lastOut(void) const; + + //! Return the value which will be output by the next call to tick(). + /*! + This method is valid only for delay settings greater than zero! + */ + virtual StkFloat nextOut(void); + + //! Input one sample to the filter and return one output. + virtual StkFloat tick(StkFloat sample); + + //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + +protected: + + // This function must be implemented in all subclasses. It is used + // to get around a C++ problem with overloaded virtual functions. + virtual StkFloat computeSample( StkFloat input ); + + unsigned long inPoint_; + unsigned long outPoint_; + StkFloat delay_; +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/DelayA.h b/nyqstk/include/DelayA.h new file mode 100644 index 0000000..4f17527 --- /dev/null +++ b/nyqstk/include/DelayA.h @@ -0,0 +1,79 @@ +/***************************************************/ +/*! \class DelayA + \brief STK allpass interpolating delay line class. + + This Delay subclass implements a fractional-length digital + delay-line using a first-order allpass filter. A fixed maximum + length of 4095 and a delay of 0.5 is set using the default + constructor. Alternatively, the delay and maximum length can be + set during instantiation with an overloaded constructor. + + An allpass filter has unity magnitude gain but variable phase + delay properties, making it useful in achieving fractional delays + without affecting a signal's frequency magnitude response. In + order to achieve a maximally flat phase delay response, the + minimum delay possible in this implementation is limited to a + value of 0.5. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_DELAYA_H +#define STK_DELAYA_H + +#include "Delay.h" + +namespace Nyq +{ + +class DelayA : public Delay +{ +public: + + //! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay. + DelayA(); + + //! Overloaded constructor which specifies the current and maximum delay-line lengths. + /*! + An StkError will be thrown if the delay parameter is less than + zero, the maximum delay parameter is less than one, or the delay + parameter is greater than the maxDelay value. + */ + DelayA(StkFloat delay, unsigned long maxDelay); + + //! Class destructor. + ~DelayA(); + + //! Clears the internal state of the delay line. + void clear(); + + //! Set the delay-line length + /*! + The valid range for \e theDelay is from 0.5 to the maximum delay-line length. + */ + void setDelay(StkFloat delay); + + //! Return the current delay-line length. + StkFloat getDelay(void) const; + + //! Return the value which will be output by the next call to tick(). + /*! + This method is valid only for delay settings greater than zero! + */ + StkFloat nextOut(void); + +protected: + + StkFloat computeSample( StkFloat input ); + + StkFloat alpha_; + StkFloat coeff_; + StkFloat apInput_; + StkFloat nextOutput_; + bool doNextOut_; +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/DelayL.h b/nyqstk/include/DelayL.h new file mode 100644 index 0000000..fa97581 --- /dev/null +++ b/nyqstk/include/DelayL.h @@ -0,0 +1,78 @@ +/***************************************************/ +/*! \class DelayL + \brief STK linear interpolating delay line class. + + This Delay subclass implements a fractional- + length digital delay-line using first-order + linear interpolation. A fixed maximum length + of 4095 and a delay of zero is set using the + default constructor. Alternatively, the + delay and maximum length can be set during + instantiation with an overloaded constructor. + + Linear interpolation is an efficient technique + for achieving fractional delay lengths, though + it does introduce high-frequency signal + attenuation to varying degrees depending on the + fractional delay setting. The use of higher + order Lagrange interpolators can typically + improve (minimize) this attenuation characteristic. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_DELAYL_H +#define STK_DELAYL_H + +#include "Delay.h" + +namespace Nyq +{ + +class DelayL : public Delay +{ +public: + + //! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay. + DelayL(); + + //! Overloaded constructor which specifies the current and maximum delay-line lengths. + /*! + An StkError will be thrown if the delay parameter is less than + zero, the maximum delay parameter is less than one, or the delay + parameter is greater than the maxDelay value. + */ + DelayL(StkFloat delay, unsigned long maxDelay); + + //! Class destructor. + ~DelayL(); + + //! Set the delay-line length. + /*! + The valid range for \e theDelay is from 0 to the maximum delay-line length. + */ + void setDelay(StkFloat delay); + + //! Return the current delay-line length. + StkFloat getDelay(void) const; + + //! Return the value which will be output by the next call to tick(). + /*! + This method is valid only for delay settings greater than zero! + */ + StkFloat nextOut(void); + + protected: + + StkFloat computeSample( StkFloat input ); + + StkFloat alpha_; + StkFloat omAlpha_; + StkFloat nextOutput_; + bool doNextOut_; +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Effect.h b/nyqstk/include/Effect.h new file mode 100644 index 0000000..812e50a --- /dev/null +++ b/nyqstk/include/Effect.h @@ -0,0 +1,74 @@ +/***************************************************/ +/*! \class Effect + \brief STK abstract effects parent class. + + This class provides common functionality for + STK effects subclasses. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Stk.h" + +#ifndef STK_EFFECT_H +#define STK_EFFECT_H + +namespace Nyq +{ + +class Effect : public Stk +{ + public: + //! Class constructor. + Effect(); + + //! Class destructor. + virtual ~Effect(); + + //! Reset and clear all internal state. + virtual void clear() = 0; + + //! Set the mixture of input and "effected" levels in the output (0.0 = input only, 1.0 = reverb only). + void setEffectMix(StkFloat mix); + + //! Return the last output value. + StkFloat lastOut() const; + + //! Return the last left output value. + StkFloat lastOutLeft() const; + + //! Return the last right output value. + StkFloat lastOutRight() const; + + //! Take one sample input and compute one sample of output. + StkFloat tick( StkFloat input ); + + //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + + protected: + + // This abstract function must be implemented in all subclasses. + // It is used to get around a C++ problem with overloaded virtual + // functions. + virtual StkFloat computeSample( StkFloat input ) = 0; + + // Returns true if argument value is prime. + bool isPrime( int number ); + + StkFloat lastOutput_[2]; + StkFloat effectMix_; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/Envelope.h b/nyqstk/include/Envelope.h new file mode 100644 index 0000000..a005768 --- /dev/null +++ b/nyqstk/include/Envelope.h @@ -0,0 +1,73 @@ +/***************************************************/ +/*! \class Envelope + \brief STK envelope base class. + + This class implements a simple envelope + generator which is capable of ramping to + a target value by a specified \e rate. + It also responds to simple \e keyOn and + \e keyOff messages, ramping to 1.0 on + keyOn and to 0.0 on keyOff. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_ENVELOPE_H +#define STK_ENVELOPE_H + +#include "Generator.h" + +namespace Nyq +{ + +class Envelope : public Generator +{ + public: + + //! Default constructor. + Envelope(void); + + //! Copy constructor. + Envelope( const Envelope& e ); + + //! Class destructor. + virtual ~Envelope(void); + + //! Assignment operator. + Envelope& operator= ( const Envelope& e ); + + //! Set target = 1. + virtual void keyOn(void); + + //! Set target = 0. + virtual void keyOff(void); + + //! Set the \e rate. + void setRate(StkFloat rate); + + //! Set the \e rate based on a time duration. + void setTime(StkFloat time); + + //! Set the target value. + virtual void setTarget(StkFloat target); + + //! Set current and target values to \e aValue. + virtual void setValue(StkFloat value); + + //! Return the current envelope \e state (0 = at target, 1 otherwise). + virtual int getState(void) const; + + protected: + + virtual StkFloat computeSample( void ); + + StkFloat value_; + StkFloat target_; + StkFloat rate_; + int state_; +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/FileRead.h b/nyqstk/include/FileRead.h new file mode 100644 index 0000000..6ecc7ae --- /dev/null +++ b/nyqstk/include/FileRead.h @@ -0,0 +1,129 @@ +/***************************************************/ +/*! \class FileRead + \brief STK audio file input class. + + This class provides input support for various + audio file formats. Multi-channel (>2) + soundfiles are supported. The file data is + returned via an external StkFrames object + passed to the read() function. This class + does not store its own copy of the file data, + rather the data is read directly from disk. + + FileRead currently supports uncompressed WAV, + AIFF/AIFC, SND (AU), MAT-file (Matlab), and + STK RAW file formats. Signed integer (8-, + 16-, and 32-bit) and floating-point (32- and + 64-bit) data types are supported. Compressed + data types are not supported. + + STK RAW files have no header and are assumed + to contain a monophonic stream of 16-bit + signed integers in big-endian byte order at a + sample rate of 22050 Hz. MAT-file data should + be saved in an array with each data channel + filling a matrix row. The sample rate for + MAT-files is assumed to be 44100 Hz. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_FILEREAD_H +#define STK_FILEREAD_H + +#include "Stk.h" + +namespace Nyq +{ + +class FileRead : public Stk +{ +public: + //! Default constructor. + FileRead(); + + //! Overloaded constructor that opens a file during instantiation. + /*! + An StkError will be thrown if the file is not found or its + format is unknown or unsupported. + */ + FileRead( std::string fileName, bool typeRaw = false ); + + //! Class destructor. + ~FileRead(); + + //! Open the specified file and determine its formatting. + /*! + An StkError will be thrown if the file is not found or its + format is unknown or unsupported. An optional parameter is + provided to specify whether the input file is of type STK RAW + (default = false). + */ + void open( std::string fileName, bool typeRaw = false ); + + //! If a file is open, close it. + void close( void ); + + //! Returns \e true if a file is currently open. + bool isOpen( void ); + + //! Return the file size in sample frames. + unsigned long fileSize( void ) const { return fileSize_; }; + + //! Return the number of audio channels in the file. + unsigned int channels( void ) const { return channels_; }; + + //! Return the file sample rate in Hz. + /*! + WAV, SND, and AIF formatted files specify a sample rate in + their headers. By definition, STK RAW files have a sample rate of + 22050 Hz. MAT-files are assumed to have a rate of 44100 Hz. + */ + StkFloat fileRate( void ) const { return fileRate_; }; + + //! Read sample frames from the file into an StkFrames object. + /*! + The number of sample frames to read will be determined from the + number of frames of the StkFrames argument. If this size is + larger than the available data in the file (given the file size + and starting frame index), the extra frames will be unaffected + (the StkFrames object will not be resized). Optional parameters + are provided to specify the starting sample frame within the file + (default = 0) and whether to normalize the data with respect to + fixed-point limits (default = true). An StkError will be thrown + if a file error occurs or if the number of channels in the + StkFrames argument is not equal to that in the file. + */ + void read( StkFrames& buffer, unsigned long startFrame = 0, bool doNormalize = true ); + +protected: + + // Get STK RAW file information. + bool getRawInfo( const char *fileName ); + + // Get WAV file header information. + bool getWavInfo( const char *fileName ); + + // Get SND (AU) file header information. + bool getSndInfo( const char *fileName ); + + // Get AIFF file header information. + bool getAifInfo( const char *fileName ); + + // Get MAT-file header information. + bool getMatInfo( const char *fileName ); + + FILE *fd_; + bool byteswap_; + bool wavFile_; + unsigned long fileSize_; + unsigned long dataOffset_; + unsigned int channels_; + StkFormat dataType_; + StkFloat fileRate_; +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/FileWvIn.h b/nyqstk/include/FileWvIn.h new file mode 100644 index 0000000..31e0b41 --- /dev/null +++ b/nyqstk/include/FileWvIn.h @@ -0,0 +1,148 @@ +/***************************************************/ +/*! \class FileWvIn + \brief STK audio file input class. + + This class inherits from WvIn. It provides a "tick-level" + interface to the FileRead class. It also provides variable-rate + "playback" functionality. Audio file support is provided by the + FileRead class. Linear interpolation is used for fractional "read + rates". + + FileWvIn supports multi-channel data. It is important to distinguish + the tick() methods, which return samples produced by averaging + across sample frames, from the tickFrame() methods, which return + references to multi-channel sample frames. + + FileWvIn will either load the entire content of an audio file into + local memory or incrementally read file data from disk in chunks. + This behavior is controlled by the optional constructor arguments + \e chunkThreshold and \e chunkSize. File sizes greater than \e + chunkThreshold (in sample frames) will be read incrementally in + chunks of \e chunkSize each (also in sample frames). + + When the file end is reached, subsequent calls to the tick() + functions return zero-valued data and isFinished() returns \e + true. + + See the FileRead class for a description of the supported audio + file formats. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_FILEWVIN_H +#define STK_FILEWVIN_H + +#include "WvIn.h" +#include "FileRead.h" + +namespace Nyq +{ + +class FileWvIn : public WvIn +{ +public: + //! Default constructor. + FileWvIn( unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 ); + + //! Overloaded constructor for file input. + /*! + An StkError will be thrown if the file is not found, its format is + unknown, or a read error occurs. + */ + FileWvIn( std::string fileName, bool raw = false, bool doNormalize = true, + unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 ); + + //! Class destructor. + virtual ~FileWvIn(); + + //! Open the specified file and load its data. + /*! + Data from a previously opened file will be overwritten by this + function. An StkError will be thrown if the file is not found, + its format is unknown, or a read error occurs. If the file data + is to be loaded incrementally from disk and normalization is + specified, a scaling will be applied with respect to fixed-point + limits. If the data format is floating-point, no scaling is + performed. + */ + void openFile( std::string fileName, bool raw = false, bool doNormalize = true ); + + //! Close a file if one is open. + void closeFile( void ); + + //! Clear outputs and reset time (file) pointer to zero. + void reset( void ); + + //! Normalize data to a maximum of +-1.0. + /*! + This function has no effect when data is incrementally loaded + from disk. + */ + void normalize( void ); + + //! Normalize data to a maximum of \e +-peak. + /*! + This function has no effect when data is incrementally loaded + from disk. + */ + void normalize( StkFloat peak ); + + //! Return the file size in sample frames. + unsigned long getSize( void ) const { return data_.frames(); }; + + //! Return the input file sample rate in Hz (not the data read rate). + /*! + WAV, SND, and AIF formatted files specify a sample rate in + their headers. STK RAW files have a sample rate of 22050 Hz + by definition. MAT-files are assumed to have a rate of 44100 Hz. + */ + StkFloat getFileRate( void ) const { return data_.dataRate(); }; + + //! Query whether reading is complete. + bool isFinished( void ) const { return finished_; }; + + //! Set the data read rate in samples. The rate can be negative. + /*! + If the rate value is negative, the data is read in reverse order. + */ + void setRate( StkFloat rate ); + + //! Increment the read pointer by \e time samples. + /*! + Note that this function will not modify the interpolation flag status. + */ + virtual void addTime( StkFloat time ); + + //! Turn linear interpolation on/off. + /*! + Interpolation is automatically off when the read rate is + an integer value. If interpolation is turned off for a + fractional rate, the time index is truncated to an integer + value. + */ + void setInterpolate( bool doInterpolate ) { interpolate_ = doInterpolate; }; + + StkFloat lastOut( void ) const; + +protected: + + virtual void computeFrame( void ); + + FileRead file_; + bool finished_; + bool interpolate_; + bool normalizing_; + bool chunking_; + StkFloat time_; + StkFloat rate_; + unsigned long chunkThreshold_; + unsigned long chunkSize_; + long chunkPointer_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Filter.h b/nyqstk/include/Filter.h new file mode 100644 index 0000000..b7c8abd --- /dev/null +++ b/nyqstk/include/Filter.h @@ -0,0 +1,127 @@ +/***************************************************/ +/*! \class Filter + \brief STK filter class. + + This class implements a generic structure that + can be used to create a wide range of filters. + It can function independently or be subclassed + to provide more specific controls based on a + particular filter type. + + In particular, this class implements the standard + difference equation: + + a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] - + a[1]*y[n-1] - ... - a[na]*y[n-na] + + If a[0] is not equal to 1, the filter coeffcients + are normalized by a[0]. + + The \e gain parameter is applied at the filter + input and does not affect the coefficient values. + The default gain value is 1.0. This structure + results in one extra multiply per computed sample, + but allows easy control of the overall filter gain. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_FILTER_H +#define STK_FILTER_H + +#include "Stk.h" +#include + +namespace Nyq +{ + +class Filter : public Stk +{ +public: + //! Default constructor creates a zero-order pass-through "filter". + Filter(void); + + //! Overloaded constructor which takes filter coefficients. + /*! + An StkError can be thrown if either of the coefficient vector + sizes is zero, or if the a[0] coefficient is equal to zero. + */ + Filter( std::vector &bCoefficients, std::vector &aCoefficients ); + + //! Class destructor. + virtual ~Filter(void); + + //! Sets all internal states of the filter to zero. + void clear(void); + + //! Set filter coefficients. + /*! + An StkError can be thrown if either of the coefficient vector + sizes is zero, or if the a[0] coefficient is equal to zero. If + a[0] is not equal to 1, the filter coeffcients are normalized by + a[0]. The internal state of the filter is not cleared unless the + \e clearState flag is \c true. + */ + void setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients, bool clearState = false ); + + //! Set numerator coefficients. + /*! + An StkError can be thrown if coefficient vector is empty. Any + previously set denominator coefficients are left unaffected. Note + that the default constructor sets the single denominator + coefficient a[0] to 1.0. The internal state of the filter is not + cleared unless the \e clearState flag is \c true. + */ + void setNumerator( std::vector &bCoefficients, bool clearState = false ); + + //! Set denominator coefficients. + /*! + An StkError can be thrown if the coefficient vector is empty or + if the a[0] coefficient is equal to zero. Previously set + numerator coefficients are unaffected unless a[0] is not equal to + 1, in which case all coeffcients are normalized by a[0]. Note + that the default constructor sets the single numerator coefficient + b[0] to 1.0. The internal state of the filter is not cleared + unless the \e clearState flag is \c true. + */ + void setDenominator( std::vector &aCoefficients, bool clearState = false ); + + //! Set the filter gain. + /*! + The gain is applied at the filter input and does not affect the + coefficient values. The default gain value is 1.0. + */ + virtual void setGain(StkFloat gain); + + //! Return the current filter gain. + virtual StkFloat getGain(void) const; + + //! Return the last computed output value. + virtual StkFloat lastOut(void) const; + + //! Input one sample to the filter and return one output. + virtual StkFloat tick( StkFloat input ); + + //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + +protected: + + StkFloat gain_; + std::vector b_; + std::vector a_; + std::vector outputs_; + std::vector inputs_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Flute.h b/nyqstk/include/Flute.h new file mode 100644 index 0000000..5b6f3bd --- /dev/null +++ b/nyqstk/include/Flute.h @@ -0,0 +1,108 @@ +/***************************************************/ +/*! \class Flute + \brief STK flute physical model class. + + This class implements a simple flute + physical model, as discussed by Karjalainen, + Smith, Waryznyk, etc. The jet model uses + a polynomial, a la Cook. + + This is a digital waveguide model, making its + use possibly subject to patents held by Stanford + University, Yamaha, and others. + + Control Change Numbers: + - Jet Delay = 2 + - Noise Gain = 4 + - Vibrato Frequency = 11 + - Vibrato Gain = 1 + - Breath Pressure = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_FLUTE_H +#define STK_FLUTE_H + +#include "Instrmnt.h" +#include "JetTable.h" +#include "DelayL.h" +#include "OnePole.h" +#include "PoleZero.h" +#include "Noise.h" +#include "ADSR.h" +#include "SineWave.h" + +namespace Nyq +{ + +class Flute : public Instrmnt +{ + public: + //! Class constructor, taking the lowest desired playing frequency. + /*! + An StkError will be thrown if the rawwave path is incorrectly set. + */ + Flute(StkFloat lowestFrequency); + + //! Class destructor. + ~Flute(); + + //! Reset and clear all internal state. + void clear(); + + //! Set instrument parameters for a particular frequency. + void setFrequency(StkFloat frequency); + + //! Set the reflection coefficient for the jet delay (-1.0 - 1.0). + void setJetReflection(StkFloat coefficient); + + //! Set the reflection coefficient for the air column delay (-1.0 - 1.0). + void setEndReflection(StkFloat coefficient); + + //! Set the length of the jet delay in terms of a ratio of jet delay to air column delay lengths. + void setJetDelay(StkFloat aRatio); + + //! Apply breath velocity to instrument with given amplitude and rate of increase. + void startBlowing(StkFloat amplitude, StkFloat rate); + + //! Decrease breath velocity with given rate of decrease. + void stopBlowing(StkFloat rate); + + //! Start a note with the given frequency and amplitude. + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Stop a note with the given amplitude (speed of decay). + void noteOff(StkFloat amplitude); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + void controlChange(int number, StkFloat value); + + protected: + + StkFloat computeSample( void ); + + DelayL jetDelay_; + DelayL boreDelay_; + JetTable jetTable_; + OnePole filter_; + PoleZero dcBlock_; + Noise noise_; + ADSR adsr_; + SineWave vibrato_; + unsigned long length_; + StkFloat lastFrequency_; + StkFloat maxPressure_; + StkFloat jetReflection_; + StkFloat endReflection_; + StkFloat noiseGain_; + StkFloat vibratoGain_; + StkFloat outputGain_; + StkFloat jetRatio_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Function.h b/nyqstk/include/Function.h new file mode 100644 index 0000000..2b773c6 --- /dev/null +++ b/nyqstk/include/Function.h @@ -0,0 +1,59 @@ +/***************************************************/ +/*! \class Function + \brief STK abstract function parent class. + + This class provides common functionality for STK classes which + implement tables or other types of input to output function + mappings. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Stk.h" + +#ifndef STK_FUNCTION_H +#define STK_FUNCTION_H + +namespace Nyq +{ + +class Function : public Stk +{ + public: + //! Class constructor. + Function(); + + //! Class destructor. + virtual ~Function(); + + //! Return the last output value. + virtual StkFloat lastOut() const { return lastOutput_; }; + + //! Take one sample input and compute one sample of output. + StkFloat tick( StkFloat input ); + + //! Take a channel of the StkFrames object as inputs to the function and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + + protected: + + // This abstract function must be implemented in all subclasses. + // It is used to get around a C++ problem with overloaded virtual + // functions. + virtual StkFloat computeSample( StkFloat input ) = 0; + + StkFloat lastOutput_; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/Generator.h b/nyqstk/include/Generator.h new file mode 100644 index 0000000..9b91ea6 --- /dev/null +++ b/nyqstk/include/Generator.h @@ -0,0 +1,58 @@ +/***************************************************/ +/*! \class Generator + \brief STK abstract unit generator parent class. + + This class provides common functionality for + STK unit generator sample-source subclasses. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_GENERATOR_H +#define STK_GENERATOR_H + +#include "Stk.h" + +namespace Nyq +{ + +class Generator : public Stk +{ + public: + //! Class constructor. + Generator( void ); + + //! Class destructor. + virtual ~Generator( void ); + + //! Return the last output value. + virtual StkFloat lastOut( void ) const { return lastOutput_; }; + + //! Compute one sample and output. + StkFloat tick( void ); + + //! Fill a channel of the StkFrames object with computed outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + + protected: + + // This abstract function must be implemented in all subclasses. + // It is used to get around a C++ problem with overloaded virtual + // functions. + virtual StkFloat computeSample( void ) = 0; + + StkFloat lastOutput_; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/Instrmnt.h b/nyqstk/include/Instrmnt.h new file mode 100644 index 0000000..0bc9585 --- /dev/null +++ b/nyqstk/include/Instrmnt.h @@ -0,0 +1,75 @@ +/***************************************************/ +/*! \class Instrmnt + \brief STK instrument abstract base class. + + This class provides a common interface for + all STK instruments. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_INSTRMNT_H +#define STK_INSTRMNT_H + +#include "Stk.h" + +namespace Nyq +{ + +class Instrmnt : public Stk +{ + public: + //! Default constructor. + Instrmnt(); + + //! Class destructor. + virtual ~Instrmnt(); + + //! Start a note with the given frequency and amplitude. + virtual void noteOn(StkFloat frequency, StkFloat amplitude) = 0; + + //! Stop a note with the given amplitude (speed of decay). + virtual void noteOff(StkFloat amplitude) = 0; + + //! Set instrument parameters for a particular frequency. + virtual void setFrequency(StkFloat frequency); + + //! Return the last output value. + StkFloat lastOut() const; + + //! Return the last left output value. + StkFloat lastOutLeft() const; + + //! Return the last right output value. + StkFloat lastOutRight() const; + + //! Compute one sample and output. + StkFloat tick( void ); + + //! Fill a channel of the StkFrames object with computed outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + virtual void controlChange(int number, StkFloat value); + + protected: + + // This abstract function must be implemented in all subclasses. + // It is used to get around a C++ problem with overloaded virtual + // functions. + virtual StkFloat computeSample( void ) = 0; + + StkFloat lastOutput_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/JCRev.h b/nyqstk/include/JCRev.h new file mode 100644 index 0000000..92848cf --- /dev/null +++ b/nyqstk/include/JCRev.h @@ -0,0 +1,57 @@ +/***************************************************/ +/*! \class JCRev + \brief John Chowning's reverberator class. + + This class is derived from the CLM JCRev + function, which is based on the use of + networks of simple allpass and comb delay + filters. This class implements three series + allpass units, followed by four parallel comb + filters, and two decorrelation delay lines in + parallel at the output. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_JCREV_H +#define STK_JCREV_H + +#include "Effect.h" +#include "Delay.h" + +namespace Nyq +{ + +class JCRev : public Effect +{ + public: + //! Class constructor taking a T60 decay time argument (one second default value). + JCRev( StkFloat T60 = 1.0 ); + + //! Class destructor. + ~JCRev(); + + //! Reset and clear all internal state. + void clear(); + + //! Set the reverberation T60 decay time. + void setT60( StkFloat T60 ); + + protected: + + StkFloat computeSample( StkFloat input ); + + Delay allpassDelays_[3]; + Delay combDelays_[4]; + Delay outLeftDelay_; + Delay outRightDelay_; + StkFloat allpassCoefficient_; + StkFloat combCoefficient_[4]; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/JetTable.h b/nyqstk/include/JetTable.h new file mode 100644 index 0000000..003a758 --- /dev/null +++ b/nyqstk/include/JetTable.h @@ -0,0 +1,41 @@ +/***************************************************/ +/*! \class JetTable + \brief STK jet table class. + + This class implements a flue jet non-linear + function, computed by a polynomial calculation. + Contrary to the name, this is not a "table". + + Consult Fletcher and Rossing, Karjalainen, + Cook, and others for more information. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_JETTABL_H +#define STK_JETTABL_H + +#include "Function.h" + +namespace Nyq +{ + +class JetTable : public Function +{ +public: + //! Default constructor. + JetTable(); + + //! Class destructor. + ~JetTable(); + +protected: + + StkFloat computeSample( StkFloat input ); + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Mandolin.h b/nyqstk/include/Mandolin.h new file mode 100644 index 0000000..e619cf9 --- /dev/null +++ b/nyqstk/include/Mandolin.h @@ -0,0 +1,75 @@ +/***************************************************/ +/*! \class Mandolin + \brief STK mandolin instrument model class. + + This class inherits from PluckTwo and uses + "commuted synthesis" techniques to model a + mandolin instrument. + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + Commuted Synthesis, in particular, is covered + by patents, granted, pending, and/or + applied-for. All are assigned to the Board of + Trustees, Stanford University. For + information, contact the Office of Technology + Licensing, Stanford University. + + Control Change Numbers: + - Body Size = 2 + - Pluck Position = 4 + - String Sustain = 11 + - String Detuning = 1 + - Microphone Position = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_MANDOLIN_H +#define STK_MANDOLIN_H + +#include "PluckTwo.h" +#include "FileWvIn.h" + +namespace Nyq +{ + +class Mandolin : public PluckTwo +{ + public: + //! Class constructor, taking the lowest desired playing frequency. + Mandolin(StkFloat lowestFrequency); + + //! Class destructor. + ~Mandolin(); + + //! Pluck the strings with the given amplitude (0.0 - 1.0) using the current frequency. + void pluck(StkFloat amplitude); + + //! Pluck the strings with the given amplitude (0.0 - 1.0) and position (0.0 - 1.0). + void pluck(StkFloat amplitude,StkFloat position); + + //! Start a note with the given frequency and amplitude (0.0 - 1.0). + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Set the body size (a value of 1.0 produces the "default" size). + void setBodySize(StkFloat size); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + void controlChange(int number, StkFloat value); + + protected: + + StkFloat computeSample( void ); + + FileWvIn *soundfile_[12]; + int mic_; + long dampTime_; + bool waveDone_; +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Modal.h b/nyqstk/include/Modal.h new file mode 100644 index 0000000..1b5443a --- /dev/null +++ b/nyqstk/include/Modal.h @@ -0,0 +1,96 @@ +/***************************************************/ +/*! \class Modal + \brief STK resonance model instrument. + + This class contains an excitation wavetable, + an envelope, an oscillator, and N resonances + (non-sweeping BiQuad filters), where N is set + during instantiation. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_MODAL_H +#define STK_MODAL_H + +#include "Instrmnt.h" +#include "Envelope.h" +#include "WaveLoop.h" +#include "SineWave.h" +#include "BiQuad.h" +#include "OnePole.h" + +namespace Nyq +{ + +class Modal : public Instrmnt +{ +public: + //! Class constructor, taking the desired number of modes to create. + /*! + An StkError will be thrown if the rawwave path is incorrectly set. + */ + Modal( unsigned int modes = 4 ); + + //! Class destructor. + virtual ~Modal(); + + //! Reset and clear all internal state. + void clear(); + + //! Set instrument parameters for a particular frequency. + virtual void setFrequency(StkFloat frequency); + + //! Set the ratio and radius for a specified mode filter. + void setRatioAndRadius(unsigned int modeIndex, StkFloat ratio, StkFloat radius); + + //! Set the master gain. + void setMasterGain(StkFloat aGain); + + //! Set the direct gain. + void setDirectGain(StkFloat aGain); + + //! Set the gain for a specified mode filter. + void setModeGain(unsigned int modeIndex, StkFloat gain); + + //! Initiate a strike with the given amplitude (0.0 - 1.0). + virtual void strike(StkFloat amplitude); + + //! Damp modes with a given decay factor (0.0 - 1.0). + void damp(StkFloat amplitude); + + //! Start a note with the given frequency and amplitude. + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Stop a note with the given amplitude (speed of decay). + void noteOff(StkFloat amplitude); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + virtual void controlChange(int number, StkFloat value) = 0; + +protected: + + StkFloat computeSample( void ); + + Envelope envelope_; + FileWvIn *wave_; + BiQuad **filters_; + OnePole onepole_; + SineWave vibrato_; + + unsigned int nModes_; + std::vector ratios_; + std::vector radii_; + + StkFloat vibratoGain_; + StkFloat masterGain_; + StkFloat directGain_; + StkFloat stickHardness_; + StkFloat strikePosition_; + StkFloat baseFrequency_; +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/ModalBar.h b/nyqstk/include/ModalBar.h new file mode 100644 index 0000000..2336b29 --- /dev/null +++ b/nyqstk/include/ModalBar.h @@ -0,0 +1,66 @@ +/***************************************************/ +/*! \class ModalBar + \brief STK resonant bar instrument class. + + This class implements a number of different + struck bar instruments. It inherits from the + Modal class. + + Control Change Numbers: + - Stick Hardness = 2 + - Stick Position = 4 + - Vibrato Gain = 1 + - Vibrato Frequency = 11 + - Direct Stick Mix = 8 + - Volume = 128 + - Modal Presets = 16 + - Marimba = 0 + - Vibraphone = 1 + - Agogo = 2 + - Wood1 = 3 + - Reso = 4 + - Wood2 = 5 + - Beats = 6 + - Two Fixed = 7 + - Clump = 8 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_MODALBAR_H +#define STK_MODALBAR_H + +#include "Modal.h" + +namespace Nyq +{ + +class ModalBar : public Modal +{ +public: + //! Class constructor. + ModalBar(); + + //! Class destructor. + ~ModalBar(); + + //! Set stick hardness (0.0 - 1.0). + void setStickHardness(StkFloat hardness); + + //! Set stick position (0.0 - 1.0). + void setStrikePosition(StkFloat position); + + //! Select a bar preset (currently modulo 9). + void setPreset(int preset); + + //! Set the modulation (vibrato) depth. + void setModulationDepth(StkFloat mDepth); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + void controlChange(int number, StkFloat value); +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/NRev.h b/nyqstk/include/NRev.h new file mode 100644 index 0000000..28031cf --- /dev/null +++ b/nyqstk/include/NRev.h @@ -0,0 +1,58 @@ +/***************************************************/ +/*! \class NRev + \brief CCRMA's NRev reverberator class. + + This class is derived from the CLM NRev + function, which is based on the use of + networks of simple allpass and comb delay + filters. This particular arrangement consists + of 6 comb filters in parallel, followed by 3 + allpass filters, a lowpass filter, and another + allpass in series, followed by two allpass + filters in parallel with corresponding right + and left outputs. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_NREV_H +#define STK_NREV_H + +#include "Effect.h" +#include "Delay.h" + +namespace Nyq +{ + +class NRev : public Effect +{ + public: + //! Class constructor taking a T60 decay time argument (one second default value). + NRev( StkFloat T60 = 1.0 ); + + //! Class destructor. + ~NRev(); + + //! Reset and clear all internal state. + void clear(); + + //! Set the reverberation T60 decay time. + void setT60( StkFloat T60 ); + + protected: + + StkFloat computeSample( StkFloat input ); + + Delay allpassDelays_[8]; + Delay combDelays_[6]; + StkFloat allpassCoefficient_; + StkFloat combCoefficient_[6]; + StkFloat lowpassState_; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/Noise.h b/nyqstk/include/Noise.h new file mode 100644 index 0000000..0cbd409 --- /dev/null +++ b/nyqstk/include/Noise.h @@ -0,0 +1,53 @@ +/***************************************************/ +/*! \class Noise + \brief STK noise generator. + + Generic random number generation using the + C rand() function. The quality of the rand() + function varies from one OS to another. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_NOISE_H +#define STK_NOISE_H + +#include "Generator.h" + +namespace Nyq +{ + +class Noise : public Generator +{ +public: + + //! Default constructor which seeds the random number generator with the system time. + Noise(); + + //! Constructor which seeds the random number generator with a given seed. + /*! + If the seed value is zero, the random number generator is + seeded with the system time. + */ + Noise( unsigned int seed ); + + //! Class destructor. + virtual ~Noise(); + + //! Seed the random number generator with a specific seed value. + /*! + If no seed is provided or the seed value is zero, the random + number generator is seeded with the current system time. + */ + void setSeed( unsigned int seed = 0 ); + +protected: + + virtual StkFloat computeSample( void ); + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/OnePole.h b/nyqstk/include/OnePole.h new file mode 100644 index 0000000..a141452 --- /dev/null +++ b/nyqstk/include/OnePole.h @@ -0,0 +1,84 @@ +/***************************************************/ +/*! \class OnePole + \brief STK one-pole filter class. + + This protected Filter subclass implements + a one-pole digital filter. A method is + provided for setting the pole position along + the real axis of the z-plane while maintaining + a constant peak filter gain. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_ONEPOLE_H +#define STK_ONEPOLE_H + +#include "Filter.h" + +namespace Nyq +{ + +class OnePole : protected Filter +{ +public: + + //! Default constructor creates a first-order low-pass filter. + OnePole(); + + //! Overloaded constructor which sets the pole position during instantiation. + OnePole( StkFloat thePole ); + + //! Class destructor. + ~OnePole(); + + //! Clears the internal state of the filter. + void clear(void); + + //! Set the b[0] coefficient value. + void setB0(StkFloat b0); + + //! Set the a[1] coefficient value. + void setA1(StkFloat a1); + + //! Set the pole position in the z-plane. + /*! + This method sets the pole position along the real-axis of the + z-plane and normalizes the coefficients for a maximum gain of one. + A positive pole value produces a low-pass filter, while a negative + pole value produces a high-pass filter. This method does not + affect the filter \e gain value. + */ + void setPole(StkFloat thePole); + + //! Set the filter gain. + /*! + The gain is applied at the filter input and does not affect the + coefficient values. The default gain value is 1.0. + */ + void setGain(StkFloat gain); + + //! Return the current filter gain. + StkFloat getGain(void) const; + + //! Return the last computed output value. + StkFloat lastOut(void) const; + + //! Input one sample to the filter and return one output. + StkFloat tick(StkFloat sample); + + //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/OneZero.h b/nyqstk/include/OneZero.h new file mode 100644 index 0000000..19da171 --- /dev/null +++ b/nyqstk/include/OneZero.h @@ -0,0 +1,84 @@ +/***************************************************/ +/*! \class OneZero + \brief STK one-zero filter class. + + This protected Filter subclass implements + a one-zero digital filter. A method is + provided for setting the zero position + along the real axis of the z-plane while + maintaining a constant filter gain. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_ONEZERO_H +#define STK_ONEZERO_H + +#include "Filter.h" + +namespace Nyq +{ + +class OneZero : protected Filter +{ + public: + + //! Default constructor creates a first-order low-pass filter. + OneZero(); + + //! Overloaded constructor which sets the zero position during instantiation. + OneZero(StkFloat theZero); + + //! Class destructor. + ~OneZero(); + + //! Clears the internal state of the filter. + void clear(void); + + //! Set the b[0] coefficient value. + void setB0(StkFloat b0); + + //! Set the b[1] coefficient value. + void setB1(StkFloat b1); + + //! Set the zero position in the z-plane. + /*! + This method sets the zero position along the real-axis of the + z-plane and normalizes the coefficients for a maximum gain of one. + A positive zero value produces a high-pass filter, while a + negative zero value produces a low-pass filter. This method does + not affect the filter \e gain value. + */ + void setZero(StkFloat theZero); + + //! Set the filter gain. + /*! + The gain is applied at the filter input and does not affect the + coefficient values. The default gain value is 1.0. + */ + void setGain(StkFloat gain); + + //! Return the current filter gain. + StkFloat getGain(void) const; + + //! Return the last computed output value. + StkFloat lastOut(void) const; + + //! Input one sample to the filter and return one output. + StkFloat tick(StkFloat sample); + + //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/PRCRev.h b/nyqstk/include/PRCRev.h new file mode 100644 index 0000000..5ee5c76 --- /dev/null +++ b/nyqstk/include/PRCRev.h @@ -0,0 +1,55 @@ +/***************************************************/ +/*! \class PRCRev + \brief Perry's simple reverberator class. + + This class is based on some of the famous + Stanford/CCRMA reverbs (NRev, KipRev), which + were based on the Chowning/Moorer/Schroeder + reverberators using networks of simple allpass + and comb delay filters. This class implements + two series allpass units and two parallel comb + filters. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_PRCREV_H +#define STK_PRCREV_H + +#include "Effect.h" +#include "Delay.h" + +namespace Nyq +{ + +class PRCRev : public Effect +{ +public: + //! Class constructor taking a T60 decay time argument (one second default value). + PRCRev( StkFloat T60 = 1.0 ); + + //! Class destructor. + ~PRCRev(); + + //! Reset and clear all internal state. + void clear(); + + //! Set the reverberation T60 decay time. + void setT60( StkFloat T60 ); + +protected: + + StkFloat computeSample( StkFloat input ); + + Delay allpassDelays_[2]; + Delay combDelays_[2]; + StkFloat allpassCoefficient_; + StkFloat combCoefficient_[2]; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/PitShift.h b/nyqstk/include/PitShift.h new file mode 100644 index 0000000..775b8e2 --- /dev/null +++ b/nyqstk/include/PitShift.h @@ -0,0 +1,52 @@ +/***************************************************/ +/*! \class PitShift + \brief STK simple pitch shifter effect class. + + This class implements a simple pitch shifter + using delay lines. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_PITSHIFT_H +#define STK_PITSHIFT_H + +#include "Effect.h" +#include "DelayL.h" + +namespace Nyq +{ + +class PitShift : public Effect +{ + public: + //! Class constructor. + PitShift(); + + //! Class destructor. + ~PitShift(); + + //! Reset and clear all internal state. + void clear(); + + //! Set the pitch shift factor (1.0 produces no shift). + void setShift(StkFloat shift); + + protected: + + StkFloat computeSample( StkFloat input ); + + DelayL delayLine_[2]; + StkFloat delay_[2]; + StkFloat env_[2]; + StkFloat rate_; + unsigned long delayLength; + unsigned long halfLength; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/PluckTwo.h b/nyqstk/include/PluckTwo.h new file mode 100644 index 0000000..eabb74d --- /dev/null +++ b/nyqstk/include/PluckTwo.h @@ -0,0 +1,90 @@ +/***************************************************/ +/*! \class PluckTwo + \brief STK enhanced plucked string model class. + + This class implements an enhanced two-string, + plucked physical model, a la Jaffe-Smith, + Smith, and others. + + PluckTwo is an abstract class, with no excitation + specified. Therefore, it can't be directly + instantiated. + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_PLUCKTWO_H +#define STK_PLUCKTWO_H + +#include "Instrmnt.h" +#include "DelayL.h" +#include "DelayA.h" +#include "OneZero.h" + +namespace Nyq +{ + +class PluckTwo : public Instrmnt +{ + public: + //! Class constructor, taking the lowest desired playing frequency. + PluckTwo(StkFloat lowestFrequency); + + //! Class destructor. + virtual ~PluckTwo(); + + //! Reset and clear all internal state. + void clear(); + + //! Set instrument parameters for a particular frequency. + virtual void setFrequency(StkFloat frequency); + + //! Detune the two strings by the given factor. A value of 1.0 produces unison strings. + void setDetune(StkFloat detune); + + //! Efficient combined setting of frequency and detuning. + void setFreqAndDetune(StkFloat frequency, StkFloat detune); + + //! Set the pluck or "excitation" position along the string (0.0 - 1.0). + void setPluckPosition(StkFloat position); + + //! Set the base loop gain. + /*! + The actual loop gain is set according to the frequency. + Because of high-frequency loop filter roll-off, higher + frequency settings have greater loop gains. + */ + void setBaseLoopGain(StkFloat aGain); + + //! Stop a note with the given amplitude (speed of decay). + virtual void noteOff(StkFloat amplitude); + + protected: + + virtual StkFloat computeSample( void ) = 0; + + DelayA delayLine_; + DelayA delayLine2_; + DelayL combDelay_; + OneZero filter_; + OneZero filter2_; + + unsigned long length_; + StkFloat loopGain_; + StkFloat baseLoopGain_; + StkFloat lastFrequency_; + StkFloat lastLength_; + StkFloat detuning_; + StkFloat pluckAmplitude_; + StkFloat pluckPosition_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/PoleZero.h b/nyqstk/include/PoleZero.h new file mode 100644 index 0000000..5ee5d10 --- /dev/null +++ b/nyqstk/include/PoleZero.h @@ -0,0 +1,91 @@ +/***************************************************/ +/*! \class PoleZero + \brief STK one-pole, one-zero filter class. + + This protected Filter subclass implements + a one-pole, one-zero digital filter. A + method is provided for creating an allpass + filter with a given coefficient. Another + method is provided to create a DC blocking filter. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_POLEZERO_H +#define STK_POLEZERO_H + +#include "Filter.h" + +namespace Nyq +{ + +class PoleZero : protected Filter +{ + public: + + //! Default constructor creates a first-order pass-through filter. + PoleZero(); + + //! Class destructor. + ~PoleZero(); + + //! Clears the internal states of the filter. + void clear(void); + + //! Set the b[0] coefficient value. + void setB0(StkFloat b0); + + //! Set the b[1] coefficient value. + void setB1(StkFloat b1); + + //! Set the a[1] coefficient value. + void setA1(StkFloat a1); + + //! Set the filter for allpass behavior using \e coefficient. + /*! + This method uses \e coefficient to create an allpass filter, + which has unity gain at all frequencies. Note that the \e + coefficient magnitude must be less than one to maintain stability. + */ + void setAllpass(StkFloat coefficient); + + //! Create a DC blocking filter with the given pole position in the z-plane. + /*! + This method sets the given pole position, together with a zero + at z=1, to create a DC blocking filter. \e thePole should be + close to one to minimize low-frequency attenuation. + + */ + void setBlockZero(StkFloat thePole = 0.99); + + //! Set the filter gain. + /*! + The gain is applied at the filter input and does not affect the + coefficient values. The default gain value is 1.0. + */ + void setGain( StkFloat gain ); + + //! Return the current filter gain. + StkFloat getGain( void ) const; + + //! Return the last computed output value. + StkFloat lastOut( void ) const; + + //! Input one sample to the filter and return one output. + StkFloat tick( StkFloat sample ); + + //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is equal to or greater than the number of + channels in the StkFrames object. + */ + StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/ReedTabl.h b/nyqstk/include/ReedTabl.h new file mode 100644 index 0000000..e6f97a5 --- /dev/null +++ b/nyqstk/include/ReedTabl.h @@ -0,0 +1,70 @@ +/***************************************************/ +/*! \class ReedTabl + \brief STK reed table class. + + This class implements a simple one breakpoint, + non-linear reed function, as described by + Smith (1986). This function is based on a + memoryless non-linear spring model of the reed + (the reed mass is ignored) which saturates when + the reed collides with the mouthpiece facing. + + See McIntyre, Schumacher, & Woodhouse (1983), + Smith (1986), Hirschman, Cook, Scavone, and + others for more information. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2002. +*/ +/***************************************************/ + +#if !defined(__REEDTABL_H) +#define __REEDTABL_H + +#include "Stk.h" + +class ReedTabl : public Stk +{ +public: + //! Default constructor. + ReedTabl(); + + //! Class destructor. + ~ReedTabl(); + + //! Set the table offset value. + /*! + The table offset roughly corresponds to the size + of the initial reed tip opening (a greater offset + represents a smaller opening). + */ + void setOffset(MY_FLOAT aValue); + + //! Set the table slope value. + /*! + The table slope roughly corresponds to the reed + stiffness (a greater slope represents a harder + reed). + */ + void setSlope(MY_FLOAT aValue); + + //! Return the last output value. + MY_FLOAT lastOut() const; + + //! Return the function value for \e input. + /*! + The function input represents the differential + pressure across the reeds. + */ + MY_FLOAT tick(MY_FLOAT input); + + //! Take \e vectorSize inputs and return the corresponding function values in \e vector. + MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); + +protected: + MY_FLOAT offSet; + MY_FLOAT slope; + MY_FLOAT lastOutput; + +}; + +#endif diff --git a/nyqstk/include/ReedTable.h b/nyqstk/include/ReedTable.h new file mode 100644 index 0000000..c7e8744 --- /dev/null +++ b/nyqstk/include/ReedTable.h @@ -0,0 +1,64 @@ +/***************************************************/ +/*! \class ReedTable + \brief STK reed table class. + + This class implements a simple one breakpoint, + non-linear reed function, as described by + Smith (1986). This function is based on a + memoryless non-linear spring model of the reed + (the reed mass is ignored) which saturates when + the reed collides with the mouthpiece facing. + + See McIntyre, Schumacher, & Woodhouse (1983), + Smith (1986), Hirschman, Cook, Scavone, and + others for more information. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_REEDTABLE_H +#define STK_REEDTABLE_H + +#include "Function.h" + +namespace Nyq +{ + +class ReedTable : public Function +{ +public: + //! Default constructor. + ReedTable(); + + //! Class destructor. + ~ReedTable(); + + //! Set the table offset value. + /*! + The table offset roughly corresponds to the size + of the initial reed tip opening (a greater offset + represents a smaller opening). + */ + void setOffset(StkFloat offset); + + //! Set the table slope value. + /*! + The table slope roughly corresponds to the reed + stiffness (a greater slope represents a harder + reed). + */ + void setSlope(StkFloat slope); + +protected: + + StkFloat computeSample( StkFloat input ); + + StkFloat offset_; + StkFloat slope_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/SKINI.msg b/nyqstk/include/SKINI.msg new file mode 100644 index 0000000..5e5fdca --- /dev/null +++ b/nyqstk/include/SKINI.msg @@ -0,0 +1,127 @@ +/*********************************************************/ +/* + Definition of SKINI Message Types and Special Symbols + Synthesis toolKit Instrument Network Interface + + These symbols should have the form __SK__ + + Where is the string used in the SKINI stream. + + by Perry R. Cook, 1995 - 2002. +*/ +/*********************************************************/ + +namespace Nyq +{ + +/***** MIDI COMPATIBLE MESSAGES *****/ +/***** Status Bytes Have Channel=0 **/ + +#define NOPE -32767 +#define YEP 1 +#define SK_DBL -32766 +#define SK_INT -32765 +#define SK_STR -32764 + +#define __SK_NoteOff_ 128 +#define __SK_NoteOn_ 144 +#define __SK_PolyPressure_ 160 +#define __SK_ControlChange_ 176 +#define __SK_ProgramChange_ 192 +#define __SK_AfterTouch_ 208 +#define __SK_ChannelPressure_ __SK_AfterTouch_ +#define __SK_PitchWheel_ 224 +#define __SK_PitchBend_ __SK_PitchWheel_ +#define __SK_PitchChange_ 249 + +#define __SK_Clock_ 248 +#define __SK_SongStart_ 250 +#define __SK_Continue_ 251 +#define __SK_SongStop_ 252 +#define __SK_ActiveSensing_ 254 +#define __SK_SystemReset_ 255 + +#define __SK_Volume_ 7 +#define __SK_ModWheel_ 1 +#define __SK_Modulation_ __SK_ModWheel_ +#define __SK_Breath_ 2 +#define __SK_FootControl_ 4 +#define __SK_Portamento_ 65 +#define __SK_Balance_ 8 +#define __SK_Pan_ 10 +#define __SK_Sustain_ 64 +#define __SK_Damper_ __SK_Sustain_ +#define __SK_Expression_ 11 + +#define __SK_AfterTouch_Cont_ 128 +#define __SK_ModFrequency_ __SK_Expression_ + +#define __SK_ProphesyRibbon_ 16 +#define __SK_ProphesyWheelUp_ 2 +#define __SK_ProphesyWheelDown_ 3 +#define __SK_ProphesyPedal_ 18 +#define __SK_ProphesyKnob1_ 21 +#define __SK_ProphesyKnob2_ 22 + +/*** Instrument Family Specific ***/ + +#define __SK_NoiseLevel_ __SK_FootControl_ + +#define __SK_PickPosition_ __SK_FootControl_ +#define __SK_StringDamping_ __SK_Expression_ +#define __SK_StringDetune_ __SK_ModWheel_ +#define __SK_BodySize_ __SK_Breath_ +#define __SK_BowPressure_ __SK_Breath_ +#define __SK_BowPosition_ __SK_PickPosition_ +#define __SK_BowBeta_ __SK_BowPosition_ + +#define __SK_ReedStiffness_ __SK_Breath_ +#define __SK_ReedRestPos_ __SK_FootControl_ + +#define __SK_FluteEmbouchure_ __SK_Breath_ +#define __SK_JetDelay_ __SK_FluteEmbouchure_ + +#define __SK_LipTension_ __SK_Breath_ +#define __SK_SlideLength_ __SK_FootControl_ + +#define __SK_StrikePosition_ __SK_PickPosition_ +#define __SK_StickHardness_ __SK_Breath_ + +#define __SK_TrillDepth_ 1051 +#define __SK_TrillSpeed_ 1052 +#define __SK_StrumSpeed_ __SK_TrillSpeed_ +#define __SK_RollSpeed_ __SK_TrillSpeed_ + +#define __SK_FilterQ_ __SK_Breath_ +#define __SK_FilterFreq_ 1062 +#define __SK_FilterSweepRate_ __SK_FootControl_ + +#define __SK_ShakerInst_ 1071 +#define __SK_ShakerEnergy_ __SK_Breath_ +#define __SK_ShakerDamping_ __SK_ModFrequency_ +#define __SK_ShakerNumObjects_ __SK_FootControl_ + +#define __SK_Strumming_ 1090 +#define __SK_NotStrumming_ 1091 +#define __SK_Trilling_ 1092 +#define __SK_NotTrilling_ 1093 +#define __SK_Rolling_ __SK_Strumming_ +#define __SK_NotRolling_ __SK_NotStrumming_ + +#define __SK_PlayerSkill_ 2001 +#define __SK_Chord_ 2002 +#define __SK_ChordOff_ 2003 + +#define __SK_SINGER_FilePath_ 3000 +#define __SK_SINGER_Frequency_ 3001 +#define __SK_SINGER_NoteName_ 3002 +#define __SK_SINGER_Shape_ 3003 +#define __SK_SINGER_Glot_ 3004 +#define __SK_SINGER_VoicedUnVoiced_ 3005 +#define __SK_SINGER_Synthesize_ 3006 +#define __SK_SINGER_Silence_ 3007 +#define __SK_SINGER_VibratoAmt_ __SK_ModWheel_ +#define __SK_SINGER_RndVibAmt_ 3008 +#define __SK_SINGER_VibFreq_ __SK_Expression_ + +} // namespace Nyq diff --git a/nyqstk/include/Saxofony.h b/nyqstk/include/Saxofony.h new file mode 100644 index 0000000..7609d4a --- /dev/null +++ b/nyqstk/include/Saxofony.h @@ -0,0 +1,108 @@ +/***************************************************/ +/*! \class Saxofony + \brief STK faux conical bore reed instrument class. + + This class implements a "hybrid" digital + waveguide instrument that can generate a + variety of wind-like sounds. It has also been + referred to as the "blowed string" model. The + waveguide section is essentially that of a + string, with one rigid and one lossy + termination. The non-linear function is a + reed table. The string can be "blown" at any + point between the terminations, though just as + with strings, it is impossible to excite the + system at either end. If the excitation is + placed at the string mid-point, the sound is + that of a clarinet. At points closer to the + "bridge", the sound is closer to that of a + saxophone. See Scavone (2002) for more details. + + This is a digital waveguide model, making its + use possibly subject to patents held by Stanford + University, Yamaha, and others. + + Control Change Numbers: + - Reed Stiffness = 2 + - Reed Aperture = 26 + - Noise Gain = 4 + - Blow Position = 11 + - Vibrato Frequency = 29 + - Vibrato Gain = 1 + - Breath Pressure = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_SAXOFONY_H +#define STK_SAXOFONY_H + +#include "Instrmnt.h" +#include "DelayL.h" +#include "ReedTable.h" +#include "OneZero.h" +#include "Envelope.h" +#include "Noise.h" +#include "SineWave.h" + +namespace Nyq +{ + +class Saxofony : public Instrmnt +{ + public: + //! Class constructor, taking the lowest desired playing frequency. + /*! + An StkError will be thrown if the rawwave path is incorrectly set. + */ + Saxofony(StkFloat lowestFrequency); + + //! Class destructor. + ~Saxofony(); + + //! Reset and clear all internal state. + void clear(); + + //! Set instrument parameters for a particular frequency. + void setFrequency(StkFloat frequency); + + //! Set the "blowing" position between the air column terminations (0.0 - 1.0). + void setBlowPosition(StkFloat aPosition); + + //! Apply breath pressure to instrument with given amplitude and rate of increase. + void startBlowing(StkFloat amplitude, StkFloat rate); + + //! Decrease breath pressure with given rate of decrease. + void stopBlowing(StkFloat rate); + + //! Start a note with the given frequency and amplitude. + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Stop a note with the given amplitude (speed of decay). + void noteOff(StkFloat amplitude); + + //! Perform the control change specified by \e number and \e value (0.0 - 128.0). + void controlChange(int number, StkFloat value); + + protected: + + StkFloat computeSample( void ); + + DelayL delays_[2]; + ReedTable reedTable_; + OneZero filter_; + Envelope envelope_; + Noise noise_; + SineWave vibrato_; + unsigned long length_; + StkFloat outputGain_; + StkFloat noiseGain_; + StkFloat vibratoGain_; + StkFloat position_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/SineWave.h b/nyqstk/include/SineWave.h new file mode 100644 index 0000000..756570d --- /dev/null +++ b/nyqstk/include/SineWave.h @@ -0,0 +1,90 @@ +/***************************************************/ +/*! \class SineWave + \brief STK sinusoid oscillator class. + + This class computes and saves a static sine "table" that can be + shared by multiple instances. It has an interface similar to the + WaveLoop class but inherits from the Generator class. Output + values are computed using linear interpolation. + + The "table" length, set in SineWave.h, is 2048 samples by default. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_SINEWAVE_H +#define STK_SINEWAVE_H + +namespace Nyq +{ + +const unsigned long TABLE_SIZE = 2048; + +} // namespace Nyq + +#include "Generator.h" + +namespace Nyq +{ + +class SineWave : public Generator +{ +public: + //! Default constructor. + SineWave( void ); + + //! Class destructor. + virtual ~SineWave( void ); + + //! Clear output and reset time pointer to zero. + void reset( void ); + + //! Set the data read rate in samples. The rate can be negative. + /*! + If the rate value is negative, the data is read in reverse order. + */ + void setRate( StkFloat rate ) { rate_ = rate; }; + + //! Set the data interpolation rate based on a looping frequency. + /*! + This function determines the interpolation rate based on the file + size and the current Stk::sampleRate. The \e frequency value + corresponds to file cycles per second. The frequency can be + negative, in which case the loop is read in reverse order. + */ + void setFrequency( StkFloat frequency ); + + //! Increment the read pointer by \e time samples, modulo file size. + void addTime( StkFloat time ); + + //! Increment current read pointer by \e angle, relative to a looping frequency. + /*! + This function increments the read pointer based on the file + size and the current Stk::sampleRate. The \e anAngle value + is a multiple of file size. + */ + void addPhase( StkFloat angle ); + + //! Add a phase offset to the current read pointer. + /*! + This function determines a time offset based on the file + size and the current Stk::sampleRate. The \e angle value + is a multiple of file size. + */ + void addPhaseOffset( StkFloat angle ); + +protected: + + StkFloat computeSample( void ); + + static StkFrames table_; + StkFloat time_; + StkFloat rate_; + StkFloat phaseOffset_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/Sitar.h b/nyqstk/include/Sitar.h new file mode 100644 index 0000000..d2b0bcd --- /dev/null +++ b/nyqstk/include/Sitar.h @@ -0,0 +1,75 @@ +/***************************************************/ +/*! \class Sitar + \brief STK sitar string model class. + + This class implements a sitar plucked string + physical model based on the Karplus-Strong + algorithm. + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + There exist at least two patents, assigned to + Stanford, bearing the names of Karplus and/or + Strong. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_SITAR_H +#define STK_SITAR_H + +#include "Instrmnt.h" +#include "DelayA.h" +#include "OneZero.h" +#include "Noise.h" +#include "ADSR.h" + +namespace Nyq +{ + +class Sitar : public Instrmnt +{ + public: + //! Class constructor, taking the lowest desired playing frequency. + Sitar( StkFloat lowestFrequency = 20 ); + + //! Class destructor. + ~Sitar(); + + //! Reset and clear all internal state. + void clear(); + + //! Set instrument parameters for a particular frequency. + void setFrequency(StkFloat frequency); + + //! Pluck the string with the given amplitude using the current frequency. + void pluck(StkFloat amplitude); + + //! Start a note with the given frequency and amplitude. + void noteOn(StkFloat frequency, StkFloat amplitude); + + //! Stop a note with the given amplitude (speed of decay). + void noteOff(StkFloat amplitude); + + protected: + + StkFloat computeSample( void ); + + DelayA delayLine_; + OneZero loopFilter_; + Noise noise_; + ADSR envelope_; + + StkFloat loopGain_; + StkFloat amGain_; + StkFloat delay_; + StkFloat targetDelay_; + +}; + +} // namespace Nyq + +#endif + diff --git a/nyqstk/include/Stk.h b/nyqstk/include/Stk.h new file mode 100644 index 0000000..e81a46c --- /dev/null +++ b/nyqstk/include/Stk.h @@ -0,0 +1,369 @@ +/***************************************************/ +/*! \class Stk + \brief STK base class + + Nearly all STK classes inherit from this class. + The global sample rate and rawwave path variables + can be queried and modified via Stk. In addition, + this class provides error handling and + byte-swapping functions. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_STK_H +#define STK_STK_H + +#include +#include +#include + +namespace Nyq +{ + +// Most data in STK is passed and calculated with the +// following user-definable floating-point type. You +// can change this to "float" if you prefer or perhaps +// a "long double" in the future. +typedef double StkFloat; + +// The "MY_FLOAT" type was deprecated in STK +// versions higher than 4.1.3 and replaced with the variable +// "StkFloat". +#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) + typedef StkFloat MY_FLOAT; + #pragma deprecated(MY_FLOAT) +#elif defined(__GXX__) + typedef StkFloat MY_FLOAT __attribute__ ((deprecated)); +#else + typedef StkFloat MY_FLOAT; // temporary +#endif + + +//! STK error handling class. +/*! + This is a fairly abstract exception handling class. There could + be sub-classes to take care of more specific error conditions ... or + not. +*/ +class StkError +{ +public: + enum Type { + STATUS, + WARNING, + DEBUG_WARNING, + MEMORY_ALLOCATION, + MEMORY_ACCESS, + FUNCTION_ARGUMENT, + FILE_NOT_FOUND, + FILE_UNKNOWN_FORMAT, + FILE_ERROR, + PROCESS_THREAD, + PROCESS_SOCKET, + PROCESS_SOCKET_IPADDR, + AUDIO_SYSTEM, + MIDI_SYSTEM, + UNSPECIFIED + }; + +protected: + std::string message_; + Type type_; + +public: + //! The constructor. + StkError(const std::string& message, Type type = StkError::UNSPECIFIED) + : message_(message), type_(type) {} + + //! The destructor. + virtual ~StkError(void) {}; + + //! Prints thrown error message to stderr. + virtual void printMessage(void) { std::cerr << '\n' << message_ << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType(void) { return type_; } + + //! Returns the thrown error message string. + virtual const std::string& getMessage(void) { return message_; } + + //! Returns the thrown error message as a C string. + virtual const char *getMessageCString(void) { return message_.c_str(); } +}; + + +class Stk +{ +public: + + typedef unsigned long StkFormat; + static const StkFormat STK_SINT8; /*!< -128 to +127 */ + static const StkFormat STK_SINT16; /*!< -32768 to +32767 */ + static const StkFormat STK_SINT24; /*!< Upper 3 bytes of 32-bit signed integer. */ + static const StkFormat STK_SINT32; /*!< -2147483648 to +2147483647. */ + static const StkFormat STK_FLOAT32; /*!< Normalized between plus/minus 1.0. */ + static const StkFormat STK_FLOAT64; /*!< Normalized between plus/minus 1.0. */ + + //! Static method which returns the current STK sample rate. + static StkFloat sampleRate(void) { return srate_; } + + //! Static method which sets the STK sample rate. + /*! + The sample rate set using this method is queried by all STK + classes which depend on its value. It is initialized to the + default SRATE set in Stk.h. Many STK classes use the sample rate + during instantiation. Therefore, if you wish to use a rate which + is different from the default rate, it is imperative that it be + set \e BEFORE STK objects are instantiated. + */ + static void setSampleRate(StkFloat rate) { if (rate > 0.0) srate_ = rate; } + + //! Static method which returns the current rawwave path. + static std::string rawwavePath(void) { return rawwavepath_; } + + //! Static method which sets the STK rawwave path. + static void setRawwavePath(std::string path); + + //! Static method which byte-swaps a 16-bit data type. + static void swap16(unsigned char *ptr); + + //! Static method which byte-swaps a 32-bit data type. + static void swap32(unsigned char *ptr); + + //! Static method which byte-swaps a 64-bit data type. + static void swap64(unsigned char *ptr); + + //! Static cross-platform method to sleep for a number of milliseconds. + static void sleep(unsigned long milliseconds); + + //! Static function for error reporting and handling using c-strings. + static void handleError( const char *message, StkError::Type type ); + + //! Static function for error reporting and handling using c++ strings. + static void handleError( std::string message, StkError::Type type ); + + //! Toggle display of WARNING and STATUS messages. + static void showWarnings( bool status ) { showWarnings_ = status; } + + //! Toggle display of error messages before throwing exceptions. + static void printErrors( bool status ) { printErrors_ = status; } + +private: + static StkFloat srate_; + static std::string rawwavepath_; + static bool showWarnings_; + static bool printErrors_; + +protected: + + std::ostringstream errorString_; + + //! Default constructor. + Stk(void); + + //! Class destructor. + virtual ~Stk(void); + + //! Internal function for error reporting which assumes message in \c errorString_ variable. + void handleError( StkError::Type type ); +}; + + +/***************************************************/ +/*! \class StkFrames + \brief An STK class to handle vectorized audio data. + + This class can hold single- or multi-channel audio data in either + interleaved or non-interleaved formats. The data type is always + StkFloat. In an effort to maintain efficiency, no out-of-bounds + checks are performed in this class. + + Possible future improvements in this class could include functions + to inter- or de-interleave the data and to convert to and return + other data types. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +class StkFrames +{ +public: + + //! The default constructor initializes the frame data structure to size zero. + StkFrames( unsigned int nFrames = 0, unsigned int nChannels = 0, bool interleaved = true ); + + //! Overloaded constructor that initializes the frame data to the specified size with \c value. + StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels, bool interleaved = true ); + + //! The destructor. + ~StkFrames(); + + //! Subscript operator which returns a reference to element \c n of self. + /*! + The result can be used as an lvalue . This reference is valid + until the resize function is called or the array is destroyed. The + index \c n must be between 0 and size less one. No range checking + is performed unless _STK_DEBUG_ is defined. + */ + StkFloat& operator[] ( size_t n ); + + //! Subscript operator that returns the value at element \c n of self. + /*! + The index \c n must be between 0 and size less one. No range + checking is performed unless _STK_DEBUG_ is defined. + */ + StkFloat operator[] ( size_t n ) const; + + //! Channel / frame subscript operator that returns a reference. + /*! + The result can be used as an lvalue. This reference is valid + until the resize function is called or the array is destroyed. The + \c frame index must be between 0 and frames() - 1. The \c channel + index must be between 0 and channels() - 1. No range checking is + performed unless _STK_DEBUG_ is defined. + */ + StkFloat& operator() ( size_t frame, unsigned int channel ); + + //! Channel / frame subscript operator that returns a value. + /*! + The \c frame index must be between 0 and frames() - 1. The \c + channel index must be between 0 and channels() - 1. No range checking + is performed unless _STK_DEBUG_ is defined. + */ + StkFloat operator() ( size_t frame, unsigned int channel ) const; + + //! Return an interpolated value at the fractional frame index and channel. + /*! + This function performs linear interpolation. The \c frame + index must be between 0.0 and frames() - 1. The \c channel index + must be between 0 and channels() - 1. No range checking is + performed unless _STK_DEBUG_ is defined. + */ + StkFloat interpolate( StkFloat frame, unsigned int channel = 0 ) const; + + //! Returns the total number of audio samples represented by the object. + size_t size() const { return size_; }; + + //! Returns \e true if the object size is zero and \e false otherwise. + bool empty() const; + + //! Resize self to represent the specified number of channels and frames. + /*! + Changes the size of self based on the number of frames and + channels. No element assignment is performed. No memory + deallocation occurs if the new size is smaller than the previous + size. Further, no new memory is allocated when the new size is + smaller or equal to a previously allocated size. + */ + void resize( size_t nFrames, unsigned int nChannels = 1 ); + + //! Resize self to represent the specified number of channels and frames and perform element initialization. + /*! + Changes the size of self based on the number of frames and + channels, and assigns \c value to every element. No memory + deallocation occurs if the new size is smaller than the previous + size. Further, no new memory is allocated when the new size is + smaller or equal to a previously allocated size. + */ + void resize( size_t nFrames, unsigned int nChannels, StkFloat value ); + + //! Return the number of channels represented by the data. + unsigned int channels( void ) const { return nChannels_; }; + + //! Return the number of sample frames represented by the data. + unsigned int frames( void ) const { return nFrames_; }; + + //! Set the sample rate associated with the StkFrames data. + /*! + By default, this value is set equal to the current STK sample + rate at the time of instantiation. + */ + void setDataRate( StkFloat rate ) { dataRate_ = rate; }; + + //! Return the sample rate associated with the StkFrames data. + /*! + By default, this value is set equal to the current STK sample + rate at the time of instantiation. + */ + StkFloat dataRate( void ) const { return dataRate_; }; + + //! Returns \c true if the data is in interleaved format, \c false if the data is non-interleaved. + bool interleaved( void ) const { return interleaved_; }; + + //! Set the flag to indicate whether the internal data is in interleaved (\c true) or non-interleaved (\c false) format. + /*! + Note that this function does not modify the internal data order + with respect to the argument value. It simply changes the + indicator flag value. + */ + void setInterleaved( bool isInterleaved ) { interleaved_ = isInterleaved; }; + +private: + + StkFloat *data_; + StkFloat dataRate_; + size_t nFrames_; + unsigned int nChannels_; + size_t size_; + size_t bufferSize_; + bool interleaved_; + +}; + + +// Here are a few other useful typedefs. +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef signed short SINT16; +typedef signed int SINT32; +typedef float FLOAT32; +typedef double FLOAT64; + +// The default sampling rate. +const StkFloat SRATE = 44100.0; + +// The default real-time audio input and output buffer size. If +// clicks are occuring in the input and/or output sound stream, a +// larger buffer size may help. Larger buffer sizes, however, produce +// more latency. +const unsigned int RT_BUFFER_SIZE = 512; + +// The default rawwave path value is set with the preprocessor +// definition RAWWAVE_PATH. This can be specified as an argument to +// the configure script, in an integrated development environment, or +// below. The global STK rawwave path variable can be dynamically set +// with the Stk::setRawwavePath() function. This value is +// concatenated to the beginning of all references to rawwave files in +// the various STK core classes (ex. Clarinet.cpp). If you wish to +// move the rawwaves directory to a different location in your file +// system, you will need to set this path definition appropriately. +#if !defined(RAWWAVE_PATH) + #define RAWWAVE_PATH "../../rawwaves/" +#endif + +const StkFloat PI = 3.14159265358979; +const StkFloat TWO_PI = 2 * PI; +const StkFloat ONE_OVER_128 = 0.0078125; + +#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_MM__) + #define __OS_WINDOWS__ + #define __STK_REALTIME__ +#elif defined(__LINUX_OSS__) || defined(__LINUX_ALSA__) || defined(__LINUX_JACK__) + #define __OS_LINUX__ + #define __STK_REALTIME__ +#elif defined(__IRIX_AL__) + #define __OS_IRIX__ + #define __STK_REALTIME__ +#elif defined(__MACOSX_CORE__) + #define __OS_MACOSX__ + #define __STK_REALTIME__ +#endif + +//#define _STK_DEBUG_ + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/WaveLoop.h b/nyqstk/include/WaveLoop.h new file mode 100644 index 0000000..67d345a --- /dev/null +++ b/nyqstk/include/WaveLoop.h @@ -0,0 +1,97 @@ +/***************************************************/ +/*! \class WaveLoop + \brief STK waveform oscillator class. + + This class inherits from FileWvIn and provides audio file looping + functionality. Any audio file that can be loaded by FileRead can + be looped using this class. + + WaveLoop supports multi-channel data. It is important to + distinguish the tick() methods, which return samples produced by + averaging across sample frames, from the tickFrame() methods, + which return references or pointers to multi-channel sample + frames. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_WAVELOOP_H +#define STK_WAVELOOP_H + +#include "FileWvIn.h" + +namespace Nyq +{ + +class WaveLoop : public FileWvIn +{ +public: + //! Default constructor. + WaveLoop( unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 ); + + //! Class constructor that opens a specified file. + WaveLoop( std::string fileName, bool raw = false, bool doNormalize = true, + unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 ); + + //! Class destructor. + virtual ~WaveLoop(); + + //! Open the specified file and load its data. + /*! + Data from a previously opened file will be overwritten by this + function. An StkError will be thrown if the file is not found, + its format is unknown, or a read error occurs. If the file data + is to be loaded incrementally from disk and normalization is + specified, a scaling will be applied with respect to fixed-point + limits. If the data format is floating-point, no scaling is + performed. + */ + void openFile( std::string fileName, bool raw = false, bool doNormalize = true ); + + //! Set the data read rate in samples. The rate can be negative. + /*! + If the rate value is negative, the data is read in reverse order. + */ + void setRate( StkFloat rate ); + + //! Set the data interpolation rate based on a looping frequency. + /*! + This function determines the interpolation rate based on the file + size and the current Stk::sampleRate. The \e frequency value + corresponds to file cycles per second. The frequency can be + negative, in which case the loop is read in reverse order. + */ + void setFrequency( StkFloat frequency ); + + //! Increment the read pointer by \e time samples, modulo file size. + void addTime( StkFloat time ); + + //! Increment current read pointer by \e angle, relative to a looping frequency. + /*! + This function increments the read pointer based on the file + size and the current Stk::sampleRate. The \e anAngle value + is a multiple of file size. + */ + void addPhase( StkFloat angle ); + + //! Add a phase offset to the current read pointer. + /*! + This function determines a time offset based on the file + size and the current Stk::sampleRate. The \e angle value + is a multiple of file size. + */ + void addPhaseOffset( StkFloat angle ); + +protected: + + virtual void computeFrame( void ); + + StkFrames firstFrame_; + StkFloat phaseOffset_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/include/WvIn.h b/nyqstk/include/WvIn.h new file mode 100644 index 0000000..a4ee60b --- /dev/null +++ b/nyqstk/include/WvIn.h @@ -0,0 +1,92 @@ +/***************************************************/ +/*! \class WvIn + \brief STK audio input abstract base class. + + This class provides common functionality for a variety of audio + data input subclasses. + + WvIn supports multi-channel data. It is important to distinguish + the tick() methods, which return samples produced by averaging + across sample frames, from the tickFrame() methods, which return + references or pointers to multi-channel sample frames. + + Both interleaved and non-interleaved data is supported via the use + of StkFrames objects. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#ifndef STK_WVIN_H +#define STK_WVIN_H + +#include "Stk.h" +#include + +namespace Nyq +{ + +class WvIn : public Stk +{ +public: + //! Default constructor. + WvIn(); + + //! Class destructor. + virtual ~WvIn(); + + //! Return the number of audio channels in the data. + unsigned int getChannels( void ) const { return data_.channels(); }; + + //! Return the average across the last output sample frame. + /*! + If no file data is loaded, the returned value is 0.0. + */ + StkFloat lastOut( void ) const; + + //! Return an StkFrames reference to the last output sample frame. + /*! + If no file data is loaded, an empty container is returned. + */ + const StkFrames& lastFrame( void ) const { return lastOutputs_; }; + + //! Read out the average across one sample frame of data. + /*! + If no file data is loaded, the returned value is 0.0. + */ + StkFloat tick( void ); + + //! Fill a channel of the StkFrames object with averaged sample frames. + /*! + The \c channel argument should be zero or greater (the first + channel is specified by 0). An StkError will be thrown if the \c + channel argument is greater than or equal to the number of + channels in the StkFrames object. If no file data is loaded, the + container is filled with zeroes. + */ + StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); + + //! Fill the StkFrames argument with data and return the same reference. + /*! + An StkError will be thrown if there is an incompatability + between the number of channels in the loaded data and that in the + StkFrames argument. If no file data is loaded, the container is + filled with zeroes. + */ + StkFrames& tickFrame( StkFrames& frames ); + +protected: + + // This abstract function must be implemented in all subclasses. + // It is used to get around a C++ problem with overloaded virtual + // functions. + virtual void computeFrame( void ) = 0; + + StkFrames data_; + StkFrames lastOutputs_; + +}; + +} // namespace Nyq + +#endif diff --git a/nyqstk/instr.cpp b/nyqstk/instr.cpp new file mode 100644 index 0000000..e39567a --- /dev/null +++ b/nyqstk/instr.cpp @@ -0,0 +1,104 @@ +#include "instr.h" +#include "Instrmnt.h" +#include "Clarinet.h" +#include "Saxofony.h" +#include "Bowed.h" +#include "BandedWG.h" +#include "Mandolin.h" +#include "Sitar.h" +#include "ModalBar.h" +#include "Flute.h" +#include "stdlib.h" +#include "string.h" + +using namespace Nyq; + +/* C interface to Instrmnt */ + +struct instr { + Instrmnt *instrObjPtr; +}; + + + +struct instr *initInstrument(int instr_type, int sample_rate) { + struct instr *in = (struct instr *) malloc(sizeof(struct instr)); + Stk::setSampleRate(sample_rate); + switch(instr_type) { + case CLARINET: + in->instrObjPtr = new Clarinet(10.0); + break; + case SAXOFONY: + in->instrObjPtr = new Saxofony(10.0); + break; + case BOWED: + in->instrObjPtr = new Bowed(10.0); + break; + case BANDEDWG: + in->instrObjPtr = new BandedWG(); + break; + case MANDOLIN: + in->instrObjPtr = new Mandolin(10.0); + break; + case SITAR: + in->instrObjPtr = new Sitar(10.0); + break; + case MODALBAR: + in->instrObjPtr = new ModalBar(); + break; + case FLUTE: + in->instrObjPtr = new Flute(10.0); + break; + default: + return NULL; + } + return in; +} + +int deleteInstrument(struct instr* in) { + delete(in->instrObjPtr); + free(in); + return 0; +} + +//! Start a note with the given frequency and amplitude. +int noteOn(struct instr* in, ::MY_FLOAT frequency, ::MY_FLOAT amplitude) { + in->instrObjPtr->noteOn(frequency, amplitude); + return 0; +} + +//! Stop a note with the given amplitude (speed of decay). +int noteOff(struct instr* in, ::MY_FLOAT amplitude) { + in->instrObjPtr->noteOff(amplitude); + return 0; +} + +//! Set instrument parameters for a particular frequency. +int setFrequency(struct instr* in, ::MY_FLOAT frequency) { + in->instrObjPtr->setFrequency(frequency); + return 0; +} + +//! Return the last output value. +/* +MY_FLOAT lastOut(struct instr* in) { + return in->instrObjPtr->lastOut(); +} +*/ + +//! Compute one output sample. +::MY_FLOAT tick(struct instr* in) { + return in->instrObjPtr->tick(); +} + +// DELETED THIS. PJM +//! Computer \e vectorSize outputs and return them in \e vector. +//MY_FLOAT *multTicks(struct instr* in, MY_FLOAT *vector, unsigned int vectorSize) { +// return in->instrObjPtr->tick(vector, vectorSize); +//} + +//! Perform the control change specified by \e number and \e value (0.0 - 128.0). +int controlChange(struct instr* in, int number, ::MY_FLOAT value) { + in->instrObjPtr->controlChange(number, value); + return 0; +} diff --git a/nyqstk/instr.h b/nyqstk/instr.h new file mode 100644 index 0000000..71df55c --- /dev/null +++ b/nyqstk/instr.h @@ -0,0 +1,54 @@ +#ifndef _INSTR_H +#define _INSTR_H + +#include "globals.h" + +/* C interface to Instrmnt */ + +/* Instrument types */ +#define CLARINET 0 +#define SAXOFONY 1 +#define BOWED 2 +#define BANDEDWG 3 +#define MANDOLIN 4 +#define SITAR 5 +#define MODALBAR 6 +#define FLUTE 7 + + + +struct instr; + +#ifdef __cplusplus +extern "C" { +#endif + +struct stkgen *initStkGen(); +int deleteStkGen(struct stkgen *); +MY_FLOAT gentick(struct stkgen *); + +void setrawwavepath(char *); +struct instr *initInstrument(int instr_type, int sample_rate); + +int deleteInstrument(struct instr* in); + +int noteOn(struct instr* in, MY_FLOAT frequency, MY_FLOAT amplitude); + +int noteOff(struct instr* in, MY_FLOAT amplitude); + +int setFrequency(struct instr* in, MY_FLOAT frequency); + +//MY_FLOAT lastOut(struct instr* in); + +MY_FLOAT tick(struct instr* in); + +//MY_FLOAT *multTicks(struct instr* in, MY_FLOAT *vector, unsigned int vectorSize); + +int controlChange(struct instr* in, int number, MY_FLOAT value); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/nyqstk/src/ADSR.cpp b/nyqstk/src/ADSR.cpp new file mode 100644 index 0000000..2b7dd92 --- /dev/null +++ b/nyqstk/src/ADSR.cpp @@ -0,0 +1,191 @@ +/***************************************************/ +/*! \class ADSR + \brief STK ADSR envelope class. + + This Envelope subclass implements a + traditional ADSR (Attack, Decay, + Sustain, Release) envelope. It + responds to simple keyOn and keyOff + messages, keeping track of its state. + The \e state = ADSR::DONE after the + envelope value reaches 0.0 in the + ADSR::RELEASE state. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "ADSR.h" + +using namespace Nyq; + +ADSR :: ADSR() : Envelope() +{ + target_ = 0.0; + value_ = 0.0; + attackRate_ = 0.001; + decayRate_ = 0.001; + sustainLevel_ = 0.5; + releaseRate_ = 0.01; + state_ = ATTACK; +} + +ADSR :: ~ADSR() +{ +} + +void ADSR :: keyOn() +{ + target_ = 1.0; + rate_ = attackRate_; + state_ = ATTACK; +} + +void ADSR :: keyOff() +{ + target_ = 0.0; + rate_ = releaseRate_; + state_ = RELEASE; +} + +void ADSR :: setAttackRate(StkFloat rate) +{ + if (rate < 0.0) { + errorString_ << "ADSR::setAttackRate: negative rates not allowed ... correcting!"; + handleError( StkError::WARNING ); + attackRate_ = -rate; + } + else attackRate_ = rate; +} + +void ADSR :: setDecayRate(StkFloat rate) +{ + if (rate < 0.0) { + errorString_ << "ADSR::setDecayRate: negative rates not allowed ... correcting!"; + handleError( StkError::WARNING ); + decayRate_ = -rate; + } + else decayRate_ = rate; +} + +void ADSR :: setSustainLevel(StkFloat level) +{ + if (level < 0.0 ) { + errorString_ << "ADSR::setSustainLevel: level out of range ... correcting!"; + handleError( StkError::WARNING ); + sustainLevel_ = 0.0; + } + else sustainLevel_ = level; +} + +void ADSR :: setReleaseRate(StkFloat rate) +{ + if (rate < 0.0) { + errorString_ << "ADSR::setReleaseRate: negative rates not allowed ... correcting!"; + handleError( StkError::WARNING ); + releaseRate_ = -rate; + } + else releaseRate_ = rate; +} + +void ADSR :: setAttackTime(StkFloat time) +{ + if (time < 0.0) { + errorString_ << "ADSR::setAttackTime: negative times not allowed ... correcting!"; + handleError( StkError::WARNING ); + attackRate_ = 1.0 / ( -time * Stk::sampleRate() ); + } + else attackRate_ = 1.0 / ( time * Stk::sampleRate() ); +} + +void ADSR :: setDecayTime(StkFloat time) +{ + if (time < 0.0) { + errorString_ << "ADSR::setDecayTime: negative times not allowed ... correcting!"; + handleError( StkError::WARNING ); + decayRate_ = 1.0 / ( -time * Stk::sampleRate() ); + } + else decayRate_ = 1.0 / ( time * Stk::sampleRate() ); +} + +void ADSR :: setReleaseTime(StkFloat time) +{ + if (time < 0.0) { + errorString_ << "ADSR::setReleaseTime: negative times not allowed ... correcting!"; + handleError( StkError::WARNING ); + releaseRate_ = sustainLevel_ / ( -time * Stk::sampleRate() ); + } + else releaseRate_ = sustainLevel_ / ( time * Stk::sampleRate() ); +} + +void ADSR :: setAllTimes(StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime) +{ + this->setAttackTime(aTime); + this->setDecayTime(dTime); + this->setSustainLevel(sLevel); + this->setReleaseTime(rTime); +} + +void ADSR :: setTarget(StkFloat target) +{ + target_ = target; + if (value_ < target_) { + state_ = ATTACK; + this->setSustainLevel(target_); + rate_ = attackRate_; + } + if (value_ > target_) { + this->setSustainLevel(target_); + state_ = DECAY; + rate_ = decayRate_; + } +} + +void ADSR :: setValue(StkFloat value) +{ + state_ = SUSTAIN; + target_ = value; + value_ = value; + this->setSustainLevel(value); + rate_ = (StkFloat) 0.0; +} + +int ADSR :: getState(void) const +{ + return state_; +} + +StkFloat ADSR :: computeSample() +{ + switch (state_) { + + case ATTACK: + value_ += rate_; + if (value_ >= target_) { + value_ = target_; + rate_ = decayRate_; + target_ = sustainLevel_; + state_ = DECAY; + } + break; + + case DECAY: + value_ -= decayRate_; + if (value_ <= sustainLevel_) { + value_ = sustainLevel_; + rate_ = (StkFloat) 0.0; + state_ = SUSTAIN; + } + break; + + case RELEASE: + value_ -= releaseRate_; + if (value_ <= 0.0) { + value_ = (StkFloat) 0.0; + state_ = DONE; + } + } + + lastOutput_ = value_; + return value_; +} diff --git a/nyqstk/src/BandedWG.cpp b/nyqstk/src/BandedWG.cpp new file mode 100644 index 0000000..05a72fa --- /dev/null +++ b/nyqstk/src/BandedWG.cpp @@ -0,0 +1,380 @@ +/***************************************************/ +/*! \class BandedWG + \brief Banded waveguide modeling class. + + This class uses banded waveguide techniques to + model a variety of sounds, including bowed + bars, glasses, and bowls. For more + information, see Essl, G. and Cook, P. "Banded + Waveguides: Towards Physical Modelling of Bar + Percussion Instruments", Proceedings of the + 1999 International Computer Music Conference. + + Control Change Numbers: + - Bow Pressure = 2 + - Bow Motion = 4 + - Strike Position = 8 (not implemented) + - Vibrato Frequency = 11 + - Gain = 1 + - Bow Velocity = 128 + - Set Striking = 64 + - Instrument Presets = 16 + - Uniform Bar = 0 + - Tuned Bar = 1 + - Glass Harmonica = 2 + - Tibetan Bowl = 3 + + by Georg Essl, 1999 - 2004. + Modified for Stk 4.0 by Gary Scavone. +*/ +/***************************************************/ + +#include "BandedWG.h" +#include "SKINI.msg" +#include + +using namespace Nyq; + +BandedWG :: BandedWG() +{ + doPluck_ = true; + + bowTable_.setSlope( 3.0 ); + adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01); + + frequency_ = 220.0; + this->setPreset(0); + + bowPosition_ = 0; + baseGain_ = (StkFloat) 0.999; + + integrationConstant_ = 0.0; + trackVelocity_ = false; + + bowVelocity_ = 0.0; + bowTarget_ = 0.0; + + strikeAmp_ = 0.0; +} + +BandedWG :: ~BandedWG() +{ +} + +void BandedWG :: clear() +{ + for (int i=0; i 1568.0) frequency_ = 1568.0; + + StkFloat radius; + StkFloat base = Stk::sampleRate() / frequency_; + StkFloat length; + for (int i=0; i 2.0) { + delay_[i].setDelay( length ); + gains_[i]=basegains_[i]; + // gains_[i]=(StkFloat) pow(basegains_[i], 1/((StkFloat)delay_[i].getDelay())); + // std::cerr << gains_[i]; + } + else { + nModes_ = i; + break; + } + // std::cerr << std::endl; + + // Set the bandpass filter resonances + radius = 1.0 - PI * 32 / Stk::sampleRate(); //frequency_ * modes_[i] / Stk::sampleRate()/32; + if ( radius < 0.0 ) radius = 0.0; + bandpass_[i].setResonance(frequency_ * modes_[i], radius, true); + + delay_[i].clear(); + bandpass_[i].clear(); + } + + //int olen = (int)(delay_[0].getDelay()); + //strikePosition_ = (int)(strikePosition_*(length/modes_[0])/olen); +} + +void BandedWG :: setStrikePosition(StkFloat position) +{ + strikePosition_ = (int)(delay_[0].getDelay() * position / 2.0); +} + +void BandedWG :: startBowing(StkFloat amplitude, StkFloat rate) +{ + adsr_.setRate(rate); + adsr_.keyOn(); + maxVelocity_ = 0.03 + (0.1 * amplitude); +} + +void BandedWG :: stopBowing(StkFloat rate) +{ + adsr_.setRate(rate); + adsr_.keyOff(); +} + +void BandedWG :: pluck(StkFloat amplitude) +{ + int j; + StkFloat min_len = delay_[nModes_-1].getDelay(); + for (int i=0; isetFrequency(frequency); + + if ( doPluck_ ) + this->pluck(amplitude); + else + this->startBowing(amplitude, amplitude * 0.001); + +#if defined(_STK_DEBUG_) + errorString_ << "BandedWG::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void BandedWG :: noteOff(StkFloat amplitude) +{ + if ( !doPluck_ ) + this->stopBowing((1.0 - amplitude) * 0.005); + +#if defined(_STK_DEBUG_) + errorString_ << "BandedWG::NoteOff: amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +StkFloat BandedWG :: computeSample() +{ + int k; + + StkFloat input = 0.0; + if ( doPluck_ ) { + input = 0.0; + // input = strikeAmp_/nModes_; + // strikeAmp_ = 0.0; + } + else { + if (integrationConstant_ == 0.0) + velocityInput_ = 0.0; + else + velocityInput_ = integrationConstant_ * velocityInput_; + + for (k=0; k 1.0 ) { + norm = 1.0; + errorString_ << "BandedWG::controlChange: control value greater than 128.0 ... setting to 128.0!"; + handleError( StkError::WARNING ); + } + + if (number == __SK_BowPressure_) { // 2 + if ( norm == 0.0 ) + doPluck_ = true; + else { + doPluck_ = false; + bowTable_.setSlope( 10.0 - (9.0 * norm)); + } + } + else if (number == 4) { // 4 + if ( !trackVelocity_ ) trackVelocity_ = true; + bowTarget_ += 0.005 * (norm - bowPosition_); + bowPosition_ = norm; + //adsr_.setTarget(bowPosition_); + } + else if (number == 8) // 8 + this->setStrikePosition( norm ); + else if (number == __SK_AfterTouch_Cont_) { // 128 + //bowTarget_ += 0.02 * (norm - bowPosition_); + //bowPosition_ = norm; + if ( trackVelocity_ ) trackVelocity_ = false; + maxVelocity_ = 0.13 * norm; + adsr_.setTarget(norm); + } + else if (number == __SK_ModWheel_) { // 1 + // baseGain_ = 0.9989999999 + (0.001 * norm ); + baseGain_ = 0.8999999999999999 + (0.1 * norm); + // std::cerr << "Yuck!" << std::endl; + for (int i=0; isetPreset((int) value); + else { + errorString_ << "BandedWG::controlChange: undefined control number (" << number << ")!"; + handleError( StkError::WARNING ); + } + +#if defined(_STK_DEBUG_) + errorString_ << "BandedWG::controlChange: number = " << number << ", value = " << value << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + + diff --git a/nyqstk/src/BiQuad.cpp b/nyqstk/src/BiQuad.cpp new file mode 100644 index 0000000..7434f4b --- /dev/null +++ b/nyqstk/src/BiQuad.cpp @@ -0,0 +1,126 @@ +/***************************************************/ +/*! \class BiQuad + \brief STK biquad (two-pole, two-zero) filter class. + + This protected Filter subclass implements a + two-pole, two-zero digital filter. A method + is provided for creating a resonance in the + frequency response while maintaining a constant + filter gain. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "BiQuad.h" +#include + +using namespace Nyq; + +BiQuad :: BiQuad() : Filter() +{ + std::vector b(3, 0.0); + std::vector a(3, 0.0); + b[0] = 1.0; + a[0] = 1.0; + Filter::setCoefficients( b, a ); +} + +BiQuad :: ~BiQuad() +{ +} + +void BiQuad :: clear(void) +{ + Filter::clear(); +} + +void BiQuad :: setB0(StkFloat b0) +{ + b_[0] = b0; +} + +void BiQuad :: setB1(StkFloat b1) +{ + b_[1] = b1; +} + +void BiQuad :: setB2(StkFloat b2) +{ + b_[2] = b2; +} + +void BiQuad :: setA1(StkFloat a1) +{ + a_[1] = a1; +} + +void BiQuad :: setA2(StkFloat a2) +{ + a_[2] = a2; +} + +void BiQuad :: setResonance(StkFloat frequency, StkFloat radius, bool normalize) +{ + a_[2] = radius * radius; + a_[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate()); + + if ( normalize ) { + // Use zeros at +- 1 and normalize the filter peak gain. + b_[0] = 0.5 - 0.5 * a_[2]; + b_[1] = 0.0; + b_[2] = -b_[0]; + } +} + +void BiQuad :: setNotch(StkFloat frequency, StkFloat radius) +{ + // This method does not attempt to normalize the filter gain. + b_[2] = radius * radius; + b_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate()); +} + +void BiQuad :: setEqualGainZeroes() +{ + b_[0] = 1.0; + b_[1] = 0.0; + b_[2] = -1.0; +} + +void BiQuad :: setGain(StkFloat gain) +{ + Filter::setGain(gain); +} + +StkFloat BiQuad :: getGain(void) const +{ + return Filter::getGain(); +} + +StkFloat BiQuad :: lastOut(void) const +{ + return Filter::lastOut(); +} + +StkFloat BiQuad :: computeSample( StkFloat input ) +{ + inputs_[0] = gain_ * input; + outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2]; + outputs_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1]; + inputs_[2] = inputs_[1]; + inputs_[1] = inputs_[0]; + outputs_[2] = outputs_[1]; + outputs_[1] = outputs_[0]; + + return outputs_[0]; +} + +StkFloat BiQuad :: tick( StkFloat input ) +{ + return this->computeSample( input ); +} + +StkFrames& BiQuad :: tick( StkFrames& frames, unsigned int channel ) +{ + return Filter::tick( frames, channel ); +} diff --git a/nyqstk/src/BowTable.cpp b/nyqstk/src/BowTable.cpp new file mode 100644 index 0000000..69069a4 --- /dev/null +++ b/nyqstk/src/BowTable.cpp @@ -0,0 +1,53 @@ +/***************************************************/ +/*! \class BowTable + \brief STK bowed string table class. + + This class implements a simple bowed string + non-linear function, as described by Smith (1986). + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "BowTable.h" +#include + +using namespace Nyq; + +BowTable :: BowTable() +{ + offset_ = (StkFloat) 0.0; + slope_ = (StkFloat) 0.1; +} + +BowTable :: ~BowTable() +{ +} + +void BowTable :: setOffset(StkFloat offset) +{ + offset_ = offset; +} + +void BowTable :: setSlope(StkFloat slope) +{ + slope_ = slope; +} + +StkFloat BowTable :: computeSample(StkFloat input) +{ + // The input represents differential string vs. bow velocity. + StkFloat sample; + sample = input + offset_; // add bias to input + sample *= slope_; // then scale it + lastOutput_ = (StkFloat) fabs( (double) sample ) + (StkFloat) 0.75; + lastOutput_ = (StkFloat) pow( lastOutput_, (StkFloat) -4.0 ); + + // Set minimum friction to 0.0 + // if (lastOutput < 0.0 ) lastOutput = 0.0; + // Set maximum friction to 1.0. + if (lastOutput_ > 1.0 ) lastOutput_ = (StkFloat) 1.0; + + return lastOutput_; +} + diff --git a/nyqstk/src/Bowed.cpp b/nyqstk/src/Bowed.cpp new file mode 100644 index 0000000..29b9c59 --- /dev/null +++ b/nyqstk/src/Bowed.cpp @@ -0,0 +1,189 @@ +/***************************************************/ +/*! \class Bowed + \brief STK bowed string instrument class. + + This class implements a bowed string model, a + la Smith (1986), after McIntyre, Schumacher, + Woodhouse (1983). + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + + Control Change Numbers: + - Bow Pressure = 2 + - Bow Position = 4 + - Vibrato Frequency = 11 + - Vibrato Gain = 1 + - Volume = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Bowed.h" +#include "SKINI.msg" + +using namespace Nyq; + +Bowed :: Bowed(StkFloat lowestFrequency) +{ + unsigned long length; + length = (long) ( Stk::sampleRate() / lowestFrequency + 1 ); + neckDelay_.setMaximumDelay( length ); + neckDelay_.setDelay( 100.0 ); + + length >>= 1; + bridgeDelay_.setMaximumDelay( length ); + bridgeDelay_.setDelay( 29.0 ); + + bowTable_.setSlope(3.0 ); + + vibrato_.setFrequency( 6.12723 ); + vibratoGain_ = 0.0; + + stringFilter_.setPole( 0.6 - (0.1 * 22050.0 / Stk::sampleRate()) ); + stringFilter_.setGain( 0.95 ); + + bodyFilter_.setResonance( 500.0, 0.85, true ); + bodyFilter_.setGain( 0.2 ); + + adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01 ); + + betaRatio_ = 0.127236; + + // Necessary to initialize internal variables. + this->setFrequency( 220.0 ); +} + +Bowed :: ~Bowed() +{ +} + +void Bowed :: clear() +{ + neckDelay_.clear(); + bridgeDelay_.clear(); +} + +void Bowed :: setFrequency(StkFloat frequency) +{ + StkFloat freakency = frequency; + if ( frequency <= 0.0 ) { + errorString_ << "Bowed::setFrequency: parameter is less than or equal to zero!"; + handleError( StkError::WARNING ); + freakency = 220.0; + } + + // Delay = length - approximate filter delay. + baseDelay_ = Stk::sampleRate() / freakency - 4.0; + if ( baseDelay_ <= 0.0 ) baseDelay_ = 0.3; + bridgeDelay_.setDelay( baseDelay_ * betaRatio_ ); // bow to bridge length + neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) ); // bow to nut (finger) length +} + +void Bowed :: startBowing(StkFloat amplitude, StkFloat rate) +{ + adsr_.setRate( rate ); + adsr_.keyOn(); + maxVelocity_ = 0.03 + ( 0.2 * amplitude ); +} + +void Bowed :: stopBowing(StkFloat rate) +{ + adsr_.setRate( rate ); + adsr_.keyOff(); +} + +void Bowed :: noteOn(StkFloat frequency, StkFloat amplitude) +{ + this->startBowing( amplitude, amplitude * 0.001 ); + this->setFrequency( frequency ); + +#if defined(_STK_DEBUG_) + errorString_ << "Bowed::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Bowed :: noteOff(StkFloat amplitude) +{ + this->stopBowing( (1.0 - amplitude) * 0.005 ); + +#if defined(_STK_DEBUG_) + errorString_ << "Bowed::NoteOff: amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Bowed :: setVibrato(StkFloat gain) +{ + vibratoGain_ = gain; +} + +StkFloat Bowed :: computeSample() +{ + StkFloat bowVelocity; + StkFloat bridgeRefl; + StkFloat nutRefl; + StkFloat newVel; + StkFloat velDiff; + StkFloat stringVel; + + bowVelocity = maxVelocity_ * adsr_.tick(); + + bridgeRefl = -stringFilter_.tick( bridgeDelay_.lastOut() ); + nutRefl = -neckDelay_.lastOut(); + stringVel = bridgeRefl + nutRefl; // Sum is String Velocity + velDiff = bowVelocity - stringVel; // Differential Velocity + newVel = velDiff * bowTable_.tick( velDiff ); // Non-Linear Bow Function + neckDelay_.tick(bridgeRefl + newVel); // Do string propagations + bridgeDelay_.tick(nutRefl + newVel); + + if ( vibratoGain_ > 0.0 ) { + neckDelay_.setDelay( (baseDelay_ * (1.0 - betaRatio_) ) + + (baseDelay_ * vibratoGain_ * vibrato_.tick()) ); + } + + lastOutput_ = bodyFilter_.tick( bridgeDelay_.lastOut() ); + + return lastOutput_; +} + +void Bowed :: controlChange(int number, StkFloat value) +{ + StkFloat norm = value * ONE_OVER_128; + if ( norm < 0 ) { + norm = 0.0; + errorString_ << "Bowed::controlChange: control value less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + } + else if ( norm > 1.0 ) { + norm = 1.0; + errorString_ << "Bowed::controlChange: control value greater than 128.0 ... setting to 128.0!"; + handleError( StkError::WARNING ); + } + + if (number == __SK_BowPressure_) // 2 + bowTable_.setSlope( 5.0 - (4.0 * norm) ); + else if (number == __SK_BowPosition_) { // 4 + betaRatio_ = 0.027236 + (0.2 * norm); + bridgeDelay_.setDelay( baseDelay_ * betaRatio_ ); + neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) ); + } + else if (number == __SK_ModFrequency_) // 11 + vibrato_.setFrequency( norm * 12.0 ); + else if (number == __SK_ModWheel_) // 1 + vibratoGain_ = ( norm * 0.4 ); + else if (number == __SK_AfterTouch_Cont_) // 128 + adsr_.setTarget(norm); + else { + errorString_ << "Bowed::controlChange: undefined control number (" << number << ")!"; + handleError( StkError::WARNING ); + } + +#if defined(_STK_DEBUG_) + errorString_ << "Bowed::controlChange: number = " << number << ", value = " << value << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} diff --git a/nyqstk/src/Chorus.cpp b/nyqstk/src/Chorus.cpp new file mode 100644 index 0000000..79929ba --- /dev/null +++ b/nyqstk/src/Chorus.cpp @@ -0,0 +1,63 @@ +/***************************************************/ +/*! \class Chorus + \brief STK chorus effect class. + + This class implements a chorus effect. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Chorus.h" +#include + +using namespace Nyq; + +Chorus :: Chorus(StkFloat baseDelay) +{ + delayLine_[0].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2); + delayLine_[0].setDelay( baseDelay ); + delayLine_[1].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2); + delayLine_[1].setDelay( baseDelay ); + baseLength_ = baseDelay; + + mods_[0].setFrequency(0.2); + mods_[1].setFrequency(0.222222); + modDepth_ = 0.05; + effectMix_ = 0.5; + this->clear(); +} + +Chorus :: ~Chorus() +{ +} + +void Chorus :: clear() +{ + delayLine_[0].clear(); + delayLine_[1].clear(); + lastOutput_[0] = 0.0; + lastOutput_[1] = 0.0; +} + +void Chorus :: setModDepth(StkFloat depth) +{ + modDepth_ = depth; +} + +void Chorus :: setModFrequency(StkFloat frequency) +{ + mods_[0].setFrequency(frequency); + mods_[1].setFrequency(frequency * 1.1111); +} + +StkFloat Chorus :: computeSample(StkFloat input) +{ + delayLine_[0].setDelay( baseLength_ * 0.707 * (1.0 + modDepth_ * mods_[0].tick()) ); + delayLine_[1].setDelay( baseLength_ * 0.5 * (1.0 - modDepth_ * mods_[1].tick()) ); + lastOutput_[0] = input * (1.0 - effectMix_); + lastOutput_[0] += effectMix_ * delayLine_[0].tick(input); + lastOutput_[1] = input * (1.0 - effectMix_); + lastOutput_[1] += effectMix_ * delayLine_[1].tick(input); + return Effect::lastOut(); +} diff --git a/nyqstk/src/Clarinet.cpp b/nyqstk/src/Clarinet.cpp new file mode 100644 index 0000000..7d910cd --- /dev/null +++ b/nyqstk/src/Clarinet.cpp @@ -0,0 +1,162 @@ +/***************************************************/ +/*! \class Clarinet + \brief STK clarinet physical model class. + + This class implements a simple clarinet + physical model, as discussed by Smith (1986), + McIntyre, Schumacher, Woodhouse (1983), and + others. + + This is a digital waveguide model, making its + use possibly subject to patents held by Stanford + University, Yamaha, and others. + + Control Change Numbers: + - Reed Stiffness = 2 + - Noise Gain = 4 + - Vibrato Frequency = 11 + - Vibrato Gain = 1 + - Breath Pressure = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Clarinet.h" +#include "SKINI.msg" + +using namespace Nyq; + +Clarinet :: Clarinet(StkFloat lowestFrequency) +{ + length_ = (long) (Stk::sampleRate() / lowestFrequency + 1); + delayLine_.setMaximumDelay( length_ ); + delayLine_.setDelay( length_ / 2.0 ); + reedTable_.setOffset((StkFloat) 0.7); + reedTable_.setSlope((StkFloat) -0.3); + + vibrato_.setFrequency((StkFloat) 5.735); + outputGain_ = (StkFloat) 1.0; + noiseGain_ = (StkFloat) 0.2; + vibratoGain_ = (StkFloat) 0.1; +} + +Clarinet :: ~Clarinet() +{ +} + +void Clarinet :: clear() +{ + delayLine_.clear(); + filter_.tick((StkFloat) 0.0); +} + +void Clarinet :: setFrequency(StkFloat frequency) +{ + StkFloat freakency = frequency; + if ( frequency <= 0.0 ) { + errorString_ << "Clarinet::setFrequency: parameter is less than or equal to zero!"; + handleError( StkError::WARNING ); + freakency = 220.0; + } + + // Delay = length - approximate filter delay. + StkFloat delay = (Stk::sampleRate() / freakency) * 0.5 - 1.5; + if (delay <= 0.0) delay = 0.3; + else if (delay > length_) delay = length_; + delayLine_.setDelay(delay); +} + +void Clarinet :: startBlowing(StkFloat amplitude, StkFloat rate) +{ + envelope_.setRate(rate); + envelope_.setTarget(amplitude); +} + +void Clarinet :: stopBlowing(StkFloat rate) +{ + envelope_.setRate(rate); + envelope_.setTarget((StkFloat) 0.0); +} + +void Clarinet :: noteOn(StkFloat frequency, StkFloat amplitude) +{ + this->setFrequency(frequency); + this->startBlowing((StkFloat) 0.55 + (amplitude * (StkFloat) 0.30), amplitude * (StkFloat) 0.005); + outputGain_ = amplitude + (StkFloat) 0.001; + +#if defined(_STK_DEBUG_) + errorString_ << "Clarinet::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.'; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Clarinet :: noteOff(StkFloat amplitude) +{ + this->stopBlowing( amplitude * 0.01 ); + +#if defined(_STK_DEBUG_) + errorString_ << "Clarinet::NoteOff: amplitude = " << amplitude << '.'; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +StkFloat Clarinet :: computeSample() +{ + StkFloat pressureDiff; + StkFloat breathPressure; + + // Calculate the breath pressure (envelope + noise + vibrato) + breathPressure = envelope_.tick(); + breathPressure += breathPressure * noiseGain_ * noise_.tick(); + breathPressure += breathPressure * vibratoGain_ * vibrato_.tick(); + + // Perform commuted loss filtering. + pressureDiff = -0.95 * filter_.tick(delayLine_.lastOut()); + + // Calculate pressure difference of reflected and mouthpiece pressures. + pressureDiff = pressureDiff - breathPressure; + + // Perform non-linear scattering using pressure difference in reed function. + lastOutput_ = delayLine_.tick(breathPressure + pressureDiff * reedTable_.tick(pressureDiff)); + + // Apply output gain. + lastOutput_ *= outputGain_; + + return lastOutput_; +} + +void Clarinet :: controlChange(int number, StkFloat value) +{ + StkFloat norm = value * ONE_OVER_128; + if ( norm < 0 ) { + norm = 0.0; + errorString_ << "Clarinet::controlChange: control value less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + } + else if ( norm > 1.0 ) { + norm = 1.0; + errorString_ << "Clarinet::controlChange: control value greater than 128.0 ... setting to 128.0!"; + handleError( StkError::WARNING ); + } + + if (number == __SK_ReedStiffness_) // 2 + reedTable_.setSlope((StkFloat) -0.44 + ( (StkFloat) 0.26 * norm )); + else if (number == __SK_NoiseLevel_) // 4 + noiseGain_ = (norm * (StkFloat) 0.4); + else if (number == __SK_ModFrequency_) // 11 + vibrato_.setFrequency((norm * (StkFloat) 12.0)); + else if (number == __SK_ModWheel_) // 1 + vibratoGain_ = (norm * (StkFloat) 0.5); + else if (number == __SK_AfterTouch_Cont_) // 128 + envelope_.setValue(norm); + else { + errorString_ << "Clarinet::controlChange: undefined control number (" << number << ")!"; + handleError( StkError::WARNING ); + } + +#if defined(_STK_DEBUG_) + errorString_ << "Clarinet::controlChange: number = " << number << ", value = " << value << '.'; + handleError( StkError::DEBUG_WARNING ); +#endif +} diff --git a/nyqstk/src/Delay.cpp b/nyqstk/src/Delay.cpp new file mode 100644 index 0000000..b5e3a3f --- /dev/null +++ b/nyqstk/src/Delay.cpp @@ -0,0 +1,197 @@ +/***************************************************/ +/*! \class Delay + \brief STK non-interpolating delay line class. + + This protected Filter subclass implements + a non-interpolating digital delay-line. + A fixed maximum length of 4095 and a delay + of zero is set using the default constructor. + Alternatively, the delay and maximum length + can be set during instantiation with an + overloaded constructor. + + A non-interpolating delay line is typically + used in fixed delay-length applications, such + as for reverberation. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Delay.h" + +using namespace Nyq; + +Delay :: Delay() : Filter() +{ + // Default maximum delay length set to 4095. + inputs_.resize( 4096 ); + this->clear(); + + inPoint_ = 0; + outPoint_ = 0; + delay_ = 0; +} + +Delay :: Delay(unsigned long delay, unsigned long maxDelay) +{ + // Writing before reading allows delays from 0 to length-1. + // If we want to allow a delay of maxDelay, we need a + // delay-line of length = maxDelay+1. + if ( maxDelay < 1 ) { + errorString_ << "Delay::Delay: maxDelay must be > 0!\n"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( delay > maxDelay ) { + errorString_ << "Delay::Delay: maxDelay must be > than delay argument!\n"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( maxDelay > inputs_.size()-1 ) { + inputs_.resize( maxDelay+1 ); + this->clear(); + } + + inPoint_ = 0; + this->setDelay( delay ); +} + +Delay :: ~Delay() +{ +} + +void Delay :: clear(void) +{ + for (unsigned int i=0; i inputs_.size() - 1 ) { // The value is too big. + errorString_ << "Delay::setDelay: argument (" << delay << ") too big ... setting to maximum!\n"; + handleError( StkError::WARNING ); + + // Force delay to maximum length. + outPoint_ = inPoint_ + 1; + if ( outPoint_ == inputs_.size() ) outPoint_ = 0; + delay_ = inputs_.size() - 1; + } + else if ( delay < 0 ) { + errorString_ << "Delay::setDelay: argument (" << delay << ") less than zero ... setting to zero!\n"; + handleError( StkError::WARNING ); + + outPoint_ = inPoint_; + delay_ = 0; + } + else { // read chases write + if ( inPoint_ >= delay ) outPoint_ = inPoint_ - delay; + else outPoint_ = inputs_.size() + inPoint_ - delay; + delay_ = delay; + } +} + +unsigned long Delay :: getDelay(void) const +{ + return (unsigned long) delay_; +} + +StkFloat Delay :: energy(void) const +{ + unsigned long i; + register StkFloat e = 0; + if (inPoint_ >= outPoint_) { + for (i=outPoint_; i delay_) { + errorString_ << "Delay::contentsAt: argument (" << tapDelay << ") too big!"; + handleError( StkError::WARNING ); + return 0.0; + } + + long tap = inPoint_ - i; + if (tap < 0) // Check for wraparound. + tap += inputs_.size(); + + return inputs_[tap]; +} + +StkFloat Delay :: lastOut(void) const +{ + return Filter::lastOut(); +} + +StkFloat Delay :: nextOut(void) +{ + return inputs_[outPoint_]; +} + +StkFloat Delay :: computeSample( StkFloat input ) +{ + inputs_[inPoint_++] = input; + + // Check for end condition + if (inPoint_ == inputs_.size()) + inPoint_ = 0; + + // Read out next value + outputs_[0] = inputs_[outPoint_++]; + + if (outPoint_ == inputs_.size()) + outPoint_ = 0; + + return outputs_[0]; +} + +StkFloat Delay :: tick( StkFloat input ) +{ + return computeSample( input ); +} + +StkFrames& Delay :: tick( StkFrames& frames, unsigned int channel ) +{ + return Filter::tick( frames, channel ); +} diff --git a/nyqstk/src/DelayA.cpp b/nyqstk/src/DelayA.cpp new file mode 100644 index 0000000..4bfefa1 --- /dev/null +++ b/nyqstk/src/DelayA.cpp @@ -0,0 +1,145 @@ +/***************************************************/ +/*! \class DelayA + \brief STK allpass interpolating delay line class. + + This Delay subclass implements a fractional-length digital + delay-line using a first-order allpass filter. A fixed maximum + length of 4095 and a delay of 0.5 is set using the default + constructor. Alternatively, the delay and maximum length can be + set during instantiation with an overloaded constructor. + + An allpass filter has unity magnitude gain but variable phase + delay properties, making it useful in achieving fractional delays + without affecting a signal's frequency magnitude response. In + order to achieve a maximally flat phase delay response, the + minimum delay possible in this implementation is limited to a + value of 0.5. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "DelayA.h" + +using namespace Nyq; + +DelayA :: DelayA() : Delay() +{ + this->setDelay( 0.5 ); + apInput_ = 0.0; + doNextOut_ = true; +} + +DelayA :: DelayA(StkFloat delay, unsigned long maxDelay) +{ + if ( delay < 0.0 || maxDelay < 1 ) { + errorString_ << "DelayA::DelayA: delay must be >= 0.0, maxDelay must be > 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( delay > (StkFloat) maxDelay ) { + errorString_ << "DelayA::DelayA: maxDelay must be > than delay argument!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + // Writing before reading allows delays from 0 to length-1. + if ( maxDelay > inputs_.size()-1 ) { + inputs_.resize( maxDelay+1 ); + this->clear(); + } + + inPoint_ = 0; + this->setDelay(delay); + apInput_ = 0.0; + doNextOut_ = true; +} + +DelayA :: ~DelayA() +{ +} + +void DelayA :: clear() +{ + Delay::clear(); + apInput_ = 0.0; +} + +void DelayA :: setDelay(StkFloat delay) +{ + StkFloat outPointer; + unsigned long length = inputs_.size(); + + if ( delay > inputs_.size() - 1 ) { // The value is too big. + errorString_ << "DelayA::setDelay: argument (" << delay << ") too big ... setting to maximum!"; + handleError( StkError::WARNING ); + + // Force delay to maxLength + outPointer = inPoint_ + 1.0; + delay_ = length - 1; + } + else if (delay < 0.5) { + errorString_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!"; + handleError( StkError::WARNING ); + + outPointer = inPoint_ + 0.4999999999; + delay_ = 0.5; + } + else { + outPointer = inPoint_ - delay + 1.0; // outPoint chases inpoint + delay_ = delay; + } + + if (outPointer < 0) + outPointer += length; // modulo maximum length + + outPoint_ = (long) outPointer; // integer part + if ( outPoint_ == length ) outPoint_ = 0; + alpha_ = 1.0 + outPoint_ - outPointer; // fractional part + + if (alpha_ < 0.5) { + // The optimal range for alpha is about 0.5 - 1.5 in order to + // achieve the flattest phase delay response. + outPoint_ += 1; + if (outPoint_ >= length) outPoint_ -= length; + alpha_ += (StkFloat) 1.0; + } + + coeff_ = ((StkFloat) 1.0 - alpha_) / + ((StkFloat) 1.0 + alpha_); // coefficient for all pass +} + +StkFloat DelayA :: getDelay(void) const +{ + return delay_; +} + +StkFloat DelayA :: nextOut(void) +{ + if ( doNextOut_ ) { + // Do allpass interpolation delay. + nextOutput_ = -coeff_ * outputs_[0]; + nextOutput_ += apInput_ + (coeff_ * inputs_[outPoint_]); + doNextOut_ = false; + } + + return nextOutput_; +} + +StkFloat DelayA :: computeSample( StkFloat input ) +{ + inputs_[inPoint_++] = input; + + // Increment input pointer modulo length. + if (inPoint_ == inputs_.size()) + inPoint_ = 0; + + outputs_[0] = nextOut(); + doNextOut_ = true; + + // Save the allpass input and increment modulo length. + apInput_ = inputs_[outPoint_++]; + if (outPoint_ == inputs_.size()) + outPoint_ = 0; + + return outputs_[0]; +} diff --git a/nyqstk/src/DelayL.cpp b/nyqstk/src/DelayL.cpp new file mode 100644 index 0000000..823526b --- /dev/null +++ b/nyqstk/src/DelayL.cpp @@ -0,0 +1,132 @@ +/***************************************************/ +/*! \class DelayL + \brief STK linear interpolating delay line class. + + This Delay subclass implements a fractional- + length digital delay-line using first-order + linear interpolation. A fixed maximum length + of 4095 and a delay of zero is set using the + default constructor. Alternatively, the + delay and maximum length can be set during + instantiation with an overloaded constructor. + + Linear interpolation is an efficient technique + for achieving fractional delay lengths, though + it does introduce high-frequency signal + attenuation to varying degrees depending on the + fractional delay setting. The use of higher + order Lagrange interpolators can typically + improve (minimize) this attenuation characteristic. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "DelayL.h" + +using namespace Nyq; + +DelayL :: DelayL() : Delay() +{ + doNextOut_ = true; +} + +DelayL :: DelayL(StkFloat delay, unsigned long maxDelay) +{ + if ( delay < 0.0 || maxDelay < 1 ) { + errorString_ << "DelayL::DelayL: delay must be >= 0.0, maxDelay must be > 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( delay > (StkFloat) maxDelay ) { + errorString_ << "DelayL::DelayL: maxDelay must be > than delay argument!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + // Writing before reading allows delays from 0 to length-1. + if ( maxDelay > inputs_.size()-1 ) { + inputs_.resize( maxDelay+1 ); + this->clear(); + } + + inPoint_ = 0; + this->setDelay(delay); + doNextOut_ = true; +} + +DelayL :: ~DelayL() +{ +} + +void DelayL :: setDelay(StkFloat delay) +{ + StkFloat outPointer; + + if ( delay > inputs_.size() - 1 ) { // The value is too big. + errorString_ << "DelayL::setDelay: argument (" << delay << ") too big ... setting to maximum!"; + handleError( StkError::WARNING ); + + // Force delay to maxLength + outPointer = inPoint_ + 1.0; + delay_ = inputs_.size() - 1; + } + else if (delay < 0 ) { + errorString_ << "DelayL::setDelay: argument (" << delay << ") less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + + outPointer = inPoint_; + delay_ = 0; + } + else { + outPointer = inPoint_ - delay; // read chases write + delay_ = delay; + } + + while (outPointer < 0) + outPointer += inputs_.size(); // modulo maximum length + + outPoint_ = (long) outPointer; // integer part + if ( outPoint_ == inputs_.size() ) outPoint_ = 0; + alpha_ = outPointer - outPoint_; // fractional part + omAlpha_ = (StkFloat) 1.0 - alpha_; +} + +StkFloat DelayL :: getDelay(void) const +{ + return delay_; +} + +StkFloat DelayL :: nextOut(void) +{ + if ( doNextOut_ ) { + // First 1/2 of interpolation + nextOutput_ = inputs_[outPoint_] * omAlpha_; + // Second 1/2 of interpolation + if (outPoint_+1 < inputs_.size()) + nextOutput_ += inputs_[outPoint_+1] * alpha_; + else + nextOutput_ += inputs_[0] * alpha_; + doNextOut_ = false; + } + + return nextOutput_; +} + +StkFloat DelayL :: computeSample( StkFloat input ) +{ + inputs_[inPoint_++] = input; + + // Increment input pointer modulo length. + if (inPoint_ == inputs_.size()) + inPoint_ = 0; + + outputs_[0] = nextOut(); + doNextOut_ = true; + + // Increment output pointer modulo length. + if (++outPoint_ == inputs_.size()) + outPoint_ = 0; + + return outputs_[0]; +} + diff --git a/nyqstk/src/Effect.cpp b/nyqstk/src/Effect.cpp new file mode 100644 index 0000000..3a109a8 --- /dev/null +++ b/nyqstk/src/Effect.cpp @@ -0,0 +1,98 @@ +/***************************************************/ +/*! \class Effect + \brief STK abstract effects parent class. + + This class provides common functionality for + STK effects subclasses. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Effect.h" +#include + +using namespace Nyq; + +Effect :: Effect() +{ +} + +Effect :: ~Effect() +{ +} + +void Effect :: setEffectMix(StkFloat mix) +{ + if ( mix < 0.0 ) { + errorString_ << "Effect::setEffectMix: mix parameter is less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + effectMix_ = 0.0; + } + else if ( mix > 1.0 ) { + errorString_ << "Effect::setEffectMix: mix parameter is greater than 1.0 ... setting to one!"; + handleError( StkError::WARNING ); + effectMix_ = 1.0; + } + else + effectMix_ = mix; +} + +StkFloat Effect :: lastOut() const +{ + return (lastOutput_[0] + lastOutput_[1]) * 0.5; +} + +StkFloat Effect :: lastOutLeft() const +{ + return lastOutput_[0]; +} + +StkFloat Effect :: lastOutRight() const +{ + return lastOutput_[1]; +} + +StkFloat Effect :: tick( StkFloat input ) +{ + return computeSample( input ); +} + +StkFrames& Effect :: tick( StkFrames& frames, unsigned int channel ) +{ + if ( channel >= frames.channels() ) { + errorString_ << "Effect::tick(): channel and StkFrames arguments are incompatible!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( frames.channels() == 1 ) { + for ( unsigned int i=0; i value_) { + value_ += rate_; + if (value_ >= target_) { + value_ = target_; + state_ = 0; + } + } + else { + value_ -= rate_; + if (value_ <= target_) { + value_ = target_; + state_ = 0; + } + } + } + + lastOutput_ = value_; + return value_; +} diff --git a/nyqstk/src/FileRead.cpp b/nyqstk/src/FileRead.cpp new file mode 100644 index 0000000..cd9eb10 --- /dev/null +++ b/nyqstk/src/FileRead.cpp @@ -0,0 +1,727 @@ +/***************************************************/ +/*! \class FileRead + \brief STK audio file input class. + + This class provides input support for various + audio file formats. Multi-channel (>2) + soundfiles are supported. The file data is + returned via an external StkFrames object + passed to the read() function. This class + does not store its own copy of the file data, + rather the data is read directly from disk. + + FileRead currently supports uncompressed WAV, + AIFF/AIFC, SND (AU), MAT-file (Matlab), and + STK RAW file formats. Signed integer (8-, + 16-, and 32-bit) and floating-point (32- and + 64-bit) data types are supported. Compressed + data types are not supported. + + STK RAW files have no header and are assumed + to contain a monophonic stream of 16-bit + signed integers in big-endian byte order at a + sample rate of 22050 Hz. MAT-file data should + be saved in an array with each data channel + filling a matrix row. The sample rate for + MAT-files is assumed to be 44100 Hz. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "string.h" +#include "FileRead.h" +#include +#include +#include +#include +#include +#include + +using namespace Nyq; + +FileRead :: FileRead() + : fd_(0) +{ +} + +FileRead :: FileRead( std::string fileName, bool typeRaw ) + : fd_(0) +{ + open( fileName, typeRaw ); +} + +FileRead :: ~FileRead() +{ + if ( fd_ ) + fclose( fd_ ); +} + +void FileRead :: close( void ) +{ + if ( fd_ ) fclose( fd_ ); + fd_ = 0; + wavFile_ = false; +} + +bool FileRead :: isOpen( void ) +{ + if ( fd_ ) return true; + else return false; +} + +void FileRead :: open( std::string fileName, bool typeRaw ) +{ + // If another file is open, close it. + close(); + + // Try to open the file. + fd_ = fopen( fileName.c_str(), "rb" ); + if ( !fd_ ) { + errorString_ << "FileRead::open: could not open or find file (" << fileName << ")!"; + handleError( StkError::FILE_NOT_FOUND ); + } + + // Attempt to determine file type from header (unless RAW). + bool result = false; + if ( typeRaw ) + result = getRawInfo( fileName.c_str() ); + else { + char header[12]; + if ( fread( &header, 4, 3, fd_ ) != 3 ) goto error; + if ( !strncmp( header, "RIFF", 4 ) && + !strncmp( &header[8], "WAVE", 4 ) ) + result = getWavInfo( fileName.c_str() ); + else if ( !strncmp( header, ".snd", 4 ) ) + result = getSndInfo( fileName.c_str() ); + else if ( !strncmp( header, "FORM", 4 ) && + ( !strncmp( &header[8], "AIFF", 4 ) || !strncmp(&header[8], "AIFC", 4) ) ) + result = getAifInfo( fileName.c_str() ); + else { + if ( fseek( fd_, 126, SEEK_SET ) == -1 ) goto error; + if ( fread( &header, 2, 1, fd_ ) != 1 ) goto error; + if ( !strncmp( header, "MI", 2 ) || + !strncmp( header, "IM", 2 ) ) + result = getMatInfo( fileName.c_str() ); + else { + errorString_ << "FileRead::open: file (" << fileName << ") format unknown."; + handleError( StkError::FILE_UNKNOWN_FORMAT ); + } + } + } + + // If here, we had a file type candidate but something else went wrong. + if ( result == false ) + handleError( StkError::FILE_ERROR ); + + // Check for empty files. + if ( fileSize_ == 0 ) { + errorString_ << "FileRead::open: file (" << fileName << ") data size is zero!"; + handleError( StkError::FILE_ERROR ); + } + + return; + + error: + errorString_ << "FileRead::open: error reading file (" << fileName << ")!"; + handleError( StkError::FILE_ERROR ); +} + +bool FileRead :: getRawInfo( const char *fileName ) +{ + // Use the system call "stat" to determine the file length. + struct stat filestat; + if ( stat(fileName, &filestat) == -1 ) { + errorString_ << "FileRead: Could not stat RAW file (" << fileName << ")."; + return false; + } + + // STK rawwave files have no header and are assumed to contain a + // monophonic stream of 16-bit signed integers in big-endian byte + // order at a sample rate of 22050 Hz. + channels_ = 1; + fileSize_ = (long) filestat.st_size / 2; // length in 2-byte samples + dataOffset_ = 0; + fileRate_ = 22050.0; + dataType_ = STK_SINT16; + byteswap_ = false; +#ifdef __LITTLE_ENDIAN__ + byteswap_ = true; +#endif + + return true; +} + +bool FileRead :: getWavInfo( const char *fileName ) +{ + // Find "format" chunk ... it must come before the "data" chunk. + char id[4]; + SINT32 chunkSize; + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + while ( strncmp(id, "fmt ", 4) ) { + if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap32((unsigned char *)&chunkSize); +#endif + if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error; + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + } + + // Check that the data is not compressed. + unsigned short format_tag; + if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error; // Read fmt chunk size. + if ( fread(&format_tag, 2, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap16((unsigned char *)&format_tag); + swap32((unsigned char *)&chunkSize); +#endif + if ( format_tag == 0xFFFE ) { // WAVE_FORMAT_EXTENSIBLE + dataOffset_ = ftell(fd_); + if ( fseek(fd_, 14, SEEK_CUR) == -1 ) goto error; + unsigned short extSize; + if ( fread(&extSize, 2, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap16((unsigned char *)&extSize); +#endif + if ( extSize == 0 ) goto error; + if ( fseek(fd_, 6, SEEK_CUR) == -1 ) goto error; + if ( fread(&format_tag, 2, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap16((unsigned char *)&format_tag); +#endif + if ( fseek(fd_, dataOffset_, SEEK_SET) == -1 ) goto error; + } + if (format_tag != 1 && format_tag != 3 ) { // PCM = 1, FLOAT = 3 + errorString_ << "FileRead: "<< fileName << " contains an unsupported data format type (" << format_tag << ")."; + return false; + } + + // Get number of channels from the header. + SINT16 temp; + if ( fread(&temp, 2, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap16((unsigned char *)&temp); +#endif + channels_ = (unsigned int ) temp; + + // Get file sample rate from the header. + SINT32 srate; + if ( fread(&srate, 4, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap32((unsigned char *)&srate); +#endif + fileRate_ = (StkFloat) srate; + + // Determine the data type. + dataType_ = 0; + if ( fseek(fd_, 6, SEEK_CUR) == -1 ) goto error; // Locate bits_per_sample info. + if ( fread(&temp, 2, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap16((unsigned char *)&temp); +#endif + if ( format_tag == 1 ) { + if (temp == 8) + dataType_ = STK_SINT8; + else if (temp == 16) + dataType_ = STK_SINT16; + else if (temp == 32) + dataType_ = STK_SINT32; + } + else if ( format_tag == 3 ) { + if (temp == 32) + dataType_ = STK_FLOAT32; + else if (temp == 64) + dataType_ = STK_FLOAT64; + } + if ( dataType_ == 0 ) { + errorString_ << "FileRead: " << temp << " bits per sample with data format " << format_tag << " are not supported (" << fileName << ")."; + return false; + } + + // Jump over any remaining part of the "fmt" chunk. + if ( fseek(fd_, chunkSize-16, SEEK_CUR) == -1 ) goto error; + + // Find "data" chunk ... it must come after the "fmt" chunk. + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + + while ( strncmp(id, "data", 4) ) { + if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap32((unsigned char *)&chunkSize); +#endif + chunkSize += chunkSize % 2; // chunk sizes must be even + if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error; + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + } + + // Get length of data from the header. + SINT32 bytes; + if ( fread(&bytes, 4, 1, fd_) != 1 ) goto error; +#ifndef __LITTLE_ENDIAN__ + swap32((unsigned char *)&bytes); +#endif + fileSize_ = 8 * bytes / temp / channels_; // sample frames + + dataOffset_ = ftell(fd_); + byteswap_ = false; +#ifndef __LITTLE_ENDIAN__ + byteswap_ = true; +#endif + + wavFile_ = true; + return true; + + error: + errorString_ << "FileRead: error reading WAV file (" << fileName << ")."; + return false; +} + +bool FileRead :: getSndInfo( const char *fileName ) +{ + // Determine the data type. + UINT32 format; + if ( fseek(fd_, 12, SEEK_SET) == -1 ) goto error; // Locate format + if ( fread(&format, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&format); +#endif + if (format == 2) dataType_ = STK_SINT8; + else if (format == 3) dataType_ = STK_SINT16; + else if (format == 4) dataType_ = STK_SINT24; + else if (format == 5) dataType_ = STK_SINT32; + else if (format == 6) dataType_ = STK_FLOAT32; + else if (format == 7) dataType_ = STK_FLOAT64; + else { + errorString_ << "FileRead: data format in file " << fileName << " is not supported."; + return false; + } + + // Get file sample rate from the header. + UINT32 srate; + if ( fread(&srate, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&srate); +#endif + fileRate_ = (StkFloat) srate; + + // Get number of channels from the header. + UINT32 chans; + if ( fread(&chans, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&chans); +#endif + channels_ = chans; + + if ( fseek(fd_, 4, SEEK_SET) == -1 ) goto error; + if ( fread(&dataOffset_, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&dataOffset_); +#endif + + // Get length of data from the header. + if ( fread(&fileSize_, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&fileSize_); +#endif + // Convert to sample frames. + if ( dataType_ == STK_SINT8 ) + fileSize_ /= channels_; + if ( dataType_ == STK_SINT16 ) + fileSize_ /= 2 * channels_; + else if ( dataType_ == STK_SINT24 ) + fileSize_ /= 3 * channels_; + else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 ) + fileSize_ /= 4 * channels_; + else if ( dataType_ == STK_FLOAT64 ) + fileSize_ /= 8 * channels_; + + byteswap_ = false; +#ifdef __LITTLE_ENDIAN__ + byteswap_ = true; +#endif + + return true; + + error: + errorString_ << "FileRead: Error reading SND file (" << fileName << ")."; + return false; +} + +bool FileRead :: getAifInfo( const char *fileName ) +{ + bool aifc = false; + char id[4]; + + // Determine whether this is AIFF or AIFC. + if ( fseek(fd_, 8, SEEK_SET) == -1 ) goto error; + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + if ( !strncmp(id, "AIFC", 4) ) aifc = true; + + // Find "common" chunk + SINT32 chunkSize; + if ( fread(&id, 4, 1, fd_) != 1) goto error; + while ( strncmp(id, "COMM", 4) ) { + if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&chunkSize); +#endif + chunkSize += chunkSize % 2; // chunk sizes must be even + if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error; + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + } + + // Get number of channels from the header. + SINT16 temp; + if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error; // Jump over chunk size + if ( fread(&temp, 2, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap16((unsigned char *)&temp); +#endif + channels_ = temp; + + // Get length of data from the header. + SINT32 frames; + if ( fread(&frames, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&frames); +#endif + fileSize_ = frames; // sample frames + + // Read the number of bits per sample. + if ( fread(&temp, 2, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap16((unsigned char *)&temp); +#endif + + // Get file sample rate from the header. For AIFF files, this value + // is stored in a 10-byte, IEEE Standard 754 floating point number, + // so we need to convert it first. + unsigned char srate[10]; + unsigned char exp; + unsigned long mantissa; + unsigned long last; + if ( fread(&srate, 10, 1, fd_) != 1 ) goto error; + mantissa = (unsigned long) *(unsigned long *)(srate+2); +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&mantissa); +#endif + exp = 30 - *(srate+1); + last = 0; + while (exp--) { + last = mantissa; + mantissa >>= 1; + } + if (last & 0x00000001) mantissa++; + fileRate_ = (StkFloat) mantissa; + + // Determine the data format. + dataType_ = 0; + if ( aifc == false ) { + if ( temp <= 8 ) dataType_ = STK_SINT8; + else if ( temp <= 16 ) dataType_ = STK_SINT16; + else if ( temp <= 24 ) dataType_ = STK_SINT24; + else if ( temp <= 32 ) dataType_ = STK_SINT32; + } + else { + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + if ( !strncmp(id, "NONE", 4) ) { + if ( temp <= 8 ) dataType_ = STK_SINT8; + else if ( temp <= 16 ) dataType_ = STK_SINT16; + else if ( temp <= 24 ) dataType_ = STK_SINT24; + else if ( temp <= 32 ) dataType_ = STK_SINT32; + } + else if ( (!strncmp(id, "fl32", 4) || !strncmp(id, "FL32", 4)) && temp == 32 ) dataType_ = STK_FLOAT32; + else if ( (!strncmp(id, "fl64", 4) || !strncmp(id, "FL64", 4)) && temp == 64 ) dataType_ = STK_FLOAT64; + } + if ( dataType_ == 0 ) { + errorString_ << "FileRead: AIFF/AIFC file (" << fileName << ") has unsupported data type (" << id << ")."; + return false; + } + + // Start at top to find data (SSND) chunk ... chunk order is undefined. + if ( fseek(fd_, 12, SEEK_SET) == -1 ) goto error; + + // Find data (SSND) chunk + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + while ( strncmp(id, "SSND", 4) ) { + if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&chunkSize); +#endif + chunkSize += chunkSize % 2; // chunk sizes must be even + if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error; + if ( fread(&id, 4, 1, fd_) != 1 ) goto error; + } + + // Skip over chunk size, offset, and blocksize fields + if ( fseek(fd_, 12, SEEK_CUR) == -1 ) goto error; + + dataOffset_ = ftell(fd_); + byteswap_ = false; +#ifdef __LITTLE_ENDIAN__ + byteswap_ = true; +#endif + + return true; + + error: + errorString_ << "FileRead: Error reading AIFF file (" << fileName << ")."; + return false; +} + +bool FileRead :: getMatInfo( const char *fileName ) +{ + // MAT-file formatting information is available at: + // http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf + + // Verify this is a version 5 MAT-file format. + char head[4]; + if ( fseek(fd_, 0, SEEK_SET) == -1 ) goto error; + if ( fread(&head, 4, 1, fd_) != 1 ) goto error; + // If any of the first 4 characters of the header = 0, then this is + // a Version 4 MAT-file. + if ( strstr(head, "0") ) { + errorString_ << "FileRead: " << fileName << " appears to be a Version 4 MAT-file, which is not currently supported."; + return false; + } + + // Determine the endian-ness of the file. + char mi[2]; + byteswap_ = false; + // Locate "M" and "I" characters in header. + if ( fseek(fd_, 126, SEEK_SET) == -1 ) goto error; + if ( fread(&mi, 2, 1, fd_) != 1) goto error; +#ifdef __LITTLE_ENDIAN__ + if ( !strncmp(mi, "MI", 2) ) + byteswap_ = true; + else if ( strncmp(mi, "IM", 2) ) goto error; +#else + if ( !strncmp(mi, "IM", 2)) + byteswap_ = true; + else if ( strncmp(mi, "MI", 2) ) goto error; +#endif + + // Check the data element type + SINT32 datatype; + if ( fread(&datatype, 4, 1, fd_) != 1 ) goto error; + if ( byteswap_ ) swap32((unsigned char *)&datatype); + if (datatype != 14) { + errorString_ << "FileRead: The file does not contain a single Matlab array (or matrix) data element."; + return false; + } + + // Determine the array data type. + SINT32 tmp; + SINT32 size; + if ( fseek(fd_, 168, SEEK_SET) == -1 ) goto error; + if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; + if (byteswap_) swap32((unsigned char *)&tmp); + if (tmp == 1) { // array name > 4 characters + if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; // get array name length + if (byteswap_) swap32((unsigned char *)&tmp); + size = (SINT32) ceil((float)tmp / 8); + if ( fseek(fd_, size*8, SEEK_CUR) == -1 ) goto error; // jump over array name + } + else { // array name <= 4 characters, compressed data element + if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error; + } + if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; + if (byteswap_) swap32((unsigned char *)&tmp); + if ( tmp == 1 ) dataType_ = STK_SINT8; + else if ( tmp == 3 ) dataType_ = STK_SINT16; + else if ( tmp == 5 ) dataType_ = STK_SINT32; + else if ( tmp == 7 ) dataType_ = STK_FLOAT32; + else if ( tmp == 9 ) dataType_ = STK_FLOAT64; + else { + errorString_ << "FileRead: The MAT-file array data format (" << tmp << ") is not supported."; + return false; + } + + // Get number of rows from the header. + SINT32 rows; + if ( fseek(fd_, 160, SEEK_SET) == -1 ) goto error; + if ( fread(&rows, 4, 1, fd_) != 1 ) goto error; + if (byteswap_) swap32((unsigned char *)&rows); + + // Get number of columns from the header. + SINT32 columns; + if ( fread(&columns, 4, 1, fd_) != 1 ) goto error; + if (byteswap_) swap32((unsigned char *)&columns); + + // Assume channels = smaller of rows or columns. + if (rows < columns) { + channels_ = rows; + fileSize_ = columns; + } + else { + errorString_ << "FileRead: Transpose the MAT-file array so that audio channels fill matrix rows (not columns)."; + return false; + } + + // Move read pointer to the data in the file. + SINT32 headsize; + if ( fseek(fd_, 132, SEEK_SET) == -1 ) goto error; + if ( fread(&headsize, 4, 1, fd_) != 1 ) goto error; // file size from 132nd byte + if (byteswap_) swap32((unsigned char *)&headsize); + headsize -= fileSize_ * 8 * channels_; + if ( fseek(fd_, headsize, SEEK_CUR) == -1 ) goto error; + dataOffset_ = ftell(fd_); + + // Assume MAT-files have 44100 Hz sample rate. + fileRate_ = 44100.0; + + return true; + + error: + errorString_ << "FileRead: Error reading MAT-file (" << fileName << ")."; + return false; +} + +void FileRead :: read( StkFrames& buffer, unsigned long startFrame, bool doNormalize ) +{ + // Make sure we have an open file. + if ( fd_ == 0 ) { + errorString_ << "FileRead::read: a file is not open!"; + Stk::handleError( StkError::WARNING ); + return; + } + + // Check the buffer size. + unsigned int nFrames = buffer.frames(); + if ( nFrames == 0 ) { + errorString_ << "FileRead::read: StkFrames buffer size is zero ... no data read!"; + Stk::handleError( StkError::WARNING ); + return; + } + + if ( buffer.channels() != channels_ ) { + errorString_ << "FileRead::read: StkFrames argument has incompatible number of channels!"; + Stk::handleError( StkError::FUNCTION_ARGUMENT ); + } + + // Check for file end. + if ( startFrame + nFrames >= fileSize_ ) + nFrames = fileSize_ - startFrame; + + long i, nSamples = (long) ( nFrames * channels_ ); + unsigned long offset = startFrame * channels_; + + // Read samples into StkFrames data buffer. + if ( dataType_ == STK_SINT16 ) { + SINT16 *buf = (SINT16 *) &buffer[0]; + if ( fseek( fd_, dataOffset_+(offset*2), SEEK_SET ) == -1 ) goto error; + if ( fread( buf, nSamples * 2, 1, fd_ ) != 1 ) goto error; + if ( byteswap_ ) { + SINT16 *ptr = buf; + for ( i=nSamples-1; i>=0; i-- ) + swap16( (unsigned char *) ptr++ ); + } + if ( doNormalize ) { + StkFloat gain = 1.0 / 32768.0; + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i] * gain; + } + else { + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i]; + } + } + else if ( dataType_ == STK_SINT32 ) { + SINT32 *buf = (SINT32 *) &buffer[0]; + if ( fseek( fd_, dataOffset_+(offset*4 ), SEEK_SET ) == -1 ) goto error; + if ( fread( buf, nSamples * 4, 1, fd_ ) != 1 ) goto error; + if ( byteswap_ ) { + SINT32 *ptr = buf; + for ( i=nSamples-1; i>=0; i-- ) + swap32( (unsigned char *) ptr++ ); + } + if ( doNormalize ) { + StkFloat gain = 1.0 / 2147483648.0; + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i] * gain; + } + else { + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i]; + } + } + else if ( dataType_ == STK_FLOAT32 ) { + FLOAT32 *buf = (FLOAT32 *) &buffer[0]; + if ( fseek( fd_, dataOffset_+(offset*4), SEEK_SET ) == -1 ) goto error; + if ( fread( buf, nSamples * 4, 1, fd_ ) != 1 ) goto error; + if ( byteswap_ ) { + FLOAT32 *ptr = buf; + for ( i=nSamples-1; i>=0; i-- ) + swap32( (unsigned char *) ptr++ ); + } + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i]; + } + else if ( dataType_ == STK_FLOAT64 ) { + FLOAT64 *buf = (FLOAT64 *) &buffer[0]; + if ( fseek( fd_, dataOffset_+(offset*8), SEEK_SET ) == -1 ) goto error; + if ( fread( buf, nSamples * 8, 1, fd_ ) != 1 ) goto error; + if ( byteswap_ ) { + FLOAT64 *ptr = buf; + for ( i=nSamples-1; i>=0; i-- ) + swap64( (unsigned char *) ptr++ ); + } + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i]; + } + else if ( dataType_ == STK_SINT8 && wavFile_ ) { // 8-bit WAV data is unsigned! + unsigned char *buf = (unsigned char *) &buffer[0]; + if ( fseek( fd_, dataOffset_+offset, SEEK_SET ) == -1 ) goto error; + if ( fread( buf, nSamples, 1, fd_) != 1 ) goto error; + if ( doNormalize ) { + StkFloat gain = 1.0 / 128.0; + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = ( buf[i] - 128 ) * gain; + } + else { + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i] - 128.0; + } + } + else if ( dataType_ == STK_SINT8 ) { // signed 8-bit data + char *buf = (char *) &buffer[0]; + if ( fseek( fd_, dataOffset_+offset, SEEK_SET ) == -1 ) goto error; + if ( fread( buf, nSamples, 1, fd_ ) != 1 ) goto error; + if ( doNormalize ) { + StkFloat gain = 1.0 / 128.0; + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i] * gain; + } + else { + for ( i=nSamples-1; i>=0; i-- ) + buffer[i] = buf[i]; + } + } + else if ( dataType_ == STK_SINT24 ) { + // 24-bit values are harder to import efficiently since there is + // no native 24-bit type. The following routine works but is much + // less efficient that that used for the other data types. + SINT32 buf; + StkFloat gain = 1.0 / 8388608.0; + if ( fseek(fd_, dataOffset_+(offset*3), SEEK_SET ) == -1 ) goto error; + for ( i=0; i>= 8; + if ( byteswap_ ) + swap32( (unsigned char *) &buf ); + if ( doNormalize ) + buffer[i] = buf * gain; + else + buffer[i] = buf; + } + } + + buffer.setDataRate( fileRate_ ); + + return; + + error: + errorString_ << "FileRead: Error reading file data."; + handleError( StkError::FILE_ERROR); +} + diff --git a/nyqstk/src/FileWvIn.cpp b/nyqstk/src/FileWvIn.cpp new file mode 100644 index 0000000..57a5f09 --- /dev/null +++ b/nyqstk/src/FileWvIn.cpp @@ -0,0 +1,213 @@ +/***************************************************/ +/*! \class FileWvIn + \brief STK audio file input class. + + This class inherits from WvIn. It provides a "tick-level" + interface to the FileRead class. It also provides variable-rate + "playback" functionality. Audio file support is provided by the + FileRead class. Linear interpolation is used for fractional "read + rates". + + FileWvIn supports multi-channel data. It is important to distinguish + the tick() methods, which return samples produced by averaging + across sample frames, from the tickFrame() methods, which return + references to multi-channel sample frames. + + FileWvIn will either load the entire content of an audio file into + local memory or incrementally read file data from disk in chunks. + This behavior is controlled by the optional constructor arguments + \e chunkThreshold and \e chunkSize. File sizes greater than \e + chunkThreshold (in sample frames) will be read incrementally in + chunks of \e chunkSize each (also in sample frames). + + When the end of a file is reached, subsequent calls to the tick() + functions return zero-valued data. + + See the FileRead class for a description of the supported audio + file formats. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "FileWvIn.h" +#include + +using namespace Nyq; + +FileWvIn :: FileWvIn( unsigned long chunkThreshold, unsigned long chunkSize ) + : finished_(true), interpolate_(false), time_(0.0), + chunkThreshold_(chunkThreshold), chunkSize_(chunkSize) +{ +} + +FileWvIn :: FileWvIn( std::string fileName, bool raw, bool doNormalize, + unsigned long chunkThreshold, unsigned long chunkSize ) + : finished_(true), interpolate_(false), time_(0.0), + chunkThreshold_(chunkThreshold), chunkSize_(chunkSize) +{ + openFile( fileName, raw, doNormalize ); +} + +FileWvIn :: ~FileWvIn() +{ + this->closeFile(); +} + +void FileWvIn :: closeFile( void ) +{ + if ( file_.isOpen() ) file_.close(); + finished_ = true; +} + +void FileWvIn :: openFile( std::string fileName, bool raw, bool doNormalize ) +{ + // Call close() in case another file is already open. + this->closeFile(); + + // Attempt to open the file ... an error might be thrown here. + file_.open( fileName, raw ); + + // Determine whether chunking or not. + if ( file_.fileSize() > chunkThreshold_ ) { + chunking_ = true; + chunkPointer_ = 0; + data_.resize( chunkSize_, file_.channels() ); + if ( doNormalize ) normalizing_ = true; + else normalizing_ = false; + } + else { + chunking_ = false; + data_.resize( (size_t) file_.fileSize(), file_.channels() ); + } + + // Load all or part of the data. + file_.read( data_, 0, doNormalize ); + + // Resize our lastOutputs container. + lastOutputs_.resize( 1, file_.channels() ); + + // Set default rate based on file sampling rate. + this->setRate( data_.dataRate() / Stk::sampleRate() ); + + if ( doNormalize & !chunking_ ) this->normalize(); + + this->reset(); +} + +void FileWvIn :: reset(void) +{ + time_ = (StkFloat) 0.0; + for ( unsigned int i=0; inormalize( 1.0 ); +} + +// Normalize all channels equally by the greatest magnitude in all of the data. +void FileWvIn :: normalize( StkFloat peak ) +{ + // When chunking, the "normalization" scaling is performed by FileRead. + if ( chunking_ ) return; + + size_t i; + StkFloat max = 0.0; + + for ( i=0; i max ) + max = (StkFloat) fabs((double) data_[i]); + } + + if (max > 0.0) { + max = 1.0 / max; + max *= peak; + for ( i=0; i file_.fileSize() - 1.0 ) { + time_ = file_.fileSize() - 1.0; + for ( unsigned int i=0; i (StkFloat) ( file_.fileSize() - 1.0 ) ) { + for ( unsigned int i=0; i (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) ) { + + while ( time_ < (StkFloat) chunkPointer_ ) { // negative rate + chunkPointer_ -= chunkSize_ - 1; // overlap chunks by one frame + if ( chunkPointer_ < 0 ) chunkPointer_ = 0; + } + while ( time_ > (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) { // positive rate + chunkPointer_ += chunkSize_ - 1; // overlap chunks by one frame + if ( chunkPointer_ + chunkSize_ > file_.fileSize() ) // at end of file + chunkPointer_ = file_.fileSize() - chunkSize_; + } + + // Load more data. + file_.read( data_, chunkPointer_, normalizing_ ); + } + + // Adjust index for the current buffer. + tyme -= chunkPointer_; + } + + if ( interpolate_ ) { + for ( unsigned int i=0; i + +using namespace Nyq; + +Filter :: Filter() +{ + // The default constructor should setup for pass-through. + gain_ = 1.0; + b_.push_back( 1.0 ); + a_.push_back( 1.0 ); + + inputs_.push_back( 0.0 ); + outputs_.push_back( 0.0 ); +} + +Filter :: Filter( std::vector &bCoefficients, std::vector &aCoefficients ) +{ + // Check the arguments. + if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) { + errorString_ << "Filter: a and b coefficient vectors must both have size > 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( aCoefficients[0] == 0.0 ) { + errorString_ << "Filter: a[0] coefficient cannot == 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + gain_ = 1.0; + b_ = bCoefficients; + a_ = aCoefficients; + + inputs_ = std::vector ( b_.size() ); + outputs_ = std::vector ( a_.size() ); + this->clear(); +} + +Filter :: ~Filter() +{ +} + +void Filter :: clear(void) +{ + unsigned int i; + for (i=0; i &bCoefficients, std::vector &aCoefficients, bool clearState ) +{ + // Check the arguments. + if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) { + errorString_ << "Filter::setCoefficients: a and b coefficient vectors must both have size > 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( aCoefficients[0] == 0.0 ) { + errorString_ << "Filter::setCoefficients: a[0] coefficient cannot == 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( b_.size() != bCoefficients.size() ) { + b_ = bCoefficients; + inputs_.clear(); + inputs_ = std::vector ( b_.size() ); + } + else { + for ( unsigned int i=0; i ( a_.size() ); + } + else { + for ( unsigned int i=0; iclear(); + + // Scale coefficients by a[0] if necessary + if ( a_[0] != 1.0 ) { + unsigned int i; + for ( i=0; i &bCoefficients, bool clearState ) +{ + // Check the argument. + if ( bCoefficients.size() == 0 ) { + errorString_ << "Filter::setNumerator: coefficient vector must have size > 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( b_.size() != bCoefficients.size() ) { + b_ = bCoefficients; + inputs_.clear(); + inputs_ = std::vector ( b_.size() ); + } + else { + for ( unsigned int i=0; iclear(); +} + +void Filter :: setDenominator( std::vector &aCoefficients, bool clearState ) +{ + // Check the argument. + if ( aCoefficients.size() == 0 ) { + errorString_ << "Filter::setDenominator: coefficient vector must have size > 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( aCoefficients[0] == 0.0 ) { + errorString_ << "Filter::setDenominator: a[0] coefficient cannot == 0!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( a_.size() != aCoefficients.size() ) { + a_ = aCoefficients; + outputs_.clear(); + outputs_ = std::vector ( a_.size() ); + } + else { + for ( unsigned int i=0; iclear(); + + // Scale coefficients by a[0] if necessary + if ( a_[0] != 1.0 ) { + unsigned int i; + for ( i=0; i0; i--) { + outputs_[0] += b_[i] * inputs_[i]; + inputs_[i] = inputs_[i-1]; + } + outputs_[0] += b_[0] * inputs_[0]; + + for (i=a_.size()-1; i>0; i--) { + outputs_[0] += -a_[i] * outputs_[i]; + outputs_[i] = outputs_[i-1]; + } + + return outputs_[0]; +} + + +StkFrames& Filter :: tick( StkFrames& frames, unsigned int channel ) +{ + if ( channel >= frames.channels() ) { + errorString_ << "Filter::tick(): channel and StkFrames arguments are incompatible!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( frames.channels() == 1 ) { + for ( unsigned int i=0; i>= 1; + jetDelay_.setMaximumDelay( length_ ); + jetDelay_.setDelay( 49.0 ); + + vibrato_.setFrequency( 5.925 ); + + this->clear(); + + filter_.setPole( 0.7 - ((StkFloat) 0.1 * 22050.0 / Stk::sampleRate() ) ); + filter_.setGain( -1.0 ); + + dcBlock_.setBlockZero(); + + adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010); + endReflection_ = 0.5; + jetReflection_ = 0.5; + noiseGain_ = 0.15; // Breath pressure random component. + vibratoGain_ = 0.05; // Breath periodic vibrato component. + jetRatio_ = 0.32; + + maxPressure_ = 0.0; + lastFrequency_ = 220.0; +} + +Flute :: ~Flute() +{ +} + +void Flute :: clear() +{ + jetDelay_.clear(); + boreDelay_.clear(); + filter_.clear(); + dcBlock_.clear(); +} + +void Flute :: setFrequency(StkFloat frequency) +{ + lastFrequency_ = frequency; + if ( frequency <= 0.0 ) { + errorString_ << "Flute::setFrequency: parameter is less than or equal to zero!"; + handleError( StkError::WARNING ); + lastFrequency_ = 220.0; + } + + // We're overblowing here. + lastFrequency_ *= 0.66666; + + // delay = length - approximate filter delay. + StkFloat delay = Stk::sampleRate() / lastFrequency_ - (StkFloat) 2.0; + if ( delay <= 0.0 ) delay = 0.3; + else if ( delay > length_ ) delay = length_; + + boreDelay_.setDelay(delay); + jetDelay_.setDelay(delay * jetRatio_); +} + +void Flute :: startBlowing(StkFloat amplitude, StkFloat rate) +{ + adsr_.setAttackRate( rate ); + maxPressure_ = amplitude / (StkFloat) 0.8; + adsr_.keyOn(); +} + +void Flute :: stopBlowing(StkFloat rate) +{ + adsr_.setReleaseRate( rate ); + adsr_.keyOff(); +} + +void Flute :: noteOn(StkFloat frequency, StkFloat amplitude) +{ + this->setFrequency( frequency ); + this->startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02 ); + outputGain_ = amplitude + 0.001; + +#if defined(_STK_DEBUG_) + errorString_ << "Flute::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Flute :: noteOff(StkFloat amplitude) +{ + this->stopBlowing( amplitude * 0.02 ); + +#if defined(_STK_DEBUG_) + errorString_ << "Flute::NoteOff: amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Flute :: setJetReflection(StkFloat coefficient) +{ + jetReflection_ = coefficient; +} + +void Flute :: setEndReflection(StkFloat coefficient) +{ + endReflection_ = coefficient; +} + +void Flute :: setJetDelay(StkFloat aRatio) +{ + // Delay = length - approximate filter delay. + StkFloat temp = Stk::sampleRate() / lastFrequency_ - (StkFloat) 2.0; + jetRatio_ = aRatio; + jetDelay_.setDelay(temp * aRatio); // Scaled by ratio. +} + +StkFloat Flute :: computeSample() +{ + StkFloat pressureDiff; + StkFloat breathPressure; + + // Calculate the breath pressure (envelope + noise + vibrato) + breathPressure = maxPressure_ * adsr_.tick(); + breathPressure += breathPressure * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() ); + //breathPressure += breathPressure * vibratoGain_ * vibrato_.tick(); + + StkFloat temp = filter_.tick( boreDelay_.lastOut() ); + temp = dcBlock_.tick( temp ); // Block DC on reflection. + + pressureDiff = breathPressure - (jetReflection_ * temp); + pressureDiff = jetDelay_.tick( pressureDiff ); + pressureDiff = jetTable_.tick( pressureDiff ) + (endReflection_ * temp); + lastOutput_ = (StkFloat) 0.3 * boreDelay_.tick( pressureDiff ); + + lastOutput_ *= outputGain_; + return lastOutput_; +} + +void Flute :: controlChange(int number, StkFloat value) +{ + StkFloat norm = value * ONE_OVER_128; + if ( norm < 0 ) { + norm = 0.0; + errorString_ << "Flute::controlChange: control value less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + } + else if ( norm > 1.0 ) { + norm = 1.0; + errorString_ << "Flute::controlChange: control value greater than 128.0 ... setting to 128.0!"; + handleError( StkError::WARNING ); + } + + if (number == __SK_JetDelay_) // 2 + this->setJetDelay( (StkFloat) (0.08 + (0.48 * norm)) ); + else if (number == __SK_NoiseLevel_) // 4 + noiseGain_ = ( norm * 0.4); + else if (number == __SK_ModFrequency_) // 11 + vibrato_.setFrequency( norm * 12.0); + else if (number == __SK_ModWheel_) // 1 + vibratoGain_ = ( norm * 0.4 ); + else if (number == __SK_AfterTouch_Cont_) // 128 + adsr_.setTarget( norm ); + else { + errorString_ << "Flute::controlChange: undefined control number (" << number << ")!"; + handleError( StkError::WARNING ); + } + +#if defined(_STK_DEBUG_) + errorString_ << "Flute::controlChange: number = " << number << ", value = " << value << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} diff --git a/nyqstk/src/Function.cpp b/nyqstk/src/Function.cpp new file mode 100644 index 0000000..51fadce --- /dev/null +++ b/nyqstk/src/Function.cpp @@ -0,0 +1,57 @@ +/***************************************************/ +/*! \class Function + \brief STK abstract function parent class. + + This class provides common functionality for STK classes which + implement tables or other types of input to output function + mappings. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Function.h" + +using namespace Nyq; + +Function :: Function() : Stk() +{ + lastOutput_ = (StkFloat) 0.0; +} + +Function :: ~Function() +{ +} + +StkFloat Function :: tick( StkFloat input ) +{ + return computeSample( input ); +} + +StkFrames& Function :: tick( StkFrames& frames, unsigned int channel ) +{ + if ( channel >= frames.channels() ) { + errorString_ << "Function::tick(): channel and StkFrames arguments are incompatible!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( frames.channels() == 1 ) { + for ( unsigned int i=0; i= frames.channels() ) { + errorString_ << "Generator::tick(): channel and StkFrames arguments are incompatible!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( frames.channels() == 1 ) { + for ( unsigned int i=0; i= frames.channels() ) { + errorString_ << "Instrmnt::tick(): channel and StkFrames arguments are incompatible!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( frames.channels() == 1 ) { + for ( unsigned int i=0; i + +using namespace Nyq; + +JCRev :: JCRev(StkFloat T60) +{ + // Delay lengths for 44100 Hz sample rate. + int lengths[9] = {1777, 1847, 1993, 2137, 389, 127, 43, 211, 179}; + double scaler = Stk::sampleRate() / 44100.0; + + int delay, i; + if ( scaler != 1.0 ) { + for (i=0; i<9; i++) { + delay = (int) floor(scaler * lengths[i]); + if ( (delay & 1) == 0) delay++; + while ( !this->isPrime(delay) ) delay += 2; + lengths[i] = delay; + } + } + + for (i=0; i<3; i++) { + allpassDelays_[i].setMaximumDelay( lengths[i+4] ); + allpassDelays_[i].setDelay( lengths[i+4] ); + } + + for ( i=0; i<4; i++ ) { + combDelays_[i].setMaximumDelay( lengths[i] ); + combDelays_[i].setDelay( lengths[i] ); + } + + this->setT60( T60 ); + outLeftDelay_.setMaximumDelay( lengths[7] ); + outLeftDelay_.setDelay( lengths[7] ); + outRightDelay_.setMaximumDelay( lengths[8] ); + outRightDelay_.setDelay( lengths[8] ); + allpassCoefficient_ = 0.7; + effectMix_ = 0.3; + this->clear(); +} + +JCRev :: ~JCRev() +{ +} + +void JCRev :: clear() +{ + allpassDelays_[0].clear(); + allpassDelays_[1].clear(); + allpassDelays_[2].clear(); + combDelays_[0].clear(); + combDelays_[1].clear(); + combDelays_[2].clear(); + combDelays_[3].clear(); + outRightDelay_.clear(); + outLeftDelay_.clear(); + lastOutput_[0] = 0.0; + lastOutput_[1] = 0.0; +} + +void JCRev :: setT60( StkFloat T60 ) +{ + for ( int i=0; i<4; i++ ) + combCoefficient_[i] = pow(10.0, (-3.0 * combDelays_[i].getDelay() / (T60 * Stk::sampleRate()))); +} + +StkFloat JCRev :: computeSample(StkFloat input) +{ + StkFloat temp, temp0, temp1, temp2, temp3, temp4, temp5, temp6; + StkFloat filtout; + + temp = allpassDelays_[0].lastOut(); + temp0 = allpassCoefficient_ * temp; + temp0 += input; + allpassDelays_[0].tick(temp0); + temp0 = -(allpassCoefficient_ * temp0) + temp; + + temp = allpassDelays_[1].lastOut(); + temp1 = allpassCoefficient_ * temp; + temp1 += temp0; + allpassDelays_[1].tick(temp1); + temp1 = -(allpassCoefficient_ * temp1) + temp; + + temp = allpassDelays_[2].lastOut(); + temp2 = allpassCoefficient_ * temp; + temp2 += temp1; + allpassDelays_[2].tick(temp2); + temp2 = -(allpassCoefficient_ * temp2) + temp; + + temp3 = temp2 + (combCoefficient_[0] * combDelays_[0].lastOut()); + temp4 = temp2 + (combCoefficient_[1] * combDelays_[1].lastOut()); + temp5 = temp2 + (combCoefficient_[2] * combDelays_[2].lastOut()); + temp6 = temp2 + (combCoefficient_[3] * combDelays_[3].lastOut()); + + combDelays_[0].tick(temp3); + combDelays_[1].tick(temp4); + combDelays_[2].tick(temp5); + combDelays_[3].tick(temp6); + + filtout = temp3 + temp4 + temp5 + temp6; + + lastOutput_[0] = effectMix_ * (outLeftDelay_.tick(filtout)); + lastOutput_[1] = effectMix_ * (outRightDelay_.tick(filtout)); + temp = (1.0 - effectMix_) * input; + lastOutput_[0] += temp; + lastOutput_[1] += temp; + + return Effect::lastOut(); +} diff --git a/nyqstk/src/JetTable.cpp b/nyqstk/src/JetTable.cpp new file mode 100644 index 0000000..0049a79 --- /dev/null +++ b/nyqstk/src/JetTable.cpp @@ -0,0 +1,41 @@ +/***************************************************/ +/*! \class JetTable + \brief STK jet table class. + + This class implements a flue jet non-linear + function, computed by a polynomial calculation. + Contrary to the name, this is not a "table". + + Consult Fletcher and Rossing, Karjalainen, + Cook, and others for more information. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "JetTable.h" + +using namespace Nyq; + +JetTable :: JetTable() : Function() +{ +} + +JetTable :: ~JetTable() +{ +} + +StkFloat JetTable :: computeSample( StkFloat input ) +{ + // Perform "table lookup" using a polynomial + // calculation (x^3 - x), which approximates + // the jet sigmoid behavior. + lastOutput_ = input * (input * input - (StkFloat) 1.0); + + // Saturate at +/- 1.0. + if (lastOutput_ > 1.0) + lastOutput_ = (StkFloat) 1.0; + if (lastOutput_ < -1.0) + lastOutput_ = (StkFloat) -1.0; + return lastOutput_; +} diff --git a/nyqstk/src/Mandolin.cpp b/nyqstk/src/Mandolin.cpp new file mode 100644 index 0000000..a1d5cf2 --- /dev/null +++ b/nyqstk/src/Mandolin.cpp @@ -0,0 +1,188 @@ +/***************************************************/ +/*! \class Mandolin + \brief STK mandolin instrument model class. + + This class inherits from PluckTwo and uses + "commuted synthesis" techniques to model a + mandolin instrument. + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + Commuted Synthesis, in particular, is covered + by patents, granted, pending, and/or + applied-for. All are assigned to the Board of + Trustees, Stanford University. For + information, contact the Office of Technology + Licensing, Stanford University. + + Control Change Numbers: + - Body Size = 2 + - Pluck Position = 4 + - String Sustain = 11 + - String Detuning = 1 + - Microphone Position = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Mandolin.h" +#include "SKINI.msg" + +using namespace Nyq; + +Mandolin :: Mandolin(StkFloat lowestFrequency) + : PluckTwo(lowestFrequency) +{ + // Concatenate the STK rawwave path to the rawwave files + soundfile_[0] = new FileWvIn( (Stk::rawwavePath() + "mand1.raw").c_str(), true ); + soundfile_[1] = new FileWvIn( (Stk::rawwavePath() + "mand2.raw").c_str(), true ); + soundfile_[2] = new FileWvIn( (Stk::rawwavePath() + "mand3.raw").c_str(), true ); + soundfile_[3] = new FileWvIn( (Stk::rawwavePath() + "mand4.raw").c_str(), true ); + soundfile_[4] = new FileWvIn( (Stk::rawwavePath() + "mand5.raw").c_str(), true ); + soundfile_[5] = new FileWvIn( (Stk::rawwavePath() + "mand6.raw").c_str(), true ); + soundfile_[6] = new FileWvIn( (Stk::rawwavePath() + "mand7.raw").c_str(), true ); + soundfile_[7] = new FileWvIn( (Stk::rawwavePath() + "mand8.raw").c_str(), true ); + soundfile_[8] = new FileWvIn( (Stk::rawwavePath() + "mand9.raw").c_str(), true ); + soundfile_[9] = new FileWvIn( (Stk::rawwavePath() + "mand10.raw").c_str(), true ); + soundfile_[10] = new FileWvIn( (Stk::rawwavePath() + "mand11.raw").c_str(), true ); + soundfile_[11] = new FileWvIn( (Stk::rawwavePath() + "mand12.raw").c_str(), true ); + + mic_ = 0; + dampTime_ = 0; + waveDone_ = soundfile_[mic_]->isFinished(); +} + +Mandolin :: ~Mandolin() +{ + for ( int i=0; i<12; i++ ) + delete soundfile_[i]; +} + +void Mandolin :: pluck(StkFloat amplitude) +{ + // This function gets interesting, because pluck + // may be longer than string length, so we just + // reset the soundfile and add in the pluck in + // the tick method. + soundfile_[mic_]->reset(); + waveDone_ = false; + pluckAmplitude_ = amplitude; + if ( amplitude < 0.0 ) { + errorString_ << "Mandolin::pluck: amplitude parameter less than zero ... setting to 0.0!"; + handleError( StkError::WARNING ); + pluckAmplitude_ = 0.0; + } + else if ( amplitude > 1.0 ) { + errorString_ << "Mandolin::pluck: amplitude parameter greater than one ... setting to 1.0!"; + handleError( StkError::WARNING ); + pluckAmplitude_ = 1.0; + } + + // Set the pick position, which puts zeroes at position * length. + combDelay_.setDelay( 0.5 * pluckPosition_ * lastLength_ ); + dampTime_ = (long) lastLength_; // See tick method below. +} + +void Mandolin :: pluck(StkFloat amplitude, StkFloat position) +{ + // Pluck position puts zeroes at position * length. + pluckPosition_ = position; + if ( position < 0.0 ) { + std::cerr << "Mandolin::pluck: position parameter less than zero ... setting to 0.0!"; + handleError( StkError::WARNING ); + pluckPosition_ = 0.0; + } + else if ( position > 1.0 ) { + errorString_ << "Mandolin::pluck: amplitude parameter greater than one ... setting to 1.0!"; + handleError( StkError::WARNING ); + pluckPosition_ = 1.0; + } + + this->pluck( amplitude ); +} + +void Mandolin :: noteOn(StkFloat frequency, StkFloat amplitude) +{ + this->setFrequency( frequency ); + this->pluck( amplitude ); + +#if defined(_STK_DEBUG_) + errorString_ << "Mandolin::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Mandolin :: setBodySize(StkFloat size) +{ + // Scale the commuted body response by its sample rate (22050). + StkFloat rate = size * 22050.0 / Stk::sampleRate(); + for ( int i=0; i<12; i++ ) + soundfile_[i]->setRate( rate ); +} + +StkFloat Mandolin :: computeSample() +{ + StkFloat temp = 0.0; + if ( !waveDone_ ) { + // Scale the pluck excitation with comb + // filtering for the duration of the file. + temp = soundfile_[mic_]->tick() * pluckAmplitude_; + temp = temp - combDelay_.tick(temp); + waveDone_ = soundfile_[mic_]->isFinished(); + } + + // Damping hack to help avoid overflow on re-plucking. + if ( dampTime_ >=0 ) { + dampTime_ -= 1; + // Calculate 1st delay filtered reflection plus pluck excitation. + lastOutput_ = delayLine_.tick( filter_.tick( temp + (delayLine_.lastOut() * 0.7) ) ); + // Calculate 2nd delay just like the 1st. + lastOutput_ += delayLine2_.tick( filter2_.tick( temp + (delayLine2_.lastOut() * 0.7) ) ); + } + else { // No damping hack after 1 period. + // Calculate 1st delay filtered reflection plus pluck excitation. + lastOutput_ = delayLine_.tick( filter_.tick( temp + (delayLine_.lastOut() * loopGain_) ) ); + // Calculate 2nd delay just like the 1st. + lastOutput_ += delayLine2_.tick( filter2_.tick( temp + (delayLine2_.lastOut() * loopGain_) ) ); + } + + lastOutput_ *= 0.3; + return lastOutput_; +} + +void Mandolin :: controlChange(int number, StkFloat value) +{ + StkFloat norm = value * ONE_OVER_128; + if ( norm < 0 ) { + norm = 0.0; + errorString_ << "Mandolin::controlChange: control value less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + } + else if ( norm > 1.0 ) { + norm = 1.0; + errorString_ << "Mandolin::controlChange: control value greater than 128.0 ... setting to 128.0!"; + handleError( StkError::WARNING ); + } + + if (number == __SK_BodySize_) // 2 + this->setBodySize( norm * 2.0 ); + else if (number == __SK_PickPosition_) // 4 + this->setPluckPosition( norm ); + else if (number == __SK_StringDamping_) // 11 + this->setBaseLoopGain( 0.97 + (norm * 0.03)); + else if (number == __SK_StringDetune_) // 1 + this->setDetune( 1.0 - (norm * 0.1) ); + else if (number == __SK_AfterTouch_Cont_) // 128 + mic_ = (int) (norm * 11.0); + else { + errorString_ << "Mandolin::controlChange: undefined control number (" << number << ")!"; + handleError( StkError::WARNING ); + } + +#if defined(_STK_DEBUG_) + errorString_ << "Mandolin::controlChange: number = " << number << ", value = " << value << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} diff --git a/nyqstk/src/Modal.cpp b/nyqstk/src/Modal.cpp new file mode 100644 index 0000000..da00f25 --- /dev/null +++ b/nyqstk/src/Modal.cpp @@ -0,0 +1,210 @@ +/***************************************************/ +/*! \class Modal + \brief STK resonance model instrument. + + This class contains an excitation wavetable, + an envelope, an oscillator, and N resonances + (non-sweeping BiQuad filters), where N is set + during instantiation. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Modal.h" +#include + +using namespace Nyq; + +Modal :: Modal(unsigned int modes) + : nModes_(modes) +{ + if ( nModes_ == 0 ) { + errorString_ << "Modal: 'modes' argument to constructor is zero!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + // We don't make the excitation wave here yet, because we don't know + // what it's going to be. + + ratios_.resize( nModes_ ); + radii_.resize( nModes_ ); + filters_ = (BiQuad **) calloc( nModes_, sizeof(BiQuad *) ); + for (unsigned int i=0; isetEqualGainZeroes(); + } + + // Set some default values. + vibrato_.setFrequency( 6.0 ); + vibratoGain_ = 0.0; + directGain_ = 0.0; + masterGain_ = 1.0; + baseFrequency_ = 440.0; + + this->clear(); + + stickHardness_ = 0.5; + strikePosition_ = 0.561; +} + +Modal :: ~Modal() +{ + for (unsigned int i=0; iclear(); +} + +void Modal :: setFrequency(StkFloat frequency) +{ + baseFrequency_ = frequency; + for (unsigned int i=0; isetRatioAndRadius( i, ratios_[i], radii_[i] ); +} + +void Modal :: setRatioAndRadius(unsigned int modeIndex, StkFloat ratio, StkFloat radius) +{ + if ( modeIndex >= nModes_ ) { + errorString_ << "Modal::setRatioAndRadius: modeIndex parameter is greater than number of modes!"; + handleError( StkError::WARNING ); + return; + } + + StkFloat nyquist = Stk::sampleRate() / 2.0; + StkFloat temp; + + if ( ratio * baseFrequency_ < nyquist ) { + ratios_[modeIndex] = ratio; + } + else { + temp = ratio; + while (temp * baseFrequency_ > nyquist) temp *= 0.5; + ratios_[modeIndex] = temp; +#if defined(_STK_DEBUG_) + errorString_ << "Modal::setRatioAndRadius: aliasing would occur here ... correcting."; + handleError( StkError::DEBUG_WARNING ); +#endif + } + radii_[modeIndex] = radius; + if (ratio < 0) + temp = -ratio; + else + temp = ratio * baseFrequency_; + + filters_[modeIndex]->setResonance(temp, radius); +} + +void Modal :: setMasterGain(StkFloat aGain) +{ + masterGain_ = aGain; +} + +void Modal :: setDirectGain(StkFloat aGain) +{ + directGain_ = aGain; +} + +void Modal :: setModeGain(unsigned int modeIndex, StkFloat gain) +{ + if ( modeIndex >= nModes_ ) { + errorString_ << "Modal::setModeGain: modeIndex parameter is greater than number of modes!"; + handleError( StkError::WARNING ); + return; + } + + filters_[modeIndex]->setGain(gain); +} + +void Modal :: strike(StkFloat amplitude) +{ + StkFloat gain = amplitude; + if ( amplitude < 0.0 ) { + errorString_ << "Modal::strike: amplitude is less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + gain = 0.0; + } + else if ( amplitude > 1.0 ) { + errorString_ << "Modal::strike: amplitude is greater than one ... setting to 1.0!"; + handleError( StkError::WARNING ); + gain = 1.0; + } + + envelope_.setRate( 1.0 ); + envelope_.setTarget( gain ); + onepole_.setPole( 1.0 - gain ); + envelope_.tick(); + wave_->reset(); + + StkFloat temp; + for (unsigned int i=0; isetResonance(temp, radii_[i]); + } +} + +void Modal :: noteOn(StkFloat frequency, StkFloat amplitude) +{ + this->strike(amplitude); + this->setFrequency(frequency); + +#if defined(_STK_DEBUG_) + errorString_ << "Modal::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.'; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Modal :: noteOff(StkFloat amplitude) +{ + // This calls damp, but inverts the meaning of amplitude (high + // amplitude means fast damping). + this->damp( 1.0 - (amplitude * 0.03) ); + +#if defined(_STK_DEBUG_) + errorString_ << "Modal::NoteOff: amplitude = " << amplitude << '.'; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Modal :: damp(StkFloat amplitude) +{ + StkFloat temp; + for (unsigned int i=0; isetResonance(temp, radii_[i]*amplitude); + } +} + +StkFloat Modal :: computeSample() +{ + StkFloat temp = masterGain_ * onepole_.tick( wave_->tick() * envelope_.tick() ); + + StkFloat temp2 = 0.0; + for (unsigned int i=0; itick(temp); + + temp2 -= temp2 * directGain_; + temp2 += directGain_ * temp; + + if (vibratoGain_ != 0.0) { + // Calculate AM and apply to master out + temp = 1.0 + (vibrato_.tick() * vibratoGain_); + temp2 = temp * temp2; + } + + lastOutput_ = temp2; + return lastOutput_; +} diff --git a/nyqstk/src/ModalBar.cpp b/nyqstk/src/ModalBar.cpp new file mode 100644 index 0000000..38e2165 --- /dev/null +++ b/nyqstk/src/ModalBar.cpp @@ -0,0 +1,198 @@ +/***************************************************/ +/*! \class ModalBar + \brief STK resonant bar instrument class. + + This class implements a number of different + struck bar instruments. It inherits from the + Modal class. + + Control Change Numbers: + - Stick Hardness = 2 + - Stick Position = 4 + - Vibrato Gain = 8 + - Vibrato Frequency = 11 + - Direct Stick Mix = 1 + - Volume = 128 + - Modal Presets = 16 + - Marimba = 0 + - Vibraphone = 1 + - Agogo = 2 + - Wood1 = 3 + - Reso = 4 + - Wood2 = 5 + - Beats = 6 + - Two Fixed = 7 + - Clump = 8 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "ModalBar.h" +#include "SKINI.msg" +#include + +using namespace Nyq; + +ModalBar :: ModalBar() + : Modal() +{ + // Concatenate the STK rawwave path to the rawwave file + wave_ = new FileWvIn( (Stk::rawwavePath() + "marmstk1.raw").c_str(), true ); + wave_->setRate( 0.5 * 22050.0 / Stk::sampleRate() ); + + // Set the resonances for preset 0 (marimba). + this->setPreset( 0 ); +} + +ModalBar :: ~ModalBar() +{ + delete wave_; +} + +void ModalBar :: setStickHardness(StkFloat hardness) +{ + stickHardness_ = hardness; + if ( hardness < 0.0 ) { + errorString_ << "ModalBar::setStickHardness: parameter is less than zero ... setting to 0.0!"; + handleError( StkError::WARNING ); + stickHardness_ = 0.0; + } + else if ( hardness > 1.0 ) { + errorString_ << "ModalBar::setStickHarness: parameter is greater than one ... setting to 1.0!"; + handleError( StkError::WARNING ); + stickHardness_ = 1.0; + } + + wave_->setRate( (0.25 * pow(4.0, stickHardness_) ) ); + masterGain_ = 0.1 + (1.8 * stickHardness_); +} + +void ModalBar :: setStrikePosition(StkFloat position) +{ + strikePosition_ = position; + if ( position < 0.0 ) { + errorString_ << "ModalBar::setStrikePosition: parameter is less than zero ... setting to 0.0!"; + handleError( StkError::WARNING ); + strikePosition_ = 0.0; + } + else if ( position > 1.0 ) { + errorString_ << "ModalBar::setStrikePosition: parameter is greater than one ... setting to 1.0!"; + handleError( StkError::WARNING ); + strikePosition_ = 1.0; + } + + // Hack only first three modes. + StkFloat temp2 = position * PI; + StkFloat temp = sin(temp2); + this->setModeGain(0, 0.12 * temp); + + temp = sin(0.05 + (3.9 * temp2)); + this->setModeGain(1, -0.03 * temp); + + temp = sin(-0.05 + (11 * temp2)); + this->setModeGain(2, 0.11 * temp); +} + +void ModalBar :: setPreset(int preset) +{ + // Presets: + // First line: relative modal frequencies (negative number is + // a fixed mode that doesn't scale with frequency + // Second line: resonances of the modes + // Third line: mode volumes + // Fourth line: stickHardness, strikePosition, and direct stick + // gain (mixed directly into the output + static StkFloat presets[9][4][4] = { + {{1.0, 3.99, 10.65, -2443}, // Marimba + {0.9996, 0.9994, 0.9994, 0.999}, + {0.04, 0.01, 0.01, 0.008}, + {0.429688, 0.445312, 0.093750}}, + {{1.0, 2.01, 3.9, 14.37}, // Vibraphone + {0.99995, 0.99991, 0.99992, 0.9999}, + {0.025, 0.015, 0.015, 0.015 }, + {0.390625,0.570312,0.078125}}, + {{1.0, 4.08, 6.669, -3725.0}, // Agogo + {0.999, 0.999, 0.999, 0.999}, + {0.06, 0.05, 0.03, 0.02}, + {0.609375,0.359375,0.140625}}, + {{1.0, 2.777, 7.378, 15.377}, // Wood1 + {0.996, 0.994, 0.994, 0.99}, + {0.04, 0.01, 0.01, 0.008}, + {0.460938,0.375000,0.046875}}, + {{1.0, 2.777, 7.378, 15.377}, // Reso + {0.99996, 0.99994, 0.99994, 0.9999}, + {0.02, 0.005, 0.005, 0.004}, + {0.453125,0.250000,0.101562}}, + {{1.0, 1.777, 2.378, 3.377}, // Wood2 + {0.996, 0.994, 0.994, 0.99}, + {0.04, 0.01, 0.01, 0.008}, + {0.312500,0.445312,0.109375}}, + {{1.0, 1.004, 1.013, 2.377}, // Beats + {0.9999, 0.9999, 0.9999, 0.999}, + {0.02, 0.005, 0.005, 0.004}, + {0.398438,0.296875,0.070312}}, + {{1.0, 4.0, -1320.0, -3960.0}, // 2Fix + {0.9996, 0.999, 0.9994, 0.999}, + {0.04, 0.01, 0.01, 0.008}, + {0.453125,0.453125,0.070312}}, + {{1.0, 1.217, 1.475, 1.729}, // Clump + {0.999, 0.999, 0.999, 0.999}, + {0.03, 0.03, 0.03, 0.03 }, + {0.390625,0.570312,0.078125}}, + }; + + int temp = (preset % 9); + for (unsigned int i=0; isetRatioAndRadius(i, presets[temp][0][i], presets[temp][1][i]); + this->setModeGain(i, presets[temp][2][i]); + } + + this->setStickHardness(presets[temp][3][0]); + this->setStrikePosition(presets[temp][3][1]); + directGain_ = presets[temp][3][2]; + + if (temp == 1) // vibraphone + vibratoGain_ = 0.2; + else + vibratoGain_ = 0.0; +} + +void ModalBar :: controlChange(int number, StkFloat value) +{ + StkFloat norm = value * ONE_OVER_128; + if ( norm < 0 ) { + norm = 0.0; + errorString_ << "ModalBar::controlChange: control value less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + } + else if ( norm > 1.0 ) { + norm = 1.0; + errorString_ << "ModalBar::controlChange: control value greater than 128.0 ... setting to 128.0!"; + handleError( StkError::WARNING ); + } + + if (number == __SK_StickHardness_) // 2 + this->setStickHardness( norm ); + else if (number == __SK_StrikePosition_) // 4 + this->setStrikePosition( norm ); + else if (number == __SK_ProphesyRibbon_) // 16 + this->setPreset((int) value); + else if (number == __SK_Balance_) // 8 + vibratoGain_ = norm * 0.3; + else if (number == __SK_ModWheel_) // 1 + directGain_ = norm; + else if (number == __SK_ModFrequency_) // 11 + vibrato_.setFrequency( norm * 12.0 ); + else if (number == __SK_AfterTouch_Cont_) // 128 + envelope_.setTarget( norm ); + else { + errorString_ << "ModalBar::controlChange: undefined control number (" << number << ")!"; + handleError( StkError::WARNING ); + } + +#if defined(_STK_DEBUG_) + errorString_ << "ModalBar::controlChange: number = " << number << ", value = " << value << '.'; + handleError( StkError::DEBUG_WARNING ); +#endif +} diff --git a/nyqstk/src/NRev.cpp b/nyqstk/src/NRev.cpp new file mode 100644 index 0000000..55f2b96 --- /dev/null +++ b/nyqstk/src/NRev.cpp @@ -0,0 +1,117 @@ +/***************************************************/ +/*! \class NRev + \brief CCRMA's NRev reverberator class. + + This class is derived from the CLM NRev + function, which is based on the use of + networks of simple allpass and comb delay + filters. This particular arrangement consists + of 6 comb filters in parallel, followed by 3 + allpass filters, a lowpass filter, and another + allpass in series, followed by two allpass + filters in parallel with corresponding right + and left outputs. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "NRev.h" +#include + +using namespace Nyq; + +NRev :: NRev(StkFloat T60) +{ + int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; + double scaler = Stk::sampleRate() / 25641.0; + + int delay, i; + for (i=0; i<15; i++) { + delay = (int) floor(scaler * lengths[i]); + if ( (delay & 1) == 0) delay++; + while ( !this->isPrime(delay) ) delay += 2; + lengths[i] = delay; + } + + for (i=0; i<6; i++) { + combDelays_[i].setMaximumDelay( lengths[i] ); + combDelays_[i].setDelay( lengths[i] ); + combCoefficient_[i] = pow(10.0, (-3 * lengths[i] / (T60 * Stk::sampleRate()))); + } + + for (i=0; i<8; i++) { + allpassDelays_[i].setMaximumDelay( lengths[i+6] ); + allpassDelays_[i].setDelay( lengths[i+6] ); + } + + this->setT60( T60 ); + allpassCoefficient_ = 0.7; + effectMix_ = 0.3; + this->clear(); +} + +NRev :: ~NRev() +{ +} + +void NRev :: clear() +{ + int i; + for (i=0; i<6; i++) combDelays_[i].clear(); + for (i=0; i<8; i++) allpassDelays_[i].clear(); + lastOutput_[0] = 0.0; + lastOutput_[1] = 0.0; + lowpassState_ = 0.0; +} + +void NRev :: setT60( StkFloat T60 ) +{ + for ( int i=0; i<6; i++ ) + combCoefficient_[i] = pow(10.0, (-3.0 * combDelays_[i].getDelay() / (T60 * Stk::sampleRate()))); +} + +StkFloat NRev :: computeSample(StkFloat input) +{ + StkFloat temp, temp0, temp1, temp2, temp3; + int i; + + temp0 = 0.0; + for (i=0; i<6; i++) { + temp = input + (combCoefficient_[i] * combDelays_[i].lastOut()); + temp0 += combDelays_[i].tick(temp); + } + for (i=0; i<3; i++) { + temp = allpassDelays_[i].lastOut(); + temp1 = allpassCoefficient_ * temp; + temp1 += temp0; + allpassDelays_[i].tick(temp1); + temp0 = -(allpassCoefficient_ * temp1) + temp; + } + + // One-pole lowpass filter. + lowpassState_ = 0.7*lowpassState_ + 0.3*temp0; + temp = allpassDelays_[3].lastOut(); + temp1 = allpassCoefficient_ * temp; + temp1 += lowpassState_; + allpassDelays_[3].tick(temp1); + temp1 = -(allpassCoefficient_ * temp1) + temp; + + temp = allpassDelays_[4].lastOut(); + temp2 = allpassCoefficient_ * temp; + temp2 += temp1; + allpassDelays_[4].tick(temp2); + lastOutput_[0] = effectMix_*(-(allpassCoefficient_ * temp2) + temp); + + temp = allpassDelays_[5].lastOut(); + temp3 = allpassCoefficient_ * temp; + temp3 += temp1; + allpassDelays_[5].tick(temp3); + lastOutput_[1] = effectMix_*(-(allpassCoefficient_ * temp3) + temp); + + temp = (1.0 - effectMix_) * input; + lastOutput_[0] += temp; + lastOutput_[1] += temp; + + return Effect::lastOut(); +} diff --git a/nyqstk/src/Noise.cpp b/nyqstk/src/Noise.cpp new file mode 100644 index 0000000..d982e02 --- /dev/null +++ b/nyqstk/src/Noise.cpp @@ -0,0 +1,51 @@ +/***************************************************/ +/*! \class Noise + \brief STK noise generator. + + Generic random number generation using the + C rand() function. The quality of the rand() + function varies from one OS to another. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Noise.h" +#include +#include + +using namespace Nyq; + +Noise :: Noise() : Generator() +{ + // Seed the random number generator with system time. + this->setSeed( 0 ); + lastOutput_ = (StkFloat) 0.0; +} + +Noise :: Noise( unsigned int seed ) : Generator() +{ + // Seed the random number generator + this->setSeed( seed ); + lastOutput_ = (StkFloat) 0.0; +} + +Noise :: ~Noise() +{ +} + +void Noise :: setSeed( unsigned int seed ) +{ + if ( seed == 0 ) + srand( (unsigned int) time(NULL) ); + else + srand( seed ); +} + +StkFloat Noise :: computeSample() +{ + lastOutput_ = (StkFloat) (2.0 * rand() / (RAND_MAX + 1.0) ); + lastOutput_ -= 1.0; + return lastOutput_; +} + diff --git a/nyqstk/src/OnePole.cpp b/nyqstk/src/OnePole.cpp new file mode 100644 index 0000000..97eee7b --- /dev/null +++ b/nyqstk/src/OnePole.cpp @@ -0,0 +1,99 @@ +/***************************************************/ +/*! \class OnePole + \brief STK one-pole filter class. + + This protected Filter subclass implements + a one-pole digital filter. A method is + provided for setting the pole position along + the real axis of the z-plane while maintaining + a constant peak filter gain. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "OnePole.h" + +using namespace Nyq; + +OnePole :: OnePole() : Filter() +{ + std::vector b(1, 0.1); + std::vector a(2, 1.0); + a[1] = -0.9; + Filter::setCoefficients( b, a ); +} + +OnePole :: OnePole(StkFloat thePole) : Filter() +{ + std::vector b(1); + std::vector a(2, 1.0); + a[1] = -thePole; + + // Normalize coefficients for peak unity gain. + if (thePole > 0.0) + b[0] = (StkFloat) (1.0 - thePole); + else + b[0] = (StkFloat) (1.0 + thePole); + + Filter::setCoefficients( b, a ); +} + +OnePole :: ~OnePole() +{ +} + +void OnePole :: clear(void) +{ + Filter::clear(); +} + +void OnePole :: setB0(StkFloat b0) +{ + b_[0] = b0; +} + +void OnePole :: setA1(StkFloat a1) +{ + a_[1] = a1; +} + +void OnePole :: setPole(StkFloat thePole) +{ + // Normalize coefficients for peak unity gain. + if (thePole > 0.0) + b_[0] = (StkFloat) (1.0 - thePole); + else + b_[0] = (StkFloat) (1.0 + thePole); + + a_[1] = -thePole; +} + +void OnePole :: setGain(StkFloat gain) +{ + Filter::setGain(gain); +} + +StkFloat OnePole :: getGain(void) const +{ + return Filter::getGain(); +} + +StkFloat OnePole :: lastOut(void) const +{ + return Filter::lastOut(); +} + +StkFloat OnePole :: tick( StkFloat input ) +{ + inputs_[0] = gain_ * input; + outputs_[0] = b_[0] * inputs_[0] - a_[1] * outputs_[1]; + outputs_[1] = outputs_[0]; + + return outputs_[0]; +} + +StkFrames& OnePole :: tick( StkFrames& frames, unsigned int channel ) +{ + return Filter::tick( frames, channel ); +} diff --git a/nyqstk/src/OneZero.cpp b/nyqstk/src/OneZero.cpp new file mode 100644 index 0000000..2aed1c1 --- /dev/null +++ b/nyqstk/src/OneZero.cpp @@ -0,0 +1,98 @@ +/***************************************************/ +/*! \class OneZero + \brief STK one-zero filter class. + + This protected Filter subclass implements + a one-zero digital filter. A method is + provided for setting the zero position + along the real axis of the z-plane while + maintaining a constant filter gain. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "OneZero.h" + +using namespace Nyq; + +OneZero :: OneZero() : Filter() +{ + std::vector b(2, 0.5); + std::vector a(1, 1.0); + Filter::setCoefficients( b, a ); +} + +OneZero :: OneZero(StkFloat theZero) : Filter() +{ + std::vector b(2); + std::vector a(1, 1.0); + + // Normalize coefficients for unity gain. + if (theZero > 0.0) + b[0] = 1.0 / ((StkFloat) 1.0 + theZero); + else + b[0] = 1.0 / ((StkFloat) 1.0 - theZero); + + b[1] = -theZero * b[0]; + Filter::setCoefficients( b, a ); +} + +OneZero :: ~OneZero(void) +{ +} + +void OneZero :: clear(void) +{ + Filter::clear(); +} + +void OneZero :: setB0(StkFloat b0) +{ + b_[0] = b0; +} + +void OneZero :: setB1(StkFloat b1) +{ + b_[1] = b1; +} + +void OneZero :: setZero(StkFloat theZero) +{ + // Normalize coefficients for unity gain. + if (theZero > 0.0) + b_[0] = 1.0 / ((StkFloat) 1.0 + theZero); + else + b_[0] = 1.0 / ((StkFloat) 1.0 - theZero); + + b_[1] = -theZero * b_[0]; +} + +void OneZero :: setGain(StkFloat gain) +{ + Filter::setGain(gain); +} + +StkFloat OneZero :: getGain(void) const +{ + return Filter::getGain(); +} + +StkFloat OneZero :: lastOut(void) const +{ + return Filter::lastOut(); +} + +StkFloat OneZero :: tick( StkFloat input ) +{ + inputs_[0] = gain_ * input; + outputs_[0] = b_[1] * inputs_[1] + b_[0] * inputs_[0]; + inputs_[1] = inputs_[0]; + + return outputs_[0]; +} + +StkFrames& OneZero :: tick( StkFrames& frames, unsigned int channel ) +{ + return Filter::tick( frames, channel ); +} diff --git a/nyqstk/src/PRCRev.cpp b/nyqstk/src/PRCRev.cpp new file mode 100644 index 0000000..c357b38 --- /dev/null +++ b/nyqstk/src/PRCRev.cpp @@ -0,0 +1,100 @@ +/***************************************************/ +/*! \class PRCRev + \brief Perry's simple reverberator class. + + This class is based on some of the famous + Stanford/CCRMA reverbs (NRev, KipRev), which + were based on the Chowning/Moorer/Schroeder + reverberators using networks of simple allpass + and comb delay filters. This class implements + two series allpass units and two parallel comb + filters. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "PRCRev.h" +#include + +using namespace Nyq; + +PRCRev :: PRCRev(StkFloat T60) +{ + // Delay lengths for 44100 Hz sample rate. + int lengths[4]= {353, 1097, 1777, 2137}; + double scaler = Stk::sampleRate() / 44100.0; + + // Scale the delay lengths if necessary. + int delay, i; + if ( scaler != 1.0 ) { + for (i=0; i<4; i++) { + delay = (int) floor(scaler * lengths[i]); + if ( (delay & 1) == 0) delay++; + while ( !this->isPrime(delay) ) delay += 2; + lengths[i] = delay; + } + } + + for (i=0; i<2; i++) { + allpassDelays_[i].setMaximumDelay( lengths[i] ); + allpassDelays_[i].setDelay( lengths[i] ); + + combDelays_[i].setMaximumDelay( lengths[i+2] ); + combDelays_[i].setDelay( lengths[i+2] ); + } + + this->setT60( T60 ); + allpassCoefficient_ = 0.7; + effectMix_ = 0.5; + this->clear(); +} + +PRCRev :: ~PRCRev() +{ +} + +void PRCRev :: clear() +{ + allpassDelays_[0].clear(); + allpassDelays_[1].clear(); + combDelays_[0].clear(); + combDelays_[1].clear(); + lastOutput_[0] = 0.0; + lastOutput_[1] = 0.0; +} + +void PRCRev :: setT60( StkFloat T60 ) +{ + combCoefficient_[0] = pow(10.0, (-3.0 * combDelays_[0].getDelay() / (T60 * Stk::sampleRate()))); + combCoefficient_[1] = pow(10.0, (-3.0 * combDelays_[1].getDelay() / (T60 * Stk::sampleRate()))); +} + +StkFloat PRCRev :: computeSample(StkFloat input) +{ + StkFloat temp, temp0, temp1, temp2, temp3; + + temp = allpassDelays_[0].lastOut(); + temp0 = allpassCoefficient_ * temp; + temp0 += input; + allpassDelays_[0].tick(temp0); + temp0 = -(allpassCoefficient_ * temp0) + temp; + + temp = allpassDelays_[1].lastOut(); + temp1 = allpassCoefficient_ * temp; + temp1 += temp0; + allpassDelays_[1].tick(temp1); + temp1 = -(allpassCoefficient_ * temp1) + temp; + + temp2 = temp1 + (combCoefficient_[0] * combDelays_[0].lastOut()); + temp3 = temp1 + (combCoefficient_[1] * combDelays_[1].lastOut()); + + lastOutput_[0] = effectMix_ * (combDelays_[0].tick(temp2)); + lastOutput_[1] = effectMix_ * (combDelays_[1].tick(temp3)); + temp = (1.0 - effectMix_) * input; + lastOutput_[0] += temp; + lastOutput_[1] += temp; + + return Effect::lastOut(); +} + diff --git a/nyqstk/src/PitShift.cpp b/nyqstk/src/PitShift.cpp new file mode 100644 index 0000000..97fd986 --- /dev/null +++ b/nyqstk/src/PitShift.cpp @@ -0,0 +1,90 @@ +/***************************************************/ +/*! \class PitShift + \brief STK simple pitch shifter effect class. + + This class implements a simple pitch shifter + using delay lines. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "PitShift.h" +#include + +using namespace Nyq; + +const int maxDelay = 5024; + +PitShift :: PitShift() +{ + delayLength = maxDelay - 24; + halfLength = delayLength / 2; + delay_[0] = 12; + delay_[1] = maxDelay / 2; + + delayLine_[0].setMaximumDelay( maxDelay ); + delayLine_[0].setDelay( delay_[0] ); + delayLine_[1].setMaximumDelay( maxDelay ); + delayLine_[1].setDelay( delay_[1] ); + effectMix_ = 0.5; + rate_ = 1.0; +} + +PitShift :: ~PitShift() +{ +} + +void PitShift :: clear() +{ + delayLine_[0].clear(); + delayLine_[1].clear(); + lastOutput_[0] = 0.0; + lastOutput_[1] = 0.0; +} + +void PitShift :: setShift(StkFloat shift) +{ + if (shift < 1.0) { + rate_ = 1.0 - shift; + } + else if (shift > 1.0) { + rate_ = 1.0 - shift; + } + else { + rate_ = 0.0; + delay_[0] = halfLength+12; + } +} + +StkFloat PitShift :: computeSample(StkFloat input) +{ + // Calculate the two delay length values, keeping them within the + // range 12 to maxDelay-12. + delay_[0] += rate_; + while (delay_[0] > maxDelay-12) delay_[0] -= delayLength; + while (delay_[0] < 12) delay_[0] += delayLength; + + delay_[1] = delay_[0] + halfLength; + while (delay_[1] > maxDelay-12) delay_[1] -= delayLength; + while (delay_[1] < 12) delay_[1] += delayLength; + + // Set the new delay line lengths. + delayLine_[0].setDelay((long)delay_[0]); + delayLine_[1].setDelay((long)delay_[1]); + + // Calculate a triangular envelope. + env_[1] = fabs( (delay_[0] - halfLength + 12) * (1.0 / (halfLength+12) ) ); + env_[0] = 1.0 - env_[1]; + + // Delay input and apply envelope. + lastOutput_[0] = env_[0] * delayLine_[0].tick(input); + lastOutput_[0] += env_[1] * delayLine_[1].tick(input); + + // Compute effect mix and output. + lastOutput_[0] *= effectMix_; + lastOutput_[0] += (1.0 - effectMix_) * input; + lastOutput_[1] = lastOutput_[0]; + + return lastOutput_[0]; +} diff --git a/nyqstk/src/PluckTwo.cpp b/nyqstk/src/PluckTwo.cpp new file mode 100644 index 0000000..2d8ad4e --- /dev/null +++ b/nyqstk/src/PluckTwo.cpp @@ -0,0 +1,132 @@ +/***************************************************/ +/*! \class PluckTwo + \brief STK enhanced plucked string model class. + + This class implements an enhanced two-string, + plucked physical model, a la Jaffe-Smith, + Smith, and others. + + PluckTwo is an abstract class, with no excitation + specified. Therefore, it can't be directly + instantiated. + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "PluckTwo.h" + +using namespace Nyq; + +PluckTwo :: PluckTwo(StkFloat lowestFrequency) +{ + length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1); + lastLength_ = length_ * 0.5; + delayLine_.setMaximumDelay( length_ ); + delayLine_.setDelay( lastLength_ ); + delayLine2_.setMaximumDelay( length_ ); + delayLine2_.setDelay( lastLength_ ); + combDelay_.setMaximumDelay( length_ ); + combDelay_.setDelay( lastLength_ ); + + baseLoopGain_ = 0.995; + loopGain_ = 0.999; + pluckAmplitude_ = 0.3; + pluckPosition_ = 0.4; + detuning_ = 0.995; + lastFrequency_ = lowestFrequency * 2.0; + +} + +PluckTwo :: ~PluckTwo() +{ +} + +void PluckTwo :: clear() +{ + delayLine_.clear(); + delayLine2_.clear(); + combDelay_.clear(); + filter_.clear(); + filter2_.clear(); +} + +void PluckTwo :: setFrequency(StkFloat frequency) +{ + lastFrequency_ = frequency; + if ( lastFrequency_ <= 0.0 ) { + errorString_ << "Clarinet::setFrequency: parameter is less than or equal to zero!"; + handleError( StkError::WARNING ); + lastFrequency_ = 220.0; + } + + // Delay = length - approximate filter delay. + lastLength_ = Stk::sampleRate() / lastFrequency_; + StkFloat delay = (lastLength_ / detuning_) - 0.5; + if ( delay <= 0.0 ) delay = 0.3; + else if ( delay > length_ ) delay = length_; + delayLine_.setDelay( delay ); + + delay = (lastLength_ * detuning_) - 0.5; + if ( delay <= 0.0 ) delay = 0.3; + else if ( delay > length_ ) delay = length_; + delayLine2_.setDelay( delay ); + + loopGain_ = baseLoopGain_ + (frequency * 0.000005); + if ( loopGain_ > 1.0 ) loopGain_ = 0.99999; +} + +void PluckTwo :: setDetune(StkFloat detune) +{ + detuning_ = detune; + if ( detuning_ <= 0.0 ) { + errorString_ << "Clarinet::setDeturn: parameter is less than or equal to zero!"; + handleError( StkError::WARNING ); + detuning_ = 0.1; + } + delayLine_.setDelay(( lastLength_ / detuning_) - 0.5); + delayLine2_.setDelay( (lastLength_ * detuning_) - 0.5); +} + +void PluckTwo :: setFreqAndDetune(StkFloat frequency, StkFloat detune) +{ + detuning_ = detune; + this->setFrequency( frequency ); +} + +void PluckTwo :: setPluckPosition(StkFloat position) +{ + pluckPosition_ = position; + if ( position < 0.0 ) { + errorString_ << "PluckTwo::setPluckPosition: parameter is less than zero ... setting to 0.0!"; + handleError( StkError::WARNING ); + pluckPosition_ = 0.0; + } + else if ( position > 1.0 ) { + errorString_ << "PluckTwo::setPluckPosition: parameter is greater than one ... setting to 1.0!"; + handleError( StkError::WARNING ); + pluckPosition_ = 1.0; + } +} + +void PluckTwo :: setBaseLoopGain(StkFloat aGain) +{ + baseLoopGain_ = aGain; + loopGain_ = baseLoopGain_ + (lastFrequency_ * 0.000005); + if ( loopGain_ > 0.99999 ) loopGain_ = 0.99999; +} + +void PluckTwo :: noteOff(StkFloat amplitude) +{ + loopGain_ = (1.0 - amplitude) * 0.5; + +#if defined(_STK_DEBUG_) + errorString_ << "PluckTwo::NoteOff: amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + diff --git a/nyqstk/src/PoleZero.cpp b/nyqstk/src/PoleZero.cpp new file mode 100644 index 0000000..66ed574 --- /dev/null +++ b/nyqstk/src/PoleZero.cpp @@ -0,0 +1,97 @@ +/***************************************************/ +/*! \class PoleZero + \brief STK one-pole, one-zero filter class. + + This protected Filter subclass implements + a one-pole, one-zero digital filter. A + method is provided for creating an allpass + filter with a given coefficient. Another + method is provided to create a DC blocking filter. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "PoleZero.h" + +using namespace Nyq; + +PoleZero :: PoleZero() : Filter() +{ + // Default setting for pass-through. + std::vector b(2, 0.0); + std::vector a(2, 0.0); + b[0] = 1.0; + a[0] = 1.0; + Filter::setCoefficients( b, a ); +} + +PoleZero :: ~PoleZero() +{ +} + +void PoleZero :: clear(void) +{ + Filter::clear(); +} + +void PoleZero :: setB0(StkFloat b0) +{ + b_[0] = b0; +} + +void PoleZero :: setB1(StkFloat b1) +{ + b_[1] = b1; +} + +void PoleZero :: setA1(StkFloat a1) +{ + a_[1] = a1; +} + +void PoleZero :: setAllpass(StkFloat coefficient) +{ + b_[0] = coefficient; + b_[1] = 1.0; + a_[0] = 1.0; // just in case + a_[1] = coefficient; +} + +void PoleZero :: setBlockZero(StkFloat thePole) +{ + b_[0] = 1.0; + b_[1] = -1.0; + a_[0] = 1.0; // just in case + a_[1] = -thePole; +} + +void PoleZero :: setGain(StkFloat gain) +{ + Filter::setGain(gain); +} + +StkFloat PoleZero :: getGain(void) const +{ + return Filter::getGain(); +} + +StkFloat PoleZero :: lastOut(void) const +{ + return Filter::lastOut(); +} + +StkFloat PoleZero :: tick( StkFloat input ) +{ + inputs_[0] = gain_ * input; + outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] - a_[1] * outputs_[1]; + inputs_[1] = inputs_[0]; + outputs_[1] = outputs_[0]; + + return outputs_[0]; +} + +StkFrames& PoleZero :: tick( StkFrames& frames, unsigned int channel ) +{ + return Filter::tick( frames, channel ); +} diff --git a/nyqstk/src/ReedTabl.cpp b/nyqstk/src/ReedTabl.cpp new file mode 100644 index 0000000..4ca6d65 --- /dev/null +++ b/nyqstk/src/ReedTabl.cpp @@ -0,0 +1,71 @@ +/***************************************************/ +/*! \class ReedTabl + \brief STK reed table class. + + This class implements a simple one breakpoint, + non-linear reed function, as described by + Smith (1986). This function is based on a + memoryless non-linear spring model of the reed + (the reed mass is ignored) which saturates when + the reed collides with the mouthpiece facing. + + See McIntyre, Schumacher, & Woodhouse (1983), + Smith (1986), Hirschman, Cook, Scavone, and + others for more information. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2002. +*/ +/***************************************************/ + +#include "ReedTabl.h" + +ReedTabl :: ReedTabl() +{ + offSet = (MY_FLOAT) 0.6; // Offset is a bias, related to reed rest position. + slope = (MY_FLOAT) -0.8; // Slope corresponds loosely to reed stiffness. +} + +ReedTabl :: ~ReedTabl() +{ + +} + +void ReedTabl :: setOffset(MY_FLOAT aValue) +{ + offSet = aValue; +} + +void ReedTabl :: setSlope(MY_FLOAT aValue) +{ + slope = aValue; +} + +MY_FLOAT ReedTabl :: lastOut() const +{ + return lastOutput; +} + +MY_FLOAT ReedTabl :: tick(MY_FLOAT input) +{ + // The input is differential pressure across the reed. + lastOutput = offSet + (slope * input); + + // If output is > 1, the reed has slammed shut and the + // reflection function value saturates at 1.0. + if (lastOutput > 1.0) lastOutput = (MY_FLOAT) 1.0; + + // This is nearly impossible in a physical system, but + // a reflection function value of -1.0 corresponds to + // an open end (and no discontinuity in bore profile). + if (lastOutput < -1.0) lastOutput = (MY_FLOAT) -1.0; + return lastOutput; +} + +MY_FLOAT *ReedTabl :: tick(MY_FLOAT *vector, unsigned int vectorSize) +{ + for (unsigned int i=0; i 1, the reed has slammed shut and the + // reflection function value saturates at 1.0. + if (lastOutput_ > 1.0) lastOutput_ = (StkFloat) 1.0; + + // This is nearly impossible in a physical system, but + // a reflection function value of -1.0 corresponds to + // an open end (and no discontinuity in bore profile). + if (lastOutput_ < -1.0) lastOutput_ = (StkFloat) -1.0; + return lastOutput_; +} + diff --git a/nyqstk/src/Saxofony.cpp b/nyqstk/src/Saxofony.cpp new file mode 100644 index 0000000..ae4fb5a --- /dev/null +++ b/nyqstk/src/Saxofony.cpp @@ -0,0 +1,198 @@ +/***************************************************/ +/*! \class Saxofony + \brief STK faux conical bore reed instrument class. + + This class implements a "hybrid" digital + waveguide instrument that can generate a + variety of wind-like sounds. It has also been + referred to as the "blowed string" model. The + waveguide section is essentially that of a + string, with one rigid and one lossy + termination. The non-linear function is a + reed table. The string can be "blown" at any + point between the terminations, though just as + with strings, it is impossible to excite the + system at either end. If the excitation is + placed at the string mid-point, the sound is + that of a clarinet. At points closer to the + "bridge", the sound is closer to that of a + saxophone. See Scavone (2002) for more details. + + This is a digital waveguide model, making its + use possibly subject to patents held by Stanford + University, Yamaha, and others. + + Control Change Numbers: + - Reed Stiffness = 2 + - Reed Aperture = 26 + - Noise Gain = 4 + - Blow Position = 11 + - Vibrato Frequency = 29 + - Vibrato Gain = 1 + - Breath Pressure = 128 + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Saxofony.h" +#include "SKINI.msg" + +using namespace Nyq; + +Saxofony :: Saxofony(StkFloat lowestFrequency) +{ + length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1); + // Initialize blowing position to 0.2 of length / 2. + position_ = 0.2; + delays_[0].setMaximumDelay( length_ ); + delays_[0].setDelay( (1.0-position_) * (length_ >> 1) ); + delays_[1].setMaximumDelay( length_ ); + delays_[1].setDelay( (1.0-position_) * (length_ >> 1) ); + + reedTable_.setOffset( 0.7 ); + reedTable_.setSlope( 0.3 ); + + vibrato_.setFrequency((StkFloat) 5.735); + + outputGain_ = 0.3; + noiseGain_ = 0.2; + vibratoGain_ = 0.1; +} + +Saxofony :: ~Saxofony() +{ +} + +void Saxofony :: clear() +{ + delays_[0].clear(); + delays_[1].clear(); + filter_.clear(); +} + +void Saxofony :: setFrequency(StkFloat frequency) +{ + StkFloat freakency = frequency; + if ( frequency <= 0.0 ) { + errorString_ << "Saxofony::setFrequency: parameter is less than or equal to zero!"; + handleError( StkError::WARNING ); + freakency = 220.0; + } + + StkFloat delay = (Stk::sampleRate() / freakency) - (StkFloat) 3.0; + if (delay <= 0.0) delay = 0.3; + else if (delay > length_) delay = length_; + + delays_[0].setDelay( (1.0-position_) * delay ); + delays_[1].setDelay( position_ * delay ); +} + +void Saxofony :: setBlowPosition(StkFloat position) +{ + if ( position_ == position ) return; + + if ( position < 0.0 ) position_ = 0.0; + else if ( position > 1.0 ) position_ = 1.0; + else position_ = position; + + StkFloat totalDelay = delays_[0].getDelay(); + totalDelay += delays_[1].getDelay(); + + delays_[0].setDelay( (1.0-position_) * totalDelay ); + delays_[1].setDelay( position_ * totalDelay ); +} + +void Saxofony :: startBlowing(StkFloat amplitude, StkFloat rate) +{ + envelope_.setRate( rate ); + envelope_.setTarget( amplitude ); +} + +void Saxofony :: stopBlowing(StkFloat rate) +{ + envelope_.setRate( rate ); + envelope_.setTarget( 0.0 ); +} + +void Saxofony :: noteOn(StkFloat frequency, StkFloat amplitude) +{ + this->setFrequency( frequency ); + this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 ); + outputGain_ = amplitude + 0.001; + +#if defined(_STK_DEBUG_) + errorString_ << "Saxofony::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Saxofony :: noteOff(StkFloat amplitude) +{ + this->stopBlowing( amplitude * 0.01 ); + +#if defined(_STK_DEBUG_) + errorString_ << "Saxofony::NoteOff: amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +StkFloat Saxofony :: computeSample() +{ + StkFloat pressureDiff; + StkFloat breathPressure; + StkFloat temp; + + // Calculate the breath pressure (envelope + noise + vibrato) + breathPressure = envelope_.tick(); + breathPressure += breathPressure * noiseGain_ * noise_.tick(); + breathPressure += breathPressure * vibratoGain_ * vibrato_.tick(); + + temp = -0.95 * filter_.tick( delays_[0].lastOut() ); + lastOutput_ = temp - delays_[1].lastOut(); + pressureDiff = breathPressure - lastOutput_; + delays_[1].tick( temp ); + delays_[0].tick( breathPressure - (pressureDiff * reedTable_.tick(pressureDiff)) - temp ); + + lastOutput_ *= outputGain_; + return lastOutput_; +} + +void Saxofony :: controlChange(int number, StkFloat value) +{ + StkFloat norm = value * ONE_OVER_128; + if ( norm < 0 ) { + norm = 0.0; + errorString_ << "Saxofony::controlChange: control value less than zero ... setting to zero!"; + handleError( StkError::WARNING ); + } + else if ( norm > 1.0 ) { + norm = 1.0; + errorString_ << "Saxofony::controlChange: control value greater than 128.0 ... setting to 128.0!"; + handleError( StkError::WARNING ); + } + + if (number == __SK_ReedStiffness_) // 2 + reedTable_.setSlope( 0.1 + (0.4 * norm) ); + else if (number == __SK_NoiseLevel_) // 4 + noiseGain_ = ( norm * 0.4 ); + else if (number == 29) // 29 + vibrato_.setFrequency( norm * 12.0 ); + else if (number == __SK_ModWheel_) // 1 + vibratoGain_ = ( norm * 0.5 ); + else if (number == __SK_AfterTouch_Cont_) // 128 + envelope_.setValue( norm ); + else if (number == 11) // 11 + this->setBlowPosition( norm ); + else if (number == 26) // reed table offset + reedTable_.setOffset(0.4 + ( norm * 0.6)); + else { + errorString_ << "Saxofony::controlChange: undefined control number (" << number << ")!"; + handleError( StkError::WARNING ); + } + +#if defined(_STK_DEBUG_) + errorString_ << "Saxofony::controlChange: number = " << number << ", value = " << value << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} diff --git a/nyqstk/src/SineWave.cpp b/nyqstk/src/SineWave.cpp new file mode 100644 index 0000000..0a823c2 --- /dev/null +++ b/nyqstk/src/SineWave.cpp @@ -0,0 +1,105 @@ +/***************************************************/ +/*! \class SineWave + \brief STK sinusoid oscillator class. + + This class computes and saves a static sine "table" that can be + shared by multiple instances. It has an interface similar to the + WaveLoop class but inherits from the Generator class. Output + values are computed using linear interpolation. + + The "table" length, set in SineWave.h, is 2048 samples by default. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "SineWave.h" +#include + +using namespace Nyq; + +StkFrames SineWave :: table_; + +SineWave :: SineWave( void ) + : time_(0.0), rate_(1.0), phaseOffset_(0.0) +{ + if ( table_.empty() ) { + table_.resize( TABLE_SIZE + 1, 1 ); + StkFloat temp = 1.0 / TABLE_SIZE; + for ( unsigned long i=0; i<=TABLE_SIZE; i++ ) + table_[i] = sin( TWO_PI * i * temp ); + } +} + +SineWave :: ~SineWave() +{ +} + +void SineWave :: reset(void) +{ + time_ = 0.0; + lastOutput_ = 0; +} + +void SineWave :: setFrequency( StkFloat frequency ) +{ + // This is a looping frequency. + this->setRate( TABLE_SIZE * frequency / Stk::sampleRate() ); +} + +void SineWave :: addTime( StkFloat time ) +{ + // Add an absolute time in samples. + time_ += time; + + while ( time_ < 0.0 ) + time_ += TABLE_SIZE; + while ( time_ >= TABLE_SIZE ) + time_ -= TABLE_SIZE; +} + +void SineWave :: addPhase( StkFloat angle ) +{ + // Add a time in cycles (one cycle = TABLE_SIZE). + time_ += TABLE_SIZE * angle; + + while ( time_ < 0.0 ) + time_ += TABLE_SIZE; + while ( time_ >= TABLE_SIZE ) + time_ -= TABLE_SIZE; +} + +void SineWave :: addPhaseOffset( StkFloat angle ) +{ + // Add a phase offset in cycles, where 1.0 = TABLE_SIZE. + phaseOffset_ = TABLE_SIZE * angle; +} + +StkFloat SineWave :: computeSample( void ) +{ + // Check limits of time address ... if necessary, recalculate modulo + // TABLE_SIZE. + while ( time_ < 0.0 ) + time_ += TABLE_SIZE; + while ( time_ >= TABLE_SIZE ) + time_ -= TABLE_SIZE; + + StkFloat tyme; + if ( phaseOffset_ ) { + tyme = time_ + phaseOffset_; + while ( tyme < 0.0 ) + tyme += TABLE_SIZE; + while ( tyme >= TABLE_SIZE ) + tyme -= TABLE_SIZE; + } + else { + tyme = time_; + } + + lastOutput_ = table_.interpolate( tyme ); + + // Increment time, which can be negative. + time_ += rate_; + + return lastOutput_; +} diff --git a/nyqstk/src/Sitar.cpp b/nyqstk/src/Sitar.cpp new file mode 100644 index 0000000..4ba0acb --- /dev/null +++ b/nyqstk/src/Sitar.cpp @@ -0,0 +1,117 @@ +/***************************************************/ +/*! \class Sitar + \brief STK sitar string model class. + + This class implements a sitar plucked string + physical model based on the Karplus-Strong + algorithm. + + This is a digital waveguide model, making its + use possibly subject to patents held by + Stanford University, Yamaha, and others. + There exist at least two patents, assigned to + Stanford, bearing the names of Karplus and/or + Strong. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Sitar.h" +#include + +using namespace Nyq; + +Sitar :: Sitar(StkFloat lowestFrequency) +{ + unsigned long length = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1); + delayLine_.setMaximumDelay( length ); + delay_ = 0.5 * length; + delayLine_.setDelay( delay_ ); + targetDelay_ = delay_; + + loopFilter_.setZero(0.01); + loopGain_ = 0.999; + + envelope_.setAllTimes(0.001, 0.04, 0.0, 0.5); + this->clear(); +} + +Sitar :: ~Sitar() +{ +} + +void Sitar :: clear() +{ + delayLine_.clear(); + loopFilter_.clear(); +} + +void Sitar :: setFrequency(StkFloat frequency) +{ + StkFloat freakency = frequency; + if ( frequency <= 0.0 ) { + errorString_ << "Sitar::setFrequency: parameter is less than or equal to zero!"; + handleError( StkError::WARNING ); + freakency = 220.0; + } + + targetDelay_ = (Stk::sampleRate() / freakency); + delay_ = targetDelay_ * (1.0 + (0.05 * noise_.tick())); + delayLine_.setDelay( delay_ ); + loopGain_ = 0.995 + (freakency * 0.0000005); + if ( loopGain_ > 0.9995 ) loopGain_ = 0.9995; +} + +void Sitar :: pluck(StkFloat amplitude) +{ + envelope_.keyOn(); +} + +void Sitar :: noteOn(StkFloat frequency, StkFloat amplitude) +{ + this->setFrequency( frequency ); + this->pluck( amplitude ); + amGain_ = 0.1 * amplitude; + +#if defined(_STK_DEBUG_) + errorString_ << "Sitar::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +void Sitar :: noteOff(StkFloat amplitude) +{ + loopGain_ = (StkFloat) 1.0 - amplitude; + if ( loopGain_ < 0.0 ) { + errorString_ << "Sitar::noteOff: amplitude is greater than 1.0 ... setting to 1.0!"; + handleError( StkError::WARNING ); + loopGain_ = 0.0; + } + else if ( loopGain_ > 1.0 ) { + errorString_ << "Sitar::noteOff: amplitude is < 0.0 ... setting to 0.0!"; + handleError( StkError::WARNING ); + loopGain_ = 0.99999; + } + +#if defined(_STK_DEBUG_) + errorString_ << "Sitar::NoteOff: amplitude = " << amplitude << "."; + handleError( StkError::DEBUG_WARNING ); +#endif +} + +StkFloat Sitar :: computeSample() +{ + if ( fabs(targetDelay_ - delay_) > 0.001 ) { + if ( targetDelay_ < delay_ ) + delay_ *= 0.99999; + else + delay_ *= 1.00001; + delayLine_.setDelay( delay_ ); + } + + lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) + + (amGain_ * envelope_.tick() * noise_.tick())); + + return lastOutput_; +} diff --git a/nyqstk/src/Stk.cpp b/nyqstk/src/Stk.cpp new file mode 100644 index 0000000..6040237 --- /dev/null +++ b/nyqstk/src/Stk.cpp @@ -0,0 +1,314 @@ +/***************************************************/ +/*! \class Stk + \brief STK base class + + Nearly all STK classes inherit from this class. + The global sample rate can be queried and + modified via Stk. In addition, this class + provides error handling and byte-swapping + functions. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "Stk.h" +#include + +using namespace Nyq; + +StkFloat Stk :: srate_ = (StkFloat) SRATE; +std::string Stk :: rawwavepath_ = RAWWAVE_PATH; +const Stk::StkFormat Stk :: STK_SINT8 = 0x1; +const Stk::StkFormat Stk :: STK_SINT16 = 0x2; +const Stk::StkFormat Stk :: STK_SINT24 = 0x4; +const Stk::StkFormat Stk :: STK_SINT32 = 0x8; +const Stk::StkFormat Stk :: STK_FLOAT32 = 0x10; +const Stk::StkFormat Stk :: STK_FLOAT64 = 0x20; +bool Stk :: showWarnings_ = false; +bool Stk :: printErrors_ = true; + +Stk :: Stk(void) +{ +} + +Stk :: ~Stk(void) +{ +} + +void Stk :: setRawwavePath( std::string path ) +{ + if ( !path.empty() ) + rawwavepath_ = path; + + // Make sure the path includes a "/" + if ( rawwavepath_[rawwavepath_.length()-1] != '/' ) + rawwavepath_ += "/"; +} + +void Stk :: swap16(unsigned char *ptr) +{ + register unsigned char val; + + // Swap 1st and 2nd bytes + val = *(ptr); + *(ptr) = *(ptr+1); + *(ptr+1) = val; +} + +void Stk :: swap32(unsigned char *ptr) +{ + register unsigned char val; + + // Swap 1st and 4th bytes + val = *(ptr); + *(ptr) = *(ptr+3); + *(ptr+3) = val; + + //Swap 2nd and 3rd bytes + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+1); + *(ptr+1) = val; +} + +void Stk :: swap64(unsigned char *ptr) +{ + register unsigned char val; + + // Swap 1st and 8th bytes + val = *(ptr); + *(ptr) = *(ptr+7); + *(ptr+7) = val; + + // Swap 2nd and 7th bytes + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+5); + *(ptr+5) = val; + + // Swap 3rd and 6th bytes + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+3); + *(ptr+3) = val; + + // Swap 4th and 5th bytes + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+1); + *(ptr+1) = val; +} + +#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) + #include +#elif defined(__OS_WINDOWS__) + #include +#endif + +void Stk :: sleep(unsigned long milliseconds) +{ +#if defined(__OS_WINDOWS__) + Sleep((DWORD) milliseconds); +#elif (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) + usleep( (unsigned long) (milliseconds * 1000.0) ); +#endif +} + +void Stk :: handleError( StkError::Type type ) +{ + handleError( errorString_.str(), type ); + errorString_.str( std::string() ); // reset the ostringstream buffer +} + +void Stk :: handleError( const char *message, StkError::Type type ) +{ + std::string msg( message ); + handleError( msg, type ); +} + +void Stk :: handleError( std::string message, StkError::Type type ) +{ + if ( type == StkError::WARNING || type == StkError::STATUS ) { + if ( !showWarnings_ ) return; + std::cerr << '\n' << message << '\n' << std::endl; + } + else if (type == StkError::DEBUG_WARNING) { +#if defined(_STK_DEBUG_) + std::cerr << '\n' << message << '\n' << std::endl; +#endif + } + else { + if ( printErrors_ ) { + // Print error message before throwing. + std::cerr << '\n' << message << '\n' << std::endl; + } + throw StkError(message, type); + } +} + +// +// StkFrames definitions +// + +StkFrames :: StkFrames( unsigned int nFrames, unsigned int nChannels, bool interleaved ) + : nFrames_( nFrames ), nChannels_( nChannels ), interleaved_( interleaved ) +{ + size_ = nFrames_ * nChannels_; + bufferSize_ = size_; + + if ( size_ > 0 ) { + data_ = (StkFloat *) calloc( size_, sizeof( StkFloat ) ); +#if defined(_STK_DEBUG_) + if ( data_ == NULL ) { + std::string error = "StkFrames: memory allocation error in constructor!"; + Stk::handleError( error, StkError::MEMORY_ALLOCATION ); + } +#endif + } + else data_ = 0; + + dataRate_ = Stk::sampleRate(); +} + +StkFrames :: StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels, bool interleaved ) + : nFrames_( nFrames ), nChannels_( nChannels ), interleaved_( interleaved ) +{ + size_ = nFrames_ * nChannels_; + bufferSize_ = size_; + if ( size_ > 0 ) { + data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) ); +#if defined(_STK_DEBUG_) + if ( data_ == NULL ) { + std::string error = "StkFrames: memory allocation error in constructor!"; + Stk::handleError( error, StkError::MEMORY_ALLOCATION ); + } +#endif + for ( long i=0; i<(long)size_; i++ ) data_[i] = value; + } + else data_ = 0; + + dataRate_ = Stk::sampleRate(); +} + +StkFrames :: ~StkFrames() +{ + if ( data_ ) free( data_ ); +} + +bool StkFrames :: empty() const +{ + if ( size_ > 0 ) return false; + else return true; +} + +void StkFrames :: resize( size_t nFrames, unsigned int nChannels ) +{ + nFrames_ = nFrames; + nChannels_ = nChannels; + + size_ = nFrames_ * nChannels_; + if ( size_ > bufferSize_ ) { + if ( data_ ) free( data_ ); + data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) ); +#if defined(_STK_DEBUG_) + if ( data_ == NULL ) { + std::string error = "StkFrames::resize: memory allocation error!"; + Stk::handleError( error, StkError::MEMORY_ALLOCATION ); + } +#endif + bufferSize_ = size_; + } +} + +void StkFrames :: resize( size_t nFrames, unsigned int nChannels, StkFloat value ) +{ + this->resize( nFrames, nChannels ); + + for ( size_t i=0; i= size_ ) { + std::ostringstream error; + error << "StkFrames::operator[]: invalid index (" << n << ") value!"; + Stk::handleError( error.str(), StkError::MEMORY_ACCESS ); + } +#endif + + return data_[n]; +} + +StkFloat StkFrames :: operator[] ( size_t n ) const +{ +#if defined(_STK_DEBUG_) + if ( n >= size_ ) { + std::ostringstream error; + error << "StkFrames::operator[]: invalid index (" << n << ") value!"; + Stk::handleError( error.str(), StkError::MEMORY_ACCESS ); + } +#endif + + return data_[n]; +} + +StkFloat& StkFrames :: operator() ( size_t frame, unsigned int channel ) +{ +#if defined(_STK_DEBUG_) + if ( frame >= nFrames_ || channel >= nChannels_ ) { + std::ostringstream error; + error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!"; + Stk::handleError( error.str(), StkError::MEMORY_ACCESS ); + } +#endif + + if ( interleaved_ ) + return data_[ frame * nChannels_ + channel ]; + else + return data_[ channel * nFrames_ + frame ]; +} + +StkFloat StkFrames :: operator() ( size_t frame, unsigned int channel ) const +{ +#if defined(_STK_DEBUG_) + if ( frame >= nFrames_ || channel >= nChannels_ ) { + std::ostringstream error; + error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!"; + Stk::handleError( error.str(), StkError::MEMORY_ACCESS ); + } +#endif + + if ( interleaved_ ) + return data_[ frame * nChannels_ + channel ]; + else + return data_[ channel * nFrames_ + frame ]; +} + +StkFloat StkFrames :: interpolate( StkFloat frame, unsigned int channel ) const +{ +#if defined(_STK_DEBUG_) + if ( frame >= (StkFloat) nFrames_ || channel >= nChannels_ ) { + std::ostringstream error; + error << "StkFrames::interpolate: invalid frame (" << frame << ") or channel (" << channel << ") value!"; + Stk::handleError( error.str(), StkError::MEMORY_ACCESS ); + } +#endif + + size_t iIndex = ( size_t ) frame; // integer part of index + StkFloat output, alpha = frame - (StkFloat) iIndex; // fractional part of index + + if ( interleaved_ ) { + iIndex = iIndex * nChannels_ + channel; + output = data_[ iIndex ]; + output += ( alpha * ( data_[ iIndex + nChannels_ ] - output ) ); + } + else { + iIndex += channel * nFrames_; + output = data_[ iIndex ]; + output += ( alpha * ( data_[ iIndex++ ] - output ) ); + } + + return output; +} diff --git a/nyqstk/src/WaveLoop.cpp b/nyqstk/src/WaveLoop.cpp new file mode 100644 index 0000000..80dc5aa --- /dev/null +++ b/nyqstk/src/WaveLoop.cpp @@ -0,0 +1,190 @@ +/***************************************************/ +/*! \class WaveLoop + \brief STK waveform oscillator class. + + This class inherits from FileWvIn and provides audio file looping + functionality. Any audio file that can be loaded by FileRead can + be looped using this class. + + WaveLoop supports multi-channel data. It is important to + distinguish the tick() methods, which return samples produced by + averaging across sample frames, from the tickFrame() methods, + which return references or pointers to multi-channel sample + frames. + + by Perry R. Cook and Gary P. Scavone, 1995 - 2005. +*/ +/***************************************************/ + +#include "WaveLoop.h" +#include + +using namespace Nyq; + +WaveLoop :: WaveLoop( unsigned long chunkThreshold, unsigned long chunkSize ) + : FileWvIn( chunkThreshold, chunkSize ), phaseOffset_(0.0) +{ +} + +WaveLoop :: WaveLoop( std::string fileName, bool raw, bool doNormalize, + unsigned long chunkThreshold, unsigned long chunkSize ) + : FileWvIn( chunkThreshold, chunkSize ), phaseOffset_(0.0) +{ + this->openFile( fileName, raw, doNormalize ); +} + +WaveLoop :: ~WaveLoop() +{ +} + +void WaveLoop :: openFile( std::string fileName, bool raw, bool doNormalize ) +{ + // Call close() in case another file is already open. + this->closeFile(); + + // Attempt to open the file ... an error might be thrown here. + file_.open( fileName, raw ); + + // Determine whether chunking or not. + if ( file_.fileSize() > chunkThreshold_ ) { + chunking_ = true; + chunkPointer_ = 0; + data_.resize( chunkSize_, file_.channels() ); + if ( doNormalize ) normalizing_ = true; + else normalizing_ = false; + } + else { + chunking_ = false; + data_.resize( file_.fileSize() + 1, file_.channels() ); + } + + // Load all or part of the data. + file_.read( data_, 0, doNormalize ); + + if ( chunking_ ) { // If chunking, save the first sample frame for later. + firstFrame_.resize( 1, data_.channels() ); + for ( unsigned int i=0; isetRate( data_.dataRate() / Stk::sampleRate() ); + + if ( doNormalize & !chunking_ ) this->normalize(); + + this->reset(); +} + +void WaveLoop :: setRate( StkFloat rate ) +{ + rate_ = rate; + + if ( fmod( rate_, 1.0 ) != 0.0 ) interpolate_ = true; + else interpolate_ = false; +} + +void WaveLoop :: setFrequency( StkFloat frequency ) +{ + // This is a looping frequency. + this->setRate( file_.fileSize() * frequency / Stk::sampleRate() ); +} + +void WaveLoop :: addTime( StkFloat time ) +{ + // Add an absolute time in samples. + time_ += time; + + StkFloat fileSize = file_.fileSize(); + while ( time_ < 0.0 ) + time_ += fileSize; + while ( time_ >= fileSize ) + time_ -= fileSize; +} + +void WaveLoop :: addPhase( StkFloat angle ) +{ + // Add a time in cycles (one cycle = fileSize). + StkFloat fileSize = file_.fileSize(); + time_ += fileSize * angle; + + while ( time_ < 0.0 ) + time_ += fileSize; + while ( time_ >= fileSize ) + time_ -= fileSize; +} + +void WaveLoop :: addPhaseOffset( StkFloat angle ) +{ + // Add a phase offset in cycles, where 1.0 = fileSize. + phaseOffset_ = file_.fileSize() * angle; +} + +void WaveLoop :: computeFrame( void ) +{ + // Check limits of time address ... if necessary, recalculate modulo + // fileSize. + StkFloat fileSize = file_.fileSize(); + while ( time_ < 0.0 ) + time_ += fileSize; + while ( time_ >= fileSize ) + time_ -= fileSize; + + StkFloat tyme; + if ( phaseOffset_ ) { + tyme = time_ + phaseOffset_; + while ( tyme < 0.0 ) + tyme += fileSize; + while ( tyme >= fileSize ) + tyme -= fileSize; + } + else { + tyme = time_; + } + + if (chunking_) { + + // Check the time address vs. our current buffer limits. + if ( ( time_ < (StkFloat) chunkPointer_ ) || + ( time_ > (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) ) { + + while ( time_ < (StkFloat) chunkPointer_ ) { // negative rate + chunkPointer_ -= chunkSize_ - 1; // overlap chunks by one frame + if ( chunkPointer_ < 0 ) chunkPointer_ = 0; + } + while ( time_ > (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) { // positive rate + chunkPointer_ += chunkSize_ - 1; // overlap chunks by one frame + if ( chunkPointer_ + chunkSize_ > file_.fileSize() ) { // at end of file + chunkPointer_ = file_.fileSize() - chunkSize_ + 1; // leave extra frame at end of buffer + // Now fill extra frame with first frame data. + for ( unsigned int j=0; j + +using namespace Nyq; + +WvIn :: WvIn() +{ +} + +WvIn :: ~WvIn() +{ +} + +StkFloat WvIn :: lastOut( void ) const +{ + if ( lastOutputs_.empty() ) return 0.0; + + if ( lastOutputs_.size() == 1 ) + return lastOutputs_[0]; + + StkFloat output = 0.0; + for ( unsigned int i=0; i= frames.channels() ) { + errorString_ << "WvIn::tick(): channel and StkFrames arguments are incompatible!"; + handleError( StkError::FUNCTION_ARGUMENT ); + } + + if ( frames.channels() == 1 ) { + for ( unsigned int i=0; icomputeFrame(); + for ( j=0; jcomputeFrame(); + index = i; + for ( j=0; j + +#include "stkint.h" + +#include "NRev.h" +#include "JCRev.h" +#include "PRCRev.h" + +using namespace Nyq; + +// Reverb Effects ========================================================== + +struct stkEffect { + Effect * effectPtr; +}; + +struct stkEffect *initStkEffect(int eff_type, ::StkFloat trev, int sample_rate) { + struct stkEffect * eff = (struct stkEffect *) malloc(sizeof(struct stkEffect)); + Stk::setSampleRate(sample_rate); + switch(eff_type) { + case NREV: + eff->effectPtr = new NRev(trev); + break; + case JCREV: + eff->effectPtr = new JCRev(trev); + break; + case PRCREV: + eff->effectPtr = new PRCRev(trev); + break; + default: + return NULL; + } + return eff; +} + +int deleteStkEffect(struct stkEffect * eff) { + delete(eff->effectPtr); + free(eff); + return 0; +} + +::StkFloat stkEffectTick(struct stkEffect * eff, ::StkFloat s) { + return eff->effectPtr->tick(s); +} + +void stkEffectSetMix (struct stkEffect * eff, ::StkFloat mix) { + eff->effectPtr->setEffectMix(mix); +} + +// PitShift =================================================== + +#include "PitShift.h" + +struct stkEffect *initStkPitShift(::StkFloat shift, int sample_rate) { + PitShift * ps; + ps = new PitShift(); + ps->setShift(shift); + struct stkEffect * eff = (struct stkEffect *) malloc(sizeof(struct stkEffect)); + Stk::setSampleRate(sample_rate); + eff->effectPtr = ps; + return eff; +} + +// Chorus ===================================================== + +#include "Chorus.h" + +struct stkEffect *initStkChorus(::StkFloat baseDelay, ::StkFloat depth, ::StkFloat freq, int sample_rate) { + Chorus * ch; + ch = new Chorus(baseDelay); + ch->setModDepth(depth); + ch->setModFrequency(freq); + struct stkEffect * eff = (struct stkEffect *) malloc(sizeof(struct stkEffect)); + Stk::setSampleRate(sample_rate); + eff->effectPtr = ch; + return eff; +} + diff --git a/nyqstk/stkint.h b/nyqstk/stkint.h new file mode 100644 index 0000000..20b4c94 --- /dev/null +++ b/nyqstk/stkint.h @@ -0,0 +1,22 @@ +typedef double StkFloat; + +#define NREV 0 +#define JCREV 1 +#define PRCREV 2 + +#ifdef __cplusplus +extern "C" { +#endif + + struct stkEffect; + struct stkEffect * initStkEffect (int, StkFloat, int); + int deleteStkEffect(struct stkEffect *); + StkFloat stkEffectTick(struct stkEffect *, StkFloat); + void stkEffectSetMix (struct stkEffect *, StkFloat); + + struct stkEffect * initStkPitShift(StkFloat, int); + struct stkEffect * initStkChorus(StkFloat, StkFloat, StkFloat, int); + +#ifdef __cplusplus +} +#endif diff --git a/nyquist.dsp b/nyquist.dsp new file mode 100644 index 0000000..ff6e12a --- /dev/null +++ b/nyquist.dsp @@ -0,0 +1,1335 @@ +# Microsoft Developer Studio Project File - Name="nyquist" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=nyquist - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "nyquist.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "nyquist.mak" CFG="nyquist - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "nyquist - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "nyquist - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "nyquist - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\WinRel" +# PROP BASE Intermediate_Dir ".\WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\WinRel" +# PROP Intermediate_Dir ".\WinRel" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".\xlisp" /I ".\snd" /I ".\nyqsrc" /I ".\tran" /I ".\cmt" /I ".\nyqstk" /I ".\nyqstk\include" /I ".\sys\win\msvc" /I ".\fft" /I ".\portaudio\pa_common" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "CMTSTUFF" /D "PA_NO_ASIO" /D "PA_NO_DS" /D "STK_NYQUIST" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "nyquist - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\WinDebug" +# PROP BASE Intermediate_Dir ".\WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\WinDebug" +# PROP Intermediate_Dir ".\WinDebug" +# PROP Ignore_Export_Lib 0 +# ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".\xlisp" /I ".\snd" /I ".\nyqsrc" /I ".\tran" /I ".\cmt" /I ".\nyqstk" /I ".\nyqstk\include" /I ".\sys\win\msvc" /I ".\fft" /I ".\portaudio\pa_common" /D "STK_NYQUIST" /D "__LITTLE_ENDIAN__" /D "_CONSOLE" /D "CMTSTUFF" /D "PA_NO_ASIO" /D "PA_NO_DS" /D "WIN32" /D "_DEBUG" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 wsock32.lib winmm.lib advapi32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "nyquist - Win32 Release" +# Name "nyquist - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\tran\abs.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\add.c +# End Source File +# Begin Source File + +SOURCE=.\tran\allpoles.c +# End Source File +# Begin Source File + +SOURCE=.\tran\alpass.c +# End Source File +# Begin Source File + +SOURCE=.\tran\alpasscv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\alpassvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\amosc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\areson.c +# End Source File +# Begin Source File + +SOURCE=.\tran\aresoncv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\atone.c +# End Source File +# Begin Source File + +SOURCE=.\tran\atonev.c +# End Source File +# Begin Source File + +SOURCE=.\snd\audiopa.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\avg.c +# End Source File +# Begin Source File + +SOURCE=.\tran\biquad.c +# End Source File +# Begin Source File + +SOURCE=.\tran\buzz.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\cext.c +# End Source File +# Begin Source File + +SOURCE=.\tran\chase.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Clarinet.cpp +# End Source File +# Begin Source File + +SOURCE=.\cmt\cleanup.c +# End Source File +# Begin Source File + +SOURCE=.\tran\clip.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmdline.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmtcmd.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\compose.c +# End Source File +# Begin Source File + +SOURCE=.\tran\congen.c +# End Source File +# Begin Source File + +SOURCE=.\tran\const.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\convolve.c +# End Source File +# Begin Source File + +SOURCE=.\tran\coterm.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\debug.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Delay.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\delaycc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\delaycv.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\DelayL.cpp +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\downsample.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Envelope.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\eqbandvvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\exp.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\extern.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\falloc.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\ffilterkit.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\fft.c +# End Source File +# Begin Source File + +SOURCE=.\fft\fftn.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Filter.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\fmosc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\follow.c +# End Source File +# Begin Source File + +SOURCE=.\tran\fromarraystream.c +# End Source File +# Begin Source File + +SOURCE=.\tran\fromobject.c +# End Source File +# Begin Source File + +SOURCE=.\tran\gate.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\handlers.c +# End Source File +# Begin Source File + +SOURCE=.\snd\ieeecvt.c +# End Source File +# Begin Source File + +SOURCE=.\tran\ifft.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\instr.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclar.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclarall.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclarfreq.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Instrmnt.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsax.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsaxall.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsaxfreq.c +# End Source File +# Begin Source File + +SOURCE=.\tran\integrate.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\inverse.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\local.c +# End Source File +# Begin Source File + +SOURCE=.\tran\log.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\lpanal.c +# End Source File +# Begin Source File + +SOURCE=.\tran\lpreson.c +# End Source File +# Begin Source File + +SOURCE=.\tran\maxv.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\mem.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifile.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifns.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\moxc.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiread.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiseq.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Noise.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\offset.c +# End Source File +# Begin Source File + +SOURCE=.\tran\oneshot.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\OneZero.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\osc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\partial.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\path.c +# End Source File +# Begin Source File + +SOURCE=.\tran\pluck.c +# End Source File +# Begin Source File + +SOURCE=.\tran\prod.c +# End Source File +# Begin Source File + +SOURCE=.\tran\pwl.c +# End Source File +# Begin Source File + +SOURCE=.\tran\quantize.c +# End Source File +# Begin Source File + +SOURCE=.\tran\recip.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\record.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\ReedTabl.cpp +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resamp.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resampv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\reson.c +# End Source File +# Begin Source File + +SOURCE=.\tran\resoncv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\sampler.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\samples.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Saxofony.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\scale.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seq.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqext.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqfnint.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqinterf.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmread.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmwrite.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqread.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqwrite.c +# End Source File +# Begin Source File + +SOURCE=.\tran\shape.c +# End Source File +# Begin Source File + +SOURCE=.\tran\sine.c +# End Source File +# Begin Source File + +SOURCE=.\tran\siosc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\slope.c +# End Source File +# Begin Source File + +SOURCE=.\snd\snd.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndcvt.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndfail.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndfnint.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndheader.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndmax.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndread.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndseq.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndwin32.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndwritepa.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sound.c +# End Source File +# Begin Source File + +SOURCE=.\tran\sqrt.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\stats.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Stk.cpp +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\stkinit.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\tapf.c +# End Source File +# Begin Source File + +SOURCE=.\tran\tapv.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\tempomap.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\timebase.c +# End Source File +# Begin Source File + +SOURCE=.\tran\tone.c +# End Source File +# Begin Source File + +SOURCE=.\tran\tonev.c +# End Source File +# Begin Source File + +SOURCE=.\tran\upsample.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\userio.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\WaveLoop.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\white.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\msvc\winfun.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\msvc\winstuff.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\WvIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlbfun.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlcont.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xldbug.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xldmem.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xleval.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlfio.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlftab.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlglob.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlimage.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlinit.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlio.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlisp.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xljump.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xllist.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlmath.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlobj.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlpp.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlprin.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlread.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlstr.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlsubr.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlsym.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlsys.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\yin.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\tran\abs.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\add.h +# End Source File +# Begin Source File + +SOURCE=.\tran\allpoles.h +# End Source File +# Begin Source File + +SOURCE=.\tran\alpass.h +# End Source File +# Begin Source File + +SOURCE=.\tran\alpassvv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\amosc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\areson.h +# End Source File +# Begin Source File + +SOURCE=.\tran\aresoncv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\atone.h +# End Source File +# Begin Source File + +SOURCE=.\tran\atonev.h +# End Source File +# Begin Source File + +SOURCE=.\snd\audiont.h +# End Source File +# Begin Source File + +SOURCE=.\snd\audiowin32.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\avg.h +# End Source File +# Begin Source File + +SOURCE=.\tran\biquad.h +# End Source File +# Begin Source File + +SOURCE=.\tran\buzz.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cext.h +# End Source File +# Begin Source File + +SOURCE=.\tran\chase.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Clarinet.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cleanup.h +# End Source File +# Begin Source File + +SOURCE=.\tran\clip.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmdline.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmtcmd.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\compose.h +# End Source File +# Begin Source File + +SOURCE=.\tran\congen.h +# End Source File +# Begin Source File + +SOURCE=.\tran\const.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\convolve.h +# End Source File +# Begin Source File + +SOURCE=.\tran\coterm.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\debug.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Delay.h +# End Source File +# Begin Source File + +SOURCE=.\tran\delay.h +# End Source File +# Begin Source File + +SOURCE=.\tran\delaycc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\delaycv.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\DelayL.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\downsample.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Envelope.h +# End Source File +# Begin Source File + +SOURCE=.\tran\exp.h +# End Source File +# Begin Source File + +SOURCE=.\xlisp\extern.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\falloc.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\ffilterkit.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\fft.h +# End Source File +# Begin Source File + +SOURCE=.\fft\fftn.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Filter.h +# End Source File +# Begin Source File + +SOURCE=.\tran\fmosc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\follow.h +# End Source File +# Begin Source File + +SOURCE=.\tran\fromarraystream.h +# End Source File +# Begin Source File + +SOURCE=.\tran\fromobject.h +# End Source File +# Begin Source File + +SOURCE=.\tran\gate.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\globals.h +# End Source File +# Begin Source File + +SOURCE=.\snd\ieeecvt.h +# End Source File +# Begin Source File + +SOURCE=.\tran\ifft.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\instr.h +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclar.h +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclarfreq.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Instrmnt.h +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsax.h +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsaxfreq.h +# End Source File +# Begin Source File + +SOURCE=.\tran\integrate.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\inverse.h +# End Source File +# Begin Source File + +SOURCE=.\tran\log.h +# End Source File +# Begin Source File + +SOURCE=.\tran\lpanal.h +# End Source File +# Begin Source File + +SOURCE=.\tran\lpreson.h +# End Source File +# Begin Source File + +SOURCE=.\tran\maxv.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\mem.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifile.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifns.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\moxc.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiread.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiseq.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Noise.h +# End Source File +# Begin Source File + +SOURCE=.\tran\offset.h +# End Source File +# Begin Source File + +SOURCE=.\tran\oneshot.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\OneZero.h +# End Source File +# Begin Source File + +SOURCE=.\tran\osc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\partial.h +# End Source File +# Begin Source File + +SOURCE=.\tran\prod.h +# End Source File +# Begin Source File + +SOURCE=.\tran\pwl.h +# End Source File +# Begin Source File + +SOURCE=.\tran\quantize.h +# End Source File +# Begin Source File + +SOURCE=.\tran\recip.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\record.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\ReedTabl.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resamp.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resampv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\reson.h +# End Source File +# Begin Source File + +SOURCE=.\tran\resoncv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\sampler.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\samples.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Saxofony.h +# End Source File +# Begin Source File + +SOURCE=.\tran\scale.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seq.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqext.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqinterf.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmread.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmwrite.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqread.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqwrite.h +# End Source File +# Begin Source File + +SOURCE=.\tran\shape.h +# End Source File +# Begin Source File + +SOURCE=.\tran\sine.h +# End Source File +# Begin Source File + +SOURCE=.\tran\siosc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\slope.h +# End Source File +# Begin Source File + +SOURCE=.\snd\snd.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndheader.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndmax.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndread.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndseq.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndwin32.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndwrite.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sound.h +# End Source File +# Begin Source File + +SOURCE=.\tran\sqrt.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\Stk.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\stkinit.h +# End Source File +# Begin Source File + +SOURCE=.\tran\tapv.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\tempomap.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\timebase.h +# End Source File +# Begin Source File + +SOURCE=.\tran\tone.h +# End Source File +# Begin Source File + +SOURCE=.\tran\tonev.h +# End Source File +# Begin Source File + +SOURCE=.\tran\upsample.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\userio.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\WaveLoop.h +# End Source File +# Begin Source File + +SOURCE=.\tran\white.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\msvc\winfun.h +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\include\WvIn.h +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xldmem.h +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlisp.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "portaudio-c" + +# PROP Default_Filter "c" +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_allocation.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_converters.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_cpuload.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_dither.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_front.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_process.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_skeleton.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_stream.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win\pa_win_hostapis.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win\pa_win_util.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win_wmme\pa_win_wmme.c +# End Source File +# End Group +# Begin Group "portaudio-h" + +# PROP Default_Filter "h" +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_allocation.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_converters.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_cpuload.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_dither.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_process.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_stream.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_util.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win_wmme\pa_win_wmme.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\portaudio.h +# End Source File +# End Group +# End Target +# End Project diff --git a/nyquist.dsw b/nyquist.dsw new file mode 100644 index 0000000..02529f8 --- /dev/null +++ b/nyquist.dsw @@ -0,0 +1,101 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "filelist"=.\misc\filelist.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "intgen"=.\misc\intgen_win32\intgen.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "nyquist"=.\nyquist.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "nyqwin"=.\nyqwin.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "packer"=.\misc\packer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "portaudio_test"=.\portaudio_test\portaudio_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "unpacker"=.\misc\unpacker.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/nyquist.sln b/nyquist.sln new file mode 100644 index 0000000..35c5340 --- /dev/null +++ b/nyquist.sln @@ -0,0 +1,177 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "filelist", "misc\filelist.vcproj", "{DA1A1539-671B-4E70-BF6E-10EC6887FAF4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intgen", "misc\intgen_win32\intgen.vcproj", "{378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nyquist", "nyquist.vcproj", "{208E5158-7B25-4185-8D8E-5E5BFC2153EC}" + ProjectSection(ProjectDependencies) = postProject + {A02E8EC5-317C-42CD-9425-60BDDE09D833} = {A02E8EC5-317C-42CD-9425-60BDDE09D833} + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} = {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nyqwin", "nyqwin.vcproj", "{19DEEB57-B0BB-476A-9960-CE360A884906}" + ProjectSection(ProjectDependencies) = postProject + {A02E8EC5-317C-42CD-9425-60BDDE09D833} = {A02E8EC5-317C-42CD-9425-60BDDE09D833} + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} = {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "packer", "misc\packer.vcproj", "{F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unpacker", "misc\unpacker.vcproj", "{E09240DC-CFBD-46BE-A6EA-2379C7502230}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osc-test-client", "liblo\test-client\osc-test-client.vcproj", "{22B02EA5-24F7-4F8D-8D8F-E066D80A0957}" + ProjectSection(ProjectDependencies) = postProject + {A02E8EC5-317C-42CD-9425-60BDDE09D833} = {A02E8EC5-317C-42CD-9425-60BDDE09D833} + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} = {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ser-to-osc", "liblo\ser-to-osc\ser-to-osc.vcproj", "{44736D55-68C4-496D-B08A-9C66844AE857}" + ProjectSection(ProjectDependencies) = postProject + {A02E8EC5-317C-42CD-9425-60BDDE09D833} = {A02E8EC5-317C-42CD-9425-60BDDE09D833} + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} = {FEA9D5D3-46BD-594F-85C6-F1380FD994A6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pthread", "liblo\pthreads.2\pthread.vcproj", "{A02E8EC5-317C-42CD-9425-60BDDE09D833}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblo", "liblo\build\vs2008\liblo.vcproj", "{FEA9D5D3-46BD-594F-85C6-F1380FD994A6}" + ProjectSection(ProjectDependencies) = postProject + {A02E8EC5-317C-42CD-9425-60BDDE09D833} = {A02E8EC5-317C-42CD-9425-60BDDE09D833} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DebugDLL|Win32 = DebugDLL|Win32 + DebugLib|Win32 = DebugLib|Win32 + Release|Win32 = Release|Win32 + ReleaseDLL|Win32 = ReleaseDLL|Win32 + ReleaseLib|Win32 = ReleaseLib|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.Debug|Win32.ActiveCfg = Debug|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.Debug|Win32.Build.0 = Debug|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.DebugDLL|Win32.Build.0 = Debug|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.DebugLib|Win32.Build.0 = Debug|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.Release|Win32.ActiveCfg = Release|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.Release|Win32.Build.0 = Release|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {DA1A1539-671B-4E70-BF6E-10EC6887FAF4}.ReleaseLib|Win32.Build.0 = Release|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.Debug|Win32.ActiveCfg = Debug|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.Debug|Win32.Build.0 = Debug|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.DebugDLL|Win32.Build.0 = Debug|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.DebugLib|Win32.Build.0 = Debug|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.Release|Win32.ActiveCfg = Release|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.Release|Win32.Build.0 = Release|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {378FBAED-0CA5-4CFB-ACF4-CCEDF8A4596E}.ReleaseLib|Win32.Build.0 = Release|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.Debug|Win32.ActiveCfg = Debug|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.Debug|Win32.Build.0 = Debug|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.DebugDLL|Win32.Build.0 = Debug|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.DebugLib|Win32.Build.0 = Debug|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.Release|Win32.ActiveCfg = Release|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.Release|Win32.Build.0 = Release|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {208E5158-7B25-4185-8D8E-5E5BFC2153EC}.ReleaseLib|Win32.Build.0 = Release|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.Debug|Win32.ActiveCfg = Debug|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.Debug|Win32.Build.0 = Debug|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.DebugDLL|Win32.Build.0 = Debug|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.DebugLib|Win32.Build.0 = Debug|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.Release|Win32.ActiveCfg = Release|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.Release|Win32.Build.0 = Release|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {19DEEB57-B0BB-476A-9960-CE360A884906}.ReleaseLib|Win32.Build.0 = Release|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.Debug|Win32.ActiveCfg = Debug|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.Debug|Win32.Build.0 = Debug|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.DebugDLL|Win32.Build.0 = Debug|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.DebugLib|Win32.Build.0 = Debug|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.Release|Win32.ActiveCfg = Release|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.Release|Win32.Build.0 = Release|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {F40BCDEF-F66F-4FEB-9513-F7EFF29BFC93}.ReleaseLib|Win32.Build.0 = Release|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.Debug|Win32.ActiveCfg = Debug|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.Debug|Win32.Build.0 = Debug|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.DebugDLL|Win32.Build.0 = Debug|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.DebugLib|Win32.Build.0 = Debug|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.Release|Win32.ActiveCfg = Release|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.Release|Win32.Build.0 = Release|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {E09240DC-CFBD-46BE-A6EA-2379C7502230}.ReleaseLib|Win32.Build.0 = Release|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.Debug|Win32.ActiveCfg = Debug|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.Debug|Win32.Build.0 = Debug|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.DebugDLL|Win32.Build.0 = Debug|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.DebugLib|Win32.Build.0 = Debug|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.Release|Win32.ActiveCfg = Release|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.Release|Win32.Build.0 = Release|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {22B02EA5-24F7-4F8D-8D8F-E066D80A0957}.ReleaseLib|Win32.Build.0 = Release|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.Debug|Win32.ActiveCfg = Debug|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.Debug|Win32.Build.0 = Debug|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.DebugDLL|Win32.Build.0 = Debug|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.DebugLib|Win32.Build.0 = Debug|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.Release|Win32.ActiveCfg = Release|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.Release|Win32.Build.0 = Release|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {44736D55-68C4-496D-B08A-9C66844AE857}.ReleaseLib|Win32.Build.0 = Release|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.Debug|Win32.ActiveCfg = Debug|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.Debug|Win32.Build.0 = Debug|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.DebugDLL|Win32.Build.0 = Debug|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.DebugLib|Win32.Build.0 = Debug|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.Release|Win32.ActiveCfg = Release|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.Release|Win32.Build.0 = Release|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {A02E8EC5-317C-42CD-9425-60BDDE09D833}.ReleaseLib|Win32.Build.0 = Release|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.Debug|Win32.ActiveCfg = Debug|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.Debug|Win32.Build.0 = Debug|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.DebugDLL|Win32.ActiveCfg = Debug|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.DebugDLL|Win32.Build.0 = Debug|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.DebugLib|Win32.ActiveCfg = Debug|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.DebugLib|Win32.Build.0 = Debug|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.Release|Win32.ActiveCfg = Release|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.Release|Win32.Build.0 = Release|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.ReleaseDLL|Win32.ActiveCfg = Release|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.ReleaseDLL|Win32.Build.0 = Release|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.ReleaseLib|Win32.ActiveCfg = Release|Win32 + {FEA9D5D3-46BD-594F-85C6-F1380FD994A6}.ReleaseLib|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/nyquist.vcproj b/nyquist.vcproj new file mode 100644 index 0000000..638f91d --- /dev/null +++ b/nyquist.vcproj @@ -0,0 +1,4983 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nyqwin.dsp b/nyqwin.dsp new file mode 100644 index 0000000..64e7f32 --- /dev/null +++ b/nyqwin.dsp @@ -0,0 +1,1310 @@ +# Microsoft Developer Studio Project File - Name="nyqwin" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=nyqwin - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "nyqwin.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "nyqwin.mak" CFG="nyqwin - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "nyqwin - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "nyqwin - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "nyqwin - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\WinRel" +# PROP BASE Intermediate_Dir ".\WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\NyqWinRel" +# PROP Intermediate_Dir ".\NyqWinRel" +# PROP Ignore_Export_Lib 0 +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /W3 /GX /O2 /I ".\xlisp" /I ".\snd" /I ".\nyqsrc" /I ".\tran" /I ".\cmt" /I ".\sys\win\msvc" /I ".\fft" /I ".\portaudio\pa_common" /I ".\nyqstk" /I ".\nyqstk\include" /D "NDEBUG" /D "WIN32" /D "CMTSTUFF" /D "WINGUI" /D "PA_NO_ASIO" /D "PA_NO_DS" /D "STK_NYQUIST" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /machine:I386 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "nyqwin - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\WinDebug" +# PROP BASE Intermediate_Dir ".\WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\NyqWinDebug" +# PROP Intermediate_Dir ".\NyqWinDebug" +# PROP Ignore_Export_Lib 0 +# ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".\xlisp" /I ".\snd" /I ".\nyqsrc" /I ".\tran" /I ".\cmt" /I ".\sys\win\msvc" /I ".\fft" /I ".\portaudio\pa_common" /I ".\nyqstk" /I ".\nyqstk\include" /D "PA_NO_ASIO" /D "PA_NO_DS" /D "CMTSTUFF" /D "WINGUI" /D "STK_NYQUIST" /D "WIN32" /D "_DEBUG" /D "DEBUG_INPUT" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 wsock32.lib winmm.lib kernel32.lib user32.lib advapi32.lib gdi32.lib comdlg32.lib /nologo /subsystem:windows /debug /machine:I386 +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "nyqwin - Win32 Release" +# Name "nyqwin - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\tran\abs.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\add.c +# End Source File +# Begin Source File + +SOURCE=.\tran\allpoles.c +# End Source File +# Begin Source File + +SOURCE=.\tran\alpass.c +# End Source File +# Begin Source File + +SOURCE=.\tran\alpasscv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\alpassvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\amosc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\areson.c +# End Source File +# Begin Source File + +SOURCE=.\tran\aresoncv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\atone.c +# End Source File +# Begin Source File + +SOURCE=.\tran\atonev.c +# End Source File +# Begin Source File + +SOURCE=.\snd\audiowin32.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\avg.c +# End Source File +# Begin Source File + +SOURCE=.\tran\biquad.c +# End Source File +# Begin Source File + +SOURCE=.\tran\buzz.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\cext.c +# End Source File +# Begin Source File + +SOURCE=.\tran\chase.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Clarinet.cpp +# End Source File +# Begin Source File + +SOURCE=.\cmt\cleanup.c +# End Source File +# Begin Source File + +SOURCE=.\tran\clip.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmdline.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmtcmd.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\compose.c +# End Source File +# Begin Source File + +SOURCE=.\tran\congen.c +# End Source File +# Begin Source File + +SOURCE=.\tran\const.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\convolve.c +# End Source File +# Begin Source File + +SOURCE=.\tran\coterm.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\debug.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Delay.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\delaycc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\delaycv.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\DelayL.cpp +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\downsample.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Envelope.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\eqbandvvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\exp.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\extern.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\falloc.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\ffilterkit.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\fft.c +# End Source File +# Begin Source File + +SOURCE=.\fft\fftn.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Filter.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\fmosc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\follow.c +# End Source File +# Begin Source File + +SOURCE=.\tran\fromarraystream.c +# End Source File +# Begin Source File + +SOURCE=.\tran\fromobject.c +# End Source File +# Begin Source File + +SOURCE=.\tran\gate.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\globals.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\handlers.c +# End Source File +# Begin Source File + +SOURCE=.\snd\ieeecvt.c +# End Source File +# Begin Source File + +SOURCE=.\tran\ifft.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\instr.cpp +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\instr.h +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclar.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclarall.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclarfreq.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Instrmnt.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsax.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsaxall.c +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsaxfreq.c +# End Source File +# Begin Source File + +SOURCE=.\tran\integrate.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\inverse.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\local.c +# End Source File +# Begin Source File + +SOURCE=.\tran\log.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\longque.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\lpreson.c +# End Source File +# Begin Source File + +SOURCE=.\tran\maxv.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\mem.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifile.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifns.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\moxc.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiread.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiseq.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Noise.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\offset.c +# End Source File +# Begin Source File + +SOURCE=.\tran\oneshot.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\OneZero.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\osc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\partial.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\path.c +# End Source File +# Begin Source File + +SOURCE=.\tran\pluck.c +# End Source File +# Begin Source File + +SOURCE=.\tran\prod.c +# End Source File +# Begin Source File + +SOURCE=.\tran\pwl.c +# End Source File +# Begin Source File + +SOURCE=.\tran\quantize.c +# End Source File +# Begin Source File + +SOURCE=.\tran\recip.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\record.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\ReedTabl.cpp +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resamp.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resampv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\reson.c +# End Source File +# Begin Source File + +SOURCE=.\tran\resoncv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvv.c +# End Source File +# Begin Source File + +SOURCE=.\tran\sampler.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\samples.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Saxofony.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\scale.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seq.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqext.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqfnint.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqinterf.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmread.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmwrite.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqread.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqwrite.c +# End Source File +# Begin Source File + +SOURCE=.\tran\shape.c +# End Source File +# Begin Source File + +SOURCE=.\tran\sine.c +# End Source File +# Begin Source File + +SOURCE=.\tran\siosc.c +# End Source File +# Begin Source File + +SOURCE=.\tran\slope.c +# End Source File +# Begin Source File + +SOURCE=.\snd\snd.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndcvt.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndfail.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndfnint.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndheader.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndmax.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndread.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndseq.c +# End Source File +# Begin Source File + +SOURCE=.\snd\sndwin32.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndwritepa.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sound.c +# End Source File +# Begin Source File + +SOURCE=.\tran\sqrt.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\stats.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\Stk.cpp +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\stkinit.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\tapf.c +# End Source File +# Begin Source File + +SOURCE=.\tran\tapv.c +# End Source File +# Begin Source File + +SOURCE=.\cmt\tempomap.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\textio.cpp +# End Source File +# Begin Source File + +SOURCE=.\cmt\timebase.c +# End Source File +# Begin Source File + +SOURCE=.\tran\tone.c +# End Source File +# Begin Source File + +SOURCE=.\tran\tonev.c +# End Source File +# Begin Source File + +SOURCE=.\tran\upsample.c +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\WaveLoop.cpp +# End Source File +# Begin Source File + +SOURCE=.\tran\white.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\msvc\winfun.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\winguistuff.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\winmain.cpp +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\winmain.rc +# End Source File +# Begin Source File + +SOURCE=.\nyqstk\src\WvIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlbfun.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlcont.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xldbug.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xldmem.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xleval.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\xlextstart.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlfio.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlftab.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlglob.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlimage.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlinit.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlio.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlisp.c +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\xlispfns.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xljump.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xllist.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlmath.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlobj.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlpp.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlprin.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlread.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlstr.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlsubr.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlsym.c +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlsys.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\yin.c +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\yin.h +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\nyqsrc\add.h +# End Source File +# Begin Source File + +SOURCE=.\tran\alpass.h +# End Source File +# Begin Source File + +SOURCE=.\tran\amosc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\areson.h +# End Source File +# Begin Source File + +SOURCE=.\tran\aresoncv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\aresonvv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\atone.h +# End Source File +# Begin Source File + +SOURCE=.\tran\atonev.h +# End Source File +# Begin Source File + +SOURCE=.\snd\audiont.h +# End Source File +# Begin Source File + +SOURCE=.\snd\audiowin32.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\avg.h +# End Source File +# Begin Source File + +SOURCE=.\tran\biquad.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\button.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cext.h +# End Source File +# Begin Source File + +SOURCE=.\tran\chase.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cleanup.h +# End Source File +# Begin Source File + +SOURCE=.\tran\clip.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmdline.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\cmtcmd.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\compose.h +# End Source File +# Begin Source File + +SOURCE=.\tran\congen.h +# End Source File +# Begin Source File + +SOURCE=.\tran\const.h +# End Source File +# Begin Source File + +SOURCE=.\tran\convolve.h +# End Source File +# Begin Source File + +SOURCE=.\tran\coterm.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\cppext.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\debug.h +# End Source File +# Begin Source File + +SOURCE=.\tran\delay.h +# End Source File +# Begin Source File + +SOURCE=.\tran\delaycv.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\downsample.h +# End Source File +# Begin Source File + +SOURCE=.\tran\exp.h +# End Source File +# Begin Source File + +SOURCE=.\xlisp\extern.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\falloc.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\ffilterkit.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\fft.h +# End Source File +# Begin Source File + +SOURCE=.\fft\fftn.h +# End Source File +# Begin Source File + +SOURCE=.\tran\fmosc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\follow.h +# End Source File +# Begin Source File + +SOURCE=.\tran\fromarraystream.h +# End Source File +# Begin Source File + +SOURCE=.\tran\fromobject.h +# End Source File +# Begin Source File + +SOURCE=.\tran\gate.h +# End Source File +# Begin Source File + +SOURCE=.\snd\ieeecvt.h +# End Source File +# Begin Source File + +SOURCE=.\tran\ifft.h +# End Source File +# Begin Source File + +SOURCE=.\tran\instrclarall.h +# End Source File +# Begin Source File + +SOURCE=.\tran\instrsaxall.h +# End Source File +# Begin Source File + +SOURCE=.\tran\integrate.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\inverse.h +# End Source File +# Begin Source File + +SOURCE=.\tran\log.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\longque.h +# End Source File +# Begin Source File + +SOURCE=.\tran\maxv.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\mem.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifile.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\midifns.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\moxc.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiread.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\multiseq.h +# End Source File +# Begin Source File + +SOURCE=.\tran\offset.h +# End Source File +# Begin Source File + +SOURCE=.\tran\oneshot.h +# End Source File +# Begin Source File + +SOURCE=.\tran\osc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\partial.h +# End Source File +# Begin Source File + +SOURCE=.\tran\pluck.h +# End Source File +# Begin Source File + +SOURCE=.\tran\prod.h +# End Source File +# Begin Source File + +SOURCE=.\tran\pwl.h +# End Source File +# Begin Source File + +SOURCE=.\tran\quantize.h +# End Source File +# Begin Source File + +SOURCE=.\tran\recip.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\record.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resamp.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\resampv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\reson.h +# End Source File +# Begin Source File + +SOURCE=.\tran\resoncv.h +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvc.h +# End Source File +# Begin Source File + +SOURCE=.\tran\resonvv.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\resource.h +# End Source File +# Begin Source File + +SOURCE=.\tran\sampler.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\samples.h +# End Source File +# Begin Source File + +SOURCE=.\tran\scale.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seq.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqext.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\seqinterf.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmread.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqmwrite.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqread.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\seqwrite.h +# End Source File +# Begin Source File + +SOURCE=.\tran\shape.h +# End Source File +# Begin Source File + +SOURCE=.\tran\sine.h +# End Source File +# Begin Source File + +SOURCE=.\tran\siosc.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\slider.h +# End Source File +# Begin Source File + +SOURCE=.\tran\slope.h +# End Source File +# Begin Source File + +SOURCE=.\snd\snd.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndheader.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndmax.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndread.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndseq.h +# End Source File +# Begin Source File + +SOURCE=.\snd\sndwin32.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sndwrite.h +# End Source File +# Begin Source File + +SOURCE=.\nyqsrc\sound.h +# End Source File +# Begin Source File + +SOURCE=.\tran\tapv.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\tempomap.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\textio.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\timebase.h +# End Source File +# Begin Source File + +SOURCE=.\tran\tone.h +# End Source File +# Begin Source File + +SOURCE=.\tran\tonev.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\typein.h +# End Source File +# Begin Source File + +SOURCE=.\tran\upsample.h +# End Source File +# Begin Source File + +SOURCE=.\cmt\userio.h +# End Source File +# Begin Source File + +SOURCE=.\tran\white.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\msvc\winfun.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\winmain.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\winmain2.h +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xldmem.h +# End Source File +# Begin Source File + +SOURCE=.\xlisp\xlisp.h +# End Source File +# Begin Source File + +SOURCE=.\sys\win\wingui\xlispfns.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\sys\win\wingui\nycon.ico +# End Source File +# End Group +# Begin Group "portaudio-c" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_allocation.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_converters.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_cpuload.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_dither.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_front.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_process.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_skeleton.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_stream.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win\pa_win_hostapis.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win\pa_win_util.c +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win_wmme\pa_win_wmme.c +# End Source File +# End Group +# Begin Group "portaudio-h" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_allocation.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_converters.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_cpuload.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_dither.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_process.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_stream.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\pa_util.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_win_wmme\pa_win_wmme.h +# End Source File +# Begin Source File + +SOURCE=.\portaudio\pa_common\portaudio.h +# End Source File +# End Group +# End Target +# End Project diff --git a/nyqwin.vcproj b/nyqwin.vcproj new file mode 100644 index 0000000..a80ddf6 --- /dev/null +++ b/nyqwin.vcproj @@ -0,0 +1,4975 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/portaudio/COMPILING.DARWIN b/portaudio/COMPILING.DARWIN new file mode 100644 index 0000000..6d7aa87 --- /dev/null +++ b/portaudio/COMPILING.DARWIN @@ -0,0 +1 @@ +To compile on darwin, you will need to use the darwin makefile, gcc 3.3 or later and the universal SDK. for more info, see http://portaudio.com/trac/wiki/TutorialDir/Compile/MacintoshCoreAudio diff --git a/portaudio/Doxyfile b/portaudio/Doxyfile new file mode 100644 index 0000000..7dbfdfe --- /dev/null +++ b/portaudio/Doxyfile @@ -0,0 +1,239 @@ +# Doxyfile 1.4.6 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = PortAudio +PROJECT_NUMBER = 2.0 +OUTPUT_DIRECTORY = ./doc/ +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = doc/src \ + src \ + include \ + test +FILE_PATTERNS = *.h \ + *.c \ + *.cpp \ + *.dox +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/portaudio/LICENSE.txt b/portaudio/LICENSE.txt new file mode 100644 index 0000000..e0ac4e8 --- /dev/null +++ b/portaudio/LICENSE.txt @@ -0,0 +1,81 @@ +Portable header file to contain: +>>>>> +/* + * PortAudio Portable Real-Time Audio Library + * PortAudio API Header File + * Latest version available at: http://www.portaudio.com + * + * Copyright (c) 1999-2006 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ +<<<<< + + +Implementation files to contain: +>>>>> +/* + * PortAudio Portable Real-Time Audio Library + * Latest version at: http://www.portaudio.com + * Implementation + * Copyright (c) 1999-2000 + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ +<<<<< \ No newline at end of file diff --git a/portaudio/Makefile.in b/portaudio/Makefile.in new file mode 100644 index 0000000..3369cbf --- /dev/null +++ b/portaudio/Makefile.in @@ -0,0 +1,212 @@ +# +# PortAudio V19 Makefile.in +# +# Dominic Mazzoni +# Modifications by Mikael Magnusson +# + +top_srcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +top_builddir = . +PREFIX = @prefix@ +prefix = $(PREFIX) +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +CC = @CC@ +CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/common -I$(top_srcdir)/src/os/unix @CFLAGS@ @DEFS@ +LIBS = @LIBS@ +AR = @AR@ +RANLIB = @RANLIB@ +LIBTOOL = @LIBTOOL@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +SHARED_FLAGS = @SHARED_FLAGS@ +LDFLAGS = @LDFLAGS@ +DLL_LIBS = @DLL_LIBS@ +CXXFLAGS = @CXXFLAGS@ +NASM = @NASM@ +NASMOPT = @NASMOPT@ +LN_S = @LN_S@ +LT_RELEASE=@LT_RELEASE@ +LT_CURRENT=@LT_CURRENT@ +LT_REVISION=@LT_REVISION@ +LT_AGE=@LT_AGE@ + +OTHER_OBJS = @OTHER_OBJS@ + +PALIB = libportaudio.la +PAINC = include/portaudio.h + +PA_LDFLAGS = $(LDFLAGS) $(SHARED_FLAGS) -rpath $(libdir) -no-undefined -export-symbols-regex "(Pa|PaMacCore)_.*" -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) +#MAKEFILE = Makefile + +COMMON_OBJS = \ + src/common/pa_allocation.o \ + src/common/pa_converters.o \ + src/common/pa_cpuload.o \ + src/common/pa_dither.o \ + src/common/pa_debugprint.o \ + src/common/pa_front.o \ + src/common/pa_process.o \ + src/common/pa_skeleton.o \ + src/common/pa_stream.o \ + src/common/pa_trace.o + +TESTS = \ + bin/paqa_devs \ + bin/paqa_errs \ + bin/patest1 \ + bin/patest_buffer \ + bin/patest_callbackstop \ + bin/patest_clip \ + bin/patest_dither \ + bin/patest_hang \ + bin/patest_in_overflow \ + bin/patest_latency \ + bin/patest_leftright \ + bin/patest_longsine \ + bin/patest_many \ + bin/patest_maxsines \ + bin/patest_multi_sine \ + bin/patest_out_underflow \ + bin/patest_pink \ + bin/patest_prime \ + bin/patest_read_record \ + bin/patest_read_write_wire \ + bin/patest_record \ + bin/patest_ringmix \ + bin/patest_saw \ + bin/patest_sine8 \ + bin/patest_sine \ + bin/patest_sine_channelmaps \ + bin/patest_sine_formats \ + bin/patest_sine_time \ + bin/patest_start_stop \ + bin/patest_stop \ + bin/patest_stop_playout \ + bin/patest_toomanysines \ + bin/patest_underflow \ + bin/patest_wire \ + bin/patest_write_sine \ + bin/pa_devs \ + bin/pa_fuzz \ + bin/pa_minlat + +# Most of these don't compile yet. Put them in TESTS, above, if +# you want to try to compile them... +ALL_TESTS = \ + $(TESTS) \ + bin/patest_sync \ + bin/debug_convert \ + bin/debug_dither_calc \ + bin/debug_dual \ + bin/debug_multi_in \ + bin/debug_multi_out \ + bin/debug_record \ + bin/debug_record_reuse \ + bin/debug_sine_amp \ + bin/debug_sine \ + bin/debug_sine_formats \ + bin/debug_srate \ + bin/debug_test1 + +OBJS = $(COMMON_OBJS) $(OTHER_OBJS) + +LTOBJS:= $(OBJS:.o=.lo) + +SUBDIRS = +@ENABLE_CXX_TRUE@SUBDIRS += bindings/cpp + +all: lib/$(PALIB) all-recursive tests + +tests: bin-stamp $(TESTS) + + +lib/$(PALIB): lib-stamp $(LTOBJS) $(MAKEFILE) $(PAINC) + $(LIBTOOL) --mode=link $(CC) $(PA_LDFLAGS) -o lib/$(PALIB) $(LTOBJS) $(DLL_LIBS) + +$(ALL_TESTS): bin/%: lib/$(PALIB) $(MAKEFILE) $(PAINC) test/%.c + $(LIBTOOL) --mode=link $(CC) -o $@ $(CFLAGS) $(top_srcdir)/test/$*.c lib/$(PALIB) $(LIBS) + + +install: lib/$(PALIB) portaudio-2.0.pc + $(INSTALL) -d $(DESTDIR)$(libdir) + $(LIBTOOL) --mode=install $(INSTALL) lib/$(PALIB) $(DESTDIR)$(libdir) + $(INSTALL) -d $(DESTDIR)$(includedir) + $(INSTALL_DATA) -m 644 $(top_srcdir)/$(PAINC) $(DESTDIR)$(includedir)/portaudio.h + $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig + $(INSTALL) -m 644 portaudio-2.0.pc $(DESTDIR)$(libdir)/pkgconfig/portaudio-2.0.pc + @echo "" + @echo "------------------------------------------------------------" + @echo "PortAudio was successfully installed." + @echo "" + @echo "On some systems (e.g. Linux) you should run 'ldconfig' now" + @echo "to make the shared object available. You may also need to" + @echo "modify your LD_LIBRARY_PATH environment variable to include" + @echo "the directory $(libdir)" + @echo "------------------------------------------------------------" + @echo "" + $(MAKE) install-recursive + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$(PALIB) + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(includedir)/portaudio.h + $(MAKE) uninstall-recursive + +clean: + $(LIBTOOL) --mode=clean rm -f $(LTOBJS) $(ALL_TESTS) lib/$(PALIB) + rm -f bin-stamp lib-stamp + -rm -rf bin lib + +distclean: clean + rm -f config.log config.status Makefile libtool portaudio-2.0.pc + +%.o: %.c $(MAKEFILE) $(PAINC) + $(CC) -c $(CFLAGS) $< -o $@ + +%.lo: %.c $(MAKEFILE) $(PAINC) + $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $< -o $@ + +%.o: %.cpp $(MAKEFILE) $(PAINC) + $(CXX) -c $(CXXFLAGS) $< -o $@ + +%.o: %.asm + $(NASM) $(NASMOPT) -o $@ $< + +bin-stamp: + -mkdir bin + touch $@ + +lib-stamp: + -mkdir lib + -mkdir -p \ + src/common \ + src/hostapi/alsa \ + src/hostapi/asihpi \ + src/hostapi/asio \ + src/hostapi/coreaudio \ + src/hostapi/dsound \ + src/hostapi/jack \ + src/hostapi/oss \ + src/hostapi/wasapi \ + src/hostapi/wdmks \ + src/hostapi/wmme \ + src/os/mac_osx \ + src/os/unix \ + src/os/win + touch $@ + +Makefile: Makefile.in config.status + $(SHELL) config.status + +all-recursive: + for dir in $(SUBDIRS); do make -C $$dir all; done + +install-recursive: + for dir in $(SUBDIRS); do make -C $$dir install; done + +uninstall-recursive: + for dir in $(SUBDIRS); do make -C $$dir uninstall; done diff --git a/portaudio/README.txt b/portaudio/README.txt new file mode 100644 index 0000000..2d7877f --- /dev/null +++ b/portaudio/README.txt @@ -0,0 +1,96 @@ +README for PortAudio + +/* + * PortAudio Portable Real-Time Audio Library + * Latest Version at: http://www.portaudio.com + * + * Copyright (c) 1999-2006 Phil Burk and Ross Bencina + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ + + +PortAudio is a portable audio I/O library designed for cross-platform +support of audio. It uses either a callback mechanism to request audio +processing, or blocking read/write calls to buffer data between the +native audio subsystem and the client. Audio can be processed in various +formats, including 32 bit floating point, and will be converted to the +native format internally. + +Documentation: + Documentation is available in "/doc/html/index.html" + Also see "src/common/portaudio.h" for API spec. + Also see http://www.portaudio.com/docs/ + And see "tests/patest_saw.c" for an example. + +For information on compiling programs with PortAudio, please see the +tutorial at: + + http://portaudio.com/trac/wiki/TutorialDir/TutorialStart + + +Important Files and Folders: + include/portaudio.h = header file for PortAudio API. Specifies API. + src/common/ = platform independant code, host independant + code for all implementations. + src/os = os specific (but host api neutral) code + src/hostapi = implementations for different host apis + + pablio = simple blocking read/write interface + + +Host API Implementations: + src/hostapi/alsa = Advanced Linux Sound Architecture (ALSA) + src/hostapi/asihpi = AudioScience HPI + src/hostapi/asio = ASIO for Windows and Macintosh + src/hostapi/coreaudio = Macintosh Core Audio for OS X + src/hostapi/dsound = Windows Direct Sound + src/hostapi/jack = JACK Audio Connection Kit + src/hostapi/oss = Unix Open Sound System (OSS) + src/hostapi/wasapi = Windows Vista WASAPI + src/hostapi/wdmks = Windows WDM Kernel Streaming + src/hostapi/wmme = Windows MME (most widely supported) + + +Test Programs: + tests/pa_fuzz.c = guitar fuzz box + tests/pa_devs.c = print a list of available devices + tests/pa_minlat.c = determine minimum latency for your machine + tests/paqa_devs.c = self test that opens all devices + tests/paqa_errs.c = test error detection and reporting + tests/patest_clip.c = hear a sine wave clipped and unclipped + tests/patest_dither.c = hear effects of dithering (extremely subtle) + tests/patest_pink.c = fun with pink noise + tests/patest_record.c = record and playback some audio + tests/patest_maxsines.c = how many sine waves can we play? Tests Pa_GetCPULoad(). + tests/patest_sine.c = output a sine wave in a simple PA app + tests/patest_sync.c = test syncronization of audio and video + tests/patest_wire.c = pass input to output, wire simulator diff --git a/portaudio/SConstruct b/portaudio/SConstruct new file mode 100644 index 0000000..15d36ba --- /dev/null +++ b/portaudio/SConstruct @@ -0,0 +1,194 @@ +import sys, os.path + +def rsplit(toSplit, sub, max=-1): + """ str.rsplit seems to have been introduced in 2.4 :( """ + l = [] + i = 0 + while i != max: + try: idx = toSplit.rindex(sub) + except ValueError: break + + toSplit, splitOff = toSplit[:idx], toSplit[idx + len(sub):] + l.insert(0, splitOff) + i += 1 + + l.insert(0, toSplit) + return l + +sconsDir = os.path.join("build", "scons") +SConscript(os.path.join(sconsDir, "SConscript_common")) +Import("Platform", "Posix", "ApiVer") + +# SConscript_opts exports PortAudio options +optsDict = SConscript(os.path.join(sconsDir, "SConscript_opts")) +optionsCache = os.path.join(sconsDir, "options.cache") # Save options between runs in this cache +options = Options(optionsCache, args=ARGUMENTS) +for k in ("Installation Dirs", "Build Targets", "Host APIs", "Build Parameters", "Bindings"): + options.AddOptions(*optsDict[k]) +# Propagate options into environment +env = Environment(options=options) +# Save options for next run +options.Save(optionsCache, env) +# Generate help text for options +env.Help(options.GenerateHelpText(env)) + +buildDir = os.path.join("#", sconsDir, env["PLATFORM"]) + +# Determine parameters to build tools +if Platform in Posix: + baseLinkFlags = threadCFlags = "-pthread" + baseCxxFlags = baseCFlags = "-Wall -pedantic -pipe " + threadCFlags + debugCxxFlags = debugCFlags = "-g" + optCxxFlags = optCFlags = "-O2" +env["CCFLAGS"] = baseCFlags.split() +env["CXXFLAGS"] = baseCxxFlags.split() +env["LINKFLAGS"] = baseLinkFlags.split() +if env["enableDebug"]: + env.AppendUnique(CCFLAGS=debugCFlags.split()) + env.AppendUnique(CXXFLAGS=debugCxxFlags.split()) +if env["enableOptimize"]: + env.AppendUnique(CCFLAGS=optCFlags.split()) + env.AppendUnique(CXXFLAGS=optCxxFlags.split()) +if not env["enableAsserts"]: + env.AppendUnique(CPPDEFINES=["-DNDEBUG"]) +if env["customCFlags"]: + env.Append(CCFLAGS=Split(env["customCFlags"])) +if env["customCxxFlags"]: + env.Append(CXXFLAGS=Split(env["customCxxFlags"])) +if env["customLinkFlags"]: + env.Append(LINKFLAGS=Split(env["customLinkFlags"])) + +env.Append(CPPPATH=[os.path.join("#", "include"), "common"]) + +# Store all signatures in one file, otherwise .sconsign files will get installed along with our own files +env.SConsignFile(os.path.join(sconsDir, ".sconsign")) + +env.SConscriptChdir(False) +sources, sharedLib, staticLib, tests, portEnv, hostApis = env.SConscript(os.path.join("src", "SConscript"), + build_dir=buildDir, duplicate=False, exports=["env"]) + +if Platform in Posix: + prefix = env["prefix"] + includeDir = os.path.join(prefix, "include") + libDir = os.path.join(prefix, "lib") + env.Alias("install", includeDir) + env.Alias("install", libDir) + + # pkg-config + + def installPkgconfig(env, target, source): + tgt = str(target[0]) + src = str(source[0]) + f = open(src) + try: txt = f.read() + finally: f.close() + txt = txt.replace("@prefix@", prefix) + txt = txt.replace("@exec_prefix@", prefix) + txt = txt.replace("@libdir@", libDir) + txt = txt.replace("@includedir@", includeDir) + txt = txt.replace("@LIBS@", " ".join(["-l%s" % l for l in portEnv["LIBS"]])) + txt = txt.replace("@THREAD_CFLAGS@", threadCFlags) + + f = open(tgt, "w") + try: f.write(txt) + finally: f.close() + + pkgconfigTgt = "portaudio-%d.0.pc" % int(ApiVer.split(".", 1)[0]) + env.Command(os.path.join(libDir, "pkgconfig", pkgconfigTgt), + os.path.join("#", pkgconfigTgt + ".in"), installPkgconfig) + +# Default to None, since if the user disables all targets and no Default is set, all targets +# are built by default +env.Default(None) +if env["enableTests"]: + env.Default(tests) +if env["enableShared"]: + env.Default(sharedLib) + + if Platform in Posix: + def symlink(env, target, source): + trgt = str(target[0]) + src = str(source[0]) + + if os.path.islink(trgt) or os.path.exists(trgt): + os.remove(trgt) + os.symlink(os.path.basename(src), trgt) + + major, minor, micro = [int(c) for c in ApiVer.split(".")] + + soFile = "%s.%s" % (os.path.basename(str(sharedLib[0])), ApiVer) + env.InstallAs(target=os.path.join(libDir, soFile), source=sharedLib) + # Install symlinks + symTrgt = os.path.join(libDir, soFile) + env.Command(os.path.join(libDir, "libportaudio.so.%d.%d" % (major, minor)), + symTrgt, symlink) + symTrgt = rsplit(symTrgt, ".", 1)[0] + env.Command(os.path.join(libDir, "libportaudio.so.%d" % major), symTrgt, symlink) + symTrgt = rsplit(symTrgt, ".", 1)[0] + env.Command(os.path.join(libDir, "libportaudio.so"), symTrgt, symlink) + +if env["enableStatic"]: + env.Default(staticLib) + env.Install(libDir, staticLib) + +env.Install(includeDir, os.path.join("include", "portaudio.h")) + + +if env["enableCxx"]: + env.SConscriptChdir(True) + cxxEnv = env.Copy() + sharedLibs, staticLibs, headers = env.SConscript(os.path.join("bindings", "cpp", "SConscript"), + exports={"env": cxxEnv, "buildDir": buildDir}, build_dir=os.path.join(buildDir, "portaudiocpp"), duplicate=False) + if env["enableStatic"]: + env.Default(staticLibs) + env.Install(libDir, staticLibs) + if env["enableShared"]: + env.Default(sharedLibs) + env.Install(libDir, sharedLibs) + env.Install(os.path.join(includeDir, "portaudiocpp"), headers) + +# Generate portaudio_config.h header with compile-time definitions of which PA +# back-ends are available, and which includes back-end extension headers + +# Host-specific headers +hostApiHeaders = {"ALSA": "pa_linux_alsa.h", + "ASIO": "pa_asio.h", + "COREAUDIO": "pa_mac_core.h", + "JACK": "pa_jack.h", + "WMME": "pa_winwmme.h", + } + +def buildConfigH(target, source, env): + """builder for portaudio_config.h""" + global hostApiHeaders, hostApis + out = "" + for hostApi in hostApis: + out += "#define PA_HAVE_%s\n" % hostApi + + hostApiSpecificHeader = hostApiHeaders.get(hostApi, None) + if hostApiSpecificHeader: + out += "#include \"%s\"\n" % hostApiSpecificHeader + + out += "\n" + # Strip the last newline + if out[-1] == "\n": + out = out[:-1] + + f = file(str(target[0]), 'w') + try: f.write(out) + finally: f.close() + return 0 + +# Define the builder for the config header +env.Append(BUILDERS={"portaudioConfig": env.Builder(action=Action(buildConfigH, + "generating '$TARGET'"), target_factory=env.fs.File,)}) + +confH = env.portaudioConfig(File("portaudio_config.h", "include"), + File("portaudio.h", "include")) +env.Default(confH) +env.Install(os.path.join(includeDir, "portaudio"), confH) + +for api in hostApis: + if api in hostApiHeaders: + env.Install(os.path.join(includeDir, "portaudio"), + File(hostApiHeaders[api], "include")) diff --git a/portaudio/V19-devel-readme.txt b/portaudio/V19-devel-readme.txt new file mode 100644 index 0000000..ad5e137 --- /dev/null +++ b/portaudio/V19-devel-readme.txt @@ -0,0 +1,129 @@ +/* + This file was a scribble area during the early phases of development. + + It's out of date but will probably hang around untill all the content + has been cleaned out or found a new home. + + Here's some tasks to undertake: + o- make sure that the @brief comments in each file are at least + as good as the file descriptions below, then delete the file + descriptions below. + + o- make sure that the coding guidelines below appear in the + pa_proposals style guide, then delete from below. + + o- verify and move the TODO items into TRAC +*/ + + +FILES: + +portaudio.h + public api header file + +pa_front.c + implements the interface defined in portaudio.h. manages multiple host apis. + validates function parameters before calling through to host apis. tracks + open streams and closes them at Pa_Terminate(). + +pa_util.h + declares utility functions for use my implementations. including utility + functions which must be implemented separately for each platform. + +pa_hostapi.h + hostapi representation structure used to interface between pa_front.c + and implementations + +pa_stream.c/h + stream interface and representation structures and helper functions + used to interface between pa_front.c and implementations + +pa_cpuload.c/h + source and header for cpu load calculation facility + +pa_trace.c/h + source and header for debug trace log facility + +pa_converters.c/h + sample buffer conversion facility + +pa_dither.c/h + dither noise generator + +pa_process.c/h + callback buffer processing facility including interleave and block adaption + +pa_allocation.c/h + allocation context for tracking groups of allocations + +pa_skeleton.c + an skeleton implementation showing how the common code can be used. + +pa_win_util.c + Win32 implementation of platform specific PaUtil functions (memory allocation, + usec clock, Pa_Sleep().) The file will be used with all Win32 host APIs. + +pa_win_hostapis.c + contains the paHostApiInitializers array and an implementation of + Pa_GetDefaultHostApi() for win32 builds. + +pa_win_wmme.c + Win32 host api implementation for the windows multimedia extensions audio API. + +pa_win_wmme.h + public header file containing interfaces to mme-specific functions and the + deviceInfo data structure. + + +CODING GUIDELINES: + +naming conventions: + #defines begin with PA_ + #defines local to a file end with _ + global utility variables begin with paUtil + global utility types begin with PaUtil (including function types) + global utility functions begin with PaUtil_ + static variables end with _ + static constants begin with const and end with _ + static funtions have no special prefix/suffix + +In general, implementations should declare all of their members static, +except for their initializer which should be exported. All exported names +should be preceeded by Pa_ where MN is the module name, for example +the windows mme initializer should be named PaWinWmme_Initialize(). + +Every host api should define an initializer which returns an error code +and a PaHostApiInterface*. The initializer should only return an error other +than paNoError if it encounters an unexpected and fatal error (memory allocation +error for example). In general, there may be conditions under which it returns +a NULL interface pointer and also returns paNoError. For example, if the ASIO +implementation detects that ASIO is not installed, it should return a +NULL interface, and paNoError. + +Platform-specific shared functions should begin with Pa_ where PN is the +platform name. eg. PaWin_ for windows, PaUnix_ for unix. + +The above two conventions should also be followed whenever it is necessary to +share functions accross multiple source files. + +Two utilities for debug messages are provided. The PA_DEBUG macro defined in +pa_implementation.h provides a simple way to print debug messages to stderr. +Due to real-time performance issues, PA_DEBUG may not be suitable for use +within the portaudio processing callback, or in other threads. In such cases +the event tracing facility provided in pa_trace.h may be more appropriate. + +If PA_LOG_API_CALLS is defined, all calls to the public PortAudio API +will be logged to stderr along with parameter and return values. + + +TODO: (these need to be turned into TRAC items) + write some new tests to exercise the multi-host-api functions + + write (doxygen) documentation for pa_trace (phil?) + + create a global configuration file which documents which PA_ defines can be + used for configuration + + need a coding standard for comment formatting + + write style guide document (ross) diff --git a/portaudio/aclocal.m4 b/portaudio/aclocal.m4 new file mode 100644 index 0000000..c80e0ac --- /dev/null +++ b/portaudio/aclocal.m4 @@ -0,0 +1,57 @@ + +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN(PKG_CHECK_MODULES, [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + diff --git a/portaudio/bindings/cpp/AUTHORS b/portaudio/bindings/cpp/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/portaudio/bindings/cpp/COPYING b/portaudio/bindings/cpp/COPYING new file mode 100644 index 0000000..c1c60a0 --- /dev/null +++ b/portaudio/bindings/cpp/COPYING @@ -0,0 +1,31 @@ +PortAudio Portable Real-Time Audio Library +Copyright (c) 1999-2006 Ross Bencina and Phil Burk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +The text above constitutes the entire PortAudio license; however, +the PortAudio community also makes the following non-binding requests: + +Any person wishing to distribute modifications to the Software is +requested to send the modifications to the original developer so that +they can be incorporated into the canonical version. It is also +requested that these non-binding requests be included along with the +license above. diff --git a/portaudio/bindings/cpp/ChangeLog b/portaudio/bindings/cpp/ChangeLog new file mode 100644 index 0000000..0201a0f --- /dev/null +++ b/portaudio/bindings/cpp/ChangeLog @@ -0,0 +1,178 @@ +Note: Because PortAudioCpp is now in the main PortAudio SVN repository, having these per-release changelogs probably doesn't make much sense anymore. Perhaps it's better to just note mayor changes by date from now on. + +PortAudioCpp v19 revision 16 06/05/22: + + mblaauw: + - Added up-to-date MSVC 6.0 projects created by David Moore. Besides MSVC 6.0 users, MSVC 7.0 users may use these projects and automatically convert them to MSVC 7.0 projects. + - Changed the code and projects (MSVC 7.1 only) to be up-to-date with PortAudio's new directory structure. + - Added equivalents of the PaAsio_GetInputChannelName() and PaAsio_GetOutputChannelName() functions to the AsioDeviceAdapter wrapper-class (missing functions pointed out by David Moore). + - Added code to PortAudio's main SVN repository. + +PortAudioCpp v19 revision 15 (unknown release date): + + mblaauw: + - Changed some exception handling code in HostApi's constructor. + - Added accessors to PortAudio PaStream from PortAudioCpp Stream (their absense being pointed out + by Tom Jordan). + - Fixed a bug/typo in MemFunToCallbackInterfaceAdapter::init() thanks to Fredrik Viklund. + - Fixed issue with concrete Stream classes possibly throwing an exception and fixed documentation w.r.t. this. + - Moved files to portaudio/binding/cpp/. Made new msvc 7.1 projects to reflect the change and removed msvc 6.0 + and 7.0 projects (because I can no longer maintain them myself). Gnu projects will probably need updating. + +PortAudioCpp v19 revision 14 03/10/24: + + mblaauw: + - Fixed some error handling bugs in Stream and System (pointed out by Tom Jordan). + - Updated documentation a little (main page). + - Fixed order of members so initializer list was in the right order in + StreamParameters (pointed out by Ludwig Schwardt). + - Added new lines at EOF's (as indicated by Ludwig Schwardt). + +PortAudioCpp v19 revision 13 03/10/19: + + lschwardt: + - Added build files for GNU/Linux. + - Fixed bug in Exception where the inherited what() member function (and destructor) had looser + exception specification (namely no exception specification, i.e. could throw anything) than + the std::exception base class's what() member function (which had throw(), i.e. no-throw guarantee). + - Changed the iterators so that they have a set of public typedefs instead of deriving the C++ standard + library std::iterator<> struct. G++ 2.95 doesn't support std::exception<> and composition-by-aggregation + is prefered over composition-by-inheritance in this case. + - Changed some minor things to avoid G++ warning messages. + + mblaauw: + - Renamed this file (/WHATSNEW.txt) to /CHANGELOG. + - Renamed /PA_ISSUES.txt to /PA_ISSUES. + - Added /INSTALL file with some build info for GNU/Linux and VC6. + - Added MSVC 6.0 projects for building PortAudioCpp as a staticly or dynamically linkable library. + - Moved build files to /build/(gnu/ or vc6/). + - Moved Doxygen configuration files to /doc/ and output to /doc/api_reference/. + - Added a /doc/README with some info how to generate Doxygen documentation. + +PortAudioCpp v19 revision 12 03/09/02: + + mblaauw: + - Updated code to reflect changes on V19-devel CVS branch. + - Fixed some typos in the documentation. + +PortAudioCpp v19 revision 11 03/07/31: + + mblaauw: + - Renamed SingleDirecionStreamParameters to DirectionSpecificStreamParameters. + - Implemented BlockingStream. + - Updated code to reflect recent changes to PortAudio V19-devel. + - Fixed a potential memory leak when an exception was thrown in the HostApi + constructor. + - Renamed ``Latency'' to ``BufferSize'' in AsioDeviceAdapter. + - Updated class documentation. + +PortAudioCpp v19 revision 10 03/07/18: + + mblaauw: + - SingleDirectionStreamParameters now has a (static) null() method. + - StreamParameters uses references for the direction-specific stream parameters + instead of pointers (use null() method (above) instead of NULL). + - StreamParameters and SingleDirectionStreamParameters must now be fully specified + and now default values are used (because this was not very useful in general and + only made things more complex). + - Updated documentation. + +PortAudioCpp v19 revision 09 03/06/25: + + mblaauw: + - Changed some things in SingleDirectionStreamParameters to ease it's usage. + - Placed all SingleDirectionStreamParameters stuff into a separate file. + + Totally redid the callback stuff, now it's less ackward and supports C++ functions. + +PortAudioCpp v19 revision 08 03/06/20: + + mblaauw: + - Made deconstructors for Device and HostApi private. + + Added a AsioDeviceWrapper host api specific device extension class. + - Refactored Exception into a Exception base class and PaException and PaCppException + derived classes. + - Added ASIO specific device info to the devs.cxx example. + - Fixed a bug in System::hostApiCount() and System::defaultHostApi(). + + Moved Device::null to System::nullDevice. + - Fixed some bugs in Device and System. + +PortAudioCpp v19 revision 07 03/06/08: + + mblaauw: + - Updated some doxy comments. + + Renamed CbXyz to CallbackXyz. + + Renamed all ``configurations'' to ``parameters''. + + Renamed HalfDuplexStreamConfiguration to SingleDirectionStreamConfiguration. + - Renamed SingleDirectionStreamParameters::streamParameters() to + SingleDirectionStreamParameters::paSteamParameters. + - Added a non-constant version of SingleDirectionStreamParameters::paStreamParameters(). + - A few improvements to SingleDirectionStreamParameters. + - Allowed AutoSystem to be created without initializing the System singleton + (using a ctor flag). + - Added a BlockingStream class (not implemented for now). + - Fixed many bugs in the implementation of the iterators. + - Fixed a bug in Device::operator==(). + + Added a C++ version of the patest_sine.c test/example. + - Added a ctor for StreamParameters for a default half-duplex stream. + - Added SingleDirectionStreamParameters::setDevice() and setNumChannels(). + - Renamed System::numHostApis() to System::hostApiCount(). + + Rewrote the iterators and related classes. They are now fully STL compliant. The System now + has a static array of all HostApis and all Devices. Only the System can create HostApis and + Devices and they are non-copyable now. All HostApis and Devices are now passed by-reference. + - Renamed (System::) getVersion() to version() and getVersionText() to versionText(). + - Renamed (Device::) numXyzChannels() to maxXyzChannels(). + - Changed some stuff in StreamParameters. + + Added a C++ version of the patest_devs.c test/example. + +PortAudioCpp v19 revision 06 03/06/04: + + mblaauw: + + Added this file to the project (roughly, a `+' denotes a major change, a `-' a minor change). + - Added System::deviceByIndex(), useful when a Device's index is stored for instance. + - Renamed System::hostApiFromTypeId() to System::hostApiByTypeId(). + - Updated and added some Doxygen documentation. + - Made Stream::usedIntputLatency(), Stream::usedOutputLatency() and + Stream::usedSampleRate() throw an paInternalError equivalent exception instead of paBadStreamPtr. + - Changed exception handling in Stream::open() functions. They now follow the PA error handling + mechanism better and a couple of bugs regarding ownership of objects were fixed. + - Renamed Device::isDefaultXyzDevice() to Device::isSystemDefaultXyzDevice(). + - Added Device::isHostApiDefaultXyzDevice(). + - Added StreamConfiguration::unsetFlag(). + - Removed CUSTOM from SampleDataFormat. + - System::hostApiByTypeId() now throws an paInternalError if the type id was out-of-range; this + is a temporary work-around (see comments). + - Changed CbInterface to use paCallbackFun() instead of operator()(). + - Renamed ``object'' to ``instance'' in CbMemFunAdapter.hxx. + - Added StreamConfiguration::setXyzHostApiSpecificSampleFormat(). + - Added StreamConfiguration::isXyzSampleFormatHostApiSpecific(). + - Changed error handling in System::terminate(), it can now throw an Exception. + - Added error handling in System::defaultHostApi(). + - Added error handling in System::hostApisEnd(). + - Changed some (but probably not all) C casts to C++ casts to avoid confusion with a + certain Python person. + - Renamed RaiiSystem to AutoSystem (class and file) as this is a come common convention. + - Renamed System::numDevices() to System::deviceCount() to be more compatible with PortAudio + (although PortAudio uses Pa_CountDevices() instead, see comment). + - Renamed HostApi::numDevices() to HostApi::deviceCount(). + - Changed INC_ to INCLUDED_ in the header multiple include guards. + - Changed the order of functions in the StreamConfiguration class' header. + - Written some more info in PortAudioCpp.hxx (Doxygen). + - Added CallbackStream.hxx and CallbackStream.cxx files. + + Refactored StreamConfiguration to remove the duplication which was there. There is now a + HalfDuplexStreamConfiguration class. Also made some improvements to these classes while + doing the refactoring. + + Moved all code files to source/portaudiocpp/ and changed includes. + + Moved all header files to include/portaudiocpp/ to easy a binary build if needed. The project + must be set to have .../include/ as a path to look for includes. + + Refactored the Stream class into a Stream base class and a CallbackStream derived class. + - Renamed Stream::usingXyz() to Stream::xyz(). + - Updated some doxy comments. + - Changed ``using namespace portaudio'' in .cxx files to ``namespace portaudio { ... }''. + +PortAudioCpp v19 revision 05 03/04/09: + + mblaauw: + - Initial release on the PortAudio mailinglist. + + + diff --git a/portaudio/bindings/cpp/INSTALL b/portaudio/bindings/cpp/INSTALL new file mode 100644 index 0000000..23e5f25 --- /dev/null +++ b/portaudio/bindings/cpp/INSTALL @@ -0,0 +1,236 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/portaudio/bindings/cpp/Makefile.am b/portaudio/bindings/cpp/Makefile.am new file mode 100644 index 0000000..b10449c --- /dev/null +++ b/portaudio/bindings/cpp/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = lib include bin +#doc + +EXTRA_DIST = portaudiocpp.pc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = portaudiocpp.pc diff --git a/portaudio/bindings/cpp/Makefile.in b/portaudio/bindings/cpp/Makefile.in new file mode 100644 index 0000000..f60601b --- /dev/null +++ b/portaudio/bindings/cpp/Makefile.in @@ -0,0 +1,642 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = . +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = README $(am__configure_deps) \ + $(srcdir)/../../config.guess $(srcdir)/../../config.sub \ + $(srcdir)/../../install-sh $(srcdir)/../../ltmain.sh \ + $(srcdir)/../../missing $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/portaudiocpp.pc.in \ + $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno configure.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = portaudiocpp.pc +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +pkgconfigDATA_INSTALL = $(INSTALL_DATA) +DATA = $(pkgconfig_DATA) +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_INCLUDES = @DEFAULT_INCLUDES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PORTAUDIO_ROOT = @PORTAUDIO_ROOT@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +SUBDIRS = lib include bin +#doc +EXTRA_DIST = portaudiocpp.pc +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = portaudiocpp.pc +all: all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \ + cd $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +portaudiocpp.pc: $(top_builddir)/config.status $(srcdir)/portaudiocpp.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)" + @list='$(pkgconfig_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \ + $(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \ + rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + mkdir $(distdir) + $(mkdir_p) $(distdir)/. $(distdir)/../.. + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && cd $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' +distuninstallcheck: + @cd $(distuninstallcheck_dir) \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am uninstall-pkgconfigDATA + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ + check-am clean clean-generic clean-libtool clean-recursive \ + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ + dist-shar dist-tarZ dist-zip distcheck distclean \ + distclean-generic distclean-libtool distclean-recursive \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-pkgconfigDATA \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am uninstall-info-am \ + uninstall-pkgconfigDATA + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/portaudio/bindings/cpp/NEWS b/portaudio/bindings/cpp/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/portaudio/bindings/cpp/README b/portaudio/bindings/cpp/README new file mode 100644 index 0000000..e69de29 diff --git a/portaudio/bindings/cpp/SConscript b/portaudio/bindings/cpp/SConscript new file mode 100644 index 0000000..2bad5ee --- /dev/null +++ b/portaudio/bindings/cpp/SConscript @@ -0,0 +1,64 @@ +import os.path + +Import("env", "buildDir") +env.Append(CPPPATH="include") + +ApiVer = "0.0.12" +Major, Minor, Micro = [int(c) for c in ApiVer.split(".")] + +sharedLibs = [] +staticLibs = [] +Import("Platform", "Posix") +if Platform in Posix: + env["SHLIBSUFFIX"] = ".so.%d.%d.%d" % (Major, Minor, Micro) + soFile = "libportaudiocpp.so" + env.AppendUnique(SHLINKFLAGS="-Wl,-soname=%s.%d" % (soFile, Major)) + + # Create symlinks + def symlink(env, target, source): + trgt = str(target[0]) + src = str(source[0]) + if os.path.islink(trgt) or os.path.exists(trgt): + os.remove(trgt) + os.symlink(os.path.basename(src), trgt) + lnk0 = env.Command(soFile + ".%d" % (Major), soFile + ".%d.%d.%d" % (Major, Minor, Micro), symlink) + lnk1 = env.Command(soFile, soFile + ".%d" % (Major), symlink) + sharedLibs.append(lnk0) + sharedLibs.append(lnk1) + +src = [os.path.join("source", "portaudiocpp", "%s.cxx" % f) for f in ("BlockingStream", "CallbackInterface", \ + "CallbackStream", "CFunCallbackStream","CppFunCallbackStream", "Device", + "DirectionSpecificStreamParameters", "Exception", "HostApi", "InterfaceCallbackStream", + "MemFunCallbackStream", "Stream", "StreamParameters", "System", "SystemDeviceIterator", + "SystemHostApiIterator")] +env.Append(LIBS="portaudio", LIBPATH=buildDir) +sharedLib = env.SharedLibrary("portaudiocpp", src, LIBS=["portaudio"]) +staticLib = env.Library("portaudiocpp", src, LIBS=["portaudio"]) +sharedLibs.append(sharedLib) +staticLibs.append(staticLib) + +headers = Split("""AutoSystem.hxx + BlockingStream.hxx + CallbackInterface.hxx + CallbackStream.hxx + CFunCallbackStream.hxx + CppFunCallbackStream.hxx + Device.hxx + DirectionSpecificStreamParameters.hxx + Exception.hxx + HostApi.hxx + InterfaceCallbackStream.hxx + MemFunCallbackStream.hxx + PortAudioCpp.hxx + SampleDataFormat.hxx + Stream.hxx + StreamParameters.hxx + SystemDeviceIterator.hxx + SystemHostApiIterator.hxx + System.hxx + """) +if env["PLATFORM"] == "win32": + headers.append("AsioDeviceAdapter.hxx") +headers = [File(os.path.join("include", "portaudiocpp", h)) for h in headers] + +Return("sharedLibs", "staticLibs", "headers") diff --git a/portaudio/bindings/cpp/aclocal.m4 b/portaudio/bindings/cpp/aclocal.m4 new file mode 100644 index 0000000..38a7545 --- /dev/null +++ b/portaudio/bindings/cpp/aclocal.m4 @@ -0,0 +1,7336 @@ +# generated automatically by aclocal 1.9.6 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005 Free Software Foundation, Inc. +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- + +# serial 48 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Check if we have a version mismatch between libtool.m4 and ltmain.sh. +# +# Note: This should be in AC_LIBTOOL_SETUP, _after_ $ltmain have been defined. +# We also should do it _before_ AC_LIBTOOL_LANG_C_CONFIG that actually +# calls AC_LIBTOOL_CONFIG and creates libtool. +# +_LT_VERSION_CHECK + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_VERSION_CHECK +# ----------------- +AC_DEFUN([_LT_VERSION_CHECK], +[AC_MSG_CHECKING([for correct ltmain.sh version]) +if test "x$ltmain" = "x" ; then + AC_MSG_RESULT(no) + AC_MSG_ERROR([ + +*** @<:@Gentoo@:>@ sanity check failed! *** +*** \$ltmain is not defined, please check the patch for consistency! *** +]) +fi +gentoo_lt_version="1.5.22" +gentoo_ltmain_version=`sed -n '/^[[ ]]*VERSION=/{s/^[[ ]]*VERSION=//;p;q;}' "$ltmain"` +if test "x$gentoo_lt_version" != "x$gentoo_ltmain_version" ; then + AC_MSG_RESULT(no) + AC_MSG_ERROR([ + +*** @<:@Gentoo@:>@ sanity check failed! *** +*** libtool.m4 and ltmain.sh have a version mismatch! *** +*** (libtool.m4 = $gentoo_lt_version, ltmain.sh = $gentoo_ltmain_version) *** + +Please run: + + libtoolize --copy --force + +if appropriate, please contact the maintainer of this +package (or your distribution) for help. +]) +else + AC_MSG_RESULT(yes) +fi +])# _LT_VERSION_CHECK + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 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 +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # Handle Gentoo/FreeBSD as it was Linux + case $host_vendor in + gentoo) + version_type=linux ;; + *) + version_type=freebsd-$objformat ;; + esac + + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + linux) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + need_lib_prefix=no + need_version=no + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + 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]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # 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 + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # 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. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II 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 can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + 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]].*|aix5*) + 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 + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # 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. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) + +# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.9.6])]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 7 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 8 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +#serial 3 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 12 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.58])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 4 + +AC_DEFUN([AM_MAINTAINER_MODE], +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 3 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 4 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_MKDIR_P +# --------------- +# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. +# +# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories +# created by `make install' are always world readable, even if the +# installer happens to have an overly restrictive umask (e.g. 077). +# This was a mistake. There are at least two reasons why we must not +# use `-m 0755': +# - it causes special bits like SGID to be ignored, +# - it may be too restrictive (some setups expect 775 directories). +# +# Do not use -m 0755 and let people choose whatever they expect by +# setting umask. +# +# We cannot accept any implementation of `mkdir' that recognizes `-p'. +# Some implementations (such as Solaris 8's) are not thread-safe: if a +# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' +# concurrently, both version can detect that a/ is missing, but only +# one can create it and the other will error out. Consequently we +# restrict ourselves to GNU make (using the --version option ensures +# this.) +AC_DEFUN([AM_PROG_MKDIR_P], +[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi +AC_SUBST([mkdir_p])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 3 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 4 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/portaudio/bindings/cpp/bin/Makefile.am b/portaudio/bindings/cpp/bin/Makefile.am new file mode 100644 index 0000000..5f97f94 --- /dev/null +++ b/portaudio/bindings/cpp/bin/Makefile.am @@ -0,0 +1,9 @@ +BINDIR = $(top_srcdir)/example +LIBDIR = $(top_builddir)/lib + +noinst_PROGRAMS = devs sine + +LDADD = $(LIBDIR)/libportaudiocpp.la + +devs_SOURCES = $(BINDIR)/devs.cxx +sine_SOURCES = $(BINDIR)/sine.cxx diff --git a/portaudio/bindings/cpp/bin/Makefile.in b/portaudio/bindings/cpp/bin/Makefile.in new file mode 100644 index 0000000..fa45b04 --- /dev/null +++ b/portaudio/bindings/cpp/bin/Makefile.in @@ -0,0 +1,470 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = devs$(EXEEXT) sine$(EXEEXT) +subdir = bin +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_devs_OBJECTS = devs.$(OBJEXT) +devs_OBJECTS = $(am_devs_OBJECTS) +devs_LDADD = $(LDADD) +devs_DEPENDENCIES = $(LIBDIR)/libportaudiocpp.la +am_sine_OBJECTS = sine.$(OBJEXT) +sine_OBJECTS = $(am_sine_OBJECTS) +sine_LDADD = $(LDADD) +sine_DEPENDENCIES = $(LIBDIR)/libportaudiocpp.la +depcomp = $(SHELL) $(top_srcdir)/../../depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(devs_SOURCES) $(sine_SOURCES) +DIST_SOURCES = $(devs_SOURCES) $(sine_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_INCLUDES = @DEFAULT_INCLUDES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PORTAUDIO_ROOT = @PORTAUDIO_ROOT@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +BINDIR = $(top_srcdir)/example +LIBDIR = $(top_builddir)/lib +LDADD = $(LIBDIR)/libportaudiocpp.la +devs_SOURCES = $(BINDIR)/devs.cxx +sine_SOURCES = $(BINDIR)/sine.cxx +all: all-am + +.SUFFIXES: +.SUFFIXES: .cxx .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bin/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu bin/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +devs$(EXEEXT): $(devs_OBJECTS) $(devs_DEPENDENCIES) + @rm -f devs$(EXEEXT) + $(CXXLINK) $(devs_LDFLAGS) $(devs_OBJECTS) $(devs_LDADD) $(LIBS) +sine$(EXEEXT): $(sine_OBJECTS) $(sine_DEPENDENCIES) + @rm -f sine$(EXEEXT) + $(CXXLINK) $(sine_LDFLAGS) $(sine_OBJECTS) $(sine_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sine.Po@am__quote@ + +.cxx.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cxx.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cxx.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +devs.o: $(BINDIR)/devs.cxx +@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT devs.o -MD -MP -MF "$(DEPDIR)/devs.Tpo" -c -o devs.o `test -f '$(BINDIR)/devs.cxx' || echo '$(srcdir)/'`$(BINDIR)/devs.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/devs.Tpo" "$(DEPDIR)/devs.Po"; else rm -f "$(DEPDIR)/devs.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(BINDIR)/devs.cxx' object='devs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o devs.o `test -f '$(BINDIR)/devs.cxx' || echo '$(srcdir)/'`$(BINDIR)/devs.cxx + +devs.obj: $(BINDIR)/devs.cxx +@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT devs.obj -MD -MP -MF "$(DEPDIR)/devs.Tpo" -c -o devs.obj `if test -f '$(BINDIR)/devs.cxx'; then $(CYGPATH_W) '$(BINDIR)/devs.cxx'; else $(CYGPATH_W) '$(srcdir)/$(BINDIR)/devs.cxx'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/devs.Tpo" "$(DEPDIR)/devs.Po"; else rm -f "$(DEPDIR)/devs.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(BINDIR)/devs.cxx' object='devs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o devs.obj `if test -f '$(BINDIR)/devs.cxx'; then $(CYGPATH_W) '$(BINDIR)/devs.cxx'; else $(CYGPATH_W) '$(srcdir)/$(BINDIR)/devs.cxx'; fi` + +sine.o: $(BINDIR)/sine.cxx +@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sine.o -MD -MP -MF "$(DEPDIR)/sine.Tpo" -c -o sine.o `test -f '$(BINDIR)/sine.cxx' || echo '$(srcdir)/'`$(BINDIR)/sine.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sine.Tpo" "$(DEPDIR)/sine.Po"; else rm -f "$(DEPDIR)/sine.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(BINDIR)/sine.cxx' object='sine.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sine.o `test -f '$(BINDIR)/sine.cxx' || echo '$(srcdir)/'`$(BINDIR)/sine.cxx + +sine.obj: $(BINDIR)/sine.cxx +@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sine.obj -MD -MP -MF "$(DEPDIR)/sine.Tpo" -c -o sine.obj `if test -f '$(BINDIR)/sine.cxx'; then $(CYGPATH_W) '$(BINDIR)/sine.cxx'; else $(CYGPATH_W) '$(srcdir)/$(BINDIR)/sine.cxx'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sine.Tpo" "$(DEPDIR)/sine.Po"; else rm -f "$(DEPDIR)/sine.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(BINDIR)/sine.cxx' object='sine.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sine.obj `if test -f '$(BINDIR)/sine.cxx'; then $(CYGPATH_W) '$(BINDIR)/sine.cxx'; else $(CYGPATH_W) '$(srcdir)/$(BINDIR)/sine.cxx'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/portaudio/bindings/cpp/build/gnu/Makefile.in b/portaudio/bindings/cpp/build/gnu/Makefile.in new file mode 100644 index 0000000..0bc6f28 --- /dev/null +++ b/portaudio/bindings/cpp/build/gnu/Makefile.in @@ -0,0 +1,106 @@ +# +# Makefile template for PortAudioCpp +# Ludwig Schwardt +# 01/10/2003 +# +# Not much to edit here - rather check configure.ac +# + +PREFIX = @prefix@ +CC = @CC@ +CXX = @CXX@ +CFLAGS = @CFLAGS@ @DEFS@ +CXXFLAGS = @CXXFLAGS@ +SHARED_FLAGS = @SHARED_FLAGS@ +LIBS = @LIBS@ +DLL_LIBS = @DLL_LIBS@ +AR = @AR@ +RANLIB = @RANLIB@ +INSTALL = @INSTALL@ + +PACPP_ROOT = @PACPP_ROOT@ +PORTAUDIO = @PORTAUDIO@ +PADLL = @PADLL@ +PACPP_DLL = @PACPP_DLL@ +PALIB = libportaudio.a +PACPP_LIB = libportaudiocpp.a +PACPP_DLLV = $(PACPP_DLL).0.0.12 + +SRCDIR = $(PACPP_ROOT)/source/portaudiocpp +BINDIR = $(PACPP_ROOT)/example +LIBDIR = $(PACPP_ROOT)/lib +DOCDIR = $(PACPP_ROOT)/doc + +OBJS = \ + $(SRCDIR)/BlockingStream.o \ + $(SRCDIR)/CallbackInterface.o \ + $(SRCDIR)/CallbackStream.o \ + $(SRCDIR)/CFunCallbackStream.o \ + $(SRCDIR)/CppFunCallbackStream.o \ + $(SRCDIR)/Device.o \ + $(SRCDIR)/DirectionSpecificStreamParameters.o \ + $(SRCDIR)/Exception.o \ + $(SRCDIR)/HostApi.o \ + $(SRCDIR)/InterfaceCallbackStream.o \ + $(SRCDIR)/MemFunCallbackStream.o \ + $(SRCDIR)/Stream.o \ + $(SRCDIR)/StreamParameters.o \ + $(SRCDIR)/System.o \ + $(SRCDIR)/SystemDeviceIterator.o \ + $(SRCDIR)/SystemHostApiIterator.o + +# Not supported yet +# $(SRCDIR)/AsioDeviceAdapter.o + +EXAMPLES = \ + $(BINDIR)/devs \ + $(BINDIR)/sine + +.PHONY: all clean docs + +all: $(EXAMPLES) $(LIBDIR)/$(PACPP_LIB) $(LIBDIR)/$(PACPP_DLL) + +clean: + rm -rf $(SRCDIR)/*.o $(BINDIR)/*.o $(EXAMPLES) $(LIBDIR) $(DOCDIR)/api_reference + rm -rf autom4te.cache config.status config.log + +docs: + cd $(DOCDIR); doxygen config.doxy.linux + +%.o: %.c + $(CC) -c $(CFLAGS) $< -o $@ + +%.o: %.cxx + $(CXX) -c $(CXXFLAGS) $< -o $@ + + +$(EXAMPLES): $(BINDIR)/%: $(BINDIR)/%.o $(OBJS) + $(CXX) $^ -o $@ $(LIBS) + +$(LIBDIR)/$(PACPP_LIB): $(LIBDIR) $(OBJS) + $(AR) ruv $(LIBDIR)/$(PACPP_LIB) $(OBJS) + $(RANLIB) $(LIBDIR)/$(PACPP_LIB) + +$(LIBDIR)/$(PACPP_DLLV): $(LIBDIR) $(OBJS) + $(CXX) $(SHARED_FLAGS) -o $(LIBDIR)/$(PACPP_DLLV) $(OBJS) $(DLL_LIBS) + +$(LIBDIR)/$(PACPP_DLL): $(LIBDIR) $(OBJS) + $(CXX) $(SHARED_FLAGS) -o $(LIBDIR)/$(PACPP_DLL) $(OBJS) $(DLL_LIBS) + +#install: $(LIBDIR)/$(PACPP_LIB) $(LIBDIR)/$(PACPP_DLLV) +# $(INSTALL) -m 644 $(LIBDIR)/$(PACPP_DLLV) $(PREFIX)/lib/$(PACPP_DLLV) +# $(INSTALL) -m 644 $(LIBDIR)/$(PACPP_LIB) $(PREFIX)/lib/$(PACPP_LIB) +# cd $(PREFIX)/lib && rm -f $(PACPP_DLL) && ln -s $(PACPP_DLLV) $(PACPP_DLL) +# @echo "" +# @echo "------------------------------------------------------------" +# @echo "PortAudioCpp was successfully installed." +# @echo "" +# @echo "On some systems (e.g. Linux) you should run 'ldconfig' now" +# @echo "to make the shared object available. You may also need to" +# @echo "modify your LD_LIBRARY_PATH environment variable to include" +# @echo "the directory $(PREFIX)/lib" +# @echo "------------------------------------------------------------" +# @echo "" + +$(LIBDIR): + mkdir $(LIBDIR) diff --git a/portaudio/bindings/cpp/build/gnu/OUT_OF_DATE b/portaudio/bindings/cpp/build/gnu/OUT_OF_DATE new file mode 100644 index 0000000..e69de29 diff --git a/portaudio/bindings/cpp/build/gnu/aclocal.m4 b/portaudio/bindings/cpp/build/gnu/aclocal.m4 new file mode 100644 index 0000000..c80e0ac --- /dev/null +++ b/portaudio/bindings/cpp/build/gnu/aclocal.m4 @@ -0,0 +1,57 @@ + +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN(PKG_CHECK_MODULES, [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + diff --git a/portaudio/bindings/cpp/build/gnu/config.guess b/portaudio/bindings/cpp/build/gnu/config.guess new file mode 100644 index 0000000..297e5c3 --- /dev/null +++ b/portaudio/bindings/cpp/build/gnu/config.guess @@ -0,0 +1,1308 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. + +timestamp='2001-10-05' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-unknown ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + sparc*) machine=`uname -p`-unknown ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE}" in + i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in + big) echo mips-unknown-linux-gnu && exit 0 ;; + little) echo mipsel-unknown-linux-gnu && exit 0 ;; + esac + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_supported_targets=`cd /; ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + cat >$dummy.c < +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-pc-linux-gnu\n", argv[1]); +# else + printf ("%s-pc-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-pc-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-pc-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[KW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/portaudio/bindings/cpp/build/gnu/config.sub b/portaudio/bindings/cpp/build/gnu/config.sub new file mode 100644 index 0000000..6eea727 --- /dev/null +++ b/portaudio/bindings/cpp/build/gnu/config.sub @@ -0,0 +1,1505 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2003-07-17' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | msp430 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | msp430-* \ + | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/portaudio/bindings/cpp/build/gnu/configure b/portaudio/bindings/cpp/build/gnu/configure new file mode 100644 index 0000000..69070c6 --- /dev/null +++ b/portaudio/bindings/cpp/build/gnu/configure @@ -0,0 +1,4297 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.57 for PortAudioCpp 12. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='PortAudioCpp' +PACKAGE_TARNAME='portaudiocpp' +PACKAGE_VERSION='12' +PACKAGE_STRING='PortAudioCpp 12' +PACKAGE_BUGREPORT='' + +ac_unique_file="../../include/portaudiocpp/PortAudioCpp.hxx" +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX LN_S RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AR PACPP_ROOT PORTAUDIO PADLL PACPP_DLL PACPP_INC SHARED_FLAGS DLL_LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os PKG_CONFIG JACK_CFLAGS JACK_LIBS LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures PortAudioCpp 12 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of PortAudioCpp 12:";; + esac + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-alsa (default=auto) + --with-jack (default=auto) + --with-oss (default=yes) + --with-host_os (no default) + --with-winapi ((wmme/directx/asio) default=wmme) + --with-macapi (asio) default=asio) + --with-asiodir (default=/usr/local/asiosdk2) + --with-dxdir (default=/usr/local/dx7sdk) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd "$ac_popdir" + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +PortAudioCpp configure 12 +generated by GNU Autoconf 2.57 + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by PortAudioCpp $as_me 12, which was +generated by GNU Autoconf 2.57. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +###### Top-level directory of pacpp +###### This makes it easy to shuffle the build directories +###### Also edit AC_CONFIG_SRCDIR above (wouldn't accept this variable)! +PACPP_ROOT="../.." + +###### +###### SET THIS TO PORTAUDIO DIRECTORY +###### +PORTAUDIO="$PACPP_ROOT/../portaudio" + +# Various other variables and flags + +PACPP_INC="$PACPP_ROOT/include" +INCLUDES="-I$PACPP_INC -I$PORTAUDIO -I$PORTAUDIO/pa_common" +CFLAGS="-g -O2 -Wall -ansi -pedantic $INCLUDES" +CXXFLAGS="$CFLAGS" +PALIBDIR="$PORTAUDIO/lib" + +# Checks for programs + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6 +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +# Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_AR="$AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_AR" && ac_cv_path_AR="no" + ;; +esac +fi +AR=$ac_cv_path_AR + +if test -n "$AR"; then + echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if [ $AR = "no" ] ; then + { { echo "$as_me:$LINENO: error: \"Could not find ar - needed to create a library\"" >&5 +echo "$as_me: error: \"Could not find ar - needed to create a library\"" >&2;} + { (exit 1); exit 1; }; }; +fi + +# This must be one of the first tests we do or it will fail... + +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +# Transfer these variables to the Makefile + + + + + + + + + +##################### CHECK FOR INSTALLED PACKAGES ############################ + +# checks for various host APIs and arguments to configure that +# turn them on or off + +echo "$as_me:$LINENO: checking for snd_pcm_open in -lasound" >&5 +echo $ECHO_N "checking for snd_pcm_open in -lasound... $ECHO_C" >&6 +if test "${ac_cv_lib_asound_snd_pcm_open+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lasound $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char snd_pcm_open (); +int +main () +{ +snd_pcm_open (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_asound_snd_pcm_open=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_asound_snd_pcm_open=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_asound_snd_pcm_open" >&5 +echo "${ECHO_T}$ac_cv_lib_asound_snd_pcm_open" >&6 +if test $ac_cv_lib_asound_snd_pcm_open = yes; then + have_alsa=yes +else + have_alsa=no +fi + + +# Determine the host description for the subsequent test. +# PKG_CHECK_MODULES seems to check and set the host variable also, but +# that then requires pkg-config availability which is not standard on +# MinGW systems and can be a pain to install. +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + + + + succeeded=no + + if test -z "$PKG_CONFIG"; then + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG + +if test -n "$PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 +echo "${ECHO_T}$PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + echo "$as_me:$LINENO: checking for jack" >&5 +echo $ECHO_N "checking for jack... $ECHO_C" >&6 + + if $PKG_CONFIG --exists "jack" ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + succeeded=yes + + echo "$as_me:$LINENO: checking JACK_CFLAGS" >&5 +echo $ECHO_N "checking JACK_CFLAGS... $ECHO_C" >&6 + JACK_CFLAGS=`$PKG_CONFIG --cflags "jack"` + echo "$as_me:$LINENO: result: $JACK_CFLAGS" >&5 +echo "${ECHO_T}$JACK_CFLAGS" >&6 + + echo "$as_me:$LINENO: checking JACK_LIBS" >&5 +echo $ECHO_N "checking JACK_LIBS... $ECHO_C" >&6 + JACK_LIBS=`$PKG_CONFIG --libs "jack"` + echo "$as_me:$LINENO: result: $JACK_LIBS" >&5 +echo "${ECHO_T}$JACK_LIBS" >&6 + else + JACK_CFLAGS="" + JACK_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + JACK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "jack"` + + fi + + + + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + have_jack=yes + else + have_jack=no + fi + + + +# Check whether --with-alsa or --without-alsa was given. +if test "${with_alsa+set}" = set; then + withval="$with_alsa" + with_alsa=$withval +else + with_alsa="yes" +fi; + + +# Check whether --with-jack or --without-jack was given. +if test "${with_jack+set}" = set; then + withval="$with_jack" + with_jack=$withval +else + with_jack="yes" +fi; + + +# Check whether --with-oss or --without-oss was given. +if test "${with_oss+set}" = set; then + withval="$with_oss" + with_oss=$withval +else + with_oss="yes" +fi; + + +# Check whether --with-host_os or --without-host_os was given. +if test "${with_host_os+set}" = set; then + withval="$with_host_os" + host_os=$withval +fi; + + +# Check whether --with-winapi or --without-winapi was given. +if test "${with_winapi+set}" = set; then + withval="$with_winapi" + with_winapi=$withval +else + with_winapi="wmme" +fi; + +# Mac API added for ASIO, can have other api's listed + +# Check whether --with-macapi or --without-macapi was given. +if test "${with_macapi+set}" = set; then + withval="$with_macapi" + with_macapi=$withval +else + with_macapi="asio" +fi; + + +# Check whether --with-asiodir or --without-asiodir was given. +if test "${with_asiodir+set}" = set; then + withval="$with_asiodir" + with_asiodir=$withval +else + with_asiodir="/usr/local/asiosdk2" +fi; + + +# Check whether --with-dxdir or --without-dxdir was given. +if test "${with_dxdir+set}" = set; then + withval="$with_dxdir" + with_dxdir=$withval +else + with_dxdir="/usr/local/dx7sdk" +fi; + + +##################### HOST-SPECIFIC LIBRARY SETTINGS ########################## + +case "${host_os}" in + darwin* ) + # Mac OS X configuration + + LIBS="-framework AudioUnit -framework AudioToolbox -framework CoreAudio"; + PADLL="libportaudio.dylib"; + PACPP_DLL="libportaudiocpp.dylib"; + SHARED_FLAGS="-framework AudioUnit -framework AudioToolbox"; + SHARED_FLAGS="$SHARED_FLAGS -framework CoreAudio -dynamiclib"; + if [ $with_macapi = "asio" ] ; then + if [ $with_asiodir ] ; then + ASIODIR="$with_asiodir"; + else + ASIODIR="/usr/local/asiosdk2"; + fi + echo "ASIODIR: $ASIODIR"; + fi + ;; + + mingw* ) + # MingW configuration + + echo "WINAPI: $with_winapi" + if [ $with_winapi = "directx" ] ; then + if [ $with_dxdir ] ; then + DXDIR="$with_dxdir"; + else + DXDIR="/usr/local/dx7sdk"; + fi + echo "DXDIR: $DXDIR" + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm -ldsound -lole32"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm -lm -L./dx7sdk/lib -ldsound -lole32"; + CFLAGS="$CFLAGS -DPA_NO_WMME -DPA_NO_ASIO"; + CXXFLAGS="$CFLAGS" + elif [ $with_winapi = "asio" ] ; then + if [ $with_asiodir ] ; then + ASIODIR="$with_asiodir"; + else + ASIODIR="/usr/local/asiosdk2"; + fi + echo "ASIODIR: $ASIODIR" + + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm -lstdc++ -lole32 -luuid"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid"; + CFLAGS="$CFLAGS -ffast-math -fomit-frame-pointer -DPA_NO_WMME -DPA_NO_DS -DWINDOWS"; + CXXFLAGS="$CFLAGS"; + else # WMME default + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm -lstdc++ -lole32 -luuid"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm"; + CFLAGS="$CFLAGS -DPA_NO_DS -DPA_NO_ASIO"; + CXXFLAGS="$CFLAGS"; + fi + ;; + + cygwin* ) + # Cygwin configuration + + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm"; + ;; + + *) + # Unix OSS configuration + + +echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 +echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_create (); +int +main () +{ +pthread_create (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_create=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread_pthread_create=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6 +if test $ac_cv_lib_pthread_pthread_create = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +else + { { echo "$as_me:$LINENO: error: libpthread not found!" >&5 +echo "$as_me: error: libpthread not found!" >&2;} + { (exit 1); exit 1; }; } +fi + + + LIBS="$LIBS -L$PALIBDIR -lportaudio" + + if [ $have_jack = "yes" ] && [ $with_jack != "no" ] ; then + LIBS="$LIBS $JACK_LIBS" + CFLAGS="$CFLAGS $JACK_CFLAGS" + cat >>confdefs.h <<\_ACEOF +#define PA_USE_JACK 1 +_ACEOF + + fi + + if [ $have_alsa = "yes" ] && [ $with_alsa != "no" ] ; then + LIBS="$LIBS -lasound" + cat >>confdefs.h <<\_ACEOF +#define PA_USE_ALSA 1 +_ACEOF + + fi + + if [ $with_oss != "no" ] ; then + cat >>confdefs.h <<\_ACEOF +#define PA_USE_OSS 1 +_ACEOF + + fi + LIBS="$LIBS -lm -lpthread"; + PADLL="libportaudio.so"; + PACPP_DLL="libportaudiocpp.so"; + SHARED_FLAGS="-shared"; +esac + + ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by PortAudioCpp $as_me 12, which was +generated by GNU Autoconf 2.57. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +PortAudioCpp config.status 12 +configured by $0, generated by GNU Autoconf 2.57, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@LN_S@,$LN_S,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@AR@,$AR,;t t +s,@PACPP_ROOT@,$PACPP_ROOT,;t t +s,@PORTAUDIO@,$PORTAUDIO,;t t +s,@PADLL@,$PADLL,;t t +s,@PACPP_DLL@,$PACPP_DLL,;t t +s,@PACPP_INC@,$PACPP_INC,;t t +s,@SHARED_FLAGS@,$SHARED_FLAGS,;t t +s,@DLL_LIBS@,$DLL_LIBS,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@PKG_CONFIG@,$PKG_CONFIG,;t t +s,@JACK_CFLAGS@,$JACK_CFLAGS,;t t +s,@JACK_LIBS@,$JACK_LIBS,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/portaudio/bindings/cpp/build/gnu/configure.ac b/portaudio/bindings/cpp/build/gnu/configure.ac new file mode 100644 index 0000000..5457c53 --- /dev/null +++ b/portaudio/bindings/cpp/build/gnu/configure.ac @@ -0,0 +1,214 @@ +# +# PortAudioCpp V19 autoconf input file +# Shamelessly ripped from the PortAudio one by Dominic Mazzoni +# Ludwig Schwardt +# + +# Require autoconf >= 2.13 +AC_PREREQ(2.13) + +AC_INIT([PortAudioCpp], [12]) +AC_CONFIG_SRCDIR([../../include/portaudiocpp/PortAudioCpp.hxx]) + +###### Top-level directory of pacpp +###### This makes it easy to shuffle the build directories +###### Also edit AC_CONFIG_SRCDIR above (wouldn't accept this variable)! +PACPP_ROOT="../.." + +###### +###### SET THIS TO PORTAUDIO DIRECTORY +###### +PORTAUDIO="$PACPP_ROOT/../portaudio" + +# Various other variables and flags + +PACPP_INC="$PACPP_ROOT/include" +INCLUDES="-I$PACPP_INC -I$PORTAUDIO -I$PORTAUDIO/pa_common" +CFLAGS="-g -O2 -Wall -ansi -pedantic $INCLUDES" +CXXFLAGS="$CFLAGS" +PALIBDIR="$PORTAUDIO/lib" + +# Checks for programs + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_LN_S +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_PATH_PROG(AR, ar, no) +if [[ $AR = "no" ]] ; then + AC_MSG_ERROR("Could not find ar - needed to create a library"); +fi + +# This must be one of the first tests we do or it will fail... +AC_C_BIGENDIAN + +# Transfer these variables to the Makefile +AC_SUBST(PACPP_ROOT) +AC_SUBST(PORTAUDIO) +AC_SUBST(PADLL) +AC_SUBST(PACPP_DLL) +AC_SUBST(PACPP_INC) +AC_SUBST(SHARED_FLAGS) +AC_SUBST(DLL_LIBS) +AC_SUBST(CXXFLAGS) + +##################### CHECK FOR INSTALLED PACKAGES ############################ + +# checks for various host APIs and arguments to configure that +# turn them on or off + +AC_CHECK_LIB(asound, snd_pcm_open, have_alsa=yes, have_alsa=no) + +# Determine the host description for the subsequent test. +# PKG_CHECK_MODULES seems to check and set the host variable also, but +# that then requires pkg-config availability which is not standard on +# MinGW systems and can be a pain to install. +AC_CANONICAL_HOST + +PKG_CHECK_MODULES(JACK, jack, have_jack=yes, have_jack=no) + +AC_ARG_WITH(alsa, + [ --with-alsa (default=auto)], + with_alsa=$withval, with_alsa="yes") + +AC_ARG_WITH(jack, + [ --with-jack (default=auto)], + with_jack=$withval, with_jack="yes") + +AC_ARG_WITH(oss, + [ --with-oss (default=yes)], + with_oss=$withval, with_oss="yes") + +AC_ARG_WITH(host_os, + [ --with-host_os (no default)], + host_os=$withval) + +AC_ARG_WITH(winapi, + [ --with-winapi ((wmme/directx/asio) default=wmme)], + with_winapi=$withval, with_winapi="wmme") + +# Mac API added for ASIO, can have other api's listed +AC_ARG_WITH(macapi, + [ --with-macapi (asio) default=asio)], + with_macapi=$withval, with_macapi="asio") + +AC_ARG_WITH(asiodir, + [ --with-asiodir (default=/usr/local/asiosdk2)], + with_asiodir=$withval, with_asiodir="/usr/local/asiosdk2") + +AC_ARG_WITH(dxdir, + [ --with-dxdir (default=/usr/local/dx7sdk)], + with_dxdir=$withval, with_dxdir="/usr/local/dx7sdk") + + +##################### HOST-SPECIFIC LIBRARY SETTINGS ########################## + +case "${host_os}" in + darwin* ) + # Mac OS X configuration + + LIBS="-framework AudioUnit -framework AudioToolbox -framework CoreAudio"; + PADLL="libportaudio.dylib"; + PACPP_DLL="libportaudiocpp.dylib"; + SHARED_FLAGS="-framework AudioUnit -framework AudioToolbox"; + SHARED_FLAGS="$SHARED_FLAGS -framework CoreAudio -dynamiclib"; + if [[ $with_macapi = "asio" ]] ; then + if [[ $with_asiodir ]] ; then + ASIODIR="$with_asiodir"; + else + ASIODIR="/usr/local/asiosdk2"; + fi + echo "ASIODIR: $ASIODIR"; + fi + ;; + + mingw* ) + # MingW configuration + + echo "WINAPI: $with_winapi" + if [[ $with_winapi = "directx" ]] ; then + if [[ $with_dxdir ]] ; then + DXDIR="$with_dxdir"; + else + DXDIR="/usr/local/dx7sdk"; + fi + echo "DXDIR: $DXDIR" + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm -ldsound -lole32"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm -lm -L./dx7sdk/lib -ldsound -lole32"; + CFLAGS="$CFLAGS -DPA_NO_WMME -DPA_NO_ASIO"; + CXXFLAGS="$CFLAGS" + elif [[ $with_winapi = "asio" ]] ; then + if [[ $with_asiodir ]] ; then + ASIODIR="$with_asiodir"; + else + ASIODIR="/usr/local/asiosdk2"; + fi + echo "ASIODIR: $ASIODIR" + + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm -lstdc++ -lole32 -luuid"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid"; + CFLAGS="$CFLAGS -ffast-math -fomit-frame-pointer -DPA_NO_WMME -DPA_NO_DS -DWINDOWS"; + CXXFLAGS="$CFLAGS"; + else # WMME default + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm -lstdc++ -lole32 -luuid"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm"; + CFLAGS="$CFLAGS -DPA_NO_DS -DPA_NO_ASIO"; + CXXFLAGS="$CFLAGS"; + fi + ;; + + cygwin* ) + # Cygwin configuration + + LIBS="-L$PALIBDIR -lportaudio" + LIBS="$LIBS -lwinmm -lm"; + PADLL="portaudio.dll"; + PACPP_DLL="portaudiocpp.dll"; + SHARED_FLAGS="-shared -mthreads"; + DLL_LIBS="-lwinmm"; + ;; + + *) + # Unix OSS configuration + + AC_CHECK_LIB(pthread, pthread_create, + , + AC_MSG_ERROR([libpthread not found!])) + + LIBS="$LIBS -L$PALIBDIR -lportaudio" + + if [[ $have_jack = "yes" ] && [ $with_jack != "no" ]] ; then + LIBS="$LIBS $JACK_LIBS" + CFLAGS="$CFLAGS $JACK_CFLAGS" + AC_DEFINE(PA_USE_JACK) + fi + + if [[ $have_alsa = "yes" ] && [ $with_alsa != "no" ]] ; then + LIBS="$LIBS -lasound" + AC_DEFINE(PA_USE_ALSA) + fi + + if [[ $with_oss != "no" ]] ; then + AC_DEFINE(PA_USE_OSS) + fi + LIBS="$LIBS -lm -lpthread"; + PADLL="libportaudio.so"; + PACPP_DLL="libportaudiocpp.so"; + SHARED_FLAGS="-shared"; +esac + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/portaudio/bindings/cpp/build/gnu/install-sh b/portaudio/bindings/cpp/build/gnu/install-sh new file mode 100644 index 0000000..e9de238 --- /dev/null +++ b/portaudio/bindings/cpp/build/gnu/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/portaudio/bindings/cpp/build/vc6/devs_example.dsp b/portaudio/bindings/cpp/build/vc6/devs_example.dsp new file mode 100644 index 0000000..af26847 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc6/devs_example.dsp @@ -0,0 +1,248 @@ +# Microsoft Developer Studio Project File - Name="devs_example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=devs_example - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "devs_example.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "devs_example.mak" CFG="devs_example - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "devs_example - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "devs_example - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "devs_example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /O2 /I "../../include/" /I "../../../../include/" /I "../../../../src/common/" /I "../../../../../asiosdk2/common/" /I "../../../../../asiosdk2/host/" /I "../../../../../asiosdk2/host/pc/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 portaudiocpp-vc6-r.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../../bin/devs_example.exe" /libpath:"../../lib" + +!ELSEIF "$(CFG)" == "devs_example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include/" /I "../../../../include/" /I "../../../../src/common/" /I "../../../../../asiosdk2/common/" /I "../../../../../asiosdk2/host/" /I "../../../../../asiosdk2/host/pc/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 portaudiocpp-vc6-d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../bin/devs_example.exe" /pdbtype:sept /libpath:"../../lib" + +!ENDIF + +# Begin Target + +# Name "devs_example - Win32 Release" +# Name "devs_example - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\..\pa_asio\iasiothiscallresolver.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_allocation.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\pa_asio\pa_asio.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_converters.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_cpuload.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_dither.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_front.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_process.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_skeleton.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_stream.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_trace.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\dsound\pa_win_ds.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\dsound\pa_win_ds_dynlink.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_win_hostapis.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_win_util.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\wmme\pa_win_wmme.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_x86_plain_converters.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\..\pa_asio\iasiothiscallresolver.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_allocation.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_converters.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_cpuload.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_dither.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_endianness.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_hostapi.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_process.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_stream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_trace.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_types.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_util.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\dsound\pa_win_ds_dynlink.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_x86_plain_converters.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Example Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\example\devs.cxx +# End Source File +# End Group +# Begin Group "ASIO 2 SDK" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\..\asiosdk2\common\asio.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\..\asiosdk2\host\asiodrivers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\..\asiosdk2\host\pc\asiolist.cpp +# End Source File +# End Group +# End Target +# End Project diff --git a/portaudio/bindings/cpp/build/vc6/devs_example.dsw b/portaudio/bindings/cpp/build/vc6/devs_example.dsw new file mode 100644 index 0000000..480c4d5 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc6/devs_example.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "devs_example"=".\devs_example.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name static_library + End Project Dependency +}}} + +############################################################################### + +Project: "static_library"=".\static_library.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/portaudio/bindings/cpp/build/vc6/sine_example.dsp b/portaudio/bindings/cpp/build/vc6/sine_example.dsp new file mode 100644 index 0000000..2539cbd --- /dev/null +++ b/portaudio/bindings/cpp/build/vc6/sine_example.dsp @@ -0,0 +1,252 @@ +# Microsoft Developer Studio Project File - Name="sine_example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=sine_example - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "sine_example.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "sine_example.mak" CFG="sine_example - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "sine_example - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "sine_example - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "sine_example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /O2 /I "../../include/" /I "../../../../include/" /I "../../../../src/common/" /I "../../../../../asiosdk2/common/" /I "../../../../../asiosdk2/host/" /I "../../../../../asiosdk2/host/pc/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 portaudiocpp-vc6-r.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../../bin/sine_example.exe" /libpath:"../../lib" + +!ELSEIF "$(CFG)" == "sine_example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include/" /I "../../../../include/" /I "../../../../src/common/" /I "../../../../../asiosdk2/common/" /I "../../../../../asiosdk2/host/" /I "../../../../../asiosdk2/host/pc/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 portaudiocpp-vc6-d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../bin/sine_example.exe" /pdbtype:sept /libpath:"../../lib" + +!ENDIF + +# Begin Target + +# Name "sine_example - Win32 Release" +# Name "sine_example - Win32 Debug" +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\..\pa_asio\iasiothiscallresolver.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_allocation.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_converters.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_cpuload.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_dither.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_endianness.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_hostapi.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_process.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_stream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_trace.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_types.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_util.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\dsound\pa_win_ds_dynlink.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_x86_plain_converters.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Example Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\example\sine.cxx +# End Source File +# End Group +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\..\pa_asio\iasiothiscallresolver.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_allocation.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\pa_asio\pa_asio.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_converters.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_cpuload.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_dither.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_front.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_process.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_skeleton.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_stream.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\common\pa_trace.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\dsound\pa_win_ds.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\dsound\pa_win_ds_dynlink.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_win_hostapis.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_win_util.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\wasapi\pa_win_wasapi.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\hostapi\wmme\pa_win_wmme.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\src\os\win\pa_x86_plain_converters.c +# End Source File +# End Group +# Begin Group "ASIO 2 SDK" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\..\asiosdk2\common\asio.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\..\asiosdk2\host\asiodrivers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\..\asiosdk2\host\pc\asiolist.cpp +# End Source File +# End Group +# End Target +# End Project diff --git a/portaudio/bindings/cpp/build/vc6/sine_example.dsw b/portaudio/bindings/cpp/build/vc6/sine_example.dsw new file mode 100644 index 0000000..04c4714 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc6/sine_example.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "sine_example"=".\sine_example.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name static_library + End Project Dependency +}}} + +############################################################################### + +Project: "static_library"=".\static_library.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/portaudio/bindings/cpp/build/vc6/static_library.dsp b/portaudio/bindings/cpp/build/vc6/static_library.dsp new file mode 100644 index 0000000..d33ba9f --- /dev/null +++ b/portaudio/bindings/cpp/build/vc6/static_library.dsp @@ -0,0 +1,395 @@ +# Microsoft Developer Studio Project File - Name="static_library" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=static_library - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "static_library.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "static_library.mak" CFG="static_library - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "static_library - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "static_library - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "static_library - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /O2 /I "../../include/" /I "../../../../include/" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"../../lib/portaudiocpp-vc6-r.lib" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include/" /I "../../../../include/" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"../../lib/portaudiocpp-vc6-d.lib" + +!ENDIF + +# Begin Target + +# Name "static_library - Win32 Release" +# Name "static_library - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\AsioDeviceAdapter.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\BlockingStream.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\CallbackInterface.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\CallbackStream.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\CFunCallbackStream.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\CppFunCallbackStream.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\Device.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\DirectionSpecificStreamParameters.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\Exception.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\HostApi.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\InterfaceCallbackStream.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\MemFunCallbackStream.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\Stream.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\StreamParameters.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\System.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\SystemDeviceIterator.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\source\portaudiocpp\SystemHostApiIterator.cxx + +!IF "$(CFG)" == "static_library - Win32 Release" + +!ELSEIF "$(CFG)" == "static_library - Win32 Debug" + +# SUBTRACT CPP /YX + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\AsioDeviceAdapter.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\AutoSystem.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\BlockingStream.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\CallbackInterface.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\CallbackStream.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\CFunCallbackStream.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\CppFunCallbackStream.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\Device.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\DirectionSpecificStreamParameters.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\Exception.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\HostApi.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\InterfaceCallbackStream.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\MemFunCallbackStream.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\PortAudioCpp.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\SampleDataFormat.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\Stream.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\StreamParameters.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\System.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\SystemDeviceIterator.hxx +# End Source File +# Begin Source File + +SOURCE=..\..\include\portaudiocpp\SystemHostApiIterator.hxx +# End Source File +# End Group +# End Target +# End Project diff --git a/portaudio/bindings/cpp/build/vc6/static_library.dsw b/portaudio/bindings/cpp/build/vc6/static_library.dsw new file mode 100644 index 0000000..cb9d090 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc6/static_library.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "static_library"=".\static_library.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/portaudio/bindings/cpp/build/vc7/OUT_OF_DATE b/portaudio/bindings/cpp/build/vc7/OUT_OF_DATE new file mode 100644 index 0000000..e69de29 diff --git a/portaudio/bindings/cpp/build/vc7_1/devs_example.sln b/portaudio/bindings/cpp/build/vc7_1/devs_example.sln new file mode 100644 index 0000000..c443bce --- /dev/null +++ b/portaudio/bindings/cpp/build/vc7_1/devs_example.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "devs_example", "devs_example.vcproj", "{1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}" + ProjectSection(ProjectDependencies) = postProject + {D18EA0C9-8C65-441D-884C-55EB43A84F2A} = {D18EA0C9-8C65-441D-884C-55EB43A84F2A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "static_library", "static_library.vcproj", "{D18EA0C9-8C65-441D-884C-55EB43A84F2A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Debug.ActiveCfg = Debug|Win32 + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Debug.Build.0 = Debug|Win32 + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Release.ActiveCfg = Release|Win32 + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Release.Build.0 = Release|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Debug.ActiveCfg = Debug|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Debug.Build.0 = Debug|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Release.ActiveCfg = Release|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/portaudio/bindings/cpp/build/vc7_1/devs_example.vcproj b/portaudio/bindings/cpp/build/vc7_1/devs_example.vcproj new file mode 100644 index 0000000..fc065f8 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc7_1/devs_example.vcproj @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/portaudio/bindings/cpp/build/vc7_1/sine_example.sln b/portaudio/bindings/cpp/build/vc7_1/sine_example.sln new file mode 100644 index 0000000..7be7c58 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc7_1/sine_example.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sine_example", "sine_example.vcproj", "{1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}" + ProjectSection(ProjectDependencies) = postProject + {D18EA0C9-8C65-441D-884C-55EB43A84F2A} = {D18EA0C9-8C65-441D-884C-55EB43A84F2A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "static_library", "static_library.vcproj", "{D18EA0C9-8C65-441D-884C-55EB43A84F2A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Debug.ActiveCfg = Debug|Win32 + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Debug.Build.0 = Debug|Win32 + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Release.ActiveCfg = Release|Win32 + {1B9A038D-80A3-4DBD-9F0D-AF10B49B863A}.Release.Build.0 = Release|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Debug.ActiveCfg = Debug|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Debug.Build.0 = Debug|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Release.ActiveCfg = Release|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/portaudio/bindings/cpp/build/vc7_1/sine_example.vcproj b/portaudio/bindings/cpp/build/vc7_1/sine_example.vcproj new file mode 100644 index 0000000..b1c7b62 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc7_1/sine_example.vcproj @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/portaudio/bindings/cpp/build/vc7_1/static_library.sln b/portaudio/bindings/cpp/build/vc7_1/static_library.sln new file mode 100644 index 0000000..36f2ac1 --- /dev/null +++ b/portaudio/bindings/cpp/build/vc7_1/static_library.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "static_library", "static_library.vcproj", "{D18EA0C9-8C65-441D-884C-55EB43A84F2A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Debug.ActiveCfg = Debug|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Debug.Build.0 = Debug|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Release.ActiveCfg = Release|Win32 + {D18EA0C9-8C65-441D-884C-55EB43A84F2A}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/portaudio/bindings/cpp/build/vc7_1/static_library.vcproj b/portaudio/bindings/cpp/build/vc7_1/static_library.vcproj new file mode 100644 index 0000000..d67324e --- /dev/null +++ b/portaudio/bindings/cpp/build/vc7_1/static_library.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/portaudio/bindings/cpp/configure b/portaudio/bindings/cpp/configure new file mode 100644 index 0000000..608a95d --- /dev/null +++ b/portaudio/bindings/cpp/configure @@ -0,0 +1,21505 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.60 for PortAudioCpp 12. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +echo=${ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +tagnames=${tagnames+${tagnames},}CXX + +tagnames=${tagnames+${tagnames},}F77 + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='PortAudioCpp' +PACKAGE_TARNAME='portaudiocpp' +PACKAGE_VERSION='12' +PACKAGE_STRING='PortAudioCpp 12' +PACKAGE_BUGREPORT='' + +ac_unique_file="include/portaudiocpp/PortAudioCpp.hxx" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +CYGPATH_W +PACKAGE +VERSION +ACLOCAL +AUTOCONF +AUTOMAKE +AUTOHEADER +MAKEINFO +install_sh +STRIP +INSTALL_STRIP_PROGRAM +mkdir_p +AWK +SET_MAKE +am__leading_dot +AMTAR +am__tar +am__untar +MAINTAINER_MODE_TRUE +MAINTAINER_MODE_FALSE +MAINT +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +DEPDIR +am__include +am__quote +AMDEP_TRUE +AMDEP_FALSE +AMDEPBACKSLASH +CCDEPMODE +am__fastdepCC_TRUE +am__fastdepCC_FALSE +CXX +CXXFLAGS +ac_ct_CXX +CXXDEPMODE +am__fastdepCXX_TRUE +am__fastdepCXX_FALSE +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +GREP +EGREP +LN_S +ECHO +AR +RANLIB +DLLTOOL +AS +OBJDUMP +CPP +CXXCPP +F77 +FFLAGS +ac_ct_F77 +LIBTOOL +DEFAULT_INCLUDES +PORTAUDIO_ROOT +LT_VERSION_INFO +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +CPPFLAGS +CXX +CXXFLAGS +CCC +CPP +CXXCPP +F77 +FFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures PortAudioCpp 12 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/portaudiocpp] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of PortAudioCpp 12:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-tags[=TAGS] include additional configurations [automatic] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + CXXCPP C++ preprocessor + F77 Fortran 77 compiler command + FFLAGS Fortran 77 compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +PortAudioCpp configure 12 +generated by GNU Autoconf 2.60 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by PortAudioCpp $as_me 12, which was +generated by GNU Autoconf 2.60. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +am__api_version="1.9" +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm -f conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } +set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + SET_MAKE= +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='portaudiocpp' + VERSION='12' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + +{ echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5 +echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6; } + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + +###### Top-level directory of pacpp +###### This makes it easy to shuffle the build directories +###### Also edit AC_CONFIG_SRCDIR above (wouldn't accept this variable)! +PACPP_ROOT="\$(top_srcdir)" +PORTAUDIO_ROOT="../.." + +# Various other variables and flags +DEFAULT_INCLUDES="-I$PACPP_ROOT/include -I$PACPP_ROOT/$PORTAUDIO_ROOT/include" +CFLAGS=${CFLAGS-"-g -O2 -Wall -ansi -pedantic"} +CXXFLAGS=${CXXFLAGS-"${CFLAGS}"} + +LT_VERSION_INFO="0:12:0" + +# Checks for programs + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +{ echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CC" am_compiler_list= + +{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + + +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + +# Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 +echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; } +if test "${lt_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done + +fi + +SED=$lt_cv_path_SED +{ echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6; } + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + +{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; } +if test "${lt_cv_ld_reload_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6; } +NM="$lt_cv_path_NM" + +{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6; } +fi + +{ echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 +echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; } +if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump'. + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | kfreebsd*-gnu | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 4939 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 +echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; } +if test "${lt_cv_cc_needs_belf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + lt_cv_cc_needs_belf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + lt_cv_cc_needs_belf=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-cygwin* | *-*-mingw* | *-*-pw32*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_DLLTOOL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { echo "$as_me:$LINENO: result: $DLLTOOL" >&5 +echo "${ECHO_T}$DLLTOOL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5 +echo "${ECHO_T}$ac_ct_DLLTOOL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AS="${ac_tool_prefix}as" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { echo "$as_me:$LINENO: result: $AS" >&5 +echo "${ECHO_T}$AS" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AS="as" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { echo "$as_me:$LINENO: result: $ac_ct_AS" >&5 +echo "${ECHO_T}$ac_ct_AS" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_OBJDUMP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { echo "$as_me:$LINENO: result: $OBJDUMP" >&5 +echo "${ECHO_T}$OBJDUMP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 +echo "${ECHO_T}$ac_ct_OBJDUMP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; + +esac + +need_locks="$enable_libtool_lock" + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +fi + + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$F77"; then + ac_cv_prog_F77="$F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_F77="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +F77=$ac_cv_prog_F77 +if test -n "$F77"; then + { echo "$as_me:$LINENO: result: $F77" >&5 +echo "${ECHO_T}$F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$F77" && break + done +fi +if test -z "$F77"; then + ac_ct_F77=$F77 + for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_F77"; then + ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_F77="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_F77=$ac_cv_prog_ac_ct_F77 +if test -n "$ac_ct_F77"; then + { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 +echo "${ECHO_T}$ac_ct_F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_F77" && break +done + + if test "x$ac_ct_F77" = x; then + F77="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + F77=$ac_ct_F77 + fi +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +rm -f a.out + +# If we don't use `.F' as extension, the preprocessor is not run on the +# input file. (Note that this only needs to work for GNU compilers.) +ac_save_ext=$ac_ext +ac_ext=F +{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; } +if test "${ac_cv_f77_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF + program main +#ifndef __GNUC__ + choke me +#endif + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_f77_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; } +ac_ext=$ac_save_ext +ac_test_FFLAGS=${FFLAGS+set} +ac_save_FFLAGS=$FFLAGS +FFLAGS= +{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 +echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_f77_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + FFLAGS=-g +cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_f77_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_prog_f77_g=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 +echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; } +if test "$ac_test_FFLAGS" = set; then + FFLAGS=$ac_save_FFLAGS +elif test $ac_cv_prog_f77_g = yes; then + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-g -O2" + else + FFLAGS="-g" + fi +else + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-O2" + else + FFLAGS= + fi +fi + +G77=`test $ac_compiler_gnu = yes && echo yes` +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! + +# find the maximum length of command line arguments +{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 +echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } +if test "${lt_cv_sys_max_cmd_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 +echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; } +else + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } +fi + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } +else + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${lt_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 +echo "${ECHO_T}$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 +echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { echo "$as_me:$LINENO: checking for file" >&5 +echo $ECHO_N "checking for file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +enable_dlopen=no +enable_win32_dll=yes + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + +test -z "$pic_mode" && pic_mode=default + +# Check if we have a version mismatch between libtool.m4 and ltmain.sh. +# +# Note: This should be in AC_LIBTOOL_SETUP, _after_ $ltmain have been defined. +# We also should do it _before_ AC_LIBTOOL_LANG_C_CONFIG that actually +# calls AC_LIBTOOL_CONFIG and creates libtool. +# +{ echo "$as_me:$LINENO: checking for correct ltmain.sh version" >&5 +echo $ECHO_N "checking for correct ltmain.sh version... $ECHO_C" >&6; } +if test "x$ltmain" = "x" ; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: + +*** [Gentoo] sanity check failed! *** +*** \$ltmain is not defined, please check the patch for consistency! *** +" >&5 +echo "$as_me: error: + +*** [Gentoo] sanity check failed! *** +*** \$ltmain is not defined, please check the patch for consistency! *** +" >&2;} + { (exit 1); exit 1; }; } +fi +gentoo_lt_version="1.5.22" +gentoo_ltmain_version=`sed -n '/^[ ]*VERSION=/{s/^[ ]*VERSION=//;p;q;}' "$ltmain"` +if test "x$gentoo_lt_version" != "x$gentoo_ltmain_version" ; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: + +*** [Gentoo] sanity check failed! *** +*** libtool.m4 and ltmain.sh have a version mismatch! *** +*** (libtool.m4 = $gentoo_lt_version, ltmain.sh = $gentoo_ltmain_version) *** + +Please run: + + libtoolize --copy --force + +if appropriate, please contact the maintainer of this +package (or your distribution) for help. +" >&5 +echo "$as_me: error: + +*** [Gentoo] sanity check failed! *** +*** libtool.m4 and ltmain.sh have a version mismatch! *** +*** (libtool.m4 = $gentoo_lt_version, ltmain.sh = $gentoo_ltmain_version) *** + +Please run: + + libtoolize --copy --force + +if appropriate, please contact the maintainer of this +package (or your distribution) for help. +" >&2;} + { (exit 1); exit 1; }; } +else + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +fi + + +# Use C for the default configuration in the libtool script +tagname= +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7708: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7712: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic='-qnocommon' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7976: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7980: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } + +if test x"$lt_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works=yes + fi + else + lt_prog_compiler_static_works=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } + +if test x"$lt_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:8080: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:8084: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag= + enable_shared_with_static_runtimes=no + archive_cmds= + archive_expsym_cmds= + old_archive_From_new_cmds= + old_archive_from_expsyms_cmds= + export_dynamic_flag_spec= + whole_archive_flag_spec= + thread_safe_flag_spec= + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + link_all_deplibs=unknown + hardcode_automatic=no + module_cmds= + module_expsym_cmds= + always_export_symbols=no + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # 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 + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # 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. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II 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 can't use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix3*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + 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 + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4* | aix5*) + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + 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].*|aix5*) + 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 + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + 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]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # 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=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + 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 + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # 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 "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + 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_libdir_flag_spec_ld='+b $libdir' + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # 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*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld='-rpath $libdir' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + hardcode_direct=yes + hardcode_shlibpath_var=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +echo "${ECHO_T}$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 +echo "${ECHO_T}$archive_cmds_need_lc" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # Handle Gentoo/FreeBSD as it was Linux + case $host_vendor in + gentoo) + version_type=linux ;; + *) + version_type=freebsd-$objformat ;; + esac + + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + linux) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + need_lib_prefix=no + need_version=no + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var" || \ + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action" >&5 +echo "${ECHO_T}$hardcode_action" >&6; } + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + ;; + *) + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + ;; + esac +fi + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + { echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case declares shl_load. + For example, HP-UX 11i declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + { echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define dlopen to an innocuous variant, in case declares dlopen. + For example, HP-UX 11i declares gettimeofday. */ +#define dlopen innocuous_dlopen + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef dlopen + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_dlopen || defined __stub___dlopen +choke me +#endif + +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# Report which library types will actually be built +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler \ + CC \ + LD \ + lt_prog_compiler_wl \ + lt_prog_compiler_pic \ + lt_prog_compiler_static \ + lt_prog_compiler_no_builtin_flag \ + export_dynamic_flag_spec \ + thread_safe_flag_spec \ + whole_archive_flag_spec \ + enable_shared_with_static_runtimes \ + old_archive_cmds \ + old_archive_from_new_cmds \ + predep_objects \ + postdep_objects \ + predeps \ + postdeps \ + compiler_lib_search_path \ + archive_cmds \ + archive_expsym_cmds \ + postinstall_cmds \ + postuninstall_cmds \ + old_archive_from_expsyms_cmds \ + allow_undefined_flag \ + no_undefined_flag \ + export_symbols_cmds \ + hardcode_libdir_flag_spec \ + hardcode_libdir_flag_spec_ld \ + hardcode_libdir_separator \ + hardcode_automatic \ + module_cmds \ + module_expsym_cmds \ + lt_cv_prog_compiler_c_o \ + exclude_expsyms \ + include_expsyms; do + + case $var in + old_archive_cmds | \ + old_archive_from_new_cmds | \ + archive_cmds | \ + archive_expsym_cmds | \ + module_cmds | \ + module_expsym_cmds | \ + old_archive_from_expsyms_cmds | \ + export_symbols_cmds | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + { echo "$as_me:$LINENO: creating $ofile" >&5 +echo "$as_me: creating $ofile" >&6;} + + cat <<__EOF__ >> "$cfgfile" +#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to yes if using DIR/libNAME${shared_ext} 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 + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + +# Check whether --with-tags was given. +if test "${with_tags+set}" = set; then + withval=$with_tags; tagnames="$withval" +fi + + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} + else + { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 +echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in + "") ;; + *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 +echo "$as_me: error: invalid tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 +echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} + { (exit 1); exit 1; }; } + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +compiler_CXX=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' +else + lt_prog_compiler_no_builtin_flag_CXX= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } +ld_shlibs_CXX=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix4* | aix5*) + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + 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].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_CXX=yes + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_CXX=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + ld_shlibs_CXX=no + ;; + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + gnu*) + ;; + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_CXX='+b $libdir' + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + interix3*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + openbsd*) + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; +esac +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +GCC_CXX="$GXX" +LD_CXX="$LD" + + +cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$rm -f confest.$objext + +# PORTME: override above test on systems where it is broken +case $host_os in +interix3*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +solaris*) + case $cc_basename in + CC*) + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + postdeps_CXX='-lCstd -lCrun' + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + +lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_CXX='-qnocommon' + lt_prog_compiler_wl_CXX='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:13037: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:13041: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_CXX=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_CXX=yes + fi + else + lt_prog_compiler_static_works_CXX=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:13141: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:13145: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_CXX=no + else + archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # Handle Gentoo/FreeBSD as it was Linux + case $host_vendor in + gentoo) + version_type=linux ;; + *) + version_type=freebsd-$objformat ;; + esac + + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + linux) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + need_lib_prefix=no + need_version=no + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || \ + test -n "$runpath_var_CXX" || \ + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 +echo "${ECHO_T}$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_CXX \ + CC_CXX \ + LD_CXX \ + lt_prog_compiler_wl_CXX \ + lt_prog_compiler_pic_CXX \ + lt_prog_compiler_static_CXX \ + lt_prog_compiler_no_builtin_flag_CXX \ + export_dynamic_flag_spec_CXX \ + thread_safe_flag_spec_CXX \ + whole_archive_flag_spec_CXX \ + enable_shared_with_static_runtimes_CXX \ + old_archive_cmds_CXX \ + old_archive_from_new_cmds_CXX \ + predep_objects_CXX \ + postdep_objects_CXX \ + predeps_CXX \ + postdeps_CXX \ + compiler_lib_search_path_CXX \ + archive_cmds_CXX \ + archive_expsym_cmds_CXX \ + postinstall_cmds_CXX \ + postuninstall_cmds_CXX \ + old_archive_from_expsyms_cmds_CXX \ + allow_undefined_flag_CXX \ + no_undefined_flag_CXX \ + export_symbols_cmds_CXX \ + hardcode_libdir_flag_spec_CXX \ + hardcode_libdir_flag_spec_ld_CXX \ + hardcode_libdir_separator_CXX \ + hardcode_automatic_CXX \ + module_cmds_CXX \ + module_expsym_cmds_CXX \ + lt_cv_prog_compiler_c_o_CXX \ + exclude_expsyms_CXX \ + include_expsyms_CXX; do + + case $var in + old_archive_cmds_CXX | \ + old_archive_from_new_cmds_CXX | \ + archive_cmds_CXX | \ + archive_expsym_cmds_CXX | \ + module_cmds_CXX | \ + module_expsym_cmds_CXX | \ + old_archive_from_expsyms_cmds_CXX | \ + export_symbols_cmds_CXX | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_CXX + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_CXX +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_CXX + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_CXX" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld + + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu + + +archive_cmds_need_lc_F77=no +allow_undefined_flag_F77= +always_export_symbols_F77=no +archive_expsym_cmds_F77= +export_dynamic_flag_spec_F77= +hardcode_direct_F77=no +hardcode_libdir_flag_spec_F77= +hardcode_libdir_flag_spec_ld_F77= +hardcode_libdir_separator_F77= +hardcode_minus_L_F77=no +hardcode_automatic_F77=no +module_cmds_F77= +module_expsym_cmds_F77= +link_all_deplibs_F77=unknown +old_archive_cmds_F77=$old_archive_cmds +no_undefined_flag_F77= +whole_archive_flag_spec_F77= +enable_shared_with_static_runtimes_F77=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +objext_F77=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code=" subroutine t\n return\n end\n" + +# Code to be used in simple link tests +lt_simple_link_test_code=" program t\n end\n" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +compiler_F77=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +GCC_F77="$G77" +LD_F77="$LD" + +lt_prog_compiler_wl_F77= +lt_prog_compiler_pic_F77= +lt_prog_compiler_static_F77= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_static_F77='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_F77='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_F77=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_F77=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_F77='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + else + lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_F77='-qnocommon' + lt_prog_compiler_wl_F77='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_F77='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_F77='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-fpic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_F77='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_F77='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_F77='-Qoption ld ';; + *) + lt_prog_compiler_wl_F77='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_F77='-Qoption ld ' + lt_prog_compiler_pic_F77='-PIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_F77='-Kconform_pic' + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_can_build_shared_F77=no + ;; + + uts4*) + lt_prog_compiler_pic_F77='-pic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_F77"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_F77=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_F77" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14748: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:14752: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_F77=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } + +if test x"$lt_prog_compiler_pic_works_F77" = xyes; then + case $lt_prog_compiler_pic_F77 in + "" | " "*) ;; + *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; + esac +else + lt_prog_compiler_pic_F77= + lt_prog_compiler_can_build_shared_F77=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_F77= + ;; + *) + lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_F77=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_F77=yes + fi + else + lt_prog_compiler_static_works_F77=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; } + +if test x"$lt_prog_compiler_static_works_F77" = xyes; then + : +else + lt_prog_compiler_static_F77= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_F77=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14852: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:14856: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_F77=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_F77= + enable_shared_with_static_runtimes_F77=no + archive_cmds_F77= + archive_expsym_cmds_F77= + old_archive_From_new_cmds_F77= + old_archive_from_expsyms_cmds_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + thread_safe_flag_spec_F77= + hardcode_libdir_flag_spec_F77= + hardcode_libdir_flag_spec_ld_F77= + hardcode_libdir_separator_F77= + hardcode_direct_F77=no + hardcode_minus_L_F77=no + hardcode_shlibpath_var_F77=unsupported + link_all_deplibs_F77=unknown + hardcode_automatic_F77=no + module_cmds_F77= + module_expsym_cmds_F77= + always_export_symbols_F77=no + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_F77= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # 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_F77=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # 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. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_F77='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_F77= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_F77=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + + # Samuel A. Falvo II 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 can't use + # them. + ld_shlibs_F77=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_F77=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_F77='-L$libdir' + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=no + enable_shared_with_static_runtimes_F77=yes + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_F77=no + fi + ;; + + interix3*) + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_F77=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_F77=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_F77=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + + if test "$ld_shlibs_F77" = no; then + runpath_var= + hardcode_libdir_flag_spec_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=yes + archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_F77=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_F77=unsupported + fi + ;; + + aix4* | aix5*) + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + 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].*|aix5*) + 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 + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_F77='' + hardcode_direct_F77=yes + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_F77=yes + else + # We have old collect2 + hardcode_direct_F77=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_F77=yes + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_libdir_separator_F77= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_F77=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_F77='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_F77="-z nodefs" + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_F77=' ${wl}-bernotok' + allow_undefined_flag_F77=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_F77='$convenience' + archive_cmds_need_lc_F77=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_F77=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_F77=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # 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_F77=' ' + allow_undefined_flag_F77=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_F77='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_F77='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_F77=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_F77=no + hardcode_direct_F77=no + hardcode_automatic_F77=yes + hardcode_shlibpath_var_F77=unsupported + whole_archive_flag_spec_F77='' + link_all_deplibs_F77=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_F77=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + freebsd1*) + ld_shlibs_F77=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_F77='+b $libdir' + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + ;; + *) + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + link_all_deplibs_F77=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + newsos6) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_shlibpath_var_F77=no + ;; + + openbsd*) + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + ;; + *) + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + allow_undefined_flag_F77=unsupported + archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_F77='-rpath $libdir' + fi + hardcode_libdir_separator_F77=: + ;; + + solaris*) + no_undefined_flag_F77=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_shlibpath_var_F77=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_F77=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_F77='$CC -r -o $output$reload_objs' + hardcode_direct_F77=no + ;; + motorola) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_F77=no + ;; + + sysv4.3*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + export_dynamic_flag_spec_F77='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_F77=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_F77='${wl}-z,text' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_F77='${wl}-z,text' + allow_undefined_flag_F77='${wl}-z,nodefs' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + export_dynamic_flag_spec_F77='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + *) + ld_shlibs_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 +echo "${ECHO_T}$ld_shlibs_F77" >&6; } +test "$ld_shlibs_F77" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_F77" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_F77=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_F77 in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_F77 + pic_flag=$lt_prog_compiler_pic_F77 + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_F77 + allow_undefined_flag_F77= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_F77=no + else + archive_cmds_need_lc_F77=yes + fi + allow_undefined_flag_F77=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # Handle Gentoo/FreeBSD as it was Linux + case $host_vendor in + gentoo) + version_type=linux ;; + *) + version_type=freebsd-$objformat ;; + esac + + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + linux) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + need_lib_prefix=no + need_version=no + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_F77= +if test -n "$hardcode_libdir_flag_spec_F77" || \ + test -n "$runpath_var_F77" || \ + test "X$hardcode_automatic_F77" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_F77" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && + test "$hardcode_minus_L_F77" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_F77=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_F77=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_F77=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 +echo "${ECHO_T}$hardcode_action_F77" >&6; } + +if test "$hardcode_action_F77" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_F77 \ + CC_F77 \ + LD_F77 \ + lt_prog_compiler_wl_F77 \ + lt_prog_compiler_pic_F77 \ + lt_prog_compiler_static_F77 \ + lt_prog_compiler_no_builtin_flag_F77 \ + export_dynamic_flag_spec_F77 \ + thread_safe_flag_spec_F77 \ + whole_archive_flag_spec_F77 \ + enable_shared_with_static_runtimes_F77 \ + old_archive_cmds_F77 \ + old_archive_from_new_cmds_F77 \ + predep_objects_F77 \ + postdep_objects_F77 \ + predeps_F77 \ + postdeps_F77 \ + compiler_lib_search_path_F77 \ + archive_cmds_F77 \ + archive_expsym_cmds_F77 \ + postinstall_cmds_F77 \ + postuninstall_cmds_F77 \ + old_archive_from_expsyms_cmds_F77 \ + allow_undefined_flag_F77 \ + no_undefined_flag_F77 \ + export_symbols_cmds_F77 \ + hardcode_libdir_flag_spec_F77 \ + hardcode_libdir_flag_spec_ld_F77 \ + hardcode_libdir_separator_F77 \ + hardcode_automatic_F77 \ + module_cmds_F77 \ + module_expsym_cmds_F77 \ + lt_cv_prog_compiler_c_o_F77 \ + exclude_expsyms_F77 \ + include_expsyms_F77; do + + case $var in + old_archive_cmds_F77 | \ + old_archive_from_new_cmds_F77 | \ + archive_cmds_F77 | \ + archive_expsym_cmds_F77 | \ + module_cmds_F77 | \ + module_expsym_cmds_F77 | \ + old_archive_from_expsyms_cmds_F77 | \ + export_symbols_cmds_F77 | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_F77 + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_F77 + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_F77 + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_F77 + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_F77 + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_F77 +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_F77 + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_F77 +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_F77 +archive_expsym_cmds=$lt_archive_expsym_cmds_F77 +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_F77 +module_expsym_cmds=$lt_module_expsym_cmds_F77 + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_F77 + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_F77 + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_F77 + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_F77 + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_F77 + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_F77 + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_F77 + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_F77 + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_F77 + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_F77 + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_F77" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_F77 + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_F77 + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_F77 + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_F77 + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +objext_GCJ=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +compiler_GCJ=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +archive_cmds_need_lc_GCJ=no + +old_archive_cmds_GCJ=$old_archive_cmds + + +lt_prog_compiler_no_builtin_flag_GCJ= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:17119: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:17123: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl_GCJ= +lt_prog_compiler_pic_GCJ= +lt_prog_compiler_static_GCJ= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_static_GCJ='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_GCJ='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_GCJ=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_GCJ=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_GCJ='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + else + lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_GCJ='-qnocommon' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-fpic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_GCJ='-Qoption ld ';; + *) + lt_prog_compiler_wl_GCJ='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_GCJ='-Qoption ld ' + lt_prog_compiler_pic_GCJ='-PIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_GCJ='-Kconform_pic' + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_can_build_shared_GCJ=no + ;; + + uts4*) + lt_prog_compiler_pic_GCJ='-pic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_GCJ"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_GCJ=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_GCJ" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:17387: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:17391: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_GCJ=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then + case $lt_prog_compiler_pic_GCJ in + "" | " "*) ;; + *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; + esac +else + lt_prog_compiler_pic_GCJ= + lt_prog_compiler_can_build_shared_GCJ=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_GCJ= + ;; + *) + lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_GCJ=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_GCJ=yes + fi + else + lt_prog_compiler_static_works_GCJ=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then + : +else + lt_prog_compiler_static_GCJ= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_GCJ=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:17491: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:17495: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_GCJ=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_GCJ= + enable_shared_with_static_runtimes_GCJ=no + archive_cmds_GCJ= + archive_expsym_cmds_GCJ= + old_archive_From_new_cmds_GCJ= + old_archive_from_expsyms_cmds_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + thread_safe_flag_spec_GCJ= + hardcode_libdir_flag_spec_GCJ= + hardcode_libdir_flag_spec_ld_GCJ= + hardcode_libdir_separator_GCJ= + hardcode_direct_GCJ=no + hardcode_minus_L_GCJ=no + hardcode_shlibpath_var_GCJ=unsupported + link_all_deplibs_GCJ=unknown + hardcode_automatic_GCJ=no + module_cmds_GCJ= + module_expsym_cmds_GCJ= + always_export_symbols_GCJ=no + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_GCJ= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # 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_GCJ=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # 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. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_GCJ= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_GCJ=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + + # Samuel A. Falvo II 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 can't use + # them. + ld_shlibs_GCJ=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_GCJ=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_GCJ='-L$libdir' + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=no + enable_shared_with_static_runtimes_GCJ=yes + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + interix3*) + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_GCJ=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_GCJ=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_GCJ=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + + if test "$ld_shlibs_GCJ" = no; then + runpath_var= + hardcode_libdir_flag_spec_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=yes + archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_GCJ=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_GCJ=unsupported + fi + ;; + + aix4* | aix5*) + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + 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].*|aix5*) + 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 + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_GCJ='' + hardcode_direct_GCJ=yes + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_GCJ=yes + else + # We have old collect2 + hardcode_direct_GCJ=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_GCJ=yes + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_libdir_separator_GCJ= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_GCJ=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_GCJ='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_GCJ="-z nodefs" + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_GCJ=' ${wl}-bernotok' + allow_undefined_flag_GCJ=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_GCJ='$convenience' + archive_cmds_need_lc_GCJ=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_GCJ=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_GCJ=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # 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_GCJ=' ' + allow_undefined_flag_GCJ=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_GCJ='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_GCJ=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_GCJ=no + hardcode_direct_GCJ=no + hardcode_automatic_GCJ=yes + hardcode_shlibpath_var_GCJ=unsupported + whole_archive_flag_spec_GCJ='' + link_all_deplibs_GCJ=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_GCJ=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + freebsd1*) + ld_shlibs_GCJ=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + ;; + *) + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + link_all_deplibs_GCJ=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + newsos6) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_shlibpath_var_GCJ=no + ;; + + openbsd*) + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + ;; + *) + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + allow_undefined_flag_GCJ=unsupported + archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_GCJ='-rpath $libdir' + fi + hardcode_libdir_separator_GCJ=: + ;; + + solaris*) + no_undefined_flag_GCJ=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_shlibpath_var_GCJ=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_GCJ=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_GCJ='$CC -r -o $output$reload_objs' + hardcode_direct_GCJ=no + ;; + motorola) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4.3*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + export_dynamic_flag_spec_GCJ='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_GCJ=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_GCJ='${wl}-z,text' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_GCJ='${wl}-z,text' + allow_undefined_flag_GCJ='${wl}-z,nodefs' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + *) + ld_shlibs_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 +echo "${ECHO_T}$ld_shlibs_GCJ" >&6; } +test "$ld_shlibs_GCJ" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_GCJ" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_GCJ=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_GCJ in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_GCJ + pic_flag=$lt_prog_compiler_pic_GCJ + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ + allow_undefined_flag_GCJ= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_GCJ=no + else + archive_cmds_need_lc_GCJ=yes + fi + allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # Handle Gentoo/FreeBSD as it was Linux + case $host_vendor in + gentoo) + version_type=linux ;; + *) + version_type=freebsd-$objformat ;; + esac + + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + linux) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + need_lib_prefix=no + need_version=no + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_GCJ= +if test -n "$hardcode_libdir_flag_spec_GCJ" || \ + test -n "$runpath_var_GCJ" || \ + test "X$hardcode_automatic_GCJ" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_GCJ" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && + test "$hardcode_minus_L_GCJ" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_GCJ=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_GCJ=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_GCJ=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 +echo "${ECHO_T}$hardcode_action_GCJ" >&6; } + +if test "$hardcode_action_GCJ" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_GCJ \ + CC_GCJ \ + LD_GCJ \ + lt_prog_compiler_wl_GCJ \ + lt_prog_compiler_pic_GCJ \ + lt_prog_compiler_static_GCJ \ + lt_prog_compiler_no_builtin_flag_GCJ \ + export_dynamic_flag_spec_GCJ \ + thread_safe_flag_spec_GCJ \ + whole_archive_flag_spec_GCJ \ + enable_shared_with_static_runtimes_GCJ \ + old_archive_cmds_GCJ \ + old_archive_from_new_cmds_GCJ \ + predep_objects_GCJ \ + postdep_objects_GCJ \ + predeps_GCJ \ + postdeps_GCJ \ + compiler_lib_search_path_GCJ \ + archive_cmds_GCJ \ + archive_expsym_cmds_GCJ \ + postinstall_cmds_GCJ \ + postuninstall_cmds_GCJ \ + old_archive_from_expsyms_cmds_GCJ \ + allow_undefined_flag_GCJ \ + no_undefined_flag_GCJ \ + export_symbols_cmds_GCJ \ + hardcode_libdir_flag_spec_GCJ \ + hardcode_libdir_flag_spec_ld_GCJ \ + hardcode_libdir_separator_GCJ \ + hardcode_automatic_GCJ \ + module_cmds_GCJ \ + module_expsym_cmds_GCJ \ + lt_cv_prog_compiler_c_o_GCJ \ + exclude_expsyms_GCJ \ + include_expsyms_GCJ; do + + case $var in + old_archive_cmds_GCJ | \ + old_archive_from_new_cmds_GCJ | \ + archive_cmds_GCJ | \ + archive_expsym_cmds_GCJ | \ + module_cmds_GCJ | \ + module_expsym_cmds_GCJ | \ + old_archive_from_expsyms_cmds_GCJ | \ + export_symbols_cmds_GCJ | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_GCJ + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_GCJ + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_GCJ + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_GCJ + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_GCJ + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_GCJ +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_GCJ + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_GCJ +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_GCJ +archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_GCJ +module_expsym_cmds=$lt_module_expsym_cmds_GCJ + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_GCJ + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_GCJ + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_GCJ + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_GCJ + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_GCJ + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_GCJ + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_GCJ + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_GCJ + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_GCJ + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_GCJ" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_GCJ + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_GCJ + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_GCJ + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_GCJ + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + RC) + + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +objext_RC=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +compiler_RC=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + +lt_cv_prog_compiler_c_o_RC=yes + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_RC \ + CC_RC \ + LD_RC \ + lt_prog_compiler_wl_RC \ + lt_prog_compiler_pic_RC \ + lt_prog_compiler_static_RC \ + lt_prog_compiler_no_builtin_flag_RC \ + export_dynamic_flag_spec_RC \ + thread_safe_flag_spec_RC \ + whole_archive_flag_spec_RC \ + enable_shared_with_static_runtimes_RC \ + old_archive_cmds_RC \ + old_archive_from_new_cmds_RC \ + predep_objects_RC \ + postdep_objects_RC \ + predeps_RC \ + postdeps_RC \ + compiler_lib_search_path_RC \ + archive_cmds_RC \ + archive_expsym_cmds_RC \ + postinstall_cmds_RC \ + postuninstall_cmds_RC \ + old_archive_from_expsyms_cmds_RC \ + allow_undefined_flag_RC \ + no_undefined_flag_RC \ + export_symbols_cmds_RC \ + hardcode_libdir_flag_spec_RC \ + hardcode_libdir_flag_spec_ld_RC \ + hardcode_libdir_separator_RC \ + hardcode_automatic_RC \ + module_cmds_RC \ + module_expsym_cmds_RC \ + lt_cv_prog_compiler_c_o_RC \ + exclude_expsyms_RC \ + include_expsyms_RC; do + + case $var in + old_archive_cmds_RC | \ + old_archive_from_new_cmds_RC | \ + archive_cmds_RC | \ + archive_expsym_cmds_RC | \ + module_cmds_RC | \ + module_expsym_cmds_RC | \ + old_archive_from_expsyms_cmds_RC | \ + export_symbols_cmds_RC | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_RC + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_RC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_RC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_RC + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_RC + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_RC +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_RC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_RC +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_RC +archive_expsym_cmds=$lt_archive_expsym_cmds_RC +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_RC +module_expsym_cmds=$lt_module_expsym_cmds_RC + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_RC + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_RC + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_RC + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_RC + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_RC + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_RC + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_RC + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_RC + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_RC + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_RC + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_RC + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_RC" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_RC + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_RC + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_RC + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_RC + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + ;; + + *) + { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 +echo "$as_me: error: Unsupported tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 +echo "$as_me: error: unable to update list of available tagged configurations." >&2;} + { (exit 1); exit 1; }; } + fi +fi + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Prevent multiple expansion + + + + + + + + + + + + + + + + + + + + + +# Transfer these variables to the Makefile + + + + + +ac_config_files="$ac_config_files Makefile lib/Makefile include/Makefile bin/Makefile doc/Makefile portaudiocpp.pc" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by PortAudioCpp $as_me 12, which was +generated by GNU Autoconf 2.60. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +PortAudioCpp config.status 12 +configured by $0, generated by GNU Autoconf 2.60, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "bin/Makefile") CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "portaudiocpp.pc") CONFIG_FILES="$CONFIG_FILES portaudiocpp.pc" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +CYGPATH_W!$CYGPATH_W$ac_delim +PACKAGE!$PACKAGE$ac_delim +VERSION!$VERSION$ac_delim +ACLOCAL!$ACLOCAL$ac_delim +AUTOCONF!$AUTOCONF$ac_delim +AUTOMAKE!$AUTOMAKE$ac_delim +AUTOHEADER!$AUTOHEADER$ac_delim +MAKEINFO!$MAKEINFO$ac_delim +install_sh!$install_sh$ac_delim +STRIP!$STRIP$ac_delim +INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim +mkdir_p!$mkdir_p$ac_delim +AWK!$AWK$ac_delim +SET_MAKE!$SET_MAKE$ac_delim +am__leading_dot!$am__leading_dot$ac_delim +AMTAR!$AMTAR$ac_delim +am__tar!$am__tar$ac_delim +am__untar!$am__untar$ac_delim +MAINTAINER_MODE_TRUE!$MAINTAINER_MODE_TRUE$ac_delim +MAINTAINER_MODE_FALSE!$MAINTAINER_MODE_FALSE$ac_delim +MAINT!$MAINT$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +DEPDIR!$DEPDIR$ac_delim +am__include!$am__include$ac_delim +am__quote!$am__quote$ac_delim +AMDEP_TRUE!$AMDEP_TRUE$ac_delim +AMDEP_FALSE!$AMDEP_FALSE$ac_delim +AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim +CCDEPMODE!$CCDEPMODE$ac_delim +am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim +am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +CXXDEPMODE!$CXXDEPMODE$ac_delim +am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim +am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LN_S!$LN_S$ac_delim +ECHO!$ECHO$ac_delim +AR!$AR$ac_delim +RANLIB!$RANLIB$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +DLLTOOL!$DLLTOOL$ac_delim +AS!$AS$ac_delim +OBJDUMP!$OBJDUMP$ac_delim +CPP!$CPP$ac_delim +CXXCPP!$CXXCPP$ac_delim +F77!$F77$ac_delim +FFLAGS!$FFLAGS$ac_delim +ac_ct_F77!$ac_ct_F77$ac_delim +LIBTOOL!$LIBTOOL$ac_delim +DEFAULT_INCLUDES!$DEFAULT_INCLUDES$ac_delim +PORTAUDIO_ROOT!$PORTAUDIO_ROOT$ac_delim +LT_VERSION_INFO!$LT_VERSION_INFO$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 14; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :C $CONFIG_COMMANDS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + + + :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 +echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir=$dirpart/$fdir + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/portaudio/bindings/cpp/configure.ac b/portaudio/bindings/cpp/configure.ac new file mode 100644 index 0000000..100656a --- /dev/null +++ b/portaudio/bindings/cpp/configure.ac @@ -0,0 +1,54 @@ +# +# PortAudioCpp V19 autoconf input file +# Shamelessly ripped from the PortAudio one by Dominic Mazzoni +# Ludwig Schwardt +# Customized for automake by Mikael Magnusson +# + +# Require autoconf >= 2.13 +AC_PREREQ(2.13) + +m4_define([lt_current], [0]) +m4_define([lt_revision], [12]) +m4_define([lt_age], [0]) + +AC_INIT([PortAudioCpp], [12]) +AC_CONFIG_SRCDIR([include/portaudiocpp/PortAudioCpp.hxx]) +AM_INIT_AUTOMAKE +AM_MAINTAINER_MODE + +###### Top-level directory of pacpp +###### This makes it easy to shuffle the build directories +###### Also edit AC_CONFIG_SRCDIR above (wouldn't accept this variable)! +PACPP_ROOT="\$(top_srcdir)" +PORTAUDIO_ROOT="../.." + +# Various other variables and flags +DEFAULT_INCLUDES="-I$PACPP_ROOT/include -I$PACPP_ROOT/$PORTAUDIO_ROOT/include" +CFLAGS=${CFLAGS-"-g -O2 -Wall -ansi -pedantic"} +CXXFLAGS=${CXXFLAGS-"${CFLAGS}"} + +LT_VERSION_INFO="lt_current:lt_revision:lt_age" + +# Checks for programs + +AC_PROG_CC +AC_PROG_CXX +AC_LIBTOOL_WIN32_DLL +AC_PROG_LIBTOOL + +# Transfer these variables to the Makefile +AC_SUBST(DEFAULT_INCLUDES) +AC_SUBST(PORTAUDIO_ROOT) +AC_SUBST(CXXFLAGS) +AC_SUBST(LT_VERSION_INFO) + +AC_CONFIG_FILES([ + Makefile + lib/Makefile + include/Makefile + bin/Makefile + doc/Makefile + portaudiocpp.pc + ]) +AC_OUTPUT diff --git a/portaudio/bindings/cpp/doc/Makefile.am b/portaudio/bindings/cpp/doc/Makefile.am new file mode 100644 index 0000000..7eb81ba --- /dev/null +++ b/portaudio/bindings/cpp/doc/Makefile.am @@ -0,0 +1,5 @@ +PACPP_ROOT = . +#INCLUDES = -I$(srcdir)/$(PACPP_ROOT)/include -I$(top_srcdir)/include + +docs: + doxygen $(srcdir)/config.doxy.linux diff --git a/portaudio/bindings/cpp/doc/Makefile.in b/portaudio/bindings/cpp/doc/Makefile.in new file mode 100644 index 0000000..e9481ad --- /dev/null +++ b/portaudio/bindings/cpp/doc/Makefile.in @@ -0,0 +1,326 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_INCLUDES = @DEFAULT_INCLUDES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PORTAUDIO_ROOT = @PORTAUDIO_ROOT@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +PACPP_ROOT = . +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ + uninstall-info-am + +#INCLUDES = -I$(srcdir)/$(PACPP_ROOT)/include -I$(top_srcdir)/include + +docs: + doxygen $(srcdir)/config.doxy.linux +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/portaudio/bindings/cpp/doc/README b/portaudio/bindings/cpp/doc/README new file mode 100644 index 0000000..5e22972 --- /dev/null +++ b/portaudio/bindings/cpp/doc/README @@ -0,0 +1,34 @@ +GNU/Linux: +---------- + +1) Download and install a recent version of Doxygen (preferably version 1.3.3 or +later). See http://www.doxygen.org/. +2) Download and install a recent version of GraphViz. See +http://www.research.att.com/sw/tools/graphviz/. +3) Run ``doxygen config.doxy.linux'' in this directory or load and generate the file +config.doxy.linux from the Doxywizard application. Or alternatively ``make docs'' can +be run from the build/gnu folder. + +The generated html documentation will be placed in /doc/api_reference/. To open +the main page of the documentation, open the file /doc/api_reference/index.html in +an html browser. + + +Windows: +-------- + +1) Download and install a recent Doxygen (preferably version 1.3.4 or later). See +http://www.doxygen.org/. +2) Download and install a recent version of GraphViz. See +http://www.research.att.com/sw/tools/graphviz/. +3) If needed, edit the config.doxy file in an ascii text editor so that +``DOT_PATH'' variable points to the folder where GraphViz is installed. +4) Run ``doxygen config.doxy'' in this directory or load and generate the file +config.doxy from the Doxywizard application. + +The generated html documentation will be placed in /doc/api_reference/. To open +the main page of the documentation, open the file /doc/api_reference/index.html in +an html browser. + + + diff --git a/portaudio/bindings/cpp/doc/config.doxy b/portaudio/bindings/cpp/doc/config.doxy new file mode 100644 index 0000000..0bfe9d3 --- /dev/null +++ b/portaudio/bindings/cpp/doc/config.doxy @@ -0,0 +1,211 @@ +# Doxyfile 1.3.6 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = PortAudioCpp +PROJECT_NUMBER = 2.0 +OUTPUT_DIRECTORY = ./ +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = YES +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +SHORT_NAMES = YES +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 4 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../source \ + ../include +FILE_PATTERNS = *.hxx \ + *.cxx +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = api_reference +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +UML_LOOK = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = "c:/Program Files/ATT/Graphviz/bin/" +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/portaudio/bindings/cpp/doc/config.doxy.linux b/portaudio/bindings/cpp/doc/config.doxy.linux new file mode 100644 index 0000000..38079f6 --- /dev/null +++ b/portaudio/bindings/cpp/doc/config.doxy.linux @@ -0,0 +1,210 @@ +# Doxyfile 1.3.3 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = PortAudioCpp +PROJECT_NUMBER = 2.0 +OUTPUT_DIRECTORY = ./ +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = YES +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = YES +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +SHORT_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 4 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = YES +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../source \ + ../include +FILE_PATTERNS = *.hxx \ + *.cxx +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = api_reference +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +UML_LOOK = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = "/usr/bin/dot" +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = search.cgi +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = /usr/local/bin/ +EXT_DOC_PATHS = diff --git a/portaudio/bindings/cpp/example/devs.cxx b/portaudio/bindings/cpp/example/devs.cxx new file mode 100644 index 0000000..31a560f --- /dev/null +++ b/portaudio/bindings/cpp/example/devs.cxx @@ -0,0 +1,177 @@ +#include +#include "portaudiocpp/PortAudioCpp.hxx" + +#ifdef WIN32 +#include "portaudiocpp/AsioDeviceAdapter.hxx" +#endif + +// --------------------------------------------------------------------------------------- + +void printSupportedStandardSampleRates( + const portaudio::DirectionSpecificStreamParameters &inputParameters, + const portaudio::DirectionSpecificStreamParameters &outputParameters) +{ + static double STANDARD_SAMPLE_RATES[] = { + 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, + 44100.0, 48000.0, 88200.0, 96000.0, -1 }; // negative terminated list + + int printCount = 0; + + for (int i = 0; STANDARD_SAMPLE_RATES[i] > 0; ++i) + { + portaudio::StreamParameters tmp = portaudio::StreamParameters(inputParameters, outputParameters, STANDARD_SAMPLE_RATES[i], 0, paNoFlag); + + if (tmp.isSupported()) + { + if (printCount == 0) + { + std::cout << " " << STANDARD_SAMPLE_RATES[i]; // 8.2 + printCount = 1; + } + else if (printCount == 4) + { + std::cout << "," << std::endl; + std::cout << " " << STANDARD_SAMPLE_RATES[i]; // 8.2 + printCount = 1; + } + else + { + std::cout << ", " << STANDARD_SAMPLE_RATES[i]; // 8.2 + ++printCount; + } + } + } + + if (printCount == 0) + std::cout << "None" << std::endl; + else + std::cout << std::endl; +} + +// --------------------------------------------------------------------------------------- + +int main(int, char*[]); +int main(int, char*[]) +{ + try + { + portaudio::AutoSystem autoSys; + + portaudio::System &sys = portaudio::System::instance(); + + std::cout << "PortAudio version number = " << sys.version() << std::endl; + std::cout << "PortAudio version text = '" << sys.versionText() << "'" << std::endl; + + int numDevices = sys.deviceCount(); + std::cout << "Number of devices = " << numDevices << std::endl; + + for (portaudio::System::DeviceIterator i = sys.devicesBegin(); i != sys.devicesEnd(); ++i) + { + std::cout << "--------------------------------------- device #" << (*i).index() << std::endl; + + // Mark global and API specific default devices: + bool defaultDisplayed = false; + + if ((*i).isSystemDefaultInputDevice()) + { + std::cout << "[ Default Input"; + defaultDisplayed = true; + } + else if ((*i).isHostApiDefaultInputDevice()) + { + std::cout << "[ Default " << (*i).hostApi().name() << " Input"; + defaultDisplayed = true; + } + + if ((*i).isSystemDefaultOutputDevice()) + { + std::cout << (defaultDisplayed ? "," : "["); + std::cout << " Default Output"; + defaultDisplayed = true; + } + else if ((*i).isHostApiDefaultOutputDevice()) + { + std::cout << (defaultDisplayed ? "," : "["); + std::cout << " Default " << (*i).hostApi().name() << " Output"; + defaultDisplayed = true; + } + + if (defaultDisplayed) + std::cout << " ]" << std::endl; + + // Print device info: + std::cout << "Name = " << (*i).name() << std::endl; + std::cout << "Host API = " << (*i).hostApi().name() << std::endl; + std::cout << "Max inputs = " << (*i).maxInputChannels() << ", Max outputs = " << (*i).maxOutputChannels() << std::endl; + + std::cout << "Default low input latency = " << (*i).defaultLowInputLatency() << std::endl; // 8.3 + std::cout << "Default low output latency = " << (*i).defaultLowOutputLatency() << std::endl; // 8.3 + std::cout << "Default high input latency = " << (*i).defaultHighInputLatency() << std::endl; // 8.3 + std::cout << "Default high output latency = " << (*i).defaultHighOutputLatency() << std::endl; // 8.3 + +#ifdef WIN32 + // ASIO specific latency information: + if ((*i).hostApi().typeId() == paASIO) + { + portaudio::AsioDeviceAdapter asioDevice((*i)); + + std::cout << "ASIO minimum buffer size = " << asioDevice.minBufferSize() << std::endl; + std::cout << "ASIO maximum buffer size = " << asioDevice.maxBufferSize() << std::endl; + std::cout << "ASIO preferred buffer size = " << asioDevice.preferredBufferSize() << std::endl; + + if (asioDevice.granularity() == -1) + std::cout << "ASIO buffer granularity = power of 2" << std::endl; + else + std::cout << "ASIO buffer granularity = " << asioDevice.granularity() << std::endl; + } +#endif // WIN32 + + std::cout << "Default sample rate = " << (*i).defaultSampleRate() << std::endl; // 8.2 + + // Poll for standard sample rates: + portaudio::DirectionSpecificStreamParameters inputParameters((*i), (*i).maxInputChannels(), portaudio::INT16, true, 0.0, NULL); + portaudio::DirectionSpecificStreamParameters outputParameters((*i), (*i).maxOutputChannels(), portaudio::INT16, true, 0.0, NULL); + + if (inputParameters.numChannels() > 0) + { + std::cout << "Supported standard sample rates" << std::endl; + std::cout << " for half-duplex 16 bit " << inputParameters.numChannels() << " channel input = " << std::endl; + printSupportedStandardSampleRates(inputParameters, portaudio::DirectionSpecificStreamParameters::null()); + } + + if (outputParameters.numChannels() > 0) + { + std::cout << "Supported standard sample rates" << std::endl; + std::cout << " for half-duplex 16 bit " << outputParameters.numChannels() << " channel output = " << std::endl; + printSupportedStandardSampleRates(portaudio::DirectionSpecificStreamParameters::null(), outputParameters); + } + + if (inputParameters.numChannels() > 0 && outputParameters.numChannels() > 0) + { + std::cout << "Supported standard sample rates" << std::endl; + std::cout << " for full-duplex 16 bit " << inputParameters.numChannels() << " channel input, " << outputParameters.numChannels() << " channel output = " << std::endl; + printSupportedStandardSampleRates(inputParameters, outputParameters); + } + } + + std::cout << "----------------------------------------------" << std::endl; + } + catch (const portaudio::PaException &e) + { + std::cout << "A PortAudio error occured: " << e.paErrorText() << std::endl; + } + catch (const portaudio::PaCppException &e) + { + std::cout << "A PortAudioCpp error occured: " << e.what() << std::endl; + } + catch (const std::exception &e) + { + std::cout << "A generic exception occured: " << e.what() << std::endl; + } + catch (...) + { + std::cout << "An unknown exception occured." << std::endl; + } + + return 0; +} diff --git a/portaudio/bindings/cpp/example/sine.cxx b/portaudio/bindings/cpp/example/sine.cxx new file mode 100644 index 0000000..577a247 --- /dev/null +++ b/portaudio/bindings/cpp/example/sine.cxx @@ -0,0 +1,137 @@ +// --------------------------------------------------------------------------------------- + +#include +#include +#include +#include +#include "portaudiocpp/PortAudioCpp.hxx" + +// --------------------------------------------------------------------------------------- + +// Some constants: +const int NUM_SECONDS = 5; +const double SAMPLE_RATE = 44100.0; +const int FRAMES_PER_BUFFER = 64; +const int TABLE_SIZE = 200; + +// --------------------------------------------------------------------------------------- + +// SineGenerator class: +class SineGenerator +{ +public: + SineGenerator(int tableSize) : tableSize_(tableSize), leftPhase_(0), rightPhase_(0) + { + const double PI = 3.14159265; + table_ = new float[tableSize]; + for (int i = 0; i < tableSize; ++i) + { + table_[i] = 0.125f * (float)sin(((double)i/(double)tableSize)*PI*2.); + } + } + + ~SineGenerator() + { + delete[] table_; + } + + int generate(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) + { + assert(outputBuffer != NULL); + + float **out = static_cast(outputBuffer); + + for (unsigned int i = 0; i < framesPerBuffer; ++i) + { + out[0][i] = table_[leftPhase_]; + out[1][i] = table_[rightPhase_]; + + leftPhase_ += 1; + if (leftPhase_ >= tableSize_) + leftPhase_ -= tableSize_; + + rightPhase_ += 3; + if (rightPhase_ >= tableSize_) + rightPhase_ -= tableSize_; + } + + return paContinue; + } + +private: + float *table_; + int tableSize_; + int leftPhase_; + int rightPhase_; +}; + +// --------------------------------------------------------------------------------------- + +// main: +int main(int, char *[]); +int main(int, char *[]) +{ + try + { + // Create a SineGenerator object: + SineGenerator sineGenerator(TABLE_SIZE); + + std::cout << "Setting up PortAudio..." << std::endl; + + // Set up the System: + portaudio::AutoSystem autoSys; + portaudio::System &sys = portaudio::System::instance(); + + // Set up the parameters required to open a (Callback)Stream: + portaudio::DirectionSpecificStreamParameters outParams(sys.defaultOutputDevice(), 2, portaudio::FLOAT32, false, sys.defaultOutputDevice().defaultLowOutputLatency(), NULL); + portaudio::StreamParameters params(portaudio::DirectionSpecificStreamParameters::null(), outParams, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff); + + std::cout << "Opening stereo output stream..." << std::endl; + + // Create (and open) a new Stream, using the SineGenerator::generate function as a callback: + portaudio::MemFunCallbackStream stream(params, sineGenerator, &SineGenerator::generate); + + std::cout << "Starting playback for " << NUM_SECONDS << " seconds." << std::endl; + + // Start the Stream (audio playback starts): + stream.start(); + + // Wait for 5 seconds: + sys.sleep(NUM_SECONDS * 1000); + + std::cout << "Closing stream..." < + +#include "portaudio.h" + +#include "portaudiocpp/SampleDataFormat.hxx" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s): +namespace portaudio +{ + class System; + class HostApi; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + ////// + /// @brief Class which represents a PortAudio device in the System. + /// + /// A single physical device in the system may have multiple PortAudio + /// Device representations using different HostApi 's though. A Device + /// can be half-duplex or full-duplex. A half-duplex Device can be used + /// to create a half-duplex Stream. A full-duplex Device can be used to + /// create a full-duplex Stream. If supported by the HostApi, two + /// half-duplex Devices can even be used to create a full-duplex Stream. + /// + /// Note that Device objects are very light-weight and can be passed around + /// by-value. + ////// + class Device + { + public: + // query info: name, max in channels, max out channels, + // default low/hight input/output latency, default sample rate + PaDeviceIndex index() const; + const char *name() const; + int maxInputChannels() const; + int maxOutputChannels() const; + PaTime defaultLowInputLatency() const; + PaTime defaultHighInputLatency() const; + PaTime defaultLowOutputLatency() const; + PaTime defaultHighOutputLatency() const; + double defaultSampleRate() const; + + bool isInputOnlyDevice() const; // extended + bool isOutputOnlyDevice() const; // extended + bool isFullDuplexDevice() const; // extended + bool isSystemDefaultInputDevice() const; // extended + bool isSystemDefaultOutputDevice() const; // extended + bool isHostApiDefaultInputDevice() const; // extended + bool isHostApiDefaultOutputDevice() const; // extended + + bool operator==(const Device &rhs); + bool operator!=(const Device &rhs); + + // host api reference + HostApi &hostApi(); + const HostApi &hostApi() const; + + private: + PaDeviceIndex index_; + const PaDeviceInfo *info_; + + private: + friend class System; + + explicit Device(PaDeviceIndex index); + ~Device(); + + Device(const Device &); // non-copyable + Device &operator=(const Device &); // non-copyable + }; + + // ----------------------------------------------------------------------------------- + +} // namespace portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_DEVICE_HXX + diff --git a/portaudio/bindings/cpp/include/portaudiocpp/DirectionSpecificStreamParameters.hxx b/portaudio/bindings/cpp/include/portaudiocpp/DirectionSpecificStreamParameters.hxx new file mode 100644 index 0000000..dd5ae0b --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/DirectionSpecificStreamParameters.hxx @@ -0,0 +1,77 @@ +#ifndef INCLUDED_PORTAUDIO_SINGLEDIRECTIONSTREAMPARAMETERS_HXX +#define INCLUDED_PORTAUDIO_SINGLEDIRECTIONSTREAMPARAMETERS_HXX + +// --------------------------------------------------------------------------------------- + +#include + +#include "portaudio.h" + +#include "portaudiocpp/System.hxx" +#include "portaudiocpp/SampleDataFormat.hxx" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s): +namespace portaudio +{ + class Device; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + ////// + /// @brief All parameters for one direction (either in or out) of a Stream. Together with + /// parameters common to both directions, two DirectionSpecificStreamParameters can make up + /// a StreamParameters object which contains all parameters for a Stream. + ////// + class DirectionSpecificStreamParameters + { + public: + static DirectionSpecificStreamParameters null(); + + DirectionSpecificStreamParameters(); + DirectionSpecificStreamParameters(const Device &device, int numChannels, SampleDataFormat format, + bool interleaved, PaTime suggestedLatency, void *hostApiSpecificStreamInfo); + + // Set up methods: + void setDevice(const Device &device); + void setNumChannels(int numChannels); + + void setSampleFormat(SampleDataFormat format, bool interleaved = true); + void setHostApiSpecificSampleFormat(PaSampleFormat format, bool interleaved = true); + + void setSuggestedLatency(PaTime latency); + + void setHostApiSpecificStreamInfo(void *streamInfo); + + // Accessor methods: + PaStreamParameters *paStreamParameters(); + const PaStreamParameters *paStreamParameters() const; + + Device &device() const; + int numChannels() const; + + SampleDataFormat sampleFormat() const; + bool isSampleFormatInterleaved() const; + bool isSampleFormatHostApiSpecific() const; + PaSampleFormat hostApiSpecificSampleFormat() const; + + PaTime suggestedLatency() const; + + void *hostApiSpecificStreamInfo() const; + + private: + PaStreamParameters paStreamParameters_; + }; + + +} // namespace portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_SINGLEDIRECTIONSTREAMPARAMETERS_HXX diff --git a/portaudio/bindings/cpp/include/portaudiocpp/Exception.hxx b/portaudio/bindings/cpp/include/portaudiocpp/Exception.hxx new file mode 100644 index 0000000..a70c2f1 --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/Exception.hxx @@ -0,0 +1,108 @@ +#ifndef INCLUDED_PORTAUDIO_EXCEPTION_HXX +#define INCLUDED_PORTAUDIO_EXCEPTION_HXX + +// --------------------------------------------------------------------------------------- + +#include + +#include "portaudio.h" + +// --------------------------------------------------------------------------------------- + +namespace portaudio +{ + + ////// + /// @brief Base class for all exceptions PortAudioCpp can throw. + /// + /// Class is derived from std::exception. + ////// + class Exception : public std::exception + { + public: + virtual ~Exception() throw() {} + + virtual const char *what() const throw() = 0; + }; + + // ----------------------------------------------------------------------------------- + + ////// + /// @brief Wrapper for PortAudio error codes to C++ exceptions. + /// + /// It wraps up PortAudio's error handling mechanism using + /// C++ exceptions and is derived from std::exception for + /// easy exception handling and to ease integration with + /// other code. + /// + /// To know what exceptions each function may throw, look up + /// the errors that can occure in the PortAudio documentation + /// for the equivalent functions. + /// + /// Some functions are likely to throw an exception (such as + /// Stream::open(), etc) and these should always be called in + /// try{} catch{} blocks and the thrown exceptions should be + /// handled properly (ie. the application shouldn't just abort, + /// but merely display a warning dialog to the user or something). + /// However nearly all functions in PortAudioCpp are capable + /// of throwing exceptions. When a function like Stream::isStopped() + /// throws an exception, it's such an exceptional state that it's + /// not likely that it can be recovered. PaExceptions such as these + /// can ``safely'' be left to be handled by some outer catch-all-like + /// mechanism for unrecoverable errors. + ////// + class PaException : public Exception + { + public: + explicit PaException(PaError error); + + const char *what() const throw(); + + PaError paError() const; + const char *paErrorText() const; + + bool isHostApiError() const; // extended + long lastHostApiError() const; + const char *lastHostApiErrorText() const; + + bool operator==(const PaException &rhs) const; + bool operator!=(const PaException &rhs) const; + + private: + PaError error_; + }; + + // ----------------------------------------------------------------------------------- + + ////// + /// @brief Exceptions specific to PortAudioCpp (ie. exceptions which do not have an + /// equivalent PortAudio error code). + ////// + class PaCppException : public Exception + { + public: + enum ExceptionSpecifier + { + UNABLE_TO_ADAPT_DEVICE + }; + + PaCppException(ExceptionSpecifier specifier); + + const char *what() const throw(); + + ExceptionSpecifier specifier() const; + + bool operator==(const PaCppException &rhs) const; + bool operator!=(const PaCppException &rhs) const; + + private: + ExceptionSpecifier specifier_; + }; + + +} // namespace portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_EXCEPTION_HXX + diff --git a/portaudio/bindings/cpp/include/portaudiocpp/HostApi.hxx b/portaudio/bindings/cpp/include/portaudiocpp/HostApi.hxx new file mode 100644 index 0000000..899fc42 --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/HostApi.hxx @@ -0,0 +1,76 @@ +#ifndef INCLUDED_PORTAUDIO_HOSTAPI_HXX +#define INCLUDED_PORTAUDIO_HOSTAPI_HXX + +// --------------------------------------------------------------------------------------- + +#include "portaudio.h" + +#include "portaudiocpp/System.hxx" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s): +namespace portaudio +{ + class Device; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + + ////// + /// @brief HostApi represents a host API (usually type of driver) in the System. + /// + /// A single System can support multiple HostApi's each one typically having + /// a set of Devices using that HostApi (usually driver type). All Devices in + /// the HostApi can be enumerated and the default input/output Device for this + /// HostApi can be retreived. + ////// + class HostApi + { + public: + typedef System::DeviceIterator DeviceIterator; + + // query info: id, name, numDevices + PaHostApiTypeId typeId() const; + PaHostApiIndex index() const; + const char *name() const; + int deviceCount() const; + + // iterate devices + DeviceIterator devicesBegin(); + DeviceIterator devicesEnd(); + + // default devices + Device &defaultInputDevice() const; + Device &defaultOutputDevice() const; + + // comparison operators + bool operator==(const HostApi &rhs) const; + bool operator!=(const HostApi &rhs) const; + + private: + const PaHostApiInfo *info_; + Device **devices_; + + private: + friend class System; + + explicit HostApi(PaHostApiIndex index); + ~HostApi(); + + HostApi(const HostApi &); // non-copyable + HostApi &operator=(const HostApi &); // non-copyable + }; + + +} + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_HOSTAPI_HXX + diff --git a/portaudio/bindings/cpp/include/portaudiocpp/InterfaceCallbackStream.hxx b/portaudio/bindings/cpp/include/portaudiocpp/InterfaceCallbackStream.hxx new file mode 100644 index 0000000..e496dd2 --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/InterfaceCallbackStream.hxx @@ -0,0 +1,49 @@ +#ifndef INCLUDED_PORTAUDIO_INTERFACECALLBACKSTREAM_HXX +#define INCLUDED_PORTAUDIO_INTERFACECALLBACKSTREAM_HXX + +// --------------------------------------------------------------------------------------- + +#include "portaudio.h" + +#include "portaudiocpp/CallbackStream.hxx" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s) +namespace portaudio +{ + class StreamParameters; + class CallbackInterface; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + + ////// + /// @brief Callback stream using an instance of an object that's derived from the CallbackInterface + /// interface. + ////// + class InterfaceCallbackStream : public CallbackStream + { + public: + InterfaceCallbackStream(); + InterfaceCallbackStream(const StreamParameters ¶meters, CallbackInterface &instance); + ~InterfaceCallbackStream(); + + void open(const StreamParameters ¶meters, CallbackInterface &instance); + + private: + InterfaceCallbackStream(const InterfaceCallbackStream &); // non-copyable + InterfaceCallbackStream &operator=(const InterfaceCallbackStream &); // non-copyable + }; + + +} // portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_INTERFACECALLBACKSTREAM_HXX diff --git a/portaudio/bindings/cpp/include/portaudiocpp/MemFunCallbackStream.hxx b/portaudio/bindings/cpp/include/portaudiocpp/MemFunCallbackStream.hxx new file mode 100644 index 0000000..a9e50ca --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/MemFunCallbackStream.hxx @@ -0,0 +1,107 @@ +#ifndef INCLUDED_PORTAUDIO_MEMFUNCALLBACKSTREAM_HXX +#define INCLUDED_PORTAUDIO_MEMFUNCALLBACKSTREAM_HXX + +// --------------------------------------------------------------------------------------- + +#include "portaudio.h" + +#include "portaudiocpp/CallbackStream.hxx" +#include "portaudiocpp/CallbackInterface.hxx" +#include "portaudiocpp/StreamParameters.hxx" +#include "portaudiocpp/Exception.hxx" +#include "portaudiocpp/InterfaceCallbackStream.hxx" + +// --------------------------------------------------------------------------------------- + +namespace portaudio +{ + + + ////// + /// @brief Callback stream using a class's member function as a callback. Template argument T is the type of the + /// class of which a member function is going to be used. + /// + /// Example usage: + /// @verbatim MemFunCallback stream = MemFunCallbackStream(parameters, *this, &MyClass::myCallbackFunction); @endverbatim + ////// + template + class MemFunCallbackStream : public CallbackStream + { + public: + typedef int (T::*CallbackFunPtr)(const void *, void *, unsigned long, const PaStreamCallbackTimeInfo *, + PaStreamCallbackFlags); + + // ------------------------------------------------------------------------------- + + MemFunCallbackStream() + { + } + + MemFunCallbackStream(const StreamParameters ¶meters, T &instance, CallbackFunPtr memFun) : adapter_(instance, memFun) + { + open(parameters); + } + + ~MemFunCallbackStream() + { + close(); + } + + void open(const StreamParameters ¶meters, T &instance, CallbackFunPtr memFun) + { + // XXX: need to check if already open? + + adapter_.init(instance, memFun); + open(parameters); + } + + private: + MemFunCallbackStream(const MemFunCallbackStream &); // non-copyable + MemFunCallbackStream &operator=(const MemFunCallbackStream &); // non-copyable + + ////// + /// @brief Inner class which adapts a member function callback to a CallbackInterface compliant + /// class (so it can be adapted using the paCallbackAdapter function). + ////// + class MemFunToCallbackInterfaceAdapter : public CallbackInterface + { + public: + MemFunToCallbackInterfaceAdapter() {} + MemFunToCallbackInterfaceAdapter(T &instance, CallbackFunPtr memFun) : instance_(&instance), memFun_(memFun) {} + + void init(T &instance, CallbackFunPtr memFun) + { + instance_ = &instance; + memFun_ = memFun; + } + + int paCallbackFun(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) + { + return (instance_->*memFun_)(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags); + } + + private: + T *instance_; + CallbackFunPtr memFun_; + }; + + MemFunToCallbackInterfaceAdapter adapter_; + + void open(const StreamParameters ¶meters) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::callbackInterfaceToPaCallbackAdapter, + static_cast(&adapter_)); + + if (err != paNoError) + throw PaException(err); + } + }; + + +} // portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_MEMFUNCALLBACKSTREAM_HXX diff --git a/portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx b/portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx new file mode 100644 index 0000000..f11e7fb --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx @@ -0,0 +1,109 @@ +#ifndef INCLUDED_PORTAUDIO_PORTAUDIOCPP_HXX +#define INCLUDED_PORTAUDIO_PORTAUDIOCPP_HXX + +// --------------------------------------------------------------------------------------- + +////// +/// @mainpage PortAudioCpp +/// +///

    PortAudioCpp - A Native C++ Binding of PortAudio V19

    +///

    PortAudio

    +///

    +/// PortAudio is a portable and mature C API for accessing audio hardware. It offers both callback-based and blocking +/// style input and output, deals with sample data format conversions, dithering and much more. There are a large number +/// of implementations available for various platforms including Windows MME, Windows DirectX, Windows and MacOS (Classic) +/// ASIO, MacOS Classic SoundManager, MacOS X CoreAudio, OSS (Linux), Linux ALSA, JACK (MacOS X and Linux) and SGI Irix +/// AL. Note that, currently not all of these implementations are equally complete or up-to-date (as PortAudio V19 is +/// still in development). Because PortAudio has a C API, it can easily be called from a variety of other programming +/// languages. +///

    +///

    PortAudioCpp

    +///

    +/// Although, it is possible to use PortAudio's C API from within a C++ program, this is usually a little awkward +/// as procedural and object-oriented paradigms need to be mixed. PortAudioCpp aims to resolve this by encapsulating +/// PortAudio's C API to form an equivalent object-oriented C++ API. It provides a more natural integration of PortAudio +/// into C++ programs as well as a more structured interface. PortAudio's concepts were preserved as much as possible and +/// no additional features were added except for some `convenience methods'. +///

    +///

    +/// PortAudioCpp's main features are: +///

      +///
    • Structured object model.
    • +///
    • C++ exception handling instead of C-style error return codes.
    • +///
    • Handling of callbacks using free functions (C and C++), static functions, member functions or instances of classes +/// derived from a given interface.
    • +///
    • STL compliant iterators to host APIs and devices.
    • +///
    • Some additional convenience functions to more easily set up and use PortAudio.
    • +///
    +///

    +///

    +/// PortAudioCpp requires a recent version of the PortAudio V19 source code. This can be obtained from CVS or as a snapshot +/// from the website. The examples also require the ASIO 2 SDK which can be obtained from the Steinberg website. Alternatively, the +/// examples can easily be modified to compile without needing ASIO. +///

    +///

    +/// Supported platforms: +///

      +///
    • Microsoft Visual C++ 6.0, 7.0 (.NET 2002) and 7.1 (.NET 2003).
    • +///
    • GNU G++ 2.95 and G++ 3.3.
    • +///
    +/// Other platforms should be easily supported as PortAudioCpp is platform-independent and (reasonably) C++ standard compliant. +///

    +///

    +/// This documentation mainly provides information specific to PortAudioCpp. For a more complete explaination of all of the +/// concepts used, please consult the PortAudio documentation. +///

    +///

    +/// PortAudioCpp was developed by Merlijn Blaauw with many great suggestions and help from Ross Bencina. Ludwig Schwardt provided +/// GNU/Linux build files and checked G++ compatibility. PortAudioCpp may be used under the same licensing, conditions and +/// warranty as PortAudio. See the PortAudio license for more details. +///

    +///

    Links

    +///

    +/// Official PortAudio site.
    +///

    +////// + +// --------------------------------------------------------------------------------------- + +////// +/// @namespace portaudio +/// +/// To avoid name collision, everything in PortAudioCpp is in the portaudio +/// namespace. If this name is too long it's usually pretty safe to use an +/// alias like ``namespace pa = portaudio;''. +////// + +// --------------------------------------------------------------------------------------- + +////// +/// @file PortAudioCpp.hxx +/// An include-all header file (for lazy programmers and using pre-compiled headers). +////// + +// --------------------------------------------------------------------------------------- + +#include "portaudio.h" + +#include "portaudiocpp/AutoSystem.hxx" +#include "portaudiocpp/BlockingStream.hxx" +#include "portaudiocpp/CallbackInterface.hxx" +#include "portaudiocpp/CallbackStream.hxx" +#include "portaudiocpp/CFunCallbackStream.hxx" +#include "portaudiocpp/CppFunCallbackStream.hxx" +#include "portaudiocpp/Device.hxx" +#include "portaudiocpp/Exception.hxx" +#include "portaudiocpp/HostApi.hxx" +#include "portaudiocpp/InterfaceCallbackStream.hxx" +#include "portaudiocpp/MemFunCallbackStream.hxx" +#include "portaudiocpp/SampleDataFormat.hxx" +#include "portaudiocpp/DirectionSpecificStreamParameters.hxx" +#include "portaudiocpp/Stream.hxx" +#include "portaudiocpp/StreamParameters.hxx" +#include "portaudiocpp/System.hxx" +#include "portaudiocpp/SystemDeviceIterator.hxx" +#include "portaudiocpp/SystemHostApiIterator.hxx" + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_PORTAUDIOCPP_HXX diff --git a/portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx b/portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx new file mode 100644 index 0000000..a7e25b2 --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx @@ -0,0 +1,35 @@ +#ifndef INCLUDED_PORTAUDIO_SAMPLEDATAFORMAT_HXX +#define INCLUDED_PORTAUDIO_SAMPLEDATAFORMAT_HXX + +// --------------------------------------------------------------------------------------- + +#include "portaudio.h" + +// --------------------------------------------------------------------------------------- + +namespace portaudio +{ + + + ////// + /// @brief PortAudio sample data formats. + /// + /// Small helper enum to wrap the PortAudio defines. + ////// + enum SampleDataFormat + { + INVALID_FORMAT = 0, + FLOAT32 = paFloat32, + INT32 = paInt32, + INT24 = paInt24, + INT16 = paInt16, + INT8 = paInt8, + UINT8 = paUInt8 + }; + + +} // namespace portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_SAMPLEDATAFORMAT_HXX diff --git a/portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx b/portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx new file mode 100644 index 0000000..8a255ec --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx @@ -0,0 +1,82 @@ +#ifndef INCLUDED_PORTAUDIO_STREAM_HXX +#define INCLUDED_PORTAUDIO_STREAM_HXX + +#include "portaudio.h" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s): +namespace portaudio +{ + class StreamParameters; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + + ////// + /// @brief A Stream represents an active or inactive input and/or output data + /// stream in the System. + /// + /// Concrete Stream classes should ensure themselves being in a closed state at + /// destruction (i.e. by calling their own close() method in their deconstructor). + /// Following good C++ programming practices, care must be taken to ensure no + /// exceptions are thrown by the deconstructor of these classes. As a consequence, + /// clients need to explicitly call close() to ensure the stream closed successfully. + /// + /// The Stream object can be used to manipulate the Stream's state. Also, time-constant + /// and time-varying information about the Stream can be retreived. + ////// + class Stream + { + public: + // Opening/closing: + virtual ~Stream(); + + virtual void close(); + bool isOpen() const; + + // Additional set up: + void setStreamFinishedCallback(PaStreamFinishedCallback *callback); + + // State management: + void start(); + void stop(); + void abort(); + + bool isStopped() const; + bool isActive() const; + + // Stream info (time-constant, but might become time-variant soon): + PaTime inputLatency() const; + PaTime outputLatency() const; + double sampleRate() const; + + // Stream info (time-varying): + PaTime time() const; + + // Accessors for PortAudio PaStream, useful for interfacing + // with PortAudio add-ons (such as PortMixer) for instance: + const PaStream *paStream() const; + PaStream *paStream(); + + protected: + Stream(); // abstract class + + PaStream *stream_; + + private: + Stream(const Stream &); // non-copyable + Stream &operator=(const Stream &); // non-copyable + }; + + +} // namespace portaudio + + +#endif // INCLUDED_PORTAUDIO_STREAM_HXX + diff --git a/portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx b/portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx new file mode 100644 index 0000000..2b6aa2e --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx @@ -0,0 +1,77 @@ +#ifndef INCLUDED_PORTAUDIO_STREAMPARAMETERS_HXX +#define INCLUDED_PORTAUDIO_STREAMPARAMETERS_HXX + +// --------------------------------------------------------------------------------------- + +#include "portaudio.h" + +#include "portaudiocpp/DirectionSpecificStreamParameters.hxx" + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + ////// + /// @brief The entire set of parameters needed to configure and open + /// a Stream. + /// + /// It contains parameters of input, output and shared parameters. + /// Using the isSupported() method, the StreamParameters can be + /// checked if opening a Stream using this StreamParameters would + /// succeed or not. Accessors are provided to higher-level parameters + /// aswell as the lower-level parameters which are mainly intended for + /// internal use. + ////// + class StreamParameters + { + public: + StreamParameters(); + StreamParameters(const DirectionSpecificStreamParameters &inputParameters, + const DirectionSpecificStreamParameters &outputParameters, double sampleRate, + unsigned long framesPerBuffer, PaStreamFlags flags); + + // Set up for direction-specific: + void setInputParameters(const DirectionSpecificStreamParameters ¶meters); + void setOutputParameters(const DirectionSpecificStreamParameters ¶meters); + + // Set up for common parameters: + void setSampleRate(double sampleRate); + void setFramesPerBuffer(unsigned long framesPerBuffer); + void setFlag(PaStreamFlags flag); + void unsetFlag(PaStreamFlags flag); + void clearFlags(); + + // Validation: + bool isSupported() const; + + // Accessors (direction-specific): + DirectionSpecificStreamParameters &inputParameters(); + const DirectionSpecificStreamParameters &inputParameters() const; + DirectionSpecificStreamParameters &outputParameters(); + const DirectionSpecificStreamParameters &outputParameters() const; + + // Accessors (common): + double sampleRate() const; + unsigned long framesPerBuffer() const; + PaStreamFlags flags() const; + bool isFlagSet(PaStreamFlags flag) const; + + private: + // Half-duplex specific parameters: + DirectionSpecificStreamParameters inputParameters_; + DirectionSpecificStreamParameters outputParameters_; + + // Common parameters: + double sampleRate_; + unsigned long framesPerBuffer_; + PaStreamFlags flags_; + }; + + +} // namespace portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_STREAMPARAMETERS_HXX diff --git a/portaudio/bindings/cpp/include/portaudiocpp/System.hxx b/portaudio/bindings/cpp/include/portaudiocpp/System.hxx new file mode 100644 index 0000000..f5fb713 --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/System.hxx @@ -0,0 +1,107 @@ +#ifndef INCLUDED_PORTAUDIO_SYSTEM_HXX +#define INCLUDED_PORTAUDIO_SYSTEM_HXX + +// --------------------------------------------------------------------------------------- + +#include "portaudio.h" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s): +namespace portaudio +{ + class Device; + class Stream; + class HostApi; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + + ////// + /// @brief System singleton which represents the PortAudio system. + /// + /// The System is used to initialize/terminate PortAudio and provide + /// a single acccess point to the PortAudio System (instance()). + /// It can be used to iterate through all HostApi 's in the System as + /// well as all devices in the System. It also provides some utility + /// functionality of PortAudio. + /// + /// Terminating the System will also abort and close the open streams. + /// The Stream objects will need to be deallocated by the client though + /// (it's usually a good idea to have them cleaned up automatically). + ////// + class System + { + public: + class HostApiIterator; // forward declaration + class DeviceIterator; // forward declaration + + // ------------------------------------------------------------------------------- + + static int version(); + static const char *versionText(); + + static void initialize(); + static void terminate(); + + static System &instance(); + static bool exists(); + + // ------------------------------------------------------------------------------- + + // host apis: + HostApiIterator hostApisBegin(); + HostApiIterator hostApisEnd(); + + HostApi &defaultHostApi(); + + HostApi &hostApiByTypeId(PaHostApiTypeId type); + HostApi &hostApiByIndex(PaHostApiIndex index); + + int hostApiCount(); + + // ------------------------------------------------------------------------------- + + // devices: + DeviceIterator devicesBegin(); + DeviceIterator devicesEnd(); + + Device &defaultInputDevice(); + Device &defaultOutputDevice(); + + Device &deviceByIndex(PaDeviceIndex index); + + int deviceCount(); + + static Device &nullDevice(); + + // ------------------------------------------------------------------------------- + + // misc: + void sleep(long msec); + int sizeOfSample(PaSampleFormat format); + + private: + System(); + ~System(); + + static System *instance_; + static int initCount_; + + static HostApi **hostApis_; + static Device **devices_; + + static Device *nullDevice_; + }; + + +} // namespace portaudio + + +#endif // INCLUDED_PORTAUDIO_SYSTEM_HXX + diff --git a/portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx b/portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx new file mode 100644 index 0000000..613fc3d --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx @@ -0,0 +1,66 @@ +#ifndef INCLUDED_PORTAUDIO_SYSTEMDEVICEITERATOR_HXX +#define INCLUDED_PORTAUDIO_SYSTEMDEVICEITERATOR_HXX + +// --------------------------------------------------------------------------------------- + +#include +#include + +#include "portaudiocpp/System.hxx" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s): +namespace portaudio +{ + class Device; + class HostApi; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + + ////// + /// @brief Iterator class for iterating through all Devices in a System. + /// + /// Devices will be iterated by iterating all Devices in each + /// HostApi in the System. Compliant with the STL bidirectional + /// iterator concept. + ////// + class System::DeviceIterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef Device value_type; + typedef ptrdiff_t difference_type; + typedef Device * pointer; + typedef Device & reference; + + Device &operator*() const; + Device *operator->() const; + + DeviceIterator &operator++(); + DeviceIterator operator++(int); + DeviceIterator &operator--(); + DeviceIterator operator--(int); + + bool operator==(const DeviceIterator &rhs); + bool operator!=(const DeviceIterator &rhs); + + private: + friend class System; + friend class HostApi; + Device **ptr_; + }; + + +} // namespace portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_SYSTEMDEVICEITERATOR_HXX + diff --git a/portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx b/portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx new file mode 100644 index 0000000..b9b13b8 --- /dev/null +++ b/portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx @@ -0,0 +1,61 @@ +#ifndef INCLUDED_PORTAUDIO_SYSTEMHOSTAPIITERATOR_HXX +#define INCLUDED_PORTAUDIO_SYSTEMHOSTAPIITERATOR_HXX + +// --------------------------------------------------------------------------------------- + +#include +#include + +#include "portaudiocpp/System.hxx" + +// --------------------------------------------------------------------------------------- + +// Forward declaration(s): +namespace portaudio +{ + class HostApi; +} + +// --------------------------------------------------------------------------------------- + +// Declaration(s): +namespace portaudio +{ + + + ////// + /// @brief Iterator class for iterating through all HostApis in a System. + /// + /// Compliant with the STL bidirectional iterator concept. + ////// + class System::HostApiIterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef Device value_type; + typedef ptrdiff_t difference_type; + typedef HostApi * pointer; + typedef HostApi & reference; + + HostApi &operator*() const; + HostApi *operator->() const; + + HostApiIterator &operator++(); + HostApiIterator operator++(int); + HostApiIterator &operator--(); + HostApiIterator operator--(int); + + bool operator==(const HostApiIterator &rhs); + bool operator!=(const HostApiIterator &rhs); + + private: + friend class System; + HostApi **ptr_; + }; + + +} // namespace portaudio + +// --------------------------------------------------------------------------------------- + +#endif // INCLUDED_PORTAUDIO_SYSTEMHOSTAPIITERATOR_HXX diff --git a/portaudio/bindings/cpp/lib/Makefile.am b/portaudio/bindings/cpp/lib/Makefile.am new file mode 100644 index 0000000..a27f7c5 --- /dev/null +++ b/portaudio/bindings/cpp/lib/Makefile.am @@ -0,0 +1,26 @@ +SRCDIR = $(top_srcdir)/source/portaudiocpp + +lib_LTLIBRARIES = libportaudiocpp.la + +LDADD = libportaudiocpp.la + +libportaudiocpp_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined + +libportaudiocpp_la_LIBADD = $(top_builddir)/$(PORTAUDIO_ROOT)/lib/libportaudio.la +libportaudiocpp_la_SOURCES = \ + $(SRCDIR)/BlockingStream.cxx \ + $(SRCDIR)/CallbackInterface.cxx \ + $(SRCDIR)/CallbackStream.cxx \ + $(SRCDIR)/CFunCallbackStream.cxx \ + $(SRCDIR)/CppFunCallbackStream.cxx \ + $(SRCDIR)/Device.cxx \ + $(SRCDIR)/DirectionSpecificStreamParameters.cxx \ + $(SRCDIR)/Exception.cxx \ + $(SRCDIR)/HostApi.cxx \ + $(SRCDIR)/InterfaceCallbackStream.cxx \ + $(SRCDIR)/MemFunCallbackStream.cxx \ + $(SRCDIR)/Stream.cxx \ + $(SRCDIR)/StreamParameters.cxx \ + $(SRCDIR)/System.cxx \ + $(SRCDIR)/SystemDeviceIterator.cxx \ + $(SRCDIR)/SystemHostApiIterator.cxx diff --git a/portaudio/bindings/cpp/lib/Makefile.in b/portaudio/bindings/cpp/lib/Makefile.in new file mode 100644 index 0000000..11be8c1 --- /dev/null +++ b/portaudio/bindings/cpp/lib/Makefile.in @@ -0,0 +1,615 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libportaudiocpp_la_DEPENDENCIES = \ + $(top_builddir)/$(PORTAUDIO_ROOT)/lib/libportaudio.la +am_libportaudiocpp_la_OBJECTS = BlockingStream.lo CallbackInterface.lo \ + CallbackStream.lo CFunCallbackStream.lo \ + CppFunCallbackStream.lo Device.lo \ + DirectionSpecificStreamParameters.lo Exception.lo HostApi.lo \ + InterfaceCallbackStream.lo MemFunCallbackStream.lo Stream.lo \ + StreamParameters.lo System.lo SystemDeviceIterator.lo \ + SystemHostApiIterator.lo +libportaudiocpp_la_OBJECTS = $(am_libportaudiocpp_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/../../depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libportaudiocpp_la_SOURCES) +DIST_SOURCES = $(libportaudiocpp_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_INCLUDES = @DEFAULT_INCLUDES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PORTAUDIO_ROOT = @PORTAUDIO_ROOT@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +SRCDIR = $(top_srcdir)/source/portaudiocpp +lib_LTLIBRARIES = libportaudiocpp.la +LDADD = libportaudiocpp.la +libportaudiocpp_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined +libportaudiocpp_la_LIBADD = $(top_builddir)/$(PORTAUDIO_ROOT)/lib/libportaudio.la +libportaudiocpp_la_SOURCES = \ + $(SRCDIR)/BlockingStream.cxx \ + $(SRCDIR)/CallbackInterface.cxx \ + $(SRCDIR)/CallbackStream.cxx \ + $(SRCDIR)/CFunCallbackStream.cxx \ + $(SRCDIR)/CppFunCallbackStream.cxx \ + $(SRCDIR)/Device.cxx \ + $(SRCDIR)/DirectionSpecificStreamParameters.cxx \ + $(SRCDIR)/Exception.cxx \ + $(SRCDIR)/HostApi.cxx \ + $(SRCDIR)/InterfaceCallbackStream.cxx \ + $(SRCDIR)/MemFunCallbackStream.cxx \ + $(SRCDIR)/Stream.cxx \ + $(SRCDIR)/StreamParameters.cxx \ + $(SRCDIR)/System.cxx \ + $(SRCDIR)/SystemDeviceIterator.cxx \ + $(SRCDIR)/SystemHostApiIterator.cxx + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cxx .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libportaudiocpp.la: $(libportaudiocpp_la_OBJECTS) $(libportaudiocpp_la_DEPENDENCIES) + $(CXXLINK) -rpath $(libdir) $(libportaudiocpp_la_LDFLAGS) $(libportaudiocpp_la_OBJECTS) $(libportaudiocpp_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BlockingStream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CFunCallbackStream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CallbackInterface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CallbackStream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CppFunCallbackStream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DirectionSpecificStreamParameters.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Exception.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HostApi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InterfaceCallbackStream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemFunCallbackStream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StreamParameters.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/System.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SystemDeviceIterator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SystemHostApiIterator.Plo@am__quote@ + +.cxx.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cxx.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cxx.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +BlockingStream.lo: $(SRCDIR)/BlockingStream.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT BlockingStream.lo -MD -MP -MF "$(DEPDIR)/BlockingStream.Tpo" -c -o BlockingStream.lo `test -f '$(SRCDIR)/BlockingStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/BlockingStream.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/BlockingStream.Tpo" "$(DEPDIR)/BlockingStream.Plo"; else rm -f "$(DEPDIR)/BlockingStream.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/BlockingStream.cxx' object='BlockingStream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o BlockingStream.lo `test -f '$(SRCDIR)/BlockingStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/BlockingStream.cxx + +CallbackInterface.lo: $(SRCDIR)/CallbackInterface.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CallbackInterface.lo -MD -MP -MF "$(DEPDIR)/CallbackInterface.Tpo" -c -o CallbackInterface.lo `test -f '$(SRCDIR)/CallbackInterface.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CallbackInterface.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/CallbackInterface.Tpo" "$(DEPDIR)/CallbackInterface.Plo"; else rm -f "$(DEPDIR)/CallbackInterface.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/CallbackInterface.cxx' object='CallbackInterface.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CallbackInterface.lo `test -f '$(SRCDIR)/CallbackInterface.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CallbackInterface.cxx + +CallbackStream.lo: $(SRCDIR)/CallbackStream.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CallbackStream.lo -MD -MP -MF "$(DEPDIR)/CallbackStream.Tpo" -c -o CallbackStream.lo `test -f '$(SRCDIR)/CallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CallbackStream.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/CallbackStream.Tpo" "$(DEPDIR)/CallbackStream.Plo"; else rm -f "$(DEPDIR)/CallbackStream.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/CallbackStream.cxx' object='CallbackStream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CallbackStream.lo `test -f '$(SRCDIR)/CallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CallbackStream.cxx + +CFunCallbackStream.lo: $(SRCDIR)/CFunCallbackStream.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CFunCallbackStream.lo -MD -MP -MF "$(DEPDIR)/CFunCallbackStream.Tpo" -c -o CFunCallbackStream.lo `test -f '$(SRCDIR)/CFunCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CFunCallbackStream.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/CFunCallbackStream.Tpo" "$(DEPDIR)/CFunCallbackStream.Plo"; else rm -f "$(DEPDIR)/CFunCallbackStream.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/CFunCallbackStream.cxx' object='CFunCallbackStream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CFunCallbackStream.lo `test -f '$(SRCDIR)/CFunCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CFunCallbackStream.cxx + +CppFunCallbackStream.lo: $(SRCDIR)/CppFunCallbackStream.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT CppFunCallbackStream.lo -MD -MP -MF "$(DEPDIR)/CppFunCallbackStream.Tpo" -c -o CppFunCallbackStream.lo `test -f '$(SRCDIR)/CppFunCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CppFunCallbackStream.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/CppFunCallbackStream.Tpo" "$(DEPDIR)/CppFunCallbackStream.Plo"; else rm -f "$(DEPDIR)/CppFunCallbackStream.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/CppFunCallbackStream.cxx' object='CppFunCallbackStream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o CppFunCallbackStream.lo `test -f '$(SRCDIR)/CppFunCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/CppFunCallbackStream.cxx + +Device.lo: $(SRCDIR)/Device.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Device.lo -MD -MP -MF "$(DEPDIR)/Device.Tpo" -c -o Device.lo `test -f '$(SRCDIR)/Device.cxx' || echo '$(srcdir)/'`$(SRCDIR)/Device.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/Device.Tpo" "$(DEPDIR)/Device.Plo"; else rm -f "$(DEPDIR)/Device.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/Device.cxx' object='Device.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Device.lo `test -f '$(SRCDIR)/Device.cxx' || echo '$(srcdir)/'`$(SRCDIR)/Device.cxx + +DirectionSpecificStreamParameters.lo: $(SRCDIR)/DirectionSpecificStreamParameters.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT DirectionSpecificStreamParameters.lo -MD -MP -MF "$(DEPDIR)/DirectionSpecificStreamParameters.Tpo" -c -o DirectionSpecificStreamParameters.lo `test -f '$(SRCDIR)/DirectionSpecificStreamParameters.cxx' || echo '$(srcdir)/'`$(SRCDIR)/DirectionSpecificStreamParameters.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/DirectionSpecificStreamParameters.Tpo" "$(DEPDIR)/DirectionSpecificStreamParameters.Plo"; else rm -f "$(DEPDIR)/DirectionSpecificStreamParameters.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/DirectionSpecificStreamParameters.cxx' object='DirectionSpecificStreamParameters.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o DirectionSpecificStreamParameters.lo `test -f '$(SRCDIR)/DirectionSpecificStreamParameters.cxx' || echo '$(srcdir)/'`$(SRCDIR)/DirectionSpecificStreamParameters.cxx + +Exception.lo: $(SRCDIR)/Exception.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Exception.lo -MD -MP -MF "$(DEPDIR)/Exception.Tpo" -c -o Exception.lo `test -f '$(SRCDIR)/Exception.cxx' || echo '$(srcdir)/'`$(SRCDIR)/Exception.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/Exception.Tpo" "$(DEPDIR)/Exception.Plo"; else rm -f "$(DEPDIR)/Exception.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/Exception.cxx' object='Exception.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Exception.lo `test -f '$(SRCDIR)/Exception.cxx' || echo '$(srcdir)/'`$(SRCDIR)/Exception.cxx + +HostApi.lo: $(SRCDIR)/HostApi.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT HostApi.lo -MD -MP -MF "$(DEPDIR)/HostApi.Tpo" -c -o HostApi.lo `test -f '$(SRCDIR)/HostApi.cxx' || echo '$(srcdir)/'`$(SRCDIR)/HostApi.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/HostApi.Tpo" "$(DEPDIR)/HostApi.Plo"; else rm -f "$(DEPDIR)/HostApi.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/HostApi.cxx' object='HostApi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o HostApi.lo `test -f '$(SRCDIR)/HostApi.cxx' || echo '$(srcdir)/'`$(SRCDIR)/HostApi.cxx + +InterfaceCallbackStream.lo: $(SRCDIR)/InterfaceCallbackStream.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT InterfaceCallbackStream.lo -MD -MP -MF "$(DEPDIR)/InterfaceCallbackStream.Tpo" -c -o InterfaceCallbackStream.lo `test -f '$(SRCDIR)/InterfaceCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/InterfaceCallbackStream.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/InterfaceCallbackStream.Tpo" "$(DEPDIR)/InterfaceCallbackStream.Plo"; else rm -f "$(DEPDIR)/InterfaceCallbackStream.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/InterfaceCallbackStream.cxx' object='InterfaceCallbackStream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o InterfaceCallbackStream.lo `test -f '$(SRCDIR)/InterfaceCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/InterfaceCallbackStream.cxx + +MemFunCallbackStream.lo: $(SRCDIR)/MemFunCallbackStream.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT MemFunCallbackStream.lo -MD -MP -MF "$(DEPDIR)/MemFunCallbackStream.Tpo" -c -o MemFunCallbackStream.lo `test -f '$(SRCDIR)/MemFunCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/MemFunCallbackStream.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/MemFunCallbackStream.Tpo" "$(DEPDIR)/MemFunCallbackStream.Plo"; else rm -f "$(DEPDIR)/MemFunCallbackStream.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/MemFunCallbackStream.cxx' object='MemFunCallbackStream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o MemFunCallbackStream.lo `test -f '$(SRCDIR)/MemFunCallbackStream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/MemFunCallbackStream.cxx + +Stream.lo: $(SRCDIR)/Stream.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Stream.lo -MD -MP -MF "$(DEPDIR)/Stream.Tpo" -c -o Stream.lo `test -f '$(SRCDIR)/Stream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/Stream.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/Stream.Tpo" "$(DEPDIR)/Stream.Plo"; else rm -f "$(DEPDIR)/Stream.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/Stream.cxx' object='Stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Stream.lo `test -f '$(SRCDIR)/Stream.cxx' || echo '$(srcdir)/'`$(SRCDIR)/Stream.cxx + +StreamParameters.lo: $(SRCDIR)/StreamParameters.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT StreamParameters.lo -MD -MP -MF "$(DEPDIR)/StreamParameters.Tpo" -c -o StreamParameters.lo `test -f '$(SRCDIR)/StreamParameters.cxx' || echo '$(srcdir)/'`$(SRCDIR)/StreamParameters.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/StreamParameters.Tpo" "$(DEPDIR)/StreamParameters.Plo"; else rm -f "$(DEPDIR)/StreamParameters.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/StreamParameters.cxx' object='StreamParameters.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o StreamParameters.lo `test -f '$(SRCDIR)/StreamParameters.cxx' || echo '$(srcdir)/'`$(SRCDIR)/StreamParameters.cxx + +System.lo: $(SRCDIR)/System.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT System.lo -MD -MP -MF "$(DEPDIR)/System.Tpo" -c -o System.lo `test -f '$(SRCDIR)/System.cxx' || echo '$(srcdir)/'`$(SRCDIR)/System.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/System.Tpo" "$(DEPDIR)/System.Plo"; else rm -f "$(DEPDIR)/System.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/System.cxx' object='System.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o System.lo `test -f '$(SRCDIR)/System.cxx' || echo '$(srcdir)/'`$(SRCDIR)/System.cxx + +SystemDeviceIterator.lo: $(SRCDIR)/SystemDeviceIterator.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT SystemDeviceIterator.lo -MD -MP -MF "$(DEPDIR)/SystemDeviceIterator.Tpo" -c -o SystemDeviceIterator.lo `test -f '$(SRCDIR)/SystemDeviceIterator.cxx' || echo '$(srcdir)/'`$(SRCDIR)/SystemDeviceIterator.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/SystemDeviceIterator.Tpo" "$(DEPDIR)/SystemDeviceIterator.Plo"; else rm -f "$(DEPDIR)/SystemDeviceIterator.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/SystemDeviceIterator.cxx' object='SystemDeviceIterator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o SystemDeviceIterator.lo `test -f '$(SRCDIR)/SystemDeviceIterator.cxx' || echo '$(srcdir)/'`$(SRCDIR)/SystemDeviceIterator.cxx + +SystemHostApiIterator.lo: $(SRCDIR)/SystemHostApiIterator.cxx +@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT SystemHostApiIterator.lo -MD -MP -MF "$(DEPDIR)/SystemHostApiIterator.Tpo" -c -o SystemHostApiIterator.lo `test -f '$(SRCDIR)/SystemHostApiIterator.cxx' || echo '$(srcdir)/'`$(SRCDIR)/SystemHostApiIterator.cxx; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/SystemHostApiIterator.Tpo" "$(DEPDIR)/SystemHostApiIterator.Plo"; else rm -f "$(DEPDIR)/SystemHostApiIterator.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$(SRCDIR)/SystemHostApiIterator.cxx' object='SystemHostApiIterator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o SystemHostApiIterator.lo `test -f '$(SRCDIR)/SystemHostApiIterator.cxx' || echo '$(srcdir)/'`$(SRCDIR)/SystemHostApiIterator.cxx + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-libLTLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am \ + uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/portaudio/bindings/cpp/portaudiocpp.pc.in b/portaudio/bindings/cpp/portaudiocpp.pc.in new file mode 100644 index 0000000..8b126d1 --- /dev/null +++ b/portaudio/bindings/cpp/portaudiocpp.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: PortAudioCpp +Description: Portable audio I/O C++ bindings +Version: 12 +Requires: portaudio-2.0 + +Libs: -L${libdir} -lportaudiocpp +Cflags: -I${includedir} diff --git a/portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx b/portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx new file mode 100644 index 0000000..c4ee25f --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx @@ -0,0 +1,83 @@ +#include "portaudiocpp/AsioDeviceAdapter.hxx" + +#include "portaudio.h" +#include "pa_asio.h" + +#include "portaudiocpp/Device.hxx" +#include "portaudiocpp/HostApi.hxx" +#include "portaudiocpp/Exception.hxx" + +namespace portaudio +{ + AsioDeviceAdapter::AsioDeviceAdapter(Device &device) + { + if (device.hostApi().typeId() != paASIO) + throw PaCppException(PaCppException::UNABLE_TO_ADAPT_DEVICE); + + device_ = &device; + + PaError err = PaAsio_GetAvailableLatencyValues(device_->index(), &minBufferSize_, &maxBufferSize_, + &preferredBufferSize_, &granularity_); + + if (err != paNoError) + throw PaException(err); + + } + + Device &AsioDeviceAdapter::device() + { + return *device_; + } + + long AsioDeviceAdapter::minBufferSize() const + { + return minBufferSize_; + } + + long AsioDeviceAdapter::maxBufferSize() const + { + return maxBufferSize_; + } + + long AsioDeviceAdapter::preferredBufferSize() const + { + return preferredBufferSize_; + } + + long AsioDeviceAdapter::granularity() const + { + return granularity_; + } + + void AsioDeviceAdapter::showControlPanel(void *systemSpecific) + { + PaError err = PaAsio_ShowControlPanel(device_->index(), systemSpecific); + + if (err != paNoError) + throw PaException(err); + } + + const char *AsioDeviceAdapter::inputChannelName(int channelIndex) const + { + const char *channelName; + PaError err = PaAsio_GetInputChannelName(device_->index(), channelIndex, &channelName); + + if (err != paNoError) + throw PaException(err); + + return channelName; + } + + const char *AsioDeviceAdapter::outputChannelName(int channelIndex) const + { + const char *channelName; + PaError err = PaAsio_GetOutputChannelName(device_->index(), channelIndex, &channelName); + + if (err != paNoError) + throw PaException(err); + + return channelName; + } +} + + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx b/portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx new file mode 100644 index 0000000..c21535f --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx @@ -0,0 +1,100 @@ +#include "portaudiocpp/BlockingStream.hxx" + +#include "portaudio.h" + +#include "portaudiocpp/StreamParameters.hxx" +#include "portaudiocpp/Exception.hxx" + +namespace portaudio +{ + + // -------------------------------------------------------------------------------------- + + BlockingStream::BlockingStream() + { + } + + BlockingStream::BlockingStream(const StreamParameters ¶meters) + { + open(parameters); + } + + BlockingStream::~BlockingStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } + + // -------------------------------------------------------------------------------------- + + void BlockingStream::open(const StreamParameters ¶meters) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), NULL, NULL); + + if (err != paNoError) + { + throw PaException(err); + } + } + + // -------------------------------------------------------------------------------------- + + void BlockingStream::read(void *buffer, unsigned long numFrames) + { + PaError err = Pa_ReadStream(stream_, buffer, numFrames); + + if (err != paNoError) + { + throw PaException(err); + } + } + + void BlockingStream::write(const void *buffer, unsigned long numFrames) + { + PaError err = Pa_WriteStream(stream_, buffer, numFrames); + + if (err != paNoError) + { + throw PaException(err); + } + } + + // -------------------------------------------------------------------------------------- + + signed long BlockingStream::availableReadSize() const + { + signed long avail = Pa_GetStreamReadAvailable(stream_); + + if (avail < 0) + { + throw PaException(avail); + } + + return avail; + } + + signed long BlockingStream::availableWriteSize() const + { + signed long avail = Pa_GetStreamWriteAvailable(stream_); + + if (avail < 0) + { + throw PaException(avail); + } + + return avail; + } + + // -------------------------------------------------------------------------------------- + +} // portaudio + + + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx b/portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx new file mode 100644 index 0000000..fd2fb53 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx @@ -0,0 +1,41 @@ +#include "portaudiocpp/CFunCallbackStream.hxx" + +#include "portaudiocpp/StreamParameters.hxx" +#include "portaudiocpp/Exception.hxx" + +namespace portaudio +{ + CFunCallbackStream::CFunCallbackStream() + { + } + + CFunCallbackStream::CFunCallbackStream(const StreamParameters ¶meters, PaStreamCallback *funPtr, void *userData) + { + open(parameters, funPtr, userData); + } + + CFunCallbackStream::~CFunCallbackStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } + + // ---------------------------------------------------------------------------------== + + void CFunCallbackStream::open(const StreamParameters ¶meters, PaStreamCallback *funPtr, void *userData) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), funPtr, userData); + + if (err != paNoError) + { + throw PaException(err); + } + } +} diff --git a/portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx b/portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx new file mode 100644 index 0000000..7e34312 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx @@ -0,0 +1,25 @@ +#include "portaudiocpp/CallbackInterface.hxx" + +namespace portaudio +{ + + namespace impl + { + + ////// + /// Adapts any CallbackInterface object to a C-callable function (ie this function). A + /// pointer to the object should be passed as ``userData'' when setting up the callback. + ////// + int callbackInterfaceToPaCallbackAdapter(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) + { + CallbackInterface *cb = static_cast(userData); + return cb->paCallbackFun(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags); + } + + + } // namespace impl + +} // namespace portaudio + + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx b/portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx new file mode 100644 index 0000000..4204dbb --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx @@ -0,0 +1,20 @@ +#include "portaudiocpp/CallbackStream.hxx" + +namespace portaudio +{ + CallbackStream::CallbackStream() + { + } + + CallbackStream::~CallbackStream() + { + } + + // ----------------------------------------------------------------------------------- + + double CallbackStream::cpuLoad() const + { + return Pa_GetStreamCpuLoad(stream_); + } + +} // namespace portaudio diff --git a/portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx b/portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx new file mode 100644 index 0000000..9538139 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx @@ -0,0 +1,81 @@ +#include "portaudiocpp/CppFunCallbackStream.hxx" + +#include "portaudiocpp/StreamParameters.hxx" +#include "portaudiocpp/Exception.hxx" + +namespace portaudio +{ + namespace impl + { + ////// + /// Adapts any a C++ callback to a C-callable function (ie this function). A + /// pointer to a struct with the C++ function pointer and the actual user data should be + /// passed as the ``userData'' parameter when setting up the callback. + ////// + int cppCallbackToPaCallbackAdapter(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) + { + FunCallbackStream::CppToCCallbackData *data = static_cast(userData); + return data->funPtr(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags, data->userData); + } + } + + // ----------------------------------------------------------------------------------- + + FunCallbackStream::CppToCCallbackData::CppToCCallbackData() + { + } + + FunCallbackStream::CppToCCallbackData::CppToCCallbackData(CallbackFunPtr funPtr, void *userData) : funPtr(funPtr), userData(userData) + { + } + + void FunCallbackStream::CppToCCallbackData::init(CallbackFunPtr funPtr, void *userData) + { + this->funPtr = funPtr; + this->userData = userData; + } + + // ----------------------------------------------------------------------------------- + + FunCallbackStream::FunCallbackStream() + { + } + + FunCallbackStream::FunCallbackStream(const StreamParameters ¶meters, CallbackFunPtr funPtr, void *userData) : adapterData_(funPtr, userData) + { + open(parameters); + } + + FunCallbackStream::~FunCallbackStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } + + void FunCallbackStream::open(const StreamParameters ¶meters, CallbackFunPtr funPtr, void *userData) + { + adapterData_.init(funPtr, userData); + open(parameters); + } + + void FunCallbackStream::open(const StreamParameters ¶meters) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::cppCallbackToPaCallbackAdapter, + static_cast(&adapterData_)); + + if (err != paNoError) + { + throw PaException(err); + } + } + + // ----------------------------------------------------------------------------------- +} diff --git a/portaudio/bindings/cpp/source/portaudiocpp/Device.cxx b/portaudio/bindings/cpp/source/portaudiocpp/Device.cxx new file mode 100644 index 0000000..cd7eb7c --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/Device.cxx @@ -0,0 +1,168 @@ +#include "portaudiocpp/Device.hxx" + +#include + +#include "portaudiocpp/HostApi.hxx" +#include "portaudiocpp/System.hxx" +#include "portaudiocpp/Exception.hxx" + +namespace portaudio +{ + + // ------------------------------------------------------------------------------- + + Device::Device(PaDeviceIndex index) : index_(index) + { + if (index == paNoDevice) + info_ = NULL; + else + info_ = Pa_GetDeviceInfo(index); + } + + Device::~Device() + { + } + + PaDeviceIndex Device::index() const + { + return index_; + } + + const char *Device::name() const + { + if (info_ == NULL) + return ""; + + return info_->name; + } + + int Device::maxInputChannels() const + { + if (info_ == NULL) + return 0; + + return info_->maxInputChannels; + } + + int Device::maxOutputChannels() const + { + if (info_ == NULL) + return 0; + + return info_->maxOutputChannels; + } + + PaTime Device::defaultLowInputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultLowInputLatency; + } + + PaTime Device::defaultHighInputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultHighInputLatency; + } + + PaTime Device::defaultLowOutputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultLowOutputLatency; + } + + PaTime Device::defaultHighOutputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultHighOutputLatency; + } + + double Device::defaultSampleRate() const + { + if (info_ == NULL) + return 0.0; + + return info_->defaultSampleRate; + } + + // ------------------------------------------------------------------------------- + + bool Device::isInputOnlyDevice() const + { + return (maxOutputChannels() == 0); + } + + bool Device::isOutputOnlyDevice() const + { + return (maxInputChannels() == 0); + } + + bool Device::isFullDuplexDevice() const + { + return (maxInputChannels() > 0 && maxOutputChannels() > 0); + } + + bool Device::isSystemDefaultInputDevice() const + { + return (System::instance().defaultInputDevice() == *this); + } + + bool Device::isSystemDefaultOutputDevice() const + { + return (System::instance().defaultOutputDevice() == *this); + } + + bool Device::isHostApiDefaultInputDevice() const + { + return (hostApi().defaultInputDevice() == *this); + } + + bool Device::isHostApiDefaultOutputDevice() const + { + return (hostApi().defaultOutputDevice() == *this); + } + + // ------------------------------------------------------------------------------- + + bool Device::operator==(const Device &rhs) + { + return (index_ == rhs.index_); + } + + bool Device::operator!=(const Device &rhs) + { + return !(*this == rhs); + } + + // ------------------------------------------------------------------------------- + + HostApi &Device::hostApi() + { + // NOTE: will cause an exception when called for the null device + if (info_ == NULL) + throw PaException(paInternalError); + + return System::instance().hostApiByIndex(info_->hostApi); + } + + const HostApi &Device::hostApi() const + { + // NOTE; will cause an exception when called for the null device + if (info_ == NULL) + throw PaException(paInternalError); + + return System::instance().hostApiByIndex(info_->hostApi); + } + + // ------------------------------------------------------------------------------- + +} // namespace portaudio + + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx b/portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx new file mode 100644 index 0000000..d3c307c --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx @@ -0,0 +1,163 @@ +#include "portaudiocpp/DirectionSpecificStreamParameters.hxx" + +#include "portaudiocpp/Device.hxx" + +namespace portaudio +{ + + // ----------------------------------------------------------------------------------- + + ////// + /// Returns a `nil' DirectionSpecificStreamParameters object. This can be used to + /// specify that one direction of a Stream is not required (i.e. when creating + /// a half-duplex Stream). All fields of the null DirectionSpecificStreamParameters + /// object are invalid except for the device and the number of channel, which are set + /// to paNoDevice and 0 respectively. + ////// + DirectionSpecificStreamParameters DirectionSpecificStreamParameters::null() + { + DirectionSpecificStreamParameters tmp; + tmp.paStreamParameters_.device = paNoDevice; + tmp.paStreamParameters_.channelCount = 0; + return tmp; + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Default constructor -- all parameters will be uninitialized. + ////// + DirectionSpecificStreamParameters::DirectionSpecificStreamParameters() + { + } + + ////// + /// Constructor which sets all required fields. + ////// + DirectionSpecificStreamParameters::DirectionSpecificStreamParameters(const Device &device, int numChannels, + SampleDataFormat format, bool interleaved, PaTime suggestedLatency, void *hostApiSpecificStreamInfo) + { + setDevice(device); + setNumChannels(numChannels); + setSampleFormat(format, interleaved); + setSuggestedLatency(suggestedLatency); + setHostApiSpecificStreamInfo(hostApiSpecificStreamInfo); + } + + // ----------------------------------------------------------------------------------- + + void DirectionSpecificStreamParameters::setDevice(const Device &device) + { + paStreamParameters_.device = device.index(); + } + + void DirectionSpecificStreamParameters::setNumChannels(int numChannels) + { + paStreamParameters_.channelCount = numChannels; + } + + void DirectionSpecificStreamParameters::setSampleFormat(SampleDataFormat format, bool interleaved) + { + paStreamParameters_.sampleFormat = static_cast(format); + + if (!interleaved) + paStreamParameters_.sampleFormat |= paNonInterleaved; + } + + void DirectionSpecificStreamParameters::setHostApiSpecificSampleFormat(PaSampleFormat format, bool interleaved) + { + paStreamParameters_.sampleFormat = format; + + paStreamParameters_.sampleFormat |= paCustomFormat; + + if (!interleaved) + paStreamParameters_.sampleFormat |= paNonInterleaved; + } + + void DirectionSpecificStreamParameters::setSuggestedLatency(PaTime latency) + { + paStreamParameters_.suggestedLatency = latency; + } + + void DirectionSpecificStreamParameters::setHostApiSpecificStreamInfo(void *streamInfo) + { + paStreamParameters_.hostApiSpecificStreamInfo = streamInfo; + } + + // ----------------------------------------------------------------------------------- + + PaStreamParameters *DirectionSpecificStreamParameters::paStreamParameters() + { + if (paStreamParameters_.channelCount > 0 && paStreamParameters_.device != paNoDevice) + return &paStreamParameters_; + else + return NULL; + } + + const PaStreamParameters *DirectionSpecificStreamParameters::paStreamParameters() const + { + if (paStreamParameters_.channelCount > 0 && paStreamParameters_.device != paNoDevice) + return &paStreamParameters_; + else + return NULL; + } + + Device &DirectionSpecificStreamParameters::device() const + { + return System::instance().deviceByIndex(paStreamParameters_.device); + } + + int DirectionSpecificStreamParameters::numChannels() const + { + return paStreamParameters_.channelCount; + } + + ////// + /// Returns the (non host api-specific) sample format, without including + /// the paNonInterleaved flag. If the sample format is host api-spefific, + /// INVALID_FORMAT (0) will be returned. + ////// + SampleDataFormat DirectionSpecificStreamParameters::sampleFormat() const + { + if (isSampleFormatHostApiSpecific()) + return INVALID_FORMAT; + else + return static_cast(paStreamParameters_.sampleFormat & ~paNonInterleaved); + } + + bool DirectionSpecificStreamParameters::isSampleFormatInterleaved() const + { + return ((paStreamParameters_.sampleFormat & paNonInterleaved) == 0); + } + + bool DirectionSpecificStreamParameters::isSampleFormatHostApiSpecific() const + { + return ((paStreamParameters_.sampleFormat & paCustomFormat) == 0); + } + + ////// + /// Returns the host api-specific sample format, without including any + /// paCustomFormat or paNonInterleaved flags. Will return 0 if the sample format is + /// not host api-specific. + ////// + PaSampleFormat DirectionSpecificStreamParameters::hostApiSpecificSampleFormat() const + { + if (isSampleFormatHostApiSpecific()) + return paStreamParameters_.sampleFormat & ~paCustomFormat & ~paNonInterleaved; + else + return 0; + } + + PaTime DirectionSpecificStreamParameters::suggestedLatency() const + { + return paStreamParameters_.suggestedLatency; + } + + void *DirectionSpecificStreamParameters::hostApiSpecificStreamInfo() const + { + return paStreamParameters_.hostApiSpecificStreamInfo; + } + + // ----------------------------------------------------------------------------------- + +} // namespace portaudio diff --git a/portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx b/portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx new file mode 100644 index 0000000..2e7e701 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx @@ -0,0 +1,123 @@ +#include "portaudiocpp/Exception.hxx" + +namespace portaudio +{ + // ----------------------------------------------------------------------------------- + // PaException: + // ----------------------------------------------------------------------------------- + + ////// + /// Wraps a PortAudio error into a PortAudioCpp PaException. + ////// + PaException::PaException(PaError error) : error_(error) + { + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Alias for paErrorText(), to have std::exception compliance. + ////// + const char *PaException::what() const throw() + { + return paErrorText(); + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Returns the PortAudio error code (PaError). + ////// + PaError PaException::paError() const + { + return error_; + } + + ////// + /// Returns the error as a (zero-terminated) text string. + ////// + const char *PaException::paErrorText() const + { + return Pa_GetErrorText(error_); + } + + ////// + /// Returns true is the error is a HostApi error. + ////// + bool PaException::isHostApiError() const + { + return (error_ == paUnanticipatedHostError); + } + + ////// + /// Returns the last HostApi error (which is the current one if + /// isHostApiError() returns true) as an error code. + ////// + long PaException::lastHostApiError() const + { + return Pa_GetLastHostErrorInfo()->errorCode; + } + + ////// + /// Returns the last HostApi error (which is the current one if + /// isHostApiError() returns true) as a (zero-terminated) text + /// string, if it's available. + ////// + const char *PaException::lastHostApiErrorText() const + { + return Pa_GetLastHostErrorInfo()->errorText; + } + + // ----------------------------------------------------------------------------------- + + bool PaException::operator==(const PaException &rhs) const + { + return (error_ == rhs.error_); + } + + bool PaException::operator!=(const PaException &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- + // PaCppException: + // ----------------------------------------------------------------------------------- + + PaCppException::PaCppException(ExceptionSpecifier specifier) : specifier_(specifier) + { + } + + const char *PaCppException::what() const throw() + { + switch (specifier_) + { + case UNABLE_TO_ADAPT_DEVICE: + { + return "Unable to adapt the given device to the specified host api specific device extension"; + } + } + + return "Unknown exception"; + } + + PaCppException::ExceptionSpecifier PaCppException::specifier() const + { + return specifier_; + } + + bool PaCppException::operator==(const PaCppException &rhs) const + { + return (specifier_ == rhs.specifier_); + } + + bool PaCppException::operator!=(const PaCppException &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- + +} // namespace portaudio + + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx b/portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx new file mode 100644 index 0000000..c6ae019 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx @@ -0,0 +1,121 @@ +#include "portaudiocpp/HostApi.hxx" + +#include "portaudiocpp/System.hxx" +#include "portaudiocpp/Device.hxx" +#include "portaudiocpp/SystemDeviceIterator.hxx" +#include "portaudiocpp/Exception.hxx" + +namespace portaudio +{ + + // ----------------------------------------------------------------------------------- + + HostApi::HostApi(PaHostApiIndex index) : devices_(NULL) + { + try + { + info_ = Pa_GetHostApiInfo(index); + + // Create and populate devices array: + int numDevices = deviceCount(); + + devices_ = new Device*[numDevices]; + + for (int i = 0; i < numDevices; ++i) + { + PaDeviceIndex deviceIndex = Pa_HostApiDeviceIndexToDeviceIndex(index, i); + + if (deviceIndex < 0) + { + throw PaException(deviceIndex); + } + + devices_[i] = &System::instance().deviceByIndex(deviceIndex); + } + } + catch (const std::exception &e) + { + // Delete any (partially) constructed objects (deconstructor isn't called): + delete[] devices_; // devices_ is either NULL or valid + + // Re-throw exception: + throw e; + } + } + + HostApi::~HostApi() + { + // Destroy devices array: + delete[] devices_; + } + + // ----------------------------------------------------------------------------------- + + PaHostApiTypeId HostApi::typeId() const + { + return info_->type; + } + + PaHostApiIndex HostApi::index() const + { + PaHostApiIndex index = Pa_HostApiTypeIdToHostApiIndex(typeId()); + + if (index < 0) + throw PaException(index); + + return index; + } + + const char *HostApi::name() const + { + return info_->name; + } + + int HostApi::deviceCount() const + { + return info_->deviceCount; + } + + // ----------------------------------------------------------------------------------- + + HostApi::DeviceIterator HostApi::devicesBegin() + { + DeviceIterator tmp; + tmp.ptr_ = &devices_[0]; // begin (first element) + return tmp; + } + + HostApi::DeviceIterator HostApi::devicesEnd() + { + DeviceIterator tmp; + tmp.ptr_ = &devices_[deviceCount()]; // end (one past last element) + return tmp; + } + + // ----------------------------------------------------------------------------------- + + Device &HostApi::defaultInputDevice() const + { + return System::instance().deviceByIndex(info_->defaultInputDevice); + } + + Device &HostApi::defaultOutputDevice() const + { + return System::instance().deviceByIndex(info_->defaultOutputDevice); + } + + // ----------------------------------------------------------------------------------- + + bool HostApi::operator==(const HostApi &rhs) const + { + return (typeId() == rhs.typeId()); + } + + bool HostApi::operator!=(const HostApi &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- + +} // namespace portaudio diff --git a/portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx b/portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx new file mode 100644 index 0000000..09e02de --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx @@ -0,0 +1,45 @@ +#include "portaudiocpp/InterfaceCallbackStream.hxx" + +#include "portaudiocpp/StreamParameters.hxx" +#include "portaudiocpp/Exception.hxx" +#include "portaudiocpp/CallbackInterface.hxx" + +namespace portaudio +{ + + // ---------------------------------------------------------------------------------== + + InterfaceCallbackStream::InterfaceCallbackStream() + { + } + + InterfaceCallbackStream::InterfaceCallbackStream(const StreamParameters ¶meters, CallbackInterface &instance) + { + open(parameters, instance); + } + + InterfaceCallbackStream::~InterfaceCallbackStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } + + // ---------------------------------------------------------------------------------== + + void InterfaceCallbackStream::open(const StreamParameters ¶meters, CallbackInterface &instance) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::callbackInterfaceToPaCallbackAdapter, static_cast(&instance)); + + if (err != paNoError) + { + throw PaException(err); + } + } +} diff --git a/portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx b/portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx new file mode 100644 index 0000000..113fe5a --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx @@ -0,0 +1,4 @@ +#include "portaudiocpp/MemFunCallbackStream.hxx" + +// (... template class ...) + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx b/portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx new file mode 100644 index 0000000..3b21f09 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx @@ -0,0 +1,195 @@ +#include "portaudiocpp/Stream.hxx" + +#include + +#include "portaudiocpp/Exception.hxx" +#include "portaudiocpp/System.hxx" + +namespace portaudio +{ + + // ----------------------------------------------------------------------------------- + + Stream::Stream() : stream_(NULL) + { + } + + Stream::~Stream() + { + // (can't call close here, + // the derived class should atleast call + // close() in it's deconstructor) + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Closes the Stream if it's open, else does nothing. + ////// + void Stream::close() + { + if (isOpen() && System::exists()) + { + PaError err = Pa_CloseStream(stream_); + stream_ = NULL; + + if (err != paNoError) + throw PaException(err); + } + } + + ////// + /// Returns true if the Stream is open. + ////// + bool Stream::isOpen() const + { + return (stream_ != NULL); + } + + // ----------------------------------------------------------------------------------- + + void Stream::setStreamFinishedCallback(PaStreamFinishedCallback *callback) + { + PaError err = Pa_SetStreamFinishedCallback(stream_, callback); + + if (err != paNoError) + throw PaException(err); + } + + // ----------------------------------------------------------------------------------- + + void Stream::start() + { + PaError err = Pa_StartStream(stream_); + + if (err != paNoError) + throw PaException(err); + } + + void Stream::stop() + { + PaError err = Pa_StopStream(stream_); + + if (err != paNoError) + throw PaException(err); + } + + void Stream::abort() + { + PaError err = Pa_AbortStream(stream_); + + if (err != paNoError) + throw PaException(err); + } + + bool Stream::isStopped() const + { + PaError ret = Pa_IsStreamStopped(stream_); + + if (ret < 0) + throw PaException(ret); + + return (ret == 1); + } + + bool Stream::isActive() const + { + PaError ret = Pa_IsStreamActive(stream_); + + if (ret < 0) + throw PaException(ret); + + return (ret == 1); + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Returns the best known input latency for the Stream. This value may differ from the + /// suggested input latency set in the StreamParameters. Includes all sources of + /// latency known to PortAudio such as internal buffering, and Host API reported latency. + /// Doesn't include any estimates of unknown latency. + ////// + PaTime Stream::inputLatency() const + { + const PaStreamInfo *info = Pa_GetStreamInfo(stream_); + if (info == NULL) + { + throw PaException(paInternalError); + return PaTime(0.0); + } + + return info->inputLatency; + } + + ////// + /// Returns the best known output latency for the Stream. This value may differ from the + /// suggested output latency set in the StreamParameters. Includes all sources of + /// latency known to PortAudio such as internal buffering, and Host API reported latency. + /// Doesn't include any estimates of unknown latency. + ////// + PaTime Stream::outputLatency() const + { + const PaStreamInfo *info = Pa_GetStreamInfo(stream_); + if (info == NULL) + { + throw PaException(paInternalError); + return PaTime(0.0); + } + + return info->outputLatency; + } + + ////// + /// Returns the sample rate of the Stream. Usually this will be the + /// best known estimate of the used sample rate. For instance when opening a + /// Stream setting 44100.0 Hz in the StreamParameters, the actual sample + /// rate might be something like 44103.2 Hz (due to imperfections in the + /// sound card hardware). + ////// + double Stream::sampleRate() const + { + const PaStreamInfo *info = Pa_GetStreamInfo(stream_); + if (info == NULL) + { + throw PaException(paInternalError); + return 0.0; + } + + return info->sampleRate; + } + + // ----------------------------------------------------------------------------------- + + PaTime Stream::time() const + { + return Pa_GetStreamTime(stream_); + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Accessor (const) for PortAudio PaStream pointer, useful for interfacing with + /// PortAudio add-ons such as PortMixer for instance. Normally accessing this + /// pointer should not be needed as PortAudioCpp aims to provide all of PortAudio's + /// functionality. + ////// + const PaStream *Stream::paStream() const + { + return stream_; + } + + ////// + /// Accessor (non-const) for PortAudio PaStream pointer, useful for interfacing with + /// PortAudio add-ons such as PortMixer for instance. Normally accessing this + /// pointer should not be needed as PortAudioCpp aims to provide all of PortAudio's + /// functionality. + ////// + PaStream *Stream::paStream() + { + return stream_; + } + + // ----------------------------------------------------------------------------------- + +} // namespace portaudio diff --git a/portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx b/portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx new file mode 100644 index 0000000..670873b --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx @@ -0,0 +1,165 @@ +#include "portaudiocpp/StreamParameters.hxx" + +#include + +#include "portaudiocpp/Device.hxx" + +namespace portaudio +{ + // ----------------------------------------------------------------------------------- + + ////// + /// Default constructor; does nothing. + ////// + StreamParameters::StreamParameters() + { + } + + ////// + /// Sets up the all parameters needed to open either a half-duplex or full-duplex Stream. + /// + /// @param inputParameters The parameters for the input direction of the to-be opened + /// Stream or DirectionSpecificStreamParameters::null() for an output-only Stream. + /// @param outputParameters The parameters for the output direction of the to-be opened + /// Stream or DirectionSpecificStreamParameters::null() for an input-only Stream. + /// @param sampleRate The to-be opened Stream's sample rate in Hz. + /// @param framesPerBuffer The number of frames per buffer for a CallbackStream, or + /// the preferred buffer granularity for a BlockingStream. + /// @param flags The flags for the to-be opened Stream; default paNoFlag. + ////// + StreamParameters::StreamParameters(const DirectionSpecificStreamParameters &inputParameters, + const DirectionSpecificStreamParameters &outputParameters, double sampleRate, unsigned long framesPerBuffer, + PaStreamFlags flags) : inputParameters_(inputParameters), outputParameters_(outputParameters), + sampleRate_(sampleRate), framesPerBuffer_(framesPerBuffer), flags_(flags) + { + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Sets the requested sample rate. If this sample rate isn't supported by the hardware, the + /// Stream will fail to open. The real-life sample rate used might differ slightly due to + /// imperfections in the sound card hardware; use Stream::sampleRate() to retreive the + /// best known estimate for this value. + ////// + void StreamParameters::setSampleRate(double sampleRate) + { + sampleRate_ = sampleRate; + } + + ////// + /// Either the number of frames per buffer for a CallbackStream, or + /// the preferred buffer granularity for a BlockingStream. See PortAudio + /// documentation. + ////// + void StreamParameters::setFramesPerBuffer(unsigned long framesPerBuffer) + { + framesPerBuffer_ = framesPerBuffer; + } + + ////// + /// Sets the specified flag or does nothing when the flag is already set. Doesn't + /// `unset' any previously existing flags (use clearFlags() for that). + ////// + void StreamParameters::setFlag(PaStreamFlags flag) + { + flags_ |= flag; + } + + ////// + /// Unsets the specified flag or does nothing if the flag isn't set. Doesn't affect + /// any other flags. + ////// + void StreamParameters::unsetFlag(PaStreamFlags flag) + { + flags_ &= ~flag; + } + + ////// + /// Clears or `unsets' all set flags. + ////// + void StreamParameters::clearFlags() + { + flags_ = paNoFlag; + } + + // ----------------------------------------------------------------------------------- + + void StreamParameters::setInputParameters(const DirectionSpecificStreamParameters ¶meters) + { + inputParameters_ = parameters; + } + + void StreamParameters::setOutputParameters(const DirectionSpecificStreamParameters ¶meters) + { + outputParameters_ = parameters; + } + + // ----------------------------------------------------------------------------------- + + bool StreamParameters::isSupported() const + { + return (Pa_IsFormatSupported(inputParameters_.paStreamParameters(), + outputParameters_.paStreamParameters(), sampleRate_) == paFormatIsSupported); + } + + // ----------------------------------------------------------------------------------- + + double StreamParameters::sampleRate() const + { + return sampleRate_; + } + + unsigned long StreamParameters::framesPerBuffer() const + { + return framesPerBuffer_; + } + + ////// + /// Returns all currently set flags as a binary combined + /// integer value (PaStreamFlags). Use isFlagSet() to + /// avoid dealing with the bitmasks. + ////// + PaStreamFlags StreamParameters::flags() const + { + return flags_; + } + + ////// + /// Returns true if the specified flag is currently set + /// or false if it isn't. + ////// + bool StreamParameters::isFlagSet(PaStreamFlags flag) const + { + return ((flags_ & flag) != 0); + } + + // ----------------------------------------------------------------------------------- + + DirectionSpecificStreamParameters &StreamParameters::inputParameters() + { + return inputParameters_; + } + + const DirectionSpecificStreamParameters &StreamParameters::inputParameters() const + { + return inputParameters_; + } + + DirectionSpecificStreamParameters &StreamParameters::outputParameters() + { + return outputParameters_; + } + + const DirectionSpecificStreamParameters &StreamParameters::outputParameters() const + { + return outputParameters_; + } + + // ----------------------------------------------------------------------------------- +} // namespace portaudio + + + + + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/System.cxx b/portaudio/bindings/cpp/source/portaudiocpp/System.cxx new file mode 100644 index 0000000..692c7a1 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/System.cxx @@ -0,0 +1,308 @@ +#include "portaudiocpp/System.hxx" + +#include +#include + +#include "portaudiocpp/HostApi.hxx" +#include "portaudiocpp/Device.hxx" +#include "portaudiocpp/Stream.hxx" +#include "portaudiocpp/Exception.hxx" +#include "portaudiocpp/SystemHostApiIterator.hxx" +#include "portaudiocpp/SystemDeviceIterator.hxx" + +namespace portaudio +{ + // ----------------------------------------------------------------------------------- + + // Static members: + System *System::instance_ = NULL; + int System::initCount_ = 0; + HostApi **System::hostApis_ = NULL; + Device **System::devices_ = NULL; + Device *System::nullDevice_ = NULL; + + // ----------------------------------------------------------------------------------- + + int System::version() + { + return Pa_GetVersion(); + } + + const char *System::versionText() + { + return Pa_GetVersionText(); + } + + void System::initialize() + { + ++initCount_; + + if (initCount_ == 1) + { + // Create singleton: + assert(instance_ == NULL); + instance_ = new System(); + + // Initialize the PortAudio system: + { + PaError err = Pa_Initialize(); + + if (err != paNoError) + throw PaException(err); + } + + // Create and populate device array: + { + int numDevices = instance().deviceCount(); + + devices_ = new Device*[numDevices]; + + for (int i = 0; i < numDevices; ++i) + devices_[i] = new Device(i); + } + + // Create and populate host api array: + { + int numHostApis = instance().hostApiCount(); + + hostApis_ = new HostApi*[numHostApis]; + + for (int i = 0; i < numHostApis; ++i) + hostApis_[i] = new HostApi(i); + } + + // Create null device: + nullDevice_ = new Device(paNoDevice); + } + } + + void System::terminate() + { + PaError err = paNoError; + + if (initCount_ == 1) + { + // Destroy null device: + delete nullDevice_; + + // Destroy host api array: + { + if (hostApis_ != NULL) + { + int numHostApis = instance().hostApiCount(); + + for (int i = 0; i < numHostApis; ++i) + delete hostApis_[i]; + + delete[] hostApis_; + hostApis_ = NULL; + } + } + + // Destroy device array: + { + if (devices_ != NULL) + { + int numDevices = instance().deviceCount(); + + for (int i = 0; i < numDevices; ++i) + delete devices_[i]; + + delete[] devices_; + devices_ = NULL; + } + } + + // Terminate the PortAudio system: + assert(instance_ != NULL); + err = Pa_Terminate(); + + // Destroy singleton: + delete instance_; + instance_ = NULL; + } + + if (initCount_ > 0) + --initCount_; + + if (err != paNoError) + throw PaException(err); + } + + + System &System::instance() + { + assert(exists()); + + return *instance_; + } + + bool System::exists() + { + return (instance_ != NULL); + } + + // ----------------------------------------------------------------------------------- + + System::HostApiIterator System::hostApisBegin() + { + System::HostApiIterator tmp; + tmp.ptr_ = &hostApis_[0]; // begin (first element) + return tmp; + } + + System::HostApiIterator System::hostApisEnd() + { + int count = hostApiCount(); + + System::HostApiIterator tmp; + tmp.ptr_ = &hostApis_[count]; // end (one past last element) + return tmp; + } + + HostApi &System::defaultHostApi() + { + PaHostApiIndex defaultHostApi = Pa_GetDefaultHostApi(); + + if (defaultHostApi < 0) + throw PaException(defaultHostApi); + + return *hostApis_[defaultHostApi]; + } + + HostApi &System::hostApiByTypeId(PaHostApiTypeId type) + { + PaHostApiIndex index = Pa_HostApiTypeIdToHostApiIndex(type); + + if (index < 0) + throw PaException(index); + + return *hostApis_[index]; + } + + HostApi &System::hostApiByIndex(PaHostApiIndex index) + { + if (index < 0 || index >= hostApiCount()) + throw PaException(paInternalError); + + return *hostApis_[index]; + } + + int System::hostApiCount() + { + PaHostApiIndex count = Pa_GetHostApiCount(); + + if (count < 0) + throw PaException(count); + + return count; + } + + // ----------------------------------------------------------------------------------- + + System::DeviceIterator System::devicesBegin() + { + DeviceIterator tmp; + tmp.ptr_ = &devices_[0]; + + return tmp; + } + + System::DeviceIterator System::devicesEnd() + { + int count = deviceCount(); + + DeviceIterator tmp; + tmp.ptr_ = &devices_[count]; + + return tmp; + } + + ////// + /// Returns the System's default input Device, or the null Device if none + /// was available. + ////// + Device &System::defaultInputDevice() + { + PaDeviceIndex index = Pa_GetDefaultInputDevice(); + return deviceByIndex(index); + } + + ////// + /// Returns the System's default output Device, or the null Device if none + /// was available. + ////// + Device &System::defaultOutputDevice() + { + PaDeviceIndex index = Pa_GetDefaultOutputDevice(); + return deviceByIndex(index); + } + + ////// + /// Returns the Device for the given index. + /// Will throw a paInternalError equivalent PaException if the given index + /// is out of range. + ////// + Device &System::deviceByIndex(PaDeviceIndex index) + { + if (index < -1 || index >= deviceCount()) + { + throw PaException(paInternalError); + } + + if (index == -1) + return System::instance().nullDevice(); + + return *devices_[index]; + } + + int System::deviceCount() + { + PaDeviceIndex count = Pa_GetDeviceCount(); + + if (count < 0) + throw PaException(count); + + return count; + } + + Device &System::nullDevice() + { + return *nullDevice_; + } + + // ----------------------------------------------------------------------------------- + + void System::sleep(long msec) + { + Pa_Sleep(msec); + } + + int System::sizeOfSample(PaSampleFormat format) + { + PaError err = Pa_GetSampleSize(format); + if (err < 0) + { + throw PaException(err); + return 0; + } + + return err; + } + + // ----------------------------------------------------------------------------------- + + System::System() + { + // (left blank intentionally) + } + + System::~System() + { + // (left blank intentionally) + } + + // ----------------------------------------------------------------------------------- + +} // namespace portaudio + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx b/portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx new file mode 100644 index 0000000..c3c00f7 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx @@ -0,0 +1,60 @@ +#include "portaudiocpp/SystemDeviceIterator.hxx" + +namespace portaudio +{ + // ----------------------------------------------------------------------------------- + + Device &System::DeviceIterator::operator*() const + { + return **ptr_; + } + + Device *System::DeviceIterator::operator->() const + { + return &**this; + } + + // ----------------------------------------------------------------------------------- + + System::DeviceIterator &System::DeviceIterator::operator++() + { + ++ptr_; + return *this; + } + + System::DeviceIterator System::DeviceIterator::operator++(int) + { + System::DeviceIterator prev = *this; + ++*this; + return prev; + } + + System::DeviceIterator &System::DeviceIterator::operator--() + { + --ptr_; + return *this; + } + + System::DeviceIterator System::DeviceIterator::operator--(int) + { + System::DeviceIterator prev = *this; + --*this; + return prev; + } + + // ----------------------------------------------------------------------------------- + + bool System::DeviceIterator::operator==(const System::DeviceIterator &rhs) + { + return (ptr_ == rhs.ptr_); + } + + bool System::DeviceIterator::operator!=(const System::DeviceIterator &rhs) + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- +} // namespace portaudio + + diff --git a/portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx b/portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx new file mode 100644 index 0000000..f34ca40 --- /dev/null +++ b/portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx @@ -0,0 +1,59 @@ +#include "portaudiocpp/SystemHostApiIterator.hxx" + +namespace portaudio +{ + // ----------------------------------------------------------------------------------- + + HostApi &System::HostApiIterator::operator*() const + { + return **ptr_; + } + + HostApi *System::HostApiIterator::operator->() const + { + return &**this; + } + + // ----------------------------------------------------------------------------------- + + System::HostApiIterator &System::HostApiIterator::operator++() + { + ++ptr_; + return *this; + } + + System::HostApiIterator System::HostApiIterator::operator++(int) + { + System::HostApiIterator prev = *this; + ++*this; + return prev; + } + + System::HostApiIterator &System::HostApiIterator::operator--() + { + --ptr_; + return *this; + } + + System::HostApiIterator System::HostApiIterator::operator--(int) + { + System::HostApiIterator prev = *this; + --*this; + return prev; + } + + // ----------------------------------------------------------------------------------- + + bool System::HostApiIterator::operator==(const System::HostApiIterator &rhs) + { + return (ptr_ == rhs.ptr_); + } + + bool System::HostApiIterator::operator!=(const System::HostApiIterator &rhs) + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- +} // namespace portaudio + diff --git a/portaudio/build/dev-cpp/Makefile-dll b/portaudio/build/dev-cpp/Makefile-dll new file mode 100644 index 0000000..856af63 --- /dev/null +++ b/portaudio/build/dev-cpp/Makefile-dll @@ -0,0 +1,78 @@ +# Project: portaudio-dll +# Makefile created by Dev-C++ 4.9.8.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = +OBJ = ./pa_skeleton.o ./pa_stream.o ./pa_trace.o ./pa_allocation.o ./pa_converters.o ./pa_cpuload.o ./pa_dither.o ./pa_front.o ./pa_process.o ./pa_asio.o ./pa_win_util.o ./pa_win_hostapis.o ./pa_win_ds.o ./dsound_wrapper.o ./pa_win_wmme.o ./iasiothiscallresolver.o $(RES) +LINKOBJ = ./pa_skeleton.o ./pa_stream.o ./pa_trace.o ./pa_allocation.o ./pa_converters.o ./pa_cpuload.o ./pa_dither.o ./pa_front.o ./pa_process.o ./pa_asio.o ./pa_win_util.o ./pa_win_hostapis.o ./pa_win_ds.o ./dsound_wrapper.o ./pa_win_wmme.o ./iasiothiscallresolver.o $(RES) +LIBS = -L"C:/Dev-CPP/lib" -fmessage-length=0 --no-export-all-symbols --add-stdcall-alias ../../../asiosdk2/asiosdk2.a -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lwinmm -O3 -s +INCS = -I"C:/Dev-CPP/include" -I"../../../asiosdk2" -I"../../../asiosdk2/common" -I"../../../asiosdk2/host" -I"../../../asiosdk2/host/pc" -I"../../pa_common" +CXXINCS = -I"C:/Dev-CPP/include/c++" -I"C:/Dev-CPP/include/c++/mingw32" -I"C:/Dev-CPP/include/c++/backward" -I"C:/Dev-CPP/include" -I"../../../asiosdk2" -I"../../../asiosdk2/common" -I"../../../asiosdk2/host" -I"../../../asiosdk2/host/pc" -I"../../pa_common" +BIN = portaudio-dll.dll +CXXFLAGS = $(CXXINCS)-O3 -fmessage-length=0 -Wall +CFLAGS = $(INCS)-DBUILDING_DLL=1 -O3 -fmessage-length=0 -Wall + +.PHONY: all all-before all-after clean clean-custom + +all: all-before portaudio-dll.dll all-after + + +clean: clean-custom + rm -f $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=libportaudio-dll.def +STATICLIB=libportaudio-dll.a + +$(BIN): $(LINKOBJ) + $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + +./pa_skeleton.o: ../../pa_common/pa_skeleton.c + $(CPP) -c ../../pa_common/pa_skeleton.c -o ./pa_skeleton.o $(CXXFLAGS) + +./pa_stream.o: ../../pa_common/pa_stream.c + $(CPP) -c ../../pa_common/pa_stream.c -o ./pa_stream.o $(CXXFLAGS) + +./pa_trace.o: ../../pa_common/pa_trace.c + $(CPP) -c ../../pa_common/pa_trace.c -o ./pa_trace.o $(CXXFLAGS) + +./pa_allocation.o: ../../pa_common/pa_allocation.c + $(CPP) -c ../../pa_common/pa_allocation.c -o ./pa_allocation.o $(CXXFLAGS) + +./pa_converters.o: ../../pa_common/pa_converters.c + $(CPP) -c ../../pa_common/pa_converters.c -o ./pa_converters.o $(CXXFLAGS) + +./pa_cpuload.o: ../../pa_common/pa_cpuload.c + $(CPP) -c ../../pa_common/pa_cpuload.c -o ./pa_cpuload.o $(CXXFLAGS) + +./pa_dither.o: ../../pa_common/pa_dither.c + $(CPP) -c ../../pa_common/pa_dither.c -o ./pa_dither.o $(CXXFLAGS) + +./pa_front.o: ../../pa_common/pa_front.c + $(CPP) -c ../../pa_common/pa_front.c -o ./pa_front.o $(CXXFLAGS) + +./pa_process.o: ../../pa_common/pa_process.c + $(CPP) -c ../../pa_common/pa_process.c -o ./pa_process.o $(CXXFLAGS) + +./pa_asio.o: ../../pa_asio/pa_asio.cpp + $(CPP) -c ../../pa_asio/pa_asio.cpp -o ./pa_asio.o $(CXXFLAGS) + +./pa_win_util.o: ../pa_win_util.c + $(CPP) -c ../pa_win_util.c -o ./pa_win_util.o $(CXXFLAGS) + +./pa_win_hostapis.o: ../pa_win_hostapis.c + $(CPP) -c ../pa_win_hostapis.c -o ./pa_win_hostapis.o $(CXXFLAGS) + +./pa_win_ds.o: ../../pa_win_ds/pa_win_ds.c + $(CPP) -c ../../pa_win_ds/pa_win_ds.c -o ./pa_win_ds.o $(CXXFLAGS) + +./dsound_wrapper.o: ../../pa_win_ds/dsound_wrapper.c + $(CPP) -c ../../pa_win_ds/dsound_wrapper.c -o ./dsound_wrapper.o $(CXXFLAGS) + +./pa_win_wmme.o: ../../pa_win_wmme/pa_win_wmme.c + $(CPP) -c ../../pa_win_wmme/pa_win_wmme.c -o ./pa_win_wmme.o $(CXXFLAGS) + +./iasiothiscallresolver.o: ../../pa_asio/iasiothiscallresolver.cpp + $(CPP) -c ../../pa_asio/iasiothiscallresolver.cpp -o ./iasiothiscallresolver.o $(CXXFLAGS) diff --git a/portaudio/build/dev-cpp/Makefile-static b/portaudio/build/dev-cpp/Makefile-static new file mode 100644 index 0000000..2a1647d --- /dev/null +++ b/portaudio/build/dev-cpp/Makefile-static @@ -0,0 +1,75 @@ +# Project: portaudio-static +# Makefile created by Dev-C++ 4.9.8.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = +OBJ = ./pa_skeleton.o ./pa_stream.o ./pa_trace.o ./pa_allocation.o ./pa_converters.o ./pa_cpuload.o ./pa_dither.o ./pa_front.o ./pa_process.o ./pa_asio.o ./pa_win_util.o ./pa_win_hostapis.o ./pa_win_ds.o ./dsound_wrapper.o ./pa_win_wmme.o ./iasiothiscallresolver.o $(RES) +LINKOBJ = ./pa_skeleton.o ./pa_stream.o ./pa_trace.o ./pa_allocation.o ./pa_converters.o ./pa_cpuload.o ./pa_dither.o ./pa_front.o ./pa_process.o ./pa_asio.o ./pa_win_util.o ./pa_win_hostapis.o ./pa_win_ds.o ./dsound_wrapper.o ./pa_win_wmme.o ./iasiothiscallresolver.o $(RES) +LIBS = -L"C:/Dev-CPP/lib" -fmessage-length=0 -O3 -s +INCS = -I"C:/Dev-CPP/include" -I"../../../asiosdk2" -I"../../../asiosdk2/common" -I"../../../asiosdk2/host" -I"../../../asiosdk2/host/pc" -I"../../pa_common" +CXXINCS = -I"C:/Dev-CPP/include/c++" -I"C:/Dev-CPP/include/c++/mingw32" -I"C:/Dev-CPP/include/c++/backward" -I"C:/Dev-CPP/include" -I"../../../asiosdk2" -I"../../../asiosdk2/common" -I"../../../asiosdk2/host" -I"../../../asiosdk2/host/pc" -I"../../pa_common" +BIN = portaudio-static.a +CXXFLAGS = $(CXXINCS)-O3 -fmessage-length=0 -Wall +CFLAGS = $(INCS)-O3 -fmessage-length=0 -Wall + +.PHONY: all all-before all-after clean clean-custom + +all: all-before portaudio-static.a all-after + + +clean: clean-custom + rm -f $(OBJ) $(BIN) + +$(BIN): $(LINKOBJ) + ar r $(BIN) $(LINKOBJ) + ranlib $(BIN) + +./pa_skeleton.o: ../../pa_common/pa_skeleton.c + $(CPP) -c ../../pa_common/pa_skeleton.c -o ./pa_skeleton.o $(CXXFLAGS) + +./pa_stream.o: ../../pa_common/pa_stream.c + $(CPP) -c ../../pa_common/pa_stream.c -o ./pa_stream.o $(CXXFLAGS) + +./pa_trace.o: ../../pa_common/pa_trace.c + $(CPP) -c ../../pa_common/pa_trace.c -o ./pa_trace.o $(CXXFLAGS) + +./pa_allocation.o: ../../pa_common/pa_allocation.c + $(CPP) -c ../../pa_common/pa_allocation.c -o ./pa_allocation.o $(CXXFLAGS) + +./pa_converters.o: ../../pa_common/pa_converters.c + $(CPP) -c ../../pa_common/pa_converters.c -o ./pa_converters.o $(CXXFLAGS) + +./pa_cpuload.o: ../../pa_common/pa_cpuload.c + $(CPP) -c ../../pa_common/pa_cpuload.c -o ./pa_cpuload.o $(CXXFLAGS) + +./pa_dither.o: ../../pa_common/pa_dither.c + $(CPP) -c ../../pa_common/pa_dither.c -o ./pa_dither.o $(CXXFLAGS) + +./pa_front.o: ../../pa_common/pa_front.c + $(CPP) -c ../../pa_common/pa_front.c -o ./pa_front.o $(CXXFLAGS) + +./pa_process.o: ../../pa_common/pa_process.c + $(CPP) -c ../../pa_common/pa_process.c -o ./pa_process.o $(CXXFLAGS) + +./pa_asio.o: ../../pa_asio/pa_asio.cpp + $(CPP) -c ../../pa_asio/pa_asio.cpp -o ./pa_asio.o $(CXXFLAGS) + +./pa_win_util.o: ../pa_win_util.c + $(CPP) -c ../pa_win_util.c -o ./pa_win_util.o $(CXXFLAGS) + +./pa_win_hostapis.o: ../pa_win_hostapis.c + $(CPP) -c ../pa_win_hostapis.c -o ./pa_win_hostapis.o $(CXXFLAGS) + +./pa_win_ds.o: ../../pa_win_ds/pa_win_ds.c + $(CPP) -c ../../pa_win_ds/pa_win_ds.c -o ./pa_win_ds.o $(CXXFLAGS) + +./dsound_wrapper.o: ../../pa_win_ds/dsound_wrapper.c + $(CPP) -c ../../pa_win_ds/dsound_wrapper.c -o ./dsound_wrapper.o $(CXXFLAGS) + +./pa_win_wmme.o: ../../pa_win_wmme/pa_win_wmme.c + $(CPP) -c ../../pa_win_wmme/pa_win_wmme.c -o ./pa_win_wmme.o $(CXXFLAGS) + +./iasiothiscallresolver.o: ../../pa_asio/iasiothiscallresolver.cpp + $(CPP) -c ../../pa_asio/iasiothiscallresolver.cpp -o ./iasiothiscallresolver.o $(CXXFLAGS) diff --git a/portaudio/build/dev-cpp/portaudio-dll.dev b/portaudio/build/dev-cpp/portaudio-dll.dev new file mode 100644 index 0000000..086e109 --- /dev/null +++ b/portaudio/build/dev-cpp/portaudio-dll.dev @@ -0,0 +1,209 @@ +[Project] +FileName=portaudio-dll.dev +Name=portaudio-dll +UnitCount=16 +Type=3 +Ver=1 +ObjFiles= +Includes=..\..\..\asiosdk2;..\..\..\asiosdk2\common;..\..\..\asiosdk2\host;..\..\..\asiosdk2\host\pc;..\..\pa_common +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler=-DBUILDING_DLL=1_@@_-O3_@@_ +CppCompiler=-O3_@@_ +Linker=--no-export-all-symbols --add-stdcall-alias_@@_../../../asiosdk2/asiosdk2.a_@@_-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lwinmm_@@_-O3 -s_@@_ +IsCpp=1 +Icon= +ExeOutput=. +ObjectOutput=. +OverrideOutput=0 +OverrideOutputName=portaudio.a +HostApplication= +Folders= +CommandLine= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=..\..\pa_common\pa_skeleton.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_skeleton.c -o ./pa_skeleton.o $(CFLAGS) + +[Unit2] +FileName=..\..\pa_common\pa_stream.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_stream.c -o ./pa_stream.o $(CFLAGS) + +[Unit3] +FileName=..\..\pa_common\pa_trace.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_trace.c -o ./pa_trace.o $(CFLAGS) + +[Unit4] +FileName=..\..\pa_common\pa_allocation.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_allocation.c -o ./pa_allocation.o $(CFLAGS) + +[Unit5] +FileName=..\..\pa_common\pa_converters.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_converters.c -o ./pa_converters.o $(CFLAGS) + +[Unit6] +FileName=..\..\pa_common\pa_cpuload.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_cpuload.c -o ./pa_cpuload.o $(CFLAGS) + +[Unit7] +FileName=..\..\pa_common\pa_dither.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_dither.c -o ./pa_dither.o $(CFLAGS) + +[Unit8] +FileName=..\..\pa_common\pa_front.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_front.c -o ./pa_front.o $(CFLAGS) + +[Unit9] +FileName=..\..\pa_common\pa_process.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_process.c -o ./pa_process.o $(CFLAGS) + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit10] +FileName=..\..\pa_asio\pa_asio.cpp +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CPP) -c pa_asio.cpp -o ./pa_asio.o $(CXXFLAGS) + +[Unit11] +FileName=..\pa_win_util.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_util.c -o ./pa_win_util.o $(CFLAGS) + +[Unit12] +FileName=..\pa_win_hostapis.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_hostapis.c -o ./pa_win_hostapis.o $(CFLAGS) + +[Unit13] +FileName=..\..\pa_win_ds\pa_win_ds.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_ds.c -o ./pa_win_ds.o $(CFLAGS) + +[Unit14] +FileName=..\..\pa_win_ds\dsound_wrapper.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c dsound_wrapper.c -o ./dsound_wrapper.o $(CFLAGS) + +[Unit15] +FileName=..\..\pa_win_wmme\pa_win_wmme.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_wmme.c -o ./pa_win_wmme.o $(CFLAGS) + +[Unit16] +FileName=..\..\pa_asio\iasiothiscallresolver.cpp +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/portaudio/build/dev-cpp/portaudio-static.dev b/portaudio/build/dev-cpp/portaudio-static.dev new file mode 100644 index 0000000..2aae584 --- /dev/null +++ b/portaudio/build/dev-cpp/portaudio-static.dev @@ -0,0 +1,209 @@ +[Project] +FileName=portaudio-static.dev +Name=portaudio-static +UnitCount=16 +Type=2 +Ver=1 +ObjFiles= +Includes=..\..\..\asiosdk2;..\..\..\asiosdk2\common;..\..\..\asiosdk2\host;..\..\..\asiosdk2\host\pc;..\..\pa_common +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler=-O3_@@_ +CppCompiler=-O3_@@_ +Linker=-O3 -s_@@_ +IsCpp=1 +Icon= +ExeOutput=. +ObjectOutput=. +OverrideOutput=0 +OverrideOutputName=portaudio.a +HostApplication= +Folders= +CommandLine= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=..\..\pa_common\pa_skeleton.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_skeleton.c -o ./pa_skeleton.o $(CFLAGS) + +[Unit2] +FileName=..\..\pa_common\pa_stream.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_stream.c -o ./pa_stream.o $(CFLAGS) + +[Unit3] +FileName=..\..\pa_common\pa_trace.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_trace.c -o ./pa_trace.o $(CFLAGS) + +[Unit4] +FileName=..\..\pa_common\pa_allocation.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_allocation.c -o ./pa_allocation.o $(CFLAGS) + +[Unit5] +FileName=..\..\pa_common\pa_converters.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_converters.c -o ./pa_converters.o $(CFLAGS) + +[Unit6] +FileName=..\..\pa_common\pa_cpuload.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_cpuload.c -o ./pa_cpuload.o $(CFLAGS) + +[Unit7] +FileName=..\..\pa_common\pa_dither.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_dither.c -o ./pa_dither.o $(CFLAGS) + +[Unit8] +FileName=..\..\pa_common\pa_front.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_front.c -o ./pa_front.o $(CFLAGS) + +[Unit9] +FileName=..\..\pa_common\pa_process.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_process.c -o ./pa_process.o $(CFLAGS) + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit10] +FileName=..\..\pa_asio\pa_asio.cpp +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CPP) -c pa_asio.cpp -o ./pa_asio.o $(CXXFLAGS) + +[Unit11] +FileName=..\..\pa_win\pa_win_util.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_util.c -o ./pa_win_util.o $(CFLAGS) + +[Unit12] +FileName=..\..\pa_win\pa_win_hostapis.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_hostapis.c -o ./pa_win_hostapis.o $(CFLAGS) + +[Unit13] +FileName=..\..\pa_win_ds\pa_win_ds.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_ds.c -o ./pa_win_ds.o $(CFLAGS) + +[Unit14] +FileName=..\..\pa_win_ds\dsound_wrapper.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c dsound_wrapper.c -o ./dsound_wrapper.o $(CFLAGS) + +[Unit15] +FileName=..\..\pa_win_wmme\pa_win_wmme.c +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c pa_win_wmme.c -o ./pa_win_wmme.o $(CFLAGS) + +[Unit16] +FileName=..\..\pa_asio\iasiothiscallresolver.cpp +CompileCpp=1 +Folder=portaudio +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/portaudio/build/dev-cpp/readme.txt b/portaudio/build/dev-cpp/readme.txt new file mode 100644 index 0000000..07108a7 --- /dev/null +++ b/portaudio/build/dev-cpp/readme.txt @@ -0,0 +1,23 @@ +From: "Peter L Jones" +Sent: Wednesday, September 17, 2003 5:18 AM +Subject: Dev-C++ project files + +I attach two project files intended for portaudio/pa_win/dev-cpp (i.e. in +parallel with the msvc directory), if you want them. One is for a static +library build and one for a DLL. I've used the static library (in building +a single monolithic DLL) but I can't guarantee the DLL version will build a +working library (I think it's mostly there, though!). + +I also attach the resulting makefiles, which may be of use to other MinGW +users. + +They're rooted in the directory given above and drop their object and +library files in the same place. They assume the asiosdk2 files are in the +same directory as portaudio/ in a sub-directory called asiosdk2/. Oh! The +DLL is built against a static asiosdk2.a library... maybe not the best way +to do it... I ought to figure out how to link against a "home made" dll in +Dev-C++, I guess ;-) + +Cheers, + +-- Peter diff --git a/portaudio/build/msvc/portaudio.def b/portaudio/build/msvc/portaudio.def new file mode 100644 index 0000000..08929d6 --- /dev/null +++ b/portaudio/build/msvc/portaudio.def @@ -0,0 +1,43 @@ +EXPORTS + +; +Pa_GetVersion @1 +Pa_GetVersionText @2 +Pa_GetErrorText @3 +Pa_Initialize @4 +Pa_Terminate @5 +Pa_GetHostApiCount @6 +Pa_GetDefaultHostApi @7 +Pa_GetHostApiInfo @8 +Pa_HostApiTypeIdToHostApiIndex @9 +Pa_HostApiDeviceIndexToDeviceIndex @10 +Pa_GetLastHostErrorInfo @11 +Pa_GetDeviceCount @12 +Pa_GetDefaultInputDevice @13 +Pa_GetDefaultOutputDevice @14 +Pa_GetDeviceInfo @15 +Pa_IsFormatSupported @16 +Pa_OpenStream @17 +Pa_OpenDefaultStream @18 +Pa_CloseStream @19 +Pa_SetStreamFinishedCallback @20 +Pa_StartStream @21 +Pa_StopStream @22 +Pa_AbortStream @23 +Pa_IsStreamStopped @24 +Pa_IsStreamActive @25 +Pa_GetStreamInfo @26 +Pa_GetStreamTime @27 +Pa_GetStreamCpuLoad @28 +Pa_ReadStream @29 +Pa_WriteStream @30 +Pa_GetStreamReadAvailable @31 +Pa_GetStreamWriteAvailable @32 +Pa_GetSampleSize @33 +Pa_Sleep @34 +PaAsio_GetAvailableLatencyValues @50 +PaAsio_ShowControlPanel @51 +PaUtil_InitializeX86PlainConverters @52 +PaAsio_GetInputChannelName @53 +PaAsio_GetOutputChannelName @54 +PaUtil_SetDebugPrintFunction @55 \ No newline at end of file diff --git a/portaudio/build/msvc/portaudio.dsp b/portaudio/build/msvc/portaudio.dsp new file mode 100644 index 0000000..efc37f6 --- /dev/null +++ b/portaudio/build/msvc/portaudio.dsp @@ -0,0 +1,265 @@ +# Microsoft Developer Studio Project File - Name="portaudio" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=portaudio - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "portaudio.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "portaudio.mak" CFG="portaudio - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "portaudio - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "portaudio - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "portaudio - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_x86" +# PROP BASE Intermediate_Dir "Release_x86" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_x86" +# PROP Intermediate_Dir "Release_x86" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\src\common" /I "..\..\include" /I ".\\" /I "..\..\src\os\win" /D "WIN32" /D "NDEBUG" /D "_USRDLL" /D "PA_ENABLE_DEBUG_OUTPUT" /D "_CRT_SECURE_NO_DEPRECATE" /D "PAWIN_USE_WDMKS_DEVICE_INFO" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setupapi.lib /nologo /dll /machine:I386 /out:"./Release_x86/portaudio_x86.dll" + +!ELSEIF "$(CFG)" == "portaudio - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_x86" +# PROP BASE Intermediate_Dir "Debug_x86" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_x86" +# PROP Intermediate_Dir "Debug_x86" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\src\common" /I "..\..\include" /I ".\\" /I "..\..\src\os\win" /D "WIN32" /D "_DEBUG" /D "_USRDLL" /D "PA_ENABLE_DEBUG_OUTPUT" /D "_CRT_SECURE_NO_DEPRECATE" /D "PAWIN_USE_WDMKS_DEVICE_INFO" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setupapi.lib /nologo /dll /debug /machine:I386 /out:"./Debug_x86/portaudio_x86.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "portaudio - Win32 Release" +# Name "portaudio - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\common\pa_allocation.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_converters.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_cpuload.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_debugprint.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_dither.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_front.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_process.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_skeleton.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_stream.c +# End Source File +# End Group +# Begin Group "hostapi" + +# PROP Default_Filter "" +# Begin Group "ASIO" + +# PROP Default_Filter "" +# Begin Group "ASIOSDK" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\asio.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\host\ASIOConvertSamples.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\host\asiodrivers.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\host\pc\asiolist.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\combase.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\debugmessage.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\register.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\pa_asio.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# End Group +# Begin Group "dsound" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\dsound\pa_win_ds.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\dsound\pa_win_ds_dynlink.c +# End Source File +# End Group +# Begin Group "wmme" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\wmme\pa_win_wmme.c +# End Source File +# End Group +# Begin Group "wasapi" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\wasapi\pa_win_wasapi.cpp +# End Source File +# End Group +# Begin Group "wdm-ks" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\wdmks\pa_win_wdmks.c +# End Source File +# End Group +# End Group +# Begin Group "os" + +# PROP Default_Filter "" +# Begin Group "win" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_hostapis.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_util.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_waveformat.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_wdmks_utils.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_x86_plain_converters.c +# End Source File +# End Group +# End Group +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\portaudio.def +# End Source File +# End Group +# End Target +# End Project diff --git a/portaudio/build/msvc/portaudio.dsw b/portaudio/build/msvc/portaudio.dsw new file mode 100644 index 0000000..6af88f4 --- /dev/null +++ b/portaudio/build/msvc/portaudio.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "portaudio"=".\portaudio.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/portaudio/build/msvc/portaudio.sln b/portaudio/build/msvc/portaudio.sln new file mode 100644 index 0000000..d4cc5dc --- /dev/null +++ b/portaudio/build/msvc/portaudio.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "portaudio", "portaudio.vcproj", "{0A18A071-125E-442F-AFF7-A3F68ABECF99}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.Build.0 = Debug|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.ActiveCfg = Release|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.Build.0 = Release|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.ActiveCfg = Release|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/portaudio/build/msvc/portaudio.vcproj b/portaudio/build/msvc/portaudio.vcproj new file mode 100644 index 0000000..1ba86af --- /dev/null +++ b/portaudio/build/msvc/portaudio.vcproj @@ -0,0 +1,1471 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/portaudio/build/msvc/readme.txt b/portaudio/build/msvc/readme.txt new file mode 100644 index 0000000..5364797 --- /dev/null +++ b/portaudio/build/msvc/readme.txt @@ -0,0 +1,80 @@ +Hello + + This is a small list of steps in order to build portaudio +(Currently v19-devel) into a VC6 DLL and lib file. +This DLL contains all 3 current win32 PA APIS (MM/DS/ASIO) + +1)Copy the source dirs that comes with the ASIO SDK inside src\hostapi\asio\ASIOSDK + so you should now have example: + + portaudio19svn\src\hostapi\asio\ASIOSDK\common + portaudio19svn\src\hostapi\asio\ASIOSDK\host + portaudio19svn\src\hostapi\asio\ASIOSDK\host\sample + portaudio19svn\src\hostapi\asio\ASIOSDK\host\pc + portaudio19svn\src\hostapi\asio\ASIOSDK\host\mac (not needed) + + You dont need "driver" + +2) + *If you have Visual Studio 6.0*, please make sure you have it updated with the latest (and final) + microsoft libraries for it, namely: + + Service pack 5: + Latest known URL: + http://msdn2.microsoft.com/en-us/vstudio/aa718363.aspx + Yes there EXISTS a service pack 6 , but the processor pack (below) isnt compatible with it. + + Processor Pack(only works with above SP5) + Latest known URL: + http://msdn2.microsoft.com/en-us/vstudio/Aa718349.aspx + This isnt absolutely required for portaudio, but if you plan on using SSE intrinsics and similar things. + Up to you to decide upon Service pack 5 or 6 depending on your need for intrinsics. + + Platform SDK (Feb 2003) : + Latest known URL: + http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm + (This will allow your code base to be x64 friendly, with correct defines + for LONG_PTR and such) + NOTE A) Yes you have to use IE activex scripts to install that - wont work in Firefox, you + may have to temporarily change tyour default browser(aint life unfair) + NOTE B) Dont forget to hit "Register PSDK Directories with Visual Studio". + you can make sure its right in VC6 if you open tools/options/directories/include files and you see SDK 2003 as the FIRST entry + (it must be the same for libs) + + DirectX 9.0 SDK Update - (Summer 2003) + Latest known URL: + http://www.microsoft.com/downloads/details.aspx?familyid=9216652f-51e0-402e-b7b5-feb68d00f298&displaylang=en + Again register the links in VC6, and check inside vc6 if headers are in second place right after SDk 2003 + + *If you have 7.0(VC.NET/2001) or 7.1(VC.2003) * + then I suggest you open portaudio.dsp (and convert if needed) + + *If you have Visual Studio 2005*, I suggest you open the portaudio.sln file + which contains 4 configurations. Win32/x64 in both Release and Debug variants + + hit compile and hope for the best. + +3)Now in any project, in which you require portaudio, + you can just link with portaudio_x86.lib, (or _x64) and of course include the + relevant headers + (portaudio.h, and/or pa_asio.h , pa_x86_plain_converters.h) See (*) + +4) Your new exe should now use portaudio_xXX.dll. + + +Have fun! + +(*): you may want to add/remove some DLL entry points. +Right now those 6 entries are _not_ from portaudio.h + +(from portaudio.def) +(...) +PaAsio_GetAvailableLatencyValues @50 +PaAsio_ShowControlPanel @51 +PaUtil_InitializeX86PlainConverters @52 +PaAsio_GetInputChannelName @53 +PaAsio_GetOutputChannelName @54 +PaUtil_SetLogPrintFunction @55 + +----- +David Viens, davidv@plogue.com \ No newline at end of file diff --git a/portaudio/build/scons/SConscript_common b/portaudio/build/scons/SConscript_common new file mode 100644 index 0000000..e5d1647 --- /dev/null +++ b/portaudio/build/scons/SConscript_common @@ -0,0 +1,28 @@ +import os.path, sys + +class ConfigurationError(Exception): + def __init__(self, reason): + Exception.__init__(self, "Configuration failed: %s" % reason) + +env = Environment() + +# sunos, aix, hpux, irix, sunos appear to be platforms known by SCons, assuming they're POSIX compliant +Posix = ("linux", "darwin", "sunos", "aix", "hpux", "irix", "sunos") +Windows = ("win32", "cygwin") + +if env["PLATFORM"] == "posix": + if sys.platform[:5] == "linux": + Platform = "linux" + else: + raise ConfigurationError("Unknown platform %s" % sys.platform) +else: + if not env["PLATFORM"] in ("win32", "cygwin") + Posix: + raise ConfigurationError("Unknown platform %s" % env["PLATFORM"]) + Platform = env["PLATFORM"] + +# Inspired by the versioning scheme followed by Qt, it seems sensible enough. There are three components: major, minor +# and micro. Major changes with each subtraction from the API (backward-incompatible, i.e. V19 vs. V18), minor changes +# with each addition to the API (backward-compatible), micro changes with each revision of the source code. +ApiVer = "2.0.0" + +Export("Platform", "Posix", "ConfigurationError", "ApiVer") diff --git a/portaudio/build/scons/SConscript_opts b/portaudio/build/scons/SConscript_opts new file mode 100644 index 0000000..7c9204c --- /dev/null +++ b/portaudio/build/scons/SConscript_opts @@ -0,0 +1,92 @@ +import os.path, sys + +def _PackageOption(pkgName, default=1): + """ Allow user to choose whether a package should be used if available. This results in a commandline option use, + where Pkgname is the name of the package with a capitalized first letter. + @param pkgName: Name of package. + @param default: The default value for this option ("yes"/"no"). + """ + return BoolOption("use%s" % pkgName[0].upper() + pkgName[1:], "use %s if available" % (pkgName), default) + +def _BoolOption(opt, explanation, default=1): + """ Allow user to enable/disable a certain option. This results in a commandline option enable